Contents of Amiga Mail articles - as of May/June 1993

Amiga Mail Volume II is a bi-monthly technical publication that contains
additional information and examples on the correct usage of the techniques
and operating system functions.

   I  Programming Practices and Standards  - general purpose programming
  II  AmigaDOS  - dos.library
 III  Exec  - the multitasking executive, exec.library
  IV  Intuition and Workbench  - the Amiga user interface
   V  Graphics  - animation, text, the Blitter, layers.library
  VI  Sound and Music  - audio, speech, MIDI
 VII  IFF  - iffparse.library and other IFF topics
VIII  Unix and Networking  - Unix SVR4, NFS, TCP/IP, Ethernet
  IX  Timer, Serial, and Parallel  - timer.device, serial & parallel port
   X  Output  - printers, printing, Postscript
  XI  Input  - user input, Commodities Exchange
 XII  CDTV  - Commodore Dynamic Total Vision
XIII  Hardware  - Cards, chips, connectors

      © Copyright 1996-1999 Amiga, Inc.


I: Programming Practices and Standards

 I-1  Tag Items and Tag Lists
 I-3  2.0 Version Strings
 I-7  The ASL Library
I-19  2.0 Compatibility Problem Areas
I-35  Release 2.0 Specific Functions and Commands
I-43  Callback Hooks
I-47  Debugging with Enforcer and Mungwall


II: AmigaDOS

  II-1  Executing External Programs with Release 2.0
  II-5  AmigaDOS Packet Interface Specification
 II-27  Standard Command Line Parsing
 II-31  Notification
 II-37  Using the AmigaDOS Pattern Matching Functions
 II-43  The 2.0 Dos.library Path Name Handling Functions
 II-49  Directory Scanning
 II-65  Writing a UserShell
 II-77  Fast AmigaDOS I/O
 II-87  Cooperative Record Locking with AmigaDOS
 II-95  Packet Level I/O under Release 2
II-107  Even Faster AmigaDOS I/O
II-113  Handling Multiple Assigns with Conventional Directories


III: Exec

 III-1  Using SetFunction() in a Debugger
III-11  68040 Compatibility Warning
III-17  Signalling with SIGF_SINGLE
III-19  Memory Pools
III-25  Quick Interrupts
III-29  Creating Exec Libraries with SAS/C 6.x


IV: Intuition and Workbench

  IV-1  Obtaining an Icon Image
  IV-3  An Introduction to V36 Screens and Windows
 IV-17  Opening Screens and Windows on Any Amiga
 IV-23  Introduction to Boopsi
 IV-41  Writing a Boopsi Image Class
 IV-57  Boopsi's Transparent Base Classes
 IV-59  AppWindows, AppIcons, and AppMenuItems
 IV-69  Making Your Windows More Shiny and Manageable
 IV-77  Optimized Window Refreshing
 IV-91  Color Wheel and Gradient Slider Boopsi Classes
IV-101  Introduction to the Datatypes library
IV-111  Boopsi in Release 3
IV-125  Features of V39 GadTools
IV-137  Menu Verify


V: Graphics

 V-1  Using the ECS Genlocking Features
V-11  Finding the Aspect Ratio
V-15  Amiga Font Scaling and Aspect Ratio
V-23  Using Compugraphic Typefaces with Bullet
V-39  Naming Graphics Display Modes


VI: Sound and Music

VI-1  Creating Virtual Voices with Amiga Audio


VII: IFF

 VII-1  The DR2D FORM
VII-17  ECS Display Modes and ILBM CAMG
VII-21  Developing New IFF FORMs and Chunks
VII-25  AmigaGuide 101


VIII: Unix and Networking

 VIII-1  Using the Amiga A3000UX as a NFS File Server
 VIII-9  Keeping Time - Interval Timing in Amiga UNIX
VIII-17  Developing Network Applications for the Amiga
VIII-31  A Shared Socket Library Server and Client
VIII-51  SANA-II Network Device Specification


IX: Timer, Serial, and Parallel

IX-1  Four Can Play - Supporting Parallel Port Joysticks


X: Output

No mail in ths directory


XI: Input

 XI-1  Introduction to Commodities Exchange
XI-21  Loading Keymaps
XI-25  Customizing the Keypad Keymap


XII: CDTV

 XII-1  Guidelines for CDTV Applications
 XII-9  Making CDTV Titles That Work on Amigas
XII-17  Memory Limits for Various CDTV Configurations


XIII: Hardware

 XIII-1  Video Adapter Diagrams
 XIII-5  The 68030 and 68040 and the Zorro III Bus
XIII-11  Expanding RAM on the Amiga 4000
XIII-15  A1200 CPU Card Expansion RAM
XIII-17  A600 Game Port Connector Form Factor


Copyright notice

Copyright © 1990-1999 Amiga, Inc.

The source and executable code of the examples may only be distributed in
free electronic form, via bulletin board or as part of a fully
non-commercial and freely redistributable diskette.  Both the source and
executable code (including comments) must be included, without
modification, in any copy.  The examples may not be published in printed
form or distributed with any commercial product. However, the programming
techniques and support routines set forth in these examples may be used in
the development of original executable software products for Amiga
computers.

All other rights reserved.

The information contained herein is subject to change without notice,
and is provided "as is" without warranty of any kind, either expressed
or implied.  The entire risk as to the use of this information is
assumed by the user.

Some of these examples were modifed slightly from the original articles.
This was to make them compatible with the V37 include files.  Each example
was recompiled with SAS C 6.56.


I-1: TagItems and Tag Lists

Staff

The implementation of tags is one of the many new features of release
2.0.  Tags made it possible to add new parameters to system functions
without interfering with the original parameters.  They also make
specifying parameter lists much clearer and easier.

A tag is made up of an attribute/value pair as defined below (from
utility/tagitem.h):

    struct TagItem
    {
        ULONG  ti_Tag;    /* identifies the type of this item */
        ULONG  ti_Data;   /* type-specific data, can be a pointer */
    };

The ti_Tag field specifies an attribute to set.  The possible values
of ti_Tag are implementation specific.  System tags are defined in the
include files.  The value the attribute is set to is specified in
ti_Data.  An example of the attribute/value pair that will specify a
window's name is:

    ti_Tag  = WA_Title;
    ti_Data = "My Window's Name";

The ti_Data field often contains 32-bit data as well as pointers.

One way tags are passed to system functions is in the form of tag
lists.  A tag list is an array or chain of arrays of TagItem
structures.  Within this array, different data items are identified by
the value of ti_Tag.  Items specific to a subsystem (Intuition,
Graphics,...) have a ti_Tag value which has the TAG_USER bit set.
Global system tags have a ti_Tag value with TAG_USER bit clear.  The
global system tabs include:

    TAG_IGNORE - A no-op.  The data item is ignored.
    TAG_MORE   - The ti_Data points to another tag list, to support
                 chaining of TagItem arrays.
    TAG_DONE   - Terminates the tag item array (or chain).
    TAG_SKIP   - Ignore the current tag item, and skip the next n array
                 elements, where n is kept in ti_Data.

Note that user tags need only be unique within the particular context
of their use.  For example, the attribute tags defined for
OpenWindow() have the same numeric value as some tags used by
OpenScreen(), but the same numeric value has different meaning in the
different contexts.

System functions receive TagItems is several ways.  One way is
illustrated in the Intuition function OpenWindow().  This function
supports an extented NewWindow structure called ExtNewWindow.  When
the NW_EXTENDED flag is set in the ExtNewWindow.Flags field,
OpenWindow() assumes that the struct TagItem *Extension field contains
a pointer to a tag list.

Another method of passing a tag list is to directly pass a pointer to
a tag list, as OpenWindowTagList() does in the following code
fragment.

    struct TagItem tagitem[3];
    struct Window *window;

    tagitem[0].ti_Tag = WA_CustomScreen;
    tagitem[0].ti_Data = screen;    /* Open on my own screen */
    tagitem[1].ti_Tag = WA_Title;
    tagitem[1].ti_Data = "AmigaMail Test Window";
    tagitem[2].ti_Tag = TAG_DONE;   /* Marks the end of the tag array. */

    /* Use defaults for everything else. Will open as big as the screen.*/

    if (window = OpenWindowTagList(NULL, /* Because all window parameters
                                          * are specified using tags, we
                                          * don't need a NewScreen
                                          * structure                   */
                                   tagitem))
    {
        /* rest of code */
        CloseWindow(window);
    }

Notice that window parameters need not be explicitly specified.
Functions that utilize tags should have reasonable defaults to fall
back on in case no valid attribute/value pair was supplied for a
particular parameter.  This fall back capability is a useful feature.
An application only has to specify the attributes that differ from the
default, rather than unnecessarily listing all the possible
attributes.

The amiga.lib support library offers an example of another way to pass
TagItems to a function.  Rather than passing a tag list, the function
OpenScreenTags() receives the attribute/value pairs in the argument
list, much like printf() receives its arguments.  Any number of
attribute/value pairs can be specified.  The following code fragment
illustrates the usage of OpenScreenTags().

struct Screen *screen;

screen = OpenScreenTags(NULL, /* Don't bother with NewScreen structure */
                        SA_Overscan, OSCAN_TEXT,
                        SA_Title, "Amiga Mail Screen",
                        TAG_DONE );

Tags are not exclusively for use with the operating system; the
programmer can implement them as well.  The run-time library
utility.library contains several functions to make using tags easier.
For more information on utility.library, see the appropriate release
2.0 Autodocs.


I-3: 2.0 Version Strings

By Carolyn Scheppner

Unlike the 1.3 version command, the 2.0 version command has the ability
to search Amiga files for a version string.  If you try the 2.0 version
command on any of the 2.0 Workbench commands, you will find that almost
all Workbench commands now contain these special version strings.  For
example, running version on the current version of  SYS:Utilities/More
will output More 37.2.

This embedded version string provides a simple way for a user to
determine the specific version of a command.  This is extremely useful
for bug reports and phone support.  You may enter these strings in your
code yourself and update them by hand when required, or you may
automate updates by using the bumprev tool (provided on a variety of
DevCon disk sets and also in the Preliminary Software Toolkit II).

 Hand-Coded Version Strings
 Automating Version Numbering with Bumprev


Hand-Coded Version Strings

The hand-coded method can be used in text files and is often quite
suitable for simple programs with a single code module.  If you code
the version strings by hand, they should be formatted like the examples
below.  The example hand-coded strings are for a program named myapp,
version 37.1, date 20-Mar-91 (20.3.91):

In C:

    UBYTE versiontag[] = "\0$VER: appname 37.1 (20.3.91)";

In assembler:

    versiontag      dc.b 0,'$VER: myapp 37.1 (20.3.91)',0

In a text file:

    $VER: myapp.doc 37.1 (20.3.91)

Note that the NULL ("\0" or 0,) at the beginning of the versiontag
string is not necessary but can be useful if you choose to #define the
string and wish to give a version number to  a C program with no data
segment.  With the initial NULL, you can concatenate a #defined
versiontag string onto an arbitrary immediate string used in your code
to get the versiontag into your code segment.


Automating Version Numbering with Bumprev

The bumprev tool and the include files it creates are what we use
internally to give version numbers to system ROM modules, disk-based
devices and libraries, and 2.0 Workbench and Extras commands.  Bumprev
creates or updates three files -- a name_rev.rev file which contains
the current revision number, and the C and assembler include files
called name_rev.h and name_rev.i.  These include files contain #defines
(.h) or macros (.i) to define the name, version, revision, and date of
your program in a variety of string and numeric formats.

By using the appropriate include file in one or more of your code
modules, you can use these #defines (or macros) in place of hardcoded
version and revision information.  This way, whenever you ``bumprev''
your revision files and recompile (or reassemble) your program, all
version, revision, and date references in your program will be
automatically updated.  You can even include a bumprev call in your
makefile for automatic revision bumping on every make (although this
can update the version number more often than is really necessary).

The usage of bumprev is:    bumprev <version> <name_rev>

For example:                bumprev 37 myapp_rev

The first time you use the above example bumprev call, it creates a
myapp_rev.rev file containing ``1'', and myapp_rev.h and .i files
containing a variety of version and revision #defines (or macros) for
version 37.1.  The next time you use the same bumprev command it
updates the files so that all #defines (or macros) are for version
37.2.

Bumprev does have some caveats.  If you accidently type ``bumprev 37
myapp'' (instead of myapp_rev), bumprev will gladly overwrite any
myapp.h or myapp.i file you happen to have rather than complain or
automatically insert _rev into the output file names.  Also, to make a
major version switch (for example from 36 to 37), you must first delete
the myapp_rev.rev file to make bumprev start the revisions over again
at 1.  Note that the 2.0 convention is for a major version number of 37
(to match the OS major version).

Here are example _rev.h and _rev.i files as generated by bumprev, and
fragments of C and assembler code which include and reference these
files.

Example myapp_rev.h generated by bumprev:

#define      VERSION       37
#define      REVISION      1
#define      DATE          "20.3.91"
#define      VERS          "myapp 37.1"
#define      VSTRING       "myapp 37.1 (20.3.91)\n\r"
#define      VERSTAG       "\0$VER: myapp 37.1 (20.3.91)"

Code example which includes myapp_rev.h:

/* myapp.c */

#include <exec/types.h>
#include <dos/dos.h>

/* stdlib.h and stdio.h contain prototypes for exit and printf.
 * Amiga.lib IO users could instead use <clib/alib_protos.h>
 *  and  <clib/alib_stdio_protos.h>
 */
#include <stdlib.h>
#include <stdio.h>
#include "myapp_rev.h"

/* NOTE: we reference VERSTAG version string for C:VERSION to find */
UBYTE versiontag[] = VERSTAG;

/* NOTE: we concatenate program name and version (VERS) with our
copyright */
UBYTE Copyright[] = VERS "Copyright(c) 1991 CATS Inc. All Rights Reserved";

void main(int argc,char **argv)
    {
    /* Print our Copyright string.
     * Copyright string includes our myapp _rev.h version and date
     */
    printf("%s\n",Copyright);
    exit(RETURN_OK);
    }

Example mylib_rev.i generated by bumprev:

VERSION     EQU  37
REVISION    EQU   1
DATE       MACRO
    dc.b    '20.3.91'
    ENDM
VERS       MACRO
    dc.b    'mylib 37.1'
    ENDM
VSTRING    MACRO
    dc.b    'mylib 37.1 (20.3.91)',13,10,0
    ENDM
VERSTAG    MACRO
    dc.b    0,'$VER: mylib 37.1 (20.3.91)',0
    ENDM

Code example which includes mylib_rev.i:

* This is an example of an initial library code module
* Mylib_rev.i is generated with bumprev

      nolist
        include "exec/types.i"
        include "exec/initializers.i"
        include "exec/libraries.i"
        include "exec/resident.i"

        include "mylib.i"
        include "mylib_rev.i"       ; Bumprev revision include file
      list

            ; external
        xref    InitLib             ; init function
        xref    FuncTable           ; function table
        xref    EndSkip             ; End of code segment

; code at start of file in case anyone tries to execute library as program

        entry   FalseStart
FalseStart
        moveq   #-1,d0
        rts

ResidentNode
        dc.w    RTC_MATCHWORD       ; RT_MATCHWORD
        dc.l    ResidentNode        ; RT_MATCHTAG
        dc.l    EndSkip             ; RT_ENDSKIP
        dc.b    RTF_AUTOINIT        ; RT_FLAGS
        dc.b    VERSION             ; RT_VERSION       ;From mylib_rev.i
        dc.b    NT_LIBRARY          ; RT_TYPE
        dc.b    0                   ; RT_PRI
        dc.l    LibName             ; RT_NAME
        dc.l    IDString            ; RT_IDString      ;Contains VSTRING
        dc.l    InitTable           ; RT_SIZE          ;  from mylib_rev.i

LibName:        DC.B    'mylib.library',0
IDString:       VSTRING                                ;From mylib_rev.i
        CNOP    0,2

InitTable
        dc.l    XMyLibBase_Size
        dc.l    FuncTable
        dc.l    DataTable
        dc.l    InitLib

DataTable
            ; standard library stuff
        INITBYTE    LN_TYPE,NT_LIBRARY
        INITLONG    LN_NAME,LibName
        INITBYTE    LIB_FLAGS,LIBF_SUMUSED!LIBF_CHANGED
        INITWORD    LIB_VERSION,VERSION                ;From mylib_rev.i
        INITWORD    LIB_REVISION,REVISION              ;From mylib_rev.i
        INITLONG    LIB_IDSTRING,IDString              ;Contains VSTRING
                                                       ;  from mylib_rev.i
            ; library specific stuff

            ; end of init list
        dc.l        0

        end


I-7: The ASL Library

by John Orr

The asl.library library provides the release 2.0 Amiga OS with system
standard file and font requesters.  Any application that needs to use a
file or font requester should use asl.library requesters because they are
easy to implement, they are easy for the user to learn, and because they
are the same from one application to the next, they make applications more
user friendly.

This article requires a general understanding of several Amiga concepts:
TagItems and TagLists (see the Utility library Autodocs), Intuition
screens and windows, some of the graphics.library's font structures, and
AmigaDOS pattern matching.

 Opening a Simple File Requester
 File Pattern Matching and Multiple Selects
 The ASL_Window Tag
 The Save Requester
 A Directory Requester
 The Font Requester
 The ASL_HookFunc Tag


Opening a Simple File Requester

Using an ASL requester requires the use of three functions:

myrequester = APTR AllocAslRequest( ULONG type, struct TagItem *tagList );
              void FreeAslRequest( APTR request );

made_selection = BOOL AslRequest( APTR request, struct TagItem *tagList );

An ASL requester is based on a FileRequester or a FontRequester structure.
Programs must allocate this structure with AllocAslRequest() (or
AllocFileRequest()see the asl.library Autodoc for more on this function).
Currently, the type field (from the above prototype) can be one of two
values (as defined in <libraries/asl.h> ), ASL_FileRequest, to ask for a
FileRequester structure, or ASL_FontRequest, to ask for a FontRequester
structure.  The values in this structure are for read access only.  Any
changes to them are carried out through asl.library function calls.  The
FreeAslRequest() function deallocates an ASL requester structure.

struct FileRequester    {   /* (from <libraries/asl.h>) */
        APTR    rf_Reserved1;
        BYTE    *rf_File;       /* Filename pointer             */
        BYTE    *rf_Dir;        /* Directory name pointer       */
        CPTR    rf_Reserved2;
        UBYTE   rf_Reserved3;
        UBYTE   rf_Reserved4;
        APTR    rf_Reserved5;
        WORD    rf_LeftEdge,rf_TopEdge; /* Preferred window pos */
        WORD    rf_Width,rf_Height;   /* Preferred window size  */
        WORD    rf_Reserved6;
        LONG    rf_NumArgs;     /* A-la WB Args, for multiselects */
        struct WBArg *rf_ArgList;
        APTR    rf_UserData;    /* Applihandle (you may write!!) */
        APTR    rf_Reserved7;
        APTR    rf_Reserved8;
        BYTE    *rf_Pat;        /* Pattern match pointer */
        };                      /* note - more reserved fields follow */

Based on the requester structure passed to it, AslRequest() brings up a
font or file requester.  When the user makes a selection, AslRequest
returns a value.  If it returns anything but FALSE (0), the user selected
a file (or a font).  AslRequest() returns FALSE if the user cancels the
requester or the requester failed for some reason.

Both AslRequest() and AllocAslRequest() accept a tag list.  This tag list
is used to set the values in the FileRequester (or FontRequester)
structure.  The C code example SimpleFR.c at the end of this article uses
the following  tags (all the ASL tags are defined in <libraries/asl.h>):

    ASL_Hail
    ASL_Width
    ASL_Height
    ASL_LeftEdge
    ASL_TopEdge
    ASL_OKText
    ASL_CancelText
    ASL_File
    ASL_Dir

ASL_Hail supplies a requester with a string to placed in the title bar of
the requester window.  ASL_Width, _Height, _LeftEdge, and _TopEdge
describe the initial dimensions and position of the requester window.
ASL_OKText and ASL_CancelText provide alternate strings for the ``OK'' and
``Cancel'' gadgets.  Currently, the size of these gadgets limits the
length of the names to about six characters.  The two remaining tags from
the above list, ASL_File and ASL_Dir, tags are specific to file
requesters.  They supply the initial file and directory names for the file
requester.

For a file requester, if AslRequest() returns anything but FALSE,
SimpleFR.c looks at the FileRequester's rf_File and rf_Dir fields to get
the name and directory of the file the user selected.  Note that the
requester allows the user to type in a name for the file and directory,
which makes it possible for a file requester to return a file and
directory that do not (currently) exist.  In the case of a save requester
(discussed a little later), the requester can create that non-existent
directory.

   Figure 1 - The SimpleFR.c file requester

The simpleFR.c example (and the rest of the ASL examples for that matter)
may be a little misleading because it only uses the requester once.  Any
application that needs a requester should allocate the requester only once
and pop up that requester every time the application needs one.  If
instead, the application allocated, used, and deallocated a requester each
time it needed one, all of the settings the user left in the requester
(like the names the user last typed into the drawer or file string
gadgets) would be reset to their initial values.  By reusing a requester,
the values stored in it are preserved.

Although retaining previous requester values from one request to another
preserves user preferences, it also preserves other values stored in the
requester structure.  The file and font requester structures contain many
private fields that toggle various features of the ASL requesters (those
features are set via tags).  If a program sets up a file requester with a
specific feature, after the requester returns, the file requester
structure is still set up with the specific feature.  The next time the
application wants to use that file requester without that specific
feature, it must explicitly turn that feature off in the subsequent
AslRequest() call.


File Pattern Matching and Multiple Selects

A file requester can filter out certain file and directory entries using
dos.library's ``wildcarding''.  Turning on a file requester's
``wildcarding'' requires using the ASL_FuncFlags tag.  This tag passes a
bit field to a requester to set several options.  The options are specific
to the type of requester (file or font).  The bitmasks are defined in
<libraries/asl.h>.

The ASL_FuncFlags's FILF_PATGAD flag toggles the file requester's
``Pattern'' gadget.  The user can type an AmigaDOS wildcard pattern into
this gadget that the requester uses to limit the file names that appear in
the requester.  An application can supply the ``Pattern'' gadget with a
default pattern matching string using the ASL_Pattern tag.

Another feature of the ASL file requester is multiple selection.  When an
application sets up a file requester, it can set the FILF_MULTISELECT flag
in the ASL_FuncFlags tag that allows the user to select several files at
once.

When the user selects several files in the requester, the FileRequester's
rf_NumArgs field contains the number of files selected.  When the
FILF_MULTISELECT bit is not set, rf_NumArgs is 0.  If rf_NumArgs is not
zero, rf_ArgList is a base pointer to an array of WBArg structures
(defined in <workbench/startup.h>).  There is a WBArg structure for each
file the user selected.

The example FilePat.c illustrates multiple selection.

FilePat.c also introduces a new function and a new tag.

    APTR AllocAslRequestTags( unsigned long type, Tag Tag1, ... );
    BOOL AslRequestTags( APTR request, Tag Tag1, ... );

FilePat.c uses AllocAslRequestTags() instead of AllocAslRequest() to
allocate and set up the file requester.  AllocAslRequestTags() is an
Amiga.lib function that accepts tag pairs in its parameter list, rather
than a pointer to a tag list.  AslRequestTags() also accepts tag pairs.


The ASL_Window Tag

An application that uses a custom screen normally wants its requesters to
open on its screen.  Using the ASL_Window tag, a program can associate a
requester with a window so the requester appears on the window's screen.
The ASL_Window tag is followed by a pointer to a window structure.
ASL_Window works with both file and font requesters.

Normally, a requester associated with a window (using ASL_Window) uses the
window's IDCMP port for its communication.  An application may not want to
share an IDCMP port with the requester.  Using the ASL_FuncFlags tag, a
program can ask for a requester that creates its own IDCMP port.  There
are two flags that accomplish this.  The first, FILF_NEWIDCMP, is used on
file requesters.   The other, FONF_NEWIDCMP, is used on font requesters.


The Save Requester

The Save requester is a special type of file requester.  The release 2.0
save requester differs from the regular file requester in several ways.
The first is its appearance.  The color of the text making up the file
name list and the color of the backround the text is rendered on are
swapped for the save requester.  This makes the difference between the
save and file requesters visual as well as functional.  Another
difference, is that a save requester does not allow the user to select by
double-clicking on a file name.  This prevents the user from accidentally
double-clicking, and thus over-writing, the wrong file.  The other
difference is that if the user types a directory name into the save
requester and the directory doesn't exist, the save requester will create
that directory (after getting the user's permission via another requester).

The FILF_SAVE flag from the ASL_FuncFlags tag creates a save requester.
Note that it does not make sense to have multiple selection in a save
requester, so the FILF_SAVE flag overrides the FILF_MULTISELECT flag.


A Directory Requester

A program may not need to process files in a requester, only the
directories.  There is another variation on asl.library's file requester
that allows this.  A new tag, ASL_ExtFlags1, toggles this option.
ASL_ExtFlags1 passes a bit field like ASL_FuncFlags.  One of
ASL_ExtFlags1's flags, FIL1F_NOFILES, sets up a requester that has no
string gadget for files and displays only directory names in the
requester's scrolling list.  When AslRequest() (or AslRequestTags() )
returns successfully, the FileRequester structure's rf__Dir field contains
the name of the directory the user selected.

Currently, there is another flag defined for ASL_ExtFlags1,
FIL1F_MATCHDIRS.  If file pattern matching is on (see the FILF_PATGAD flag
for ASL_FuncFlags), setting FIL1F_MATCHDIRS tells the file requester to
pattern match directory names as well as file names.  Of course, if both
of ASL_ExtFlags1's flags are set, the requester will only pattern match
directory names.


The Font Requester

The ASL library also contains a font requester.  The default font
requester consists of two scrolling lists, one containing font names, the
other containing font sizes.  Each scrolling list is accompanied by a
string gadget which lets the user type in the name and size of the font
they want.

   Figure 2 - The FontReq.c font requester

The font size string gadget (actually, an integer gadget) is especially
useful because it allows the user to type in a font size that doesn't
appear in the font size scrolling list.  If the font size the user
requests does not already exist in the system, the Amiga can generate the
font size the user requests either through bitmap scaling, or, if scalable
outline fonts are available, by scaling an outline font.

Using the font requester is similar to using the file requester.  First,
allocate a requester structure.  A font requester requires the
FontRequester structure:

struct FontRequester    {
        APTR    fo_Reserved1[2];
        struct TextAttr fo_Attr;       /* Returned TextAttr            */
        UBYTE   fo_FrontPen;           /* Returned pens, if selected   */
        UBYTE   fo_BackPen;
        UBYTE   fo_DrawMode;
        APTR    fo_UserData;
        };

To allocate this structure, use AllocAslRequest() or AllocAslRequestTags()
with the first argument set to ASL_FontRequest.

There are several tags that are specific to the font requester:

    ASL_FontName
    ASL_FontHeight
    ASL_FontStyles
    ASL_FontFlags
    ASL_FrontPen
    ASL_BackPen
    ASL_MinHeight
    ASL_MaxHeight
    ASL_ModeList

The first six tags are used to place initial values into the FontRequester
structure.  They correspond respectively to the FontRequester's
fo_Attr.ta_Name, fo_Attr.ta_YSize, fo_Attr.ta_Style, fo_Attr.ta_Flags,
fo_FrontPen, and fo_BackPen fields.  ASL_MinHeight specifies the minimum Y
height that the font requester should list.  ASL_MaxHeight specifies the
maximum Y height that the font requester should list.  Note that these
tags only limit the range of font sizes that the font requester displays,
the user is free to type in any value.  The ASL_ModeList tag specifies the
strings used for the font requester's drawing mode gadget.  This is
discussed later in the chapter.

The are several options available to the font requester that are toggled
by setting flags with the ASL_FuncFlags tag.  These flags are:

    FONF_FRONTCOLOR
    FONF_BACKCOLOR
    FONF_STYLES
    FONF_FIXEDWIDTH
    FONF_DRAWMODE

A simple font requester (one without any of the above FONF_ flags set)
only lets the user choose a font and a Y size.  Setting the flags above
adds options to the font requester.  FONF_FRONTCOLOR and FONF_BACKCOLOR
add color selection gadgets to the requester, one for choosing a font's
foreground color (labeled ``Text'' on the requester) and the other for
choosing the backround color (labeled ``Field'').  The font requester
records the user's setting in the FontRequester's fo_FrontPen and
fo_BackPen fields.  FONF_STYLES sets up several gadgets to choose the
style of the font (bold, italics, underline).  The font requester saves
these setting in the fo_Attr.ta_Style bit field according to the style
flags defined in <graphics/text.h>.  FONF_FIXEDWIDTH limits the font name
display to fixed width (non-proportional) fonts (note that this does not
prevent the user from typing in a proportional font name).  FONF_DRAWMODE
adds a cycle gadget to the font requester so the user can choose the draw
mode.  The draw mode is saved in the requester's fo_DrawMode field.  The
number stored there corresponds to the draw mode's position in the
gadget's cycle.

The draw mode cycle gadget initially is labeled ``Mode'' and has three
elements in its cycle: ``JAM1'', ``JAM2'', and ``Complement''.  These
yield a result of 0, 1, and 2, respectively.  It is possible to change the
names and number of draw modes with the ASL_ModeList tag.  This tag
accepts a pointer to an array of strings.  The first string replaces
``Mode'' as the label for the draw mode cycle gadget.  The strings that
follow replace the elements of the cycle gadget.  The last entry in the
array has to be NULL to tell the requester where the list of entries ends.

The FontReq.c example illustrates how to use a font requester.


The ASL_HookFunc Tag

The ASL_HookFunc tag passes an ASL requester a pointer to a custom
function.  The requester can use this function for two purposes.  The
first is to determine if the requester should display a particular file or
font name.  The other purpose is to process messages that the requester
receives at its IDCMP port that are not meant for the requester.  Some
ASL_FuncFlags flags toggle these options:

    FILF_DOWILDFUNC
    FONF_DOWILDFUNC
    FILF_DOMSGFUNC
    FONF_DOMSGFUNC

The FILF_DOWILDFUNC and FONF_DOWILDFUNC flags cause a requester to call
the hook function for every file or font entry.  The requester displays
the file or font name only if the hook function tells it to.  For a file
requester, if the hook function returns a zero, the file requester will
display the file name.  For a font requester, if the hook function returns
anything but zero, the font requester will display the font name and size.
Note that if the DOWILDFUNC function changes the current directory, it
must restort the current directory before it exits.  Neglecting to restore
the current directory can confuse DOS.

The FILF_DOMSGFUNC and FONF_DOMSGFUNC flags cause a requester to call the
hook function when it receives certain IntuiMessages at the IDCMP port it
shares with a window (see the ASL_Window tag).  The requester passes on
IntuiMessages not meant for the requester.  The hook function is
responsible for returning a pointer to the IntuiMessage.  The requester
will take care of replying to the message.

A requester passes three parameters to the hook function:

    ULONG MyHookFunc(ULONG type, CPTR object, CPTR AslRequester)

If MyHookFunc() is called from a file requester doing DOWILDFUNC:

    type = FILF_DOWILDFUNC
    object is a pointer to an AnchorPath structure (from <dos/dosasl.h>)
    AslRequester is a pointer to the FileRequester that called the hook
    function
    (Return a zero to display this file)

Note that the AnchorPath structure is a dos.library structure used in
pattern matching.  See dos.library documentation for more details.

Referencing the specific file or directory from within the DOWILDFUNC hook
function is a little tricky.  For a file requester, the rf_Dir field is
not guaranteed to contain the name of the directory being scanned.  The
correct way to find the file and directory name is from the AnchorPath
structure passed to the DOWILDFUNC.  The structure contains a
FileInfoBlock structure called ap_Info that contains the file name
(fib_FileName).  The AnchorPath structure's ap_Current field contains a
pointer to an AChain structure (from <dos/dosasl.h>) which contains a
field called an_Lock.  This is a lock on the directory being scanned.

If MyHookFunc() is called from a font requester doing DOWILDFUNC:

    type = FONF_DOWILDFUNC
    object is a pointer to a TextAttr structure (from <graphics/text.h>)
    AslRequester is a pointer to the FontRequester that called the hook
    function
    (Return non-zero to display this particular font size)

If MyHookFunc() is called from a file or font requester doing DOMSGFUNC:

    type = FILF_DOMSGFUNC
    object is a pointer to the IntuiMessage for the function to process
    AslRequester is a pointer to the FileRequester or FontRequester that
    called the hook function
    (Return the pointer to the IntuiMessage)

Notice that it is possible for a requester to use both DOWILDFUNC and
DOMSGFUNC at the same time.  The hook function has to differentiate
between the two cases by testing the type passed to it.  It is not
possible for font and file requester to share a hook function for a
DOWILDFUNC, because FILF_DOWILDFUNC is defined to be the same value as
FONF_DOWILDFUNC, so the hook function cannot tell if object (from the
prototype above) is a pointer to an AnchorPath structure or a pointer to a
TextAttr structure.  It is possible for font and file requesters to share
one hook function for DOMSGFUNC (even though FILF_DOMSGFUNC and
FONF_DOMSGFUNC are equal) because, in this case, font and file requesters
both call the hook function in the same manner.

The example FileHook.c illustrates the use of a hook function for both
DOWILDFUNC and DOMSGFUNC.


I-19: 2.0 Compatibility Problem Areas

by Carolyn Scheppner, Bryce Nesbitt, Peter Cherna, and Darren Greenwald

Release 2.04 is finished and soon will be available in Enhancer Packs.  If
your products are not yet compatible, your time is up.  If you are
developing new software, you need to avoid the compatibility traps.  This
comprehensive list of 2.0 compatibility problem areas can help you avoid
compatibility problems.  Note that this document is not identical to the
one published in the 1991 DevCon notes.  There are several extra problems
covered here that weren't mentioned in the 1991 DevCon notes.

 General Compatibility Problem Areas
 2.0 Changes That Can Affect Compatibility
 Additional Information


General Compatibility Problem Areas

One sure fire way to write incompatible software is to fail to follow the
Amiga programming guidelines listed in the beginning of your Amiga ROM
Kernel and Amiga Hardware manuals.  Please read the guidelines and follow
them!

The following improper Amiga programming practices are likely to fail on
new ROMs or hardware:

* Calling ROM code directly.

* Directly or indirectly reading or writing random memory addresses or
  low memory (especially location zero) due to improperly initialized
  pointers or structures.  Use Mungwall and Enforcer when writing and
  testing your code!

* Assuming addresses/location/amounts of RAM or system structures.

* Requiring all free RAM.

* Mishandling 32-bit addresses.  For example, using signed math or
  signed comparisons on addresses, or doing a BOOL or WORD test to
  determine if a pointer is non-zero.

* Overwriting memory allocations.  With 32-bit addresses, a 1-byte
  overwrite of a string array can wipe out the high byte of a pointer or
  stack return address.  This bug could go unnoticed on a 24-bit address
  machine (eg. A500,A2500, etc) but crash the system or cause other
  problems on an A3000.

* Shaving stack size too close.  System function stack usage changes
  with each OS release. o Improper flags or garbage in system structures.
  A bit that means nothing under one OS may drastically change the
  behavior of a function in a newer version of the OS.  Clear structures
  before using, and use correct flags.

* Passing garbage in previously unused upper bytes of function arguments
  (for example-the upper word of the ULONG AvailFonts() Flags parameter).

* Improper register or condition code handling.  Do not assume registers
  D0-D1/A0-A1 are preserved after system calls!  Some function calls
  happen to preserve some registers.  This can change in any revisions of
  the OS.  In some cases we have modifed the values returned in registers
  to keep certain applications from failing under 2.0.  We do not
  guarantee those modifications will remain in place.  Condition codes are
  also in an undefined state on the return from a system call.  Assembler
  code must test (TST,MOVE,CMP,etc.) D0 results before branching on
  condition codes.  Use Scratch by Bill Hawes (via the scratchall script)
  to catch scratch register misuse in assembler code.

* Misuse of function return values.  Use function prototypes and read
  the Autodocs for the functions you are using.  Some system functions
  return just success or failure, or nothing at all (void).  In such
  cases, the value which the function happens to return must not be used
  except as it is documented.

* Calling system library functions from assembler without placing the
  library base pointer in A6.  All system functions may assume that their
  library's base pointer is in A6.  A function's need to reference its
  library base can change in different OS revisions.

* Depending on unsupported side effects or undocumented behavior.  Be
  sure to read the RKM chapters, Autodocs, and include file comments.

* Poking/peeking system private structures.  Do not poke or peek any
  system structure unless told to do so in official Commodore
  documentation.

* Assuming current choices, configurations or initial values.  If the
  current possibilities are A, B, or C, do not assume C if it isn't A or
  B.  Check specifically for the choices currently implemented, and
  provide default behavior for unexpected values.

* Failure to properly allocate resources before using them.

* Failure to properly close/deallocate resources.

* Improper reading/writing of hardware registers.  You must mask out
  bits you are not interested in on reads, and write undefined bits as
  zero.

* Assuming initial values of hardware registers.  If you are going
  direct to the hardware, do not depend on the initial values of any
  hardware registers. The settings may not be the same on different
  versions of the OS or from boot to boot.  Always set up all of the
  hardware registers that affect your code. o Processor speed dependencies
  such as software delay loops.

* Processor instruction dependencies.  Do not use instructions which are
  privileged on any Motorola 68xxx family processor.  Do not use CLR on a
  hardware register which is triggered by any access (use MOVE #0
  instead). The 68000 CLR instruction performs two accesses (Read, then
  Write).  The 68020 and higher CLR instruction performs just one access.

* Depending on or failing to account for cache or prefetch effects.
  Self-modifying or trackdisk-loaded code requires cache flushes ( see the
  exec.library/CacheClearU() function ).

Amiga debugging tools such as Enforcer, Mungwall, and Scratch can find
many program bugs that may affect compatibility.  A program that is
Enforcer/Mungwall/Scratch clean stands a much better chance of working
well under current and future versions of the OS.  These tools are on the
Denver/Milano DevCon disks.  Enforcer and Mungwall are also on the
kickfile disks.


2.0 Changes That Can Affect Compatibility

There are several 2.0-specific areas where OS changes and enhancements can
cause compatibility problems for some software.

 Exec                 Timer.device               Layers
 Expansion            Trackdisk                  Graphics
 Strap                CIA Timers                 Fonts
 DOS                  Other Hardware Issues      CLI / Shell
 Audio.device         Intuition                  Console
 Gameport.device      Preferences
 Serial.device        Workbench


Exec

* Do not jump to location $FC0002 as part of performing a system RESET.
  Many RESET functions jumped to what was the start of the ROM under 1.3.
  The 2.0 ROM is twice the size.  We've added a temporary compatibility
  hack called ``Kickety-Split'' to the 2.04 Kickstart ROM.  The ROM is
  split into two halves with a redirecting jump at $FC0002.  This hack
  does not appear on the A3000 and due to space considerations will not
  appear on future machines.

* Everything has moved.

* The Supervisor stack is not in the same place as it was under 1.3.
  This has caused problems for some games that completely take over the
  Amiga.  If your program goes into Supervisor mode, you must either
  respect allocated memory or provide your own Supervisor stack when
  taking over the machine.

* ExecBase is moved to expansion memory if possible.  Previously,
  ExecBase would only end up in one of two fixed locations.  As a result,
  ColdCapture may be called after expansion memory has been configured.
  Great pains were taken to make this compatible.

* Exception/Interrupt vectors may move.  This means the 68010 and above
  Vector Base Register (VBR) may contain a non-zero value.  Poking assumed
  low memory vector addresses may have no effect.  You must read the VBR
  on 68010 and above to find the base.

* No longer tolerant of wild Forbid() counts.  Under 1.3, sometimes this
  bug could go unnoticed.  Make sure that all Forbid's are matched with
  one and only one Permit (and vice versa).

* When an Exec device gets an IORequest, it must validate io_Command.
  If the io_Command is 0 or out of range, the device must return
  IOERR_NOCMD and take no other action.  The filesystem now sends new
  commands and expects older devices to properly ignore them.

* A 2.0 fix to task-switching allows a busy task to properly regain the
  processor after an interrupt until either its quantum (4 vertical
  blanks) is up or a higher priority task preempts it.  This can
  dramatically change the behavior of multitask programs where one task
  busyloops while another same-priority task Wait()s.  See Task Switching
  in the Additional Information section at the end of this document.


Expansion

* ExpansionBase is private - use FindConfigDev().

* Memory from contiguous cards of the same memory type is automatically
  merged into one memory pool.


Strap

* romboot.library is gone.

* audio.device cannot be OpenDevice()ed by a boot block program because
  it is not yet InitResident()ed.  If OpenDevice() of audio.device fails
  during strap, you must FindResident()/InitResident() audio.device, and
  then try OpenDevice() again.

* Boot from other floppies (+5,-10,-20,-30) is possible.

* Undocumented system stack and register usage at Diag and Boot time
  have changed.


DOS

* DOS is now written in C and assembler, not BCPL.  The BCPL compiler
  artifact which caused D0 function results to also be in D1 is gone.  2.0
  compatibility patches which return some DOS function results in both D0
  and D1 are not guaranteed to remain in the next release.  Fix your
  programs! Use Scratch to find these problems in your code.

* DOS now has a real library base with normal LVO vectors.

* Stack usage has all changed (variables, direction).

* New packet and lock types.  Make sure you are not passing stack
  garbage for the second argument to Lock().

* Process structure is bigger.  ``Rolling your own'' Process structure
  from a Task fails.

* Unless documented otherwise, you must be a process to call DOS
  functions. DOS function dependence on special process structures can
  change with OS revisions.


Audio.device

* Now not initialized until used.  This means low memory open failure is
  possible.  Check your return values from OpenDevice().  This also means
  audio.device cannot be opened during 2.0 Strap unless InitResident()ed
  first. If OpenDevice() of audio.device fails during strap, you must
  FindResident()/InitResident() audio.device, and then try OpenDevice()
  again. There will be a small memory loss (until reboot) generated by the
  first opener of audio.device or narrator.device (memory used in building
  of audio.device's base).


Gameport.device

* Initial state of hardware lines may differ.


Serial.device

* Clears io_Device on CloseDevice() (since 1.3.2)


Timer.device

* The most common mistake programmers make with timer.device is to send
  off a particular timerequest before the previous use of that timerequest
  has completed.  Use IO_Torture to catch this problem.

* IO_QUICK requests may be deferred and be replied as documented.

* VBLANK timer requests, as documented, now wait at least as long as the
  full number of VBlanks you asked for.  Previously, a partial vertical
  blank could count towards your requested number.  The new behavior is
  more correct and matches the docs, but it can cause VBlank requests to
  now take up to 1 VBlank longer under 2.0 as compared to 1.3.  For
  example, a 1/10 second request, may take 6-7 Vblanks instead of 5-6
  VBlanks, or about 15% longer.


Trackdisk

* Private trackdisk structures have changed.  See trackdisk.doc for a
  compatible REMCHANGEINT.

* Buffer is freeable, so low memory open failure is possible.

* Do not disable interrupts (any of them) then expect trackdisk to
  function while they are disabled.


CIA Timers

* System use of CIA timers has changed.  Don't peek timers you think the
  system is using in a particular manner.

* Don't depend on initial values of CIA registers.

* Don't mess with CIABase.  Use cia.resource.

* If your code requires hardware level CIA timers, allocate the timers
  using cia.resource AddICRVector()! Very important!  Operating system
  usage of the CIA timers has changed.  The new 2.0 timer.device (``Jumpy
  the Magic Timer Device'') will try to jump to different CIA's so
  programs that properly allocate timers will have a better chance of
  getting what they want.  If possible, be flexible and design your code
  to work with whatever timer you can successfully allocate.

* OS usage of INT6 is increasing.  Do not totally take over INT6, and do
  not terminate the server chain if an interrupt is not for you.


Other Hardware Issues

* Battery-backed clock is different on A3000.  Use battclock.resource to
  access the real-time clock if battclock.resource can be opened.

* A 68030 hardware characteristic causes longword-aligned longword
  writes to allocate a valid entry in the data cache,  even if the
  hardware area shouldn't be cached.  This can cause problems for IO
  registers and shared memory devices.  To solve this: 1) Don't do that 2)
  Flush the cache or 3) Use Enforcer Quiet.  See the Motorola 68030 manual
  under the description of the Write Allocate bit (which must be set for
  the Amiga to run with the Data Cache).


Intuition

* Private IBase variables have moved/changed.  Reading them is illegal.
  Writing them is both illegal and dangerous.

* Poking IBase MaxMouse variables is now a no-op, but please stop poking
  when Intuition version is >35.

* If you are opening on the Workbench screen, be prepared to handle
  larger screens, new modes, new fonts, and overscan.  Also see Font
  compatibility information. o Screen TopEdge and LeftEdge may be negative.

* LeftAmiga-Select is used for dragging large screens.  Do not use
  LeftAmiga-key combinations for application command keys.  The LeftAmiga
  key is reserved for system use.

* For compatibility reasons, GetScreenData() lies if the Workbench
  screen is a mode only available after release 1.3.  It will try to
  return the most sensible mode that old OpenScreen() can open.  This was
  necessary to keep applications that cloned the Workbench screen from
  having problems.  To properly handle new modes, see LockPubScreen() and
  GetVPModeID(), and the SA_DisplayID tag for OpenScreenTags().

* Using combined RAWKEY and VANILLAKEY now gives VANILLAKEY messages for
  regular keys, and RAWKEY messages for special keys (fkeys, help, etc.)

* Moving a SIMPLE_REFRESH window does not necessarily cause a
  REFRESHWINDOW event because layers now preserves all the bits it can.

* Sizing a SIMPLE_REFRESH window will not clear it.

* MENUVERIFY/REQVERIFY/SIZEVERIFY can time out if you take too long to
  ReplyMsg().

* Menu-key equivalents are ignored while string gadgets are active.

* You can't type control characters into string gadgets by default.  Use
  CTRL-Amiga-char to type them in or use IControl Prefs to change the
  default behavior.

* Width and Height parameters of AutoRequest are ignored.

* New default colors, new gadget images.

* JAM1 rendering/text in border may be invisible gadgets over default
  colors.

* The cursor for string gadgets can no longer reside outside the cleared
  container area.  If your gadget is (for example) 32 pixels wide, with
  MaxChars of 4, then all 32 pixels will be cleared, instead of just 24,
  as was true in 1.3.

* Applications and requesters that fail to specify desired fonts will
  get user 2.0 Font Pref fonts that may be much larger or proportional in
  some cases.  Screen and window titlebars (and their gadgets) will be
  taller when accomodating a larger font.  Applications which open on the
  Workbench screen must adapt to variable size titlebars.  Any application
  which accepts system defaults for its screen, window, menu, Text or
  IntuiText fonts must adapt to different fonts and titlebar sizes.
  String gadgets whose height is too small for a font will revert to a
  smaller ROM font.  There are now 2 different user-specifiable default
  system fonts which affect different Intuition features.  This can lead
  to mismatches in mixed gadgets and text.  For more information on where
  various system fonts come from and how they can be controlled, see
  Intuition Fonts in the Additional Information section at the end of this
  document.

* Don't modify gadgets directly without first removing them from the
  gadget list, unless you are using a system function designed for that
  purpose, such as NewModifyProp() or SetGadgetAttrs().

* Don't rely on NewModifyProp() to fully refresh your prop gadget after
  you've changed values in the structure.  NewModifyProp() will only
  correctly refresh changes which were passed to it as parameters.  Use
  Remove/Add/RefreshGList() for other kinds of changes.

* Custom screens must be of type CUSTOMSCREEN or PUBLICSCREEN.  Other
  types are illegal.  One application opens their screen with
  NewScreen.Type = 0 (instead of CUSTOMSCREEN, 0x0F).  Then, when they
  open their windows, they specify NewWindow.Type of 0 and
  NewWindow.Screen of NULL, instead of Type=CUSTOMSCREEN and Screen=(their
  screen).  That happened to work before, but they are now broken.

* Referencing IntuiMessage->IAddress as a Gadget pointer on non-Gadget
  IDCMP messages, or as a Window pointer (rather than looking at the
  proper field IntuiMessage->IDCMPWindow) may now cause Enforcer hits or
  crashes.  The IAddress field used to always contain a pointer of some
  type even for IDCMP events for which no IAddress value is documented.
  Now, for some IDCMP events, IAddress may contain other data (a
  non-address, possibly an odd value which would crash a 68000 based
  system).

* Using Intuition flags in the wrong structure fields (for example,
  using ACTIVEWINDOW instead of ACTIVATE).  To alleviate this problem, 2.0
  has introduced modern synonyms that are less confusing than the old
  ones.  For example, IDCMP_ACTIVEWINDOW and WFLG_ACTIVATE.  This
  particular example of confusion (there are several) was the nastiest,
  since IDCMP_ACTIVEWINDOW, when stuffed into NewWindow.Flags, corresponds
  numerically to WFLG_NW_EXTENDED, which informs Intuition that the
  NewWindow structure is immediately followed by a TagList, which isn't
  there!  Intuition does some validation on the tag-list pointer, in order
  to partially compensate.  To make your compiler use the new synonyms
  only, add this line to your code before Intuition include files: #define
  INTUI_V36_NAMES_ONLY.

* Do not place spaces into the StringInfo->Buffer of a LONGINT string
  gadget. Under 1.3, it turned out that worked, but under 2.0, the
  validation routine that checks for illegal keystrokes looks at the
  contents for illegal (i.e. non-numeric) characters, and if any are found
  assumes that the user typed an illegal keystroke.  The user's only
  options may be shift-delete or Amiga-X. Use the correct justification
  instead.

* If you specify NULL for a font in an IntuiText, don't assume you'll
  get Topaz 8.  Either explicitly supply the font you you need or be
  prepared to size accordingly.  Otherwise, your rendering will be wrong,
  and the user will have to reset his Preferences just to make your
  software work right.

* Window borders are now drawn in the screen's DetailPen and BlockPen
  rather than the Window's pens.  For best appearance, you should pass a
  SA_Pens array to OpenScreen().  This can be done in a backwards
  compatible manner with the ExtNewScreen structure and the NS_EXTENDED
  flag.

* The system now renders into the full width of window borders, although
  the widths themselves are unchanged.

* Window borders are filled upon activation and inactivation.

* Window border rendering has changed significantly for 2.0.  Note that
  the border dimensions are unchanged from 1.x (Look at
  window->BorderLeft/Top/Width/Height if you don't believe us!).  If your
  gadget intersects the border area, although it may have looked OK under
  1.3, a visual conflict may occur under 2.0.  If Intuition notices a
  gadget which is substantially in the border but not declared as such, it
  treats it as though it were (this is called ``bordersniffing'').  Never
  rely on Intuition to sniff these out for you; always declare them
  explicitly (see the Gadget Activation flags GACT_RIGHTBORDER etc.).  See
  Intuition Gadgets and Window Borders in the Additional Information
  section at the end of this article.


Preferences

* Some old struct Preferences fields are now ignored by SetPrefs (for
  example FontHeight).  SetPrefs also stops listening to the pointer
  fields as soon as a new-style pointer is passed to Intuition (new-style
  pointers can be taller or deeper).

* Preferences ViewX/YOffset only applies to the default mode.  You
  cannot use these fields to move the position of all modes.

* The Preferences LACEWB bit is not necessarily correct when Workbench
  is in a new display mode (akin to GetScreenData()).


Workbench

* The Workbench GUI now has new screen sizes, screen top/left offsets,
  depths, modes, and fonts.

* Default Tool now searches paths.

* New Look (boxed) icons take more space.

* Do not use icons which have more 1bits set in PlanePick than planes in
  the ImageData (one IFF-to-Icon utility does this).  Such icons will
  appear trashed on deeper Workbenches.

* New Look colors have black and white swapped (as compared to 1.3).

* The Workbench screen may not be open at startup-sequence time until
  some output occurs to the initial Shell window.  This can break
  startup-sequence-started games that think they can steal WB's screen
  bitplanes.  Do not steal the WB screen's planes (For compatibility,
  booting off pre-2.0 disks forces the initial screen open.  This is not
  guaranteed to remain in the system).  Use startup code that can detach
  when RUN (such as cback.o) and use CloseWorkbench() to regain the
  screen's memory.

  Under 1.3 the Workbench Screen and initial CLI opened before the first
  line in s:startup-sequence.  Some naughty programmers, in an attempt to
  recover memory, would search for the bitplane pointers and appropriate
  the memory for their own use.  This behavior is highly unsafe.

  By default 2.0 opens the initial CLI on the first _output_ from the
  s:startup-sequence.  This allows screen modes and other parameters to be
  set before the user sees the screen.  However, this broke so many
  programs that we put in the ``silent-startup'' hack.  A disk installed
  with 1.3 install opens the screen as before.  A disk installed under 2.0
  opens silently.

  Never steal the Workbench bitplanes.  You don't know where they are, how
  big they are, what format they may be in, or even if they are allocated.
  Recovering the memory is a bit tricky.

  Under 2.0:  Simply avoid any output from your s:startup-sequence.  If
  your program opens a screen it will be the first screen the user ever
  sees.  Note that if ENDCLI is ever hit, the screen will pop open.

  Under 1.3:  After ENDCLI, call the CloseWorkbench() function to close
  the screen.  This also works under 2.0.  Loop on CloseWorkbench() with a
  delay between loops.  Continue looping until CloseWorkbench() succeeds
  or too much time has passed.  Note that a new program called EndRun is
  available for starting non-returning programs from the startup-sequence.
  EndRun will reduce memory fragmentation and will close Workbench if it
  is open.  EndRun.lzh will be available in Commodore's Amiga listings
  area on BIX.


Layers

* Use NewLayerInfo() to create, not FattenLayerInfo(), ThinLayerInfo(),
  InitLayers().

* Simple-refresh preserves all of the pixels it can.  Sizing a
  SIMPLE_REFRESH window no longer clears the whole window.

* Speed of layer operations is different.  Don't depend on layer
  operations to finish before or after other asynchronous actions.


Graphics

* Do not rely on the order of Copper list instructions.  For example,
  2.0's MrgCop() builds different Copper lists to that of 1.3, by
  including new registers in the list (e.g. MOVE xxxx,DIWHIGH).  This
  changes the positions of  the  other  instructions.   We  know  of one
  game that 'assumes' the BPLxPTRs  would be at a certain offset in the
  Copper list, and that is now broken on machines running 2.0 with the new
  Denise chip.

* Graphics and layers functions which use the blitter generally return
  after STARTING the final blit.  If you are mixing graphics rendering
  calls and processor access of the same memory, you must WaitBlit()
  before touching (or deallocating) the source or destination memory with
  the processor.  For example, the Text() function was sped up for 2.0,
  causing some programs to trash partial lines of text.

* ColorMap structure is bigger.  Programs must use GetColorMap() to
  create one.

* Blitter rtns decide ascend/descend on 1st plane only.

* Changing the display mode of an existing screen or viewport while it
  is open is still not a supported operation.

* GfxBase DisplayFlags and row/cols may not match Workbench screen.

* Do not hardcode modulo values - use BitMap->BytesPerRow.

* If the graphics Autodocs say that you need a TmpRas of a certain size
  for some functions, then you must make that the minimum size.  In some
  cases, before 2.0, you may have gotten away with using a smaller TmpRas
  with some functions (for example Flood() ).  To be more robust, Graphics
  now checks the TmpRas size and will fail the function call if the TmpRas
  is too small.

* ECS chips under 2.0 use a different method of generating displays.
  The display window registers now control DMA.

* LoadRGB4() used to poke colors into the active copperlist with no
  protection against deallocation of that copperlist while it was being
  poked. Under 2.0, semaphore protection of the copperlist was added to
  LoadRGB4(). This semaphore protection makes it totally incorrect and
  extremely dangerous to call LoadRGB4() during an interrupt.  The general
  symptom of this problem is that a system deadlock can be caused by
  dragging one screen up and down while another is cycling.  Color cycling
  should be performed from within a task, not an interrupt.  Note that in
  general, the only functions which may be safely called from within an
  interrupt are the small list of Exec functions documented in the ``Exec:
  Interrupts'' chapter of ROM Kernel Manual: Libraries and Devices.


Fonts

* Some font format changes (old format supported).

* Private format of .font files has changed (use FixFonts to create).

* Default fonts may be larger, proportional.

* Topaz is now sans-serif.

* Any size font will be created via scaling as long as TextAttr.Flags
  FPF_DESIGNED bit is not set.  If you were asking for an extreme size,
  like size 1 to get smallest available, or 999 to get largest available,
  you will get a big (or very very small) surprise now.

* Do not use -1 for TextAttr.Flags or Styles, nor as the flags for
  AvailFonts (one high bit now causes AvailFonts to return different
  structures).  Only set what you know you want.  A kludge has been added
  to the OS to protect applications which currently pass -1 for AvailFonts
  flags.


CLI / Shell

* Many more commands are now built-in (no longer in C:).  This can break
  installation scripts that copy C:commandname, and programs that try to
  Lock() or Open() C:commandname to check for the command's existence.

* The limit of 20 CLI processes is gone and the DOSBase CLI table has
  changed to accomodate this.  Under V36 and higher, you should use new
  2.0 functions rather than accessing the CLI table directly.

* Shell windows now have Close Gadgets.  The EOF character is passed for
  the Close Gadget of a Shell.  This is -1L with CON: getchar(), and the
  Close Gadget raw event ESC seq with RAW:.

* Shells now use the simple-refresh character-mapped console (see
  Console notes).


Console

* By default, CON: now opens SIMPLE_REFRESH windows using the V36/V37
  console character mapped mode.  Because of some differences between
  character mapped consoles, and SMART_REFRESH non-mapped consoles, this
  may cause incompatibilities with some applications.  For example, the
  Amiga private sequences to set left/top offset, and set line/page length
  behave differently in character mapped console windows.  The only known
  work-around is to recompile asking for a CON: (or RAW:) window using the
  SMART flag.

* Simple refresh/character mapped console windows now support the
  ability to highlight, and copy text with the mouse.  This feature, as
  well as pasting text should be transparent to programs which use CON:
  for console input, and output.  Pasted text will appear in your input
  stream as if the user had typed it.

* While CONCLIP (see s:startup-sequence) is running, programs may
  receive ``<CSI>0 v'' in their input stream indicating the user wants to
  paste text from the clipboard.  This shouldn't cause any problems for
  programs which parse correctly (however we know that it does; the most
  common problems are outputting the sequence, or confusing it with
  another sequence like that for FKEY 1 which is ``<CSI>0~'').

* The console.device now renders a ghosted cursor in inactive console
  windows (both SMART_REFRESH, and SIMPLE_REFRESH with character maps).
  Therefore, rendering over the console's cursor with graphics.library
  calls can trash the cursor; if you must do this, first turn off the
  cursor.

* Some degree of unofficial support has been put in for programs which
  use SMART_REFRESH console windows, and use graphics.library calls mixed
  with console.device sequences to scroll, draw text, clear, etc.  This is
  not supported in SIMPLE_REFRESH windows with character maps, and is
  strongly discouraged in all cases.

* Closing an Intuition window before closing the attached console.device
  worked in the past; it will now crash or hang the machine.

* Under 1.2-1.3, vacated portions of a console window (e.g., areas
  vacated because of a clear, or a scroll) were filled in with the
  character cell color.  As of V36 this is no longer true; vacated areas
  are filled in with the global background color which can be set using
  the SGR sequence ``<ESC>[>##m'' where ## is a value between 0-7.  In
  order to set the background color under V36/V37, send the SGR to set
  background color, and a FormFeed to clear the screen.

* Note that SIMPLE_REFRESH character mapped consoles are immediately
  redrawn with the global background color when changed--this is not
  possible with SMART_REFRESH windows.


Additional Information

 Task Switching
 Intuition Gadgets and Window Borders
 Intuition Fonts


Task Switching

The 1.3 Kickstart contained two task switching bugs.  After an interrupt,
a task could lose the CPU to another equal priority task, even if the
first task's time was not up.  The second bug allowed a task who's time
was up to hold on to the CPU either forever, or until a higher priority
task was scheduled.  Two busy-waiting tasks at high priority would never
share the CPU.  Because the input.device runs at priority 20, usually the
effect of these bugs was masked out for low priority tasks.  Because of
the bugs, the ExecBase->Quantum field had little effect.

For 2.0, a task runs until either its Quantum is up, or a higher priority
task preempts it.  When the Quantum time is up, the task will now lose the
CPU.  The Quantum was set to 16/60 second for 1.3, and 4/60 second for 2.0.

In general, the 2.0 change makes the system more efficient by eliminating
unnecessary task switches on interrupt-busy systems (for example, during
serial input).  However, the change has caused problems for some programs
that use two tasks of equal priority, one busy-waiting and one Wait()ing
on events such as serial input.  Previously, each incoming serial
character interrupt would cause task context switch allowing the
event-handling task to run immediately.  Under 2.0 the two tasks share the
processor fairly.


Intuition Gadgets and Window Borders

If 2.0 Intuition finds a gadget whose hit area (gadget Left/Top/
Width/Height) is substantially inside the border, it will be treated as
though it was declared in the border.  This is called ``bordersniffing''.
Gadgets declared as being in the border or detected by Intuition as being
in the border are refreshed each time after the border is refreshed, and
thus aren't clobbered.

Noteworthy special cases:

1) A gadget that has several pixels not in the border is not
   bordersniffed.  An example would be an 18-pixel high gadget in the
   bottom border of a SIZEBBOTTOM window.  About half the gadget will
   be clobbered by the border rendering.

2) A gadget that is not substantially in the border but has imagery that
   extends into the border cannot be sniffed out by Intuition.

3) A gadget that is substantially in the border but has imagery that
   extends into the main part of the window will be sniffed out as a
   border gadget, and this could change the refreshing results.  A
   common trick to put imagery in a window is to put a 1x1 or 0x0 dummy
   gadget at window location (0,0) and attach the window imagery to it.
   To support this, Intuition will never bordersniff gadgets of size |x|
   or smaller.

All these cases can be fixed by setting the appropriate GACT_xxxBORDER
gadget Activation flag.

4) In rare cases, buttons rendered with Border structures and JAM1 text
   may appear invisible under 2.0.  We apologize, but there is nothing
   that can be done on our end, even if the application technically did
   nothing wrong.


Intuition Fonts

The following table shows where the Intuition gets its fonts from:

   What you tell OpenScreen  Screen's Font          Windows' RPort's Font
   ------------------------  -------------          ---------------------
A. NewScreen.Font = myfont  myfont                          myfont
B. NewScreen.Font = NULL    GfxBase->DefaultFont    GfxBase->DefaultFont
C. {SA_Font, myfont}        myfont                          myfont
D. {SA_SysFont, 0}          GfxBase->DefaultFont    GfxBase->DefaultFont
E. {SA_SysFont, 1}          Font Prefs Screen text  GfxBase->DefaultFont

Notes:

  A and B are the options that existed in releases prior to V36.

  C and D are new V36 tags that are equivalent to A and B respectively.

  E is a NEW option for V36.  The Workbench screen uses this option.

  GfxBase->DefaultFont will always be monospace.  This is the
  ``System Default Text'' from Font Preferences.

  The ``Screen Text'' choice from Font Preferences can be monospace or
  proportional.

  'myfont' can be any font of the programmer's choosing, including a
  proportional one.  This is true under all releases of the OS.

The menu bar, window titles, menu-items, and the contents of a string
gadget use the screen's font.  The font used for menu items can be
overridden in the item's IntuiText structure.  Under V36 and higher, the
font used in a string gadget can be overridden through the StringExtend
structure.  The font of the menu bar and window titles cannot be
overridden.  Because the 2.0 Workbench screen uses option E to specify its
Screen font from the user's Screen font Preferences, applications which
open windows on the Workbench screen may get very large or proportional
fonts in their menu bars, window titles, menu-items and string gadgets.

To predict your window's titlebar height before you call OpenWindow():

    topborder = screen->WBorTop + screen->Font->ta_YSize + 1

The screen's font may not legally be changed after a screen is opened.

Be sure the screen cannot go away on you.  This is true if:

    1) You opened the screen yourself.
    2) You currently have a window open on the screen.
    3) You currently hold a lock on this screen (see LockPubScreen() ).

IntuiText rendered into a window (either through PrintIText() or as a
gadget's GadgetText) defaults to the Window RastPort font, but can be
overridden using its ITextFont field.  Text rendered with the Text()
graphics.library call appears in the Window RastPort font.

The Window's RPort's font shown above is the initial font that Intuition
sets for you in your window's RastPort.  It is legal to change that
subsequently with SetFont().


I-35: Release 2.0 Specific Functions and Commands

Compiled by Carolyn Scheppner

The 2.0 Release of the Amiga Operating System contains hundreds of new
library functions and device commands.  The following list is a quick
reference for all of the functions and commands that were introduced to
the Amiga OS in releases 2.00 through 2.04 (V36 and V37).  Only the 2.04
release contains all of these functions.

 asl.library (basename: _AslBase)  V36
 battclock.resource (basename: _BattClockBase)
 battmem.resource (basename: _BattMemBase)
 clipboard.device (device commands)
 commodities.library (basename: _CxBase)  V36
 disk.resource (basename: _DiskBase)
 diskfont.library (basename: _DiskfontBase)
 dos.library (basename: _DOSBase)
 exec.library (basename: _SysBase)
 expansion.library (basename: _ExpansionBase)
 gadtools.library (basename: _GadToolsBase)  V36
 graphics.library (basename: _GfxBase)
 icon.library (basename: _IconBase)
 iffparse.library (basename: _IFFParseBase)  V36
 input.device (basename: _InputBase)
 intuition.library (basename: _IntuitionBase)
 keymap.library (basename: _KeymapBase)
 layers.library (basename: _LayersBase)
 mathieeesingbas.library (basename: _MathIeeeSingBasBase)  V36
 mathieeesingtrans.library (basename: _MathIeeeSingTransBase)  V36
 ramdrive.device (basename: _RamdriveDevice)
 rexxsyslib.library (basename: _RexxSysBase)  V36
 Timer.Device (basename: _TimerBase)
 trackdisk.device (device commands)
 utility.library (basename: _UtilityBase)  V36
 workbench.library (basename: _WorkbenchBase)


asl.library (basename: _AslBase) V36

AllocAslRequest(type,tagList)(d0/a0)    - Also stack-based amiga.lib stub
                                          AllocAslRequestTags() alloc an
                                          ASL requester, with TagItem
                                          modifiers (V36)
AllocFileRequest()()                    - Allocates a FileRequester
                                          structure (V36)
AslRequest(request,tagList)(a0/a1)      - lso stack-based amiga.lib stub
                                          AslRequestTags().  Get input
                                          from user for an ASL requester
                                          (V36)
FreeAslRequest(request)(a0)             - Frees requester obtained from
                                          AllocAslRequest (V36)
FreeFileRequest(fileReq)(a0)            - Frees requester allocated by
                                          AllocFileRequest (V36)
RequestFile(fileReq)(a0)                - request user to select file(s)
                                          (V36)


battclock.resource (basename: _BattClockBase)

ReadBattClock()()                       - Read time from clock chip.  (V36)

ResetBattClock()()                      - Reset the clock chip.  (V36)
WriteBattClock(time)(d0)                - Set the time on the clock chip.
                                          (V36)


battmem.resource (basename: _BattMemBase)

ObtainBattSemaphore()()                 - Obtain access to nonvolatile
                                          ram. (V36)
ReadBattMem(buffer,offset,length)(a0,d0/d1)
                                        - Read a bitstring from
                                          nonvolatile ram.  (V36)
ReleaseBattSemaphore()()                - Allow nonvolatile ram to others.
                                           (V36)
WriteBattMem(buffer,offset,length)(a0,d0/d1)
                                        - Write a bitstring to nonvolatile
                                          ram.  (V36)


clipboard.device (device commands)

CBD_CHANGEHOOK                          - Add or remove a clip change
                                          hook.


commodities.library (basename: _CxBase) V36

ActivateCxObj(co,true)(a0,d0)           - Change the activation state of a
                                          commodity object.
AddIEvents(events)(a0)                  - Add input events to commodities'
                                          input stream. (V36)
AttachCxObj(headobj,co)(a0/a1)          - Attach a commodity object to the
                                          end of an existing
ClearCxObjError(co)(a0)                 - Clear the accumulated error
                                          value of a commodity
CreateCxObj(type,arg1,arg2)(d0/a0/a1)   - Create a new commodity object.
                                          (V36)
CxBroker(nb,error)(a0,d0)               - Create a commodity broker. (V36)
CxMsgData(cxm)(a0)                      - Obtain a pointer to a commodity
                                          message's data area. (V36)
CxMsgID(cxm)(a0)                        - Obtain the ID of a commodity
                                          message. (V36)
CxMsgType(cxm)(a0)                      - Obtain the type of a commodity
                                          message. (V36)
CxObjError(co)(a0)                      - Obtain a commodity object's
                                          accumulated error. (V36)
CxObjType(co)(a0)                       - Obtain the type of a commodity
                                          object. (V36)
DeleteCxObj(co)(a0)                     - Delete a commmodity object. (V36)

DeleteCxObjAll(co)(a0)                  - Recursively delete a tree of
                                          commodity objects.
DisposeCxMsg(cxm)(a0)                   - Delete a commodity message. (V36)

DivertCxMsg(cxm,headobj,ret)(a0/a1/a2)  - Send a commodity message down an
                                          object list. (V36)
EnqueueCxObj(headobj,co)(a0/a1)         - Insert a commodity object within
                                          a list of objects
InsertCxObj(headobj,co,pred)(a0/a1/a2)  - Insert a commodity object in a
                                          list after a given
InvertKeyMap(ansicode,event,km)(d0/a0/a1)
                                        - Generate an input event from an
                                          ANSI code. (V36)
ParseIX(description,ix)(a0/a1)          - Initialize an input expression
                                          given a description string.
RemoveCxObj(co)(a0)                     - Remove a commodity object from a
                                          list. (V36)
RouteCxMsg(cxm,co)(a0/a1)               - Set the next destination of a
                                          commodity message. (V36)
SetCxObjPri(co,pri)(a0,d0)              - Set the priority of a commodity
                                          object. (V36)
SetFilter(filter,text)(a0/a1)           - Change the matching condition of
                                          a commodity filter.
SetFilterIX(filter,ix)(a0/a1)           - Change the matching condition of
                                          a commodity filter.
SetTranslate(translator,events)(a0/a1)  - Replace a translator object's
                                          translation list. (V36)


disk.resource (basename: _DiskBase)

ReadUnitID(unitNum)(d0)                 - Reread and return the type of
                                          drive (V37)


diskfont.library (basename: _DiskfontBase)

NewScaledDiskFont(sourceFont,destTextAttr)(a0/a1)
                                        - Create a DiskFont scaled from
                                          another. (V36)


dos.library (basename: _DOSBase)

AbortPkt(port,pkt)(d1/d2)               - Aborts an asynchronous packet,
                                          if possible. (V36)
AddBuffers(name,number)(d1/d2)          - Changes the number of buffers
                                          for a filesystem (V36)
AddDosEntry(dlist)(d1)                  - Add a Dos List entry to the
                                          lists (V36)
AddPart(dirname,filename,size)(d1/d2/d3)- Appends a file/dir to the end of
                                          a path (V36)
AddSegment(name,seg,system)(d1/d2/d3)   - Adds a resident segment to the
                                          resident list (V36)
AllocDosObject(type,tags)(d1/d2)        - Creates a dos object (V36)
AssignAdd(name,lock)(d1/d2)             - Adds a lock to an assign for
                                          multi-directory assigns (V36)
AssignLate(name,path)(d1/d2)            - Creates an assignment to a
                                          specified path later (V36)
AssignLock(name,lock)(d1/d2)            - Creates an assignment to a
                                          locked object (V36)
AssignPath(name,path)(d1/d2)            - Creates an assignment to a
                                          specified path (V36)
AttemptLockDosList(flags)(d1)           - Attempt to lock the Dos Lists
                                          for use (V36)
ChangeMode(type,fh,newmode)(d1/d2/d3)   - Change the current mode of a
                                          lock or filehandle (V36)
CheckSignal(mask)(d1)                   - Checks for break signals (V36)
Cli()()                                 - Returns a pointer to the CLI
                                          structure of the process (V36)
CliInitNewcli(dp)(a0)                   - Set up a process as a shell
                                          according to the inital packet.
CliInitRun(dp)(a0)                      - Set up a process as a shell
                                          according to the inital packet.
CompareDates(date1,date2)(d1/d2)        - Compares two datestamps (V36)
CreateNewProc(tags)(d1)                 - Create a new process (V36)
DateToStr(datetime)(d1)                 - Converts a DateStamp to a string
                                          (V36)
DeleteVar(name,flags)(d1/d2)            - Deletes a local or environment
                                          variable (V36)
DoPkt(port,action,arg1,arg2,arg3,arg4,arg5)(d1/d2/d3/d4/d5/d6/d7)
                                        - Send a dos packet and wait for
                                          reply (V36)
DupLockFromFH(fh)(d1)                   - Gets a lock on an open file (V36)

EndNotify(notify)(d1)                   - Ends a notification request (V36)

ErrorReport(code,type,arg1,device)(d1/d2/d3/d4)
                                        - Displays a Retry/Cancel
                                          requester for an error (V36)
ExAll(lock,buffer,size,data,control)(d1/d2/d3/d4/d5)
                                        - Examine an entire directory (V36)

ExamineFH(fh,fib)(d1/d2)                - Gets information on an open file
                                          (V36)
Fault(code,header,buffer,len)(d1/d2/d3/d4)
                                        - Returns the text associated with
                                          a DOS error code (V36)
FGetC(fh)(d1)                           - Read a character from the
                                          specified input (buffered) (V36)
FGets(fh,buf,buflen)(d1/d2/d3)          - Reads a line from the specified
                                          input (buffered) (V36)
FilePart(path)(d1)                      - Returns the last component of a
                                          path (V36)
FindArg(keyword,template)(d1/d2)        - Find a keyword in a template
                                          (V36)
FindCliProc(num)(d1)                    - Returns a pointer to the
                                          requested CLI process (V36)
FindDosEntry(dlist,name,flags)(d1/d2/d3)- Finds a specific Dos List entry
                                          (V36)
FindSegment(name,seg,system)(d1/d2/d3)  - Finds a segment on the resident
                                          list (V36)
FindVar(name,type)(d1/d2)               - Finds a local variable (V36)
Flush(fh)(d1)                           - Flushes buffers for a buffered
                                          filehandle (V36)
Format(filesystem,volumename,dostype)(d1/d2/d3)
                                        - Causes a filesystem to
                                          initialize itself (V36)
FPutC(fh,ch)(d1/d2)                     - Write a character to the
                                          specified output (buffered) (V36)
FPuts(fh,str)(d1/d2)                    - Writes a string the the
                                          specified output (buffered) (V36)
FRead(fh,block,blocklen,number)(d1/d2/d3/d4)
                                        - Reads a number of blocks from an
                                          input (buffered) (V36)
FreeArgs(args)(d1)                      - Free allocated memory after
                                          ReadArgs() (V36)
FreeDeviceProc(dp)(d1)                  - Releases port returned by
                                          GetDeviceProc() (V36)
FreeDosEntry(dlist)(d1)                 - Frees an entry created by
                                          MakeDosEntry (V36)
FreeDosObject(type,ptr)(d1/d2)          - Frees an object allocated by
                                          AllocDosObject() (V36)
FWrite(fh,block,blocklen,number)(d1/d2/d3/d4)
                                        - Writes a number of blocks to an
                                          output (buffered) (V36)
GetArgStr()()                           - Returns the arguments for the
                                          process (V36)
GetConsoleTask()()                      - Returns the default console for
                                          the process (V36)
GetCurrentDirName(buf,len)(d1/d2)       - Returns the current directory
                                          name (V36)
GetDeviceProc(name,dp)(d1/d2)           - Finds a handler to send a
                                          message to (V36)
GetFileSysTask()()                      - Returns the default filesystem
                                          for the process (V36)
GetProgramDir()()                       - Returns a lock on the directory
                                          the program was loaded
GetProgramName(buf,len)(d1/d2)          - Returns the current program name
                                          (V36)
GetPrompt(buf,len)(d1/d2)               - Returns the prompt for the
                                          current process (V36)
GetVar(name,buffer,size,flags)(d1/d2/d3/d4)
                                        - Returns the value of a local or
                                          global variable (V36)
Inhibit(name,onoff)(d1/d2)              - Inhibits access to a filesystem
                                          (V36)
InternalLoadSeg(fh,table,funcarray,stack)(d0/a0/a1/a2)
                                        - Low-level load routine (V36)
InternalUnLoadSeg(seglist,freefunc)(d1/a1)
                                        - Unloads a seglist loaded with
                                          InternalLoadSeg() (V36)
IsFileSystem(name)(d1)                  - Returns whether a Dos handler is
                                          a filesystem (V36)
LockDosList(flags)(d1)                  - Locks the specified Dos Lists
                                          for use (V36)
LockRecord(fh,offset,length,mode,timeout)(d1/d2/d3/d4/d5)
                                        - Locks a portion of a file (V36)
LockRecords(recArray,timeout)(d1/d2)    - Lock a series of records (V36)
MakeDosEntry(name,type)(d1/d2)          - Creates a DosList structure (V36)

MakeLink(name,dest,soft)(d1/d2/d3)      - Creates a filesystem link (V36)
MatchEnd(anchor)(d1)                    - Free storage allocated for
                                          MatchFirst()/MatchNext() (V36)
MatchFirst(pat,anchor)(d1/d2)           - Finds file that matches pattern
                                          (V36)
MatchNext(anchor)(d1)                   - Finds the next file or directory
                                          that matches pattern (V36)
MatchPattern(pat,str)(d1/d2)            - Checks for a pattern match with
                                          a string (V36)
MatchPatternNoCase(pat,str)(d1/d2)      - Checks for a pattern match with
                                          a string (V37)
MaxCli()()                              - Returns the highest CLI process
                                          number possibly in use (V36)
NameFromFH(fh,buffer,len)(d1/d2/d3)     - Get the name of an open
                                          filehandle (V36)
NameFromLock(lock,buffer,len)(d1/d2/d3) - Returns the name of a locked
                                          object (V36)
NewLoadSeg(file,tags)(d1/d2)            - Improved version of LoadSeg for
                                          stacksizes (V36)
NextDosEntry(dlist,flags)(d1/d2)        - Get the next Dos List entry (V36)

OpenFromLock(lock)(d1)                  - Opens a file you have a lock on
                                          (V36)
ParentOfFH(fh)(d1)                      - Returns a lock on the parent
                                          directory of a file (V36)
ParsePattern(pat,buf,buflen)(d1/d2/d3)  - Create a tokenized string for
                                          MatchPattern() (V36)
ParsePatternNoCase(pat,buf,buflen)(d1/d2/d3)
                                        - Create a tokenized string for
PathPart(path)(d1)                      - Returns a pointer to the end of
                                          the next-to-last (V36)
PrintFault(code,header)(d1/d2)          - Returns the text associated with
                                          a DOS error code (V36)
PutStr(str)(d1)                         - Writes a string the the default
                                          output (buffered) (V36)
ReadArgs(template,array,args)(d1/d2/d3) - Parse the command line input
                                          (V36)
ReadItem(name,maxchars,cSource)(d1/d2/d3)
                                        - Reads a single argument/name
                                          from command line (V36)
ReadLink(port,lock,path,buffer,size)(d1/d2/d3/d4/d5)
                                        - Reads the path for a soft
                                          filesystem link (V36)
Relabel(drive,newname)(d1/d2)           - Change the volume name of a
                                          volume (V36)
RemAssignList(name,lock)(d1/d2)         - Remove an entry from a multi-dir
                                          assign (V36)
RemDosEntry(dlist)(d1)                  - Removes a Dos List entry from
                                          it's list (V36)
RemSegment(seg)(d1)                     - Removes a resident segment from
                                          the resident list (V36)
ReplyPkt(dp,res1,res2)(d1/d2/d3)        - Replies a packet to the person
                                          who sent it to you (V36)
RunCommand(seg,stack,paramptr,paramlen)(d1/d2/d3/d4)
                                        - Runs a program using the current
                                          process (V36)
SameDevice(lock1,lock2)(d1/d2)          - Are two locks are on partitions
                                          of the device? (V37)
SameLock(lock1,lock2)(d1/d2)            - Returns whether two locks are on
                                          the same object (V36)
SelectInput(fh)(d1)                     - Select a filehandle as the
                                          default input channel (V36)
SelectOutput(fh)(d1)                    - Select a filehandle as the
                                          default input channel (V36)
SendPkt(dp,port,replyport)(d1/d2/d3)    - Sends a packet to a handler (V36)

SetArgStr(string)(d1)                   - Sets the arguments for the
                                          current process (V36)
SetConsoleTask(task)(d1)                - Sets the default console for the
                                          process (V36)
SetCurrentDirName(name)(d1)             - Sets the directory name for the
                                          process (V36)
SetFileDate(name,date)(d1/d2)           - Sets the modification date for a
                                          file or dir (V36)
SetFileSize(fh,pos,mode)(d1/d2/d3)      - Sets the size of a file (V36)
SetFileSysTask(task)(d1)                - Sets the default filesystem for
                                          the process (V36)
SetIoErr(result)(d1)                    - Sets the value returned by
                                          IoErr() (V36)
SetMode(fh,mode)(d1/d2)                 - Set the current behavior of a
                                          handler (V36)
SetProgramDir(lock)(d1)                 - Sets the directory returned by
                                          GetProgramDir (V36)
SetProgramName(name)(d1)                - Sets the name of the program
                                          being run (V36)
SetPrompt(name)(d1)                     - Sets the CLI/shell prompt for
                                          the current process (V36)
SetVar(name,buffer,size,flags)(d1/d2/d3/d4)
                                        - Sets a local or environment
                                          variable (V36)
SetVBuf(fh,buff,type,size)(d1/d2/d3/d4) - Set buffering modes and size
                                          (V36)
SplitName(name,seperator,buf,oldpos,size)(d1/d2/d3/d4/d5)
                                        - Splits out a component of a
                                          pathname into a buffer (V36)
StartNotify(notify)(d1)                 - Starts notification on a file or
                                          directory (V36)
StrToDate(datetime)(d1)                 - Converts a string to a DateStamp
                                          (V36)
StrToLong(string,value)(d1/d2)          - String to long value (decimal)
                                          (V36)
SystemTagList(command,tags)(d1/d2)      - Have a shell execute a command
                                          line (V36)
UnGetC(fh,character)(d1/d2)             - Makes a char available for
                                          reading again. (buffered) (V36)
UnLockDosList(flags)(d1)                - Unlocks the Dos List (V36)
UnLockRecord(fh,offset,length)(d1/d2/d3)- Unlock a record (V36)
UnLockRecords(recArray)(d1)             - Unlock a list of records (V36)
VFPrintf(fh,format,argarray)(d1/d2/d3)  - Format and print a string to a
                                          file (buffered) (V36)
VFWritef(fh,format,argarray)(d1/d2/d3)  - Write a BCPL formatted string to
                                          a file (buffered) (V36)
VPrintf(format,argarray)(d1/d2)         - Format and print string
                                          (buffered) (V36)
WaitPkt()()                             - Waits for a packet to arrive at
                                          your pr_MsgPort (V36)
WriteChars(buf,buflen)(d1/d2)           - Writes bytes to the the default
                                          output (buffered) (V36)


exec.library (basename: _SysBase)

AllocVec(byteSize,requirements)(d0/d1)  - Allocate memory and keep track
                                          of the size  (V36)
CacheClearE(address,length,caches)(a0,d0/d1)
                                        - Cache clearing with extended
                                          control (V37)
CacheClearU()()                         - User callable simple cache
                                          clearing (V37)
CacheControl(cacheBits,cacheMask)(d0/d1)- Instruction & data cache control
CachePostDMA(address,length,flags)(a0/a1,d1)
                                        - Take actions after to hardware
                                          DMA  (V37)
CachePreDMA(address,length,flags)(a0/a1,d1)
                                        - Take actions prior to hardware
                                          DMA  (V37)
ColdReboot()()                          - Reboot the Amiga (V36)
CreateIORequest(port,size)(a0,d0)       - Create an IORequest structure
                                          (V36)
CreateMsgPort()()                       - Allocate and initialize a new
                                          message port  (V36)
DeleteIORequest(iorequest)(a0)          - Free a request made by
                                          CreateIORequest()  (V36)
DeleteMsgPort(port)(a0)                 - Free a message port created by
                                          CreateMsgPort  (V36)
FreeVec(memoryBlock)(a1)                - Return AllocVec() memory to the
                                          system  (V36)
ObtainSemaphoreShared(sigSem)(a0)       - Gain shared access to a
                                          semaphore (V36)
StackSwap(newSize,newSP,newStack)(d0/d1/a0)
                                        - Exec supported method of
                                          replacing a task's stack.


expansion.library (basename: _ExpansionBase)

AddBootNode(bootPri,flags,deviceNode,configDev)(d0/d1/a0/a1)
                                        - Add a BOOTNODE to the system
                                          (V36)


gadtools.library (basename: _GadToolsBase) V36

CreateContext(glistptr)(a0)             - Create a place for GadTools
                                          context data. (V36)
CreateGadgetA(kind,gad,ng,taglist)(d0/a0/a1/a2)
                                        - Allocate and initialize a
                                          gadtools gadget. (V36)
CreateMenusA(newmenu,taglist)(a0/a1)    - Allocate and fill out a menu
                                          structure. (V36)
DrawBevelBoxA(rport,left,top,width,height,taglist)(a0,d0/d1/d2/d3/a1)
                                        - Draws a bevelled box. (V36)
FreeGadgets(gad)(a0)                    - Free a linked list of gadgets.
                                          (V36)
FreeMenus(menu)(a0)                     - Frees memory allocated by
                                          CreateMenusA(). (V36)
FreeVisualInfo(vi)(a0)                  - Return any resources taken by
                                          GetVisualInfo. (V36)
GetVisualInfoA(screen,taglist)(a0/a1)   - Get information GadTools needs
                                          for visuals. (V36)
GT_BeginRefresh(win)(a0)                - Begin refreshing friendly to
                                          GadTools. (V36)
GT_EndRefresh(win,complete)(a0,d0)      - End refreshing friendly to
                                          GadTools. (V36)
GT_FilterIMsg(imsg)(a1)                 - Filter an IntuiMessage through
                                          GadTools. (V36)
GT_GetIMsg(iport)(a0)                   - Get an IntuiMessage, with
                                          GadTools processing. (V36)
GT_PostFilterIMsg(imsg)(a1)             - Return the unfiltered message
                                          after
GT_RefreshWindow(win,req)(a0/a1)        - Refresh all the GadTools
                                          gadgets. (V36)
GT_ReplyIMsg(imsg)(a1)                  - Reply a message obtained with
                                          GT_GetIMsg(). (V36)
GT_SetGadgetAttrsA(gad,win,req,taglist)(a0/a1/a2/a3)
                                        - Change the attributes of a
                                          GadTools gadget. (V36)
LayoutMenuItemsA(firstitem,vi,taglist)(a0/a1/a2)
                                        - Position all the menu items.
                                          (V36)
LayoutMenusA(firstmenu,vi,taglist)(a0/a1/a2)
                                        - Position all the menus and menu
                                          items. (V36)


graphics.library (basename: _GfxBase)

BitMapScale(bitScaleArgs)(a0)           - Perform raster scaling on a bit
                                          map. (V36)
CloseMonitor(monitorSpec)(a0)           - Close a MonitorSpec (V36)
EraseRect(rp,xMin,yMin,xMax,yMax)(a1,d0/d1/d2/d3)
                                        - Fill a defined rectangular area
                                          using the current BackFill hook.
                                          (V36)
ExtendFont(font,fontTags)(a0/a1)        - Ensure tf_Extension has been
                                          built for a font (V36)
FindDisplayInfo(displayID)(d0)          - Search for a record identified
                                          by a specific key (V36)
FontExtent(font,fontExtent)(a0/a1)      - Get the font attributes of the
                                          current font (V36)
GetDisplayInfoData(handle,buf,size,tagID,displayID)(a0/a1,d0/d1/d2)
                                        - Query DisplayInfo Record
                                          parameters (V36)
GetVPModeID(vp)(a0)                     - Get the 32 bit DisplayID from a
                                          ViewPort. (V36)
GfxAssociate(associateNode,gfxNodePtr)(a0/a1)
                                        - Associate a graphics extended
                                          node with a given pointer
GfxFree(gfxNodePtr)(a0)                 - Free a graphics extended data
                                          structure (V36)
GfxLookUp(associateNode)(a0)            - Find a graphics extended node
                                          associated with a given pointer
                                          (V36)
GfxNew(gfxNodeType)(d0)                 - Allocate a graphics extended
                                          data structure (V36)
ModeNotAvailable(modeID)(d0)            - Check to see if a DisplayID
                                          isn't available. (V36)
NextDisplayInfo(displayID)(d0)          - Iterate current displayinfo
                                          identifiers (V36)
OpenMonitor(monitorName,displayID)(a1,d0)
                                        - Open a named MonitorSpec (V36)
ReadPixelArray8(rp,xstart,ystart,xstop,ystop,array,temprp)
                                         (a0,d0/d1/d2/d3/a2,a1)
                                        - Read the pen number value of a
                                          rectangular array
ReadPixelLine8(rp,xstart,ystart,width,array,tempRP)(a0,d0/d1/d2/a2,a1)
                                        - Read the pen number value of a
                                          horizontal line
ScalerDiv(factor,numerator,denominator)(d0/d1/d2)
                                        - Get the scaling result that
                                          BitMapScale would. (V36)
StripFont(font)(a0)                     - Remove the tf_Extension from a
                                          font (V36)
TextExtent(rp,string,count,textExtent)(a1,a0,d0/a2)
                                        - Determine raster extent of text
                                          data. (V36)
TextFit(rp,string,strLen,textExtent,constrainingExtent,strDirection,
       constrainingBitWidth,constrainingBitHeight)(a1,a0,d0/a2/a3,d1/d2/d3)
                                        - Count characters that will fit
                                          in a given extent (V36)
VideoControl(colorMap,tagarray)(a0/a1)  - Modify the operation of a
                                          ViewPort's ColorMap (V36)
WeighTAMatch(reqTextAttr,targetTextAttr,targetTags)(a0/a1/a2)
                                        - Get a measure of how well two
                                          fonts match. (V36)
WritePixelArray8(rp,xstart,ystart,xstop,ystop,array,temprp)
                (a0,d0/d1/d2/d3/a2,a1)
                                        - Write the pen number value of a
                                          rectangular array
WritePixelLine8(rp,xstart,ystart,width,array,tempRP)(a0,d0/d1/d2/a2,a1)
                                        - Write the pen number value of a
                                          horizontal line


icon.library (basename: _IconBase)

DeleteDiskObject(name)(a0)              - Delete a Workbench disk object
                                          from disk.
GetDefDiskObject(type)(d0)              - Read default wb disk object from
                                          disk.       (V36)
GetDiskObjectNew(name)(a0)              - Read in a Workbench disk object
                                          from disk.
PutDefDiskObject(diskObject)(a0)        - Write disk object as the default
                                          for its type.  (V36)


iffparse.library (basename: _IFFParseBase) V36

AllocIFF()()                            - Create a new IFFHandle
                                          structure.
AllocLocalItem(type,id,ident,dataSize)(d0/d1/d2/d3)
                                        - Create a local context item
                                          structure.
CloseClipboard(clipboard)(a0)           - Close and free an open
                                          ClipboardHandle.
CloseIFF(iff)(a0)                       - Close an IFF context.
CollectionChunk(iff,type,id)(a0,d0/d1)  - Declare a chunk type for
                                          collection.
CollectionChunks(iff,propArray,nProps)(a0/a1,d0)
                                        - Declare many collection chunks
                                          at once.
CurrentChunk(iff)(a0)                   - Get context node for current
                                          chunk.
EntryHandler(iff,type,id,position,handler,object)(a0,d0/d1/d2/a1/a2)
                                        - Add an entry handler to the
                                          IFFHandle context.
ExitHandler(iff,type,id,position,handler,object)(a0,d0/d1/d2/a1/a2)
                                        - Add an exit handler to the
                                          IFFHandle context.
FindCollection(iff,type,id)(a0,d0/d1)   - Get a pointer to the current
                                          list of collection
FindLocalItem(iff,type,id,ident)(a0,d0/d1/d2)
                                        - Return a local context item from
                                          the context stack.
FindProp(iff,type,id)(a0,d0/d1)         - Search for a stored property
                                          chunk.
FindPropContext(iff)(a0)                - Get the property context for the
                                          current state.
FreeIFF(iff)(a0)                        - Deallocate an IFFHandle struct.
FreeLocalItem(localItem)(a0)            - Deallocate a local context item
                                          structure.
GoodID(id)(d0)                          - Test if an identifier follows
                                          the IFF 85 specification.
GoodType(type)(d0)                      - Test if a type follows the IFF
                                          85 specification.
IDtoStr(id,buf)(d0/a0)                  - Convert a longword identifier to
                                          a null-terminated string.
InitIFF(iff,flags,streamHook)(a0,d0/a1) - Initialize an IFFHandle struct
                                          as a user stream.
InitIFFasClip(iff)(a0)                  - Initialize an IFFHandle as a
                                          clipboard stream.
InitIFFasDOS(iff)(a0)                   - Initialize an IFFHandle as a DOS
                                          stream.
LocalItemData(localItem)(a0)            - Get pointer to user data for
                                          local context item.
OpenClipboard(unitNum)(d0)              - Create a handle on a clipboard
                                          unit.
OpenIFF(iff,rwMode)(a0,d0)              - Prepare an IFFHandle to read or
                                          write a new IFF stream.
ParentChunk(contextNode)(a0)            - Get the nesting context node for
                                          the given chunk.
ParseIFF(iff,control)(a0,d0)            - Parse an IFF file from an
                                          IFFHandle struct stream.
PopChunk(iff)(a0)                       - Pop top context node off context
                                          stack.
PropChunk(iff,type,id)(a0,d0/d1)        - Specify a property chunk to
                                          store.
PropChunks(iff,propArray,nProps)(a0/a1,d0)
                                        - Declare many property chunks at
                                          once.
PushChunk(iff,type,id,size)(a0,d0/d1/d2)- Push a new context node on the
                                          context stack.
ReadChunkBytes(iff,buf,size)(a0/a1,d0)  - Read bytes from the current
                                          chunk into a buffer.
ReadChunkRecords(iff,buf,bytesPerRecord,nRecords)(a0/a1,d0/d1)
                                        - Read record elements from the
                                          current chunk into
SetLocalItemPurge(localItem,purgeHook)(a0/a1)
                                        - Set purge vector for a local
                                          context item.
StopChunk(iff,type,id)(a0,d0/d1)        - Declare a chunk which should
                                          cause ParseIFF to return.
StopChunks(iff,propArray,nProps)(a0/a1,d0)
                                        - Declare many stop chunks at
                                          once.
StopOnExit(iff,type,id)(a0,d0/d1)       - Declare a stop condition for
                                          exiting a chunk.
StoreItemInContext(iff,localItem,contextNode)(a0/a1/a2)
                                        - Store local context item in
                                          given context node.
StoreLocalItem(iff,localItem,position)(a0/a1,d0)
                                        - Insert a local context item into
                                          the context stack.
WriteChunkBytes(iff,buf,size)(a0/a1,d0) - Write data from a buffer into
                                          the current chunk.
WriteChunkRecords(iff,buf,bytesPerRecord,nRecords)(a0/a1,d0/d1)
                                        - Write records from a buffer to
                                          the current


input.device (basename: _InputBase)

PeekQualifier()()                       - Get the input device's current
                                          qualifiers (V36)


intuition.library (basename: _IntuitionBase)

AddClass(class)(a0)                     - Make a public class available
                                          (V36)
BuildEasyRequestArgs(window,easyStruct,idcmp,args)(a0/a1,d0/a3)
                                        - Simple creation of system
                                          request. (V36)
ChangeWindowBox(window,left,top,width,height)(a0,d0/d1/d2/d3)
                                        - Change window position and
                                          dimensions. (V36)
DisposeObject(object)(a0)               - Deletes a 'boopsi' object. (V36)
DrawImageState(rp,image,leftOffset,topOffset,state,drawInfo)
                                         (a0/a1,d0/d1/d2/a2)
                                        - Draw an (extended) Intuition
                                          Image with
EasyRequestArgs(window,easyStruct,idcmpPtr,args)(a0/a1/a2/a3)
                                        - Easy alternative to AutoRequest()
                                         . (V36)
EraseImage(rp,image,leftOffset,topOffset)(a0/a1,d0/d1)
                                        - Erases an Image. (V36)
FreeClass(classPtr)(a0)                 - Frees a boopsi class created by
                                          MakeClass(). (V36)
FreeScreenDrawInfo(screen,drawInfo)(a0/a1)
                                        - Finish using a DrawInfo
                                          structure. (V36)
GadgetMouse(gadget,gInfo,mousePoint)(a0/a1/a2)
                                        - Calculate gadget-relative mouse
                                          position. (V36)
GetAttr(attrID,object,storagePtr)(d0/a0/a1)
                                        - Inquire the value of some
                                          attribute of an object. (V36)
GetDefaultPubScreen(nameBuffer)(a0)     - Get name of default public
                                          screen. (V36)
GetScreenDrawInfo(screen)(a0)           - Get pointer to rendering
                                          information. (V36)
LockPubScreen(name)(a0)                 - Prevent a public screen from
                                          closing. (V36)
LockPubScreenList()()                   - Prevent changes to the system
                                          list. (V36)
MakeClass(classID,superClassID,superClassPtr,instanceSize,flags)
                                         (a0/a1/a2,d0/d1)
                                        - Create and initialize a boopsi
                                          class. (V36)
MoveWindowInFrontOf(window,behindWindow)(a0/a1)
                                        - Arrange the relative depth of a
                                          window. (V36)
NewObjectA(class,classID,tagList)(a0/a1/a2)
                                        - Create an object from a class.
                                          (V36)
NextObject(objectPtrPtr)(a0)            - Iterate through the object on an
                                          Exec list. (V36)
NextPubScreen(screen,namebuf)(a0/a1)    - Identify next public screen in
                                          the cycle. (V36)
ObtainGIRPort(gInfo)(a0)                - Set up a RastPort for a custom
                                          gadget. (V36)
OpenScreenTagList(newScreen,tagList)(a0/a1)
                                        - Also stack-based amiga.lib stub
                                          OpenScreenTags().  OpenScreen() with TagItem extension array. (V36)
OpenWindowTagList(newWindow,tagList)(a0/a1)
                                        - Also stack-based amiga.lib stub
                                          OpenWindowTags().  OpenWindow() with TagItem extension. (V36)
PointInImage(point,image)(d0/a0)        - Tests whether an image
                                          "contains" a point. (V36)
PubScreenStatus(screen,statusFlags)(a0,d0)
                                        - Change status flags for a public
                                          screen. (V36)
QueryOverscan(displayID,rect,oScanType)(a0/a1,d0)
                                        - Inquire about a standard
                                          overscan region. (V36)
ReleaseGIRPort(rp)(a0)                  - Release a custom gadget
                                          RastPort. (V36)
RemoveClass(classPtr)(a0)               - Make a public boopsi class
                                          unavailable. (V36)
ResetMenuStrip(window,menu)(a0/a1)      - Re-attach a menu strip to a
                                          window. (V36)
SetAttrsA(object,tagList)(a0/a1)        - Specify attribute values for an
                                          object. (V36)
SetDefaultPubScreen(name)(a0)           - Choose a new default public
                                          screen. (V36)
SetEditHook(hook)(a0)                   - Set global processing for string
                                          gadgets. (V36)
SetGadgetAttrsA(gadget,window,requester,tagList)(a0/a1/a2/a3)
                                        - Specify attribute values for a
                                          boopsi gadget. (V36)
SetMouseQueue(window,queueLength)(a0,d0)- Change limit on pending mouse
                                          messages. (V36)
SetPubScreenModes(modes)(d0)            - Establish global public screen
                                          behavior. (V36)
SysReqHandler(window,idcmpPtr,waitInput)(a0/a1,d0)
                                        - Handle system requester input.
                                          (V36)
UnlockPubScreen(name,screen)(a0/a1)     - Release lock on a public screen.
                                          (V36)
UnlockPubScreenList()()                 - Release public screen list
                                          semaphore. (V36)
ZipWindow(window)(a0)                   - Change window to "alternate"
                                          position and


keymap.library (basename: _KeymapBase)

AskKeyMapDefault()()                    - Ask for a pointer to the current
                                          default
MapANSI(string,count,buffer,length,keyMap)(a0,d0/a1,d1/a2)
                                        - Encode an ANSI string into
                                          keycodes. (V36)
MapRawKey(event,buffer,length,keyMap)(a0/a1,d1/a2)
                                        - Decode single raw key input
                                          event to an ANSI
SetKeyMapDefault(keyMap)(a0)            - Set the current default keymap.
                                          (V36)


layers.library (basename: _LayersBase)

CreateBehindHookLayer(li,bm,x0,y0,x1,y1,flags,hook,bm2)
                                         (a0/a1,d0/d1/d2/d3/d4/a3,a2)
                                        - Create a new layer behind all
                                          existing layers.
CreateUpfrontHookLayer(li,bm,x0,y0,x1,y1,flags,hook,bm2)
                                         (a0/a1,d0/d1/d2/d3/d4/a3,a2)
                                        - Create a new layer on top of
                                          existing layers.
InstallLayerHook(layer,hook)(a0/a1)     - Safely install a new
                                          Layer->BackFill hook.
MoveSizeLayer(layer,dx,dy,dw,dh)(a0,d0/d1/d2/d3)
                                        - Position/Size layer


mathieeesingbas.library (basename: _MathIeeeSingBasBase) V36

IEEESPAbs(parm)(d0)                     - Compute absolute value of IEEE
                                          single precision argument
IEEESPAdd(leftParm,rightParm)(d0/d1)    - Add one single precision IEEE
                                          number to another
IEEESPCeil(parm)(d0)                    - Compute Ceil function of IEEE
                                          single precision number
IEEESPCmp(leftParm,rightParm)(d0/d1)    - Compare two single precision
                                          floating point numbers
IEEESPDiv(dividend,divisor)(d0/d1)      - Divide one single precision IEEE
                                          by another
IEEESPFix(parm)(d0)                     - Convert IEEE single float to
                                          integer
IEEESPFloor(parm)(d0)                   - Compute Floor function of IEEE
                                          single precision number
IEEESPFlt(integer)(d0)                  - Convert integer to IEEE single
                                          precision number
IEEESPMul(leftParm,rightParm)(d0/d1)    - Multiply one double precision
                                          IEEE number by another
IEEESPNeg(parm)(d0)                     - Compute negative value of IEEE
                                          single precision number
IEEESPSub(leftParm,rightParm)(d0/d1)    - Subtract one single precision
                                          IEEE number from another
IEEESPTst(parm)(d0)                     - Compare IEEE single precision
                                          value to 0.0


mathieeesingtrans.library (basename: _MathIeeeSingTransBase) V36

IEEESPAcos(parm)(d0)                    - Compute the arc cosine of a
                                          number
IEEESPAsin(parm)(d0)                    - Compute the arcsine of a number
IEEESPAtan(parm)(d0)                    - Compute the arc tangent of
                                          number
IEEESPCos(parm)(d0)                     - Compute the cosine of a floating
                                          point number
IEEESPCosh(parm)(d0)                    - Compute the hyperbolic cosine of
                                          a floating point number
IEEESPExp(parm)(d0)                     - Compute the exponential of e
IEEESPFieee(parm)(d0)                   - Convert IEEE single to IEEE
                                          single
IEEESPLog(parm)(d0)                     - Compute the natural logarithm of
                                          a floating point number
IEEESPLog10(parm)(d0)                   - Compute logarithm base 10 of a
                                          number
IEEESPPow(exp,arg)(d1,d0)               - Raise a number to another number
                                          power
IEEESPSin(parm)(d0)                     - Compute the sine of a floating
                                          point number
IEEESPSincos(cosptr,parm)(a0,d0)        - Compute the arc tangent of a
                                          floating point number
IEEESPSinh(parm)(d0)                    - Compute the hyperbolic sine of a
                                          floating point number
IEEESPSqrt(parm)(d0)                    - Compute the square root of a
                                          number
IEEESPTan(parm)(d0)                     - Compute the tangent of a
                                          floating point number
IEEESPTanh(parm)(d0)                    - Compute the hyperbolic tangent
                                          of a floating point number
IEEESPTieee(parm)(d0)                   - Convert IEEE single to IEEE
                                          single


ramdrive.device (basename: _RamdriveDevice)

KillRAD(unit)(d0)                       - Kill ramdrive.device unit
KillRAD0()()                            - Kill ramdrive.device unit 0


rexxsyslib.library (basename: _RexxSysBase) V36

ClearRexxMsg(msgptr,count)(a0,d0)       - Releases and clears the argument
                                          array in a RexxMsg
CreateArgstring(string,length)(a0,d0)   - Create an argument string
                                          structure
CreateRexxMsg(port,extension,host)(a0/a1,d0)
                                        - Create an ARexx message
                                          structure
DeleteArgstring(argstring)(a0)          - Releases an Argstring created by
                                          CreateArgstring()
DeleteRexxMsg(packet)(a0)               - Releases a RexxMsg structure
                                          created by CreateRexxMsg()
FillRexxMsg(msgptr,count,mask)(a0,d0/d1)- Fill the argument strings as
                                          needed
IsRexxMsg(msgptr)(a0)                   - Function to determine if a
                                          message came from ARexx
LengthArgstring(argstring)(a0)          - Returns the length value stored
                                          in the argstring
LockRexxBase(resource)(d0)              - Obtain a semaphore lock on the
                                          RexxBase structure
UnlockRexxBase(resource)(d0)            - Release a semaphore lock on the
                                          RexxBase structure


Timer.Device (basename: _TimerBase)

GetSysTime(dest)(a0)                    - Get the system time. (V36)
ReadEClock(dest)(a0)                    - Get the current value of the
                                          E-Clock. (V36)


trackdisk.device (device commands)

TD_GETGEOMETRY                          - Gets the disk geometry table.
TD_EJECT                                - For those drives that support
                                          it.


utility.library (basename: _UtilityBase) V36

AllocateTagItems(numItems)(d0)          - Allocate a TagItem array (or
                                          chain). (V36)
Amiga2Date(amigaTime,date)(d0/a0)       - Calculate the date from a
                                          timestamp.  (V36)
CallHookPkt(hook,object,paramPacket)(a0/a2,a1)
                                        - Invoke a Hook function callback.
                                          (V36)
CheckDate(date)(a0)                     - Checks ClockData struct for
                                          legal date. (V36)
CloneTagItems(tagList)(a0)              - Copies a TagItem list.  (V36)
Date2Amiga(date)(a0)                    - Calculate seconds from
                                          01-Jan-1978.  (V36)
FilterTagChanges(newTagList,oldTagList,apply)(a0/a1,d0)
                                        - Eliminate TagItems which specify
                                          no change. (V36)
FilterTagItems(tagList,filterArray,logic)(a0/a1,d0)
                                        - Remove selected items from a
                                          TagItem list. (V36)
FindTagItem(tagVal,tagList)(d0/a0)      - Scans TagItem list for a Tag.
                                          (V36)
FreeTagItems(tagList)(a0)               - Frees allocated TagItem lists.
                                          (V36)
GetTagData(tagVal,defaultVal,tagList)(d0/d1/a0)
                                        - Obtain data corresponding to
                                          Tag. (V36)
MapTags(tagList,mapList,includeMiss)(a0/a1,d0)
                                        - Convert ti_Tag values in a list
                                          via map pairing. (V36)
NextTagItem(tagListPtr)(a0)             - Iterate TagItem lists. (V36)
PackBoolTags(initialFlags,tagList,boolMap)(d0/a0/a1)
                                        - Builds a "Flag" word from a
                                          TagList. (V36)
RefreshTagItemClones(cloneList,origList)(a0/a1)
                                        - Rejuvenates a clone from the
                                          original. (V36)
SDivMod32(dividend,divisor)(d0/d1)      - Signed 32 by 32 bit division and
                                          modulus. (V36)
SMult32(factor1,factor2)(d0/d1)         - Signed 32 by 32 bit multiply
                                          with 32 bit result. (V36)
Stricmp(string1,string2)(a0/a1)         - Case-insensitive string compare.
                                          (V37)
Strnicmp(string1,string2,length)(a0/a1,d0)
                                        - Case-insensitive string compare,
                                          length-limited. (V37)
TagInArray(tagVal,tagArray)(d0/a0)      - Check if a Tag value appears in
                                          a Tag array. (V36)
ToLower(character)(d0)                  - Convert a character to
                                          lowercase. (V37)
ToUpper(character)(d0)                  - Convert a character to
                                          uppercase. (V37)
UDivMod32(dividend,divisor)(d0/d1)      - Unsigned 32 by 32 bit division
                                          and modulus. (V36)
UMult32(factor1,factor2)(d0/d1)         - Unsigned 32 by 32 bit multiply
                                          with 32 bit result. (V36)


workbench.library (basename: _WorkbenchBase)

AddAppIconA(id,userdata,text,msgport,lock,diskobj,taglist)
                                         (d0/d1/a0/a1/a2/a3/a4)
                                        - Also stack-based amiga.lib stub
                                          AddAppIcon().  Add an icon to workbench's list of appicons.        (V36)
AddAppMenuItemA(id,userdata,text,msgport,taglist)(d0/d1/a0/a1/a2)
                                        - Also stack-based amiga.lib stub
                                          AddAppMenuItem().  Add a menuitem to workbench's list of appmenuitems (V36)
AddAppWindowA(id,userdata,window,msgport,taglist)(d0/d1/a0/a1/a2)
                                        - Also stack-based amiga.lib stub
                                          AddAppWindow() add a window to workbench's list of appwindows.  (V36)
RemoveAppIcon(appIcon)(a0)              - Remove an icon from workbench's
                                          list            (V36)
RemoveAppMenuItem(appMenuItem)(a0)      - Remove a menuitem from
                                          workbench's list      (V36)
RemoveAppWindow(appWindow)(a0)          - Remove a window from workbench's
                                          list         (V36)


I-43: Callback Hooks

by David Junod

The callback features of Release 2 provide a standard means for
applications to extend the functionality of libraries, devices, and
their applications.  This standard makes it easy for the operating
system to use custom modules from different high level programming
languages as part of the operating system.  For example, the layers
library, which takes care of treating a display as a series of layered
regions, allows an application to attach a pattern function to a
display layer.  Instead of filling in the background of a layer with
the background color, the layers library calls the custom pattern
function which fills in the layer display with a custom background
pattern.

 Callback Hook Functions and Structures
 Simple Callback Hook Usage


Callback Hook Functions and Structures

An application passes a custom function in the form of a callback Hook
(from <utility/hooks.h>):

    /* Standard hook structure */
    struct Hook
    {
        struct MinNode h_MinNode;
        ULONG (*h_Entry)();     /* stub function entry point */
        ULONG (*h_SubEntry)();  /* the custom function entry point */
        VOID *h_Data;           /* owner specific */
    };

    h_MinNode - This field is reserved for use by the module that will
    call the Hook.

    h_Entry - This is the address of the Hook stub.  When the OS calls
    a callback function, it puts parameters for the callback function
    in CPU registers A0, A1, and A2.  This makes it tough for higher
    level language programmers to use a callback function because most
    higher level languages don't have a way to manipulate CPU registers
    directly.  The solution is a stub function which first copies the
    parameters from the CPU registers to a place where a high level
    language function can get to them.   The stub function then calls
    the callback function.  Typically, the stub pushes the registers
    onto the stack in a specific order and the high level language
    callback function pops them off the stack.

    h_SubEntry - This is the address of the actual callback function
    that the application has defined.  The stub calls this function.

    h_Data - This field is for the application to use.  It could point
    to a global storage structure that the callback function utilizes.

There is only one function defined in utility.library for callback
functions.

    ULONG CallHookPkt(struct Hook *hook, VOID *object, VOID *paramPkt);
                               A0          A2            A1

This function invokes a standard callback Hook function.


Simple Callback Hook Usage

A Hook function must accept the following three parameters in these
specific registers:

    A0  Pointer to the Hook structure.
    A2  Pointer to an object to manipulate.  The object is context
        specific.
    A1  Pointer to a message packet.  This is also context specific.

For a callback function written in C, the parameters should appear in
this order:

myCallbackFunction(Pointer to Hook (A0),
                   Pointer to Object (A2),
                   Pointer to message (A1));

This is because the standard C stub pushes the parameters onto the
stack in the following order: A1, A2, A0.  The following assembly
language routine is a callback stub for C:

    INCLUDE 'exec/types.i'
    INCLUDE 'utility/hooks.i'

    xdef        _hookEntry

    _hookEntry:
        move.l  a1,-(sp)                ; push message packet pointer
        move.l  a2,-(sp)                ; push object pointer
        move.l  a0,-(sp)                ; push hook pointer
        move.l  h_SubEntry(a0),a0       ; fetch actual Hook entry point ...
        jsr     (a0)                    ; and call it
        lea     12(sp),sp               ; fix stack
        rts

If your C compiler supports registerized parameters, your callback
functions can get the parameters directly from the CPU registers
instead of having to use a stub to push them on the stack.  The
following C language routine uses registerized parameters to put
parameters in the right registers.  This routine requires a C compiler
that supports registerized parameters.

    #include <exec/types.h>
    #include <utility/hooks.h>

    #define     ASM     __asm
    #define     REG(x)  register __ ## x

    /* This function converts register-parameter hook calling
     * convention into standard C conventions.  It requires a C
     * compiler that supports registerized parameters, such as
     * SAS/C 5.xx or greater.
     */
    ULONG ASM hookEntry(REG(a0) struct Hook *h, REG(a2) VOID *o, REG(a1) VOID *msg)
    {
        return ((*h->h_SubEntry)(h, o, msg));
    }

A callback function is executed on the context of the module that
invoked it.  This usually means that callback functions cannot call
functions that need to look at environment specific data.  For example,
printf() needs to look at the current process's input and output
stream.  Entities like Intuition have no input and output stream.  The
limitations on a callback function depend heavily upon the subsystem
that is using them.  See that subsystem's documentation for more
information.

For the callback function to access any of its global data, it needs to
make sure the CPU can find the function's data segment.  It does this
by forcing the function to load the offset for the program's data
segment into CPU register A4.  See your compiler documentation for
details.

The following is a simple function that can be used as a callback Hook.

    ULONG MyFunction (struct Hook *h, VOID *o, VOID *msg)
    {
        /* A SASC and Manx function that obtains access to the global data segment */
        geta4();

        /* Debugging function to send a string to the serial port */
        KPrintF("Inside MyFunction()n");

        return (1);
    }

The next step is to initialize the Hook for use.  This basically means
that the fields of the Hook structure must be filled with appropriate
values.

The following simple function initializes a Hook structure.

    /* This simple function is used to initialize a Hook */
    VOID InitHook (struct Hook *h, ULONG (*func)(), VOID *data)
    {
        /* Make sure a pointer was passed */
        if (h)
        {
            /* Fill in the hook fields */
            h->h_Entry = (ULONG (*)()) hookEntry;
            h->h_SubEntry = func;
            h->h_Data = data;
        }
    }

Hooks1.c is a simple example of initializing and using a callback
Hook function.


I-47: Debugging with Enforcer and Mungwall

by Carolyn Scheppner

It is almost impossible for a human being to develop software without
including some bugs.  Some bugs make themselves known rather quickly.
Other bugs are not so easy to notice.  For example, two hard to find bugs
that sometimes slip past developers are using uninitialized pointers and
using memory which has already been freed.  These bugs often reference
semi-random memory, which contains semi-random data. Typically the
behavior of the software depends on the data passed to it.   If that data
is erratic, the behavior of the software will also be erratic.  Because
the behavior is erratic and unpredictable, the problem is very hard to
spot.  Quite often, bugs like these go unnoticed until software is running
in a real user's multitasking environment.  Fortunately, debugging tools
like Enforcer and Mungwall (and for assembler programmers, Scratch by Bill
Hawes) help uncover hidden bugs.

Enforcer is a debugging tool written by Bryce Nesbitt.  Its job is to
report any attempts to access regions of the Amiga address space that are
off-limits to applications.  These off-limits accesses include reading and
writing to the lowest 1K range of memory (except for reading ExecBase from
$4), writing to the Kickstart ROM, and reading and writing to non-existent
memory ranges.

Enforcer requires that the CPU has access to an MMU (Memory Management
Unit) to catch reads and writes to memory.  Most 68020 based accelerator
boards have MMU chips on them.  An MMU is built-in to each 68030 and 68040
CPU (currently Enforcer does not support 68040).

When an application tries to read a memory location that has been
read-protected by Enforcer, Enforcer intercepts that memory read, reports
the illegal memory access (known as an ``Enforcer hit''), and shows the
application a zero instead of the contents of the memory address.  The
application has no idea that Enforcer did anything.  When an application
tries to write to a memory location that has been write-protected by
Enforcer, Enforcer prevents the illegal memory write and issues an
Enforcer hit.

Enforcer is even more powerful when used in combination with Mungwall.
Mungwall was written by Ewout Walraven and is based on Memmung by Bryce
Nesbitt and Memwall by Randell Jesup.  The ``mung'' part of Mungwall fills
all of free memory (and all subsequently freed memory) with a large, odd,
32-bit value.  An odd value is likely to cause serious problems for any
program that uses wild or uninitialized pointers, or uses memory after it
has been freed.

Unlike Enforcer, Mungwall does not require any special hardware. Mungwall
can run without Enforcer and on non-MMU machines.

Mungwall uses several special 32-bit values to ``mung'' memory which helps
diagnose problems:

   Except when Enforcer is running, Mungwall sets location zero to
   $C0DEDBAD.  Normally, location zero is $00000000.  By putting an odd,
   non-zero value in location zero, any erroneous references to location
   zero are much more likely to show themselves.  For example, a program
   that references  location zero as character array will see a string
   that starts with the ASCII values $C0 $DE $DB $AD, rather than seeing a
   NULL string.

   When Mungwall starts up, it sets all free memory to $ABADCAFE.  If this
   number shows up while an application is running, it is likely that
   someone is referencing memory in the free list.

   When a program allocates memory, Mungwall sets that memory to $DEADF00D
   (Except when allocating memory with MEMF_CLEAR).  When an application
   accidentally accesses its memory before initializing it, the
   application will find the well-known value $DEADF00D rather than some
   random value that happened to be left in memory.

   Mungwall fills deallocated memory with $DEADBEEF, which makes using
   freed memory bugs much more obvious.

The ``wall'' part of Mungwall allocates extra memory before and after
every memory allocation and fills this memory ``wall'' with a fill pattern
(normally $BB) and some information Mungwall uses to perform certain tests
on an application's memory blocks:

   When an application deallocates memory, Mungwall reports when the size
   of the deallocated memory block does not match its size when it was
   allocated.

   Mungwall reports when a memory block's ``walls'' have been overwritten.

   Mungwall reports allocations and deallocations of memory blocks that
   are zero bytes long and deallocations of memory blocks that start at
   location zero.

   Mungwall has an option to ``snoop'' and report on all memory
   allocations and deallocations for all tasks or specific tasks.  This
   feature can be useful when tracking down memory losses.  Because the
   snoop option can generate so many reports, the output can be run
   through the snoopstrip program which will throw away all matching
   allocate/deallocate pairs.

 The Debugging Setup
 Sample Enforcer Output
 Sample Mungwall Output
 Using Enforcer and Mungwall Together
 A Sample Debugging Session
 More Remote Debugging Tips
 Who Should Use Enforcer and Mungwall


The Debugging Setup

Enforcer and Mungwall both output their debugging information to the
serial port at the baud rate to which the Amiga's serial hardware is
currently set.  After powerup, the serial hardware is set to 9600 baud.
You can use a terminal package to alter the current baud rate setting.
To set up an Amiga for serial debugging, connect your Amiga's serial
port via a NULL-modem serial cable to a terminal.

The best debugging setup is to connect your Amiga to another computer
running a terminal package.  Ideally the terminal package should have
an ASCII capture mode so it can capture all the serial debugging output
and save it to a file for examination.  The terminal package should
also beep when it receives a CTRL-G, as both Enforcer and Mungwall send
a CTRL-G beep with each Enforcer/Mungwall hit. There are several less
effective alternatives to using Enforcer and Mungwall with a remote
terminal.  Both can send their output to a serial printer.  There are
special versions of both Enforcer and Mungwall that send their output
to the parallel port (Enforcer.par and Mungwall.par) for output to a
parallel printer.  In a pinch, attach a modem to the serial port and
run a terminal package set to the modem's baud rate.  As long as the
modem has not made any telephone connection, the modem will bounce back
any Enforcer or Mungwall hits that come through the serial port, which
the terminal package can capture.  Because the debugging information
has to move at modem's baud rate, the modem method tends to lose data,
especially when there is a lot Enforcer/Mungwall hits.


Sample Enforcer Output

Here is a sample Enforcer hit which was caused by a program called
Lawbreaker which tried to read from location $14.

Program Counter (approximate)=  343F4A                    Fault address       =      14
User stack pointer           =  348734                    DOS process address =  339590
Data: DDDD0000 DDDD1100 DDDD2200 DDDD3300 DDDD4400 DDDD5500 DDDD6600 DDDD7700
Addr: AAAA0000 AAAA1100 AAAA2200 AAAA3300 AAAA4400 AAAA5500 AAAA6600 00002E28
Stck: 00210D70 00000FA0 00339F84 BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB
READ-WORD  (---)(-)(-)    SR=0008   SSW=0161
Background CLI, "lawbreaker", Hunk #0, Offset $5A

Program Counter - Normally, this is the address of the instruction that
was executing when the Enforcer hit occurred.  For some types of
Enforcer hits, this is the address of the instruction that executed
after the hit.  Note that if a program passes a bad pointer or an
improperly initialized structure to a system ROM routine, it can cause
the ROM code to read or write to an illegal address.

Fault Address - This is the address where the illegal access occurred.
In this example, the illegal access occurred at address $14, and as
specified later in the debugging output, this access was a READ-WORD
access.  So the illegal memory access was an attempt to read a word (2
bytes) at address $14.  Low memory accesses are often caused by NULL
pointers to structures.  If, for example, a ROM routine references a
WORD-sized structure member at offset $20, and an application passes
the ROM routine a NULL pointer as a pointer to that structure, Enforcer
will report that the ROM routine tried to read a word at address $20.

User Stack Pointer - This is the value that was in register A7 when the
Enforcer hit occurred.  It points to the top of the stack for the task
that was running when the Enforcer hit occurred.

DOS Process Address - This points to the Task structure of the task
that was running when the Enforcer hit occurred.

Data/Addr (Register Dump) - This is the contents of registers D0-D7 and
A0-A7.  This information can help assembly programmers and programmers
who like to debug at a low level.  Notice that register A7, the stack
pointer, no longer contains the stack pointer for the task that caused
the Enforcer hit (A7 does not match the user stack pointer above).
Ignore the value in A7.

Stck (Stack Dump) - This is the eight long words at the top of the
offending program's stack.  For those who need to see more of the
stack, there is a special version of Enforcer called
Enforcer.megastack.  that shows the last 32 long words on the stack.

Access Type - This tells what kind of memory access the Enforcer hit
is.  In this example the access is a READ-WORD, which most likely is a
result of Lawbreaker accessing a word-sized structure member.  There
are two other read access types: READ-BYTE, which is generally a result
of a bad string pointer, and READ-LONG, which is normally a result of a
bad pointer or a bad pointer within a structure.  When an errant
program directly or indirectly writes over Enforcer-protected memory,
Enforcer reports a  WRITE-BYTE, WRITE-WORD, or WRITE-LONG type access.
When Enforcer issues an INSTRUCTION type memory access, the CPU tried
to load an instruction from an invalid address.  Some common causes for
this type of Enforcer hit are:

An errant program has overwritten a program's instructions,
An errant program has overwritten a subroutine return address
        that was on the stack,
The CPU tried to execute a library function using an invalid library base.

Notice that the errant program is not necessarily the program that
caused the Enforcer hit.

Interrupt/Forbid/Disable - The series of parentheses after the access
type indicate if the Enforcer hit occurred in an interrupt (and if so,
the interrupt level), Forbid, or Disable state:

(I-n)(-)(-)     The hit occurred in an n level interrupt.
(---)(F)(-)     The hit occurred while the Amiga was in a Forbid state.
(---)(-)(D)     The hit occurred while the Amiga was in a Disable state.

SR (Status Register) - The CPU's status register (see 680x0 manual for
more information).

SSW (Special Status Word) - The special status word for 68010 though
68040 CPUs (see 680x0 manual for more information).

Program Name - The program name is the name of the task or command that
was executing when the Enforcer hit occurred.

Hunk Number and Offset - If possible, Enforcer also provides a hunk
offset to where the program counter was if the hit occurred within the
program's own code instructions.  This will only work if the errant
program was started from a shell.


Sample Mungwall Output

When Mungwall reports a hit, it lists:

The function that triggered the hit (either AllocMem() or FreeMem()).
It includes the functions arguments.

The name of the offending program (``attempted by `<program name>' '').

The address of the offending program's Task structure (``at 0x<task
address>'').

The address from which AllocMem()/FreeMem() was called.  Mungwall
reports two addresses: one labelled ``A:'' and one labelled ``C:''.
The ``A:'' address is the address if AllocMem()/FreeMem() was called
directly (i.e., using assembler or #pragmas) by the offending program.
The ``C:'' address is the address if AllocMem()/FreeMem() was called
from an amiga.lib C stub by the offending program.  Since Mungwall
patches the memory allocation functions, it can only guess the caller's
address based on the return address it finds on the stack.

The stack pointer at the time of the Mungwall hit.  It is labelled
``SP:''.

Note that Mungwall ignores the layers.library's partial deallocations.
If any other debugging tools patch AllocMem() or FreeMem(), Mungwall's
``A:'' and ``C:'' addresses may be thrown off by additional information
pushed on the stack, and Mungwall will also be unable to screen out the
layers.library's partial deallocations (which will often show up as
Mungwall hits on your task, CON:, or input.device).

Here are some sample Mungwall hits that were produced by a program
called mungwalltest.  As a reminder, the arguments for memory functions
are AllocMem(size,type) and FreeMem(address,size).

AllocMem(0x0,10000) attempted by `mungwalltest' (at 0x339590)
  from A:0x35C03A C:0x35677E SP:0x35CFC0         Tried to allocate 0 bytes
                                                 of memory.

FreeMem(0x0,16) attempted by `mungwalltest' (at 0x339590)
  from A:0x35C068 C:0x3567C4 SP:0x35CFB8         Tried to free memory with
                                                 a NULL pointer.

FreeMem(0x33BD10,0) attempted by `mungwalltest' (at 0x339590)
  from A:0x35C068 C:0x3567D4 SP:0x35CFB0         Tried to free 0 bytes of
                                                 memory.

Mis-aligned FreeMem(0x33BD14,16) attempted by `mungwalltest' (at 0x339590)
      from A:0x35C068 C:0x3567E2 SP:0x35CFA8     Deallocation address is
                                                 incorrect because it is
                                                 not aligned according to
                                                 AllocMem()'s lowest
                                                 memory chunk size.

Mismatched FreeMem size 14!
Original allocation: 16 bytes from A:0x35C03A C:0x3567A0 Task 0x339590
Testing with original size.                      Deallocation size does
                                                 not match the allocation
                                                 size.

19 byte(s) before allocation at 0x33BD10, size 16 were hit!
>$: BBBBBBBB BBBBBBBB BB536572 6765616E 74277320 50657070 65722000
                                                 Something wrote to the
                                                 bytes which precede the
                                                 allocation.

8 byte(s) after allocation at 0x33BD10, size 16 were hit!
>$: 75622042 616E6400 BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBBB
                                                 Something wrote to the
                                                 bytes which follow the
                                                 allocation.


Using Enforcer and Mungwall Together

Alone, Mungwall can catch a large variety of memory-related software
problems.  If Mungwall and Enforcer are used together, they can catch
many more well-hidden bugs.  One bug that is hard to catch is when a
program either mistakenly reads memory that does not belong to the
program or reads its own memory without initializing the memory first.

These bugs are normally hard to catch because the behavior of the
errant program usually depends on how it reacts to the data that
happens to be stored in that memory.  This makes the behavior of the
bug erratic.  Sometimes the errant program may crash.  Sometimes the
errant program may write over another program's data, causing the other
program to crash.  At other times, no noticeable abnormality takes
place.

Mungwall and Enforcer together can help find these bugs.  Because
Mungwall fills freed memory with the same odd 32-bit values, when an
errant program mistakenly accesses memory,  the behavior of the bug
will be consistent while Mungwall is running.  Also, the values
Mungwall puts in memory are more likely to cause the errant program to
access Enforcer-protected memory, triggering an Enforcer hit.


A Sample Debugging Session

The following is an example of debugging an Enforcer hit that occurred
using a test program called ownertest.  This hit was generated on an
A2500 with a 2.04 ROM image loaded using ZKick:

Program Counter (approximate)=  201946          Fault address       =       0
User stack pointer           =  566110          DOS process address =  38E888
Data: 00282D90 00000000 000003ED 0038FD8C 00000001 00000001 000E203B 00000001
Addr: 00225469 00000001 00282DE0 00448A3A 004487C0 004487CC 00001420 00002E28
Stck: 00448A3A 00223BA2 00280810 000003ED 0038FD8C 00000001 00000001 000E203B
READ-BYTE  (---)(F)(-)    SR=0010   SSW=0751
Background CLI, "ownertest"

The Program Counter is at $201946.  On a machine with the Kickstart in
ROM, the ROM addresses range from $F80000 to $FFFFFF under 2.0 or
greater and from $FC0000 to $FFFFFF under 1.3.  On a softkicked A3000,
the addresses are in the same range as real ROM addresses.  On a
softkicked A2500, $201946 is a ROM address (in this case, the ROM
ranges from $200000 to $27FFFF).  The first thing to do is figure out
in which ROM module the Enforcer hit occurred.  The debugging tool
owner , by Michael Sinz, will figure that out:

    1.Ram Disk:> owner 0x201946

    Address  - Owner
    --------   -----
    00201946 - in resident module: exec 37.132 (23.5.91)

Note that Owner looks at the ROM addresses of the Amiga on which it is
executing, so you must run owner on the machine that generated the
Enforcer hit.

Next, use the debugging tool lvo to figure out what function entry in
the Exec ROM module is closest to that ROM address.  Like owner, lvo
also looks at local machine's ROM addresses, so you have to run owner
on the machine that generated the Enforcer hit.  Note that lvo requires
the FD files to be in an ``FD:'' assign directory.  Pass the address
and the module name (from owner) to lvo.

    1.Ram Disk:> lvo exec romaddress=0x201946

    Closest to $201946 without going over:
    exec.library LVO $feec -276 FindName() jumps to $20192a on this system

Hmmm.  A lot of functions use FindName() on Exec lists, so, in this
case, the Program Counter does not pinpoint the problem.  However, it
does hint that FindName() probably received a bad string pointer.  The
``READ-BYTE'' attribute of the Enforcer hit is an extra clue that the
Ownertest program has a problem with a string pointer, since the most
common READ-BYTE actions are on strings.

Let's check the Enforcer stack dump and see if there are any other ROM
addresses there which might have called FindName():

    Stck: 00448A3A 00223BA2 00280810 000003ED 0038FD8C 00000001 00000001
          000E203B

The address closest to the top of the stack that looks like a ROM
address on this particular system is 0x00223BA2.  Let's see what ROM
module contains this address:

    1.Ram Disk:> owner 0x223BA2

    Address  - Owner
    --------   -----
    00223BA2 - in resident module: graphics 37.35 (23.5.91)

Let's see what function in the Graphics library is closest to this ROM
address:

    1.Ram Disk:> lvo graphics 0x223BA2

    Closest to $223ba2 without going over:
    graphics.library  LVO $ffb8 -72  OpenFont() jumps to $223b84 on this
    system

It looks like the ownertest program has a problem with a font name that
was not properly initialized.


More Remote Debugging Tips

Debugging with Enforcer and Mungwall is even more effective when an
application sends other debugging information to the serial or parallel
port.  The linker library debug.lib contains a printf()-like function,
kprintf(), to print information to the serial port.  The linker library
ddebug.lib contains a similar function called dprintf() that prints
debugging information to the parallel port.  The output from these
functions intermix with the output from Enforcer and Mungwall, making
it easy to pinpoint which part of the code is causing Enforcer or
Mungwall hits.

Functions like kprintf() and dprintf() are useful, but adding and
removing them from programs can be tedious.  One easy way to deal with
this problem is to include them only when a special label is defined:

    /**********    debug macros     ***********/
    #define MYDEBUG  1
    void kprintf(UBYTE *fmt,...);
    void dprintf(UBYTE *fmt,...);
    #define DEBTIME 0
    #define bug printf
    #if MYDEBUG
    #define D(x) (x); if(DEBTIME>0) Delay(DEBTIME);
    #else
    #define D(x) ;
    #endif /* MYDEBUG */
    /********** end of debug macros **********/

Set MYDEBUG to 1 to turn on debugging.  Set ``bug'' to:
    ``printf'' to send debugging information to the default console,
    ``kprintf'' to send debugging information to the serial port
            (link with debug.lib), and
    ``dprintf'' to send debugging information to the parallel port
            (link with ddebug.lib).

When using this macro, make sure there two close parentheses before the
semicolon at the end of each D(bug()) statement.

Example macro usage:

        win = OpenWindow(&mynewwin);
        D(bug("Opened window at $%lx\n", win));

A different low-level method of figuring out which instructions caused
an Enforcer hit is to disassemble program memory where the hit
occurred.  First, match the disassembly with your own code.  Assembly
programmers could just compare the disassembly to their source.  Others
could take the hex values of a sequence of position-independent 68000
instructions near the hit (i.e.  no addresses except for offsets and
branches) and do a search for this pattern in your object modules.  If
you find the pattern, do a mixed source and object disassembly of that
object module and then look in the output for instructions matching
those where the hit occurred.   For example, with SAS's OMD you could
compile your code with the flag -d1, then do the following:

    1.Ram Disk:> OMD >ram:dump mymodule.o mymodule.c


Who Should Use Enforcer and Mungwall

If you are developing Amiga software, it is extremely important that
you invest in a MMU, or at the very least make sure that your software
is tested on machines with  Enforcer and Mungwall (also test with
Enforcer alone as Mungwall can hide certain types of bugs).  If you are
programming in assembly, you should also test with Scratch by Bill
Hawes to catch improper usage of CPU registers.

Enforcer and Mungwall are not just for developers and QA departments.
Anyone who uses software can help find bugs in it with Enforcer.
During normal usage, they can catch hidden software problems.  Many
people at Commodore run Enforcer all of the time.  As more and more
people begin running these tools, they will become less tolerant of
software that causes Enforcer and Mungwall hits.

At a small developer meeting at a recent Amiga trade show, CATS was
disappointed to discover that, although the majority of the audience
believed that they needed Enforcer, a relatively small percentage of
them owned the equipment necessary to run it (i.e.,  an MMU).  If you
don't have an MMU, get one.  The investment in an A3000, 68030 card, or
68020+MMU card will quickly pay for itself.  It significantly cuts down
development time because it quickly catches bugs that are otherwise
hard to track down.


II-1: Executing External Programs with Release 2.0

by Carolyn Scheppner

The 2.0 Amiga operating system provides more flexible methods of
launching programs from an application.  The 2.0 dos.library contains
a new function, System(), which is more flexible and powerful than the
1.3 Execute() function.  Improvements to the con-handler, CON:, allow
programs to create ``auto con'' windows, which are console windows
that will only appear if input is requested from or output is sent to
that console.  The 2.0 con-handler also provides several other
enhancements, including Close gadgets for CON: windows and a feature
which allows a program to use an existing window as its CON: window.

 The System() Function
 The 2.0 Con-handler


The System() Function

The System() function is intended to replace the Execute() function of
release 1.3.  System() spawns a shell process to execute the command
line which is passed to System() as an argument.  The shell parses the
command-line normally, just like command-lines typed directly into the
shell's console.  If it can, System() will pass the current path and
directory to the programs it launches.

The System() function can execute external commands either
synchronously or asynchronously.  When System() is used synchronously,
control returns to the calling program after the external program has
completed.  In this case, System() returns the external program's
return code, or a -1 if the command could not be found or run.  On the
other hand, when System() initiates a program asynchronously, the
program is no longer a concern for the caller.  The operating system
will take care of the cleanup.  This is extremely useful for an
application that must start up multiple programs on user demand, such
as a hot key commodity.  By default, System() starts programs
synchronously.  To launch a program asynchronously, use the SYS_Asynch
tag with the data field set to TRUE.

With the System() call, it is easy to provide programs with specific
input and output handles.  The tags SYS_Input and SYS_Output (defined
in dos/dostags.h) are used to supply the input and output file
handles.  A program can pass its own input and output handles to a
synchronously launched program by passing the results of Input() and
Output(), respectively.  Note that with a synchronous System() call,
the OS will not close these handles when the spawned process exits.
In the case of an asynchronously launched program, the launching
program normally must provide new IO handles since the system
automatically closes these handles when the asynchronous process ends.
Because AmigaDOS wants separate handles for input and output, System()
will automatically create an output handle if it's passed a handle for
SYS_Input and NULL for SYS_Output.  This allows a program to open a
CON: window for input and use it for both input and output, as
System() will test to see if input is interactive and, if so, will
attempt to open ``*'' for output to that console.  If the input file
handle is not interactive, System() opens ``*'' on the current console
task.

Programs launched using System() are not restricted to the built-in,
or Boot, shell.  In the near future, System() will be able to take
advantage of specially designed shells (the design requirements of
these special shells have not yet been documented).  Two tags,
SYS_UserShell and SYS_CustomShell, specify which shell System() should
use to execute the command-line.  By using the SYS_UserShell tag with
a tag value of TRUE, an application tells System() to send a command
to the user's preferred shell rather that the boot shell (Note that
the default user shell is the boot shell).  If an application opens a
shell for the user or executes the user's command-lines, it should
tell System() to use the user shell.  If an application requires
consistent shell behavior, it must not use the user shell because the
user can change the user shell.  Another shell tag, SYS_CustomShell,
allows an application to choose other shells besides the boot and user
shells.  This tag's data field should contain the custom shell's name
as it appears in the system resident list.

Although it does offer many features, System() does have some
limitations.  First, because command paths currently only exist in the
CLI structure, Workbench (non-CLI) processes have no paths.
Consequently, when a Workbench process calls a program using System(),
the shell has no path to search for that program (aside from the
system default search path of C: and the current directory).  A second
limitation of the System() function involves CTRL-C/D/E/F handling.
When a task opens a CON: window to provide a handle for a
System()-launched command, that task is the owner of the handle.  This
has two effects.  A System()-launched command running in that CON:
window will only be able to receive CTRL-C/D/E/F signals while it is
doing input or output to the window (i.e. when it has a pending read
or write).  If the task that owns the handle is still around, it
receives CTRL-C/D/E/F signals whenever those keys are pressed in the
CON: window.


The 2.0 Con-handler

The 2.0 con-handler (CON:) has many new enhancements that allow
programs to further customize their console windows. An application
requests these new features by appending keywords to the end of the
CON: specification string for Open().  These keywords may appear in
any order after the title string in the CON: specification.

These new keywords are:

    AUTO            Don't open CON: window until/unless input or
                        output occurs
    CLOSE           Put a close gadget on the CON: window
    WAIT            Hold off Close until user clicks Close or types CTRL-\
    WINDOW  0xaddr  Use specified window (may be on a custom screen)
    SCREEN  name    Open on specified public screen

The additional CON: keywords BACKDROP, NODRAG, NOBORDER, NOSIZE,
SIMPLE, and SMART, allow control of other attributes of a CON: window.

An AUTO/CLOSE/WAIT CON: window is perfect for 2.0-specific C startup
code and for asynchronous System() startup of arbitrary commands.
Because of the ``auto con'' feature (AUTO), the system will never open
the CON: window of a program that doesn't do any stdio (example:
Calculator).  If a command does stdio input or output, the window will
not open until stdio occurs. If the window opens, the wait feature
(WAIT) causes the window to stay open until the user types CTRL-\ (end
of file) or clicks the Close gadget.  The CLOSE keyword tells the
con-handler to put a close gadget on the CON: window.

Example: ``CON:/0/0/640/200/My Title/AUTO/CLOSE/WAIT''

The SCREEN keyword along with a public screen name allows an
application to open a CON: window on that public screen.  Alternately,
an application can use the WINDOW keyword to attach a console to an
already open Intuition window.  The hex address of the Intuition
window must follow the WINDOW keyword.  This makes it possible for
System()-launched programs to do their stdio in a window on a custom
screen.

The example code, SystemTest.c, provides two simple subroutines for
executing external commands, and demonstrates the following 2.0
features:

   o Synchronous System() command execution using the calling
       program's Input()/Output().
   o Synchronous System() command execution in a custom screen window.
   o Asynchronous System() command startup with an AUTO/CLOSE/WAIT window.
   o OpenScreenTags and OpenWindowTags for a 2.0 New Look window.


II-5: AmigaDOS Packet Interface Specification

AmigaDOS Packet Interface Specification

by John Toebes

AmigaDOS communicates with file systems and other DOS handlers by
sending and receiving packets.  Opening and closing file handles
(including console file handles), creating directories, and renaming
disks all require DOS to tell a handler to perform these actions
through sending a packet.  The particular action a handler performs
depends on the type of packet it receives.

This article documents the standard AmigaDOS packet types.  For
information on how to use packets to communicate with handlers see
the AmigaDOS Manual.

Packets sent to a file system or handler can be divided into several
basic categories:

    o   Basic Input/Output

These actions deal with tranferring data to and from objects
controlled by the handler.

    o   File/Directory Manipulation/Information

These actions are used to gain access to and manipulate the high
level structures of the file system.

    o   Volume Manipulation/Information

These actions allow access to the specific volume controlled by the
file system.

    o   Handler Maintenance and Control

These allow control over the handler/file system itself, independent
of the actual volume or structure underneath.

    o   Handler Internal

These actions are never sent to the handler directly.  Instead they
are generally responses to IO requests made by the handler.  The
handler makes these responses look like packets in order to simplify
processing.

    o   Obsolete Packets

These packets are no longer valid for use by handlers and file
systems.

    o   Console Only Packets

These packets are specific to console handlers.  File Systems can
ignore these packets.

Much of this information can be extracted from Developer Conference
notes, The AmigaDOS Manual, and various Fred Fish disks.  However,
because there is no single complete reference to these packet types,
a consolidated view of all the packets is presented here.  Several
structures are referenced here which can be found by looking at the
include files <dos/dos.h> and <dos/dosextens.h>.  (If you are using
the 1.3 version of the include files, these are in the libraries
directory instead of the dos directory).  Before attempting to work
with a file handler you should first become familiar with these files.

Each packet type documented in this article is listed with its action
name, its corresponding number, any AmigaDOS routines which uses this
packet, and the list of  parameters that the packets uses.  The C
variable types for the packet parameters are one of the following
types:

BPTR    This is BCPL pointer (the address of the given object shifted
        right by 2).  Note: this means that the object must be
        aligned on a longword boundary.

LOCK    This is a BPTR to a FileLock structure returned by a previous
        ACTION_LOCATE_OBJECT.  A lock of 0 is legal, indicating the
        root of the volume for the handler.

BSTR    This is a BPTR to a string where the first byte indicates the
        number of characters in the string.  This length byte is
        unsigned but because it is stored in a byte, the strings are
        limited to 255 characters in length.

BOOL    A 32-bit boolean value either containing DOSTRUE (-1) or
        DOSFALSE (0).  Note: equality comparisons with DOSTRUE should
        be avoided.

CODE    A 32 bit error code as defined in the dos/dos.h include file.
        Handlers should not return error codes besides those defined
        in dos/dos.h.

ARG1    The FileHandle->fh_Arg1 field.

LONG    A 32 bit integer value.

Summary of Defined Packet Numbers

This is a listing of all the DOS packets defined by Commodore.
Packets 0-1999 are reserved for use by Commodore.  Unless otherwise
noted, packets 2050-2999 are reserved for use by third party
developers (see chart below).  The remaining packets are reserved for
future expansion (Note: packets 2008, 2009, 4097, and 4098 are in use
by Commodore).

        Decimal Hex     Action #define

        0       0x0000  ACTION_NIL
        1               <Reserved by Commodore>
        2       0x0002  ACTION_GET_BLOCK
        3               <Reserved by Commodore>
        4       0x0004  ACTION_SET_MAP
        5       0x0005  ACTION_DIE
        6       0x0006  ACTION_EVENT
        7       0x0007  ACTION_CURRENT_VOLUME
        8       0x0008  ACTION_LOCATE_OBJECT
        9       0x0009  ACTION_RENAME_DISK
        10-14           <Reserved by Commodore>
        15      0x000F  ACTION_FREE_LOCK
        16      0x0010  ACTION_DELETE_OBJECT
        17      0x0011  ACTION_RENAME_OBJECT
        18      0x0012  ACTION_MORE_CACHE
        19      0x0013  ACTION_COPY_DIR
        20      0x0014  ACTION_WAIT_CHAR
        21      0x0015  ACTION_SET_PROTECT
        22      0x0016  ACTION_CREATE_DIR
        23      0x0017  ACTION_EXAMINE_OBJECT
        24      0x0018  ACTION_EXAMINE_NEXT
        25      0x0019  ACTION_DISK_INFO
        26      0x001A  ACTION_INFO
        27      0x001B  ACTION_FLUSH
        28      0x001C  ACTION_SET_COMMENT
        29      0x001D  ACTION_PARENT
        30      0x001E  ACTION_TIMER
        31      0x001F  ACTION_INHIBIT
        32      0x0020  ACTION_DISK_TYPE
        33      0x0021  ACTION_DISK_CHANGE
        34      0x0022  ACTION_SET_DATE
        35-39           <Reserved by Commodore>
        40      0x0028  ACTION_SAME_LOCK
        41-81           <Reserved by Commodore>
        82      0x0052  ACTION_READ
        83-86           <Reserved by Commodore>
        87      0x0057  ACTION_WRITE
        88-993          <Reserved by Commodore>
        994     0x03E2  ACTION_SCREEN_MODE
        995     0x03E3  ACTION_CHANGE_SIGNAL
        996-1000        <Reserved by Commodore>
        1001    0x03E9  ACTION_READ_RETURN
        1002    0x03EA  ACTION_WRITE_RETURN
        1003            <Reserved by Commodore>
        1004    0x03EC  ACTION_FINDUPDATE
        1005    0x03ED  ACTION_FINDINPUT
        1006    0x03EE  ACTION_FINDOUTPUT
        1007    0x03EF  ACTION_END
        1008    0x03F0  ACTION_SEEK
        1009-1019       <Reserved by Commodore>
        1020    0x03FC  ACTION_FORMAT
        1021    0x03FD  ACTION_MAKE_LINK
        1022    0x03FE  ACTION_SET_FILE_SIZE
        1023    0x03FF  ACTION_WRITE_PROTECT
        1024    0x0400  ACTION_READ_LINK
        1025            <Reserved by Commodore>
        1026    0x0402  ACTION_FH_FROM_LOCK
        1027    0x0403  ACTION_IS_FILESYSTEM
        1028    0x0404  ACTION_CHANGE_MODE
        1029            <Reserved by Commodore>
        1030    0x0406  ACTION_COPY_DIR_FH
        1031    0x0407  ACTION_PARENT_FH
        1032            <Reserved by Commodore>
        1033    0x0409  ACTION_EXAMINE_ALL
        1034    0x040A  ACTION_EXAMINE_FH
        1035-2007       <Reserved by Commodore>
        2008    0x07D8  ACTION_LOCK_RECORD
        2009    0x07D9  ACTION_FREE_RECORD
        2010-2049       <Reserved by Commodore>
        2050-2999       <Reserved for 3rd Party Handlers>
        4097    0x1001  ACTION_ADD_NOTIFY
        4098    0x1002  ACTION_REMOVE_NOTIFY
        4099-           <Reserved by Commodore for Future Expansion>


Basic Input/Output

The Basic Input/Output actions are supported by both handlers and
file systems.  In this way, the application can get a stream level
access to both devices and files.  One difference that arises between
the two is that a handler will not necessarily support an ACTION_SEEK
while it is generally expected for a file system to do so.

These actions work based on a FileHandle which is filled in by one of
the three forms of opens:

ACTION_FINDINPUT         1005    Open(..., MODE_OLDFILE)
ACTION_FINDOUTPUT        1006    Open(..., MODE_NEWFILE)
ACTION_FINDUPDATE        1004    Open(..., MODE_READWRITE)
ARG1:   BPTR    FileHandle to fill in
ARG2:   LOCK    Lock on directory that ARG3 is relative to
ARG3:   BSTR    Name of file to be opened (relative to ARG1)

RES1:   BOOL    Success/Failure (DOSTRUE/DOSFALSE)
RES2:   CODE    Failure code if RES1 is DOSFALSE

All three actions use the lock (ARG2) as a base directory location
from which to open the file.  If this lock is NULL, then the file
name (ARG3) is relative to the root of the current volume.  Because
of this, file names are not limited to a single file name but instead
can include a volume name (followed by a colon) and multiple slashes
allowing the file system to fully resolve the name.  This eliminates
the need for AmigaDOS or the application to parse names before
sending them to the file system.  Note that the lock in ARG2 must be
associated with the file system in question.  It is illegal to use a
lock from another file system.

The calling program owns the file handle (ARG1).  The program must
initialize the file handle before trying to open anything  (in the
case of a call to Open(), AmigaDOS allocates the file handle
automatically and then frees it in Close() ).  All fields must be
zero except the fh_Pos and fh_End fields which should be set to -1.
The Open() function fills in the fh_Type field with a pointer to the
MsgPort of the handler process.  Lastly, the handler must initialize
fh_Arg1 with something that allows the handler to uniquely locate the
object being opened (normally a file).  This value is implementation
specific.  This field is passed to the READ/WRITE/SEEK/ END/TRUNCATE
operations and not the file handle itself.

FINDINPUT and FINDUPDATE are similar in that they only succeed if the
file already exists.  FINDINPUT will open with a shared lock while
FINDUPDATE will open it with a shared lock but if the file doesn't
exist, FINDUPDATE will create the file.  FINDOUTPUT will always open
the file (deleting any existing one) with an exclusive lock.

ACTION_READ              'R'     Read(...)
ARG1:   ARG1    fh_Arg1 field of the opened FileHandle
ARG2:   APTR    Buffer to put data into
ARG3:   LONG    Number of bytes to read

RES1:   LONG    Number of bytes read.
       0 indicates EOF.
      -1 indicates ERROR
RES2:   CODE    Failure code if RES1 is -1

This action extracts data from the file  (or input channel) at the
current position.  If fewer bytes remain in the file than requested,
only those bytes remaining will be returned with the number of bytes
stored in RES1.  The handler indicates an error is indicated by
placing a -1 in RES1 and the error code in RES2.  If the read fails,
the current file position remains unchanged.  Note that a handler may
return a smaller number of bytes than requested, even if not at the
end of a file.  This happens with interactive type file handles which
may return one line at a time as the user hits return, for example
the console handler, CON:.

ACTION_WRITE             'W'     Write(...)
ARG1:   ARG1    fh_Arg1 field of the opened file handle
ARG2:   APTR    Buffer to write to the file handle
ARG3:   LONG    Number of bytes to write

RES1:   LONG    Number of bytes written.
RES2:   CODE    Failure code if RES1 not the same as ARG3

This action copies data into the file (or output channel) at the
current position.  The file is automatically extended if the write
passes the end of the file.  The handler indicates failure by
returning a byte count in RES1 that differs from the number of bytes
requested in ARG3.  In the case of a failure, the handler does not
update the current file position (although the file may have been
extended and some data overwritten) so that an application can safely
retry the operation.

ACTION_SEEK              1008    Seek(...)
ARG1:   ARG1    fh_Arg1 field of the opened FileHandle
ARG2:   LONG    New Position
ARG3:   LONG    Mode:   OFFSET_BEGINNING,OFFSET_END, or  OFFSET_CURRENT

RES1:   LONG    Old Position.   -1 indicates an error
RES2:   CODE    Failure code if RES1 = -1

This packet sets the current file position.  The new position (ARG2)
is relative to either the beginning of the file (OFFSET_BEGINNING),
the end of the file (OFFSET_END), or the current file position
(OFFSET_CURRENT), depending on the mode set in ARG3.  Note that ARG2
can be negative.  The handler returns the previous file position in
RES1.  Any attempt to seek past the end of the file will result in an
error and will leave the current file position in an unknown location.

ACTION_END               1007    Close(...)
ARG1:   ARG1    fh_Arg1 field of the opened FileHandle

RES1:   LONG    DOSTRUE

This packet closes an open file handle.  This function generally
returns a DOSTRUE as there is little the application can do to
recover from a file closing failure.  If an error is returned under
2.0, DOS will not deallocate the file handle.  Under 1.3, it does not
check the result.

ACTION_LOCK_RECORD       2008    LockRecord(fh,pos,len,mod,tim)
ARG1:   BPTR    FileHandle to lock record in
ARG2:   LONG    Start position (in bytes) of record in the file
ARG3:   LONG    Length (in bytes) of record to be locked
ARG4:   LONG    Mode
                 0 = Exclusive
                 1 = Immediate Exclusive (timeout is ignored)
                 2 = Shared
                 3 = Immediate Shared (timeout is ignored)
ARG5:   LONG    Timeout period in AmigaDOS ticks (0 is legal)

RES1:   BOOL    Success/Failure (DOSTRUE/DOSFALSE)
RES2:   CODE    Failure code if RES1 is DOSFALSE

This function locks an area of a file in either a sharable
(indicating read-only) or exclusive (indicating read/write) mode.
Several sharable record locks from different file handles can exist
simultaneously on a particular file area but only one file handle can
have exclusive record locks on a particular area at a time.  The
``exclusivity'' of an exclusive file lock only applies to record
locks from other file handles, not to record locks within the file
handle.  One file handle can have any number of overlapping exclusive
record locks.  In the event of overlapping lock ranges, the entire
range must be lockable before the request can succeed.  The timeout
period (ARG5) is the number of AmigaDOS ticks (1/50 second) to wait
for success before failing the operation.

ACTION_FREE_RECORD       2009    UnLockRecord(file,pos,len)
ARG1:   BPTR    FileHandle to unlock record in
ARG2:   LONG    Start position (in bytes) of record in the file
ARG3:   LONG    Length of record (in bytes) to be unlocked

RES1:   BOOL    Success/Failure (DOSTRUE/DOSFALSE)
RES2:   CODE    Failure code if RES1 is DOSFALSE

This function unlocks any previous record lock.  If the given range
does not represent one that is currently locked in the file,
ACTION_FREE_RECORD returns an error.  In the event of multiple locks
on a given area, only one lock is freed.

ACTION_SET_FILE_SIZE     1022    SetFileSize(file,off,mode)
ARG1:   BPTR    FileHandle of opened file to modify
ARG2:   LONG    New end of file location based on mode
ARG3:   LONG    Mode.  One of OFFSET_CURRENT, OFFSET_BEGIN, or OFFSET_END

RES1:   BOOL    Success/Failure (DOSTRUE/DOSFALSE)
RES2:   CODE    Failure code if RES1 is DOSFALSE

This function is used to change the physical size of an opened file.
ARG2, the new end-of-file position, is relative to either the current
file position (OFFSET_CURRENT), the beginning of the file
(OFFSET_BEGIN), or the end of the file (OFFSET_END), depending on the
mode set in ARG3.  The current file position will not change unless
the current file position is past the new end-of-file position.  In
this case, the new file position will move to the new end of the
file.  If there are other open file handles on this file,
ACTION_SET_FILE_SIZE sets the end-of-file for these alternate file
handles to either their respective current file position or to the
new end-of-file position of the file handle in ARG1, whichever makes
the file appear longer.


Directory/File Manipulation/Information

The directory/file actions permits an application to make queries
about and modifications to handler objects. These packets perform
functions such as creating subdirectories, resolving links, and
filling in FileInfoBlock structures for specific files.

ACTION_LOCATE_OBJECT     8       Lock(...)
ARG1:   LOCK    Lock on directory to which ARG2 is relative
ARG2:   BSTR    Name (possibly with a path) of object to lock
ARG3:   LONG    Mode:   ACCESS_READ/SHARED_LOCK, ACCESS_WRITE/EXCLUSIVE_LOCK

RES1:   LOCK    Lock on requested object or 0 to indicate failure
RES2:   CODE    Failure code if RES1 = 0

The AmigaDOS function Lock() uses this action to create its locks.
Given a name for the object, which may include a path, (ARG2)  and a
lock on a directory from which to look for the name (and path),
ACTION_LOCATE_OBJECT will locate the object within the file system
and create a FileLock structure associated with the object.  If  the
directory lock in ARG1 is NULL, the name is relative to the root of
the file handler's volume (a.k.a. ``:'').  The memory for the
FileLock structure returned in RES1 is maintained by the handler and
freed by an ACTION_FREE_LOCK.  Although it's not a requirement, if an
handler expects to support the pre-1.3 Format command, it must accept
any illegal mode as ACCESS_READ.

A handler can create an exclusive lock only if there are no other
outstanding locks on the given object. Once created, an exclusive
lock prevents any other locks from being created for that object.  In
general, a handler uses the FileLock->fl_Key field to uniquely
identify an object.  Note that some applications rely on this
(although a handler is not required to implement this packet).

The fl_Volume field of the returned FileLock structure should point
to the DOS device list's volume entry for the volume on which the
lock exists.  In addition, there are several diagnostic programs that
expect all locks for a volume to be chained together off the
dl_LockList field in the volume entry.  Note that relying on this
chaining is not safe, and can cause serious problems including a
system crash.  No application should use it.

ACTION_COPY_DIR          19      DupLock(...)
ARG1:   LOCK    Lock to duplicate

RES1:   LOCK    Duplicated Lock or 0 to indicate failure
RES2:   CODE    Failure code if RES1 = 0

This action's name is misleading as it does not manipulate
directories.  Instead, it creates a copy of a shared lock.  The copy
is subsequently freed with an ACTION_FREE_LOCK.  Note that it is
valid to pass a NULL lock.  Currently, the DupLock() call always
returns 0 if passed a 0, although a handler is not required to return
a 0.

ACTION_FREE_LOCK         15      UnLock(...)
ARG1:   LOCK    Lock to free

RES1:   BOOL    TRUE

This action frees the lock passed to it.  The AmigaDOS function
Unlock() uses this packet.  If passed a NULL lock, the handler should
return success.

ACTION_EXAMINE_OBJECT    23      Examine(...)
ARG1:   LOCK    Lock of object to examine
ARG2:   BPTR    FileInfoBlock to fill in

RES1:   BOOL    Success/failure (DOSTRUE/DOSFALSE)
RES2:   CODE    Failure code if RES1 = DOSFALSE

This action fills in the FileInfoBlock with information about the
locked object.  The Examine() function uses this packet.  This packet
is actually used for two different types of operations.  It is called
to obtain information about a given object while in other cases, it
is called to prepare for a sequence of EXAMINE_NEXT operations in
order to traverse a directory.

This seemingly simple operation is not without its quirks.  One in
particular is the FileInfoBlock->fib_Comment field.  This field used
to be 116 bytes long, but was changed to 80 bytes in release 1.2.
The extra 36 bytes lie in the fib_Reserved field.  Another quirk of
this packet is that both the fib_EntryType and the fib_DirEntryType
fields must be set to the same value, as some programs look at one
field while other programs look at the other.

File systems should use the same values for fib_DirEntryType as the
ROM file system and ram-handler do.  These are as follows:

ST_ROOT          1
ST_USERDIR       2
ST_SOFTLINK      3 NOTE: this Shows up as a directory unless checked for explicitly
ST_LINKDIR       4
ST_FILE         -3
ST_LINKFILE     -4

Also note that for directories, handlers must use numbers greater
than 0, since some programs test to see if fib_DirEntryType is
greater than zero, ignoring the case where fib_DirEntryType equals 0.
Handlers should avoid using 0 because it is not interpreted
consistently.

ACTION_EXAMINE_NEXT      24      ExNext(...)
ARG1:   LOCK    Lock on directory being examined
ARG2:   BPTR    BPTR FileInfoBlock

RES1:   BOOL    Success/failure (DOSTRUE/DOSFALSE)
RES2:   CODE    Failure code if RES1 = DOSFALSE

The ExNext() function uses this packet to obtain information on all
the objects in a directory.   ACTION_EXAMINE fills in a FileInfoBlock
structure describing the first file or directory stored in the
directory referred to in the lock in ARG1.  ACTION_EXAMINE_NEXT is
used to find out about the rest of the files and directories stored
in the ARG1 directory.  ARG2 contains a pointer to a valid
FileInfoBlock field that was filled in by either an ACTION_EXAMINE or
a previous ACTION_EXAMINE_NEXT call.  It uses this structure to find
the next entry in the directory.  This packets writes over the old
FileInfoBlock with information on the next file or directory in the
ARG2 directory.  ACTION_EXAMINE_NEXT returns a failure code of
ERROR_NO_MORE_ENTRIES when there are no more files or directories
left to be examined.  Unfortunately, like ACTION_EXAMINE, this packet
has its own peculiarities.  Among the quirks that ACTION_EXAMINE_NEXT
must account for are:

· The situation where an application calls ACTION_EXAMINE_NEXT one or
more times and then stops invoking it before encountering the end of
the directory.

· The situation where a FileInfoBlock passed to ACTION_EXAMINE_NEXT
is not the same as the one passed to ACTION_EXAMINE or even the
previous EXAMINE_NEXT operation.  Instead, it is a copy of the
FileInfoBlock with only the fib_DiskKey and the first 30 bytes of the
fib_FileName fields copied over.  This is now considered to be
illegal and will not work in the future.  Any new code should not be
written in this manner.

· Because a handler can receive other packet types between
ACTION_EXAMINE_NEXT operations, the ACTION_EXAMINE_NEXT function must
handle any special cases that may result.

· The LOCK passed to ACTION_EXAMINE_NEXT is not always the same lock
used in previous operations.  It is however a lock on the same object.

Because of these problems, ACTION_EXAMINE_NEXT is probably the
trickiest action to write in any handler.  Failure to handle any of
the above cases can be quite disastrous.

ACTION_CREATE_DIR        22      CreateDir(...)
ARG1:   LOCK    Lock to which ARG2 is relative
ARG2:   BSTR    Name of new directory  (relative to ARG1)

RES1:   LOCK    Lock on new directory
RES2:   CODE    Failure code if RES1 = DOSFALSE

ACTION_DELETE_OBJECT     16      DeleteFile(...)
ARG1:   LOCK    Lock to which ARG2 is relative
ARG2:   BSTR    Name of object to delete (relative to ARG1)

RES1:   BOOL    Success/failure (DOSTRUE/DOSFALSE)
RES2:   CODE    Failure code if RES1 = DOSFALSE

ACTION_RENAME_OBJECT     17      Rename(...)
ARG1:   LOCK    Lock to which ARG2 is relative
ARG2:   BSTR    Name of object to rename (relative to ARG1)
ARG3:   LOCK    Lock associated with target directory
ARG4:   BSTR    Requested new name for the object

RES1:   BOOL    Success/failure (DOSTRUE/DOSFALSE)
RES2:   CODE    Failure code if RES1 = DOSFALSE

These three actions perform most of the work behind the AmigaDOS
commands MakeDir, Delete, and Rename  (for single files).  These
packets take as their parameters a lock describing where the file is
and a name relative to that lock.  It is the responsibility of the
file system to ensure that the operation is not going to cause
adverse effects.  In particular, the RENAME_OBJECT action allows
moving files across directory bounds and as such must ensure that it
doesn't create hidden directory loops by renaming a directory into a
child of itself.

For Directory objects, the DELETE_OBJECT action must ensure that the
directory is empty before allowing the operation.

ACTION_PARENT            29      Parent(...)
ARG1:   LOCK    Lock on object to get the parent of

RES1:   LOCK    Parent Lock
RES2:   CODE    Failure code if RES1 = 0

This action receives a lock on an object and creates a shared lock on
the object's parent.  If the original object has no parent, then a
lock of 0 is returned.  Note that this operation is typically used in
the process of constructing the absolute path name of a given object.

ACTION_SET_PROTECT       21      SetProtection(...)
ARG1:   Unused
ARG2:   LOCK    Lock to which ARG3 is relative
ARG3:   BSTR    Name of object (relative to ARG2)
ARG4:   LONG    Mask of new protection bits

RES1:   BOOL    Success/failure (DOSTRUE/DOSFALSE)
RES2:   CODE    Failure code if RES1 = DOSFALSE

This action allows an application to modify the protection bits of an
object.  The 4 lowest order bits (RWED) are a bit peculiar.  If their
respective bit is set, that operation is not allowed (i.e. if a
file's delete bit is set the file is not deleteable).  By default,
files are created with the RWED bits set and all others cleared.
Additionally, any action which modifies a file is required to clear
the A (archive) bit.  See the dos/dos.h include file for the
definitions of the bit fields.

ACTION_SET_COMMENT       28      SetComment(...)
ARG1:   Unused
ARG2:   LOCK    Lock to which ARG3 is relative
ARG3:   BSTR    Name of object (relative to ARG2)
ARG4:   BSTR    New Comment string

RES1:   BOOL    Success/failure (DOSTRUE/DOSFALSE)
RES2:   CODE    Failure code if RES1 = DOSFALSE

This action allows an application to set the comment string of an
object.  If the object does not exist then DOSFALSE will be returned
in RES1 with the failure code in RES2.  The comment string is limited
to 79 characters.

ACTION_SET_DATE          34      SetFileDate(...) in 2.0
ARG1:   Unused
ARG2:   LOCK    Lock to which ARG3 is relative
ARG3:   BSTR    Name of Object (relative to ARG2)
ARG4:   CPTR    DateStamp

RES1:   BOOL    Success/failure (DOSTRUE/DOSFALSE)
RES2:   CODE    Failure code if RES1 = DOSFALSE

This action allows an application to set an object's creation date.

ACTION_FH_FROM_LOCK      1026    OpenFromLock(lock)
ARG1:   BPTR    BPTR to file handle to fill in
ARG2:   LOCK    Lock of file to open

RES1:   BOOL    Success/failure (DOSTRUE/DOSFALSE)
RES2:   CODE    Failure code if RES1 = NULL

This action open a file from a given lock.  If this action is
successful, the file system will essentially steal the lock so a
program should not use it anymore.  If ACTION_FH_FROM_LOCK fails, the
lock is still usable by an application.

ACTION_SAME_LOCK         40      SameLock(lock1,lock2)
ARG1:   BPTR    Lock 1 to compare
ARG2:   BPTR    Lock 2 to compare

RES1:   LONG    Result of comparison, one of
    DOSTRUE           if locks are for the same object
    DOSFALSE          if locks are on different objects
RES2:   CODE    Failure code if RES1 is LOCK_DIFFERENT

This action compares the targets of two locks.  If they point to the
same object, ACTION_SAME_LOCK should return LOCK_SAME.

ACTION_MAKE_LINK         1021    MakeLink(name,targ,mode)
ARG1:   BPTR    Lock on directory ARG2 is relative to
ARG2:   BSTR    Name of the link to be created (relative to ARG1)
ARG3:   BPTR    Lock on target object or name (for soft links).
ARG4:   LONG    Mode of link, either LINK_SOFT or LINK_HARD

RES1:   BOOL    Success/Failure (DOSTRUE/DOSFALSE)
RES2:   CODE    Failure code if RES1 is DOSFALSE

This packet causes the file system to create a link to an already
existing file or directory.  There are two kinds of links, hard links
and soft links.  The basic difference between them is that a file
system resolves a hard link itself, while the file system passes a
string back to DOS telling it where to find a soft linked file or
directory.   To the packet level programmer, there is essentially no
difference between referencing a file by its original name or by its
hard link name.  In the case of a hard link, ARG3 is a lock on the
file or directory that the link is ``linked'' to, while in a soft
link, ARG3 is a pointer (CPTR) to a C-style string.

In an over-simplified model of the ROM file system, when asked to
locate a file, the system scans a disk looking for a file header with
a specific (file) name.  That file header points to the actual file
data somewhere on the disk.  With hard links, more than one file
header can point to the same file data, so data can be referenced by
more than one name.  When the user tries to delete a hard link to a
file, the system first checks to see if there are any other hard
links to the file.  If there are, only the hard link is deleted, the
actual file data the hard link used to reference remains, so the
existing hard links can still use it.  In the case where the original
link (not a hard or soft link) to a file is deleted, the file system
will make one of its hard links the new ``real'' link to the file.
Hard links can exist on directories as well.  Because hard links
``link'' directly to the underlying media, hard links in one file
system cannot reference objects in another file system.

Soft links are resolved through DOS calls.  When the file system
scans a disk for a file or directory name and finds that the name is
a soft link, it returns an error code (ERROR_IS_SOFT_LINK).  If this
happens, the application must ask the file system to tell it what the
link the link refers to by calling ACTION_READ_LINK.  Soft Links are
stored on the media, but instead of pointing directly to data on the
disk, a soft link contains a path to its object.  This path can be
relative to the lock in ARG1, relative to the volume (where the
string will be prepended by a colon ':'), or an absolute path.  An
absolute path contains the name of another volume, so a soft link can
reference files and directories on other disks.

ACTION_READ_LINK         1024  ReadLink(port,lck,nam,buf,len)
ARG1:   BPTR    Lock on directory that ARG2 is relative to
ARG2:   CPTR    Path and name of link (relative to ARG1).
                  NOTE: This is a C string not a BSTR
ARG3:   APTR    Buffer for new path string
ARG4:   LONG    Size of buffer in bytes

RES1:   LONG    Actual length of returned string, -2 if there isn't
                  enough space in buffer,or -1 for other errors
RES2:   CODE    Failure code

This action reads a link and returns a path name to the link's
object.  The link's name (plus any necessary path) is passed as a
CPTR (ARG2) which points to a C-style string, not a BSTR.
ACTION_READ_LINK returns the path name in ARG3.  The length of the
target string is returned in RES1 (or a -1 indicating an error).

ACTION_CHANGE_MODE       1028    ChangeMode(type,obj,mode)
ARG1:   LONG    Type of object to change - either CHANGE_FH
                  or CHANGE_LOCK
ARG2:   BPTR    object to be changed
ARG3:   LONG    New mode for object - see ACTION_FINDINPUT,
                  and ACTION_LOCATE_OBJECT

RES1:   BOOL    Success/Failure (DOSTRUE/DOSFALSE)
RES2:   CODE    Failure code if RES1 is DOSFALSE

This action requests that the handler change the mode of the given
file handle or lock to the mode in ARG3.  This request should fail if
the handler can't change the mode as requested  (for example an
exclusive request for an object that has multiple users).

ACTION_COPY_DIR_FH       1030    DupLockFromFH(fh)
ARG1:   LONG    fh_Arg1 of file handle

RES1:   BPTR    Lock associated with file handle or NULL
RES2:   CODE    Failure code if RES1 = NULL

This action requests that the handler return a lock associated with
the currently opened file handle.  The request may fail for any
restriction imposed by the file system (for example when the file
handle is not opened in a shared mode).  The file handle is still
usable after this call, unlike the lock in ACTION_FH_FROM_LOCK.

ACTION_PARENT_FH         1031    ParentOfFH(fh)
ARG1:   LONG    fh_Arg1 of File handle to get parent of

RES1:   BPTR    Lock on parent of a file handle
RES2:   CODE    Failure code if RES1 = NULL

This action obtains a lock on the parent directory (or root of the
volume if at the top level) for a currently opened file handle.  The
lock is returned as a shared lock and must be freed.  Note that
unlike ACTION_COPY_DIR_FH, the mode of the file handle is
unimportant.   For an open file, ACTION_PARENT_FH should return a
lock under all circumstances.

ACTION_EXAMINE_ALL       1033    ExAll(lock,buff,size,type,ctl)
ARG1:   BPTR    Lock on directory to examine
ARG2:   APTR    Buffer to store results
ARG3:   LONG    Length (in bytes) of buffer (ARG2)
ARG4:   LONG    Type of request - one of the following:
           ED_NAME Return only file names
           ED_TYPE Return above plus file type
           ED_SIZE Return above plus file size
           ED_PROTECTION Return above plus file protection
           ED_DATE Return above plus 3 longwords of date
           ED_COMMENT Return above plus comment or NULL
ARG5:   BPTR    Control structure to store state information.  The control
                  structure must be allocated with AllocDosObject()!

RES1:   LONG    Continuation flag - DOSFALSE indicates termination
RES2:   CODE    Failure code if RES1 is DOSFALSE

This action allows an application to obtain information on multiple
directory entries.  It is particularly useful for applications that
need to obtain information on a large number of files and directories.

This action fills the buffer (ARG2) with partial or whole ExAllData
structures.  The size of the ExAllData structure depends on the type
of request.  If the request type field (ARG4) is set to ED_NAME, only
the ed_Name field is filled in.  Instead of copying the unused fields
of the ExAllData structure into the buffer, ACTION_EXAMINE_ALL
truncates the unused fields.  This effect is cumulative, so requests
to fill in other fields in the ExAllData structure causes all fields
that appear in the structure before the requested field will be
filled in as well.  Like the ED_NAME case mentioned above, any field
that appears after the requested field will be truncated (see the
ExAllData structure below).  For example, if the request field is set
to ED_COMMENT, ACTION_EXAMINE_ALL fills in all the fields of the
ExAllData structure, because the ed_Comment field is last.  This is
the only case where the packet returns entire ExAllData structures.

struct ExAllData {
        struct ExAllData *ed_Next;
        UBYTE  *ed_Name;
        LONG    ed_Type;
        ULONG   ed_Size;
        ULONG   ed_Prot;
        ULONG   ed_Days;
        ULONG   ed_Mins;
        ULONG   ed_Ticks;
        UBYTE  *ed_Comment;     /* strings will be after last used field. Note: */
};                              /* Bug in V37 FFS treats this as a BSTR.        */

Each ExAllData structure entry has an ead_Next field which points to
the next ExAllData structure.  Using these links, a program can
easily chain through the ExAllData structures without having to worry
about how large the structure is.  Do not examine the fields beyond
those requested as they certainly will not be initialized (and will
probably overlay the next entry).

The most important part of this action is the ExAllControl structure.
It must be allocated and freed through
AllocDosObject()/FreeDosObject().  This allows the structure to grow
if necessary with future revisions of the operating and file systems.
Currently, ExAllControl contains four fields:

    Entries - This field is maintained by the file system and
    indicates the actual number of entries present in the
    buffer after the action is complete.  Note that a value of
    zero is possible here as no entries may match the match
    string.

    LastKey - This field must be initialized to 0 by the
    calling application before using this packet for the first
    time.  This field is maintained by the file system as a
    state indicator of the current place in the list of entries
    to be examined.  The file system may test this field to
    determine if this is the first or a subsequent call to this
    action.

    MatchString - This field points to a pattern matching
    string parsed by ParsePattern() or ParsePatternNoCase().
    The string controls which directory entries are returned.
    If this field is NULL, then all entries are returned.
    Otherwise, this string is used to pattern match the names
    of all directory entries before putting them into the
    buffer.  The default AmigaDOS pattern match routine is used
    unless MatchFunc is not NULL (see below).  Note that it is
    not acceptable for the application to change this field
    between subsequent calls to this action for the same
    directory.

    MatchFunc - This field contains a pointer to an alternate
    pattern matching routine to validate entries.  If it is
    NULL then the standard AmigaDOS wild card routines will be
    used.  Otherwise, MatchFunc points to a hook function that
    is called in the following manner:

BOOL = MatchFunc(hookptr, data,typeptr)
                   A0      A1    A2
hookptr    Pointer to hook being called
data       Pointer to (partially) filled in ExAllData for item
             being checked.
typeptr    Pointer to longword indicating the type of the
             ExAll request (ARG4).

This function is expected to return DOSTRUE if the entry is accepted
and DOSFALSE if it is to be discarded.

ACTION_EXAMINE_FH        1034    ExamineFH(fh,fib)
ARG1:   BPTR    File handle on open file
ARG2:   BPTR    FileInfoBlock to fill in

RES1:   BOOL    Success/Failure (DOSTRUE/DOSFALSE)
RES2:   CODE    Failure code if RES1 is DOSFALSE

This function examines a file handle and fills in the FileInfoBlock
(found in ARG2) with information about the current state of the file.
This routine is analogous to the ACTION_EXAMINE_OBJECT action for
locks.  Because it is not always possible to provide an accurate file
size (for example when buffers have not been flushed or two processes
are writing to a file), the fib_Size field (see dos/dos.h) may be
inaccurate.

ACTION_ADD_NOTIFY        4097    StartNotify(NotifyRequest)
ARG1:   BPTR    NotifyRequest structure

RES1:   BOOL    Success/Failure (DOSTRUE/DOSFALSE)
RES2:   CODE    Failure code if RES1 is DOSFALSE

This action asks a file system to notify the calling program if a
particular file is altered.  A file system notifies a program either
by sending a message or by signaling a task.

struct NotifyRequest {
        UBYTE *nr_Name;
        UBYTE *nr_FullName;             /* set by dos - don't touch */
        ULONG nr_UserData;              /* for applications use */
        ULONG nr_Flags;

        union {

            struct {
                struct MsgPort *nr_Port;        /* for SEND_MESSAGE */
            } nr_Msg;

            struct {
                struct Task *nr_Task;           /* for SEND_SIGNAL */
                UBYTE nr_SignalNum;             /* for SEND_SIGNAL */
                UBYTE nr_pad[3];
            } nr_Signal;
        } nr_stuff;

        ULONG nr_Reserved[4];           /* leave 0 for now */

        /* internal use by handlers */
        ULONG nr_MsgCount;              /* # of outstanding msgs */
        struct MsgPort *nr_Handler;     /* handler sent to (for EndNotify) */
};

To use this packet, an application needs to allocate and initialize a
NotifyRequest structure (see above).  As of this writing,
NotifyRequest structures are not allocated by AllocDosObject(), but
this may change in the future.  The handler gets the watched file's
name from the nr_FullName field.  The current file system does not
currently support wild cards in this field, although there is nothing
to prevent other handlers from doing so.

The string in nr_FullName must be an absolute path, including the
name of the root volume (no assigns).  The absolute path is necessary
because the file or its parent directories do not have to exist when
the notification is set up.  This allows notification on files in
directories that do not yet exist.  Notification will not occur until
the directories and file are created.

An application that uses the StartNotify() DOS call does not fill in
the NotifyRequest's nr_FullName field, but instead fills in the
nr_Name field.  StartNotify() takes the name from the nr_Name field
and uses GetDeviceProc() and NameFromLock() to expand any assigns
(such as ENV:), storing the result in nr_FullName.  Any application
utilizing the packet level interface instead of StartNotify() must
expand their own assigns.  Handlers must not count on nr_Name being
correct.

The notification type depends on which bit is set in the
NotifyRequest.nr_Flags field.  If the NRF_SEND_MESSAGE bit is set, an
application receives notification of changes to the file through a
message (see NotifyMessage from dos/notify.h).  In this case, the
nr_Port field must point to the message port that will receive the
notifying message .  If the nr_Flags NRF_SEND_SIGNAL bit is set, the
file system will signal a task instead of sending a message.  In this
case, nr_Task points to the task and nr_SignalNum is the signal
number.  Only one of these two bits should be set!

When an application wants to limit the number of NotifyMessages an
handler can send per NotifyRequest, the application sets the
NRF_WAIT_REPLY bit in the nr_Flags field.  This bit tells the handler
not to send new NotifyMessages to a NotifyRequest's message port if
the application has not returned a previous NotifyMessage.  This
pertains only to a specific NotifyRequest--if other NotifyRequests
exist on the same file (or directory) the handler will still send
NotifyMessages to the other NotifyRequest's message ports.  The
NRF_WAIT_REPLY bit only applies to message notification.

If an application needs to know if a file or directory exists at the
time the application sets up notification on that file or directory,
the application can set the NRF_NOTIFY_INITIAL bit in the nr_Flags
field.  If the file or directory exists, the handler sends an initial
message or gives an initial signal.

Handlers should only perform a notification when the actual contents
of the file have changed.  This includes ACTION_WRITE,
ACTION_SET_DATE, ACTION_DELETE, ACTION_RENAME_OBJECT,
ACTION_FINDUPDATE, ACTION_FINDINPUT, and ACTION_FINDOUTPUT.  It may
also include other actions such as ACTION_SET_COMMENT or
ACTION_SET_PROTECT, but this is not required (and may not be expected
by the application as there is no need to reread the data).

ACTION_REMOVE_NOTIFY     4098    EndNotify(NotifyRequest)
ARG1:   BPTR    Pointer to previously added notify request

RES1:   BOOL    Success/Failure (DOSTRUE/DOSFALSE)
RES2:   CODE    Failure code if RES1 is DOSFALSE

This action cancels a notification (see ACTION_ADD_NOTIFY) .  ARG1 is
the NotifyRequest structure used to initiate the notification.  The
handler should abandon any pending notification messages.  Note that
it is possible for a file system to receive a reply from a previously
sent notification message even after the notification has been
terminated.  It should accept these messages silently and throw them
away.


Volume Manipulation/Information

The Volume Manipulation and Information actions are used to allow
access to the underlying volume currently being manipulated by the
file system.

ACTION_CURRENT_VOLUME    7       <sendpkt only>
RES1:   BPTR    Pointer to volume node of current volume

This action returns a pointer to the volume node (from the DOS device
list) associated with the file system.  As the volume node may be
removed from the device list when the file system mounts a different
volume (such as when directed to by an ACTION_INHIBIT) there is no
guarantee that this pointer will remain valid for any amount of time.
This action is generally used by AmigaDOS to provide the volume line
of a requester.

ACTION_DISK_INFO         25      Info(...)
ARG1:   BPTR    Pointer to an InfoData structure to fill in

RES1:   BOOL    Success/Failure (DOSTRUE/DOSFALSE)

ACTION_INFO              26      <sendpkt only>
ARG1:   LOCK    Lock
ARG2:   BPTR    Pointer to a InfoData Structure to fill in

RES1:   BOOL    Success/Failure (DOSTRUE/DOSFALSE)

These actions are used to get information about the device and status
of the file handler.  ACTION_DISK_INFO is used by the info command to
report the status of the volume currently in the drive.  It fills in
an InfoData structure about the volume the file system currently
controls.  This structure should be longword aligned.  ACTION_INFO
fills in an InfoData structure for  the volume the lock (ARG1) is on
instead of the volume currently in the drive.  These actions are
generally expected to return DOSTRUE.

The ACTION_DISK_INFO packet has a special meaning for console style
handlers.  When presented with this packet, a console style handler
should return a pointer to the window associated with the open handle.

ACTION_RENAME_DISK      9       Relabel(...) in 2.0
ARG1:   BSTR    New disk name

RES1:   BOOL    Success/Failure (DOSTRUE/DOSFALSE)

This action allows an application to change the name of the current
volume.  A file system implementing this function must also change
the name stored in the volume node of the DOS device list.

ACTION_FORMAT            1020    Format(fs,vol,type)
ARG1:   BSTR    Name for volume (if supported)
ARG2:   LONG    Type of format (file system specific)

RES1:   BOOL    Success/Failure (DOSTRUE/DOSFALSE)
RES2:   CODE    Failure code if RES1 is DOSFALSE

This packet tells a file system to perform any device or file system
specific formatting on any newly initialized media.  Upon receiving
this action, a file system can assume that the media has already been
low level formatted and should proceed to write out any high level
disk structure necessary to create an empty volume.


Handler Maintenance and Control

A number of packets are defined to give an application some control
over a file system:

ACTION_DIE               5      <sendpkt only>
RES1:   BOOL    DOSTRUE

As its name implies, the ACTION_DIE packet tells a handler to quit.
All new handlers are expected to implement this packet.  Because of
outstanding locks and the fact that the handler address is returned
by the DeviceProc() routine, it is unlikely that the handler can
disappear completely, but instead will have to release as many
resources as possible and simply return an error on all packets sent
to it.

In the future, the system may be able to determine if there are any
outstanding DeviceProc() references to a handler, and therefore make
it is safe to shut down completely.

ACTION_FLUSH             27     <sendpkt only>
RES1:   BOOL    DOSTRUE

This action causes the file system to flush out all buffers to disk
before returning this packet.  If any writes are pending, they must
be processed before responding to this packet.  This packet allows an
application to make sure that the data that is supposed to be on the
disk is actually written to the disk instead of waiting in a buffer.

ACTION_MORE_CACHE        18      AddBuffers(...) in 2.0
ARG1:   LONG    Number of buffers to add

RES1:   BOOL    DOSTRUE (-1L)
RES2:   LONG    New total number of buffers

This action allows an application to change the number of internal
buffers used by the file system for caching.  Note that a positive
number increases the number of buffers while a negative number
decreases the number of buffers.  In all cases, the number of current
buffers should be returned in RES2.  This allows an application to
inquire the number of buffers by sending in a value of 0 (resulting
in no change).  Note that the OFS and FFS in 1.3 do not accept a
negative number of buffers.

Note that there is a bug in the ROM file system in both Release 2.04
and Release 3.0 that jumbles its return values for this packet.  The
file system erroneously returns the new number of buffers in RES1
instead of RES2 (it returns a failure code in RES2).  To work around
this bug when using this packet, test RES1 to see if it is DOSTRUE
(-1L).  If it is, look at RES2 for the number of buffers, otherwise
RES1 should contain the new total number of buffers.

ACTION_INHIBIT           31     Inhibit(...) in 2.0
ARG1:   BOOL    DOSTRUE = inhibit,      DOSFALSE = uninhibit

RES1:   BOOL    Success/failure (DOSTRUE/DOSFALSE)

This action is probably one of the most dangerous that a file system
has to handle.  When inhibited (ARG1 = DOSTRUE), the file system must
not access any underlying media and return an error code on all
attempts to access the device.  Once uninhibited (ARG1 = DOSFALSE),
the file system must assume that the medium has been changed.  The
file system must flush the buffers before the ACTION_INHIBIT ,
popping up a requester demanding that the user put back the current
disk, if necessary.  The handler may choose to reject an inhibit
request if any objects are open for writing.

Although it's not required, a handler should nest inhibits.  Prior to
2.0, the system handlers did not keep a nesting count and were
subject to some obscure race conditions.  The 2.0 ROM filing system
introduced a nesting count.

ACTION_WRITE_PROTECT     1023    <sendpkt only>
ARG1:   BOOL    DOSTRUE/DOSFALSE (write protect/un-write protect)
ARG2:   LONG    32 Bit pass key

RES1:   BOOL    DOSTRUE/DOSFALSE

This is a new packet defined for the Fast File System.  This packet
allows an application to change the write protect flag of a disk (if
possible - applications cannot write to floppies that have their
write-protect tabs set).  This packet is primarily intended to allow
write-protecting non-removable media such as hard disks.  The value
in ARG1 toggles the write status.  The 32-bit passkey allows a
program to prevent other programs from unwrite-protecting a disk.  To
unlock a disk, ARG2 must match the passkey of the packet that locked
the disk, unless the disk was locked with a passkey of 0.  In this
case, no passkey is necessary to unlock the disk.

ACTION_IS_FILESYSTEM     1027    IsFileSystem(devname)

RES1:   BOOL    Success/Failure (DOSTRUE/DOSFALSE)
RES2:   CODE    Failure code if RES1 is DOSFALSE

Through this function, a handler can indicates whether or not it is a
file system (whether or not it can  support separate files for
storing information).  Programs will assume a handler can create
multiple, distinct files through calls to Open() if the handler
returns this packet with a DOSTRUE value.  A handler does not need to
support directories and subdirectories in order to qualify as a file
system.  It does have to support the Examine()/ExNext() calls.

Note that the AmigaDOS routine IsFileSystem() will attempt to use
Lock(":",SHARED_ACCESS) if this packet returns ERROR_ACTION_NOT_KNOWN.


Handler Internal

There are several actions that are generally used by handlers to
allow messages returning from requested services (typically an Exec
device) to look like incoming request packets.  This allows the
handler to request an asynchronous operation but be notified of the
completion.  For example, a handler sends the serial.device a request
for a read, but instead of sending a plain IO request, it sends a DOS
packet disguised as an IO request.  The serial.device treats the
packet like a normal IO request, returning it to the handler when it
is finished. When the handler gets back its disguised DOS packet, it
knows that the read has completed.

ACTION_NIL               0       <internal>

Although not specifically an action, many returns look like this
value because the action field has not been filled in.

ACTION_READ_RETURN       1001    <internal>

Generally used to indicate the completion of an asynchronous read
request.

ACTION_WRITE_RETURN      1002    <internal>

Generally used to indicate the completion of an asynchronous write
request.

ACTION_TIMER             30     <internal>

Used to indicate the passage of a time interval.  Many handlers have
a steady stream of ACTION_TIMER packets so that they can schedule
house keeping and flush buffers when no activity has occurred for a
given time interval.


Obsolete Packets

There are several packet types that are documented within the system
include files that are obsolete.  A file system is not expected to
handle these packets and any program which sends these packets can
not expect them to work:

ACTION_DISK_CHANGE      33      <Obsolete>

ACTION_DISK_TYPE        32      <Obsolete>

ACTION_EVENT             6      <Obsolete>

ACTION_GET_BLOCK         2      <Obsolete>

ACTION_SET_MAP           4      <Obsolete>

Of particular note here is ACTION_DISK_CHANGE.  The DiskChange
command uses the ACTION_INHIBIT packet to accomplish its task.


Console Only Packets

The remaining packets are only used for console handlers and do not
need to be implemented by a file system.

ACTION_SCREEN_MODE       994    SetMode() in 2.0
ARG1:   LONG    Mode (zero or one)

RES1:   BOOL    Success/Failure (DOSTRUE/DOSFALSE)
RES2:   CODE    Failure code if RES1 is DOSFALSE

Switch the console to and from RAW mode.  An ARG1 of one indicates
the unprocessed, raw mode while an ARG1 of zero indicates the
processed, ``cooked'' mode.

ACTION_CHANGE_SIGNAL     995    <sendpkt only>
ARG1:   LONG    The fh_Arg1 of the console file handle
ARG2:   APTR    MsgPort of the process to signal
ARG3:   LONG    Reserved, currently this must be zero

RES1:   BOOL    Success/Failure (DOSTRUE/DOSFALSE)
RES2:   CODE    Failure code if RES1 is DOSFALSE

This packet redirects what process the console handler signals when
the user hits  Control-C, Control-D, Control-E, or Control-F.
Normally the process that opened the file handle receives the break
signal.

ACTION_WAIT_CHAR         20     WaitForChar()
ARG1:   ULONG   Timeout in microseconds

RES1:   BOOL    Success/Failure (DOSTRUE/DOSFALSE)
RES2:   CODE    Failure code if RES1 is DOSFALSE

Performs a timed read of a character.  The WaitForChar() function
uses this packet.

ACTION_DISK_INFO         25      <sendpkt only>
ARG1:   BPTR    Pointer to an InfoData structure to fill in

RES1:   BOOL    Success/Failure (DOSTRUE/DOSFALSE)

The ACTION_DISK_INFO packet has a special meaning for console style
handlers.  When presented with this packet, a console style handler
should return a pointer to the window associated with the open handle
in the InfoData structure's id_VolumeNode field (the InfoData
structure is defined in <dos/dos.h>).  Note that some consoles can
return a NULL Window pointer (for example, an AUTO CON: or a AUX:
console).  The Amiga's standard console handler, CON:, also returns a
pointer to the console handler's IO request in the id_InUse field.
In some cases, the IO request's io_Unit field (which normally point
to a ConUnit structure) will be NULL.  See also the ACTION_DISK_INFO
packet in the ``Volume Manipulation/Information'' section.


II-27: Standard Command Line Parsing

by John Orr

One of the new features in release 2.0 is system standard command line
parsing.  Its presence has two benefits: it standardizes the way in which
the user supplies command line arguments, making it much easier on the
user, and it also removes some tedious programming (and code size) from
every application that uses it.

The dos.library's ReadArgs() routine is the heart of this feature:

   struct RDArgs *rda = ReadArgs( UBYTE *argtemplate, LONG *argarray,
                                     struct RDArgs *myrda );

This function stores each argument supplied on the command line in its
corresponding entry in the array of LONG words, argarray.  The format in
which ReadArgs() stores each argument is based on the description of the
command line supplied in the first argument, argtemplate.  This
description is a C-style string containing a name for each argument.

Each argument name in the template should be a full, descriptive name (for
example ``Quick'' not ``Q'').  Each option can be prepended by an
abbreviation of the form ``abbrev='' (for example ``Q=Quick'').  The
argtemplate options must be delimited by commas.  Avoid using the names of
common commands as keywords, otherwise the user will have to delimit them
with quotes.

The ordinal position that an argument appears in the description string
determines what its corresponding position in argarray is (the first
argument corresponds to the first entry in argarray, the second argument
corresponds to the second entry in argarray, ...).  There must be an entry
in argarray for each argument in the description string so that ReadArgs()
has a place to store each argument's value.

Each argument name in the template can be followed by modifiers that tell
ReadArgs() the format of the argument.  The valid modifiers are:

/S - Switch.  This is considered a boolean variable.  If this option is
    present, ReadArgs() will set the corresponding array entry in
    argarray (an array of LONGs) to something besides zero. If the option
    is not present, ReadArgs() will set the entry to 0.

/K - Keyword.  This means that ReadArgs() will not fill in the
    corresponding entry in argarray unless the keyword appears with the
    parameter.  For example, if the template is ``Name/K'', then unless
    ``Name=<string>'' or ``Name <string>'' appears in the command line,
    the ``Name'' entry in argarray will not be altered by ReadArgs(). /N
    - Number. This means the parameter is considered a decimal integer,
    and ReadArgs() will convert it to a LONG.  If the argument is not
    valid, ReadArgs() will fail.  If the option is present in the command
    line (and it is valid), ReadArgs() will fill in the corresponding
    entry with a pointer to the LONG.

/T - Toggle.  This is similar to the switch (/S) modifier, but causes the
    corresponding boolean (in argarray) to toggle.   For example,  if the
    array entry corresponding to an argtemplate of ``binary/T'' is set to
    something besides FALSE and the word ``binary'' appears by itself on
    the command line, ReadArgs() will toggle that array entry to FALSE.

/A - Always.  This modifier tells ReadArgs() that this option is required.
    ReadArgs() will fail if the keyword does not appear in the command
    line.

/F - Final (rest of line).  If this is specified, the part of the command
    line that follows this option is taken as the parameter for this
    option, even if other option keywords appear in it.

/M - Multiple arguments.  This means the argument will take any number of
    strings (or integers as this modifier can be used with the /N
    modifier), returning them as an array of strings.  Any arguments not
    considered to be part of another option will be added to this option.
    Only one /M should appear in a template.  Example: for a template
    ``Dir/M,All/S'' the command-line ``foo bar all qwe'' will set the
    boolean ``all'', and return an array consisting of ``foo'', ``bar'',
    and ``qwe''.  The entry in the array will be a pointer to an array of
    string pointers, the last of which will be NULL.

There is an intentional interaction between /M parameters and /A
parameters.  If there are unfilled /A parameters after parsing, ReadArgs()
will grab strings from the end of a previous /M parameter list to fill the
/A's.  This is used for things like Copy (``From/A/M,To/A'').

If the user does not supply a non-required argument (one without the
``/A'' modifier) on the command line, ReadArgs() will leave the argument's
argarray entry alone.  Before calling ReadArgs(), a program should either
set the argarray entries to reasonable default values or clear them, so
the application can't be confused by any garbage values left in the array.

If it is successful, ReadArgs() returns a pointer to a RDArgs structure
(from <dos/rdargs.h>).  ReadArgs() uses this structure internally to
control its operation.  It is possible to pass ReadArgs() a custom RDArgs
structure (myrda in the ReadArgs() prototype above).  For most
applications myrda will be NULL, as most applications do not need to
control ReadArgs().

    struct RDArgs {
        struct    CSource RDA_Source; /* Select input source */
        LONG      RDA_DAList;         /* PRIVATE. */
        UBYTE     *RDA_Buffer;        /* Optional string parsing space. */
        LONG      RDA_BufSiz;         /* Size of RDA_Buffer (0..n) */
        UBYTE     *RDA_ExtHelp;       /* Optional extended help */
        LONG      RDA_Flags;          /* Flags for any required control */
    };

Any successful call to ReadArgs() (even those that use a custom RDArgs
structure) must be complemented with a call to FreeArgs() to free the
resources that ReadArgs() allocates:

    void FreeArgs(struct RDArgs *rda);

where rda is the RDArgs structure used by ReadArgs().

An application can use a custom RDArgs structure to provide an alternate
command line source, an alternate temporary storage buffer, or an extended
help string.  The custom RDArgs structure must be allocated with
AllocDosObject() and deallocated with FreeDosObject().  See the Autodocs
for more details on these functions.

The RDArgs.RDA_Source field is used to supply ReadArgs() with an alternate
command line to parse.  If this field is non-NULL, ReadArgs() will use it
as a pointer to a CSource structure describing the alternate command line.
The CSource structure (from <dos/rdargs.h>) is as follows:

    struct CSource {
        UBYTE   *CS_Buffer;
        LONG    CS_Length;
        LONG    CS_CurChr;
    };

Where CS_Buffer is the command line to parse, CS_Length is the length of
CS_Buffer, and CS_CurChr is the position in CS_Buffer from which
ReadArgs() should begin its parsing.  Normally CS_CurChr is initialized to
zero.

ReadArgs() uses the RDArgs structure's RDA_DAList field for internal use.
This field must be set to NULL before ReadArgs() uses this structure.

The RDA_Buffer and RDA_BufSiz fields allow an application to supply a
fixed-size buffer in which to store parsed data.  This allows the
application to pre-allocate a buffer rather than requiring ReadArgs() to
allocate buffer space.  If either RDA_Buffer or RDA_BufSiz is NULL,
ReadArgs() assumes the application has not supplied a buffer.

RDA_ExtHelp is a text string which ReadArgs() displays if the user asks
for additional help.  The user asks for additional help by typing a
question mark when ReadArgs() prompts the user for input (which normally
happens only after he or she types a question mark as the only argument on
the command line).

RDA_Flags is a bit field used to toggle certain options of ReadArgs().
Currently, only one option is implemented, RDAF_NOPROMPT.   When set,
RDAF_NOPROMPT prevents ReadArgs() from prompting the user.

The following code, ReadArgs.c, uses a custom RDArgs structure to pass a
command line to ReadArgs.


II-31: Notification

by Ewout Walraven

File Notification is a form of interprocess communication available under
Release 2.0.  An application can ask a file system (like the RAM disk
handler RAM:, df0:, df1:...) that supports notification to inform it
whenever changes are made to a specific file or directory, making it easy
for the application to react to such changes.  The V37 ROM file system and
the V37 and V36 RAM disk handler support file notification.

Under Release 2.0, the preferences control program, IPrefs, sets up
notification on most of the preferences files in ENV:sys.  If the user
alters any of these files (which he/she normally does with a preferences
editor), the system will notify IPrefs about the change. IPrefs will react
to this notification by attempting to alter the user's environment to
reflect the preference change.  For example, if the user opens the
ScreenMode preferences editor and alters the Workbench environment so that
the Workbench screen should be a Hires NTSC screen, ScreenMode writes a
file called Screenmode.prefs to the ENV:sys directory which happens to be
in RAM:. Because IPrefs has set up notification on this file, the RAM disk
file system will notify IPrefs of the change, IPrefs will read in the
Screenmode.prefs file and will try to reset the Workbench screen so it is
in Hires NTSC mode.

Notification allows very different applications to share common data files
without knowing anything about each other.  This has many possible uses in
the Amiga's single user, multitasking environment.  One possible use for
notification is in a desktop publishing (DTP) package.  The user can open
the DTP package to layout a group of ILBMs, some structured drawings, and
word processed text.  When the user loads each of these, the DTP package
sets up notification on each of their corresponding files.  If the user
loads an appropriate editor and changes any of the files on which the DTP
package has set up notification, the DTP package will receive notification
of these changes and can automatically re-import these files into the
current DTP document without the user having to intervene.  Another
possible use for notification might be in a make utility.  A make program
for a compiler could set up notification on a set of source code and
object files.  If any of those files change, the make program will
recompile and link the program, without the programmer having to intervene.

Setting up file notification on a file is easy.  The StartNotify()
function from dos.library starts notification on a file or directory:

    BOOL StartNotify( struct NotifyRequest *notify );

StartNotify() returns DOSTRUE if the call is successful, or it returns
DOSFALSE (for example, when the file's file system does not support
notification).  This function takes a pointer to an initialized
NotifyRequest structure as its only argument (as defined in
<dos/notify.h>):

struct NotifyRequest {
   UBYTE *nr_Name;  /* File/directory name which you want notification */
   UBYTE *nr_FullName; /* Used by DOS. Do not use */
   ULONG nr_UserData;  /* For applications use */
   ULONG nr_Flags;  /* Flags indicating Signal or Message notification */

   union {
      /* Used for Message notification */
      struct {
         struct MsgPort *nr_Port; /* Message port to receive messages on */
     } nr_Msg;
     /* Used for Signal notification */
     struct {
        struct Task *nr_Task;       /* The task to signal */
        UBYTE nr_SignalNum;         /* The signal number to use. */
        UBYTE nr_pad[3];
     } nr_Signal;
   } nr_stuff;

   ULONG nr_Reserved[4];          /* leave 0 for now */

   /* Used internally by handlers */
   ULONG nr_MsgCount;             /* number of outstanding messages */
   struct MsgPort *nr_Handler;    /* handler to send to (for EndNotify) */
};

This structure must not be altered by the application while notification
is in effect!

The nr_Name field contains a pointer to the name of the file on which to
set up notification.  Currently, nr_Name has to be a file name and path
containing a logical device name (for example df0:, work:, fonts:).  The
nr_FullName field is for the private use of the file system.  Any other
use of it is strictly prohibited.  The nr_UserData field is available for
an applications private use.

The nr_Flags field tells the file system which type of notification to set
up, message or signal.  When the file system uses message notification, it
notifies an application by sending an Exec message.  An application asks a
file handler to notify it via an Exec message by setting the
NRF_SEND_MESSAGE flag in nr_Flags.  When the file system uses signal
notification, it sets an Exec signal to notify an application.  An
application receives notification via a signal by setting the
NRF_SEND_SIGNAL flag.

The nr_Flags field has two other flags, NRF_WAIT_REPLY and
NRF_NOTIFY_INITIAL. The NRF_WAIT_REPLY tells the file handler not to send
notification messages about a specific file/directory to an application if
the application has not replied to a previous notification message about
that specific file.  This flag only applies to message notification.  The
NRF_NOTIFY_INITIAL flag tells the file handler to notify the application
if the file exists when it sets up notification on the file.  The flags
for the nr_Flags field are defined in <dos/notify.h>.

The layout of the rest of the NotifyRequest structure depends on the type
of notification.  If the application is using message notification, it
must supply the handler with a message port to send the notification
messages. The NotifyRequest.nr_stuff.nr_Msg.nr_Port field contain the
pointer to the message port that will receive the message notifications.
If the application is using a signal for notification, it must supply a
pointer to the task to signal and the number (not bit!) of the signal.  In
this case, the NotifyRequest.nr_stuff.nr_Signal.nr_Task field should
contain the appropriate task pointer and  the
NotifyRequest.nr_stuff.nr_Signal.nr_SignalNum field should contain the
signal number.

When a file handler uses message notification, it will send a
NotifyMessage:

struct NotifyMessage {
   struct Message nm_ExecMessage;
   ULONG  nm_Class;               /* Class, will be NOTIFY_CLASS */
   UWORD  nm_Code;                /* Code, will be NOTIFY_CODE */
   struct NotifyRequest *nm_NReq; /* Point to NotifyRequest you supplied */
   ULONG  nm_DoNotTouch;          /* private */
   ULONG  nm_DoNotTouch2;         /* private */
};

Message notification is especially useful if you are monitoring more than
one file.  It quickly enables you to find out which file/directory caused
this message by either comparing the NotifyRequest structure returned in
nm_NReq with the one you sent in the StartNotify() function, or by reading
the NotifyRequest's nr_UserData field.  Because the NotifyMessage's
nm_Class and nm_Code fields contain values that distinguish it from other
types of messages, you can use an already allocated message port (from a
window for example) to receive notification messages.

To end notification on a file, use the dos.library function EndNotify():

    void EndNotify( struct NotifyRequest *notify );

An application must call this function for each of its successful
StartNotify() calls.  This function takes one parameter, a pointer to the
NotifyRequest structure that the application used to initiate the
notification.  In the case of message notification, EndNotify() will
remove all pending notify messages from your message port.  After calling
this function, it is safe for the application to change or free the
NotifyRequest structure.  The application may also remove the message port
or free the signal bit.

A file handler should send notification when it receives any of the
following packets (from <dos/dosextens.h>) about the notification file or
directory:

        ACTION_RENAME_OBJECT
        ACTION_RENAME_DISK
        ACTION_CREATE_DIR
        ACTION_DELETE_OBJECT

        ACTION_WRITE
        ACTION_FINDUPDATE
        ACTION_FINDOUTPUT
        ACTION_SET_FILE_SIZE

        ACTION_SET_DATE

The first four packets will cause notification immediately.  The second
four packets will cause notification when the notification file is closed.
The last packet, ACTION_SET_DATE, should cause notification immediately,
but due to a bug in the V37 ROM file system, only the RAM disk's file
handler (RAM:) will send notification.

Notice that some of the packets that trigger a notification are sent by a
process when it is trying to create a new file or directory.  A file
system that supports notification should be able to set up notification on
a file or directory that does not currently exist.  A file system should
send notification when it creates that file or directory.

Note however that, although notification on directories is part of the OS
in release 2.0, it does not work correctly.  In the ROM file system,
directory notification only works if that directory exists when
notification is set up. If your application tries to set up notification
on a ROM file system directory before the directory exists, your
application will never receive notification about that directory.  If
notification is set up for a directory in RAM:, you will only be informed
when that directory is created or deleted and when files are created in
that directory, not when files are changed or deleted.

When implementing notification in your application, there are several
things to remember.  Not every file system supports notification, in
particular, most network file systems will not support notification.  For
this reason, no application should require notification to function.

At the end of this article are two examples for file notification.
SignalNotification.c implements signal notification on a single target.
MessageNotification.c shows how to start message notification on multiple
targets.  Note that these examples are not linked with startup code (like
c.o).  Although these examples do set up SysBase and DosBase to gain
access to exec.library and dos.library, the examples do not handle the
startup message (WBenchMsg) that Workbench sends when it launches an
application, so do not run these examples from Workbench.


II-37: Using the AmigaDOS Pattern Matching Functions

by Ewout Walraven

One of the additions made to dos.library for release 2.0 is a series of
functions to do standard pattern matching.  Using a set of standard string
matching tokens, any application can use these functions to test if a
particular string matches a pattern.  The Amiga OS uses these functions
for processing file name strings for its new directory scanning functions.

These functions can be used in every circumstance where you would like to
enable the user to enter a pattern to indicate more than one target
string.  Using these functions not only makes it unnecessary to implement
your own pattern matching routines, but by using the familiar DOS pattern
tokens in your application, it is easier for the user to learn how to use
your application.

 Patterns      Parsing      Matching


Patterns

An AmigaDOS pattern matching string is a combination of alphanumeric
characters and a series of special token characters.  These token
characters are part of the ASCII character set and they denote such things
as string matching wildcards, string repetitions, and string negation.
Pattern matching strings can use parentheses to delimit pattern matching
substrings.

?    The question mark matches any single character.  For example,
     the pattern matching string "A?B" matches any string that is
     three letters long, that starts with an "A" and ends with a
     "B".

#    The number sign matches strings containing zero or more
     repetitions of the expression that immediately follows the # in
     the pattern matching string.  For example, the pattern matching
     string "#A" matches any string that consists of one or more of
     the "A" character.  The pattern matching string "#?" matches
     any non-NULL string.  The # can apply to entire substrings
     delimited by parentheses.  For example, the pattern string
     "#(AB)" matches any string consisting of one or more
     repetitions of the substring "AB" (AB, ABAB, ABABAB...).

%    Matches the NULL string.

|    This is the OR symbol.  This matches strings that contain the
     expressions on either side of the OR sign.  The expressions and
     the OR symbol need to be enclosed in parentheses.  For example,
     the pattern matching string "(A|B)" matches the string "A"
     or the string "B".  The pattern matching string A(B|%|C)
     matches the strings "AB", "A", and "AC".

~    The tilde negates the expression that follows it.  All
     strings that do not match the expression that follows the tilde
     will match the expression with the tilde.  For example, the
     pattern matching string "~(#?.info)" matches any string that
     does not match the string "#?.info" (does not end with the
     substring ".info").

*    The star is provided as an synonym to "#?".  This is an
     option which can be turned on.  Note that the star can not be
     used by itself on all non-FileSystem devices, like a logical
     device name assigned to a directory on a file system.  For
     example:
                Assign A: dh0:tmp
                cd a:
                list *

     will produce an error.  The SetStar.c example at the end of this
     article is a small, stand-alone utility to turn this option on
     and off.

[]   All characters within brackets indicate a character class.  Any
     character in the character class qualifies.  Within a character
     class, a character range can be indicated by specifing the start
     and stop character, separated with a minus sign.  Note that
     character classes are case sensitive.  If character classes are
     to be used in a case insensitive form, they should be translated
     to uppercase.  Here are some example:

       [ACF]#?         matches strings starting with `A', `C', or `F'
       [A-D]#?         matches strings starting with `A', `B', `C', or `D'
       [~ACF]#?        matches strings not starting with `A', `C', or `F'

'    The quote character neutralizes the special meaning of a
     special character.  Here are some examples:

       '#'? matches only the literal string "#?"
       '?(A|B|C|%)'# matches the literal strings "?#", "?A#", "?B#", "?C#"
       " matches '

()   Parentheses group special characters.  The expression within the
     parentheses is a subpattern.


Parsing

When you want to use a string as an AmigaDOS wildcard pattern, the system
must first parse it.  The system builds a token string which the system
uses to match strings.  There are two functions in dos.library to parse
pattern matching strings:

    LONG ParsePattern(UBYTE *SourcePattern, UBYTE *MyDestination,
                        LONG DestLength);

    LONG ParsePatternNoCase(UBYTE *SourcePattern, UBYTE *MyDestination,
                              LONG DestLength);

The ParsePattern() function creates a case sensitive token string, whereas
the ParsePatternNoCase() functions creates a case insensitive token
string.  Both functions require a pointer to a destination buffer
(MyDestination in the above prototype) to place the tokenized string in.
Since every character in the pattern can be expanded to two tokens (3 in
one case), this buffer should be at twice as as large as the original
pattern plus 2 bytes.  As a general rule, allocating a buffer three times
the size of the pattern will hold all patterns.  The third argument,
DestLength, indicates the size of the destination buffer provided.  These
functions will returns one of three values:

-1    if there is an error (if the buffer is too small to hold all the
      tokens or the source string contains an invalid pattern),

1     if the wildcard pattern was parsed successfully and the pattern
      contains one of the special token characters.

0     if the wildcard pattern was parsed successfully and pattern
      contained only alphanumeric characters (no special token
      characters)


Matching

Once a pattern is parsed, it can be compared to a string using either the
case sensitive MatchPattern() or the case insensitive MatchPatternNoCase()
functions.  These functions have the following synopsis:

    BOOL MatchPattern(UBYTE *mytokenpattern, UBYTE *mystring);
    BOOL MatchPatternNoCase (UBYTE *mytokenpattern, UBYTE *mystring);

These functions will compare the wildcard pattern string, mytokenpattern
(created by ParsePattern/NoCase()), to mystring.  If mystring matches the
pattern in mytokenpattern, these routines return TRUE, otherwise they
return FALSE.

Because these routines are recursive, they can use a lot of stack space,
although they will not use more than 1500 bytes of stack space.  Make sure
the stack space is at least 1500 bytes before calling these routines.

In V36, these routines did not perform any stack checking.  This was added
in V37.  If either of these functions detect a stack overflow, they will
return 0 and IoErr() will return ERROR_TOO_MANY_LEVELS.  If IoErr()
returns 0, there was simply no match.  The Pattern.c example at the end of
this article shows how to use the parse and match functions and allows you
to test and experiment with patterns.


II-43: The 2.0 Dos.library Path Name Handling Functions

By Ewout Walraven

When processing file names, it is often necessary to extract only a file
name from a path or to generate an absolute path to a file.  The release
2.0 dos.library contains several routines designed to make this easier.

The FilePart() function takes a pointer to a file path and returns a
pointer to the last part of the string (the part of the string that
follows the last separator character, "/").  The last part of the string
is normally a file or directory name.

    UBYTE *FilePart(UBYTE *mypath);

In case mypath (from the prototype above) consists only of a file or
directory name (like startup-sequence, s, or libs), FilePart() returns a
pointer to the start of the string (a.k.a. the same value as mypath).

The PathPart() function returns a pointer to the last character in the
path string that doesn't include the file name (usually the separator
character "/"):

    UBYTE *PathPart(UBYTE *mypath);

If passed a pointer to the path string "sys:s/startup-sequence",
PathPart() will return a pointer to  "/startup-sequence".  The application
can then put a \0 where PathPart() points so that the original string has
been shortened to a path part string.  In case mypath (from the above
prototype) is only a file name, PathPart() returns a pointer to this file
name (the same value as mypath).  This can confuse an application if it
blindly expects PathPart() to return a path.  An application should make
sure the pointer PathPart() returns is not the same pointer the
application passed to the function.

Both FilePart() and PathPart() consider the initial colon of an absolute
path name (a path starting with a volume/device/assign name) to be a
special separator character, but PathPart() will not include the colon in
the string it returns a pointer to.  For example, if passed the string
"ram:tmpfile", PathPart() will return a pointer to the string "tmpfile".

Neither FilePart() nor PathPart() check the syntax of the path string
passed to them, so if your application passes an invalid path to them,
they will pass back equally invalid path fragments.  Also, they do not
process any of the wildcard tokens, treating them as normal characters.
The following chart summarizes the possible results of the FilePart() and
PathPart() functions.  It assumes that the path supplied to the functions
is valid.

    wholepath is the path passed to FilePart() and PathPart(),
    pathpart is result of PathPart(),
    and filepart is the result of FilePart().

    1. If (wholepath != pathpart != filepart), then filepart points
       to the the file or directory name in wholepath and pathpart
       points to the '/' before the file or directory name in
       wholepath.  For example:

            wholepath: "ram:t/tmpfile"
            Filepart: "tmpfile"
            Pathpart: "/tmpfile"

            wholepath: "//t/tmpfile"
            Filepart: "tmpfile"
            Pathpart: "/tmpfile"

    2. If (wholepath != pathpart == filepart), then filepart and
       pathpart point to a file or a directory name preceded by a
       volume name or series of separator characters.  For example:

            wholepath: "ram:tmpfile"
            Filepart: "tmpfile"
            Pathpart: "tmpfile"

            wholepath: "//tmpfile"
            Filepart: "tmpfile"
            Pathpart: "tmpfile"

    3. If (wholepath == pathpart == filepart) then pathpart points
       to either a file or a directory name.  This name is not preceded
       by a volume name.

            wholepath: "tmpfile"
            Filepart: "tmpfile"
            Pathpart: "tmpfile"

    4. If (pathpart[0] == 0), then path points to either "" (current
       directory), a series of separators ("/", "//", ":", etc.), or a
       volume/device name.

            wholepath: "////"
            Filepart: ""
            Pathpart: ""

            wholepath: "ram:"
            Filepart: ""
            Pathpart: ""

The dos.library AddPart() function lets you append a file or directory
name to the end of a (relative) path, inserting any necessary separator
characters:

BOOL AddPart(UBYTE *mypathname, UBYTE *myfilename, ULONG mysize);
AddPart() will add myfilename to the end of mypathname.  The mysize
argument indicates how large the mypathname buffer is.  In case this
buffer is too small, AppPart() returns FALSE and makes no changes to the
buffer.  If myfilename is an absolute path, it will replace the current
contents of the mypathname buffer.  If myfilename starts with a colon,
AddPart() will generate a new path relative to the root of the
volume/device in mypathname.

These functions are used in subsequent examples.  The Part.c example lets
you view the results of these functions.  Taking a path and a file name as
arguments, Path.c interprets the path, removes the file name (if part of)
from the path and replaces the path's file name with the file name
supplied in the argument list.

Another dos.library function called SplitName() makes it possible to
extract individual volume/device, directory, or file names (referred to
here as path components) from a path string:

    WORD = SplitName(UBYTE *mypathname, UBYTE separatorchar,
                      UBYTE *buffer, WORD oldposition, LONG buffersize);

SplitName() searches through the string mypathname for the separator
character (separatorchar from the above prototype) starting at
oldposition. As it is stepping through mypathname, SplitName() copies the
characters it encounters from mypathname to the buffer, terminating the
resulting string with a NULL.  It does not copy the separator character
into the buffer.  If it finds the separator character, SplitName() returns
the position of the character that follows the separator character.  This
position can be used as the oldposition argument in subsequent calls to
SplitName() to extract other path components from the same path.  If
SplitName() does not find another separator character, it will return -1,
although it will still copy characters from mypathname to buffer.  For
example, if SplitName() was called with the following arguments:

    mypathname = "ram:env/sys/win.pat"
    separatorchar = '/'
    oldposition = 8
    buffersize = 10

buffer would contain the NULL terminated string "sys" and SplitName()
would return a value of 12.  If SplitName() was called again placing the
return value of 12 into oldposition, buffer would contain the NULL
terminated string "win.pat" and SplitName() would return a value of -1,
as there are no separator characters in mypathname beyond the eleventh
character.

If SplitName() runs out of room in the buffer, it will copy as much of the
characters as it can fit (buffersize - 1) and will write a NULL into the
last position in the buffer (actually, if a path component is followed by
a separator character and the 2.04 version SplitName() runs out of room in
the buffer, SplitName() will only copy (buffersize - 2) characters into
the buffer.  This may be rectified in the future).  Also, if SplitName()
runs out of room in the buffer and it finds another separator character,
the position it returns will not be of the character that follows the
separator character.  Instead, SplitName() will return the position of the
actual separator character.

The Split.c example shows the behavior of this function.  The example
takes two arguments, the path name to split up and the size of the
destination buffer SplitName() should use for the path components.


II-49: Directory Scanning

by Ewout Walraven

Prior to release 2.0, examining the contents of directories using
dos.library required the use of two functions: Examine() and ExNext().
Although these routines perform the task for which they were intended,
they have limitations.  One is that these functions require stepping
through a directory one entry at a time.  For most applications that need
to do directory scanning, it would more efficient to scan a directory in
one pass rather than many.  This would significantly reduce the time spent
scanning. Also, these functions don't know anything about the AmigaDOS
wildcards, so any wildcard processing must be done by the application, not
by the OS.

 Atomic Directory Scanning
 MultiDirectory Assigns
 Filename Matching


Atomic Directory Scanning

The dos.library function ExAll() is a powerful, V37 replacement for the
Examine() and ExNext() functions:

    BOOL ExAll(BPTR mydirlock, UBYTE *mybuffer,
               LONG mybuffersize, LONG mydatatype,
               struct ExAllControl *myexall);

ExAll() performs a one pass directory scan on a directory lock (mydirlock
from the prototype above).  ExAll() fills a buffer (mybuffer from the
above prototype) with partial or whole ExAllData structures (from
<dos/exall.h>):

struct ExAllData {
    struct ExAllData *ed_Next; /* Pointer to the next structure */
    UBYTE *ed_Name;		            /* File name */
    LONG  ed_Type;             /* File type */
    ULONG ed_Size;             /* File size */
    ULONG ed_Prot;  /* Protection bits (FIBF_ definitions in <dos/dos.h> */
    ULONG ed_Days;  /* Date in three longwords, forming a DateStamp. */
    ULONG ed_Mins;
    ULONG ed_Ticks;
    UBYTE *ed_Comment;         /* File comment.  Cannot be used */
};

ExAll() copies an ExAllData structure into mybuffer for each entry in the
directory.  The size of the ExAllData structure depends on the value in
mydatatype.  The mydatatype parameter can have the following values:

   ED_NAME        - ed_Name - file name
   ED_TYPE        - ed_Type - file type (directory, file, soft link, etc.)
   ED_SIZE        - ed_Size - file size
   ED_PROTECTION  - ed_Prot - file protection bits
   ED_DATE        - ed_Days, ed_Mins, ed_Ticks - file date in long words
   ED_COMMENT     - ed_Comment - file comment (not currently supported).

Each of the possible mydatatype values corresponds to a field (or in the
case of ED_DATE, a set of three fields) in the ExAllData structure.  When
ExAll() writes an ExAllData structure to mybuffer, it writes only the
field that corresponds to mydatatype plus the fields that precede that
datatype in the ExAllData structure.  For example, if mydatatype is
ED_SIZE, ExAll() would write ed_Next, ed_Type, and ed_Size to the buffer,
ignoring the fields that follow ed_Size in the the ExAllData structure.

The ExAllData structures in mybuffer are organized into a linked list.
The ExAllData structure's ed_Next field either points to the next
directory entry's ExAllData structure or is NULL if no directory entries
follow. Applications should only access the ExAllData structures using
this link list.

As ExAll() scans a directory, it copies partial or whole ExAllData
structure into mybuffer until it either runs out of directory entries or
until it runs out of room in mybuffer.  If ExAll() runs out of room, it
will return a non-zero value, indicating that your application needs to
perform more passes to finish scanning the directory.

To keep track of everything, ExAll() uses an application-supplied
structure called ExAllControl (from <dos/exall.h>):

struct ExAllControl {
    ULONG eac_Entries; /* The number of entries returned in the buffer */
    ULONG eac_LastKey; /* Used to keep track of position in directory. */
               /* Do not change this value! */
    UBYTE *eac_MatchString; /* Optional parsed pattern for pattern match */
    struct Hook *eac_MatchFunc;
               /* Optional application hook to be called for each entry */
           /* Can be used to individually allow entries in the      */
               /*  buffer or not                                        */
};

The ExAllControl structure must be allocated and freed using
AllocDosObject() and FreeDosObject():

    myexallcontrol = AllocDosObject(DOS_EXALLCONTROL, NULL);
    FreeDosObject(DOS_EXALLCONTROL, myexallcontrol);

The ExAllControl structure's eac_Entries field contains the number of
directory entries that ExAll() wrote into mybuffer.  The eac_LastKey field
is used by the file system to keep track of its place in the directory.
An application must set this field to zero before calling ExAll() and must
not make any changes to this field between scans of a directory.

The eac_MatchString field is used to pattern match the names of directory
entries using the standard AmigaDOS pattern matching functions (for more
on AmigaDOS pattern matching see the article ``Using the AmigaDOS Pattern
Matching Functions'' in the September/October issue of Amiga Mail.  If
eac_MatchString is not NULL, ExAll() will only create ExAllData structures
for the directory entries whose names match the matching string.  Note
that this matching string must have been parsed by ParsePatternNoCase().
If eac_MatchString is NULL, ExAll() will not perform any pattern matching.

The eac_MatchFunc field points to an application-supplied hook function.
If this hook is not NULL, ExAll() will call the hook function.  If the
hook function returns TRUE, ExAll() will copy an ExAllData structure for
this directory entry into mybuffer.  The hook is called in the following
manner:

    BOOL = MatchFunc(hookptr, exalldata, typeptr)
                       A0        A1         A2

where:

hookptr is a pointer to the hook being called exalldata is a pointer to
the exalldata structure of the current directory entry typeptr is a
pointer to a longword indicating the type of the ExAllData structure
(mydatatype from the ExAll() prototype above).

By supplying a hook, each entry in the directory can be accepted or
rejected according to your applications needs.  An application can use
both the matching string and MatchFunc() to perform AmigaDOS pattern
matching and custom matching on directory entries.

The code example ListDir.c at the end of this article is a simple example
of how to use ExAll().  The example ListDir2.c is a more complicated
example that uses pattern matching and a hook function.


MultiDirectory Assigns

As of V36 it is possible to have a logical device assignment to more than
one directory (see the dos.library Autodocs for AssignLock()/AssignAdd()).
Since the user can utilize this with the C:Assign command, it is good
practice to support this feature.  The shell itself supports
multidirectory assigns, although not all C: commands do.  In general, when
your application is presented with only a device name to scan, you should
check if it is an assignment.  If it is, use GetDeviceProc() to get the
handler for it, process it, and loop until GetDeviceProc() returns NULL,
indicating there are no more directories for this assign.  See the
Autodocs for details.

The program Find.c is a more realistic example of the usage of patterns
and ExAll() and shows a method of supporting multidirectory assigns.  It
scans one or more directories or volumes for the occurrence of a
particular pattern.  This example recursively scans subdirectories which
means that Find.c may need more stack space than normal to keep from
overflowing the stack.  Find.c has two required arguments, a pattern and
one or more directories to examine.  It has two keywords, FILES and DIRS,
to tell it to scan only for files or directories, respectively.  The ALL
keyword instructs Find.c to recurse into subdirectories when it encounters
them.


Filename Matching

The release 2.0 dos.library introduced several other functions for
directory scanning:

    LONG MatchFirst(UBYTE *mypattern, struct AnchorPath *myanchorpath);
    LONG MatchNext(struct AnchorPath *myanchorpath);
    VOID MatchEnd(struct AnchorPath *myanchorpath);

When using these functions, an application first calls MatchFirst(), which
performs some initialization (like calling ParsePattern() on the pattern
matching string, mypattern) and finds the first directory entry that
matches the directory entry mypattern.  This pattern is relative to the
current directory.   An application must use the the MatchNext() call to
find subsequent matching directory entries.  After the application is done
looking for matches or the application encounters an error, it must call
MatchEnd() to release internal buffers.

Before using these functions, you need to set up an AnchorPath structure.
This structure must be initialized by MatchFirst() and passed to
MatchNext() and MatchEnd() so they can keep track of the directory scan.
An application must not make any changes to this structure while in the
middle of a directory scan (before calling MatchEnd()).  This AnchorPath
structure must be longword aligned and is defined in <dos/dosasl.h> as
follows:

struct AnchorPath {
    struct AChain   *ap_Base;  /* Pointer to the first anchor */
#define ap_First ap_Base       /* Compatibility synonym. Don't use */
    struct AChain   *ap_Last;  /* Pointer to the last anchor */
#define ap_Current ap_Last     /* Compatiblity synomym. Don't use */
    LONG    ap_BreakBits;      /* Bit flags to stop scanning */
    LONG    ap_FoundBreak;     /* Bits flags which caused the stop */
    BYTE    ap_Flags;          /* Behaviour flags */
    BYTE    ap_Reserved;       /* Reserved for now */
    WORD    ap_Strlen;         /* Buffer size for path name */
                               /* This used to be ap_Length  */
#define ap_Length ap_Flags     /* Compatibility for LONGWORD ap_Length */
                               /* Don't use */
    struct  FileInfoBlock ap_Info;  /* FileInfoBlock for matched entry */
    UBYTE   ap_Buf[1];         /* Application allocated buffer for full */
                               /* path name*/
};

If your application does not need a full path name to matching directory
entries, it should initialize the ap_Strlen field to zero.  In this case,
your application can get what it needs from the AnchorPath's ap_Info
field. It can also get a lock on the directory from ap_Current->an_Lock
field.  If your application needs the full path name of matching directory
entries, it must allocate a buffer at the end of the AnchorPath structure
and put the size of the buffer, in bytes, into ap_Strlen.

The ap_BreakBits field allows the user to abort a directory scan in
progress.  The bits in this field correspond to the SIGBREAKF_ bits
defined in <dos/dos.h>.  If the corresponding bit is set in ap_BreakBits,
MatchFirst() or MatchNext() will stop a scan in progress if one of those
signals occurs.  If this occurs, the bit of the signal that caused the
break will be set in ap_FoundBreak.

With this information alone it is possible to perform simple file pattern
matching.  As previously mentioned, the first match must be found with
MatchFirst().  If MatchFirst() (or MatchNext()) cannot find a match or it
encounters an error, it returns an error number, otherwise it returns a
zero (which is unusual for a dos.library function).  If MatchFirst() does
not encounter any problems, the application should look for subsequent
matches by calling MatchNext().  The application should call MatchNext()
until it returns an AmigaDOS error value.  MatchNext() accepts a pointer
to the AnchorPath structure initialized by MatchFirst().

Normally, the error that MatchNext() returns is ERROR_NO_MORE_ENTRIES,
indicating that there are no more directory entries that match mypattern.
MatchEnd() is used to release any resources that were allocated in the
scanning process.  Due to a number of bugs in the V36 implementation,
these functions should only be used as of V37.  ListPattern.c is a simple
example of using MatchFirst()/MatchNext().

For more complex matching, the ap_Flags field can be used to define the
behavior of MatchFirst() and MatchNext().  Currently, there are several
flags defined:

    APF_ITSWILD
    APF_DODIR
    APF_DIDDIR
    APF_NOMEMERR
    APF_DirChanged
    APF_FollowHLinks

The APF_ITSWILD flag will be set if a wildcard was present in the pattern
after the call to MatchFirst().  It will be used to instruct MatchNext()
but your application can check it too and perform an action depending on
its status.

The APF_DODIR flag instructs MatchFirst/Next() to enter a directory if it
encounters one.  This flag can be set and reset on an individual basis.
Once MatchNext() is finished processing a directory, it will set the
APF_DIDDIR bit and will change the AnchorPath's directory back to the
parent directory.

APF_NOMEMERR indicates that MatchFirst/Next() encountered a fatal out of
memory error.  Processing the directory should be aborted and an error
returned to the user.

The APF_DirChanged flag indicates that MatchNext() noticed that directory
lock has changed since the previous MatchNext() call.

The APF_FollowHLinks flag tells MatchFirst/MatchNext() to follow hard link
directories if the APF_DODIR bit is set.  This feature is in place to
avoid confusing applications that do not know anything about hard links.

Most existing versions of the 2.0 include file <dos/dosasl.h> mention two
other flags, APF_DOWILD and APF_DODOT.  These are not currently in use by
the system.

The DirComp.c example is a more complex example of using
MatchFirst()/Next().  It takes a path, which may include wildcards, and
compares the directory entries it finds with those in the target
directory. If the user specifies the DATE keyword, DirComp will also
compare the datestamps.  The ALL keyword tells DirComp to do a recursive
scan.  For deeply nested directories the BUFFER keyword can enlarge the
buffer that DirComp uses from its standard 256 bytes up to 4096 bytes
(calling it the ``Joanne'' keyword might be more appropriate).


II-65: Writing a UserShell

by Randell Jesup

One of the features of Release 2.0 is that the OS allows the user to
change the system default shell, or the UserShell.  Any time the user
opens a shell with NewShell, executes a script, RUNs a command, or
indirectly calls System() with SYS_UserShell, the OS will call the
UserShell instead of the BootShell (by default the system sets up the
BootShell as the UserShell).

Creating UserShells is not easy, and requires doing a fairly large number
of things for no apparent reason (the reasons are there, they're just not
obvious to the outsider).  This article will attempt to give you the
information you need in order to create a usable, system-friendly
UserShell.

 Initialization
 A Word About the Shell's I/O Handles
 The Main Shell Loop
 Finding a Program
 Running a Program
 Cleanup
 Installing the New User Shell
 Credits

 myshell.c


Initialization

The entity that starts the shell calls the shell code in C style (RTS to
exit). This entity also sends a startup packet to your process port.  You
must retrieve this packet before doing any DOS I/O (much like WBMessages).
You can use WaitPkt() for this.  The entity will take care of attaching a
CommandLineInterface structure to your process, which will be freed on
exit from the UserShell by the system.

In your process structure, check the SegArray pointed to by pr_Seglist
(note that it's a BPTR).  If SegArray[4] is NULL, you must move the value
from SegArray[3] to SegArray[4], and NULL out SegArray[3].  This is
because SegArray[3] will be used to store the seglist pointer for each
program you run.

The startup packet contains some information that tells the UserShell what
kind of shell to be.  At present, the two sets of sources can launch the
UserShell:

    The Run command, Execute(), or System()
    The NewShell or NewCLI resident commands

The size of the stack that the system gives the UserShell depends on how
the user started the shell.  If it was started from Execute() or System(),
the stack is 3200 bytes.  If the UserShell was started from Run, NewShell,
or NewCLI, the stack is 4000.

The type of shell required is specified by the combination of the packet's
dp_Res1 and dp_Res2 fields.   Here's a piece of code for turning them into
a value from 0 to 3:

    init_type = (parm_pkt->dp_Res1 == 0 ? 0:2)|(parm_pkt->dp_Res2 == 0 ? 0:1);

Currently, only types 0 and 2 are implemented.  For 1 and 3 you should
exit with an error (returning the packet).  Type 0 is for Run, Execute()
and System(), type 2 is for NewShell and NewCLI.  After setting up your
SegArray as above, for type 0 call CliInitRun(pkt), and for type 2 call
CliInitNewcli(pkt). These both return a value we'll call ``fn''.  Keep fn
around, it has useful state information that you'll need later.  Note that
these CliInitXxxx functions don't follow the normal DOS convention of Dn
for arguments (they use A0 for pkt!).

The CliInitXxxx functions do many magic things to get all the streams and
structures properly set up, etc.  You shouldn't need to know anything
about this or what the values in the packet are, other than dp_Res1 and
dp_Res2 (see the Appendix for more information on these functions).

       Definitions for the values of fn:

    Bit 31    Set to indicate flags are valid
    Bit  3     Set to indicate an asynchronous System() call
    Bit  2     Set if this is a System() call
    Bit  1     Set if user provided input stream
    Bit  0     Set if RUN provided output stream

If fn bit 31 is 0 (fn >= 0), then you must check IoErr() to find out what
to do.  If IoErr() is a pointer to your process, there has been an error
in the initialization of the CLI structure and processing the packet.  In
this case you should clean up and exit.  You don't have to return the
packet because the CliInitXxxx functions take care of this for you if
there is an error.  If IoErr() isn't a pointer to your process, then if
this is a NewCLI or NewShell command (init_type of 2), reply the packet
immediately.

If the init_type is 0, you have to look at fn to determine when to send
back the startup packet.  If the shell was called from an asynchronous
System() function ((fn & 0x8000000C) == 0x8000000C), return the packet
immediately.  If this is a synchronous System() call ((fn & 0x8000000C) ==
0x80000004) or the fn flags are valid but this is not a System() call ((fn
& 0x8000000C) == 0x80000000) (Execute() does this), you return the packet
just before exiting from your shell (see the Cleanup section below).  If
the fn flags are invalid (bit 31 == 0), but there is something other than
your task pointer in IoErr(), then this shell was called by the Run
command.  Here you can either return the packet immediately, or return it
after having loaded the first command (or failed to find/load it).  This
delay in reply helps avoid the disk thrashing caused by two commands
loading at the same instant.

When you do a ReplyPkt(), use ReplyPkt(pkt, pkt->dp_Res1, pkt->dp_Res2) to
avoid losing error codes set up by CliInitXxxx.

Initialize pr_HomeDir to NULL, set up any local shell variables, etc.

We're all set up now, so you can now enter your main loop and start taking
commands.


A Word About the Shell's I/O Handles

There are three pairs of I/O handles in a shell process.  The shell's
Process structure contains the pr_CIS (current input stream) and pr_COS
(current output stream) file handles.  That Process's CommandLineInterface
structure contains the other two pairs of I/O handles:
cli_StandardInput/cli_StandardOutput and
cli_CurrentInput/cli_CurrentOutput.  Each has different uses within a
normal shell.

Routines that operate on Input() or Output(), such as ReadArgs() or
ReadItem(), use the pr_CIS and pr_COS I/O handles (which they acquire by
calling the dos.library routines Input() and Output(), not by directly
looking at the Process structure).  Shell-launched application programs
the run on the shell's process also use these I/O handles as their normal
input and output channels. This is where functions like scanf() and
printf() get and send their input and output.  The shell changes these
file handles (using SelectInput()/SelectOutput()) according to the shell
defaults and according to any I/O redirection.

The cli_StandardInput and cli_StandardOutput I/O handles are the default
input and output channels for the shell.  They usually refer to the user's
console window and will not change while the shell is running.  The shell
should use these values as the default values for pr_CIS and pr_COS (via
SelectInput() and SelectOutput()) when it runs a command from a command
line.

The cli_CurrentInput handle is the current source of command lines.  This
normally is the same as cli_StandardInput.  The cli_CurrentInput handle
will differ from cli_StandardInput when the shell is executing a script or
when handling an Execute() or System() call.  In these cases, it points to
a file handle from which the shell is reading commands.  This handle
refers to one of three files: the script file you called with the execute
command, a temporary file created by the execute command, or a pseudo file
created by Execute() or System().

When a shell runs the execute command, If cli_CurrentInput differs from
cli_StandardInput, The execute command will close cli_CurrentInput and
replace it with a new one, so don't cache the value of cli_CurrentInput as
it will be invalid.  In this case, cli_CurrentInput must not be the same
as pr_CIS when you call RunCommand() if the executable could possible be
the execute commands (or anything else that tries to close
cli_CurrentInput).

The cli_CurrentOutput file handle is currently unused by the system.  It's
initialized to the same as cli_StandardOutput.


The Main Shell Loop

Note: some things in this section assume your UserShell will act similarly
to the Boot Shell in 2.0.  If not, modify to see fit, but pay close
attention to things external programs will notice (such as the setup of
the process and CLI structures).  In particular, the article assumes that
you handle scripts by redirecting cli_CurrentInput to a file with the
script in it, as the execute command does.  Note that the execute command
will attempt to do this if you run it--be careful.

Before reading a command line, you need to SelectInput() on the I/O handle
in the current cli_CurrentInput, and SelectOutput() on cli_StandardOutput.
This makes sure the shell is reading from its command line source and
writing to the the default output handle.

If this shell is executing a script, you should check if the user hit the
break key for scripts (Ctrl-D is what the BootShell uses).  If you do
detect a script break, you can print an error message to the current
output stream by calling PrintFault(304, "<your shell name>").  304 is the
error number (ERROR_BREAK) and the string gets prepended to the error
message (which is currently " :***Break").  This allows the OS to print
the error message using the standard error message which can be
internationalized in future versions of the OS.

Next, determine if you should print a prompt.  The nasty statement below
sets up the Interactive flag for you, by setting it if the following are
true:

    This shell is not a background shell
    input has not been redirected to an Execute/script
    file this is not a System() call

You don't have to handle it precisely this way, but this works (Note:
0x80000004 is a test for whether this is a System() call, see the ``fn''
bit definitions above).

#define SYSTEM     ((((LONG)fn) & 0x80000004) == 0x80000004)
#define NOTSCRIPT  (clip->cli_CurrentInput == clip->cli_StandardInput)

  clip->cli_Interactive = (!clip->cli_Background && NOTSCRIPT && !SYSTEM) ?
                   DOSTRUE : FALSE;

The BootShell prints a prompt if cli_Interactive is DOSTRUE.

Do all your mucking with the input line, alias and local variable
expansion, etc.


Finding a Program

There are several possible places a shell can look for commands passed to
it. The resident list is an important place to look as it contains many
commands that the user finds important enough to keep loaded into memory
at all times. Some shells have commands built directly into them.  Of
course, if the shell cannot find a command in the resident list or in its
collection of internal commands, the shell has to scan the path looking
for the command.  If a shell supports the script bit, when it finds a
command on disk with the script bit set, it should read commands from the
script file.

Here's how you deal with commands on the resident list: After finding the
command (under Forbid()!), if the Segment structure's seg_UC is >= 0,
increment it; if less than 0, don't modify it.  If seg_UC is less than
CMD_DISABLED, the corresponding resident command is currently disabled and
you should not execute it.  The same is true if seg_UC is equal to
CMD_SYSTEM.  After incrementing seg_UC, you can Permit().  After using a
resident command, decrement the seg_UC count if it's greater than 0 (under
Forbid() again).

When identifying scripts, I advise that you use something unique to
identify your scripts, and pass all other scripts to the Boot Shell via
System() for execution.  A good method (which was worked out on BIX long
ago) is to include within the first 256 characters or so, the string
"#!<your shell name, ala csh>!#".  BootShells could, for example, start
with "; #!c:execute!#.  The idea is the string inside the #!...!# should
be the interpreter to run on the script.  If none is specified, give it to
the BootShell.  If you want, you could extend this to include handling of
the sequence for all interpreters. The programs should be invoked as
"<interpreter> <filename> <args>" as if the user had typed that.

Don't forget to set pr_HomeDir for programs loaded from disk.  The Lock in
pr_HomeDir should be a DupLock() of the directory the program was loaded
from. For programs from the resident list, leave it NULL.

Please support multi-assigned C: directories.  The important thing here is
to not lock C:.  Instead, prepend ``C:'' onto the filename you wish to
Lock()/LoadSeg().  Also, if a command is loaded from C:, get its
pr_HomeDir by Lock()ing the file (with C: prepended), and then using
ParentDir() to get its home directory.

The Path is attached to cli_CommandDir.  It is a BPTR to a NULL
terminated, singly-linked list (connected via BPTRs) of directory Locks:

    struct pathBPTRlistentry {
        BPTR   pathBPTRlistentry *next;
        struct Lock              directorylock
    }

Please don't modify the list; use the Path command instead.  This will
make it far easier for us to improve this in the future.

Make sure you clear the SIGBREAK_CTRL_x signals before starting a program.
In order to prevent the user from hitting a break key somewhere between
where you check for the break and where you clear the signals (thus losing
the break signal), you may wish check for a break and clear the signals at
the same time. The safest way is to use:

    oldsigs = SetSignal(0L, SIGBREAK_CTRL_C |
                            SIGBREAK_CTRL_D |
                            SIGBREAK_CTRL_E |
                            SIGBREAK_CTRL_F);

Then you can check oldsigs for any signals that you care about.


Running a Program

To actually invoke a program on your process, use RunCommand()--it does
special compatibility magic that keeps certain third-party applications
working properly.   If RunCommand() fails due to lack of memory, it
returns -1 (normally success!).  In this case, check IoErr().  If it is
equal to ERROR_NO_FREE_STORE, then RunCommand() really ran out of memory.
Note that RunCommand() stuffs a copy of your arguments into the buffer of
the input handle for use by ReadArgs(), and un-stuffs them when the
program exits.  Also note that RunCommand() takes stack size in bytes, and
cli_DefaultStack is the size of the stack in LONGs.

After the program has completed, free the Lock in pr_HomeDir and set it to
NULL.  Re-setup your I/O handles with SelectInput() on cli_CurrentInput
and SelectOutput() on cli_StandardOutput.  It's a good idea to NULL
cli_Module here as well, as it can make your exit/cleanup logic easier.

You must eat any unused buffered input.  Here's some tricky code that does
that (read the Autodocs to figure it out if you wish):

    ch = UnGetC(Input(),-1) ? 0 : '\n';
    while ((ch != '\n') && (ch != END_STREAM_CH)) ch = FGetC(Input());

Note: ENDSTREAMCH is EOF (-1).  Newer include files #define this in
<dos/stdio.h> and <dos/stdio.i>.

To finish the main input loop, use the code below or something like it.
This keeps compatibility with certain hacks people had figured out about
1.3 (See SYSTEM and NOTSCRIPT #defines above).

        /* for compatibility */
        /* system exit special case - taken only if they have played */
        /* around with the input stream */
        if (SYSTEM && NOTSCRIPT) break;
    } while (ch != ENDSTREAMCH);

EndCLI sets fh_End = 0, which causes FGetC() to call replenish(), which
returns ENDSTREAMCH on fh_End == 0.  EndCLI also sets cli_Background!
This neatly avoids a prompt after EndCLI.

After you've gotten an EOF (falling out of the while(ch != ENDSTREAMCH)
statement above), you need to check if the shell was executing a script
file. For Execute-type scripts, if (cli_CurrentInput != cli_StandardInput)
is true, the shell was executing a script.  If this is the case, you'll
need to Close() the cli_CurrentInput, and DeleteFile() the temporary file
cli_CommandFile, if there is a file name there.  Next, set
cli_CurrentInput to cli_StandardInput, and restore the fail level.  Then
you go back to your normal input loop and accept commands again.  Note:
this is based on handling scripts in the same manner as the BootShell--you
may handle them in different ways.

On EOF, you also need to check if this is a System() call.  The check for
a System() call is ((fn & 0x80000004) == 0x80000004).  If you had been
handling a System() call, or if the shell was not executing a script, you
should go to your cleanup code to exit.


Cleanup

If you're exiting, use fn to tell you what to close, etc.  First check if
fn contains valid flags ((fn & 0x80000000) != 0)).  If it does not have
valid flags, Flush() and Close() cli_StandardOutput (if non-NULL), and
Close() cli_StandardInput (if non-NULL).  If fn does contain valid flags,
Flush(Output()), then check the other flags in fn.  If (fn&2 == 0) (if the
user didn't provide an input stream), Close() cli_StandardInput.  If (fn&1
== 1) (if Run provided an output stream), Close() cli_StandardOutput
(note, this is opposite the previous flag!)  If (fn&8 == 0) (if this is
not an asynchronous System() call), you still have to ReplyPkt() the
initial packet.  Before sending back the packet put cli_ReturnCode in the
packet's result1 and cli_Result2 in the packet's result2 (i.e. return the
result of the last program run if this was a synchronous System() or
Execute() call).

In cleanup, unlock pr_CurrentDir and set it to NULL, free up anything you
allocated, and exit!  The system will take care of your
CommandLineInterface structure, and anything else it allocated.


Installing the New User Shell

After you have compiled your creation, you need to put its seglist on the
resident list under the name ``shell''.  Adding it to the resident list is
a simple:

    Resident shell <shell-file> SYSTEM

Now anything that calls the user shell (like NewShell, Execute(), and
System()) will call your shell.  Note that under 2.04, the Shell icon
actually runs sys:System/CLI, which calls the BootShell (the default
UserShell) and not the current UserShell.

If you need to restore the BootShell as the UserShell, compile and run the
program RestoreShell.c at the end of this article


Credits

I thank greatly the input and bug reports I got from Bill Hawes during the
development of the 2.0 DOS and it's shell interface.  It's still extremely
ungainly, but it is now usable.

I also thank Michael B. Smith and Jesper Steen Moller for taking the
initial confusing Usenet article I posted and making working shells from
that information, and John Orr for making me write this article and
producing the example (which helped make me clean up confusing points in
it).


II-77: Fast AmigaDOS I/O

Fast AmigaDOS I/O

by Martin Taillefer

Reading and writing data is crucial to most applications and is, in
many cases, a major bottleneck.  Using the Amiga's sophisticated file
system architecture can help reduce, and sometimes eliminate, the
time spent waiting for I/O to complete.  This article presents six
small routines that can greatly improve an application's I/O
performance.

Typically, an application processes a file in the following manner:

Step 1: Open the file.
Step 2: Read some data (with the DOS library's Read() function).
Step 3: Process that data.
Step 4: Repeat steps 2 and 3 until the application is finished
        processing the file.
Step 5: Close file.

This sequence of steps is effective, but it does have a potential
bottleneck.  Whenever the application reads some data using the DOS
Read() function, the Amiga has to put that task to sleep and ask the
file system to fetch the data.  The file system then starts up the
disk hardware and reads the data.  After the file system finishes
reading the data, the operating system wakes up the application.

The problem is step 2.  While the file system is busy reading data
from the disk, the application is idle, waiting for the DOS I/O in
Read() to complete.  A more sophisticated application would initiate
an asynchronous read, allowing the application to continue to do some
other important chore while the file system is busy reading.  If all
goes well, the file system will be finished with the asynchronous
read by the time the application is finished with its chore, so the
application will not have to wait for any DOS I/O to complete before
the application can access data.

Using the routines presented in this article, an application
processes a file in the following manner:

Step 1:  Open the file with OpenAsync().  This function opens the
         file and, if the file is opened for reading, OpenAsync()
         asks the file system to start reading data, asynchronously.
Step 2:  Read some data with ReadAsync().  If the asynchronous read
         request that OpenAsync() sent has not completed, ReadAsync()
         will put the application to sleep until that request
         returns. Ideally, the read will have returned, so the
         application won't have to wait. ReadAsync() will also
         initiate a new asynchronous read so new file data is ready
         when the application needs it.
Step 3:  Process the file data.
Step 4:  Repeat steps 2 and 3 until the application processes
         all its file data.
Step 5:  Close the file with CloseAsync().

Immediately after opening the file, OpenAsync() sends a request to
the file system to get it reading data in the background.  If all
goes well, by the time the application gets around to reading the
first byte of data, the file system has already copied the data into
memory.  That means the application doesn't need to wait and can
immediately start processing the data.  As soon as the application
starts processing data from the file using ReadAsync(), ReadAsync()
sends out a second request to the file system to fill up a second
buffer.  Once the application is done processing the first buffer, it
starts processing the second one.  When this happens, the file system
starts filling up the first buffer again with new data.  This process
continues until the application has read all of its data.  This
technique is known as ``double-buffered asynchronous I/O''.

The set of functions presented below offer high-performance I/O using
the technique described above.  The interface is very similar to
standard AmigaDOS files.  These routines enable full asynchronous
read/write of any file.

These functions are especially useful on an Amiga with a DMA (Direct
Memory Access) hard drive.  DMA makes it possible to transfer data to
memory at the same time the CPU is busy executing a task's
instructions.  A DMA data transfer is truly parallel, so, under
normal conditions, the CPU is operating at full speed, unaffected by
the DMA transfer.  This parallelism is what makes the set of
accompanying routines so efficient.  They exploit the fact that the
Amiga can transfer an application's data while the application is
busy processing other data.

Although these asynchronous routines make disk I/O much faster, they
do have an important limitation.  The routines do not support seeking
into a file.

 Async.doc
 ASyncExample.c
 ASyncIO.c
 ASyncIO.h


II-87: Cooperative Record Locking with AmigaDOS

Cooperative Record Locking with AmigaDOS

by Ewout Walraven

Cooperative record locking was introduced to the Amiga's ROM file
system and RAM-handler (RAM:) in Release 2.  The Amiga's cooperative
record locking scheme allows an application to lock regions of a file
rather than locking an entire file.  These regions are known as
records.

The Amiga thinks of a record in terms of size and offset.  The size
refers to the length of the record in bytes.  The offset refers to
the starting position of the record from the beginning of the file.
The size and offset can vary from record to record.  The only limit
on a record's size and offset are the limits the file system has on
the size of the file.

In Release 2, there are two basic types of record lock, exclusive and
shared.  An exclusive lock gives an application exclusive access to a
record.  While an application holds an exclusive record lock, no
other process can obtain a record lock that overlaps the exclusively
locked region.  The file system can only grant an exclusive record
lock on a region that is not part of an existing record lock.

The other type of record lock, the shared lock, gives an application
shared access to a record.  While an application holds a shared
record lock, other applications can also obtain a shared record lock
that overlaps the original shared record lock, but no other process
can obtain an exclusive record lock that overlaps the shared record
lock.

To lock (or unlock) a record within a file, an application needs a
valid file handle on the file.  Two DOS Library functions handle
individual record locks:

    BOOL LockRecord(BPTR myFH, ULONG my_offset, ULONG my_length,
                    ULONG my_mode, ULONG my_timeout);

    BOOL UnLockRecord(BPTR myFH, ULONG my_offset, ULONG my_length);

In both functions, the myFH field refers to the valid file handle
mentioned above, and the my_offset and my_length fields refer to the
record's offset and size.

The LockRecord() function has two additional parameters: my_mode and
my_timeout.  The my_mode field refers to the type of record.  Release
2 supports four record types:

    REC_EXCLUSIVE        Create an exclusive record lock.  If the record
      is not immediately available, the file system will make a second
      record lock attempt when the timeout expires.  The timeout (the
      my_timeout field from the RecordLock() prototype above) is in DOS
      ticks (1/50 of a second).

    REC_EXCLUSIVE_IMMED  This record type is like REC_EXCLUSIVE, but the
      attempt to lock a record will fail if the record is not immediately
      available.  In this case the file system ignores the timeout.

    REC_SHARED           Create a shared record lock.  If the record is
      not immediately available, the file system will make a second record
      lock attempt when the timeout expires.  The timeout (the my_timeout
      field from the RecordLock() prototype above) is in DOS ticks (1/50th
      of a second).

    REC_SHARED_IMMED     This record type is like REC_SHARED, but the
      attempt to lock a record will fail if the record is not immediately
      available.  In this case the file system ignores the timeout.

The Amiga record locking scheme is cooperative--the file system
does not prevent any process from accessing any part of a data
file.  The record locking scheme has nothing to do with other
actions of a file system.  The file system will let other
processes read and write a data file regardless of any existing
record locks on the data file.

Also, when an application attempts to create a record lock, the file
system's record locking mechanism only makes sure the record won't
conflict with any existing record locks on the same data file.  The
file system doesn't check the validity of the locked region.  This
makes it possible to lock records in an empty data file and also to
lock records that are well beyond the end of a data file.  This
feature may be useful to an application that needs to lock records
that don't exist yet.

When releasing a record lock, an application must provide exactly the
same parameters it used when it locked the record.  Attempting to
unlock a record using a different offset or length will fail.  If the
application does not successfully unlock a record, the record lock
will remain in effect.  This means further requests to lock that
record can fail, depending on the type of record lock.  The record
lock will remain in effect until the data file is removed or the
system restarted.  As with most Amiga resources, an application
should release a record lock as quickly as possible.  This helps out
other applications that might be waiting to access the locked record.

Locking Multiple Records

DOS Library offers a function to lock an array of record locks:

    BOOL LockRecords(struct RecordLock *recordarray, ULONG multi_timeout);

LockRecords() locks a group of records using one function call.
LockRecords() accepts a pointer to an array of RecordLock structures
(as defined in <dos/record.h>):

struct RecordLock {
        BPTR    rec_FH; /* The file handle of the data file */
        ULONG   rec_Offset;     /* The record offset in the data file */
        ULONG   rec_Length;     /* The length of the record */
        ULONG   rec_Mode;       /* The mode of the record lock */
};

The fields in each RecordLock structure correspond to the parameters
from the LockRecord() function.  The records do not have to be in the
same file.  The array is terminated by a dummy RecordLock with a NULL
file handle (rec_FH).

The RecordLock structure does not include a timeout.  Instead,
LockRecords() applies the same timeout (multi_timeout from the
LockRecords() prototype above) to each RecordLock in the array.  If
LockRecords() fails to lock any of the records in its array,
LockRecords() releases any successful record locks from the array,
and return DOSFALSE.

To unlock records locked by LockRecords(), use the dos.library
function UnLockRecords():

BOOL UnLockRecords(struct RecordLock *recordarray);

This function accepts the same array used to lock the records with
LockRecords().

Note that it is possible to use UnLockRecord() on a record locked by
LockRecords().  However, if an application uses UnLockRecord() to
unlock one record in the RecordLock array, it should use
UnLockRecord() to unlock all of the records in the array.

Locking Records Using DOS Packets

To lock a record using the DOS packet interface, send an
ACTION_LOCK_RECORD (2008) packet to the file system.  This packet
uses the following arguments:

ARG1: BTPR   The file handle of the data file in which you wish to lock a record.
ARG2: ULONG  The offset (in bytes) in the file of the record.
ARG3: ULONG  The length (in bytes) of the record.
ARG4: ULONG  The mode with which you wish to lock record.
ARG5: ULONG  Time (in ticks) you are will to wait for the record to become available.

RES1: BOOL   Upon return RES1 will contain the success/failure status:
             DOSTRUE if the record lock was successfully locked.
             DOSFALSE if the record lock failed.
RES2: CODE   Failure code if the record lock failed for a reason other than denied
             access (collision for example).

To unlock a record using the DOS packet interface, send an
ACTION_FREE_RECORD (2009) packet.  This packet uses the following
arguments:

ARG1: BPTR   The file handle of the data file in which you locked the record.
ARG2: ULONG  The offset (in bytes) in the file of the record with which you locked
             the record.
ARG3: ULONG  The length (in bytes) of the record with which you locked the record.

RES1: BOOL   Upon return RES1 will contain the success/failure status:
             DOSTRUE if the record lock was successfully unlocked.
             DOSFALSE if there was no lock to unlock.
RES2: CODE   Possible failure code if the record lock could not be unlocked.

 LockRecord.c
 ExRecLock1.c
 ExRecLock2.c


II-95: Packet Level I/O under Release 2

Packet Level I/O under Release 2

by Dale Larson and John Orr

Normally when an application needs to perform I/O using DOS, it uses
functions from the dos.library to open, read, write, and close any
I/O channels.  These functions take care of talking to the underlying
DOS device (see the ``About Devices'' section below), shielding the
programmer from most of the grunt work it takes to carry out the I/O.
These functions are adequate for most I/O needs.

 *********************************************************
 *                                                       *
 * About Devices                                         *
 *                                                       *
 *                                                       *
 * The term ``DOS devices'' is confusing because the     *
 * term ``device'' is a bit overloaded.  There are       *
 * three entities on the Amiga that are referred to as   *
 * a device.  There is the Exec device (for example      *
 * trackdisk.device and console.device) the AmigaDOS     *
 * device (such as DF0: and RAM:), and the logical       *
 * AmigaDOS device name (for example, SYS:, C:, and      *
 * S:).  The Exec level device is basically a subset of  *
 * an Exec library.  Exec devices are described in the   *
 * RKRM: Devices book. The AmigaDOS device is a higher   *
 * level entity than the Exec device (AmigaDOS devices   *
 * often utilize Exec devices).  An AmigaDOS device has  *
 * a process associated with it, normally referred to    *
 * as a handler, that controls the AmigaDOS I/O stream   *
 * via a FileHandle.  The AmigaDOS logical device name   *
 * (better known as an ``assign'') is made to look like  *
 * an AmigaDOS device, but is a higher level entity      *
 * than the AmigaDOS device.  Both the AmigaDOS device   *
 * and the logical device name are referred to by a      *
 * name ending in a colon (':').  The logical device     *
 * can refer to any directory on an AmigaDOS device (as  *
 * long as the AmigaDOS device supports having files).   *
 * The user can change the directory to which logical    *
 * device name refers from a command line. This article  *
 * deals primarily with AmigaDOS devices.                *
 *                                                       *
 *********************************************************

One of the reasons these functions are only adequate is because they
are synchronous.  When an application attempts to transfer data using
one of these functions, the I/O function waits for the entire
transfer to finish before returning.  Ideally, the application should
be able to perform I/O asynchronously, so it can do something else
while the data transfer takes place.

Another reason that these functions are only adequate is because they
don't implement all of the features built into DOS devices.  To
utilize these features, an application has to work on a lower level.
The application has to talk directly to the DOS device.

The Packet Level

When DOS functions talk to devices such as the floppy drive or the
serial port, they talk to a special process called a handler.  Every
DOS device (like CON:, SER:, DF0:, and PIPE:) has a handler process.
The handler process is responsible for receiving and carrying out a
standard set of DOS device commands.  It provides a standard
programming interface to a lower-level I/O software or hardware
entity (such as an Exec device).  The packet interface abstracts the
lower-level entity so that dos.library functions don't have to deal
with a lot of bothersome details such as moving a disk head or
reading serial registers.   The interface to every handler is the
same, so every DOS device operates in the same manner, regardless of
any underlying software or hardware.  Theoretically, to the
dos.library functions, writing to the console handler (CON:) should
be no different than writing to the serial port handler (SER:) or the
DF0: handler.  The handler lets dos.library functions treat all DOS
devices in the same way.

Typically, the handler talks directly to an underlying Exec device.
Two examples are the CON: and the DF0: handlers.  The CON: handler
process talks directly to the console.device.   When trying to access
a floppy in DF0:, the DF0: handler talks directly to the
trackdisk.device.  These handlers accept handler level commands (for
example, ACTION_READ and ACTION_WRITE) and hide any Exec level I/O
from the dos.library functions and subsequently, the application.

In cases like the DF0: handler, which is a special type of handler
called a file system, the handler has to take care of organizing the
lower-level medium into directories and files.  The DF0: handler
takes care of translating directory and file names into terms the
trackdisk.device can understand (disk blocks).  The only requirement
of a handler to be a file system is that the handler must support
files.  A file system does not have to support a directory structure
to be considered a file system.  Handlers which are not file systems
are called stream handlers.

Some handlers do not have any underlying software or hardware.
Handlers such as RAM: have no underlying software or hardware.  These
kinds of handlers take care of implementing everything necessary to
carry out the I/O rather than delegating to an Exec device.

Handlers receive commands through an Exec message port.  Every
handler process has a message port for receiving commands.  A handler
accepts a command in the form of a DosPacket structure (defined in
<dos/dosextens.h>), which is an extension of an Exec Message
structure:

struct DosPacket {
   struct Message *dp_Link;
   struct MsgPort *dp_Port;  /* Reply port for the packet */
                             /* Must be filled in each send. */
   LONG dp_Type;
   LONG dp_Res1;             /* Result #1 */
   LONG dp_Res2;             /* For file system calls this is what would
                              * have been returned by IoErr() */
   LONG dp_Arg1;             /* Argument list */
   LONG dp_Arg2;
   LONG dp_Arg3;
   LONG dp_Arg4;
   LONG dp_Arg5;
   LONG dp_Arg6;
   LONG dp_Arg7;
}; /* DosPacket */

The dp_Type field contains an identifier corresponding to the
command.  The identifiers for each of the standard commands are
defined in <dos/dosextens.h>.  For example, the command to write data
is ACTION_WRITE.  Each packet type has different parameters, which
the programmer supplies in the ``dp_Arg'' fields.

After a handler finishes with a packet, it returns the packet to the
message port in dp_Port.  The handler places return values (including
any error codes) in the result fields dp_Res1 and dp_Res2.  If there
was an error, dp_Res2 contains the corresponding DOS error code.

The packet types are described in the Amiga Mail article ``AmigaDOS
Packet Interface Specification'' on page II-5 and also in The
AmigaDOS Manual, 3rd Edition.  Since its original publication, the
``AmigaDOS Packet Interface Specification'' has been updated numerous
times in Amiga Mail to correct errors.  The information in that
article (plus its errata) should appear in the next edition of The
AmigaDOS Manual.

Finding the Handler

There are various ways to find the address of the target handler's
Message port, which is also called a process identifier by some
documentation.  When working with an open FileHandle, the handler's
port address is in the FileHandle's fh_Type field.  Note that the
dos.library functions normally access a FileHandle using a BPTR, so
to get to the fh_Type field an application has to do something like
this:

    my_handler_port = ((struct FileHandle *)BADDR(FileHandle))->fh_Type);

Because the AmigaDOS device NIL: has no handler process, the fh_Type
field of any of its file handle's will be NULL.  The application must
account for this case.

When working with a device or assign name, an application can get to
the handler's message port by using the dos.library function
GetDeviceProc():

    struct DevProc *GetDeviceProc(UBYTE *dev_name, struct DevProc *prev_devproc);

This function returns a pointer to the following structure:

struct DevProc {
        struct MsgPort *dvp_Port;     /* The handler's Message port     */
        BPTR            dvp_Lock;     /*           (send packets there) */
        ULONG           dvp_Flags;
        struct DosList *dvp_DevNode;  /* DON'T TOUCH OR USE! */
};

This function is intended to improve on the DeviceProc() function as
it also deals with multiple assigns.  GetDeviceProc() must be
countered by FreeDeviceProc().  See the GetDeviceProc() Autodoc for
more details.

The Old Way

Prior to Release 2, sending packets was relatively complicated.  Some
of the early disks from the Fred Fish Library (disks 35, 56, and 66)
contain complete examples of using DOS packets synchronously and
asynchronously.  As of Release 2.04, dos.library contains functions
which make it easier to use DOS packets synchronously and
asynchronously.

Synchronous Packet Calls

Performing synchronous packet I/O is now very simple.  Simply call
the dos.library function DoPkt():

LONG DoPkt(struct MsgPort *handler_port, LONG action_id, LONG arg1,
           LONG arg2, LONG arg3, LONG arg4, LONG arg5);

This function allocates and fills out a DosPacket using the packet
type ('action_id') and arguments ('arg1', 'arg2', etc.) you supply.
This function then sends off the packet to the 'handler_port' and
waits for the packet to return.   DoPkt() returns the value from the
packet's dp_Res1 field.  To get the value from the packet's dp_Res2
field, call the dos.library function IoErr().  Assembly language
programmers can also get dp_Res2 from register D1.

Asynchronous Packet Calls

To do asynchronous packet calls, things are a little more complex,
but they are still much better than they were before V37 (This
subject was partially covered in Martin Taillefer's article, ``Fast
AmigaDOS I/O'', page II-77, from the September/October 1992 issue of
Amiga Mail).  When using a DOS packet asynchronously, there are three
things to do before sending the packet anywhere:

    o Acquire a message port
    o Allocate and initialize the packet
    o Set up the packet's arguments

Acquiring the Message Port

It is possible for an application to use its process message port for
packet transmissions rather than allocating a new one.  It can get to
its Process structure by calling FindTask() with an argument of NULL.
The Process structure has an Exec MsgPort structure embedded in it,
which an application can get to via the pr_MsgPort field.  The bad
thing about using this port is that many system functions also use
it.  Consequently, after sending an asynchronous packet, an
application can not call any system functions that use pr_MsgPort.
This includes most dos.library functions, many C compiler linker
library functions, and many standard I/O functions (i.e., printf()
and scanf()).  The application has to wait for the asynchronous
packet to return before calling such functions.  If the application
sent an asynchronous packet and inadvertently initiated some other
packet level I/O before the asynchronous packet came back, it is
possible to cause an ``unexpected packet received'' system crash if
the asynchronous packet returned at the wrong time.  Also, an
application should remove such a packet from the process message port
using the WaitPkt() function.  This function will take care of any
system idiosyncrasies that the application would otherwise need to
address itself.  This applies to idiosyncrasies that exist now or new
ones that may appear in the future.

As of V37, arguably the best and easiest way to acquire a message
port is to create one with the exec.library call CreateMsgPort().  By
allocating its own message port, the application doesn't have to
worry about any problems with sharing the port.

Allocating and Initializing a Packet

The packet I/O system uses Exec's message passing system, so each
DosPacket must also have an Exec Message structure.  As both
structures are necessary, they have been combined in a single
StandardPacket structure (defined in <dos/dosextens.h>):

struct StandardPacket {
   struct Message   sp_Msg;
   struct DosPacket sp_Pkt;
}; /* StandardPacket */

To make a packet usable, the Exec Message and DosPacket structures
have to be set up to point to each other.  The DosPacket structure is
straightforward about its link to its corresponding message.  The
DosPacket's dp_Link field must point to the packet's Message
structure.  However, the link from the Message to the DosPacket is a
bit obscure.  The Message contains an Exec Node structure which in
turn contains a field called ln_Name.  Although the Node structure
defines ln_Name as a character array, the DOS packet I/O system
instead requires that this field point to the Message's corresponding
DosPacket:

    my_standard_pkt->sp_Msg.mn_Node.ln_Name = (STRPTR)(my_standard_pkt->sp_Pkt);

As of V37, the dos.library function AllocDosObject() is usually the
best way to allocate a StandardPacket.  To allocate one, call:

    mypacket = AllocDosObject(DOS_STDPKT, NULL);

This function takes care of linking the StandardPacket's Message and
DosPacket.  Note that the function call above does not return a
pointer to a StandardPacket.  This function allocates an entire
StandardPacket structure, but it returns a pointer to the
StandardPacket's sp_Pkt field.  To access the sp_Msg portion of the
StandardPacket, use the pointer in the dp_Link field.

Any structure allocated with AllocDosObject() must be freed with
FreeDosObject().  To free 'mypacket' from the above AllocDosObject()
call:

    FreeDosObject(DOS_STDPKT, mypacket);

Filling in Packet Arguments

Before sending an asynchronous packet, an application needs to fill
in its action and arguments.  For example, a packet set up to read
4096 bytes from an open file handle might look something like this:

. . .

#define BUFSIZE 4096

. . .

BPTR myfh;
struct DosPacket *my_pkt;
UBYTE *buffer[BUFSIZE];

        . . .

        my_pkt->dp_Type = ACTION_READ;
        my_pkt->dp_Arg1 = ((struct FileHandle *)BADDR(myfh))->fh_Arg1;
        my_pkt->dp_Arg2 = buffer;
        my_pkt->dp_Arg3 = BUFSIZE;

        . . .

Sending the Asynchronous Packet

To send a packet asynchronously, use the dos.library SendPkt() function:

    SendPkt(struct DosPacket *mypacket,
            struct MsgPort *handlerport, struct MsgPort *replyport)

This function sends 'mypacket' to 'handlerport' and exits without
waiting for the packet to come back.  When the packet returns, it
will arrive at 'replyport'.

Waiting for the Asynchronous Packet

After calling SendPkt(), the application can go about its business,
taking care of some other work while the DOS device handles the
application's packet.  Eventually, the application will have to test
the reply port to see if the packet has come back yet.  It can do
this with WaitPort() or, if the application has to test for more than
just the reply port's signal, it can use Wait().  If the application
doesn't poll its signals too often, it can test its own signal bits
using SetSignal() (see the exec.library Autodocs and the
``Introduction to Exec'' chapter of the Release 2 RKRM: Devices for
more information on how to use these functions).  Be sure to remove
any and all packets from the message port using GetMsg().

If the application used its process message port (pr_MsgPort) as the
reply port, it must use the WaitPkt() function to remove the packet
from the message port.  As mentioned earlier, this function will take
care of any hidden system idiosyncrasies so the application never has
to account for them.  WaitPkt() will not necessarily clear the
process message port's signal bit.  Like SendPkt(), WaitPkt() assumes
any DosPacket it works with is part of a StandardPacket structure.

The dos.library contains a function called AbortPkt() that, at a
glance, looks like it might be useful to an application that needs to
abort a packet (for example, upon receiving a break signal).  This
function, which was introduced in Release 2, is supposed to attempt
to abort a packet that has already been sent to a handler.  If the
abort operation is successful, the aborted packet will arrive at its
original reply port (the same place the packet would have arrived if
it was successful).  Unfortunately, the abort operation will never be
successful, at least not under existing releases of the operating
system.  Currently, this function returns without doing anything (the
most recent release is 3.0 or V39).  In the future when AbortPkt()
does do something, it will assume that any DosPacket it works with is
part of a StandardPacket structure.

Interpreting the Packet Results

Upon returning to the application, for most packets, there will be
result values in dp_Res1 and dp_Res2.  For most packets, if dp_Res1
is DOSTRUE, the packet returned without a problem.  If dp_Res1 is
DOSFALSE, the handler experienced an error with the packet and there
should be an error code in dp_Res2.  The error codes are defined in
<dos/dos.h>.  Note that not all packets follow this error reporting
convention.  See the ``AmigaDOS Packet Interface Specification''
article on page II-5 for more information on how individual packets
work.

Packets without dos.library Functions

Besides offering the ability to do asynchronous I/O, directly using
DOS packets also allows applications to utilize features of certain
handlers that are not available through a dos.library function.

The following packets are not available via a dos.library function as
of Release 3.0:

    ACTION_WRITE_PROTECT    ACTION_DISK_INFO (for console handlers)

If an application needs the feature that these packets provide, the
application has to send the packet to the handler.  The first two
packets are fairly straightforward and are explained in the
``AmigaDOS Packet Interface Specification'' article on page II-5 of
Amiga Mail.

The ACTION_DISK_INFO packet is peculiar because its function changes
depending on the handler.  When sent to a file system handler, it
returns information about its media.  The dos.library function Info()
uses this packet.  The ACTION_DISK_INFO packet has a different
meaning to a console handler.  When a console handler receives this
packet, it returns a pointer to the window of the open console file
handle.  When an application needs this pointer, the only way to get
it as of Release 3.0 is to send the console handler this packet.

There are two commonly used packets that an application could not
call through a dos.library function under 1.3 that now have
corresponding dos.library functions.  The packet to rename a disk,
ACTION_RENAME_DISK, is now available through the dos.library function
Relabel().  Also the ACTION_SCREEN_MODE packet acquired a dos.library
function, SetMode().

About the Examples

Two examples accompany this article.  The first, CompareIO.c, uses
packet level I/O to copy the standard input channel to the standard
output channel (as set up by the standard startup code, c.o).
CompareIO uses both synchronous and asynchronous I/O to perform the
copy and reports the time it takes to do each.  The other example,
InOutCTRL-C.c, also uses packets to copy the standard input channel
to the standard output channel, but it only uses asynchronous I/O.
The second example does a better job checking for a user break.

 CompareIO.c
 InOutCTRL-C.c


II-107: Even Faster AmigaDOS I/O

Even Faster AmigaDOS I/O

In the September/October 1992 Amiga Mail issue, there is an article by
Martin Taillefer called, ``Fast AmigaDOS I/O''. Most of the article
consists of a code listing.  The code listing is a series of special
I/O routines (plus their Autodocs) that are similar in appearance to
the dos.library synchronous I/O functions Open(), Close(), Read(), and
Write(), but they use asynchronous I/O instead.  These functions shield
the programmer from the complicated, lower-level DOS work, allowing the
application programmer to easily take advantage of the performance of
asynchronous I/O.  They are as easy to use as the synchronous
dos.library I/O calls, but they yield much higher performance.

Of course, Martin Taillefer, the guy who wrote the asynchronous I/O
routines, had to improve upon his work. Besides working out one or two
minor bugs, he has further improved the performance of the code and has
also added a new feature.  There is a new routine called SeekAsync(),
which allows an application to seek into a file while using Martin's
asynchronous DOS I/O calls.

In making these improvements, Martin has made significant changes to
the file that contains the asynchronous I/O functions, AsyncIO.c and
can be found at the end of this article.  The Autodocs for the original
asynchronous I/O functions have not changed, so they have not been
reprinted here.  This article contains only the Autodoc for
SeekAsync().  See the original article, ``Fast AmigaDOS I/O'' for the
remaining files.

 ASync.doc
 ASyncExample.c
 ASyncIO.c
 ASyncIO.h


II-113: Handling Multiple Assigns with Conventional Directories

Handling Multiple Assigns with Conventional Directories

Staff

One of the features introduced by Release 2 is Multiple Assigning. This
feature allows an AmigaDOS assign to carry over several directories which can
be on different volumes. This makes it possible to split up assigns such as
libs: and fonts:.

The article ``Directory Scanning'' on page II-49 contains an example called
find.c that illustrates scanning a path that can contain a multiassign.
However, besides being rather complicated, find.c makes a special case of
scanning assigns, which isn't necessary (find.c also did something
evil--find.c uses DOSBase's private pointer to the utility.library,
essentially using the utility.library without opening it). The method needed
to scan a multiassign directory also works on conventional directories.

Scanning a multiassign requires calling the dos.library function
GetDeviceProc() in a loop to see each directory of the multiassign. Using
GetDeviceProc(), the application doesn't have to concern itself with the
differences between assigns, multiassigns, and volumes. The application just
keeps calling GetDeviceProc() until it gets back a NULL.

struct DevProc *GetDeviceProc( STRPTR name, struct DevProc *dp );

The name can be any valid dos path. If there is a device name present,
GetDeviceProc() will find the device's entry in the dos list and copy some
information into a DevProc structure:

struct DevProc {
    struct MsgPort *dvp_Port;   /* Device's Message port, also called a Process identifier */
    BPTR            dvp_Lock;   /* Lock on root of assign or lock on root of volume */
    ULONG           dvp_Flags;
    struct DosList *dvp_DevNode;/* DON'T TOUCH OR USE! */
};

The important fields here are dvp_Lock and dvp_Port. The dvp_Lock field is a
lock on the root of the object named in GetDeviceProc(). It serves as a
starting point in locating the named object. If the object name contains an
assign (i.e. ``libs:''), dvp_Lock is the root of the assign. For example, on a
typical Release 2 system, the libs: assign refers to the libs directory on the
System2.0: volume. Calling GetDeviceProc() on ``libs:'' in this case will
yield a lock on System2.0:libs.

If the named object contains a dos volume, dvp_Lock is either a lock on the
root of the dos volume or NULL. If the object named in GetDeviceProc()
contains a non-filesystem device (i.e., ``ser:'', ``par:'', ``prt:'', etc.) or
it does not contain a device name, dvp_Lock is NULL.

The dvp_Port field points to a message port. This message port is connected to
the handler process of a DOS device. The handler process controls a DOS
device. DOS functions (like the Lock() function) use this message port to talk
to the handler process of the named object. For example, from the ``libs:''
example above, the dvp_Port field refers to the message port of the handler
process for the System2.0: volume.

Note that dvp_Lock is only a lock on the root of the named object. If the
named object is a path several directories deep (for example,
libs:gadgets/colorwheel.gadget), it's up to the application to handle the rest
of the path. The application also has to handle the case where the named
object is a path without a device name.

Although an application can send DOS packets directly to the message port
(dvp_Port) of a handler process, normally it is easier to use functions from
dos.library. The multilist.c example uses the Lock() function to lock the
named object. Multilist has to do something a little unorthodox to use Lock().
Lock() accepts a path name to the object to lock. Lock() understands absolute
paths (i.e. paths with a logical device name like ``df1:'' or ``libs:'') and
relative paths. If Lock() receives an absolute path name, Lock() can find the
device's handler process using the logical device name in the absolute path.
For a relative path, Lock() does not have enough information to find the named
object, so it assumes the path is relative to the current directory and file
system (each process has a current directory and file system).

This makes Lock() a little more difficult to use in multilist.c because, when
processing an absolute path, multilist has to process the logical device name
separately from the rest of the path. It has to use GetDeviceProc() to find
the root of a logical device name (which can be an assign, multiassign, volume
name, etc.) then it has to strip the logical device name from the absolute
path. Without a logical device name, the path has become relative rather than
absolute. The path is now relative to dvp_Lock and dvp_Port. In order for
Lock() to work with this relative path, multilist must temporarily set the
current directory and file system to the values in dvp_Lock and dvp_Port,
respectively.

Note that the Autodoc for GetDeviceProc() says to check IoErr() for
ERROR_NO_MORE_ENTRIES after receiving a NULL from GetDeviceProc(). Due to a
bug, DOS does not set the error value correctly. Also note that the Autodoc
says to check the DevProc structure's dvp_Flags field for the DVPF_ASSIGN
flag. This was necessary in the 2.00 and 2.01 releases of the operating system
due to a bug in DOS, but is no longer necessary.

The following example, multilist.c, accepts an arbitrary path name and lists
the contents of it. The function DoAllAssigns() does all of the multiassign
work. DoAllAssigns() accepts a path and a function pointer. It gets a lock on
the object named in the path, and passes the lock to the function. This
example is based on a Usenet posting by Randell Jesup.

 multilist.c


III-1: Using SetFunction() in a Debugger

By Ewout Walraven

The Amiga OS consists of a set of libraries (and devices), which reside in
ROM or on disk.  These libraries provide a set of routines which are
shared by the Amiga tasks (hence the name shared library).

The way in which an Amiga library is organized allows a programmer to
change where the system looks for a library routine.  Exec provides a
function to do this: SetFunction().  The SetFunction() routine redirects a
library function call to an application-supplied function (Although this
article doesn't address it, SetFunction() can also be used on Exec
devices).  The SetPatch utility uses SetFunction().  SetPatch is a program
which replaces some OS routines with improved ones, primarily to fix bugs
in ROM libraries.

Normally, programs should not attempt to ``improve'' library functions.
Because most programmers do not know exactly what system library functions
do internally, OS patches can do more harm than good. However, a useful
place to use SetFunction() is in a debugger.  Using SetFunction(), a
debugger can reroute library calls to a debugging function.  The debugging
function can inspect the arguments to a library function call before
calling the original library routine (if everything is OK).  Such a
debugging function doesn't do any OS patching, it merely inspects.

SetFunction() is also useful for testing an application under conditions
it does not encounter normally.  For example, a debugging program can
force a program's memory allocations to fail or prevent a program's window
from opening.  This allows a programmer to find bugs that only arise under
special circumstances.  Some programs that use SetFunction() for debugging
purposes are IO_Torture, Memoration and MungWall.  A real watchdog is
Wedge, which, as its name implies, allows you to install a wedge for
practically every function of a standard library and inform you about the
register values passed to the function.  These types of debugging tools
helped debug release 2.0 of the OS and found bugs and 1.3 dependencies in
commercial applications.

Although useful, SetFunction()ing library routines poses several problems.
First of all, the wedge routine will have to be re-entrant, like all Exec
library functions.  Secondly, there is always a problem with removing the
wedge.  If another task has SetFunction()ed the same library routine as
the debugger (a very real possibility), it is not normally possible to
remove the first wedge, since the other task depends on the presence of
your task's code.  This would force your task to hang around, waiting for
the other task(s) to remove their wedges. You also need to know when it is
safe to unload your debugging code. Removing it while another task is
executing it will quickly lead to a hopelessly crashed system.

For those of you who might be thinking about writing down the ROM
addresses returned by SetFunction() and using them in some other programs:
Forget It.  The address returned by SetFunction() is only good on the
current system at the current time.  Blindly jumping into ROM will cause
your programs to break.

 Exec Library Structure
 Caveats
 An Example Debugger


Exec Library Structure

When a library is opened for the first time, a library node structure, a
jump table, and a data area are created in RAM.

   Fig. 1 - An Exec Library Base in RAM

The library node structure address is the base address of the library.
OpenLibrary() returns this base address.  The library's jump table, which
directly precedes the library node in RAM, consists of six byte long
entries containing a jump instruction (JMP) to a corresponding library
function.  The jump table is initialized when Exec opens the library.
Each function's entry in the jump table (also known as a vector) is always
a constant (negative) offset from the library base. These fixed negative
offsets are known as Library Vector Offsets (LVO). Note that the first
four function vectors are reserved for use by Exec. They point to standard
library functions for opening, closing, and expunging the library, plus
there is space reserved for a fourth function vector.  The base address of
a library is determined dynamically when the library is loaded into RAM.
See the Exec introduction chapter in the ROM Kernel Manual: Libraries and
Devices for more information on libraries.

The SetFunction() routine replaces an LVO address with a new address
which points to the wedge routine.  SetFunction() returns the old vector
address, which the wedge routine can use to call the original library
function from within the wedge.  Note that if another task
SetFunction()s the same library function, SetFunction() returns the
address of your debugging routine (to the second task)  as the old
vector.  At that point your task can no longer exit since that would
mean that that other task has an invalid pointer to your function and
will most likely crash the system when it tries to use your function.

   Fig. 2 - Calling a Library Function

There is a way around this problem.  Instead of SetFunction()ing a library
function with the address of your wedge code, build your own jump table
and use the addresses of its entries as arguments to SetFunction() calls.
This method allows you to unload your code when you want to because if
another task SetFunction()s your routine, that task will get a pointer to
a jump table entry, not your routine.

   Fig. 3 - Using SetFunction() with a Jump Table

   Fig. 4 - Another Debugger SetFunction()s an Entry in the Jump Table

Now when you want to exit, all you need to do is replace the entries in
your jump table which point to your functions with the original function
vectors which were returned by SetFunction().  By not freeing the memory
allocated for the jump table your task can exit any time, regardless of
other tasks which SetFunction()ed the same library routines.  The other
task(s) will never know what happened.

   Fig. 5 - Original Debugger Removes its Debugging Routine

The next time the debugger is executed, it looks for the jump table it
left behind and replaces the entries in it with pointers to its own
functions.  Incidentally, this is an easy way to provide a mechanism to
determine if your debugging program has already been installed.


Caveats

There are some things to keep in mind when using SetFunction().  The
scheme described above can force a second task to hang around forever if
it SetFunction()ed a routine before you, since your debugger will not
normally release its handle on the second task's function.  Whenever
possible, install jump table based debuggers before any other
SetFunction()ing program (but after SetPatch of course).

Some debuggers interpret the return address of the caller.  When a
debugger jumps (JMP) to (what it thinks is) the original function, there
will be no problem.  However, if a debugger performs a JSR to a second
debugging function which interprets the return address, the second
debugging function will receive the first debugging function's return
address (the one that performed the JSR) rather than the return address of
the application that called the library function in the first place. This
can confuse the second debugger.  Two good examples of this are Scratcher
and MungWall, which both SetFunction() FreeMem().  MungWall looks at the
return address of the caller.  Since Scratcher calls the old FreeMem()
function with a JSR instruction, it would mislead MungWall if run after
it.  Preferably, debuggers that interpret the return address should be
started after other debuggers.

Although it is not common, some library functions call other library
functions and depend on certain scratch registers to contain valid values.
SetFunction()ing one of these functions is likely to change the values in
these scratch registers, leading to problems.  Because these dependencies
are not always documented, you might innocently run into one.  Scratcher
is an excellent tool for finding such dependencies.

In the past, some system functions did not have a JMP vector in their
entry in the LVO table.  Instead, the actual function was in the jump
table.  SetFunction() will not work on such a function.

Any debugging routine should be careful not to call the function it has
patched with SetFunction(), either directly or indirectly.  Doing so will
likely cause a stack overflow and crash the machine.  This may seem a bit
obvious until you consider how easy it is to indirectly call a system
routine.   Many system functions are not atomic.  They have to call lower
level system functions.  If you call a higher level system functions in
the debugging code and you have SetFunction()ed one of the routines the
high level function uses, the machine will probably crash from a stack
overflow.

Using SetFunction() on disk-based libraries and devices requires a little
extra care.  Unlike a ROM library, libraries (and devices) loaded into RAM
can be expunged when memory gets low.  To prevent the system from
expunging a library (or device) you have SetFunction()ed, either keep the
library (or device) opened, or use SetFunction() to patch the library's
expunge function.

Remember that when you install a wedge, another program can call it almost
instantly.  Because of this, the wedge should be completely set up before
you install it.

Note that dos.library is now a standard library and can be SetFunction()ed
as of V36.  Before V36 you would have to Forbid(), get the six original
bytes of the entry in the function vector table, install the new vector,
perform a SumLibrary() and then Permit().

If it is necessary to put debugging code into a Forbid() or Disable()
state, keep it in that state for as little time as possible to limit
system slowdown.  Remember that you cannot Disable() for more than 250
microseconds.  Be sure to read the Disable()/Enable() Autodocs before
using them.


An Example Debugger

The usage of SetFunction() is shown by the example debugging program at
the end of this article, ISpy.  ISpy uses a semaphore to gain access to
its jump table.  This jump table contains pointers to the wedge routines.
When executed, each wedge routine puts a shared lock on the semaphore to
indicate that the code is being executed.  To get an idea of who is
calling the debugger entries, ISpy uses a little assembler stub to load a4
with the address of the stack of the caller and calls a C routine where
the actual (simple) argument checking is done.  When ISpy is signalled to
exit, it tries to get an exclusive lock on the semaphore in a Forbid()en
state.  If this succeeds, it can safely assume its code is not being
executed at the moment and can therefore place the original function
vectors in the jump table and exit, leaving the semaphore behind.  This
semaphore is also used to check whether ISpy is already installed.  If so,
the new instance will exit immediately. Because of the use of shared
semaphore locks, this program will only run with V37.  By using a global
counter (which is incremented each time a function is entered and
decremented when it is exited) ISpy can be adapted to V33.  Because of the
way ISpy is set up, it is very easy to add argument checking front ends
for functions, and have multiple versions of ISpy for different libraries.

Memoration and Scratcher by Bill Hawes.  IO_Torture by Bryce Nesbitt.
Wedge and DevMon by Carolyn Scheppner.  MungWall by Ewout Walraven
(inspired by Memwall by Randell Jesup and MemMung by Bryce Nesbitt).


III-11: 68040 Compatibility Warning

by Michael Sinz

    editor's note: the new exec.library routines referred to in this
    article are part of the 2.04 OS release.

Now that Motorola's 68040ä CPU is available, it will not be long before it
appears in Amiga-based products.  In fact, many Amiga magazines already
have ads for 3rd party 68040 CPU cards.

The 68040 is a much more powerful CPU than its predecessors.  It has 4K of
cache memory for instructions and another 4K cache for data.  The reason
for these two separate caches is so that the CPU core can access data and
CPU instructions at the same time.

Although the 68040 provides greater performance it also brings with it
greater compatibility problems.  Just the fact that the caches are so much
larger than Motorola's 68030 CPU can cause problems.  However, this is not
its biggest obstacle.

The 68040 data cache has a mode that can make the system run much faster
in most cases.  It is called CopyBack mode.  When a program writes data to
memory in this mode, the data goes into the cache but not into the
physical RAM.  That means that if a program or a piece of hardware were to
read that RAM without going through the data cache on the 68040, it will
read old data. CopyBack mode effects two areas of the Amiga: DMA devices
and the CPU's instruction reading.

CopyBack mode effects DMA devices because they read and write data
directly to memory.  Using DMA with CopyBack mode requires a cache flush.
If a DMA device needs to read RAM via DMA, it must first make sure that
data in the caches has been written to memory.  It can do this by calling
the Exec function CachePreDMA().  If a DMA device is about to write to
memory, it should call CachePreDMA() before the write, do the DMA write,
and then call CachePostDMA(), which  makes sure that the CPU uses the data
just written to memory.

An added advantage of using the CachePreDMA() and CachePostDMA() functions
is that they give the OS the chance to tell the DMA device that the
physical addresses and memory sizes are not the same.  This will make it
possible in the future to add features such as virtual memory.  See the
Autodocs for more information on these calls (the Autodocs have been
included in this article). The other major compatibility problem with the
68040's CopyBack mode is with fetching CPU instructions.  CPU instructions
have to be loaded into memory so the CPU can copy them into its
instruction cache.  Normally, instructions that will beexecuted are
written to memory by the CPU (i.e. loading a program from disk).  In
CopyBack mode, anything the CPU writes to memory, including CPU
instructions, doesn't actually go into memory, it goes into the data
cache.  If instructions are not flushed out of the data cache to RAM, the
68040 will not be able to find them when it tries to copy them into the
instruction cache for execution.  It will instead find and attempt to
execute whatever garbage data happened to be left at that location in RAM.

To remedy this, any program that writes instructions to memory must flush
the data cache after writing.  The V37 Exec function CacheClearU() takes
care of this.  Release 2.0 of the Amiga OS correctly flushes the caches as
needed after it does the LoadSeg() of a program (LoadSeg() loads Amiga
executable programs into memory from disk).  Applications need to do the
same if they write code to memory.  One such example was the article
``Creating Multiple Processes with Re-entrant Code'' from the
November/December 1989 issue of Amiga Mail (Volume I).  For that example
to work with the 68040's CopyBack mode, it needs to flush the cache before
it asks the system to execute the code it wrote to memory (which may still
be in the cache).  It can do that by calling CacheClearU() before the call
to CreateProc().  In C that would be:

extern struct ExecBase *SysBase;

    . . .

    /* If we are in 2.0, call CacheClearU() before CreateProc() */
    if (SysBase->LibNode.lib_Version >= 37) CacheClearU();

    /* Now do the CreateProc() call... */
    proc=CreateProc(... /* whatever your call is like */ ...);

    . . .

For those of you programming in assembly:

**************************************************************************
* Check to see if we are running in V37 ROM or better.  If so,
* we want to call CacheClearU() to make sure we are safe on future
* hardware such as the 68040.  This section of code assumes that
* a6 points at ExecBase.  a0/a1/d0/d1 are trashed in CacheClearU()
*
            cmpi.w  #37,LIB_VERSION(a6)     ; Check if exec is >= V37
            bcs.s   TooOld                  ; If less than V37, too old...
            jsr     _LVOCacheClearU(a6)     ; Clear the cache...
TooOld:
*
**************************************************************************

Note that CreateProc() is not the only routine where CopyBack mode could
be a problem.  Any program that copies code into memory for execution that
is not done via LoadSeg() (for example, ``Using SetFunction() in a
Debugger'' from the March/April 1991 issue of Amiga Mail), you will need
to call CacheClearU().  Many input.device handlers have been known to
allocate and copy the handler code into memory and then exit back to the
system.  These programs also need to have this call in them.  The above
code will work under pre-2.0 versions of the OS, and will do the correct
operations in 2.04 (and beyond).

Heeding these compatibility guidelines will allow the system to enable
CopyBack mode, enhancing the performance of the Amiga considerably.
Ignoring these guidelines will prevent the Amiga from taking advantage of
CopyBack mode and possibly other advanced features of the 68040 (and
beyond).

 CacheControl      CacheClearU       CachePreDMA
 CacheClearE       CachePostDMA


CacheControl

exec.library/CacheControl                        exec.library/CacheControl

NAME
    CacheControl - Instruction & data cache control

SYNOPSIS
    oldBits = CacheControl(cacheBits,cacheMask)
    D0                     D0        D1

    ULONG CacheControl(ULONG,ULONG);

FUNCTION
    This function provides global control of any instruction or data
    caches that may be connected to the system.  All settings are
    global -- per task control is not provided.

    The action taken by this function will depend on the type of
    CPU installed.  This function may be patched to support external
    caches, or different cache architectures.  In all cases the function
    will attempt to best emulate the provided settings.  Use of this
    function may save state specific to the caches involved.

    The list of supported settings is provided in the exec/execbase.i
    include file.  The bits currently defined map directly to the Motorola
    68030 CPU CACR register.  Alternate cache solutions may patch into
    the Exec cache functions.  Where possible, bits will be interpreted to
    have the same meaning on the installed cache.

INPUTS
    cacheBits - new values for the bits specified in cacheMask.

    cacheMask - a mask with ones for all bits to be changed.

RESULT
    oldBits   - the complete prior values for all settings.

NOTE
    As a side effect, this function clears all caches.

    Selected bit definitions for Cache manipulation calls from
    <exec/execbase.i>

    BITDEF  CACR,EnableI,0          ;Enable instruction cache
    BITDEF  CACR,FreezeI,1          ;Freeze instruction cache
    BITDEF  CACR,ClearI,3           ;Clear instruction cache
    BITDEF  CACR,IBE,4              ;Instruction burst enable
    BITDEF  CACR,EnableD,8          ;68030 Enable data cache
    BITDEF  CACR,FreezeD,9          ;68030 Freeze data cache
    BITDEF  CACR,ClearD,11          ;68030 Clear data cache
    BITDEF  CACR,DBE,12             ;68030 Data burst enable
    BITDEF  CACR,WriteAllocate,13   ;68030 Write-Allocate mode (must
                                    ;always be set)
    BITDEF  CACR,EnableE,30
*
*   With this bit set, the external cache states then match the internal
*   cache states.  That is, if the internal data cache is turned on,
*   the external data cache is turned on.  Same for instruction caches.
*   If the external cache only exists as a single unified cache,
*   this will turn on if the data cache is on.  (This is done for
*   compatibility reasons)  With this bit clear, the external caches
*   are turned off.

    BITDEF  CACR,CopyBack,31    ;Master enable for copyback caches

    BITDEF  DMA,Continue,1      ;Continuation flag for CachePreDMA
    BITDEF  DMA,NoModify,2      ;Set if DMA does not update memory

SEE ALSO
    exec/execbase.i, CacheClearU, CacheClearE


CacheClearE

exec.library/CacheClearE                          exec.library/CacheClearE

NAME
    CacheClearE - Cache clearing with extended control (V37)

SYNOPSIS
    CacheClearE(address,length,caches)
                a0      d0     d1

    void CacheClearE(APTR,ULONG,ULONG);

FUNCTION
    Flush out the contents of the CPU instruction and/or data caches.
    If dirty data cache lines are present, push them to memory first.

    Motorola CPUs have separate instruction and data caches.  A data
    write does not update the instruction cache.  If an instruction is
    written to memory or modified, the old instruction may still exist
    in the cache.  Before attempting to execute the code, a flush of
    the instruction cache is required.

    For most systems, the data cache is not updated by Direct Memory
    Access (DMA), or if some external factor changes shared memory.

    Caches must be cleared after *any* operation that could cause
    invalid or stale data.  The most common cases are DMA and modifying
    instructions using the processor.

    Some examples:
                    Self modifying code
                    Building Jump tables
                    Run-time code patches
                    Relocating code for use at different addresses.
                    Loading code from disk

INPUTS
    address - Address to start the operation.  This may be rounded
              due to hardware granularity.
    length  - Length of area to be cleared, or $FFFFFFFF to indicate all
              addresses should be cleared.
    caches  - Bit flags to indicate what caches to affect.  The current
              supported flags are:
                    CACRF_ClearI    ;Clear instruction cache
                    CACRF_ClearD    ;Clear data cache
              All other bits are reserved for future definition.

NOTES
    On systems with a copyback mode cache, any dirty data is pushed
    to memory as a part of this operation.

    Regardless of the length given, the function will determine the most
    efficient way to implement the operation.  For some cache systems,
    including the 68030, the overhead partially clearing a cache is often
    too great.  The entire cache may be cleared.

    For all current Amiga models, Chip memory is set with Instruction
    caching enabled, data caching disabled.  This prevents coherency
    conflicts with the blitter or other custom chip DMA.  Custom chip
    registers are marked as non-cacheable by the hardware.

    The system takes care of appropriately flushing the caches for normal
    operations.  The instruction cache is cleared by all calls that
    modify instructions, including LoadSeg(), MakeLibrary() and
    SetFunction().

SEE ALSO
    exec/execbase.i, CacheControl, CacheClearU


CacheClearU

exec.library/CacheClearU                          exec.library/CacheClearU

NAME
    CacheClearU - User callable simple cache clearing (V37)

SYNOPSIS
    CacheClearU()

    void CacheClearU();

FUNCTION
    Flush out the contents of any CPU instruction and data caches.
    If dirty data cache lines are present, push them to memory first.

    Caches must be cleared after *any* operation that could cause
    invalid or stale data.  The most common cases are DMA and modifying
    instructions using the processor.  See the CacheClearE() autodoc
    for a more complete description.

    Some examples of when the cache needs clearing:
                    Self modifying code
                    Building Jump tables
                    Run-time code patches
                    Relocating code for use at different addresses.
                    Loading code from disk

SEE ALSO
    exec/execbase.i, CacheControl, CacheClearE


CachePostDMA

exec.library/CachePostDMA                        exec.library/CachePostDMA

NAME
    CachePostDMA - Take actions after to hardware DMA  (V37)

SYNOPSIS
    CachePostDMA(vaddress,&length,flags)
                 a0       a1      d0

    CachePostDMA(APTR,LONG *,ULONG);

FUNCTION
    Take all appropriate steps after Direct Memory Access (DMA).  This
    function is primarily intended for writers of DMA device drivers.  The
    action will depend on the CPU type installed, caching modes, and the
    state of any Memory Management Unit (MMU) activity.

    As implemented
            68000 - Do nothing
            68010 - Do nothing
            68020 - Do nothing
            68030 - Flush the data cache
            68040 - Flush matching areas of the data cache
            ????? - External cache boards, Virtual Memory Systems, or
                    future hardware may patch this vector to best emulate
                    the intended behavior.
                    With a Bus-Snooping CPU, this function my end up
                    doing nothing.

INPUTS
    address - Same as initially passed to CachePreDMA
    length  - Same as initially passed to CachePreDMA
    flags   - Values:
                    DMA_NoModify - If the area was not modified (and
                    thus there is no reason to flush the cache) set
                    this bit.

SEE ALSO
    exec/execbase.i, CachePreDMA, CacheClearU, CacheClearE


CachePreDMA

exec.library/CachePreDMA                          exec.library/CachePreDMA

NAME
    CachePreDMA - Take actions prior to hardware DMA  (V37)

SYNOPSIS
    paddress = CachePreDMA(vaddress,&length,flags)
    d0                     a0       a1      d0

    APTR CachePreDMA(APTR,LONG *,ULONG);

FUNCTION
    Take all appropriate steps before Direct Memory Access (DMA).  This
    function is primarily intended for writers of DMA device drivers.  The
    action will depend on the CPU type installed, caching modes, and the
    state of any Memory Management Unit (MMU) activity.

    This function supports advanced cache architectures that have
    "copyback" modes.  With copyback, write data may be cached, but not
    actually flushed out to memory.  If the CPU has unflushed data at the
    time of DMA, data may be lost.

    As implemented
            68000 - Do nothing
            68010 - Do nothing
            68020 - Do nothing
            68030 - Do nothing
            68040 - Write any matching dirty cache lines back to memory.
                    As a side effect of the 68040's design, matching data
                    cache lines are also invalidated -- future CPUs may
                    be different.
            ????? - External cache boards, Virtual Memory Systems, or
                    future hardware may patch this vector to best emulate
                    the intended behavior.
                    With a Bus-Snooping CPU, this function my end up
                    doing nothing.

INPUTS
    address - Base address to start the action.
    length  - Pointer to a longword with a length.
    flags   - Values:
                    DMA_Continue - Indicates this call is to complete
                    a prior request that was broken up.

RESULTS
    paddress- Physical address that coresponds to the input virtual
              address.
    &length - This length value will be updated to reflect the contiguous
              length of physical memory present at paddress.  This may
              be smaller than the requested length.  To get the mapping
              for the next chunk of memory, call the function again with
              a new address, length, and the DMA_Continue flag.

NOTE
    Due to processor granularity, areas outside of the address range
    may be affected by the cache flushing actions.  Care has been taken
    to ensure that no harm is done outside the range, and that activities
    on overlapping cache lines won't harm data.

SEE ALSO
    exec/execbase.i, CachePostDMA, CacheClearU, CacheClearE


III-17: Signalling with SIGF_SINGLE

Signalling with SIGF_SINGLE

by John Orr

The ROM Kernel Reference Manuals state that sixteen of a task's 32
signal bits are reserved for the operating system's private use, but,
like any good rule, there is an exception.  One of these sixteen
bits, the SIGF_SINGLE bit, can be useful to some applications, if
used correctly.

Many system functions need to put their task to sleep while waiting
for a single event, which requires using one of the task's signals.
Rather than forcing each of these system functions to allocate a
signal, then Wait(), then deallocate the signal, the operating system
has permanently allocated one signal, the SIGF_SINGLE, for this type
of signalling.  When a system function needs stop a task to Wait()
for a single signal, it can use SIGF_SINGLE.

The only purpose a program can use SIGF_SINGLE for is Wait()ing
because the task cannot call any system functions while it is using
SIGF_SINGLE.  A program that calls system functions while using
SIGF_SINGLE can cause itself and the operating system serious
problems because the system functions can use SIGF_SINGLE as well.
If a program calls a system function while using SIGF_SINGLE, two bad
things can happen:

1) The errant task's event takes place before the system function
waits on SIGF_SINGLE (or while the system function is waiting on
SIGF_SINGLE).  In this case, the system function will think its event
has taken place because its signal became set.  The errant task will
never find out that its event has taken place, as the system function
will clear the SIGF_SINGLE bit after Wait()ing on it.

2) The errant task's event and the system function's event take place
while the system function is waiting on SIGF_SINGLE.  In this case,
the system function will function normally, clear the SIGF_SINGLE
bit, and exit.  The errant task will never know that its event has
taken place.

Before Wait()ing on SIGF_SINGLE, clear it using SetSignal():

    SetSignal(0L, SIGF_SINGLE);

This step is necessary because it is possible that the last system
function that used the SIGF_SINGLE signal did not clear the
SIGF_SINGLE bit.

Also, an application should not wait on other signals while it is
waiting on SIGF_SINGLE.  Waiting on other signals at the same time
makes it possible for a program to wake up while the SIGF_SINGLE is
still outstanding.  If this happens, the program will still have to
go back to sleep, which requires calling a system function.

SIGF_Single.c is a simple example of using the SIGF_SINGLE signal.
It starts a child process and waits for that child process to signal
the main process using the SIGF_SINGLE signal.

 SIGF_Single.c


III-19: Memory Pools

Memory Pools

by Mark Ricci

A memory pool is a block of memory that an application allocates for
all its memory needs.  The application draws from this pool rather
than the system's free memory list whenever it requires memory.

Memory pools add to the efficiency of the system and applications in
two ways.  The first is a potential decrease in memory fragmentation.
Memory fragmentation is a condition where system memory is made up of
blocks of allocated memory interspersed with blocks of free memory.
The second benefit of memory pools is faster memory allocations and
deallocations.

System memory starts out as one large, contiguous block.  The first
time a task allocates memory, the system memory is broken into two
blocks--allocated memory and free memory.  As different tasks
allocate memory, the allocated memory block increases and the free
memory block decreases as shown in Figure 1. The memory blocks remain
contiguous until a task frees some memory.  At that point, a gap may
appear in the block of allocated memory if the newly freed block was
not the last one allocated.  While this creates additional free
memory, it also means that free memory is now two or more
non-contiguous fragments instead of one contiguous block.  In a
multitasking system like the Amiga, tasks are constantly allocating
and freeing memory which can create many gaps in memory.  As a
result, free memory can consist of many small pieces rather than one
large block (Figure 2).

This can lead to problems if an application needs a large block of
contiguous memory.  For example, consider an application that needs a
block of memory 200,000 bytes long.  If free memory is severely
fragmented, the largest block of free memory may only be 150k.  The
system may have five megabytes of free memory available, but that
five megabytes of memory is broken into fragments no larger than
150k.  In this case, the application cannot allocate its 200k.

By having an application take a pool of memory and allocate from it,
fragmentation of system memory is decreased.  An application may
require six allocations ranging from 20 to 678 bytes in size which
can be scattered throughout system memory.  However, if those same
six allocations are taken from a pool, the fragmentation occurs
within the pool, but as far as the system is concerned, it's missing
one large block instead of six small ones.

An application using a memory pool will have faster memory
allocations because the memory list of a pool is smaller, and
therefore easier to traverse than the memory list of the system
memory.  For deallocations, it's even faster because deleting the
pool itself deletes all the individual allocations made from it
instead of having to deallocate each piece that was allocated.

Memory Pool Organization

A memory pool consists of units called puddles.  Other than that, it
has no formal organization.  There is no pool structure defined
anywhere.  All you know about a pool is its address.  Exec's pool
manager handles the rest of the details.

When you create a pool, you specify the size of its puddles and a
threshold value, not the size of the pool.  This is because memory
pools are dynamic, they have no fixed size.  The pool manager takes
the memory for your application from the puddles.  As you require
memory, the pool manager expands the pool by adding puddles, and as
you free memory, the pool manager shrinks the pool by deleting
puddles.

The size of the puddles is important because the pool manager will
try to use as much of a puddle as possible before adding a new
puddle.  Each time you allocate memory from the pool, the pool
manager takes the memory from a puddle unless an allocation exceeds
the amount of memory remaining in a puddle.  If the allocation
request exceeds the memory remaining in a puddle, the pool manager
adds a new puddle.  If the allocation exceeds the pool's puddle size,
the pool manager will create a special oversized puddle to
accommodate the application.

The key is to use all the drops in a puddle.  If you create a pool
with puddles of 200 bytes and allocate 150 bytes at a time, you'll
waste 50 bytes in every puddle.  Set the puddle size in accordance
with your memory requirements.

The threshold value is the size of the largest allocation to use
within a single puddle.  An allocation request larger than the
threshold value causes the pool manager to add a new puddle.
Ideally, the threshold value should be the size of the largest
allocation you will make.

The relationship between puddle size and threshold can be tuned for
optimal utilization of a pool.   Threshold sizes cannot exceed puddle
sizes and are recommended to be one half the puddle size so that you
can fit two of your largest allocations in a single puddle.  However,
if you are going to have a mix of large and small allocations, you
might want to set a threshold value that allocates a majority of a
puddle for a large allocation, and then uses up the remainder of the
puddle with the smaller allocations.

Creating a Memory Pool

You create a memory pool by calling CreatePool() specifying the
puddle size, threshold size, and memory type.  The memory type is
borrowed from the AllocMem() function and is comprised of the MEMF_
flags defined in <exec/memory.h>.  See the Autodoc for AllocMem() for
more information on those flags.

If successful, CreatePool() returns the address of the memory pool.

    APTR mem_pool;

    if (mem_pool = CreatePool(MEMF_FAST,4096,2048))
    {
        .  .  .
    }

    else
        printf("Pool could not be created.\n");

The example above attempts to create a pool of Fast memory with a
puddle size of 4096 bytes and a threshold size of 2048 bytes.

If your application requires memory of different types (for example,
Chip memory and Fast memory), it must create a pool for each type.

Take note, again, that all you know about a pool is its address.  Do
not poke around it trying to figure out its organization.  It's
private for a reason!

Allocating Memory from a Pool's Puddles

Memory is obtained from a pool's puddles by calling AllocPooled().
AllocPooled() requires a pointer to the memory pool and the size of
the memory block needed.  If successful, AllocPooled() returns a
pointer to the memory.

    struct timerequest *TimerReq;

    if (TimerReq = AllocPooled(mem_pool, sizeof(struct timerequest))
    {
        .  .  .
    }

    else
        printf("Memory could not be allocated.\n");

Freeing Memory from a Pool's Puddles

An application can free a block of memory it allocated from a pool by
calling FreePooled():

    FreePooled(mem_pool, mem_drop, mem_size);

This function requires a pointer to the memory pool (mem_pool), a
pointer to the block of memory being freed (mem_drop), and the size
of the memory being freed (mem_size).

Deleting a Memory Pool

A memory pool is deleted by calling DeletePool() with a pointer to
the memory pool you wish to delete.

    DeletePool(mem_pool);

Deleting a pool also frees the puddles in it.  This is quicker than
doing individual FreePooled() calls.  For example, a text editor will
allocate memory for each line of the file being edited.  When the
editor is exited, each of the allocations has to be freed.  With
DeletePool(), it would take only one call instead of many.

Why Use Pools When You Can Allocate Memory Yourself?

You could simulate memory pools yourself by allocating the memory you
think you'll need and then using it as you go along.  You'll also
have to keep track of your usage and if you exceed your allocation,
you will have to allocate additional memory.  Another potential
problem is that unlike pools where you dynamically get memory, the
allocation scheme requires you to attempt one large allocation, which
may fail, and then requires at least two smaller allocations.  At
that point, you're no farther ahead than you were before.

With pools, you have the pool manager to handle all the details of
allocating memory.  You can sit back and create the pool, allocate
memory from the puddles and free the pool when you're done.  That's a
lot easier than doing it yourself.

Here's an additional incentive for using memory pools:

Future memory technologies will be implemented through pools.

The example below illustrates the use of memory pools instead of
allocating system memory.

 PoolTime.c


III-25: Quick Interrupts

Quick Interrupts

by Michael Sinz

    [Editor's note: This article was written from the
    programmer's perspective, and doesn't discuss any of
    the hardware issues.  See the ``Appendix K: Zorro
    Expansion Bus'' section of the third edition of the
    Amiga Hardware Reference Manual for more information.]

One of the features of the Zorro III bus is the Quick Interrupt, also
known as the vectored interrupt.  This feature allows Zorro III
hardware to supply a vector number to the system when an interrupt
occurs.  The system uses this vector number to go directly to an
interrupt routine.

Conventional Amiga Interrupts

The Amiga handles normal interrupts from Zorro II cards using an
interrupt server chain.  There are two interrupts available from the
Zorro II bus, the PORTS and EXTER interrupt server chains.  If a driver
for a Zorro II card needs to use an interrupt, it adds an interrupt
routine to the appropriate chain.  When the interrupt occurs, Exec
calls each routine in the interrupt chain, which are sorted in priority
order.  Exec continues until it finds the routine that corresponds to
the device that triggered the interrupt.

The server chain allows several routines to share a single interrupt.
This means that several devices trigger the same interrupt, so each
interrupt routine must do some processing to determine if its card
triggered the interrupt or if some other source caused the interrupt.
For example, an interrupt routine might examine a register on its card
to determine that the card triggered the interrupt.

Although this scheme allows unrelated pieces of software to easily
share an interrupt, it can make the interrupt overhead rather high.
These two interrupt server chains also handle interrupts from the CIA
chips, which are used to trigger a variety of events.  As a result,
these server chains can contain a multitude of interrupt routines.

Consider what happens when a Zorro II card generates a PORTS interrupt.
Exec has to perform some set up and then step through the PORTS server
chain.  Exec calls each interrupt routine in priority order looking for
the routine that services this interrupt.  If there are 20 interrupt
routines of higher priority than the card's interrupt routine in the
server chain, Exec has to call 20 other routines before it gets to the
correct routine.

Zorro III Quick Interrupts

Quick interrupts avoid the overhead involved in Exec's interrupt server
chains.  Exec only helps set up the quick interrupt, which it does via
the exec.library function ObtainQuickVector() (see the Autodoc at the
end of this article).  Once Exec has set up the quick interrupt
routine, it does not intervene.  Unlike conventional Amiga interrupt
routines, which are called as subroutines from Exec's main interrupt
code, the Amiga jumps directly to the quick interrupt routine using a
private vector.  This behavior requires quick interrupt routines to
take some special precautions.

There are two important differences between a conventional Amiga
interrupt routine and a quick quick interrupt routine.  A quick
interrupt routine must save and restore all of the registers it
changes, including D0, D1, A0, and A1.  It must do this because, unlike
regular interrupt routines, Exec doesn't do it for you.  Also, a quick
interrupt routine ends with a RTE (return from exception) instruction.

If your quick interrupt routine is 100% self-contained and does not
access any operating system structures or routines, then the work is
rather simple.  Just save the registers you use, perform your interrupt
processing, restore the registers, and end with an RTE.  If, however,
the routine needs to call the OS or use an OS structure, it must check
if the interrupt has been delayed.  This is necessary in case the
interrupt hit the CPU just after the CPU had told the hardware to hold
off interrupts (see the Autodoc for ObtainQuickVector() to find out how
to perform this test).

As the Amiga OS is a dynamic operating system, quick interrupts are
allocated by the OS.  If your hardware/software wants to use a quick
interrupt, it must allocate a vector with ObtainQuickVector().  This
routine accepts a pointer to the quick interrupt code (not a pointer to
an Interrupt structure).  If Exec installed the vector,
ObtainQuickVector() returns the vector number.  When the quick
interrupt occurs, the Zorro III card sends this vector number to the
CPU, which tells the CPU where the interrupt code is.

ObtainQuickVector() returns 0 if there are no more vectors.  Since the
number of vectors is limited, any Zorro III device that uses quick
interrupts must be able to fall back to the Amiga's conventional
interrupt scheme.

The LVO for ObtainQuickVector() was added for V39, but it was not fully
implemented until after the initial release.  This means the OS that
currently ships with the Amiga 4000 and Amiga 1200, Release 3.00, will
always return 0 (no SetPatch currently exists to correct this, but a
future SetPatch may do so).  ObtainQuickVector() only works in the
developer releases of the OS that follwed the initial release.  Since a
Zorro III device driver must handle the case where it cannot obtain a
vector, this function should never cause a hardware product to fail.
There is no reliable way to obtain a vector before V39.

exec.library/ObtainQuickVector                 exec.library/ObtainQuickVector

   NAME
        Function to obtain an install a Quick Interrupt vector            (V39)

   SYNOPSIS
        vector=ObtainQuickVector(interruptCode)
        d0                       a0

        ULONG ObtainQuickVector(APTR);

   FUNCTION
        This function will install the code pointer into the quick interrupt
        vector it allocates and returns to you the interrupt vector that
        your Quick Interrupt system needs to use.

        This function may also return 0 if no vectors are available.  Your
        hardware should be able to then fall back to using the shared
        interrupt server chain should this happen.

        The interrupt code is a direct connect to the physical interrupt.
        This means that it is the responsibility of your code to do all
        of the context saving/restoring required by interrupt code.

        Also, due to the performance of the interrupt controller, you may
        need to also watch for "false" interrupts.  These are interrupts
        that come in just after a DISABLE.  The reason this happens is
        because the interrupt may have been posted before the DISABLE
        hardware access is completed.  For example:

        myInt:          move.l  d0,-(sp)        ; Save d0...
                        move.w  _intenar,d0     ; Get interrupt enable state
                        btst.l  #INTB_INTEN,d0  ; Check if pending disable
                        bne.s   realInt         ; If not, do real one...
        exitInt:        move.l  (sp)+,d0        ; Restore d0
                        rte                     ; Return from int...
        ;
        realInt:        ; Now do your int code...  d0 is already saved
                        ; ALL other registers need to be saved if needed
                        ; This includes a0/a1/d0/d1 as this is an interrupt
                        ; and not a function call...
                        ;
                        bra.s   exitInt         ; Exit interrupt...

        If your interrupt will not play with system (OS) structures and your
        own structures are safe to play with you do not need to check for
        the disable.  It is only needed for when the system is in disable but
        that "one last interrupt" still got through.

   NOTE
        This function was not implemented fully until V39.  Due to a miscue
        it is not safe to call in V37 EXEC.  (Sorry)

   INPUTS
        A pointer to your interrupt code.  This code is not an EXEC interrupt
        but is directly connected to the hardware interrupt.  Thus, the
        interrupt code must not modify any registers and must return via
        an RTE.

   RESULTS
        The 8-bit vector number used for Zorro-III Quick Interrupts
        If it returns 0, no quick interrupt was allocatable.  The device
        should at this point switch to using the shared interrupt server
        method.

   SEE ALSO


III-29: Writing Runtime Libraries with SAS/C 6.x

Writing Runtime Libraries with SAS/C 6.x

by John Wiederhirn

The benefits of the Amiga's runtime libraries go beyond their ability to share
code and save memory. For a single application, runtime libraries offer
application developers a great deal of flexibility. Some potential benefits
include:

1. Patching applications by releasing new libraries.

If an application's runtime libraries house most of the its functionality, a
developer can easily release bug fixes or patches by sending registered users
the new versions of runtime libraries. SAS/C is a good example of this, as
most of the compiler's functionality is in the runtime libraries. Since the
libraries aren't particularly useful without the executeable ``front end'' of
the program (the program that opens and uses the libraries), developers can
readily distribute patches electronically without supplying the entire
program.

2. Makes program ``leveling'' easier.

A developer can make an application upgradable from a ``consumer'' to a
``professional'' edition using a runtime library. The user can upgrade by
adding a library. When the software starts up, it tries to open the enhanced
library with the additional functions. If the software can't open the library,
it configures itself as the ``consumer'' version.

3. Allows greater extensibility.

With careful design, you can expose an interface to your program which allows
``scripts'' to be written in C or other compiled languages. This can greatly
enhance your program's extensibility beyond simple ARexx scripting. Done
correctly, others can even use such an Application Programmer Interface (API)
to create large scale turnkey applications by tying together smaller
applications using C bindings.

4. Provides simple overlaying.

If an application opens and closes libraries only as it needs them, Exec's
library handling system can act as a simple overlay manager. For example,
consider a desktop publishing application that keeps all its printing routines
in one library and all its screen rendering routines in another library. If
the application closes its rendering library when it needs to print, the OS
can expunge the rendering library if the system is low on memory while loading
and using the printing library. When the application finishes printing, it can
close the printing library and reopen the rendering library, so the OS can
expunge the printing library while the application isn't using it.

The benefits sound useful but, unfortunately, designing and implementing
runtime libraries on the Amiga has always been rather arcane. Developing a
runtime library typically requires assembly programming and an intimate
knowledge of obscure system structures with names like ``ROMTag'' and
``MatchWords''. As a result, only a small number of programmers are willing to
tackle writing a runtime library.

To help make the task of developing Amiga runtime libraries easy, SAS added
library building features to their compiler which eliminates a lot of the
confusion surrounding runtime library development.

This article assumes that the reader has a basic knowledge of the structure of
an Exec runtime library (also called a shared library) and the terminology
surrounding them. For more information on the basics of runtime libraries, see
the ``Introduction to Exec'' chapter of the Amiga ROM Kernel Reference Manual:
Libraries (3rd edition).

Creating a runtime library using the SAS tools in Amiga C 6.x breaks down into
a few distinct steps:

1. Writing the Functions

When designing the functions, you need to explicitly declare the register
usage to the compiler. SAS does this with the ``__asm'' directive and the
``register'' keyword:

        ULONG  __saveds __asm mylibfunc( register __d0 ULONG somevar,
                                         register __a0 APTR someptr );

The ``__asm'' portion of this prototype tells the compiler that mylibfunc uses
a specific CPU register for each function parameter. The ``register'' keyword
tells the compiler which CPU register to use for a specific parameter. In the
sample above, the ``mylibfunc'' function requires two parameters. When the
compiler compiles a program that uses ``mylibfunc'', it will place the first
parameter, somevar, in CPU register D0 and the other parameter, someptr, in
CPU register A0.

The SAS/C 6.x tools do impose some rules on the functions that will go into an
Exec runtime library. The most important of these is that each and every
routine in the library callable from outside the library must be declared
using the SAS/C ``__saveds'' directive. For example:

struct Armadillo * __saveds __asm CreateArmadillo( register __a0 struct NewArmadillo * );

A programmer might not want all of a library's functions accesible from
outside the library. Several functions may use an internal subroutine that has
no legitimate purpose outside of the library. These internal functions should
be declared as ``static'' routines. A sample prototype might look like this:

static BOOL ValidateArmadillo( struct Armadillo * );

Don't get internal functions confused with functions with private entry
points. An internal function is only accessible from other functions within
the same library as it does not have a entry in the Library Vector Offset
(LVO) table. The static functions are not accessible outside of the library,
and do not need the ``__saveds'' and ``__asm'' directives.

Some of the Amiga's ROM libraries have private entry point functions. These
functions have an LVO and parameters like public functions. The only
difference is that the public functions are documented (via prototypes and
pragma files, which are discussed later) so all programmers can use them. For
private entry point functions, only the library designer knows about the
functions, so only the library designer can use them.

2. Selecting Data for the Library Base

Many libraries need some amount of global data (data that is external to any
library function). For example, if the functions in mylib.library use
functions from the graphics.library and intuition.library, mylib.library would
probably keep the library bases of graphics.library and intuition.library in
its global data area.

When an application opens a library, the OpenLibrary() function returns a
pointer to a Library structure (defined <exec/libraries.h>). This structure
contains information that Exec uses to manage the library system. Typically,
runtime libraries keep their global data directly after their Library
structure. An example of an Amiga ROM library followed by its global data is
GfxBase. There is a GfxBase structure defined in <graphics/gfxbase.h> which
starts off with an Exec Library structure and is followed by global data for
the graphics.library.

The SAS/C library tools also use this scheme for global data. When building a
library, the SAS/C linker, Slink, gathers data declared as global (data
outside of any function) and appends that data after the Library structure.
The linker handles this automatically, so the programmer doesn't have to do
anything special to make this happen.

Because the linker creates the library base automatically, there is no library
base structure like the GfxBase structure. When an application opens this
library with OpenLibrary(), OpenLibrary() returns a pointer to a Library
structure which is followed by the library's global data. Unfortunately, the
application (which we'll call the library's client) does not know how the
linker arranged this global data. As a result, it is impossible for a library
client to access any part of the library's global data using only the pointer
returned by OpenLibrary(). This does not include the Library structure, only
the global data that follows it.

At first, this ``feature'' may seem quite annoying, but it actually serves a
purpose. The global data is global to the library, not the whole world. If the
information were made directly accessible via a C structure, the format of the
library's global data would have to remain fixed if the library were to
maintain backwards compatibility. If a library needs to make a global data
item accessible outside the library, the library can supply a function that
returns a pointer to that global data. As an example, if your library has a
variable in its base declared as:

ULONG ActiveArmadillos; /* Number of armadillos the client's using */

and you decide that library clients need to access this data, then you can
provide a function such as:

ULONG __saveds CountArmadillos( VOID );

which would simply return the value of ActiveArmadillos to the caller. This
also means that if the format of ``ActiveArmadillos'' should change (say from
a simple counter to a linked list of names), then the function can
transparently adapt to the new design.

The 32K Barrier

A potentially important limitation of the SAS/C library generation is that
Slink restricts the size of a library base. They way in which Slink builds the
library causes the OS to create a ``near data'' section and ``far data''
section when loading the library into memory. Slink places the library base
into the near section. Because of the way programs access data in the near
section, the near section is limited to 32K.

If 32K is too limiting, there are alternatives. One is to force read-only data
into the far section. To force a variable into the far section, use the
``__far'' keyword when declaring the variable. For example, when SAS/C
encounters the following line in library source code:

APTR __far mylibtable;

it knows to place mylibtable in the far data section. This will generate a
warning at link-time, but in this case the warning is ignorable. These items
get placed in the far data section, which is shared among all clients of the
library. Since all clients have to share the far data, the data has to either
be read-only or the clients must use a semaphore to gain access to the data.

If a library is low on near data space and strings occupy a significant amount
of that space, try the STRMERGE compile option. This tells the compiler to put
the strings in with the library code instead of in the near data section.

3. Choosing the Type of Library Base

The SAS runtime library tools offer two ways to handle library bases. There is
the conventional method where there is only one copy of a library's LVO
tables, Library structure, and global data. In this case, OpenLibrary()
returns the same library base pointer for every program that opens the same
library. There is also a second method where each library client receives its
own copy of the library's LVO tables, Library structure, and global data. In
this case, OpenLibrary() returns a different library base pointer for every
program that opens the same library. The socket.library from Commodore's AS225
TCP/IP networking software is an example of a library that returns a unique
library base for each client.

If a library returns a different library base to each client, each instance of
the library has its own near data space. This can be useful if the library
needs to allocate non-sharable resources (for example, file handles) for each
client. It can also be used to store parsing state information, callback
hooks, or anything else you need to design as a part of the library base. Note
that, although such a library can have many near data spaces, there is still
only one far data space area.

A library that uses separate bases has drawbacks. Since each client receives
its own copy of the library base, this scheme uses more memory. This scheme
also complicates the open and close routines for the library, although the
SAS/C runtime library generation tools hide the complications from the
programmer. Also, the Exec routine SetFunction() will only work on one
instance of a library base. If a client calls SetFunction() on its instance of
the library base, it will not effect the existing library bases of other
clients.

The difference between generating a single base library versus generating a
multiple base library is almost too simple. When linking the library, the
programmer only needs to use the libinitr.o object file instead of libinit.o.
SAS/C takes care of the extra work involved in creating multiple base library,
so the programmer doesn't have to worry about it.

Note that if a library opens a multiple base library, that library also has to
be a multiple base library.

4. Handling Initialization and Shutdown

For every runtime library, the OS reserves several LVOs for system use.
According to the ``Introduction to Exec'' chapter of the Amiga ROM Kernel
Reference Manual: Libraries, the system currently uses three vectors for an
open function, a close function, and an expunge function. The OS calls a
library's open function whenever a program opens the library with
OpenLibrary(). The library's open routine takes care of the initialization a
library needs to do for every library client. The OS calls a library's close
function when a program closes a library with CloseLibrary(). The close
routine relinquishes any resources allocated by the library's open routine.
When the system is low on memory, the OS calls a library's expunge vector to
ask the library to relinquish its resources so the system can unload the
library.

The ``Introduction to Exec'' chapter neglects to mention the existence of a
fourth function known as the library init function. This function does not
have a true LVO like the other system reserved LVOs, which is one of the
reasons its not well documented. The OS calls a library's init function when
opening the library for the first time. This routine handles initialization
that is global to the entire library. It differs from the library's open
routine in that the system calls the init routine only once whereas the system
calls the open routine for every OpenLibrary() call. The expunge routine
cleans up after the init routine.

SAS/C automatically takes care of most of the work involved in creating these
functions, but it can't do everything. For example, if a library needs to open
other libraries, the compiler can't take of that automatically, so the library
programmer has to take care of it.

When SAS/C builds a library, it looks for two functions in the library code,
__UserLibInit() and __UserLibCleanup(). If SAS/C finds a function called
__UserLibInit(), it includes that function in either the library's init
function or the library's open function, depending on the library's base type.
If the compiler finds the __UserLibCleanup() function, it includes that
function in either the library's close function or the library's expunge
function.

In a multiple base library (a library base for each client), SAS/C makes the
__UserLibInit() function part of the library's open function and the
__UserLibCleanup() function part of the library's close function. In this
case, the OS ends up calling the __UserLibInit() and __UserLibCleanup()
functions every time a library client calls OpenLibrary() and CloseLibrary().

Because there are some significant restrictions on what OS functions a library
can call from its expunge function, the __UserLibCleanup() function of a
single base library is severely limited. Specifically, the expunge vector
cannot break a Forbid() state! Since there are only a handful of OS functions
that are guaranteed not to break the forbid state, very few OS functions are
usable in the expunge function. Any function that uses the Wait() function
breaks a forbid, so functions like

WaitPort() are illegal. DOS I/O is illegal. In fact, the only functions that
are legal in expunge are those which specifically mention in their autodoc
that they do not break a forbid. These include (but are not limited to):

AttemptSemaphore()          Disable()           FindPort()
ReleaseSemaphore()          Enable()            FindTask()
AllocMem()                  Signal()            AddHead()
FreeMem()                   Cause()             AddTail()
AllocVec()                  GetMsg()            RemHead()
FreeVec()                   PutMsg()            RemTail()
FindSemaphore()             ReplyMsg()          FindName()

In a single base library (one library base for all clients), SAS/C makes the
__UserLibInit() function part of the library's init function and the
__UserLibCleanup() function part of the library's expunge function. When the
system encounters this type of library, it calls the __UserLibInit() and
__UserLibCleanup() functions only as the system loads and unloads the library.

The prototypes for these routines are:

int __saveds __UserLibInit(void);
void __saveds __UserLibCleanup(void);

The following code sample uses these function to open and close some
libraries. Notice that the __UserLibInit() call returns 0 if it is successful
otherwise it returns 1.

#include <exec/types.h>
#include <graphics/gfxbase.h>
#include <clib/exec_protos.h>
#include <pragmas/exec_pragmas.h>

struct Library *GfxBase = NULL;
struct Library *SysBase = NULL;

int __saveds __UserLibInit(void)
{
    int retval = 1;

    SysBase = (*((void **)4));

    if (GfxBase = OpenLibrary("graphics.library",39L))
        retval = 0;

    return(retval);
}

void __saveds __UserLibCleanup(void)
{
    CloseLibrary(GfxBase);
}

Note that SAS/C does not require the library programmer to supply these functions.

5. Constructing the Function Description File

The function descriptor or ``.fd'' file defines all the function entry points
in a runtime library. SAS/C uses this file to help compile the library. The
following is an excerpt from the fd file ``armadillo_lib.fd'', which is part
of the example source at the end of this article:

##base _DilloBase
##bias 30
##public
CreateArmadillo()()
DeleteArmadillo(dillo)(A0)
NameArmadillo(dillo,name,len)(A0/A1,D0)
##private
. . .

##end

The ##base command names the global variable that points to this library's
base. The ##bias command is always going to be 30 for SAS/C generated
libraries (the reasons are not relevant and are beyond the scope of this
article). The ##public command tells SAS/C that the function descriptions that
follow should be callable by all programs. This is the opposite of the
##private command, which tells SAS/C that the function descriptions that
follow all have private entry points. The ##public and ##private commands
don't affect the library itself. These become important later when creating
pragma files.

Each function description consists of the name of a library function, the name
of each of the function's parameters, and the corresponding CPU registers the
function uses to pass its parameters. For example, from the NameArmadillo()
function description, the ``dillo'' parameter is passed in register A0, the
``name'' parameter is passes in register A1, and the ``len'' parameter is
passed in register D0. The slash tells the compiler it can use the assembler
instruction MOVEM when handling these registers (although it does not indicate
a range of registers). For more information on writing .fd files, please
consult page 29 of the SAS/C 6.0 Library Reference Manual.

6. Compiling and Linking

When compiling library code modules, make sure that stack checking is turned
off (with the NOSTKCHK option), and that all the modules are compiled with the
LIBCODE parameter.

Once all the modules compile, the next step is to link them all together into
the runtime library. The Slink syntax for doing this is:

SLINK TO <libname>.library \
FROM LIB:libent.o <lib init module> <lib code modules> \
LIBFD <fdfile>         \
[LIB <link libraries>] \
[LIBPREFIX <prefix>]   \
[LIBID <id_string>]    \
[LIBVERSION <version>] \
[LIBREVISION <revision>]

<libname> 		= Library name, for example ``exec'' or ``dos''.
<lib init module> 	= LIB:libinit.o for a single base library or LIB:libinitr.o for a
                          multiple base library.
<lib code modules> 	= Your code modules for the library
<fdfile> 		= The .fd file for your library
<link libraries> 	= [Optional] Any link libraries used by your code.
<prefix> 		= [Optional] An in-library prefix on your function names.
<id_string> 		= [Optional] Used to set the __LibID value.
<version> 		= [Optional] Version value to be embedded in the library.
<revision> 		= [Optional] Revision value to be embedded in the library.

If you were designing ``armadillo.library'' which was comprised of code
modules called dillo_open.c, dillo_close.c and dillo_read.c, an .fd file
called armadillo_lib.fd, the SLINK command line might look like this:

SLINK TO armadillo.library \
FROM LIB:libent.o LIB:libinitr.o dillo_open. dillo_close.o dillo_read.o \
LIBFD armadillo_lib.fd \
LIBPREFIX "LIB" \        <-- See ``Using LIBPREFIX to Distinguish Library Functions''
                             from the ``Additional Hints and Tips'' section below.
LIBID "Armadillo Library" \
LIBVERSION 1 \
LIBREVISION 0

The '\' character is used to indicate a line wrapping onto the next line. In
reality, you'd enter the entire command above as a single typed command. More
likely, though, all of this would be combined into a makefile.

If all goes well, Slink will create the runtime library. The next step is to
create prototypes and pragmas so applications can call the new library.

7. Protos and Pragmas

To make it possible for applications to use the new library, it needs
prototypes and pragmas for its functions. The functions should already have
protoypes from the library's source code, but you'll have to collect them into
a single file and remove private functions.

The SAS/C tool fd2pragma generates a pragma file from the function description
(``fd'') file. It should not generate pragmas for any functions that the fd
file has marked as ``##private''.

When making <libname>_protos.h and <libname>_pragmas.h files (and matching .i
files if you intend them to be accessible from assembly language), if your
library has externally-accessible private routines, remove these from the
pragma files you plan to distribute.

Additional Hints and Tips
(provided by the nice folks at SAS)

C Standard Library and Runtime Libraries

Many standard library functions rely upon some initialization and clean up
code that is part of the standard startup code. Since a library does not use
such start up code, a library can't call many of these functions. The stdio
functions are an example.

In some cases with multibase libraries only (not single base libraries!),
there are ways around this limitation. You can use malloc() if you make an
explicit call to _MemCleanup() in a _UserLibCleanup() function. You can use
level 2 file I/O functions (fopen(), fclose(), fread(), fwrite(), fprintf(),
etc.) if you explicitly close all files that you open (of course Amiga
programmers should be used to reliquishing any resources they allocate). Note
that for level 2 file I/O to work, you must have been called by a process, not
a task, and if you are a general-purpose library, there is no good way to
guarantee this. Remember that for a single base library, the expunge routine
cannot break a forbid, so a single base library is very limited as to what it
can call in its __UserLibCleanup()!

Don't Use Stack Extension or Checking

Don't use stack extension or stack checking in a runtime library. Also, the
__stack variable will have no effect.

Using __aligned on Library Functions and Variables

If you want the __aligned keyword to work correctly on automatic variables in
your library, you must put the __aligned keyword on each function listed in
your .fd file (along with __saveds and __asm.) This is because your library
might get called from some other task or process whose stack is not aligned.
This use of __aligned will cost you a pointer register variable for the
duration of the function so declared, however.

Function Pointers, Callback Hooks, and You

You can't pass function pointers to CreateProc() or callback hooks, even if
you correctly use __saveds. This is due to the fact that __saveds in a runtime
library depends on register A6 being set up to contain the library base, and
this probably won't be the case when your callback is called or when
CreateProc() branches to your entry point. A good workaround is to pass
getreg(REG_A4) as the userdata item for your callback, then do putreg(REG_A4,
userdata) in your callback routine.

Using LIBPREFIX to Distinguish Library Functions

A keen trick is to declare your library routine with an "Extra" parameter in
register A6 that is the library base, and to use a LIBPREFIX value to
differentiate between the outside-the-library version of the function and the
inside-the-library version. Example:

int myfunc(int x, int y);   // User's version of the prototype
#pragma libcall MyLibBase myfunc <magic>  // Pragma for myfunc

....
/* Now, in the source code for the library: */
int __asm __saveds
LIBmyfunc(register __d0 int x,
register __d1 int y,
register __a6 struct Library *MyLibBase)
{
...
}

To tell Slink that LIBmyfunc is really the 'myfunc' referred to in the .fd
file, use the LIBPREFIX=_LIB option. If you do this, you may refer to simply
'myfunc' in your code, both inside and outside the library, and all such
references will go through the library base, giving the user a chance to
SetFunction() your function correctly if desired. The fact that the library
base is present as an explicit variable is a nice bonus.

No Auto-Open Library Code

You can't rely on the auto-open library routines to work correctly in a
runtime library. You must explicitly open each library base, and close it when
you are done. This includes SysBase, DOSBase, etc. Be particularly careful
when using UTILLIB or MATH=IEEE, since these routines silently try to open
various library bases for you. You have to remember to open these bases
yourself.

About the Example

The example code implements a do-nothing library, called armadillo.library.
This library has five entry points, and they serve only to demonstrate some of
the different library base access features. Pay particular attention to the
prototypes and mapping of the function code to the prototypes and .fd file for
the library. There are two library routines which are not
externally-accessible and one private externally-accessible entry point which
is not reflected in the prototypes or pragmas (but is noted in the .fd file).

The makefile is a ``generic'' framework for a runtime library's makefile. With
only slight modifications, this same file could be used for most runtime
libraries you might want to create (and you are free to use it as desired).

 Armadillo_lib.fd
 dillo.c
 dillo.h
 dillo_lib.c
 dillo_protos.h
 dillo_test.c
 Makefile


IV-1: Obtaining an Icon Image

By David N. Junod

One of the many improvements made to Workbench for release 2.0 lies in its
ability to supply an application with arguments from Workbench. Prior to
release 2.0, the only Workbench supported way an application could receive
Workbench arguments was through the Workbench startup message.  Now,
Workbench arguments can come from many sources including AppWindows,
AppIcons, and the ASL file requester.  These enhancements have made
processing Workbench arguments more beneficial than ever.

When an application is started via Workbench, the application receives a
startup message (struct WBStartup) from Workbench.  This message contains
a pointer to an array of WBArg structures.  The array of WBArgs
corresponds to all Workbench icons that were selected at the time the
application was launched.  Each WBArg structure contains a file lock on
the file or directory associated with each icon, as well as the name
associated with the icon.  A WBArg supplies the link to the icon, or the
DiskObject, itself, from which necessary information, such as application
or project ToolTypes, can be extracted.

Under release 2.0, Workbench supplies WBArgs using several different
structures.  The structure used depends on the source of the WBArgs. When
it launches an application, Workbench sends the application WBArgs through
the WBStartup structure.  AppWindows and AppIcons use the AppMessage
structure to send WBArgs.  The ASL file requester provides the arguments
in the FileRequester structure.

Also with release 2.0, it is possible that icons passed to an application
do not have an .info file associated with them.  Workbench can now display
all files and directories iconically, not just those with .info files. For
icons without .info files, Workbench supplies a default icon based on the
protection bits and object type (file, dir, etc.) so the user can
manipulate files and directories from Workbench.

The following routine, wbarg.c, uses GetDiskObjectNew() which should be
used only when an application requires an image for every Workbench
argument, whether actual or default.  To only read actual icons and
tooltypes, modify the routine to use GetDiskObject() instead.  For more
information, see the release 2.0 Autodocs.


IV-3: An Introduction to V36 Screens and Windows

by Ewout Walraven

    Editor's Note: The following article assumes the reader is
    familiar with the concept and implementation of tags in
    Intuition under release 2.0.  More information on the
    subject can be found in the Amiga Mail article
    "TagItems and Tag Lists".

The new intuition.library provides the programmer with flexible yet
simple methods of opening Intuition screens and windows.  This article
is an introduction to some of the Intuition and relevant
graphics.library functions that make this possible. For more in depth
information see the 1990 DevCon notes as well as the Autodoc and
include files for release 2.0.

 The Display Database             Visitor Windows
 Opening Screens and Windows      Overscan
 Public Screens                   DisplayClip


The Display Database

Release 2.0 of the OS introduces system support for different monitor
types and programmable display modes.  Applications can make use of
these features through the Display Database.  The Display Database
provides an easy way for applications to stay compatible with past,
present and future versions of the OS and the display hardware.

The database contains information about the available monitor types
(like PAL or VGA) and the display modes that a particular monitor type
is capable of displaying (like Lores, Hires, SuperHires, etc).  This
database makes it possible for the user to dynamically add new monitor
types to the system, typically by calling the addmonitor command using
a monitor spec file as an argument.  These monitor types will be added
to the database after the default monitor. The default monitor
properties are determined at boot time based on the configuration of
the custom chip set. The default monitor is always either an alias for
the NTSC or PAL monitor type.

When a monitor type is added to the database, the system figures out
which display modes are available to this monitor type, based on the
properties of the monitor's spec file and the configuration of the
custom chip set.  Later, the Display Database can be queried on the
availability of a particular display mode using the appropriate
graphics.library calls.

The following is an example of how to use graphics.library functions
to find out what display modes are available. See the 2.0 Autodocs for
a detailed description of the various functions.

    ULONG modeID;
    ULONG skipID;

    ULONG error, result;
    struct DisplayInfoHandle displayhandle;
    struct DisplayInfo displayinfo;
    struct NameInfo nameinfo;

    /* graphics.library must be opened */

    /* Don't want duplicate entries in the list for the
     * 'default monitor', so we'll skip the the videomode
     * for which default.monitor is the alias.
     */

    /* INVALID_ID indicates both the start and the end of the list of
       available keys */
    modeID = INVALID_ID;

    GetDisplayInfoData(NULL, (UBYTE *) & displayinfo,
            sizeof(struct DisplayInfo), DTAG_DISP, LORES_KEY);
    if (displayinfo.PropertyFlags & DIPF_IS_PAL)
        skipID = PAL_MONITOR_ID;
    else
        skipID = NTSC_MONITOR_ID;

    /* Given a ModeID, NextDisplayInfo
                        returns the next ModeID in the list */
    while((modeID = NextDisplayInfo(modeID)) != INVALID_ID) {

        /* Skip it? */
        if (modeID & MONITOR_ID_MASK != skipID) {

            /* ModeNotAvailable returns NULL if a displaymode,
               specified by the modeID, is available, or an error
               indicating why it is not available.
            */
            if ((error = ModeNotAvailable(modeID)) == NULL) {

                /* This displaymode is available, get the naming
                   information. GetDisplayInfoData, can either be
                   called with a handle to a displaymode record, or
                   the display modeID. Never use the handle directly.
                */

                /* returns NULL if not found */
                if (displayhandle = FindDisplayInfo(modeID)) {
                    result = GetDisplayInfoData(displayhandle,
                            (UBYTE *)&nameinfo, sizeof(struct NameInfo),
                            DTAG_NAME, NULL);
                    if (result)     /* 'result' indicates the number
                                        of bytes placed in the buffer */
                        printf("%s is available.\n", nameinfo.Name);
                }
            }
        }
    }

Using the GetDisplayInfoData() function, this example asks only for
the descriptive name of the display mode via the NameInfo structure.
Using this same function with a different tag, other information on a
particular display mode can be obtained.  GetDisplayInfoData() can
supply information about the properties of the display mode
(DisplayInfo), the display mode's dimensions (DimensionInfo) or the
display mode's monitor specifications (MonitorInfo).  Refer to
graphics/displayinfo.h for a description of the various structures.


Opening Screens and Windows

Intuition V36 supplies two new functions to open screens and windows:
OpenScreenTagList() and OpenWindowTagList(). They provide added
functionality over the older OpenScreen() and OpenWindow() functions.
Instead of the NewScreen and NewWindow structures, an array of
parameters called tags is passed to the function in the form of a
TagItem structure pointer.  This array is known as a tag list.  For a
description of using tags in Intuition, see the Amiga Mail article
``TagItems and Tag Lists''.

The following is a simple example of the usage of OpenScreenTagList()
and OpenWindowTagList(), using only a tag list as a parameter to each
function.

    struct TagItem tagitem[3];
    struct Screen *screen;
    struct Window *window;

    tagitem[0].ti_Tag  = SA_DisplayID;
    tagitem[0].ti_Data = HIRES_KEY;     /* Use HIRES displaymode
                                           for default monitor */
    tagitem[1].ti_Tag  = SA_Title;
    tagitem[1].ti_Data = "AmigaMail Test Screen";
    tagitem[2].ti_Tag  = TAG_DONE;    /* Marks the end of the tag array. */

    /* All others options will be set to default. Note this screen will not
       open with the 'New Look', due to the absence of the SA_Pens tag and
       data. Further examples will have this tag */

    if (screen = OpenScreenTagList(NULL,   tagitem)) {
        tagitem[0].ti_Tag = WA_CustomScreen;
        tagitem[0].ti_Data = screen;    /* Open on my own screen */
        tagitem[1].ti_Tag = WA_Title;
        tagitem[1].ti_Data = "AmigaMail Test Window";
        tagitem[2].ti_Tag = TAG_DONE; /* Marks the end of the tag array. */

        /* Use defaults for everything else. Will open as big as the screen. */

        if (window = OpenWindowTagList(NULL, tagitem)) {

            /* rest of code */

            CloseWindow(window);
        }
        CloseScreen(screen)
    }

See the intuition/intuition.h and intuition/screens.h include files
for a complete list of currently supported tags.

Intuition.library provides a function to get information about screens
and display modes called GetScreenDrawInfo().  This function returns a
subset of the data supplied by the graphics.library's
GetDisplayInfoData() function.  Given a pointer to a screen,
GetScreenDrawInfo() returns a pointer to a DrawInfo structure
describing that screen.  Note that this structure is read-only.  The
DrawInfo structure contains information about the resolution, default
font and pen colors of the screen.  Since the system allocates the
DrawInfo structure when GetScreenDrawInfo() is called, a program must
tell the system to free it by calling FreeScreenDrawInfo().  Of
course, a program should only release the DrawInfo structure after it
is no longer needed.

When using GetScreenDrawInfo() on a public screen, the screen should
first be locked using Intuition's LockPubScreen() function.  This will
prevent a public screen from closing while your program is looking at
the screen's DrawInfo structure.  UnlockPubScreen() will unlock the
screen.  Public screens are discussed in more detail later in this
article.

The graphics.library function GetVPModeID() provides a way of
determining the display mode ID associated with a ViewPort.  Passed
the ViewPort attached to a screen, the function will return the
display mode ID for that ViewPort, or INVALID_ID if no display mode ID
is associated with the ViewPort.

An example of the usage of GetVPModeID() and the other functions
discussed so far in this article are provided in at the end of
thisarticle in example 1, CloneWB.c.  This example also uses the
stack-based amiga.lib support library functions OpenScreenTags() and
OpenWindowTags(), both of which are documented in the release 2.0
Autodocs.


Public Screens

V36 introduces the public screen, a custom screen on which other
applications can open their windows.  A familiar example of a public
screen is the Workbench screen.  The public screen provides the
ability to create system supported environment alternatives to the
Workbench.

Opening a public screen is just like opening a custom screen.  The
only difference is in the tags used when the screen is opened.  There
must be a SA_PubName tag, with the screen's name as the tag's data.
Applications will access the screen by this name.  When a public
screen is first opened, it is still private to the application that
opened it.  This will give the program that opened the screen the
opportunity to set up before other applications can access the screen.

After a public screen is explicitly made public, anybody can put a
lock on the screen or open a window on it.  Both locks and 'visitor
windows' prevent applications from closing their public screens.
Intuition keeps track of the number of locks and visitor windows on a
public screen by incrementing and decrementing the screen's visitor
count.  When the number of visitors is zero, the screen can be closed.

The following code fragment shows how to open a public screen and
change its status from private to public using the Intuition function
PubScreenStatus().

    if (pubscreen = OpenScreenTags(NULL, SA_DisplayID, HIRES_KEY,
                    SA_Depth, 2, SA_Title, "AmigaMail Test Public Screen",
                    SA_PubName, "AmigaMail Test Public Screen",
                    /* By providing the public name, you indicate
                       it will be public */
                    SA_Pens, dri_Pens,
                    SA_ErrorCode, &oserror,
                    TAG_END)) {
        /* change mode from 'private' to 'public' */
        oldstatus = PubScreenStatus(pubscreen, 0);}

If for any reason Intuition could not open the screen, the error
number will be returned in the data portion of the SA_ErrorCode tag
(the OpenScreen errors are listed in intuition/screens.h). This error
can indicate that the system is out of memory, that the requested
display mode is not supported by the video hardware or monitor, or
that the public screen name is already being used by another public
screen.

Some OpenScreen errors can be avoided.  Make sure the display mode a
screen requires is available (one of the previous examples shows how
to find all available display modes).  For example, before opening a
public screen, make sure its name is not already being used by an
existing public screen.  Before opening a public screen named
ExamplePublicScreen, try to put a lock on a screen with that name
using LockPubScreen().  If this call succeeds, the system has found
and locked a screen with that name, so you can't use it.  If the call
fails, the system does not have a screen by that name, indicating that
it's OK to open the new screen with that name.  An application should
make sure it removes all locks on a screen when the screen is no
longer needed.

If a screen already exists with that name, there are several options
available, all of which should reflect user preferences.  One option
is not to open a screen, using the existing screen instead.  For
example, if the user double-clicks an application's project icon, the
application would check if its public screen is already opened and
open windows there before trying to open a new screen.  Another option
is to open a new screen with a slightly different name.  A public
screen that would have been named ExamplePublicScreen might instead be
called ExamplePublicScreen2.  A third option is to quit.  In any case,
the user should normally be choosing the actions of the application,
not the programmer.

Programs find specific public screens by their name, so public screens
must have a unique name as identification.  With a maximum name length
of 139 characters, supplying a unique name shouldn't be a problem.
This name should reflect the nature of the screen's purpose, if for no
other reason, to make it easy to figure out what the screen is used
for.  Ambiguous names such as "PublicScreen" or "MyScreen" should not
be used as they tell nothing about the nature of the screen.  Also,
more than one "less creative" programmer might be inclined to give
such generic names to their public screen, which can confuse both user
and application.

As a public screen can be used as an alternative to the Workbench
environment, programs opening public screens should normally make the
screen is at least 640 pixels wide.  Many applications assume that the
Workbench is at least 640x200 and would be severely crippled if opened
on a 320x200 screen.

Before a public screen can be closed, it has to be made private again.
As long as there are visitors (windows and locks) on a public screen,
an attempt to change the screen's status to private will fail.  To
make closing down public screens easier, Intuition can signal an
application when the last visitor 'leaves' a public screen.  While
waiting to close a locked public screen, an application can start to
shut down by unloading code or closing windows.  After the screen has
been made private again, Intuition removes it from the public screen
list.  The following code illustrates this.

if ((oldstatus = PubScreenStatus(pubscreen, PSNF_PRIVATE)) & PSNF_PRIVATE)
            CloseScreen(pubscreen);

To tell Intuition to signal when all the visitor windows on a public
screen have been closed, use the SA_PubSig and SA_PubTask tags when
opening the screen.  The SA_PubSig data is the number of a signal bit
you have allocated.  An application can specify which task to signal
when all the visitors have left by supplying a pointer to that task
with the SA_PubTask tag.  If this tag is absent or its data = NULL,
the task which opened the public screen will be signaled.

When putting up any requesters on a public screen, be sure to supply
the requester with a pointer to a visitor window on that screen.  This
will prevent the requester from popping up on the wrong screen.  This
will also prevent needless incrementing of the public screen's visitor
count as the requester will not be considered a visitor.

Prior to release 2.02, UnlockPublicScreen() did not signal when the
visitor count reached zero.  With release 2.02, UnlockPubScreen() will
signal the specified task when the visitor count reaches zero.  Under
2.00 and 2.01, only CloseWindow() would signal.

There is always a default public screen available.  Normally this
would be the Workbench, but an application can make its own public
screen the default, or better yet, a screen manager utility could let
the user choose the default public screen.  An application should not
automatically make its public screen the default as this might confuse
the user and can conflict with user preferences.

Because older programs do not know about public screens, The SHANGHAI
flag has been provided to 'shanghai' requests to open a window on the
Workbench screen, forcing the window to open on the default public
screen. Of course, a release 2.0 application that wants to open a
window on a specific public screen can do so provided that the
specific screen is available.  Another flag, POPPUBSCREEN, instructs
Intuition to move public screens to the front if a window is opened on
it.  The SHANGHAI and POPPUBSCREEN flags can be set using
PubScreenStatus() but, as the flags are global and should be set
according to the preferences of the user, applications should not be
changing them.

Example 2, Pub.c, shows how to open a public screen, make it the
default and shut it down.  The example can be found at the end of this
article.

To aid 'screen manager' utilities, the list of public screens can be
locked and copied using LockPubScreenList().  UnlockPubScreenList()
will unlock the list.  Don't try to interpret the list itself.
Instead, copy it and release the lock. To receive an updated copy
later on, lock and copy the list again. Lockpub.c is a small example
of locking the public screen list.


Visitor Windows

Opening a visitor window on a public screen is like opening a window
on a custom screen except that the window is specifically defined as a
visitor.  This is done when opening the window by either replacing the
CUSTOMSCREEN flag in the (Ext)NewWindow->Type field with PUBLICSCREEN
or using a WA_PubScreenName or WA_PubScreen tag.  To use the
PUBLICSCREEN flag or the WA_PubScreen tag (this tag has a pointer to
the public screen as data), the screen must be prevented from closing.
Normally this is done by locking the desired public screen.  In either
case the program must provide a pointer to the public screen if it
requires a specific public screen.  If an application has no
preference towards a particular screen, it can pass NULL as the data
for the WA_PubScreen tag to open a window on the default public
screen.

The following example shows how to open a visitor window on a specific
public screen or, if that screen can't be found, on the default public
screen.

    struct Screen *screen;
    struct Window *window;
    UBYTE namebuffer[MAXPUBSCREENNAME];

    if (!(screen = LockPubScreen("CATScreen"))) {
        /* Can't lock CATScreen, fall back on default */
        /* The method used in this example to fall back on the default
           screen is not necessary and is provided only to illustrate
           the usage of GetDefaultPubScreen().
        */
        GetDefaultPubScreen(namebuffer);
        /* Lock it, so it can't go away. */
        /* If in this split second another screen is made the default
           and this one closes, screen would become NULL and the window
           will open on the default public screen anyway.
        */
        screen = LockPubScreen(namebuffer);
    }
    if (window = OpenWindowTags(NULL,
                    WA_Left, 0, WA_Width, screen->Width,
                    WA_Top, screen->BarHeight,
                    WA_Height, screen->Height - screen->BarHeight,
                    WA_PubScreen, screen,
                    WA_Flags,
                    WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE|ACTIVATE|
                              SIMPLE_REFRESH|NOCAREREFRESH,
                    WA_Title, "AmigaMail Visitor window", TAG_END)) {
        /* Don't need the lock anymore. */
        UnlockPubScreen(NULL, screen);
                        .
                        .
                        .
        CloseWindow(window);
    } else UnlockPubScreen(NULL, screen);   /* OpenWindow failed for
                                           some other reason */

In this code example, once it is locked (first by LockPubScreen(),
later by the visitor window) the screen can't go away until all its
visitors have left.  After opening its initial visitor window, an
application can open non-visitor windows on a public screen, however
these windows will have to be closed before releasing the lock on the
public screen.

When opening a visitor window, the public screen on which it opens
can be specified by using a pointer to the screen (with the
WA_PubScreen tag) or by supplying the screen name (using the
WA_PubScreenName tag).  This latter method is particularly useful
where an application prefers a specific public screen, but can run
using the default public screen.  If the preferred public screen is
not present when an application attempts to open a visitor window,
the window will either open on the default public screen or will fail
to open depending on the WA_PubScreenFallBack tag. If this tag is
present and is set to TRUE, the window will open on the default
screen.  If WA_PubScreenFallBack is not present or is set to FALSE,
the window will not open.


Overscan

In release 2.0, Intuition fully supports video overscan.  There are
four standard overscan specifiers: OSCAN_TEXT, OSCAN_STANDARD,
OSCAN_MAX and OSCAN_VIDEO.  OSCAN_TEXT is based on user preference
settings and indicates a display which is within the visible bounds
of the monitor.  The dimensions of this type of overscan are used for
the Workbench screen and for the defaults for OpenScreenTagList(),
STDSCREENWIDTH and STDSCREENHEIGHT.  OVERSCAN_STANDARD is also based
on user preference settings.  The edges of an OVERSCAN_STANDARD
display are set by the user via Preferences to be just outside the
visible bounds of the monitor.  OSCAN_MAX is the largest display
fully supported by Intuition.  OSCAN_VIDEO is the largest display
region which, for a given display mode, can be reliably generated.
Note that OSCAN_VIDEO displays are not scrollable.

The Intuition function QueryOverscan() returns rectangle information
for the indicated overscan type of a particular display mode.  Using
the rectangle returned by QueryOverscan(), it is possible to
explicitly specify the offset and dimensions of the DisplayClip
region.  Note however that this custom rectangle must fit within the
OSCAN_MAX rectangle, offset included.  It is not permitted to specify
custom rectangles whose values are in between OSCAN_MAX and
OSCAN_VIDEO, nor is it permitted to specify rectangles larger than
OSCAN_VIDEO.


DisplayClip

The DisplayClip defines the on-monitor region, and is independent of
the screen dimension.  The rectangle describing the DisplayClip
determines how much of the screen can be seen at a time.  The screen
is "shown through" the DisplayClip in much the same way a SuperBitmap
is shown through a window.  If the screen is larger than the
DisplayClip, only part of the screen will be visible.  The DisplayClip
makes it is possible for Intuition to support hardware scrolling of a
raster larger than can fit on the display.  Intuition will take care
of specifying the rectangle of the DisplayClip region based on the
default screen dimensions or based on the SA_Overscan tag (if it is
present), so most programs shouldn't have to specify the DisplayClip
rectangle.

Example 3, ScreenDisplayModes.c, illustrates opening any type of
screen currently available to the system, using any type of available
overscan.


IV-17: Opening Screens and Windows on Any Amiga

by Ewout Walraven

The release 2.0 intuition.library has a multitude of new display
possibilities at its disposal that developers can use to improve their
software.  Many products can benefit from the flexibility that higher
display resolutions and larger display areas offer and from the
polished user interface available with the "New Look" in release
2.0.  Because backward compatibility with 1.3 is important to many
developers, these new features should be used in a way that will work
with older systems.

This article shows how to take advantage of the display resources
available to Intuition under any Amiga system.  This article assumes
the reader has some knowledge of release 2.0 (V36) screens and
windows.  For more information, see the article
"An Introduction to V36 Screens and Windows" from the
September/October 1990 issue of Amiga Mail.

 Opening Full Size Screens
 PAL or NTSC?
 Opening Full Sized Windows


Opening Full Size Screens

Under pre-V36 versions of the operating system, a method commonly used
to open a screen according to user preference was to "clone" the
Workbench screen (to create a screen with the same resolution and view
mode as the Workbench screen).  Normally, applications called the
Intuition function GetScreenData() to learn the Workbench screen's
resolution and display mode.

Programmers should no longer rely on GetScreenData() to return the
actual resolution and display mode under release 2.0.  When asked
about the Workbench screen, the V2.0 GetScreenData() returns the video
mode of a Hires screen, or, if the screen is interlaced, a Hires
interlaced screen.  The dimensions GetScreenData() returns will be the
lesser of either the OSCAN_TEXT dimensions or the actual Workbench
screen dimensions.  This change to GetScreenData() prevents some
programs developed for 1.3 from opening full size screens and windows
under 2.0.  The change had to be made to avoid confusing programs that
couldn't handle the higher resolutions and new display modes that are
available in release 2.0.  For example, when GetScreenData() is called
on a system using a SuperHires interlaced Workbench screen, it returns
the dimensions and view mode of a Hires interlaced screen.  If
GetScreenData() had supplied the actual resolution instead, a program
that assumed the resolution could not be greater than 640x400 could be
severely crippled.  The exception to this rule is a system running in
one of the A2024 (or Hedley Hires) modes.  To remain compatible with
the V35 version of GetScreenData(), the release 2.0 version returns
the correct dimensions of a screen in A2024 mode.

Another method previously used to get information about the Workbench
screen was to look at the GfxBase->NormalDisplayRows and
GfxBase->NormalDisplayColumns fields.  As with GetScreenData(), these
fields contain the dimensions of a text overscan Hires (or Hires
interlace) screen.  Obviously, these fields should no longer be used
to obtain the actual dimensions of the Workbench screen.

To clone the Workbench screen under 2.0, lock the Workbench screen,
get the screen's display mode ID, and get the necessary display
information.  The article "An Introduction to V36 Screens and Windows"
from the September/October 1990 issue of Amiga Mail contains the
example CloneWB.c which illustrates cloning the Workbench screen
under release 2.0.  Any application that wants to clone the Workbench
screen should be prepared to handle any type of screen, because the
user can change the Workbench screen to any type of screen they
desire.


PAL or NTSC?

Some programs need to determine if the Workbench screen is in PAL or
NTSC mode.  Before release 2.0, it was impossible for the system to
switch between NTSC and PAL.  The PAL/NTSC state in which the machine
booted dictated the mode of its displays.  Pre-V36 systems could
determine the PAL/NTSC state of the machine by examining a bit the in
GfxBase->DisplayFlags field, which is set at boot time under all
versions of the OS.

Thanks to the ECS and the new system software, PAL and NTSC display
resolutions can coexist, which obsoletes examining GfxBase->DisplayFlags
to determine the PAL/NTSC state of a particular system.  Release 2.0
ignores the PAL/NTSC flag after it sets the flag at boot time.  This
means that under 2.0, if the system boots as NTSC, it is not possible
to open a PAL screen in a way that will work correctly with release 1.3.

To respect the user setup of the Workbench rather than the default
video mode, a program should use the V36 graphics.library and
intuition.library functions to determine the display mode ID of the
Workbench screen.  Using that ID, an application can open a screen or
find more information about the properties of the Workbench screen.
The extscreen.c example at the end of this article shows how to check
for a PAL mode screen under any version of the operating system.


Opening Full Sized Windows

Because there is no guarantee that GetScreenData() will return the
correct screen resolution, programs can't use it to obtain the
dimensions needed to open a full sized window.  To get the correct
screen resolution of the Workbench screen, programs have to examine
the Height and Width fields of the Screen structure returned by
LockPubScreen().

To make supporting new and old versions of the operating system
easier, Intuition V36 offers a way to open screens and windows that is
compatible with previous versions of the Amiga OS.  Instead of
requiring the use of new functions to open V36 specific screens and
windows, the OpenWindow() and OpenScreen() functions each accept an
extended structure, ExtNewWindow and ExtNewScreen, respectively.
These structures allow the programmer to pass tags to the V36
OpenScreen() and OpenWindow() functions while remaining compatible
with older versions of these functions.  Older versions of Intuition
ignore the excess baggage at the end of the structure where the tags
are kept.  These tags are partially used in V35 (a 1.3 release) to
support the A2024 modes.  Note that the ExtNewScreen and ExtNewWindow
structures may be extended in the future, so programs must not assume
their size is static.

To use the "New Look", pass the SA_Pens tag and a pen array in
ExtNewScreen.  Using the New Look requires a little bit more
responsibility from an application.  Programs that aren't careful can
experience problems with the layout of graphics and gadgets in New
Look windows and screens.  For example, a lot of programs made
assumptions about the height of a window's title bar.  Under 1.3, this
didn't present much of a problem because the title bar height didn't
normally change.  Under 2.0, the user can choose system fonts, varying
the size of the title bar.  Graphics and gadgets rendered into the
application's window can write over the title bar if the application
isn't careful.

The example at the end of this article, extscreen.c, illustrates how
to open a screen and window under release 2.0, using 2.0 specific
features if they are available, while staying compatible with older
versions of the operating system.  This example will open a screen in
A2024 mode (under V37, V36, or V35) if the resources are available.


IV-23: Introduction to Boopsi

By John Orr

Boopsi is an acronym for Basic Object Oriented Programming System for
Intuition.  On its simplest level, boopsi allows the application
programmer to create Intuition supported gadgets and images with minimal
overhead.  It allows a program to consolidate gadgets into one entity to
make processing and updating easy.  On a more sophisticated level,
boopsi provides ways to create a wide variety of system supported,
extensible custom gadgets.

Understanding boopsi requires an understanding of several of the
concepts behind Object Oriented Programming (OOP).  This article only
briefly covers those concepts.  For a more in depth explanation of those
concepts, see Timothy Budd's book titled A Little Smalltalk (Addison-
Wesley Publishing ISBN 0-201-10698-1).  A port (by Bill Kinnersley) of
Timothy Budd's Little Smalltalk interpreter is on Fish disk #37.

In the boopsi version of the Object Oriented Programming (OOP) model,
everything is an Object.  Each object is a distinct entity.  Certain
objects have similar characteristics and can be classified into
different groups called classes.  As objects, a dog, a cat, and a mouse
are all distinct objects but they all have something in common; they can
all be classified as animals.  A specific object is an instance of a
particular class ("Rover" is an instance of class "dog").

Classes can be subdivided into subclasses.  A vegetable object class can
have several subclasses such as peas, corn, and spinach.  Inversely, the
superclass of peas, corn, and spinach is "vegetable".  In turn, both
the "animal" and "vegetable" classes are subclasses.   They are
subclasses of a universal root category.  The OOP language Smalltalk
calls this class "Object".

                      Figure 1 - Classes

                            object
                               |
                    ___________|__________
                   /                      \
                  /                        \
               animal                  vegetables
                 |                          |
            _____|_____                _____|_____
           /     |     \              /     |     \
          /      |      \            /      |      \
        dog     cat    mouse       peas    corn  spinach

In boopsi, the universal root category is called rootclass.  Intuition
supplies three subclasses of rootclass: gadgetclass, imageclass, and
icclass.  All boopsi gadgets in the system are an instance of
gadgetclass.  Likewise, all boopsi images are an instance of imageclass.
The remaining subclass, icclass, is a concept new to Intuition that
allow one boopsi object (such as a gadget) to notify another boopsi
object when some specific event occurs.    For example, a program can
offer a user two methods of altering one integer value; one by sliding a
proportional gadget, the other by typing in a value at a string gadget.
Without boopsi, the program would have to explicitly update one gadget
when the other was altered by the user.  Using a boopsi icclass object,
the gadgets can update each other.  The gadgets update each other
automatically, without the calling program's intervention.

The rootclass' subclasses each have their own subclasses.  These
subclasses are discussed later in this article.

                 Figure 2 - The Boopsi Classes

                            rootclass
                               /
                 _____________/____________
                /         /                \
               /         /                  \
           icclass      /                gadgetclass
             /         /                      \
            /         /         _______________\___________________
           /     imageclass    /           /         \             \
          /         /         /           /           \             \
     modelclass    /      propgclass  strgclass  buttongclass  groupgclass
                  /                                     \
                 /                                       \
         _______/___________________________        frbuttongclass
        /         \            \            \
       /           \            \            \
  frameiclass  sysiclass  fillrectclass  itexticlass

It is possible for an application to create its own custom boopsi class.
When an application creates a class, it can make it either public or
private.  A public class has a name associated with it (for example
gadgetclass) so arbitrary applications can access it.  A private class
has no name associated with it, so unless an application has a pointer
to the class, it cannot access it.

Each class has a set of methods associated with it  Each method of a
class is an operation that applies to objects of that class.  A example
of a method for a class of integers is to add or to subtract "integer"
objects.  All boopsi actions are carried out via methods.

In OOP terminology, an application requests an object to perform some
method by sending the object a message (which is not related to the Exec
style message).  In boopsi, the amiga.lib function DoMethod() accepts a
method ID and some method specific parameters (older versions of
amiga.lib do not have DoMethod(), but the function is available on the
Atlanta DevCon disks in classface.o).  DoMethod() creates a message from
these parameters and sends the message to the object:

    ULONG DoMethod(Object *myobject, ULONG MethodID, ...);

where myobject is a pointer to the target object, MethodID specifies
which method to perform.  Any remaining parameters are passed on to the
method in the form of a boopsi message.  Each message contains the
method ID and the parameters for the method.  The parameters are method
specific.  For example, one way to delete the imageclass object
obj2delete is to call the DoMethod() function like this:

    DoMethod(obj2delete, OM_DISPOSE);

The OM_DISPOSE method does not require any arguments, so, in this case,
DoMethod() has only two arguments.

One peculiar thing about the above function call is that the OM_DISPOSE
method is not defined for imageclass.  It is instead defined in the
superclass of imageclass, rootclass.  The OM_DISPOSE method works
because imageclass inherits the methods of its superclass, rootclass.
If an object is asked to perform a method that its class does not
explicitly define, it passes the request onto its superclass for
processing.  This superclass can in turn pass on the request to its
superclass if it does not understand the method requested.

Some of the methods currently defined for Boopsi's rootclass are:

OM_NEW - Creates a new object.  Normally this method is not called
directly by the application programmer (a.k.a. using the DoMethod()
function).  Instead, there is an Intuition function called NewObject()
that takes care of creating objects.

    APTR NewObject( struct IClass *privateclass, UBYTE *publicclassID,
                      unsigned long tag1, ...);

The privateclass and publicclassID parameters are used to specify the
new object's class. NewObject() only pays attention to one of these.
If privateclass is NULL, publicclassID points to a string naming the
class of the new object.  If privateclass is not NULL, it contains a
pointer to a private class.  The remaining arguments make up a series
of tag ID/data pairs.  These are used to set the object's default
attributes.  These attributes are specific to the class in question.
This function returns a handle to the new object.

Each object (or instance of a class) has instance data associated with
it.  The OM_NEW method takes care of allocating memory for the instance
data for each class.  Instance data is class specific, but all
subclasses inherit instance data from their superclasses.  For example,
part of the instance data for a gadgetclass object is a Gadget
structure.  Any objects that are instances of subclasses of gadgetclass
have a Gadget structure embedded in them.  Subclasses can have their own
class specific instance data in addition to the instance data inherited
from the superclass.

Boopsi gadgetclass and imageclass objects are organized so that
NewObject() returns a pointer to the corresponding Intuition structure
embedded within them (struct Gadget and struct Image, respectively).
This makes it possible to use non-boopsi Intuition functions on boopsi
objects.  Normally, these internal structures should be considered
private, and should be accessed through the corresponding attributes,
but if it is necessary, an application can look at certain fields in the
embedded structure.  For both gadgets and images, the Left, Top, Width,
and Height fields are legal to look at.  The Images NextImage field is
also OK for viewing.  However, this does not mean that it is OK for an
application to go poking around the internals of boopsi objects.  All
boopsi objects are strictly private and can change without notice.  Use
only the functions Intuition provides for manipulating boopsi objects.

Another function, NewObjectA(), works exactly like NewObject(), but
instead of accepting the tag pairs as arguments, it accepts a single
pointer to a TagList.  See the Intuition Autodocs for more details.

OM_DISPOSE - Deletes an object.  Like OM_NEW this method is not normally
called directly by the application program.  Instead there is an
Intuition function DisposeObject() that takes care of object disposal.

    void DisposeObject( APTR object2delete );

OM_SET - Sets object specific attributes.  This method is not normally
called by the application program directly.  Instead, there are two
Intuition functions that set object attributes:

    ULONG SetAttrs( APTR object, unsigned long tag1, ... );

    ULONG SetGadgetAttrs( struct Gadget *mygadgetobject, struct Window
        *window, struct Requester *requester, unsigned long tag1, ... );

SetAttrs() accepts as arguments a pointer to the object in question and
a series of tag pairs corresponding to the attributes to set.
SetGadgetAttrs() is a special version of SetAttrs() that is required to
change the attributes of gadgetclass objects.  SetGadgetAttrs() is
similar to SetAttrs(), except it has some extra parameters that a gadget
needs to redraw itself in response to the attribute changes.  This
function can be used on non-gadgetclass objects as the gadget specific
parameters are ignored by the other object classes.  If the gadget is
not yet attached to a window or requester, these arguments should be set
to NULL.

Both of these functions have corresponding TagList based arguments,
SetAttrsA() and SetGadgetAttrs().

OM_GET - Reads an object specific attribute.  The Intuition function
GetAttr() provides easy access to this method:

    ULONG GetAttr( unsigned long attrID, APTR object, ULONG *storagePtr );

GetAttr() fills in storagePtr with the value of the object's attribute
attrID.  The function returns FALSE if there is an error.

OM_ADDMEMBER - Adds a boopsi object to another object's list, if it has
one.  Certain object classes have an Exec list as part of their instance
data.  To add the object object2add to the list of the object mainobject
use DoMethod() like so:

    DoMethod(mainobject, OM_ADDMEMBER, object2add);

DoMethod() also has a non-varargs form called DM() (also in amiga.lib).
DM() accepts an object pointer and a pointer to a structure specific to
a method.  For example, the DM() form of the above DoMethod() call would
look like this:

    DM(mainobject, addmemstruct);

where addmemstruct is a pointer to the following structure (defined in
<intuition/classusr.h>):

    struct opMember {
        ULONG    MethodID;      /* in this case MethodID = OM_ADDMEMBER */
        Object   *opam_Object;  /* = addmemstruct */
};

OM_REMMEMBER - Removes a boopsi object previously added with
OM_ADDMEMBER.  The parameters are the same for OM_ADDMEMBER.

OM_UPDATE - Updates attributes of an object.  For gadgets, this method
is very similar to the OM_SET method.  It is normally used only between
objects for notifying each other of attribute changes, so simple boopsi
users should use the SetAttrs() and SetGadgetAttrs() functions.

OM_NOTIFY - Notifies one object when another object's attribute(s) have
changed.  It is normally used only between objects for modifying each
others attributes, so simple boopsi users should use the SetAttrs() and
SetGadgetAttrs() functions.

 Attributes                 Gadgetclass Subclasses      Appendix
 Imageclass Subclasses      Interconnection


Attributes

All boopsi objects have attributes associated with them.  These
attributes reflect various properties of a specific object.  For
example, an image object has attributes such as IA_Left, IA_Top,
IA_Width, and IA_Height, all of which correspond to fields in the Image
structure.  Five methods deal with an object's attributes:

  OM_NEW sets attributes at object creation (initialization) time
  OM_SET changes attributes after the object has been created
  OM_GET reads an object attribute
  OM_UPDATE updates an object attribute (for use by objects only)
  OM_NOTIFY notifies one object of changes to another object's attributes

Not all of these methods apply to all attributes.  Some attributes are
not "settable" or not "gettable", for example.   See the appendix at
the end of this article to find out which of these methods apply to
specific attributes.


Imageclass Subclasses

An imageclass object contains an Image structure that Intuition uses to
render objects such as gadgets.  Boopsi imageclass objects are organized
so that when NewObject() returns a pointer to an imageclass object, it
points to the actual Image structure.

Normally, an application does not create an imageclass object.  Instead,
it will use a subclass of imageclass.  Currently, there are four
subclasses:  frameiclass, sysiclass, fillrectclass, and itexticlass.

frameiclass - An embossed or recessed rectangular frame, rendered in the
  proper DrawInfo pens, with enough intelligence to bound or center its
  contents.

sysiclass - The class of system images.  The class includes all the
  images for the system gadgets, and the Gadtools check mark and button
  glyphs.

fillrectclass - Rectangle with frame and pattern support.

itexticlass - A specialized image class used for rendering text.  Note
  that you have to calculate itexticlass object's width and height
  yourself.


Gadgetclass Subclasses

A gadgetclass object contains an Intuition Gadget structure.  Like
imageclass, applications do not normally create objects of this class,
but instead create objects of subclasses of gadgetclass.  Currently,
gadgetclass has four subclasses:

propgclass - An easy to use, one-dimensional proportional gadget.

strgclass - A string gadget.

groupgclass - A special gadget class that creates one composite gadget
  out of several others.

buttongclass - A repeating boolean button gadget.

buttongclass has a subclass of its own:

frbuttongclass - A button that outlines its label with a frame.

The example boopsi1.c (at the end of this article) uses sysiclass images
and several boopsi gadgets.  The example takes care of processing and
updating the gadgets.


Interconnection

The boopsi gadgets in boopsi1.c are not very powerful.  The gadgets work
independently of each other, forcing the application to unify them.  It
is possible to make gadget objects update each other without the
application's intervention.

Gadgetclass defines two attributes used in this updating process:
ICA_Target and ICA_Map.  The ICA_Target attribute specifies a pointer to
a target object.  If an object's attribute changes (and the OM_NOTIFY
method applies to that attribute), the object sends itself an OM_NOTIFY
message.  If the object has a target object, the target will receive an
OM_UPDATE message which usually tells the target to set one of its own
attributes.  For example, when the user slides the knob of a propgclass
object, its PGA_Top attribute changes.  If this object has a second
propgclass object as its target, the second object will receive an
OM_UPDATE message and will set its corresponding PGA_Top attribute to
the PGA_Top value of the first propgclass object.

Because objects of different classes do not always have corresponding
attributes, there is a way to map attributes of one object to the
attributes of another.  The ICA_Map accepts a TagItem array of attribute
pairs.  The first entry in the pair is the source attribute ID and the
second is the target object's attribute.  For example, an ICA_Map that
maps a prop gadget's PGA_Top attribute to a string gadget's
STRINGA_LongVal attribute would look like this:

    struct TagItem slidertostring[] = {
        {PGA_Top, STRINGA_LongVal},
        {TAG_END, }
    };

Note that the OM_UPDATE method has to apply to the target attribute for
the change to take place.

Although the gadget attributes ICA_Target and ICA_Map allow boopsi
gadgets to update each other, by themselves these attributes do not
provide the application with any information on changes to the gadgets.
Instead of using another gadget as a target object, an object targets an
icclass object.  Icclass  (or InterConnection) objects are simple
information forwarders.

Icclass defines two attributes: ICA_Target and ICA_Map, which are almost
identical to the gadgetclass attributes.  The difference is that icclass
objects can send the application an IDCMPUPDATE IntuiMessage when it
receives an OM_UPDATE.  If an icclass object receives an OM_UPDATE, it
will send the IntuiMessage only if the icclass object's ICA_Target is
ICTARGET_IDCMP and the updated attribute is mapped to a special dummy
attribute, ICSPECIAL_CODE.  The IntuiMessage's Code field contains the
lower 16 bits of the updated attribute.

Icclass has a more powerful subclass called modelclass.  A modelclass
object sends OM_UPDATE messages to an entire list of objects that the
modelclass object maintains.  This makes it possible for gadgets to
update each other and for the application to find out about the changes.
A modelclass object "broadcasts" attribute changes to its list of
boopsi objects and it also lets the application know about attribute
changes because it inherits the ICTARGET_IDCMP mechanism from icclass.
To add objects to a modelclass object's list, use the OM_ADDMEMBER
method.

The power of icclass and modelclass lies in using them to create a
custom subclass.  Consider a group of prop gadgets each of which is used
to control one of a color's R, G, B, H, S, and V components.  When the
user changes one of the color components with a prop gadget, the custom
model will be notified of that change and, because it is customized for
this specific purpose, it will recalculate the values for the remaining
components.   The model will then let the rest of the prop gadget
objects (which are attached to icclass objects in the custom model's
personal list) know about the changes to their component values so they
can move their slider to its new position.  All this work is done by the
objects themselves; the application does not have to process any of the
intermediate input.

In general, boopsi's power lies in its Intuition-supported
extensibility.  Using the existing boopsi classes as a foundation,  you
can create entirely new subclasses.  This makes it possible to create
your own custom gadgetry and have it work perfectly with Intuition, just
like any existing gadget.   New subclasses of modelclass can be used to
create gadgets that talk directly to ARexx or the clipboard device.  If
new classes are general enough, they can be made public so other
applications can use them.


IV-41: Writing a Boopsi Image Class

By David N. Junod

    Editor's note: this article and its source code reference
    several functions that, at press time, were only available from
    the classface.asm and hookface.asm assembly source files that
    appear on the Atlanta and Milan DevCon disks.  The functions
    from these files should eventually appear in amiga.lib.

The most sophisticated level of Intuition programming is to write a boopsi
class.  The easiest way to enter the boopsi class writer's arena is to
write an image class.

Boopsi's imageclass is one of the standard classes built into Intuition.
As its name implies, it is a class of Intuition Images.  These boopsi
images can be used in place of traditional Image structure (as they
contain an Intuition Image structure), but they are much more powerful.
By using boopsi methods, an application or Intuition can tell an
imageclass object to render itself.  Because it renders itself (rather
than Intuition rendering it), the imageclass object is free to render
whatever it wants (well, within reason).  For example, a boopsi image
object can render itself according to the current display resolution, or
to scale itself to any size an application requests.

This article is designed to provide the novice boopsi programmer with the
information needed to write an image class for their application.  This
article assumes the reader is already familar with some boopsi concepts.
For more information on boopsi, see the article "Introduction to Boopsi"
in the March/April 1991 issue of Amiga Mail or the Atlanta (or Milan)
DevCon notes and disks.  The example custom class at the end of this
article, mytextlabelclass.c, shows how to create a custom image class that
renders a text label with an underline beneath a character.  This
character can be used to trigger some event.

When designing a specific class, you must first choose a superclass that
is suitable for your needs.  If you are creating a new image class, then
its superclass will either be imageclass or some subclass of imageclass.

Classes may be public or private.  Any application can access a public
class.  Before a class can be considered public it must first have a name
and must be part of  the public class list maintained by Intuition.  It
can then be accessed by other applications.  A private class is not in the
public class list and can only be used by applications that have a pointer
to the Class structure (usually the application that implemented the
class).

 Callback Hooks                   Boopsi Rootclass Methods
 Initializing a Boopsi Class      Imageclass Methods
 Boopsi Dispatcher                Image Class Example


Callback Hooks

When you present a custom image to Intuition, you provide a pointer to a
Hook structure that Intuition uses to find functions needed by various
image operations.  Without going into great detail, a hook provides a
pointer to a function that the system calls using Amiga register parameter
conventions.  The hook supplies enough information to conveniently
transfer control to a High-Level Language (HLL) entry point.  Boopsi
imageclass objects provide Intuition with a hook to a method dispatcher
function.

The Hook structure is defined as follows (from <utility/hooks.h>):

    /* new standard hook structure */
    struct Hook
    {
        struct MinNode  h_MinNode;
        ULONG       (*h_Entry)();   /* stub function entry point */
        ULONG       (*h_SubEntry)();/* the custom function entry point */
        VOID        *h_Data;        /* owner specific */
    };

The assembly language stub for C parameter conventions that boopsi classes (and custom gadgets) require is:

    _hookEntry:
        move.l  a1,-(sp)                ; push message packet pointer
        move.l  a2,-(sp)                ; push object pointer
        move.l  a0,-(sp)                ; push hook pointer
        move.l  h_SubEntry(a0),a0       ; fetch C entry point ...
        jsr     (a0)                    ; ... and call it
        lea     12(sp),sp               ; fix stack
        rts

The C language stub, for C compilers that support registerized parameters
is:

    /* This function converts register-parameter hook calling
     * convention into standard C conventions.  It requires a C
     * compiler that supports registerized parameters, such as
     * SAS/C 5.xx or greater.
     */
    ULONG __asm hookEntry(
        register __a0 struct Hook *h,
        register __a2 VOID *o,
        register __a1 VOID *msg)
    {
        return ((*h->h_SubEntry)(h, o, msg));
    }


Initializing a Boopsi Class

You need some simple code to initialize a class and its hook.  When
initializing a class, you specify the size of the class's instance and
what the superclass is, and you also have to supply a pointer to a hook
entry stub.

The following code fragment illustrates the initialization of a private
subclass of imageclass.

    ULONG __saveds dispatchmyTextLabel();

    /* This is the data that each instance of our class will need. */
    struct localObjData
    {
        /* Font to use */
        struct TextFont *lod_Font;

        /* The key that is underlined */
        UWORD lod_Key;

        /* DrawMode */
        UBYTE lod_Mode;
    };

    #define MYCLASSID           NULL
    #define SUPERCLASSID        (IMAGECLASS)
    #define LSIZE               (sizeof(struct localObjData))

    Class *initmyTextLabelClass (VOID)
    {
        extern ULONG __saveds dispatchmyTextLabel();
        extern ULONG hookEntry ();        /* defined in hookface.asm */
        Class *cl;

        if (cl = MakeClass (MYCLASSID, SUPERCLASSID, NULL, LSIZE, 0))
        {
            /* Fill in the callback hook */
            cl->cl_Dispatcher.h_Entry = hookEntry;
            cl->cl_Dispatcher.h_SubEntry = dispatchmyTextLabel;
        }

        /* Return a pointer to the class */
        return (cl);
    }

In order to make the class public instead of private, do the following:

    #define MYCLASSID           "mytextlabelclass"

    ULONG __saveds dispatchmyTextLabel();

    Class *initmyTextLabelClass (VOID)
    {
        extern ULONG __saveds dispatchmyTextLabel();
        extern ULONG hookEntry ();
        Class *cl;

        if (cl = MakeClass (MYCLASSID, SUPERCLASSID, NULL, LSIZE, 0))
        {
            /* Fill in the callback hook */
            cl->cl_Dispatcher.h_Entry = hookEntry;
            cl->cl_Dispatcher.h_SubEntry = dispatchmyTextLabel;

            /* Make the class public */
            AddClass (cl);
        }

        /* Return a pointer to the class */
        return (cl);
    }


Boopsi Dispatcher

Now all you need to do is implement a dispatcher routine.  When the
dispatcher is in operation, Intuition passes method IDs to it.  The
dispatcher will either execute code corresponding to the a method ID (the
code is usually part of the dispatcher) or delegate processing the method
to the superclass (or it can do a little of both).

The following fragment provides an example of what a dispatcher for a
boopsi class looks like (Note that __saveds (Save DS) is used to insure
that register A4 is set up properly for indirect addressing with the SASC
compiler):

   ULONG __saveds dispatchmyTextLabel (Class *cl, Object *o, Msg msg)
   {
       struct localObjData *lod;
       Object *newobj;
       ULONG retval;

       switch (msg->MethodID)
       {
           /* Create a new object */
           case OM_NEW:
               /* Have our superclass create it.  DSM() passes on the
                * message to the superclass, where msg is the structure
                * containing the message specific parameters.
                */
               if (newobj = (Object *) DSM (cl, o, msg))
               {
                   /* Set the attributes */
                   setmyTextLabelAttrs(cl, newobj, (struct opSet *) msg);
               }

               retval = (ULONG) newobj;
               break;

           /* Obtain information on an attribute */
           case OM_GET:
               retval = getmyTextLabelAttrs (cl, o, (struct opGet *) msg);
               break;

           /* Set attributes */
           case OM_UPDATE:
           case OM_SET:
               /* Let the superclass set the attributes that it
                * knows about. */
               retval = DSM (cl, o, msg);

               /* Set the attributes that we care about */
               retval |= setmyTextLabelAttrs (cl, o, (struct opSet *) msg);
               break;

           /* Draw the various states that the image supports */
           case IM_DRAW:
           case IM_DRAWFRAME:
               retval = drawmyTextLabel (cl, o, (struct impDraw *) msg);
               break;

           /* Let the superclass handle everything else */
           default:
               retval = (ULONG) DSM (cl, o, msg);
               break;
       }

       return (retval);
   }


Boopsi Rootclass Methods

Since all classes should be subclasses of some class, with the exception
of rootclass, all classes you write will be subclasses--perhaps indirectly
so--of rootclass.  Because of this, your class must either implement the
rootclass methods or defer processing of these methods to the superclass
(as DispatchmyTextLabel() did).  Provided below are brief descriptions of
the rootclass methods.  Remember that any message unrecognized by a class
dispatcher should be passed to the superclass (using the amiga.lib
functions DSM() or DoSuperMethod() ).

The rootclass method IDs that a subclass of imageclass needs to understand
are:

    OM_NEW			Create a new object.
    OM_DISPOSE		Delete an object.
    OM_SET			Change an object's attributes.
    OM_GET			Retrieve the value of one of the object's attributes.

The dispatcher should pass other rootclass methods on to the superclass.

Each method requires one or more parameters.  The MethodID is the only
common parameter for each method.

 OM_NEW      OM_DISPOSE      OM_SET      OM_GET


OM_NEW

The OM_NEW method receives the following arguments:

    struct opSet
    {
        ULONG MethodID;
        struct TagItem *ops_AttrList;
        struct GadgetInfo *ops_GInfo;
    };

The ops_AttrList field contains a pointer to the TagItem array of
attributes for the new object.  The ops_GInfo field is always NULL for the
OM_NEW method.

Unlike other methods, this method is not passed an object pointer (since
the whole idea is to create an object).  The pointer normally used to pass
a boopsi object is instead used to pass the address of the object's "true
class" (the class the object is an instance of).  That way, all class
dispatchers can tell if they are the "true class" of the object being
created (as opposed to a superclass of the true class).  Also, with this
pointer, rootclass can determine what the instance data is for an object,
and can allocate the right amount of memory for it.

For the OM_NEW method, the new class's dispatcher should do the following:

1) Pass the message along to the superclass.  All classes do this as
   rootclass takes care of allocating memory for the new object.  As the
   OM_NEW method works "top down" (from rootclass down through its
   subclasses to the true class), each class will in turn initialize its
   corresponding instance data.  This all happens before the new class's
   dispatcher regains control.  Eventually, the message comes back from
   the superclass with a newly allocated object (unless of course
   something failed and you receive a NULL pointer instead).

2) Obtain a pointer to the object's instance data for this class.  Use the
   INST_DATA() macro (defined in <intuition/classes.h>).  INST_DATA()
   takes two arguments, a pointer to your class and a pointer to the
   object.

       void *INST_DATA(*Class, *Object);

3) Initialize your instance data.  You may allocate additional memory
   buffers for your object, or even create other objects which are
   components to objects of your class.

4) Process your initial attribute list (from the opSet structure passed in
   the OM_NEW message).  In particular, process all the attributes that
   can be set only at initialization time.  After you deal with the
   "initialization only" attributes, apply the same attribute processing
   on these remaining attributes that you would apply to an OM_SET
   message.

5) Return the object to the caller.


OM_DISPOSE

The OM_DISPOSE method instructs the class to deallocate an object. This
method receives no parameters.

For the OM_DISPOSE method, the new class's dispatcher should do the
following:

1) Free any additional memory you allocated (memory allocated in step
   3 from OM_NEW).

2) Dispose of any objects that you created as components of your
   object (component objects created in step 3 from OM_NEW).

3) Pass the message up to the superclass, which will eventually reach
   rootclass, which will free the memory allocated for the object.

The mytextlabelclass example at the end of this article does not allocate
any extra resources when it creates an object.  Because it does not have
to release any resources, the mytextlabelclass dispatcher lets its
superclass handle the OM_DISPOSE method. Eventually, some superclass of
mytextlabelclass will deallocate all of the memory for the OM_DISPOSEd
object.


OM_SET

This method is used to set an object's attributes.  The Intuition function
SetAttr() calls this method.  It receives the following arguments:

    struct opSet
    {
        ULONG MethodID;
        struct TagItem *ops_AttrList;
        struct GadgetInfo *ops_GInfo;
    };

For the OM_SET method, the new class's dispatcher should process the
attributes your class recognizes and have the superclass process any
unrecognized attributes.  Note that a subclass dispatcher can directly
process attributes it inherits from a superclass, rather than passing the
message on to the superclass.

Note that mytextlabelclass treats the OM_UPDATE method exactly like the
OM_SET method.  This is OK because these two methods are functionally
equivalent for imageclass classes.


OM_GET

Retrieve an object's attribute.  This method receives the following
parameters:

    struct opGet
    {
        ULONG MethodID;
        ULONG opg_AttrID;
        ULONG *opg_Storage;
    };

If the new class recognizes the attribute, the new class should fill in
opg_Storage's target with the attribute's value.  If the attribute is
actually the attribute of some component object, you might want to pass
the message on and let the component object process the OM_GET. If
completely unrecognized, you should pass the message to your superclass.


Imageclass Methods

Imageclass defines several methods of its own which subclasses of
imageclass either have to implement or pass on to their superclass. The
method IDs for imageclass are defined in <intuition/imageclass.h>.  Each
method requires some parameters.  The MethodID is the only parameter
common to each method.

 IM_DRAW       IM_HITTEST        IM_ERASEFRAME      IM_MOVE
 IM_ERASE      IM_DRAWFRAME      IM_HITFRAME        IM_FRAMEBOX


IM_DRAW

The IM_DRAW method is used to tell the image to render itself.  The
Intuition function DrawImageState() uses this method.  IM_DRAW receives
the following parameters:

    struct impDraw
    {
        ULONG MethodID;
        struct RastPort *imp_RPort;
        struct
        {
            WORD X;
            WORD Y;
        } imp_Offset;

        ULONG imp_State;
        struct DrawInfo *imp_DrInfo;
    };

The imp_State field contains the visual state to render the image. The
visual states (defined in <intuition/imageclass.h>) are:

        IDS_NORMAL              idle state
        IDS_SELECTED            for selected gadgets.
        IDS_DISABLED            for disabled gadgets.
        IDS_BUSY                for future functionality
        IDS_INDETERMINATE       for future functionality
        IDS_INACTIVENORMAL      normal, in inactive window border.
    IDS_INACTIVESELECTED	selected, in inactive border.
    IDS_INACTIVEDISABLED	disabled, in inactive border.

When setting the pens to render an image, use the values from the
imp_DrInfo->dri_Pens pen array (Note that it is possible that imp_DrInfo
will be NULL).  The possible pen values are defined in
<intuition/screens.h>.

The following code fragment shows how to use the shadow color for
rendering.

    UWORD *pens = (imp->imp_DrInfo) ? imp->imp_DrInfo->dri_Pens : NULL;

    if (pens)
    {
        SetAPen (imp->imp_RPort, pens[SHADOWPEN]);
    }


IM_ERASE

The IM_ERASE method tells an image to erase itself.  The Intuition
function EraseImage() uses this method.  IM_ERASE receives the following
parameters:

    struct impErase
    {
        ULONG MethodID;
        struct RastPort *imp_RPort;
        struct
        {
            WORD X;
            WORD Y;
        } imp_Offset;
    };

The mytextlabelclass example doesn't know anything about this method, so
it blindly passes this message on to the superclass.  The superclass,
imageclass, will call the graphics.library function EraseRect() using the
dimensions found in the imageclass object's Image structure.


IM_HITTEST

IM_HITTEST returns true if a point is within the image.  The Intuition
function PointInImage() uses this method.  IM_HITTEST requires the
following parameters:

    struct impHitTest
    {
        ULONG MethodID;
        struct
        {
            WORD X;
            WORD Y;
        } imp_Point;
    };

The mytextlabelclass example blindly passes this method on to its
superclass.  The superclass, imageclass, will return TRUE if the point is
within the old Image structure box.


IM_DRAWFRAME

The IM_DRAWFRAME method instructs the image to render itself within the
confines of the given rectangle.  It receives the following parameters:

    struct impDraw
    {
        ULONG MethodID;
        struct RastPort *imp_RPort;
        struct
        {
            WORD X;
            WORD Y;
        } imp_Offset;

        ULONG imp_State;
        struct DrawInfo *imp_DrInfo;

        struct
        {
            WORD Width;
            WORD Height;
        } imp_Dimensions;
    };

The Width and Height fields provide the object's rectangular bounds. How
the image object deals with the frame is implementation specific.
Typically, a scaleable image will scale itself as best it can to fit into
the rectangle.  The mytextlabelclass.c example does not actually implement
this method, instead mytextlabelclass treats IM_DRAWFRAME like the IM_DRAW
method.

In general, applications that use this method to draw an object should use
the IM_ERASEFRAME method (see below) to erase it.  This will ensure that
the image was erased at the proper scale.


IM_ERASEFRAME

The IM_ERASEFRAME method instructs an image confined to a given rectangle
to erase itself.  Normally this method is used to erase an image drawn
using the IM_DRAWFRAME method.  This method expects the following
parameters:

    struct impErase
    {
        ULONG MethodID;
        struct RastPort *imp_RPort;
        struct
        {
            WORD X;
            WORD Y;
        } imp_Offset;

        /* these parameters only valid for IM_ERASEFRAME */
        struct
        {
            WORD Width;
            WORD Height;
        } imp_Dimensions;
    };

The mytextlabelclass example blindly passes this method on to its
superclass.  The superclass treats IM_ERASEFRAME just like IM_ERASE.


IM_HITFRAME

The IM_HITFRAME method is used to determine if a point is within an image
that is contained within (or scaled to) the given rectangle. This method
is intended to test images that were rendered using IM_DRAWFRAME.  This
method receives the following parameters:

    struct impHitTest
    {
        ULONG MethodID;
        struct
        {
            WORD X;
            WORD Y;
        } imp_Point;

        struct
        {
            WORD Width;
            WORD Height;
        } imp_Dimensions;
    };

The mytextlabelclass example blindly passes this method on to its
superclass.  The superclass treat this meothd just like the IM_HITTEST
method.


IM_MOVE

The IM_MOVE method erases and redraws an image.  It is intended for use in
some subclass of imageclass that performs animation or smooth dragging.
Currently, no public boopsi classes implement this method.


IM_FRAMEBOX

The IM_FRAMEBOX method returns size information for an image (usually some
sort of frame image).  The following parameters are associated with the
IM_FRAMEBOX method.

    struct impFrameBox
    {
        ULONG MethodID;
        struct IBox *imp_ContentsBox;  /* Application supplied IBox for the result */
        struct IBox *imp_FrameBox;     /* Rectangle to frame */
        struct DrawInfo *imp_DrInfo;
        ULONG imp_FrameFlags;
    };

This method is used to ask the image what size it would like to be, if it
had to frame the rectangle in the imp_FrameBox field.  This method
normally applies only to image classes that put a frame around some object
(like frameiclass).  By passing the dimensions and position of a
rectangle, the framing image determines the position and size it should be
to properly "frame" the object bounded by the imp_FrameBox rectangle.
IM_FRAMEBOX stores the result in the IBox structure pointed to by
imp_ContentsBox.  This method allows an application to use a framing image
without having to worry about image specific details such as accounting
for the thickness of the frame or centering the frame around the object.

The imp_FrameFlags field is a bit field used to specify certain options
for the IM_FRAMEBOX method.  Currently, there is only one defined for it,
FRAMEF_SPECIFY.  If this bit is set, IM_FRAMEBOX has to use the width and
height supplied to it in the imp_FrameBox field (even if these are too
small!) as the frame dimensions.  It can only adjust its position,
typically to center the object as best as possible.

This method is not supported by the mytextlabelclass example.  It passes
this message to its superclass which does not support this method either.
When the message returns from the superclass, the return value will be
zero, indicating to the application that this method is not supported.


Image Class Example

The image class example code, mytextlabelclass.c, illustrates a complete
custom image class.  This image class provides an application with textual
labels that have a particular character underlined.  This is useful for
indicating which key controls a gadget (although the example provided only
utilizes imageclass objects; there are no gadgets involved).

A custom image can be used in the place of any standard Intuition Image
structure.  For example, an application can attach an imageclass object
to: the GadgetRender and SelectRender fields of a Gadget structure
(defined in <intuition/intuition.h>), the ReqImage field of a Requester
structure, or even the ItemFill field of the MenuItem structure.

Under Intuition V36, the DrawImage() function passed an invalid DrawInfo
structure, therefore it wasn't possible to use a custom imageclass object
and the DrawImage() together.  With V37, a NULL DrawInfo is passed when no
valid DrawInfo is available.

The example code (usemyIC.c) initializes and uses a custom imageclass
object.  Notice that usemyIC.c directly manipulates fields within the
Image structure embedded within the boopsi imageclass object.  This is
legal for image classes whose immediate superclass is imageclass (for the
LeftEdge, TopEdge, Width, Height, ImageData, PlanePick, and PlaneOnOff
Image structure fields only; the other Image structure fields are off
limits).  Indirect subclasses of imageclass may not alter the values in
the embedded Image structure as future direct subclasses of imageclass may
need to know about changes to values in the Image structure.


IV-57: Boopsi's Transparent Base Classes

by Peter Cherna

[Editor's note: This article assumes the reader is already familar with
several boopsi concepts.  For more information on boopsi, see the article
"Introduction to Boopsi" from the March/April 1991 issue of Amiga Mail.]

Although it is normally considered a "programming sin", in some cases it
is legal to directly manipulate some internal fields of certain boopsi
objects.  For compatibility reasons, a boopsi Image or Gadget object
contains an actual Image or Gadget structure.  To a large degree, a boopsi
Image or Gadget looks like a regular Image or Gadget.  Most fields in
these embedded Image and Gadget structures generally contain information
equivalent to the information in a conventional Image or Gadget (although
not always).  This means that many programs and routines that don't know
about boopsi can still make some use of boopsi Images and Gadgets.  These
objects are instances of the Transparent Base Classes, imageclass and
gadgetclass.

To change an attribute of a boopsi object, you normally invoke a set
method (OM_SET).  The Intuition functions SetAttrs() and SetGadgetAttrs()
invoke this method.  A boopsi class is informed of any attribute change at
that time, allowing it to react to this change.  The reaction can include
validation of the changed attribute, changing other attributes to match,
or informing other objects of the change.  That is the inherent advantage
of a function-access approach to changing attributes.

When using conventional Images and Gadgets, you generally modify the
structure's fields directly.  This operation is very fast.  For such
Images and Gadgets, there is no class that needs to know about the
changes, so there is no problem.  However, this is untrue of boopsi Images
and Gadgets.  Although directly modifying the boopsi object's internal
structure would provide a performance increase over using the boopsi
OM_SET mechanism, altering a boopsi object's internal structure directly
will not give the class the opportunity to react to any structure changes.
This violates the boopsi concept, and therefore cannot be done in general.
In order to provide a balance between the flexibility of function access
and the performance of direct access, the transparent base classes
imageclass and gadgetclass will not depend on being informed of changes to
certain fields in the internal Image and Gadget structures.  This means
that direct subclasses of imageclass or gadgetclass (for example,
frameiclass, sysiclass, propgclass, buttongclass, or any direct subclass
you create) are allowed to poke specific fields.  Indirect subclasses of
imageclass or gadgetclass (for example, subclasses of propgclass,
frameiclass, or other indirect subclasses you create) may not poke those
fields, since their parent classes may depend on hearing about changes to
these fields, which the SetAttrs() call (or similar function) provides.

For images, the following Image structure fields are the only fields that
may be poked by image classes whose immediate superclass is imageclass:

        LeftEdge
        TopEdge
        Width
        Height
        ImageData
        PlanePick
        PlaneOnOff

For gadgets, the following Gadget structure fields are the only fields
that may be poked by gadget classes whose immediate superclass is
gadgetclass:

        LeftEdge
        TopEdge
        Width
        Height
        Flags
        Activation
        GadgetType
        GadgetRender
        SelectRender
        GadgetText
        SpecialInfo

In all cases, the direct subclass must take care to maintain sensible
values for these fields.

Under no circumstances may an indirect subclass poke one of these fields,
even if the subclass knows the superclasses do not depend on notification
for this field.  This is the only way to preserve  the possibility for
future enhancements to that superclass.


IV-59: AppWindows, AppIcons, and AppMenuItems

By Fred Mitchell and John Orr

Since its inception, the Workbenchä has had a limitation.  Although it is
a fairly powerful user interface, that power is not accessible to
application programs.   The power is limited to an interface that only
launches other programs.  After Workbench launches a program, the program
no longer has any ties to the Workbench GUI.  If an application needs an
iconic interface, it has to create its own, independent of Workbench.

Workbench 2.0 is different.  Through the workbench.library, applications
can utilize the iconic interface of Workbench 2.0.  There are three
elements to this interface: AppWindows, AppIcons, and AppMenuItems.  In
this article, they are referred to as AppObjects.

When the user drops a Workbench icon onto a special kind of application
window called an AppWindow, Workbench sends a message to the application
that created the AppWindow.  This message contains a complete list of the
icons that the user dropped on the window.  This is useful for an
application like an editor.  The editor can open an Intuition window on
the Workbench screen and make it into an AppWindow so that when the user
drops an icon on the AppWindow, the editor will load the icon's
corresponding file.  The IconEdit utility that comes on the 2.0 release
disks does this.

An application can also create its own icons for the Workbench window.
These icons are called AppIcons.  They are similar to AppWindows in that
Workbench will tell an application what icons the user dropped on its
AppIcon.  In addition, Workbench will notify the application if the user
double-clicks the AppIcon.  This makes AppIcons useful not only as a
"drop box" (like an AppWindow), but they can also be used as some sort
of activator for an application.  For example, a word processor that opens
a window on the Workbench can use an AppIcon to "iconify" its window.
When the user wants to get rid of a cumbersome window, he iconifies it,
which gets rid of the window and leaves an AppIcon on the Workbench window
in its place.  When the user wants the window back, he double-clicks the
AppIcon and the window reappears.

The release 2.0 Workbench has a special menu called "Tools".  It is
special because unlike the other Workbench menus, any application can add
its own menu items to this menu.  These menu items are called
AppMenuItems.  Like the AppIcon, the AppMenu can be used both as an
activator and as a "drop box". When the user selects one of these menu
items, Workbench sends a message to the application that created the
AppMenuItem.  If there were any icons selected when the user selected the
AppMenuItem, the application will also get a list of those icons.

 The AppMessage Structure      AppWindows      AppMenuItems
 Adding AppObjects             AppIcons        adc.c


The AppMessage Structure

When Workbench notifies an application of AppWindow, AppIcon, or
AppMenuItem activity, it sends an AppMessage to the application's message
port (from <workbench/workbench.h>):

    #define      AM_VERSION     1

    struct AppMessage {
        struct Message am_Message;    /* standard message structure */
        UWORD am_Type;                /* message type */
        ULONG am_UserData;            /* application specific */
        ULONG am_ID;                  /* application definable ID */
        LONG am_NumArgs;              /* # of elements in arglist */
        struct WBArg *am_ArgList;     /* the arguments themselves */
        UWORD am_Version;             /* will be AM_VERSION */
        UWORD am_Class;               /* message class */
        WORD am_MouseX;               /* mouse x position of event */
        WORD am_MouseY;               /* mouse y position of event */
        ULONG am_Seconds;             /* current system clock time */
        ULONG am_Micros;              /* current system clock time */
        ULONG am_Reserved[8];
    };

The AppMessage's am_Type field tells the application which type of
AppObject the message is about.  The field will be:

        MTYPE_APPWINDOW if the message is about an AppWindow,
        MTYPE_APPICON if the message is about an AppIcon, or
        MTYPE_APPMENUITEM if the message is about an AppMenuItem.

When an application creates an AppObject, it can assign the AppObject
application specific data (most likely a pointer) and an ID.  Workbench
will pass an AppObject's data and ID back to the application when it sends
an AppMessage about the AppObject.  The AppMessage's am_UserData and am_ID
fields hold the user data and the ID.

The am_NumArgs field tells how many icons were involved in the user's
AppObject action.  For an AppWindow or AppIcon, am_NumArgs is the number
of icons the user dropped on the AppWindow or AppIcon.  For an
AppMenuItem, am_NumArgs represents the number of icons that were selected
when the user selected this AppMenuItem.  If no icons were selected during
an AppMenuItem event or the user double-clicked on an AppIcon, am_NumArgs
will be zero. Workbench does not send AppMessages if the user
double-clicks an AppWindow.

The am_ArgList field is a pointer to a list of WBArgs (from
<workbench/startup.h>) corresponding to each icon dropped (or selected).
If there were no icons dropped or selected, this field will be NULL.

For future expansion possibilities, the AppMessage structure has a version
number.  The version number is #defined as AM_VERSION in
<workbench/workbench.h>.

The am_MouseX and am_MouseY fields apply only to AppWindows and contain
the coordinates of the mouse pointer when the user dropped the icon(s).
These coordinates are relative to the AppWindow's upper left corner.

The am_Seconds and am_Micros fields represent the time that the event took
place.

Any remaining fields are undefined at present and should be set to NULL.


Adding AppObjects

The V37 workbench.library is made up of functions to add and remove
AppObjects, two for each type of AppObject:

    struct AppWindow *AddAppWindow( unsigned long myID,
        unsigned long userdata, struct Window *mywindow,
        struct MsgPort *mymsgport, Tag tag1, ...);

    struct AppIcon *AddAppIcon( unsigned long myID,
        unsigned long userdata, UBYTE *mytext,
        struct MsgPort *mymsgport, struct FileLock *mylock,
        struct DiskObject *diskobj, Tag tag1, ... );

    struct AppMenuItem *AddAppMenuItem( unsigned long myid,
         unsigned long userdata, UBYTE *menutext,
         struct MsgPort *mymsgport, Tag tag1, ... );

    BOOL RemoveAppWindow( struct AppWindow *appWindow );

    BOOL RemoveAppIcon( struct AppIcon *appIcon );

    BOOL RemoveAppMenuItem( struct AppMenuItem *appMenuItem );

The "AddApp" functions have several parameters in common.  The myID and
userdata parameters are values the application assigns to the AppObject.
Workbench puts these values in the AppMessage's am_ID and am_UserData
fields when it sends an AppMessage about an AppObject.  If an application
receives AppMessages about several AppObjects at the same message port,
the application can use the am_ID field to tell which AppObject Workbench
is talking about.

The mymsgport field tells Workbench where to send this AppObject's
AppMessages.  To make it easy to distinguish AppMessages from other types
of messages, an application should devote a message port exclusively to
AppMessages.

In the future, these AddApp functions will be able to process tag pairs in
the parameter list.  Currently, there are no tags defined for any of the
AppObject functions.

All of the AddApp functions return a NULL if the function failed otherwise
they return a pointer to a private structure.  The pointer serves only as
a handle for the application to pass to the "RemoveApp" functions.  Do not
use it for anything else!

Each of the RemoveApp functions removes one type of AppObject using the
handle returned by the corresponding AddApp function.  At present, these
functions all return TRUE, but this behavior is not guaranteed to continue
in the future.


AppWindows

The workbench.library's AddAppWindow() call makes an application's
Intuition window into an AppWindow.  It has one parameter that is
different from the other AddApp calls, a window pointer.  The mywindow
field (from the prototype above) must point to an open Intuition window
that is on the Workbench screen.

The C source code example AppWindow.c at the end of this article is a
simple example of how to create an AppWindow.

There are two interesting things to note about the AppWindow.  First,
because an AppWindow is still an Intuition window, an application can use
a Workbench AppWindow for any purpose it would need a normal Workbench
based window for. An application can render graphics and text in it,
process its IntuiMessages, or create menus for it.  Also, because
Workbench tells where on an AppWindow icons were dropped, an application
can use a small region of a window as a drop box rather than the entire
AppWindow.  A program can even have several drop boxes on the same window.
Using simple rendering routines, an application can draw the boxes so the
user can see where to drop icons.


AppIcons

The workbench.library function AddAppIcon() adds an AppIcon to the
Workbench window.  There are three parameters unique to this AddApp
function.  The mytext parameter (from the prototype above) is the string
that will appear beneath the AppIcon on the Workbench window.  The diskobj
parameter points to a DiskObject structure that Workbench will use for the
AppIcon's imagery.  It should be filled in as follows (from the wb.doc
Autodoc):

   diskobj - pointer to a DiskObject structure filled in as follows:
       do_Magic - NULL
       do_Version - NULL
       do_Gadget - a gadget structure filled in as follows:
           NextGadget - NULL
           LeftEdge - NULL
           TopEdge - NULL
           Width - width of icon hit-box
           Height - height of icon hit-box
           Flags - NULL or GADGHIMAGE
           Activation - NULL
           GadgetType - NULL
           GadgetRender - pointer to Image structure filled in as follows:
               LeftEdge - NULL
               TopEdge - NULL
               Width - width of image (must be <= Width of hit box)
               Height - height of image (must be <= Height of hit box)
               Depth - # of bit-planes in image
               ImageData - pointer to actual word aligned bits (CHIP MEM)
               PlanePick - Plane mask ((1 << depth) - 1)
               PlaneOnOff - 0
               NextImage - NULL
           SelectRender - pointer to alternate Image struct or NULL
           GadgetText - NULL
           MutualExclude - NULL
           SpecialInfo - NULL
           GadgetID - NULL
           UserData - NULL
       do_Type - NULL
       do_DefaultTool - NULL
       do_ToolTypes - NULL
       do_CurrentX - NO_ICON_POSITION (recommended)
       do_CurrentY - NO_ICON_POSITION (recommended)
       do_DrawerData - NULL
       do_ToolWindow - NULL
       do_StackSize - NULL

An easy way to create a DiskObject is to make an icon with the V2.0 icon
editor, IconEdit.  An application can call GetDiskObject() on the icon and
pass that to AddAppIcon().

AddAppIcon()'s mylock parameter is for future enhancements and should be
set to NULL.

Because AppIcons are Workbench icons, the user can drop them on an
AppWindow or another AppIcon (or select them with an AppMenuItem).  As
there is no file, directory, or disk associated with an AppIcon (at least
for the moment), the lock passed for the icon in NULL.  Do not try to
process icons with a NULL lock.

The C source code example AppIcon.c at the end of this article is a simple
example of how to create an AppIcon.

   AppIcon.h


AppMenuItems

Using the workbench.library's AddAppMenuItem() call, an application can
add an AppMenuItem to the Workbench's "Tools" menu.  This AppAdd function
has one parameter unique to it, menutext (from the prototype above).  It
points to the string that appears in the "Tools" menu.

An AppMenuItem performs the same functions as an AppIcon or AppWindow, but
it does not require the overhead of a DiskObject or a window.  It also
does not require the user to drop icons on an object.  In some cases, the
user might prefer to use an AppMenuItem over an AppIcon or AppWindow
because the user doesn't have to shuffle around the Workbench windows to
get to the "Tools" menu.  Note that in older versions of release 2.0,
Workbench did not supply a list of WBArgs when the user selected an
AppMenuItem.

The C source code example AppMenu.c at the end of this article is a simple
example of how to create an AppMenuItem.


IV-69: Making Your Windows More Shiny and Manageable

By Ewout Walraven

The Intuition window paradigm has features that make it easy for the user
to manage windows.  The user can select, move, resize, close, or depth
arrange their windows on any screen so they can quickly get to the window
they need. With 2.0 and a little work, the tools are there to give the
user even greater powers to manage and organize their working environment.

This article addresses some release 2.0 system features which can further
integrate your application's window into the 2.0 environment.  These
features include public screens, the zoom gadget, AppIcons, and
AppMenuItems, which are not discussed in detail here.  For more
information on public screens and the zoom gadget, see the
intuition.library Autodocs and the article
"An Introduction to V36 Screens and Windows" from the September/October
issue of Amiga Mail.  For more information on AppIcons and AppMenuItems,
see the workbench.library Autodocs and the article
"AppWindows, AppIcons, and AppMenuItems", which is in this issue of
Amiga Mail.

 Public Screens      Zooming      Iconifying


Public Screens

The public screens introduced in 2.0 make it possible for the user to open
several screens where different applications can open windows.  If an
application allows the user to choose the public screen on which it opens
its window, the user can more easily organize their working environment.
They can spread their work across several public screens allowing them to
use the screen that has the palette or resolution best suited to their
purposes. This also buys the user more room for windows.  In case one
screen gets too cluttered with windows, the user can open an application's
window on a different public screen.

There are number of ways you can support public screens.  If your
application uses command line options or reads tooltypes, it can support
the PUBSCREEN keyword as a command line argument or tooltype.  This lets
the user indicate the name of the public screen on which your windows
should open.  For example, if some developer wrote a new shell that
supported public screens, the shell's icon could have the following
tooltype in its icon:

    PUBSCREEN=<pubscreenname>

which tells the shell to open its window on the public screen named
pubscreenname.

If an application supports ARexx, it can support a JUMPTOSCREEN command
that tells it to move, or jump, its window to a specific public screen.
The application would open a new window on the public screen named in the
JUMPTOSCREEN command and closes its old window.  Your application can even
provide a jump-to-next-screen gadget, that makes the window jump to the
next public screen.  By using the intuition.library NextPubScreen(), your
application can get the name of the next screen in the public screen list,
close its window on the current screen and re-open it on the next.

The example program jumpy.c opens a window which jumps from one screen to
another when the user clicks the jump gadget.


Zooming

A very simple, but convenient feature you can ask the system to add to
your window is a zoom gadget.  A zoom gadget allows the user to toggle
between two window sizes simply by clicking on a gadget.  In 2.0, a window
gets a zoom gadget automatically when it has both a sizing and depth
gadget, although you don't need a sizing gadget to get a zoom gadget.  You
can ask for a zoom gadget by specifying the WA_Zoom tag when opening the
window.  The WA_Zoom tag takes an array of four WORDs, describing the
initial LeftEdge, TopEdge, Width, and Height values of the window's
alternate dimensions and position. Because such a window has no sizing
gadget, the user can only toggle between two window sizes, the original
size and the alternate size specified with the WA_Zoom tag.  The
preference editors use this feature to toggle between a full-sized window
and a window displaying only the title bar.  The example zoom.c shows how
easy it is to implement this feature.


Iconifying

Although the zoom gadget provides a pseudo-iconifying feature, the
Workbench's AppIcon and AppMenuItem features provide true iconification.
To iconify a window, create the AppIcon or AppMenuItem that will replace
the window.  Next, store the state of the window (like its current
position or the state of its gadgets), so the application can restore the
window to its original state when the application reopens it.  Now close
the window. Because it is possible for the AddAppIcon() or
AddAppMenuItem() function to fail, It is important to create the AppIcon
or AppMenuItem before closing the window.  If an application closes the
window first and Workbench can't create the AppIcon or AppMenuItem, there
will be no AppIcon or AppMenuItem for the user to select to uniconify the
window.

An application can set up a gadget or menu item so the user can tell the
application to iconify the window.  If the application uses a gadget to
iconify, it should not put the gadget in the window border because there
is no standard "look" to what an iconify gadget should look like.

The last example, hide.c, shows how to use AppIcons and AppMenuItems to
iconify a window.

   hide.h


IV-77: Optimized Window Refreshing

by Martin Taillefer

Maintaining the graphical contents of an Amiga window can be
difficult.  There are many subtleties associated with the process
known as window refreshing.  At present, many applications refresh
their windows in suboptimal ways, or fail to refresh correctly under
all conditions.  This article attempts to explore and resolve the
window refreshing problems commonly encountered by applications.

 Damaging Information          Using Multiple RastPorts
 When To Refresh               Refreshing a Sizable Window
 Scrolling Your Life Away      BeginRefresh() and EndRefresh()
 Faster Rendering              Backfill Hook

 Optimrefresh.c


Damaging Information

Although many people think of Intuition as the Amiga's windowing
system, the lower-level Layers library actually handles most of the
work involved in maintaining Intuition's windowed environment.  The
Layers library divides a single physical display (a BitMap) into
multiple virtual displays.  Each of these virtual displays is known
as a layer.  Intuition uses the functions in the Layers library to
move, resize, and depth arrange these layers.

Normally, each Intuition window consists of a single layer.
Intuition adds borders and gadgetry to the layer to give it the
familiar Intuition window appearance.  Intuition also takes care of
monitoring user input to let the user move, resize, and depth arrange
windows.  When Intuition wishes to change the size or position of a
window, it calls functions in the Layers library to do most of the
grunt work.

One of the main reasons for a layered rendering system is to provide
multiple independent logical rendering regions to applications.  The
layer is the basis for the Intuition Window.  The functions in the
Layers library allow several applications to render into the same
physical display (an Intuition Screen for example) without worrying
about interfering with each other.  As far as the application is
concerned, it has an entire display all to itself.

There is a limit to the isolation that this layered environment
offers applications.  Because layers can overlap, by moving,
resizing, or deleting a layer, a program can uncover portions of
underlying layers.  These newly exposed portions are called "damage
regions".  A layer can sustain damage when a task performs layers
operations on it or other layers in the same display.  When the
Layers library damages a layer, it sets the layer's LAYERREFRESH bit
in the Flags field of the Layer structure.

When damage occurs to a layer, the damaged region of the layer must
be repaired by redrawing it.  The entity responsible for redrawing
the damaged region depends on the type of layer.  The Layers library
offers three types of layers: simple refresh, smart refresh, and
superbitmap.  Subsequently, Intuition bases its three types of
windows on these three types of layers.  The difference between each
type has to do with the way in which each handles damage repair.

When a layers operation damages a simple refresh layer, the entire
burden of repairing the layer's damage rests on the application that
created the layer (if the application is using Intuition windows,
which are built on top of layers, Intuition shares the burden of
damage repair with the application.  More on this later).  This is
because a simple refresh layer does not preserve its contents.  The
advantage of this type of layer is that it doesn't use much memory.
The disadvantage is that every time a layers operation reveals a
portion of a simple refresh layer, the application must explicitly
rerender the exposed damaged regions.

Smart refresh layers help the application by doing some of the
refreshing automatically.  If a layer operation conceals a portion of
a layer, that portion is automatically copied to an off-screen
buffer.  If a layer operation later reveals that portion of the
layer, the Layers library uses the temporary buffer to update the
revealed region.  The Layers library does not leave the LAYERREFRESH
bit set in this case because the Layers library took care of the
damage.  The application still needs to refresh the smart refresh
layer whenever it is made larger, as the Layers library has no idea
what should be in the newly exposed areas.  In this case, the Layers
library will leave the LAYERREFRESH bit set.

Finally, superbitmap layers totally eliminate the need for an
application to refresh the display.  The Layers library maintains a
complete off-screen buffer representing the layer's contents.  When a
layer operation exposes new portions of a layer, the Layers library
automatically updates these regions by copying from the off-screen
buffer.  The Layers library will never leave the LAYERREFRESH bit set
for a superbitmap layer.

For the application programmer, a superbitmap layer offers the
simplest approach to refreshing the layer as the entire burden of
repairing damaged regions falls on the Layers library.  This added
convenience does have a cost--because of its off-screen buffer, the
superbitmap layer requires a significantly larger amount of memory
compared to the simple and smart refresh layers.  The Layers library
allocates this memory even if the layer never sustains damage.


When To Refresh

The way in which an application determines that it needs to refresh a
layer depends on whether an application deals with layers directly
via the Layers library, or indirectly via Intuition.  It is important
to keep in mind that each Intuition window has a Layer at its core.
If an application uses Intuition windows it may not use the Layers
library to create, delete, move, resize, or update the window layers.
The application must use the corresponding Intuition functions
instead.

If an application uses layers directly, it must look at a layer's
LAYERREFRESH bit to tell if the layer sustained damage and needs
repair.  Since the application created and maintains its layers, it
knows when damage can occur, so it checks for damage at those times.

Intuition manages an arbitrary number of layers on behalf of any
number of client applications.  All windowing operations happen on
Intuition's time frame.  Since other applications and the user can
ask Intuition to manipulate window layers around at any time, it is
not possible for a window-based application to know by itself when to
refresh its window.  That would involve polling the window layer's
LAYERREFRESH bit, which is a big no-no in a multitasking system.
Instead, Intuition provides a refresh notification mechanism through
the IDCMP system.

Whenever Intuition performs a layer operation that can damage a
window layer, it checks the damage state of each layer in the current
screen by inspecting each layer's LAYERREFRESH bit.  If Intuition
finds that a layer's LAYERREFRESH bit is set, Intuition takes care of
refreshing the damaged areas of the window that are Intuition's
responsibility (for example, the window borders and gadgets).
Following that, Intuition looks at the WFLG_NOCAREREFRESH bit in the
Window structure.  If this bit is set, Intuition's refresh processing
for the window is complete, and all damage region information is
discarded.  However, If the bit is clear, Intuition sends an
IDCMP_REFRESHWINDOW message to the window's IDCMP port, essentially
asking the window to refresh itself.

So, instead of having to poll the LAYERREFRESH bit, an application
can just wait for Intuition to tell it to refresh its window.  This
is convenient and fits in well with the IDCMP mechanism.


Scrolling Your Life Away

A scrolling display is a part of many user interfaces.  An easy way
to make people think an application is slow is to give it a sluggish
user interface.  Regardless of the actual speed at which an
application performs its job, if its user interface management is
slow, the user will get the impression the whole application is slow.

The ScrollRaster() and ClipBlit() routines are the two principal ways
of scrolling data within a layer.  ScrollRaster() moves the data
within a RastPort.  ClipBlit() moves data from one RastPort to the
next, but works equally well if the source and destination RastPorts
are the same.

Smart refresh layers are relatively easy to scroll with either
ScrollRaster() or ClipBlit().  Although ClipBlit() has a theoretical
advantage over ScrollRaster(), the performance of these functions is
generally equivalent.  ScrollRaster() does a minimum of two Blitter
operations: one to scroll the data, and a generally smaller one to
erase the area that was scrolled away.  ClipBlit() can do a single
blit to move the data in the layer, and leaves the rest of the
display alone.  Thus, while scrolling large amounts of data, an
application can get better CPU/Blitter processing overlap by using
ClipBlit().  Consider the following pseudo-code of what happens in
ScrollRaster() versus ClipBlit():

Within the ScrollRaster() function:
  Wait for any outstanding Blitter operation to complete
  Initiate a Blitter operation to move the data in the window
  Wait for the Blitter operation to complete
  Initiate a second small Blitter operation to clear the scrolled region
  Return to the caller while the small blit is still in progress

Within the ClipBlit() function:
  Wait for any outstanding Blitter operation to complete
  Initiate a Blitter operation to move the data in the window
  Return to the caller while the blit is still in progress

Since the Blitter and the CPU can run concurrently, the second
approach provides the most throughput, as the Blitter performs most
of the scrolling work at the same time the application code runs
after ClipBlit().  In practice though, ScrollRaster() and ClipBlit()
run at about the same speed.

For a smart refresh window, ScrollRaster() and ClipBlit() do not
present a problem.  As long as the application only scrolls the
contents of the window and not the window borders, the Layers library
will take care of fixing any damage.  Intuition will never know what
happened.  For a simple refresh window however, there is a problem.
The reason has to do with the following:

       +--------------+           +--------------+
       |aaaaaaaaaaaaaa|           |bbbbaaaaaabbbb|
       |bbbb+----+bbbb|           |cccc+----+cccc|
       |cccc|    |cccc|           |dddd|    |dddd|
       |dddd+----+dddd|           |eeee+----+eeee|
       |eeeeeeeeeeeeee|           |              |
       +--------------+           +--------------+

          Figure  1a                 Figure  1b

Figure 1a represents a small window that the user placed on top of a
larger simple refresh window.  When an application scrolls the larger
window's contents upwards with ScrollRaster(), the result looks like
Figure 1b.  This operation exposes two portions of the larger window,
the section at the bottom of the large window (the part
ScrollRaster() clears) and also the area above the smaller window
(which ScrollRaster() leaves intact).

The application that owns the larger window has to refresh the two
portions exposed by ScrollRaster().  The application knows to refresh
the bottom section of the window because the damage is a direct
result of the application calling ScrollRaster().  The problem is the
area above the smaller window.  The application does not know that
there is a window overlapping its larger window, so it does not
directly know about any damage resulting from other overlapping
layers.  Because the application used a graphics.library function to
manipulate the window, Intuition does not know about the damage
either.  The result is that the larger window is damaged and no one
knows it.

If the larger window had been a smart refresh window, the Layers
library would have cached this portion of the larger window and
ScrollRaster() would have taken action to make sure the cached region
got restored.  For a simple refresh window, this portion only gets
added to the window layer's damage list and no rendering actually
occurs.

The solution to this problem is for the application to act as
Intuition would if it were scrolling.  When Intuition manipulates a
layer, it checks the LAYERREFRESH bit of each of its layers to see if
any of them was damaged.  After the application calls ScrollRaster()
on its window, the application has to look at the LAYERREFRESH bit of
the window's layer.  If the bit is set, damage exists and the
application needs to repair the window.  As this window is the only
window that can sustain layer damage as a result of the call to
ScrollRaster(), the application needs to check only its own window's
layer for damage.

Note that to scroll the contents of a simple refresh window, an
application has to use ScrollRaster() rather than ClipBlit().  The
reason is ClipBlit() does not add anything to the window layer's
damage region, so an application will never know about the damage.
Also, unlike ScrollRaster(), ClipBlit() does not scroll the window
layer's damage region.  If the layer already has damage when an
application calls ScrollRaster(), the position of the damage region
will move along with the data in the layer.  Note that prior to
Release 2, ScrollRaster() did not scroll the layer's damage list.


Faster Rendering

When rendering to a RastPort, an application can improve its
rendering performance if it renders using a limited number of colors.
Each RastPort contains a mask field which specifies the writeable
bitplanes of the RastPort's BitMap.  If a RastPort's bitplane is
write-protected, the system ignores that bitplane when rendering to
the RastPort.

An application can control the BitMap mask by using the SetWrMsk()
macro (defined in <graphics/gfxmacros.h>).  This macro accepts a
pointer to a RastPort, and a new mask.  The mask is an 8 bit value.
Each bit of the value represents a BitMap bitplane.  For example, a
mask of value 5, which is 00000101 in binary, restricts rendering in
that BitMap to planes 0 and 2 which are the only two bits set in the
binary value.

One type of application that can improve its performance by using the
RastPort Mask is the text editor.  Typically, a text editor needs to
render its text in a single color, generally color 1.  This means the
editor only needs to render to bitplane 0.  All other planes will
always remain blank.  If these planes are going to remain blank, why
should the editor bother to render to them or scroll them?

When scrolling large sections of the display, ScrollRaster() can make
the display look unstable because it continuously clears portions of
the display.  ClipBlit() eliminates this visual nuisance as it does
not clear the display.  Unfortunately, ClipBlit() by itself is
useless for scrolling a simple refresh window because it does not
deal with damage regions.  The solution is sneaky but quite
effective.  An application can do the following each time it scrolls
a simple refresh layer:

  Set the RastPort Mask to limit the number of writeable bitplanes.
  Use ClipBlit() to scroll the data.
  Set the RastPort Mask to 0.
  Use ScrollRaster() to scroll the same data.

In the procedure above, ClipBlit() scrolls the window contents but
not the damage regions.  ScrollRaster() scrolls the damage region,
but because the RastPort mask is 0, ScrollRaster() does not affect
the window contents.  Setting the RastPort mask to 0 prevents the
system from disturbing the data in any of the planes of the BitMap.

The above trick can come in quite handy.  It is fairly fast as well,
although it can involve some hidden overhead.  Even though
ScrollRaster() doesn't move data on the display, it still needs to go
through all the layer's clipping regions, which can be time consuming.


Using Multiple RastPorts

A RastPort specifies attributes needed to perform many rendering
operations.  These include the RastPort's foreground, background, and
drawing mode.  The Graphics library functions SetAPen(), SetBPen(),
and SetDrMd() set each of these attributes, respectively.

Although these functions appear to have fairly simple purposes in
life, the SetAPen(), SetBPen(), and SetDrMd() are quite CPU intensive
routines.  These functions require recalculating values that the OS
caches in private parts of the RastPort.  If an application only
requires a few different combinations of foreground/background/draw
mode, it can improve its performance by using a different RastPort
structure for each combination.  An application sets the attributes
of several RastPorts only once which is generally more efficient that
setting the attributes of one RastPort every time the rendering
attributes change.

Assume an application has a window in which it renders all of its
data in pen 1, and clears any part of its display using color 0.
Such an application can improve its rendering performance by doing
the following:

    struct RastPort dataRP;
    struct RastPort clrRP;

    dataRP = *window->RPort;
    SetAPen(&dataRP,1);
    SetBPen(&dataRP,0);

    clrRP = *window->RPort;
    SetAPen(&clrRP,0);

    /* renders to the window's RastPort in color 1 */
    Text(&dataRP,"hello",5);

    /* clears a section of the window's RastPort in color 0 */
    RectFill(&clrRPort,0,0,10,10);


Refreshing a Sizable Window

A sizable window is by far the trickiest to refresh correctly.  The
most important and often overlooked point is that an application
needs to ensure the size of its window does not change while it is
refreshing the window.  If the application doesn't and the user
changes the window size, the application will refresh the window at
the window's old size rather than its new size.  This can severely
corrupt the appearance of the window.

There are two main ways an application can keep the size of its
window stable while refreshing  the window.  The first method is to
keep the size of the window locked most of the time, unlocking the
window only when the user tries to size the window.  The other
approach is to lock the window size only while rendering to the
window.

The first method is part of Intuition's IDCMP mechanism.  To lock a
window's size, an application sets the window's IDCMP_SIZEVERIFY
IDCMP flag.  When the user attempts to size the window by clicking on
the window's sizing gadget, Intuition notifies the application by
sending an IDCMP_SIZEVERIFY message to the window's IDCMP port.
Intuition will keep the window's size locked until the application
returns the IDCMP_SIZEVERIFY message.

In general this scheme works well, but it does have two problems.
First, if the application is busy doing some processing, such as
recalculating a spreadsheet, it may not notice that the message
arrived until it is done with its current processing.  The result is
the user will not be able to size the window until the application is
finished processing, which might more time than the user wants.

The second problem occurs when the application is waiting for input
from Intuition, such as in the middle of an EasyRequest() call.  If
the user clicks on the sizing gadget of the application's window
while the requester is up, Intuition will wait for the system will
enter a deadlock.  Intuition will wait for the application to send
back will not see the IDCMP_SIZEVERIFY event until the user satisfies
the EasyRequest().  The result will be a system deadlock.  Many
applications suffer from this problem.

The second problem occurs when the application is waiting for input
from Intuition, such as in the middle of an EasyRequest() call.  If
the user clicks on the sizing gadget of the application's window
while the requester is up, the system will enter a deadlock.  When
the user clicks the sizing gadget, Intuition sends the
IDCMP_SIZEVERIFY message and waits for a reply.  Because the
application is already waiting for the EasyRequest() to return, the
application cannot send back the reply.  Many applications suffer
from this problem.

As of Release 2, Intuition has adapted and avoids these deadlocks.
Intuition will time out the sizing operation if the application does
not process the IDCMP_SIZEVERIFY message within a given time period.
Although the user can no longer deadlock the system, this situation
can still confuse the user because clicking on the window's sizing
gadget no longer sizes the window.  That does not mean an application
should rely upon Intuition to avoid the deadlock.  An application
should always avoid these conditions.

In general, it is simpler and safer for the application to lock a
window only during the rendering process.  The application can do
this by surrounding all rendering operations with calls to the Layers
library functions LockLayer() and UnlockLayer().  LockLayer() locks
the size and position of a layer.  While a window's layer is locked,
an application can safely look at the window's current size and
render to it without any danger of the size changing.  Once the
application finishes rendering, it unlocks the window's layer by
calling UnlockLayer().  When using this method, an application must
not set the window's IDCMP_SIZEVERIFY bit.  Be careful which system
functions an application calls while it has a layer locked.  Only use
the Graphics library rendering functions and the simple Intuition
rendering functions (i.e., PrintIText(), DrawImage(), etc.).  In
particular, avoid calls that deal with gadgets (including
RefreshGList()) and other locks (i.e., LockIBase() and
LockLayerInfo()).


BeginRefresh() and EndRefresh()

To improve the performance of repairing damage to simple and smart
refresh windows, Intuition can put a window into a special refresh
state using Intuition's BeginRefresh() function:

    VOID BeginRefresh(struct Window *window)

While a window is in this state, the system restricts attempts to
render into the window to the window's damaged regions.  Because the
system ignores rendering operations outside the window's damage
regions, an application only refreshes the parts of a window that
need refreshing.  This can significant decrease the amount of time
necessary to refresh the window.  This also reduces the possibility
of visual flicker that can happen if an application has to redraw the
entire contents of a window.

To end a window's special refresh state, use EndRefresh():

    VOID EndRefresh(struct Window *window, BOOL Complete)

Compared to BeginRefresh(), EndRefresh() has an extra parameter, a
boolean value.  If this value is TRUE, Intuition assumes that all of
the refreshing for this window is finished and removes all of the
window layer's damaged regions.  In most cases, this value should be
TRUE.  See the Autodoc for BeginRefresh() and EndRefresh() for more
information.


Backfill Hook

Whenever a layer sustains damage, the damaged region is cleared to
color 0.  Clearing the region requires an often lengthy Blitter
operation which is unnecessary if the application plans to redraw the
damaged region anyway.  Such an application can improve its
performance by preventing the Layers library from clearing the
damaged regions.  This is what layer backfill hooks are for.

Backfill hooks are a new Layers library feature added in Release 2.
A backfill hook is a custom function that an application attaches to
a specific layer.  Whenever damage occurs to a layer, the Layers
library calls that layer's custom backfill hook.  The Layers library
passes the position and dimensions of the damage area to the backfill
hook.  The backfill hook can render into the damage area, refreshing
it.  Theoretically, the backfill hook can redraw a layer's damaged
regions instead of clearing the damage area to color 0.

Unfortunately, refreshing a layer from a backfill hook can be quite
difficult.  The backfill hook code is usually called from a different
task than the main application.  If the backfill hook and the
application do not properly arbitrate access to the application's
data, dangerous race conditions can occur if the hook and the
application try to access the same data.  Another problem with
rendering through the backfill hook is that no clipping is available.
The backfill hook must do its own clipping to ensure that no
rendering goes outside the dimensions specified when the hook is
called, which in itself can be quite difficult.

For many situations, the best use of a backfill hook is to have it do
nothing.  Whenever the hook is called, it simply returns without
doing any rendering.  This has the effect of eliminating the extra
blit done to clear the damage region to color 0.  This can speed
layer operations quite a bit.

There is one problem with a no-op backfill hook.  If the application
is busy doing some processing and damage occurs to its layer, the
display will remain dirty until the application finishes its
processing and notices that the layer is damaged.  This damage can
include remnants of system imagery, like window borders, which can
confuse the user.

One way to overcome this problem is to use a backfill hook that
changes its behavior depending on the state of the application.  If
the application is not too busy to notice damage to its window's
layer, the backfill hook does not erase the display.  However, if the
application is too busy to refresh its damaged window, the backfill
hook clears the damaged portion of the display.  Using this method,
the backfill hook will not waste time erasing the damage when the
application will update it immediately, but the backfill hook will
erase the damage if the application can't refresh for a while.


IV-91: Color Wheel and Gradient Slider Boopsi Classes

Color Wheel and Gradient Slider Boopsi Classes

by Mark Ricci, Martin Taillefer, and David Miller

The Color Wheel and Gradient Slider classes are V39 additions to
Boopsi.  They are specifically intended for use with the expanded
color capabilities of the Advanced Graphics ArchitectureÔ (AGA).  In
order to understand their use and the reasons they were added, a
brief background on color theory follows.

The color model in Amiga systems from V30 (Release 1.0) through V38
(Release 2.1) has been RGB based, that is, color was specified as
some combination of red, green and blue.  These are known as the
primary additive colors.  If you start at a value of zero for each
primary--the color black--adding varying levels of them enables you
to specify any of the Amiga's colors till you've added them all at
their highest level which is the color white.

The opposite of the primary additive colors are the subtractive
primary colors, cyan, magenta, and yellow, respectively.  These
colors are created by completely subtracting one of the primary
colors from white.  Cyan is green-blue, magenta is red-blue, and
yellow is red-green.  Subtracting all of them brings you back to the
color black.

Another method of specifying colors is in terms of hue, saturation
and brightness, HSB.  Hue is the dominant wavelength in the light we
receive; we associate color names with hue.  Saturation is a measure
of the purity of the dominant wavelength, that is, the more dominant
the wavelength, the more pure or saturated it is.  Brightness is a
measure of the luminance or brilliance of the wavelength.

The RGB method of color specification is used because it corresponds
to the red, green and blue receptor cones in our eyes.  Through the
varying intensities of these wavelengths that the receptors receive,
we are able to see colors.  It's a natural way for us to represent
colors and till now,  was the only OS-supported way on the Amiga.
Some applications did allow users to specify colors in terms of HSV
(V stands for value and corresponds to brightness), but the HSV
calculations had to be done by the application.

Under V39 (Release 3.0), the color model includes both RGB and HSB.
It also expands from a twelve bit color definition--four bits each
for red, green and blue--to a twenty-five bit color definition -
eight bits each for red, green and blue plus one bit for genlocking.
With the expanded color model, programmers and users have finer
control over color selection than ever before.

The new color model is based on a color cylinder where the set of
available hues, saturations and brightnesses is represented as a
cylinder.  The cylinder is divided radially into hues, with the
saturation level of a hue increasing from zero at the center of the
cylinder to its maximum at the outer edge of the cylinder.  The
altitude of the cylinder represents the brightness of the hue.  At
the top of the cylinder, the brightness is maximized; at the bottom,
the brightness is minimized.  We see the minimum brightness as black,
regardless of the hue; the maximum brightness of a hue, however, is
not white.

If you refer to color theory literature, you will notice the V39
color model closely resembles the Munsell color model.  The
similarity is not by design, but makes for interesting reading
nonetheless.

To implement the new color model, V39 adds two new Boopsi classes,
the Color Wheel and Gradient Slider classes.  The classes provide two
gadgets for working with the expanded palettes of AGA machines, the
color wheel and gradient slider gadgets.  The color wheel gadget is a
two dimensional representation of the hue and saturation elements of
the cylinder called a color wheel.  The gradient slider gadget is
based on the brightness element of the color cylinder.

Visually, the color wheel gadget is a display of all of the available
hues and their saturations depicted as a multicolored wheel with a
selector knob that can be moved anywhere on the wheel.  The gradient
slider is typically a vertically oriented slider displaying a smooth
transition of a color from its brightest to its darkest.  The
gradient slider knob selects the intensity of the brightness.

This is a huge change in how a user selects colors.  The old method
was to display a color in an indicator box with three sliders for the
red, green and blue components of the color and each slider's knob
set at the proper level of the components.  The user would then
select the desired color by manipulating the three sliders.

With the color wheel gadget, the user can move the knob to the
approximate color he wishes to use, and then, if sliders are provided
as they are in the V39 Palette Preferences editor, manipulate the
sliders to refine the components of the selected color.

In the same way that the color wheel knob can be moved to the
approximate color, the gradient slider gadget knob can be moved to
the approximate brightness level.  The color wheel and gradient
slider gadgets provide a much more intuitive method for selecting
colors.

For developers, the new gadgets do the heavy lifting like all Boopsi
gadgets.  As the user moves the mouse across the color wheel, the
gadget will return the RGB or HSB value (depending on which you
request) corresponding to the knob location, and the gradient slider
will return the current position of the knob as a value between the
highest brightness value and the lowest brightness value.  In
addition, the color wheel has two functions that convert RGB values
to HSB and vice versa.

The Color Wheel Gadget

The color wheel gadget has two rendering modes of display: monochrome
and color.  The rendering mode is dependent on the number of
bitplanes its screen has, and the number of available pens.  Four or
less bitplane screens generally result in a monochrome wheel, though
if there are enough pens available, you will get a minimal color
wheel with four bitplanes.  Five through eight bitplane screens
result in successively more colors as the bitplanes increase.  The
V39 Palette Preferences editor, for example, uses eight bitplanes.

The monochrome rendering mode exists for instances where the color
wheel is being used on an ECS system and there aren't enough pens
available, or when the color wheel screen cannot get four bitplanes.
If you are using an ECS machine, you can be fairly certain of getting
a minimal color wheel if you limit the gradient slider pen array to
four pens.

A monochrome color wheel is broken into six sectors, one each for the
additive and subtractive primaries, The sectors are denoted by the
first letter of its associated primary as shown below.

You can localize the sector markers by using the WHEEL_Abbrv tag.
The default string is "GCBMRY."  Make sure your localized tag is in
the proper order.

The color wheel gadget can handle both RGB and HSB 32-bit values.
This enables developers  and users to work with it in either mode.
When you create the color wheel, the RGB or HSB values you set
determine the initial position of the knob.  These values default if
you do not supply them.  The RGB defaults are full red, no green, no
blue; the HSB defaults are hue 0, full saturation, full brightness.
The default knob position is, accordingly, the topmost edge of the
red section of the color wheel.

RGB and HSB values can be passed to the gadget either as separate tag
items, or in an RGB or HSB structure.  The tags and the structures
are defined in <gadgets/colorwheel.h>.

        Tag Name                Purpose

        WHEEL_Hue               set the hue component
        WHEEL_Saturation        set the saturation component
        WHEEL_Brightness        set the brightness component
        WHEEL_HSB               set HSB using an HSB structure

        WHEEL_Red               set the red component
        WHEEL_Green             set the green component
        WHEEL_Blue              set the blue component
        WHEEL_RGB               set RGB using an RGB structure

 struct ColorWheelHSB
     {
         ULONG cw_Hue;
         ULONG cw_Saturation;
         ULONG cw_Brightness;
     };

 struct ColorWheelRGB
     {
         ULONG cw_Red;
         ULONG cw_Green;
         ULONG cw_Blue;
     };

Keep in mind that although you can specify brightness, it will not be
displayed because the colorwheel's two dimensions are hue and
saturation.  Instead, the colorwheel gadget can pass this value to
the gradient slider gadget if you set the WHEEL_GradientSlider tag
with the address of the gradient slider.  Then, any time the wheel
brightness is modified, the slider knob position will automatically
display the change.

The color wheel will return either RGB or HSB values depending on how
you query it.  If you wish to continuously receive mouse position
reports as the user moves the knob, set the GA_FollowMouse tag when
you create it.

The Gradient Slider Gadget

The gradient slider gadget is a non-proportional gadget for the
brightness component of a color.  It has a special attribute--it can
render a pen array as a color gradient in its box.  If you properly
specify the pen array, the gradient slider will render it as a smooth
transition, most times from brightest to darkest, although you may
choose to go from darkest to brightest.  The intent of the gradient
is to allow the user to move the knob to the appropriate brightness
level of the selected color.

The position of the gradient slider knob is set by the value of the
GRAD_CurrVal tag.  However, there are two potential pitfalls that you
must take into account when setting this tag.  The first is that the
top of the slider is zero and the bottom of the slider is the largest
value in its range.  This is the opposite of what you would expect.
The other is that the gradient slider works with 16-bit values, not
32-bit like the color wheel.  Make sure you account for these.

If you modify the brightness of the color wheel, the gradient slider
will pick up the change via the link established by the color wheel's
WHEEL_GradientSlider tag.  The gradient slider converts the 32-bit
brightness value to a 16-bit value and sets the knob position to the
proper position.

Creating the Pen Array

The pen array you pass to the gradient slider is a set of pen numbers
you obtain using the V39 ObtainPen() function, or from an existing
set of pens like the screen's pens.  In most cases, you will use the
ObtainPen() function.

Before you create the pen array, you need to decide where you will
begin.  You have two choices, you can use a color from the current
palette or design a color of your own.  In the former case, you
access the color registers of the screen's colormap; in the latter
case, you set the RGB or HSB values yourself.  In this article, color
0 (color registers 0, 1, and 2) of the screen's palette will be used.

To access a colormap's registers, you call the V39 function
GetRGB32(), passing it the colormap, the starting color register, the
number of registers and an array large enough to hold three times the
number of registers you request.  This is because a color register
has a 32-bit value for each of its red, green and blue components.

     ULONG colortable[12];  /* space for the first four colors */
     struct Screen *Colorscreen;

     /* Get the first four colors */
     GetRGB32(Colorscreen->ViewPort.ColorMap,0L,4L,colortable);

Once you decide which color to use, the RGB values must be converted
to HSB values in order to modify the brightness.  You do this with
the color wheel function ConvertRGBToHSB() which converts the RGB
values stored in a ColorWheelRGB structure to HSB values and returns
them in a ColorWheelHSB structure.

     struct ColorWheelRGB rgb;
     struct ColorWheelHSB hsb;

     /* set RGB values for color 0 in ColorWheelRGB structure */
     rgb.cw_Red   = colortable[0];
     rgb.cw_Green = colortable[1];
     rgb.cw_Blue  = colortable[2];

     /* now convert the RGB values to HSB */
     ConvertRGBToHSB(&rgb,&hsb);

Since the topmost color is going to be the brightest, its brightness
must be set to the maximum value, $FFFFFFFF.

     /* max out the brightness component */
     hsb.cw_Brightness = 0xffffffff;

The final decision is the number of pens to use to render the
gradient.  A good rule of thumb is eight pens as a minimum and
sixteen as a maximum.  Eight will give you a nice display and sixteen
will give you a very nice display.  If you're wondering, the Palette
Preferences editor uses thirty-two pens.

With the starting color converted to HSB, its brightness maximized
and the number of pens set, the pen array can be built by converting
each new HSB value back to RGB with the ConvertHSBToRGB() function
and calling ObtainPen().  Remember, member 0 of the array will be the
starting color and each successive member will be proportionately
dimmer.  To facilitate updating the pen array later on, a structure
for use with the V39 LoadRGB32() function is set up for each pen
number.  The code below demonstrates how the array is built.

     #define GRADCOLORS   16       /* Set to 4 for ECS to ensure enough color wheel pens */
     struct load32 color_list[GRADCOLORS + 1];
     WORD penns[GRADCOLORS +1];
     WORD numPens;

     numPens = 0;
     while (numPens < GRADCOLORS)
     {
         hsb.cw_Brightness = 0xffffffff - ((0xffffffff / GRADCOLORS) * numPens);
         ConvertHSBToRGB(&hsb,&rgb);

         penns[numPens] = ObtainPen(Myscreen->ViewPort.ColorMap,-1,
                          rgb.cw_Red,rgb.cw_Green,rgb.cw_Blue,PEN_EXCLUSIVE);
         if (penns[numPens] == -1)
             break;

         /* Set up LoadRGB32() structure for this pen */
         color_list[numPens].l32_len = 1;
         color_list[numPens].l32_pen = penns[numPens];
         numPens++;
     }
     penns[numPens] = ~0;
     color_list[numPens].l32_len = 0;

The pen array is now complete and ready to be passed to the gradient
slider when you create it.

Updating The Pen Array

In our scheme, we said the color gradient is updated every time the
user moves the mouse to a new position on the color wheel.  This is
done by updating the pen array whenever a mousemove message is
received.

The algorithm is to query the color wheel for the current HSB setting
and then loop through all the pens as we did above to gradually
decrease the brightness.  There is one difference, though, instead of
obtaining pens, we will change the colors of the pens using either
SetRGB32() or LoadRGB32(), both of which were added for V39.

If you use SetRGB32(), you must call it for each pen you change; if
you use LoadRGB32(), you can pass it a structure containing a
variable number of pens to change in one call.  As we said, we will
use LoadRGB32().

     case IDCMP_MOUSEMOVE:

        /*
         * Change gradient slider color each time
         * colorwheel knob is moved.  This is one
         * method you can use.
         */

        /* Query the colorwheel */
        GetAttr(WHEEL_HSB,colwheel,(ULONG *)&hsb);

        i = 0;

        while (i < numPens)
        {
            hsb.cw_Brightness = 0xffffffff - ((0xffffffff / numPens) * i);
            ConvertHSBToRGB(&hsb,&rgb);

            color_list[i].l32_red = rgb.cw_Red;
            color_list[i].l32_grn = rgb.cw_Green;
            color_list[i].l32_blu = rgb.cw_Blue;
            i++;
        }
        LoadRGB32(&Myscreen->ViewPort,(ULONG *)color_list);
        break;

Using the Gadgets

The color wheel and gradient slider gadgets are found on the system
in the Classes/Gadgets drawer of Workbench as colorwheel.gadget and
gradientslider.gadget instead of being part of Intuition.  They must
be opened with OpenLibrary() before they can be used.

        struct Library *ColorWheelBase, *GradientSliderBase;

        main()
        {
        ...

        OpenLibrary("Classes/Gadgets/colorwheel.gadget",39L);
        OpenLibrary("Classes/Gadgets/gradientslider.gadget",39L);

Once opened, you use them as you would any Boopsi gadgets, that is,
create them using NewObject() and dispose of them using
DisposeObject().  However, you must use CloseLibrary() because you
used OpenLibrary() earlier.

        CloseLibrary(ColorWheelBase);
        CloseLibrary(GradientSliderBase);

The example program below creates a color wheel and gradient slider
on the deepest screen possible.  As you move the color wheel knob
around the wheel, it will update the gradient of the gradient slider.

 WheelGrad.c


IV-101: Introduction to the Datatypes Library

Introduction to the Datatypes Library

by Dan Baker

The latest version of the Amiga operating system, Release 3.0,
includes the new datatypes library.  The purpose of the datatypes
library is to provide software tools for handling data in an
object-oriented way.  The object-oriented approach means that your
application can work with numerous data file standards without having
to worry about the complex details of each one.  Instead you need
only understand the simple conventions of the datatypes library.

The datatypes library is built on Intuition's boopsi facility (boopsi
is an acronym for Basic Object-Oriented Programming System for
Intuition).  Although not required, it is very helpful to know a
little about how boopsi works before trying to use the datatypes
library.  For information on boopsi, refer to chapter 12 and appendix
B of the Amiga ROM Kernel Reference Manual: Libraries (ISBN
0-201-56774-1).  Some familiarity with object-oriented theory and
practice is also helpful, though not required.

Since the datatypes library uses the TagItem structure for passing
parameters to functions, you will have to understand how TagItems
work before you can call the functions in the datatypes library.  For
more information on TagItems refer to chapter 37 of the Libraries
manual.

Why Use the Datatypes Library?

One practical benefit of the datatypes library is that it allows you
to quickly add support for IFF data files (this article will show you
how).  However, the goals of the datatypes library are much more
ambitious than that.  Here's a summary:

    Consistent, simple handling of multiple data standards -
    Most of the details of dealing with the various data
    standards are hidden. Once you have learned how to handle
    one type of data with the datatypes library, you will find
    that the other types are handled in much the same way.

    Extensible - You can add your own types of data objects to
    those already supported by the datatypes library.
    Datatypes has functions that allow other applications to
    find out about and work with your data object, without
    having to understand the internal details of the data.

    Automatic support of IFF and clipboard - The initial
    version of the datatypes library (V39) provides support for
    8SVX sound data and ILBM graphic data.  These are the two
    most widely used data file standards on the Amiga.
    Developers who want to support these IFF standards no
    longer have to become IFF experts.  Similarly, the
    datatypes library provides a consistent and easy-to-use
    interface to the Amiga's clipboard device to encourage data
    sharing between applications.

    Intuition gadget support - Because the datatypes library is
    implemented with boopsi, the data objects it handles can
    also be treated as gadgets.  Gadget operations can be
    performed on data objects within Intuition's task context,
    the same as other boopsi gadgets.

    Automatic conversion from one format to another - Future
    versions of the datatypes library will support other types
    of data objects.  Conversion from one format to another
    will be automatically handled by the library.

    Validation - Datatypes lets you easily check if a given
    file is a valid instance of one of the data objects it
    supports.  For example, you can check to see if a file is a
    valid ILBM or not.

Classes, Objects and Methods

The jargon used to describe the datatypes library may be a little
confusing if you have never worked with object-oriented systems
before.  For instance, the kinds of data supported by the library are
divided into ``classes'' and ``sub-classes''.  The term ``class'' is
used here in a familiar way; the members of a class simply have a
common set of properties.  The members of a sub-class have all the
properties of the parent class and additional properties specific to
the sub-class.  (Each sub-class could be further broken down into
sub-sub-classes and so on.)

Class:      Ungulate    Has hooves, can run.
Sub-class:  Cow         Has udder, can be milked (also has hooves and can run).
Object:     Daisy       An instance of class Cow; can run and can be milked.

An actual instance of a class or sub-class is referred to as an
``object''.  The term ``object'' is appropriate because in general we
want to ignore the details of each individual case and concentrate
instead on what we can do with an object based on its class.  In the
example above the Daisy object can run and can be milked.  The
operations that can be performed with an object are referred to as
``methods'' and the object is said to ``inherit'' the methods and
other attributes of its parent class (which in turn inherits the
methods and attributes of its parent class, if it has one).

Currently, there are only four object classes (see Table 1) in the
datatypes library.  More will be implemented in future versions of
the Amiga OS.

Table 1: Datatypes Library Object Classes in Release 3.0 (V39)

  Object Classes          Autodoc File Showing the
  and Sub-classes             Methods Supported        Type of Data Object
 -----------------       --------------------------   ---------------------
 Picture class             <picture_dtc.doc>
   ILBM sub-class            <ilbm_dtc.doc>           IFF graphic image file

 Sound class               <sound_dtc.doc>
   8SVX sub-class            <8svx_dtc.doc>           IFF audio sample file

 Text class                 <text_dtc.doc>
   ASCII sub-class           <ASCII_dtc.doc>          ASCII characters

 AmigaGuide class          <amigaguide_dtc.doc>       Hypertext databases

The examples programs listed below demonstrate how to perform some
basic ``methods'' on ILBM and 8SVX class objects.

Datatypes Class Attributes

Datatype library classes have other attributes in addition to the
methods (operations) that they support.  For each attribute, there is
a corresponding TagItem defined in the datatypes library that you can
use to examine or set that attribute in a particular object

For example, picture objects have a display mode attribute.  The tag
that controls this attribute is named PDTA_ModeID and is described in
the Autodoc file picture_dtc.doc.  See the Autodoc files for each
class (as shown in Table 1) for a complete list of all class
attributes.

The class attribute descriptions in the include files also have a set
of codes that indicate the ``applicability'' of the attribute.  The
codes are as follows:

I - Initialize.  You can initialize the attribute when the object is created.
S - Set.  You can set the attribute to a new value after the object is created.
G - Get.  You can get the value of the attribute after the object is created.
N - Notify.  Changing the attribute triggers the object to send notification.
U - Update.  Attribute can be set using the object's OM_UPDATE method.

These codes may seem a little mysterious until you have actually
tried using the datatypes library.  The N and U codes in particular
are for special applications that want to implement their own object
classes, an advanced topic beyond the scope of this article.

Basic Functions of the Datatypes Library

If all these new concepts seem a little daunting, rest assured; the
datatypes library uses conventional C language function calls to get
the job done.  The calls you will be using most often are listed
below.  Notice that for each of these basic functions of the V39
datatypes library there is an equivalent boopsi call in the V37
Intuition library.

 Function Name          Library             Purpose
-----------------  -----------------   ------------------------------------

NewDTObject()      datatypes.library   Create a datatype object in
NewObject()        intuition.library   memory from a file or clip.

DisposeDTObject()  datatypes.library   Free an object created earlier with
DisposeObject()    intuition.library   NewDTObject() (or NewObject() ).

GetDTAttrs()       datatypes.library   Get attributes of a datatype object.
GetAttr()          intuition.library

SetDTAttrs()       datatypes.library   Set attributes for a datatype object.
SetAttrs()         intuition.library

DoDTMethod()       datatypes.library   Perform the given method (operation)
DoMethod()         amiga.lib           with a datatype object.

In a typical application the sequence of calls might be performed
like this:

1.  Use NewDTObject() to create an object in memory from given data.
2.  Get (or perhaps set) attributes of the object using GetDTAttr()
    (or SetDTAttrs() ).
3.  Perform ``methods'' (operations) with the object using
    DoDTMethod().
4.  Free the object and any memory or other resources it was using
    with the DisposeDTObject() call.

Basic Structures of the Datatypes Library

There are a lot of structures used with datatypes library function
calls; too many to summarize in this article.  However, here's a
listing of the relevant include files that contain the structure
definitions of interest to class users.

<datatypes/datatypes.h>         Group IDs, error numbers plus library overhead
<datatypes/datatypesclass.h>    Defines datatype methods and associated structures
<datatypes/picture.h>           Structures specific to the picture class
<datatypes/sound.h>             Structures specific to the sound class
<datatypes/text.h>              Structures specific to the text class
<libraries/amigaguide.h>        Structures and methods for AmigaGuide databases
<intuition/classusr.h>          Defines general boopsi object methods
<intuition/gadgetclass.h>       Defines gadget methods and associated structures

The two most important definitions in these include files appear in
<intuition/classusr.h>.  The objects used with datatypes library
functions (and the boopsi functions in Intuition) are defined as
follows:

    typedef ULONG   Object;     /* abstract handle */

Since we want to treat objects as black boxes and don't really care
how they are implemented, this definition is very appropriate.  When
a method is performed with an object, the parameter used to identify
the method is a Msg structure defined as follows:

    typedef struct {
        ULONG MethodID;
        /* method-specific data goes here */
    }       *Msg;

Some methods require more information than just the method
identifier.  Such methods have a custom structure defined in the
include files.  All method structures, however, begin with a field
that contains the method ID.

A Simple Datatypes Example

The example program listed here should clarify some of the concepts
discussed so far.  Suppose you have a communications program and want
to add the capability of playing back a user-specified 8SVX sample
file for the bell sound (Ctrl-G).  The program below shows how to
play a sound with the datatypes library.

In this program, objects are of class 8SVX (a sub-class of the sound
datatype).  The method performed with the object is named DTM_TRIGGER
(described in the Autodoc file sound_dtc.doc).  The DTM_TRIGGER
method (with type set to STM_PLAY) causes a sampled sound to be
played on the Amiga's audio hardware.  Since the DTM_TRIGGER method
requires other information in addition to the method ID, a dtTrigger
structure is used.  This structure is defined in
<datatypes/datatypesclass.h>.

Note that if the sound datatype is enhanced to support other types of
sound files in a future version of the Amiga OS, the code given here
will automatically support the new type.  This example expects the
file name and path to a sound file.

 dt.c

In addition to playing back a sampled sound, the datatypes library
allows sound objects to become gadgets (the library includes default
imagery for a sound gadget).  Since all datatypes object classes are
implemented as a sub-class of the boopsi ``gadget'' class, they all
support the methods of gadget objects as described in the boopsi
chapter of the Libraries manual.

A Picture Class Example

Here is a second, more complex example showing how to use all the
datatypes library functions described so far.  In this example, the
objects used are of class ILBM, a sub-class of picture.

Two methods will be performed with the object, DTM_PROCLAYOUT and
DTM_FRAMEBOX.  Both these methods have associated structures
(gpLayout and dtFrameBox respectively).  DTM_PROCLAYOUT makes the
object available within the context of your application task (as
opposed to Intuition's).  DTM_FRAMEBOX queries the display
environment required by the picture.

Other attributes of the picture are obtained with a call to
GetDTAttrs() and then a matching Intuition screen is created and the
ILBM object is displayed.  This example expects the file and path
name of a picture file.

 dtpic.c

As with 8SVX objects, the datatypes library allows ILBM objects to be
treated as gadgets.  Remember that all datatypes object classes a
sub-class of the boopsi ``gadget'' class and therefore support the
gadget methods described in the boopsi chapter of the Amiga ROM
Kernel Reference Manual: Libraries.


IV-111: Boopsi in Release 3

Boopsi in Release 3

by John Orr and Peter Cherna

For Release 3, Intuition gained significant improvements that
directly affect Intuition's object oriented programming subsystem,
Boopsi.  Intuition now has gadget help features, bounding boxes for
gadgets and their imagery, special custom layout gadgetry, and
several other features that all have an impact on Boopsi.

This article assumes that the reader already has a basic
understanding of Boopsi and the object oriented programming model.
For those not comfortable with these concepts, see the
``Boopsi--Object Oriented Intuition'' chapter of the ROM Kernel
Reference Manual: Libraries.

DoGadgetMethodA()

One Boopsi-related function added to intuition.library for Release 3
is DoGadgetMethodA():

    ULONG DoGadgetMethodA(struct Gadget *object, struct Window *win,
                          struct Requester *req, Msg msg);

This function is similar to amiga.lib's DoMethod(), except
DoGadgetMethod() passes along the object's graphical environment in
the form of a GadgetInfo structure.  DoGadgetMethodA() gets this
structure from the gadget's window (or requester).  The GadgetInfo
structure is important because a Boopsi gadget needs the information
in that structure to render itself.  Note that if you give
DoGadgetMethodA() a NULL Window and NULL Requester pointer,
DoGadgetMethodA() will pass a NULL GadgetInfo pointer.

The name and first parameter of DoGadgetMethodA() may lead you to
believe that this function applies only to gadgets.  Although you can
certainly use this function on gadget objects, the function is not
restricted to gadget objects.  You can use this function on any
Boopsi object.  This is important for an object such as a model
object, which may react to any Boopsi message by invoking some method
on gadget objects connected to it.  Because the model object receives
environment information in the form of a GadgetInfo structure, the
model can pass that information on to any objects connected to it.

Before this function, passing the environment information was not
that easy.  A good example of this is the rkmmodelclass example in
the ``Boopsi--Object Oriented Intuition'' chapter of RKRM: Libraries
(page 312-315).  In that example, the rkmmodelclass is a subclass of
modelclass.  The rkmmodelclass object inherits the behavior of
modelclass, so its sends updates to its member objects.  One feature
rkmmodelclass adds to modelclass is that these objects maintain an
internal integer value.  If that value changes, the rkmmodelclass
object propagates that change to its member objects.

If one of the member objects happens to be a gadget object, changing
the rkmmodelclass object's internal value may change the visual state
of the gadgets.  For the gadget's to update their visual state, they
need the environment information from the GadgetInfo structure as
well as the new internal value of the rkmmodelclass object.  If an
application used DoMethod() or SetAttrs() to set the rkmmodelclass
object's internal value, the rkmmodelclass object would not get a
GadgetInfo structure.  When the rkmmodelclass object propagates the
internal value change to its member objects, it has no environment
information to pass on to its member objects.  As a result, the
member gadgets can not update their visual state directly.  This is
particularly annoying for a propgclass object, because the visual
state of the propgclass object can depend on the rkmmodelclass
object's integer value.

DoGadgetMethodA() corrects this problem.  It passes a pointer to a
GadgetInfo structure for the window (or requester) you pass to it.
If you plan on implementing new Boopsi methods that need a GadgetInfo
structure in their Boopsi message, make sure the second long word of
the Boopsi message is a pointer to the GadgetInfo structure.
DoGadgetMethodA() assumes that every method (except for OM_NEW,
OM_SET, OM_NOTIFY, and OM_UPDATE; see the next paragraph) expects a
GadgetInfo pointer in that place.

Iif you use DoGadgetMethodA() to send an OM_SET message to a Boopsi
gadget, DoGadgetMethodA() passes a pointer to a GadgetInfo structure
as the third long word in the Boopsi message.  DoGadgetMethodA() is
smart enough to know that the OM_SET method uses an opSet structure
as its message, which has a pointer to a GadgetInfo structure as its
third long word.  DoGadgetMethodA() passes a GadgetInfo structure as
the third parameter for the OM_NEW, OM_SET, OM_NOTIFY, and OM_UPDATE
methods.  For all other methods, like the gadgetclass methods,
DoGadgetMethodA() passes a GadgetInfo structure as the second long
word.  For more information, see the V39 Autodoc for
DoGadgetMethodA() and its varargs equivalent, DoGadgetMethod().

Bounding Boxes for Gadgets

Before Release 3, gadgets only had a select (or hit) box.  This box
is the area of the window that the user can click in to select the
gadget.  The select box limits certain gadgets because the gadget's
imagery could lie outside of the gadget's hit box.  For example, the
hit box for a string gadget is the area that text appears when the
user types into the gadget (see Figure 1).  Many string gadgets have
a border and a label, which the programmer sets using the Gadget
structure's GadgetRender and GadgetText fields.  The border and label
imagery appears outside of the hit box.

 Figure 1 - String Gadget without Bounding Box

The major disadvantage of a gadget's imagery being external to its
hit box has to do with relative gadgets (these are sometimes referred
to as GREL gadgets).  Intuition positions one of these gadgets
relative to the edge's of the gadget's window.  When the window
changes dimensions, Intuition repositions the gadget within the
window.  The gadget can also make its size relative to the window's
dimensions.

When Intuition resizes a window, it remembers which portions of the
window's display sustained visual damage.  When Intuition refreshes
the visual state of the window, it only redisplays the parts of the
window that sustained visual damage.  When Intuition resizes a window
that has a GREL gadget, Intuition erases the old gadget by erasing
the hit box of the gadget and remembers that area as a region it will
have to refresh.  Intuition also figures out where the the new hit
box will be and remembers that area as a region Intuition will have
to refresh.  Because Intuition will not erase or redraw any imagery
that falls outside of the GREL gadget's hit box, Intuition will
ignore any part of the gadget's label or border that is outside the
hit box.

To remedy this situation, Intuition added a bounding box to gadgets.
If a gadget has a bounding box, Intuition uses the bounding box in
place of the hit box when figuring out what areas to refresh.  With a
bounding box, a gadget can extend its hit area to encompass all of
its imagery.

The bounding box feature is not specific to Boopsi gadgets.  Any
Intuition gadget can have one.  If the gadget doesn't supply a
bounding box, Intuition will use the gadget's normal hit box as the
bounding box, which yields the same result as previous versions of
the OS.

Adding the bounding box feature to Intuition gadgets required
extending the Gadget structure.  There is a new structure called
ExtGadget that is a superset of the old Gadget structure (from
<intuition/intuition.h>):

struct ExtGadget
{
    /* The first fields match struct Gadget exactly */
    struct ExtGadget *NextGadget; /* Matches struct Gadget */
    WORD LeftEdge, TopEdge;       /* Matches struct Gadget */
    WORD Width, Height;           /* Matches struct Gadget */
    UWORD Flags;                  /* Matches struct Gadget */
    APTR SpecialInfo;             /* Matches struct Gadget */
    UWORD GadgetID;               /* Matches struct Gadget */
    APTR UserData;                /* Matches struct Gadget */

    /* These fields only exist under V39 and only if GFLG_EXTENDED is set */
    ULONG MoreFlags;
    WORD BoundsLeftEdge;        /* Bounding extent for gadget, valid */
    WORD BoundsTopEdge;         /* only if the GMORE_BOUNDS bit in   */
                                /*  the MoreFlags field is set.  The */
    WORD BoundsWidth;           /* GFLG_RELxxx flags affect these    */
    WORD BoundsHeight;          /* coordinates as well.              */
};

Intuition discerns a Gadget from an ExtGadget by testing the Flags
field.  If the GFLG_EXTENDED bit is set, the Gadget structure is
really an ExtGadget structure.  Intuition will use the bounding box
only if the GMORE_BOUNDS bit in the ExtGadget.MoreFlags field is set.

Gadgetclass supports an attribute called GA_Bounds that sets up a
Boopsi gadget's bounding box.  It expects a pointer to an IBox
structure (from <intuition/intuition.h>) in the ti_Data field, which
gadgetclass copies into the bounding box fields in the ExtGadget
structure.

Gadget Help

Intuition V39 introduces a help system designed around Intuition
gadgets.  Window-based applications can elect to receive a new type
of IDCMP message called IDCMP_GADGETHELP when the user positions the
pointer over one of the window's gadgets.  The pointer is over the
gadget if the pointer is within the gadget's bounding box (which
defaults to the gadget's hit box).

Using the intuition.library function HelpControl(), an application
can turn Gadget Help on and off for a window:

  VOID HelpControl(struct Window *my_win, ULONG help_flags);

Currently, the only flag defined for the help_flags field is
HC_GADGETHELP (from <intuition/intuition.h>).  If the HC_GADGETHELP
bit is set, HelpControl() turns on help for my_win, otherwise
HelpControl() turns off gadget help for the window.

When gadget help is on for the active window, Intuition sends
IDCMP_GADGETHELP messages to the window's IDCMP port.  Each time the
user moves the pointer from one gadget to another, Intuition sends an
IDCMP_GADGETHELP message about the new gadget.  Intuition also sends
an IDCMP_GADGETHELP message when the user positions the pointer over
a gadgetless portion of the window, and when the user moves the
pointer outside of the window. An application can find out what
caused the IDCMP_GADGETHELP message by first examining the
IntuiMessage's IAddress field.  If IAddress is NULL, the pointer is
outside of the window.  If IAddress is the window address, the
pointer is inside of the window, but not over any gadget.  If
IAddress is some other value, the user positioned the pointer over
one of the window's gadgets and IAddress is the address of that
gadget.

To discern between the different system gadgets (window drag bar,
window close gadget, etc.) an application has to check the GadgetType
field of the gadget:

    #define GTYP_SYSTYPEMASK 0xF0   /* This constant did not appear in */
                                    /* earlier V39 include files.      */

    sysgtype = ((struct Gadget *)imsg->IAddress)->GadgetType & GTYP_SYSTYPEMASK;

The constant GTYP_SYSTYPEMASK  (defined in <intuition/intuition.h>)
corresponds to the bits of the GadgetType field used for the system
gadget type.  There are several possible values for sysgtype (defined
in <intuition/intuition.h>):

    GTYP_SIZING		Window sizing gadget
    GTYP_WDRAGGING	Window drag bar
    GTYP_WUPFRONT		Window depth gadget
    GTYP_WDOWNBACK	Window zoom gadget
    GTYP_CLOSE		Window close gadget

If sysgtype is zero, IAddress is the address of an application's
gadget.

Not all gadget's will trigger an IDCMP_GADGETHELP event.  Intuition
will send gadget help events when the pointer is over a gadget with
an extended Gadget structure (struct ExtGadget from
<intuition/intuition.h>) and a set GMORE_GADGETHELP flag (from the
ExtGadget.MoreFlags field).

To set or clear this flag for a Boopsi gadget, an application can use
the GA_GadgetHelp attribute.  Setting GA_GadgetHelp to TRUE sets the
flags and setting it to FALSE clears the flag.  Only the OM_SET
method applies to this gadgetclass attribute.

To support gadget help, gadgetclass gained a new method called
GM_HELPTEST.  This method uses the same message structure as
GM_HITTEST, struct gpHitTest (defined in <intuition/gadgetclass.h>),
and operates similarly to GM_HITTEST.  While a window is in help
mode, when the user positions the pointer within the bounding box of
a Boopsi gadget that supports gadget help, Intuition sends the gadget
a GM_HELPTEST message.

Like the GM_HITTEST method, the GM_HELPTEST method asks a gadget if a
point is within the gadget's bounds.  Like the GM_HITTEST method, the
GM_HELPTEST method allows a Boopsi gadget to have a non-rectangular
hit area (or in this case, a help area).  If the point is within the
gadget, the gadget uses one of two return codes.  If the gadget
returns a value of GMR_HELPHIT, Intuition places a value of 0xFFFF in
the Code field of the IDCMP_GADGETHELP message. The gadget also has
the option of using GMR_HELPCODE instead of GMR_HELPHIT.
GMR_HELPCODE is a little peculiar as a return value.  Although
GMR_HELPCODE is 32 bits long, Intuition identifies GMR_HELPCODE using
only its upper 16 bits.  If the upper 16 bits of GM_HELPTEST's return
value matches the upper 16 bits of GMR_HELPCODE, Intuition copies the
lower word of the return value into the Code field of the
IDCMP_GADGETHELP message.  The Boopsi gadget is free to set the
return value's lower word to any 16-bit value.

If the point is not within the gadget's ``help spot'', the gadget
returns GMR_NOHELPHIT.  Intuition will then look under that gadget
for more gadgets.  If a gadget's dispatcher passes the GM_HELPTEST
method on to the gadgetclass dispatcher, the gadgetclass dispatcher
will always return GMR_HELPHIT.

An application can put several windows in the same help group.  This
feature groups several windows so that as long as one of those
windows is active, the application can receive IDCMP_GADGETHELP
messages about all of those windows.  For more information, See the
HelpControl() Autodoc and the WA_HelpGroup section of the
OpenWindow() Autodoc (both are in intuition.doc).

Boopsi Gadgets and ScrollRaster()

This section covers some fairly complicated aspects of Intuition
Windows and how Intuition interacts with the Layers system.  For a
more in depth explanation, see the article, ``Optimized Window
Refreshing'' from the July/August 1992 issue of Amiga Mail.

Scrolling an Intuition display with ScrollRaster() is unlike many
other rendering operations because it can damage a window layer.
ScrollRaster() is both a rendering function and a layering function
(ScrollRaster() is a graphics.library function, but it is aware of
the Layers system).  If window X overlaps window Y, scrolling window
Y can scroll a portion of window Y out from underneath window X:

 Figure 2 - Damage from a Scrolling Operation

For both smart refresh and super bitmap windows, this does not
present a problem.  Layers remembers what was underneath window X and
restores that portion of the display when a layers operation reveals
it.  When a scrolling operation damages a smart refresh or super
bitmap window, Layers repairs the display.

         What is Layer Damage?

         The Layers definition of ``damage'' is a little
         confusing.  Looking at the illustration, two areas of
         window Y need to be refreshed: the area that used to be
         underneath window X, and the area that was scrolled
         into view at the bottom of window Y (the partially
         visible ``RSTUVWXY'').  Layers considers only one of
         these areas to be ``damaged'', the area the was
         scrolled out from underneath window X. Layers considers
         it damaged because the damage was caused by the
         presence of another window layer.  The task that called
         ScrollRaster() has no idea that there is an overlapping
         window layer, so it is up to Layers to account for that
         damage.  On the other hand, the task that called
         ScrollRaster() knows that the area at the bottom of
         window Y needs refreshing, so the task knows to fix
         that area of the window.  To Layers, damage is the area
         of a layer that needs refreshing as a result of layers
         operation.

For a simple refresh window, Layers remembers which portion of the
window layer is damaged.  Layers does nothing to repair the damage.
Layers leaves repairing the damage to Intuition.  After performing a
layers operation on a window (such as scrolling a portion of a
window), Intuition must check if that operation caused layer damage
(either to that window or other windows on the display).

In Release 2, when Intuition told a scrolling Boopsi gadget to render
itself, Intuition did not check for layer damage.  If that gadget
damaged the display with the ScrollRaster() function, Intuition did
not repair that damage.

As of Release 3.0, Intuition has a flag set aside in the MoreFlags
field of the ExtGadget structure called GMORE_SCROLLRASTER (defined
in <intuition/intuition.h>).  If this flag is set, when the gadget
damages the display with ScrollRaster() (or ScrollRasterBF()),
Intuition redraws all GMORE_SCROLLRASTER gadgets in the damaged
window.  The class dispatcher should take care of setting this flag
when creating the gadget in the OM_NEW method.

ScrollRaster() is not the only function in Release 3 that can scroll
a window's contents.  For Release 3, the Intuition library gained a
function specifically to scroll a window's raster.  That function,
ScrollWindowRaster(), is similar to ScrollRaster(), but
ScrollWindowRaster() is Intuition-friendly.  Boopsi gadgets must not
use this function, they should use ScrollRaster() or ScrollRasterBF()
instead.  Also any applications that use GMORE_SCROLLRASTER gadgets
must use ScrollWindowRaster() for scrolling.  Note that gadgets
supplied by third parties or Commodore may be GMORE_SCROLLRASTER
gadgets.  For more information on ScrollWindowRaster(), see its
Autodoc.

Smart Layout Gadgets

Prior to Release 3, Intuition took care of laying out GREL gadgets
whenever the dimensions of the window change.  This was a limitation
for a GREL Boopsi gadget that wants to perform its own layout.
Because Intuition didn't tell the Boopsi gadget that the window's
dimensions changed, the gadget cannot react to the change.

As of Release 3, Intuition uses a new gadget method called GM_LAYOUT
to tell a GREL Boopsi gadget that its window's dimensions have
changed.  The GM_LAYOUT method uses the gpLayout structure (defined
in <intuition/gadgetclass.h>) as its message:

struct gpLayout
{
    ULONG	              MethodID;
    struct GadgetInfo  *gpl_GInfo;
    ULONG               gpl_Initial; /* This field is non-zero if this method was invoked
                                      * during AddGList() or OpenWindow().  zero if this
                                      * method was invoked during window resizing.
                                      */
};

For GREL gadgets, Intuition sends a GM_LAYOUT message just after
erasing the gadget's bounding box.  Intuition does not touch the
values of the gadget's bounding box or hit box, it lets the gadget
handle recalculating these values.  Thee gadget can lay itself out
based on the new window (or requester) dimensions found in the
GadgetInfo structure passed in the GM_LAYOUT message (gpl_GInfo from
the gpLayout structure).  Intuition also adds the old and new
bounding box of the gadget to the window's damaged regions so that
the gadget will appear is its new position.  The gadget must not
perform any rendering inside the GM_LAYOUT method.  Intuition will
send a GM_RENDER message to the gadget when its time to redraw the
gadget in its new position.

There are two cases where Intuition sends a GM_LAYOUT message:

    When the gadget's window is resized
    When Intuition adds the gadget to a window

There are two ways for a window to gain gadgets.  An application can
explicitly add gadgets using the AddGList() function.  The window can
also gain gadgets during it initialization in the OpenWindow() call.

For most GREL Boopsi gadgets, Intuition expects the values in the
LeftEdge, TopEdge, Width, and Height fields to follow the existing
convention for regular GREL gadgets.  Each of these fields has a flag
in the Gadget.Flags field (GFLG_RELRIGHT, GFLG_RELBOTTOM,
GFLG_RELWIDTH, and GFLG_RELHEIGHT, respectively).  If that field's
flag is set, Intuition expects the value in that field to be relative
to either the window border or the window dimensions.  For example,
if GFLG_RELRIGHT is set, Intuition expects the value in the gadget's
LeftEdge field to be relative to the right window border.

There is a special kind of GREL Boopsi gadget called a custom
relativity gadget.  For this type of gadget, Intuition expects the
values in the LeftEdge, TopEdge, Width, and Height fields to be
absolute measurements, just like the values Intuition expects in
these fields for non-GREL gadgets.

Setting the GFLG_RELSPECIAL bit in the Gadget.Flags field marks the
gadget as a custom relativity gadget.  The best way to set this bit
is by setting the GA_RelSpecial attribute to TRUE when creating the
gadget.

Disabled Imagery

Certain gadget types support using a Boopsi Image as its imagery.
These gadget types include the non-Boopsi boolean gadget, the
frbuttonclass gadget, and the buttongclass gadget (This can also
include private gadget classes that support the GA_Image attribute).
The Gadget structure contains a field called GadgetRender which can
point to a Boopsi Image object (the GFLG_GADGIMAGE bit in the
Gadget.Flags field should also be set, see the``Intuition Gadgets''
chapter of the RKRM:Libraries for more information).  Intuition uses
this image as the gadget's imagery.

When a gadget uses this scheme for its imagery, Intuition sends
IM_DRAW (and IM_DRAWFRAME) messages to the image object.  These
imageclass methods not only tell a Boopsi image to render itself,
they also tell the image which state to draw itself.  Some examples
of image states include normal, selected, and disabled.

Prior to Release 3, when Intuition sent a draw message to one of
these images, it only used the normal and selected states.  If the
image was disabled, Intuition told the image to draw itself as normal
or selected and would render the standard ``ghosted'' imagery over
the gadget.

Under Release 3, Intuition will use the disabled state as well, but
only if the gadget's image object supports it.  When Intuition adds
the gadget to a window, Intuition tests the IA_SupportsDisabled
attribute of the gadget's image object.  This imageclass attribute
was introduced in Release 3.  If this attribute is TRUE, the image
supports disabled imagery (both the IDS_DISABLED and
IDS_SELECTEDDISABLED states), so Intuition sets the GFLG_IMAGEDISABLE
flag in the Gadget structure's Flags field.  Intuition uses this flag
to tell if it should use the image's disabled state in the
IM_DRAW/IM_DRAWFRAME message.

As the IA_SupportsDisabled attribute is a fixed property of an image
object, it is only accessible using the OM_GET method.  An
application cannot set it or clear it.

Frameiclass Frame Types

For Release 3, the Boopsi image class frameiclass acquired a new
attribute, IA_FrameType.  This attribute allows applications to
choose a frame style for a frame image.  Currently there are four
styles available:

    FRAME_DEFAULT - This is the default frame which was the only
    available frame in V37.  It has thin edges.

    FRAME_BUTTON - This is the imagery for the standard button
    gadget. It has thicker sides and nicely edged corners.

    FRAME_RIDGE - This is a ridge commonly used by standard string
    gadgets.  When recessed (using the frameiclass attribute
    IA_Recessed), this image appears as a groove.  Applications and
    utilities commonly use the recessed image to visually group
    objects on the display.

    FRAME_ICONDROPBOX - This broad ridge is the system standard
    imagery for icon ``drop boxes'' inside of an AppWindow (see the
    ``Workbench and Icon Library'' chapter of the RKRM:Libraries for
    more information on AppWindows).  The recessed version has no
    standard purpose.

 Figure 3 - Frameiclass Frame Types

Additions to Sysiclass

The class of system images, sysiclass, gained two new images for
Release 3, a menu check mark image and an Amiga key image
(respectively, MENUCHECK and AMIGAKEY from
<intuition/imageclass.h>):

 Figure 4 - Menu Check Mark and Amiga Key Images

This class also gained a new attribute called
SYSIA_ReferenceFont.  This attribute, which is only accessible
with the OM_NEW method, points to a TextFont structure.  The
MENUCHECK and AMIGAKEY images will use this font to figure out
how large to make the image.  This attribute overrides the
SYSIA_DrawInfo font and SYSIA_Size attributes when calculating
the dimensions of the image.

About the Example

The example at the end of this article, relative.c, uses three
features mentioned in this article.  The example implements a
private subclass of gadgetclass.  The new class utilizes the
frameiclass IA_FrameType attribute to create a button gadget.
The class also takes advantage of the custom relativity feature.
The example opens a window placing one of these gadgets in the
middle of the window, sizing the gadget relative to the window's
dimensions.

The example also illustrates the gadget help feature of
Intuition.  When the private class dispatcher receives a
GM_HELPTEST message, it returns the bitwise AND of GMR_HELPCODE
and the value 0xC0DE.  When the example receives an
IDCMP_GADGETHELP message at the window's message port, the
example examines the message to find out what object triggered
the help message and printf()s the results.

 relative.c


IV-125: Features of V39 GadTools

Features of V39 GadTools

by Mark Ricci

The V39 GadTools library has been upgraded with new features and
capabilities that support the enhanced graphic capabilities of the AA
chipset.  Other improvements include support for IDCMP_GADGETHELP
events, more support for IDCMP_GADGETUP events, scalable imagery and a
new function, GT_GetGadgetAttrs(), to obtain the values of certain
gadget attributes.

This article assumes you are familiar with the previous version of the
GadTools library.  If not, you should refer to the ``GadTools Library''
chapter of the Amiga ROM Kernel Reference Manual: Libraries for an
in-depth explanation of GadTools.  You should also refer to the
GadTools Autodoc for complete explanations of the GadTools functions.
All tags and constants referenced in this article are defined in
<libraries/gadtools.h> and <intuition/intuition.h>.

The NewLook Menus

For V37, Intuition received a facelift.  V37 introduced the ``NewLook''
rendering scheme, which improved the appearance of most of the elements
of the Amiga user interface (windows, system gadgets, standard Boopsi
classes, etc.).  One element of the Amiga's GUI that escaped the
NewLook was the menu system.

For V39, Intuition added the NewLook to its menus.  When Intuition
renders NewLook menus, it gets the colors for the menu from the Palette
Preferences set by the user.  Before V39, Intuition used the window's
DetailPen and BlockPen to draw the menu and the colors of the MenuItems
depended on the MenuItem's IntuiText or Image structure.

GadTools fully supports Intuition's NewLook menus.  To make GadTools
use the NewLook color scheme for a window's menus, an application needs
to do two things.  First, it needs to tell Intuition that it wants
NewLook menu imagery for the window.  It does this when opening the
window by passing the {WA_NewLookMenus, TRUE} tag/value pair to
OpenWindowTags().  Second, the application needs to remind GadTools
that the window uses NewLook imagery for its menus.  The application
does this by passing the {GTMN_NewLookMenus, TRUE} tag/value pair to
LayoutMenus():

    struct VisualInfo *vi;

    LayoutMenus(menusready, vi, GTMN_NewLookMenus, TRUE, TAG_END);

Instead of using the GTMN_NewLookMenus tag, it's possible to set the
menu colors yourself by using the GTMN_FrontPen tag to set the pen
number for rendering menu text.  In addition to this tag, you must set
the screen's BARDETAILPEN and BARTRIMPEN to match the menu text pen and
set the BARBLOCKPEN to the color you want for the title bar.  However,
you cannot control how Intuition complements menu items and you do not
automatically get the user's menu color preferences, so you will not
get as perfect NewLook menu as you would by leaving it to the system.

Gadgets

Most GadTools gadgets received new attributes in V39.  These include
new IDCMP events, the ability to specify rendering pens, and scalable
imagery.

IDCMP Events

Button, integer and string gadgets can send IDCMP_GADGETDOWN events by
setting the GA_Immediate tag to TRUE.

Disabling

MX and listview gadgets join the other GadTools gadgets in having a
disable attribute.  Set the GA_Disabled tag to TRUE to disable, and
FALSE to re-enable.

Scalable Imagery

Checkbox and MX gadgets are no longer fixed in size.  You can scale
them to any width and height.  If you do not specify scaling, GadTools
uses its built-in default dimensions.  These dimensions,  which are
defined in <libraries/gadtools.h> , are CHECKBOXWIDTH and
CHECKBOXHEIGHT for checkbox gadgets, and  MXWIDTH by MXHEIGHT for MX
gadgets.

To scale a checkbox gadget, set the GTCB_Scaled tag to TRUE, and set
the desired width and height in the ng_Width and ng_Height fields of
the NewGadget structure.  The default value of GTCB_Scaled is FALSE,
meaning use the default size of 26 by 11, the values of CHECKBOXWIDTH
and CHECKBOXHEIGHT, respectively.

To scale an MX gadget, set the GTMX_Scaled tag to TRUE, and set the
desired width and height in the ng_Width and ng_Height fields of the
NewGadget structure.  The default value of GTMX_Scaled is FALSE,
meaning use the default size of 17 by 9, the values of MXWIDTH by
MXHEIGHT, respectively.  If you scale MX gadgets, you must also set the
GTMX_Spacing tag to NewGadget.ng_TextAttr->ta_YSize + 1 to properly
space the buttons with respect to the font.

Rendering Pens, Display Format, Justification, Clipping and Display Size

Application writers use number, text, and to some degree, slider
gadgets, to present information to the user.  The new attributes for
these gadgets improve the presentation of the information.

You can specify any pen for rendering the foreground and the background
of number and text gadgets.  This allows you to use color for emphasis
or aesthetics.  For example, you might use red as the foreground color
in a text gadget for emphasis.  You can also use C-language-like
formatting strings for the displays, e.g., %lx  would give you
hexadecimal output in a number gadget.  The Exec RawDoFmt() function
processes this string, so refer to that function for details.

Text clipping is another new attribute.  It clips the display to fit
within the borders of the gadget.  This prevents the text or number
from running over the border of a gadget if it's too large for the
gadget.  Along with text clipping, the number, text and slider gadgets
can left, center and right justify their displays.

Finally, you can specify the size of the string buffer that number and
slider gadgets use when formatting their text.  This buffer must be
large enough to hold the entire string generated by the gadget, as the
gadget doesn't do any bounds checking on the buffer.  Underestimating
the size of the buffer will cause the gadget to overwrite the buffer,
overwriting whatever happens to follow the buffer in memory.

For number gadgets, the GTNM_FrontPen tag specifies the pen to use for
rendering the number.  The default is DrawInfo->dri_Pens[TEXTPEN]).
GTNM_BackPen specifies the pen to use for rendering the background of
the number.  The default is to use the background color of the gadget's
window.

GTNM_Justification specifies the type of justification within the
gadget box.  GTJ_LEFT renders the number flush with the left side of
the gadget, GTJ_RIGHT renders the number flush with the right side, and
GTJ_CENTER centers the number.  The default is GTJ_LEFT.

GTNM_Format specifies the C-language-like formatting string used to
display the number.  You must use the ``l'' (long) modifier.  The
default is ``%ld''.  The gadget passes the formatting string to the
exec.library function RawDoFmt(), which generates the string that
appears in the number gadget.  See the Autodoc for RawDoFmt() for more
information on the formatting string.

If an application changes the default formatting string with the
GTNM_Format tag, the string that the number gadget displays may become
significantly longer.  For example, if the application uses the format
string ``my number is %ld'', when the gadget processes the formatting
string with RawDoFmt(), RawDoFmt() generates a string at least 14
characters long.  By default, the gadget sets aside a 10 byte buffer
for RawDoFmt() to use, so the formatting string above is too long for
the default buffer.  The tag GTNM_MaxNumberLen sets the size of this
buffer.

GTNM_Clipped controls text clipping.  The default behavior differs
between number gadgets with borders and number gadgets without borders.
For bordered number gadgets, the default is TRUE--clip the display to
fit within the gadget borders.  For gadgets without borders, the
default is FALSE--no clipping.

Text gadgets also have a new set of attributes that correspond to the
new number gadget attributes.  These corresponding tags are:
GTTX_FrontPen, GTTX_BackPen, GTTX_Justification, and GTTX_Clipped.
There is no corresponding text gadget tag for GTMN_MaxNumberLen or
GTMN_Format.

Slider gadgets use the GTSL_Justification tag with the constants listed
above (GTJ_LEFT, GTJ_RIGHT, and GTJ_CENTER) to control justification of
the gadgets numeric display.  The GTSL_MaxPixelLen tag specifies the
maximum pixel size of the level display for any value of the slider.
This is primarily useful when dealing with proportional fonts.  The
default is the font's character width (from the font's
TextFont->tf_XSize field) multiplied by the value in the
GTSL_MaxLevelLen tag.

New Gadget-Specific Attributes

MX gadgets can now have titles.  The gadget obtains its title from the
ng_GadgetText field of the NewGadget structure.  The GTMX_TitlePlace
tag specifies where to place the title.  The possible values are:

    PLACETEXT_LEFT  Right-align text on left side
    PLACETEXT_RIGHT Left-align text on right side
    PLACETEXT_ABOVE Center text above
    PLACETEXT_BELOW Center text below

For compatibility reasons, GadTools will not put a title on the MX
gadget if the GTMX_TitlePlace tag is not present.

Listviews

Listview gadget improvements include forced display of an item,
highlighting of the selected item in the listview and custom callback
hooks.

The GTLV_MakeVisible tag specifies the number of the item that should
be forced into the viewing area.  It overrides the GTLV_Top tag.

In V37, a listview identified its currently selected item by displaying
it in a text gadget beneath the listview.   The tag GTLV_ShowSelected
specifies how the listview indicates which item is the currently
selected item.  If set to NULL, the listview places a highlight bar
over the currently selected item.  If GTLV_ShowSelected points to a
string gadget, the listview displays the selected item in the string
gadget in addition to a highlight bar.

You can use callback hooks to render a listview's items.  The listview
in the V39 Palette Preferences editor uses a callback hook to display
the standard user interface pens.  The callback hook makes it possible
for each item to display the pen color in addition to the pen name.
The pen color appears in a little box at the left edge of each item in
the listview.

Palette

GTPA_NumColors sets the number of colors to display in the palette
gadget.  This overrides the GTPA_Depth tag and allows numbers that are
not powers of 2 (which was a limitation of the V37 palette gadget).
The default is 2.

Palette gadgets can now have their own array of pen numbers.
GTPA_ColorTable is a pointer to a array of pen numbers.  The array must
contain at least as many entries as there are colors displayed in the
palette gadget.  The default is NULL which causes a 1-to-1 mapping of
pen numbers.  That means if you don't specify this tag, your palette
will use pen number 0 through pen n-1, where n is the number of colors
you set in GTPA_NumColors.  For example, if you set GTPA_NumColors to 6
and don't specify GTPA_ColorTable, you will get a pen array of pens 0,
1, 2, 3, 4, and 5.

A pen array you specify looks like this:

    UBYTE colors[8]= {1,2,15,6,0,3,8};

Setting GTPA_ColorTable to this array indicates that the palette pens
are 1, 2, 15, 6, 0, 3 and 8, respectively.  Note that you have to
allocate pens to be certain you can use them and control them.  See the
Amiga OS V39 Developer Release Notes for information on allocating and
sharing pens.

You cannot use the GTPA_ColorTable tag with the GTPA_ColorOffset tag.
The GTPA_ColorOffset tag specifies which pen to use as the first pen of
a palette.  For example, if you set it to 4, the first pen used in the
palette will be pen 4.  If you use the GTPA_ColorTable tag, the
GTPA_ColorOffset tag is ignored.

However, you can do color offsets with a color table by setting the
value of the GTPA_ColorTable tag to point to the color table plus the
offset you want.  In the table above, you could specify pen 6 (the
fourth member of the table) as the first pen to use by setting
GPTA_ColorTable in this manner:

    CreateGadget(PALETTE_KIND, gad, &ng,
                 GTPA_ColorTable, &colors[3],
                 TAG_END);

Note that the GTPA_NumColors tag is not present in the call above.
This will default the number of colors to two, so the palette gadget
created above will be a two color gadget that uses pens 6 and 0, the
fourth and fifth pens in the array.

Obtaining Gadget Attributes

Prior to V39, the only way to obtain the attributes of a GadTools
gadget was through the Code field of an IDCMP_GADGETUP IntuiMessage.
In addition to having to wait until the user clicked on a gadget, this
method limited you to obtaining one attribute at a time.

A new GadTools function, GT_GetGadgetAttrs() obtains a gadget's
attributes.  You may call the function at any time after creating a
gadget and for as many attributes as the function supports for that
gadget.

GT_GetGadgetAttrs() accepts a taglist of the attributes to obtain.  An
application passes it the address of the gadget, the address of the
window containing the gadget, a NULL field (this field is reserved for
later use and must be NULL for now), and a taglist.  Each attribute
value pair in the taglist supplies the ID of the tag to get (in ti_Tag)
and an address where GT_GetGadgetAttrs() can store the tag's value.
Since all tag values are longwords, expect GT_GetGadgetAttrs() to copy
a longword for each attribute you request.  The function returns the
number of attributes it obtained.

LONG how_many, top_item = 0, selected_item = 0;

how_many = GT_GetGadgetAttrs( listview_gad, win, NULL,
                              GTLV_Top, &top_item,
                              GTLV_Selected, &selected_item,
                              TAG_DONE );

How_many contains the number of gadget attributes GT_GetGadgetAttrs()
obtained.  GT_GetGadgetAttrs() copies the value of the listview top and
the selected item into top_item and selected_item, respectively.  Use
longword targets to hold the returned values.

GT_GetGadgetAttrs() supports GA_Disabled (TRUE if the gadget is
disabled; FALSE if the gadget is active) for all GadTools gadgets
except text and number gadgets.  Other attributes are specific to each
gadget as follows:

    Checkbox - GTCB_Checked returns TRUE if the checkbox gadget
    is checked, or FALSE if the gadget is not checked.

    Cycle - GTCY_Active returns the ordinal number, counting up
    from zero, of the active choice.  GTCY_Labels returns a
    pointer to the NULL-terminated array of choices.

    Integer - GTIN_Number returns the contents of the gadget.

    Listview - GTLV_Top returns the ordinal number, counting up
    from zero, of the top item.  GTLV_Selected returns the
    ordinal number of the selected item.  GTLV_Labels returns a
    pointer to the List structure associated with the gadget.

    MX - GTMX_Active returns the ordinal number, counting up
    from zero, of the active selection.

    Palette - GTPA_Color returns the ordinal number of the
    selected color. This number corresponds to the selected
    color's position in the palette's GTPA_ColorTable array.
    GTPA_ColorOffset returns the ordinal number of the first
    color used in the palette.  GTPA_ColorTable returns a
    pointer to the table of pen numbers used for the gadget, if
    there is one.

    Scroller - GTSC_Top returns the number of the top line
    visible in the scroller.  GTSC_Total returns the total
    number of lines in the scroller.  GTSC_Visible returns the
    number of visible lines in the scroller.

    Slider - GTSL_Min returns the minimum value of the slider.
    GTSL_Max returns the maximum value of the slider.
    GTSL_Level returns the current level of the slider.

    String - GTST_String returns a pointer to the gadget's
    buffer.

    Text - GTTX_Text returns a pointer to the gadget's buffer.

Message Handling - ExtIntuiMessage Structure

For V39, the IntuiMessage structure has been extended to allow for
tablet support.  The GadTools message handling
functions--GT_FilterIMsg(), GT_GetIMsg(), GT_PostFilterIMsg() and
GT_ReplyIMsg()--work with the extended IntuiMessage structure,
ExtIntuiMessage, but are backwards compatible with IntuiMessage.

Gadget Help

All GadTools gadgets support Intuition's gadget help feature.  You
enable this by calling the intuition.library function HelpControl().
Gadget help is either on or off for all GadTools gadgets in a window;
you cannot selectively enable it for certain gadgets as you can with
Intuition gadgets.  For more information, refer to page IV-114 of the
``Boopsi in Release 3'' article in the January/February 1993 issue of
Amiga Mail.

Bevel Box

Bevel boxes now come in three types that you specify with
GTBB_FrameType.  BBFT_BUTTON generates the type of box used around
button gadgets.  BBFT_RIDGE generates the type of box used for string
gadgets.  BBFT_ICONDROPBOX generates a box suitable for a standard icon
drop box imagery.  The default is BBFT_BUTTON.  These frame types are
similar to the Boopsi imageclass frame types FRAME_BUTTON, FRAME_RIDGE,
and FRAME_ICONDROPBOX, that are pictured on page IV-120 of the ``Boopsi
in Release 3'' article in the January/February 1993 issue of Amiga Mail.

Example Code - NewGadgets.c

The example code below is a demonstration of some of the V39 GadTools
changes and how to specify them in your code.  You'll notice that it
lacks many of the features required to actually use the gadgets.  This
is by design.  The intent is for you to modify an existing application
using the example as a guide.

 NewGadgets.c

NewGadgets.c produced the screen shot below.

 Figure 1 - Some New GadTools Features


IV-137: Menu Verify Handling

Menu Verify Handling

by John Orr and Peter Cherna

Menu verify has been a part of Intuition for a long time, so it may
seem a bit odd to see an Amiga Mail article on the subject.
Unfortunately, the ``Intuition Menus'' chapter of the Amiga ROM Kernel
Reference Manual: Libraries is a bit unclear on the subject.  It does
not sufficiently cover why an application would need to use this
feature and how an application should handle it.

Menu Verify

When the user tries to pull down the active window's menu, Intuition
offers applications a chance to prepare for the menu operation.
Intuition delays displaying any menus until the application has
finished its preparations for the menu operation.  This feature is
known as menu verify.

Menu verification works using the IDCMP mechanism.  For an Intuition
screen, when the user triggers Intuition into drawing the menu,
Intuition sends an IDCMP_MENUVERIFY message to every window on that
screen that asked to hear about menu verify events.  Intuition will not
display the menus until it gets back all the IDCMP_MENUVERIFY messages.

If the active window uses menu verification, Intuition gives that
window the option to cancel the menu operation.  This allows the
application to selectively use the menu button to activate the menu or
to perform some other function.

Beginning with V36, Intuition introduced a time out on menu verify
operations.  If the active window's application takes too long to
respond to the IDCMP_MENUVERIFY message, Intuition will cancel the menu
operation.  This feature helps avoid some deadlocks that can occur
while Intuition is waiting on the active window.  This feature applies
only to the active window; Intuition will wait indefinitely for the
IDCMP_MENUVERIFY message from an inactive window.

Reasons to Use Menu Verify

The primary purpose of the menu verify feature is to arbitrate access
to screen resources.  There are really only two screen resources that
an application might need to use directly, the palette and the bitmap.

Some applications need as many pens as possible, so they change the
color values of the pens that Intuition uses to render the menus.  This
can present a problem if the application happens to alter the menu pen
colors so that the menu's foreground color is difficult (if not
impossible) to see against the background color.  The menu items will
be unreadable to the user.

To prevent this problem, the application has to restore the original
pen colors when the user pulls down the menu.  The application can do
this using menu verify.  When the user hits the menu button, Intuition
sends the application a menu verify message.  When the application
receives this message, it restores the menu colors and then returns the
IDCMP_MENUVERIFY message so Intuition can properly render the menus.
When the menu operation is over, Intuition will send a ``conclusion''
IDCMP message.  The ``conclusion'' message is covered later in this
article.

Another reason to use menu verify is to arbitrate rendering access to
an Intuition Screen's bitmap.  While Intuition is displaying the menus,
the application must not render directly to the screen's bitmap because
the application could draw over the menus.  The application must wait
until the menu operation is over to resume rendering.

This raises some important questions.  Why render into a screen's
bitmap (Screen-> RastPort.BitMap)?  Shouldn't I render into a window
instead?

The quick answer is: ``render into a window's rastport instead of
rendering directly into a screen's bitmap''.  Rendering to a window's
rastport offers several advantages over rendering directly to the
screen's bitmap.  The window offers the application efficient clipping,
making the application simpler because it doesn't need to worry about
rendering into rectangular bounds.  The window also supports a layered
display, so the application can ignore the consequences of arbitrating
access to the screen's bitmap.

There are some cases where, arguably, it might be advantageous for an
application to render directly into a screen's bitmap.  Rendering into
a screen's bitmap versus rendering to a window's rastport offers a
slight improvement in performance.  Part of this improvement is due to
the lack of clipping on a screen's bitmap, which the window provides,
so the performance improvement is questionable if you still need to
perform clipping.

One case where an application has to render into a screen's bitmap is
when graphics functions that operate below the layers level.  For
example blitter objects (BOBs) operate below the layers level.  If the
application is operating below the layers level, it can't render to a
windowed display.

Reasons Not to Use Menu Verify

One feature of Intuition menus is that the user can toggle a menu item
between a selected ``checked'' state and an unselected ``unchecked''
state.  Intuition keeps track of the state, so the application only has
to read the state from the MenuItem structure.  In some cases, the
state of the menu item can be affected by something besides the user
performing menu operations, so the application has to explicitly change
the state of the menu item.

Some applications use the menu verify feature as a mechanism for
updating the state of the menu items.  When such an application
receives the IDCMP_MENUVERIFY message, it updates the checked flag of
the menu items and then returns the menu verify message.  Some
applications also use this method to manage the enabled and disabled
state of a menu item.

Although this method works, it should not be necessary to interrupt the
menu event.  Almost all applications should be able to keep their menu
states current using ResetMenuStrip().  It is also possible to use
SetMenuStrip(), but since ResetMenuStrip() is considerably faster than
SetMenuStrip(), ResetMenuStrip() is better.  See the Autodoc for
ResetMenuStrip() for more details.

Some people may think one potential use for menu verify is to assign an
alternative meaning to the right mouse button.  For example, when the
pointer is not within the title bar of a screen, some paint packages
use the right mouse button to paint using the background color.  Using
menu verify, it is possible for a application to intercept the menu
verify event, checking to see if the pointer is within the title bar.
If it isn't, the application cancels the menu event.  After cancelling
the menu event, Intuition will send a right button down event, which
the application can interpret.

This mechanism may work, but it is not very efficient.  There is a
better way to do this using WFLG_RMBTRAP.  This flag is from the Flags
field in the Window structure.  When set, this flag disables menu
operations for the window.  When the user hits the menu button,
Intuition sends the window IDCMP_MOUSEBUTTONS events instead of menu
events.

To use WFLG_RMBTRAP as an alternative to menu verify, the application
tracks mouse movement using IDCMP_MOUSEMOVE.  While the pointer is
outside of the screen's title bar, the application makes sure the
WFLG_RMBTRAP flag is set.   If the user hits the right mouse button
while WFLG_RMBTRAP is set, Intuition sends the application a mouse
button event.  While the pointer is inside the screen's title bar, the
application makes sure the WFLG_RMBTRAP flag is clear.  If the user
hits the right mouse button while WFLG_RMBTRAP is clear, Intuition
generates a normal menu event for the window.

WFLG_RMBTRAP is an exception to most fields in Intuition structures
because it is legal for an application to directly modify this flag.
Note that this change must take place as an atomic operation so that
Exec cannot perform a task switch in the middle of the change.  If you
are unsure your compiler will do this, use a Forbid()/Permit() pair to
prevent a task switch.

There are cases where an application is too busy to handle any menu
event so it needs to prevent menu operations for a while.  This is
another case where menu verify is inappropriate.  A better way to block
menus is to remove the menu with the Intuition function
ClearMenuStrip() and restore it later with ResetMenuStrip().  Another
potentially useful way to block menu operations is using a requester.

Will I Ever Need to Cancel a Menu Operation?

When the active window receives an IDCMP_MENUVERIFY message, it has the
option of cancelling the menu operation.  Although this feature may
have some possible uses, for the moment there is no recommended use for
it.

Handling Menu Verify Events

Typically, an application uses menu verify because the application
needs to know when the menus are down.  This goes for the menus of any
window on the screen, not just the application's window.  When the
application receives its IDCMP_MENUVERIFY message, it performs some
minor processing (restoring menu pen colors, for example) and records
the fact that the display is in a ``menu processing'' state (i.e.
Intuition is going to display the menus).  The application then returns
the menu verify message so Intuition can continue with the menu
operation.  The application cannot utilize the screen's resources until
the menu processing state is over.

There are two types of events that can end the menu processing state.
A cancellation or a menu pick can terminate the menu processing state.

There are several events that can cancel a menu operation.  Some
possibilities include Intuition timing out waiting for an outstanding
IDCMP_MENUVERIFY, the active window cancelling the menu operation, and
Intuition failing to allocate enough resources to display the menus.
The ``Intuition Menus'' chapter of the Amiga ROM Kernel Manual:
Libraries attempts to interpret these causes based on the IDCMP
messages that arrive after the application returns the IDCMP_MENUVERIFY
message.

The book should not have mentioned how to interpret the cause of a menu
cancellation.  The reasoning for the cancellation is not really
relevant.  Trying to interpret the cause of a menu cancellation is a
bad idea (especially if you interpret based on the information in the
book; it's wrong).  The only important fact is that the ``menu
processing'' state has terminated and the application can resume normal
operations.

Any of the following message combinations signify the cancellation of
the ``menu processing'' state:

  o IDCMP_MOUSEBUTTONS (IntuiMessage.Code is equal to MENUUP) only
  o IDCMP_MENUPICK (IntuiMessage.Code is equal to MENUNULL) only
  o IDCMP_MOUSEBUTTONS (IntuiMessage.Code is equal to MENUUP) then
      IDCMP_MENUPICK (IntuiMessage.Code is equal to MENUNULL)
  o IDCMP_MENUPICK (IntuiMessage.Code is equal to MENUNULL) then
      IDCMP_MOUSEBUTTONS (IntuiMessage.Code is equal to MENUUP)

Since the active window can cancel menu operations, the application may
need to determine if its window is the active window.  The application
can do this by examining the IntuiMessage.Code field of the menu verify
message.  If that field is equal to MENUWAITING (defined in
<intuition/intuition.h>) the window is not active.  However, if that
field is equal to MENUHOT (defined in <intuition/intuition.h>) the
window is active and can cancel the menu operation by changing the Code
field of the menu verify message to MENUCANCEL (also defined in
<intuition/intuition.h>).  If the application cancels the menu
operation, Intuition will send the active window an IDCMP_MOUSEBUTTONS
event about the right mouse button.

The following are possible cases signifying that the ``menu
processing'' state is over because the user successfully pulled down
and released the menu (there was no cancellation):

  o IDCMP_MENUPICK (IntuiMessage.Code is equal to the menu code)
  o (spurious) IDCMP_MOUSEBUTTONS (IntuiMessage.Code is equal to MENUUP)
      then IDCMP_MENUPICK (IntuiMessage.Code is equal to the menu code)

Note that the menu code could be MENUNULL if no item was selected.
IDCMP_MENUHELP events have the same meaning as the IDCMP_MENUPICK
messages when it comes to terminating the ``menu processing'' state.

There are rare cases in 3.0 and prior, where Intuition does not send
the application an IDCMP message after the user picks a menu item.  The
result is the application does not know that the ``menu processing''
state is over.  The only notable case is when the user types a menu
keyboard shortcut, and Intuition times out waiting for the application
to respond to the menu verify message.

V40 should fix the lack of a terminating event in those rare cases, as
well as eliminate the spurious IDCMP_MOUSEBUTTONS event that can occur
for successful menu picks.

About Double Menu Requesters

Intuition has a feature that allows an application to put up a special
type of requester when the user double clicks the right mouse button.
This requester is known as a Double Menu Requester.  Unfortunately, the
double menu requester is considered to be inconsistant with the Amiga's
user interface, so using them in any capacity is strongly discouraged.
Using them in conjunction with menu verify is even more strongly
discouraged because they significantly complicate processing menu
verify events.  For this reason, never use double menu requester and
menu verify together!


V-1: Using the ECS Genlocking Features

By Ewout Walraven

The ECS Denise chip (8373-R2a), coupled with the release 2.0
graphics.library, opens up a whole new set of genlocking
possibilities.  Unlike the old Denise, whose only genlocking ability
allowed keying1 on color register zero, the ECS Denise allows keying
on any color register.  Also, the ECS Denise allows keying on any
bitplane of the ViewPort being genlocked.  With the ECS Denise, the
border area surrounding the display can be made transparent (always
passes video) or opaque (overlays using color 0).  All the new
features are set individually for each ViewPort.  These features can
be used in conjunction with each other, making interesting scenarios
possible.  These hardware capabilities and the software support in
release 2.0 offer new challenges for video oriented software.

VideoControl()
--------------

The graphics.library function VideoControl() modifies the operation of
a ViewPort's ColorMap and also reports on the ColorMap's status.

    error = BOOL VideoControl( struct ColorMap *colormap,
                           struct TagItem *videocommandstagarray );

Using VideoControl(), a program can enable, disable, or obtain the
state of a ViewPort's genlocking features.  It returns NULL if no
error occurred.  The function uses a tag based interface.

This article is concerned with the following VideoControl() tags:

    VTAG_BITPLANEKEY_GET
    VTAG_BITPLANEKEY_SET
    VTAG_BITPLANEKEY_CLR
    VTAG_CHROMA_PLANE_GET
    VTAG_CHROMA_PLANE_SET
    VTAG_BORDERBLANK_GET
    VTAG_BORDERBLANK_SET
    VTAG_BORDERBLANK_CLR
    VTAG_BORDERNOTRANS_GET
    VTAG_BORDERNOTRANS_SET
    VTAG_BORDERNOTRANS_CLR
    VTAG_CHROMAKEY_GET
    VTAG_CHROMAKEY_SET
    VTAG_CHROMAKEY_CLR
    VTAG_CHROMAPEN_GET
    VTAG_CHROMAPEN_SET
    VTAG_CHROMAPEN_CLR

See <graphics/videocontrol.h> for a complete list of all the available
tags.

VTAG_BITPLANEKEY_GET is used to find out the status of the bitplane
keying mode.  VTAG_BITPLANEKEY_SET and VTAG_BITPLANEKEY_CLR activate
and deactivate bitplane keying mode.  If bit plane key mode is on,
genlocking will key on the bits set in a specific bitplane from the
ViewPort (the specific bitplane is set with a different tag).  The
data portion of these tags is NULL.

For inquiry commands like VTAG_BITPLANEKEY_GET (tags ending in _GET),
VideoControl() changes the _GET tag ID to the corresponding _SET or
_CLR tag ID, reflecting the current state.  For example, when passed
the following tag array:

    struct TagItem videocommands[] =
    {
        { VTAG_BITPLANEKEY_GET, NULL},
        {VTAG_END_CM, NULL}
    };

VideoControl() changes the VTAG_BITPLANEKEY_GET ID to
VTAG_BITPLANEKEY_SET if bit plane keying is currently on, or to
VTAG_BITPLANEKEY_CLR if bit plane keying is off.  In both of these
cases, VideoControl() only uses the tag's ID, ignoring the tag's data
field.

The VTAG_CHROMA_PLANE_GET tag returns the number of the bitplane keyed
on when bit plane keying mode is on.  VideoControl() changes the tag's
data value to the bitplane number.  VTAG_CHROMA_PLANE_SET sets the
bitplane number to the tag's data value.

VTAG_BORDERBLANK_GET is used to obtain the border blank mode status.
This tag works exactly like VTAG_BITPLANEKEY_GET.  VideoControl()
changes the tag's ID to reflect the current border blanking state.
VTAG_BORDERBLANK_SET and VTAG_BORDERBLANK_CLR activate and deactivate
border blanking.  If border blanking is on, the Amiga will not display
anything in its display border, allowing an external video signal to
show through the border area.  On the Amiga display, the border
appears black.  The data portion of these tags is NULL.

Respectively, the VTAG_BORDERNOTRANS_GET, VTAG_BORDERNOTRANS_SET, and
VTAG_BORDERNOTRANS_CLR tags are used to obtain the status of
BorderNoTransparent mode, and to activate and to deactivate this mode.
If set, the Amiga display's border will overlay external video with
the color in register 0.  Because border blanking mode takes
precedence over BorderNoTransparent mode, setting BorderNoTransparent
has no effect if border blanking is on.  The data portion of these
tags is NULL.

Respectively, the VTAG_CHROMAKEY_GET, VTAG_CHROMAKEY_SET, and
VTAG_CHROMAKEY_CLR tags are used to obtain the status of chroma keying
mode, and to activate and deactivate chroma keying mode.  If set, the
genlock will key on colors from specific color registers (the specific
color registers are set using a different tag).  If chroma keying is
not set, the genlock will key on color register 0.  The data portion
of these tags is NULL.

VTAG_CHROMAPEN_GET obtains the chroma keying status of an individual
color register.  The tag's data field contains the register number.
Like the other _GET tags, VideoControl() changes the tag ID to one
reflecting the current state.  VTAG_CHROMAPEN_SET and
VTAG_CHROMAPEN_CLR activate and deactivate chroma keying for each
individual color register.  chroma keying can be active for more than
one register.  By turning off border blanking and activating chroma
keying mode, but turning off chroma keying for each color register, a
program can overlay every part of an external video source, completely
blocking it out.

After using VideoControl() to set values in the ColorMap, the
ColorMap's ViewPort has to be rebuilt with MakeVPort(), MrgCop(), and
LoadView(), so the changes can take effect.  A program that uses a
screen's ViewPort rather than its own ViewPort should use the
Intuition functions MakeScreen() and RethinkDisplay() to make the
display changes take effect.

The following example, genlockdemo.c, shows how to add genlock support
for an Intuition screen.


V-11: Finding the Aspect Ratio

by Carolyn Scheppner

The pixel aspect ratio describes the ratio of the width (x Aspect) to
height (y Aspect) of the pixels in a Screen or ViewPort.  In order to
create a truly What-You-See-Is-What-You-Get graphics display on the Amiga,
you need to find the pixel aspect ratio of the display mode you are using.
With the proper aspect ratio, an application can correctly display and
store ILBM files, can rotate objects properly, and can calculate the
proper dimensions to draw true circles and squares so they appear the same
on the Amiga display as they would on some other output device, like a
laser printer.

Under 1.3 and the original Amiga chip set, relatively few display modes
were available.  Under pre-2.0 versions of the OS, applications can use
hard-coded values for the X/Y pixel aspect ratio.  The aspect ratios for
the display modes available to the 1.3 system are ( xaspect / yaspect ):

        NTSC Lores      44/52
        PAL Lores       44/44

        Halve the X aspect for Hires modes.
        Halve the Y aspect for interlaced modes.

These aspect values are more accurate than the values in the original IFF
document.

On PAL displays, the pixels of Lores screens and Hires Interlace screens
are square, as they have an aspect ratio of 44/44 and 22/22, respectively.
To draw a square 100 pixels wide in one of these PAL modes, you could
simply draw a square that is 100 pixels x 100 pixels.  On a PAL Lores
Interlace display, the Y resolution is doubled, making each pixel half as
tall, so you would have to draw a rectangle that was 100 pixels x 200
pixels to get the same size square.

On an NTSC display, pixels are not square.  Pixels on a Lores NTSC screen
have an aspect ratio of 44/52 (or 11/13).  This means that each pixel is
slightly narrower than it is high.

To draw a true square that is 100 pixels wide in an arbitrary display
mode, it is necessary to calculate the correct height for the square based
on the pixel aspect ratio.

    width / yAspect = height / xAspect

(in words, width is to yAspect as height is to xAspect)

If the X/Y aspect is 44/52 (Lores NTSC), the calculation would be:

    100 / 52 = height / 44

    height = (100 * 44) / 52 = 4400 / 52    /* solve for height */

Because this example uses only integer math, the ratio must be rounded to
the nearest integer.  A fraction a/b (where a and b are integers) rounded
to the nearest integer approximately equals:

    ( a + ( b / 2 ) )  /  b

apply this to the ratio above:

    height = ( 4400 + (52>>1) ) / 52      /* with rounding */
    height = 4426/52 = 85.115384...       /* Approximate */
    height = 85                           /* truncated */

Therefore, to be square on a 44/52 aspect screen, a 100 pixel wide square
would have to be 85 pixels tall.

Under 2.0 and the ECS chip set, the Amiga display is more dynamic.  It has
many new display modes, each of which has its own distinct pixel aspect
ratio.  For this reason, it is not practical nor desirable to hard code
the aspect ratios for the modes that you know about (except when running
under 1.3).  When running under 2.0, the pixel aspect should be determined
by querying the display database (see the article ``An Introduction to V36
Screens and Windows'' from the September /October 1990 issue of Amiga Mail
for more information on how to query the display database).  A valid
DisplayInfo structure contains the X and Y aspect in the Resolution.x and
Resolution.y fields.  When writing an ILBM under 2.0, use these pixel
aspects from the display database for the BMHD chunk's xAspect and yAspect
values.

The following example getaspect.c demonstrates how to determine the X and
Y aspects under both release 2.0 and 1.3.


V-15: Amiga Font Scaling and Aspect Ratio

by John Orr

[Editor's Note: This article assumes the reader is familiar with how the
Amiga stores and manages bitmap fonts under pre-2.0 Releases of the
operating system.  For more information, see the "Graphics: Text" chapter
of the RKM:Libraries and Devices Manual.]

The Release 2.0 OS offers a significant improvement over the Amiga's
previous font resources: it now has the ability to scale fonts to new
sizes and dimensions.  This means, if the diskfont.library can't find the
font size an application requests, it can create a new bitmap font by
scaling the bitmap of a different size font in the same font family.  The
2.04 release of the OS improved upon the diskfont.library's font scaling
ability so the Amiga now can utilize AGFA/Compugraphic outline fonts,
yielding scalable fonts that don't have the exaggerated jagged edges
inherent in bitmap scaling.

The best thing about the Amiga's font scaling is that its addition to the
system is completely invisible to an application program.  Because the
diskfont.library takes care of all the font scaling, any program that uses
OpenDiskFont() to open a font can have scalable fonts available to it.
For simple scaling, the programming interface is the same using Release
2.0 as it was under 1.3.

However, there is one feature of the 2.0 diskfont.library that the 1.3
programming interface cannot handle.  When scaling a font (either from an
outline or from another bitmap), the 2.0 diskfont.library can adjust the
width of a font's glyphs according to an aspect ratio passed to
OpenDiskFont().  A font glyph is the graphical representations associated
with each symbol or character of a font.

The aspect ratio refers to the shape of the pixels that make up the bitmap
that diskfont.library creates when it scales a font.  This ratio is the
width of a pixel to the height of the pixel (XWidth/YWidth).  The
diskfont.library uses this ratio to figure out how wide to make the font
glyphs so that the look of a font's glyphs will be the same on display
modes with very different aspect ratios.  For more information on Amiga
aspect ratios,  see Carolyn Scheppner's article, ``Finding the Aspect
Ratio'', from the September/October 1991 issue of Amiga Mail.

To add this new feature, several changes to the OS were necessary:

    1) The OS needed to be able to store an aspect ratio for any font
       loaded into the system list,

    2) The structures that diskfont.library uses to store bitmap fonts on
       disk had to be updated so they can store the aspect ratio a font
       was designed for, and,

    3) The way in which an application requests fonts from
       diskfont.library had to be altered so that an application could
       askfor a specific aspect ratio.

For the diskfont.library to be able to scale a font to a new aspect ratio,
it needs to know what the font's current aspect ratio is.  The Amiga gets
the aspect ratio of a font currently in the system list from an extension
to the TextFont structure called (oddly enough) TextFontExtension.  Under
2.0, when the system opens a new font (and there is sufficient memory), it
creates this extension.

A font's TextFont structure contains a pointer to its associated
TextFontExtension.  While the font is opened, the TextFont's
tf_Message.mn_ReplyPort field points to a font's TextFontExtension.  The
<graphics/text.h> include file #defines tf_Message.mn_ReplyPort as
tf_Extension.

The TextFontExtension structure contains only one field of interest: a
pointer to a tag list associated with this font:

    struct TagItem *tfe_Tags;   /* Text Tags for the font */

If a font has an aspect ratio associated with it, the OS stores the aspect
ratio as a tag/value pair in the tfe_Tags tag list.

The TA_DeviceDPI tag holds a font's aspect ratio.  The data portion of the
TA_DeviceDPI tag contains an X DPI (dots per inch) value in its upper word
and a Y DPI value in its lower word.  These values are unsigned words
(UWORD).  At present, these values do not necessarily reflect the font's
true X and Y DPI, so their specific values are not relevant.  At present,
only the ratio of the X aspect to the Y aspect is important (more on this
later in the article).

Notice that the X and Y DPI values are not aspect values.  The X and Y aspect
values are the reciprocals of the X and Y DPI values, respectively:

    XDPI = 1/XAspect
    YDPI = 1/YAspect

so, the aspect ratio is YDPI/XDPI, not XDPI/YDPI.

Before accessing the tag list, an application should make sure that this
font has a corresponding TextFontExtension.  The ExtendFont() function
will return a value of TRUE if this font already has an extension or
ExtendFont() was able to create an extension for this font.

 Where Do the X and Y DPI values Come From?
 Some Things to Look Out For


Where Do the X and Y DPI values Come From?

The Amiga has a place to store a font's X and Y DPI values once the font
is loaded into memory, but where do these X and Y values come from?  A
font's X and Y DPI values can come from several sources.  The X and YDPI
can come from a font's disk-based representation, or it can be set by the
programmer.

For the traditional Amiga bitmap fonts, in order to store the X and Y DPI
values in a bitmap font's .font file, the structures that make up the
.font file had to be expanded slightly.  There are two changes from the
structures described in the ``Graphics:Text'' chapter of the RKM:
Libraries and Devices manual.  The first is that the fch_FileID in the
FontContentsHeader structure (essentially, the .font file) contains a
different file ID (TFCH_ID from <libraries/diskfont.h>) from the
traditional .font file.  This tells the diskfont.library that this
FontContentsHeader uses a special kind of FontContents structure called a
TFontContents structure.  The difference between these structures is that
the TFontContents structure allows the OS to store tag value pairs in the
extra space set aside for the font's name.

    struct TFontContents {
        char    tfc_FileName[MAXFONTPATH-2];
        UWORD   tfc_TagCount;       /* including the TAG_DONE tag */
        /*
         * if tfc_TagCount is non-zero, tfc_FileName is overlayed with
         * Text Tags starting at:  (struct TagItem *)
         * &tfc_FileName[MAXFONTPATH-(tfc_TagCount*sizeof(struct TagItem))]
         */
        UWORD   tfc_YSize;
        UBYTE   tfc_Style;
        UBYTE   tfc_Flags;
    };

Currently, out of all the system standard bitmap fonts (ones loaded from
bitmaps on disk or ROM, not scaled from a bitmap or outline), only one has
a built in aspect ratio: Topaz-9.

For the Compugraphic outline fonts, the X and Y DPI values are built into
the font outline.  Because the format of the Compugraphic outline fonts is
proprietary, information about their layout is available only from
AGFA/Compugraphic.  For most people, the format of the outline fonts is
not important, as the diskfont.library handles converting the fonts to an
Amiga-usable form.

The other place where a font can get an aspect ratio is an application.
When an application opens a font with OpenDiskFont(), it can supply the
TA_DeviceDPI tag that the diskfont.library uses to scale (if necessary)
the font according to the aspect ratio.  To do so, an application has to
pass OpenDiskFont() an extended version of the TextAttr structure called
the TTextAttr:

    struct TTextAttr {
        STRPTR  tta_Name;           /* name of the font */
        UWORD   tta_YSize;          /* height of the font */
        UBYTE   tta_Style;          /* intrinsic font style */
        UBYTE   tta_Flags;          /* font preferences and flags */
        struct TagItem *tta_Tags;   /* extended attributes */
    };

The TextAttr and the TTextAttr are identical except that the tta_Tags
field points to a tag list where you place your TA_DeviceDPI tag.  To tell
OpenDiskFont() that it has a TTextAttr structure rather than a TextAttr
structure, set the FSF_TAGGED bit in the tta_Style field.

For example, to ask for Topaz-9 scaled to an aspect ratio of 75 to 50, the
code might look something like this:

...

#define MYXDPI (75L << 16)
#define MYYDPI (50L)

struct TTextAttr mytta = {
   "topaz.font",
   9,
   FSF_TAGGED,
   0L,
   NULL
};

struct TagItem tagitem[2];
struct TextFont *myfont;
ULONG dpivalue;
struct Library *UtilityBase, *DiskfontBase, *GfxBase;
void main(void)
{
   tagitem[0].ti_Tag = TA_DeviceDPI;
   tagitem[0].ti_Data = MYXDPI | MYYDPI;
   tagitem[1].ti_Tag = TAG_END;

...
     if (myfont = OpenDiskFont(&mytta))
     {
        dpivalue = GetTagData(TA_DeviceDPI,
           0L,
           ((struct TextFontExtension *)(myfont->tf_Extension))->tfe_Tags);
        if (dpivalue) printf("XDPI = %d    YDPI = %d\n",
                        ((dpivalue & 0xFFFF0000)>>16),
                        (dpivalue & 0x0000FFFF));
        /* blah, blah, render some text, blah, blah */
        ...

       CloseFont(myfont);
   }
...

}

From  FTA.c


Some Things to Look Out For

One misleading thing about the TA_DeviceDPI tag is that its name implies
that the diskfont.library is going to scale the font glyphs according to
an actual DPI (dots per inch) value.  As far as scaling is concerned, this
tag serves only as a way to specify the aspect ratio, so the actual values
of the X and Y elements are not important, just the ratio of one to the
other.  A font glyph will look the same if the ratio is 2:1 or 200:100 as
these two ratios are equal.

To makes things a little more complicated, when diskfont.library scales a
bitmap font using an aspect ratio, the X and Y DPI values that the OS
stores in the font's TextFontExtension are identical to the X and Y DPI
values passed in the TA_DeviceDPI tag.  This means the system can
associate an X and Y DPI value to an open font size that is very different
from the font size's actual X and Y DPI.  For this reason, applications
should not use these values as real DPI values.  Instead, only use them to
calculate a ratio. For the Compugraphic outline fonts, things are a little
different.  The X and Y DPI values are built into the font outline and
reflect a true X and Y DPI. When the diskfont.library creates a font from
an outline, scaling it according to an application-supplied aspect ratio,
diskfont.library does not change the YDPI setting.  Instead, it calculates
a new XDPI based on the font's YDPI value and the aspect ratio passed in
the TA_DeviceDPI tag.  It does this because the Amiga thinks of a font
size as being a height in pixels.  If an application was able to change
the true Y DPI of a font, the diskfont.library would end up creating font
sizes that were much larger or smaller than the YSize the application
asked for.  If an application needs to scale a font according to height as
well as width, the application can adjust the value of the YSize it asks
for in the TTextAttr.

As mentioned earlier, almost all of the system standard bitmap fonts do
not have a built in aspect ratio.  This means that if an application loads
one of these bitmap fonts without supplying an aspect ratio, the system
will not put a TA_DeviceDPI tag in the font's TextFontExtension: the font
will not have an aspect ratio.  If a font size that is already in the
system font list does not have an associated X and Y DPI, the
diskfont.library cannot create a new font of the same size with a
different aspect ratio.  The reason for this is the diskfont.library
cannot tell the difference between two instances of the same font size
where one has an aspect ratio and the other does not.  Because
diskfont.library cannot see this difference, when an application asks, for
example, for Topaz-8 with an aspect ratio of 2:1, OpenDiskFont() first
looks through the system list to see if that font is loaded.
OpenDiskFont() happens to find the ROM font Topaz-8 in the system font
list, which has no X and Y DPI.  Because it cannot see the difference,
diskfont.library thinks it has found what it was looking for, so it does
not create a new Topaz-8 with an aspect ratio of 2:1, and instead opens
the Topaz-8 with no aspect ratio.

This also causes problems for programs that do not ask for a specific
aspect ratio.  When an application asks for a font size without specifying
an aspect ratio, OpenDiskFont() will not consider the aspect ratios of
fonts in the system font list when it is looking for a matching font.  If
a font of the same font and style is already in the system font list, even
though it may have a wildly distorted aspect ratio, OpenDiskFont() will
return the font already in the system rather than creating a new one.

Due to a bug in the 2.00 through 2.04 versions of the graphics.library
function WeighTAMatch(), the OS ignores the aspect ratio of a font when
trying to determine if the TTextAttr passed to OpenDiskFont() matches a
font already in the system font list.  If an application asks for a font
that exactly matches a font already in the font list in all ways except in
aspect ratio, OpenDiskFont() will open the font in the system font list
rather than creating a font with a matching aspect ratio.  For example, if
an application requests CGTimes-20 with an aspect ratio of 1:2 and while
scanning through the system font list OpenDiskFont() finds CGtimes-20 with
an aspect ratio of 1:1, OpenDiskFont() will open the font with a 1:1
aspect ratio.  A patch that temporarily fixes this bug, SetPatchWTAM, is
on the Denver/Milano DevCon disks.

The following example, cliptext.c, renders the contents of a text file to
a Workbench window.  This example gets the new aspect ratio for a font by
asking the display database what the aspect ratio of the current display
mode is.


V-23: Using Compugraphic Typefaces with Bullet

by John Orr

One of the improvements made to the Amiga's operating system for
Workbench Release 2.1 is programmatic control of AGFA's IntelliFontÒ
scaling engine.  With this engine, application programs can fully
utilize Compugraphic (CG) typefaces installed by Fountain (the CG
typeface install that comes with 2.04 and 2.1).  Some of the features
that the font scaling engine offers include:

    * Rasterization of a typeface to arbitrary vertical and horizontal
      resolutions.

    * Baseline rotation of glyphs to an arbitrary angle.

    * Glyph shearing (italicizing) to any angle from -45 to 45 degrees
      (inclusive).

    * Access to kerning tables.

    * Algorithmic emboldening.

 Starting the Engine      Width Lists      Other Level 0 Tags
 Rasterizing a Glyph      Rotating         The Otag File Tags
 Kerning                  Shearing         About the Examples

 Engine.c


Starting the Engine

There are several steps involved in using a font outline on the Amiga.

Step 1. Open the font contents file (the ".font" file) and verify that
        it has a corresponding outline tag file (an ".otag" file).

Step 2. Open the otag file, verify that it is valid, load its tag list
        into memory, and resolve any memory indirections in the tag list.

Step 3. Find out the name of the typeface's scaling engine and obtain a
        pointer to the engine's GlyphEngine structure.

Step 4. Tell the engine which typeface to use.

Step 5. Set other scaling engine parameters.


Step 1

All system supported fonts on the Amiga have a font contents file.
From this file, an application can determine a font's type, so the
application knows how to utilize the font.  The font contents file is
a FontContentsHeader structure (defined in <diskfont/diskfont.h>).
The first field of that structure (fch_FileID) contains an ID
identifying the font's type.  If that type is OTAG_ID (0x0F03), the
font is an outline and it should have a corresponding otag file.  The
otag file should be in the same directory as the font contents file.


Step 2

The otag file contains a tag list that describes the typeface.  All
of these tags are defined in <diskfont/diskfonttag.h> as either level
1, level 2, or level 3 outline tags.  Level 1 tags are required to be
present in an otag file.  Level 2 and 3 tags are optional.  See the
include file for more information on the tag levels.

The first tag of the otag file is always OT_FileIdent.  Its value is
the size of the otag file.  This tag is here to verify the validity
of the otag file.  If the first tag is not OT_FileIdent, or the
OT_FileIdent tag value is not the size of the otag file, the otag
file is invalid, so don't attempt to use it.  If the file is valid,
copy the entire file into a buffer.

The tags from the otag file have a special OT_Indirect bit.  If this
bit is set, the tag's value is an indirect reference to data defined
elsewhere in the otag file.  The tag's value is the offset to the
data (in bytes) from the beginning of the otag file.  For example,
the otag file fonts:CGTimes.otag that is on the 2.04 Release disks
contains the tag OT_Family (0x80009003), which has its OT_Indirect
bit set.  The value of the OT_Family tag is 195, meaning that the
data for it--the NULL terminated string ``CG Times''--is located 195
bytes into the otag file.

Of course, if an application read the file fonts:CGTimes.otag into a
memory buffer, the ``CG Times'' string would be 195 bytes from the
beginning of the buffer.  The OT_Family tag must point to the
absolute address of its data, so when an application loads an otag
file into memory, it has to resolve the indirection of the
OT_Indirect tags in memory.  The application can do this by adding
the buffer address to each OT_Indirect tag value.


Step 3

One of the level 1 outline tags is the OT_Engine tag.  This tag
refers to the name of this typeface's scaling engine.  At present
there is only one scaling engine available on the Amiga.  It is named
Bullet.  This is the IntelliFont scaling engine.  The name is left
over from the original implementation of the IntelliFont engine used
on the Amiga.  The scaling engine itself is in its own Exec library,
called bullet.library.  To open the engine, build a complete library
name by adding the string ".library" to the OT_Engine string, and
open it with OpenLibrary().  Don't assume that OT_Engine will always
be the string ``bullet''.  In the future, Commodore or some third
party developer may create additional scaling engines libraries that
will allow the Amiga to use other types of outline typefaces
(PostScript, Nimbus-Q, etc.).  Using the proper library name will
help ensure compatibility with future possible scaling engines.

All scaling engine libraries contain several functions:

OpenEngine()                  If successful, returns a pointer to
                               the library's GlyphEngine structure.
CloseEngine()                 Releases the GlyphEngine structure
                               obtained in OpenEngine().
SetInfo()/SetInfoA()          Sets current parameters of a scaling
                               engine (the current typeface, the
                               current point size, the current output
                               resolution, etc.)
ObtainInfo()/ObtainInfoA()    Queries a scaling engine for glyph
                               information (a glyph's bitmap, the
                               kerning value between two glyphs, etc.).
ReleaseInfo()/ReleaseInfoA()  Releases data obtained with
                               ObtainInfo()/ObtainInfoA().

To obtain a pointer to a GlyphEngine structure for a particular
scaling library, use that library's OpenEngine() routine.  The
function takes no arguments.


Step 4

Setting a scaling engine's current typeface involves the SetInfoA()
(or SetInfo()) function and the Level 0 tags from
<diskfont/diskfonttag.h>.  The SetInfoA() function takes two
parameters, a pointer to the GlyphEngine structure, and a tag list of
level 0 outline tags.  The Level 0 tags act as commands for a scaling
engine, some of which are for setting scaling engine parameters (with
SetInfo() or SetInfoA()), and some of which are for querying
information from a scaling engine (with ObtainInfo() or
ObtainInfoA()).

Two tags set a scaling engine's current typeface: OT_OTagPath and
OT_TagList.  The OT_OTagPath tag points to the full path name of a
typeface's otag file (for example, fonts:CGTimes.otag).  The
OT_OTagList tag points to the tag list created in step 2 above.


Step 5

There are three other parameters the scaling engine needs in order
answer queries for information:

   OT_DeviceDPI            OT_PointHeight          OT_GlyphCode

The OT_DeviceDPI tag refers to the resolution of the output device.
The tag value's high word is the horizontal resolution and the low
word is the vertical resolution.  Both are unsigned words measured in
dots per inch.

The OT_PointHeight tag refers to the height of a typeface in points.
One point is approximately equal to 1/72 of an inch
(AGFA/Compugraphic defines the point to be 0.01383 inches).  For CG
typefaces, this height is the distance between baselines from one
line to the next (without any leading adjustments).  The point height
is represented as a fixed point, two's complement binary number, with
the point situated in the middle of a long word.  This means the
lower word is the fractional portion and the upper word the whole
number portion (the number covers the powers of two from 215 through
2-16).

For those who may not know, a two's complement number is a way of
representing negative numbers.  To find the two's complement of a
negative number, find the one's complement of the absolute value of
that number (change all the binary ones to zeros and all the zeros to
ones) and then add one to the result.  To change from two's
complement, subtract one from the two's complement number and find
the one's complement of the number.  For example,

Before conversion to two's complement, the absolute value of the one
byte decimal quantity -32 is represented as:

    In binary         0010 0000  ($20)
    One's complement  1101 1111  ($DF)
    Add One           0000 0001  ($01)
    -----------------------------------
    Two's complement  1110 0000  ($E0)

So the number -32 is encoded as 1110 0000 or 0xE0 in hex.  Notice
that the high bit (the sign bit) of the encoded number is set if the
number is negative.  If the number is zero or greater, the high bit
is clear.  This procedure is independent of where the ``point'' is in
the negative number (the ``point'' in this case is the divider
between the whole portion of the number and the fractional portion).
When the computer adds one to the one's complement, it does not
consider where the ``point'' is in the one's complement, the computer
just treats the one's complement value as a whole integer.  For
example, to encode the decimal quantity -531/256 as a two byte, fixed
point, two's complement binary number where the point is situated in
the middle of the two bytes:

531/256 = -(2 + 19/256) = -2.13 in hex

In binary           0000 0010.0001 0011   ($02.13 in hex, with the point)

One's complement    1111 1101 1110 1100   ($FDEC  in hex ignore the point
                                                  from now on)
Add One             0000 0000 0000 0001   ($0001)
----------------------------------------
Two's complement    1111 1101 1110 1101   ($FDED)

Notice that the one added to the one's complement is in the 2-8 (=
1/256) column.

The OT_GlyphCode tag refers to the current glyph.  When an
application asks the scaling engine to rasterize a glyph, this is the
glyph the engine renders.  The scaling engine uses Unicode encoding
to represent glyphs.  Unicode is an international character encoding
standard that encompasses many of the world's national scripts in a
16-bit code space.  Conveniently, the Amiga's Latin-1, 8-bit
character set corresponds to the same glyphs as the Unicode standard.
To set the current glyph to a character from the Amiga character set,
use the same Latin-1 code, but pad it out to a 16-bit value.

Because the Compugraphic typefaces use their own character set, the
scaling engine in the bullet.library has to map the Unicode glyph
codes to Compugraphic glyph codes.  Note that the Unicode standard
encompasses many more glyphs than just the Latin-1 character set or
the Compugraphic character set, so many of the characters in the
Unicode set do not map to any glyphs in the Compugraphic set.  For
example, Unicode includes several Asian ideogram sets, that the
Compugraphic set does not.  The result is the vast majority of the
Unicode characters are not available using Compugraphic typefaces.
The Compugraphic character set covers roughly 400 glyphs.  For more
information on the UniCode standard, see the Unicode Consortium's
book The Unicode Standard, Worldwide Character Encoding published by
Addison-Wesley (ISBN 0-201-56788-1).


Rasterizing a Glyph

Once an application has set up the scaling engine, obtaining a glyph
is a matter of asking for it.  As was mentioned earlier, the
ObtainInfoA()/ObtainInfo() function queries a scaling engine for
glyph information.  This function accepts a pointer to a GlyphEngine
structure and a tag list.  To ask for a rasterization of a glyph,
pass ObtainInfo() the OT_GlyphMap tag.  The engine expects the
OT_GlyphMap value to be an address where it can place the address of
a GlyphMap structure.  The GlyphMap structure (defined in
<diskfont/glyph.h>) is for reading only and looks like this:

struct GlyphMap {
    UWORD  glm_BMModulo;    /* # of bytes in row: always multiple of 4 */
    UWORD  glm_BMRows;      /* # of rows in bitmap */
    UWORD  glm_BlackLeft;   /* # of blank pixel columns at left of */
                            /* glyph */
    UWORD  glm_BlackTop;    /* # of blank rows at top of glyph */
    UWORD  glm_BlackWidth;  /* span of non-blank columns (horizontal */
                            /* span of the glyph) */
    UWORD  glm_BlackHeight; /* span of non-blank rows (vertical span of */
                            /* the glyph) */
    FIXED  glm_XOrigin;     /* distance from upper left corner of */
                            /* bitmap to lower */
    FIXED  glm_YOrigin;     /* left of glyph (baseline), in fractional */
                            /* pixels */
    WORD   glm_X0;          /* approximation of XOrigin in whole pixels */
    WORD   glm_Y0;          /* approximation of YOrigin in whole pixels */
    WORD   glm_X1;          /* approximation of XOrigin + Width */
    WORD   glm_Y1;          /* approximation of YOrigin + Width */
    FIXED  glm_Width;       /* character advance, as fraction of em */
                            /* width */
    UBYTE *glm_BitMap;      /* actual glyph bitmap */
};

The glm_BitMap field points to a single bitplane bitmap of the glyph.
This bitmap is not necessarily in Chip RAM, so if an application
needs to use the blitter to render the glyph, it has to copy the
bitmap to a Chip RAM buffer.  The fields glm_BMModulo and glm_BMRows
are the dimensions of the whole bitmap.  The glyph itself does not
occupy the entire bitmap area.  The fields glm_BlackLeft,
glm_BlackTop, glm_BlackWidth, and glm_BlackHeight describe the
position and dimension of the glyph within the bitmap.  The fields
glm_XOrigin and glm_YOrigin are the X and Y offsets from the bitmap's
upper left corner to the glyph's lower left corner.  The lower left
corner lies on the glyph's baseline.  These X and Y offsets are in
fractional pixels.  The fields glm_X0 and glm_Y0 are rounded versions
of glm_XOrigin and glm_YOrigin, respectively.

The glm_Width field is a measure of the width of the glyph in
fractions of an em (pronounced like the letter 'M').  This value is a
fixed point binary fraction.  The em is a relative measurement.  A
distance of one em is equal to the point size of the typeface.  For
example, in a 36 point typeface, one em equals 36 points which is
approximately equal to a half inch.  For a 72 point typeface, one em
equals 72 points which is approximately equal to one inch.

When an application is finished with the GlyphMap structure, it must
use the ReleaseInfoA() or ReleaseInfo() function to relinquish the
GlyphMap structure.  This function uses the same format as
ObtainInfoA()/ObtainInfo(), except the data value of the OT_GlyphMap
tag is a pointer to the GlyphMap structure (rather than a pointer to
a pointer).


Kerning

The IntelliFont scaling engine also supports two types of kerning.
One type of kerning is called text kerning, which is for regular
bodies of text.  The other type of kerning is called design kerning,
which is for more obvious displays, like headlines.  The basic
difference is that design kerning is generally more tightly spaced
than text kerning.

Before asking for a kerning pair, an application has to tell the
engine which character pair to kern.  It does this using one of the
SetInfo() functions to set the primary glyph, OT_GlyphCode, and the
secondary glyph code, OT_GlyphCode2.

To ask the scaling engine for a kerning value, use one of the
ObtainInfo() functions with the OT_TextKernPair (for text kerning) or
OT_DesignKernPair (for design kerning) tags.  The engine expects the
value of the kerning tag to be an address where it can store a four
byte long kerning value.  The kerning value is a fixed point binary
fraction of an em square (like the glm_Width field from the GlyphMap
structure).  This value is the distance to remove from the primary
character advance (the glm_Width of OT_GlyphCode) when rendering the
secondary glyph (OT_GlyphCode2) immediately following the primary
glyph.

Unlike other ObtainInfo() tags, the scaling engine does not allocate
any resources when answering queries about kerning values.
Applications do not have to use ReleaseInfo() functions for kerning
queries made with either OT_TextKernPair or OT_DesignKernPair.


Width Lists

An application can find the widths of a typeface's glyphs using the
OT_WidthList tag with one of the ObtainInfo() functions.  The engine
expects the OT_WidthList value to be an address where it can place
the address of a MinList structure.  This MinList points to a list of
GlyphWidthEntry structures.  The GlyphWidthEntry structure (defined
in <diskfont/glyph.h>) is for reading only and looks like this:

struct GlyphWidthEntry {
    struct MinNode gwe_Node;  /* on list returned by OT_WidthList */
                              /* inquiry */
    UWORD          gwe_Code;  /* entry's character code value */
    FIXED          gwe_Width; /* character advance, as fraction of */
                              /* em width */
};

The MinList contains an entry for each valid Unicode glyph ranging
from the primary glyph, OT_GlyphCode, through the secondary glyph,
OT_GlyphCode2.  The engine does not create a GlyphWidthEntry
structure for codes without glyphs (for example the codes before the
space character in the Latin-1 character set).

When an application is finished with the width list, it must use one
of the ReleaseInfo() functions to relinquish the list.  This function
uses the same format as the ObtainInfo() functions, except the data
value of the OT_WidthList tag is a pointer to the MinList (rather
than a pointer to a pointer).  The primary and secondary code values
do not have to remain constant while an application is using a width
list.  The engine deallocates the width list resources independently
of the primary and secondary code values, so these can change after
obtaining a width list.

The following code fragment asks the scaling engine, ge, for a list
of character widths of the Unicode glyphs ranging from unicode
(OT_GlyphCode) to unicode2 (OT_GlyphCode2), inclusive.  The fragment
steps through the list of widths, printing each one.

struct MinList *widthlist;
struct GlyphWidthEntry *widthentry;
.  .  .

if (SetInfo(ge,
            OT_GlyphCode,   unicode,
            OT_GlyphCode2,  unicode2,
            TAG_END) == OTERR_Success)
{
    if (ObtainInfo(ge, OT_WidthList, &widthlist, TAG_END) == OTERR_Success)
    {
        for (widthentry = (struct GlyphWidthEntry *) widthlist->mlh_Head;
            widthentry->gwe_Node.mln_Succ;
            widthentry = (struct GlyphWidthEntry *)
            widthentry->gwe_Node.mln_Succ)
        {
            printf("$%lx: %ld.%ld\n",
                widthentry->gwe_Code,
                widthentry->gwe_Width>>16,
                ((widthentry->gwe_Width&0xffff)*10000)>>16);
        }
        ReleaseInfo(ge, OT_WidthList, widthlist, TAG_END);
    }
}
.  .  .

Notice that the ObtainInfo() functions (as well as the SetInfo()
functions) return an error code (the error codes are defined in
<diskfont/oterrors.h>).  If that error code is equal to
OTERR_Success, the operation was successful.


Rotating

Taking advantage of other features of the Bullet library is a matter
of setting other engine parameters using one of the SetInfo()
functions with some other level 0 tags.  One interesting feature of
the IntelliFont engine is its ability to rotate glyphs.  By setting
the OT_RotateSin and OT_RotateCos values, the IntelliFont engine can
rotate a glyph's baseline from the glyph origin (the glm_XOrigin and
glm_YOrigin from the GlyphMap structure).

The OT_RotateSin and OT_RotateCos are, respectively, the sine and
cosine of the baseline rotation angle.  The engine can rotate to any
angle.  The sine and cosine must correspond to the same angle and
must be in the sine and cosine value range (0 through 1 inclusive).
The engine does not do any error checking on the sine and cosine
values.  As a result, the engine will yield strange results if the
sine and cosine are from very different angles or if these values are
out of range for sines and cosines (greater than 1).  By default, the
engine sets these values to 0.0 and 1.0, the sine and cosine of 0
degrees.  These values are encoded as fixed point binary fractions
(the negative values are two's complement).

When setting the baseline rotation, an application must set both the
sine and cosine.  It must set OT_RotateSin first, then OT_RotateCos.
An application can set both values in the same SetInfo() function,
but the sine must come first.  For example, to set the rotation angle
to 150 degrees:

The sine of 150 degrees is 0.5 which is 0x00008000 in hex.  The
cosine of 150 degrees is approximately -0.866 which is approximately
0xffff224c in hex (two's complement), so:

.  .  .

if (SetInfo(ge,
       OT_RotateSin, 0x8000,
       OT_RotateCos, 0xFFFF224C,
       TAG_END) == OTERR_Success) /* If SetInfo() returns OTERR_Success, */
                                  /* it worked OK. */
{   /* The baseline rotation has been set, now the application can */
    /* render it. */

    .  .  .


Shearing

Like baseline rotation, glyph shearing (also known as italicizing) is
a matter of setting some Level 0 tags.  The shearing tags,
OT_ShearSin and OT_ShearCos, specify the shearing angle, or the angle
at which the typeface is italicized.  This angle refers to the angle
that results from rotating the vertical axis clockwise.  The angle
can range from -45 to 45 degrees (inclusive).  Like the rotation
angle, the shearing angle is represented as a sine and cosine value
that must correspond to the same angle and must fall into normal
bounds for sine and cosine values.  Also like the rotation angle sine
and cosine tags, an application must set both the OT_ShearSin and
OT_ShearCos tags, in that order.  By default, the shearing value is
zero degrees meaning there is no shearing (OT_ShearSin = 0x00000000,
OT_ShearCos = 0x00010000).


Other Level 0 Tags

There are several other Level 0 tags:

OT_DotSize
----------
This tag specifies the X and Y size of the target device's dots.  The
X and Y DPI imply a dot size.  For example, at 300 X and 300 Y DPI,
the resolution implied dot size is 1/300 inches by 1/300 inches.  For
some devices (like some dot matrix printers), the size of the output
dot does not match its resolution implied size.  To a degree, the
IntelliFont engine can account for this.  The dot size is represented
as a percentage of the dot's resolution implied size.  The X
percentage is in the tag value's upper word, and the Y percentage is
in the tag value's lower word.

OT_SetFactor
------------
This tag distorts the width of a typeface by changing the width of
the em square.  The scaling engine changes the em width to this tag's
value.  The value is a fixed point binary fraction.

OT_EmboldenX/OT_EmboldenY
-------------------------
These tags specify the algorithmic emboldening factor in the X and Y
direction, respectively.  The tag values are fixed point two's
complement binary numbers.  The units are measured in ems.
Emboldening values above zero embolden the typeface.  Emboldening
values below zero lighten the typeface.  By default, both values are
zero.

OT_GlyphWidth
-------------
This tag's value specifies a width for the current typeface.  It is a
fraction of an em represented as a fixed point binary number.  If
this value is set to something besides 0.0, all glyphs will have this
width.  To turn off the constant width, set OT_GlyphMap back to 0.0
(its default value).


The Otag File Tags

The Outline Tag (otag) file contains a number of tags that describe a
font outline to the Diskfont library.  The purpose of most of these
tags is to allow Diskfont to attribute styles to a typeface when
loading a font outline as a standard Amiga system font.  Most
applications that use the scaling engine will not need to worry about
the meaning of the majority of these tags, but they are described
below.  The following tags are Level 1 tags and must be present in
every otag file:

OT_FileIdent
------------
Every valid otag file starts with this tag.  Its value is the size of
the file.  It doesn't really have anything to do with the definition
of the typeface, but it does serve as a way to check the validity of
the otag file.

OT_Engine
---------
This tag's value points to a string naming the font scaling engine.
For example, the OT_Engine tag in fonts:CGTimes.otag is ``bullet''.

OT_Family
---------
This tag's value points to a string naming the typefaces font family.
For example, the OT_Family in fonts:CGTimes.otag is ``bullet''.

OT_SymbolSet
------------
This tag's value is a two byte ASCII code for this typeface's symbol
set.  This tells the system which symbol set to use to map the Amiga
character set to the Compugraphic character set. The symbol set for
most CG fonts designed for use with the Amiga is ``L1'', which stands
for Latin1.  The exception is the CG fonts from Gold Disk, Inc.  They
use the ``GD'' (Gold Disk) symbol set.

OT_YSizeFactor
--------------
For traditional Amiga fonts, the font size does not include any
spacing on top or bottom of the typeface--the Amiga doesn't consider
it part of the font.  CG fonts include spacing on the top and bottom
of their typefaces.  This tag's value is a ratio of the point height
of a typeface to its ``black'' height (the point height minus the
space on the typeface's top and bottom).  The high word is the point
height factor and the low word is the black height factor.  Note that
these values form a ratio.  Individually, they do not necessarily
reflect any useful value.

OT_SerifFlag
------------
If this tag's value is TRUE, this typeface has serifs.

OT_StemWeight
-------------
This tag's value can be anywhere from 0 through 255 and indicates a
nominal weight or ``boldness'' to the typeface.  The
<diskfont/diskfonttag.h> include file defines a set of ratings for
this tag's value.  See that file for more details.  When the Diskfont
library opens an outline font, it uses this value to determine if a
typeface is bold.

OT_SlantStyle
-------------
The <diskfont/diskfonttag.h> include file defines a set of three
possible values for this tag's value.  See that file for more
details.  When the Diskfont library opens an outline font, it uses
this value to determine if a typeface is italicized/obliqued.

OT_HorizStyle
-------------
This tag's value can be anywhere from 0 through 255 and indicates a
nominal width rating to the typeface.  The <diskfont/diskfonttag.h>
include file defines a set of ratings for this tag's value.  See that
file for more details.  When the Diskfont library opens an outline
font, it uses this value to determine if a typeface is extended.

OT_AvailSizes
-------------
This tag's value points to a sorted list of UWORDs. The first UWORD
is the number of entries in the sorted list.  The remaining UWORDs
are the font sizes that the Diskfont library lists when calling
AvailFonts().

OT_SpecCount
------------
This tag's value is a number of spec tags that follow it.  A spec tag
is private to the scaling engine.

The following are Level 2 tags.  They may also be in an otag file but
are not required:

OT_BName
--------
This tag points to a string naming the bold variant of this typeface.
For example, the fonts:CGTimes.otag file lists ``CGTimesBold'' as its
bold variant.

OT_IName
--------
This tag points to a string naming the italic variant of this
typeface.

OT_BIName
---------
This tag points to a string naming the bold italic variant of this
typeface.

OT_SpaceWidth
-------------
This tag's value is the width of the space character at 250 points
(where there are 72.307 points in an inch).  The width is in Design
Window Units (DWUs).  One DWU is equal to 1/2540 inches. To convert
to X pixels:

    OT_SpaceWidth   pointsize
    ------------- * --------- *  XDPI = spacewidth in pixels (X dots)
        2540           250

OT_IsFixed
----------
If this tag's value is TRUE, every glyph in this
typeface has the same character advance (a fixed width).

OT_InhibitAlgoStyle
-------------------
This tag's value is a bitmask that is compatible with the ta_Style
field of the TextAttr structure (defined in <graphics/text.h>).  This
tag tells which styles cannot be added to a typeface algorithmically.
For example, if the FSF_BOLD bit in OT_InhibitAlgoStyle is set and a
user asks for a bold version of the typeface, the diskfont.library
(or an application) can add that style algorithmically.

At present there are no Level 3 tags.


About the Examples

This article contains two code examples.  The first, Rotate.c, rotates
a user-specified glyph around a central point.  By default, it
rotates a 36 point 'A' using the font fonts:CGTimes.font.  If Rotate
finds an AmigaDOS environment variable called "XYDPI", it will use
the X and Y DPI it finds in that variable as the default target
device DPI (see the description of the Level 0 OT_DeviceDPI tag).  If
that variable is not defined, Rotate will use an XDPI of 68 and a
YDPI of 27 which, nominally, is the X and Y DPI of a standard Hires
display.

The second example, View.c, displays a file using the same defaults as
Rotate.  View utilizes kerning pairs to display its glyphs.  Because
View only considers "visible" characters, it ignores characters
that have widths but no glyph.  The result is, View doesn't print any
space characters.  If View were smarter, it would ask the scaling
engine for a width list so it could properly advance the current
pointer when it comes across a space or some other character without
a glyph.

Notice that View uses a slightly modified version of BulletMain.c
called BulletMainFile.c.  Only BulletMain.c appears in the example
code.  The only significant difference between the two is that
BulletMainFile.c obtains a file name for View to display.


V-39: Naming Graphics Display Modes

Naming Graphics Display Modes

by Martin Taillefer

The graphics.library database contains a list of all available display modes
on any given Amiga. Each mode has a given set of attributes, including
possibly a name. Only a subset of the available modes in the system have
names. The other modes are less significant and don't have names directly
associated with them.

When showing a list of available modes to the user, unnamed modes become a
problem. How should they be presented to the user? A simple solution is to
dynamically construct names for unnamed modes. The name construction can be
based on a mode's attributes, resulting in a descriptive name for the mode.

The NameMode() routine in the program below accepts a graphics.library mode
id, and a string buffer, and fills-in the string buffer with the name of the
given mode. If the mode has a real name entry in the graphics database, that
name is returned. If there is no real name entry, a name is constructed for
the mode based on the mode's properties. A routine very similar to this is
present in the ASL screen mode requester, and in the ScreenMode prefs editor.

The following program outputs the names of all current graphics database modes
to the console.

 NameMode.c


VI-1: Creating Virtual Voices with Amiga Audio

Creating Virtual Voices with Amiga Audio

by Dan Baker

Every Amiga model comes standard with 4-channel, 8-bit stereo audio
hardware.  This hardware provides every application with the capability
of producing 4-part, stereo sound.  Some applications however may want
to exceed the 4-channel limit.  For games and other applications that
use sound effects extensively, it may be desirable to trigger more than
4 sounds simultaneously.  This article demonstrates two techniques you
can use to implement virtual voices on the Amiga's audio hardware
effectively doubling the number of voices available to 8.

Audio Hardware Limits

Using DMA, the audio hardware can fetch about 2 bytes per scan line for
each channel without processor intervention.  This means that each
audio channel can play back sampled data at up to 28,867 bytes per
second.  It turns out that this 28,867 byte per second limit far
exceeds the requirements of most audio sample files.

The typical 8SVX file contains data sampled at a rate of about 10,000
bytes per second.  In that case, the audio hardware only uses about 1/3
of the available audio bandwidth.  The audio hardware is capable of
fetching much more sound data without affecting system performance.
The question then arises, can this extra horsepower be harnessed in
some way?  The answer is yes.

Audio Interleaving

An application can use any extra audio bandwidth to interleave the
bytes from two separate sample files.  This technique allows an
application to play both samples simultaneously on a single audio
channel.

For instance, if you have two files sampled at 10,000 bytes per second,
you could set the playback speed to 20,000 bytes per second and
alternate playing bytes from each sample.  The effective speed of each
sample is preserved since each sample is output only half the time.

 Figure 1 - Interleaved audio data

As shown in the diagram above, an application interleaves the data
bytes from two sound files into a memory buffer.  The application then
plays the back the interleaved sample at twice the rate.  Note that for
this method to work, the speeds of the two samples should be the same,
or at least a close match.  Another restriction is that the sample
speed must be no more than half the maximum speed available on the
Amiga.  Since the playback speed has to be doubled for interleaving to
work and since the speed limit of the Amiga's built in audio hardware
is 28,867 bytes per second, the speed limit of each interleaved sample
is 14,433 bytes per second.

The biggest advantage of audio interleaving is that it exploits unused
audio bandwidth available on the Amiga hardware.  Also, interleaving
does not effect the values of the sampled sound data.  The individual
sound samples remain in their original, noninterleaved form. The
disadvantage is interleaving certain wave forms can combine into an
unexpected and undesirable wave form.  Consider the following two wave
forms:

 Figure 2 - Wave Forms

When the Amiga interleaves these two wave forms, it has to alternate
between wave form A and wave form B.  Because the Amiga is constantly
oscillating between two wave forms, it produces a completely different
wave form:

 Figure 3 - Wave Form

In practice, this usually isn't a problem if you are working with
sampled sound.  Typically, sampled sounds are not pure periodic wave
forms (like the wave forms above).

Audio Averaging

It is not always possible to interleave two samples.  For example, the
frequency of a sample may be more than 14,433 bytes per second, so
doubling it would exceed the 28,867 bytes per second limit.  In that
case, there is another trick you can do to the audio data to combine
two samples on one channel.

If the values from each sample file are added and the resulting value
is divided by two, a new data stream can be created which contains the
audio information from both files.

 Figure 4 - Averaged output data

Note that in the example above, data values are represented as signed
bytes in the range -128 to +127 using twos complement format.  The
resulting average values are correct as shown.  Even though the
ioa_Data field of the IOAudio structure used for all audio.device
requests is shown as (UBYTE *) in the include file <devices/audio.h>,
do not be misled.  The data values are signed bytes.

Audio averaging introduces some noise into the resulting combined
signal.  Dividing the summed values by two effectively reduces the
dynamic range of the component samples by one bit (from eight to seven
bits).  Also, when the values are divided by two, any fractional amount
is truncated, hence, some information is lost.

Despite these drawbacks, the results of audio averaging on the Amiga's
eight bit audio hardware are comparable to the interleaving technique
described above.  In fact, the two techniques are virtually
indistinguishable on the current generation of Amigas (although this
may not always be true--see the ``Audio Experiments'' section later in
this article).

Virtual Voices

When two samples are combined on a single channel using interleaving or
averaging, both samples are clearly audible but, subjectively, it
sounds as if one bit of volume control has been lost on each sample.
Because of this, it is not wise to carry these virtual voice techniques
to an extreme.  Combining samples without limit will result in a badly
degraded composite in which the component signals are no longer clearly
audible. It is however quite feasible to double the number of available
voices to 8 using interleaving or averaging techniques.  The loss of
fidelity with 8 virtual voices is quite tolerable.  The code listed
below shows how this can be implemented.

Using the Interplay Program

The program, named interplay.c, allows the playback of standard IFF
8SVX files in three different ways:

1.  Normal playback of a single file on one channel
2.  Interleaved playback of two files on one channel
3.  Averaged playback of two files on one channel

For normal playback of a single 8SVX file, enter the following command
at the Shell prompt:

    1>interplay sample.8svx

This feature allows you to find out how a sample sounds alone as
compared with its interleaved or averaged counterpart.

For playback of two 8SVX files on a single channel using interleaving,
enter the following command at the Shell prompt:

    1>interplay voice.8svx music.8svx

The program reads the two files, figures out which has the faster
sampling rate, and sets the audio device to twice that value.  If the
calculated rate exceeds the maximum of 28,867 bytes per second, then
interplay sets the speed to the maximum.  The program then interleaves
the data from the two files so that the bytes played by the audio
channel alternate from one file to the other.  If the data from one
file runs out before the other, any remaining data bytes are
interleaved with zero.

For playback of two 8SVX files on a single channel using averaging,
enter the following command at the Shell prompt:

    1>interplay voice.8svx music.8svx SUM

The ``SUM'' keyword enables averaging instead of interleaving.  In this
case, the speed is set to whichever file uses the faster playback rate.
One byte is taken from each file, the two bytes are added and then
divided by two.  The resulting average value is played back.  If the
data from one file runs out before the other, any remaining data bytes
are averaged with zero.

Interplay can play samples of any size.  If a sample is too long, you
can terminate playback by pressing Ctrl-C.

How Interplay Works

Interplay uses a double-buffered approach for the playback of samples
of arbitrary length.  While one data buffer is playing, the other data
buffer is being prepared using either the averaging or interleaving
technique descried above.

Most of the code in the main loop within main() is concerned with
switching between one of the two playback buffers and their
corresponding I/O request blocks and message ports.  The averaging or
interleaving of bytes actually takes place in the FillAudio()
subroutine, not in main().

The reading and parsing of the 8SVX file are handled by the Parse8svx()
subroutine which takes as a parameter an InterPlay structure.  The
InterPlay struture holds all the state information that the program
needs to manage playback of the sampled data.  Thus there will be one
filled-in InterPlay structure for each file to be played back.  If the
user requests a combined playback, the two InterPlay structures are
linked together via the InterPlay.next_iplay field.  Otherwise this
field is set to NULL.

Housekeeping for the audio.device channels used is handled by the
SiezeChannel() and ReleaseChannel() subroutines.

Audio Experiments

Using the interplay.c program listed below, we found that there was
very little difference in the audio quality between the two methods of
combining samples.  We also found that for best results, the dynamic
ranges within the samples themselves had to be closely matched or the
result would be one sample drowning out the other.  Of course, it also
helps if the speeds are a close match.  If they aren't then one or the
other of the samples will be too slow or too fast.

Although both of these methods work comparitively well on the Amiga's
eight-bit audio hardware, doing the same tricks with 16-bit samples on
16-bit hardware would yield a different result.  As mentioned earlier,
the drawback of the averaging method is it loses a bit from the dynamic
range of the sound samples.  Compared to eight-bit sound, this loss is
much less significant when working with 16-bit sound.  As the dynamic
range increases, the impact of losing a single bit from the dynamic
range decreases.  On the other hand, the drawback to the interleaving
method is that it has to oscillate between two samples, which produces
a waveform equal to the sample playback rate.  The waveform is
independent of the dynamic range, so it remains constant as the dynamic
range increases.  The result is the avaeraging method will produce
superior results on systems with greater dynamic range.

Perhaps the best thing about the audio techniques demonstrated by
interplay.c is that they are not limited to the Amiga architecture.  In
fact, you can use interleaving and averaging with any system that
supports the variable speed playback of digitally sampled audio.  These
methods will work not only in the current generation of Amigas but in
any future system that support digital audio, although as the dynamic
range increases, the additive method will provide superior sound
quality.


VII-1: The DR2D FORM

by Ross Cunniff and John Orr

A standard IFF FORM to describe 2D drawings has been sorely needed for
a long time.  Several commercial drawing packages have been available
for some time but none has established its file format as the Amiga
standard.  The absence of a 2D drawing standard hinders the
development of applications that use 2D drawings as it forces each
application to understand several private standards instead of a
single one.  Without a standard, data exchange for both the developer
and the user is difficult, if not impossible.

The DR2D FORM fills this void.  This FORM was developed by Taliesin,
Inc. for use as the native file format for their two-dimensional
structured drawing package, ProVector.  Saxon Industries and Soft
Logik Publishing Corporation are planning to support this new FORM in
the near future.

Many of the values stored in the DR2D FORM are stored as IEEE single
precision floating point numbers.  These numbers consist of 32 bits,
arranged as follows:

 _______________________________________________________________________
| s e e e e e e e | e m m m m m m m | m m m m m m m m | m m m m m m m m |
 -----------------------------------------------------------------------
  31            24  23            16  15            8   7             0

where:

    s   is the sign of the number where 1 is negative and 0 is
          positive.
    e   is the 8 bit exponent in excess 127 form.  This number
          is the power of two to which the mantissa is raised
          (Excess 127 form means that 127 is added to the
          exponent before packing it into the IEEE number.)
    m   is the 23 bit mantissa.  It ranges from 1.0000000 to
          1.999999..., where the leading base-ten one is
          assumed.

An IEEE single precision with the value of 0.0000000 has all its bits
cleared.

 The DR2D Chunks                          The Object Chunks
 The Global Drawing Attribute Chunks      A Simple DR2D Example
 The Object Attribute Chunks              The OFNT FORM


The DR2D Chunks

 FORM (0x464F524D)       /* All drawings are a FORM */
 DR2D (0x44523244)       /* ID of 2D drawing */


FORM (0x464F524D) / All drawings are a FORM /

    struct FORMstruct {
        ULONG       ID;             /* DR2D */
        ULONG       Size;
    };


DR2D (0x44523244) / ID of 2D drawing /

The DR2D chunks are broken up into three groups: the global drawing
attribute chunks, the object attribute chunks, and the object chunks.
The global drawing attribute chunks describe elements of a 2D drawing
that are common to many objects in the drawing.  Document preferences,
palette information, and custom fill patterns are typical
document-wide settings defined in global drawing attribute chunks.
The object attribute chunks are used to set certain properties of the
object chunk(s) that follows the object attribute chunk.  The current
fill pattern, dash pattern, and line color are all set using an object
attribute chunk.  Object chunks describe the actual DR2D drawing.
Polygons, text, and bitmaps are found in these chunks.


The Global Drawing Attribute Chunks

The following chunks describe global attributes of a DR2D document.

 DRHD (0x44524844)       /* Drawing header */
 PPRF (0x50505249)       /* Page preferences */
 CMAP (0x434D4150)       /* Color map (Same as ILBM CMAP) */
 FONS (0x464F4E53)       /* Font chunk (Same as FTXT FONS chunk) */
 DASH (0x44415348)       /* Line dash pattern for edges */
 AROW (0x41524F57)       /* An arrow-head pattern */
 FILL (0x46494C4C)       /* Object-oriented fill pattern */
 LAYR (0x4C415952)       /* Define a layer */


DRHD (0x44524844) / Drawing header /

The DRHD chunk contains the upper left and lower right extremes of the
document in (X, Y) coordinates.  This chunk is required and should
only appear once in a document in the outermost layer of the DR2D file
(DR2Ds can be nested).

    struct DRHDstruct {
        ULONG       ID;
        ULONG       Size;                   /* Always 16 */
        IEEE        XLeft, YTop,
                    XRight, YBot;
    };

The point (XLeft,YTop) is the upper left corner of the project and the
point (XRight,YBot) is its lower right corner.  These coordinates not
only supply the size and position of the document in a coordinate
system, they also supply the project's orientation.  If XLeft <
XRight, the X-axis increases toward the right.  If YTop < YBot, the
Y-axis increases toward the bottom.  Other combinations are possible;
for example in Cartesian coordinates, XLeft would be less than XRight
but YTop would be greater than YBot.


PPRF (0x50505249) / Page preferences /

The PPRF chunk contains preference settings for ProVector.  Although
this chunk is not required, its use is encouraged because it contains
some important environment information.

    struct PPRFstruct {
        ULONG       ID;
        ULONG       Size;
        char        Prefs[Size];
    };

DR2D stores preferences as a concatenation of several null-terminated
strings, in the Prefs[] array.  The strings can appear in any order.
The currently supported strings are:

            Units=<unit-type>
            Portrait=<boolean>
            PageType=<page-type>
            GridSize=<number>

where:
            <unit-type>     is either Inch, Cm, or Pica
            <boolean>       is either True or False
            <page-type>     is either Standard, Legal, B4, B5, A3,
                              A4, A5, or Custom
            <number>        is a floating-point number

The DR2D FORM does not require this chunk to explicitly state all the
possible preferences.  In the absence of any particular preference
string, a DR2D reader should fall back on the default value.  The
defaults are:

            Units=Inch
            Portrait=True
            PageType=Standard
            GridSize=1.0


CMAP (0x434D4150) / Color map (Same as ILBM CMAP) /

This chunk is identical to the ILBM CMAP chunk as described in the IFF
ILBM documentation.

    struct CMAPstruct {
        ULONG       ID;
        ULONG       Size;
        UBYTE       ColorMap[Size];
    };

ColorMap is an array of 24-bit RGB color values.  The 24-bit value is
spread across three bytes, the first of which contains the red
intensity, the next contains the green intensity, and the third
contains the blue intensity.  Because DR2D stores its colors with
24-bit accuracy, DR2D readers must not make the mistake that some ILBM
readers do in assuming the CMAP chunk colors correspond directly to
Amiga color registers.


FONS (0x464F4E53) / Font chunk (Same as FTXT FONS chunk) /

The FONS chunk contains information about a font used in the DR2D
FORM.  ProVector does not include support for Amiga fonts.  Instead,
ProVector uses fonts defined in the OFNT FORM which is documented
later in this article.

    struct FONSstruct {
        ULONG       ID;
        ULONG       Size;
        UBYTE       FontID;         /* ID the font is referenced by */
        UBYTE       Pad1;           /* Always 0 */
        UBYTE       Proportional;   /* Is it proportional? */
        UBYTE       Serif;          /* does it have serifs? */
        CHAR        Name[Size-4];   /* The name of the font */
    };

The UBYTE FontID field is the number DR2D assigns to this font.
References to this font by other DR2D chunks are made using this
number.

The Proportional and Serif fields indicate properties of this font.
Specifically, Proportional indicates if this font is proportional, and
Serif indicates if this font has serifs.  These two options were
created to allow for font substitution in case the specified font is
not available.  They are set according to these values:

    0       The DR2D writer didn't know if this font is
              proportional/has serifs.
    1       No, this font is not proportional/does not have
              serifs.
    2       Yes, this font is proportional/does have serifs.

The last field, Name[], is a NULL terminated string containing the
name of the font.


DASH (0x44415348) / Line dash pattern for edges /

This chunk describes the on-off dash pattern associated with a line.

    struct DASHstruct {
        ULONG       ID;
        ULONG       Size;
        USHORT      DashID;                 /* ID of the dash pattern */
        USHORT      NumDashes;              /* Should always be even */
        IEEE        Dashes[NumDashes];      /* On-off pattern */
    };

DashID is the number assigned to this specific dash pattern.
References to this dash pattern by other DR2D chunks are made using
this number.

The Dashes[] array contains the actual dash pattern.  The first number
in the array (element 0) is the length of the "on" portion of the
pattern.  The second number (element 1) specifies the "off" portion
of the pattern.  If there are more entries in the Dashes array, the
pattern will continue.  Even-index elements specify the length of an
"on" span, while odd-index elements specify the length of an "off"
span.  There must be an even number of entries.  These lengths are not
in the same units as specified in the PPRF chunk, but are multiples of
the line width, so a line of width 2.5 and a dash pattern of 1.0, 2.0
would have an "on" span of length 1.0 x 2.5 = 2.5 followed by an
"off" span of length 2.0 x 2.5 = 5.  The following figure shows
several dash pattern examples.  Notice that for lines longer than the
dash pattern, the pattern repeats.

   figure 1 - dash patterns

By convention, DashID 0 is reserved to mean `No line pattern at all',
i.e. the edges are invisible.  This DASH pattern should not be defined
by a DR2D DASH chunk.  Again by convention, a NumDashes of 0 means
that the line is solid.


AROW (0x41524F57) / An arrow-head pattern /

The AROW chunk describes an arrowhead pattern.  DR2D open polygons
(OPLY) can have arrowheads attached to their endpoints.  See the
description of the OPLY chunk later in this article for more
information on the OPLY chunk.

    #define ARROW_FIRST  0x01 /* Draw an arrow on the OPLY's first point */
    #define ARROW_LAST   0x02 /* Draw an arrow on the OPLY's last point */

    struct AROWstruct {
        ULONG       ID;
        ULONG       Size;
        UBYTE       Flags;          /* Flags, from ARROW_*, above */
        UBYTE       Pad0;           /* Should always 0 */
        USHORT      ArrowID;        /* Name of the arrow head */
        USHORT      NumPoints;
        IEEE        ArrowPoints[NumPoints*2];
    };

The Flags field specifies which end(s) of an OPLY to place an
arrowhead based on the #defines above.  ArrowID is the number by which
an OPLY will reference this arrowhead pattern.

The coordinates in the array ArrowPoints[] define the arrowhead's
shape.  These points form a closed polygon.  See the section on the
OPLY/CPLY object chunks for a descriptionof how DR2D defines shapes.
The arrowhead is drawn in the same coordinate system relative to the
endpoint of the OPLY the arrowhead is attached to.  The arrowhead's
origin (0,0) coincides with the OPLY's endpoint.  DR2D assumes that
the arrowhead represented in the AROW chunk is pointing to the right
so the proper rotation can be applied to the arrowhead.  The arrow is
filled according to the current fill pattern set in the ATTR object
attribute chunk.


FILL (0x46494C4C) / Object-oriented fill pattern /

The FILL chunk defines a fill pattern.  This chunk is only valid
inside nested DR2D FORMs.  The GRUP object chunk section of this
article contans an example of the FILL chunk.

    struct FILLstruct {
        ULONG       ID;
        ULONG       Size;
        USHORT      FillID;                 /* ID of the fill */
    };

FillID is the number by which the ATTR object attribute chunk
references fill patterns.  The FILL chunk must be the first chunk
inside a nested DR2D FORM.  A FILL is followed by one DR2D object plus
any of the object attribute chunks (ATTR, BBOX) associated with the
object.

   Figure 2 - fill patterns

DR2D makes a "tile" out of the fill pattern, giving it a virtual
bounding box based on the extreme X and Y values of the FILL's object
(Fig. A).  The bounding box shown in Fig. A surrounding the pattern
(the two ellipses) is invisible to the user.  In concept, this
rectangle is pasted on the page left to right, top to bottom like
floor tiles (Fig. B).  Again, the bounding boxes are not visible.  The
only portion of this tiled pattern that is visible is the part that
overlaps the object (Fig. C) being filled.  The object's path is
called a clipping path, as it "clips" its shape from the tiled
pattern (Fig. D).  Note that the fill is only masked on top of
underlying objects, so any "holes" in the pattern will act as a
window, leaving visible underlying objects.


LAYR (0x4C415952) / Define a layer /

A DR2D project is broken up into one or more layers.  Each DR2D object
is in one of these layers.  Layers provide several useful features.
Any particular layer can be "turned off", so that the objects in the
layer are not displayed.  This eliminates the unnecessary display of
objects not currently needed on the screen.  Also, the user can lock a
layer to protect the layer's objects from accidental changes.

    struct LAYRstruct {
        ULONG    ID;
        ULONG    Size;
        USHORT   LayerID;              /* ID of the layer */
        char     LayerName[16];        /* Null terminated and padded */
        UBYTE    Flags;                /* Flags, from LF_*, below */
        UBYTE    Pad0;                 /* Always 0 */
    };

LayerID is the number assigned to this layer.  As the field's name
indicates, LayerName[] is the NULL terminated name of the layer.
Flags is a bit field who's bits are set according to the #defines
below:

    #define LF_ACTIVE       0x01    /* Active for editing */
    #define LF_DISPLAYED    0x02    /* Displayed on the screen */

If the LF_ACTIVE bit is set, this layer is unlocked.  A set
LF_DISPLAYED bit indicates that this layer is currently visible on the
screen.  A cleared LF_DISPLAYED bit implies that LF_ACTIVE is not set.
The reason for this is to keep the user from accidentally editing
layers that are invisible.


The Object Attribute Chunks

 ATTR (0x41545452)       /* Object attributes */
 BBOX (0x42424F48)       /* Bounding box of next object in FORM */
 XTRN (0x5854524E)       /* Externally controlled object */


ATTR (0x41545452) / Object attributes /

The ATTR chunk sets various attributes for the objects that follow it.
The attributes stay in effect until the next ATTR changes the
attributes, or the enclosing FORM ends, whichever comes first.

    /* Various fill types */
    #define FT_NONE         0    /* No fill                 */
    #define FT_COLOR        1    /* Fill with color from palette */
    #define FT_OBJECTS      2    /* Fill with tiled objects */

    struct ATTRstruct {
        ULONG       ID;
        ULONG       Size;
        UBYTE       FillType;    /* One of FT_*, above      */
        UBYTE       JoinType;    /* One of JT_*, below      */
        UBYTE       DashPattern; /* ID of edge dash pattern */
        UBYTE       ArrowHead;   /* ID of arrowhead to use  */
        USHORT      FillValue;   /* Color or object with which to fill */
        USHORT      EdgeValue;   /* Edge color index        */
        USHORT      WhichLayer;  /* ID of layer it's in     */
        IEEE        EdgeThick;   /* Line width              */
    };

FillType specifies what kind of fill to use on this ATTR chunk's
objects.  A value of FT_NONE means that this ATTR chunk's objects are
not filled.  FT_COLOR indicates that the objects should be filled in
with a color.  That color's ID (from the CMAP chunk) is stored in the
FillValue field.  If FillType is equal to FT_OBJECTS, FillValue
contains the ID of a fill pattern defined in a FILL chunk.

JoinType determines which style of line join to use when connecting
the edges of line segments.  The field contains one of these four
values:

    /* Join types */
    #define JT_NONE    0            /* Don't do line joins */
    #define JT_MITER        1       /* Mitered join */
    #define JT_BEVEL        2       /* Beveled join */
    #define JT_ROUND        3       /* Round join */

DashPattern and ArrowHead contain the ID of the dash pattern and arrow
head for this ATTR's objects.  A DashPattern of zero means that there
is no dash pattern so lines will be invisible.  If ArrowHead is 0,
OPLYs have no arrow head.  EdgeValue is the color of the line
segments.  WhichLayer contains the ID of the layer this ATTR's objects
are in.  EdgeThick is the width of this ATTR's line segments.


BBOX (0x42424F48) / Bounding box of next object in FORM /

The BBOX chunk supplies the dimensions and position of a bounding box
surrounding the DR2D object that follows this chunk in the FORM.  A
BBOX chunk can apply to a FILL or AROW as well as a DR2D object.  The
BBOX chunk appears just before its DR2D object, FILL, or AROW chunk.

    struct BBOXstruct {
        ULONG       ID;
        ULONG       Size;
        IEEE                XMin, YMin,     /* Bounding box of obj. */
                            XMax, YMax;     /* including line width */
    };

In a Cartesian coordinate system, the point (XMin, YMin) is the
coordinate of the lower left hand corner of the bounding box and
(XMax, YMax) is the upper right.  These coordinates take into
consideration the width of the lines making up the bounding box.


XTRN (0x5854524E) / Externally controlled object /

The XTRN chunk was created primarily to allow ProVector to link DR2D
objects to ARexx functions.

    struct XTRNstruct {
        ULONG   ID;
        ULONG   Size;
        short   ApplCallBacks;             /* From #defines, below */
        short   ApplNameLength;
        char    ApplName[ApplNameLength];  /* Name of ARexx func to call */
    };

ApplName[] contains the name of the ARexx script ProVector calls when
the user manipulates the object in some way.  The ApplCallBacks field
specifies the particular action that triggers calling the ARexx script
according to the #defines listed below.

    /* Flags for ARexx script callbacks */
    #define    X_CLONE     0x0001    /* The object has been cloned */
    #define    X_MOVE      0x0002    /* The object has been moved */
    #define    X_ROTATE    0x0004    /* The object has been rotated */
    #define    X_RESIZE    0x0008    /* The object has been resized */
    #define    X_CHANGE    0x0010    /* An attribute (see ATTR) of the
                                        object has changed */
    #define    X_DELETE    0x0020    /* The object has been deleted */
    #define    X_CUT       0x0040    /* The object has been deleted, but
                                        stored in the clipboard */
    #define    X_COPY      0x0080    /* The object has been copied to the
                                        clipboard */
    #define    X_UNGROUP   0x0100    /* The object has been ungrouped */

For example, given the XTRN object:

    FORM xxxx DR2D {
            XTRN xxxx { X_RESIZE | X_MOVE, 10, "Dimension" }
            ATTR xxxx { 0, 0, 1, 0, 0, 0, 0.0 }
            FORM xxxx DR2D {
                    GRUP xxxx { 2 }
                    STXT xxxx { 0, 0.5, 1.0, 6.0, 5.0, 0.0, 4, "3.0" }
                    OPLY xxxx { 2, { 5.5, 5.5, 8.5, 5.5 } }
            }
    }

ProVector would call the ARexx script named Dimension if the user
resized or moved this object.  What exactly ProVector sends depends
upon what the user does to the object.  The following list shows what
string(s) ProVector sends according to which flag(s) are set.  The
parameters are described below.

    X_CLONE     "appl CLONE objID dx dy"
    X_MOVE      "appl MOVE objID dx dy"
    X_ROTATE    "appl ROTATE objID cx cy angle"
    X_RESIZE    "appl RESIZE objID cx cy sx sy"
    X_CHANGE    "appl CHANGE objID et ev ft fv ew jt fn"
    X_DELETE    "appl DELETE objID"
    X_CUT       "appl CUT objID"
    X_COPY      "appl COPY objID"
    X_UNGROUP   "appl UNGROUP objID"

where:
    appl is the name of the ARexx script
    CLONE, MOVE, ROTATE, RESIZE, etc. are literal strings
    objID is the object ID that ProVector assigns to this object
    (dx, dy) is the position offset of the CLONE or MOVE
    (cx, cy) is the point around which the object is rotated or resized
    angle is the angle (in degrees) the object is rotated
    sx and sy are the scaling factors in the horizontal and
      vertical directions, respectively.
    et is the edge type (the dash pattern index)
    ev is the edge value (the edge color index)
    ft is the fill type
    fv is the fill index
    ew is the edge weight
    jt is the join type
    fn is the font name

The X_CHANGE message reflects changes to the attributes found in the
ATTR chunk.

If the user resized the XTRN object shown above by factor of 2,
ProVector would call the ARexx script Dimension like this:

    Dimension RESIZE 1985427 7.0 4.75 2.0 2.0


The Object Chunks

The following chunks define the objects available in the DR2D FORM.

 VBM  (0x56424D20)       /* Virtual BitMap */
 CPLY (0x43504C59)       /* Closed polygon */
 OPLY (0x4F504C59)       /* Open polygon */
 GRUP (0x47525550)       /* Group */
 STXT (0x53545854)       /* Simple text */
 TPTH (0x54505448)       /* A text string along a path */


VBM (0x56424D20) / Virtual BitMap /

The VBM chunk contains the position, dimensions, and file name of an
ILBM image.

    struct VBMstruct {
        IEEE        XPos, YPos,     /* Virtual coords */
                    XSize, YSize,   /* Virtual size */
                    Rotation;       /* in degrees */
        USHORT      PathLen;        /* Length of dir path */
        char        Path[PathLen];  /* Null-terminated path of file */
    };

The coordinate (XPos, YPos) is the position of the upper left hand
corner of the bitmap and the XSize and YSize fields supply the x and y
dimensions to which the image should be scaled.  Rotation tells how
many degrees to rotate the ILBM around its upper left hand corner.
ProVector does not currently support rotation of bitmaps and will
ignore this value.  Path contains the name of the ILBM file and may
also contain a partial or full path to the file.  DR2D readers should
not assume the path is correct.  The full path to an ILBM on one
system may not match the path to the same ILBM on another system.  If
a DR2D reader cannot locate an ILBM file based on the full path name
or the file name itself (looking in the current directory), it should
ask the user where to find the image.


CPLY (0x43504C59) and OPLY (0x4F504C59)

Polygons are the basic components of almost all 2D objects in the DR2D
FORM.  Lines, squares, circles, and arcs are all examples of DR2D
polygons.  There are two types of DR2D polygons, the open polygon
(OPLY) and the closed polygon (CPLY).  The difference between a closed
and open polygon is that the computer adds a line segment connecting
the endpoints of a closed polygon so that it is a continuous path.  An
open polygon's endpoints do not have to meet, like the endpoints of a
line segment.

    struct POLYstruct {
        ULONG       ID;
        ULONG       Size;
        USHORT      NumPoints;
        IEEE        PolyPoints[2*NumPoints];
    };

The NumPoints field contains the number of points in the polygon and
the PolyPoints array contains the (X, Y) coordinates of the points of
the non-curved parts of polygons.  The even index elements are X
coordinates and the odd index elements are Y coordinates.

   Figure 3 - Bezier curves

DR2D uses Bezier cubic sections, or cubic splines, to describe curves
in polygons.  A set of four coordinates (P1 through P4) defines the
shape of a cubic spline.  The first coordinate (P1) is the point where
the curve begins.  The line from the first to the second coordinate
(P1 to P2) is tangent to the curve at the first point.  The line from
P3 to P4 is tangent to the cubic section, where it ends at P4.

The coordinates describing the cubic section are stored in the
PolyPoints[] array with the coordinates of the normal points.  DR2D
inserts an indicator point before a set of cubic section points to
differentiate a normal point from the points that describe a curve.
An indicator point has an X value of 0xFFFFFFFF.  The indicator
point's Y value is a bit field.  If this bit field's low-order bit is
set, the points that follow the indicator point make up a cubic
section.

The second lowest order bit in the indicator point's bit field is the
MOVETO flag.  If this bit is set, the point (or set of cubic section
points) starts a new polygon, or subpolygon.  This subpolygon will
appear to be completely separate from other polygons but there is an
important connection between a polygon and its subpolygon.
Subpolygons make it possible to create holes in polygons.  An example
of a polygon with a hole is the letter "O".  The "O" is a filled
circular polygon with a smaller circular polygon within it.  The
reason the inner polygon isn't covered up when the outer polygon is
filled is that DR2D fills are done using the even-odd rule.

The even-odd rule determines if a point is "inside" a polygon by
drawing a ray outward from that point and counting the number of path
segments the ray crosses.  If the number is even, the point is outside
the object and shouldn't be filled.  Conversely, an odd number of
crossings means the point is inside and should be filled.  DR2D only
applies the even-odd rule to a polygon and its subpolygons, so no
other objects are considered in the calculations.

Taliesin, Inc. supplied the following algorithm to illustrate the
format of DR2D polygons.  OPLYs, CPLYs, AROWs, and ProVector's outline
fonts all use the same format:

    typedef union {
        IEEE num;
        LONG bits;
    } Coord;

    #define INDICATOR       0xFFFFFFFF
    #define IND_SPLINE      0x00000001
    #define IND_MOVETO      0x00000002

    /* A common pitfall in attempts to support DR2D has
            been to fail to recognize the case when an
            INDICATOR point indicates the following
            coordinate to be the first point of BOTH a
            Bezier cubic and a sub-polygon, ie. the
            value of the flag = (IND_CURVE | IND_MOVETO) */

    Coord   Temp0, Temp1;
    int     FirstPoint, i, Increment;

    /* Initialize the path */
    NewPath();
    FirstPoint = 1;

    /* Draw the path */
    i = 0;
    while( i < NumPoints ) {
        Temp0.num = PolyPoints[2*i];    Temp1.num = PolyPoints[2*i + 1];
        if( Temp0.bits == INDICATOR ) {
            /* Increment past the indicator */
            Increment = 1;
            if( Temp1.bits & IND_MOVETO ) {
                /* Close and fill, if appropriate */
                if( ID == CPLY ) {
                    FillPath();
                }
                else {
                    StrokePath();
                }

                /* Set up the new path */
                NewPath();
                FirstPoint = 1;
            }
            if( Temp1.bits & IND_CURVE ) {
                /* The next 4 points are Bezier cubic control points */
                if( FirstPoint )
                    MoveTo( PolyPoints[2*i + 2], PolyPoints[2*i + 3] );
                else
                    LineTo( PolyPoints[2*i + 2], PolyPoints[2*i + 3] );
                CurveTo(    PolyPoints[2*i + 4], PolyPoints[2*i + 5],
                            PolyPoints[2*i + 6], PolyPoints[2*i + 7],
                            PolyPoints[2*i + 8], PolyPoints[2*i + 9] );
                FirstPoint = 0;
                /* Increment past the control points */
                Increment += 4;
            }
        }
        else {
            if( FirstPoint )
                MoveTo(     PolyPoints[2*i], PolyPoints[2*i + 1] );
            else
                LineTo(     PolyPoints[2*i], PolyPoints[2*i + 1] );
            FirstPoint = 0;

            /* Increment past the last endpoint */
            Increment = 1;
        }

        /* Add the increment */
        i += Increment;
    }

    /* Close the last path */
    if( ID == CPLY ) {
        FillPath();
    }
    else {
        StrokePath();
    }


GRUP (0x47525550) / Group /

The GRUP chunk combines several DR2D objects into one.  This chunk is
only valid inside nested DR2D FORMs, and must be the first chunk in
the FORM.

    struct GROUPstruct {
        ULONG       ID;
        ULONG       Size;
        USHORT      NumObjs;
    };

The NumObjs field contains the number of objects contained in this
group.  Note that the layer of the GRUP FORM overrides the layer of
objects within the GRUP.  The following example illustrates the layout
of the GRUP (and FILL) chunk.

   FORM { DR2D              /* Top-level drawing... */
            DRHD { ... }    /* Confirmed by presence of DRHD chunk */
            CMAP { ... }    /* Various other things... */
            FONS { ... }
            FORM { DR2D             /* A nested form... */
                    FILL { 1 }      /* Ah!  The fill-pattern table */
                    CPLY { ... }    /* with only 1 object */
            }
            FORM { DR2D             /* Yet another nested form */
                    GRUP { ..., 3 } /* Ah! A group of 3 objects */
                    TEXT { ... }
                    CPLY { ... }
                    OPLY { ... }
            }
            FORM { DR2D             /* Still another nested form */
                    GRUP { ..., 2 } /* A GRUP with 2 objects */
                    OPLY { ... }
                    TEXT { ... }
            }
    }


STXT (0x53545854) / Simple text /

The STXT chunk contains a text string along with some information on
how and where to render the text.

    struct STXTstruct {
        ULONG       ID;
        ULONG       Size;
        UBYTE       Pad0;           /* Always 0 (for future expansion) */
        UBYTE       WhichFont;      /* Which font to use */
        IEEE        CharW, CharH,   /* W/H of an individual char */
                    BaseX, BaseY,   /* Start of baseline */
                    Rotation;       /* Angle of text (in degrees) */
        USHORT      NumChars;
        char        TextChars[NumChars];
    };

The text string is in the character array, TextChars[].  The ID of the
font used to render the text is WhichFont.  The font's ID is set in a
FONS chunk.  The starting point of the baseline of the text is (BaseX,
BaseY).  This is the point around which the text is rotated.  If the
Rotation field is zero (degrees), the text's baseline will originate
at (BaseX, BaseY) and move to the right.  CharW and CharH are used to
scale the text after rotation.  CharW is the average character width
and CharH is the average character height.  The CharW/H fields are
comparable to an X and Y font size.


TPTH (0x54505448) / A text string along a path /

This chunk defines a path (polygon) and supplies a string to render
along the edge of the path.

    struct TPTHstruct {
        ULONG   ID;
        ULONG   Size;
        UBYTE   Justification;      /* see defines, below */
        UBYTE   WhichFont;          /* Which font to use */
        IEEE    CharW, CharH;       /* W/H of an individual char    */
        USHORT  NumChars;           /* Number of chars in the string */
        USHORT  NumPoints;          /* Number of points in the path */
        char    TextChars[NumChars];/* PAD TO EVEN #! */
        IEEE    Path[2*NumPoints];  /* The path on which the text lies */
    };

WhichFont contains the ID of the font used to render the text.
Justification controls how the text is justified on the line.
Justification can be one of the following values:

    #define J_LEFT          0x00    /* Left justified */
    #define J_RIGHT         0x01    /* Right justified */
    #define J_CENTER        0x02    /* Center text */
    #define J_SPREAD        0x03    /* Spread text across path */

CharW and CharH are the average width and height of the font
characters and are akin to X and Y font sizes, respectively.  A
negative FontH implies that the font is upsidedown.  Note that CharW
must not be negative.  NumChars is the number of characters in the
TextChars[] string, the string containing the text to be rendered.
NumPoints is the number of points in the Path[] array.  Path[] is the
path along which the text is rendered.  The path itself is not
rendered.  The points of Path[] are in the same format as the points
of a DR2D polygon.


A Simple DR2D Example

Here is a (symbolic) DR2D FORM:

    FORM { DR2D
        DRHD 16 { 0.0, 0.0, 10.0, 8.0 }
        CMAP  6 { 0,0,0, 255,255,255 }
        FONS  9 { 1, 0, 1, 0, "Roman" } 0
        DASH 12 { 1, 2, {1.0, 1.0} }
        ATTR 14 { 0, 0, 1, 0, 0, 0, 0, 0.0 }
        BBOX 16 { 2.0, 2.0, 8.0, 6.0 }
        FORM { DR2D
            GRUP  2 { 2 }
            BBOX 16 { 3.0, 4.0, 7.0, 5.0 }
            STXT 36 { 0,1, 0.5, 1.0, 3.0, 5.0, 0.0, 12, "Hello, World" }
            BBOX 16 { 2.0, 2.0, 8.0, 6.0 }
            OPLY 42 { 5, {2.0,2.0, 8.0,2.0, 8.0,6.0, 2.0,6.0, 2.0,2.0 }
        }
    }

This is what the DR2D FORM above should look like:

   Figure 4 - Simple DR2D drawing


The OFNT FORM

 OFNT    (0x4F464E54)    /* ID of outline font file */
 OFHD    (0x4F464844)    /* ID of OutlineFontHeaDer */
 KERN    (0x4B45524C)    /* Kerning pair */
 CHDF    (0x43484446)    /* Character definition */


OFNT (0x4F464E54) / ID of outline font file /

ProVector's outline fonts are stored in an IFF FORM called OFNT.  This
IFF is a separate file from a DR2D.  DR2D's FONS chunk refers only to
fonts defined in the OFNT form.


OFHD (0x4F464844) / ID of OutlineFontHeaDer /

This chunk contains some basic information on the font.

    struct OFHDstruct {
        char   FontName[32];   /* Font name, null padded */
        short  FontAttrs;      /* See FA_*, below */
        IEEE   FontTop,        /* Typical height above baseline */
               FontBot,        /* Typical descent below baseline */
               FontWidth;      /* Typical width, i.e. of the letter O */
    };

    #define FA_BOLD         0x0001
    #define FA_OBLIQUE      0x0002
    #define FA_SERIF        0x0004

The FontName field is a NULL terminated string containing the name of
this font.  FontAttrs is a bit field with flags for several font
attributes.  The flags, as defined above, are bold, oblique, and
serif.  The unused higher order bits are reserved for later use.  The
other fields describe the average dimensions of the characters in this
font.  FontTop is the average height above the baseline, FontBot is
the average descent below the baseline, and FontWidth is the average
character width.


KERN (0x4B45524C) / Kerning pair /

The KERN chunk describes a kerning pair.  A kerning pair sets the
distance between a specific pair of characters.

    struct KERNstruct {
        short   Ch1, Ch2;  /* The pair to kern (allows for 16 bits...) */
        IEEE    XDisplace, /* Amount to displace -left +right */
                YDisplace; /* Amount to displace -down +up */
    };

The Ch1 and Ch2 fields contain the pair of characters to kern.  These
characters are typically stored as ASCII codes.  Notice that OFNT
stores the characters as a 16-bit value.  Normally, characters are
stored as 8-bit values.  The wary programmer will be sure to cast
assigns properly to avoid problems with assigning an 8-bit value to a
16-bit variable.  The remaining fields, XDisplace and YDisplace,
supply the baseline shift from Ch1 to Ch2.


CHDF (0x43484446) / Character definition /

This chunk defines the shape of ProVector's outline fonts.

    struct CHDFstruct {
        short   Ch;         /* The character we're defining (ASCII) */
        short   NumPoints;  /* The number of points in the definition */
        IEEE    XWidth,     /* Position for next char on baseline - X */
                YWidth;     /* Position for next char on baseline - Y */
     /* IEEE    Points[2*NumPoints]*/       /* The actual points */
    };

    #define INDICATOR   0xFFFFFFFF  /* If X == INDICATOR, Y is an action */
    #define IND_SPLINE  0x00000001  /* Next 4 pts are spline control pts */
    #define IND_MOVETO  0x00000002     /* Start new subpoly */
    #define IND_STROKE  0x00000004  /* Stroke previous path */
    #define IND_FILL    0x00000008  /* Fill previous path */

Ch is the value (normally ASCII) of the character outline this chunk
defines.  Like Ch1 and Ch2 in the KERN chunk, Ch is stored as a 16-bit
value.  (XWidth,YWidth) is the offset to the baseline for the
following character.  OFNT outlines are defined using the same method
used to define DR2D's polygons (see the description of OPLY/CPLY for
details).

Because the OFNT FORM does not have an ATTR chunk, it needed an
alternative to make fills and strokes possible.  There are two extra
bits used in font indicator points not found in polygon indicator
points, the IND_STROKE and IND_FILL bits (see defines above).  These
two defines describe how to render the current path when rendering
fonts.

The current path remains invisible until the path is either filled
and/or stroked.  When the IND_FILL bit is set, the currently defined
path is filled in with the current fill pattern (as specified in the
current ATTR chunk).  A set IND_STROKE bit indicates that the
currently defined path itself should be rendered.  The current ATTR's
chunk dictates the width of the line, as well as several other
attributes of the line.  These two bits apply only to the OFNT FORM
and should not be used in describing DR2D polygons.


VII-17: ECS Display Modes and ILBM CAMG

By Carolyn Scheppner

Under versions of the Amiga operating system and hardware prior to release
2.0, the display modes available to the system (such as HIRES, LACE, HAM,
HALFBRITE, DUALPF) could all be described in the 16-bit ViewPort.Modes
field. When saving an Amiga display to an ILBM file, the ViewPort mode
field, also referred to as a view mode, was preserved along with the image
to make sure it could be later displayed in the proper display mode.  The
ILBM CAMG chunk stores a display's view mode.

When using Amiga operating systems prior to release 2.0, storing the view
mode in an ILBM involves extracting the 16-bit view mode, masking out the
GENLOCK_AUDIO, GENLOCK_VIDEO, VP_HIDE, and SPRITES flags, and storing the
result as a 32-bit value in the CAMG chunk.  The upper word of the value
should be zero.  Reading the view mode requires masking out the
undesirable bits mentioned above from the CAMG's 32-bit value, and then
use the low word of the result as a 16-bit value for ViewPort.Modes or
NewScreen.ViewModes when opening a display.

The 2.0 operating system and the ECS chips support a large number of
display modes--too many for the old 16-bit view mode to represent.  Under
2.0, display modes are now specified by a 32-bit ModeID which is not
stored in the ViewPort, but is instead held in private graphics lists.
The graphics.library provides functions for accessing this extended
display information.  The GetVPModeID() function returns a ViewPort's
32-bit ModeID:

    ULONG  modeID = GetVPModeID(struct ViewPort *vp);

When saving a display under release 2.0, an ILBM writer must preserve the
entire 32-bit modeID in the CAMG chunk.  The advantage of this is ILBM
readers that don't know about the release 2.0 32-bit view mode can still
display ILBMs saved under 2.0.  Although ModeIDs are numeric values rather
than bit masks, the 2.0 ModeIDs were designed to contain the pre-2.0 bits
in their low word for the matching (or closest match) old ViewPort mode.
For example, the 2.0 ModeID for a Hires-Interlace display has the HIRES
and LACE bits set in its low word.  The 2.0 ModeID for a Productivity
Interlaced display also has the HIRES and LACE bits set in its low word
because, of the display modes available to a non-ECS or pre-2.0 system, a
Hires-Interlace display is most like the Productivity Interlaced display.

By storing the entire 32-bit ModeID in the CAMG chunk, 2.0 compatible ILBM
readers can display the image in the proper display mode if that display
mode is available to the current system.  Old ILBM readers will not be
able to use the new display modes, but they will truncate the new 32-bit
ModeID into a 16-bit view mode which will normally provide a reasonable
view mode for the image.

There are several CAMG values saved by old ILBM writers which are invalid
modeID values.  An ILBM writer will produce ILBMs with invalid modeID
values if it:

    *  fails to mask out SPRITES|VP_HIDE|GENLOCK_AUDIO|GENLOCK_VIDEO.

    *  saves a 2.0 extended view mode as 16 bits rather than saving the
       32-bit modeID returned by GetVPModeID().

    *  saves garbage in the upper word of the
       CAMG value.

All valid modeIDs either have an upper word of 0 and do not have the
<graphics/view.h> EXTENDED_MODE bit set in the low word, or have a non-0
upper word and do have the EXTENDED_MODE bit set in the lower word.  CAMG
values which are invalid modeIDs must be screened out and fixed before
using them.

/* Knock bad bits out of old-style CAMGs modes before checking
 * availability. (some ILBM CAMG's have these bits set in old 1.3 modes,
 * and should not) If not an extended monitor ID, or if marked as
 * extended but missing upper 16 bits, screen out inappropriate bits now.
 */
if((!(modeid & MONITOR_ID_MASK)) ||
    ((modeid & EXTENDED_MODE)&&(!(modeid & 0xFFFF0000))))
        modeid &=
           (~(EXTENDED_MODE|SPRITES|GENLOCK_AUDIO|GENLOCK_VIDEO|VP_HIDE));

/* Check for bogus CAMG like some brushes have, with junk in
 * upper word and extended bit NOT set not set in lower word.
 */
if((modeid & 0xFFFF0000)&&(!(modeid & EXTENDED_MODE)))
    {
    /* Bad CAMG, so ignore CAMG and determine a mode based on
     * based on pagesize or aspect
     */
     modeid = NULL;
     if(wide >= 640)    modeid |= HIRES;
     if(high >= 400)    modeid |= LACE;
     }

The following example, camg.c, illustrates how to handle the possible CAMG
values.


VII-21: Developing New IFF FORMs and Chunks

by Christian Ludwig - Multimedia Standards Engineer, CATS

IFF has been one of the keys to the Amiga's superiority in multimedia
applications, allowing interchange of media elements between packages.
The wealth of standard IFF FORMs and chunks gives the Amiga user
data-sharing capabilities that are virtually unequaled on other systems.
The Amiga's ability to render an image, touch it up, convert it to a
different display mode, and load it into in another package is something
that is a chore on other platforms, simply because the format of the image
file may be different from one application to the next.  IFF files lessen
the need for ``conversion'' software, because most Amiga applications can
read and write them.

Since its introduction as an open standard in 1985, IFF has widened to
encompass data of many sorts--and the need for new IFF types continues to
grow.  To satisfy these growing needs, developers will continue to define
and support new IFF types.  Now that both the console and iffparse.library
support sharing IFF files through the clipboard in release 2.0, IFF
support is more important than ever.

When developing a new IFF type, there are several steps you should follow:

* Discuss needs and specifications within the developer community and with
  Commodore.

    The most important thing about designing IFF FORMs and chunks is
    that they meet the data storage and transfer needs of multiple
    applications.  When more than one product uses the same IFF
    type, the market widens for all products that use that IFF type.
    Users are not forced to use one product or another, but can buy
    as many as they need to get the job done, fully utilizing all
    the features that each product has to offer.  This step helps to
    ensure that a proposed IFF form or chunk type is flexible and
    isn't redundant.  A good way to start this kind of discussion is
    to post a message in Commodore's amiga.dev/iff conference on the
    BIX electronic network.  Also, feel free to contact me to
    discuss your IFF needs and issues.  You can reach me at (215)
    431-9316 or on BIX (cludwig).  I can also be reached via UseNet
    InterNet e-mail at:

        chrisl@cbmvax.commodore.com or ...[uunet|rutgers]!cbmvax!chrisl.

* Implement the new type and conduct feasibility tests.

    Before settling on a format, set up prototype code to test the
    proposed format.  This will help to prove that the idea is sound
    and can be implemented in software before others try to use it.

* Submit specifications to Commodore.

    Coming up with a new kind of IFF FORM or chunk is easy--almost
    too easy. Just about anyone can follow the IFF guidelines and
    define their own FORM or chunk.  If every application used a
    different IFF FORM, one application would be unable to share
    data with another because it can't read the other application's
    IFF FORM1.  It's like making up a new word for something that
    everyone sees every day.  You may understand what the word
    means, but when you try to use your new word to communicate with
    others, they won't understand you.  Further, deciding to use a
    pre-existing FORM or chunk in a new and different way is a lot
    like making up your own meaning for a pre-existing word.
    Confusion results when programs try to read FORMs or chunks
    whose meaning was altered by a non-conforming program.

    To avoid the problem of incompatible IFF types, register your
    new IFF types with CATS.  CATS acts as a ``dictionary'' of IFF
    types.  By submitting your proposals for FORM or chunk types to
    CATS, you help prevent duplication of an existing data type.
    Also, if you register your new IFF type, it is more likely that
    it will be adopted as an IFF standard that other applications
    will use.  For example, the ANIM form came from third party
    developers who proposed and refined the format.  Now ANIM is the
    de facto standard for animation files.

    CATS wants this last step to be as easy as possible, so we've
    included a standard form at the end of this article.  Just
    photocopy the form whenever you need it, and use it as a guide
    for submitting your FORM or chunk specifications.  The
    registration form should be

    accompanied by a disk containing ASCII text files of the IFF
    specification. If available, include some code examples which
    demonstrate the use of the IFF type.  Please do not place
    copyright notices in your specifications or examples so that
    CATS may make them available to other developers.

    For an excellent example of a third party FORM specification,
    see the WORD FORM in the third party specification section of
    the IFF manual.   For an example of chunk descriptions, examine
    the 8SVX FORM's SEQN and FADE chunks in the same section.

    Note that even you don't plan to release the specifications of
    your FORM or chunk, you must still register the name with CATS.
    This is the only way to prevent name conflicts in IFF files.
    You should register your FORM and chunk names before finalizing
    your product and its documentation in case there is a name
    conflict with an existing IFF type.

* Distribute final specifications to the developer community.

    Once you have registered your FORM or chunk with CATS, you
    should release the specifications of the chunk to the developer
    community.  Although CATS publishes FORMs and chunks in the IFF
    Manual and occasionally in Amiga Mail, developers should not
    rely on these methods to distribute their IFF type
    specification.  One of the most efficient ways to distribute
    your specification is to include it in your application's
    documentation.  Another good distribution method is to post the
    final specifications in amiga.dev/iff on BIX.  Distributing the
    specification will increase the probability of your form or
    chunk becoming a standard.

   CATS IFF FORM/Chunk Registration Form


VII-25: AmigaGuide(TM) 101

AmigaGuide(TM) 101

by Jerry Hartzler

NOTE: AmigaGuide(TM) is now available to developers on the 3.0
Workbench release, the CATS Developer CD and Commodore's closed Amiga
developer listings area on BIX, CIX and ADSP.  Developers with a
Workbench or Includes License can amend their license to distribute
AmigaGuide.  Currently CATS is in the process of putting together an
archive file that will be made available to the general public.

Compared to other platforms, Amiga-based utilities that display
on-line documentation are relatively weak.  Until 1991, Amiga users
had to rely on basic text viewing utilities like More, which lack the
navigational capabilities of hypertext programs.  In a hypertext
environment, when the user wants more information on a subject, the
user simply clicks on a word and the hypertext utility automatically
cross references the subject.  No type of hypertext-like utility was
available on the Amiga--that is, until AmigaGuide came along.

AmigaGuide can display plain ASCII text files and AmigaGuide
databases.  An AmigaGuide database is a single file that consists of
a set of documents called nodes.  If you were to convert a book into
an AmigaGuide database, a convenient way to organize the database is
to make each chapter of the book into a node.  Each node may contain
references to other nodes (chapters) or databases (other books),
using a link.  When a user selects a link--which usually appears in
the form of a button within the text--AmigaGuide dereferences the
link and displays its node.  This makes it easier for the user to
find the information he is looking for because the user no longer
needs to search through a document.  AmigaGuide already knows where
the information is.

Buttons within AmigaGuide can do other actions as well, such as
execute Shell or ARexx commands.  An ARexx port is also built into
AmigaGuide providing users the means to support and control the
utility.  Therefore, like a book, an AmigaGuide database can display
illustrations.  It can go a step beyond by playing sounds and music,
and by being truly interactive with the user, able to ask questions
and evaluate responses.

This article was written to familiarize you with AmigaGuide and the
format of its databases.

Setting up AmigaGuide

AmigaGuide consists of the AmigaGuide utility and an Exec library
called amigaguide.library.  AmigaGuide should be placed in the
SYS:Utilities drawer and amigaguide.library placed in the Libs:
drawer.  As of Release 3, the OS comes with a utility called
MultiView that understands and displays AmigaGuide databases.
MultiView requires amigaguide.datatype and .datatypes.library in
order to display AmigaGuide databases.

AmigaGuide can run from the Workbench or the Shell.  To run from
Workbench, the default tool of an AmigaGuide database or text icon
should be set to ``AmigaGuide''.

From the Shell, use the following command template:

    AmigaGuide <my_DataBase>

where <my_DataBase> is the name of the AmigaGuide database or text
file to display.

For example:

    1> AmigaGuide Autodocs

attempts to open the ``Autodocs'' database.  In its search for a
database, AmigaGuide will first look in the current directory and
then through the AmigaGuide path for the database.

The AmigaGuide path is a global environment variable.  AmigaGuide
stores its environment variables in the ENV:AmigaGuide directory
assigned in RAM:.

The variable named ``path'' contains the list of directory names that
AmigaGuide will search through when it attempts to open a database.
Directory names are separated by a space.  The path variable is set
and stored in the ENV:AmigaGuide directory through the use of the
AmigaDOS SetEnv command (Note that as of Release 3, if the AmigaGuide
directory does not exist, SetEnv will not create it).

For example:

    1> SetEnv AmigaGuide/Path "Workbench:Autodocs Workbench:Includes"

Of course all variables set in RAM: disappear once the computer is
turned off.  To prevent this, copy the file ENV:AmigaGuide/Path to
the ENVARC:AmigaGuide directory.  The system copies the ENVARC:
directory to ENV: upon start-up.

The MultiView utility uses the  amigaguide.datatype which uses this
the environment variable as its path.

The AmigaGuide Window

AmigaGuide displays text within an Intuition window.  The window
contains scroll bars, buttons and pull-down menus making it easy to
browse, search and print text.

Along the top edge of the AmigaGuide window is a row of six
navigation buttons:

  Contents: This button displays the Table Of Contents for the current
  database or node.  See the @NODE and @TOC commands below.

  Index: This button displays the Index for the current database.  See
  the @INDEX command below.

  Help: By deafault, this button displays the database named help.guide
  in the s: directory.  Under 3.0, the database is named
  amigaguide.guide in the Help:<country>/sys directory.  This database
  contains help in using AmigaGuide.

  Retrace: This button goes back to the previous node.

  Browse: These buttons step through the nodes in sequential order (the
  order they appear in the database).

AmigaGuide Databases

Creating an AmigaGuide database is quite simple.  An AmigaGuide
database is basically an ASCII text file, embedded with commands to
tell AmigaGuide what to do.  Let's take a look at the commands used
in AmigaGuide and then make up a simple database.

There are three types of AmigaGuide commands.  Database commands
break up a document into nodes.  Node commands set attributes within
a node.  Action commands are only found within a special node command
called a ``link point''.  As the name implies, action commands
perform some action.

Database Commands

Database commands should not be used within the nodes themselves.
They must start in the first column of a line.  If a line in an
AmigaGuide database begins with an at (@) sign, then AmigaGuide
interprets the line as a command.  Although the AmigaGuide commands
appear here in upper-case, AmigaGuide commands are not case sensitive.

@DATABASE <name> - This command identifies a file as an AmigaGuide
database.  It must be the first line of the database.

@NODE <name> <title> - This command indicates the start of a node.
The first node of a database should be named ``MAIN''.  ``MAIN'' is
typically the master table of contents for the database (see the @TOC
node command in the next section).  When AmigaGuide displays the
node, it displays <title> in the window's title bar.  If there are
any spaces in the <title>, it must be in quotes.  A node name cannot
contain spaces, tabs, colons (':') or slants ('/').

@DNODE <name> - This command indicates the start of a dynamic node.
Dynamic nodes are beyond the scope of this introductory article and
therefore are not discussed here.

@INDEX <node name> - This command tells AmigaGuide which node to use
as the index for the database.  When the user hits the ``Index''
button at the top of the AmigaGuide window, AmigaGuide will display
the node specified by this command.  The node can be in another
database.  If the node is in another database, the node name is the
file name of the database followed by a slant (`/`), followed by the
name of the node in the other database.  For example, to access the
MAIN node in another database called ``other_database'', the link
point looks like this:

    @{"my label" LINK other_database/MAIN}

The name of the other database can contain a full path to the other
database.  If it doesn't, AmigaGuide will search the AmigaGuide path
for the other database.

@REMARK <remark> - This commands lets you add programmer remarks to a
database.  AmigaGuide ignores the remarks.

Node Commands

These commands are only valid within a @NODE.  They must start in the
first column of a line unless otherwise noted.

@ENDNODE <name> - This command ends a node.

@TITLE <title> - AmigaGuide displays <title> in the node's window
title bar.  It must start at the beginning of a line.  This command
isn't necessary if you use the <title> option in @NODE.

@TOC <node name> - This command tells AmigaGuide which node to
display when the user hits the ``Contents'' button while displaying
this node.  If a node does not have a @TOC command, the table of
contents defaults to ``MAIN''.  The <node name> can be in another
database.  See the @INDEX command in the ``Database Commands''
section for more information on the format of <node name>.

@PREV <node name> - The ``Browse'' buttons can be reprogrammed so as
not to step through the nodes in sequential order.  For example, if
this command appears in a @NODE, AmigaGuide  will display the <node
name> node when the user selects the ``< Browse'' button while in the
current node.  The <node name> can be in another database.  See the
@INDEX command in the ``Database Commands'' section for more
information on the format of <node name>.

@NEXT <node name> - Similar to @PREV but will display the <node name>
node when the user selects ``Browse >'' button while in the current
node.  The <node name> can be in another database.  See the @INDEX
command in the ``Database Commands'' section for more information on
the format of <node name>.

@{"<label>" <action command>} - This command is referred to as a link
point.  AmigaGuide makes the string <label> into a button.  The
<label> must be enclosed by quotes.  When the user hits that button,
AmigaGuide carries out <action command> (see the next section of this
article for a description of action commands).  A link point does not
have to start in the first column, it can appear anywhere on a line.

Action Commands

These commands are for use with the link point command described in
the ``Node Commands'' section of this article.

LINK <node name> <line#> - This command loads and displays the <node
name> node at the line number specified in <line #>.  The <line #>
parameter is optional and it defaults to zero.  The node can be in
another database.  The <node name> can be in another database.  See
the @INDEX command in the ``Database Commands'' section for more
information on the format of <node name>.

The <line #> parameter is optional and it defaults to zero.  The
default line number is line zero.

RX <ARexx command> - This commands executes the ARexx macro named in
<ARexx command>.

RXS <command> - This commands executes the ARexx string file named in
<command>.

SYSTEM <command> - This commands executes the AmigaDOS command named
in <command>.

QUIT - When AmigaGuide encounters this command is shuts down the
current database.

A Working Database

As an example, Let's make the text file below into a simple
AmigaGuide database.  The simple database will consists of a single
node.

  What is a user interface? This sweeping phrase covers all
  aspects of communication between the user and the computer. It
  includes the innermost mechanisms of the computer and rises to
  the height of defining a philosophy to guide the interaction
  between human and machine.  Intuition is, above all else, a
  philosophy turned into software.  See the Amiga ROM Kernel
  Reference Manual: Libraries for more information.

  Intuition screens are the basis of any display Intuition can
  make. Screens determine the fundamental characteristics of the
  display such as the resolution and palette and they set up the
  environment for multiple, overlapping windows that makes it
  possible for each application to have its own separate visual
  context.

  Windows are rectangular display areas that open on screens.
  The window acts as a virtual terminal allowing a program to
  interact with the user as if it had the entire display all to
  itself. Windows are moveable and can be positioned anywhere
  within the screen on which they exist.  Windows may also have a
  title and borders containing various gadgets for controlling
  the window.

  Gadgets are software controls symbolized by an image that the
  user can operate with the mouse or keyboard.  They are the
  Amiga's equivalent of buttons, knobs and dials.

  Menus are command and option lists associated with an
  application window that the user can bring into view at any
  time.  These lists provide the user with a simple way to access
  features of the application without having to remember or enter
  complex character-based command strings.

If AmigaGuide displayed the file above, it would appear without any
buttons linking it to text files or databases.  To mark this file as
an AmigaGuide database, add the @DATABASE command.  As mentioned
earlier, it must start on the first line in the first column of the
file.

Since there will be no index for this database, the next command can
be a @NODE.  For AmigaGuide to open a database, it must contain a
node.  Since this will be the first node in the database, it should
be named ``MAIN''.

At the bottom of the file, on a separate line, add the @ENDNODE
command.  This tells AmigaGuide that the current node ends here.  All
nodes must contain an @ENDNODE command.

This is what we have so far:

    @DATABASE
    @NODE MAIN
    What is a user interface? This sweeping phrase covers all
            .
            .
            .
    complex character-based command strings.
    @ENDNODE

The file is now an AmigaGuide database.  However, since the database
has only one node and has no link points, the database will still
appear as plain text.  Also, AmigaGuide will ghost all of the
navigation buttons.  The database can be broken into smaller nodes if
desired.  Normally such a short file would not need to be broken up,
but it makes a good example.

One important issue to consider while designing an AmigaGuide
database is how to lay it out.  Some thought should go into the
break-up of a document into manageable nodes, and how these nodes
relate--and eventually link--to one another.  Each node should
consist of information dealing with one topic and should contain
links to other related nodes.

Notice that the example text is about Intuition, but each paragraph
discusses a different topic of Intuition.  The first paragraph is an
overview followed by four paragraphs: one each on screens, windows,
gadgets and menus.  This organization makes it convenient to make
each paragraph a node with a table of contents in the beginning:

    Intuition Table of Contents

    Introduction
    Screens
    Windows
    Gadgets
    Menus

Since the ``Table of Contents'' node is first, it is the MAIN node.
The other paragraphs follow the MAIN node, each in their own separate
node.  So as not to confuse AmigaGuide, each node within a database
must have a different name.

    @DATABASE
    @NODE MAIN "Intuition Table of Contents"
    Introduction
    Screens
    Windows
    Gadgets
    Menus
    @ENDNODE

    @NODE Intro "Introduction"
    What is a user interface? This sweeping phrase...
    @ENDNODE

    @NODE Screen "Screens"
    Intuition screens are the basis of any display...
    @ENDNODE

    @NODE Window "Windows"
    Windows are rectangular display areas that open...
    @ENDNODE

    @NODE Gadget "Gadgets"
    Gadgets are software controls symbolized by an...
    @ENDNODE

    @NODE Menu "Menus"
    Menus are command and option lists associated...
    @ENDNODE

When AmigaGuide loads the database above, AmigaGuide displays the
MAIN node with the title string ``Intuition Table of Contents'' in
the window's title bar.  As the user clicks the ``Browse'' buttons at
the top of the AmigaGuide window, AmigaGuide steps through each node
in the database, displaying each paragraph.  Notice that each node in
the database uses the window title parameter.  As the ``Browse''
buttons step through the database displaying the different nodes in
sequence, the AmigaGuide window title changes to match the title from
the current node.

An important limitation of the database above is the only way to
access the different nodes is using the ``Browse'' button to step
through them in the order they appear in the database.  The database
still has no buttons within the nodes to link to other nodes.

Using Link Points

The link point command is probably the most commonly used command in
a database.  With it you can make a word in one node reference
another node.  For example, in the ``Table of Contents'' node from
the previous example, you can make each entry from the table into a
button that references its respective node.

The template for a link point is:

    @{<label> <action command>}

The label parameter is the word or phrase in a database that is made
into a button, and the action command is the action AmigaGuide takes
when the user clicks the button.  For our example, we want each topic
in the table of contents to be a label and the action command for
each to be a LINK command.  The LINK command loads and displays
another node.

    @{<label> LINK <name> <line#>}

For example, if you change the word ``Introduction'' from the Table
of Contents node into a link point it would look like this:

    @{"Introduction" LINK Intro}

The <label> string must be in quotes.  If you load the database into
AmigaGuide after making the change above, the word ``Introduction''
would appear as a button on the Table of Contents screen.  If the
user clicks on the ``Introduction'' button, AmigaGuide displays the
node named ``Intro''.

Unlike other AmigaGuide commands, link points do not need to start in
the first column.  This makes it easy to indent a button from the
left edge of the window and also to embed a button within a block of
text.

Link points can also link to nodes in other databases.  As an
example, consider the following excerpt from the ``Intro'' node:

  philosophy turned into software.  See the Amiga ROM Kernel Reference
  Manual: Libraries for more information.

If an AmigaGuide database of Amiga ROM Kernel Reference Manual:
Libraries was readily available,  it would be convenient if the word
``Libraries'' from the excerpt was a button, linking the word
``Libraries'' directly to the Libraries manual database.  If the
Libraries manual database was named Libraries_Manual and it was in
the current AmigaGuide path, to make the word ``Libraries'' from the
``Intro'' node into a link point that opens the Libraries_Manual
database, change the excerpt above to the following:

  philosophy turned into software.  See the Amiga ROM Kernel
  Reference Manual: @{"Libraries" LINK Libraries_Manual/Intro} for more information.

In the example above, when the user selects the ``Libraries'' button,
AmigaGuide will try to display the MAIN node from the database called
Libraries_Manual.  AmigaGuide will first look for Libraries_Manual in
the directory where the example database resides.  If it's not there,
AmigaGuide searches through its path for the database.  Alternately,
you can supply a full path name to Libraries_Manual.

A link point can also be used to display a picture.  For example, to
display an ILBM image of a Workbench screen from the ``Screen'' node,
use the SYSTEM action command:

    @{"Picture of a Workbench Screen" SYSTEM sys:utilities/Display sys:Workbench.pic}

From the command above, when the user click the ``Picture of a
Workbench Screen'' button, SYSTEM executes the Display utility.
Display shows the ILBM file sys:Workbench.pic.  Because Display is
merely a shell command, you can substitute your own ILBM viewer for
Display.

Below is the finished database with a few more interactive link
points.

  @DATABASE
  @NODE MAIN "Intuition Table of Contents"
  @{"Introduction" LINK Intro}
  @{"Screens" LINK Screen}
  @{"Windows" LINK Window}
  @{"Gadgets" LINK Gadget}
  @{"Menus" LINK Menu}
  @ENDNODE

  @NODE Intro "Introduction"
  What is a user interface? This sweeping phrase covers all
  aspects of communication between the user and the computer.  It
  includes the innermost mechanisms of the computer and rises to
  the height of defining a philosophy to guide the interaction
  between human and machine.  Intuition is, above all else, a
  philosophy turned into software.  See the Amiga ROM Kernel
  Reference Manual: @{"Libraries" LINK Libraries_Manual/Intro} for more information.
  @ENDNODE

  @NODE Screen "Screens"
  Intuition screens are the basis of any display Intuition can
  make.  Screens determine the fundamental characteristics of the
  display such as the resolution and palette and they set up the
  environment for multiple, overlapping @{"windows" LINK Window} that makes it
  possible for each application to have its own separate visual
  context.

  @{"Picture of a Workbench Screen" SYSTEM sys:utilities/Display sys:Workbench.pic}

  @ENDNODE

  @NODE Window "Windows"
  Windows are rectangular display areas that open on @{"screens" LINK screen}.  The
  window acts as a virtual terminal allowing a program to interact
  with the user as if it had the entire display all to itself.
  Windows are moveable and can be positioned anywhere within the
  screen on which they exist.  Windows may also have a title and
  borders containing various @{"gadgets" LINK Gadget} for controlling the window.
  @ENDNODE

  @NODE Gadget "Gadgets"
  Gadgets are software controls symbolized by an image that the
  user can operate with the mouse or keyboard.  They are the
  Amiga's equivalent of buttons, knobs and dials.
  @ENDNODE

  @NODE Menu "Menus"
  Menus are command and option lists associated with an
  application @{"window" LINK Window} that the user can bring into view at any
  time.  These lists provide the user with a simple way to access
  features of the application without having to remember or enter
  complex character-based command strings.
  @ENDNODE

Although this is a small sample and only a few basic commands are
used, it is a good start to making your own AmigaGuide database.

The Doctor Is In

To make it easier to create a bug-free database, below is a list of
common mistakes made when editing an AmigaGuide database.

As with any type of programming, errors are bound to crop up.  One of
the most common mistakes is spelling errors.  Always double check
your spelling of commands.  Also, make sure all commands that should
begin in the first column do so.

Symptom:  AmigaGuide displays a database as a text file.  For
example, instead of a button, AmigaGuide displays the link point
command that was supposed to display the button.

Cure: AmigaGuide does not think the file is an AmigaGuide database.
Check that the first line of the file is the @DATABASE command and
that it starts in the first column.

Symptom: When displaying a database node, AmigaGuide displays nothing
in its window.

Cure: Either the @ENDNODE command is not present in the node or the
@ENDCODE command does not start in the first column.

Symptom: AmigaGuide does not display a button or its label.

Cure: The <label> parameter in the link point is missing or not
enclosed in quotes.

Symptom: When the user selects a button, AmigaGuide flashes the
screen and displays the error message ``Couldn't locate <node>''.

Cure: AmigaGuide cannot locate the node specified in the button's
link point command.  If the link point command points to a node in
another database, the database must be in the AmigaGuide path or the
node must contain the full path name to the database.  The link point
command also require a NODE name as the last parameter in the path
separated by a slant (/).  If the file is only text and not an
AmigaGuide database, its path name should end with ``/MAIN''.  If a
node or file has any spaces in its name, the path name must be
enclosed within quotes.

Symptom: AmigaGuide flashes the screen when a button is selected but
displays no error message.

Cure: AmigaGuide does not recognize the <action command> parameter in
the link point, or AmigaGuide cannot locate the specified node (see
the cure above).

Symptom: AmigaGuide does not fully display a button.

Cure: Check that all of the link points end with a closing brace (}).
Note that there is a bug in AmigaGuide that can crash the system if a
link point does not end with a closing brace.

Symptom: AmigaGuide will not load a database and displays a ``Can't
find Node'' requester.

Cure: All databases must contain at least one node.  If the file is
short, all the text can be in one node called ``MAIN''.  If you do
not wish to make the file a database at all, remove the @DATABASE
command.

Symptom: AmigaGuide does not allow the the user to browse the
database to its end.  It either stops browsing before reaching the
last node, or it gets caught in an endless loop, cycling through a
number of nodes.

Cure: At least two nodes within a single database have the same name.
Every node must have a different name unless they are in separate
databases.


VIII-1: Using the Amiga A3000UX as a NFS File Server

By David Miller - Unix Technical Support Specialist, CATS

You've just added an A3000UX to your ethernet and you can rcp and ftp
files between UNIX and AmigaDOS using the AS225 TCP/IP software.  Great!
But what about the AS225's Network File System (NFS) client software?
Under AmigaDOS, the NFS software lets your Amiga mount the drives of a NFS
server as normal DOS volumes, but how do you set up a server?

NFS allows one machine to share files with other machines connected to a
network.  NFS lets multiple machines access the same files, so only one
copy of the data is necessary.  A client machine (a client is any machine
that can mount a shared directory) can free some of its disk space by
moving common programs to the server's disk (a server is any machine that
shares a part of its disk with other machines).

There are however limitations when sharing files between machines with
different operating systems.  For example;

*  Filenames - UNIX S5 filesystem does not support filenames longer than
   14 characters.  If you copy files from AmigaDOS to UNIX, make sure
   that they are unique in the first 14 characters.  And don't forget
   about the ".info" files! If you copy a file that has a ".info" file
   associated with it, be sure that the name preceding the ".info" does
   not exceed 9 characters.

*  Permissions - UNIX files have permissions for read, write, and execute.
   There is no delete permission; if you have write access to the
   directory, you can delete any file it contains.  Script and archive
   bits are not supported either, so setting the script or archive bits,
   or clearing the delete bit will not work.

*  Filenotes - UNIX does not support filenotes.  If you copy a file from
   an AmigaDOS filesystem to a UNIX filesystem, any file notes will be
   lost. Likewise, you cannot add a comment to a file on a UNIX
   filesystem.  You will not receive any error indication, but the
   operation will have no effect.

The following notes will walk you step-by-step through the process of
configuring and administering NFS on the A3000UX.  If you have used NFS
before with BSD, Sun/OS, Ultrix, or any other operating system, you should
at least skim over these notes, because the implementation is different
under UNIX SVR4.

To keep this article brief, I'm making the following assumptions:

    *  You know how to use one of the editors shipped with Amiga UNIX.
    *  You know how to log in as root or how to su to root.

If you don't, read the Learning Amiga UNIX and Using Amiga UNIX manuals
which come with the  A3000UX.

The five examples illustrate how to do some simple file sharing with NFS.
Using the concepts discussed in these examples you will be able to select
the options necessary to share files while maintaining system security and
integrity.  But, first, you need to start the networking software on the
A3000UX, if it's not already running.  To do this, type the following:

    # init 3

This changes the operating to ``run-level'' 3, the networking run-level.
Other run-levels include:

      S - single user maintenance mode
      0 - system power off
      1 - single user mode
      2 - multiuser mode w/o networking
      3 - multiuser mode w/ networking
      4 - user defined
      5 - system reboot
      6 - system reboot

To find out what your machine's current run-level is, type:

    # who -r

The output will look something like this:

    run-level 3  Jun 18 18:40    3    0    S

Here's what all of that means:

                 run-level 3  Jun 18 18:40    3    0    S
                 -----------  ------------    -    -    -
                      |            |          |    |    |
    This is the   ____|            |          |    |    |
    current state                  |          |    |    |
    of your machine                |          |    |    |
                                   |          |    |    |
    This is when the current ______|          |    |    |
    run-level was entered                     |    |    |
                                              |    |    |
    This is the current run-level ____________|    |    |
                                                   |    |
    This is the number of times                    |    |
    your machine has been in this _________________|    |
    run-level before.                                   |
                                                        |
    This is the previous run-level _____________________|

This is the host table (/etc/inet/hosts on Amiga UNIX and INET:db/hosts on
AmigaDOS) that I'll be using for the examples:

    #
    #       TCP/IP HOST TABLE
    #
    #
    127.0.0.1       localhost loghost loopback me
    #
    #
    #       Widget works engineering network
    #
    #
    # IP Number     Name          Nickname      Comment
    #
    192.9.120.1      Hydrogen       H           # A3000UX - in comp center
    192.9.120.2      Helium         He          # A2000   - in room 316
    192.9.120.3      Lithium        Li          # A2500   - in room 321
    192.9.120.4      Beryllium      Be          # A3000   - in room 320
    192.9.120.5      Boron          B           # A2500   - in room 119
    192.9.120.6      Carbon         C           # A2000   - in room 119
    192.9.120.7      Nitrogen       N           # A2000   - in room 204
    192.9.120.8      Oxygen         O           # A3000   - in room 220
    192.9.120.9      Fluorine       F           # A2500   - in room 132
    192.9.120.10     Neon           Ne          # A3000   - in room 307

The host table contains a list of IP addresses with node names for each of
those addresses.  The machine uses this list to find other nodes by their
name, rather than their numeric IP address.

Example 1
---------

Hydrogen has a directory called /home/scratch which is for temporary
storage. Everyone should be able to read and write in this directory.  To
share this with the rest of the net, the administrator of Hydrogen would
type:

    share -F nfs -o rw /home/scratch

where:

            share  is the command to share files between hosts.
           -F nfs  tells the program share to use the NFS filesystem.
            -o rw  tells the program share to allow all systems both
                     read and write access to the shared files.  This
                     is the default if you don't supply any options.
                     I've just included it here for completeness.
    /home/scratch  is the directory to be shared.

Example 2
---------

Hydrogen also has a large disk attached as /storage.  To allow other hosts
to use this as extra disk space type the following:

    share -F nfs -o rw=Helium /storage/Helium
    share -F nfs -o rw=Lithium /storage/Lithium
            ...
    share -F nfs -o rw=Ne /storage/Neon

where:

       -o rw=name  tells share to allow <name> to mount this resource
                     and to deny access to everyone else.

This establishes private storage areas for each host.  This way all of the
hosts can share the disk without having their files readable by everyone
on the network.

Note the use of the nickname Ne for the host Neon.  Nicknames must be
explicitly entered in the host table and may be used interchangeably with
the full name of the host.

Example 3
---------

A group of hosts on the first floor of your building are all being used on
one big project, so they need a common work area to store files.  The
administrator could create a work area in /storage called, for example,
ff-project, for first-floor-project, then give the hosts on the first
floor access to this work area by typing:

    share -F nfs -o rw=Boron:Carbon:Fluorine /storage/ff-project

where:

    -o rw=name[:name]...

allows read and write access to the hosts that are listed and denies
access to everyone else and

    /storage/ff-project

is the name of the directory to share.

Example 4
---------

Hydrogen has a directory called /home/public which is full of useful Amiga
tools.  To share these with the rest of the net, the administrator of
Hydrogen would type:

    share -F nfs -o ro /home/public

where:

    -o ro

tells share to make the shared filesystem readable to all hosts and
writable by no one.  The ``ro'' stands for ``read-only'' and

    /home/public

is the name of the directory to share.

The files are shared read-only for two reasons.  The first is that it
prevents temporary files from being created in the shared partition.  Also
it prevents accidental or malicious removal of shared files.

Example 5
---------

Now, coincidentally, Hydrogen also has a directory called /home/private
which is full of special tools used only by the development staff on the
3rd floor. To share these exclusively with the hosts on the third floor,
the administrator of Hydrogen would type:

    share -F nfs -o ro=He:Li:Be:Ne /home/private

where:

    -o ro=name[:name]...

tells the share program to give the listed hosts read access to the shared
files.  All other hosts will be denied access to the shared files (Note
the use of nicknames) and

    /home/private

is the name of the shared filesystem.

These options may be combined to allow different types of access.  For
example:

    -o rw=Helium:Neon,ro

Everyone can read shared files, but only Helium and Neon have write access.

    -o rw,ro=Fluorine

Everyone except Fluorine may read and write files.  Fluorine may only read
files.

    -o rw=C:O,ro=N

Carbon and Oxygen have read and write access, Nitrogen has read access,
and the others have no access.

To summarize:

    -o ro      Gives everyone read-only access to the shared files
    -o rw      Gives everyone read/write access
    -o ro=...  Gives read-only access to the listed hosts
    -o rw=...  Gives read/write access to the listed hosts

If a host appears in both a rw= and a ro= list, the host will be given
read and write access.  The ordering of the options does not matter.

Since you probably want these directories to be shared automatically every
time you start Amiga UNIX, you need to perform the following steps:

1. Edit the file /etc/inittab and change the line:

         is:2:initdefault
     to
         is:3:initdefault

     This will make your machine go directly to run-level 3 when you boot
     the UNIX Operating System.

2. Edit the file /etc/dfs/dfstab, and enter one line for each directory
   to be shared.  For Example 1 above, this would be the line:

         share -F nfs -o ro /home/public

     So, the complete dfstab for the 5 examples given above would look
     something like this:

         #
         # For Example 1
         #
         share -F nfs -o rw /home/scratch

         #
         # For Example 2
         #
         share -F nfs -o rw=Hydrogen /storage/Hydrogen
         share -F nfs -o rw=Helium /storage/Helium
         share -F nfs -o rw=Lithium /storage/Lithium
         share -F nfs -o rw=Beryllium /storage/Beryllium
         share -F nfs -o rw=Boron /storage/Boron
         share -F nfs -o rw=Carbon /storage/Carbon
         share -F nfs -o rw=Nitrogen /storage/Nitrogen
         share -F nfs -o rw=Oxygen /storage/Oxygen
         share -F nfs -o rw=Fluorine /storage/Fluorine
         share -F nfs -o rw=Neon /storage/Neon

         #
         # For Example 3
         #
         share -F nfs -o rw=Boron:Carbon:Fluorine /storage/ff-project

         #
         # For Example 4
         #
         share -F nfs -o ro /home/public

         #
         # For Example 5
         #
         share -F nfs -o ro=He:Li:Be:Ne /home/private

3. Run the command:

         shareall -F nfs

     which will share all of the NFS filesystems, and the command:

         unshareall -F nfs

     which will make the NFS filesystems unavailable.

For those interested in more information on UNIX SVR4 networking, either
as a user or an administrator, UNIX System V Release 4 - Network User's
and Administrator's Guide, published by Prentice Hall is an excellent
starting place.

If you have any suggestions for the new Amiga UNIX section of Amiga Mail,
please send it to me either via email:

        davidm@cbmvax.commodore.com
                or
        ...!{rutgers,uunet}!cbmvax!davidm

or US Mail:

        ATTN:  David Miller
        Commodore Applications and Technical Support
        Commodore Business Machines, Inc.
        1200 Wilson Drive
        West Chester, PA 19380

or FAX:

        David Miller
        Commodore Business Machines
        +1 215 431 9156

or BIX:

        david.miller


VIII-9: Keeping Time--Interval Timers in Amiga UNIX

By David Miller

The Sleep() function
--------------------

When you want your program to pause for a number of seconds then continue,
you will typically use the sleep(3) function (the notation NAME(SECTION#)
refers to the manual page NAME in the SECTION# chapter of the UNIX
Reference Manuals; section 1 is commands, section 2 is system calls, and
section 3 is library functions).  There is also a sleep(1) program which
provides the same function to shell scripts.  For example:

In C:

    main()
    {
            printf("Hello world!\n");
            sleep(5);
    }

Shell:

    #!/usr/bin/sh

    echo "Hello world!"
    sleep 5

The following example is an implementation of the sleep(3) function.

Example 1: SLEEP() Using ALARM()
--------------------------------

     1  # include       <signal.h>
     2  static void trap ()
     3  {
     4  }
     5  unsigned sleep ( unsigned duration )
     6  {
     7          void            (*oldsig)();
     8          unsigned        oldtime;
     9          oldsig = signal(SIGALRM, trap);
    10          oldtime = alarm(0);
    11          if (oldtime && oldtime < duration)
    12                  alarm(oldtime);
    13          else
    14                  alarm(duration);
    15          pause();
    16          signal(SIGALRM, oldsig);
    17          if (oldtime > duration)
    18                  alarm(oldtime - duration);
    19          if (oldtime && oldtime < duration)
    20                  return(duration - oldtime);
    21          else
    22                  return 0;
    23  }

   Line            Explanation
   ----            -----------
      1   The file signal.h defines the parameters for the signal(2)
          function.

    2-4   trap() is the simple signal handler that just sets a flag that
          another piece of code will examine.

      5   Define the sleep() function.

    6-8   oldsig is a variable that will be used to save the previous
          state of the signal handler; oldtime will be used to save the
          state of the alarm clock.

      9   Establish trap() as the current signal handler for the alarm
          signal.  The previous handler is saved in oldsig.

     10   Clear the alarm clock, saving the current state.

  11-14   If the previous setting of alarm was sooner than duration, use
          the old value, otherwise use duration to set the alarm.

     15   Pause the process until the alarm goes off.

     16   Restore the old signal handler.

  17-18   If the old alarm setting was later than duration, reset the
          alarm with the difference between duration and oldtime (the
          time remaining until the previous alarm).

  19-22   If an existing alarm is making sleep return early, return the
          time remaining on the requested sleep.

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

To schedule its ``wake up'' time, sleep(3) uses the alarm(2) system call.
The alarm(2) system call asks the OS to deliver a signal (basically a
software interrupt) in some number of seconds according to the system
clock. However, setting an alarm for 2 seconds does not mean that you will
receive an alarm signal in exactly two seconds.

The OS processes alarm requests once every second.  Each time an alarm
request is processed, the number of seconds remaining for that alarm is
decremented by one.  When the number of seconds remaining reaches zero,
the OS delivers a signal to the process.  Given this, if a process places
a 1 second alarm request 1 microsecond before the OS does its alarm
processing, the signal will arrive in 1 microsecond, not in 1 second.  An
alarm set for N seconds actually means:

    deliver a signal after N-1 seconds, but before N seconds.

If you'd like to see for yourself, try running this shell script:

    $ for i in 1 2 3 4 5 6 7 8 9 10
    > do
    >       time sleep 2
    > done

How many times did the process actually take more than 2 seconds?  If you
try it with both the Korn shell, ksh(1), and the System V shell, sh(1),
you'll find that under ksh(1) it takes about 1.2 seconds and under sh(1)
it takes about 1.8 seconds (There is a difference because sh(1) counts the
time required to start the sleep process whereas ksh(1) only counts the
actual running time).  The sleep(1) program rarely, if ever, actually
sleeps for 2 seconds.

If you are writing a daemon that checks for some event every 5 minutes, or
if you want to pause the output to give the user a chance to read it,
alarm's 1 second granularity is fine.  But what about that daemon that
needs to wake up every second?  Waking up after 1 microsecond could cause
the process to run almost continuously.  For any sort of realtime
processing, one second is a very long time.  So how do you sleep for less
than one second reliably?

The answer is do not use an alarm, use an interval timer.

Interval Timers
---------------

Each interval timer has a resolution of 1 tick of the system's clock, or 1
microsecond (whichever is larger).  Additionally, you can configure an
interval timer to automatically restart itself.  The system provides each
process with three independent interval timers:

ITIMER_REAL
-----------
    This timer will count down in real time.  That is, this timer will
    continue to run when your process is waiting for the OS to perform a
    system call, or when the OS preempts your process.  When the timer
    expires, the OS will deliver a SIGALARM signal.

ITIMER_VIRTUAL
--------------
    This timer counts down only when your process is running.  If your
    process makes a system call, or is preempted, this timer will stop
    counting.  The timer will resume when your process resumes execution.
    When this timer reaches zero, the process will receive a SIGVTALRM
    signal.

    Possible uses for this timer include checkpointing (saving data after
    some period of execution) and multithreading.  The virtual timer is
    more desireable for these applications since it counts only when the
    process is running; there is no reason to perform a checkpoint or
    switch threads if the process has been idle.

ITIMER_PROF
-----------
    This timer will stop counting any time your process is preempted by
    the OS, but will not stop when the process is waiting for a system
    call to return.  When it expires the OS generates a SIGPROF signal.

    This timer is designed to be used for execution profiling by
    interpreters. By having a profiling timer send a signal every second,
    or fraction of a second, and examining the current position in the
    interpreted code, the process can determine where the most execution
    time is being spent.

All three timers operate on the following structure:

    struct itimerval
    {
            struct timeval it_interval;
            struct timeval it_value;
    }

The timeval structure looks like this:

      struct timeval
      {
            long tv_sec;
            long tv_usec;
      }

Both of these structures are defined in the <sys/time.h> include file.

    Note that System V Release 4.0 does not guarantee that these are the
    only members of these structures, nor that they will occur in this
    order.  You must initialize the members individually.  This can be
    annoying and tedious, but it allows the structure to be expanded in
    future releases.

You set and examine timers using these two functions:

    int getitimer(int which, struct itimerval *myvalue)

places the current timer setting into myvalue

    int setitimer(int which, struct itimerval *myvalue, struct itimerval *myovalue);

sets the timer.  It gets the new time from myvalue and places the previous
setting in myovalue.

Now, let us take a look at the sleep function again.  The code in example
2 creates a new version of sleep that will sleep an exact number of
seconds.

Example 2: SLEEP() Using an Interval Timer
------------------------------------------

     1  # include       <signal.h>
     2  # include       <sys/time.h>
     3  static void trap ()
     4  {
     5  }
     6  unsigned mysleep ( unsigned duration )
     7  {
     8         void                    (*oldsig)();
     9         struct itimerval        oldtime;
    10         struct itimerval        newtime;
    11         oldsig = signal(SIGALRM, trap);
    12         getitimer(ITIMER_REAL, &oldtime);
    13         if (oldtime.it_value.tv_sec == 0
                        && oldtime.it_value.tv_usec == 0
                        || oldtime.it_value.tv_sec >= duration)
    14         {
    15                 newtime.it_interval.tv_sec = 0;
    16                 newtime.it_interval.tv_usec = 0;
    17                 newtime.it_value.tv_sec = duration;
    18                 newtime.it_value.tv_usec = 0;
    19                 setitimer(ITIMER_REAL, &newtime, NULL);
    20         }
    21         pause();
    22         signal(SIGALRM, oldsig);
    23         if (oldtime.it_value.tv_sec > duration)
    24         {
    25                 oldtime.it_value.tv_sec -= duration;
    26                 setitimer(ITIMER_REAL, &newtime, NULL);
    27         }
    28         if (oldtime && oldtime < n)
    29                 return(n - oldtime);
    30         else
    31                 return 0;
    32  }

  Line        Explanation
  ----        -----------
   1-2    The file signal.h defines the parameters of the signal(2)
          function.  The file <sys/time.h> defines ITIMER_REAL and the
          structures used by getitimer(3) and setitimer(3).

   3-5    trap() is the simple signal handler that just sets a flag that
          another piece of code will examine.

   6-7    Define the mysleep() function.

  8-10    oldsig will hold the previous state of the signal handler;
          oldtime will hold the state of the timer; and newtime will be
          used to set the new timer parameters.

     11   Establish trap() as the current signal handler for the alarm
          signal.  The previous handler is saved in oldsig.

     12   Fetch the current settings of the timer.

  13-20   If the timer was idle (both parts of it_value are zero) or it
          is set to go off later than duration (it_value.tv_sec is greater
          than duration), set the timer to go off in  duration seconds.

     21   pause(2) the process until the timer expires.

     22   Restore the old signal handler.

  23-27   If the old timer setting was later than duration, reset the
          timer with the difference between duration and
          oldtime.it_value.tv_sec (the time remaining until expiration of
          the previous setting).

  28-32   If an existing timer is making mysleep() return early, return
          the time remaining on the requested mysleep().

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

This example uses what is called a ``one-shot'' timer.  The timer goes off
once, and then stops.  By supplying an interval setting, the timer becomes
a clock, generating alarm signals on a regular basis.

The code fragment in Example 3 shows how to set the timer to produce a 1.5
second clock that will start ``ticking'' in 1 minute.

Example 3: Using an Interval Timer as a Clock
---------------------------------------------

     1  # include       <sys/time.h>
     2  ...
     3          {
     4                  struct itimerval        newtime;
     5                  newtime.it_value.tv_sec = 60;
     6                  newtime.it_value.tv_usec = 0;
     7                  newtime.it_interval.tv_sec = 5;
     8                  newtime.it_interval.tv_usec = 500000;
     9                  setitimer(ITIMER_REAL, &newtime, 0);
    10          }
    11  ...

  Line        Explanation
  ----        -----------
     1   The file <sys/time.h> defines ITIMER_REAL and the structures
         used by getitimer(3) and setitimer(3).

     2   Other code.

     3   Start of block.

     4   Structure newtime will hold the setting for the timer.

   5-6   Set it_value to expire in 1 minute.

   7-8   Set it_interval to reload it_value with 5 seconds and 500,000.
         microseconds (one half of a second).

     9   Load the new settings into the ITIMER_REAL timer.

    10   End of block.

    11   Other code.

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

When the time interval specified by it_value expires, the contents of
it_interval is copied into it_value and the timer is restarted.  If the
interval specified by it_interval is zero, the timer stops.  Timers can be
stopped at anytime by calling setitimer(3) with the members of it_value
set to zero.

So there you have the realtime interval timer.  The other timers work
exactly the same way, varying only in when the timer is running.  For more
information on interval timers see UNIX System V Release 4 - Programmer's
Reference Manual, published by Prentice Hall.  Next time, we'll explore
context switching, multithreading, and light weight processes.


VIII-17: Developing Network Applications for the Amiga

by Dale Larson

When you run a wire between two or more computers, you have a network.
Big Deal.  When your applications use that wire however, you have a
revolution. Although some of the following software is only internal or
experimental, these are things I can do now with my Amiga, with software
that I have now:

    * From my Amiga, I can transparently access filesystems on Suns,
      on the local Vax system (cbmvax), and on other Amigas.

    * Whenever I print, I send my files to a network printer.

    * I continuously receive mail on my Amiga--from as far as
      Seattle, Sydney and Denmark, and near as a desk next to mine.

    * Every night when I go home, my Amigas at work (and several
      others) are used to do distributed graphics rendering.  The
      process is started over the network and all data is sent over
      the network.  A picture that would have taken a week can be
      finished overnight.

In the scheme of what is possible, this is only the tip of the iceberg.

    * In a high school environment, a network could allow students
      to interactively participate in computer simulations.  It could
      allow them to collaborate electronically.  It could allow
      teachers to electronically monitor and assist students.  It
      could save schools money because peripherals such as printers,
      hard-drives and CD-ROMs could be easily shared.  Even the
      computational power of one expensive machine could be shared by
      the students.

    * A small office can use a network for an email-like facility
      for phone messages and other notes.  Another application might
      replace the intercom. Form letters can be kept in a central
      database accessed by a word processor.  A distributed
      appointment calendar could allow a secretary to add a new
      appointment even as the boss is looking at what his afternoon
      schedule is.  A distributed database application would allow
      access to such things as a central client database, outstanding
      orders and the present inventory.

    * Imagine multi-player games that use the computational power of
      each machine connected by a high speed Local Area Network (LAN).

    * In a software development environment, several programmers can
      work on the same project, updating the same sources.  Debugging
      information could be sent over the network, or a debugger on one
      machine could control the programs on others (For example, there
      is a version of Wack that runs over a network).

    * Multimedia applications might do any number of exciting things
      with the network.  A few of the applications which have been
      experimented with on other machines are: real-time audio and
      video conferencing, interactive demos for groups, and shared
      electronic blackboards.

In much the same way as all applications are candidates for a GUI
interface, all applications are candidates for becoming network
applications.  The GUI has only changed the ways in which people interact
with their computers.  Networks will change the ways in which people
interact with each other.

This article introduces some of the principles of writing network programs
using the AS225's Berkeley Socket interface.  Even more so than in most of
software development, networking seems simple in theory, but, in reality,
gets complicated in a hurry.  To develop network software for AS225, you
will need to obtain the Network Developer's kit from CATS.  It has all the
necessary include files and Autodocs to develop for the AS225's
socket.library.  Also, you should plan read at least some of the material
in the "References" section of this article.

 Protocol Layers and the Berkeley Sockets Interface
 Network Applications
 Application Protocols
 Kinds of Servers
 Addresses
 Finding Servers
 Reserved Ports
 Skeleton for Applications Using TCP (connection-based)
 Skeleton for Applications Using UDP (connectionless)
 Which Protocol Is Right For My Application?
 The Shared Socket Library
 References


Protocol Layers and the Berkeley Sockets Interface

Network applications should always be written to the Application
Programmer's Interface (API) of a particular protocol, not to the network
hardware.  Network standards usually include several protocols layered one
on top of another. These groups are often referred to as protocol stacks.
At the lowest level, one of the protocols must interface to some network
hardware.  Each layer adds some abstraction to using the network on a
lower level.  This serves to make it easier to program network software as
the developer doesn't have to deal with networking details that are well
below the level of the software under development.

The International Standards Organization (ISO) has created a reference
model on which to base new network layerings.  The ISO 7-Layer Reference
Model of Open Systems Interconnection looks like this:

                 ------------------------------------
                | 7  Application                     |
                |------------------------------------|
                | 6  Presentation                    |
                |------------------------------------|
                | 5  Session                         |
                |------------------------------------|
                | 4  Transport                       |
                |------------------------------------|
                | 3  Network                         |
                |------------------------------------|
                | 2  Data Link (Hardware Interface)  |
                |------------------------------------|
                | 1  Physical Hardware Connection    |
                 ------------------------------------

                     ISO-7 Layer Reference Model

The only protocol stack for the Amiga which is currently available from
Commodore is TCP/IP.  Our AS225 software package includes the standard
TCP/IP protocols and several standard Internet applications.  It has the
same API as most Unix machines running TCP/IP using the Berkeley Sockets
interface.

Unix was designed to have a common method of accessing both files and
devices. Before a Unix application can perform any I/O operations on a
file, it has to open() it.  The Unix open call returns an integer called a
file descriptor that corresponds to the open file.  The application uses
this file descriptor to manipulate the file.

This method of I/O is not quite general enough for networking.  Instead,
there is the Berkeley Sockets interface.  A socket is an entity used to
send and receive data across a network.  A socket can be "plugged in" or
bound directly to the socket of some other application on another machine
somewhere on the network.  Like the Unix file system, applications access
their sockets using a file descriptor, although it is typically referred
to as a socket descriptor.

Thousands of network applications have been written to the socket
interface. AS225 has been shipping since December, 1990, and everything
needed to write network applications for AS225 is included on the 1991
DevCon disks and on the Network Developer's Disk.

On the Amiga, layers 1 and 2 should always be the network hardware and
SANA-II Network Device Driver (SANA-II defines the lowest level software
interface to networking hardware).  In AS225, layer 3 is the IP and ICMP
protocols of the TCP/IP protocol stack.  These protocols aren't used
directly by application developers.  Essentially, they handle machine to
machine communication.  The transport layer uses the network layer (and
the layers below it) to provide communication between individual processes
on different machines.  Most current network applications use transport
protocols.  The transport protocols in TCP/IP are TCP and UDP.

The TCP transport protocol is a connection-oriented, stream protocol.
Basically, the socket of one application connects to the socket of another
application and they communicate across the network in data streams.  The
two applications can be running on arbitrary machines on a network.  The
big plus of using TCP is that it is a reliable protocol.  If the data is
put in one end of a TCP stream, it either gets to the other end intact, or
not at all (which causes an error at the sender's end).  This makes it
easier to program applications because the application programmer does not
have to worry about packet corruption.

UDP is a connectionless, datagram protocol.  An application using UDP
sends datagrams to some other application on the network.  A datagram is a
fixed-length message.  Because the sockets of UDP applications are not
connected, a datagram sent from a socket can be sent to an arbitrary UDP
socket.  Unlike TCP, UDP is not a reliable protocol, so an application
that uses UDP has to account for errors that can occur during transmission.

The details of all the various protocols and how they behave are quite
complex and are beyond the scope of this article.  This article deals with
the difference between connection-oriented stream protocols (sockets which
are obtained as type SOCK_STREAM) and connectionless datagram protocols
(type SOCK_DGRAM).

The Amiga Shared Socket Library (socket.library) is Commodore's
implementation of the standard functions for manipulating, sending data
to, and receiving data from sockets.  Other network APIs for TCP/IP have
been written for other platforms (most notably TLI on Unix SVR4 systems).
Programs written using sockets on one machine can communicate just fine
with programs written using another API (i.e., TLI) on another machine.
Sockets are not specific to TCP/IP.  They can be used with different
"domains".  TCP/IP is one domain, another network protocol is another
domain and local Inter-Process Communication (IPC) is yet another.  Our
socket library currently supports only TCP/IP.

Layers 5 and 6 of the OSI model, the presentation and session layers, do
not exist in TCP/IP, or most other protocol stacks.  So with TCP/IP on the
Amiga, the protocol stack looks like this:

                 -------------------------------------------
                | Application                               |
                |-------------------------------------------|
                | Transport (TCP, UDP)                      |
                |-------------------------------------------|
                | Network   (IP, ICMP)                      |
                |-------------------------------------------|
                | Data Link (SANA-II Network Device Driver) |
                |-------------------------------------------|
                | Hardware  (ethernet, arcnet, ...)         |
                 -------------------------------------------

                           TCP/IP Protocol Stack

In spite of the fact that protocols come in a stack, your application will
only come into direct contact with a protocol at the top of the stack.  In
the case of TCP/IP, this is the transport layer.  In theory, you are not
required to know protocols below the one used for your application.  In
practice, higher-level protocols are often described in terms of additions
to lower-level protocols.


Network Applications

Most network applications are built around a client/server model.  In the
client/server model, a server application runs on one machine somewhere on
a network.  That server waits for a request for a particular service it
provides. These requests come from client applications that are running on
other machines on the network.  A service can be as simple as echoing back
text sent to the server or as complex as providing a remote login
facility.  For example, the ftp (File Transfer Program) application copies
files between networked machines.  Ftp actually consists of two programs,
a client and a server.  The server waits around for a client to request
some service, like listing a directory or transferring a file.

On most networks, each machine is capable of running both client and
server programs simultaneously, but on some networks a machine is either a
client or a server and may only run programs of that type.  The focus of
this article is peer-to-peer networks (the former), not client-server
networks (the latter).


Application Protocols

Every networked program must agree on how to send data across the network
and on what meaning to attach to that data.  Therefore, the application
itself has a protocol.  This is the application layer of the ISO reference
model and TCP/IP protocol stack.  The application-specific protocol can
include such things as what transport protocol will be used, what
initialization takes place, how any security is implemented, what format
data will be in, etc.

For standard Internet applications (ftp for example), the application
protocols are specified in detail in one or more reference documents
called Requests for Comments, or RFCs.  RFCs are the specifications for
Internet protocols and standard applications.  Even if you aren't
implementing a standard Internet application, the RFCs offer insight into
the complexities of application protocols and how they should be
specified.  See the "References" section of this article for more
information on RFCs and standard Internet applications.

Normally application protocols are general enough that network
applications can be ported to any machine which supports the network
protocol.  Neither the client nor the server knows (or cares) what type of
machine is at the other end.  Sometimes only one half of the application
(client or server) is available for a given machine.  For example, the
currently released version of AS225 includes an NFS (Network File System)
client program, but no NFS server program.  To use NFS with AS225 requires
access to any machine with an NFS server--it does not require any
particular type of machine.


Kinds of Servers

There are two kinds of servers.  Those which process one request at a time
are called "iterative servers".  Those which simultaneously service
multiple requests (often by spawning a process to handle each request) are
called "concurrent servers".  Iterative servers are generally easier to
write, but are only suitable for services which can be handled quickly
and/or will not be accessed by multiple clients.  Applications which use
connectionless protocols (UDP) frequently have iterative servers, while
applications with connection-oriented protocols (TCP) usually have
concurrent servers.


Addresses

All data on the network is sent to and from network addresses.  There are
many different types of network addresses, at least one type for each
layer of the protocol stack.  For example, the Network layer of the TCP/IP
protocol stack uses the IP and ICMP protocols which use 32-bit internet
addresses (which are usually represented in "dotted decimal notation"
e.g., 192.9.210.4) to talk to a specific machine at a specific
internet-style address.  When applications communicate with each other,
they usually use a transport layer protocol, therefore the data is sent
from one transport address to another.  A transport address generally
corresponds to a specific program running on a specific machine somewhere
on a network.

A transport address consists of three parts: a protocol, a host address,
and a process association.  In AS225, the protocol in a transport address
is either TCP or UDP.  The host address is dependent upon the protocol,
but in AS225, the host address is always the internet address of the host.
The process association is also protocol dependent, and in AS225, the
process association is a port number.  TCP/IP port numbers are 16-bit
integers that are used by the transport protocols on each host to direct
network traffic to a specific process running on the machine at that
internet address.

The set of port numbers is unique to each protocol.  For example, port
number 42 for UDP might belong to a different process than that which
belongs to port number 42 for TCP.  Without port numbers, multiple network
programs could not run simultaneously.

Transport protocols are analogous in some ways to Amiga Exec devices.  In
such an analogy, there is a TCP device and a UDP device.  Each device has
about 65,000 units and none of the units can be opened in shared mode.

Once a socket is created, it has to be bound to a transport address.  An
application binds an address to a socket in one of two ways.  The binding
can be made explicitly by the program to a specific transport address
(using the bind() call).  Servers normally use this type of binding.  In
this case, the server uses a preset, "well-known" port number in its
transport address.  The port number is well-known because all of the
server's possible clients know what that particular server's port number
is.   Because these clients know the server's port number, the clients can
construct a transport address for that particular service on any machine
that runs that server.  For example, the default, well-known port number
for ftp is 21.  If a client wants to use ftp to transfer files from a
machine at the internet address 192.9.210.4, it can use ftp's port number,
the machine's internet address, and the protocol (ftp uses TCP) to find
the ftp server at 192.9.210.4.  As long as there is an ftp server running
at 192.9.210.4, the client should have no problem finding the server. This
type of socket is analogous to a public message port.

The other way to bind a socket to a transport address is to let the socket
library arbitrarily choose a port number for the application.  Normally
client applications bind this way because a client does not need a
well-known address. The client supplies the server with its transport
address when it sets up communication with the server.  This type of
socket is analogous to a private Exec message port.


Finding Servers

A client "finds" its server by the server's transport address.  As was
mentioned eariler, the transport address consists of a protocol, a host
address, and a port number.  For the TCP/IP protocol stack, the protocol
is either TCP or UDP.

The next thing the client needs to build after the transport address is an
internet address for the server's machine.  Normally the client obtains
that address from the user.  The address can be in one of two forms, an
internet address (in dotted decimal notation), or a host name which is an
ASCII string that corresponds to the host's internet address.  If the
client gets a host name, it asks the socket.library what internet address
corresponds to the host name.

When a server starts, it opens a socket and bind()s that socket using the
server's well-known port number.  There are two ways for the server's
well-known port to become well-known:

  1) A server's well-known port number can be hard-coded into both the
     client and server.  This is recommended for prototyping new programs,
     but is a Very Bad Thing for programs which will be distributed.  The
     port number is arbitrary, but must not be one of the reserved ports
     (see the next section) and must not conflict with a port number
     already in use.

  2) Port numbers can be configurable.  All distributed network
     applications should use configurable port numbers.  In programs
     written for AS225, you should use the inet:db/services file to
     configure a port number.  The function getservbyname() accepts a
     protocol (UDP or TCP) and the name of a well-known server and returns
     the port number of that service.  This requires you to configure your
     application by adding an entry to the inet:db/services file on every
     machine which will use the application.  Many standard Internet
     applications and Unix remote services are already in the
     inet:db/services file that comes with AS225.  If your application
     isn't already included, your installation scripts should add the
     entry for your application to inet:db/services.  Offer a default
     value, but let your user actually pick the number since your port
     number must not conflict with another (pre-existing) port number.


Reserved Ports

Port numbers 1-255 are reserved for standard Internet applications (like
ftp) and port numbers 256-1023 are reserved for standard Unix remote
services (which are often available for machines other than Unix).  You
should never choose any of these port numbers for your application unless
it is an implementation of a standard for which the port number is
reserved.  For more information on port numbering and reserved ports, see
the "References" section at the end of this article.


Skeleton for Applications Using TCP (connection-based)

Aside from the special quirks of the socket.library (which is discussed in
the "Shared Socket Library" section below), the basic outline of the core
of most client/server model applications written with TCP starts with the
server:

Create a socket:

    int socket(int family, int type, int protocol)

Where family specifies the protocol family (which for the TCP/IP protocol
stack is AF_INET from <sys/socket.h>), type specifies the abstract type of
communication (either SOCK_STREAM for TCP or SOCK_DGRAM for UDP), and
protocol is not generally used in the TCP/IP protocol stack and should be
set to zero. If socket() fails, it returns a -1, otherwise it returns a
socket descriptor.

Next, get the well-known port number of the server's service:

    struct servent *getservbyname(char *family, char *service)

where family is one of two strings, "tcp" or "udp".  The service argument
is the name of the service that this server provides.  The function
returns a NULL if there was an error.  Otherwise, it returns pointer to a
servent structure (from <netdb.h>):

    struct  servent {
        char   *s_name;      /* official service name */
        char   **s_aliases;     /* alias list */
        int    s_port;       /* port # */
        char   *s_proto;     /* protocol to use */
    };

Next, build a sockaddr_in (from <netinet/in.h>) structure using the port
number from the s_port field of the servent structure returned by
getservbyname():

    struct in_addr {
        u_long s_addr;
    };

    struct sockaddr_in {
        short     sin_family;        /* address family.  Make this
                                        AF_INET for TCP/IP */
        u_short   sin_port;          /* the port number (the value from
                                        servent.s_port)    */
        struct    in_addr sin_addr;  /* internet address. For TCP/IP, make
                                        sin_addr.s_addr INADDR_ANY.  Bind
                                        will know what to do with this. */
        char      sin_zero[8];       /* unused by TCP/IP */
    };

The sockaddr_in structure is a TCP/IP specific version of the sockaddr
structure.

Now give the sockaddr_in to bind() in order to attach a specific address
to the socket:

    int bind(int servsocket, struct sockaddr *name, int namelength)

where, servsocket is the socket descriptor of the socket that needs a
specific address, name is a pointer to the sockaddr structure (or, for
TCP/IP purposes, a sockaddr_in structure) that describes the address, and
namelength is the length of the sockaddr structure.

Once the socket is bound to an address, the server calls listen() to
indicate that it is waiting to receive connections.

The server is ready to start its main processing loop.  The accept()
function waits for and accepts a new connection at a socket:

    int accept(int servsocket, struct sockaddr *name, int namelength)

where, servsocket is the socket (descriptor) on which the server is
waiting for connections, name points to a buffer where accept() copies a
sockaddr structure describing the client that is trying to connect to the
server, and namelength is the length of the name buffer.

If accept() fails, it returns a negative value, otherwise accept() returns
a socket descriptor of a new socket that is connected to the client's
socket.

The server can communicate with the client using the new socket while it
continues to listen to its original socket for new connections.  The
server may serve one client at a time (an iterative server), or give the
new socket (the one returned by accept()) to a new process so it can
handle talking to the client (a concurrent server).

Setting up the client is similar to setting up the server.  You have to
create a socket, find the service's well-known port number, and initialize
a sockaddr_in structure that refers to the server.  Creating the socket
and finding the service's port number are identical to the method
described above.

To initialize the sockaddr_in structure, fill in the sin_family (AF_INET)
and sin_port (service's well-known port number) fields as in the server.
To fill in the sin_addr field, the client needs to find the internet
address of the server's machine.  The client has to find this from either
from an ASCII string of the IP address or the host name (either of which
the client will probably get from the user).  The inet_addr() function
accepts an ASCII string of a numeric IP address and returns the internet
address to put in the sockaddr_in's sin_addr.s_addr field.  If the client
only has the host name, it has to call gethostbyname() to find out the
server's machine address:

    struct hostent *gethostbyname(char *hostname)

The parameter hostname is an ASCII string naming the host.  This function
figures out the address of the host (usually by looking it up in the
inet:db/hosts file).  This function returns a pointer to a hostent
structure:

    struct  hostent {
        char   *h_name;       /* official name of host */
        char   **h_aliases;   /* alias list */
        int    h_addrtype;    /* host address type */
        int    h_length;      /* length of address */
        char   **h_addr_list; /* list of addresses from name server */
    #define  h_addr  h_addr_list[0]  /* address, for backward
                                        compatibility */
    };

The #defined field, h_addr, contains a pointer to an in_addr structure,
which contains the actual host address.  Copy this value into the
sockaddr_in.sin_addr.s_addr field.

Now the client needs to establish a connection between itself and the
server. It does this with the connect() function():

    int connect(int clientsocket, struct sockaddr *servname,
                int namelength)

where, clientsocket is the socket the client created earlier, servname
points to the sockaddr_in structure the client just built, and namelength
is the length of that sockaddr_in structure.

The server and client communicate using the send() and recv() functions:

    int send(int socket, char *buf, int buflength, int flags)
    int recv(int socket, char *buf, int buflength, int flags)

where, socket is the socket to send to/receive from, buf is a buffer that
contains the data to transmit/is a place for recv() to put the data it
receives, buflength is the length of buf, and flags is beyond the scope of
this article.  For the moment, you can set it to zero.

The data is a continuous stream, with any meaning assigned by the
application protocol (not to be confused with the network protocol).  The
data is always received either intact or not at all.  The data almost
always gets there unless there is a serious network or host machine
problem.  When the communications are finished, both sides s_close() the
sockets which were connected.


Skeleton for Applications Using UDP (connectionless)

The basic outline of most client/server model applications written with
UDP look something like this:

Server gets a socket with socket(), gets a port number with
getservbyname(), builds a sockaddr_in structure describing the server, and
gives that structure to bind() in order to attach a specific address to
the socket.  It then loops, waiting to recvfrom() any incoming datagrams
and responding to any requests in those datagrams.

    int recvfrom(int socket, char *buf, int buflength, int flags,
                 struct sockaddr *clientname, int namelength)

The recvfrom() function is similar to the recv() function except it has
two extra parameters.  clientname is a buffer for a sockaddr_in structure.
When recvfrom() receives a datagram from some application on the network,
it fills in clientname with the transport address of that application.
The size of the structure is namelength.

The client gets a server hostname from the user, gets a socket(), gets the
server's port number with getservbyname(), builds a sockaddr_in structure
describing the server, and sendto()s a datagram to the server's well-known
address:

int sendto(int socket, char *buf, int buflength, int flags, struct
sockaddr *servername, int namelength) The client either waits for the
server to send back a datagram to the client's socket, or give up because
the server took too much time to reply.  The client does this by calling
select().  This function puts the client to sleep until either a
particular set of sockets is ready for reading, writing, or exception
processing, or after a timeout period has passed without any activity.

    int select(int numsocks, fd_set *readsocks, fd_set *writesocks,
               fd_set *exceptsocks, struct timeval *timeout)

The numsocks parameter is 1 plus the number of sockets select() is waiting
on. The readsocks, writesocks, and exceptsocks parameters are each a
bitmask which tells select() which socket (or sockets) to wait for
activity on.  The fd_set structure (defined in <sys/types.h>), is
basically a handle to one of these bitmasks.  Programs cannot directly
manipulate the bits in these masks. Instead, there are functions to do
this:

    FD_ZERO(struct fd_set *mymask)                /* clear all bits in
                                                     mymask */
    FD_SET(int mysocket, struct fd_set *mymask)   /* turn on the bit for
                                                     mysocket in mymask */
    FD_CLR(int mysocket, struct fd_set *mymask)   /* turn off the bit for
                                                     mysocket in mymask */
    FD_ISSET(int mysocket, struct fd_set *mymask) /* test if mysocket's bit
                                                     in mymask is set */

For the purposes of this article, the only relevant mask is readsocks,
because the client is only waiting to read from a socket.  Since the
client isn't interested in the other masks, it makes writesocks and
exceptsocks NULL.

The last parameter, timeout, sets the maximum amount of time that select()
should wait for activity on the sockets it is watching.

When select() returns, its return value is either -1 if it failed, 0 if
there was a timeout, or a positive number, which is the number of sockets
that became ready.  When select returns, it sets the bits in the bitmasks
according to which socket (or sockets) became ready.

When select() returns, if a socket became ready, the client calls
recvfrom() to get the datagram the server sent back.  On timeout, the
client might try to re-send the datagram since it may have been lost or
corrupted.  Datagrams can be also be received in an order different from
that in which they were sent and can be received in duplicate.


Which Protocol Is Right For My Application?

Generally, if your application requires moving bulk data to far away
places, you should be using TCP.  For many other applications, TCP is also
appropriate just because its reliability makes it easy to use.  TCP is so
easy to use because it provides so much functionality.  The price paid for
ease of use is performance.

TCP does a good job of moving bulk data from one side of the planet to
another. For data which will only be sent across one physical network (one
LAN), or for data sent in small pieces, TCP doesn't perform so well.  A
much more specific set of functionality can always provide better
performance than the most general set can. For performance-critical
applications which don't move bulk data, UDP is usually the protocol of
choice.  Unfortunately, since UDP doesn't provide reliability, the
application protocol must.  This means a much more complicated application
protocol.  It isn't nearly as bad as it sounds, though, and Stevens (1990)
offers two examples.


The Shared Socket Library

The primary goal of the Shared Socket Library is to provide a network API
which is as compatible with standard Unix as possible.  This makes porting
many applications much easier, but it also creates many little quirks that
cannot be "fixed".  The justification behind this is: faithfully emulating
Unix's quirks is better than creating new ones, since at least you can
then write more portable software and only need to remember one set of
quirks.  Remember this when you wish that some function returned *void
rather than *foo, etc.  Expect to get a few spurious compiler warnings
from your nice ANSI 'C' compiler.

Many functions in socket.library are only needed by those developers
porting standard Unix remote services and probably should not be used by
most Amiga applications.  For example, all the functions dealing with user
and group IDs belong in this category.

To use the socket.library functions, the first thing you have to do, of
course, is open it.  This library is a little unconventional because it
returns a different library base for each OpenLibrary() call.  The Shared
Socket Library uses different library bases to keep track of some global
data for each process that opens it.  If you start a new process with a
new context, the new process must open and initialize socket.library.
Tasks should not access the socket.library, only processes should.

Before using any other function in the socket.library, you must call its
function setup_sockets() to initialize the library:

    ULONG retval = setup_sockets( UWORD max_sockets, int *errnop );

where max_sockets is the maximum number of sockets that can be open at
once and errnop points to errno, a global integer that provides details
about error conditions.  This global value is used extensively by the
standard socket functions.  The standard Amiga C startup code (c.o)
creates a global variable labelled "errno" which you can use as the global
pointer.

The setup_sockets() call must be matched with the cleanup_sockets() call.
This takes care of deallocating system resources that setup_sockets()
allocates.

The socket.library assumes that all ints are 32-bit values.  If you are
using a compiler which doesn't use 32-bit ints, you must make sure that
all ints are converted to longs by your code.

There are a couple of important differences between the AS225
socket.library and the standard Unix implementation.  When writing
softwarefor AS225, you cannot use the read(), write(), close(), and
ioctl() functions on sockets. These functions come from Unix and apply
both to files and sockets.  To avoid confusion, socket.library does not
contain these functions.  Use the socket.library functions recv(), send(),
s_close(), and s_ioctl() instead.

The standard Unix implementation has a series of get*() functions.  These
functions return a pointer to a static buffer.  The buffer returned by a
call to getX*() is cleared on the next invocation of getX*().  For
example, the buffer pointed to by the return of gethostent() is cleared by
another call to gethostent(), gethostbyaddr() or gethostbyname(), but not
by a call to getprotoent(), etc.  None of the get*ent(), set*ent() or
end*ent() functions should normally be used except for porting existing
programs.

The Shared Socket Library contains a function called selectwait().  This
function combines the select() function with the exec.library Wait()
function so that an Amiga networked application can wait on both Amiga
events and network events at the same time.

This article, the examples from the Network Developer's disk,  and the
include files and the Autodocs should be enough to get you started.
Writing network applications can be very complex and difficult, but is
well worth the effort. This article only introduces you to writing network
applications for the Amiga with AS225, and has left a lot unsaid about the
socket interface and about networking in general.  In addition to the
Shared Socket Library include files and Autodocs, the following books and
articles are all highly recommended. Several should be required reading
for anyone seriously developing any Amiga and/or Unix network applications
with TCP/IP:


References

Comer, D.E. (1991a), Internetworking with TCP/IP, Volume I, 2d:
Principles, Protocols, and Architecture. Prentice-Hall, ISBN 0-13-468505-9

    If you want more detail on how the protocols work (especially how
    they support internetworking), this is the place to look.  Little
    programming information is in this volume.

Comer, D.E. and Stevens, D.L. (1991b), Internetworking with TCP/IP, Volume
II: Design, Implementation and Internals. Prentice-Hall,
ISBM 0-13-472242-6.

    There is more detail here than most application developers will want
    or need, but some subjects (i.e., Out-Of-Band data) are covered here
    better than in any other text.  The text includes a complete TCP/IP
    implementation for Xinu.  It should be easily understandable by Amiga
    developers, in part, because Xinu happens to have a rather Exec-like
    IPC mechanism.

Stevens, W.R. (1990), Unix Network Programming.  Prentice-Hall,
ISBN 0-13-949876-1.

    This book starts at the beginning and methodically leads the reader
    through many advanced topics.  If it weren't for the fact that it
    serves as a reference and a tutorial, it could be thought of as the
    RKMs for AS225 software development.  It introduces network protocols
    in some detail, and sockets in great detail.  It includes source and
    discussion of several real-world examples: ping, tftp, rlogin, lpr,
    rcmd, rmt, etc.  Everyone in the Amiga Networking group owns a copy.

RFCs
----

All Internet standards start life as Requests For Comments.  They are
still called RFCs even if they become required, recommended, or elective.
If you wish to implement a standard Internet application, you should
obtain any currently applicable RFC(s) and study them closely.  Here is
one way to obtain RFCs:

CSNET:
------

    CSNET Coordination and Information Center (CIC)
            Hotline: (617) 873-2777
    10 Moulton Street, Cambridge, MA 02138
            Email:  cic@sh.cs.net
        Info-Server requests to: info-server@sh.cs.net

The CSNET Info-Server stocks all RFCs with numbers higher than 900, unless
(like RFC 900) they have been obsoleted by later RFCs.  The Info-Server
also stocks selected RFCs with numbers lower than 900.

The CSNET Info-Server is an automatic program that delivers information by
electronic mail.  To order a document from the Info-Server, send a message
to "info-server@sh.cs.net".  You do not need a subject field.  The text of
your message must be in a special format, such as:

             REQUEST: rfc
              TOPIC: heLP
              Topic: RFC822
             request: END

The text may any combination of upper-case and lower-case letters.

The above request asks for two documents "HELP" and "RFC822" from the
collection "RFC".  Your message must have a "REQUEST" line, and one or
more "TOPIC:" lines to specify one or more documents. The optional
statement "REQUEST: END" terminates your specification.  Any subsequent
text in the message is ignored by the Info-Server.

    NOTICE:
    -------
    The Topic: field must be of the form "rfc822", and NOT "822" or
    "rfc822.txt".


VIII-31: A Shared Socket Library Server and Client

by John Wiederhirn and John Orr

Wednesday is gyro day in CATS, so we have to go out to lunch and eat
gyros.  Because David the Engineer used to work in CATS, we are morally
obligated to bring him along.  Like the rest of the engineers, David is
usually working very hard and doesn't notice what time it is, so we
have to remind him that it's time to leave for lunch.  Unfortunately,
David can't hear us yelling to him in the Engineering department, so we
needed an alternate way to tell David that is was time for lunch.  The
only logical conclusion was to write a program that uses the Shared
Socket Library to make a requester pop up on David's Workbench screen
telling him it is lunch time.

To write a network application for the Shared Socket Library you will
need two things:

    1) An understand the material in the article
       "Developing Network Applications for the Amiga" from the
       January/February 1992 issue of Amiga Mail.

    2) The Shared Socket Library include files and Autodocs
       (which are on the Network Developer's Disk and the
       Denver/Milano 1991 Devcon disks)
@rem link used to go to "cats_cd:devcon_disks/devcon_91/contents_91.2/Network!Socket"
This application has to be broken into two pieces, a client and a
server.  The client program will send out the notes.  On Amiga A, the
user runs the client (SendNote), passing it a note string (like
"David, it's time to eat") and a machine address for Amiga B.  The
client then sends a note request off to the note server (ShowNote) on
Amiga B.  When the note server gets the note request, it pops up an
EasyRequest containing the note on Amiga B.  The server waits for the
user to click an "OK" gadget, then sends back an acknowledgement to
the client.

There are a couple of decisions to make about the application before
coding anything.  First, there are two transport protocols to choose
from: TCP and UDP.  To make things easier, this application uses TCP
because it is a reliable protocol, so the application doesn't have to
worry about making sure data makes it across the network.  The
application uses a client/server model, but there are two of those
models to choose from: iterative and concurrent.  Because this
application does not need to handle more than one request at the same
time, the iterative server is a better choice.  This also makes coding
easier.

 The Application Protocol
 The ShowNote Server Application
 Listening for Network and Amiga Events
 Identifying Network Events and Talking to the Client
 Starting the ShowNote Server
 The SendNote Client Application
 Resolving the Target (Host) Address
 Locating the Server Port and Connecting to It
 Starting the SendNote Client

 Note.h      SendNote.c      ShowNote.c


The Application Protocol

The note program now needs an application protocol for sending
information between the client and server.  When the client sends a
request message to the server, it needs to send the note string.  It
also would be nice to supply the text for the buttons that will pop up
in the requester.  On the return trip from ShowNote to the SendNote
client, the protocol only needs to define some return codes so the
client can tell if the request worked and which button on the requester
the remote user clicked.  Because the application needs to send
different types of packets (one type containing a message request, the
other type containing the response from the server), the protocol needs
to have a way to specify a packet type.

The following structure is the packet that ShowNote and SendNote send
back and forth to each other:

    struct NetNote
    {
        int nn_Code;
        int nn_Retval;
        char    nn_Text[200],
                nn_Button[40];
    };

On the trip from client to server, the nn_Code field is the message
request packet type (NN_MSG), nn_Text is the note for the remote user,
and nn_button is the text for the EasyRequest buttons.  On the return
trip, nn_Code is either NN_ACK, if there was no error, or NN_ERR, if
there was an error.  If there was no error, nn_Retval contains the
number of the EasyRequest button that the user selected.

In this application, the same packet is passed back and forth for both
legs of the trip (client to server and vice versa).  If the application
required sending large chunks of data in one direction and small chunks
of data in the other direction, it would be a good idea to use packets
of different sizes.  Otherwise, if the application used only one packet
size, the size of the packet would be huge compared to the size of the
small chunk of data, which would unnecessarily loading the network.


The ShowNote Server Application

Although the Amiga's Shared Socket Library is meant to be compatible
with the Unix socket implementation, there are a couple of
Amiga-specific quirks that an Amiga networked application has to take
care of.  First, an Amiga application has to open the Shared Socket
Library (socket.library).  Before calling any other functions in
socket.library, the program has to call the socket.library function,
setup_sockets().  ShowNote.c code has almost all of the network
intialization material in the SS_Init() function.

    /*
    ** Attempt to open socket library and initialize socket environment.
    ** If this fails, bail out to the non-returning AppPanic() routine.
    */

    if (SockBase = OpenLibrary("inet:libs/socket.library",0L))
    {
        setup_sockets( 3, &errno );
    }
    else
    {
        AppPanic("Can't open socket.library!",0);
    }

Unlike most libraries, socket.library does not go in LIBS:.  Instead,
it goes with the network-specific support files, in INET:, in a LIBS
directory.  This location needs to be hardcoded into the application.

Next, create a socket:

    /*
    ** Open the initial socket on which incoming messages will queue for
    ** handling.  While the server is iterative, I do it this way so that
    ** SIGBREAKF_CTRL_C will continue to function.
    */

    int snum;

    if ((snum = socket( AF_INET, SOCK_STREAM, 0 )) == -1)
    {
        AppPanic("Socket Creation:",errno);
    }

and figure out what the well-known port number of the server is.  For
testing purposes, SendNote and ShowNote use a hard-coded port number
(8769).  If the application was installed on a network, each machine
that ran the server would need an entry for the "note" service in the
inet:db/services file.  In that case, both the server and the client
would have to use getservbyname() to find the port number of the
"note" service.

The server then needs to build a sockaddr_in structure describing
itself.  The sockaddr_in contains all the information needed to map an
initialized socket to a specific transport address on the Internet
(thus the _in suffix, other network protocols have different suffixes).
Before the socket can be assigned an Internet transport address, it
needs to be initialized:

    struct sockaddr_in sockaddr;

    memset( &sockaddr, 0, len ); /* clear sockaddr */
    sockaddr.sin_family = AF_INET;
    sockaddr.sin_port = 8769;
    sockaddr.sin_addr.s_addr = INADDR_ANY;

Next, bind the socket to the well-known address in sockaddr.

    if ( bind( snum, (struct sockaddr *)&sockaddr, len ) < 0 )
    {
        AppPanic("Socket Binding:",errno);
    }

    /*
    ** Okay, the socket is as ready as it gets.  Now all we need to do is to
    ** tell the system that the socket is open for business.
    */

    listen( snum, 5 );

The call to bind() takes the socket identifier and sockaddr_in
structure and assigns a unique network identity (a transport address)
to the socket, making it visible to the network.  The listen() call
tells socket.library the socket is ready to receive incoming messages.
The '5' in the listen() call tells the system the size of the
connection request queue.

A connection request that a client sends to the server's socket goes
into this queue and waits for the server to process it.  If requests
arrive at the server's socket faster than the server can process them,
the queue fills to capacity.  While the queue is full, the system
rejects any other incoming connection requests.  ShowNote uses 5
because that is the maximum allowed by Berkeley Sockets.


Listening for Network and Amiga Events

Once back in the main() routine, the application is almost ready to
start processing network events.  The only thing remaining is to decide
what kind of events the server needs to hear about.  Most applications
will need to be aware of both network and local Amiga events, which
means separate masks need to be set up for both types of events.  On
the network side, the mask needs to contain information on which
sockets need responses.

    /* First, prepare the various masks for signal processing */
    fd_set sockmask;

    FD_ZERO( &sockmask );
    FD_SET( socket, &sockmask );

The sockmask variable will be used as a template to indicate what
network events the application notices.  Since sockmask came off the
stack and contains garbage, the FD_ZERO() call clears all its network
signal bits.  The FD_SET() call sets the mask to listen for events
relating to the socket that the server created earlier.  Everything is
prepared, so the next step is entering the event loop itself.

    long umask;
    fd_set mask;

    while(1)
    {
        /*
        ** Reset the mask values for another pass
        */

        mask = sockmask;
        umask = SIGBREAKF_CTRL_C;

        /*
        ** selectwait is a combo network and Amiga Wait() rolled into
        ** a single call.  It allows the app to respond to both Amiga
        ** signals (CTRL-C in this case) and to network events.
        **
        ** Here, if the selectwait event is the SIGBREAK signal, we
        ** bail and AppPanic() but otherwise its a network event.
        */

        if (selectwait( 2, &mask, NULL, NULL, NULL, &umask ) == -1 )
        {
            AppPanic("CTRL-C:\nProgram terminating!",0);
        }

Before an event occurs, the mask variable tells selectwait() which
network events the server wants to receive.  After an event occurs, the
mask variable indicates which socket triggered the network event.  The
sockmask variable is used to reset mask back to its original mask value
at the top of each pass through the event loop.

In addition to waiting on network events, selectwait() also waits on
Exec signals for the current task.  For this example, the only Amiga
event the server cares about is a Ctrl-C break (SIGBREAKF_CTRL_C).  The
selectwait() function has a simple purpose, but due to the wide scope
of network events, the function has a myriad of parameters and
configurations. This example uses the bare minimum of what's possible
using selectwait(), and many network-friendly applications will be able
to get by using only a small subset of selectwait()'s potential.  In
this case, the network event set is passed in mask, and the Amiga event
mask is passed in umask.

If selectwait() returns with a value of -1, it means the Amiga event
mask was the trigger.  Otherwise, a network event caused the function
to return.  This example is simple enough that a Ctrl-C interrupt can
be handled rather easily.


Identifying Network Events and Talking to the Client

If selectwait() returned as a result of a network event, then a bit
more detective work is needed to determine which socket caused the
event.  The example only has to watch a single socket, so if that
socket wasn't the cause, an error occurred.  In more complex servers,
the server might have to check each of several sockets using the
FD_ISSET() macro to determine which one caused the event.  There is
also the possibility that more than a single event came in at the same
time, so an application with many active sockets needs to take into
account the possibility of multiple true results from FD_ISSET().

    if (FD_ISSET( socket, &mask ))
    {
        HandleMsg( socket );
    }
    else
    {
        AppPanic("Network Signal Error!",0);
    }

The FD_ISSET() macro checks if there was activity on a socket by
checking if the socket's bit is set in the socket mask passed to
selectwait().  In this code, there is only a single active socket, so
if that socket isn't the trigger then there was an error.

When a client tries to talk with a server, it first attempts to get a
connection between itself and the server.  In this example, the server
application returns from its selectwait() with that socket identified
in the mask variable.  The server has to accept the connection:

    sockadd_in saddr;
    int len;

    if (!(nsock = accept( sock, (struct sockaddr *)&saddr, &len )))
    {
        AppPanic("Accept:",errno);
    }

When the server calls accept(), the function attempts to form a
connection with the client.  If it can do so, it returns a new socket
identifier.  The new socket identifier corresponds to a new socket
where the all future communication between the client and server will
occur.  This allows concurrent servers to use an existing socket to
establish new connections while carrying on other private client-server
conversations.

The accept() function also passes back a sockaddr_in structure
describing the client.  In this example, the server uses this address
to figure out the client's host name:

    struct hostname *hent;
    struct in_addr sad;
    char *dd_addr, *hname, rname[80];

    /*
    ** Get the internet address out of the sockaddr_in structure and then
    ** create a dotted-decimal format string from it.
    */

    sad = saddr.sin_addr;
    dd_addr = inet_ntoa(sad.s_addr);

    /*
    ** Use the internet address to find out the machine's name
    */

    if ( !( hent = gethostbyaddr( (char *) &sad.s_addr,
                                  sizeof(struct in_addr),
                                  AF_INET )))
    {
        AppPanic("Client resolution:\nAddress not in hosts db!", 0 );
    }
    hname = hent->h_name;

Right now, if the server cannot identify the client's machine, it
terminates with an error.  While this may seem a bit drastic, it does
prevent anonymous messages from being sent across the system.  Coding a
secure client and server requires more complex protocols and involves
many other issues which are beyond the scope of this article.

After doing a little formatting of the address and name information,
the HandleMsg() function begins the actual process of communicating
with the client.

    int nsock;
    struct NetNote in;

    /*
    ** Okay, now the waiting packet needs to be removed from the connected
    ** socket that accept() gave back to us.  Verify its of type NN_MSG and
    ** if not, set return type to NN_ERR.  If it is, then display it and
    ** return an NN_ACK message.
    */

    recv( nsock, (char *)&in, sizeof(struct NetNote), 0 );
    if (in.nn_Code == NN_MSG)
    {
        DisplayBeep(NULL);  /* DisplayBeep() to get the user's attention */
        DisplayBeep(NULL);
        retv = DoER( rname, (char *)&in.nn_Text, (char *)&in.nn_Button );
        in.nn_Code = NN_ACK;
        in.nn_Retval = retv;
    }
    else
    {
        in.nn_Code = NN_ERR;
    }

The recv() function removes a struct NetNote sized amount of data from
the socket nsock and places that information in a buffer.  Once the
message packet is in the buffer, the server verifies it is a proper
packet by checking the nn_Code.  The checking isn't really necessary
since the example uses a reliable protocol (TCP) and there is only one
type of packet the server can receive.  After checking the packet, the
server prepared the nn_Code field for the return trip to the client.
If there was something wrong with the packet, the server sets nn_Code
to NN_ERR, otherwise the server sets nn_Code to NN_ACK. If there was no
error, the server extracts the message and button text from the NetNote
packet.  The server passes them plus name and address information for
the client to the DoER() routine.  The DoER() routine creates a system
EasyRequest, displays it, and returns a value which corresponds to the
button which was pressed.  The return information on which button was
pressed is encoded into the nn_Retval field of the NetNote packet,
which is then ready to be sent back to the client.

The prepared packet is sent back to the client using the send()
function:

    /*
    ** Having dealt with the message one way or the other, send the message
    ** back at the remote, then disconnect from the remote and return.
    */

    send( nsock, (char *)&in, sizeof(struct NetNote), 0 );
    s_close( nsock );

The HandleMsg() function then closes nsock using s_close(). The packet
protocol between the client and server in this application is defined
so there are no cases where the client would send another message, so
it can close the socket and break the connection.  The
acknowledgement/error packet will arrive at the client regardless of
whether the connection is still active or not, at least under TCP/IP.
HandleMsg() returns to the main() routine and event loop.

Once back in the main event loop, the server will continue connecting
and responding to client messages until it receives a Ctrl-C interrupt
or an error condition occurs.


Starting the ShowNote Server

The ShowNote server should run as a backround CLI process.  To start
it, type the following line at a CLI prompt:

    run >nil: shownote

You can start up the server when you boot your Amiga by adding that
line to s:user-startup.


The SendNote Client Application

The client application, SendNote, sends a message for a server to pop
up on its display.  While the server is an Intuition program in that it
uses a requester to display the messages and get responses, the client
(SendNote) is strictly a CLI-based application.  SendNote parses its
command line using the AmigaDOS 2.0 ReadArgs() call.  For more
information on ReadArgs(), see the AmigaDOS Manual, 3rd Edition from
Bantam, the article "Standard Command Line Parsing" from the May/June
1991 issue of Amiga Mail, or the DOS library includes and Autodocs.
There is very little difference in the application-wide setup of
sockets between the client and server.  Both must open socket.library
and call setup_sockets() to initialize the socket environment.  One
minor difference is the number of sockets the client initializes.  The
client only needs a single socket to establish a connection to the
server, where the server requires at least two (one for receiving
connection requests and one for talking to a client).

The FinalExit() routine is both the client's error handler and its
shutdown routine.  Since the client doesn't need to maintain so much
operating information, the shutdown routine is rather simple, and can
be used for both errors and normal termination.


Resolving the Target (Host) Address

The client gets a string back from the ReadArgs() call which contains
the hostname in either dotted-decimal notation or ASCII form.  The
clint needs to convert that string to a usable form.

    struct sockaddr_in serv;
    struct hostent *host;
    char *hostnam, *text, *button;

    /*
    ** First we need to try and resolve the host machine as an IP/Internet address.
    ** If that fails, fall back to seaching the hosts file for it.  Later versions of
    ** gethostbyname() may use DNS to find a host name, rather than searching the hosts file.
    */

    bzero( &serv, sizeof(struct sockaddr_in) );
    if ( (serv.sin_addr.s_addr = inet_addr(hostnam)) == INADDR_NONE )
    {
        /*
        ** Okay, the program wasnt handed a dotted decimal address,
        ** so we check and see if it was handed a machine name.
        */

        if ( (host = gethostbyname(hostnam)) == NULL )
        {
            printf("Host not found: %s\n",host);
            FinalExit( RETURN_ERROR );
        }

        /*
        ** It does indeed have a name, so copy the addr field from the
        ** hostent structure into the sockaddr structure.
        */

        bcopy( host->h_addr, (char *)&serv.sin_addr, host->h_length );
    }

After clearing out the serv sockadd_in structure, the client tries to
convert the host name string (hostnam) it got from its command line
from dotted-decimal to an IP address block using the inet_addr()
function.  If this fails, the server treats the string hostnam as an
ASCII string containing a host name, and tries to get a normal IP
address using gethostbyname().  This will search the hosts file
(inet:db/hosts) for a matching entry.  Future versions of
gethostbyname() may use DNS (domain name system), which allows
gethostbyname() to ask a server for host information rather than
looking it up in a hosts file.

If it is successful, gethostbyname() returns a pointer to a hostent
structure.  It requires a little work to to convert this hostent
structure to a sockaddr_in (IP socket address) structure.  There is a
sockaddr structure embedded inside the hostent structure which can be
used as a sockaddr string in this case.  The call to bcopy() copies
that embedded sockaddr structure into the client's sockaddr_in buffer.


Locating the Server Port and Connecting to It

The next step is to find the server's port number.  In the case of this
example, the port name is hardcoded into the server and client.  A real
networked application should have an entry for the "note" service in
the inet:db/services file.  The code below finds the port number in the
client machine's inet:db/services file.

    struct servent *servptr;
    char servnam[] = "note";

    if ((servptr = getservbyname( servnam, "tcp" )) == NULL)
    {
        printf("%s not in inet:db/services list!",servnam);
        FinalExit( RETURN_ERROR );
    }
    serv.sin_port = servptr->s_port;

    /*
    ** This tells the system the socket in question is an Internet socket
    */

    serv.sin_family = AF_INET;

Since the client and server are running on top of an IP (Internet
Protocol) system, the client needs to specify AF_INET in its call to
socket() just as the server did.

    /*
    ** Initialize the socket
    */

    if ( (sock = socket( AF_INET, SOCK_STREAM, 0 )) < 0 )
    {
        printf("socket gen: %s\n", strerror(errno));
        FinalExit( RETURN_ERROR );
    }

The client socket is initialized and ready.  Because the client knows
the IP address of the server's machine and the service number of the
"note" service, the client knows the well-known transport address so
it can attempt to establish a connection with the server:

    /*
    ** Connect the socket to the remote socket, which belongs to the
    ** server, and which will "wake up" the server.
    */

    if ( connect( sock,
                  (struct sockaddr *) &serv,
                  sizeof(struct sockaddr) ) < 0 )
    {
        printf("connect: %s\n", strerror(errno));
        s_close( sock );
        FinalExit( RETURN_ERROR );
    }

The connect() call contacts the server across the network and attempts
to form a connection.  There are many things which can go wrong at this
point, and any return less than zero indicates an error condition.  If
an error does occur, the socket.library function strerror() converts
the error number in errno into a readable error message, which is then
displayed by the client.  In case of an error, the client already has a
socket open, so it then must close the socket and terminate using the
application's error handler, FinalExit().

Once the connection is established, the client needs to prepare the
note request packet.  Since the call to ReadArgs() has already parsed
everything, the client only has to copy the strings into a NetNote
structure:

    struct NetNote out;

    out.nn_Code = NN_MSG;
    strcpy( (char *)&out.nn_Text, text );
    strcpy( (char *)&out.nn_Button, button );

The client has filled in all the relevant fields of the NetNote
structure, so it is ready to send.  The server will fill in the
nn_Retval field before passing it back to the client, so the client
doesn't need to fill it in for the client-to-server leg of the trip.
All that remains is to transfer the packet across the network:

    send( sock, (char *)&out, sizeof(struct NetNote), 0 );

    printf("\nMessage sent to %s...waiting for answer...\n", hostnam );

    /*
    ** Wait for either acknowlegde or error.
    */

    recv( sock, (char *)&out, sizeof(struct NetNote), 0 );

Now the client has to wait for the server to respond.  This is one of
the few points where the client can hang forever.  If the server
receives the message, and never replies back, the client will never
stop waiting for a reply.  A real application would time-out if the
server didn't respond within a certain time interval.  One way to do
this is using a selectwait() which breaks when triggered by a
timer.device event.  We'll leave that as an exercise.

The call to recv() waits until the server sends back a reply.  Once the
client receives the reply, the client has to check the NetNote
structure's nn_Code field.  If it's NN_ERR, an error occurred, and the
client terminates through the FinalExit() handler.  If an NN_ACK packet
comes back from the server, the nn_Retval field contains the number of
the button the user pressed on the ShowNote requester.

The server gets the button number directly from the EasyRequest()
function that the server uses to pop up the requester.  The buttons on
the requester are numbered from 1, increasing left to right, except for
the rightmost button, which is button zero.  If there is only one
button, that button will return a zero (it's the furthest right).

After the client gets the packet back from the server, the client's
task is complete.  It only has to clean up after itself.


Starting the SendNote Client

The SendNote command has the following template, and uses the AmigaDOS
2.0 ReadArgs() call to parse the CLI command line:

    SENDNOTE HOST/A,TEXT,BUTTON

The HOST argument is the address of the server machine.  It is either a
dotted-decimal notation address or its ASCII  host name from the
inet:db/hosts file.  The TEXT argument is the string the server will
pop up in its requester.  The BUTTON argument is the ASCII string that
will appear in the requester button.  For example:

    sendnote 123.123.123.1 "I've fallen and I can't get up!" "Help me!"

displays a requester on the machine whose address is 123.123.123.1,
with the text of the requester saying "I've fallen and I can't get up!"
and a button labeled "Help me!".  If that machine is not running the
server, then SendNote just displays an error message and terminates.
If the inet:db/hosts file on the machine running SendNote has an entry
that gives 123.123.123.1 the name "foo", then

    sendnote foo "I've fallen and I can't get up!" "Help me!"

will have the exact same effect as the previous form of the command.
There are also default values for both the TEXT and BUTTON arguments.
If the user doesn't provide an argument for BUTTON, then ShowNote
defaults to "OK".  If both TEXT and BUTTON are missing, the TEXT
argument defaults to "==PING!==".  To give the user on the server
machine several buttons to choose from, put several strings in the
BUTTON argument delimited by `|` characters, like this:

    sendnote foo "Is it time yet?" "yes|no|maybe"

That's all there is to the client application.  Because the
socket.library routines take care of so much of the network "nitty
gritty", the application code can deal with networks in a
straight-forward and simple manner.  Two applications (client and
server), each around 8K bytes in size, are able to implement a complete
and working intranetwork communication system (albeit a very simplistic
one).  If you are interested in doing more serious development using
the AS225 software (and thus IP and TCP/UDP), you should take a look at
more advanced texts.  A good start is Unix Network Programming by W. R.
Stevens (Prentice-Hall, ISBN 0-13-949876-1).  It covers many aspects of
network protocol and application design, as well as explaining quite a
bit about "Berkeley Sockets" which socket.library implements.


VIII-51: SANA-II Network Device Driver Specification

Amiga Networking Group -  Brian Jackson, Dale Larson
                          Greg Miller, Kenneth Dyke

The SANA-II Network Device Driver Specification is a standard for an Amiga
software interface between networking hardware and network protocol stacks
(or for software tools such as network monitors). A network protocol stack
is a layer of software that network applications use to address particular
processes on remote machines and to send data reliably in spite of
hardware errors. There are several common network protocol stacks
including TCP/IP, OSI, AppleTalk, DECNet and Novell.

SANA-II device drivers are intended to allow multiple network protocol
stacks running on the same machine to share one network device. For
example, the TCP/IP and AppleTalk protocol stacks could both run on the
same machine over one ethernet board. The device drivers are also intended
to allow network protocol stacks to be written in a hardware-independent
fashion so that a different version of each protocol stack doesn't have to
be written for each networking hardware device.

The standard does not address the writing of network applications.
Application writers must not use SANA-II Device Drivers directly. Network
applications must use the API provided by the network protocol software
the application supports. There is not an Amiga standard network API at
the time of this writing, though there is the AS225 TCP/IP package and its
socket.library as well as other (third-party) packages.

To write a SANA-II device driver, you will need to be familiar with the
specification documents for the hardware you are writing to and with the
SANA-II Network Device Driver Specification.

To write a network protocol stack which will use SANA-II device drivers,
you should have general familiarity with common network hardware and must
be very familiar with the SANA-II Network Device Driver Specification as
well as the specification for the protocol you are developing. If you are
creating a new protocol, you must obtain a protocol type number for any
hardware on which your protocol will be used.

Commodore supports the SANA-II specification by providing drivers for the
Commodore-Amiga network hardware. We have an A2065.device (Ethernet) and
intend to produce an A2060.device (ARCNET). We also try to examine review
copies of third-party SANA-II networking hardware and software to try to
make sure that they interoperate with our products.

This standard has undergone several drafts with long periods for comment
from developers and the Amiga community at large. These drafts include a
UseNet release which was also distributed on the Fish Disks in June, 1991
(as well as published in the '91 DevCon notes), and the November 7 Draft
for Final Comment and Approval distributed via Bix, ADSP and UseNet. There
were also several intermediate drafts with more limited distribution.

This version of the specification is final. Any new version of the
standard (i.e., to add new features) is planned to be backward compatible.
No SANA-II device driver or software utilizing those drivers should be
written to any earlier version of the specification.

Distribution of this version of the standard is unlimited. Anyone may
write Amiga software which implements a SANA-II network device driver or
which calls a SANA-II network device driver without restriction and may
freely distribute such software that they have written. Amiga is a
registered trademark of Commodore-Amiga, Inc. Ethernet is a trademark of
Xerox Corporation. ARCNET is a trademark of Datapoint Corporation. DECNet
is a trademark of Digital Equipment Corporation. AppleTalk is a trademark
of Apple Computer, Inc.

It is important to try to test each SANA-II device driver against all
software which uses SANA-II devices. Available example programs are
valuable in initial testing. The Amiga Networking Group is interested in
receiving evaluation and/or beta test copies of all Amiga networking
hardware, SANA-II device drivers and software which uses SANA-II devices.
However, we make no assurances regarding any testing which we may or may
not perform with such evaluation copies. Contact:

    Amiga Networking Group
    Commodore International Services Corporation
    Technology Group
    1200 Wilson Drive
    West Chester, PA 19380, USA

 Driver Form                  Ethernet Packet Types     Errors
 Opening a SANA-II Device     ARCNET Frames             Standard Commands
 Buffer Management            Addressing                Acknowledgments
 Packet Type                  Hardware Type             Unresolved Issues

 SANA-II Developer Support Package


Driver Form

SANA-II device drivers are Amiga Exec device drivers. They use an extended
IORequest structure and a number of extended commands for tallying network
statistics, sending broadcasts and multicasts, network addressing and the
handling of unexpected packets. The Amiga ROM Kernel Reference Manual:
Devices includes information on how to construct an Exec device.


Opening a SANA-II Device

As when opening any other Exec device, on the call to OpenDevice() a
SANA-II device receives an IORequest structure which the device
initializes for the opener's use. The opener must copy this structure if
it desires to use multiple asynchronous requests. The SANA-II IORequest is
defined as follows:

    struct IOSana2Req
    {
        struct IORequest ios2_Req;
        ULONG ios2_WireError;
        ULONG ios2_PacketType;
        UBYTE ios2_SrcAddr[SANA2_MAX_ADDR_BYTES];
        UBYTE ios2_DstAddr[SANA2_MAX_ADDR_BYTES];
        ULONG ios2_DataLength;
        APTR *ios2_Data;
        APTR *ios2_StatData;
        APTR *ios2_BufferManagement;
    };

  ios2_Req              - A standard Exec device IORequest.

  ios2_WireError        - A more specific device code which may be
                          set when there is an io_Error. See
                          <devices/sana2.h> for the defined
                          WireErrors.

  ios2_PacketType       - The type of packet requested. See the
                          section on "Packet Type".

  ios2_SrcAddr          - The device fills in this field with the
                          interface (network hardware) address of
                          the source of the packet that satisfied
                          a read command. The bytes used to hold
                          the address will be left justified but
                          the bit layout is dependent on the
                          particular type of network.

  ios2_DstAddr          - Before the device user sends a packet, it
                          fills this with the interface destination
                          address of the packet. On receives, the
                          device fills this with the interface
                          destination address. Other commands may
                          use this field differently (see the SANA-II
                          Network Device Driver Autodocs). The
                          bytes used to hold the address will be
                          left justified but the bit layout is
                          dependent on the particular type of network.

  ios2_DataLength       - The device user initializes this field with
                          the amount of data available in the Data
                          buffer before passing the IOSana2Req to
                          the device. The device fills in this field
                          with the size of the packet data as it was
                          sent on the wire. This does not include
                          the header and trailer information.
                          Depending on the network type and protocol
                          type, the driver may have to calculate
                          this value. This is generally used only
                          for reads and writes (including broadcast
                          and multicast).

  ios2_Data             - A pointer to some abstract data structure
                          containing packet data. Drivers may not
                          directly manipulate or examine anything
                          pointed to by Data! This is generally
                          used only for reads and writes (including
                          broadcast and multicast).

  ios2_StatData         - Pointer to a structure in which to place
                          a snapshot of device statistics. The data
                          area must be long word aligned. This is
                          only used on calls to the statistics
                          commands.

  ios2_BufferManagement - The opener places a pointer to a tag list
                          in this field before calling OpenDevice().
                          Functions pointed to in the tag list are
                          called by the device when processing
                          IORequests from the opener. When returned
                          from OpenDevice(), this field contains a
                          pointer to driver-private information
                          used to access these functions.
                          See "Buffer Management" below for more
                          details.

The flags used with the device on OpenDevice() are (SANA2OPB_xxx):

  SANA2OPB_MINE  - Exclusive access to the unit requested.
  SANA2OPB_PROM  - Promiscuous mode requested. Hardware which
                   supports promiscuous mode allows all packets
                   sent over the wire to be captured whether or not
                   they are addressed to this node.

The flags used during I/O requests are (SANA2IOB_xxx):

  SANA2IOB_RAW   - Raw packet read/write requested. Raw packets
                   should include the entire data-link layer packet.
                   Devices with the same hardware device number
                   should have the same raw packet format.
  SANA2IOB_BCAST - Broadcast packet (received).
  SANA2IOB_MCAST - Multicast packet (received).
  SANA2IOB_QUICK - Quick IO requested.


Buffer Management

Unlike most other Exec Device drivers, SANA-II drivers have no internal
buffers. Instead, they read/write to/from an abstract data structure
allocated by the driver user. The driver accesses these buffers only via
functions that the driver user provides to the driver. The driver user
must provide two functions--one copies data to the abstract data structure
and one copies data from the abstract data structure. The driver user can
therefore choose the data structure used for buffer management by both the
driver and driver user in order to have efficient memory and CPU usage
overall.

The IOSana2Req contains a pointer to data and the length of said data. A
driver is not allowed to make assumptions about how the data is stored.
The driver cannot directly manipulate or examine the buffer in any manner.
The driver can only access the buffer by calling the functions provided by
the driver user.

Before calling OpenDevice(), the driver user points ios2_BufferManagement
to a list of tags (defined in <devices/sana2.h>) which include pointers to
the buffer management functions required by the driver (defined below).
The driver will fail to open if the driver user does not supply all of the
required functions.  If the device opens successfully, the driver sets
ios2_BufferManagement to a value which this opener must use in all future
calls to the driver.  This "magic cookie" is used from then on to access
these functions (a "magic cookie" is a value which one software entity
passes to another but which is only meaningful to one of the software
entities).  The driver user may not use the "magic cookie" in any way--it
is for the driver to do with as it wishes.  The driver could in theory
choose to just copy the tag list to driver-owned memory and then parse the
list for every IORequest, but it is much more efficient for the driver to
create some sort of table of functions and to point ios2_BufferManagement
to that table.

The specification currently includes only two tags for the OpenDevice()
ios2_BufferManagement tag list:

    S2_CopyToBuff  - This is a pointer to a function which conforms to
             the CopyToBuff Autodoc.

    S2_CopyFromBuff - This is a pointer to a function which conforms to
             the CopyFromBuff Autodoc.


Packet Type

Network frames always have a type field associated with them. These type
fields vary in length, position and meaning by frame type (frame types
generally correspond one-to-one with hardware types, but see
"Ethernet Packet Types" below). The meanings of the type numbers are
always carefully defined and every type number is registered with some
official body. Do not use a type number which is not registered for any
standard hardware you use or in a manner inconsistent with that
registration.

The type field allows the SANA-II device driver to fulfill CMD_READs based
on the type of packet the driver user wants. Multiple protocols can
therefore run over the same wire using the same driver without stepping on
each other's toes.

Packet types are specified as a long word. Unfortunately, the type field
means different things on different wires. Driver users must allow their
software to be configured with a SANA-II device name, unit number and the
type number(s) used by the protocol stack with each device. This way, if
new hardware becomes available, a hardware manufacturer can supply a
listing of type assignments to configure pre-existing software.


Ethernet Packet Types

Ethernet has a special problem with packet types. Two types of ethernet
frames can be sent over the same wire--ethernet and 802.3. These frames
differ in that the Type field of an ethernet frame is the Length field of
an 802.3 frame. This creates a problem in that demultiplexing incoming
packets can be cumbersome and inefficient, as well as requiring driver
users to be aware of the frame type used.

All 802.3 frames have numbers less than 1500 in the Type field. The only
frames with numbers less than 1500 in the type field are 802.3 frames.
SANA-II ethernet drivers abnormally return packets contained in ethernet
frames when the requested Type falls within the 802.3 range--if the Type
requested is within the 802.3 range, the driver returns the next packet
contained within an 802.3 frame, regardless of the type specified for the
packet within the 802.3 frame. This requires that there be no more than
one driver user requesting 802.3 packets and that it do its own
interpretation of the frames.


ARCNET Frames

ARCNET also has a special problem with framing. ARCNET frames consist of a
hardware header and a software header. The software header is in the data
area of the hardware packet, and includes at least the protocol ID.

There are two types of software header. Old-style ARCNET software headers
consist entirely of a one or two byte protocol ID. New ARCNET software
headers (defined in RFC 1201 and in the paper "ARCNET Packet Header
Definition Standard", Novell, Inc., 1989) include more information. They
allow more efficient use of ARCNET through data link layer fragmentation
and reassembly (ARCNET has a small Maximum Transmission Unit) and allow
sending any size packet up to the MTU (rather than requiring that packets
of size 253, 254 and 255 be padded to at least 256 bytes).

SANA-II device drivers for ARCNET should implement the old ARCNET packet
headers. Driver users which wish to interoperate with platforms using the
new software headers must add the new fields to the data to be sent and
must process it for incoming data. A SANA-II driver which implemented the
data link layer fragmentation internally (and advertised a large MTU)
could be more efficient than requiring the driver user to do it. This
would make driver writing more difficult and reduce interoperability, but
if there is ever a demand for that extra performance, a new hardware type
may be assigned by Commodore for SANA-II ARCNET device drivers which
implement the new framing.


Addressing

In the SANA-II standard, network hardware addresses are stored in an array
of n bytes. No meaning is ascribed by the standard to the contents of the
array.

In case there exists a network which does not have an address field
consisting of a number of bits not divisible by eight, add pad bits at the
end of the bit stream. For example, if an address is ten bits long it will
be stored like this:

    98765432 10PPPPPP
    BYTE 0   BYTE 1

Where the numerals are bit numbers and 'P' is a pad (ignored) bit.

Driver users which do not implement the bit shifting necessary to use a
network with such addressing (if one exists) should at least check the
number of significant bits in the address field (returned from the
device's S2_DEVICEQUERY function) to make sure that it is evenly divisible
by eight.

Driver users will map hardware addresses to protocol addresses in a
protocol and hardware dependent manner, as described by the relevant
standards (i.e., RFC 826 for TCP/IP over Ethernet, RFC 1201 or 1051 for
TCP/IP over ARCNET). Some protocols will always use the same mapping on
all hardware, but other protocols will have particular address mapping
schemes for some particular hardware and a reasonable default for other
(unknown) hardware.

Some SANA-II devices will have "hardware addresses" which aren't really
hardware addresses. As an example, consider PPP (Point-to-Point Protocol).
PPP is a standard for transmitting IP packets over a serial line. It uses
IP addresses negotiated during the establishment of a connection. In a
SANA-II driver implementation of PPP, the driver would negotiate the
address at S2_CONFIGINTERFACE. Thus, the address in SrcAddr returned by
the device on an S2_CONFIGINTERFACE (or in a subsequent
S2_GETSTATIONADDRESS) will be a protocol address, not a true hardware
address.

    Note:
    -----
    Some hardware always uses a ROM hardware address. Other hardware
    which has a ROM address or is configurable with DIP switches may be
    overridden by software. Some hardware always dynamically allocates a
    new hardware address at initialization. See "Configuration" for
    details on how this is handled by driver writers and by driver users.


Hardware Type

The HardwareType returned by the device's S2_DEVICEQUERY function is
necessary for those protocols whose standards require different behavior
on different hardware. It is also useful for determining appropriate
packet type numbers to use with the device. The HardwareType values
already issued for standard network hardware are the same as those in RFC
1060 (assigned numbers). Hardware developers implementing networks without
a SANA-II hardware number must contact CATS to have a new hardware type
number assigned. Driver users should all have reasonable defaults which
can be used for hardware with which they are not familiar.


Errors

The SANA-II extended IORequest structure (struct IOSana2Req) includes both
the ios2_Error and ios2_WireError fields. Driver users must always check
IOSana2Reqs on return for an error in ios2_Error. ios2_Error will be zero
if no error occurred, otherwise it will contain a value from
<exec/errors.h> or <devices/sana2.h>. If there was an error, there may be
more specific information in ios2_WireError. Drivers are required to fill
in the WireError if there is an applicable error code.

Error codes are #defined in the "defined errors" sections of the file
<devices/sana2.h>:

   IOSana2Req S2io_Error field (S2ERR_xxx):

   S2ERR_NO_RESOURCES     - Insufficient resources available.
   S2ERR_BAD_ARGUMENT     - Noticeably bad argument.
   S2ERR_BAD_STATE        - Command inappropriate for current state.
   S2ERR_BAD_ADDRESS      - Noticeably bad address.
   S2ERR_MTU_EXCEEDED     - Write data too large.
   S2ERR_NOT_SUPPORTED    - Command is not supported by this driver. This
                            is similar to IOERR_NOCMD as defined in
                            <exec/errors.h> but S2ERR_NOT_SUPPORTED
                            indicates that the requested command is a
                            valid SANA-II command and that the driver
                            does not support it because the hardware is
                            incapable of supporting it (e.g.,
                            S2_MULTICAST). Note that IOERR_NOCMD is still
                            valid for reasons other than a lack of
                            hardware support (i.e., commands which are
                            no-ops in a SANA-II driver).
   S2ERR_SOFTWARE         - Software error of some kind.
   S2ERR_OUTOFSERVICE     - When a hardware device is taken off-line, any
                            pending requests are returned with this error.

See also the standard errors in <exec/errors.h>.

   IOSana2Req S2io_WireError field (S2WERR_xxx):

   S2WERR_NOT_CONFIGURED  - Command requires unit to be configured.
   S2WERR_UNIT_ONLINE     - Command requires that the unit be off-line.
   S2WERR_UNIT_OFFLINE    - Command requires that the unit be on-line.
   S2WERR_ALREADY_TRACKED - Protocol is already being tracked.
   S2WERR_NOT_TRACKED     - Protocol is not being tracked.
   S2WERR_BUFF_ERROR      - Buffer management function returned an error.
   S2WERR_SRC_ADDRESS     - Problem with the source address field.
   S2WERR_DST_ADDRESS     - Problem with destination address field.
   S2WERR_BAD_BROADCAST   - Problem with an attempt to broadcast.
   S2WERR_BAD_MULTICAST   - Problem with an attempt to multicast.
   S2WERR_MULTICAST_FULL  - Multicast address list full.
   S2WERR_BAD_EVENT       - Event specified is unknown.
   S2WERR_BAD_STATDATA    - The S2IO_StatData pointer or the data it
                            points to failed a sanity check.
   S2WERR_IS_CONFIGURED   - Attempt to reconfigure the unit.
   S2WERR_NULL_POINTER    - A NULL pointer was detected in one of the
                            arguments. S2ERR_BAD_ARGUMENT should always
                            be the S2ERR.


Standard Commands

See the SANA-II Network Device Driver Autodocs for full details on each of
the SANA-II device commands. Extended commands are explained in the
sections below.

Many of the Exec device standard commands are no-ops in SANA-II devices,
but this may not always be the case. For example, CMD_RESET might someday
be used for dynamically reconfiguring hardware. This should present no
compatibility problems for properly written drivers.

 Broadcast and Multicast      Configuration
 Stats                        On-line


Broadcast and Multicast

  S2_ADDMULTICASTADDRESS        S2_MULTICAST
  S2_DELMULTICASTADDRESS        S2_BROADCAST

Some hardware supports broadcast and/or multicast. A broadcast is a packet
sent to all other machines. A multicast is a packet sent to a set of
machines. Drivers for hardware which does not allow broadcast or multicast
will return ios2_Error S2ERR_NOT_SUPPORTED as appropriate.

To send a broadcast, use S2_BROADCAST instead of CMD_WRITE. Broadcasts are
received just like any other packets (using a CMD_READ for the appropriate
packet type).

To send a multicast, use S2_MULTICAST instead of CMD_WRITE. The device
keeps a list of addresses that want to receive multicasts. You add a
receiver's address to this list by using S2_ADDMULTICASTADDRESS. The
receiver then posts a CMD_READ for the type of packet to be received. Some
SANA-II devices which support multicast may have a limit on the number of
addresses that can simultaneously wait for packets. Always check for an
S2WERR_MULTICAST_FULL error return when adding a multicast address.

Note that when the device adds a multicast address, it is usually added
for all users of the device, not just the driver user which called
S2_ADDMULTICASTADDRESS. In other words, received multicast packets will
fill a read request of the appropriate type regardless of whether the
requesting driver user is the same one which added the multicast address.

In general, driver users should not care how received packets were sent
(normally or broadcast/multicast), only that it was received. If a driver
user really must know, however, it can check for SANA2IOB_BCAST and/or
SANA2IOB_MCAST in the ios2_Flags field.

Drivers should keep a count for the number of opens on a multicast address
so that they don't actually remove it until it has been
S2_DELMULTICASTADDRESS'd as many times as it has been
S2_ADDMULTICASTADDRESS'd.


Stats

  S2_TRACKTYPE     S2_GETTYPESTATS      S2_GETGLOBALSTATS
  S2_UNTRACKTYPE   S2_GETSPECIALSTATS   S2_READORPHAN

There are many statistics which may be very important to someone trying to
debug, tune or optimize a protocol stack, as well as to the end user who
may need to tune parameters or investigate a problem. Some of these
statistics can only be kept by the SANA-II driver, thus there are several
required and optional statistics and commands for this purpose.

S2_TRACKTYPE tells the device driver to gather statistics for a particular
packet type. S2_UNTRACKTYPE tells it to stop (keeping statistics by type
causes the driver to use additional resources). S2_GETTYPESTATS returns
any statistics accumulated by the driver for a type being tracked (stats
are lost when a type is S2_UNTRACKTYPE'd). Drivers are required to
implement the functionality of type tracking. The stats are returned in a
struct Sana2PacketTypeStats:

        struct Sana2PacketTypeStats
        {
          ULONG PacketsSent;
          ULONG PacketsReceived;
          ULONG BytesSent;
          ULONG BytesReceived;
          ULONG PacketsDropped;
        };

    PacketsSent     - Number of packets of a particular type sent.
    PacketsReceived - Number of packets of a particular type that
                      satisfied a read command.
    BytesSent       - Number of bytes of data sent in packets of a
                      particular type.
    BytesReceived   - Number of bytes of data of a particular packet
                      type that satisfied a read command.
    PacketsDropped  - Number of packets of a particular type that were
                      received while there were no pending reads of that
                      packet type.

S2_GETGLOBALSTATS returns global statistics kept by the driver. Drivers
are required to keep all applicable statistics. Since all are applicable
to most hardware, most drivers will maintain all statistics. The stats are
returned in a struct Sana2DeviceStats:

        struct Sana2DeviceStats
        {
          ULONG PacketsReceived;
          ULONG PacketsSent;
          ULONG BadData;
          ULONG Overruns;
          ULONG UnknownTypesReceived;
          ULONG Reconfigurations;
          struct timeval LastStart;
        };

    PacketsReceived     - Number of packets that this unit has received.
    PacketsSent         - Number of packets that this unit has sent.
    BadData             - Number of bad packets received (i.e., hardware
                          CRC failed).
    Overruns            - Number of packets dropped due to insufficient
                          resources available in the network interface.
    UnknownTypeReceived - Number of packets received that had no pending
                          read command with the appropriate packet type.
    Reconfigurations    - Number of network reconfigurations since this
                          unit was last configured.
    LastStart           - The time when this unit last went on-line.

S2_GETSPECIALSTATS returns any special statistics kept by a particular
driver. Each new wire type will have a set of documented, required
statistics for that wire type and a standard set of optional statistics
for that wire type (optional because they might not be available from all
hardware). The data returned by S2_GETSPECIALSTATS will require
wire-specific interpretation. See <devices/sana2specialstats.h> for
currently defined special statistics. The statistics are returned in the
following structures:

        struct Sana2SpecialStatRecord
        {
          ULONG Type;
          ULONG Count;
          char *String;
        };

    Type   - Statistic identifier.
    Count  - Statistic itself.
    String - An identifying, null-terminated string for the statistic.
             Should be plain ASCII with no formatting characters.

        struct Sana2SpecialStatHeader
        {
          ULONG RecordCountMax;
          ULONG RecordCountSupplied;
          struct Sana2SpecialStatRecord[RecordCountMax];
        };

    RecordCountMax      - There is space for this many records into which
                          statistics may be placed.
    RecordCountSupplied - Number of statistic records supplied.

S2_READORPHAN is not, strictly speaking, a statistical function. It is a
request to read any packet of a type for which there is no outstanding
CMD_READ. S2_READORPHAN might be used in the same manner as many
statistics, though, such as to determine what packet types are causing
overruns, etc.


Configuration

  S2_DEVICEQUERY     S2_CONFIGINTERFACE    S2_GETSTATIONADDRESS

The device driver needs to configure the hardware before using it. The
driver user must know some network hardware parameters (hardware address
and MTU, for example) when using it. These commands address those needs.

When a driver user is initialized, it should try to S2_CONFIGINTERFACE
even though an interface can only be configured once and someone else may
have done it. Before you call S2_CONFIGINTERFACE, first call
S2_GETSTATIONADDRESS to determine the factory address (if any). Also
provide for user-override of the factory address (that address may be
optional and the user may need to override it). When S2_CONFIGINTERFACE
returns, check the ios2_SrcAddr for the actual address the hardware has
been configured with. This is because some hardware (or serial line
standards such as PPP) always dynamically allocates an address at
initialization.

Driver users will want to use S2_DEVICEQUERY to determine the MTU and
other characteristics of the network. The structure returned from
S2_DEVICEQUERY is defined as:

        struct Sana2DeviceQuery
        {
          ULONG SizeAvailable;
          ULONG SizeSupplied;
          ULONG DevQueryFormat;
          ULONG DeviceLevel;
          UWORD AddrFieldSize;
          ULONG MTU;
          ULONG BPS;
          ULONG HardwareType;
        };

    SizeAvailable  - Size, in bytes, of the space available in which to
                     place device information. This includes both size
                     fields.
    SizeSupplied   - Size, in bytes, of the data supplied.
    DevQueryFormat - The format defined here is format 0.
    DeviceLevel    - This spec defines level 0.
    AddrFieldSize  - The number of bits in an interface address.
    MTU            - Maximum Transmission Unit, the size, in bytes,
                     of the maximum packet size, not including header
                     and trailer information.
    BPS            - Best guess at the raw line rate for this network
                     in bits per second.
    HardwareType   - Specifies the type of network hardware the driver
                     controls.


On-line

     S2_ONLINE       S2_ONEVENT       S2_OFFLINE

In order to run hardware tests on an otherwise live system, the S2_OFFLINE
command allows the SANA-II device driver to be "turned off" until the
tests are complete and an ONLINE is sent to the driver. S2_ONLINE causes
the interface to re-configure and re-initialize. Any packets destined for
the hardware while the device is off-line will be lost. All pending and
new requests to the driver shall be returned with S2ERR_OUTOFSERVICE when
a device is off-line.

All driver users must understand that any IO request may return with
S2ERR_OUTOFSERVICE because the driver is off-line (any other program may
call S2_OFFLINE to make it so). In such an event, the driver will usually
want to wait until the unit comes back on-line (for the program which
called S2_OFFLINE to call S2_ONLINE). It may do this by calling S2_ONEVENT
to wait for S2EVENT_ONLINE. S2_ONEVENT allows the driver user to wait on
various events.

A driver must track events, but may not distinguish between some types of
events. Drivers return S2_ONEVENT with S2_ERR_NOT SUPPORTED and
S2WERR_BAD_EVENT for unsupported Events. One error may cause more than one
Event (see below). Errors which seem to have been caused by a malformed or
unusual request should not generally trigger an event.

    Event types (S2EVENT_xxx):

      ERROR    - Return when any error occurs.
      TX       - Return on any transmit error (always an error).
      RX       - Return on any receive error (always an error).
      ONLINE   - Return when unit goes on-line or return immediately if
                 unit is already on-line (not an error).
      OFFLINE  - Return when unit goes off-line or return immediately if
                 unit is already off-line (not an error.)
      BUFF     - Return on any buffer management function error (always
                 an error).
      HARDWARE - Return when any hardware error occurs (always an error,
                 may be a TX or RX, too).
      SOFTWARE - Return when any software error occurs (always an error,
                 may be a TX or RX, too).


Acknowledgments

Many people and companies have contributed to the SANA-II Network Device
Driver Specification. The original SANA-II Autodocs and includes were put
together by Ray Brand, Perry Kivolowitz (ASDG) and Martin Hunt. Those
original documents evolved to their current state and grew to include this
document at the hands of Dale Larson and Greg Miller. Brian Jackson and
John Orr provided valuable editing. Randell Jesup has provided sage advice
on several occasions. The buffer management callback mechanism was his
idea. Dale Luck (GfxBase) and Rick Spanbauer (Ameristar Technologies) have
provided valuable comments throughout the process. Nicolas Benezan
(ADONIS) provided many detailed and useful comments on weaknesses in late
drafts of the specification. Thanks to all the above and the numerous
others who have contributed with their comments, questions and
discussions.


Unresolved Issues

Unfortunately, it isn't possible to completely isolate network protocols
from the hardware they run on. Hardware types and addressing both remain
somewhat hardware-dependent in spite of our efforts. See the "Packet Type"
section for an explanation of how packet types are handled and why
protocols cannot be isolated from them. See the "Addressing" section for
an explanation of how addressing is handled any why protocols cannot be
isolated from it.

Additionally, there are at least two cases where a hardware type has
multiple framing methods in use (ethernet/802.3 and arcnet/(Novell)
"ARCNET Packet Header Definition Standard"). In both cases, software which
must interoperate with other platforms on this hardware may need to be
aware of the distinctions and may have to do extra processing in order to
use the appropriate frame type. See the sections on
"Ethernet Packet Types" and on "ARCNET frames" for more details.


IX-1: Four Can Play-Supporting Parallel Port Joysticks

by Chris Ludwig

One of the many reasons people buy computer-based products is to use
them as an "entertainment box".  Amiga users are no exception in this
regard.  The Amiga has all the ingredients needed to be a great game
machine; fast high-quality graphics, high-fidelity stereo sound, fast
processor, and built-in joystick ports.

With this level of hardware support, it's no wonder that some of the
industry's best games continue to be written for the Amiga first.

The only kind of games that don't currently lend themselves to the
Amiga's built-in hardware are those that are meant to be played by more
than two players simultaneously.  Several types of games fall into this
category, the most notable being the scrolling cooperative.  This type
of game, where up to four players control on-screen versions of
themselves, is quite popular in video arcades.  Another format that
lends itself to having more than two joysticks is the board game
simulation.  It's simply easier to play a four player board game if
each player has his or her own control.

Because the Amiga has only two joystick ports, there are currently only
a small number of "greater than two" player games available.  So how
do these games get around the two port limitation?  The developers of
these games have worked up a little bit of external hardware that
remaps some parallel port input lines as two more joystick ports for
single button joysticks.

Fortunately, these developers are all using the same wiring in their
interfaces.  Unfortunately, neither the interface nor its
specifications have been widely available.

This article explains the construction of these parallel port joystick
adapters (this article refers to them "+2" adapters), and
demonstrates a coding strategy which will allow your software to access
these two new ports.  Though the instructions are fairly simple, if not
done properly, it is possible to damage your computer, so Commodore
does not recommend that you build these yourself.  This information is
provided for your convenience and is expressly subject to the
disclaimer and warnings found at the beginning of this publication.

 Building the +2 Interface
 Housing the Interface
 Supporting the Interface in Software


Building the +2 Interface

The interface that these two extra joystick ports require is quite
straightforward in design and does not require any power.  Essentially,
two male 9-pin "d-sub" connectors (the type commonly used for
joystick ports) are wired directly to a 25-pin "d-sub" connector.

The gender of the 25-pin connector depends on the Amiga model.  Amiga
1000 computers have a non-standard, male 25-pin parallel port, so the
Amiga 1000 adapters will need a female connector.  All other Amigas
have standard female 25-pin parallel ports, so adapters for A500, A600,
A2000, A3000, A3000T, and CDTV units should have a male 25-pin
connector.

The only difference between the requirements for the A1000 "+2"
adapter and the "+2" adapter for the rest of the Amiga/CDTV product
line is the gender.  The "+2" adapter only uses parallel port pins
that all Amigas/CDTVs have in common.  These particular pins were
chosen so that one "+2" adapter and a gender changer could connect
two joysticks to any existing Amiga.  Because some of the unused pins
carry voltages, only wire the pins specified in the chart!  Doing
otherwise can destroy components inside the Amiga!

  Parallel function   Parallel port   JOY3    JOY4    Joystick function
                      (25 pin male)   (9pm)   (9pm)
  ---------------------------------------------------------------------
  Data bit 0                2           1               JOY3 UP
  Data bit 1                3           2               JOY3 DOWN
  Data bit 2                4           3               JOY3 LEFT
  Data bit 3                5           4               JOY3 RIGHT

  Data bit 4                6                   1       JOY4 UP
  Data bit 5                7                   2       JOY4 DOWN
  Data bit 6                8                   3       JOY4 LEFT
  Data bit 7                9                   4       JOY4 RIGHT

  Busy                      11                  6       JOY4 FIRE
  Select (Online)           13          6               JOY3 FIRE

  ground                    18                  8       JOY4 GROUND
  ground                    19          8               JOY3 GROUND

                        The "+2" Interface


Housing the Interface

For development purposes, you can construct a "+2" adapter from two
25-pin male d-sub connectors.  One connector attaches to the parallel
port, while the other accepts the two 9-pin female joystick plugs.
Simply build the "number 3" joystick connector into the leftmost 9
pins, and the "number 4" connector into the rightmost 9 pins.  The
pin-outs for this setup are in the "Non-Production +2 Interface"
chart below.

  Parallel function   Parallel port   JOY3    JOY4    Joystick function
                      (25 pin male)   (9pm)   (9pm)
  ---------------------------------------------------------------------
  Data bit 0                2           1               JOY3 UP
  Data bit 1                3           2               JOY3 DOWN
  Data bit 2                4           3               JOY3 LEFT
  Data bit 3                5           4               JOY3 RIGHT

  Data bit 4                6                   9       JOY4 UP
  Data bit 5                7                   10      JOY4 DOWN
  Data bit 6                8                   11      JOY4 LEFT
  Data bit 7                9                   12      JOY4 RIGHT

  Busy                      11                  22      JOY4 FIRE
  Select (Online)           13          14              JOY3 FIRE

  ground                    18                  24      JOY4 GROUND
  ground                    19          16              JOY3 GROUND

                  The Non-Productive "+2" Interface

This arrangement is attractive to developers primarily because it has
few parts and it's easy to construct.  It is appropriate only for
developer use and testing.  Do not consider it for any sort of user
distribution, because the connectors for certain brands of joysticks
are too big to fit side by side into a 25-pin connector.  Users will
become quite irate upon finding that they can't use their "wiz-stik
5000" with their 4 player game adapter.

With this in mind, adapters intended for use by end users should be
built into some sort of casework.  The box should include two suitably
spaced joystick connectors, and a cable that allows the user to easily
attach the adapter to the parallel port.  Be sure that the cable is
long enough to allow users to place the adapter where they can get to
it easily.

Alternatively, the device could simply be a pair of long cables in a
"Y" shape, with a parallel connector at the base of the "Y", and
joystick connector on the other ends.  Such an adapter would probably
be the cheapest way to go.

Developers must caution end users to turn their computer's power off
before plugging in a "+2" adapter.  This will prevent users from
accidentally destroying the 8520 chips which control the parallel port.
To further prevent 8520 damage, developers should choose 25-pin
connectors without a metal case or shield.  While plugging the device
in, it's rather easy to accidentally brush (and short) the metal
shields of certain connectors against the pins of the parallel port.

No matter what the decision regarding implementation, remember that
game players can be quite rough.  All cables should be suitably long,
and all connectors should utilize a proper strain relief system.


Supporting the Interface in Software

Because this "+2" joystick adapter attaches to the parallel port,
supporting it in software is simply a matter of reading the correct
lines on the parallel port.

Many Amiga game programmers make the decision to throw away the OS and
directly manipulate the hardware.  These programmers will no doubt come
up with their own personal scheme for reading the appropriate
information from the port.  Other, more forward thinking developers,
may want to write their software in such a way as to be compatible with
the OS.

The following pair of code samples work in tandem to demonstrate one
method of reading the necessary information from the parallel port in
an OS friendly manner.  The C program 4play.c is a simple example that
demonstrates how to access the assembly functions.  The assembly
language program read34.asm properly allocates the parallel port and any
necessary signal lines, warning the OS not to let any other applications
use them.  Other assembly routines do the actual hardware level reading
and place the joystick values into C variables.  A cleanup routine
releases the port and signal lines.  The example does not mask out the
directional or fire button bits, it only prints the raw joystick data.
I'll leave it as an exercise for the reader to interpret the meaning of
the raw data.

   lmkfile


XI-1: Introduction to Commodities Exchange

by John Orr

The input.device has a hand in almost all user input on the Amiga.  It
gathers input events from the keyboard, the gameport (mouse), and
several other sources, into one input "stream".  Special programs
called input event handlers intercept input events
 along this stream, examining and sometimes changing the input events.
Both Intuition and the console device use input handlers to process
user input.

Using the input.device, a program can introduce its own custom handler
into the chain of input handlers at almost any point in the chain.
"Hot key" programs, shell pop-up programs, and screen blankers all
commonly use custom input handlers to monitor u ser input before it
gets to the Intuition input handler.

Custom input handlers do have their drawbacks, however.  Not only are
these handlers hard to program, but because there is no standard way
to implement and control them, multiple handlers often do not work
well together.  Their antisocial behavior can res ult in load order
dependencies and incompatibilities between different custom input
handlers.  Even for the expert user, having several custom input
handlers coexist peacefully can be next to impossible.  The custom
input handler needs to take its next ev olutionary step.

Commodities Exchange is that step.  It provides a simple, standardized
way to program and control custom input handlers.  It is divided into
three parts: an Exec library, a controller program, and a scanned
library.

The Exec library is called commodities.library.  When it is first
opened, commodities.library establishes a single input handler just
before Intuition in the input chain.  When this input handler receives
an input event, it creates a CxMessage (Commoditie s Exchange Message)
corresponding to the input event, and diverts the CxMessage through
the network of Commodities Exchange input handlers.  These handlers
are made up of trees of different CxObjects (Commodities Exchange
Objects), each of which performs a simple operation on the CxMessages.
Any CxMessages that exit the network are returned to the
input.device's input stream as input events.

Through function calls to the commodities.library, an application can
install a custom input handler.  A Commodities Exchange application,
sometimes simply referred to as a commodity, uses the CxObject
primitives to do things such as filter certain CxMess ages, translate
CxMessages, signal a task when a CxObject receives a CxMessage, send a
message when a CxObject receives a CxMessage, or if necessary, call a
custom function when a CxObject receives a CxMessage.

The controller program is called Commodities Exchange.  The user can
monitor and control all the currently running Commodities Exchange
applications from this one program.  The user can enable and disable a
commodity, kill a commodity, or, if the commodit y has a window, ask
the commodity to show or hide its window.  When the user requests any
of these actions, the controller program sends the commodity a
message, telling it which action to perform.

The third component of Commodities Exchange is its scanned library
functions.  These functions are part of the amiga.lib scanned library.
They do a lot of the work involved with parsing command lines and tool
types.

Commodities Exchange is ideal for programs like hot keys/pop ups,
screen blankers, and mouse blankers that need to monitor all user
input.  Commodities Exchange should not be used as an alternate
method of receiving user input for an application.  Other a
pplications depend on getting user input in some form or another from
the input stream.  A greedy program that diverts input to itself
rather than letting the input go to where the user expects it can
seriously confuse the user, not to mention compromise the advantages
of multitasking.

 CxObjects                Filter CxObjects         Uniqueness
 Installing a Broker      Senders CxObjects        DeleteCxObjAll()
 CxMessages               Translate CxObjects      Other CxObjects
 Tool Types               CxObject Errors          IX


CxObjects

CxObjects are the basic building blocks used to construct a
commodity. A commodity uses CxObjects to take care of all
manipulations of CxMessages. When a CxMessage "arrives" at a
CxObject, that CxObject carries out its primitive action and then, if
it has not deleted the CxMessage, it passes the CxMessage on to the
next CxObject.  A commodity links together CxObjects into a tree,
organizing these simple action objects to perform some higher
function.

A CxObject is in one of two states, active or inactive.  An active
CxObject performs its primitive action every time it receives a
CxMessage.  If a CxObject is inactive, CxMessages bypass it,
continuing to the CxObject that follows the inactive one.  By d
efault, all CxObjects except the type called brokers are created in
the active state.

   Figure 1: The Commodities Network


Installing a Broker

The Commodities Exchange input handler maintains a master list of
CxObjects to which it diverts input events using CxMessages.  The
CxObjects in this master list are a special type of CxObject called a
broker.  The only thing a broker CxObject does is div ert CxMessages
to its own personal list of CxObjects.  A commodity creates a broker
and attaches other CxObjects to it.  These attached objects take care
of the actual input handler related work of the commodity and make up
the broker's personal list.

Program listing 1, Broker.c, (located at the end of this article) is a
very simple example of a working commodity.  It serves only to
illustrate the basics of a commodity, not to actually perform any
useful function.  It shows how to set up a broker and p rocess
commands from the controller program.

Besides opening commodities.library and creating an Exec message
port, setting up a commodity requires creating a broker.  The
function CxBroker() creates a broker and adds it to the master list.

    CxObj *CxBroker(struct NewBroker *nb, long *error);

CxBroker()'s first argument is a pointer to a NewBroker structure:

    struct NewBroker {
       BYTE     nb_Version;  /* There's an implicit pad byte after */
       BYTE     *nb_Name;    /*     this BYTE */
       BYTE     *nb_Title;
       BYTE     *nb_Descr;
       SHORT    nb_Unique;
       SHORT    nb_Flags;
       BYTE     nb_Pri; /* There's an implicit pad byte after this BYTE */
       struct   MsgPort   *nb_Port;
       WORD     nb_ReservedChannel;
    };

Commodities Exchange gets all the information it needs about the
broker from this structure.  NewBroker's nb_Version field contains
the version number of the NewBroker structure.  This should be set to
NB_VERSION which is defined in <libraries/commodities .h>.  The
nb_Name, nb_Title, and nb_Descr point to strings which hold the name,
title, and description of the broker.  The two bit fields, nb_Unique
and nb_Flags, toggle certain features of Commodities Exchange based
on their values.  They are discussed in detail later in this article.

The nb_Pri field contains the broker's priority.  Commodities Exchange
inserts the broker into the master list based on this number.  Higher
priority brokers get CxMessages before lower priority brokers.

CxBroker()'s second argument is a pointer to a LONG.  If this pointer
is not NULL, CxBroker() fills in this field with one of the following
codes from <libraries/commodities.h>:

    CBERR_OK        0        /* No error                         */
    CBERR_SYSERR    1        /* System error , no memory, etc    */
    CBERR_DUP       2        /* uniqueness violation             */
    CBERR_VERSION   3        /* didn't understand nb_VERSION     */


CxMessages

There are actually two types of CxMessages.  The first, CXM_IEVENT,
corresponds to an input event and travels through the Commodities
Exchange network.  The other type, CXM_COMMAND, carries a command to
a commodity.  A CXM_COMMAND normally comes from the controller
program and is used to pass user commands on to a commodity.  A
commodity receives these commands through an Exec message port that
the commodity sets up before it calls CxBroker.  The NewBroker's
nb_Port field points to this message port.  A c ommodity can tell the
difference between the two types of CxMessages by calling the
CxMsgType() function.

    ULONG CxMsgType(CxMsg *cxm);
    UBYTE *CxMsgData(CxMsg *cxm);
    LONG  CxMsgID(CxMsg *cxm);

A CxMessage not only has a type, it can also have a data pointer as
well as an ID associated with it.  The data associated with a
CXM_IEVENT is an InputEvent structure.  By using the CxMsgData()
function, a commodity can obtain a pointer to the correspond ing
InputEvent of a CXM_IEVENT.  Commodities Exchange does not give an ID
to the CXM_IEVENT CxMessages it introduces to the Commodities network,
but certain CxObjects can assign an ID to a CXM_IEVENT CxMessage.

CXM_COMMAND CxMessages generally do not use the data pointer.
Instead, they use an ID.  They use this ID to specify the command
passed to a commodity.  CxMsgID() extracts the ID from a CxMessage.

    oldactivationvalue = LONG ActivateCxObj(CxObj *co,
                           long newactivationvalue);

After successfully completing the initial set up and activating the
broker using ActivateCxObj(), a commodity can begin its input
processing loop.  The example Broker.c receives input from one source,
the controller program.  The controller program sends a CxMessage each
time the user clicks its enable, disable, or kill gadgets.  Using the
CxMsgID() function, the commodity finds out what the command is and
executes it.

Notice that Broker.c uses Ctrl-C as a break key.  This is a change
from 1990 Atlanta DevCon Notes on Commodities Exchange which said to
use Ctrl-E.  The break key for any commodity should be Ctrl-C.

The commands that a commodity can receive from the controller program
(as defined in <libraries/commodities.h>) are:

    CXCMD_DISABLE     /* please disable yourself       */
    CXCMD_ENABLE      /* please enable yourself        */
    CXCMD_KILL        /* go away for good              */
    CXCMD_APPEAR      /* open your window, if you can  */
    CXCMD_DISAPPEAR   /* hide your window              */

The CXCMD_DISABLE, CXCMD_ENABLE, and CXCMD_KILL commands correspond
to the similarly named controller program gadgets, "Disable",
"Enable", and "Kill"; CXCMD_APPEAR and CXCMD_DISAPPEAR correspond to
the controller program gadgets, "Show" and "Hi de".  These gadgets
are ghosted in Broker.c because it has no window (It doesn't make
much sense to give the user a chance to click the "Show" and "Hide"
gadgets).  In order to do this, Broker.c has to tell Commodities
Exchange to ghost these gadge ts.  When CxBroker() sets up a broker,
it looks at the NewBroker.nb_Flags field to see if the COF_SHOW_HIDE
bit (from <libraries/commodities.h>) is set.  If it is, the "Show"
and "Hide" gadgets for this broker will be selectable. Otherwise they
are g hosted and disabled.

Shutting down a commodity is easy.  After replying to all CxMessages
waiting at the broker's message port, a commodity can delete its
CxObjects.  DeleteCxObj() removes a single CxObject from the
Commodities network.

    void DeleteCxObj(CxObj *co);


Tool Types

A goal of Commodities Exchange is to improve user control over input
handlers.  One way in which it accomplishes this is through the use of
standard ToolTypes.  The user will expect commodities to recognize the
set of standard tool types:

    CX_PRIORITY
    CX_POPUP
    CX_POPKEY

CX_PRIORITY lets the user set the priority of a commodity.  The string
"CX_PRIORITY=" is a number from -128 to 127.  The higher the number,
the higher the priority of the commodity, giving it access to input
events before lower priority commodities.  All commodities should
recognize CX_PRIORITY.

CX_POPUP and CX_POPKEY are only relevant to commodities with a window.
The string "CX_POPUP=" should be followed by a "yes" or "no", telling
the commodity if it should or shouldn't show its window when it is
first launched.  CX_POPKEY is followed by a st ring describing the key
to use as a hot key for "popping up" the commodity's window.  The
description string for CX_POPKEY describes an input event.  The
specific format of the string is discussed later in this article.

Commodities Exchange's support library functions simplify parsing
arguments from either the Workbench or a CLI.  A Workbench launched
commodity gets its arguments directly from the tool types in the
commodity's icon.  CLI launched commodities get their ar guments from
the command line, but these arguments look exactly like the tool types
from the commodity's icon.  For example, the following command line
sets the priority of a commodity called HotKey to 5:

    HotKey "CX_PRIORITY=5"

Commodities Exchange has several support library functions used to
parse arguments:

    tooltypearray = char **ArgArrayInit(int argc, char **argv);
    void ArgArrayDone(void);
    tooltypevalue = char *ArgString(char **tooltypearray,
                                char *tooltype, char *defaultvalue);
    tooltypevalue = LONG *ArgInt(char **tooltypearray,
                                char *tooltype, LONG defaultvalue);

ArgArrayInit() initializes a tool type array of strings which it
creates from the startup arguments, argc and argv.  It doesn't matter
if these startup arguments come from the Workbench or from a CLI,
ArgArrayInit() can extract arguments from either source.  Because
ArgArrayInit() uses some icon.library functions, a commodity is
responsible for opening that library before using the function.

ArgArrayInit() also uses some resources that must be returned to the
system when the commodity is done.  ArgArrayDone() performs this clean
up.  Like ArgArrayInit(), ArgArrayDone() uses icon.library, so the
library has to remain open until ArgArrayDone() is finished.

The support library has two functions that use the tool type array
set up by ArgArrayInit(), ArgString() and ArgInt().  ArgString()
scans the tool type array for a specific tool type.  If successful,
it returns a pointer to the value associated with that tool type.  If
it doesn't find the tool type, it returns the default value passed to
it. ArgInt() is similar to ArgString().  It also scans the
ArgArrayInit()'s tool type array, but it returns a LONG rather than a
string pointer.  ArgInt() extracts the i nteger value associated with
a tool type, or, if that tool type is not present, it returns the
default value.

Of course, these tool type parsing functions are not restricted to the
standard Commodities Exchange tool types.  A commodity that requires
any arguments should use these functions along with custom tool types
to obtain these values.  Because the Commodit ies Exchange standard
arguments are processed as tool types, the user will expect to enter
other arguments as tool types.


Filter CxObjects

Because not all commodities are interested in every input event that
makes it way down the input chain, Commodities Exchange has a method
for filtering them.  A filter CxObject compares the CxMessages it
receives to a pattern.  If a CxMessage matches the pattern, the filter
diverts the CxMessage down its personal list of CxObjects.

    CxObj *CxFilter(char *descriptionstring);

The C macro CxFilter() (defined in <libraries/commodities.h>) returns
a pointer to a filter CxObject.  The macro has only one argument, a
pointer to a string describing which input events to filter.  The
following regular expression outlines the format of a description
string (CX_POPKEY uses the same description string format):

    [class]  ( [-] (qual | syn) )*  [ [-] upstroke]  [highmap |ANSICode]
             the * means zero or more occurances of ( [-] ( qual | syn ) )

where:

class can be any one of the strings in the table below.  Each string
corresponds to a class of input event (shown below).  The classes are
defined in <devices/inputevent.h>.  Commodities Exchange will assume
the class is rawkey if the class is not explici tly stated.

    "rawkey"        IECLASS_RAWKEY
    "rawmouse"      IECLASS_RAWMOUSE
    "event"         IECLASS_EVENT
    "pointerpos"    IECLASS_POINTERPOS
    "timer"         IECLASS_TIMER
    "newprefs"      IECLASS_NEWPREFS
    "diskremoved"   IECLASS_DISKREMOVED
    "diskinserted"  IECLASS_DISKINSERTED

qual is one of the strings in the table below.  Each string
corresponds to an input event qualifier (followed by its ID from
<devices/inputevent.h>).  A dash preceding the qualifier string tells
the filter object not to care if that qualifier is present i n the
input event.  Notice that there can be more than one qual (or none at
all) in the input description string.

    "lshift"            IEQUALIFIER_LSHIFT
    "rshift"            IEQUALIFIER_RSHIFT
    "capslock"          IEQUALIFIER_CAPSLOCK
    "control"           IEQUALIFIER_CONTROL
    "lalt"              IEQUALIFIER_LALT
    "ralt"              IEQUALIFIER_RALT
    "lcommand"          IEQUALIFIER_LCOMMAND
    "rcommand"          IEQUALIFIER_RCOMMAND
    "numericpad"        IEQUALIFIER_NUMERICPAD
    "repeat"            IEQUALIFIER_REPEAT
    "midbutton"         IEQUALIFIER_MIDBUTTON
    "rbutton"           IEQUALIFIER_RBUTTON
    "leftbutton"        IEQUALIFIER_LEFTBUTTON
    "relativemouse"     IEQUALIFIER_RELATIVEMOUSE

syn is one of the strings in the table below.  These strings act as
synonyms for groups of qualifiers.  Each string below is followed by
its identifier from <libraries/commodities.h>.  A dash preceding the
synonym string tells the filter object not to car e if that qualifier
is present in the input event.  Notice that there can be more than one
syn (or none at all) in the input description string.

    "shift"     IXSYM_SHIFT    /* look for either shift key */
    "caps"      IXSYM_CAPS     /* look for either shift key or capslock */
    "alt"       IXSYM_ALT      /* look for either alt key */

upstroke is the literal string "upstroke".  If this string is absent,
the filter considers only downstrokes.  If is present alone, the
filter considers only upstrokes.  If preceded by a dash, the filter
considers both upstrokes and downstrokes.

highmap is one of the following strings:

    "space", "backspace", "tab", "enter", "return", "esc", "del", "up",
    "down", "right", "left", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
    "f8", "f9", "f10", "help".

ANSICode is a single character (for example `a`) that Commodities
Exchange looks up in the system default keymap.

The following are some example description strings:

    "rawkey lshift alt f2"    Function key f2 with the left shift and
                                either alt key pressed.
    "-shift -alt -control a"  The key that produces an 'a' with or
                                without any shift, alt, or control keys
                                pressed.
    "rawmouse rbutton"        A mouse move with the right mouse button
                                 down.
    "timer"                   A timer event.

As of commodities.library version 37.3, ParseIX(), the function used
to parse input description strings, does not parse certain classes
correctly.  Only the rawkey, diskremoved, and newprefs classes are
properly parsed.  For the moment, any commodity that needs to look
for the other classes must directly use Commodities Exchange's
internal format for input event descriptions, input expressions or
IX, discussed later in this article.

A filter has to be inserted into the Commodities network before it can
process any CxMessages.  AttachCxObj() adds a CxObject to the personal
list of another commodity.  The HotKey.c example uses this function to
attach its filter to a broker.

    void AttachCxObj(CxObj *HeadObj, CxObj *co);

This function uses the Exec function AddTail() to add the CxObject to
the end of HeadObj's personal list.  The position of a CxObject list
determines which CxObject gets CxMessages first.  Other functions
exist to add CxObjects at different points in the list (see the
commodities.doc Autodoc for details).


Senders CxObjects

A filter CxObject by itself is not especially useful.  It needs some
other CxObjects attached to it.  A commodity interested in knowing if
a specific key was pressed uses a filter to detect and divert the
corresponding CxMessage down the filter's personal list.  The filter
does this without letting the commodity know what happened.  The
sender CxObject is used to notify a commodity that it received a
CxMessage.  CxSender() is a macro that creates a sender CxObject.

    senderCxObj = CxObj *CxSender(struct MsgPort *senderport, LONG cxmID);

CxSender() supplies the sender with an Exec message port and an ID.
For every CxMessage a sender receives, it sends a new CxMessage to the
Exec message port passed in CxSender().  Normally, the commodity
creates this port.  It is not unusual for a commod ity's broker and
sender(s) to share an Exec message port.  The HotKey.c example does
this to avoid creating unnecessary message ports.  A sender uses the
ID (cxmID) passed to CxSender() as the ID for all the CxMessages that
the it transmits.  A commodity uses the ID to monitor CxMessages from
several senders at a single message port.

A sender does several things when it receives a CxMessage.  First, it
duplicates the CxMessage's corresponding input event and creates a new
CxMessage.  Then, it points the new CxMessage's data field to the copy
of the input event and sets the new CxMessa ge's ID to the ID passed
to CxSender().  Finally, it sends the new CxMessage to the port passed
to CxSender(), asynchronously.

Because HotKey uses only one message port between its broker and
sender object, it has to extract the CxMessage's type so it can tell
if it is a CXM_IEVENT or a CXM_COMMAND.  If HotKey gets a CXM_IEVENT,
it compares the CxMessage's ID to the sender's ID, EVT_HOTKEY, to see
which sender sent the CxMessage.  Of course HotKey has only one
sender, so it only checks for only one ID.  If it had more senders,
HotKey would check for the ID of each of the other senders as well.

Although HotKey doesn't use it, a CXM_IEVENT CxMessage contains a
pointer to the copy of an input event.  A commodity can extract this
pointer (using CxMsgData() ) if it needs to examine the input event
copy.  This pointer is only valid before the CxMessa ge reply.  Note
that it does not make any sense to modify the input event copy.

Senders are attached almost exclusively to CxObjects that filter out
most input events (usually a filter CxObject).  Because a sender
sends a CxMessage for every single input event it gets, it should
only get a select few input events.  The AttachCxObj() function can
add a CxObject to the end of a filter's (or some other filtering
CxObject's) personal list. A commodity should not attach a CxObject
to a sender as a sender ignores any CxObjects in its personal list.


Translate CxObjects

Normally, after a commodity processes a hot key input event, it needs
to eliminate the input event.  Other commodities may need to replace
an input event with a different one.  The translate CxObject can be
used for these purposes.

    translateCxObj = CxObj *CxTranslate(struct InputEvent *newinputevent);

The macro CxTranslate() creates a new translate CxObject.
CxTranslate()'s only argument is a pointer to a chain of one or more
InputEvent structures.  When a translate CxObject receives a
CxMessage, it eliminates the CxMessage and its corresponding input
event from the system.  The translator introduces a new input event,
which Commodities Exchange copies from the InputEvent structure passed
to CxTranlate() (newinputevent from the function prototype above), in
place of the deleted input event.  The trans lator introduces the new
input event after the Commodities Exchange input handler in the
input.device's input stream.  Any CxObjects that follow the translator
in the Commodities network will see neither the deleted CxMessage nor
the new input event.

A translator is normally attached to some kind of filtering CxObject.
If it wasn't, it would translate all input events into the same exact
input event.  Like the sender CxObject, a translator does not divert
CxMessages down its personal list, so it does n't serve any purpose to
add any to it.

HotKey utilizes a special kind of translator.  Instead of supplying a
new input event, HotKey passes a NULL to CxTranslate().  If a
translator has a NULL new input event pointer, it does not introduce a
new input event, but still eliminates any CxMessages and corresponding
input events it receives.


CxObject Errors

A Commodities Exchange function that acts on a CxObject records errors
in the CxObject's accumulated error field.  The function CxObjError()
returns a CxObject's error field.

    co_errorfield = LONG CxObjError( CxObj *co );

Each bit in the error field corresponds to a specific type of error.
The following is a list of the currently defined CxObject errors and
their corresponding bit mask constants.

    COERR_ISNULL             CxObjError() was passed a NULL.
    COERR_NULLATTACH         Someone tried to attach a NULL CxObj to this
    CxObj.  COERR_BADFILTER  This CxObj is a filter and currently has an
                               invalid filter description.
    COERR_BADTYPE            Someone tried to perform a type specific
                               function on the wrong kind of CxObject
                               (for example calling SetFilter() on a
                               sender CxObject).

The remaining bits are reserved by Commodore for future use.  HotKey
checks the error field of its filter CxObject to make sure the filter
is valid.  HotKey does not need to check the other objects with
CxObjError() because it already makes sure that thes e other objects
are not NULL, which is the only other kind of error the other objects
can cause in this situation.


Uniqueness

When a commodity opens its broker, it can ask Commodities Exchange not
to launch another broker with the same name (nb_Name).  This
uniqueness feature's purpose is to prevent the user from starting
duplicate commodities.  If a commodity asks, Commodities Exchange will
not only refuse to create a new, similarly named broker, but it will
also notify the original commodity if someone tries to do so.

A commodity tells Commodities Exchange not to allow duplicates by
setting certain bits in the nb_Unique field of the NewBroker structure
it sends to CxBroker():

    NBU_UNIQUE      bit 0
    NBU_NOTIFY      bit 1

Setting the NBU_UNIQUE bit prevents duplicate commodities.  Setting
the NBU_NOTIFY bit tells Commodities Exchange to notify a commodity if
an attempt was made to launch a duplicate.  Such a commodity will
receive a CXM_COMMAND CxMessage with an ID of CXCM D_UNIQUE when
someone tries to duplicate it.  Because the uniqueness feature uses
the name a programmer gives a commodity to differentiate it from other
commodities, it is possible for completely different commodities to
share the same name, preventing th e two from coexisting.  For this
reason, a commodity should not use a name that is likely to be in use
by other commodities (like "filter" or "hotkey").

When HotKey gets a CXCMD_UNIQUE CxMessage, it shuts itself down.
HotKey and all the windowless commodities that come with the 2.0
Workbench shut themselves down when they get a CXCMD_UNIQUE CxMessage.
Because the user will expect all windowless commodit ies to work this
way, all windowless commodities should follow this standard.

When the user tries to launch a duplicate of a system commodity that
has a window, the system commodity moves its window to the front of
the display, as if the user had clicked the "Show" gadget in the
controller program's window.  A windowed commodity should mimic
conventions set by existing windowed system commodities, and move its
window to the front of the display.


DeleteCxObjAll()

Cleaning up after a commodity requires deleting its CxObjects.  If a
commodity has a lot of CxObjects, deleting each individually can be a
bit tedious.  DeleteCxObjAll() will delete a CxObject and any other
CxObjects that are attached to it.

    void DeleteCxObjAll( CxObj *delete_co );

HotKey uses this function to delete all its CxObjects.  A commodity
that uses DeleteCxObjAll() to delete all its CxObjects should make
sure that they are all connected to the main one.


Other CxObjects

There are three remaining CxObjects:

    signalCxObj = CxObj  *CxSignal(struct Task *,LONG signal);
    debugCxObj  = CxObj  *CxDebug(LONG ID);
    customCxObj = CxObj  *CxCustom(LONG *customfunction(), LONG  cxmID);

When a signal CxObject receives a CxMessage, it signals a task.  When
a debug CxObject receives a CxMessage, it sends debugging information
to the serial port using kprintf().  Note that the debug CxObj did not
work before V37.

A custom CxObject is the only means by which a commodity can directly
modify input events as they pass through the Commodities network as
CxMessages.  The custom CxObject is probably the most dangerous of the
CxObjects to use.  Unlike the rest of the code
 a commodities programmer writes, the code passed to a custom CxObject
runs as part of the input.device task, putting severe restrictions on
the function.  No DOS or Intuition functions can be called.  No
assumptions can be made about the values of regist ers upon entry.
Any function passed to CxCustom() should be very quick and very
simple, with a minimum of stack usage.

Commodities Exchange calls a custom CxObject's function as follows:

    void customfunction(CxMsg *cxm, CxObj *customcxobj);

where cxm is a pointer to a CxMessage corresponding to a real input
event, and customcxobj is a pointer to the custom CxObject.  The
custom function can extract the pointer to the input event by calling
CxMsgData().  Before passing the CxMessage to the cu stom function,
Commodities Exchange sets the CxMessage's ID to the ID passed to
CxCustom().


IX

Commodities Exchange does not use the input event description strings
discussed earlier to match input events.  Instead, Commodities
Exchange converts these strings to its own internal format.  These
input expressions are available for commodities to use instead of the
input description strings.

The following is the IX structure as defined in
<libraries/commodities.h>:

    #define IX_VERSION   2

    struct InputXpression {
       UBYTE   ix_Version;     /* must be set to IX_VERSION  */
       UBYTE   ix_Class;       /* class must match exactly   */
       UWORD   ix_Code;
       UWORD   ix_CodeMask;    /* normally used for UPCODE   */
       UWORD   ix_Qualifier;
       UWORD   ix_QualMask;
       UWORD   ix_QualSame;    /* synonyms in qualifier      */
       };
    typedef struct InputXpression IX;

The ix_Version field contains the current version number of the
InputXpression structure.  The current version is defined as
IX_VERSION.  The ix_Class field contains the IECLASS_ constant (as
defined in <devices/inputevent.h>) of the particular class of i nput
event sought.  Commodities Exchange uses the ix_Code and ix_CodeMask
fields to match the ie_Code field of a struct InputEvent.  The bits of
ix_CodeMask indicate which bits are relevant in the ix_Code field when
trying to match against a ie_Code.  If any bits in ix_CodeMask are
off, Commodities Exchange does not consider the corresponding bit in
ie_Code when trying to match input events.  This is used primarily to
mask out the IECODE_UP_PREFIX bit of rawkey events, making it easier
to match both up an d down presses of a particular key.

IX's qualifier fields, ix_Qualifier, ix_QualMask, and ix_QualSame, are
used to match the ie_Qualifier field of an InputEvent structure.  The
ix_Qualifier and ix_QualMask fields work just like ix_Code and
ix_CodeMask.  The bits of ix_CodeMask indicate whic h bits are
relevant when comparing ix_Qualifier to ie_Qualifier.  The ix_QualSame
field tells Commodities Exchange that certain qualifiers are
equivalent.  The bits of this field can be set to any of the following
values:

    #define IXSYM_SHIFT  1  /* left- and right- shift are equivalent    */
    #define IXSYM_CAPS   2  /* either shift or caps lock are equivalent */
    #define IXSYM_ALT    4  /* left- and right- alt are equivalent      */

For example, the input description string

    "rawkey -caps -lalt -relativemouse -upstroke ralt tab"

matches a tab upstroke or downstroke with the right alt key pressed
whether or not the left alt, either shift, or the capslock keys are
down.  The following IX structure corresponds to that input
description string:

IX ix = {
    IX_VERSION,             /* The version */
    IECLASS_RAWKEY,         /* We're looking for a RAWKEY event */
    0x42,                   /* The key the usa0 keymap maps to a tab */
    0x00FF & (~IECODE_UP_PREFIX), /* We want up and down key presses */
    IEQUALIFIER_RALT,             /* The right alt key must be down */
    0xFFFF & ~(IEQUALIFIER_LALT | IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT |
                IEQUALIFIER_CAPSLOCK | IEQUALIFIER_RELATIVEMOUSE),
                /* don't care about left alt, shift, capslock,
                   or relativemouse qualifiers */
    IXSYM_CAPS  /* The shift keys and the capslock
                   key qualifers are all equivalent */
};

The CxFilter() macro only accepts a description string to describe an
input event.  A commodity can change this filter, however.

    void SetFilter( CxObj *filter, char *descrstring );
    void SetFilterIX( CxObj *filter, IX *ix );

SetFilter() and SetFilterIX() change which input events a filter
CxObject diverts.  SetFilter() accepts a pointer to an input
description string.  SetFilterIX() accepts a pointer to an IX input
expression.  A commodity that uses either of these functions should
check the filter's error code with CxObjError() to make sure the
change worked.

    errorcode = LONG ParseIX( char *descrstring, IX *ix );

The function ParseIX() parses an input description string and
translates it into an IX input expression.  Commodities Exchange uses
ParseIX() to convert the description string in CxFilter() to an IX
input expression.  As was mentioned previously, as of co
mmodities.library version 37.3, ParseIX() does not work with certain
kinds of input strings.

This article is by no means an exhaustive description of Commodities
Exchange.  For more information, see the Commodities Exchange Autodocs
(commodities.doc for commodities.library and cx.doc for the macros and
linker library functions) and the sample commodities from the 1990
Atlanta DevCon disks.


XI-21/Loading Keymaps

Loading Keymaps

by Martin Taillefer

The Amiga uses a keymap to translate a raw key code from the keyboard into an
escape sequence, a string, or an ANSI character value. The keymap helps make
it possible to easily configure a single Amiga for use in different locales
that use different keyboard layouts.

The Amiga system generally has a single global keymap used by the system
software and by all applications. It is sometimes desirable to use keymaps in
application software which differ from the current system keymap. This can be
done by building a keymap into the application's code, or by loading alternate
keymaps from disk.

On page 813 of the Amiga ROM Kernel Reference Manual: Libraries, 3rd Edition,
the ``Setting the Default Keymap'' section states:

``When making a keymap the system default, first check whether the keymap has
been loaded previously by checking the keymap list of the keymap.resource. If
it has not been loaded already, it can be loaded from DEVS:Keymaps and added
to the keymap list of the keymap.resource.''

Unfortunately, the manual doesn't mention how to perform either of these
tasks. If you look through the existing Amiga documentation, you will have a
very hard time finding any information at all on the keymap.resource (even
though it was introduced to the OS in Release 1.2). Since the keymap.resource
doesn't do very much and since it was not intended to be accessible to
application programmers, no significant documentation was ever written. The
keymap.resource only serves as an anchor for the system's list of keymaps. The
keymap.resource has no mechanisms to manipulate its list if keymaps, so the
application must perform this task.

The source code included with this article provides an easy to use function
that loads a keymap from disk into memory and returns a pointer to it. The
function adds the loaded keymap to the system's keymap list.

Note that applications rarely need to load an entire keymap from disk. In many
cases, an application is better off duplicating the system's default keymap
and making some minor modifications to it. The application can use this keymap
privately via the console device, so the application doesn't have to interfere
with the user's global keymap settings. See the article, ``Customizing the
Keypad Keymap'' in the May/June 1993 issue of Amiga Mail.

Prior to V38 (2.04 and earlier), keymaps were kept in the DEVS:Keymaps
directory. Starting with V38 (2.1), keymaps are kept in the KEYMAPS:
multi-assign directory. This newer approach allows keymap files to reside in
multiple independent directories all referenced via the multi-assign. This is
similar to the way LIBS: and DEVS: are set up.

Another change that occurred in V38 was that the Input preferences editor now
lets the user pick the keymap to use for the system. This is a very simple and
natural choice for the user. In prior releases, the user was expected to
fiddle with the SetMap program, which was not very intuitive. Starting with
V38, the SetMap program is no longer a part of the Amiga system software
distribution.

The LoadKeyMap() function listed below takes a single parameter which is the
name of the keymap to load. This should include the full path to the keymap
you wish to load. The function then checks to see if the keymap is already on
the keymap.resource's keymap list. If this is the case, the function returns a
pointer to the keymap that is already loaded. If the keymap is not in memory,
then the function attempts to load the keymap from disk and install it in the
system. The function returns NULL in case of any failure.

Unlike most other Amiga system resources, keymaps cannot be removed from
memory once loaded. There is no open count maintained for keymaps. Keymaps are
so small however, such a limitation is not a problem. This is why the sample
code has no need for an UnloadKeyMap() function.

 LoadKeyMap.c
 LoadKeyMap.h


XI-25: Customizing the Keypad Keymap

Customizing the
Keypad Keymap

by John Orr and Carolyn Scheppner

The article ``Loading Keymaps'' in this issue of Amiga Mail discusses how to
load a keymap file from disk and add it to the system's list of keymaps. The
article also mentions that, although it does have some legitimate uses, a
console-based application rarely needs to concern itself with system-global
keymaps. In most cases, it is both easier and more system friendly for the
application to duplicate its console's keymap and make some modifications to
the copy of the keymap. Since such an application has a private copy of the
keymap, the application does not have to interfere with the user's global
keymap settings. Since this application is using a copy of the user's default
keymap, the technique works with many different national keyboards.

The KeyMap

To understand how to alter a KeyMap, you have to understand the layout of a
KeyMap. This is covered in the ``Keymap Library'' chapter of the Amiga ROM
Kernel Reference Manual: Libraries, although it is a bit hard to follow.
Hopefully, this section describes the layout of an Amiga Keymap a little
better.

Each key on the Amiga keyboard has its own 7-bit raw key code. It is a raw key
because there is no character value assigned to it yet, so it isn't ``cooked''
yet. The Amiga doesn't bother assigning a character value to a specific key on
a keyboard because the letter printed on a key can vary greatly between
keyboards intended for use with different languages. The Amiga uses a KeyMap
to map raw key codes from the keyboard to an ANSI character.

The Amiga's input.device handles generating raw key input events. The
input.device reads the state of the keyboard using the keyboard.device. There
are two ways to use the keyboard to trigger the input.device into generating a
raw key input event. When the user presses a key, the input.device creates an
IECLASS_RAWKEY InputEvent structure (see <devices/inputevent.h>) and stores
the raw key code as a byte in the ie_Code field. This is known as a ``key
down'' event. The input.device also creates a similar input event when the
user releases a key, but it sets the high bit of the raw code byte to indicate
the user let go of the key (sometimes called a ``key up'' event). If any
qualifier keys (Control, Shift, or Alt) were pressed when the raw key was
pressed (or released), the input.device sets some qualifier bits in the
InputEvent's ie_Qualifier field. The input.device then adds the InputEvent to
the input stream.

As the input events travel down the input stream, a variety of input handlers
(like Intuition's input handler) have the opportunity to examine the input
events, possibly adding and removing input events. If the IECLASS_RAWKEY
InputEvent eventually arrives at the console.device's input handler, the
console.device can use a KeyMap to convert (or ``cook'') the raw key event
into one of several things:

An ANSI character
A String (32 characters or less)
A Dead Key (or Double Dead Key)

The following is the KeyMap structure (from <devices/keymap.h>):

struct   KeyMap
{
    UBYTE   *km_LoKeyMapTypes;
    ULONG   *km_LoKeyMap;
    UBYTE   *km_LoCapsable;
    UBYTE   *km_LoRepeatable;
    UBYTE   *km_HiKeyMapTypes;
    ULONG   *km_HiKeyMap;
    UBYTE   *km_HiCapsable;
    UBYTE   *km_HiRepeatable;
};

The KeyMap maps the range from raw key 0x00 through 0x7F. As mentioned
earlier, the high bit of the raw code is reserved for the up/down state of the
key. Each field in the KeyMap structure is a vector that points to a table.
The KeyMap splits the range of raw keys into a low set, 0x00 through 0x39, and
a high set, 0x40 though 0x7F. The vectors with names that start with ``km_Lo''
refer to the lower range (0x00 through 0x39). Likewise, the vectors with names
that start with ``km_Hi'' refer to the higher range (0x40 through 0x7F). Each
table has an entry for each raw key in its range.

The km_LoKeyMapTypes and km_HiKeyMapTypes fields each point to an array of
bytes. Each array has an entry for each raw key in its range (0x00-0x39 for
LoKeyMapTypes and 0x40-0x7F for HiKeyMaps). These arrays, known as the Key
Type tables, describe a key's type and its relevant qualifiers. Each entry is
a bitfield composed of the following flags (from <devices/keymap.h>):

KCF_SHIFT    /* The mapping is different for shifted mapping vs. non-shifted */
KCF_ALT      /* The mapping is different for ALTed keys vs. non-ALTed */
KCF_CONTROL  /* The mapping is different for CTRLed keys vs. non-CTRLed */

KCF_DEAD    /* This key is a ``deadable'' key */
KCF_STRING  /* This key maps to a string */
KCF_NOP     /* This key maps to nothing */

The km_LoKeyMap and km_HiKeyMap fields each point to an array containing a
long word entry for each raw key in its range. These arrays are known as the
Key Map tables. The purpose of the long word depends on the corresponding
entry from the key type tables:

For string keys (the KCF_STRING bit from the key type table is set), the entry
is a 32-bit pointer to string data (more on this later).

For deadable keys (the KCF_DEAD bit from the key type table is set), the entry
is a 32-bit pointer to dead key data.

For KCF_NOP keys, the entry is undefined.

For all other keys (for lack of a better term, we'll call them ``normal''
keys), the entry consists of four bytes. Each of these bytes is an eight bit
ANSI code. The raw key ``maps'' to one of these four bytes. The qualifier keys
that were pressed when the user hit the raw key determine which of the four
ANSI codes to use.

Unfortunately, since each normal raw key can only map to one of four bytes,
there is not enough space to handle all possible qualifier combinations. Since
there are three qualifier keys (Shift, Alt, and Control), each raw key would
require eight bytes to have an entry for all possible qualifier key
combinations.

As this scheme can't support all possible qualifier combinations, it only
supports some combinations. The easiest case to handle is where the user hits
the raw key without any qualifiers. The raw key without qualifiers always maps
to the ANSI value in the low order byte of its entry in the Key Map table.

The meaning of the upper three bytes of the key map table entry changes
according to the raw key's key type value (from the key type table). The
following chart shows how the key type value changes the meaning of all four
bytes. If a qualifier does not appear in the ``Key Type'' column, the
keymapping software ignores that qualfier for the key. For example, if the key
type is KCF_SHIFT|KCF_ALT and the user is holding the shift and alt keys while
pressing a normal raw key, the raw key maps to the ANSI code in the high order
byte (bits 31-24). If the key map entry is the long word 0xD0F04464, the raw
key maps to the ANSI value 0xD0.

Another good example to consider is where the key type is KC_VANILLA. The
vanilla qualifier does not mean plain! KC_VANILLA is a combination (a logical
OR) of the three qualifier key types. When the key type is KC_VANILLA and the
user is holding the Control key, the keymapping software maps the the raw key
to the low order byte, but it clears bits five and six of the value it ouputs.
The keymapping software ignores the state of the shift and Alt keys. Using the
key map entry 0xD0F04464, the raw key maps to the low byte (0x64) but with its
fifth and sixth bit cleared:

%0110 0100    This is 0x64 in binary
%1001 1111    bitwise AND to clear bits 5 and 6
-----------
%0000 0100    = 0x04

The next fields from the KeyMap structure are km_LoCapsable and km_HiCapsable,
which point to the Capsable tables. These tables contain a single bit for each
raw key in their range. Their purpose is to tell the keymapping software what
to do when the Caps Lock button is on (the LED in the Caps Lock button is
lit). If a raw key's Capsable bit is set, the keymapping software treats the
raw key as a shifted raw key while the Caps Lock LED is on.

Like the Capsable tables, the Repeatable tables (km_LoRepeatable and
km_HiRepeatable) contain a single bit for each raw key in their range. If a
raw key's Capsable bit is set, the keymapping software should allow the key to
repeat if the user holds it down long enough. The Input Preferences editor
sets the time intervals that the input.device waits before repeating the key
and between key repeats. The input.device takes care of adding these events to
the input stream. When the keymapping software sees the series of repeated
keys, it may elect to throw away almost all of them if the key is not marked
as repeatable in the keymap.

String Output Keys

A keymap can also map a raw key to a string. A raw key maps to a string if the
key's entry in the key type table has the KCF_STRING bit set. For string keys,
the corresponding long word entry in the Lo/HiKeyMap is a 32-bit pointer to
the string data.

The string data consists of a table of 16-bit entries. Unlike the ``normal''
keys, string keys can account for every possible qualifier key combination.
Since there must be an entry in the string key's table for each qualfier
combination, the number of table entries depends on how many qualifier bits
are set in the key's key type table entry. If x is the number of qualifier
bits set in the key type table then the number of table entries is 2x.

If all three qualifier bits are set, there are eight entries. They appear in
the table in the following order:

Table 2 - String Key Data Table

   000  No Qualifiers
   001  Shift
   010  Alt
   011  Alt+Shift
   100  Control
   101  Control+Shift
   110	Control+Alt
   111  Control+Alt+Shift

To adjust the table above for fewer qualifiers, remove the rows that contain
the missing qualifier. For example, if the KCF_SHIFT and KCF_CONTROL bits are
set, the KCF_ALT qualifier is missing, so remove all the lines with an ``Alt''
in them:

Table 3 - A Shiftable Control Key

   00  No Qualifiers
   01  Shift
   10  Control
   11  Control+Shift

Each entry in the string data table is organized into two bytes, the first
byte tells the keymapping software the length of the string that the raw key
maps to. The second byte is a positive offset from the beginning of the table
to the string itself. Since this offset is only eight bits wide, every string
must start within the 255 bytes after the beginning of the table. For a raw
key that uses a full string data table, the keymap needs the first 16 bytes,
leaving enough room for about 34 bytes per string. Normally, the key's strings
should not exceed 32 bytes as larger strings can overflow the console.device's
input buffer, so 32 bytes is a good upper limit.

Unlike a C-style string, the raw key's string does not need a zero terminator
at the end (although it's not a bad idea to have a zero there if there is
enough space).

Simple KeyMap Example

The following is a pseudo-assembler fragment that shows the key type and the
map table entries for the first three keys of the high keymap (raw keys 0x40,
0x41, and 0x42):

newHiKeyTypes:
    DC.B        KCF_ALT,KC_NOQUAL,      ;key 0x40 (spacebar), key 0x41 (backspace)
    DC.B        KCF_STRING+KCF_SHIFT,   ;key 0x42 is the tab key on the US keyboard
        ...     ;(other keys)
newHiKeyMap:
    DC.B        0,0,$A0,$20     ;key 0x40: nil, nil, the Alted-space key maps to $A0 which
                                ;  is the ANSI Non-Breakable Space (NBSP), the plain space
                                ;  key maps to $20 which is the space character.
    DC.B        0,0,0,$08       ;key 0x41: Back Space key only
    DC.L        newkey42        ;key 0x42: definition for string to output for Tab key
        ...                     ;(other keys)
newkey42:
    DC.B        new42ue - new42us       ;length of the unshifted string (new42us)
    DC.B        new42us - newkey42      ;number of bytes from start of
                                        ;  string descriptor to start of this string
    DC.B        new42se - new42ss       ;length of the shifted string (new42ss)
    DC.B        new42ss - newkey42      ;number of bytes from start of
                                        ;  string descriptor to start of this string
new42us:  DC.B        '[TAB]'
new42ue:
new42ss:  DC.B        '[SHIFTED-TAB]'
new42se:

The keymap fragment above shows two kinds of keys, a ``normal'' key and a
string key. Looking at the key types table which starts at the newHiKeyTypes
label, key 0x40 is neither a dead key, a No Op key, or a string key, so key
0x40 is a ``normal'' key. It has one modifier, KCF_ALT. Looking at Table 1,
the Key Map table entry for key 0x40 should only have two defined bytes. The
third byte is the raw key with the Alt modifier and the fourth byte is the raw
key without modifiers. Looking at key 0x40's entry in the key map table (the
first four bytes of newHiKeyMap), if the user hits raw key 0x40 with the Alt
key down, this keymap maps the key to ANSI character 0xA0, which is the ANSI
Non-Breakable Space character (NBSP). Since only the KCF_ALT qualifier bit is
set, this keymap ignores the other qualifier keys.

Key 0x41 is similar to key 0x40 as it is a ``normal'' key as well. One way in
which key 0x41 differs from key 0x40 is that it has no qualifiers. According
to Table 1, if the user presses raw key 0x41 with or without qualifiers, this
keymap maps to the fourth byte in key 0x41's entry in the key map table, so
raw key 0x41 maps to the ANSI character 0x08, which is the backspace
character.

The last key, 0x42, has two bits set in its entry from the key types table,
KCF_STRING and KCF_SHIFT, so it is a shiftable string key. For a string key,
the entry from the key map table is a 32-bit pointer to string key data
instead of the four ANSI codes a ``normal' key uses. Key 0x42's key map entry
points to newkey42. As key 0x42 is shiftable, the string data should only have
two entries in it. To adjust Table 2 for the shift qualifier, remove the rows
that contain Alt and Control. The table that starts at newkey42 should look
like this:

00	No Qualifiers
01	Shift

Looking at the keymap example, the ``No Qualifiers'' entry in the string table
shows that the length of the ``No Qualifiers'' string is new42ue-new42us. The
second byte in the string table entry is the offset from newkey42 to the ``No
Qualifiers'' string, which points to the string ``[TAB]''.

A Word About Dead-Class Keys

The Amiga keymap scheme also supports dead-class keys, which allow one key
press to modify the next key press. However, robustly altering a keymap by
adding dead-class keys requires an impractical amount of overhead and is not
particularly useful for the purposes described here. Dead-class keys are not
covered in this article. For more information, see the ``Keymap Library''
chapter of the Amiga ROM Kernel Reference Manual: Libraries.

Cloning and Altering the KeyMap

The AppKeyMap code at the end of this article contains a function which
duplicates a KeyMap structure plus all the KeyMap's associated tables. Cloning
a keymap is a fairly straightforward memory copy, although the AppKeyMap code
adds a little twist to make it easier for other functions to reference the
entries in the table. The way <devices/keymap.h> defines the KeyMap structure,
the keymap tables are split into a low set (``km_Lo...'') and a high set
(``km_Hi...''). This makes looking up entries in the tables a nuisance because
you have to treat ``Lo'' raw key and ``Hi'' raw keys separately. When the
CreateAppKeyMap() function creates the tables, it organizes the tables so the
``Hi'' table directly follows the ``Lo'', joining the two tables into one.
This allows other functions in the AppKeyMap code to use a raw key value as an
index into the table.

Altering the keymap is also rather straightforward, particularly because the
CreateAppKeyMap() function made the table entries much easier to reference.
The only remotely complicated part is handling the Capsable and Repeatable
tables. These are both bit tables (there a single bit entry for each raw key),
so handling them in C is a little cumbersome.

About the Code Example

The appmap_demo.c example is a shell-only program. It opens the console.device
and uses its CD_ASKKEYMAP command to obtain a copy of the shell's current
keymap. Using the AppKeyMap functions, the example duplicates and alters the
keymap copy. Appmap_demo.c then uses the console's CD_SETKEYMAP command to
install the keymap copy as the shell's current keymap. The user can type at
the shell's window trying out the altered keymap. When finished, the example
restores the shell's original keymap using the console's CD_SETKEYMAP command
and exits.

An application can also use this technique when attaching a console.device to
an Intuition window.

 AppKeyMap.doc
 AppKeyMap.c
 AppKeyMap.h
 AppMap_demo.c


XII-1: CDTV Application Guidelines

Staff

A CDTV application is not simply an Amiga application running in a
different box.  The CDTV player imposes certain restrictions on an
application--no menus and large icons, for example, and provides
certain benefits--large storage capacity and digital audio.  The wise
CDTV developer respects the former and takes advantage of the latter.

The list below gives you, the developer, a quick reference to the do's
and don'ts of CDTV applications. It contains rules and common sense
advice. They are broken into two groups, minimum requirements and
quality standards.

Minimum Requirements - The minimum necessary to be an acceptable CDTV
application.

Quality Standards - To get into people's homes, you need to do more
than the minimum.  These will help you make the trip.

 Level 1 Minimum Requirements
 Reference Titles
 Recreation Titles
 Level 2 Quality: The Next Standard


Level 1 Minimum Requirements

1. No program crashes.  The application should not crash, guru or
  otherwise cease to be functional.  Test, retest and test again till you
  are sure your application is robust.

2. No logic or flow errors.  The application cannot take a path other
  than the one requested or expected by the user.  For example, if the
  user asks for a map, but instead gets a picture of a tree, a logic or
  flow error has occurred.

3. All images presented should be free of error and look clean.  For
  example, a title should not have a garbled picture or a video sequence
  that exhibits solarization, i.e., a color picture that looks like a
  negative.

4. No low quality images.  All still images should be high quality,
  preferably digitized interlaced HAM images.  Drawings or animations
  should be detailed and free of major color banding.  All still images
  should be overscanned unless a conscious effort is made to provide a
  colored border.

5. User interface.  The program should follow generally accepted CDTV
  interface rules including:

      A button for action, B button for backup, arrow keys move in
      direction of arrow.

      Single click to select an object.

      Use highlighted hitboxes rather than a pointer where possible.

      Highlighted hitboxes should be accessible by cursor keys in any
      direction.

      If a pointer is used for products with invisible hot boxes or for
      special purposes such as coloring, the pointer should change when
      it is over an invisible hot box and be in a form relevant to the
      application (paint brush, wand, etc.).

      Numbered items should allow use of the numeric keypad on the
      controller.

      Selectable items should stand out (e.g., 3D buttons) from
      non-selectable items, and they should give audio/visual feedback
      when selected.

      Selectable items should give appropriate, consistent, and
      predictable results.

      There should be no references to a computer keyboard (e.g., F1 key).

6. The application should look good on any television.  This means you
  should buy a cheap television for testing.

7. There should be no signs of AmigaDOS.  Examples include the AmigaDOS
  cursor, Workbench screen, system requesters, sleep icon, pull down
  menus, flashing title bar, front/back gadgets, or jargon (x memory
  free, loading next module, etc.).

8. Efforts must be made to reduce perceived boot-up time.  The
  titlescreen should appear within five seconds of the appearance of the
  CDTV Interactive Multimedia logo.  (See Discis' products) The program
  should show a title screen before doing anything else.  It should not
  show CLI, Workbench, or any pointer.

9. It must have a screen blanker tied to preferences.  We recommend the
  screen blanker supplied as part of the OS.

10. Applications must work under AmigaDOS 1.3 and 2.0 in both NTSC and
  PAL. Programs should be able to successfully pass enforcer and mungwall
  testing.

11. The program must be designed for use on a PAL or NTSC TV, which
  means care must be taken in regard to all graphic elements (fonts,
  symbols, pictures, animations, video) with respect to size, style,
  color combinations, and contrast.  Test your applications on those two
  environments, not just with a monitor and one of the two standards.
  Specific suggestions include:

      Fonts should be simple with no thin lines, anti-aliased, easy to
      read on a television and at least 20 point size.

      Text should generally be highly contrasted to its background.

      Text should have borders or drop shadows to make it more readable.

      Don't use pure colors (R, G, B values should be less than or equal
      to 13 out of a range of 0--15) because they bleed on television
      sets.

      Be careful of the colors used as some colors show up very
      differently on NTSC versus PAL.  For example, deep red in NTSC
      comes out pale pink in PAL.  The only way to find this out is to
      test on both systems.

      Avoid stark contrasts when using thin horizontal lines since this
      will not look good in an interlaced medium (TV), and avoid single
      pixel horizontal lines entirely.

      Do not base instructions solely on color, i.e., don't state ``Pick
      the orange button'' since TV sets will be adjusted differently.
      This could also be a problem for colorblind users.

      There should be no more than nine selectable (by cursor or by
      pointer) items on a screen unless the individual items are
      recognizable because they are part of a set (i.e., alphabet,
      numbers, states). Nine items fit well with the font size required
      for television.

12. Products must not substitute repetitiveness for depth by reusing
  the same elements in different places.  If a product is perceptually
  redundant, it is boring.  For example, using a passage from Beethoven's
  Piano Concerto No. 5 as an example of his music, and as an example of
  how a piano sounds, and as an example of a piano concerto is a lack of
  depth.

13. Eliminate all spelling and grammatical errors; people will not want
  to use a product, especially an education product, if they cannot trust
  something elementary like its spelling. Run your text through a spell
  checker and a grammar checker. Some of these titles are available in UK
  English or American English only, and these are acceptable, at least
  for the initial shipment.

14. Programs should reboot when the disc is removed unless the program
  disc needs to be removed for the product to be usable (CD-Remix).  The
  program should reboot when the eject button is pushed, and the reboot
  should occur even if the disk is being accessed or Amiga audio is
  playing.

15. Sound quality should match the application requirement. Use Amiga
  sounds for audio feedback; CD-DA for game background, dramatic intro
  music and other sections designed to evoke an emotional response. All
  sounds should be clear and free from hiss or other extraneous problems.
  Speech must be ungarbled and unclipped and digitized at a reasonable
  level or be CD-DA.

16. Volume levels of speech, music, and sound effects should be uniform
  throughout the product.  All audio must come through both channels
  unless there is a compelling reason to do otherwise.  Note that
  compelling does not mean being unwilling to take the time to code so
  that the sound comes through both channels nor does it mean that your
  authoring system only works with one channel.  Compelling does mean
  trying to add depth to the sound by having one person come through the
  right channel and another through the left channel.

17. Interruptability.  All titles need to be interruptable at any time,
  including title and credit screens, introduction, during accesses, or
  animations.

18. Products must use preferences for language selections.  Unless the
  language chosen in preferences is unavailable, the user should not
  normally see language selection screens.

19. All programs that can save to a floppy must be able to format a
  disk.

20. All programs should test for joystick/mouse mode.  If the
  controller is not in the proper mode, it should ask the user to change
  modes.

21. Programs should disable keys that are not functional in the
  product. Typically this means disabling the audio keys for CD control.

22. Controller responsiveness.  The product should not queue up button
  presses, it should react and give feedback immediately, and any cursor
  or highlight should move quickly enough for that specific application.
  In many cases, if a pointer is used it should include an accelerator
  feature.  If a user feels compelled to repeat an operation because
  there is no response, the application is at fault.

23. The products should not have any dead time, i.e., time when nothing
  is occurring.  Accesses should first give audio and visual feedback
  that a selection has been made, then have a transition of some sort,
  then begin the load during the transition. The transition interlude can
  consist of music, color cycling, a voice over, a fade to a colored
  screen, or in some way distract the user.  A sleep or load symbol is
  generally insufficient to improve the perception.

24. Test that your product works properly with a trackball and a mouse.

25. They should also not be adversely affected by the presence of video
  peripherals such as genlocks.


Reference Titles

The reason someone purchases or uses a reference title is for the
information contained within.  A reference application should not have
any of the following:

26. Inaccurate reference data.  Imagine you're a student doing a
  homework assignment, using the CDTV title as a reference work. Your
  teacher gives you an ``F'' because your facts are wrong.

27. Missing information.  If a menu, icon or other reference indicates
  that information relating to the subject matter is available, the
  information should be accessible from that point.  In other words, if
  something is selectable, it must present the data associated with it.

28. An inability to accept keyboard input, print, or save to disk even
  though most people will not be able to take advantage of these features
  at the moment.


Recreation Titles

29. A title must be playable to completion.  No user or program error
  should prohibit the game from continuing. If you make a stupid move and
  get eaten by a dragon and the game ends, you have played to completion.
  If you make an incorrect move and the game freezes up or prohibits the
  continuation of play, it is a not move that shouldn't have been made,
  it is a bug.

30. A multiple player option should be in every recreational product.
  Where it makes sense (certain sports and arcade games), two-player
  simultaneous play is a requirement (e.g., hockey and football).

31. Simulations must attempt to match the real world in as much detail
  as possible, including the standard rules of play in sports games.


Level 2 Quality: The Next Standard

In addition to the requirements of the Level One, products need to be
compelling enough to compete successfully in the marketplace.

32. All titles must have an important and distinguishing value over
  doing the product on magnetic media, or by book, or by cassette.
  Products should have greater detail, more choices, more ``sizzle'', be
  easier to use, or be faster to perform a function.  Ports from another
  platform--including the Amiga--must be enhanced (music, speech,
  additional video, more choices, etc.).  An example of an excellent port
  is SimCity which added digital audio and rewrote the user interface to
  take advantage of the numeric keypad on the IR controller.

33. Timely response is important.

    On a multitasking operating system, the time that elapses from when
    a selection is made till the activity begins  should be no more
    than three seconds.  This is part perception (i.e., start showing a
    graphic change while still loading), part disk organization (to
    speed access times), and part programming (sometimes things can be
    cached or optimized).  (Asterix appears to have achieved this goal,
    so it is therefore possible.)  To reiterate, first audio/visual
    feedback, then some type of transition interlude which lasts no
    longer than three seconds, then the desired result.

    For very long searches that cannot be done in a short period of
    time, inform the user of the progress of the search.  Options
    include putting up a screen and start listing ``hits'' or showing a
    ``gas gauge'' depicting the progress of a search.

34. Multimedia elements should be comparable to video or cartoons
  viewed on TV.  These elements (animations, speech, music, sounds,
  video) should be streamed from disk so that they can be more in-depth
  and longer in duration.  The animations should normally be 3
  dimensional and change focus (i.e., background, perspective), not
  limited to a static background screen.

35. Educational titles and adventure type recreational products need to
  have a depth of interactivity options.  For instance, if a character is
  walking down a street, the user should be able to go down alleyways,
  into buildings, etc. Each screen or in each section should have
  more than one (and more than two!) things that can be done. These
  options should include non-linear choices, i.e., being able to jump
  around. Linear choices are really no choices at all because you must
  follow a prescribed path.

36. Educational titles should have some type of testing function to
  allow you to examine your progress in a section.  The Bookmark feature
  should be used if appropriate (e.g., game scores, place in a book,
  tests, etc.).

37. Reference titles should allow numbers and spaces to be input for
  searches. All reference titles should support searches on keywords in
  body or title, and not be just an alphabetized index of options
  (similar to the index of a book). They should also have the Bookmark
  feature using Non-Volatile RAM (NVR) to save search criteria and
  possibly the resultant elements.

38. Recreational titles should use continuous streamed animations and
  CD audio for background.  They should be able to save game states and
  high scores using NVR.

39. Possible suggestions:

Online help

    Templates to fit on top of the IR controller to simplify the
    buttons for complex products (i.e., flight simulator).

    Optionally viewable demo commercials of other products.

    Hardware add-ons (a la Nintendo).

    Supply a formatted disk (or at least a disk label) if the product
    can use a floppy.


XII-9: Making CDTV Titles That Work on Amigas

by Ben Phister, CATS

In the coming months Commodore plans to begin delivery of the A570
drive.  This CD-ROM peripheral for the Amiga 500 and Amiga 500 Plus
should rapidly expand the installed base of CDTV-compatible players.
With over 3 million Amigas sold worldwide, the potential for the A570
is enormous.

The A570 presents exciting opportunities for CDTV developers.  It also
presents a certain number of challenges.  Great efforts have been made
to ensure compatibility of titles for both platforms.  However, there
are numerous differences between the CDTV and the A570: keyboard plus
mouse vs. remote control, TV sets in a living room vs. RGB monitors on
a desktop, Kickstart 2.04 vs. Kickstart 1.3, etc.

With the availability of the optional keyboard for CDTV players, many
users now attach a keyboard to their CDTV.  Other users have attached
CD-ROM peripherals to their Amiga 2000 or A3000 computers, and need
keyboard support from titles.

To ensure strong sales of your title on all the systems capable of
playing CDTV discs, your title should take advantage of the new
features of the A570, yet remain easy-to-use on the CDTV player.  This
article discusses the differences between the two systems, and presents
extensions to the CDTV User Interface Guidelines to allow titles to run
on both platforms.

 Physical Differences
 Operating System Issues
 Emulating the Remote Controller
 Screen Design Issues
 Three Levels of Support for the A570
 Conclusion


Physical Differences

The A570 does not include the following items found on the CDTV player:

    * Infrared remote control.
    * Audio CD control buttons (Play, FF, etc.).
    * Fluorescent display.
    * Personal RAM Card slot.
    * RF or composite video output to TV or VCR.
    * MIDI ports.

Of course, functional equivalents of most of these items are already a
part of the Amiga 500; many others are available as options. Although
the Amiga lacks the standard CDTV resources above, the Amiga connected
to the A570 provides resources not available on all CDTVs.  Every title
running on an A570 will have access to a floppy disk drive and a
keyboard.  CDTV titles should support saving to a floppy, along with
saving to a personal RAM card.


Operating System Issues

 Kickstart 1.3 vs. 2.04
 What Am I Running On?
 Memory


Kickstart 1.3 vs. 2.04

The A570 connects to either an A500 running Kickstart 1.3 or 2.04, or
an A500 Plus running Kickstart 2.04.  It is imperative that your
application work in both these environments.  The A570 uses the
Kickstart ROM routines found in the host computer.  It contains its own
ROMs which provide the CDTV-specific functions (cdtv.device,
playerprefs.library, Audio control panel, CDTV Preferences, etc.)


What Am I Running On?

It is possible for applications to detect if they are running on an
A570 or on a CDTV player.  There is an A570-specific module called
"A690ID".  A title can test to see if this module is present using the
exec.library function FindResident().  If the "A690ID" module is
present, the title is running on an A570-equipped A500.


Memory

An Amiga with an A570 may have various amounts of RAM.  In a CDTV the
minimum memory configuration is 1 Mbyte of Chip RAM.  Do not assume
that all systems have the same memory configuration.  Some users might
try to run your application on an Amiga + A570 with only 512K of Chip
RAM and no Fast RAM.  Others may have a 512K Chip/512K Fast RAM system.
To avoid crashing due to memory shortages, check the amount of memory
available when your application begins execution.  If not enough memory
is available, you should display a message to that effect and stop
operating rather than crashing the machine.

Others may have more than 1 Mbyte of RAM: either Fast or Chip memory.
Your title should also work properly under these conditions.


Emulating the Remote Controller

One of the major differences between the A570 and the CDTV is the
remote controller.  The Amiga's keyboard, the mouse, and, optionally,
the joystick replace the remote controller.  Your title must take these
differences into account, and your input handling routines may require
modification.  The following section will discuss these differences,
and make additions to the CDTV User Interface Guidelines.

Here is a chart describing how Amiga keyboard and mouse actions should
correspond to the CDTV player's remote controller buttons.

    Remote Controller   Amiga Keyboard         Amiga Mouse/Joystick
    -----------------   --------------         --------------------
     cursor buttons      Cursor keys              Mouse movement
  (directional arrows)

       'A' button       Left Alt + Left Amiga,     Left button
                        Left Amiga key alone,
                        F9 function key,
                        'A' key on keyboard

       'B' button       Right Alt + Right Amiga    Right button
                        Right Amiga key alone,
                        F10 function key
                        'B' key on keyboard

       0-9 buttons      Keyboard 0-9
                        Keypad number keys

         ESCAPE         Esc and Help
         ENTER          Return or keypad Enter
         REW            F1
         PLAY           F2
         PAUSE          F3
         FF             F4
         STOP           F5

 Cursor Buttons               Escape Key                      Genlock
 The 'A' and 'B' Buttons      Help Key                        CD/TV
 0-9 Buttons                  REW, PLAY, PAUSE, FF, STOP      JOY/MOUSE


Cursor Buttons

An application that runs on an A570 can emulate the four directional
arrow buttons on the CDTV remote control using two methods: via mouse
movements and via the four directional arrows next to the numeric
keypad.  Titles should support both methods of cursor control.  Jumping
highlights are easy to control using the arrow keys.  If the title has
a pointer, the user should be able to move it using the mouse, but, in
case the user doesn't have a mouse, titles should also allow the user
to move the pointer with the arrow keys.


The 'A' and 'B' Buttons

The A and B buttons on the remote correspond to the left and right
buttons on the mouse.  If the user prefers to use a keyboard for input,
he can use any of the following:

    The left Alt/left Amiga combination for the 'A' button and right
    Alt/right Amiga for the 'B' button.

    The left Amiga key (raw keycode 66 hex) alone for 'A', and right Amiga
    key (raw keycode 67 hex) alone for 'B'.

    The F9 function key (rawkey code 58 hex) for 'A' and F10 function key
    (rawkey code 59 hex) for 'B'.

    the A (for left) and B (for right) keys on the keyboard.

By offering a keyboard equivalent to the 'A' and 'B' button, users with
keyboards will not have to move their hands from the keyboard to the
mouse in order to confirm a selection.  It also avoids accidental
movements of the mouse when pressing the rodent's left or right button.

The F9 and F10 function keys were selected because of their convenient
location near the directional arrow keys on the keyboard.

Supporting the 'A' and 'B' keys on the keyboard is more complicated.
The 'A' or 'B' key on the keyboard cannot be equivalents for the
remote's A and B buttons during the input of a text string.  In other
situations, however, this mapping can be helpful to the neophyte user.

If a title uses the console device, it should support both uppercase
and lowercase ('A' and 'a').  Furthermore, the raw keycodes for the 'A'
and 'B' keys must always be translated via the active keymap to
determine the actual ASCII value.  The rawkeyconvert.c routines in the
ROM Kernel manual give an example of this translation process.

If your title reads raw keycodes directly, beware of using raw keycodes
for the 'A' and 'B' keys on the keyboard, as the raw keycodes may
change if the user has a French keyboard.  The French keyboard has
reversed the position of the 'A' and the 'Q' keys.  If you choose to
have raw keycode support, you should accept both the 'A' (raw keycode
20 hex) and 'Q' (raw keycode 10 hex) for the 'A' button, and 'B' (raw
keycode 35 hex) for the 'B' button.


0-9 Buttons

The 0-9 and ENTER buttons located in the center of the remote are
replaced by the Amiga keyboard's numeric keypad.  The keycodes of the
remote represent those found on the keypad, the only difference being
the reversed physical layout of the keys:

                Remote              Numeric keypad

                1 2 3                   7 8 9
                4 5 6 0                 4 5 6
                7 8 9                   1 2 3
                                          0

Your code will probably not have to be modified to take this into
account, unless it displays 9 icons in a grid pattern, and wants the
user to type in a number corresponding to a certain position.  If you
support a jumping highlight (as suggested in the CDTV User Interface
Guidelines), this should not be a problem.

Your code should also support the 10 numeric keys on top of the
alphanumeric keyboard (just below the function keys) for input of
numbers.


Escape Key

The ESCAPE key requires special attention with a keyboard.  On the CDTV
remote control, the ESCAPE key generates the ESCAPE rawkey code of 45
hex, the same code as on the A500's keyboard.  The CDTV User Interface
Guidelines recommend that titles use the ESCAPE button as a HELP key.


Help Key

The A500 keyboard has a Help key, rawkey code 5F.  To run effectively
on both the CDTV and A500 with an A570, applications should support
both the Escape key and the Help key to obtain Help functions.  If an
application detects that the user has pressed either the Help key or
the Escape key on the Amiga keyboard, the application should provide a
help function to the user.


REW, PLAY, PAUSE, FF, STOP

These keys are mapped by the A570 ROM to the F1 through F5 keys on the
Amiga keyboard.  The Audio Control Panel uses these equivalents to play
CD audio discs.  If a title detects a keypress on F1 through F5, it
should react as if the user had pressed the corresponding remote
control button.

Certain titles ported from the Amiga to the CDTV may have already
established alternate uses of the F1 through F5 keys on the keyboard.
Any such application that retains its mapping of the F1 through F5 keys
for its A570 version should clearly document these alternate key
mappings in its manual.


Genlock

The Genlock button on the CDTV remote is for mode selection of an
optional video genlock device that can be installed in the CDTV.  This
button has no equivalent on the A570.  If you want to support this
feature in an application running on an A570, you cannot be sure that
the genlock used with the Amiga supports software control of mode
switching.  Again, mention this fact in the user manual.


CD/TV

This button on the CDTV remote controller determines whether the
TV/monitor displays input from the CDTV or from the broadcast (or
cable) TV source.  This button has no equivalent on the A570.  If the
user has his Amiga connected to a TV set, his existing cabling handles
this switch-over.


JOY/MOUSE

This button on the remote determines whether the remote's cursor
buttons respond as a joystick or as a mouse.  This is not necessary on
the Amiga + A570: to enter joystick mode, the user simply plugs a
joystick into the Amiga.  To enter mouse mode, he uses his mouse.

Some CDTV applications only support one mode or the other.  Titles
should support both modes, if possible.  If a title only supports
joystick mode and the title cannot be reasonably controlled from the
keyboard, you should indicate this on your packaging, as an Amiga +
A570 user might not have a joystick.


Screen Design Issues

The typical CDTV user is sitting approximately 3 meters from his TV
set.  The typical A570 user will be sitting less than one meter from an
RGB monitor.  These differences require some foresight on the part of
your application.

 Fonts


Fonts

For CDTV usage, a typical font should be no less than 18 points high.
This permits the user to easily view text from a distance.  An A570
user might prefer a smaller font in order to have more text on the
screen, especially when using text-based applications.  In this case,
an application should offer a selection of at least 2 different-sized
fonts to the user.


Three Levels of Support for the A570

Full support for the A570 implies numerous constraints for the CDTV
developer.  He has to worry about supporting a keyboard, working with
different versions of the operating system, dealing with varying memory
configurations and working around differences between Amiga and CDTV
displays.  The issues of starting, exiting, and multitasking titles
remain.

There are several Amiga/CDTV configurations that may be booted into a
CLI or Workbench environment: Amiga + A570, any Amiga computer equipped
with a CD-ROM, and a CDTV player with a floppy or hard disk attached.
In these cases, the user may want to launch a CDTV title from that
environment.  If he does so, he will expect the title to exit cleanly,
release all memory, remove any special assigns that may have been
executed, etc.

Users may even want to multitask a title.  Most Amiga applications may
be multitasked, and the user may well expect the same from a CDTV
title.  Reference titles would be significantly enhanced if they
supported cutting-and-pasting directly into another application like a
word processor.  Those developing dictionary and encyclopedia titles
may want to provide access methods for users or other applications to
search on a key word.  Some may even want to add an ARexx port.

These issues, while reasonable requests from a user, add significant
new burdens to the developer.  Many CDTV titles are designed to take
over the machine.  Many of these titles require all the memory
available in the system (and even more, in some cases).  They often
make special assigns for fonts, data, etc.  Many include no clean-up
code.

Full compliance to AmigaDOS standards may be unreasonable for some
titles.  To address this problem, we have established three levels of
compatibility for CDTV titles running on Amigas: Minimal Support,
Support For Workbench Startup and Exit, and Full Multitasking Support.

 Level One-Minimal Support
 Level Two-Support For Workbench Startup and Exit
 Level Three-Full Multitasking Support


Level One-Minimal Support

An application that meets Level One support requires only a few
enhancements from a standard CDTV-only title.

  1) Supports input from the keyboard and the mouse.

  2) Runs under both Release 1.3 and Release 2 of the operating system
  (which is expected of all CDTV titles).

  3) Includes a way for the user to start the title from a CLI and the
     Workbench.  Such a title may reboot the system when it starts up.
     It may take over the entire system, refuse to multitask with other
     programs, have no cleanup code, and never exit.

Commodore has developed a standard icon and associated code, called
BootCD, which developers may include on their CDTV disc.  This icon
will appear from the Workbench.  If the user double-clicks it, a
message will appear telling the user to remove any floppy disks from
the drive, and warning that pressing the Continue gadget will reboot
the system.  If the user continues, BootCD will reset the system, and
the system will then boot directly from your title on CD-ROM.


Level Two-Support For Workbench Startup and Exit

This level provides the user with a way to run CDTV applications
without rebooting the system.  A Level Two compliant title will also
return cleanly to the Workbench or the CLI when it is finished.  This
stage requires that a title:

  1) Supports input from the keyboard and the mouse.

  2) Runs under both Release 1.3 and Release 2.0 of the operating system.

  3) Launches from either the Workbench (via an icon) or the CLI.

  4) Manages any resources it allocates.

  5) Safely and Cleanly aborts in case any resource allocation fails.

  6) Cleans up properly upon exit, closing all libraries and devices, and
     returning all memory.

  7) Remembers the environment from which the user launched the title.
     If the user started the title from a CLI or Workbench, the title must
     be able to restore that environment cleanly.  If the title was booted
     directly from the CD-ROM, before exiting, the title should take
     precautions against leaving the system in an unusable environment.
     For example, if a title makes all of the Workbench colors black using
     the devs:system-configuration file, the user should not be allowed to
     return to the CLI or Workbench, as the user will only see a black
     screen.

In level two compatible titles, temporary assigns are acceptable.  The
application may assign system directories (such as fonts:, sys:, etc.)
to the CD during startup.  If it does so the title must restore any of
the assigns it reassigned.

A simple way to launch a title from a Workbench icon is using the IconX
utility.  This allows you to create a script that the system executes
when the user clicks on the program icon.  This script may contain any
assigns that a title requires.

An easy way a title can tell if the user booted directly from the
CD-ROM is checking for special command line arguments.  Imagine your
title is called ``MyApp''.  When the user boots the system from the
CD-ROM, the startup-sequence launches the application by using a
special command line, for example: ``MyApp ss''.  The ``ss'' tells the
title that the system was booted from the CD-ROM.  If the user starts
the application from the CLI, he would simply type ``MyApp''.  A title
might even utilize another special command line option to tell if it
was launched from an IconX script (i.e. ``MyApp iconx'').  Using this
method a title can detect how the user started it and can choose an
appropriate exit plan.


Level Three-Full Multitasking Support

A title conforming to Level Three support allows users to multitask
freely (given sufficient memory).  These titles must include support
for points 1) through 7) above.  Furthermore, Level Three titles may
not re-assign any directory assigns that the system requires (i.e.
fonts:, sys:, s:, etc.).

If a title in this category needs to access a particular font on the
CD-ROM, it should not re-assign fonts: to cd0:fonts.  Instead, it
should refer to the full path name of the CD via the volume name of the
disc (for example, MyDisk:Data/MyFile).  You should not refer to the
device name (cd0:) since this may vary, either with more than one
CD-ROM peripheral attached, or a different device name for a
third-party drive.

If your title does refer to a volume name, be careful when
pre-mastering the title.  Make sure you enter the correct volume name
when running the ISO utility.  If another company does the
pre-mastering for you, make sure they use the correct volume name.


Conclusion

Full support for the A570 does require a certain amount of effort on
behalf of the CDTV developer.  Many of these points are also relevant
for those CDTV owners that expand their unit to be an Amiga.

Remember, you are not obliged to support all these features.  Many CDTV
applications take over total control of the system, and are not
designed to multitask.  There is nothing wrong with doing this, even if
you want your title to run on the A570.  If you include Level One
support, you can insist that your title be booted directly from the CD.
It is better to have a title which runs perfectly on the CDTV than one
which is awkward to use on both the CDTV and the A570.


XII-17: Memory Limits for Various CDTV Configurations

by Adam Levin-Delson

RAM space is at a premium in the CDTV, so for the developer who is
creating CDTV titles, it is important to know what the limits of
system memory are.  This is especially true for developers who want
their titles to work on a variety of CDTV/A500 configurations.  To
help assist developers in making titles work on the maximum number of
configurations, the following chart shows a variety of hardware
configurations capable of playing CDTV discs.

For comparison purposes, all machines were allowed to boot far enough
to open the Workbench screen (in the default size) and a CLI/Shell
window.  This represents a reasonable starting point for developers
to estimate if their application will fit into a CDTV's memory (To
properly ascertain the amount of free memory in a particular
CDTV/A500(+) at run time, use the Exec library's AvailMem()
function).  These results are not guaranteed for any particular
configuration, they can and will change depending upon many
variables, including additional hardware, overscan or interlaced
screens, etc.  Use this information only as a guideline.  Do not
assume that these result will remain constant in future releases of
the OS.

    WARNING:
    --------
    A title that consumes too much memory on a current configuration
    may not work in the future if a new release of the OS consumes
    even a little more memory.

Important note about Workbench V1.3 and V 2.0.  Under 1.3, the
Workbench screen and initial CLI always open upon booting with an
AmigaDOS disc.  Under 2.0, the system only opens the Workbench screen
when necessary,  and only opens an initial CLI if the
Startup-sequence attempts to output text.  The C:Avail program first
calculates the amount of free RAM and then prints out the results.
Under 2.0, this means the amount of memory printed by Avail would
differ from the amount of memory actually free by the amount needed
to create the Workbench screen and initial CLI.

             NTSC/ 1.3/
  Machine     PAL  2.0  Peripherals  *  Avail   In-Use  Maximum  Largest
  -------    ----  ---  -----------  -  -----   ------  -------  -------
  CDTV       NTSC  1.3  internal HD  c  799448  240704  1040152  797312
                        floppy
  CDTV       NTSC  1.3  floppy       c  886688  153464  1040152  710472
  CDTV       NTSC  2.0  floppy       c  840616  206936  1047552  689200
  CDTV       NTSC  1.3  SCSI card    c  881248  158904  1040152  704904
  CDTV       NTSC  1.3  floppy       c  878824  161328  1040152  878624
  CDTV       PAL   2.0  floppy       c  807528  239992  1047520  792880
  CDTV       PAL   2.0  none         c  828784  218768  1047552  824736
  CDTV       PAL   1.3  floppy       c  877936  162216  1040152  710552
  CDTV       PAL   1.3  internal HD  c  790488  249664  1040152  788352
                        floppy
  A500/570   NTSC  1.3  internal FD  c  466256  56976   523232   466208
                                     f  412728  104160  516888   412552
                                     t  878984  161136  1040120  466208
  A500/570   PAL   1.3  internal FD  c  457296  65936   523232   457248
                                     f  412704  104184  516888   412064
                                     t  870000  170120  1040120  457248
  A500+/570  PAL   2.0  internal FD  c  809744  237776  1047520  795144
  A500+      PAL   2.0  internal FD  c  839688  207864  1047552  838648
  CDTV       NTSC  1.3  floppy       c  886688  153464  1040152  710472
  CDTV       NTSC  2.0  floppy       c  840616  206936  1047552  689200
  CDTV       NTSC  1.3  SCSI card    c  881248  158904  1040152  704904
  CDTV       NTSC  1.3  floppy       c  878824  161328  1040152  878624
  CDTV       PAL   2.0  floppy       c  807528  239992  1047520  792880
  CDTV       PAL   2.0  none         c  828784  218768  1047552  824736
  CDTV       PAL   1.3  floppy       c  877936  162216  1040152  710552
  A500/570   NTSC  1.3  internal     c  466256  56976   523232   466208
                        floppy       f  412728  104160  516888   412552
                                     t  878984  161136  1040120  466208
  A500/570   PAL   1.3  internal     c  457296  65936   523232   457248
                        floppy       f  412704  104184  516888   412064
                                     t  870000  170120  1040120  457248
  A500+/570  PAL   2.0  internal     c  809744  237776  1047520  795144
                        floppy
  A500+      PAL   2.0  internal     c  839688  207864  1047552  838648
                        floppy

  * c=chip; f=fast; t=total
  FD = Floppy Drive; HD = Hard Drive


XIII-1: Video Adapter Diagrams

by Adam Levin-Delson

All Amigas have a video connector which supplies RGB output in both
analog and digital formats.  This allows the Amiga to use many
different types of monitors.  Besides this standard Amiga video
connector, the A3000 (and A3000T) have a ``Video Display Enhancer''
(VDE) connector which supplies an analog RGB signal at up to twice the
bandwidth of the standard Amiga port.

Commodore sells a number of monitors which have cables that allow you
to connect them to the Amiga.  Other manufacturers sell monitors that
will work with an Amiga, but many of these monitors are not
pin-compatible with the Amiga.  This can be remedied by buying or
building an adapter which either reconfigures the wiring or adds the
necessary circuitry between the computer and monitor.  This article
contains the wiring diagrams for those adapters.

 Warning
 Construction Tips
 15-Pin Male D-Sub to 9 Pin Female D-Sub Analog Adapter
 23-Pin Female D-Sub to 15 Pin Female D-Sub Analog Adapter
 23-Pin Female D-Sub to 9 Pin Female D-Sub Analog Adapter
 23-Pin Female D-Sub to 9 Pin Female D-Sub Digital Adapter


Warning

Though these instructions are fairly simple, if not done properly, it
is possible to damage both your computer and your video monitor, so
Commodore does not recommend that you build these yourself.  If you are
not proficient with the tools, parts, or procedures involved in making
these adapters, you should purchase them in completed form (Commodore
part numbers are provided later).  This information is provided for
your convenience and is expressly subject to the disclaimer and
warnings found at the beginning of this publication.


Construction Tips

Keep wires as short as possible to limit interference.

Female 23-pin connectors can be kludged from female 25-pin connectors
with a little patience and a little hacksaw.  Male 23-pin connectors
can be kludged from male 25-pin connectors by pulling a couple of pins.

Radio Shack's D-sub hoods (part numbers 276-15xx) make ideal adapter
housings, especially where additional circuitry is required.


15-Pin Male D-Sub to 9 Pin Female D-Sub Analog Adapter

This adapter connects the A3000's VDE connector to a 15/31kHz
analog-RGB monitor with a 9-pin connector.  Commodore does not
currently offer this adapter.

Alternatively, reverse the gender of both ends to connect a 15-pin,
multi-scan analog-RGB monitor to a computer's 9-pin analog-RGB
connector (non-Amiga).  This adapter is available from Commodore as
part #390683-01.

   15-Pin Male to 9 Pin Female Analog Diagram


23-Pin Female D-Sub to 15 Pin Female D-Sub Analog Adapter

This adapter connects the Amiga's standard RGB connector to a 15/31kHz
analog-RGB monitor with a 15-pin connector.

This adapter is available from Commodore as part #390682-01.

   23-Pin Female to 15 Pin Female Analog Diagram

A1-A14 are pins 1-14 of a 74HCT08 (dual-input AND gate) IC chip.  C1 is
a .01uf 50V ceramic capacitor.


23-Pin Female D-Sub to 9 Pin Female D-Sub Analog Adapter

This adapter connects the Amiga's standard RGB connector to a 15kHz
analog-RGB monitor with a 9-pin connector.

   23-Pin Female to 9 Pin Female Analog Diagram

A1-A14 are pins 1-14 of a 74HCT08 (dual-input AND gate) IC chip. C1 is
a .01uf 50V ceramic capacitor.


23-Pin Female D-Sub to 9 Pin Female D-Sub Digital Adapter

This adapter connects the Amiga's standard RGB connector to a 15kHz
digital-RGB video monitor with a 9-pin connector.

   23-Pin Female to 9 Pin Female Digital Diagram

A1-A14 are pins 1-14 of a 74LS04 (hex inverter) IC chip.  B1-B14 are
pins 1-14 of another 74LS04 IC chip.  C1 is a .1uf 16V ceramic
capacitor.


XIII-5: The 68030 and 68040 on the Zorro III Bus

The 68030 and 68040 on the Zorro III Bus

by Michael Sinz

The Zorro III bus presents several special design issues for systems
with either a 68030 or 68040 CPU.  This article discusses those
design issues and offers solutions to the potential problems that
they present to those developing Zorro III devices, in particular,
Zorro III devices that are not exclusively memory expansion devices.

Background - 68030 and 68040 Caches

Both the 68030 and the 68040 have two caches; one for instructions
and one for data.  The 68030's caches are 256-bytes long.  The
68040's caches are considerably larger: each is 4K long.  Both CPU's
caches store memory in 16-byte blocks which are referred to as a
cache line.  The CPU only keeps one address for each cache line.
Each cache line is further broken up into long words called cache
entries.  On the 68030, each cache entry is marked as either valid or
invalid, telling the CPU which long words in the cache still contain
valid data.  On the 68040, only an entire cache line can be marked as
valid or invalid.

When the 68030 caches a memory address, it uses bits four through
seven of the address as a hash value.  This value is an index that
tells the 68030 which cache line to use for a specific address.  This
means each memory address corresponds to only one cache line.  For
example, if the 68030 tried to read a long word from 0x0FFFFF9F,
since the 68030 index extends from bit four through seven, the index
is 0x9, which corresponds to the tenth cache line.  This also means
that many memory addresses correspond to the same cache line.  For
example, the addresses 0x01FFFF9F, 0x02FFFF9F, 0x03FFFF9F, and
0x04FFFF9F all correspond to the same cache line.

The 68040 cache uses a similar indexing scheme, but the 68040 is a
little more dynamic.  The 68040 has four cache lines for each index,
so the 68040 cache can hold on to four different addresses that share
the same index.  The 68040 also has a larger index (six bits).

While the caches are active, when the CPU executes an instruction
that reads memory, it will check if that memory is already in the
cache.  If the memory is in the cache and the cache entry (or, in the
case of the 68040, the cache line) is marked as valid, a cache hit
occurs, so the CPU reads from the cache instead of main memory.  If
the memory is not in the cache, or the cache entry (or cache line) is
marked invalid, a cache miss occurs, so the CPU has to perform a main
memory fetch.

The cache lines are used in conjunction with the 68030's and 68040's
burst mode.  Normally, the 68030 fills its caches one entry at a
time.  While in burst mode, the CPU fills its caches a whole cache
line at a time. This helps to reduce the number of cache misses.

On the 68030, it is possible to turn burst mode on and off
independently of its caches.  If the 68030 cache is on and burst mode
is off, the 68030 can fill its cache a single long word at a time,
rather than the four words at a time it would do in burst mode.  The
68040 is different.  On the 68040, the only way to turn on burst mode
is to turn on the cache, so there is no way to prevent a burst access
when using the cache.  The 68040 always fills a whole cache line at a
time.

The instruction cache on both CPUs is fairly straightforward.  As the
CPU fetches instructions from memory, it copies them into the cache
for quick access later.  The only time the CPU changes the
instruction cache is when it does a memory fetch.

The data cache is different.  The data cache can change when the CPU
fetches memory and when the CPU executes an instruction that writes
to memory.  The 68030 and 68040 deal with this differently.

The 68030 data cache is a write-through cache.  This means whenever
the 68030 executes an instruction that writes to memory, the 68030
always performs a write to main memory, even if that address is in
the data cache.

When a data write causes a cache miss, the 68030 will act as if it
has no data cache and write directly to memory (except in
write-allocate mode--see the next paragraph).  When a data write
causes a cache hit, the 68030 will update the cache entry (or
entries) as well as write to memory.  Basically, on a memory write
operation, the 68030 will only update cache entries that are
currently cached.  It will not allocate a new cache entry for a cache
miss.

The 68030 data cache has a mode called write-allocate.  In this mode,
the 68030 not only updates the data in the cache, but, in the case of
a cache miss, the 68030 can also allocate a new cache entry.  While
in this mode, if a data write causes a cache miss, the CPU first
marks the corresponding cache entry as invalid (or, if in burst mode,
the CPU marks the entire cache line as invalid).  If the data write
is a long word write and it is aligned on a long word boundary, the
CPU updates that long word in the cache and marks it as valid. The
68040 data cache is not always a write through cache.  It has a mode
called copyback.  While in copyback mode, a write operation on the
68040 will not write through to memory.  The data will remain in the
data cache until the CPU flushes it out.  For more information, see
the article, ``68040 Compatibility Warning'' from the July/August
1991 Amiga Mail.

Zorro III and the 68030

When the 68030 reads data from a memory address, it will cache that
address only if that memory address is marked as cachable.  Certain
areas of memory cannot be cachable, for example, hardware registers
of a Zorro III card.  On the Zorro III bus, when the CPU attempts to
read an address that is not cachable, the device that exists in that
address space asserts the Zorro III cache inhibit line (/CINH).  The
bus controller will turn this signal into the CPU's cache inhibit
signal, which tells the CPU not to cache the address.

The problem is with the 68030's data cache in write-allocate mode
(which the Amiga OS requires).  When write-allocate mode is disabled,
the 68030 will only allocate a cache entry for a data address if the
address is cachable.  The CPU knows if the address is cachable
because the device told it using the cache inhibit line.

While in write-allocate mode, the 68030 will also allocate a cache
entry during certain write operations.  If, while in write-allocate
mode, the 68030 writes a long word to a long word aligned address,
the 68030 will write to that address and will allocate a cache entry
for that address.  This provides a loophole where the 68030 will
allocate a cache entry for a non-cachable memory address.  If the CPU
does a long word write to a Zorro III hardware register that happens
to be aligned on a long word address, the 68030 will put that address
in the cache.  If the CPU attempts to read from that address again
and that address happens to still be in the data cache, it will see
the value in the cache and will not attempt to read the hardware
register.

So far, the conditions under which this loophole can occur have been
rare.  The loophole requires that a hardware register be both
writable and readable, aligned on a long word address, and be four
bytes long. This precludes the Amiga custom chip registers as they
are not both readable and writable (in general they are not four
bytes long either).  Zorro II devices don't apply as Zorro II devices
only have a 16 bit wide data path.  The small size of the 68030's
data cache also makes it tough for a register write and read to occur
without a cache flush happening in between.

However, as Zorro III devices start to hit the market, the conditions
under which the loophole can occur will become more commonplace.  To
avoid this problem, Zorro III card designers can utilize the
following hardware trick.

The trick is to ``mirror'' all of the hardware registers.  In this
scheme, every register that is both readable and writable is
accessible at two addresses.  One address is exclusively for reading
and the other address is exclusively for writing.  Now, if the 68030
performs a write and allocates a cache entry, the 68030 caches the
writing address, but not the reading address.

Another hardware trick that might seem to be a viable solution is to
align 32-bit register ports so that they do not fall on a long word
boundary.  Using this method, the 68030 will never cache the register
address on a data write because it is not aligned properly.  The
problem with this method is that reading (or writing) a long word
from a non-long word aligned address is considerably slower than from
a long word aligned address. This can almost double the amount of bus
traffic, making the entire system slower.

The 68040 and Zorro III

The 68040 does not have the problem that the 68030 has with Zorro II
space.  The 68040 contains two registers to give data space a default
mapping without the need of a Memory Management Unit (MMU).  On an
Amiga with a 68040, Exec uses one of these registers to map the low
24-bits of the Amiga's address space (the Zorro II range,
$00000000-$00FFFFFFFF) as non-cachable and serialized1 .

The Amiga uses the second register to map the remaining memory
($01000000-$FFFFFFFF) as cachable and non-serialized.  Because of its
mapping, any RAM in this region will yield considerably higher
performance than RAM in Zorro II space.  Unfortunately, this mapping
can cause problems for a Zorro III device that is not RAM.

When the 68040 accesses a Zorro III device that is in cachable
address space, the device can still tell the CPU that an address is
not cachable by asserting the CPU's cache inhibit line.  This
overrides the default mapping the 68040 has placed on the address
space.  However, this does not stop the CPU from doing a full line
burst.  When accessing address space mapped as cachable, the 68040
will always attempt to read or write a block the size of an entire
cache line (four long words).

This presents a problem when the 68040 attempts to read from a Zorro
III device that is in cachable address space and the device asserts
the CPU's cache inhibit line.  The 68040 cannot notice that the Zorro
III device asserted the CPU's cache inhibit line until the 68040
reads the first long word of the burst cycle.  By the time the 68040
sees that the first long word is not cachable, it is already too late
to stop the burst cycle, so the 68040 finishes the burst.  When the
burst is done, the 68040 throws out the extra three long words from
the burst read.  In this case, the 68040 performs four long word
memory accesses instead of just one.

Writing to the device is even worse.  When the 68040 writes data to
an address that is not currently in the data cache, the 68040 will
first try to fill a cache line.  When the 68040 sees that the device
asserts the CPU's cache inhibit line, it will finish the read and
then write out one long word.  Essentially, to perform a single
memory write, the 68040 performs four memory reads and one memory
write.

These excessive memory accesses can significantly hinder system
performance.  Certain Zorro III designs could make the 68040 as much
as four to five times slower.

The full line bursts also cause a second potential problem for some
possible Zorro III devices.  Reading certain types of hardware
registers will trigger the hardware to perform some extra function as
well.  It is not uncommon for a hardware device to supply a new data
value for a register after the CPU reads that register. If a Zorro
III device has such a register and the device is located in cachable
address space, the device can experience problems with reads and
writes of addresses surrounding the register.  If the CPU reads a
second hardware register at an address that is in the same quad-long
word as the register (i.e. the first register's address would be in
the same cache line as the second register's address),   when the CPU
performs its full line burst, it will read the first register in
addition to the second register.  Because the CPU reads the first
register, the device will reload the first register with a new value,
losing the previous value.

The Solution

There is a solution that will fix both potential problems for Zorro
III cards on 68040-based Amigas.  The MMU in the 68040 can map
specific pages of memory as non-cachable.  The 37.10 version of the
68040.library creates MMU tables that map only Zorro III memory
devices as cachable (actually it maps all RAM except Chip RAM as
cachable).  The library marks other Zorro III devices as
non-cachable.  The new library prevents the 68040 from doing full
line bursts to non-cachable devices, so the CPU only reads or writes
one long word at a time.  As the 68040.library uses the MMU to map
all address space, invalid addresses can no longer cause bus errors
(Guru #00000002), which may help a few ill-behaved products to work
on 68040 systems.

The 37.10 68040.library is part of the V39 OS present on the current
A4000.  Developers who are working on or have released 68040-based
expansion devices should contact CATS to obtain information on
distributing the library with their product.

There is only one problem with this solution.  Not all 68040s have
MMUs.  There are three kinds of 68040 chip: the MC68040, the
MC68LC040, and the MC68EC040.  The MC68040 has both an Floating Point
Unit (FPU) and an MMU.  The MC68LC040 is a regular MC68040 without an
FPU.  The MC68EC040 is a MC68LC040 without an MMU.

As the 68040.library requires an MMU to map address space, the fix
described above will not work on systems with an MC68EC040.  Because
burst mode on the 68040 is activated along with the cache, there is
no way to prevent a 68EC040-equipped Amiga from doing full line
bursts when accessing cachable address space.  This means a 68EC040
cannot prevent the excessive reads and writes when reading
non-cachable Zorro III devices that reside in cachable address space.
A 68EC040-equipped Amiga will experience a significant decrease in
performance when accessing non-cachable Zorro III devices.  For this
reason we cannot recommend that anyone use a 68EC040 (or any future
68000 series CPU that has no MMU) as the CPU on a Zorro III bus
system.

If someone decides not to heed this warning and create a 68EC040 CPU
card for the Zorro III bus, there is nothing the 68EC040 card can do
to prevent these problems, although there is still a way for a Zorro
III card to prevent the second 68040 problem (the ``register
trigger'' problem).  A Zorro III card that needs to use ``trigger''
registers can arrange the trigger registers so that each register is
in its own quad-long word.  This way, when the 68EC040 reads one of
these registers, the read operation won't disturb other registers, as
two registers do not reside in the same quad-long word.  Note that
this fix will not prevent the first problem (the performance decrease
problem) and it does not address the possibility that future CPUs may
have an eight or sixteen long word cache line.


XIII-11: Expanding RAM on the Amiga 4000

Expanding RAM on the Amiga 4000

by Adam Levin-Delson

Commodore currently sells the Amiga 4000 with two megabytes of Chip
RAM and four megabytes of Fast RAM.  Chip RAM refers to memory that
both the CPU and the Amiga's custom chips can access directly.  The
custom chips cannot directly access Fast RAM.  Two megabytes is the
maximum amount of Chip RAM that the computer can presently access,
but Fast RAM can be upgraded to a maximum of either four or 16
megabytes, depending upon the type of RAM used.

Memory Layout

All the A4000's RAM is packaged in SIMM (single in-line memory
module) format, which is easy to handle, making upgrading a simple
procedure.  A single four-megabyte SIMM is used to give the Amiga its
four megabytes of Fast RAM.  This leaves three more Fast RAM SIMM
slots, each capable of holding another four megabytes for a total of
eight, twelve, or the maximum of sixteen megabytes of Fast RAM.  It
is possible to use less expensive one megabyte SIMMs as Fast RAM, but
since SIMM types cannot be mixed this would require the removal of
the existing four-megabyte SIMM.  Since there are only four SIMM
slots, using one-megabyte SIMMs would yield a maximum of four
megabytes of memory.

The single slot for Chip RAM is unique in that it has no neighboring
slot to its right.  This allows the use of a double-sided SIMM (with
chips on both sides), instead of the single-sided SIMMs as required
by the spacing of the Fast RAM SIMM slots.  A single two-megabyte
SIMM is used to give the Amiga its two megabytes of Chip RAM.  This
SIMM may be removed and a one-megabyte SIMM used in its place, giving
a total of one megabyte of Chip RAM.

Adding Memory

Adding SIMMs to the existing Fast RAM requires no additional action.
Changing from four megabyte to one megabyte SIMMs (or vice versa)
requires changing a jumper on the motherboard.  This jumper (J852) is
on the left side of the motherboard (the same side as the SIMM slots
are on).  It is labelled ``SIMM SIZE'' and has two positions: ``256K
x 32'' and ``1M x 32''.  Jumper the ``256K'' pin and the center pin
for one megabyte SIMMs, the ``1M'' pin and the center pin for four
megabyte SIMMs.

No jumper change is required when switching between one-megabyte and
two-megabyte Chip RAM SIMMs.

SIMM Specifications

Each one megabyte Fast RAM SIMM must meet the following specifications:

physical:       72-pin, single-sided SIMM with a maximum height of
                one inch (If this SIMM is to be used as Chip RAM,
                it may be double-sided).
electrical:     80-nanosecond DRAM, 256 kilobytes by 32 bits or 256
                kilobytes by 36 bits.

Each two megabyte Fast RAM SIMM must meet the following specifications:

physical:       72-pin, SIMM with a maximum height of one inch (This SIMM
                is only suitable as Chip RAM.  As such, it may be
                double-sided).
electrical:     80-nanosecond DRAM, 512 kilobytes by 32 bits or 512
                kilobytes by 36 bits.

Each four megabyte Fast RAM SIMM must meet the following specifications:

physical:       72-pin, single-sided SIMM with a maximum height of one
                inch.
electrical:     80-nanosecond DRAM, 1 megabyte by 32 bits or 1 megabyte
                by 36bits.

The ``by 36 bits'' parts are overkill in that only the first 32 bits
are used, but they may be more readily available than the ``by 32
bits'' parts.

Amiga 4000 Block Diagram

Below is a block diagram of a production A4000 motherboard.  It shows
the approxomate position of most of its major chips and most of the
jumpers that may be of interest to delelopers.

J100/J104 - Both are three pin jumpers.  Together, these jumpers
determine the source of the CPU clock.  For both J100 and J104, if
pins 1 and 2 are connected, the CPU daughterboard uses the internal
clock on the motherboard.  If pins 2 and 3 are connected, the
daughterboard uses its own clock.  As the 68040 daughterboard has its
own clock, pins 2 and 3 are the default.  These two jumpers must be
set to the same clock!

J212 - This is a three pin jumper.  If pins 1 and 2 are connected,
the system defaults to an NTSC system.  If pins 2 and 3 are
connected, the system defaults to a PAL system.

J351 - This is a two pin shunt.  If it is closed, the system will
assume floppy drive DF1: is a 880K floppy drive.  If it is open, the
system assumes DF1: is a 1.76M floppy drive.

J850 - This is a two pin shunt.  If it is closed, the system will use
the DSACK signal to terminate a bus cycle.  If it is open, the system
will use the STERM signal.

J852 - This is a three pin jumper.  If pins 1 and 2 are connected,
the system assumes that the Fast RAM SIMMs are 4 Megabyte SIMMs.  If
pins 2 and 3 are connected, the system assumes that the Fast RAM
SIMMs are 1 Megabyte SIMMs.

SIMM Manufacturers

The following companies make the listed SIMMs which are known to work
in the A4000.  This list is not intended to endorse any particular
manufacturer, nor to imply that other sources do not exist.  This
list is included solely for completeness of information.

    Part             Commodore      Manufacturer        Manufacturer
                    part number     part number

1 megabyte SIMMs    391396-01       Motorola            MCM32256S-80
                                                        MCM32L256S-80
                                    Micron              MT8D25632M-80

2 megabyte SIMMs    391517-01       Motorola            MCM32512S-80
                                    Micron              MT16D51232M-80
                                    Texas Instruments   TM512CBK32-80

4 megabyte SIMMs    391518-01       Motorola            MCM32100S-80
                                    Micron              MT8D132M-80
                                    Texas Instruments   TM124BBK32-80


XIII-15: A1200 CPU Card Expansion RAM

A1200 CPU Card Expansion RAM

by Michael Sinz

When the Amiga OS boots, it automatically notices and utilizes
expansion hardware (such as RAM).  Prior to the A3000, the only CPU
native to any Amiga was the MC68000, which could only address a
24-bit wide address space.  As a result, the address space that was
available to these machines was only 24 bits wide.  CPU expansion
products for the MC68000-based Amigas (like the A2630 for the A2000)
can utilize address space beyond the 24-bit limit, but the CPU board
cannot use the AutoConfig process to add expansion RAM in the address
space beyond the 24-bit limit.

Like the MC68000 based Amigas, the Amiga 1200 also has a CPU that
only addresses a 24-bit wide address space, the MC68EC020.  Also like
most of the MC68000 based Amigas, it is possible to add a CPU
expansion device.  One way the A1200 differs from its 24-bit siblings
is the A1200 has set aside a 128 Megabyte range of address space
($0800 0000 through $0FFF FFFF) specifically for such a device (just
like the A3000).  Any expansion RAM on the A1200's CPU card should
appear in this range.

The Release 3 OS in the current A1200 is not smart enough to
recognize a 32-bit CPU expansion device vs. a 24-bit expansion
device.  As a result, the system assumes that the expansion device is
a 24-bit expansion device.  If a user expands their A1200 with a
32-bit CPU card that has 32-bit expansion memory on it, the OS cannot
automatically add the CPU card's expansion memory during the
autoconfig process.  The CPU card's ROM has to add the memory to the
system.

The code to make the A1200 smart enough to recognize a 32-bit CPU
card will be in a future ROM revision.  This change will allow the OS
to automatically notice and add the CPU card's expansion RAM.  This
makes it possible for the system to add this 32-bit memory to the
A1200's system memory relatively early in the boot process.  Because
the memory is available earlier in the boot process, Exec has the
opportunity to use the 32-bit memory for system purposes (this can
include the supervisor stack, ExecBase, and most other library bases).

This change presents a minor problem for an A1200 CPU card that adds
its own memory.  Before the CPU card can add its memory to the system
memory list, it must make sure the OS has not already added that
memory.  The CPU card can use the following code to test if the A1200
has already added the CPU card's expansion memory.  This code queries
the system about the type of memory located at the low end of the
coprocessor slot expansion address range.  If the system has already
added memory at this location, TypeOfMem() returns the
characteristics of that memory.  If no memory is at that location,
TypeOfMem() returns zero.

    /*
     * Note that we check the memory 16K from the start as the
     * first few bytes may have been used by the OS when doing
     * the automatic testing...
     */
    if (!TypeOfMem(0x08001000))
    {
        /*
         * If TypeOfMem() returned 0, the memory does not
         * exist.  At this point, you can do whatever
         * memory tests that may be needed and then
         * AddMemList() the memory as needed.
         *
         * **NOTE**  Do *NOT* do the memory test if the memory
         * has already been added as it may be in use by some
         * very important things, including interrupt vectors
         * and/or code.
         */
        AddMemList(size,MEMF_FAST|MEMF_PUBLIC,pri,0x08000000,"CPU RAM");
    }

More About the New A1200 Code

The code to make the A1200 detect 32-bit CPU cards will also notice
``natural wrapping'' in the board's memory.  If a board has only a
limited amount of memory, it is possible to design the board so that
the physical memory is accessible at many addresses at regular
address intervals.  For example, if the board has four megabytes of
memory, that memory could be accessed at four megabyte intervals
(address $0800 0000, $0840 0000, $0880 0000, and so on).

Because the OS notices the wrap, CPU cards can use a more economical
design because they don't have to be as complex.  It also cuts down
on the need for jumpers or switch settings.  The code requires that
the A1200 CPU board's memory sizes be in multiples of 1 megabyte
(512K is not supported).


XIII-17: Game Port Form Factor

Game Port Form Factor

The new models in the Amiga product family all use a standard a
D-style, 9-pin male connector for mouse and joystick controllers.  On
the Amiga 600, the small size of the motherboard requires a design in
which these two connectors are very close together.

Shown below are the recommended dimensions to use for the female
connector on a mouse or joystick compatible with all Amiga models.
All dimensions are in millimeters.

The diagrams below show the arrangement of the connectors on the new
Amiga models, the Amiga 600, Amiga 1200, and Amiga 4000.  Note that
these show the openings in the Amiga's casework, not the size of the
connectors.  As you can see, the placement of the connectors on the
Amiga 600 requires a mouse or joystick with a connector that conforms
to the specification above.   All dimensions are in millimeters.

Figure 1 - A1200 Game Port
Figure 2 - A4000 Game Port
Figure 3 - A600 Game Port
Figure 4 - Game connector casing


I-7/SimpleFR.c

;/* simpleFR.c - Execute me to compile me with SAS/C 6.56
sc DATA=NEAR NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 simpleFR.c
slink FROM LIB:c.o,simpleFR.o TO simpleFR LIBRARY LIB:sc.lib,LIB:amiga.lib
quit
*/

/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <clib/asl_protos.h>
#include <clib/exec_protos.h>
#include <clib/alib_stdio_protos.h>
#include <dos/dosasl.h>
#include <exec/libraries.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

UBYTE *vers = "\0$VER: simpleFR 1.1";

void main(void);

#define MYLEFTEDGE 0
#define MYTOPEDGE  0
#define MYWIDTH    320
#define MYHEIGHT   400

struct Library *AslBase;

struct TagItem frtags[] =
{
    ASL_Hail,       (ULONG)"The RKM file requester",
    ASL_Height,     MYHEIGHT,
    ASL_Width,      MYWIDTH,
    ASL_LeftEdge,   MYLEFTEDGE,
    ASL_TopEdge,    MYTOPEDGE,
    ASL_OKText,     (ULONG)"O KAY",
    ASL_CancelText, (ULONG)"not OK",
    ASL_File,       (ULONG)"asl.library",
    ASL_Dir,        (ULONG)"libs:",
    TAG_DONE
};

void main()
{

    struct FileRequester *fr;

    if (AslBase = OpenLibrary("asl.library", 36L))
    {
        if (fr = (struct FileRequester *)
            AllocAslRequest(ASL_FileRequest, frtags))
        {
            /* Application body, blah, blah,... */

            /* Application need a requester */
            if (AslRequest(fr, 0L))
                printf("file choice = %s%s\n", fr->rf_Dir, fr->rf_File);
            else
                printf("User Cancelled\n");

            /* More application body, blah, blah... */
        }

        /* Don't need any more requesters, better
        ** give the requester structure back.
        */
        FreeAslRequest(fr);
    }
    CloseLibrary(AslBase);
}


I-7/FilePat.c

;/* filepat.c - Execute me to compile me with SAS/C 6.56
sc DATA=NEAR NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 filepat.c
slink FROM LIB:c.o,filepat.o TO filepat LIBRARY LIB:sc.lib,LIB:amiga.lib
quit
*/

/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <clib/asl_protos.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/alib_stdio_protos.h>
#include <workbench/startup.h>
#include <intuition/intuition.h>
#include <intuition/screens.h>
#include <graphics/displayinfo.h>
#include <exec/libraries.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

UBYTE *vers = "\0$VER: filepat 1.0";

void main(void);

struct Library *AslBase;
struct IntuitionBase *IntuitionBase;
struct Screen *screen;
struct Window *window;

struct WBArg *wbargs;

LONG x;

void main()
{

    struct FileRequester *fr;

    if (AslBase = OpenLibrary("asl.library", 36L))
    {
        if (IntuitionBase = (struct IntuitionBase *)
                OpenLibrary("intuition.library", 36L))
        {
            if (screen = (struct Screen *)OpenScreenTags(NULL,
                    SA_DisplayID, HIRESLACE_KEY,
                    SA_Title, "ASL Test Screen",
                    TAG_END))
            {
                if (window = (struct Window *)OpenWindowTags(NULL,
                        WA_CustomScreen, screen,
                        WA_Title, "ASL Test Window",
                        WA_Flags, WINDOWDEPTH | WINDOWDRAG,
                        TAG_END))
                {
                    if (fr = (struct FileRequester *)
                        AllocAslRequestTags(ASL_FileRequest,
                            ASL_Hail, (ULONG)"RKM File Requester, FilePat",
                            ASL_Dir,  (ULONG)"libs:",
                            ASL_File, (ULONG)"asl.library",

                            /* The initial pattern string for the
                            ** pattern gadget.
                            */
                            ASL_Pattern, (ULONG)"~(rexx#?|math#?)",

                            /* turn on multiselection and the pattern
                            ** matching gadget.
                            */
                            ASL_FuncFlags, FILF_MULTISELECT | FILF_PATGAD,

                            /* This requester is associated with this
                            ** window (and uses its message port).
                            */
                            ASL_Window, window,
                            TAG_DONE))
                    {
                        /* Application code body...*/

                        /* Put up file requester */
                        if (AslRequest(fr, 0L))
                        {
                            /* If the file requester's rf_NumArgs field
                            ** is not zero, the user multiselected. The
                            ** number of files is stored in rf_NumArgs.
                            */
                            if (fr->rf_NumArgs)
                            {
                                /* rf_ArgList is an array of WBArg structures
                                ** (defined in <workbench/startup.h>).
                                ** Each entry in the WBArg array corresponds
                                ** to one of the files the user selected
                                ** (the entries are in alphabetical order).
                                */
                                wbargs = fr->rf_ArgList;

                                /* The user multiselected, step through
                                ** the list of selected files.
                                */
                                for ( x=0;  x < fr->rf_NumArgs;  x++ )
                                    printf("Argument %d - %s%s\n", x,
                                        fr->rf_Dir, wbargs[x].wa_Name);
                            }
                            else
                                /* The user didn't multiselect, use the
                                ** normal way to get the file name.
                                */
                                printf("%s%s\n", fr->rf_Dir, fr->rf_File);
                        }
                        /* More application code body... */

                        /* Done with the FileRequester, better return it */
                        FreeAslRequest(fr);
                    }
                    CloseWindow(window);
                }
                CloseScreen(screen);
            }
            CloseLibrary(IntuitionBase);
        }
        CloseLibrary(AslBase);
    }
}


I-7/FontReq.c

;/* fontreq.c - Execute me to compile me with SAS/C 6.56
sc DATA=NEAR NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 fontreq.c
slink FROM LIB:c.o,fontreq.o TO fontreq LIBRARY LIB:sc.lib,LIB:amiga.lib
quit
*/

/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <clib/asl_protos.h>
#include <clib/exec_protos.h>
#include <clib/alib_stdio_protos.h>
#include <exec/libraries.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

UBYTE *vers = "\0$VER: fontreq 1.0";

void main(void);
struct Library *AslBase, *UtilityBase;

/* The replacement strings for the "mode" cycle gadget.  The
** first string is the cycle gadget's label.  The other strings
** are the actual strings that will appear on the cycle gadget.
*/
UBYTE *modelist[] =
{
    "RKM Modes",
    "Mode 0",
    "Mode 1",
    "Mode 2",
    "Mode 3",
    "Mode 4",
    "Mode 5",
    "Mode 6",
    "Mode 7",
    "Mode 8",
    "Mode 9",
    NULL
};

void main()
{

    struct FontRequester *fr;

    if (AslBase = OpenLibrary("asl.library", 36L))
    {

        if (fr = (struct FontRequester *)
            AllocAslRequestTags(ASL_FontRequest,
                /* tell the requester to use my custom mode names */
                ASL_ModeList, modelist,

                /* Supply initial values for requester */
                ASL_FontName, (ULONG)"topaz.font",
                ASL_FontHeight, 11L,
                ASL_FontStyles, FSF_BOLD | FSF_ITALIC,
                ASL_FrontPen,  0x00L,
                ASL_BackPen,   0x01L,

                /* Only display font sizes between 8 and
                ** 14, inclusive. */
                ASL_MinHeight, 8L,
                ASL_MaxHeight, 14L,

                /* Give us all the gadgetry, but only display
                ** fixed width fonts */
                ASL_FuncFlags, FONF_FRONTCOLOR | FONF_BACKCOLOR |
                    FONF_DRAWMODE | FONF_STYLES | FONF_FIXEDWIDTH,
                TAG_DONE))
        {
            /* application code here... */

            /* Pop up the requester */
            if (AslRequest(fr, 0L))
            {
                /* The user selected something,  report their choice */
                printf("%s\n  YSize = %d  Style = 0x%x   Flags = 0x%x\n"
                       "  FPen = 0x%x   BPen = 0x%x   DrawMode = 0x%x\n",
                               fr->fo_Attr.ta_Name,
                               fr->fo_Attr.ta_YSize,
                               fr->fo_Attr.ta_Style,
                               fr->fo_Attr.ta_Flags,
                               fr->fo_FrontPen,
                               fr->fo_BackPen,
                               fr->fo_DrawMode);
            }
            else
                /* The user cancelled the requester, or
                ** some kind of error occured preventing
                ** the requester from opening. */
                printf("Request Cancelled\n");

            /* more application code here ...*/

            FreeAslRequest(fr);
        }
        CloseLibrary(AslBase);
    }
}


I-7/FileHook.c

;/* filehook.c - Execute me to compile me with SAS/C 6.56
sc DATA=NEAR NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 filehook.c
slink FROM LIB:c.o,filehook.o TO filehook LIBRARY LIB:sc.lib,LIB:amiga.lib
quit
*/
/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <clib/asl_protos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>
#include <clib/alib_stdio_protos.h>
#include <dos/dosasl.h>
#include <intuition/intuition.h>
#include <exec/libraries.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

#define DESTPATLENGTH 20

UBYTE *vers = "\0$VER: filehook 1.0";

void main(void);

struct Library *AslBase;
struct IntuitionBase *IntuitionBase;
struct Window *window;

CPTR HookFunc();

/* this is the pattern matching string that the hook function uses */
UBYTE *sourcepattern = "(#?.info)";
UBYTE pat[DESTPATLENGTH];

void main()
{

    struct FileRequester *fr;

    /* This is a dos.library function that turns a pattern matching
    ** string into something the DOS pattern matching functions
    ** can understand.
    */
    ParsePattern(sourcepattern, pat, DESTPATLENGTH);

    if (AslBase = OpenLibrary("asl.library", 36L))
    {
        if (IntuitionBase = (struct IntuitionBase *)
                    OpenLibrary("intuition.library", 36L))
        {
            /* open a window that gets ACTIVEWINDOW events */
            if (window = (struct Window *)OpenWindowTags(NULL,
                    WA_Title, "ASL Hook Function Example",
                    WA_IDCMP, IDCMP_ACTIVEWINDOW,
                    WA_Flags, WINDOWDEPTH,
                    TAG_END))
            {
                if (fr = AllocFileRequest())
                {
                    /* application body here... */

                    if (AslRequestTags(fr,
                        ASL_Window, window,
                        ASL_TopEdge, 0L,
                        ASL_Height, 200L,
                        ASL_Hail, (ULONG)"Pick an icon to save",
                        ASL_HookFunc, (ULONG)HookFunc,
                        ASL_FuncFlags, FILF_DOWILDFUNC | FILF_DOMSGFUNC | FILF_SAVE,
                        ASL_OKText, (ULONG)"Save",
                        TAG_DONE))
                    {
                        printf("You picked %s%s\n", fr->rf_Dir, fr->rf_File);
                    }

                    /* more application body here */

                    FreeFileRequest(fr);
                }
                CloseWindow(window);
            }
            CloseLibrary(IntuitionBase);
        }
        CloseLibrary(AslBase);
    }
}

CPTR HookFunc(LONG type, CPTR obj, struct FileRequester *fr)
{
    static BOOL returnvalue;
    switch(type)
    {
        case FILF_DOMSGFUNC:
        /* We got a message meant for the window */
            printf("You activated the window\n");
            return(obj);
            break;
        case FILF_DOWILDFUNC:
        /* We got an AnchorPath structure, should
        ** the requester display this file? */

            /* MatchPattern() is a dos.library function that
            ** compares a matching pattern (parsed by the
            ** ParsePattern() DOS function) to a string and
            ** returns true if they match. */
            returnvalue = MatchPattern(pat,
                    ((struct AnchorPath *)obj)->ap_Info.fib_FileName);

            /* we have to negate MatchPattern()'s return value
            ** because the file requester expects a zero for
            ** a match not a TRUE value */
            return( (CPTR)(! returnvalue) );
            break;
    }
}


I-43/Hooks1.c

/* hooks1.c
 * Simple hook example
 * Copyright (C) 1991-1999 Amiga, Inc.
 *
 */

#include <exec/types.h>
#include <exec/libraries.h>
#include <utility/hooks.h>
#include <clib/exec_protos.h>
#include <clib/utility_protos.h>

extern struct Library *SysBase;
struct Library *UtilityBase;

#define ASM     __asm
#define REG(x)  register __ ## x

/* This function converts register-parameter Hook calling
 * convention into standard C conventions.  It requires a C
 * compiler that supports registerized parameters, such as
 * SAS/C 5.xx or greater.
 */
ULONG ASM
hookEntry(REG(a0) struct Hook *h, REG(a2) VOID *o, REG(a1) VOID *msg)
{
    return ((*h->h_SubEntry)(h, o, msg));
}

/* This simple function is used to initialize a Hook */
VOID InitHook (struct Hook *h, ULONG (*func)(), VOID *data)
{
    /* Make sure a pointer was passed */
    if (h)
    {
        /* Fill in the Hook fields */
        h->h_Entry = (ULONG (*)()) hookEntry;
        h->h_SubEntry = func;
        h->h_Data = data;
    }
}

/* This function only prints out a message to the serial port indicating that
 * we are inside the callback function.  Note that we cannot use printf() or
 * any other functions that use standard I/O with any of the system modules that
 * support callback Hooks, because there is no guarantee that there would
 * be a valid Output() channel. */

ULONG MyFunction (struct Hook *h, VOID *o, VOID *msg)
{
    /* Obtain access to the global data segment */
    geta4();

    /* Debugging function to send a string to the serial port */
    KPrintF("Inside MyFunction()\n");

    return (1);
}

int main (int argc, char **argv)
{
    struct Hook h;

    /* Open the utility library */
    if (UtilityBase = OpenLibrary ("utility.library", 36))
    {
        /* Initialize the callback Hook */
        InitHook (&h, MyFunction, NULL);

        /* Use the utility library function to invoke the Hook */
        CallHookPkt (&h, NULL, NULL);

        /* Close utility library now that we're done with it */
        CloseLibrary (UtilityBase);
    }
    else
    {
        /* Display an error message */
        printf ("Couldn't open utility.library\n");
    }
}


II-1/SystemTest.c

;/* SystemTest.c - Execute me to compile me with SAS/C 6.56
;   Demonstration of System(), AUTO CON, and custom screen CON
sc DATA=NEAR NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 SystemTest.c
slink FROM LIB:c.o,SystemTest.o TO SystemTest LIBRARY LIB:sc.lib,LIB:amiga.lib
quit
*/
/*
Copyright (c) 1990-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <exec/types.h>
#include <exec/libraries.h>
#include <dos/dos.h>
#include <dos/dostags.h>
#include <intuition/intuition.h>
#include <graphics/displayinfo.h>

#ifdef LATTICE
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

/* our function error codes */
#define SYSTEMFAIL      (-1L)
#define WINDOWFAIL      (-2L)

/* function prototypes */
LONG beginCommand(UBYTE *command);
LONG doCommand(UBYTE *command, BPTR other);
VOID checkResult(UBYTE *command, LONG result);

/* Formatted version string for the 2.0 VERSION command */
UBYTE *vers = "\0$VER: SystemTest 36.10";

struct Library *IntuitionBase;

struct Screen *OpenScreenTags(struct NewScreen *,ULONG tags, ...);
struct Window *OpenWindowTags(struct NewWindow *,ULONG tags, ...);

void main(int argc, char **argv)
    {
    extern struct Library *DOSBase;
    struct Screen *scr = NULL;
    struct Window *win = NULL;
    ULONG penspecterm = ~0;
    LONG result;
    BPTR file;
    UBYTE *command;
    UBYTE buf[128];

    if(DOSBase->lib_Version < 36)
        {
        printf("This example requires dos.library V36 or higher\n");
        exit(RETURN_FAIL);
        }
    if(!(IntuitionBase = OpenLibrary("intuition.library",36)))
        {
        printf("This example requires intuition.library V36 or higher\n");
        exit(RETURN_FAIL);
        }

    /* SYNCHRONOUS SYSTEM() WITH OUR INPUT/OUTPUT
     */
    printf("\n*** SystemTest: Synchronous System call 'dir libs:':\n");
    command = "dir libs:";
    result = doCommand(command,NULL);
    checkResult(command,result);
    printf("\n*** SystemTest: Synchronous System call of nonexistant command:\n");
    command = "badcommand";
    result = doCommand(command,NULL);
    checkResult(command,result);

    printf("\n*** SystemTest: Synchronous System call 'ask \"...Answer y now\"':\n");
    command =
        "ask \"Ready for CON: on a Custom Screen? Answer y now (should return 5):\"";
    result = doCommand(command,NULL);
    checkResult(command,result);

   /* SYNCHRONOUS SYSTEM() WITH CON: IN A CUSTOM SCREEN AND WINDOW
     */
    if(scr = OpenScreenTags(NULL,
                SA_Width, 640,
                SA_Height, 200,
                SA_Depth, 3,
                SA_DisplayID, HIRES_KEY,
                SA_Pens, &penspecterm,  /* Give us New Look */
                TAG_DONE))
        {
        if(win = OpenWindowTags(NULL,
                WA_CustomScreen, scr,
                WA_Flags, WINDOWDRAG|WINDOWCLOSE|ACTIVATE,
                WA_IDCMP, CLOSEWINDOW,
                WA_Top, 20,
                WA_Height, scr->Height - 20,
                WA_Title, "Custom Window",
                WA_ScreenTitle, "Custom Screen",
                TAG_DONE))
            {
            sprintf(buf,"CON://///WINDOW0x%lx", win); /* adds window pointer */
            if(file = Open(buf, MODE_OLDFILE))
                {
                command = "echo \"CLI commands on a custom screen!\"";
                result = doCommand(command,file);
                command = "dir libs:";
                result = doCommand(command,file);
                command = "echo \"( Click CLOSE gadget, or type CTRL-C )\"";
                result = doCommand(command,file);
                Wait(1 << win->UserPort->mp_SigBit | SIGBREAKF_CTRL_C);
                Close(file);    /* Closes the window too */
                }
            else CloseWindow(win);
            }
        CloseScreen(scr);
        }

    printf("\n*** SystemTest: Synchronous System call 'ask \"...Answer y now\"':\n");
    command = "ask \"Ready for Asynchronous demo? Answer y now (should return 5):\"";
    result = doCommand(command,NULL);
    checkResult(command,result);

    /* ASYNCHRONOUS SYSTEM() WITH ON-DEMAND AUTO/WAIT CON:
     */
    printf("\n*** SystemTest: Asynchronous startup of 'Sys:Utilities/Clock':\n");
    command = "SYS:Utilities/Clock";
    result = beginCommand(command);
    checkResult(command,result);

    printf("\n*** SystemTest: Asynchronous startup of 'avail':\n");
    command = "avail";
    result = beginCommand(command);
    checkResult(command,result);

    printf("\nSystemTest exiting. Close Clock and Autocon window when you wish.\n");

    CloseLibrary(IntuitionBase);
    exit(RETURN_OK);
    }

/*
 * Synchronous external command (wait for return)
 * Uses your Input/Output unless you supply other handle
 * Result will be return code of the command, unless the System() call
 * itself fails, in which case the result will be -1
 */
LONG doCommand(UBYTE *command, BPTR other)
    {
    struct TagItem stags[4];

    stags[0].ti_Tag = SYS_Input;
    stags[0].ti_Data = other ? other : Input();
    stags[1].ti_Tag = SYS_Output;
    stags[1].ti_Data = other ? NULL: Output();
    stags[3].ti_Tag = TAG_DONE;
    return(System(command, stags));
    }

/*
 * Asynchronous external command started with its own autocon Input/Output
 * This routine shows use of the SYS_UserShell tag as well.
 * Result will only reflect whether System() call itself succeeded.
 * If System() call fails, result will be -1L
 * We are using -2L as result if our Open of CON: fails
 */
UBYTE *autocon="CON:0/40/640/150/Auto CON Window Opens if Needed/auto/close/wait";
LONG beginCommand(UBYTE *command)
    {
    struct TagItem stags[5];
    BPTR file;

    if(file = Open(autocon, MODE_OLDFILE))
        {
        stags[0].ti_Tag = SYS_Input;
        stags[0].ti_Data = file;
        stags[1].ti_Tag = SYS_Output;
        stags[1].ti_Data = NULL;
        stags[2].ti_Tag = SYS_Asynch;
        stags[2].ti_Data = TRUE;
        stags[3].ti_Tag = SYS_UserShell;
        stags[3].ti_Data = TRUE;
        stags[4].ti_Tag = TAG_DONE;
        return(System(command, stags));
        }
    else return(WINDOWFAIL);
    }

/*
 * Demo routine outputs result of System
 */
VOID checkResult(UBYTE *command, LONG result)
    {
    if(result == SYSTEMFAIL)
        printf("*** SystemTest: could not start process for command\n");
    else if(result == WINDOWFAIL)
        printf("*** SystemTest: can't open con: for command\n");
    else
        printf("*** SystemTest: command (if synchronous) returned %ld\n",result);
    }

/*
 * Stack based stubs for opening screen, window
 */
struct Screen *OpenScreenTags(ns, tags)
struct NewScreen *ns;
ULONG tags;
    {
    return (OpenScreenTagList(ns, (struct TagItem *)&tags));
    }

struct Window *OpenWindowTags(nw, tags)
struct NewWindow *nw;
ULONG tags;
    {
    return (OpenWindowTagList(nw, (struct TagItem *)&tags));
    }


II-27/ReadArgs.c

;/* ReadArgs.c - Execute me to compile me with SAS/C 6.56
sc DATA=NEAR NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 ReadArgs.c
slink FROM LIB:c.o,ReadArgs.o TO ReadArgs LIBRARY LIB:sc.lib,LIB:amiga.lib
quit
*/

/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <dos/dos.h>
#include <dos/rdargs.h>
#include <clib/dos_protos.h>
#include <clib/alib_stdio_protos.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }
#endif

UBYTE *vers = "\0$VER: ReadArgs 1.0";

#define TEMPLATE "S=SourceFiles/A/M,D=DebugLevel/K/N,L=link/S"
#define OPT_SOURCE  0
#define OPT_DEBUG   1
#define OPT_LINK    2
#define OPT_COUNT   3

/* The array of LONGs where ReadArgs() will store the data from
** the command line arguments.  C guarantees that all the array
** entries will be set to zero.
*/
LONG result[OPT_COUNT];

/* My custom RDArgs */
struct RDArgs *myrda;

ULONG StrLen(UBYTE *);

void main(void)
{
    UWORD x;
    UBYTE **sourcefiles;

    /* Need to ask DOS for a RDArgs structure */
    if (myrda = (struct RDArgs *)AllocDosObject(DOS_RDARGS, NULL))
    {
        /* set up my parameters for ReadArgs() */

        /* use the following command line */
        myrda->RDA_Source.CS_Buffer = "file1 file2 file3 D=1 Link file4 file5\n";
        myrda->RDA_Source.CS_Length = (LONG)StrLen(myrda->RDA_Source.CS_Buffer);

        /* parse my command line */
        if (ReadArgs(TEMPLATE, result, myrda))
        {
            /*start printing out the results */

            /* We don't need to check if there is a value in
            ** result[OPT_SOURCE] because the ReadArgs() template
            ** requires (using the /A modifier) that there be
            ** file names, so ReadArgs() will either fill in a
            ** value or ReadArgs() will fail.
            */
            sourcefiles = (UBYTE **)result[OPT_SOURCE];
            /* VPrintf() is a lot like Printf() except it's in
            ** ROM, and the arguments are referenced from an
            ** array rather than being extracted from the stack.
            */
            VPrintf("Files specified:\n", NULL);
            for (x=0; sourcefiles[x]; x++)
                VPrintf("\t%s\n", (LONG *)&sourcefiles[x]);

            /* Is there something in the "DebugLevel" option?
            ** If there is, print it.
            */
            if (result[OPT_DEBUG])
                VPrintf("Debugging Level = %ld\n", (LONG *)result[OPT_DEBUG]);

            /* If the link toggle was present, say something about it. */
            if (result[OPT_LINK])
                VPrintf("linking...\n", NULL);
            FreeArgs(myrda);
        }
        FreeDosObject(DOS_RDARGS, myrda);
    }
}

ULONG StrLen(UBYTE *string)
{
    ULONG x = 0L;

    while (string[x++]);
    return(x);
}


II-31/SignalNotification.c

;/* SignalNotification.c.  Compiled with SAS/C 6.56
sc NMINC STRMERGE NOSTKCHK NODEBUG DATA=FAR IGNORE=73 SignalNotification.c
slink from SignalNotification.o to SignalNotification lib lib:amiga.lib
quit

Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <dos/dosasl.h>
#include <dos/notify.h>
#include <dos/rdargs.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>

/* Use pragmas if you've got them */

static UBYTE   *VersTag = "\0$VER: SignalNotification 37.1 (09.07.91)";
struct Library *DOSBase;
struct ExecBase *SysBase;

VOID            main(VOID);

VOID
main(VOID)
{

    struct RDArgs  *readargs;
    LONG            rargs[2];
    struct NotifyRequest *notifyrequest;
    UBYTE          *filename;
    ULONG           signr, signal;

    /* To appease amiga.lib */
    SysBase = (*((struct Library **) 4));

    /* Fail silently if < 37 */
    if (DOSBase = OpenLibrary("dos.library", 37))
    {
        /* See the DOS Autodocs for more information about ReadArgs() */
        if (readargs = ReadArgs("Filename/A", rargs, NULL))
        {
            filename = (UBYTE *) (rargs[0]);

            /* Allocate a NotifyRequest structure */
            if (notifyrequest = AllocMem(sizeof(struct NotifyRequest), MEMF_CLEAR))
            {
                /* And allocate a signalbit */
                if ((signr = AllocSignal(-1L)) != -1)
                {

                    /* Initialize notifcation request */
                    notifyrequest->nr_Name = filename;
                    notifyrequest->nr_Flags = NRF_SEND_SIGNAL | NRF_NOTIFY_INITIAL;
                    /* Signal this task */
                    notifyrequest->nr_stuff.nr_Signal.nr_Task =
                            (struct Task *) FindTask(NULL);
                    /* with this signal bit */
                    notifyrequest->nr_stuff.nr_Signal.nr_SignalNum = signr;

                    if ((StartNotify(notifyrequest)) == DOSTRUE)
                    {
                        /* Loop until Ctrl-C to exit */
                        for (;;)
                        {
                            signal = Wait(1L << signr | SIGBREAKF_CTRL_C);
                            if (signal & (1L << signr))
                                VFPrintf(Output(), "Notification signal!\n", NULL);
                            if (signal & SIGBREAKF_CTRL_C)
                            {
                                EndNotify(notifyrequest);
                                PrintFault(ERROR_BREAK, NULL);
                                break;
                            }
                        }
                    }
                    else
                        PrintFault(ERROR_NOT_IMPLEMENTED, NULL);    /* most logical */

                    FreeSignal(signr);
                }
                else
                    VFPrintf(Output(), "No signal available\n", NULL);
                FreeMem(notifyrequest, sizeof(struct NotifyRequest));
            }
            else
                PrintFault(ERROR_NO_FREE_STORE, NULL);

            FreeArgs(readargs);
        }
        else
            PrintFault(IoErr(), NULL);
        CloseLibrary(DOSBase);
    }
}


II-31/MessageNotification.c

;/* MessageNotification.c - Compiled with SAS/C 6.56:
sc NMINC STRMERGE NOSTKCHK NODEBUG DATA=FAR IGNORE=73 MessageNotification.c
slink from MessageNotification.o to MessageNotification lib lib:amiga.lib
quit

Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/lists.h>
#include <exec/nodes.h>
#include <dos/dos.h>
#include <dos/dosasl.h>
#include <dos/notify.h>
#include <dos/rdargs.h>

#include <clib/alib_protos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>

/* Use pragmas if you've got them */

static UBYTE   *VersTag = "\0$VER: MessageNotification 37.1 (09.07.91)";
struct Library *DOSBase;
struct ExecBase *SysBase;

/* I'll keep track of the NotifyRequests in an Exec list */
struct NotifyNode
{
    struct Node     nn_Node;
    struct NotifyRequest nn_NotifyRequest;
    /* and whatever is useful. Maybe a FileInfoBlock structure... */
};

VOID            main(VOID);

VOID
main(VOID)
{

    struct RDArgs  *readargs;
    LONG            rargs[2];
    struct NotifyRequest *notifyrequest;
    struct NotifyMessage *notifymsg;
    struct List    *notifylist;
    struct MsgPort *notifyport;
    struct NotifyNode *nnode, *nextnode;
    UBYTE         **filenames;
    ULONG           signal, notifysignal;

    /* To appease amiga.lib */
    SysBase = (*((struct Library **) 4));

    /* Fail silently if < 37 */
    if (DOSBase = OpenLibrary("dos.library", 37))
    {

        /* See the DOS Autodocs for more information about ReadArgs() */
        if (readargs = ReadArgs("Filename/A/M", rargs, NULL))
        {
            /* Pointer to array of filenames */
            filenames = (UBYTE **) (rargs[0]);

            if (notifyport = CreateMsgPort())
            {
                if (notifylist = AllocMem(sizeof(struct List), MEMF_CLEAR))
                {
                    /* initialize list */
                    NewList(notifylist);

                    /* The list of filenames is terminated with a NULL */
                    while (*filenames)
                    {
                        /* Get a NotifyNode */
                        if (nnode = AllocMem(sizeof(struct NotifyNode), MEMF_CLEAR))
                        {
                            /*
                             * Use ln_Name to store qualified filename to
                             * monitor. Note that I keep using that pointer to
                             * the command argument line here. In a real life
                             * application you're better off copying the
                             * string.
                             */
                            nnode->nn_Node.ln_Name = (UBYTE *) * filenames++;
                            notifyrequest = &(nnode->nn_NotifyRequest);

                            /* Initialize notifcation request */
                            notifyrequest->nr_Name = nnode->nn_Node.ln_Name;
                            notifyrequest->nr_Flags = NRF_SEND_MESSAGE | NRF_WAIT_REPLY;
                            notifyrequest->nr_stuff.nr_Msg.nr_Port = notifyport;
                            /*
                             * I'm storing the address of the NotifyNode in
                             * nr_UserData. Not going to do anything with it
                             * here, but it would enable me to use the node
                             * immediately when I receive a NotifyMessage.
                             */
                            notifyrequest->nr_UserData = (ULONG) nnode;
                            /*
                             * only add the node to the list if notification is
                             * supported
                             */
                            if ((StartNotify(notifyrequest)) == DOSTRUE)
                            {
                                AddTail(notifylist, (struct Node *) nnode);
                                Printf("Notification on %s\n",
                                       (LONG) nnode->nn_Node.ln_Name);
                            }
                            else
                            {
                                Printf("Notification failed on %s\n",
                                       (LONG) nnode->nn_Node.ln_Name);
                                FreeMem(nnode, sizeof(struct NotifyNode));
                            }
                        }
                        else
                        {
                            PrintFault(ERROR_NO_FREE_STORE, NULL);
                            break;
                        }
                    }

                    /*
                     * Is list empty? If so get out of here. (Macro defined in
                     * <exec/lists.h>)
                     */
                    if (!(IsListEmpty(notifylist)))
                    {
                        /*
                         * No empty, so we've got outstanding NotifyRequests.
                         * Loop until Ctrl-C.
                         */
                        notifysignal = 1L << notifyport->mp_SigBit;
                        for (;;)
                        {
                            /* Wait for message port signals and break */
                            signal = Wait(notifysignal | SIGBREAKF_CTRL_C);

                            if (signal & notifysignal)
                            {
                                while (notifymsg =
                                        (struct NotifyMessage *) GetMsg(notifyport))
                                {
                                    /*
                                     * Here is that node again, stuffed in
                                     * nr_UserData. Can immediately reference
                                     * its data, like comparing filesize with
                                     * stored filesize in node, or remove it
                                     * (after an EndNotify() ofcourse).
                                     */
                                    Printf("Notification message for %s, Node at 0x%lx\n",
                                           (LONG) notifymsg->nm_NReq->nr_Name,
                                      (LONG) notifymsg->nm_NReq->nr_UserData);
                                    ReplyMsg((struct Message *) notifymsg);
                                }
                            }

                            if (signal & SIGBREAKF_CTRL_C)
                            {
                                /*
                                 * Walk down the list, remove all
                                 * NotifyRequests, free all nodes.
                                 */
                                nnode = (struct NotifyNode *) notifylist->lh_Head;
                                while (nextnode =
                                        (struct NotifyNode *) nnode->nn_Node.ln_Succ)
                                {
                                    notifyrequest = &(nnode->nn_NotifyRequest);
                                    Printf("Removing notifcation for %s\n",
                                           (LONG) notifyrequest->nr_Name);
                                    /*
                                     * remove this request. EndNotify() will
                                     * also remove any messages on the message
                                     * port.
                                     */
                                    EndNotify(notifyrequest);
                                    /*
                                     * Not really needed to Remove() the node,
                                     * never going to use this list again
                                     */
                                    Remove((struct Node *) nnode);
                                    FreeMem(nnode, sizeof(struct NotifyNode));
                                    nnode = nextnode;
                                }
                                break;
                            }
                        }
                    }
                    FreeMem(notifylist, sizeof(struct List));
                }
                DeleteMsgPort(notifyport);
            }
            FreeArgs(readargs);
        }
        else
            PrintFault(IoErr(), NULL);
        CloseLibrary(DOSBase);
    }
}


II-37/SetStar.c

;/* SetStar.c.   AmigaMail '*' wildcard example. Pure code if pragmas are used.
;* Compiled with SAS/C 6.56
sc NMINC STRMERGE NOSTKCHK NODEBUG DATA=FAR IGNORE=73 SetStar.c
slink from SetStar.o to SetStar lib lib:amiga.lib; if you don't have pragmas
quit
 *
 */
/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <exec/types.h>
#include <dos/dosextens.h>
#include <dos/rdargs.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>

/*
 * undef PRAGMAS if you don't have them #define PRAGMAS
 */
#ifdef PRAGMAS
#include <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>
#else
struct ExecBase *SysBase;
struct DosLibrary *DOSBase;

#endif

static UBYTE   *VersTag = "\0$VER: SetStar 37.1 (12.07.91)";

VOID            main(VOID);
UWORD           StrLen(UBYTE *);

VOID
main(VOID)
{
#ifdef PRAGMAS
    struct DosLibrary *DOSBase;

#endif

    struct RDArgs  *readargs;
    LONG            rargs[2];
    UWORD           on, off;

#ifndef PRAGMAS
    /* set up SysBase */
    SysBase = (*((struct Library **) 4));
#endif

    /* Fail silently if < 37 */
    if (DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 37))
    {
        rargs[0] = 0;
        rargs[1] = 0;

        /* See the DOS Autodocs for more information about ReadArgs() */
        if (readargs = ReadArgs("ON/S,OFF/S", rargs, NULL))
        {
            on = (UWORD) (rargs[0]);
            off = (UWORD) (rargs[1]);

            /*
             * The RNF_WILDSTAR bit in the rn_Flags field indicates whether the
             * '*' should be treated as wildcard or not.
             *
             * Show current setting if both ON & OFF or specified or neither.
             */
            if (on == off)
            {
                if (DOSBase->dl_Root->rn_Flags & RNF_WILDSTAR)
                    rargs[0] = (LONG) "ON";
                else
                    rargs[0] = (LONG) "OFF";
                VFPrintf(Output(), "Wildstar is %s\n", rargs);
            }
            else
            {
                if (on)
                    DOSBase->dl_Root->rn_Flags |= RNF_WILDSTAR;
                else
                    DOSBase->dl_Root->rn_Flags &= ~RNF_WILDSTAR;
            }
            FreeArgs(readargs);
        }
        else
            PrintFault(IoErr(), NULL);
        CloseLibrary((struct Library *) DOSBase);
    }
}


II-37/Pattern.c

;/* Pattern.c.   AmigaMail pattern matching example.  Compiled with SAS/C 6.56:
sc NMINC STRMERGE NOSTKCHK NODEBUG DATA=FAR IGNORE=73 Pattern.c
slink from Pattern.o to Pattern lib lib:amiga.lib
quit
*/
/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <dos/dosasl.h>
#include <dos/rdargs.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/utility_protos.h>

/* define pragmas if you have them
#define PRAGMAS */
#ifdef PRAGMAS
#include <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>
#include <pragmas/utility_pragmas.h>
#else
struct ExecBase *SysBase;
struct DosLibrary *DOSBase;
struct Library *UtilityBase;
#endif

VOID            main(VOID);
UWORD           StrLen(UBYTE *);

VOID main(VOID)
{
#ifdef PRAGMAS
    struct DosLibrary *DOSBase;
    struct Library *UtilityBase;

#endif

    struct RDArgs  *readargs;
    LONG            rargs[3];
    LONG            vargs[4];
    UBYTE         **strings;
    UBYTE          *pattern, *parsebuffer;
    UWORD           case_sensitive, buffersize;
    LONG            iswild, success;
    COUNT           i;

#ifndef PRAGMAS
    /* set up SysBase */
    SysBase = (*((struct Library **) 4));
#endif

    /* Fail silently if < 37 */
    if (DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 37))
    {
        UtilityBase = DOSBase->dl_UtilityBase;

        /* See the DOS Autodocs for more information about ReadArgs() */
        if (readargs = ReadArgs("PATTERN/A,CASE/S,STRINGS/A/M", rargs, NULL))
        {

            /* The pattern. */
            pattern = (UBYTE *) (rargs[0]);

            /*
             * Case sensitive or not? (default not. Note filename matching
             * should ALWAYS be case insensitive).
             */
            case_sensitive = (UWORD) (rargs[1]);

            /* Pointer to array of strings to match */
            strings = (UBYTE **) (rargs[2]);

            /* Get a buffer big enough to hold all the tokens */
            buffersize = StrLen(pattern) * 3;

            if (parsebuffer = AllocMem(buffersize, MEMF_CLEAR))
            {

                /* Parse the pattern, according to case sensitivity flag */
                if (case_sensitive)
                    iswild = ParsePattern(pattern, parsebuffer, buffersize);
                else
                {
                    /* make pattern uppercase in case of character classes */
                    i = 0;
                    while (pattern[i])
                        pattern[i] = ToUpper(pattern[i++]);
                    iswild = ParsePatternNoCase(pattern, parsebuffer, buffersize);
                }

                /*
                 * -1 if ParsePattern() failed, 0 for no wildcards, 1 for
                 * wildcards. For this I don't care if the supplied pattern had
                 * wildcards or not.
                 */
                if (iswild != -1)
                {
                    /* The array of strings is terminated with a NULL */
                    while (*strings)
                    {

                        /*
                         * MatchPattern() returns 1 for a successful match, 0
                         * for no match
                         */
                        if (case_sensitive)
                            success = MatchPattern(parsebuffer, *strings);
                        else
                            success = MatchPatternNoCase(parsebuffer, *strings);
                        if (success)
                        {
                            vargs[0] = (LONG) * strings;
                            VFPrintf(Output(), "Match: %s\n", vargs);
                        }
                        else
                        {
                            if (IoErr() != 0)
                            {
                                VFPrintf(Output(), "Overflow\n", NULL);
                                break;
                            }
                        }
                        strings++;
                    }
                }
                else
                    PrintFault(ERROR_BAD_TEMPLATE, pattern);
                FreeMem(parsebuffer, buffersize);
            }
            else
                PrintFault(ERROR_NO_FREE_STORE, NULL);
            FreeArgs(readargs);
        }
        else
            PrintFault(IoErr(), NULL);
        CloseLibrary((struct Library *) DOSBase);
    }
}

UWORD StrLen(UBYTE * string)
{
    UBYTE          *length = string + 1;

    while (*string++ != '\0');
    return ((UWORD) (string - length));
}


II-43/Part.c

;/* Part.c - AmigaMail File/Path separator example.  Compiled with SAS/C 6.56.
sc NMINC STRMERGE NOSTKCHK NODEBUG DATA=FAR IGNORE=73 Part.c
slink from Part.o to Part lib lib:amiga.lib ; if you don't have pragmas
quit
 */
/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/rdargs.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>

/* def PRAGMAS if you have them */
/* #define PRAGMAS */
#ifdef PRAGMAS
#include <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>
#else
struct ExecBase *SysBase;
struct Library *DOSBase;

#endif

VOID            main(VOID);
LONG            GetPath(UBYTE * path, UBYTE * buffer, LONG buffersize);
UBYTE          *ItsWild(UBYTE * string);

VOID main(VOID)
{
#ifdef PRAGMAS
    struct Library *DOSBase;

#endif
    struct RDArgs  *readargs;
    LONG            rargs[2];
    LONG            vargs[8];
    UBYTE          *path, *filename;
    UBYTE          *buffer;
    UBYTE          *filepart, *pathpart;
    struct Process *process;
    BPTR            lock;
    APTR            wptr;
    BOOL            error;

#ifndef PRAGMAS
    /* set up SysBase */
    SysBase = (*((struct Library **) 4));
#endif

    /* Fail silently if < 37 */
    if (DOSBase = OpenLibrary("dos.library", 37))
    {

        /*
         * Use a generous 256 byte buffer. Should suffice for everything but
         * extreme cases.
         */
        if (buffer = AllocMem(256, MEMF_CLEAR))
        {

            if (readargs = ReadArgs("PATH/A,FILENAME/A", rargs, NULL))
            {
                path = (UBYTE *) (rargs[0]);
                filename = (UBYTE *) (rargs[1]);

                error = GetPath(path, buffer, 255);
                if (error)
                    PrintFault(error, NULL);

                filepart = FilePart(path);
                pathpart = PathPart(path);

                vargs[0] = (LONG) path;
                vargs[1] = (LONG) filepart;
                vargs[2] = (LONG) pathpart;
                vargs[3] = (LONG) buffer;
                VFPrintf(Output(),
                         "Filename: %s\nFilepart: %s\nPathpart: %s\nPath: %s\n",
                         vargs);

                /* No requesters */
                process = (struct Process *) FindTask(NULL);
                wptr = process->pr_WindowPtr;
                process->pr_WindowPtr = (APTR) - 1L;

                /*
                 * Make sure this name is for real. This will weed out names
                 * like "dh0:/" and non-existent directories. (and also
                 * complain about non-mounted volumes.) It is tempting to look
                 * for trailing slashes and remove them but you shouldn't. You
                 * might misinterpret the users intention. Better to generate a
                 * warning and prompt for new input.
                 */
                if (lock = Lock(buffer, SHARED_LOCK))
                    UnLock(lock);
                else
                    PrintFault(IoErr(), buffer);

                /* Reset windowpointer */
                process->pr_WindowPtr = wptr;

                /*
                 * Normally we should respect the test for an invalid path. To
                 * show the results however, we blunder along...
                 *
                 * Add the filename to the path.
                 */
                if (AddPart(buffer, filename, 255))
                    vargs[0] = (LONG) buffer;
                else
                    vargs[0] = (LONG) "OVERFLOW";

                VFPrintf(Output(), "\nNew path: %s\n", vargs);

                FreeArgs(readargs);
            }
            else
                PrintFault(IoErr(), NULL);
            FreeMem(buffer, 256);
        }
        CloseLibrary(DOSBase);
    }
}

/*
 * Standalone function to isolate a path and copy it into a supplied buffer.
 * Does not test if the path is valid. Returns an error in case of buffer
 * overflow.
 */
LONG
GetPath(UBYTE * path, UBYTE * buffer, LONG buffersize)
{
    UBYTE          *pathpart, *filepart;
    UBYTE          *tmp1, *tmp2;
    BPTR            lock;
    struct FileInfoBlock *fib;
    LONG            error = 0;

    /* Open own copy of dos.library if pragmas are used so it's standalone */
#ifdef PRAGMAS
    struct Library *DOSBase;

    if (!(DOSBase = OpenLibrary("dos.library", 36)))
        return (1);
#endif

    /*
     * If there seems to be no path, the pathpart will point to the filepart
     * too, so we need to check for that.
     */
    filepart = FilePart(path);
    pathpart = PathPart(path);

    /*
     * This also handles cases where there is only a volume/device name, only a
     * directory name or a combo of those.
     */
    if (pathpart == path)
    {

        /*
         * There seems to be only one component. Copy it if it is not wild.
         * Caller will have to check whether if it exists and if it is a file
         * or directory.
         */
        if (!(ItsWild(pathpart)))
            pathpart = NULL;
    }

    if (pathpart != path)
    {

        /*
         * If pathpart equals filepart (pointer wise) then there is only one
         * component (possible preceeded by a volume name).
         */
        if (pathpart == filepart)
        {
            if (!(ItsWild(pathpart)))
                pathpart = NULL;
        }
        else
        {

            /*
             * Try to lock it to determine if the last component is a
             * directory.
             */
            if (lock = Lock(path, SHARED_LOCK))
            {
                if (fib = AllocMem(sizeof(struct FileInfoBlock), MEMF_CLEAR))
                {
                    if ((Examine(lock, fib)) == DOSTRUE)
                    {
                        /* Hey it's a directory after all */
                        if (fib->fib_DirEntryType > 0)
                            pathpart = NULL;
                    }
                    FreeMem(fib, sizeof(struct FileInfoBlock));
                }
                UnLock(lock);
            }           /* else treat it as a filename */
        }

        /* Copy the pathpart in the buffer */
        tmp1 = buffer;
        tmp2 = path;
        while ((*tmp1++ = *tmp2++) && (tmp2 != pathpart))
        {
            if (tmp1 == (buffer + buffersize))
            {
                error = ERROR_NO_FREE_STORE;
                break;
            }
        }
        *tmp1 = '\0';  /* NULL terminate. */
    }

#ifdef PRAGMAS
    CloseLibrary(DOSBase);
#endif
    return (error);
}

/* Simple test whether a filename contains wildcards or not */
UBYTE          *
ItsWild(UBYTE * string)
{
    static UBYTE   *special = "#?*%([|";
    UBYTE          *tmp = string;
    COUNT           i;

    do
    {
        for (i = 0; special[i] != '\0'; i++)
        {
            if (*tmp == special[i])
                return (tmp);
        }
        tmp++;
    } while (*tmp);

    return (NULL);
}


II-43/Split.c

;/* Split.c - AmigaMail SplitName() example.  Compiled with SAS/C 6.56.
sc NMINC STRMERGE NOSTKCHK NODEBUG DATA=FAR IGNORE=73 Split.c
slink from Split.o to Split lib lib:amiga.lib ; if you don't have pragmas
quit
* Tuesday, 16-Jul-91 12:15:49, Ewout
*
*
*/
/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <exec/memory.h>
#include <dos/dosextens.h>
#include <dos/rdargs.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>

/* def PRAGMAS if you have them */
/* #define PRAGMAS */
#ifdef PRAGMAS
#include <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>
#else
struct ExecBase *SysBase;
struct DosLibrary *DOSBase;

#endif

#define BUFFERSIZE      128

VOID            main(VOID);

VOID
main(VOID)
{
#ifdef PRAGMAS
    struct DosLibrary *DOSBase;

#endif
    struct RDArgs  *readargs;
    LONG            rargs[2];
    UBYTE          *filename, *buffer;
    ULONG           buffersize;
    WORD            position = 0;
    LONG            vargs[4];

#ifndef PRAGMAS
    /* set up SysBase */
    SysBase = (*((struct Library **) 4));
#endif

    /* Fail silently if < 37 */
    if (DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 37))
    {

        /* See the DOS Autodocs for more information about ReadArgs() */
        if (readargs = ReadArgs("FILE/A,BUFFERSIZE/A/N", rargs, NULL))
        {
            filename = (UBYTE *) rargs[0];
            buffersize = *((LONG *) rargs[1]);
            if (buffersize < 1 || buffersize > 4096)
                buffersize = BUFFERSIZE;

            if (buffer = AllocMem(buffersize, MEMF_CLEAR))
            {
                position = SplitName(filename, ':', buffer, position, buffersize);

                vargs[0] = position;
                vargs[1] = (LONG) buffer;
                VFPrintf(Output(), "Devicename: position: %ld Buffer: %s\n", vargs);

                if (position == -1)
                    position = 0;

                do
                {
                    position =
                        SplitName(filename, '/', buffer, position, buffersize);
                    vargs[0] = position;
                    vargs[1] = (LONG) buffer;
                    VFPrintf(Output(),
                             "Path component: position: %ld Buffer: %s\n",
                             vargs);
                } while (position != -1);
                FreeMem(buffer, buffersize);
            }
            FreeArgs(readargs);

        }
        else
            PrintFault(IoErr(), NULL);
        CloseLibrary((struct Library *) DOSBase);
    }
}


II-49/ListDir.c

;/* ListDir.c - Amiga Mail simple ExAll() example.
sc NMINC STRMERGE NOSTKCHK NODEBUG DATA=FAR IGNORE=73 ListDir.c
slink from ListDir.o to ListDir lib lib:amiga.lib ;if you don't have pragmas
quit
 *
 * Pure code if pragmas are used.
 * Tuesday, 16-Jul-91 16:21:14, Ewout
 *
 * Compiled with SAS/C 6.56
 */
/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <exec/memory.h>
#include <dos/dosextens.h>
#include <dos/rdargs.h>
#include <dos/exall.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>

/* undef PRAGMAS if you don't have them */
#define PRAGMAS
#undef PRAGMAS
#ifdef PRAGMAS
#include <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>
#else
struct ExecBase *SysBase;
struct DosLibrary *DOSBase;

#endif

/* Buffersize to receive filenames in */
#define BUFFERSIZE 512

VOID            main(VOID);

VOID
main(VOID)
{
#ifdef PRAGMAS
    struct DosLibrary *DOSBase;

#endif
    struct RDArgs  *readargs;
    LONG            rargs[2];
    struct ExAllControl *excontrol;
    struct ExAllData *ead, *buffer;
    UBYTE          *source;
    BPTR            sourcelock;
    BOOL            exmore;
    LONG            error;

#ifndef PRAGMAS
    /* set up SysBase */
    SysBase = (*((struct Library **) 4));
#endif

    /* Fail silently if < 37 */
    if (DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 37))
    {

        if (readargs = ReadArgs("DIRECTORY/A", rargs, NULL))
        {

            source = (UBYTE *) rargs[0];

            if (buffer = AllocMem(BUFFERSIZE, MEMF_CLEAR))
            {

                if (sourcelock = Lock(source, SHARED_LOCK))
                {
                    if (excontrol = AllocDosObject(DOS_EXALLCONTROL, NULL))
                    {
                        excontrol->eac_LastKey = 0;

                        do
                        {

                            exmore = ExAll(sourcelock,
                                           buffer,
                                           BUFFERSIZE,
                                           ED_NAME,
                                           excontrol);
                            error = IoErr();
                            if ((exmore == NULL &&
                                (error != ERROR_NO_MORE_ENTRIES)))
                                break;

                            if (excontrol->eac_Entries == 0)
                                continue;

                            ead = buffer;
                            do
                            {

                                /* Check for CTRL-C */
                                if (SetSignal(0L, SIGBREAKF_CTRL_C) &
                                        SIGBREAKF_CTRL_C)
                                {
                                    error = ERROR_BREAK;
                                    exmore = FALSE;
                                    break;
                                }

                                rargs[0] = (LONG) ead->ed_Name;
                                VFPrintf(Output(), "%s\n", rargs);

                                ead = ead->ed_Next;
                            } while (ead);
                        } while (exmore);

                        if (error != ERROR_NO_MORE_ENTRIES)
                            PrintFault(error, NULL);

                        FreeDosObject(DOS_EXALLCONTROL, excontrol);
                    }
                    else
                        PrintFault(ERROR_NO_FREE_STORE, NULL);

                    UnLock(sourcelock);
                }
                else
                    PrintFault(IoErr(), source);

                FreeMem(buffer, BUFFERSIZE);
            }
            else
                PrintFault(ERROR_NO_FREE_STORE, NULL);
            FreeArgs(readargs);

        }
        else
            PrintFault(IoErr(), NULL);
        CloseLibrary((struct Library *) DOSBase);
    }
}


II-49/ListDir2.c

;/* ListDir2.c   AmigaMail seconds ExAll() example.
sc NMINC STRMERGE NOSTKCHK NODEBUG DATA=FAR IGNORE=73 ListDir2.c
slink from ListDir2.o to ListDir2 lib lib:amiga.lib ;if you don't have pragmas
quit
 *
 * Pure code if pragmas are used.
 * Tuesday, 16-Jul-91 16:21:14, Ewout
 *
 * Compiled with SAS/C 6.56
 */

/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <exec/memory.h>
#include <dos/dosextens.h>
#include <dos/rdargs.h>
#include <dos/exall.h>
#include <utility/hooks.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/utility_protos.h>

/* undef PRAGMAS if you don't have them */
#define PRAGMAS
#undef PRAGMAS
#ifdef PRAGMAS
#include <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>
#include <pragmas/utility_pragmas.h>
#else
struct ExecBase *SysBase;
struct DosLibrary *DOSBase;
struct Library *UtilityBase;

#endif

/* Buffersize to receive filenames in */
#define BUFFERSIZE 512

VOID            main(VOID);
UWORD           StrLen(UBYTE *);

/* SAS/C specific, use asm stub otherwise */
#define ASM __asm
#define REG(x) register __## x
BOOL ASM  ExAllHook(REG(a0) struct Hook * hook,
                    REG(a1) struct ExAllData * data,
                    REG(a2) LONG * datatype);

VOID
main(VOID)
{
#ifdef PRAGMAS
    struct DosLibrary *DOSBase;
    struct Library *UtilityBase;

#endif
    struct RDArgs  *readargs;
    LONG            rargs[4];
    struct ExAllControl *excontrol;
    struct ExAllData *ead, *buffer;
    struct Hook     exallhook;
    UBYTE          *pattern, *parsebuffer;
    BPTR            sourcelock;
    BOOL            exmore;
    COUNT           i;
    LONG            parselength, type, error;

#ifndef PRAGMAS
    /* set up SysBase */
    SysBase = (*((struct Library **) 4));
#endif

    /* Fail silently if < 37 */
    if (DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 37))
    {
        UtilityBase = DOSBase->dl_UtilityBase;

        rargs[1] = 0L;
        rargs[2] = 0L;
        if (readargs = ReadArgs("PATTERN/A,DIRS/S,FILES/S", rargs, NULL))
        {

            pattern = (UBYTE *) rargs[0];

            /*
             * If DIRS or files not specified or both, accept
             * both files and directories
             */
            if (rargs[1] == rargs[2])
                type = 0;
            else
            {
                /* Accept only directories */
                if (rargs[1])
                    type = 1;
                /* Accept only files */
                else
                    type = -1;
            }

            parselength = StrLen(pattern) * 3;
            if (parsebuffer = AllocMem(parselength, MEMF_CLEAR))
            {

                /* Make pattern uppercase for possible character classes */
                i = 0;
                while (pattern[i])
                    pattern[i] = ToUpper(pattern[i++]);

                if ((ParsePatternNoCase(pattern, parsebuffer, parselength)) != -1)
                {

                    if (buffer = AllocMem(BUFFERSIZE, MEMF_CLEAR))
                    {

                        sourcelock =
                                ((struct Process *) FindTask(NULL))->pr_CurrentDir;

                        if (excontrol = AllocDosObject(DOS_EXALLCONTROL, NULL))
                        {

                            exallhook.h_Entry = (ULONG (*)())ExAllHook;
                            exallhook.h_Data = (VOID *) type;

                            excontrol->eac_MatchString = parsebuffer;
                            excontrol->eac_MatchFunc = &exallhook;

                            do
                            {

                                exmore = ExAll(sourcelock,
                                               buffer,
                                               BUFFERSIZE,
                                               ED_TYPE,
                                               excontrol);
                                error = IoErr();
                                if ((exmore == NULL &&
                                    (error != ERROR_NO_MORE_ENTRIES)))
                                    break;

                                if (excontrol->eac_Entries == 0)
                                    continue;

                                ead = buffer;
                                do
                                {

                                    /* Check for CTRL-C */
                                    if (SetSignal(0L, SIGBREAKF_CTRL_C) &
                                        SIGBREAKF_CTRL_C)
                                    {
                                        error = ERROR_BREAK;
                                        exmore = FALSE;
                                        break;
                                    }

                                    rargs[0] = (LONG) ead->ed_Name;
                                    VFPrintf(Output(), "%s\n", rargs);

                                    ead = ead->ed_Next;
                                } while (ead);
                            } while (exmore);

                            if (error != ERROR_NO_MORE_ENTRIES)
                                PrintFault(error, NULL);

                            FreeDosObject(DOS_EXALLCONTROL, excontrol);
                        }
                        else
                            PrintFault(ERROR_NO_FREE_STORE, NULL);

                        FreeMem(buffer, BUFFERSIZE);
                    }
                    else
                        PrintFault(ERROR_NO_FREE_STORE, NULL);
                }
                else
                    PrintFault(ERROR_BAD_TEMPLATE, NULL);
                FreeMem(parsebuffer, parselength);
            }
            else
                PrintFault(ERROR_NO_FREE_STORE, NULL);
            FreeArgs(readargs);

        }
        else
            PrintFault(IoErr(), NULL);
        CloseLibrary((struct Library *) DOSBase);
    }
}

BOOL ASM
ExAllHook(REG(a0) struct Hook * hook,
          REG(a1) struct ExAllData * data,
          REG(a2) LONG * datatype)
{
    LONG            neededfiletype = (LONG) hook->h_Data;
    BOOL            success = TRUE;

    if (neededfiletype != 0)
    {
        if (data->ed_Type > 0 && neededfiletype < 0)
            success = FALSE;
        if (data->ed_Type < 0 && neededfiletype > 0)
            success = FALSE;
    }
    return (success);
}

UWORD
StrLen(UBYTE * string)
{
    UBYTE          *length = string + 1;

    while (*string++ != '\0');
    return ((UWORD) (string - length));
}


II-49/Find.c

;/* Find.c - Amiga Mail ExAll() example.
sc NMINC STRMERGE NOSTKCHK NODEBUG DATA=FAR IGNORE=73 Find.c
slink from Find.o to Find lib lib:amiga.lib; if you don't have pragmas
quit
 *
 * Pure code if pragmas are used.
 * Tuesday, 16-Jul-91 16:21:14, Ewout
 *
 * Compiled with SAS/C 6.56
 */
/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <exec/memory.h>
#include <dos/dosextens.h>
#include <dos/rdargs.h>
#include <dos/exall.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/utility_protos.h>

/* undef PRAGMAS if you don't have them */
/* #define PRAGMAS */
#undef PRAGMAS
#ifdef PRAGMAS
#include <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>
#include <pragmas/utility_pragmas.h>
#else
struct ExecBase *SysBase;
struct DosLibrary *DOSBase;
struct Library *UtilityBase;

#endif

/* ExAll buffersize to receive data in */
#define BUFFERSIZE 512
/* Default buffersize for hold fully qualified filenames */
#define NAMEBUFFERSIZE 512

/* Used to pass data around to functions */
struct FindControl
{
  struct DosLibrary *fc_DOSBase;
  UBYTE          *fc_Parsebuffer;       /* Buffer which contains the parsed pattern */
  ULONG           fc_Parselength;       /* The length of this buffer */
  UBYTE          *fc_Namebuffer;        /* Buffer to hold the filename */
  ULONG           fc_Namelength;        /* The length of that buffer */
  BOOL            fc_Files;  /* BOOLEAN which tells if we should only look for files */
  BOOL            fc_Dirs;   /* BOOLEAN which tells if we should only look for dirs */
  BOOL            fc_All;    /* ALL keyword? */
};

static UBYTE   *VersTag = "\0$VER: Find 37.1 (16.07.91)";

LONG            main(VOID);
LONG            ScanDirectory(struct FindControl *, UBYTE *);
BOOL            IsAssign(struct FindControl *, UBYTE *);
LONG            MultiScanDirectory(struct FindControl *, UBYTE *);
UWORD           StrLen(UBYTE *);

LONG
main(VOID)
{
#ifdef PRAGMAS
  struct DosLibrary *DOSBase;
  struct Library *UtilityBase;

#endif
  struct RDArgs  *readargs;
  LONG            rargs[6];
  struct FindControl *fc;
  UBYTE          *pattern, **directories;
  struct Process *process;
  APTR            windowptr;
  COUNT           i;
  LONG            rc = 0, error = 0, fatalerror = 0;

#ifndef PRAGMAS
  /* set up SysBase */
  SysBase = (*((struct Library **) 4));
#endif

  /* Fail silently if < 37 */
  if (DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 37))
  {
    UtilityBase = DOSBase->dl_UtilityBase;

    rargs[0] = 0L;
    rargs[1] = 0L;
    rargs[2] = 0L;
    rargs[3] = 0L;
    rargs[4] = 0L;
    rargs[5] = 0L;

    if (readargs =
        ReadArgs("PATTERN/A,DIRECTORY/A/M,FILES/S,DIRS/S,ALL/S,BUFFER/K/N",
                 rargs,
                 NULL))
    {

      if (fc = AllocMem(sizeof(struct FindControl), MEMF_CLEAR))
      {

#ifdef PRAGMAS
        fc->fc_DOSBase = DOSBase;
#endif

        pattern = (UBYTE *) rargs[0];

        fc->fc_Parselength = StrLen(pattern) * 3;
        if (fc->fc_Parsebuffer = AllocMem(fc->fc_Parselength, MEMF_CLEAR))
        {

          /* Make pattern uppercase for possible character classes */
          i = 0;
          while (pattern[i])
            pattern[i] = ToUpper(pattern[i++]);

          if ((ParsePatternNoCase(pattern,
                                  fc->fc_Parsebuffer,
                                  fc->fc_Parselength)) != -1)
          {

            directories = (UBYTE **) rargs[1];

            fc->fc_Files = (BOOL) rargs[2];
            fc->fc_Dirs = (BOOL) rargs[3];
            fc->fc_All = (BOOL) rargs[4];

            /*
             * Both set or cleared, clear both anyway. Easier checking later on.
             */
            if (fc->fc_Files == fc->fc_Dirs)
              fc->fc_Files = fc->fc_Dirs = FALSE;

            if (rargs[5])
              fc->fc_Namelength = *((LONG *) rargs[5]);

            if (fc->fc_Namelength < NAMEBUFFERSIZE || fc->fc_Namelength > 4096)
              fc->fc_Namelength = NAMEBUFFERSIZE;

            if (fc->fc_Namebuffer = AllocMem(fc->fc_Namelength, MEMF_CLEAR))
            {
              process = (struct Process *) FindTask(NULL);
              windowptr = process->pr_WindowPtr;
              process->pr_WindowPtr = (APTR) - 1L;

              while (*directories)
              {

                /*
                 * Check if this is a standalone assign which appears in the assign
                 * list?
                 */
                if (IsAssign(fc, *directories))
                  error = MultiScanDirectory(fc, *directories++);
                else
                  error = ScanDirectory(fc, *directories++);

                if (error != 0)
                  break;
              }

              process->pr_WindowPtr = windowptr;

              FreeMem(fc->fc_Namebuffer, fc->fc_Namelength);
            }
            else
              fatalerror = ERROR_NO_FREE_STORE;
          }
          else
            fatalerror = ERROR_BAD_TEMPLATE;

          FreeMem(fc->fc_Parsebuffer, fc->fc_Parselength);
        }
        else
          fatalerror = ERROR_NO_FREE_STORE;
        FreeMem(fc, sizeof(struct FindControl));
      }
      else
        fatalerror = ERROR_NO_FREE_STORE;

      FreeArgs(readargs);

    }
    else
      fatalerror = IoErr();

    /*
     * Error handling: To be informative, errors are shown while scanning, so the
     * file name which caused the error can be displayed. Other errors are shown
     * here. Errors which occured in the main loop are considered fatal, others
     * (except BREAK) just error.
     */

    if (fatalerror)
    {
      error = fatalerror;
      PrintFault(fatalerror, NULL);
    }

    SetIoErr(error);
    if (error != 0)
    {
      if (fatalerror)
        rc = RETURN_FAIL;
      else if (error == ERROR_BREAK)
        rc = RETURN_WARN;
      else
        rc = RETURN_ERROR;
    }

    CloseLibrary((struct Library *) DOSBase);
  }
  else
    rc = RETURN_FAIL;
  return (rc);
}

LONG
ScanDirectory(struct FindControl * fc, UBYTE * source)
{
#ifdef PRAGMAS
  struct DosLibrary *DOSBase = fc->fc_DOSBase;

#endif
  LONG            vargs[1];
  struct ExAllControl *excontrol;
  struct ExAllData *ead, *buffer;
  BPTR            sourcelock, namelock, olddirlock;
  BOOL            exmore;
  LONG            error;

  /*
   * Because this function may be recursively, get a fresh buffer per function call.
   */
  if (buffer = AllocMem(BUFFERSIZE, MEMF_CLEAR))
  {

    /* Get a lock on the start directory and make it the current directory */
    if (sourcelock = Lock(source, SHARED_LOCK))
    {
      olddirlock = CurrentDir(sourcelock);

      if (excontrol = AllocDosObject(DOS_EXALLCONTROL, NULL))
      {

        do
        {
          /* Get both file name and type to support FILES/DIRS kewords */
          exmore = ExAll(sourcelock, buffer, BUFFERSIZE, ED_TYPE, excontrol);
          error = IoErr();
          if ((exmore == NULL && (error != ERROR_NO_MORE_ENTRIES)))
          {
            PrintFault(error, source);
            break;
          }
          if (excontrol->eac_Entries == 0)
            continue;

          ead = buffer;
          do
          {

            /* Check for CTRL-C */
            if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
            {
              error = ERROR_BREAK;
              PrintFault(error, NULL);
              exmore = FALSE;
              break;
            }

            /*
             * Check if this one matches. If it does see if it is of the right type.
             */
            if (MatchPatternNoCase(fc->fc_Parsebuffer, ead->ed_Name))
            {
              if ((ead->ed_Type < 0 && fc->fc_Dirs == FALSE)
                  || (ead->ed_Type > 0 && fc->fc_Files == FALSE))
              {
                /* It is. Lock it and get the fully qualified file name */
                if (namelock = Lock(ead->ed_Name, SHARED_LOCK))
                {
                  if ((NameFromLock(namelock,
                                    fc->fc_Namebuffer,
                                    fc->fc_Namelength)) == DOSTRUE)
                  {
                    vargs[0] = (LONG) fc->fc_Namebuffer;
                    VFPrintf(Output(), "%s\n", vargs);
                  }
                  else
                  {
                    error = IoErr();
                    PrintFault(error, ead->ed_Name);
                  }
                  UnLock(namelock);
                }
                else
                {
                  error = IoErr();
                  PrintFault(error, ead->ed_Name);
                }
              }
            }

            /*
             * If the ALL keyword is used and this is a directory, step in it by
             * calling this function recursively.
             */
            if (ead->ed_Type > 0 && fc->fc_All)
            {
              error = ScanDirectory(fc, ead->ed_Name);
              if (error != 0)
              {
                exmore = FALSE;
                break;
              }
            }
            ead = ead->ed_Next;
          } while (ead);
        } while (exmore);

        FreeDosObject(DOS_EXALLCONTROL, excontrol);

      }
      else
        error = ERROR_NO_FREE_STORE;

      CurrentDir(olddirlock);
      UnLock(sourcelock);
    }
    else
    {
      error = IoErr();
      PrintFault(error, source);
    }
    FreeMem(buffer, BUFFERSIZE);
  }
  else
    error = ERROR_NO_FREE_STORE;

  if (error == ERROR_NO_MORE_ENTRIES)
    error = 0;
  else if (error == ERROR_NO_FREE_STORE)
    PrintFault(error, NULL);

  return (error);
}

BOOL
IsAssign(struct FindControl * fc, UBYTE * name)
{
#ifdef PRAGMAS
  struct DosLibrary *DOSBase = fc->fc_DOSBase;
  struct Library *UtilityBase = DOSBase->dl_UtilityBase;

#endif
  struct DosList *doslist;
  UBYTE          *assignname;
  UCOUNT          assignlength;
  LONG            position;
  BOOL            result = FALSE;

  /* First lets check if this resembles a devicename. */
  position = SplitName(name, ':', fc->fc_Namebuffer, 0, fc->fc_Namelength);

  if (position != -1)
  {
    /* Hmmm. */
    if (name[position] == '\0')
    {

      /*
       * I guess it does. Lets see if we can find it in the assign list. Keep the
       * DoSList locked as briefly as possible. This shouldn't take long.
       */
      if (doslist = AttemptLockDosList(LDF_ASSIGNS | LDF_READ))
      {
        while (doslist = NextDosEntry(doslist, LDF_ASSIGNS))
        {

          /* It's a BPTR */
          assignname = (UBYTE *) BADDR(doslist->dol_Name);
          assignlength = assignname[0];

          if ((Strnicmp(assignname + 1, fc->fc_Namebuffer, assignlength)) == 0)
          {
            /* Yup, it is. */
            result = TRUE;
            break;
          }
        }
        UnLockDosList(LDF_ASSIGNS | LDF_READ);
      }    /* Can't lock DosList, don't bother */
    }
  }
  return (result);
}

LONG
MultiScanDirectory(struct FindControl * fc, UBYTE * source)
{
#ifdef PRAGMAS
  struct DosLibrary *DOSBase = fc->fc_DOSBase;

#endif
  struct DevProc *cproc = NULL;
  struct MsgPort *filesystemtask;
  LONG            error;

  filesystemtask = GetFileSysTask();

  do
  {
    /* Find handler */
    if (cproc = GetDeviceProc(source, cproc))
    {
      SetFileSysTask(cproc->dvp_Port);
      if ((NameFromLock(cproc->dvp_Lock,
           fc->fc_Namebuffer,
           fc->fc_Namelength)) == DOSTRUE)
      {
        error = ScanDirectory(fc, fc->fc_Namebuffer);
      }
      else
      {
        error = IoErr();
        PrintFault(error, source);
      }

      if (error != 0)
        break;
    }
    else
    {
      error = IoErr();
      PrintFault(error, source);
    }

    /* Handle multi-assign */
  } while (cproc && (cproc->dvp_Flags & DVPF_ASSIGN));

  SetFileSysTask(filesystemtask);
  if (cproc)
    FreeDeviceProc(cproc);

  return (error);
}

UWORD
StrLen(UBYTE * string)
{
  UBYTE          *length = string + 1;

  while (*string++ != '\0');
  return ((UWORD) (string - length));
}


II-49/ListPattern.c

;/* ListPattern.c - AmigaMail MatchFirst()/MatchNext() example.
sc NMINC STRMERGE NOSTKCHK NODEBUG DATA=FAR IGNORE=73 ListPattern.c
slink from ListPattern.o to ListPattern lib lib:amiga.lib ;if you don't have pragmas
quit
 */
/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <exec/memory.h>
#include <dos/dosextens.h>
#include <dos/rdargs.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>

/* undef PRAGMAS if you don't have them */
#define PRAGMAS
#undef PRAGMAS
#ifdef PRAGMAS
#include <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>
#else

struct ExecBase *SysBase;
struct DosLibrary *DOSBase;
#endif

VOID            main(VOID);
UWORD           StrLen(UBYTE *);

VOID
main(VOID)
{

#ifdef PRAGMAS
    struct DosLibrary *DOSBase;
#endif

    struct RDArgs  *readargs;
    LONG            rargs[1];
    LONG            vargs[4];
    UBYTE          *pattern;
    struct AnchorPath *anchorpath;
    LONG            error;

#ifndef PRAGMAS
    /* set up SysBase */
    SysBase = (*((struct Library **) 4));
#endif

    /* Fail silently if < 37 */
    if (DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 37))
    {
        /* See the DOS Autodocs for more information about ReadArgs() */
        if (readargs = ReadArgs("PATTERN/A", rargs, NULL))
        {
            pattern = (UBYTE *) rargs[0];
            if (anchorpath = AllocMem(sizeof(struct AnchorPath) + 512, MEMF_CLEAR))
            {
                anchorpath->ap_Strlen = 512;
                anchorpath->ap_BreakBits = SIGBREAKF_CTRL_C;

                if ((error = MatchFirst(pattern, anchorpath)) == 0)
                {
                    do
                    {
                        vargs[0] = (LONG) anchorpath->ap_Buf;
                        VFPrintf(Output(), "%s\n", vargs);
                    } while ((error = MatchNext(anchorpath)) == 0);
                }

                MatchEnd(anchorpath);

                if (error != ERROR_NO_MORE_ENTRIES)
                    PrintFault(error, NULL);

                FreeMem(anchorpath, sizeof(struct AnchorPath) + 512);
            }
            FreeArgs(readargs);
        }
        else
            PrintFault(IoErr(), NULL);
        CloseLibrary((struct Library *) DOSBase);
    }
}


II-49/DirComp.c

;/* DirComp.c - AmigaMail Directory Compare example using MatchFirst()/Next().
sc NMINC STRMERGE NOSTKCHK NODEBUG DATA=FAR IGNORE=73 DirComp.c
slink from DirComp.o to DirComp lib lib:amiga.lib ; if you don't have pragmas
quit
 *
 * Pure code if pragmas are used.
 * Monday, 15-Jul-91 16:07:31, Ewout
 *
 * Compiled with SAS/C 6.56
 */
/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <exec/memory.h>
#include <dos/dosextens.h>
#include <dos/rdargs.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>

/* undef PRAGMAS if you don't have them */
#undef PRAGMAS
#ifdef PRAGMAS
#include <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>
#else
struct ExecBase *SysBase;
struct DosLibrary *DOSBase;

#endif

/* Default size of buffer to build full targetpaths in */
#define BUFFERSIZE 256

static UBYTE   *VersTag = "\0$VER: DirComp 37.1 (15.07.91)";

LONG            main(VOID);
LONG            GetPath(UBYTE * path, UBYTE * buffer, LONG buffersize);
UBYTE          *ItsWild(UBYTE * string);
UWORD           StrLen(UBYTE *);

LONG
main(VOID)
{
#ifdef PRAGMAS
  struct DosLibrary *DOSBase;

#endif
  struct RDArgs  *readargs;
  LONG            rargs[5], vargs[5];
  UBYTE          *source, *target;
  ULONG           buffersize = 0;
  UBYTE          *sourcedir, *targetdir;
  UBYTE          *textbuffer, *tmp, *tmp1, *tmp2;
  struct AnchorPath *anchorpath;
  struct FileInfoBlock *fib, *targetfib;
  struct Process *process;
  APTR            wptr;
  BPTR            dirlock, filelock;
  BOOL            checkdatestamp, all;
  LONG            date, error, rc = 0;

#ifndef PRAGMAS
  /* set up SysBase */
  SysBase = (*((struct Library **) 4));
#endif

  /* Fail silently if < 37 */
  if (DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 37))
  {
    rargs[0] = 0L;
    rargs[1] = 0L;
    rargs[2] = 0L;
    rargs[3] = 0L;
    rargs[4] = 0L;

    if (readargs = ReadArgs("SOURCE/A,TARGET/A,DATE/S,ALL/S,BUFFER/K/N", rargs, NULL))
    {

      source = (UBYTE *) rargs[0];
      target = (UBYTE *) rargs[1];
      checkdatestamp = (BOOL) rargs[2];
      all = (BOOL) rargs[3];

      if (!(sourcedir = AllocMem(StrLen(source) + 129, MEMF_CLEAR)))
        error = ERROR_NO_FREE_STORE;
      else
      {
        /* 128 bytes to print informative text */
        textbuffer = sourcedir + StrLen(source) + 1;

        /* use user specified buffersize if indicated */
        if (rargs[4])
          buffersize = *((LONG *) rargs[4]);
        if (buffersize < BUFFERSIZE || buffersize > 4096)
          buffersize = BUFFERSIZE;

        if (!(targetdir = AllocMem(buffersize, MEMF_CLEAR)))
          error = ERROR_NO_FREE_STORE;
        else
        {
          if (!(targetfib = AllocDosObject(DOS_FIB, NULL)))
            error = ERROR_NO_FREE_STORE;
          else
          {

            /*
             * Check if source and target are valid.
             *
             * Separate source path from pattern (if any). Use the source path figure
             * out what to append to the target.
             */

            /* No requesters */
            process = (struct Process *) FindTask(NULL);
            wptr = process->pr_WindowPtr;
            process->pr_WindowPtr = (APTR) - 1L;

            if ((error = GetPath(source, sourcedir, StrLen(source) + 1) == 0))
            {
              if (!(dirlock = Lock(sourcedir, SHARED_LOCK)))
                error = IoErr();
              else
              {
                UnLock(dirlock);
                if (!(dirlock = Lock(target, SHARED_LOCK)))
                  error = IoErr();
                else
                {
                  UnLock(dirlock);

                  if (anchorpath = AllocMem(sizeof(struct AnchorPath) + buffersize,
                                            MEMF_CLEAR))
                  {
                    anchorpath->ap_Strlen = buffersize;

                    /* Allow to break on CTRL-C */
                    anchorpath->ap_BreakBits = SIGBREAKF_CTRL_C;

                    if ((error = MatchFirst(source, anchorpath)) == 0)
                    {

                      do
                      {
                        fib = &(anchorpath->ap_Info);

                        /*
                         * APF_DIDDIR indicates that we used returned from a
                         * directory. In that case we clear both APF_DIDDIR and
                         * APF_DODIR, so we can start afresh with the next one.
                         */

                        if (anchorpath->ap_Flags & APF_DIDDIR)
                          anchorpath->ap_Flags &= ~(APF_DODIR | APF_DIDDIR);
                        else
                        {

                          /*
                           * Make a filename for the target directory. First copy
                           * targetname into buffer.
                           */
                          targetdir[0] = '\0';
                          tmp = targetdir;
                          tmp1 = target;
                          while (*tmp++ = *tmp1++);

                          /* Skip sourcename in ap_Buf */
                          tmp1 = sourcedir;
                          tmp2 = anchorpath->ap_Buf;
                          while (*tmp1++ == *tmp2++);
                          /* Skip back 1 if not after a separator */
                          if (*(tmp2 - 1) != '/')
                            tmp2--;

                          /*
                           * We hit the source itself, don't compare it, but enter
                           * it.
                           */
                          if (*tmp2 == 0)
                          {
                            anchorpath->ap_Flags |= APF_DODIR;
                            continue;
                          }

                          /* Build it */
                          if (AddPart(targetdir, tmp2, buffersize - 1))
                            vargs[0] = (LONG) targetdir;
                          else
                          {
                            PrintFault(ERROR_NO_FREE_STORE, NULL);
                            break;
                          }

                          /* Lock it and check it out */
                          if (filelock = Lock(targetdir, SHARED_LOCK))
                          {
                            if ((Examine(filelock, targetfib)) == DOSTRUE)
                            {
                              textbuffer[0] = '\0';

                              /*
                               * To get nice output without work I use AddPart() to
                               * add differences to the textbuffer.
                               */
                              if (targetfib->fib_DirEntryType
                                  != fib->fib_DirEntryType)
                                AddPart(textbuffer, "of different type", 128);
                              else
                              {
                                if (targetfib->fib_Size < fib->fib_Size)
                                  AddPart(textbuffer, "smaller", 128);
                                else if (targetfib->fib_Size > fib->fib_Size)
                                  AddPart(textbuffer, "larger", 128);

                                if (checkdatestamp)
                                {
                                  date = CompareDates((struct DateStamp *)
                                        & (fib->fib_Date),
                                      (struct DateStamp *) & (targetfib->fib_Date));
                                  if (date < 0)
                                    AddPart(textbuffer, "older", 128);
                                  else if (date > 0)
                                    AddPart(textbuffer, "newer", 128);
                                }
                              }

                              if (*textbuffer != NULL)
                              {
                                vargs[1] = (LONG) textbuffer;
                                VFPrintf(Output(), "%s: object %s\n", vargs);
                              }
                            }
                            else
                              PrintFault(IoErr(), targetdir);
                            UnLock(filelock);
                          }
                          else
                          {
                            PrintFault(IoErr(), targetdir);

                            /*
                             * If and error occured on a directory name, don't enter
                             * it.
                             */
                            if (fib->fib_DirEntryType > 0)
                              continue;

                          }

                          /*
                           * If the ALL keyword has been used and this is a directory
                           * enter it by setting the APF_DODIR flag.
                           */

                          if (fib->fib_DirEntryType > 0 && all != FALSE)
                            anchorpath->ap_Flags |= APF_DODIR;

                        }

                      } while ((error = MatchNext(anchorpath)) == 0);
                    }

                    MatchEnd(anchorpath);

                    if (error == ERROR_NO_MORE_ENTRIES)
                      error = 0;

                    FreeMem(anchorpath, sizeof(struct AnchorPath) + buffersize);
                  }
                }
              }
              /* Reset windowpointer */
              process->pr_WindowPtr = wptr;
            }
            else
              PrintFault(error, NULL);
            FreeDosObject(DOS_FIB, targetfib);
          }
          FreeMem(targetdir, buffersize);
        }
        FreeMem(sourcedir, StrLen(sourcedir) + 129);
      }
      FreeArgs(readargs);
    }
    else
      error = IoErr();

    SetIoErr(error);
    if (error)
    {
      PrintFault(error, NULL);
      if (error = ERROR_BREAK)
        rc = RETURN_WARN;
      else
        error = RETURN_FAIL;
    }
    CloseLibrary((struct Library *) DOSBase);
  }
  return (rc);
}

LONG
GetPath(UBYTE * path, UBYTE * buffer, LONG buffersize)
{
  UBYTE          *pathpart, *filepart;
  UBYTE          *tmp1, *tmp2;
  BPTR            lock;
  struct FileInfoBlock *fib;
  LONG            error = 0;

  /* Open own copy of dos.library if pragmas are used so it's standalone */
#ifdef PRAGMAS
  struct Library *DOSBase;

  if (!(DOSBase = OpenLibrary("dos.library", 36)))
    return (1);
#endif

  /*
   * If there seems to be no path, the pathpart will point to the filepart too, so we
   * need to check for that.
   */
  filepart = FilePart(path);
  pathpart = PathPart(path);

  /*
   * This also handles cases where there is only a volume/device name, only a
   * directory name or a combo of those.
   */
  if (pathpart == path)
  {

    /*
     * There seems to be only one component. Copy it if it is not wild. Caller will
     * have to check whether if it exists and if it is a file or directory.
     */
    if (!(ItsWild(pathpart)))
      pathpart = NULL;
  }

  if (pathpart != path)
  {

    /*
     * If pathpart equals filepart (pointer wise) then there is only one component
     * (possible preceeded by a volume name).
     */
    if (pathpart == filepart)
    {
      if (!(ItsWild(pathpart)))
        pathpart = NULL;
    }
    else
    {
      /* Try to lock it to determine if the last component is a directory. */
      if (lock = Lock(path, SHARED_LOCK))
      {
        if (fib = AllocMem(sizeof(struct FileInfoBlock), MEMF_CLEAR))
        {
          if ((Examine(lock, fib)) == DOSTRUE)
          {
            /* Hey it's a directory after all */
            if (fib->fib_DirEntryType > 0)
              pathpart = NULL;
          }
          FreeMem(fib, sizeof(struct FileInfoBlock));
        }
        UnLock(lock);
      }                                          /* else treat it as a filename */
    }

    /* Copy the pathpart in the buffer */
    tmp1 = buffer;
    tmp2 = path;
    while ((*tmp1++ = *tmp2++) && (tmp2 != pathpart))
    {
      if (tmp1 == (buffer + buffersize))
      {
        error = ERROR_NO_FREE_STORE;
        break;
      }
    }
    *tmp1 = '\0';                                /* NULL terminate. */
  }

#ifdef PRAGMAS
  CloseLibrary(DOSBase);
#endif
  return (error);
}

UBYTE          *
ItsWild(UBYTE * string)
{
  static UBYTE   *special = "#?*%([|";
  UBYTE          *tmp = string;
  COUNT           i;

  do
  {
    for (i = 0; special[i] != '\0'; i++)
    {
      if (*tmp == special[i])
        return (tmp);
    }
    tmp++;
  } while (*tmp);

  return (NULL);
}

UWORD
StrLen(UBYTE * string)
{
  UBYTE          *length = string + 1;

  while (*string++ != '\0');
  return ((UWORD) (string - length));
}


II-65/myshell.c

;/* myshell.c - Execute to compile me with SAS/C 6.56 using pragmas
; (c)  Copyright 1992-1999 Amiga, Inc.   All rights reserved.
; The information contained herein is subject to change without notice,
; and is provided "as is" without warranty of any kind, either expressed
; or implied.  The entire risk as to the use of this information is
; assumed by the user.
;
sc DATA=FAR NMINC STRMERGE NOSTKCHK CODE=NEAR PARMS=REG NODEBUG IGNORE=73 DEFINE=DOPRAGMAS myshell.c
slink FROM myshell.o TO myshell smallcode smalldata
quit
*/

/*
 * This is a basically a skeleton of a UserShell.  A UserShell is a special
 * shell that can replace the default system shell.  It has to meets some
 * system requirements to function as a system shell.  This example takes care
 * of all of those requirements. To make this shell the system shell, use the
 * resident command:
 *
 * resident shell MyShell SYSTEM
 *
 * Because this shell only serves as an minimal example of a UserShell and does
 * not do many of the standard functions a shell normally performs.  It is
 * limited to the commands from the resident list (which would make it a bad
 * idea to add this shell to the resident list if you need a useable default
 * shell!)
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dosextens.h>
#include <dos/stdio.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/alib_stdio_protos.h>

#ifdef DOPRAGMAS
#include <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>
#endif

long            main(void);

#define COMMANDBUFLENGTH    64
#define COMMANDLINELENGTH   512
#define PROMPTLENGTH        256

/* True if this is a System() Instigated shell */
#define SYSTEM ((ml->fn & 0x80000004) == 0x80000004)

/* true if this shell is executing a script */
#define ISSCRIPT (ml->mycli->cli_CurrentInput != ml->mycli->cli_StandardInput)

/* true if this shell is *not* executing a script */
#define NOTSCRIPT (ml->mycli->cli_CurrentInput == ml->mycli->cli_StandardInput)

struct mylocals
{
  struct Library    *sysBase;
  struct Library    *dosBase;
  struct Process    *myprocess;
  struct DosPacket  *mypacket;
  long              fn;        /* notice that fn is signed.  Some conditionals
                                  in this code rely on this value being signed.
                               */
  struct CommandLineInterface *mycli;
};

/*
 * define the library base labels (SysBase and DOSBase)
 * so we don't have to declare them as a global.  Can't have global data in
 * resident code.
 */
#define SysBase (ml->sysBase)
#define DOSBase (ml->dosBase)

long            mainshellloop(struct mylocals *);
long            strlen(UBYTE *);

long
main(void)
{
  struct mylocals globals, *ml = &globals;
  BPTR           *segment;
  long            shelltype, error;

  /*
   * Poof, this shell has winked into existence.  It could have come from the
   * user executing the "newshell" code via the newshell program, or it could
   * have come from some other application using one of the DOS calls that use
   * a shell, like System().  In any case, whatever caused this shell to wink
   * into existence will also cause a special startup packet to appear in this
   * process' message port.  This packet is very personal and private to DOS
   * and probably will change with future versions of the OS, so don't worry
   * about what's in it.  That would be bad.
   */
  error = RETURN_OK;
  /* Open libraries */
  SysBase = *((struct Library **) 4L);
  if (DOSBase = OpenLibrary("dos.library", 37))
  {
    /* First, get the packet that the newshell segment sends. */
    globals.mypacket = WaitPkt();
    globals.myprocess = (struct Process *) FindTask(NULL);

    /*
     * Some arcane magic here for the UserShell.  We have to look at this
     * process' array of Segment pointers.  If entry 4 in the array is NULL, we
     * have to move entry 3 to entry 4 and NULL entry 4.  This is because entry
     * 3 will be used to store the seglist pointer for each program this shell
     * runs.
     */
    segment = (BPTR *) BADDR(globals.myprocess->pr_SegList);
    if (!segment[4])
    {
      segment[4] = segment[3];
      segment[3] = NULL;
    }
    /*
     * The packet that newshell sends tells us how the shell was invoked. The
     * dp_Res1 and dp_Res2 fields of the packet structure represent,
     * respectively, the high order bit and low order bit of a two-bit
     * bitfield.  The following line of code will turn these values into a
     * value from 0 to 3:
     */
    shelltype = (globals.mypacket->dp_Res1 == 0 ? 0 : 2) |
      (globals.mypacket->dp_Res2 == 0 ? 0 : 1);

    /*
     * at the moment, only the values 0 and 2 are defined.  Type 0 is for Run,
     * Execute(), and System().  Type 2 is for NewShell and NewCli.
     */
    if ((shelltype == 2) || (shelltype == 0))
    {

      /*
       * These two functions CliInitNewcli() and CliInitRun() take care setting
       * up the shell's CommandLineInterface structure (current directories,
       * paths, input streams...) using the secret startup packet we got
       * earlier.  They differ slightly in their setup based on the shell type.
       * The exact workings of these functions is private and personal to DOS,
       * and is subject to change. If you are wondering what exactly these
       * functions do, don't worry about it.  That would also be bad.
       */
      if (shelltype == 0)
        globals.fn = CliInitRun(globals.mypacket);
      else

        /*
         * CliInitNewCli() handles the shell startup file (default is
         * s:Shell-startup) and stuffs a filehandle to it into
         * globals.mycli->cli_CurrentInput.
         */
        globals.fn = CliInitNewcli(globals.mypacket);

      /*
       * Definitions for the values of globals.fn:
       *     Bit 31     Set to indicate flags are valid
       *     Bit  3     Set to indicate asynch system call
       *     Bit  2     Set if this is a System() call
       *     Bit  1     Set if user provided input stream
       *     Bit  0     Set if RUN provided output stream
       */

      /*
       * If the high bit of globals.fn is clear, check IoErr() to see if it
       * points to this process.  If it does, there was an error with the
       * CliInitXxx... function.  On an error, clean up and exit.  You won't
       * have to return the packet if there was an error because the
       * CliInitXxxx function will take care of that.
       */
      if ((globals.fn & 0x80000000) == 0)       /* Is high bit clear? */
        if ((struct Process *) IoErr() == globals.myprocess)   /* is there an error? */
          error = RETURN_FAIL;
        else if (shelltype == 0)
        {
          ReplyPkt(globals.mypacket,
                   globals.mypacket->dp_Res1,
                   globals.mypacket->dp_Res2);
          globals.mypacket = NULL;
        }
      if (error != RETURN_FAIL)
      {

        /*
         * OK, no error.  If this shell was invoked via NewShell or NewCLI
         * (shelltype == 2), or if this is an asynchronous System() initiated
         * shell, return the startup message.   Although this example doesn't
         * do it, if shelltype == 0, you can wait to reply the packet until you
         * try to LoadSeg() your first command (to avoid disk gronking). When
         * you use ReplyPkt() to reply the packet, use it like it appears below
         * to avoid losing error codes set up by CliInitXxx.
         */
        if (((globals.fn & 0x8000000C) == 0x8000000C) || (shelltype == 2))
        {
          ReplyPkt(globals.mypacket,
                   globals.mypacket->dp_Res1,
                   globals.mypacket->dp_Res2);
          globals.mypacket = NULL;
        }

        if (globals.mycli = Cli())
        {
          /* Set up local shell variables and any custom set up here */
          globals.mycli->cli_ReturnCode = 0;
          globals.mycli->cli_Result2 = 0;
          globals.myprocess->pr_HomeDir = NULL;

          /* Ready to start processing commands */
          error = mainshellloop(ml);
          if (globals.fn < 0)          /* if we got valid flags from
                                        * CliInitXxxx (High bit of fn is set). */
          {
            Flush(Output());
            /* if user DID NOT provide input stream, close standardinput */
            if ((globals.fn & 2) == 0)
              Close(globals.mycli->cli_StandardInput);

            /* if RUN provided output stream, close it */
            if ((globals.fn & 1) == 1)
            {
              Flush(globals.mycli->cli_StandardOutput);
              Close(globals.mycli->cli_StandardOutput);
            }

            /* If we didn't send the packet back yet, send it back */
            if (globals.mypacket)
              ReplyPkt(globals.mypacket, error, globals.mypacket->dp_Res2);
          }
          else
            /*
             * the flags weren't valid so close the Standard I/O handles if
             * they still exist.
             */
          {
            if (globals.mycli->cli_StandardOutput)
            {
              Flush(globals.mycli->cli_StandardOutput);
              Close(globals.mycli->cli_StandardOutput);
            }
            if (globals.mycli->cli_StandardInput)
            {
              Flush(globals.mycli->cli_StandardInput);
              Close(globals.mycli->cli_StandardInput);
            }
          }
          /* release the process' lock on the current directory */
          UnLock(globals.myprocess->pr_CurrentDir);
        }
        else
          error = RETURN_FAIL;         /* I have a NULL CLI! */
      }
    }
    else
      /* shelltype != 0 or 2 */
    {
      error = RETURN_FAIL;
      ReplyPkt(globals.mypacket,
               globals.mypacket->dp_Res1,
               globals.mypacket->dp_Res2);
    }
    CloseLibrary(DOSBase);
  }
  else
    error = RETURN_FAIL;

  return error;
}
long mainshellloop(struct mylocals * ml)
{
  BOOL            done = FALSE;
  unsigned char   ch, *prompt, *command, *commandname, *cmd, *cmdname;
  struct Segment *cmdseg;
  long            result;
  WORD            x;

  ml->mycli->cli_FailLevel = RETURN_FAIL;

  if (command = (char *) AllocVec(COMMANDLINELENGTH + COMMANDBUFLENGTH +
                                  PROMPTLENGTH, MEMF_CLEAR))
  {
    commandname = &(command[COMMANDLINELENGTH]);
    prompt = &(command[COMMANDLINELENGTH + COMMANDBUFLENGTH]);
    do
    {
      /* Make sure the shell looks to cli_CurrentInput for its command lines */

      SelectInput(ml->mycli->cli_CurrentInput);
      /* is this an interactive shell? */
      ml->mycli->cli_Interactive =
      /* if this is not a backround CLI, and */
        ((!(ml->mycli->cli_Background)) &&
      /* input has not been redirected to an script file, and */
         NOTSCRIPT &&
      /* this shell was not started from System() */
         (!SYSTEM)) ? DOSTRUE : DOSFALSE;

      /* if this is a script and the user hit CTRL-D, break out of the script */
      if (!((SetSignal(0L, SIGBREAKF_CTRL_C |
                       SIGBREAKF_CTRL_D |
                       SIGBREAKF_CTRL_E |
                       SIGBREAKF_CTRL_F) & SIGBREAKF_CTRL_D) &&
            (!SYSTEM) && (ISSCRIPT)))
      {
        /* if this shell is interactive and there is a prompt, print it */
        /* (unless, of course, this was created by Run, etc) */
        if (ml->mycli->cli_Interactive == DOSTRUE && !(ml->mycli->cli_Background))
        {

          /*
           * If this wasn't an example, I would probably change the prompt
           * here, probably to reflect the name of the current directory.
           */
          /* print the prompt */
          if (GetPrompt(prompt, 256))
          {
            FPuts(Output(), prompt);
            /* Make sure the prompt gets printed */
            Flush(Output());
          }
        }
        /* Get Command */
        if (FGets(ml->mycli->cli_CurrentInput, command, COMMANDLINELENGTH))
        {
          cmd = command;
          /* skip leading spaces in command line */
          while (*cmd == ' ')
            cmd++;

          /*
           * If I was bothering to deal with aliases, I would probably resolve
           * them here.
           */

          cmdname = commandname;
          x = 0;
          /* copy the actual command from the cmd buffer */
          while ((*cmd >= '0') && (*cmd <= 'z') && (x < (COMMANDBUFLENGTH - 1)))
          {
            *cmdname++ = *cmd++;
            x++;
          }
          *cmdname = '\0';
          /*
           * OK, now we have the actual command in commandname. Using it we can
           * find the actual executeable code.  The command could come from
           * several sources:
           *
           * The resident list
           * The shell (an internal command)
           * disk (from either an absolute or relative path)
           *
           * This example only looks through the resident list for commands. A
           * real shell would also try to load a command from disk if the
           * command is not present in the resident list (or the command is not
           * internal to the shell.
           */

          /* Search resident list for the command */
          Forbid();
          if (!(cmdseg = FindSegment(commandname, NULL, FALSE)))
            cmdseg = FindSegment(commandname, NULL, TRUE);
          if (cmdseg)
          {
            if ((cmdseg->seg_UC < CMD_DISABLED) ||
                (cmdseg->seg_UC == CMD_SYSTEM))
              cmdseg = NULL;
            else if (cmdseg->seg_UC >= 0)
              cmdseg->seg_UC++;
          }
          Permit();

          /*
           * if !cmdseg, the command was not in the resident list.  If I were
           * bothering to look for commands on disk, I would try to load the
           * command here.  If I has successfully loaded a command and was
           * going to execute it, I would have to set ml->myprocess->pr_HomeDir
           * to be a DupLock() of the directory I loaded the command from.  I
           * don't do this for commands from the resident list because they
           * have no home directory.
           */

          /* If we did find a command, run it */
          if (cmdseg)
          {
            /* Clear the error field before executing the command */
            SetIoErr(0);

            SetProgramName(commandname);
            ml->mycli->cli_Module = cmdseg->seg_Seg;

            /*
             * Set the I/O streams to their defaults. NOTE: StandardInput, NOT
             * CurrentInput!  The Execute command will cause nasty things to
             * happen if you use CurrentInput, since it must close that in
             * order to change the input stream to the next file. Obviously,
             * this only applies if you're using the normal AmigaDOS Execute
             * command for scripts.
             */
            SelectInput(ml->mycli->cli_StandardInput);
            SelectOutput(ml->mycli->cli_StandardOutput);

            /*
             * If I were doing redirection, the I/O handles above would be the
             * redirection handles.
             */

            /* Run the command */
            result = RunCommand(ml->mycli->cli_Module,
                                (ml->mycli->cli_DefaultStack * 4),
                                cmd,
                                strlen(cmd));
            /*
             * OK, we returned from the command.  Fill in any error codes in
             * the appropriate CLI fields.
             */
            ml->mycli->cli_ReturnCode = result;
            ml->mycli->cli_Result2 = IoErr();
            /* If I had bothered to load code from an executable file on disk,
             * I would have to unload it now.  Since I didn't, all I have to do
             * is NULL cli_Module.
             */
            ml->mycli->cli_Module = NULL;

            SetProgramName("");
            Forbid();
            if (cmdseg->seg_UC > 0)
              cmdseg->seg_UC--;
            Permit();
            cmdseg = NULL;
          }
          else
          {
            /* we couldn't find the command.  Print an error message unless the
             * command starts with a non-alphanumeric character (like a
             * carriage return) or the first character is a comment character.
             */
            if ((commandname[0] >= '0') &&
                (commandname[0] <= 'z') &&
                (commandname[0] != ';'))
            {
              PutStr(commandname);
              PutStr(": Command not found\n");
              Flush(Output());
            }
          }

          /* if you set up redirection I/O handles for the command don't forget
           * to flush and close them.
           */

          /* Make sure the proper I/O handles are in place. */
          SelectInput(ml->mycli->cli_CurrentInput);
          SelectOutput(ml->mycli->cli_StandardOutput);

          /* Get rid of any unused data left in the buffer */
          ch = UnGetC(Input(), -1) ? '\0' : '\n';
          while ((ch != '\n') && (ch != ENDSTREAMCH))
            ch = FGetC(Input());
          if (ch == ENDSTREAMCH)
            done = TRUE;
        }
        else
          done = TRUE;                 /* We got an EOF when reading in a
                                        * command */
        if (done)
        {
          if (ISSCRIPT)
          {
            done = FALSE;              /* this is a script (which could be
                                        * s:shell-startup), so don't quit, just
                                        * exit the script and set up IO
                                        * handles. */
            /* Close the script file */
            Close(ml->mycli->cli_CurrentInput);
            /* Reset the input to what we started with */
            SelectInput(ml->mycli->cli_StandardInput);
            ml->mycli->cli_CurrentInput = ml->mycli->cli_StandardInput;

            /* Restore Fail Level after executing a script */
            ml->mycli->cli_FailLevel = RETURN_ERROR;

            /* if the script created a file, delete it */
            if (((char *) BADDR(ml->mycli->cli_CommandFile))[0])
            {
              cmd = (char *) BADDR(ml->mycli->cli_CommandFile);
              CopyMem(&(cmd[1]), command, (LONG) cmd[0]);
              command[cmd[0]] = '\0';
              DeleteFile(command);
              cmd[0] = '\0';
            }
          }
        }
      }
      else
        /* Somebody hit CTRL_D in a script */
      {
        /* print the string associated with error #304 */
        PrintFault(304, "MyShell");
        /* Close the script file */
        Close(ml->mycli->cli_CurrentInput);
        /* Reset the input to what we started with */
        SelectInput(ml->mycli->cli_StandardInput);
        ml->mycli->cli_CurrentInput = ml->mycli->cli_StandardInput;

        cmd = (char *) BADDR(ml->mycli->cli_CommandFile);
        cmd[0] = '\0';
      }
      /* this takes care of some problems certain programs caused */
      if (SYSTEM && NOTSCRIPT)
        done = TRUE;

    } while (!done);
    FreeVec((void *) command);
  }
  return result;
}

long strlen(UBYTE * string)
{
  long            x = 0L;

  while (string[x]) x++;
  return x;
}


II-65/RestoreShell.c

;/* RestoreShell.c - Execute me to compile me with SAS/C 6.56
; (c)  Copyright 1992-1999 Amiga, Inc.   All rights reserved.
; The information contained herein is subject to change without notice,
; and is provided "as is" without warranty of any kind, either expressed
; or implied.  The entire risk as to the use of this information is
; assumed by the user.
;
sc DATA=NEAR NMINC STRMERGE NOSTKCHK NODEBUG IGNORE=73 RestoreShell.c
slink FROM lib:c.o RestoreShell.o TO RestoreShell LIBRARY lib:sc.lib lib:amiga.lib smallcode smalldata
quit
*/
/* restore the BootShell as the UserShell.  Note that this
   only switches back the BootShell, it does not unload the
   current user shell ("shell" on the resident list) as it
   is possible that some instance of it can still be running.
*/
#include <exec/types.h>
#include <dos/dosextens.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }
#endif

UBYTE *vers = "\0$VER: RestoreShell 1.0";

void main(void)
{
    struct Segment
        *bootshell_seg,
        *shell_seg;

    Forbid();
    shell_seg = FindSegment("shell", NULL, CMD_SYSTEM);
    bootshell_seg = FindSegment("bootshell", NULL, CMD_SYSTEM);
    if (bootshell_seg)
        shell_seg->seg_Seg = bootshell_seg->seg_Seg;
    Permit();
}


II-77/Async.doc

(c)  Copyright 1992-1999 Amiga, Inc.   All rights reserved.
The information contained herein is subject to change without notice,
and is provided "as is" without warranty of any kind, either expressed
or implied.  The entire risk as to the use of this information is
assumed by the user.

 TABLE OF CONTENTS

asyncio/CloseAsync
asyncio/OpenAsync
asyncio/ReadAsync
asyncio/ReadAsyncChar
asyncio/WriteAsync
asyncio/WriteAsyncChar
asyncio/CloseAsync                                         asyncio/CloseAsync

   NAME
        CloseAsync -- close an async io file.

   SYNOPSIS
        result = CloseAsync(file);

        LONG CloseAsync(struct AsyncFile *);

   FUNCTION
        Closes a file, flushing any pending writes.  Once this call has been
        made, the file can no longer be accessed.

   INPUTS
        file - the file to close.  May be NULL.

   RESULT
        result - < 0 for an error, >= 0 for success.  Indicates whether closing
                 the file worked or not.  If the file was opened in read-mode,
                 then this call will always work.  In case of error,
                 dos.library/IoErr() can give more information.

   SEE ALSO
        OpenAsync, dos.library/Close()

 asyncio/OpenAsync                                           asyncio/OpenAsync

   NAME
        OpenAsync -- open a file for asynchronous IO.

   SYNOPSIS
        file = OpenAsync(fileName, accessMode, bufferSize);

        struct AsyncFile OpenAsync(STRPTR, UBYTE, LONG);

   FUNCTION
        The named file is opened and an async file handle returned.  If the
        accessMode is MODE_READ, an existing file is opened for reading.
        If the value is MODE_WRITE, a new file is created for writing.  If
        a file of the same name already exists, it is first deleted.  If
        accessMode is MODE_APPEND, an existing file is prepared for writing.
        Data written is added to the end of the file.  If the file does not
        exists, it is created.

        'fileName' is a filename and CANNOT be a simple device such as NIL:, a
        window specification such as CON: or RAW:, or "*".

        'bufferSize' specifies the size of the IO buffer to use.  There are
        in fact two buffers allocated, each of roughly (bufferSize/2) bytes
        in size.  The actual buffer size use can vary slightly as the size
        is rounded to speed up DMA.

        If the file cannot be opened for any reason, the value returned
        will be NULL, and a secondary error code will be available by
        calling the routine dos.library/IoErr().

    INPUTS
        name - name of the file to open
        accessMode - one of MODE_READ, MODE_WRITE, or MODE_APPEND
        bufferSize - size of IO buffer to use.  8192 is recommended as it
                     provides very good performance for relatively little
                     memory.

    RESULTS
        file - an async file handle or NULL for failure.  You should not access
               the fields in the AsyncFile structure, these are private to the
               async IO routines.  In case of failure, dos.library/IoErr() can
               give more information.

    SEE ALSO
        CloseAsync(), dos.library/Open()

 asyncio/ReadAsync                                           asyncio/ReadAsync

   NAME
        ReadAsync -- read bytes from an async file.

   SYNOPSIS
        actualLength = ReadAsync(file,buffer,numBytes);

        LONG ReadAsync(struct AsyncFile *file, APTR buffer, LONG numBytes);

   FUNCTION
        Read() reads bytes of information from an opened async file
        into the buffer given.  'numBytes' is the number of bytes to read from
        the file.

        The value returned is the length of the information actually read.
        So, when 'actualLength' is greater than zero, the value of
        'actualLength' is the the number of characters read.  Usually
        ReadAsync() will try to fill up your buffer before returning.  A value
        of zero means that end-of-file has been reached.  Errors are indicated
        by a value of -1.

    INPUTS
        file - opened file to read, as obtained from OpenAsync()
        buffer - buffer where to put bytes read
        numBytes - number of bytes to read into buffer

    RESULT
        actualLength - actual number of bytes read, or -1 if an error.  In
                       case of error, dos.library/IoErr() can give more
                       information.

    SEE ALSO
        OpenAsync(), CloseAsync(), WriteAsync(), ReadCharAsync(),
        dos.library/Read()

 asyncio/ReadCharAsync                                   asyncio/ReadCharAsync

   NAME
        ReadCharAsync -- read a single byte from an async file.

   SYNOPSIS
        byte = ReadCharAsync(file);

        LONG ReadCharAsync(struct AsyncFile *file);

   FUNCTION
        This function reads a single byte from an async file.  The byte is
        returned, or -1 if there was an error reading, or if the end-of-file
        was reached.

   INPUTS
        file - opened file to read from, as obtained from OpenAsync()

   RESULT
        byte - the byte read, or -1 if no byte was read.  In case of error,
               dos.library/IoErr() can give more information.

   SEE ALSO
        OpenAsync(), CloseAsync(), WriteCharAsync(), ReadAsync()
        dos.library/Read()

 asyncio/WriteAsync                                         asyncio/WriteAsync

   NAME
        WriteAsync -- write data to an async file.

   SYNOPSIS
        actualLength = WriteAsync(file,buffer,numBytes);

        LONG WriteAsync(struct AsyncFile *file, APTR buffer, LONG numBytes);

   FUNCTION
        WriteAsync() writes bytes of data to an opened async file.  'numBytes'
        indicates the number of bytes of data to be transferred.  'buffer'
        points to the data to write.  The value returned is the length of
        information actually written.  So, when 'numBytes' is greater than
        zero, the value of 'numBytes' is the number of characters written.
        Errors are indicated by a value of -1.

    INPUTS
        file - an opened file, as obtained from OpenAsync()
        buffer - address of data to write
        numBytes - number of bytes to write to the file

    RESULT
        actualLength - number of bytes written, or -1 if error.  In case
                       of error, dos.library/IoErr() can give more
                       information.

    SEE ALSO
        OpenAsync(), CloseAsync(), ReadAsync(), WriteCharAsync(),
        dos.library/Write

 asyncio/WriteCharAsync                                 asyncio/WriteCharAsync

   NAME
        WriteCharAsync -- write a single byte to an async file.

   SYNOPSIS
        result = WriteCharAsync(file,byte);

        LONG WriteCharAsync(struct AsyncFile *, UBYTE byte);

   FUNCTION
        This function write a single byte to an async file.

   INPUTS
        file - an opened async file, as obtained from OpenAsync()
        byte - byte of data to add to the file

   RESULT
        result - 1 if the byte was written, -1 if there was an error.  In
                 case of error, dos.library/IoErr() can give more information.

   SEE ALSO
        OpenAsync(), CloseAsync(), ReadAsync(), WriteCharAsync(),
        dos.library/Write


II-77/ASyncExample.c

;/* ASyncExample.c - Execute me to compile me with SAS/C 6.56
sc NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 ASyncExample.c
slink FROM LIB:c.o,ASyncExample.o TO ASyncExample LIBRARY LIB:sc.lib,LIB:amiga.lib,asyncio.o
quit ;*/

/*
(c)  Copyright 1992-1999 Amiga, Inc.   All rights reserved.
The information contained herein is subject to change without notice,
and is provided "as is" without warranty of any kind, either expressed
or implied.  The entire risk as to the use of this information is
assumed by the user.
*/

#include <exec/types.h>
#include <exec/exec.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <stdio.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>

#include "asyncio.h"

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }
#endif

VOID main(VOID)
{
struct AsyncFile *in;
LONG              num;
struct AsyncFile *out;

    if (in = OpenAsync("s:Startup-Sequence", MODE_READ, 8192))
    {
        if (out = OpenAsync("t:test_sync", MODE_WRITE, 8192))
        {
            while ((num = ReadCharAsync(in)) >= 0)
            {
                WriteCharAsync(out,num);
            }
            CloseAsync(out);
        }
        CloseAsync(in);
    }
}


II-77/ASyncIO.c

;/* ASyncIO.c - Execute me to compile with SAS/C 6.56
sc NMINC STRMERGE NOSTKCHK IGNORE=73 asyncio.c
quit
*/

/*
(c)  Copyright 1992-1999 Amiga, Inc.   All rights reserved.
The information contained herein is subject to change without notice,
and is provided "as is" without warranty of any kind, either expressed
or implied.  The entire risk as to the use of this information is
assumed by the user.
*/

#include <exec/types.h>
#include <exec/exec.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <stdio.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>

#include "asyncio.h"

/*****************************************************************************/

static VOID SendAsync(struct AsyncFile *file, APTR arg2)
{
    /* send out an async packet to the file system. */

    file->af_Packet.sp_Pkt.dp_Port = &file->af_PacketPort;
    file->af_Packet.sp_Pkt.dp_Arg2 = (LONG)arg2;
    PutMsg(file->af_Handler, &file->af_Packet.sp_Msg);
    file->af_PacketPending = TRUE;
}

/*****************************************************************************/

static VOID WaitPacket(struct AsyncFile *file)
{
    /* This enables signalling when a packet comes back to the port */
    file->af_PacketPort.mp_Flags = PA_SIGNAL;

    /* Wait for the packet to come back, and remove it from the message
     * list. Since we know no other packets can come in to the port, we can
     * safely use Remove() instead of GetMsg(). If other packets could come in,
     * we would have to use GetMsg(), which correctly arbitrates access in such
     * a case
     */
    Remove((struct Node *)WaitPort(&file->af_PacketPort));

    /* set the port type back to PA_IGNORE so we won't be bothered with
     * spurious signals
     */
    file->af_PacketPort.mp_Flags = PA_IGNORE;

    /* packet is no longer pending, we got it */
    file->af_PacketPending = FALSE;
}

/*****************************************************************************/

struct AsyncFile *OpenAsync(STRPTR fileName, UBYTE mode, LONG bufferSize)
{
struct AsyncFile  *file;
struct FileHandle *fh;

    /* The buffer size is rounded to a multiple of 32 bytes. This will make
     * DMA as fast as can be
     */

    bufferSize = (bufferSize + 31) & 0xffffffe0;

    /* now allocate the ASyncFile structure, as well as the read buffer. Add
     * 15 bytes to the total size in order to allow for later quad-longword
     * alignement of the buffers
     */

    if (file = AllocVec(sizeof(struct AsyncFile) + bufferSize + 15,
                        MEMF_ANY|MEMF_CLEAR))
    {
        if (mode == MODE_READ)
        {
            file->af_File     = Open(fileName,MODE_OLDFILE);
            file->af_ReadMode = TRUE;
        }
        else if (mode == MODE_WRITE)
        {
            file->af_File = Open(fileName,MODE_NEWFILE);
        }
        else if (mode == MODE_APPEND)
        {
            /* in append mode, we open for writing, and then seek to the
             * end of the file. That way, the initial write will happen at
             * the end of the file, thus extending it
             */

            if (file->af_File = Open(fileName,MODE_READWRITE))
            {
                if (Seek(file->af_File,0,OFFSET_END) < 0)
                {
                    Close(file->af_File);
                    file->af_File = NULL;
                }
            }
        }

        if (!file->af_File)
        {
            /* file didn't open, free stuff and leave */
            FreeVec(file);
            return(NULL);
        }

        /* initialize the ASyncFile structure. We do as much as we can here,
         * in order to avoid doing it in more critical sections
         *
         * Note how the two buffers used are quad-longword aligned. This helps
         * performance on 68040 systems with copyback cache. Aligning the data
         * avoids a nasty side-effect of the 040 caches on DMA. Not aligning
         * the data causes the device driver to have to do some magic to avoid
         * the cache problem. This magic will generally involve flushing the
         * CPU caches. This is very costly on an 040. Aligning things avoids
         * the need for magic, at the cost of at most 15 bytes of ram.
         */

        fh                  = BADDR(file->af_File);
        file->af_Handler    = fh->fh_Type;
        file->af_BufferSize = bufferSize / 2;
        file->af_Buffers[0] =
                (APTR)(((ULONG)file + sizeof(struct AsyncFile) + 15) & 0xfffffff0);
        file->af_Buffers[1] =
                (APTR)((ULONG)file->af_Buffers[0] + file->af_BufferSize);
        file->af_Offset     = file->af_Buffers[0];

        /* this is the port used to get the packets we send out back.
         * It is initialized to PA_IGNORE, which means that no signal is
         * generated when a message comes in to the port. The signal bit number
         * is initialized to SIGB_SINGLE, which is the special bit that can
         * be used for one-shot signalling. The signal will never be set,
         * since the port is of type PA_IGNORE. We'll change the type of the
         * port later on to PA_SIGNAL whenever we need to wait for a message
         * to come in.
         *
         * The trick used here avoids the need to allocate an extra signal bit
         * for the port. It is quite efficient.
         */

        file->af_PacketPort.mp_MsgList.lh_Head     =
                (struct Node *)&file->af_PacketPort.mp_MsgList.lh_Tail;
        file->af_PacketPort.mp_MsgList.lh_TailPred =
                (struct Node *)&file->af_PacketPort.mp_MsgList.lh_Head;
        file->af_PacketPort.mp_Node.ln_Type        = NT_MSGPORT;
        file->af_PacketPort.mp_Flags               = PA_IGNORE;
        file->af_PacketPort.mp_SigBit              = SIGB_SINGLE;
        file->af_PacketPort.mp_SigTask             = FindTask(NULL);

        file->af_Packet.sp_Pkt.dp_Link          = &file->af_Packet.sp_Msg;
        file->af_Packet.sp_Pkt.dp_Arg1          = fh->fh_Arg1;
        file->af_Packet.sp_Pkt.dp_Arg3          = file->af_BufferSize;
        file->af_Packet.sp_Msg.mn_Node.ln_Name  = (STRPTR)&file->af_Packet.sp_Pkt;
        file->af_Packet.sp_Msg.mn_Node.ln_Type  = NT_MESSAGE;
        file->af_Packet.sp_Msg.mn_Length        = sizeof(struct StandardPacket);

        if (mode == MODE_READ)
        {
            /* if we are in read mode, send out the first read packet to the
             * file system. While the application is getting ready to read
             * data, the file system will happily fill in this buffer with
             * DMA transfer, so that by the time the application needs the data,
             * it will be in the buffer waiting
             */

            file->af_Packet.sp_Pkt.dp_Type = ACTION_READ;
            if (file->af_Handler)
                SendAsync(file,file->af_Buffers[0]);
        }
        else
        {
            file->af_Packet.sp_Pkt.dp_Type = ACTION_WRITE;
            file->af_BytesLeft             = file->af_BufferSize;
        }
    }

    return(file);
}

/*****************************************************************************/

LONG CloseAsync(struct AsyncFile *file)
{
LONG result;
LONG result2;

    result = 0;
    if (file)
    {
        if (file->af_PacketPending)
            WaitPacket(file);

        result  = file->af_Packet.sp_Pkt.dp_Res1;
        result2 = file->af_Packet.sp_Pkt.dp_Res2;
        if (result >= 0)
        {
            if (!file->af_ReadMode)
            {
                /* this will flush out any pending data in the write buffer */
                result  = Write(file->af_File,
                          file->af_Buffers[file->af_CurrentBuf],
                          file->af_BufferSize - file->af_BytesLeft);
                result2 = IoErr();
            }
        }

        Close(file->af_File);
        FreeVec(file);

        SetIoErr(result2);
    }

    return(result);
}

/*****************************************************************************/

LONG ReadAsync(struct AsyncFile *file, APTR buf, LONG numBytes)
{
LONG totalBytes;
LONG bytesArrived;

    totalBytes = 0;

    /* if we need more bytes than there are in the current buffer, enter the
     * read loop
     */

    while (numBytes > file->af_BytesLeft)
    {
        /* this takes care of NIL: */
        if (!file->af_Handler)
            return(0);

        WaitPacket(file);

        bytesArrived = file->af_Packet.sp_Pkt.dp_Res1;
        if (bytesArrived <= 0)
        {
            /* error, get out of here */
            SetIoErr(file->af_Packet.sp_Pkt.dp_Res2);
            return(-1);
        }

        /* enable this section of code if you want special processing for
         * reads bigger than the buffer size
         */
#ifdef OPTIMIZE_BIG_READS
        if (numBytes > file->af_BytesLeft + bytesArrived + file->af_BufferSize)
        {
            if (file->af_BytesLeft)
            {
                CopyMem(file->af_Offset,buf,file->af_BytesLeft);

                numBytes   -= file->af_BytesLeft;
                buf         = (APTR)((ULONG)buf + file->af_BytesLeft);
                totalBytes += file->af_BytesLeft;
                file->af_BytesLeft = 0;
            }

            if (bytesArrived)
            {
                CopyMem(file->af_Buffers[file->af_CurrentBuf],buf,bytesArrived);

                numBytes   -= bytesArrived;
                buf         = (APTR)((ULONG)buf + bytesArrived);
                totalBytes += bytesArrived;
            }

            bytesArrived = Read(file->af_File,buf,numBytes);

            if (bytesArrived <= 0)
                return(-1);

            SendAsync(file,file->af_Buffers[0]);
            file->af_CurrentBuf = 0;
            file->af_BytesLeft  = 0;

            return(totalBytes + bytesArrived);
        }
#endif

        if (file->af_BytesLeft)
        {
            CopyMem(file->af_Offset,buf,file->af_BytesLeft);

            numBytes   -= file->af_BytesLeft;
            buf         = (APTR)((ULONG)buf + file->af_BytesLeft);
            totalBytes += file->af_BytesLeft;
        }

        /* ask that the buffer be filled */
        SendAsync(file,file->af_Buffers[1-file->af_CurrentBuf]);

        file->af_Offset     = file->af_Buffers[file->af_CurrentBuf];
        file->af_CurrentBuf = 1 - file->af_CurrentBuf;
        file->af_BytesLeft  = bytesArrived;
    }

    if (numBytes)
    {
        CopyMem(file->af_Offset,buf,numBytes);
        file->af_BytesLeft -= numBytes;
        file->af_Offset     = (APTR)((ULONG)file->af_Offset + numBytes);
    }

    return (totalBytes + numBytes);
}

/*****************************************************************************/

LONG ReadCharAsync(struct AsyncFile *file)
{
char ch;

    if (file->af_BytesLeft)
    {
        /* if there is at least a byte left in the current buffer, get it
         * directly. Also update all counters
         */

        ch = *(char *)file->af_Offset;
        file->af_BytesLeft--;
        file->af_Offset = (APTR)((ULONG)file->af_Offset + 1);

        return((LONG)ch);
    }

    /* there were no characters in the current buffer, so call the main read
     * routine. This has the effect of sending a request to the file system to
     * have the current buffer refilled. After that request is done, the
     * character is extracted for the alternate buffer, which at that point
     * becomes the "current" buffer
     */

    if (ReadAsync(file,&ch,1) > 0)
        return((LONG)ch);

    /* We couldn't read above, so fail */

    return(-1);
}

/*****************************************************************************/

LONG WriteAsync(struct AsyncFile *file, APTR buf, LONG numBytes)
{
LONG totalBytes;

    totalBytes = 0;

    while (numBytes > file->af_BytesLeft)
    {
        /* this takes care of NIL: */
        if (!file->af_Handler)
        {
            file->af_Offset    = file->af_Buffers[file->af_CurrentBuf];
            file->af_BytesLeft = file->af_BufferSize;
            return(numBytes + totalBytes);
        }

        if (file->af_BytesLeft)
        {
            CopyMem(buf,file->af_Offset,numBytes);

            numBytes   -= file->af_BytesLeft;
            buf         = (APTR)((ULONG)buf + file->af_BytesLeft);
            totalBytes += file->af_BytesLeft;
        }

        if (file->af_PacketPending)
        {
            WaitPacket(file);

            if (file->af_Packet.sp_Pkt.dp_Res1 <= 0)
            {
                /* an error occurred, leave */
                SetIoErr(file->af_Packet.sp_Pkt.dp_Res2);
                return(-1);
            }
        }

        /* send the current buffer out to disk */
        SendAsync(file,file->af_Buffers[file->af_CurrentBuf]);

        file->af_CurrentBuf   = 1 - file->af_CurrentBuf;
        file->af_Offset       = file->af_Buffers[file->af_CurrentBuf];
        file->af_BytesLeft    = file->af_BufferSize;
    }

    if (numBytes)
    {
        CopyMem(buf,file->af_Offset,numBytes);
        file->af_BytesLeft -= numBytes;
        file->af_Offset     = (APTR)((ULONG)file->af_Offset + numBytes);
    }

    return (totalBytes + numBytes);
}

/*****************************************************************************/

LONG WriteCharAsync(struct AsyncFile *file, char ch)
{
    if (file->af_BytesLeft)
    {
        /* if there's any room left in the current buffer, directly write
         * the byte into it, updating counters and stuff.
         */

        *(char *)file->af_Offset = ch;
        file->af_BytesLeft--;
        file->af_Offset = (APTR)((ULONG)file->af_Offset + 1);

        /* one byte written */
        return(1);
    }

    /* there was no room in the current buffer, so call the main write
     * routine. This will effectively send the current buffer out to disk,
     * wait for the other buffer to come back, and then put the byte into
     * it.
     */

    return(WriteAsync(file,&ch,1));
}


II-77/ASyncIO.h

/* ASyncIO.h - Header File for ASyncIO.c */

#ifndef ASYNCIO_H
#define ASYNCIO_H

/*****************************************************************************/

#include <exec/types.h>
#include <exec/ports.h>
#include <dos/dos.h>

/*****************************************************************************/

struct AsyncFile
{
    BPTR                  af_File;
    struct MsgPort       *af_Handler;
    APTR                  af_Offset;
    LONG                  af_BytesLeft;
    ULONG                 af_BufferSize;
    APTR                  af_Buffers[2];
    struct StandardPacket af_Packet;
    struct MsgPort        af_PacketPort;
    ULONG                 af_CurrentBuf;
    UBYTE                 af_PacketPending;
    UBYTE                 af_ReadMode;
};

/*****************************************************************************/

#define MODE_READ   0  /* read an existing file                             */
#define MODE_WRITE  1  /* create a new file, delete existing file if needed */
#define MODE_APPEND 2  /* append to end of existing file, or create new     */

/*****************************************************************************/

struct AsyncFile *OpenAsync(STRPTR fileName, UBYTE mode, LONG bufferSize);
LONG CloseAsync(struct AsyncFile *file);
LONG ReadAsync(struct AsyncFile *file, APTR buf, LONG numBytes);
LONG ReadCharAsync(struct AsyncFile *file);
LONG WriteAsync(struct AsyncFile *file, APTR buf, LONG numBytes);
LONG WriteCharAsync(struct AsyncFile *file, char ch);

/*****************************************************************************/

#endif /* ASYNCIO_H */


II-87/LockRecord.c

; /* LockRecord.c - Execute me to compile me with SAS/C 6.56
sc NMINC STRMERGE NOSTKCHK NODEBUG DATA=FAR IGNORE=73 LockRecord.c
slink FROM LockRecord.o to LockRecord LIB lib:amiga.lib
quit
*
* AmigaMail LockRecord()/UnLockRecord() example.
*/

/*
(c)  Copyright 1992-1999 Amiga, Inc.   All rights reserved.
The information contained herein is subject to change without notice,
and is provided "as is" without warranty of any kind, either expressed
or implied.  The entire risk as to the use of this information is
assumed by the user.
*/

#include <exec/memory.h>
#include <exec/lists.h>
#include <dos/dosextens.h>
#include <dos/rdargs.h>
#include <dos/record.h>
#include <utility/tagitem.h>

#include <clib/alib_protos.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/utility_protos.h>

void GetCommandLine(BPTR, struct RDArgs *rdargs, UBYTE *cmdbuffer);
void DoLockRecord(BPTR, struct RDArgs *rdargs);
void DoUnLockRecord(BPTR fh, struct RDArgs *rdargs);
void ListRecordLocks(void);
struct LockNode *FindRecordLock(ULONG offset, ULONG length);

/* List and node structures to keep track of record locks */
struct LockNode {
    struct LockNode *ln_Succ;
    struct LockNode *ln_Pred;
    ULONG ln_Counter;
    ULONG ln_Offset;
    ULONG ln_Length;
    ULONG ln_Mode;
};

struct LockList {
    struct LockNode *lh_Head;
    struct LockNode *lh_Tail;
    struct LockNode *lh_TailPred;
    ULONG lh_Counter;
};

/* Pseudo data file */
#define TESTFILE "t:locktest"

#define LOCK_TEMPLATE "OFFSET/K/N,LENGTH/K/N,EXCLUSIVE/S,IMMEDIATE/S,TIMEOUT/K/N"
#define UNLOCK_TEMPLATE "OFFSET/K/N,LENGTH/K/N"

#define OFFSET_POS      0
#define LENGTH_POS      1
#define EXCLUSIVE_POS   2
#define IMMEDIATE_POS   3
#define TIMEOUT_POS     4

struct Library *SysBase;
struct DosLibrary *DOSBase;
struct Library *UtilityBase;

struct LockList *locklist;

LONG main(void)
{
    BPTR fh;
    struct RDArgs *rdargs;
    struct CSource *csource;
    UBYTE *cmdbuffer;
    struct LockNode *lnode, *nnode;
    LONG error = RETURN_OK;

    SysBase = (*((struct Library **) 4));

    /* Fails silently if < 37 */
    if (DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 37))
    {
        UtilityBase = DOSBase->dl_UtilityBase;

        if (locklist = AllocMem(sizeof(struct LockList), MEMF_CLEAR))
        {
            NewList((struct List *)locklist);

            /* Allocate RDArgs structure to parse command lines */
            if (rdargs = AllocDosObject(DOS_RDARGS, TAG_END))
            {
                csource = &rdargs->RDA_Source;

                /* Get buffer to read command lines in */
                if (csource->CS_Buffer = AllocMem(512, MEMF_CLEAR))
                {
                    csource->CS_Length = 512;
                    csource->CS_CurChr = 0;

                    /* Buffer to isolate command keyword */
                    if (cmdbuffer = AllocMem(80, MEMF_CLEAR))
                    {

                        /* Open a testfile, create it if necessary */
                        if (fh = Open(TESTFILE, MODE_READWRITE))
                        {

                            /* Process command lines */
                            GetCommandLine(fh, rdargs, cmdbuffer);

                            /* Try to get rid of outstanding record locks */
                            lnode = locklist->lh_Head;
                            while (nnode = lnode->ln_Succ)
                            {

                                /* Try to unlock pending locks */
                                if ((UnLockRecord(fh,
                                                  lnode->ln_Offset,
                                                  lnode->ln_Length)) == DOSFALSE)
                                {
                   Printf("Error unlocking record %ld with offset %ld length %ld\n",
                                        lnode->ln_Counter,
                                        lnode->ln_Offset,
                                        lnode->ln_Length);
                                    if (IoErr())
                                        PrintFault(IoErr(), NULL);
                                }
                                /* Remove node no matter what */
                                FreeMem(lnode, sizeof(struct LockNode));
                                lnode = nnode;
                            };

                            Close(fh);
                        }
                        FreeMem(cmdbuffer, 80);
                    } else
                        SetIoErr(ERROR_NO_FREE_STORE);

                    FreeMem(csource->CS_Buffer, 512);
                } else
                    SetIoErr(ERROR_NO_FREE_STORE);

                FreeDosObject(DOS_RDARGS, rdargs);
            } else
                SetIoErr(ERROR_NO_FREE_STORE);

            FreeMem(locklist, sizeof(struct LockList));
        } else
            SetIoErr(ERROR_NO_FREE_STORE);

        error = IoErr();
        if (error)
        {
            PrintFault(IoErr(), NULL);
            error = RETURN_FAIL;
        }

        CloseLibrary((struct Library *)DOSBase);
    }
    return(error);
}
void GetCommandLine(BPTR fh, struct RDArgs *rdargs, UBYTE *cmdbuffer)
{
    struct CSource *csource = &rdargs->RDA_Source;
    UBYTE *cmdlinebuffer = csource->CS_Buffer;
    LONG error;

    /* Prompt for command line */
    Write(Output(), "Cmd> ", 5);

    /* Loop forever, waiting for commands */
    for (;;)
    {
        /* Get command line */
        if ((FGets(Input(), cmdlinebuffer, 512)) != NULL)
        {

            /* Use ReadItem() to isolate actual command */
            error = ReadItem(cmdbuffer, 80, csource);

            /* Break on error */
            if (error == ITEM_ERROR)
                break;

            /* Make sure I've got something */
            else if (error != ITEM_NOTHING)
            {
                /* cmdbuffer now contains the command:
                 *
                 * KNOWN COMMANDS:
                 * QUIT
                 * LIST
                 * LOCKRECORD
                 * UNLOCKRECORD
                 */

                if ((Stricmp("QUIT", cmdbuffer)) == 0)
                    break;
                else if ((Stricmp("HELP", cmdbuffer)) == 0)
                {
                    Printf("Available commands:\n");
                    Printf("LOCKRECORD %s\n", LOCK_TEMPLATE);
                    Printf("UNLOCKRECORD %s\n", UNLOCK_TEMPLATE);
                    Printf("LIST\n");
                    Printf("QUIT\n");
                }
                else if ((Stricmp("LIST", cmdbuffer)) == 0)
                    ListRecordLocks();  /* Show all current locks */
                else
                {

                    /* Note that I've already isolated the command
                     * keyword, so I'm using Source->CS_CurChr to point
                     * after it.
                     */
                    csource->CS_Buffer += csource->CS_CurChr;
                    csource->CS_CurChr = 0;

                    if ((Stricmp("LOCKRECORD", cmdbuffer)) == 0)
                        DoLockRecord(fh, rdargs);
                    else if ((Stricmp("UNLOCKRECORD", cmdbuffer)) == 0)
                        DoUnLockRecord(fh, rdargs);
                    else
                        PrintFault(ERROR_NOT_IMPLEMENTED, cmdbuffer);

                    /* Reset CSource */
                    csource->CS_Buffer = cmdlinebuffer;
                }

                /* Output new prompt. Make sure csource is OK. */
                Write(Output(), "Cmd> ", 5);
                csource->CS_CurChr = 0;
            }
        } else
            break;
    }
}

void DoLockRecord(BPTR fh, struct RDArgs *rdargs)
{
    struct RDArgs *readargs;
    LONG rargs[5];
    ULONG offset, length, timeout, mode;
    ULONG result;
    struct LockNode *lnode;

    offset = length = timeout = mode = 0;
    rargs[0] = rargs[1] = rargs[2] = rargs[3] = rargs[4] = 0;

    if (readargs = ReadArgs(LOCK_TEMPLATE, rargs, rdargs))
    {

        if (rargs[OFFSET_POS])
            offset = *((LONG *)rargs[OFFSET_POS]);
        if (rargs[LENGTH_POS])
            length = *((LONG *)rargs[LENGTH_POS]);
        if (rargs[TIMEOUT_POS])
            timeout = *((LONG *)rargs[TIMEOUT_POS]);

        /* Type of locking */
        if (rargs[EXCLUSIVE_POS])
        {
            if (rargs[IMMEDIATE_POS])
                mode = REC_EXCLUSIVE_IMMED;
            else
                mode = REC_EXCLUSIVE;
        }
        else
        {
            if (rargs[IMMEDIATE_POS])
                mode = REC_SHARED_IMMED;
            else
                mode = REC_SHARED;
        }

        rargs[0] = offset;
        rargs[1] = length;
        switch (mode)
        {
            case REC_EXCLUSIVE_IMMED:
                rargs[2] = (LONG)"REC_EXCLUSIVE_IMMED";
                break;
            case REC_EXCLUSIVE:
                rargs[2] = (LONG)"REC_EXCLUSIVE";
                break;
            case REC_SHARED_IMMED:
                rargs[2] = (LONG)"REC_SHARED_IMMED";
                break;
            case REC_SHARED:
                rargs[2] = (LONG)"REC_SHARED";
                break;
        }
        rargs[3] = timeout;

        /* Show what I'm going to do */
        VFPrintf(Output(),
            "LockRecord: Offset %ld, Length %ld, Mode %s, Timeout %ld...",
            rargs);
        Flush(Output());

        /* Lock the record. Parameters are not checked. It is f.e. possible to
         * specify an offset larger than the size of the file. Possible since
         * Record Locks are not related to the file itself, only the means for
         * you to do arbitration.
         *
         * Note that the timeout value is in ticks...
         */
        result = LockRecord(fh, offset, length, mode, timeout);

        if (result == DOSTRUE)
        {
            Write(Output(), "OK\n", 3);

            /* Add a node to track this record lock */
            if (lnode = AllocMem(sizeof(struct LockNode), MEMF_CLEAR))
            {
                lnode->ln_Counter = locklist->lh_Counter++;
                lnode->ln_Offset = offset;
                lnode->ln_Length = length;
                lnode->ln_Mode = mode;

                AddTail((struct List *)locklist, (struct Node *)lnode);
            }
            else
            {
                /* Not enough memory for node. You're on your own... */
                Write(Output(), "Not enough memory to track record lock.\n", 40);
            }
        }
        else
        {
            Write(Output(), "FAILED\n", 7);
            if (IoErr())
                PrintFault(IoErr(), NULL);
        }

        /* Release memory associated with readargs */
        FreeArgs(readargs);
    } else
        PrintFault(IoErr(), NULL);
}

void DoUnLockRecord(BPTR fh, struct RDArgs *rdargs)
{
    struct RDArgs *readargs;
    LONG rargs[2];
    ULONG offset, length;
    ULONG result;
    struct LockNode *lnode;

    offset = length = 0;
    rargs[0] = rargs[1] = 0;

    if (readargs = ReadArgs(LOCK_TEMPLATE, rargs, rdargs))
    {

        if (rargs[OFFSET_POS])
            offset = *((LONG *)rargs[OFFSET_POS]);
        if (rargs[LENGTH_POS])
            length = *((LONG *)rargs[LENGTH_POS]);

        rargs[0] = offset;
        rargs[1] = length;

        /* Show what I'm going to do */
        VFPrintf(Output(), "UnLockRecord: Offset %ld, Length %ld...", rargs);
        Flush(Output());

        /* Unlock indicated record with indicated offset and length.
         * If the same record (same offset/length) is locked multiple times,
         * only one, the first one in the list , will be unlocked.
         */
        result = UnLockRecord(fh, offset, length);

        if (result == DOSTRUE) {
            Write(Output(), "OK\n", 3);

            /* Remove node associated with this lock */
            if (lnode = FindRecordLock(offset, length))
            {
                Remove((struct Node *)lnode);
                FreeMem(lnode, sizeof(struct LockNode));
            }
        }
        else
        {
            Write(Output(), "FAILED\n", 7); /* Keep locknode */
            if (IoErr())
                PrintFault(IoErr(), NULL);
        }
        /* Release memory associated with readargs */
        FreeArgs(readargs);
    } else
        PrintFault(IoErr(), NULL);
}

void ListRecordLocks(void)
{
    struct LockNode *lnode;
    LONG rargs[4];

    for (lnode = locklist->lh_Head; lnode->ln_Succ; lnode = lnode->ln_Succ)
    {
        rargs[0] = lnode->ln_Counter;
        rargs[1] = lnode->ln_Offset;
        rargs[2] = lnode->ln_Length;

        switch (lnode->ln_Mode)
        {
            case REC_EXCLUSIVE_IMMED:
                rargs[3] = (LONG)"REC_EXCLUSIVE_IMMED";
                break;
            case REC_EXCLUSIVE:
                rargs[3] = (LONG)"REC_EXCLUSIVE";
                break;
            case REC_SHARED_IMMED:
                rargs[3] = (LONG)"REC_SHARED_IMMED";
                break;
            case REC_SHARED:
                rargs[3] = (LONG)"REC_SHARED";
                break;
        }

        VFPrintf(Output(), "RecordLock #%ld: Offset %ld Length %ld Mode %s\n", rargs);
    }
    Flush(Output());
}

struct LockNode *FindRecordLock(ULONG offset, ULONG length)
{
    struct LockNode *lnode;

    for (lnode = locklist->lh_Head; lnode->ln_Succ; lnode = lnode->ln_Succ)
    {
        if ((lnode->ln_Offset == offset) && lnode->ln_Length == length)
            return(lnode);
    }
    return(NULL);
}


II-87/ExRecLock1.c

;/* ExRecLock1.c - Execute me to compile me with SAS/C 6.56
sc DATA=NEAR NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 ExRecLock1.c
slink FROM LIB:c.o,ExRecLock1.o TO ExRecLock1 LIBRARY LIB:sc.lib,LIB:amiga.lib
quit ;*/

/*
(c)  Copyright 1992-1999 Amiga, Inc.   All rights reserved.
The information contained herein is subject to change without notice,
and is provided "as is" without warranty of any kind, either expressed
or implied.  The entire risk as to the use of this information is
assumed by the user.
*/

/* This is a simple example of using record locking to create an exclusive record    */
/* lock on a file, and writing to that record.  The example ExRecLock2 is almost     */
/* exactly the same as this example, except ExRecLock2 uses the record lock directly */
/* after ExRecLock1's record.  If you try to run ExRecLock1 (or ExRecLock2) while    */
/* another instance of ExRecLock1 (or ExRecLock2) is running, the second record lock */
/* attempt will fail.                                                                */

#include <clib/dos_protos.h>
#include <clib/alib_protos.h>
#include <clib/alib_stdio_protos.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }                    /* Disable Lattice CTRL/C handling */
void chkabort(void) { return; }
#endif

#define RECORDSIZE   12
#define RECORDOFFSET 0

extern struct Library *DOSBase;

UBYTE *vers = "\0$VER: ExRecLock1 37.2";
UBYTE *string = "ExRecLock1\n";                           /* This string will be the */
                                                          /* contents of the record. */
void main(void)
{
    BPTR fh;

    if (DOSBase->lib_Version >= 37)   /* Record locking was introduced in Release 2, */
    {                                 /* but the standard startup code will open any */
                                      /* version of dos.library, so we have to ex-   */
                                      /* plicitly check the version number of DOS.   */

        if (fh = Open("t:testRLock", MODE_READWRITE))     /* Open the file, creating */
        {                                                 /*        it if necessary. */
            if (DOSTRUE == LockRecord(fh,           /* Lock the record as exclusive, */
                                      RECORDOFFSET, /* and do not wait if it is not  */
                                      RECORDSIZE,   /* available immediately.        */
                                      REC_EXCLUSIVE_IMMED, 0))
            {
                LONG error = RECORDOFFSET;

                                     /* If the record is beyond the end of the file, */
                if (Seek(fh, 0, OFFSET_END) < RECORDOFFSET)    /* lengthen the file. */
                    error = SetFileSize(fh, RECORDOFFSET, OFFSET_BEGINNING);

                if (error == RECORDOFFSET)    /* If there was no error with the file */
                {                             /*                file size, continue. */
                    if (Seek(fh, RECORDOFFSET, OFFSET_BEGINNING) < 0)
                        PrintFault(IoErr(), "Seek() error");

                    if (Write(fh, string, RECORDSIZE) < 0)
                        PrintFault(IoErr(), "Write() error");
                    else
                        PutStr("Write successful, ");
                }
                PutStr("Waiting 10 seconds...\n");
                TimeDelay(UNIT_VBLANK, 10, 0);       /* Amiga.lib function that puts */
                          /* a task to sleep for a given amount of time.  This waits */
                          /* 10 seconds before unlocking the record to give the user */
                          /* a chance to start a second copy of this example.        */
                UnLockRecord(fh, RECORDOFFSET, RECORDSIZE);
            }
            else PrintFault(IoErr(), "Record Lock Failed");
            Close(fh);
        }
        else PrintFault(IoErr(), "Open Failed");
    }
    else PutStr("Need dos.library V37 or greater.\n");
}


II-87/ExRecLock2.c

;/* ExRecLock2.c - Execute me to compile me with SAS/C 6.56
sc DATA=NEAR NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 ExRecLock2.c
slink FROM LIB:c.o,ExRecLock2.o TO ExRecLock2 LIBRARY LIB:sc.lib,LIB:amiga.lib
quit ;*/

/*
(c)  Copyright 1992-1999 Amiga, Inc.   All rights reserved.
The information contained herein is subject to change without notice,
and is provided "as is" without warranty of any kind, either expressed
or implied.  The entire risk as to the use of this information is
assumed by the user.
*/

/* This is a simple example of using record locking to create an exclusive record    */
/* lock on a file, and writing to that record.  The example ExRecLock1 is almost     */
/* exactly the same as this example, except ExRecLock1 uses the record lock directly */
/* before ExRecLock2's record.  If you try to run ExRecLock2 (or ExRecLock1) while   */
/* another instance of ExRecLock2 (or ExRecLock1) is running, the second record lock */
/* attempt will fail.                                                                */

#include <clib/dos_protos.h>
#include <clib/alib_protos.h>
#include <clib/alib_stdio_protos.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }                    /* Disable Lattice CTRL/C handling */
void chkabort(void) { return; }
#endif

#define RECORDSIZE   12
#define RECORDOFFSET 12

extern struct Library *DOSBase;

UBYTE *vers = "\0$VER: ExRecLock2 37.2";
UBYTE *string = "ExRecLock2\n";                           /* This string will be the */
                                                          /* contents of the record. */
void main(void)
{
    BPTR fh;

    if (DOSBase->lib_Version >= 37)   /* Record locking was introduced in Release 2, */
    {                                 /* but the standard startup code will open any */
                                      /* version of dos.library, so we have to ex-   */
                                      /* plicitly check the version number of DOS.   */

        if (fh = Open("t:testRLock", MODE_READWRITE))     /* Open the file, creating */
        {                                                 /*        it if necessary. */
            if (DOSTRUE == LockRecord(fh,           /* Lock the record as exclusive, */
                                      RECORDOFFSET, /* and do not wait if it is not  */
                                      RECORDSIZE,   /* available immediately.        */
                                      REC_EXCLUSIVE_IMMED, 0))
            {
                LONG error = RECORDOFFSET;

                                     /* If the record is beyond the end of the file, */
                if (Seek(fh, 0, OFFSET_END) < RECORDOFFSET)    /* lengthen the file. */
                    error = SetFileSize(fh, RECORDOFFSET, OFFSET_BEGINNING);

                if (error == RECORDOFFSET)    /* If there was no error with the file */
                {                             /*                file size, continue. */
                    if (Seek(fh, RECORDOFFSET, OFFSET_BEGINNING) < 0)
                        PrintFault(IoErr(), "Seek() error");

                    if (Write(fh, string, RECORDSIZE) < 0)
                        PrintFault(IoErr(), "Write() error");
                    else
                        PutStr("Write successful, ");
                }
                PutStr("Waiting 10 seconds...\n");
                TimeDelay(UNIT_VBLANK, 10, 0);       /* Amiga.lib function that puts */
                          /* a task to sleep for a given amount of time.  This waits */
                          /* 10 seconds before unlocking the record to give the user */
                          /* a chance to start a second copy of this example.        */
                UnLockRecord(fh, RECORDOFFSET, RECORDSIZE);
            }
            else PrintFault(IoErr(), "Record Lock Failed");
            Close(fh);
        }
        else PrintFault(IoErr(), "Open Failed");
    }
    else PutStr("Need dos.library V37 or greater.\n");
}


II-95/CompareIO.c

;/* CompareIO.c - Execute me to compile me with SAS/C 6.56
sc DATA=FAR NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 CompareIO.c
slink FROM LIB:c.o,CompareIO.o TO CompareIO LIBRARY LIB:sc.lib,LIB:amiga.lib,lib:debug.lib
quit ;*/

/* (c)  Copyright 1992-1999 Amiga, Inc.   All rights reserved.       */
/* The information contained herein is subject to change without notice,  */
/* and is provided "as is" without warranty of any kind, either expressed */
/* or implied.  The entire risk as to the use of this information is      */
/* assumed by the user.                                                   */

/* CompareIO.c uses packet level I/O to copy the standard input channel to the */
/* standard output channel (as set up by the standard startup code, c.o).      */
/* CompareIO uses both synchronous and asynchronous I/O to perform the copy    */
/* and reports the time it takes to do each.                                   */

#include <exec/types.h>
#include <dos/dosextens.h>
#include <devices/timer.h>

#include <clib/dos_protos.h>
#include <clib/timer_protos.h>
#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/alib_stdio_protos.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }                    /* Disable Lattice CTRL/C handling */
void chkabort(void) { return; }
#endif

#define BUFSIZE 8192

UBYTE *vers = "\0$VER: CompareIO 37.14 Nov-12-92";

ULONG AsyncLoop(void);
ULONG SyncLoop(void);

extern struct Library *DOSBase;
struct Library *TimerBase;

struct MsgPort *myport;

struct FileHandle *in, *out;
BPTR results, in_start, out_start;

struct DosPacket *sp_read, *sp_write;

UBYTE buffer[BUFSIZE*2];

struct timeval time_start, time_finish;
struct timerequest timer_io;

ULONG vfprintfargs[2]; /* An array of pointers */

void main(void)
{
  if (DOSBase->lib_Version >= 37)
  {
    if (results = Open("*", MODE_NEWFILE)) /* This is for printing the results.      */
    {                                      /* Since the example is already using the */
                                           /* standard I/O channels for its own      */
                                           /* purposes, there needs to be a separate */
                                           /* channel to output the results.         */
      if (!OpenDevice(TIMERNAME, UNIT_MICROHZ, &timer_io, 0L))
      {
        TimerBase = (struct Library *)timer_io.tr_node.io_Device;

        if (myport = CreateMsgPort())
        {
          in_start  = Input();  /* Need to hold on to input and output so no one can */
          out_start = Output(); /* change them while this example is using them.     */
          if (in = (struct FileHandle *)BADDR(in_start))
          {
            if (out = (struct FileHandle *)BADDR(out_start))
            {
              if (sp_read = AllocDosObject(DOS_STDPKT, NULL))
              {
                if (sp_write = AllocDosObject(DOS_STDPKT, NULL))
                {
                       /* When AllocDosObject() allocates a StandardPacket, it takes */
                       /* care of linking together the Message and DosPacket.        */
                       /* AllocDosObject() points the DosPacket's dp_Link field at   */
                       /* the StandardPacket's Message structure.  It also points    */
                       /* the Message's mn_Node.ln_Name field at the DosPacket:      */
                       /*                 sp_read->dp_Link = sp_Msg;                 */
                       /*                 sp_Msg->mn_Node.ln_Name = (STRPTR)sp_read; */

                  sp_read->dp_Type = ACTION_READ;   /* Fill out ACTION_READ packet.  */
                  sp_read->dp_Arg1 = in->fh_Arg1;

                  sp_write->dp_Type = ACTION_WRITE; /* Fill out ACTION_WRITE packet. */
                  sp_write->dp_Arg1 = out->fh_Arg1;

                  VFPrintf(results, "\n      Method     Seconds   Micros\n", NULL);
                  VFPrintf(results,   "   ------------  -------   ------\n", NULL);

                  GetSysTime(&time_start);
                  if (AsyncLoop())
                  {
                    GetSysTime(&time_finish);
                    SubTime(&time_finish, &time_start);
                    vfprintfargs[0] = time_finish.tv_secs;
                    vfprintfargs[1] = time_finish.tv_micro;
                    VFPrintf(results,
                             "   Asynchronous:  %3ld     %7ld\n", &vfprintfargs[0]);

                    GetSysTime(&time_start);
                    if (SyncLoop())
                    {
                      GetSysTime(&time_finish);
                      SubTime(&time_finish, &time_start);
                      vfprintfargs[0] = time_finish.tv_secs;
                      vfprintfargs[1] = time_finish.tv_micro;
                      VFPrintf(results,
                               "    Synchronous:  %3ld     %7ld\n", &vfprintfargs[0]);
                    }
                    else
                      VFPrintf(results, "         *******  Stop  ******\n", NULL);
                  }
                  else
                    VFPrintf(results, "         *******  Stop  ******\n", NULL);

                  FreeDosObject(DOS_STDPKT, sp_write);
                }
                FreeDosObject(DOS_STDPKT, sp_read);
              }
            }
          }
          DeleteMsgPort(myport);
        }
        CloseLibrary(TimerBase);
      }
      Close(results);
    }
  }
}

ULONG AsyncLoop()
{
struct StandardPacket *mysp;
UBYTE *buf;

LONG amount_read;

BOOL sp_read_busy  = TRUE,                    /*    Is the ACTION_READ packet busy?  */
     sp_write_busy = FALSE,                   /*    Is the ACTION_WRITE packet busy? */
     done          = FALSE;                   /*    Is the program finished?         */
ULONG ok           = TRUE;

  if (!((out->fh_Arg1) && (in->fh_Arg1)))    /* Don't bother if in or out uses NIL:  */
    return(FALSE);
  sp_read->dp_Arg2 = (LONG)buffer;   /* The buffer to fill in.           */
  sp_read->dp_Arg3 = BUFSIZE;        /* The size of the Arg2 buffer.     */

  SendPkt(sp_read, in->fh_Type, myport);   /* Send initial read request. */

  sp_write->dp_Type = ACTION_WRITE; /* Fill out the ACTION_WRITE packet. */
  sp_write->dp_Arg1 = out->fh_Arg1;
  sp_write->dp_Arg2 = (LONG)&buffer[BUFSIZE];  /* Arg2 points to the buffer to write */
  sp_write->dp_Arg3 = 0L;                      /* out.  At first glance, it might    */
  sp_write->dp_Res1 = 0L;                      /* seem odd to bother setting Arg2    */
                                      /* when the program hasn't read anything yet.  */
                                      /* This is to set up for the main loop.  The   */
                                      /* main loop swaps the ACTION_READ buffer with */
                                      /* the ACTION_WRITE buffer when it receives    */
                                      /* a completed read.  Likewise, dp_Arg3 and    */
                                      /* dp_Res1 are set to make the ACTION_READ     */
                                      /* look like it has a valid return value so    */
                                      /* main loop won't fail the first time through */
                                      /* the loop.                                   */

                /* main() has already taken care of sending the initial read to the  */
                /* handler.  Because we need the data from that read before we can   */
  while (!done) /* do anything, the first thing to do is wait for its return.        */
  {
    do                                   /*      Wait for the ACTION_READ to return. */
    {
      WaitPort(myport);
      while (mysp = (struct StandardPacket *)GetMsg(myport))   /* ...empty the port. */
      {
                          /* If this message is the ACTION_READ packet, mark it as   */
                          /* no longer busy so we can use it to start another read.  */
        if (mysp->sp_Pkt.dp_Type == ACTION_READ)    sp_read_busy  = FALSE;

                          /* If this message is instead the ACTION_WRITE packet,     */
                          /* mark it as not busy.  We need to check for this because */
                          /* the WRITE_PACKET from the previous interation through   */
                          /* the loop might have come back before the ACTION_WRITE   */
                          /* from the previous interation.                           */
        else
          if (mysp->sp_Pkt.dp_Type == ACTION_WRITE) sp_write_busy = FALSE;
      }
    } while (sp_read_busy);                   /* End of "wait for ACTION_READ" loop. */

                                          /* Get ready to send the next ACTION_READ. */
    buf = (UBYTE *)(sp_read->dp_Arg2);    /* Hold on to the important stuff from the */
    amount_read = sp_read->dp_Res1;       /* ACTION_READ we just got back so we can  */
                                          /* reuse the packet to start a new read    */
                                          /* while processing the last read's data.  */

    while (sp_write_busy)          /* Because this example only uses two buffers and */
    {                              /* the ACTION_WRITE might be using one of them,   */
                                   /* this example has to wait for an outstanding    */
                                   /* ACTION_WRITE to return before reusing the      */
                                   /* ACTION_WRITE packet's buffer.                  */
      WaitPort(myport);
      while (mysp = (struct StandardPacket *)GetMsg(myport))
        if (mysp->sp_Pkt.dp_Type == ACTION_WRITE) sp_write_busy = FALSE;
    }

    if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
    {
      done = TRUE;
      ok   = FALSE;
    }
    else
    {
               /* This tests the return values from the ACTION_READ and ACTION_WRITE */
               /* packets.  The ACTION_READ packet returns the number of bytes it    */
               /* read in dp_Res1, which was copied earlier into amount_read. If it  */
               /* is 0, the read packet found the EOF.  If it is negative, there was */
               /* an error.  In the case of ACTION_WRITE, an error occurs if the     */
               /* number of bytes that ACTION_WRITE was supposed to write (Arg3)     */
               /* does not match the actual number it wrote, which ACTION_WRITE re-  */
               /* turns in Res1.  This test is the reason dp_Res1 and dp_Arg3 were   */
               /* set to zero when the ACTION_WRITE packet was set up in main().     */
      if ((amount_read > 0) && (sp_write->dp_Res1 == sp_write->dp_Arg3))
      {
        sp_read->dp_Arg2 = sp_write->dp_Arg2;  /* ACTION_WRITE is finished with its  */
                                               /* buffer, use it in the next read.   */

        SendPkt(sp_read, in->fh_Type, myport); /* Send the next ACTION_READ and mark */
        sp_read_busy = TRUE;                   /* the ACTION_READ as busy.           */

        /* Process Buffer.  This example doesn't do anything with the data from the  */
        /* last ACTION_READ, it just passes it on to the STDOUT handler.             */

        sp_write->dp_Arg2 = (LONG)buf;         /*    Set up the ACTION_WRITE packet. */
        sp_write->dp_Arg3 = amount_read;
        SendPkt(sp_write, out->fh_Type, myport);   /* Send the next ACTION_WRITE and */
        sp_write_busy = TRUE;                      /* mark the ACTION_WRITE as busy. */
      }
      else                             /* A packet returned with a failure, so quit. */
      {
        done = TRUE;
        if ((amount_read < 0) || (sp_write->dp_Res1 != sp_write->dp_Arg3)) ok = FALSE;
      }
    }
  }
  return(ok);
}

ULONG SyncLoop()
{
BOOL  done = FALSE;
ULONG ok   = TRUE;
BPTR lock;

  if (!((out->fh_Arg1) && (in->fh_Arg1)))    /* Don't bother if in or out uses NIL:  */
    return(FALSE);

  sp_read->dp_Arg2 = (LONG)buffer;
  sp_read->dp_Arg3 = BUFSIZE*2;
  sp_write->dp_Arg2 = (LONG)buffer;

  if (lock = DupLockFromFH(in_start))
  {
    UnLock(lock);                          /* Make sure this is a filesystem and not */
    Seek(in_start, 0, OFFSET_BEGINNING);   /* a console.  If this is a filesystem,   */
  }                                        /* go to the beginning of the file.       */

  while (!done)
  {
    if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
    {
      done = TRUE;
      ok = FALSE;
    }
    else
    {
      SendPkt(sp_read, in->fh_Type, myport);
      WaitPort(myport);
      while (GetMsg(myport));

      if (sp_read->dp_Res1 > 0)
      {
        sp_write->dp_Arg3 = sp_read->dp_Res1;
        SendPkt(sp_write, out->fh_Type, myport);
        WaitPort(myport);
        while (GetMsg(myport));
        if (sp_write->dp_Res1 != sp_write->dp_Arg3)
        {
          done = TRUE;
          ok   = FALSE;
        }
      }
      else
      {
        done = TRUE;
        if (sp_read->dp_Res1 < 0) ok = FALSE;
      }
    }
  }
  return(ok);
}


II-95/InOutCTRL-C.c

;/* InOutCTRL-C.c - Execute me to compile me with SAS/C 6.56
sc DATA=FAR NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 InOutCTRL-C.c
slink FROM LIB:c.o,InOutCTRL-C.o TO InOutCTRL-C LIBRARY LIB:sc.lib,LIB:amiga.lib,lib:debug.lib
quit ;*/

/* (c)  Copyright 1992-1999 Amiga, Inc.   All rights reserved.       */
/* The information contained herein is subject to change without notice,  */
/* and is provided "as is" without warranty of any kind, either expressed */
/* or implied.  The entire risk as to the use of this information is      */
/* assumed by the user.                                                   */

/* InOutCTRL-C.c uses packets to copy the standard input channel to the        */
/* standard output channel using asynchronous I/O.  This example does a better */
/* job checking for a user break than the accompanying example, CompareIO.c.   */

#include <exec/types.h>
#include <dos/dosextens.h>

#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/alib_stdio_protos.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }                    /* Disable Lattice CTRL/C handling */
void chkabort(void) { return; }
#endif

#define BUFSIZE 8192

UBYTE *vers = "\0$VER: InOutCTRL-C 37.9 Nov-12-92";

void MainLoop(void);

extern struct Library *DOSBase;

struct MsgPort  *myport;
ULONG portsignal, signals, sigmask;

struct FileHandle *in, *out;
struct DosPacket *sp_read, *sp_write;

UBYTE buf1[BUFSIZE], buf2[BUFSIZE];

void main(void)
{
  if (DOSBase->lib_Version >= 37)                                        /* 2.0 only */
  {
    if (myport = CreateMsgPort())
    {
      if (in = (struct FileHandle *)BADDR(Input()))        /* Need file handle to    */
      {                                                    /* get to Handler process */
        if (out = (struct FileHandle *)BADDR(Output()))
        {
          if (sp_read = AllocDosObject(DOS_STDPKT, NULL))    /* Allocate two         */
          {                                                  /* StandardPackets: one */
            if (sp_write = AllocDosObject(DOS_STDPKT, NULL)) /* for reading, and one */
            {                                                /* for writing. */

              sp_read->dp_Type = ACTION_READ;    /* Fill out the ACTION_READ packet. */
              sp_read->dp_Arg1 = in->fh_Arg1;
              sp_read->dp_Arg2 = (LONG)buf1;     /* The buffer to fill in.           */
              sp_read->dp_Arg3 = BUFSIZE;        /* The size of the Arg2 buffer.     */

                       /* When AllocDosObject() allocates a StandardPacket, it takes */
                       /* care of linking together the Message and DosPacket.        */
                       /* AllocDosObject() points the DosPacket's dp_Link field at   */
                       /* the StandardPacket's Message structure.  It also points    */
                       /* the Message's mn_Node.ln_Name field at the DosPacket:      */
                       /*                 sp_read->dp_Link = sp_Msg;                 */
                       /*                 sp_Msg->mn_Node.ln_Name = (STRPTR)sp_read; */

              if (!((out->fh_Arg1) && (in->fh_Arg1)))     /* Don't bother if in or   */
                return;                                   /*          out uses NIL:  */

              SendPkt(sp_read, in->fh_Type, myport);   /* Send initial read request. */

              portsignal = 1L<<myport->mp_SigBit;          /* Record the signal bits */
              sigmask    = SIGBREAKF_CTRL_C | portsignal;  /*         for later use. */

              sp_write->dp_Type = ACTION_WRITE; /* Fill out the ACTION_WRITE packet. */
              sp_write->dp_Arg1 = out->fh_Arg1;
              sp_write->dp_Arg2 = (LONG)buf2;  /* Arg2 points to the buffer to write */
              sp_write->dp_Arg3 = 0L;          /* out.  At first glance, it might    */
              sp_write->dp_Res1 = 0L;          /* seem odd to bother setting Arg2    */
                                      /* when the program hasn't read anything yet.  */
                                      /* This is to set up for the main loop.  The   */
                                      /* main loop swaps the ACTION_READ buffer with */
                                      /* the ACTION_WRITE buffer when it receives    */
                                      /* a completed read.  Likewise, dp_Arg3 and    */
                                      /* dp_Res1 are set to make the ACTION_READ     */
                                      /* look like it has a valid return value so    */
                                      /* main loop won't fail the first time through */
                                      /* the loop.                                   */
              MainLoop();
              FreeDosObject(DOS_STDPKT, sp_write);
            }
            FreeDosObject(DOS_STDPKT, sp_read);
          }
        }
      }
      DeleteMsgPort(myport);
    }
  }
}

void MainLoop()
{
struct StandardPacket *mysp;
UBYTE *buf;

LONG amount_read;

BOOL sp_read_busy  = TRUE,                    /*    Is the ACTION_READ packet busy?  */
     sp_write_busy = FALSE,                   /*    Is the ACTION_WRITE packet busy? */
     done           = FALSE;                  /*    Is the program finished?         */

                /* main() has already taken care of sending the initial read to the  */
                /* handler.  Because we need the data from that read before we can   */
  while (!done) /* do anything, the first thing to do is wait for its return.        */
  {
    do                                   /*      Wait for the ACTION_READ to return. */
    {
      signals = Wait(sigmask);           /*          Wait for port signal or CTRL-C. */

      if (signals & portsignal)          /* If a message arrived at the port, ...    */
      {
        while (mysp = (struct StandardPacket *)GetMsg(myport)) /* ...empty the port. */
        {
                          /* If this message is the ACTION_READ packet, mark it as   */
                          /* no longer busy so we can use it to start another read.  */
          if (mysp->sp_Pkt.dp_Type == ACTION_READ)    sp_read_busy  = FALSE;

                          /* If this message is instead the ACTION_WRITE packet,     */
                          /* mark it as not busy.  We need to check for this because */
                          /* the WRITE_PACKET from the previous interation through   */
                          /* the loop might have come back before the ACTION_WRITE   */
                          /* from the previous interation.                           */
          else
            if (mysp->sp_Pkt.dp_Type == ACTION_WRITE) sp_write_busy = FALSE;
        }
      }

      if (signals & SIGBREAKF_CTRL_C) /* If someone hit CTRL-C, start to quit. */
      {
        done = TRUE;                      /* If the ACTION_READ is still out, try to */
        if (sp_read_busy)                 /* abort it.  As of V39, AbortPkt() does   */
          AbortPkt(in->fh_Type, sp_read); /* not do anything, so this function has   */
      }                                   /* no effect. Maybe a later release of the */
                                          /* OS will support packet aborting.        */

    } while (sp_read_busy);                   /* End of "wait for ACTION_READ" loop. */

                                          /* Get ready to send the next ACTION_READ. */
    buf = (UBYTE *)(sp_read->dp_Arg2);    /* Hold on to the important stuff from the */
    amount_read = sp_read->dp_Res1;       /* ACTION_READ we just got back so we can  */
                                          /* reuse the packet to start a new read    */
                                          /* while processing the last read's data.  */

    while (sp_write_busy)          /* Because this example only uses two buffers and */
    {                              /* the ACTION_WRITE might be using one of them,   */
                                   /* this example has to wait for an outstanding    */
                                   /* ACTION_WRITE to return before reusing the      */
                                   /* ACTION_WRITE packet's buffer.                  */
      signals = Wait(sigmask);

      if (signals & portsignal)           /*  If a message arrived at the port, ...  */
      {                                              /*          ... empty the port. */
        while (mysp = (struct StandardPacket *)GetMsg(myport))
          if (mysp->sp_Pkt.dp_Type == ACTION_WRITE) sp_write_busy = FALSE;
      }

      if (signals & SIGBREAKF_CTRL_C)     /*   If someone hit CTRL-C, start to quit. */
      {
        done = TRUE;                      /* If the ACTION_READ is still out, try to */
        if (sp_write_busy) AbortPkt(out->fh_Type, sp_write);            /* abort it. */
      }
    }

               /* Make sure the user didn't hit CTRL-C.  If the user hit CTRL-C dur- */
    if (!done) /* ing one of the "wait for packet" loops, done == TRUE.  Notice that */
    {          /* this example does not actually break for the CTRL-C until after it */
               /* gets back both packets.                                            */

               /* This tests the return values from the ACTION_READ and ACTION_WRITE */
               /* packets.  The ACTION_READ packet returns the number of bytes it    */
               /* read in dp_Res1, which was copied earlier into amount_read. If it  */
               /* is 0, the read packet found the EOF.  If it is negative, there was */
               /* an error.  In the case of ACTION_WRITE, an error occurs if the     */
               /* number of bytes that ACTION_WRITE was supposed to write (Arg3)     */
               /* does not match the actual number it wrote, which ACTION_WRITE re-  */
               /* turns in Res1.  This test is the reason dp_Res1 and dp_Arg3 were   */
               /* set to zero when the ACTION_WRITE packet was set up in main().     */
      if ((amount_read > 0) && (sp_write->dp_Res1 == sp_write->dp_Arg3))
      {
        sp_read->dp_Arg2 = sp_write->dp_Arg2;  /* ACTION_WRITE is finished with its  */
                                               /* buffer, use it in the next read.   */

        SendPkt(sp_read, in->fh_Type, myport); /* Send the next ACTION_READ and mark */
        sp_read_busy = TRUE;                   /* the ACTION_READ as busy.           */

        /* Process Buffer.  This example doesn't do anything with the data from the  */
        /* last ACTION_READ, it just passes it on to the STDOUT handler.             */

        sp_write->dp_Arg2 = (LONG)buf;         /*    Set up the ACTION_WRITE packet. */
        sp_write->dp_Arg3 = amount_read;
        SendPkt(sp_write, out->fh_Type, myport);   /* Send the next ACTION_WRITE and */
        sp_write_busy = TRUE;                      /* mark the ACTION_WRITE as busy. */
      }
      else                             /* A packet returned with a failure, so quit. */
        done = TRUE;
    }
  }
}


II-107/ASync.doc

TABLE OF CONTENTS

asyncio/CloseAsync
asyncio/OpenAsync
asyncio/ReadAsync
asyncio/ReadCharAsync
asyncio/SeekAsync
asyncio/WriteAsync
asyncio/WriteCharAsync
 asyncio/CloseAsync                                         asyncio/CloseAsync

   NAME
        CloseAsync -- close an async file.

   SYNOPSIS
        success = CloseAsync(file);

        LONG CloseAsync(struct AsyncFile *);

   FUNCTION
        Closes a file, flushing any pending writes. Once this call has been
        made, the file can no longer be accessed.

   INPUTS
        file - the file to close. May be NULL, in which case this function
               returns -1 and sets the IoErr() code to ERROR_INVALID_LOCk.

   RESULT
        result - < 0 for an error, >= 0 for success. Indicates whether closing
                 the file worked or not. If the file was opened in read-mode,
                 then this call will always work. In case of error,
                 dos.library/IoErr() can give more information.

   SEE ALSO
        OpenAsync(), dos.library/Close()
 asyncio/OpenAsync                                           asyncio/OpenAsync

   NAME
        OpenAsync -- open a file for asynchronous IO.

   SYNOPSIS
        file = OpenAsync(fileName, accessMode, bufferSize);

        struct AsyncFile OpenAsync(const STRPTR, UBYTE, LONG);

   FUNCTION
        The named file is opened and an async file handle returned. If the
        accessMode is MODE_READ, an existing file is opened for reading.
        If accessMode is MODE_WRITE, a new file is created for writing. If
        a file of the same name already exists, it is first deleted. If
        accessMode is MODE_APPEND, an existing file is prepared for writing.
        Data written is added to the end of the file. If the file does not
        exists, it is created.

        'fileName' is a filename and CANNOT be a window specification such as
        CON: or RAW:, or "*"

        'bufferSize' specifies the size of the IO buffer to use. There are
        in fact two buffers allocated, each of roughly (bufferSize/2) bytes
        in size. The actual buffer size use can vary slightly as the size
        is rounded to speed up DMA.

        If the file cannot be opened for any reason, the value returned
        will be NULL, and a secondary error code will be available by
        calling the routine dos.library/IoErr().

    INPUTS
        name - name of the file to open, cannot be a window specification
        accessMode - one of MODE_READ, MODE_WRITE, or MODE_APPEND
        bufferSize - size of IO buffer to use. 8192 is recommended as it
                     provides very good performance for relatively little
                     memory.

    RESULTS
        file - an async file handle or NULL for failure. You should not access
               the fields in the AsyncFile structure, these are private to the
               async IO routines. In case of failure, dos.library/IoErr() can
               give more information.

    SEE ALSO
        CloseAsync(), dos.library/Open()
 asyncio/ReadAsync                                           asyncio/ReadAsync

   NAME
        ReadAsync -- read bytes from an async file.

   SYNOPSIS
        actualLength = ReadAsync(file, buffer, numBytes);

        LONG ReadAsync(struct AsyncFile *, APTR, LONG);

   FUNCTION
        This function reads bytes of information from an opened async file
        into the buffer given. 'numBytes' is the number of bytes to read from
        the file.

        The value returned is the length of the information actually read.
        So, when 'actualLength' is greater than zero, the value of
        'actualLength' is the the number of characters read. Usually
        ReadAsync() will try to fill up your buffer before returning. A value
        of zero means that end-of-file has been reached. Errors are indicated
        by a value of -1.

    INPUTS
        file - opened file to read, as obtained from OpenAsync()
        buffer - buffer where to put bytes read
        numBytes - number of bytes to read into buffer

    RESULT
        actualLength - actual number of bytes read, or -1 if an error. In
                       case of error, dos.library/IoErr() can give more
                       information.

    SEE ALSO
        OpenAsync(), CloseAsync(), ReadCharAsync(), WriteAsync(),
        dos.library/Read()
 asyncio/ReadCharAsync                                   asyncio/ReadCharAsync

   NAME
        ReadCharAsync -- read a single byte from an async file.

   SYNOPSIS
        byte = ReadCharAsync(file);

        LONG ReadCharAsync(struct AsyncFile *);

   FUNCTION
        This function reads a single byte from an async file. The byte is
        returned, or -1 if there was an error reading, or if the end-of-file
        was reached.

   INPUTS
        file - opened file to read from, as obtained from OpenAsync()

   RESULT
        byte - the byte read, or -1 if no byte was read. In case of error,
               dos.library/IoErr() can give more information. If IoErr()
               returns 0, it means end-of-file was reached. Any other value
               indicates an error.

   SEE ALSO
        OpenAsync(), CloseAsync(), ReadAsync(), WriteCharAsync()
        dos.library/Read()
 asyncio/SeekAsync                                           asyncio/SeekAsync

   NAME
        SeekAsync -- set the current position for reading or writing within
                     an async file.

   SYNOPSIS
        oldPosition = SeekAsync(file, position, mode);

        LONG SeekAsync(struct AsyncFile *, LONG, BYTE);

   FUNCTION
        SeekAsync() sets the read/write cursor for the file 'file' to the
        position 'position'. This position is used by the various read/write
        functions as the place to start reading or writing. The result is the
        current absolute position in the file, or -1 if an error occurs, in
        which case dos.library/IoErr() can be used to find more information.
        'mode' can be SEEK_START, SEEK_CURRENT or SEEK_END. It is used to
        specify the relative start position. For example, 20 from current
        is a position 20 bytes forward from current, -20 is 20 bytes back
        from current.

        To find out what the current position within a file is, simply seek
        zero from current.

    INPUTS
        file - an opened async file, as obtained from OpenAsync()
        position - the place where to move the read/write cursor
        mode - the mode for the position, one of SEEK_START, SEEK_CURRENT,
               or SEEK_END.

    RESULT
        oldPosition - the previous position of the read/write cursor, or -1
                      if an error occurs. In case of error, dos.library/IoErr()
                      can give more information.

    SEE ALSO
        OpenAsync(), CloseAsync(), ReadAsync(), WriteAsync(),
        dos.library/Seek()
 asyncio/WriteAsync                                         asyncio/WriteAsync

   NAME
        WriteAsync -- write data to an async file.

   SYNOPSIS
        actualLength = WriteAsync(file, buffer, numBytes);

        LONG WriteAsync(struct AsyncFile *, APTR, LONG);

   FUNCTION
        WriteAsync() writes bytes of data to an opened async file. 'numBytes'
        indicates the number of bytes of data to be transferred. 'buffer'
        points to the data to write. The value returned is the length of
        information actually written. So, when 'numBytes' is greater than
        zero, the value of 'numBytes' is the number of characters written.
        Errors are indicated by a return value of -1.

    INPUTS
        file - an opened file, as obtained from OpenAsync()
        buffer - address of data to write
        numBytes - number of bytes to write to the file

    RESULT
        actualLength - number of bytes written, or -1 if error. In case
                       of error, dos.library/IoErr() can give more
                       information.

    SEE ALSO
        OpenAsync(), CloseAsync(), ReadAsync(), WriteCharAsync(),
        dos.library/Write()
 asyncio/WriteCharAsync                                 asyncio/WriteCharAsync

   NAME
        WriteCharAsync -- write a single byte to an async file.

   SYNOPSIS
        result = WriteCharAsync(file, byte);

        LONG WriteCharAsync(struct AsyncFile *, UBYTE);

   FUNCTION
        This function writes a single byte to an async file.

   INPUTS
        file - an opened async file, as obtained from OpenAsync()
        byte - byte of data to add to the file

   RESULT
        result - 1 if the byte was written, -1 if there was an error. In
                 case of error, dos.library/IoErr() can give more information.

   SEE ALSO
        OpenAsync(), CloseAsync(), ReadAsync(), WriteAsync(),
        dos.library/Write()


II-107/ASyncExample.c

;/* ASyncExample.c - Execute me to compile me with SAS/C 6.56
sc data=near nominc strmer streq nostkchk saveds ign=73 AsyncExample.c
slink FROM LIB:c.o,ASyncExample.o TO ASyncExample LIBRARY lib:sc.lib,LIB:Amiga.lib,asyncio.o
quit ;*/

/* (c)  Copyright 1993-1999 Amiga, Inc.   All rights reserved. */
/* The information contained herein is subject to change without    */
/* notice, and is provided "as is" without warranty of any kind,    */
/* either expressed or implied.  The entire risk as to the use of   */
/* this information is assumed by the user.                         */

#include <exec/types.h>
#include <exec/exec.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <stdio.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>

#include "asyncio.h"

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }
#endif

VOID main(VOID)
{
struct AsyncFile *in;
LONG              num;
struct AsyncFile *out;

    if (in = OpenAsync("x", MODE_READ, 8192))
    {
        if (out = OpenAsync("t:test_sync", MODE_WRITE, 8192))
        {
            while ((num = ReadCharAsync(in)) >= 0)
            {
                WriteCharAsync(out,num);
            }
            CloseAsync(out);
        }
        CloseAsync(in);
    }
}


II-107/ASyncIO.c

;/* ASyncIO.c - Execute me to compile with SAS/C 6.56
sc data=near nominc strmer streq nostkchk saveds ign=73 AsyncIO.c
quit
*/

/* (c)  Copyright 1993-1999 Amiga, Inc.   All rights reserved. */
/* The information contained herein is subject to change without    */
/* notice, and is provided "as is" without warranty of any kind,    */
/* either expressed or implied.  The entire risk as to the use of   */
/* this information is assumed by the user.                         */

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <dos/dosextens.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>

#include <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>

#include "asyncio.h"

/*****************************************************************************/

extern struct Library *DOSBase;
extern struct Library *SysBase;

/*****************************************************************************/

/* this macro lets us long-align structures on the stack */
#define D_S(type,name) char a_##name[sizeof(type)+3]; \
                       type *name = (type *)((LONG)(a_##name+3) & ~3);

/*****************************************************************************/

/* send out an async packet to the file system. */
static VOID SendPacket(struct AsyncFile *file, APTR arg2)
{
    file->af_Packet.sp_Pkt.dp_Port = &file->af_PacketPort;
    file->af_Packet.sp_Pkt.dp_Arg2 = (LONG)arg2;
    PutMsg(file->af_Handler, &file->af_Packet.sp_Msg);
    file->af_PacketPending = TRUE;
}

/*****************************************************************************/

/* this function waits for a packet to come back from the file system. If no
 * packet is pending, state from the previous packet is returned. This ensures
 * that once an error occurs, it state is maintained for the rest of the life
 * of the file handle.
 *
 * This function also deals with IO errors, bringing up the needed DOS
 * requesters to let the user retry an operation or cancel it.
 */
static LONG WaitPacket(struct AsyncFile *file)
{
LONG bytes;

    if (file->af_PacketPending)
    {
        /* mark packet as no longer pending since we are going to get it */
        file->af_PacketPending = FALSE;

        while (TRUE)
        {
            /* This enables signalling when a packet comes back to the port */
            file->af_PacketPort.mp_Flags = PA_SIGNAL;

            /* Wait for the packet to come back, and remove it from the message
             * list. Since we know no other packets can come in to the port, we can
             * safely use Remove() instead of GetMsg(). If other packets could come in,
             * we would have to use GetMsg(), which correctly arbitrates access in such
             * a case
             */
            Remove((struct Node *)WaitPort(&file->af_PacketPort));

            /* set the port type back to PA_IGNORE so we won't be bothered with
             * spurious signals
             */
            file->af_PacketPort.mp_Flags = PA_IGNORE;

            bytes = file->af_Packet.sp_Pkt.dp_Res1;
            if (bytes >= 0)
            {
                /* packet didn't report an error, so bye... */
                return(bytes);
            }

            /* see if the user wants to try again... */
            if (ErrorReport(file->af_Packet.sp_Pkt.dp_Res2,
                            REPORT_STREAM,
                            file->af_File,NULL))
                return(-1);

            /* user wants to try again, resend the packet */
            SendPacket(file,file->af_Buffers[file->af_CurrentBuf]);
        }
    }

    /* last packet's error code, or 0 if packet was never sent */
    SetIoErr(file->af_Packet.sp_Pkt.dp_Res2);

    return(file->af_Packet.sp_Pkt.dp_Res1);
}

/*****************************************************************************/

/* this function puts the packet back on the message list of our
 * message port.
 */
static VOID RequeuePacket(struct AsyncFile *file)
{
    AddHead(&file->af_PacketPort.mp_MsgList,&file->af_Packet.sp_Msg.mn_Node);
    file->af_PacketPending = TRUE;
}

/*****************************************************************************/

/* this function records a failure from a synchronous DOS call into the
 * packet so that it gets picked up by the other IO routines in this module
 */
VOID RecordSyncFailure(struct AsyncFile *file)
{
    file->af_Packet.sp_Pkt.dp_Res1 = -1;
    file->af_Packet.sp_Pkt.dp_Res2 = IoErr();
}

/*****************************************************************************/

struct AsyncFile *OpenAsync(const STRPTR fileName, UBYTE accessMode, LONG bufferSize)
{
struct AsyncFile  *file;
struct FileHandle *fh;
BPTR               handle;
BPTR               lock;
LONG               blockSize;
D_S(struct InfoData,infoData);

    handle = NULL;
    file   = NULL;
    lock   = NULL;

    if (accessMode == MODE_READ)
    {
        if (handle = Open(fileName,MODE_OLDFILE))
            lock = DupLockFromFH(handle);
    }
    else
    {
        if (accessMode == MODE_WRITE)
        {
            handle = Open(fileName,MODE_NEWFILE);
        }
        else if (accessMode == MODE_APPEND)
        {
            /* in append mode, we open for writing, and then seek to the
             * end of the file. That way, the initial write will happen at
             * the end of the file, thus extending it
             */

            if (handle = Open(fileName,MODE_READWRITE))
            {
                if (Seek(handle,0,OFFSET_END) < 0)
                {
                    Close(handle);
                    handle = NULL;
                }
            }
        }

        /* we want a lock on the same device as where the file is. We can't
         * use DupLockFromFH() for a write-mode file though. So we get sneaky
         * and get a lock on the parent of the file
         */
        if (handle)
            lock = ParentOfFH(handle);
    }

    if (handle)
    {
        /* if it was possible to obtain a lock on the same device as the
         * file we're working on, get the block size of that device and
         * round up our buffer size to be a multiple of the block size.
         * This maximizes DMA efficiency.
         */

        blockSize = 512;
        if (lock)
        {
            if (Info(lock,infoData))
            {
                blockSize = infoData->id_BytesPerBlock;
                bufferSize =
                    (((bufferSize + blockSize - 1) / blockSize) * blockSize) * 2;
            }
            UnLock(lock);
        }

        /* now allocate the ASyncFile structure, as well as the read buffers.
         * Add 15 bytes to the total size in order to allow for later
         * quad-longword alignement of the buffers
         */

        if (file = AllocVec(sizeof(struct AsyncFile) + bufferSize + 15,MEMF_ANY))
        {
            file->af_File      = handle;
            file->af_ReadMode  = (accessMode == MODE_READ);
            file->af_BlockSize = blockSize;

            /* initialize the ASyncFile structure. We do as much as we can here,
             * in order to avoid doing it in more critical sections
             *
             * Note how the two buffers used are quad-longword aligned. This
             * helps performance on 68040 systems with copyback cache. Aligning
             * the data avoids a nasty side-effect of the 040 caches on DMA.
             * Not aligning the data causes the device driver to have to do
             * some magic to avoid the cache problem. This magic will generally
             * involve flushing the CPU caches. This is very costly on an 040.
             * Aligning things avoids the need for magic, at the cost of at
             * most 15 bytes of ram.
             */

            fh                     = BADDR(file->af_File);
            file->af_Handler       = fh->fh_Type;
            file->af_BufferSize    = bufferSize / 2;
            file->af_Buffers[0]
                = (APTR)(((ULONG)file + sizeof(struct AsyncFile) + 15) & 0xfffffff0);
            file->af_Buffers[1]
                = (APTR)((ULONG)file->af_Buffers[0] + file->af_BufferSize);
            file->af_Offset        = file->af_Buffers[0];
            file->af_CurrentBuf    = 0;
            file->af_SeekOffset    = 0;
            file->af_PacketPending = FALSE;

            /* this is the port used to get the packets we send out back.
             * It is initialized to PA_IGNORE, which means that no signal is
             * generated when a message comes in to the port. The signal bit
             * number is initialized to SIGB_SINGLE, which is the special bit
             * that can be used for one-shot signalling. The signal will never
             * be set, since the port is of type PA_IGNORE. We'll change the
             * type of the port later on to PA_SIGNAL whenever we need to wait
             * for a message to come in.
             *
             * The trick used here avoids the need to allocate an extra signal
             * bit for the port. It is quite efficient.
             */

            file->af_PacketPort.mp_MsgList.lh_Head
                = (struct Node *)&file->af_PacketPort.mp_MsgList.lh_Tail;
            file->af_PacketPort.mp_MsgList.lh_Tail     = NULL;
            file->af_PacketPort.mp_MsgList.lh_TailPred
                = (struct Node *)&file->af_PacketPort.mp_MsgList.lh_Head;
            file->af_PacketPort.mp_Node.ln_Type        = NT_MSGPORT;
            file->af_PacketPort.mp_Flags               = PA_IGNORE;
            file->af_PacketPort.mp_SigBit              = SIGB_SINGLE;
            file->af_PacketPort.mp_SigTask             = FindTask(NULL);

            file->af_Packet.sp_Pkt.dp_Link          = &file->af_Packet.sp_Msg;
            file->af_Packet.sp_Pkt.dp_Arg1          = fh->fh_Arg1;
            file->af_Packet.sp_Pkt.dp_Arg3          = file->af_BufferSize;
            file->af_Packet.sp_Pkt.dp_Res1          = 0;
            file->af_Packet.sp_Pkt.dp_Res2          = 0;
            file->af_Packet.sp_Msg.mn_Node.ln_Name  = (STRPTR)&file->af_Packet.sp_Pkt;
            file->af_Packet.sp_Msg.mn_Node.ln_Type  = NT_MESSAGE;
            file->af_Packet.sp_Msg.mn_Length        = sizeof(struct StandardPacket);

            if (accessMode == MODE_READ)
            {
                /* if we are in read mode, send out the first read packet to
                 * the file system. While the application is getting ready to
                 * read data, the file system will happily fill in this buffer
                 * with DMA transfers, so that by the time the application
                 * needs the data, it will be in the buffer waiting
                 */

                file->af_Packet.sp_Pkt.dp_Type = ACTION_READ;
                file->af_BytesLeft             = 0;
                if (file->af_Handler)
                    SendPacket(file,file->af_Buffers[0]);
            }
            else
            {
                file->af_Packet.sp_Pkt.dp_Type = ACTION_WRITE;
                file->af_BytesLeft             = file->af_BufferSize;
            }
        }
        else
        {
            Close(handle);
        }
    }

    return(file);
}

/*****************************************************************************/

LONG CloseAsync(struct AsyncFile *file)
{
LONG result;

    if (file)
    {
        result = WaitPacket(file);
        if (result >= 0)
        {
            if (!file->af_ReadMode)
            {
                /* this will flush out any pending data in the write buffer */
                result = Write(file->af_File,
                               file->af_Buffers[file->af_CurrentBuf],
                               file->af_BufferSize - file->af_BytesLeft);
            }
        }

        Close(file->af_File);
        FreeVec(file);
    }
    else
    {
        SetIoErr(ERROR_INVALID_LOCK);
        result = -1;
    }

    return(result);
}

/*****************************************************************************/

LONG ReadAsync(struct AsyncFile *file, APTR buffer, LONG numBytes)
{
LONG totalBytes;
LONG bytesArrived;

    totalBytes = 0;

    /* if we need more bytes than there are in the current buffer, enter the
     * read loop
     */

    while (numBytes > file->af_BytesLeft)
    {
        /* drain buffer */
        CopyMem(file->af_Offset,buffer,file->af_BytesLeft);

        numBytes           -= file->af_BytesLeft;
        buffer              = (APTR)((ULONG)buffer + file->af_BytesLeft);
        totalBytes         += file->af_BytesLeft;
        file->af_BytesLeft  = 0;

        bytesArrived = WaitPacket(file);
        if (bytesArrived <= 0)
        {
            if (bytesArrived == 0)
                return(totalBytes);

            return(-1);
        }

        /* ask that the buffer be filled */
        SendPacket(file,file->af_Buffers[1-file->af_CurrentBuf]);

        if (file->af_SeekOffset > bytesArrived)
            file->af_SeekOffset = bytesArrived;

        file->af_Offset      = (APTR)((ULONG)file->af_Buffers[file->af_CurrentBuf]
                                   + file->af_SeekOffset);
        file->af_CurrentBuf  = 1 - file->af_CurrentBuf;
        file->af_BytesLeft   = bytesArrived - file->af_SeekOffset;
        file->af_SeekOffset  = 0;
    }

    CopyMem(file->af_Offset,buffer,numBytes);
    file->af_BytesLeft -= numBytes;
    file->af_Offset     = (APTR)((ULONG)file->af_Offset + numBytes);

    return (totalBytes + numBytes);
}

/*****************************************************************************/

LONG ReadCharAsync(struct AsyncFile *file)
{
unsigned char ch;

    if (file->af_BytesLeft)
    {
        /* if there is at least a byte left in the current buffer, get it
         * directly. Also update all counters
         */

        ch = *(char *)file->af_Offset;
        file->af_BytesLeft--;
        file->af_Offset = (APTR)((ULONG)file->af_Offset + 1);

        return((LONG)ch);
    }

    /* there were no characters in the current buffer, so call the main read
     * routine. This has the effect of sending a request to the file system to
     * have the current buffer refilled. After that request is done, the
     * character is extracted for the alternate buffer, which at that point
     * becomes the "current" buffer
     */

    if (ReadAsync(file,&ch,1) > 0)
        return((LONG)ch);

    /* We couldn't read above, so fail */

    return(-1);
}

/*****************************************************************************/

LONG WriteAsync(struct AsyncFile *file, APTR buffer, LONG numBytes)
{
LONG totalBytes;

    totalBytes = 0;

    while (numBytes > file->af_BytesLeft)
    {
        /* this takes care of NIL: */
        if (!file->af_Handler)
        {
            file->af_Offset    = file->af_Buffers[0];
            file->af_BytesLeft = file->af_BufferSize;
            return(numBytes);
        }

        if (file->af_BytesLeft)
        {
            CopyMem(buffer,file->af_Offset,file->af_BytesLeft);

            numBytes   -= file->af_BytesLeft;
            buffer      = (APTR)((ULONG)buffer + file->af_BytesLeft);
            totalBytes += file->af_BytesLeft;
        }

        if (WaitPacket(file) < 0)
            return(-1);

        /* send the current buffer out to disk */
        SendPacket(file,file->af_Buffers[file->af_CurrentBuf]);

        file->af_CurrentBuf = 1 - file->af_CurrentBuf;
        file->af_Offset     = file->af_Buffers[file->af_CurrentBuf];
        file->af_BytesLeft  = file->af_BufferSize;
    }

    CopyMem(buffer,file->af_Offset,numBytes);
    file->af_BytesLeft -= numBytes;
    file->af_Offset     = (APTR)((ULONG)file->af_Offset + numBytes);

    return (totalBytes + numBytes);
}

/*****************************************************************************/

LONG WriteCharAsync(struct AsyncFile *file, UBYTE ch)
{
    if (file->af_BytesLeft)
    {
        /* if there's any room left in the current buffer, directly write
         * the byte into it, updating counters and stuff.
         */

        *(UBYTE *)file->af_Offset = ch;
        file->af_BytesLeft--;
        file->af_Offset = (APTR)((ULONG)file->af_Offset + 1);

        /* one byte written */
        return(1);
    }

    /* there was no room in the current buffer, so call the main write
     * routine. This will effectively send the current buffer out to disk,
     * wait for the other buffer to come back, and then put the byte into
     * it.
     */

    return(WriteAsync(file,&ch,1));
}

/*****************************************************************************/

LONG SeekAsync(struct AsyncFile *file, LONG position, BYTE mode)
{
LONG  current, target;
LONG  minBuf, maxBuf;
LONG  bytesArrived;
LONG  diff;
LONG  filePos;
LONG  roundTarget;
D_S(struct FileInfoBlock,fib);

    bytesArrived = WaitPacket(file);

    if (bytesArrived < 0)
        return(-1);

    if (file->af_ReadMode)
    {
        /* figure out what the actual file position is */
        filePos = Seek(file->af_File,OFFSET_CURRENT,0);
        if (filePos < 0)
        {
            RecordSyncFailure(file);
            return(-1);
        }

        /* figure out what the caller's file position is */
        current = filePos - (file->af_BytesLeft+bytesArrived);

        /* figure out the absolute offset within the file where we must seek to */
        if (mode == MODE_CURRENT)
        {
            target = current + position;
        }
        else if (mode == MODE_START)
        {
            target = position;
        }
        else /* if (mode == MODE_END) */
        {
            if (!ExamineFH(file->af_File,fib))
            {
                RecordSyncFailure(file);
                return(-1);
            }

            target = fib->fib_Size + position;
        }

        /* figure out what range of the file is currently in our buffers */
        minBuf = current - (LONG)((ULONG)file->af_Offset -
                     (ULONG)file->af_Buffers[1 - file->af_CurrentBuf]);
        maxBuf = current + file->af_BytesLeft
                     + bytesArrived;  /* WARNING: this is one too big */

        diff = target - current;

        if ((target < minBuf) || (target >= maxBuf))
        {
            /* the target seek location isn't currently in our buffers, so
             * move the actual file pointer to the desired location, and then
             * restart the async read thing...
             */

            /* this is to keep our file reading block-aligned on the device.
             * block-aligned reads are generally quite a bit faster, so it is
             * worth the trouble to keep things aligned
             */
            roundTarget = (target / file->af_BlockSize) * file->af_BlockSize;

            if (Seek(file->af_File,roundTarget-filePos,OFFSET_CURRENT) < 0)
            {
                RecordSyncFailure(file);
                return(-1);
            }

            SendPacket(file,file->af_Buffers[0]);

            file->af_SeekOffset = target-roundTarget;
            file->af_BytesLeft  = 0;
            file->af_CurrentBuf = 0;
        }
        else if ((target < current) || (diff <= file->af_BytesLeft))
        {
            /* one of the two following things is true:
             *
             * 1. The target seek location is within the current read buffer,
             * but before the current location within the buffer. Move back
             * within the buffer and pretend we never got the pending packet,
             * just to make life easier, and faster, in the read routine.
             *
             * 2. The target seek location is ahead within the current
             * read buffer. Advance to that location. As above, pretend to
             * have never received the pending packet.
             */

            RequeuePacket(file);

            file->af_BytesLeft -= diff;
            file->af_Offset     = (APTR)((ULONG)file->af_Offset + diff);
        }
        else
        {
            /* at this point, we know the target seek location is within
             * the buffer filled in by the packet that we just received
             * at the start of this function. Throw away all the bytes in the
             * current buffer, send a packet out to get the async thing going
             * again, readjust buffer pointers to the seek location, and return
             * with a grin on your face... :-)
             */

            diff -= file->af_BytesLeft;

            SendPacket(file,file->af_Buffers[1-file->af_CurrentBuf]);

            file->af_Offset
                = (APTR)((ULONG)file->af_Buffers[file->af_CurrentBuf] + diff);
            file->af_CurrentBuf = 1 - file->af_CurrentBuf;
            file->af_BytesLeft  = bytesArrived - diff;
        }
    }
    else
    {
        if (Write(file->af_File,
                  file->af_Buffers[file->af_CurrentBuf],
                  file->af_BufferSize - file->af_BytesLeft) < 0)
        {
            RecordSyncFailure(file);
            return(-1);
        }

        /* this will unfortunately generally result in non block-aligned file
         * access. We could be sneaky and try to resync our file pos at a
         * later time, but we won't bother. Seeking in write-only files is
         * relatively rare (except when writing IFF files with unknown chunk
         * sizes, where the chunk size has to be written after the chunk data)
         */

        current = Seek(file->af_File,position,mode);

        if (current < 0)
        {
            RecordSyncFailure(file);
            return(-1);
        }

        file->af_BytesLeft  = file->af_BufferSize;
        file->af_CurrentBuf = 0;
    }

    return(current);
}


II-107/ASyncIO.h

/* (c)  Copyright 1993-1999 Amiga, Inc.   All rights reserved. */
/* The information contained herein is subject to change without    */
/* notice, and is provided "as is" without warranty of any kind,    */
/* either expressed or implied.  The entire risk as to the use of   */
/* this information is assumed by the user.                         */

#ifndef ASYNCIO_H
#define ASYNCIO_H

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef EXEC_PORTS_H
#include <exec/ports.h>
#endif

#ifndef DOS_DOS_H
#include <dos/dos.h>
#endif

/*****************************************************************************/

/* This structure is public only by necessity, don't muck with it yourself, or
 * you're looking for trouble
 */
struct AsyncFile
{
    BPTR                  af_File;
    ULONG                 af_BlockSize;
    struct MsgPort       *af_Handler;
    APTR                  af_Offset;
    LONG                  af_BytesLeft;
    ULONG                 af_BufferSize;
    APTR                  af_Buffers[2];
    struct StandardPacket af_Packet;
    struct MsgPort        af_PacketPort;
    ULONG                 af_CurrentBuf;
    ULONG                 af_SeekOffset;
    UBYTE                 af_PacketPending;
    UBYTE                 af_ReadMode;
};

/*****************************************************************************/

#define MODE_READ   0  /* read an existing file                             */
#define MODE_WRITE  1  /* create a new file, delete existing file if needed */
#define MODE_APPEND 2  /* append to end of existing file, or create new     */

#define MODE_START   -1   /* relative to start of file         */
#define MODE_CURRENT  0   /* relative to current file position */
#define MODE_END      1   /* relative to end of file         */

/*****************************************************************************/

struct AsyncFile *OpenAsync(const STRPTR fileName, UBYTE accessMode, LONG bufferSize);
LONG CloseAsync(struct AsyncFile *file);
LONG ReadAsync(struct AsyncFile *file, APTR buffer, LONG numBytes);
LONG ReadCharAsync(struct AsyncFile *file);
LONG WriteAsync(struct AsyncFile *file, APTR buffer, LONG numBytes);
LONG WriteCharAsync(struct AsyncFile *file, UBYTE ch);
LONG SeekAsync(struct AsyncFile *file, LONG position, BYTE mode);

/*****************************************************************************/

#endif /* ASYNCIO_H */


II-113/multilist.c

;/* multilist.c -- execute me to compile me
sc data=near nominc strmer streq nostkchk saveds ign=73 multilist
slink FROM LIB:c.o multilist.o TO multilist LIB LIB:sc.lib LIB:amiga.lib
quit
*/

/* This example illustrates how to scan DOS file names without      */
/* having to make a special case for assigns and multiassigns.      */
/* The DoAllAssigns() routine accepts an arbitrary dos path and     */
/* a pointer to a function.  DoAllAssigns() will call this function */
/* passing it a lock to the object named in the path.               */

#define BUFSIZE 1024

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dosextens.h>
#include <dos/exall.h>

#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <stdio.h>
#include <strings.h>

BOOL DoAllAssigns(char *, BOOL (*)());
BOOL ListContents(BPTR);

extern struct DosLibrary *DOSBase;

void main(int argc, char **argv)
{
    if (DOSBase->dl_lib.lib_Version >= 37)
    {
        if (argc > 1)
        {
            (void) DoAllAssigns(argv[1], &ListContents);
        }
    }
}

       /* Pass this routine a directory lock and it prints the names of the  */
       /* files and directories in that directory.  If you pass this routine */
       /* a file lock, it just prints the file's name.                       */
BOOL ListContents(BPTR lock)
{
    struct ExAllControl  *myeac;
    struct ExAllData     *myead;
    APTR                 buffer;
    BOOL                 done;
    struct FileInfoBlock *myfib;

    if (myfib = AllocDosObject(DOS_FIB, NULL))
    {
        if (Examine(lock, myfib) == DOSTRUE)
        {
            if (myfib->fib_DirEntryType > 0)
            {
                if (buffer = AllocVec(BUFSIZE, MEMF_PUBLIC))
                {
                    if (myeac = AllocDosObject(DOS_EXALLCONTROL, NULL))
                    {
                        myeac->eac_LastKey = 0;

                        do
                        {
                            done = ExAll(lock, buffer, BUFSIZE, ED_NAME, myeac);
                            myead = buffer;
                            while (myead)
                            {
                                printf("%s\n", myead->ed_Name);
                                myead = myead->ed_Next;
                            }
                        } while (done != 0);
                        FreeDosObject(DOS_EXALLCONTROL, myeac);
                    }
                    FreeVec(buffer);
                }
            }
            else printf("%s\n", myfib->fib_FileName);
        }
        FreeDosObject(DOS_FIB, myfib);
    }
    return TRUE;
}

/* This routine accepts a path string that may include a device name. From   */
/* that string, this routine locks the object named in the path and calls    */
/* the function passback_func() on the lock.  DoAllAssigns() should work on  */
/* paths with assigns and multiassigns, as well as a filesystem-based device */
/* (i.e. df0:, work:, ram:, etc.)                                            */

BOOL DoAllAssigns(char *dos_path, BOOL (*passback_func)(BPTR lock))
{
    struct DevProc *dp=NULL;
    struct MsgPort *old_fsport;
    BPTR           lock, old_curdir;
    char           *rest_of_path;

    while(dp = GetDeviceProc(dos_path, dp))
    {                                        /* I need to cut the device name from  */
        rest_of_path = strchr(dos_path,':'); /* the front of dos_path so I can give */
                                             /* that substring to Lock().           */
        if (rest_of_path == NULL)                 /* There was no device name to    */
            rest_of_path = dos_path;              /* cut off, use the whole string. */
        else
            rest_of_path++;     /* Increment string pointer to just past the colon. */

        old_fsport = SetFileSysTask(dp->dvp_Port); /* in case dp->dvp_Lock is NULL. */
        old_curdir = CurrentDir(dp->dvp_Lock);     /* Lock() locks relative to the  */
                                /* current directory and falls back to the root of  */
                                /* the current file system if dp->dvp_Lock is NULL. */

        lock = Lock(rest_of_path,SHARED_LOCK);

        (void) SetFileSysTask(old_fsport); /* reset the process' default filesystem */
        (void) CurrentDir(old_curdir);     /* port and current dir to their initial */
                                           /* values for clean up later.            */

        if (lock)
        {
            if (!(*passback_func)(lock))
            {
                printf("function returned false\n");
                UnLock(lock);         /* UnLock() will ignore NULL lock */
                FreeDeviceProc(dp);
                return FALSE;
            }
            UnLock(lock);
        }
    }
    if (IoErr() == ERROR_NO_MORE_ENTRIES)
        return TRUE;               /* At present, a bug in DOS prevents this case, */
    else                           /* so DoAllAssigns() always returns FALSE.      */
        return FALSE;
}


III-1/ISpy.c

;/* Execute me to compile with SAS/C 6.56
sc DATA=NEAR NMINC STRMERGE NODEBUG NOSTKCHK OPTIMIZE IGNORE=73 ispy.c
asm -iINCLUDE: ispy_stubs.asm
slink from lib:c.o ispy.o ispy_stubs.o LIB lib:amiga.lib lib:scnb.lib lib:debug.lib SC SD ND
quit
**      ISpy. AmigaMail SetFunction() example.
**

Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <exec/types.h>
#include <exec/execbase.h>
#include <exec/memory.h>
#include <exec/semaphores.h>
#include <dos/dos.h>
#include <libraries/gadtools.h>
#include <string.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }
#endif

#define ASM __asm __saveds
#define REG(x) register __## x

#ifdef PARALLEL
#define zprintf dprintf
extern VOID     dprintf(STRPTR,...);
#else
#define zprintf kprintf
extern VOID     kprintf(STRPTR,...);
#endif

#ifdef DEBUG
#define D(x) x
#else
#define D(x) ;
#endif

/* Local protos */
VOID            main(VOID);
BOOL            InstallWedge(VOID);
BOOL            RemoveWedge(VOID);
struct JumpTable *GetJumpTable(UBYTE *);

/* Assembler stubs will return a pointer to the caller's stack in a4.
 * The only system function at this moment using a4 is the workbench.library
 * AddAppIconA() function.
 */
#define ACALLER (0)             /* StackPtr[0] = ACaller, StackPtr[1] = saved A6 in stub */
#define CCALLER (2)             /* StackPtr[2] = CCaller */

/* The number of 'replacement' functions */
#define NUMBEROFFUNCTIONS (4)

/* prototypes for the functions to be SetFunction()'ed. */

/* intuition.library */
struct Screen  *(*ASM oldOpenScreen) (REG(a0) struct NewScreen *,
                                      REG(a6) struct Library *);
struct Window  *(*ASM oldOpenWindowTagList) (REG(a0) struct NewWindow *,
                                             REG(a1) struct TagItem *,
                                             REG(a6) struct Library *);
struct Screen  *ASM newOpenScreen(REG(a0) struct NewScreen *,
                                  REG(a4) ULONG *,
                                  REG(a6) struct Library *);
struct Window  *ASM newOpenWindowTagList(REG(a0) struct NewWindow *,
                                         REG(a1) struct TagItem *,
                                         REG(a4) ULONG *,
                                         REG(a6) struct Library *);

/* exec.library */
VOID(*ASM oldFreeMem) (REG(a1) VOID *,
                       REG(d0) ULONG,
                       REG(a6) struct Library *);
VOID ASM        newFreeMem(REG(a1) VOID *,
                           REG(d0) ULONG,
                           REG(a4) ULONG *,
                           REG(a6) struct Library *);

/* graphics.library */
VOID(*ASM oldSetFont) (REG(a1) struct RastPort *,
                       REG(a0) struct TextFont *,
                       REG(a6) struct Library *);
VOID ASM        newSetFont(REG(a1) struct RastPort *,
                           REG(a0) struct TextFont *,
                           REG(a4) ULONG *,
                           REG(a6) struct Library *);

/* Assembler Stubs */
extern          OpenScreenStub();
extern          OpenWindowTagListStub();
extern          FreeMemStub();
extern          SetFontStub();

/* The LVO's to use from amiga.lib */
extern          LVOOpenScreen;
extern          LVOOpenWindowTagList;
extern          LVOFreeMem;
extern          LVOSetFont;

extern struct ExecBase *SysBase;
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;

/* Use a table and an array to make it a little more generic and easier to
 * add functions.
 */
struct LVOTable
{
    LONG            lt_LVO;
    struct Library *lt_LibBase;
    ULONG           lt_oldFunction;
    ULONG           lt_newFunction;
};

struct LVOTable LVOArray[] =
{
    {&LVOOpenScreen, (struct Library *) &IntuitionBase,
        &oldOpenScreen,
        &OpenScreenStub},
    {&LVOOpenWindowTagList, (struct Library *) &IntuitionBase,
                        &oldOpenWindowTagList, &OpenWindowTagListStub},
    {&LVOFreeMem, (struct Library *) & SysBase, &oldFreeMem, &FreeMemStub},
    {&LVOSetFont, (struct Library *) & GfxBase, &oldSetFont, &SetFontStub},
};

struct JumpTable
{
    struct SignalSemaphore jt_Semaphore;
    UWORD           pad_word;
    struct Task    *jt_Owner;
    UBYTE           jt_Function[NUMBEROFFUNCTIONS * 6];
};

/* Strings */
/* The name this JumpTable/Semaphore will get. */
static UBYTE   *JTName = "ISpy-MiscJumpTable";

static UBYTE   *VersTag = "\0$VER: ISpy 37.4 (21.3.91)";
static UBYTE   *VerTitle = "Ispy 37.4";
static UBYTE   *Copyright = "\nCopyright (c) 1991-1999 Amiga, Inc.\n";
static UBYTE   *CBreak = "CTRL-C or BREAK to exit...\n";
VOID
main(VOID)
{

    Write(Output(), (STRPTR) VerTitle, strlen((STRPTR) VerTitle));
    Write(Output(), Copyright, strlen(Copyright));

    if (SysBase->LibNode.lib_Version > 36)
    {
        if (IntuitionBase = OpenLibrary("intuition.library", 37))
        {
            if (GfxBase = OpenLibrary("graphics.library", 37))
            {
                if (InstallWedge())
                {
                    Write(Output(), CBreak, strlen(CBreak));
                    Wait(SIGBREAKF_CTRL_C);
                    RemoveWedge();
                }
                CloseLibrary(GfxBase);
            }
            else
                Write(Output(), "Couldn't open graphics.library\n", 31);
            CloseLibrary(IntuitionBase);
        }
        else
            Write(Output(), "Couldn't open intuition.library\n", 32);
    }
    else
        Write(Output(), "Requires at least Kickstart 2.04\n", 33);
}

BOOL
InstallWedge(VOID)
{
    struct JumpTable *jumptable;
    ULONG          *addressptr;
    UCOUNT          i, j;

    Forbid();

    /* Get pointer to JumpTable. Create it if necessary */
    if (jumptable = GetJumpTable(JTName))
    {
        /* Try to get exclusive lock on semaphore, in case it already existed. */
        if (AttemptSemaphore((struct SignalSemaphore *) jumptable))
        {
            /* Make sure nobody else has function addresses in the jumptable */
            if (jumptable->jt_Owner == NULL)
            {
                jumptable->jt_Owner = FindTask(0);
                /* Don't want to disable any longer than necessary */
                Disable();

                for (i = 2, j = 0; i < NUMBEROFFUNCTIONS * 6; i += 6, j++)
                {
                    /* Replace addresses in the jumptable with my own. */
                    addressptr = (ULONG *) ((UBYTE *) jumptable->jt_Function + i);
                    (*((ULONG *) LVOArray[j].lt_oldFunction)) = (ULONG) * addressptr;
                    *addressptr = (ULONG) LVOArray[j].lt_newFunction;
                    D(zprintf("setting table to Function: 0x%lx\n", *addressptr));
                }
                Enable();
            }
            else
                Write(Output(), "Already running.\n", 16);
            ReleaseSemaphore((struct SignalSemaphore *) jumptable);
        }
        else
            Write(Output(), "Can't lock table.\n", 18);
    }
    else
        Write(Output(), "Can't create jumptable\n", 23);
    Permit();
    return ((BOOL) jumptable);
}

BOOL
RemoveWedge(VOID)
{
    struct JumpTable *jumptable;
    ULONG          *addressptr;
    UCOUNT          i, j;

    Forbid();

    if (jumptable = GetJumpTable(JTName))
    {
        D(zprintf("jumptable @ 0x%lx\n", jumptable));

        /* Check if this task owns this jumptable */
        if (jumptable->jt_Owner == FindTask(0))
        {

            /* Get the semaphore exclusively.
             * Depending on what got SetFunction()'ed this could take some time.
             * Also note that shared locks are used to indicate the code is
             * being executed and that shared locks can jump ahead of queue'ed
             * exclusive locks, adding to the waittime.
             */
            ObtainSemaphore((struct SignalSemaphore *) jumptable);

            Disable();

            /* Restore old pointers in jumptable */

            for (i = 2, j = 0; i < NUMBEROFFUNCTIONS * 6; i += 6, j++)
            {
                addressptr = (ULONG *) ((UBYTE *) jumptable->jt_Function + i);
                *addressptr = (*((ULONG *) LVOArray[j].lt_oldFunction));
                D(zprintf("setting table to oldFunction: 0x%lx\n", *addressptr));
            }

            Enable();

            jumptable->jt_Owner = NULL;
            ReleaseSemaphore((struct SignalSemaphore *) jumptable);
        }
    }

    Permit();

    return (TRUE);
}

struct JumpTable *
GetJumpTable(UBYTE * name)
{
    struct JumpTable *jumptable;
    ULONG          *addressptr;
    UWORD          *jmpinstr;
    UBYTE          *jtname;
    UCOUNT          i, j;

    /* Not really necessary to forbid again, just to indicate that I don't
     * want another task to create the semaphore while I'm trying to do the
     * same. Here GetJumpTable() is only called from InstallWedge(), so it
     * will just bump the forbid count.
     */
    Forbid();

    if (!(jumptable = (struct JumpTable *) FindSemaphore(name)))
    {
        if (jumptable = AllocMem(sizeof(struct JumpTable), MEMF_PUBLIC | MEMF_CLEAR))
        {
            if (jtname = AllocMem(32, MEMF_PUBLIC | MEMF_CLEAR))
            {

                for (i = 0, j = 0; i < NUMBEROFFUNCTIONS * 6; i += 6, j++)
                {
                    jmpinstr = (UWORD *) ((UBYTE *) jumptable->jt_Function + i);
                    *jmpinstr = 0x4EF9;

                    addressptr = (ULONG *) ((UBYTE *) jumptable->jt_Function + i + 2);
                    *addressptr = (ULONG) SetFunction(
                        (struct Library *) (*((ULONG *) LVOArray[j].lt_LibBase)),
                        LVOArray[j].lt_LVO,
                        (VOID *) ((UBYTE *) jumptable->jt_Function + i));
                }

                jumptable->jt_Semaphore.ss_Link.ln_Pri = 0;

                strcpy(jtname, name);
                jumptable->jt_Semaphore.ss_Link.ln_Name = jtname;
                AddSemaphore((struct SignalSemaphore *) jumptable);
                /* In 1.2/1.3 AddSemaphore() didn't work properly.
                ** Under 1.2/1.3, change it to:
                ** InitSemaphore(jumptable);
                ** Forbid();
                ** Enqueue(&SysBase->SemaphoreList, jumptable);
                ** Permit();
                */
            }
            else
            {
                FreeMem(jumptable, sizeof(struct JumpTable));
                jumptable = NULL;
            }
        }
    }

    Permit();

    /* If succeeded, you now have a jumptable which entries point to the original
     * library functions. If another task SetFunction()'ed one or more of those
     * already, that task can never go away anymore.
     */
    return (jumptable);
}

/* Note: if you'd want this to work with 1.3, you wouldn't/couldn't lock the
 * semaphore, but instead would have to use a global to in- and decrement.
 * When exiting, you'd spin around the global counter, waiting for it to reach
 * zero. At that point you'd Disable(), reset the pointers in the jumptable and
 * Enable() again.
 */

struct Screen  *ASM
newOpenScreen(REG(a0) struct NewScreen * newscreen,
              REG(a4) ULONG * stackptr,
              REG(a6) struct Library * base)
{
    struct SignalSemaphore *jt;
    struct Screen  *screen = NULL;

    /* Find the semaphore to lock shared, indicating the routine is being run. */
    /* For speed reasons you may want to cache the pointer to the semaphore
    ** in a global variable */
    if (jt = FindSemaphore(JTName))
    {
        /* Lock shared in 2.0. In 1.3 you'd increment a global counter */
        ObtainSemaphoreShared(jt);
        /* Simple test for valid argument. Could check all the fields too. */
        if (newscreen != NULL)
        {
            screen = (*oldOpenScreen) (newscreen, base);
        }
        else
        {
            ULONG           ACaller = stackptr[ACALLER];
            ULONG           CCaller = stackptr[CCALLER];

            Forbid();           /* To make sure the output isn't garbled */
            zprintf("OpenScreen(NULL) by `%s' (at 0x%lx) from A:0x%lx C:0x%lx SP:0x%lx\n",
                    SysBase->ThisTask->tc_Node.ln_Name,
                    SysBase->ThisTask,
                    ACaller,
                    CCaller,
                    stackptr);
            Permit();
        }
        /* Release shared lock. In 1.3  you'd decrement the global pointer */
        ReleaseSemaphore(jt);
    }

    return (screen);
}

struct Window  *ASM
newOpenWindowTagList(REG(a0) struct NewWindow * newwindow,
                     REG(a1) struct TagItem * tags,
                     REG(a4) ULONG * stackptr,
                     REG(a6) struct Library * base)
{
    struct SignalSemaphore *jt;
    struct Window  *window = NULL;

    if (jt = FindSemaphore(JTName))
    {
        ObtainSemaphoreShared(jt);
        if (newwindow != NULL || tags != NULL)
        {
            window = (*oldOpenWindowTagList) (newwindow, tags, base);
        }
        else
        {
            ULONG           ACaller = stackptr[ACALLER];
            ULONG           CCaller = stackptr[CCALLER];

            Forbid();
            zprintf("OpenWindowTagList(NULL,NULL) by `%s' (at 0x%lx) from A:0x%lx C:0x%lx SP:0x%lx\n",
                    SysBase->ThisTask->tc_Node.ln_Name,
                    SysBase->ThisTask,
                    ACaller,
                    CCaller,
                    stackptr);
            Permit();
        }
        ReleaseSemaphore(jt);
    }

    return (window);
}

VOID ASM
newFreeMem(REG(a1) VOID * memptr,
           REG(d0) ULONG size,
           REG(a4) ULONG * stackptr,
           REG(a6) struct Library * base)
{
    struct SignalSemaphore *jt;

    if (jt = FindSemaphore(JTName))
    {
        ObtainSemaphoreShared(jt);
        if (memptr != NULL && size != 0L)
        {
            (*oldFreeMem) (memptr, size, base);
        }
        else
        {
            ULONG           ACaller = stackptr[ACALLER];
            ULONG           CCaller = stackptr[CCALLER];

            Forbid();
            zprintf("FreeMem(0x%lx,%ld) by `%s' (at 0x%lx) from A:0x%lx C:0x%lx SP:0x%lx\n",
                    memptr, size,
                    SysBase->ThisTask->tc_Node.ln_Name,
                    SysBase->ThisTask,
                    ACaller,
                    CCaller,
                    stackptr);
            Permit();
        }

        ReleaseSemaphore(jt);
    }
}

VOID ASM
newSetFont(REG(a1) struct RastPort * rp,
           REG(a0) struct TextFont * font,
           REG(a4) ULONG * stackptr,
           REG(a6) struct Library * base)
{
    struct SignalSemaphore *jt;

    if (jt = FindSemaphore(JTName))
    {
        ObtainSemaphoreShared(jt);
        if (rp != NULL && font != NULL)
        {
            (*oldSetFont) (rp, font, base);
        }
        else
        {
            ULONG           ACaller = stackptr[ACALLER];
            ULONG           CCaller = stackptr[CCALLER];

            Forbid();
            zprintf("SetFont(0x%lx,0x%lx) by `%s' (at 0x%lx) from A:0x%lx C:0x%lx SP:0x%lx\n",
                    rp, font,
                    SysBase->ThisTask->tc_Node.ln_Name,
                    SysBase->ThisTask,
                    ACaller,
                    CCaller,
                    stackptr);
            Permit();
        }
        ReleaseSemaphore(jt);
    }
}


III-1/Ispy_stubs.asm

**
**      ISpy stubs
**
**
** Copyright (c) 1991-1999 Amiga, Inc.
**
** This example is provided in electronic form by Amiga,
** Inc. for use with the Amiga Mail Volume II technical publication.
** Amiga Mail Volume II contains additional information on the correct
** usage of the techniques and operating system functions presented in
** these examples.  The source and executable code of these examples may
** only be distributed in free electronic form, via bulletin board or
** as part of a fully non-commercial and freely redistributable
** diskette.  Both the source and executable code (including comments)
** must be included, without modification, in any copy.  This example
** may not be published in printed form or distributed with any
** commercial product. However, the programming techniques and support
** routines set forth in these examples may be used in the development
** of original executable software products for Amiga
** computers.
**
** All other rights reserved.
**
** This example is provided "as-is" and is subject to change; no
** warranties are made.  All use is at your own risk. No liability or
** responsibility is assumed.
**
**
    INCLUDE "exec/types.i"

    SECTION CODE

    XREF	_SysBase

    XREF    _LVOForbid
    XREF    _LVOPermit

    XREF	_newOpenScreen
    XREF	_newOpenWindowTagList
    XREF	_newFreeMem
    XREF	_newSetFont

    XDEF	_OpenScreenStub
    XDEF	_OpenWindowTagListStub
    XDEF	_FreeMemStub
    XDEF	_SetFontStub

_OpenScreenStub:
    movem.l	a4,-(sp)
    lea		4(sp),a4
    jsr		_newOpenScreen
    movem.l	(sp)+,a4
    rts

_OpenWindowTagListStub:
    movem.l	a4,-(sp)
    lea		4(sp),a4
    jsr		_newOpenWindowTagList
    movem.l	(sp)+,a4
    rts

_FreeMemStub:
    movem.l	a4,-(sp)
    lea		4(sp),a4
    jsr		_newFreeMem
    movem.l	(sp)+,a4
    rts

_SetFontStub:
    movem.l	a4,-(sp)
    lea		4(sp),a4
    jsr		_newSetFont
    movem.l	(sp)+,a4
    rts

    END


III-17/SIGF_Single.c

;/* SIGF_Single.c - Execute me to compile me with SAS/C 6.56
sc DATA=NEAR NMINC STRMERGE NOSTKCHK SAVEDS IGNORE=73 SIGF_Single.c
slink FROM LIB:c.o,SIGF_Single.o TO SIGF_Single LIBRARY LIB:amiga.lib,LIB:sc.lib
quit ;*/

/*
(c)  Copyright 1992-1999 Amiga, Inc.   All rights reserved.
The information contained herein is subject to change without notice,
and is provided "as is" without warranty of any kind, either expressed
or implied.  The entire risk as to the use of this information is
assumed by the user.
*/

/* This example program illustrates simple usage of the SIGF_SINGLE */
/* signal for "single shot" signalling.  This signal is one of the  */
/* system private signals, but applications can use it in certain   */
/* cases, but only if used carefully.  Specifically, applications   */
/* should use it only to Wait() on, and using only that signal      */
/* (applications cannot Wait() on other signals in the same         */
/* Wait()).  Not following these rules can cause serious system     */
/* problems. For more details, see the Amiga Mail article,          */
/* "Signalling with SIGF_SINGLE" from the September/October 1992    */
/* issue of Amiga Mail.                                             */

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dosextens.h>
#include <dos/dostags.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/alib_protos.h>
#include "stdio.h"

#ifdef LATTICE
int CXBRK(void) { return(0); }     /* Disable Lattice CTRL/C handling. */
int chkabort(void) { return(0); }  /* really */
#endif

static UBYTE *VersTag = "$VER: SIGF_Single 38.8 (28.2.96)";

void childprocesscode(void);      /* prototype for our childprocess routine. */

struct Process *mainprocess = NULL, *childprocess = NULL;
UBYTE childprocessname[] = "RKM_signal_childprocess";

BPTR output;

void main(int argc, char **argv)
{
    if (output = Open("*", MODE_OLDFILE))       /* Open the console for the  */
                                                /*            child process. */
    {
        mainprocess = (struct Process *)FindTask(NULL);/* childprocess can   */
                                                       /* access this global.*/

        if (childprocess = CreateNewProcTags(
                    NP_Entry,       childprocesscode,  /* The child process  */
                    NP_StackSize,   2000L,             /*              code. */
                    NP_Name,        childprocessname,
                    NP_Output,      output,
                    NP_FreeSeglist, FALSE,
                    NP_CloseOutput, TRUE,
                    TAG_DONE,       0L))

        {                                   /* I split the PutStr() into two */
            PutStr("Main Process: Created a child process"); /* to fit code  */
            PutStr(" and waiting on SIGF_SINGLE.\n");        /* on an 8.5 by */
                                                             /* 11 page.     */

            Flush(Output());    /* Make sure the PutStr() above appears      */
                                /* in the console window before the child    */
                                /* process start PutStr()ing to the console. */

            SetSignal(0L, SIGF_SINGLE);        /* Use SIGF_SINGLE only after */
                                               /* clearing it.               */

            /* Wake up the child. */
            Signal((struct Task *)childprocess,SIGBREAKF_CTRL_F);

            Wait(SIGF_SINGLE);     /* Only use SIGF_SINGLE for Wait()ing and */
                                   /* Wait on that signal alone!             */

            PutStr("Main Process: Received signal from child.\n");
        }
        else
            PutStr("Main Process: Can't create child process. Exiting.\n");
    }
    else
        PutStr("Main Process: Can't open CON:.  Exiting.\n");
}

void childprocesscode(void)     /* This function is what CreateNewProcTags() */
{                               /* loads as the child process.  This child   */
                                /* signals the parent using SIGF_SINGLE.     */
    ULONG x;

    /* Wait for a startup signal. This is to allow the parent process to
     * print its banner message and clear SIGF_SINGLE.
     */
    Wait(SIGBREAKF_CTRL_F);

    PutStr("Child Process: I'm alive and starting a 5 second TimeDelay()");
    Flush(Output());

    for (x = 0; x < 5; x++)
    {
        TimeDelay(UNIT_VBLANK, 1, 0);     /* Delay for 5 seconds, printing a */
        FPuts(Output(), " .");            /* dot during each second.         */
        Flush(Output());
    }

    TimeDelay(UNIT_VBLANK, 1, 0);

    PutStr(" Finished.\n");
    PutStr("Child Process: Signalling main process and exiting.  Bye.\n");
    Flush(Output());

    Signal((struct Task *)mainprocess, SIGF_SINGLE);    /* Finished waiting, */
                                                        /* signal the main   */
                                                        /* process and exit  */
                                                        /* child process.    */
}


III-19/PoolTime.c

;/*  Pooltime.c
sc DATA=NEAR NMINC STRMERGE NOSTKCHK SAVEDS IGNORE=73 pooltime
slink FROM LIB:c.o pooltime.o TO pooltime LIB LIB:sc.lib LIB:amiga.lib
quit

This program demonstrates the use of a memory pool to allocate memory
for two timerequest structures.  Before pools, the memory required for
the timerequests was allocated using AllocMem().
*/

/* (c)  Copyright 1993-1999 Amiga, Inc.   All rights reserved. */
/* The information contained herein is subject to change without    */
/* notice, and is provided "as is" without warranty of any kind,    */
/* either expressed or implied.  The entire risk as to the use of   */
/* this information is assumed by the user.                         */

#include <exec/types.h>
#include <exec/memory.h>
#include <devices/timer.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }     /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

VOID main(VOID);

void main()
{
struct timerequest *TimerIO[3];
struct MsgPort *TimerMP;
struct Message *TimerMSG;
APTR *TimerPool;            /* pointer to memory pool */
ULONG x,seconds[3]={4,1,2}, microseconds[3]={0,0,0};
int allin = 3;
char *position[]={"last","second","first"};

if (TimerMP = CreateMsgPort())
    {
    if (TimerIO[0] = CreateIORequest(TimerMP,sizeof(struct timerequest)) )
        {
        if (!OpenDevice(TIMERNAME, UNIT_VBLANK,(struct IORequest *) TimerIO[0], 0L))
            {
            /* Set command to TR_ADDREQUEST */
            TimerIO[0]->tr_node.io_Command = TR_ADDREQUEST;

                /* Create the memory pool */
            if (TimerPool = CreatePool(MEMF_FAST,400,200))
                {
                     /* Allocate pooled memory from TimerPool */
                if (TimerIO[1]=(struct timerequest *)
                        AllocPooled(TimerPool,sizeof(struct timerequest)))
                    {
                        /* Allocate pooled memory from TimerPool */
                    if (TimerIO[2]=(struct timerequest *)
                            AllocPooled(TimerPool,sizeof(struct timerequest)))
                        {
                        /* Copy fields from request used to open the timer device */
                        *TimerIO[1] = *TimerIO[0];
                        *TimerIO[2] = *TimerIO[0];

                        /* Initialize other fields */
                        for (x=0;x<3;x++)
                            {
                            TimerIO[x]->tr_time.tv_secs   = seconds[x];
                            TimerIO[x]->tr_time.tv_micro  = microseconds[x];
                            }

                        printf("\n\nSending multiple requests\n\n");

                        /* Send multiple requests asynchronously */
                        SendIO(TimerIO[0]);
                        SendIO(TimerIO[1]);
                        SendIO(TimerIO[2]);

                        /* Now go to sleep with WaitPort() waiting for the requests */
                        while (allin)
                              {
                              WaitPort(TimerMP);
                              TimerMSG=GetMsg(TimerMP);  /* Get the reply message */
                              for (x=0;x<3;x++)
                                if (TimerMSG==(struct Message *)TimerIO[x])
                                    printf("Request %ld finished %s\n",
                                           x,position[--allin]);
                              }
                        }
                    else
                        printf("Error: Could not allocate memory for TimerIO[2]\n");
                    }
                else
                    printf("Error: Could not allocate memory for TimerIO[1]\n");

                /* Delete the entire pool.  You could also free each individual
                 * allocation using FreePooled(), but this is quicker because a pool's
                 * puddles are automatically drained when you delete the pool.
                 */
                DeletePool(TimerPool);
                }
            else
                printf("Error: Could not allocate memory pool\n");

            CloseDevice(TimerIO[0]);
            }
        else
            printf("Error: Could not open %s\n", TIMERNAME);

        DeleteIORequest(TimerIO[0]);
        }
    else
        printf("Error: could not create IORequest\n");

    DeleteMsgPort(TimerMP);
    }
else
    printf("Error: Could not create message port\n");
}


III-29/Armadillo_lib.fd

*
* armadillo.library - Sample SAS/C run-time library
*
* © Copyright Amiga, Inc.
* All Rights Reserved.
*
##base _DilloBase
##bias 30
##public
CreateArmadillo()()
DeleteArmadillo(dillo)(A0)
NameArmadillo(dillo,name,len)(A0/A1,D0)
FillArmadillo(dillo,weight)(A0,D0)
FlattenArmadillo(dillo,flat)(A0,D0)
DilloFlat(dillo)(A0)
DilloWeight(dillo)(A0)
DilloName(dillo,buf,len)(A0/A1,D0)
ClearDillo(dillo)(A0)
DilloBirths()()
##end


III-29/dillo.c

/*
**  dillo.c
**
**  A code module of armadillo.library, which implements the main library
**  functions.  Strictly do-nothing code for example.
**
**  © Copyright 1993-1999, Amiga, Inc. All Rights Reserved.
**  Written by John Wiederhirn
**
*/

#include    <exec/types.h>
#include    <exec/memory.h>
#include    <clib/exec_protos.h>
#include    <pragmas/exec_pragmas.h>

extern struct ExecBase *SysBase;	/* olsen 30-Jan-96 */

#include    "dillo.h"
#include    "dillo_protos.h"

/* The next prototype is for a static function which is only available
** to code inside the library itself.
*/

static void ClearDilloName(struct Armadillo * );

/* The following global data item becomes part of the near data section
** for each library client.  Since this library is designed to give a
** different library base to each client, this data item is unique per
** client.
**
** It holds the number of armadillos a given client has open at once.
*/

ULONG TotalDillos = 0L;

/* In contrast to the previous global data item, the following goes in
** the far data section and is global to all library clients.  Read access
** doesn't need arbitration, but write access needs a semaphor or use of
** a Forbid()/Permit() pair (see CreateDillo() below).
**
** It holds the number of times CreateDillo has been called overall.
*/

ULONG __far TotalDillosCreated = 0L;

/* This routine just allocates a `struct Armadillo', and increments
** the number of armadillos this client has by one.  If the allocation
** cannot be done, this routine returns NULL.
*/

struct Armadillo * __saveds __asm
LIBCreateArmadillo( register __a6 struct Library *DilloBase )
{
    struct Armadillo *newdillo = NULL;

    if ( newdillo = AllocMem( sizeof(struct Armadillo), MEMF_CLEAR ))
    {
        /* Armadillo allocated, so increment number of dillos.
        ** Note that to reference the client-unique data takes no
        ** special coding.
        */

        TotalDillos++;

        /* Since we've also added to the overall number created, we
        ** need to also update the TotalDillosCreated variable in
        ** the far data section.  That means a Forbid() and Permit()
        ** around the action (which MUST complete).
        */

        Forbid();
        TotalDillosCreated++;
        Permit();

    }

    /* And return either the address of the new armadillo, or else
    ** return NULL if the allocation failed.
    */

    return( newdillo );
}

/* This function wipes an existing Armadillo structure out of existance
** and decrements the number of Armadillos for this client.  Note that the
** number of Armadillos created overall does not go down.
*/

VOID __saveds __asm
LIBDeleteArmadillo( register __a0 struct Armadillo *dillo,
                    register __a6 struct Library *DilloBase )
{
    /* This routine is ``safe'' in that it can handle being given a NULL
    ** pointer (in which case it does nothing).
    */

    if ( dillo )
    {
        /* We do indeed appear to have an armadillo on our hands
        ** so we decrement the overall count and deallocate the
        ** memory it uses.
        */

        TotalDillos--;

        FreeMem( dillo, sizeof( struct Armadillo ));
    }

    return;
}

/* This transfers the contents of a string up to 32 characters long into
** the name buffer of an Armadillo.  Any attempt to transfer more than 32
** characters gets truncated to 32 characters.  Returns FALSE if dillo
** was a NULL pointer, the pointer to the string was NULL, or the length
** of the transfer was to be 0L.
*/

BOOL __saveds __asm
LIBNameArmadillo( register __a0 struct Armadillo *dillo,
                  register __a1 STRPTR dname,
                  register __d0 ULONG len,
                  register __a6 struct Library *DilloBase )
{
    BOOL retval = FALSE;

    /* This routine is ``safe'' in that it can handle being given a NULL
    ** pointer (in which case it does nothing).
    */

    if ( dillo && dname && len )
    {
        CopyMem( (APTR) dname, (APTR) &(dillo->name), ((len>31L)?32L:len) );
        retval = TRUE;
    }

    return( retval );
}

/* Assigns a value to the weight field of an Armadillo structure.  It
** returns NULL if a NULL pointer is passed in or amt was 0L.
*/

BOOL __saveds __asm
LIBFillArmadillo( register __a0 struct Armadillo *dillo,
                  register __d0 ULONG amt,
                  register __a6 struct Library *DilloBase )
{
    BOOL retval = FALSE;

    /* This routine is ``safe'' in that it can handle being given a NULL
    ** pointer (in which case it does nothing).
    */

    if ( dillo && amt )
    {
        dillo->weight = amt;
        retval = TRUE;
    }

    return( retval );
}

/* In homage to the Texas state animal, the roadkill armadillo, this function
** sets whether a given Armadillo is flattened or not.  Returns NULL if a
** NULL pointer was passed as the Armadillo structure.
*/

BOOL __saveds __asm
LIBFlattenArmadillo( register __a0 struct Armadillo *dillo,
                     register __d0 BOOL flatd,
                     register __a6 struct Library *DilloBase )
{
    BOOL retval = FALSE;

    /* This routine is ``safe'' in that it can handle being given a NULL
    ** pointer (in which case it does nothing).
    */

    if ( dillo )
    {
        dillo->flat = flatd;
        retval = TRUE;
    }

    return( retval );
}

/* Returns whether or not the Armadillo has been flattened.  If a NULL
** pointer is passed in, this function returns FALSE (not really distinct).
*/

BOOL __saveds __asm
LIBDilloFlat( register __a0 struct Armadillo *dillo,
              register __a6 struct Library *DilloBase )
{
    BOOL retval = FALSE;

    /* This routine is ``safe'' in that it can handle being given a NULL
    ** pointer (in which case it returns FALSE).
    */

    if ( dillo )
    {
        retval = dillo->flat;
    }

    return( retval );
}

/* Returns the weight of a given Armadillo or 0L if a NULL pointer
** is passed instead of an Armadillo (no pointer == no weight ).
*/

ULONG __saveds __asm
LIBDilloWeight( register __a0 struct Armadillo *dillo,
                register __a6 struct Library *DilloBase )
{
    ULONG retval = 0L;

    /* This routine is ``safe'' in that it can handle being given a NULL
    ** pointer (in which case it returns 0L).
    */

    if ( dillo )
    {
        retval = dillo->weight;
    }

    return( retval );
}

/* This function copies the name of an Armadillo into the caller-specified
** buffer (which MUST be at least 32 characters in length).  A NULL pointer
** for the Armadillo, buffer or len will get a FALSE return, otherwise a
** return of TRUE if the transfer occurred.
*/

BOOL __saveds __asm
LIBDilloName( register __a0 struct Armadillo *dillo,
              register __a1 STRPTR buf,
              register __d0 ULONG len,
              register __a6 struct Library *DilloBase )
{
    BOOL retval = FALSE;

    /* This routine is ``safe'' in that it can handle being given a NULL
    ** pointer (in which case it does nothing).
    */

    if ( dillo && buf && len)
    {
        CopyMem( (APTR) &(dillo->name), (APTR) buf, ((len>31L)?32L:len) );
        retval = TRUE;
    }

    return( retval );
}

/* Following are non-public but externally-accessible entry points. */

/* This routine clears out the contents of an Armadillo.  It also is an
** example of using a non-public non-ext.-accessible routine in a shared
** library.
*/

VOID __saveds __asm
LIBClearDillo( register __a0 struct Armadillo *dillo,
               register __a6 struct Library *DilloBase )
{
    /* This routine is ``safe'' in that it can handle being given a NULL
    ** pointer (in which case it does nothing).
    */

    if ( dillo )
    {
        dillo->flat = FALSE;
        dillo->weight = 0L;
        ClearDilloName( dillo );
    }
}

/* This routine does an "unprotected" query (legal, since the access is
** read-only) of the TotalDillosCreated variable in the far data section.
*/

ULONG __saveds __asm
LIBDilloBirths( register __a6 struct Library *DilloBase )
{
    return( TotalDillosCreated );
}

/* Following call is a non-public non-externally-accessible function */

/* This function is callable ONLY from within this module.  It clears out
** the name buffer for a given Armadillo.
*/

static VOID
ClearDilloName( struct Armadillo *dillo )
{
    int i;

    /* This routine is NOT 'safe'.  Params must be pre-checked. */

    for(i=0;i<31;i++)
        dillo->name[i] = '\0';

}


III-29/dillo.h

#ifndef DILLO_H
#define DILLO_H

/*
**  dillo.h - Header file for armadillo.library code modules
**            © Copyright 1993-1999, Amiga, Inc.
**            All Rights Reserved.
**            Written by John Wiederhirn
**
**  This is the header file for the armadillo.library code modules.  It
**  just gives a basic structure definition.
**
*/

struct Armadillo
{
    UBYTE   name[32];
    ULONG   weight;
    BOOL    flat;
};

#endif /* DILLO_H */


III-29/dillo_lib.c

/*
**  dillo_lib.c
**
**  Contains the __UserLibInit() and __UserLibCleanup() routines for
**  the armadillo.library example shared library.
**
**  © Copyright 1993-1999, Amiga, Inc. All Rights Reserved.
**  Written by John Wiederhirn
**
*/

#include    <exec/types.h>
#include    <clib/exec_protos.h>
#include    <pragmas/exec_pragmas.h>

/* These prototypes are just to keep the compiler happy since we don't
** want them in the distributable proto file.
*/

int __saveds __UserLibInit(void);
void __saveds __UserLibCleanup(void);

/* Following global item (UtilityBase) is created so our library can make
** utility.library calls.  Technically putting it in the near section is a waste
** of memory, but for this example, it serves its purpose.  Note also that we
** don't actually MAKE any Utility calls, but we COULD.
*/

struct Library *UtilityBase = NULL;
struct Library *SysBase = NULL;

/*
*/

int __saveds
__UserLibInit( void )
{
    int retval = 1;

    SysBase = (*((void **)4));

    /* Here we attempt to open Utility library.  Not a particularly good
    ** example, but it gets the point across.  If exec.library could not
    ** be opened (say for a second it couldn't), then __UserLibInit would
    ** return 1 indicating failure (where a return of 0 means success).
    */

    if (UtilityBase = OpenLibrary( "utility.library", 0L ))
        retval = 0;

    return( retval );
}

/* About as basic a routine as you can get, this routine cleans up the library
** by providing a matching CloseLibrary of the Utility library base we opened
** in the __UserLibInit() routine.
*/

void __saveds
__UserLibCleanup( void )
{
    CloseLibrary( UtilityBase );
}


III-29/dillo_protos.h

#ifndef DILLO_PROTOS_H
#define DILLO_PROTOS_H

/*
**  dillo_protos.h - Header file for armadillo.library code modules
**                   © Copyright 1993-1999, Amiga, Inc.
**                   All Rights Reserved.
**                   Generated by SAS/C 6.2 (Modified by JFW)
**
**  Function prototypes for all of the functions in the library.  Used
**  to keep SAS/C docile.
**
*/

struct Armadillo * __asm __saveds CreateArmadillo(void);
void __asm __saveds DeleteArmadillo(register __a0 struct Armadillo * );
BOOL __asm __saveds NameArmadillo(register __a0 struct Armadillo * ,
                                  register __a1 STRPTR ,
                                  register __d0 ULONG );
BOOL __asm __saveds FillArmadillo(register __a0 struct Armadillo * ,
                                  register __d0 ULONG );
BOOL __asm __saveds FlattenArmadillo(register __a0 struct Armadillo * ,
                                     register __d0 BOOL );
BOOL __asm __saveds DilloFlat(register __a0 struct Armadillo * );
ULONG __asm __saveds DilloWeight(register __a0 struct Armadillo * );
BOOL __asm __saveds DilloName(register __a0 struct Armadillo * ,
                              register __a1 STRPTR ,
                              register __d0 ULONG );
void __asm __saveds ClearDillo(register __a0 struct Armadillo * );
ULONG __asm __saveds DilloBirths(void);

#endif /* DILLO_PROTOS_H */


III-29/dillo_test.c

;/* dillo_test.c - Execute me to compile me with SAS/C 6.56
sc data=far nominc strmer streq nostkchk saveds ign=73 dillo_test.c
slink FROM LIB:c.o,dillo_test.o TO dillo_test LIB LIB:SC.lib,LIB:Amiga.lib
quit
*/

/*
**  dillo_test.c
**
**  This is the sample program to test the functions inside
**  armadillo.library.  It creates a small array of Armadillos
**  and after assigning various values, prints out their status.
**
*/

#include    <exec/types.h>
#include    <exec/libraries.h>

#include    <clib/exec_protos.h>
#include    <pragmas/exec_pragmas.h>

#include    <stdio.h>

#include    "dillo_protos.h"
#include    "armadillo_pragmas.h"

extern struct ExecBase *SysBase;	/* olsen 30-Jan-96 */

/* Global data for the test program */

struct Library *DilloBase;      /* armadillo.library library base */

APTR dillo[5];                  /* Array of generic pointers to     */
                                /* armadillos, since programs don't */
                                /* need to know what the insides of */
                                /* an armadillo look like.          */

STRPTR names[5] = { "Alex", "Bob", "Chris", "Daniel", "Eustace" };
ULONG namlen[5] = { 5, 4, 6, 7, 8 };
ULONG weight[5] = { 18, 20, 19, 17, 354 };

void
main(void)
{
    BOOL okay = FALSE;
    ULONG i = 0L;

    if (DilloBase = OpenLibrary("armadillo.library",0))
    {

        for (i=0;i<5;i++)
        {
            if (dillo[i] = CreateArmadillo())
            {
                if (okay = NameArmadillo( dillo[i], names[i], namlen[i] ))
                {
                    printf("Armadillo %ld named %s.\n",i,names[i]);
                }
                else
                {
                    printf("Armadillo %ld naming failure, it's anonymous.\n",i);
                }

                if (okay = FillArmadillo( dillo[i], weight[i] ))
                {
                    printf("Armadillo %ld weighs %ld.\n",i,weight[i]);
                }
                else
                {
                    printf("Armadillo %ld fill failure, it's dieting.\n",i);
                }

                if (i>2)
                {
                    if (okay = FlattenArmadillo( dillo[i], TRUE ))
                    {
                        printf("Armadillo %ld had a slight mishap.\n",i);
                    }
                }
            }
            else
            {
                printf("Couldn't create Armadillo %ld\n",i);
            }
        }

        /* Okay, all the armadillos are created (hopefully) and */
        /* so as proof of concept and to test the data access   */
        /* functions, now the program shows the status of each  */
        /* of the armadillos.                                   */

        printf("\nArmadillo Status Report\n");
        printf("-----------------------\n");

        for(i=0;i<5;i++)
        {
            UBYTE namebuf[33];

            printf("Armadillo #%ld\n",i);
            if (DilloName(dillo[i],(STRPTR)&namebuf,32))
            {
                printf("  Name   = \"%s\"\n",namebuf);
            }
            else
            {
                printf("  Name is invalid.\n");
            }
            printf("  Weight = %ld pounds\n\n",DilloWeight(dillo[i]));
            printf("  Dillo is %s\n",
                   (DilloFlat(dillo[i])?"flat":"lucky"));
            printf("-----\n");
        }

        printf("Total Dillos created: %ld\n\n",DilloBirths());

        /* Now that the armadillos have been tested, we can */
        /* delete them with gleeful abandon.                */

        for(i=0;i<5;i++)
        {
            DeleteArmadillo( dillo[i] );
        }

        /* We're done, so close the library... */
        CloseLibrary(DilloBase);
    }
    else
    {
        printf("Couldn't open armadillo.library!\n");
    }
}


III-29/Makefile

##
##  armadillo.library makefile
##
##  This is a more-or-less generic makefile, which is currently set
##  to compile armadillo.library but which can easily be changed to
##  use your own files...

MODNAME=            armadillo
VERSION=            37
REVISION=           0

LIBFILE=            $(MODNAME).library

FD_CONV=            SC:C/FD2PRAGMA
FD_FILE=            $(MODNAME)_lib.fd
PRAGMA_FILE=        $(MODNAME)_pragmas.h

C_COMPILER=         SC:C/SC
C_OPTS=             STREQ STRMER NOSTKCHK LIBCODE

LINKER=             SC:C/SLINK

C_SOURCES=          dillo_lib.c dillo.c

OBJECTS=            dillo_lib.o dillo.o
LIBS=               LIB:sc.lib LIB:amiga.lib

LIBENT=             LIB:libent.o
LIBINIT=            LIB:libinitr.o
LIBPREFIX=          _LIB

##############################################################################
# Build the library...

$(LIBFILE): $(OBJECTS) $(LIBS) $(PRAGMA_FILE)

    $(LINKER) WITH <<
TO $(LIBFILE)
FROM $(LIBENT) $(LIBINIT) $(OBJECTS)
LIBFD $(FD_FILE)
LIBPREFIX $(LIBPREFIX)
LIBVERSION $(VERSION)
LIBREVISION $(REVISION)
LIB $(LIBS)
<

$(PRAGMA_FILE): $(FD_FILE)

##############################################################################
# Default rules...
#
.c.o:
    $(C_COMPILER) $(C_OPTS) $*.c

.fd.h:
    $(FD_CONV) $(FD_FILE) $(PRAGMA_FILE)

##############################################################################
# Delete all object files
#
clean:
    @Delete $(OBJECTS)
    @Delete $(LIBFILE)(|.info)
    @Delete $(MODNAME).map(|.info)

##############################################################################
# Load the new library into the system
#
reload:
    @copy $(LIBFILE) LIBS:
    @copy $(FD_FILE) FD:
    @flushlibs
    @version $(LIBFILE)


IV-1/wbarg.c

/* wbarg.c
 * How to get an icon from a Workbench argument
 * Written by David N. Junod, 27-Aug-90
 */
/*
Copyright (c) 1990-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/libraries.h>
#include <libraries/dos.h>
#include <workbench/icon.h>
#include <workbench/startup.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/wb_protos.h>
#include <pragmas/dos_pragmas.h>
#include <pragmas/exec_pragmas.h>
#include <pragmas/wb_pragmas.h>
#include <string.h>

extern struct Library *IconBase, *DOSBase, *SysBase;

struct DiskObject *GetDiskObjectNew (STRPTR name);
struct DiskObject *GetDiskObject (STRPTR name);

#pragma libcall IconBase GetDiskObjectNew 84 801

/****** wbarg/IconFromWBArg ********************************************
*
*   NAME
*	IconFromWBArg - Obtains the icon from a Workbench argument.
*
*   SYNOPSIS
*	dob = IconFromWBArg (wbarg);
*
*	struct DiskObject *dob;
*	struct WBArg *wbarg;
*
*   FUNCTION
*	Given a valid Workbench argument, this command will return the
*	proper icon.  This call uses the new (V36) GetDiskObjectNew call
*	to ensure that an icon will be returned.
*
*	This functions requires dos.library and icon.library to be opened
*	by the application.
*
*   INPUTS
*	wbarg	- Pointer to a filled in WBArg structure.
*
*   RESULTS
*	dob	- Pointer to a DiskObject structure.  Application must call
*		  FreeDiskObject when done with the icon.
*
**********************************************************************/

struct DiskObject *IconFromWBArg (struct WBArg * arg)
{
    struct DiskObject *dob = NULL;
    UBYTE work_name[34];
    BPTR old, new;

    /* Copy the WBArg contents */
    strcpy (work_name, arg->wa_Name);

    /* Duplicate the lock */
    if (new = DupLock (arg->wa_Lock))
    {
    BOOL success = FALSE;

    /*
     * If we don't have a name, then get one. Only Tools & Projects have a
     * valid name.
     */
    if (strlen (work_name) == 0)
    {
        LONG msize = sizeof (struct FileInfoBlock);
        struct FileInfoBlock *info;

        /* This block needs to be longword aligned, so allocate it */
        if (info = (struct FileInfoBlock *) AllocMem (msize, MEMF_CLEAR))
        {
        /* Examine the lock, so that we can figure out the name */
        if (Examine (new, info))
        {
            /* Copy the name of the lock */
            strcpy (work_name, info->fib_FileName);

            /* See if the lock is a directory */
            if (info->fib_DirEntryType > 0)
            {
            /* Unlock the existing lock */
            UnLock (new);

            /* Go to the parent drawer */
            if ((new = ParentDir (arg->wa_Lock)) == NULL)
            {
                /* A disk icon was passed */
                strcpy (work_name, "disk");
                new = DupLock (arg->wa_Lock);

            }	/* End of if disk */
            }		/* End of if directory */

            /* We have a name */
            success = TRUE;

        }		/* End of examine */

        /* Free the temporary block */
        FreeMem ((APTR) info, msize);
        }
    }
    else
    {
        /* Show that we have a name to work with */
        success = TRUE;
    }

    /* See if we should try getting the icon */
    if (success)
    {
        /* go to the directory where the icon resides */
        old = CurrentDir (new);

        /*
         * GetDiskObjectNew is a new function, for AmigaOS version 2.0,
         * therefore we need to check the version level.
         */
        if (IconBase->lib_Version >= 36)
        dob = GetDiskObjectNew (work_name);
        else
        dob = GetDiskObject (work_name);

        /* go back to where we used to be */
        CurrentDir (old);
    }

    /* release the duplicated lock */
    UnLock (new);
    }

    /* return the icon */
    return (dob);
}


IV-3/CloneWB.c

;/* CloneWB.c -  V36 Clone Workbench screen.  Compiled with SAS/C 6.56
sc NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 LINK CloneWB.c
quit

Copyright (c) 1990-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <stdio.h>
#include <stdlib.h>
#include <intuition/intuition.h>
#include <intuition/screens.h>
#include <graphics/displayinfo.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>

#include <pragmas/exec_pragmas.h>
#include <pragmas/intuition_pragmas.h>
#include <pragmas/graphics_pragmas.h>

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
extern struct Library *SysBase;

struct EasyStruct failedES = {
    sizeof(struct EasyStruct), 0, "CWB",
    "%s",
    "OK",
};

void            main(void);

void
main(void)
{
    struct Screen *wbscreen;
    struct Screen *clonescreen;
    struct Window *window;
    struct ViewPort *vp;
    struct IntuiMessage *msg;
    ULONG modeID;

    struct DisplayInfo displayinfo;
    struct MonitorInfo monitorinfo;
    struct DimensionInfo dimensioninfo;
    struct NameInfo nameinfo;
    struct DrawInfo *drawinfo;

    ULONG result;

    /* Fails silently when not V36 */
    if (IntuitionBase = OpenLibrary("intuition.library", 36)) {
        if (GfxBase = OpenLibrary("graphics.library", 36)) {

            if (wbscreen = LockPubScreen("Workbench")) {
                /* Using intuition.library/GetScreenDrawInfo(), we get the pen
                 * array we'll use for the screen clone the easy way. */
                drawinfo = GetScreenDrawInfo(wbscreen);

                vp = &(wbscreen->ViewPort);
                /* Use graphics.library/GetVPModeID() to get the ModeID of the
                 * Workbench screen. */
                if ((modeID = GetVPModeID(vp)) != INVALID_ID) {
                    /* OK, we got a valid ModeID for the Workbench
                     * screen (surprise) */

                    /* With just the ModeID, the lock on the Workbench
                     * screen & drawinfo->dri_Pens we're able to clone the
                     * Workbench exactly, displaymode and all. When you want
                     * to know everything there is to know about this
                     * displaymode, use graphics.library/GetDisplayInfoData().
                     */
                    /* 'result' is the actual # of bytes copies
                     * into the buffer.
                     * See graphics/displayinfo.h for definitions
                     * of the various structures.
                     */
                    result = GetDisplayInfoData(NULL,
                                                (UBYTE *)&monitorinfo,
                                                sizeof(struct MonitorInfo),
                                                DTAG_MNTR, modeID);
                    result = GetDisplayInfoData(NULL,
                                                (UBYTE *)&displayinfo,
                                                sizeof(struct DisplayInfo),
                                                DTAG_DISP, modeID);
                    result = GetDisplayInfoData(NULL,
                                                (UBYTE *)&dimensioninfo,
                                                sizeof(struct DimensionInfo),
                                                DTAG_DIMS,
                                                modeID);
                    result = GetDisplayInfoData(NULL,
                                                (UBYTE *)&nameinfo,
                                                sizeof(struct NameInfo),
                                                DTAG_NAME,
                                                modeID);

                    /* If you don't want to clone the workbench exactly,
                     * you could use one of the other overscan modes
                     * and/or min/max.
                     * dimensions in dimensioninfo or open a regular screen.
                     */
                    if (clonescreen = OpenScreenTags(NULL,
                        /* Could use STDSCREENWIDTH/HEIGHT for non-scrollable
                         * screens. Those make */
                        SA_Width, wbscreen->Width,

                        /* OpenScreen() use the textoverscan values */
                        SA_Height, wbscreen->Height,

                        SA_DisplayID, modeID,

                        SA_Depth, wbscreen->BitMap.Depth,

                        /*Workbench always sizes up to OSCAN_TEXT, so do we */
                        SA_Overscan, OSCAN_TEXT,

                        SA_Pens, drawinfo->dri_Pens,

                        SA_Title, nameinfo.Name,

                        /* Doesn't hurt for screens which don't scroll */
                        SA_AutoScroll, TRUE,

                        TAG_END)) {

                        if (window = OpenWindowTags(NULL,
                            WA_Top, clonescreen->BarHeight + 1,
                            WA_Height, clonescreen->Height
                                                - (clonescreen->BarHeight + 1),
                            WA_CustomScreen, clonescreen,
                            WA_MinWidth, 320,
                            WA_MinHeight, 100,
                            WA_MaxWidth, clonescreen->Width,
                            WA_MaxHeight, clonescreen->Height,

                            /* I'm only interested in CLOSEWINDOW messages */
                            WA_IDCMP, CLOSEWINDOW,
                            WA_Flags, WINDOWSIZING|WINDOWDRAG|
                                           WINDOWDEPTH|WINDOWCLOSE|ACTIVATE,
                            WA_Title, "Close to exit.",
                            TAG_END)) {

                            /* Wait for the closewindow message */
                            WaitPort(window->UserPort);
                            /* And remove message from the port */
                            while(msg = (struct IntuiMessage *)
                                  GetMsg(window->UserPort))
                                ReplyMsg((struct Message *)msg);
                            CloseWindow(window);
                        } else
                            EasyRequest(NULL, &failedES, NULL,
                                        "Can't open window");
                        CloseScreen(clonescreen);
                    } else
                        EasyRequest(NULL, &failedES, NULL,
                                    "Can't open screen");
                } else
                    EasyRequest(NULL, &failedES, NULL, "Invalide ModeID");
                FreeScreenDrawInfo(wbscreen, drawinfo);
                UnlockPubScreen(NULL, wbscreen);
            } else
                EasyRequest(NULL, &failedES, NULL,
                            "Can't lock Workbench screen");
            CloseLibrary(GfxBase);
        }
        CloseLibrary(IntuitionBase);
    }
}


IV-3/Pub.c

;/* Pub.c -  V36 Simple public screen example.
;   Compiled with SAS/C 6.56
sc NMINC STRMERGE NOSTKCHK LINK IGNORE=73 Pub.c
quit

Copyright (c) 1990-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <intuition/intuition.h>
#include <intuition/screens.h>
#include <graphics/displayinfo.h>
#include <libraries/gadtools.h>
#include <exec/memory.h>
#include <dos/dosextens.h>

#include <clib/exec_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/intuition_protos.h>

#include <pragmas/exec_pragmas.h>
#include <pragmas/gadtools_pragmas.h>
#include <pragmas/intuition_pragmas.h>

struct IntuitionBase *IntuitionBase;
struct Library *GadToolsBase;
extern struct Library *SysBase;

static UWORD dri_Pens[] =
{0, 1, 1, 2, 1, 3, 1, 0, 3, ~0};

/* Gadtools menu stuff */
#define QUIT 1
struct NewMenu sdm_menu[] =
{
    {NM_TITLE, "Project", 0, 0, 0, 0,},
    {NM_ITEM, "Quit", "Q", 0, 0, (void *) QUIT,},
    {NM_END, NULL, 0, 0, 0, 0,},
};

struct EasyStruct failedES =
{
    sizeof(struct EasyStruct), 0, "AMPub",
    "%s",
    "OK",
};

void main(void);

void
main(void)
{

    struct Screen *pubscreen;
    struct Window *window;
    struct Menu *menu;
    void *vi;

    struct IntuiMessage *msg;
    UBYTE defaultpubname[MAXPUBSCREENNAME];
    UWORD oldstatus;
    UWORD oldmodes;
    ULONG signal, wsignal, lastsignal, allocsignal;
    ULONG oserror;
    BOOL ABORT = FALSE;
    BOOL CLOSEDOWN = FALSE;
    struct Task *task;

    /* Fails silently if not V36 */
    if (IntuitionBase = OpenLibrary("intuition.library", 36)) {
        if (GadToolsBase = OpenLibrary("gadtools.library", 36)) {
            if ((allocsignal = AllocSignal(-1)) != -1) {
                lastsignal = 1 << allocsignal;

                /* We'll use our task address to get signaled when the last
                 * visitor window leaves. */
                task =
                  (struct Task *)&((struct Process *)FindTask(NULL))->pr_Task;

                /* Get the name of the currently default
                 * public screen (normally WB) */
                GetDefaultPubScreen(defaultpubname);

                /* Note that no checking is done to make sure the
                 * public screen name is unique.  If the public name is
                 * not unique, OSERR_PUBNOTUNIQUE is returned in an
                 * application supplied variable as data for the SA_ErrorCode
                 * tag.  In this case however, if OpenScreen fails, for
                 * whatever reason, we just bail out.
                 */

                if (pubscreen = OpenScreenTags(NULL,
                                 SA_DisplayID, HIRES_KEY,
                                 SA_Depth, 2,
                                 SA_Title,  "AmigaMail Test Public Screen",
                                 SA_PubName,"AmigaMail Test Public Screen",

                                 SA_PubSig, allocsignal,
                                 SA_PubTask, task,
                                          /* Normally you'd supply 0L, if you
                                          * the task which opened the screen to
                                          * be signaled.
                                          */
                                 SA_Pens, dri_Pens, SA_ErrorCode, &oserror,
                                 TAG_END)) {
                    if (menu = CreateMenus(sdm_menu, TAG_DONE)) {
                        if (window = OpenWindowTags(NULL,
                                      WA_Top, pubscreen->BarHeight + 1,
                                      WA_Height, pubscreen->Height
                                                 - (pubscreen->BarHeight + 1),
                                      WA_CustomScreen, pubscreen,
                                      WA_IDCMP, MENUPICK,
                                      WA_Flags, ACTIVATE|BACKDROP|
                                                    BORDERLESS|NOCAREREFRESH,
                                      TAG_END)) {

                            vi = GetVisualInfo(pubscreen, TAG_END);
                            if (LayoutMenus(menu, vi, TAG_DONE)) {
                                SetMenuStrip(window, menu);

                                /* Now we have a screen, named "AmigaMail Test
                                 * Public Screen", which is still marked
                                 * private, but ready to be made public.
                                 */
                                oldstatus = PubScreenStatus(pubscreen, 0);
                                /* Now it is really public. We'll make it the
                                 * default (and shanghai attempts to open
                                 * windows on the Workbench.
                                 */
                                SetDefaultPubScreen(
                                               "AmigaMail Test Public Screen");

                                oldmodes = SetPubScreenModes(SHANGHAI|
                                                             POPPUBSCREEN);

                                wsignal = 1 << window->UserPort->mp_SigBit;

                                do {
                                    signal = Wait(wsignal|lastsignal);
                                    /* The last visitor just left our screen */
                                    if (signal & lastsignal) {
                                        if (CLOSEDOWN)
                                            if ((oldstatus =
                                                 PubScreenStatus(pubscreen,
                                                           PSNF_PRIVATE)) & 1)
                                                ABORT = TRUE;
                                    }

                                    /* If not wsignal, this while-loop will not
                                     * be executed.
                                     */
                                    while(msg = (struct IntuiMessage *)
                                          GetMsg(window->UserPort)) {
                                    if (msg->Class == MENUPICK) {
                                            if ((UWORD)(MENU_USERDATA
                                                    (ItemAddress(menu,
                                                        msg->Code))) == QUIT) {
                                            /* If we can't make our screen
                                             * private again, we got
                                             * visitor window(s). Note
                                             * window(s) you open without
                                             * specifiying SA_PubScreenName,
                                             * are NOT considered visitor
                                             * windows.  So it's easy to try
                                             * to make your public screen
                                             * private again, without having
                                             * to close down your own windows
                                             * first.
                                             */

                                            if ((oldstatus =
                                                 PubScreenStatus(pubscreen,
                                                          PSNF_PRIVATE)) & 1) {
                                                ABORT = TRUE;
                                                }
                                            else {
                                                /* Close as soon as possible */
                                                     CLOSEDOWN = TRUE;
                                                    EasyRequest(window,
                                                                &failedES,
                                                                NULL,
                       "Can't make screen private.\nPlease close all windows");
                                                }
                                            }
                                        }
                                        ReplyMsg((struct Message *)msg);
                                    }
                                } while (ABORT == FALSE);

                                /* Restore orignal default */
                                SetDefaultPubScreen(defaultpubname);
                                ClearMenuStrip(window);
                                FreeVisualInfo(vi);
                            } else
                                EasyRequest(NULL,
                                            &failedES,
                                            NULL,
                                            "Can't layout menu's");
                            CloseWindow(window);
                        } else
                            EasyRequest(NULL,
                                        &failedES,
                                        NULL,
                                        "Can't open window");
                        FreeMenus(menu);
                    } else EasyRequest(NULL,
                                       &failedES,
                                       NULL,
                                       "Can't create menu's");
                    CloseScreen(pubscreen);
                } else
                    EasyRequest(NULL,
                                &failedES,
                                NULL,
                                "Can't open public screen");
                FreeSignal(allocsignal);
            } else
            EasyRequest(NULL, &failedES, NULL, "No signal available");
            CloseLibrary(GadToolsBase);
        }
    CloseLibrary(IntuitionBase);
    }
}


IV-3/Lockpub.c

/*
 * V36 Lock public screen list example
 *
 * Compiled with SAS/C 6.56:  sc NMINC STRMERGE NOSTKCHK LINK lockpub.c
 * Use V36 include files.
 *
 * Copyright (c) 1990-1999 Amiga, Inc.
 *
 * This example is provided in electronic form by Amiga,
 * Inc. for use with the Amiga Mail Volume II technical publication.
 * Amiga Mail Volume II contains additional information on the correct
 * usage of the techniques and operating system functions presented in
 * these examples.  The source and executable code of these examples may
 * only be distributed in free electronic form, via bulletin board or
 * as part of a fully non-commercial and freely redistributable
 * diskette.  Both the source and executable code (including comments)
 * must be included, without modification, in any copy.  This example
 * may not be published in printed form or distributed with any
 * commercial product. However, the programming techniques and support
 * routines set forth in these examples may be used in the development
 * of original executable software products for Amiga
 * computers.
 *
 * All other rights reserved.
 *
 * This example is provided "as-is" and is subject to change; no
 * warranties are made.  All use is at your own risk. No liability or
 * responsibility is assumed.
 *
 */

#include <string.h>

#include <intuition/intuition.h>
#include <intuition/screens.h>
#include <exec/memory.h>
#include <exec/lists.h>

#include <clib/intuition_protos.h>
#include <clib/exec_protos.h>
#include <clib/alib_protos.h>

void main (void);

struct IntuitionBase *IntuitionBase;

void main(void)
{

    struct List *publist;
    struct List *copy_publist;
    struct PubScreenNode *psnode;
    struct PubScreenNode *copy_psnode;

    /* fails silently if not V36 */
    if (IntuitionBase = OpenLibrary("intuition.library", 36)) {
        if (copy_publist = AllocMem(sizeof(struct List), MEMF_CLEAR)) {
            NewList(copy_publist);

            /* Lock the public screen list */
            publist = LockPubScreenList();

            /* and copy it */
            for (psnode = (struct PubScreenNode *)publist->lh_Head;
                     psnode->psn_Node.ln_Succ;
                     psnode = (struct PubScreenNode *)psnode->psn_Node.ln_Succ) {
                if (copy_psnode = AllocMem(sizeof(struct PubScreenNode), MEMF_CLEAR)) {
                    /* Copy the structure */
                    *copy_psnode = *psnode;

                    /* ln_Name points to the public screen name, make your own copy */
                    if (copy_psnode->psn_Node.ln_Name =
                            AllocMem(strlen(psnode->psn_Node.ln_Name) + 1, MEMF_CLEAR))
                        strcpy(copy_psnode->psn_Node.ln_Name, psnode->psn_Node.ln_Name);
                    else
                        printf("Not enough memory to copy screen name\n");

                    AddTail(copy_publist, (struct Node *)copy_psnode);
                } else {
                    printf("out of memory\n");
                    break;
                }
           }
           UnlockPubScreenList();

           psnode = (struct PubScreenNode *)copy_publist->lh_Head;
           while (copy_psnode = (struct PubScreenNode *)psnode->psn_Node.ln_Succ) {
                printf("%s\n", psnode->psn_Node.ln_Name);

                printf("psn_Screen       0x%lx\n", psnode->psn_Screen);
                                                               /* a pointer to the public screen */
                printf("psn_Flags        0x%lx\n", psnode->psn_Flags);
                                                               /* the flags */
                printf("psn_VisitorCount %ld\n", psnode->psn_VisitorCount);
                                                               /* the number of visitorwindows */
                printf("psn_SigTask      0x%lx\n", psnode->psn_SigTask);
                                                               /* The task to signal when the */
                                                               /* visitor is gone */
                printf("psn_SigBit       %ld\n\n", psnode->psn_SigBit);
                                                               /* The signalbit number to use */
                                                               /* to signal the task */

                if (psnode->psn_Node.ln_Name)
                    FreeMem(psnode->psn_Node.ln_Name, strlen(psnode->psn_Node.ln_Name) + 1);
                Remove((struct Node *)psnode);
                FreeMem(psnode, sizeof(struct PubScreenNode));
                psnode = copy_psnode;
           }
           FreeMem(copy_publist, sizeof(struct List));
        }
        CloseLibrary(IntuitionBase);
    }
}


IV-3/ScreenDisplayModes.c

;/* ScreenDisplayModes.c - V36 Screen Displaymode selector example
; Compiled with SAS/C 6.56
sc NMINC STRMERGE NOSTKCHK LINK IGNORE=73 ScreenDisplayModes.c
quit

Copyright (c) 1990-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <string.h>
#include <intuition/intuition.h>
#include <intuition/screens.h>
#include <libraries/gadtools.h>
#include <graphics/displayinfo.h>
#include <graphics/text.h>
#include <exec/memory.h>
#include <exec/ports.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/alib_protos.h>

#include <pragmas/exec_pragmas.h>
#include <pragmas/intuition_pragmas.h>
#include <pragmas/graphics_pragmas.h>
#include <pragmas/gadtools_pragmas.h>

#define SWITCH 888
#define QUIT   999

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Library *GadToolsBase;
extern struct Library *SysBase;

void main(void);
void ShowDisplayModes(struct List * dlist);
struct Screen *OpenAScreen(struct DimensionInfo * di, UBYTE * name,
               ULONG overscantype);
struct Window *OpenAWindow(struct Screen * screen, ULONG overscantype);

struct DisplayNode {
    struct Node dn_Node;
    struct DimensionInfo dn_Dimensioninfo;
};

/* The workbench compatible pens we'll use for that New Look. */
static UWORD dri_Pens[] = {0, 1, 1, 2, 1, 3, 1, 0, 3, ~0};

/* Gadtools menu stuff */
struct NewMenu sdm_menu[] =
{
    {NM_TITLE, "Project", 0, 0, 0, 0,},
    {NM_ITEM, "Switch Mode", "S", 0, 0, (void *) SWITCH,},
    {NM_ITEM, "Set Overscan", 0, 0, 0, 0,},
    {NM_SUB, "Text", 0, CHECKIT | CHECKED, ~1, (void *) OSCAN_TEXT,},
    {NM_SUB, "Standard", 0, CHECKIT, ~2, (void *) OSCAN_STANDARD,},
    {NM_SUB, "Max", 0, CHECKIT, ~4, (void *) OSCAN_MAX,},
    {NM_SUB, "Video", 0, CHECKIT, ~8, (void *) OSCAN_VIDEO,},
    {NM_ITEM, NM_BARLABEL, 0, CHECKIT, 0, 0,},
    {NM_ITEM, "Quit", "Q", 0, 0, (void *) QUIT,},
    {NM_END, NULL, 0, 0, 0, 0,},
};

UBYTE *OScanDescr[] = {NULL, "OSCAN_TEXT", "OSCAN_STANDARD",
             "OSCAN_MAX", "OSCAN_VIDEO"};

struct EasyStruct failedES =
{
    sizeof(struct EasyStruct), 0, "SDM",
    "%s",
    "OK",
};

void
main(void)
{
    struct List *dlist;
    struct DisplayNode *dnode;
    struct DisplayNode *wnode, *nnode;

    ULONG modeID;
    ULONG skipID;

    ULONG result;
    struct DisplayInfo displayinfo;
    struct NameInfo nameinfo;

    /* Fails silently if not V36 */
    if (IntuitionBase = OpenLibrary("intuition.library", 36)) {
        if (GfxBase = OpenLibrary("graphics.library", 36)) {
            if (GadToolsBase = OpenLibrary("gadtools.library", 36)) {
                if (dlist = AllocMem(sizeof(struct List), MEMF_CLEAR)) {
                    NewList(dlist);

                    /*
                     * Don't want duplicate entries in the list for the
                     * 'default monitor', so we'll skip the the videomode
                     * for which default.monitor is the alias.
                     */

                    /* INVALID_ID indicates the beginning and the end
             * of the list of available keys.
             */
                    modeID = INVALID_ID;

                    GetDisplayInfoData(NULL, (UBYTE *) & displayinfo,
                       sizeof(struct DisplayInfo),
                       DTAG_DISP, LORES_KEY);
                    if (displayinfo.PropertyFlags & DIPF_IS_PAL)
                        skipID = PAL_MONITOR_ID;
                    else
                        skipID = NTSC_MONITOR_ID;
                    while ((modeID = NextDisplayInfo(modeID)) != INVALID_ID) {
                        if ((modeID & MONITOR_ID_MASK) != skipID) {
                /*
                 * For this example,only 'named' keys are accepted.  Others
                 * which have no description are left out
                  * even though they may be available.
                  * HAM and EXTRAHALFBRIGHT are examples of this.
                  * If needed a name could be made like '320x400 HAM Interlace'.
                  */

                            if (result = GetDisplayInfoData(NULL,
                                (UBYTE *) & nameinfo,
                                sizeof(struct NameInfo),
                                DTAG_NAME,
                                modeID)) {
                                result = GetDisplayInfoData(NULL,
                                (UBYTE *) & displayinfo,
                                sizeof(struct DisplayInfo),
                                DTAG_DISP,
                                modeID);
                                if (!(displayinfo.NotAvailable)) {
                                    if (dnode =
                    (struct DisplayNode *)
                    AllocMem(sizeof(struct DisplayNode),
                         MEMF_CLEAR)) {
                                        result = GetDisplayInfoData(NULL,
                           (UBYTE *) &
                           (dnode->dn_Dimensioninfo),
                           sizeof(struct DimensionInfo),
                           DTAG_DIMS,
                           modeID);
                                        /* to keep it short: if NOMEM,
                     * just don't copy
                     */
                                        if (dnode->dn_Node.ln_Name
                        = AllocMem(strlen(nameinfo.Name)
                               + 1, MEMF_CLEAR))
                                            strcpy(dnode->dn_Node.ln_Name,
                           nameinfo.Name);
                                        AddTail(dlist, (struct Node *) dnode);
                                    } else {
                                        EasyRequest(NULL, &failedES, NULL,
                            "Out of memory");
                                        /* Force modeID to INVALID to break */
                                        modeID = INVALID_ID;
                                    }
                                }
                            }
                        }
                    }
                    ShowDisplayModes(dlist);

                    wnode = (struct DisplayNode *) dlist->lh_Head;
                    while (nnode = (struct DisplayNode *)
               (wnode->dn_Node.ln_Succ)) {

                        if (wnode->dn_Node.ln_Name)
                            FreeMem(wnode->dn_Node.ln_Name,
                    strlen(wnode->dn_Node.ln_Name) +1);
                        Remove((struct Node *) wnode);
                        FreeMem(wnode, sizeof(struct DisplayNode));
                        wnode = nnode;
                    }
                    FreeMem(dlist, sizeof(struct List));
                } else
                    EasyRequest(NULL, &failedES, NULL, "Out of memory");
                CloseLibrary(GadToolsBase);
            }
            CloseLibrary(GfxBase);
        }
        CloseLibrary(IntuitionBase);
    }
}

void
ShowDisplayModes(struct List * dlist)
{
    struct Screen *screen;
    struct Window *window;
    struct Gadget *glist, *gadget, *hitgadget;
    struct DrawInfo *drawinfo;
    struct TextFont *defaultfont;
    struct TextAttr *textattr;
    struct IntuiMessage *imsg;
    struct NewGadget *ng;
    struct Menu *menu;
    struct MenuItem *item;
    void *vi;
    ULONG iclass, icode, code;
    struct DisplayNode *dnode;
    struct DimensionInfo *dimensioninfo;
    ULONG overscantype = OSCAN_TEXT;
    ULONG curmode = 0;
    BOOL ABORT = TRUE, OK;
    int i;

    if (ng = AllocMem(sizeof(struct NewGadget), MEMF_CLEAR)) {
        if (textattr = AllocMem(sizeof(struct TextAttr), MEMF_CLEAR)) {
            if (textattr->ta_Name = AllocMem(48, MEMF_CLEAR)) {

                dnode = (struct DisplayNode *) dlist->lh_Head;

                if (menu = CreateMenus(sdm_menu, TAG_DONE)) {
                    do {
                        dimensioninfo = &(dnode->dn_Dimensioninfo);
                        OK = FALSE;
                        if (screen = OpenAScreen(dimensioninfo,
                         dnode->dn_Node.ln_Name,
                         overscantype)) {
                            drawinfo = GetScreenDrawInfo(screen);
                            defaultfont = drawinfo->dri_Font;
                            strcpy(textattr->ta_Name,
                   defaultfont->tf_Message.mn_Node.ln_Name);

                            textattr->ta_YSize = defaultfont->tf_YSize;
                            textattr->ta_Style = defaultfont->tf_Style;
                            textattr->ta_Flags = defaultfont->tf_Flags;

                            if (window = OpenAWindow(screen, overscantype)) {
                                vi = GetVisualInfo(screen, TAG_END);
                                if (LayoutMenus(menu, vi, TAG_DONE)) {
                                    if (gadget = CreateContext(&glist)) {
                                        ng->ng_LeftEdge =
                      window->BorderLeft + 10;
                                        ng->ng_TopEdge =
                      window->BorderTop + 10;
                                        ng->ng_Width =
                      window->Width -
                        (window->BorderLeft + 10) -
                          (window->BorderRight + 10);
                                        ng->ng_Height =
                      window->Height -
                        (window->BorderTop + 10) -
                          (window->BorderBottom + 10) -
                        (4 + defaultfont->tf_YSize + 2);
                                        ng->ng_TextAttr = textattr;
                                        ng->ng_GadgetText = NULL;
                                        ng->ng_VisualInfo = vi;
                                        ng->ng_GadgetID = 1;
                                        ng->ng_Flags = PLACETEXT_ABOVE;
                                        gadget =
                      CreateGadget(LISTVIEW_KIND, gadget,
                               ng, GTLV_Labels, dlist,
                               GTLV_ShowSelected, NULL,
                               GTLV_Selected, curmode,
                               TAG_END);

                                        ng->ng_TopEdge +=
                      gadget->Height +
                        defaultfont->tf_YSize + 10;
                                        ng->ng_Width = 80;
                                        ng->ng_LeftEdge =
                      ((window->Width - window->BorderLeft
                        - window->BorderRight) / 2) - 30;
                                        ng->ng_Height = defaultfont->tf_YSize + 8;
                                        ng->ng_GadgetID = 2;
                                        ng->ng_GadgetText = "OK";
                                        ng->ng_VisualInfo = vi;
                                        ng->ng_Flags = PLACETEXT_IN;
                                        gadget =
                      CreateGadget(BUTTON_KIND, gadget,
                               ng, TAG_END);

                                        AddGList(window, glist, -1, -1, NULL);
                                        RefreshGList(glist, window, NULL, -1);
                                        GT_RefreshWindow(window, NULL);
                                        SetMenuStrip(window, menu);
                                        ABORT = FALSE;
                                    } else
                                        EasyRequest(window, &failedES, NULL,
                            "Can't create gadget context");
                                } else
                                    EasyRequest(window, &failedES, NULL,
                        "Can't layout menus");

                                do {
                                    WaitPort(window->UserPort);
                                    while (imsg = GT_GetIMsg(window->UserPort)) {
                                        iclass = imsg->Class;
                                        icode = imsg->Code;
                                        hitgadget =
                      (struct Gadget *) imsg->IAddress;
                                        GT_ReplyIMsg(imsg);

                                        switch (iclass) {
                                        case GADGETUP:
                                            if (hitgadget->GadgetID == 1) {
                                                dnode =
                          (struct DisplayNode *)
                            dlist->lh_Head;
                                                for (i = 0; i < icode; i++)
                                                dnode =
                          (struct DisplayNode *)
                            dnode->dn_Node.ln_Succ;
                                                curmode = i;
                                            }
                                            if (hitgadget->GadgetID == 2)
                                                OK = TRUE;
                                            break;
                                        case MENUPICK:
                                            while ((icode != MENUNULL)
                           && (ABORT == FALSE)) {
                                                item = ItemAddress(menu, icode);

                                                code = (ULONG) MENU_USERDATA(item);
                                                if (code == QUIT)
                                                    ABORT = TRUE;
                                                else if
                                                    (code == SWITCH)
                                                    OK = TRUE;
                                                else
                                                    overscantype = (ULONG) code;
                                                icode = item->NextSelect;
                                            }
                                            break;
                                        case CLOSEWINDOW:
                                            ABORT = TRUE;
                                            break;
                                        }
                                    }
                                } while (ABORT == FALSE && OK == FALSE);
                                ClearMenuStrip(window);
                                CloseWindow(window);
                                FreeVisualInfo(vi);
                                FreeGadgets(glist);
                            } else
                                EasyRequest(NULL, &failedES, NULL,
                        "Can't open window");
                            FreeScreenDrawInfo(screen, drawinfo);
                            CloseScreen(screen);
                        } else
                            EasyRequest(NULL, &failedES, NULL,
                    "Can't open screen");
                    } while (ABORT == FALSE);
                    FreeMenus(menu);
                } else
                    EasyRequest(NULL, &failedES, NULL, "Can't create menus");
                FreeMem(textattr->ta_Name, 48);
            } else
                EasyRequest(NULL, &failedES, NULL, "Out of memory");
            FreeMem(textattr, sizeof(struct TextAttr));
        } else
            EasyRequest(NULL, &failedES, NULL, "Out of memory");
        FreeMem(ng, sizeof(struct NewGadget));
    } else
        EasyRequest(NULL, &failedES, NULL, "Out of memory");
}

/*
 * It's advised to use one of the overscan constants and
 * STDSCREENWIDTH and STDSCREENHEIGHT. For this example however, we'll
 * skip all that an use QueryOverscan to get the rectangle describing the
 * requested overscantype and pass that as the displayclip description.
 * Actually, since we pass the standard rectangle from the display database,
 * it is equivalent to the prefered:
 *
 * screen = OpenScreenTags(NULL,
 *                         SA_DisplayID, di->Header.DisplayID,
 *                         SA_Overscan, overscantype,
 *                         SA_Width, STDSCREENWIDTH,
 *                         SA_Height, STDSCREENHEIGHT,
 *                         SA_Title, name,
 *                         SA_Depth, 2,
 *                         SA_SysFont, 1,
 *                         SA_Pens, dri_Pens,
 *                         TAG_END);
 */

struct Screen *
OpenAScreen(struct DimensionInfo * di, UBYTE * name, ULONG overscantype)
{

    struct Rectangle rectangle;

    /* Can't fail, already made sure it's a valid displayID */
    QueryOverscan(di->Header.DisplayID, &rectangle, overscantype);

    return (OpenScreenTags(NULL,
                           SA_DisplayID, di->Header.DisplayID,
                           SA_DClip, &rectangle,
                           SA_Title, name,
                           SA_Depth, 2,
                           SA_SysFont, 1,   /* Use the prefered WB screen font */
                           SA_Pens, dri_Pens,
                           TAG_END));
}

struct Window *
OpenAWindow(struct Screen * screen, ULONG overscantype)
{
    return (OpenWindowTags(NULL,
                           WA_Top, screen->BarHeight + 1,
                           WA_Height, screen->Height - (screen->BarHeight + 1),
                           WA_CustomScreen, screen,
                           WA_IDCMP, CLOSEWINDOW | LISTVIEWIDCMP | MENUPICK,
                           WA_Flags, WINDOWCLOSE | ACTIVATE,
                           WA_Title, OScanDescr[overscantype],
                           TAG_END));
}


IV-17/extscreen.c

;/* extscreen.c - Usage of NS_EXTENDED & NW_EXTENDED.  Compiled with SAS/C 6.56
sc NMINC STRMERGE NOSTKCHK LINK IGNORE=73 extscreen.c
quit
 */
/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <intuition/intuition.h>
#include <graphics/gfxbase.h>
#include <graphics/displayinfo.h>
#include <intuition/screens.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>

#include <stdio.h>
#include <stdlib.h>

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
extern struct ExecBase *SysBase;

/* To get that New Look we'll use Workbench compatible pen numbers.
 * The end of the pen array is indicated with ~0.
 * Note that the screen depth should comply with the pen numbers used.
 * I.e. specifying pen number 3 on a one bitplane screen will obviously
 * not give the desired effect.
 * A description of the pen array can be found in intuition/screens.h.
 */

static UWORD    dri_Pens[] =
{ 0, 1, 1, 2, 1, 3, 1, 0, 3, ~0};

/* zoom/zip/zap/zop array to illustrate NW_EXTENDED */
static UWORD    zoomdata[] =
{ 30, 30, 200, 100};

/* Old style requester to be compatible with < V36 */
struct IntuiText reqtext[] = {
    { 0,1, JAM1, 10,10, NULL, NULL, NULL},
    { 0,1, JAM1, 6,3, NULL, "Continue", NULL},
};

/* local protos */
void            main(void);
BOOL CheckPAL(STRPTR screenname);

void main(void)
{
    struct ExtNewScreen xnewscreen;
    struct ExtNewWindow xnewwindow;
    struct Screen  *screen;
    struct Window  *window;
    struct IntuiMessage *msg;
    struct DisplayInfo displayinfo;
    struct TagItem  taglist[3];
    BOOL OpenA2024 = FALSE;
    BOOL IsV36 = FALSE;
    BOOL IsPAL;

    if (IntuitionBase = OpenLibrary("intuition.library", 33))
    {
        if (GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 33))
        {

            /* V36 check if a 10 Hz A2024 screen can be opened. If this has to be
             * done in V35 (Jumpstart), start by checking the library version
             * ofcourse. Next simply open the screen with A2024 parameters. If this
             * fails there are a couple of possibilities. The system may have run
             * out of memory or even though the user is running V35 s/he hasn't set
             * up Hedley mode. Logical step in case of failure is to try again with
             * regular parameters. Depending on the nature of the program, this could
             * be done everytime the program starts, or according to some kind of
             * user preferences setting.
             */

            /* Check for V36>. If present check Hedley (A2024) availability */
            if (GfxBase->LibNode.lib_Version >= 36)
            {
                IsV36 = TRUE;
                /* Use GetDisplayInfoData() with the DTAG_DISP to get the display info,
                 * containing availability. Note that availability means that the user
                 * admonitor'ed A2024, not necessarily that there is a physical A2024
                 * out there.
                 */
                if(GetDisplayInfoData(NULL, (UBYTE *)&displayinfo,
                    sizeof(struct DisplayInfo), DTAG_DISP, A2024TENHERTZ_KEY))
                    if (displayinfo.NotAvailable == 0)
                        OpenA2024 = TRUE;
            }
            else
            {
                /* Check if V35. If it is indicate I want the  tags added to open a
                 * A2024 screen. Note that this still doesn't mean I can actually open
                 * in Hedley mode.
                 */
                if (GfxBase->LibNode.lib_Version == 35)
                    OpenA2024 = TRUE;
            }

            /* Use a separate CheckPAL() function to see if how the use has set up
             * the system.
             */
            IsPAL = CheckPAL("Workbench");

            /* Build taglist, this is completely ignored in V33/V34 and V35 doesn't
             * recognize tags other than those A2024 ones.
             */

            /* Pass the A2024 tags. Note that with V36 it is easy to pass the
             * displaymodeid as a tag (SA_DisplayID) that that is not V35 compatible.
             * Also for V35 compatability this must be the first tag. */

            if (OpenA2024)
            {
                taglist[0].ti_Tag = NSTAG_EXT_VPMODE;
                taglist[0].ti_Data = VPF_A2024 | VPF_TENHZ;
            }
            else
            {
                /* With V36 Intuition fully supports overscan. We'll pass the
                 * Overscantype used by Workbench as a tag, and specify
                 * STDSCREENWIDTH/HEIGHT in the Width and Height fields of
                 * the ExtNewScreen structure.
                 */
                taglist[0].ti_Tag = SA_Overscan;
                taglist[0].ti_Data = OSCAN_TEXT;
            }

            /* Indicate we want the New Look if this system is running V36 by
             * specifying the SA_Pens tag and passing the pen array as data.
             */
            taglist[1].ti_Tag = SA_Pens;
            taglist[1].ti_Data = (ULONG) dri_Pens;

            /* End the taglist with TAG_DONE */
            taglist[2].ti_Tag = TAG_DONE;

            /* If V36, the overscan mode will give us the right offsets */
            xnewscreen.LeftEdge = 0;
            xnewscreen.TopEdge = 0;

            /* Width = 1008 if A2024, 640 if < V35, STDSCREENWIDTH if V36> */
            xnewscreen.Width = (OpenA2024) ? 1008 : (IsV36) ? STDSCREENWIDTH : 640;

            /* Height=1024 if A2024 & PAL, 800 if A2024 & NTSC, else STDSCREENHEIGHT */
            xnewscreen.Height = (OpenA2024) ? ((IsPAL) ? 1024 : 800) : STDSCREENHEIGHT;

            xnewscreen.Depth = 2;
            xnewscreen.DetailPen = 0;
            xnewscreen.BlockPen = 1;

            /* Set viewmodes to 0 if going to attempt to open in Hedley mode */
            xnewscreen.ViewModes = (OpenA2024) ? 0 : HIRES | LACE;

            /* Use NS_EXTENDED to tell V35 tags are on their way */
            xnewscreen.Type = CUSTOMSCREEN | NS_EXTENDED;

            /* Default font */
            xnewscreen.Font = NULL;

            xnewscreen.DefaultTitle =
                     (OpenA2024) ? "VPF_A2024|VPF_TENHZ" : "HIRES|LACE";
            xnewscreen.Gadgets = NULL;

            /* Pass the taglist as a V35 compatible extension. V34 will ignore this */
            xnewscreen.Extension = taglist;

            if ((screen = OpenScreen(&xnewscreen)) == NULL)
            {
                /* Can't open screen. Might be V35 A2024 failure. Try with something
                 * simpler.
                 */
                xnewscreen.Width = (IsV36) ? STDSCREENWIDTH : 640;
                xnewscreen.Height = STDSCREENHEIGHT;
                xnewscreen.ViewModes = HIRES | LACE;
                xnewscreen.DefaultTitle = "HIRES|LACE";
                /* Get rid of A2024 tags, keep the others. */
                taglist[0].ti_Tag = SA_Overscan;
                taglist[0].ti_Data = OSCAN_TEXT;
                OpenA2024 = FALSE;
                screen = OpenScreen(&xnewscreen);
                /* If it still fails, give up */
            }

            /* If screen opened, open a simple ExtNewWindow on it and wait */
            if (screen)
            {
                /* Give me a zoom gadget on my window. */
                taglist[0].ti_Tag = WA_Zoom,
                taglist[0].ti_Data = (ULONG) zoomdata;
                taglist[1].ti_Tag = TAG_DONE;

                xnewwindow.LeftEdge = 0;
                xnewwindow.TopEdge = screen->BarHeight + 1;
                xnewwindow.Width = screen->Width;
                xnewwindow.Height = screen->Height - xnewwindow.TopEdge;
                xnewwindow.DetailPen = 0;
                xnewwindow.BlockPen = 1;
                xnewwindow.IDCMPFlags = CLOSEWINDOW;
                xnewwindow.Flags =
                    WINDOWSIZING | WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE |
                      NW_EXTENDED | SMART_REFRESH | NOCAREREFRESH | ACTIVATE;
                xnewwindow.FirstGadget = NULL;
                xnewwindow.CheckMark = NULL;
                xnewwindow.Title = "Close to exit.";
                xnewwindow.Screen = screen;
                xnewwindow.BitMap = NULL;
                xnewwindow.MinWidth = 100;
                xnewwindow.MinHeight = 50;
                xnewwindow.MaxWidth = ~0;
                xnewwindow.MaxHeight = ~0;
                xnewwindow.Type = CUSTOMSCREEN;
                /* The window extension is completely ignored if not V36 */
                xnewwindow.Extension = taglist;

                if (window = OpenWindow(&xnewwindow))
                {
                    WaitPort(window->UserPort);
                    while (msg = (struct IntuiMessage *)GetMsg(window->UserPort))
                        ReplyMsg((struct Message *)msg);
                    CloseWindow(window);
                }

                else
                {
                    reqtext[0].IText = "Can't open window";
                    AutoRequest(NULL, &reqtext[0], NULL, &reqtext[1],
                                NULL, GADGETUP, 320, 60);
                }
                CloseScreen(screen);
            }
            else
            {
                reqtext[0].IText = "Can't open screen";
                AutoRequest(NULL, &reqtext[0], NULL, &reqtext[1],
                            NULL, GADGETUP, 320, 60);
            }
            CloseLibrary((struct Library *) GfxBase);
        }
        CloseLibrary(IntuitionBase);
    }
}

/* CheckPAL returns TRUE, if the the videomode of the specified public screen (or default videmode)
 * is PAL.
 * If the screenname is NULL, the default public screen will be used.
 */

BOOL CheckPAL(STRPTR screenname)
{
    struct Screen *screen;
    ULONG modeID = LORES_KEY;
    struct DisplayInfo displayinfo;
    BOOL IsPAL;

    if (GfxBase->LibNode.lib_Version >= 36)
    {
    /*
     * We got V36, so lets use the new calls to find out what
     * kind of videomode the user (hopefully) prefers.
     */

        if (screen = LockPubScreen(screenname))
        {
            /*
             * Use graphics.library/GetVPModeID() to get the ModeID of the specified
             * screen.  Will use the default public screen (Workbench most of the time)
             * if NULL It is very_ unlikely that this would be invalid, heck it's
             * impossible.
             */
            if ((modeID = GetVPModeID(&(screen->ViewPort))) != INVALID_ID)
            {
                /*
                 * If the screen is in VGA mode, we can't tell whether the system is
                 * PAL or NTSC. So to be fullproof we fall back to the displayinfo of
                 * the default.monitor by inquiring about just the LORES_KEY
                 * displaymode if we don't know. The default.monitor reflects the
                 * initial video setup of the system, thus is an alias for either
                 * ntsc.monitor or pal.monitor. We only use the displaymode of the
                 * specified public screen if it's display mode is PAL or NTSC and NOT
                 * the default.
                 */

                if (!((modeID & MONITOR_ID_MASK) == NTSC_MONITOR_ID ||
                      (modeID & MONITOR_ID_MASK) == PAL_MONITOR_ID))
                    modeID = LORES_KEY;
            }
            UnlockPubScreen(NULL, screen);
        } /* if fails modeID = LORES_KEY. Can't lock screen,
           * so fall back on default monitor. */

        if (GetDisplayInfoData(NULL, (UBYTE *) & displayinfo,
            sizeof(struct DisplayInfo), DTAG_DISP, modeID))
        {
            if (displayinfo.PropertyFlags & DIPF_IS_PAL)
                IsPAL = TRUE;
            else
                IsPAL = FALSE;  /* Currently the default monitor is always either
                                 * PAL or NTSC.
                                 */
        }
    }
    else /* < V36. The enhancements to the videosystem in
          * V36 cannot be better expressed than
          * with the simple way to determine PAL in V34.
          */
        IsPAL= (GfxBase->DisplayFlags & PAL) ? TRUE : FALSE;

    return(IsPAL);
}


IV-23: Appendix: Boopsi Class Reference

This appendix documents all the standard classes, their methods, and
their attributes.  The parameters for each moethod can be found in the
appropriate include file.  Each attribute is followed by a code that
lists the methods that apply to that attribute.  The codes are as
follows:

    I       OM_NEW
    S       OM_SET
    G       OM_GET
    N       OM_NOTIFY
    U       OM_UPDATE

                            rootclass
                               /
                 _____________/____________
                /         /                \
               /         /                  \
           icclass      /                gadgetclass
             /         /                      \
            /         /         _______________\___________________
           /     imageclass    /           /         \             \
          /         /         /           /           \             \
     modelclass    /      propgclass  strgclass  buttongclass  groupgclass
                  /                                     \
                 /                                       \
         _______/___________________________        frbuttongclass
        /         \            \            \
       /           \            \            \
  frameiclass  sysiclass  fillrectclass  itexticlass


rootclass

Class:                  rootclass
Superclass:             None
Description:            Base class for all other classes
Include File:           <intuition/classusr.h>

New Methods:
------------

OM_NEW - Create a new object.  This method is passed a pointer to the
"true class" of the object in place of the yet to be created object.
The Root class will allocate enough memory for all the instance data of
the true class.

OM_DISPOSE - Delete an object.  This method will free the same amount of
memory as allocated by OM_NEW.

OM_ADDTAIL - Add an object to an Exec list, based on a MinNode in the
private rootclass object header.  You can provide any Exec list you
want, and iterate the objects on the list using the Intuition function
NextObject().

OM_REMOVE  - Remove an object from an Exec list.

The following methods are defined for all objects, but are no-ops in the
rootclass.  Implementation for specific subclasses is done to support
these conventions.

OM_ADDMEMBER - Add some object (passed to the method) to the objects
list, which is defined by the class.  Examples include the broadcast
list of modelclass objects, and the component gadgets of a groupgclass
object.  This is typically implemented by sending the OM_ADDTAIL message
to the member object.

OM_REMMEMBER - Remove a member object previously added by OM_ADDMEMBER.
You typically send the OM_REMOVE message to the member object.

OM_SET - Set attributes from passed attribute list.  The Root class
defines no attributes.

OM_GET - Retrieve an attribute.

OM_UPDATE - "Be updated" of external changes.  A no-op for rootclass.

OM_NOTIFY - Notify other of changes provided in the message.  A no-op
for the root class.

Changed Methods:
----------------

Not applicable.

Attributes:
-----------

None.


imageclass

Class:                  imageclass
Superclass:             rootclass
Description:            Base class for Intuition Images
Include File:           <intuition/imageclass.h>

New Methods:
------------

IM_DRAW - Draw the image in the RastPort passed in the message, at the
xoffset and in the state provided in the message.

IM_HITTEST - Return TRUE if the point passed is within the image.  This
base Image class returns TRUE if the point is within the old Image
structure box.

IM_ERASE - Erase an image.  This class will call the new graphics
library function EraseRect() for its Image box.  IM_ERASE does not test
the box dimensions  (>= 0).

IM_MOVE - Erase and redraw an image.  This is intended for subclasses
capable of performing animation or smooth dragging (e.g., prop gadget
knobs).  A no-op for imageclass.

IM_FRAMEBOX - A no-op for this base class, but implemented by image
subclasses which are "stretchable".  For example, frameiclass objects
put an embossed frame around a text label or glyph.  The message passed
to this method contains a pointer to a box describing the dimensions of
the contents to frame, and a pointer to a frame box for the result.
There is also a FrameFlags field which currentlly has only one defined
flag, FRAMEF_SPECIFY.

The idea behind this frame business is to support multiple gadgets (as
found in a system requester) which share a single frame image object,
but render it in different dimensions appropriate for their enclosed
label.  The operation of this method should be defined by suitable
subclasses as follows, and return non-zero to indicate that they support
this method.

If FRAMEF_SPECIFY is not set, you should set up the povided frame box
with the position and dimensions of the frame you would render to
enclose the contents box.  This is an inquiry function used, for
example, by a gadget which wants to know what sized frame dimensions to
pass to IM_DRAWFRAME (defined below) and how to center the contents.

The caller might then add a little aesthetic margin by increasing the
dimensions (or might decide to make a column of framed objects all the
same width as the largest one), and having done so, can call the method
IM_FRAMEBOX again, this time with FRAMEF_SPECIFY set.  Now, your method
is expected to respect the dimensions specified in the frame box (even
if you think they are too small!) and to set up only the position of the
frame box appropriately for enclosing the provided contents box.
Currently implemented frame image classes always center the contents,
but future classes might want to support an attribute for optional left
or right justification of the contents.

IM_DRAWFRAME - Image subclasses which assign proper meaning to this
class (i.e. frameiclass) should respect the dimensions that are passed
in this message by superceding this method.  If imageclass sees this
message, it will convert it to an IM_DRAW message and send it back to
the image's true class.  This way, any subclass of imageclass which
doesn't implement or recognize the IM_DRAWFRAME method will default to
drawing objects at their "natural" dimensions.

IM_HITFRAME - Perform a hit test for the image respecting the frame
dimensions passed in the message.  Useful for something like a
stretchable rounded box.  This class just performs the same as
IM_HITTEST, ignoring the dimensions passed.

IM_ERASEFRAME - Erase an image respecting the frame dimensions passed in
the message.  This class calls EraseRect() for the frame dimensions,
again not checking dimension validity.

Changed Methods:
----------------

OM_NEW - Instance data contains an Image structure, and its Depth field
is initialized to CUSTOMIMAGEDEPTH, which identifies such images to
Intuition.  The Width and Height fields are set to arbitrary positive
numbers for safety, but you should always set them to something
meaningful.

OM_SET - Applies all supported attributes, returns '1'.

Attributes:
-----------

IA_Left                         (ISG)
IA_Top                          (ISG)
IA_Width                        (ISG)
IA_Height                       (ISG)

These attributes are stored (by imageclass) as values in the familiar
Image structure.

IA_FGPen                        (ISG)
IA_BGPen                        (ISG)

These attributes are maintained in the PlanePick and PlaneOnOff fields,
which concept they generalize.

IA_Data                         (ISG)

A pointer to general image data.  This value is stored in the ImageData
field of the old Image structure.

IA_LineWidth                    ()

A no-op for imageclass.

IA_Pens                         ()

Defined but not supported by imageclass. Pointer to UWORD pens[],
terminated by ~0.  This can be used to the exclusion of DrawInfo
attributes or parameters, or as an override.


frameiclass

Class:                  frameiclass
Superclass:             imageclass
Description:            A raised, sunken, or chisled image class
                        supporting frame dimensions and Intuition new
                        look parameters.
Include File:           <intuition/imageclass.h>

New Methods:
------------

None, but implements some of the no-ops in imageclass.

Changed Methods:
----------------

OM_GET - A no-op for this class.

IM_DRAW - Draws the embossed frame in its natural (Image) dimensions.
Frame thickness support of IA_LineWidth is currently not implemented.
Frame type is determined by attributes below, colors determined by
DrawInfo and supports these drawing states:

        IDS_NORMAL, IDS_INACTIVENORMAL, IDS_DISABLED:

Renders edges in shadowPen, shinePen, and backgroundPen for the
interior.  NOTE: No ghosting is done for IDS_DISABLED.

        IDS_SELECTED, IDS_INACTIVESELECTED:

Renders edges in shadowPen, shinePen, and hifillPen, for the interior.

IM_DRAWFRAME - Same as IM_DRAW, but draws frame to specified exterior
dimensions.

IM_FRAMEBOX - Centers contents, adds dimension for frame thickness, plus
an interior margin of the same thickness.

Attributes:
-----------

IA_Recessed                     (IS)

Specifies that the frame should be recessed into the drawing surface
(shadowPen used on upper and left edges).  Default is FALSE, a raised
frame.

IA_DoubleEmboss                 (IS)

Two nested embossed frames for "chisled" boxes or "ridges".  Not
currently supported.

IA_EdgesOnly                    (IS)

Does not fill frame, just draws the edges.

IA_LineWidth                    ()

Not currently supported.


sysiclass

Class:                  sysiclass
Superclass:             imageclass
Description:            Class for system and standard application images.
Include File:           <intuition/imageclass.h>

New Methods:
------------

None.

Changed Methods:
----------------

OM_NEW - Executes a drawing commands list to create a fast-rendering
image object.  The glyph of the object is defined by the attribute
SYSIA_Which.  The SYSIA_DrawInfo parameter is required at
initialization, as is IA_Height.  Image size defaults are established by
SYSIA_Size, but some images  (title bar gadget images) require
IA_Height.  Images are scaled to their dimensions.

Attributes:
-----------

SYSIA_DrawInfo                  (IS)

This attribute must be passed to OM_NEW and OM_SET to allow the image to
be generated into a bitmap cache.

SYSIA_Which                     (I)

Identifies which of the system image glyphs the caller wants.  It can be
one of the following:

    DEPTHIMAGE     Window depth arrangement image.
    ZOOMIMAGE      Window Zoom image.
    SIZEIMAGE      Window Sizing image.
    CLOSEIMAGE     Window close image.
    SDEPTHIMAGE    Screen depth arrangement image.
    LEFTIMAGE      Left arrow image.
    UPIMAGE        Up arrow image.
    RIGHTIMAGE     Right arrow image.
    DOWNIMAGE      Down arrow image.
    CHECKIMAGE     Checkmark image.
    MXIMAGE        Radio button image.

SYSIA_Size                      (I)

Identifies which default dimensions to use for the object.  This
generalizes Intuition's older concept of two different system image
dimensions.  The system currently uses SYSISIZE_MEDRES as the default,
SYSISIZE_HIRES for screens with title bars greater than 22 pixels, and
SYSISIZE_LORES for screens with fat pixels.


fillrectclass

Class:                  fillrectclass
Superclass:             imageclass
Description:            Rectangle with frame and pattern support
Include File:           <intuition/imageclass.h>

New Methods:
------------

None.

Changed Methods:
----------------

IM_DRAW - Draws the pattern in its natural (Image) dimensions.

IM_DRAWFRAME - Same as IM_DRAW, but draws pattern to specified exterior
dimensions.

Attributes:
-----------

IA_APattern                     (IS)

Points to the pattern to fill in the Image structure's ImageData field.

IA_APatSize                     (IS)

The pattern's dimension.

IA_Mode                         (IS)

Drawing mode for the pattern.


itexticlass

Class:                  itexticlass
Superclass:             imageclass
Description:            IntuiText equivalent with attribute override.
Include File:           <intuition/imageclass.h>

New Methods:
------------

None.

Changed Methods:
----------------

IM_DRAW - Draws IntuiText specified as IA_Data overriding the attributes
specified in the IntuiText structure.  The Mode used is JAM1, the color
as specified as IA_FGPen.  The position of the itexticlass object is
added to the position of the IntuiText.

This class was defined to make new-looking AutoRequesters without
changing the IntuiText structures passed to it.

Attributes:
-----------

IA_Data                         (ISG)

Processed blindly by superclass, must be a pointer to a normal IntuiText
structure.

IA_FGPen                        (ISG)

Processed by superclass, used as APen when drawing text.

IA_Left, IA_Top                 (ISG)

Added to IntuiText offsets.


icclass

Class:                  icclass
Superclass:             rootclass
Description:            Base class of simple forwarding interconnection.
Include File:           <intuition/icclass.h>

New Methods:
------------

ICM_SETLOOP
ICM_CLEARLOOP
ICM_CHECKLOOP - All of these methods are used internally by subclasses
to manage a loop inhibition for broadcasted messages.  They increment,
decrement, and return the value of that counter.

Changed Methods:
----------------

OM_SET - Sets attributes and returns 0.  Note that this is not the same
behavior as OM_NOTIFY.

OM_NOTIFY - Issues an OM_UPDATE message to the object indicated by
attribute ICA_Target, first converting the attribute tags according to
the ICA_Map attribute.  The internal loop count is incremented until the
OM_UPDATE method it invokes on ICA_Target returns.  Also, it will do
nothing at all if that loop count was non-zero to begin with, preventing
itself from participating in an infinite loop.

OM_UPDATE - Receive update notices from others.  This base IC class just
passes the message along, treating it exactly like an OM_NOTIFY message.
Subclasses will probably redefine this method to perform a calculation,
the result of which they might forward to others by issuing themselves
an OM_NOTIFY message.  Unfortunately, this class converts the OM_SET and
OM_NOTIFY messages to an OM_NOTIFY by changing their MethodID field, and
does not restore it to what it originally was.

Attributes:
-----------

ICA_Target                      (IS)

Target object for OM_UPDATE messages.  If this attribute is given the
value ICTARGET_IDCMP, then the notification will consist of sending an
IDCMPUPDATE IntuiMessage to a window.  The window is determined by the
GadgetInfo structure passed around when the object is connected to
gadgets.

ICA_Map                         (IS)

Attribute mapping list.

ICSPECIAL_CODE                  (*)

This is a magic dummy attribute: if it occurs as a target in the ICA_Map
mapping list, and ICA_Target is ICTARGET_IDCMP, then the new value of
the corresponding attribute will be copied into the IntuiMessage.Code
field of the IDCMPUPDATE message (just the lower sixteen bits of the
attribute value will fit).  This sometimes makes it particularly simple
to process IDCMPUPDATE messages with a single item of interest.


modelclass

Class:                  modelclass
Superclass:             icclass
Description:            Provides "broadcast" interconnection.
Include File:           <intuition/icclass.h>

New Methods:
------------

None.

Changed Methods:
----------------

OM_ADDMEMBER - Adds an object to the the Model's internally maintained
broadcast list.  Anything on this list will be DISPOSED when the model
object is disposed.

OM_REMMEMBER - Removes objects added by OM_ADDMEMBER.

OM_DISPOSE - Disposes members of the broadcast list as well as itself.

OM_NOTIFY, OM_UPDATE - these behave like the icclass methods, but first
an OM_UPDATE message is sent to all members of the object's broadcast
list, un-mapped.  The members of the broadcast list are typically
icclass objects, which have gadgets as their targets and appropriate
mapping lists.  If you are creating a useful subclass, you will probably
want to intercept OM_UPDATE, but pass OM_NOTIFY to modelclass, your
superclass.

Attributes:
-----------

ICA_Map, ICA_Target -  Same as for the superclass (icclass).


gadgetclass

Class:                  gadgetclass
Superclass:             rootclass
Description:            Base class for Intuition compatible gadget classes
Include File:           <intuition/gadgetclass.h>

New Methods:
------------

Intuition uses the following methods to control a gadget.  Only custom
gadget class implentors will be interested in these.

GM_HITTEST
GM_RENDER
GM_GOACTIVE
GM_HANDLEINPUT
GM_GOINACTIVE

Changed Methods:
----------------

OM_NEW - Initializes transparent Gadget structure.  LeftEdge and TopEdge
are set to 0, Width and Height are arbitrary constants which you should
override.  Sets GadgetType to CUSTOMGADGET, and installs a pointer to
the gadgetclass data structure in the MutualExclude field.  These
objects are also valid "custom gadgets."

Links self into a NextGadget linked list if GA_Previous is passed to
OM_NEW.

OM_UPDATE and OM_SET are used simply to change the attributes.  This
gadgetclass does not implement any concrete gadgets.  This is left to
the subclasses.

OM_NOTIFY - This class will issue an OM_UPDATE message to ICA_Target
through ICA_Map.  Subclasses of gadgetclass are advised to let the
superclass handle this method.

Attributes:
-----------

GA_Left                         (IS)
GA_Top                          (IS)
GA_Width                        (IS)
GA_Height                       (IS)

These correspond to position and dimension fields in the Intuition
Gadget structure.  Setting these clears the "gadget relative" flags
(below).

GA_RelRight                     (IS)
GA_RelBottom                    (IS)
GA_RelWidth                     (IS)
GA_RelHeight                    (IS)

These are alternative position/dimension attributes.  Setting these
stores the corresponding data in the Left/Top/Width/Height Gadget
fields, respectively, and sets the corresponding "relative" flag
(GRELRIGHT, GRELBOTTOM, and so on).

GA_IntuiText                    (IS)
GA_Text                         (IS)
GA_LabelImage                   (IS)

This copies the ti_Data value blindly into the Gadget.GadgetText field,
and sets the flags LABELSTRING and LABELIMAGE as appropriate in
Gadget.Flags.  GA_IntuiText requires that ti_Data be an IntuiText
pointer, as with old-style gadgets.  GA_Text takes a pointer to a NULL-
terminated string (UBYTE *).  GA_LabelImage takes a pointer to a
(boopsi) image.

Classes which support the attributes other than GA_IntuiText must
document themselves appropriately, but this facility allows us to have
low-overhead text gadgets and gadgets with iconic labels.

GA_Image                        (IS)

This may be a boopsi image or a regular image.  Things are designed so
that the image may be shared between gadgets. The image will not be
disposed when the gadget object is disposed.

GA_Border                       (IS)
GA_SelectRender                 (IS)
GA_ID                           (IS)
GA_UserData                     (IS)
GA_SpecialInfo                  (IS)

All of this group of attributes correspond to fields in the Gadget
structure.

GA_Disabled                     (IS)
GA_GZZGadget                    (IS)
GA_Selected                     (IS)
GA_EndGadget                    (IS)
GA_Immediate                    (IS)
GA_RelVerify                    (IS)
GA_FollowMouse                  (IS)
GA_RightBorder                  (IS)
GA_LeftBorder                   (IS)
GA_TopBorder                    (IS)
GA_BottomBorder                 (IS)
GA_ToggleSelect                 (IS)
GA_SysGadget                    (IS)
GA_TabCycle                     (IS)

This group corresponds to Boolean attributes (flags) in the Gadget
structure.  This class will put the correct flag in the correct field.
You can pass any non-zero value in the ti_Data tag field to cause the
corresponding flag to be set.  Pass zero to clear.

GA_HighLight                    (IS)

Sets the "GADGHIGHBITS" portion of Gadget.Flags to the attribute value
in ti_Data.

GA_SysGType                     (IS)

Sets the system gadget type portion of Gadget.GadgetType to the (masked)
value in ti_Data.

GA_Previous                     (I)

Previous gadget (or (struct Gadget **)) in linked list.  This attribute
cannot be used to link new gadgets into the gadget list of an open
window or requester.  You must use AddGList().

ICA_Target                      (IS)
ICA_Map                         (IS)

These are given the same meaning as in icclass, from which they are
borrowed.


propgclass

Class:                  propgclass
Superclass:             gadgetclass
Description:            Extended function proportional gadgets.
Include File:           <intuition/gadgetclass.h>

New Methods:
------------

None.

Changed Methods:
----------------

All methods defined by gadgetclass are handled to provide compatible
proportional gadget processing.

OM_SET, OM_UPDATE - Changes attributes and, if needed and if propgclass
is the true class, will update the slider visuals by updating the knob
position and dimensions.

GM_HANDLEINPUT - If the knob position changes sufficiently to change
PGA_Top, this method will issue an OM_NOTIFY message, with attributes
PGA_Top and GA_ID.  The OPUF_INTERIM flag will be set for intermediate
messages issued while the mouse is dragging the slider knob. This method
Will issue a message with OPUF_INTERIM clear when it is done, which is
the "final value".

Attributes:
-----------

GA_Image                        (I)
GA_Border                       (I)

If you don't pass GA_Image to NewObject(), the gadget will create and
use an AUTOKNOB.  Likewise if you pass (the "illegal" attribute)
GA_Border: an AUTOKNOB will be used instead.

GA_HighLight                    (I)

GADGHBOX highlighting is not allowed, and will be converted to GADGHBOX.

GA_SpecialInfo                  ()

This attributed is "forced" to point to the PropInfo allocated for
objects of this class.

Other gadgetclass attributes are passed along to the superclass.

PGA_Freedom                     (IG)

May be either of FREEHORIZ or FREEVERT (not both).  The default is
FREEVERT.

PGA_Borderless                  (I)

Means the same as PropInfo.Flags BORDERLESS.

PGA_HorizPot, PGA_VertPot, PGA_HorizBody, PGA_VertBody

These are defined in the include file but obsolete and will not be
supported.  Class propgclass supports gadgets that are vertical or
horizontally free, but not both.

PGA_Top                         (ISGNU)
PGA_Visible                     (ISU)
PGA_Total                       (ISU)

These attributes are very useful replacements to Pot and Body variables.
They are based on the use of proportional gadgets to control scrolling
text.  When scrolling 100 lines of text in a 25 line visible window, you
would set PGA_Total to 100, PGA_Visible to 25, and watch PGA_Top run
from 0 to 75 (the top line of the last page).  All internal prop gadget
values will be calculated based on these (depending on whether the
gadget is FREEHORIZ or FREEVERT). "Container clicks" for page jumps will
leave an overlap of one line, unless the value PGA_Visible is 1, in
which case the prop gadget acts as an integer numeric slider taking
values from 0 to PGA_Total - 1.  Note that PGA_Top has OM_NOTIFY access.
All three of these attributes have OM_UPDATE access, so they can be
controlled via interconnections.

PGA_NewLook                     (I)

Equivalent to PropInfo.Flags PROPNEWLOOK flag.


strgclass

Class:                  strgclass
Superclass:             gadgetclass
Description:            Intuition compatible string gadgets.
Include File:           <intuition/gadgetclass.h>

New Methods:
------------

None.

Changed Methods:
----------------

All methods defined by gadgetclass are handled to provide compatible
string gadget processing.

OM_NEW - Sets up StringInfo and StringExtend structures.  Will allocate
a Buffer if needed and will use shared data buffers for UndoBuffer and
WorkBuffer if the MaxChars is less than SG_DEFAULTMAXCHARS (128).
Default text pens are FG = 1, BG = 0;

Attributes:
-----------

GA_ID                           (ISG)

Will be included in OM_NOTIFY messages generated.

STRINGA_MaxChars                (I)
STRINGA_Buffer                  (I)
STRINGA_UndoBuffer              (I)
STRINGA_WorkBuffer              (I)

Specify various buffers defined for string gadgets and extended string
gadgets.  If your value of STRINGA_MaxChars is less than
SG_DEFAULTMAXCHARS (120 for now), then this class can provide all these
buffers for you.  Note that UndoBuffer and WorkBuffer can be shared by
many separate gadgets, providing they are as large as the largest
MaxChars they will encounter.

STRINGA_BufferPos               (ISU)
STRINGA_DispPos                 (ISU)

Familiar cursor and scroll position.

STRINGA_AltKeyMap               (IS)

Same as StringInfo.AltKeyMap.

STRINGA_Font                    (IS)

Font for string gadget text.  Must be an open TextFont.

STRINGA_Pens                    (IS)

Pen numbers, packed as two shorts into a longword, for rendering gadget
text.

STRINGA_ActivePens              (IS)

Optional pen numbers, packed as two shorts into a longword, for
rendering gadget text, when the gadget is active.

STRINGA_EditHook                (I)

Custom string gadget edit hook.

STRINGA_EditModes               (IS)

Value taken from flags defined in <intuition/sghooks.h> for initial
editing modes.

STRINGA_ReplaceMode             (IS)
STRINGA_FixedFieldMode          (IS)
STRINGA_NoFilterMode            (IS)

These three are independent Boolean equivalents to the individual flags
that you can set for STRINGA_EditModes.

STRINGA_Justification           (IS)

Takes the values STRINGCENTER, STRINGRIGHT, and STRINGLEFT (which is 0).

STRINGA_LongVal                 (ISGNU)

When you specify this to a string gadget object, it means first that the
gadget is now for integer entry only, and the value of the gadget takes
the numeric value passed in ti_Data.  Note that this attribute has
OM_NOTIFY and OM_UPDATE access.

STRINGA_TextVal                 (ISGNU)

When you specify this to a string gadget object, it means that the
gadget is for text entry only, and the value of the gadget is copied
from the string value passed as a UBYTE pointer in ti_Data.  Note that
this attribute has OM_NOTIFY and OM_UPDATE access.

STRINGA_ExitHelp                (IS)

Set this if you want the gadget to exit when the ``Help'' key is
pressed.  Look for a code of 0x5f, the rawkey code for help.

Notification messages will be issued whenever the gadget chooses to go
inactive (not when it is aborted).  The OPUF_INTERIM flag is always
clear.


groupgclass

Class:                  groupgclass
Superclass:             gadgetclass
Description:            Composite gadget objects
Include File:           <intuition/gadgetclass.h>

New Methods:
------------

None

Changed Methods:
----------------

OM_SET - Passes most attributes to the superclass, but propagates
changes in position to its members appropriately. Also, GA_Width and
GA_Height are calculated from the position and dimension of the
membership.

OM_ADDMEMBER - add a gadget to the group list.  Add the gadgets you want
in the group right after you create it and leave them there until you
are done.  Note that all members of the groupgclass object will be
deleted by OM_DISPOSE.

OM_DISPOSE - this class will dispose of the object and all its member
gadgets.

Attributes:
-----------

LAYOUTA_Orientation
LAYOUTA_Spacing
LAYOUTA_LayoutObj

These attributes specify simple layout parameters and a "layout object
delegate" are not currently implemented.  GA_Width and GA_Height are
calculated from the membership.

GA_Left                         (IS)
GA_Position                     (IS)

These are propagated magically to the membership.

The gadget relative flags (GA_RelWidth, GA_RelHeight, and so on) are not
supported.


buttongclass

Class:                  buttongclass
Superclass:             gadgetclass
Description:            A (repeatable) command button gadget.
Include File:           <intuition/gadgetclass.h>

New Methods:
------------

None.

Changed Methods:
----------------

GM_HITTEST - Delegates this question to its GA_Image attribute.

GM_HANDLEINPUT - Will behave like a button, but continuously issues
OM_NOTIFY messages for each IECLASS_TIMER event.

Flag OPUF_INTERIM will be set for all but the last notification.

The notified attribute is GA_ID, with a twist: the value sent will be
the negative of GadgetID if the pointer is not currently over the gadget
image.

GM_RENDER - All rendering is passed along to the GadgetRender Image.
The state provided is  IDS_INACTIVESELECTED, IDS_INACTIVENORMAL,
IDS_SELECTED, or IDS_NORMAL.

Attributes:
-----------

GA_Image                        (IS)

Changing the image will cause the gadget to refresh itself.


frbuttonclass

Class:                  frbuttonclass
Superclass:             buttongclass
Description:            A button gadget that knows how to outline its
                        "label" within a shared "frame image".

New Methods:
------------

None.

Changed Methods:
----------------

OM_NEW - Will set up its dimensions depending on GA_Image, including
support for frame images.  If GA_Image understands the IM_FRAMEBOX
method, dimensions are calculated to surround the "label" stashed in
GadgetText, which can be GA_IntuiText, GA_Text, or GA_LabelImage.

OM_SET - If you change the dimensions, this method will adjust the
contents by using IM_FRAMEBOX with FRAMEIF_SPECIFY.

GM_HITTEST - uses IM_HITFRAME.

GM_RENDER - uses IM_DRAWFRAME.  First draws the frame, then draws the
contents or label described under OM_NEW.

Attributes:
-----------

GA_Width                        (IS)
GA_Height                       (IS)

If you change these, the contents will be readjusted and the gadget re-
rendered.


IV-23/boopsi1.c

;/* boopsi1.c - Execute me to compile me with SAS/C 6.56
sc DATA=NEAR NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 boopsi1.c
slink FROM LIB:c.o,boopsi1.o TO boopsi1 LIBRARY LIB:sc.lib,LIB:Amiga.lib
quit
*/

/* boopsi example showing simple creation of boopsi
** gadgets and using system images.
*/
/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <intuition/intuition.h>
#include <intuition/classusr.h>
#include <intuition/imageclass.h>
#include <intuition/gadgetclass.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }
#endif

UBYTE *vers = "\0$VER: boopsi1 1.0";

void ProcessWindow(void);

#define MYPROP       1L
#define MYSTRING     2L
#define MYLEFTBUT    3L
#define MYRIGHTBUT   4L

#define GADTOP      10L
#define STRLEFT     20L
#define STRWIDTH    30L
#define STRHEIGHT   11L
#define INITVALUE   25L
#define PROPWIDTH   100L
#define PROPVIS     10L
#define BUTGADWID   11L
#define BUTGADHEI   11L

struct Screen *screen;
struct Window *window;
struct DrawInfo *drinfo;
struct Library *IntuitionBase;
struct Gadget *prop, *string, *leftbut, *rightbut, *mygadgets;
struct Image *rightbimage, *leftbimage;

void main(void)
{
    struct Gadget *tmpgad;
    WORD gadtop;

    tmpgad = (struct Gadget *)&mygadgets;

    if (IntuitionBase = OpenLibrary("intuition.library", 36L))
    {
        if (screen = LockPubScreen(NULL))
        {
            /* need my screen's DrawInfo for the system gadget images */
            drinfo = GetScreenDrawInfo(screen);

            gadtop = screen->Font->ta_YSize + GADTOP;
            if (window = OpenWindowTags(NULL,
                    WA_Title, (ULONG *)"AMail boopsi1",
                    WA_Height, gadtop+STRHEIGHT+10L,
                    WA_Width,  STRLEFT+STRWIDTH+PROPWIDTH+2*BUTGADWID+15,
                    WA_Flags, WFLG_DEPTHGADGET | WFLG_DRAGBAR | WFLG_CLOSEGADGET,
                    WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_GADGETUP,
                            TAG_END))
            {

                /* Create a boopsi string gadget */
                if (string = (struct Gadget *)NewObject(NULL, "strgclass",
                            /* All the normal Gadget fields */
                            GA_ID,              MYSTRING,
                            GA_Immediate,           TRUE,
                            GA_RelVerify,           TRUE,
                            GA_Top,             gadtop,
                            GA_Left,            STRLEFT,
                            GA_Width,           STRWIDTH,
                            GA_Height,          STRHEIGHT,
                            STRINGA_MaxChars,   3,
                            STRINGA_LongVal,    INITVALUE,
                            STRINGA_Justification, STRINGRIGHT,

                            /* Boopsi makes it easy to link gadgets together.
                            ** The GA_Previous tag accepts a (struct Gadget **)
                            ** to the previous gadget in the list, then changes
                            ** this value to point to the gadget being
                            ** created (in this case, "string").
                            */
                            GA_Previous,        tmpgad,
                            TAG_END))
                {
                    /* create the prop gadget */
                    if (prop = (struct Gadget *)NewObject(NULL, "propgclass",
                                GA_Immediate,   TRUE,
                                GA_RelVerify,   TRUE,
                                PGA_Freedom,    FREEHORIZ,
                                PGA_Borderless, FALSE,
                                GA_Left,        STRLEFT + STRWIDTH,
                                GA_Top,         gadtop,
                                GA_Height,      BUTGADHEI,
                                PGA_Top,        INITVALUE,
                                PGA_Visible,    PROPVIS,
                                PGA_Total,      PROPWIDTH,
                                GA_ID,          MYPROP,

                                /* link prop to string and
                                ** make tmpgad point to prop. */
                                GA_Previous,    tmpgad,
                                TAG_END))
                    {
                        /* Ask the system for a left arrow image
                        ** for the left arrow gadget. */
                        if (leftbimage = (struct Image *)NewObject(NULL,
                            "sysiclass",

                            /* boopsi needs this screen's DrawInfo
                            ** structure to get the right image.  */
                            SYSIA_DrawInfo,   drinfo,
                            SYSIA_Which,      LEFTIMAGE,

                            /* this will give us 11 x 11 buttons */
                            SYSIA_Size,       SYSISIZE_MEDRES,
                                  TAG_END))
                        {
                            /* Now ask for a right arrow */
                            if (rightbimage = (struct Image *)NewObject(NULL,
                                "sysiclass",
                                SYSIA_DrawInfo,   drinfo,
                                SYSIA_Which,      RIGHTIMAGE,
                                SYSIA_Size,       SYSISIZE_MEDRES,
                                              TAG_END))
                            {
                                /* Create the left button */
                                if (leftbut = (struct Gadget *)NewObject(NULL,
                                    "buttongclass",
                                    GA_ID,        MYLEFTBUT,
                                    GA_Immediate, TRUE,
                                    GA_RelVerify, TRUE,
                                    GA_Image,     leftbimage,
                                    GA_Top,       gadtop,
                                    GA_Left,      STRLEFT+STRWIDTH+PROPWIDTH-15,
                                    GA_Width,     BUTGADWID,
                                    GA_Height,    BUTGADHEI,
                                    GA_Previous,  tmpgad,
                                    TAG_END))
                                {
                                    /* Create the right button */
                                    if (rightbut = (struct Gadget *)NewObject(NULL,
                                        "buttongclass",
                                        GA_ID,        MYRIGHTBUT,
                                        GA_Immediate, TRUE,
                                        GA_RelVerify, TRUE,
                                        GA_Image,     rightbimage,
                                        GA_Top,       gadtop,
                                        GA_Left,
                                            STRLEFT+STRWIDTH+PROPWIDTH+BUTGADWID-10,
                                        GA_Width,     BUTGADWID,
                                        GA_Height,    BUTGADHEI,
                                        GA_Previous,  tmpgad,
                                        TAG_END))
                                    {
                                        /* All of the gadgets have been created
                                        ** and linked together.  Add them to the
                                        ** display and display them.
                                        */
                                        AddGList(window, mygadgets, -1, -1, NULL);
                                        RefreshGList(mygadgets, window, NULL, -1);
                                        ProcessWindow();
                                        RemoveGList(window, mygadgets, -1);
                                        DisposeObject(rightbut);
                                    }
                                    DisposeObject(leftbut);
                                }
                                DisposeObject(rightbimage);
                            }
                            DisposeObject(leftbimage);
                        }
                        DisposeObject(prop);
                    }
                    DisposeObject(string);
                }
                CloseWindow(window);
            }
            FreeScreenDrawInfo(screen, drinfo);
            UnlockPubScreen(NULL, screen);
        }
        CloseLibrary(IntuitionBase);
    }
}

void ProcessWindow(void)
{
    struct IntuiMessage *imsg;
    BOOL returnvalue = TRUE;
    ULONG class;
    LONG currval = INITVALUE;
    struct Gadget *g;

    while (returnvalue)
    {
        WaitPort(window->UserPort);
        while (imsg = (struct IntuiMessage *)GetMsg(window->UserPort))
        {
            g = (struct Gadget *)imsg->IAddress;
            class = imsg->Class;
            ReplyMsg((struct Message *)imsg);
            switch (class)
            {
                case IDCMP_CLOSEWINDOW:
                    returnvalue = FALSE;
                    break;
                case IDCMP_GADGETUP:
                    switch (g->GadgetID)
                    {
                        case MYLEFTBUT:
                            currval--;
                            break;
                        case MYRIGHTBUT:
                            currval++;
                            break;
                        case MYPROP:
                            /* read the prop gadget's value */
                            GetAttr(PGA_TOP, prop, &currval);
                            break;
                        case MYSTRING:
                            /* read the string gadget's value */
                            GetAttr(STRINGA_LongVal, string, &currval);
                            break;
                    }
                    /* make sure the value is between 0 and 90 */
                    if (currval < 0L)
                        currval = 0L;
                    else
                        if (currval > PROPWIDTH - PROPVIS)
                            currval = PROPWIDTH - PROPVIS;

                    /* Update the values of the prop and string.
                    ** gadgets (Intuition takes care of the  refresh). */

                    SetGadgetAttrs( prop, window, NULL,
                                    PGA_TOP, currval,
                                TAG_END );

                    SetGadgetAttrs( string, window, NULL,
                                STRINGA_LongVal, currval,
                                    TAG_END );

                    break;
            }
        }
    }
}


IV-41/mytextlabelclass.c

/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
 *
 * Written by David N. Junod
 *
 * Compiled with SAS/C 6.56 sc NMINC STRMERGE OPTSIZE OPTIMIZE OPTGLOBAL NOSTKCHK
 * (must be linked with classface.o and hookface.o)
 *
 * The Image structure as used by this class:
 *
 * struct Image {
 *
 * SHORT    LeftEdge;        <----Offset relative to the container
 * SHORT    TopEdge;
 *
 * SHORT    Width;           <----Contains the text extent of the string
 * SHORT    Height;
 *
 * SHORT    Depth;           <----Maintained by boopsi (must be set to CUSTOMIMAGEDEPTH).
 *
 * USHORT   *ImageData;      <----Pointer to a NULL terminated text string
 *
 * UBYTE    PlanePick;       <----We use this for the foreground color
 *
 * UBYTE    PlaneOnOff;      <----We use this for the background color
 *
 * struct Image *NextImage;  <----Pointer to the next image.  Handled by DrawImage(). };
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/libraries.h>
#include <intuition/intuition.h>
#include <intuition/classes.h>
#include <intuition/classusr.h>
#include <intuition/cghooks.h>
#include <intuition/gadgetclass.h>
#include <intuition/imageclass.h>
#include <intuition/icclass.h>
#include <intuition/screens.h>
#include <graphics/gfx.h>
#include <graphics/gfxmacros.h>
#include <libraries/gadtools.h>
#include <utility/tagitem.h>
#include <clib/macros.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/utility_protos.h>
#include <string.h>

extern struct Library *SysBase, *DOSBase;
extern struct Library *IntuitionBase, *GfxBase, *UtilityBase;

/*
 * Because we are dealing with imageclass objects, the data structure that makes up the
 * object is an intuition Image structure.
 */
#define IM(o)   ((struct Image *)(o))

#define MYCLASSID       NULL
#define SUPERCLASSID    (IMAGECLASS)

Class          *initmyTextLabelClass(VOID);
ULONG           freemyTextLabelClass(Class * cl);
ULONG __saveds  dispatchmyTextLabel(Class * cl, Object * o, Msg msg);
ULONG           setmyTextLabelAttrs(Class * cl, Object * o, struct opSet * msg);
ULONG           getmyTextLabelAttr(Class * cl, Object * o, struct opGet * msg);
ULONG           drawmyTextLabel(Class * cl, Object * o, struct impDraw * msg);
WORD            aTextExtent(struct RastPort *, STRPTR, LONG, struct TextExtent *);
UWORD           GetLabelKeystroke(STRPTR label);
static VOID     getContentsExtent(Class * cl, Object * o, struct DrawInfo * drinfo);

/* prototypes of functions from classface.o */
ULONG           DoMethod(Object * o, ULONG methodID,...);
ULONG           DoSuperMethod(Class * cl, Object * o, ULONG methodID,...);
ULONG           CoerceMethod(Class * cl, Object * o, ULONG methodID,...);
ULONG           CM(Class * cl, Object * o, Msg msg);
ULONG           DM(Object * o, Msg msg);
ULONG           DSM(Class * cl, Object * o, Msg msg);
ULONG           SetSuperAttrs(Class * cl, Object * o, ULONG data,...);

struct localObjData
{
    /* Font to use */
    struct TextFont *lod_Font;

    /* The key that is underlined */
    UWORD           lod_Key;

    /* DrawMode */
    UBYTE           lod_Mode;
};

Class          *
initmyTextLabelClass(VOID)
{
    ULONG           hookEntry(); /* from hookface.o */
    Class          *cl;

    if (cl = MakeClass(MYCLASSID,
                       SUPERCLASSID, NULL,
                       sizeof(struct localObjData), 0))
    {
        /* Fill in the callback hook */
        cl->cl_Dispatcher.h_Entry = hookEntry;
        cl->cl_Dispatcher.h_SubEntry = dispatchmyTextLabel;
    }
    /* Return a pointer to the class */
    return (cl);
}

ULONG
freemyTextLabelClass(Class * cl)
{

    /* Try to free the public class */
    return ((ULONG) FreeClass(cl));
}

/*
 * The SAS "__saveds" flag tells the SAS compiler to put
 * the data storage address + 32766 into A4.
 */
ULONG           __saveds
dispatchmyTextLabel(Class * cl, Object * o, Msg msg)
{
    struct localObjData *lod;
    Object         *newobj;
    ULONG           retval;

    switch (msg->MethodID)
    {
    case OM_NEW:
        /* Pass up to the superclass... */
        if (newobj = (Object *) DSM(cl, o, msg))
        {
            struct TagItem *attrs = ((struct opSet *) msg)->ops_AttrList;
            struct DrawInfo *drinfo;

            /* Get the DrawInfo */
            drinfo = (struct DrawInfo *) GetTagData(SYSIA_DrawInfo, NULL, attrs);

            /* Get the instance data */
            lod = INST_DATA(cl, newobj);

            /* Establish defaults */
            IM(newobj)->PlanePick = 1;
            lod->lod_Mode = JAM1;

            /* Set the attributes */
            setmyTextLabelAttrs(cl, newobj, (struct opSet *) msg);

            /* Get the bounding rectangle of the label */
            getContentsExtent(cl, newobj, drinfo);
        }
        retval = (ULONG) newobj;
        break;

    case OM_GET:
        retval = getmyTextLabelAttr(cl, o, (struct opGet *) msg);
        break;

    case OM_UPDATE:
    case OM_SET:
        /* Do the superclass first */
        retval = DSM(cl, o, msg);

        /* Call our set routines */
        retval += setmyTextLabelAttrs(cl, o, (struct opSet *) msg);
        break;

    case IM_DRAW:               /* draw the label */
    case IM_DRAWFRAME:          /* drawmyTextLabel() will take care of
                                   extra framing info */
        retval = drawmyTextLabel(cl, o, (struct impDraw *) msg);
        break;

    /* Let the superclass handle everything else */
    default:
        retval = (ULONG) DSM(cl, o, msg);
        break;
    }

    return (retval);
}

/* Set attributes of an object */
ULONG
setmyTextLabelAttrs(Class * cl, Object * o, struct opSet * msg)
{
    struct localObjData *lod = INST_DATA(cl, o);
    struct TagItem *tags = msg->ops_AttrList;
    struct TagItem *tstate;
    struct TagItem *tag;
    ULONG           tidata;

    /* process rest */
    tstate = tags;
    while (tag = NextTagItem(&tstate))
    {
        tidata = tag->ti_Data;
        switch (tag->ti_Tag)
        {
        case IA_FGPen:
            IM(o)->PlanePick = (UBYTE) tidata;
            break;

        case IA_BGPen:
            IM(o)->PlaneOnOff = (UBYTE) tidata;
            break;

            /* Must be a TextFont pointer. */
        case IA_Font:
            /* Set the font */
            lod->lod_Font = (struct TextFont *) tidata;
            break;

            /* Drawing mode to use */
        case IA_Mode:
            lod->lod_Mode = (UBYTE) tidata;
            break;

        case IA_Data:
            IM(o)->ImageData = (USHORT *) tidata;
            lod->lod_Key = GetLabelKeystroke((STRPTR) tidata);
            break;
        }
    }

    return (1L);
}

/* Inquire attributes of an object */
ULONG
getmyTextLabelAttr(Class * cl, Object * o, struct opGet * msg)
{
    struct localObjData *lod = INST_DATA(cl, o);

    switch (msg->opg_AttrID)
    {
    case IA_Font:
        *msg->opg_Storage = (ULONG) lod->lod_Font;
        break;

    case IA_Mode:
        *msg->opg_Storage = (ULONG) lod->lod_Mode;
        break;

        /* Let the superclass try */
    default:
        return ((ULONG) DSM(cl, o, msg));
    }

    return (1L);
}

ULONG
drawmyTextLabel(Class * cl, Object * o, struct impDraw * msg)
{
    struct localObjData *lod = INST_DATA(cl, o);
    STRPTR          label = (STRPTR) IM(o)->ImageData;
    struct DrawInfo *di = msg->imp_DrInfo;
    struct RastPort *rp = msg->imp_RPort;
    struct TextFont *tf = NULL;
    WORD            len = strlen(label);
    WORD            left, top;
    WORD            height = 0;
    WORD            width = 0;
    WORD            i;

    /* Clear the key */
    lod->lod_Key = NULL;

    /* Get a pointer to the font to use */
    if (!(tf = lod->lod_Font) && di)
    {
        tf = di->dri_Font;
    }

    /* Make sure we have font pointer */
    if (tf)
    {
        /* Set the font */
        SetFont(rp, tf);
    }
    /* Figure out our coordinates */
    top = msg->imp_Offset.Y + IM(o)->TopEdge + rp->TxBaseline;
    left = msg->imp_Offset.X + IM(o)->LeftEdge;

    /* See if we have frame information. */
    if (msg->MethodID == IM_DRAWFRAME)
    {
        /* Center the text inside the frame. */
        width = msg->imp_Dimensions.Width;
        height = msg->imp_Dimensions.Height;
        top += ((height - IM(o)->Height) > 0) ? ((height - IM(o)->Height) / 2) : 0;
        left += ((width - IM(o)->Width) > 0) ? ((width - IM(o)->Width) / 2) : 0;
    }

    /* Set the colors */
    SetAPen(rp, IM(o)->PlanePick);
    SetBPen(rp, IM(o)->PlaneOnOff);

    /* Set the drawing mode */
    SetDrMd(rp, lod->lod_Mode);

    /* Move to the start */
    Move(rp, left, top);

    /* Step through string */
    for (i = 0; i < (len - 1); i++)
    {
        /* Is this an '_' ? */
        if (label[i] == '_')
        {
            WORD            bot = (top + rp->TxHeight - rp->TxBaseline);
            WORD            mark;

            /* Draw the first part of the string */
            Text(rp, label, i);

            /* Remember where we are in the string */
            mark = rp->cp_x;

            /* Draw the underscore */
            Move(rp, mark, bot);
            Draw(rp, (mark + TextLength(rp, &label[(i + 1)], 1L) - 2), bot);

            /* Return to where we were */
            Move(rp, mark, top);

            /*
             * Draw the rest of the string.  This one is done last so that the cursor
             * could be positioned after the text.
             */
            Text(rp, &label[(i + 1)], (len - i - 1));

            /* Return the underlined character */
            lod->lod_Key = (UWORD) label[i];
        }
    }

    /* Do we have an underscore? */
    if (!lod->lod_Key)
    {
        /* Didn't find an '_' sign */
        Text(rp, label, len);
    }
    return (1L);
}

UWORD
GetLabelKeystroke(STRPTR label)
{
    LONG            count = (label) ? strlen(label) : 0L;
    LONG            i;

    /* Search for an _ sign */
    for (i = 0; i < (count - 1); i++)
    {
        /* Did we find an _ sign? */
        if (label[i] == '_')
        {
            return ((UWORD) label[(i + 1)]);
        }
    }

    return (0);
}

/* TextExtent that honors the '_' as being a non-printable character (once) */
WORD
aTextExtent(struct RastPort * rp, STRPTR string, LONG count, struct TextExtent * te)
{
    WORD retval = FALSE;
    STRPTR buffer;
    LONG i;

    /* Allocate a temporary buffer */
    if (buffer = AllocVec ((count + 1), MEMF_CLEAR))
    {
    /* Step through string */
    for (i = 0; i < count; i++)
    {
            /* Is this an '_' sign? */
            if (string[i] == '_')
            {
        /* Add the rest of the label to the buffer */
        strcat (buffer, &string[(i + 1)]);

        /* Adjust the length of the string. */
        count--;
        break;
        }
        else
        {
        /* Copy each character over, until we reach the _ mark */
        buffer[i] = string[i];
        }
        }

        /* Get the extent */
        TextExtent(rp, buffer, count, te);

    /* Free the temporary buffer */
    FreeVec (buffer);

    /* Show that we were successful */
    retval = TRUE;
    }

    /* Return whatever textextent returned */
    return (retval);
}

static          VOID
getContentsExtent(Class * cl, Object * o, struct DrawInfo * drinfo)
{
    struct localObjData *lod = INST_DATA(cl, o);
    struct TextExtent te =
    {NULL};
    struct RastPort rp;
    STRPTR          label;

    /* maybe look at some flags to handle other types of text someday */
    if (label = (STRPTR) IM(o)->ImageData)
    {
        /* Initialize the RastPort */
        InitRastPort(&rp);

        if (lod->lod_Font)
        {
            SetFont(&rp, lod->lod_Font);
        }
        else if (drinfo && drinfo->dri_Font)
        {
            SetFont(&rp, drinfo->dri_Font);
        }
        /* Get the rectangle for the label */
        aTextExtent(&rp, label, strlen(label), &te);

        /* Set the image structure */
        IM(o)->Width = te.te_Width;
        IM(o)->Height = te.te_Height;
    }
    else
    {
        IM(o)->Width = IM(o)->Height = 0;
    }
}


IV-41/usemyIC.c

/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
 *
 * Compiled with SAS/C 6.56 NMINC STRMERGE OPTSIZE OPTIMIZE OPTGLOBAL NOSTKCHK
 * (must be linked with mytextlabelclass.o, classface.o and hookface.o)
 *
 * Written by David N. Junod
 */

#include <exec/types.h>
#include <exec/libraries.h>
#include <intuition/intuition.h>
#include <intuition/classes.h>
#include <intuition/classusr.h>
#include <intuition/cghooks.h>
#include <intuition/gadgetclass.h>
#include <intuition/imageclass.h>
#include <graphics/gfx.h>
#include <graphics/gfxmacros.h>
#include <libraries/gadtools.h>
#include <utility/tagitem.h>
#include <clib/macros.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/utility_protos.h>
#include <string.h>

extern struct Library *SysBase, *DOSBase;
struct Library *IntuitionBase, *GfxBase, *UtilityBase;

Class          *initmyTextLabelClass(VOID);
ULONG           freemyTextLabelClass(Class * cl);

VOID
main(VOID)
{
    Class          *cl;
    struct Image   *im;
    struct Window  *win;
    struct RastPort *rp;
    UWORD           top, left, height;

    /* Make sure we're at least using Version 2.0 */
    if (IntuitionBase = OpenLibrary("intuition.library", 36))
    {
        GfxBase = OpenLibrary("graphics.library", 36);
        UtilityBase = OpenLibrary("utility.library", 36);

        /* Open a window, without system gadgets or IDCMP events */
        if (win = OpenWindowTags(NULL,
                                 WA_Left, 10,
                                 WA_Top, 10,
                                 WA_Width, 320,
                                 WA_Height, 100,
                                 TAG_DONE))
        {
            /* Cache the pointer to the RastPort */
            rp = win->RPort;

            /* Cache the upper-left coordinates of the window */
            top = win->BorderTop + INTERHEIGHT;
            left = win->BorderRight + INTERWIDTH;

            /* Cache the height of the font */
            height = rp->TxHeight + INTERHEIGHT;

            /* Initialize the custom image class. */
            if (cl = initmyTextLabelClass())
            {
                /* Create a new image structure, using the given string. */
                if (im = NewObject(cl, NULL,
                                   IA_Data, (ULONG) "Line _1",
                                   TAG_DONE))
                {
                    /* Paint using the provided text string. */
                    DrawImageState(rp, im, left, top,
                                   IDS_NORMAL, NULL);

                    /* Replace the text string, and paint it. */
                    im->ImageData = (USHORT *) "Line _2";
                    DrawImageState(rp, im, left, top + height,
                                   IDS_NORMAL, NULL);

                    /* Replace the text string, and paint it. */
                    im->ImageData = (USHORT *) "Line _3";
                    DrawImageState(rp, im, left, top + (height * 2),
                                   IDS_NORMAL, NULL);

                    /* Free the image. */
                    DisposeObject(im);
                }

                /* Free the image class. */
                freemyTextLabelClass(cl);
            }

            Delay(250);
            CloseWindow(win);
        }

        CloseLibrary(UtilityBase);
        CloseLibrary(GfxBase);
        CloseLibrary(IntuitionBase);
    }
}


IV-59/adc.c

;/*
sc link ignore=73 adc.c
quit

Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

/****** AppWorkbench.demo/ADC *************************************************

    NAME
        ADC -- AppWorkbench - Complete and contained demo of how to use
               the AppWorkbench Interface.

    AUTHOR
        Fred Mitchell, Copyright © 1991-1999 Amiga, Inc.
        3.00    08 Jul 1991 - All known problems are rectified.

    FUNCTION
        Demonstrates use of AppIcons, AppMenu, and AppWindow.

    COMPILE
        sc link adc

******************************************************************************/

/* Includes */
#include <exec/types.h>
#include <intuition/intuition.h>
#include <workbench/icon.h>
#include <workbench/workbench.h>
#include <workbench/startup.h>
#include <dos.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/dostags.h>

/* Defines  */
#define ASIZE   500     /* size of the arrays */

/* Structs, externs, and prototypes */

struct AppWindow *awin = NULL;
struct Window *win = NULL;

struct AppIcon *aicon = NULL;

struct AppMenuItem *amenu[ASIZE];
char *appName[ASIZE];
short  amicount = NULL;

struct Remember *key = NULL;
struct MsgPort *aport = NULL;   /* message port to be used with appicon system */

struct Library  *GfxBase,
                *IntuitionBase,
                *IconBase,
                *WorkbenchBase,
                *GadToolsBase;

extern struct Library *DOSBase, *SysBase;

/* Prototypes   */

void _main(void);
void ProcessIcon(struct Window *win,
                 struct AppMessage *am);
UBYTE *BSTRtoSTR(ULONG b);
void ShutDown(void);
void warning(char *s);
void warning2(char *r, char *s);
void fatal(char *s);
void fatal2(char *r, char *s);
struct Window *MakeWindow(struct Remember **key);
void UpdateWindow(struct Window *win);
void FreePid(struct ProcID *pid);

/* Icon data    */
USHORT	chip	BlackHoleGadData1[] = {
/* Plane 0 */
    0x0000,0x01ff,0xf087,0xff00,0x0000,0x0000,0x01ff,0xb807,
    0xfc00,0x0000,0x0000,0x007f,0xbc07,0x7c00,0x0000,0x0000,
    0x000f,0xfc03,0xfc00,0x0000,0x0000,0x0007,0xfe23,0xfc00,
    0x0000,0x0000,0x0001,0xfe03,0xfc00,0x0000,0x0000,0x0220,
    0x7f07,0xfc00,0x0000,0x0000,0x0000,0x7f03,0xfc00,0x0000,
    0x0000,0x0000,0x3f07,0x9800,0x0000,0x0000,0x0000,0x3f03,
    0xf800,0x0000,0x0000,0x7ff0,0x0e07,0xf000,0x0000,0x0000,
    0xfffc,0x0e87,0xf000,0x0000,0x0033,0xeffe,0x0e1f,0xf000,
    0x0000,0x00ff,0xf7ff,0x7d0f,0xc200,0x3000,0x01ff,0xffff,
    0x3c9f,0xc000,0x3000,0x03ff,0xffff,0xabff,0x8000,0x7000,
    0x07ff,0x7e53,0xbeff,0x0000,0xf000,0x0f3e,0x7807,0xf7fe,
    0x0871,0xf000,0x13ff,0xe007,0x5b00,0x00e2,0xe000,0x01f3,
    0xc018,0xffd0,0x01e7,0xc000,0x03a3,0x800d,0x5b60,0x03ff,
    0xe400,0x07c7,0x087f,0xf7c0,0x1f7e,0x7800,0x0780,0x00ff,
    0xbee5,0x3ffc,0xf000,0x0700,0x01f9,0xca7f,0xffff,0xe000,
    0x0600,0x03f8,0x9eff,0xffff,0xc000,0x0600,0x27f4,0x3f7f,
    0xf7fe,0x8000,0x0000,0x0ff0,0xf83f,0xfbfc,0x0000,0x0000,
    0x0ff0,0x781f,0xff80,0x0000,0x0000,0x0fe0,0x7a07,0xff00,
    0x0000,0x0000,0x0fe0,0x7c00,0x0000,0x0000,0x0000,0x1ae0,
    0x7f00,0x0000,0x0000,0x0000,0x3fe0,0x7f00,0x2000,0x0000,
    0x0000,0x3fe0,0x3f84,0x0000,0x0000,0x0000,0x1fc0,0x3fc0,
    0x0000,0x0000,0x0000,0x3fe4,0x3ff0,0x0000,0x0000,0x0000,
    0x3fe0,0x3fff,0x0000,0x0000,0x0000,0x3ff0,0x3eff,0x8000,
    0x0000,0x0000,0x7ff0,0x9dff,0xc000,0x0000,
/* Plane 1 */
    0x0000,0x003c,0xf027,0x9f00,0x0000,0x0000,0x007f,0xf807,
    0xfc00,0x0000,0x0000,0x0057,0xcc43,0x7c00,0x0000,0x0000,
    0x0003,0xcd01,0xfc00,0x0000,0x0000,0x0100,0x0e01,0xec00,
    0x0000,0x0000,0x0000,0x0e01,0xfc00,0x0000,0x0000,0x0080,
    0x0701,0xfc00,0x0000,0x0000,0x0000,0x4101,0xfc00,0x0000,
    0x0000,0x0080,0x2103,0xf800,0x0000,0x0000,0x0002,0x1943,
    0x3800,0x0000,0x0000,0x7ff0,0x2986,0x0000,0x0000,0x0040,
    0xf88e,0x5984,0x1000,0x0000,0x0033,0xf801,0x090c,0xf000,
    0x0000,0x00fe,0xf800,0xfa68,0xc000,0x3000,0x01ff,0xf000,
    0xd3b8,0xd000,0x3000,0x03ff,0xf87e,0x54f0,0x8500,0x7000,
    0x07ff,0x704f,0x41e3,0x0000,0xf000,0x0f3e,0x600f,0x0802,
    0x0071,0xf000,0x03df,0xc000,0xa4fe,0x00f3,0xe000,0x01b3,
    0x805f,0x0071,0x00e6,0xc000,0x03e7,0x8032,0xa4e0,0x01fd,
    0xe000,0x07c7,0x0060,0x0848,0x037a,0x7800,0x0780,0x00cf,
    0xc179,0x07fc,0xf000,0x0700,0x518b,0xb5bf,0x0fff,0xe000,
    0x0600,0x071c,0xe500,0x07ff,0xc000,0x0600,0x0712,0x4f80,
    0x0fbe,0x8000,0x0000,0x0f10,0x9c40,0x0ffc,0x0000,0x0000,
    0x0c10,0x9e38,0x8f81,0x0000,0x0000,0x0902,0x8847,0xff00,
    0x0000,0x0000,0x0f80,0x4c00,0x8000,0x0000,0x0000,0x1fa0,
    0x4700,0x0000,0x0000,0x0000,0x3fc0,0x4100,0x8000,0x0000,
    0x0000,0x3fc0,0x0000,0x0000,0x0000,0x0000,0x1fc0,0x3880,
    0x4000,0x0000,0x0000,0x37c0,0x6180,0x0000,0x0000,0x0000,
    0x3fc1,0x21e3,0x0000,0x0000,0x0000,0x3fd0,0x37ff,0x8000,
    0x0000,0x0000,0x7f82,0x1ffc,0xc000,0x0000,
};

USHORT	chip	BlackHoleGadData2[] = {
/* Plane 0 */
    0x000b,0xfc00,0x9ff0,0x7fc0,0x0000,0x0043,0xc090,0x0fe5,
    0x1380,0x0000,0x000f,0x8003,0x0370,0x0300,0x0000,0x0027,
    0x0080,0x0362,0x03c0,0x0000,0x0002,0x0fcc,0x5ee0,0x07c0,
    0x0000,0x000c,0x1ffa,0x4ef0,0x07e0,0x2000,0x0008,0x3efe,
    0x00fc,0x2365,0x0000,0x0018,0x7fff,0xc075,0xa020,0x0000,
    0x403c,0x0f2b,0xc0bc,0x0034,0x0000,0x24de,0x098f,0x44f0,
    0x0019,0x0000,0x817e,0x1387,0xc0e3,0x001c,0x4000,0x0064,
    0x0380,0xc073,0x3a1f,0x0000,0x0000,0xc311,0x63c1,0x9e0e,
    0x0000,0x8080,0x0501,0xe6c1,0xfe06,0x0200,0x0100,0x2a01,
    0xff80,0xfe06,0x4400,0x0180,0x09c1,0xdf00,0x5405,0x0000,
    0x2548,0x0db1,0xfd04,0x2801,0x0800,0x0384,0x97ff,0xd700,
    0xf801,0x0000,0xa200,0x1fd6,0xffe3,0x7201,0x8800,0x2302,
    0x3e8f,0xbbe6,0xf081,0x8800,0x2300,0xbd07,0xfedf,0xf000,
    0x8a00,0x0100,0x7e0b,0xd7ff,0xd243,0x8000,0x2100,0xe843,
    0x7f1b,0x7025,0x4800,0x0140,0xd403,0xf707,0x0003,0x0000,
    0x44c0,0xfe0d,0xff00,0x8801,0x0000,0x80c1,0xfe3f,0x8b01,
    0xc002,0x0200,0x00c1,0xf36c,0x0621,0xa600,0x0000,0x01f1,
    0x9b7c,0x0e03,0x004c,0x0000,0x0471,0x81be,0x0fc3,0x00f9,
    0x0200,0x0131,0x837a,0x8bb7,0x40f6,0x4800,0x0040,0x837e,
    0x07dd,0xe1f8,0x0400,0x0009,0x8a5a,0x01fa,0xfef0,0x0000,
    0x014f,0x907c,0x41ff,0xf860,0x0000,0x080f,0xc03f,0xc4bf,
    0xf0c0,0x0000,0x0007,0xc09a,0xc447,0xe180,0x0000,0x0005,
    0xa01d,0x9004,0x0110,0x0000,0x0007,0xf03f,0xf110,0x0348,
    0x0000,0x0007,0xfebf,0xfa04,0x7f80,0x0000,
/* Plane 1 */
    0x0083,0x3c7f,0x9c70,0x7fc0,0x0000,0x0007,0xce7f,0x8c6a,
    0xd380,0x0000,0x001f,0xbfed,0x003f,0xc200,0x0000,0x0007,
    0x70fc,0x02ef,0xe3c0,0x0000,0x0002,0xcfcc,0x5d8b,0xe7c0,
    0x0000,0x0005,0x9824,0x0a17,0xe7e0,0x6000,0x000b,0x3886,
    0x5e0f,0xd360,0x0000,0x0018,0x7841,0xdf9d,0xf824,0x0000,
    0x003c,0x0e91,0xd684,0x78b4,0x0000,0x23de,0x6889,0x7ab0,
    0x18dc,0x0000,0x416e,0xf374,0x16a1,0x00dd,0x4000,0x0064,
    0xe379,0x9eb7,0x3a5e,0x0000,0x8001,0x634d,0x7981,0x9e4e,
    0x0000,0x8003,0xc574,0xa65f,0xf266,0x0000,0x0023,0xe93d,
    0xbfbf,0x62f6,0x4400,0x09e7,0xe9c5,0x003b,0xf5f1,0x2000,
    0x4767,0xc931,0x01eb,0x39e1,0x0000,0x07f3,0x9e4a,0x291c,
    0x09c1,0x0000,0x8267,0xd430,0x00c3,0x9341,0x9800,0x836d,
    0xa086,0x446e,0x176d,0x8200,0x3305,0xa366,0x009a,0x57cc,
    0x8200,0x0107,0x41fa,0x2827,0xfb9f,0xc000,0x010f,0xbb9b,
    0x0113,0x3fcd,0xc400,0x091e,0x8fb1,0x017f,0x0fcf,0x2000,
    0x44d8,0x81f9,0xfb79,0x0f88,0x0000,0x00c1,0xfebb,0x224d,
    0xcf80,0x0200,0x00c1,0xf36a,0x26dd,0xad00,0x0200,0x00f1,
    0x9be1,0xf93f,0x0e4c,0x0000,0x0571,0x8133,0xba5f,0x1ee9,
    0x0400,0x0071,0xb323,0x3027,0x5cf7,0x8800,0x0040,0xbb53,
    0xf72e,0xe1f8,0x0000,0x0049,0xbe65,0xf144,0x3ef0,0x0000,
    0x000f,0x8f40,0xac82,0x3860,0x0000,0x0c0c,0xdf23,0x40d8,
    0x30c0,0x0000,0x0004,0xcfd5,0xc447,0xe180,0x0000,0x0004,
    0xa7d4,0x905c,0x0120,0x0000,0x0007,0xf7f9,0xf1fd,0x83c0,
    0x0000,0x0007,0xf930,0x9ff8,0x7c80,0x0000,
};

struct	Image	BlackHoleGadI1 = {
    0, 0,				/* Top Corner */
    71, 38, 2,			/* Width, Height, Depth */
    &BlackHoleGadData1[0],		/* Image Data */
    0x0003, 0x0000,			/* PlanePick,PlaneOnOff */
    NULL				/* Next Image */
};

struct	Image	BlackHoleGadI2 = {
    0, 0,				/* Top Corner */
    71, 38, 2,			/* Width, Height, Depth */
    &BlackHoleGadData2[0],		/* Image Data */
    0x0003, 0x0000,			/* PlanePick,PlaneOnOff */
    NULL				/* Next Image */
};

struct Gadget gad =
   {
   NULL,			/* Next Gadget		   */
   NULL,NULL,		/* Left Edge, Top Edge	   */
   71,38,			/* Width, Height	   */
   GFLG_GADGHIMAGE, /* Flags		   */
   NULL,            /* Activation  */
   NULL,			/* Gadget Type		   */
   (APTR)&BlackHoleGadI1,   /* Gadget Render	   */
   (APTR)&BlackHoleGadI2,   /* Select Render	   */
   NULL,                    /* Gadget Text		   */
   NULL,                    /* Mutual Exclude	   */
   NULL,                    /* Special Info		   */
   };

void main()
{
    /* Automatic variables  */
    ULONG sig;
    struct DiskObject *dob = NULL;
    struct AppMessage *am;
    struct IntuiMessage *tim, im;
    struct FileInfoBlock *fib = NULL;
    BOOL alive = TRUE;

    if (!(IntuitionBase = (void *) OpenLibrary("intuition.library", 37)))
        fatal("Can't open Intuition.library");

    if (!(GfxBase = (void *) OpenLibrary("graphics.library", 37)))
        fatal("Can't open graphics.library");

    if (!(IconBase = (void *) OpenLibrary("icon.library", 37)))
        fatal("Can't open icon.library");

    if (!(WorkbenchBase = (void *) OpenLibrary("workbench.library", 37)))
        fatal("Can't open workbench.library");

    fib = (struct FileInfoBlock *) calloc(sizeof(*fib), 1);  /* allocate the FileInfoBlock */

    win = MakeWindow(&key);
    aport = (void *) CreatePort(NULL, 0);
    awin = (struct AppWindow *) AddAppWindow(0, win, win, aport, NULL);    /* setup appwindow */
    if (!win || !aport || !awin)
        fatal2("ADC: General Failure.", "Could be Low Memory condition.");

    /* setup disk object    */
    dob = (struct DiskObject *) calloc(sizeof(*dob), 1);
    dob->do_Magic = NULL;
    dob->do_Version = NULL;
    dob->do_Gadget = gad;
    dob->do_Type = NULL;
    dob->do_DefaultTool = NULL;
    dob->do_ToolTypes = NULL;
    dob->do_CurrentX = dob->do_CurrentY = NO_ICON_POSITION;
    dob->do_DrawerData = NULL;
    dob->do_ToolWindow = NULL;
    dob->do_StackSize = 0;

    if (!(aicon = (struct AppIcon *) AddAppIcon(NULL, NULL, "Application", aport, NULL, dob, TAG_END)))
        fatal("ADC: Could not create AppIcon");
    amenu[amicount++] = (void *) AddAppMenuItem(NULL, "Quit", "Quit AppDemo", aport, NULL);

    while (alive)
    {
        sig = (1 << aport->mp_SigBit) |
                ((win) ? (1 << win->UserPort->mp_SigBit) : NULL);
        sig = Wait(sig);

        /* App Messages   */
        if (sig & (1 << aport->mp_SigBit)) /* an app signal */
        {
            while (am = (struct AppMessage *) GetMsg(aport))
            {
                switch(am->am_Type)
                {
                case AMTYPE_APPWINDOW:   /* something was dropped in the window  */
                    ProcessIcon(win, am);
                    break;

                case AMTYPE_APPICON:     /* icon was double-clicked */
                    if (!am->am_NumArgs) /* Double-Clicked  */
                    {
                        if (!win) /* is our (app) window open? */
                        {
                            if (!(win = MakeWindow(&key)))
                            {
                                warning("ADC: Cannot open window!");
                                break;
                            }

                            if (!(awin = (struct AppWindow *) AddAppWindow(NULL, NULL, win, aport, NULL)))
                            {
                                warning("ADC: Cannot make window an AppWindow!");
                                CloseWindow(win); win = NULL;
                            }
                        }
                        WindowToFront(win);
                        ActivateWindow(win);
                        UpdateWindow(win);
                    }
                    else /* Icons dropped on AppIcon    */
                        ProcessIcon(win, am);

                    break;

                case AMTYPE_APPMENUITEM: /* menu item was selected */
                    if (!stricmp(am->am_UserData, "quit"))
                        alive = FALSE;

                    else /* we have something real */
                    {
                        SystemTags(am->am_UserData, SYS_Input, Open("nil:", MODE_NEWFILE),
                                                    SYS_Output, Open("CON:////Application_Output/CLOSE/AUTO/WAIT", MODE_NEWFILE),
                                                    SYS_Asynch, TRUE,
                                                    NP_StackSize, 30000,    /* Let's be generous    */
                                                    NP_Priority, 0,
                                                    NP_Cli, FALSE,
                                                    TAG_END, NULL);
                    }
                    break;

                default:
                    break;
                }
                ReplyMsg(am);
            }
        }

        /* Window Messages    */
        if (win && (sig & (1 << win->UserPort->mp_SigBit))) /* an IDCMP signal */
        {
            while (win && (tim = (struct IntuiMessage*) GetMsg(win->UserPort)))
            {
                im = *tim;
                ReplyMsg(tim);
                switch (im.Class)
                {
                case CLOSEWINDOW:
                    UpdateWindow(win);
                    RemoveAppWindow(awin); awin = NULL;
                    CloseWindow(win); win = NULL;
                    break;

                case NEWSIZE:
                case REFRESHWINDOW:
                    UpdateWindow(win);
                    break;

                default:
                    break;
                }
            }
        }
    }

    ShutDown();
}

void ProcessIcon(struct Window *win, struct AppMessage *am)
{
    UBYTE buf[256], *name;  /* general work buffer & pointer */
    struct FileInfoBlock *fib = (struct FileInfoBlock *) calloc(1, sizeof(*fib));
    int i;

    if (fib)
    {
        for (i = 0; i < am->am_NumArgs; ++i)    /* until list exhausted */
        {
            if (am->am_ArgList[i].wa_Lock)
            {
                if (Examine(am->am_ArgList[i].wa_Lock, fib))
                {
                    if (!NameFromLock(am->am_ArgList[i].wa_Lock, buf, sizeof(buf)))
                        fatal("ADC: GetPath failed!!");

                    if (buf[strlen(buf)-1] != ':') /* do we need to add a slash?    */
                    {
                        buf[strlen(buf)+1] = NULL;
                        buf[strlen(buf)] = '/';
                    }

                    /* append name to path
                    */
                    if (amicount < ASIZE)
                    {
                        appName[amicount] = name = (char*) strdup(am->am_ArgList[i].wa_Name);
                        strcat(buf, am->am_ArgList[i].wa_Name);
                        amenu[amicount] = (struct AppMenu*) AddAppMenuItem(amicount, strdup(buf), name, aport, NULL);
                        ++amicount;
                    }
                    else
                        warning2("ADC: Array Overflow - Cannot add", am->am_ArgList[i].wa_Name);
                }
                else
                    warning2("ADCCant find directory for", am->am_ArgList[i].wa_Name);
            }
            else
                warning2("ADC: Entry Without Lock!!", am->am_ArgList[i].wa_Name);
        }
        UpdateWindow(win);

        free(fib);
    }
}

UBYTE *BSTRtoSTR(b)
ULONG b;
{
    UBYTE *bstr, *str, *s;
    int c;

    bstr = BADDR(b);
    str = s = (UBYTE*) calloc(1, (c = *bstr++) + 1);
    while(c--)
        *s++ = *bstr++;

    return str;
}

void ShutDown()
{
    int i;

    for (i = 0; i < amicount; ++i)
        if (!RemoveAppMenuItem(amenu[i]))
            warning("ADC: RemoveAppMenuItem failed!");
    amicount = 0;

    if (aicon)
    {
        if (!RemoveAppIcon(aicon))
            warning("ADC: RemoveAppIcon failed!");
        aicon = NULL;
    }

    if (awin)
    {
        if (!RemoveAppWindow(awin))
            warning("ADC: RemoveAppWindow Failed!");
        awin = NULL;
    }
    if (win)
        CloseWindow(win), win = NULL;

    if (aport)
        DeletePort(aport), aport = NULL;

    FreeRemember(&key, TRUE);

    if (GfxBase)        CloseLibrary(GfxBase),       GfxBase = NULL;
    if (IntuitionBase)  CloseLibrary(IntuitionBase), IntuitionBase = NULL;
    if (IconBase)       CloseLibrary(IconBase),      IconBase = NULL;
    if (WorkbenchBase)  CloseLibrary(WorkbenchBase), WorkbenchBase = NULL;

    exit(0);
}

struct NewWindow newwin = {
    100, 100,   /* LeftEdge, TopEdge */
    300, 150,   /* Width, Height */
    1, 2,       /* DetailPen, BlockPen */
    CLOSEWINDOW | NEWSIZE | MOUSEBUTTONS | VANILLAKEY,  /* IDCMPFlags */
    WINDOWSIZING | WINDOWDRAG | WINDOWCLOSE | WINDOWDEPTH | SMART_REFRESH | GIMMEZEROZERO, /* Flags */
    NULL,       /* FirstGadget */
    NULL,       /* CheckMark */
    NULL,       /* Title */
    NULL,       /* Screen */
    NULL,       /* BitMap */
    50, 50, -1, -1, /* MinWidth, MinHeight, MaxWidth, MaxHeight */
    WBENCHSCREEN    /* Type */
    };

struct Window *MakeWindow(key) /* standard window creation */
struct Remember **key;
{
    struct Window *win;

    if (win = (struct Window*) OpenWindow(&newwin))
        SetWindowTitles(win, "AppDemo", "Application Launcher by Fred Mitchell");

    return win;
}

void UpdateWindow(win)  /* display list of programs in window */
struct Window *win;
{
    short height, i;

    if (win)
    {
        SetRast(win->RPort, 0);
        SetAPen(win->RPort, 1);
        SetDrMd(win->RPort, JAM1);
        height = win->RPort->Font->tf_YSize + 2;

        for (i = 1; i < amicount; ++i)
        {
            Move(win->RPort, 0, height * i);
            Text(win->RPort, appName[i], strlen(appName[i]));
        }

        /* update newwindow structure with new size/location    */
        newwin.LeftEdge = win->LeftEdge;
        newwin.TopEdge  = win->TopEdge;
        newwin.Width    = win->Width;
        newwin.Height   = win->Height;
    }
}

void FreePid(pid)   /* free the list of ProcessID's */
struct ProcID *pid;
{
    if (pid->nextID)
        FreePid(pid->nextID);

    /* free(pid); ...*/
}

/* Warning and Fatal Routines   */

static int _GetResponse(struct Window *win)
{
    int ret = (int) win;

    if ((BOOL) win != 0 && (BOOL) win != 1)
    {
        while ((ret = SysReqHandler(win, NULL, TRUE)) == -2)
            ;
        FreeSysRequest(win);
    }
    return ret;
}

void fatal(m)  /* Program bug detected - could be fatal! */
char *m;    /* message */
{
    struct EasyStruct es;

    es.es_StructSize = sizeof(es);
    es.es_Flags = NULL;
    es.es_Title = "<FATAL ERROR>";
    es.es_TextFormat = "Fatal Error: %s";
    es.es_GadgetFormat = "OK";

    _GetResponse((struct Window*) BuildEasyRequest(NULL, &es, NULL, m));
    ShutDown();
}

void fatal2(m, n)  /* Program bug detected - could be fatal! */
char *m, *n;    /* message */
{
    struct EasyStruct es;

    es.es_StructSize = sizeof(es);
    es.es_Flags = NULL;
    es.es_Title = "<FATAL ERROR>";
    es.es_TextFormat = "Fatal Error: %s\n%s";
    es.es_GadgetFormat = "OK";

    _GetResponse((struct Window*) BuildEasyRequest(NULL, &es, NULL, m, n));
    ShutDown();
}

void warning(m) /* Far less serious - non-fatal error */
char *m;    /* message */
{
    struct EasyStruct es;

    es.es_StructSize = sizeof(es);
    es.es_Flags = NULL;
    es.es_Title = "Warning";
    es.es_TextFormat = "Error: %s";
    es.es_GadgetFormat = "Continue";

    _GetResponse((struct Window*) BuildEasyRequest(NULL, &es, NULL, m));
}

void warning2(m, n) /* Far less serious - non-fatal error */
char *m, *n;    /* messages */
{
    struct EasyStruct es;

    es.es_StructSize = sizeof(es);
    es.es_Flags = NULL;
    es.es_Title = "Warning";
    es.es_TextFormat = "Error: %s\n%s";
    es.es_GadgetFormat = "Continue";

    _GetResponse((struct Window*) BuildEasyRequest(NULL, &es, NULL, m, n));
}


IV-59/AppWindow.c

;/* AppWindow.c - Execute me to compile me with SAS/C 6.56
sc NMINC STRMERGE NOSTKCHK NODEBUG DATA=NEAR IGNORE=73 AppWindow.c
slink FROM LIB:c.o,AppWindow.o TO AppWindow LIBRARY LIB:sc.lib,LIB:amiga.lib
quit
*/
/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <exec/memory.h>
#include <intuition/intuition.h>
#include <workbench/startup.h>
#include <workbench/workbench.h>

#ifdef LATTICE
#include <stdio.h>

/* disable SAS/C CTRL-C handing */
int
CXBRK(void)
{
    return (0);
}
int
chkabort(void)
{
    return (0);
}

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/icon_protos.h>
#include <clib/wb_protos.h>
#endif

struct IntuitionBase *IntuitionBase;
struct WorkbenchBase *WorkbenchBase;

void            main(void);

void
main(void)
{
    struct MsgPort *msgport;
    struct Window  *window;
    struct AppWindow *appwindow;
    struct IntuiMessage *imsg;
    struct AppMessage *appmsg;
    struct WBArg   *argptr;

    ULONG           id = 1, userdata = 0;
    BOOL            ABORT = FALSE;
    UCOUNT          i;

    /* Open Intuition.library & Workbench.library. Fail silently if < 36 */
    if (IntuitionBase = OpenLibrary("intuition.library", 36))
    {
        if (WorkbenchBase = OpenLibrary("workbench.library", 36))
        {
            /* Create the message port to which Workbench can send messages */
            if (msgport = CreateMsgPort())
            {
                if (window =
                    OpenWindowTags(NULL, WA_Left, 0, WA_Top, 1, WA_Width, 160,
                                   WA_Height, 50, WA_IDCMP, CLOSEWINDOW,
                                   WA_Flags, WINDOWCLOSE | WINDOWDRAG,
                                   WA_Title, "AppWindow", TAG_END))
                {

                    /*
                     * Turn the window we opened into an AppWindow. Provide an
                     * ID so you can tell possible more AppWindows apart.
                     */
                    if (appwindow = AddAppWindow(id, userdata, window, msgport, NULL))
                    {
                        do
                        {
                            /* Wait for either a CLOSEWINDOW or an AppMessage */
                            Wait(1 << window->UserPort->mp_SigBit |
                                1 << msgport->mp_SigBit);
                            while (imsg = (struct IntuiMessage *)
                                GetMsg(window->UserPort))
                            {
                                if (imsg->Class = CLOSEWINDOW)
                                    ABORT = TRUE;
                                ReplyMsg((struct Message *) imsg);
                            }
                            while (appmsg = (struct AppMessage *) GetMsg(msgport))
                            {

                                /*
                                 * The AppMessage type will be MTYPE_APPWINDOW,
                                 * the ID & userdata are what we supplied when
                                 * the window was designed as an AppWindow.
                                 * NumArgs allows us to process the Workbench
                                 * arguments properly.
                                 */
                                printf(
                       "aw: appmsg=%lx, Type=%ld, ID=%ld, UserData=%ld, NumArgs=%ld\n",
                                       appmsg, appmsg->am_Type, appmsg->am_ID,
                                       appmsg->am_UserData, appmsg->am_NumArgs);

                                /*
                                 * Get a pointer to the start of the Workbench
                                 * argument list.
                                 */
                                argptr = appmsg->am_ArgList;
                                for (i = 0; i < appmsg->am_NumArgs; i++)
                                {

                                    /*
                                     * The lock will be on the directory in
                                     * which the file resides. If there is no
                                     * filename, either a volume or window was
                                     * dropped on us.
                                     */
                                    printf("\targ(%ld): Name='%s', Lock=%lx\n",
                                           i, argptr->wa_Name, argptr->wa_Lock);
                                    /* Point to next argument */
                                    argptr++;
                                }
                                ReplyMsg((struct Message *) appmsg);
                            }
                        } while (ABORT == FALSE);
                        /* remove the appwindow status and close down */
                        RemoveAppWindow(appwindow);
                    }
                    else
                        printf("Couldn't AddAppWindow\n");
                    CloseWindow(window);
                }
                else
                    printf("Couldn't open window\n");
                DeleteMsgPort(msgport);
            }
            else
                printf("Coulnd't create messageport\n");
            CloseLibrary(WorkbenchBase);
        }
        else
            printf("Couldn't open workbench.library\n");
        CloseLibrary(IntuitionBase);
    }
    else
        printf("Couldn't open intuition.library\n");
}


IV-59/AppIcon.c

;/* Compile me with SAS/C 6.56
sc NMINC STRMERGE NOSTKCHK NODEBUG DATA=NEAR IGNORE=73 AppIcon.c
slink FROM LIB:c.o,AppIcon.o TO AppIcon LIBRARY LIB:sc.lib,LIB:Amiga.lib
quit
*/
/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <intuition/intuition.h>
#include <exec/memory.h>
#include <workbench/startup.h>
#include <workbench/workbench.h>

#include "appicon.h"

#ifdef LATTICE
#include <stdio.h>

/* disable SAS/C CTRL-C handing */
int
CXBRK(void)
{
    return (0);
}
int
chkabort(void)
{
    return (0);
}

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/wb_protos.h>
#endif

struct IntuitionBase *IntuitionBase;
struct WorkbenchBase *WorkbenchBase;

void            main(void);

void
main(void)
{
    struct MsgPort *msgport;
    struct Window  *window;
    struct AppIcon *appicon;
    struct IntuiMessage *imsg;
    struct AppMessage *appmsg;
    struct WBArg   *argptr;

    ULONG           id = 1, userdata = 0;
    BOOL            ABORT = FALSE;
    UCOUNT          i;

    /* Open needed libraries. Fail silently if < 36 */
    if (IntuitionBase = OpenLibrary("intuition.library", 36))
    {
        if (WorkbenchBase = OpenLibrary("workbench.library", 36))
        {
            if (msgport = CreateMsgPort())
            {
                if (window =
                    OpenWindowTags(NULL, WA_Left, 0, WA_Top, 1, WA_Width, 160,
                                   WA_Height, 50, WA_IDCMP, CLOSEWINDOW,
                                   WA_Flags, WINDOWCLOSE | WINDOWDRAG,
                                   WA_Title, "AppIcon", TAG_END))
                {

                    /* Add the icon to Workbench */
                    if (appicon = AddAppIcon(id, userdata, "AppIcon",
                        msgport, NULL, &AppIconDObj, NULL))
                    {
                        do
                        {
                            Wait(1 << window->UserPort->mp_SigBit |
                                1 << msgport->mp_SigBit);
                            while (imsg = (struct IntuiMessage *)
                                GetMsg(window->UserPort))
                            {
                                if (imsg->Class = CLOSEWINDOW)
                                    ABORT = TRUE;
                                ReplyMsg((struct Message *) imsg);
                            }
                            while (appmsg = (struct AppMessage *) GetMsg(msgport))
                            {
                                printf(
                       "ai: appmsg=%lx, Type=%ld, ID=%ld, UserData=%ld, NumArgs=%ld\n",
                                       appmsg, appmsg->am_Type, appmsg->am_ID,
                                       appmsg->am_UserData, appmsg->am_NumArgs);
                                argptr = appmsg->am_ArgList;

                                /*
                                 * If am->NumArgs is zero the user
                                 * double-clicked on our icon, otherwise one or
                                 * more icons were dropped on top of it.
                                 */
                                for (i = 0; i < appmsg->am_NumArgs; i++)
                                {
                                    printf("\targ(%ld): Name='%s', Lock=%lx\n",
                                    i, argptr->wa_Name, argptr->wa_Lock);
                                    argptr++;
                                }
                                ReplyMsg((struct Message *) appmsg);
                            }
                        } while (ABORT == FALSE);
                        /* Remove the AppIcon and clean up */
                        RemoveAppIcon(appicon);
                    }
                    else
                        printf("Couldn't add AppIcon\n");
                    CloseWindow(window);
                }
                else
                    printf("Couldn't open window\n");
                DeleteMsgPort(msgport);
            }
            else
                printf("Couldn't create messageport\n");
            CloseLibrary(WorkbenchBase);
        }
        else
            printf("Couldn't open workbench.library\n");
        CloseLibrary(IntuitionBase);
    }
    else
        printf("Couldn't open intuition.library\n");
}


IV-59/AppIcon.h

/*
 * AppIcon.h - Icon for AppIcon. Output from IconEd.
 *

Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

UWORD chip      AppIcon1IData[] =
{
/* Plane 0 */
    0x0000, 0x0000, 0x0000, 0x8000, 0x0000, 0x0000, 0x0001, 0x8000,
    0x0000, 0x0000, 0x0011, 0x8000, 0x0000, 0x0000, 0x0031, 0x8000,
    0x0000, 0x0000, 0x0231, 0x8000, 0x0000, 0x0000, 0x0631, 0x8000,
    0x0000, 0x0000, 0x4631, 0x8000, 0x0000, 0x0000, 0xC631, 0x8000,
    0x0000, 0x0000, 0xC631, 0x8000, 0x0000, 0x0000, 0xC631, 0x8000,
    0x0000, 0x0000, 0xC631, 0x8000, 0x0000, 0x0000, 0xC631, 0x8000,
    0x0000, 0x0000, 0xC631, 0x8000, 0x0000, 0xFFFF, 0xC631, 0x8000,
    0x0000, 0x0000, 0x0631, 0x8000, 0x001F, 0xFFFF, 0xFE31, 0x8000,
    0x0000, 0x0000, 0x0031, 0x8000, 0x03FF, 0xFFFF, 0xFFF1, 0x8000,
    0x0000, 0x0000, 0x0001, 0x8000, 0x7FFF, 0xFFFF, 0xFFFF, 0x8000,
/* Plane 1 */
    0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0xC000, 0x0000, 0x0000, 0x0000,
    0xC7FF, 0xFFFF, 0xFFE0, 0x0000, 0xC600, 0x0000, 0x0000, 0x0000,
    0xC63F, 0xFFFF, 0xFC00, 0x0000, 0xC630, 0x0000, 0x0000, 0x0000,
    0xC631, 0xFFFF, 0x8000, 0x0000, 0xC631, 0x8000, 0x0000, 0x0000,
    0xC631, 0x8000, 0x0000, 0x0000, 0xC631, 0x8000, 0x0000, 0x0000,
    0xC631, 0x8000, 0x0000, 0x0000, 0xC631, 0x8000, 0x0000, 0x0000,
    0xC631, 0x8000, 0x0000, 0x0000, 0xC631, 0x0000, 0x0000, 0x0000,
    0xC630, 0x0000, 0x0000, 0x0000, 0xC620, 0x0000, 0x0000, 0x0000,
    0xC600, 0x0000, 0x0000, 0x0000, 0xC400, 0x0000, 0x0000, 0x0000,
    0xC000, 0x0000, 0x0000, 0x0000, 0x8000, 0x0000, 0x0000, 0x0000,
};

struct Image    AppIconI1 =
{
    0, 0,                                        /* Upper left corner */
    49, 20, 2,                                   /* Width, Height, Depth */
    AppIcon1IData,                               /* Image data */
    0x0003, 0x0000,                              /* PlanePick, PlaneOnOff */
    NULL                                         /* Next image */
};

UWORD chip      AppIconI2Data[] =
{
/* Plane 0 */
    0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0xC000, 0x0000, 0x0000, 0x0000,
    0xC7FF, 0xFFFF, 0xFFE0, 0x0000, 0xC600, 0x0000, 0x0000, 0x0000,
    0xC63F, 0xFFFF, 0xFC00, 0x0000, 0xC630, 0x0000, 0x0000, 0x0000,
    0xC631, 0xFFFF, 0x8000, 0x0000, 0xC631, 0x8000, 0x0000, 0x0000,
    0xC631, 0x8000, 0x0000, 0x0000, 0xC631, 0x8000, 0x0000, 0x0000,
    0xC631, 0x8000, 0x0000, 0x0000, 0xC631, 0x8000, 0x0000, 0x0000,
    0xC631, 0x8000, 0x0000, 0x0000, 0xC631, 0x0000, 0x0000, 0x0000,
    0xC630, 0x0000, 0x0000, 0x0000, 0xC620, 0x0000, 0x0000, 0x0000,
    0xC600, 0x0000, 0x0000, 0x0000, 0xC400, 0x0000, 0x0000, 0x0000,
    0xC000, 0x0000, 0x0000, 0x0000, 0x8000, 0x0000, 0x0000, 0x0000,
/* Plane 1 */
    0x0000, 0x0000, 0x0000, 0x8000, 0x0000, 0x0000, 0x0001, 0x8000,
    0x0000, 0x0000, 0x0011, 0x8000, 0x0000, 0x0000, 0x0031, 0x8000,
    0x0000, 0x0000, 0x0231, 0x8000, 0x0000, 0x0000, 0x0631, 0x8000,
    0x0000, 0x0000, 0x4631, 0x8000, 0x0000, 0x0000, 0xC631, 0x8000,
    0x0000, 0x0000, 0xC631, 0x8000, 0x0000, 0x0000, 0xC631, 0x8000,
    0x0000, 0x0000, 0xC631, 0x8000, 0x0000, 0x0000, 0xC631, 0x8000,
    0x0000, 0x0000, 0xC631, 0x8000, 0x0000, 0xFFFF, 0xC631, 0x8000,
    0x0000, 0x0000, 0x0631, 0x8000, 0x001F, 0xFFFF, 0xFE31, 0x8000,
    0x0000, 0x0000, 0x0031, 0x8000, 0x03FF, 0xFFFF, 0xFFF1, 0x8000,
    0x0000, 0x0000, 0x0001, 0x8000, 0x7FFF, 0xFFFF, 0xFFFF, 0x8000,
};

struct Image    AppIconI2 =
{
    0, 0,                                        /* Upper left corner */
    49, 20, 2,                                   /* Width, Height, Depth */
    AppIconI2Data,                               /* Image data */
    0x0003, 0x0000,                              /* PlanePick, PlaneOnOff */
    NULL                                         /* Next image */
};

struct DiskObject AppIconDObj =
{
    NULL,                                        /* Magic Number */
    NULL,                                        /* Version */
    {                                            /* Embedded Gadget Structure */
        NULL,                                    /* Next Gadget Pointer */
        0, 0, 49, 21,                            /* Left,Top,Width,Height */
        GADGHIMAGE,                              /* Flags */
        NULL,                                    /* Activation Flags */
        NULL,                                    /* Gadget Type */
        (APTR) & AppIconI1,                      /* Render Image */
        (APTR) & AppIconI2,                      /* Select Image */
        NULL,                                    /* Gadget Text */
        NULL,                                    /* Mutual Exclude */
        NULL,                                    /* Special Info */
        0,                                       /* Gadget ID */
        NULL,                                    /* User Data */
    },
    NULL,                                        /* Icon Type */
    NULL,                                        /* Default Tool */
    NULL,                                        /* Tool Type Array */
    NO_ICON_POSITION,                            /* Current X */
    NO_ICON_POSITION,                            /* Current Y */
    NULL,                                        /* Drawer Structure */
    NULL,                                        /* Tool Window */
    NULL                                         /* Stack Size */
};


IV-59/AppMenu.c

;/* AppMenu.c - Execute me to compile me with SAS/C 6.56
sc NMINC STRMERGE NOSTKCHK NODEBUG DATA=NEAR IGNORE=73 AppMenu.c
slink FROM LIB:c.o,AppMenu.o TO AppMenu LIBRARY LIB:sc.lib,LIB:Amiga.lib
quit
*/
/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <intuition/intuition.h>
#include <exec/memory.h>
#include <workbench/startup.h>
#include <workbench/workbench.h>

#ifdef LATTICE

/* disable SAS/C CTRL-C handing */
int
CXBRK(void)
{
    return (0);
}
int
chkabort(void)
{
    return (0);
}

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/icon_protos.h>
#include <clib/wb_protos.h>
#include <clib/dos_protos.h>
#include <clib/alib_stdio_protos.h>
#endif

struct IntuitionBase *IntuitionBase;
struct WorkbenchBase *WorkbenchBase;

void            main(void);

void
main(void)
{
    struct MsgPort *msgport;
    struct Window  *window;
    struct AppMenuItem *appmenuitem;
    struct IntuiMessage *imsg;
    struct AppMessage *appmsg;
    struct WBArg   *argptr;

    ULONG           id = 1, userdata = 0, i;
    BOOL            ABORT = FALSE;

    /* Open Intuition.library & Workbench.library. Fail silently if < 36 */
    if (IntuitionBase = OpenLibrary("intuition.library", 36))
    {
        if (WorkbenchBase = OpenLibrary("workbench.library", 36))
        {
            /* Create the message port to which Workbench can send messages */
            if (msgport = CreateMsgPort())
            {
                if (window =
                    OpenWindowTags(NULL, WA_Left, 0, WA_Top, 1, WA_Width, 160,
                                   WA_Height, 50, WA_IDCMP, CLOSEWINDOW,
                                   WA_Flags, WINDOWCLOSE | WINDOWDRAG,
                                   WA_Title, "AppMenu", TAG_END))
                {

                    /* Use our window to attach an menu item to the Tools menu. */
                    if (appmenuitem = AddAppMenuItem(id, userdata,
                                                     "AppMenuItem", msgport, NULL))
                    {

                        do
                        {
                            /* Wait for either a CLOSEWINDOW or an AppMessage */
                            Wait(1 << window->UserPort->mp_SigBit |
                                 1 << msgport->mp_SigBit);
                            while (imsg = (struct IntuiMessage *)
                                GetMsg(window->UserPort))
                            {
                                if (imsg->Class = CLOSEWINDOW)
                                    ABORT = TRUE;
                                ReplyMsg((struct Message *) imsg);
                            }
                            while (appmsg = (struct AppMessage *) GetMsg(msgport))
                            {

                                /*
                                 * The AppMessage type will be MTYPE_APPMENU,
                                 * the ID & userdata are what we supplied when
                                 * the window was designed as an AppWindow.
                                 * Since there are no Workbench arguments for
                                 * menu operations, NumArgs will always be 0.
                                 */
                                printf(
                       "am: appmsg=%lx, Type=%ld, ID=%ld, UserData=%ld, NumArgs=%ld\n",
                                       appmsg, appmsg->am_Type, appmsg->am_ID,
                                       appmsg->am_UserData, appmsg->am_NumArgs);
                                argptr = appmsg->am_ArgList;
                                for (i = 0; i < appmsg->am_NumArgs; i++)
                                {

                                    /*
                                     * The lock will be on the directory in
                                     * which the file resides. If there is no
                                     * filename, either a volume or window was
                                     * dropped on us.
                                     */
                                    printf("\targ(%ld): Name='%s', Lock=%lx\n", i,
                                           argptr->wa_Name, argptr->wa_Lock);
                                    /* Point to next argument */
                                    argptr++;
                                }

                                ReplyMsg((struct Message *) appmsg);
                            }
                        } while (ABORT == FALSE);
                        /* remove the AppMenu and close down */
                        RemoveAppMenuItem(appmenuitem);
                    }
                    else
                        printf("Couldn't add AppMenuItem\n");
                    CloseWindow(window);
                }
                else
                    printf("Couldn't open window\n");
                DeleteMsgPort(msgport);
            }
            else
                printf("Coulnd't create messageport\n");
            CloseLibrary(WorkbenchBase);
        }
        else
            printf("Couldn't open workbench.library\n");
        CloseLibrary(IntuitionBase);
    }
    else
        printf("Couldn't open intuition.library\n");
}


IV-69/jumpy.c

;/* Jumpy.c - Execute me to compile me with SAS/C 6.56
sc DATA=NEAR NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 Jumpy.c
slink FROM LIB:c.o,Jumpy.o TO Jumpy LIBRARY LIB:sc.lib,LIB:amiga.lib
quit
*/
/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <intuition/intuition.h>
#include <intuition/screens.h>
#include <graphics/text.h>
#include <libraries/gadtools.h>

#ifdef LATTICE
#include <string.h>
#include <clib/alib_protos.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/graphics_protos.h>
/* disable SAS/C CTRL-C handing */
int             CXBRK(void)
{
    return (0);
}
int             chkabort(void)
{
    return (0);
}

#endif

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Library *GadToolsBase;
struct Library *IconBase;
struct Library *CxBase;

LONG            main(LONG, UBYTE **);

LONG
main(LONG argc, UBYTE ** argv)
{
    struct Window       *window;
    struct IntuiMessage *imsg;
    struct Gadget       *gadgetcontext;
    struct Gadget       *gadget, *nextscreengadget;
    struct NewGadget     ng;
    struct TextExtent    textextent;
    UWORD                left, top;
    void                *visualinfo;
    UBYTE               *startupname;
    UBYTE                namebuffer[MAXPUBSCREENNAME];
    UBYTE              **tooltypes;
    BOOL                 ABORT = FALSE;

    if (IntuitionBase = OpenLibrary("intuition.library", 37))
    {
        /* Open GfxBase to use TextExtent() so we can handle proportional fonts */
        if (GfxBase = OpenLibrary("graphics.library", 37))
        {
            if (GadToolsBase = OpenLibrary("gadtools.library", 37))
            {

                /*
                 * Open commodities & icon.library so we can use ArgArray
                 * functions
                 */
                if (CxBase = OpenLibrary("commodities.library", 37))
                {
                    if (IconBase = OpenLibrary("icon.library", 37))
                    {
                        left = 50;
                        top = 50;                /* Initial offset */
                        /* Note that these are functions in amiga.lib */
                        if (tooltypes = ArgArrayInit(argc, argv))
                        {
                            startupname =
                                ArgString(tooltypes, "PUBSCREEN", "Workbench");
                            strcpy(namebuffer, startupname);
                            ArgArrayDone();
                        }
                        else
                            strcpy(namebuffer, "Workbench");
                        do
                        {
                            /* open a window with tags */
                            /* no NewWindow structure, tags only */
                            if (window = OpenWindowTags(NULL,
                                        /* Open at far left corner */
                                        WA_Left,  left,
                                        WA_Top,   top,
                                        WA_Width, 150,
                                        WA_Height, 80,
                                        WA_Title, (LONG) "jumpy",
                                        WA_PubScreenName, (LONG) namebuffer,
                                        /* if no pubscreen with this name exists... */
                                        WA_PubScreenFallBack, TRUE,
                                        /* ...fall back on default pubscreen */
                                        WA_Flags, WFLG_DRAGBAR | WFLG_DEPTHGADGET |
                                            WFLG_CLOSEGADGET | WFLG_ACTIVATE |
                                            WFLG_SMART_REFRESH | WFLG_NOCAREREFRESH,
                                        WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_GADGETUP,
                                        TAG_DONE))
                            {

                                /*
                                 * Get the visual info gadtools needs for the
                                 * screen we opened on
                                 */
                                if (visualinfo = GetVisualInfoA(window->WScreen, NULL))
                                {

                                    /*
                                     * Create a simple gadtools button and sort
                                     * of lay it out. Note this doesn't do any
                                     * checking for legal (window) dimensions.
                                     */
                                    if (gadget = CreateContext(&gadgetcontext))
                                    {

                                        /*
                                         * Use TextExtent to handle
                                         * proportional fonts
                                         */
                                        TextExtent(&(window->WScreen->RastPort),
                                                   "Jump", 4, &textextent);
                                        ng.ng_Width = textextent.te_Width + 8;
                                        ng.ng_LeftEdge = (window->Width / 2) -
                                                          (ng.ng_Width / 2);
                                        ng.ng_Height = textextent.te_Height + 4;
                                        ng.ng_TopEdge = (
                                            (window->Height - window->BorderTop -
                                                window->BorderBottom) / 2) +
                                            (ng.ng_Height / 2);
                                        ng.ng_TextAttr = window->WScreen->Font;
                                        ng.ng_GadgetText = "Jump";
                                        ng.ng_VisualInfo = visualinfo;
                                        ng.ng_GadgetID = 1;
                                        ng.ng_Flags = PLACETEXT_IN;
                                        nextscreengadget = gadget =
                                            CreateGadget(BUTTON_KIND, gadget, &ng,
                                                         TAG_END);
                                        AddGList(window, gadget, -1, -1, NULL);
                                        RefreshGList(gadget, window, NULL, -1);
                                        GT_RefreshWindow(window, NULL);

                                        WaitPort(window->UserPort);
                                        while (imsg = (struct IntuiMessage *)
                                            GetMsg(window->UserPort))
                                        {
                                            if (imsg->Class == IDCMP_CLOSEWINDOW)
                                                ABORT = TRUE;
                                            else if (imsg->Class = IDCMP_GADGETUP)
                                                NextPubScreen(window->WScreen,
                                                              namebuffer);
                                            ReplyMsg((struct Message *) imsg);
                                        }
                                        RemoveGadget(window, nextscreengadget);
                                        FreeGadgets(gadgetcontext);
                                    }
                                    FreeVisualInfo(visualinfo);
                                }
                                left = window->LeftEdge;
                                top = window->TopEdge;
                                CloseWindow(window);
                            }
                        } while (ABORT == FALSE);

                        CloseLibrary(IconBase);
                    }
                    CloseLibrary(CxBase);
                }
                CloseLibrary(GadToolsBase);
            }
            CloseLibrary(GfxBase);
        }
        CloseLibrary(IntuitionBase);
    }
    return (0);
}


IV-69/zoom.c

;/* Zoom.c - Execute me to compile me with SAS/C 6.56
sc DATA=NEAR NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 Zoom.c
slink FROM LIB:c.o,Zoom.o TO Zoom LIBRARY LIB:sc.lib,LIB:amiga.lib
quit
*/
/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <intuition/intuition.h>
#include <intuition/screens.h>

#ifdef LATTICE
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
/* disable SAS/C CTRL-C handing */

int             CXBRK(void)
{
    return (0);
}

int             chkabort(void)
{
    return (0);
}
#endif

struct IntuitionBase *IntuitionBase;

LONG            main(void);

LONG main(void)
{
    struct IBox     ibox;    /* The structure we'll use to specify the zoom'ed
                              * dimension. */
    struct Screen  *wbscreen;
    struct Window  *window;
    struct Message *msg;     /* Make this an IntuiMessage when you want to use
                              * it */

    if (IntuitionBase = OpenLibrary("intuition.library", 37))
    {

        /* Lock workbench screen so we can watch it closely */
        if (wbscreen = LockPubScreen("Workbench"))
        {

            /*
             * Generate a nice position for the zoom'ed window. Note that this
             * specifies the INITIAL position of the window. Since we don't
             * have a size gadget, the user can't change the height and width,
             * but the offset is changed as the window is dragged.
             */
            ibox.Left = wbscreen->Width - 180;   /* far right corner */
            ibox.Top = wbscreen->BarHeight + 1;  /* Just below screen bar */
            ibox.Width = 180;
            /* ght of the window topborder */
            ibox.Height = wbscreen->WBorTop + wbscreen->Font->ta_YSize + 1;

            /* open a window with tags */
            if (window = OpenWindowTags(NULL,    /* no NewWindow structure,
                                                  * tags only */
                                        WA_Left, 0,     /* Open at far left
                                                         * corner */
                                        WA_Top, wbscreen->BarHeight + 1,
                                        WA_Width, 200,
                                        WA_Height, 100,
                                        WA_Title, (LONG) "A simple window",
                WA_Flags, WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET |
                     WFLG_ACTIVATE | WFLG_SIMPLE_REFRESH | WFLG_NOCAREREFRESH,

                                        /* Only interested in closewindow      */
                                        WA_IDCMP, IDCMP_CLOSEWINDOW,

                                        /* pass the alternate zoom dimension   */
                                        WA_Zoom, (LONG) & ibox,

                                        TAG_DONE))
            {

                /* And just wait for windowclose */
                WaitPort(window->UserPort);
                /* clear the message port */
                while (msg = GetMsg(window->UserPort))
                    ReplyMsg(msg);

                CloseWindow(window);
            }
            UnlockPubScreen(NULL, wbscreen);
        }
        CloseLibrary(IntuitionBase);
    }
}


IV-69/hide.c

;/* Hide.c - Execute me to compile me with SAS/C 6.56
sc DATA=NEAR NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 Hide.c
slink FROM LIB:c.o,Hide.o TO Hide LIBRARY LIB:sc.lib,LIB:amiga.lib
quit
*/
/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <intuition/intuition.h>
#include <intuition/screens.h>
#include <graphics/text.h>
#include <libraries/gadtools.h>
#include <workbench/startup.h>
#include <workbench/workbench.h>
#include "hide.h"

#ifdef LATTICE
#include <clib/alib_protos.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/graphics_protos.h>
#include <clib/wb_protos.h>

/* disable SAS/C CTRL-C handing */
int             CXBRK(void)
{
    return (0);
}
int             chkabort(void)
{
    return (0);
}

#endif

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct WorkbenchBase *WorkbenchBase;
struct Library *GadToolsBase;

LONG            main(void);

LONG
main(void)
{
    struct Window  *window;
    struct IntuiMessage *imsg;
    struct Gadget  *gadgetcontext;
    struct Gadget  *gadget, *hidegadget;
    struct MsgPort *appport;
    struct NewGadget ng;
    struct TextExtent textextent;
    struct AppIcon *appicon = NULL;
    struct AppMessage *appmsg;
    UWORD           left, top;
    void           *visualinfo;
    ULONG           signal, windowsignal, waitmask;
    BOOL            ABORT = FALSE;
    BOOL            CONTINUE, ICONIFY;

    if (IntuitionBase = OpenLibrary("intuition.library", 37))
    {
        /* Open GfxBase to use TextExtent() so we can handle proportional fonts */
        if (GfxBase = OpenLibrary("graphics.library", 37))
        {
            /* Open gadtools for that lonely gadget */
            if (GadToolsBase = OpenLibrary("gadtools.library", 37))
            {
                if (WorkbenchBase = OpenLibrary("workbench.library", 37))
                {
                    /* Message to receive appmessage on */
                    if (appport = CreateMsgPort())
                    {
                        /* open a window with tags */
                        left = top = 50;
                        do
                        {
                            /* no NewWindow structure, tags only */
                            if (window = OpenWindowTags(NULL,
                                         /* Open at far left corner */
                                         WA_Left, left,
                                         WA_Top, top,
                                         WA_Width, 150,
                                         WA_Height, 80,
                                         WA_Title, (LONG) "hide",
                                         WA_Flags, WFLG_DRAGBAR |
                                             WFLG_DEPTHGADGET | WFLG_CLOSEGADGET |
                                             WFLG_ACTIVATE | WFLG_SMART_REFRESH |
                                             WFLG_NOCAREREFRESH,
                                         WA_IDCMP,
                                             IDCMP_CLOSEWINDOW | IDCMP_GADGETUP,
                                         TAG_DONE))
                            {
                                windowsignal = 1L << window->UserPort->mp_SigBit;
                                /*
                                 * Get the visual info gadtools needs for the
                                 * screen we opened on
                                 */
                                if (visualinfo = GetVisualInfoA(window->WScreen, NULL))
                                {

                                    /*
                                     * Create a simple gadtools button and sort
                                     * of lay it out
                                     */
                                    if (gadget = CreateContext(&gadgetcontext))
                                    {

                                        /*
                                         * Use TextExtent to handle
                                         * proportional fonts
                                         */
                                        TextExtent(&(window->WScreen->RastPort),
                                                   "Hide", 4, &textextent);
                                        ng.ng_Width = textextent.te_Width + 8;
                                        ng.ng_LeftEdge = (window->Width / 2)
                                                              - (ng.ng_Width / 2);
                                        ng.ng_Height = textextent.te_Height + 4;
                                        ng.ng_TopEdge = (
                                            (window->Height - window->BorderTop
                                                - window->BorderBottom) / 2)
                                            + (ng.ng_Height / 2);
                                        ng.ng_TextAttr = window->WScreen->Font;
                                        ng.ng_GadgetText = "Hide";
                                        ng.ng_VisualInfo = visualinfo;
                                        ng.ng_GadgetID = 1;
                                        ng.ng_Flags = PLACETEXT_IN;
                                        hidegadget = gadget =
                                            CreateGadget(BUTTON_KIND, gadget,
                                                         &ng, TAG_END);
                                        AddGList(window, gadget, -1, -1, NULL);
                                        RefreshGList(gadget, window, NULL, -1);
                                        GT_RefreshWindow(window, NULL);

                                        CONTINUE = TRUE;
                                        waitmask = windowsignal|
                                                       1L << appport->mp_SigBit;
                                        do
                                        {
                                            signal = Wait(waitmask);

                                          if (signal & windowsignal)
                                            {
                                                while (imsg = (struct IntuiMessage *)
                                                    GetMsg(window->UserPort))
                                                {
                                                    if (imsg->Class ==
                                                            IDCMP_CLOSEWINDOW)
                                                    {
                                                        ABORT = TRUE;
                                                        CONTINUE = FALSE;
                                                        ICONIFY = FALSE;
                                                    }
                                                    else
                                                    if (imsg->Class == IDCMP_GADGETUP)
                                                        ICONIFY = TRUE;
                                                    ReplyMsg((struct Message *) imsg);
                                                }
                                            }
                                            if (signal & (1L << appport->mp_SigBit))
                                            {
                                                while (appmsg = (struct AppMessage *)
                                                    GetMsg(appport))
                                                {

                                                    /*
                                                     * If am->NumArgs is zero
                                                     * the user double-clicked
                                                     * on our icon, otherwise
                                                     * one or more icons were
                                                     * dropped on top of it.
                                                     */
                                                    if (appmsg->am_NumArgs == 0)
                                                    {
                                                        RemoveAppIcon(appicon);
                                                        CONTINUE = FALSE;
                                                    }
                                                    ReplyMsg(
                                                        (struct Message *) appmsg);
                                                }
                                            }
                                            if (ICONIFY)
                                            {

                                                /*
                                                 * Add appicon, close window if
                                                 * succesful
                                                 */
                                                appicon = AddAppIcon(1, NULL, "Hide",
                                                    appport, NULL, &AppIconDObj, NULL);
                                                if (appicon == NULL)
                                                {
                                                    DisplayBeep(window->WScreen);
                                                }
                                                else
                                                {
                                                    RemoveGadget(window, hidegadget);
                                                    left = window->LeftEdge;
                                                    top = window->TopEdge;
                                                    CloseWindow(window);
                                                    window = NULL;
                                                    /* there is no window
                                                     * message port anymore */
                                                    waitmask =
                                                        1L << appport->mp_SigBit;
                                                }
                                                ICONIFY = FALSE;
                                            }
                                        } while (CONTINUE == TRUE);
                                        if (window)
                                            RemoveGadget(window, hidegadget);
                                        FreeGadgets(gadgetcontext);
                                    }
                                    FreeVisualInfo(visualinfo);
                                }

                                if (window)
                                {
                                    left = window->LeftEdge;
                                    top = window->TopEdge;
                                    CloseWindow(window);
                                }
                            }
                        } while (ABORT == FALSE);
                        DeleteMsgPort(appport);
                    }
                    CloseLibrary(WorkbenchBase);
                }
                CloseLibrary(GadToolsBase);
            }
            CloseLibrary(GfxBase);
        }
        CloseLibrary(IntuitionBase);
    }
    return (0);
}


IV-69/hide.h

/*
 * Hide.h

Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

UWORD chip      ImageI1Data[] =
{
/* Plane 0 */
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8208, 0x0000, 0x0000,
    0x8208, 0x7FFF, 0xFFFF, 0xFEF8, 0x4000, 0x0000, 0x00A8, 0x4000,
    0x0000, 0x0048, 0x4000, 0x0000, 0x00A8, 0x4000, 0x0000, 0x0048,
    0x4000, 0x0000, 0x00A8, 0x4000, 0x0000, 0x0008, 0x4000, 0x0000,
    0x0008, 0x4000, 0x0000, 0x00E8, 0x4000, 0x0000, 0x0008, 0xFFFF,
    0xFFFF, 0xFFF8,
/* Plane 1 */
    0xFFFF, 0xFFFF, 0xFFF8, 0x8000, 0x0000, 0x4100, 0x8000, 0x0000,
    0x4100, 0x8000, 0x0000, 0x0100, 0xC000, 0x0000, 0x0110, 0xC000,
    0x0000, 0x0110, 0xC000, 0x0000, 0x0110, 0xC000, 0x0000, 0x0110,
    0xC000, 0x0000, 0x0110, 0xC000, 0x0000, 0x0110, 0xC000, 0x0000,
    0x0110, 0xC000, 0x0000, 0x0110, 0xFFFF, 0xFFFF, 0xFFF0, 0x0000,
    0x0000, 0x0000,
};

struct Image    ImageI1 =
{
    0, 0,                    /* Upper left corner */
    45, 14, 2,               /* Width, Height, Depth */
    ImageI1Data,             /* Image data */
    0x0003, 0x0000,          /* PlanePick, PlaneOnOff */
    NULL                     /* Next image */
};

UWORD chip      ImageI2Data[] =
{
/* Plane 0 */
    0x0000, 0x0000, 0x0000, 0x7FFF, 0xFFFF, 0xBEF8, 0x7FFF, 0xFFFF,
    0xBEF8, 0x7FFF, 0xFFFF, 0xFEF8, 0x4000, 0x0000, 0x00E8, 0x4000,
    0x0000, 0x00E8, 0x4000, 0x0000, 0x00E8, 0x4000, 0x0000, 0x00E8,
    0x4000, 0x0000, 0x00E8, 0x4000, 0x0000, 0x00A8, 0x4000, 0x0000,
    0x00A8, 0x4000, 0x0000, 0x00E8, 0x4000, 0x0000, 0x0008, 0xFFFF,
    0xFFFF, 0xFFF8,
/* Plane 1 */
    0xFFFF, 0xFFFF, 0xFFF8, 0xFFFF, 0xFFFF, 0x7DF0, 0xFFFF, 0xFFFF,
    0x7DF0, 0x8000, 0x0000, 0x0100, 0xC000, 0x0000, 0x0150, 0xC000,
    0x0000, 0x01B0, 0xC000, 0x0000, 0x0150, 0xC000, 0x0000, 0x01B0,
    0xC000, 0x0000, 0x0150, 0xC000, 0x0000, 0x01F0, 0xC000, 0x0000,
    0x01F0, 0xC000, 0x0000, 0x0110, 0xFFFF, 0xFFFF, 0xFFF0, 0x0000,
    0x0000, 0x0000,
};

struct Image    ImageI2 =
{
    0, 0,                    /* Upper left corner */
    45, 14, 2,               /* Width, Height, Depth */
    ImageI2Data,             /* Image data */
    0x0003, 0x0000,          /* PlanePick, PlaneOnOff */
    NULL                     /* Next image */
};

struct DiskObject AppIconDObj =
{
    0,
    0,
    {                        /* Embedded Gadget Structure */
        NULL,                /* Next Gadget Pointer */
        0, 0, 45, 15,        /* Left,Top,Width,Height */
        GFLG_GADGHIMAGE,
        0,                   /* Activation Flags */
        0,                   /* Gadget Type */
        (APTR) & ImageI1,    /* Render Image */
        (APTR) & ImageI2,    /* Select Image */
        NULL,                /* Gadget Text */
        NULL,                /* Mutual Exclude */
        NULL,                /* Special Info */
        0,                   /* Gadget ID */
        NULL,                /* User Data */
    },
    0,                       /* Icon Type */
    NULL,                    /* Default Tool */
    NULL,                    /* Tool Type Array */
    NO_ICON_POSITION,        /* Current X */
    NO_ICON_POSITION,        /* Current Y */
    NULL,                    /* Drawer Structure */
    NULL,                    /* Tool Window */
    0                        /* Stack Size */
};


IV-77/Optimrefresh.c

;/* Optimrefresh.c - Execute me to compile me with SAS/C 6.56
sc NMINC STRMERGE STREQ MCCONS COMNEST UNSCHAR NOSTKCHK SAVEDS IGNORE=73 optimrefresh.c
slink FROM LIB:c.o,optimrefresh.o TO optimrefresh LIBRARY LIB:sc.lib,LIB:amiga.lib
quit ;*/

/* Copyright © 1992 Martin Taillefer.   All rights reserved.              */
/* The information contained herein is subject to change without notice,  */
/* and is provided "as is" without warranty of any kind, either expressed */
/* or implied.  The entire risk as to the use of this information is      */
/* assumed by the user.                                                   */

/* This program demonstrates optimal window refreshing using a scrolling text
 * display as a sample.
 */

#include <exec/types.h>
#include <exec/libraries.h>
#include <exec/memory.h>
#include <utility/hooks.h>
#include <utility/tagitem.h>
#include <graphics/gfxmacros.h>
#include <intuition/intuition.h>
#include <intuition/screens.h>
#include <intuition/gadgetclass.h>
#include <dos.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/layers_protos.h>
#include <clib/alib_protos.h>
#include <clib/dos_protos.h>

/*****************************************************************************/

/* There is one Line structure for every line of text in our fictional
 * document.
 */
struct Line
{
    struct MinNode ln_Link;     /* to link the lines together           */
    STRPTR         ln_Text;     /* pointer to the text for this line    */
    ULONG          ln_TextLen;  /* the length of the text for this line */
};

/*****************************************************************************/

/* system libraries */
struct Library  *IntuitionBase;
struct Library  *GfxBase;
struct Library  *LayersBase;

/* global display handles */
struct Screen   *screen;
struct Window   *window;
struct Gadget   *scroller;
struct Hook      refreshHook;

struct RastPort render;
struct RastPort clear;

/* our document along with associated view information */
struct MinList   document;
ULONG            numLines;
ULONG            topLine;
ULONG            oldTopLine;
ULONG            linesVisible;
ULONG            columnsVisible;
ULONG            fontHeight;
ULONG            fontWidth;
ULONG            viewHeight;
ULONG            viewWidth;
ULONG            usefulWidth;
ULONG            usefulHeight;

/* a state flag indicating whether the main application is busy */
BOOL             taskBusy;
/*****************************************************************************/

VOID InitDocument(VOID);
VOID FreeDocument(VOID);
VOID EventLoop(VOID);
VOID __asm BackFillHook(register __a2 struct RastPort    *rp,
                        register __a1 struct BackFillMsg *bfm);

/*****************************************************************************/

/* This is where it all begins.
 */
ULONG main(void)
{
    /* open the system libraries we need.
     */
    IntuitionBase = OpenLibrary("intuition.library",37);
    GfxBase       = OpenLibrary("graphics.library",37);
    LayersBase    = OpenLibrary("layers.library",37);

    if (IntuitionBase && GfxBase && LayersBase)
    {
        /* get a pointer to the default public screen */
        if (screen = LockPubScreen(NULL))
        {
            /* allocate and initialize a scroller as a BOOPSI object */
            if (scroller = NewObject(NULL,"propgclass",
                  GA_RelRight,    -13,
                  GA_Top,         1+screen->WBorTop+screen->Font->ta_YSize+1,
                  GA_Width,       10,
                  GA_RelHeight,   -12-(screen->WBorTop+screen->Font->ta_YSize+1),
                  GA_RelVerify,   TRUE,
                  GA_Immediate,   TRUE,
                  GA_FollowMouse, TRUE,
                  GA_RightBorder, TRUE,
                  PGA_Borderless, TRUE,
                  PGA_Freedom,    FREEVERT,
                  PGA_Total,      1,
                  PGA_Visible,    1,
                  PGA_Top,        0,
                  PGA_NewLook,    TRUE,
                  TAG_DONE))
            {
                /* initialize data used by the backfill hook */
                refreshHook.h_Entry = ( ULONG (*)() )BackFillHook;  /* point the */
                taskBusy            = TRUE;               /* hook to our routine. */

                /* open the window */
                if (window = OpenWindowTags(NULL,
                      WA_Left,          0,
                      WA_Top,           0,
                      WA_PubScreen,     screen,
                      WA_AutoAdjust,    TRUE,
                      WA_CloseGadget,   TRUE,
                      WA_DepthGadget,   TRUE,
                      WA_DragBar,       TRUE,
                      WA_SizeGadget,    TRUE,
                      WA_SizeBRight,    TRUE,
                      WA_Title,         "Optimized Refresh Sample",
                      WA_SimpleRefresh, TRUE,
                      WA_Activate,      TRUE,
                      WA_Gadgets,       scroller,
                      WA_MinWidth,      32,
                      WA_MinHeight,     10+12+(screen->Font->ta_YSize+1),
                      WA_MaxWidth,      -1,
                      WA_MaxHeight,     -1,
                      WA_IDCMP,         IDCMP_CLOSEWINDOW | IDCMP_NEWSIZE
                                        | IDCMP_REFRESHWINDOW | IDCMP_GADGETUP
                                        | IDCMP_GADGETDOWN | IDCMP_MOUSEMOVE
                                        | IDCMP_VANILLAKEY,
                      WA_BackFill,      &refreshHook,
                      TAG_DONE))
                {
                    /* initialize our document structure */
                    InitDocument();

                    /* process user events in the window */
                    EventLoop();

                    /* free our document structure */
                    FreeDocument();

                    /* close up shop */
                    CloseWindow(window);
                }
                /* free the scroller BOOPSI object */
                DisposeObject(scroller);
            }
            /* unlock the default public screem */
            UnlockPubScreen(NULL,screen);
        }
    }

    /* close the libraries we opened */
    CloseLibrary(LayersBase);
    CloseLibrary(GfxBase);
    CloseLibrary(IntuitionBase);

    /* tell the shell everything is all right */
    return(0);
}

/*****************************************************************************/

/* This function initializes our document. That means allocating 100
 * Line structures and linking them together in an Exec list. The lines
 * are filled with a pattern of text so we have something to display
 * in our window
 */
VOID InitDocument(VOID)
{
struct Line *line;
UWORD        i,j;

    NewList((struct List *)&document);
    numLines = 0;
    i        = 100;
    while (i--)
    {
        if (line = AllocVec(sizeof(struct Line)+91,MEMF_CLEAR|MEMF_PUBLIC))
        {
            line->ln_Text    = (STRPTR)((ULONG)line + sizeof(struct Line));
            line->ln_TextLen = 40;
            AddTail((struct List *)&document,(struct Node *)line);
            numLines++;

            j = 0;
            while (j < 90)
            {
                line->ln_Text[j] = (numLines % 96) + 32;
                j++;
            }
        }
    }
}

/*****************************************************************************/

/* This function frees all the memory allocated by InitDocument() */
VOID FreeDocument(VOID)
{
struct Line *line;

    while (line = (struct Line *)RemHead((struct List *)&document))
        FreeVec(line);
}

/*****************************************************************************/
/* This is the message packet passed by layers.library to a backfill hook.
 * It contains a pointer to the layer that has been damaged, a Rectangle
 * structure that defines the bounds of the damage. No rendering can occur
 * outside of these coordinates.
 *
 * The backfill hook is also passed a RastPort in which the rendering
 * should be performed.
 */
struct BackFillMsg
{
    struct Layer     *bf_Layer;
    struct Rectangle  bf_Bounds;
    LONG              bf_OffsetX;
    LONG              bf_OffsetY;
};

VOID __asm BackFillHook(register __a2 struct RastPort    *rp,
                        register __a1 struct BackFillMsg *bfm)
{
struct RastPort crp;

    crp       = *rp;            /* copy the rastport                      */
    crp.Layer = NULL;           /* eliminate bogus clipping from our copy */

    if (taskBusy)
    {
        SetWrMsk(&crp,0xff);    /* if the main task is busy, clear all planes */
    }
    else
    {
        SetWrMsk(&crp,0xfe);    /* otherwise, clear all planes except plane 0 */
    }

    SetAPen(&crp,0);                     /* set the pen to color 0         */
    SetDrMd(&crp,JAM2);                  /* set the rendering mode we need */
    RectFill(&crp,bfm->bf_Bounds.MinX,   /* clear the whole area           */
                  bfm->bf_Bounds.MinY,
                  bfm->bf_Bounds.MaxX,
                  bfm->bf_Bounds.MaxY);
}

/*****************************************************************************/

/* Adjust the scroller object to reflect the current window size and
 * scroll offset within our document
 */
VOID SetScroller(struct Window *window, struct Gadget *scroller,
                 ULONG linesVisible, ULONG numLines, ULONG topLines)
{
    SetGadgetAttrs(scroller,window,NULL,PGA_Visible, linesVisible,
                                        PGA_Total,   numLines,
                                        PGA_Top,     topLine,
                                        TAG_DONE);
}

/*****************************************************************************/

/* Render a single line of text at a given position */
VOID RenderLine(UWORD x, UWORD y, UWORD w, STRPTR text, ULONG len)
{
    Move(&render,x,y);                  /* move the cursor to the position */

    if (len > columnsVisible)           /* is line is longer than allowed? */
        len = columnsVisible;           /* yes, so reduce its length       */

    Text(&render,text,len);             /* write to the window             */

    if (len < columnsVisible)
        RectFill(&clear,render.cp_x,y-render.TxBaseline,
                        x+w-1,y-render.TxBaseline+fontHeight-1);

}
/*****************************************************************************/

/* This function performs most of the rendering work needed by our sample.
 * It first locks the window's layer to insure it doesn't get sized during
 * the rendering process. It then looks at the current window size and
 * adjusts its rendering variables in consequence. If the damage parameter
 * is set to TRUE, the routine then proceeds to explicitly erase any area
 * of the display to which we will not be rendering in the rendering loop.
 * This erases any left over characters that could be left if the user sizes
 * the window smaller. Finally, the routine determines which lines of the
 * display need to be updated and goes on to do it.
 */
VOID RefreshView(BOOL damage)
{
ULONG        i;
struct Line *line;
UWORD        x,y;

    /* lock the window's layer so its size will not change */
    LockLayer(NULL,window->WLayer);

    /* determine various values based on the current size of the window */
    viewWidth      = window->Width - window->BorderLeft - window->BorderRight;
    fontWidth      = window->RPort->Font->tf_XSize;
    columnsVisible = viewWidth / fontWidth;

    viewHeight     = window->Height - window->BorderTop - window->BorderBottom;
    fontHeight     = window->RPort->Font->tf_YSize;
    linesVisible   = viewHeight / fontHeight;

    usefulWidth = columnsVisible * fontWidth;

    if (linesVisible > numLines)
    {
        usefulHeight = numLines * fontHeight;
        topLine      = 0;
    }
    else if (topLine + linesVisible > numLines)
    {
        topLine      = (numLines - linesVisible);
        usefulHeight = (numLines - topLine) * fontHeight;
    }
    else
    {
        usefulHeight = linesVisible * fontHeight;
    }

    /* if we were called because of damage, we must erase any left over
     * garbage
     */
    if (damage)
    {
        /* erase anything left over on the right side of the window */
        if ((window->BorderLeft + usefulWidth < window->Width - window->BorderRight)
        &&   usefulHeight)
        {
            RectFill(&clear,window->BorderLeft + usefulWidth,
                            window->BorderTop,
                            window->Width - window->BorderRight - 1,
                            window->BorderTop + usefulHeight - 1);
        }

        /* erase anything left over on the bottom of the window */
        if ((window->BorderLeft < window->Width - window->BorderRight)
        &&  (window->BorderTop + usefulHeight < window->Height - window->BorderBottom))
        {
            RectFill(&clear,window->BorderLeft,
                            window->BorderTop + usefulHeight,
                            window->Width - window->BorderRight - 1,
                            window->Height - window->BorderBottom - 1);
        }
    }

    /* if we have at least one line and one column to render... */
    if (usefulHeight && usefulWidth)
    {
        /* get a pointer to the first line currently visible */
        line = (struct Line *)document.mlh_Head;
        i    = topLine;
        while (line->ln_Link.mln_Succ && i--)
            line = (struct Line *)line->ln_Link.mln_Succ;

        if (damage
        || (topLine >= oldTopLine + linesVisible - 1)
        || ((oldTopLine > linesVisible)
        && (topLine <= oldTopLine - linesVisible + 1)))
        {
            /* the whole display must be redrawn */
            x = window->BorderLeft;
            y = window->BorderTop + window->RPort->Font->tf_Baseline;
            i = linesVisible;
        }
        else if (topLine < oldTopLine)
        {
            /* we just need to scroll the text */
            ScrollRaster(&render,0,-(LONG)((oldTopLine - topLine) * fontHeight),
                         window->BorderLeft,
                         window->BorderTop,
                         window->BorderLeft+usefulWidth-1,
                         window->BorderTop+usefulHeight-1);

            /* indicates what section needs to be redrawn */
            x = window->BorderLeft;
            y = window->BorderTop + window->RPort->Font->tf_Baseline;
            i = oldTopLine - topLine;
        }
        else if (topLine > oldTopLine)
        {
            /* we just need to scroll the text */
            ScrollRaster(&render,0,(topLine - oldTopLine) * fontHeight,
                         window->BorderLeft,
                         window->BorderTop,
                         window->BorderLeft+usefulWidth-1,
                         window->BorderTop+usefulHeight-1);

            /* indicates what section needs to be redrawn */
            i = linesVisible - (topLine - oldTopLine);
            while (line->ln_Link.mln_Succ && i--)
                line = (struct Line *)line->ln_Link.mln_Succ;

            x = window->BorderLeft;
            y = window->BorderTop + window->RPort->Font->tf_Baseline
                + (fontHeight * (linesVisible - (topLine - oldTopLine)));
            i = topLine - oldTopLine;
        }
        else
        {
            /* we don't need to render anything */
            i = 0;
        }

        /* render all the lines we need */
        while (i-- && line->ln_Link.mln_Succ)
        {
            RenderLine(x,y,usefulWidth,line->ln_Text,line->ln_TextLen);
            y    += fontHeight;
            line  = (struct Line *)line->ln_Link.mln_Succ;
        }
    }

    /* unlock the layer so normal operations can resume */
    UnlockLayer(window->WLayer);

    /* keep track of what the current top line is. That way, when we
     * come back in this routine later, and "topLine" has changed, we
     * can tell how many lines we need to scroll in order to sync up the
     * display
     */
    oldTopLine = topLine;
}

/*****************************************************************************/

/* Whenever the application is busy, this function is called. It will
 * change the behavior of the backfill hook in order to improve the
 * appearance of the display until the application completes its lengthy
 * task.
 *
 * You could also set a busy pointer in the document window in this routine
 * to tell the user you are not listening to him for awhile.
 */
VOID BusyState(BOOL makeBusy)
{
    taskBusy = makeBusy;

    if (LAYERREFRESH & window->WLayer->Flags)
    {
        BeginRefresh(window);
        RefreshView(TRUE);
        EndRefresh(window,TRUE);
    }
}

/*****************************************************************************/

/* This routine is a typical event processor. It looks and acts on all events
 * arriving at the window's port.
 */
VOID EventLoop(VOID)
{
struct IntuiMessage *intuiMsg;
ULONG                class;

    topLine    = 0;
    oldTopLine = 0;

    /* initialize rendering attributes we are going to use */
    render = *window->RPort;
    SetDrMd(&render,JAM2);
    SetWrMsk(&render,1);         /* we only want to render in the first plane */
    SetAPen(&render,1);

    /* initialize clearing attributes we are going to use */
    clear = *window->RPort;
    SetDrMd(&clear,JAM2);
    SetWrMsk(&clear,1);          /* we only want to clear the first plane */
    SetAPen(&clear,0);

    /* render the initial display */
    RefreshView(TRUE);

    /* set the initial scroller position and size */
    SetScroller(window,scroller,linesVisible,numLines,topLine);

    /* we aren't busy, so register that fact */
    BusyState(FALSE);

    while (TRUE)
    {
        /* if the LAYERREFRESH flag is set in the window's layer, it
         * means the layer has some damage we should repair.
         */
        if (LAYERREFRESH & window->WLayer->Flags)
        {
            /* enter optimized repair state */
            BeginRefresh(window);

            /* redraw the whole display through the optimized repair
             * region
             */
            RefreshView(TRUE);

            /* tell the system we are done repairing the window
             */
            EndRefresh(window,TRUE);
        }

        /* nothing left to do but wait for user input */
        WaitPort(window->UserPort);
        intuiMsg = (struct IntuiMessage *)GetMsg(window->UserPort);
        class    = intuiMsg->Class;
        ReplyMsg(intuiMsg);

        /* we got a message, so act on it */
        switch (class)
        {
            /* user clicked on the close gadget, exit the program */
            case IDCMP_CLOSEWINDOW  : return;

            /* user sized the window. We need to redraw the whole
             * display in order to eliminate any garbage. Start by
             * calling BeginRefresh() and EndRefresh() to eliminate
             * the window's damage regions then completely redraw
             * the window contents.
             */
            case IDCMP_NEWSIZE      : BeginRefresh(window);
                                      EndRefresh(window,TRUE);
                                      RefreshView(TRUE);
                                      SetScroller(window,
                                                  scroller,
                                                  linesVisible,
                                                  numLines,
                                                  topLine);
                                      break;

            /* Intuition is telling us damage occured to our layer.
             * Don't bother doing anything, the check at the top of the
             * loop will catch this fact and refresh the display
             *
             * Even though we don't do anything with these events, we
             * still need them to be sent to us so we will wake up and
             * look at the LAYERREFRESH bit.
             */
            case IDCMP_REFRESHWINDOW: break;

            /* user is playing with the scroller. Get the scroller's current
             * top line and synchronize the display to match it
             */
            case IDCMP_GADGETUP     :
            case IDCMP_GADGETDOWN   :
            case IDCMP_MOUSEMOVE    : GetAttr(PGA_Top,scroller,&topLine);
                                      RefreshView(FALSE);
                                      break;

            /* whenever a key is hit, we fake becoming busy for 4
             * seconds. During that time, try to size and depth arrange
             * the window to see what happens to its contents
             */
            case IDCMP_VANILLAKEY   : BusyState(TRUE);
                                      Delay(200);
                                      BusyState(FALSE);
                                      break;
        }
    }
}


IV-91/WheelGrad.c

;/*
sc DATA=NEAR OPTSIZE OPTIMIZE OPTGLOBAL NOSTKCHK NMINC STRMERGE STREQ MCCONS COMNEST IGNORE=73 WheelGrad.c
slink from lib:c.o WheelGrad.o to WheelGrad lib lib:sc.lib lib:amiga.lib
quit
*/

/*
(c)  Copyright 1992-1999 Amiga, Inc.   All rights reserved.
The information contained herein is subject to change without notice,
and is provided "as is" without warranty of any kind, either expressed
or implied.  The entire risk as to the use of this information is
assumed by the user.
*/

/*
 * WheelGrad.c - simple example of colorwheel and gradient slider
 *
 * Puts up a colorwheel and gradient slider and changes the gradient slider
 * color based on where the colorwheel knob is moved.  This will get you
 * pointed in the right direction.
 *
 * The code will attempt to open the deepest possible screen by querying
 * the display database.
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <intuition/screens.h>
#include <graphics/displayinfo.h>
#include <intuition/gadgetclass.h>
#include <gadgets/colorwheel.h>
#include <gadgets/gradientslider.h>
#include <dos/dos.h>

#include <clib/intuition_protos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/graphics_protos.h>
#include <clib/colorwheel_protos.h>

#include <stdio.h>
#include <stdlib.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

struct Library *IntuitionBase = NULL;
struct Library *GfxBase = NULL;
struct Library *ColorWheelBase = NULL;
struct Library *GradientSliderBase = NULL;

struct load32
{
    UWORD	l32_len;
    UWORD	l32_pen;
    ULONG	l32_red;
    ULONG	l32_grn;
    ULONG	l32_blu;
};

void main(void)
{
struct Screen *Myscreen;
struct Window *Mywindow;
struct IntuiMessage *msg;
struct Gadget *colwheel, *gradslid;

#define GRADCOLORS 16  /* Set to 4 for ECS to ensure enough color wheel pens */

ULONG colortable[96], mywinsig;
struct load32 color_list[GRADCOLORS + 1];
WORD penns[GRADCOLORS + 1];
WORD  i;
BOOL   Closeflag = FALSE;
struct ColorWheelRGB rgb;
struct ColorWheelHSB hsb;
WORD numPens;
ULONG modeID = HIRES_KEY;
UWORD maxdepth;
DisplayInfoHandle displayhandle;
struct DimensionInfo dimensioninfo;
ULONG gdidres;
ULONG exitvalue = RETURN_FAIL;

    if (IntuitionBase = OpenLibrary("intuition.library",39))
    if (GfxBase = OpenLibrary("graphics.library",39))
    if (ColorWheelBase = OpenLibrary("gadgets/colorwheel.gadget",39L))
    if (GradientSliderBase=OpenLibrary("gadgets/gradientslider.gadget",39L))
    if (displayhandle = FindDisplayInfo(modeID))
    if (gdidres=GetDisplayInfoData(displayhandle,(UBYTE *) &dimensioninfo,
                   sizeof(struct DimensionInfo),
                   DTAG_DIMS,NULL))
    {
    maxdepth = dimensioninfo.MaxDepth;

        Myscreen = OpenScreenTags(NULL,
                  SA_Depth,         maxdepth,
                  SA_SharePens,     TRUE,
                  SA_LikeWorkbench, TRUE,
                  SA_Interleaved,   TRUE,
                  SA_Title,         "WheelGrad Screen",
                  TAG_DONE);

        if (Myscreen)
        {
            /* Get colors and set up gradient slider as color 0. */

            /* get the RGB components of color 0 */
            GetRGB32(Myscreen->ViewPort.ColorMap,0L,32L,colortable);
            rgb.cw_Red   = colortable[0];
            rgb.cw_Green = colortable[1];
            rgb.cw_Blue  = colortable[2];

            /* now convert the RGB values to HSB, and max out B component */
            ConvertRGBToHSB(&rgb,&hsb);
            hsb.cw_Brightness = 0xffffffff;

            numPens = 0;
            while (numPens < GRADCOLORS)
            {
                hsb.cw_Brightness = 0xffffffff - ((0xffffffff / GRADCOLORS) * numPens);
                ConvertHSBToRGB(&hsb,&rgb);

                penns[numPens] = ObtainPen(Myscreen->ViewPort.ColorMap,-1,
                                 rgb.cw_Red,rgb.cw_Green,rgb.cw_Blue,PEN_EXCLUSIVE);
                if (penns[numPens] == -1)
                    break;

                /* Set up LoadRGB32() structure for this pen */
        color_list[numPens].l32_len = 1;
        color_list[numPens].l32_pen = penns[numPens];
                numPens++;
            }
            penns[numPens] = ~0;
        color_list[numPens].l32_len = 0;

        /* Create gradient slider and colorwheel gadgets */
        gradslid = (struct Gadget *)NewObject(NULL,"gradientslider.gadget",
                         GA_Top,        50,
                         GA_Left,       177,
                         GA_Width,      20,
                         GA_Height,     100,
                         GA_ID,         1L,
                         GRAD_PenArray, penns,
                         PGA_Freedom,   LORIENT_VERT,
                         TAG_END);

        colwheel = (struct Gadget *)NewObject(NULL, "colorwheel.gadget",
                  GA_Top,               50,
                  GA_Left,              50,
                  GA_Width,             120,
                  GA_Height,            100,
                  WHEEL_Red,            colortable[0],
                  WHEEL_Green,          colortable[1],
                  WHEEL_Blue,           colortable[2],
                  WHEEL_Screen,         Myscreen,
                  WHEEL_GradientSlider, gradslid,  /* connect gadgets */
                  GA_FollowMouse,       TRUE,
                  GA_Previous,          gradslid,
                  GA_ID,                7L,
                  TAG_END);

        if (gradslid && colwheel)
        {
        if (Mywindow = OpenWindowTags(NULL, WA_Left,         10,
                            WA_Top,          20,
                            WA_Height,       200,
                            WA_Width,        400,
                            WA_Title,        "WheelGrad Window",
                            WA_CustomScreen, Myscreen,
                            WA_IDCMP,        IDCMP_CLOSEWINDOW | IDCMP_MOUSEMOVE,
                            WA_SizeGadget,   TRUE,
                            WA_DragBar,      TRUE,
                            WA_CloseGadget,  TRUE,
                            WA_Gadgets,      gradslid,
                            TAG_DONE))
        {
            mywinsig = 1 << Mywindow->UserPort->mp_SigBit;

            do
            {
            Wait(mywinsig);

            while (msg = (struct IntuiMessage *)GetMsg(Mywindow->UserPort))
            {
                switch (msg->Class)
                {
                case IDCMP_CLOSEWINDOW:
                   Closeflag = TRUE;
                   break;
                case IDCMP_MOUSEMOVE:

                   /*
                * Change gradient slider color each time
                * colorwheel knob is moved.  This is one
                * method you can use.
                */

                   /* Query the colorwheel */
                   GetAttr(WHEEL_HSB,colwheel,(ULONG *)&hsb);

                   i = 0;

                   while (i < numPens)
                   {
                   hsb.cw_Brightness =
                                  0xffffffff - ((0xffffffff / numPens) * i);
                   ConvertHSBToRGB(&hsb,&rgb);

                   color_list[i].l32_red = rgb.cw_Red;
                   color_list[i].l32_grn = rgb.cw_Green;
                   color_list[i].l32_blu = rgb.cw_Blue;
                   i++;
                   }
                   LoadRGB32(&Myscreen->ViewPort,(ULONG *)color_list);
                   break;
                }
                ReplyMsg((struct Message *)msg);
            }
            }
            while (Closeflag == FALSE);
        }
        CloseWindow(Mywindow);
        }

            /* Get rid of the gadgets */
            DisposeObject(colwheel);
            DisposeObject(gradslid);

            /* Always release the pens */
            while (numPens > 0)
            {
                numPens--;
                ReleasePen(Myscreen->ViewPort.ColorMap,penns[numPens]);
            }

            CloseScreen(Myscreen);
        exitvalue = RETURN_OK;
        }
    else
        printf("Failed to open screen\n");
    }

    if (gdidres == 0)
    printf("Screen mode dimension information not available\n");

    if (displayhandle == NULL)
    printf("Failed to find HIRES_KEY in display database\n");

    if (GradientSliderBase)
        CloseLibrary(GradientSliderBase);
    else
    printf("Failed to open gadgets/gradientslider.gadget\n");

    if (ColorWheelBase)
        CloseLibrary(ColorWheelBase);
    else
    printf("Failed to open gadgets/colorwheel.gadget\n");

    if (GfxBase)
        CloseLibrary(GfxBase);
    else
    printf("Failed to open graphics.library\n");

    if (IntuitionBase)
        CloseLibrary(IntuitionBase);
    else
    printf("Failed to open intuition.library\n");

    exit(exitvalue);
}


IV-101/dt.c

; /* Compiled with SAS/C 6.56.  Run from CLI only.
sc DATA=NEAR NMINC STRMERGE NOSTKCHK IGNORE=73 dt.c
slink from lib:c.o dt.o TO dt LIBRARY lib:sc.lib lib:amiga.lib
quit ; */

#include <exec/types.h>
#include <datatypes/datatypesclass.h>  /* This includes other files we need */
#include <stdio.h>

#include <clib/exec_protos.h>          /* Prototypes for system functions */
#include <clib/intuition_protos.h>
#include <clib/datatypes_protos.h>

#ifdef LATTICE                         /* Disable SAS/C CTRL-C handling */
int CXBRK(void)    { return(0); }
int chkabort(void) { return(0); }
#endif

struct Library *IntuitionBase=NULL;    /* System library bases */
struct Library *DataTypesBase=NULL;

VOID main(int argc, char **argv)
{
APTR dtobject=NULL;        /* Pointer to a datatypes object */
struct dtTrigger mydtt;    /* A trigger structure for the DTM_TRIGGER method */
ULONG dores;               /* Variable for return values    */

if (IntuitionBase=OpenLibrary("intuition.library",39L))
   {
   if(DataTypesBase=OpenLibrary("datatypes.library",39L) )
      {
      if(argc > 1 ) /* CLI only, at least one argument please. */
         {
         /* Attempt to make an 8svx sound object from the file name the user */
         /* specified in the command line.  For a list of possible error     */
         /* returns, see the Autodocs for NewDTObjectA().  The group ID tag  */
         /* will allow only sound datatype files to be accepted for the call.*/
         if (dtobject = NewDTObject(argv[1], DTA_GroupID, GID_SOUND,
                                             TAG_END) )
            {
            mydtt.MethodID     = DTM_TRIGGER; /* Fill in the dtTrigger struct */
            mydtt.dtt_GInfo    = NULL;
            mydtt.dtt_Function = STM_PLAY;
            mydtt.dtt_Data     = NULL;

            /* The return value of the DTM_TRIGGER method used with the 8svx */
            /* sound datatype is undefined in V39.  This is likely to change */
            /* in future versions of the Amiga operating system.             */
            dores = DoDTMethodA(dtobject, NULL, NULL, &mydtt);

            /* Let the 8svx sound finish playing.  Currently (V39) there is  */
            /* no programmatic way to find out when it is finished playing.  */
            Wait(SIGBREAKF_CTRL_C);

            DisposeDTObject(dtobject);
            }
         else printf("Couldn't create new object or not a sound data file\n");

         }
      else printf("Give a file name too.\n");

      CloseLibrary(DataTypesBase);
      }
   else printf("Can't open datatypes library\n");

   CloseLibrary(IntuitionBase);
   }
else printf("Can't open V39 Intuition\n");
}


IV-101/dtpic.c

; /* Compiled with SAS/C 6.56.  Run from CLI only.
sc DATA=NEAR NMINC STRMERGE NOSTKCHK IGNORE=73 dtpic.c
slink from lib:c.o dtpic.o TO dtpic LIBRARY lib:sc.lib lib:amiga.lib
quit ; */

#include <exec/types.h>
#include <datatypes/datatypes.h>      /* Datatypes definitions we need */
#include <datatypes/pictureclass.h>
#include <stdio.h>

#include <clib/exec_protos.h>         /* Prototypes for system functions */
#include <clib/intuition_protos.h>
#include <clib/alib_protos.h>
#include <clib/datatypes_protos.h>
#include <clib/graphics_protos.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }     /* Disable SAS/C CTRL-C handling */
int chkabort(void) { return(0); }
#endif

struct Library *IntuitionBase=NULL;   /* System library bases */
struct Library *GfxBase=NULL;
struct Library *DataTypesBase=NULL;

VOID main(int argc, char **argv)
{
APTR dtobject=NULL;                   /* Pointer to a datatypes object       */
ULONG res;                            /* Variable for function return values */
struct dtFrameBox mydtFrameBox;       /* Use this with DTM_FRAMEBOX method   */
struct FrameInfo myFrameInfo;         /* For info returned from DTM_FRAMEBOX */
struct gpLayout mygpLayout;           /* Use this with DTM_PROCLAYOUT method */

ULONG modeID = INVALID_ID;            /* Variables for storing the display */
struct Screen *myScreen=NULL;         /* environment information obtained  */
struct BitMap *bm = NULL;             /* the datatype object.              */
ULONG *cregs = NULL;
ULONG i,r,g,b,numcolors;

if (IntuitionBase=OpenLibrary("intuition.library",39L))
  {
  if (GfxBase=OpenLibrary("graphics.library",39L))
    {
    if(DataTypesBase=OpenLibrary("datatypes.library",0L))
        {
        if(argc > 1 ) /* CLI only, at least one argument please.  */
            {
            /* Attempt to create a picture object in memory from the file    */
            /* name given by the user in the command line.  If we wanted to  */
            /* show the picture in a screen set up ahead of time, we could   */
            /* set PDTA_Remap to TRUE and provide a pointer to the screen    */
            /* with the PDTA_Screen tag (datatypes.library handles the rest).*/
            /* However in this case we want to first find out the attributes */
            /* of the picture object and set up a matching screen and do the */
            /* remapping later.  Therefore PDTA_Remap is set to false.       */
            /* The group ID tag ensures that we get only a picture file type.*/
            if (dtobject = NewDTObject(argv[1], PDTA_Remap,  FALSE,
                                                DTA_GroupID, GID_PICTURE,
                                                TAG_END) )
                {
                /* Here we want to find the display environment required by  */
                /* this picture.  To do that, perform the DTM_FRAMEBOX method */
                /* on the object.  The datatypes library fills in the struct */
                /* FrameBox you give it with the info on the display needed.  */
                mydtFrameBox.MethodID         = DTM_FRAMEBOX;
                mydtFrameBox.dtf_GInfo        = NULL;
                mydtFrameBox.dtf_ContentsInfo = NULL;
                mydtFrameBox.dtf_FrameInfo    = &myFrameInfo;
                mydtFrameBox.dtf_SizeFrameInfo= sizeof (struct FrameInfo);
                mydtFrameBox.dtf_FrameFlags   = 0L;

                /* The return value from DTM_FRAMEBOX is currently undefined */
                res = DoMethodA(dtobject, &mydtFrameBox);

                /* OK, now do the layout (remap) of the object on our process */
                mygpLayout.MethodID   = DTM_PROCLAYOUT;
                mygpLayout.gpl_GInfo  = NULL;
                mygpLayout.gpl_Initial= 1L;

                /* The return value of DTM_PROCLAYOUT is non-zero for success */
                if( res = DoMethodA(dtobject, &mygpLayout) )
                   {
                   /* Get the attributes of this picture object.  You could  */
                   /* use a series of GetAttr() function calls here instead.  */
                   res = GetDTAttrs(dtobject, PDTA_ModeID, &modeID,
                                              PDTA_CRegs, &cregs,
                                              PDTA_BitMap, &bm,
                                              TAG_END);

                   /* Did we get all threee attributes? */
                   if( (modeID!=INVALID_ID) && (cregs) && (bm) )
                       {
                       /* Open a screen that matches the picture object */
                       if( myScreen = OpenScreenTags( NULL,
                           SA_Width,     myFrameInfo.fri_Dimensions.Width,
                           SA_Height,    myFrameInfo.fri_Dimensions.Height,
                           SA_Depth,     myFrameInfo.fri_Dimensions.Depth,
                           SA_DisplayID, modeID,
                           SA_BitMap,    bm,
                           TAG_END) )
                           {
                           /* Now fill in the color registers for this screen */
                           numcolors = 2<<(myFrameInfo.fri_Dimensions.Depth-1);
                           for( i=0; i < numcolors; i++ )
                              {
                              r = cregs[i * 3 + 0];
                              g = cregs[i * 3 + 1];
                              b = cregs[i * 3 + 2];
                              SetRGB32(&myScreen->ViewPort, i, r, g, b);
                              }

                           printf("Ctrl-C in this window to quit\n");
                           /* Wait for the user to have a look...  */
                           Wait(SIGBREAKF_CTRL_C);

                           CloseScreen(myScreen);
                           }
                       else printf("Couldn't open required screen\n");
                       }
                   else printf("Couldn't get picture attributes\n");

                  DisposeDTObject(dtobject);
                  }
               else printf("Couldn't perform PROC_LAYOUT\n");
               }
            else printf("Couldn't create new object or not a picture file\n");
            }
        else printf("Give a file name too.\n");

        CloseLibrary(DataTypesBase);
        }
    else printf("Can't open datatypes library\n");

    CloseLibrary(GfxBase);
    }
  else printf("Can't open V39 graphics\n");

  CloseLibrary(IntuitionBase);
  }
else printf("Can't open V39 Intuition\n");
}


IV-111/relative.c

;/*
sc DATA=NEAR NMINC STRMERGE NOSTKCHK SAVEDS IGNORE=73 relative
slink FROM LIB:c.o relative.o TO relative LIB LIB:sc.lib LIB:amiga.lib
quit
*/

/* (c)  Copyright 1993-1999 Amiga, Inc.   All rights reserved. */
/* The information contained herein is subject to change without    */
/* notice, and is provided "as is" without warranty of any kind,    */
/* either expressed or implied.  The entire risk as to the use of   */
/* this information is assumed by the user.                         */

/*
 * relative.c - shows custom gadget relativity
 *
 * custom gadget relativity allows a gadget to arbitrarily resize
 * itself whenever the window changes size.  This is a complete superset
 * of the functionality of the old GRELWIDTH, GRELRIGHT, etc., features.
 * This example shows a subclass of gadgetclass whose imagery comes
 * from frameiclass.  This gadget's property is that it is always half
 * the size of its domain, and centered within it.  That is, it's always
 * half as wide and half as tall as the inner area of its window, and
 * centered within that area.
 */

#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <intuition/imageclass.h>
#include <intuition/cghooks.h>
#include <intuition/classes.h>
#include <intuition/classusr.h>

#include <clib/alib_protos.h>
#include <clib/alib_stdio_protos.h>
#include <clib/exec_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>

struct Library *GfxBase = NULL;
struct Library *IntuitionBase = NULL;
struct Window *win = NULL;
struct Gadget *gad = NULL;
Class *customrelclass = NULL;

Class *initCustomRelClass(void);
ULONG __saveds __asm dispatchCustomRel( register __a0 Class *cl,
                                         register __a2 Object *o,
                                         register __a1 Msg msg );
void                 renderCustomRel( struct Gadget *gad,
                                       struct RastPort *rp,
                                       struct GadgetInfo *gi );
void                 layoutCustomRel( struct Gadget *gad,
                                       struct GadgetInfo *gi,
                                       ULONG initial );
LONG                 handleCustomRel( struct Gadget *gad,
                                       struct gpInput *msg );

void main(void)
{
  if ( GfxBase = OpenLibrary("graphics.library",39) )
  {
    if ( IntuitionBase = OpenLibrary("intuition.library",39) )
    {
      if ( customrelclass = initCustomRelClass() )
      {
        if ( gad = NewObject( customrelclass, NULL,
            GA_Left, 20,
            GA_Top, 20,
            GA_Width, 20,
            GA_Height, 20,
            GA_RelVerify, TRUE,
            GA_Immediate, TRUE,
            TAG_DONE ) )
        {
          if ( win = OpenWindowTags( NULL,
              WA_Title, "Custom Relativity Demo",
              WA_CloseGadget, TRUE,
              WA_DepthGadget, TRUE,
              WA_DragBar, TRUE,
              WA_SizeGadget, TRUE,
              WA_Gadgets, gad,
              WA_Activate, TRUE,
              WA_IDCMP, IDCMP_GADGETHELP | IDCMP_RAWKEY | IDCMP_CLOSEWINDOW |
                        IDCMP_GADGETDOWN | IDCMP_GADGETUP,
              WA_Width, 150,
              WA_Height, 150,
              WA_MinWidth, 50,
              WA_MinHeight, 50,
              WA_MaxWidth, ~0,
              WA_MaxHeight, ~0,
              WA_NoCareRefresh, TRUE,
              TAG_DONE ) )
          {
            BOOL terminated = FALSE;
            struct IntuiMessage *imsg;

            /* Turn on Gadget Help */
            HelpControl( win, HC_GADGETHELP );

            while (!terminated)
            {
              Wait (1 << win->UserPort->mp_SigBit);
              while (imsg = (struct IntuiMessage *) GetMsg(win->UserPort))
              {
                switch ( imsg->Class )
                {
                case IDCMP_CLOSEWINDOW:
                  terminated = TRUE;
                  break;

                case IDCMP_RAWKEY:
                  printf("RAWKEY %lx\n", imsg->Code);
                  break;

                case IDCMP_GADGETUP:
                  printf("Gadget Up\n");
                  break;

                case IDCMP_GADGETDOWN:
                  printf("Gadget Down\n");
                  break;

                case IDCMP_GADGETHELP:
                  if ( imsg->IAddress == NULL )
                  {
                    printf("Gadget Help: Mouse not over window\n");
                  }
                  else if ( imsg->IAddress == (APTR) win )
                  {
                    printf("Gadget Help: Mouse in window, not over a gadget\n");
                  }
                  else
                  {
                    /* Detect system gadgets.  Figure out by looking at
                     * system-gadget-type bits in GadgetType field:
                     */
                    LONG sysgtype =
                      ((struct Gadget *)imsg->IAddress)->GadgetType & GTYP_SYSTYPEMASK;
                    switch ( sysgtype )
                    {
                    case GTYP_SIZING:
                      printf("Gadget Help for window sizing gadget\n");
                      break;

                    case GTYP_WDRAGGING:
                      printf("Gadget Help for window drag-bar\n");
                      break;

                    case GTYP_WUPFRONT:
                      printf("Gadget Help for window depth gadget\n");
                      break;

                    case GTYP_WDOWNBACK:
                      printf("Gadget Help for window zoom gadget\n");
                      break;

                    case GTYP_CLOSE:
                      printf("Gadget Help for window close gadget\n");
                      break;

                    case 0:
                      /* In this example, we only have one gadget,
                       * so we know which one it is.  Normally, you'd
                       * have to figure that out here, using the
                       * usual techniques you already use for other
                       * gadget messages.
                       */
                      printf("Gadget Help for gadget, code 0x%x\n",
                          imsg->Code);
                      break;

                    default:
                      printf("Gadget Help on some other system gadget\n");
                      break;
                    }
                  }
                }
                ReplyMsg((struct Message *)imsg);
              }
            }
            CloseWindow( win );
          }
          DisposeObject( gad );
        }
        FreeClass( customrelclass );
      }
      CloseLibrary( IntuitionBase );
    }
    CloseLibrary( GfxBase );
  }
}

/* initCustomRelClass()
 *
 * Initialize a simple private subclass of gadgetclass that
 * knows about GM_LAYOUT.
 *
 */

Class *initCustomRelClass( void )
{
  Class *cl;

  /* Create a private class: */
  if ( cl = MakeClass( NULL, "gadgetclass", NULL, 0, 0 ) )
  {
    cl->cl_Dispatcher.h_SubEntry = NULL;
    cl->cl_Dispatcher.h_Entry = dispatchCustomRel;
    cl->cl_Dispatcher.h_Data = NULL;
  }
  return ( cl );
}

/* dispatchCustomRel()
 *
 * boopsi dispatcher for the custom relativity class.
 *
 */

ULONG __saveds __asm
dispatchCustomRel( register __a0 Class *cl,
                    register __a2 Object *o,
                    register __a1 Msg msg )
{
  ULONG retval = 1;
  Object *newobj;

  switch ( msg->MethodID )
  {
  case OM_NEW:
    if ( retval = (ULONG)(newobj = (Object *) DoSuperMethodA( cl, o, msg )) )
    {
      /* Set custom relativity */
      ((struct Gadget *)newobj)->Flags |= GFLG_RELSPECIAL;

      /* Tell Intuition this gadget supports gadget help */
      SetAttrs(newobj, GA_GadgetHelp, TRUE, TAG_DONE, NULL);

      /* Attempt to allocate a frame.  If I can't, then
       * delete myself and fail.
       */
      if ( ! ( ((struct Gadget *)newobj)->GadgetRender =
          NewObject( NULL, "frameiclass",
                     IA_FrameType, FRAME_BUTTON,
                     TAG_DONE ) ) )
      {
        CoerceMethod( cl, o, OM_DISPOSE );
        retval = NULL;
      }
    }
    break;

  case GM_LAYOUT:
    layoutCustomRel( (struct Gadget *)o, ((struct gpLayout *)msg)->gpl_GInfo,
        ((struct gpLayout *)msg)->gpl_Initial );
    break;

  case GM_RENDER:
    renderCustomRel( (struct Gadget *)o, ((struct gpRender *) msg)->gpr_RPort,
        ((struct gpRender *) msg)->gpr_GInfo );
    break;

  case GM_GOACTIVE:
    return( GMR_MEACTIVE );
    break;

  case GM_HELPTEST:
    return(GMR_HELPCODE | 0x0000C0DE);
    break;

  case GM_HANDLEINPUT:
    retval = handleCustomRel( (struct Gadget *)o, (struct gpInput *)msg );
    break;

  case OM_DISPOSE:
    DisposeObject( ((struct Gadget *)o)->GadgetRender );
    /* fall through to default */
  default:
    retval = (ULONG) DoSuperMethodA( cl, o, msg );
  }
  return( retval );
}

/* renderCustomRel()
 *
 * Simple routine to draw my imagery based on my selected state.
 *
 */
void
renderCustomRel( struct Gadget *gad, struct RastPort *rp, struct GadgetInfo *gi )
{
  DrawImageState( rp, gad->GadgetRender, gad->LeftEdge, gad->TopEdge,
      (gad->Flags & GFLG_SELECTED) ? IDS_SELECTED : IDS_NORMAL,
      gi ? gi->gi_DrInfo : NULL );
}

/* layoutCustomRel()
 *
 * Lay myself out based on my domain dimensions.  Refigure my own size,
 * then inform my image of the size change.
 *
 */
void
layoutCustomRel( struct Gadget *gad, struct GadgetInfo *gi, ULONG initial )
{
  if ( gi->gi_Requester )
  {
    /* Center it within the requester */
    gad->Width = gi->gi_Domain.Width / 2;
    gad->Height = gi->gi_Domain.Height / 2;
    gad->LeftEdge = gad->Width / 2;
    gad->TopEdge = gad->Height / 2;
  }
  else
  {
    /* Center it within the window, after accounting for
     * the window borders
     */
    gad->Width = ( gi->gi_Domain.Width -
        gi->gi_Window->BorderLeft - gi->gi_Window->BorderRight ) / 2;
    gad->Height = ( gi->gi_Domain.Height -
        gi->gi_Window->BorderTop - gi->gi_Window->BorderBottom ) / 2;
    gad->LeftEdge = ( gad->Width / 2 ) + gi->gi_Window->BorderLeft;
    gad->TopEdge = ( gad->Height / 2 ) + gi->gi_Window->BorderTop;
  }
  SetAttrs( gad->GadgetRender,
    IA_Width, gad->Width,
    IA_Height, gad->Height,
    TAG_DONE );
}

/* handleCustomRel()
 *
 * Routine to handle input to the gadget.  Behaves like a basic
 * hit-select gadget.
 *
 */
LONG
handleCustomRel( struct Gadget *gad, struct gpInput *msg )
{
  WORD selected = 0;
  struct RastPort *rp;
  LONG retval = GMR_MEACTIVE;

  /* Could send IM_HITTEST to image instead */
  if ( ( msg->gpi_Mouse.X >= 0 ) &&
      ( msg->gpi_Mouse.X < gad->Width ) &&
      ( msg->gpi_Mouse.Y >= 0 ) &&
      ( msg->gpi_Mouse.Y < gad->Height ) )
  {
    selected = GFLG_SELECTED;
  }

  if ((msg->gpi_IEvent->ie_Class == IECLASS_RAWMOUSE) &&
      (msg->gpi_IEvent->ie_Code == SELECTUP))
  {
    /* gadgetup, time to go */
    if ( selected )
    {
      retval = GMR_NOREUSE | GMR_VERIFY;
    }
    else
    {
      retval = GMR_NOREUSE;
    }
    /* and unselect the gadget on our way out... */
    selected = 0;
  }

  if ( ( gad->Flags & GFLG_SELECTED ) != selected )
  {
    gad->Flags ^= GFLG_SELECTED;
    if ( rp = ObtainGIRPort( msg->gpi_GInfo ) )
    {
      DoMethod( (Object *)gad, GM_RENDER, msg->gpi_GInfo, rp, GREDRAW_UPDATE );
      ReleaseGIRPort( rp );
    }
  }

  return( retval );
}


IV-125/NewGadgets.c

;/* newgadgets.c -- execute me to compile me
sc data=near nominc strmer streq nostkchk saveds ign=73 newgadgets
slink FROM LIB:c.o newgadgets.o TO newgadgets LIB LIB:sc.lib LIB:amiga.lib
quit

This code is only designed to demonstrate some of the new 3.0 GadTools
features. It does not handle all of the IDCMP events and other conditions like
allocating pens for the palette gadget that a good user interface should.

Note also, that it takes advantage of the SAS 6.0 C compiler.

*/

/* (c)  Copyright 1993-1999 Amiga, Inc.   All rights reserved. */
/* The information contained herein is subject to change without    */
/* notice, and is provided "as is" without warranty of any kind,    */
/* either expressed or implied.  The entire risk as to the use of   */
/* this information is assumed by the user.                         */

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/nodes.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <intuition/gadgetclass.h>
#include <libraries/diskfont.h>
#include <libraries/gadtools.h>

#include <clib/intuition_protos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/alib_protos.h>
#include <clib/diskfont_protos.h>
#include <clib/graphics_protos.h>
#include <clib/gadtools_protos.h>

#include <stdio.h>

#ifdef LATTICE
int
CXBRK (void)
{
  return (0);
}                               /* Disable Lattice CTRL/C handling */

int
chkabort (void)
{
  return (0);
}                               /* really */

#endif

/* declare the library base pointers */
extern struct IntuitionBase *IntuitionBase;
extern struct Library *DiskfontBase, *GfxBase, *GadToolsBase;

/* lots of gadgets used here */
struct Gadget *glist = NULL, *stringgad, *textgad, *checkgad, *mxgad, *palgad, *listgad,
 *intgad, *numgad, *slid1gad, *slid2gad, *slid3gad;

/* assign the gadget ids even though we're not using them */
#define MYGAD_STRING        69
#define MYGAD_TEXT          70
#define MYGAD_CHECK         71
#define MYGAD_MX            72
#define MYGAD_PAL           73
#define MYGAD_LIST          74
#define MYGAD_INT           75
#define MYGAD_NUM           76
#define MYGAD_SLIDERLEFT    77
#define MYGAD_SLIDERCENTER  78
#define MYGAD_SLIDERRIGHT   79

struct List *DaList;            /* the listview list */

UBYTE colors[7] =
{1, 2, 15, 6, 0, 3, 8};   /* the palette colortable */

/*
 *  Create the listview list
 */

BOOL
CreateDaList (UBYTE * names[])
{
  struct Node *DaListNode;
  USHORT i;
  BOOL okay = TRUE;

  if (DaList = AllocMem (sizeof (struct List), MEMF_FAST))
  {
    NewList (DaList);

    for (i = 0; names[i] != NULL && okay == TRUE; i++)
    {
      if (DaListNode = AllocMem (sizeof (struct Node), MEMF_FAST))
      {
        DaListNode->ln_Name = names[i];
        DaListNode->ln_Type = 100L;
        DaListNode->ln_Pri = 0;
        AddTail (DaList, DaListNode);
      }
      else
      {
        printf ("Could not allocate memory for node\n");
        okay = FALSE;
      }
    }
  }
  else
  {
    printf ("Could not allocate memory for list\n");
    okay = FALSE;
  }

  return (okay);
}

/*
 * Create the gadgets.
 *   The gadgets are more or less positioned relative to the window size
 *   and each other.  This is not extremely sophisticated, so don't expect
 *   them to look good on a lores screen.
 */

struct Gadget *
CreateGads (struct Screen *scr, struct VisualInfo *vi,
            struct TextAttr *gadfont)
{
  struct Gadget *gad;
  struct NewGadget ng;
  UBYTE *BassLines[] =
  {"Always", "Fine", "Do", "Boys", "Good", NULL};       /* mx choices */
  UBYTE *BassSpaces[] =
  {"Grass", "Eat", "Cows", "All", NULL};        /* listview choices */

  if (gad = CreateContext (&glist))
  {
    /* create an MX gadget */
    ng.ng_TextAttr = gadfont;
    ng.ng_VisualInfo = vi;
    ng.ng_LeftEdge = 80 + scr->WBorLeft;
    ng.ng_TopEdge = 30 + scr->WBorTop + (scr->Font->ta_YSize + 1);
    ng.ng_Width = 50;
    ng.ng_Height = 30;
    ng.ng_GadgetText = "Bass Lines";
    ng.ng_GadgetID = MYGAD_MX;
    ng.ng_Flags = 0;
    mxgad = gad = CreateGadget (MX_KIND, gad, &ng,
                                GTMX_TitlePlace, PLACETEXT_ABOVE,
                                GTMX_Labels, BassLines, GTMX_Scaled, TRUE,
                                GTMX_Spacing, gadfont->ta_YSize + 1, TAG_END);
    /* create a slider gadget */
    ng.ng_TopEdge = scr->Height - 170;
    ng.ng_Height = 10;
    ng.ng_Width = 100;
    ng.ng_GadgetText = "Left Justified";
    ng.ng_GadgetID = MYGAD_SLIDERLEFT;
    ng.ng_Flags = PLACETEXT_ABOVE;
    slid1gad = gad = CreateGadget (SLIDER_KIND, gad, &ng,
                                   GTSL_MaxLevelLen, 6,
                                   GTSL_MaxPixelLen, 64,
                                   GTSL_Max, 512,
                                   GTSL_Justification, GTJ_LEFT,
                                   GTSL_LevelFormat, "%lx",
                                   GTSL_LevelPlace, PLACETEXT_BELOW,
                                   TAG_END);

    /* create a slider gadget */
    ng.ng_TopEdge = ng.ng_TopEdge + 55;
    ng.ng_GadgetText = "Centered";
    ng.ng_GadgetID = MYGAD_SLIDERCENTER;
    slid2gad = gad = CreateGadget (SLIDER_KIND, gad, &ng,
                                   GTSL_MaxLevelLen, 6,
                                   GTSL_MaxPixelLen, 64,
                                   GTSL_Max, 512,
                                   GTSL_LevelFormat, "%lx",
                                   GTSL_Justification, GTJ_CENTER,
                                   GTSL_LevelPlace, PLACETEXT_BELOW,
                                   TAG_END);

    /* create a slider gadget */
    ng.ng_TopEdge = ng.ng_TopEdge + 55;
    ng.ng_GadgetText = "Right Justified";
    ng.ng_GadgetID = MYGAD_SLIDERRIGHT;
    slid3gad = gad = CreateGadget (SLIDER_KIND, gad, &ng,
                                   GTSL_MaxLevelLen, 6,
                                   GTSL_MaxPixelLen, 64,
                                   GTSL_Max, 512,
                                   GTSL_LevelFormat, "%lx",
                                   GTSL_Justification, GTJ_RIGHT,
                                   GTSL_LevelPlace, PLACETEXT_BELOW,
                                   TAG_END);

    /* Set these in case the listview cannot be created */
    ng.ng_LeftEdge = 240 + scr->WBorLeft;
    ng.ng_TopEdge = 30 + scr->WBorTop + (scr->Font->ta_YSize + 1);

    if (CreateDaList (BassSpaces))
    {
      /* create a listview gadget */
      ng.ng_LeftEdge = 240 + scr->WBorLeft;
      ng.ng_TopEdge = 30 + scr->WBorTop + (scr->Font->ta_YSize + 1);
      ng.ng_Width = 100;
      ng.ng_Height = 30 + gadfont->ta_YSize + 14;
      ng.ng_GadgetText = "Bass Spaces";
      ng.ng_GadgetID = MYGAD_LIST;
      listgad = gad = CreateGadget (LISTVIEW_KIND, gad, &ng,
                                    GTLV_ShowSelected, NULL,
                                    GTLV_Selected, 2,
                                    GTLV_MakeVisible, 2,
                                    GTLV_Labels, DaList,
                                    TAG_END);
    }

    /* create a checkbox gadget */
    ng.ng_LeftEdge = ng.ng_LeftEdge + 30;
    ng.ng_TopEdge = ng.ng_TopEdge + 130;
    ng.ng_Width = 50;
    ng.ng_Height = 30;
    ng.ng_GadgetText = "BigCheck";
    ng.ng_GadgetID = MYGAD_TEXT;
    ng.ng_Flags = PLACETEXT_ABOVE;
    checkgad = gad = CreateGadget (CHECKBOX_KIND, gad, &ng,
                                   GTCB_Scaled, TRUE, TAG_END);

    /* create a string gadget */
    ng.ng_LeftEdge = scr->Width - scr->WBorRight - 190;
    ng.ng_TopEdge = ng.ng_TopEdge - 130;
    ng.ng_Width = 150;
    ng.ng_Height = gadfont->ta_YSize + 14;
    ng.ng_GadgetText = "String Immediate";
    ng.ng_GadgetID = MYGAD_STRING;
    stringgad = gad = CreateGadget (STRING_KIND, gad, &ng,
                                    GA_Immediate, TRUE, TAG_END);

    /* create a text gadget */
    ng.ng_TopEdge = ng.ng_TopEdge + 55;
    ng.ng_Height = gadfont->ta_YSize + 2;
    ng.ng_GadgetText = "Echo After Click";
    ng.ng_GadgetID = MYGAD_TEXT;
    textgad = gad = CreateGadget (TEXT_KIND, gad, &ng,
                                  GTTX_Border, TRUE,
                                  GTTX_FrontPen, 3,
                                  GTTX_BackPen, 2,
                                  GTTX_Clipped, TRUE,
                                  TAG_END);

    /* create a palette gadget */
    ng.ng_TopEdge = ng.ng_TopEdge + 80;
    ng.ng_Width = 100;
    ng.ng_Height = 30;
    ng.ng_GadgetText = "Odd Colors";
    ng.ng_GadgetID = MYGAD_PAL;
    palgad = gad = CreateGadget (PALETTE_KIND, gad, &ng,
                                 GTPA_ColorTable, colors,
                                 GTPA_NumColors, 7,
                                 GTPA_Color, 2,
                                 GTPA_IndicatorWidth, 21,
                                 TAG_END);

    /* create an integer gadget */
    ng.ng_Width = 150;
    ng.ng_LeftEdge = scr->Width + scr->WBorRight - 190;
    ng.ng_TopEdge = scr->Height - 170;
    ng.ng_Height = gadfont->ta_YSize + 14;
    ng.ng_GadgetText = "Number, please";
    ng.ng_GadgetID = MYGAD_INT;
    intgad = gad = CreateGadget (INTEGER_KIND, gad, &ng,
                                 GTIN_MaxChars, 14,
                                 TAG_END);

    /* create a number gadget */
    ng.ng_TopEdge = ng.ng_TopEdge + 60;
    ng.ng_Width = 100;
    ng.ng_Height = gadfont->ta_YSize + 2;
    ng.ng_GadgetText = "Echo Number";
    ng.ng_GadgetID = MYGAD_NUM;
    numgad = gad = CreateGadget (NUMBER_KIND, gad, &ng,
                                 GTNM_FrontPen, 3,
                                 GTNM_Format, "%04ld",
                                 GTNM_Clipped, TRUE,
                                 GTNM_Number, 0xffff1,
                                 TAG_END);
  }
  else
    printf ("Could not create context\n");

  return (gad);
}

/*
 *  Create Menu.
 */

struct Menu *
CreateDaMenu (struct NewMenu *themenu, struct VisualInfo *vi)
{
  struct Menu *menusready;

  if (menusready = CreateMenus (themenu, TAG_END))
    LayoutMenus (menusready, vi, GTMN_NewLookMenus, TRUE, TAG_END);
  else
    printf ("Could not create menus\n");

  return (menusready);
}

/*
 *  Process menu events.
 */

BOOL
ProcessDaMenu (USHORT menunumber, struct Window * win, struct Menu * menustrip,
               struct VisualInfo * vi)
{
  USHORT menunum, itemnum, subnum;
  BOOL closeit = FALSE;
  menunum = MENUNUM (menunumber);
  itemnum = ITEMNUM (menunumber);
  subnum = SUBNUM (menunumber);

  switch (menunum)
  {
  case 0:                       /* project menu */
    closeit = TRUE;
    break;
  case 1:                       /* justify text menu */
    switch (itemnum)
    {
    case 0:                     /* left justify string */
      GT_SetGadgetAttrs (textgad, win, NULL,
                         GTTX_Justification, GTJ_LEFT,
                         GTTX_Text, "Left", TAG_END);
      break;
    case 2:                     /* center justify string */
      GT_SetGadgetAttrs (textgad, win, NULL,
                         GTTX_Justification, GTJ_CENTER,
                         GTTX_Text, "Center", TAG_END);
      break;
    case 4:                     /* right justify string */
      GT_SetGadgetAttrs (textgad, win, NULL,
                         GTTX_Justification, GTJ_RIGHT,
                         GTTX_Text, "Right", TAG_END);
    }
  }

  return (closeit);
}

/*
 *  Process IDCMP events
 *    Again, this is very incomplete.  You would do a lot more if this were a
 *    real application.
 */

void
ProcessEvents (struct Window *win, struct Menu *menustrip, struct VisualInfo *vi)
{
  struct IntuiMessage *msg;
  ULONG msgclass;
  LONG num;
  BOOL Closeflag = FALSE;
  STRPTR holdstring;
  USHORT menunumber;

  while (!Closeflag)
  {
    Wait (1 << win->UserPort->mp_SigBit);

    while ((!Closeflag) && (msg = GT_GetIMsg (win->UserPort)))
    {
      msgclass = msg->Class;

      switch (msgclass)
      {
      case IDCMP_CLOSEWINDOW:
        Closeflag = TRUE;
        break;

      case IDCMP_GADGETDOWN:
        if (msg->IAddress == stringgad)
        {
          holdstring = ((struct StringInfo *) (stringgad->SpecialInfo))->Buffer;
          GT_SetGadgetAttrs (textgad, win, NULL,
                             GTTX_Text, holdstring, TAG_END);
        }
        break;

      case IDCMP_GADGETUP:
        if (msg->IAddress == intgad)
        {
          num = ((struct StringInfo *) (intgad->SpecialInfo))->LongInt;
          GT_SetGadgetAttrs (numgad, win, NULL, GTNM_Number, num,
                             GTNM_Justification, GTJ_RIGHT, TAG_END);
        }
        break;

      case IDCMP_MENUPICK:
        menunumber = msg->Code;
        while (menunumber != MENUNULL && !Closeflag)
        {
          Closeflag = ProcessDaMenu (menunumber, win, menustrip, vi);
          menunumber = (ItemAddress (menustrip, menunumber))->NextSelect;
        }
      }
      GT_ReplyIMsg (msg);
    }
  }
}

/*
 *  Free the memory used for the listview.
 */

void
FreeDaMemory (void)
{
  struct Node *freenode, *nextnode;

  freenode = (struct Node *) DaList->lh_Head;
  while (nextnode = (struct Node *) freenode->ln_Succ)
  {
    FreeMem (freenode, sizeof (struct Node));
    freenode = nextnode;
  }
  FreeMem (DaList, sizeof (struct List));
}

/*
 *  main().
 *    With SAS 6.0, you don't have to open libraries, so we can get straight
 *    to work.
 */

void
main (void)
{
  struct Screen *Gadscreen;
  struct Window *Gadwindow;
  struct VisualInfo *vi;
  struct TextFont *Appfont;
  struct Menu *menuptr;

  /* use a font you like */
  struct TextAttr nicefont =
  {
    "diamond.font",             /*  STRPTR  ta_Name     name of the font */
    15,                         /*  UWORD   ta_YSize    height of the font */
    FS_NORMAL,                  /*  UBYTE   ta_Style    intrinsic font style */
    FPF_DISKFONT                /*  UBYTE   ta_Flags    font preferences and flags */
  };

  struct NewMenu Gadmenu[] =
  {
    {NM_TITLE, "Project", 0, 0, 0, 0,},
    {NM_ITEM, "Quit", "Q", 0, 0, 0,},

    {NM_TITLE, "Justify Text", 0, 0, 0, 0,},
    {NM_ITEM, "Left", "L", 0, 0, 0,},
    {NM_ITEM, NM_BARLABEL, 0, 0, 0, 0,},
    {NM_ITEM, "Center", "M", 0, 0, 0,},
    {NM_ITEM, NM_BARLABEL, 0, 0, 0, 0,},
    {NM_ITEM, "Right", "R", 0, 0, 0,},
    {NM_END, NULL, 0, 0, 0, 0,},
  };

  if (Appfont = OpenDiskFont (&nicefont))
  {
    if (Gadscreen = OpenScreenTags (NULL,
                                    SA_Left, 0,
                                    SA_Top, 0,
                                    SA_LikeWorkbench, TRUE,
                                    SA_Font, &nicefont,
                                    SA_Title, "Some New GadTools Features",
                                    TAG_DONE))
    {
      if ((vi = GetVisualInfo (Gadscreen, TAG_END)) != NULL)
      {
        if (CreateGads (Gadscreen, vi, &nicefont) != NULL)
        {
          if (menuptr = CreateDaMenu (Gadmenu, vi))
          {
            if (Gadwindow = OpenWindowTags (NULL,
                                            WA_Left, Gadscreen->LeftEdge,
                                    WA_Top, Gadscreen->TopEdge + Gadscreen->BarHeight,
                                  WA_Height, Gadscreen->Height - Gadscreen->BarHeight,
                                            WA_Width, Gadscreen->Width,
                                WA_MinWidth, Gadscreen->Height - Gadscreen->BarHeight,
                                            WA_MinHeight, Gadscreen->Width,
                                            WA_Gadgets, glist,
                                            WA_Title, "Lots of Gadgets",
                                            WA_CustomScreen, Gadscreen,
                                    WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_ACTIVEWINDOW |
                                            IDCMP_GADGETDOWN | IDCMP_MENUPICK |
                                      IDCMP_GADGETHELP | IDCMP_GADGETUP | SLIDERIDCMP,
                                       WA_Flags, WFLG_DEPTHGADGET | WFLG_CLOSEGADGET |
                                            WFLG_ACTIVATE,
                                            WA_NewLookMenus, TRUE,
                                            WA_DragBar, TRUE,
                                            WA_CloseGadget, TRUE,
                                            TAG_DONE))
            {
              if (SetMenuStrip (Gadwindow, menuptr))
              {
                GT_RefreshWindow (Gadwindow, NULL);

                ProcessEvents (Gadwindow, menuptr, vi);

                ClearMenuStrip (Gadwindow);

                FreeMenus (menuptr);

                CloseWindow (Gadwindow);
              }
            }
          }
        }
        else
          printf ("Could not create gadgets\n");

        if (DaList)
          FreeDaMemory ();

        FreeGadgets (glist);

        FreeVisualInfo (vi);
      }

      else
        printf ("Could not get visual info\n");

      CloseScreen (Gadscreen);
    }
    else
      printf ("Could not open screen\n");

    CloseFont (Appfont);
  }
  else
    printf ("Could not open %s\n", nicefont.ta_Name);
}


V-1/genlockdemo.c

;/* genlockdemo.c - Amiga Mail Jan/Feb '91 Genlock VideoControl example.
sc DATA=NEAR NMINC STRMERGE STREQ NOSTKCHK IGNORE=73 genlockdemo.c
slink FROM LIB:c.o,genlockdemo.o TO genlockdemo LIBRARY LIB:sc.lib,LIB:amiga.lib
quit
*/
/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <exec/types.h>
#include <exec/memory.h>
#include <graphics/gfxbase.h>
#include <graphics/displayinfo.h>
#include <graphics/VideoControl.h>
#include <graphics/view.h>
#include <intuition/intuition.h>
#include <intuition/screens.h>
#include <libraries/gadtools.h>

#include <clib/alib_stdio_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/exec_protos.h>
#include <clib/gadtools_protos.h>

/* Some gadget ID's */
#define BORDERBLANK_ID          16
#define BORDERNOTRANS_ID        17
#define BITPLANEKEY_ID          18
#define CHROMAPLANE_ID          19
#define CHROMAKEY_ID            20

/* Some protos */
VOID main(VOID);
BOOL CheckPAL(STRPTR);
UWORD strlen(STRPTR);

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Library *GadToolsBase;

/* Give me 3D look window (I'll use a quiet screen */
static UWORD dri_Pens[] =
{0, 1, 1, 2, 1, 3, 1, 0, 3, ~0};

/* Just a demo, set everything to topaz 80. */
static struct TextAttr Topaz80 = {"topaz.font", 8, 0, 0,};

/* strings for cycle gadget */
static STRPTR ChPlaneText[] = {"Plane 0", "Plane 1", "Plane 2", "Plane 3", NULL};

struct EasyStruct failedES = {sizeof(struct EasyStruct), 0, "GenlockDemo", "%s", "Continue",};

VOID main(VOID)
{
        struct Screen *genscreen;
        struct Window *controlwindow;
        struct Gadget *glist, *gadget, *hitgadget;
        struct ViewPort *vp;
        void *vi;
        struct NewGadget ng;
        struct IntuiMessage *imsg;
        struct TagItem vtags[24];
        ULONG GadgetPtrs[21];
        ULONG iclass, icode;
        STRPTR gtextbuffer, gtextptr;
        UWORD i, j;
        BOOL ABORT = FALSE;
        BOOL IsPAL;
        /* Fails silently if < V37 */
        if (IntuitionBase = OpenLibrary("intuition.library", 37))
        {
                if (GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 37))
                {
                        if (GadToolsBase = OpenLibrary("gadtools.library", 37))
                        {
                                if (GfxBase->ChipRevBits0 & GFXF_HR_DENISE)
                                {
                                        /* Check if the user happens to prefer PAL or if this is a true PAL System. */
                                        IsPAL = CheckPAL("Workbench");
                                        /* buffer for some gadget text */
                                        if (gtextbuffer = AllocMem(256, MEMF_CLEAR))
                                        {
                                                gtextptr = gtextbuffer;

                                                /* Open a 'standard' HIRES screen */
                                                if (genscreen = OpenScreenTags(NULL, SA_Pens, (ULONG) dri_Pens,
                                                SA_DisplayID, HIRES_KEY,
                                                SA_Depth, 4,
                                                /* Give me a lot of border */
                                                SA_Width, 640,
                                                SA_Height, (IsPAL) ? 256 : 200,
                                                SA_Overscan, 0,
                                                /* Hold the titlebar, please */
                                                SA_Quiet, TRUE,
                                                /* Give me sysfont 0 as default rastport font. */
                                                SA_SysFont, 1,
                                                TAG_DONE))
                                                {

                                                        /* Blast some colorbars in screen's rastport, leave some color 0 gaps */
                                                        for (i = 0, j = 0; i < 16; i++, j += 40)
                                                        {
                                                                SetAPen(&(genscreen->RastPort), i);
                                                                RectFill(&(genscreen->RastPort), (j + 1), 0, (j + 30), (IsPAL) ? 255 : 199);

                                                        }
                                                        /* A line to show where borders start */
                                                        SetAPen(&(genscreen->RastPort), 5);
                                                        Move(&(genscreen->RastPort),0,0);
                                                        Draw(&(genscreen->RastPort),genscreen->Width-1,0);
                                                        Draw(&(genscreen->RastPort),genscreen->Width-1,genscreen->Height-1);
                                                        Draw(&(genscreen->RastPort),0,genscreen->Height-1);
                                                        Draw(&(genscreen->RastPort),0,0);

                                                        /* Open a restricted window, no draggin, sizing, just closing.
                                                         * (don't want to refresh screen)
                                                         */
                                                        if (controlwindow = OpenWindowTags(NULL, WA_Title, (ULONG) "VideoControl",
                                                        WA_Left, 210,
                                                        WA_Top, 20,
                                                        WA_Width, 220,
                                                        WA_Height, 150,
                                                        WA_CustomScreen, genscreen,
                                                        WA_Flags, WFLG_CLOSEGADGET | WFLG_ACTIVATE | WFLG_NOCAREREFRESH,
                                                        WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_GADGETUP,
                                                        TAG_DONE))
                                                        {

                                                                /* Ok, got a window, lets make some gadgets */
                                                                if (vi = GetVisualInfo(genscreen, TAG_END))
                                                                {
                                                                        if (gadget = CreateContext(&glist))
                                                                        {
                                                                                ng.ng_TextAttr = &Topaz80;
                                                                                ng.ng_VisualInfo = vi;
                                                                                ng.ng_Flags = PLACETEXT_LEFT | NG_HIGHLABEL;

                                                                                ng.ng_LeftEdge = controlwindow->BorderLeft + 120;
                                                                                ng.ng_TopEdge = controlwindow->BorderTop + 2;
                                                                                ng.ng_Width = 12;
                                                                                ng.ng_Height = 12;
                                                                                ng.ng_GadgetText = "BORDERBLANK";
                                                                                ng.ng_GadgetID = BORDERBLANK_ID;
                                                                                gadget = CreateGadget(CHECKBOX_KIND, gadget, &ng, TAG_END);
                                                                                GadgetPtrs[BORDERBLANK_ID] = (ULONG) gadget;

                                                                                ng.ng_TopEdge += gadget->Height + 2;
                                                                                ng.ng_GadgetText = "BORDERNOTRANS";
                                                                                ng.ng_GadgetID = BORDERNOTRANS_ID;
                                                                                gadget = CreateGadget(CHECKBOX_KIND, gadget, &ng, TAG_END);
                                                                                GadgetPtrs[BORDERNOTRANS_ID] = (ULONG) gadget;

                                                                                ng.ng_TopEdge += gadget->Height + 2;
                                                                                ng.ng_GadgetText = "CHROMAKEY";
                                                                                ng.ng_GadgetID = CHROMAKEY_ID;
                                                                                gadget = CreateGadget(CHECKBOX_KIND, gadget, &ng, TAG_END);
                                                                                GadgetPtrs[CHROMAKEY_ID] = (ULONG) gadget;

                                                                                ng.ng_TopEdge += gadget->Height + 2;
                                                                                ng.ng_GadgetText = "BITPLANEKEY";
                                                                                ng.ng_GadgetID = BITPLANEKEY_ID;
                                                                                gadget = CreateGadget(CHECKBOX_KIND, gadget, &ng, TAG_END);
                                                                                GadgetPtrs[BITPLANEKEY_ID] = (ULONG) gadget;

                                                                                ng.ng_TopEdge += gadget->Height + 2;
                                                                                ng.ng_Width = 90;
                                                                                ng.ng_GadgetText = "CHROMAPLANE";
                                                                                ng.ng_GadgetID = CHROMAPLANE_ID;
                                                                                gadget = CreateGadget(CYCLE_KIND, gadget, &ng, GTCY_Labels, (ULONG) ChPlaneText,
                                                                                TAG_END);
                                                                                GadgetPtrs[CHROMAPLANE_ID] = (ULONG) gadget;

                                                                                ng.ng_TopEdge += gadget->Height + 20;
                                                                                ng.ng_Width = 12;
                                                                                ng.ng_Flags = PLACETEXT_ABOVE | NG_HIGHLABEL;
                                                                                for (j = 0; j < 2; j++)
                                                                                {
                                                                                for (i = 0; i < 8; i++)
                                                                                {
                                                                                ng.ng_LeftEdge = controlwindow->BorderLeft + 2 + (i * gadget->Width);
                                                                                sprintf(gtextptr, "%ld", i + (j * 8));
                                                                                ng.ng_GadgetText = gtextptr;
                                                                                ng.ng_GadgetID = i + (j * 8);
                                                                                gadget = CreateGadget(CHECKBOX_KIND, gadget, &ng, TAG_END);
                                                                                GadgetPtrs[i] = (ULONG) gadget;
                                                                                gtextptr += strlen(gtextptr) + 1;
                                                                                }
                                                                                ng.ng_TopEdge += gadget->Height;
                                                                                ng.ng_Flags = PLACETEXT_BELOW | NG_HIGHLABEL;
                                                                                }
                                                                                AddGList(controlwindow, glist, -1, -1, NULL);
                                                                                RefreshGList(glist, controlwindow, NULL, -1);
                                                                                GT_RefreshWindow(controlwindow, NULL);

                                                                                /* Finally, a window with some gadgets...
                                                                                *
                                                                                * Get the current genlock state.
                                                                                * Obviously I already know what the settings will be (all off),
                                                                                * since I opened the screen myself. Do it just to show how to get them.
                                                                                */

                                                                                vp = &(genscreen->ViewPort);

                                                                                /* Is borderblanking on? */
                                                                                vtags[0].ti_Tag = VTAG_BORDERBLANK_GET;
                                                                                vtags[0].ti_Data = NULL;
                                                                                /* Is bordertransparent set */
                                                                                vtags[1].ti_Tag = VTAG_BORDERNOTRANS_GET;
                                                                                vtags[1].ti_Data = NULL;
                                                                                /* Key on bitplane? */
                                                                                vtags[2].ti_Tag = VTAG_BITPLANEKEY_GET;
                                                                                vtags[2].ti_Tag = NULL;
                                                                                /* Get plane which is used to key on */
                                                                                vtags[3].ti_Tag = VTAG_CHROMA_PLANE_GET;
                                                                                vtags[3].ti_Data = NULL;
                                                                                /* Chromakey overlay on? */
                                                                                vtags[4].ti_Tag = VTAG_CHROMAKEY_GET;
                                                                                vtags[4].ti_Data = NULL;

                                                                                for (i = 0; i < 16; i++)
                                                                                {
                                                                                /* Find out which colors overlay */
                                                                                vtags[i + 5].ti_Tag = VTAG_CHROMA_PEN_GET;
                                                                                vtags[i + 5].ti_Data = i;
                                                                                }

                                                                                /* Indicate end of tag array */
                                                                                vtags[21].ti_Tag = VTAG_END_CM;
                                                                                vtags[21].ti_Data = NULL;

                                                                                /* And send the commands. On return the Tags themself will
                                                                                * indicate the genlock settings for this ViewPort's ColorMap.
                                                                                */
                                                                                VideoControl(vp->ColorMap, vtags);

                                                                                /* And initialize gadgets, according to genlock settings */
                                                                                if (vtags[0].ti_Tag == VTAG_BORDERBLANK_SET)
                                                                                GT_SetGadgetAttrs((struct Gadget *) GadgetPtrs[BORDERBLANK_ID],
                                                                                controlwindow, NULL, GTCB_Checked, TRUE, TAG_DONE);
                                                                                if (vtags[1].ti_Tag == VTAG_BORDERNOTRANS_SET)
                                                                                GT_SetGadgetAttrs((struct Gadget *) GadgetPtrs[BORDERNOTRANS_ID],
                                                                                controlwindow, NULL, GTCB_Checked, TRUE, TAG_DONE);
                                                                                if (vtags[2].ti_Tag == VTAG_BITPLANEKEY_SET)
                                                                                GT_SetGadgetAttrs((struct Gadget *) GadgetPtrs[BITPLANEKEY_ID],
                                                                                controlwindow, NULL, GTCB_Checked, TRUE, TAG_DONE);
                                                                                if (vtags[3].ti_Tag == VTAG_CHROMA_PLANE_SET)
                                                                                GT_SetGadgetAttrs((struct Gadget *) GadgetPtrs[CHROMAPLANE_ID],
                                                                                controlwindow, NULL, GTCY_Active, vtags[3].ti_Data,
                                                                                TAG_DONE);
                                                                                if (vtags[4].ti_Tag == VTAG_CHROMAKEY_SET)
                                                                                GT_SetGadgetAttrs((struct Gadget *) GadgetPtrs[CHROMAKEY_ID],
                                                                                controlwindow, NULL, GTCB_Checked, TRUE, TAG_DONE);
                                                                                for (i = 0; i < 16; i++)
                                                                                {
                                                                                if (vtags[i + 5].ti_Tag == VTAG_CHROMA_PEN_SET)
                                                                                GT_SetGadgetAttrs((struct Gadget *) GadgetPtrs[i],
                                                                                controlwindow, NULL, GTCB_Checked, TRUE);
                                                                                }

                                                                                /* Will only send single commands from here on. */
                                                                                vtags[1].ti_Tag = VTAG_END_CM;

                                                                                /* Get user input. */
                                                                                do
                                                                                {
                                                                                WaitPort(controlwindow->UserPort);
                                                                                while (imsg = GT_GetIMsg(controlwindow->UserPort)) {
                                                                                iclass = imsg->Class;
                                                                                icode = imsg->Code;
                                                                                hitgadget = (struct Gadget *) imsg->IAddress;
                                                                                GT_ReplyIMsg(imsg);

                                                                                switch (iclass)
                                                                                {
                                                                                case GADGETUP:
                                                                                if (hitgadget->GadgetID < 16)
                                                                                {
                                                                                /* Set colorkey */
                                                                                if (hitgadget->Flags & SELECTED)
                                                                                vtags[0].ti_Tag = VTAG_CHROMA_PEN_SET;
                                                                                /* Clear colorkey */
                                                                                else
                                                                                vtags[0].ti_Tag = VTAG_CHROMA_PEN_CLR;
                                                                                vtags[0].ti_Data = hitgadget->GadgetID;
                                                                                }
                                                                                else
                                                                                {
                                                                                switch (hitgadget->GadgetID) {
                                                                                case BORDERBLANK_ID:
                                                                                /* Set borderblanking on */
                                                                                if (hitgadget->Flags & SELECTED)
                                                                                vtags[0].ti_Tag =
                                                                                VTAG_BORDERBLANK_SET;
                                                                                /* Turn borderblanking off */
                                                                                else
                                                                                vtags[0].ti_Tag =
                                                                                VTAG_BORDERBLANK_CLR;
                                                                                break;
                                                                                case BORDERNOTRANS_ID:
                                                                                /* Set bordertransparency on */
                                                                                if (hitgadget->Flags & SELECTED)
                                                                                vtags[0].ti_Tag =
                                                                                VTAG_BORDERNOTRANS_SET;
                                                                                /* Turn bordertransparency off */
                                                                                else
                                                                                vtags[0].ti_Tag =
                                                                                VTAG_BORDERNOTRANS_CLR;
                                                                                break;
                                                                                case BITPLANEKEY_ID:
                                                                                /* Key on current selected bitplane
                                                                                * (chromaplane) */
                                                                                if (hitgadget->Flags & SELECTED)
                                                                                vtags[0].ti_Tag =
                                                                                VTAG_BITPLANEKEY_SET;
                                                                                /* Turn bitplane keying off */
                                                                                else
                                                                                vtags[0].ti_Tag =
                                                                                VTAG_BITPLANEKEY_CLR;
                                                                                break;
                                                                                case CHROMAPLANE_ID:
                                                                                /* Set plane to key on */
                                                                                vtags[0].ti_Tag = VTAG_CHROMA_PLANE_SET;
                                                                                vtags[0].ti_Data = icode;
                                                                                break;
                                                                                case CHROMAKEY_ID:
                                                                                /* Set chromakey overlay on */
                                                                                if (hitgadget->Flags & SELECTED)
                                                                                vtags[0].ti_Tag = VTAG_CHROMAKEY_SET;
                                                                                /* Turn chromakey overlay off */
                                                                                else
                                                                                vtags[0].ti_Tag = VTAG_CHROMAKEY_CLR;
                                                                                break;
                                                                                }
                                                                                }

                                                                                /* send video command */
                                                                                VideoControl(vp->ColorMap, vtags);
                                                                                /* Now use MakeScreen() and RethinkDisplay()
                                                                                * to make the VideoControl changes
                                                                                * take effect.  If we were using our own
                                                                                * Viewport rather than borrowing one from
                                                                                * a screen, we would instead do:
                                                                                *   MakeVPort(ViewAddress(),vp);
                                                                                *   MrgCop(ViewAddress());
                                                                                *   LoadView(ViewAddres());
                                                                                */
                                                                                MakeScreen(genscreen);
                                                                                RethinkDisplay();
                                                                                break;

                                                                                case CLOSEWINDOW:
                                                                                /* Get out of here */
                                                                                ABORT = TRUE;
                                                                                break;
                                                                                }
                                                                                }
                                                                                }
                                                                                while (ABORT == FALSE);

                                                                                RemoveGList(controlwindow, glist, -1);
                                                                                FreeGadgets(glist);
                                                                        }
                                                                        else
                                                                                EasyRequest(NULL, &failedES, NULL, "Can't create gadget context");
                                                                        FreeVisualInfo(vi);
                                                                }
                                                                else
                                                                        EasyRequest(NULL, &failedES, NULL, "Can't get visual info");
                                                                CloseWindow(controlwindow);
                                                        }
                                                        else
                                                                EasyRequest(NULL, &failedES, NULL, "Can't open window");
                                                        CloseScreen(genscreen);
                                                }
                                                else
                                                        EasyRequest(NULL, &failedES, NULL, "Can't open screen");
                                                FreeMem(gtextbuffer, 256);
                                        }
                                        else
                                                EasyRequest(NULL, &failedES, NULL, "Out of memory");
                                }
                                else
                                        EasyRequest(NULL, &failedES, NULL, "Requires ECS");
                                CloseLibrary(GadToolsBase);
                        }
                        CloseLibrary((struct Library *) GfxBase);
                }
                CloseLibrary(IntuitionBase);
        }
}

BOOL CheckPAL(STRPTR screenname)
{
        struct Screen *screen;
        ULONG modeID = LORES_KEY;
        struct DisplayInfo displayinfo;
        BOOL IsPAL;

        if (GfxBase->LibNode.lib_Version >= 36)
        {
        /*
         * We got V36, so lets use the new calls to find out what
         * kind of videomode the user (hopefully) prefers.
         */

                if (screen = LockPubScreen(screenname))
                {
                        /*
                         * Use graphics.library/GetVPModeID() to get the ModeID of the specified screen.
                         * Will use the default public screen (Workbench most of the time) if NULL It is
                         * _very_ unlikely that this would be invalid, heck it's impossible.
                         */
                        if ((modeID = GetVPModeID(&(screen->ViewPort))) != INVALID_ID)
                        {
                                /*
                                 * If the screen is in VGA mode, we can't tell whether the system is PAL or NTSC. So
                                 * to be fullproof we fall back to the displayinfo of the default.monitor by
                                 * inquiring about just the LORES_KEY displaymode if we don't know. The
                                 * default.monitor reflects the initial video setup of the system, thus is an alias
                                 * for either ntsc.monitor or pal.monitor. We only use the displaymode of the
                                 * specified public screen if it's display mode is PAL or NTSC and NOT the default.
                                 */

                                if (!((modeID & MONITOR_ID_MASK) == NTSC_MONITOR_ID ||
                                      (modeID & MONITOR_ID_MASK) == PAL_MONITOR_ID))
                                        modeID = LORES_KEY;
                        }
                        UnlockPubScreen(NULL, screen);
                } /* if fails modeID = LORES_KEY. Can't lock screen, so fall back on default monitor. */

                if (GetDisplayInfoData(NULL, (UBYTE *) & displayinfo,
                    sizeof(struct DisplayInfo), DTAG_DISP, modeID))
                {
                        if (displayinfo.PropertyFlags & DIPF_IS_PAL)
                            IsPAL = TRUE;
                        else
                            IsPAL = FALSE;  /* Currently the default monitor is always either
                                             * PAL or NTSC.
                                             */
                }
        }
        else /* < V36. The enhancements to the videosystem in V36 cannot be better expressed than
                * with the simple way to determine PAL in V34.
                */
                IsPAL= (GfxBase->DisplayFlags & PAL) ? TRUE : FALSE;

        return(IsPAL);
}


V-11/getaspect.c

;/* getaspect.c - Execute me to compile me with SAS/C 6.56
sc DATA=NEAR NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 getaspect.c
slink FROM LIB:c.o,getaspect.o TO getaspect LIBRARY LIB:sc.lib,LIB:amiga.lib
quit

Gets X/Y pixel aspect of a screen's ViewPort
*/
/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <exec/types.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <graphics/displayinfo.h>
#include <graphics/gfxbase.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

#define MINARGS 1

UBYTE *vers = "\0$VER: getaspect 37.1";
UBYTE *Copyright =
  "getaspect v37.1\nCopyright (c) 1990-1999 Amiga, Inc.  All Rights Reserved";
UBYTE *usage = "Usage: getaspect";

void bye(UBYTE *s, int e);
void cleanup(void);

struct Library *IntuitionBase;
struct Library *GfxBase;

void main(int argc, char **argv)
    {
    struct Screen *first;
    struct ViewPort *vp;
    struct DisplayInfo DI;
    ULONG  modeid;
    UBYTE  xAspect, yAspect;

    if(((argc)&&(argc<MINARGS))||(argv[argc-1][0]=='?'))
    {
    printf("%s\n%s\n",Copyright,usage);
    bye("",RETURN_OK);
    }

    /* We will check later to see if we can call V36 functions */
    IntuitionBase = OpenLibrary("intuition.library",34);
    GfxBase = OpenLibrary("graphics.library",34);
    if((!IntuitionBase)||(!GfxBase))
    bye("Can't open intuition or graphics library",RETURN_FAIL);

    printf("Using front screen's ViewPort (for example purposes only):\n");

    first = ((struct IntuitionBase *)IntuitionBase)->FirstScreen;
    vp = &first->ViewPort;

    xAspect = 0;    /* So we can tell when we've got it */

    if(GfxBase->lib_Version >= 36)
    {
        modeid = GetVPModeID(vp);

        if(GetDisplayInfoData(NULL, (UBYTE *)&DI, sizeof(struct DisplayInfo),
        DTAG_DISP, modeid))
        {
        printf("Running 2.0,  ViewPort modeid is $%08lx\n",modeid);
        xAspect = DI.Resolution.x;
        yAspect = DI.Resolution.y;
        printf("Pixel  xAspect=%ld  yAspect=%ld\n",xAspect, yAspect);
        printf("PaletteRange is %ld\n",DI.PaletteRange);
        }
    }

    if(!xAspect)  /* pre-2.0 or GetDisplayInfoData failed */
    {
    modeid = vp->Modes;
    printf("Not running 2.0, ViewPort mode is $%04lx\n",modeid);
        /* default lores pixel ratio */
        xAspect = 44;
        yAspect = ((struct GfxBase *)GfxBase)->DisplayFlags & PAL  ? 44 : 52;
        if(modeid & HIRES)      xAspect = xAspect >> 1;
        if(modeid & LACE)       yAspect = yAspect >> 1;
    printf("Pixel  xAspect=%ld  yAspect=%ld\n",xAspect, yAspect);
        }

    bye("",RETURN_OK);
    }

void bye(UBYTE *s, int e)
    {
    cleanup();
    exit(e);
    }

void cleanup()
    {
    if(GfxBase) CloseLibrary(GfxBase);
    if(IntuitionBase)   CloseLibrary(IntuitionBase);
    }


V-15/FTA.c

;/* FTA.c - Execute me to compile me with SAS/C 6.56
sc NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 FTA.c
slink FROM LIB:c.o,FTA.o TO FTA LIBRARY LIB:sc.lib,LIB:amiga.lib
quit

Sept. 17 1991 by John Orr

Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <exec/types.h>
#include <intuition/intuition.h>
#include <graphics/text.h>
#include <graphics/gfx.h>
#include <libraries/diskfont.h>
#include <utility/tagitem.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/alib_stdio_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/diskfont_protos.h>
#include <clib/utility_protos.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }
#endif

#define MYXDPI (75L << 16)
#define MYYDPI (50L)

struct TTextAttr mytta = {
    "topaz.font",
    9,
    FSF_TAGGED,
    0L,
    NULL
};

struct TagItem tagitem[2];
struct TextFont *myfont;
ULONG dpivalue;

struct Library *UtilityBase, *DiskfontBase, *GfxBase;

void main(void)
{
    tagitem[0].ti_Tag = TA_DeviceDPI;
    tagitem[0].ti_Data = MYXDPI | MYYDPI;
    tagitem[1].ti_Tag = TAG_END;

    if (DiskfontBase = OpenLibrary("diskfont.library", 36L))
    {
        if (UtilityBase = OpenLibrary("utility.library", 36L))
        {
            if (GfxBase = OpenLibrary("graphics.library", 36L))
            {
                if (myfont = OpenDiskFont(&mytta))
                {
                    dpivalue = GetTagData(TA_DeviceDPI,
                                     0L,
                                     ((struct TextFontExtension *)(myfont->tf_Extension))->tfe_Tags);
                    if (dpivalue) printf("XDPI = %d    YDPI = %d\n",
                                    ((dpivalue & 0xFFFF0000)>>16),
                                    (dpivalue & 0x0000FFFF));
                    CloseFont(myfont);
                }
                CloseLibrary(GfxBase);
            }
            CloseLibrary(UtilityBase);
        }
        CloseLibrary(DiskfontBase);
    }
}


V-15/cliptext.c

;/* cliptext.c - Execute me to compile me with SAS/C 6.56
sc NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 cliptext.c
slink FROM LIB:c.o,cliptext.o TO cliptext LIBRARY LIB:sc.lib,LIB:amiga.lib
quit ;

Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/
#include <exec/types.h>
#include <dos/rdargs.h>
#include <dos/dosextens.h>
#include <intuition/intuition.h>
#include <graphics/text.h>
#include <graphics/displayinfo.h>
#include <graphics/regions.h>
#include <graphics/gfx.h>
#include <libraries/diskfont.h>
#include <libraries/diskfonttag.h>
#include <utility/tagitem.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/layers_protos.h>
#include <clib/alib_stdio_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/diskfont_protos.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }
#endif

UBYTE *vers = "\0$VER: cliptext 37.2";

#define BUFSIZE          4096
#define FONT_NAME        0
#define FONT_SIZE        1
#define FILE_NAME        2
#define JAM_MODE         3
#define XASP             4
#define YASP             5
#define NUM_ARGS         6
#define DEFAULTFONTSIZE  11L
#define DEFAULTJAMMODE   0L
#define DEFAULTXASP      0L
#define DEFAULTYASP      0L

void MainLoop(void);

LONG args[NUM_ARGS];
struct TagItem tagitem[2];
UBYTE buffer[BUFSIZE];
BPTR myfile;
struct Library *DiskfontBase, *IntuitionBase, *LayersBase, *GfxBase;
struct IntuiMessage *mymsg;
struct DrawInfo *mydrawinfo;
struct Window *mywin;
struct RastPort *myrp;
struct TTextAttr myta;
struct TextFont *myfont;
struct Rectangle myrectangle;
struct Region *new_region;

void main(int argc, char **argv)
{
  struct RDArgs *myrda;
  struct DisplayInfo mydi;
  ULONG mymodeid;

  LONG mydefaultfontsize = DEFAULTFONTSIZE;
  LONG mydefaultJAMMode = DEFAULTJAMMODE;
  LONG mydefaultXASP = 0L;
  LONG mydefaultYASP = 0L;
  args[FONT_NAME] = (LONG)"topaz.font";
  args[FONT_SIZE] = (LONG)&mydefaultfontsize;
  args[FILE_NAME] = (LONG)"s:startup-sequence";
  args[JAM_MODE]  = (LONG)&mydefaultJAMMode;
  args[XASP]      = (LONG)&mydefaultXASP;
  args[YASP]      = (LONG)&mydefaultYASP;

  /* dos.library standard command line parsing--See the dos.library Autodoc for details */
  if (myrda = ReadArgs("FontName,FontSize/N,FileName,Jam/N,XASP/N,YASP/N\n", args, NULL))
  {
    if (myfile = Open((UBYTE *)args[FILE_NAME], MODE_OLDFILE) )   /* Open the file to display. */
    {
      if (DiskfontBase = OpenLibrary("diskfont.library", 37L))          /* Open the libraries. */
      {
        if (IntuitionBase = OpenLibrary("intuition.library", 37L))
        {
          if (GfxBase = OpenLibrary("graphics.library", 37L))
          {
            if (LayersBase = OpenLibrary("layers.library", 37L))
            {
              if (mywin = OpenWindowTags(NULL,                            /* Open that window. */
                     WA_MinWidth,     100,     /* This application wants to hear about three   */
                     WA_MinHeight,    100,     /* things: 1) When the user clicks the window's */
                     WA_SmartRefresh, TRUE,    /* close gadget, 2) when the user starts to     */
                     WA_SizeGadget,   TRUE,    /* resize the window, 3) and when the user has  */
                     WA_CloseGadget,  TRUE,    /* finished resizing the window.                */
                     WA_IDCMP,       IDCMP_CLOSEWINDOW | IDCMP_NEWSIZE | IDCMP_SIZEVERIFY,
                     WA_DragBar,     TRUE,
                     WA_DepthGadget, TRUE,
                     WA_Title,       (ULONG)args[FILE_NAME],
                     TAG_END))
              {
                tagitem[0].ti_Tag = OT_DeviceDPI;

                /* See if there is a non-zero value in the XASP or YASP fields. Diskfont.library */
                /* will get a divide by zero GURU if you give it a zero XDPI or YDPI value.      */

                /* if there is a zero value in one of them... */
                if (  ( (*(ULONG *)args[XASP]) == 0) || ( (*(ULONG *)args[YASP]) == 0)  )
                {
                  /* ...then use the aspect ratio of the current display as a default... */
                  mymodeid = GetVPModeID(&(mywin->WScreen->ViewPort));
                  if (GetDisplayInfoData( NULL, (UBYTE *)&mydi,
                                          sizeof(struct DisplayInfo), DTAG_DISP, mymodeid))
                  {
                    mydefaultXASP = mydi.Resolution.x;
                    mydefaultYASP = mydi.Resolution.y;
                    printf("XAsp = %ld    YAsp = %ld\n", mydefaultXASP, mydefaultYASP);
                    /* Notice that the X and Y get _swapped_ to keep the look of the    */
                    /* font glyphs the same using screens with different aspect ratios. */
                    args[YASP]    = (LONG)&mydefaultXASP;
                    args[XASP]    = (LONG)&mydefaultYASP;
                  }
                  else /* ...unless something is preventing us from getting the screen  */
                       /* screens resolution.  In that case, forget about the DPI tag.  */
                       tagitem[0].ti_Tag = TAG_END;
                }
                /* Here we have to put the X and Y DPI into the OT_DeviceDPI tags data field.  */
                /* THESE ARE NOT REAL X AND Y DPI VALUES FOR THIS FONT OR DISPLAY. They only   */
                /* serve to supply the diskfont.library with values to calculate the aspect    */
                /* ratio.  The X value gets stored in the upper word of the tag value and the Y*/
                /* DPI gets stored in the lower word.  Because ReadArgs() stores the _address_ */
                /* of integers it gets from the command line, you have to dereference the      */
                /* pointer it puts into the argument array, which results in some ugly casting.*/

                tagitem[0].ti_Data = (ULONG)( ( (UWORD) *( (ULONG *)args[XASP] ) << 16) |
                                               ((UWORD) *( (ULONG *)args[YASP]) ) );
                tagitem[1].ti_Tag = TAG_END;

                myta.tta_Name = (STRPTR)args[FONT_NAME];           /* Set up the TTextAttr     */
                myta.tta_YSize = *((LONG *)args[FONT_SIZE]);       /* structure to match the   */
                myta.tta_Style = FSF_TAGGED;                       /* font the user requested. */
                myta.tta_Flags = 0L;
                myta.tta_Tags = tagitem;

                if (myfont = OpenDiskFont(&myta))       /* open that font */
                {
                 /* This is for the layers.library clipping region that gets attached to the   */
                 /* window.  This prevents the application from unnecessarily rendering beyond */
                  myrectangle.MinX = mywin->BorderLeft; /* the bounds of the inner part of     */
                  myrectangle.MinY = mywin->BorderTop;  /* the window.  For now, you can       */
                  myrectangle.MaxX = mywin->Width -     /* ignore the layers stuff if you are  */
                      (mywin->BorderRight + 1);         /* just interested in learning about   */
                  myrectangle.MaxY = mywin->Height -    /* using text.  For more information   */
                      (mywin->BorderBottom + 1);        /* on clipping regions and layers, see */
                                                        /* the Layers chapter of this manual.  */

                  if (new_region = NewRegion())                           /* more layers stuff */
                  {
                    if (OrRectRegion(new_region, &myrectangle));     /* Even more layers stuff */
                    {
                      InstallClipRegion(mywin->WLayer, new_region);
                      /* Obtain a pointer to the window's rastport and set up some of the      */
                      myrp = mywin->RPort;    /* rastport attributes. This example obtains the */
                      SetFont(myrp, myfont);  /* text pen for the window's screen using        */
                      if (mydrawinfo =GetScreenDrawInfo(mywin->WScreen)) /* GetScreenDrawInfo()*/
                      {
                        SetAPen(myrp, mydrawinfo->dri_Pens[TEXTPEN]);
                        FreeScreenDrawInfo(mywin->WScreen, mydrawinfo);
                      }
                      SetDrMd(myrp, (BYTE)(*((LONG *)args[JAM_MODE])));

                      MainLoop();
                    }
                    DisposeRegion(new_region);
                  }
                  CloseFont(myfont);
                }
                CloseWindow(mywin);
              }
              CloseLibrary(LayersBase);
            }
            CloseLibrary(GfxBase);
          }
          CloseLibrary(IntuitionBase);
        }
        CloseLibrary(DiskfontBase);
      }
      Close(myfile);
    }
    FreeArgs(myrda);
  }
  else VPrintf("Error parsing arguments\n", NULL);
}

void MainLoop(void)
{
    LONG count, actual, position;
    BOOL aok = TRUE, waitfornewsize = FALSE;
    struct Task *mytask;

    mytask = FindTask(NULL);
    Move(myrp, mywin->BorderLeft + 1, mywin->BorderTop + myfont->tf_YSize + 1);

    while (((actual = Read(myfile, buffer, BUFSIZE)) > 0) && aok) /* While there's something   */
    {                                                             /* to read, fill the buffer. */
        position = 0;
        count = 0;

        while (position <= actual)
        {
           if (!(waitfornewsize))
           {
               while ( ((buffer[count] >= myfont->tf_LoChar) &&
                       (buffer[count] <= myfont->tf_HiChar)) && (count <= actual) )
                   count++;

               Text(myrp, &(buffer[position]), (count)-position);

               while ( ((buffer[count] < myfont->tf_LoChar) ||
                       (buffer[count] > myfont->tf_HiChar)) && (count <= actual) )
               {
                   if (buffer[count] == 0x0A)
                       Move(myrp, mywin->BorderLeft, myrp->cp_y + myfont->tf_YSize + 1);
                   count++;
               }
               position = count;
           }
           else WaitPort(mywin->UserPort);

           while (mymsg = (struct IntuiMessage *)GetMsg(mywin->UserPort))
           {
               if (mymsg->Class == IDCMP_CLOSEWINDOW)     /* The user clicked the close gadget */
               {
                   aok = FALSE;
                   position = actual + 1;
                   ReplyMsg((struct Message *)mymsg);
               }                                                     /* The user picked up the */
               else if (mymsg->Class == IDCMP_SIZEVERIFY)            /* window's sizing gadget */
               {
                  /* When the user has picked up the window's sizing gadget when the           */
                  /* IDCMP_SIZEVERIFY flag is set, the application has to reply to this message*/
                  /* to tell Intuition to allow the user to move the sizing gadget and resize  */
                  /* the window.  The reason for using this here is because the user can resize*/
                  /* the window while cliptext.c is rendering text to the window. Cliptext.c   */
                  /* has to stop rendering text when it receives an IDCMP_SIZEVERIFY message.  */
                  /*                                                                           */
                  /* if this example had instead asked to hear about IDCMP events that could   */
                  /* take place between SIZEVERIFY and NEWSIZE events (especially INTUITICKS), */
                  /* it should turn off those events here using ModifyIDCMP().                 */
                  /*                                                                           */
                  /* After we allow the user to resize the window, we cannot write into the    */
                  /* window until the user has finished resizing it because we need the        */
                  /* window's new size to adjust the clipping area.  Specifically, we have     */
                  /* to wait for an IDCMP_NEWSIZE message which Intuition will send when the   */
                  /* user lets go of the resize gadget.  For now, we set the waitfornewsize    */
                  /* flag to stop rendering until we get that NEWSIZE message.                 */

                   waitfornewsize = TRUE;
                   WaitBlit();

                   ReplyMsg((struct Message *)mymsg);            /* The blitter is done, let the */
               }                                                 /* user resize the window.      */
               else
               {
                   ReplyMsg((struct Message *)mymsg);
                   waitfornewsize = FALSE;
                          /* The user has resized the window, so get the new window dimensions */
                   myrectangle.MinX = mywin->BorderLeft;      /* and readjust the layers       */
                   myrectangle.MinY = mywin->BorderTop;       /* clipping region accordingly.  */
                   myrectangle.MaxX = mywin->Width - (mywin->BorderRight + 1);
                   myrectangle.MaxY = mywin->Height - (mywin->BorderBottom + 1);
                   InstallClipRegion(mywin->WLayer, NULL);
                   ClearRegion(new_region);
                   if (OrRectRegion(new_region, &myrectangle))
                       InstallClipRegion(mywin->WLayer, new_region);
                   else
                   {
                       aok = FALSE;
                       position = actual + 1;
                   }
               }
           }
           if (mytask->tc_SigRecvd & SIGBREAKF_CTRL_C)              /* Check for user break.   */
           {
               aok = FALSE;
               position = actual + 1;
           }

           if (myrp->cp_y > (mywin->Height - (mywin->BorderBottom + 2))) /* if we reached the  */
           {                                               /* bottom of the page, clear the    */
               Delay(25);                                  /* rastport and move back to the top*/

               SetRast(myrp, 0);      /* Set the entire rastport to color zero.  This will not */
               Move(myrp,             /* the window borders because of the layers clipping.    */
               mywin->BorderLeft + 1,
               mywin->BorderTop + myfont->tf_YSize + 1);
            }
        }
    }
    if (actual < 0) VPrintf("Error while reading\n", NULL);
}


V-23/Engine.c

;/* Engine.c - Execute me to compile me with SAS/C 6.56
sc NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 Engine.c
quit ;*/

/* (c)  Copyright 1992-1999 Amiga, Inc.   All rights reserved.       */
/* The information contained herein is subject to change without notice,  */
/* and is provided "as is" without warranty of any kind, either expressed */
/* or implied.  The entire risk as to the use of this information is      */
/* assumed by the user.                                                   */

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dostags.h>
#include <dos/dos.h>
#include <diskfont/diskfonttag.h>
#include <diskfont/diskfont.h>
#include <diskfont/glyph.h>
#include <diskfont/oterrors.h>
#include <utility/tagitem.h>
#include <string.h>

#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/utility_protos.h>
#include <clib/bullet_protos.h>

#define OTAG_ID 0x0f03   /* this really belongs in <diskfont/diskfont.h>, */
                         /* but it's not there, yet.                      */

extern UBYTE   *librarystring; /* ".library", defined in BulletMain.c. */

struct TagItem *AllocOtag(STRPTR);
void            FreeOtag(void *);
struct Library *OpenScalingLibrary(struct TagItem *);
void            CloseScalingLibrary(struct Library *);
struct GlyphEngine *GetGlyphEngine(struct TagItem *, STRPTR);
void            ReleaseGlyphEngine(struct GlyphEngine *);

#define BUFSIZE     256

extern struct Library *BulletBase, *UtilityBase;

/*************************************************************************************/
/* open the otag file, allocate a buffer, read the file into the buffer, verify that */
/* the file is OK, relocate all of the address relocation tags, close the otag file. */
/*************************************************************************************/
struct TagItem *
AllocOtag(STRPTR otagname)
{
  BPTR            otfile;
  struct TagItem *ti, *tip, *returnti;
  struct FileInfoBlock *fib;

  ti = NULL;

  if (fib = AllocDosObject(DOS_FIB, NULL))    /* The FileInfoBlock of the OTAG file */
  {                                           /* contains the file's size.          */
    if (otfile = Open(otagname, MODE_OLDFILE))
    {
      if (ExamineFH(otfile, fib))
      {
        if (returnti = (struct TagItem *) AllocVec(fib->fib_Size, MEMF_CLEAR))
        {
          if (Read(otfile, (UBYTE *) returnti, fib->fib_Size))
          {
            if ((returnti->ti_Tag == OT_FileIdent)               /* Test to see if */
                && (returnti->ti_Data == (ULONG) fib->fib_Size)) /* the OTAG file  */
            {                                                    /* is valid.      */
              tip = returnti;
              while (ti = NextTagItem(&tip))     /* Step through and relocate tags */
              {
                if (ti->ti_Tag & OT_Indirect)
                {
                  ti->ti_Data = (ULONG) returnti + ti->ti_Data;
                }
              }
            }
          }
        }
      }
      Close(otfile);
    }
    FreeDosObject(DOS_FIB, fib);
  }
  return (returnti);
}

/**************************************************************************/
/*********** Deallocates resources allocated by AllocOtag(). **************/
/**************************************************************************/
void
FreeOtag(void *vector)
{
  FreeVec(vector);
}

/*****************************************************************************/
/******* Scans through a TagList looking for an scaling engine name. *********/
/*******           If it finds one, it opens that library.           *********/
/*****************************************************************************/
struct Library *
OpenScalingLibrary(struct TagItem * ti)
{
  STRPTR          enginename;
  UBYTE           libnamebuffer[BUFSIZE];

  if (enginename = (STRPTR) GetTagData(OT_Engine, NULL, ti))
  {
    strcpy(libnamebuffer, enginename);
    strcat(libnamebuffer, librarystring);

    return (OpenLibrary(libnamebuffer, 0L));
  }
  return(NULL);  /*   <----- BUG!:--  This line was missing in the original */
}                /*                        publication of this code module. */

/**************************************************************************/
/******* Deallocates resources allocated by OpenScalingLibrary(). *********/
/**************************************************************************/
void
CloseScalingLibrary(struct Library * bbase)
{
  CloseLibrary(bbase);
}

/**************************************************************************/
/* Open the glyph engine, give it the tags from the otag file, and set up */
/* a default device dpi so it doesn't crash if someone forgets to set it. */
/**************************************************************************/
struct GlyphEngine *
GetGlyphEngine(struct TagItem * ti, STRPTR otagpath)
{
  struct GlyphEngine *ge = NULL;
  BOOL            ok = TRUE;

  if (ge = OpenEngine())
  {
    ok = FALSE;
    if (SetInfo(ge,
                OT_OTagList, ti,
                OT_OTagPath, otagpath,
                TAG_END) == OTERR_Success)
    {
      if (SetInfo(ge,
                  OT_DeviceDPI, ((ULONG) 77) << 16 | 75,
                  TAG_END) == OTERR_Success)
      {
        ok = TRUE;
      }
    }
  }

  if (!ok)
  {
    CloseEngine(ge);
    ge = NULL;
  }
  return (ge);
}

/**************************************************************************/
/********* Deallocates resources allocated by GetGlyphEngine(). ***********/
/**************************************************************************/
void
ReleaseGlyphEngine(struct GlyphEngine * ge)
{
  CloseEngine(ge);
}


V-23/Rotate.c

;/* Rotate.c - Execute me to compile me with SAS/C 6.56
sc NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 Rotate.c
slink FROM LIB:c.o,BulletMain.o,engine.o,Rotate.o TO Rotate LIBRARY LIB:sc.lib,LIB:amiga.lib
quit ;*/

/* (c)  Copyright 1992-1999 Amiga, Inc.   All rights reserved.       */
/* The information contained herein is subject to change without notice,  */
/* and is provided "as is" without warranty of any kind, either expressed */
/* or implied.  The entire risk as to the use of this information is      */
/* assumed by the user.                                                   */

#include <exec/types.h>
#include <diskfont/diskfonttag.h>
#include <diskfont/diskfont.h>
#include <diskfont/glyph.h>
#include <diskfont/oterrors.h>
#include <graphics/gfx.h>
#include <graphics/regions.h>
#include <utility/tagitem.h>
#include <intuition/intuition.h>
#include <devices/timer.h>

#include <clib/alib_stdio_protos.h>
#include <clib/alib_protos.h>
#include <clib/bullet_protos.h>
#include <clib/exec_protos.h>
#include <clib/layers_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>

extern struct Library *BulletBase, *UtilityBase, *GfxBase, *IntuitionBase;
struct Library *LayersBase;
void            BulletExample(struct GlyphEngine *,
                              struct Window *,
                              struct RastPort *,
                              ULONG, ULONG, ULONG, ULONG, ULONG);

UBYTE          *vers = "\0$VER: Rotate 38.10";

#define TABLE_ENTRIES 24
#define SINE_INDEX    0
#define COSINE_INDEX  1

/* precalculated sine and cosine */
LONG            table[TABLE_ENTRIES][2] =
{
  {0x0, 0x10000},             /* 0   degrees */ /* Notice that the sine and cosine  */
  {0x424e, 0xf747},           /* 15  degrees */ /* values have to correspond to the */
  {0x8000, 0xddb4},           /* 30  degrees */ /* same angle.  The IntelliFont     */
  {0xb505, 0xb505},           /* 45  degrees */ /* engine will have severe mental   */
  {0xddb4, 0x8000},           /* 60  degrees */ /* problems if the values aren't    */
  {0xf747, 0x424e},           /* 75  degrees */ /* close to representing the same   */
  {0x10000, 0x0},             /* 90  degrees */ /* angle.                           */
  {0xf747, 0xffffbdbe},       /* 105 degrees */
  {0xddb4, 0xffff8000},       /* 120 degrees */
  {0xb505, 0xffff4afb},       /* 135 degrees */
  {0x8000, 0xffff224c},       /* 150 degrees */
  {0x424e, 0xffff08b9},       /* 165 degrees */
  {0x0, 0xffff0000},          /* 180 degrees */
  {0xffffbdbe, 0xffff08b9},   /* 195 degrees */
  {0xffff8000, 0xffff224c},   /* 210 degrees */
  {0xffff4afb, 0xffff4afb},   /* 225 degrees */
  {0xffff224c, 0xffff8000},   /* 240 degrees */
  {0xffff08b9, 0xffffbdbe},   /* 255 degrees */
  {0xffff0000, 0x0},          /* 270 degrees */
  {0xffff08b9, 0x424e},       /* 285 degrees */
  {0xffff224c, 0x8000},       /* 300 degrees */
  {0xffff4afb, 0xb505},       /* 315 degrees */
  {0xffff8000, 0xddb4},       /* 330 degrees */
  {0xffffbdbe, 0xf747}        /* 345 degrees */
};

struct Rectangle rectangle;
struct Region    *region;

void
BulletExample(struct GlyphEngine * ge,
              struct Window * w, struct RastPort * rp,
     ULONG pointheight, ULONG xdpi, ULONG ydpi, ULONG unicode, ULONG unicode2)
{
  struct GlyphMap *gm;
  PLANEPTR        tempbitmap;
  ULONG           centerx, centery, x, y, dx, dy, sin, cos, oldx, oldy, olddx,
                  olddy, emheight, emwidth;
  ULONG           i = 0;

  struct IntuiMessage *mymsg;
  BOOL            done = FALSE;

  if (pointheight > 180) pointheight = 180;

  if (SetInfo(ge,
              OT_DeviceDPI, ((ULONG) xdpi) << 16 | ydpi,
              TAG_END) != OTERR_Success)
        return;

  emheight = (pointheight * ydpi) / 72; /* Calculate the pixel dimensions */
  emwidth  = (pointheight * xdpi) / 72; /* of the EM square.              */
  centerx  = w->BorderLeft + emheight;
  centery  = w->BorderTop  + emwidth;

  dx = (2 * emwidth) + w->BorderLeft + w->BorderRight;  /* Calculate window size to */
  dy = (2 * emheight) + w->BorderTop + w->BorderBottom; /* fit around glyph com-    */
  dx = (dx > 640) ? 640 : dx;                           /* fortablely.              */
  dy = (dy > 200) ? 200 : dy;
  dx = (dx < 80) ? 80: dx;
  dy = (dy < 50) ? 50: dy;

  if (ModifyIDCMP(w, IDCMP_CHANGEWINDOW))
  {
    ChangeWindowBox(w, w->LeftEdge, w->TopEdge, dx, dy);        /* Set window size  */
    WaitPort(w->UserPort);                                      /* and wait for the */
    while (mymsg = (struct IntuiMessage *) GetMsg(w->UserPort)) /* dimension change */
      ReplyMsg((struct Message *) mymsg);                       /* to take place.   */
    if (!(ModifyIDCMP(w, NULL))) return;  /* Quit if there is a problem with IDCMP. */
  }

  x = centerx; /* calculate original rendering position. */
  y = centery;
  dx = 1;   /* Since dx and dy are no longer necessary for figuring out the window  */
  dy = 1;   /* dimensions, I use them to measure the full width and height of the   */
            /* glyph bitmap supplied by bullet.  I need this to erase the glyph.    */

  if (LayersBase = OpenLibrary("layers.library", 37L)) /* These lines are       */
  {                                                    /* here to install       */
    rectangle.MinX = w->BorderLeft;                    /* a clipping            */
    rectangle.MinY = w->BorderTop;                     /* region to the         */
    rectangle.MaxX = w->Width  - w->BorderRight - 1;   /* window to keep        */
    rectangle.MaxY = w->Height - w->BorderBottom - 1;  /* the glyph within      */
                                                       /* window bounds.        */
    if (region = NewRegion())                          /* For more information, */
    {                                                  /* see the "Layers"      */
      if (OrRectRegion(region, &rectangle))            /* chapter of the        */
      {                                                /* RKRM: Libraries       */
        InstallClipRegion(w->WLayer, region);          /* Manual.               */

        if (SetInfo(ge,
                    OT_GlyphCode, unicode,                      /* Set the glyph to */
                    OT_PointHeight, (ULONG) pointheight << 16,  /* rotate and its   */
                    TAG_END) == OTERR_Success)                  /* pointsize.       */
        {
          SetDrMd(w->RPort, JAM1);
          if (tempbitmap = AllocRaster(640, 200))
          {
            if (ModifyIDCMP(w, IDCMP_CLOSEWINDOW)) /* Turn on close window reports  */
            {                                      /* so the example can quit.      */
              for (i = 0; done == FALSE; i++)
              {
                if (i == TABLE_ENTRIES)
                  i = 0;

                sin = table[i][SINE_INDEX];   /* Step through the sine/cosine array */
                cos = table[i][COSINE_INDEX]; /* 360 degrees @ 15 degree increments */

                if (SetInfo(ge,                  /* Set the current rotation angle. */
                            OT_RotateSin, sin,
                            OT_RotateCos, cos,
                            TAG_END) == OTERR_Success)
                {
                  if ((ObtainInfo(ge, OT_GlyphMap, &gm, TAG_END)) == OTERR_Success)
                  {
                    oldx = x;               /* Calculate the dimension and position */
                    oldy = y;               /* of the new glyph's bitmap and save   */
                    olddx = dx;             /* the old values so we can erase the   */
                    olddy = dy;             /* glyph that is still on the screen.   */
                    x = centerx - gm->glm_X0;
                    y = centery - gm->glm_Y0;
                    dx = gm->glm_BMModulo * 8;
                    dy = gm->glm_BMRows;

                    CopyMem(gm->glm_BitMap,/* Copy the glyph's bitmap into Chip RAM */
                            tempbitmap,    /* so we can blit it into a RastPort.    */
                            gm->glm_BMModulo * gm->glm_BMRows);

                                                            /* Erase the old glyph. */
                    RectFill(rp, oldx, oldy, oldx + olddx, oldy + olddy);

                    WaitBlit();                 /* Wait for the old glyph to erase. */

                    BltTemplate(                   /* Blit the new glyph into the   */
                                 tempbitmap,       /* window's RastPort.            */
                                 0,
                                 gm->glm_BMModulo,
                                 w->RPort,
                                 x,
                                 y,
                                 dx,
                                 dy);          /* Running several instances of this */
                                               /* example simultaneously can really */
                                               /* slow the system, so we give other */
                    TimeDelay(UNIT_VBLANK, 0, 250000);  /*   tasks a chance to run. */
                    ReleaseInfo(ge, OT_GlyphMap, gm, TAG_END);
                  }
                }                               /* Check for a CLOSEWINDOW message. */
                while (mymsg = (struct IntuiMessage *) GetMsg(w->UserPort))
                {
                  ReplyMsg((struct Message *) mymsg);
                  done = TRUE;
                }
              }
            }
            FreeRaster(tempbitmap, 640, 200);
          }
        }
      }
      DisposeRegion(region);
    }
    CloseLibrary(LayersBase);
  }
}


V-23/View.c

;/* View.c - Execute me to compile me with SAS/C 6.56
sc NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 View.c
slink FROM LIB:c.o,BulletMainFile.o,engine.o,View.o TO View LIBRARY LIB:sc.lib,LIB:amiga.lib
quit ;*/

/* (c)  Copyright 1992-1999 Amiga, Inc.   All rights reserved.       */
/* The information contained herein is subject to change without notice,  */
/* and is provided "as is" without warranty of any kind, either expressed */
/* or implied.  The entire risk as to the use of this information is      */
/* assumed by the user.                                                   */

#include <exec/types.h>
#include <exec/memory.h>
#include <diskfont/diskfonttag.h>
#include <diskfont/diskfont.h>
#include <diskfont/glyph.h>
#include <diskfont/oterrors.h>
#include <graphics/gfx.h>
#include <utility/tagitem.h>
#include <intuition/intuition.h>
#include <devices/timer.h>
#include <dos/dos.h>

#include <clib/alib_stdio_protos.h>
#include <clib/alib_protos.h>
#include <clib/bullet_protos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>

UBYTE          *vers = "\0$VER: View 38.7";

extern struct Library *BulletBase, *UtilityBase, *GfxBase, *IntuitionBase;
void            BulletExample(struct GlyphEngine *,
                              struct Window *,
                              struct RastPort *,
                              ULONG, ULONG, ULONG, STRPTR);
struct GlyphMap *gm;
PLANEPTR        tempbitmap;
struct IntuiMessage *mymsg;
UBYTE          *viewfilebuf, *currchar;
ULONG           currposition, emheight, emwidth, x, y;

BPTR            viewfile;
LONG            actual;
struct Task    *mytask;
struct FileInfoBlock *fib;

void
BulletExample(struct GlyphEngine * ge,
              struct Window * w, struct RastPort * rp,
              ULONG pointheight, ULONG xdpi, ULONG ydpi, STRPTR viewfilename)
{
  UWORD           wlimitx, wlimity, newwidth;
  FIXED           kern;

  wlimitx = w->Width  - w->BorderRight  - 2; /* The X and Y extent of the window */
  wlimity = w->Height - w->BorderBottom - 2; /* that we can draw into.           */

  if (SetInfo(ge,                                      /* Set up the X and Y DPI of */
              OT_DeviceDPI, ((ULONG)xdpi) << 16 | ydpi,/* target raster.  Neither   */
              OT_PointHeight, (ULONG)pointheight << 16,/* of these can be zero!     */
              TAG_END) != OTERR_Success)               /* BulletMainFile.c checks   */
    return;                                            /* for zero.                 */

  if (viewfile = Open(viewfilename, MODE_OLDFILE))/* Open the ASCII file to display.*/
  {
    if (fib = AllocDosObject(DOS_FIB, NULL))      /* Find out how big the display   */
    {                                             /* file is by looking at its      */
      if (ExamineFH(viewfile, fib))               /* FileInfoBlock.  Allocate that  */
      {                                           /* Much memory.                   */
        if (viewfilebuf = (UBYTE *) AllocVec(fib->fib_Size, MEMF_CLEAR))
        {
          if (Read(viewfile, (UBYTE *) viewfilebuf, fib->fib_Size))    /* Read the  */
          {                                          /* whole file into its buffer. */
            SetDrMd(w->RPort, JAM1);
            if (tempbitmap = AllocRaster(640, 200)) /* Allocate some Chip RAM space */
            {      /* where we can temporarily store the glyph so we can blit it.   */
              if (ModifyIDCMP(w, IDCMP_CLOSEWINDOW))  /* Turn on the Close gadget.  */
              {
                emheight = (pointheight * ydpi) / 72; /* Calculate the dimensions   */
                emwidth = (pointheight * xdpi) / 72;  /* of the EM square in screen */
                     /* pixels. This is necessary because bullet.library measures   */
                     /* character widths and kerning values as fractions of an EM.  */
                     /* An EM (pronounced like the letter 'M') is a measure of      */
                     /* distance that is equal to the point size of a typeface      */
                     /* (which means one EM is not constant across different type   */
                     /* sizes).  For a 72 point typeface, one EM = 72 points which  */
                     /* approximately equals one inch.                              */

                x = w->BorderLeft + 2;           /* Calculate the starting point    */
                y = w->BorderTop + 2 + emheight; /* for glyph rendering.            */

                                      /* Step through each character in the buffer. */
                for (currposition = 0; currposition < fib->fib_Size; currposition++)
                {
                                /* Set the current glyph, which is the one we'll be */
                                /* rendering in this interation of the loop, and    */
                                /* the secondary glyph, which, besides being the    */
                                /* next glyph we will render, is necessary to find  */
                                /* the proper kerning value between the glyphs.     */
                                /* Notice that this example does not account for    */
                                /* the presence of non-printables (carriage return, */
                                /* DEL, etc.) which effects the kerning.  A real    */
                  if (SetInfo(ge,  /* application should consider these.            */
                              OT_GlyphCode,  (ULONG) viewfilebuf[currposition],
                              OT_GlyphCode2, (ULONG) viewfilebuf[currposition + 1],
                              TAG_END) == OTERR_Success)
                  {
                    kern = 0;         /* Find the kerning adjustment between glyph1 */
                                      /* and glyph2.  This example doesn't account  */
                                      /* for the validity of the glyphs.            */
                    ObtainInfo(ge, OT_TextKernPair, &kern, TAG_END);

                                                  /* Ask the scaling engine for the */
                                                  /* bitmap for the current glyph.  */
                    if ((ObtainInfo(ge, OT_GlyphMap, &gm, TAG_END)) == OTERR_Success)
                    {
                       /* Calculate the width of the current character including    */
                       /* any kerning adjustment.  Because the width is represented */
                       /* as a fixed point binary fraction of an EM, this needs to  */
                       /* be converted to a width in screen pixels.                 */
                      newwidth = ((gm->glm_Width - kern) * emwidth) / 65536;

                      if ((x + newwidth) > wlimitx)  /* Make sure the glyph gets    */
                      {                              /* rendered inside the window  */
                                                     /* bounds.                     */
                        x = w->BorderLeft + 2;
                        y += emheight;
                        if (y > wlimity)   /* If the text goes beyond the bottom of */
                        {                  /* the window, clear the window and move */
                                           /* the current rendering position to the */
                                           /* upper left.                           */
                          y = w->BorderTop + 2 + emheight;
                          RectFill(rp, w->BorderLeft, w->BorderTop, wlimitx, wlimity);
                        }
                      }

                      CopyMem(gm->glm_BitMap,/* Copy the raw bitmap to chip memory. */
                              tempbitmap,
                              gm->glm_BMModulo * gm->glm_BMRows);

                      BltTemplate(           /* Render the glyph using the blitter  */
                                             /* and the RastPort settings.          */
                                   (PLANEPTR) (((ULONG) tempbitmap)
                                     + (gm->glm_BMModulo * gm->glm_BlackTop)
                                         + ((gm->glm_BlackLeft >> 4) << 1)),
                                   gm->glm_BlackLeft & 0xF,
                                   gm->glm_BMModulo,
                                   w->RPort,
                                   x - gm->glm_X0 + gm->glm_BlackLeft,
                                   y - gm->glm_Y0 + gm->glm_BlackTop,
                                   gm->glm_BlackWidth,     /* glm_X0 & Y0 are used  */
                                   gm->glm_BlackHeight);   /* to make the example a */
                                    /* little simpler.  They are not as accurate as */
                                    /* using glm_XOrigin and glm_YOrigin in con-    */
                                    /* juntion with fractional width and kerning    */
                                    /* values.                                      */

                      x += newwidth;
                      ReleaseInfo(ge, OT_GlyphMap, gm, TAG_END);
                    }
                    while (mymsg = (struct IntuiMessage *) GetMsg(w->UserPort))
                    {                                       /* Did the user hit the */
                      ReplyMsg((struct Message *) mymsg);   /* Close Gadget?        */
                      currposition = fib->fib_Size + 1;
                    }
                  }
                }
              }
              FreeRaster(tempbitmap, 640, 200);
            }
          }
          FreeVec(viewfilebuf);
        }
      }
      FreeDosObject(DOS_FIB, fib);
    }
    Close(viewfile);
  }
}


V-23/BulletMain.c

;/* BulletMain.c - Execute me to compile me with SAS/C 6.56
sc NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 BulletMain.c
quit ;*/

/* (c)  Copyright 1992-1999 Amiga, Inc.   All rights reserved.       */
/* The information contained herein is subject to change without notice,  */
/* and is provided "as is" without warranty of any kind, either expressed */
/* or implied.  The entire risk as to the use of this information is      */
/* assumed by the user.                                                   */

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/rdargs.h>
#include <dos/dos.h>
#include <dos/var.h>
#include <diskfont/diskfonttag.h>
#include <diskfont/diskfont.h>
#include <diskfont/glyph.h>
#include <diskfont/oterrors.h>
#include <utility/tagitem.h>
#include <string.h>
#include <graphics/displayinfo.h>
#include <intuition/intuition.h>
#include <intuition/screens.h>

#include <clib/dos_protos.h>
#include <clib/graphics_protos.h>
#include <clib/exec_protos.h>
#include <clib/utility_protos.h>
#include <clib/bullet_protos.h>
#include <clib/intuition_protos.h>

#define OTAG_ID 0x0f03

#ifdef LATTICE
int CXBRK(void) { return (0);} /* Disable Lattice CTRL/C handling */
int chkabort(void) { return (0);}
#endif

UBYTE   *readargsstring = "FontName,Size/N,XDPI/N,YDPI/N,CharCode/N,CharCode2/N\n";
UBYTE   *librarystring = ".library";
UBYTE   *fontstring     = "fonts:cgtimes.font";
UBYTE   *dpivarname = "XYDPI";  /* Name of an X/Y DPI environment variable. */
                                /* If this ENV: variable exists, this code  */
                                /* will use the X and Y DPI stored there.   */
                                /* This code will also save the X and Y DPI */
                                /* in XYDPI if the user supplies a DPI.     */
                                /* XYDPI encodes the DPI just like the      */
                                /* OT_DeviceDPI tag.                        */
extern struct TagItem *AllocOtag(STRPTR);
extern void     FreeOtag(void *);
extern struct Library *OpenScalingLibrary(struct TagItem *);
extern void     CloseScalingLibrary(struct Library *);
extern struct GlyphEngine *GetGlyphEngine(struct TagItem *, STRPTR);
extern void     ReleaseGlyphEngine(struct GlyphEngine *);
extern void
BulletExample(struct GlyphEngine *,
              struct Window *,
              struct RastPort *, ULONG, ULONG, ULONG, ULONG, ULONG);

#define BUFSIZE     256

#define NUM_ARGS    6    /* Arguments for ReadArgs(). */
#define FONT_NAME   0
#define SIZE        1
#define XDPI        2
#define YDPI        3
#define CODE        4
#define CODE2       5
LONG            args[NUM_ARGS];
struct RDargs  *myrda;

struct Library *BulletBase, *UtilityBase, *GfxBase, *IntuitionBase;

UBYTE           buf[BUFSIZE];
BPTR            fontfile, dpifile;
UBYTE          *otagname;
UWORD           fchid;

struct GlyphEngine *ge;

struct DrawInfo *drawinfo;
struct RastPort rp;

void            main(int argc, char **argv)
{
  struct TagItem *ti;
  struct GlyphEngine *ge;
  struct Window  *w;

  UBYTE           xydpi[5];

  ULONG           defpointheight = 36;   /* Default values for ReadArgs() */
  ULONG           defxdpi = 68;          /* variables.                    */
  ULONG           defydpi = 27;
  ULONG           defcode = (ULONG) 'A';
  ULONG           defcode2 = 0;

  if (GfxBase = OpenLibrary("graphics.library", 37L))
  {
    if (IntuitionBase = OpenLibrary("intuition.library", 37L))
    {
      if (myrda = ReadArgs(readargsstring, args, NULL))
      {
        if (args[XDPI] && args[YDPI]) /* If the user sets the DPI from the command  */
        {            /* line, make sure the environment variable also gets changed. */
          *(ULONG *)xydpi = ( (*(LONG *) args[XDPI]) << 16 | (*(ULONG *) args[YDPI]) );
          SetVar(dpivarname, xydpi, 5,
              GVF_GLOBAL_ONLY | GVF_BINARY_VAR | GVF_DONT_NULL_TERM);
        }
        else                            /* If the user did NOT set the X OR Y DPI...*/
        {
          args[XDPI] = (LONG) &defxdpi; /* ...set to default values and look for    */
          args[YDPI] = (LONG) &defydpi; /* an environment variable called "XYDPI".  */
                                                  /* Read the environment variable, */
          if ((GetVar(dpivarname, xydpi, 5,        /* XYDPI, if it exists.          */
              GVF_GLOBAL_ONLY | GVF_BINARY_VAR | GVF_DONT_NULL_TERM)) != -1)

     /* BUG!: In the original publication of this code, the line above erroneously  */
     /* tested for the wrong return value.  It caused unexpected results when using */
     /* the default X and Y DPI values.  This bug was also present in BulletMain.c. */

          {
            if ( (*(ULONG *)xydpi & 0xFFFF0000) && (*(ULONG *)xydpi & 0x0000FFFF) )
            {     /* Make sure the environment variable is OK to use by making sure */
                  /* that neither X or YDPI is zero. If XYDPI is OK, use it as the  */
              defxdpi = ((*(ULONG *)xydpi) & 0xFFFF0000) >> 16;        /* default.  */
              defydpi = (*(ULONG *)xydpi) & 0x0000FFFF;
            }
          }
        }
        if (!(args[SIZE]))
          args[SIZE] = (LONG) &defpointheight;
        if (!(args[CODE]))
          args[CODE] = (LONG) &defcode;
        if (!(args[CODE2]))
          args[CODE2] = (LONG) &defcode2;
        if (!(args[FONT_NAME]))
          args[FONT_NAME] = (LONG) fontstring;
                                           /* Open the ".font" file which contains  */
                                           /* the FontContentsHeader for this font. */
        if (fontfile = Open((STRPTR) args[FONT_NAME], MODE_OLDFILE))
        {
          if (Read(fontfile, &fchid, sizeof(UWORD)))
          {
            if (fchid == OTAG_ID)             /* Does this font have an .otag file? */
            {
              strcpy(buf, (STRPTR) args[FONT_NAME]); /* Put together the otag file  */
              if (otagname = &(buf[strlen(buf) - 4]))/* name from the .font file.   */
              {
                strcpy(otagname, "otag");
                if (UtilityBase = OpenLibrary("utility.library", 37L))
                {
                  if (ti = AllocOtag(buf))      /* open the otag file and copy its  */
                  {                             /* tags into memory.                */
                    if (BulletBase = OpenScalingLibrary(ti)) /* Pass the function   */
                    {                                  /* the OTAG tag list which it*/
                                                       /* needs to open the scaling */
                      if (ge = GetGlyphEngine(ti, buf))/* library.  Open the        */
                      {                                /* library's scaling engine. */
                        if (w = OpenWindowTags(NULL,
                                               WA_Width,         640,
                                               WA_Height,        200,
                                               WA_SmartRefresh,  TRUE,
                                               WA_SizeGadget,    FALSE,
                                               WA_CloseGadget,   TRUE,
                                               WA_IDCMP,         NULL,
                                               WA_DragBar,       TRUE,
                                               WA_DepthGadget,   TRUE,
                                               WA_Title,         (ULONG)argv[0],
                                               TAG_END))
                        {
                          rp = *(w->RPort); /* Clone window's RastPort.  The second */
                                            /* Rastport is for rendering with the   */
                                            /* background color.                    */

                          if (drawinfo = GetScreenDrawInfo(w->WScreen)) /* Get the  */
                          {             /* Screen's DrawInfo to get its pen colors. */
                            SetAPen(w->RPort, drawinfo->dri_Pens[TEXTPEN]);
                            SetAPen(&rp, drawinfo->dri_Pens[BACKGROUNDPEN]);
                            FreeScreenDrawInfo(w->WScreen, drawinfo);

                            BulletExample(ge, w, &rp, *(ULONG *) args[SIZE],
                                          *(ULONG *) args[XDPI],
                                          *(ULONG *) args[YDPI],
                                          *(ULONG *) args[CODE],
                                          *(ULONG *) args[CODE2]);
                          }
                          CloseWindow(w);
                        }
                        ReleaseGlyphEngine(ge);
                      }
                      CloseScalingLibrary(BulletBase);
                    }
                    FreeOtag(ti);
                  }
                  CloseLibrary(UtilityBase);
                }
              }
            }
          }
          Close(fontfile);
        }
        FreeArgs(myrda);
      }
      CloseLibrary(IntuitionBase);
    }
    CloseLibrary(GfxBase);
  }
}


V-23/BulletMainFile.c

;/* BulletMainFile.c - Execute me to compile me with SAS/C 6.56
sc NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 BulletMainFile.c
quit ;*/

/* (c)  Copyright 1992-1999 Amiga, Inc.   All rights reserved.       */
/* The information contained herein is subject to change without notice,  */
/* and is provided "as is" without warranty of any kind, either expressed */
/* or implied.  The entire risk as to the use of this information is      */
/* assumed by the user.                                                   */

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/rdargs.h>
#include <dos/dos.h>
#include <dos/var.h>
#include <diskfont/diskfonttag.h>
#include <diskfont/diskfont.h>
#include <diskfont/glyph.h>
#include <diskfont/oterrors.h>
#include <utility/tagitem.h>
#include <string.h>
#include <graphics/displayinfo.h>
#include <intuition/intuition.h>
#include <intuition/screens.h>

#include <clib/dos_protos.h>
#include <clib/graphics_protos.h>
#include <clib/exec_protos.h>
#include <clib/utility_protos.h>
#include <clib/bullet_protos.h>
#include <clib/intuition_protos.h>

#define OTAG_ID 0x0f03
#define BUFSIZE     256

#ifdef LATTICE
int CXBRK(void) { return (0);} /* Disable Lattice CTRL/C handling */
int chkabort(void) { return (0);}
#endif

UBYTE     *readargsstring = "FileName/A,FontName,Size/N,XDPI/N,YDPI/N\n";
UBYTE     *librarystring  = ".library";
UBYTE     *fontstring     = "fonts:cgtimes.font";
UBYTE     *dpivarname = "XYDPI";   /* Name of an X/Y DPI environment variable. */
                                   /* If this ENV: variable exists, this code  */
                                   /* will use the X and Y DPI stored there.   */
                                   /* This code will also save the X and Y DPI */
                                   /* in XYDPI if the user supplies a DPI.     */
                                   /* XYDPI encodes the DPI just like the      */
                                   /* OT_DeviceDPI tag.                        */
extern struct TagItem *AllocOtag(STRPTR);
extern void     FreeOtag(void *);
extern struct Library *OpenScalingLibrary(struct TagItem *);
extern void     CloseScalingLibrary(struct Library *);
extern struct GlyphEngine *GetGlyphEngine(struct TagItem *, STRPTR);
extern void     ReleaseGlyphEngine(struct GlyphEngine *);
extern void
BulletExample(struct GlyphEngine *,
                  struct Window *,
                  struct RastPort *, ULONG, ULONG, ULONG, STRPTR);

#define NUM_ARGS    5 /* Arguments for ReadArgs(). */
#define VIEW_FILE   0
#define FONT_NAME   1
#define SIZE        2
#define XDPI        3
#define YDPI        4
LONG            args[NUM_ARGS];
struct RDargs  *myrda;

struct Library *BulletBase, *UtilityBase, *GfxBase, *IntuitionBase;

UBYTE           buf[BUFSIZE];
BPTR            fontfile, dpifile;
UBYTE          *otagname;
UWORD           fchid;

struct GlyphEngine *ge;

struct DrawInfo *drawinfo;
struct RastPort rp;

void            main(int argc, char **argv)
{
  struct TagItem *ti;
  struct GlyphEngine *ge;
  struct Window  *w;

  UBYTE           xydpi[5];

  LONG           defpointheight = 36;   /* Default values for ReadArgs() variables. */
  LONG           defxdpi = 68;
  LONG           defydpi = 27;

  if (GfxBase = OpenLibrary("graphics.library", 37L))
  {
    if (IntuitionBase = OpenLibrary("intuition.library", 37L))
    {
      if (myrda = ReadArgs(readargsstring, args, NULL))
      {
        if (args[XDPI] && args[YDPI]) /* If the user sets the DPI from the command  */
        {            /* line, make sure the environment variable also gets changed. */
          *(ULONG *)xydpi = ( (*(LONG *)args[XDPI]) << 16 | (*(ULONG *)args[YDPI]) );
          SetVar(dpivarname, xydpi, 5,
              GVF_GLOBAL_ONLY | GVF_BINARY_VAR | GVF_DONT_NULL_TERM);
        }
        else                           /* If the user did NOT set the X OR Y DPI... */
        {
          args[XDPI] = (LONG) &defxdpi;/* ...set to default values and see if there */
          args[YDPI] = (LONG) &defydpi;/* there is an environment variable "XYDPI". */
                                                  /* Read the environment variable, */
          if ((GetVar(dpivarname, xydpi, 5,       /* XYDPI, if it exists.           */
              GVF_GLOBAL_ONLY | GVF_BINARY_VAR | GVF_DONT_NULL_TERM)) != -1)

/* BUG! In the original publication of this code, the line above erroneously tested */
/* tested for the wrong return value.  It caused unexpected results when using the  */
/* default X and Y DPI values.  This bug was also present in BulletMain.c.          */

          {
            if ( (*(ULONG *)xydpi & 0xFFFF0000) && (*(ULONG *)xydpi & 0x0000FFFF) )
            {          /* Make sure the environment variable is OK to use by making */
                       /* sure that neither X or YDPI is zero. If XYDPI is OK, use  */
              defxdpi = ((*(ULONG *)xydpi) & 0xFFFF0000) >> 16; /* it as a default. */
              defydpi = (*(ULONG *)xydpi) & 0x0000FFFF;
            }
          }
        }
        if (!(args[SIZE]))
          args[SIZE] = (LONG) &defpointheight;
        if (!(args[FONT_NAME]))
          args[FONT_NAME] = (LONG) fontstring;
                                           /* Open the ".font" file which contains  */
                                           /* the FontContentsHeader for this font. */

        if (fontfile = Open((STRPTR) args[FONT_NAME], MODE_OLDFILE))
        {
          if (Read(fontfile, &fchid, sizeof(UWORD)))
          {
            if (fchid == OTAG_ID)            /* Does this font have an .otag file? */
            {
              strcpy(buf, (STRPTR) args[FONT_NAME]);   /* Put together the .otag   */
              if (otagname = &(buf[strlen(buf) - 4]))  /* file name from the .font */
              {                                        /* file name.               */
                strcpy(otagname, "otag");
                if (UtilityBase = OpenLibrary("utility.library", 37L))
                {
                  if (ti = AllocOtag(buf))      /* open the otag file and copy its */
                  {                             /* tags into memory.               */
                    if (BulletBase = OpenScalingLibrary(ti)) /* Pass the function  */
                    {                                  /* the OTAG tag list which  */
                      if (ge = GetGlyphEngine(ti, buf))/* it needs to open the     */
                      {                              /* scaling library.  Open the */
                                                     /* library's scaling engine.  */
                        if (w = OpenWindowTags(NULL,
                                               WA_Width,         640,
                                               WA_Height,        200,
                                               WA_SmartRefresh,  TRUE,
                                               WA_SizeGadget,    FALSE,
                                               WA_CloseGadget,   TRUE,
                                               WA_IDCMP,         NULL,
                                               WA_DragBar,       TRUE,
                                               WA_DepthGadget,   TRUE,
                                               WA_Title,         (ULONG)argv[0],
                                               TAG_END))
                        {
                          rp = *(w->RPort);    /* Clone window's RastPort.  The    */
                                               /* second Rastport is for rendering */
                                               /* with the background color.       */
                          if (drawinfo = GetScreenDrawInfo(w->WScreen)) /* Get the */
                          {            /* screen's DrawInfo to get its pen colors. */
                            SetAPen(w->RPort, drawinfo->dri_Pens[TEXTPEN]);
                            SetAPen(&rp, drawinfo->dri_Pens[BACKGROUNDPEN]);
                            FreeScreenDrawInfo(w->WScreen, drawinfo);
                          }

                          BulletExample(ge, w, &rp, *(ULONG *) args[SIZE],
                                        *(ULONG *) args[XDPI],
                                        *(ULONG *) args[YDPI],
                                        (STRPTR) args[VIEW_FILE]);
                          CloseWindow(w);
                        }
                        ReleaseGlyphEngine(ge);
                      }
                      CloseScalingLibrary(BulletBase);
                    }
                    FreeOtag(ti);
                  }
                  CloseLibrary(UtilityBase);
                }
              }
            }
          }
          Close(fontfile);
        }
        FreeArgs(myrda);
      }
      CloseLibrary(IntuitionBase);
    }
    CloseLibrary(GfxBase);
  }
}


V-39/NameMode.c

#include <exec/types.h>
#include <graphics/displayinfo.h>
#include <stdio.h>
#include <string.h>

#include <clib/graphics_protos.h>
#include <clib/utility_protos.h>

/*****************************************************************************/

#define MONITOR_PART(id) ((id) & MONITOR_ID_MASK)

/*****************************************************************************/

BOOL NameMode (ULONG modeID, STRPTR result)
{
  struct NameInfo nameInfo;
  struct DisplayInfo dispInfo;
  struct DimensionInfo dimInfo;
  struct MonitorInfo monInfo;
  char buffer[DISPLAYNAMELEN + 1];
  UWORD len;
  DisplayInfoHandle dh;

  result[0] = 0;

  dh = FindDisplayInfo (modeID);
  if (GetDisplayInfoData (dh, (APTR) & dispInfo, sizeof (struct DisplayInfo),
                          DTAG_DISP, INVALID_ID), INVALID_ID)
  {
    if (!dispInfo.NotAvailable)
    {
      if (GetDisplayInfoData (dh, (APTR) & dimInfo, sizeof (struct DimensionInfo),
                              DTAG_DIMS, INVALID_ID))
      {
    /* Get name or make one if no name available */
    if (GetDisplayInfoData (dh, (APTR) & nameInfo, sizeof (struct NameInfo),
                            DTAG_NAME, INVALID_ID))
    {
      strcpy (result, nameInfo.Name);
      return (TRUE);
    }
    else
    {
      if (GetDisplayInfoData (dh, (APTR) & monInfo, sizeof (struct MonitorInfo),
                              DTAG_MNTR, INVALID_ID))
      {
        if ((monInfo.Mspc) && (monInfo.Mspc->ms_Node.xln_Name))
        {
          strcpy (buffer, monInfo.Mspc->ms_Node.xln_Name);
          len = strlen (buffer);
          if ((len > 8) && (Strnicmp (&buffer[len - 8], ".monitor", len - 8)
                                                                         == 0))
          {
        buffer[len - 8] = 0;
        len -= 8;
          }

          while (len > 0)
        buffer[--len] = ToUpper (buffer[len]);
        }
      }

      sprintf (result, "%s:%lu x %lu %s%s%s",
           buffer,
           (dimInfo.Nominal.MaxX - dimInfo.Nominal.MinX + 1),
           (dimInfo.Nominal.MaxY - dimInfo.Nominal.MinY + 1),
           (dispInfo.PropertyFlags & DIPF_IS_HAM) ? "HAM " :
           (dispInfo.PropertyFlags & DIPF_IS_EXTRAHALFBRITE) ? "EHB " : "",
           (dispInfo.PropertyFlags & DIPF_IS_PF2PRI) ? "DPF2 " :
           (dispInfo.PropertyFlags & DIPF_IS_DUALPF) ? "DPF " : "",
           (dispInfo.PropertyFlags & DIPF_IS_LACE) ? "Laced " : "", "");

      return (TRUE);
    }
      }
    }
  }

  return (FALSE);
}

/*****************************************************************************/

void main (void)
{
  ULONG modeID;
  char name[64];

  modeID = INVALID_ID;
  while ((modeID = NextDisplayInfo (modeID)) != INVALID_ID)
  {
    if (MONITOR_PART (modeID))	/* ignore "default" monitor */
    {
      if (NameMode (modeID, name))
      {
    printf ("%s\n", name);
      }
    }
  }
}


VI-1/interplay.c

;/* interplay.c -- execute me to compile me
sc DATA=NEAR NMINC STRMERGE NOSTKCHK IGNORE=73 interplay.c
slink FROM LIB:c.o + interplay.o TO interplay LIBRARY lib:sc.lib+lib:amiga.lib
quit
*/

/* (c)  Copyright 1993-1999 Amiga, Inc.   All rights reserved. */
/* The information contained herein is subject to change without    */
/* notice, and is provided "as is" without warranty of any kind,    */
/* either expressed or implied.  The entire risk as to the use of   */
/* this information is assumed by the user.                         */

/* Interlay.c - Run from Shell (CLI) only.  Given two file names of IFF
** 8SVX 8-bit sampled audio data, plays the data from both files using just
** one channel.  This demonstrates how virtual audio channels can be
** implemented.
**
** The program supports two different methods for virtual voices.  Method 1
** (the default method) interleaves bytes from each file so that the data words
** fed into the Amiga's audio hardware contain one byte each from the given
** files.  The samples are then played back at twice their normal speed.  Since
** each sample only gets half of the playback bandwidth, the speed sounds
** correct.  To the listener, it sounds as if both samples are playing
** simultaneously even though only one channel is used.
**
** Normally the maximum playback rate with the Amiga's audio hardware is about
** 28K bytes/sec.  Since interleaving requires doubling the nominal sampling
** rate, it will only work with audio data created at a sampling rate of 14K
** bytes/sec or less.
**
** Method 2, takes one byte from each file, sums them and divides by two.
** The resulting byte value is sent to the Amiga's audio hardware.  No speed
** increase is required for this technique, however some noise  is introduced
** by the averaging of the byte values.  To use method 2, inlcude the SUM
** keyword as the last argument typed on the command line.  Examples:
**
**    interplay talk.8svx music.8svx SUM  (Uses method 2, averaging)
**    interplay talk.8svx music.8svx      (Uses method 1, interleaving)
**    interplay talk.8svx                 (Normal single file 8SVX playback)
**
** For an example of conventional IFF 8SVX audio see the "Amiga ROM Kernel
** Reference Manual: Devices", 3rd edition (ISBN 0-201-56775-X), page 28 and
** page 515.
*/

#include <exec/types.h>
#include <exec/devices.h>
#include <exec/memory.h>
#include <devices/audio.h>
#include <dos/dos.h>

#include <iff/iff.h>
#include <iff/8svx.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/alib_protos.h>

#include <stdio.h>
#include <string.h>
#include <dos.h>      /* This is the dos.h file from SAS/C not Commodore */

#ifdef SASC
int CXBRK(VOID)    { return(0); };
int chkabort(VOID) { return(0); };
#endif

#define BUF_SIZE 1024

/* Prototypes for functions defined in this program */
struct IOAudio *SiezeChannel( VOID );
VOID            ReleaseChannel( struct IOAudio * );
char           *Parse8svx(char *, struct InterPlay * );
VOID            EndParse( struct InterPlay * );
VOID            FillAudio(struct InterPlay *, struct IOAudio * );

struct InterPlay                       /* This is the main structure used for */
    {                                  /*  storage of playback state info.    */
    ULONG             sample_done;     /* 0=Keep playing, 1=all done playing. */
    UBYTE            *sample_byte;     /* Pointer for going through the data. */
    UBYTE            *sample_loc;      /* Start of 8SVX BODY data in memory.  */
    ULONG             sample_size;     /*  and total size of file for freeing.*/
    struct InterPlay *next_iplay;      /* Link to second data set. NULL means */
                                       /*  no second file name was given.     */
    LONG              offsetBody;      /* Offset into the file of BODY Chunk. */
    UWORD             sample_speed;    /* Value for audio period register.    */
    BOOL              USE_SUMMING;     /* TRUE means use averaging,           */
    };                                 /*  FALSE means use interleaving.      */

/* Version string for AmigaDOS VERSION command. */
UBYTE versiontag[] = "$VER: Interplay 1.0 (2.2.93)";

/*-----------------------------------------
**
**          main()
**
**-----------------------------------------
*/

VOID main(int argc, char **argv)
{
struct InterPlay  mainplay,otherplay;   /* Two instances of the InterPlay    */
                                        /*  structure, one for each file.    */
struct IOAudio *pIOA_1=NULL,
               *pIOA_2=NULL,            /* Two IOAudio pointers, plus one    */
               *pIOA  =NULL;            /*  for switching back and forth     */
struct MsgPort *mport1=NULL,            /*  during double-buffering.         */
               *mport2=NULL,            /* Two MsgPort pointers, plus one    */
               *mport =NULL;            /*  for switching back and forth.    */

struct Message *msg;                    /* For the GetMsg() call.            */

LONG aswitch = 0L;                      /* Double-buffering logical switch.  */

static BYTE chip playbuffer1[BUF_SIZE]; /* Two buffers, one for each IOAudio */
static BYTE chip playbuffer2[BUF_SIZE]; /*  request.  Play out of one while  */
                                        /*  the other is being set up.       */
char *errormsg;     /* For error returns */
ULONG wakemask=0L;  /* For Wait() call   */

/* Give an AmigaDOS style help message */
if( (argc == 2) && !strcmp(argv[1],"?\0") )
    printf("8SVX-FILES/M,SUM/S\n");

else if(argc>=2) /* OK got at least one argument. */
    {
    /* Get an audio channel at the highest priority */
    if( pIOA_1=SiezeChannel() )
      {
      mport1 = pIOA_1->ioa_Request.io_Message.mn_ReplyPort;
      pIOA_1->ioa_Data = playbuffer1;

      /* Get a 2nd MsgPort and 2nd IOAudio structure for double-buffering */
      pIOA_2 = AllocMem(sizeof(struct IOAudio),MEMF_PUBLIC | MEMF_CLEAR );
      mport2 = CreatePort(0,0);
      if( pIOA_2 && mport2 )
          {
          /* The 2 IOAudio requests should be initialized the same */
          /* except for the buffer and the reply port they use.    */
          *pIOA_2 = *pIOA_1;
          pIOA_2->ioa_Request.io_Message.mn_ReplyPort = mport2;
          pIOA_2->ioa_Data = playbuffer2;

          /* Default is to use interleaving, not averaging */
          mainplay.USE_SUMMING = FALSE;

          /* Parse the 8SVX file and fill in the InterPlay structure */
          errormsg = Parse8svx( argv[1] , &mainplay );

          /* If a second file name was given by the user then this is */
          /* an interleave request, so parse the 2nd 8SVX file.       */
          if( argc>=3 && !errormsg )
              {
              errormsg = Parse8svx( argv[2] , &otherplay );
              mainplay.next_iplay = &otherplay;

              /* If the SUM keyword was given in the command line, set the */
              /* SUMMING flag so that averaging, not interleaving, is used.*/
              if( (argc == 4) &&
                  ( !strcmp(argv[3],"SUM\0") || !strcmp(argv[3],"sum\0") )  )
                  mainplay.USE_SUMMING = TRUE;
              }
          else
              otherplay.sample_done = 1;

          if(!errormsg) /* File names given parsed OK? */
              {
              /* Fill up the buffer for the first request. */
              FillAudio( &mainplay, pIOA_1);

              /* Is there enough data to double-buffer ? */
              if(!mainplay.sample_done || !otherplay.sample_done)
                  {
                  /* OK, enough data to double-buffer; fill up 2nd request */
                  FillAudio( &mainplay, pIOA_2 );
                  BeginIO((struct IORequest *) pIOA_1 );
                  BeginIO((struct IORequest *) pIOA_2 );

                  /* Initial state of double-buffering variables */
                  aswitch=0; pIOA=pIOA_2; mport=mport1;

                  /*---------------------*/
                  /*  M A I N   L O O P  */
                  /*---------------------*/
                  while(!mainplay.sample_done || !otherplay.sample_done)
                      {
                      wakemask=Wait( (1 << mport->mp_SigBit) |
                                               SIGBREAKF_CTRL_C  );

                      if( wakemask & SIGBREAKF_CTRL_C )
                          {
                          otherplay.sample_done = 1;
                          mainplay.sample_done = 1;
                          }

                      while((msg=GetMsg(mport))==NULL){}

                      /* Toggle double-buffering variables */
                      if  (aswitch) {aswitch=0;pIOA=pIOA_2;mport=mport1;}
                      else          {aswitch=1;pIOA=pIOA_1;mport=mport2;}

                      FillAudio( &mainplay, pIOA );
                      BeginIO((struct IORequest *) pIOA );
                      }

                  wakemask=Wait( 1 << mport->mp_SigBit );
                  while((msg=GetMsg(mport))==NULL){}

                  if  (aswitch) {aswitch=0;pIOA=pIOA_2;mport=mport1;}
                  else          {aswitch=1;pIOA=pIOA_1;mport=mport2;}

                  wakemask=Wait( 1 << mport->mp_SigBit );
                  while((msg=GetMsg(mport))==NULL){}
                  }
              else
                  {
                  /* Only enough data to fill up one buffer */
                  BeginIO((struct IORequest *) pIOA_1 );
                  wakemask=Wait( 1 << mport1->mp_SigBit );
                  while((msg=GetMsg(mport1))==NULL){}
                  }
              }
          else
              /* One or the other of the files had a problem in Parse8svx() */
              printf(errormsg);

          /* Free the memory used for the 8SVX files in Parse8svx() */
          if(mainplay.next_iplay)
              EndParse( &otherplay );
          EndParse( &mainplay );

          }
      else printf("Couldn't get memory for a second IOAudio and MsgPort\n");

      /* Free the ports and memory used by the 2 IOAudio requests */
      if(mport2) DeletePort(mport2);
      if(pIOA_2) FreeMem( pIOA_2, sizeof(struct IOAudio) );

      ReleaseChannel(pIOA_1);
      }
    else printf("Couldn't get a channel on the audio device\n");
    }
else printf("Enter one or two 8SVX filenames.\n");
}

/*----------------------------------------------------------------------
** struct IOAudio *res = SiezeChannel( VOID )
**
**   Allocates any channel at the highest priority.  Once allocated,
**   the hardware registers of the given channel can be hit directly
**   without interfering with normal audio.device operation.
**
**   Retruns NULL on failure
**   or returns the address of the IOAudio used to get the channel.
**   If the call to this function succeeds, ReleaseChannel() should
**   be called later to free the channel and memory used for the IOAudio.
**-----------------------------------------------------------------------
*/
struct IOAudio *
SiezeChannel( VOID )
{
struct IOAudio *myAIOreq=NULL;
struct MsgPort *myAIOreply=NULL;
UBYTE chans[] = {1,2,4,8};      /* Try to get one channel, any channel */
BYTE dev = -1;

myAIOreq=(struct IOAudio *)AllocMem(sizeof(struct IOAudio),MEMF_PUBLIC );
if(myAIOreq)
    {
    myAIOreply=CreatePort(0,0);
    if(myAIOreply)
        {
        myAIOreq->ioa_Request.io_Message.mn_ReplyPort   = myAIOreply;
        myAIOreq->ioa_Request.io_Message.mn_Node.ln_Pri = 127;
        myAIOreq->ioa_Request.io_Command                = ADCMD_ALLOCATE;
        myAIOreq->ioa_AllocKey                          = 0;
        myAIOreq->ioa_Data                              = chans;
        myAIOreq->ioa_Length                            = sizeof(chans);

        dev=OpenDevice("audio.device",0L,(struct IORequest *)myAIOreq,0L);

       if(! dev)
            return( myAIOreq ); /* Successful exit */

        DeletePort( myAIOreply );
        }
    FreeMem( myAIOreq, sizeof(struct IOAudio) );
    }
return( NULL );
}

/*---------------------------------------------------------------
** VOID ReleaseChannel(struct IOAudio *rel );
**
**   Frees the channel and any asociated memory allocated earlier
**   with SiezeChannel().
**---------------------------------------------------------------
*/
VOID
ReleaseChannel(struct IOAudio *rel)
{
if(rel)
    {
    CloseDevice( (struct IORequest *) rel );

    if(rel->ioa_Request.io_Message.mn_ReplyPort)
        {
        DeletePort(rel->ioa_Request.io_Message.mn_ReplyPort);
        }
    FreeMem( rel, sizeof(struct IOAudio) );
    }
}

/*--------------------------------------------------------------------
**
** char *Parse8svx( char *filename, struct InterPlay *play_state)
**
**   Pass this function the name of an 8svx file.  It opens the file and
**   finds the VHDR and BODY Chunks.  Playback information is stored
**   in the InterPlay structure.
**
**   A NULL return indicates the parse was completely successful.
**   A non-NULL return means the file cannot be played back for
**   some reason.  In that case the return value is a pointer to
**   an error message explaining what went wrong.
**
**   After calling Parse8svx(), End Parse() should be called
**   to free any memory used.
**
**----------------------------------------------------------------------
*/
char *
Parse8svx(char *fname, struct InterPlay *play)
{
BYTE iobuffer[12];
LONG rdcount=0L;
Chunk *pChunk=NULL;
GroupHeader *pGH=NULL;

Voice8Header *pV8Head = NULL;
char         *error   = NULL;
BPTR         filehandle=NULL;
BOOL         NO_BODY  = TRUE;
BOOL         NO_VHDR  = TRUE;

/* Under normal operation, this function leaves the file positioned */
/* at the BODY Chunk.  However, for some degenerate 8SVX files, one */
/* additional seek is needed at the end.  In that case this field   */
/* (play->offsetBody) will be changed to the seek offset.           */
play->offsetBody = 0;
play->sample_loc = NULL;   /* Set to non-NULL if memory is allocated  */
play->next_iplay = NULL;   /* Default is no successors, no interleave */
play->sample_done= 0L;     /* Will be set to 1 when playback is done  */

filehandle= NULL;          /* Set to non-NULL if the file opens       */

NO_BODY=TRUE;
NO_VHDR=TRUE;

/* This section just makes sure that the first 12 bytes of the */
/* file conform to the IFF FORM specification, sub-type 8SVX.  */
filehandle = Open( fname, MODE_OLDFILE );
if(filehandle)
    {
    /* Next, read the first 12 bytes to check the type */
    rdcount =Read( filehandle, iobuffer, 12L );
    if(rdcount==12L)
        {
        /* Make sure it is an IFF FORM type */
        pGH = (GroupHeader *)iobuffer;
        if(pGH->ckID == FORM)
            {
            /* Make sure it is an 8SVX sub-type */
            if(pGH->grpSubID != ID_8SVX)
                    error="Not an 8SVX file\n";
            }
        else
            error="Not an IFF FORM\n";
        }
    else
        error="Read error or file too short1\n";
    }
else
    error="Couldn't open that file. Try another.\n";

/* Read through all Chunks until BODY and VHDR */
/* Chunks are found or until an error occurs.  */
while( !error &&   (NO_BODY  ||  NO_VHDR) )
    {
    /* Read the first 8 bytes of the Chunk to get the type and size */
    rdcount =Read( filehandle, iobuffer, 8L );
    if(rdcount==8L)
        {
        pChunk=(Chunk *)iobuffer;
        switch(pChunk->ckID)
            {

            case ID_VHDR:
                /* AllocMem() ckSize rounded up and read */
                /* the VHDR, filling in the InterPlay */
                if(pChunk->ckSize & 1L)
                    pChunk->ckSize++;

                pV8Head = AllocMem(pChunk->ckSize, MEMF_PUBLIC);
                if(pV8Head)
                    {
                    rdcount=Read(filehandle,pV8Head,pChunk->ckSize);
                    if(rdcount==pChunk->ckSize )
                        {
                        if(pV8Head->sCompression==sCmpNone)
                            {
                            /* Set the playback speed */
                            play->sample_speed = (UWORD)
                                        (3579545L / pV8Head->samplesPerSec);

                            /* Set up start, end of sample data */
                            play->sample_size = pV8Head->oneShotHiSamples
                                                   + pV8Head->repeatHiSamples;
                            }
                        else error="Can't read compressed file\n";
                        }
                    else error="Read problem in header\n";

                    FreeMem(pV8Head, pChunk->ckSize );
                    }
                else error="Couldn't get header memory\n";
                NO_VHDR = FALSE;
                break;

            case ID_BODY:
                /* Technically, a VHDR could come after a BODY.*/
                /* This is a pretty unlikely occurence though. */
                if(NO_VHDR)
                    {
                    if(pChunk->ckSize & 1L)
                        pChunk->ckSize++;

                    rdcount = Seek(filehandle, pChunk->ckSize, OFFSET_CURRENT);
                    if(rdcount==-1)
                        error="Problem during BODY-skipping seek\n";
                    else
                        play->offsetBody=rdcount;
                    }
                NO_BODY = FALSE;
                break;

            default:
                /* Ignore other Chunks, skipping over them */
                if(pChunk->ckSize & 1L)
                    pChunk->ckSize++;

                rdcount = Seek(filehandle, pChunk->ckSize, OFFSET_CURRENT);
                if(rdcount==-1)
                    error="Problem during chunk-skipping seek\n";
                break;
            }
        }
    else error = "Read error or file too short2\n";
    }

if(!error)
    {
    /* In case the VHDR came after the BODY, seek back to the BODY */
    if(play->offsetBody)
        {
        rdcount = Seek(filehandle, play->offsetBody, OFFSET_BEGINNING);
        if(rdcount==-1)
            error="Couldn't seek to BODY\n";
        }

    /* OK now get the BODY data into a memory block */
    play->sample_loc = AllocMem( play->sample_size, MEMF_PUBLIC );
    if(play->sample_loc)
        {
        rdcount = Read(filehandle, play->sample_loc, play->sample_size);
        if(rdcount!=play->sample_size)
            error = "Error during BODY read\n";
        else
            play->sample_byte=play->sample_loc;
        }
    else
        error="Couldn't get memory for BODY Chunk\n";
    }

if(filehandle)
    Close(filehandle);

return(error);
}

/*---------------------------------------------------------------
**
** VOID EndParse( struct InterPlay * );
**
**   This function simply frees any memory used by an earlier
**   call to Parse8svx().
**
**---------------------------------------------------------------
*/
VOID
EndParse( struct InterPlay *play )
{
if(play->sample_loc)
    FreeMem(play->sample_loc, play->sample_size );
}

/*-----------------------------------------------------------------------------
**
** VOID FillAudio(struct InterPlay *, struct IOAudio * );
**
**   This function gets 512 bytes each from 2 BODY buffers and interleaves
**   the bytes in the audio playback buffer.
**------------------------------------------------------------------------------
*/
VOID
FillAudio(struct InterPlay *inplay, struct IOAudio *ioa )
{
struct InterPlay *play1,*play2;
ULONG remainder1,remainder2,x;
UWORD speedfac;
WORD value;

if(ioa->ioa_Request.io_Command != CMD_WRITE) /* For 1st time callers only */
    {
    /* When two files are played at once, their speeds must match.  Use  */
    /* whichever speed is fastest. Interleaved requests also require the */
    /* speed to be doubled (period is halved).  However, the period      */
    /* cannot be lower than 124 or audio DMA bandwidth will be exceeded. */
    speedfac = inplay->sample_speed;

    if(inplay->next_iplay)
        {
        if(inplay->next_iplay->sample_speed < inplay->sample_speed)
            speedfac = inplay->next_iplay->sample_speed;

        if ( !(inplay->USE_SUMMING) )
            speedfac /= 2;
        }

    if(speedfac < 124)
        speedfac = 124;

    ioa->ioa_Request.io_Command = CMD_WRITE;
    ioa->ioa_Request.io_Flags   = ADIOF_PERVOL;
    ioa->ioa_Volume             = 63;
    ioa->ioa_Period             = speedfac;
    ioa->ioa_Length             = BUF_SIZE;
    ioa->ioa_Cycles             = 1;
    }

if(inplay->next_iplay)
    {
    play1=inplay;
    play2=inplay->next_iplay;

    remainder1 = play1->sample_size - (play1->sample_byte - play1->sample_loc);
    remainder2 = play2->sample_size - (play2->sample_byte - play2->sample_loc);

    if(play1->USE_SUMMING)
        {
        /*
        ** AVERAGING LOGIC for playing TWO samples on ONE channel
        */
        for(x=0; x<BUF_SIZE ;x++)
            {
            value = 0;

            if( x<remainder1 )
                {
                value += *( (BYTE *)(play1->sample_byte) );
                play1->sample_byte++;
                }
            else if( x==remainder1 )
                play1->sample_done=1;

            if( x<remainder2 )
                {
                value += *( (BYTE *)(play2->sample_byte) );
                play2->sample_byte++;
                }
            else if( x==remainder2 )
                play2->sample_done=1;

            *(ioa->ioa_Data + x) = (UBYTE) (value/2);
            }
        }
    else
        {
        /*
        ** INTERLEAVE LOGIC for playing TWO samples on ONE channel
        */

        /* If there are more bytes in the 1st sample data file, place them in */
        /* the EVEN positions in the playback buffer of this IOAudio request. */
        for(x=0; (x<BUF_SIZE) && (x<2*remainder1); x+=2 )
            {
            *(ioa->ioa_Data + x) = *(play1->sample_byte);
            play1->sample_byte++;
            }
        /* If there are no more bytes then mark the 1st sample as done */
        if(x<BUF_SIZE)
            play1->sample_done=1L;

        while(x<BUF_SIZE)      /* Pad the playback buffer with zeroes. */
            {
            *(ioa->ioa_Data + x) = 0;
            x+=2;
            }

        /* If there are more bytes in the 2nd sample data file, place them in */
        /* the ODD positions in the playback buffer of this IOAudio request.  */
        for(x=1; (x<BUF_SIZE) && (x<2*remainder2);x+=2)
            {
            *(ioa->ioa_Data + x) = *(play2->sample_byte);
            play2->sample_byte++;
            }
        /* If there are no more bytes then mark the 2nd sample as done */
        if(x<BUF_SIZE)
            play2->sample_done=1L;

        while(x<BUF_SIZE)      /* Pad the playback buffer with zeroes. */
            {
            *(ioa->ioa_Data + x) = 0;
            x+=2;
            }
        }
    }
else
    {
    /*
    ** REGULAR LOGIC for playing a single sample on a single channel.
    */
    remainder1= inplay->sample_size - (inplay->sample_byte-inplay->sample_loc);
    if(remainder1 > BUF_SIZE)
        {
        CopyMem(inplay->sample_byte,ioa->ioa_Data,BUF_SIZE);
        inplay->sample_byte+=BUF_SIZE;
        }
    else
        {
        CopyMem(inplay->sample_byte,ioa->ioa_Data,remainder1);
        ioa->ioa_Length=remainder1;
        inplay->sample_done=1L;
        }
    }
}


VII-17/camg.c

;/* Camg.c - Execute me to compile me with SAS/C 6.56
sc NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 camg.c
slink FROM LIB:c.o,camg.o TO camg LIBRARY LIB:sc.lib,LIB:amiga.lib
quit
*/
/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

/*
 * Camg.c Demonstrates use of ILBM.CAMG value. Filters out junk CAMGs and bad
 * bits. Adapts to 2.0 and 1.3
 *
 * Note - Under 2,0, when writing a CAMG you should write the 32-bit value
 * returned by the 2.0 graphics function GetVPModeID(viewport);
 */

#include <exec/types.h>
#include <exec/libraries.h>
#include <intuition/intuition.h>
#include <graphics/displayinfo.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>

#include <stdio.h>

struct Screen  *openidscreen(SHORT wide, SHORT high, SHORT deep, ULONG modeid);
ULONG           modefallback(ULONG modeid, SHORT wide, SHORT high, SHORT deep);

#define DEBUG

struct Library *GfxBase;
struct Library *IntuitionBase;

void            main(int argc, char **argv)
{
    struct Screen  *screen;

    /*
     * Test the routines by passing various bad or possibly unavailable CAMG
     * modeid values
     */
    if (GfxBase = OpenLibrary("graphics.library", 0))
    {
        if (IntuitionBase = OpenLibrary("intuition.library", 0))
        {
            /* Junk CAMG    */
            if (screen = openidscreen(640, 400, 3, 0x12340000))
                CloseScreen(screen);

            /* Bad bits like VP_HIDE and SPRITES */
            if (screen = openidscreen(320, 400, 3, 0x00006004))
                CloseScreen(screen);

            /* Extended bit set but not a valid modeid */
            if (screen = openidscreen(320, 400, 3, 0x00009004))
                CloseScreen(screen);

            /* An ECS Mode - demonstrates modefallback if not available */
            if (screen = openidscreen(640, 400, 2, 0x00039025))
                CloseScreen(screen);

            CloseLibrary(IntuitionBase);
        }
        CloseLibrary(GfxBase);
    }
}

struct NewScreen ns = {NULL};

/*
 * simple openidscreen
 *
 * Passed width, height, depth, and modeid, attempts to open a 2.0 or 1.3 screen.
 * Demonstrates filtering out of bad CAMGs and modefallback() for unavailable
 * modes.
 */

struct Screen  *
openidscreen(SHORT wide, SHORT high, SHORT deep, ULONG modeid)
{
    extern struct Library *GfxBase;
    struct Screen  *screen = NULL;

#ifdef DEBUG
    printf("\nAsked to open screen with modeid $%08lx\n", modeid);
#endif

    /*
     * BEFORE USING A CAMG YOU HAVE READ, YOU MUST SCREEN OUT JUNK CAMGs AND
     * INAPPROPRIATE BITS IN OLD 16-BIT CAMGs. YOU MAY WANT TO PLACE THESE
     * FIRST TWO TESTS WITH YOUR CAMG-READING CODE TO SCREEN OUT BAD CAMGs
     * IMMEDIATELY.
     */

    /*
     * Knock bad bits out of old-style CAMG modes before checking availability.
     * (some ILBM CAMG's have these bits set in old 1.3 modes, and should not)
     * If not an extended monitor ID, or if marked as extended but missing
     * upper 16 bits, screen out inappropriate bits now.
     */
    if ((!(modeid & MONITOR_ID_MASK)) ||
        ((modeid & EXTENDED_MODE) && (!(modeid & 0xFFFF0000))))
        modeid &=
            (~(EXTENDED_MODE | SPRITES | GENLOCK_AUDIO | GENLOCK_VIDEO | VP_HIDE));

    /*
     * Check for bogus CAMG like some brushes have, with junk in upper word and
     * extended bit NOT set not set in lower word.
     */
    if ((modeid & 0xFFFF0000) && (!(modeid & EXTENDED_MODE)))
    {
        /*
         * Bad CAMG, so ignore CAMG and determine a mode based on based on
         * pagesize or aspect
         */
        modeid = NULL;
        if (wide >= 640)
            modeid |= HIRES;
        if (high >= 400)
            modeid |= LACE;
    }

#ifdef DEBUG
    printf("After filtering, mode is now $%08lx\n", modeid);
#endif

    /*
     * Now see if mode is available
     */
    if (GfxBase->lib_Version >= 36)
    {
        /* if mode is not available, try a fallback mode */
        if (ModeNotAvailable(modeid))
            modeid = modefallback(modeid, wide, high, deep);

        if (!(ModeNotAvailable(modeid)))         /* if mode is available */
        {
            /*
             * We have an available mode id Here you may wish to create a
             * custom, or centered, or overscan display clip based on the size
             * of the image.  Or just use one of the standard clips.
             *
             * The 2.0 Display program uses QueryOverscan to get the settings of
             * this modeid's OSCAN_TEXT, OSCAN_STANDARD, and OSCAN_MAX. Display
             * centers the screen (via TopEdge and LeftEdge) within the user's
             * closest OSCAN rectangle, and creates a display clip by using the
             * same values and then clipping the values to be within OSCAN_MAX
             * limits.  If the centered screen ends up lower than user's
             * OSCAN_TEXT settings, I move it up to same MinY as his OSCAN_TEXT
             * --- otherwise his Workbench might peek over the top.
             */

            /*
             * Now use extended OpenScreen or OpenScreenTags for this modeid.
             * (this gives you the benefit of system-supported overscan, etc.)
             */
#ifdef DEBUG
            printf("Doing OpenScreenTags of modeid $%08lx\n", modeid);
#endif
            screen = OpenScreenTags(NULL,
                                    SA_Width, wide,
                                    SA_Height, high,
                                    SA_Depth, deep,
                                    SA_DisplayID, modeid);
        }
    }

    if (!screen) /* not 2.0, or mode not
                  * available, or can't open */
    {
        /*
         * Try an old-style OpenScreen with modefallback() modeid
         */

        modeid = modefallback(modeid, wide, high, deep);

        ns.Width = wide;
        ns.Height = high;
        ns.Depth = deep;
        ns.ViewModes = modeid;

#ifdef DEBUG
        printf("Doing old OpenScreen of mode $%04lx\n", modeid);
#endif

        screen = OpenScreen(&ns);
    }

    return (screen);
}

/*
 * modefallback - passed an unavailable modeid, attempts to provide an
 * available replacement modeid to use instead
 */

ULONG
modefallback(ULONG modeid, SHORT wide, SHORT high, SHORT deep)
{
    extern struct Library *GfxBase;
    ULONG           newmodeid;

    /*
     * Here you should either be asking the user what mode they want OR
     * searching the display database and choosing an appropriate replacement
     * mode based on what you or the user deem important (colors, or aspect, or
     * size, etc.).  You could also use a built in table for modes you know
     * about, and substitute mode you wish to use when the desired mode is not
     * available.
     *
     * This simple routine simply masks out everything but old modes. This is a
     * way to get some kind of display open but not necessarily a suitable or
     * compatible display.
     */

    newmodeid = modeid & (HIRES | LACE | HAM | EXTRA_HALFBRITE);

#ifdef DEBUG
    printf("Modefallback passed 0x%08lx, returning 0x%08lx\n", modeid, newmodeid);
#endif

    return (newmodeid);
}


VII-21/Form.txt

                           CATS IFF FORM/Chunk
                            Registration Form
                           -------------------

How to register an IFF FORM or Chunk:

    * Make Sure your FORM/Chunk names follow the naming conventions in
      the document EA IFF 85 Standard for Interchange Format Files
      (available from CATS) and also in the 1.3 RKM: Includes &
      Autodocs IFF Appendix.

    * Call CATS at (215) 431-9300 to find out if you FORM/Chunk name
      conflicts with any existing name.

    * Fill out this form.

    * Mail this form and and an AmigaDOS disk containing the ASCII
      text specification of your FORMs/Chunks (plus any include files
      and sample source code) to:

          CATS - IFF Registration
          Commodore Business Machines, Inc.
          1200 Wilson Drive
          West Chester, PA 19380
          USA

==========================================================================

Date ____ /____ /____    Company Name ____________________________________

Contact __________________________________________________________________

Address __________________________________________________________________

City, State, ZIP _________________________________________________________

Telephone _____________________ CATS Developer Number ____________________

 _
|_| New Form      Name ________ Brief Description ________________________

 _
|_| New Chunk(s)  Name ________ Brief Description ________________________

for               Name ________ Brief Description ________________________
FORM: __________
                  Name ________ Brief Description ________________________

                  Name ________ Brief Description ________________________

Software Titles that support this FORM/Chunk: ____________________________

__________________________________________________________________________

Check the following that apply:

     _
    |_| Form/Chunk specification enclosed on disk

     _
    |_| Code examples enclosed on disk

     _
    |_| FORM/Chunk specification is proprietary and should not be released


VIII-31/Note.h

/*
** Note.h - Some generic external references
*/
/* (c)  Copyright 1992-1999 Amiga, Inc.   All rights reserved. */
/* The information contained herein is subject to change without    */
/* notice, and is provided "as is" without warranty of any kind,    */
/* either expressed or implied.  The entire risk as to the use of   */
/* this information is assumed by the user.                         */

extern struct Library   *IntuitionBase,
                        *SockBase;

/*
** Amiga System Includes
*/

#include <exec/types.h>
#include <exec/exec.h>
#include <dos/dos.h>
#include <dos/rdargs.h>
#include <dos/dostags.h>
#include <dos/dosextens.h>
#include <intuition/intuition.h>
#include <utility/tagitem.h>

/*
** Amiga System Prototypes
*/

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>

/*
** socket.library Includes
*/

#include <sys/types.h>
#include <sys/socket.h>
#include <ss/socket.h>
/* make sure you rename <ss/socket_pragmas.sas|manx>
to <ss/socket_pragmas.h> */
#include <ss/socket_pragmas.h>
#include <netdb.h>

/*
** ...and some generic ANSI stuff
*/

#include <stdio.h>
#include <string.h>
#include <stddef.h>
#include <stdarg.h>
#include <stdlib.h>
#include <errno.h>

/*
** The definition of the structure which is the message packet passed
** between the client and server.  This has been kept about as minimal
** as possible, but the buffers had to be designated that way to keep
** the code of the handler routines down in size.
**
** The #define's give the valid types that may be in the nn_Code field
** of the NetNote packet.
*/

struct NetNote
{
    int     nn_Code;
    int     nn_Retval;
    char    nn_Text[200],
            nn_Button[40];
};

#define NN_MSG  0
#define NN_ACK  1
#define NN_ERR  2

/*
** This definition is used in both the client and server as the name any
** entries in the INET:DB/SERVICES file will be under.
*/

#define APPNAME "notes"

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }
#endif

/*
** End of note.h
*/


VIII-31/SendNote.c

;/* sendnote.c - Execute to compile with SAS/C 6.56
sc DATA=FAR NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 sendnote.c
slink FROM LIB:c.o sendnote.o TO sendnote LIBRARY LIB:sc.lib LIB:amiga.lib
quit
*/

/* (c)  Copyright 1992-1999 Amiga, Inc.   All rights reserved. */
/* The information contained herein is subject to change without    */
/* notice, and is provided "as is" without warranty of any kind,    */
/* either expressed or implied.  The entire risk as to the use of   */
/* this information is assumed by the user.                         */

/*
** Our Application Prototypes (specific to notes.c file)
*/

void    main( int, char ** );
void    FinalExit( int );

/*
** Application-specific defines and globals
*/

char Version[] = "\0$VER: SendNote 1.2 (1.12.91)";

#define TEMPLATE    "Host/A,Text,Button"
#define OPT_HOST    0
#define OPT_TEXT    1
#define OPT_BUTTON  2
#define OPT_COUNT   3

/*
** The library bases...we need em later...
*/

struct Library *IntuitionBase, *SockBase;

/*
** All other includes and protos are indexed off our catch-all file
** note.h which both the client (sendnote.c) and server (shownote.c)
** include.
*/

#include    "note.h"

void    main(int argc, char **argv)
{
    struct RDArgs *rdargs;      /* ReadArgs() return information */

    struct sockaddr_in serv;    /* Server's Internet Address */

    struct hostent *host;       /* The located host info */

    struct NetNote out;         /* Message packet for send/recv */

    long opts[OPT_COUNT] =  {
                            0L,
                            (long)"== PING! ==",
                            (long)"OK"
                            };

    int sock;                   /* The working socket */

    char *hostnam,                  /* Arg of hostname */
         *text,                 /* Arg of text to be sent */
         *button;               /* Arg of button text */

    /*
    ** Process arguments using new (2.0) dos calls.
    */

    rdargs = (struct RDArgs *)ReadArgs( (UBYTE *)TEMPLATE, opts, NULL );
    if(rdargs == NULL)
    {
        puts("Command line not accepted!");
        FinalExit( RETURN_ERROR );
    }

    hostnam = (char *)opts[OPT_HOST];
    text = (char *)opts[OPT_TEXT];
    button  = (char *)opts[OPT_BUTTON];

    /*
    **  Open socket.library and intialize socket space
    */

    if (SockBase = OpenLibrary("inet:libs/socket.library", 0L))
    {
        setup_sockets( 1, &errno );
    }
    else
    {
        puts("Can't open socket.library!");
        FinalExit( RETURN_ERROR );
    }

    /*
    ** First we need to try and resolve the host machine as a
    ** normal IP/Internet address.  If that fails, fall back to seaching
    ** the hosts file for it.  Before anything, we need to clear out
    ** the buffer (serv) where the information will be placed, using
    ** the bzero() call (actually a macro in sys/types.h).
    */

    bzero( &serv, sizeof(struct sockaddr_in) );
    if ( (serv.sin_addr.s_addr = inet_addr(hostnam)) == INADDR_NONE )
    {
        /*
        ** Okay, the program wasnt handed a dotted decimal address,
        ** so we check and see if it was handed a machine name.
        **
        ** NOTE:  Grab the information you need before you use the
        **        gethostbyname() call again.  Subsequent calls
        **        will overwrite the buffer it hands back.
        */

        if ( (host = gethostbyname(hostnam)) == NULL )
        {
            printf("Host not found: %s\n",host);
            FinalExit( RETURN_ERROR );
        }

        /*
        ** It does indeed have a name, so copy the addr field from the
        ** hostent structure into the sockaddr structure.
        */

        bcopy( host->h_addr, (char *)&serv.sin_addr, host->h_length );
    }

/*
**  Following is commented out for ease of testing purposes!  Normally, apps
**  should obtain server numbers using this type of code and a matching entry
**  in the inet:db/services file.
**
**  {
**      struct servent *servptr;
**      char *servnam = APPNAME;
**
**      *
**      ** Open the INET:DB/SERVICES file and locate the server info
**      ** by matching the name and service.
**      *
**
**      if ((servptr = getservbyname( servnam, "tcp" )) == NULL)
**      {
**          printf("%s not in inet:db/services list!",servnam);
**          FinalExit( RETURN_ERROR );
**      }
**      serv.sin_port = servptr->s_port;
**  }
**
*/

    /*
    ** If you used the above code, you would remove this line:
    */

    serv.sin_port = 8769;

    /*
    ** This tells the system the socket in question is an Internet socket
    */

    serv.sin_family = AF_INET;

    /*
    ** Initialize the socket
    */

    if ( (sock = socket( AF_INET, SOCK_STREAM, 0 )) < 0 )
    {
        printf("socket gen: %s\n", strerror(errno));
        FinalExit( RETURN_ERROR );
    }

    /*
    ** Connect the socket to the remote socket, which belongs to the
    ** server, and which will "wake up" the server.
    */

    if ( connect( sock,
                  (struct sockaddr *)&serv,
                  sizeof(struct sockaddr) ) < 0 )
    {
        printf("connect: %s\n", strerror(errno));
        s_close( sock );
        FinalExit( RETURN_ERROR );
    }

    /*
    ** Compose the message packet for transmission
    */

    out.nn_Code = NN_MSG;
    strcpy( (char *)&out.nn_Text, text );
    strcpy( (char *)&out.nn_Button, button );

    /*
    ** Send the packet to the remote system
    */

    send( sock, (char *)&out, sizeof(struct NetNote), 0 );

    printf("\nMessage sent to %s...waiting for answer...\n", hostnam );

    /*
    ** Wait for either acknowledge or error.  This is a potential hang
    ** location if the server is mortally wounded.
    */

    recv( sock, (char *)&out, sizeof(struct NetNote), 0 );

    /*
    ** Evaluate the packet returned to us
    */

    if (out.nn_Code == NN_ACK)
    {
        printf("Response:  Button %ld pressed.\n\n", out.nn_Retval );
    }
    else
    {
        puts("Error during message send...please try again later!");
        FinalExit( RETURN_ERROR );
    }

    /*
    ** Since ReadArgs() was called inside the main() function, the pointer
    ** to the buffer it created needs to be deallocated inside main().
    */

    if (rdargs)
    {
        FreeArgs( rdargs );
    }

    FinalExit( RETURN_OK );

}

/*
**  FinalExit() - Non-returning routine which handles exits and cleanups.
**
**
*/

void    FinalExit( int retcode )
{

    /*
    ** If SockBase is non-null, it means that socket.library was opened,
    ** and a socket environment was initialized.  Remove the environment
    ** and close the library.
    */

    if (SockBase)
    {
        cleanup_sockets();
        CloseLibrary(SockBase);
    }

    /*
    ** Terminate program, handing return code out to the shell handler
    */

    exit( retcode );
}


VIII-31/ShowNote.c

;/* shownote.c - Execute to compile with SAS/C 6.56
sc DATA=FAR NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 shownote.c
slink FROM LIB:c.o shownote.o TO shownote LIBRARY LIB:sc.lib LIB:amiga.lib
quit
*/

/* (c)  Copyright 1992-1999 Amiga, Inc.   All rights reserved. */
/* The information contained herein is subject to change without    */
/* notice, and is provided "as is" without warranty of any kind,    */
/* either expressed or implied.  The entire risk as to the use of   */
/* this information is assumed by the user.                         */

/*
** Our Application Prototypes (specific to noter.c file)
*/
void    main( void );
void    TG_Init( void );
int     SS_Init( void );
int     DoER( char *, char *, char * );
void    AppPanic( char *, int );
void    HandleMsg( int );

/*
** Application-specific defines and globals
*/

char Version[] = "\0$VER: ShowNote 1.2 (1.12.91)";

/*
** The library bases...we need em later...
*/

struct Library *IntuitionBase, *SockBase;

/*
** All other includes and protos are indexed off our catch-all file
** note.h which both the client (sendnote.c) and server (shownote.c) include.
*/

#include    "note.h"

VOID    main( VOID )
{
    int     socket;         /* The socket */

    fd_set  sockmask,       /* Mask of open sockets */
            mask;           /* Return value of socketwait() */

    long    umask;          /* AmigaDOS signal mask */

    /*
    ** Call TG_Init to prepare the generic Amiga stuff for use...
    */

    TG_Init();

    /*
    ** ...and SS_Init for the socket-specific arrangements, keeping
    ** track of what it hands back.
    */

    socket = SS_Init();

    /*
    ** First, prepare the various masks for signal processing
    */

    FD_ZERO( &sockmask );
    FD_SET( socket, &sockmask );

    /*
    ** And we enter the event loop itself
    */

    while(1)
    {
        /*
        ** Reset the mask values for another pass
        */

        mask = sockmask;
        umask = SIGBREAKF_CTRL_C;

        /*
        ** selectwait is a combo network and Amiga Wait() rolled into
        ** a single call.  It allows the app to respond to both Amiga
        ** signals (CTRL-C in this case) and to network events.
        **
        ** Here, if the selectwait event is the SIGBREAK signal, we
        ** bail and AppPanic() but otherwise its a network event.
        ** This is a very crude way of handling the exit, but it
        ** is an effective one
        */

        if (selectwait( 2, &mask, NULL, NULL, NULL, &umask ) == -1 )
        {
            AppPanic("CTRL-C:\nProgram terminating!",0);
        }

        /*
        ** Since the contact between the client and server is so
        ** quick, an iterative server is adeqaute.  For cases where
        ** extended connections or concurrent connections are needed,
        ** either a state-machine or concurrent server would be a
        ** better choice.
        **/

        /*
        ** Here, we accept the pending connection (the only case
        ** possible with this mechanism) and dispatch to a routine
        ** which actually handles the client-server communication.
        */

        if (FD_ISSET( socket, &mask ))
        {
            HandleMsg( socket );
        }
        else
        {
            AppPanic("Network Signal Error!",0);
        }
    }
}

/*
**  AppPanic() - General Shutdown Routine
**
**  This routine serves to provide both a nice GUI way of indicating error
**  conditions to the user, and to handle all the aspects of shutting the
**  server down.  In a real-world application, you would probably separate
**  the error condition shutdown from the normal shutdown.  Since this is
**  an example, it would add needless complexity to the code.  Further,
**  as far as this server is concerned, shutting down _is_ an error state,
**  since SIGBREAKF_CTRL_C is a process-specific warning of shutdown.
*/

VOID    AppPanic( char *panictxt, int panicnum )
{
    char buffer[255];

    if (!panicnum)
    {
        DoER( APPNAME, panictxt, "OK" );
    }
    else
    {
        sprintf( (char *)&buffer, "%s\n\n%s", panictxt, strerror(panicnum));
        DoER( APPNAME, (char *)&buffer, "OK" );
    }
    if (SockBase)
    {
        cleanup_sockets();
        CloseLibrary(SockBase);
    }

    if (IntuitionBase)
    {
        CloseLibrary(IntuitionBase);
    }

    exit(RETURN_ERROR);

}

/*
**  DoER() - Attempt at a "generic" wrapper for EasyRequest()
**
**  Since EasyRequest(), though "easy", still requires some initialization
**  before it can be used, this routine acts as a wrapper to EasyRequest.
**  It also catches and provides a means to implement application-generic
**  values for what gets handed to the EasyRequest routine, making coding
**  just a wee bit easier.
*/
int     DoER( char *titletxt, char *msgtxt, char *btntxt )
{
    struct EasyStruct easy =    {
                                sizeof(struct EasyStruct),
                                NULL,
                                NULL,
                                NULL,
                                NULL
                                };

    int retval = 0;

    if (IntuitionBase)
    {
        if (titletxt)
        {
            easy.es_Title = titletxt;
        }
        else
        {
            easy.es_Title = APPNAME;
        }

        if (msgtxt)
        {
            easy.es_TextFormat = msgtxt;
        }
        else
        {
            easy.es_TextFormat = "Null message text!\nIsnt it?";
        }

        if (btntxt)
        {
            easy.es_GadgetFormat = btntxt;
        }
        else
        {
            easy.es_GadgetFormat = "Take off, eh!";
        }

        retval = EasyRequest( NULL, &easy, NULL, NULL );
        return (retval);
    }
}

/*
**  TG_Init() - Initializer of AOS/Intuition
**
**  This routine just handles opening Intuition, but would be a good
**  place to put any other initialization code which is specific to getting
**  an application's Amiga environment properly set up.
*/
VOID    TG_Init( VOID )
{
    IntuitionBase = OpenLibrary("intuition.library",36);
    if (!IntuitionBase)
        exit(RETURN_ERROR);
}
/*
**  SS_Init() - Initializer of shared socket library
**
**  SS_Init() handles the opening of socket.library, the formation of an
**  application-specific socket environment, and the creation of the initial
**  socket for the server.  It returns an identifier to the socket it has
**  prepared, which just happens to represent itself as an int.
*/
int     SS_Init( VOID )
{
    struct sockaddr_in  sockaddr;

    int snum, len = sizeof(sockaddr);

    /*
    ** Attempt to open socket library and initialize socket environ.
    ** If this fails, bail out to the non-returning AppPanic() routine.
    */

    /*
    ** The errno variable is a part of ANSI, and is defined in the c.o
    ** startup code.  Essentially, its where ANSI functions put their
    ** error codes when they fail.  For more information, consult a
    ** reference to ANSI C.
    */

    if (SockBase = OpenLibrary("inet:libs/socket.library",0L))
    {
        setup_sockets( 3, &errno );
    }
    else
    {
        AppPanic("Can't open socket.library!",0);
    }

    /*
    ** Open the initial socket on which incoming messages will queue for
    ** handling.  While the server is iterative, I do it this way so that
    ** SIGBREAKF_CTRL_C will continue to function.
    */

    if ((snum = socket( AF_INET, SOCK_STREAM, 0 )) == -1)
    {
        AppPanic("Socket Creation:",errno);
    }

    /*
    ** Here we clear and prepare the information to give our socket
    ** a real address on the system.
    */

    memset( &sockaddr, 0, len );
    sockaddr.sin_family = AF_INET;

    /*
    **  Following is commented out for ease of testing purposes!
    **
    **  {
    **      struct servent *servptr;
    **      char *serv = APPNAME;
    **
    **      if ((servptr = getservbyname( serv, "tcp" )) == NULL)
    **      {
    **          AppPanic("Service not in inet:db/services list!",0);
    **      }
    **      sockaddr.sin_port = servptr->s_port;
    **  }
    */

    sockaddr.sin_port = 8769;

    sockaddr.sin_addr.s_addr = INADDR_ANY;

    /*
    ** Having everything set up, we now attempt to allocate the port number
    ** for our socket.  If this fails, we bail.
    */

    if ( bind( snum, (struct sockaddr *)&sockaddr, len ) < 0 )
    {
        AppPanic("Socket Binding:",errno);
    }

    /*
    ** Okay, the socket is as ready as it gets.  Now all we need to do is to
    ** tell the system that the socket is open for business.  In an ideal
    ** world, this needs to be checked for errors, but for the scope of the
    ** example, it isnt necessary.  By the way, the '5' in the listen() call
    ** indicates the "queue size" for number of outstanding requests.
    */

    listen( snum, 5 );

    /*
    ** And last, we pass the socket number back to the main routine.
    */

    return snum;
}

/*
**  HandleMsg() - Handles client connection and message display
**
**  This is where 90% of the "function" of the program occurs.  This routine
**  connects the server to the client socket, gets the incoming message pkt,
**  acknowledges it, displays it, then terminates the client connection.
**  For doing all that, its small, a testament to how easily the actual work
**  can be done.
*/
void    HandleMsg( int sock )
{
    struct NetNote in;              /* Buffer for incoming packets */

    struct sockaddr_in saddr;       /* Socket address from accept() */
    struct in_addr sad;             /* Internet address component */

    struct hostent *hent;           /* Internet host information */

    int nsock,                      /* New socket from accept() */
        len,                        /* Length of addr from accept() */
        retv;                       /* Return value from DoER call */

    char rname[80],                 /* Buffer for titlebar string */
         *hname,                    /* Ptr to the hostname */
         *dd_addr;                  /* Ptr to the dotted-decimal address */

    /*
    ** We accept() the attempted connection on socket 'sock'
    ** which also yields the addr of the remote machine.  Then we
    ** attempt to convert the name to something meaningful.
    **
    ** First, we clear the stuff...
    */

    bzero( (char *)&rname, 80);
    bzero( (char *)&saddr, sizeof(struct sockaddr_in) );
    bzero( (char *)&sad, sizeof(struct in_addr) );
    len = sizeof(struct sockaddr_in);

    /*
    ** Then we accept the connection on the socket
    */
    /* Bug fixed 1/93: line below checked for wrong return value. Sorry Dale! */
    if (!(nsock = accept( sock, (struct sockaddr *)&saddr, &len )))
    {
        AppPanic("Accept:",errno);
    }

    /*
    ** Break the internet address out of the sockaddr_in structure and then
    ** create a dotted-decimal format string from it, for later use
    */

    sad = saddr.sin_addr;
    dd_addr = inet_ntoa(sad.s_addr);

    /*
    ** Use the internet address to find out the machine's name
    */

    if ( !(hent =
            gethostbyaddr( (char *)&sad.s_addr,
                           sizeof(struct in_addr),
                           AF_INET )))
    {
        AppPanic("Client resolution:\nAddress not in hosts db!", 0 );
    }
    hname = hent->h_name;

    /*
    ** Form the string which goes into the title bar using name & address
    */

    sprintf( rname, "FROM: %s (%s)", hname, dd_addr );

    /*
    ** Okay, now the waiting packet needs to be removed from the connected
    ** socket that accept() gave back to us.  Verify its of type NN_MSG and
    ** if not, set return type to NN_ERR.  If it is, then display it and
    ** return an NN_ACK message.
    */

    recv( nsock, (char *)&in, sizeof(struct NetNote), 0 );
    if (in.nn_Code == NN_MSG)
    {
        DisplayBeep(NULL);
        DisplayBeep(NULL);
        retv = DoER( rname, (char *)&in.nn_Text, (char *)&in.nn_Button );
        in.nn_Code = NN_ACK;
        in.nn_Retval = retv;
    }
    else
    {
        in.nn_Code = NN_ERR;
    }

    /*
    ** Having dealt with the message one way or the other, send the message
    ** back at the remote, then disconnect from the remote and return.
    */

    send( nsock, (char *)&in, sizeof(struct NetNote), 0 );
    s_close( nsock );

}


VIII-51: SANA-II Network Device Driver Specification

SANA-II Developer Support Package  - May 21, 1992
--------------------------------------------------
Commodore-Amiga Networking Group

All files in this archive are (C) Copyright 1992-1999 Amiga, Inc.

Warning
-------

The information contained herein is subject to change without
notice. Amiga specifically does not make any endorsement or
representation with respect to the use, results, or performance of
the information (including without limitation its capabilities,
appropriateness, reliability, currentness or availability).

Disclaimer
----------

This information is provided "As Is" without warranty of any
kind, either express or implied.  The entire risk as to the use of
this information is assumed by the user.  In no event will
Amiga or its affiliated companies be liable for any damages,
direct, indirect, incidental, special or consequential, resulting
from any claim arising out of the information presented herein,
even if it has been advised of the possibility of such damages.
Some states do not allow the exclusion or limitation of such
implied warranties, so the above limitations may not apply.

----------------------------------------------------------------------
All the files in this archive are freely redistributable as long as
the above Copyright, Warning and Disclaimer are present in all copies.
----------------------------------------------------------------------

This archive contains the following files:

  readme  ............. this file.
  standard.txt  ....... The SANA-II spec itself.
  changes.txt  ........ changes from the previous preliminary spec.
  ethernet.txt  ....... useful ethernet information for programmers.
  ARCNET.txt  ......... useful ARCNET information for programmers.
  copybuff.doc  ....... autodocs for application provided functions.
  sana2device.doc ..... autodoc for SANA-II device functions.
  sana2specialstats.h . includes
  sana2.h ............. includes
  sana2specialstats.i . includes
  sana2.i ............. includes
  a2060.device ........ (BETA) SANA-II driver for CBM A2060 card.
  a2065.device ........ SANA-II driver for CBM A2065 card.

                      ------- NOTE NOTE -------

Developers, please note ...  The standard system location for SANA-II
network device drivers is in a directory called 'sana2' which exists
in the "DEVS:" directory.  Example:

devs:sana2/a2065.device

This is the official location for these drivers. It may be necessary
for your install programs/scripts to create this directory.

                      ------- NOTE NOTE -------

The included A2060 device driver is a BETA driver and should be dealt
with accordingly. At the time of this writing the driveer has NOT
received the testing that it should.  You can get our attention on
this subject via email to 'networking@cbmvax.commodore.com'. Please
let us know of any problems so we can fix them a.s.a.p.

                      ----- QUESTIONS ??? -----

Bug reports and enhancement requests may be submitted as follows:

  Please clearly state that the subsystem is "sana2".

  If possible, generate your reports using the Amiga "Report"
  program (distributed on the 2.0 Native Developer Update
  Software Toolkit II disk).

  (When sending enhancement requests, substitute "suggestions" for
  "bugs" in the following addresses)

Mail:

  European registered developers send reports to their support
  manager.

  U.S./others mail to: Amiga Software Engineering,
                       ATTN: BUG REPORTS,
                       CBM,
                       1200 Wilson Drive,
                       West Chester, PA., 19380, USA

  European ADSP users: Post bugs to adsp.bugs

UUCP:

  to uunet!cbmvax!bugs OR rutgers!cbmvax!bugs OR bugs@commodore.COM
  (enhancement requests to cbmvax!suggestions instead of cbmvax!bugs)

  For technical questions regarding SANA-2 implementation, send to
  networking@cbmvax.commodore.com

BIX:

  Post bugs in the appropriate bugs topic of your closed conference.
  Non-registered developer, post in BIX amiga.dev bugs or suggestions.


VIII-51/include/devices/sana2.h

#ifndef SANA2_SANA2DEVICE_H
#define SANA2_SANA2DEVICE_H 1
/*
**	$Filename: devices/sana2.h $
**	$Revision: 1.10 $
**	$Date: 92/01/10 15:10:05 $
**
**	Structure definitions for SANA-II devices.
**
**	(C) Copyright 1991-1999 Amiga, Inc.
**		All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef EXEC_PORTS_H
#include <exec/ports.h>
#endif

#ifndef EXEC_IO_H
#include <exec/io.h>
#endif

#ifndef EXEC_ERRORS_H
#include <exec/errors.h>
#endif

#ifndef DEVICES_TIMER_H
#include <devices/timer.h>
#endif

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

#define SANA2_MAX_ADDR_BITS	(128)
#define SANA2_MAX_ADDR_BYTES	((SANA2_MAX_ADDR_BITS+7)/8)

struct IOSana2Req
{
    struct IORequest ios2_Req;
    ULONG ios2_WireError;		/* wire type specific error	*/
    ULONG ios2_PacketType;		/* packet type			*/
    UBYTE ios2_SrcAddr[SANA2_MAX_ADDR_BYTES];	/* source addr	*/
    UBYTE ios2_DstAddr[SANA2_MAX_ADDR_BYTES];	/* dest address	*/
    ULONG ios2_DataLength;		/* length of packet data	*/
    VOID *ios2_Data;		/* packet data			*/
    VOID *ios2_StatData;		/* statistics data pointer	*/
    VOID *ios2_BufferManagement;	/* see SANA-II OpenDevice adoc	*/
};

/*
** defines for the ios2_Flags field
*/
#define SANA2IOB_RAW	(7)		/* raw packet IO requested	*/
#define SANA2IOF_RAW	(1<<SANA2IOB_RAW)

#define	SANA2IOB_BCAST	(6)		/* broadcast packet (received)	*/
#define	SANA2IOF_BCAST	(1<<SANA2IOB_BCAST)

#define	SANA2IOB_MCAST	(5)		/* multicast packet (received)	*/
#define	SANA2IOF_MCAST	(1<<SANA2IOB_MCAST)

#define SANA2IOB_QUICK	(IOB_QUICK)	/* quick IO requested (0)	*/
#define SANA2IOF_QUICK	(IOF_QUICK)

/*
** defines for OpenDevice() flags
*/
#define SANA2OPB_MINE	(0)		/* exclusive access requested	*/
#define SANA2OPF_MINE	(1<<SANA2OPB_MINE)

#define SANA2OPB_PROM	(1)		/* promiscuous mode requested	*/
#define SANA2OPF_PROM	(1<<SANA2OPB_PROM)

/*
** defines for OpenDevice() tags
*/
#define S2_Dummy	(TAG_USER + 0xB0000)

#define S2_CopyToBuff	(S2_Dummy + 1)
#define S2_CopyFromBuff	(S2_Dummy + 2)

struct Sana2DeviceQuery
{
/*
** Standard information
*/
    ULONG	SizeAvailable;		/* bytes available		*/
    ULONG	SizeSupplied;		/* bytes supplied		*/
    ULONG	DevQueryFormat;		/* this is type 0		*/
    ULONG	DeviceLevel;		/* this document is level 0	*/
/*
** Common information
*/
    UWORD	AddrFieldSize;		/* address size in bits		*/
    ULONG	MTU;			/* maximum packet data size	*/
    ULONG	BPS;			/* line rate (bits/sec)		*/
    ULONG	HardwareType;		/* what the wire is		*/
/*
** Format specific information
*/
};

/*
** defined Hardware types
**
**  If your hardware type isn't listed below contact CATS to get a new
**  type number added for your hardware.
*/
#define S2WireType_Ethernet		1
#define S2WireType_IEEE802		6
#define S2WireType_Arcnet		7
#define S2WireType_LocalTalk		11

#define S2WireType_AmokNet		200

#define S2WireType_PPP			253
#define S2WireType_SLIP			254
#define S2WireType_CSLIP		255

struct Sana2PacketTypeStats
{
    ULONG PacketsSent;		/* transmitted count		*/
    ULONG PacketsReceived;		/* received count		*/
    ULONG BytesSent;		/* bytes transmitted count	*/
    ULONG BytesReceived;		/* bytes received count		*/
    ULONG PacketsDropped;		/* packets dropped count	*/
};

struct Sana2SpecialStatRecord
{
    ULONG Type;			/* statistic identifier		*/
    ULONG Count;			/* the statistic		*/
    char *String;			/* statistic name		*/
};

struct Sana2SpecialStatHeader
{
    ULONG RecordCountMax;		/* room available		*/
    ULONG RecordCountSupplied;	/* number supplied		*/
    /* struct Sana2SpecialStatRecord[RecordCountMax]; */
};

struct Sana2DeviceStats
{
    ULONG PacketsReceived;		/* received count		*/
    ULONG PacketsSent;		/* transmitted count		*/
    ULONG BadData;			/* bad packets received		*/
    ULONG Overruns;			/* hardware miss count		*/
    ULONG UnknownTypesReceived;	/* orphan count			*/
    ULONG Reconfigurations;		/* network reconfigurations	*/
    struct timeval LastStart;	/* time of last online		*/
};

/*
** Device Commands
*/
#define S2_START		(CMD_NONSTD)

#define S2_DEVICEQUERY		(S2_START+ 0)
#define S2_GETSTATIONADDRESS	(S2_START+ 1)
#define S2_CONFIGINTERFACE	(S2_START+ 2)
#define S2_ADDMULTICASTADDRESS	(S2_START+ 5)
#define S2_DELMULTICASTADDRESS	(S2_START+ 6)
#define S2_MULTICAST		(S2_START+ 7)
#define S2_BROADCAST		(S2_START+ 8)
#define S2_TRACKTYPE		(S2_START+ 9)
#define S2_UNTRACKTYPE		(S2_START+10)
#define S2_GETTYPESTATS		(S2_START+11)
#define S2_GETSPECIALSTATS	(S2_START+12)
#define S2_GETGLOBALSTATS	(S2_START+13)
#define S2_ONEVENT		(S2_START+14)
#define S2_READORPHAN		(S2_START+15)
#define S2_ONLINE		(S2_START+16)
#define S2_OFFLINE		(S2_START+17)

#define S2_END			(S2_START+18)

/*
** defined errors for ios2_Error  (see also <exec/errors.h>)
*/
#define S2ERR_NO_ERROR		0	/* peachy-keen			*/
#define S2ERR_NO_RESOURCES	1	/* resource allocation failure	*/
#define S2ERR_BAD_ARGUMENT	3	/* garbage somewhere		*/
#define S2ERR_BAD_STATE		4	/* inappropriate state		*/
#define S2ERR_BAD_ADDRESS	5	/* who?				*/
#define	S2ERR_MTU_EXCEEDED	6	/* too much to chew		*/
#define S2ERR_NOT_SUPPORTED	8	/* hardware can't support cmd	*/
#define S2ERR_SOFTWARE		9	/* software error detected	*/
#define S2ERR_OUTOFSERVICE	10	/* driver is OFFLINE		*/
/*
** From <exec/errors.h>
**
**	IOERR_OPENFAIL	 (-1) * device/unit failed to open *
**	IOERR_ABORTED	 (-2) * request terminated early [after AbortIO()] *
**	IOERR_NOCMD	 (-3) * command not supported by device *
**	IOERR_BADLENGTH	 (-4) * not a valid length (usually IO_LENGTH) *
**	IOERR_BADADDRESS (-5) * invalid address (misaligned or bad range) *
**	IOERR_UNITBUSY	 (-6) * device opens ok, but requested unit is busy *
**	IOERR_SELFTEST   (-7) * hardware failed self-test *
*/

/*
** defined errors for ios2_WireError
*/
#define S2WERR_GENERIC_ERROR	0	/* no specific info available	*/
#define	S2WERR_NOT_CONFIGURED	1	/* unit not configured		*/
#define S2WERR_UNIT_ONLINE	2	/* unit is currently online	*/
#define S2WERR_UNIT_OFFLINE	3	/* unit is currently offline	*/
#define	S2WERR_ALREADY_TRACKED	4	/* protocol already tracked	*/
#define	S2WERR_NOT_TRACKED	5	/* protocol not tracked		*/
#define S2WERR_BUFF_ERROR	6	/* buff mgt func returned error	*/
#define S2WERR_SRC_ADDRESS	7	/* source address problem	*/
#define S2WERR_DST_ADDRESS	8	/* destination address problem	*/
#define S2WERR_BAD_BROADCAST	9	/* broadcast address problem	*/
#define S2WERR_BAD_MULTICAST	10	/* multicast address problem	*/
#define S2WERR_MULTICAST_FULL	11	/* multicast address list full	*/
#define S2WERR_BAD_EVENT	12	/* unsupported event class      */
#define S2WERR_BAD_STATDATA	13	/* statdata failed sanity check */
#define S2WERR_IS_CONFIGURED	15	/* attempt to config twice      */
#define S2WERR_NULL_POINTER	16	/* null pointer detected        */

/*
** defined events
*/
#define	S2EVENT_ERROR		(1L<<0)	/* error catch all		*/
#define	S2EVENT_TX		(1L<<1)	/* transmitter error catch all	*/
#define	S2EVENT_RX		(1L<<2)	/* receiver error catch all	*/
#define	S2EVENT_ONLINE		(1L<<3)	/* unit is in service		*/
#define	S2EVENT_OFFLINE		(1L<<4)	/* unit is not in service	*/
#define	S2EVENT_BUFF		(1L<<5)	/* buff mgt function error	*/
#define S2EVENT_HARDWARE	(1L<<6)	/* hardware error catch all	*/
#define S2EVENT_SOFTWARE	(1L<<7)	/* software error catch all	*/

#endif	/* SANA2_SANA2DEVICE_H */


Developer Support Package / sana2device.doc

TABLE OF CONTENTS

   sana2.device/AbortIO
   sana2.device/CloseDevice
   sana2.device/CMD_CLEAR
   sana2.device/CMD_FLUSH
   sana2.device/CMD_INVALID
   sana2.device/CMD_READ
   sana2.device/CMD_RESET
   sana2.device/CMD_START
   sana2.device/CMD_STOP
   sana2.device/CMD_UPDATE
   sana2.device/CMD_WRITE
   sana2.device/OpenDevice
   sana2.device/S2_ADDMULTICASTADDRESS
   sana2.device/S2_BROADCAST
   sana2.device/S2_CONFIGINTERFACE
   sana2.device/S2_DELMULTICASTADDRESS
   sana2.device/S2_DEVICEQUERY
   sana2.device/S2_GETGLOBALSTATS
   sana2.device/S2_GETSPECIALSTATS
   sana2.device/S2_GETSTATIONADDRESS
   sana2.device/S2_GETTYPESTATS
   sana2.device/S2_MULTICAST
   sana2.device/S2_OFFLINE
   sana2.device/S2_ONEVENT
   sana2.device/S2_ONLINE
   sana2.device/S2_READORPHAN
   sana2.device/S2_TRACKTYPE
   sana2.device/S2_UNTRACKTYPE


sana2.device/AbortIO

NAME
    AbortIO -- Remove an existing device request.

SYNOPSIS
    error = AbortIO(Sana2Req)
    D0              A1

    LONG AbortIO(struct IOSana2Req *);

FUNCTION
    This is an exec.library call.

    This function aborts an ioRequest. If the request is active, it may or
    may not be aborted. If the request is queued it is removed. The
    request will be returned in the same way as if it had normally
    completed.  You must WaitIO() after AbortIO() for the request to
    return.

INPUTS
    Sana2Req        - Sana2Req to be aborted.

RESULTS
    error           - Zero if the request was aborted, non-zero otherwise.
                      io_Error in Sana2Req will be set to IOERR_ABORTED
                      if it was aborted.

NOTES

SEE ALSO
    exec.library/AbortIO(), exec.library/WaitIO()

BUGS


sana2.device/CloseDevice

NAME
    CloseDevice -- Close the device.

SYNOPSIS
    CloseDevice(Sana2Req)
                A1

    void CloseDevice(struct IOSana2Req *);

FUNCTION
    This function is called by exec.library CloseDevice().

    This function performs whatever cleanup is required at device closes.

    Note that all IORequests MUST be complete before closing. If any are
    pending, your program must AbortIO() then WaitIO() each outstanding
    IORequest to complete them.

INPUTS
    Sana2Req        - Pointer to IOSana2Req initialized by OpenDevice().

NOTES

SEE ALSO
    exec.library/CloseDevice(), exec.library/OpenDevice()

BUGS


sana2.device/CMD_CLEAR

NAME
    Clear -- Clear internal network interface read buffers.

FUNCTION
    There are no device internal buffers, so CMD_CLEAR does not apply to
    this class of device.

IO REQUEST
    ios2_Command    - CMD_CLEAR.

RESULTS
    ios2_Error      - IOERR_NOCMD.

NOTES

SEE ALSO

BUGS


sana2.device/CMD_FLUSH

NAME
    Flush -- Clear all queued I/O requests for the SANA-II device.

FUNCTION
    This command aborts all I/O requests in both the read and write
    request queues of the device.  All pending I/O requests are
    returned with an error message (IOERR_ABORTED).  CMD_FLUSH does not
    affect active requests.

IO REQUEST
    ios2_Command    - CMD_FLUSH.

RESULTS
    ios2_Error      - Zero if successful; non-zero otherwise.

NOTES

SEE ALSO

BUGS


sana2.device/CMD_INVALID

NAME
    Invalid -- Return with error IOERR_NOCMD.

FUNCTION
    This command causes device driver to reply with an error IOERR_NOCMD
    as defined in <exec/errors.h> indicating the command is not supported.

IO REQUEST
    ios2_Command    - CMD_INVALID.

RESULTS
    ios2_Error      - IOERR_NOCMD.

NOTES

SEE ALSO

BUGS
    Not known to be useful.


sana2.device/CMD_READ

NAME
    Read -- Get a packet from the network.

FUNCTION
    Get the next packet available of the requested packet type. The data
    copied (via a call to the requestor-provided CopyToBuffer function)
    into ios2_Data is normally the Data Link Layer packet data only. If
    bit SANA2IOB_RAW is set in ios2_Flags, then the entire physical frame
    will be returned.

    Unlike most Exec devices, SANA-II device drivers do not have internal
    buffers.  If you wish to read data from a SANA-II device you should
    have multiple CMD_READ requests pending at any given time.  The
    functions provided by you the requestor will be used for any incoming
    packets of the type you've requested.  If no read requests are
    outstanding for a type which comes in and no read_orphan requests are
    outstanding, the packet will be lost.

IO REQUEST
    ios2_Command    - CMD_READ
    ios2_Flags      - Supported flags are:
                        SANA2IOB_RAW
                        SANA2IOB_QUICK
    ios2_PacketType - Packet type desired.
    ios2_Data       - Abstract data structure to hold packet data.

RESULTS
    ios2_Error      - Zero if successful; non-zero otherwise.
    ios2_WireError  - More specific error number.
    ios2_Flags      - The following flags may be returned:
                        SANA2IOB_RAW
                        SANA2IOB_BCAST
                        SANA2IOB_MCAST
    ios2_SrcAddr    - Source interface address of packet.
    ios2_DstAddr    - Destination interface address of packet.
    ios2_DataLength - Length of packet data.
    ios2_Data       - Abstract data structure which packet data is
                      contained in.

NOTES
    The driver may not directly examine or modify anything pointed to by
    ios2_Data.  It *must* use the requester-provided functions to access
    this data.

SEE ALSO
    S2_READORPHAN, CMD_WRITE, any_protocol/CopyToBuffer

BUGS


sana2.device/CMD_RESET

NAME
    Reset -- Reset the network interface to initialized state.

FUNCTION
    Currently, SANA-II devices can only be configured once (with
    CMD_CONFIGINTERFACE) and cannot be re-configured, hence,
    CMD_RESET does not apply to this class of device.

IO REQUEST
    ios2_Command    - CMD_RESET.

RESULTS
    ios2_Error      - IOERR_NOCMD.

NOTES

SEE ALSO

BUGS


sana2.device/CMD_START

NAME
    Start -- Restart device operation.

FUNCTION
    There is no way for the driver to keep queuing requests without
    servicing them, so CMD_STOP does not apply to this class of device.
    S2_OFFLINE and S2_ONLINE do perform a similar function to CMD_STOP
    and CMD_START

IO REQUEST
    ios2_Command    - CMD_START.

RESULTS
    ios2_Error      - IOERR_NOCMD.

NOTES

SEE ALSO
    S2_ONLINE, S2_OFFLINE

BUGS


sana2.device/CMD_STOP

NAME
    Stop -- Pause device operation.

FUNCTION
    There is no way for the driver to keep queuing requests without
    servicing them, so CMD_STOP does not apply to this class of device.
    S2_OFFLINE and S2_ONLINE do perform a similar function to CMD_STOP
    and CMD_START

IO REQUEST
    ios2_Command    - CMD_STOP.

RESULTS
    ios2_Error      - IOERR_NOCMD.

NOTES

SEE ALSO
    S2_ONLINE, S2_OFFLINE

BUGS


sana2.device/CMD_UPDATE

NAME
    Update -- Force packets out to device.

FUNCTION
    Since there are no device internal buffers, CMD_UPDATE does not
    apply to this class of device.

IO REQUEST
    ios2_Command    - CMD_UPDATE.

RESULTS
    ios2_Error      - IOERR_NOCMD.

NOTES

SEE ALSO

BUGS


sana2.device/CMD_WRITE

NAME
    Write -- Send packet to the network.

FUNCTION
    This command causes the packet to be sent to the specified network
    interface. Normally, appropriate packet header and trailer information
    will be added to the packet data when it is sent.  If bit SANA2IOB_RAW
    is set in io_Flags, then the ios2_Data is assumed to contain an entire
    physical frame and will be sent (copied to the wire via
    CopyFromBuffer() unmodified.

    Note that the device should not check to see if the destination
    address is on the local hardware.  Network protocols should realize
    that the packet has a local destination long before it gets to a
    SANA-II driver.

IO REQUEST
    ios2_Command    - CMD_WRITE.
    ios2_Flags      - Supported flags are:
                        SANA2IOB_RAW
                        SANA2IOB_QUICK
    ios2_PacketType - Packet type to send.
    ios2_DstAddr    - Destination interface address for this packet.
    ios2_DataLength - Length of the Data to be sent.
    ios2_Data       - Abstract data structure which packet data is
                      contained in.

RESULTS
    ios2_Error      - Zero if successful; non-zero otherwise.
    ios2_WireError  - More specific error number.

NOTES
    The driver may not directly examine or modify anything pointed to by
    ios2_Data.  It *must* use the requester-provided functions to access
    this data.

SEE ALSO
    CMD_READ, S2_BROADCAST, S2_MULTICAST, any_protocol/CopyFromBuffer

BUGS


sana2.device/OpenDevice

NAME
    Open -- Request an opening of the network device.

SYNOPSIS
    error = OpenDevice(unit, IOSana2Req, flags)
    D0                 D0    A1          D1

    BYTE OpenDevice(ULONG, struct IOSana2Req *, ULONG);

FUNCTION
    This function is called by exec.library OpenDevice().

    This function performs whatever initialization is required per
    device open and initializes the Sana2Req for use by the
    device.

INPUTS
    unit            - Device unit to open.
    Sana2Req        - Pointer to IOSana2Req structure to be initialized by
                      the sana2.device.
    flags           - Supported flags are:
                            SANA2OPB_MINE
                            SANA2OPB_PROM
    ios2_BufferManagement   - A pointer to a tag list containing
                              pointers to buffer management functions.

RESULTS
    error           - same as io_Error
    io_Error        - Zero if successful; non-zero otherwise.
    io_Device       - A pointer to whatever device will handle the calls
                      for this unit.  This pointer may be different
                      depending on what unit is requested.
    ios2_BufferManagement   - A pointer to device internal information
                              used to call buffer management functions.

NOTES

SEE ALSO
    exec.library/OpenDevice(), exec.library/CloseDevice()

BUGS


sana2.device/S2_ADDMULTICASTADDRESS

NAME
    AddMulticastAddress -- Enable an interface multicast address.

FUNCTION
    This command causes the device driver to enable multicast packet
    reception for the requested address.

IO REQUEST
    ios2_Command    - S2_ADDMULTICASTADDRESS.
    ios2_SrcAddr    - Multicast address to enable.

RESULTS
    ios2_Error      - Zero if successful; non-zero otherwise.
    ios2_WireError  - More specific error number.

NOTES
    Multicast addresses are added globally -- anyone using the device
    may receive packets as a result of any multicast address which has
    been added for the device.

    Since multicast addresses are not "bound" to a particular packet type,
    each enabled multicast address has an "enabled" count associated with
    it so that if two protocols add the same multicast address and later
    one removes it, it is still enabled until the second removes it.

SEE ALSO
    S2_MULTICAST, S2_DELMULTICASTADDRESS

BUGS


sana2.device/S2_BROADCAST

NAME
    Broadcast -- Broadcast a packet on network.

FUNCTION
    This command works the same as CMD_WRITE except that it also performs
    whatever special processing of the packet is required to do a
    broadcast send. The actual broadcast mechanism is neccessarily
    network/interface/device specific.

IO REQUEST
    ios2_Command    - S2_BROADCAST.
    ios2_Flags      - Supported flags are:
                            SANA2IOB_RAW
                            SANA2IOB_QUICK
    ios2_PacketType - Packet type to send.
    ios2_DataLength - Length of the Data to be sent.
    ios2_Data       - Abstract data structure which packet data is
                      contained in.

RESULTS
    ios2_DstAddr    - The contents of this field are to be
                      considered trash upon return of the IOReq.
    ios2_Error      - Zero if successful; non-zero otherwise.
                      This command can fail for many reasons and
                      is not supported by all networks and/or
                      network interfaces.
    ios2_WireError  - More specific error number.

NOTES
    The DstAddr field may be trashed by the driver because this function
    may be implemented by filling DstAddr with a broadcast address and
    internally calling CMD_WRITE.

SEE ALSO
    CMD_WRITE, S2_MULTICAST

BUGS


sana2.device/S2_CONFIGINTERFACE

NAME
    ConfigInterface -- Configure the network interface.

FUNCTION
    This command causes the device driver to initialize the interface
    hardware and to set the network interface address to the address in
    ios2_SrcAddr. This command can only be executed once and, if
    successful, will leave the driver and network interface fully
    operational and the network interface in ios2_SrcAddr.

    To set the interface address to the factory address, the network
    management software must use GetStationAddress first and then call
    ConfigInterface with the result. If there is no factory address then
    the network software must pick an address to use.

    Until this command is executed the device will not listen for any
    packets on the hardware.

IO REQUEST
    ios2_Command    - S2_CONFIGINTERFACE.
    ios2_Flags      - Supported flags are:
                            SANA2IOB_QUICK
    ios2_SrcAddr    - Address for this interface.

RESULTS
    ios2_Error      - Zero if successful; non-zero otherwise.
    ios2_WireError  - More specific error number.
    ios2_SrcAddr    - Address of this interface as configured.

NOTES
    Some networks have the interfaces choose a currently unused interface
    address each time the interface is initialized. The caller must check
    ios2_SrcAddr for the actual interface address after configuring the
    interface.

SEE ALSO
    S2_GETSTATIONADDRESS

BUGS


sana2.device/S2_DELMULTICASTADDRESS

NAME
    DelMultiCastAddress -- Disable an interface multicast address.

FUNCTION
    This command causes device driver to disable multicast packet
    reception for the requested address.

    It is an error to disable a multicast address that is not enabled.

IO REQUEST
    ios2_Command    - S2_DELMULTICASTADDRESS
    ios2_SrcAddr    - Multicast address to disable.

RESULTS
    ios2_Error      - Zero if successful; non-zero otherwise.
    ios2_WireError  - More specific error number.

NOTES
    Multicast addresses are added globally -- anyone using the device
    may receive packets as a result of any multicast address which has
    been added for the device.

    Since multicast addresses are not "bound" to a particular packet type,
    each enabled multicast address has an "enabled" count associated with
    it so that if two protocols add the same multicast address and later
    one removes it, it is still enabled until the second removes it.

SEE ALSO
    S2_ADDMULTICASTADDRESS

BUGS


sana2.device/S2_DEVICEQUERY

NAME
    DeviceQuery -- Return parameters for this network interface.

FUNCTION
    This command causes the device driver to report information about the
    device. Up to SizeAvailable bytes of the information is copied
    into a buffer pointed to by ios2_StatData. The format of the data is
    as follows:

        struct Sana2DeviceQuery
        {
        /*
        ** Standard information
        */
            ULONG SizeAvailble; /* bytes available */
            ULONG SizeSupplied; /* bytes supplied */
            LONG  DevQueryFormat;   /* this is type 0 */
            LONG  DeviceLevel;      /* this document is level 0 */

        /*
        ** Common information
        */
            UWORD AddrFieldSize;    /* address size in bits */
            ULONG MTU;              /* maximum packet data size */
            LONG  bps;              /* line rate (bits/sec) */
            LONG  HardwareType;     /* what the wire is */

        /*
        ** Format specific information
        */
        };

    The SizeAvailable specifies the number of bytes that the caller
    is prepared to accomodate, including the standard information fields.

    SizeSupplied is the number of bytes actually supplied,
    including the standard information fields, which will not exceed
    SizeAvailable.

    <devices/sana2.h> includes constants for these values.  If your
    hardware does not have a number assigned to it, you must contact
    CATS to get a hardware number.

IO REQUEST
    ios2_Command    - S2_DEVICEQUERY.
    ios2_StatData   - Pointer to Sana2DeviceQuery structure to fill in.

RESULTS
    ios2_Error      - Zero if successful; non-zero otherwise.
    ios2_WireError  - More specific error number.

NOTES

SEE ALSO

BUGS


sana2.device/S2_GETGLOBALSTATS

NAME
    GetGlobalStats -- Get interface accumulated statistics.

FUNCTION
    This command causes the device driver to retrieve various global
    runtime statistics for this network interface. The format of the
    data returned is as follows:

        struct Sana2DeviceStats
        {
            ULONG PacketsReceived;
            ULONG PacketsSent;
            ULONG BadData;
            ULONG Overruns;
            ULONG UnknownTypesReceived;
            ULONG Reconfigurations;
            timeval LastStart;
        };

IO REQUEST
    ios2_Command    - S2_GETGLOBALSTATS.
    ios2_StatData   - Pointer to Sana2DeviceStats structure to fill.

RESULTS
    ios2_Error      - Zero if successful; non-zero otherwise.
    ios2_WireError  - More specific error number.

NOTES

SEE ALSO
    S2_GETSPECIALSTATS

BUGS


sana2.device/S2_GETSPECIALSTATS

NAME
    GetSpecialStats -- Get network type specific statistics.

FUNCTION
    This function returns statistics which are specific to the type of
    network medium this driver controls. For example, this command could
    return statistics common to all Ethernets which are not common to all
    network mediums in general.

    The supplied Sana2SpecialStatData structure is given below:

        struct Sana2SpecialStatData
        {
            ULONG RecordCountMax;
            ULONG RecordCountSupplied;
            struct Sana2StatRecord[RecordCountMax];
        };

    The format of the data returned is:

        struct Sana2StatRecord
        {
            ULONG Type;     /* commodore registered */
            LONG Count;     /* the stat itself */
            char *String;   /* null terminated */
        };

    The RecordCountMax field specifies the number of records that the
    caller is prepared to accomodate.

    RecordCountSupplied is the number of record actually supplied which
    will not exceed RecordCountMax.

IO REQUEST
    ios2_Command    - S2_GETSPECIALSTATS.
    ios2_StatData   - Pointer to a Sana2SpecialStatData structure to fill.
                      RecordCountMax must be initialized.

RESULTS
    ios2_Error      - Zero if successful; non-zero otherwise.
    ios2_WireError  - More specific error number.

NOTES
    Commodore will maintain registered statistic Types.

SEE ALSO
    S2_GETGLOBALSTATS, <devices/sana2specialstats.h>

BUGS


sana2.device/S2_GETSTATIONADDRESS

NAME
    GetStationAddress -- Get default and interface address.

FUNCTION
    This command causes the device driver to copy the current interface
    address into ios2_SrcAddr, and to copy the factory default station
    address (if any) into ios2_DstAddr.

IO REQUEST
    ios2_Command    - S2_GETSTATIONADDRESS.

RESULTS
    ios2_Error      - Zero if successful; non-zero otherwise.
    ios2_WireError  - More specific error number.
    ios2_SrcAddr    - Current interface address.
    ios2_DstAddr    - Default interface address (if any).

NOTES

SEE ALSO
    S2_CONFIGINTERFACE

BUGS


sana2.device/S2_GETTYPESTATS

NAME
    GetTypeStats -- Get accumulated type specific statistics.

FUNCTION
    This command causes the device driver to retrieve various packet type
    specific runtime statistics for this network interface. The format of
    the data returned is as follows:

        struct Sana2TypeStatData
        {
            LONG PacketsSent;
            LONG PacketsReceived;
            LONG BytesSent;
            LONG BytesReceived;
            LONG PacketsDropped;
        };

IO REQUEST
    ios2_Command    - S2_GETTYPESTATS.
    ios2_PacketType - Packet type of interest.
    ios2_StatData   - Pointer to TypeStatData structure to fill in.

RESULTS
    ios2_Error      - Zero if successful; non-zero otherwise.
    ios2_WireError  - More specific error number.

NOTES
    Statistics for a particular packet type are only available while that
    packet type is being ``tracked''.

SEE ALSO
    S2_TRACKTYPE, S2_UNTRACKTYPE

BUGS


sana2.device/S2_MULTICAST

NAME
    Multicast -- Multicast a packet on network.

FUNCTION
    This command works the same as CMD_WRITE except that it also performs
    whatever special processing of the packet is required to do a
    multicast send. The actual multicast mechanism is neccessarily
    network/interface/device specific.

IO REQUEST
    ios2_Command    - S2_MULTICAST.
    ios2_Flags      - Supported flags are:
                            SANA2IOB_RAW
                            SANA2IOB_QUICK
    ios2_PacketType - Packet type to send.
    ios2_DstAddr    - Destination interface address for this packet.
    ios2_DataLength - Length of the Data to be sent.
    ios2_Data       - Abstract data structure which packet data is
                      contained in.

RESULTS
    ios2_Error      - Zero if successful; non-zero otherwise.
                      This command can fail for many reasons and
                      is not supported by all networks and/or
                      network interfaces.
    ios2_WireError  - More specific error number.

NOTES
    The address supplied in ios2_DstAddr will be sanity checked (if
    possible) by the driver. If the supplied address fails this sanity
    check, the multicast request will fail immediately with ios2_Error
    set to S2WERR_BAD_MULTICAST.

    Another Amiga will not receive a multicast packet unless it has had
    the particular multicast address being used S2_ADDMULTICASTADRESS'd.

SEE ALSO
    CMD_WRITE, S2_BROADCAST, S2_ADDMULTICASTADDRESS

BUGS


sana2.device/S2_OFFLINE

NAME
    Offline -- Remove interface from service.

FUNCTION
    This command removes a network interface from service.

IO REQUEST
    ios2_Command    - S2_OFFLINE.

RESULTS
    ios2_Error      - Zero if successful; non-zero otherwise.
    ios2_WireError  - More specific error number.

NOTES
    Aborts all pending reads and writes with ios2_Error set to
    S2ERR_OUTOFSERVICE.

    While the interface is offline, all read, writes and any other
    command that touches interface hardware will be rejected with
    ios2_Error set to S2ERR_OUTOFSERVICE.

    This command is intended to permit a network interface to be
    tested on an otherwise live system.

SEE ALSO
    S2_ONLINE

BUGS


sana2.device/S2_ONEVENT

NAME
    OnEvent -- Return when specified event occures.

FUNCTION
    This command returns when a particular event condition has occured
    on the network or this network interface.

IO REQUEST
    ios2_Command    - S2_ONEVENT.
    ios2_Flags      - Supported flags are:
                            SANA2IOB_QUICK
    ios2_WireError  - Mask of event(s) to wait for
                      (from <devices/sana2.h>).

RESULTS
    ios2_Error      - Zero if successful; non-zero otherwise.
    ios2_WireError  - Mask of events that occured.

NOTES
    If this device driver does not understand the specified event
    condition(s) then the command returns immediately with
    ios2_Req.io_Error set to S2_ERR_NOT_SUPPORTED and ios2_WireError
    S2WERR_BAD_EVENT.  A successful return will have ios2_Error set to
    zero ios2_WireError set to the event number.

    All pending requests for a particular event will be returned when
    that event occurs.

    All event types that cover a particular condition are returned when
    that condition occures. For instance, if an error is returned by
    a buffer management function during receive processing, events of
    types S2EVENT_ERROR, S2EVENT_RX and S2EVENT_BUFF would be returned if
    pending.

    Types ONLINE and OFFLINE return immediately if the device is
    already in the state to be waited for.

SEE ALSO

BUGS


sana2.device/S2_ONLINE

NAME
    Online -- Put a network interface back in service.

FUNCTION
    This command places an offline network interface back into service.

IO REQUEST
    ios2_Command    - S2_ONLINE.

RESULTS
    ios2_Error      - Zero if successful; non-zero otherwise.
    ios2_WireError  - More specific error number.

NOTES
    This command is responsible for putting the network interface
    hardware back into a known state (as close as possible to the
    state before S2_OFFLINE) and resets the unit global and special
    statistics.

SEE ALSO
    S2_OFFLINE

BUGS


sana2.device/S2_READORPHAN

NAME
    ReadOrphan -- Get a packet for which there is no reader.

FUNCTION
    Get the next packet available that does not satisfy any then-pending
    CMD_READ requests. The data returned in the ios2_Data structure is
    normally the Data Link Layer packet type field and the packet data. If
    bit SANA2IOB_RAW is set in ios2_Flags, then the entire Data Link Layer
    packet, including both header and trailer information, will be
    returned.

IO REQUEST
    ios2_Command    - CMD_READORPHAN.
    ios2_Flags      - Supported flags are:
                            SANA2IOB_RAW
                            SANA2IOB_QUICK
    ios2_DataLength - Length of the Data to be sent.
    ios2_Data       - Abstract data structure which packet data is
                      contained in.

RESULTS
    ios2_Error      - Zero if successful; non-zero otherwise.
    ios2_WireError  - More specific error number.
    ios2_Flags      - The following flags may be returned:
                            SANA2IOB_RAW
                            SANA2IOB_BCAST
                            SANA2IOB_MCAST
    ios2_SrcAddr    - Source interface address of packet.
    ios2_DstAddr    - Destination interface address of packet.
    ios2_DataLength - Length of the Data to be sent.
    ios2_Data       - Abstract data structure which packet data is
                      contained in.

NOTES
    This is intended for debugging and management tools.  Protocols should
    not use this.

    As with 802.3 packets on an ethernet, to determine which protocol
    family the returned packet belongs to you may have to specify
    SANA2IOB_RAW to get the entire data link layer wrapper (which is where
    the protocol type may be kept). Notice this necessarily means that
    this cannot be done in a network interface independent fashion.  The
    driver will, however, fill in the PacketType field to the best of its
    ability.

SEE ALSO
    CMD_READ, CMD_WRITE

BUGS


sana2.device/S2_TRACKTYPE

NAME
    TrackType -- Accumulate statistics about a packet type.

FUNCTION
    This command causes the device driver to accumulate statistics about
    a particular packet type. Packet type statistics, for the particular
    packet type, are zeroed by this command.

IO REQUEST
    ios2_Command    - S2_TRACKTYPE.
    ios2_PacketType - Packet type of interest.

RESULTS
    ios2_Error      - Zero if successful; non-zero otherwise.
    ios2_WireError  - More specific error number.

NOTES

SEE ALSO
    S2_UNTRACKTYPE, S2_GETTYPESTATS

BUGS


sana2.device/S2_UNTRACKTYPE

NAME
    UntrackType -- End statistics about a packet type.

FUNCTION
    This command causes the device driver to stop accumulating
    statistics about a particular packet type.

IO REQUEST
    ios2_Command    - S2_UNTRACKTYPE.
    ios2_PacketType - Packet type of interest.

RESULTS
    ios2_Error      - Zero if successful; non-zero otherwise.
    ios2_WireError  - More specific error number.

NOTES

SEE ALSO
    S2_TRACKTYPE, S2_GETTYPESTATS

BUGS


VIII-51/include/devices/sana2specialstats.h

#ifndef SANA2_SANA2SPECIALSTATS_H
#define SANA2_SANA2SPECIALSTATS_H 1
/*
**	$Filename: devices/sana2specialstats.h $
**	$Revision: 1.3 $
**	$Date: 92/01/10 15:10:29 $
**
**	Defined ids for SANA-II special statistics.
**
**
**	(C) Copyright 1991-1999 Amiga, Inc.
**		All Rights Reserved
*/

#ifndef SANA2_SANA2DEVICE_H
#include <sana2/sana2device.h>
#endif	/* !SANA2_SANA2DEVICE_H */

/*
** The SANA-II special statistic identifier is an unsigned 32 number.
** The upper 16 bits identify the type of network wire type to which
** the statistic applies and the lower 16 bits identify the particular
** statistic.
**
** If you desire to add a new statistic identifier, contacts CATS.
*/

/*
** defined ethernet special statistics
*/

#define S2SS_ETHERNET_BADMULTICAST	((((S2WireType_Ethernet)&0xffff)<<16)|0x0000)
/*
** This count will record the number of times a received packet tripped
** the hardware's multicast filtering mechanism but was not actually in
** the current multicast table.
*/

#define S2SS_ETHERNET_RETRIES		((((S2WireType_Ethernet)&0xffff)<<16)|0x0001)
/*
** This count records the total number of retries which have resulted
** from transmissions on this board.
*/

#endif	/* SANA2_SANA2SPECIALSTATS_H */


IX-1/4play.c

/*
 * 4play.c
 */

#include    <exec/types.h>
#include    <libraries/dos.h>

#include    <stdlib.h>
#include    <stdio.h>

#include    <clib/exec_protos.h>

UBYTE portdata;
UBYTE *portptr = &portdata;

UBYTE firedata;
UBYTE *fireptr = &firedata;

extern int getport(void);
extern void read34(void);
extern void freeport(void);

/*
 * Lattice control-c stop...
 */
int CXBRK(void) { return(0); }      /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }   /* really */

void Quit(char whytext[], LONG return_code)
{
    if(return_code==0) freeport();  /* Assembly routine to
                                       de-allocate parallel port */

    printf("%s\n",whytext);

    exit(return_code);              /* returning non-zero
                                       terminates the program */
}

void main(void)
{
    BOOL done=FALSE;
    UBYTE error;

    /* getport() is an assembly routine that allocates the parallel port
     * and makes all the lines we're interested in "read" lines.
     */
    if(error=getport()) Quit("Parallel port in use",25);
    /* WARNING:
     * This example continuously reads the ports and checks for CTRL_C,
     * thereby eating a lot of CPU time.  Actual applications that expect
     * to be even more system friendly might want to set up some interrupts
     * on the fire button lines, such that the game can read the ports less
     * often, but never miss a "fire" press.
     */

    while(!done)
    {
        read34();       /* read34() is the assembly routine that copies the
                         * relavent data from the port into our variables.
                         */

        /* We'll just print the raw bytes from the read, and leave it as an
         * exercise for the reader to mask out the relevant bits.
         * (Check the pinouts to find which bits the switches appear at.)
         */
        printf("portdata = %u, firedata = %u\n",portdata,firedata);

        /* Check CTRL_C */
        if(SetSignal(0L,0L) & SIGBREAKF_CTRL_C) /* Hit since last check? */
        {
            SetSignal(0L,SIGBREAKF_CTRL_C); /* Clear old status */
            done=TRUE;
        }
    }
    Quit("Ctrl-C was pressed.",0);
}


IX-1/read34.asm

;
; read34.asm
;
; interface code for the "2 more players" parallel port hack.
;
    csect	text			; this here's the meat

    xdef	Name			; Name of our application, so that
Name	dc.b	'4play',0		; other applications will know
                    ; who's tying up the port. ;-)

    xdef	_read34			; function names for linker
    xdef	_getport
    xdef	_freeport

    xref	_portptr		; c pointer for port data
    xref	_fireptr		; c pointer for fire buttons

    xref	_SysBase		; exec system base (from c.o)

    INCLUDE	"resources/misc.i"

    xdef	MiscName
MiscName	MISCNAME		; macro from resources/misc.i

    xdef	_MiscResource
_MiscResource	dc.l	0		; place to store misc.resource base

;parallel port hardware addresses (from amiga.lib)

    xref	_ciaaprb			; the actual port address
    xref	_ciaaddrb		; data direction register

    xref	_ciabpra			; control lines are here
    xref	_ciabddra		; data direction register
;from amiga.lib
    xref	_LVOOpenResource
    xref	_LVOAllocMiscResource
    xref	_LVOFreeMiscResource

_getport
;This routine simply allocates the parallel port in a system friendly
;way, and sets up the lines we want to use as input lines.
;

;save registers on the stack

    movem.l	a2-a6/d2-d7,-(sp)	; push regs

;open the misc.resource

    lea	MiscName,a1		; put name of misc.resource in a1
    movea.l	_SysBase,a6		; put SysBase in a6
    jsr	_LVOOpenResource(a6)
    move.l	d0,_MiscResource	; store address of misc.resource
    bne.s	grabit

;Oops, couldn't open misc.resource.  Sounds like big trouble to me.

    moveq	#20,d0			; error code
    bra	done

;This is where we grab the hardware.  If some other task has allocated
;the parallel data port or the parallel control bits, this routine will
;return non-zero.

;This part grabs the port itself

grabit	lea	Name,a1			; The name of our app
    moveq	#MR_PARALLELPORT,d0	; what we want
    movea.l	_MiscResource,a6	; MiscResource Base is in A6
    jsr	_LVOAllocMiscResource(a6)
    move.l	d0,d1
    beq.s	grab2

;well, somebody else must've got the port first.

    moveq	#30,d0			; error code
    bra	done

;This part grabs the control bits (busy, pout, and sel.)
;We really don't need pout, but it comes free with PARALLELBITS,
;so we'll take it anyway.

grab2	lea	Name,a1			; The name of our app
    moveq	#MR_PARALLELBITS,d0	; what we want
    jsr	_LVOAllocMiscResource(a6)
    move.l	d0,d1
    beq.s	setread

;well, somebody else must've got the bits first.

    moveq	#40,d2
    bra	freepar

;set up parallel port for reading

setread	move.b	#0,_ciaaddrb		; all lines read

    andi.b	#$FF,_ciabddra		; busy, pout, and sel. to read

;Well, we made it this far, so we've got exclusive access to
;the parallel port, and all the lines we want to use are
;set up.   From here we can just put back the regs and return to
;the caller.

    bra	done

;If something happened AFTER we got exclusive access to the parallel port,
;we'll need to let go of the port before we return the error.

freepar	moveq	#MR_PARALLELPORT,d0
    movea.l	_MiscResource,a6
    jsr	_LVOFreeMiscResource(a6)

    move.l	d2,d0			; put error code into d0

;Restore registers and return
;(error code is in d0)

done	movem.l (sp)+,a2-a6/d2-d7	; pop regs
    rts

_freeport
;This routine just makes sure that we let go of the parallel port and
;control lines, so somebody else can use 'em, now that we're all done.
;
;PS - Don't call this one if you got an error from _getport, as some
;of the resources might not have been opened, etc.
;

;save registers on the stack

    movem.l	a2-a6/d2-d7,-(sp)	; push regs

;free control lines

    moveq	#MR_PARALLELBITS,d0
    movea.l	_MiscResource,a6
    jsr	_LVOFreeMiscResource(a6)

;free parallel port

    moveq	#MR_PARALLELPORT,d0
    movea.l	_MiscResource,a6
    jsr	_LVOFreeMiscResource(a6)

;Clean up, restore registers, and return

    movem.l (sp)+,a2-a6/d2-d7	; pop regs
    rts

_read34
;All this routine does is copy the data from the ports to other addresses.
;
;In this case the destinations happens to be whatever C variables are
;pointed at by _portptr and _fireptr.
;

    movea.l	_portptr,a1		; a1 now holds the destination
    move.b	_ciaaprb,(a1)		; move byte from port to dest

    movea.l	_fireptr,a1		; a1 now holds the destination
    move.b	_ciabpra,(a1)		; move byte from port to dest

    rts

    end


IX-1/lmkfile

ASM	= asm
AFLAGS	= -iinclude:
CC	= sc
CFLAGS	= NMINC STRMERGE
LN	= slink

LIBS = LIB:sc.lib LIB:amiga.lib

.c.o:
        $(CC) $(CFLAGS) $*.c

.asm.o:
        $(ASM) $(AFLAGS) $*.asm

4play:	4play.o read34.o
        $(LN) FROM LIB:c.o,4play.o,read34.o TO 4play LIBRARY $(LIBS)


XI-1/Broker.c

;/* broker.c - Simple skeletal example of opening a broker compiled with SAS/C 6.56
sc DATA=FAR NMINC STRMERGE NOSTKCHK IGNORE=73 broker.c
slink FROM LIB:c.o,broker.o TO broker LIBRARY LIB:sc.lib,LIB:amiga.lib
quit
 */
/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <exec/libraries.h>
#include <libraries/commodities.h>
#include <dos/dos.h>
#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/alib_stdio_protos.h>
#include <clib/commodities_protos.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }
#endif

struct Library *CxBase;

void main(void);
LONG ProcessMsg(void);

CxObj *broker;

struct MsgPort *broker_mp;

struct NewBroker newbroker = {
    NB_VERSION, /* nb_Version - Version of the NewBroker structure */
    "AmigaMail broker", /* nb_Name - Name CX uses to identify this commodity */
    "Broker",   /* nb_Title - Title of commodity that appears in CXExchange */
    "A simple example of a broker",  /* nb_Descr - Description of the commodity */
    0,          /* nb_Unique - Tells CX not to launch new commodity with same name */
    0,          /* nb_Flags - Tells CX if this commodity has a window */
    0,          /* nb_Pri - This commodity's priority */
    0,          /* nb_Port - MsgPort CX talks to */
    0           /* nb_ReservedChannel - reserved for later use */
};

ULONG cxsigflag;

void main()
{
    /* Before bothering with anything else, open the library */
    if (CxBase = OpenLibrary("commodities.library", 37L))
    {
        /* Commodities talks to a Commodities application through
         * an Exec Message port, which the application provides
         */
        if (broker_mp = CreateMsgPort())
        {
            newbroker.nb_Port = broker_mp;

            /* The commodities.library function CxBroker() adds a
             * broker to the master list.  It takes two arguments,
             * a pointer to a NewBroker structure and a pointer to
             * a LONG.  The NewBroker structure contains information
             * to set up the broker.  If the second argument is not
             * NULL, CxBroker will fill it in with an error code.
             */
            if (broker = CxBroker(&newbroker, NULL))
            {
                cxsigflag = 1L << broker_mp->mp_SigBit;

                /* After it's set up correctly, the broker
                 * has to be activated
                 */
                ActivateCxObj(broker, 1L);

                /* the main processing loop */
                while (ProcessMsg());

                /* It's time to clean up.  Start by removing
                 * the broker from the Commodities master list.
                 * The DeleteCxObjAll() function will take care
                 * of removing a CxObject and all those connected
                 * to it from the Commodities network
                 */
                DeleteCxObj(broker);
            }
            DeletePort(broker_mp);
        }
        CloseLibrary(CxBase);
    }
}

LONG ProcessMsg(void)
{
    CxMsg *msg;

    ULONG sigrcvd, msgid, msgtype;
    LONG returnvalue = 1L;

    /* wait for something to happen */
    sigrcvd = Wait(SIGBREAKF_CTRL_C | cxsigflag);

    /* process any messages */
    while(msg = (CxMsg *)GetMsg(broker_mp))
    {
        /* Extract necessary information from the CxMessage and return it */
        msgid = CxMsgID(msg);
        msgtype = CxMsgType(msg);
        ReplyMsg((struct Message *)msg);

        switch(msgtype)
        {
            case CXM_IEVENT:
                /* Shouldn't get any of these in this example */
                break;
            case CXM_COMMAND:
                /* Commodities has sent a command */
                printf("A command: ");
                switch(msgid)
                {
                    case CXCMD_DISABLE:
                        printf("CXCMD_DISABLE\n");
                        /* The user clicked Commodities Exchange disable
                         * gadget better disable
                         */
                        ActivateCxObj(broker, 0L);
                        break;
                    case CXCMD_ENABLE:
                        /* user clicked enable gadget */
                        printf("CXCMD_ENABLE\n");
                        ActivateCxObj(broker, 1L);
                        break;
                    case CXCMD_KILL:
                        /* user clicked kill gadget, better quit */
                        printf("CXCMD_KILL\n");
                        returnvalue = 0L;
                        break;
                }
                break;
            default:
                printf("Unknown msgtype\n");
                break;
        }
    }

    /* Test to see if user tried to break */
    if (sigrcvd & SIGBREAKF_CTRL_C)
    {
        returnvalue = 0L;
        printf("CTRL C signal break\n");
    }
    return(returnvalue);
}


XI-1/HotKey.c

;/* HotKey.c - Simple hot key commodity.  Compiled with SAS/C 6.56
sc DATA=FAR NMINC STRMERGE NOSTKCHK IGNORE=73 hotkey.c
slink FROM LIB:c.o,hotkey.o TO hotkey LIBRARY LIB:scnb.lib,LIB:amiga.lib
quit
 */
/*
Copyright (c) 1991-1999 Amiga, Inc.

This example is provided in electronic form by Amiga, Inc.
for use with the Amiga Mail Volume II technical publication.
Amiga Mail Volume II contains additional information on the correct
usage of the techniques and operating system functions presented in
these examples.  The source and executable code of these examples may
only be distributed in free electronic form, via bulletin board or
as part of a fully non-commercial and freely redistributable
diskette.  Both the source and executable code (including comments)
must be included, without modification, in any copy.  This example
may not be published in printed form or distributed with any
commercial product. However, the programming techniques and support
routines set forth in these examples may be used in the development
of original executable software products for Amiga
computers.

All other rights reserved.

This example is provided "as-is" and is subject to change; no
warranties are made.  All use is at your own risk. No liability or
responsibility is assumed.
*/

#include <exec/libraries.h>
#include <libraries/commodities.h>
#include <dos/dos.h>
#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/alib_stdio_protos.h>
#include <clib/commodities_protos.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }
#endif

#define EVT_HOTKEY 1L

struct Library *CxBase, *IconBase;

void main(int, char **);
LONG ProcessMsg(void);

struct MsgPort *broker_mp;

CxObj *broker, *filter, *sender, *translate;

struct NewBroker newbroker = {
    NB_VERSION,
    "AmigaMail HotKey",           /* string to identify this broker */
    "A Simple HotKey",
    "A simple hot key commodity",
    NBU_UNIQUE | NBU_NOTIFY,      /* Don't want any new commodities
                                   * starting with this name.  If someone
                                   * tries it, let me know */
    0,
    0,
    0,
    0
};

ULONG cxsigflag;

void main(int argc, char **argv)
{
    char *hotkey, **ttypes;

    if (CxBase = OpenLibrary("commodities.library", 37L))
    {
        /* open the icon.library for the support library
         * functions, ArgArrayInit() and ArgArrayDone()
         */
        if (IconBase = OpenLibrary("icon.library", 36L))
        {
            if (broker_mp = CreateMsgPort())
            {
                newbroker.nb_Port = broker_mp;
                cxsigflag = 1L << broker_mp->mp_SigBit;

                /* ArgArrayInit() is a support library function
                 * (from the 2.0 version of amiga.lib) that makes it
                 * easy to read arguments from either a CLI or from
                 * the Workbench's ToolTypes.  Because it uses
                 * icon.library, the library has to be open before
                 * calling this function.  ArgArrayDone() cleans up
                 * after this function.
                 */
                ttypes = ArgArrayInit(argc, argv);

                /* ArgInt() (also from amiga.lib) searches through the
                 * array set up by ArgArrayInit() for a specific
                 * ToolType.  If it finds one, it returns the numeric
                 * value of the number that followed the ToolType
                 * (i.e. CX_PRIORITY=7).  If it doesn't find the ToolType,
                 * it returns the default value (the third argument)
                 */
                newbroker.nb_Pri = (BYTE)ArgInt(ttypes, "CX_PRIORITY", 0);

                /* ArgString() works just like ArgInt(), except it
                 * returns a pointer to a string rather than an integer.
                 * In the example below, if there is no ToolType "HOTKEY",
                 * the function returns a pointer to "rawkey control esc".
                 */
                hotkey = ArgString(ttypes, "HOTKEY", "rawkey control esc");

                if (broker = CxBroker(&newbroker, NULL))
                {
                    /* CxFilter() is a macro that creates a filter
                     * CxObject.  This filter passes input events that
                     * match the string pointed to by hotkey.
                     */
                    if (filter = CxFilter(hotkey))
                    {
                        /* Add a CxObject to another's personal list */
                        AttachCxObj(broker, filter);

                        /* CxSender() creates a sender CxObject.  Every
                         * time a sender gets a CxMessage, it sends a new
                         * CxMessage to the port pointed to in the first
                         * argument.  CxSender()'s second argument will be
                         * the ID of any CxMessages the sender sends to
                         * the port.  The data pointer associated with the
                         * CxMessage will point to a *COPY* of the
                         * InputEvent structure associated with the orginal
                         * CxMessage.
                         */
                        if (sender = CxSender(broker_mp, EVT_HOTKEY))
                        {
                            AttachCxObj(filter, sender);

                            /* CxTranslate() creates a translate CxObject.
                             * When a translate CxObject gets a CxMessage,
                             * it deletes the original CxMessage and adds
                             * a new input event to the input.device's
                             * input stream after the Commodities input
                             * handler.  CxTranslate's argument points
                             * to an InputEvent structure from which to
                             * create the new input event.  In this example,
                             * the pointer is NULL, meaning no new event
                             * should be introduced.
                             */
                            if (translate = (CxTranslate(NULL)))
                            {
                                AttachCxObj(filter, translate);

                                /* CxObjError() is a commodities.library
                                 * function that returns the internal
                                 * accumulated error code of a CxObject.
                                 */
                                if (! CxObjError(filter))
                                {
                                    ActivateCxObj(broker, 1L);
                                    while (ProcessMsg());
                                }
                            }
                        }
                    }
                    /* DeleteCxObjAll() is a commodities.library function
                     * that not only deletes the CxObject pointed to in
                     * its argument, but it deletes all of the CxObjects
                     * that are attached to it.
                     */
                    DeleteCxObjAll(broker);
                }
                DeletePort(broker_mp);
            }

            /* this amiga.lib function cleans up after ArgArrayInit() */
            ArgArrayDone();
            CloseLibrary(IconBase);
        }
        CloseLibrary(CxBase);
    }
}

LONG ProcessMsg(void)
{
    extern struct MsgPort *broker_mp;
    extern CxObj *broker;

    extern ULONG cxsigflag;

    CxMsg *msg;

    ULONG sigrcvd, msgid, msgtype;
    LONG returnvalue = 1L;

    sigrcvd = Wait(SIGBREAKF_CTRL_C | cxsigflag);

    while(msg = (CxMsg *)GetMsg(broker_mp))
    {
        msgid = CxMsgID(msg);
        msgtype = CxMsgType(msg);
        ReplyMsg((struct Message *)msg);

        switch(msgtype)
        {
            case CXM_IEVENT:
                printf("A CXM_EVENT, ");
                switch(msgid)
                {
                    case EVT_HOTKEY:
                    /* We got the message from the sender CxObject */
                        printf("You hit the HotKey.\n");
                        break;

                    default:
                        printf("unknown.\n");
                        break;
                }
                break;

            case CXM_COMMAND:
                printf("A command: ");
                switch(msgid)
                {
                    case CXCMD_DISABLE:
                        printf("CXCMD_DISABLE\n");
                        ActivateCxObj(broker, 0L);
                        break;

                    case CXCMD_ENABLE:
                        printf("CXCMD_ENABLE\n");
                        ActivateCxObj(broker, 1L);
                        break;

                    case CXCMD_KILL:
                        printf("CXCMD_KILL\n");
                        returnvalue = 0L;
                        break;

                    case CXCMD_UNIQUE:
                    /* Commodities Exchange can be told not
                     * only to refuse to launch a commodity with
                     * a name already in use but also can notify
                     * the already running commodity that it happened.
                     * It does this by sending a CXM_COMMAND with the
                     * ID set to CXMCMD_UNIQUE.  If the user tries
                     * to run a windowless commodity that is already
                     * running, the user wants the commodity to shut down.
                     */
                        printf("CXCMD_UNIQUE\n");
                        returnvalue = 0L;
                        break;
                    default:
                        printf("Unknown msgid\n");
                        break;
                }
                break;
            default:
                printf("Unknown msgtype\n");
                break;
        }
    }

    if (sigrcvd & SIGBREAKF_CTRL_C)
    {
        returnvalue = 0L;
        printf("CTRL C signal break\n");
    }

    return(returnvalue);
}


XI-21/LoadKeyMap.c

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/libraries.h>
#include <devices/keymap.h>
#include <dos/dos.h>

#include <clib/exec_protos.h>
#include <clib/utility_protos.h>
#include <clib/dos_protos.h>

#include <pragmas/exec_pragmas.h>
#include <pragmas/utility_pragmas.h>
#include <pragmas/dos_pragmas.h>

#include "loadkeymap.h"

/*****************************************************************************/

extern struct Library *SysBase;
extern struct Library *UtilityBase;
extern struct Library *DOSBase;

/*****************************************************************************/

/* Case-insensitive version of FindName() */
static struct Node *FindNameNC(struct List *list, STRPTR name)
{
struct Node *node;
WORD         result;

    node = list->lh_Head;
    while (node->ln_Succ)
    {
        result = Stricmp(name,node->ln_Name);
        if (result == 0)
            return(node);

        node = node->ln_Succ;
    }

    return(NULL);
}

/*****************************************************************************/

struct KeyMap *LoadKeyMap(STRPTR name)
{
BPTR                   segment;
struct KeyMapResource *kr;
struct KeyMapNode     *kn;
STRPTR                 base;

    kn      = NULL;
    segment = NULL;

    /* open the keymap resource, in order to gain access to the keymap list */
    if (kr = (struct KeyMapResource *)OpenResource("keymap.resource"))
    {
        segment = NULL;
        base = FilePart(name);

        /* must access the list under Forbid() */
        Forbid();

        /* is the keymap we want already on the keymap list? */
        if (!(kn = (struct KeyMapNode *)FindNameNC(&kr->kr_List,base)))
        {
            /* if not on the keymap list, try loading it */
            if (segment = LoadSeg(name))
            {
                /* see if someone added it to the keymap list while we were
                 * doing a LoadSeg() (which broke Forbid() )
                 */
                if (!(kn = (struct KeyMapNode *)FindNameNC(&kr->kr_List,base)))
                {
                    kn = (struct KeyMapNode *)((segment << 2) + sizeof(BPTR));

                    /* we've loaded a keymap file. Do a few sanity checks
                     * to make sure it is a keymap, and not some bogus
                     * load file
                     */
                    if (TypeOfMem(kn->kn_Node.ln_Name)
                    &&  Stricmp(name,kn->kn_Node.ln_Name))
                    {
                        /* add to the system's keymap list */
                        AddHead(&(kr->kr_List),(struct Node *)kn);
                    }
                    else
                    {
                        /* bogus load file! Get rid of it and fail */
                        UnLoadSeg(segment);
                        kn = NULL;
                    }
                }
                else
                {
                    /* the keymap was added to the list behind our back!
                     * Free what was loaded and return happily
                     */
                    UnLoadSeg(segment);
                }
            }
        }

        /* get out of forbidden state */
        Permit();
    }

    if (kn)
        return(&kn->kn_KeyMap);

    return(NULL);
}


XI-21/LoadKeyMap.h

#ifndef LOADKEYMAP_H
#define LOADKEYMAP_H

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef DEVICES_KEYMAP_H
#include <devices/keymap.h>
#endif

/*****************************************************************************/

struct KeyMap *LoadKeyMap(STRPTR name);

/*****************************************************************************/

#endif /* LOADKEYMAP_H */


XI-25/AppKeyMap.doc

 AppKeyMap.o/AlterAppKeyMap                         AppKeyMap.o/AlterAppKeyMap

   NAME
    AlterAppKeyMap -- Changes keyboard mappings for a keymap

   SYNOPSIS
    AlterAppKeyMap(mykeymap, keyarray, arrayentries);

    void AlterAppKeyMap(struct KeyMap *,
                    struct MyKey *,
                    UWORD);

   FUNCTION
    Using an array of MyKey structures (which describe a series of
    rawkeys), this function	changes the rawkey's corresponding
    mapping values in mykeymap.  Only call this function on
    a private copy of a KeyMap (including its data).

   INPUTS
    mykeymap = pointer to a KeyMap structure.  AlterAppKeyMap() will
      make changes to this KeyMap's data, so this KeyMap should
      be a private copy of a KeyMap (including the data the KeyMap
      points to).

    keyarray  = pointer to an array of struct MyKey (from
      appkeymap.h):

            struct MyKey
            {
              UBYTE RawCode;	/* RawCode of character to change      */
                /* in the KeyMap.  Correponds to the   */
                /* Lo/HiKeyMap structures from the     */
                /* KeyMap structure.		       */
              UBYTE MapType;	/* The Lo/HiKeyMapTypes field.         */
              UBYTE Capsable;   /* This TRUE/FALSE state of this bit   */
                                /* gets translated to the correspond-  */
                                /* bit in KeyMap.Lo/HiCapsable.        */
              UBYTE Repeatable; /* This TRUE/FALSE state of this bit   */
                                /* gets translated to the correspond-  */
                                /* bit in KeyMap.Lo/HiRepeatable.      */
              ULONG Map;	/* Map data for key.  This points to   */
                          /* data for the rawkey.  Its format    */
                          /* depends on the key type. This field */
                          /* correponds to KeyMap.Lo/HiKeyMap.   */
            };

        arrayentries = The number of MyKey entries in keyarray.

   RESULT
    For each MyKey entry in keyarray, AlterKeyMap() finds the correpsonding
    raw key	entry in mykeymap and changes the data to match the entry
    in keyarray.  AlterKeyMap() makes changes directly to the KeyMap's
    data, so don't call this function on a system copy of a keymap, make
    a copy of it.

    Note that the console.device's CD_ASKKEYMAP only copies a KeyMap
    structure, which is only a set of pointers.  If you want to customize
    a copy of a keymap, you also have to duplicate the data that
    the KeyMap references.  If you do not duplicate the keymap data when
    customizing a keymap, you'll write over data that many keymaps are
    currently using.

    This function assumes that the keymap passed to it was duplicated
    using the CreateAppKeyMap() function.  CreateAppKeyMap() puts
    the keymap tables in a specific order and AlterAppKeyMap()
    expects to find the tables in that order.  Only call AlterAppKeyMap()
    on keymaps duplicated with CreateAppKeyMap().

   BUGS

   SEE ALSO
    console.device/CD_ASKKEYMAP console.device/CD_SETKEYMAP "appkeymap.h"
    AppKeyMap.o/CreateAppKeyMap() AppKeyMap.o/DeleteAppKeyMap()

 AppKeyMap.o/CreateAppKeyMap                       AppKeyMap.o/CreateAppKeyMap

   NAME
    CreateAppKeyMap -- Create a new KeyMap by duplicating an existing one.

   SYNOPSIS
    newkeymap = CreateAppKeyMap(origkeymap);

    struct KeyMap *CreateAppKeyMap(struct KeyMap *);

   FUNCTION
    This function accepts a pointer to a KeyMap structure and duplicates it.
    CreateAppKeyMap() allocates the memory for a KeyMap structure and all
    the tables associated with that keymap.

   INPUTS
    origkeymap = points to a KeyMap to duplicate.

   RESULT
    If successful, this function returns a pointer to a duplicate of
    origkeymap.  CreateAppKeyMap() duplicates all of the tables that
    origkeymap references, so an application can make changes to the
    duplicate.  If CreateAppKeyMap() fails, it returns NULL.  The
    DeleteAppKeyMap() function deallocates the resources allocated
    by CreateAppKeyMap().

    CreateAppKeyMap() places the duplicate tables in an order so
    that a "Lo" table (for example, KeyMap.km_LoKeyMap) is immediately
    followed by the corresponding "Hi" table (KeyMap.km_HiKeyMap).
    This allows application to reference the two tables as one using
    the raw key value as an index.

   BUGS

   SEE ALSO
    console.device/CD_ASKKEYMAP console.device/CD_SETKEYMAP "appkeymap.h"
    AppKeyMap.o/AlterAppKeyMap() AppKeyMap.o/DeleteAppKeyMap()

 AppKeyMap.o/DeleteAppKeyMap                       AppKeyMap.o/DeleteAppKeyMap

   NAME
    DeleteAppKeyMap -- Relinquish the resources allocated by
                       CreateAppKeyMap.

   SYNOPSIS
    DeleteAppKeyMap(mykeymap);

    void DeleteAppKeyMap(struct KeyMap *);

   FUNCTION
       This function accepts a pointer to a keymap allocated by
       CreateAppKeyMap() and deallocates the resources allocated
       by that function.

   INPUTS
    mykeymap = points to a KeyMap to deallocate.

   RESULT
       Frees memory previously used by mykeymap and its associated tables.

   BUGS

   SEE ALSO
    console.device/CD_ASKKEYMAP console.device/CD_SETKEYMAP "appkeymap.h"
    AppKeyMap.o/AlterAppKeyMap() AppKeyMap.o/CreateAppKeyMap()


XI-25/AppKeyMap.c

;/* appkeymap.c link module - Execute me to compile me with SAS/C 6.56
sc data=far nominc strmer streq nostkchk saveds ign=73 appkeymap.c
quit
*/

/* appkeymap.c - subroutines to create/delete an application keymap
 *               by modifying a copy of a keymap
 *
 * The modifications made to the keymap are controlled by the "mykeys" array.
 * To create more complex keymappings, see the Rom Kernel Manual Libraries
 * keymap library chapter (p 821 et al).
 *
 * NOTE: disabling all numeric pad keys creates a good keymap for use
 * with either keymap.library MapANSI() or commodities InvertString().
 * If you used a default keymap with the above functions, numeric keypad
 * raw key values would be returned for keys which are available with
 * fewer keypresses on numeric pad than on the normal keyboard.
 * It is generally preferable to have the normal keyboard raw values
 * since many applications attach special meanings to numeric pad keys.
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <devices/console.h>
#include <devices/keymap.h>

#include <clib/exec_protos.h>
#include <clib/keymap_protos.h>
#include <clib/alib_protos.h>

#include "appkeymap.h"

/* local functions */
static void CopyKeyMap (struct KeyMap *source, struct KeyMap *dest);

struct KeyMap *
CreateAppKeyMap (struct KeyMap *defkeymap)
{
  struct KeyMap *appkeymap = NULL;
  struct KeyMapArrays *karrays;
  ULONG keymapsize;

                                /* Because of the way this code allocates memory,  */
                                /* it must make sure the KeyMap structure will take*/
                                /* up an even amount of bytes (so the tables that  */
                                /* follow it will be word aligned).  This adds one */
                                /* to the size of the KeyMap structure's size if   */
                                /* necessary.  This is only for future compatibil- */
                                /* ity as a KeyMap structure is currently even.    */
  keymapsize = (sizeof(struct KeyMap)+1)&0x0000FFFE;

                                /* Allocate the space for the clone of the KeyMap. */
                                /* This includes space for the KeyMap structure    */
                                /* which is immediately followed by space for the  */
                                /* keymapping tables.                              */
  if (appkeymap = (struct KeyMap *)
          AllocVec (sizeof (struct KeyMap) + sizeof (struct KeyMapArrays),
                    MEMF_CLEAR|MEMF_PUBLIC) )
  {
                  /* Initialize the pointer to the KeyMapArrays structure. These   */
                  /* arrays are organized so that the "Lo" tables are immediately  */
                  /* followed by the "Hi" tables, so you don't have to treat the   */
                  /* Lo and Hi maps separately.  This allows AlterKeyMap() to find */
                  /* Hi map raw key entries by use the raw key value as an index   */
                  /* into the Lo map tables.                                       */
    karrays = (struct KeyMapArrays *) ((ULONG)appkeymap + keymapsize);

                  /* Initialize the appkeymap fields to point to the KeyMapArrays. */
                  /* Each LH array contains the Lo table followed by the Hi table. */
    appkeymap->km_LoKeyMap      = &karrays->LHKeyMap[0];
    appkeymap->km_HiKeyMap      = &karrays->LHKeyMap[LO_MAP_SIZE];
    appkeymap->km_LoKeyMapTypes = &karrays->LHKeyMapTypes[0];
    appkeymap->km_HiKeyMapTypes = &karrays->LHKeyMapTypes[LO_TYPE_SIZE];
    appkeymap->km_LoCapsable    = &karrays->LHCapsable[0];
    appkeymap->km_HiCapsable    = &karrays->LHCapsable[LO_CAPS_SIZE];
    appkeymap->km_LoRepeatable  = &karrays->LHRepeatable[0];
    appkeymap->km_HiRepeatable  = &karrays->LHRepeatable[LO_REPS_SIZE];

    CopyKeyMap (defkeymap, appkeymap);     /* Copy the keymap arrays to appkeymap. */
  }

  return (appkeymap);
}

void
DeleteAppKeyMap (struct KeyMap *appkeymap)
{
  if (appkeymap)
    FreeVec (appkeymap);
}

void
AlterAppKeyMap (struct KeyMap *appkeymap, struct MyKey *mykeys, UWORD mykeycount)
{
  ULONG *keymappings;
  UBYTE *keymaptypes, *capsables, *repeatables;
  UBYTE rawkeynum;
  int i, bytenum, bitnum;

/* AlterAppKeyMap() assumes that the tables of the keymap passed to it are */
/* contiguous from Lo through Hi. This allows AlterAppKeyMap() to directly */
/* reference any key using its raw key code as an index.  This also limits */
/* an application to using AlterAppKeyMap() to modify only keymap created  */
/* by CreateAppKeyMap().                                                   */

  keymappings = appkeymap->km_LoKeyMap;
  keymaptypes = appkeymap->km_LoKeyMapTypes;
  capsables   = appkeymap->km_LoCapsable;
  repeatables = appkeymap->km_LoRepeatable;

  for (i = 0; i < mykeycount; i++)
  {

                                    /* Because we allocated each of our Lo and Hi    */
    rawkeynum = mykeys[i].RawCode;  /* array pairs as sequential memory, we can use  */
                                    /* the RAWKEY values directly  to index into our */
                                    /* sequential Lo/Hi array.                       */

    keymaptypes[rawkeynum] = mykeys[i].MapType;
    keymappings[rawkeynum] = mykeys[i].Map;

    bytenum = rawkeynum >> 3; /* These are for the Capsable + Repeatable bit tables. */
    bitnum = rawkeynum % 8;   /*    Careful--There's only a 1 bit entry per raw key! */

    if (mykeys[i].Capsable)
      capsables[bytenum] |= (1 << bitnum);          /* If capsable, set bit, else... */
    else
      capsables[bytenum] &= (~(1 << bitnum));       /*             ...clear the bit. */

    if (mykeys[i].Repeatable)
      repeatables[bytenum] |= (1 << bitnum);      /* If repeatable, set bit, else... */
    else
      repeatables[bytenum] &= (~(1 << bitnum));   /*               ...clear the bit. */
  }
}

static void
CopyKeyMap (struct KeyMap *source, struct KeyMap *dest)
{
  UBYTE *bb;
  ULONG *ll;
  int i;

  for (i = 0, ll = source->km_LoKeyMap; i < LO_MAP_SIZE; i++)
    dest->km_LoKeyMap[i] = *ll++;
  for (i = 0, ll = source->km_HiKeyMap; i < HI_MAP_SIZE; i++)
    dest->km_HiKeyMap[i] = *ll++;

  for (i = 0, bb = source->km_LoKeyMapTypes; i < LO_TYPE_SIZE; i++)
    dest->km_LoKeyMapTypes[i] = *bb++;
  for (i = 0, bb = source->km_HiKeyMapTypes; i < HI_TYPE_SIZE; i++)
    dest->km_HiKeyMapTypes[i] = *bb++;

  for (i = 0, bb = source->km_LoCapsable; i < LO_CAPS_SIZE; i++)
    dest->km_LoCapsable[i] = *bb++;
  for (i = 0, bb = source->km_HiCapsable; i < HI_CAPS_SIZE; i++)
    dest->km_HiCapsable[i] = *bb++;

  for (i = 0, bb = source->km_LoRepeatable; i < LO_REPS_SIZE; i++)
    dest->km_LoRepeatable[i] = *bb++;
  for (i = 0, bb = source->km_HiRepeatable; i < HI_REPS_SIZE; i++)
    dest->km_HiRepeatable[i] = *bb++;
}


XI-25/AppKeyMap.h

#define UP_KEY      0x4C   /* Raw keys which are the same on all keyboards */
#define DOWN_KEY    0x4D
#define RIGHT_KEY   0x4E
#define LEFT_KEY    0x4F

#define F1_KEY      0x50
#define F2_KEY      0x51
#define F3_KEY      0x52
#define F4_KEY      0x53
#define F5_KEY      0x54
#define F6_KEY      0x55
#define F7_KEY      0x56
#define F8_KEY      0x57
#define F9_KEY      0x58
#define F10_KEY     0x59

#define N0_KEY      0x0F
#define N1_KEY      0x1D
#define N2_KEY      0x1E
#define N3_KEY      0x1F
#define N4_KEY      0x2D
#define N5_KEY      0x2E
#define N6_KEY      0x2F
#define N7_KEY      0x3D
#define N8_KEY      0x3E
#define N9_KEY      0x3F

#define NPERIOD_KEY 0x3C
#define NOPAREN_KEY 0x5A
#define NCPAREN_KEY 0x5B
#define NSLASH_KEY  0x5C
#define NASTER_KEY  0x5D
#define NMINUS_KEY  0x4A
#define NPLUS_KEY   0x5E
#define NENTER_KEY  0x43

/* Sizes of the "Lo" and "Hi" KeyMap tables */

#define LO_MAP_SIZE  64   /* Notice that the Lo and Hi tables are NOT the same */
#define HI_MAP_SIZE  56   /* size!  The Lo tables have eight more entries than */
#define LO_TYPE_SIZE 64   /* the Hi tables.  The RKM is incorrect in saying    */
#define HI_TYPE_SIZE 56   /* that the Lo and Hi tables are the same size.      */
#define LO_CAPS_SIZE 8		/* 8 bytes x 8 bits-per-byte = */
#define HI_CAPS_SIZE 7		/* 7 bytes x 8 bits-per-byte = */
#define LO_REPS_SIZE 8		/* 64 bit-wide entries.        */
#define HI_REPS_SIZE 7		/* 56 bit-wide entries.        */

void AlterAppKeyMap (struct KeyMap *,
             struct MyKey *,
             UWORD);
struct KeyMap *CreateAppKeyMap (struct KeyMap *);
void DeleteAppKeyMap (struct KeyMap *);
UBYTE FindMaxDeadKey(struct KeyMap *);

struct MyKey /* AlterAppKeyMap() expects an array of MyKey structures. */
             /* This structure contains all the information needed to  */
             /* redefine a key mapping.                                */
{
  UBYTE RawCode;
  UBYTE MapType;    /* Qualifier flags and key type. */
  UBYTE Capsable;   /* Is this key Capsable?         */
  UBYTE Repeatable; /* Is this key Repeatable?       */
  ULONG Map;        /* This field either points to some key data or */
};                  /* contains a four-byte table of ANSI values.   */

struct KeyMapArrays  /* We allocate each Lo and Hi table pair as a single array */
{
  ULONG LHKeyMap[LO_MAP_SIZE << 1];
  UBYTE LHKeyMapTypes[LO_TYPE_SIZE << 1];
  UBYTE LHCapsable[LO_CAPS_SIZE << 1];
  UBYTE LHRepeatable[LO_REPS_SIZE << 1];
};


XI-25/AppMap_demo.c

;/* appmap_demo.c - Execute me to compile me with SAS/C 6.56
sc data=far nominc strmer streq nostkchk saveds ign=73 appmap_demo.c
slink FROM LIB:c.o,appmap_demo.o,appkeymap.o TO appmap_demo LIB LIB:SC.lib,LIB:Amiga.lib
quit
*/

/* Appmap_demo uses the routines in appkeymap.o to clone the current  */
/* task's console keymap.  Appmap_demo then modifies the keymap clone */
/* by redefining some of the keypad keys.  It installs a string key,  */
/* a "normal" key, and a NO OP key, which are acceptable replacements */
/* for keypad keys on a console-based application.                    */
/*                                                                    */
/* This example also installs a dead/deadable key pair and a double   */
/* dead/deadable key pair.  These are provided only as a means for    */
/* understanding how dead-class keys work.  Do not use them as part   */
/* of anything for public consumption.                                */

#include       <exec/types.h>
#include       <exec/memory.h>
#include       <exec/io.h>
#include       <dos/dos.h>
#include       <devices/console.h>
#include       <devices/keymap.h>

#include       <clib/exec_protos.h>
#include       <clib/dos_protos.h>

#include       <stdio.h>
#include       <stdlib.h>

#ifdef  __SASC
void __regargs __chkabort(void);
void __regargs __chkabort(void){}
#endif

#include "appkeymap.h"

#define MYKEYCOUNT 7

far UBYTE deadmap[] =           /* The data for the dead key (the introducer) */
{
  0, '4',                       /* maps to '4' when keypad 4 is pressed alone */
  DPF_DEAD, 1                   /* maps to a dead key when shift is down      */
};

far UBYTE deadablemap[] =
{
  0, '5',                       /* maps to '5' when keypad 5 is pressed alone */
  DPF_MOD, 4,                   /* maps to a deadable key when shift is down  */
  '5', 0xC2, '5', '5', '5'      /* Entry 1 in this table maps to 0xC2, the    */
};                              /* others map to '5'.                         */

far UBYTE doubledeadmap[] =
{
  0, '6',                              /* maps to '6' when keypad 6 is pressed alone */
  DPF_DEAD, 1 | (2 << DP_2DFACSHIFT)   /* maps to a dead key when shift is down      */
};

far UBYTE doubledeadablemap[] =
{
  0, '7',                       /* maps to '7' when keypad 7 is pressed alone */
  DPF_MOD, 4,                   /* maps to a deadable key when shift is down  */
  '7', '7', 0xA5, 0xA9, '7'     /* Entry 2 in this table maps to $A5, entry 3 */
};                              /* to $A9, the others to '7'.                 */

UBYTE strings[] =
{
        5,16,
        5,21,
        3,26,
        9,29,
        4,38,
        10,42,
        8,52,
        14,60,
        'p','l','a','i','n',
        's','h','i','f','t',
        'a','l','t',
        's','h','i','f','t','+','a','l','t',
        'c','t','r','l',
        'c','t','r','l','+','s','h','i','f','t',
        'c','t','r','l','+','a','l','t',
        'c','t','r','l','+','a','l','t','+','s','h','i','f','t'
};

struct MyKey mykeys[MYKEYCOUNT] =
{
  { N1_KEY,                    /* The '1' from the numeric key pad                 */
    KCF_STRING | KC_VANILLA,   /* This is a string key that accepts all qualifiers */
    1, 1,                      /* Capsable and Repeatable                          */
    (ULONG) strings            /* This points to the key's string data table       */
  },

  { N2_KEY,     /* The '2' from the numeric key pad                           */
    KC_VANILLA, /* VANILLA key generating shift-alted, alted, shifted, plain  */
    0, 0,       /* Non-Capsable, Non-Repeatable                               */
    0x26252423  /* This long word is four ANSI codes: $26=& $25=% $24=$ $23=# */
  },

  { N3_KEY,     /* The '3' from the numeric key pad */
    KCF_NOP,    /* This key is a NO OPeration key   */
    0, 0,       /* Non-Capsable, Non-Repeatable     */
    0L
  },

  { N4_KEY,                /* The '4' from the numeric key pad */
    KCF_DEAD | KCF_SHIFT,  /* A shiftable Dead-class key       */
    0, 0,                  /* Non-Capsable, Non-Repeatable     */
    (ULONG) deadmap        /* pointer to dead-class key data   */
  },

  { N5_KEY,                /* The '5' from the numeric key pad */
    KCF_DEAD | KCF_SHIFT,  /* A shiftable Dead-class key       */
    0, 0,                  /* Non-Capsable, Non-Repeatable     */
    (ULONG) deadablemap    /* pointer to dead-class key data   */
  },

  { N6_KEY,                /* The '6' from the numeric key pad */
    KCF_DEAD | KCF_SHIFT,  /* A shiftable Dead-class key       */
    0, 0,                  /* Non-Capsable, Non-Repeatable     */
    (ULONG) doubledeadmap  /* pointer to dead-class key data   */
  },

  { N7_KEY,                   /* The '7' from the numeric key pad */
    KCF_DEAD | KCF_SHIFT,     /* A shiftable Dead-class key       */
    0, 0,                     /* Non-Capsable, Non-Repeatable     */
    (ULONG) doubledeadablemap /* pointer to dead-class key data   */
  }
};

extern struct Library *SysBase;

struct KeyMap *appkeymap, defkeymap;

struct IOStdReq *conio = NULL;
struct MsgPort *replyport = NULL;

/* prototypes for our program functions */

void closeall (void);
void closeout (UBYTE * errstring, LONG rc);
struct IOStdReq *makeio (void);
void freeio (struct IOStdReq *ior);

void
main (int argc, char **argv)
{
  LONG rc = 0;

/* This example is shell-only. It modifies a shell's keymap while running. */
/* Alternately, you could modify this demo code to change the keymap       */
/* of the console.device of another CON: window OR a console.device        */
/* unit you've attached to your own Intuition window.  You need the        */
/* device and unit pointers for the console unit you wish to affect.       */

  if (!argc)
    exit (RETURN_FAIL);

  if (SysBase->lib_Version < 37)
    closeout ("Kickstart 2.0 required", RETURN_FAIL);

  conio = makeio ();
  if (conio == NULL)
    closeout ("Can't create IORequest", RETURN_FAIL);

  conio->io_Command = CD_ASKKEYMAP;          /* Obtain a copy of the    */
  conio->io_Data = (APTR) & defkeymap;       /* shell console's KeyMap. */
  conio->io_Length = sizeof (struct KeyMap);
  DoIO (conio);

  appkeymap = CreateAppKeyMap (&defkeymap);

  if (appkeymap == NULL)
    closeout ("Can't create keymap", RETURN_FAIL);

/* If we get here, all went OK.  We now have appkeymap and defkeymap, and  */
/* conio IOStdRequest is init'd to talk to our shell's console device unit */

  AlterAppKeyMap (appkeymap, mykeys, MYKEYCOUNT);

  conio->io_Command = CD_SETKEYMAP;      /* Set the keymap for the console */
  conio->io_Data = (APTR) appkeymap;     /* to be the modified clone.      */
  conio->io_Length = sizeof (struct KeyMap);
  DoIO (conio);

  printf ("Appkeymap installed for this console.\n");
  printf ("Changes for our keymap were specified in an array in appmap_demo.c\n\n");
  printf ("Numeric pad 1 is now a repeatable and capsable string key.  It\n");
  printf ("    also prints a different string for all qualifier combos.\n");
  printf ("Numeric pad 2 is different chars if normal, shifted, alted, shift-alted.\n");
  printf ("Numeric pad 3 is disabled.\n");
  printf ("Shift-Numeric pad 4 is a dead-key.  Shift-Numeric pad 5 is a deadable key.\n");
  printf ("    When you hit Shift-Numeric pad 4 then Shift-Numeric pad 5, this\n");
  printf ("    example prints '\302'\n");
  printf ("Shift-Numeric pad 6 is a double dead-key.  Shift-Numeric pad 7 is a deadable\n");
  printf ("    key.  When you hit Shift-Numeric pad 6 once then Shift-Numeric pad 7,\n");
  printf ("    this example prints '\245'.  When you hit Shift-Numeric pad 6 twice then\n");
  printf ("    Shift-Numeric pad 7, this example prints '\251'.\n");
  printf ("\nHit return to exit when done\n");
  getchar ();
  printf ("Setting this console back to default keymap\n");

  conio->io_Command = CD_SETKEYMAP;          /* Restore the shell's original keymap */
  conio->io_Data = (APTR) & defkeymap;
  conio->io_Length = sizeof (struct KeyMap);
  DoIO (conio);

  closeall ();
  exit (rc);
}

struct IOStdReq *
makeio (void)
{
  struct MsgPort *conport;
  struct IOStdReq *ior = NULL;
  struct InfoData *id;
  struct Process *proc;

  proc = (struct Process *) FindTask (NULL);
  conport = (struct MsgPort *) proc->pr_ConsoleTask;
  if (!conport)
    return (NULL);

  if (id = (struct InfoData *)
      AllocMem (sizeof (struct InfoData), MEMF_PUBLIC | MEMF_CLEAR))
  {
    if (DoPkt (conport, ACTION_DISK_INFO, ((ULONG) id) >> 2, 0L, 0L, 0L, 0L))
    {
      if (replyport = CreateMsgPort ())
      {
        if (ior = CreateIORequest (replyport, sizeof (struct IOStdReq)))
        {
          ior->io_Device = ((struct IOStdReq *) id->id_InUse)->io_Device;
          ior->io_Unit = ((struct IOStdReq *) id->id_InUse)->io_Unit;
        }
      }
    }
    FreeMem (id, sizeof (struct InfoData));
  }
  return (ior);
}

void
freeio (struct IOStdReq *ior)
{
  if (ior)
  {
    if (ior->io_Message.mn_ReplyPort)
      DeleteMsgPort (ior->io_Message.mn_ReplyPort);
    DeleteIORequest (ior);
  }
}

void
closeall ()
{
  if (conio)
    freeio (conio);
  if (appkeymap)
    DeleteAppKeyMap (appkeymap);
}

void
closeout (UBYTE * errstring, LONG rc)
{
  if (*errstring)
    printf ("%s\n", errstring);
  closeall ();
  exit (rc);
}


SANA-II Developer Support Package / Changes

There have been no substantive changes from the Novemeber 7 Draft for
Final Comment and approval.  There have been minor clarifications and
typographical corrections and a section was added to clarify ARCNET
framing.

Since the Fish Disk/'91 DevCon draft of the SANA-II standard, here is a
summary list of the important changes:

- Packet type specification has been drastically simplified.  The original
  standard called for a generalized "Packet Magic" which all drivers and
  protocols had to deal with, even though few people should ever have to
  worry about the problem.  We could also have specified that there are
  802.3 SANA-II drivers and that there are ethernet drivers and that if
  you want 802.3 and ethernet (even if on the same wire) from the same
  machine, use two ethernet boards.  This didn't make sense because we
  don't anticipate multiple protocols needing to use 802.3 frames nor
  much encouragement for hardware manufactures to provide special 802.3
  drivers. The current solution keeps the standard simple and allows
  highly efficient implementations, but it does make ethernet drivers a
  little more complex and does make using 802.3 frames harder.

- The original SANA-II device driver specification therefore called for
  drivers to have no internal buffers and to get all buffers from
  protocols in the form of a data structure called a NetBuff. Hence, all
  protocols were required to use NetBuffs.  This was highly
  unsatisfactory since most protocols are implemented from an existing
  code base which includes its own buffer management scheme.  NetBuffs
  are removed from the standard and replaced with a function callback.

- The original standard called for an interface to the ability of some
  hardware to simultaneously accept packets for several hardware
  addresses. Such a feature is of dubious usefulness.  In order to
  simplify the standard, station aliases are no longer part of the
  SANA-II Network Device Driver Specification. If station aliasing does
  turn out to be a useful feature available on some hardware for the
  Amiga, the standard can easily be extended to re-introduce station
  aliasing.  Remember that all Exec drivers must check for io_Command
  values not supported by the driver. Hence, SANA-II commands can be
  added without requiring that existing drivers be rev'd.

- Since the IOSana2Req structure had to be changed anyway, many names in
  <devices/sana2.h> have been changed to be more consistent with other
  system names. It is believed that global search and replace should make
  this a mostly trivial change and that the benefits gained from
  consistent naming outweigh the inconvenience to those few who have
  existing SANA-II code.

- Events are now defined as a bit mask rather than as scalars.


SANA-II Developer Support Package / ethernet.txt

**	$Filename: ethernet.txt $
**	$Revision: 1.2 $
**	$Date: 92/01/10 15:18:46 $

#define S2WireType_Ethernet             1

ios2_DataLength:
    valid ethernet packets have 64 to 1500 bytes of data.

Address format:
    Ethernet addresses consist of 47 bits of address information and
    a 1 bit multicast flag. The standard for expressing ethernet
    addresses is as 6 bytes (octets) in the order in which the bytes
    are transmitted with the low-order bits in a byte transmitted
    first. The multicast flag bit is the least-significant bit of the
    first byte.

    Ethernet addresses in a Sana2IOReq occupy the first 6 bytes of
    an address field in transmission order with the low-order bits in
    a byte transmitted first.

Station Address:
    Each ethernet board must have a unique ethernet hardware address.
    Drivers will override any attempt to set the address to anything
    other than the ROM address.

Raw reads and writes:
    6 bytes of destination address,
    6 bytes of source address,
    2 bytes of type,
    64 to 1500 bytes of data
    (followed by 4 byte CRC value covering all of the above
     which is hardware generated and checked, hence not included
     in even raw packets)

Multicast:	Supported

Broadcast:	Supported

Promiscuous:	Supported

Packet Type Numbers for Ethernet are assigned by:

    Xerox Corporation
    Xerox Systems Institute
    475 Oakmead Parkway, Sunnyvale, CA 94086
    Attn: Ms. Fonda Pallone
    (408) 737-4652

Some Common Packet Type Numbers:

      decimal  Hex        Description
      -------  ---        -----------
         000   0000-05DC  IEEE 802.3 Length Field
        2048   0800       TCP/IP -- IP
        2054   0806       TCP/IP -- ARP
       32821   8035       TCP/IP -- RARP
       32923   809B       Appletalk
       33011   80F3       AppleTalk AARP (Kinetics)
       33100   814C       SNMP
       33079   8137-8138  Novell, Inc.


VIII-51: SANA-II Network Device Driver Specification

**	$Filename: ARCNET.txt $
**	$Revision: 1.3 $
**	$Date: 92/01/10 15:18:56 $

S2WireType_Arcnet	7

ios2_DataLength:
    506 byte MTU (because of the possibility of two byte Types).
    Packets of size 254, 255, or 256 bytes are padded to 257 bytes before
    transmition.

Station Address:
    ARCNET hardware may have addresses set with jumpers, DIP switches
    or software.  Different drivers may therefore behave differently
    with S2_CONFIGINTERFACE.

    Hardware addresses should be assigned by users from highest to lowest
    because there is some efficiency gained in the token passing scheme
    this way.  For example, on a three node network, hardware numbers 254,
    253 and 252 should be used rather than 1, 2 and 3.

Raw reads and writes:
    Short Packets (1-253 bytes)
        Destination Address		(1 byte)
        Source Address			(1 byte)
        Count (256-N-Type length)	(1 byte)
        Padding				(to byte number Count)
        Type				(1 or 2 bytes)
        Data				(N bytes)

    Long Packets (257-506 bytes)
        Destination Address		(1 byte)
        Source Address			(1 byte)
        zero				(1 byte)
        Count (512-N-Type length)	(1 byte)
        Padding				(to byte number Count)
        Type				(1 or 2 bytes)
        Data				(N bytes)

Multicast:	Not Supported

Broadcast:	Supported

Promiscuous:	Generally Not Supported

Packet Type Numbers for ARCNET are assigned by:
    Datapoint Corporation

Some Common Packet Type Numbers

    decimal  hex    description
    -------  ---    -----------
    221      DD     AppleTalk
    240      F0     TCP/IP -- IP   (RFC 1051)
    241      F1     TCP/IP -- ARP  (RFC 1051)
    212      F0     TCP/IP    IP   (RFC 1201, proposed)
    213      F1     TCP/IP -- ARP  (RFC 1201, proposed)
    214	 D6	TCP/IP -- RARP (RFC 1201, proposed)
    247      F7     Banyan Vines
    250      FA     Novell IPX


Developer Support Package / copybuff.doc

TABLE OF CONTENTS

   any_sana2_protocol/CopyFromBuff
   any_sana2_protocol/CopyToBuff


any_sana2_protocol/CopyFromBuff

NAME
    CopyFromBuff -- Copy n bytes from an abstract data structure.

SYNOPSIS
    success = CopyFromBuff(to, from, n)
    d0                     a0  a1    d0

    BOOL CopyToBuff(VOID *, VOID *, ULONG);

FUNCTION
    This function copies 'n' bytes of data in the abstract data structure
    pointed to by 'from' into the contigous memory pointed to by 'to'.
    'to' must contain at least 'n' bytes of usable memory or innocent
    memory will be overwritten.

INPUTS
    to              - pointer to contiguous memory to copy to.
    from            - pointer to abstract structure to copy from.
    n               - number of bytes to copy.

RESULT
    success         - TRUE if operation was successful, else FALSE.

EXAMPLE

NOTES
    This function must be callable from interupts.  In particular, this
    means that this function may not directly or indirectly call any
    system memory functions (since those functions rely on Forbid() to
    protect themselves) and that  you must not compile this function
    with stack checking enabled.  See the RKM:Libraries Exec:Interupts
    chapter for more details on what is legal in a routine called from
    an interupt handler.

    'C' programmers should not compile with stack checking (option '-v'
    in SAS) and should geta4() or __saveds.

BUGS

SEE ALSO


any_sana2_protocol/CopyToBuff

NAME
    CopyToBuff -- Copy n bytes to an abstract data structure.

SYNOPSIS
    success = CopyToBuff(to, from, n)
    d0                   a0  a1    d0

    BOOL CopyToBuff(VOID *, VOID *, ULONG);

FUNCTION
    This function first does any initialization and/or allocation
    required to prepare the abstract data structure pointed at by 'to'
    to be filled with 'n' bytes of data from 'from'.  It then executes
    the copy operation.

    If, for example, there is not enough memory available to prepare
    the abstract data structure, the call is failed and FALSE is returned.

    The buffer management scheme should be such that any memory needed
    to fulfill CopyToBuff() calls is already allocated from the system
    before the call to CopyToBuff() is made.

INPUTS
    to              - pointer to abstract structure to copy to.
    from            - pointer to contiguous memory to copy from.
    n               - number of bytes to copy.

RESULT
    success         - TRUE if operation was successful, else FALSE.

EXAMPLE

NOTES
    This function must be callable from interupts.  In particular, this
    means that this function may not directly or indirectly call any
    system memory functions (since those functions rely on Forbid() to
    protect themselves) and that you must not compile this function
    with stack checking enabled.  See the RKM:Libraries Exec:Interupts
    chapter for more details on what is legal in a routine called from
    an interupt handler.

    'C' programmers should not compile with stack checking (option '-v'
    in SAS) and should geta4() or __saveds.

BUGS

SEE ALSO


VIII-51/include/devices/sana2specialstats.i

    IFND	SANA2_SANA2SPECIALSTATS_I
SANA2_SANA2SPECIALSTATS_I	SET	1
**
**	$Filename: devices/sana2specialstats.i $
**	$Revision: 1.3 $
**	$Date: 92/01/10 15:10:35 $
**
**	Defined ids for SANA-II special statistics.
**
**
**	(C) Copyright 1991-1999 Amiga, Inc.
**		All Rights Reserved
**

    IFND	SANA2_SANA2DEVICE_I
    INCLUDE	"sana2/sana2device.i"
    ENDC	!SANA2_SANA2DEVICE_I

;
; The SANA-II special statistic identifier is an unsigned 32 number.
; The upper 16 bits identify the type of network wire type to which
; the statistic applies and the lower 16 bits identify the particular
; statistic.
;

; If you'd like to add new statistic identifiers, contact CATS.

;
; defined ethernet special statistics
;

S2SS_ETHERNET_BADMULTICAST	EQU	((((S2WIRETYPE_ETHERNET)&$ffff)<<16)|$0000)
;
; This count will record the number of times a received packet tripped
; the hardware's multicast filtering mechanism but was not actually in
; the current multicast table.
;

S2SS_ETHERNET_RETRIES		EQU	((((S2WIRETYPE_ETHERNET)&$ffff)<<16)|$0001)
;
; This count records the total number of retries which have resulted
; from transmissions on this board.
;

    ENDC	SANA2_SANA2SPECIALSTATS_I


VIII-51/include/devices/sana2.i

        IFND    SANA2_SANA2DEVICE_I
SANA2_SANA2DEVICE_I     SET     1
**
**	$Filename: devices/sana2.i $
**	$Revision: 1.11 $
**	$Date: 92/01/10 15:10:19 $
**
**      Structure definitions for SANA-II devices.
**
**      (C) Copyright 1991-1999 Amiga, Inc.
**              All Rights Reserved
**

        IFND    EXEC_TYPES_I
        INCLUDE "exec/types.i"
        ENDC

        IFND    EXEC_PORTS_I
        INCLUDE "exec/ports.i"
        ENDC

        IFND    EXEC_IO_I
        INCLUDE "exec/io.i"
        ENDC

        IFND    EXEC_ERRORS_I
        INCLUDE "exec/errors.i"
        ENDC

        IFND    DEVICES_TIMER_I
        INCLUDE "devices/timer.i"
        ENDC

        IFND    UTILITY_TAGITEM_I
        INCLUDE "utility/tagitem.i"
        ENDC

SANA2_MAX_ADDR_BITS     EQU     128
SANA2_MAX_ADDR_BYTES    EQU     ((SANA2_MAX_ADDR_BITS+7)/8)

 STRUCTURE IOSana2Req,0
        STRUCT  IOS2_REQ,IO_SIZE
        ULONG   IOS2_WIREERROR          ; wire type specific error
        ULONG   IOS2_PACKETTYPE         ; packet type
        STRUCT  IOS2_SRCADDR,SANA2_MAX_ADDR_BYTES       ; source address
        STRUCT  IOS2_DSTADDR,SANA2_MAX_ADDR_BYTES       ; dest address
        ULONG   IOS2_DATALENGTH         ; length of packet data
        APTR    IOS2_DATA               ; packet data (not touched by driver!)
        APTR    IOS2_STATDATA           ; statistics data pointer
        APTR    IOS2_BUFFERMANAGEMENT   ; see SANA-II OpenDevice adoc

        LABEL   IOS2_SIZE

;
; equates for the IOS2_FLAGS field
;

SANA2IOB_RAW    EQU     7               ; raw packet IO requested
SANA2IOF_RAW    EQU     (1<<SANA2IOB_RAW)

SANA2IOB_BCAST  EQU     6               ; broadcast packet (received)
SANA2IOF_BCAST  EQU     (1<<SANA2IOB_BCAST)

SANA2IOB_MCAST  EQU     5               ; multicast packet (received)
SANA2IOF_MCAST  EQU     (1<<SANA2IOB_MCAST)

SANA2IOB_QUICK  EQU     IOB_QUICK       ; quick IO requested (0)
SANA2IOF_QUICK  EQU     IOF_QUICK

;
; equates for OpenDevice()
;

SANA2OPB_MINE   EQU     0               ; exclusive access requested
SANA2OPF_MINE   EQU     (1<<SANA2OPB_MINE)

SANA2OPB_PROM   EQU     1               ; promiscuous mode requested
SANA2OPF_PROM   EQU     (1<<SANA2OPB_PROM)

S2_Dummy        EQU     (TAG_USER+$B0000)
S2_COPYTOBUFF   EQU     S2_Dummy+1
S2_COPYFROMBUFF EQU     S2_Dummy+2

 STRUCTURE SANA2DEVICEQUERY,0
        ; Standard information
        ULONG   S2DQ_SIZEAVAILABLE      ; bytes available
        ULONG   S2DQ_SIZESUPPLIED       ; bytes supplied
        ULONG    S2DQ_FORMAT             ; this is type 0
        ULONG    S2DQ_DEVICELEVEL        ; this document is level 0

        ; Common information
        UWORD   S2DQ_ADDRFIELDSIZE           ; address size in bits
        ULONG   S2DQ_MTU                ; maximum packet data size
        ULONG    S2DQ_BPS                ; line rate (bits/sec)
        ULONG    S2DQ_HARDWARETYPE       ; what the wire is

        ; Format specific information
        LABEL   S2DQ_SIZE

;
; defined SANA-II hardware types
;

S2WIRETYPE_ETHERNET             EQU     1
S2WIRETYPE_IEEE802              EQU     6
S2WIRETYPE_ARCNET               EQU     7
S2WIRETYPE_LOCALTALK            EQU     11

S2WIRETYPE_PPP                  EQU     253
S2WIRETYPE_SLIP                 EQU     254
S2WIRETYPE_CSLIP                EQU     255

 STRUCTURE SANA2PACKETTYPESTATS,0
        ULONG    S2PTS_TXPACKETS         ; transmitted count
        ULONG    S2PTS_RXPACKETS         ; received count
        ULONG    S2PTS_TXBYTES           ; bytes transmitted count
        ULONG    S2PTS_RXBYTES           ; bytes received count
        ULONG    S2PTS_PACKETSDROPPED    ; packets dropped count
        LABEL   S2PTS_SIZE

 STRUCTURE SANA2SPECIALSTATRECORD,0
        ULONG   S2SSR_TYPE              ; statistic identifier
        ULONG    S2SSR_COUNT             ; the statistic
        APTR    S2SSR_STRING            ; statistic name
        LABEL   S2SSR_SIZE

 STRUCTURE SANA2SPECIALSTATHEADER,0
        ULONG   S2SSH_RECORDCOUNTMAX            ; room available
        ULONG   S2SSH_RECORDCOUNTSUPPLIED       ; number supplied
        LABEL   S2SSH_SIZE

 STRUCTURE SANA2DEVICESTATS,0
        ULONG    S2DS_PACKETSRECEIVED           ; received count
        ULONG    S2DS_PACKETSSENT               ; transmitted count
        ULONG    S2DS_BADDATA                   ; bad packets received
        ULONG    S2DS_OVERRUNS                  ; hardware miss count
        ULONG    S2DS_SOFTMISSES                ; software miss count
        ULONG    S2DS_UNKNOWNTYPESRECEIVED      ; orphan count
        ULONG    S2DS_RECONFIGURATIONS          ; network reconfigurations
        STRUCT  S2DS_LASTSTART,TV_SIZE          ; time of last online
        LABEL   S2DS_SIZE

;
; Device Commands
;

S2_START                EQU     (CMD_NONSTD)

S2_DEVICEQUERY          EQU     (S2_START+0)
S2_GETSTATIONADDRESS    EQU     (S2_START+1)
S2_CONFIGINTERFACE      EQU     (S2_START+2)
S2_ADDMULTICASTADDRESS  EQU     (S2_START+5)
S2_DELMULTICASTADDRESS  EQU     (S2_START+6)
S2_MULTICAST            EQU     (S2_START+7)
S2_BROADCAST            EQU     (S2_START+8)
S2_TRACKTYPE            EQU     (S2_START+9)
S2_UNTRACKTYPE          EQU     (S2_START+10)
S2_GETTYPESTATS         EQU     (S2_START+11)
S2_GETSPECIALSTATS      EQU     (S2_START+12)
S2_GETGLOBALSTATS       EQU     (S2_START+13)
S2_ONEVENT              EQU     (S2_START+14)
S2_READORPHAN           EQU     (S2_START+15)
S2_ONLINE               EQU     (S2_START+16)
S2_OFFLINE              EQU     (S2_START+17)

S2_END                  EQU     (S2_START+18)

;
; defined errors for IOS2_ERROR
;

S2ERR_NO_ERROR          EQU     0       ; peachy-keen
S2ERR_NO_RESOURCES      EQU     1       ; resource allocation failure
S2ERR_BAD_ARGUMENT      EQU     3       ; garbage somewhere
S2ERR_BAD_STATE         EQU     4       ; inappropriate state
S2ERR_BAD_ADDRESS       EQU     5       ; who?
S2ERR_MTU_EXCEEDED      EQU     6       ; too much to chew
S2ERR_NOT_SUPPORTED     EQU     8       ; command not supported by hardware
S2ERR_SOFTWARE          EQU     9       ; software error detected
S2ERR_OUTOFSERVICE	EQU	10	; driver is offline
;SEE ALSO <exec/errors.i>

;
; defined errors for IOS2_WIREERROR
;

S2WERR_GENERIC_ERROR    EQU     0       ; no specific info available
S2WERR_NOT_CONFIGURED   EQU     1       ; unit not configured
S2WERR_UNIT_ONLINE      EQU     2       ; unit is currently online
S2WERR_UNIT_OFFLINE     EQU     3       ; unit is currently offline
S2WERR_ALREADY_TRACKED  EQU     4       ; protocol already tracked
S2WERR_NOT_TRACKED      EQU     5       ; protocol not tracked
S2WERR_BUFF_ERROR       EQU     6       ; buffer mgmt func returned error
S2WERR_SRC_ADDRESS      EQU     7       ; source address problem
S2WERR_DST_ADDRESS      EQU     8       ; destination address problem
S2WERR_BAD_BROADCAST    EQU     9       ; broadcast address problem
S2WERR_BAD_MULTICAST    EQU     10      ; multicast address problem
S2WERR_MULTICAST_FULL   EQU     11      ; multicast address list full
S2WERR_BAD_EVENT        EQU     12      ; unsupported event class
S2WERR_BAD_STATDATA     EQU     13      ; statdata failed sanity check
S2WERR_IS_CONFIGURED    EQU     15      ; attempt to config twice
S2WERR_NULL_POINTER     EQU     16      ; null pointer detected

;
; defined events
;

S2EVENT_ERROR       equ 1      ; error catch all
S2EVENT_TX          equ 2      ; transmitter error catch all
S2EVENT_RX          equ 4      ; receiver error catch all
S2EVENT_ONLINE      equ 8      ; unit is in service
S2EVENT_OFFLINE     equ 16     ; unit is not in service
S2EVENT_BUFF        equ 32     ; buffer mgmt function error catch all
S2EVENT_HARDWARE    equ 64     ; hardware error catch all
S2EVENT_SOFTWARE    equ 128    ; software error catch all

        ENDC    SANA2_SANA2DEVICE_I


Amiga® RKM Devices: Contents

     Preface             Chapters             NOTE:
                         --------
  1  Introduction                  9  Parallel Device
  2  Audio Device                 10  Printer Device
  3  Clipboard Device             11  SCSI Device
  4  Console Device               12  Serial Device
  5  Gameport Device              13  Timer Device
  6  Input Device                 14  Trackdisk Device
  7  Keyboard Device              15  Resources
  8  Narrator Device

  A  IFF:Interchange File Format      Index
  B  Example Device
  C  Amiga Floppy Boot Process And Physical Layout


Please note...

  All AmigaGuide buttons in this manual for Amiga specific structures
  and functions point to the 2.04 Includes and Autodocs manual.


Amiga® RKM Devices: Preface

The Amiga® Technical Reference Series is the official guide to programming
Amiga computers.  This revised edition of the Amiga ROM Kernel
Reference Manual: Devices provides detailed information about the Amiga's
I/O subsystems.  It has been updated for Release 2 (Kickstart V36 and up)
of the Amiga operating system, however, most of the material and example
programs are also compatible with version 1.3.

This book is intended for the following audiences:

   *  Novice Amiga programmers who want to try out features of the Amiga
      devices without writing full-blown applications.

   *  Experienced programmers new to the Amiga.

   *  Amiga programmers and developers who want to use the devices in an
      application.

It is assumed that the reader can program in C or at least understand it.

Here is a brief overview of the contents:

 Chapter 1, Introduction to Amiga System Devices   An introduction to the
concept of an Amiga system device, the device interface, and how to
perform I/O using the devices.

 Chapter 2, Audio Device   The Amiga audio device allows you to play music
and make sounds.  Two example programs are included.

 Chapter 3, Clipboard Device   The clipboard device is a central facility
for sharing information between applications.  The chapter covers the
types of clipboard data and the proper ways to use the clipboard.  Two
example programs are included plus an extensively commented module of
support functions for the programs.

 Chapter 4, Console Device  The console device is the text-oriented
interface for Amiga windows.  The chapter lists the escape sequences used
for console windows and the types of console windows.  An example program
is included.

 Chapter 5, Gameport Device   The gameport device manages the various
pointing devices you plug into the mouse/joystick connectors.  The chapter
discusses the types of pointing devices, the protocol for using the device
and includes an example program.

 Chapter 6, Input Device   The input device collects input event
information and passes this on to the operating system.  The chapter
covers this interaction between the various input sources of the system,
tells how to create your own input events and includes two example
programs.

 Chapter 7, Keyboard Device   The keyboard device is the Amiga keyboard
manager.  The chapter covers how to read the keyboard at a low level and
also how to program system reset (Ctrl-Amiga-Amiga) handlers. Three
example programs are included.

 Chapter 8, Narrator Device   The narrator device is the voice of the
Amiga.  This chapter explains how to use the narrator device and the
translator library, how to write phonetic strings for the device, and
discusses the technical aspects of computer generated speech in thorough,
but understandable terms. Two example programs are included.

 Chapter 9, Parallel Device   The parallel device manages the Amiga
parallel port. Two example programs are included.

 Chapter 10, Printer Device   The printer device translates character
streams into printer specific sequences.  The chapter covers how to use
the printer device and how to write your own printer driver.  It contains
two example programs and two complete printer drivers.

 Chapter 11, SCSI Device   The SCSI device provides the Small Computer
System Interface for the Amiga.  The chapter covers how to send Amiga
specific and SCSI specific commands to SCSI devices.  An example program
is included.

 Chapter 12, Serial Device   The serial device manages the Amiga serial
port.  Three example programs are included.

 Chapter 13, Timer Device   The timer device an interface to the Amiga's
internal clocks.  The chapter explains the types of clocks and clock
units.  Four example programs are included.

 Chapter 14, Trackdisk Device   The trackdisk device controls the Amiga
disk drives.  The chapter covers how to use the drives at a high-level
(formatted reads and writes) and low-level (raw reads and writes). An
example program is included.

 Chapter 15, Resources   The Amiga resources are a collection of low-level
interfaces to special Amiga hardware.  The chapter covers the general
resource interface and how to use all seven resources. Example code is
included for all but one of the resources.

 Appendix A, IFF, Interchange File Format   IFF is the standardized file
format of the Amiga.  This appendix introduces IFF, covers five of the IFF
types, lists the official FORM and Chunk names that are reserved and in
use and how to register new ones.  IFF include files, link modules,
example programs and utilities are included.

 Appendix B, Example Device   This appendix contains the assembly code for
an Amiga device for all those who want to create their own custom software
I/O device.

 Appendix C, Amiga Floppy Boot Process and Physical Layout   This appendix
lists the method used to read the boot block of a floppy and how the data
is arranged in the boot block.

The other manuals in this series are the Amiga User Interface Style Guide,
an application design specification and reference work for Amiga
programmers, the Amiga ROM Kernel Reference Manual: Includes and Autodocs,
an alphabetically organized reference of ROM function summaries and Amiga
system include files, the Amiga ROM Kernel Reference Manual: Libraries, a
work consisting of tutorial-style chapters on the use of each Amiga system
library, and the Amiga Hardware Reference Manual, a detailed description
of the Amiga's hardware components.


Amiga® RKM Devices: 1 Introduction to Amiga System Devices

The Amiga system devices are software engines that provide access to the
Amiga hardware.  Through these devices, a programmer can operate a modem,
spin a disk drive motor, time an event, speak to a user and blast a
trumpet sound in beautiful, living stereo.  Yet, for all that variety, the
programmer uses each device in the same basic manner.

                        Amiga System Devices

 Audio         Controls the use of the audio hardware
 Clipboard     Manages the cutting and pasting of common data blocks
 Console       Provides the text-oriented user interface.
 Gameport      Controls the two mouse/joystick ports.
 Input         Processes input from the gameport and keyboard devices.
 Keyboard      Controls the keyboard.
 Narrator      Produces the Amiga synthesized speech.
 Parallel      Controls the parallel port.
 Printer       Converts a standard set of printer control codes to printer
               specific codes.
 SCSI          Controls the Small Computer Standard Interface hardware.
 Serial        Controls the serial port.
 Timer         Provides timing functions to measure time intervals and send
               interrupts.
 Trackdisk     Controls the Amiga floppy disk drives.

 What is a Device?                             I/O Request Completion
 Accessing a Device                            Ending Device Access
 Using a Device                                Devices With Functions
 Synchronous vs. Asynchronous Requests         Example Device Programs


1 Introduction to Amiga System Devices / What is a Device?

An Amiga device is a software module that accepts commands and data and
performs I/O operations based on the commands it receives.  In most cases,
a device interacts with either internal or external hardware. Generally,
an Amiga device runs as a separate task which is capable of processing
your commands while your application attends to other things.

Device I/O is based on the Exec messaging system.  The philosophy behind
the devices is that I/O operations should be consistent and uniform.  You
print a file in the same manner as you play an audio sample, i.e., you
send the device in question a WRITE command and the address of the buffer
holding the data you wish to write.

The result is that the interface presented to the programmer is
essentially device independent and accessible from any computer language.
This greatly expands the power the Amiga computer brings to the programmer
and, ultimately, to the user.

Devices support two types of commands: Exec standard commands like READ
and WRITE, and device specific commands like the trackdisk device MOTOR
command which controls the floppy drive motor.  The Exec standard commands
are supported by most Amiga devices.  You should keep in mind, however,
that supporting standard commands does not mean that all devices execute
them in exactly the same manner.

This manual contains a chapter about each of the Amiga devices.  The
chapters cover how you use a device and the commands it supports.  In
addition, the Amiga ROM Kernel Reference Manual: Includes and Autodocs
contains expanded explanations of the commands and the include files for
each device, and the Amiga ROM Kernel Reference Manual: Libraries contains
chapters on Exec.  The command explanations list the data, flags, and
other information required by a device to execute a command.  The Exec
chapters provide detailed discussions of its operation.  Both are very
useful manuals to have on your desk when you are programming the devices.


1 Introduction to Amiga System Devices / Accessing a Device

Accessing a device requires obtaining a message port, allocating memory
for a specialized message packet called an I/O request, setting a pointer
to the message port in the I/O request, and finally, establishing the link
to the device itself by opening it.  An example of how to do this will be
provided later in this chapter.

The message port is used by the device to return messages to you.  A
message port is obtained by calling the CreateMsgPort() or CreatePort()
function.  You must delete the message port when you are finished by
calling the DeleteMsgPort() or DeletePort() function.

For pre-V36 versions of the operating system (before Release 2.0), use the
amiga.lib functions CreatePort() and DeletePort(); for V36 and higher, use
the Exec functions CreateMsgPort() and DeleteMsgPort(). CreatePort() and
DeletePort() are upward compatible, you can use them with V36/V37;
CreateMsgPort() and DeleteMsgPort() are not backward compatible, however.

The I/O request is used to send commands and data from your application to
the device.  The I/O request consists of fields used to hold the command
you wish to execute and any parameters it requires.  You set up the fields
with the appropriate information and send it to the device by using Exec
I/O functions.

At least four methods exist for creating an I/O request:

   *  Declaring it as a structure.  The memory required will be allocated
      at compile time.

   *  Declaring it as a pointer and calling the AllocMem() function.  You
      will have to call the FreeMem() function to release the memory when
      you are done.

   *  Declaring it as a pointer and calling the CreateExtIO() function.
      This function not only allocates the memory for the request, it also
      puts the message port in the I/O request.  You will have to call the
      DeleteExtIO() function to delete the I/O request when you are done.
      This is the pre-V36 method (used in 1.3 and earlier versions of the
      operating system), but is upward compatible.

   *  Declaring it as a pointer and calling the CreateIORequest() function.
      This function not only allocates the memory for the request, it also
      puts the message port in the I/O request.  You will have to call the
      DeleteIORequest() function to delete the I/O request when you are
      done.  This is the V36/V37 method; it is not backwards compatible.

The message port pointer in the I/O request tells the device where to
respond with messages for your application.  You must set a pointer to the
message port in the I/O request if you declare it as a structure or
allocate memory for it using AllocMem().

The device is opened by calling the OpenDevice() function.  In addition to
establishing the link to the device, OpenDevice() also initializes fields
in the I/O request.  OpenDevice() has this format:

  return = OpenDevice(device_name,unit_number,
                     (struct IORequest *)IORequest,flags)

where:

   *  device_name is one of the following NULL-terminated strings for
      system devices:

        audio.device        keyboard.device    serial.device
        clipboard.device    narrator.device    timer.device
        console.device      parallel.device    trackdisk.device
        gameport.device     printer.device     input.device
        scsi.device

   *  unit_number refers to one of the logical units of the device. Devices
      with one unit always use unit 0.  Multiple unit devices like the
      trackdisk device and the timer device use the different units for
      specific purposes.  The device chapters discuss the units in detail.

   *  IORequest is the structure discussed above.  Some of the devices have
      their own I/O requests defined in their include files and others use
      standard I/O requests, (IOStdReq).  The device chapters list the I/O
      request that each device requires.

   *  flags are bits set to indicate options for some of the devices.  This
      field is set to zero for devices which don't accept options when they
      are opened.  The device chapters and autodocs list the flags values
      and uses.

   *  return is an indication of whether the OpenDevice() was successful
      with zero indicating success.  Never assume that a device will
      successfully open.  Check the return value and act accordingly.

   Zero Equals Success for OpenDevice().
   -------------------------------------
   Unlike most Amiga system functions, OpenDevice() returns zero for
   success and a device-specific error value for failure.


1 Introduction to Amiga System Devices / Using a Device

Once a device has been opened, you use it by passing the I/O request to
it. When the device processes the I/O request, it acts on the information
the I/O request contains and returns a reply message, i.e., the I/O
request, to the reply port specified in the I/O request when it is
finished. The I/O request is passed to a device using one of three
functions, DoIO(), SendIO() and BeginIO(). They take only one argument:
the I/O request you wish to pass to the device.

   *  DoIO() is a synchronous function. It will not return until the device
      has responded to the I/O request.

   *  SendIO() is an asynchronous function.  It can return immediately, but
      the I/O operation it initiates may take a short or long time.  Using
      SendIO() requires you to monitor the message port for a return
      message from the device.  In addition, some devices do not actually
      respond asynchronously even though you called SendIO(); they will
      return when the I/O operation is finished.

   *  BeginIO() is commonly used to control the quick I/O bit when sending
      an I/O request to a device.  When the quick I/O flag (IOF_QUICK) is
      set in the I/O request, a device is allowed to take certain shortcuts
      in performing and completing a request.  If the request can complete
      immediately, the device will not return a reply message and the quick
      I/O flag will remain set.  If the request cannot be completed
      immediately, the QUICK_IO flag will be clear.  DoIO() normally
      requests quick I/O; SendIO() does not.

DoIO() and SendIO() are most commonly used.

An I/O request typically has three fields set for every command sent to a
device.  You set the command itself in the io_Command field, a pointer to
the data for the command in the io_Data field, and the length of the data
in the io_Length field.

  SerialIO->IOSer.io_Length = sizeof(ReadBuffer);
  SerialIO->IOSer.io_Data = ReadBuffer;
  SerialIO->IOSer.io_Command  = CMD_READ;
  SendIO((struct IORequest *)SerialIO);

Commands consist of two parts - a prefix and the command word separated by
an underscore, all in upper case.  The prefix indicates whether the
 command is an Exec or device specific command.  All Exec commands have
CMD as the prefix.  They are defined in the include file exec/io.h.

 Amiga Exec Commands
 Amiga System Device Command Prefixes and Examples


1 / Using a Device /Amiga Exec Commands

        CMD_CLEAR       CMD_READ        CMD_STOP
        CMD_FLUSH       CMD_RESET       CMD_WRITE
        CMD_INVALID     CMD_START       CMD_UPDATE

You should not assume that a device supports all Exec commands.  Always
check the documentation before attempting to use one of them.

Device specific command prefixes vary with the device.


1 / Using a Device / Amiga System Device Command Prefixes and Examples

        Device          Prefix                          Example
        ------          ------                          -------
        Audio           ADCMD                           ADCMD_ALLOCATE
        Clipboard       CBD                             CBD_POST
        Console         CD                              CD_ASKKEYMAP
        Gameport        GPD                             GPD_SETCTYPE
        Input           IND                             IND_SETMPORT
        Keyboard        KBD                             KBD_READMATRIX
        Narrator        no device specific commands
        Parallel        PDCMD                           PDCMD_QUERY
        Printer         PRD                             PRD_PRTCOMMAND
        SCSI            HD                              HD_SCSICMD
        Serial          SDCMD                           SDCMD_BREAK
        Timer           TR                              TR_ADDREQUEST
        Trackdisk       TD and ETD                      TD_MOTOR/ETD_MOTOR

Each device maintains its own I/O request queue.  When a device receives
an I/O request, it either processes the request immediately or puts it in
the queue because one is already being processed.   After an I/O request
is completely processed, the device checks its queue and if it finds
another I/O request, begins to process that request.


1 Introduction Amiga System Devices / Synchronous vs. Asynchronous Requests

As stated above, you can send I/O requests to a device synchronously or
asynchronously.  The choice of which to use is largely a function of your
application.

Synchronous requests use the DoIO() function.  DoIO() will not return
control to your application until the I/O request has been satisfied by
the device.  The advantage of this is that you don't have to monitor the
message port for the device reply because DoIO() takes care of all the
message handling. The disadvantage is that your application will be tied
up while the I/O request is being processed, and should the request not
complete for some reason, DoIO() will not return and your application will
hang.

Asynchronous requests use the SendIO() and BeginIO() functions. Both
return to your application almost immediately after you call them.  This
allows you to do other operations, including sending more I/O requests to
the device.

   Do Not Touch!
   -------------
   When you use SendIO() or BeginIO(), the I/O request you pass to the
   device and any associated data buffers should be considered
   read-only. Once you send it to the device, you must not modify it in
   any way until you receive the reply message from the device or abort
   the request (though you must still wait for a reply). Any exceptions
   to this rule are documented in the autodoc for the device.

Sending multiple asynchronous I/O requests to a device can be tricky
because devices require them to be unique and initialized.  This means
you can't use an I/O request that's still in the queue, but you need the
fields which were initialized in it when you opened the device.  The
solution is to copy the initialized I/O request to another I/O request(s)
before sending anything to the device.

Regardless of what you do while you are waiting for an asynchronous I/O
request to return, you need to have some mechanism for knowing when the
request has been done.  There are two basic methods for doing this.

The first involves putting your application into a wait state until the
device returns the I/O request to the message port of your application.
You can use the WaitIO(), Wait() or WaitPort() function to wait for the
return of the I/O request.

WaitIO() not only waits for the return of the I/O request, it also takes
care of all the message handling functions.  This is very convenient, but
you can pay for this convenience: your application will hang in the
unlikely event that the I/O request does not return.

Wait() waits for a signal to be sent to the message port.  It will awaken
your task when the signal arrives, but you are responsible for all of the
message handling.

WaitPort() waits for the message port to be non-empty.  It returns a
pointer to the message in the port, but you are responsible for all of the
message handling.

The second method to detect when the request is complete involves using
the CheckIO() function.  CheckIO() takes an I/O request as its argument
and returns an indication of whether or not it has been completed. When
CheckIO() returns the completed indication, you will still have to remove
the I/O request from the message port.


1 Introduction to Amiga System Devices / I/O Request Completion

A device will set the io_Error field of the I/O request to indicate the
success or failure of an operation.  The indication will be either zero
for success or a non-zero error code for failure.  There are two types of
error codes:  Exec I/O and device specific. Exec I/O errors are defined in
the include file exec/errors.h; device specific errors are defined in the
include file for each device.  You should always check that the operation
you requested was successful.

The exact method for checking io_Error can depend on whether you use
DoIO() or SendIO().   In both cases, io_Error will be set when the I/O
request is returned, but in the case of DoIO(), the DoIO() function itself
returns the same value as io_Error.

This gives you the option of checking the function return value:

  SerialIO->IOSer.io_Length   = sizeof(ReadBuffer);
  SerialIO->IOSer.io_Data  = ReadBuffer;
  SerialIO->IOSer.io_Command  = CMD_READ;
  if (DoIO((struct IORequest *)SerialIO);
      printf("Read failed.  Error: %ld\n",SerialIO->IOSer.io_Error);

Or you can check io_Error directly:

  SerialIO->IOSer.io_Length   = sizeof(ReadBuffer);
  SerialIO->IOSer.io_Data  = ReadBuffer;
  SerialIO->IOSer.io_Command  = CMD_READ;
  DoIO((struct IORequest *)SerialIO);

  if (SerialIO->IOSer.io_Error)
      printf("Read failed.  Error: %ld\n",SerialIO->IOSer.io_Error);

Keep in mind that checking io_Error is the only way that I/O requests sent
by SendIO() can be checked.

Testing for a failed I/O request is a minimum step, what you do beyond
that depends on your application.  In some instances, you may decide to
resend the I/O request, and in others, you may decide to stop your
application.   One thing you'll almost always want to do is to inform the
user that an error has occurred.

   Exiting The Correct Way.
   ------------------------
   If you decide that you must prematurely end your application, you
   should deallocate, release, give back and let go of everything you
   took to run the application.  In other words, you should exit
   gracefully.


1 Introduction to Amiga System Devices / Ending Device Access

You end device access by reversing the steps you took to access it.  This
means you close the device, deallocate the I/O request memory and delete
the message port.  In that order!

Closing a device is how you tell Exec that you are finished using a device
and any associated resources.  This can result in housecleaning being
performed by the device.  However, before you close a device, you might
have to do some housecleaning of your own.

A device is closed by calling the CloseDevice() function. The
CloseDevice() function does not return a value. It has this format:

  CloseDevice(IORequest)

where IORequest is the I/O request used to open the device.

You should not close a device while there are outstanding I/O requests,
otherwise you can cause major and minor problems.  Let's begin with the
minor problem: memory.  If an I/O request is outstanding at the time you
close a device, you won't be able to reclaim the memory you allocated for
it.

The major problem: the device will try to respond to the I/O request.  If
the device tries to respond to an I/O request, and you've deleted the
message port (which is covered below), you will probably crash the system.

One solution would be to wait until all I/O requests you sent to the
device return.  This is not always practical if you've sent a few requests
and the user wants to exit the application immediately.

In that case, the only solution is to abort and remove any outstanding I/O
requests. You do this with the functions AbortIO() and WaitIO().  They
must be used together for cleaning up. AbortIO() will abort an I/O
request, but will not prevent a reply message from being sent to the
application requesting the abort. WaitIO() will wait for an I/O request to
complete and remove it from the message port.  This is why they must be
used together.

   Be Careful With AbortIO().
   --------------------------
   Do not AbortIO() an I/O request which has not been sent to a device.
   If you do, you may crash the system.

After the device is closed, you must deallocate the I/O request memory.
The exact method you use depends on how you allocated the memory in the
first place.  For AllocMem() you call FreeMem(), for CreateExtIO() you
call DeleteExtIO(), and for CreateIORequest() you call DeleteIORequest().
If you allocated the I/O request memory at compile time, you naturally
have nothing to free.

Finally, you must delete the message port you created.  You delete the
message port by calling DeleteMsgPort() if you used CreateMsgPort(), or
DeletePort() if you used CreatePort().

Here is the checklist for gracefully exiting:

   1. Abort any outstanding I/O requests with AbortIO()

   2. Wait for the completion of any outstanding or aborted I/O requests
      with WaitIO().

   3. Close the device with CloseDevice().

   4. Release the I/O request memory with either DeleteIORequest(),
      DeleteExtIO() or FreeMem() (as appropriate).

   5. Delete the message port with DeleteMsgPort() or DeletePort().


1 Introduction to Amiga System Devices / Devices With Functions

Some devices, in addition to their commands, provide functions which can
be directly called by applications.  These functions are documented in the
device specific FD files and Autodocs of the Amiga ROM Kernel Reference
Manual: Includes and Autodocs and the device chapters of this manual.

Devices with functions behave much like Amiga libraries, i.e., you set up
a base address pointer and call the functions as offsets from the pointer.
(See the Exec Libraries" chapter of the Amiga ROM Kernel Reference
Manual: Libraries.)

The procedure for accessing a device's functions is as follows:

   *  Declare the device base address variable in the global data area.
      The name of the base address can be found in the device's FD file.

   *  Create a message port using one of the previously discussed methods
      if you haven't already done so.

   *  Create an I/O request using one of the previously discussed methods
      if you haven't already done so. Remember to set the message port
      pointer in the I/O request if necessary.

   *  Call OpenDevice(), passing the I/O request if you haven't already
      done so.  When you do this, the device returns a pointer to its base
      address in the io_Device field of the I/O request structure.  Consult
      the include file for the structure you are using to determine the
      full name of the io_Device field.  The base address is only valid
      while the device is open.

   *  Set the device base address variable to the pointer returned in the
      io_Device field.

We will use the timer device to illustrate the above method.  The name of
the timer device base address is listed in its FD file as "TimerBase."

  #include <devices/timer.h>

  struct Library *TimerBase;    /* device base address pointer */

  struct MsgPort *TimerMP;      /* message port pointer */
  struct timerequest *TimerIO;  /* I/O request pointer */

      /* Create the message port */
  if (TimerMP=CreatePort(NULL,NULL))
      {
          /* Create the I/O request */
      if (TimerIO = (struct timerequest *)
          {           CreateExtIO(TimerMP,sizeof(struct timerequest)))
              /* Open the timer device */
          if (!(OpenDevice(TIMERNAME,UNIT_MICROHZ,TimerIO,0)))
              {
              /* Set up pointer for timer functions */
              TimerBase = (struct Library *)TimerIO->tr_node.io_Device;

              ... use functions ...

              /* Close the timer device */
              CloseDevice(TimerIO);
              }

          /* Delete the I/O request */
          DeleteExtIO(TimerIO);
          }

      /* Delete the message port */
      DeletePort(TimerMP);
      }


1 Introduction to Amiga System Devices / Example Device Programs

The following short programs are examples of how to use a device.  Both
send the serial device command SDCMD_QUERY to the serial device to
determine the status of the serial device lines and registers.  The first
program is for pre-V36 versions of the operating system (before Release 2)
and the second is for V36 and higher.  You may use the pre-V36 version
with V36 and higher, but you may not use the V36 version with older
systems.

The programs differ in the way they create the message port and I/O
request.  The pre-V36 version uses the amiga.lib functions CreatePort() to
create the message port and CreateExtIO() to create the I/O request; the
V36 version uses the Exec functions CreateMsgPort() to create the message
port and CreateIORequest() to create the I/O request.  Those are the only
differences.

     Device Usage Example (Pre-V36)
     Device Usage Example (Kickstart V36 And Up)


Amiga® RKM Devices: 9 / Parallel Device

The parallel device provides a hardware-independent interface to the
Amiga's Centronics-compatible parallel port. The primary use of the Amiga
parallel port is for output to printers, but with its extensions for
bi-directional I/O, it can also be used for communication with digitizers
and high-speed links with other computers.  The parallel device is based
on the conventions of Exec device I/O, with extensions for parameter
setting and control.

 Parallel Device Commands and Functions
 Device Interface
 Ending A Read or Write with Termination Characters
 Setting Parallel Parameters
 Querying the Parallel Device
 Additional Information on the Parallel Device


9 Parallel Device / Parallel Device Commands and Functions

Command          Operation
-------          ---------
CMD_FLUSH        Purge all queued requests for the parallel device.  Does
                 not affect active requests.

CMD_READ         Read a stream of characters from the parallel port.  The
                 number of characters can be specified or a termination
                 character(s) can be used.

CMD_RESET        Reset the parallel port to its initialized state.  All
                 active and queued I/O requests will be aborted.

CMD_START        Restart all paused I/O over the parallel port.
                 Reactivates the handshaking sequence.

CMD_STOP         Pause all active I/O over the parallel port.  Deactivates
                 the handshaking sequence.

CMD_WRITE        Write out a stream of characters to the parallel port.
                 The number of characters can be specified or a
                 NULL-terminated string can be sent.

PDCMD_QUERY      Return the status of the parallel port lines and
                 registers.

PDCMD_SETPARAMS  Set the parameters of the parallel port.

Exec Functions as Used in This Chapter
--------------------------------------
AbortIO()        Abort a command to the parallel device. If the command is
                 in progress, it is stopped immediately.  If it is queued,
                 it is removed from the queue.

BeginIO()        Initiate a command and return immediately (asynchronous
                 request).  This is used to minimize the amount of system
                 overhead.

CheckIO()        Determine the current state of an I/O request.

CloseDevice()    Relinquish use of the parallel device.  All requests must
                 be complete.

DoIO()           Initiate a command and wait for completion (synchronous
                 request).

OpenDevice()     Obtain use of the parallel device.

SendIO()         Initiate a command and return immediately (asynchronous
                 request).

WaitIO()         Wait for the completion of an asynchronous request.  When
                 the request is complete the message will be removed from
                 your reply port.

Exec Support Functions as Used in This Chapter
----------------------------------------------
CreateExtIO()    Create an extended I/O request structure of type
                 IOExtPar.  This structure will be used to communicate
                 commands to the parallel device.

CreatePort()     Create a signal message port for reply messages from the
                 parallel device.  Exec will signal a task when a message
                 arrives at the port.

DeleteExtIO()    Delete an extended I/O request structure created by
                 CreateExtIO().

DeletePort()     Delete the message port created by CreatePort().


9 Parallel Device / Device Interface

The parallel device operates like the other Amiga devices.  To use it, you
must first open the parallel device, then send I/O requests to it, and
then close it when finished.  See "Introduction to Amiga System Devices"
chapter for general information on device usage.

The I/O request used by the parallel device is called IOExtPar.

    struct   IOExtPar
        {
        struct  IOStdReq IOPar;
        ULONG   io_PExtFlags;   /* additional parallel flags */
        UBYTE   io_Status;      /* status of parallel port and registers */
        UBYTE   io_ParFlags;    /* parallel device flags */
        struct  IOPArray io_PTermArray; /* termination character array */
        };

See the include file devices/parallel.h for the complete structure
definition.

 Opening The Parallel Device 		 Writing To The Parallel Device
 Reading From The Parallel Device 	 Closing The Parallel Device


9 Device Interface / Opening The Parallel Device

Three primary steps are required to open the parallel device:

   *  Create a message port using CreatePort(). Reply messages from the
      device must be directed to a message port.

   *  Create an extended I/O request structure of type IOExtPar using
      CreateExtIO(). CreateExtIO() will initialize the I/O request to point
      to your reply port.

   *  Open the parallel device.  Call OpenDevice(),passing the I/O request.

   struct MsgPort  *ParallelMP;         /* Pointer to reply port */
   struct IOExtPar *ParallelIO;         /* Pointer to I/O request */

   if (ParallelMP=CreatePort(0,0) )
      if (ParallelIO=(struct IOExtPar *)
              CreateExtIO(ParallelMP,sizeof(struct IOExtPar)) )
         if (OpenDevice(PARALLELNAME,0L,(struct IORequest *)ParallelIO,0) )
               printf("%s did not open\n",PARALLELNAME);

During the open, the parallel device pays attention to just one flag;
PARF_SHARED.  For consistency, the other flag bits should also be properly
set.  Full descriptions of all flags will be given later.  When the
parallel device is opened, it fills the latest default parameter settings
into the IOExtPar block.


9 / Device Interface / Reading From The Parallel Device

You read from the parallel device by passing an IOExtPar to the device
with CMD_READ set in io_Command, the number of bytes to be read set in
io_Length and the address of the read buffer set in io_Data.

   #define READ_BUFFER_SIZE 256
   /* Reserve SIZE bytes of storage */
   char ParallelReadBuffer[READ_BUFFER_SIZE];

   ParallelIO->IOPar.io_Length   = READ_BUFFER_SIZE;
   ParallelIO->IOPar.io_Data     = (APTR)&ParallelReadBuffer[0];
   ParallelIO->IOPar.io_Command  = CMD_READ;
   DoIO((struct IORequest *)ParallelIO);

If you use this example, your task will be put to sleep waiting until the
parallel device reads 256 bytes (or terminates early).  Early termination
can be caused by error conditions.


9 / Device Interface / Writing To The Parallel Device

You write to the parallel device by passing an IOExtPar to the device with
CMD_WRITE set in io_Command, the number of bytes to be written set in
io_Length and the address of the write buffer set in io_Data.

To write a NULL-terminated string, set the length to -1; the device will
output from your buffer until it encounters and transmits a value of zero
(0x00).

   ParallelIO->IOPar.io_Length   = -1;
   ParallelIO->IOPar.io_Data     = (APTR)"Parallel lines cross 7 times...";
   ParallelIO->IOPar.io_Command  = CMD_WRITE;
   DoIO((struct IORequest *)ParallelIO);             /* execute write */

The length of the request is -1, meaning we are writing a NULL-terminated
string. The number of characters sent can be found in io_Actual.


9 / Device Interface / Closing The Parallel Device

Each OpenDevice() must eventually be matched by a call to CloseDevice().
When the last close is performed, the device will deallocate all resources
and buffers.  The latest parameter settings will be saved for the next
open.

All I/O requests must be complete before CloseDevice().  If any requests
are still pending, abort them with AbortIO():

   if (!(CheckIO(ParallelIO)))
       {
       AbortIO(ParallelIO);  /* Ask device to abort request, if pending */
       }
   WaitIO(ParallelIO);       /* Wait for abort, then clean up */
   CloseDevice((struct IORequest *)ParallelIO);


9 Parallel Device / Ending A Read or Write with Termination Characters

Reads and writes from the parallel device may terminate early if an error
occurs or if an end-of-file is sensed.  For example, if a break is
detected on the line, any current read request will be returned with the
error ParErr_DetectedBreak. The count of characters read to that point
will be in the io_Actual field of the request.

You can specify a set of possible end-of-file characters that the parallel
device is to look for in the input or output stream using the
PDCMD_SETPARAMS command. These are contained in an io_PTermArray that you
provide. io_PTermArray is used only when the PARF_EOFMODE flag is selected
(see Parallel Flags below).

If EOF mode is selected, each input data character read into or written
from the user's data block is compared against those in io_PTermArray. If
a match is found, the IOExtPar is terminated as complete, and the count of
characters transferred (including the termination character) is stored in
io_Actual.

To keep this search overhead as efficient as possible, the parallel device
requires that the array of characters be in descending order. The array
has eight bytes and all must be valid (that is, do not pad with zeros
unless zero is a valid EOF character). Fill to the end of the array with
the lowest value termination character. When making an arbitrary choice of
EOF character(s), you will get the quickest response from the lowest
value(s) available.

     Terminate_Parallel.c

The read will terminate before the io_Length number of characters is read
if a "Q", "E", or "A" is detected.

   It's Usually For Output.
   ------------------------
   Most applications for the parallel device use the device for output,
   hence the termination feature is usually done on the output stream.


9 Parallel Device / Setting Parallel Parameters

You can control the parallel parameters shown in the following table. The
parameter name within the parallel IOExtPar data structure is shown below.
All of the fields described in this section are filled with defaults when
you call OpenDevice().  Thus, you need not worry about any parameter that
you do not need to change.  The parameters are defined in the include file
devices/parallel.h.

                   PARALLEL PARAMETERS (IOExtPar)
   IOExtPar
   Field Name      Parallel Device Parameter It Controls
   ----------      -------------------------------------
   io_PExtFlags    Reserved for future use.

   io_PTermArray   A byte-array of eight termination characters, must
                   be in descending order.  If EOFMODE is set in the
                   parallel flags, this array specifies eight possible
                   choices of characters to use as an end-of-file mark.
                   See the section above titled  "Ending A Read Or Write
                   with Termination Characters" and the PDCMD_SETPARAMS
                   summary page in the Autodocs.

   io_Status       Contains status information.  It is filled in by the
                   PDCMD_QUERY command.

   io_ParFlags     See "Parallel Flags" below.

You set the parallel parameters by passing an IOExtPar to the device with
PDCMD_SETPARAMS set in io_Command and with the flags and parameters set to
the values you want.

   ParallelIO->io_ParFlags     &= ~PARF_EOFMODE;   /* Set EOF mode */
   ParallelIO->IOPar.io_Command = PDCMD_SETPARAMS; /* Set params command */
   if (DoIO(ParallelIO);
       printf("Error setting parameters!\n");

The above code fragment modifies one bit in io_ParFlags, then sends the
command.

   Proper Time for Parameter Changes.
   ----------------------------------
   A parameter change should not be performed while an I/O request is
   actually being processed, because it might invalidate already active
   request handling.  Therefore you should use PDCMD_SETPARAMS only when
   you have no parallel I/O requests pending.

 Parallel Flags (Bit Definitions For Io_parflags)


9 / Setting Parallel Parameters / Parallel Flags (Bits for io_ParFlags)

The flags shown in the following table can be set to affect the operation
of the parallel device.  Note that the default state of all of these flags
is zero.  The flags are defined in the include file devices/parallel.h.

                        PARALLEL FLAGS (io_ParFlags)

    Flag Name           Effect on Device Operation
    ---------           --------------------------
   PARF_EOFMODE         Set this bit if you want the parallel
                        device to check I/O characters against io_TermArray
                        and terminate the I/O request immediately if an
                        end-of-file character has been encountered.
                        Note:  This bit can be set and reset directly in
                        the user's IOExtPar block without a call to
                        PDCMD_SETPARAMS.

   PARF_ACKMODE         Set this bit if you want to use ACK handshaking.

   PARF_FASTMODE        Set this bit if you want to use
                        high-speed mode for transfers to high-speed
                        printers.  This mode will send out data as long as
                        the BUSY signal is low. The printer must be
                        able to raise the BUSY signal within three
                        microseconds or data will be lost. Should only be
                        used when the device has been opened for exclusive
                        -access.

   PARF_SLOWMODE        Set this bit if you want to use slow
                        -speed mode for transfers to very slow printers.
                        Should not be used with high-speed printers.

   PARF_SHARED          Set this bit if you want to allow other
                        tasks to simultaneously access the parallel port.
                        The default is exclusive access. If someone already
                        has the port, whether for exclusive or shared
                        access, and you ask for exclusive access, your
                        OpenDevice() call will fail (must be modified
                        before OpenDevice()).


9 Parallel Device / Querying the Parallel Device

You query the parallel device by passing an IOExtPar to the device with
PDCMD_QUERY set in io_Command.  The parallel device will respond with the
status of the parallel port lines and registers.

   UWORD Parallel_Status;

   ParallelIO->IOPar.io_Command  = PDCMD_QUERY; /* indicate query */
   DoIO((struct IORequest *)ParallelIO);

   Parallel_Status = ParallelIO->io_Status;     /* store returned status */

The 8 status bits of the parallel device are returned in io_Status.

                       PARALLEL DEVICE STATUS BITS

   Bit    Active              Function
   ---    ------              --------
    0       high        Printer busy toggle (offline)
    1       high        Paper out
    2       high        Printer Select on the A1000. On theA500 and A2000,
                        select is also connected to to the parallel port's
                        Ring Indicator. Be cautious when making cables.
    3        -          read=0; write=1
    4-7      -          (reserved)

The parallel device also returns error codes whenever an operation is
attempted.

   struct IOPArray Terminators =
   {
   0x51454141,   /* Q E A A */
   0x41414141    /* fill to end with lowest value,must be in desc. order */
   };

   ParallellIO->io_ParFlags != PARF_EOFMODE;        /* Set EOF mode flag */
   ParallelIO->io_PTermArray = Terminators;/* Set termination characters */
   ParallellIO->IOPar.io_Command  = PDCMD_SETPARAMS;   /* Set parameters */
   if (DoIO((struct IORequest *)ParallelIO))
       printf("Set Params failed. Error: %ld ",ParallelIO->IOPar.io_Error);

The error is returned in the io_Error field of the IOExtPar structure.

                       PARALLEL DEVICE ERROR CODES

               Error              Value        Explanation
               -----              -----        -----------
              ParErr_DevBusy        1          Device in use
              ParErr_BufToBig       2          Out of memory
              ParErr_InvParam       3          Invalid parameter
              ParErr_LineErr        4          Parallel line error
              ParErr_NotOpen        5          Device not open
              ParErr_PortReset      6          Port Reset
              ParErr_InitErr        7          Initialization Error

     Parallel.c


9 Parallel Device / Additional Information on the Parallel Device

Additional programming information on the parallel device can be found in
the include files and the Autodocs for the parallel device.  Both are
contained in the Amiga ROM Kernel Reference Manual: Includes and Autodocs.

                     Parallel Device Information height
                     ----------------------------------
                     INCLUDES        devices/parallel.h
                                     devices/parallel.i

                     AUTODOCS        parallel.doc


Amiga® RKM Devices: 2 Audio Device

The Amiga has four hardware audio channels - two of the channels produce
audio output from the left audio connector, and two from the right.  These
channels can be used in many ways. You can combine a right and a left
channel for stereo sound, use a single channel, or play a different sound
through each of the channels to create four-part harmony.

 About Amiga Audio
 Audio Device Commands and Functions
 Device Interface
 A Simple Audio Example
 Audio Allocation and Arbitration
 Allocation and Arbitration Commands
 Hardware Control Commands
 Double Buffered Sound Example
 Additional Information on the Audio Device


2 Audio Device / About Amiga Audio

Most personal computers that produce sound have hardware designed for one
specific synthesis technique. The Amiga computer uses a very general
method of digital sound synthesis that is quite similar to the method used
in digital hi-fi components and state-of-the-art keyboard and drum
synthesizers.

For programs that can afford the memory, playing sampled sounds gives you
a simple and very CPU-efficient method of sound synthesis.  A sampled
sound is a table of numbers which represents a sound digitally. When the
sound is played back by the Amiga, the table is fed by a DMA channel into
one of the four digital-to-analog converters in the custom chips. The
digital-to-analog converter converts the samples into voltages that can be
played through amplifiers and loudspeakers, reproducing the sound.

On the Amiga you can create sound data in many other ways. For instance,
you can use trigonometric functions in your programs to create the more
traditional sounds - sine waves, square waves, or triangle waves - by
using tables that describe their shapes. Then you can combine these waves
for richer sound effects by adding the tables together. Once the data are
entered, you can modify them with techniques described below. For
information about the limitations of the audio hardware and suggestions
for improving system efficiency and sound quality, refer to the Amiga
Hardware Reference Manual.

Some commands enable your program to co-reside with other programs using
the audio device at the same time. Programs can co-reside because the
audio device handles allocation of audio channels and arbitrates among
programs competing for the same resources.  When properly used, this
allows many programs to use the audio device simultaneously.

The audio device commands help isolate the programmer from the
idiosyncrasies of the custom chip hardware and make it easier to use. But
you can also produce sound on the Amiga by directly accessing the hardware
registers if you temporarily lock out other users first.  For certain
types of sound synthesis, this is more CPU-efficient.

 Definitions


2 / About Amiga Audio / Definitions

Terms used in the following discussions may be unfamiliar. Some of the
more important ones are defined below.

Amplitude
   The height of a waveform, which corresponds to the amount of voltage or
   current in the electronic circuit.

Amplitude modulation
   A means of producing special audio effects by using one channel to alter
   the amplitude of another.

Channel
   One "unit" of the audio device.

Cycle
   One repetition of a waveform.

Frequency
   The number of times per second a cycle repeats.

Frequency modulation
   A means of producing special audio effects by using one channel to
   affect the period of the waveform produced by another channel.

Period
   The time elapsed between the output of successive sound samples,
    in units of system clock ticks.

Precedence
   Priority of the user of a sound channel.

Sample
   Unit of audio data, one of the fixed-interval points on the waveform.

Waveform
   Graph that shows a model of how the amplitude of a sound varies over
   time-usually over one cycle.


2 Audio Device / Audio Device Commands and Functions

Command          Operation
-------          ---------
 ADCMD_ALLOCATE    Allocate one or more of the four audio channels.

 ADCMD_FINISH      Abort the current write request on one or more of the
                   channels.  Can be done immediately or at the end of the
                   current cycle.

 ADCMD_FREE        Free one or more audio channels.

 ADCMD_LOCK        Lock one or more audio channels.

 ADCMD_PERVOL      Change the period and volume for writes in progress. Can
                   be done immediately or at the end of the cycle.

 ADCMD_SETPREC     Set the allocation precedence of one or more channels.

 ADCMD_WAITCYCLE   Wait for the current write cycle to complete on a single
                   channel.  Returns at the end of the cycle or immediately
                   if no cycle is active on the channel.

 CMD_FLUSH         Purge all write cycles and waitcycles (in-progress and
                   queued) for one or more channels.

 CMD_READ          Return a pointer to the I/O block currently writing on a
                   single channel.

 CMD_RESET         Reset one or more channels their initialized state.  All
                   active and queued requests will be aborted.

 CMD_START         Resume writes to one or more channels that were stopped.

 CMD_STOP          Stop any write cycle in progress on one or more
                                   channels.

 CMD_WRITE         Start a write cycle on a single channel.

Exec Functions as Used in This Chapter
--------------------------------------
AbortIO()        Abort a command to the audio device. If in progress, it
                 is stopped immediately, otherwise it is removed from the
                 queue.

BeginIO()        Initiate a command and return immediately (asynchronous
                 request).

CheckIO()        Determine the current state of an I/O request.

CloseDevice()    Relinquish use of the audio device.

OpenDevice()     Obtain use of the audio device.

Wait()           Wait for a signal from the audio device.

WaitPort()       Wait for the audio message port to receive a message.

Exec Support Functions as Used in This Chapter
----------------------------------------------
AllocMem()       Allocate a block of memory.

CreatePort()     Create a signal message port for reply messages from the
                 audio device.  Exec will signal a task when a message
                 arrives at the reply port.

DeletePort()     Delete the message port created by CreatePort().

FreeMem()        Free a block of previously allocated memory.


2 Audio Device / Device Interface

The audio device operates like the other Amiga I/O devices.  To make
sound, you first open the audio device, then send I/O requests to it, and
then close it when finished.  See "Introduction to Amiga System Devices"
chapter for general information on device usage.

Audio device commands use an extended I/O request block named IOAudio to
send commands to the audio device.  This is the standard IORequest block
with some extra fields added at the end.

struct IOAudio
{
    struct IORequest ioa_Request;/* I/O request block. See exec/io.h.    */
    WORD   ioa_AllocKey;       /* Alloc. key filled in by audio device   */
    UBYTE  *ioa_Data;          /* Pointer to a sample or allocation mask */
    ULONG  ioa_Length;         /* Length of sample or allocation mask.   */
    UWORD  ioa_Period;         /* Sample playback speed                  */
    UWORD  ioa_Volume;         /* Volume of sound                        */
    UWORD  ioa_Cycles;         /* # of times to play sample. 0=forever.  */
    struct Message ioa_WriteMsg;/* Filled in by device- usually not used */
};

See the include file devices/audio.h for the complete structure definition.

 Opening The Audio Device 	 Audio And System I/O Functions
 Audio Device Command Types      Closing The Audio Device
 Scope Of Audio Commands


2 / Device Interface / Opening The Audio Device

Before you can use the audio device, you must first open it with a call to
OpenDevice(). Four primary steps are required to open the audio device:

   *  Create a message port using CreatePort Reply messages from the
      device must be directed to a message port.

   *  Allocate memory for an extended I/O request structure of type
      IOAudio using AllocMem().

   *  Fill in io_Message.mn_ReplyPort with the message port created by
      CreatePort.

   *  Open the audio device.  Call OpenDevice(), passing IOAudio.

  struct MsgPort  *AudioMP;      /* Define storage for port pointer */
  struct IOAudio  *AudioIO;      /* Define storage for IORequest pointer */

  if (AudioMP = CreatePort(0,0) )
      {
      AudioIO = (struct IOAudio *)
                AllocMem(sizeof(struct IOAudio), MEMF_PUBLIC | MEMF_CLEAR);
      if (AudioIO)
          {
          AudioIO->ioa_Request.io_Message.mn_ReplyPort  = AudioMP;
          AudioIO->ioa_AllocKey                         = 0;
          }

      if (OpenDevice(AUDIONAME,0L,(struct IORequest *)AudioIO,0L) )
          printf("%s did not open\n",AUDIONAME);

A special feature of the OpenDevice() function with the audio device
allows you to automatically allocate channels for your program to use when
the device is opened.  This is convenient since you must allocate one or
more channels before you can produce sound.

This is done by setting ioa_AllocKey to zero, setting
ioa_Request.io_Message.mn_Node.ln_Pri to the appropriate precedence,
setting io_Data to the address of a channel combination array, and setting
ioa_Request.ioa_Length to a non-zero value (the length of the channel
combination array).  The audio device will attempt to allocate channels
just as if you had sent the ADCMD_ALLOCATE command (see below).  If the
allocation fails, the OpenDevice() call will return immediately.

If you want to allocate channels at some later time, set the
ioa_Request.ioa_Length field of the IOAudio block to zero when you call
OpenDevice().  For more on channel allocation and the  ADCMD_ALLOCATE
command, see the section on Allocation and Arbitration below.

    UBYTE chans[] = {1,2,4,8};  /* get any of the four channels */

    if (AudioIO)
        {
        AudioIO->ioa_Request.io_Message.mn_ReplyPort  = AudioMP;
        AudioIO->ioa_AllocKey                         = 0;
        AudioIO->ioa_Request.io_Message.mn_Node.ln_Pri= 120;
        AudioIO->ioa_Data                             = chans;
        AudioIO->ioa_Length                           = sizeof(chans);
        }

    if (OpenDevice(AUDIONAME,0L,(struct IORequest *)AudioIO,0L) )
        printf("%s did not open\n",AUDIONAME);


2 / Device Interface / Audio Device Command Types

Commands for audio use can be divided into two categories:
allocation/arbitration commands and hardware control commands.

There are four allocation/arbitration commands.  These do not actually
produce any sound.  Instead they manage and arbitrate the audio resources
for the many tasks that may be using audio in the Amiga's multitasking
environment.

    ADCMD_ALLOCATE   - Reserves an audio channel for your program to use.
    ADCMD_FREE       - Frees an audio channel.
    ADCMD_SETPREC    - Changes the precedence of a sound in progress.
    ADCMD_LOCK       - Tells if a channel has been stolen from you.

The hardware control commands are used to set up, start, and stop sounds
on the audio device:

    CMD_WRITE        - The main command.  Starts a sound playing.
    ADCMD_FINISH     - Aborts a sound in progress.
    ADCMD_PERVOL     - Changes the period (speed) and volume of a sound
                        in progress.
    CMD_FLUSH        - Clears the audio channels.
    CMD_RESET        - Resets and initializes the audio device.
    ADCMD_WAITCYCLE  - Signals you when a cycle finishes.
    CMD_STOP         - Temporarily stops a channel from playing.
    CMD_START        - Restarts an audio channel that was stopped.
    CMD_READ         - Returns a pointer to the current IOAudio request.


2 / Device Interface / Scope Of Audio Commands

Most audio commands can operate on multiple channels.  The exceptions are
ADCMD_WAITCYCLE, CMD_WRITE and CMD_READ, which can only operate on one
channel at a time.  You specify the channel(s) that you want to use by
setting the appropriate bits in the ioa_Request.io_Unit field of the
IOAudio block.  If you send a command for a channel that you do not own,
your command will be ignored.  For more details, see the section on
"Allocation and Arbitration" below.


2 / Device Interface / Audio And System I/O Functions

 BeginIO()
 Wait() and WaitPort()
 AbortIO()


2 / Audio And System I/O Functions / BeginIO()

All the commands that you can give to the audio device should be sent by
calling the BeginIO() function.  This differs from other Amiga devices
which generally use SendIO() or DoIO().  You should not use SendIO() or
DoIO() with the audio device because these functions clear some special
flags used by the audio device; this might cause audio to work incorrectly
under certain circumstances.  To be safe, you should always use BeginIO()
with the audio device.


2 / Audio And System I/O Functions / Wait() and WaitPort()

These functions can be used to put your task to sleep while a sound plays.
Wait() takes a wake-up mask as its argument. The wake-up mask is usually
the mp_SigBit of a MsgPort that you have set up to get replies back from
the audio device.

WaitPort() will put your task to sleep while a sound plays.  The argument
to WaitPort() is a pointer to a MsgPort that you have set up to get
replies back from the audio device.

Wait() and WaitPort() will not remove the message from the reply port.
You must use GetMsg() to remove it.

You must always use Wait() or WaitPort() to wait for I/O to finish with
the audio device.


2 / Audio And System I/O Functions / AbortIO()

This function can be used to cancel requests for ADCMD_ALLOCATE,
ADCMD_LOCK, CMD_WRITE, or ADCMD_WAITCYCLE. When used with the audio
device, AbortIO() always succeeds.


2 / Device Interface / Closing The Audio Device

An OpenDevice() must eventually be matched by a call to CloseDevice().

All I/O requests must be complete before CloseDevice().  If any requests
are still pending, abort them with AbortIO() :

  AbortIO((struct IORequest *)AudioIO);  /* Abort any pending requests */
  WaitPort(AudioMP);                     /* Wait for abort message */
  GetMsg(AudioMP);                       /* Get abort message */
  CloseDevice((struct IORequest *)AudioIO);

CloseDevice() performs an ADCMD_FREE command on any channels selected by
the ioa_Request.io_Unit field of the IOAudio request.  This means that if
you close the device with the same IOAudio block that you used to allocate
your channels (or a copy of it), the channels will be automatically freed.

If you allocated channels with multiple allocation commands, you cannot
use this function to close all of them at once. Instead, you will have to
issue one ADCMD_FREE command for each allocation that you made. After
issuing the ADCMD_FREE commands for each of the allocations, you can call
CloseDevice().


2 Audio Device / A Simple Audio Example

The Amiga's audio software has a complex allocation and arbitration system
which is described in detail in the sections below.  At this point,
though, it may be helpful to look at a simple audio example:

     Audio.c


2 Audio Device / Audio Allocation and Arbitration

The first command you send to the audio device should always be
ADCMD_ALLOCATE.  You can do this when you open the device, or at a later
time.  You specify the channels you want in the ioa_Data field of the
IOAudio block. If the allocation succeeds, the audio device will return
the channels that you now own in the lower four bits of the
ioa_Request.io_Unit field of your IOAudio block. For instance, if the
io_Unit field equals 5 (binary 0101) then you own channels 2 and 0.  If
the io_Unit field equals 15 (binary 1111) then you own all the channels.

When you send the ADCMD_ALLOCATE command, the audio device will also
return a unique allocation key in the ioa_AllocKey of the IOAudio block.
You must use this allocation key for all subsequent commands that you send
to the audio device.  The audio device uses this unique key to identify
which task issued the command.  If you do not use the correct allocation
key assigned to you by the audio device when you send a command, your
command will be ignored.

When you request a channel with ADCMD_ALLOCATE, you specify a precedence
number from -128 to 127 in the ioa_Request.io_Message.mn_Node.ln_Pri field
of the IOAudio block. If a channel you want is being used and you have
specified a higher precedence than the current user, ADCMD_ALLOCATE will
"steal" the channel from the other user. Later on, if your precedence is
lower than that of another user who is performing an allocation, the
channel may be stolen from you.

If you set the precedence to 127 when you open the device or raise the
precedence to 127 with the ADCMD_SETPREC command, no other tasks can steal
a channel from you. When you have finished with a channel, you must
relinquish it with the ADCMD_FREE command to make it available for other
users.

The following table shows suggested precedence values.

                SUGGESTED PRECEDENCES FOR CHANNEL ALLOCATION

   Predecence                   Type of Sound
   ----------                   -------------
     127          Unstoppable. Sounds first allocated at lower precedence,
                  then set to this to the highest level.

     90 - 100     Emergencies.  Alert, urgent situation
                  that requires immediate action.

     80 - 90      Annunciators.  Attention, bell (CTRL-G).

     75           Speech. Synthesized or recorded speech (narrator.device).

     50 - 70      Sonic cues.  Sounds thatprovide information that is not
                  provided by graphics. Only the beginning of each sound
                  (enough to recognize it) should be at this level;the rest
                  should be set to sound effects level.

    -50 - 50      Music program.  Musical notes in music-oriented program.
                  The higher levels should be used for the attack portions
                  of each note.

    -70 - -50     Sound effects.  Sounds used in conjunction with graphics.
                  More important sounds should use higher levels.

    -100 - -80    Background. Theme music and restartable background
                  sounds.

    -128          Silence. Lowest level (freeing the channel completely
                  is preferred).

If you attempt to perform a command on a channel that has been stolen from
you by a higher priority task, an AUDIO_NOALLOCATION error is returned and
the bit in the ioa_Request.io_Unit field corresponding to the stolen
channel is cleared so you know which channel was stolen.

If you want to be warned before a channel is stolen so that you have a
chance to stop your sound gracefully, then you should use the ADCMD_LOCK
command after you open the device.  This command is also useful for
programs which write directly to the audio hardware.  For more on
ADCMD_LOCK, see the section below.


2 Audio Device / Allocation and Arbitration Commands

These commands allow the audio channels to be shared among different tasks
and programs. None of these commands can be called from interrupt code.

 ADCMD_ALLOCATE       ADCMD_FREE       ADCMD_SETPREC       ADCMD_LOCK


2 / Allocation and Arbitration Commands / ADCMD_ALLOCATE

This command gives your program a channel to use and should be the first
command you send to the audio device.  You specify the channels you want
by setting a pointer to an array in the ioa_Data field of the IOAudio
structure.  This array uses a value of 1 to allocate channel 0, 2 for
channel 1, 4 for channel 2, and 8 for channel 3. For multiple channels,
add the values together.  For example, if you want to allocate all
channels, use a value of 15.

If you want a pair of stereo channels and you have no preference about
which of the left and right channels the system will choose for the
allocation, you can pass a pointer to an array containing 3, 5, 10, and
12. Channels 1 and 2 produce sound on the left side and channels 0 and 3
on the right side. The table below shows how this array corresponds to all
the possible combinations of a right and a left channel.

                     POSSIBLE CHANNEL COMBINATIONS
                                                           Decimal
     Channel 3    Channel 2    Channel 1    Channel 0      Value of
      (right)       (left)      (left)       (right)    Allocation Mask
     ---------    ---------    ---------    ---------   ---------------
         0            0            1            1              3
         0            1            0            1              5
         1            0            1            0              10
         1            1            0            0              12

 How ADCMD_ALLOCATE Operates                ADCMD_ALLOCATE Examples
 The ADIOF_NOWAIT Flag                      The Allocation Key


2 / ADCMD_ALLOCATE / How ADCMD_ALLOCATE Operates

The ADCMD_ALLOCATE command tries the first  combination , 3, to see if
channels 0 and 1 are not being used. If they are available, the 3 is
copied into the io_Unit field and you get an allocation key for these
channels in the ioa_AllocKey field. You copy the key into other I/O blocks
for any other commands you may want to perform on these channels.

If channels 0 and 1 are being used, ADCMD_ALLOCATE tries the other
combinations in turn.  If all the combinations are in use, ADCMD_ALLOCATE
checks the precedence number of the users of the channels and finds the
combination that requires it to steal the channel or channels of the
lowest precedence. If all the combinations require stealing a channel or
channels of equal or higher precedence, the ADCMD_ALLOCATE request fails.
Precedence is in the ln_Pri field of the io_Message in the IOAudio block
you pass to ADCMD_ALLOCATE; it has a value from -128 to 127.


2 / ADCMD_ALLOCATE / The ADIOF_NOWAIT Flag

If you need to produce a sound right now and otherwise don't want to
allocate, set the ADIOF_NOWAIT flag to 1. This will cause the command to
return an IOERR_ALLOCFAILED error if it cannot allocate any of the
channels. If you are producing a non-urgent sound and you can wait, set
the ADIOF_NOWAIT flag to 0. Then, the IOAudio block returns only when you
get the allocation. If ADIOF_NOWAIT is set to 0, the audio device will
continue to retry the allocation request whenever channels are freed until
it is successful. If the program decides to cancel the request,
AbortIO() can be used.


2 / ADCMD_ALLOCATE / ADCMD_ALLOCATE Examples

The following are more examples of how to tell ADCMD_ALLOCATE your channel
preferences. If you want any channel, but want a right channel first, use
an array containing 1, 8, 2, and 4:

  0001
  1000
  0010
  0100

If you only want a right channel, use 1 and 8 (channels 0 and 3):

  0001
  1000

If you want only a left channel, use 2 and 4  (channels 1 and 2):

  0010
  0100

If you want to allocate a channel and keep it for a sound that can be
interrupted and restarted, allocate it at a certain precedence. If it is
stolen, allocate it again with the ADIOF_NOWAIT flag set to 0. When the
channel is relinquished, you will get it again.


2 / ADCMD_ALLOCATE / The Allocation Key

If you want to perform multi-channel commands, all the channels must have
the same key since the IOAudio block has only one allocation key field.
The channels must all have that same key even when they were not allocated
simultaneously. If you want to use a key you already have, you can pass
that key in the ioa_AllocKey field and ADCMD_ALLOCATE can allocate other
channels with that existing key. The ADCMD_ALLOCATE command returns a new
and unique key only if you pass it a zero in the allocation key field.


2 / Allocation and Arbitration Commands / ADCMD_FREE

ADCMD_FREE is the opposite of ADCMD_ALLOCATE. When you perform ADCMD_FREE
on a channel, it does a CMD_RESET command on the hardware and "unlocks"
the channel. It also checks to see if there are other pending allocation
requests. You do not need to perform ADCMD_FREE on channels stolen from
you. If you want channels back after they have been stolen, you must
reallocate them with the same allocation key.


2 / Allocation and Arbitration Commands / ADCMD_SETPREC

This command changes the precedence of an allocated channel. As an example
of the use of ADCMD_SETPREC, assume that you are making the sound of a
chime that takes a long time to decay. It is important that user hears the
chime but not so important that he hears it decay all the way. You could
lower precedence after the initial attack portion of the sound to let
another program steal the channel. You can also set the precedence to
maximum (127) if you do not want the channel(s) stolen from you.


2 / Allocation and Arbitration Commands / ADCMD_LOCK

The ADCMD_LOCK command performs the "steal verify" function. When
another application is attempting to steal a channel or channels,
ADCMD_LOCK gives you a chance to clean up before the channel is stolen.
You perform a ADCMD_LOCK command right after the ADCMD_ALLOCATE command.
ADCMD_LOCK does not return until a higher-priority user attempts to steal
the channel(s) or you perform an ADCMD_FREE command. If someone is
attempting to steal, you must finish up and ADCMD_FREE the channel as
quickly as possible.

You must use ADCMD_LOCK if you want to write directly to the hardware
registers instead of using the device commands. If your channel is stolen,
you are not notified unless the ADCMD_LOCK command is present. This could
cause problems for the task that has stolen the channel and is now using
it at the same time as your task. ADCMD_LOCK sets a switch that is not
cleared until you perform an ADCMD_FREE command on the channel. Canceling
an ADCMD_LOCK request with AbortIO() will not free the channel.

The following outline describes how ADCMD_LOCK works when a channel is
stolen and when it is not stolen.

   1. User A allocates a channel.
   2. User A locks the channel.

If User B allocates the channel with a higher precedence:

   3. User B's ADCMD_ALLOCATE command is suspended (regardless of the
      setting of the ADIOF_NOWAIT flag).
   4. User A's lock command is replied to with an error
      (ADIOERR_CHANNELSTOLEN).
   5. User A does whatever is needed to finish up when a channel is stolen.
   6. User A frees the channel with ADCMD_FREE.
   7. User B's ADCMD_ALLOCATE command is replied to. Now user B has the
      channel.

Otherwise, if the channel is not allocated by another user:

   3. User A finishes the sound.
   4. User A performs the ADCMD_FREE command.
   5. User A's ADCMD_LOCK command is replied to.

Never make the freeing of a channel (if the channel is stolen) dependent
on allocating another channel. This may cause a deadlock. If you want
channels back after they have been stolen, you must reallocate them with
the same allocation key. To keep a channel and never let it be stolen, set
precedence to maximum (127). Do not use a lock for this purpose.


2 Audio Device / Hardware Control Commands

The following commands change hardware registers and affect the actual
sound output.

 CMD_WRITE 	            CMD_FLUSH                     CMD_STOP
 ADCMD_FINISH 	            CMD_RESET                     CMD_START
 ADCMD_PERVOL               ADCMD_WAITCYCLE               CMD_READ


2 / Hardware Control Commands / CMD_WRITE

This is a single-channel command and is the main command for making
sounds. You pass the following to CMD_WRITE:

   *  A pointer to the waveform to be played (must start on a word boundary
      and must be in memory accessible by the custom chips, MEMF_CHIP)

   *  The length of the waveform in bytes (must be an even number)

   *  A count of how many times you want to play the waveform

If the count is 0, CMD_WRITE will play the waveform from beginning to end,
then repeat the waveform continuously until something aborts it.

If you want period and volume to be set at the start of the sound, set the
WRITE command's ADIOF_PERVOL flag. If you do not do this, the previous
volume and period for that channel will be used. This is one of the flags
that is cleared by DoIO() and SendIO(). The ioa_WriteMsg field in the
IOAudio block is an extra message field that can be replied to at the
start of the CMD_WRITE. This second message is used only to tell you when
the CMD_WRITE command starts processing, and it is used only when the
ADIOF_WRITEMESSAGE flag is set to 1.

If a CMD_STOP has been performed, the CMD_WRITE requests are queued up.
The CMD_WRITE command does not make its own copy of the waveform, so any
modification of the waveform before the CMD_WRITE command is finished may
affect the sound. This is sometimes desirable for special effects. To
splice together two waveforms without clicks or pops, you must send a
separate, second CMD_WRITE command while the first is still in progress.
This technique is used in double-buffering, which is described below.

By using two waveform buffers and two CMD_WRITE requests you can compute a
waveform continuously. This is called double-buffering. The following
describes how you use double-buffering.

   1. Compute a waveform in memory buffer A.

   2. Issue CMD_WRITE A with io_Data pointing to buffer A.

   3. Continue the waveform in memory buffer B.

   4. Issue CMD_WRITE B with io_Data pointing to Buffer B.

   5. Wait for CMD_WRITE A to finish.

   6. Continue the waveform in memory buffer A.

   7. Issue CMD_WRITE A with io_Data pointing to Buffer A.

   8. Wait for CMD_WRITE B to finish.

   9. Loop back to step 3 until the waveform is finished.

  10. At the end, remember to wait until both CMD_WRITE A and B are
      finished.


2 / Hardware Control Commands / ADCMD_FINISH

The ADCMD_FINISH command aborts (calls AbortIO() ) the current write
request on a channel or channels. This is useful if you have something
playing, such as a long buffer or some repetitions of a buffer, and you
want to stop it.

ADCMD_FINISH has a flag you can set (ADIOF_SYNCCYCLE) that allows the
waveform to finish the current cycle before aborting it. This is useful
for splicing together sounds at zero crossings or some other place in the
waveform where the amplitude at the end of one waveform matches the
amplitude at the beginning of the next. Zero crossings are positions
within the waveform at which the amplitude is zero. Splicing at zero
crossings gives you fewer clicks and pops when the audio channel is turned
off or the volume is changed.


2 / Hardware Control Commands / ADCMD_PERVOL

ADCMD_PERVOL lets you change the volume and period of a CMD_WRITE that is
in progress. The change can take place immediately or you can set the
ADIOF_SYNCCYCLE flag to have the change occur at the end of the cycle.
This is useful to produce vibratos, glissandos, tremolos, and volume
envelopes in music or to change the volume of a sound.


2 / Hardware Control Commands / CMD_FLUSH

CMD_FLUSH aborts (calls AbortIO() ) all CMD_WRITE and all ADCMD_WAITCYCLEs
that are queued up for the channel or channels. It does not abort
ADCMD_LOCKs (only ADCMD_FREE clears locks).


2 / Hardware Control Commands / CMD_RESET

CMD_RESET restores all the audio hardware registers. It clears the attach
bits, restores the audio interrupt vectors if the programmer has changed
them, and performs the CMD_FLUSH command to cancel all requests to the
channels. CMD_RESET also unstops channels that have had a CMD_STOP
performed on them. CMD_RESET does not unlock channels that have been
locked by ADCMD_LOCK.


2 / Hardware Control Commands / ADCMD_WAITCYCLE

This is a single-channel command. ADCMD_WAITCYCLE is replied to when the
current cycle has completed.  If there is no CMD_WRITE in progress, it
returns immediately.


2 / Hardware Control Commands / CMD_STOP

This command stops the current write cycle immediately. If there are no
CMD_WRITEs in progress, it sets a flag so any future CMD_WRITEs are queued
up and do not begin processing (playing).


2 / Hardware Control Commands / CMD_START

CMD_START undoes the CMD_STOP command. Any cycles that were stopped by the
CMD_STOP command are actually lost because of the impossibility of
determining exactly where the DMA ceased. If the CMD_WRITE command was
playing two cycles and the first one was playing when CMD_STOP was issued,
the first one is lost and the second one will be played.

This command is also useful when you are playing the same wave form with
the same period out of multiple channels. If the channels are stopped when
the CMD_WRITE commands are issued, CMD_START exactly synchronizes them,
avoiding cancellation and distortion. When channels are allocated, they
are effectively started by the CMD_START command.


2 / Hardware Control Commands / CMD_READ

CMD_READ is a single-channel command. Its only function is to return a
pointer to the current CMD_WRITE command. It enables you to determine
which request is being processed.


2 Audio Device / Double Buffered Sound Example

The program listed below demonstrates double buffering with the audio
device.  Run the program from the CLI.  It takes one parameter - the name
of an IFF 8SVX sample file to play on the Amiga's audio device. The
maximum size for a sample on the Amiga is 128K. However, by using
double-buffering and queueing up requests to the audio device, you can
play longer samples smoothly and without breaks.

     Audio_8SVX.c


2 Audio Device / Additional Information on the Audio Device

Additional programming information on the audio device can be found in
the include files and the Autodocs for the audio device.  Both are
contained in the Amiga ROM Kernel Reference Manual: Includes and Autodocs.
Information can also be found in the Amiga Hardware Reference Manual.

                   Audio Device Information
                -------------------------------
                INCLUDES        devices/audio.h
                                devices/audio.i

                AUTODOCS        audio.doc


Amiga® RKM Devices: 10 Printer Device

The printer device offers a way of sending configuration-independent
output to a printer attached to the Amiga. It can be thought of as a
filter: it takes standard commands as input and translates them into
commands understood by the printer. The commands sent to the printer are
defined in a specific printer driver program. For each type of printer in
use, a driver (or the driver of a compatible printer) should be present in
the devs:printers directory.

           Printer Driver Source Code In This Chapter
           ------------------------------------------
   EpsonX          A YMCB, 8 pin, multi-density interleaved printer.
   HP_LaserJet     A black and white, multi-density, page-oriented printer.

 Printer Device Commands and Functions
 Printer Device Access
 Device Interface
 Sending Printer Commands to a Printer
 Obtaining Printer Specific Data
 Reading and Changing the Printer Preferences Settings
 Querying the Printer Device
 Error Codes from the Printer Device
 Dumping a Rastport to a Printer
 Creating a Printer Driver
 Example Printer Driver Source Code
 Additional Information on the Printer Device


10 Printer Device / Printer Device Commands and Functions

Command         Operation
-------         ----------
CMD_FLUSH       Remove all queued requests for the printer device.  Does
                not affect active requests.

CMD_RESET       Reset the printer device to its initialized state.  All
                active and queued I/O requests will be aborted.

CMD_START       Restart all paused I/O requests

CMD_STOP        Pause all active and queued I/O requests.

CMD_WRITE       Write out a stream of characters to the printer device.
                The number of characters can be specified or a
                NULL-terminated string can be sent.

PRD_DUMPRPORT   Dump the specified RastPort to a graphics printer.

PRD_PRTCOMMAND  Send a command to the printer.

PRD_QUERY       Return the status of the printer port's lines and
                registers.

PRD_RAWWRITE    Send unprocessed output to the the printer.

Exec Functions as Used in This Chapter
--------------------------------------
AbortIO()       Abort a command to the printer device.

CloseDevice()   Relinquish use of the printer device.  All requests must
                be complete before closing.

DoIO()          Start a command and wait for completion (synchronous
                request).

OpenDevice()    Obtain use of the printer device.

SendIO()        Start a command and return immediately (asynchronous
                request).

WaitIO()        Wait for the completion of an asynchronous request.  When
                the request is complete, the message will be removed from
                the printer message port.

Exec Support Functions as Used in This Chapter
----------------------------------------------
CreatePort()    Create a signal message port for reply messages from the
                audio device.  Exec will signal a task when a message
                arrives at the reply port.

CreateExtIO()   Create an I/O request structure of type printerIO.  This
                structure will be used to send commands to the printer
                device.

DeletePort()    Delete the message port created by CreatePort().

DeleteExtIO()   Delete an I/O request structure created by CreateExtIO().


10 Printer Device / Printer Device Access

The printer device is totally transparent to an application. It uses
information set up by the Workbench Preferences Printer and PrinterGfx
tools to identify the type of printer connection (serial or parallel),
type of dithering, etc.  It also offers the flexibility to send raw
information to the printer for special non-standard or unsupported
features. Raw data transfer is not recommended for conventional text and
graphics since it will result in applications that will only work with
certain printers. By using the standard printer device interface, an
application can perform device independent output to a printer.

   Don't Hog The Device.
   ---------------------
   The printer device is currently an exclusive access device.  Do not
   tie it up needlessly.

There are two ways of doing output to the printer device:

*  PRT:-the AmigaDOS printer device
   PRT: may be opened just like any other AmigaDOS file. You may send
   standard escape sequences to PRT: to specify the options you want as
   shown in the command table below. The escape sequences are
   interpreted by the printer driver, translated into printer-specific
   escape sequences and forwarded to the printer. When using PRT: the
   escape sequences and data must be sent as a character stream. Using
   PRT: is by far the easiest way of doing text output to a printer.

*  printer.device - to directly access the printer device itself
   By opening the printer device directly, you have full control over
   the printer.  You can either send standard escape sequences as shown
   in the command table below or send raw characters directly to the
   printer with no processing at all. Doing this would be similar to
   sending raw characters to SER: or PAR: from AmigaDOS. (Since this
   interferes with device-independence it is strongly discouraged).
   Direct access to the printer device also allows you to transmit
   device I/O commands, such as reset and flush, and do a raster dump on
   a graphics-capable printer.

   Use A Stream to Escape.
   -----------------------
   All "raw escape sequences" transmitted to the printer through the
   printer device must take the form of a character stream.

 Opening Prt:        Writing To Prt:        Closing Prt:


10 / Printer Device Access / Opening Prt:

When using the printer device as PRT:, you can open it just as though it
were a normal AmigaDOS output file.

    struct FileHandle *file;

    file = Open( "PRT:", MODE_NEWFILE ); /* Open PRT: */
    if (file == 0)                       /* if the open was unsuccessful */
        exit(PRINTER_WONT_OPEN);


10 / Printer Device Access / Writing To Prt:

Once you've opened it, you can print by calling the AmigaDOS Write()
standard I/O routine.

    actual_length = Write(file, dataLocation, length);

    where

    file is a file handle.

dataLocation
   is a pointer to the first character in the output stream you wish to
   write.  This stream can contain the standard escape sequences as
   shown in the command table below. The printer command aRAW (see the
   Printer Device Command Functions table below) can be used in the
   stream if character translation is not desired.

length
   is the length of the output stream.

actual_length
   is the actual length of the write. For the printer device, if there
   are no errors, this will be the same as the length of write
   requested. The only exception is if you specify a value of -1 for
   length. In this case, -1 for length means that a null (0) terminated
   stream is being written to the printer device. The device returns the
   count of characters written prior to encountering the null.  If it
   returns a value of -1 in actual_length, there has been an error.

   -1 = STOP!
   ----------
   If a -1 is returned by Write(), do not do any additional printing.


10 / Printer Device Access / Closing Prt:

When the printer I/O is complete, you should close PRT:. Don't keep the
device open when you are not using it.  The user may have changed the
printer settings by using the Workbench Preferences tool.  There's also
the possibility the printer has been turned off and on again causing the
printer to switch to its own default settings. Every time the printer
device is opened, it reads the current Preferences settings. Hence, by
always opening the printer device just before printing and always closing
it afterwards, you ensure that your application is using the current
Preferences settings.

Close(file);

   In DOS, You Must Be A Process.
   ------------------------------
   Printer I/O through the DOS must be done by a process, not by a task.
   DOS utilizes information in the process control block and would
   become confused if a simple task attempted to perform these
   activities. Printer I/O using the printer device directly, however,
   can be performed by a task.

The remainder of this chapter will deal with using the printer device
directly.


10 Printer Device / Device Interface

The printer device operates like the other Amiga devices.  To use it, you
must first open the printer device, then send I/O requests to it, and then
close it when finished.  See the Introduction to Amiga Devices chapter
for general information on device usage.

There are three distinct kinds of data structures required by the printer
I/O routines. Some of the printer device I/O commands, such as CMD_START
and CMD_WRITE require only an IOStdReq data structure. Others, such as
PRD_DUMPRPORT and PRD_PRTCOMMAND, require an extended data structure
called IODRPReq (for "Dump a RastPort Request") or IOPrtCmdReq (for
"Printer Command Request").

For convenience, it is strongly recommended that you define a single data
structure called printerIO, that can be used to represent any of the three
pre-defined printer communications request blocks.

    union printerIO
    {
        struct IOStdReq    ios;
        struct IODRPReq    iodrp;
        struct IOPrtCmdReq iopc;
    };

    struct IODRPReq
    {
        struct  Message io_Message;
        struct  Device  *io_Device;     /* device node pointer  */
        struct  Unit    *io_Unit;       /* unit (driver private)*/
        UWORD   io_Command;             /* device command */
        UBYTE   io_Flags;
        BYTE    io_Error;               /* error or warning num */
        struct  RastPort *io_RastPort;  /* raster port */
        struct  ColorMap *io_ColorMap;  /* color map */
        ULONG   io_Modes;               /* graphics viewport modes */
        UWORD   io_SrcX;                /* source x origin */
        UWORD   io_SrcY;                /* source y origin */
        UWORD   io_SrcWidth;            /* source x width */
        UWORD   io_SrcHeight;           /* source x height */
        LONG    io_DestCols;            /* destination x width */
        LONG    io_DestRows;            /* destination y height */
        UWORD   io_Special;             /* option flags */
    };

    struct IOPrtCmdReq
    {
        struct  Message io_Message;
        struct  Device  *io_Device;     /* device node pointer  */
        struct  Unit    *io_Unit;       /* unit (driver private)*/
        UWORD   io_Command;             /* device command */
        UBYTE   io_Flags;
        BYTE    io_Error;               /* error or warning num */
        UWORD   io_PrtCommand;          /* printer command */
        UBYTE   io_Parm0;               /* first command parameter */
        UBYTE   io_Parm1;               /* second command parameter */
        UBYTE   io_Parm2;               /* third command parameter */
        UBYTE   io_Parm3;               /* fourth command parameter */
    };

See the include file exec/io.h for more information on IOStdReq and the
include file devices/printer.h for more information on IODRPReq and
IOPrtCmdReq.

 Opening The Printer Device
 Writing Text To The Printer Device
 Important Points About Print Requests
 Closing The Printer Device


10 / Device Interface / Opening The Printer Device

Three primary steps are required to open the printer device:

   *  Create a message port using CreatePort().  Reply messages from the
      device must be directed to a message port.

   *  Create an extended I/O request structure of type printerIO with the
      CreateExtIO() function.  This means that one memory area can be used
      to represent three distinct forms of memory layout for the three
      different types of data structures that must be used to pass commands
      to the printer device. By using CreateExtIO(), you automatically
      allocate enough memory to hold the largest structure in the union
      statement.

   *  Open the printer device.  Call OpenDevice(), passing the I/O request.

    union printerIO
    {
        struct IOStdReq    ios;
        struct IODRPReq    iodrp;
        struct IOPrtCmdReq iopc;
    };

    struct MsgPort  *PrintMP;         /* Message port pointer */
    union printerIO *PrintIO;         /* I/O request pointer */

    if (PrintMP=CreateMsgPort() )
      if (PrintIO=(union printerIO *)
                   CreateExtIO(PrintMP,sizeof(union printerIO)) )
         if (OpenDevice("printer.device",0L,(struct IORequest *)PrintIO,0))
              printf("printer.device did not open\n");

The printer device automatically fills in default settings for all printer
device parameters from Preferences.  In addition, information about the
printer itself is placed into the appropriate fields of printerIO. (See
the Obtaining Printer Specific Data section below.)

   Pre-V36 Tasks and OpenDevice().
   -------------------------------
   Tasks in pre-V36 versions of the operating system are not able to
   safely OpenDevice() the printer device because it may be necessary to
   load it in from disk, something only a process could do under
   pre-V36.  V36 and higher versions of the operating system do not have
   such a limitation.


10 / Device Interface / Writing Text To The Printer Device

Text written to a printer can be either processed text or unprocessed text.

Processed text is written to the device using the CMD_WRITE command. The
printer device accepts a character stream, translates any embedded escape
sequences into the proper sequences for the printer being used and then
sends it to the printer.  The escape sequence translation is based on the
printer driver selected either through Preferences or through your
application.  You may also send a NULL-terminated string as processed text.

Unprocessed text is written to the device using the PRD_RAWWRITE command.
The printer device accepts a character stream and sends it unchanged to
the printer.  This implies that you know the exact escape sequences
required by the printer you are using.  You may not send a NULL-terminated
string as unprocessed text.

One additional point to keep in mind when using PRD_RAWWRITE is that
Preference settings for the printer are ignored.  Unless the printer has
already been initialized by another command, the printer's own default
settings will be used when printing raw, not the user's Preferences
settings.

You write processed text to the printer device by passing an IOStdReq to
the device with CMD_WRITE set in io_Command, the number of bytes to be
written set in io_Length and the address of the write buffer set in
io_Data.

To write a NULL-terminated string, set the length to -1; the device will
output from your buffer until it encounters a value of zero (0x00).

    PrintIO->ios.io_Length  = -1;
    PrintIO->ios.io_Data    =
         (APTR)"I went to a fight and a hockey game broke out."
    PrintIO->ios.io_Command = CMD_WRITE;
    DoIO((struct IORequest *)PrintIO);

The length of the request is -1, meaning we are writing a NULL-terminated
string. The number of characters sent will be found in io_Actual after the
write request has completed.

You write unprocessed text to the printer device by passing an IOStdReq to
the device with PRD_RAWWRITE set in io_Command, the number of bytes to be
written set in io_Length and the address of the write buffer set in
io_Data.

    UBYTE *outbuffer;

    PrintIO->ios.io_Length   = strlen(outbuffer);
    PrintIO->ios.io_Data     = (APTR)outbuffer;
    PrintIO->ios.io_Command  = PRD_RAWWRITE;
    DoIO((struct IORequest *)PrintIO);

   IOStdReq Only.
   --------------
   I/O requests with CMD_WRITE and PRD_RAWWRITE must use the IOStdReq
   structure of the union printerIO.


10 / Device Interface / Important Points About Print Requests

*  Perform printer I/O from a separate task or process
   It is quite reasonable for a user to expect that printing will be
   performed as a background operation.  You should try to accommodate
   this expectation as much as possible.

*  Give the user a chance to stop
   Your application should always allow the user to stop a print request
   before it is finished.

*  Don't confuse aborting a print request with cancelling a page
   Some applications seem to offer the user the ability to abort a
   multi-page print request when in fact the abort is only for the
   current page being printed. This results in the next page being
   printed instead of the request being stopped. Do not do this!  It
   only confuses the user and takes away from your application.  There
   is nothing wrong with allowing the user to cancel a page and continue
   to the next page, but it should be explicit that this is the case. If
   you abort a print request, the entire request should be aborted.


10 / Device Interface / Closing The Printer Device

Each OpenDevice() must eventually be matched by a call to CloseDevice().

All I/O requests must be complete before CloseDevice().  If any requests
are still pending, abort them with AbortIO().

   AbortIO(PrintIO);  /* Ask device to abort request, if pending */
   WaitIO(PrintIO);   /* Wait for abort, then clean up */

   CloseDevice((struct IORequest *)PrintIO);

   Use AbortIO() / WaitIO() Intelligently.
   -------------------------------------
   Only call AbortIO()/WaitIO() for requests which have already been
   sent to the printer device.  Using the AbortIO()/WaitIO() sequence on
   requests which have not been sent results in a hung condition.


10 Printer Device / Sending Printer Commands to a Printer

As mentioned before, it is possible to include printer commands (escape
sequences) in the character stream and send them to the printer using the
CMD_WRITE device I/O command. It is also possible to use the printer
command names using the device I/O command PRD_PRTCOMMAND with the
IOPrtCmdReq data structure. This gives you a mnemonic way of setting the
printer to your program needs.

You send printer commands to the device by passing an IOPrtCmdReq to the
device with PRD_PRTCOMMAND set in io_Command, the printer command set in
io_PrtCommand and up to four parameters set in Parm0 through Parm3.

   #include <devices/printer.h>

   PrintIO->iopc.io_PrtCommand = aSLRM;  /* Set left & right margins */
   PrintIO->iopc.io_Parm0 = 1;           /* Set left margin = 1 */
   PrintIO->iopc.io_Parm1 = 79;          /* Set right margin = 79 */
   PrintIO->iopc.io_Parm2 = 0;
   PrintIO->iopc.io_Parm3 = 0;
   PrintIO->iopc.io_Command = PRD_PRTCOMMAND;
   DoIO((struct IORequest *)PrintIO);

Consult the command function table listed below for other printer commands.

 Printer Command Definitions


10 / Sending Printer Commands to a Printer / Command Definitions

The following table describes the supported printer functions.

   Just Because We Have It Doesn't Mean You Do.
   --------------------------------------------
   Not all printers support every command.  Unsupported commands will
   either be ignored or simulated using available functions.

To transmit a command to the printer device, you can either formulate a
character stream containing the material shown in the "Escape Sequence"
column of the table below or send an PRD_PRTCOMMAND device I/O command
to the printer device with the "Name" of the function you wish to
perform.

                     PRINTER DEVICE COMMAND FUNCTIONS

           Cmd     Escape                                          Defined
   Name    No.     Sequence   Function                               by:
   ----    ---     --------   --------                             -------
   aRIS    0       ESCc       Reset                                ISO
   aRIN    1       ESC#1      Initialize                           +++
   aIND    2       ESCD       Linefeed                             ISO
   aNEL    3       ESCE       Return,linefeed                      ISO
   aRI     4       ESCM       Reverse linefeed                     ISO
   aSGR0   5       ESC[0m     Normal char set                      ISO
   aSGR3   6       ESC[3m     Italics on                           ISO
   aSGR23  7       ESC[23m    Italics off                          ISO
   aSGR4   8       ESC[4m     Underline on                         ISO
   aSGR24  9       ESC[24m    Underline off                        ISO
   aSGR1   10      ESC[1m     Boldface on                          ISO
   aSGR22  11      ESC[22m    Boldface off                         ISO
   aSFC    12      ESC[nm     Set foreground color where n         ISO
                              stands for a pair of ASCII digits,
                              3 followed by any number 0-9
                              (See ISOColor Table)

   aSBC    13      ESC[nm     Set background color where n         ISO
                              stands for a pair of ASCII digits,
                              4 followed by any number 0-9
                              (See ISO Color Table)

   aSHORP0 14      ESC[0w     Normal pitch                         DEC
   aSHORP2 15      ESC[2w     Elite on                             DEC
   aSHORP1 16      ESC[1w     Elite off                            DEC
   aSHORP4 17      ESC[4w     Condensed fine on                    DEC
   aSHORP3 18      ESC[3w     Condensed off                        DEC
   aSHORP6 19      ESC[6w     Enlarged on                          DEC
   aSHORP5 20      ESC[5w     Enlarged off                         DEC
   aDEN6   21      ESC[6"z    Shadow print on                      DEC
   aDEN5   22      ESC[5"z    Shadow print off            (sort of)DEC
   aDEN4   23      ESC[4"z    Doublestrike on                      DEC
   aDEN3   24      ESC[3"z    Doublestrike off                     DEC
   aDEN2   25      ESC[2"z    NLQ on                               DEC
   aDEN1   26      ESC[1"z    NLQ off                              DEC

   aSUS2   27      ESC[2v     Superscript on                       +++
   aSUS1   28      ESC[1v     Superscript off                      +++
   aSUS4   29      ESC[4v     Subscript on                         +++
   aSUS3   30      ESC[3v     Subscript off                        +++
   aSUS0   31      ESC[0v     Normalize the line                   +++
   aPLU    32      ESCL       Partial line up                      ISO
   aPLD    33      ESCK       Partial line down                    ISO

   aFNT0   34      ESC(B      US char set or Typeface 0            DEC
   aFNT1   35      ESC(R      French char set or Typeface 1        DEC
   aFNT2   36      ESC(K      German char set or Typeface 2        DEC
   aFNT3   37      ESC(A      UK char set or Typeface 3            DEC
   aFNT4   38      ESC(E      Danish I char set or Typeface 4      DEC
   aFNT5   39      ESC(H      Swedish char set or Typeface 5       DEC
   aFNT6   40      ESC(Y      Italian char set or Typeface 6       DEC
   aFNT7   41      ESC(Z      Spanish char set or Typeface 7       DEC
   aFNT8   42      ESC(J      Japanese char set or Typeface 8      +++
   aFNT9   43      ESC(6      Norwegian char set or Typeface 9     DEC
   aFNT10  44      ESC(C      Danish II char set or Typeface 10    +++
                              (See Suggested Typefaces Table)

   aPROP2  45      ESC[2p     Proportional on                      +++
   aPROP1  46      ESC[1p     Proportional off                     +++
   aPROP0  47      ESC[0p     Proportional clear                   +++
   aTSS    48      ESC[n E    Set proportional offset              ISO
   aJFY5   49      ESC[5 F    Auto left justify                    ISO
   aJFY7   50      ESC[7 F    Auto right justify                   ISO
   aJFY6   51      ESC[6 F    Auto full justify                    ISO
   aJFY0   52      ESC[0 F    Auto justify off                     ISO
   aJFY3   53      ESC[3 F    Letter space (justify)      (special)ISO
   aJFY1   54      ESC[1 F    Word fill(auto center)      (special)ISO

   aVERP0  55      ESC[0z     1/8" line spacing                    +++
   aVERP1  56      ESC[1z     1/6" line spacing                    +++
   aSLPP   57      ESC[nt     Set form length n                    DEC
   aPERF   58      ESC[nq     Perf skip n (n>0)                    +++
   aPERF0  59      ESC[0q     Perf skip off                        +++

   aLMS    60      ESC#9      Left margin set                      +++
   aRMS    61      ESC#0      Right margin set                     +++
   aTMS    62      ESC#8      Top margin set                       +++
   aBMS    63      ESC#2      Bottom margin set                    +++
   aSTBM   64      ESC[n;     nr Top and bottom margins            DEC
   aSLRM   65      ESC[n;     ns Left and right margins DEC
   aCAM    66      ESC#3      Clear margins +++

   aHTS    67      ESCH       Set horizontal tab                   ISO
   aVTS    68      ESCJ       Set vertical tabs                    ISO
   aTBC0   69      ESC[0g     Clear horizontal tab                 ISO
   aTBC3   70      ESC[3g     Clear all h. tabs                    ISO
   aTBC1   71      ESC[1g     Clear vertical tab                   ISO
   aTBC4   72      ESC[4g     Clear all v. tabs                    ISO
   aTBCALL 73      ESC#4      Clear all h. & v. tabs               +++
   aTBSALL 74      ESC#5      Set default tabs                     +++
   aEXTEND 75      ESC[n"x    Extended commands                    +++

   aRAW    76      ESC[n"r    Next n chars are raw                 +++

   Legend:
   ------
   ISO     indicates that the sequence has been defined by the
           International Standards Organization.  This is
           also very similar to ANSI x3.64.

   DEC     indicates a control sequence defined by Digital Equipment
           Corporation.

   +++     indicates a sequence unique to Amiga.

   n       stands for a decimal number expressed as a set of ASCII
           digits. In the aRAW string ESC[5"rHELLO, n is substituted by 5,
           the number of RAW characters you send to the printer.

           ISO Color Table            Suggested Typefaces
           ---------------            -------------------
           0  Black                   0   Default typeface
           1  Red                     1   Line Printer or equivalent
           2  Green                   2   Pica or equivalent
           3  Yellow                  3   Elite or equivalent
           4  Blue                    4   Helvetica or equivalent
           5  Magenta                 5   Times Roman or equivalent
           6  Cyan                    6   Gothic or equivalent
           7  White                   7   Script or equivalent
           8  NC                      8   Prestige or equivalent
           9  Default                 9   Caslon or equivalent
                                      10  Orator or equivalent


10 Printer Device / Obtaining Printer Specific Data

Information about the printer in use can be obtained by reading the
PrinterData and PrinterExtendedData structures.  The values found in these
structures are determined by the printer driver selected through
Preferences.  The data structures are defined in devices/prtbase.h.

Printer specific data is returned in printerIO when the printer device is
opened.  To read the structures, you must first set the PrinterData
structure to point to iodrp.io_Device of the printerIO used to open the
device and then set PrinterExtendedData to point to the extended data
portion of PrinterData.

     Printer_Data.c


10 Printer Device / Reading and Changing Printer Preferences Settings

The user preferences can be read and changed without running the Workbench
Preferences tool.  Reading printer preferences can be done by referring to
PD->pd_Preferences.  Listed on the next page are the printer Preferences
fields and their valid ranges.

Text Preferences
----------------
    PrintPitch        -  PICA, ELITE, FINE
    PrintQuality      -  DRAFT, LETTER
    PrintSpacing      -  SIX_LPI, EIGHT_LPI
    PrintLeftMargin   -  1 to PrintRightMargin
    PrintRightMargin  -  PrintLeftMargin to 999
    PaperLength       -  1 to 999
    PaperSize         -  US_LETTER, US_LEGAL, N_TRACTOR, W_TRACTOR,CUSTOM
    PaperType         -  FANFOLD, SINGLE

Graphic Preferences
-------------------
    PrintImage        -  IMAGE_POSITIVE, IMAGE_NEGATIVE
    PrintAspect       -  ASPECT_HORIZ, ASPECT_VERT
    PrintShade        -  SHADE_BW, SHADE_GREYSCALE, SHADE_COLOR
    PrintThreshold    -  1 to 15
    PrintFlags        -  CORRECT_RED, CORRECT_GREEN, CORRECT_BLUE,
                         CENTER_IMAGE, IGNORE_DIMENSIONS,
                         BOUNDED_DIMENSIONS, ABSOLUTE_DIMENSIONS,
                         PIXEL_DIMENSIONS, MULTIPLY_DIMENSIONS,
                         INTEGER_SCALING, ORDERED_DITHERING,
                         HALFTONE_DITHERING, FLOYD_DITHERING,
                         ANTI_ALIAS, GREY_SCALE2
    PrintMaxWidth     -  0 to 65535
    PrintMaxHeight    -  0 to 65535
    PrintDensity      -  1 to 7
    PrintXOffset      -  0 to 255

This example program changes various settings in the printer device's
copy of preferences.

     Set_Prefs.c

   Do Your Duty.
   -------------
   The application program is responsible for range checking if the user
   is able to change the preferences from within the application.


10 Printer Device / Querying the Printer Device

The status of the printer port and registers can be determined by querying
the printer device.  The information returned will vary depending on the
type of printer - parallel or serial - selected by the user.  If parallel,
the data returned will reflect the current state of the parallel port; if
serial, the data returned will reflect the current state of the serial
port.

You query the printer device by passing an IOStdReq to the device with
PRD_QUERY set in io_Command and a pointer to a structure to hold the

status set in io_Data.

   struct PStat
   {
       UBYTE LSB;       /* least significant byte of status */
       UBYTE MSB;       /* most significant byte of status */
   };

   union printerIO *PrintIO;

   struct PStat status;

   PrintIO->ios.io_Data = &status;      /* point to status structure */
   PrintIO->ios.io_Command = PRD_QUERY;
   DoIO((struct IORequest *)request);

The status is returned in the two UBYTES set in the io_Data field.  The
printer type, either serial or parallel, is returned in the io_Actual
field.

   io_Data         Bit     Active          Function (Serial Device)
   -------         ---     ------          ------------------------
     LSB           0       low             reserved
                   1       low             reserved
                   2       low             reserved
                   3       low             Data Set Ready
                   4       low             Clear To Send
                   5       low             Carrier Detect
                   6       low             Ready To Send
                   7       low             Data Terminal Ready
     MSB           8       high            read buffer overflow
                   9       high            break sent (most recent output)
                   10      high            break received (as latest input)
                   11      high            transmit x-OFFed
                   12      high            receive x-OFFed
                   13-15   high            reserved

   io_Data         Bit     Active          Function (Parallel Device)
   -------         ---     ------          --------------------------
     LSB           0       high            printer busy (offline)
                   1       high            paper out
                   2       high            printer selected
                   3        -              read=0; write=1
                   4-7                     reserved
     MSB           8-15                    reserved

   io_Actual                               1-parallel, 2-serial


10 Printer Device / Error Codes from the Printer Device

The printer device returns error codes whenever an operation is attempted.
There are two types of error codes that can be returned.  Printer device
error codes have positive values; Exec I/O error codes have negative
values. Therefore, an application should check for a non-zero return code
as evidence of an error, not simply a value greater than zero.

   PrintIO->ios.io_Length   = strlen(outbuffer);
   PrintIO->ios.io_Data     = (APTR)outbuffer;
   PrintIO->ios.io_Command  = PRD_RAWWRITE;
   if (DoIO((struct IORequest *)PrintIO))
       printf("RAW Write failed.  Error: %d ",PrintIO->ios.io_Error);

The error is found in io_Error.

                  PRINTER DEVICE ERROR CODES

   Error                   Value Explanation
   -----                   ----- -----------
   PDERR_NOERR               0   Operation successful
   PDERR_CANCEL              1   User canceled request
   PDERR_NOTGRAPHICS         2   Printer cannot output graphics
   PDERR_INVERTHAM           3   OBSOLETE
   PDERR_BADDIMENSION        4   Print dimensions are illegal
   PDERR_DIMENSIONOVERFLOW   5   OBSOLETE
   PDERR_INTERNALMEMORY      6   No memory available for internal variables
   PDERR_BUFFERMEMORY        7   No memory available for print buffer

                      EXEC ERROR CODES

   Error                   Value Explanation
   ----                    ----- -----------
   IOERR_OPENFAIL           -1   Device failed to open
   IOERR_ABORTED            -2   Request terminated early (after AbortIO())
   IOERR_NOCMD              -3   Command not supported by device
   IOERR_BADLENGTH          -4   Not a valid length


10 Printer Device / Dumping a Rastport to a Printer

You dump a RastPort (drawing area) to a graphics capable printer by
passing an IODRPReq to the device with PRD_DUMPRPORT set in io_Command
along with several parameters that define how the dump is to be rendered.

    union printerIO *PrintIO
    struct RastPort *rastPort;
    struct ColorMap *colorMap;
    ULONG modeid;
    UWORD sx, sy, sw, sh;
    LONG dc, dr;
    UWORD s;

    PrintIO->iodrp.io_RastPort = rastPort; /* pointer to RastPort */
    PrintIO->iodrp.io_ColorMap = colorMap; /* pointer to color map */
    PrintIO->iodrp.io_Modes = modeid;      /* ModeID of ViewPort */
    PrintIO->iodrp.io_SrcX = sx;           /* RastPort X offset */
    PrintIO->iodrp.io_SrcY = sy;           /* RastPort Y offset */
    PrintIO->iodrp.io_SrcWidth = sw;       /* print width from X offset */
    PrintIO->iodrp.io_SrcHeight = sh;      /* print height from Y offset */
    PrintIO->iodrp.io_DestCols = dc;       /* pixel width */
    PrintIO->iodrp.io_DestRows = dr;       /* pixel height */
    PrintIO->iodrp.io_Special = s;         /* flags */
    PrintIO->iodrp.io_Command = PRD_DUMPRPORT;
    SendIO((struct IORequest *)request);

The asynchronous SendIO() routine is used in this example instead of the
synchronous DoIO().  A call to DoIO() does not return until the I/O
request is finished. A call to SendIO() returns immediately.  This allows
your task to do other processing such as checking if the user wants to
abort the I/O request.  It should also be used when writing a lot of text
or raw data with CMD_WRITE and PRD_RAWWRITE.

Here is an overview of the possible arguments for the RastPort dump.

   io_RastPort     A pointer to a RastPort. The RastPort's bitmap could be
                   in Fast memory.

   io_ColorMap     A pointer to a ColorMap. This could be a custom one.
   io_Modes        The viewmode flags or the ModeID returned from
                   GetVPModeID() (V36).

   io_SrcX         X offset in the RastPort to start printing from.
   io_SrcY         Y offset in the RastPort to start printing from.
   io_SrcWidth     Width of the RastPort to print from io_SrcX.
   io_SrcHeight    Height of the RastPort to print from io_SrcY.
   io_DestCols     Width of the dump in printer pixels.
   io_DestRows     Height of the dump in printer pixels.
   io_Special      Flag bits (described below).

Looking at these arguments you can see the enormous flexibility the
printer device offers for dumping a RastPort. The RastPort pointed to
could be totally custom defined. This flexibility means it is possible to
build a BitMap with the resolution of the printer. This would result in
having one pixel of the BitMap correspond to one pixel of the printer. In
other words, only the resolution of the output device would limit the
final result. With 12 bit planes and a custom ColorMap, you could dump
4096 colors - without the HAM limitation - to a suitable printer. The
offset, width and height parameters allow dumps of any desired part of the
picture. Finally the ViewPort mode, io_DestCols, io_DestRows parameters,
together with the io_Special flags define how the dump will appear on
paper and aid in getting the correct aspect ratio.

 Printer Special Flags
 Printing With Corrected Aspect Ratio
 Strip Printing
 Additional Notes About Graphic Dumps


10 / Dumping a Rastport to a Printer / Printer Special Flags

The printer special flags (io_Flags) of the IODRPReq provide a high degree
of control over the printing of a RastPort.

   SPECIAL_ASPECT       Allows one of the dimensions to be
                        reduced/expanded to preserve the correct
                        aspect ratio of the printout.

   SPECIAL_CENTER       Centers the image between the left and right
                        edge of the paper.

   SPECIAL_NOFORMFEED   Prevents the page from being ejected after
                        a graphics dump.  Usually used to mix graphics and
                        text or multiple graphics dump on a page oriented
                        printer (normally a laser printer).

   SPECIAL_NOPRINT      The print size will be computed, and set
                        in io_DestCols and io_DestRows, but won't print.
                        This way the application can see what the actual
                        printsize in printerpixels would be.

   SPECIAL_TRUSTME      Instructs the printer not to send a reset
                        before and after the dump.  This flag is obsolete
                        for V1.3 (and higher) drivers.

   SPECIAL_DENSITY1-7   This flag bit is set by the user in Preferences.
                        Refer to "Reading and Changing the Printer
                        Preferences Settings" if you want to change to
                        density of the printout. (Or any other setting for
                        that matter.)

   SPECIAL_FULLCOLS     The width is set to the maximum possible,
                        as determined by the printer or the configuration
                        limits.

   SPECIAL_FULLROWS     The height is set to the maximum possible, as
                        determined by the printer or the configuration
                        limits.

   SPECIAL_FRACCOLS     Informs the printer device that the value in
                        io_DestCols is to be taken as a longword binary
                        fraction of the maximum for the dimension.  For
                        example, if io_DestCols is 0x8000, the width
                        would be 1/2 (0x8000 / 0xffff) of the width of
                        the paper.

   SPECIAL_FRACROWS     Informs the printer device that the value in
                        io_DestRows is to be taken as a longword binary
                        fraction for the dimension.

   SPECIAL_MILCOLS      Informs the printer device that the value in
                        io_DestCols is specified in thousandths of an inch.
                        For example, if io_DestCols is 8000, the width of
                        the printout would be 8.000 inches.

   SPECIAL_MILROWS      Informs the printer device that the value in
                        io_DestRows is specified in thousandths of an inch.

The flags are defined in the include file devices/printer.h.


10 / Dumping Rastport to a Printer / Printing Corrected Aspect Ratio

Using the special flags it is fairly easy to ensure a graphic dump will
have the correct aspect ratio on paper. There are some considerations
though when printing a non-displayed RastPort.  One way to get a corrected
aspect ratio dump is to calculate the printer's ratio from XDotsInch and
YDotsInch (taking into account that the printer may not have square
pixels) and then adjust the width and height parameters accordingly. You
then ask for a non-aspect-ratio-corrected dump since you already corrected
it yourself.

Another possibility is having the printer device do it for you. To get a
correct calculation you could build your RastPort dimensions in two ways:

   1. Using an integer multiple of one of the standard (NTSC) display
      resolutions and setting the io_Modes argument accordingly. For
      example if your RastPort dimensions were 1280 x 800 (an even multiple
      of 640 x 400) you would set io_Modes to LACE | HIRES. Setting the
      SPECIAL_ASPECT flag would enable the printer device to properly
      calculate the aspect ratio of the image.

   2. When using an arbitrary sized RastPort, you can supply the ModeID of
      a display mode which has the aspect ratio you would like for your
      RastPort. The aspect ratio of the various display modes are defined
      as ticks-per-pixel in the Resolution field of the DisplayInfo
      structure.  You can obtain this value from the graphics database.
      For example, the resolution of Productivity Mode is 22:22, in other
      words, 1:1, perfect for a RastPort sized to the limits of the output
      device.  See the "Graphics Library" chapters of the  Amiga ROM
      Kernel Reference Manual: Libraries for general information on the
      graphics system.

The following example will dump a RastPort to the printer and wait for
either the printer to finish or the user to cancel the dump and act
accordingly.

     Demo_Dump.c


10 / Dumping a Rastport to a Printer / Strip Printing

Strip printing is a method which allows you to print a picture that
normally requires a large print buffer when there is not much memory
available. This would allow, for example, a RastPort to be printed at a
higher resolution than it was drawn in. Strip printing is done by creating
a temporary RastPort as wide as the source RastPort, but not as high. The
source RastPort is then rendered, a strip at a time, into the temporary
RastPort which is dumped to the printer.

The height of the strip to dump must be an integer multiple of the
printer's NumRows if a non-aspect-ratio-corrected image is to be printed.

For an aspect-ratio-corrected image, the SPECIAL_NOPRINT flag will have
to be used to find an io_DestRows that is an integer multiple of NumRows.
This can be done by varying the source height and asking for a
SPECIAL_NOPRINT dump until io_DestRows holds a number that is an integer
multiple of the printer's NumRows.

If smoothing is to work with strip printing, a raster line above and below
the actual area should be added. The line above should be the last line
from the previous strip, the line below should be the first line of the
next strip. Of course, the first strip should not have a line added above
and the last strip should not have a line added below.

The following is a strip printing procedure for a RastPort which is 200
lines high.

First strip

   * copy source line 0 through 50 (51 lines) to strip RastPort lines 0
     through 50 (51 lines).
   * io_SrcY = 0, io_Height = 50.
   * the printer device can see there is no line above the first line to
     dump (since SrcY = 0) and that there is a line below the last line to
     dump (since there is a 51 line RastPort and only 50 lines are dumped).

Second strip

   * copy source line 49 through 100 (52 lines) to strip RastPort lines 0
     through 51 (52 lines).
   * io_SrcY = 1, io_Height = 50.
   * the printer device can see there is a line above the first line to
     dump (since SrcY = 1) and that there is a line below the last line to
     dump (since there is a 52 line RastPort and only 50 lines are dumped).

Third strip

   * copy source line 99 through 150 (52 lines) to strip RastPort lines 0
     through 51 (52 lines).
   * io_SrcY = 1, io_Height = 50.
   * the printer device can see there is a line above the first line to
     dump (since SrcY = 1) and that there is a line below the last line to
     dump (since there is a 52 line RastPort and only 50 lines are dumped).

Fourth strip

   * copy source line 149 through 199 (51 lines) to strip RastPort lines 0
     through 50 (51 lines).
   * io_SrcY = 1, io_Height = 50.
   * the printer device can see there is a line above the first line to
     dump (since SrcY = 1) and that there is no line below the last line to
     dump (since there is a 51 line RastPort and only 50 lines are dumped).


10 / Dumping Rastport to a Printer / Additional Notes on Graphic Dumps

   1. When dumping a 1 bitplane image select the black and white mode in
      Preferences. This is much faster than a grey-scale or color dump.

   2. Horizontal dumps are much faster than vertical dumps.

   3. Smoothing doubles the print time.  Use it for final copy only.

   4. F-S dithering doubles the print time.  Ordered and half-tone
      dithering incur no extra overhead.

   5. The lower the density, the faster the printout.

   6. Friction-fed paper tends to be much more accurate than tractor-fed
      paper in terms of vertical dot placement (i.e., less horizontal
      strips or white lines).

   7. Densities which use more than one pass tend to produce muddy
      grey-scale or color printouts.  It is recommended not to choose these
      densities when doing a grey-scale or color dump.

   Keep This in Mind.
   ------------------
   It is possible that the printer has been instructed to receive a
   certain amount of data and is still in an "expecting" state if an
   I/O request has been aborted by the user. This means the printer
   would try to finish the job with the data the next I/O request might
   send. Currently the best way to overcome this problem is for the
   printer to be reset.


10 Printer Device / Creating a Printer Driver

Creating the printer-dependent modules for the printer device involves
writing the data structures and code, compiling and assembling them, and
linking to produce an Amiga binary object file. The modules a driver
contains varies depending on whether the printer is non-graphics or
graphics capable.

All drivers contain these modules:

   macros.i        -  include file for init.asm,contains printer device
                      macro definitions
   printertag.asm  -  printer specific capabilities such as density,
                      character sets and color
   init.asm        -  opens the various libraries required by the printer
                      driver.  This will be the same for all printers
   data.c          -  contains printer device RAW commands and the extended
                      character set supported by the printer
   dospecial.c     -  printer specific special processing required for
                      printer device commands like aSLRM and aSFC

Graphic printer drivers require these additional modules:

   render.c        -  printer specific processing to do graphics output
                      and fill the output buffer
   transfer.c      -  printer specific processing called by render.c
                      to output the buffer to the printer.  Code it in
                      assembly if speed is important
   density.c       -  printer specific processing to construct the proper
                      print density commands

The first piece of the printer driver is the PrinterSegment structure
described in devices/prtbase.h (this is pointed to by the BPTR returned by
the LoadSeg() of the object file). The PrinterSegment contains the
PrinterExtendedData (PED) structures (also described in devices/prtbase.h)
at the beginning of the object.  The PED structure contains data
describing the capabilities of the printer, as well as pointers to code
and other data. Here is the assembly code for a sample PrinterSegment,
which would be linked to the beginning of the sequence of files as
printertag.asm.

     printertag.asm

The printer name should be the brand name of the printer that is available
for use by programs wishing to be specific about the printer name in any
diagnostic or instruction messages. The four functions at the top of the
structure are used to initialize this printer-dependent code:

   (*(PED->ped_Init))(PD) ;
      This is called when the printer-dependent code is loaded and provides
      a pointer to the printer device for use by the printer-dependent
      code. It can also be used to open up any libraries or devices needed
      by the printer-dependent code.

   (*(PED->ped_Expunge))() ;
      This is called immediately before the printer-dependent code is
      unloaded, to allow it to close any resources obtained at
      initialization time.

   (*(PED->ped_Open))(ior) ;
      This is called in the process of an OpenDevice() call, after the
      Preferences are read and the correct primitive I/O device (parallel
      or serial) is opened.  It must return zero if the open is successful,
      or non-zero to terminate the open and return an error to the user.

   (*(PED->ped_Close))(ior) ;
      This is called in the process of a CloseDevice() call to allow the
      printer-dependent code to close any resources obtained at open time.

The pd_ variable provided as a parameter to the initialization call is a
pointer to the PrinterData structure described in devices/prtbase.h. This
is also the same as the io_Device entry in printer I/O requests.

   pd_SegmentData
      This points back to the PrinterSegment, which contains the PED.

   pd_PrintBuf
      This is available for use by the printer-dependent code - it is not
      otherwise used by the printer device.

   (*pd_PWrite)(data, length);
      This is the interface routine to the primitive I/O device.  This
      routine uses two I/O requests to the primitive device, so writes are
      double-buffered. The data parameter points to the byte data to send,
      and the length is the number of bytes.

   (*pd_PBothReady)();
      This waits for both primitive I/O requests to complete.  This is
      useful if your code does not want to use double buffering.  If you
      want to use the same data buffer for successive pd_PWrites, you must
      separate them with a call to this routine.

   pd_Preferences
      This is the copy of Preferences in use by the printer device,
      obtained when the printer was opened.

The timeout field is the number of seconds that an I/O request from the
printer device to the primitive I/O device (parallel or serial) will
remain posted and unsatisfied before the timeout requester is presented to
the user. The timeout value should be long enough to avoid the requester
during normal printing.

The PrintMode field is a flag which indicates whether text has been
printed or not (1 means printed, 0 means not printed). This flag is used
in drivers for page oriented printers to indicate that there is no
alphanumeric data waiting for a formfeed.

 Writing Alphanumeric Printer Drivers
 Writing A Graphics Printer Driver
 Testing The Printer Driver


10 / Creating a Printer Driver / Writing Alphanumeric Printer Drivers

The alphanumeric portion of the printer driver is designed to convert ANSI
x3.64 style commands into the specific escape codes required by each
individual printer.  For example, the ANSI code for underline-on is
ESC[4m.  The Commodore MPS-1250 printer would like a ESC[-1 to set
underline-on. The HP LaserJet accepts ESC[&dD as a start underline
command. By using the printer driver, all printers may be handled in a
similar manner.

There are two parts to the alphanumeric portion of the printer driver: the
Command Table data table and the DoSpecial() routine.

 Command Table
 DoSpecial()
 Printertag.asm
 Extended Character Table
 Character Conversion Routine


10 / / Writing An Alphanumeric Printer Driver / Command Table

The CommandTable is used to convert all escape codes that can be handled
by simple substitution. It has one entry per ANSI command supported by the
printer driver. When you are creating a custom CommandTable, you must
maintain the order of the commands in the same sequence as that shown in
devices/printer.h. By placing the specific codes for your printer in the
proper positions, the conversion takes place automatically.

   Octal knows NULL.
   -----------------
   If the code for your printer requires a decimal 0 (an ASCII NULL
   character), you enter this NULL into the CommandTable as octal 376
   (decimal 254).

Placing an octal value of 377 (255 decimal) in a position in the command
table indicates to the printer device that no simple conversion is
available on this printer for this ANSI command.  For example, if a
daisy-wheel printer does not have a foreign character set, 377 octal (255
decimal) is placed in that position in the command table. However, 377 in
a position can also mean that the ANSI command is to be handled by code
located in the DoSpecial() function. For future compatibility all printer
commands should be present in the command table, and those not supported
by the printer filled with the dummy entry 377 octal.


10 / / Writing An Alphanumeric Printer Driver / DoSpecial()

The DoSpecial() function is meant to implement all the ANSI functions that
cannot be done by simple substitution, but can be handled by a more
complex sequence of control characters sent to the printer. These are
functions that need parameter conversion, read values from Preferences,
and so on. Complete routines can also be placed in dospecial.c. For
instance, in a driver for a page oriented-printer such as the HP LaserJet,
the dummy Close() routine from the init.asm file would be replaced by a
real Close() routine in dospecial.c. This close routine would handle
ejecting the paper after text has been sent to the printer and the printer
has been closed.

The DoSpecial() function is set up as follows:

   #include "exec/types.h"
   #include "devices/printer.h"
   #include "devices/prtbase.h"

   extern struct PrinterData *PD;

   DoSpecial(command,outputBuffer,vline,currentVMI,crlfFlag,Parms)
   UBYTE outputBuffer[];
   UWORD *command;
   BYTE *vline;
   BYTE *currentVMI;
   BYTE *crlfFlag;
   UBYTE Parms[];
   {                /* code begins here... */

   where

   command
      points to the command number. The devices/printer.h file contains the
      definitions for the routines to use (aRIN is initialize, and so on).

   vline
      points to the value for the current line position.

   currentVMI
      points to the value for the current line spacing.

   crlfFlag
      points to the setting of the "add line feed after carriage return"
      flag.

   Parms
      contain whatever parameters were given with the ANSI command.

   outputBuffer
      points to the memory buffer into which the converted command is
      returned.

Almost every printer will require an aRIN (initialize) command in
DoSpecial(). This command reads the printer settings from Preferences and
creates the proper control sequence for the specific printer.  It also
returns the character set to normal (not italicized, not bold, and so on).
Other functions depend on the printer.

Certain functions are implemented both in the CommandTable and in the
DoSpecial() routine. These are functions such as superscript, subscript,
PLU (partial line up), and PLD (partial line down), which can often be
handled by a simple conversion. However, some of these functions must also
adjust the printer device's line-position variable.

   Save the Data!
   --------------
   Some printers lose data when sent their own reset command. For this
   reason, it is recommended that if the printer's own reset command is
   going to be used, PD->pd_PWaitEnabled should be defined to be a
   character that the printer will not print. This character should be
   put in the reset string before and after the reset character(s) in
   the command table.

In the EpsonX[CBM_MPS-1250] DoSpecial() function you'll see

   if (*command == aRIS)
       {        /* reset command */
       PD->pd_PWaitEnabled = \375; /* preserve that data! */
   }

while in the command table the string for reset is defined as
"\\375\\033@\\375". This means that when the printer device outputs the
reset string "\\033@", it will first see the "\\375", wait a second and
output the reset string. While the printer is resetting, the printer
device gets the second "\\375" and waits another second. This ensures that
no data will be lost if a reset command is embedded in a string.


10 / / Writing An Alphanumeric Printer Driver / Printertag.asm

For an alphanumeric printer the printer-specific values that need to be
filled in printertag.asm are as follows:

   MaxColumns
      the maximum number of columns the printer can print across the page.

   NumCharSets
      the number of character sets which can be selected.

   8BitChars
      a pointer to an extended character table. If the field is null, the
      default table will be used.

   ConvFunc
      a pointer to a character conversion routine. If the field is null,no
      conversion routine will be used.


10 / / Writing An Alphanumeric Printer Driver / Extended Character Table

The 8BitChars field could contain a pointer to a table of characters for
the ASCII codes $A0 to $FF. The symbols for these codes are shown in the
IFF Appendix of this manual. If this field contains a NULL, it means
no specific table is provided for the driver, and the default table is to
be used instead.

Care should be taken when generating this table because of the way the
table is parsed by the printer device. Valid expressions in the table
include \011 where 011 is an octal number, \\000 for null and \\n
where n is a 1 to 3 digit decimal number. To enter an actual backslash in
the table requires the somewhat awkward \\\\. As an example, here is a
list of the first entries of the EpsonxX[CBM_MPS-1250] table:

   char *ExtendedCharTable[] =
        {
        " ",                       /* NBSP */
        "\033R\007[\033R\\0",      /* i */
        "c\010|",                  /* c| */
        "\033R\003#\033R\\0",      /* L- */
        "\033R\005$\033R\\0",      /* o */
        "\033R\010\\\\\033R\\0",   /* Y- */
        "|",                       /* | */
        "\033R\002@\033R\\0",      /* SS */
        "\033R\001~\033R\\0",      /* " */
        "c",                       /* copyright */
        "\033S\\0a\010_\033T",     /* a_ */
        "<",                       /* << */
        "~",                       /* - */
        "-",                       /* SHY */
        "r",                       /* registered trademark */
        "-",                       /* - */
        /* more entries go here */
   };


10 / / Writing An Alphanumeric Printer Driver / Character Conversion

The ConvFunc field contains a pointer to a character conversion function
that allows you to selectively translate any character to a combination of
other characters. If no translation conversion is necessary (for most
printers it isn't), the field should contain a null.

ConvFunc() arguments are a pointer to a buffer, the character currently
processed, and a CR/LF flag. The ConvFunc() function should return a -1 if
no conversion has been done. If the character is not to be added to the
buffer, a 0 can be returned. If any translation is done, the number of
characters added to the buffer must be returned.

Besides simple character translation, the ConvFunc() function can be used
to add features like underlining to a printer which doesn't support them
automatically. A global flag could be introduced that could be set or
cleared by the DoSpecial() function. Depending on the status of the flag
the ConvFunc() routine could, for example, put the character, a backspace
and an underline character in the buffer and return 3, the number of
characters added to the buffer.

The ConvFunc() function for this could look like the following example:

   #define DO_UNDERLINE   0x01
   #define DO_BOLD        0x02
   /* etc */

   external short myflags;

   int ConvFunc(buffer, c, crlf_flag)
   char *buffer, c;
   int crlf_flag
   {
   int nr_of_chars_added = 0;

   /* for this example we only do this for chars in the 0x20-0x7e range */
   /* Conversion of ESC (0x1b) and CSI (0x9b) is NOT recommended */

   if (c > 0x1f && c < 0x7f)
       {             /* within space - ~ range ? */
       if (myflags & DO_UNDERLINE)
           {
           *buffer++ = c;                /* the character itself */
           *buffer++ = 0x08;             /* a backspace */
           *buffer++ = '_';              /* an underline char */
           nr_of_chars_added = 3;        /* added three chars to buffer */
           }
       if (myflags & DO_BOLD)
           {
           if (nr_of_chars_added)
               {      /* already have added something */
               *buffer++ = 0x08;         /* so we start with backspace */
               ++nr_of_chars_added;      /* and increment the counter */
               }
           *buffer++ = c;
           *buffer++ = 0x08;
           *buffer++ = c;
           ++nr_of_chars_added;
           if (myflags & DO_UNDERLINE)
               {      /* did we do underline too? */
               *buffer++ = 0x08;         /* then backspace again */
               *buffer++ = '_';          /* (printer goes crazy by now) */
               nr_of_chars_added += 2;   /* two more chars */
               }
           }
       }
   if (nr_of_chars_added)
       return(nr_of_chars_added);        /* total nr of chars we added */
   else
       return(-1);                       /* we didn't do anything */
   }

In DoSpecial() the flagbits could be set or cleared, with code like the
following:

   if (*command == aRIS)             /* reset  command */
       myflags = 0;                  /* clear all flags */

   if (*command == aRIN)             /* initialize command */
       myflags = 0;

   if (*command == aSGR0)            /* 'PLAIN' command */
       myflags = 0;

   if (*command == aSGR4)            /* underline on */
       myflags |= DO_UNDERLINE;      /* set underline bit */

   if (*command == aSGR24)           /* underline off */
       myflags &= ~DO_UNDERLINE;     /* clear underline bit */

   if (*command == aSGR1)            /* bold on */
       myflags |= DO_BOLD;           /* set bold bit */

   if (*command == aSGR22)           /* bold off */
       myflags &= ~DO_BOLD;          /* clear bold bit */

Try to keep the expansions to a minimum so that the throughput will not be
slowed down too much, and to reduce the possibility of data overrunning
the printer device buffer.


10 / Creating a Printer Driver / Writing A Graphics Printer Driver

Designing the graphics portion of a custom printer driver consists of two
steps: writing the printer-specific Render(), Transfer() and SetDensity()
functions, and replacing the printer-specific values in printertag.asm.
Render(), Transfer() and SetDensity() comprise render.c, transfer.c, and
density.c modules, respectively.

A printer that does not support graphics has a very simple form of
Render(); it returns an error. Here is sample code for Render() for a
non-graphics printer (such as an Alphacom or Diablo 630):

   #include "exec/types.h"
   #include "devices/printer.h"
   int Render()
   {
       return(PDERR_NOTGRAPHICS);
   }

The following section describes the contents of a typical driver for a
printer that does support graphics.

 Render()      Transfer()      SetDensity()      Printertag.asm


10 / Writing A Graphics Printer Driver / Render()

This function is the main printer-specific code module and consists of
seven parts referred to here as cases:

   *  Pre-Master initialization (Case 5)

   *  Master initialization (Case 0)

   *  Putting the pixels in a buffer (Case 1)

   *  Dumping a pixel buffer to the printer (Case 2)

   *  Closing down (Case 4)

   *  Clearing and initializing the pixel buffer (Case 3)

   *  Switching to the next color(Case 6)  (special case for multi-color
      printers)

   State Your Case.
   ----------------
   The numbering of the cases reflects the value of each step as a case
   in a C-language switch statement.  It does not denote the order that
   the functions are executed; the order in which they are listed above
   denotes that.

For each case, Render() receives four long variables as parameters:
ct, x,  y and status.  These parameters are described
below for each of the seven cases that Render() must handle.

Pre-Master initialization (Case 5)
----------------------------------
Parameters:

         ct - 0 or pointer to the IODRPReq structure passed to PCDumpRPort
         x  - io_Special flag from the IODRPReq structure
         y  - 0

When the printer device is first opened, Render() is called with ct set to
0, to give the driver a chance to set up the density values before the
actual graphic dump is called.

The parameter passed in x will be the io_Special flag which contains the
density and other SPECIAL flags. The only flags used at this point are the
DENSITY flags, all others should be ignored. Never call PWrite() during
this case.  When you are finished handling this case, return PDERR_NOERR.

Master initialization (Case 0).
-------------------------------
Parameters:

         ct - pointer to a IODRPReq structure
         x  - width (in pixels) of printed picture
         y  - height (in pixels) of printed picture

   Everything is A-OK.
   -------------------
   At this point the printer device has already checked that the values
   are within range for the printer.  This is done by checking values
   listed in printertag.asm.

The x and y value should be used to allocate enough memory for a command
and data buffer for the printer. If the allocation fails,
PDERR_BUFFERMEMORY should be returned. In general, the buffer needs to be
large enough for the commands and data required for one pass of the print
head. These typically take the following form:

       <start gfx cmd> <data> <end gfx cmd>

The <start gfx cmd> should contain any special, one-time initializations
that the printer might require such as:

   *  Carriage Return - some printers start printing graphics without
      returning the printhead. Sending a CR assures that printing will
      start from the left edge.

   *  Unidirectional - some printers which have a bidirectional mode
      produce non-matching vertical lines during a graphics dump, giving a
      wavy result. To prevent this, your driver should set the printer to
      unidirectional mode.

   *  Clear margins - some printers force graphic dumps to be done within
      the text margins, thus they should be cleared.

   *  Other commands - enter the graphics mode, set density, etc.

   Multi-Pass? Don't Forget the Memory.
   ------------------------------------
   In addition to the memory for commands and data, a multi-pass color
   printer must allocate enough buffer space for each of the different
   color passes.

The printer should never be reset during the master initialization case
This will cause problems during multiple dumps. Also, the pointer to the
IODRPReq structure in ct should not be used except for those rare printers
which require it to do the dump themselves. Return the PDERR_TOOKCONTROL
error in that case so that the printer device can exit gracefully.

   PDERR_TOOKCONTROL, An Error in Name Only.
   -----------------------------------------
   The printer device error code, PDERR_TOOKCONTROL, is not an error at
   all, but an internal indicator that the printer driver is doing the
   graphic dump entirely on its own. The printer device can assume the
   dump has been done.  The calling application will not be informed of
   this, but will receive PDERR_NOERR instead.

The example render.c functions listed at the end of this chapter use
double buffering to reduce the dump time which is why the AllocMem() calls
are for BUFSIZE times two, where BUFSIZE represents the amount of memory
for one entire print cycle. However, contrary to the example source code,
allocating the two buffers independently of each other is recommended. A
request for one large block of contiguous memory might be refused.  Two
smaller requests are more likely to be granted.

Putting the pixels in a buffer (Case 1).
----------------------------------------
Parameters:

         ct - pointer to a PrtInfo structure.
         x  - PCM color code (if the printer is PCC_MULTI_PASS).
         y  - printer row # (the range is 0 to pixel height - 1).

In this case, you are passed an entire row of YMCB intensity values
(Yellow, Magenta, Cyan, Black).  To handle this case, you call the
Transfer() function in the transfer.c module.  You should return
PDERR_NOERR after handling this case. The PCM-defines for the x parameter
from the file devices/prtgfx.h are PCMYELLOW, PCMMAGENTA, PCMCYAN and
PCMBLACK.

Dumping a pixel buffer to the printer (Case 2).
-----------------------------------------------
Parameters:

         ct - 0
         x  - 0
         y  - # of rows sent (the range is 1 to NumRows).

At this point the data can be Run Length Encoded (RLE) if your printer
supports it. If the printer doesn't support RLE, the data should be
white-space stripped. This involves scanning the buffer from end to
beginning for the position of the first occurrence of a non-zero value.
Only the data from the beginning of the buffer to this position should be
sent to the printer.  This will significantly reduce print times.

The value of y can be used to advance the paper the appropriate number of
pixel lines if your printer supports that feature. This helps prevent
white lines from appearing between graphic dumps.

You can also do post-processing on the buffer at this point. For
example, if your printer uses the hexadecimal number $03 as a command and
requires the sequence $03 $03 to send $03 as data, you would probably want
to scan the buffer and expand any $03s to $03 $03 during this case. Of
course, you'll need to allocate space somewhere in order to expand the
buffer.

The error from PWrite() should be returned after this call.

Clearing and initializing the pixel buffer (Case 3)
---------------------------------------------------
Parameters:

         ct - 0
         x  - 0
         y  - 0

The printer driver does not send blank pixels so you must initialize
the buffer to the value your printer uses for blank pixels (usually 0).
Clearing the buffer should be the same for all printers. Initializing the
buffer is  printer specific, and it includes placing the printer-specific
control codes in the buffer before and after the data.

This call is made before each Case 2 call. Clear your active print buffer
- remember you are double buffering - and initialize it if necessary.
After this call, PDERR_NOERR should be returned.

Closing Down (Case 4).
----------------------
Parameters:

         ct - error code
         x  - io_Special flag from the IODRPReq structure
         y  - 0

This call is made at the end of the graphic dump or if the graphic dump
was cancelled for some reason.  At this point you should free the printer
buffer memory. You can determine if memory was allocated by checking that
the value of PD->pd_PrintBuf is not NULL. If memory was allocated, you
must wait for the print buffers to clear (by calling PBothReady) and then
deallocate the memory. If the printer - usually a page oriented
printer - requires a page eject command, it can be given here. Before you
do, though, you should check the SPECIAL_NOFORMFEED bit in x. Don't issue
the command if it is set.

If the error condition in ct is PDERR_CANCEL, you should not PWrite().
This error indicates that the user is trying to cancel the dump for
whatever reason. Each additional PWrite() will generate another printer
trouble requester. Obviously, this is not desirable.

During this render case PWrite() could be used to:

   *  reset the line spacing.  If the printer doesn't have an advance 'n'
      dots command, then you'll probably advance the paper by changing the
      line spacing. If you do, set it back to either 6 or 8 lpi (depending
      on Preferences) when you are finished printing.

   *  set bidirectional mode if you selected unidirectional mode in render
      Case 0.

   *  set black text; some printers print the text in the last color used,
      even if it was in graphics mode.

   *  restore the margins if you cancelled the margins in render Case 0.

   *  any other command needed to exit the graphics mode, eject the page,
      etc.

Either PDERR_NOERR or the error from PWrite() should be returned after
this call.

Switching to the next color (Case 6)
------------------------------------
This call provides support for printers which require that colors be sent
in separate passes. When this call is made, you should instruct the
printer to advance its color panel. This case is only needed for printers
of the type PCC_MULTI_PASS, such as the CalComp ColorMaster.


10 / Writing A Graphics Printer Driver / Transfer()

Transfer() dithers and renders an entire row of pixels passed to
it by the Render() function. When Transfer() gets called, it is passed 5
parameters:

Parameters:

          PInfo     - a pointer to a PrtInfo structure
          y         - the row number
          ptr       - a pointer to the buffer
          colors    - a pointer to the color buffers
          BufOffset - the buffer offset for interleaved printing.

The dithering process of Transfer() might entail thresholding, grey-scale
dithering, or color-dithering each destination pixel.

If PInfo->pi_threshold is non-zero, then the dither value is:

       PInfo->pi_threshold \^15

If PInfo->pi_threshold is zero, then the dither value is computed
by:

       *(PInfo->pi_dmatrix + ((y & 3) * 2) + (x & 3))

where x is initialized to PInfo->pi_xpos and is incremented for each of
the destination pixels.  Since the printer device uses a 4x4 dither
matrix, you must calculate the dither value exactly as given above.
Otherwise, your driver will be non-standard and the results will be
unpredictable.

The Transfer() function renders by putting a pixel in the print buffer
based on the dither value. If the intensity value for the pixel is greater
than the dither value as computed above, then the pixel should be put in
the print buffer. If it is less than, or equal to the dither value, it
should be skipped to process the next pixel.

Printer         Type of
Color Class     Dithering       Rendering logic
-----------     ---------       ---------------
PCC_BW          Thresholding    Test the black value against the threshold
                                value to see if you should render a black
                                pixel.

                Grey Scale      Test the black value against the dither
                                value to see if you should render a black
                                pixel.

                Color           NA

PCC_YMC         Thresholding    Test the black value against the
                                threshold value to see if you should render
                                a black pixel.  Print yellow, magenta and
                                cyan pixel to make black.

                Grey Scale      Test the black value against the dither
                                value to see if you should render a black
                                pixel. Print yellow, magenta and cyan pixel
                                to make black.

                Color           Test the yellow value against the dither
                                value to see if you should render a yellow
                                pixel. Repeat this process for magenta and
                                cyan.

PCC_YMCB        Thresholding    Test the black value against the threshold
                                value to see if you should render a black
                                pixel.

                Grey Scale      Test the black value against the dither
                                value to see if you should render a black
                                pixel.

                Color           Test the black value against the dither
                                value to see if you should render a black
                                pixel. If black is not rendered, then
                                test the yellow value against the dither
                                value to see if you should render a yellow
                                pixel.  Repeat this process for magenta and
                                cyan. (See the EpsonX_transfer.c file)

PCC_YMC_BW      Thresholding    Test the black value against the threshold
                                value to see if you should render a black
                                pixel.

                Grey Scale      Test the black value against the dither
                                value to see if you should render a black
                                pixel.

                Color           Test the yellow value against the dither
                                value to see if you should render a yellow
                                pixel. Repeat this process for magenta and
                                cyan.

In general, if black is rendered for a specific printer dot, then the YMC
values should be ignored, since the combination of YMC is black. It is
recommended that the printer buffer be constructed so that the order of
colors printed is yellow, magenta, cyan and black, to prevent smudging and
minimize color contamination on ribbon color printers.

The example transfer.c files are provided in C for demonstration only.
Writing this module in assembler can cut the time needed for a graphic
dump in half. The EpsonX transfer.asm file is an example of this.


10 / Writing A Graphics Printer Driver / SetDensity()

SetDensity() is a short function which implements multiple densities. It
is called in the Pre-master initialization case of the Render() function.
It is passed the density code in density_code. This is used to select the
desired density or, if the user asked for a higher density than is
supported, the maximum density available.  SetDensity() should also handle
narrow and wide tractor paper sizes.

Densities below 80 dpi should not be supported in SetDensity(), so that a
minimum of 640 dots across for a standard 8.5x11-inch paper is guaranteed.
This results in a 1:1 correspondence of dots on the printer to dots on the
screen in standard screen sizes. The HP LaserJet is an exception to this
rule. Its minimum density is 75 dpi because the original HP LaserJet had
too little memory to output a full page at a higher density.


10 / Writing A Graphics Printer Driver / Printertag.asm

For a graphic printer the printer-specific values that need to be filled
in in printertag.asm are as follows:

MaxXDots
   The maximum number of dots the printer can print across the page.

MaxYDots
   The maximum number of dots the printer can print down the page.
   Generally, if the printer supports roll or form feed paper, this
   value should be 0 indicating that there is no limit. If the printer
   has a definite y dots maximum (as a laser printer does), this number
   should be entered here.

XDotsInch
   The dot density in x (supplied by SetDensity(), if it exists).

YDotsInch
   The dot density in y (supplied by SetDensity(), if it exists).

PrinterClass
   The printer class of the printer.

      PPC_BWALPHA     black&white alphanumeric, no graphics.
      PPC_BWGFX       black&white (only) graphics.
      PPC_COLORALPHA  color alphanumeric, no graphics.
      PPC_COLORGFX    color (and maybe black&white) graphics.

ColorClass
   The color class the printer falls into.

      PCC_BW         Black&White only
      PCC_YMC        Yellow Magenta Cyan only.
      PCC_YMC_BW     Yellow Magenta Cyan or Black&White, but not both
      PCC_YMCB       Yellow Magenta Cyan Black
      PCC_WB         White&Black only, 0 is BLACK
      PCC_BGR        Blue Green Red
      PCC_BGR_WB     Blue Green Red or Black&White
      PCC_BGRW       Blue Green Red White

NumRows
   The number of pixel rows printed by one pass of the print head. This
   number is used by the non-printer-specific code to determine when to
   make a render Case 2 call to you. You have to keep this number in
   mind when determining how big a buffer you'll need to store one print
   cycle's worth of data.


10 / Creating a Printer Driver / Testing The Printer Driver

A printer driver should be thoroughly tested before it is released. Though
labor intensive, the alphanumeric part of a driver can be easily tested.
The graphics part is more difficult.  Following are some recommendations
on how to test this part.

Start with a black and white (threshold 8), grey scale and color dump of
the same picture. The color dump should be in color, of course. The grey
scale dump should be like the color dump, except it will consist of
patterns of black dots. The black and white dump will have solid black and
solid white areas.

Next, do a dump with the DestX and DestY dots set to an even multiple of
the XDotsInch and YDotsInch for the printer. For example, if the printer
has a resolution of 120 x 144 dpi, a 480 x 432 dump could be done. This
should produce a printed picture which covers 4 x 3 inches on paper. If
the width of the picture is off, then the wrong value for XDotsInch has
been put in printertag.asm. If the height of the picture is off, the wrong
value for YDotsInch is in printertag.asm.

Do a color dump as wide as the printer can handle with the density set to
7.

Make sure that the printer doesn't force graphic dumps to be done within
the text margins. This can easily be tested by setting the text margins to
30 and 50, the pitch to 10 cpi and then doing a graphic dump wider than 2
inches. The dump should be left justified and as wide as you instructed.
If the dump starts at character position 30 and is cut off at position 50,
the driver will have to be changed. These changes involve clearing the
margins before the dump (Case 0) and restoring the margins after the dump
(Case 4). An example of this is present in render.c source example listed
at the end of this chapter.

   The Invisible Setup.
   --------------------
   Before the graphic dump, some text must be sent to the printer to
   have the printer device initialize the printer. The "text" sent
   does not have to contain any printable characters (i.e., you can send
   a carriage return or other control characters).

As a final test, construct an image with a white background that has
objects in it surrounded by white space. Dump this as black and white,
grey scale and color. This will test the white-space stripping or RLE, and
the ability of the driver to handle null lines. The white data areas
should be separated by at least as many lines of white space as the
NumRows value in the printertag.asm file.


10 Printer Device / Example Printer Driver Source Code

As an aid in writing printer drivers, source code for two different
classes of printers is supplied. Both drivers have been successfully
generated with Lattice C 5.10 and Lattice Assembler 5.10. The example
drivers are:

   EpsonX       A YMCB, 8 pin, multi-density interleaved printer.
   HP_Laserjet  A black&white, multi-density, page-oriented printer.

All printer drivers use the following include file macros.i for init.asm.

     macros.i

 EpsonX
 HP_Laserjet


10 / Example Printer Driver Source Code / EpsonX

For the EpsonX driver, both the assembly and C version of Transfer() are
supplied. In the Makefile the (faster) assembly version is used to
generate the driver.  The EpsonX driver can be generated with the
included Makefile.

     Makefile            init.asm         transfer.asm
     macros.i            data.c           transfer.c
     printertag.asm      dospecial.c      density.c
     rev.i               render.c


10 / Example Printer Driver Source Code / HP_Laserjet

The driver for the HP_LaserJet can be generated with the following
Makefile.

     Makefile            init.asm         transfer.asm
     macros.i            data.c           transfer.c
     printertag.asm      dospecial.c      density.c
     hp_rev.i            render.c


10 Printer Device / Additional Information on the Printer Device

Additional programming information on the printer device can be found in
the include files and the Autodocs for the printer device.   Both are
contained in the Amiga ROM Kernel Reference Manual: Includes and Autodocs.

                       Printer Device Information
                    ---------------------------------
                    INCLUDES        devices/printer.h
                                    devices/printer.i
                                    devices/prtbase.h
                                    devices/prtbase.i
                                    devices/prtgfx.h
                                    devices/prtgfx.i

                    AUTODOCS        printer.doc

Additional printer drivers can be found on Fred Fish Disk #344 under
RKMCompanion.


Amiga® RKM Devices: 3 Clipboard Device

The clipboard device allows the exchange of data dynamically between one
application and another. It is responsible for caching data that has been
"cut" and providing data to "paste" in an application. A special
"post" mode allows an application to inform the clipboard device that
the application has data available. The clipboard device will request this
data only if the data is actually needed. The clipboard will cache the
data in RAM and will automatically spool the data to disk if necessary.

The clipboard device is implemented as an Exec-style device, and supports
random access reads and writes on data within the clipboard. All data in
the clipboard must be in IFF format.  A new library, IFFParse Library, has
been added to the Amiga libraries.  The routines in iffparse.library can
and should be used for reading and writing data to the clipboard.  This
chapter contains a brief discussion of IFF as it relates to the clipboard
(for more details see Appendix A).

               NEW CLIPBOARD FEATURES FOR VERSION 2.0

                   Feature                 Description
               --------------             --------------
               CBD_CHANGEHOOK             Device Command

   Compatibility Warning:
   ----------------------
   The new features for the 2.0 clipboard device are not backwards
   compatible.

 Clipboard Device Commands and Functions
 Device Interface
 Monitoring Clipboard Changes
 Example Clipboard Programs
 Support Functions Called from Example Programs
 Include File for the Example Programs
 Additional Information on the Clipboard Device


3 Clipboard Device / Clipboard Device Commands and Functions

Command             Command Operation
-------             -----------------
CBD_CHANGEHOOK      Specify a hook to be called when the data on the
                    clipboard has changed (V36).

CBD_CURRENTREADID   Return the Clip ID of the current clip to read.  This
                    is used to determine if a clip posting is still the
                    latest cut.

CBD_CURRENTWRITEID  Return the Clip ID of the latest clip written.  This
                    is used to determine if the clip posting data is
                    obsolete.

CBD_POST            Post the availability of clip data.

CMD_READ            Read data from the clipboard for a paste.  Data can be
                    read from anywhere in the clipboard by specifying an
                    offset >0 in the I/O request.

CMD_UPDATE          Indicate that the data provided with a write command
                    is complete and available for subsequent read/pastes.

CMD_WRITE           Write data to the clipboard as a cut.

Exec Functions as Used in This Chapter
--------------------------------------
CloseDevice()       Relinquish use of the clipboard device.  All requests
                    must be complete before closing.

DoIO()              Initiate a command and wait for completion
                    (synchronous request).

GetMsg()            Get next message from a message port.

OpenDevice()        Obtain use of the clipboard device.

SendIO()            Initiate a command and return immediately
                    (asynchronous request).

Exec Support Functions as Used in This Chapter
----------------------------------------------
CreateExtIO()       Create an I/O request structure of type IOClipReq.
                    This structure will be used to communicate commands to
                    the clipboard device.

CreatePort()        Create a signal message port for reply messages from
                    the clipboard device.  Exec will signal a task when a
                    message arrives at the port.

DeleteExtIO()       Delete an I/O request structure created by
                    CreateExtIO().

DeletePort()        Delete the message port created by CreatePort().


3 Clipboard Device / Device Interface

The clipboard device operates like the other Amiga devices.  To use it,
you must first open the clipboard device, then send I/O requests to it,
and then close it when finished. See "Introduction to Amiga System Devices"
chapter for general information on device usage.

  struct IOClipReq
  {
      struct  Message io_Message;
      struct  Device  *io_Device;     /* device node pointer  */
      struct  Unit    *io_Unit;       /* unit (driver private)*/
      UWORD   io_Command;             /* device command */
      UBYTE   io_Flags;               /* including QUICK and SATISFY */
      BYTE    io_Error;               /* error or warning num */
      ULONG   io_Actual;              /* number of bytes transferred */
      ULONG   io_Length;              /* number of bytes requested */
      STRPTR  io_Data;                /* either clip stream or post port */
      ULONG   io_Offset;              /* offset in clip stream */
      LONG    io_ClipID;              /* ordinal clip identifier */
  };

See the include file devices/clipboard.h for the complete
structure definition.

The clipboard device I/O request, IOClipReq, looks like a standard
IORequest structure except for the addition of the io_ClipID field, which
is used by the device to identify clips. It must be set to zero by the
application for a post or an initial write or read, but preserved for
subsequent writes or reads, as the clipboard device uses this field
internally for bookkeeping purposes.

 Opening The Clipboard Device        Updating The Clipboard Device
 Clipboard Data 		     Clipboard Messages
 Multiple Clips 		     Reading From The Clipboard Device
 Writing To The Clipboard Device     Closing The Clipboard Device


3 / Device Interface / Opening The Clipboard Device

Three primary steps are required to open the clipboard device:

    *  Create a message port using CreatePort(). Reply messages from the
       device must be directed to a message port.

    *  Create an extended I/O request structure of type IOClipReq using
       CreateExtIO().

    *  Open the clipboard device. Call OpenDevice(), passing the IOClipReq.

    struct MsgPort  *ClipMP;          /* pointer to message port*/
    struct IOClipReq *ClipIO;         /* pointer to IORequest */

    if (ClipMP=CreatePort(0L,0L) )
        {
        if (ClipIO=(struct IOClipReq *)
                    CreateExtIO(ClipMP,sizeof(struct IOClipReq)))
            {
            if (OpenDevice("clipboard.device",0L,ClipIO,0))
                printf("clipboard.device did not open\n");
            else
                {
                 ... do device processing
                }
            {
        else
            printf("Error: Could not create IORequest\n");
        }
    else
        printf("Error: Could not create message port\n");


3 / Device Interface / Clipboard Data

Data on the clipboard resides in one of three places. When an application
posts a cut, the data resides in the private memory space of that
application. When an application writes to the clipboard, either of its
own volition or in response to a message from the clipboard requesting
that it satisfy a post, the data is copied to the clipboard which is
either memory or a special disk file. When the clipboard is not open, the
data resides in the special disk file located in the directory specified
by the CLIPS: logical AmigaDOS assign.

Data on the clipboard is self-identifying. It must be a correct IFF
(Interchange File Format) file; the rest of this section refers to IFF
concepts. See the Appendix A in this manual for a complete description of
IFF. If the top-level chunk is of type CAT with an identifier of CLIP,
that indicates that the contained chunks are different representations of
the same data, in decreasing order of preference on the part of the
producer of the clip. Any other data is as defined elsewhere (probably a
single representation of the cut data produced by an application).

The IFFParse.Library also contains functions which simplify reading and
writing of IFF data to the clipboard device.  See the "IFFParse Library"
chapter of the Amiga ROM Kernel Reference Manual: Libraries for more
information.

A clipboard tool, which is an application that allows a Workbench user to
view a clip, should understand the text (FTXT) and graphics (ILBM) form
types. Applications using the clipboard to export data should include at
least one of these types in a CAT CLIP so that their data can be
represented on the clipboard in some form for user feedback.

You should not, in any way, rely on the specifics of how files in CLIPS:
are handled or named.  The only proper way to read or write clipboard data
is via the clipboard device.

   Play Nice!
   ----------
   Keep in mind that while your task is reading from or writing to a
   clipboard unit, other tasks cannot.  Therefore, it is important to be
   fast.  If possible, make a copy of the clipboard data in RAM instead
   of processing it while the read or write is in progress.


3 / Device Interface / Multiple Clips

The clipboard supports multiple clips, i.e., the clipboard device can
contain more than one distinct piece of data.  This is not to be confused
with the IFF CAT CLIP, which allows for different representation of the
same data.

The multiple clips are implemented as different units in the clipboard
device.  The unit is specified at OpenDevice() time.

    struct IOClipReq *ClipIO;
    LONG unit;

    OpenDevice("clipboard.device", unit, ClipIO, 0);

By default, applications should use clipboard unit 0. However, it is
recommended that each application provide a mechanism for selecting the
unit number which will be used when the clipboard is opened. This will
allow the user to create a convention for storing different types of data
in the clipboard. Applications should never write to clipboard unit 0
unless the user requests it (e.g., selecting COPY or CUT within an
application).

Clipboard units 1-255 can be used by the more advanced user for:

   *  Sharing data between applications within an ARexx Script.

   *  Customizing applications to store different kinds of data in
      different clipboard units.

   *  Customizing an application to use multiple cut/copy/paste buffers.

   *  Specialized utilities which might display and/or automatically modify
      the contents of a clipboard unit.

All applications which provide CUT, COPY and PASTE capabilities, should,
at a minimum, provide support for clipboard unit 0.


3 / Device Interface / Writing To The Clipboard Device

You write to the clipboard device by passing an IOClipReq to the device
with CMD_WRITE set in io_Command, the number of bytes to be written set in
io_Length and the address of the write buffer set in io_Data.

    ClipIO->io_Data = (char *) data;
    ClipIO->io_Length = 4L;
    ClipIO->io_Command = CMD_WRITE;

An initial write should set io_Offset to zero.  Each time a write is done,
the device will increment io_Offset by the length of the write.

As previously stated, the data you write to the clipboard must be in IFF
format.  This requires a certain amount of preparation prior to actually
writing the data if it is not already in IFF format.  A brief explanation
of the IFF format will be helpful in this regard.

For our purposes, we will limit our discussion to a simple formatted text
(FTXT) IFF file.  An FTXT file looks like:

           FORM <length of succeeding bytes>
           FTXT
           CHRS <length of succeeding bytes>
                <data bytes>
                <pad byte of zero if the preceding chunk has odd length>

           Note: Uppercase characters above are literals.

Based on the above file format, a hex dump of an IFF FTXT file containing
 the string "Enterprise" would look like:

           0000   464F524D  FORM
           0004   00000016  (length of FTXT, CHRS, 0xA and data)
           0008   46545854  FTXT
           000C   43485253  CHRS
           0010   0000000A  (length of Enterprise)
           0014   456E7465  Ente
           0018   72707269  rpri
           001C   7365      se

A code fragment for doing this:

    LONG slen = strlen ("Enterprise");
    BOOL odd = (slen & 1);      /* pad byte flag */

    /* set length depending on whether string is odd or even length */
    LONG length = (odd) ? slen + 1 : slen;

    /* Reset the clip id */
    ClipIO->io_ClipID = 0;
    ClipIO->io_Offset = 0;

    error = writeLong ((LONG *) "FORM");/* "FORM" */

    /* add 12 bytes for FTXT,CHRS & length byte to string length */
    length += 12;
    error = writeLong (&length);
    error = writeLong ((LONG *) "FTXT");/* "FTXT" for example */
    error = writeLong ((LONG *) "CHRS");/* "CHRS" for example */
    error = writeLong (&slen);      /* #  (length of string) */

    ClipIO->io_Command = CMD_WRITE;
    ClipIO->io_Data = (char *) string;
    ClipIO->io_Length = slen;               /* length of string */
    error = (LONG) DoIO (clipIO);   /* text string */

    LONG writeLong (LONG * ldata)
    {
        ClipIO->io_Command = CMD_WRITE;
        ClipIO->io_Data = (char *) ldata;
        ClipIO->io_Length = 4L;
        return ( (LONG) DoIO (clipIO) );
    }

The fragment above does no error checking because it's a fragment.  You
should always error check.  See the example programs at the end of this
chapter for the proper method of error checking.

   Iffparse That Data!
   -------------------
   Keep in mind that the functions in the iffparse.library can be used
   to write data to the clipboard. See the "IFFParse Library" chapter
   of the Amiga ROM Kernel Reference Manual: Libraries for more
   information.


3 / Device Interface / Updating The Clipboard Device

When the final write is done, an update command must be sent to the device
to indicate that the writing is complete and the data is available. You
update the clipboard device by passing an IOClipReq to the device with
CMD_UPDATE set in io_Command.

    ClipIO->io_Command = CMD_UPDATE;
    DoIO(ClipIO);


3 / Device Interface / Clipboard Messages

When an application performs a post, it must specify a message port for
the clipboard to send a message to if it needs the application to satisfy
the post with a write called the SatisfyMsg.

    struct SatisfyMsg
    {
    struct  Message sm_Message; /* the length will be 6 */
    UWORD   sm_Unit;            /* 0 for the primary clip unit */
    LONG    sm_ClipID;          /* the clip identifier of the post */
    }

This structure is defined in the include file devices/clipboard.h.

If the application wishes to determine if a post it has recently performed
is still the current clip, it should compare the io_ClipID found in the
post request upon return with that returned by the CBD_CURRENTREADID
command.

If an application has a pending post and wishes to determine if it should
satisfy it (for example, before it exits), it should compare the io_ClipID
of the post I/O request with that of the CBD_CURRENTWRITEID command. If
the application receives a satisfy message from the clipboard device
(format described below), it must immediately perform the write with the
io_ClipID of the post. The satisfy message from the clipboard may be
removed from the application message port by the clipboard device at any
time (because it is re-used by the clipboard device). It is not dangerous
to spuriously satisfy a post, however, because it is identified by the
io_ClipID.

The cut data is provided to the clipboard device via either a write or a
post of the cut data. The write command accepts the data immediately and
copies it onto the clipboard. The post command allows an application to
inform the clipboard of a cut, but defers the write until the data is
actually required for a paste.

In the preceding discussion, references to the read and write commands of
the clipboard device actually refer to a sequence of read or write
commands, where the clip data is acquired and provided in pieces instead
of all at once.

The clipboard has an end-of-clip concept that is analogous to end-of-file
for both read and write. The read end-of-file must be triggered by the
user of the clipboard in order for the clipboard to move on to service
another application's requests, and consists of reading data past the end
of file. The write end-of-file is indicated by use of the update command,
which indicates to the clipboard that the previous write commands are
completed.


3 / Device Interface / Reading From The Clipboard Device

You read from the clipboard device by passing an IOClipReq to the device
with CMD_READ set in io_Command, the number of bytes to be read set in
io_Length and the address of the read buffer set in io_Data.

    ClipIO->io_Command = CMD_READ;
    ClipIO->io_Data = (char *) read_data;
    ClipIO->io_Length = 20L;

io_Offset must be set to zero for the first read of a paste sequence.  An
io_Actual that is less than the io_Length indicates that all the data has
been read.  After all the data has been read, a subsequent read must be
performed (one whose io_Actual returns zero) to indicate to the clipboard
device that all the data has been read. This allows random access of the
clip while reading. Providing only valid reads are performed, your program
can seek/read anywhere within the clip by setting the io_Offset field of
the I/O request appropriately.

   Tell The Clipboard You Are Finished Reading.
   --------------------------------------------
   Your application must perform an extra read (one whose io_Actual
   returns zero) to indicate to the clipboard device that all data has
   been read, if io_Actual is not already zero.

The data you read from the clipboard will be in IFF format.  Conversion
from IFF may be necessary depending on your application.

   Iffparse That Data!
   -------------------
   Keep in mind that the functions in the iffparse.library can be used
   to read data from the clipboard. See the "IFFParse Library"
   chapter of the Amiga ROM Kernel Reference Manual: Libraries for more
   information.


3 / Device Interface / Closing The Clipboard Device

Each OpenDevice() must eventually be matched by a call to
CloseDevice().

    CloseDevice(ClipIO);

When the last task closes a clipboard unit with CloseDevice(), the
contents of the unit may be copied to a disk file in CLIPS: so that the
clipboard device can be expunged.


3 Clipboard Device / Monitoring Clipboard Changes

Some applications require notification of changes to data on the
clipboard. Typically, these applications will need to do some processing
when this occurs. You can set up such an environment through the
CBD_CHANGEHOOK command. CBD_CHANGEHOOK allows you to specify a hook to be
called when the data on the clipboard changes.

For example, a show clipboard utility would need to know when the data on
the clipboard is changed so that it can display the new data.  The hook it
would specify would read the new clipboard data and display it for the
user.

You specify a hook for the clipboard device by initializing a Hook
structure and then passing an IOClipReq to the device with CBD_CHANGEHOOK
set in io_Command, 1 set in io_Length, and the address of the Hook
structure set in io_Data.

    ULONG HookEntry ();            /* Declare the hook assembly function */
    struct IOClipReq *ClipIO;      /* Declare the IOClipReq */
    struct Hook *ClipHook;         /* Declare the Hook */

    /* Prepare the hook */
    ClipHook->h_Entry = HookEntry; /* C intrfce in asmbly rout. HookEntry*/
    ClipHook->h_SubEntry = HookFunc;/* Call function when Hook activated */
    ClipHook->h_Data = FindTask(NULL);/* Set pointer to current task */

    ClipIO->io_Data = (char *) ClipHook;/* Point to hook struct */
    ClipIO->io_Length = 1;              /* Add hook to clipboard */
    ClipIO->io_Command = CBD_CHANGEHOOK;
    DoIO(clipIO);

The above code fragment assumes that an assembly language routine
HookEntry() has been coded:

    ; entry interface for C code
    _HookEntry:
            move.l  a1,-(sp)            ; push message packet pointer
            move.l  a2,-(sp)            ; push object pointer
            move.l  a0,-(sp)            ; push hook pointer
            move.l  h_SubEntry(a0),a0   ; fetch C entry point ...
            jsr     (a0)                ; ... and call it
            lea     12(sp),sp           ; fix stack
            rts

It also assumes that the function HookFunc() has been coded.  One of the
example programs at the end of this chapter has hook processing in it.
See the include file utility/hooks.h and The Amiga ROM Kernel Reference
Manual: Libraries for further information on hooks.

You remove a hook by passing an IOClipReq to the device with the address
of the Hook structure set in io_Data, 0 set in io_Length and
CBD_CHANGEHOOK set in io_Command.

    ClipIO->io_Data = (char *) ClipHook;  /* point to hook struct */
    ClipIO->io_Length = 0;                /* Remove hook from clipboard */
    ClipIO->io_Command = CBD_CHANGEHOOK;
    (DoIO (clipIO))

You must remove the hook or it will continue indefinitely.

 Caveats For CBD_CHANGEHOOK


3 / Monitoring Clipboard Changes / Caveats For CBD_CHANGEHOOK

   *  CBD_CHANGEHOOK should only be used by a special application, such as
      a clipboard viewing program.  Most applications can check the
      contents of the clipboard when, and if, the user requests a paste.

   *  Do not add system overhead by blindly reading and parsing the
      clipboard everytime a user copies data to it.  If all applications
      did this, the system could become intolerably slow whenever an
      application wrote to the clipboard.  Only read and parse when it is
      necessary.


3 Clipboard Device / Additional Information on the Clipboard Device

Additional programming information on the clipboard device can be found in
the include files for the clipboard device, iffparse library and utility
library, and the Autodocs for all three. They are contained in the
Amiga ROM Kernel Reference Manual: Includes and Autodocs.

                     Clipboard Device Information
                   -----------------------------------
                   INCLUDES       devices/clipboard.h
                                  devices/clipboard.i
                                  libraries/iffparse.h
                                  libraries/iffparse.i
                                  utility/hooks.h
                                  utility/hooks.i

                   AUTODOCS       clipboard.doc
                                  iffparse.doc
                                  utility.doc


Amiga® RKM Devices: 11 SCSI Device

The Small Computer System Interface (SCSI) hardware of the A3000 and
A2091/A590 is controlled by the SCSI device.  The SCSI device allows
an application to send Exec I/O commands and SCSI commands to
a SCSI peripheral.  Common SCSI peripherals include hard drives, streaming
tape units and CD-ROM drives.

 SCSI Device Commands and Functions
 Device Interface
 SCSI-Direct
 RigidDiskBlock - Fields and Implementation
 Amiga BootStrap
 SCSI-Direct Example
 Additional Information on the SCSI Device


11 SCSI Device / SCSI Device Commands and Functions

SCSI Device Command  Operation
-------------------  ---------
HD_SCSICMD           Issue a SCSI-direct command to a SCSI unit.

Trackdisk Device Commands Supported by the SCSI Device
------------------------------------------------------
TD_CHANGESTATE       Return the disk present/not-present status of a drive.
TD_FORMAT            Initialize one or more tracks with a data buffer.
TD_PROTSTATUS        Return the write-protect status of a disk.
TD_SEEK              Move the head to a specific track.

Exec Commands Supported by SCSI Device
--------------------------------------
CMD_READ             Read one or more sectors from a disk.
CMD_START            Restart a SCSI unit that was previously stopped with
                     CMD_STOP.
CMD_STOP             Stop a SCSI unit.
CMD_WRITE            Write one or more sectors to a disk.

Exec Functions as Used in This Chapter
--------------------------------------
AbortIO()            Abort an I/O request to the SCSI device.
AllocMem()           Allocate a block of memory.
AllocSignal()        Allocate a signal bit.
CheckIO()            Return the status of an I/O request.
CloseDevice()        Relinquish use of the SCSI device. All requests must
                     be complete before closing.

DoIO()               Initiate a command and wait for completion
                     (synchronous request).

FreeMem()            Free a block of previously allocated memory.
FreeSignal()         Free a previously allocated signal.
OpenDevice()         Obtain use of the SCSI device.  You specify the type
                     of unit and its characteristics in the call to
                     OpenDevice().

WaitIO()             Wait for completion of an I/O request and remove it
                     from the reply port.

Exec Support Functions as Used in This Chapter
----------------------------------------------
CreateExtIO()        Create an extended IORequest structure for use in
                     communicating with the SCSI device.

CreatePort()         Create a message port for reply messages from the
                     SCSI device.  Exec will signal a task when a message
                     arrives at the port.

DeleteExtIO()        Delete the extended IORequest structure created by
                     CreateExtIO().

DeletePort()         Delete the message port created by CreatePort().


11 SCSI Device / Device Interface

The SCSI device operates like other Amiga devices.  To use it, you must
first open the SCSI device, then send I/O requests to it, and then close
it when finished.  See the "Introduction to Amiga System Devices"
chapter for general information on device usage.

The power of the SCSI device comes from its special facility for passing
SCSI and SCSI-2 command blocks to any SCSI unit on the bus.  This facility
is commonly called SCSI-direct and it allows the Amiga to perform SCSI
functions that are "non-standard" in terms of the normal Amiga I/O model.

To send SCSI-direct or other commands to the SCSI device, an extended I/O
request structure named IOStdReq is used.

   struct IOStdReq
   {
       struct  Message io_Message;
       struct  Device  *io_Device;/* device node pointer  */
       struct  Unit    *io_Unit;  /* unit (driver private)*/
       UWORD   io_Command;        /* device command */
       UBYTE   io_Flags;
       BYTE    io_Error;          /* error or warning num */
       ULONG   io_Actual;         /* actual number of bytes transferred */
       ULONG   io_Length;         /* requested number bytes transferred*/
       APTR    io_Data;           /* points to data area */
       ULONG   io_Offset;         /* offset for block structured devices */
   };

See the include file exec/io.h for the complete structure definition.

 Opening The SCSI Device
 Closing The SCSI Device


11 / Device Interface / Opening The SCSI Device

Three primary steps are required to open the SCSI device:

   *  Create a message port using CreatePort(). Reply messages from the
      device must be directed to a message port.

   *  Create an I/O request structure of type IOStdReq. The IOStdReq
      structure is created by the CreateExtIO() function. CreateExtIO will
      initialize your IOStdReq to point to your reply port.

   *  Open the SCSI device.  Call OpenDevice() passing it the I/O request
      and the SCSI unit encoded in the unit field.

SCSI unit encoding consists of three decimal digits which refer
to the SCSI Target ID (bus address) in the 1s digit, the SCSI logical unit
(LUN) in the 10s digit, and the controller board in the 100s digit.  For
example:

   SCSI unit    Meaning
   ---------    -------
   6            drive at address 6
   12           LUN 1 on multiple drive controller at address 2
   104          second controller board, address 4
   88           not valid: both logical units and addresses range from 0-7

The Commodore 2090/2090A unit numbers are encoded differently.  The SCSI
logical unit (LUN) is in the 100s digit, and the SCSI Target ID is a
permuted 1s digit: Target ID 0-6 maps to unit 3-9 (7 is reserved for the
controller).

   2090/A unit  Meaning
   ----------   -------
   3            drive at address 0
   109          drive at address 6, logical unit 1
   1            not valid: this is not a SCSI unit.Perhaps it's an ST506
                unit.

Some controller boards generate a unique name for the second controller
board, instead of implementing the 100s digit (e.g., the 2090A's
iddisk.device).

    struct MsgPort *SCSIMP;      /* Message port pointer */
    struct IOStdReq *SCSIIO;     /* IORequest pointer */

        /* Create message port */
    if (!(SCSIMP = CreatePort(NULL,NULL)))
        cleanexit("Can't create message port\n",RETURN_FAIL);

        /* Create IORequest */
    if (!(SCSIIO = CreateExtIO(SCSIMP,sizeof(struct IOStdReq))))
        cleanexit("Can't create IORequest\n",RETURN_FAIL);

        /* Open the SCSI device */
    if (error = OpenDevice("scsi.device",6L,SCSIIO,0L))
        cleanexit("Can't open scsi.device\n",RETURN_FAIL);

In the code above, the SCSI unit at address 6 of logical unit 0 of board 0
is opened.


11 / Device Interface / Closing The SCSI Device

Each OpenDevice() must eventually be matched by a call to CloseDevice().
All I/O requests must be complete before calling CloseDevice().  If any
requests are still pending, abort them with AbortIO().

    if (!(CheckIO(SCSIIO)))
        {
        AbortIO(SCSIIO);   /* Ask device to abort any pending requests */
        WaitIO(SCSIIO);    /* Wait for abort, then clean up */
        }
    CloseDevice(SCSIIO);   /* Close SCSI device */


11 SCSI Device / SCSI-Direct

SCSI-direct is the facility of the Amiga's SCSI device interface that
allows low-level SCSI commands to be passed directly to a SCSI unit on the
bus. This makes it possible to support the special features of tape
drives, hard disks and other SCSI equipment that do not fit into the
Amiga's normal I/O model. For example, with SCSI-direct, special commands
can be sent to hard drives to modify various drive parameters that are
normally inaccessible or which differ from drive to drive.

In order to use SCSI-direct, you must first open the SCSI device for the
unit you want to use in the manner described above.  You then send an
HD_SCSICMD I/O request with a pointer to a SCSI command data structure.

The SCSI device uses a special data structure for SCSI-direct
commands named SCSICmd.

   struct SCSICmd
   {
    UWORD *scsi_Data;      /* word aligned data for SCSI Data Phase */
                           /* (optional) data need not be byte aligned */
                           /* (optional) data need not be bus accessible */
    ULONG  scsi_Length;    /* even length of Data area */
                           /* (optional) data can have odd length */
                           /* (optional) data length can be > 2**24 */
    ULONG  scsi_Actual;    /* actual Data used */
    UBYTE *scsi_Command;   /* SCSI Command (same options as scsi_Data) */
    UWORD  scsi_CmdLength; /* length of Command */
    UWORD  scsi_CmdActual; /* actual Command used */
    UBYTE  scsi_Flags;     /* includes intended data direction */
    UBYTE  scsi_Status;    /* SCSI status of command */
    UBYTE *scsi_SenseData; /* sense data: filled if SCSIF_[OLD]AUTOSENSE */
                           /* is set and scsi_Status has CHECK CONDITION */
                           /* (bit 1) set */
    UWORD  scsi_SenseLength;/* size of scsi_SenseData, also bytes to */
                           /* request w/ SCSIF_AUTOSENSE, must be 4..255 */
    UWORD  scsi_SenseActual;/* amount actually fetched (0 = no sense) */
   };

See the include file devices/scsidisk.h for the complete structure
definition.

SCSICmd will contain the SCSI command and any associated data that you
wish to pass to the SCSI unit.  You set its fields to the values required
by the unit and the command.  When you have opened the SCSI device and set
the SCSICmd to the proper values, you are ready for SCSI-direct.

You send a SCSI-direct command by passing an IOStdReq to the SCSI device
with a pointer to the SCSICmd structure set in io_Data, the size of the
SCSICmd structure set in io_Length and HD_SCSICMD set in io_Command.:

    struct IOStdReq *SCSIreq = NULL;
    struct SCSICmd Cmd;           /* where the actual SCSI command goes */

    SCSIreq->io_Length  = sizeof(struct SCSICmd);
    SCSIreq->io_Data    = (APTR)&Cmd;
    SCSIreq->io_Command = HD_SCSICMD;
    DoIO(SCSIreq);

The SCSICmd structure must be filled in prior to passing it to the SCSI
unit.  How it is filled in depends on the SCSI-direct being passed to the
unit.  Below is an example of setting up a SCSICmd structure for the
MODE_SENSE SCSI-direct command.

   UBYTE *buffer;           /* a data buffer used for mode sense data */
   UBYTE  Sense[20];        /* buffer for request sense data */
   struct SCSICmd Cmd;      /* where the actual SCSI command goes */

   /* the command being sent */

   static UBYTE ModeSense[]={ 0x1a,0,0xff,0,254,0 };

   Cmd.scsi_Data = (UWORD *)buffer;     /* where we put mode sense data */
   Cmd.scsi_Length = 254;               /* how much we will accept      */
   Cmd.scsi_CmdLength = 6;              /* length of the command        */
   Cmd.scsi_Flags = SCSIF_AUTOSENSE |   /* do automatic REQUEST_SENSE   */
                    SCSIF_READ;         /* set expected data direction  */
   Cmd.scsi_SenseData = (UBYTE *)Sense; /* where sense data will go     */
   Cmd.scsi_SenseLength = 18;           /* how much we will accept      */
   Cmd.scsi_SenseActual = 0;            /* how much has been received   */

   Cmd.scsi_Command=(UBYTE *)ModeSense; /* issuing a MODE_SENSE command */

The fields of the SCSICmd are:

scsi_data
   This field points to the data buffer for the SCSI data phase (if any is
   expected).It is generally the job of the driver software to ensure that
   the given buffer is DMA-accessible and to drop to programmed I/O if it
   isn't.  The filing system provides a stop-gap fix for non-conforming
   drivers with the AddressMask parameter in DEVS:mountlist. For absolute
   safety, restrict all direct reads and writes to Chip RAM.

scsi_Length
   This is the expected length of data to be transferred.  If an unknown
   amount of data is to be transferred from target to host, set the
   scsi_Length to be larger than the maximum amount of data expected. Some
   controllers explicitly use scsi_Length as the amount of data to
   transfer. The A2091, A590 and A3000 drivers always do programmed I/O
   for data transfers under 256 bytes or when the DMA chip doesn't support
   the required alignment.

scsi_Actual
   How much data was actually received from or sent to the SCSI unit in
   response to the SCSI-direct command.

scsi_Command
   The SCSI-direct command.

scsi_CmdLength
   The length of the SCSI-direct command in bytes.

scsi_CmdActual
   The actual number of bytes of the SCSI-direct command that were
   transferred to the SCSI unit.

scsi_Flags
   These flags contain the intended data direction for the SCSI command. It
   is not strictly necessary to set the data direction flag since the SCSI
   protocol will inform the driver which direction data transfers will be
   going.  However, some controllers use this information to set up DMA
   before issuing the command .  It can also be used as a sanity check in
   case the data phase goes the wrong way.

   One flag in particular, is worth noting.  SCSIF_AUTOSENSE is used to
   make the driver perform an automatic REQUEST SENSE if the target returns
   CHECK CONDITION for a SCSI command.  The reason for having the driver do
   this is the multitasking nature of the Amiga.If two tasks were accessing
   the same drive and the first received a CHECK CONDITION, the second task
   would destroy the sense information when it sent a command.
   SCSIF_AUTOSENSE prevents the caller from having to make two I/O requests
   and removes this window of vulnerability.

scsi_Status
   The status of the SCSI-direct command. The values returned in this field
   can be found in the SCSI specification.  For example, 2 is
   CHECK_CONDITION.

scsi_SenseActual
   If the SCSIF_AUTOSENSE flag is set, it is important to initialize this
   field to zero before issuing a SCSI command because some drivers don't
   support AUTOSENSE and won't initialize the field.

scsi_SenseData
   This field is used only for SCSIF_AUTOSENSE.  If a REQUEST SENSE command
   is directly sent to the driver, the data will be deposited in the buffer
   pointed to by scsi_Data.

Keep in mind that SCSI-direct is geared toward an initiator role so it
can't be expected to perform target-like operations.  You can only send
commands to a device, not receive them from an initiator.  There is no
provision for SCSI messaging, either.  This is due mainly to the
interactive nature of the extended messages (such as synchronous transfer
requests) which have to be handled by the driver because it knows the
limitations of the controller card and has to be made aware of such
protocol changes.


11 SCSI Device / RigidDiskBlock - Fields and Implementation

The RigidDiskBlock (RDB) standard was borne out of the same development
effort as HD_SCSICMD and as a result has a heavy bias towards SCSI.
However, there is nothing in the RDB specification that makes it unusable
for devices using other bus protocols.  The XT style disks used in the
A590 also support the RDB standard.

The RDB scheme was designed to allow the automatic mounting of all
partitions on a hard drive and subsequent booting from the highest
priority partition even if it has a soft loaded filing system.  Disks can
be removed from one controller and plugged into another (supporting the
RDB scheme) and will carry with it all the necessary information for
mounting and booting with them.

The preferred method of creating RigidDiskBlocks is with the HDToolBox
program supplied by Commodore.  Most controllers include an RDB editor or
utility.

When a driver is initialized, it uses the information contained in the RDB
to mount the required partitions and mark them as bootable if needed.  The
driver is also responsible for loading any filing systems that are
required if they are not already available on the filesystem.resource
list.  File- systems are added to the resource according to DosType and
version number.

The following is a listing of devices/hardblocks.h that describes all the
fields in the RDB specification.

/*--------------------------------------------------------------------
 *
 *      This file describes blocks of data that exist on a hard disk
 *      to describe that disk.  They are not generically accessable to
 *      the user as they do not appear on any DOS drive.  The blocks
 *      are tagged with a unique identifier, checksummed, and linked
 *      together.  The root of these blocks is the RigidDiskBlock.
 *
 *      The RigidDiskBlock must exist on the disk within the first
 *      RDB_LOCATION_LIMIT blocks.  This inhibits the use of the zero
 *      cylinder in an AmigaDOS partition: although it is strictly
 *      possible to store the RigidDiskBlock data in the reserved
 *      area of a partition, this practice is discouraged since the
 *      reserved blocks of a partition are overwritten by "Format",
 *      "Install", "DiskCopy", etc.  The recommended disk layout,
 *      then, is to use the first cylinder(s) to store all the drive
 *      data specified by these blocks: i.e. partition descriptions,
 *      file system load images, drive bad block maps, spare blocks,
 *      etc.
 *
 *      Though only 512 byte blocks are currently supported by the
 *      file system, this proposal tries to be forward-looking by
 *      making the block size explicit, and by using only the first
 *      256 bytes for all blocks but the LoadSeg data.
 *
 *------------------------------------------------------------------*/

/*
 *  NOTE
 *      optional block addresses below contain $ffffffff to indicate
 *      a NULL address, as zero is a valid address
 */
struct RigidDiskBlock {
  ULONG   rdb_ID;            /* 4 character identifier */
  ULONG   rdb_SummedLongs;   /* size of this checksummed structure */
  LONG    rdb_ChkSum;        /* block checksum (longword sum to zero) */
  ULONG   rdb_HostID;        /* SCSI Target ID of host */
  ULONG   rdb_BlockBytes;    /* size of disk blocks */
  ULONG   rdb_Flags;         /* see below for defines */
  /* block list heads */
  ULONG   rdb_BadBlockList;  /* optional bad block list */
  ULONG   rdb_PartitionList; /* optional first partition block */
  ULONG   rdb_FileSysHeaderList; /* optional file system header block */
  ULONG   rdb_DriveInit;     /* optional drive-specific init code */
                             /* DriveInit(lun,rdb,ior): */
                                /* "C" stk & d0/a0/a1 */
  ULONG   rdb_Reserved1[6];  /* set to $ffffffff */
  /* physical drive characteristics */
  ULONG   rdb_Cylinders;     /* number of drive cylinders */
  ULONG   rdb_Sectors;       /* sectors per track */
  ULONG   rdb_Heads;         /* number of drive heads */
  ULONG   rdb_Interleave;    /* interleave */
  ULONG   rdb_Park;          /* landing zone cylinder */
  ULONG   rdb_Reserved2[3];
  ULONG   rdb_WritePreComp;  /* starting cylinder: write precompensation */
  ULONG   rdb_ReducedWrite;  /* starting cylinder: reduced write current */
  ULONG   rdb_StepRate;      /* drive step rate */
  ULONG   rdb_Reserved3[5];
  /* logical drive characteristics */
  ULONG   rdb_RDBBlocksLo;   /* low block of range reserved for
                                /* hardblocks */
  ULONG   rdb_RDBBlocksHi;   /* high block of range for these hardblocks */
  ULONG   rdb_LoCylinder;    /* low cylinder of partitionable disk area */
  ULONG   rdb_HiCylinder;    /* high cylinder of partitionable data area */
  ULONG   rdb_CylBlocks;     /* number of blocks available per cylinder */
  ULONG   rdb_AutoParkSeconds; /* zero for no auto park */
  ULONG   rdb_HighRDSKBlock; /* highest block used by RDSK */
                             /* (not including replacement bad blocks) */
  ULONG   rdb_Reserved4;
  /* drive identification */
  char    rdb_DiskVendor[8];
  char    rdb_DiskProduct[16];
  char    rdb_DiskRevision[4];
  char    rdb_ControllerVendor[8];
  char    rdb_ControllerProduct[16];
  char    rdb_ControllerRevision[4];
  ULONG   rdb_Reserved5[10];
};

#define IDNAME_RIGIDDISK        0x5244534B      /* 'RDSK' */

#define RDB_LOCATION_LIMIT      16

#define RDBFB_LAST      0      /* no disks exist to be configured after */
#define RDBFF_LAST      0x01L  /*   this one on this controller */
#define RDBFB_LASTLUN   1      /* no LUNs exist to be configured */
#define RDBFF_LASTLUN   0x02L  /*   greater than this one at this SCSI */
                               /*   Target ID */
#define RDBFB_LASTTID   2      /* no Target IDs exist to be configured */
#define RDBFF_LASTTID   0x04L  /*   greater than this one on this */
                               /*   SCSI bus */
#define RDBFB_NORESELECT 3     /* don't bother trying to perform */
                               /*   reselection when talking */
#define RDBFF_NORESELECT 0x08L /*   to this drive */
#define RDBFB_DISKID    4      /* rdb_Disk... identification valid */
#define RDBFF_DISKID    0x10L
#define RDBFB_CTRLRID   5      /* rdb_Controller...identification valid */
#define RDBFF_CTRLRID   0x20L
                               /* added 7/20/89 by commodore: */
#define RDBFB_SYNCH     6      /* drive supports scsi synchronous mode */
#define RDBFF_SYNCH     0x40L  /* DANGEROUS TO USE IF IT DOESN'T! */

/*------------------------------------------------------------------*/
struct BadBlockEntry {
    ULONG   bbe_BadBlock;      /* block number of bad block */
    ULONG   bbe_GoodBlock;     /* block number of replacement block */
};

struct BadBlockBlock {
    ULONG   bbb_ID;            /* 4 character identifier */
    ULONG   bbb_SummedLongs;   /* size of this checksummed structure */
    LONG    bbb_ChkSum;        /* block checksum (longword sum to zero) */
    ULONG   bbb_HostID;        /* SCSI Target ID of host */
    ULONG   bbb_Next;          /* block number of the next BadBlockBlock */
    ULONG   bbb_Reserved;
    struct BadBlockEntry bbb_BlockPairs[61]; /* bad block entry pairs */
    /* note [61] assumes 512 byte blocks */
};

#define IDNAME_BADBLOCK         0x42414442      /* 'BADB' */

/*------------------------------------------------------------------*/
struct PartitionBlock {
    ULONG   pb_ID;            /* 4 character identifier */
    ULONG   pb_SummedLongs;   /* size of this checksummed structure */
    LONG    pb_ChkSum;        /* block checksum (longword sum to zero) */
    ULONG   pb_HostID;        /* SCSI Target ID of host */
    ULONG   pb_Next;          /* block number of the next PartitionBlock */
    ULONG   pb_Flags;         /* see below for defines */
    ULONG   pb_Reserved1[2];
    ULONG   pb_DevFlags;      /* preferred flags for OpenDevice */
    UBYTE   pb_DriveName[32]; /* preferred DOS device name: BSTR form */
                              /* (not used if this name is in use) */
    ULONG   pb_Reserved2[15]; /* filler to 32 longwords */
    ULONG   pb_Environment[17]; /* environment vector for this partition */
    ULONG   pb_EReserved[15]; /* reserved for future environment vector */
};

#define IDNAME_PARTITION      0x50415254      /* 'PART' */

#define PBFB_BOOTABLE   0     /* this partition intended to be bootable */
#define PBFF_BOOTABLE   1L    /*  (expected directories and files exist) */
#define PBFB_NOMOUNT    1     /* do not mount this partition (manually */
#define PBFF_NOMOUNT    2L    /*   mounted, but space reserved here) */

/*------------------------------------------------------------------*/
struct FileSysHeaderBlock {
    ULONG   fhb_ID;          /* 4 character identifier */
    ULONG   fhb_SummedLongs; /* size of this checksummed structure */
    LONG    fhb_ChkSum;      /* block checksum (longword sum to zero) */
    ULONG   fhb_HostID;      /* SCSI Target ID of host */
    ULONG   fhb_Next;        /* block number of next FileSysHeaderBlock */
    ULONG   fhb_Flags;       /* see below for defines */
    ULONG   fhb_Reserved1[2];
    ULONG   fhb_DosType;     /* file system description: match this with */
                             /* partition environment's DE_DOSTYPE entry */
    ULONG   fhb_Version;     /* release version of this code */
    ULONG   fhb_PatchFlags;  /* bits set for those of the following that */
                             /*  need to be substituted into a standard */
                             /*  device node for this file system: e.g. */
                             /*  0x180 to substitute SegList & GlobalVec */
    ULONG   fhb_Type;        /* device node type: zero */
    ULONG   fhb_Task;        /* standard dos "task" field: zero */
    ULONG   fhb_Lock;        /* not used for devices: zero */
    ULONG   fhb_Handler;     /* filename to loadseg: zero placeholder */
    ULONG   fhb_StackSize;   /* stacksize to use when starting task */
    LONG    fhb_Priority;    /* task priority when starting task */
    LONG    fhb_Startup;     /* startup msg: zero placeholder */
    LONG    fhb_SegListBlocks; /* first of linked list of LoadSegBlocks: */
                             /*   note that this entry requires some */
                             /*   processing before substitution */
    LONG    fhb_GlobalVec;   /* BCPL global vector when starting task */
    ULONG   fhb_Reserved2[23];/* (those reserved by PatchFlags) */
    ULONG   fhb_Reserved3[21];
};

#define IDNAME_FILESYSHEADER    0x46534844      /* 'FSHD' */

/*------------------------------------------------------------------*/
struct LoadSegBlock {
    ULONG   lsb_ID;             /* 4 character identifier */
    ULONG   lsb_SummedLongs;    /* size of this checksummed structure */
    LONG    lsb_ChkSum;         /* block checksum (longword sum to zero) */
    ULONG   lsb_HostID;         /* SCSI Target ID of host */
    ULONG   lsb_Next;           /* block number of the next LoadSegBlock */
    ULONG   lsb_LoadData[123];  /* data for "loadseg" */
    /* note [123] assumes 512 byte blocks */
};

#define IDNAME_LOADSEG

 How A Driver Uses RDB
 Alien Filing Systems


11 / RigidDiskBlock-Fields and Implementation / How A Driver Uses RDB

The information contained in the RigidDiskBlock and subsequent
PartitionBlocks, et al., is used by a driver in the following manner.

After determining that the target device is a hard disk (using the
SCSI-direct command INQUIRY), the driver will scan the first
RDB_LOCATION_LIMIT (16) blocks looking for a block with the "RDSK"
identifier and a correct sum-to-zero checksum.  If no RDB is found then
the driver will give up and not attempt to mount any partitions for this
unit.  If the RDB is found then the driver looks to see if there's a
partition list for this unit (rdb_PartitionList). If none, then just the
rdb_Flags will be used to determine if there are any LUNs or units after
this one.  This is used for early termination of the search for units on
bootup.

If a partition list is present, and the partition blocks have the correct
ID and checksum, then for each partition block the driver does the
following.

   1. Checks the PBFB_NOMOUNT flag.  If set then this partition is just
      reserving space.  Skip to the next partition without mounting the
      current one.

   2. If PBFB_NOMOUNT is false, then the partition is to be mounted.  The
      driver fetches the given drive name from pb_DriveName.  This name
      will be of the form dh0, work, wb_2.x etc.  A check is made to see if
      this name already exists on eb_MountList or DOS's device list. If it
      does, then the name is algorithmically altered to remove duplicates.
      The A590, A2091 and A3000 append .n (where n is a number) unless
      another name ending with .n is found.  In that case the name is
      changed to .n+1 and the search for duplicates is retried.

   3. Next the driver constructs a parameter packet for MakeDosNode() using
      the (possibly altered) drive name and information about the Exec
      device name and unit number.  MakeDosNode() is called to create a DOS
      device node.  MakeDosNode() constructs a filesystem startup message
      from the given information and fills in defaults for the ROM filing
      system.

   4. If MakeDosNode() succeeds then the driver checks to see if the entry
      is using a standard ("DOS\0") filing system.  If not then the
      routine for patching in non-standard filing systems is called (see
      "Alien File Systems" below).

   5. Now that the DOS node has been set up and the correct filing system
      segment has been associated with it, the driver checks PBFB_BOOTABLE
      to see if this partition is marked as bootable.  If the partition is
      not bootable, or this is not autoboot time (DiagArea == 0) then the
      driver simply calls AddDosNode() to enqueue the DOS device node.  If
      the partition is bootable, then the driver constructs a boot node and
      enqueues it on eb_MountList using the boot priority from the
      environment vector.  If this boot priority is -128 then the partition
      is not considered bootable.


11 / RigidDiskBlock - Fields and Implementation / Alien Filing Systems

When a filing system other than the ROM filing system is to be used, the
following steps take place.

   1. First, open filesystem.resource in preparation for finding the
      filesystem segment we want.  If filesystem.resource doesn't exist
      then create it and add it via AddResource().  Under 2.0 the resource
      is created by the system early on in the initialization sequence.
      Under pre-V36 Kickstart, it is the responsibility of the first RDB
      driver to create it.

   2. Scan filesystem.resource looking for a filesystem that matches the
      DosType and version that we want.  If it exists go to step 4.

   3. Since the driver couldn't find the filesystem it needed, it will have
      to load it from the RDB area.  The list of FileSysHeaderBlocks
      (pointed to by the "RDSK" block) is scanned for a filesystem of the
      required DosType and version.  If none is found then the driver will
      give up and abort the mounting of the partition.  If the required
      filesystem is found, then it is LoadSeg()'ed from the "LSEG" blocks
      and added as a new entry to the filesystem.resource.

   4. The SegList pointer of the found or loaded filesystem is held in the
      FileSysEntry structure (which is basically an environment vector for
      this filing system).  Using the patch flags, the driver now patches
      the newly created environment vector (pointed to by the new DosNode)
      using the values in the FileSysEntry being used.  This ensures that
      the partition will have the correct filing system set up with the
      correct mount variables using a shared SegList.

The eb_Mountlist will now be set up with prioritized bootnodes and maybe
some non-bootable, but mounted partitions.  The system bootstrap will now
take over.


11 SCSI Device / Amiga BootStrap

At priority -40 in the system module initialization sequence, after most
other modules are initialized, appropriate expansion boards are
configured.  Appropriate boards will match a FindConfigDev(, -1,-1)
 - these are all boards on the expansion library board list.
Furthermore, they will meet all of the following conditions:

   1. CDB_CONFIGME set in cd_Flags,

   2. ERTB_DIAGVALID set in cd_Rom->er_Type,

   3. diagnostic area pointer (in cd_Rom->er_Reserved0c) is non-zero,

   4. DAC_CONFIGTIME set in da_Config, and

   5. at least one valid resident tag within the diagnostic area, the first
      of which is used by InitResident() below.  This resident structure
      was patched to be valid during the ROM diagnostic routine run when
      the expansion library first initialized the board.

Boards meeting all these conditions are initialized with the standard
InitResident() mechanism, with a NULL SegList.  The board initialization
code can find its ConfigDev structure with the expansion library's
GetCurrentBinding() function.  This is an appropriate time for drivers to
Enqueue() a boot node on the expansion library's eb_MountList for use by
the strap module below, and clear CDB_CONFIGME so a C:BindDrivers command
will not try to initialize the board a second time.

This module will also enqueue nodes for 3.5" trackdisk device
units.  These nodes will be at the following priorities:

                           Priority     Drive
                           --------     -----
                             5          df0:
                           -10          df1:
                           -20          df2:
                           -30          df3:

Next, at priority -60 in the system module initialization sequence, the
strap module is invoked.  Nodes from the prioritized eb_MountList list is
used in priority order in attempts to boot. An item on the list is given a
chance to boot via one of two different mechanisms, depending on whether
it it uses boot code read in off the disk (BootBlock booting), or uses
boot code provided in the device ConfigDev diagnostic area
(BootPoint booting).  Floppies always use the BootBlock method.  Other
entries put on the eb_MountList (e.g. hard disk partitions) used the
BootPoint mechanism for pre-V36 Kickstart, but can use either for V36/V37.

The eb_MountList is modified before each boot attempt, and then
restored and re-modified for the next attempt if the boot fails:

   1. The node associated with the current boot attempt is placed at the
      head of the eb_MountList.

   2. Nodes marked as unusable under AmigaDOS are removed from the list.
      Nodes that are unusable are marked by the longword
      bn_DeviceNode->dn_Handler having the most significant bit set.  This
      is used, for example, to keep UNIX partitions off the AmigaDOS device
      list when booting AmigaDOS instead of UNIX.

The selection of which of the two different boot mechanisms to use
proceeds as follows:

   1. The node must be valid boot node, i.e. meet both of the following
      conditions:

       a) ln_Type is NT_BOOTNODE,
       b) bn_DeviceNode is non-zero,

   2. The type of boot is determined by looking at the DosEnvec pointed to
      by fssm_Environ pointed to by the dn_Startup in the bn_DeviceNode:

       a) if the de_TableSize is less than DE_BOOTBLOCKS, or the
          de_BootBlocks entry is zero, BootPoint booting is specified,
          otherwise

       b) de_BootBlocks contains the number of blocks to read in from
          the beginning of the partition, checksum, and try to boot from.

 Bootblock Booting
 Bootpoint Booting


11 / Amiga BootStrap / Bootblock Booting

In BootBlock booting the sequence of events is as follows:

   1. The disk device must contain valid boot blocks:

       a) the device and unit from dn_Startup opens successfully,

       b) memory is available for the <de_BootBlocks> * <de_SizeBlock> * 4
          bytes of boot block code,

       c) the device commands CMD_CLEAR, TD_CHANGENUM, and CMD_READ of the
          boot blocks execute without error,

       d) the boot blocks start with the three characters "DOS" and pass
          the longword checksum (with carry wraparound), and

       e) memory is available to construct a boot node on the eb_MountList
          to describe the floppy.  If a device error is reported in 1.c.,
          or if memory is not available for 1.b. or 1.e., a recoverable
          alert is presented before continuing.

   2. The boot code in the boot blocks is invoked as follows:

       a) The address of the entry point for the boot code is offset
          BB_ENTRY into the boot blocks in memory.

       b) The boot code is invoked with the I/O request used to issue the
          device commands in 1.c. above in register A1, with the io_Offset
          pointing to the beginning of the partition (the origin of the
          boot blocks) and SysBase in A6.

   3. The boot code returns with results in both D0 and A0.

       a) Non-zero D0 indicates boot failure.  The recoverable alert
          AN_BootError is presented before continuing.

       b) Zero D0 indicates A0 contains a pointer to the function to
          complete the boot.  This completion function is chained to with
          SysBase in A6 after the strap module frees all its resources.
          It is usually the dos.library initialization function, from the
          dos.library resident tag.  Return from this function is
          identical to return from the strap module itself.


11 / Amiga BootStrap / Bootpoint Booting

BootPoint booting follows this sequence:

   1. The eb_MountList node must contain a valid BootPoint:

       a) ConfigDev pointer (in ln_Name) is non-zero,

       b) diagnostic area pointer (in cd_Rom er_Reserved0c) is non-zero,

       c) DAC_CONFIGTIME set in da_Config.

   2. The boot routine of a valid boot node is invoked as follows:

       a) The address of the boot routine is calculated from da_BootPoint.

       b) The resulting boot routine is invoked with the ConfigDev pointer
          on the stack in C fashion (i.e., (*boot)(configDev);). Moreover,
          register A2 will contain the address of the associated
          eb_MountList node.

   3. Return from the boot routine indicates failure to boot.

If all entries fail to boot, the user is prompted to put a bootable disk
into a floppy drive with the "strap screen".  The system floppy drives
are polled for new disks.  When one appears, the "strap screen" is removed
and the appropriate boot mechanism is applied as described above.  The
process of prompting and trying continues till a successful boot occurs.


11 SCSI Device / Additional Information on the SCSI Device

Additional programming information on the SCSI device can be found in the
include files for the SCSI device and RigidDiskBlock.  Both are contained
in the Amiga ROM Kernel Reference Manual: Includes and Autodocs.

For information on the SCSI commands, see either the ANSI-X3T9 (draft
SCSI-2) or ANSI X3.131 (SCSI-1) specification.  The NCR SCSI BBS - phone
number (316)636-8700 (2400 baud) - has electronic copies of the current
SCSI specifications.

                        SCSI Device Information
                  -------------------------------------
                  INCLUDES        devices/scsidisk.h
                                  devices/scsidisk.i
                                  devices/hardblocks.h
                                  devices/hardblocks.i


Amiga® RKM Devices: 4 Console Device

The console device provides the text-oriented interface for Intuition
windows.  It acts like an enhanced ASCII terminal obeying many of the
standard ANSI sequences as well as special sequences unique to the Amiga.
The console device also provides a copy-and-paste facility and an internal
character map to redraw a window when it is resized.

                  NEW CONSOLE FEATURES FOR VERSION 2.0

               Feature                       Description
               -------                       -----------
              CONU_LIBRARY                    New #define
              CONU_STANDARD                   New #define
              CONU_CHARMAP                    Console Unit
              CONU_SNIPMAP                    Console Unit
              CONFLAG_DEFAULT                 Console Flag
              CONFLAG_NODRAW_ON_NEWSIZE       Console Flag

   Compatibility Warning:
   ----------------------
   The new features for the 2.0 console device are not backwards
   compatible.

 Console Device Commands and Functions
 Device Interface
 About Console I/O
 Writing to the Console Device
 Reading from the Console Device
 Copy and Paste Support
 Selecting Raw Input Events
 Input Event Reports
 Using the Console Device Without a Window
 Where Is All the Keymap Information?
 Console Device Caveats
 Console Device Example Code
 Additional Information on the Console Device


4 Console Device / Console Device Commands and Functions

Command              Operation
-------              ---------
CD_ASKDEFAULTKEYMAP  Get the current default keymap.

CD_ASKKEYMAP         Get the current key map structure for this console.

CD_SETDEFAULTKEYMAP  Set the current default keymap.

CD_SETKEYMAP         Set the current key map structure for this console.

CMD_CLEAR            Remove any reports waiting to satisfy read requests
                     from the console input buffer.

CMD_READ             Read the next input, generally from the keyboard.
                     The form of this input is as an ANSI byte stream.

CMD_WRITE            Write a text record to the display interpreting
                     any ANSI control characters in the record.

Console Device Function
-----------------------
CDInputHandler()     Handle an input event for the console device.

RawKeyConvert()      Decode raw input classes and convert input events of
                     type IECLASS_RAWKEY to ANSI bytes based on the keymap
                     in use.

Exec Functions as Used in This Chapter
--------------------------------------
AbortIO()            Abort an I/O request to the console device.

CheckIO()            Return the status of an I/O request.

CloseDevice()        Relinquish use of the console device.  All requests
                     must be complete before closing.

DoIO()               Initiate a command and wait for completion
                     (synchronous request).

GetMsg()             Get the next message from the reply port.

OpenDevice()         Obtain use of the console device.  You specify the
                     type of unit and its characteristics in the call to
                     OpenDevice().

OpenLibrary()        Gain access to a library.

OpenWindow()         Open an intuition window.

SendIO()             Initiate a command and return immediately
                     (asynchronous request).

Wait()               Wait for one or more signals.

WaitIO()             Wait for completion of an I/O request and remove it
                     from the reply port.

WaitPort()           Wait for the reply port to be non-empty. Does not
                     remove the message from port.

Exec Support Functions as Used in This Chapter
----------------------------------------------
CreateExtIO()        Create an extended I/O request structure for use in
                     communicating with the console device.

CreatePort()         Create a message port for reply messages from the
                     console device.  Exec will signal a task when a
                     message arrives at the port.

DeleteExtIO()        Delete the extended I/O request structure created by
                     CreateExtIO().

DeletePort()         Delete the message port created by CreatePort().


4 Console Device / Device Interface

The console device operates like the other Amiga devices.  To use it, you
must first open the console device, then send I/O requests to it, and then
close it when finished.  See the "Introduction to Amiga System Devices"
chapter for general information on device usage.

The I/O request used by the console device is called IOStdReq.

   struct IOStdReq
   {
       struct  Message io_Message;
       struct  Device  *io_Device;/* device node pointer  */
       struct  Unit    *io_Unit;  /* unit (driver private)*/
       UWORD   io_Command;        /* device command */
       UBYTE   io_Flags;
       BYTE    io_Error;          /* error or warning num */
       ULONG   io_Actual;         /* actual number of bytes transferred */
       ULONG   io_Length;         /* requested number bytes transferred*/
       APTR    io_Data;           /* points to data area */
       ULONG   io_Offset;         /* offset for block structured devices */
   };

See the include file exec/io.h for the complete structure definition.

 Console Device Units
 Opening The Console Device
 Closing The Console Device


4 / Device Interface / Console Device Units

The console device provides four units, three that require a console
window and one that does not. The unit type is specified when you open the
device. See the Opening the Console Device section below for more
details.

The CONU_STANDARD unit (0) is generally used with a SMART_REFRESH window.
This unit has the least amount of overhead (e.g., memory usage and
rendering time), and is highly compatible with all versions of the
operating system.

As of V36, a character mapped console device was introduced.  There are
two variations of character mapped console units.  Both must be used with
SIMPLE_REFRESH windows and both have the ability to automatically redraw a
console window when resized or revealed.

A character mapped console can be opened which allows the user to
drag-select text with the mouse and COPY the highlighted area.  The copied
text can then be PASTEd into other console windows or other windows which
support reading data from the clipboard device.

Character mapped console units have more overhead than standard consoles
(e.g., rendering times and memory usage).

The CONU_LIBRARY unit (-1) does not require a console window.  It is
designed to be primarily used with the console device functions and also
with the console device commands that do not require a console window.

The Amiga uses the ECMA-94 Latin1 International 8-bit character set. See
Appendix A (page 397) for a table of character codes.


4 / Device Interface / Opening The Console Device

Four primary steps are required to open the console device:

   *  Create a message port using CreatePort(). Reply messages from the
      device must be directed to a message port.

   *  Create an I/O request structure of type IOStdReq. The IOStdReq
      structure is created by the CreateExtIO() function. CreateExtIO will
      initialize your I/O request to point to your reply port.

   *  Open an Intuition window and set a pointer to it in the io_Data field
      of the IOStdReq and the size of the window in the io_Length field.
      This is the window to which the console will be attached.  The window
      must be SIMPLE_REFRESH for use with the CONU_CHARMAP and CONU_SNIPMAP
      units.

   *  Open the console device.  Call OpenDevice() passing it the I/O
      request and the type of console unit set in the unit and flags
      fields. Console unit types and flag values are listed below.

Console device units:

   *  CONU_LIBRARY  - Return the device library vector pointer used for
      calling console device functions.  No console is opened.

   *  CONU_STANDARD - Open a standard console.

   *  CONU_CHARMAP  - Open a console with a character map.

   *  CONU_SNIPMAP  - Open a console with a character map and
      copy-and-paste support.

See the include file devices/conunit.h for the unit definitions
and the Amiga ROM Kernel Reference Manual: Includes and Autodocs for an
explanation of each unit.

   No Changes Required
   -------------------
   CONU_STANDARD has a numeric value of zero to insure compatibility
   with pre-V36 applications.  CONU_LIBRARY has a numeric value of
   negative one and is also compatible with pre-V36 applications.

Console device flags:

   *  CONFLAG_DEFAULT - The console device will redraw the window when it
      is resized.

   *  CONFLAG_NODRAW_ON_NEWSIZE - The console device will not redraw the
      window when it is resized

The character map units, CONU_CHARMAP and CONU_SNIPMAP, are the only units
which use the flags parameter to set how the character map is used.
CONU_STANDARD units ignore the flags parameter.

See the include file devices/conunit.h for the flag definitions and the
Amiga ROM Kernel Reference Manual: Includes and Autodocs for an
explanation of the flags.

    struct MsgPort *ConsoleMP;   /* Message port pointer */
    struct IOStdReq *ConsIO;     /* I/O structure pointer */
    struct Window   *win = NULL; /* Window pointer */

    struct NewWindow nw =
    {
        10, 10,                    /* starting position (left,top) */
        620,180,                   /* width, height */
        -1,-1,                     /* detailpen, blockpen */
        CLOSEWINDOW,               /* flags for idcmp */
        WINDOWDEPTH|WINDOWSIZING|
        WINDOWDRAG|WINDOWCLOSE|
        SIMPLE_REFRESH|ACTIVATE,    /* window flags */
        NULL,                      /* no user gadgets */
        NULL,                      /* no user checkmark */
        "Console Test",            /* title */
        NULL,                      /* pointer to window screen */
        NULL,                      /* pointer to super bitmap */
        100,45,                    /* min width, height */
        640,200,                   /* max width, height */
        WBENCHSCREEN               /* open on workbench screen */
    };

        /* Create reply port console */
    if (!(ConsoleMP = CreatePort("RKM.Console",0)))
        cleanexit("Can't create write port\n",RETURN_FAIL);

        /* Create message block for device I/O */
    if (!(ConsIO = CreateExtIO(ConsoleMP,sizeof(struct IOStdReq))))
        cleanexit("Can't create IORequest\n",RETURN_FAIL);

        /* Open a window - we assume intuition.library is already open */
    if (!(win = OpenWindow(&nw)))
        cleanexit("Can't open window\n",RETURN_FAIL);

        /* Set window pointer and size in I/O request */
    ConsIO->io_Data = (APTR) win;
    ConsIO->io_Length = sizeof(struct Window);

        /* Open the console device */
    if (error = OpenDevice("console.device",CONU_CHARMAP,ConsIO,
                                            CONFLAG_DEFAULT))
        cleanexit("Can't open console.device\n",RETURN_FAIL);


4 / Device Interface / Closing The Console Device

Each OpenDevice() must eventually be matched by a call to CloseDevice().

All I/O requests must be complete before CloseDevice().  If any requests
are still pending, abort them with AbortIO().

    if (!(CheckIO(ConsIO)))
        AbortIO(ConsIO);    /* Ask device to abort any pending requests */

    WaitIO(ConsIO);         /* Wait for abort, then clean up */
    CloseDevice(ConsIO);    /* Close console device */


4 Console Device / About Console I/O

The console device may be thought of as a kind of terminal. You send
character streams to the console device; you also receive them from the
console device. These streams may be characters, control sequences or a
combination of the two.

Console I/O is closely associated with the Amiga Intuition interface; a
console must be tied to a window that is already opened.  From the Window
data structure, the console device determines how many characters it can
display on a line and how many lines of text it can display in a window
without clipping at any edge.

You can open the console device many times, if you wish. The result of
each open call is a new console unit. AmigaDOS and Intuition see to it
that only one window is currently active and its console, if any, is the
only one (with a few exceptions) that receives notification of input
events, such as keystrokes. Later in this chapter you will see that other
Intuition events can be sensed by the console device as well.

   Introducing...
   --------------
   For this entire chapter the characters "<CSI>" represent the
   control sequence introducer. For output you may use either the
   two-character sequence  <Esc>[ (0x1B 0x5B) or the one-byte value
   0x9B. For input you will receive 0x9B unless the sequence has been
   typed by the user.

 Exec Functions And The Console Device
 General Console Screen Output
 Console Keyboard Input


4 / About Console I/O / Exec Functions And The Console Device

The various Exec functions such as DoIO(), SendIO(), AbortIO() and
CheckIO() operate normally. The only caveats are that CMD_WRITE may cause
your application to wait internally, even with SendIO(), and a task using
CMD_READ to wait on a response from a console is at the user's mercy.  If
the user never reselects that window, and the console response provides
the only wake-up call, that task will sleep forever.


4 / About Console I/O / General Console Screen Output

Console character screen output (as compared to console command sequence
transmission) outputs all standard printable characters (character values
hex 20 through 7E and A0 through FF) normally.

Many control characters such as BACKSPACE (0x8) and RETURN (0x13) are
translated into their exact ANSI equivalent actions. The LINEFEED
character (0xA) is a bit different in that it can be translated into a
RETURN/LINEFEED action. The net effect is that the cursor moves to the
first column of the next line whenever an <LF> is displayed. This option
is set via the mode control sequences discussed under
Control Sequences for Window Output.


4 / About Console I/O / Console Keyboard Input

If you read from the console device, the keyboard inputs are preprocessed
for you and you will get ASCII characters, such as "B." Most normal
text-gathering programs will read from the console device in this manner.
Some programs may also ask to receive raw events in their console stream.
Keypresses are converted to ASCII characters or CSI sequences via the
keymap associated with the unit.


4 Console Device / Writing to the Console Device

You write to the console device by passing an I/O request to the device
with a pointer to the write buffer set in io_Data, the number of bytes in
the buffer set in io_Length and CMD_WRITE set in io_Command.

    UBYTE *outstring= "Make it so.";

    ConsIO->io_Data = outstring;
    ConsIO->io_Length = strlen(outstring);
    ConsIO->io_Command = CMD_WRITE;
    DoIO(ConsIO);

You may also send NULL-terminated strings to the console device in the
same manner except that io_Length must be set to -1.

    ConsIO->io_Data = "\033[3mOh boy.";
    ConsIO->io_Length = -1;
    ConsIO->io_Command = CMD_WRITE;
    DoIO(ConsIO);

The fragment above will output the string "Oh boy." in italics.  Keep in
mind that setting the text rendition to italics will remain in effect
until you specifically instruct the console device to change it to another
text style.

 Hints For Writing Text
 Control Sequences For Window Output
 Example Console Control Sequences


4 / Writing to the Console Device / Hints For Writing Text

256 Is A Nice Round Number
--------------------------
   You must keep in mind that the console device locks all layers while
   writing text.  To avoid, problems with this, it is best to send
   smaller rather larger numbers of character to be written.  We
   recommend no more than 256 bytes per write as the optimum size

Turn Off The Cursor
-------------------
   If your console is attached to a V1.2/1.3 SuperBitmap window, you
   will not see a cursor rendered. For output speed and compatibility
   with future OS versions which may visibly render the cursor, you
   should send the cursor-off sequence (ESC[0 p) whenever you open or
   reset (ESCc) a SuperBitmap window's console.


4 / Writing to the Console Device / Control Sequences For Window Output

The following table lists functions that the console device supports,
along with the character stream that you must send to the console to
produce the effect.  For more information on the control sequences,
consult the console.doc of the Amiga ROM Kernel Reference Manual: Includes
and Autodocs. The table uses the second form of <CSI>, that is, the hex
value 0x9B, to minimize the number of characters to be transmitted to
produce a function.

A couple of notes about the table. If an item is enclosed in square
brackets, it is optional and may be omitted.  For example, for INSERT [N]
CHARACTERS the value for N is shown as optional.  The console device
responds to such optional items by treating the value of N as 1 if it is
not specified. The value of N or M is always a decimal number, having one
or more ASCII digits to express its value.

                      ANSI CONSOLE CONTROL SEQUENCES

                                              Sequence of Characters
    Console Command                           (in Hexadecimal Form)
    ---------------                           ---------------------
    BELL                                       07
    (Flash the display
     ie; do an Intuition DisplayBeep())

    BACKSPACE                                  08
    (move left one column)

    HORIZONTAL TAB                             09
    (move right one tab stop)

    LINEFEED                                   0A
    (move down one text line as
     specified by the mode function)

    VERTICAL TAB                               0B
    (move up one text line)

    FORMFEED                                   0C
    (clear the console's window)

    CARRIAGE RETURN                            0D
    (move to first column)

    SHIFT IN                                   OE
    (undo SHIFT OUT)

    SHIFT OUT                                  0F
    (set MSB of each character
     before displaying)

    ESC                                        1B
    (escape; can be part of the
     control sequence introducer)

    INDEX                                      84
    (move the active position down
     one line)

    NEXT LINE                                  85
    (go to the beginning of the next
     line)

    HORIZONTAL TABULATION SET                  88
    (Set a tab at the active cursor
     position)

    REVERSE INDEX                              8D
    (move the active position up one
     line)

    CSI                                        9B
    (control sequence introducer)

    RESET TO INITIAL STATE 1B                  63

    INSERT [N] CHARACTERS 9B [N]               40
    (insert one or more spaces,
     shifting the remainder of the line
     to the right)

    CURSOR UP [N] CHARACTER POSITIONS          9B [N] 41
    (default = 1)

    CURSOR DOWN [N] CHARACTER POSITIONS        9B [N] 42
    (default = 1)

    CURSOR FORWARD [N] CHARACTER POSITIONS     9B [N] 43
    (default = 1)

    CURSOR BACKWARD [N] CHARACTER              9B [N] 44
    (default = 1)

    CURSOR NEXT LINE [N]                       9B [N] 45
    (to column 1)

    CURSOR PRECEDING LINE [N]                  9B [N] 46
    (to column 1)

    CURSOR POSITION                            9B [N] [3B M] 48
    (where N is row, M is column, and
    semicolon (hex 3B) must be present
    as a separator, or if row is left
    out, so the console device can tell
    that the number after the semicolon
    actually represents the column number)

    CURSOR HORIZONTAL TABULATION               9B [N] 49
    (move cursor forward to Nth tab
     position)

    ERASE IN DISPLAY                           9B 4A
    (only to end of display)

    ERASE IN LINE                              9B 4B
    (only to end of line)

    INSERT LINE                                9B 4C
    (above the line containing the
     cursor)

    DELETE LINE                                9B 4D
    (remove current line, move
     all lines up one position to
     fill gap, blank bottom line)

    DELETE CHARACTER [N]                       9B [N] 50
    (that cursor is sitting on
     and to the right if
    [N] is specified)

    SCROLL UP [N] LINES                        9B [N] 53
    (Remove line(s) from top of window,
     move all other lines up, blanks [N]
     bottom lines)

    SCROLL DOWN [N] LINES                      9B [N] 54
    (Remove line(s) from bottom of
     window, move all other lines down,
     blanks [N] top lines)

    CURSOR TABULATION CONTROL                  9B [N] 57
    (where N = 0 set tab, 2 = clear tab,
     5 = clear all tabs.)

    CURSOR BACKWARD TABULATION                 9B [N] 5A
    (move cursor backward to Nth
     tab position.)

    SET LINEFEED MODE                          9B 32 30 68
    (cause LINEFEED to respond
     as RETURN-LINEFEED)

    RESET NEWLINE MODE                         9B 32 30 6C
    (cause LINEFEED to respond
     only as LINEFEED)

    DEVICE STATUS REPORT                       9B 36 6E
    (cause console device to
     insert a CURSOR POSITION REPORT
     into your read stream; see
     "Reading from the Console Device"
     for more information)

    SELECT GRAPHIC RENDITION                  9B N 3B 3N 3B 4N 3B >N 6D
    (select text style, character color,      (See note below).
     character cell color,background color)

For SELECT GRAPHIC RENDITION, any number of parameters, in any order,
are valid. They are separated by semicolons.

The parameters follow:

    <text style> =

        0  Plain text                      8   Concealed mode
        1  Boldface                        22  Normal color, not bold (V36)
        2  faint (secondary color)         23  Italic off (V36)
        3  Italic                          24  Underscore off (V36)
        4  Underscore                      27  Reversed off (V36)
        7  Reversed character/cell colors  28  Concealed off (V36)

    <character color> =

        30-37  System colors 0-7 for character color.
        39     Reset to default character color
               Transmitted as two ASCII characters.

    <character cell color> =

        40-47  System colors 0-7 for character cell color.
        39     Reset to default character color
               Transmitted as two ASCII characters.

    <background color> =

        >0-7System colors 0-7 for background color.(V36)
        You must specify the ">" in order for this to
        be recognized and it must be the last parameter.

For example, to select bold face, with color 3 as the character color, and
color 0 as the character cell color and the background color, send the hex
sequence:

    9B 31 3B 33 33 3B 34 30 3B 3E 30 6D

representing the ASCII sequence:

    <CSI>1;33;40;>0m

where <CSI> is the control sequence introducer, here used as the single
character value 0x9B.

   Go Easy On The Eyes.
   --------------------
   In most cases, the character cell color and the background color
   should be the same.

 Set Graphic Rendition Implementation Notes


4 / / Set Graphic Rendition Implementation Notes

Previous versions of the operating system did not support the global
background color sequence as is listed above.  Instead, the background
color was set by setting the character cell color and then clearing the
screen (e.g., a FORMFEED).

In fact, vacated areas of windows (vacated because of an ERASE or SCROLL)
were filled in with the character cell color.  This is no longer the case.
Now, when an area is vacated, it is filled in with the global background
color.

SMART_REFRESH windows are a special case:

Under V33-V34:
   The cell color had to be set and a FORMFEED (clear window) needed to
   be sent on resize or immediately to clear the window and set the
   background color.

   For example, if you took a CLI window and sent the sequence to set the
   cell color to something other than the default,the background color
   would not be changed immediately (contrary to what was expected).

   If you then sent a FORMFEED,the background color would change,but if you
   resized the window larger, you would note that the newly revealed areas
   were filled in with PEN 0.

Under V36-V37 (non-character mapped):
   You need to set the global background color and do a FormFeed.  The
   background color will then be used to fill the window, but like
   V33-V34, if you make the window larger, the vacated areas will be
   filled in with PEN 0.

Under V36-V37 (character mapped):
   You need to set the global background color, the window is redrawn
   immediately (because we have the character map) and will be correctly
   redrawn with the global background color on subsequent resizes.

The sequences in the next table are not ANSI standard sequences, they are
private Amiga sequences. In these command descriptions, length, width, and
offset are comprised of one or more ASCII digits, defining a decimal value.

                     AMIGA CONSOLE CONTROL SEQUENCES

        Console Command             Sequence of Characters(in Hex Format)
    ----------------------          -------------------------------------
    ENABLE SCROLL(default)                     9B 3E 31 68

    DISABLE SCROLL                             9B 3E 31 6C

    AUTOWRAP ON (default)                      9B 3F 37 68

    AUTOWRAP OFF                               9B 3F 37 6C

    SET PAGE LENGTH                            9B <length> 74
    (in character raster lines, causes
     console to recalculate,using
     current font, how many text lines
     will fit on the page)

    SET LINE LENGTH                            9B <width> 75
    (in character positions, using
     current font, how many characters
     should be placed on each line)

    SET LEFT OFFSET                            9B <offset> 78
    (in raster columns, how far from
     the left of the window should
     the text begin)

    SET TOP OFFSET                             9B <offset> 79
    (in raster lines, how far
     from the top of the window's
     RastPort should the topmost
     line of the character begin)

    SET RAW EVENTS                             9B <events> 7B
    (set the raw input events that
     will trigger an INPUT EVENT
     REPORT. see the
     "Selecting Raw Input Events"
     section below  for more details.)

    INPUT EVENT REPORT                         9B <parameters> 7C
    (returned by the console device
     in response to a raw event
     set by the SET RAW EVENT sequence.
     See the "Input Event Reports"
     section below for more details.)

    RESET RAW EVENTS                           9B <events> 7D
    (reset the raw events set by
     the SET RAW EVENT sequence. See the
     "Selecting Raw Input Events"
     section below.)

    SPECIAL KEY REPORT                         9B <keyvalue> 7E
    (returned by the console device
     whenever HELP, or one of the
     function keys or arrow keys is
     pressed.  Some sequences do not end
     with 7E)

    SET CURSOR RENDITION                       9B N 20 70
    (make the cursor visible or invisible:
     Note-turning off the cursor increases
     text output speed)

        Invisible:                             9B 30 20 70
        Visible:                               9B 20 70

    WINDOW STATUS REQUEST                      9B 30 20 71
    (ask the console device to tell you
     the current bounds of the window,
     in upper and lower row and column
     character positions.  User may have
     resized or repositioned it.See
     "Window Bounds Report" below.)

    WINDOW BOUNDS REPORT                       9B 31 3B 31 3B <bot margin>
    (returned by the console device in         3B <right margin> 72
     response to a WINDOW STATUS REQUEST
     sequence)

    RIGHT AMIGA V PRESS                        9B 30 20 76
    (returned by the console device when
     the user presses RIGHT-AMIGA-V.  See
     the "Copy and Paste Support" section
     below for more details.)

   Give Back What You Take.
   ------------------------
   The console device normally handles the SET PAGE LENGTH, SET LINE
   LENGTH, SET LEFT OFFSET, and SET TOP OFFSET functions automatically.
   To allow it to do so again after setting your own values, send the
   functions without a parameter.


4 / Writing to the Console Device / Example Console Control Sequences

                                     Character String       Numeric (hex)
                                        Equivalent           Equivalent
                                     ----------------       -------------
    Move cursor right by 1:              <CSI>C or           9B 43
                                         <CSI>1C             9B 31 43

    Move cursor right by 20:             <CSI>20C            9B 32 30 43

    Move cursor to upper-left corner
    (Home Position)                      <CSI>H  or          9B 48
                                         <CSI>1;1H or        9B 31 3B 31 48
                                         <CSI>;1H or         9B 3B 31 48
                                         <CSI>1;H            9B 31 3B 48
    Move cursor to the fourth column
    of the first line of the window:     <CSI>1;4H or        9B 31 3B 34 48
                                         <CSI>;4H            9B 3B 34 48

    Clear the window:                    <FF> or             0C
                                         CTRL-L or
    (home and clear to end of window)    <CSI>H<CSI>J        9B 48 9B 4A


4 Console Device / Reading from the Console Device

Reading input from the console device returns an ANSI 3.64 standard byte
stream.  This stream may contain normal characters and/or RAW input event
information.  You may also request other RAW input events using the SET
RAW EVENTS and RESET RAW EVENTS control sequences discussed below.  See
"Selection of Raw Input Events.".

Generally, console reads are performed asynchronously so that your program
can respond to other events and other user input (such as menu selections)
when the user is not typing on the keyboard. To perform asynchronous I/O,
an I/O request is sent to the console using the SendIO() function (rather
than a synchronous DoIO() which would wait until the read request returned
with a character).

You read from the console device by passing an I/O request to the device
with a pointer to the read buffer set in io_Data, the number of bytes in
the buffer set in io_Length and CMD_READ set in io_Command.

   #define READ_BUFFER_SIZE 25
   char ConsoleReadBuffer[READ_BUFFER_SIZE];

   ConsIO->io_Data = (APTR)ConsoleReadBuffer;
   ConsIO->io_Length = READ_BUFFER_SIZE;
   ConsIO->io_Command = CMD_READ;
   SendIO(ConsIO);

   You May Get Less Than You Bargained For.
   ----------------------------------------
   A request for more than one character may be satisfied by the receipt
   of only one character.  If you request more than one character, you
   will have to examine the io_Actual field of the request when it
   returns to determine how many characters you have actually received.

After sending the read request, your program can wait on a combination of
signal bits including that of the reply port you created. The following
fragment demonstrates waiting on both a queued console read request, and
Window IDCMP messages:

   ULONG conreadsig = 1 << ConsoleMP->mp_SigBit;
   ULONG windowsig = 1 << win->UserPort->mp_SigBit;

   /* A character, or an IDCMP msg, or both will wake us up */
   ULONG signals = Wait(conreadsig | windowsig);

   if (signals & conreadsig)
       {
       /* Then check for a character */
       };

   if (signals & windowsig)
       {
       /* Then check window messages */
       };

 Information About The Input Stream
 Cursor Position Report
 Window Bounds Report


4 / Reading from the Console Device / Information About The Input Stream

For the most part, keys whose keycaps are labeled with ANSI-standard
characters will ordinarily be translated into their ASCII-equivalent
character by the console device through the use of its keymap. Keymap
information can be found in the "Keymap Library" chapter of the Amiga
ROM Kernel Reference Manual: Libraries.

For keys other than those with normal ASCII equivalents, an escape
sequence is generated and inserted into your input stream.  For example,
in the default state (no raw input events selected)  the function, arrow
and special keys (reserved for 101 key keyboards) will cause the sequences
shown in the next table to be inserted in the input stream.

                      SPECIAL KEY REPORT SEQUENCES

     Key        Unshifted Sends     Shifted Sends
     ---        ---------------     -------------
     F1            <CSI>0~            <CSI>10~
     F2            <CSI>1~            <CSI>11~
     F3            <CSI>2~            <CSI>12~
     F4            <CSI>3~            <CSI>13~
     F5            <CSI>4~            <CSI>14~
     F6            <CSI>5~            <CSI>15~
     F7            <CSI>6~            <CSI>16~
     F8            <CSI>7~            <CSI>17~
     F9            <CSI>8~            <CSI>18~
     F10           <CSI>9~            <CSI>19~
     F11           <CSI>20~           <CSI>30~ (101 key keyboard)
     F12           <CSI>21~           <CSI>31~ (101 key keyboard)
     HELP          <CSI>?~            <CSI>?~  (same sequence for both)
     Insert        <CSI>40~           <CSI>50~ (101 key keyboard)
     Page Up       <CSI>41~           <CSI>51~ (101 key keyboard)
     Page Down     <CSI>42~           <CSI>52~ (101 key keyboard)
     Pause/Break   <CSI>43~           <CSI>53~ (101 key keyboard)
     Home          <CSI>44~           <CSI>54~ (101 key keyboard)
     End           <CSI>45~           <CSI>55~ (101 key keyboard)

     Arrow keys:
     Up            <CSI>A             <CSI>T
     Down          <CSI>B             <CSI>S
     Left          <CSI>D             <CSI>A   (notice the space
     Right         <CSI>C             <CSI>@    after <CSI>)


4 / Reading from the Console Device / Cursor Position Report

If you have sent the DEVICE STATUS REPORT command sequence, the console
device returns a cursor position report into your input stream.  It takes
the form:

    <CSI><row>;<column>R

For example, if the cursor is at column 40 and row 12, here are the ASCII
values (in hex) you receive in a stream:

    9B 34 30 3B 31 32 52


4 / Reading from the Console Device / Window Bounds Report

A user may have either moved or resized the window to which your console
is bound.  By issuing a WINDOW STATUS REPORT to the console, you can read
the current position and size in the input stream.  This window bounds
report takes the following form:

    <CSI>1;1;<bottom margin>;<right margin> r

The bottom and right margins give you the window row and column dimensions
as well. For a window that holds 20 lines with 60 characters per line, you
will receive the following in the input stream:

    9B 31 3B 31 3B 32 30 3B 36 30 20 72


4 Console Device / Copy and Paste Support

As noted above, opening the console device with a unit of CONU_SNIPMAP
allows the user to drag-select text with the mouse and copy the selection
with Right-Amiga-C.

Internally, the snip is copied to a private buffer managed by the console
device where it can be copied to other console device windows by pressing
Right-Amiga-V.

However, your application should assume that the user is running the
Conclip" utility which is part of the standard Workbench 2.0
environment.  Conclip copies snips from the console device to the
clipboard device where they can be used by other applications which
support reading from the clipboard.

When Conclip is running and the user presses Right-Amiga-V, the console
device puts an escape sequence in your read stream - <CSI>0 v  (Hex 9B 30
20 76) - which tells you that the user wants to paste text from the
clipboard.

Upon receipt of this sequence, your application should read the contents
of the clipboard device, make a copy of any text found there and then
release the clipboard so that it can be used by other applications.  See
the "Clipboard Device" chapter for more information on reading data from
it.

You paste what you read from the clipboard by using successive writes to
the console.  In order to avoid problems with excessively long data in the
clipboard, you should limit the size of writes to something reasonable.
(We define reasonable as no more than 1K per write with the ideal amount
being 256 bytes.)  You should also continue to monitor the console read
stream for additional use input, paster requests and, possibly, RAW INPUT
EVENTS while you are doing this.

You should not open a character mapped console unit with COPY capability
if you are unable to support PASTE from the clipboard device.  The user
will reasonably expect to be able to PASTE into windows from which a COPY
can be done.

Keep in mind that users do make mistakes, so an UNDO mechanism for
aborting a PASTE is highly desirable - particularly if the user has just
accidentally pasted text into an application like a terminal program which
is sending data at a slow rate.

   Use CON:, You'll Be Glad You Did.
   ---------------------------------
   It is highly recommended that you consider using the console-handler
   (CON:) if you want a console window with COPY and PASTE
   capablilities. CON: provides you with free PASTE support and is
   considerably easier to open and use than using the console device
   directly.


4 Console Device / Selecting Raw Input Events

If the keyboard information - including "cooked" keystrokes - does not
give you enough information about input events, you can request additional
information from the console driver.

The command to SET RAW EVENTS is formatted as:

    <CSI>[event-types-separated-by-semicolons]{

If, for example, you need to know when each key is pressed and released,
you would request "RAW keyboard input." This is done by writing
"<CSI>1{" to the console.  In a single SET RAW EVENTS request, you can
ask the console to set up for multiple event types at one time.  You must
send multiple numeric parameters, separating them by semicolons (;). For
example, to ask for gadget pressed, gadget released, and close gadget
events, write:

    <CSI>7;8;11{

You can reset, that is, delete from reporting, one or more of the raw
input event types by using the RESET RAW EVENTS command, in the same
manner as the SET RAW EVENTS was used to establish them in the first
place.  This command stream is formatted as:

    <CSI>[event-types-separated-by-semicolons]}

So, for example, you could reset all of the events set in the above
example by transmitting the command sequence:

    <CSI>7;8;11}

   The Read Stream May Not Be Dry.
   -------------------------------
   There could still be pending RAW INPUT EVENTS in your read stream
   after turning off one or more RAW INPUT EVENTS.

The following table lists the valid raw input event types.

                      RAW INPUT EVENT TYPES
    Request                                        Request
    Number   Description              Number     Description
    -------  -----------              ------     -----------
      0      No-op (used internally)    11       Close Gadget
      1      RAW keyboard input *       12       Window resized
      2      RAW mouse input            13       Window refreshed
      3      Private Console Event      14       Preferences changed
      4      Pointer position           15       Disk removed
      5      (unused)                   16       Disk inserted
      6      Timer                      17       Active window
      7      Gadget pressed             18       Inactive window
      8      Gadget released            19       New pointer position (V36)
      9      Requester activity         20       Menu help (V36)
      10     Menu numbers               21       Window changed (V36)
                                                 (zoom, move)

      * Note:Intuition swallows all except the select button.

The event types-requester, window refreshed, active window, inactive
window, window resized and window changed-are dispatched to the console
unit which owns the window from which the events are generated, even if it
is not the active (selected ) window at the time the event is generated.
This ensures that the proper console unit is notified of those events. All
other events are dispatched to the active console unit (if it has
requested those events).


4 Console Device / Input Event Reports

If you select any of these events you will start to get information about
the events in the following form:

<CSI><class>;<subclass>;<keycode>;<qualifiers>;<x>;<y>;<secs>;<microsecs>|

<CSI>
   is a one-byte field.  It is the "control sequence introducer," 0x9B
   in hex.

<class>
   is the RAW input event type, from the above table.

<subclass>
   is usually 0. If the mouse is moved to the right controller, this
   would be 1.

<keycode>
   indicates which raw key number was pressed. This field can also be
   used for mouse information.

   The Raw Key Might Be The Wrong Key.
   -----------------------------------
   National keyboards often have different keyboard arrangements. This
   means that a particular raw key number may represent different
   characters on different national keyboards. The normal console read
   stream (as opposed to raw events) will contain the proper ASCII
   character for the keypress as translated according to the user's
   keymap.

<qualifiers>
   indicates the state of the keyboard and system.

The qualifiers are defined as follows:

                         INPUT EVENT QUALIFIERS

   Bit  Mask   Key
   ---  ----   ---
    0   0001   Left shift
    1   0002   Right shift
    2   0004   Caps Lock Associated keycode is special; see below.
    3   0008   Ctrl
    4   0010   Left Alt
    5   0020   Right Alt
    6   0040   Left Amiga key pressed
    7   0080   Right Amiga key pressed
    8   0100   Numeric pad
    9   0200   Repeat
    10  0400   Interrupt Not currently used.
    11  0800   Multibroadcast This window (active one) or all windows.
    12  1000   Middle mouse button (Not available on standard mouse)
    13  2000   Right mouse button
    14  4000   Left mouse button
    15  8000   Relative mouse Mouse coordinates are relative, not absolute.

The Caps Lock key is handled in a special manner. It generates a keycode
only when it is pressed, not when it is released. However, the up/down bit
(80 hex) is still used and reported. If pressing the Caps Lock key causes
the LED to light, keycode 62 (Caps Lock pressed) is sent. If pressing the
Caps Lock key extinguishes the LED, keycode 190 (Caps Lock released) is
sent. In effect, the keyboard reports this key as held down until it is
struck again.

The <x> and <y> fields are filled by some classes with an Intuition
address:  x<<16+y.

The <seconds> and <microseconds> fields contain the system time stamp
taken at the time the event occurred.  These values are stored as
longwords by the system.

With RAW keyboard input selected, keys will no longer return a simple
one-character "A" to "Z" but will instead return raw keycode reports
of the form:

  <CSI>1;0;<keycode>;<qualifiers>;<prev1>;<prev2>;<seconds>;<microseconds>|

For example, if the user pressed and released the A key with the left
Shift and right Amiga keys also pressed, you might receive the following
data:

  <CSI>1;0;32;32769;14593;5889;421939940;316673|

  <CSI>1;0;160;32769;0;0;421939991;816683|

The <keycode> field is an ASCII decimal value representing the key pressed
or released.  Adding 128 to the pressed key code will result in the
released keycode.

The <prev1> and <prev2> fields are relevant for the interpretation of keys
which are modifiable by dead-keys (see "Dead-Class Keys" section). The
<prev1> field shows the previous key pressed.  The lower byte shows the
qualifier, the upper byte shows the key code. The <prev2> field shows the
key pressed before the previous key.  The lower byte shows the qualifier,
the upper byte shows the key code.


4 Console Device / Using the Console Device Without a Window

Most console device processing involves a window, but there are functions
and special commands that may be used without a window.  To use the
console device without a window, you call OpenDevice() with the console
unit CONU_LIBRARY.

The console device functions are CDInputHandler() and RawKeyConvert();
they may only be used with the CONU_LIBRARY console unit.  The console
device commands which do not require a window are CD_ASKDEFAULTKEYMAP
and CD_SETDEFAULTKEYMAP; they be used with any console unit.  The
advantage of using the commands with the CONU_LIBRARY unit is the lack of
overhead required for CONU_LIBRARY because it doesn't require a window.

To use the functions requires the following steps:

   *  Declare the console device base address variable ConsoleDevice in the
      global data area.

   *  Declare storage for an I/O request of type IOStdReq.

   *  Open the console device with CONU_LIBRARY set as the console unit.

   *  Set the console device base address variable to point to the device
      library vector which is returned in io_Device.

   *  Call the console device function(s).

   *  Close the console device when you are finished.

   #include <devices/conunit.h>
   struct ConsoleDevice *ConsoleDevice;  /* declare device base address */

   struct IOStdReq ConsIO= {0};          /* I/O request */

   main()

       /* Open the device with CONU_LIBRARY for function use */
   if (0 == OpenDevice("console.device",CONU_LIBRARY,
                      (struct IORequest *)&ConsIO,0) )
       {
       /* Set the base address variable to the device library vector */
       ConsoleDevice = (struct ConsoleDevice *)ConsIO.io_Device;

                     .
                     .    (console device functions would be called here)
                     .

       CloseDevice(ConsIO);
       }

The code fragment shows only the steps outlined above, it is not complete
in any sense of the word.  For a complete example of using a console
device function, see the rawkey.c code example in the
"Intuition: Mouse and Keyboard" chapter of the Amiga ROM Kernel Reference
Manual: Libraries.  The example uses the RawKeyConvert() function.

To use the commands with the CONU_LIBRARY console unit, you follow the
same steps that were outlined in the Opening the Console Device section of
this chapter.

   struct MsgPort *ConsoleMP;       /* pointer to our message port */
   struct IOStdReq *ConsoleIO;      /* pointer to our I/O request */
   struct KeyMap  *keymap;          /* pointer to keymap */

       /* Create the message port */
   if (ConsoleMP=CreateMsgPort())
       {
           /* Create the I/O request */
       if (ConsoleIO = CreateIORequest(ConsoleMP,sizeof(struct IOStdReq)))
           {
               /* Open the Console device */
           if (OpenDevice("console.device",CONU_LIBRARY,
                         (struct IORequest *)ConsoleIO,0L))

               /* Inform user that it could not be opened */
               printf("Error: console.device did not open\n");
           else
               {
                  /* Allocate memory for the keymap */
               if (keymap = (struct KeyMap *)
                  AllocMem(sizeof(struct KeyMap),MEMF_PUBLIC | MEMF_CLEAR))
                  {
                  /* device opened, send CD_ASKKEYMAP command to it */
                  ConsoleIO->io_Length = sizeof(struct KeyMap);
                  ConsoleIO->io_Data = (APTR)keymap; /* where to put it */
                  ConsoleIO->io_Command = CD_ASKKEYMAP;
                  DoIO((struct IORequest *)ConsoleIO))
                  }

               CloseDevice(ConsIO);
               }

Again, as in the previous code fragment, this is not complete (that's why
it's a fragment!) and you should only use it as a guide.


4 Console Device / Where Is All the Keymap Information?

Unlike previous editions of this chapter, this one has a very small amount
of keymap information.  Keymap information is now contained,
appropriately enough, in the "Keymap Library" chapter of the
Amiga ROM Kernel Reference Manual: Libraries.


4 Console Device / Console Device Caveats

   *  Only one console unit can be attached per window.  Sharing a console
      window must be done at a level higher than the device.

   *  Do not mix graphics.library calls with console rendering in the same
      areas of a window.  It is permissible to send console sequences to
      adjust the area in which console renders, and use graphics.library
      calls to render outside of the area console is using.

For example, do not render text with console sequences and scroll using
the graphics.library ScrollRaster() function.

   *  The character map feature is private and cannot be accessed by the
      programmer.  Implementation details and behaviors of the character
      map my change in the future.

   *  Do not use an IDCMP with character mapped consoles.  All Intuition
      messages should be obtained via RAW INPUT EVENTS from the console
      device.


4 Console Device / Additional Information on the Console Device

Additional programming information on the console device can be found in
the include files and the Autodocs for the console device.  Both are
contained in the Amiga ROM Kernel Reference Manual: Includes and Autodocs.

                     Console Device Information
                  ---------------------------------
                  INCLUDES        devices/console.h
                                  devices/console.i
                                  devices/conunit.h
                                  devices/conunit.h

                  AUTODOCS        console.doc


Amiga® RKM Devices: 12 Serial Device

The serial device provides a hardware-independent interface to the Amiga's
built-in RS-232C compatible serial port.  Serial ports have a wide range
of uses, including communication with modems, printers, MIDI devices, and
other computers.  The same device interface can be used for additional
"byte stream oriented devices" - usually more serial ports.  The serial
device is based on the conventions of Exec device I/O, with extensions for
parameter setting and control.

                   Serial Device Characteristics
                   -----------------------------
                   MODES           Exclusive
                                   Shared Access

                   BAUD RATES      110-292,000

                   HANDSHAKING     Three-Wire
                                   Seven-Wire

 Serial Device Commands and Functions
 Device Interface
 A Simple Serial Port Example
 Alternative Modes for Serial Input or Output
 Setting Serial Parameters (SDCMD_SETPARAMS)
 Querying the Serial Device
 Sending the Break Command
 Error Codes from the Serial Device
 Multiple Serial Port Support
 Taking Over the Hardware
 Advanced Example of Serial Device Usage
 Additional Information on the Serial Device


12 Serial Device / Serial Device Commands and Functions

Device Command   Operation
--------------   ---------
CMD_CLEAR        Reset the serial port's read buffer pointers.

CMD_FLUSH        Purge all queued requests for the serial device (does not
                 affect active requests).

CMD_READ         Read a stream of characters from the serial port buffer.
                 The number of characters can be specified or a
                 termination character(s) used.

CMD_RESET        Reset the serial port to its initialized state.  All
                 active and queued I/O requests will be aborted and the
                 current buffer will be released.

CMD_START        Restart all paused I/O over the serial port.  Also sends
                 an "xON".

CMD_STOP         Pause all active I/O over the serial port.  Also sends an
                 "xOFF".

CMD_WRITE        Write out a stream of characters to the serial port.  The
                 number of characters can be specified or a
                 NULL-terminated string can be sent.

SDCMD_BREAK      Send a break signal out the serial port.  May be done
                 immediately or queued. Duration of the break (in
                 microseconds) can be set by the application.

SDCMD_QUERY      Return the status of the serial port lines and registers,
                 and the number of bytes in the serial port's read buffer.

SDCMD_SETPARAMS  Set the parameters of the serial port.  This ranges from
                 baud rate to number of microseconds a break will last.

Exec Functions as Used in This Chapter
--------------------------------------
AbortIO()        Abort a command to the serial device. If the command is
                 in progress, it is stopped immediately.  If it is queued,
                 it is removed from the queue.

BeginIO()         Initiate a command and return immediately (asynchronous
                 request).  This is used to minimize the amount of system
                 overhead.

CheckIO()        Determine the current state of an I/O request.

CloseDevice()    Relinquish use of the serial device.  All requests must
                 be complete.

DoIO()           Initiate a command and wait for completion (synchronous
                 request).

OpenDevice()     Obtain use of the serial device.

SendIO()         Initiate a command and return immediately (asynchronous
                 request).

WaitIO()         Wait for the completion of an asynchronous request. When
                 the request is complete the message will be removed from
                 your reply port.

Exec Support Functions as Used in This Chapter
----------------------------------------------
CreateExtIO()    Create an extended I/O request structure of type
                 IOExtSer.  This structure will be used to communicate
                 commands to the serial device.

CreatePort()     Create a signal message port for reply messages from the
                 serial device.  Exec will signal a task when a message
                 arrives at the port.

DeleteExtIO()    Delete an extended I/O request structure created by
                 CreateExtIO().

DeletePort()     Delete the message port created by CreatePort().


12 Serial Device / Device Interface

The serial device operates like the other Amiga devices.  To use it, you
must first open the serial device, then send I/O requests to it, and then
close it when finished.  See the "Introduction to Amiga System Devices"
chapter for general information on device usage.

The I/O request used by the serial device is called IOExtSer.

    struct IOExtSer
       {
        struct   IOStdReq IOSer;
        ULONG    io_CtlChar;    /* control characters */
        ULONG    io_RBufLen;    /* length in bytes of serial read buffer */
        ULONG    io_ExtFlags;   /* additional serial flags */
        ULONG    io_Baud;       /* baud rate */
        ULONG    io_BrkTime;    /* duration of break in microseconds */
        struct   iOTArray  io_TermArray;  /* termination character array */
        UBYTE    io_ReadLen;    /* number of bits per read character */
        UBYTE    io_WriteLen;   /* number of bits per write character */
        UBYTE    io_StopBits;   /* number of stopbits for read */
        UBYTE    io_SerFlags;   /* serial device flags */
        UWORD    io_Status;     /* status of serial port and lines */
    };

See the include file devices/serial.h for the complete structure
definition.

 Opening The Serial Device 		 Writing To The Serial Device
 Reading From The Serial Device 	 Closing The Serial Device


12 / Device Interface / Opening The Serial Device

Three primary steps are required to open the serial device:

   *  Create a message port using CreatePort(). Reply messages from the
      device must be directed to a message port.

   *  Create an extended I/O request structure of type IOExtSer using
      CreateExtIO(). CreateExtIO() will initialize the I/O request to point
      to your reply port.

   *  Open the serial device.  Call OpenDevice(), passing the I/O request.

   struct MsgPort  *SerialMP;          /* Define storage for one pointer */
   struct IOExtSer *SerialIO;         /* Define storage for one pointer */

   if (SerialMP=CreatePort(0,0) )
       if (SerialIO=(struct IOExtSer *)
              CreateExtIO(SerialMP,sizeof(struct IOExtSer)) )
           SerialIO->io_SerFlags=SERF_SHARED;  /* Turn on SHARED mode */
           if (OpenDevice(SERIALNAME,0L,(struct IORequest *)SerialIO,0) )
               printf("%s did not open\n",SERIALNAME);

During the open, the serial device pays attention to a subset of the flags
in the io_SerFlags field.  The flag bits, SERF_SHARED and SERF_7WIRE, must
be set before open.  For consistency, the other flag bits should also be
properly set.  Full descriptions of all flags will be given later.

The serial device automatically fills in default settings for all
parameters - stop bits, parity, baud rate, etc.  For the default unit, the
settings will come from Preferences.  You may need to change certain
parameters, such as the baud rate, to match your requirements. Once the
serial device is opened, all characters received will be buffered, even if
there is no current request for them.


12 / Device Interface / Reading From The Serial Device

You read from the serial device by passing an IOExtSer to the device with
CMD_READ set in io_Command, the number of bytes to be read set in
io_Length and the address of the read buffer set in io_Data.

   #define READ_BUFFER_SIZE 256
   char SerialReadBuffer[READ_BUFFER_SIZE]; /* Reserve SIZE bytes */

   SerialIO->IOSer.io_Length   = READ_BUFFER_SIZE;
   SerialIO->IOSer.io_Data     = (APTR)&SerialReadBuffer[0];
   SerialIO->IOSer.io_Command  = CMD_READ;
   DoIO((struct IORequest *)SerialIO);

If you use this example, your task will be put to sleep waiting until the
serial device reads 256 bytes (or terminates early).  Early termination
can be caused by error conditions such as a break.  The number of
characters actually received will be recorded in the io_Actual field of the
IOExtSer structure you passed to the serial device.


12 / Device Interface / Writing To The Serial Device

You write to the serial device by passing an IOExtSer to the device with
CMD_WRITE set in io_Command, the number of bytes to be written set in
io_Length and the address of the write buffer set in io_Data.

To write a NULL-terminated string, set the length to -1; the device will
output from your buffer until it encounters and transmits a value of zero
(0x00).

   SerialIO->IOSer.io_Length   = -1;
   SerialIO->IOSer.io_Data     = (APTR)"Life is but a dream. ";
   SerialIO->IOSer.io_Command  = CMD_WRITE;
   DoIO((struct IORequest *)SerialIO);             /* execute write */

The length of the request is -1, meaning we are writing a NULL-terminated
string. The number of characters sent can be found in io_Actual.


12 / Device Interface / Closing The Serial Device

Each OpenDevice() must eventually be matched by a call to CloseDevice().
When the last close is performed, the device will deallocate all resources
and buffers.

All IORequests must be complete before CloseDevice().  Abort any pending
requests with AbortIO().

   if (!(CheckIO(SerialIO)))
       {
       AbortIO((struct IORequest *)SerialIO); /* Ask device to abort */
       }			              /*   request, if pending */
   WaitIO((struct IORequest *)SerialIO);      /* Wait for abort, then */
   CloseDevice((struct IORequest *)SerialIO); /*  clean up */


12 Serial Device / Alternative Modes for Serial Input or Output

As an alternative to DoIO() you can use an asynchronous I/O request to
transmit the command.  Asynchronous requests are initiated with SendIO().
Your task can continue to execute while the device processes the command.
You can occasionally do a CheckIO() to see if the I/O has completed.  The
write request in this example will be processed while the example
continues to run:

    SerialIO->IOSer.io_Length   = -1;
    SerialIO->IOSer.io_Data     = (APTR)"Save the whales! ";
    SerialIO->IOSer.io_Command  = CMD_WRITE;
    SendIO((struct IORequest *)SerialIO);

    printf("CheckIO %lx\n",CheckIO((struct IORequest *)SerialIO));
    printf("The device will process the request in the background\n");
    printf("CheckIO %lx\n",CheckIO((struct IORequest *)SerialIO));
    WaitIO((struct IORequest *)SerialIO);  /* Remove message and cleanup */

Most applications will want to wait on multiple signals.  A typical
application will wait for menu messages from Intuition at the same time as
replies from the serial device.  The following fragment demonstrates
waiting for one of three signals.  The Wait() will wake up if the read
request ever finishes, or if the user presses Ctrl-C or Ctrl-F from the
Shell.  This fragment may be inserted into the above complete example.

    /* Precalculate a wait mask for the CTRL-C, CTRL-F and message
     * port signals.  When one or more signals are received,
     * Wait() will return.  Press CTRL-C to exit the example.
     * Press CTRL-F to wake up the example without doing anything.
     * NOTE: A signal may show up without an associated message!
     */

    WaitMask = SIGBREAKF_CTRL_C|
                SIGBREAKF_CTRL_F|
                 1L << SerialMP->mp_SigBit;

    SerialIO->IOSer.io_Command  = CMD_READ;
    SerialIO->IOSer.io_Length   = READ_BUFFER_SIZE;
    SerialIO->IOSer.io_Data     = (APTR)&SerialReadBuffer[0];
    SendIO(SerialIO);

    printf("Sleeping until CTRL-C, CTRL-F, or serial input\n");

    while (1)
           {
           Temp = Wait(WaitMask);
           printf("Just woke up (YAWN!)\n");

           if (SIGBREAKF_CTRL_C & Temp)
               break;

           if (CheckIO(SerialIO) ) /* If request is complete... */
               {
               WaitIO(SerialIO);   /* clean up and remove reply */
               printf("%ld bytes received\n",SerialIO->IOSer.io_Actual);
               break;
               }
           }
    AbortIO(SerialIO);  /* Ask device to abort request, if pending */
    WaitIO(SerialIO);   /* Wait for abort, then clean up */

   WaitIO() vs. Remove().
   ----------------------
   The WaitIO() function is used above, even if the request is already
   known to be complete.  WaitIO() on a completed request simply removes
   the reply and cleans up.  The Remove() function is not acceptable for
   clearing the reply port; other messages may arrive while the function
   is executing.

 High Speed Operation
 Use Of BeginIO() With The Serial Device
 Ending A Read Or Write Using Termination Characters
 Using Separate Read And Write Tasks


12 / Alternative Modes for Serial Input or Output / High Speed Operation

The more characters that are processed in each I/O request, the higher the
total throughput of the device.  The following technique will minimize
device overhead for reads:

   *  Use the SDCMD_QUERY command to get the number of characters currently
      in the buffer (see the devices/serial.h Autodocs for information on
      SDCMD_QUERY).

   *  Use DoIO() to read all available characters (or the maximum size of
      your buffer).  In this case, DoIO() is guaranteed to return without
      waiting.

   *  If zero characters are in the buffer, post an asynchronous request
      (SendIO()) for 1 character.  When at least one is ready, the device
      will return it.  Now go back to the first step.

   *  If the user decides to quit the program, AbortIO() any pending
      requests.


12 / / Use Of BeginIO() With The Serial Device

Instead of transmitting the read command with either DoIO() or SendIO(),
you might elect to use the low level BeginIO() interface to a device.

BeginIO() works much like SendIO(), i.e., asynchronously, except it gives
you control over the quick I/O bit (IOB_QUICK) in the io_Flags field.
Quick I/O saves the overhead of a reply message, and perhaps the overhead
of a task switch. If a quick I/O request is actually completed quickly,
the entire command will execute in the context of the caller. See the
"Exec: Device Input/Output" chapter of the Amiga ROM Kernel Reference
Manual: Libraries for more detailed information on quick I/O.

The device will determine if a quick I/O request will be handled quickly.
Most non-I/O commands will execute quickly; read and write commands may or
may not finish quickly.

   SerialIO.IOSer.io_Flags |= IOF_QUICK;  /* Set QuickIO Flag */

   BeginIO((struct IORequest *)SerialIO);
   if (SerialIO->IOSer.io_Flags & IOF_QUICK )
       /* If flag is still set, I/O was synchronous and is now finished.
        * The IORequest was NOT appended a reply port.  There is no
        * need to remove or WaitIO() for the message.
        */
       printf("QuickIO\n");
   else
        /* The device cleared the QuickIO bit.  QuickIO could not happen
         * for some reason; the device processed the command normally.
         * In this case BeginIO() acted exactly like SendIO().
         */
        printf("Regular I/O\n");
   WaitIO(SerialIO);

The way you read from the device depends on your need for processing
speed. Generally the BeginIO() route provides the lowest system overhead
when quick I/O is possible.  However, if quick I/O does not work, the same
reply message overhead still exists.


12 / / Ending A Read Or Write Using Termination Characters

Reads and writes from the serial device may terminate early if an error
occurs or if an end-of-file (EOF) is sensed.  For example, if a break is
detected on the line, any current read request will be returned with the
error SerErr_DetectedBreak.  The count of characters read to that point
will be in the io_Actual field of the request.

You can specify a set of possible end-of-file characters that the serial
device is to look for in the input stream  or output using the
SDCDMD_SETPARAMS command. These are contained in an io_TermArray that you
provide. io_TermArray is used only when the SERF_EOFMODE flag is selected
(see the Serial Flags section below).

If EOF mode is selected, each input data character read into or written
from the user's data block is compared against those in io_TermArray. If a
match is found, the IOExtSer is terminated as complete, and the count of
characters transferred (including the termination character) is stored in
io_Actual.

To keep this search overhead as efficient as possible, the serial device
requires that the array of characters be in descending order. The array
has eight bytes and all must be valid (that is, do not pad with zeros
unless zero is a valid EOF character). Fill to the end of the array with
the lowest value termination character. When making an arbitrary choice of
EOF character(s), you will get the quickest response from the lowest
value(s) available.

     Terminate_Serial.c

The read will terminate before the io_Length number of characters
is read if a "Q", "E", ETX, or EOT is detected in the serial input stream.


12 / / Using Separate Read And Write Tasks

In some cases there are advantages to creating a separate IOExtSer for
reading and writing.  This allows simultaneous operation of both reading
and writing.  Some users of the device have separate tasks for read and
write operations. The sample code below creates a separate reply port and
request for writing to the serial device.

struct IOExtSer *SerialWriteIO;
struct MsgPort  *SerialWriteMP;

/*
 * If two tasks will use the same device at the same time, it is
 * preferred use two OpenDevice() calls and SHARED mode.  If exclusive
 * access mode is required, then you will need to copy an existing
 * IORequest.
 * Remember that two separate tasks will require two message ports.
 */

SerialWriteMP = CreatePort(0,0);
SerialWriteIO = (struct IOExtSer *)
                CreateExtIO( SerialWriteMP,sizeof(struct IOExtSer) );

if (SerialWriteMP && SerialWriteIO )
    {

    /* Copy over the entire old IO request, then stuff the
     * new Message port pointer.
     */

    CopyMem( SerialIO, SerialWriteIO, sizeof(struct IOExtSer) );
    SerialWriteIO->IOSer.io_Message.mn_ReplyPort = SerialWriteMP;

    SerialWriteIO->IOSer.io_Command  = CMD_WRITE;
    SerialWriteIO->IOSer.io_Length = -1;
    SerialWriteIO->IOSer.io_Data = (APTR)"A poet's food is love and fame";
    DoIO(SerialWriteIO);
    }

   Where's OpenDevice()?
   ---------------------
   This code assumes that the OpenDevice() function has already been
   called.  The initialized read request block is copied onto the new
   write request block.


12 Serial Device / Setting Serial Parameters (SDCMD_SETPARAMS)

When the serial device is opened, default values for baud rate and other
parameters are automatically filled in from the serial settings in
Preferences.  The parameters may be changed by using the
SDCMD_SETPARAMS command.  The flags are defined in the include file
devices/serial.h.

                   SERIAL DEVICE PARAMETERS (IOExtSer)

   IOExtSer
   Field Name   Serial Device Parameter It Controls
   ---------    -----------------------------------
   io_CtlChar   Control characters to use for xON, xOFF,
                INQ, ACK respectively.  Positioned within an unsigned
                longword in the sequence from low address to high as
                listed.  INQ and ACK handshaking is not currently
                supported.

   io_RBufLen   Recommended size of the buffer that the serial device
                should allocate for incoming data.  For some hardware the
                buffer size will not be adjustable.  Changing the value
                may cause the device to allocate a new buffer, which might
                fail due to lack of memory. In this case the old buffer
                will continue to be used.

                For the built-in unit, the minimum size is 64 bytes.
                Out-of-range numbers will be truncated by the device.
                When you do an SDCMD_SETPARAMS command, the driver senses
                the difference between its current value and the value of
                buffer size you request.  All characters that may already
                be in the old buffer will be discarded.  Thus it is wise
                to make sure that you do not attempt buffer size changes
                (or any change to the serial device, for that matter)
                while any I/O is actually taking place.

   io_ExtFlags  An unsigned long that contains the flags SEXTF_MSPON and
                SEXTF_MARK.  SEXTF_MSPON enables either mark or space
                parity.  SEXTF_MARK selects mark parity (instead of space
                parity).  Unused bits are reserved.

   io_Baud      The real baud rate you request.  This is an unsigned long
                value in the range of 1 to 4,294,967,295.  The device will
                reject your baud request if the hardware is unable to
                support it.

                For the built-in driver, any baud rate in the range of 110
                to about 1 megabaud is acceptable.  The built-in driver
                may round 110 baud requests to 112 baud. Although baud
                rates above 19,200 are supported by the hardware, software
                overhead will limit your ability to "catch" every single
                character that should be received.  Output data rate,
                however, is not software-dependent.

   io_BrkTime   If you issue a break command, this variable specifies how
                long, in microseconds, the break condition lasts.  This
                value controls the break time for all future break
                commands until modified by another SDCMD_SETPARAMS.

   io_TermArray A byte-array of eight termination characters, must be in
                descending order.  If the EOFMODE bit is set in the serial
                flags, this array specifies eight possible choices of
                character to use as an end of file mark.  See the section
                above "Ending a Read Or Write Using Termination Characters"
                and the SDCMD_SETPARAMS summary page in the Autodocs.

   io_ReadLen   How many bits per read character; typically a value of 7
                or 8.  Generally must be the same as io_WriteLen.

   io_WriteLen  How many bits per write character; typically a value of 7
                or 8.  Generally must be the same as io_ReadLen.

   io_StopBits  How many stop bits are to be expected when reading a
                character and to be produced when writing a character;
                typically 1 or 2. The built-in driver does not allow
                values above 1 if io_WriteLen is larger than 7.

 io_SerFlags    See the "Serial Flags" section below.

 io_Status      Contains status information filled in by the SDCMD_QUERY
                command.  Break status is cleared by the execution of
                SDCMD_QUERY.

You set the serial parameters by passing an IOExtSer to the device with
SDCMD_SETPARAMS set in io_Command and with the flags and parameters set to
the values you want.

  SerialIO->io_SerFlags      &= ~SERF_PARTY_ON; /* set parity off */
  SerialIO->io_SerFlags      |= SERF_XDISABLED; /* set xON/xOFF disabled */
  SerialIO->io_Baud           = 9600;           /* set 9600 baud */
  SerialIO->IOSer.io_Command  = SDCMD_SETPARAMS;/* Set params command */
  if (DoIO((struct IORequest *)SerialIO))
      printf("Error setting parameters!\n");

The above fragment modifies two bits in io_SerFlags and changes the baud
rate. If the parameters you request are unacceptable or out of range, the
SDCMD_SETPARAMS command will fail.  You are responsible for checking the
error code and informing the user.

   Proper Time for Parameter Changes.
   ----------------------------------
   A parameter change should not be performed while an I/O request is
   actually being processed because it might invalidate the request
   handling already in progress.  To avoid this, you should use
   SDCMD_SETPARAMS only when you have no serial I/O requests pending.

 Serial Flags (Bit Definitions For io_SerFlags)


12 / Setting Serial Parameters / Serial Flags (Bits For io_SerFlags)

There are additional serial device parameters which are controlled by
flags set in the io_SerFlags field of the IOExtSer structure.  The default
state of all of these flags is zero. SERF_SHARED and SERF_7WIRE must
always be set before OpenDevice(). The flags are defined in the include
file serial.h.

                        SERIAL FLAGS (IO_SERFLAGS)

   Flag Name            Effect on Device Operation
   --------             ---------------------------
   SERF_XDISABLED       Disable the XON/XOFF feature.  XON/XOFF must be
                        disabled during XModem transfers.

   SERF_EOFMODE         Set this bit if you want the serial device to
                        check input characters against io_TermArray and to
                        terminate the read immediately if an end-of-file
                        character has been encountered. Note:  this bit
                        may be set and reset directly in the user's
                        IOExtSer without a call to SDCMD_SETPARAMS.

   SERF_SHARED          Set this bit if you want to allow other tasks to
                        simultaneously access the serial port.  The
                        default is exclusive-access. Any number of tasks
                        may have shared access. Only one task may have
                        exclusive access.  If someone already has the port
                        for exclusive access, your OpenDevice() call will
                        fail. This flag must be set before OpenDevice().

   SERF_RAD_BOOGIE      If set, this bit activates high-speed mode.
                        Certain peripheral devices (MIDI, for example)
                        require high serial throughput.  Setting this bit
                        high causes the serial device to skip certain of
                        its internal checking code to speed throughput.
                        Use SERF_RAD_BOOGIE only when you have:

                        *  Disabled parity checking
                        *  Disabled XON/XOFF handling
                        *  Use 8-bit character length
                        *  Do not wish a test for a break signal

                        Note that the Amiga is a multitasking system and
                        has immediate processing of software interrupts.
                        If there are other tasks running, it is possible
                        that the serial driver may be unable to keep up
                        with high data transfer rates, even with this bit
                        set.

   SERF_QUEUEDBRK       If set, every break command that you transmit will
                        be enqueued. This means that all commands will be
                        executed on a FIFO (first in, first out) basis.

                        If this bit is cleared (the default), a break
                        command takes immediate precedence over any serial
                        output already enqueued. When the break command
                        has finished, the interrupted request will
                        continue (if not aborted by the user).

   SERF_7WIRE           If set at OpenDevice() time, the serial device
                        will use seven-wire handshaking for RS-232-C
                        communications. Default is three-wire (pins 2, 3,
                        and 7).

   SERF_PARTY_ODD       If set, selects odd parity.  If clear, selects
                        even parity.

   SERF_PARTY_ON        If set, parity usage and checking is enabled. Also
                        see the SERF_MSPON bit described under io_ExtFlags
                        above.


12 Serial Device / Querying the Serial Device

You query the serial device by passing an IOExtSer to the device with
SDCMD_QUERY set in io_Command.  The serial device will respond with the
status of the serial port lines and registers, and the number of unread
characters in the read buffer.

   UWORD Serial_Status;
   ULONG Unread_Chars;

   SerialIO->IOSer.io_Command  = SDCMD_QUERY; /* indicate query */
   SendIO((struct IORequest *)SerialIO);

   Serial_Status = SerialIO->io_Status; /* store returned status */
   Unread_Chars = SerialIO->IOSer.io_Actual; /* store unread count */

The 16 status bits of the serial device are returned in io_Status; the
number of unread characters is returned in io_Actual.

                       SERIAL DEVICE STATUS BITS

         Bit     Active     Symbol      Function
         ---     ------     ------      --------
          0        -                    Reserved
          1        -                    Reserved
          2      high       (RI)        Parallel Select on the A1000.  On
                                        the A500 and A2000, Select is also
                                        connected to the serial port's
                                        Ring Indicator.  (Be cautious when
                                        making cables.)

          3      low        (DSR)       Data set ready
          4      low        (CTS)       Clear to send
          5      low        (CD)        Carrier detect
          6      low        (RTS)       Ready to send
          7      low        (DTR)       Data terminal ready
          8      high                   Read overrun
          9      high                   Break sent
          10     high                   Break received
          11     high                   Transmit x-OFFed
          12     high                   Receive x-OFFed
          13-15    -                    (reserved)


12 Serial Device / Sending the Break Command

You send a break through the serial device by passing an IOExtSer to the
device with SDCMD_BREAK set in io_Command.  The break may be immediate or
queued.  The choice is determined by the state of flag SERF_QUEUEDBRK in
io_SerFlags.

   SerialIO->IOSer.io_Command  = SDCMD_BREAK; /* send break */
   SendIO((struct IORequest *)SerialIO);

The duration of the break (in microseconds) can be set in io_BrkTime. The
default is 250,000 microseconds (.25 seconds).


12 Serial Device / Error Codes from the Serial Device

The serial device returns error codes whenever an operation is attempted.

   SerialIO->IOSer.io_Command  = SDCMD_SETPARAMS; /* Set parameters */
   if (DoIO((struct IORequest *)SerialIO))
       printf("Set Params failed. Error: %ld ",SerialIO->IOSer.io_Error);

The error is returned in the io_Error field of the IOExtSer structure.

                    SERIAL DEVICE ERROR CODES

    Error                   Value    Explanation
    -----                   -----    ----------
    SerErr_DevBusy          1        Device in use
    SerErr_BaudMismatch     2        Baud rate not supported by hardware
    SerErr_BufErr           4        Failed to allocate new read buffer
    SerErr_InvParam         5        Bad parameter
    SerErr_LineErr          6        Hardware data overrun
    SerErr_ParityErr        9        Parity error
    SerErr_TimerErr         11       Timeout (if using 7-wire handshaking)
    SerErr_BufOverflow      12       Read buffer overflowed
    SerErr_NoDSR            13       No Data Set Ready
    SerErr_DetectedBreak    15       Break detected
    SerErr_UnitBusy         16       Selected unit already in use


12 Serial Device / Multiple Serial Port Support

Applications that use the serial port should provide the user with a means
to select the name and unit number of the driver.  The defaults will be
"serial.device" and unit number 0.  Typically unit 0 refers to the
user-selected default.  Unit 1 refers to the built-in serial port.
Numbers above 1 are for extended units.  The physically lowest connector
on a board will always have the lowest unit number.

Careful attention to error handling is required to survive in a multiple
port environment.  Differing serial hardware will have different
capabilities.  The device will refuse to open non-existent unit numbers
(symbolic name mapping of unit numbers is not provided at the device
level). The SDCMD_SETPARAMS command will fail if the underlying hardware
cannot support your parameters.  Some devices may use quick I/O for read
or write requests, others will not.  Watch out for partially completed
read requests; io_Actual may not match your requested read length.

If the Tool Types mechanism is used for selecting the device and unit, the
defaults of "DEVICE=serial.device" and "UNIT=0" should be provided.
The user should be able to permanently set the device and unit in a
configuration file.


12 Serial Device / Taking Over the Hardware

For some applications use of the device driver interface is not possible.
By following the established rules, applications may take over the serial
interface at the hardware level.  This extreme step is not, however,
encouraged.  Taking over means losing the ability to work with additional
serial ports, and will limit future compatibility.

Access to the hardware registers is controlled by the misc.resource. See
the "Resources" chapter, and exec/misc.i for details.  The MR_SERIALBITS
and MR_SERIALPORT units control the serial registers.

One additional complication exists.  The current serial device will not
release the misc.resource bits until after an expunge.  This code provides
a work around:

   /*
   * A safe way to expunge ONLY a certain device.
   * This code attempts to flush ONLY the named device out of memory and
   * nothing else.  If it fails, no status is returned (the information
   * would have no valid use after the Permit().
   */
   #include <exec/types.h>
   #include <exec/execbase.h>

   void FlushDevice(char *);

   extern struct ExecBase *SysBase;

   void FlushDevice(name)
   char  *name;
   {
   struct Device *devpoint;

   Forbid();   /* ugly */
   if (devpoint = (struct Device *)FindName(&SysBase->DeviceList,name) )
       RemDevice(devpoint);
   Permit();
   }


12 Serial Device / Additional Information on the Serial Device

Additional programming information on the serial device can be found in
the include files and the Autodocs for the serial device.  Both are
contained in the Amiga ROM Kernel Reference Manual: Includes and Autodocs.

                        Serial Device Information
                    --------------------------------
                    INCLUDES        devices/serial.h
                                    devices/serial.i

                    AUTODOCS        serial.doc


Amiga® RKM Devices: 5 Gameport Device

The gameport device manages access to the Amiga gameport connectors for
the operating system.  It enables the Amiga to interface with various
external pointing devices like mice (two and three button), joysticks,
trackballs and light pens.  There are two units in the gameport device,
unit 0 and unit 1.

                       AMIGA GAMEPORT CONNECTORS

                Model       Unit 0              Unit 1
                -----   ---------------     --------------
                A3000   Front Connector     Back Connector
                A2000   Left Connector      Right Connector
                A1000   1                   2
                A500    1 JOYSTICK          2 JOYSTICK

 Gameport Device Commands and Functions
 Device Interface
 Gameport Events
 Setting and Reading the Controller Type
 Joystick Example Program
 Additional Information on the Gameport Device


5 Gameport Device / Gameport Device Commands and Functions

Command         Operation
-------         ---------
CMD_CLEAR       Clear the gameport input buffer.

GPD_ASKCTYPE    Return the type of gameport controller being used.

GPD_ASKTRIGGER  Return the conditions that have been preset for triggering.

GPD_READEVENT   Read one or more gameport events.

GPD_SETCTYPE    Set the type of the controller to be used.

GPD_SETTRIGGER  Preset the conditions that will trigger a gameport event.

Exec Functions as Used in This Chapter
--------------------------------------
AbortIO()       Abort a command to the gameport device.

CheckIO()       Return the status of an I/O request.

CloseDevice()   Relinquish use of the gameport device.  All requests must
                be complete before closing.

DoIO()          Initiate a command and wait for completion (synchronous
                request).

OpenDevice()    Obtain shared use of one unit of the gameport device. The
                unit number specified is placed in the I/O request
                structure for use by gameport commands.

SendIO()        Initiate a command and return immediately (asynchronous
                request).

WaitIO()        Wait for the completion of an asynchronous request.  When
                the request is complete the message will be removed from
                reply port.

Exec Support Functions as Used in This Chapter
----------------------------------------------
CreateExtIO()   Create an extended I/O request structure of type IOStdReq.
                This structure will be used to communicate commands to the
                gameport device.

CreatePort()    Create a signal message port for reply messages from the
                gameport device.  Exec will signal a task when a message
                arrives at the port.

DeleteExtIO()   Delete an I/O request structure created by CreateExtIO().

DeletePort()    Delete the message port created by CreatePort().

   Who Runs The Mouse?
   -------------------
   When the input device or Intution is operating, unit 0 is usually
   dedicated to gathering mouse events.  The input device uses the
   gameport device to read the mouse events.  (For applications that
   take over the machine without starting up the input device or
   Intuition, unit 0 can perform the same functions as unit 1.)  See the
   "Input Device" chapter for more information on the input device.


5 Gameport Device / Device Interface

The gameport device operates like the other Amiga devices.  To use it, you
must first open the gameport device, then send I/O requests to it, and
then close it when finished. See the "Introduction to Amiga System Devices"
chapter for general information on device usage.

The I/O request used by the gameport device is called IOStdReq.

    struct IOStdReq
    {
        struct  Message io_Message;
        struct  Device  *io_Device; /* device node pointer  */
        struct  Unit    *io_Unit; /* unit (driver private)*/
        UWORD   io_Command;       /* device command */
        UBYTE   io_Flags;
        BYTE    io_Error;         /* error or warning num */
        ULONG   io_Actual;        /* actual number of bytes transferred */
        ULONG   io_Length;        /* requested number bytes transferred*/
        APTR    io_Data;          /* points to data area */
        ULONG   io_Offset;        /* offset for block structured devices */
    };

See the include file exec/io.h for the complete structure definition.

 Opening The Gameport Device
 Gameport Device Controllers
 Closing The Gameport Device


5 / Device Interface / Opening The Gameport Device

Three primary steps are required to open the gameport device:

   *  Create a message port using CreatePort(). Reply messages from the
      device must be directed to a message port.

   *  Create an I/O request structure of type IOStdReq. The IOStdReq
      structure is created by the CreateExtIO() function. CreateExtIO()
      will initialize the I/O request with your reply port.

   *  Open the gameport device.  Call OpenDevice(), passing the I/O request
      and and indicating the unit you wish to use.

   struct MsgPort *GameMP;   /* Message port pointer */
   struct IOStdReq *GameIO;  /* I/O request pointer */

     /* Create port for gameport device communications */
   if (!(GameMP = CreatePort("RKM_game_port",0)))
       cleanexit(" Error: Can't create port\n",RETURN_FAIL);

     /* Create message block for device I/O */
   if (!(GameIO = CreateExtIO(GameMP,sizeof(struct IOStdReq))))
       cleanexit(" Error: Can't create I/O request\n",RETURN_FAIL);

     /* Open the right/back (unit 1, number 2) gameport.device unit */
   if (error=OpenDevice("gameport.device",1,GameIO,0))
       cleanexit(" Error: Can't open gameport.device\n",RETURN_FAIL);

The gameport commands are unit specific.  The unit number specified in the
call to OpenDevice() determines which unit is acted upon.


5 / Device Interface / Gameport Device Controllers

The Amiga has five gameport device controller types.

                 GAMEPORT DEVICE CONTROLLERS

         Controller Type         Description
         ---------------         -----------
         GPCT_MOUSE              Mouse controller
         GPCT_ABSJOYSTICK        Absolute (digital) joystick
         GPCT_RELJOYSTICK        Relative (digital) joystick
         GPCT_ALLOCATED          Custom controller
         GPCT_NOCONTROLLER       No controller

To use the gameport device, you must define the type of device connected
to the gameport and define how the device is to respond. The gameport
device can be set up to return the controller status immediately or only
when certain conditions have been met.

When a gameport device unit reponds to a request for input, it creates an
input event. The contents of the input event will vary based on the type
of device and the trigger conditions you have declared.

   *  A mouse controller can report input events for one, two, or three
      buttons and for positive or negative (x,y) movements. A trackball
      controller or car-driving controller is generally of the same type
      and can be declared as a mouse controller.

   *  An absolute joystick reports one single event for each change of its
      current location. If, for example, the joystick is centered and the
      user pushes the stick forward and holds it in that position, only one
      single forward-switch event will be generated.

   *  A relative joystick, on the other hand, is comparable to an absolute
      joystick with "autorepeat" installed. As long as the user holds the
      stick in a position other than centered, the gameport device
      continues to generate position reports.

   *  There is currently no system software support for proportional
      joysticks or proportional controllers (e.g., paddles). If you write
      custom code to read proportional controllers or other controllers
      (e.g., light pen) make certain that you issue GPD_SETCTYPE (explained
      below) with controller type GPCT_ALLOCATED to insure that other
      applications know the connector is being used.

   GPCT_NOCONTROLLER.
   ------------------
   The controller type GPCT_NOCONTROLLER is not a controller at all, but
   a flag to indicate that the unit is not being used at the present
   time.


5 / Device Interface / Closing The Gameport Device

Each OpenDevice() must eventually be matched by a call to CloseDevice().

All I/O requests must be complete before CloseDevice().  If any requests
are still pending, abort them with AbortIO() and remove them with WaitIO().

    if (!(CheckIO(GameIO)))
        {
        AbortIO(GameIO);  /* Ask device to abort request, if pending */
        }
    WaitIO((GameIO);   /* Wait for abort, then clean up */
    CloseDevice(GameIO);


5 Gameport Device / Gameport Events

A gameport event is an InputEvent structure which describes the following:

   * The class of the event - always set to IECLASS_RAWMOUSE for the
     gameport device.

   * The subclass of the event - 0 for the left port; 1 for the right port.

   * The code - which button and its state.  (No report = 0xFF)

   * The qualifier - only button and relative mouse bits are set.

   * The position - either a data address or mouse position count.

   * The time stamp - delta time since last report, returned as frame
     count in tv_secs field.

   * The next event - pointer to next event.

    struct InputEvent GameEV
    {
        struct InputEvent *ie_NextEvent;  /* next event */
        UBYTE    ie_Class;                /* input event class */
        UBYTE    ie_SubClass;             /* subclass of the class */
        UWORD    ie_Code;                 /* input event code */
        UWORD    ie_Qualifier;            /* event qualifiers in effect */
           union
           {
             struct
             {
              WORD   ie_x;                /* x position for the event */
              WORD   ie_y;                /* y position for the event */
             }  ie_xy;
             APTR ie_addr;
           } ie_position;
        struct timeval ie_TimeStamp;      /* delta time since last report
    }

See the include file devices/inputevent.h for the complete structure
definition and listing of input event fields.

 Reading Gameport Events
 Setting Gameport Event Trigger Conditions
 Determining The Trigger Conditions


5 / Gameport Events / Reading Gameport Events

You read gameport events by passing an I/O request to the device with
GPD_READEVENT set in io_Command, the address of the InputEvent structure
to store events set in io_Data and the size of the structure set in
io_Length.

   struct InputEvent  GameEV;
   struct IOStdRequest *GameIO;  /* Must be initialized prior to using */

   void send_read_request()
   {
   GameIO->io_Command = GPD_READEVENT;  /* Read events */
   GameIO->io_Length = sizeof (struct InputEvent);
   GameIO->io_Data = (APTR)&GameEV;     /* put events in GameEV*/
   SendIO(GameIO);                      /* Asynchronous */
   }


5 / Gameport Events / Setting Gameport Event Trigger Conditions

You set the conditions that can trigger a gameport event by passing an I/O
request to the device with GPD_SETTRIGGER set in io_Command and the
address of a GamePortTrigger structure set in io_Data.

The information needed for gameport trigger setting is placed into a
GamePortTrigger data structure which is defined in the include file
devices/gameport.h.

    struct GamePortTrigger
    {
        UWORD    gpt_Keys;      /* key transition triggers */
        UWORD    gpt_Timeout;   /* time trigger (vertical blank units) */
        UWORD    gpt_XDelta;    /* X distance trigger */
        UWORD    gpt_YDelta;    /* Y distance trigger */
    }

A few points to keep in mind with the GPD_SETTRIGGER command are:

    *  Setting GPTF_UPKEYS enables the reporting of upward transitions.
       Setting GPTF_DOWNKEYS enables the reporting of downward transitions.
       These flags may both be specified.

    *  The field gpt_Timeout specifies the time interval (in vertical blank
       units) between reports in the absence of another trigger condition.
       In other words, an event is generated every gpt_Timeout ticks.
       Vertical blank units may differ from country to country (e.g 60 Hz
       NTSC, 50 Hz PAL.)  To find out the exact frequency use this code
       fragment:

       #include <exec/execbase.h>
       extern struct ExecBase *SysBase;

       UBYTE get_frequency(void)
       {
       return((UBYTE)SysBase->VBlankFrequency);
       }

    *  The gpt_XDelta and gpt_YDelta fields specify the x and y distances
       which, if exceeded, trigger a report.

For a mouse controller, you can trigger on a certain minimum-sized move in
either the x or y direction, on up or down transitions of the mouse
buttons, on a timed basis, or any combination of these conditions.

For example, suppose you normally signal mouse events if the mouse moves
at least 10 counts in either the x or y directions. If you are moving the
cursor to keep up with mouse movements and the user moves the mouse less
than 10 counts, after a period of time you will want to update the
position of the cursor to exactly match the mouse position. Thus the timed
report of current mouse counts would be preferred. The following structure
would be used:

    #define XMOVE 10
    #define YMOVE 10

    struct GamePortTrigger GameTR =
    {
        GPTF_UPKEYS | GPTF_DOWNKEYS, /* trigger on all key transitions */
        1800,                  /* and every 36(PAL) or 30(NTSC) seconds */
        XMOVE,                 /* for any 10 in an x or y direction */
        YMOVE
    };

For a joystick controller, you can select timed reports as well as
button-up and button-down report trigger conditions. For an absolute
joystick specify a value of one (1) for the GameTR_XDelta and
GameTR_YDelta fields or you will not get any direction events. You set the
trigger conditions by using the following code or its equivalent:

    struct IOStdReq *GameIO;

    void set_trigger_conditions(struct GamePortTrigger *GameTR)
    {
    GameIO->io_Command = GPD_SETTRIGGER;    /* set trigger conditions */
    GameIO->io_Data = (APTR)GameTR;         /* from GameTR */
    GameIO->io_Length = sizeof(struct GamePortTrigger);
    DoIO(GameIO);
    }

   Triggers and Reads.
   -------------------
   If a task sets trigger conditions and does not ask for the position
   reports the gameport device will queue them up anyway. If the trigger
   conditions occur again and the gameport device buffer is filled, the
   additional triggers will be ignored until the buffer is read by a
   device read request (GPD_READEVENT) or a system CMD_CLEAR command
   flushes the buffer.


5 / Gameport Events / Determining The Trigger Conditions

You determine the conditions required for triggering gameport events by
passing an I/O request to the device with GPD_ASKTRIGGER set in
io_Command, the length of the GamePortTrigger structure set in io_Length
and the address of the structure set in io_Data.  The gameport device will
respond with the event trigger conditions currently set.

    struct IOStdReq *GameIO;  /* Must be initialized prior to using */

    struct GamePortTrigger GameTR;

    void get_trigger_conditions(struct GamePortTrigger *GameTR)
    {
    GameIO->io_Command = GPD_ASKTRIGGER;    /* get type of triggers */
    GameIO->io_Data = (APTR)GameTR;         /* place data here */
    GameIO->io_Length= sizeof(GameTR);
    DoIO(GameIO);
    }


5 Gameport Device / Setting and Reading the Controller Type

 Determining The Controller Type
 Setting The Controller Type


5 / Setting and Reading Controller Type / Determining The Controller Type

You determine the type of controller being used by passing an I/O request
to the device with GPD_ASKCTYPE set in io_Command, 1 set in io_Length and
the number of the unit set in io_Unit. The gameport device will respond
with the type of controller being used.

   struct IOStdReq *GameIO;  /* Must be initialized prior to using */

   BYTE GetControllerType()
   {
   BYTE controller_type = 0;

   GameIO->io_Command = GPD_ASKCTYPE;         /* get type of controller */
   GameIO->io_Data = (APTR)&controller_type;  /* place data here */
   GameIO->io_Length = 1;
   DoIO(GameIO);
   return (controller_type);
   }

The BYTE value returned corresponds to one of the five controller types
noted above.


5 / Setting and Reading the Controller Type / Setting The Controller Type

You set the type of gameport controller by passing an I/O request to the
device with GPD_SETCTYPE set in io_Command, 1 set in io_Length and the
address of the byte variable describing the controller type set in io_Data.

The gameport device is a shared device; many tasks may have it open at any
given time. Hence, a high level protocol has been established to prevent
multiple tasks from reading the same unit at the same time.

 Three Step Protocol for Using the Gameport Device


5 / Setting Controller Type /Three Step Protocol for Using Gameport Device

Step 1:
    Send GPD_ASKCTYPE to the device and check for a GPCT_NOCONTROLLER
    return. Never issue GPD_SETCTYPE without checking whether the desired
    gameport unit is in use.

Step 2:
    If GPCT_NOCONTROLLER is returned, you have access to the gameport.
    Set the allocation flag to GPCT_MOUSE, GPCT_ABSJOYSTICK or
    GPCT_RELJOYSTICK if you use a system supported controller, or
    GPCT_ALLOCATED if you use a custom controller.

    struct IOStdReq *GameIO;  /* Must be initialized prior to using */

    BOOL set_controller_type(type)
    BYTE type;
    {

    BOOL success = FALSE;
    BYTE controller_type = 0;

    Forbid();                           /*critical section start */
    GameIO->io_Command = GPD_ASKCTYPE;  /* inquire current status */
    GameIO->io_Length = 1;
    GameIO->io_Flags = IOF_QUICK;
    GameIO->io_Data = (APTR)&controller_type; /* put answer in here */
    DoIO(GameIO);

    /* No one is using this device unit, let's claim it */
    if (controller_type == GPCT_NOCONTROLLER)
        {
        GameIO->io_Command = GPD_SETCTYPE;/* set controller type */
        GameIO->io_Length = 1;
        GameIO->io_Data = (APTR)&type;  /* set to input param */
        DoIO( GameIO);
        success = TRUE;
        UnitOpened = TRUE;
        }
    Permit(); /* critical section end */

    /* success can be TRUE or FALSE, see above */
    return(success);
    }

Step 3:
    The program must set the controller type back to GPCT_NOCONTROLLER
    upon exiting your program:

    struct IOStdReq *GameIO;  /* Must be initialized prior to using */

    void free_gp_unit()
    {
    BYTE type = GPCT_NOCONTROLLER;
    GameIO->io_Command = GPD_SETCTYPE;  /* set controller type */
    GameIO->io_Length = 1;
    GameIO->io_Data = (APTR)&type;      /* set to unused */
    DoIO( GameIO);
    }

This three step protocol allows applications to share the gameport device
in a system compatible way.

    A Word About The Functions.
    ---------------------------
    The functions shown above are designed to be included in any
    application using the gameport device.  The first function,
    set_controller_type(), would be the first thing done after opening
    the gameport device. The second function, free_gp_unit(), would be
    the last thing done before closing the device.


5 Gameport Device / Additional Information on the Gameport Device

Additional programming information on the gameport device can be found in
the include files and the Autodocs for the gameport and input devices.
Both are contained in the Amiga ROM Kernel Reference Manual: Includes and
Autodocs.

                       Gameport Device Information
                   -----------------------------------
                   INCLUDES       devices/gameport.h
                                  devices/gameport.i
                                  devices/inputevent.h
                                  devices/inputevent.i

                   AUTODOCS       gameport.doc


Amiga® RKM Devices: 13 Timer Device

The Amiga timer device provides a general interface to the Amiga's
internal clocks.  Through the timer device, time intervals can be
measured, time delays can be effected, system time can be set and
retrieved, and arithmetic operations can be performed on time values.

                  NEW TIMER FEATURES FOR VERSION 2.0

               Feature                 Description
               --------                -----------
               UNIT_ECLOCK             New timer device unit
               UNIT_WAITUNTIL          New timer device unit
               UNIT_WAITECLOCK         New timer device unit
               ReadEClock()            New function

   Compatibility Warning:
   ----------------------
   The new features for 2.0 are not backwards compatible.

 Timer Device Commands and Functions
 Device Interface
 System Time
 Adding a Time Request
 Using the Time Arithmetic Functions
 E-Clock Time and Its Relationship to Actual Time
 Example Timer Program
 Additional Information on the Timer Device


13 Timer Device / Timer Device Commands and Functions

Command        Operation
-------        ---------
TR_ADDREQUEST  Request that the timer device wait a specified period of
               time before replying to the request.

TR_GETSYSTIME  Get system time and place in a timeval structure.

TR_SETSYSTIME  Set the system time from the value in a  timeval structure.

Device Functions
----------------
AddTime()      Add one  timeval structure to another.  The result is placed
               in the first timeval structure.

CmpTime()      Compare one  timeval structure to another.  The result is
               returned as a longword.

GetSysTime()   Get system time and place in a  timeval structure.

ReadEClock()   Read the current 64 bit value of the E-Clock into an
               EClockVal structure.  The count rate of the E-Clock is also
               returned. (V36)

SubTime()      Subtract one timerequest structure from another. The result
               is placed in the first timerequest structure.

Exec Functions as Used in This Chapter
--------------------------------------
AbortIO()      Abort a command to the timer device.

CheckIO()      Return the status of an I/O request.

CloseDevice()  Relinquish use of the timer device. All requests must be
               complete before closing.

DoIO()         Initiate a command and wait for completion (synchronous
               request).

OpenDevice()   Obtain use of the timer device.  The timer device may be
               opened multiple times.

SendIO()       Initiate a command and return immediately (asynchronous
               request).

Exec Support Functions as Used in This Chapter
----------------------------------------------
CreateExtIO()  Create an extended I/O request structure of type
               timerequest.  This structure will be used to communicate
               commands to the timer device.

CreatePort()   Create a signal message port for reply messages from the
               timer device.  Exec will signal a task when a message
               arrives at the reply port.

DeleteExtIO()  Delete the timerequest extended I/O request structure
               created by CreateExtIO().

DeletePort()   Delete the message port created by CreatePort().


13 Timer Device / Device Interface

The timer device operates in a similar manner to the other Amiga devices.
To use it, you must first open it, then send I/O requests to it, and then
close it when finished. See the Introduction to Amiga System Devices
chapter for general information on device usage.

The timer device also provides timer functions in addition to the usual
I/O request protocol.  These functions still require the device to be
opened with the proper timer device unit, but do not require a message
port. However, the base address of the timer library must be obtained in
order to use the timer functions.

The two modes of timer device operation are not mutually exclusive.  You
may use them both within the same application.

The I/O request used by the timer device is called timerequest.

   struct timerequest
   {
       struct IORequest tr_node;
       struct timeval tr_time;
   };

The timer device functions are passed a time structure, either timeval for
non E-Clock units or EClockVal for E-Clock units.

   struct timeval
   {
        ULONG tv_secs;   /* seconds */
        ULONG tv_micro;  /* microseconds */
   };

   struct EClockVal
   {
       ULONG ev_hi;   /* Upper longword of E-Clock time */
       ULONG ev_lo;   /* Lower longword of E-Clock time */
   };

See the include file devices/timer.h for the complete structure
definitions. Time requests fall into three categories:

   *  Time delay - wait a specified period of time.  A time delay causes an
      application to wait a certain length of time. When a time delay is
      requested, the number of seconds and microseconds to delay are
      specified in the I/O request.

   *  Time measure - how long something takes to complete.  A time measure
      is a three-step procedure where the system or E-Clock time is
      retrieved, an operation or series of operations is performed, and
      then another time retrieval is done.  The difference between the two
      time values is the measure of the duration of the operation.

   *  Time alarm - wait till a specific time.  A time alarm is a request to
      be notified when a specific time value has occurred.  It is similar
      to a time delay except that the absolute time value is specified in
      the I/O request.

   What is an E-Clock?
   -------------------
   The E-Clock is the clock used by the Motorola 68000 processor family
   to communicate with other Motorola 8-bit chips.  The E-Clock returns
   two distinct values - the E-Clock value in the form of two longwords
   and the count rate (tics/second) of the E-Clock.  The count rate is
   related to the master frequency of the machine and is different
   between PAL and NTSC machines.

 Timer Device Units
 Opening The Timer Device
 Closing The Timer Device


13 / Device Interface / Timer Device Units

There are five units in the timer device.

                           TIMER DEVICE UNITS

                   Unit                        Use
                ------------            ---------------
                UNIT_MICROHZ            Interval Timing
                UNIT_VBLANK             Interval Timing
                UNIT_ECLOCK             Interval Timing
                UNIT_WAITUNTIL          Time Event Occurrence
                UNIT_WAITECLOCK         Time Event Occurrence

   *  The VBLANK timer unit is very stable and has a granularity comparable
      to the vertical blanking time.  When you make a timing request, such
      as "signal me in 21 seconds," the reply will come at the next
      vertical blank after 21 seconds have elapsed.  This timer has very
      low overhead and may be more accurate then the MICROHZ and ECLOCK
      units for long time periods. Keep in mind that the vertical blanking
      time varies depending on the display mode.

   *  The MICROHZ timer unit uses the built-in precision hardware timers to
      create the timing interval you request. It accepts the same type of
      command - "signal me in so many seconds and microseconds." The
      microhertz timer has the advantage of greater resolution than the
      vertical blank timer, but it may have less accuracy over long periods
      of time.  The microhertz timer also has much more system overhead,
      which means accuracy is reduced as the system load increases. It is
      primarily useful for short-burst timing for which critical accuracy
      is not required.

   *  The ECLOCK timer unit uses the Amiga E-Clock to measure the time
      interval you request.  This is the most precise time measure
      available through the timer device.

   *  The WAITUNTIL timer unit acts as an alarm clock for time requests.
      It will signal the task when systime is greater than or equal to a
      specified time value.  It has the same granularity as the VBLANK
      timer unit.

   *  The WAITECLOCK timer unit acts as an alarm clock for time requests.
      It will signal the task when the E-Clock value is greater than or
      equal to a specified time value.  It has the same granularity as the
      ECLOCK timer unit.

   Granularity vs. Accuracy.
   -------------------------
   Granularity is the sampling frequency used to check the timers.
   Accuracy is the precision of a measured time interval with respect to
   the same time interval in real-time.  We speak only of granularity
   because the sampling frequency directly affects how accurate the
   timers appear to be.


13 / Device Interface / Opening The Timer Device

Three primary steps are required to open the timer device:

   *  Create a message port using CreatePort(). Reply messages from the
      device must be directed to a message port.

   *  Create an I/O request structure of type timerequest using
      CreateExtIO().

   *  Open the timer device with one of the five timer device units. Call
      OpenDevice() passing a pointer to the  timerequest.

   struct MsgPort *TimerMP;   /* Message port pointer */
   struct timerequest *TimerIO;  /* I/O structure pointer */

     /* Create port for timer device communications */
   if (!(TimerMP = CreatePort(0,0)))
       cleanexit(" Error: Can't create port\n",RETURN_FAIL);

     /* Create message block for device IO */
   if (!(TimerIO = (struct timerequest *)
                   CreateExtIO(TimerMP)(sizeof timerequest)) )
       cleanexit(" Error: Can't create IO request\n",RETURN_FAIL);

     /* Open the timer device with UNIT_MICROHZ */
   if (error=OpenDevice(TIMERNAME,UNIT_MICROHZ,TimerIO,0))
       cleanexit(" Error: Can't open Timer.device\n",RETURN_FAIL);

The procedure for applications which only use the timer device functions
is slightly different:

   *  Declare the timer device base address variable TimerBase in the
      global data area.

   *  Allocate memory for a timerequest structure and a  timeval structure
      using AllocMem().

   *  Call OpenDevice(), passing the allocated timerequest structure.

   *  Set the timer device base address variable to point to the timer
      device base.

   struct Library *TimerBase;  /* global library pointer */

   struct timerequest *TimerIO;
   struct timeval *time1;

     /* Allocate memory for timerequest and timeval structures */
   TimerIO=(struct timerequest *)AllocMem(sizeof(struct timerequest),
                                  MEMF_PUBLIC | MEMF_CLEAR);
   time1=(struct timeval *)AllocMem(sizeof(struct timeval),
                                  MEMF_PUBLIC | MEMF_CLEAR);
   if (!TimerIO | !time1)
       cleanexit(" Error: Can't allocate memory for I/O structures\n",
                          RETURN_FAIL);

   if (error=OpenDevice(TIMERNAME,UNIT_MICROHZ,TimerIO,0))
       cleanexit(" Error: Can't open Timer.device\n",RETURN_FAIL);

     /* Set up pointer for timer functions */
   TimerBase = (struct Library *)TimerIO->tr_node.io_Device;


13 / Device Interface / Closing The Timer Device

Each OpenDevice() must eventually be matched by a call to CloseDevice().

All I/O requests must be complete before CloseDevice().  If any requests
are still pending, abort them with AbortIO().

   if (!(CheckIO(TimerIO)))
       {
       AbortIO(TimerIO);    /* Ask device to abort any pending requests */
       }
   WaitIO(TimerIO);         /* Clean up */
   CloseDevice((struct IORequest *)TimerIO);  /* Close Timer device */


13 Timer Device / System Time

The Amiga has a system time feature provided for the convenience of the
developer.  It is a monotonically increasing time base which should be the
same as real time. The timer device provides two commands to use with the
system time.  In addition,  there are utility functions in utility.library
which are very useful with system time.   See the "Utility Library"
chapter of the  Amiga ROM Kernel Reference Manual: Libraries for more
information.

The command TR_SETSYSTIME sets the system's idea of what time it is. The
system starts out at time "zero" so it is safe to set it forward to the
"real" time. However, care should be taken when setting the time
backwards.

The command TR_GETSYSTIME is used to get the system time. The timer device
does not interpret system time to any physical value. By convention, it
tells how many seconds have passed since midnight, January 1, 1978.  Your
program must calculate the time from this value.

The function GetSysTime() can also be used to get the system time. It
returns the same value as TR_GETSYSTIME, but uses less overhead.

Whenever someone asks what time it is using TR_GETSYSTIME, the return
value of the system time is guaranteed to be unique and unrepeating so
that it can be used by applications as a unique identifier.

   System time at boot time.
   -------------------------
   The timer device sets system time to zero at boot time. AmigaDOS will
   then reset the system time to the value specified on the boot disk.
   If the AmigaDOS C:SetClock command is given, this also resets system
   time.

Here is a program that can be used to determine the system time.
The command is executed by the timer device and, on return, the caller can
find the data in his request block.

     Get_Systime.c


13 Timer Device / Adding a Time Request

Time delays and time alarms are done by opening the timer device with the
proper unit and submitting a timerequest to the device with TR_ADDREQUEST
set in io_Command and the appropriate values set in tv_secs and tv_micro.

Time delays are used with the UNIT_MICROHZ, UNIT_VBLANK, and
UNIT_ECLOCK units. The time specified in a time delay timerequest is a
relative measure from the time the request is posted.  This means that the
tv_secs and tv_micro fields should be set to the amount of delay required.

When the specified amount of time has elapsed, the driver will send the
timerequest back via ReplyMsg().  You must fill in the ReplyPort pointer
of the timerequest structure if you wish to be signaled. Also, the number
of microseconds must be normalized; it should be a value less than one
million.

For a minute and a half delay, set 60 in tv_secs and 500,000 in tv_micro.

    TimerIO->tr_node.io_Command = TR_ADDREQUEST;
    TimerIO->tr_time.tv_secs  = 60;        /* Delay a minute */
    TimerIO->tr_time.tv_micro = 500000;    /* and a half     */
    DoIO(TimerIO);

Time alarms are used with the UNIT_WAITUNTIL and UNIT_WAITECLOCK units.
The tv_secs and tv_micro fields should be set to the absolute time value
of the alarm.  For an alarm at 10:30 tonight, the number of seconds from
midnight, January 1, 1978 till 10:30 tonight should be set in tv_secs.
The timer device will not return until the time is greater than or equal
to the absolute time value.

For our purposes, we will set an alarm for three hours from now by getting
the current system time and adding three hours of seconds to it.

   #define SECSPERHOUR (60*60)
   struct timeval *systime;

   GetSysTime(systime);   /* Get current system time */

   TimerIO->tr_node.io_Command = TR_ADDREQUEST;
   TimerIO->tr_time.tv_secs  = systime.tv_secs+(SECSPERHOUR*3);
   TimerIO->tr_time.tv_micro = systime.tv_micro;
   DoIO(TimerIO);

   Time requests with the E-Clock Units.
   -------------------------------------
   Time requests with the E-Clock units - UNIT_ECLOCK and
   UNIT_WAITECLOCK - work the same as the other units except that the
   values specified in their I/O requests are compared against the value
   of the E-Clock.  See "E-Clock Time and Its Relationship to Actual Time"
   below.

Remember, you must never reuse a timerequest until the timer device has
replied to it.  When you submit a timer request, the driver destroys the
values you have provided in the  timeval structure. This means that you
must reinitialize the time specification before reposting a timerequest.

Keep in mind that the timer device provides a general time-delay
capability. It can signal you when at least a certain amount of time has
passed. The timer device is very accurate under normal system loads, but
because the Amiga is a multitasking system, the timer device cannot
guarantee that exactly the specified amount of time has
elapsed - processing overhead increases as more tasks are run.
High-performance applications (such as MIDI time-stamping) may want to
take over the 16-bit counters of the CIA B timer resource instead of using
the timer device.

   Problems with small time requests in V1.3 and earlier versions.
   ---------------------------------------------------------------
   You must also take care  to avoid posting a timerequest of less than
   2 microseconds with the UNIT_MICROHZ timer device if you are using
   V1.3 or earlier versions of the system software.  In V1.3 and earlier
   versions of the Amiga system software, sending a timerequest for 0 or
   1 microseconds can cause a system crash.  Make sure all your timer
   requests are for 2 microseconds or more when you use the UNIT_MICROHZ
   timer with those versions.

 Multiple Timer Requests


13 / Adding a Time Request / Multiple Timer Requests

Multiple requests may be posted to the timer driver. For example, you can
make three timer requests in a row:

    Signal me in 20 seconds (request 1)
    Signal me in 30 seconds (request 2)
    Signal me in 10 seconds (request 3)

As the timer queues these requests, it changes the time values and sorts
the timer requests to service each request at the desired interval,
resulting effectively in the following order:

    (request 3) in now+10 seconds
    (request 1) 10 seconds after request 3 is satisfied
    (request 2) 10 seconds after request 1 is satisfied

If you wish to send out multiple timer requests, you have to create
multiple request blocks. You can do this by allocating memory for each
timerequest you need and filling in the appropriate fields with command
data.  Some fields are initialized by the call to the OpenDevice()
function.  So, for convenience, you may allocate memory for the
timerequest you need, call OpenDevice() with one of them, and then copy
the initialized fields into all the other timerequest.

It is also permissible to open the timer device multiple times.  In some
cases this may be easier than opening it once and using multiple requests.
When multiple requests are given, SendIO() should be used to transmit each
one to the timer.

     Multiple_Timers.c

If all goes according to plan, TimerIO[1] will finish first, TimerIO[2]
will finish next, and TimerIO[0] will finish last.


13 Timer Device / Using the Time Arithmetic Functions

As indicated above, the time arithmetic functions are accessed in the
timer device structure as if they were a routine library. To use them, you
create an IORequest block and open the timer.  In the IORequest block is a
pointer to the device's base address. This address is needed to access
each routine as an offset - for example, _LVOAddTime, _LVOSubTime,
_LVOCmpTime - from that base address.

     Timer_Arithmetic.c

 Why Use Time Arithmetic?


13 / Using the Time Arithmetic Functions / Why Use Time Arithmetic?

As mentioned earlier in this section, because of the multitasking
capability of the Amiga, the timer device can provide timings that are at
least as long as the specified amount of time. If you need more precision
than this, using the system timer along with the time arithmetic routines
can at least, in the long run, let you synchronize your software with this
precision timer after a selected period of time.

Say, for example, that you select timer intervals so that you get 161
signals within each 3-minute span. Therefore, the  timeval you would have
selected would be 180/161, which comes out to 1 second and 118,012
microseconds per interval.  Considering the time it takes to set up a call
to set the timer and delays due to task-switching (especially if the
system is very busy), it is possible that after 161 timing intervals, you
may be somewhat beyond the 3-minute time. Here is a method you can use to
keep in sync with system time:

   1. Begin.

   2. Read system time; save it.

   3. Perform your loop however many times in your selected interval.

   4. Read system time again, and compare it to the old value you saved.
      (For this example, it will be more or less than 3 minutes as a total
      time elapsed.)

   5. Calculate a new value for the time interval ( timeval); that is, one
      that (if precise) would put you exactly in sync with system time the
      next time around. Timeval will be a lower value if the loops took too
      long, and a higher value if the loops didn't take long enough.

   6. Repeat the cycle.

Over the long run, then, your average number of operations within a
specified period of time can become precisely what you have designed.

   You Can't Do 1+1 on E-Clock Values.
   -----------------------------------
   The arithmetic functions are not designed to operate on EClockVals.


13 Timer Device / E-Clock Time and Its Relationship to Actual Time

Unlike GetSysTime(), the two values returned by ReadEClock() - tics/sec
and the EClockVal structure - have no direct relationship to actual time.
The tics/sec is the E-Clock count rate, a value which is related to the
system master clock.  The EClockVal structure is simply the upper longword
and lower longword of the E-Clock 64 bit register.

However, when two EClockVal structures are subtracted from each other and
divided by the tics/sec (which remains constant), the result does have a
relationship to actual time.  The value of this calculation is a measure
of fractions of a second that passed between the two readings.

/* E-Clock Fractions of a second fragment
 *
 * This fragment reads the E-Clock twice and subtracts the two ev_lo values
 *         time2->ev_lo  - time1->ev_lo
 * and divides the result by the E-Clock tics/secs returned by ReadEClock()
 * to get the fractions of a second
 */

struct EClockVal *time1,*time2;
ULONG E_Freq;
LONG error;
struct timerequest *TimerIO;

TimerIO  = (struct timerequest *)AllocMem(sizeof(struct timerequest ),
            MEMF_CLEAR | MEMF_PUBLIC);

time1 = (struct EClockVal *)AllocMem(sizeof(struct EClockVal ),
         MEMF_CLEAR | MEMF_PUBLIC);

time2 = (struct EClockVal *)AllocMem(sizeof(struct EClockVal ),
         MEMF_CLEAR | MEMF_PUBLIC);

if (!(error = OpenDevice(TIMERNAME,UNIT_ECLOCK,
              (struct IORequest *)TimerIO,0L)) )
    {
    TimerBase = (struct Library *)TimerIO->tr_node.io_Device;
    E_Freq =  ReadEClock((struct EClockVal *) time1); /* Get initial */
                                                      /*   reading   */

       /*  place operation to be measured here */

    E_Freq =  ReadEClock((struct EClockVal *) time2); /* Get 2nd reading */
    printf("\nThe operation took: %f fractions of a second\n",
            (time2->ev_lo-time1->ev_lo)/(double)E_Freq);

    CloseDevice( (struct IORequest *) TimerIO );
    }

   The Code Takes Some Liberties.
   ------------------------------
   The above fragment only uses the lower longword of the EClockVal
   structures in calculating the fractions of a second that passed.
   This was done to simplify the fragment.  Naturally, you would have to
   at least check the values of the upper longwords if not use them to
   get an accurate measure.


13 Timer Device / Additional Information on the Timer Device

Additional programming information on the timer device and the utilities
library can be found in their include files and Autodocs.  All are
contained in the Amiga ROM Kernel Reference Manual: Includes and Autodocs.

                       Timer Device Information
                    -------------------------------
                    INCLUDES        devices/timer.h
                                    devices/timer.i
                                    utility/date.h
                                    utility/date.i

                    AUTODOCS        timer.doc
                                    utility.doc


Amiga® RKM Devices: 6 Input Device

The input device is the central collection point for input events
disseminated throughout the system. The best way to describe the input
device is a manager of a stream with feeders.  The input device itself and
other modules such as the file system add events to the stream; so do
input device "users" - programs or other devices that use parts of the
stream or change it in some way.  Feeders of the input device include the
keyboard, timer and gameport devices.  The keyboard, gameport, and timer
devices are special cases in that the input device opens them and asks
them for input. Users of the input device include Intuition and the
console device.

                     NEW FEATURES FOR VERSION 2.0

                    Feature              Description
             ---------------------    -----------------
             IECLASS_NEWPOINTERPOS    Input Event Class
             IECLASS_MENUHELP         Input Event Class
             IECLASS_CHANGEWINDOW     Input Event Class
             IESUBCLASS_COMPATIBLE    Input Event SubClass
             IESUBCLASS_PIXEL         Input Event SubClass
             IESUBCLASS_TABLET        Input Event SubClass
             PeekQualifier()          Function

   Compatibility Warning:
   ----------------------
   The new features for the 2.0 input device are not backwards
   compatible.

 Input Device Commands and Functions
 Device Interface
 Using the Mouse Port With the Input Device
 Adding an Input Handler
 Writing Events to the Input Device Stream
 Setting the Key Repeat Threshold
 Setting the Key Repeat Interval
 Determining the Current Qualifiers
 Input Device and Intuition
 Example Input Device Program
 Additional Information on the Input Device


6 Input Device / Input Device Commands and Functions

Command          Operation
-------          ---------
CMD_FLUSH        Purge all active and queued requests for the input device.

CMD_RESET        Reset the input port to its initialized state.  All
                 active and queued I/O requests will be aborted.  Restarts
                 the device if it has been stopped.

CMD_START        Restart the currently active input (if any) and resume
                 queued I/O requests.

CMD_STOP         Stop any currently active input and prevent queued I/O
                 requests from starting.

IND_ADDHANDLER   Add an input-stream handler into the handler chain.

IND_REMHANDLER   Remove an input-stream handler from the handler chain.

IND_SETMPORT     Set the controller port to which the mouse is connected.

IND_SETMTRIG     Set conditions that must be met by a mouse before a
                 pending read request will be satisfied.

IND_SETMTYPE     Set the type of device at the mouse port.

IND_SETPERIOD    Set the period at which a repeating key repeats.

IND_SETTHRESH    Set the repeating key hold-down time before repeat starts.

IND_WRITEEVENT   Propagate an input event stream to all devices.

Input Device Function
---------------------
PeekQualifier()  Return the input device's current qualifiers. (V36)

Exec Functions as Used in This Chapter
--------------------------------------
AbortIO()        Abort a command to the input device.

CheckIO()        Return the status of an I/O request.

CloseDevice()    Relinquish use of the input device.

DoIO()           Initiate a command and wait for completion (synchronous
                 request).

OpenDevice()     Obtain shared use of the input device.

SendIO()         Initiate a command and return immediately (asynchronous
                 request).

Exec Support Functions as Used in This Chapter
----------------------------------------------
CreateExtIO()    Create an extended I/O request structure of type
                 IOStdReq.  This structure will be used to communicate
                 commands to the input device.

CreatePort()     Create a signal message port for reply messages from the
                 input device.  Exec will signal a task when a message
                 arrives at the reply port.

DeleteExtIO()    Delete an I/O request structure created by CreateExtIO().

DeletePort()     Delete the message port created by CreatePort().


6 Input Device / Device Interface

The input device operates like the other Amiga devices.  To use it, you
must first open the input device, then send I/O requests to it, and then
close it when finished.  See the Introduction to Amiga System Devices
chapter for general information on device usage.

A number of structures are used by the input device to do its processing.
Some are used to pass commands and data to the device, some are used to
describe input events like mouse movements and key depressions, and one
structure is used to describe the environment for input event handlers.

The I/O request used by the input device for most commands is IOStdReq.

   struct IOStdReq
   {
       struct Message io_Message; /* message reply port */
       struct Device  *io_Device; /* device node pointer */
       struct Unit    *io_Unit;   /* unit */
       UWORD  io_Command;         /* input device command */
       UBYTE  io_Flags;           /* input device flags */
       BYTE   io_Error;           /* error code */
       ULONG  io_Length;          /* number of bytes to transfer */
       APTR   io_Data;            /* pointer to data area */
   };

See the include file exec/io.h for the complete structure definition.

Two of the input device commands - IND_SETTHRESH and IND_SETPERIOD -
require a time specification and must use a timerequest structure instead
of an IOStdReq.

   struct timerequest
   {
       struct IORequest tr_node;
       struct timeval tr_time;
   };

As you can see, the timerequest structure includes an IORequest structure.
The io_Command field of theIORequest indicates the command to the input
device and the timeval structure sets the time values.  See the include
file devices/timer.h for the complete structure definition.

   In Case You Feel Like Reinventing the Wheel...
   ----------------------------------------------
   You could define a "super-IORequest" structure for the input device
   which would combine the IOStdReq fields with the timeval structure of
   the timerequest structure.

 Opening The Input Device
 Input Device Event Types
 Closing The Input Device


6 / Device Interface / Opening The Input Device

Three primary steps are required to open the input device:

   *  Create a message port using CreatePort(). Reply messages from the
      device must be directed to a message port.

   *  Create an I/O request structure of type IOStdReq or timerequest. The
      I/O request created by the CreateExtIO() function will be used to
      pass commands and data to the input device.

   *  Open the Input device.  Call OpenDevice(), passing the I/O request.

   struct MsgPort  *InputMP;   /* Message port pointer */
   struct IOStdReq *InputIO;   /* I/O request pointer */

   if (InputMP=CreatePort(0,0) )
       if (InputIO=(struct IOStdReq *)
                    CreateExtIO(InputMP,sizeof(struct IOStdReq)) )
           if (OpenDevice("input.device",0L,(struct IORequest *)InputIO,0))
               printf("input.device did not open\n");

The above code will work for all the input device commands except for the
ones which require a time specification.  For those, the code would look
like this:

   #include <devices/timer.h>

   struct MsgPort  *InputMP;      /* Message port pointer */
   struct timerequest *InputIO;   /* I/O request pointer */

   if (InputMP=CreatePort(0,0) )
       if (InputIO=(struct timerequest *)
                    CreateExtIO(InputMP,sizeof(struct timerequest)) )
           if (OpenDevice("input.device",0L,(struct IORequest *)InputIO,0))
               printf("input.device did not open\n");


6 / Device Interface / Input Device Event Types

The input device is automatically opened by the console device when the
system boots.  When the input device is opened, a task named
"input.device" is started. The input device task communicates directly
with the keyboard device to obtain raw key events. It also communicates
with the gameport device to obtain mouse button and mouse movement events
and with the timer device to obtain time events. In addition to these
events, you can add your own input events to the input device, to be fed
to the handler chain (see below).

The keyboard device is accessible directly (see the Keyboard Device
chapter).  However, once the input.device task has started, you should not
read events from the keyboard device directly, since doing so will deprive
the input device of the events and confuse key repeating.

The gameport device has two units. As you view the Amiga, looking at the
gameport connectors, the left connector is assigned as the primary mouse
input for Intuition and contributes gameport input events to the input
event stream.

The right connector is handled by the other gameport unit and is currently
unassigned.  While the input  device task is running, that task expects to
read the input from the left connector. Direct use of the gameport device
is covered in the Gameport Device chapter of this manual.

The timer device is used to generate time events for the input device. It
is also used to control key repeat rate and key repeat threshold. The
timer device is a shared-access device and is described in
Timer Device chapter of this manual.

The device-specific commands are described below.  First though, it may be
helpful to consider the types of input events that the input device deals
with. An input event is a data structure that describes the following:

   *  The class of the event-often describes the device that generated
      the event.

   *  The subclass of the event-space for more information if needed.

   *  The code-keycode if keyboard, button information if mouse, others.

   *  A qualifier such as "Alt key also down,"or "key repeat active".

   *  A position field that contains a data address or a mouse position
      count.

   *  A time stamp, to determine the sequence in which the events occurred.

   *  A link-field by which input events are linked together.

   *  The class, subclass, code and qualifier of the previous down key.

The full definitions for each field can be found in the include file
devices/inputevent.h.  You can find more information about input events in
the Gameport Device and Console Device chapters of this manual.

The various types of input events are listed below.

                         Input Device Event Types
                         ------------------------
   IECLASS_NULL            A NOP input event
   IECLASS_RAWKEY          A raw keycode from the keyboard device
   IECLASS_RAWMOUSE        The raw mouse report from the gameport device
   IECLASS_EVENT           A private console event
   IECLASS_POINTERPOS      A pointer position report
   IECLASS_TIMER           A timer event
   IECLASS_GADGETDOWN      Select button pressed down over a
                           gadget (address in ie_EventAddress)
   IECLASS_GADGETUP        Select button released over the same gadget
                           (address in ie_EventAddress)
   IECLASS_REQUESTER       Some requester activity has taken place.
   IECLASS_MENULIST        This is a menu number transmission (menu
                           number is in ie_Code)
   IECLASS_CLOSEWINDOW     User has selected active window's Close Gadget
   IECLASS_SIZEWINDOW      This window has a new size
   IECLASS_REFRESHWINDOW   The window pointed to by
                           ie_EventAddress needs to be refreshed
   IECLASS_NEWPREFS        New preferences are available
   IECLASS_DISKREMOVED     The disk has been removed
   IECLASS_DISKINSERTED    The disk has been inserted
   IECLASS_ACTIVEWINDOW    The window is about to be been made active
   IECLASS_INACTIVEWINDOW  The window is about to be made inactive
   IECLASS_NEWPOINTERPOS   Extended-function pointer position report (V36)
   IECLASS_MENUHELP        Help key report during Menu session (V36)
   IECLASS_CHANGEWINDOW    The Window has been modified with move,
                           size, zoom, or change (V36)

There is a difference between simply receiving an input event from a
device and actually becoming a handler of an input event stream. A handler
is a routine that is passed an input event list.  It is up to the handler
to decide if it can process the input events. If the handler does not
recognize an event, it leaves it undisturbed in the event list.

   It All Flows Downhill.
   ----------------------
   Handlers can themselves generate new linked lists of events which can
   be passed down to lower priority handlers.

The InputEvent structure is used by the input device to describe an input
event such as a keypress or a mouse movement.

   struct InputEvent
   {
       struct  InputEvent *ie_NextEvent;/* the next chronological event */
       UBYTE   ie_Class;            /* the input event class */
       UBYTE   ie_SubClass;         /* optional subclass of the class */
       UWORD   ie_Code;             /* the input event code */
       UWORD   ie_Qualifier;        /* qualifiers in effect for the event*/
       union
       {
           struct
           {
               WORD    ie_x;        /* the pointer position for event */
               WORD    ie_y;
           } ie_xy;
           APTR    ie_addr;         /* the event address */
           struct
           {
               UBYTE   ie_prev1DownCode;/* previous down keys for dead */
               UBYTE   ie_prev1DownQual;/* key translation: the ie_Code */
               UBYTE   ie_prev2DownCode;/* &low byte of ie_Qualifier for */
               UBYTE   ie_prev2DownQual;/* last & second last down keys */
           } ie_dead;
       } ie_position;
       struct timeval ie_TimeStamp;     /* the system tick at the event */
   };

The IEPointerPixel and IEPointerTablet structures are used to set the
mouse position with the IECLASS_NEWPOINTERPOS input event class.

   struct IEPointerPixel
   {
       struct Screen       *iepp_Screen;   /* pointer to an open screen */
       struct
       {                           /* pixel coordinates in iepp_Screen */
           WORD    X;
           WORD    Y;
       } iepp_Position;
   };

   struct IEPointerTablet
   {
       struct
       {
           UWORD   X;
           UWORD   Y;
       } iept_Range;       /* 0 is min, these are max      */
       struct
       {
           UWORD   X;
           UWORD   Y;
       } iept_Value;       /* between 0 and iept_Range     */

       WORD iept_Pressure; /* -128 to 127 (unused, set to 0)  */
   };

See the include file devices/inputevent.h for the complete structure
definitions.

For input device handler installation, the Interrupt structure is used.

   struct Interrupt
   {
       struct Node is_Node;
       APTR   is_Data;         /* server data segment */
       VOID   (*is_Code)();    /* server code entry   */
   };

See the include file exec/interrupts.h for the complete structure
definition.


6 / Device Interface / Closing The Input Device

Each OpenDevice() must eventually be matched by a call to CloseDevice().
All I/O requests must be complete before CloseDevice().  If any requests
are still pending, abort them with AbortIO():

   if (!(CheckIO(InputIO)))
       {
       AbortIO(InputIO);  /* Ask device to abort request, if pending */
       }
   WaitIO(InputIO);       /* Wait for abort, then clean up */
   CloseDevice((struct IORequest *)InputIO);


6 Input Device / Using the Mouse Port With the Input Device

To get mouse port information you must first set the current mouse port by
passing an IOStdReq to the device with IND_SETMPORT set in io_Command and
a pointer to a byte set in io_Data.  If the byte is set to 0 the left
controller port will be used as the current mouse port; if it is set to 1,
the right controller port will be used.

   BYTE port = 1;      /* set mouse port to right controller */

   InputIO->io_Data = &port;
   InputIO->io_Flags = IOF_QUICK;
   InputIO->io_Length = 1;
   InputIO->io_Command = IND_SETMPORT;
   BeginIO((struct IORequest *)InputIO);
   if (InputIO->io_Error)
       printf("\nSETMPORT failed %d\n",InputIO->io_Error);

   Put That Back!
   --------------
   The default mouse port is the left controller.  Don't forget to set
   the mouse port back to the left controller before exiting if you
   change it to the right controller during your application.

 Setting The Conditions For A Mouse Port Report


6 / Setting The Conditions For A Mouse Port Report

You set the conditions for a mouse port report by passing an IOStdReq to
the device with IND_SETMTRIG set in io_Command, the address of a
GamePortTrigger structure set in io_Data and the length of the structure
set in io_Length.

   struct GamePortTrigger InputTR;

   InputIO->io_Data = (APTR)InputTR;     /* set trigger conditions */
   InputIO->io_Command = IND_SETMTRIG;   /* from InputTR */
   InputIO->io_Length = sizeof(struct GamePortTrigger);
   DoIO(InputIO);

The information needed for mouse port report setting is contained in a
GamePortTrigger data structure which is defined in the include file
devices/gameport.h.

   struct GamePortTrigger
   {
       UWORD    gpt_Keys;      /* key transition triggers */
       UWORD    gpt_Timeout;   /* time trigger (vertical blank units) */
       UWORD    gpt_XDelta;    /* X distance trigger */
       UWORD    gpt_YDelta;    /* Y distance trigger */
   };

See the Gameport Device chapter of this manual for a full description
of setting mouse port trigger conditions.


6 Input Device / Adding an Input Handler

You add an input-stream handler to the input chain by passing an IOStdReq
to the device with IND_ADDHANDLER set in io_Command and a pointer to an
Interrupt structure set in io_Data.

   struct Interrupt *InputHandler;
   struct IOStdReq  *InputIO

   InputHandler->is_Code=ButtonSwap;         /* Address of code */
   InputHandler->is_Data=NULL;               /* User Value passed in A1 */
   InputHandler->is_Node.ln_Pri=100;         /* Priority in food chain */
   InputHandler->is_Node.ln_Name=NameString; /* Name of handler */

   InputIO->io_Data=(APTR)inputHandler;      /* Point to the structure */
   InputIO->io_Command=IND_ADDHANDLER;       /* Set command ... */
   DoIO((struct IORequest *)InputIO);        /* DoIO( ) the command */

Intuition is one of the input device handlers and normally distributes
most of the input events.

Intuition inserts itself at priority position 50. The console device sits
at priority position 0. You can choose the position in the chain at which
your handler will be inserted by setting the priority field in the
list-node part of the interrupt data structure you pass to this routine.

   Speed Saves.
   ------------
   Any processing time expended by a handler subtracts from the time
   available before the next event happens. Therefore, handlers for the
   input stream must be fast. For this reason it is recommended that the
   handlers be written in assembly.

 Rules For Input Device Handlers
 Removing An Input Handler


6 / Adding an Input Handler / Rules For Input Device Handlers

The following rules should be followed when you are designing an input
handler:

   *  If an input handler is capable of processing a specific kind of an
      input event and that event has no links (ie_NextEvent = 0), the
      handler can end the handler chain by returning a NULL (0) value.

   *  If there are multiple events linked together, the handler is free to
      unlink an event from the input event chain, thereby passing a shorter
      list of events to subsequent handlers. The starting address of the
      modified list is the return value.

   *  If a handler wishes to add new events to the chain that it passes to
      a lower-priority handler, it may initialize memory to contain the new
      event or event chain. The handler, when it again gets control on the
      next round of event handling, should assume nothing about the current
      contents of the memory blocks attached to the event chain.  Lower
      priority handlers may have modified the memory as they handled their
      part of the event.  The handler that allocates the memory for this
      purpose should keep track of the starting address and the size of
      this memory chunk so that the memory can be returned to the free
      memory list when it is no longer needed.

Your assembly language handler routine should be structured similar to the
following pseudo-language statement:

   newEventChain = yourHandlerCode(oldEventChain, yourHandlerData);
        d0       =                      a0               a1

where:

   *  yourHandlerCode is the entry point to your routine.

   *  oldEventChain is the starting address for the current chain of input
      events.

   *  yourHandlerData is a user-definable value, usually a pointer to some
      data structure your handler requires.

   *  newEventChain is the starting address of an event chain which you are
      passing to the next handler, if any.

When your handler code is called, the event chain is passed in A0 and the
handler data is passed in A1. (You may choose not to use A1.) When your
code returns, it should return the pointer to the event chain in D0. If
all of the events were removed by the routine, return NULL. A NULL (0)
value terminates the handling thus freeing more CPU resources.

Memory that you use to describe a new input event that you have added to
the event chain is available for reuse or deallocation when the handler is
called again or after the IND_REMHANDLER command for the handler is
complete. There is no guarantee that any field in the event is unchanged
since a handler may change any field of an event that comes through the
food chain.

   Do Not Confuse the Device.
   --------------------------
   Altering a repeat key report will confuse the input device when it
   tries to stop the repeating after the key is raised under pre-V36
   Kickstart.

Because IND_ADDHANDLER installs a handler in any position in the handler
chain, it can, for example, ignore specific types of input events as well
as act upon and modify existing streams of input. It can even create new
input events for Intuition or other programs to interpret.


6 / Adding an Input Handler / Removing An Input Handler

You remove a handler from the handler chain by passing an IOStdReq to the
device IND_REMHANDLER set in io_Command and a pointer to the Interrupt
structure used to add the handler.

   struct Interrupt *InputHandler;
   struct IOStdReq  *InputIO;

   InputIO->io_Data=(APTR)InputHandler;   /* Which handler to REM */
   InputIO->io_Command=IND_REMHANDLER;    /* The REM command */
   DoIO((struct IORequest *)InputIO);     /* Send the command */


6 Input Device / Writing Events to the Input Device Stream

Typically, input events are internally generated by the timer device,
keyboard device, and input device.

An application can also generate an input event by setting the appropriate
fields for the event in an InputEvent structure and sending it to the
input device. It will then be treated as any other event and passed
through to the input handler chain.  However, I/O requests for
IND_WRITEEVENT cannot be made from interrupt code.

You generate an input event by passing an IOStdReq to the device with
IND_WRITEEVENT set in io_Command, a pointer to an InputEvent structure set
in io_Data and the length of the structure set in io_Length.

   struct InputEvent *FakeEvent;
   struct IOStdReq   *InputIO;

   InputIO->io_Data=(APTR)FakeEvent;
   InputIO->io_Length=sizeof(struct InputEvent);
   InputIO->io_Command=IND_WRITEEVENT;
   DoIO((struct IORequest *)InputIO);

   You Know What Happens When You Assume.
   --------------------------------------
   This command propagates the input event through the handler chain.
   The handlers may link other events onto the end of this event or
   modify the contents of the data structure you constructed in any way
   they wish. Therefore, do not assume any of the data will be the same
   from event to event.

 Setting The Position Of The Mouse


6 / Writing Events to Input Device Stream / Setting Position Of Mouse

One use of writing input events to the input device is to set the
position of the mouse pointer.  The mouse pointer can be positioned by
using the input classes IECLASS_POINTERPOS and IECLASS_NEWPOINTERPOS .

There are two ways to set the position of the mouse pointer using the
pre-V36 Kickstart input class IECLASS_POINTERPOS:

   *  At an absolute position on the current screen.

   *  At a position relative to the current mouse pointer position on the
      current screen.

In both cases, you set the Class field of the InputEvent structure to
IECLASS_POINTERPOS, ie_X with the new x-coordinate and ie_Y with the new
y-coordinate.   Absolute positioning is done by setting ie_Qualifier to
NULL and relative positioning is done by setting ie_Qualifier to
RELATIVE_MOUSE.

Once the proper values are set, pass an IOStdReq to the input device with
a pointer to the InputEvent structure set in io_Data and io_Command set to
IND_WRITEEVENT.

There are three ways to set the mouse pointer position using
IECLASS_NEWPOINTERPOS:

   *  At an absolute x-y coordinate on a screen-you specify the exact
      location of the pointer and which screen.

   *  At an relative x-y coordinate-you specify where it will go in
      relation to the current pointer position and which screen.

   *  At a normalized position on a tablet device-you specify the maximum
      x-value and y-value of the tablet and an x-y coordinate between them
      and the input device will normalize it to fit.

The basic steps required are the same for all three methods.

   *  Get a pointer to the screen where you want to position the pointer.
      This is not necessary for the tablet device.

   *  Set up a structure to indicate the new position of the pointer.

For absolute and relative positioning, you set up an IEPointerPixel
structure with iepp_Position.X set to the new x-coordinate,
iepp_Position.Y set to the new y-coordinate and iepp_Screen set to the
screen pointer. You set up an InputEvent structure with ie_SubClass set to
IESUBCLASS_PIXEL, a pointer to the IEPointerPixel structure set in
ie_EventAddress, IECLASS_NEWPOINTERPOS set in Class, and ie_Qualifier set
to either IEQUALIFIER_RELATIVEMOUSE for relative positioning or NULL for
absolute positioning.

For tablet positioning, you set up an IEPointerTablet structure with
iept_Range.X set to the maximum x-coordinate and iept_Range.Y set to the
maximum y-coordinate, and iept_Value.X set to the new x-coordinate and
iept_Value.Y set to the new y-coordinate. You set up an InputEvent
structure with a pointer to the IEPointerTablet structure set in
ie_EventAddress, ie_SubClass to IESUBCLASS_TABLET and Class set to
IECLASS_NEWPOINTERPOS.

Finally, for all three methods, pass an IOStdReq to the device with a
pointer to the InputEvent structure set in io_Data and io_Command set to
IND_WRITEEVENT.

The following example sets the mouse pointer at an absolute position on a
public screen using IECLASS_NEWPOINTERPOS.  Notice that it uses V36
functions wherever possible.

     Set_Mouse.c


6 Input Device / Setting the Key Repeat Threshold

The key repeat threshold is the number of seconds and microseconds a user
must hold down a key before it begins to repeat. This delay is normally
set by the Preferences tool or by Intuition when it notices that the
Preferences have been changed, but you can also do it directly through the
input device.

You set the key repeat threshold by passing a timerequest with
IND_SETTHRESH set in io_Command and the number of seconds to delay set in
tv_secs and the number of microseconds to delay set in tv_micro.

   #include <devices/timer.h>

   struct timerequest *InputTime;/* Init with CreateExtIO() before using */

   InputTime->tr_time.tv_secs=1;         /* 1 second */
   InputTime->tr_time.tv_micro=500000;   /* 500000 microseconds */
   InputTime->tr_node.io_Command=IND_SETTHRESH;
   DoIO((struct IORequest *)InputTime);

The code above will set the key repeat threshold to 1.5 seconds.


6 Input Device / Setting the Key Repeat Interval

The key repeat interval is the time period, in seconds and microseconds,
between key repeat events once the initial key repeat threshold has
elapsed. (See Setting the Key Repeat Threshold.)  Like the key
repeat threshold, this is normally issued by Intuition and preset by the
Preferences tool.

You set the key repeat interval by passing a timerequest with
IND_SETPERIOD set in io_Command and the number of seconds set in tv_secs
and the number of microseconds set in tv_micro. struct timerequest
*InputTime; /* Initialize with CreateExtIO() before using */

   InputTime->tr_time.tv_secs=0;
   InputTime->tr_time.tv_micro=12000;  /* .012 seconds */
   InputTime->tr_node.io_Command=IND_SETPERIOD;
   DoIO((struct IORequest *)InputTime);

The code above sets the key repeat interval to .012 seconds.

   The Right Tool For The Right Job.
   ---------------------------------
   As previously stated, you must use a timerequest structure with
   IND_SETTHRESH and IND_SETPERIOD.


6 Input Device / Determining the Current Qualifiers

Some applications need to know whether the user is holding down a
qualifier key or a mouse button during an operation.  To determine the
current qualifiers, you call the input device function PeekQualifier().

PeekQualifier() returns what the input device considers to be the current
qualifiers at the time PeekQualifier() is called (e.g., keyboard
qualifiers and mouse buttons).   This does not include any qualifiers
which have been added, removed or otherwise modified by input handlers.

In order to call the function, you must set a pointer to the input device
base address.  The pointer must be declared in the global data area of
your program.  Once you set the pointer, you can call the function. You
must open the device in order to access the device base address.

PeekQualifier() returns an unsigned word with bits set according to the
qualifiers in effect at the time the function is called.  It takes no
parameters.

   struct Library *InputBase;      /* Input device base address pointer */

   VOID main(VOID)
   {
   struct IOStdReq   *InputIO;     /* I/O request block */
   UWORD  Quals;                   /* qualifiers */
     .
     .
     .
   if (!OpenDevice("input.device",NULL,(struct IORequest *)InputIO,NULL))
        {
        /* Set input device base address in InputBase */
        InputBase = (struct Library *)InputIO->io_Device;

        /* Call the function */
        Quals = PeekQualifier();
        .
        .
        .
        CloseDevice(InputIO);
        }
   }
The qualifiers returned are listed in the table below.

           Bit     Qualifier               Key or Button
           ---     ---------               -------------
            0      IEQUALIFIER_LSHIFT      Left Shift
            1      IEQUALIFIER_RSHIFT      Right Shift
            2      IEQUALIFIER_CAPSLOCK    Caps Lock
            3      IEQUALIFIER_CONTROL     Control
            4      IEQUALIFIER_LALT        Left Alt
            5      IEQUALIFIER_RALT        Right Alt
            6      IEQUALIFIER_LCOMMAND    Left-Amiga
            7      IEQUALIFIER_RCOMMAND    Right-Amiga
            12     IEQUALIFIER_MIDBUTTON   Middle Mouse
            13     IEQUALIFIER_RBUTTON     Right Mouse
            14     IEQUALIFIER_LEFTBUTTON  Left Mouse


6 Input Device / Input Device and Intuition

There are several ways to receive information from the various devices
that are part of the input device. The first way is to communicate
directly with the device. This method is not recommended while the input
device task is running - which is most of the time. The second way is to
become a handler for the stream of events which the input device produces.
That method is shown above.

The third method of getting input from the input device is to retrieve the
data from the console device or from the IDCMP (Intuition Direct
Communications Message Port).   These are the preferred methods for
applications in a multitasking environment because each application can
receive juts its own input (i.e., only the input which occurs when one of
its window is active).  See the "Intuition" chapters of Amiga ROM Kernel
Reference Manual: Libraries for more information on IDCMP messages. See
the Console Device chapter of this manual for more information on
console device I/O.


6 Input Device / Additional Information on the Input Device

Additional programming information on the input device can be found in
the include files and the autodocs for the input device.  Both are
contained in the Amiga ROM Kernel Reference Manual: Includes and Autodocs.

                        Input Device Information
                  ----------------------------------
                  INCLUDES      devices/input.h
                                devices/input.i
                                devices/inputevent.h
                                devices/inputevent.i

                  AUTODOCS      input.doc


Amiga® RKM Devices: 14 Trackdisk Device

The Amiga trackdisk device directly drives the disk, controls the disk
motors, reads raw data from the tracks, and writes raw data to the tracks.
Normally, you use the AmigaDOS functions to write or read data from the
disk. The trackdisk device is the lowest-level software access to the disk
data and is used by AmigaDOS to access the disks.  The trackdisk device
supports the usual commands such as CMD_WRITE and CMD_READ.  In addition,
it supports an extended form of these commands to allow additional control
over the trackdisk device.

                    NEW FEATURES FOR VERSION 2.0

                    Feature            Description
                --------------       --------------
                TD_GETGEOMETRY       Device Command
                TD_EJECT             Device Command
                IOTF_INDEXSYNC       Device Command Flag
                IOTF_WORDSYNC        Device Command Flag
                Fast RAM Buffers     Now Supported

   Compatibility Warning:
   ----------------------
   The new features for 2.0 are not backwards compatible.

 Trackdisk Device Commands and Functions
 Device Interface
 Advanced Commands
 Disk Status Commands
 Commands for Diagnostics and Repair
 Notification of Disk Changes
 Commands for Low-Level Access
 Trackdisk Device Errors
 Example Trackdisk Program
 Additional Information on the Trackdisk Device


14 Trackdisk Device / Trackdisk Device Commands and Functions

Command          Operation
--------         ----------
CMD_CLEAR        Mark track buffer as invalid. Forces the track to be
ETD_CLEAR        re-read.  ETD_CLEAR also checks for a diskchange.

CMD_READ         Read one or more sectors from a disk.  ETD_READ also
ETD_READ         reads the sector label area and checks for a diskchange.

CMD_UPDATE       Write out track buffer if it has been changed. ETD_UPDATE
ETD_UPDATE       also checks for a diskchange.

CMD_WRITE        Write one or more sectors to a disk.  ETD_WRITE also
ETD_WRITE        writes the sector label area and checks for a diskchange.

TD_ADDCHANGEINT  Add an interrupt handler to be activated on a diskchange.

TD_CHANGENUM     Return the current value of the diskchange counter used
                 by the ETD commands to determine if a diskchange has
                 occurred.

TD_CHANGESTATE   Return the disk present/not-present status of a drive.

TD_EJECT         Eject a disk from a drive.  This command will only work
                 on drives that support an eject command (V36).

TD_FORMAT        Initialize one or more tracks with a data buffer.
ETD_FORMAT       ETD_FORMAT also initializes the sector label area.

TD_GETDRIVETYPE  Return the type of disk drive in use by the unit.

TD_GETGEOMETRY   Return the disk geometry table (V36).

TD_GETNUMTRACKS  Return the number of tracks usable with the unit.

TD_MOTOR         Turn the motor on or off.  ETD_MOTOR also checks for a
ETD_MOTOR        diskchange.

TD_PROTSTATUS    Return the write-protect status of a disk.

TD_RAWREAD       Read RAW sector data from disk (unencoded MFM).
ETD_RAWREAD      ETD_RAWREAD also checks for a diskchange.

TD_RAWWRITE      Write RAW sector data to disk.  ETD_RAWWRITE also checks
ETD_RAWWRITE     for a diskchange.

TD_REMCHANGEINT  Remove a diskchange interrupt handler.

TD_SEEK          Move the head to a specific track.  ETD_SEEK also checks
                 for a

ETD_SEEK         diskchange.

Exec Functions as Used in This Chapter
--------------------------------------
AbortIO()        Abort a command to the trackdisk device.

BeginIO()        Initiate a command and return immediately (asynchronous
                 request).

CloseDevice()    Relinquish use of a disk unit.

DoIO()           Initiate a command and wait for completion (synchronous
                 request).

OpenDevice()     Obtain exclusive use of a particular disk unit.

Exec Support Functions as Used in This Chapter
----------------------------------------------
CreateExtIO()    Create an extended I/O request structure of type IOExtTD.
                 This structure will be used to communicate commands to
                 the trackdisk device.

CreatePort()     Create a signal message port for reply messages from the
                 trackdisk device.  Exec will signal a task when a message
                 arrives at the reply port.

DeleteExtIO()    Delete an I/O request structure created by CreateExtIO().

DeletePort()     Delete the message port created by CreatePort().


14 Trackdisk Device / Device Interface

The trackdisk device operates like other Amiga devices.  To use it, you
must first open the device, then send I/O requests to it, and then close
it when finished.  See the "Introduction to Amiga System Devices"
chapter for general information on device usage.

The trackdisk device uses two different types of I/O request blocks,
IOStdReq and IOExtTD and two types of commands, standard and extended.
An IOExtTD is required for the extended trackdisk commands (those
beginning with "ETD_"), but can be used for both types of commands.
Thus, the IOExtTD is the type of I/O request that will be used in this
chapter.

    struct IOExtTD
    {
        struct  IOStdReq iotd_Req;
        ULONG   iotd_Count;         /* Diskchange counter */
        ULONG   iotd_SecLabel;      /* Sector label data */
    };

See the include file devices/trackdisk.h for the complete structure
definition.

The enhanced commands listed above - those beginning with "ETD_" - are
similar to their standard counterparts but have additional features: they
allow you to control whether a command will be executed if the disk has
been changed and they allow you to read or write to the sector label
portion of a sector.

Enhanced commands require a larger I/O request, IOExtTD, than the IOStdReq
request used by the standard commands.  IOExtTD contains extra information
needed by the enhanced command; since the standard form of a command
ignores the extra fields, IOExtTD requests can be used for both types. The
extra information takes the form of two extra longwords at the end of the
data structure.  These commands are performed only if the change count is
less than or equal to the value in the iotd_Count field of the command's
request block.

The iotd_Count field keeps old I/O requests from being performed when the
disk is changed.  Any request found with an iotd_Count less than the
current change counter value will be returned with a characteristic error
(TDERR_DiskChange) in the io_Error field. This allows stale I/O requests
to be returned to the user after a disk has been changed. The current
disk-change counter value can be obtained by TD_CHANGENUM.  If the user
wants enhanced disk I/O but does not care about disk removal, then
iotd_Count may be set to the maximum unsigned long integer value
(0xFFFFFFFF).

The iotd_SecLabel field allows access to the sector identification section
of the sector header. Each sector has 16 bytes of descriptive data space
available to it; the trackdisk device does not interpret this data.  If
iotd_SecLabel is NULL, then this descriptive data is ignored.  If it is
not NULL, then iotd_SecLabel should point to a series of contiguous
16-byte chunks (one for each sector that is to be read or written).  These
chunks will be written out to the sector's label region on a write or
filled with the sector's label area on a read.  If a CMD_WRITE (the
standard write call) is done, then the sector label area is left unchanged.

 About Amiga Floppy Disks 		 Writing To The Trackdisk Device
 Opening The Trackdisk Device 		 Closing The Trackdisk Device
 Reading From The Trackdisk Device


14 / Device Interface / About Amiga Floppy Disks

The standard 3.5 inch Amiga floppy disk consists of a number of tracks
that are NUMSECS (11) sectors of TD_SECTOR (512) usable data bytes plus
TD_LABELSIZE (16) bytes of label area. There are usually 2 tracks per
cylinder (2 heads) and 80 cylinders per disk.  The number of tracks can be
found using the TD_GETNUMTRACKS command.

For V36 and higher systems, the NUMSECS in some drives may be variable and
may change when a disk is inserted.  Use TD_GETGEOMETRY to determine the
current number of sectors.

   Think Tracks not Cylinders.
   ---------------------------
   The result is given in tracks and not cylinders. On a standard 3.5"
   drive, this gives useful space of 880K bytes plus 28K bytes of sector
   label area per floppy disk.

Although the disk is logically divided up into sectors, all I/O to the
disk is done a track at a time. This allows access to the drive with no
interleaving and increases the useful storage capacity by about 20
percent.  Each disk drive on the system has its own buffer which holds the
track data going to and from the drive.

Normally, a read of a sector will only have to copy the data from the
track buffer. If the track buffer contains another track's data, then the
buffer will first be written back to the disk (if it is "dirty") and the
new track will be read in.  All track boundaries are transparent to the
programmer (except for FORMAT, SEEK, and RAWREAD/RAWWRITE commands)
because you give the device an offset into the disk in the number of bytes
from the start of the disk. The device ensures that the correct track is
brought into memory.

The performance of the disk is greatly enhanced if you make effective use
of the track buffer. The performance of sequential reads will be up to an
order of magnitude greater than reads scattered across the disk. In
addition, only full-sector writes on sector boundaries are supported.

The trackdisk device is based upon a standard device structure. It has the
following restrictions:

   *  All reads and writes must use an io_Length that is an integer
      multiple of TD_SECTOR bytes (the sector size in bytes).

   *  The offset field must be an integer multiple of TD_SECTOR.

   *  The data buffer must be word-aligned.

   *  Under pre-V36, the data buffer must be also be in Chip RAM.


14 / Device Interface / Opening The Trackdisk Device

Three primary steps are required to open the trackdisk device:

   *  Create a message port by calling CreatePort(). Reply messages from
      the device must be directed to a message port.

   *  Create an extended I/O request structure of type IOExtTD.  The
      IOExtTD structure is created by the CreateExtIO() function.

   *  Open the trackdisk device.  Call OpenDevice(), passing it the
      extended I/O request.

For the trackdisk device, the flags parameter of the OpenDevice() function
specifies whether you are opening a 3.5" drive (flags=0) or a 5.25" drive
(flags=1).  With flags set to 0 trackdisk will only open a 3.5" drive.  To
tell the device to open any drive it understands, set the flags parameter
to TDF_ALLOW_NON_3_5.  (See the include file devices/trackdisk.h for more
information.)

   #include <devices/trackdisk.h>

   struct MsgPort *TrackMP;         /* Pointer for message port */
   struct IOExtTD *TrackIO;         /* Pointer for IORequest */

   if (TrackMP=CreatePort(0,0) )
       if (TrackIO=(struct IOExtTD *)
              CreateExtIO(TrackMP,sizeof(struct IOExtTD)) )
           if (OpenDevice(TD_NAME,0L,(struct IORequest *)TrackIO,Flags) )
               printf("%s did not open\n",TD_NAME);

   Disk Drive Unit Numbers.
   ------------------------
   The unit number - second parameter of the OpenDevice() call - can be
   any value from 0 to 3.  Unit 0 is the built-in 3.5" disk drive.
   Units 1 through 3 represent additional disk drives that may be
   connected to an Amiga system.


14 / Device Interface / Reading From The Trackdisk Device

You read from the trackdisk device by passing an IOExtTD to the device
with CMD_READ set in io_Command, the number of bytes to be read set in
io_Length, the address of the read buffer set in io_Data and the track you
want to read - specified as a byte offset from the start of the disk - set
in io_Offset.

The byte offset of a particular track is calculated by multiplying the
number of the track you want to read by the number of bytes in a track.
The number of bytes in a track is obtained by multiplying the number of
sectors (NUMSECS) by the number of bytes per sector (TD_SECTOR). Thus you
would multiply 11 by 512 to get 5632 bytes per track. To read track 15,
you would multiply 15 by 5632 giving 84,480 bytes offset from the
beginning of the disk.

    #define TRACK_SIZE ((LONG) (NUMSECS * TD_SECTOR))
    UBYTE *Readbuffer;
    SHORT tracknum;

    if (Readbuffer = AllocMem(TRACK_SIZE,MEMF_CLEAR|MEMF_CHIP))
        {
        DiskIO->iotd_Req.io_Length = TRACK_SIZE;
        DiskIO->iotd_Req.io_Data = (APTR)Readbuffer;
        DiskIO->iotd_Req.io_Offset = (ULONG)(TRACK_SIZE * track);
        DiskIO->iotd_Req.io_Command = CMD_READ;
        DoIO((struct IORequest *)DiskIO);
        }

For reads using the enhanced read command ETD_READ, the IOExtTD is set the
same as above with the addition of setting iotd_Count to the current
diskchange number.  The diskchange number is returned by the TD_CHANGENUM
command (see below).  If you wish to also read the sector label area, you
must set iotd_SecLabel to a non-NULL value.

    DiskIO->iotd_Req.io_Length = TRACK_SIZE;
    DiskIO->iotd_Req.io_Data = (APTR)Readbuffer;
    DiskIO->iotd_Req.io_Offset = (ULONG)(TRACK_SIZE * track);
    DiskIO->iotd_Count = change_count;
    DiskIO->iotd_Req.io_Command = ETD_READ;
    DoIO((struct IORequest *)DiskIO);

ETD_READ and CMD_READ obey all of the trackdisk device restrictions noted
above. They transfer data from the track buffer to the user's buffer. If
the desired sector is already in the track buffer, no disk activity is
initiated. If the desired sector is not in the buffer, the track
containing that sector is automatically read in. If the data in the
current track buffer has been modified, it is written out to the disk
before a new track is read.


14 / Device Interface / Writing To The Trackdisk Device

You write to the trackdisk device by passing an IOExtTD to the device with
CMD_WRITE set in io_Command, the number of bytes to be written set in
io_Length, the address of the write buffer set in io_Data and the track
you want to write - specified as a byte offset from the start of the
disk - set in io_Offset.

    #define TRACK_SIZE ((LONG) (NUMSECS * TD_SECTOR))
    UBYTE *Writebuffer;

    if (Writebuffer = AllocMem(TRACK_SIZE,MEMF_CLEAR|MEMF_PUBLIC))
        {
        DiskIO->iotd_Req.io_Length = TRACK_SIZE;
        DiskIO->iotd_Req.io_Data = (APTR)Writebuffer;
        DiskIO->iotd_Req.io_Offset = (ULONG)(TRACK_SIZE * tracknum);
        DiskIO->iotd_Req.io_Command = CMD_WRITE;
        DoIO((struct IORequest *)DiskIO);
        }

For writes using the enhanced write command ETD_WRITE, the IOExtTD is set
the same as above with the addition of setting iotd_Count to the current
diskchange number.  The diskchange number is returned by the TD_CHANGENUM
command (see below).  If you wish to also write the sector label area, you
must set iotd_SecLabel to a non-NULL value.

    DiskIO->iotd_Req.io_Length = TRACK_SIZE;
    DiskIO->iotd_Req.io_Data = (APTR)Writebuffer;
    DiskIO->iotd_Req.io_Offset = (ULONG)(TRACK_SIZE * tracknum);
    DiskIO->iotd_Count = change_count;
    DiskIO->iotd_Req.io_Command = ETD_WRITE;
    DoIO((struct IORequest *)DiskIO);

ETD_WRITE and CMD_WRITE obey all of the trackdisk device restrictions
noted above. They transfer data from the user's buffer to the track
buffer. If the track that contains this sector is already in the track
buffer, no disk activity is initiated. If the desired sector is not in the
buffer, the track containing that sector is automatically read in. If the
data in the current track buffer has been modified, it is written out to
the disk before a new track is read in for modification.


14 / Device Interface / Closing The Trackdisk Device

As with all devices, you must close the trackdisk device when you have
finished using it. To release the device, a CloseDevice() call is executed
with the same IOExtTD used when the device was opened. This only closes
the device and makes it available to the rest of the system. It does not
deallocate the IOExtTD structure.

    CloseDevice((struct IORequest *)DiskIO);


14 Trackdisk Device / Advanced Commands

 Determining The Drive Geometry Table 	  Updating A Track Sector
 Clearing The Track Buffer 		  Formatting A Track
 Controlling The Drive Motor 		  Ejecting A Disk


14 / Advanced Commands / Determining The Drive Geometry Table

The layout geometry of a disk drive can be determined by using the
TD_GETGEOMETRY command.  The layout can be defined three ways:

   *  TotalSectors

   *  Cylinders and CylSectors

   *  Cylinders, Heads, and TrackSectors.

Of the three, TotalSectors is the most accurate, Cylinders and CylSectors
is less so, and Cylinders, Heads and TrackSectors is the least accurate.
All are usable, though the last two may waste some portion of the
available space on some drives.

The TD_GETGEOMETRY commands returns the disk layout geometry in a
DriveGeometry structure:

    struct DriveGeometry
    {
        ULONG dg_SectorSize;      /* in bytes */
        ULONG dg_TotalSectors;    /* total # of sectors on drive */
        ULONG dg_Cylinders;       /* number of cylinders */
        ULONG dg_CylSectors;      /* number of sectors/cylinder */
        ULONG dg_Heads;           /* number of surfaces */
        ULONG dg_TrackSectors;    /* number of sectors/track */
        ULONG dg_BufMemType;      /* preferred buffer memory type */
                                  /* (usually MEMF_PUBLIC) */
        UBYTE dg_DeviceType;      /* codes as defined in the SCSI-2 spec*/
        UBYTE dg_Flags;           /* flags, including removable */
        UWORD dg_Reserved;
    };

See the include file devices/trackdisk.h for the complete structure
definition and values for the dg_DeviceType and dg_Flags fields.

You determine the drive layout geometry by passing an IOExtTD with
TD_GETGEOMETRY set in io_Command and a pointer to a DriveGeometry
structure set in io_Data.

   struct DriveGeometry *Euclid;

   Euclid = (struct DriveGeometry *)
             AllocMem(sizeof(struct DriveGeometry),
                      MEMF_PUBLIC | MEMF_CLEAR);

   DiskIO->iotd_Req.io_Data = Euclid;     /* put layout geometry here */
   DiskIO->iotd_Req.io_Command = TD_GETGEOMETRY;
   DoIO((struct IORequest *)DiskIO);

For V36 and higher versions of the operating system, TD_GETGEOMETRY is
preferred over TD_GETNUMTRACKS for determining the number of tracks on a
disk.  This is because new drive types may have more sectors or different
sector sizes, etc., than standard Amiga drives.


14 / Advanced Commands / Clearing The Track Buffer

ETD_CLEAR and CMD_CLEAR mark the track buffer as invalid, forcing a reread
of the disk on the next operation. ETD_UPDATE or CMD_UPDATE would be used
to force data out to the disk before turning the motor off. ETD_CLEAR or
CMD_CLEAR is usually used after having locked out the trackdisk device via
the use of the disk resource, when you wish to prevent the track from
being updated, or when you wish to force the track to be re-read.
ETD_CLEAR or CMD_CLEAR will not do an update, nor will an update command
do a clear.

You clear the track buffer by passing an IOExtTD to the device with
CMD_CLEAR or ETD_CLEAR set in io_Command.  For ETD_CLEAR, you must also
set iotd_Count to the current diskchange number.

   DiskIO->iotd_Req.io_Command = TD_CLEAR;
   DoIO((struct IORequest *)DiskIO);


14 / Advanced Commands / Controlling The Drive Motor

ETD_MOTOR and TD_MOTOR give you control of the motor. When the trackdisk
device executes this command, the old state of the motor is returned in
io_Actual. If io_Actual is zero, then the motor was off.  Any other value
implies that the motor was on.  If the motor is just being turned on, the
device will delay the proper amount of time to allow the drive to come up
to speed. Normally, turning the drive on is not necessary - the device
does this automatically if it receives a request when the motor is off.

However, turning the motor off is the programmer's responsibility. In
addition, the standard instructions to the user are that it is safe to
remove a disk if, and only if, the motor is off (that is, if the disk
light is off).

You control the drive motor by passing an IOExtTD to the device with
TD_MOTOR or ETD_MOTOR set in io_Command and the state you want to put the
motor in set in io_Length.  If io_Length is set to 1, the trackdisk device
will turn on the motor; a 0 will turn it off. For ETD_MOTOR, you must also
set iotd_Count to the current diskchange number.

   DiskIO->iotd_Req.io_Length = 1;          /* Turn on the drive motor */
   DiskIO->iotd_Req.io_Command = TD_MOTOR;
   DoIO((struct IORequest *)DiskIO);


14 / Advanced Commands / Updating A Track Sector

The Amiga trackdisk device does not write data sectors unless it is
necessary (you request that a different track be used) or until the user
requests that an update be performed. This improves system speed by
caching disk operations.  The update commands ensure that any buffered
data is flushed out to the disk. If the track buffer has not been changed
since the track was read in, the update commands do nothing.

You update a data sector by passing an IOExtTD to the device with
CMD_UPDATE or ETD_UPDATE set in io_Command.  For ETD_UPDATE, you must also
set iotd_Count to the current diskchange number.

   DiskIO->iotd_Req.io_Command = TD_UPDATE;
   DoIO((struct IORequest *)DiskIO);


14 / Advanced Commands / Formatting A Track

ETD_FORMAT and TD_FORMAT are used to write data to a track that either has
not yet been formatted or has had a hard error on a standard write
command. TD_FORMAT completely ignores all data currently on a track and
does not check for disk change before performing the command. The device
will format the requested tracks, filling each sector with the contents of
the buffer pointed to by io_Data field. You should do a read pass to
verify the data.

If you have a hard write error during a normal write, you may find it
possible to use the TD_FORMAT command to reformat the track as part of
your error recovery process. ETD_FORMAT will write the sector label area
if the iotd_SecLabel is non-NULL.

You format a track by passing an IOExtTD to the device with TD_FORMAT or
ETD_FORMAT set in io_Command, io_Data set to at least track worth of data,
io_Offset field set to the byte offset of the track you want to write and
the io_Length set to the length of a track. For ETD_FORMAT, you must also
set iotd_Count to the current diskchange number.

    #define TRACK_SIZE ((LONG) (NUMSECS * TD_SECTOR))
    UBYTE *Writebuffer;

    if (WriteBuffer = AllocMem(TRACK_SIZE,MEMF_CLEAR|MEMF_CHIP))
        {
        DiskIO->iotd_Req.io_Length=TRACK_SIZE;
        DiskIO->iotd_Req.io_Data=(APTR)Writebuffer;
        DiskIO->iotd_Req.io_Offset=(ULONG)(TRACK_SIZE * track);
        DiskIO->iotd_Req.io_Command = TD_FORMAT;
        DoIO((struct IORequest *)DiskIO);
        }


14 / Advanced Commands / Ejecting A Disk

Certain disk drive manufacturers allow software control of disk ejection.
The trackdisk device provides the TD_EJECT command to tell such drives to
eject a disk.

You eject a disk by passing an IOExtTD to the device with TD_EJECT set in
io_Command.

   DiskIO->iotd_Req.io_Command = TD_EJECT;
   DoIO((struct IORequest *)DiskIO);

   Read the Instruction Manual.
   ----------------------------
   The Commodore 3.5" drives for the Amiga and most other Amiga drive
   manufacturers do not support software disk ejects.  Attempting this
   command on those drives will result in an error condition.  Consult
   the instruction manual for your disk drive to determine whether this
   is supported.


14 Trackdisk Device / Disk Status Commands

Disk status commands return status on the current disk in the opened unit.
These commands may be done with quick I/O and thus may be called within
interrupt handlers (such as the trackdisk disk change handler). See the
"Exec: Device Input/Output" chapter of the Amiga ROM Kernel Reference
Manual: Libraries for more detailed information on quick I/O.

 Determining The Presence Of A Disk
 Determining The Write-Protect Status Of A Disk
 Determining The Drive Type
 Determining The Number Of Tracks Of A Drive
 Determining The Current Diskchange Number


14 / Disk Status Commands / Determining The Presence Of A Disk

You determine the presence of a disk in a drive by passing an IOExtTD to
the device with TD_CHANGESTATE set in io_Command.  For quick I/O, you must
set io_Flags to IOF_QUICK.

   DiskIO->iotd_Req.io_Flags = IOF_QUICK;
   DiskIO->iotd_Req.io_Command = TD_CHANGESTATE;
   BeginIO((struct IORequest *)DiskIO);

TD_CHANGESTATE returns the presence indicator of a disk in io_Actual. The
value returned will be zero if a disk is currently in the drive and
nonzero if the drive has no disk.


14 / Disk Status Commands / Determining The Write-Protect Status Of A Disk

You determine the write-protect status of a disk by passing an IOExtTD to
the device with TD_PROTSTATUS set in io_Command.  For quick I/O, you must
set io_Flags to IOF_QUICK.

   DiskIO->iotd_Req.io_Flags = IOF_QUICK;
   DiskIO->iotd_Req.io_Command = TD_PROTSTATUS;
   BeginIO((struct IORequest *)DiskIO);

TD_PROTSTATUS returns the write-protect status in io_Actual. The value
will be zero if the disk is not write-protected and nonzero if the disk is
write-protected.


14 / Disk Status Commands / Determining The Drive Type

You determine the drive type of a unit by passing an IOExtTD to the device
with TD_GETDRIVETYPE set in io_Command.  For quick I/O, you must set
io_Flags to IOF_QUICK.

   DiskIO->iotd_Req.io_Flags = IOF_QUICK;
   DiskIO->iotd_Req.io_Command = TD_GETDRIVETYPE;
   BeginIO((struct IORequest *)DiskIO);

TD_GETDRIVETYPE returns the drive type for the unit that was opened in
io_Actual. The value will be DRIVE3_5 for 3.5" drives and DRIVE5_25 for
5.25" drives.  The unit can be opened only if the device understands the
drive type it is connected to.


14 / Disk Status Commands / Determining The Number Of Tracks Of A Drive

You determine the number of a tracks of a drive by passing an IOExtTD to
the device with TD_GETNUMTRACKS set in io_Command.  For quick I/O, you
must set io_Flags to IOF_QUICK.

    DiskIO->iotd_Req.io_Flags = IOF_QUICK;
    DiskIO->iotd_Req.io_Command = TD_GETNUMTRACKS;
    BeginIO((struct IORequest *)DiskIO);

TD_GETNUMTRACKS returns the number of tracks on that device in io_Actual.
This is the number of tracks of TD_SECTOR * NUMSECS size. It is not the
number of cylinders. With two heads, the number of cylinders is half of
the number of tracks.  The number of cylinders is equal to the number of
tracks divided by the number of heads (surfaces).  The standard 3.5" Amiga
drive has two heads

TD_GETGEOMETRY is the preferred over TD_GETNUMTRACKS for V36 and higher
versions of the operating system especially since new drive types may have
more sectors or different sector sizes, etc., than standard Amiga drives.


14 / Disk Status Commands / Determining The Current Diskchange Number

You determine the current diskchange number of a disk by passing an
IOExtTD to the device with TD_CHANGENUM set in io_Command.  For quick I/O,
you must set io_Flags to IOF_QUICK.

    DiskIO->iotd_Req.io_Flags = IOF_QUICK;
    DiskIO->iotd_Req.io_Command = TD_CHANGENUM;
    BeginIO((struct IORequest *)DiskIO);

TD_CHANGENUM returns the current value of the diskchange counter (as used
by the enhanced commands) in io_Actual. The disk change counter is
incremented each time the disk is inserted or removed.

    ULONG change_count;

    DiskIO->iotd_Req.io_Flags = IOF_QUICK;
    DiskIO->iotd_Req.io_Command = TD_CHANGENUM;
    BeginIO((struct IORequest *)DiskIO);
    /* store current diskchange value */
    change_count = DiskIO->iotd_Req.io_Actual;

    DiskIO->iotd_Req.io_Length = 1;     /* Turn on the drive motor */
    DiskIO->iotd_Count = change_count;
    DiskIO->iotd_Req.io_Command = ETD_MOTOR;
    DoIO((struct IORequest *)DiskIO);


14 Trackdisk Device / Commands for Diagnostics and Repair

The trackdisk device provides commands to move the drive heads to a
specific track. These commands are provided for internal diagnostics, disk
repair, and head cleaning only.

 Moving The Drive Head To A Specific Track


14 / Diagnostics and Repair / Moving The Drive Head To A Specific Track

You move the drive head to a specific track by passing an IOExtTD to the
device with TD_SEEK or ETD_SEEK set in io_Command, and io_Offset set to
the byte offset of the track to which the seek is to occur.

    DiskIO->iotd_Req.io_Offset = (ULONG)(TRACK_SIZE * track);
    DiskIO->iotd_Req.io_Command = TD_SEEK;
    DoIO((struct IORequest *)DiskIO);

   Seeking is not Reading.
   -----------------------
   TD_SEEK and ETD_SEEK do not verify their position until the next
   read. That is, they only move the heads; they do not actually read
   any data.


14 Trackdisk Device / Notification of Disk Changes

Many programs will wish to be notified if the user has changed the disk in
the active drive. While this can be done via the Intuition DISKREMOVED and
DISKINSERTED messages, sometimes more tightly controlled testing is
required.  The trackdisk device provides commands to initiate interrupt
processing when disks change.

 Adding A Diskchange Software Interrupt Handler
 Removing A Diskchange Software Interrupt Handler


14 / / Adding A Diskchange Software Interrupt Handler

The trackdisk device lets you add a software interrupt handler that will
be Cause()'ed when a disk insert or remove occurs.   Within the handler,
you may only call the status commands that can use IOF_QUICK.

You add a software interrupt handler by passing an IOExtTD to the device
with a pointer to an Interrupt structure set in io_Data, the length of the
structure set in io_Length and TD_ADDCHANGEINT set in io_Command.

   DiskIO->iotd_Req.io_Length = sizeof(struct Interrupt)
   DiskIO->iotd_Req.io_Data   = (APTR)Disk_Interrupt;
   DiskIO->iotd_Req.io_Command = TD_ADDCHANGEINT;
   SendIO((struct IORequest *)DiskIO);

   Going, going, gone.
   -------------------
   This command does not return when executed. It holds onto the
   IORequest until the TD_REMCHANGEINT command is executed with that
   same IORequest.  Hence, you must use SendIO() with this command.


14 / / Removing A Diskchange Software Interrupt Handler

You remove a software interrupt handler by passing an IOExtTD to the
device with a pointer to an Interrupt structure set in io_Data, the length
of the structure set in io_Length and TD_REMCHANGEINT set in io_Command.
You must pass it the same Interrupt structure used to add the handler.

    DiskIO->iotd_Req.io_Length = sizeof(struct Interrupt)
    DiskIO->iotd_Req.io_Data   = (APTR)Disk_Interrupt;
    DiskIO->iotd_Req.io_Command = TD_REMCHANGEINT;
    DoIO((struct IORequest *)DiskIO);

   Don't use with pre-V36 and earlier versions.
   --------------------------------------------
   Under pre-V36 and earlier versions of the Amiga system software,
   TD_REMCHANGEINT does not work and should not be used.  Instead, use
   the workaround listed in the "trackdisk.doc" of the Amiga ROM
   Kernel Reference Manual: Includes and Autodocs.


14 Trackdisk Device / Commands for Low-Level Access

The trackdisk device provides commands to read and write raw flux changes
on the disk. The data returned from a low-level read or sent via a
low-level write should be encoded into some form of legal flux patterns.
See the Amiga Hardware Reference Manual and books on magnetic media
recording and reading.

   Proceed at your own risk with V1.3 and earlier versions.
   --------------------------------------------------------
   In V1.3 Kickstart and earlier these functions are unreliable even
   though under certain configurations the commands may appear to work.

 Reading Raw Data From A Disk
 Writing Raw Data To A Disk
 Limitations For Synced Reads And Writes


14 / Commands for Low-Level Access / Reading Raw Data From A Disk

ETD_RAWREAD and TD_RAWREAD perform a raw read from a track on the disk.
They seek to the specified track and read it into the user's buffer.

No processing of the track is done. It will appear exactly as the bits
come off the disk - typically in some legal flux format (such as MFM, FM,
GCR, etc; if you don't know what these are, you shouldn't be using this
call). Caveat programmer.

This interface is intended for sophisticated programming only. You must
fully understand digital magnetic recording to be able to utilize this
call. It is also important that you understand that the MFM encoding
scheme used by the higher level trackdisk routines may change without
notice. Thus, this routine is only really useful for reading and decoding
other disks such as MS-DOS formatted disks.

You read raw data from a disk by passing an IOExtTD to the device with
TD_RAWREAD or ETD_RAWREAD set in io_Command, the number of bytes to be
read set in io_Length (maximum 32K), a pointer to the read buffer set in
io_Data, and io_Offset set to the byte offset of the track where you want
to the read to begin.  For ETD_RAWREAD, you must also set iotd_Count to
the current diskchange number.

  DiskIO->iotd_Req.io_Length = 1024;          /* number of bytes to read */
  DiskIO->iotd_Req.io_Data = (APTR)Readbuffer; /* pointer to buffer */
  DiskIO->iotd_Req.io_Offset = (ULONG)(TRACK_SIZE * track); /* track no. */
  DiskIO->iotd_Req.io_Flags = IOTDF_INDEX      /* Set for index sync */
  DiskIO->iotd_Count = change_count;           /* diskchange number */
  DiskIO->iotd_Req.io_Command = ETD_RAWREAD;
  DoIO((struct IORequest *)DiskIO);

A raw read may be synched with the index pulse by setting the
IOTDF_INDEXSYNC flag or synched with a $4489 sync pattern by setting the
IOTDF_WORDSYNC flag.  See the "trackdisk.doc" of the Amiga ROM Kernel
Reference Manual: Includes and Autodocs for more information about these
flags.

   Forewarned is Forearmed.
   ------------------------
   Amiga, Inc. may make enhancements to the disk format in the
   future. Amiga, Inc. intends to provide compatibility within the
   trackdisk device.  Anyone who uses these raw routines is bypassing
   this upward-compatibility and does so at her own risk.


14 / Commands for Low-Level Access / Writing Raw Data To A Disk

ETD_RAWWRITE and TD_RAWWRITE perform a raw write to a track on the disk.
They seek to the specified track and write it from the user's buffer.

No processing of the track is done. It will be written exactly as the bits
come out of the buffer - typically in some legal flux format (such as
MFM, FM, GCR; if you don't know what these are, you shouldn't be using
this call). Caveat Programmer.

This interface is intended for sophisticated programming only. You must
fully understand digital magnetic recording to be able to utilize this
call. It is also important that you understand that the MFM encoding
scheme used by the higher level trackdisk routines may change without
notice. Thus, this routine is only really useful for encoding and writing
other disk formats such as MS-DOS disks.

You write raw data to a disk by passing an IOExtTD to the device with
TD_RAWWRITE or ETD_RAWWRITE set in io_Command, the number of bytes to be
written set in io_Length (maximum 32K), a pointer to the write buffer set
in io_Data, and io_Offset set to the byte offset of the track where you
want to the write to begin.  For ETD_RAWWRITE, you must also set
iotd_Count to the current diskchange number.

  DiskIO->iotd_Req.io_Length = 1024;         /* number of bytes to write */
  DiskIO->iotd_Req.io_Data = (APTR)Writebuffer; /* pointer to buffer */
  DiskIO->iotd_Req.io_Offset = (ULONG)(TRACK_SIZE * track); /* track no. */
  DiskIO->iotd_Req.io_Flags = IOTDF_INDEX      /* Set for index sync */
  DiskIO->iotd_Count = change_count;           /* diskchange number */
  DiskIO->iotd_Req.io_Command = ETD_RAWWRITE;
  DoIO((struct IORequest *)DiskIO);

A raw read may be synched with the index pulse by setting the
IOTDF_INDEXSYNC flag or synched with a $4489 sync pattern by setting the
IOTDF_WORDSYNC flag.  See the "trackdisk.doc" of the Amiga ROM Kernel
Reference Manual: Includes and Autodocs for more information about these
flags.


14 / Low-Level Access Commands / Limitations For Synced Reads And Writes

There is a delay between the index pulse and the start of bits coming in
from the drive (e.g. dma started). It is in the range of 135-200
microseconds. This delay breaks down as follows: 55 microseconds for
software interrupt overhead (this is the time from interrupt to the write
of the DSKLEN register); 66 microsecs for one horizontal line delay
(remember that disk I/O is synchronized with Agnus' display fetches). The
last variable (0-65 microseconds) is an additional scan line since DSKLEN
is poked anywhere in the horizontal line. This leaves 15 microseconds
unaccounted for. In short, you will almost never get bits within the first
135 microseconds of the index pulse, and may not get it until 200
microseconds. At 4 microsecs/bit, this works out to be between 4 and 7
bytes of user data delay.

   Forewarned is Forearmed.
   ------------------------
   Amiga, Inc. may make enhancements to the disk format in the
   future. Amiga, Inc. intends to provide compatibility within the
   trackdisk device.  Anyone who uses these raw routines is bypassing
   this upward-compatibility and does so at her own risk.


14 Trackdisk Device / Trackdisk Device Errors

The trackdisk device returns error codes whenever an operation is
attempted.

    DiskIO->iotd_Req.io_Length = TRACK_SIZE;
    DiskIO->iotd_Req.io_Data = (APTR)Writebuffer;
    DiskIO->iotd_Req.io_Offset = (ULONG)(TRACK_SIZE * tracknum);
    DiskIO->iotd_Count = change_count;
    DiskIO->iotd_Req.io_Command = ETD_WRITE;
    if (DoIO((struct IORequest *)DiskIO))
        printf("ETD_WRITE failed.  Error: %ld\n",DiskIO-iotd.io_Error);

When an error occurs, these error numbers will be returned in the io_Error
field of your IOExtTD block.

              TRACKDISK DEVICE ERROR CODES

        Error       Value         Explanation
------------------  ----- -----------------------------
TDERR_NotSpecified   20   Error could not be determined
TDERR_NoSecHdr       21   Could not find sector header
TDERR_BadSecPreamble 22   Error in sector preamble
TDERR_BadSecID       23   Error in sector identifier
TDERR_BadHdrSum      24   Header field has bad checksum
TDERR_BadSecSum      25   Sector data field has bad checksum
TDERR_TooFewSecs     26   Incorrect number of sectors on track
TDERR_BadSecHdr      27   Unable to read sector header
TDERR_WriteProt      28   Disk is write-protected
TDERR_DiskChanged    29   Disk has been changed or is not currently present
TDERR_SeekError      30   While verifying seek position, found seek error
TDERR_NoMem          31   Not enough memory to do this operation
TDERR_BadUnitNum     32   Bad unit number (unit # not attached)
TDERR_BadDriveType   33   Bad drive type (not an Amiga 3 1/2 inch disk)
TDERR_DriveInUse     34   Drive already in use (only one task exclusive)
TDERR_PostReset      35   User hit reset; awaiting doom


14 Trackdisk Device / Additional Information on the Trackdisk Device

Additional programming information on the trackdisk device can be found in
the include files and the autodocs for the trackdisk device.  Both are
contained in the Amiga ROM Kernel Reference Manual: Includes and Autodocs.

                      Trackdisk Device Information
                  -----------------------------------
                  INCLUDES        devices/trackdisk.h
                                  devices/trackdisk.h

                  AUTODOCS        trackdisk.doc


Amiga® RKM Devices: 7 Keyboard Device

The keyboard device gives low-level access to the Amiga keyboard.  When
you send this device the command to read one or more keystrokes from the
keyboard, for each keystroke (whether key-up or key-down) the keyboard
device creates a data structure called an input event to describe what
happened. The keyboard device also provides the ability to do operations
within the system reset processing (Ctrl-Amiga-Amiga).

 Keyboard Device Commands and Functions
 Device Interface
 Reading the Keyboard Matrix
 Amiga Reset Handling
 Reading Keyboard Events
 Additional Information on the Keyboard Device


7 Keyboard Device / Keyboard Device Commands and Functions

Command               Operation
-------               ---------
CMD_CLEAR             Clear the keyboard input buffer.  Removes any key
                      transitions from the input buffer.

KBD_ADDRESETHANDLER   Add a reset handler function to the list of
                      functions called  by the keyboard device to clean up
                      before a hard reset.

KBD_REMRESETHANDLER   Remove a previously added reset handler from the
                      list of functions called by the keyboard device to
                      clean up before a hard reset.

KBD_RESETHANDLERDONE  Indicate that a handler has completed its job and
                      reset could possibly occur now.

KBD_READMATRIX        Read the state of every key in the keyboard.  Tells
                      the up/down state of every key.

KBD_READEVENT         Read one (or more) raw key event from the keyboard
                      device.

Exec Functions as Used in This Chapter
--------------------------------------
AbortIO()             Abort a command to the keyboard device.

AllocMem()            Allocate a block of memory.

CheckIO()             Return the status of an I/O request.

CloseDevice()         Relinquish use of the keyboard device.

DoIO()                Initiate a command and wait for it to complete
                      (synchronous request).

FreeMem()             Free a block of previously allocated memory.

OpenDevice()          Obtain use of the keyboard device.

SendIO()              Initiate a command and return immediately
                      (asynchronous request).

WaitIO()              Wait for the completion of an asynchronous request.
                      When the request is complete the message will be
                      removed from reply port.

Exec Support Functions as Used in This Chapter
----------------------------------------------
CreateExtIO()         Create an extended I/O request structure.  This
                      structure will be used to communicate commands to
                      the keyboard device.

CreatePort()          Create a signal message port for reply messages from
                      the keyboard device.  Exec will signal a task when a
                      message arrives at the port.

DeleteExtIO()         Delete an extended I/O request structure created by
                      CreateExtIO().

DeletePort()          Delete the message port created by CreatePort().


7 Keyboard Device / Device Interface

The keyboard device operates like the other Amiga devices.  To use it, you
must first open the keyboard device, then send I/O requests to it, and
then close it when finished.  See the "Introduction to Amiga System Devices"
chapter for general information on device usage.

The I/O request used by the keyboard device is called IOStdReq.

    struct IOStdReq
    {
        struct  Message io_Message;
        struct  Device  *io_Device; /* device node pointer  */
        struct  Unit    *io_Unit;   /* unit (driver private)*/
        UWORD   io_Command;         /* device command */
        UBYTE   io_Flags;
        BYTE    io_Error;        /* error or warning num */
        ULONG   io_Actual;       /* actual number of bytes transferred */
        ULONG   io_Length;       /* requested number bytes transferred*/
        APTR    io_Data;         /* points to data area */
        ULONG   io_Offset;       /* offset for block structured devices */
    };

See the include file exec/io.h for the complete structure definition.

 Opening The Keyboard Device
 Closing The Keyboard Device


7 / Device Interface / Opening The Keyboard Device

Three primary steps are required to open the keyboard device:

   *  Create a message port using the CreatePort() function.

   *  Create an extended I/O request structure using the CreateExtIO()
      function. CreateExtIO() will initialize the I/O request with your
      reply port.

   *  Open the keyboard device. Call OpenDevice(), passing the I/O request.

struct MsgPort  *KeyMP;         /* Pointer for Message Port */
struct IOStdReq *KeyIO;         /* Pointer for I/O request */

if (KeyMP=CreatePort(NULL,NULL))
  if (KeyIO=(struct IOStdReq *)CreateExtIO(KeyMP,sizeof(struct IOStdReq)))
    if (OpenDevice( "keyboard.device",NULL,(struct IORequest *)KeyIO,NULL))
        printf("keyboard.device did not open\n");


7 / Device Interface / Closing The Keyboard Device

An OpenDevice() must eventually be matched by a call to CloseDevice().

All I/O requests must be complete before CloseDevice().  If any requests
are still pending, abort them with AbortIO() and remove them with WaitIO().

   if (!(CheckIO(KeyIO)))
       {
       AbortIO(KeyIO);  /* Ask device to abort request, if pending */
       }
       WaitIO(KeyIO);   /* Wait for abort, then clean up */
   CloseDevice(KeyIO);


7 Keyboard Device / Reading the Keyboard Matrix

The KBD_READMATRIX command returns the current state of every key in the
key matrix (up = 0,  down = 1). You provide a data area that is at least
large enough to hold one bit per key, approximately 16 bytes.  The
keyboard layout for the A500, A2000 and A3000 is shown in the figure
below, indicating the raw numeric value that each key transmits when it is
pressed.  This value is the numeric position that the key occupies in the
key matrix.

     Figure 7-1 - Keyboard Layout

The following example will read the key matrix and display the up-down
state of all of the elements in the matrix in a table.  Reading the column
header and then the row number as a hex number gives you the raw key code.

     Read_Keyboard_Matrix.c

In addition to the matrix data returned in io_Data, io_Actual
returns the number of bytes filled in io_Data with key matrix data,
i.e., the minimum of the supplied length and the internal key matrix
size.

    Value of io_Length.
    -------------------
    A value of 13 in the io_Length field will be sufficient for most
    keyboards; extended keyboards will require a larger number.  However,
    you must always set this field to 13 for V34 and earlier versions of
    Kickstart.

To find the status of a particular key - for example, to find out if the
F2 key is down - you find the bit that specifies the current state by
dividing the key matrix value by 8. Since hex 51 = 81, this indicates that
the bit is in byte number 10 of the matrix. Then take the same number
(decimal 81) and use modulo 8 to determine which bit position within that
byte represents the state of the key. This yields a value of 1. So, by
reading bit position 1 of byte number 10, you determine the status of the
function key F2.


7 Keyboard Device / Amiga Reset Handling

 When a user presses the Ctrl key and both left- and right-Amiga keys
simulataneously (the reset sequence), the keyboard device senses this and
calls a prioritized chain of reset-handlers. These might be thought of as
clean-up routines that "must" be performed before reset is allowed to
occur. For example, if a disk write is in progress, the system should
finish that before resetting the hardware so as not to corrupt the
contents of the disk.

It is important to note that not all Amigas handle reset processing in the
same way.  On the A500, the reset key sequence sends a hardware reset
signal and never goes through the reset handlers.  Also some of the early
A2000s (i.e., German keyboards with the function keys the same size as the
Esc key) do not handle the reset via the reset handlers.  It is thus
recommended that your application not rely on the reset handler abilities
of the keyboard device.

 Adding A Reset Handler (KBD_ADDRESETHANDLER)
 Removing A Reset Handler (KBD_REMRESETHANDLER)
 Ending A Reset Task (KBD_RESETHANDLERDONE)


7 / Amiga Reset Handling / Adding A Reset Handler (KBD_ADDRESETHANDLER)

The KBD_ADDRESETHANDLER command adds a custom routine to the chain of
reset-handlers.  Reset handlers are just like any other handler and are
added to the handler list with an Interrupt structure.  The priority field
in the list node of the Interrupt structure establishes the sequence in
which reset handlers are processed by the system.  Keyboard reset handlers
are currently limited to the priority values of a software interrupt, that
is, values of -32, -16, 0, 16, and 32.

The io_Data field of the I/O request is filled in with a pointer to the
Interrupt structure and the io_Command field is set to
KBD_ADDRESETHANDLER.  These are the only two fields you need to initialize
to add a reset handler.  Any return value from the command is ignored.
All keyboard reset handlers are activated if time permits.  Normally, a
reset handler will just signal the requisite task and return.  The task
then does whatever processing it needs to do and notifies the system that
it is done by using the KBD_RESETHANDLERDONE command described below.

   Non-interference and speed are the keys to success.
   ---------------------------------------------------
   If you add your own handler to the chain, you must ensure that your
   handler allows the rest of reset processing to occur.  Reset must
   continue to function.  Also, if you don't execute your reset code
   fast enough, the system will still reboot (about 10 seconds).


7 / Amiga Reset Handling / Removing A Reset Handler (KBD_REMRESETHANDLER)

This command is used to remove a keyboard reset handler from the system.
You need to supply the same Interrupt structure to this command that you
used with the KBD_ADDRESETHANDLER command.


7 / Amiga Reset Handling / Ending A Reset Task (KBD_RESETHANDLERDONE)

This command tells the system that your reset handling code has completed.
If you are the last outstanding reset handler, the system will reset after
this call.

    Can't Stop, Got No Brakes.
    --------------------------
    After 10 seconds, the system will reboot, regardless of outstanding
    reset handlers.

Here is an example program that installs a reset handler and either waits
for the reboot or for the user to close the window. If there was a reboot,
the window will close and, if executed from the shell, it will display a
few messages. If the user closes the window, the handler is removed and
the program exits cleanly.

     Key_Reset.c


7 Keyboard Device / Reading Keyboard Events

Reading keyboard events is normally not done through direct access to the
keyboard device. (Higher level devices such as the input device and
console device are available for this.  See the chapter Input Device
for more information on the intimate linkage between the input device and
the keyboard device.)  This section is provided primarily to show you the
component parts of a keyboard input event.

The keyboard matrix figure shown at the beginning of this chapter gives
the code value that each key places into the ie_Code field of the input
event for a key-down event. For a key-up event, a value of hexadecimal 80
is or'ed with the value shown above. Additionally, if either shift key is
down, or if the key is one of those in the numeric keypad, the qualifier
field of the keyboard input event will be filled in accordingly. In V34
and earlier versions of Kickstart, the keyboard device does not set the
numeric qualifier for the keypad keys "(", ")", "/", "*" and "+".

When you ask to read events from the keyboard, the call will not be
satisfied until at least one keyboard event is available to be returned.
The io_Length field must contain the number of bytes available in io_Data
to insert events into. Thus, you should use a multiple of the number of
bytes in an InputEvent (see example below).

    Type-Ahead Processing.
    ----------------------
    The keyboard device can queue up several keystrokes without a task
    requesting a report of keyboard events. However, when the keyboard
    event buffer has been filled with no task interaction, additional
    keystrokes will be discarded.

     Example Read Keyboard Event Program


7 Keyboard Device / Additional Information on the Keyboard Device

Additional programming information on the keyboard device can be found in
the include files for the keyboard and input devices and the Autodocs for
the keyboard device.  All are contained in the Amiga ROM Kernel Reference
Manual: Includes and Autodocs.

                       Keyboard Device Information
                     --------------------------------
                     INCLUDES     devices/keyboard.h
                                  devices/keyboard.i
                                  devices/inputevent.h
                                  devices/inputevent.i

                     AUTODOCS     keyboard.doc


Amiga® RKM Devices: 15 Resources

The Amiga's low-level hardware control functions are collectively referred
to as "Resources".  Most applications will never need to use the
hardware at the resource level - the Amiga's device interface is much more
convenient and provides for multitasking.  However, some high performance
applications, such as MIDI time stamping, may require direct access to the
Amiga hardware registers.

                     NEW FEATURES FOR VERSION 2.0

                     Feature         Description
                     ---------       ------------
                     BattClock       New resource
                     BattMem         New resource
                     FileSystem      New resource

   Compatibility Warning:
   ----------------------
   The new features for 2.0 are not backwards compatible.

 The Amiga Resources      BattMem Resource      FileSystem Resource
 Resource Interface       CIA Resource          Misc Resource
 BattClock Resource       Disk Resource         Potgo Resource


15 Resources / The Amiga Resources

There are currently seven standard resources in the Amiga system.  The
following lists the name of each resource and its function.

battclock.resource
   grants access to the battery-backed clock chip.

battmem.resource
   grants access to non-volatile RAM.

cia.resource
   grants access to the interrupts and timer bits of the 8520 CIA
   (Complex Interface Adapter) chips.

disk.resource
   grants temporary exclusive access to the disk hardware.

FileSystem.resource
   grants access to the file system.

misc.resource
   grants exclusive access to functional blocks of chip registers.  At
   present, definitions have been made for the serial and parallel
   hardware only.

potgo.resource
   manages the bits of the proportional I/O pins on the game controller
   ports.

The resources allow you direct access to the hardware in a way that is
compatible with multitasking.  They also allow you to temporarily bar
other tasks from using the resource.  You may then use the associated
hardware directly for your special purposes.  If applicable, you must
return the resource back to the system for other tasks to use when you are
finished with it.

See the Amiga Hardware Reference Manual for detailed information on the
actual hardware involved.

   Look Before You Leap.
   ---------------------
   Resources are just one step above direct hardware manipulation. You
   are advised to try the higher level device and library approach
   before resorting to the hardware.


15 Resources / Resource Interface

Resources provide functions that you call to do low-level operations with
the hardware they access.  In order to use the functions of a resource,
you must obtain a pointer to the resource.  This is done by calling the
OpenResource() function with the resource name as its argument.

OpenResource() returns a pointer to the resource you request or NULL
if it does not exist.

    #include <resources/filesysres.h>

    struct FileSysResource *FileSysResBase = NULL;

    if (!(FileSysResBase = OpenResource(FSRNAME)))
        printf("Cannot open %s\n",FSRNAME);

There is no CloseResource() function.  When you are done with a resource,
you are done with it.  However, as you will see later in this chapter,
some resources provide functions to allocate parts of the hardware they
access. In those cases, you will have to free those parts for anyone else
to use them.

Each resource has at least one include file in the resources subdirectory
of the include directory.  Some of the include files contain only the name
of the resource; others list structures and bit definitions used by the
resource.  The include files will be listed at the end of this chapter.

Calling a resource function is the same as calling any other function on
the Amiga.  You have to know what parameters it accepts and the return
value, if any.  The Autodocs for each resource lists the functions and
their requirements.

    #include <hardware/cia.h>
    #include <resources/cia.h>

    struct Library *CIAResource = NULL;

    void main()
    {

    WORD mask = 0;

    if (!(CIAResource = OpenResource(CIABNAME)))
        printf("Cannot open %s\n",CIABNAME);
    else
       {
        /* What is the interrupt enable mask? */
         mask = AbleICR(CIAResource,0);

        printf("\nThe CIA interrupt enable mask: %x \n",mask);
       }
    }

   Looks Can Be Deceiving.
   -----------------------
   Some resources may look like libraries and act like libraries, but be
   assured they are not libraries.


15 Resources / BattClock Resource

The battery-backed clock (BattClock) keeps Amiga time while the system is
powered off.  The time from the BattClock is loaded into the Amiga system
clock as part of the boot sequence.

The battclock resource provides access to the BattClock.  Three functions
allow you to read the BattClock value, reset it and set it to a value you
desire.

                           BattClock Resource Functions
                           ----------------------------
     ReadBattClock()       Read the time from the BattClock and
                           returns it as the number of seconds since
                           12:00 AM, January 1, 1978.

     ResetBattClock()      Reset the BattClock to 12:00 AM, January 1,
                           1978.

     WriteBattClock()      Set the BattClock to the number of seconds
                           you pass it relative to 12:00 AM, January
                           1, 1978.

The utility.library contains time functions which convert the number of
seconds since 12:00 AM, January 1, 1978 to a date and time we can
understand, and vice versa.  You will find these functions useful when
dealing with the BattClock.  The example program below uses the
Amiga2Date() utility function to convert  the value returned by
ReadBattClock().  See the "Utility Library" chapter of the Amiga ROM
Kernel Reference Manual: Libraries for a discussion of the utility.library
and the Amiga ROM Kernel Reference Manual: Includes and Autodocs for a
listing of its functions.

   So, You Want to Be A Time Lord?
   -------------------------------
   This resource will allow you to set the BattClock to any value you
   desire. Keep in mind that this time will endure a reboot and could
   adversely affect your system.

     Read_BattClock.c

Additional programming information on the battclock resource can be found
in the include files and the Autodocs for the battclock resource and the
utility library.


15 Resources / BattMem Resource

The battery-backed memory (BattMem) preserves a small portion of Amiga
memory while the system is powered off.  Some of the information stored in
this memory is used during the system boot sequence.

The battmem resource provides access to the BattMem.  Four functions allow
you to use the BattMem.

                              BattMemResource Functions
                              -------------------------
     ObtainBattSemaphore()    Obtain exclusive access to the BattMem.

     ReadBattMem()            Read a bitstring from the BattMem.  You
                              specify the bit position and the number of
                              bits you wish to read.

     ReleaseBattSemaphore()   Relinquish exclusive access to the BattMem.

     WriteBattMem()           Write a bitstring to the BattMem.  You
                              specify the bit position and the number of
                              bits you wish to write.

The system considers BattMem to be a set of bits rather than bytes. This
is done to conserve the limited space available. All bits are reserved,
and applications should not read, or write undefined bits. Writing bits
should be done with extreme caution since the settings will survive
power-down/power-up. You can find the bit definitions in the BattMem
include files resources/battmembitsamiga.h, resources/battmembitsamix.h
and resources/battmembitsshared.h. They should be consulted before you do
anything with the resource.

   You Don't Need This Resource.
   -----------------------------
   The BattMem resource is basically for system use only.  There is
   generally no reason for applications to use it. It is documented here
   simply for completeness.

Additional information on the battmem resource can be found in the include
files and the Autodocs for the battmem resource.

                        BattMem Resource Information
                --------------------------------------------
                INCLUDES        resources/battmem.i
                                resources/battmembitsamiga.h
                                resources/battmembitsamix.h
                                resources/battmembitsshared.h
                AUTODOCS        battmem.doc


15 Resources / CIA Resource

The CIA resource provides access to the timers and timer interrupt bits of
the 8520 Complex Interface Adapter (CIA) A and B chips.   This resource is
intended for use by high performance timing applications such as MIDI time
stamping and SMPTE time coding.

Four functions allow you to interact with the CIA hardware.

                           CIA Resource Functions
                           ----------------------
     AbleICR()             Enable or disable Interrupt Control
                           Register interrupts.  Can also return the
                           current or previous enabled interrupt mask.

     AddICRVector()        Allocate one of the CIA timers by assigning
                           an interrupt handler to an interrupt bit
                           and enabling the interrupt of one of the
                           timers. If the timer you request is not
                           available, a pointer to the interrupt
                           structure that owns it will be returned.

     RemICRVector()        Remove an interrupt handler from an
                           interrupt bit and disable the interrupt.

     SetICR()              Cause or clear one or more interrupts, or
                           return the current or previous interrupt
                           status.

Each CIA chip has two interval timers within it - Timer A and Timer
B - that may be available. The CIA chips operate at different interrupt
levels with the CIA-A timers at interrupt level 2 and the CIA-B timers at
interrupt level 6.

   Choose A Timer Wisely.
   ----------------------
   The timer you use should be based solely on interrupt level and
   availability. If the timer you request is not available, try for
   another.  Whatever you do, do not base your decision on what you
   think the timer is used for by the system.

You allocate a timer by calling AddICRVector(). This is the only way you
should access a timer.   If the function returns zero, you have
successfully allocated that timer.  If it is unavailable, the owner
interrupt will be returned.

   /* allocate CIA-A Timer A */
   inta = AddICRVector (CIAResource, CIAICRB_TA, &tint);

   if (inta)  /* if allocate was not successful */
       printf("Error: Could not allocate timer\n");
   else
       {
       ...ready for timing
       }

The timer is deallocated by calling RemICRVector().  This is the only way
you should deallocate a timer.

   RemICRVector(CIAResource, CIAICRB_TA, &tint);

Your application should not make any assumptions regarding which interval
timers (if any) are available for use; other tasks or critical operating
system routines may be using the interval timers. In fact, in the latest
version of the operating system, the timer device may dynamically allocate
one of the interval timers.

   Time Is Of The Essence!
   -----------------------
   There are a limited number of free CIA interval timers.  Applications
   which use the interval timers may not be able to run at the same time
   if all interval timers are in use.  As a general rule, you should use
   the timer device for most interval timing.

You read from and write to the CIA interrupt control registers using
SetICR() and AbleICR().  SetICR() is useful for sampling which cia
interrupts (if any) are active.  It can also be used to clear and generate
interrupts.  AbleICR() is used to disable and enable a particular CIA
interrupt.  Additional information about these functions can be found in
the Amiga ROM Kernel Reference Manual: Includes and Autodocs.

Things to keep in mind:

   1. Never directly read from or write to the CIA interrupt control
      registers.  Always use SetICR() and AbleICR().

   2. Your interrupt routine will be called with a pointer to your data
      area in register A1, and a pointer to the code being called in
      register A5. No other registers are set up for you.  You must observe
      the standard convention of preserving all registers except D0-D1 and
      A0-A1.

   3. Never turn off all level 2 or level 6 interrupts.  The proper way to
      disable interrupts for an interval timer that you've successfully
      allocated is via the AbleICR() function.

   4. Interrupt handling code should be written in assembly code and, if
      possible, should signal a task to do most of the work.

   5. Do not make assumptions about which CIA interval timers (if any) are
      available for use.  The only proper way to own an interval timer is
      via the AddICRVector() function.

   6. Do not use SetICR(), AbleICR() and RemICRVector() to affect timers or
      other CIA hardware which your task does not own.

Changes in the CIA resource:

   *  In pre-V36 versions of the operating system, SetICR() could return
      FALSE for a particular interrupt just prior to processing the
      interrupt. SetICR() now returns TRUE for a particular interrupt until
      sometime after the interrupt has been processed.

   *  Applications which only need to read a CIA interval timer should use
      the ReadEClock() function of the timer device.  See "Timer Device"
      chapter of this manual for more information on ReadEClock().

   *  The timer device may dynamically allocate a free CIA interval timer.
      Do not make any assumptions regarding which interval timers are in
      use unless you are taking over the machine completely.

     Cia_Interval.c

Additional programming information on the CIA resource can be found in the
include files and the Autodocs for the CIA resource and the 8520 spec.
The includes files and Autodocs are in the Amiga ROM Kernel Reference
Manual: Includes and Autodocs and the 8520 spec is in the Amiga
Hardware Reference Manual.

                         CIA Resource Information
                     -------------------------------
                     INCLUDES        resources/cia.h
                                     resources/cia.i
                                     hardware/cia.h
                                     hardware/cia.i

                     AUTODOCS        cia.doc

                     HARDWARE        8520 specification


15 Resources / Disk Resource

The Disk resource obtains exclusive access to the floppy disk hardware
There are four disk/MFM units available, units 0-3.

Six functions are available for dealing with the floppy disk hardware.

                      Disk Resource Functions
                      -----------------------
     AllocUnit()      Allocate one of the units of the disk
                      resource.

     FreeUnit()       Deallocate an allocated disk unit.

     GetUnit()        Allocate the disk for a driver.

     GetUnitID()      Return the drive ID of a specified drive
                      unit.

     GiveUnit()       Free the disk.

     ReadUnitID()     Reread and return the drive ID of a
                      specified unit.

The disk resource provides both a gross and a fine unit allocation scheme.
AllocUnit() and FreeUnit() are used to claim a unit for long term use, and
GetUnit() and GiveUnit() are used to claim a unit and the disk hardware
for shorter periods.

The trackdisk device uses and abides by both allocation schemes.  Because
a trackdisk unit is never closed for Amiga 3.5" drives (the file system
keeps them open) the associated resource units will always be allocated
for these drives.  GetUnit() and GiveUnit() can still be used, however, by
other applications that have not succeeded with AllocUnit().

You must not change the state of of a disk that the trackdisk device is
using unless you either

   a) force its removal before giving it up, or

   b) return it to the original track (with no changes to the track), or

   c) CMD_STOP the unit before GetUnit(), update the current track number
      and CMD_START it after GiveUnit().  This option is only available
      under V36 and higher versions of the operating system.

ReadUnitID() is provided to handle drives which use the unit number in a
dynamic manner.  Subsequent GetUnit() calls will return the value obtained
by ReadUnitID().

It is therefore possible to prevent the trackdisk device from using units
that have not yet been mounted by successfully performing an AllocUnit()
for that unit.  It is also possible to starve trackdisk usage by
performing a GetUnit(). The appropriate companion routine (FreeUnit() or
GiveUnit()) should be called to restore the resource at the end of its use.

     Get_Disk_Unit_ID.c

Additional programming information on the disk resource can be found in
the include files and the Autodocs for the disk resource.

                       Disk Resource Information
                    --------------------------------
                    INCLUDES        resources/disk.h
                                    resources/disk.i

                    AUTODOCS        disk.doc


15 Resources / FileSystem Resource

The FileSystem resource returns the filesystems that are available on the
Amiga.  It has no functions.  Opening the FileSystem resource returns a
pointer to a List structure containing the current filesystems in the
Amiga.

     Get_Filesys.c

Additional programming information on the FileSystem resource can be found
in the include files and the Autodocs for the FileSystem resource in the
Amiga ROM Kernel Reference Manual: Includes and Autodocs and the
"Expansion" chapter of the Amiga ROM Kernel Reference Manual: Libraries.

                       FileSystem Resource Information
                    --------------------------------------
                    INCLUDES        resources/filesysres.h
                                    resources/filesysres.i

                    AUTODOCS        filesysres.doc

                    LIBRARIES       expansion library


15 Resources / Misc Resource

The misc resource oversees usage of the serial data port, the serial
communication bits, the parallel data and handshake port, and the parallel
communication bits.  Before using serial or parallel port hardware, it
first must be acquired from the misc resource.

The misc resource provides two functions for allocating and freeing the
serial and parallel hardware.

                             Misc Resource Functions
                             ------------------------
     AllocMiscResource()     Allocate one of the serial or parallel
                             misc resources.

     FreeMiscResource()      Deallocate one of the serial or
                             parallel misc resources.

Once you've successfully allocated one of the misc resources, you are free
to write directly to its hardware locations.  Information on the serial
and parallel hardware can be found in the Amiga Hardware Reference Manual
and the hardware/custom.h include file.

The two examples below are assembly and C versions of the same code for
locking the serial misc resources and waiting for CTRL-C to be pressed
before releasing them.

     Assembly Example Of Allocating Misc Resources
     C Example Of Allocating Misc Resources


15 / Misc Resource / C Example Of Allocating Misc Resources

     Allocate_Misc.c

The example below will try to open the serial device and execute the
SDCMD_QUERY command.  If it cannot open the serial device, it will do an
AllocMiscResource() on the serial port and return the name of the owner.

     Query_Serial.c

   Take Over Everything.
   ---------------------
   There are two serial.device resources to take over, MR_SERIALBITS and
   MR_SERIALPORT.  You should get both resources when you take over the
   serial port to prevent other tasks from using them.  The
   parallel.device also has two resources to take over.  See the
   resources/misc.h include file for the relevant definitions and
   structures.

Under V1.3 and earlier versions of the Amiga system software the
MR_GETMISCRESOURCE routine will always fail if the serial device has been
used at all by another task (even if that task has finished using the
resource.  In other words, once a printer driver or communication package
has been activated, it will keep the associated resource locked up
preventing your task from using it. Under these conditions, you must get
the resource back from the system yourself.

You do this by calling the function FlushDevice() as follows:

/*
 * A safe way to expunge ONLY a certain device.  The serial.device holds
 * on to the misc serial resource until a general expunge occurs.
 * This code attempts to flush ONLY the named device out of memory and
 * nothing else.  If it fails, no status is returned since it would have
 * no valid use after the Permit().
 */

#include <exec/types.h>
#include <exec/execbase.h>

#include <clib/exec_protos.h>

void FlushDevice(char *);

extern struct ExecBase *SysBase;

void FlushDevice(char *name)
{
struct Device *devpoint;

Forbid();

if (devpoint=(struct Device *)FindName(&SysBase->DeviceList,name) )
    RemDevice(devpoint);

Permit();
}

Additional programming information on the misc resource can be found in
the include files and the Autodocs for the misc resource.

                       Misc Resource Information
                    ---------------------------------
                    INCLUDES        resources/misc.h
                                    resources/misc.i
                                    hardware/custom.h
                                    hardware/custom.i
                    AUTODOCS        misc.doc


15 Resources / Potgo Resource

The potgo resource is used to get control of the hardware POTGO register
connected to the proportional I/O pins on the game controller ports. There
are two registers, POTGO (write-only) and POTINP (read-only). These pins
could also be used for digital I/O.

The potgo resource provides three functions for working with the POTGO
hardware.

                       Potgo Resource Functions
                       ------------------------
     AllocPotBits()    Allocate bits in the POTGO register.

     FreePotBits()     Free previously allocated bits in the POTGO
                       register.

     WritePotgo()      Set and clear bits in the POTGO register.
                       The bits must have been allocated before
                       calling this function.

The example program shown below demonstrates how to use the ptogo resource
to track mouse button presses on port 1.

     Read_Potinp.c

Additional programming information on the potgo resource can be found in
the include files and the Autodocs for the potgo resource.

                         Potgo Resource Information
                      ---------------------------------
                      INCLUDES        resources/potgo.h
                                      resources/potgo.i
                                      utility/hooks.h
                                      utility/hooks.i

                      AUTODOCS        potgo.doc


Amiga® RKM Devices: 8 Narrator Device

This chapter describes the narrator device which, together with the
translator library, provides all of the Amiga's text-to-speech functions.
The narrator device is used to produce high-quality human-like speech in
real time.

           NEW NARRATOR FEATURES FOR VERSION 2.0

   Feature        Description         Function
   -------        -----------         --------
   NDB_NEWIORB    Flag                Use V37 features
   NDB_WORDSYNC   Flag                Synchronize speech/mouth on words
   NDB_SYLSYNC    Flag                Synchronize speech/mouth on syllables
   F0enthusiasm   narrator_rb field   F0 excursion factor
   F0perturb      narrator_rb field   Amount of F0 perturbation
   F1adj          narrator_rb field   F1 adjustment in ±5% steps
   F2adj          narrator_rb field   F2 adjustment in ±5% steps
   F3adj          narrator_rb field   F3 adjustment in ±5% steps
   A1adj          narrator_rb field   A1 adjustment in decibels
   A2adj          narrator_rb field   A2 adjustment in decibels
   A3adj          narrator_rb field   A3 adjustment in decibels
   articulate     narrator_rb field   Transition time multiplier
   centralize     narrator_rb field   Degree of vowel centralization
   centphon       narrator_rb field   Pointer to central ASCII phon
   AVbias         narrator_rb field   Amplitude of voicing bias
   AFbias         narrator_rb field   Amplitude of frication bias
   priority       narrator_rb field   Priority while speaking

   Compatibility Warning:
   ----------------------
   The new features for the 2.0 narrator device are not backwards
   compatible.

 Narrator Device Commands and Functions
 Device Interface
 Writing to the Narrator Device
 Reading from the Narrator Device
 How to Write Phonetically for Narrator
 A More Technical Explanation
 Example Speech and Mouth Movement Program
 Additional Information on the Narrator Device


8 Narrator Device / Narrator Device Commands and Functions

Command         Operation
-------         ---------
CMD_FLUSH       Purge all active and queued requests for the narrator
                device.

CMD_READ        Read mouth shapes associated with an active write from the
                narrator device.

CMD_RESET       Reset the narrator port to its initialized state. All
                active and queued I/O requests will be aborted.  Restarts
                the device if it has been stopped.

CMD_START       Restart the currently active speech (if any) and resume
                queued I/O requests.

CMD_STOP        Stop any currently active speech and prevent queued I/O
                requests from starting.

CMD_WRITE       Write a stream of characters to the narrator device and
                generate mouth movement data for reads.

Exec Functions as Used in This Chapter
--------------------------------------
AbortIO()       Abort a command to the narrator device. If the command is
                in progress, it is stopped immediately.  If it is queued,
                it is removed from the queue.

BeginIO()       Initiate a command and return immediately (asynchronous
                request).  This is used to minimize the amount of system
                overhead.

CloseDevice()   Relinquish use of the narrator device.  All requests must
                be complete.

CheckIO()       Return the status of an I/O request.

CloseLibrary()  Relinquish use of a previously opened library.

DoIO()          Initiate a command and wait for completion (synchronous
                request). Should be used with care because it will not
                return control if the request does not complete.

OpenDevice()    Obtain use of the narrator device.

OpenLibrary()   Obtain use of a library.

SendIO()        Initiate a command and return immediately (asynchronous
                request).

WaitIO()        Wait for the completion of an asynchronous request. When
                the request is complete the message will be removed from
                reply port.

Exec Support Functions as Used in This Chapter
----------------------------------------------
CreateExtIO()   Create an extended I/O request structure of type
                narrator_rb.  This structure will be used to communicate
                commands to the narrator device.

CreatePort()    Create a signal message port for reply messages from the
                narrator device.  Exec will signal a task when a message
                arrives at the port.

DeleteExtIO()   Delete an extended I/O request structure created by
                CreateExtIO().

DeletePort()    Delete the message port created by CreatePort().


8 Narrator Device / Device Interface

The narrator device operates like all other Amiga devices.  To use the
narrator device, you must first open it.  This initializes certain global
areas, opens the audio device, allocates audio channels, and performs
other housekeeping functions.  Once open, the device is ready to receive
I/O commands (most typically CMD_WRITE andCMD_READ). Finally, when
finished, the user should close the device.  This will free some buffers
and allow the entire device to be expunged should the system require
memory.  See the Introduction to Amiga System Devices chapter for general
information on device usage.

The narrator device uses two extended I/O request structures: narrator_rb
for write commands (to produce speech output) and mouth_rb for read
commands (to receive mouth shape changes and word/syllable synchronization
events).  Both I/O request structures have been expanded (in a backwards
compatible fashion) for the V37 narrator device with several new fields
defined.

    struct narrator_rb
    {
       struct IOStdReq  message; /* Standard IORequest Block       */
       UWORD   rate;             /* Speaking rate (words/minute)   */
       UWORD   pitch;            /* Baseline pitch in Hertz        */
       UWORD   mode;             /* Pitch mode                     */
       UWORD   sex;              /* Sex of voice                   */
       UBYTE   *ch_masks;        /* Pointer to audio allocation maps  */
       UWORD   nm_masks;         /* Number of audio allocation maps   */
       UWORD   volume;           /* Volume. 0 (off) thru 64        */
       UWORD   sampfreq;         /* Audio sampling frequency       */
       UBYTE   mouths;           /* If non-zero, generate mouths   */
       UBYTE   chanmask; /* Which ch mask used (internal - do not modify)*/
       UBYTE   numchan;  /* Num ch masks used (internal- do not modify) */
       UBYTE   flags;            /* New feature flags              */
       UBYTE   F0enthusiasm;     /* F0 excursion factor            */
       UBYTE   F0perturb;        /* Amount of F0 perturbation      */
       BYTE    F1adj;            /* F1 adjustment in +- 5% steps   */
       BYTE    F2adj;            /* F2 adjustment in +- 5% steps   */
       BYTE    F3adj;            /* F3 adjustment in +- 5% steps   */
       BYTE    A1adj;            /* A1 adjustment in decibels      */
       BYTE    A2adj;            /* A2 adjustment in decibels      */
       BYTE    A3adj;            /* A3 adjustment in decibels      */
       UBYTE   articulate;       /* Transition time multiplier     */
       UBYTE   centralize;       /* Degree of vowel centralization */
       char    *centphon;        /* Pointer to central ASCII phon  */
       BYTE    AVbias;           /* Amplitude of voicing bias      */
       BYTE    AFbias;           /* Amplitude of frication bias    */
       BYTE    priority;         /* Priority while speaking        */
       BYTE    pad1;             /* For alignment                  */
    };

    struct mouth_rb
    {
       struct  narrator_rb voice;/* Speech IORequest Block         */
       UBYTE   width;            /* Mouth width (returned value)   */
       UBYTE   height;           /* Mouth height (returned value)  */
       UBYTE   shape;            /* Internal use, do not modify    */
       UBYTE   sync;             /* Returned sync events           */
    };

Details on the meaning of the various fields of the two I/O request blocks
can be found in the Writing to the Narrator Device and
Reading from the Narrator Device sections later in this chapter.  See
the include file devices/narrator.h for the complete structure definitions.

 The Amiga Speech System
 Opening The Narrator Device
 Closing The Narrator Device


8 / Device Interface / The Amiga Speech System

The speech system on the Amiga is divided into two subsystems:

   *  The translator library,  consisting of a single function:
      Translate(), which converts an English string into its phonetic
      representation, and

   *  The narrator device, which uses the phonetic representation
      (generated either manually or by the translator library) as input to
      generate human-like speech and play it out via the audio device.

The two subsystems can be used either together or individually. Generally,
hand coding phonetic text will produce better quality speech than using
the translator library, but this requires the programmer to "hard code"
the phonetic text in the program or otherwise restrict the input to
phonetic text only.  If the program must handle arbitrary English input,
the translator library should be used.

Below is an example of how you would use the translator library to
translate a string for the narrator device.

    #define BUFLEN 500

    APTR EnglStr;                   /* pointer to sample input string */
    LONG EnglLen;                   /* input length */
    UBYTE PhonBuffer[BUFLEN];       /* place to put the translation */
    LONG rtnCode;                   /* return code from function */

    struct narrator_rb *VoiceIO;    /* speaking I/O request block */
    struct mouth_rb *MouthIO;       /* mouth movement I/O request block */

    EnglStr = "This is Amiga speaking.";    /* a test string */
    EnglLen = strlen(EnglStr);
    rtnCode = Translate(EnglStr, EnglLen, (APTR)&PhonBuffer[0], BUFLEN);

    voice_io->message.io_Command = CMD_WRITE;
    voice_io->message.io_Offset  = 0;
    voice_io->message.io_Data    = PhonBuffer;
    voice_io->message.io_Length  = strlen(PhonBuffer);
    DoIO((struct IORequest *)VoiceIO)

This chapter discusses only the narrator device; refer to the "Translator
Library" chapter of the Amiga ROM Kernel Reference Manual: Libraries for
more information on the translator library.

While the narrator device on the Amiga supports all of the major device
commands (see the  Narrator Device Commands and Functions section), two of
these commands do most of the work in the device.  They are:

   *  CMD_WRITE - This command is used to send a phonetic string to the
      device to be spoken.  The narrator_rb I/O request block also contains
      several parameters which can be set to control  various aspects of
      the speech, such as pitch, speaking rate, male/female voice, and so
      on. Some of the options are rather arcane.  See the
      Writing to the Narrator Device section for a complete list
      of options and their descriptions.

   *  CMD_READ - The narrator device can be told to generate various
      synchronization events which the user can query.  These events are:
      mouth shape changes, word sync, and/or syllable sync.  The events can
      be generated singly or in any combination, as requested by the user.
      Word and syllable synchronization events are new to system 2.0 and
      later (V37 and later of the narrator device).  See the
      Reading from the Narrator Device section for more details.


8 / Device Interface / Opening The Narrator Device

Three primary steps are required to open the narrator device:

   *  Create a message port using CreatePort(). Reply messages from the
      device must be directed to a message port.

   *  Create an extended I/O request structure of type narrator_rb.  The
      narrator_rb structure is created by the CreateExtIO() function.

   *  Open the narrator device.  Call OpenDevice() passing the I/O request.

    struct MsgPort *VoiceMP;
    struct narrator_rb *VoiceIO;

    if (VoiceMP = CreatePort("speech_write",0))
        if (VoiceIO = (struct narrator_rb *)
                        CreateExtIO(VoiceMP,sizeof(struct narrator_rb));
            if (OpenDevice("narrator.device", 0, VoiceIO, 0))
                    printf("narrator.device did not open\n");

When the narrator device is first opened, it initializes certain fields in
the user's narrator_rb I/O request structure.  In order to maintain
backwards compatibility with older versions of the narrator device, a
mechanism was needed for the device to ascertain whether it was being
opened with a V37 or pre-V37 style I/O request structure. The pad field in
the pre-V37 narrator_rb I/O request structure (which no one should have
ever touched!) has been replaced by the flags field in the V37 narrator_rb
structure, and is our path to upward compatibility.  The device checks to
see if a bit is set in this flags field.  This bit must be set before
opening the device if V37 or later features of the narrator device are to
be used.  There are two defined constants in the include file, NDB_NEWIORB
and NDF_NEWIORB. NDB_NEWIORB specifies the bit which must be set in the
flags field, NDF_NEWIORB is the field definition of the bit (1 <<
NDB_NEWIORB).

Once the device is opened, the mouth_rb (read) I/O request structure can
be set up.  Each CMD_READ request must be matched with an associated
CMD_WRITE request.  This is necessary for the device to match the various
sync events with a particular utterance.  The read I/O request structure
is easily set up as follows:

   *  Create a read message port using the CreatePort() function.

   *  Allocate memory for the mouth_rb extended I/O request structure using
      AllocMem().

   *  Copy the narrator_rb I/O request structure used to open the device
      into the voice field of the mouth_rb I/O request structure. This will
      set the fields necessary for the device to make the correct
      correspondence between read and write requests.

   *  Copy the pointer to the read message port returned from CreatePort()
      into the voice.message.io_Message.mn_ReplyPort field of the mouth_rb
      structure.

The following code fragment, in conjunction with the OpenDevice() code
fragment above, shows how to set up the mouth_rb structure:

    struct  MsgPort   *MouthMP;
    struct  mouth_rb  *MouthIO;

    if (MouthMP = CreatePort("narrator_read", 0))
      if (!(MouthIO = (struct mouth_rb *)
                 AllocMem(sizeof(struct mouth_rb),MEMF_PUBLIC|MEMF_CLEAR)))
          {
          /* Copy I/O request used in OpenDevice */
          MouthIO->voice = *VoiceIO;
          /* Set port */
          MouthIO->voice.message.io_Message.mn_ReplyPort=MouthMP;
          }
      else
          printf("AllocMem failed\n");
    else
        printf("CreatePort failed\n");


8 / Device Interface / Closing The Narrator Device

Each OpenDevice() must be eventually matched by a call to CloseDevice().
This is necessary to allow the system to expunge the device in low memory
conditions.  As long as any task has the device open, or has forgotten to
close it before terminating, the narrator device will not be expunged.

All I/O requests must have completed before the task can close the device.
If any requests are still pending, the user must abort them before closing
the device.

    if (!(CheckIO(VoiceIO)
        {
        AbortIO(VoiceIO);  /* Abort queued or in progress request */
        }
    WaitIO((struct IORequest *)VoiceIO); /* Wait for abort to do its job */
    CloseDevice(VoiceIO);                /* Close the device */


8 Narrator Device / Writing to the Narrator Device

You write to the narrator device by passing a narrator_rb I/O request to
the device with CMD_WRITE set in io_Command, the number of bytes to be
written set in io_Length and the address of the write buffer set in
io_Data.

    VoiceIO->message.io_Command = CMD_WRITE;
    VoiceIO->message.io_Offset  = 0;
    VoiceIO->message.io_Data    = PhonBuffer;
    VoiceIO->message.io_Length  = strlen(PhonBuffer);
    DoIO((struct IORequest *)VoiceIO);

You can control several characteristics of the speech, as indicated in the
narrator_rb struct shown in the Device Interface section.

Generally, the narrator device attempts to speak in a non-regional dialect
of American English.  With pre-V37 versions of the device, the user could
change only a few of the more basic aspects of the speaking voice such as
pitch, male/female, speaking rate, etc.  With the V37 and later versions
of the narrator device, the user can now change many more aspects of the
speaking voice.  In addition, in the pre-V37 device, only mouth shape
changes could be queried by the user.  With the V37 device, the user can
also receive start of word and start of syllable synchronization events.
These events can be generated independently, giving the user much greater
flexibility in synchronizing voice to animation or other effects.

The following describes the fields of the narrator_rb structure:

message.io_Data
    Points to a NULL-terminated ASCII phonetic input string.  For
    backwards compatibility issues, the string may also be terminated
    with a "#" symbol.  See the How to Write Phonetically for Narrator
    section of this chapter for details.

message.io_Length
    Length of the input string.  The narrator device  will parse the
    input string until either a NULL or a "#" is encountered, or until
    io_Length characters have been processed.

rate
    The speaking rate in words/minute.  Range is from 40 to 400 wpm.

pitch
    The baseline pitch of the speaking voice.  Range is 65 to 320 Hertz.

mode
    The F0 (pitch) mode.  ROBOTICF0 produces a monotone pitch, NATURALF0
    produces a normal pitch contour, and MANUALF0 (new for V37 and later)
    gives the user more explicit control over the pitch contour by
    creative use of accent numbers.  In MANUALF0 mode, a given accent
    number will have the same effect on the pitch regardless of its
    position in the sentence and its relation to other accented
    syllables. In NATURALF0 mode, accent numbers have a reduced effect
    towards the end of sentences (especially long ones).  In addition,
    the proximity of other accented syllables, the number of syllables in
    the word, and the number of phrases and words in the sentence all
    affect the pitch contour.  In MANUALF0 mode these things are ignored
    and it's up to the user to do the controlling.  This has the
    advantage of being able to have the pitch be more expressive.  The
    F0enthusiasm field will scale the effect.

sex
    Controls the sex of  the speaking voice (MALE or FEMALE).  In
    actuality, only the formant targets are changed.  The user must still
    change the pitch and speaking rate of the voice to get the correct
    sounding sex.  See the include files for default pitch and rate
    settings.

ch_masks
    Pointer to a set of audio allocation maps.  See the "Audio Device"
    chapter for details.

nm_masks
    Number of audio allocation maps.  See the "Audio Device" chapter
    for details.

volume
    Sets the volume of the speaking voice.  Range 0 - 64.

sampfreq
    The synthesizer is ``tuned" to a sampling frequency of 22,200 Hz.
    Changing sampfreq affects pitch and formant tunings and can be used
    to create unusual vocal effects.  For V37 and later, it is
    recommended that F1, F2, and F3adj be used instead to achieve this
    effect.

mouths
    If set to a non-zero value will direct the narrator device  to
    generate mouth shape changes and send this data to the user in
    response to read requests.  See the Reading from the Narrator Device
    section for more details.

chanmask
    Used internally by the narrator device. The user should not modify
    this field.

numchan
    Used internally by the narrator device.  The user should not modify
    this field.

flags (V37)
    Used to specify V37 features of the device.  Possible bit settings
    are: NDB_NEWIORB - I/O request block  uses V37 features. NDB_WORDSYNC
    - Device should generate start of word sync events. NDB_SYLSYNC -
    Device should generate start of syllable sync events. These bit
    definitions and their corresponding field definitions (NDF_NEWIORB,
    NDF_WORDSYNC, and NDF_SYLSYNC) can be found in the include files.

F0enthusiasm (V37)
    The value of this field controls the scaling of pitch (F0) excursions
    used on accented syllables and has the effect of making the narrator
    device sound more or less "enthusiastic" about what it is saying.
    It is calibrated in 1/32s with unity (32) being the default value.
    Higher values cause more F0 variation, lesser values cause less.
    This feature is most useful in manual F0 mode.

F0perturb (V37)
    Non-zero values in this field cause varying amounts of random
    low-frequency modulation of the pitch (F0).  In other words, the
    pitch shakes in much the same way as an elderly person's voice does.
    Range is 0 to 255.

F1adj, F2adj, F3adj (V37)
    Changes the tuning of the formant frequencies. A formant is a major
    vocal tract resonance, and the frequencies of these formants move
    continuously as we speak.  Traditionally, they have been given the
    abbreviations of F1, F2, F3... with F1 being the one lowest in
    frequency.  Moving these formants away from their normal positions
    causes drastic changes in the sound of the voice and is a very
    powerful tool in the creation of character voices.  This adjustment
    is in ±5% steps.  Positive values raise the formant frequencies and
    vice versa. The default is zero.  Use these adjustments instead of
    changing sampfreq.

A1adj, A2adj, A3adj (V37)
    In a parallel formant synthesizer, the amplitudes of the formants
    need to be specified along with their frequencies.  These fields bias
    the amplitudes computed by the narrator device.  This is useful for
    creating different tonal balances (bass or treble), and listening to
    formants in isolation for educational purposes.  The adjustments are
    calibrated directly in ±1db (decibel) steps.  Using negative values
    will cause no problems; use of positive numbers can cause clipping.
    If you want to raise an amplitude, try cutting the others the same
    relative amount, then bring them all up equally until clipping is
    heard, then back them off.  This should produce an optimum setting.
    This field has a +31 to -32 db range and the value -32db is
    equivalent to -infinity, shutting that formant off completely.

articulate (V37)
    According to the popular theories of speech production, we move our
    articulators (jaw, tongue, lips, etc.) smoothly from one "target"
    position to the next.  These articulatory targets correspond to
    acoustic targets specified by the narrator device for each phoneme.
    The device calculates the time it should take to get from one target
    to the next and this field allows you to intervene in that process.
    Values larger than the default will cause the transitions to be
    proportionately longer and vice versa.  This field is calibrated in
    percent with 100 being the default.  For example, a value of 50 will
    cause the transitions to take half the normal time, with the result
    being "sharper", more deliberate sounding speech (not necessarily
    more natural).  A value of 200  will cause the transitions to be
    twice as long, slurring the speech.  Zero is a special value in the
    narrator device will take special measures to create no transitions
    at all and each phoneme will simply be abutted to the next.

centralize (V37)
    This field together with centphon can be used to create regional
    accent effects by modifying vowel sounds.  centralize specifies the
    degree (in percent) to which vowel targets are "pulled" towards the
    targets of the vowel specified by centphon.   The default value of 0%
    indicates that each vowel in the utterance retains its own target
    values.  The maximum value of 100% indicates that each vowel's
    targets are replaced by the targets of the specified vowel.
    Intermediate values control the degree of interpolation between the
    utterance vowel's targets and the targets of the vowel specified by
    centphon.

centphon (V37)
    Pointer to an ASCII string specifying the vowel whose targets are
    used in the interpolation specified by centralize.  The vowels which
    can be specified are: IY, IH, EH, AE, AA, AH, AO, OW, UH, ER, UW.
    Specifying other than these will result in an error code being
    returned.

AVbias, AFbias (V37)
    Controls the relative amplitudes of the voiced and unvoiced speech
    sounds.  Voiced sounds are those made with the vocal cords vibrating,
    such as vowels and some consonants like y, r, w, and m.  Unvoiced
    sounds are made without the vocal cords vibrating and use the sound
    of turbulent air, such as s, t, sh, and f.  Some sounds are
    combinations of both such as z and v.  AVbias and AFbias change the
    default amplitude of the voiced and unvoiced components of the sounds
    respectively.  (AV stands for Amplitude of Voicing and AF stands for
    Amplitude of Frication).  These fields are calibrated in ±1db steps
    and have the same range as the other amplitude biases, namely +31 to
    -32 db.  Again, positive values may cause clipping.  Negative values
    are the most useful.

priority (V37)
    Task priority while speaking.  When the narrator device begins to
    synthesize a sentence, the task priority remains unchanged while it
    is calculating acoustic parameters.  However, when speech begins at
    the end of this process, the priority is bumped to 100 (the default
    value). If you wish, you may change this to anything you want.
    Higher values will tend to lock out most anything while speech is
    going on, and lower values may cause audible breaks in the speech
    output. The following example shows how to issue a write request to
    the narrator device.  The first write is done with the default
    parameter settings.  The second write is done after modifying the
    first and third formant loudness and using the centralization feature.

The following example shows how to issue a write request to the narrator
device.  The first write is done with the default parameter settings.  The
second write is done after modifying the first and third formant loudness
and using the centralization feature.

     Speak_Narrator.c


8 Narrator Device / Reading from the Narrator Device

All read requests to the narrator device must be matched to an associated
write request.  This is done by copying the narrator_rb structure used in
the OpenDevice() call into the voice field of the mouth_rb I/O request
structure.  You must do this after the call to OpenDevice().  Matching the
read and write requests allows the narrator device to coordinate I/O
requests across multiple uses of the device.

In pre-V37 versions of the narrator device, only mouth shape changes can
be queried from the device.  This is done by setting the mouths field of
the narrator_rb I/O request structure (the write request) to a non-zero
value.  The write request is then sent asynchronously to the device and
while it is in progress, synchronous read requests are sent to the device
using the mouth_rb I/O request structure.  When the mouth shape has
changed, the device will return the read request to the user with bit 0
set in the sync field of the mouth_rb.  The fields width and height of the
mouth_rb structure will contain byte values which are proportional to the
actual width and height of the mouth for the phoneme currently being
spoken.  Read requests sent to the narrator device are not returned to the
user until one of two things happen: either the mouth shape has changed
(this prevents the user from having to constantly redraw the same mouth
shape), or the speech has completed.  The user can check io_Error to
determine if the mouth shape has changed (a return code of 0) or if the
speech has completed (return code of ND_NoWrite).

In addition to returning mouth shapes, reads to the V37 narrator device
can also perform two new functions: word and syllable sync. To generate
word and/or syllable sync events, the user must specify several bits in
the flags field of the write request (narrator_rb structure).  The bits
are NDB_WORDSYNC and NDB_SYLSYNC, for start of word and start of syllable
synchronization events, respectively, and, of course, NDB_NEWIORB, to
indicate that the V37 I/O request is required.

NDB_WORDSYNC and NDB_SYLSYNC tell the device to expect read requests and
to generate the appropriate event(s). As with mouth shape change events,
the write request is sent asynchronously to the device and, while it is in
progress, synchronous read requests are sent to the device.  The sync
field of the mouth_rb structure will contain flags indicating which events
(mouth shape changes, word sync, and/or syllable sync) have occurred.

The returned sync field flags are:

    bit 0 (0x01) -> mouth shape change event
    bit 1 (0x02) -> start-of-word synchronization event
    bit 2 (0x04) -> start-of-syllable synchronization event

and 1 or more flags may be set for any particular read.

As with mouth shape changes, read requests will not return until the
requested event(s) have occurred, and the user must test the io_Error
field of the mouth_rb structure to tell when the speech has completed (an
error return of  ND_NoWrite).

Several read events can be compressed into a single event.  This can occur
in two ways: first when two dissimilar events occur between two successive
read requests.  For example, a single read may return both a mouth change
and a syllable sync event.  This should not present a problem if the user
checks for all events. The second is when multiple events of the same type
occur between successive read requests.  This is of no great concern in
dealing with mouth shape changes because, presumably, mouth events are
used to drive animation, and the animation procedure will simply draw the
current mouth shape.

    Watch Those Sync Events.
    ------------------------
    When word or syllable sync is desired, the narrator device may
    compress multiple sync events into a single sync event.  Missing a
    word or syllable sync may cause word highlighting (for example) to
    lose sync with the speech output.  A future version of the device
    will include an extension to the mouth_rb I/O request structure which
    will contain word and syllable counts and, possibly, other
    synchronization methods.

The following code fragment shows the basics of how to perform reads from
the narrator device.  For a more complete example, see the sample program
at the end of this chapter.  For this fragment, take the code of the
previous write example as a starting point.  Then the following code would
need to be added:

    struct  mouth_rb  *MouthIO;     /* Pointer to read IORequest block */
    struct  MsgPort   *MouthMP;     /* Pointer to read message port    */

/*
 * (1) Create a message port for the read request.
 */
    if (!(MouthMP = CreatePort("narrator_read", 0L)))
        BellyUp("Read CreatePort failed");

/*
 * (2) Create an extended IORequest of type mouth_rb.
 */
    if (!(MouthIO = (struct mouth_rb *)
                     CreateExtIO(MouthMP, sizeof(struct mouth_rb))))
        BellyUp("Read CreateExtIO failed");

/*
 * (3) Set up the read IORequest. Do this after the call to OpenDevice().
 * We assume that the write IORequest and the OpenDevice have been done
 */
    MouthIO->voice  =  *SpeakIO;
    MouthIO->voice.message.io_Message.mn_ReplyPort = ReadMsgPort;
    MouthIO->voice.message.io_Command = CMD_READ;

/*
 * (4) Set the flags field of the narrator_rb write request to return the
 *     desired sync events.  If mouth shape changes are required, then the
 *     mouths field of the IORequest should be set to a non-zero value.
 */

    SpeakIO->mouths = 1;            /* Generate mouth shape changes */
    SpeakIO->flags = NDF_NEWIORB  | /* Indicates V37 style IORequest */
                     NDF_WORDSYNC | /* Request start-of-word sync events */
                     NDF_SYLSYNC;   /* Request start-of-syll sync events */

/*
 * (5) Issue asynchronous write request. The driver initiates the write
 *      request and returns immediately.
 */

    SendIO(SpeakIO);

/*
 * (6) Issue synchronous read requests. For each request we check the sync
 *     field to see which events have occurred.  Since any combination of
 *     events can be returned in a single read, we must check all
 *     possibilities.  We continue looping until the read request returns
 *     an error of ND_NoWrite, which indicates that the write request has
 *     completed.
 */

    for (DoIO(MouthIO);MouthIO->voice.message.io_Error
                             != ND_NoWrite;DoIO(MouthIO))
          {
          if (MouthIO->sync & 0x01)  DoMouthShape();
          if (MouthIO->sync & 0x02)  DoWordSync();
          if (MouthIO->sync & 0x04)  DoSyllableSync();
          }

/*
 *  (7) Finally, we must perform a WaitIO() on the original write request.
 */

    WaitIO(SpeakIO);


8 Narrator Device / How to Write Phonetically for Narrator

This section describes in detail the procedure used to specify phonetic
strings to the narrator speech synthesizer. No previous experience with
phonetics is required. The only thing you may need is a good pronunciation
dictionary for those times when you doubt your own ears. You do not have
to learn a foreign language or computer language. You are just going to
learn how to write down the English that comes out of your own mouth. In
writing phonetically you do not have to know how a word is spelled, just
how it is said.

                            TABLE OF PHONEMES

                                  Vowels

          Phoneme      Example              Phoneme     Example
          -------      -------              -------     --------
          IY           beet, eat            IH          bit, in
          EH           bet, end             AE          bat, ad
          AA           bottle, on           AH          but, up
          AO           ball, awl            UH          book, soot
          ER           bird, early          OH          border
          AX*          about, calibrate     IX*         solid, infinite

         * AX and IX should never be used in stressed syllables.

                                Diphthongs

          Phoneme      Example              Phoneme     Example
      -------      -------		    -------     --------
          EY           bay,aid              AY          bide,I
          OY           boy,oil              AW          bound,owl
          OW           boat,own             UW          brew,boolean

                                Consonants

          Phoneme      Example              Phoneme    Example
      -------      -------   	    -------    -------
          R            red                  L           long
          W            wag                  Y           yellow,comp(Y)uter
          M            men                  N           no
          NX           sing                 SH          shy
          S            soon                 TH          thin
          F            fed                  ZH          pleasure
          Z            has,zoo              DH          then
          V            very                 WH          when
          CH           check                J           judge
          /H           hole                 /C          loch
          B            but                  P           put
          D            dog                  T           toy
          K            keg,copy             G           guest

                             Special Symbol

          Phoneme               Example             Explanation
          -------               -------             -----------
          DX                    pity                tongue flap
          Q                     kitt(Q)en           glottal stop
          QX                                        silent vowel

                         Contractions (see text)

                               UL = AXL
                               IL = IXL
                               UM = AXM
                               IM = IXM
                               UN = AXN
                               IN = IXN

                          Digits and Punctuation

    Digits 1-9    Syllabic stress, ranging from secondary through emphatic
    .             Period - sentence final character.
    ?             Question mark - sentence final character
    -             Dash - phrase delimiter
    ,             Comma - clause delimiter
    ()            Parentheses - noun phrase delimiters (see text)

The narrator device  works on utterances at the sentence level.  Even if
you want to say only one word, it will treat it as a complete sentence.
Therefore, narrator wants one of two punctuation marks to appear at the
end of every sentence - a period or a question mark.  The period is used
for almost all utterances and will cause a final fall in pitch to occur at
the end of a sentence.  The question mark is used at the end of yes/no
questions only, and results in a final rise in pitch.

For example, the question, Do you enjoy using your Amiga? would take a
question mark at the end, while the question, What is your favorite color?
should be followed (in the phonetic transcription) with a period.  If no
punctuation appears at the end of a string, narrator will append a dash to
it, which will result in a short pause.  Narrator recognizes other
punctuation marks as well, but these are left for later discussion.

 Phonetic Spelling 	      Hints For Intelligibility
 Stress And Intonation        Example Of English And Phonetic Texts
 Punctuation 		      Concluding Remarks


8 / How to Write Phonetically for Narrator / Phonetic Spelling

Utterances are usually written phonetically using an alphabet of symbols
known as IPA (International Phonetic Alphabet).  This alphabet is found at
the front of most good dictionaries.  The symbols can be hard to learn and
were not readily available on computer keyboards, so the Advanced Research
Projects Agency (ARPA) came up with the ARPABET, a way of representing
each symbol using one or two upper case letters. Narrator uses an expanded
version of the ARPABET to specify phonetic sounds.

A phonetic sound, or phoneme, is a basic speech sound, a speech atom.
Working backwards: sentences can be broken into words, words into
syllables, and syllables into phonemes.  The word cat has three letters
and (coincidentally) three phonemes.  Looking at the table of phonemes we
find the three sounds that make up the word cat. They are the phonemes K,
AE, and T, written as KAET. The word cent translates as SEHNT. Notice that
both words begin with the letter c, but because they are pronounced
differently they have different phonetic spellings. These examples
introduce a very important concept of phonetic spelling: spell it like it
sounds, not like it looks.

 Choosing the Right Vowel
 Choosing the Right Consonant
 Contractions and Special Symbols


8 / Phonetic Spelling / Choosing the Right Vowel

Phonemes, like letters, are divided into two categories: vowels and
consonants.  Loosely defined, a vowel is a continuous sound made with the
vocal cords vibrating and air exiting the mouth (as opposed to the nose).
A consonant is any other sound, such as those made by rushing air (like S
or TH), or by interruptions in the air flow by the lips or tongue (B  or
T).  All vowels use a two letter ASCII phonetic code while consonants use
a one or two letter code.

In English we write with only five vowels: a, e, i, o, and u.  It would be
easy if we only said  five vowels.  However, we say more than 15 vowels.
Narrator provides for most of them.  Choose the proper vowel by listening:
Say the word aloud,  perhaps extending the vowel sound you want to hear
and then compare the sound you are making to the sounds made by the vowels
in the examples on the phoneme list.  For example, the a in apple sounds
the same as the a in cat, not like the a in Amiga, talk, or made.  Notice
also that some of the example words in the list do not even use any of the
same letters contained in the phoneme code; for example AA as in bottle.

Vowels are divided into two groups: those that maintain the same sound
throughout their durations and those that change their sound.  The ones
that change are called diphthongs.  Some of us were taught the terms long
and short  to describe vowel sounds.  Diphthongs fall into the long
category, but these two terms are inadequate to fully differentiate
between vowels and should be avoided.  The diphthongs are the last six
vowels listed in the table.  Say the word made out loud very slowly.
Notice how the a starts out like the e in bet  but ends up like the e in
beet.  The a, therefore, is a diphthong in this word and we would use EY
to represent it.  Some speech synthesis systems require you to specify the
changing sounds in diphthongs as separate elements, but narrator takes
care of the assembly of diphthongal sounds for you.


8 / Phonetic Spelling / Choosing the Right Consonant

Consonants are divided into many categories by phoneticians, but we need
not concern ourselves with most of them.  Picking the correct consonant is
very easy if you pay attention to just two categories: voiced and
unvoiced.  A voiced consonant is made with the vocal cords vibrating, and
an unvoiced one is made when the vocal cords are silent. Sometimes English
uses the same letter combinations to represent both. Compare the th in
thin with the th in then. Notice that the first is made with air rushing
between the tongue and upper teeth.  In the second, the vocal cords are
vibrating also.  The voiced th phoneme is DH and the unvoiced one is TH.
Therefore, thin is phonetically spelled as THIHN while the word then is
spelled DHEHN.

A sound that is particularly subject to mistakes is voiced and unvoiced S,
phonemes Z and S, respectively.   Clearly the word bats ends with an S and
the word has ends with a Z. But, how do you spell close?  If you say "What
time do you close?", you spell it with a Z, and if you are saying "I love
to be close to you." you use an S.

Another sound that causes some confusion is the r sound.  There are two
different r-like phonemes in the Narrator alphabet:  R under the
consonants and ER under the vowels.  Use ER if the r sound is the vowel
sound in the syllable like in bird, absurd, and flirt.  Use the R if the r
sound precedes or follows another vowel sound in that syllable as in car,
write, and craft.


8 / Phonetic Spelling / Contractions and Special Symbols

There are several phoneme combinations that appear very often in English
words.  Some of these are caused by our laziness in pronunciation.  Take
the word connector for example.  The o in the first syllable is almost
swallowed out of existence. You would not use the AA phoneme; you would
use the AX phoneme instead. It is because of this relaxation  of vowels
that we find ourselves using AX and IX very often.  Since this relaxation
frequently occurs before l, m, and n, narrator has a shortcut for typing
these combinations. Instead of personal being spelled PERSIXNAXL, we can
spell it PERSINUL, making it a little more readable.  Anomaly goes from
AXNAAMAXLIY to UNAAMULIY, and KAAMBIXNEYSHIXN becomes KAAMBINEYSHIN for
combination.  It may be hard to decide whether to use the AX or IX brand
of relaxed vowel.  The only way to find out is to use both and see which
sounds best.

Other special symbols are used internally by narrator.  Sometimes they are
inserted into or substituted for part of your input sentence.  You can
type them in directly if you wish.  The most useful is probably the Q or
glottal stop, an interruption of air flow in the glottis.  The word
Atlantic has one between the t and the l. Narrator knows there should be a
glottal stop there and saves you the trouble of typing it. But narrator is
only close to perfect, so sometimes a word or word pair might slip by that
would have sounded better with a Q stuck in someplace.


8 / How to Write Phonetically for Narrator / Stress And Intonation

It is not enough to tell narrator what you want said.  For the best
results you must also tell narrator how you want it said.  In this way you
can alter a sentence's meaning, stress important words, and specify the
proper accents in polysyllabic words.  These things improve the
naturalness and thus the intelligibility of the spoken output.

Stress and intonation are specified by the single digits 1-9 following a
vowel phoneme code.  Stress and intonation are two different things, but
are specified by a single number.

Stress is, among other things, the elongation of a syllable.  A syllable
is either stressed or not, so the presence of a number after the vowel in
a syllable indicates stress on that syllable.  The value of the number
indicates the intonation. These numbers are referred to here as stress
marks  but keep in mind that they also affect intonation.

Intonation here means the pitch pattern or contour of an utterance. The
higher the stress mark, the higher the potential for an accent in pitch.
A sentence's basic contour is comprised of a quickly rising pitch gesture
up to the first stressed syllable in the sentence, followed by a slowly
declining tone throughout the sentence, and finally, a quick fall to a low
pitch on the last syllable.  The presence of additional stressed syllables
causes the pitch to break its slow, declining pattern with rises and falls
around each stressed syllable.  Narrator uses a very sophisticated
procedure to generate natural pitch contours based on how you mark the
stressed syllables.

 How and Where to Put the Stress Marks
 Which Stress Value Do I Use?


8 / / Stress And Intonation / How and Where to Put the Stress Marks

The stress marks go immediately to the right of vowel phoneme codes. The
word cat has its stress marked after the AE, e.g., KAE5T. You generally
have no choice about the location of a number; there is definitely a right
and wrong location.  A number should either go after a vowel or it should
not.  Narrator will not flag an error if you forget to put a stress mark
in or if you place it on the wrong vowel. It will only tell you if a
stress mark has been put after a non-vowel, i.e., consonant or punctuation.

The rules for placing stress marks are as follows:

   *  Always place a stress mark in a content  word.  A content word is one
      that contains some meaning.  Nouns, verbs, and adjectives are all
      content words, they tell the listener what you are talking about.
      Words like but, if, and the are not content words. They do not convey
      any real world meaning, but are required to make the sentence
      function, so they are given the name function words.

   *  Always place a stress mark on the accented syllable(s) of
      polysyllabic words, whether they are content or function words.  A
      polysyllabic word is any word of more than one syllable.  Commodore
      has its stress (often called accent) on the first syllable and would
      be spelled KAA5MAXDOHR, while computer is stressed on the second
      syllable: KUMPYUW5TER.

If you are in doubt about which syllable gets the stress, look up the word
in a dictionary and you will find an accent mark over the stressed
syllable.  If more than one syllable in a word receives stress, they
usually are not of equal value.  These are referred to as primary and
secondary stresses.  The word understand has its first and last syllables
stressed, with the syllable stand getting the primary stress and the
syllable un getting the secondary stress. This produces the phonetic
representation AH1NDERSTAE4ND.  Syllables with secondary stress should be
marked with a value of only 1 or 2.

Compound words (words with more than one root) such as baseball, software,
and lunchwagon can be written as one word, but should be thought of as
separate words when marking stress.  Thus, lunchwagon would be spelled
LAH5NCHWAE2GIN.  Notice that the lunch got a higher stress mark than the
wagon.   This is common in compound words, the first word usually receives
the primary stress.


8 / / Stress And Intonation / Which Stress Value Do I Use?

If you get the spelling and stress mark positions correct, you are 95
percent of the way to a good sounding sentence.  The next thing to do is
decide on the stress mark values.  They can be roughly related to parts of
speech, and you can use the table shown below as a guide to assigning
values.

                        RECOMMENDED STRESS VALUES

                  Part of Speech         Stress Value
                  --------------         ------------
                  Exclamations               9
                  Adverbs                    7
                  Quantifiers                7
                  Nouns                      5
                  Adjectives                 5
                  Verbs                      4
                  Pronouns                   3
                  Secondary stress            1 or 2
                  Everything else             None

The above values merely suggest a range.  If you want attention directed
to a certain word, raise its value.  If you want to downplay a word, lower
it.  Sometimes even a function word can be the focus of a sentence.  It is
quite conceivable that the word to in the sentence Please deliver this to
Mr. Smith.  could receive a stress mark of 9. This would add focus to the
word, indicating that the item should be delivered to Mr. Smith in person.


8 / How to Write Phonetically for Narrator / Punctuation

In addition to the period or question mark that is required at the end of
a sentence, Narrator also recognizes dashes, commas, and parentheses.

The comma goes where you would normally put a comma in an English
sentence.  It causes narrator to pause with a slightly rising pitch,
indicating that there is more to come.  The use of additional commas, that
is, more than would be required for written English - is often helpful.
They serve to set clauses off from one another.  There is a tendency for a
listener to lose track of the meaning of a sentence if the words run
together.  Read your sentence aloud while pretending to be a newscaster.
The locations for additional commas should leap out at you.

The dash serves almost the same purpose as the comma, except that the dash
does not cause the pitch to rise so severely.  A rule of thumb is: Use
dashes to divide phrases and commas to divide clauses.

Parentheses provide additional information to narrator's intonation
function.  They should be put around noun phrases of two or more content
words.  This means that the noun phrase, a giant yacht should be
surrounded with parentheses because it contains two content words, giant
and yacht.  The phrase my friend should not have parentheses around it
because it contains only one content word.  Noun phrases can get fairly
large, like the best time I've ever had or a big basket of fruit and nuts.
The parentheses are most effective around these large phrases; the smaller
ones can sometimes go without.  The effect of parentheses is subtle, and
in some sentences you might not notice their presence.  In sentences of
great length, however, they help provide for a very natural contour.


8 / How to Write Phonetically / Hints For Intelligibility

There are a few tricks you can use to improve the intelligibility of a
sentence.  Often, a polysyllabic word is more recognizable than a
monosyllabic word.  For instance, instead of saying huge, say enormous.
The longer version contains information in every syllable, thus giving the
listener a greater chance to hear it correctly.

Another good practice is to keep sentences to an optimal length. Writing
for reading and writing for speaking are two different things. Try not to
write a sentence that cannot be easily spoken in one breath. Such a
sentence tends to give the impression that the speaker has an infinite
lung capacity and sounds unnatural.  Try to keep sentences confined to one
main idea; run-on sentences tend to lose their meaning.

New terms should be highly stressed the first time they are heard. This
gives the listener something to cue on, and can aid in comprehension.

The insertion of the glottal stop phoneme Q at the end of a word can
sometimes help prevent slurring of one word into another.  When we speak,
we do not pause at the end of each word, but instead transition smoothly
between words.  This can sometimes reduce intelligibility by eliminating
word boundary cues.  Placing a Q, (not the silent vowel QX) at the end of
a word results in some phonological effects taking place which can restore
the word boundary cues.


8 / Writing Phonetically / English And Phonetic Text Example

Cardiomyopathy.  I had never heard of it before,
but there it was listed as the form of heart disease
that felled not one or two but all three of the
artificial heart recipients.  A little research
produced some interesting results.  According to an
article in the Nov. 8, 1984, New
England Journal of Medicine, cigarette smoking causes
this lethal disease that weakens the heart's pumping
power.  While the exact mechanism is not clear, Dr.
Arthur J. Hartz speculated that nicotine or carbon
monoxide in the smoke somehow poisons the heart and
leads to heart failure.

KAA1RDIYOWMAYAA5PAXTHIY.  AY /HAED NEH1VER /HER4D AXV IHT BIXFOH5R,
BAHT DHEH5R IHT WAHZ - LIH4STIXD AEZ (DHAX FOH5RM AXV /HAA5RT DIHZIY5Z)
DHAET FEH4LD (NAAT WAH5N OHR TUW5) - BAHT (AO7L THRIY5 AXV DHAX
AA5RTAXFIHSHUL /HAA5RTQ RIXSIH5PIYINTS).  (AH LIH5TUL RIXSER5CH)
PROHDUW5ST (SAHM IH5NTRIHSTIHNX RIXZAH5LTS).  AHKOH5RDIHNX TUW (AEN
AA5RTIHKUL IHN DHAX NOWVEH5MBER EY2TH NAY5NTIYNEYTIYFOH1R NUW
IY5NXGLIND JER5NUL AXV MEH5DIXSIN), (SIH5GEREHT SMOW5KIHNX) KAO4ZIHZ
(DHIHS LIY5THUL DIHZIY5Z) DHAET WIY4KINZ (DHAX /HAA5RTS PAH4MPIHNX
PAW2ER).  WAYL (DHIY IHGZAE5KT MEH5KINIXZUM) IHZ NAAT KLIY5R, DAA5KTER
AA5RTHER JEY2 /HAARTS SPEH5KYULEYTIHD DHAET NIH5KAXTIYN, OHR KAA5RBIN
MUNAA5KSAYD IHN DHAX SMOW5K - SAH5M/HAW1 POY4ZINZ DHAX /HAA5RT, AEND
LIY4DZ TUW (/HAA5RT FEY5LYER).


8 / How to Write Phonetically for Narrator / Concluding Remarks

This guide should get you off to a good start in phonetic writing for
Narrator.  The only way to get really proficient is to practice.  Many
people become good at it in as little as one day.  Others make continual
mistakes because they find it hard to let go of the rules of English
spelling, so trust your ears.


8 Narrator Device / A More Technical Explanation

The narrator speech synthesizer is a computer model of the human speech
production process.  It attempts to produce accurately spoken utterances
of any English sentence, given only a phonetic representation as input.
Another program in the Amiga speech system, the translator device, derives
the required phonetic spelling from English text. Timing and pitch
contours are produced automatically by the synthesizer software.

In humans, the physical act of producing speech sounds begins in the
lungs.  To create a voiced sound, the lungs force air through the vocal
folds (commonly called the vocal cords), which are held under tension and
which periodically interrupt the flow of air, thus creating a buzz-like
sound.  This buzz, which has a spectrum rich in harmonics, then passes
through the vocal tract and out the lips and nose, which alters its
spectrum drastically.  This is because the vocal tract acts as a frequency
filter, selectively reinforcing some harmonics and suppressing others.  It
is this filtering that gives a speech sound its identity.  The amplitude
versus frequency graph of the filtering action is called the vocal tract
transfer function.  Changing the shape of the throat, tongue, and mouth
retunes the filter system to accentuate different frequencies.

The sound travels as a pressure wave through the air, and it causes the
listener's eardrum to vibrate.  The ear and brain of the listener decode
the incoming frequency pattern.  From this the listener can subconsciously
make a judgement about what physical actions were performed by the speaker
to make the sound.  Thus the speech chain is completed, the speaker having
encoded his physical actions on a buzz via selective filtering and the
listener having turned the sound into guesses about physical actions by
frequency decoding.

Now that we know how humans produce speech, how does the Amiga do it? It
turns out that the vocal tract transfer function is not random, but tends
to accentuate energy in narrow bands called formants.  The formant
positions move fairly smoothly as we speak, and it is the formant
frequencies to which our ears are sensitive.  So, luckily, we do not have
to model throat, tongue, teeth and lips with our computer, we can imitate
formant actions instead.

A good representation of speech requires up to five formants, but only the
lowest three are required for intelligibility.  The pre-V37 Narrator had
only three formants, while the V37 Narrator has five formants for a more
natural sounding voice.  We begin with an oscillator that produces a
waveform similar to that which is produced by the vocal folds, and we pass
it through a series of resonators, each tuned to a different formant
frequency.  By controlling the volume and pitch of the oscillator and the
frequencies of the resonators, we can produce highly intelligible and
natural-sounding speech.  Of course the better the model the better the
speech; but more importantly, experience has shown that the better the
control of the model's parameters, the better the speech.

Oscillators, volume controls, and resonators can all be simulated
mathematically in software, and it is by this method that the narrator
system operates.  The input phonetic string is converted into a series of
target values for the various parameters.  A system of rules then operates
on the string to determine things such as the duration of each phoneme and
the pitch contour.  Transitions between target values are created and
smoothed to produce natural, continuous changes from one sound to the next.

New values are computed for each parameter for every 8 milliseconds of
speech, which produces about 120 acoustic changes per second.  These
values drive a mathematical model of the speech synthesizer.  The accuracy
of this simulation is quite good.  Human speech has more formants that the
narrator model, but they are high in frequency and low in energy content.

The human speech production mechanism is a complex and wonderful thing.
The more we learn about it, the better we can make our computer
simulations.  Meanwhile, we can use synthetic speech as yet another
computer output device to enhance the man/machine dialogue.


8 Narrator Device / Additional Information on the Narrator Device

Additional programming information on the narrator device can be found in
the include files and the Autodocs for the narrator device and the
Autodocs for the translator library.  All are contained in the Amiga ROM
Kernel Reference Manual: Includes and Autodocs.

                    Narrator Device Information
                 ----------------------------------
                 INCLUDES        devices/narrator.h
                                 devices/narrator.i

                 AUTODOCS        narrator.doc
                                 translator.doc


Amiga® RKM Devices: Appendix A - IFF: Interchange File Format

One of the Amiga's strengths is the wide acceptance of several IFF
specifications.  Most notable is the ease with which graphic files (of
form ILBM) can be transferred among dozens of paint, animation and
special effects packages.  This ability to to easily share data between a
variety of programs lets the user select the best program for a specific
job rather than fighting the restritions of a single, all-in-one software
package.  Developers can market specialized applications that are good at
a certain limited set of operations, and with the help of the multitasking
Amiga operating system, create the effect of a large integrated system.

Any developer with a package that creates or reads data should use an
existing IFF standard.  If no current IFF form is suitable then the
developer should contact other developers and users with similar needs and
work out a new IFF form using the design principles specified in this
appendix.  To prevent conflicts, new IFF forms must be registered with
Amiga, Inc. before they are used.  No additional restrictions are placed on
the design of IFF forms aside from the general IFF syntax rules listed
here.

                 Contents of the IFF Specification
                 ---------------------------------
 EA IFF 85 - General IFF Format Specifications
 FORM Specifications from the Original EA Document
 Third Party Public FORM and Chunk Specifications and Additional Documents
 IFF Source Code


Amiga® RKM Devices: Index

           A              Note: Numbers refer to page numbers in the
          B C           "Amiga® ROM Kernal Reference Manual: Devices"
          D E           3rd edition, ISBN 0-201-56776-8
         F G H
           I
         J K L
         M N O
           P
          Q R
           S
           T
         U V W


A Index

AbortIO(),
Absolute_Joystick.c, 95
Accessing a Device,
ADCMD_ALLOCATE command, 22 - examples, 23
ADCMD_FINISH command, 26
ADCMD_FREE command, 24
ADCMD_LOCK command, 24
ADCMD_PERVOL command, 26
ADCMD_SETPREC command, 24
ADCMD_WAITCYCLE command, 27
AddTime(), 295
ADIOF_NOWAIT flag, 23
ADIOF_PERVOL flag, 25
ADIOF_SYNCCYCLE flag, 26
ADIOF_WRITEMESSAGE, 25
Allocate_Misc.c, 340
Alloc_Misc.a, 339
Amiga BootStrap -->
AMIGA keys, 79
Amiga System Devices -->
ARPABET, 144
Audio Channels -->
Audio Device -->
Audio Hardware, 22
Audio.c, 19
Audio_8SVX.c, 28


Amiga BootStrap Index

Amiga BootStrap, 257
  boot mechanisms, 258
  bootblock booting, 259
  bootpoint booting, 259
  expansion board configuration, 257
  nodes, 258


Amiga System Devices Index

Amiga System Devices,
  accessing functions,
  asynchronous I/O requests,
  closing,
  commands,
  definition,
  device base address pointer,
  device names,
  device specific command prefixes,
  devices with functions,
  error checking,
  error indications,
  error processing,
  error reporting,
  Exec command prefixes,
  gracefully exiting,
  opening,
  passing I/O requests,
  synchronous I/O requests,


Audio Channels Index

Audio Channels, 13
  allocation key, 24
  allocation/arbitration commands, 22
  allocation, 21, 22
  changing the precedence, 24
  combinations, 22
  freeing, 24
  Lock, 22
  multi-channel, 24
  stealing, 21, 22


Audio Device Index

Audio Device, 13
  AbortIO(), 18
  additional information, 34
  BeginIO(), 18
  changing the volume, 26
  channel, 14
  CloseDevice(), 18
  closing, 18
  CMD_FLUSH, 27
  CMD_READ, 27
  CMD_RESET, 27
  CMD_START, 27
  CMD_STOP, 27
  CMD_WRITE, 25
  commands and functions, 15
  definitions, 14
  device interface, 16
  double-buffering, 26
  free, 17
  hardware control commands, 25
  IORequest block, 16
  IORequest structures, 16
  lock, 17
  opening, 16
  playing a sound, 25
  precedence of users, 22
  precedence, 17
  reserve, 17
  sample, 14
  scope of commands, 17
  simple audio example, 18
  starting a sound, 27
  steal channel, 22
  stopping a sound, 26, 27
  Wait(), 18
  WaitPort(), 18


B,C Index

BattClock Resource, 325 - additional information, 327 - functions, 325
BattMem Resource, 327 - additional information, 327 - functions, 327
BeginIO(), , , 18, 271
Boot priority - floppy disks, 258

Caps Lock key, 78
Cause(), 314
CBD_CHANGEHOOK command, 42 - caveats, 43
CBD_CURRENTREADID command, 40
Cbio.c, 50
Changehook_Test.c, 47
CheckIO(),
CIA Resource -->
Cia_Interval.c, 329
Clipboard Device -->
Clipboard Tool, 38
Clipdemo.c, 43
ClipID, 41
Clip - identification, 37
Closing A Device,  - outstanding I/O requests,
CMD_CLEAR Command, 310
CMD_READ Command, 307
CMD_UPDATE Command, 310
CMD_WRITE command, 177
CMD_WRITE Command, 308
CmpTime(), 295
Commodore SCSI Drives - unit numbers, 250
Complex_Serial.c, 280
Console Device -->
Console.c, 81
Current Clip, 40


CIA Resource Index

CIA Resource, 328
  additional information, 335
  functions, 328
  reading and writing ICRs, 329
  reminders, 329
  timer allocation, 328


Clipboard Device Index

Clipboard Device, 35
  additional information, 59
  advanced uses, 38
  closing, 42
  CMD_READ, 41
  CMD_UPDATE, 40
  CMD_WRITE, 39
  commands and functions, 36
  current clip, 40
  data, 37
  device interface, 37
  disk file, 37
  end-of-clip, 41
  IFF, 38
  IORequest structures, 37
  io_Offset, 39
  monitoring changes, 42
  multiple clips, 38
  multiple units, 38
  new features, 35
  opening, 37
  posting, 40
  post, 41
  reading, 41
  unit numbers, 38
  updating, 40
  writing, 39


Console Device Index

Console Device, 61
  additional information, 86
  caveats, 81
  character output, 66
  closing, 65
  console units, 63, 64
  control sequence introducer, 78
  control sequences, 67
  device interface, 63
  input event qualifiers, 78
  input stream, 75
  I/O request structures, 63
  keyboard input, 66
  new features, 61
  OpenDevice flags, 64
  raw events, 77
  raw input types, 77
  reads, 74
  system functions, 62
  window bounds, 75


D,E Index

Demo_Dump.c, 190
Device Specific Commands,
devices/audio.h, 16
devices/clipboard.h, 37, 40
devices/gameport.h, 92
devices/hardblocks.h, 256
devices/inputevent.h, 105, 106
devices/narrator.h, 134
devices/parallel.h, 161
devices/printer.h, 175
devices/prtbase.h, 181, 196
devices/scsidisk.h, 251
devices/serial.h, 267
devices/timer.h, 287
devices/trackdisk.h, 305
Digital-To-Analog, 13
Disk Resource, 335 - add'l info, 337 - allocation, 336 - functions, 335
DISKINSERTED message, 314
DISKREMOVED message, 314
DoIO(), ,
DoSpecial(), 199 - parameters, 199

E-Clock, 287 - E-Clock time, 298 - ECLOCK Timer Unit, 288 - EClockVal, 298
Ejecting a disk, 311
End-of-Clip, 41
End-of-File, 41
EpsonX Driver -->
ETD_CLEAR Command, 310
ETD_FORMAT Command, 311
ETD_MOTOR Command, 310
ETD_RAWREAD Command, 315
ETD_RAWWRITE Command, 316
ETD_READ Command, 307
ETD_SEEK Command, 314
ETD_UPDATE Command, 310
ETD_WRITE Command, 308
Exec Commands, ,
exec/errors.h,
exec/interrupts.h, 106
exec/io.h,
Exec error codes, 187


EpsonX Driver Index

EpsonX Driver, 210
  data.c, 214
  density.c, 230
  dospecial.c, 217
  init.asm, 213
  macros.i, 211
  makefile, 210
  printertag.asm, 212
  render.c, 221
  rev.i, 212
  transfer.asm, 225
  transfer.c, 228


F,G,H Index

Filesystem Resource, 337 - additional information, 338
Floppy Disk -->
FlushDevice(), 342
Flux Format, 315, 316
FTXT, 39
Full_Narrator.c, 151

Gameport Connectors, 104
Gameport Device -->
Gameport Events, 91
GamePortTrigger structure, 92
GetSysTime(), 290
Get_Disk_Unit_ID.c, 336
Get_Filesys.c, 337
Get_Systime.c, 290
GPCT_ABSJOYSTICK flag, 90, 94
GPCT_ALLOCATED flag, 90, 94
GPCT_MOUSE flag, 90, 94
GPCT_NOCONTROLLER flag, 90, 94, 95
GPCT_RELJOYSTICK flag, 90, 94
GPD_ASKCTYPE command, 94
GPD_ASKTRIGGER command, 93
GPD_READEVENT command, 91
GPD_SETCTYPE command, 94
GPD_SETTRIGGER command, 92
GPTF_DOWNKEYS flag, 92
GPTF_UPKEYS flag, 92
Graphic Dumps -->

hardware/custom.h, 339
Harmony, 13
HDToolBox, 253
HD_SCSICMD command, 251
Hookface.asm, 56
Hook, 42
HP_LaserJet Driver -->


Floppy Disk Index

Floppy Disk, 306
  floppy boot process, 571
  floppy disk format, 572
  floppy physical layout, 571
  MFM encoding, 573
  I/O, 306


Gameport Device Index

Gameport Device, 87
  additional information, 100
  closing, 90
  commands and functions, 88
  connectors, 87
  controllers, 89
  determining controller type, 94
  determining triggering conditions, 93
  IORequest structures, 89
  joystick controller, 90
  joystick controller, 93
  mouse controller, 90
  mouse controller, 92
  opening, 89
  reading, 91
  setting controller type, 94
  setting triggering conditions, 92
  triggering events, 92
  units, 104
  use protocol, 94


Graphic Dumps Index

Graphic Dumps
  additional notes, 194


HP_LaserJet Driver Index

HP_LaserJet Driver, 231
  data.c, 235
  density.c, 242
  dospecial.c, 237
  hp_rev.i, 233
  init.asm, 233
  macros.i, 231
  printertag.asm, 232
  render.c, 240
  transfer.asm, 243
  transfer.c, 242


I Index

I/O request,  - creating,
IDCMP, 114
IECLASS_NEWPOINTERPOS, 106, 110
IECLASS_POINTERPOS, 110
iffparse.library, 35, 38, 353
IFF -->
Index Pulse, 317
IND_ADDHANDLER Command, 108
IND_REMHANDLER Command, 109
IND_SETMPORT command, 107
IND_SETMTRIG command, 107
IND_SETPERIOD Command, 113
IND_SETTHRESH Command, 112
IND_WRITEEVENT Command, 109
IND_WRITEEVENT command, 110
Input Device -->
Input Event Chain, 108 - multiple events, 108 - new events, 108
Input Events - generators of, 109 - Intuition handling of, 108
Input Qualifiers, 114
Input Request Block, 103
InputHandler.a, 116
International Phonetic Alphabet, 144
Interrupt, 314
Intuition - as input device handler, 108 - mouse input, 104
IOAudio, 16
IOB_QUICK flag, 271
IOClipReq, 37
IOExtPar, 161
IOExtSer, 267
IOStdReq Structure, 63, 89, 249
IOTDF_INDEXSYNC flag, 316
IOTDF_WORDSYNC flag, 316
io_ParFlags, 166
io_PTermArray, 163, 165
io_SerFlags, 276
io_TermArray, 272


IFF Index

IFF
  chunk, 352
  color map chunk, 352
  definition, 351
  file contents, 351
  file extensibility, 354
  FORM and chunk registry, 429
  FORM, 352
  ILBM, 352
  introduction, 351


Input Device Index

Input Device, 101
  adding a handler, 108
  additional information, 118
  and Intuition, 114
  closing, 106
  commands and functions, 102
  designing an input handler, 108
  determining current qualifiers, 113
  device interface, 103
  event handler, 108
  generating input events, 109
  input events, 105
  key repeat events, 113
  memory deallocation, 109
  new features, 101
  opening, 103
  PeekQualifier(), 113
  removing a handler, 109
  setting key repeat interval, 113
  setting key repeat timing, 112
  setting mouse port report, 107
  setting mouse port, 107
  setting the mouse position, 110
  time specification, 104


J,K,L Index

Joystick Controller, 90, 93

KBD_ADDRESETHANDLER command, 124
KBD_READEVENT command, 128
KBD_READMATRIX command, 121
KBD_REMRESETHANDLER command, 124
KBD_RESETHANDLERDONE command, 124
Keyboard Device -->
Keyboard_Events.c, 128
KeyHandler.a, 127
Key_Reset.c, 125

Light Pen, 90


Keyboard Device Index

Keyboard Device, 104, 119
  adding a reset handler routine, 124
  additional information, 130
  closing, 121
  commands and functions, 120
  device interface, 121
  IORequest structures, 121
  keyboard events, 119
  opening, 121
  reading keyboard events, 128
  reading the keyboard matrix, 121
  removing a reset handler routine, 124
  signaling the end of a reset routine, 124


M,N,O Index

macros.i, 210
Makeup Of Speech, 144
Message Port,  - creating,
MFM encoding, 315, 316
MICROHZ Timer Unit, 288
Misc Resource -->
Mouse Button Events, 104
Mouse Controller, 90, 92
Mouse Movement Events, 104
mouth_rb -->
Multiple Asynchronous I/O requests,
Multiple_Timers.c, 293

Narrator Device -->
narrator_rb -->
NDF_NEWIORB flag, 135, 138
NDF_SYLSYNC flag, 138
NDF_WORDSYNC flag, 138

OpenDevice(),
Opening A Device,
OpenResource, 324


Misc Resource Index

Misc Resource, 280, 338
  additional information, 343
  allocation, 339
  functions, 339


mouth_rb Index

mouth_rb
  sync field values, 141


Narrator Device Index

Narrator Device, 131
  additional information, 158
  closing, 136
  CMD_READ, 134
  CMD_WRITE, 134
  commands and functions, 132
  controlling speech characteristics, 136
  device interface, 133
  dialect, 136
  introduction, 134
  mouth movement IORequest, 133, 135
  mouth movements, 141
  new features, 131
  OpenDevice() flags, 135
  opening, 135
  phonemes, 143
  Punctuating phonetic strings, 144
  reading, 141
  speaking, 136
  speech IORequest, 133
  syllable synchronization, 141
  technical explanation, 149
  word synchronization, 141
  writing phonetically, 143
  writing, 136


narrator_rb Index

narrator_rb
  field descriptions, 136
  field descriptions, 137
  field descriptions, 138


P Index

Parallel Device -->
Parallel.c, 167
PARF_ACKMODE flag, 166
PARF_EOFMODE flag, 163, 166
PARF_FASTMODE flag, 166
PARF_SHARED flag, 161, 166
PARF_SLOWMODE flag, 166
PBFB_NOMOUNT flag, 256
PDCMD_QUERY command, 166
PDCMD_SETPARAMS command, 165
PeekQualifier(), 113
Pending Post, 41
Phonemes -->
POTGO Resource, 343
Potgo Resource - additional information, 345 - functions, 343
PRD_DUMPRPORT command, 187
PRD_PRTCOMMAND command, 178
PRD_QUERY command, 186
PRD_RAWWRITE command, 177
Pre_V36_Device_Use.c,
Printer Device -->
Printer Driver -->
printerIO Union, 175
printertag.asm, 196 - fields, 200 - parts, 197
Printer_Data.c, 181
PRT:, 173 - closing, 174 - opening, 173 - writing output, 173
PStat - printer device status structure, 186


Parallel Device Index

Parallel Device, 159
  additional information, 168
  break conditions, 163
  closing, 162
  commands and functions, 160
  device interface, 161
  EOF mode, 163
  error codes, 167
  flags, 166
  io_PTermArray, 163, 165
  null-terminated write, 162
  opening, 161
  parameters, 165
  querying the device, 166
  reading, 162
  setting parameters, 165
  status bits, 166
  terminating a read or write, 163
  writing, 162


Phonemes Index

Phonemes, 143
  consonant groups, 145
  consonants, 143
  contraction and special symbols, 145
  contractions, 144
  digits and punctuation, 144
  diphthongs, 143, 145
  example text, 149
  glottal stop, 146
  hints for intelligibility, 148
  punctuation, 148
  sentence length, 148
  special symbols, 144
  stress and intonation, 146, 147
  stress mark placement rules, 146
  vowel groups, 145
  vowels, 143


Printer Device Index

Printer Device, 171
  access, 173
  additional information, 246
  alphanumeric drivers, 198
  changing printer preferences, 182
  closing AmigaDOS printer device, 174
  closing, 177
  commands and functions, 172, 179
  CommandTable, 198
  creating drivers, 196
  data structures, 175
  device interface, 175
  direct use, 173
  double buffering, 204
  driver modules, 196
  dumping a RastPort, 187
  dumping buffer, 205
  error codes, 187
  Exec printer I/O, 175
  graphic driver modules, 196
  graphic preferences, 183
  graphics printer drivers, 203
  ISO color table, 181
  NULL-terminated writes, 177
  obtaining printer data, 181
  opening AmigaDOS printer device, 173
  opening, 175
  parallel status bits, 186
  Preferences, 198
  print request guidelines, 177
  printer command definitions, 178
  printer special flags, 188
  printing with corrected aspect ratio, 189
  processes and tasks, 174
  querying the device, 185
  sending printer commands, 178
  serial status bits, 186
  strip printing, 193
  suggested typefaces, 181
  text preferences, 182
  timeout, 198
  two methods of output, 173
  using directly, 175
  writing processed text, 176
  writing unprocessed text, 176


Printer Driver Index

Printer Driver, 171, 196
  buffer deallocation, 206
  character conversion routine, 201
  CommandTable, 198
  DoSpecial(), 199
  driver modules, 196
  example source code, 209
  extended character table, 200
  graphic driver modules, 196, 203
  printertag.asm, 208
  Render(), 203
  SetDensity(), 208
  testing, 209
  Transfer(), 206


Q,R Index

Query_Serial.c, 341
Quick I/O, , 271

RastPort -->
Read_BattClock.c, 326
Read_Keyboard_Matrix.c, 122
Read_Potinp.c, 343
Render() -->
ReplyMsg(), 292
Reset Handlers, 124
Resources -->
RigidDiskBlock -->
Run Length Encoding, 205


RastPort Index

RastPort, 187, 193
  building dimensions, 189
  dump arguments, 188
  printing a non-displayed, 189


Render() Index

Render(), 203
  cases, 203
  clearing and initializing pixel buffer, 205
  closing down, 206
  dumping a pixel buffer, 205
  master initialization, 203
  pre-master initialization, 203
  putting pixels in a buffer, 205
  switching to next color, 206


Resources Index

Resources, 323
  BattClock Resource, 325
  BattMem Resource, 327
  CIA resource, 328
  Disk resource, 335
  FileSystem resource, 337
  include files, 325
  interface, 324
  listing, 324
  Misc resource, 338
  OpenResource(), 324
  Potgo Resource, 343


RigidDiskBlock Index

RigidDiskBlock, 253
  creation, 253
  non-ROM filing system, 257
  specification, 253
  use of information, 256


S Index

SatisfyMsg, 40
SCSI Device -->
SCSI-Direct, 250 - ModeSense setup, 251 - SCSICmd, 251
SCSICmd, 251 - fields, 252
SCSIF_AUTOSENSE flag, 252
SCSI_Direct.c, 260
SDCMD_BREAK, 279
SDCMD_QUERY command, 278
SDCMD_SETPARAMS command, 275
Sending A Command To A Device,
SendIO(), , , 270
SERF_7WIRE flag, 267
SERF_EOFMODE flag, 272
SERF_QUEUEDBRK, 279
SERF_SHARED flag, 267
Serial Device -->
SetDensity(), 208
Setting The Mouse Position -->
Set_Mouse.c, 111
Set_Prefs.c, 183
Simple_Serial.c, 268
Simple_Timer.c, 299
Sound Synthesis, 13
Speak_Narrator.c, 139
SPECIAL_ASPECT flag, 189
SPECIAL_NOPRINT flag, 194
Speech Output - introduction, 134
Strip Printing -->
Structures -->
SubTime(), 295
Swap_Buttons.c, 115
Sync'ed Read and Write Limitations, 316
System Time, 290


SCSI Device Index

SCSI Device, 247
  additional information, 263
  closing, 250
  commands and functions, 248
  device interface, 249
  opening, 249
  RigidDiskBlock, 253
  SCSI-direct, 250
  system functions, 248
  unit numbers, 249


Serial Device Index

Serial Device, 265
  additional information, 284
  alternative I/O modes, 270
  break command, 279
  break conditions, 272
  buffered characters, 267
  closing, 268
  commands and functions, 266
  device characteristics, 265
  device interface, 266
  EOF mode, 272
  error codes, 279
  high speed operation, 271
  io_TermArray, 272
  multiple ports, 280
  NULL-terminated write, 268
  opening, 267
  parameters, 275
  querying the device, 278
  quick I/O, 271
  reading, 267
  separate tasks, 273
  serial flags, 276
  setting parameters, 275
  status bits, 278
  terminating the read, 272
  using BeginIO(), 271
  writing, 268


Setting The Mouse Position Index

Setting The Mouse Position
  basic method, 110
  pre-V36 absolute position, 110
  pre-V36 relative position, 110
  V36 absolute position, 110
  V36 normalized position, 110
  V36 relative position, 110


Strip Printing Index

Strip Printing, 193
  aspect-ratio-corrected image, 194
  height of strip, 194
  procedure, 194
  smoothing, 194


Structures Index

Structures
  DriveGeometry, 309
  EClockVal, 287
  GamePortTrigger, 92
  GamePortTrigger, 107
  IEPointerPixel, 106
  IEPointerTablet, 106
  InputEvent, 91, 104, 106, 110
  Interrupt, 106
  IOAudio, 16
  IOClipReq, 37
  IODRPReq, 175
  IODRPReq, 187
  IOExtPar, 161
  IOExtSer, 267
  IOExtTD, 305
  IOExtTD, 305
  IOPrtCmdReq, 175
  IOStdReq, 103, 175, 249
  mouth_rb, 133
  narrator_rb, 133
  PrinterData, 181
  PrinterData, 197
  PrinterExtendedData, 181
  printerIO, 175
  PrinterSegment, 196
  SatisfyMsg, 40
  SCSICmd, 251
  timerequest, 103, 112, 113, 287
  timeval, 287


T Index

Taking Over The Serial Hardware, 280
TDF_ALLOW_NON_3_5 flag, 307
TD_ADDCHANGEINT Command, 314
TD_CHANGENUM Command, 313
TD_CHANGESTATE Command, 312
TD_FORMAT Command, 311
TD_GETDRIVETYPE command, 312
TD_GETGEOMETRY command, 309
TD_GETGEOMETRY, 313
TD_GETNUMTRACKS Command, 312
TD_MOTOR Command, 310
TD_PROTSTATUS Command, 312
TD_RAWREAD Command, 315
TD_RAWWRITE Command, 316
TD_REMCHANGEINT Command, 314
TD_SEEK Command, 314
Terminate_Parallel.c, 163
Terminate_Serial.c, 272
Text To Speech - introduction, 134
Time Events, 104
Timer Device -->
TimerBase Variable, 289
Timer_Arithmetic.c, 295
Trackdisk Device -->
Track_Copy.c, 318
Transfer(), 206 - dithering, 206
Translator Library, 134 - example fragment, 134
TR_GETSYSTIME command, 290
TR_SETSYSTIME Command, 290


Timer Device Index

Timer Device, 104, 285
  adding a time request, 291
  additional information, 302
  closing, 290
  commands and functions, 286
  device interface, 287
  E-Clock time, 287, 298
  functions, 287
  multiple timer requests, 293
  opening for device functions, 289
  opening multiple times, 293
  opening, 289
  time alarms, 292
  time arithmetic functions, 295
  time delays, 292
  time requests, 287
  units, 288
  uses of time arithmetic, 296


Trackdisk Device Index

Trackdisk Device, 303
  adding an interrupt handler, 314
  additional information, 322
  byte offset calculation, 307
  clearing the track buffer, 310
  closing, 308
  commands and functions, 304
  controlling the drive motor, 310
  determining drive geometry, 309
  determining the diskchange number, 313
  determing write-protect status, 312
  determining drive type, 312
  determining the number of tracks, 312
  determining the presence of a disk, 312
  device interface, 305
  diagnostic commands, 314
  ejecting a disk, 311
  enhanced commands, 305
  error codes, 317
  floppy disk I/O, 306
  formatting a track, 311
  iotd_Count, 305
  low-level access, 315
  moving the drive head, 314
  notification of disk changes, 314
  opening, 307
  reading raw data, 315
  reading, 307
  removing an interrupt handler, 314
  restrictions, 306
  sector label, 306
  status commands, 311
  updating a track sector, 310
  writing raw data, 316
  writing, 308


U,V,W Index

Using a Device,
utility.library, 290, 325

V36_Device_Use.c, 10
VBLANK Timer Unit, 288
Vertical Blank Frequency - find current VB frequency, 92

Wait(), , 18, 270
WAITECLOCK Timer Unit, 288
WaitIO(), ,
WaitPort(), , 18
WAITUNTIL Timer Unit, 288
Window structure, 66


Amiga® RKM Devices: Appendix B Example Device

This appendix contains source code for a sample device.  The example code
is an excellent starting point for those who want to create a custom
device and add it to the Amiga's system software.

The example is a complete four-unit, static-sized RAM disk that works
under the old (standard) filing system, the new Fast Filing System (FFS),
and has optional code to bind it to an AUTOCONFIG(TM) device.

The examples have been assembled under the Metacomco assembler V11.0 and
under the CAPE assembler V2.0.

 ramdev-mountlist      ramdev.i      asmsupp.i      ramdev.device.asm


Amiga® RKM Devices: Appendix C : Floppy Boot Process and Physical Layout

The first two sectors on each floppy disk contain special boot
information. These sectors are read into the system at an arbitrary
position; therefore, the code must be position independent.  The first
three longwords come from the include file devices/bootblock.h. The type
must be BBID_DOS; the checksum must be correct (an additive carry
wraparound sum of 0xffffffff). Execution starts at location 12 of the
first sector read in.

The code is called with an open trackdisk.device I/O request pointer in A1
(see the ``Trackdisk'' chapter for more information). The boot code is
free to use the IO request as it wishes (the code may trash A1, but must
not trash the I/O request itself).

The boot code must return values in two registers:  D0 and A0. D0 is a
failure code - if it is non-zero then a system alert will be called, and
the system will reboot.

If D0 is zero then A0 must contain the start address to jump to.  The
strap module will free the boot sector memory, free the boot picture
memory, close the trackdisk.device I/O request, do any other cleanup that
is required, then jump to the location pointed to by A0.

Boot code may allocate memory, use trackdisk.device to load relocatable
information into the memory, then return with D0=0 and A0 pointing to
code. The system will clean up, then call the code.

 Commodore-Amiga Disk Format
 MFM Track Encoding


Appendix C / Commodore-Amiga Disk Format

The following are details about how the bits on the Commodore-Amiga
disk are actually written.

    Gross Data Organization:

        3 1/2 inch (90mm) disk
        double-sided
        80 cylinders/160 tracks

    Per-track Organization:

        Nulls written as a gap, then 11 or 22 sectors of data.
        No gaps written between sectors.

    Per-sector Organization:

        All data is MFM encoded.  This is the pre-encoded contents
        of each sector:

            two bytes of 00 data    (MFM = $AAAA each)
            two bytes of A1*        ("standard sync byte" -- MFM
                                     encoded A1 without a clock pulse)
                                    (MFM = $4489 each)
            one byte of format byte (Amiga 1.0 format = $FF)
            one byte of track number
            one byte of sector number
            one byte of sectors until end of write (NOTE 1)
                [above 4 bytes treated as one longword
                 for purposes of MFM encoding]
            16 bytes of OS recovery info (NOTE 2)
                [treated as a block of 16 bytes for encoding]
            four bytes of header checksum
                [treated as a longword for encoding]
            four bytes of data-area checksum
                [treated as a longword for encoding]
            512 bytes of data
                [treated as a block of 512 bytes for encoding]

    NOTE:
    -----
    The track number and sector number are constant for each particular
    sector. However, the sector offset byte changes each time we rewrite
    the track.

    The Amiga does a full track read starting at a random position on the
    track and going for slightly more than a full track read to assure
    that all data gets into the buffer. The data buffer is examined to
    determine where the first sector of data begins as compared to the
    start of the buffer. The track data is block moved to the beginning
    of the buffer so as to align some sector with the first location in
    the buffer.

    Because we start reading at a random spot, the read data may be
    divided into three chunks: a series of sectors, the track gap, and
    another series of sectors. The sector offset value tells the disk
    software how many more sectors remain before the gap. From this the
    software can figure out the buffer memory location of the last byte
    of legal data in the buffer. It can then search past the gap for the
    next sync byte and, having found it, can block move the rest of the
    disk data so that all 11 sectors of data are contiguous.

        Example:

            The first-ever write of the track from a buffer looks
            like this:

            <GAP> |sector0|sector1|sector2|......|sector10|

            sector offset values:

                      11      10      9     .....     1

            (If I find this one at the start of my read buffer, then I
             know there are this many more sectors with no intervening
             gaps before I hit a gap).  Here is a sample read of this
             track:

            <junk>|sector9|sector10|<gap>|sector0|...|sector8|<junk>

            value of 'sectors till end of write':

                      2        1     ....    11   ...    3

            result of track re-aligning:

            <GAP>|sector9|sector10|sector0|...|sector8|

            new sectors till end of write:

                     11       10      9    ...     1

            so that when the track is rewritten, the sector offsets
            are adjusted to match the way the data was written.

    Sector Label Area
    -----------------
    This is operating system dependent data and relates to how AmigaDOS
    assigns sectors to files.  Reserved for future use.


Appendix C / MFM Track Encoding

When data is MFM encoded, the encoding is performed on the basis of a data
block-size. In the sector encoding described above, there are bytes
individually encoded; three segments of 4 bytes of data each, treated as
longwords; one segment of 16 bytes treated as a block; two segments of
longwords for the header and data checksums; and the data area of 512
bytes treated as a block.

When the data is encoded, the odd bits are encoded first, then the even
bits of the block.

The procedure is: Make a block of bytes formed from all odd bits of the
block, encode as MFM.  Make a block of bytes formed from all even bits of
the block, encode as MFM.  Even bits are shifted left one bit position
before being encoded.

The raw MFM data that must be presented to the disk controller will be
twice as large as the unencoded data.  The relationship is:

 1 -> 01
 0 -> 10    ;if following a 0
 0 -> 00    ;if following a 1

With clever manipulation, the blitter can be used to encode and decode the
MFM.


Devices/Dev_examples/Pre_V36_Device_Use.c

/*
 * Pre_V36_Device_Use.c
 *
 * This is an example of using the serial device.
 * First, we will attempt to create a message port with CreatePort()
 * Next, we will attempt to create the I/O request with CreateExtIO()
 * Then, we will attempt to open the serial device with OpenDevice()
 * If successful, we will send the SDCMD_QUERY command to it
 * and reverse our steps.
 * If we encounter an error at any time, we will gracefully exit.
 *
 * Compile with SAS C 5.10  lc -cfistq -v -y -L
 *
 * Run from CLI only
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/io.h>
#include <devices/serial.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }     /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

void main(void)
{
struct MsgPort *SerialMP;       /* pointer to our message port */
struct IOExtSer *SerialIO;      /* pointer to our I/O request */

    /* Create the message port */
if (SerialMP=CreatePort(NULL,NULL))
    {
        /* Create the I/O request */
    if (SerialIO = (struct IOExtSer *)CreateExtIO(SerialMP,sizeof(struct IOExtSer)))
        {
            /* Open the serial device */
        if (OpenDevice(SERIALNAME,0,(struct IORequest *)SerialIO,0L))

            /* Inform user that it could not be opened */
            printf("Error: %s did not open\n",SERIALNAME);
        else
            {
            /* device opened, send query command to it */
            SerialIO->IOSer.io_Command  = SDCMD_QUERY;
            if (DoIO((struct IORequest *)SerialIO))

                /* Inform user that query failed */
                printf("Query  failed. Error - %d\n",SerialIO->IOSer.io_Error);
            else
                /* Print serial device status - see include file for meaning */
                printf("\n\tSerial device status: %x\n\n",SerialIO->io_Status);

            /* Close the serial device */
            CloseDevice((struct IORequest *)SerialIO);
            }
        /* Delete the I/O request */
        DeleteExtIO(SerialIO);
        }
    else
        /* Inform user that the I/O request could be created */
        printf("Error: Could create I/O request\n");

    /* Delete the message port */
    DeletePort(SerialMP);
    }
else
    /* Inform user that the message port could not be created */
    printf("Error: Could not create message port\n");
}


Devices/Dev_examples/V36_Device_Use.c

  /*
   * V36_Device_Use.c
   *
   * This is an example of using the serial device.
   * First, we will attempt to create a message port with CreateMsgPort()
   * Next, we will attempt to create the I/O request with CreateIORequest()
   * Then, we will attempt to open the serial device with OpenDevice()
   * If successful, we will send the SDCMD_QUERY command to it
   * and reverse our steps.
   * If we encounter an error at any time, we will gracefully exit.
   *
   * Compile with SAS C 5.10  lc -cfistq -v -y -L
   *
   * Requires Kickstart V36 or greater.
   *
   * Run from CLI only
   */

  #include <exec/types.h>
  #include <exec/memory.h>
  #include <exec/io.h>
  #include <devices/serial.h>

  #include <clib/exec_protos.h>
  #include <clib/alib_protos.h>

  #include <stdio.h>

  #ifdef LATTICE
  int CXBRK(void) { return(0); }     /* Disable SAS CTRL/C handling */
  int chkabort(void) { return(0); }  /* really */
  #endif

  void main(void)
  {
  struct MsgPort *SerialMP;       /* pointer to our message port */
  struct IOExtSer *SerialIO;      /* pointer to our I/O request */

      /* Create the message port */
  if (SerialMP=CreateMsgPort())
      {
          /* Create the I/O request */
      if (SerialIO = CreateIORequest(SerialMP,sizeof(struct IOExtSer)))
          {
              /* Open the serial device */
          if (OpenDevice(SERIALNAME,0,(struct IORequest *)SerialIO,0L))

              /* Inform user that it could not be opened */
              printf("Error: %s did not open\n",SERIALNAME);
          else
              {
              /* device opened, send query command to it */
              SerialIO->IOSer.io_Command  = SDCMD_QUERY;
              if (DoIO((struct IORequest *)SerialIO))

                  /* Inform user that query failed */
                  printf("Query  failed. Error - %d\n",SerialIO->IOSer.io_Error);
              else
                  /* Print serial device status - see include file for meaning */
                  printf("\n\tSerial device status: %x\n\n",SerialIO->io_Status);

              /* Close the serial device */
              CloseDevice((struct IORequest *)SerialIO);
              }
          /* Delete the I/O request */
          DeleteIORequest(SerialIO);
          }
      else
          /* Inform user that the I/O request could be created */
          printf("Error: Could create I/O request\n");

      /* Delete the message port */
      DeleteMsgPort(SerialMP);
      }
  else
      /* Inform user that the message port could not be created */
      printf("Error: Could not create message port\n");
  }


Devices/Dev_examples/Terminate_Parallel.c

/*
 * Terminate_Parallel.c
 *
 * This is an example of using a termination array for writes from the
 * parallel device. A termination array is set up for the characters Q, E,
 * A and %. The EOFMODE flag is set in io_ParFlags to indicate that we want
 * to use a termination array by sending the PDCMD_SETPARAMS command to the
 * device. Then, a CMD_WRITE command is sent to the device with io_Length
 * set to -1. The write will terminate when one of the four characters in
 * the termination array is sent or when the end of the write buffer has
 * been reached.
 *
 * Compile with SAS C 5.10  lc -b1 -cfistq -v -y -L
 *
 * Run from CLI only
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/io.h>
#include <devices/parallel.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

void main(void)
{
struct MsgPort  *ParallelMP;          /* Define storage for one pointer */
struct IOExtPar *ParallelIO;         /* Define storage for one pointer */

struct IOPArray Terminators =
{
0x51454125,/* Q E A A */
0x25252525 /* fill to end with lowest value, must be in descending order */
};

UBYTE *WriteBuffer ="abcdefghijklmEopqrstuvwxyze";
UWORD ctr;

if (ParallelMP=CreatePort(0,0))
    {
    if (ParallelIO=(struct IOExtPar *)
                    CreateExtIO(ParallelMP,sizeof(struct IOExtPar)) )
        {
        if (OpenDevice(PARALLELNAME,0L,(struct IORequest *)ParallelIO,0) )
            printf("%s did not open\n",PARALLELNAME);
        else
           {
            /* Tell user what we are doing */
            printf("\fLooking for Q, E, A or % in output\n");

            /* Set EOF mode flag
             * Set the termination array
             * Send PDCMD_SETPARAMS to the parallel device
             */
            ParallelIO->io_ParFlags |= PARF_EOFMODE;
            ParallelIO->io_PTermArray = Terminators;
            ParallelIO->IOPar.io_Command  = PDCMD_SETPARAMS;
            if (DoIO((struct IORequest *)ParallelIO))
              printf("Set Params failed ");   /* Inform user of error */
            else
             {
             /* Send buffer */
             ParallelIO->IOPar.io_Length   = -1;
             ParallelIO->IOPar.io_Data     = WriteBuffer;
             ParallelIO->IOPar.io_Command  = CMD_WRITE;
             if (DoIO((struct IORequest *)ParallelIO))
              printf("Error: Write failed\n");
             else
             {
               /* Display all characters sent */
               printf("\nThese characters were sent:\n\t\t\tASCII\tHEX\n");
               for (ctr=0;ctr<ParallelIO->IOPar.io_Actual;ctr++)
                    printf("\t\t\t%c\t%x\n",*WriteBuffer,*WriteBuffer++);
               printf("\nThe actual number of characters sent: %d\n",
                         ParallelIO->IOPar.io_Actual);
             }
           }
           CloseDevice((struct IORequest *)ParallelIO);
            }

        DeleteExtIO((struct IORequest *)ParallelIO);
        }
    else
        printf("Error: Could not create I/O request\n");

    DeletePort(ParallelMP);
    }
else
    printf("Error: Could not create message port\n");
}


Devices/Dev_examples/Parallel.c

/*
 * Parallel.c
 *
 * Parallel device example
 *
 * Compile with SAS C 5.10: LC -b1 -cfistq -v -y -L
 *
 * Run from CLI only
 */

#include <exec/types.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <devices/parallel.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }     /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

void main(void)
{
struct MsgPort  *ParallelMP;          /* Define storage for one pointer */
struct IOExtPar *ParallelIO;         /* Define storage for one pointer */
ULONG            WaitMask;          /* Collect all signals here       */
ULONG            Temp;             /* Hey, we all need pockets :-)   */

if (ParallelMP=CreatePort(0,0) )
    {
    if (ParallelIO=(struct IOExtPar *)
        CreateExtIO(ParallelMP,sizeof(struct IOExtPar)) )
        {
        if (OpenDevice(PARALLELNAME,0L,(struct IORequest *)ParallelIO,0) )
            printf("%s did not open\n",PARALLELNAME);
        else
            {
            /* Precalculate a wait mask for the CTRL-C,CTRL-F and message
             * port signals.  When one or more signals are received, Wait()
             *  will return.  Press CTRL-C to exit the example.  Press
             * CTRL-F to wake up the example without doing anything.
             * NOTE: A signal may show up without an associated message!
             */
            WaitMask = SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_F |
                       1L << ParallelMP->mp_SigBit;

            ParallelIO->IOPar.io_Command  = CMD_WRITE;
            ParallelIO->IOPar.io_Length   = -1;
            ParallelIO->IOPar.io_Data     = (APTR)"Hey, Jude!\\r\n";
            SendIO(ParallelIO);             /* execute write */

            printf("Sleeping until CTRL-C, CTRL-F, or write finish\n");
            while(1)
                {
                Temp = Wait(WaitMask);
                printf("Just woke up (YAWN!)\n");

                if (SIGBREAKF_CTRL_C & Temp)
                    break;

                if (CheckIO(ParallelIO) ) /* If request is complete... */
                    {
                    WaitIO(ParallelIO);   /* clean up and remove reply */
                    printf("%ld bytes sent\n",ParallelIO->IOPar.io_Actual);
                    break;
                    }
                }

            AbortIO(ParallelIO);/* Ask dev. to abort request if pending */
            WaitIO(ParallelIO); /* Wait for abort, then clean up */

            CloseDevice((struct IORequest *)ParallelIO);
            }
        DeleteExtIO(ParallelIO);
        }
    DeletePort(ParallelMP);
    }
}


Devices/Dev_examples/Audio.c

/*
 * Audio.c
 *
 * Audio example
 *
 * Compile with SAS C 5.10  lc -b1 -cfistq -v -y -L
 *
 * Run from CLI only
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <devices/audio.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <graphics/gfxbase.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/dos_protos.h>
#include <clib/graphics_protos.h>

#include <stdlib.h>
#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }     /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

struct GfxBase *GfxBase;

/*-----------------------------------------------------------*/
/* The whichannel array is used when we allocate a channel.  */
/* It tells the audio device which channel we want. The code */
/* is 1 =channel0, 2 =channel1, 4 =channel2, 8 =channel3.    */
/* If you want more than one channel, add the codes up.      */
/* This array says "Give me channel 0. If it's not available */
/* then try channel 1; then try channel 2 and then channel 3 */
/*-----------------------------------------------------------*/
UBYTE           whichannel[] = { 1,2,4,8 };

void main(int argc, char **argv)
{
struct IOAudio *AudioIO;    /* Pointer to the I/O block for I/O commands */
struct MsgPort *AudioMP;    /* Pointer to a port so the device can reply */
struct Message *AudioMSG;   /* Pointer for the reply message             */
ULONG           device;
BYTE           *waveptr;              /* Pointer to the sample bytes     */
LONG            frequency = 440;      /* Frequency of the tone desired   */
LONG            duration  = 3;        /* Duration in seconds             */
LONG            clock     = 3579545;  /* Clock constant, 3546895 for PAL */
LONG            samples   = 2;        /* Number of sample bytes          */
LONG            samcyc    = 1;        /* Number of cycles in the sample  */

/*-----------------------------------------------------------------------*/
/* Ask the system if it is PAL or NTSC and set clock constant accordingly*/
/*-----------------------------------------------------------------------*/
GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0L);
if (GfxBase == 0L)
    goto killaudio;
if (GfxBase->DisplayFlags & PAL)
    clock = 3546895;        /* PAL clock */
else
    clock = 3579545;        /* NTSC clock */

if (GfxBase)
    CloseLibrary((struct Library *) GfxBase);

/*-----------------------------------------------------------------------*/
/*  Create an audio I/O block so we can send commands to the audio device*/
/*-----------------------------------------------------------------------*/
AudioIO = (struct IOAudio *)
           AllocMem( sizeof(struct IOAudio),MEMF_PUBLIC | MEMF_CLEAR);
if (AudioIO == 0)
    goto killaudio;
printf("IO block created...\n");

/*-------------------------------------------------------------------*/
/* Create a reply port so the audio device can reply to our commands */
/*-------------------------------------------------------------------*/
AudioMP = CreatePort(0,0);
if (AudioMP == 0)
    goto killaudio;
printf("Port created...\n");

/*----------------------------------------------------------------------*/
/* Set up the audio I/O block for channel allocation:                   */
/* ioa_Request.io_Message.mn_ReplyPort is the address of a reply port.  */
/* ioa_Request.io_Message.mn_Node.ln_Pri sets the precedence (priority) */
/*   of our use of the audio device. Any tasks asking to use the audio  */
/*   device that have a higher precedence will steal the channel from us.*/
/* ioa_Request.io_Command is the command field for I/O.                  */
/* ioa_Request.io_Flags is used for the I/O flags.                       */
/* ioa_AllocKey will be filled in by the audio device if the allocation */
/*   succeeds. We must use the key it gives for all other commands sent.*/
/* ioa_Data is a pointer to the array listing the channels we want.     */
/* ioa_Length tells how long our list of channels is.                   */
/*----------------------------------------------------------------------*/
AudioIO->ioa_Request.io_Message.mn_ReplyPort   = AudioMP;
AudioIO->ioa_Request.io_Message.mn_Node.ln_Pri = 0;
AudioIO->ioa_Request.io_Command                = ADCMD_ALLOCATE;
AudioIO->ioa_Request.io_Flags                  = ADIOF_NOWAIT;
AudioIO->ioa_AllocKey                          = 0;
AudioIO->ioa_Data                              = whichannel;
AudioIO->ioa_Length                            = sizeof(whichannel);
printf("I/O block initialized for channel allocation...\n");

/*-----------------------------------------------*/
/* Open the audio device and allocate a channel  */
/*-----------------------------------------------*/
device = OpenDevice(AUDIONAME,0L, (struct IORequest *) AudioIO ,0L);
if (device != 0)
    goto killaudio;
printf("%s opened, channel allocated...\n",AUDIONAME);

/*----------------------------------------------*/
/* Create a very simple audio sample in memory. */
/* The sample must be CHIP RAM                  */
/*----------------------------------------------*/
waveptr = (BYTE *)AllocMem( samples , MEMF_CHIP|MEMF_PUBLIC);
if (waveptr == 0)
    goto killaudio;
waveptr[0] =  127;
waveptr[1] = -127;
printf("Wave data ready...\n");

/*------------------------------------------------------------*/
/* Set up audio I/O block to play a sample using CMD_WRITE.   */
/* The io_Flags are set to ADIOF_PERVOL so we can set the     */
/*    period (speed) and volume with the our sample;          */
/* ioa_Data points to the sample; ioa_Length gives the length */
/* ioa_Cycles tells how many times to repeat the sample       */
/* If you want to play the sample at a given sampling rate,   */
/* set ioa_Period = clock/(given sampling rate)               */
/*------------------------------------------------------------*/
AudioIO->ioa_Request.io_Message.mn_ReplyPort =AudioMP;
AudioIO->ioa_Request.io_Command          =CMD_WRITE;
AudioIO->ioa_Request.io_Flags            =ADIOF_PERVOL;
AudioIO->ioa_Data                        =(BYTE *)waveptr;
AudioIO->ioa_Length                      =samples;
AudioIO->ioa_Period                      =clock*samcyc/(samples*frequency);
AudioIO->ioa_Volume                      =64;
AudioIO->ioa_Cycles                      =frequency*duration/samcyc;
printf("I/O block initialized to play tone...\n");

/*-------------------------------------------------------*/
/* Send the command to start a sound using BeginIO()     */
/* Go to sleep and wait for the sound to finish with     */
/* WaitPort().  When we wake-up we have to get the reply */
/*-------------------------------------------------------*/
printf("Starting tone now...\n");
BeginIO((struct IORequest *) AudioIO );
WaitPort(AudioMP);
AudioMSG = GetMsg(AudioMP);

printf("Sound finished...\n");

killaudio:

printf("Killing audio device...\n");
if (waveptr != 0)
    FreeMem(waveptr, 2);
if (device == 0)
    CloseDevice( (struct IORequest *) AudioIO );
if (AudioMP != 0)
    DeletePort(AudioMP);
if (AudioIO != 0)
    FreeMem( AudioIO,sizeof(struct IOAudio) );
}


Devices/Dev_examples/Audio_8SVX.c

/*
 * Audio_8SVX.c
 *
 * 8SVX example - double buffers >128K samples
 *
 * Compile with SAS C 5.10  lc -b1 -cfistq -v -y -L
 *
 * Run from CLI only
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <devices/audio.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <graphics/gfxbase.h>
#include <iff/iff.h>
#include <iff/8svx.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/dos_protos.h>
#include <clib/graphics_protos.h>

#include <stdlib.h>
#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }     /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

#define VHDR MakeID('V','H','D','R')
#define BODY MakeID('B','O','D','Y')
#define MY8S MakeID('8','S','V','X')

void              kill8svx(char *);
void              kill8(void);

/*--------------------*/              /* These globals are needed */
/*   G L O B A L S    */              /* by the clean up routines */
/*--------------------*/
struct IOAudio     *AIOptr1,          /* Pointers to Audio IOBs      */
                   *AIOptr2,
                   *Aptr;
struct Message     *msg;              /* Msg, port and device for    */
struct MsgPort     *port,             /* driving audio               */
                   *port1,*port2;
       ULONG        device;
       UBYTE       *sbase,*fbase;     /* For sample memory allocation */
       ULONG        fsize,ssize;      /* and freeing                  */

struct FileHandle  *v8handle;
       UBYTE        chan1[]  = {  1 };/* Audio channel allocation arrays */
       UBYTE        chan2[]  = {  2 };
       UBYTE        chan3[]  = {  4 };
       UBYTE        chan4[]  = {  8 };
       UBYTE       *chans[] = {chan1,chan2,chan3,chan4};

       BYTE         oldpri,c;         /* Stuff for bumping priority */

struct Task        *mt=0L;
struct GfxBase     *GfxBase = NULL;

/*-----------*/
/*  M A I N  */
/*-----------*/

void main(int argc,char **argv)
{

/*-------------*/
/* L O C A L S */
/*-------------*/

       char         *fname;               /* File name and data pointer*/
       UBYTE        *p8data;              /* for file read.            */
       ULONG         clock;               /* Clock constant            */
       ULONG         length[2];           /* Sample lengths            */
       BYTE          iobuffer[8],         /* Buffer for 8SVX header    */
                    *psample[2];          /* Sample pointers           */
       Chunk        *p8Chunk;             /* Pointers for 8SVX parsing */
       Voice8Header *pVoice8Header;
       ULONG         y,rd8count,speed;    /* Counters, sampling speed  */
       ULONG         wakebit;             /* A wakeup mask             */

/*-------------*/
/*   C O D E   */
/*-------------*/

/*------------------------------*/
/* Check Arguments, Initialize  */
/*------------------------------*/

fbase=0L;
sbase=0L;
AIOptr1=0L;
AIOptr2=0L;
port=0L;
port1=0L;
port2=0L;
v8handle=0L;
device=1L;

if (argc < 2)
    {
    kill8svx("No file name given.\n");
    exit(1L);
    }
fname=argv[1];

/*---------------------------*/
/* Initialize Clock Constant */
/*---------------------------*/

GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0L);
if (GfxBase==0L)
    {
    puts("Can't open graphics library\n");
    exit(1L);
    }

if (GfxBase->DisplayFlags & PAL)
    clock=3546895L;        /* PAL clock */
else
    clock=3579545L;        /* NTSC clock */

if (GfxBase)
    CloseLibrary( (struct Library *) GfxBase);

/*---------------*/
/* Open the File */
/*---------------*/

v8handle= (struct FileHandle *) Open(fname,MODE_OLDFILE);
if (v8handle==0)
    {
    kill8svx("Can't open 8SVX file.\n");
    exit(1L);
    }

/*-------------------------------------------*/
/* Read the 1st 8 Bytes of the File for Size */
/*-------------------------------------------*/
rd8count=Read((BPTR)v8handle,iobuffer,8L);
if (rd8count==-1)
    {
    kill8svx ("Read error.\n");
    exit(1L);
    }

if (rd8count<8)
    {
    kill8svx ("Not an IFF 8SVX file, too short\n");
    exit(1L);
    }

/*-----------------*/
/* Evaluate Header */
/*-----------------*/
p8Chunk=(Chunk *)iobuffer;
if (p8Chunk->ckID != FORM )
    {
    kill8svx("Not an IFF FORM.\n");
    exit(1L);
    }

/*--------------------------------------------*/
/* Allocate Memory for File and Read it in.   */
/*--------------------------------------------*/
fbase= (UBYTE *)AllocMem(fsize=p8Chunk->ckSize , MEMF_PUBLIC|MEMF_CLEAR);
if (fbase==0)
    {
    kill8svx("No memory for read.\n");
    exit(1L);
    }

p8data=fbase;

rd8count=Read((BPTR)v8handle,p8data,p8Chunk->ckSize);
if (rd8count==-1)
    {
    kill8svx ("Read error.\n");
    exit(1L);
    }

if (rd8count<p8Chunk->ckSize)
    {
    kill8svx ("Malformed IFF, too short.\n");
    exit(1L);
    }

/*-------------------*/
/* Evaluate IFF Type */
/*-------------------*/
if (MakeID( *p8data, *(p8data+1) , *(p8data+2) , *(p8data+3) ) != MY8S )
    {
    kill8svx("Not an IFF 8SVX file.\n");
    exit(1L);
    }

/*----------------------*/
/* Evaluate 8SVX Chunks */
/*----------------------*/
p8data=p8data+4;

while( p8data < fbase+fsize )
  {
  p8Chunk=(Chunk *)p8data;

  switch(p8Chunk->ckID)
    {
    case VHDR:
      /*------------------------------------------------*/
      /* Get a pointer to the 8SVX header for later use */
      /*------------------------------------------------*/
      pVoice8Header=(Voice8Header *)(p8data+8L);
      break;

    case BODY:
      /*-------------------------------------------------*/
      /* Create pointers to 1-shot and continuous parts  */
      /* for the top octave and get length. Store them.  */
      /*-------------------------------------------------*/
        psample[0] = (BYTE *)(p8data + 8L);
        psample[1] = psample[0] + pVoice8Header->oneShotHiSamples;
        length[0] = (ULONG)pVoice8Header->oneShotHiSamples;
        length[1] = (ULONG)pVoice8Header->repeatHiSamples;
        break;

    default:
      break;
    }
    /* end switch */

  p8data = p8data + 8L + p8Chunk->ckSize;

  if (p8Chunk->ckSize&1L == 1)
      p8data++;
  }

/* Play either the one-shot or continuous, not both */
if (length[0]==0)
    y=1;
else
    y=0;

/*---------------------------------------*/
/* Allocate chip memory for samples and  */
/* copy from read buffer to chip memory. */
/*---------------------------------------*/
if (length[y]<=102400)
    ssize=length[y];
else
    ssize=102400;

sbase=(UBYTE *)AllocMem( ssize , MEMF_CHIP | MEMF_CLEAR);
if (sbase==0)
    {
    kill8svx("No chip memory.\n");
    exit(1L);
    }

CopyMem(psample[y],sbase,ssize);
psample[y]+=ssize;

/*----------------------------------*/
/* Calculate playback sampling rate */
/*----------------------------------*/
speed =  clock / pVoice8Header->samplesPerSec;

/*-------------------*/
/* Bump our priority */
/*-------------------*/
mt=FindTask(NULL);
oldpri=SetTaskPri(mt,21);

/*--------------------------------*/
/* Allocate two audio I/O blocks  */
/*--------------------------------*/
AIOptr1=(struct IOAudio *)
      AllocMem( sizeof(struct IOAudio),MEMF_PUBLIC|MEMF_CLEAR);
if (AIOptr1==0)
    {
    kill8svx("No IO memory\n");
    exit(1L);
    }

AIOptr2=(struct IOAudio *)
      AllocMem( sizeof(struct IOAudio),MEMF_PUBLIC|MEMF_CLEAR);
if (AIOptr2==0)
    {
    kill8svx("No IO memory\n");
    exit(1L);
    }

/*----------------------*/
/* Make two reply ports */
/*----------------------*/

port1=CreatePort(0,0);
if (port1==0)
    {
    kill8svx("No port\n");
    exit(1L);
    }

port2=CreatePort(0,0);
if (port2==0)
    {
    kill8svx("No port\n");
    exit(1L);
    }

c=0;
while(device!=0 && c<4)
  {
  /*---------------------------------------*/
  /* Set up audio I/O block for channel    */
  /* allocation and Open the audio device  */
  /*---------------------------------------*/
  AIOptr1->ioa_Request.io_Message.mn_ReplyPort   = port1;
  AIOptr1->ioa_Request.io_Message.mn_Node.ln_Pri = 127;  /* No stealing! */
  AIOptr1->ioa_AllocKey                          = 0;
  AIOptr1->ioa_Data                              = chans[c];
  AIOptr1->ioa_Length                            = 1;

  device=OpenDevice(AUDIONAME,0L,(struct IORequest *)AIOptr1,0L);
  c++;
  }

if (device!=0)
    {
    kill8svx("No channel\n");
    exit(1L);
    }

/*-------------------------------------------*/
/* Set Up Audio IO Blocks for Sample Playing */
/*-------------------------------------------*/

AIOptr1->ioa_Request.io_Command   =CMD_WRITE;
AIOptr1->ioa_Request.io_Flags     =ADIOF_PERVOL;

/*--------*/
/* Volume */
/*--------*/

AIOptr1->ioa_Volume=60;

/*---------------*/
/* Period/Cycles */
/*---------------*/

AIOptr1->ioa_Period =(UWORD)speed;
AIOptr1->ioa_Cycles =1;

*AIOptr2 = *AIOptr1;   /* Make sure we have the same allocation keys, */
                       /* same channels selected and same flags       */
                       /* (but different ports...)                    */

AIOptr1->ioa_Request.io_Message.mn_ReplyPort   = port1;
AIOptr2->ioa_Request.io_Message.mn_ReplyPort   = port2;

/*--------*/
/*  Data  */
/*--------*/

AIOptr1->ioa_Data            =(UBYTE *)sbase;
AIOptr2->ioa_Data            =(UBYTE *)sbase + 51200;

/*-----------------*/
/*  Run the sample */
/*-----------------*/

if (length[y]<=102400)
    {
    AIOptr1->ioa_Length=length[y];         /* No double buffering needed */
    BeginIO((struct IORequest *)AIOptr1);  /* Begin the sample, wait for */
    wakebit=0L;                            /* it to finish, then quit.   */
    wakebit=Wait(1 << port1->mp_SigBit);
    while((msg=GetMsg(port1))==0){};
    }
else
    {
    length[y]-=102400;                    /* It's a real long sample so  */
    AIOptr1->ioa_Length=51200L;           /* double buffering is needed  */
    AIOptr2->ioa_Length=51200L;
    BeginIO((struct IORequest *)AIOptr1); /* Start up the first 2 blocks */
    BeginIO((struct IORequest *)AIOptr2);
    Aptr=AIOptr1;
    port=port1;                           /* Set the switch... */

    while(length[y]>0)
      {                                   /* Wait() for one IO to finish */
      wakebit=Wait(1 << port->mp_SigBit); /* reuse the IO block & queue  */
      while((msg=GetMsg(port))==0){};     /* it up again while the 2nd IO*/
                                          /* block plays.Switch & repeat */
      /* Set length of next IO block */
      if (length[y]<=51200)
          Aptr->ioa_Length=length[y];
      else
          Aptr->ioa_Length=51200L;

      /* Copy sample fragment from read buffer to chip memory */
      CopyMem(psample[y],Aptr->ioa_Data,Aptr->ioa_Length);

      /* Adjust size and pointer of read buffer*/
      length[y]-=Aptr->ioa_Length;
      psample[y]+=51200;

      BeginIO((struct IORequest *)Aptr);

      if (Aptr==AIOptr1)
          {
          Aptr=AIOptr2;                /* This logic handles switching  */
          port=port2;                  /* between the 2 IO blocks and   */
          }                            /* the 2 ports we are using.     */
      else
          {
          Aptr=AIOptr1;
          port=port1;
          }
      }

    /*-------------------------------------------------*/
    /* OK we are at the end of the sample so just wait */
    /* for the last two parts of the sample to finish  */
    /*-------------------------------------------------*/
    wakebit=Wait(1 << port->mp_SigBit);
    while((msg=GetMsg(port))==0){};
    if (Aptr==AIOptr1)
        {
        Aptr=AIOptr2;                  /* This logic handles switching  */
        port=port2;                    /* between the 2 IO blocks and   */
        }                              /* the 2 ports we are using.     */
    else
        {
        Aptr=AIOptr1;
        port=port1;
        }
    wakebit=Wait(1 << port->mp_SigBit);
    while((msg=GetMsg(port))==0){};
    }

kill8();
exit(0L);
}

/*----------------*/
/* Abort the Read */
/*----------------*/
void
kill8svx(kill8svxstring)
char *kill8svxstring;
{
puts(kill8svxstring);
kill8();
}

/*-------------------------*/
/* Return system resources */
/*-------------------------*/
void kill8()
{
if (device ==0)
    CloseDevice((struct IORequest *)AIOptr1);
if (port1  !=0)
    DeletePort(port1);
if (port2  !=0)
    DeletePort(port2);
if (AIOptr1!=0)
    FreeMem( AIOptr1,sizeof(struct IOAudio) );
if (AIOptr2!=0)
    FreeMem( AIOptr2,sizeof(struct IOAudio) );

if (mt!=0)
    SetTaskPri(mt,oldpri);

if (sbase !=0)
    FreeMem (sbase, ssize);
if (fbase !=0)
    FreeMem(fbase,fsize);
if (v8handle!=0)
    Close((BPTR)v8handle);
}


Devices/Dev_examples/Printer_Data.c

/*
 * Printer_Data.c
 *
 * Example getting driver specifics.
 *
 * Compiled with SAS C 5.10a. lc -cfist -v -L Printer_Data
 *
 * Run from CLI only
 */

#include <exec/types.h>
#include <exec/ports.h>
#include <devices/printer.h>
#include <devices/prtbase.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/alib_stdio_protos.h>

union printerIO
{
    struct IOStdReq    ios;
    struct IODRPReq    iodrp;
    struct IOPrtCmdReq iopc;
};

VOID main(VOID);

VOID main(VOID)
{
struct MsgPort  *PrinterMP;
union printerIO *PIO;
struct PrinterData *PD;
struct PrinterExtendedData *PED;

/* Create non-public messageport. Could use CreateMsgPort() for this, that's
 * V37 specific however.
 */
if (PrinterMP = (struct MsgPort *)CreatePort(0,0))
    {
    /* Allocate printerIO union */
    if (PIO = (union printerIO *)CreateExtIO(PrinterMP, sizeof(union printerIO)))
        {
        /* Open the printer.device */
        if (!(OpenDevice("printer.device",0,(struct IORequest *)PIO,0)))
            {

            /* Now that we've got the device opened, let's see what we've got.
             * First, get a pointer to the printer data.
             */
            PD = (struct PrinterData *)PIO->iodrp.io_Device;
            /* And a pointer to the extended data */
            PED = (struct PrinterExtendedData *)&PD->pd_SegmentData->ps_PED;

            /* See the <devices/prtbase.h> include file for more details on
             * the PrinterData and PrinterExtendedData structures.
             */
            printf("Printername: '%s', Version: %ld, Revision: %ld\n",
            PED->ped_PrinterName, PD->pd_SegmentData->ps_Version,
            PD->pd_SegmentData->ps_Revision);

            printf("PrinterClass: 0x%lx, ColorClass: 0x%lx\n",
            PED->ped_PrinterClass, PED->ped_ColorClass);

            printf("MaxColumns: %ld, NumCharSets: %ld, NumRows: %ld\n",
                PED->ped_MaxColumns, PED->ped_NumCharSets,PED->ped_NumRows);

            printf("MaxXDots: %ld, MaxYDots: %ld, XDotsInch: %ld, YDotsInch: %ld\n",
                PED->ped_MaxXDots, PED->ped_MaxYDots, PED->ped_XDotsInch, PED->ped_YDotsInch);

            CloseDevice((struct IORequest *)PIO);
            }
         else
             printf("Can't open printer.device\n");
        DeleteExtIO((struct IORequest *)PIO);
        }
    else
        printf("Can't CreateExtIO\n");
    DeletePort((struct MsgPort *)PrinterMP);
    }
else
   printf("Can't CreatePort\n");
}


Devices/Dev_examples/Set_Prefs.c

/*
 * Set_Prefs.c
 *
 * This example changes the printer device's COPY of preferences (as obtained
 * when the printer device was opened by a task via OpenDevice()).  Note that
 * it only changes the printer device's copy of preferences, not the preferences
 * as set by the user via the preference editor(s).
 *
 * Compile with SAS C 5.10: LC -b1 -cfistq -v -y -L
 *
 * Run from CLI only
 */

#include <exec/types.h>
#include <devices/printer.h>
#include <devices/prtbase.h>
#include <intuition/intuition.h>
#include <intuition/screens.h>
#include <intuition/preferences.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/alib_stdio_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>

struct Library *IntuitionBase;
struct Library *GfxBase;

union printerIO
{
    struct IOStdReq    ios;
    struct IODRPReq    iodrp;
    struct IOPrtCmdReq iopc;
};

struct MsgPort *PrintMP;
union printerIO *pio;

char message[] = "\
This is a test message to see how this looks when printed\n\
using various printer settings.\n\n";

VOID main(VOID);
VOID DoPrinter(VOID);
int DoTest(VOID);

VOID main(VOID)
{

if (IntuitionBase = OpenLibrary("intuition.library",0L))
    {
    if (GfxBase = OpenLibrary("graphics.library",0L))
        {
        DoPrinter();
        CloseLibrary(GfxBase);
        }

    CloseLibrary(IntuitionBase);
    }
}

VOID DoPrinter(VOID)
{

if (PrintMP = CreatePort(0L,0L))
    {
    if (pio = (union printerIO *)CreateExtIO(PrintMP,sizeof(union printerIO)))
        {
        if (!(OpenDevice("printer.device",0L,(struct IORequest *)pio,0L)))
            {
            DoTest();
            CloseDevice((struct IORequest *)pio);
            }
        DeleteExtIO((struct IORequest *)pio);
        }
    DeletePort(PrintMP);
    }
}

DoTest(VOID)
{
struct PrinterData *PD;
struct Preferences *prefs;
UWORD newpitch;
UWORD newspacing;

/* Send INIT sequence - make sure printer is inited - some      */
/* printers may eject the current page if necessary when inited */

pio->ios.io_Command = CMD_WRITE;
pio->ios.io_Data = "\033#1";
pio->ios.io_Length = -1L;

if (DoIO((struct IORequest *)pio))
    return(FALSE);

/* Print some text using the default settings from Preferences */

pio->ios.io_Command = CMD_WRITE;
pio->ios.io_Data = message;
pio->ios.io_Length = -1L;

if(DoIO((struct IORequest *)pio))
   return(FALSE);

/* Now try changing some settings
 * Note that we could just as well send the printer.device escape
 * sequences to change these settings, but this is an example program.
 */

/* Get pointer to printer data  */
PD = (struct PrinterData *) pio->ios.io_Device;

/* Get pointer to printer's copy of preferences
 * Note that the printer.device makes a copy of preferences when
 * the printer.device is successfully opened via OpenDevice(),
 * so we are only going to change the COPY of preferences
 */

prefs = &PD->pd_Preferences;

/* Change a couple of settings                          */

if (prefs->PrintSpacing == SIX_LPI)
    newspacing = EIGHT_LPI;
if (prefs->PrintSpacing == EIGHT_LPI)
    newspacing = SIX_LPI;

if (prefs->PrintPitch == PICA)
    newpitch = ELITE;
if (prefs->PrintPitch == ELITE)
    newpitch = FINE;
if (prefs->PrintPitch == FINE)
    newpitch = PICA;

/* And let's change the margins too for this example */

prefs->PrintLeftMargin = 20;
prefs->PrintRightMargin = 40;

prefs->PrintPitch = newpitch;
prefs->PrintSpacing = newspacing;

/* Send INIT sequence so that these settings are used */

pio->ios.io_Command = CMD_WRITE;
pio->ios.io_Data = "\033#1";
pio->ios.io_Length = -1L;

if(DoIO((struct IORequest *)pio))
   return(FALSE);

pio->ios.io_Command = CMD_WRITE;
pio->ios.io_Data = message;
pio->ios.io_Length = -1L;

if(DoIO((struct IORequest *)pio))
   return(FALSE);

/* Send FormFeed so page is ejected  */

pio->ios.io_Command = CMD_WRITE;
pio->ios.io_Data = "\014";
pio->ios.io_Length = -1L;

if(DoIO((struct IORequest *)pio))
   return(FALSE);

return(TRUE);
}


Devices/Dev_examples/Demo_Dump.c

/* Demo_Dump.c
 *
 * Simple example of dumping a rastport to the printer, changing
 * printer preferences programmatically and handling error codes.
 *
 * Compile with SAS C 5.10a. lc -cfist -v -L Demo_Dump
 *
 * Requires Kickstart V37
 * Run from CLI only
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/ports.h>
#include <devices/printer.h>
#include <devices/prtbase.h>
#include <dos/dos.h>
#include <intuition/intuition.h>
#include <intuition/screens.h>
#include <graphics/displayinfo.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/alib_stdio_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;

union printerIO
{
    struct IOStdReq    ios;
    struct IODRPReq    iodrp;
    struct IOPrtCmdReq iopc;
};

struct EasyStruct reqES =
{
    sizeof(struct EasyStruct), 0, "DemoDump",
    "%s",
    NULL,
};

/* Possible printer.device and I/O errors */
static UBYTE *ErrorText[] =
{
    "PDERR_NOERR",
    "PDERR_CANCEL",
    "PDERR_NOTGRAPHICS",
    "INVERTHAM",                /* OBSOLETE */
    "BADDIMENSION",
    "DIMENSIONOVFLOW",  /* OBSOLETE */
    "INTERNALMEMORY",
    "BUFFERMEMORY",
    /* IO_ERRs */
    "IOERR_OPENFAIL",
    "IOERR_ABORTED",
    "IOERR_NOCMD",
    "IOERR_BADLENGTH"
};

/* Requester Action text */
static UBYTE *ActionText[] =
{
    "OK|CANCEL",
    "Continue",
    "Abort",
};

#define OKCANCELTEXT 0
#define CONTINUETEXT 1
#define ABORTTEXT    2

VOID main(VOID);

VOID main(VOID)
{
struct MsgPort  *PrinterMP;
union printerIO *PIO;
struct PrinterData *PD;
struct PrinterExtendedData *PED;
struct Screen *pubscreen;
struct ViewPort *vp;
STRPTR textbuffer;
LONG modeID, i,j;
ULONG dcol[5], drow[5];
ULONG signal;

/* Fails silently if not V37 or greater. Nice thing to do would be to put up
 * a V33 requester of course.
 */

/* Set up once */
reqES.es_GadgetFormat = ActionText[CONTINUETEXT];

if (IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 37))
  {
  /* Using graphics.library to get the displaymodeID of the public screen,
   * which we'll pass to the printer.device.
   */
  if (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 37))
    {
    if (textbuffer = (STRPTR)AllocMem(256, MEMF_CLEAR))
      {
      /* Create non-public messageport. Since we depend on V37 already, we'll
       * use the new Exec function.
       */
      if (PrinterMP = CreateMsgPort())
        {
        /* Allocate printerIO union */
        if (PIO = (union printerIO *)CreateExtIO(PrinterMP, sizeof(union printerIO)))
          {
          /* Open the printer.device */
          if (!(OpenDevice("printer.device",0,(struct IORequest *)PIO,0)))
            {
            /* Yahoo, we've got it.
             * We'll use the PrinterData structure to get to the the printer
             * preferences later on. The PrinterExtendedData structure will
             * reflect the changes we'll make to the preferences.
             */

            PD = (struct PrinterData *)PIO->iodrp.io_Device;
            PED = (struct PrinterExtendedData *)&PD->pd_SegmentData->ps_PED;

            /* We're all set. We'll grab the default public screen (normally
             * Workbench) and see what happens when we dump it with different
             * densities.
             * Next we'll put up a nice requester for the user and ask if
             * (s)he wants to actually do the dump.
             */

            if (pubscreen = LockPubScreen(NULL))
              {
              vp = &(pubscreen->ViewPort);
              /* Use graphics.library/GetVPModeID() to get the ModeID of the screen. */
              if ((modeID = GetVPModeID(vp)) != INVALID_ID)
                {
                /* Seems we got a valid ModeID for the default public screen (surprise).
                 * Do some fake screen dumps with densities 1, 3, 5 and 7. Depending on
                 * the driver, one or more may be the same.
                 */

                /* Fill in those parts of the IODRPRequest which won't change */
                PIO->iodrp.io_Command = PRD_DUMPRPORT;
                PIO->iodrp.io_RastPort = &(pubscreen->RastPort);
                PIO->iodrp.io_ColorMap = vp->ColorMap;
                PIO->iodrp.io_Modes = modeID;
                PIO->iodrp.io_SrcX = pubscreen->LeftEdge;
                PIO->iodrp.io_SrcY = pubscreen->TopEdge;
                PIO->iodrp.io_SrcWidth = pubscreen->Width;
                PIO->iodrp.io_SrcHeight = pubscreen->Height;

                for (i = 1,j=0; i < 8; i+=2,j++)
                  {
                  /* On return these will contain the actual dump dimension */
                  PIO->iodrp.io_DestCols = 0;
                  PIO->iodrp.io_DestRows = 0;
                  /* We'll simply change our local copy of the
                   * Preferences structure. Likewise we could change
                   * all printer-related preferences.
                   */
                  PD->pd_Preferences.PrintDensity = i;
                  PIO->iodrp.io_Special = SPECIAL_NOPRINT|SPECIAL_ASPECT;

                  /* No need to do asynchronous I/O here */
                  DoIO((struct IORequest *)PIO);

                  if (PIO->iodrp.io_Error == 0)
                    {
                    dcol[j] = PIO->iodrp.io_DestCols;
                    drow[j] = PIO->iodrp.io_DestRows;
                    }
                  else
                    {
                    j = PIO->iodrp.io_Error;
                    if (j < 0)
                      j = j * -1 + 7;

                    sprintf(textbuffer, "Error: %s\n", ErrorText[j]);
                    reqES.es_GadgetFormat = ActionText[CONTINUETEXT];
                    EasyRequest(NULL, &reqES, NULL, textbuffer);
                    break;
                    }
                  }
                /* Simple, lazy way to check if we encountered any problems */
                if (i == 9)
                  {
                  /* Build an 'intelligent' requester */
                  sprintf(textbuffer,
                    "%s: %5ld x %5ld\n%s: %5ld x %5ld\n%s: %5ld x%5ld\n%s: %5ld x %5ld\n\n%s",
                    "Density 1", dcol[0], drow[0],
                    "Density 3", dcol[1], drow[1],
                    "Density 5", dcol[2], drow[2],
                    "Density 7", dcol[3], drow[3],
                    "Print screen at highest density?");
                  reqES.es_GadgetFormat = ActionText[OKCANCELTEXT];

                  /* Obviously the choice presented to the user here is a very
                   * simple one. To print or not to print. In a real life
                   * application, a requester could be presented, inviting
                   * the user to select density, aspect, dithering etc.
                   * The fun part is, of course, that the user can, to a certain
                   * degree, be informed about the effects of her/his selections.
                   */
                  if (EasyRequest(NULL, &reqES, NULL, textbuffer))
                    {
                    /* We've still got the density preference set to the highest
                     * density, so no need to change that.
                     * All we do here is re-initialize io_DestCols/Rows and remove
                     * the SPECIAL_NOPRINT flag from io_Special.
                     */
                    PIO->iodrp.io_DestCols = 0;
                    PIO->iodrp.io_DestRows = 0;
                    PIO->iodrp.io_Special &= ~SPECIAL_NOPRINT;

                    /* Always give the user a change to abort.
                     * So we'll use SendIO(), instead of DoIO(), to be asynch and
                     * catch a possible user request to abort printing. Normally,
                     * the user would be presented with a nice, fat, ABORT requester.
                     * However, since this example doesn't even open a window, and is
                     * basically a 'GraphicDumpDefaultPubscreen' equivalent, we'll use
                     * CTRL-C as the user-abort. Besides that, got to keep it short.
                     */
                    SendIO((struct IORequest *)PIO);

                    /* Now Wait() for either a user signal (CTRL-C) or a signal from
                     * the printer.device
                     */
                    signal = Wait(1 << PrinterMP->mp_SigBit | SIGBREAKF_CTRL_C);

                    if (signal & SIGBREAKF_CTRL_C)
                      {
                      /* User wants to abort */
                      AbortIO((struct IORequest *)PIO);
                      WaitIO((struct IORequest *)PIO);
                      }

                    if (signal & (1 << PrinterMP->mp_SigBit))
                      {
                      /* printer is either ready or an error has occurred */
                      /* Remove any messages */
                      while(GetMsg(PrinterMP));
                      }
                    /* Check for errors (in this case we count user-abort as an error) */
                    if (PIO->iodrp.io_Error != 0)
                      {
                      j = PIO->iodrp.io_Error;
                      if (j < 0)
                        j = j * -1 + 7;
                      sprintf(textbuffer, "Error: %s\n", ErrorText[j]);
                      reqES.es_GadgetFormat = ActionText[CONTINUETEXT];
                      EasyRequest(NULL, &reqES, NULL, textbuffer);
                      }

                    } /* else user doesn't want to print */
                  }
                }
              else
                /* Say what? */
                EasyRequest(NULL, &reqES, NULL, "Invalid ModeID\n");
              UnlockPubScreen(NULL, pubscreen);
              }
            else
              EasyRequest(NULL, &reqES, NULL, "Can't lock Public Screen\n");

            CloseDevice((struct IORequest *)PIO);
            }
          else
            EasyRequest(NULL, &reqES, NULL, "Can't open printer.device\n");

          DeleteExtIO((struct IORequest *)PIO);
          }
        else
          EasyRequest(NULL, &reqES, NULL, "Can't create Extented I/O Request\n");
        DeleteMsgPort(PrinterMP);
        }
      else
        EasyRequest(NULL, &reqES, NULL, "Can't create Message port\n");
      /* else Out of memory? 256 BYTES? */
      FreeMem(textbuffer,256);
      }
    CloseLibrary(GfxBase);
    } /* else MAJOR confusion */
  CloseLibrary(IntuitionBase);
  }
}


Devices/Dev_examples/printertag.asm

**********************************************************************
*
*       printer device dependent code tag
*
*
*
**********************************************************************

        SECTION         printer

*------ Included Files -----------------------------------------------

        INCLUDE         "exec/types.i"
        INCLUDE         "exec/nodes.i"
        INCLUDE         "exec/strings.i"

        INCLUDE         "epsonX_rev.i"  ; contains VERSION & REVISION

        INCLUDE         "devices/prtbase.i"

*------ Imported Names -----------------------------------------------

        XREF            _Init
        XREF            _Expunge
        XREF            _Open
        XREF            _Close
        XREF            _CommandTable
        XREF            _PrinterSegmentData
        XREF            _DoSpecial
        XREF            _Render
        XREF            _ExtendedCharTable

*------ Exported Names -----------------------------------------------

        XDEF            _PEDData

**********************************************************************
        ; in case anyone tries to execute this
        MOVEQ   #0,D0
        RTS

        DC.W    VERSION        ; must be at least 35 (V1.3 and up)
        DC.W    REVISION       ; your own revision number
_PEDData:
        DC.L    printerName    ; pointer to the printer name
        DC.L    _Init          ; pointer to the initialization code
        DC.L    _Expunge       ; pointer to the expunge code
        DC.L    _Open          ; pointer to the open code
        DC.L    _Close         ; pointer to the close code
        DC.B    PPC_COLORGFX   ; PrinterClass
        DC.B    PCC_YMCB       ; ColorClass
        DC.B    136            ; MaxColumns
        DC.B    10             ; NumCharSets
        DC.W    8              ; NumRows
        DC.L    1632           ; MaxXDots
        DC.L    0              ; MaxYDots
        DC.W    120            ; XDotsInch
        DC.W    72             ; YDotsInch
        DC.L    _CommandTable  ; pointer to Command strings
        DC.L    _DoSpecial     ; pointer to Command Code function
        DC.L    _Render        ; pointer to Graphics Render function
        DC.L    30             ; Timeout

        DC.L    _ExtendedCharTable  ; pointer to 8BitChar table

        DS.L    1              ; Flag for PrintMode (reserve space)
        DC.L    0              ; pointer to ConvFunc (char conversion function)

printerName:
        DC.B    'EpsonX'
        DC.B    0
        END


FORM Specs from the Original EA Document / FTXT IFF Formatted Text

Date:	November 15, 1985 (Updated Oct, 1988 Commodore-Amiga, Inc.)
From:	Steve Shaw and Jerry Morrison, Electronic Arts
        and Bob "Kodiak" Burns, Commodore-Amiga
Status:	Adopted

 Introduction
 Standard Data and Property Chunks
 FTXT Stripper
 Appendix A: Character Code Table
 Appendix B: FTXT Example
 Appendix C: ISO/ANSI Control Sequences


FTXT IFF Formatted Text / Introduction

This memo is the IFF supplement for FORM FTXT.  An FTXT is an IFF "data
section" or "FORM type" - which can be an IFF file or a part of one -
containing a stream of text plus optional formatting information.
EA IFF 85 is Electronic Arts' standard for interchange format files.
(See the IFF reference.)

An FTXT is an archival and interchange representation designed for three
uses. The simplest use is for a "console device" or "glass teletype" (the
minimal 2-D text layout means): a stream of "graphic" ("printable")
characters plus positioning characters "space" ("SP") and line terminator
("LF").  This is not intended for cursor movements on a screen although it
does not conflict with standard cursor-moving characters.  The second use
is text that has explicit formatting information (or "looks") such as font
family and size, typeface, etc.  The third use is as the lowest layer of a
structured document that also has "inherited" styles to implicitly control
character looks.  For that use, FORMs FTXT would be embedded within a
future document FORM type.  The beauty of FTXT is that these three uses
are interchangeable, that is, a program written for one purpose can read
and write the others' files.  So a word processor does not have to write a
separate plain text file to communicate with other programs.

Text is stored in one or more "CHRS" chunks inside an FTXT.  Each CHRS
contains a stream of 8-bit text compatible with ISO and ANSI data
interchange standards.  FTXT uses just the central character set from the
ISO/ANSI standards.  (These two standards are henceforth called "ISO/ANSI"
as in "see the ISO/ANSI reference".)

Since it's possible to extract just the text portions from future document
FORM types, programs can exchange data without having to save both plain
text and formatted text representations.

Character looks are stored as embedded control sequences within CHRS
chunks. This document specifies which class of control sequences to use:
the CSI group.  This document does not yet specify their meanings, e.g.,
which one means "turn on italic face".  Consult ISO/ANSI.

Section 2 defines the chunk types character stream "CHRS" and font
specifier "FONS".  These are the "standard" chunks.  Specialized chunks
for private or future needs can be added later.  Section 3 outlines an
FTXT reader program that strips a document down to plain unformatted text.
Appendix A is a code table for the 8-bit ISO/ANSI character set used here.
Appendix B is an example FTXT shown as a box diagram.  Appendix C is a
racetrack diagram of the syntax of ISO/ANSI control sequences.

 Reference


FTXT IFF Formatted Text / Reference

Amiga® is a registered trademark of Commodore-Amiga, Inc.
Electronic Arts(tm) is a trademark of Electronic Arts.

IFF: "EA IFF 85" Standard for Interchange Format Files describes the
underlying conventions for all IFF files.

ISO/ANSI: ISO/DIS 6429.2 and ANSI X3.64-1979.  International Organization
for Standardization (ISO) and American National Standards Institute (ANSI)
data- interchange standards.  The relevant parts of these two standards
documents are identical.  ISO standard 2022 is also relevant.


FTXT IFF Formatted / Standard Data and Property Chunks

The main contents of a FORM FTXT is in its character stream "CHRS" chunks.
Formatting property chunks may also appear.  The only formatting property
yet defined is "FONS", a font specifier.  A FORM FTXT with no CHRS
represents an empty text stream.  A FORM FTXT may contain nested IFF
FORMs, LISTs, or CAT s, although a "stripping" reader (see section 3) will
ignore them.

 Character Sets
 Control Sequences
 Data Chunk CHRS
 Property Chunk FONS
 Future Properties
 Positioning Units


Standard Data and Property Chunks / Character Set

FORM FTXT uses the core of the 8-bit character set defined by the ISO/ANSI
standards cited at the start of this document.  (See Appendix A for a
character code table.)  This character set is divided into two "graphic"
groups plus two "control" groups.  Eight of the control characters begin
ISO/ANSI standard control sequences.  (See "Control Sequences", below.)
Most control sequences and control characters are reserved for future use
and for compatibility with ISO/ANSI.  Current reader programs should skip
them.

* C0 is the group of control characters in the range NUL (hex 0) through
  hex 1F.  Of these, only LF (hex 0A) and ESC (hex 1B) are significant.
  ESC begins a control sequence.  LF is the line terminator, meaning "go
  to the first horizontal position of the next line".  All other C0
  characters are not used.  In particular, CR (hex 0D) is not recognized
  as a line terminator.

* G0 is the group of graphic characters in the range hex 20 through hex
  7F.  SP (hex 20) is the space character.  DEL (hex 7F) is the delete
  character which is not used.  The rest are the standard ASCII printable
  characters "!" (hex 21) through "~" (hex 7E).

* C1 is the group of extended control characters in the range hex 80
  through hex 9F.  Some of these begin control sequences.  The control
  sequence starting with CSI (hex 9B) is used for FTXT formatting.  All
  other control sequences and C1 control characters are unused.

* G1 is the group of extended graphic characters in the range NBSP (hex
  A0) through "ÿ" (hex FF).  It is one of the alternate graphic groups
  proposed for ISO/ANSI standardization.


Standard Data and Property Chunks / Control Sequences

Eight of the control characters begin ISO/ANSI standard "control
sequences" (or "escape sequences").  These sequences are described below
and diagramed in Appendix C.

    G0	  ::= (SP through DEL)
    G1	  ::= (NBSP through "ÿ")

    ESC-Seq	  ::= ESC (SP through "/") * ("0" through "~")
    ShiftToG2 ::= SS2 G0
    ShiftToG3 ::= SS3 G0
    CSI-Seq	  ::= CSI (SP through "?") * ("@" through "~")
    DCS-Seq   ::= (DCS | OSC | PM | APC) (SP through "~" | G1) * ST

"ESC-Seq" is the control sequence ESC (hex 1B), followed by zero or more
characters in the range SP through "/" (hex 20 through hex 2F), followed
by a character in the range "0" through "~" (hex 30 through hex 7E).
These sequences are reserved for future use and should be skipped by
current FTXT reader programs.

SS2 (hex 8E) and SS3 (hex 8F) shift the single following G0 character into
yet-to-be-defined graphic sets G2 and G3, respectively.  These sequences
should not be used until the character sets G2 and G3 are standardized.  A
reader may simply skip the SS2 or SS3 (taking the following character as a
corresponding G0 character) or replace the two-character sequence with a
character like "?" to mean "absent".

FTXT uses "CSI-Seq" control sequences to store character formatting (font
selection by number, type face, and text size) and perhaps layout
information (position and rotation).  "CSI-Seq" control sequences start
with CSI (the "control sequence introducer", hex 9B).  Syntactically, the
sequence includes zero or more characters in the range SP through "?" (hex
20 through hex 3F) and a concluding character in the range "@" through "~"
(hex 40 through hex 7E).  These sequences may be skipped by a minimal FTXT
reader, i.e., one that ignores formatting information.

Note: A future FTXT standardization document will explain the uses of
CSI-Seq sequences for setting character face (light weight vs. medium vs.
bold, italic vs. upright, height, pitch, position, and rotation).  For
now, consult the ISO/ANSI references.

"DCS-Seq" is the control sequences starting with DCS (hex 90), OSC (hex
9D), PM (hex 9E), or APC (hex 9F), followed by zero or more characters
each of which is in the range SP through "~" (hex 20 through hex 7E) or
else a G1 character, and terminated by an ST (hex 9C).  These sequences
are reserved for future use and should be skipped by current FTXT reader
programs.


Standard Data and Property Chunks / Data Chunk CHRS

A CHRS chunk contains a sequence of 8-bit characters abiding by the
ISO/ANSI standards cited at the start of this document.  This includes the
character set and control sequences as described above and summarized in
Appendix A and Appendix C.

A FORM FTXT may contain any number of CHRS chunks.  Taken together, they
represent a single stream of textual information.  That is, the contents
of CHRS chunks are effectively concatenated except that (1) each control
sequence must be completely within a single CHRS chunk, and (2) any
formatting property chunks appearing between two CHRS chunks affects the
formatting of the latter chunk's text.  Any formatting settings set by
control sequences inside a CHRS carry over to the next CHRS in the same
FORM FTXT.  All formatting properties stop at the end of the FORM since
IFF specifies that adjacent FORMs are independent of each other (although
not independent of any properties inherited from an enclosing LIST or
FORM).


Standard Data and Property Chunks / Property Chunk FONS

The optional property "FONS" holds a FontSpecifier as defined in the C
declaration below.  It assigns a font to a numbered "font register" so it
can be referenced by number within subsequent CHRS chunks.  (This function
is not provided within the ISO and ANSI standards.)  The font specifier
gives both a name and a description for the font so the recipient program
can do font substitution.

By default, CHRS text uses font 1 until it selects another font.  A
minimal text reader always uses font 1.  If font 1 hasn't been specified,
the reader may use the local system font as font 1.

typedef struct {
  UBYTE id;     /* 0 through 9 is a font id number referenced by an SGR
                   control sequence selective parameter of 10 through 19.
                   Other values are reserved for future standardization. */
  UBYTE pad1;   /* reserved for future use; store 0 here                 */
  UBYTE proportional; /* proportional font-- 0=unknown, 1=no, 2=yes      */
  UBYTE serif;  /* serif font-- 0 = unknown, 1 = no, 2 = yes             */
  char  name[]; /* A NUL-terminated string naming the preferred font.    */
  } FontSpecifier;

Fields are filed in the order shown.  The UBYTE fields are byte-packed (2
per 16-bit word).  The field pad1 is reserved for future standardization.
Programs should store 0 there for now.

The field proportional indicates if the desired font is proportional width
as opposed to fixed width.  The field serif indicates if the desired font
is serif as opposed to sans serif. [Issue: Discuss font substitution!]


Standard Data and Property Chunks / Future Properties

New optional property chunks may be defined in the future to store
additional formatting information.  They will be used to represent
formatting not encoded in standard ISO/ANSI control sequences and for
"inherited" formatting in structured documents.  Text orientation might be
one example.


Standard Data and Property Chunks / Positioning Units

Unless otherwise specified, position and size units used in FTXT
formatting properties and control sequences are in decipoints (720
decipoints/inch). This is ANSI/ISO Positioning Unit Mode (PUM) 2.  While a
metric standard might be nice, decipoints allow the existing U.S.A.
typographic units to be encoded easily, e.g., "12 points" is "120
decipoints".


FTXT IFF Formatted / FTXT Stripper

An FTXT reader program can read the text and ignore all formatting and
structural information in a document FORM that uses FORMs FTXT for the
leaf nodes.  This amounts to stripping a document down to a stream of
plain text. It would do this by skipping over all chunks except FTXT.CHRS
(CHRS chunks found inside a FORM FTXT) and within the FTXT.CHRS chunks
skipping all control characters and control sequences.  (Appendix C
diagrams this text scanner.) It may also read FTXT.FONS chunks to find a
description for font 1.

Here's a Pascal-ish program for an FTXT stripper.  Given a FORM (a
document of some kind), it scans for all FTXT.CHRS chunks.  This would
likely be applied to the first FORM in an IFF file.

  PROCEDURE ReadFORM4CHRS();    {Read an IFF FORM for FTXT.CHRS chunks.}
    BEGIN
    IF the FORM's subtype = "FTXT"
        THEN ReadFTXT4CHRS()
    ELSE WHILE something left to read in the FORM
       DO BEGIN
          read the next chunk header;
          CASE the chunk's ID OF
               "LIST", "CAT ": ReadCAT4CHRS();
               "FORM": ReadFORM4CHRS();
                OTHERWISE skip the chunk's body;
          END
       END
    END;

  {Read a LIST or CAT for all FTXT.CHRS chunks.}
  PROCEDURE ReadCAT4CHRS();
    BEGIN
    WHILE something left to read in the LIST or CAT
    DO BEGIN
       read the next chunk header;
       CASE the chunk's ID OF
             "LIST", "CAT ": ReadCAT4CHRS();
             "FORM": ReadFORM4CHRS();
             "PROP": IF we're reading a LIST AND the PROP's subtype = "FTXT"
                    THEN read the PROP for "FONS" chunks;
             OTHERWISE error--malformed IFF file;
          END
       END
    END;

  PROCEDURE ReadFTXT4CHRS();    {Read a FORM FTXT for CHRS chunks.}
    BEGIN
    WHILE something left to read in the FORM FTXT
    DO BEGIN
       read the next chunk header;
       CASE the chunk's ID OF
          "CHRS": ReadCHRS();
          "FONS": BEGIN
                   read the chunk's contents into a FontSpecifier variable;
                   IF the font specifier's id = 1
                   THEN use this font;
                  END;
            OTHERWISE skip the chunk's body;
        END
      END
    END;

  {Read an FTXT.CHRS. Skip all control sequences and unused control chars.}
  PROCEDURE ReadCHRS();
    BEGIN
    WHILE something left to read in the CHRS chunk
    DO
       CASE read the next character OF
          LF:  start a new output line;
          ESC: SkipControl([' '..'/'], ['0'..'~']);
          IN [' '..'~'], IN [NBSP..'ÿ']: output the character;
          SS2, SS3: ; {Just handle the following G0 character directly,
                      ignoring the shift to G2 or G3.}
          CSI: SkipControl([' '..'?'], ['@'..'~']);
            DCS, OSC, PM, APC: SkipControl([' '..'~'] + [NBSP..'ÿ'], [ST]);
       END
    END;

  {Skip a control sequence of the format (rSet)* (tSet), i.e., any number of
  characters in the set rSet followed by a character in the set tSet.}
  PROCEDURE SkipControl(rSet, tSet);
  VAR c: CHAR;
    BEGIN
       REPEAT c := read the next character
       UNTIL c NOT IN rSet;

       IF c NOT IN tSet
          THEN put character c back into the input stream;
    END

The following program is an optimized version of the above routines
ReadFORM4CHRS and ReadCAT4CHRS for the case where you're ignoring fonts as
well as formatting.  It takes advantage of certain facts of the IFF format
to read a document FORM and its nested FORMs, LISTs, and CAT s without a
stack. In other words, it's a hack that ignores all fonts and faces to
cheaply get to the plain text of the document.

  {Cheap scan of an IFF FORM for FTXT.CHRS chunks.}
  PROCEDURE ScanFORM4CHRS();
    BEGIN
    IF the document FORM's subtype = "FTXT"
        THEN ReadFTXT4CHRS()
    ELSE WHILE something left to read in the FORM
         DO BEGIN
            read the next chunk header;
        IF it's a group chunk (LIST, FORM, PROP, or CAT)
        THEN read its subtype ID;
        CASE the chunk's ID OF
        "LIST", "CAT ":;	{NOTE: See explanation below.*}
        "FORM": IF this FORM's subtype = "FTXT"
                THEN ReadFTXT4CHRS()
            ELSE;	{NOTE: See explanation below.*}
        OTHERWISE skip the chunk's body;
        END
    END
    END;

*Note: This implementation is subtle.  After reading a group header other
than FORM FTXT it just continues reading.  This amounts to reading all the
chunks inside that group as if they weren't nested in a group.


FTXT IFF Formatted / Appendix A: Character Code Table

This table corresponds to the ISO/DIS 6429.2 and ANSI X3.64-1979 8-bit
character set standards.  Only the core character set of those standards
is used in FTXT.

Two G1 characters aren't defined in the standards and are shown as dark
gray entries in this table.  Light gray shading denotes control
characters.  (DEL is a control character although it belongs to the
graphic group G0.)

           ISO/DIS 6429.2 and ANSI X3.64-1979 Character Code Table
           -------------------------------------------------------

        MSN (most significant nybble)
        0  1    2   3   4   5   6   7     8   9     A    B   C   D   E   F
     +--------+-------------------------+---------+------------------------
LSN 0| NUL   | SP   0   @   P   `   p  |     DCS |NBSP   °   À   Ð   à   ð
    1|       |  !   1   A   Q   a   q  |         |  ¡    ±   Á   Ñ   á   ñ
    2|       |  "   2   B   R   b   r  |         |  ¢    ²   Â   Ò   â   ò
    3|       |  #   3   C   S   c   s  |         |  £    ³   Ã   Ó   ã   ó
    4|       |  $   4   D   T   d   t  |         |  ¤        Ä   Ô   ä   ô
    5|       |  %   5   E   U   e   u  |         |  ¥    µ   Å   Õ   å   õ
    6|       |  &   6   F   V   f   v  |         |  ¦    ¶   Æ   Ö   æ   ö
    7|       |  '   7   G   W   g   w  |         |  §    ·   Ç   ×   ç   ÷
    8|       |  (   8   H   X   h   x  |         | uml   ¸   È   Ø   è   ø
    9|       |  )   9   I   Y   i   y  |         | (c)   ¹   É   Ù   é   ù
    A| LF    |  *   :   J   Z   j   z  |         |       º   Ê   Ú   ê   ú
    B|    ESC|  +   ;   K   [   k   {  |     CSI |  «    »   Ë   Û   ë   û
    C|       |  ,   <   L   \   l   |  |     ST  |  ¬    ¼   Ì   Ü   ì   ü
    D| CR    |  -   =   M   ]   m   }  |     OSC | SHY   ½   Í   Ý   í   ý
    E|       |  .   >   N   ^   n   ~  | SS2 PM  |  ®    ¾   Î   Þ   î   þ
    F|       |  /   ?   O   _   o  DEL | SS3 APC |      ¿   Ï   ß   ï   ÿ
      \__ __/ \___________ ___________/ \___ ___/ \___________ ___________/
         V                 V                 V                 V
       Control       Graphic Group        Control        Graphic Group
       Group C0            G0             Group C1            G1

NBSP is non-breaking space
SHY is soft hyphen


FTXT IFF Formatted / Appendix B. FTXT Example

Here's a box diagram for a simple example: "The quick brown fox jumped.
Four score and seven", written in a proportional serif font named "Roman".

              +-----------------------+
              |                       |
              |   'FORM'        86    |  FORM 86 FTXT
              |                       |
           -- +-----------------------+
           |  |                       |
           |  |   'FTXT'              |
           |  |                       |
           |  |  +-----------------+  |
           |  |  | 'FONS'      10  |  |  .FONS 10
           |  |  |-----------------|  |
           |  |  | 01, 00, 02, 02  |  |
           |  |  |-----------------|  |
           |  |  | Roman\0         |  |
           |  |  +-----------------+  |
           |  |                       |
           |  |  +-----------------+  |
      86  <   |  | 'CHRS'      27  |  |  .CHRS 27
     bytes |  |  |-----------------|  |
           |  |  | The quick brown |  |
           |  |  | fox jumped      |  |
           |  |  +-----------------+  |
           |  |    0                  |
           |  |  +-----------------+  |
           |  |  | 'CHRS'      20  |  |  .CHRS 20
           |  |  |-----------------|  |
           |  |  | Four score and  |  |
           |  |  | seven           |  |
           |  |  +-----------------+  |
           |  |                       |
           -- +-----------------------+

The "0" after the first CHRS chunk is a pad byte.


FTXT IFF Formatted / Appendix C. ISO/ANSI Control Sequences

This is a racetrack diagram of the ISO/ANSI characters and control
sequences as used in FTXT CHRS chunks.

     line terminator
---+-----------------> LF------------------------------------------------>
   |
   |\  ESC-Seq
   | +---------------> ESC--------------------------+---> 0 through ~ --->
   |                        |                       |
   |                        +<----SP through \  <---+
   |
   |\  printable
   | +----------+----> SP through ~ ------------------------------------->
   |            |                      /
   |            +----> G1------------>+
   |
   |\  ShiftToG2
   | +---------------> G0----------------------> (produces a G2 character)
   |
   |\  ShiftToG3
   | +---------------> G0----------------------> (produces a G3 character)
   |
   |
   |\  CSI-Seq
   | +--------------> CSI--+-----------------------+----> @ through ~ --->
   |                       |                       |
   |                       +<--- SP through ?  <---+
   |
   |\  DCS-Seq
   | +---------> DCS, OSC,-+-----------------------+----------> ST ------>
   |             PM, APC   |                       |    \
   |                       +<--- SP through ~  <---+     +----> G1 ------>
   |
    \  discard
     +--------------------> any other character-------------------------->

Of the various control sequences, only CSI-Seq is used for FTXT character
formatting information.  The others are reserved for future use and for
compatibility with ISO/ANSI standards.  Certain character sequences are
syntactically malformed, e.g., CSI followed by a C0, C1, or G1 character.
Writer programs should not generate reserved or malformed sequences and
reader programs should skip them.

Consult the ISO/ANSI standards for the meaning of the CSI-Seq control
sequences.

The two character set shifts SS2 and SS3 may be used when the graphic
character groups G2 and G3 become standardized.


Devices/Dev_examples/Epsonx_transfer.c

/*
        C-language Transfer routine for EpsonX driver.
 */

#include <exec/types.h>
#include <devices/printer.h>
#include <devices/prtbase.h>
#include <devices/prtgfx.h>

Transfer(PInfo, y, ptr, colors, BufOffset)
struct PrtInfo *PInfo;
UWORD y;                /* row # */
UBYTE *ptr;             /* ptr to buffer */
UWORD *colors;          /* indexes to color buffers */
ULONG BufOffset;        /* used for interleaved printing */
{
        extern struct PrinterData *PD;
        extern struct PrinterExtendedData *PED;

        static UWORD bit_table[8] = {128, 64, 32, 16, 8, 4, 2, 1};
        union colorEntry *ColorInt;
        UBYTE *bptr, *yptr, *mptr, *cptr, Black, Yellow, Magenta, Cyan;
        UBYTE *dmatrix, dvalue, threshold;
        UWORD x, width, sx, *sxptr, color, bit, x3;

        /* printer non-specific, MUST DO FOR EVERY PRINTER */
        x = PInfo->pi_xpos;
        ColorInt = PInfo->pi_ColorInt;
        sxptr = PInfo->pi_ScaleX;
        width = PInfo->pi_width;

        /* printer specific */
        if (PED->ped_YDotsInch == 216)
        {
                BufOffset *= y % 3;
                y /= 3;
        }
        else if (PED->ped_YDotsInch == 144)
        {
                BufOffset *= y & 1;
                y /= 2;
        }
        else
        {
                BufOffset = 0;
        }
        bit = bit_table[y & 7];
        bptr = ptr + colors[0] + BufOffset;
        yptr = ptr + colors[1] + BufOffset;
        mptr = ptr + colors[2] + BufOffset;
        cptr = ptr + colors[3] + BufOffset;

        /* pre-compute threshold; are we thresholding? */
        if (threshold = PInfo->pi_threshold)
        { /* thresholding */
                dvalue = threshold ^ 15;
                bptr += x;
                do { /* for all source pixels */
                        /* pre-compute intensity values for Black component */
                        Black = ColorInt->colorByte[PCMBLACK];
                        ColorInt++;

                        sx = *sxptr++;

                        do { /* use this pixel 'sx' times */
                                if (Black > dvalue)
                                {
                                        *bptr |= bit;
                                }
                                bptr++; /* done 1 more printer pixel */
                        } while (--sx);
                } while (--width);
        }

        else
        { /* not thresholding, pre-compute ptr to dither matrix */
                dmatrix = PInfo->pi_dmatrix + ((y & 3) << 2);
                if (PD->pd_Preferences.PrintShade == SHADE_GREYSCALE)
                {
                        do { /* for all source pixels */
                                /* pre-compute intensity values for Black */
                                Black = ColorInt->colorByte[PCMBLACK];
                                ColorInt++;

                                sx = *sxptr++;

                                do { /* use this pixel 'sx' times */
                                        if (Black > dmatrix[x & 3])
                                        {
                                                *(bptr + x) |= bit;
                                        }
                                        x++; /* done 1 more printer pixel */
                                } while (--sx);
                        } while (--width);
                }
                else
                { /* color */
                        do { /* for all source pixels */
                                /* compute intensity values for each color */
                                Black = ColorInt->colorByte[PCMBLACK];
                                Yellow = ColorInt->colorByte[PCMYELLOW];
                                Magenta = ColorInt->colorByte[PCMMAGENTA];
                                Cyan = ColorInt->colorByte[PCMCYAN];
                                ColorInt++;

                                sx = *sxptr++;

                                do { /* use this pixel 'sx' times */
                                        x3 = x >> 3;
                                        dvalue = dmatrix[x & 3];
                                        if (Black > dvalue)
                                        {
                                                *(bptr + x) |= bit;
                                        }
                                        else
                                        { /* black not rendered */
                                                if (Yellow > dvalue)
                                                {
                                                        *(yptr + x) |= bit;
                                                }
                                                if (Magenta > dvalue)
                                                {
                                                        *(mptr + x) |= bit;
                                                }
                                                if (Cyan > dvalue)
                                                {
                                                        *(cptr + x) |= bit;
                                                }
                                        }
                                        ++x; /* done 1 more printer pixel */
                                } while (--sx);
                        } while (--width);
                }
        }
}


Devices/Dev_examples/macros.i

**********************************************************************
*
*       printer device macro definitions
*
**********************************************************************

*------ external definition macros -----------------------------------

XREF_EXE        MACRO
        XREF            _LVO\1
                ENDM

XREF_DOS        MACRO
        XREF            _LVO\1
                ENDM

XREF_GFX        MACRO
        XREF            _LVO\1
                ENDM

XREF_ITU        MACRO
        XREF            _LVO\1
                ENDM

*------ library dispatch macros --------------------------------------

CALLEXE         MACRO
                CALLLIB _LVO\1
                ENDM

LINKEXE         MACRO
                LINKLIB _LVO\1,_SysBase
                ENDM

LINKDOS         MACRO
                LINKLIB _LVO\1,_DOSBase
                ENDM

LINKGFX         MACRO
                LINKLIB _LVO\1,_GfxBase
                ENDM

LINKITU         MACRO
                LINKLIB _LVO\1,_IntuitionBase
                ENDM


Devices/Dev_examples/Epsonx_Makefile

LC = lc:lc
ASM = lc:asm
CFLAGS = -iINCLUDE: -b0 -d0 -v
ASMFLAGS = -iINCLUDE:
LINK = lc:blink
LIB = lib:lc.lib+lib:amiga.lib
OBJ = printertag.o+init.o+data.o+dospecial.o+render.o+transfer.o+density.o
TARGET = EpsonX

        @$(LC) $(CFLAGS) $*

$(TARGET): printertag.o init.o data.o dospecial.o render.o density.o transfer.o
        @$(LINK) <WITH <
        FROM $(OBJ)
        TO $(TARGET)
        LIBRARY $(LIB)
        NODEBUG SC SD VERBOSE MAP $(TARGET).map H
        <

init.o: init.asm
        @$(ASM) $(ASMFLAGS) init.asm

printertag.o: printertag.asm epsonX_rev.i
        @$(ASM) $(ASMFLAGS) printertag.asm

transfer.o: transfer.asm
        @$(ASM) $(ASMFLAGS) transfer.asm

dospecial.o: dospecial.c

data.o: data.c

density.o: density.c

render.o: render.c


Devices/Dev_examples/Epsonx_init.asm

**********************************************************************
*
*       printer device functions
*
**********************************************************************

        SECTION         printer

*------ Included Files -----------------------------------------------

        INCLUDE         "exec/types.i"
        INCLUDE         "exec/nodes.i"
        INCLUDE         "exec/lists.i"
        INCLUDE         "exec/memory.i"
        INCLUDE         "exec/ports.i"
        INCLUDE         "exec/libraries.i"

        INCLUDE         "macros.i"

*------ Imported Functions -------------------------------------------

        XREF_EXE        CloseLibrary
        XREF_EXE        OpenLibrary
        XREF            _AbsExecBase

        XREF            _PEDData

*------ Exported Globals ---------------------------------------------

        XDEF            _Init
        XDEF            _Expunge
        XDEF            _Open
        XDEF            _Close
        XDEF            _PD
        XDEF            _PED
        XDEF            _SysBase
        XDEF            _DOSBase
        XDEF            _GfxBase
        XDEF            _IntuitionBase

**********************************************************************
        SECTION         printer,DATA
_PD             DC.L    0
_PED            DC.L    0
_SysBase        DC.L    0
_DOSBase        DC.L    0
_GfxBase        DC.L    0
_IntuitionBase  DC.L    0

**********************************************************************
        SECTION         printer,CODE
_Init:
                MOVE.L  4(A7),_PD
                LEA     _PEDData(PC),A0
                MOVE.L  A0,_PED
                MOVE.L  A6,-(A7)
                MOVE.L  _AbsExecBase,A6
                MOVE.L  A6,_SysBase

*           ;------ open the dos library
                LEA     DLName(PC),A1
                MOVEQ   #0,D0
                CALLEXE OpenLibrary
                MOVE.L  D0,_DOSBase
                BEQ     initDLErr

*           ;------ open the graphics library
                LEA     GLName(PC),A1
                MOVEQ   #0,D0
                CALLEXE OpenLibrary
                MOVE.L  D0,_GfxBase
                BEQ     initGLErr

*           ;------ open the intuition library
                LEA     ILName(PC),A1
                MOVEQ   #0,D0
                CALLEXE OpenLibrary
                MOVE.L  D0,_IntuitionBase
                BEQ     initILErr

                MOVEQ   #0,D0
pdiRts:
                MOVE.L  (A7)+,A6
                RTS

initPAErr:
                MOVE.L  _IntuitionBase,A1
                LINKEXE CloseLibrary

initILErr:
                MOVE.L  _GfxBase,A1
                LINKEXE CloseLibrary

initGLErr:
                MOVE.L  _DOSBase,A1
                LINKEXE CloseLibrary

initDLErr:
                MOVEQ   #-1,D0
                BRA.S   pdiRts

ILName:
                DC.B    'intuition.library'
                DC.B    0
DLName:
                DC.B    'dos.library'
                DC.B    0
GLName:
                DC.B    'graphics.library'
                DC.B    0
                DS.W    0

*---------------------------------------------------------------------
_Expunge:
                MOVE.L  _IntuitionBase,A1
                LINKEXE CloseLibrary

                MOVE.L  _GfxBase,A1
                LINKEXE CloseLibrary

                MOVE.L  _DOSBase,A1
                LINKEXE CloseLibrary

*---------------------------------------------------------------------
_Open:
                MOVEQ   #0,D0
                RTS

*---------------------------------------------------------------------
_Close:
                MOVEQ   #0,D0
                RTS

                END


Devices/Dev_examples/Epsonx_transfer.asm

**********************************************************************
*
* Transfer routine for EpsonX
*
**********************************************************************

        INCLUDE "exec/types.i"

        INCLUDE "intuition/intuition.i"
        INCLUDE "devices/printer.i"
        INCLUDE "devices/prtbase.i"
        INCLUDE "devices/prtgfx.i"

        XREF    _PD
        XREF    _PED
        XREF    _LVODebug
        XREF    _AbsExecBase

        XDEF    _Transfer

        SECTION         printer,CODE
_Transfer:
; Transfer(PInfo, y, ptr, colors, BufOffset)
; struct PrtInfo *PInfo         4-7
; UWORD y;                      8-11
; UBYTE *ptr;                   12-15
; UWORD *colors;                16-19
; ULONG BufOffset               20-23

        movem.l d2-d6/a2-a4,-(sp)       ;save regs used

        movea.l 36(sp),a0               ;a0 = PInfo
        move.l  40(sp),d0               ;d0 = y
        movea.l 44(sp),a1               ;a1 = ptr
        movea.l 48(sp),a2               ;a2 = colors
        move.l  52(sp),d1               ;d1 = BufOffset

        move.l  d0,d3                   ;save y
        moveq.l #3,d2
        and.w   d0,d2                   ;d2 = y & 3
        lsl.w   #2,d2                   ;d2 = (y & 3) << 2
        movea.l pi_dmatrix(a0),a3       ;a3 = dmatrix
        adda.l  d2,a3                   ;a3 = dmatrix + ((y & 3) << 2)

        movea.l _PED,a4                 ;a4 = ptr to PED
        cmpi.w  #216,ped_YDotsInch(a4)  ;triple interleaving?
        bne.s   10$                     ;no
        divu.w  #3,d0                   ;y /= 3
        swap.w  d0                      ;d0 = y % 3
        mulu.w  d0,d1                   ;BufOffset *= y % 3
        swap.w  d0                      ;d0 = y / 3
        bra.s   30$

10$:    cmpi.w  #144,ped_YDotsInch(a4)  ;double interleaving?
        bne.s   20$                     ;no, clear BufOffset
        asr.w   #1,d0                   ;y /= 2
        btst    #0,d3                   ;odd pass?
        bne.s   30$                     ;no, dont clear BufOffset

20$:    moveq.l #0,d1                   ;BufOffset = 0

30$:    move.w  d0,d6
        not.b   d6                      ;d6 = bit to set
        adda.l  d1,a1                   ;ptr += BufOffset

        movea.l _PD,a4                  ;a4 = ptr to PD
        cmpi.w  #SHADE_COLOR,pd_Preferences+pf_PrintShade(a4)   ;color dump?
        bne     not_color               ;no

color:

; a0 - PInfo
; a1 - ptr (ptr + BufOffset)
; a2 - colors
; a3 - dmatrix ptr
; d0 - y
; d1 - BufOffset
; d6 - bit to set

        movem.l d7/a5-a6,-(sp)          ;save regs used

        movea.l a1,a4
        movea.l a1,a5
        movea.l a1,a6
        adda.w  (a2)+,a1                ;a1 = ptr + colors[0] (bptr)
        adda.w  (a2)+,a4                ;a4 = ptr + colors[1] (yptr)
        adda.w  (a2)+,a5                ;a5 = ptr + colors[2] (mptr)
        adda.w  (a2)+,a6                ;a6 = ptr + colors[3] (cptr)

;       move.l  a6,-(sp)
;       move.l  _AbsExecBase,a6
;       jsr     _LVODebug(a6)
;       move.l  (sp)+,a6

        movea.l pi_ColorInt(a0),a2      ;a2 = ColorInt ptr
        move.w  pi_width(a0),width      ;# of pixels to do
        move.w  pi_xpos(a0),d2          ;d2 = x
        movea.l pi_ScaleX(a0),a0        ;a0 = ScaleX (sxptr)
        move.b  d6,d7                   ;d7 = bit to set

; a0 - sxptr
; a1 - bptr
; a2 - ColorInt ptr
; a3 - dmatrix ptr
; a4 - yptr
; a5 - mptr
; a6 - cptr
; d1 - Black
; d2 - x
; d3 - dvalue (dmatrix[x & 3])
; d4 - Yellow
; d5 - Magenta
; d6 - Cyan
; d7 - bit to set

cwidth_loop:
        move.b  PCMBLACK(a2),d1         ;d1 = Black
        move.b  PCMYELLOW(a2),d4        ;d4 = Yellow
        move.b  PCMMAGENTA(a2),d5       ;d5 = Magenta
        move.b  PCMCYAN(a2),d6          ;d6 = Cyan
        addq.l  #ce_SIZEOF,a2           ;advance to next entry

        move.w  (a0)+,sx                ;# of times to use this pixel

csx_loop:
        moveq.l #3,d3
        and.w   d2,d3                   ;d3 = x & 3
        move.b  0(a3,d3.w),d3           ;d3 = dmatrix[x & 3]

black:
        cmp.b   d3,d1                   ;render black?
        ble.s   yellow                  ;no, try ymc
        bset.b  d7,0(a1,d2.w)           ;set black pixel
        bra.s   csx_end

yellow:
        cmp.b   d3,d4                   ;render yellow pixel?
        ble.s   magenta                 ;no.
        bset.b  d7,0(a4,d2.w)           ;set yellow pixel

magenta:
        cmp.b   d3,d5                   ;render magenta pixel?
        ble.s   cyan                    ;no.
        bset.b  d7,0(a5,d2.w)           ;set magenta pixel

cyan:
        cmp.b   d3,d6                   ;render cyan pixel?
        ble.s   csx_end                 ;no, skip to next pixel.
        bset.b  d7,0(a6,d2.w)           ;clear cyan pixel

csx_end:
        addq.w  #1,d2                   ;x++
        subq.w  #1,sx                   ;sx--
        bne.s   csx_loop
        subq.w  #1,width                ;width--
        bne.s   cwidth_loop

        movem.l (sp)+,d7/a5-a6          ;restore regs used
        bra     exit

not_color:
; a0 - PInfo
; a1 - ptr
; a2 - colors
; a3 - dmatrix ptr
; d0 - y
; d6 - bit to set

        adda.w  (a2),a1                 ;a1 = ptr + colors[0]
        move.w  pi_width(a0),d1         ;d1 = width
        subq.w  #1,d1                   ;adjust for dbra

        move.w  pi_threshold(a0),d3     ;d3 = threshold, thresholding?
        beq.s   grey_scale              ;no, grey-scaling

threshold:
; a0 - PInfo
; a1 - ptr
; a3 - dmatrix ptr
; d1 - width-1
; d3 - threshold
; d6 - bit to set

        eori.b  #15,d3                  ;d3 = dvalue
        movea.l pi_ColorInt(a0),a2      ;a2 = ColorInt ptr
        move.w  pi_xpos(a0),d2          ;d2 = x
        movea.l pi_ScaleX(a0),a0        ;a0 = ScaleX (sxptr)
        adda.w  d2,a1                   ;ptr += x

; a0 - sxptr
; a1 - ptr
; a2 - ColorInt ptr
; a3 - dmatrix ptr (NOT USED)
; d1 - width
; d3 - dvalue
; d4 - Black
; d5 - sx
; d6 - bit to set

twidth_loop:
        move.b  PCMBLACK(a2),d4         ;d4 = Black
        addq.l  #ce_SIZEOF,a2           ;advance to next entry

        move.w  (a0)+,d5                ;d5 = # of times to use this pixel

        cmp.b   d3,d4                   ;render this pixel?
        ble.s   tsx_end                 ;no, skip to next pixel.
        subq.w  #1,d5                   ;adjust for dbra

tsx_render:                             ;yes, render this pixel sx times
        bset.b  d6,(a1)                 ;*(ptr) |= bit;

        adda.w  #1,a1                   ;ptr++
        dbra    d5,tsx_render           ;sx--
        dbra    d1,twidth_loop          ;width--
        bra.s   exit                    ;all done

tsx_end:
        adda.w  d5,a1                   ;ptr += sx
        dbra    d1,twidth_loop          ;width--
        bra.s   exit

grey_scale:
; a0 - PInfo
; a1 - ptr
; a3 - dmatrix ptr
; d0 - y
; d1 - width-1
; d6 - bit to set

        movea.l pi_ColorInt(a0),a2      ;a2 = ColorInt ptr
        move.w  pi_xpos(a0),d2          ;d2 = x
        movea.l pi_ScaleX(a0),a0        ;a0 = ScaleX (sxptr)

; a0 - sxptr
; a1 - ptr
; a2 - ColorInt ptr
; a3 - dmatrix ptr
; d1 - width
; d2 - x
; d3 - dvalue (dmatrix[x & 3])
; d4 - Black
; d5 - sx
; d6 - bit to set

gwidth_loop:
        move.b  PCMBLACK(a2),d4         ;d4 = Black
        addq.l  #ce_SIZEOF,a2           ;advance to next entry

        move.w  (a0)+,d5                ;d5 = # of times to use this pixel
        subq.w  #1,d5                   ;adjust for dbra

gsx_loop:
        moveq.l #3,d3
        and.w   d2,d3                   ;d3 = x & 3
        move.b  0(a3,d3.w),d3           ;d3 = dmatrix[x & 3]

        cmp.b   d3,d4                   ;render this pixel?
        ble.s   gsx_end                 ;no, skip to next pixel.

        bset.b  d6,0(a1,d2.w)           ;*(ptr + x) |= bit

gsx_end
        addq.w  #1,d2                   ;x++
        dbra    d5,gsx_loop             ;sx--
        dbra    d1,gwidth_loop          ;width--

exit:
        movem.l (sp)+,d2-d6/a2-a4       ;restore regs used
        moveq.l #0,d0                   ;flag all ok
        rts                             ;goodbye

sx      dc.w    0
width   dc.w    0

        END


Devices/Dev_examples/Epsonx_macros.i

**********************************************************************
*
*       printer device macro definitions
*
**********************************************************************

*------ external definition macros -----------------------------------

XREF_EXE        MACRO
        XREF            _LVO\1
                ENDM

XREF_DOS        MACRO
        XREF            _LVO\1
                ENDM

XREF_GFX        MACRO
        XREF            _LVO\1
                ENDM

XREF_ITU        MACRO
        XREF            _LVO\1
                ENDM

*------ library dispatch macros --------------------------------------

CALLEXE         MACRO
                CALLLIB _LVO\1
                ENDM

LINKEXE         MACRO
                LINKLIB _LVO\1,_SysBase
                ENDM

LINKDOS         MACRO
                LINKLIB _LVO\1,_DOSBase
                ENDM

LINKGFX         MACRO
                LINKLIB _LVO\1,_GfxBase
                ENDM

LINKITU         MACRO
                LINKLIB _LVO\1,_IntuitionBase
                ENDM


Devices/Dev_examples/Epsonx_data.c

/*
        Data.c table for EpsonX driver.
*/

char *CommandTable[] ={
        "\375\033@\375",/* 00 aRIS reset                        */
        "\377",         /* 01 aRIN initialize                   */
        "\012",         /* 02 aIND linefeed                     */
        "\015\012",     /* 03 aNEL CRLF                         */
        "\377",         /* 04 aRI reverse LF                    */

                        /* 05 aSGR0 normal char set             */
        "\0335\033-\376\033F",
        "\0334",        /* 06 aSGR3 italics on                  */
        "\0335",        /* 07 aSGR23 italics off                */
        "\033-\001",    /* 08 aSGR4 underline on                */
        "\033-\376",    /* 09 aSGR24 underline off              */
        "\033E",        /* 10 aSGR1 boldface on                 */
        "\033F",        /* 11 aSGR22 boldface off               */
        "\377",         /* 12 aSFC set foreground color         */
        "\377",         /* 13 aSBC set background color         */

                        /* 14 aSHORP0 normal pitch              */
        "\033P\022\033W\376",
                        /* 15 aSHORP2 elite on                  */
        "\033M\022\033W\376",
        "\033P",        /* 16 aSHORP1 elite off                 */
                        /* 17 aSHORP4 condensed fine on         */
        "\017\033P\033W\376",
        "\022",         /* 18 aSHORP3 condensed fine off        */
        "\033W\001",    /* 19 aSHORP6 enlarge on                */
        "\033W\376",    /* 20 aSHORP5 enlarge off               */

        "\377",         /* 21 aDEN6 shadow print on             */
        "\377",         /* 22 aDEN5 shadow print off            */
        "\033G",        /* 23 aDEN4 double strike on            */
        "\033H",        /* 24 aDEN3 double strike off           */
        "\033x\001",    /* 25 aDEN2 NLQ on                      */
        "\033x\376",    /* 26 aDEN1 NLQ off                     */

        "\033S\376",    /* 27 aSUS2 superscript on              */
        "\033T",        /* 28 aSUS1 superscript off             */
        "\033S\001",    /* 29 aSUS4 subscript on                */
        "\033T",        /* 30 aSUS3 subscript off               */
        "\033T",        /* 31 aSUS0 normalize the line          */
        "\377",         /* 32 aPLU partial line up              */
        "\377",         /* 33 aPLD partial line down            */

        "\033R\376",    /* 34 aFNT0 Typeface 0                  */
        "\033R\001",    /* 35 aFNT1 Typeface 1                  */
        "\033R\002",    /* 36 aFNT2 Typeface 2                  */
        "\033R\003",    /* 37 aFNT3 Typeface 3                  */
        "\033R\004",    /* 38 aFNT4 Typeface 4                  */
        "\033R\005",    /* 39 aFNT5 Typeface 5                  */
        "\033R\006",    /* 40 aFNT6 Typeface 6                  */
        "\033R\007",    /* 41 aFNT7 Typeface 7                  */
        "\033R\010",    /* 42 aFNT8 Typeface 8                  */
        "\033R\011",    /* 43 aFNT9 Typeface 9                  */
        "\033R\012",    /* 44 aFNT10 Typeface 10                */

        "\033p1",       /* 45 aPROP2 proportional on            */
        "\033p0",       /* 46 aPROP1 proportional off           */
        "\377",         /* 47 aPROP0 proportional clear         */
        "\377",         /* 48 aTSS set proportional offset      */
        "\377",         /* 49 aJFY5 auto left justify           */
        "\377",         /* 50 aJFY7 auto right justify          */
        "\377",         /* 51 aJFY6 auto full jusitfy           */
        "\377",         /* 52 aJFY0 auto jusity off             */
        "\377",         /* 53 aJFY3 letter space                */
        "\377",         /* 54 aJFY1 word fill                   */

        "\0330",        /* 55 aVERP0 1/8" line spacing          */
        "\0332",        /* 56 aVERP1 1/6" line spacing          */
        "\033C",        /* 57 aSLPP set form length             */
        "\033N",        /* 58 aPERF perf skip n (n > 0)         */
        "\033O",        /* 59 aPERF0 perf skip off              */

        "\377",         /* 60 aLMS set left margin              */
        "\377",         /* 61 aRMS set right margin             */
        "\377",         /* 62 aTMS set top margin               */
        "\377",         /* 63 aBMS set bottom margin            */
        "\377",         /* 64 aSTBM set T&B margins             */
        "\377",         /* 65 aSLRM set L&R margins             */
        "\377",         /* 66 aCAM clear margins                */

        "\377",         /* 67 aHTS set horiz tab                */
        "\377",         /* 68 aVTS set vert tab                 */
        "\377",         /* 69 aTBC0 clear horiz tab             */
        "\033D\376",    /* 70 aTBC3 clear all horiz tabs        */
        "\377",         /* 71 aTBC1 clear vert tab              */
        "\033B\376",    /* 72 aTBC4 clear all vert tabs         */
                        /* 73 aTBCALL clear all h & v tabs      */
        "\033D\376\033B\376",
                        /* 74 aTBSALL set default tabs          */
        "\033D\010\020\030\040\050\060\070\100\110\120\130\376",

        "\377",         /* 75 aEXTEND extended commands         */
        "\377"          /* 76 aRAW next 'n' chars are raw       */
};

/*
   For each character from character 160 to character 255, there is
   an entry in this table, which is used to print (or simulate printing of)
   the full Amiga character set. (see AmigaDos Developer's Manual, pp A-3)
   This table is used only if there is a valid pointer to this table
   in the PEDData table in the printertag.asm file, and the VERSION is
   33 or greater.  Otherwise, a default table is used instead.
   To place non-printable characters in this table, you can either enter
   them as in C strings (ie \011, where 011 is an octal number, or as
   \\000 where 000 is any decimal number, from 1 to 3 digits.  This is
   usually used  to enter a NUL into the array (C has problems with it
   otherwise.), or if you forgot your octal calculator.  On retrospect,
   was a poor choice for this function, as you must say \\\\ to enter a
   backslash as a backslash.  Live and learn...
*/
char *ExtendedCharTable[] = {
        " ",                                    /* NBSP*/
        "\033R\007[\033R\\0",                   /* i */
        "c\010|",                               /* c| */
        "\033R\003#\033R\\0",                   /* L- */
        "\033R\005$\033R\\0",                   /* o */
        "\033R\010\\\\\033R\\0",                /* Y- */
        "|",                                    /* | */
        "\033R\002@\033R\\0",                   /* SS */

        "\033R\001~\033R\\0",                   /* " */
        "c",                                    /* copyright */
        "\033S\\0a\010_\033T",                  /* a_ */
        "<",                                    /* << */
        "~",                                    /* - */
        "-",                                    /* SHY */
        "r",                                    /* registered trademark */
        "-",                                    /* - */

        "\033R\001[\033R\\0",                   /* degrees */
        "+\010_",                               /* +_ */
        "\033S\\0002\033T",                     /* 2 */
        "\033S\\0003\033T",                     /* 3 */
        "'",                                    /* ' */
        "u",                                    /* u */
        "P",                                    /* reverse P */
        "\033S\\000.\033T",                     /* . */

        ",",                                    /* , */
        "\033S\\0001\033T",                     /* 1 */
        "\033R\001[\033R\\0\010-",              /* o_ */
        ">",                                    /* >> */
        "\033S\\0001\033T\010-\010\033S\0014\033T",     /* 1/4 */
        "\033S\\0001\033T\010-\010\033S\0012\033T",     /* 1/2 */
        "\033S\\0003\033T\010-\010\033S\0014\033T",     /* 3/4 */
        "\033R\007]\033R\\0",                   /* upside down ? */

        "A\010`",                               /* ``A */
        "A\010'",                               /* 'A */
        "A\010^",                               /* ^A */
        "A\010~",                               /* ~A */
        "\033R\002[\033R\\0",                   /* "A */
        "\033R\004]\033R\\0",                   /* oA */
        "\033R\004[\033R\\0",                   /* AE */
        "C\010,",                               /* C, */

        "E\010`",                               /* ``E */
        "\033R\011@\033R\\0",                   /* 'E */
        "E\010^",                               /* ^E */
        "E\010\033R\001~\033R\\0",              /* "E */
        "I\010`",                               /* ``I */
        "I\010`",                               /* 'I */
        "I\010^",                               /* ^I */
        "I\010\033R\001~\033R\\0",              /* "I */

        "D\010-",                               /* -D */
        "\033R\007\\\\\033R\\0",                /* ~N */
        "O\010`",                               /* ``O */
        "O\010'",                               /* 'O */
        "O\010^",                               /* ^O */
        "O\010~",                               /* ~O */
        "\033R\002\\\\\033R\\0",                /* "O */
        "x",                                    /* x */

        "\033R\004\\\\\033R\\0",                /* 0 */
        "U\010`",                               /* ``U */
        "U\010'",                               /* 'U */
        "U\010^",                               /* ^U */
        "\033R\002]\033R\\0",                   /* "U */
        "Y\010'",                               /* 'Y */
        "T",                                    /* Thorn */
        "\033R\002~\033R\\0",                   /* B */

        "\033R\001@\033R\\0",                   /* ``a */
        "a\010'",                               /* 'a */
        "a\010^",                               /* ^a */
        "a\010~",                               /* ~a */
        "\033R\002{\033R\\0",                   /* "a */
        "\033R\004}\033R\\0",                   /* oa */
        "\033R\004{\033R\\0",                   /* ae */
        "\033R\001\\\\\033R\\0",                /* c, */

        "\033R\001}\033R\\0",                   /* ``e */
        "\033R\001{\033R\\0",                   /* 'e */
        "e\010^",                               /* ^e */
        "e\010\033R\001~\033R\\0",              /* "e */
        "\033R\006~\033R\\0",                   /* ``i */
        "i\010'",                               /* 'i */
        "i\010^",                               /* ^i */
        "i\010\033R\001~\033R\\0",              /* "i */

        "d",                                    /* d */
        "\033R\007|\033R\\0",                   /* ~n */
        "\033R\006|\033R\\0",                   /* ``o */
        "o\010'",                               /* 'o */
        "o\010^",                               /* ^o */
        "o\010~",                               /* ~o */
        "\033R\002|\033R\\0",                   /* "o */
        ":\010-"                                /* :- */

        "\033R\004|\033R\\0",                   /* o/ */
        "\033R\001|\033R\\0",                   /* ``u */
        "u\010'",                               /* 'u */
        "u\010^",                               /* ^u */
        "\033R\002}\033R\\0",                   /* "u */
        "y\010'",                               /* 'y */
        "t",                                    /* thorn */
        "y\010\033R\001~\033R\\0"               /* "y */
};


Devices/Dev_examples/Epsonx_printertag.asm

**********************************************************************
*
*       printer device dependent code tag
*
**********************************************************************

        SECTION         printer

*------ Included Files -----------------------------------------------

        INCLUDE         "exec/types.i"
        INCLUDE         "exec/nodes.i"
        INCLUDE         "exec/strings.i"

        INCLUDE         "epsonX_rev.i"

        INCLUDE         "devices/prtbase.i"

*------ Imported Names -----------------------------------------------

        XREF            _Init
        XREF            _Expunge
        XREF            _Open
        XREF            _Close
        XREF            _CommandTable
        XREF            _PrinterSegmentData
        XREF            _DoSpecial
        XREF            _Render
        XREF            _ExtendedCharTable

*------ Exported Names -----------------------------------------------

        XDEF            _PEDData

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

                MOVEQ   #0,D0           ; show error for OpenLibrary()
                RTS
                DC.W    VERSION
                DC.W    REVISION
_PEDData:
                DC.L    printerName
                DC.L    _Init
                DC.L    _Expunge
                DC.L    _Open
                DC.L    _Close
                DC.B    PPC_COLORGFX    ;PrinterClass
                DC.B    PCC_YMCB        ; ColorClass
                DC.B    136             ; MaxColumns
                DC.B    10              ; NumCharSets
                DC.W    8               ; NumRows
                DC.L    1632            ; MaxXDots
                DC.L    0               ; MaxYDots
                DC.W    120             ; XDotsInch
                DC.W    72              ; YDotsInch
                DC.L    _CommandTable   ; Commands
                DC.L    _DoSpecial
                DC.L    _Render
                DC.L    30              ; Timeout
                DC.L    _ExtendedCharTable      ; 8BitChars
                DS.L    1               ; PrintMode (reserve space)
                DC.L    0               ; ptr to char conversion function

printerName:
                dc.b    'EpsonX',0

                END


Devices/Dev_examples/Epsonx_dospecial.c

/*
        DoSpecial for EpsonX driver.
*/

#include "exec/types.h"
#include "devices/printer.h"
#include "devices/prtbase.h"

#define LMARG   3
#define RMARG   6
#define MARGLEN 8

#define CONDENSED       7
#define PITCH           9
#define QUALITY         17
#define LPI             24
#define INITLEN         26

DoSpecial(command, outputBuffer, vline, currentVMI, crlfFlag, Parms)
char outputBuffer[];
UWORD *command;
BYTE *vline;
BYTE *currentVMI;
BYTE *crlfFlag;
UBYTE Parms[];
{
        extern struct PrinterData *PD;

        int x = 0, y = 0;
        /*
                00-00   \375    wait
                01-03   \033lL  set left margin
                04-06   \033Qq  set right margin
                07-07   \375    wait
        */

        static char initMarg[MARGLEN+1] = "\375\033lL\033Qq\375";
        /*
                00-01   \0335           italics off
                02-04   \033-\000       underline off
                05-06   \033F           boldface off
                07-07   \022            cancel condensed mode
                08-09   \033P           select pica (10 cpi)
                10-12   \033W\000       enlarge off
                13-14   \033H           doublestrike off
                15-17   \033x\000       draft
                18-19   \033T           super/sub script off
                20-22   \033p0          proportional off
                23-24   \0332           6 lpi
                25-25   \015            carriage return
        */
        static char initThisPrinter[INITLEN+1] =
        "\0335\033-\000\033F\022\033P\033W\000\033H\033x\000\033T\033p0\0332\015";

        static BYTE ISOcolorTable[10] = {0, 5, 6, 4, 3, 1, 2, 0};

        if (*command == aRIN) {
                while (x < INITLEN) {
                        outputBuffer[x] = initThisPrinter[x];
                        x++;
                }

                if (PD->pd_Preferences.PrintQuality == LETTER) {
                        outputBuffer[QUALITY] = 1;
                }

                *currentVMI = 36; /* assume 1/6 line spacing (36/216 => 1/6) */
                if (PD->pd_Preferences.PrintSpacing == EIGHT_LPI) {
                        outputBuffer[LPI] = '0';
                        *currentVMI = 27; /* 27/216 => 1/8 */
                }

                if (PD->pd_Preferences.PrintPitch == ELITE) {
                        outputBuffer[PITCH] = 'M';
                }
                else if (PD->pd_Preferences.PrintPitch == FINE) {
                        outputBuffer[CONDENSED] = '\017'; /* condensed */
                        outputBuffer[PITCH] = 'P'; /* pica condensed */
                }

                Parms[0] = PD->pd_Preferences.PrintLeftMargin;
                Parms[1] = PD->pd_Preferences.PrintRightMargin;
                *command = aSLRM;
        }

        if (*command == aCAM) { /* cancel margins */
                y = PD->pd_Preferences.PaperSize == W_TRACTOR ? 136 : 80;
                if (PD->pd_Preferences.PrintPitch == PICA) {
                        Parms[1] = (10 * y) / 10;
                }
                else if (PD->pd_Preferences.PrintPitch == ELITE) {
                        Parms[1] = (12 * y) / 10;
                }
                else { /* fine */
                        Parms[1] = (17 * y) / 10;
                }
                Parms[0] = 1;
                y = 0;
                *command = aSLRM;
        }

        if (*command == aSLRM) { /* set left and right margins */
                PD->pd_PWaitEnabled = 253;
                if (Parms[0] == 0) {
                        initMarg[LMARG] = 0;
                }
                else {
                        initMarg[LMARG] = Parms[0] - 1;
                }
                initMarg[RMARG] = Parms[1];
                while (y < MARGLEN) {
                        outputBuffer[x++] = initMarg[y++];
                }
                return(x);
        }

        if (*command == aPLU) {
                if (*vline == 0) {
                        *vline = 1;
                        *command = aSUS2;
                        return(0);
                }
                if (*vline < 0) {
                        *vline = 0;
                        *command = aSUS3;
                        return(0);
                }
                return(-1);
        }

        if (*command == aPLD) {
                if (*vline == 0) {
                        *vline = -1;
                        *command = aSUS4;
                        return(0);
                }
                if (*vline > 0) {
                        *vline = 0;
                        *command = aSUS1;
                        return(0);
                }
                return(-1);
        }

        if (*command == aSUS0) {
                *vline = 0;
        }

        if (*command == aSUS1) {
                *vline = 0;
        }

        if (*command == aSUS2) {
                *vline = 1;
        }

        if (*command == aSUS3) {
                *vline = 0;
        }

        if (*command == aSUS4) {
                *vline = -1;
        }

        if (*command == aVERP0) {
                *currentVMI = 27;
        }

        if (*command == aVERP1) {
                *currentVMI = 36;
        }

        if (*command == aIND) { /* lf */
                outputBuffer[x++] = '\033';
                outputBuffer[x++] = 'J';
                outputBuffer[x++] = *currentVMI;
                return(x);
        }

        if (*command == aRI) { /* reverse lf */
                outputBuffer[x++] = '\033';
                outputBuffer[x++] = 'j';
                outputBuffer[x++] = *currentVMI;
                return(x);
        }

        if (*command == aSFC) {
                if (Parms[0] == 39) {
                        Parms[0] = 30; /* set defaults */
                }
                if (Parms[0] > 37) {
                        return(0); /* ni or background color change */
                }
                outputBuffer[x++] = '\033';
                outputBuffer[x++] = 'r';
                outputBuffer[x++] = ISOcolorTable[Parms[0] - 30];
                /*
                Kludge to get this to work on a CBM_MPS-1250  which interprets
                'ESCr' as go into reverse print mode.  The 'ESCt' tells it to
                get out of reverse print mode.  The 'NULL' is ignored by the
                CBM_MPS-1250 and required by all Epson printers as the
                terminator for the 'ESCtNULL' command which means select
                normal char set (which has no effect).
                */
                outputBuffer[x++] = '\033';
                outputBuffer[x++] = 't';
                outputBuffer[x++] = 0;
                return(x);
        }

        if (*command == aRIS) {
                PD->pd_PWaitEnabled = 253;
        }

        return(0);
}


Devices/Dev_examples/Epsonx_density.c

/*
        Density module for EpsonX driver.
*/

#include <exec/types.h>
#include "devices/printer.h"
#include "devices/prtbase.h"

SetDensity(density_code)
ULONG density_code;
{
        extern struct PrinterData *PD;
        extern struct PrinterExtendedData *PED;

        /* SPECIAL_DENSITY     0    1    2    3    4    5    6    7 */
        static int XDPI[8] = {120, 120, 120, 240, 120, 240, 240, 240};
        static int YDPI[8] = {72, 72, 144, 72, 216, 144, 216, 216};
        static char codes[8] = {'L', 'L', 'L', 'Z', 'L', 'Z', 'Z', 'Z'};

        PED->ped_MaxColumns =
                PD->pd_Preferences.PaperSize == W_TRACTOR ? 136 : 80;
        density_code /= SPECIAL_DENSITY1;
        /* default is 80 chars (8.0 in.), W_TRACTOR is 136 chars (13.6 in.) */
        PED->ped_MaxXDots =
                (XDPI[density_code] * PED->ped_MaxColumns) / 10;
        PED->ped_XDotsInch = XDPI[density_code];
        PED->ped_YDotsInch = YDPI[density_code];
        if ((PED->ped_YDotsInch = YDPI[density_code]) == 216) {
                PED->ped_NumRows = 24;
        }
        else if (PED->ped_YDotsInch == 144) {
                PED->ped_NumRows = 16;
        }
        else {
                PED->ped_NumRows = 8;
        }
        return((int)codes[density_code]);
}


Devices/Dev_examples/Epsonx_rev.i

VERSION         EQU     35
REVISION        EQU     1


Devices/Dev_examples/Epsonx_render.c

/*
        EpsonX (EX/FX/JX/LX/MX/RX) driver.
*/

#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/memory.h>
#include "devices/printer.h"
#include "devices/prtbase.h"

#define NUMSTARTCMD     7       /* # of cmd bytes before binary data */
#define NUMENDCMD       1       /* # of cmd bytes after binary data */
#define NUMTOTALCMD     (NUMSTARTCMD + NUMENDCMD)       /* total of above */
#define NUMLFCMD        4       /* # of cmd bytes for linefeed */
#define MAXCOLORBUFS    4       /* max # of color buffers */

#define STARTLEN        19
#define PITCH           1
#define CONDENSED       2
#define LMARG           8
#define RMARG           11
#define DIREC           15

static ULONG TwoBufSize;
static UWORD RowSize, ColorSize, NumColorBufs, dpi_code, spacing;
static UWORD colorcodes[MAXCOLORBUFS];

Render(ct, x, y, status)
long ct, x, y, status;
{
        extern void *AllocMem(), FreeMem();

        extern struct PrinterData *PD;
        extern struct PrinterExtendedData *PED;

        UBYTE *CompactBuf();
        static ULONG BufSize, TotalBufSize, dataoffset;
        static UWORD spacing, colors[MAXCOLORBUFS];
        /*
                00-01   \003P           set pitch (10 or 12 cpi)
                02-02   \022            set condensed fine (on or off)
                03-05   \033W\000       enlarge off
                06-08   \033ln          set left margin to n
                09-11   \033Qn          set right margin to n
                12-12   \015            carriage return
                13-15   \033U1          set uni-directional mode
                16-18   \033t\000       see kludge note below
                Kludge to get this to work on a CBM_MPS-1250  which interprets
                'ESCr' as go into reverse print mode.  The 'ESCt' tells it to
                get out of reverse print mode.  The 'NULL' is ignored by the
                CBM_MPS-1250 and required by all Epson printers as the
                terminator for the 'ESCtNULL' command which means select
                normal char set (which has no effect).
        */

        static UBYTE StartBuf[STARTLEN+1] =
                "\033P\022\033W\000\033ln\033Qn\015\033U1\033t\000";

        UBYTE *ptr, *ptrstart;
        int err;

        switch(status) {
                case 0 : /* Master Initialization */
                        /*
                                ct      - pointer to IODRPReq structure.
                                x       - width of printed picture in pixels.
                                y       - height of printed picture in pixels.
                        */
                        RowSize = x;
                        ColorSize = RowSize + NUMTOTALCMD;
                        if (PD->pd_Preferences.PrintShade == SHADE_COLOR) {
                                NumColorBufs = MAXCOLORBUFS;
                                colors[0] = ColorSize * 3; /* Black */
                                colors[1] = ColorSize * 0; /* Yellow */
                                colors[2] = ColorSize * 1; /* Magenta */
                                colors[3] = ColorSize * 2; /* Cyan */
                                colorcodes[0] = 4; /* Yellow */
                                colorcodes[1] = 1; /* Magenta */
                                colorcodes[2] = 2; /* Cyan */
                                colorcodes[3] = 0; /* Black */
                        }
                        else { /* grey-scale or black&white */
                                NumColorBufs = 1;
                                colors[0] = ColorSize * 0; /* Black */
                                colorcodes[0] = 0; /* Black */
                        }
                        BufSize = ColorSize * NumColorBufs + NUMLFCMD;
                        if (PED->ped_YDotsInch == 216) {
                                TwoBufSize = BufSize * 3;
                                TotalBufSize = BufSize * 6;
                        }
                        else if (PED->ped_YDotsInch == 144) {
                                TwoBufSize = BufSize * 2;
                                TotalBufSize = BufSize * 4;
                        }
                        else {
                                TwoBufSize = BufSize * 1;
                                TotalBufSize = BufSize * 2;
                        }
                        PD->pd_PrintBuf = AllocMem(TotalBufSize, MEMF_PUBLIC);
                        if (PD->pd_PrintBuf == NULL) {
                                err = PDERR_BUFFERMEMORY;
                        }
                        else {
                                dataoffset = NUMSTARTCMD;
                                /*
                                        This printer prints graphics within its
                                        text margins.  This code makes sure the
                                        printer is in 10 cpi and then sets the
                                        left and right margins to their minimum
                                        and maximum values (respectively).  A
                                        carriage return is sent so that the
                                        print head is at the leftmost position
                                        as this printer starts printing from
                                        the print head's position.  The printer
                                        is put into unidirectional mode to
                                        reduce wavy vertical lines.
                                */
                                StartBuf[PITCH] = 'P'; /* 10 cpi */
                                StartBuf[CONDENSED] = '\022'; /* off */
                                /* left margin of 1 */
                                StartBuf[LMARG] = 0;
                                /* right margin of 80 or 136 */
                                StartBuf[RMARG] = PD->pd_Preferences.
                                        PaperSize == W_TRACTOR ? 136 : 80;
                                /* uni-directional mode */
                                StartBuf[DIREC] = '1';
                                err = (*(PD->pd_PWrite))(StartBuf, STARTLEN);
                        }
                        break;

                case 1 : /* Scale, Dither and Render */
                        /*
                                ct      - pointer to PrtInfo structure.
                                x       - 0.
                                y       - row # (0 to Height - 1).
                        */
                        Transfer(ct, y, &PD->pd_PrintBuf[dataoffset], colors,
                                BufSize);
                        err = PDERR_NOERR; /* all ok */
                        break;

                case 2 : /* Dump Buffer to Printer */
                        /*
                                ct      - 0.
                                x       - 0.
                                y       - # of rows sent (1 to NumRows).

                        */
                        /* white-space strip */
                        ptrstart = &PD->pd_PrintBuf[dataoffset - NUMSTARTCMD];
                        if (PED->ped_YDotsInch == 72) {
                                /* y range : 1 to 8 */
                                y = y * 3 - spacing;
                                ptr = CompactBuf(ptrstart + NUMSTARTCMD,
                                        ptrstart, y, 1);
                        }
                        else if (PED->ped_YDotsInch == 144) {
                                /* y range : 1 to 16 */
                                ptr = CompactBuf(ptrstart + NUMSTARTCMD,
                                        ptrstart, 2, 1);
                                if (y > 1) {
                                        ptr = CompactBuf(&PD->pd_PrintBuf[
                                                dataoffset + BufSize],
                                                ptr, y * 3 / 2 - 2, 0);
                                }
                        }
                        else if (PED->ped_YDotsInch == 216) {
                                /* y range : 1 to 24 */
                                ptr = CompactBuf(ptrstart + NUMSTARTCMD,
                                        ptrstart, 1, 1);
                                if (y > 1) {
                                        ptr = CompactBuf(&PD->pd_PrintBuf[
                                                dataoffset + BufSize],
                                                ptr, 1, 0);
                                }
                                if (y > 2) {
                                        ptr = CompactBuf(&PD->pd_PrintBuf[
                                                dataoffset + BufSize * 2],
                                                ptr, y - 2, 0);
                                }
                        }
                        err = (*(PD->pd_PWrite))(ptrstart, ptr - ptrstart);
                        if (err == PDERR_NOERR) {
                                dataoffset = (dataoffset == NUMSTARTCMD ?
                                        TwoBufSize : 0) + NUMSTARTCMD;
                        }
                        break;

                case 3 : /* Clear and Init Buffer */
                        /*
                                ct      - 0.
                                x       - 0.
                                y       - 0.
                        */
                        ClearAndInit(&PD->pd_PrintBuf[dataoffset]);
                        err = PDERR_NOERR;
                        break;

                case 4 : /* Close Down */
                        /*
                                ct      - error code.
                                x       - io_Special flag from IODRPReq.
                                y       - 0.
                        */
                        err = PDERR_NOERR; /* assume all ok */
                        /* if user did not cancel print */
                        if (ct != PDERR_CANCEL) {
                                /* restore preferences pitch and margins */
                                if (PD->pd_Preferences.PrintPitch == ELITE) {
                                        StartBuf[PITCH] = 'M'; /* 12 cpi */
                                }
                                else if (PD->pd_Preferences.PrintPitch == FINE) {
                                        StartBuf[CONDENSED] = '\017'; /* on */
                                }
                                StartBuf[LMARG] =
                                        PD->pd_Preferences.PrintLeftMargin - 1;
                                StartBuf[RMARG] =
                                        PD->pd_Preferences.PrintRightMargin;
                                StartBuf[DIREC] = '0'; /* bi-directional */
                                err = (*(PD->pd_PWrite))(StartBuf, STARTLEN);
                        }
                        (*(PD->pd_PBothReady))();
                        if (PD->pd_PrintBuf != NULL) {
                                FreeMem(PD->pd_PrintBuf, TotalBufSize);
                        }
                        break;

                case 5 :  /* Pre-Master Initialization */
                        /*
                                ct      - 0 or pointer to IODRPReq structure.
                                x       - io_Special flag from IODRPReq.
                                y       - 0.
                        */
                        /* kludge for sloppy tractor mechanism */
                        spacing = PD->pd_Preferences.PaperType == SINGLE ?
                                1 : 0;
                        dpi_code = SetDensity(x & SPECIAL_DENSITYMASK);
                        err = PDERR_NOERR;
                        break;
        }
        return(err);
}

UBYTE *CompactBuf(ptrstart, ptr2start, y, flag)
UBYTE *ptrstart, *ptr2start;
long y;
int flag; /* 0 - not first pass, !0 - first pass */
{
        static int x;
        UBYTE *ptr, *ptr2;
        long ct;
        int i;

        ptr2 = ptr2start; /* where to put the compacted data */
        if (flag) {
                x = 0; /* flag no transfer required yet */
        }

        for (ct=0; ct<NumColorBufs; ct++, ptrstart += ColorSize) {
                i = RowSize;
                ptr = ptrstart + i - 1;
                while (i > 0 && *ptr == 0) {
                        i--;
                        ptr--;
                }

                if (i != 0) { /* if data */
                        *(++ptr) = 13;                  /* <cr> */
                        ptr = ptrstart - NUMSTARTCMD;
                        *ptr++ = 27;
                        *ptr++ = 'r';
                        *ptr++ = colorcodes[ct];        /* color */
                        *ptr++ = 27;
                        *ptr++ = dpi_code;              /* density */
                        *ptr++ = i & 0xff;
                        *ptr++ = i >> 8;                /* size */
                        i += NUMTOTALCMD;
                        if (x != 0) { /* if must transfer data */
                                /* get src start */
                                ptr = ptrstart - NUMSTARTCMD;
                                do { /* transfer and update dest ptr */
                                        *ptr2++ = *ptr++;
                                } while (--i);
                        }

                        else { /* no transfer required */
                                ptr2 += i; /* update dest ptr */
                        }
                }

                if (i != RowSize + NUMTOTALCMD) { /* if compacted or 0 */
                        x = 1; /* flag that we need to transfer next time */
                }
        }

        *ptr2++ = 13; /* cr */
        *ptr2++ = 27;
        *ptr2++ = 'J';
        *ptr2++ = y; /* y/216 lf */
        return(ptr2);
}

ClearAndInit(ptr)
UBYTE *ptr;
{
        ULONG *lptr, i, j;

        /*
                Note : Since 'NUMTOTALCMD + NUMLFCMD' is > 3 bytes if is safe
                to do the following to speed things up.
        */
        i = TwoBufSize - NUMTOTALCMD - NUMLFCMD;
        j = (ULONG)ptr;
        if (!(j & 1)) { /* if on a word boundary, clear by longs */
                i = (i + 3) / 4;
                lptr = (ULONG *)ptr;
                do {
                        *lptr++ = 0;
                } while (--i);
        }
        else { /* clear by bytes */
                do {
                        *ptr++ = 0;
                } while (--i);
        }
        return(0);
}


Devices/Dev_examples/HP_Laserjet_Makefile

LC = lc:lc
ASM = lc:asm
CFLAGS = -iINCLUDE: -b0 -d0 -v
ASMFLAGS = -iINCLUDE:
LINK = lc:blink
LIB = lib:amiga.lib+lib:lc.lib
OBJ = printertag.o+init.o+data.o+dospecial.o+render.o+transfer.o+density.o
TARGET = hp_laserjet

        @$(LC) $(CFLAGS) $*

$(TARGET): printertag.o init.o data.o dospecial.o render.o density.o transfer.o
        @$(LINK) <WITH <
        FROM $(OBJ)
        TO $(TARGET)
        LIBRARY $(LIB)
        NODEBUG SC SD VERBOSE MAP $(TARGET).map H
        <

init.o: init.asm
        @$(ASM) $(ASMFLAGS) init.asm

printertag.o: printertag.asm hp_rev.i
        @$(ASM) $(ASMFLAGS) printertag.asm

transfer.o: transfer.asm
        @$(ASM) $(ASMFLAGS) transfer.asm

dospecial.o: dospecial.c

data.o: data.c

density.o: density.c

render.o: render.c


Devices/Dev_examples/HP_Laserjet_init.asm

**********************************************************************
*
*       printer device functions
*
**********************************************************************

        SECTION         printer

*------ Included Files -----------------------------------------------

        INCLUDE         "exec/types.i"
        INCLUDE         "exec/nodes.i"
        INCLUDE         "exec/lists.i"
        INCLUDE         "exec/memory.i"
        INCLUDE         "exec/ports.i"
        INCLUDE         "exec/libraries.i"

        INCLUDE         "macros.i"

*------ Imported Functions -------------------------------------------

        XREF_EXE        CloseLibrary
        XREF_EXE        OpenLibrary
        XREF            _AbsExecBase

        XREF            _PEDData

*------ Exported Globals ---------------------------------------------

        XDEF            _Init
        XDEF            _Expunge
        XDEF            _Open
        XDEF            _PD
        XDEF            _PED
        XDEF            _SysBase
        XDEF            _DOSBase
        XDEF            _GfxBase
        XDEF            _IntuitionBase

**********************************************************************
        SECTION         printer,DATA
_PD             DC.L    0
_PED            DC.L    0
_SysBase        DC.L    0
_DOSBase        DC.L    0
_GfxBase        DC.L    0
_IntuitionBase  DC.L    0

**********************************************************************
        SECTION         printer,CODE
_Init:
                MOVE.L  4(A7),_PD
                LEA     _PEDData(PC),A0
                MOVE.L  A0,_PED
                MOVE.L  A6,-(A7)
                MOVE.L  _AbsExecBase,A6
                MOVE.L  A6,_SysBase

*           ;------ open the dos library
                LEA     DLName(PC),A1
                MOVEQ   #0,D0
                CALLEXE OpenLibrary
                MOVE.L  D0,_DOSBase
                BEQ     initDLErr

*           ;------ open the graphics library
                LEA     GLName(PC),A1
                MOVEQ   #0,D0
                CALLEXE OpenLibrary
                MOVE.L  D0,_GfxBase
                BEQ     initGLErr

*           ;------ open the intuition library
                LEA     ILName(PC),A1
                MOVEQ   #0,D0
                CALLEXE OpenLibrary
                MOVE.L  D0,_IntuitionBase
                BEQ     initILErr

                MOVEQ   #0,D0
pdiRts:
                MOVE.L  (A7)+,A6
                RTS

initPAErr:
                MOVE.L  _IntuitionBase,A1
                LINKEXE CloseLibrary
initILErr:
                MOVE.L  _GfxBase,A1
                LINKEXE CloseLibrary
initGLErr:
                MOVE.L  _DOSBase,A1
                LINKEXE CloseLibrary
initDLErr:
                MOVEQ   #-1,D0
                BRA.S   pdiRts

ILName:
                DC.B    'intuition.library'
                DC.B    0
DLName:
                DC.B    'dos.library'
                DC.B    0
GLName:
                DC.B    'graphics.library'
                DC.B    0
                DS.W    0

*---------------------------------------------------------------------
_Expunge:
                MOVE.L  _IntuitionBase,A1
                LINKEXE CloseLibrary

                MOVE.L  _GfxBase,A1
                LINKEXE CloseLibrary

                MOVE.L  _DOSBase,A1
                LINKEXE CloseLibrary

*---------------------------------------------------------------------
_Open:
                MOVEQ   #0,D0
                RTS

                END


Devices/Dev_examples/HP_Laserjet_transfer.asm

**********************************************************************
*
* Transfer routine for HP_LaserJet
*
**********************************************************************

        INCLUDE "exec/types.i"

        INCLUDE "intuition/intuition.i"
        INCLUDE "devices/printer.i"
        INCLUDE "devices/prtbase.i"
        INCLUDE "devices/prtgfx.i"

        XREF    _PD

        XDEF    _Transfer

        SECTION         printer,CODE
_Transfer:
; Transfer(PInfo, y, ptr)
; struct PrtInfo *PInfo         4-7
; UWORD y;                      8-11
; UBYTE *ptr;                   12-15
;

        movem.l d2-d6/a2-a3,-(sp)       ;save regs used

        movea.l 32(sp),a0               ;a0 = PInfo
        move.l  36(sp),d0               ;d0 = y
        movea.l 40(sp),a1               ;a1 = ptr

        move.w  pi_width(a0),d1         ;d1 = width
        subq.w  #1,d1                   ;adjust for dbra

        move.w  pi_threshold(a0),d3     ;d3 = threshold, thresholding?
        beq.s   grey_scale              ;no, grey-scale

threshold:
; a0 - PInfo
; a1 - ptr
; d0 - y
; d1 - width
; d3 - threshold

        eori.b  #15,d3                  ;d3 = dvalue
        movea.l pi_ColorInt(a0),a2      ;a2 = ColorInt ptr
        move.w  pi_xpos(a0),d2          ;d2 = x
        movea.l pi_ScaleX(a0),a0        ;a0 = ScaleX (sxptr)

; a0 - sxptr
; a1 - ptr
; a2 - ColorInt ptr
; a3 - dmatrix ptr (NOT USED)
; d0 - byte to set (x >> 3)
; d1 - width
; d2 - x
; d3 - dvalue
; d4 - Black
; d5 - sx
; d6 - bit to set

twidth_loop:
        move.b  PCMBLACK(a2),d4         ;d4 = Black
        addq.l  #ce_SIZEOF,a2           ;advance to next entry

        move.w  (a0)+,d5                ;d5 = # of times to use this pixel (sx)

        cmp.b   d3,d4                   ;render this pixel?
        ble.s   tsx_end                 ;no, skip to next pixel.
        subq.w  #1,d5                   ;adjust for dbra

tsx_render:                             ;yes, render this pixel sx times
        move.w  d2,d0
        lsr.w   #3,d0                   ;compute byte to set
        move.w  d2,d6
        not.w   d6                      ;compute bit to set
        bset.b  d6,0(a1,d0.w)           ;*(ptr + x >> 3) |= 2 ^ x

        addq.w  #1,d2                   ;x++
        dbra    d5,tsx_render           ;sx--
        dbra    d1,twidth_loop          ;width--
        bra.s   exit                    ;all done

tsx_end:
        add.w   d5,d2                   ;x += sx
        dbra    d1,twidth_loop          ;width--
        bra.s   exit

grey_scale:
; a0 - PInfo
; a1 - ptr
; d0 - y
; d1 - width

        movea.l pi_ColorInt(a0),a2      ;a2 = ColorInt ptr
        moveq.l #3,d2
        and.w   d0,d2                   ;d2 = y & 3
        lsl.w   #2,d2                   ;d2 = (y & 3) << 2
        movea.l pi_dmatrix(a0),a3       ;a3 = dmatrix
        adda.l  d2,a3                   ;a3 = dmatrix + ((y & 3) << 2)
        move.w  pi_xpos(a0),d2          ;d2 = x
        movea.l pi_ScaleX(a0),a0        ;a0 = ScaleX (sxptr)

; a0 - sxptr
; a1 - ptr
; a2 - ColorInt ptr
; a3 - dmatrix ptr
; d0 - byte to set (x >> 3)
; d1 - width
; d2 - x
; d3 - dvalue (dmatrix[x & 3])
; d4 - Black
; d5 - sx
; d6 - bit to set

gwidth_loop:
        move.b  PCMBLACK(a2),d4         ;d4 = Black
        addq.l  #ce_SIZEOF,a2           ;advance to next entry

        move.w  (a0)+,d5                ;d5 = # of times to use this pixel (sx)
        subq.w  #1,d5                   ;adjust for dbra

gsx_loop:
        moveq.l #3,d3
        and.w   d2,d3                   ;d3 = x & 3
        move.b  0(a3,d3.w),d3           ;d3 = dmatrix[x & 3]

        cmp.b   d3,d4                   ;render this pixel?
        ble.s   gsx_end                 ;no, skip to next pixel.

        move.w  d2,d0
        lsr.w   #3,d0                   ;compute byte to set
        move.w  d2,d6
        not.w   d6                      ;compute bit to set
        bset.b  d6,0(a1,d0.w)           ;*(ptr + x >> 3) |= 2 ^ x

gsx_end
        addq.w  #1,d2                   ;x++
        dbra    d5,gsx_loop             ;sx--
        dbra    d1,gwidth_loop          ;width--

exit:
        movem.l (sp)+,d2-d6/a2-a3       ;restore regs used
        moveq.l #0,d0                   ;flag all ok
        rts                             ;goodbye

        END


Devices/Dev_examples/HP_Laserjet_macros.i

**********************************************************************
*
*       printer device macro definitions
*
**********************************************************************

*------ external definition macros -----------------------------------

XREF_EXE        MACRO
        XREF            _LVO\1
                ENDM

XREF_DOS        MACRO
        XREF            _LVO\1
                ENDM

XREF_GFX        MACRO
        XREF            _LVO\1
                ENDM

XREF_ITU        MACRO
        XREF            _LVO\1
                ENDM

*------ library dispatch macros --------------------------------------

CALLEXE         MACRO
                CALLLIB _LVO\1
                ENDM

LINKEXE         MACRO
                LINKLIB _LVO\1,_SysBase
                ENDM

LINKDOS         MACRO
                LINKLIB _LVO\1,_DOSBase
                ENDM

LINKGFX         MACRO
                LINKLIB _LVO\1,_GfxBase
                ENDM

LINKITU         MACRO
                LINKLIB _LVO\1,_IntuitionBase
                ENDM


Devices/Dev_examples/HP_Laserjet_transfer.c

/*
        Example transfer routine for HP_LaserJet driver.

        Transfer() should be written in assembly code for speed
*/

#include <exec/types.h>
#include <devices/prtgfx.h>

Transfer(PInfo, y, ptr)
struct PrtInfo *PInfo;
UWORD y;        /* row # */
UBYTE *ptr;     /* ptr to buffer */
{
        static UBYTE bit_table[] = {128, 64, 32, 16, 8, 4, 2, 1};
        UBYTE *dmatrix, Black, dvalue, threshold;
        union colorEntry *ColorInt;
        UWORD x, width, sx, *sxptr, bit;

        /* pre-compute */
        /* printer non-specific, MUST DO FOR EVERY PRINTER */
        x = PInfo->pi_xpos; /* get starting x position */
        ColorInt = PInfo->pi_ColorInt; /* get ptr to color intensities */
        sxptr = PInfo->pi_ScaleX;
        width = PInfo->pi_width; /* get # of source pixels */

        /* pre-compute threshold; are we thresholding? */
        if (threshold = PInfo->pi_threshold) { /* thresholding */
                dvalue = threshold ^ 15; /* yes, so pre-compute dither value */
                do { /* for all source pixels */
                        /* pre-compute intensity value for Black */
                        Black = ColorInt->colorByte[PCMBLACK];
                        ColorInt++; /* bump ptr for next time */

                        sx = *sxptr++;

                        /* dither and render pixel */
                        do { /* use this pixel 'sx' times */
                                /* if we should render Black */
                                if (Black > dvalue) {
                                        /* set bit */
                                        *(ptr + (x >> 3)) |= bit_table[x & 7];
                                }
                                ++x; /* done 1 more printer pixel */
                        } while (--sx);
                } while (--width);
        }
        else { /* not thresholding, pre-compute ptr to dither matrix */
                dmatrix = PInfo->pi_dmatrix + ((y & 3) << 2);
                do { /* for all source pixels */
                        /* pre-compute intensity value for Black */
                        Black = ColorInt->colorByte[PCMBLACK];
                        ColorInt++; /* bump ptr for next time */

                        sx = *sxptr++;

                        /* dither and render pixel */
                        do { /* use this pixel 'sx' times */
                                /* if we should render Black */
                                if (Black > dmatrix[x & 3]) {
                                        /* set bit */
                                        *(ptr + (x >> 3)) |= bit_table[x & 7];
                                }
                                ++x; /* done 1 more printer pixel */
                        } while (--sx);
                } while (--width);
        }
}


Devices/Dev_examples/HP_Laserjet_printertag.asm

**********************************************************************
*
*       printer device dependent code tag
*
**********************************************************************

        SECTION         printer

*------ Included Files -----------------------------------------------

        INCLUDE         "exec/types.i"
        INCLUDE         "exec/nodes.i"
        INCLUDE         "exec/strings.i"

        INCLUDE         "hp_rev.i"

        INCLUDE         "devices/prtbase.i"

*------ Imported Names -----------------------------------------------

        XREF            _Init
        XREF            _Expunge
        XREF            _Open
        XREF            _Close
        XREF            _CommandTable
        XREF            _PrinterSegmentData
        XREF            _DoSpecial
        XREF            _Render
        XREF            _ExtendedCharTable
        XREF            _ConvFunc

*------ Exported Names -----------------------------------------------

        XDEF            _PEDData

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

                MOVEQ   #0,D0           ; show error for OpenLibrary()
                RTS
                DC.W    VERSION
                DC.W    REVISION
_PEDData:
                DC.L    printerName
                DC.L    _Init
                DC.L    _Expunge
                DC.L    _Open
                DC.L    _Close
                DC.B    PPC_BWGFX       ; PrinterClass
                DC.B    PCC_BW          ; ColorClass
                DC.B    0               ; MaxColumns
                DC.B    0               ; NumCharSets
                DC.W    1               ; NumRows
                DC.L    600             ; MaxXDots
                DC.L    795             ; MaxYDots
                DC.W    75              ; XDotsInch
                DC.W    75              ; YDotsInch
                DC.L    _CommandTable   ; Commands
                DC.L    _DoSpecial
                DC.L    _Render
                DC.L    30              ; Timeout
                DC.L    _ExtendedCharTable      ; 8BitChars
                DS.L    1               ; PrintMode (reserve space)
                DC.L    _ConvFunc       ; ptr to char conversion function

printerName:
                dc.b    'HP_LaserJet',0

                END


Devices/Dev_examples/HP_Laserjet_dospecial.c

/*
        DoSpecial for HP_LaserJet driver.
*/

#include "exec/types.h"
#include "devices/printer.h"
#include "devices/prtbase.h"

#define LPI             7
#define CPI             15
#define QUALITY         17
#define INIT_LEN        30
#define LPP             7
#define FORM_LEN        11
#define LEFT_MARG       3
#define RIGHT_MARG      7
#define MARG_LEN        12

DoSpecial(command, outputBuffer, vline, currentVMI, crlfFlag, Parms)
char outputBuffer[];
UWORD *command;
BYTE *vline;
BYTE *currentVMI;
BYTE *crlfFlag;
UBYTE Parms[];
{
        extern struct PrinterData *PD;
        extern struct PrinterExtendedData *PED;

        static UWORD textlength, topmargin;
        int x, y, j;
        static char initThisPrinter[INIT_LEN] =
                "\033&d@\033&l6D\033(s0b10h1q0p0s3t0u12V";
        static char initForm[FORM_LEN] = "\033&l002e000F";
        static char initMarg[MARG_LEN] = "\033&a000l000M\015";
        static char initTMarg[] = "\033&l000e000F";

        x = y = j = 0;

        if (*command == aRIN) {
                while(x < INIT_LEN) {
                        outputBuffer[x] = initThisPrinter[x];
                        x++;
                }
                outputBuffer[x++] = '\015';

                if (PD->pd_Preferences.PrintSpacing == EIGHT_LPI) {
                        outputBuffer[LPI] = '8';
                }

                if (PD->pd_Preferences.PrintPitch == ELITE) {
                        outputBuffer[CPI] = '2';
                }
                else if (PD->pd_Preferences.PrintPitch == FINE) {
                        outputBuffer[CPI] = '5';
                }

                if (PD->pd_Preferences.PrintQuality == LETTER) {
                        outputBuffer[QUALITY] = '2';
                }

                j = x; /* set the formlength = textlength, top margin = 2 */
                textlength = PD->pd_Preferences.PaperLength;
                topmargin = 2;

                while (y < FORM_LEN) {
                        outputBuffer[x++] = initForm[y++];
                }
                numberString(textlength, j + LPP, outputBuffer);

                Parms[0] = PD->pd_Preferences.PrintLeftMargin;
                Parms[1] = PD->pd_Preferences.PrintRightMargin;
                *command = aSLRM;
        }

        if (*command == aSLRM) {
                j = x;
                y = 0;
                while(y < MARG_LEN) {
                        outputBuffer[x++] = initMarg[y++];
                }
                numberString(Parms[0] - 1, j + LEFT_MARG, outputBuffer);
                numberString(Parms[1] - 1, j + RIGHT_MARG, outputBuffer);
                return(x);
        }

        if ((*command == aSUS2) && (*vline == 0)) {
                *command = aPLU;
                *vline = 1;
                return(0);
        }

        if ((*command == aSUS2) && (*vline < 0)) {
                *command = aRI;
                *vline = 1;
                return(0);
        }

        if ((*command == aSUS1) && (*vline > 0)) {
                *command = aPLD;
                *vline = 0;
                return(0);
        }

        if ((*command == aSUS4) && (*vline == 0)) {
                *command = aPLD;
                *vline = -1;
                return(0);
        }

        if ((*command == aSUS4) && (*vline > 0)) {
                *command = aIND;
                *vline = -1;
                return(0);
        }

        if ((*command == aSUS3) && (*vline < 0)) {
                *command = aPLU;
                *vline = 0;
                return(0);
        }

        if(*command == aSUS0) {
                if (*vline > 0) {
                        *command = aPLD;
                }
                if (*vline < 0) {
                        *command = aPLU;
                }
                *vline = 0;
                return(0);
        }

        if (*command == aPLU) {
                (*vline)++;
                return(0);
        }

        if (*command == aPLD){
                (*vline)--;
                return(0);
        }

        if (*command == aSTBM) {
                if (Parms[0] == 0) {
                        Parms[0] = topmargin;
                }
                else {
                        topmargin = --Parms[0];
                }

                if (Parms[1] == 0) {
                        Parms[1] = textlength;
                }
                else {
                        textlength=Parms[1];
                }
                while (x < 11) {
                        outputBuffer[x] = initTMarg[x];
                        x++;
                }
                numberString(Parms[0], 3, outputBuffer);
                numberString(Parms[1] - Parms[0], 7, outputBuffer);
                return(x);
        }

        if (*command == aSLPP) {
                while(x < 11) {
                        outputBuffer[x] = initForm[x];
                        x++;
                }
                /*restore textlength, margin*/
                numberString(topmargin, 3, outputBuffer);
                numberString(textlength, 7, outputBuffer);
                return(x);
        }

        if (*command == aRIS) {
                PD->pd_PWaitEnabled = 253;
        }

        return(0);
}

numberString(Param, x, outputBuffer)
UBYTE Param;
int x;
char outputBuffer[];
{
        if (Param > 199) {
                outputBuffer[x++] = '2';
                Param -= 200;
        }
        else if (Param > 99) {
                outputBuffer[x++] = '1';
                Param -= 100;
        }
        else {
                outputBuffer[x++] = '0'; /* always return 3 digits */
        }

        if (Param > 9) {
                outputBuffer[x++] = Param / 10 + '0';
        }
        else {
                outputBuffer[x++] = '0';
        }

        outputBuffer[x++] = Param % 10 + '0';
}

ConvFunc(buf, c, flag)
char *buf, c;
int flag; /* expand lf into lf/cr flag (0-yes, else no ) */
{
        if (c == '\014') { /* if formfeed (page eject) */
                PED->ped_PrintMode = 0; /* no data to print */
        }
        return(-1); /* pass all chars back to the printer device */
}

Close(ior)
struct printerIO *ior;
{
        if (PED->ped_PrintMode) { /* if data has been printed */
                (*(PD->pd_PWrite))("\014",1); /* eject page */
                (*(PD->pd_PBothReady))(); /* wait for it to finish */
                PED->ped_PrintMode = 0; /* no data to print */
        }
        return(0);
}


Devices/Dev_examples/HP_Laserjet_density.c

/*
        Density module for HP_LaserJet
*/

#include <exec/types.h>
#include <devices/printer.h>
#include <devices/prtbase.h>

SetDensity(density_code)
ULONG density_code;
{
        extern struct PrinterData *PD;
        extern struct PrinterExtendedData *PED;
        extern char StartCmd[];

        /* SPECIAL_DENSITY     0   1   2    3    4    5    6    7 */
        static int XDPI[8] = {75, 75, 100, 150, 300, 300, 300, 300};
        static char codes[8][3] = {
        {'0','7','5'},{'0','7','5'},{'1','0','0'},{'1','5','0'},
        {'3','0','0'},{'3','0','0'},{'3','0','0'},{'3','0','0'},
        };

        density_code /= SPECIAL_DENSITY1;
        PED->ped_MaxXDots = XDPI[density_code] * 8; /* 8 inches */

        /* default is 10.0, US_LEGAL is 14.0 */
        PED->ped_MaxYDots =
                PD->pd_Preferences.PaperSize == US_LEGAL ? 14 : 10;
        PED->ped_MaxYDots *= XDPI[density_code];

        PED->ped_XDotsInch = PED->ped_YDotsInch = XDPI[density_code];
        StartCmd[8] = codes[density_code][0];
        StartCmd[9] = codes[density_code][1];
        StartCmd[10] = codes[density_code][2];
}


Devices/Dev_examples/HP_Laserjet_rev.i

VERSION         EQU     35
REVISION        EQU     1


Devices/Dev_examples/HP_Laserjet_render.c

/*
        HP_LaserJet driver.
*/

#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/memory.h>
#include <devices/prtbase.h>
#include <devices/printer.h>

#define NUMSTARTCMD     7       /* # of cmd bytes before binary data */
#define NUMENDCMD       0       /* # of cmd bytes after binary data */
#define NUMTOTALCMD (NUMSTARTCMD + NUMENDCMD)   /* total of above */

extern SetDensity();
/*
        00-04   \033&l0L        perf skip mode off
        05-11   \033*t075R      set raster graphics resolution (dpi)
        12-16   \033*r0A        start raster graphics
*/
char StartCmd[18] = "\033&l0L\033*t075R\033*r0A";

Render(ct, x, y, status)
long ct, x, y, status;
{
        extern void *AllocMem(), FreeMem();

        extern struct PrinterData *PD;
        extern struct PrinterExtendedData *PED;

        static UWORD RowSize, BufSize, TotalBufSize, dataoffset;
        static UWORD huns, tens, ones; /* used to program buffer size */
        UBYTE *ptr, *ptrstart;
        int i, err;

        err=PDERR_NOERR;
        switch(status) {
                case 0 : /* Master Initialization */
                        /*
                                ct      - pointer to IODRPReq structure.
                                x       - width of printed picture in pixels.
                                y       - height of printed picture in pixels.
                        */
                        RowSize = (x + 7) / 8;
                        BufSize = RowSize + NUMTOTALCMD;
                        TotalBufSize = BufSize * 2;
                        PD->pd_PrintBuf = AllocMem(TotalBufSize, MEMF_PUBLIC);
                        if (PD->pd_PrintBuf == NULL) {
                                err = PDERR_BUFFERMEMORY; /* no mem */
                        }
                        else {
                                ptr = PD->pd_PrintBuf;
                                *ptr++ = 27;
                                *ptr++ = '*';
                                *ptr++ = 'b';   /* transfer raster graphics */
                                *ptr++ = huns | '0';
                                *ptr++ = tens | '0';
                                *ptr++ = ones | '0';    /* printout width */
                                *ptr = 'W';             /* terminator */
                                ptr = &PD->pd_PrintBuf[BufSize];
                                *ptr++ = 27;
                                *ptr++ = '*';
                                *ptr++ = 'b';   /* transfer raster graphics */
                                *ptr++ = huns | '0';
                                *ptr++ = tens | '0';
                                *ptr++ = ones | '0';    /* printout width */
                                *ptr = 'W';             /* terminator */
                                dataoffset = NUMSTARTCMD;
                        /* perf skip mode off, set dpi, start raster gfx */
                                err = (*(PD->pd_PWrite))(StartCmd, 17);
                        }
                        break;

                case 1 : /* Scale, Dither and Render */
                        /*
                                ct      - pointer to PrtInfo structure.
                                x       - 0.
                                y       - row # (0 to Height - 1).
                        */
                        Transfer(ct, y, &PD->pd_PrintBuf[dataoffset]);
                        err = PDERR_NOERR; /* all ok */
                        break;

                case 2 : /* Dump Buffer to Printer */
                        /*
                                ct      - 0.
                                x       - 0.
                                y       - # of rows sent (1 to NumRows).
                                White-space strip.
                        */
                        i = RowSize;
                        ptrstart = &PD->pd_PrintBuf[dataoffset - NUMSTARTCMD];
                        ptr = ptrstart + NUMSTARTCMD + i - 1;
                        while (i > 0 && *ptr == 0) {
                                i--;
                                ptr--;
                        }
                        ptr = ptrstart + 3; /* get ptr to density info */
                        *ptr++ = (huns = i / 100) | '0';
                        *ptr++ = (i - huns * 100) / 10 | '0';
                        *ptr = i % 10 | '0'; /* set printout width */
                        err = (*(PD->pd_PWrite))(ptrstart, i + NUMTOTALCMD);
                        if (err == PDERR_NOERR) {
                                dataoffset = (dataoffset == NUMSTARTCMD ?
                                        BufSize : 0) + NUMSTARTCMD;
                        }
                        break;

                case 3 : /* Clear and Init Buffer */
                        /*
                                ct      - 0.
                                x       - 0.
                                y       - 0.
                        */
                        ptr = &PD->pd_PrintBuf[dataoffset];
                        i = RowSize;
                        do {
                                *ptr++ = 0;
                        } while (--i);
                        break;

                case 4 : /* Close Down */
                        /*
                                ct      - error code.
                                x       - io_Special flag from IODRPReq struct
                                y       - 0.
                        */
                        err = PDERR_NOERR; /* assume all ok */
                        /* if user did not cancel the print */
                        if (ct != PDERR_CANCEL) {
                                /* end raster graphics, perf skip mode on */
                                if ((err = (*(PD->pd_PWrite))
                                        ("\033*rB\033&l1L", 9)) == PDERR_NOERR) {
                                        /* if want to unload paper */
                                        if (!(x & SPECIAL_NOFORMFEED)) {
                                                /* eject paper */
                                                err = (*(PD->pd_PWrite))
                                                        ("\014", 1);
                                        }
                                }
                        }
                        /*
                                flag that there is no alpha data waiting that
                                needs a formfeed (since we just did one)
                        */
                        PED->ped_PrintMode = 0;
                         /* wait for both buffers to empty */
                        (*(PD->pd_PBothReady))();
                        if (PD->pd_PrintBuf != NULL) {
                                FreeMem(PD->pd_PrintBuf, TotalBufSize);
                        }
                        break;

                case 5 : /* Pre-Master Initialization */
                        /*
                                ct      - 0 or pointer to IODRPReq structure.
                                x       - io_Special flag from IODRPReq struct
                                y       - 0.
                        */
                        /* select density */
                        SetDensity(x & SPECIAL_DENSITYMASK);
                        break;
        }
        return(err);
}


Devices/Dev_examples/Clipdemo.c

/*
 * Clipdemo.c
 *
 * Demonstrate use of clipboard I/O.  Uses general functions
 * provided in cbio.c
 *
 * Compile with SAS C 5.10: LC -b1 -cfistq -v -y -L+cbio.o
 *
 * Run from CLI only
 */

#include <exec/types.h>
#include <exec/ports.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <devices/clipboard.h>
#include <libraries/dosextens.h>
#include <libraries/dos.h>

#include "cb.h"

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

#define FORGETIT 0
#define READIT   1
#define WRITEIT  2
#define POSTIT   3

/* prototypes */

int ReadClip( void );           /* Demonstrate reading clipboard data    */
int WriteClip( char * );        /* Demonstrate write to clipboard        */
int PostClip( char * );         /* Demonstrate posting data to clipboard */

void main( USHORT, char **);

char message[] = "\
\nPossible switches are:\n\n\
-r            Read, and output contents of clipboard.\n\
-w [string]   Write string to clipboard.\n\n\
-p [string]   Write string to clipboard using the clipboard POST mechanism.\n\n\
              The Post can be satisfied by reading data from\n\
              the clipboard.  Note that the message may never\n\
              be received if some other application posts, or\n\
              performs an immediate write to the clipboard.\n\n\
              To run this test you must run two copies of this example.\n\
              Use the -p switch with one to post data, and the -r switch\n\
              with another to read the data.\n\n\
              The process can be stopped by using the BREAK command,\n\
              in which case this example checks the CLIP write ID\n\
              to determine if it should write to the clipboard before\n\
              exiting.\n\n";

void main(argc,argv)
USHORT argc;
char **argv;
{

int todo;
char *string;

todo = FORGETIT;

if (argc)     /* from CLI ? */
    {

    /* Very simple code to parse for arguments - will suffice for
     * the sake of this example
     */

    if (argc > 1)
       {
       if (!(strcmp(argv[1],"-r")))
           todo = READIT;
       if (!(strcmp(argv[1],"-w")))
           todo = WRITEIT;
       if (!(strcmp(argv[1],"-p")))
           todo = POSTIT;

       string = NULL;

       if (argc > 2)
           string=argv[2];

       }

    switch (todo)
            {

            case READIT:

                 ReadClip();
                 break;

            case POSTIT:

                 PostClip(string);
                 break;

            case WRITEIT:

                 WriteClip(string);
                 break;

            default:

                 printf("%s",message);
                 break;

            }
    }
}

/*
 * Read, and output FTXT in the clipboard.
 *
 */

ReadClip()
{
struct IOClipReq *ior;
struct cbbuf *buf;

/* Open clipboard.device unit 0 */

if (ior=CBOpen(0L))
    {

    /* Look for FTXT in clipboard */

    if (CBQueryFTXT(ior))
        {

        /* Obtain a copy of the contents of each CHRS chunk */

        while (buf=CBReadCHRS(ior))
              {
              /* Process data */

              printf("%s\n",buf->mem);

              /* Free buffer allocated by CBReadCHRS() */

              CBFreeBuf(buf);
              }

        /* The next call is not really needed if you are sure */
        /* you read to the end of the clip.                   */

        CBReadDone(ior);
        }
    else
        {
        puts("No FTXT in clipboard");
        }

    CBClose(ior);
    }

else
    {
    puts("Error opening clipboard unit 0");
    }

return(0L);
}

/*
 * Write a string to the clipboard
 *
 */

WriteClip(string)
char *string;
{

struct IOClipReq *ior;

if (string == NULL)
    {
    puts("No string argument given");
    return(0L);
    }

/* Open clipboard.device unit 0 */

if (ior = CBOpen(0L))
    {
    if (!(CBWriteFTXT(ior,string)))
        {
        printf("Error writing to clipboard: io_Error = %ld\n",ior->io_Error);
        }
    CBClose(ior);
    }
else
    {
    puts("Error opening clipboard.device");
    }

return(0);
}

/*
 * Write a string to the clipboard using the POST mechanism
 *
 * The POST mechanism can be used by applications which want to
 * defer writing text to the clipboard until another application
 * needs it (by attempting to read it via CMD_READ).  However
 * note that you still need to keep a copy of the data until you
 * receive a SatisfyMsg from the clipboard.device, or your program
 * exits.
 *
 * In most cases it is easier to write the data immediately.
 *
 * If your program receives the SatisfyMsg from the clipboard.device,
 * you MUST write some data.  This is also how you reply to the message.
 *
 * If your program wants to exit before it has received the SatisfyMsg,
 * you must check the io_ClipID field at the time of the post against
 * the current post ID which is obtained by sending the CBD_CURRENTWRITEID
 * command.
 *
 * If the value in io_ClipID (returned by CBD_CURRENTWRITEID) is greater
 * than your post ID, it means that some other application has performed
 * a post, or immediate write after your post, and that you're application
 * will never receive the SatisfyMsg.
 *
 * If the value in io_ClipID (returned by CBD_CURRENTWRITEID) is equal
 * to your post ID, then you must write your data, and send CMD_UPDATE
 * before exiting.
 *
 */

PostClip(string)
char *string;
{

struct MsgPort *satisfy;
struct SatisfyMsg *sm;
struct IOClipReq *ior;
int mustwrite;
ULONG postID;

if (string == NULL)
    {
    puts("No string argument given");
    return(0L);
    }

if (satisfy = CreatePort(0L,0L))
    {

    /* Open clipboard.device unit 0 */

    if (ior = CBOpen(0L))
        {
        mustwrite = FALSE;

        /* Notify clipboard we have data */

        ior->io_Data    = (STRPTR)satisfy;
        ior->io_ClipID  = 0L;
        ior->io_Command = CBD_POST;
        DoIO( (struct IORequest *) ior);

        postID = ior->io_ClipID;

        printf("\nClipID = %ld\n",postID);

        /* Wait for CTRL-C break, or message from clipboard */
        Wait(SIGBREAKF_CTRL_C|(1L << satisfy->mp_SigBit));

        /* see if we got a message, or a break */
        puts("Woke up");

        if (sm = (struct SatisfyMsg *)GetMsg(satisfy))
            {
            puts("Got a message from the clipboard\n");

            /* We got a message - we MUST write some data */
            mustwrite = TRUE;
            }
        else
            {
            /* Determine if we must write before exiting by
             * checking to see if our POST is still valid
             */

            ior->io_Command = CBD_CURRENTWRITEID;
            DoIO( (struct IORequest *) ior);

            printf("CURRENTWRITEID = %ld\n",ior->io_ClipID);

            if (postID >= ior->io_ClipID)
                mustwrite = TRUE;

            }

        /* Write the string of text */

        if (mustwrite)
            {
            if (!(CBWriteFTXT(ior,string)))
                puts("Error writing to clipboard");
            }
        else
            {
            puts("No need to write to clipboard");
            }

        CBClose(ior);
        }
    else
        {
        puts("Error opening clipboard.device");
        }

    DeletePort(satisfy);
    }
else
    {
    puts("Error creating message port");
    }

return(0);
}

/*
 * Changehook_Test.c
 *
 * Demonstrate the use of CBD_CHANGEHOOK command.
 * The program will set a hook and wait for the clipboard data to change.
 * You must put something in the clipboard in order for it to return.
 *
 * Compile with SAS C 5.10: LC -cfist -v -y -L+Hookface.o+cbio.o
 *
 * Requires Kickstart 36 or greater.
 *
 * Run from CLI only
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/ports.h>
#include <exec/tasks.h>
#include <exec/io.h>
#include <devices/clipboard.h>
#include <dos/dos.h>
#include <utility/hooks.h>
#include "cb.h"

#include <clib/macros.h>
#include <clib/alib_protos.h>
#include <clib/exec_protos.h>

#include <stdio.h>
#include <string.h>

LONG version = 1L;

extern ULONG SysBase, DOSBase;

/* Data to pass around with the clipHook */
struct CHData
{
    struct Task *ch_Task;
    LONG ch_ClipID;
};

struct MsgPort *clip_port;
struct Hook hook;
struct CHData ch;

ULONG clipHook (struct Hook * h, VOID * o, struct ClipHookMsg * msg)
{
struct CHData *ch = (struct CHData *) h->h_Data;

if (ch)
   {
   /* Remember the ID of clip */
   ch->ch_ClipID = msg->chm_ClipID;

   /* Signal the task that started the hook */
   Signal (ch->ch_Task, SIGBREAKF_CTRL_E);
   }

return (0);
}

struct IOClipReq *OpenCB (LONG unit)
{
struct IOClipReq *clipIO;

/* Open clipboard unit 0 */

if (clipIO = CBOpen( 0L ))
    {
    ULONG hookEntry ();

    /* Fill out the IORequest */
    clipIO->io_Data = (char *) &hook;
    clipIO->io_Length = 1;
    clipIO->io_Command = CBD_CHANGEHOOK;

    /* Set up the hook data */
    ch.ch_Task = FindTask (NULL);

    /* Prepare the hook */
    hook.h_Entry = hookEntry;
    hook.h_SubEntry = clipHook;
    hook.h_Data = &ch;

    /* Start the hook */
    if (DoIO (clipIO))
        printf ("unable to set hook\n");
    else
        printf ("hook set\n");

    /* Return success */
    return ( clipIO );
    }

/* return failure */
return (NULL);
}

void CloseCB (struct IOClipReq *clipIO)
{

/* Fill out the IO request */
clipIO->io_Data = (char *) &hook;
clipIO->io_Length = 0;
clipIO->io_Command = CBD_CHANGEHOOK;

    /* Stop the hook */
if (DoIO (clipIO))
    printf ("unable to stop hook\n");
else
    /* Indicate success */
    printf ("hook is stopped\n");

CBClose(clipIO);
}

main (int argc, char **argv)
{
struct IOClipReq *clipIO;

ULONG sig_rcvd;

printf ("Test v%ld\n", version);

if (clipIO=OpenCB (0L))
    {
    sig_rcvd = Wait ((SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_E));

    if (sig_rcvd & SIGBREAKF_CTRL_C)
        printf ("^C received\n");

    if (sig_rcvd & SIGBREAKF_CTRL_E)
        printf ("clipboard change, current ID is %ld\n", ch.ch_ClipID);

    CloseCB(clipIO);
    }
}


Devices/Dev_examples/Cbio.c

/* Cbio.c
 *
 * Provide standard clipboard device interface routines
 *            such as Open, Close, Post, Read, Write, etc.
 *
 * Compile with SAS C 5.10: LC -b1 -cfistq -v -y
 *
 *  NOTE - These functions are useful for writing, and reading simple
 *         FTXT.  Writing, and reading complex FTXT, ILBM, etc.,
 *         requires more work - under 2.0 it is highly recommended that
 *         you use iffparse.library.
 */

#include <exec/types.h>
#include <exec/ports.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <devices/clipboard.h>

#define CBIO 1

#include "cb.h"

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

/****** cbio/CBOpen *************************************************
*
*   NAME
*       CBOpen() - Open the clipboard.device
*
*   SYNOPSIS
*       ior = CBOpen(unit)
*
*       struct IOClipReq *CBOpen( ULONG )
*
*   FUNCTION
*       Opens the clipboard.device.  A clipboard unit number
*       must be passed in as an argument.  By default, the unit
*       number should be 0 (currently valid unit numbers are
*       0-255).
*
*   RESULTS
*       A pointer to an initialized IOClipReq structure, or
*       a NULL pointer if the function fails.
*
*********************************************************************/

struct IOClipReq *CBOpen(unit)
ULONG unit;
{
struct MsgPort *mp;
struct IOStdReq *ior;

if (mp = CreatePort(0L,0L))
    {
    if (ior=CreateExtIO(mp,sizeof(struct IOClipReq)))
        {
        if (!(OpenDevice("clipboard.device",unit,ior,0L)))
            {
            return((struct IOClipReq *)ior);
            }
        DeleteExtIO(ior);
        }
    DeletePort(mp);
    }
return(NULL);

}

/****** cbio/CBClose ************************************************
*
*   NAME
*       CBClose() - Close the clipboard.device
*
*   SYNOPSIS
*       CBClose()
*
*       void CBClose()
*
*   FUNCTION
*       Close the clipboard.device unit which was opened via
*       CBOpen().
*
*********************************************************************/

void CBClose(ior)
struct IOClipReq *ior;
{
struct MsgPort *mp;

mp = ior->io_Message.mn_ReplyPort;

CloseDevice((struct IOStdReq *)ior);
DeleteExtIO((struct IOStdReq *)ior);
DeletePort(mp);

}

/****** cbio/CBWriteFTXT *********************************************
*
*   NAME
*       CBWriteFTXT() - Write a string of text to the clipboard.device
*
*   SYNOPSIS
*       success = CBWriteFTXT( ior, string)
*
*       int CBWriteFTXT(struct IOClipReq *, char *)
*
*   FUNCTION
*       Write a NULL terminated string of text to the clipboard.
*       The string will be written in simple FTXT format.
*
*       Note that this function pads odd length strings automatically
*       to conform to the IFF standard.
*
*   RESULTS
*       TRUE if the write succeeded, else FALSE.
*
*********************************************************************/

int CBWriteFTXT(ior,string)
struct IOClipReq *ior;
char *string;
{

ULONG length, slen;
BOOL odd;
int success;

slen = strlen(string);
odd = (slen & 1);               /* pad byte flag */

length = (odd) ? slen+1 : slen;

/* initial set-up for Offset, Error, and ClipID */

ior->io_Offset = 0;
ior->io_Error  = 0;
ior->io_ClipID = 0;

/* Create the IFF header information */

WriteLong(ior, (long *) "FORM");     /* "FORM"             */
length+=12L;                         /* + "[size]FTXTCHRS" */
WriteLong(ior, &length);             /* total length       */
WriteLong(ior, (long *) "FTXT");     /* "FTXT"             */
WriteLong(ior, (long *) "CHRS");     /* "CHRS"             */
WriteLong(ior, &slen);               /* string length      */

/* Write string */
ior->io_Data    = (STRPTR)string;
ior->io_Length  = slen;
ior->io_Command = CMD_WRITE;
DoIO( (struct IORequest *) ior);

/* Pad if needed */
if (odd)
    {
    ior->io_Data   = (STRPTR)"";
    ior->io_Length = 1L;
    DoIO( (struct IORequest *) ior);
    }

/* Tell the clipboard we are done writing */

ior->io_Command=CMD_UPDATE;
DoIO( (struct IORequest *) ior);

/* Check if io_Error was set by any of the preceding IO requests */
success = ior->io_Error ? FALSE : TRUE;

return(success);
}

WriteLong(ior, ldata)
struct IOClipReq *ior;
long *ldata;
{

ior->io_Data    = (STRPTR)ldata;
ior->io_Length  = 4L;
ior->io_Command = CMD_WRITE;
DoIO( (struct IORequest *) ior);

if (ior->io_Actual == 4)
    {
    return( ior->io_Error ? FALSE : TRUE);
    }

return(FALSE);

}

/****** cbio/CBQueryFTXT **********************************************
*
*   NAME
*       CBQueryFTXT() - Check to see if clipboard contains FTXT
*
*   SYNOPSIS
*       result = CBQueryFTXT( ior )
*
*       int CBQueryFTXT(struct IOClipReq *)
*
*   FUNCTION
*       Check to see if the clipboard contains FTXT.  If so,
*       call CBReadCHRS() one or more times until all CHRS
*       chunks have been read.
*
*   RESULTS
*       TRUE if the clipboard contains an FTXT chunk, else FALSE.
*
*   NOTES
*       If this function returns TRUE, you must either call
*       CBReadCHRS() until CBReadCHRS() returns FALSE, or
*       call CBReadDone() to tell the clipboard.device that
*       you are done reading.
*
*
*********************************************************************/

int CBQueryFTXT(ior)
struct IOClipReq *ior;
{
ULONG cbuff[4];

/* initial set-up for Offset, Error, and ClipID */

ior->io_Offset = 0;
ior->io_Error  = 0;
ior->io_ClipID = 0;

/* Look for "FORM[size]FTXT" */

ior->io_Command = CMD_READ;
ior->io_Data    = (STRPTR)cbuff;
ior->io_Length  = 12;

DoIO( (struct IORequest *) ior);

/* Check to see if we have at least 12 bytes */

if (ior->io_Actual == 12L)
    {
    /* Check to see if it starts with "FORM" */
    if (cbuff[0] == ID_FORM)
        {
        /* Check to see if its "FTXT" */
        if (cbuff[2] == ID_FTXT)
            return(TRUE);
        }

    /* It's not "FORM[size]FTXT", so tell clipboard we are done */
    }

CBReadDone(ior);

return(FALSE);
}

/****** cbio/CBReadCHRS **********************************************
*
*   NAME
*       CBReadCHRS() - Reads the next CHRS chunk from clipboard
*
*   SYNOPSIS
*       cbbuf = CBReadCHRS( ior )
*
*       struct cbbuf *CBReadCHRS(struct IOClipReq * )
*
*   FUNCTION
*       Reads and returns the text in the next CHRS chunk
*       (if any) from the clipboard.
*
*       Allocates memory to hold data in next CHRS chunk.
*
*   RESULTS
*       Pointer to a cbbuf struct (see cb.h), or a NULL indicating
*       a failure (e.g., not enough memory, or no more CHRS chunks).
*
*       ***Important***
*
*       The caller must free the returned buffer when done with the
*       data by calling CBFreeBuf().
*
*   NOTES
*       This function strips NULL bytes, however, a full reader may
*       wish to perform more complete checking to verify that the
*       text conforms to the IFF standard (stripping data as required).
*
*       Under 2.0, the AllocVec() function could be used instead of
*       AllocMem() in which case the cbbuf structure may not be
*       needed.
*
*********************************************************************/

struct cbbuf *CBReadCHRS(ior)
struct IOClipReq *ior;
{
ULONG chunk,size;
struct cbbuf *buf;
int looking;

/* Find next CHRS chunk */

looking = TRUE;
buf = NULL;

while (looking)
      {
      looking = FALSE;

      if (ReadLong(ior,&chunk))
          {
          /* Is CHRS chunk ? */
          if (chunk == ID_CHRS)
              {
              /* Get size of chunk, and copy data */
              if (ReadLong(ior,&size))
                  {
                  if (size)
                      buf=FillCBData(ior,size);
                  }
              }

            /* If not, skip to next chunk */
          else
              {
              if (ReadLong(ior,&size))
                  {
                   looking = TRUE;
                   if (size & 1)
                       size++;    /* if odd size, add pad byte */

                    ior->io_Offset += size;
                  }
              }
          }
      }

if (buf == NULL)
    CBReadDone(ior);        /* tell clipboard we are done */

return(buf);
}

ReadLong(ior, ldata)
struct IOClipReq *ior;
ULONG *ldata;
{
ior->io_Command = CMD_READ;
ior->io_Data    = (STRPTR)ldata;
ior->io_Length  = 4L;

DoIO( (struct IORequest *) ior);

if (ior->io_Actual == 4)
    {
    return( ior->io_Error ? FALSE : TRUE);
    }

return(FALSE);
}

struct cbbuf *FillCBData(ior,size)
struct IOClipReq *ior;
ULONG size;
{
register UBYTE *to,*from;
register ULONG x,count;

ULONG length;
struct cbbuf *buf,*success;

success = NULL;

if (buf = AllocMem(sizeof(struct cbbuf),MEMF_PUBLIC))
    {

    length = size;
    if (size & 1)
        length++;            /* if odd size, read 1 more */

    if (buf->mem = AllocMem(length+1L,MEMF_PUBLIC))
        {
        buf->size = length+1L;

        ior->io_Command = CMD_READ;
        ior->io_Data    = (STRPTR)buf->mem;
        ior->io_Length  = length;

        to = buf->mem;
        count = 0L;

        if (!(DoIO( (struct IOStdReq *) ior)))
            {
            if (ior->io_Actual == length)
                {
                success = buf;      /* everything succeeded */

                /* strip NULL bytes */
                for (x=0, from=buf->mem ;x<size;x++)
                     {
                     if (*from)
                         {
                         *to = *from;
                         to++;
                         count++;
                         }

                     from++;
                     }
                *to=0x0;            /* Null terminate buffer */
                buf->count = count; /* cache count of chars in buf */
                }
            }

        if (!(success))
            FreeMem(buf->mem,buf->size);
        }
    if (!(success))
        FreeMem(buf,sizeof(struct cbbuf));
    }

return(success);
}

/****** cbio/CBReadDone **********************************************
*
*   NAME
*       CBReadDone() - Tell clipboard we are done reading
*
*   SYNOPSIS
*       CBReadDone( ior )
*
*       void CBReadDone(struct IOClipReq * )
*
*   FUNCTION
*       Reads past end of clipboard file until io_Actual is equal to 0.
*       This is tells the clipboard that we are done reading.
*
*********************************************************************/

void CBReadDone(ior)
struct IOClipReq *ior;
{
char buffer[256];

ior->io_Command = CMD_READ;
ior->io_Data    = (STRPTR)buffer;
ior->io_Length  = 254;

/* falls through immediately if io_Actual == 0 */

while (ior->io_Actual)
      {
      if (DoIO( (struct IORequest *) ior))
          break;
      }
}

/****** cbio/CBFreeBuf **********************************************
*
*   NAME
*       CBFreeBuf() - Free buffer allocated by CBReadCHRS()
*
*   SYNOPSIS
*       CBFreeBuf( buf )
*
*       void CBFreeBuf( struct cbbuf * )
*
*   FUNCTION
*       Frees a buffer allocated by CBReadCHRS().
*
*********************************************************************/

void CBFreeBuf(buf)
struct cbbuf *buf;
{
FreeMem(buf->mem, buf->size);
FreeMem(buf, sizeof(struct cbbuf));
}

*************************************************************************
*        Hookface.asm
*        assembly routines for Chtest
*
*        Assemble with Adapt  hx68 hookface.a to hookface.o
*        Link with Changehook_Test.o as shown in Changehook_Test.c header
*
*************************************************************************
        INCDIR  'include:'
        INCLUDE 'exec/types.i'
        INCLUDE 'utility/hooks.i'
        xdef    _callHook
        xdef    _callHookPkt
        xdef    _hookEntry
        xdef    _stubReturn
*************************************************************************
* new hook standard
* use struct Hook (with minnode at the top)
*
* *** register calling convention: ***
*       A0 - pointer to hook itself
*       A1 - pointer to parameter packed ("message")
*       A2 - Hook specific address data ("object," e.g, gadget )
*
* ***  C conventions: ***
* Note that parameters are in unusual register order: a0, a2, a1.
* This is to provide a performance boost for assembly language
* programming (the object in a2 is most frequently untouched).
* It is also no problem in "register direct" C function parameters.
*
* calling through a hook
*       callHook( hook, object, msgid, p1, p2, ... );
*       callHookPkt( hook, object, msgpkt );
*
* using a C function:   CFunction( hook, object, message );
*       hook.h_Entry = hookEntry;
*       hook.h_SubEntry = CFunction;
*************************************************************************
* C calling hook interface for prepared message packet
_callHookPkt:
        movem.l a2/a6,-(sp)     ; protect
        move.l  12(sp),a0       ; hook
        move.l  16(sp),a2       ; object
        move.l  20(sp),a1       ; message
        ; ------ now have registers ready, invoke function
        pea.l   hreturn(pc)
        move.l  h_Entry(a0),-(sp)       ; old rts-jump trick
        rts
hreturn:
        movem.l (sp)+,a2/a6
        rts

* C calling hook interface for "varargs message packet"
_callHook:
        movem.l a2/a6,-(sp)     ; protect
        move.l  12(sp),a0       ; hook
        move.l  16(sp),a2       ; object
        lea.l   20(sp),a1       ; message
        ; ------ now have registers ready, invoke function
        pea.l   hpreturn(pc)
        move.l  h_Entry(a0),-(sp)       ; old rts-jump trick
        rts
hpreturn:
        movem.l (sp)+,a2/a6
        rts

* entry interface for C code (large-code, stack parameters)
_hookEntry:
        move.l  a1,-(sp)
        move.l  a2,-(sp)
        move.l  a0,-(sp)
        move.l  h_SubEntry(a0),a0       ; C entry point
        jsr     (a0)
        lea     12(sp),sp
_stubReturn:
        rts


Devices/Dev_examples/cb.h

/***********************************************************************
 *
 * cb.h - Include file used by clipdemo.c, changehook_test.c and cbio.c
 *
 ***********************************************************************/

struct cbbuf {

        ULONG size;     /* size of memory allocation            */
        ULONG count;    /* number of characters after stripping */
        UBYTE *mem;     /* pointer to memory containing data    */
};

#define MAKE_ID(a,b,c,d) ((a<<24L) | (b<<16L) | (c<<8L) | d)

#define ID_FORM MAKE_ID('F','O','R','M')
#define ID_FTXT MAKE_ID('F','T','X','T')
#define ID_CHRS MAKE_ID('C','H','R','S')

#ifdef CBIO

/* prototypes */

struct IOClipReq        *CBOpen         ( ULONG );
void                    CBClose         (struct IOClipReq *);
int                     CBWriteFTXT     (struct IOClipReq *, char *);
int                     CBQueryFTXT     (struct IOClipReq *);
struct cbbuf            *CBReadCHRS     (struct IOClipReq *);
void                    CBReadDone      (struct IOClipReq *);
void                    CBFreeBuf       (struct cbbuf *);

/* routines which are meant to be used internally by routines in cbio */

int                     WriteLong       (struct IOClipReq *, long *);
int                     ReadLong        (struct IOClipReq *, ULONG *);
struct cbbuf            *FillCBData     (struct IOClipReq *, ULONG);

#else

/* prototypes */

extern struct IOClipReq *CBOpen         ( ULONG );
extern void             CBClose         (struct IOClipReq *);
extern int              CBWriteFTXT     (struct IOClipReq *, char *);
extern int              CBQueryFTXT     (struct IOClipReq *);
extern struct cbbuf     *CBReadCHRS     (struct IOClipReq *);
extern void             CBReadDone      (struct IOClipReq *);
extern void             CBFreeBuf       (struct cbbuf *);

#endif


Devices/Dev_examples/SCSI_Direct.c

/*
 * SCSI_Direct.c
 *
 * The following program demonstrates the use of the HD_SCSICmd to send a
 * MODE SENSE to a unit on the requested device (default scsi.device).  This
 * code can be easily modified to send other commands to the drive.
 *
 * Compile with SAS C 5.10  lc -b1 -cfistq -v -y -L
 *
 * Run from CLI only
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/io.h>
#include <devices/scsidisk.h>
#include <dos/dosextens.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>

#include <stdlib.h>
#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

#define BUFSIZE 256

UBYTE *buffer;                  /* a data buffer used for mode sense data */
struct IOStdReq SCSIReq;        /* a standard IORequest structure */
struct SCSICmd Cmd;             /* where the actual SCSI command goes */
UBYTE  Sense[20];               /* buffer for request sense data */
struct MsgPort Port;            /* our ReplyPort */

void ShowSenseData(void);

static UBYTE TestReady[] = { 0,0,0,0,0,0 };     /* not used but here for  */
static UBYTE StartUnit[] = { 0x1b,0,0,0,1,0 };  /* illustration of other  */
static UBYTE StopUnit[] =  { 0x1b,0,0,0,0,0 };  /* commands.              */

static UBYTE ModeSense[]={ 0x1a,0,0xff,0,254,0 }; /* the command being sent */

void main(int argc, char **argv)
{
int unit,tval,i;
char *dname = "scsi.device";
UBYTE *tbuf;

if ((argc < 2) || (argc > 3))
    {
    printf("Usage: %s unit [xxxx.device]\n",argv[0]);
    exit(100);
    }

unit = atoi( argv[1] );
if (argc == 3)
    dname = argv[2];

buffer = (UBYTE *) AllocMem(BUFSIZE, MEMF_PUBLIC|MEMF_CLEAR);

if (!buffer)
    {
    printf("Couldn't get memory\n");
    exit(100);
    }

Port.mp_Node.ln_Pri = 0;                        /* setup the ReplyPort */
Port.mp_SigBit      = AllocSignal(-1);
Port.mp_SigTask     = (struct Task *)FindTask(0);
NewList( &(Port.mp_MsgList) );

SCSIReq.io_Message.mn_ReplyPort = &Port;

if (OpenDevice( dname, unit, &SCSIReq, 0))
    {
    printf("Couldn't open unit %ld on %s\n",unit,dname);
    FreeMem( buffer,BUFSIZE );
    exit(100);
    }

SCSIReq.io_Length  = sizeof(struct SCSICmd);
SCSIReq.io_Data    = (APTR)&Cmd;
SCSIReq.io_Command = HD_SCSICMD;        /* the command we are sending   */

Cmd.scsi_Data = (UWORD *)buffer;        /* where we put mode sense data */
Cmd.scsi_Length = 254;          /* how much we will accept      */
Cmd.scsi_CmdLength = 6;         /* length of the command        */
Cmd.scsi_Flags = SCSIF_AUTOSENSE|SCSIF_READ;
                                /* do automatic REQUEST_SENSE   */
                                /* set expected data direction  */
Cmd.scsi_SenseData =(UBYTE *)Sense;     /* where sense data will go     */
Cmd.scsi_SenseLength = 18;              /* how much we will accept      */
Cmd.scsi_SenseActual = 0;               /* how much has been received   */

Cmd.scsi_Command=(UBYTE *)ModeSense;/* issuing a MODE_SENSE command     */
DoIO( &SCSIReq );                       /* send it to the device driver */

if (Cmd.scsi_Status)
    ShowSenseData();      /* if bad status then show it */

else
    {
    printf("\nBlock descriptor header\n");
    printf("=======================\n");
    printf("Mode Sense data length  = %d\n",(short)buffer[0]);
    printf("Block descriptor length = %d\n",(short)buffer[3]);
    tbuf = &buffer[4];
    printf("Density code            = %d\n",(short)tbuf[0]);
    tval = (tbuf[1]<<16) + (tbuf[2]<<8) + tbuf[3];
    printf("Number of blocks        = %ld\n",tval);
    tval = (tbuf[5]<<16) + (tbuf[6]<<8) + tbuf[7];
    printf("Block size              = %ld\n",tval);

    tbuf += buffer[3];          /* move to page descriptors */

    while ((tbuf - buffer) < buffer[0])
           {

           switch (tbuf[0] & 0x7f)
                   {
                   case 1:
                          printf("\nError Recovery Parameters\n");
                          printf("=========================\n");
                          printf("Page length             = %d\n",(short)tbuf[1]);
                          printf("DISABLE CORRECTION      = %d\n",(short)tbuf[2]&1);
                          printf("DISABLE XFER ON ERROR   = %d\n",(short)(tbuf[2]>>1)&1);
                          printf("POST ERROR              = %d\n",(short)(tbuf[2]>>2)&1);
                          printf("ENABLE EARLY CORRECTION = %d\n",(short)(tbuf[2]>>3)&1);
                          printf("READ CONTINUOUS         = %d\n",(short)(tbuf[2]>>4)&1);
                          printf("TRANSFER BLOCK          = %d\n",(short)(tbuf[2]>>5)&1);
                          printf("AUTO READ REALLOCATION  = %d\n",(short)(tbuf[2]>>6)&1);
                          printf("AUTO WRITE REALLOCATION = %d\n",(short)(tbuf[2]>>7)&1);
                          printf("Retry count             = %d\n",(short)tbuf[3]);
                          printf("Correction span         = %d\n",(short)tbuf[4]);
                          printf("Head offset count       = %d\n",(short)tbuf[5]);
                          printf("Data strobe offset count= %d\n",(short)tbuf[6]);
                          printf("Recovery time limit     = %d\n",(short)tbuf[7]);

                          tbuf += tbuf[1]+2;
                          break;

                   case 2:
                          printf("\nDisconnect/Reconnect Control\n");
                          printf("============================\n");
                          printf("Page length             = %d\n",(short)tbuf[1]);
                          printf("Buffer full ratio       = %d\n",(short)tbuf[2]);
                          printf("Buffer empty ratio      = %d\n",(short)tbuf[3]);
                          tval = (tbuf[4]<<8)+tbuf[5];
                          printf("Bus inactivity limit    = %d\n",tval);
                          tval = (tbuf[6]<<8)+tbuf[7];
                          printf("Disconnect time limit   = %d\n",tval);
                          tval = (tbuf[8]<<8)+tbuf[9];
                          printf("Connect time limit      = %d\n",tval);
                          tval = (tbuf[10]<<8)+tbuf[11];
                          printf("Maximum burst size      = %d\n",tval);
                          printf("Disable disconnection   = %d\n",(short)tbuf[12]&1);

                          tbuf += tbuf[1]+2;
                          break;

                   case 3:
                          printf("\nDevice Format Parameters\n");
                          printf("========================\n");
                          printf("Page length             = %d\n",(short)tbuf[1]);
                          tval = (tbuf[2]<<8)+tbuf[3];
                          printf("Tracks per zone         = %d\n",tval);
                          tval = (tbuf[4]<<8)+tbuf[5];
                          printf("Alternate sectors/zone  = %d\n",tval);
                          tval = (tbuf[6]<<8)+tbuf[7];
                          printf("Alternate tracks/zone   = %d\n",tval);
                          tval = (tbuf[8]<<8)+tbuf[9];
                          printf("Alternate tracks/volume = %d\n",tval);
                          tval = (tbuf[10]<<8)+tbuf[11];
                          printf("Sectors per track       = %d\n",tval);
                          tval = (tbuf[12]<<8)+tbuf[13];
                          printf("Bytes per sector        = %d\n",tval);
                          tval = (tbuf[14]<<8)+tbuf[15];
                          printf("Interleave              = %d\n",tval);
                          tval = (tbuf[16]<<8)+tbuf[17];
                          printf("Track skew factor       = %d\n",tval);
                          tval = (tbuf[18]<<8)+tbuf[19];
                          printf("Cylinder skew factor    = %d\n",tval);

                          tbuf += tbuf[1]+2;
                          break;

                   case 4:
                          printf("\nDrive Geometry Parameters\n");
                          printf("=========================\n");
                          printf("Page length             = %d\n",(short)tbuf[1]);
                          tval = (tbuf[2]<<16)+(tbuf[3]<<8)+tbuf[4];
                          printf("Number of cylinders     = %ld\n",tval);
                          printf("Number of heads         = %d\n",(short)tbuf[5]);
                          tval = (tbuf[6]<<16)+(tbuf[6]<<8)+tbuf[8];
                          printf("Start write precomp     = %ld\n",tval);
                          tval = (tbuf[9]<<16)+(tbuf[10]<<8)+tbuf[11];
                          printf("Start reduced write     = %ld\n",tval);
                          tval = (tbuf[12]<<8)+tbuf[13];
                          printf("Drive step rate         = %d\n",tval);
                          tval = (tbuf[14]<<16)+(tbuf[15]<<8)+tbuf[16];
                          printf("Landing zone cylinder   = %ld\n",tval);

                          tbuf += tbuf[1]+2;
                          break;

                   default:
                           printf("\nVendor Unique Page Code %2x\n",(short)tbuf[0]);
                           printf("==========================\n");
                           for (i=0; i<=tbuf[1]+1; i++ )
                                printf("%x ",(short)tbuf[i]);

                           printf("\n");
                           tbuf += tbuf[1]+2;
                   }
           }
    }

CloseDevice( &SCSIReq );
FreeMem( buffer, BUFSIZE );
FreeSignal(Port.mp_SigBit);
}

void ShowSenseData(void)
{
int i;

for (i=0; i<18; i++)
     printf("%x ",(int)Sense[i]);

printf("\n");
}


Devices/Dev_examples/Console.c

/*
 * Console.c
 *
 * Example of opening a window and using the console device
 * to send text and control sequences to it.  The example can be
 * easily modified to do additional control sequences.
 *
 * Compile with SAS C 5.10: LC -b1 -cfistq -v -y -L
 *
 * Run from CLI only.
 */

#include <exec/types.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <libraries/dos.h>
#include <devices/console.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }     /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

/* Note - using two character <CSI> ESC[.  Hex 9B could be used instead */
#define RESETCON  "\033c"
#define CURSOFF   "\033[0 p"
#define CURSON    "\033[ p"
#define DELCHAR   "\033[P"

* SGR (set graphic rendition) */
#define COLOR02   "\033[32m"
#define COLOR03   "\033[33m"
#define ITALICS   "\033[3m"
#define BOLD      "\033[1m"
#define UNDERLINE "\033[4m"
#define NORMAL    "\033[0m"

/* our functions */
void cleanexit(UBYTE *,LONG);
void cleanup(void);
BYTE OpenConsole(struct IOStdReq *,struct IOStdReq *, struct Window *);
void CloseConsole(struct IOStdReq *);
void QueueRead(struct IOStdReq *, UBYTE *);
UBYTE ConGetChar(struct MsgPort *, UBYTE *);
LONG ConMayGetChar(struct MsgPort *, UBYTE *);
void ConPuts(struct IOStdReq *, UBYTE *);
void ConWrite(struct IOStdReq *, UBYTE *, LONG);
void ConPutChar(struct IOStdReq *, UBYTE);
void main(int argc, char **argv);
struct NewWindow nw =
    {
    10, 10,                           /* starting position (left,top) */
    620,180,                          /* width, height */
    -1,-1,                            /* detailpen, blockpen */
    CLOSEWINDOW,                      /* flags for idcmp */
    WINDOWDEPTH|WINDOWSIZING|
    WINDOWDRAG|WINDOWCLOSE|
    SMART_REFRESH|ACTIVATE,           /* window flags */
    NULL,                             /* no user gadgets */
    NULL,                             /* no user checkmark */
    "Console Test",                   /* title */
    NULL,                             /* pointer to window screen */
    NULL,                             /* pointer to super bitmap */
    100,45,                           /* min width, height */
    640,200,                          /* max width, height */
    WBENCHSCREEN                      /* open on workbench screen */
    };

/* Opens/allocations we'll need to clean up */
struct Library  *IntuitionBase = NULL;
struct Window   *win = NULL;
struct IOStdReq *writeReq = NULL;    /* IORequest block pointer */
struct MsgPort  *writePort = NULL;   /* replyport for writes      */
struct IOStdReq *readReq = NULL;     /* IORequest block pointer */
struct MsgPort  *readPort = NULL;    /* replyport for reads       */
BOOL OpenedConsole = FALSE;

BOOL FromWb;

void main(argc, argv)
int argc;
char **argv;
    {
    struct IntuiMessage *winmsg;
    ULONG signals, conreadsig, windowsig;
    LONG lch;
    SHORT InControl = 0;
    BOOL Done = FALSE;
    UBYTE ch, ibuf;
    UBYTE obuf[200];
    BYTE error;

    FromWb = (argc==0L) ? TRUE : FALSE;

    if(!(IntuitionBase=OpenLibrary("intuition.library",0)))
         cleanexit("Can't open intuition\n",RETURN_FAIL);

    /* Create reply port and io block for writing to console */
    if(!(writePort = CreatePort("RKM.console.write",0)))
         cleanexit("Can't create write port\n",RETURN_FAIL);

    if(!(writeReq = (struct IOStdReq *)
                    CreateExtIO(writePort,(LONG)sizeof(struct IOStdReq))))
         cleanexit("Can't create write request\n",RETURN_FAIL);

    /* Create reply port and io block for reading from console */
    if(!(readPort = CreatePort("RKM.console.read",0)))
         cleanexit("Can't create read port\n",RETURN_FAIL);

    if(!(readReq = (struct IOStdReq *)
                   CreateExtIO(readPort,(LONG)sizeof(struct IOStdReq))))
         cleanexit("Can't create read request\n",RETURN_FAIL);

    /* Open a window */
    if(!(win = OpenWindow(&nw)))
         cleanexit("Can't open window\n",RETURN_FAIL);

    /* Now, attach a console to the window */
    if(error = OpenConsole(writeReq,readReq,win))
         cleanexit("Can't open console.device\n",RETURN_FAIL);
    else OpenedConsole = TRUE;

    /* Demonstrate some console escape sequences */
    ConPuts(writeReq,"Here's some normal text\n");
    sprintf(obuf,"%s%sHere's text in color 3 & italics\n",COLOR03,ITALICS);
    ConPuts(writeReq,obuf);
    ConPuts(writeReq,NORMAL);
    Delay(50);      /* Delay for dramatic demo effect */
    ConPuts(writeReq,"We will now delete this asterisk =*=");
    Delay(50);
    ConPuts(writeReq,"\b\b");  /* backspace twice */
    Delay(50);
    ConPuts(writeReq,DELCHAR); /* delete the character */
    Delay(50);

    QueueRead(readReq,&ibuf); /* send the first console read request */

    ConPuts(writeReq,"\n\nNow reading console\n");
    ConPuts(writeReq,"Type some keys.  Close window when done.\n\n");

    conreadsig = 1 << readPort->mp_SigBit;
    windowsig = 1 << win->UserPort->mp_SigBit;

    while(!Done)
        {
        /* A character, or an IDCMP msg, or both could wake us up */
        signals = Wait(conreadsig|windowsig);

        /* If a console signal was received, get the character */
        if (signals & conreadsig)
            {
            if((lch = ConMayGetChar(readPort,&ibuf)) != -1)
                {
                ch = lch;
                /* Show hex and ascii (if printable) for char we got.
                 * If you want to parse received control sequences, such as
                 * function or Help keys,you would buffer control sequences
                 * as you receive them, starting to buffer whenever you
                 * receive 0x9B (or 0x1B[ for user-typed sequences) and
                 * ending when you receive a valid terminating character
                 * for the type of control sequence you are receiving.
                 * For CSI sequences, valid terminating characters
                 * are generally 0x40 through 0x7E.
                 * In our example, InControl has the following values:
                 * 0 = no, 1 = have 0x1B, 2 = have 0x9B OR 0x1B and [,
                 * 3 = now inside control sequence, -1 = normal end esc,
                 * -2 = non-CSI(no [) 0x1B end esc
                 * NOTE - a more complex parser is required to recognize
                 *  other types of control sequences.
                 */

                /* 0x1B ESC not followed by '[', is not CSI seq */
                if (InControl==1)
                    {
                    if(ch=='[') InControl = 2;
                    else InControl = -2;
                    }

                if ((ch==0x9B)||(ch==0x1B))  /* Control seq starting */
                    {
                    InControl = (ch==0x1B) ? 1 : 2;
                    ConPuts(writeReq,"=== Control Seq ===\n");
                    }

                /* We'll show value of this char we received */
                if (((ch >= 0x1F)&&(ch <= 0x7E))||(ch >= 0xA0))
                   sprintf(obuf,"Received: hex %02x = %c\n",ch,ch);
                else sprintf(obuf,"Received: hex %02x\n",ch);
                ConPuts(writeReq,obuf);

                /* Valid ESC sequence terminator ends an ESC seq */
                if ((InControl==3)&&((ch >= 0x40) && (ch <= 0x7E)))
                    {
                    InControl = -1;
                    }
                if (InControl==2) InControl = 3;
                /* ESC sequence finished (-1 if OK, -2 if bogus) */
                if (InControl < 0)
                    {
                    InControl = 0;
                    ConPuts(writeReq,"=== End Control ===\n");
                    }
                }
            }

        /* If IDCMP messages received, handle them */
        if (signals & windowsig)
            {
            /* We have to ReplyMsg these when done with them */
            while (winmsg = (struct IntuiMessage *)GetMsg(win->UserPort))
                {
                switch(winmsg->Class)
                    {
                    case CLOSEWINDOW:
                      Done = TRUE;
                      break;
                    default:
                      break;
                     }
                ReplyMsg((struct Message *)winmsg);
                }
            }
        }

    /* We always have an outstanding queued read request
     * so we must abort it if it hasn't completed,
     * and we must remove it.
     */
    if(!(CheckIO(readReq)))  AbortIO(readReq);
    WaitIO(readReq);     /* clear it from our replyport */

    cleanup();
    exit(RETURN_OK);
    }

void cleanexit(UBYTE *s,LONG n)
    {
    if(*s & (!FromWb)) printf(s);
    cleanup();
    exit(n);
    }

void cleanup()
    {
    if(OpenedConsole) CloseConsole(writeReq);
    if(readReq)       DeleteExtIO(readReq);
    if(readPort)      DeletePort(readPort);
    if(writeReq)      DeleteExtIO(writeReq);
    if(writePort)     DeletePort(writePort);
    if(win)           CloseWindow(win);
    if(IntuitionBase) CloseLibrary(IntuitionBase);
    }

/* Attach console device to an open Intuition window.
 * This function returns a value of 0 if the console
 * device opened correctly and a nonzero value (the error
 * returned from OpenDevice) if there was an error.
 */
BYTE OpenConsole(writereq, readreq, window)
struct IOStdReq *writereq;
struct IOStdReq *readreq;
struct Window *window;
    {
    BYTE error;

    writereq->io_Data = (APTR) window;
    writereq->io_Length = sizeof(struct Window);
    error = OpenDevice("console.device", 0, writereq, 0);
    readreq->io_Device = writereq->io_Device; /* clone required parts */
    readreq->io_Unit   = writereq->io_Unit;
    return(error);
    }

void CloseConsole(struct IOStdReq *writereq)
    {
    CloseDevice(writereq);
    }

/* Output a single character to a specified console
 */
void ConPutChar(struct IOStdReq *writereq, UBYTE character)
    {
    writereq->io_Command = CMD_WRITE;
    writereq->io_Data = (APTR)&character;
    writereq->io_Length = 1;
    DoIO(writereq);
    /* command works because DoIO blocks until command is done
     * (otherwise ptr to the character could become invalid)
     */
    }

/* Output a stream of known length to a console
 */
void ConWrite(struct IOStdReq *writereq, UBYTE *string, LONG length)
    {
    writereq->io_Command = CMD_WRITE;
    writereq->io_Data = (APTR)string;
    writereq->io_Length = length;
    DoIO(writereq);
    /* command works because DoIO blocks until command is done
     * (otherwise ptr to string could become invalid in the meantime)
     */
    }

/* Output a NULL-terminated string of characters to a console
 */
void ConPuts(struct IOStdReq *writereq,UBYTE *string)
    {
    writereq->io_Command = CMD_WRITE;
    writereq->io_Data = (APTR)string;
    writereq->io_Length = -1;  /* means print till terminating null */
    DoIO(writereq);
    }

/* Queue up a read request to console, passing it pointer
 * to a buffer into which it can read the character
 */
void QueueRead(struct IOStdReq *readreq, UBYTE *whereto)
   {
   readreq->io_Command = CMD_READ;
   readreq->io_Data = (APTR)whereto;
   readreq->io_Length = 1;
   SendIO(readreq);
   }

/* Check if a character has been received.
 * If none, return -1
 */
LONG ConMayGetChar(struct MsgPort *msgport, UBYTE *whereto)
    {
    register temp;
    struct IOStdReq *readreq;

    if (!(readreq = (struct IOStdReq *)GetMsg(msgport))) return(-1);
    temp = *whereto;                /* get the character */
    QueueRead(readreq,whereto);     /* then re-use the request block */
    return(temp);
    }

/* Wait for a character
 */
UBYTE ConGetChar(struct MsgPort *msgport, UBYTE *whereto)
    {
    register temp;
    struct IOStdReq *readreq;

    WaitPort(msgport);
    readreq = (struct IOStdReq *)GetMsg(msgport);
    temp = *whereto;               /* get the character */
    QueueRead(readreq,whereto);    /* then re-use the request block*/
    return((UBYTE)temp);
    }


Lib_examples/rawkey.c

;/* rawkey.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 rawkey.c
Blink FROM LIB:c.o,rawkey.o TO rawkey LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
**
** The following example uses RawKeyConvert() to convert the
** IDCMP_RAWKEY input stream into an ANSI input stream.  See the
** "Console Device" chapter in the Amiga ROM Kernel Reference Manual:
** Devices for more information on RawKeyConvert() and the data it
** returns.
**
** rawkey.c - How to correctly convert from RAWKEY to keymapped ASCII
*/
#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <devices/inputevent.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/console_protos.h>
#include <stdio.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

/* our function prototypes */
LONG deadKeyConvert(struct IntuiMessage *msg, UBYTE *kbuffer,
                    LONG kbsize, struct KeyMap *kmap, struct InputEvent *ievent);
VOID print_qualifiers(ULONG qual);
BOOL doKeys(struct IntuiMessage *msg, struct InputEvent *ievent,
                    UBYTE **buffer, ULONG *bufsize);
VOID process_window(struct Window *win, struct InputEvent *ievent,
                    UBYTE **buffer, ULONG *bufsize);

/* A buffer is created for RawKeyConvert() to put its output. BUFSIZE is the size of
** the buffer in bytes.  NOTE that this program starts out with a buffer size of 2.
** This is only to show how the buffer is automatically increased in size  by this
** example!  In an application, start with a much larger buffer and you will probably
** never have to increase its size. 128 bytes or so should do the trick, but always
** be able to change the size if required.
*/
#define BUFSIZE (2)

struct Library *IntuitionBase, *ConsoleDevice;

/* main() - set-up everything used by program. */
VOID main(int argc, char **argv)
{
struct Window *win;
struct IOStdReq ioreq;
struct InputEvent *ievent;
UBYTE *buffer;
ULONG bufsize = BUFSIZE;

if(IntuitionBase = OpenLibrary("intuition.library",37)) {
    /* Open the console device just to do keymapping. (unit -1 means any unit) */
    if (0 == OpenDevice("console.device",-1,(struct IORequest *)&ioreq,0)) {
        ConsoleDevice = (struct Library *)ioreq.io_Device;

        /* Allocate the initial character buffer used by deadKeyConvert() and RawKeyConvert()
        ** for returning translated characters. If the characters generated by these routines
        ** cannot fit into the buffer, the application must pass a larger buffer.  This is
        ** done in this code by freeing the old buffer and allocating a new one.
        */
        if (buffer = AllocMem(bufsize,MEMF_CLEAR)) {
            if (ievent = AllocMem(sizeof(struct InputEvent),MEMF_CLEAR)) {
                if (win = OpenWindowTags(NULL,
                        WA_Width, 300,
                        WA_Height, 50,
                        WA_Flags, WFLG_DEPTHGADGET | WFLG_CLOSEGADGET | WFLG_ACTIVATE,
                        WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_RAWKEY,
                        WA_Title, "Raw Key Example",
                        TAG_END)) {
                    printf("Press keyboard keys to see ASCII conversion from rawkey\n");
                    printf("Unprintable characters will be shown as %c\n\n",0x7f);
                    process_window(win,ievent,&buffer,&bufsize);
                    CloseWindow(win);
                    }
                FreeMem(ievent,sizeof(struct InputEvent));
                }
            /* Buffer can be freed elsewhere in the program so test first. */
            if (buffer != NULL)
                FreeMem(buffer,bufsize);
            }
        CloseDevice((struct IORequest *)&ioreq);
        }
    CloseLibrary(IntuitionBase);
    }
}

/* Convert RAWKEYs into VANILLAKEYs, also shows special keys like HELP, Cursor Keys,
** FKeys, etc.  It returns:
**   -2 if not a RAWKEY event.
**   -1 if not enough room in the buffer, try again with a bigger buffer.
**   otherwise, returns the number of characters placed in the buffer.
*/
LONG deadKeyConvert(struct IntuiMessage *msg, UBYTE *kbuffer,
    LONG kbsize, struct KeyMap *kmap, struct InputEvent *ievent)
{
if (msg->Class != IDCMP_RAWKEY) return(-2);
ievent->ie_Class = IECLASS_RAWKEY;
ievent->ie_Code = msg->Code;
ievent->ie_Qualifier = msg->Qualifier;
ievent->ie_position.ie_addr = *((APTR*)msg->IAddress);

return(RawKeyConvert(ievent,kbuffer,kbsize,kmap));
}

/* print_qualifiers() - print out the values found in the qualifier bits of
** the message. This will print out all of the qualifier bits set.
*/
VOID print_qualifiers(ULONG qual)
{
printf("Qual:");
if (qual & IEQUALIFIER_LSHIFT)         printf("LShft,");
if (qual & IEQUALIFIER_RSHIFT)         printf("RShft,");
if (qual & IEQUALIFIER_CAPSLOCK)       printf("CapLok,");
if (qual & IEQUALIFIER_CONTROL)        printf("Ctrl,");
if (qual & IEQUALIFIER_LALT)           printf("LAlt,");
if (qual & IEQUALIFIER_RALT)           printf("RAlt,");
if (qual & IEQUALIFIER_LCOMMAND)       printf("LCmd,");
if (qual & IEQUALIFIER_RCOMMAND)       printf("RCmd,");
if (qual & IEQUALIFIER_NUMERICPAD)     printf("NumPad,");
if (qual & IEQUALIFIER_REPEAT)         printf("Rpt,");
if (qual & IEQUALIFIER_INTERRUPT)      printf("Intrpt,");
if (qual & IEQUALIFIER_MULTIBROADCAST) printf("Multi Broadcast,");
if (qual & IEQUALIFIER_MIDBUTTON)      printf("MidBtn,");
if (qual & IEQUALIFIER_RBUTTON)        printf("RBtn,");
if (qual & IEQUALIFIER_LEFTBUTTON)     printf("LBtn,");
if (qual & IEQUALIFIER_RELATIVEMOUSE)  printf("RelMouse,");
}

/* doKeys() - Show what keys were pressed. */
BOOL doKeys(struct IntuiMessage *msg, struct InputEvent *ievent,
            UBYTE **buffer, ULONG *bufsize)
{
USHORT char_pos;
USHORT numchars;
BOOL   ret_code = TRUE;
UBYTE  realc, c;

/* deadKeyConvert() returns -1 if there was not enough space in the buffer to
** convert the string. Here, the routine increases the size of the buffer on the
** fly...Set the return code to FALSE on failure.
*/
numchars = deadKeyConvert(msg, *buffer, *bufsize - 1, NULL, ievent);
while ((numchars == -1) && (*buffer != NULL)) {
    /* conversion failed, buffer too small. try to double the size of the buffer. */
    FreeMem(*buffer, *bufsize);
    *bufsize = *bufsize << 1;
    printf("Increasing buffer size to %d\n", *bufsize);

    if (NULL == (*buffer = AllocMem(*bufsize, MEMF_CLEAR)))  ret_code = FALSE;
    else  numchars = deadKeyConvert(msg, *buffer, *bufsize - 1, NULL, ievent);
    }

/* numchars contains the number of characters placed within the buffer.  Key up events and   */
/* key sequences that do not generate any data for the program (like deadkeys) will return   */
/* zero.  Special keys (like HELP, the cursor keys, FKeys, etc.) return multiple characters  */
/* that have to then be parsed by the application.  Allocation failed above if buffer is NULL*/
if (*buffer != NULL) {
    /* if high bit set, then this is a key up otherwise this is a key down */
    if (msg->Code & 0x80)
          printf("Key Up:   ");
    else
          printf("Key Down: ");

    print_qualifiers(msg->Qualifier);
    printf(" rawkey #%d maps to %d ASCII character(s)\n", 0x7F & msg->Code, numchars);
    for (char_pos = 0; char_pos < numchars; char_pos++) {
        realc = c = (*buffer)[char_pos];
        if ((c <= 0x1F)||((c >= 0x80)&&(c < 0xa0)))
            c = 0x7f;
        printf("  %3d ($%02x) = %c\n", realc, realc, c);
        }
    }
return(ret_code);
}

/* process_window() - simple event loop.  Note that the message is not replied
** to until the end of the loop so that it may be used in the doKeys() call.
*/
VOID process_window(struct Window *win, struct InputEvent *ievent,
    UBYTE **buffer, ULONG *bufsize)
{
struct IntuiMessage *msg;
BOOL done;

done = FALSE;
while (done == FALSE) {
    Wait((1L<<win->UserPort->mp_SigBit));
    while ((done == FALSE) && (msg = (struct IntuiMessage *)GetMsg(win->UserPort))) {
        switch (msg->Class) {     /* handle our events */
            case IDCMP_CLOSEWINDOW:
                done = TRUE;
                break;
            case IDCMP_RAWKEY:
                if (FALSE == doKeys(msg,ievent,buffer,bufsize))
                    done = TRUE;
                break;
            }
        ReplyMsg((struct Message *)msg);
        }
    }
}


Devices/Dev_examples/Simple_Serial.c

/*
 * Simple_Serial.c
 *
 * This is an example of using the serial device.  First, we will attempt
 * to create a message port with CreateMsgPort().  Next, we will attempt
 * to create the IORequest with CreateExtIO().  Then, we will attempt to
 * open the serial device with OpenDevice().  If successful, we will write
 * a NULL-terminated string to it and reverse our steps.  If we encounter
 * an error at any time, we will gracefully exit.
 *
 * Compile with SAS C 5.10  lc -b1 -cfistq -v -y -L
 *
 * Run from CLI only
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/io.h>
#include <devices/serial.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

void main(void)
{
struct MsgPort *SerialMP;       /* pointer to our message port */
struct IOExtSer *SerialIO;      /* pointer to our IORequest */

/* Create the message port */
if (SerialMP=CreateMsgPort())
    {
    /* Create the IORequest */
    if (SerialIO = (struct IOExtSer *)
                    CreateExtIO(SerialMP,sizeof(struct IOExtSer)))
        {
        /* Open the serial device */
        if (OpenDevice(SERIALNAME,0,(struct IORequest *)SerialIO,0L))

            /* Inform user that it could not be opened */
            printf("Error: %s did not open\n",SERIALNAME);
        else
            {
            /* device opened, write NULL-terminated string */
            SerialIO->IOSer.io_Length   = -1;
            SerialIO->IOSer.io_Data     = (APTR)"Amiga ";
            SerialIO->IOSer.io_Command  = CMD_WRITE;
            if (DoIO((struct IORequest *)SerialIO))     /* execute write */
                printf("Write failed.  Error - %ld\n",SerialIO->IOSer.io_Error);

            /* Close the serial device */
            CloseDevice((struct IORequest *)SerialIO);
            }
        /* Delete the IORequest */
        DeleteExtIO(SerialIO);
        }
    else
        /* Inform user that the IORequest could be created */
        printf("Error: Could create IORequest\n");

    /* Delete the message port */
    DeleteMsgPort(SerialMP);
    }
else
    /* Inform user that the message port could not be created */
    printf("Error: Could not create message port\n");
}

/*
   DoIO() vs. SendIO().
   --------------------
   The above example code contains some simplifications.  The DoIO()
   function in the example is not always appropriate for executing the
   CMD_READ or CMD_WRITE commands.  DoIO() will not return until the I/O
   request has finished.  With serial handshaking enabled, a write
   request may never finish.  Read requests will not finish until
   characters arrive at the serial port.  The following sections will
   demonstrate a solution using the SendIO() and AbortIO() functions.

*/


Devices/Dev_examples/Complex_Serial.c

/*
 * Complex_Serial.c
 *
 * Complex tricky example of serial.device usage
 *
 * Compile with SAS C 5.10  lc -b1 -cfistq -v -y -L
 *
 * Run from CLI only
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/io.h>
#include <devices/serial.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

void main(void)
{
struct MsgPort  *SerialMP;          /* Define storage for one pointer */
struct IOExtSer *SerialIO;         /* Define storage for one pointer */

#define READ_BUFFER_SIZE 32
char SerialReadBuffer[READ_BUFFER_SIZE]; /* Reserve SIZE bytes storage */

struct IOExtSer *SerialWriteIO = 0;
struct MsgPort  *SerialWriteMP = 0;

ULONG Temp;
ULONG WaitMask;

if (SerialMP=CreatePort(0,0) )
    {
    if (SerialIO=(struct IOExtSer *)
                 CreateExtIO(SerialMP,sizeof(struct IOExtSer)) )
        {
        SerialIO->io_SerFlags=0;    /* Example of setting flags */

        if (OpenDevice(SERIALNAME,0L,SerialIO,0) )
            printf("%s did not open\n",SERIALNAME);
        else
            {
            SerialIO->IOSer.io_Command  = SDCMD_SETPARAMS;
            SerialIO->io_SerFlags      &= ~SERF_PARTY_ON;
            SerialIO->io_SerFlags      |= SERF_XDISABLED;
            SerialIO->io_Baud           = 9600;
            if (Temp=DoIO(SerialIO))
                printf("Error setting parameters - code %ld!\n",Temp);

            SerialIO->IOSer.io_Command  = CMD_WRITE;
            SerialIO->IOSer.io_Length   = -1;
            SerialIO->IOSer.io_Data     = (APTR)"Amiga.";
            SendIO(SerialIO);
            printf("CheckIO %lx\n",CheckIO(SerialIO));
            printf("The device will process the request in the background\n");
            printf("CheckIO %lx\n",CheckIO(SerialIO));
            WaitIO(SerialIO);

            SerialIO->IOSer.io_Command  = CMD_WRITE;
            SerialIO->IOSer.io_Length   = -1;
            SerialIO->IOSer.io_Data     = (APTR)"Save the whales! ";
            DoIO(SerialIO);             /* execute write */

            SerialIO->IOSer.io_Command  = CMD_WRITE;
            SerialIO->IOSer.io_Length   = -1;
            SerialIO->IOSer.io_Data     = (APTR)"Life is but a dream.";
            DoIO(SerialIO);             /* execute write */

            SerialIO->IOSer.io_Command  = CMD_WRITE;
            SerialIO->IOSer.io_Length   = -1;
            SerialIO->IOSer.io_Data     = (APTR)"Row, row, row your boat.";
            SerialIO->IOSer.io_Flags = IOF_QUICK;
            BeginIO(SerialIO);

            if (SerialIO->IOSer.io_Flags & IOF_QUICK )
                {

                /*
                 * Quick IO could not happen for some reason; the device
                 *  processed the command normally.  In this case
                 *  BeginIO() acted exactly like SendIO().
                 */

                printf("Quick IO\n");
                }
            else
                {

                /* If flag is still set, IO was synchronous and is now finished.
                 * The IO request was NOT appended a reply port.  There is no
                 * need to remove or WaitIO() for the message.
                 */

                printf("Regular IO\n");
                }

            WaitIO(SerialIO);

            SerialIO->IOSer.io_Command  = CMD_UPDATE;
            SerialIO->IOSer.io_Length   = -1;
            SerialIO->IOSer.io_Data     = (APTR)"Row, row, row your boat.";
            SerialIO->IOSer.io_Flags = IOF_QUICK;
            BeginIO(SerialIO);

            if (0 == SerialIO->IOSer.io_Flags & IOF_QUICK )
                {

                /*
                 * Quick IO could not happen for some reason; the device processed
                 * the command normally.  In this case BeginIO() acted exactly
                 * like SendIO().
                 */

                printf("Regular IO\n");

                WaitIO(SerialIO);
                }
            else
                {

                /* If flag is still set, IO was synchronous and is now finished.
                 * The IO request was NOT appended a reply port.  There is no
                 * need to remove or WaitIO() for the message.
                 */

                printf("Quick IO\n");
                }

            /* Precalculate a wait mask for the CTRL-C, CTRL-F and message
             * port signals.  When one or more signals are received,
             * Wait() will return.  Press CTRL-C to exit the example.
             * Press CTRL-F to wake up the example without doing anything.
             * NOTE: A signal may show up without an associated message!
             */

            WaitMask = SIGBREAKF_CTRL_C|
                        SIGBREAKF_CTRL_F|
                         1L << SerialMP->mp_SigBit;

            SerialIO->IOSer.io_Command  = CMD_READ;
            SerialIO->IOSer.io_Length   = READ_BUFFER_SIZE;
            SerialIO->IOSer.io_Data     = (APTR)&SerialReadBuffer[0];
            SendIO(SerialIO);

            printf("Sleeping until CTRL-C, CTRL-F, or serial input\n");

            while (1)
                   {
                   Temp = Wait(WaitMask);
                   printf("Just woke up (YAWN!)\n");

                   if (SIGBREAKF_CTRL_C & Temp)
                       break;

                   if (CheckIO(SerialIO) ) /* If request is complete... */
                       {
                       WaitIO(SerialIO);   /* clean up and remove reply */

                       printf("%ld bytes received\n",SerialIO->IOSer.io_Actual);
                       break;
                       }
                   }

            AbortIO(SerialIO);  /* Ask device to abort request, if pending */
            WaitIO(SerialIO);   /* Wait for abort, then clean up */

            /*
             * If two tasks will use the same device at the same time, it is preferred
             * use two OpenDevice() calls and SHARED mode.  If exclusive access mode
             * is required, then you will need to copy an existing IO request.
             *
             * Remember that two separate tasks will require two message ports.
             */

            SerialWriteMP = CreatePort(0,0);
            SerialWriteIO = (struct IOExtSer *)
                            CreateExtIO( SerialWriteMP,sizeof(struct IOExtSer) );

            if (SerialWriteMP && SerialWriteIO )
                {

                /* Copy over the entire old IO request, then stuff the
                 * new Message port pointer.
                 */

                CopyMem( SerialIO, SerialWriteIO, sizeof(struct IOExtSer) );
                SerialWriteIO->IOSer.io_Message.mn_ReplyPort = SerialWriteMP;

                SerialWriteIO->IOSer.io_Command  = CMD_WRITE;
                SerialWriteIO->IOSer.io_Length   = -1;
                SerialWriteIO->IOSer.io_Data     = (APTR)"A poet's food is love and fame";
                DoIO(SerialWriteIO);
                }

            if (SerialWriteMP)
                DeletePort(SerialWriteMP);

            if (SerialWriteIO)
                DeleteExtIO(SerialWriteIO);

            CloseDevice(SerialIO);
            }

        DeleteExtIO(SerialIO);
        }
    else
        printf("Unable to create IORequest\n");

    DeletePort(SerialMP);
    }
else
    printf("Unable to create message port\n");
}


Devices/Dev_examples/Terminate_Serial.c

/*
 * Terminate_Serial.c
 *
 * This is an example of using a termination array for reads from the serial
 * device. A termination array is set up for the characters Q, E, etx (CTRL-D)
 * and eot (CTRL-C).  The EOFMODE flag is set in io_SerFlags to indicate that
 * we want to use a termination array by sending the SDCMD_SETPARAMS command to
 * the device.  Then, a CMD_READ command is sent to the device with
 * io_Length set to 25.
 *
 * The read will terminate whenever one of the four characters in the termination
 * array is received or when 25 characters have been received.
 *
 * Compile with SAS C 5.10  lc -b1 -cfistq -v -y -L
 *
 * Run from CLI only
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/io.h>
#include <devices/serial.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

void main(void)
{
struct MsgPort  *SerialMP;          /* Define storage for one pointer */
struct IOExtSer *SerialIO;         /* Define storage for one pointer */

struct IOTArray Terminators =
{
0x51450403,   /* Q E etx eot */
0x03030303    /* fill to end with lowest value */
};

#define READ_BUFFER_SIZE 25
UBYTE ReadBuff[READ_BUFFER_SIZE];
UWORD ctr;

if (SerialMP=CreatePort(0,0) )
    {
    if (SerialIO=(struct IOExtSer *) CreateExtIO(SerialMP,sizeof(struct IOExtSer)))
        {
        if (OpenDevice(SERIALNAME,0L,(struct IORequest *)SerialIO,0) )
            printf("%s did not open\n",SERIALNAME);
        else
            {
             /* Tell user what we are doing */
             printf("\fLooking for Q, E, EOT or ETX\n");

             /* Set EOF mode flag
              * Set the termination array
              * Send SDCMD_SETPARAMS to the serial device
              */
             SerialIO->io_SerFlags |= SERF_EOFMODE;
             SerialIO->io_TermArray = Terminators;
             SerialIO->IOSer.io_Command  = SDCMD_SETPARAMS;
             if (DoIO((struct IORequest *)SerialIO))
                 printf("Set Params failed ");   /* Inform user of error */
             else
                 {
                 SerialIO->IOSer.io_Length   = READ_BUFFER_SIZE;
                 SerialIO->IOSer.io_Data     = (APTR)&ReadBuff[0];
                 SerialIO->IOSer.io_Command  = CMD_READ;
                 if (DoIO((struct IORequest *)SerialIO))     /* Execute Read */
                     printf("Error: Read failed\n");
                 else
                     {
                      /* Display all characters received */
                      printf("\nThese characters were read:\n\t\t\tASCII\tHEX\n");
                      for (ctr=0;ctr<SerialIO->IOSer.io_Actual;ctr++)
                           printf("\t\t\t  %c\t%x\n",ReadBuff[ctr],ReadBuff[ctr]);
                      printf("\nThe actual number of characters read: %d\n",
                                  SerialIO->IOSer.io_Actual);
                      }
                 }
            CloseDevice((struct IORequest *)SerialIO);
            }

        DeleteExtIO((struct IORequest *)SerialIO);
        }
    else
        printf("Error: Could not create IORequest\n");

    DeletePort(SerialMP);
    }
else
    printf("Error: Could not create message port\n");
}


Devices/Dev_examples/Absolute_joystick.c

/*
 * Absolute_Joystick.c
 *
 * Gameport device absolute joystick example
 *
 * Compile with SAS 5.10  lc -b1 -cfistq -v -y -L
 *
 * Run from CLI only
 */

#include <exec/types.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <exec/exec.h>
#include <dos/dos.h>
#include <devices/gameport.h>
#include <devices/inputevent.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }     /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

#define JOY_X_DELTA (1)
#define JOY_Y_DELTA (1)
#define TIMEOUT_SECONDS (10)

extern struct ExecBase *SysBase;

/*-----------------------------------------------------------------------
** Routine to print out some information for the user.
*/
VOID printInstructions(VOID)
{
printf("\n >>> gameport.device Absolute Joystick Demo <<<\n\n");

if (SysBase->VBlankFrequency==60)
    printf(" Running on NTSC system (60 Hz).\n");
else if (SysBase->VBlankFrequency==50)
    printf(" Running on PAL system (50 Hz).\n");

printf(" Attach joystick to rear connector (A3000) and (A1000).\n"
       " Attach joystick to right connector (A2000).\n"
       " Attach joystick to left connector (A500).\n"
       " Then move joystick and click its button(s).\n\n"
       " To exit program press and release fire button 3 times in a row.\n"
       " The program also exits if no activity occurs for 1 minute.\n\n");
}

/*-----------------------------------------------------------------------
** print out information on the event received.
*/
BOOL check_move(struct InputEvent *game_event)
{
WORD xmove, ymove;
BOOL timeout=FALSE;

xmove = game_event->ie_X;
ymove = game_event->ie_Y;

if (xmove == 1)
    {
    if (ymove == 1) printf("RIGHT DOWN\n");
    else if (ymove == 0) printf("RIGHT\n");
    else if (ymove ==-1) printf("RIGHT UP\n");
    else printf("UNKNOWN Y\n");
    }
else if (xmove ==-1)
    {
    if (ymove == 1) printf("LEFT DOWN\n");
    else if (ymove == 0) printf("LEFT\n");
    else if (ymove ==-1) printf("LEFT UP\n");
    else printf("UNKNOWN Y\n");
    }
else if (xmove == 0)
    {
    if (ymove == 1) printf("DOWN\n");
    /* note that 0,0 can be a timeout, or a direction release. */
    else if (ymove == 0)
        {
        if (game_event->ie_TimeStamp.tv_secs >=
                        (UWORD)(SysBase->VBlankFrequency)*TIMEOUT_SECONDS)
            {
            printf("TIMEOUT\n");
            timeout=TRUE;
            }
        else printf("RELEASE\n");
        }
    else if (ymove ==-1) printf("UP\n");
    else printf("UNKNOWN Y\n");
    }
else
    {
    printf("UNKNOWN X ");
    if (ymove == 1) printf("unknown action\n");
    else if (ymove == 0) printf("unknown action\n");
    else if (ymove ==-1) printf("unknown action\n");
    else printf("UNKNOWN Y\n");
    }

return(timeout);

}

/*-----------------------------------------------------------------------
** send a request to the gameport to read an event.
*/
VOID send_read_request( struct InputEvent *game_event,
                        struct IOStdReq *game_io_msg)
{
game_io_msg->io_Command = GPD_READEVENT;
game_io_msg->io_Flags   = 0;
game_io_msg->io_Data    = (APTR)game_event;
game_io_msg->io_Length  = sizeof(struct InputEvent);
SendIO(game_io_msg);  /* Asynchronous - message will return later */
}

/*-----------------------------------------------------------------------
** simple loop to process gameport events.
*/
VOID processEvents( struct IOStdReq *game_io_msg,
                    struct MsgPort  *game_msg_port)
{
BOOL timeout;
SHORT timeouts;
SHORT button_count;
BOOL  not_finished;
struct InputEvent game_event;   /* where input event will be stored */

/* From now on, just read input events into the event buffer,
** one at a time.  READEVENT waits for the preset conditions.
*/
timeouts = 0;
button_count = 0;
not_finished = TRUE;

while ((timeouts < 6) && (not_finished))
    {
    /* Send the read request */
    send_read_request(&game_event,game_io_msg);

    /* Wait for joystick action */
    Wait(1L << game_msg_port->mp_SigBit);
    while (NULL != GetMsg(game_msg_port))
        {
        timeout=FALSE;
        switch(game_event.ie_Code)
            {
            case IECODE_LBUTTON:
                printf(" FIRE BUTTON PRESSED \n");
                break;

            case (IECODE_LBUTTON | IECODE_UP_PREFIX):
                printf(" FIRE BUTTON RELEASED \n");
                if (3 == ++button_count)
                    not_finished = FALSE;
                break;

            case IECODE_RBUTTON:
                printf(" ALT BUTTON PRESSED \n");
                button_count = 0;
                break;

            case (IECODE_RBUTTON | IECODE_UP_PREFIX):
                printf(" ALT BUTTON RELEASED \n");
                button_count = 0;
                break;

            case IECODE_NOBUTTON:
                /* Check for change in position */
                timeout = check_move(&game_event);
                button_count = 0;
                break;

            default:
                break;
            }

        if (timeout)
            timeouts++;
        else
            timeouts=0;
        }
    }
}

/*-----------------------------------------------------------------------
** allocate the controller if it is available.
** you allocate the controller by setting its type to something
** other than GPCT_NOCONTROLLER.  Before you allocate the thing
** you need to check if anyone else is using it (it is free if
** it is set to GPCT_NOCONTROLLER).
*/
BOOL set_controller_type(BYTE type, struct IOStdReq *game_io_msg)
{
BOOL success = FALSE;
BYTE controller_type = 0;

/* begin critical section
** we need to be sure that between the time we check that the controller
** is available and the time we allocate it, no one else steals it.
*/
Forbid();

game_io_msg->io_Command = GPD_ASKCTYPE;    /* inquire current status */
game_io_msg->io_Flags   = IOF_QUICK;
game_io_msg->io_Data    = (APTR)&controller_type; /* put answer in here */
game_io_msg->io_Length  = 1;
DoIO(game_io_msg);

/* No one is using this device unit, let's claim it */
if (controller_type == GPCT_NOCONTROLLER)
    {
    game_io_msg->io_Command = GPD_SETCTYPE;
    game_io_msg->io_Flags   = IOF_QUICK;
    game_io_msg->io_Data    = (APTR)&type;
    game_io_msg->io_Length  = 1;
    DoIO( game_io_msg);
    success = TRUE;
    }

Permit(); /* critical section end */
return(success);
}

/*-----------------------------------------------------------------------
** tell the gameport when to trigger.
*/
VOID set_trigger_conditions(struct GamePortTrigger *gpt,
                            struct IOStdReq *game_io_msg)
{
/* trigger on all joystick key transitions */
gpt->gpt_Keys   = GPTF_UPKEYS | GPTF_DOWNKEYS;
gpt->gpt_XDelta = JOY_X_DELTA;
gpt->gpt_YDelta = JOY_Y_DELTA;
/* timeout trigger every TIMEOUT_SECONDS second(s) */
gpt->gpt_Timeout = (UWORD)(SysBase->VBlankFrequency) * TIMEOUT_SECONDS;

game_io_msg->io_Command = GPD_SETTRIGGER;
game_io_msg->io_Flags   = IOF_QUICK;
game_io_msg->io_Data    = (APTR)gpt;
game_io_msg->io_Length  = (LONG)sizeof(struct GamePortTrigger);
DoIO(game_io_msg);
}

/*-----------------------------------------------------------------------
** clear the buffer.  do this before you begin to be sure you
** start in a known state.
*/
VOID flush_buffer(struct IOStdReq *game_io_msg)
{
game_io_msg->io_Command = CMD_CLEAR;
game_io_msg->io_Flags   = IOF_QUICK;
game_io_msg->io_Data    = NULL;
game_io_msg->io_Length  = 0;
DoIO(game_io_msg);
}

/*-----------------------------------------------------------------------
** free the unit by setting its type back to GPCT_NOCONTROLLER.
*/
VOID free_gp_unit(struct IOStdReq *game_io_msg)
{
BYTE type = GPCT_NOCONTROLLER;

game_io_msg->io_Command = GPD_SETCTYPE;
game_io_msg->io_Flags   = IOF_QUICK;
game_io_msg->io_Data    = (APTR)&type;
game_io_msg->io_Length  = 1;
DoIO(game_io_msg);
}

/*-----------------------------------------------------------------------
** allocate everything and go.  On failure, free any resources that
** have been allocated.  this program fails quietly-no error messages.
*/
VOID main(int argc,char **argv)
{
struct GamePortTrigger   joytrigger;
struct IOStdReq         *game_io_msg;
struct MsgPort          *game_msg_port;

/* Create port for gameport device communications */
if (game_msg_port = CreatePort("RKM_game_port",0))
    {
    /* Create message block for device IO */
    if (game_io_msg = (struct IOStdReq *)
                      CreateExtIO(game_msg_port,sizeof(*game_io_msg)))
        {
        game_io_msg->io_Message.mn_Node.ln_Type = NT_UNKNOWN;

        /* Open the right/back (unit 1, number 2) gameport.device unit */
        if (!OpenDevice("gameport.device",1,game_io_msg,0))
            {
            /* Set controller type to joystick */
            if (set_controller_type(GPCT_ABSJOYSTICK,game_io_msg))
                {
                /* Specify the trigger conditions */
                set_trigger_conditions(&joytrigger,game_io_msg);

                printInstructions();

                /* Clear device buffer to start from a known state.
                ** There might still be events left
                */
                flush_buffer(game_io_msg);

                processEvents(game_io_msg,game_msg_port);

                /* Free gameport unit so other applications can use it ! */
                free_gp_unit(game_io_msg);
                }
            CloseDevice(game_io_msg);
            }
        DeleteExtIO(game_io_msg);
        }
    DeletePort(game_msg_port);
    }
}


Devices/Dev_examples/Simple_Timer.c

/* Simple_Timer.c
 *
 * A simple example of using the timer device.
 *
 * Compile with SAS C 5.10: LC -b1 -cfistq -v -y -L
 *
 * Run from CLI only
 */

#include <exec/types.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <devices/timer.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/dos_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }     /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

/* Our timer sub-routines */
void delete_timer  (struct timerequest *);
LONG get_sys_time  (struct timeval *);
LONG set_new_time  (LONG);
void wait_for_timer(struct timerequest *, struct timeval *);
LONG time_delay    ( struct timeval *, LONG );
struct timerequest *create_timer( ULONG );
void show_time     (ULONG);

struct Library *TimerBase;      /* to get at the time comparison functions */

/* manifest constants -- "will never change" */
#define   SECSPERMIN   (60)
#define   SECSPERHOUR  (60*60)
#define   SECSPERDAY   (60*60*24)

void main(int argc,char **argv)
{
LONG seconds;
struct timerequest *tr;      /* IO block for timer commands */
struct timeval oldtimeval;   /* timevals to store times     */
struct timeval mytimeval;
struct timeval currentval;

printf("\nTimer test\n");

/* sleep for two seconds */
currentval.tv_secs = 2;
currentval.tv_micro = 0;
time_delay( &currentval, UNIT_VBLANK );
printf( "After 2 seconds delay\n" );

/* sleep for four seconds */
currentval.tv_secs = 4;
currentval.tv_micro = 0;
time_delay( &currentval, UNIT_VBLANK );
printf( "After 4 seconds delay\n" );

/* sleep for 500,000 micro-seconds = 1/2 second */
currentval.tv_secs = 0;
currentval.tv_micro = 500000;
time_delay( &currentval, UNIT_MICROHZ );
printf( "After 1/2 second delay\n" );

printf( "DOS Date command shows: " );
(void) Execute( "date", 0, 0 );

/* save what system thinks is the time....we'll advance it temporarily */
get_sys_time( &oldtimeval );
printf("Original system time is:\n");
show_time(oldtimeval.tv_secs );

printf("Setting a new system time\n");

seconds = 1000 * SECSPERDAY + oldtimeval.tv_secs;

set_new_time( seconds );

/* (if user executes the AmigaDOS DATE command now, he will*/
/* see that the time has advanced something over 1000 days */
printf( "DOS Date command now shows: " );
(void) Execute( "date", 0, 0 );

get_sys_time( &mytimeval );
printf( "Current system time is:\n");
show_time(mytimeval.tv_secs);

/* Added the microseconds part to show that time keeps */
/* increasing even though you ask many times in a row  */
printf("Now do three TR_GETSYSTIMEs in a row (notice how the microseconds increase)\n\n");
get_sys_time( &mytimeval );
printf("First TR_GETSYSTIME \t%ld.%ld\n",mytimeval.tv_secs, mytimeval.tv_micro);
get_sys_time( &mytimeval );
printf("Second TR_GETSYSTIME \t%ld.%ld\n",mytimeval.tv_secs, mytimeval.tv_micro);
get_sys_time( &mytimeval );
printf("Third TR_GETSYSTIME \t%ld.%ld\n",mytimeval.tv_secs, mytimeval.tv_micro);

printf( "\nResetting to former time\n" );
set_new_time( oldtimeval.tv_secs );

get_sys_time( &mytimeval );
printf( "Current system time is:\n");
show_time(mytimeval.tv_secs);

/* just shows how to set up for using the timer functions, does not */
/* demonstrate the functions themselves.  (TimerBase must have a    */
/* legal value before AddTime, SubTime or CmpTime are performed.    */
tr = create_timer( UNIT_MICROHZ );
TimerBase = (struct Library *)tr->tr_node.io_Device;

/* and how to clean up afterwards */
TimerBase = (struct Library *)(-1);
delete_timer( tr );
}

struct timerequest *create_timer( ULONG unit )
{
/* return a pointer to a timer request.  If any problem, return NULL */
LONG error;
struct MsgPort *timerport;
struct timerequest *TimerIO;

timerport = CreatePort( 0, 0 );
if (timerport == NULL )
    return( NULL );

TimerIO = (struct timerequest *)
    CreateExtIO( timerport, sizeof( struct timerequest ) );
if (TimerIO == NULL )
    {
    DeletePort(timerport);   /* Delete message port */
    return( NULL );
    }

error = OpenDevice( TIMERNAME, unit,(struct IORequest *) TimerIO, 0L );
if (error != 0 )
    {
    delete_timer( TimerIO );
    return( NULL );
    }
return( TimerIO );
}

/* more precise timer than AmigaDOS Delay() */
LONG time_delay( struct timeval *tv, LONG unit )
{
struct timerequest *tr;
/* get a pointer to an initialized timer request block */
tr = create_timer( unit );

/* any nonzero return says timedelay routine didn't work. */
if (tr == NULL )
    return( -1L );

wait_for_timer( tr, tv );

/* deallocate temporary structures */
delete_timer( tr );
return( 0L );
}

void wait_for_timer(struct timerequest *tr, struct timeval *tv )
{

tr->tr_node.io_Command = TR_ADDREQUEST; /* add a new timer request */

/* structure assignment */
tr->tr_time = *tv;

/* post request to the timer -- will go to sleep till done */
DoIO((struct IORequest *) tr );
}

LONG set_new_time(LONG secs)
{
struct timerequest *tr;
tr = create_timer( UNIT_MICROHZ );

/* non zero return says error */
if (tr == 0 )
    return( -1 );

tr->tr_time.tv_secs = secs;
tr->tr_time.tv_micro = 0;
tr->tr_node.io_Command = TR_SETSYSTIME;
DoIO((struct IORequest *) tr );

delete_timer(tr);
return(0);
}

LONG get_sys_time(struct timeval *tv)
{
struct timerequest *tr;
tr = create_timer( UNIT_MICROHZ );

/* non zero return says error */
if (tr == 0 )
    return( -1 );

tr->tr_node.io_Command = TR_GETSYSTIME;
DoIO((struct IORequest *) tr );

/* structure assignment */
*tv = tr->tr_time;

delete_timer( tr );
return( 0 );
}

void delete_timer(struct timerequest *tr )
{
struct MsgPort *tp;

if (tr != 0 )
    {
    tp = tr->tr_node.io_Message.mn_ReplyPort;

    if (tp != 0)
        DeletePort(tp);

    CloseDevice( (struct IORequest *) tr );
    DeleteExtIO( (struct IORequest *) tr );
    }
}

void show_time(ULONG secs)
{
ULONG days,hrs,mins;

/* Compute days, hours, etc. */
mins=secs/60;
hrs=mins/60;
days=hrs/24;
secs=secs%60;
mins=mins%60;
hrs=hrs%24;

/* Display the time */
printf("*   Hour Minute Second  (Days since Jan.1,1978)\n");
printf("*%5ld:%5ld:%5ld      (%6ld )\n\n",hrs,mins,secs,days);
}      /* end of main */


Devices/Dev_examples/Get_Systime.c

/* Get_Systime.c
 *
 * Get system time example
 *
 * Compile with SAS C 5.10: LC -b1 -cfistq -v -y -L
 *
 * Run from CLI only
 */

#include <exec/types.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <devices/timer.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }     /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

struct timerequest *TimerIO;
struct MsgPort *TimerMP;
struct Message *TimerMSG;

VOID main(VOID);

void main()
{
LONG error;
ULONG days,hrs,secs,mins,mics;

if (TimerMP = CreatePort(0,0))
    {
    if (TimerIO = (struct timerequest *)
                   CreateExtIO(TimerMP,sizeof(struct timerequest)) )
        {
            /* Open with UNIT_VBLANK, but any unit can be used */
        if (!(error=OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)TimerIO,0L)))
            {
            /* Issue the command and wait for it to finish, then get the reply */
            TimerIO->tr_node.io_Command = TR_GETSYSTIME;
            DoIO((struct IORequest *) TimerIO);

            /* Get the results and close the timer device */
            mics=TimerIO->tr_time.tv_micro;
            secs=TimerIO->tr_time.tv_secs;

            /* Compute days, hours, etc. */
            mins=secs/60;
            hrs=mins/60;
            days=hrs/24;
            secs=secs%60;
            mins=mins%60;
            hrs=hrs%24;

            /* Display the time */
            printf("\nSystem Time (measured from Jan.1,1978)\n");
            printf("  Days   Hours  Minutes Seconds Microseconds\n");
            printf("%6ld %6ld %6ld %6ld %10ld\n",days,hrs,mins,secs,mics);

            /* Close the timer device */
            CloseDevice((struct IORequest *) TimerIO);
            }
        else
            printf("\nError: Could not open timer device\n");

        /* Delete the IORequest structure */
        DeleteExtIO(TimerIO);
        }
    else
        printf("\nError: Could not create I/O structure\n");

    /* Delete the port */
    DeletePort(TimerMP);
    }
else
    printf("\nError: Could not create port\n");
}


Devices/Dev_examples/Multiple_Timers.c

/*  Multiple_Timers.c
 *
 *  This program is designed to do multiple (3) time requests using one
 *  OpenDevice.  It creates a message port - TimerMP, creates an
 *  extended I/O structure of type timerequest named TimerIO[0] and
 *  then uses that to open the device.  The other two time request
 *  structures - TimerIO[1] and TimerIO[2] - are created using AllocMem
 *  and then copying TimerIO[0] into them.  The tv_secs field of each
 *  structure is set and then three SendIOs are done with the requests.
 *  The program then goes into a while loop until all messages are received.
 *
 * Compile with SAS C 5.10  lc -b1 -cfistq -v -y -L
 *
 * Run from CLI only
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <devices/timer.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

VOID main(VOID);

void main(void)
{
struct timerequest *TimerIO[3];
struct MsgPort *TimerMP;
struct Message *TimerMSG;

ULONG error,x,seconds[3]={4,1,2}, microseconds[3]={0,0,0};

int allin = 3;
char *position[]={"last","second","first"};

if (TimerMP = CreatePort(0,0))
    {
    if (TimerIO[0] = (struct timerequest *)
                      CreateExtIO(TimerMP,sizeof(struct timerequest)) )
        {
            /* Open the device once */
        if (!(error=OpenDevice( TIMERNAME, UNIT_VBLANK,(struct IORequest *) TimerIO[0], 0L)))
            {
            /* Set command to TR_ADDREQUEST */
            TimerIO[0]->tr_node.io_Command = TR_ADDREQUEST;

            if (TimerIO[1]=(struct timerequest *)
                    AllocMem(sizeof(struct timerequest),MEMF_PUBLIC | MEMF_CLEAR))
                {
                if (TimerIO[2]=(struct timerequest *)
                       AllocMem(sizeof(struct timerequest),MEMF_PUBLIC | MEMF_CLEAR))
                    {
                    /* Copy fields from the request used to open the timer device */
                    *TimerIO[1] = *TimerIO[0];
                    *TimerIO[2] = *TimerIO[0];

                    /* Initialize other fields */
                    for (x=0;x<3;x++)
                        {
                        TimerIO[x]->tr_time.tv_secs   = seconds[x];
                        TimerIO[x]->tr_time.tv_micro  = microseconds[x];
                        printf("\nInitializing TimerIO[%d]",x);
                        }

                    printf("\n\nSending multiple requests\n\n");

                    /* Send multiple requests asynchronously */
                    /* Do not got to sleep yet...            */
                    SendIO((struct IORequest *)TimerIO[0]);
                    SendIO((struct IORequest *)TimerIO[1]);
                    SendIO((struct IORequest *)TimerIO[2]);

                    /* There might be other processing done here */

                    /* Now go to sleep with WaitPort() waiting for the requests */
                    while (allin)
                          {
                          WaitPort(TimerMP);
                          /* Get the reply message */
                          TimerMSG=GetMsg(TimerMP);
                          for (x=0;x<3;x++)
                              if (TimerMSG==(struct Message *)TimerIO[x])
                                  printf("Request %ld finished %s\n",x,position[--allin]);
                          }

                    FreeMem(TimerIO[2],sizeof(struct timerequest));
                    }

                else
                    printf("Error: could not allocate TimerIO[2] memory\n");

                FreeMem(TimerIO[1],sizeof(struct timerequest));
                }

            else
                printf("Error could not allocate TimerIO[1] memory\n");

            CloseDevice((struct IORequest *) TimerIO[0]);
            }

        else
            printf("\nError: Could not OpenDevice\n");

        DeleteExtIO((struct IORequest *) TimerIO[0]);
        }

    else
        printf("Error: could not create IORequest\n");

    DeletePort(TimerMP);
    }

else
    printf("\nError: Could not CreatePort\n");
}


Devices/Dev_examples/Timer_Arithmetic.c

/*
 * Timer_Arithmetic.c
 *
 * Example of timer device arithmetic functions
 *
 * Compile with SAS C 5.10  lc -b1 -cfistq -v -y -L
 *
 * Run from CLI only
 *
 */

#include <exec/types.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <devices/timer.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/timer_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }     /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

struct Library *TimerBase;  /* setup the interface variable (must be global) */

void main(int argc,char **argv)
{
struct timeval     *time1, *time2, *time3;
struct timerequest *tr;
LONG               error,result;

/*------------------------------------*/
/* Get some memory for our structures */
/*------------------------------------*/
time1=(struct timeval *)AllocMem(sizeof(struct timeval),
                               MEMF_PUBLIC | MEMF_CLEAR);
time2=(struct timeval *)AllocMem(sizeof(struct timeval),
                               MEMF_PUBLIC | MEMF_CLEAR);
time3=(struct timeval *)AllocMem(sizeof(struct timeval),
                               MEMF_PUBLIC | MEMF_CLEAR);
tr=(struct timerequest *)AllocMem(sizeof(struct timerequest),
                               MEMF_PUBLIC | MEMF_CLEAR);
/* Make sure we got the memory */
if(!time1 | !time2 | !time3 | !tr) goto cleanexit;

/*---------------------------------------------------------------------------*/
/* Set up values to test time arithmetic with.  In a real application these  */
/* values might be filled in via the GET_SYSTIME command of the timer device */
/*---------------------------------------------------------------------------*/
time1->tv_secs = 3;   time1->tv_micro = 0;           /* 3.0 seconds */
time2->tv_secs = 2;   time2->tv_micro = 500000;      /* 2.5 seconds */
time3->tv_secs = 1;   time3->tv_micro = 900000;      /* 1.9 seconds */

printf("Time1 is %ld.%ld\n" , time1->tv_secs,time1->tv_micro);
printf("Time2 is %ld.%ld\n" , time2->tv_secs,time2->tv_micro);
printf("Time3 is %ld.%ld\n\n",time3->tv_secs,time3->tv_micro);

/*-------------------------------*/
/* Open the MICROHZ timer device */
/*-------------------------------*/
error = OpenDevice(TIMERNAME,UNIT_MICROHZ,(struct IORequest *) tr, 0L);
if(error) goto cleanexit;

/* Set up to use the special time arithmetic functions */
TimerBase = (struct Library *)tr->tr_node.io_Device;

/*--------------------------------------------------------------------------*/
/* Now that TimerBase is initialized, it is permissible to call the         */
/* time-comparison or time-arithmetic routines.  Result of this example     */
/* is -1 which means the first parameter has greater time value than second */
/* parameter; +1 means the second parameter is bigger; 0 means equal.       */
/*--------------------------------------------------------------------------*/
result = CmpTime( time1, time2 );
printf("Time1 and Time2 compare = %ld\n",result);

/* Add time2 to time1, result in time1 */
AddTime( time1, time2);
printf("Time1 + Time2 = %ld.%ld\n",time1->tv_secs,time1->tv_micro);

/* Subtract time3 from time2, result in time2 */
SubTime( time2, time3);
printf("Time2 - Time3 = %ld.%ld\n",time2->tv_secs,time2->tv_micro);

/*------------------------------------*/
/* Free system resources that we used */
/*------------------------------------*/
cleanexit:
  if (time1)
      FreeMem(time1,sizeof(struct timeval));
  if (time2)
      FreeMem(time2,sizeof(struct timeval));
  if (time3)
      FreeMem(time3,sizeof(struct timeval));
  if (!error)
      CloseDevice((struct IORequest *) tr);
  if (tr)
      FreeMem(tr,sizeof(struct timerequest));
}


Devices/Dev_examples/Swap_Buttons.c

/*
 * Swap_Buttons.c
 *
 * This example swaps the function of the left and right mouse buttons
 * The C code is just the wrapper that installs and removes the
 * input.device handler that does the work.
 *
 * The handler is written in assembly code since it is important that
 * handlers be as fast as possible while processing the input events.
 *
 * Compile and link as follows:
 *
 * SAS C 5.10:
 *  LC -b1 -cfirst -v -w Swap_Buttons.c
 *
 * Adapt assemble:
 *  HX68 InputHandler.a to InputHandler.o
 *
 * BLink:
 *  BLink from LIB:c.o+Swap_Buttons.o+InputHandler.o LIB LIB:lc.lib
 *  LIB:amiga.lib TO Swap_Buttons
 *
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/interrupts.h>
#include <devices/input.h>
#include <intuition/intuition.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/intuition_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }     /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

UBYTE NameString[]="Swap Buttons";

struct NewWindow mywin={50,40,124,18,0,1,CLOSEWINDOW,
                      WINDOWDRAG|WINDOWCLOSE|SIMPLE_REFRESH|NOCAREREFRESH,
                      NULL,NULL,NameString,NULL,NULL,0,0,0,0,WBENCHSCREEN};

extern VOID ButtonSwap();

extern struct IntuitionBase *IntuitionBase;

/*
 * This routine opens a window and waits for the one event that
 * can happen (CLOSEWINDOW)  This is just to let the user play with
 * the swapped buttons and then close the program...
 */
VOID WaitForUser(VOID)
{
struct Window  *win;

if (IntuitionBase=(struct IntuitionBase *)
                                OpenLibrary("intuition.library",33L))
    {
    if (win=OpenWindow(&mywin))
        {
        WaitPort(win->UserPort);
        ReplyMsg(GetMsg(win->UserPort));

        CloseWindow(win);
        }
    CloseLibrary((struct Library *)IntuitionBase);
    }
}

VOID main(VOID)
{
struct IOStdReq  *inputReqBlk;
struct MsgPort   *inputPort;
struct Interrupt *inputHandler;

if (inputPort=CreatePort(NULL,NULL))
    {
    if (inputHandler=AllocMem(sizeof(struct Interrupt),
                               MEMF_PUBLIC|MEMF_CLEAR))
        {
        if (inputReqBlk=(struct IOStdReq *)CreateExtIO(inputPort,
                                                 sizeof(struct IOStdReq)))
            {
            if (!OpenDevice("input.device",NULL,
                             (struct IORequest *)inputReqBlk,NULL))
                {
                inputHandler->is_Code=ButtonSwap;
                inputHandler->is_Data=NULL;
                inputHandler->is_Node.ln_Pri=100;
                inputHandler->is_Node.ln_Name=NameString;
                inputReqBlk->io_Data=(APTR)inputHandler;
                inputReqBlk->io_Command=IND_ADDHANDLER;
                DoIO((struct IORequest *)inputReqBlk);

                WaitForUser();

                inputReqBlk->io_Data=(APTR)inputHandler;
                inputReqBlk->io_Command=IND_REMHANDLER;
                DoIO((struct IORequest *)inputReqBlk);

                CloseDevice((struct IORequest *)inputReqBlk);
                }
            else
                printf("Error: Could not open input.device\n");

            DeleteExtIO((struct IORequest *)inputReqBlk);
            }
        else
            printf("Error: Could not create I/O request\n");

        FreeMem(inputHandler,sizeof(struct Interrupt));
        }
    else
        printf("Error: Could not allocate interrupt struct memory\n");

    DeletePort(inputPort);
    }
else
    printf("Error: Could not create message port\n");
}

************************************************************************
*       InputHandler.a
*
* InputHandler that does a Left/Right mouse button swap...
*
* See Swap_Buttons.c for details on how to compile/assemble/link...
*
************************************************************************
*
* Required includes...
*
        INCDIR  "include:"
        INCLUDE "exec/types.i"
        INCLUDE "exec/io.i"
        INCLUDE "devices/inputevent.i"
*
************************************************************************
*
* Make the entry point external...
*
        xdef    _ButtonSwap
*
************************************************************************
*
* This is the input handler that will swap the
* mouse buttons for left handed use.
*
* The event list gets passed to you in  a0.
* The is_Data field is passed to you in a1.
* This example does not use the is_Data field...
*
* On exit you must return the event list in d0.  In this way
* you could add or remove items from the event list.
*
* The handler gets called here...
*
*
_ButtonSwap:    move.l  a0,-(sp)        ; Save the event list
*
* Since the event list could be a linked list, we start a loop
* here to handle all of the events passed to us.
*
CheckLoop:      move.w  ie_Qualifier(a0),d1             ; Get qualifiers...
                move.w  d1,d0                           ; Two places...
*
* Since we are changing left and right mouse buttons, we need to make
* sure that we change the qualifiers on all of the messages.  The
* left and right mouse buttons are tracked in the message qualifiers
* for use in such things as dragging.  To make sure that we continue
* to drag correctly, we change the qualifiers.
*
CheckRight:     btst    #IEQUALIFIERB_RBUTTON,d1        ; Check for right
                beq.s   NoRight
                bset    #IEQUALIFIERB_LEFTBUTTON,d0     ; Set the left...
                beq.s   CheckLeft
NoRight:        bclr    #IEQUALIFIERB_LEFTBUTTON,d0     ; Clear the left...
*
CheckLeft:      btst    #IEQUALIFIERB_LEFTBUTTON,d1     ; Check for left
                beq.s   NoLeft
                bset    #IEQUALIFIERB_RBUTTON,d0        ; Set the right...
                beq.s   SaveQual
NoLeft:         bclr    #IEQUALIFIERB_RBUTTON,d0        ; Clear the right..
*
SaveQual:       move.w  d0,ie_Qualifier(a0)             ; Save back...
*
* The actual button up/down events are transmitted as the
* code field in RAWMOUSE events.  The code field must the be
* checked and modified when needed on RAWMOUSE events.  If the
* event is not a RAWMOUSE, we are done with it.
*
                cmp.b   #IECLASS_RAWMOUSE,ie_Class(a0)  ; Check for mouse
                bne.s   NextEvent                       ; If not, next...
*
                move.w  ie_Code(a0),d0                  ; Get code...
                move.w  d0,d1                           ; Save...
                and.w   #$7F,d0                         ; Mask UP_PREFIX
                cmp.w   #IECODE_LBUTTON,d0              ; Check for Left...
                beq.s   SwapThem                        ; If so, swap...
                cmp.w   #IECODE_RBUTTON,d0              ; Check for Right..
                bne.s   NextEvent                       ; If not, next...
*
SwapThem:       eor.w   #1,d1                           ; Flip bottom bit
                move.w  d1,ie_Code(a0)                  ; Save it...
*
* The event list is linked via a pointer to the next event
* in the first element of the structure.  That is why it is not
* nessesary to use:  move.l ie_NextEvent(a0),d0
*
* The reason I move to d0 first is that this also checks for zero.
* The last event in the list will have a NULL ie_NextEvent field.
* This is NOT as standard EXEC list where the node after the last
* node is NULL.  Input events are single-linked for performance.
*
NextEvent:      move.l  (a0),d0                         ; Get next event
                move.l  d0,a0                           ; into a0...
                bne.s   CheckLoop                       ; Do some more.
*
* All done, just return the event list...  (in d0)
*
                move.l  (sp)+,d0        ; Get event list back...
                rts                     ; return from handler...


Devices/Dev_examples/Set_Mouse.c

/*
 * Set_Mouse.c
 *
 * This example sets the mouse at x=100 and y=200
 *
 * Compile with SAS C 5.10: LC -b1 -cfistq -v -y -L
 * Requires Kickstart 36 or greater.
 *
 * Run from CLI only
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <devices/input.h>
#include <devices/inputevent.h>
#include <intuition/screens.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

struct IntuitionBase *IntuitionBase;

void main(void)
{
struct IOStdReq   *InputIO;           /* I/O request block */
struct MsgPort    *InputMP;           /* Message port */
struct InputEvent *FakeEvent;         /* InputEvent pointer */
struct IEPointerPixel *NeoPix;      /* New mouse position pointer */
struct Screen *PubScreen;             /* Screen pointer */

if (InputMP = CreateMsgPort())
    {
    if (FakeEvent = AllocMem(sizeof(struct InputEvent),MEMF_PUBLIC))
        {
        if (NeoPix  = AllocMem(sizeof(struct IEPointerPixel),MEMF_PUBLIC))
            {
            if (InputIO = CreateIORequest(InputMP,sizeof(struct IOStdReq)))
                {
                if (!OpenDevice("input.device",NULL,
                               (struct IORequest *)InputIO,NULL))
                    {
                        /* Open Intuition library */
                    if (IntuitionBase=(struct IntuitionBase *)
                                      OpenLibrary("intuition.library",36L))
                        {
                        /* Get pointer to screen and lock screen */
                        if (PubScreen=(struct Screen *)LockPubScreen(NULL))
                            {
                            /* Set up IEPointerPixel fields */
                            /* WB screen */
                            NeoPix->iepp_Screen=(struct Screen *)PubScreen;
                            /* put pointer at x = 100 */
                            NeoPix->iepp_Position.X = 100;
                            /* put pointer at y = 200 */
                            NeoPix->iepp_Position.Y = 200;

                            /* Set up InputEvent fields */
                            /* IEPointerPixel */
                            FakeEvent->ie_EventAddress = (APTR)NeoPix;
                            FakeEvent->ie_NextEvent = NULL;
                            /* new mouse pos */
                            FakeEvent->ie_Class = IECLASS_NEWPOINTERPOS;
                            /* on pixel */
                            FakeEvent->ie_SubClass = IESUBCLASS_PIXEL;
                            FakeEvent->ie_Code = IECODE_NOBUTTON;
                            /* absolute positioning */
                            FakeEvent->ie_Qualifier = NULL;

                            /* InputEvent */
                            InputIO->io_Data = (APTR)FakeEvent;
                            InputIO->io_Length = sizeof(struct InputEvent);
                            InputIO->io_Command = IND_WRITEEVENT;
                            DoIO((struct IORequest *)InputIO);
                            /* Unlock screen */
                            UnlockPubScreen(NULL,PubScreen);
                            }
                        else
                            printf("Could not get pointer to screen\n");
                        /* Close intuition library */
                        CloseLibrary(IntuitionBase);
                        }
                    else
                        /* Can't open V36 (or higher) intuition.library */
                        printf("Error:Can't open V36 intuition.library\n");

                    CloseDevice((struct IORequest *)InputIO);
                    }
                else
                    printf("Error: Could not open input.device\n");

                DeleteIORequest(InputIO);
                }
            else
                printf("Error: Could not create IORequest\n");

            FreeMem(NeoPix,sizeof(struct IEPointerPixel));
            }
        else
            printf("Error: Could not allocate memory for NeoPix\n");

        FreeMem(FakeEvent,sizeof(struct InputEvent));
        }
    else
        printf("Error: Could not allocate memory for FakeEvent\n");

    DeleteMsgPort(InputMP);
    }
else
    printf("Error: Could not create message port\n");
}


Devices/Dev_examples/Track_Copy.c

/*
 * Track_Copy.c
 *
 * This program does a track by track copy from one drive to another
 *
 * Compile with SAS C 5.10  LC -cfist -ms -v -L
 *
 * This program will only run from the CLI.  If started from
 * the workbench, it will just exit...
 *
 * Usage:  trackcopy  dfx dfy
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <devices/trackdisk.h>
#include <dos/dosextens.h> */

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/dos_protos.h>

#include <stdio.h>
#include <string.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }     /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

#define TRACK_SIZE      ((LONG)(NUMSECS * TD_SECTOR))

/*
 * Turn the BUSY flag off/on for the drive
 * If onflag is TRUE, the disk will be marked as busy...
 *
 * This is to stop the validator from executing while
 * we are playing with the disks.
 */
VOID disk_busy(UBYTE *drive,LONG onflag)
{
struct StandardPacket *pk;
struct Process        *tsk;

    tsk=(struct Process *)FindTask(NULL);
    if (pk=AllocMem(sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR))
    {
        pk->sp_Msg.mn_Node.ln_Name=(UBYTE *)&(pk->sp_Pkt);

        pk->sp_Pkt.dp_Link=&(pk->sp_Msg);
        pk->sp_Pkt.dp_Port=&(tsk->pr_MsgPort);
        pk->sp_Pkt.dp_Type=ACTION_INHIBIT;
        pk->sp_Pkt.dp_Arg1=(onflag ? -1L : 0L);

        PutMsg(DeviceProc(drive),(struct Message *)pk);
        WaitPort(&(tsk->pr_MsgPort));
        GetMsg(&(tsk->pr_MsgPort));
        FreeMem(pk,(long)sizeof(*pk));
    }
}

/*
 * This turns the motor off
 */
VOID Motor_Off(struct IOExtTD *disk)
{
    disk->iotd_Req.io_Length=0;
    disk->iotd_Req.io_Command=TD_MOTOR;
    DoIO((struct IORequest *)disk);
}

/*
 * This turns the motor on
 */
VOID    Motor_On(struct IOExtTD *disk)
{
    disk->iotd_Req.io_Length=1;
    disk->iotd_Req.io_Command=TD_MOTOR;
    DoIO((struct IORequest *)disk);
}

/*
 * This reads a track, reporting any errors...
 */

SHORT Read_Track(struct IOExtTD *disk,UBYTE *buffer,SHORT track)
{
SHORT All_OK=TRUE;

    disk->iotd_Req.io_Length=TRACK_SIZE;
    disk->iotd_Req.io_Data=(APTR)buffer;
    disk->iotd_Req.io_Command=CMD_READ;
    disk->iotd_Req.io_Offset=(ULONG)(TRACK_SIZE * track);
    DoIO((struct IORequest *)disk);
    if (disk->iotd_Req.io_Error)
    {
        All_OK=FALSE;
        printf("Error %u when reading track %d",disk->iotd_Req.io_Error,track);
    }
    return(All_OK);
}

/*
 * This writes a track, reporting any errors...
 */

SHORT Write_Track(struct IOExtTD *disk,UBYTE *buffer,SHORT track)
{
SHORT All_OK=TRUE;

    disk->iotd_Req.io_Length=TRACK_SIZE;
    disk->iotd_Req.io_Data=(APTR)buffer;
    disk->iotd_Req.io_Command=TD_FORMAT;
    disk->iotd_Req.io_Offset=(ULONG)(TRACK_SIZE * track);
    DoIO((struct IORequest *)disk);
    if (disk->iotd_Req.io_Error)
    {
        All_OK=FALSE;
        printf("Error %d when writing track %d",disk->iotd_Req.io_Error,track);
    }
    return(All_OK);
}

/*
 * This function finds the number of TRACKS on the device.
 * NOTE That this is TRACKS and not cylinders.  On a Two-Head
 * drive (such as the standard 3.5" drives) the number of tracks
 * is 160, 80 cylinders, 2-heads.
 */

SHORT FindNumTracks(struct IOExtTD *disk)
{
    disk->iotd_Req.io_Command=TD_GETNUMTRACKS;
    DoIO((struct IORequest *)disk);
    return((SHORT)disk->iotd_Req.io_Actual);
}

/*
 * This routine allocates the memory for one track and does
 * the copy loop.
 */

VOID Do_Copy(struct IOExtTD *diskreq0,struct IOExtTD *diskreq1)
{
UBYTE *buffer;
SHORT track;
SHORT All_OK;
SHORT NumTracks;

    if (buffer=AllocMem(TRACK_SIZE,MEMF_CHIP|MEMF_PUBLIC))
    {
        printf(" Starting Motors\r");
        Motor_On(diskreq0);
        Motor_On(diskreq1);
        All_OK=TRUE;

        NumTracks=FindNumTracks(diskreq0);

        for (track=0;(track<NumTracks) && All_OK;track++)
        {
            printf(" Reading track %d\r",track);

            if (All_OK=Read_Track(diskreq0,buffer,track))
            {
                printf(" Writing track %d\r",track);

                All_OK=Write_Track(diskreq1,buffer,track);
            }
        }
        if (All_OK) printf(" * Copy complete *");
        printf("\n");
        Motor_Off(diskreq0);
        Motor_Off(diskreq1);
        FreeMem(buffer,TRACK_SIZE);
    }
    else printf("No memory for track buffer...\n");
}

/*
 * Prompts the user to remove one of the disks.
 * Since this program makes an EXACT copy of the disks
 * AmigaDOS would get confused by them so one must be removed
 * before the validator is let loose.  Also, note that the
 * disks may NEVER be in drives on the SAME computer at the
 * SAME time unless one of the disks is renamed.  This is due
 * to a bug in the system.  It would normally be prevented
 * by a diskcopy program that knew the disk format and modified
 * the creation date by one clock-tick such that the disks would
 * be different.
 */

VOID Remove_Disks(VOID)
{
    printf("\nYou *MUST* remove at least one of the disks now.\n");
    printf("\nPress RETURN when ready\n");
    while(getchar()!='\n');
}

/*
 * Prompts the user to insert the disks.
 */

VOID Insert_Disks(char drive1[], char drive2[])
{
    printf("\nPlease insert source disk in %s\n",drive1);
    printf("\n          and destination in %s\n",drive2);
    printf("\nPress RETURN when ready\n");
    while(getchar()!='\n');
}

/*
 * Open the devices and mark them as busy
 */
VOID Do_OpenDevice(struct IOExtTD *diskreq0,struct IOExtTD *diskreq1, long unit[])
{
char drive1[] = "DFx:";  /* String for source drive */
char drive2[] = "DFx:";  /* String for destination drive */

    drive1[2] = unit[0]+ '0';  /* Set drive number for source */

    if (!OpenDevice(TD_NAME,unit[0],(struct IORequest *)diskreq0,0L))
    {
          disk_busy(drive1,TRUE);
          drive2[2] = unit[1]+ '0';  /* Set drive number for destination */

        if (!OpenDevice(TD_NAME,unit[1],(struct IORequest *)diskreq1,0L))
        {
            disk_busy(drive2,TRUE);

            Insert_Disks(drive1,drive2);
            Do_Copy(diskreq0,diskreq1);
            Remove_Disks();

            disk_busy(drive2,FALSE);
            CloseDevice((struct IORequest *)diskreq1);
        }
        else printf("Could not open %s\n",drive2);

        disk_busy(drive1,FALSE);
        CloseDevice((struct IORequest *)diskreq0);
    }
    else printf("Could not open %s\n",drive1);
}

SHORT ParseArgs(int argc, char **argv, long Unit[])
#define OKAY 1
{
int j=1, params = OKAY;
char *position[]={"First","Second"};

if (argc != 3)
    {
    printf("\nYou must specify a source and destination disk\n");
    return(!OKAY);
    }
else if (strcmp(argv[1],argv[2]) == 0)
           {
           printf("\nYou must specify different disks for source and destination\n");
           return(!OKAY);
           }
     else while (params == OKAY && j<3)
           {
           if (strnicmp(argv[j],"df",2)==0)
             {
             if (argv[j][2] >= '0' && argv[j][2] <= '3' && argv[j][3] == '\0')
               {
               Unit[j-1] = argv[j][2] - 0x30;
               }
             else
               {
               printf("\n%s parameter is wrong, unit number must be 0-3\n",position[j-1]);
               params = !OKAY;
               return(!OKAY);
               }
             }
           else
             {
             printf("\n%s parameter is wrong, you must specify a floppy device df0 - df3\n",
                     position[j-1]);
             params=!OKAY;
             return(!OKAY);
             }
           j++;
           }
return(OKAY);
}

VOID main(int argc,char **argv)
{
struct IOExtTD *diskreq0;
struct IOExtTD *diskreq1;
struct MsgPort *diskPort;
long unit[2];

    if (ParseArgs(argc, argv, unit))       /* Check inputs */
    {
        if (diskPort=CreatePort(NULL,NULL))
        {
            if (diskreq0=(struct IOExtTD *)CreateExtIO(diskPort,
                                                 sizeof(struct IOExtTD)))
            {
                if (diskreq1=(struct IOExtTD *)CreateExtIO(diskPort,
                                                 sizeof(struct IOExtTD)))
                {
                    Do_OpenDevice(diskreq0,diskreq1, unit);
                    DeleteExtIO((struct IORequest *)diskreq1);
                }
                else printf("Out of memory\n");
                DeleteExtIO((struct IORequest *)diskreq0);
            }
            else printf("Out of memory\n");
            DeletePort(diskPort);
        }
        else printf("Could not create diskReq port\n");
    }
}
/*
   Only one per customer.
   ----------------------
   Since this example program makes an exact track-for-track duplicate,
   AmigaDOS will get confused if both disks are in drives on the system
   at the same time. While the disks are inhibited, this does not cause
   a problem, but during normal operation, this will cause a system
   hang. To prevent this, you can relabel one of the disks. A commercial
   diskcopy program would have to understand the disk format and either
   relabel the disk or modify the volume creation date/time by a bit in
   order to make the disks look different to the system.
*/


Devices/Dev_examples/Read_Keyboard_Matrix.c

/*
 * Read_Keyboard_Matrix.c
 *
 * Compile with SAS C 5.10  lc -b1 -cfistq -v -y -L
 *
 * Run from CLI only
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/libraries.h>
#include <dos/dos.h>
#include <devices/keyboard.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }     /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

/*
 * There are keycodes from 0x00 to 0x7F, so the matrix needs to be
 * of 0x80 bits in size, or 0x80/8 which is 0x10 or 16 bytes...
 */
#define MATRIX_SIZE 16L

/*
 * This assembles the matrix for display that translates directly
 * to the RAW key value of the key that is up or down
 */

VOID Display_Matrix(UBYTE *keyMatrix)
{
SHORT  bitcount;
SHORT  bytecount;
SHORT   mask;
USHORT twobyte;

printf("\n    0 1 2 3 4 5 6 7");
printf("\n  +-----------------");
for (bitcount=0;bitcount<16;bitcount++)
    {
    printf("\n%x |",bitcount);
    mask=1 << bitcount;
    for (bytecount=0;bytecount<16;bytecount+=2)
        {
        twobyte=keyMatrix[bytecount] | (keyMatrix[bytecount+1] << 8);
        if (twobyte & mask)
            printf(" *");
        else
            printf(" -");
        }
    }
printf("\n\n");
}

void main(int argc, char *argv[])
{
extern struct Library *SysBase;
struct IOStdReq *KeyIO;
struct MsgPort  *KeyMP;
UBYTE    *keyMatrix;

if (KeyMP=CreatePort(NULL,NULL))
  {
  if (KeyIO=(struct IOStdReq *)CreateExtIO(KeyMP,sizeof(struct IOStdReq)))
    {
    if (!OpenDevice("keyboard.device",NULL,(struct IORequest *)KeyIO,NULL))
      {
      if (keyMatrix=AllocMem(MATRIX_SIZE,MEMF_PUBLIC|MEMF_CLEAR))
        {
         KeyIO->io_Command=KBD_READMATRIX;
         KeyIO->io_Data=(APTR)keyMatrix;
         KeyIO->io_Length= SysBase->lib_Version >= 36 ? MATRIX_SIZE : 13;
         DoIO((struct IORequest *)KeyIO);

        /* Check for CLI startup... */
        if (argc)
            Display_Matrix(keyMatrix);

        FreeMem(keyMatrix,MATRIX_SIZE);
        }
    else
          printf("Error: Could not allocate keymatrix memory\");

      CloseDevice((struct IORequest *)KeyIO);
      }
      else
        printf("Error: Could not open keyboard.device\n");

    DeleteExtIO((struct IORequest *)KeyIO);
    }
    else
      printf("Error: Could not create I/O request\n");

  DeletePort(KeyMP);
  }
  else
    printf("Error: Could not create message port\n");
}


Devices/Dev_examples/Key_Reset.c

/*
 * Key_Reset.c
 *
 * This is in two parts...
 *
 * Compile this C code with SAS C 5.10:
 *      lc -b1 -cfistq -v -y Key_Reset
 *
 * Assemble the ASM code with Adapt
 *  HX68 KeyHandler.a to KeyHandler.o
 *
 * Link with:
 * Blink FROM LIB:c.o+Key_Reset.o+KeyHandler.o TO
 *        Key_Reset LIB LIB:lc.lib LIB:amiga.lib
 */

/*
 * Keyboard device reset handler example...
 */
#include <exec/types.h>
#include <exec/io.h>
#include <exec/ports.h>
#include <exec/memory.h>
#include <devices/keyboard.h>
#include <intuition/intuition.h>
#include <exec/interrupts.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/intuition_protos.h>
#include <clib/dos_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }     /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
void main();
#endif

extern VOID ResetHandler();

UBYTE NameString[]="Reset Handler Test";

struct NewWindow mywin={0,0,178,10,0,1,CLOSEWINDOW,
                      WINDOWDRAG|WINDOWCLOSE|SIMPLE_REFRESH|NOCAREREFRESH
                      NULL,NULL,NameString,NULL,NULL,0,0,0,0,WBENCHSCREEN};

extern struct IntuitionBase *IntuitionBase;

struct MyData
    {
    struct Task  *MyTask;
           ULONG MySignal;
    };

/*
 * This routine opens a window and waits for the one event that
 * can happen (CLOSEWINDOW)
 */
short WaitForUser(ULONG MySignal)
{
struct Window  *win;
       short   ret=0;

if (IntuitionBase=(struct IntuitionBase *)
                   OpenLibrary("intuition.library",0L))
    {
    if (win=(struct Window *)OpenWindow(&mywin))
        {
        ret=(MySignal==Wait(MySignal | (1L << win->UserPort->mp_SigBit)));
        CloseWindow(win);
        }
    else
        printf("Error: Could not open window\n");
    CloseLibrary((struct Library *)IntuitionBase);
    }
else
    printf("Error: Could not open intution.library\n");
return(ret);
}

VOID main(int argc, char *argv[])
{
struct IOStdReq  *KeyIO;
struct MsgPort   *KeyMP;
struct Interrupt *keyHandler;
struct MyData    MyDataStuff;
       ULONG     MySignal;

if ((MySignal=AllocSignal(-1L))!=-1)
    {
    MyDataStuff.MyTask=FindTask(NULL);
    MyDataStuff.MySignal=1L << MySignal;

    if (KeyMP=CreatePort(NULL,NULL))
        {
        if (keyHandler =
                AllocMem(sizeof(struct Interrupt),MEMF_PUBLIC|MEMF_CLEAR))
            {
            if (KeyIO=(struct IOStdReq *)
                      CreateExtIO(KeyMP,sizeof(struct IOStdReq)))
                {
                if (!OpenDevice("keyboard.device",NULL,(struct IORequest *)
                                                        KeyIO,NULL))
                    {
                    keyHandler->is_Code=ResetHandler;
                    keyHandler->is_Data=(APTR)&MyDataStuff;

                    /*
                     * Note that only software interrupt priorities
                     * can be used for the .ln_Pri on the reset
                     * handler...
                     */
                    keyHandler->is_Node.ln_Pri=16;

                    keyHandler->is_Node.ln_Name=NameString;
                    KeyIO->io_Data=(APTR)keyHandler;
                    KeyIO->io_Command=KBD_ADDRESETHANDLER;
                    DoIO((struct IORequest *)KeyIO);

                    if (WaitForUser(MyDataStuff.MySignal))
                        {
                        if (argc) /* Check for CLI */
                            {
                            printf("System going down\n");
                            printf("Cleaning up...\n");
                            /* Show a delay, like cleanup... */
                            Delay(20);
                            printf("*Poof*\n");
                            }
                        /* We are done with our cleanup */

                        KeyIO->io_Data=(APTR)keyHandler;
                        KeyIO->io_Command=KBD_RESETHANDLERDONE;
                        DoIO((struct IORequest *)KeyIO);
                        /*
                         * Note that since the above call
                         * tells the system it is safe to reboot
                         * and will cause the reboot if this
                         * task was the last to say so, the call
                         * never really returns...  The system
                         * just reboots...
                         */
                        }

                    KeyIO->io_Data=(APTR)keyHandler;
                    KeyIO->io_Command=KBD_REMRESETHANDLER;
                    DoIO((struct IORequest *)KeyIO);

                    CloseDevice((struct IORequest *)KeyIO);
                    }
                else
                    printf("Error: Could not open keyboard.device\n");

                DeleteExtIO((struct IORequest *)KeyIO);
                }
            else
                printf("Error: Could not create I/O request\n");

            FreeMem(keyHandler,sizeof(struct Interrupt));
            }
        else
            printf("Error: Could not allocate memory for interrupt\n");

        DeletePort(KeyMP);
        }
    else
        printf("Error: Could not create message port\n");

    FreeSignal(MySignal);
    }
else
    printf("Error: Could not allocate signal\n");
}
\kern -20pt
************************************************************************
*       KeyHandler.a
*
* Keyboard reset handler that signals the task in the structure...
*
* See Key_Reset.c for details on how to compile/assemble/link...
*
************************************************************************
* Required includes...
*
        INCDIR  "include:"
        INCLUDE "exec/types.i"
        INCLUDE "exec/io.i"
        INCLUDE "devices/keyboard.i"
*
        xref    _AbsExecBase    ; We get this from outside...
        xref    _LVOSignal      ; We get this from outside...
*
************************************************************************
* Make the entry point external...
*
        xdef    _ResetHandler
*
************************************************************************
*
* This is the input handler
* The is_Data field is passed to you in a1.
*
* This is the structure that is passed in A1 in this example...
*
        STRUCTURE       MyData,0
        APTR            MyTask
        ULONG           MySignal
*
************************************************************************
* The handler gets called here...
*
_ResetHandler:  move.l  MySignal(a1),d0 ; Get signal to send
                move.l  MyTask(a1),a1           ; Get task
*
* Now signal the task...
*
                move.l  a6,-(sp)        ; Save the stack...
                move.l  _AbsExecBase,a6 ; Get ExecBase
                jsr     _LVOSignal(a6)  ; Send the signal
                move.l  (sp)+,a6        ; Restore A6
*
* Return to let other handlers execute.
*
                rts                     ; return from handler...
*
                END
************************************************************************


Devices/Dev_examples/Keyboard_Events.c

/* Shown below is an example keyboard.device read-event program:   */
/*
 * Keyboard_Events.c
 *
 * This example does not work very well in a system where
 * input.device is active since input.device also actively calls for
 * keyboard events via this call. For that reason, you will not get all of
 * the keyboard events. Neither will the input device;no one will be happy.
 *
 * Compile with SAS 5.10  lc -b1 -cfistq -v -y -L
 *
 * Run from CLI only
 */

#include <exec/types.h>
#include <exec/io.h>
#include <exec/ports.h>
#include <exec/memory.h>
#include <devices/inputevent.h>
#include <devices/keyboard.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }     /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

VOID Display_Event(struct InputEvent *keyEvent)
{
printf("Got key event: KeyCode: %2x  Quailifiers: %4x\n",
               keyEvent->ie_Code,
               keyEvent->ie_Qualifier);
}

VOID main(int argc, char *argv[])
{
struct IOStdReq   *keyRequest;
struct MsgPort    *keyPort;
struct InputEvent *keyEvent;
       SHORT      loop;

if (keyPort=CreatePort(NULL,NULL))
  {
  if (keyRequest=
          (struct IOStdReq *)CreateExtIO(keyPort,sizeof(struct IOStdReq)))
      {
      if (!OpenDevice("keyboard.device",NULL,
                        (struct IORequest *)keyRequest,NULL))
          {
          if (keyEvent=AllocMem(sizeof(struct InputEvent),MEMF_PUBLIC))
              {
              for (loop=0;loop<4;loop++)
                   {
                   keyRequest->io_Command=KBD_READEVENT;
                   keyRequest->io_Data=(APTR)keyEvent;

                   /*
                    * We want 1 event, so we just set the
                    * length field to the size, in bytes
                    * of the event.  For multiple events,
                    * set this to a multiple of that size.
                    * The keyboard device NEVER fills partial
                    * events...
                    */

                   keyRequest->io_Length=sizeof(struct InputEvent);
                   DoIO((struct IORequest *)keyRequest);

                       /* Check for CLI startup... */
                   if (argc)
                       Display_Event(keyEvent);
                   }

              FreeMem(keyEvent,sizeof(struct InputEvent));
              }
          else
              printf("Error:Could not allocate memory for InputEvent\n");

          CloseDevice((struct IORequest *)keyRequest);
          }
      else
          printf("Error: Could not open keyboard.device\n");

      DeleteExtIO((struct IORequest *)keyRequest);
      }
  else
      printf("Error: Could not create I/O request\n");

  DeletePort(keyPort);
  }
  else
    printf("Error: Could not create message port\n");
}


Devices/Dev_examples/Read_BattClock.c

/*
 * Read_BattClock.c
 *
 * Example of reading the BattClock and converting its output to
 * a useful measure of time by calling the Amiga2Date() utility function.
 *
 * Compile with SAS C 5.10  lc -b1 -cfistq -v -y -L
 *
 * Run from CLI only
 */

#include <exec/types.h>
#include <dos/dos.h>
#include <utility/date.h>
#include <resources/battclock.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/battclock_protos.h>
#include <clib/utility_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

VOID main(VOID);

struct Library *UtilityBase = NULL;
struct Library *BattClockBase;

VOID main(VOID)
{
UBYTE *Days[] ={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
UBYTE *Months[] = {"January","February","March","April","May","June",
                   "July","August","September","October","November","December"};
UBYTE *ampm;
ULONG AmigaTime;
struct ClockData MyClock;

if (UtilityBase = (struct Library *)OpenLibrary("utility.library",33))
    {
    if (BattClockBase= OpenResource(BATTCLOCKNAME))
        {
        /* Get number of seconds till now */
        AmigaTime = ReadBattClock();

        /* Convert to a ClockData structure */
        Amiga2Date(AmigaTime,&MyClock);

        printf("\nRobin, tell everyone the BatDate and BatTime");

        /* Print the Date */
        printf("\n\nOkay Batman, the BatDate is ");
        printf("%s, %s %d, %d",Days[MyClock.wday],Months[MyClock.month-1],
                               MyClock.mday,MyClock.year);

        /* Convert military time to normal time and set AM/PM */
        if (MyClock.hour < 12)
            ampm = "AM";        /* hour less than 12, must be morning */
        else
            {
            ampm = "PM";         /* hour greater than 12,must be night */
            MyClock.hour -= 12;  /* subtract the extra 12 of military */
            };

        if (MyClock.hour == 0)
            MyClock.hour = 12;   /* don't forget the 12s */

        /* Print the time */
        printf("\n             the BatTime is ");
        printf("%d:%02d:%02d %s\n\n",MyClock.hour,MyClock.min,MyClock.sec,ampm);
        }
    else
       printf("Error: Unable to open the %s\n",BATTCLOCKNAME);

    /* Close the utility library */
    CloseLibrary(UtilityBase);
    }

else
    printf("Error: Unable to open utility.library\n");
}


Devices/Dev_examples/Cia_Interval.c

/*
 * Cia_Interval.c
 *
 * Demonstrate allocation and use of a cia interval timer
 *
 * Compile with SAS C 5.10  lc -b1 -cfistq -v -y -L
 *
 * Run from CLI only
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/tasks.h>
#include <exec/interrupts.h>
#include <hardware/cia.h>
#include <resources/cia.h>

#include <clib/exec_protos.h>
#include <clib/cia_protos.h>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

/* prototypes */

void    StartTimer      (struct freetimer *ft, struct exampledata *ed);
int     FindFreeTimer   (struct freetimer *ft, int preferA);
int     TryTimer        (struct freetimer *ft);
void    main            ( USHORT, char **);

/* see usage of these defines in StartTimer() below */

#define COUNTDOWN 20
#define HICOUNT 0xFF
#define LOCOUNT 0xFF

#define STOPA_AND  CIACRAF_TODIN |CIACRAF_PBON | CIACRAF_OUTMODE | CIACRAF_SPMODE

        /*
        ;
        ; AND mask for use with control register A
        ; (interval timer A on either CIA)
        ;
        ; STOP -
        ;       START bit 0 == 0 (STOP IMMEDIATELY)
        ;       PBON  bit 1 == same
        ;       OUT   bit 2 == same
        ;       RUN   bit 3 == 0 (SET CONTINUOUS MODE)
        ;       LOAD  bit 4 == 0 (NO FORCE LOAD)
        ;       IN    bit 5 == 0 (COUNTS 02 PULSES)
        ;       SP    bit 6 == same
        ;       TODIN bit 7 == same (unused on ciacra)

        */

#define STOPB_AND  CIACRBF_ALARM | CIACRBF_PBON | CIACRBF_OUTMODE

        /*
        ;
        ; AND mask for use with control register B
        ; (interval timer B on either CIA)
        ;
        ; STOP -
        ;       START bit 0 == 0 (STOP IMMEDIATELY)
        ;       PBON  bit 1 == same
        ;       OUT   bit 2 == same
        ;       RUN   bit 3 == 0 (SET CONTINUOUS MODE)
        ;       LOAD  bit 4 == 0 (NO FORCE LOAD)
        ;       IN0   bit 5 == 0 (COUNTS 02 PULSES)
        ;       IN1   bit 6 == 0 (COUNTS 02 PULSES)
        ;       ALARM bit 7 == same (TOD alarm control bit)

        */

#define STARTA_OR  CIACRAF_START

        /*
        ;
        ; OR mask for use with control register A
        ; (interval timer A on either CIA)
        ;
        ; START -
        ;
        ;       START bit 0 == 1 (START TIMER)
        ;
        ;       All other bits unaffected.
        ;

        */

#define STARTB_OR  CIACRBF_START

        /*
        ;
        ; OR mask for use with control register B
        ; (interval timer A on either CIA)
        ;
        ; START -
        ;
        ;       START bit 0 == 1 (START TIMER)
        ;
        ;       All other bits unaffected.
        ;

        */

/*
 * Structure which will be used to hold all relevant information about
 * the cia timer we manage to allocate.
 *
 */

struct freetimer
{
    struct Library *ciabase;        /* CIA Library Base             */
    ULONG  timerbit;                /* timer bit allocated          */
    struct CIA *cia;                /* ptr to hardware              */
    UBYTE *ciacr;                   /* ptr to control register      */
    UBYTE *cialo;                   /* ptr to low byte of timer     */
    UBYTE *ciahi;                   /* ptr to high byte of timer    */
    struct Interrupt timerint;      /* Interrupt structure          */
    UBYTE  stopmask;                /* Stop/set-up timer            */
    UBYTE  startmask;               /* Start timer                  */
};

/*
 * Structure which will be used by the interrupt routine called
 * when our cia interval timer generates an interrupt.
 *
 */

struct exampledata
{
    struct Task *task;      /* task to signal */
    ULONG   signal;         /* Signal bit to use */
    ULONG   counter;
};

struct CIA *ciaa = (struct CIA *)0xbfe001;
struct CIA *ciab = (struct CIA *)0xbfd000;

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

/*
 * This is the interrupt routine which will be called when our CIA
 * interval timer counts down.
 *
 * This example decrements a counter each time the interrupt routine
 * is called until the counter reaches 0, at which time it signals
 * our main task.
 *
 * Note that interrupt handling code should be efficient, and will
 * generally be written in assembly code.  Signaling another task
 * such as this example does is also a useful way of handling
 * interrupts in an expedient manner.
 */

void __asm ExampleInterrupt(register __a1 struct exampledata *ed)
{
if (ed->counter)
    {
    ed->counter--;                  /* decrement counter */
    }
else
    {
    ed->counter = COUNTDOWN;        /* reset counter     */

    Signal(ed->task,(1L << ed->signal));
    }
}

/***********************************
 *  main()
 ***********************************/

void main(USHORT argc,char **argv)
{
struct freetimer ft;
struct exampledata ed;

/* Set up data which will be passed to interrupt */

ed.task = FindTask(0L);

if (ed.signal = AllocSignal(-1L))
    {
    /* Prepare freetimer structure : set-up interrupt */

    ft.timerint.is_Node.ln_Type = NT_INTERRUPT;
    ft.timerint.is_Node.ln_Pri  = 0;
    ft.timerint.is_Node.ln_Name = "cia_example";

    ft.timerint.is_Data         = (APTR)&ed;
    ft.timerint.is_Code         = (APTR)ExampleInterrupt;

    /* Call function to find a free CIA interval timer
     * with flag indicating that we prefer a CIA-A timer.
     */

    printf("Attempting to allocate a free timer\n");

    if (FindFreeTimer(&ft,TRUE))
        {
        if (ft.cia == ciaa)
            {
            printf("CIA-A timer ");
            }
        else
            {
            printf("CIA-B timer ");
            }

        if (ft.timerbit == CIAICRB_TA)
            {
            printf("A allocated\n");
            }
        else
            {
            printf("B allocated\n");
            }

        /* We found a free interval timer.  Let's start it running. */

        StartTimer(&ft,&ed);

        /* Wait for a signal */

        printf("Waiting for signal bit %ld\n",ed.signal);

        Wait(1L<<ed.signal);

        printf("We woke up!\n");

        /* Release the interval timer */

        RemICRVector(ft.ciabase,ft.timerbit,&ft.timerint);

        }
    else
        {
        printf("No CIA interval timer available\n");
        }

    FreeSignal(ed.signal);
    }
}

/*
 * This routine sets up the interval timer we allocated with
 * AddICRVector().  Note that we may have already received one, or
 * more interrupts from our timer.  Make no assumptions about the
 * initial state of any of the hardware registers we will be using.
 *
 */

void StartTimer(struct freetimer *ft, struct exampledata *ed)
{
register struct CIA *cia;

cia = ft->cia;

/* Note that there are differences between control register A,
 * and B on each CIA (e.g., the TOD alarm bit, and INMODE bits.
 */

if (ft->timerbit == CIAICRB_TA)
    {
    ft->ciacr = &cia->ciacra;       /* control register A   */
    ft->cialo = &cia->ciatalo;      /* low byte counter     */
    ft->ciahi = &cia->ciatahi;      /* high byte counter    */

    ft->stopmask = STOPA_AND;       /* set-up mask values   */
    ft->startmask = STARTA_OR;
    }
else
    {
    ft->ciacr = &cia->ciacrb;       /* control register B   */
    ft->cialo = &cia->ciatblo;      /* low byte counter     */
    ft->ciahi = &cia->ciatbhi;      /* high byte counter    */

    ft->stopmask = STOPB_AND;       /* set-up mask values   */
    ft->startmask = STARTB_OR;
    }

/* Modify control register within Disable().  This is done to avoid
 * race conditions since our compiler may generate code such as:
 *
 *      value = Read hardware byte
 *      AND  value with MASK
 *      Write value to hardware byte
 *
 * If we take a task switch in the middle of this sequence, two tasks
 * trying to modify the same register could trash each others' bits.
 *
 * Normally this code would be written in assembly language using atomic
 * instructions so that the Disable() would not be needed.
 */

Disable();

/* STOP timer, set 02 pulse count-down mode, set continuous mode */

*ft->ciacr &= ft->stopmask;
Enable();

/* Clear signal bit - interrupt will signal us later */
SetSignal(0L,1L<<ed->signal);

/* Count-down X # of times */
ed->counter = COUNTDOWN;

/* Start the interval timer - we will start the counter after
 * writing the low, and high byte counter values
 */

*ft->cialo = LOCOUNT;
*ft->ciahi = HICOUNT;

/* Turn on start bit - same bit for both A, and B control regs  */

Disable();
*ft->ciacr |= ft->startmask;

Enable();
}

/*
 * A routine to find a free interval timer.
 *
 * This routine makes no assumptions about which interval timers
 * (if any) are available for use.  Currently there are two interval
 * timers per CIA chip.
 *
 * Because CIA usage may change in the future, your code should use
 * a routine like this to find a free interval timer.
 *
 * Note that the routine takes a preference flag (which is used to
 * to indicate that you would prefer an interval timer on CIA-A).
 * If the flag is FALSE, it means that you would prefer an interval
 * timer on CIA-B.
 *
 */

FindFreeTimer(struct freetimer *ft, int preferA)
{
struct CIABase *ciaabase, *ciabbase;

/* get pointers to both resource bases */

ciaabase = OpenResource(CIAANAME);
ciabbase = OpenResource(CIABNAME);

/* try for a CIA-A timer first ? */

if (preferA)
    {
    ft->ciabase = ciaabase; /* library address  */
    ft->cia     = ciaa;     /* hardware address */
    }
else
    {
    ft->ciabase = ciabbase; /* library address  */
    ft->cia     = ciab;     /* hardware address */
    }

if (TryTimer(ft))
    return(TRUE);

/* try for an interval timer on the other cia */

if (!(preferA))
    {
    ft->ciabase = ciaabase; /* library address  */
    ft->cia     = ciaa;     /* hardware address */
    }
else
    {
    ft->ciabase = ciabbase; /* library address  */
    ft->cia     = ciab;     /* hardware address */
    }

if (TryTimer(ft))
    return(TRUE);

return(FALSE);

}

/*
 * Try to obtain a free interval timer on a CIA.
 */

TryTimer(struct freetimer *ft)
{

if (!(AddICRVector(ft->ciabase,CIAICRB_TA,&ft->timerint)))
    {
    ft->timerbit = CIAICRB_TA;
    return(TRUE);
    }

if (!(AddICRVector(ft->ciabase,CIAICRB_TB,&ft->timerint)))
    {
    ft->timerbit = CIAICRB_TB;
    return(TRUE);
    }

return(FALSE);
}


Devices/Dev_examples/Get_Disk_Unit_ID.c

   /*
    * Get_Disk_Unit_ID.c
    *
    * Example of getting the UnitID of a disk
    *
    * Compile with SAS C 5.10  lc -b1 -cfistq -v -y -L
    *
    * Run from CLI only
    */

   #include <exec/types.h>
   #include <exec/memory.h>
   #include <dos/dos.h>
   #include <resources/disk.h>

   #include <clib/exec_protos.h>

   #include <stdio.h>

   #ifdef LATTICE
   int CXBRK(void) { return(0); }  /* Disable SAS CTRL/C handling */
   int chkabort(void) { return(0); }  /* really */

   /* There is no amiga.lib stub for this function so a pragma is required
    * This is a pragma for SAS C
    * Your compiler may require a different format
    */
   #pragma libcall DiskBase GetUnitID 1e 1
   #endif

   struct Library *DiskBase = NULL;

   LONG GetUnitID(long);

   void main(int argc, char **argv)
   {
   LONG ids= 0;
   LONG type;

   if (!(DiskBase= (struct Library *)OpenResource(DISKNAME)))
       printf("Cannot open %s\n,DISKNAME");
   else
      {
       printf("Defined drive types are:\n");
       printf("  AMIGA  $00000000\n");
       printf("  5.25'' $55555555\n");
       printf("  AMIGA  $00000000 (high density)\n");
       printf("  None   $FFFFFFFF\n\n");

       /* What are the UnitIDs? */
        for (ids = 0; ids < 4; ids++)
           {
            type = GetUnitID(ids);
            printf("The UnitID for unit %d is $%08lx\n",ids,type);
           }
      }
   }


Devices/Dev_examples/Get_Filesys.c

   /*
    * Get_Filesys.c
    *
    * Example of examining the FileSysRes list
    *
    * Compile with SAS C 5.10  lc -b1 -cfistq -v -y -L
    *
    * Run from CLI only
    */

   #include <exec/types.h>
   #include <exec/memory.h>
   #include <dos/dos.h>
   #include <resources/filesysres.h>

   #include <clib/exec_protos.h>

   #include <stdio.h>

   #ifdef LATTICE
   int CXBRK(void) { return(0); }  /* Disable SAS CTRL/C handling */
   int chkabort(void) { return(0); }  /* really */
   #endif

   struct FileSysResource *FileSysResBase = NULL;

   void main(int argc, char **argv)
   {

   struct FileSysEntry *fse;
   int x;

   /* NOTE - you should actually be in a Forbid while accessing any
    * system list for which no other method of arbitration is available.
    * However, for this example we will be printing the information
    * (which would break a Forbid anyway) so we won't Forbid.
    * In real life, you should Forbid, copy the information you need,
    * Permit, then print the info.
    */
   if (!(FileSysResBase = (struct FileSysResource *)OpenResource(FSRNAME)))
       printf("Cannot open %s\n",FSRNAME);
   else
       {
       for ( fse = (struct FileSysEntry *)FileSysResBase->fsr_FileSysEntries.lh_Head;
             fse->fse_Node.ln_Succ;
             fse = (struct FileSysEntry *)fse->fse_Node.ln_Succ)
            {
            printf("Found filesystem creator: %s\n",fse->fse_Node.ln_Name);

            printf("                 DosType: ");
            for (x=24; x>=8; x-=8)
                 putchar((fse->fse_DosType >> x) & 0xFF);

            putchar((fse->fse_DosType & 0xFF) + 0x30);

            printf("\n                 Version: %d",(fse->fse_Version >> 16));
            printf(".%ld\n\n",(fse->fse_Version & 0xFFFF));
            }
        }
   }


Devices/Dev_examples/Alloc_Misc.a

* Alloc_Misc.a
*
* Assembly language fragment that grabs the two parts of the serial
* resource (using misc.resource).  If it gets the resource, it will
* wait for CTRL-C to be pressed before releasing.
*
* While we are waiting, the query_serial program should be run.  It will try
* to open the serial device and if unsuccessful, will return the name of the
* owner.  It will be us, Serial Port Hog!
*
* When a task has successfully obtained the serial resource, it "owns"
* the hardware registers that control the serial port.  No other tasks
* are allowed to interfere.
*
* Assemble with Adapt
*     HX68 Allocate_Misc.a to Allocate_Misc.o
*
* Link
*     Blink FROM Allocate_Misc.o TO Allocate_Misc LIB LIB:amiga.lib
*

                INCDIR  "include:"
                INCLUDE "exec/types.i"
                INCLUDE "resources/misc.i"
                INCLUDE "dos/dos.i"

        xref    _AbsExecBase     ; We get this from outside...
        xref    _LVOOpenResource ; We get this from outside...
        xref    _LVOWait         ; We get this from outside...

;
; Open Exec and the misc.resource, check for success
;
                move.l  _AbsExecBase,a6         ;Prepare to use exec
                lea.l   MiscName(pc),a1
                jsr     _LVOOpenResource(a6)    ;Open "misc.resource"
                move.l  d0,d7                   ;Stash resource base
                bne.s   resource_ok
                moveq   #RETURN_FAIL,d0
                rts

resource_ok     exg.l   d7,a6                   ;Put resource base in A6

;
; We now have a pointer to a resource.
; Call one of the resource's library-like vectors.
;
                move.l  #MR_SERIALBITS,d0       ;We want these bits
                lea.l   MyName(pc),a1           ;This is our name
                jsr     MR_ALLOCMISCRESOURCE(a6)
                tst.l   d0
                bne.s   no_bits                 ;Someone else has it...
                move.l  #MR_SERIALPORT,d0
                lea.l   MyName(pc),a1
                jsr     MR_ALLOCMISCRESOURCE(a6)
                tst.l   d0
                bne.s   no_port                 ;Someone else has it...
;
; We just stole the serial port registers; wait.
; Nobody else can use the serial port, including the serial.device!
;
                exg.l   d7,a6                   ;use exec again
                move.l  #SIGBREAKF_CTRL_C,d0
                jsr     _LVOWait(a6)            ;Wait for CTRL-C
                exg.l   d7,a6                   ;Get resource base back
;
; Free 'em up
;
                move.l  #MR_SERIALPORT,d0
                jsr     MR_FREEMISCRESOURCE(a6)
no_port
                move.l  #MR_SERIALBITS,d0
                jsr     MR_FREEMISCRESOURCE(a6)
no_bits
                moveq   #RETURN_FAIL,d0
                rts
;
; Text area
;
MiscName        dc.b    'misc.resource',0
MyName          dc.b    'Serial Port Hog',0
                dc.w    0
                END


Devices/Dev_examples/Allocate_Misc.c

/*
 * Allocate_Misc.c
 *
 * Example of allocating a miscellaneous resource
 * We will allocate the serial resource and wait till
 * CTRL-C is pressed.  While we are waiting, the
 * query_serial program should be run.  It will try
 * to open the serial device and if unsuccessful, will
 * return the name of the owner.  It will be us!
 *
 * Compile with SAS C 5.10  lc -b1 -cfistq -v -y -L
 *
 * Run from CLI only
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <resources/misc.h>

#include <clib/exec_protos.h>
#include <clib/misc_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

struct Library *MiscBase = NULL;

void main(int argc, char **argv)
{
UBYTE *owner = NULL;       /* owner of misc resource */

if (!(MiscBase= (struct Library *)OpenResource(MISCNAME)))
    printf("Cannot open %s\n",MISCNAME);
else
   {
    /* Allocate both pieces of the serial hardware */
    if ((owner = AllocMiscResource(MR_SERIALPORT,"Serial Port Hog")) == NULL)
        {
        if ((owner = AllocMiscResource(MR_SERIALBITS,"Serial Port Hog")) == NULL)
            {
            /* Wait for CTRL-C to be pressed */
            printf("\nWaiting for CTRL-C...\n");
            Wait(SIGBREAKF_CTRL_C);

            /* We're back */

            /* Deallocate the serial port register */
            FreeMiscResource(MR_SERIALBITS);
            }
        else
            printf("\nUnable to allocate MR_SERIALBITS because %s owns it\n",owner);

        /* Deallocate the serial port */
        FreeMiscResource(MR_SERIALPORT);
       }
    else
       printf("\nUnable to allocate MR_SERIALPORT because %s owns it\n",owner);
   }
}


Devices/Dev_examples/Query_Serial.c

/*
 * Query_Serial.c
 *
 * We will try to open the serial device and if unsuccessful,
 * will return the name of the owner.
 *
 * Compile with SAS C 5.10  lc -b1 -cfistq -v -y -L
 *
 * Run from CLI only
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <resources/misc.h>
#include <devices/serial.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/dos_protos.h>
#include <clib/misc_protos.h>

#include <stdio.h>
#include <stdlib.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }     /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

struct Library *MiscBase;

struct MsgPort  *SerialMP;         /* Message port pointer */
struct IOExtSer *SerialIO;         /* I/O request pointer */

void main(void)
{
UWORD status;    /* return value of SDCMD_QUERY */
UBYTE *user;     /* name of serial port owner if not us */

if (SerialMP=CreatePort(NULL,NULL) )
    {
    if (SerialIO=(struct IOExtSer *)CreateExtIO(SerialMP,sizeof(struct IOExtSer)) )
        {
        if (OpenDevice(SERIALNAME,0L,(struct IORequest *)SerialIO,0))
            {
            printf("\n%s did not open",SERIALNAME);

            MiscBase= (struct Library *)OpenResource(MISCNAME);

            /* Find out who has the serial device */
            if ((user = AllocMiscResource(MR_SERIALPORT,"Us")) == NULL)
                {
                printf("\n");
                FreeMiscResource(MR_SERIALPORT);
                }
            else
                printf(" because %s owns it \n\n",user);
            }
        else
            {
            SerialIO->IOSer.io_Command  = SDCMD_QUERY;
            DoIO((struct IORequest *)SerialIO);             /* execute query */

            status = SerialIO->io_Status;                    /* store returned status */

            printf("\tThe serial port status is %x\n",status);

            CloseDevice((struct IORequest *)SerialIO);
            }

        DeleteExtIO(SerialIO);
        }
    else
        printf("Can't create I/O request\n");

    DeletePort(SerialMP);
    }
else
    printf("Can't create message port\n");
}


Devices/Dev_examples/Read_Potinp.c

/*
 * Read_Potinp.c
 *
 * An example of using the potgo.resource to read pins 9 and 5 of
 * port 1 (the non-mouse port).  This bypasses the gameport.device.
 * When the right or middle button on a mouse plugged into port 1 is pressed,
 * the read value will change.
 *
 * Use of port 0 (mouse) is unaffected.
 *
 * Compile with SAS C 5.10  lc -b1 -cfistq -v -y -L
 *
 * Run from CLI only
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <resources/potgo.h>
#include <hardware/custom.h>

#include <clib/exec_protos.h>
#include <clib/potgo_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) {return(0);}  /* Disable SAS Ctrl-C checking */
int chkabort(void) { return(0); }  /* really */
#endif

struct PotgoBase *PotgoBase;
ULONG potbits;
UWORD value;

#define UNLESS(x) if(!(x))
#define UNTIL(x)  while(!(x))

#define OUTRY 1L<<15
#define DATRY 1L<<14
#define OUTRX 1L<<13
#define DATRX 1L<<12

extern struct Custom far custom;

void main(int argc,char **argv)
{
UNLESS (PotgoBase=(struct PotgoBase *)OpenResource("potgo.resource"))
        return;

potbits=AllocPotBits(OUTRY|DATRY|OUTRX|DATRX);

/* Get the bits for the right and middle mouse buttons on the alternate mouse port. */

if (potbits != (OUTRY|DATRY|OUTRX|DATRX))
    {
    printf("Pot bits are already allocated! %lx\n",potbits);
    FreePotBits(potbits);
    return;
    }

/* Set all ones in the register (masked by potbits) */
WritePotgo(0xFFFFFFFFL,potbits);

printf("\nPlug a mouse into the second port.  This program will indicate when\n");
printf("the right or middle button (if the mouse is so equipped) is pressed.\n");
printf("Stop the program with Control-C. Press return now to begin.\n");

getchar();

UNTIL (SIGBREAKF_CTRL_C & SetSignal(0L,0L))
      /* until CTRL-C is pressed */
      {
      /* Read word at $DFF016 */
        value = custom.potinp;

      /* Show what was read (restricted to our allocated bits) */
      printf("POTINP = $%lx\n",value & potbits);
      }

FreePotBits(potbits);
}


Devices/Dev_examples/Full_Narrator.c

/*
 * Full_Narrator.c
 *
 * This example program sends a string of phonetic text to the narrator
 * device and, while it is speaking, highlights, word-by-word, a
 * corresponding English string.  In addition, mouth movements are drawn
 * in a separate window.
 *
 * Compile with SAS C 5.10  lc -b1 -cfistq -v -y -L
 *
 * Requires Kickstart V37 or greater.
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <intuition/intuition.h>
#include <ctype.h>
#include <exec/exec.h>
#include <fcntl.h>
#include <devices/narrator.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/dos_protos.h>

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }     /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

/*
 *  Due to an omission, the sync field defines were not included in older
 *  versions of the narrator device include files.  So, if they haven't
 *  already been defined, do so now.
 */

#ifndef NDF_READMOUTH                        /* Already defined ? */
#define NDF_READMOUTH   0x01                 /* No, define here   */
#define NDF_READWORD    0x02
#define NDF_READSYL     0x04
#endif

#define PEN3    3                            /* Drawing pens */
#define PEN2    2
#define PEN1    1
#define PEN0    0

BOOL FromCLI = TRUE;
BYTE chans[4] = {3, 5, 10, 12};

LONG EyesLeft;                               /* Left edge of left eye     */
LONG EyesTop;                                /* Top of eyes box           */
LONG EyesBottom;                             /* Bottom of eyes box        */
LONG YMouthCenter;                           /* Pixels from top edge      */
LONG XMouthCenter;                           /* Pixels from left edge     */
LONG LipWidth, LipHeight;                    /* Width and height of mouth */

struct TextAttr MyFont = {"topaz.font", TOPAZ_SIXTY, FS_NORMAL, FPF_ROMFONT,};

struct  IntuitionBase   *IntuitionBase = NULL;
struct  GfxBase         *GfxBase = NULL;

struct  MsgPort         *VoicePort = NULL;
struct  MsgPort         *MouthPort = NULL;

struct  narrator_rb     *VoiceIO = NULL;
struct  mouth_rb        *MouthIO = NULL;

struct  IntuiText  HighLight;
struct  NewWindow  NewWindow;
struct  Window    *TextWindow;
struct  Window    *FaceWindow;
struct  RastPort  *FaceRast;

void main(int argc, char **argv)
{
LONG     i;
LONG     sentence;
LONG     Offset;
LONG     CharsLeft;
LONG     ScreenPos;
LONG     WordLength;
LONG     LineNum;
UBYTE    *Tempptr;
UBYTE    *English;
UBYTE    *OldEnglish;
UBYTE     c;

UBYTE    *PhonPtr;              /* Pointer to phonetic text     */
LONG     PhonSize;              /* Size of phonetic text        */
UBYTE    *PhonStart[100];       /* Start of phonetic sentences  */
LONG     NumPhonStarts;         /* Number of phonetic sentences */

UBYTE    *EngPtr;               /* Pointer to English text      */
LONG     EngSize;               /* Size of English text         */
UBYTE    *EngStart[100];        /* Start of English sentences   */
LONG     NumEngStarts;          /* Number of English sentences  */

UBYTE    *EngLine[24];          /* Start of line on screen      */
LONG     EngBytes[24];          /* Bytes per line on screen     */
LONG     NumEngLines;           /* Number of lines on screen    */

extern  void  Cleanup(UBYTE *errmsg);
extern  void  ClearWindow(struct Window *TextWindow);
extern  void  DrawFace(void);
extern  void  UpdateFace(void);

/*
 *  (0)   Note whether the program was started from the CLI or from
 *        Workbench.
 */

if (argc == 0)
    FromCLI = FALSE;

/*
 *  (1)   Setup the phonetic text to be spoken.  If there are any non-
 *        alphabetic characters in the text (such as NEWLINES or TABS)
 *        replace them with spaces.  Then break up the text into sentences,
 *        storing the start of each sentence in PhonStart array elements.
 */

PhonPtr = "KAA1RDIYOWMAYAA5PAXTHIY.  AY /HAED NEH1VER /HER4D AXV IHT "
          "BIXFOH5R, BAHT DHEH5R IHT WAHZ - LIH4STIXD AEZ (DHAX FOH5RM "
          "AXV /HAA5RT DIHZIY5Z) DHAET FEH4LD (NAAT WAH5N OHR TUW5) - "
          "BAHT (AO7L THRIY5 AXV DHAX AA5RTAXFIHSHUL /HAA5RTQ "
          "RIXSIH5PIYINTS).  (AH LIH5TUL RIXSER5CH) PROHDUW5ST (SAHM "
          "IH5NTRIHSTIHNX RIXZAH5LTS). AHKOH5RDIHNX TUW (AEN AA5RTIHKUL "
          "IHN DHAX NOWVEH5MBER EY2THQX NAY5NTIYNEYTIYFOH1R NUW IY5NXGLIND "
          "JER5NUL AXV MEH5DIXSIN), (SIH5GEREHT SMOW5KIHNX) KAO4ZIHZ "
          "(DHIHS LIY5THUL DIHZIY5Z) DHAET WIY4KINZ (DHAX /HAA5RTS "
          "PAH4MPIHNX PAW2ER).  WAYL (DHIY IHGZAE5KT MEH5KINIXZUM) IHZ "
          "NAAT KLIY5R, DAA5KTER AA5RTHER JEY2 /HAARTS SPEH5KYULEYTIHD "
          "DHAET NIH4KAXTIY2N- OHR KAA5RBIN MUNAA5KSAYD IHN DHAX SMOW5K- "
          "SAH5M/HAW1 POY4ZINZ DHAX /HAA5RT, AEND LIY4DZ TUW (/HAA5RT "
          "FEY5LYER).";

PhonSize = strlen(PhonPtr);
NumPhonStarts = 0;
PhonStart[NumPhonStarts++] = PhonPtr;
for (i = 0;  i < PhonSize;  ++i)
     {
     if (isspace((int)(c = *PhonPtr++)))
         *(PhonPtr-1) = ' ';
     if ((c == '.') || (c == '?'))
         {
         *PhonPtr = '\0';
         PhonStart[NumPhonStarts++] = ++PhonPtr;
         }
     }

/*
 *  (2)  Create the English text corresponding to the phonetic text above.
 *       As before, insure that there are no TABS or NEWLINES in the text.
 *       Break the text up into sentences and store the start of each
 *       sentence in EngStart array elements.
 */
EngPtr = "Cardiomyopathy. I had never heard of it before, but there it was "
         "listed as the form of heart disease that felled not one or two but "
         "all three of the artificial heart recipients. A little research "
         "produced some interesting results. According to an article in the "
         "November 8, 1984, New England Journal of Medicine, cigarette smoking "
         "causes this lethal disease that weakens the heart's pumping power.   "
         "While the exact mechanism is not clear, Doctor Arthur J Hartz "
         "speculated that nicotine or carbon monoxide in the smoke somehow "
         "poisons the heart and leads to heart failure.";

EngSize = strlen(EngPtr);
NumEngStarts = 0;
EngStart[NumEngStarts++] = EngPtr;
for (i = 0;  i < EngSize;  ++i)
     {
     if (isspace((int)(c = *EngPtr++)))
         *(EngPtr-1) = ' ';
     if ((c == '.') || (c == '?'))
         {
         *EngPtr = '\0';
         EngStart[NumEngStarts++] = ++EngPtr;
         }
     }

/*
 *  (3)   Open Intuition and Graphics libraries.
 */

if (!(IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",0)))
    Cleanup("can't open intuition");

if ((GfxBase=(struct GfxBase *)OpenLibrary("graphics.library", 0)) == NULL)
    Cleanup("can't open graphics");

/*
 *  (4)   Setup the NewWindow structure for the text display and
 *        open the text window.
 */
NewWindow.LeftEdge    = 20;
NewWindow.TopEdge     = 100;
NewWindow.Width       = 600;
NewWindow.Height      = 80;
NewWindow.DetailPen   = 0;
NewWindow.BlockPen    = 1;
NewWindow.Title       = " Narrator Demo ";
NewWindow.Flags       = SMART_REFRESH | ACTIVATE | WINDOWDEPTH | WINDOWDRAG;
NewWindow.IDCMPFlags  = NULL;
NewWindow.Type        = WBENCHSCREEN;
NewWindow.FirstGadget = NULL;
NewWindow.CheckMark   = NULL;
NewWindow.Screen      = NULL;
NewWindow.BitMap      = NULL;
NewWindow.MinWidth    = 600;
NewWindow.MinHeight   = 80;
NewWindow.MaxWidth    = 600;
NewWindow.MaxHeight   = 80;

if ((TextWindow = (struct Window *)OpenWindow(&NewWindow)) == NULL)
    Cleanup("Text window could not be opened");

/*
 *  (4)   Setup the NewWindow structure for the face display, open the
 *        window, cache the RastPort pointer, and draw the initial face.
 */

NewWindow.LeftEdge    = 20;
NewWindow.TopEdge     = 12;
NewWindow.Width       = 120;
NewWindow.Height      = 80;
NewWindow.DetailPen   = 0;
NewWindow.BlockPen    = 1;
NewWindow.Title       = " Face ";
NewWindow.Flags       = SMART_REFRESH | WINDOWDEPTH | WINDOWDRAG;
NewWindow.IDCMPFlags  = NULL;
NewWindow.Type        = WBENCHSCREEN;
NewWindow.FirstGadget = NULL;
NewWindow.CheckMark   = NULL;
NewWindow.Screen      = NULL;
NewWindow.BitMap      = NULL;
NewWindow.MinWidth    = 120;
NewWindow.MinHeight   = 80;
NewWindow.MaxWidth    = 120;
NewWindow.MaxHeight   = 80;

if ((FaceWindow = (struct Window *)OpenWindow(&NewWindow)) == NULL)
    Cleanup("Face window could not be opened");

FaceRast = FaceWindow->RPort;

DrawFace();

/*
 *  (5)   Create read and write msg ports.
 */

if ((MouthPort = CreatePort(NULL,0)) == NULL)
    Cleanup("Can't get read port");
if ((VoicePort = CreatePort(NULL,0)) == NULL)
    Cleanup("Can't get write port");

/*
 *  (6)   Create read and write I/O request blocks.
 */

if (!(MouthIO = (struct mouth_rb *)
                  CreateExtIO(MouthPort,sizeof(struct mouth_rb))))
    Cleanup("Can't get read IORB");

if (!(VoiceIO = (struct narrator_rb *)
                   CreateExtIO(VoicePort,sizeof(struct narrator_rb))))
    Cleanup("Can't get write IORB");

/*
 *  (7)   Set up the write I/O request block and open the device.
 */

VoiceIO->ch_masks            = &chans[0];
VoiceIO->nm_masks            = sizeof(chans);
VoiceIO->message.io_Command = CMD_WRITE;
VoiceIO->flags               = NDF_NEWIORB;

if (OpenDevice("narrator.device", 0, VoiceIO, 0) != NULL)
    Cleanup("OpenDevice failed");

/*
 *  (8)   Set up the read I/O request block.
 */

MouthIO->voice.message.io_Device = VoiceIO->message.io_Device;
MouthIO->voice.message.io_Unit   = VoiceIO->message.io_Unit;
MouthIO->voice.message.io_Message.mn_ReplyPort = MouthPort;
MouthIO->voice.message.io_Command = CMD_READ;

/*
 *  (9)   Initialize highlighting IntuiText structure.
 */

HighLight.FrontPen  = 1;
HighLight.BackPen   = 0;
HighLight.DrawMode  = JAM1;
HighLight.ITextFont = &MyFont;
HighLight.NextText  = NULL;

/*
 *  (10)   For each sentence, put up the English text in BLACK.  As
 *         Narrator says each word, highlight that word in BLUE.  Also
 *         continuously draw mouth shapes as Narrator speaks.
 */

for (sentence = 0; sentence < NumPhonStarts; ++sentence)
     {
     /*
      *  (11)  Begin by breaking the English sentence up into lines of
      *        text in the window.  EngLine is an array containing a
      *        pointer to the start of each English text line.
      */

     English = EngStart[sentence] + strspn((UBYTE *)EngStart[sentence], " ");
     NumEngLines = 0;
     EngLine[NumEngLines++] = English;
     CharsLeft = strlen(English);
     while (CharsLeft > 51)
           {
           for (Offset = 51; *(English+Offset) != ' '; --Offset) ;
           EngBytes[NumEngLines-1] = Offset;
           English                += Offset + 1;
           *(English-1)            = '\0';
           EngLine[NumEngLines++]  = English;
           CharsLeft              -= Offset + 1;
           }
     EngBytes[NumEngLines-1] = CharsLeft;

     /*
      *  (12)   Clear the window and draw in the unhighlighted English text.
      */

     ClearWindow(TextWindow);

     HighLight.FrontPen = 1;
     HighLight.LeftEdge = 10;
     HighLight.TopEdge  = 20;

     for (i = 0; i < NumEngLines; ++i)
          {
          HighLight.IText = EngLine[i];
          PrintIText(TextWindow->RPort, &HighLight, 0, 0);
          HighLight.TopEdge += 10;
          }

     HighLight.TopEdge  = 20;
     HighLight.FrontPen = 3;
     HighLight.IText    = EngLine[0];

     /*
      *  (13)   Set up the write request with the address and length of
      *         the phonetic text to be spoken.  Also tell device to
      *         generate mouth shape changes and word sync events.
      */

     VoiceIO->message.io_Data   = PhonStart[sentence];
     VoiceIO->message.io_Length = strlen(VoiceIO->message.io_Data);
     VoiceIO->flags             = NDF_NEWIORB | NDF_WORDSYNC;
     VoiceIO->mouths            = 1;

    /*
     *  (14)   Send the write request to the device.  This is an
     *         asynchronous write, the device will return immediately.
     */

     SendIO(VoiceIO);

    /*
     *  (15)   Initialize some variables.
     */

     ScreenPos  = 0;
     LineNum    = 0;
     English    = EngLine[LineNum];
     OldEnglish = English;
     MouthIO->voice.message.io_Error = 0;

    /*
     *  (16)   Issue synchronous read requests.  For each request we
     *         check the sync field to see if the read returned a mouth
     *         shape change, a start of word sync event, or both.  We
     *         continue issuing read requests until we get a return code
     *         of ND_NoWrite, which indicates that the write has finished.
     */

     for (DoIO(MouthIO);MouthIO->voice.message.io_Error != ND_NoWrite;DoIO(MouthIO))
          {

          /*
           *  (17)   If bit 1 of the sync field is on, this is a start
           *         of word sync event.  In that case we highlight the
           *         next word.
           */

          if (MouthIO->sync & NDF_READWORD)
              {
              if ((Tempptr = strchr(English, ' ')) != NULL)
                  {
                  English = Tempptr + 1;
                  *(English-1) = '\0';
                  }
              PrintIText(TextWindow->RPort, &HighLight, 0, 0);
              WordLength      = strlen(OldEnglish) + 1;
              HighLight.IText = English;
              OldEnglish      = English;
              ScreenPos      += WordLength;

              if (ScreenPos >= EngBytes[LineNum])
                  {
                  HighLight.LeftEdge   = 10;
                  HighLight.TopEdge   += 10;
                  ScreenPos            = 0;
                  English = OldEnglish = EngLine[++LineNum];
                  HighLight.IText      = English;
                  }
              else
                  HighLight.LeftEdge += 10*WordLength;
              }

          /*
           *  (18)   If bit 0 of the sync field is on, this is a mouth
           *         shape change event.  In that case we update the face.
           */

          if (MouthIO->sync & NDF_READMOUTH)
              UpdateFace();

          }

     /*
      *  (19)   The write has finished (return code from last read equals
      *         ND_NoWrite).  We must wait on the write I/O request to
      *         remove it from the message port.
      */

     WaitIO(VoiceIO);

     }

/*
 *  (20)   Program completed, cleanup and return.
 */

Cleanup("Normal completion");

}

void Cleanup(UBYTE *errmsg)
{

/*
 *  (1)   Cleanup and go away.  This routine does not return but EXITs.
 *        Everything it does is pretty self explanatory.
 */

if (FromCLI)
    printf("%s\n\r", errmsg);
if (TextWindow)
    CloseWindow(TextWindow);
if (FaceWindow)
    CloseWindow(FaceWindow);
if (VoiceIO && VoiceIO->message.io_Device)
    CloseDevice(VoiceIO);
if (VoiceIO)
    DeleteExtIO(VoiceIO);
if (VoicePort)
    DeletePort(VoicePort);
if (MouthIO)
    DeleteExtIO(MouthIO);
if (MouthPort)
    DeletePort(MouthPort);
if (GfxBase)
    CloseLibrary(GfxBase);
if (IntuitionBase)
    CloseLibrary(IntuitionBase);

exit(RETURN_OK);
}

void ClearWindow(struct Window *TextWindow)
{
LONG    OldPen;

/*
 *  (1)   Clears a window.
 */

OldPen = (LONG)TextWindow->RPort->FgPen;
SetAPen(TextWindow->RPort, 0);
SetDrMd(TextWindow->RPort, JAM1);
RectFill(TextWindow->RPort, 3, 12, TextWindow->Width-3, TextWindow->Height-2);
SetAPen(TextWindow->RPort, OldPen);
}

void DrawFace()
{

/*
 *  (1)   Draws the initial face.  The variables defined here are used in
 *        UpdateFace() to redraw the mouth shape.
 */

EyesLeft = 15;
EyesTop = 20;
EyesBottom = 35;

XMouthCenter = FaceWindow->Width >> 1;
YMouthCenter = FaceWindow->Height - 25;

SetAPen(FaceWindow->RPort, PEN1);
RectFill(FaceWindow->RPort, 3, 10, FaceWindow->Width-3, FaceWindow->Height-2);

SetAPen(FaceWindow->RPort, PEN0);
RectFill(FaceWindow->RPort, EyesLeft, EyesTop, EyesLeft+25, EyesTop+15);
RectFill(FaceWindow->RPort, EyesLeft+65, EyesTop, EyesLeft+90, EyesTop+15);

SetAPen(FaceWindow->RPort, PEN3);
Move(FaceWindow->RPort, XMouthCenter-(FaceWindow->Width >> 3), YMouthCenter);
Draw(FaceWindow->RPort, XMouthCenter+(FaceWindow->Width >> 3), YMouthCenter);
}

void UpdateFace()
{

/*
 *  (1)   Redraws mouth shape in response to a mouth shape change message
 *        from the device.  Its all pretty self explanatory.
 */

WaitBOVP(&FaceWindow->WScreen->ViewPort);
SetAPen(FaceRast, PEN1);
RectFill(FaceRast, 3, EyesBottom, FaceWindow->Width-3, FaceWindow->Height-2);

LipWidth  = MouthIO->width*3;
LipHeight = MouthIO->height*2/3;

SetAPen(FaceRast, PEN3);
Move(FaceRast, XMouthCenter - LipWidth, YMouthCenter);
Draw(FaceRast, XMouthCenter           , YMouthCenter - LipHeight);
Draw(FaceRast, XMouthCenter + LipWidth, YMouthCenter);
Draw(FaceRast, XMouthCenter,            YMouthCenter + LipHeight);
Draw(FaceRast, XMouthCenter - LipWidth, YMouthCenter);
}


Devices/Dev_examples/Speak_Narrator.c

/*
 * Speak_Narrator.c
 *
 * This example program sends a string of phonetic text to the narrator
 * device twice, changing some of the characteristics the second time.
 *
 * Compile with SAS C 5.10  lc -b1 -cfistq -v -y -L
 *
 * Requires Kickstart V37 or greater.
 */

#include <exec/types.h>
#include <exec/exec.h>
#include <dos/dos.h>
#include <devices/narrator.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/dos_protos.h>

#include <string.h>
#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }     /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

void main(void)
{
struct  MsgPort     *VoiceMP;
struct  narrator_rb *VoiceIO;
UBYTE   *PhoneticText    = "DHIHS IHZ AHMIY5GAH SPIY5KIHNX.";
BYTE    audio_chan[4]   = {3, 5, 10, 12};

if (VoiceMP=CreateMsgPort())  /* Create the message port */
  {                           /* Create the I/O request */
  if (VoiceIO = CreateIORequest(VoiceMP,sizeof(struct narrator_rb)))
    {
    /*Set the NEWIORB bit in the flags field to use the new fields*/
    VoiceIO->flags = NDF_NEWIORB;

    /* Open the narrator device */
    if (OpenDevice("narrator.device",0,(struct IORequest *)VoiceIO,0L))
        /* Inform user that it could not be opened */
        printf("Error: narrator.device did not open\n");
    else
        {
         /* Speak the string using the default parameters */
         VoiceIO->ch_masks = &audio_chan[0];
         VoiceIO->nm_masks = sizeof(audio_chan);
         VoiceIO->message.io_Command = CMD_WRITE;
         VoiceIO->message.io_Data = PhoneticText;
         VoiceIO->message.io_Length = strlen(PhoneticText);
         DoIO(VoiceIO);

         /* Now change some of the characteristics:
          *    Raise the first formant, lower the third formant,
          *    and move 50% of the way towards AO.
          * and speak it again.
          */

        VoiceIO->A1adj = -32;          /* Shut off first formant  */
        VoiceIO->A3adj =  11;          /* Raise the third formant */
        VoiceIO->centralize = 50;      /* Move 50% of the way     */
        VoiceIO->centphon = "AO";      /* towards AO              */
        DoIO(VoiceIO);

        /* Close the narrator device */
        CloseDevice((struct IORequest *)VoiceIO);
        }
    /* Delete the IORequest */
    DeleteIORequest(VoiceIO);
    }
  else
    /* Inform user that the I/O request could be created */
    printf("Error: Could not create I/O request\n");

  /* Delete the message port */
  DeleteMsgPort(VoiceMP);
  }
else
  /* Inform user that the message port could not be created */
  printf("Error: Could not create message port\n");
}


A / FORM Specs from Original EA Doc / ILBM IFF Interleaved Bitmap

Date:	January 17, 1986 (CRNG data updated Oct, 1988 by Jerry Morrison)
    (Appendix E added and CAMG updated Oct, 1988
         by Commodore-Amiga, Inc.)

From:	Jerry Morrison, Electronic Arts

Status:	Released and in use

 Introduction
 Standard Properties
 Standard BODY Data Chunk
 Non-standard Data Chunks
 Appendix A. ILBM Regular Expression
 Appendix B. ILBM Box Diagram
 Appendix C. IFF Hints
 Appendix D. ByteRun1 Encoding
 Appendix E. Standards Committee


ILBM IFF Interleaved Bitmap / Introduction

EA IFF 85 is Electronic Arts' standard for interchange format files.
"ILBM" is a format for a 2 dimensional raster graphics image, specifically
an InterLeaved bitplane BitMap image with color map.  An ILBM is an IFF
"data section" or "FORM type", which can be an IFF file or a part of one.
ILBM allows simple, highly portable raster graphic storage.

An ILBM is an archival representation designed for three uses.  First, a
stand- alone image that specifies exactly how to display itself
(resolution, size, color map, etc.).  Second, an image intended to be
merged into a bigger picture which has its own depth, color map, and so
on.  And third, an empty image with a color map selection or "palette" for
a paint program.  ILBM is also intended as a building block for composite
IFF FORMs like "animation sequences" and "structured graphics".  Some uses
of ILBM will be to preserve as much information as possible across
disparate environments.  Other uses will be to store data for a single
program or highly cooperative programs while maintaining subtle details.
So we're trying to accomplish a lot with this one format.

This memo is the IFF supplement for FORM ILBM.  Section 2 defines the
purpose and format of property chunks bitmap header "BMHD", color map
"CMAP", hotspot "GRAB", destination merge data "DEST", sprite information
"SPRT", and Commodore Amiga viewport mode "CAMG".  Section 3 defines the
standard data chunk "BODY".  These are the "standard" chunks.  Section 4
defines the non- standard data chunks.  Additional specialized chunks like
texture pattern can be added later.  The ILBM syntax is summarized in
Appendix A as a regular expression and in Appendix B as a box diagram.
Appendix C explains the optional run encoding scheme.  Appendix D names
the committee responsible for this FORM ILBM standard.

Details of the raster layout are given in part 3, Standard Data Chunk.
Some elements are based on the Commodore Amiga hardware but generalized
for use on other computers.  An alternative to ILBM would be appropriate
for computers with true color data in each pixel, though the wealth of
available ILBM images makes import and export important.

 Reference


ILBM IFF Interleaved Bitmap / Reference

"EA IFF 85" Standard for Interchange Format Files describes the
underlying conventions for all IFF files.

Amiga® is a registered trademark of Commodore-Amiga, Inc.
Electronic Arts(tm) is a trademark of Electronic Arts.
Macintosh(tm) is a trademark licensed to Apple Computer, Inc.
MacPaint(tm) is a trademark of Apple Computer, Inc.


ILBM IFF Interleaved Bitmap / Standard Properties

ILBM has several defined property chunks that act on the main data chunks.
The required property "BMHD" and any optional properties must appear
before any "BODY" chunk.  (Since an ILBM has only one BODY chunk, any
following properties would be superfluous.)  Any of these properties may
be shared over a LIST of several ILBMs by putting them in a PROP ILBM (See
the EA IFF 85 document).

 BMHD
 CMAP
 GRAB
 DEST
 SPRT
 CAMG


Standard Properties / BMHD

The required property "BMHD" holds a BitMapHeader as defined in the
following documentation.  It describes the dimensions of the image, the
encoding used, and other data necessary to understand the BODY to
follow.

typedef UBYTE Masking;     /* Choice of masking technique. */

#define mskNone                0
#define mskHasMask             1
#define mskHasTransparentColor 2
#define mskLasso               3

typedef UBYTE Compression;    /* Choice of compression algorithm
   applied to the rows of all source and mask planes.  "cmpByteRun1"
   is the byte run encoding described in Appendix C.  Do not compress
   across rows! */
#define cmpNone        0
#define cmpByteRun1    1

typedef struct {
  UWORD       w, h;             /* raster width & height in pixels      */
  WORD        x, y;             /* pixel position for this image        */
  UBYTE       nPlanes;          /* # source bitplanes                   */
  Masking     masking;
  Compression compression;
  UBYTE       pad1;             /* unused; ignore on read, write as 0   */
  UWORD       transparentColor; /* transparent "color number" (sort of) */
  UBYTE       xAspect, yAspect; /* pixel aspect, a ratio width : height */
  WORD        pageWidth, pageHeight; /* source "page" size in pixels    */
    } BitMapHeader;

Fields are filed in the order shown.  The UBYTE fields are byte-packed
(the C compiler must not add pad bytes to the structure).

The fields w and h indicate the size of the image rectangle in pixels.
Each row of the image is stored in an integral number of 16 bit words.
The number of words per row is words=((w+15)/16) or Ceiling(w/16).  The
fields x and y indicate the desired position of this image within the
destination picture. Some reader programs may ignore x and y.  A safe
default for writing an ILBM is (x, y) = (0, 0).

The number of source bitplanes in the BODY chunk is stored in nPlanes.  An
ILBM with a CMAP but no BODY and nPlanes = 0 is the recommended way to
store a color map.

Note: Color numbers are color map index values formed by pixels in the
destination bitmap, which may be deeper than nPlanes if a DEST chunk calls
for merging the image into a deeper image.

The field masking indicates what kind of masking is to be used for this
image. The value mskNone designates an opaque rectangular image.  The
value mskHasMask means that a mask plane is interleaved with the bitplanes
in the BODY chunk (see below).  The value mskHasTransparentColor indicates
that pixels in the source planes matching transparentColor are to be
considered "transparent". (Actually, transparentColor isn't a "color
number" since it's matched with numbers formed by the source bitmap rather
than the possibly deeper destination bitmap.  Note that having a
transparent color implies ignoring one of the color registers.  The value
mskLasso indicates the reader may construct a mask by lassoing the image
as in MacPaint(tm).  To do this, put a 1 pixel border of transparentColor
around the image rectangle.  Then do a seed fill from this border.  Filled
pixels are to be transparent.

Issue: Include in an appendix an algorithm for converting a transparent
color to a mask plane, and maybe a lasso algorithm.

A code indicating the kind of data compression used is stored in
compression. Beware that using data compression makes your data unreadable
by programs that don't implement the matching decompression algorithm.  So
we'll employ as few compression encodings as possible.  The run encoding
byteRun1 is documented in Appendix C.

The field pad1 is a pad byte reserved for future use.  It must be set to 0
for consistency.

The transparentColor specifies which bit pattern means "transparent".
This only applies if masking is mskHasTransparentColor or mskLasso.
Otherwise, transparentColor should be 0 (see above).

The pixel aspect ratio is stored as a ratio in the two fields xAspect and
yAspect.  This may be used by programs to compensate for different aspects
or to help interpret the fields w, h, x, y, pageWidth, and pageHeight,
which are in units of pixels.  The fraction xAspect/yAspect represents a
pixel's width/height.  It's recommended that your programs store proper
fractions in the BitMapHeader, but aspect ratios can always be correctly
compared with the test:

    xAspect * yDesiredAspect = yAspect * xDesiredAspect

Typical values for aspect ratio are width : height = 10 : 11  for an Amiga
320 x 200 display and 1 : 1 for a Macintosh(tm) display.

The size in pixels of the source "page" (any raster device) is stored in
pageWidth and pageHeight, e.g., (320, 200) for a low resolution Amiga
display. This information might be used to scale an image or to
automatically set the display format to suit the image.  Note that the
image can be larger than the page.


Standard Properties / CMAP

The optional (but encouraged) property "CMAP" stores color map data as
triplets of red, green, and blue intensity values.  The n color map
entries ("color registers") are stored in the order 0 through n-1,
totaling 3n bytes. Thus n is the ckSize/3.  Normally, n would equal
2^(nPlanes).

A CMAP chunk contains a ColorMap array as defined below.  Note that these
typedefs assume a C compiler that implements packed arrays of 3-byte
elements.

    typedef struct {
        UBYTE red, green, blue;           /* color intensities 0..255 */
        } ColorRegister;                  /* size = 3 bytes           */

    typedef ColorRegister ColorMap[n];    /* size = 3n bytes          */

The color components red, green, and blue represent fractional intensity
values in the range 0 through 255 256ths.  White is (255, 255, 255) and
black is (0, 0, 0).  If your machine has less color resolution, use the
high order bits.  Shift each field right on reading (or left on writing)
and assign it to (from) a field in a local packed format like Color4,
below.  This achieves automatic conversion of images across environments
with different color resolutions.  On reading an ILBM, use defaults if the
color map is absent or has fewer color registers than you need.  Ignore
any extra color registers. (See Appendix E for a better way to write
colors)

The example type Color4 represents the format of a color register in
working memory of an Amiga computer, which has 4 bit video DACs.  (The
":4" tells smarter C compilers to pack the field into 4 bits.)

    typedef struct {
        unsigned pad1 :4, red :4, green :4, blue :4;
        } Color4;                /*   Amiga RAM format.  Not filed.  */

Remember that every chunk must be padded to an even length, so a color map
with an odd number of entries would be followed by a 0 byte, not included
in the ckSize.


Standard Properties / GRAB

The optional property "GRAB" locates a "handle" or "hotspot" of the image
relative to its upper left corner, e.g., when used as a mouse cursor or a
"paint brush".  A GRAB chunk contains a Point2D.

    typedef struct {
        WORD x, y;         /* relative coordinates (pixels) */
        } Point2D;


Standard Properties / DEST

The optional property "DEST" is a way to say how to scatter zero or more
source bitplanes into a deeper destination image.  Some readers may ignore
DEST.

The contents of a DEST chunk is DestMerge structure:

typedef struct {
  UBYTE depth;      /* # bitplanes in the original source               */
  UBYTE pad1;       /* unused; for consistency put 0 here               */
  UWORD planePick;  /* how to scatter source bitplanes into destination */
  UWORD planeOnOff; /* default bitplane data for planePick              */
  UWORD planeMask;  /* selects which bitplanes to store into            */
  } DestMerge;

The low order depth number of bits in planePick, planeOnOff, and planeMask
correspond one-to-one with destination bitplanes.  Bit 0 with bitplane 0,
etc. (Any higher order bits should be ignored.)  "1" bits in planePick
mean "put the next source bitplane into this bitplane", so the number of
"1" bits should equal nPlanes.  "0" bits mean "put the corresponding bit
from planeOnOff into this bitplane".  Bits in planeMask gate writing to
the destination bitplane: "1" bits mean "write to this bitplane" while "0"
bits mean "leave this bitplane alone".  The normal case (with no DEST
property) is equivalent to planePick = planeMask = 2^(nPlanes) - 1.

Remember that color numbers are formed by pixels in the destination bitmap
(depth planes deep) not in the source bitmap (nPlanes planes deep).


Standard Properties / SPRT

The presence of an "SPRT" chunk indicates that this image is intended as a
sprite.  It's up to the reader program to actually make it a sprite, if
even possible, and to use or overrule the sprite precedence data inside
the SPRT chunk:

    typedef UWORD SpritePrecedence;/* relative precedence,0 is the high */

Precedence 0 is the highest, denoting a sprite that is foremost.

Creating a sprite may imply other setup.  E.g., a 2 plane Amiga sprite
would have transparentColor = 0.  Color registers 1, 2, and 3 in the CMAP
would be stored into the correct hardware color registers for the hardware
sprite number used, while CMAP color register 0 would be ignored.


Standard Properties / CAMG

A "CAMG" chunk is specifically for Commodore Amiga ILBM's.  All
Amiga-based reader and writer software should deal with CAMG.  The Amiga
supports many different video display modes including interlace, Extra
Halfbrite, hold and modify (HAM), plus a variety of new modes under the
2.0 operating system. A CAMG chunk contains a single long word (length=4)
which specifies the Amiga display mode of the picture.

Prior to 2.0, it was possible to express all available Amiga ViewModes in
16 bits of flags (Viewport->Modes or NewScreen->ViewModes).  Old-style
writers and readers place a 16-bit Amiga ViewModes value in the low word
of the CAMG, and zeros in the high word.  The following Viewmode flags
should always be removed from old-style 16-bit ViewModes values when
writing or reading them:

EXTENDED_MODE | SPRITES | VP_HIDE |
          GENLOCK_AUDIO | GENLOCK_VIDEO (=0x7102, mask=0x8EFD)

New ILBM readers and writers, should treat the full CAMG longword as a
32-bit ModeID to support new and future display modes.

New ILBM writers, when running under the 2.0 Amiga operating system,
should directly store the full 32-bit return value of the graphics
function GetVPModeID(vp) in the CAMG longword.  When running under 1.3,
store a 16-bit Viewmodes value masked as described above.

ILBM readers should only mask bits out of a CAMG if the CAMG has a zero
upper word (see exception below).  New ILBM readers, when running under
2.0, should then treat the 32-bit CAMG value as a ModeID, and should use
the graphics ModeNotAvailable() function to determine if the mode is
available.  If the mode is not available, fall back to another suitable
display mode.  When running under 1.3, the low word of the CAMG may
generally be used to open a compatible display.

Note that one popular graphics package stores junk in the upper word of
the CAMG of brushes, and incorrect values (generally zero) in the low
word.  You can screen for such junk values by testing for non-zero in the
upper word of a ModeID in conjunction with the 0x00001000 bit NOT set in
the low word.

The following code fragment demonstrates ILBM reader filtering of
inappropriate bits in 16-bit CAMG values.

#include <graphics/view.h>
#include <graphics/displayinfo.h>

/* Knock bad bits out of old-style CAMG modes before checking availability.
 * (some ILBM CAMG's have these bits set in old 1.3 modes, and should not)
 * If not an extended monitor ID, or if marked as extended but missing
 * upper 16 bits, screen out inappropriate bits now.
 */
if((!(modeid & MONITOR_ID_MASK)) ||
    ((modeid & EXTENDED_MODE)&&(!(modeid & 0xFFFF0000))))
   modeid &=
      (~(EXTENDED_MODE|SPRITES|GENLOCK_AUDIO|GENLOCK_VIDEO|VP_HIDE));

/* Check for bogus CAMG like some brushes have, with junk in
 * upper word and extended bit NOT set not set in lower word.
 */
if((modeid & 0xFFFF0000)&&(!(modeid & EXTENDED_MODE)))
    {
    /* Bad CAMG, so ignore CAMG and determine a mode based on
     * based on pagesize or aspect
     */
     modeid = NULL;
     if(wide >= 640) modeid |= HIRES;
     if(high >= 400) modeid |= LACE;
     }

/* Now, ModeNotAvailable() may be used to determine if mode is available.
 *
 * If the mode is not available, you may prompt the user for a mode
 * choice, or search the 2.0 display database for an appropriate
 * replacement mode, or you may be able to get a relatively compatible
 * old display mode by masking out all bits except
 * HIRES | LACE | HAM | EXTRA_HALFBRITE
 */

   if((modeid & 0xFFFF0000)&&(!(modeid & 0x00001000)))
    {
    /* Then probably invalid ModeID */
    }


ILBM IFF Interleaved Bitmap / Standard BODY Data Chunk

 Raster Layout
 BODY


Standard BODY Data Chunk / Raster Layout

Raster scan proceeds left-to-right (increasing X) across scan lines, then
top-to-bottom (increasing Y) down columns of scan lines.  The coordinate
system is in units of pixels, where (0,0) is the upper left corner.

The raster is typically organized as bitplanes in memory.  The
corresponding bits from each plane, taken together, make up an index into
the color map which gives a color value for that pixel.  The first
bitplane, plane 0, is the low order bit of these color indexes.

A scan line is made of one "row" from each bitplane.  A row is one plane's
bits for one scan line, but padded out to a word (2 byte) boundary (not
necessarily the first word boundary).  Within each row, successive bytes
are displayed in order and the most significant bit of each byte is
displayed first.

A "mask" is an optional "plane" of data the same size (w, h) as a
bitplane. It tells how to "cut out" part of the image when painting it
onto another image.  "One" bits in the mask mean "copy the corresponding
pixel to the destination".  "Zero" mask bits mean "leave this destination
pixel alone".  In other words, "zero" bits designate transparent pixels.

The rows of the different bitplanes and mask are interleaved in the file
(see below).  This localizes all the information pertinent to each scan
line.  It makes it much easier to transform the data while reading it to
adjust the image size or depth.  It also makes it possible to scroll a big
image by swapping rows directly from the file without the need for
random-access to all the bitplanes.


Standard BODY Data Chunk / BODY

The source raster  is stored in a "BODY" chunk.  This one chunk holds all
bitplanes and the optional mask, interleaved by row.

The BitMapHeader, in a BMHD property chunk, specifies the raster's
dimensions w, h, and nPlanes.  It also holds the masking field which
indicates if there is a mask plane and the compression field which
indicates the compression algorithm used.  This information is needed to
interpret the BODY chunk, so the BMHD chunk must appear first.  While
reading an ILBM's BODY, a program may convert the image to another size by
filling (with transparentColor) or clipping.

The BODY's content is a concatenation of scan lines.  Each scan line is a
concatenation of one row of data from each plane in order 0 through
nPlanes-1 followed by one row from the mask (if masking = hasMask ).  If
the BitMapHeader field compression is cmpNone, all h rows are exactly
(w+15)/16 words wide. Otherwise, every row is compressed according to the
specified algorithm and the stored widths depend on the data compression.

Reader programs that require fewer bitplanes than appear in a particular
ILBM file can combine planes or drop the high-order (later) planes.
Similarly, they may add bitplanes and/or discard the mask plane.

Do not compress across rows, and don't forget to compress the mask just
like the bitplanes.  Remember to pad any BODY chunk that contains an odd
number of bytes and skip the pad when reading.


ILBM IFF Interleaved Bitmap / Nonstandard Data Chunks

The following data chunks were defined after various programs began using
FORM ILBM so they are "nonstandard" chunks.  See the registry document for
the latest information on additional non-standard chunks.

 CRNG
 CCRT


Nonstandard Data Chunks / CRNG

A "CRNG" chunk contains "color register range" information.  It's used by
Electronic Arts' Deluxe Paint program to identify a contiguous range of
color registers for a "shade range" and color cycling.  There can be zero
or more CRNG chunks in an ILBM, but all should appear before the BODY
chunk. Deluxe Paint normally writes 4 CRNG chunks in an ILBM when the user
asks it to "Save Picture".

    typedef struct {
        WORD  pad1;      /* reserved for future use; store 0 here    */
        WORD  rate;      /* color cycle rate                         */
        WORD  flags;     /* see below                                */
        UBYTE low, high; /* lower and upper color registers selected */
        } CRange;

The bits of the flags word are interpreted as follows: if the low bit is
set then the cycle is "active", and if this bit is clear it is not active.
Normally, color cycling is done so that colors move to the next higher
position in the cycle, with the color in the high slot moving around to
the low slot.  If the second bit of the flags word is set, the cycle moves
in the opposite direction.  As usual, the other bits of the flags word are
reserved for future expansion.  Here are the masks to test these bits:

    #define RNG_ACTIVE  1
    #define RNG_REVERSE 2

The fields low and high indicate the range of color registers (color
numbers) selected by this CRange.

The field active indicates whether color cycling is on or off.  Zero means
off.

The field rate determines the speed at which the colors will step when
color cycling is on.  The units are such that a rate of 60 steps per
second is represented as 2^14 = 16384.  Slower rates can be obtained by
linear scaling: for 30 steps/second, rate = 8192; for 1 step/second, rate
= 16384/60 * 273.


Nonstandard Data Chunks / CCRT

Commodore's Graphicraft program uses a similar chunk "CCRT" (for Color
Cycling Range and Timing).  This chunk contains a CycleInfo structure.

    typedef struct {
        WORD  direction;    /* 0 = don't cycle.  1 = cycle forwards      */
                            /* (1, 2, 3). -1 = cycle backwards (3, 2, 1) */
        UBYTE start, end;   /* lower and upper color registers selected  */
        LONG  seconds;      /* # seconds between changing colors plus... */
        LONG  microseconds; /* # microseconds between changing colors    */
        WORD  pad;          /* reserved for future use; store 0 here     */
        } CycleInfo;

This is very similar to a CRNG chunk.  A program would probably only use
one of these two methods of expressing color cycle data, new programs
should use CRNG.  You could write out both if you want to communicate this
information to both Deluxe Paint and Graphicraft.


ILBM IFF Interleaved Bitmap / Appendix A. ILBM Regular Expression

Here's a regular expression summary of the FORM ILBM syntax.  This could
be an IFF file or a part of one.

    ILBM ::= "FORM" #{    "ILBM" BMHD [CMAP] [GRAB] [DEST] [SPRT] [CAMG]
                            CRNG* CCRT* [BODY]    }

    BMHD ::= "BMHD" #{    BitMapHeader    }
    CMAP ::= "CMAP" #{    (red green blue)*    } [0]
    GRAB ::= "GRAB" #{    Point2D    }
    DEST ::= "DEST" #{    DestMerge    }
    SPRT ::= "SPRT" #{    SpritePrecedence    }
    CAMG ::= "CAMG" #{    LONG    }

    CRNG ::= "CRNG" #{    CRange    }
    CCRT ::= "CCRT" #{    CycleInfo    }
    BODY ::= "BODY" #{    UBYTE*    } [0]

The token "#" represents a ckSize LONG count of the following {braced}
data bytes.  E.g., a BMHD's "#" should equal sizeof(BitMapHeader).
Literal strings are shown in "quotes", [square bracket items] are
optional, and "*" means 0 or more repetitions.  A sometimes-needed pad
byte is shown as "[0]".

The property chunks BMHD, CMAP, GRAB, DEST, SPRT, CAMG and any CRNG and
CCRT data chunks may actually be in any order but all must appear before
the BODY chunk since ILBM readers usually stop as soon as they read the
BODY.  If any of the 6 property chunks are missing, default values are
inherited from any shared properties (if the ILBM appears inside an IFF
LIST with PROPs) or from the reader program's defaults.  If any property
appears more than once, the last occurrence before the BODY is the one
that counts since that's the one that modifies the BODY.


ILBM IFF Interleaved Bitmap / Appendix B. ILBM Box Diagram

Here's a box diagram for a simple example: an uncompressed image 320 x 200
pixels x 3 bitplanes.  The text to the right of the diagram shows the
outline that would be printed by the Sift utility program for this
particular file.

              +--------------------+
              |                    |
              |  'FORM'     24070  |  FORM 24070 ILBM
              |                    |
           -- +--------------------+
           |  |                    |
           |  |  'ILBM'            |
           |  |                    |
           |  | +----------------+ |
           |  | |  'BMHD'    20  | |  .BMHD 20
           |  | |----------------| |
           |  | |  320, 200,     | |
           |  | |  0 ....        | |
           |  | +----------------+ |
           |  |                    |
           |  | +----------------+ |
    24070 <   | |  'CMAP'    21  | |  .CMAP 21
     bytes |  | |----------------| |
           |  | |  0, 0, 0,      | |
           |  | |  255 ....      | |
           |  | +----------------+ |
           |  |   0                |
           |  | +----------------+ |
           |  | |  'BODY'  24000 | |  .BODY 24000
           |  | |----------------| |
           |  | |  0, 0, 0....   | |
           |  | +----------------+ |
           |  |                    |
           -- +--------------------+

The "0" after the CMAP chunk is a pad byte.


ILBM IFF Interleaved Bitmap / Appendix C. IFF Hints

Hints on ILBM files from Jerry Morrison, Oct 1988.  How to avoid some
pitfalls when reading ILBM files:

  * Don't ignore the BitMapHeader.masking field.  A bitmap with a mask
    (such as a partially-transparent DPaint brush or a DPaint picture with
    a stencil) will read as garbage if you don't de-interleave the mask.

  * Don't assume all images are compressed.  Narrow images aren't usually
    run-compressed since that would actually make them longer.

  * Don't assume a particular image size.  You may encounter overscan
    pictures and PAL pictures.

There's a better way to read a BODY than the example IFF code.  The
GetBODY routine should call a GetScanline routine once per scan line,
which calls a GetRow routine for each bitplane in the file.  This in turn
calls a GetUnpackedBytes routine, which calls a GetBytes routine as needed
and unpacks the result.  (If the picture is uncompressed, GetRow calls
GetBytes directly.) Since theunpacker knows how many packed bytes to read,
this avoids juggling buffers for a memory-to-memory UnPackBytes routine.

Caution: If you make many AmigaDOS calls to read or write a few bytes at a
time, performance will be mud! AmigaDOS has a high overhead per call, even
with RAM disk.  So use buffered read/write routines.

Different hardware display devices have different color resolutions:

    Device        R:G:B bits    maxColor
    -------       ----------    --------
    Mac SE            1              1
    IBM EGA       2:2:2              3
    Atari ST      3:3:3              7
    Amiga         4:4:4             15
    CD-I          5:5:5             31
    IBM VGA       6:6:6             63
    Mac II        8:8:8            255

An ILBM CMAP defines 8 bits of Red, Green and Blue (i.e., 8:8:8 bits of
R:G:B). When displaying on hardware which has less color resolution, just
take the high order bits.  For example, to convert ILBM's 8-bit Red to the
Amiga's 4-bit Red, right shift the data by 4 bits  (R4 := R8 >> 4).

To convert hardware colors to ILBM colors, the ILBM specification says
just set the high bits (R8 := R4 << 4).  But you can transmit higher
contrast to foreign display devices by scaling the data [0..maxColor] to
the full range [0..255].  In other words, R8 := (Rn x 255) ÷ maxColor.
(Example #1:  EGA color 1:2:3 scales to 85:170:255.  Example #2:  Amiga
15:7:0 scales to 255:119:0).  This makes a big difference where maxColor
is less than 15.  In the extreme case, Mac SE white (1) should be
converted to ILBM white (255), not to ILBM gray (128).

 CGA and EGA subtleties
 24-bit ILBMs


Appendix C. IFF Hints / CGA and EGA subtleties

IBM EGA colors in 350 scan line mode are 2:2:2 bits of R:G:B, stored in
memory as xxR'G'B'RBG.  That's 3 low-order bits followed by 3 high-order
bits.

IBM CGA colors are 4 bits stored in a byte as xxxxIRGB.  (EGA colors in
200 scan line modes are the same as CGA colors, but stored in memory as
xxxIxRGB.) That's 3 high-order bits (one for each of R, G, and B) plus one
low-order " Intensity" bit for all 3 components R, G, and B.  Exception:
IBM monitors show IRGB = 0110 as brown, which is really the EGA color
R:G:B = 2:1:0, not dark yellow 2:2:0.


ILBM IFF Interleaved Bitmap / 24-bit ILBMs

When storing deep images as ILBMs (such as images with 8 bits each of R,G,
and B), the bits for each pixel represent an absolute RGB value for that
pixel rather than an index into a limited color map.  The order for saving
the bits is critical since a deep ILBM would not contain the usual CMAP of
RGB values (such a CMAP would be too large and redundant).

To interpret these "deep" ILBMs, it is necessary to have a standard order
in which the bits of the R, G, and B values will be stored.  A number of
different orderings have already been used in deep ILBMs, so it was
necessary to us chose one of these orderings as a standard.

The following bit ordering has been chosen as the default bit ordering for
deep ILBMs.

Default standard deep ILBM bit ordering:
saved first -----------------------------------------------> saved last
R0 R1 R2 R3 R4 R5 R6 R7 G0 G1 G2 G3 G4 G5 G6 G7 B0 B1 B2 B3 B4 B5 B6 B7

One other existing deep bit ordering that you may encounter is the 21-bit
NewTek format.

NewTek deep ILBM bit ordering:
saved first ------------------------------------------------> saved last
R7 G7 B7 R6 G6 B6 R5 G5 B5 R4 G4 B4 R3 G3 B3 R2 G2 B2 R1 G1 B1 R0 G0 B0

Note that you may encounter CLUT chunks in deep ILBM's.  See the
Third Party Specs appendix for more information on CLUT chunks.


ILBM IFF Interleaved Bitmap / Appendix D. ByteRun1 Run Encoding

The run encoding scheme byteRun1 is best described by pseudo code for the
decoder Unpacker (called UnPackBits in the Macintosh(tm) toolbox):

  UnPacker:
    LOOP until produced the desired number of bytes
        Read the next source byte into n
        SELECT n FROM
            [0..127]   => copy the next n+1 bytes literally
            [-1..-127] => replicate the next byte -n+1 times
            -128       => no operation
            ENDCASE;
        ENDLOOP;

In the inverse routine Packer, it's best to encode a 2 byte repeat run as
a replicate run except when preceded and followed by a literal run, in
which case it's best to merge the three into one literal run.  Always
encode 3 byte repeats as replicate runs.

Remember that each row of each scan line of a raster is separately packed.


ILBM IFF Interleaved Bitmap / Appendix E. Standards Committee

The following people contributed to the design of this FORM ILBM standard:

Bob "Kodiak" Burns, Commodore-Amiga
R. J. Mical, Commodore-Amiga
Jerry Morrison, Electronic Arts
Greg Riker, Electronic Arts
Steve Shaw, Electronic Arts
Dan Silva, Electronic Arts
Barry Walsh, Commodore-Amiga


Appendix A / EA IFF 85 - General IFF Format Specifications

 A Quick Introduction to IFF
 EA IFF 85: Standard for Interchange Format Files


General IFF Format Specifications / A Quick Introduction to IFF

Jerry Morrison, Electronic Arts
10-17-88

IFF is the Amiga-standard "Interchange File Format", designed to work
across many machines.

 Why IFF?                               How to read an IFF file
 What is IFF?                           File extensibility
 What is the Trick?                     Advanced Topics
 What does an IFF file look like?


A Quick Introduction to IFF / Why IFF?

Did you ever have this happen to your picture file?

   You can't load it into another paint program.
   You need a converter to adopt to "ZooPaint" release 2.0 or a new
    hardware feature.
   You must "export" and "import" to use it in a page layout program.
   You can't move it to another brand of computer.

What about interchanging musical scores, digitized audio, and other data?
It seems the only thing that does interchange well is plain ASCII text
files.

It's inexcusable. And yet this is "normal" in MS-DOS.


A Quick Introduction to IFF / What is IFF?

IFF, the "Interchange File Format" standard, encourages multimedia
interchange between different programs and different computers.  It
supports long-lived, extensible data.  It's great for composite files like
a page layout file that includes photos, an animation file that includes
music, and a library of sound effects.

IFF is a 2-level standard.  The first layer is the "wrapper" or "envelope"
structure for all IFF files.  Technically, it's the syntax.  The second
layer defines particular IFF file types such as ILBM (standard raster
pictures), ANIM (animation), SMUS (simple musical score), and 8SVX (8-bit
sampled audio voice).

IFF is also a design idea: programs should use interchange formats for
their everyday storage.

This way, users rarely need converters and import/export commands to
change software releases, application programs, or hardware.


A Quick Introduction to IFF / What is the trick?

File compatibility is easy to achieve if programmers let go of one
notion - dumping internal data structures to disk.  A program's internal
data structures should really be suited to what the program does and how
it works.  What's "best" changes as the program evolves new functions and
methods.  But a disk format should be suited to storage and interchange.

Once we design internal formats and disk formats for their own separate
purposes, the rest is easy.  Reading and writing become behind-the-scenes
conversions.  But two conversions hidden in each program is much better
than a pile of conversion programs.

Does this seem strange?  It's what ASCII text programs do!  Text editors
use line tables, piece tables, gaps, and other structures for fast editing
and searching.  Text generators and consumers construct and parse files.
That's why the ASCII standard works so well.

Also, every file must be self-sufficient.  E.g., a picture file has to
include its size and number of bits/pixel.


A Quick Introduction to IFF / What does an IFF file look like?

IFF is based on data blocks called "chunk"s. Here's an example color map
chunk:

                         +------------------+ in an ILBM file, CMAP means
          char typeID[4] | "CMAP"           | "color map"
                         |------------------+
  unsigned long dataSize |  48              | 48 data bytes
                         |------------------+
             char data[] |  0,0,0,255,      | 16 3-byte color values:
                         |  255,255,255...  | black, white, ....
                         +------------------+

                         +------------------+ in an ILBM file, CMAP means
                         | "CMAP"           | "color map"
                         |------------------+
                         |  48              | 48 data bytes
                         |------------------+
                         |  0,0,0,255,      | 16 3-byte color values:
                         |  255,255,255...  | black, white, ....
                         +------------------+

A chunk is made of a 4-character type identifier, a 32 bit data byte
count, and the data bytes. It's like a Macintosh "resource" with a 32-bit
size.

Fine points:

 o Every 16- and 32-bit number is stored in 68000 byte order - highest
    byte first.

   An Intel CPU must reverse the 2- or 4-byte sequence of each number.
   This applies to chunk dataSize fields and to numbers inside chunk
   data.  It does not affect character strings and byte data because you
   can't reverse a 1-byte sequence.  But it does affect the 32-bit math
   used in IFF's MakeID macro.  The standard does allow CPU specific byte
   ordering hidden within a chunk itself, but the practice is discouraged.

 o Every 16- and 32-bit number is stored on an even address.

 o Every odd-length chunk must be followed by a 0 pad byte.  This pad
    byte is not counted in dataSize.

 o An ID is made of 4 ASCII characters in the range " " (space, hex 20)
    through "~" (tilde, hex 7E).  Leading spaces are not permitted.

 o IDs are compared using a quick 32-bit equality test.  Case matters.

A chunk typically holds a C structure, Pascal record, or an array.  For
example, an ILBM picture has a BMHD bitmap header chunk (a structure)
and a BODY raster body chunk (an array).

To construct an IFF file, just put a file type ID (like ILBM) into a
wrapper chunk called a "FORM" (Think "FILE").  Inside that wrapper place
chunks one after another (with pad bytes as needed).  The chunk size
always tells you how many more bytes you need to skip over to get to the
next chunk.

              +------------------+
              |                  |
              |  "FORM"          |  FORM is a special chunk ID
              |                  |
              +------------------+
              |   24070          |  24070 data bytes
           -- +------------------+
           |  |                  |
           |  |  "ILBM"          |  FORM type is ILBM
           |  |                  |
           |  | +--------------+ |
           |  | |  "BMHD"      | |  A BMHD bitmap header chunk
           |  | |--------------| |  (20 data bytes)
           |  | |   20         | |
           |  | |--------------| |
           |  | |  320, 200,   | |
           |  | |  0 ....      | |
           |  | +--------------+ |
           |  |                  |
           |  | +--------------+ |
           |  | |  "CMAP"      | |  A CMAP color map chunk
    24070 <   | |--------------| |  (21 data bytes = 1 pad)
    bytes  |  | |   21         | |
           |  | |--------------| |
           |  | |  0, 0, 0,    | |
           |  | |  255 ....    | |
           |  | +--------------+ |
           |  |   0              |  A pad byte
           |  | +--------------+ |
           |  | |  "BODY"      | |
           |  | |--------------| |  A BODY raster body chunk
           |  | |  24000       | |  (24000 data bytes)
           |  | |--------------| |
           |  | |  0, 0, 0.... | |
           |  | +--------------+ |
           -- +------------------+

A FORM always contains one 4-character FORM type ID (a file type, in this
case "ILBM") followed by any number of data chunk.  In this example, the
FORM type is "ILBM", which stands for "InterLeaved BitMap".  (ILBM is an
IFF standard for bitplane raster pictures.)  This example has 3 chunks.
Note the pad byte after the odd length chunk.

Within FORMs ILBM, BMHD identifies a bitmap header chunk, CMAP a color
map, and BODY a raster body.  In general, the chunk IDs in a FORM are
local to the FORM type ID.  The  exceptions are the 4 global chunk IDs
"FORM", LIST, CAT , and PROP.  (A FORM may contain other FORM
chunks.  E.g., an animation FORM might contain picture FORMs and sound
FORMs.)


A Quick Introduction to IFF / How to read an IFF file?

Example code and modules are provided for reading IFF files using
iffparse.library. However, if you wish to read a non-complex FORM by hand,
the following logic can be used.

Once you have entered the FORM (for example, the FORM ILBM shown above),
stored the FORM length (24070 in the ILBM example) and are positioned on
the first chunk, you may:

Loop: (Until end-of-file or end-of-form)

        - Read the 4-character identifier of the chunk
        - Read the 32-bit (4 byte) chunklength
        - Decide if you want that chunk
              if yes, read chunklength bytes into destination
              structure or buffer
              if no, seek forward chunklength bytes
        - If chunklength is odd, seek one more byte.

Every IFF file is a FORM, LIST, or CAT chunk.  You can recognize an
IFF file by those first 4 bytes.  ("FORM" is far and away the most common.
We'll get to LIST and CAT below.)  If the file contains a FORM, dispatch
on the FORM type ID to a chunk-reader loop like the one above.


A Quick Introduction to IFF / File extensibility

IFF files are extensible and forward/backward compatible:

  o Chunk contents should be designed for compatibility across
     environments and for longevity.  Every chunk should have a path for
     future expansion; at minimum this will be an unused bit or two.

  o The standards team for a FORM type can extend one of the chunks that
     contains a structure by appending new, optional structure fields.

  o Anyone can define new FORM types as well as new chunk types within a
     FORM type.  Storing private chunks within a FORM is OK, but be sure
     to register your activities with Commodore Applications and Technical
     Support.

  o A chunk can be superseded by a new chunk type, e.g., to store more
     bits per RGB color register. New programs can output the old chunk
     (for backward compatibility) along with the new chunk.

  o If you must change data in an incompatible way, change the chunk ID or
     the FORM type ID.


A Quick Introduction to IFF/ Advanced Topics

CAT, LIST, and PROP

Sometimes you want to put several "files" into one, such as a picture
library. This is what CAT is for.  It "concatenates" FORM and LIST chunks.

          +--------------------+
          |                    |
          |   "CAT "           |  concatenation
          |                    |
          +--------------------+
          |   48160            |  48160 data bytes
          +--------------------+
          |                    |
          |   "ILBM"           |  This concatenation contains FORMs ILBM
          |                    |
          |  +--------------+  |
          |  |  "FORM"      |  |  A FORM ILBM
          |  |--------------|  |
          |  |   24070      |  |
          |  |--------------|  |
          |  |  "ILBM"      |  |
          |  |--------------|  |
          |  |  ....        |  |
          |  +--------------+  |
          |                    |
          |  +--------------+  |
          |  |  "FORM"      |  |  Another FORM ILBM
          |  |--------------|  |
          |  |   24070      |  |
          |  |--------------|  |
          |  |  "ILBM"      |  |
          |  |--------------|  |
          |  |  ....        |  |
          |  +--------------+  |
          |                    |
          +--------------------+

This example CAT holds two ILBMs. It can be shown outline-style:

  CAT ILBM
  ..FORM ILBM   \
  ....BMHD      | a complete FORM ILBM picture
  ....CMAP      |
  ....BODY      /
  ..FORM ILBM
  ....BMHD
  ....CMAP
  ....BODY

Sometimes you want to share the same color map across many pictures. LIST
and PROP do this:

  LIST ILBM
  ..PROP ILBM   default properties for FORMs ILBM
  ....CMAP      an ILBM CMAP chunk (there could be a BMHD chunk here, too)
  ..FORM ILBM
  ....BMHD      (there could be a CMAP here to override the default)
  ....BODY
  ..FORM ILBM
  ....BMHD      (there could be a CMAP here to override the default)
    ....BODY

A LIST holds PROPs and FORMs (and occasionally LISTs and CATs).  A PROP
ILBM contains default data (in the above example, just one CMAP chunk) for
all FORMs ILBM in the LIST.  Any FORM may override the PROP-defined
default with its own CMAP.  All PROPs must appear at the beginning of a
LIST.  Each FORM type standardizes (among other things) which of its
chunks are "property chunks" (may appear in PROPs) and which are "data
chunks" (may not appear in PROPs).


Appendix A / EA IFF 85: Standard for Interchange Format Files

Document Date:	January 14, 1985  (Updated Oct, 1988 Commodore-Amiga, Inc.)
From:		Jerry Morrison, Electronic Arts
Status:		Released to the public domain, and in use

 Introduction                   LISTs, CATs and Shared Property
 Background for Designers       Standard File Structure
 Primitive Data Types           Standards Committee
 Data Sections                  Appendix A. Reference


EA IFF 85: Standard for Interchange Format Files / Introduction

 Standards are Good for Software Developers
 Standards are Good for Software Users
 Here is EA IFF 1985
 References


A / Introduction / Standards are Good for Software Developers

As home computer hardware evolves into better and better media machines,
the demand increases for higher quality, more detailed data.  Data
development gets more expensive, requires more expertise and better tools,
and has to be shared across projects.  Think about several ports of a
product on one CD-ROM with 500M Bytes of common data!

Development tools need standard interchange file formats.  Imagine
scanning in images of "player" shapes, transferring them to an image
enhancement package, moving them to a paint program for touch up, then
incorporating them into a game.  Or writing a theme song with a Macintosh
score editor and incorporating it into an Amiga game.  The data must at
times be transformed, clipped, filled out, and moved across machine kinds.
Media projects will depend on data transfer from graphic, music, sound
effect, animation, and script tools.


A / Introduction / Standards are Good for Software Users

Customers should be able to move their own data between independently
developed software products.  And they should be able to buy data
libraries usable across many such products.  The types of data objects to
exchange are open-ended and include plain and formatted text, raster and
structured graphics, fonts, music, sound effects, musical instrument
descriptions, and animation.

The problem with expedient file formats - typically memory dumps is that
they're too provincial.  By designing data for one particular use (such as
a screen snapshot), they preclude future expansion (would you like a full
page picture?  a multi-page document?).  In neglecting the possibility
that other programs might read their data, they fail to save contextual
information (how many bit planes?  what resolution?).  Ignoring that other
programs might create such files, they're intolerant of extra data (a
different picture editor may want to save a texture palette with the
image), missing data (such as no color map), or minor variations (perhaps
a smaller image).  In practice, a filed representation should rarely
mirror an in-memory representation.  The former should be designed for
longevity; the latter to optimize the manipulations of a particular
program.  The same filed data will be read into different memory formats
by different programs.

The IFF philosophy: "A little behind-the-scenes conversion when programs
read and write files is far better than NxM explicit conversion utilities
for highly specialized formats".

So we need some standardization for data interchange among development
tools and products.  The more developers that adopt a standard, the better
for all of us and our customers.


A / Introduction / Here is EA IFF 1985

Here is our offering: Electronic Arts' IFF standard for Interchange File
Format.  The full name is "EA IFF 1985".  Alternatives and justifications
are included for certain choices.  Public domain subroutine packages and
utility programs are available to make it easy to write and use
IFF-compatible programs.

Part 1 introduces the standard.  Part 2 presents its requirements and
background.  Parts 3, 4, and 5 define the primitive data types, FORMs, and
LISTs, respectively, and how to define new high level types.  Part 6
specifies the top level file structure.  Section 7 lists names of the
group responsible for this standard.  Appendix A is included for quick
reference and Appendix B.


A / Introduction / References

American National Standard Additional Control Codes for Use with ASCII, ANSI
standard 3.64-1979 for an 8-bit character set.  See also ISO standard 2022
and ISO/DIS standard 6429.2.

The C Programming Language, Brian W. Kernighan and Dennis M. Ritchie, Bell
Laboratories.  Prentice-Hall, Englewood Cliffs, NJ, 1978.

C, A Reference Manual, Samuel P. Harbison and Guy L. Steele Jr., Tartan
Laboratories.  Prentice-Hall, Englewood Cliffs, NJ, 1984.

Compiler Construction, An Advanced Course, edited by F. L. Bauer and J.
Eickel (Springer-Verlag, 1976).  This book is one of many sources for
information on recursive descent parsing.

DIF Technical Specification (c) 1981 by Software Arts, Inc.  DIF(tm) is
the format for spreadsheet data interchange developed by Software Arts,
Inc. DIF(tm) is a trademark of Software Arts, Inc.

"FTXT" IFF Formatted Text, from Electronic Arts.  IFF supplement document
for a text format.

"ILBM" IFF Interleaved Bitmap, from Electronic Arts.  IFF supplement
document for a raster image format.

M68000 16/32-Bit Microprocessor Programmer's Reference Manual (c) 1984,
1982, 1980, 1979 by Motorola, Inc.

PostScript Language Manual (c) 1984 Adobe Systems Incorporated.
PostScript(tm) is a trademark of Adobe Systems, Inc. Times and Helvetica®
are registered trademarks of Allied Corporation.

Inside Macintosh (c) 1982, 1983, 1984, 1985 Apple Computer, Inc., a
programmer's reference manual. Apple® is a trademark of Apple Computer,
Inc. MacPaint(tm) is a trademark of Apple Computer, Inc. Macintosh(tm) is
a trademark licensed to Apple Computer, Inc.

InterScript: A Proposal for a Standard for the Interchange of Editable
Documents (c) 1984 Xerox Corporation.  Introduction to InterScript (c)
1985 Xerox Corporation.

Amiga® is a registered trademark of Amiga, Inc.

Electronics Arts(tm) is a trademark of Electronic Arts.


A / EA IFF 85:Standard for Interchange Format Files / Design Background

Part 2 is about the background, requirements, and goals for the standard.
It's geared for people who want to design new types of IFF objects. People
just interested in using the standard may wish to quickly scan this
section.

 What Do We Need?     Data Abstraction
 Think Ahead          Previous Work
 Scope


Background for Designers / What Do We Need?

A standard should be long on prescription and short on overhead.  It
should give lots of rules for designing programs and data files for
synergy.  But neither the programs nor the files should cost too much more
than the expedient variety.  Although we are looking to a future with
CD-ROMs and perpendicular recording, the standard must work well on floppy
disks.

For program portability, simplicity, and efficiency, formats should be
designed with more than one implementation style in mind.  It ought to be
possible to read one of many objects in a file without scanning all the
preceding data.   (In practice, pure stream I/O is adequate although
random access makes it easier to write files.)  Some programs need to read
and play out their data in real time, so we need good compromises between
generality and efficiency.

As much as we need standards, they can't hold up product schedules.  So we
also need a kind of decentralized extensibility where any software
developer can define and refine new object types without some "standards
authority" in the loop.  Developers must be able to extend existing
formats in a forward- and backward-compatible way.  A central repository
for design information and example programs can help us take full
advantage of the standard.

For convenience, data formats should heed the restrictions of various
processors and environments.  For example, word-alignment greatly helps
68000 access at insignificant cost to 8088 programs.

Other goals include the ability to share common elements over a list of
objects and the ability to construct composite objects.

And finally, "Simple things should be simple and complex things should be
possible" - Alan Kay.


Background for Designers / Think Ahead

Let's think ahead and build programs that read and write files for each
other and for programs yet to be designed.  Build data formats to last for
future computers so long as the overhead is acceptable.  This extends the
usefulness and life of today's programs and data.

To maximize interconnectivity, the standard file structure and the
specific object formats must all be general and extensible.  Think ahead
when designing an object.  File formats should serve many purposes and
allow many programs to store and read back all the information they need;
even squeeze in custom data.  Then a programmer can store the available
data and is encouraged to include fixed contextual details.  Recipient
programs can read the needed parts, skip unrecognized stuff, default
missing data, and use the stored context to help transform the data as
needed.


Background for Designers / Scope

IFF addresses these needs by defining a standard file structure, some
initial data object types, ways to define new types, and rules for
accessing these files.  We can accomplish a great deal by writing programs
according to this standard, but do not expect direct compatibility with
existing software. We'll need conversion programs to bridge the gap from
the old world.

IFF is geared for computers that readily process information in 8-bit
bytes. It assumes a "physical layer" of data storage and transmission that
reliably maintains "files" as sequences of 8-bit bytes.  The standard
treats a "file" as a container of data bytes and is independent of how to
find a file and whether it has a byte count.

This standard does not by itself implement a clipboard for cutting and
pasting data between programs.  A clipboard needs software to mediate
access, and provide a notification mechanism so updates and requests for
data can be detected.


Background for Designers / Data Abstraction

The basic problem is how to represent information  in a way that's
program- independent, compiler- independent, machine-independent, and
device-independent.

The computer science approach is "data abstraction", also known as
"objects", "actors", and "abstract data types".  A data abstraction has a
"concrete representation" (its storage format), an "abstract
representation" (its capabilities and uses), and access procedures that
isolate all the calling software from the concrete representation.  Only
the access procedures touch the data storage.  Hiding mutable details
behind an interface is called "information hiding".  What is hidden are
the non-portable details of implementing the object, namely the selected
storage representation and algorithms for manipulating it.

The power of this approach is modularity.  By adjusting the access
procedures we can extend and restructure the data without impacting the
interface or its callers.  Conversely, we can extend and restructure the
interface and callers without making existing data obsolete.  It's great
for interchange!

But we seem to need the opposite: fixed file formats for all programs to
access.  Actually, we could file data abstractions ("filed objects") by
storing the data and access procedures together.  We'd have to encode the
access procedures in a standard machine-independent programming language á
la PostScript.  Even with this, the interface can't evolve freely since we
can't update all copies of the access procedures.  So we'll have to design
our abstract representations for limited evolution and occasional
revolution (conversion).

In any case, today's microcomputers can't practically store true data
abstractions.  They can do the next best thing: store arbitrary types of
data in "data chunks", each with a type identifier and a length count.
The type identifier is a reference by name to the access procedures (any
local implementation).  The length count enables storage-level object
operations like "copy" and "skip to next" independent of object type or
contents.

Chunk writing is straightforward.  Chunk reading requires a trivial parser
to scan each chunk and dispatch to the proper access/conversion procedure.
Reading chunks nested inside other chunks may require recursion, but no
look ahead or backup.

That's the main idea of IFF.  There are, of course, a few other
details....


Background for Designers / Previous Work

Where our needs are similar, we borrow from existing standards. Our basic
need to move data between independently developed programs is similar to
that addressed by the Apple Macintosh desk scrap or "clipboard" [Inside
Macintosh chapter "Scrap Manager"].  The Scrap Manager works closely with
the Resource Manager, a handy filer and swapper for data objects (text
strings, dialog window templates, pictures, fonts?) including types yet to
be designed [Inside Macintosh chapter "Resource Manager"].  The Resource
Manager is akin to Smalltalk's object swapper.

We will probably write a Macintosh desk accessory that converts IFF files
to and from the Macintosh clipboard for quick and easy interchange with
programs like MacPaint and Resource Mover.

Macintosh uses a simple and elegant scheme of four-character "identifiers"
to identify resource types, clipboard format types, file types, and file
creator programs.  Alternatives are unique ID numbers assigned by a
central authority or by hierarchical authorities, unique ID numbers
generated by algorithm, other fixed length character strings, and variable
length strings.  Character string identifiers double as readable signposts
in data files and programs. The choice of 4 characters is a good tradeoff
between storage space, fetch/compare/store time, and name space size.
We'll honor Apple's designers by adopting this scheme.

"PICT" is a good example of a standard structured graphics format
(including raster images) and its many uses [Inside Macintosh chapter
"QuickDraw"]. Macintosh provides QuickDraw routines in ROM to create,
manipulate, and display PICTs.  Any application can create a PICT by
simply asking QuickDraw to record a sequence of drawing commands.  Since
it's just as easy to ask QuickDraw to render a PICT to a screen or a
printer, it's very effective to pass them betweenprograms, say from an
illustrator to a word processor.  An important feature is the ability to
store "comments" in a PICT which QuickDraw will ignore.  (Actually, it
passes them to your optional custom "comment handler".)

PostScript, Adobe System's print file standard, is a more general way to
represent any print image (which is a specification for putting marks on
paper) [PostScript Language Manual].  In fact, PostScript is a
full-fledged programming language.  To interpret a PostScript program is
to render a document on a raster output device.  The language is defined
in layers: a lexical layer of identifiers, constants, and operators; a
layer of reverse polish semantics including scope rules and a way to
define new subroutines; and a printing-specific layer of built-in
identifiers and operators for rendering graphic images.  It is clearly a
powerful (Turing equivalent) image definition language.  PICT and a subset
of PostScript are candidates for structured graphics standards.

A PostScript document can be printed on any raster output device
(including a display) but cannot generally be edited.  That's because the
original flexibility and constraints have been discarded.  Besides, a
PostScript program may use arbitrary computation to supply parameters like
placement and size to each operator.  A QuickDraw PICT, in comparison, is
a more restricted format of graphic primitives parameterized by constants.
So a PICT can be edited at the level of the primitives, e.g., move or
thicken a line.  It cannot be edited at the higher level of, say, the bar
chart data which generated the picture.

PostScript has another limitation: not all kinds of data amount to marks
on paper.  A musical instrument description is one example.  PostScript is
just not geared for such uses.

"DIF" is another example of data being stored in a general format usable
by future programs [DIF Technical Specification].  DIF is a format for
spreadsheet data interchange.  DIF and PostScript are both expressed in
plain ASCII text files.  This is very handy for printing, debugging,
experimenting, and transmitting across modems.  It can have substantial
cost in compaction and read/write work, depending on use.  We won't store
IFF files this way but we could define an ASCII alternate representation
with a converter program.

InterScript is the Xerox standard for interchange of editable documents
[Introduction to InterScript].  It approaches a harder problem: How to
represent editable word processor documents that may contain formatted
text, pictures, cross-references like figure numbers, and even highly
specialized objects like mathematical equations?  InterScript aims to
define one standard representation for each kind of information.  Each
InterScript-compatible editor is supposed to preserve the objects it
doesn't understand and even maintain nested cross-references.  So a simple
word processor would let you edit the text of a fancy document without
discarding the equations or disrupting the equation numbers.

Our task is similarly to store high level information and preserve as much
content as practical while moving it between programs.  But we need to
span a larger universe of data types and cannot expect to centrally define
them all. Fortunately, we don't need to make programs preserve information
that they don't understand.  And for better or worse, we don't have to
tackle general- purpose cross-references yet.


App.A EA IFF/ Primitive Data Types

Atomic components such as integers and characters that are interpretable
directly by the CPU are specified in one format for all processors.  We
chose a format that's the same as used by the Motorola MC68000 processor
[M68000 16/32-Bit Microprocessor Programmer's Reference Manual].  The high
byte and high word of a number are stored first.

N.B.: Part 3 dictates the format for "primitive" data types where-and
only where-used in the overall file structure.  The number of such
occurrences of dictated formats will be small enough that the costs of
conversion, storage, and management of processor-specific files would far
exceed the costs of conversion during I/O by "foreign" programs.  A
particular data chunk may be specified with a different format for its
internal primitive types or with processor or environment specific
variants if necessary to optimize local usage.  Since that hurts data
interchange, it's not recommended.  (Cf. Designing New Data Sections, in
Part 4.)

 Alignment   Characters   Type IDs   Strings           Links
 Numbers     Dates        Chunks     Data Properties   File References


Primitive Data Types / Alignment

All data objects larger than a byte are aligned on even byte addresses
relative to the start of the file.  This may require padding.  Pad bytes
are to be written as zeros, but don't count on that when reading.

This means that every odd-length "chunk" must be padded so that the next
one will fall on an even boundary.  Also, designers of structures to be
stored in chunks should include pad fields where needed to align every
field larger than a byte.  For best efficiency, long word data should be
arranged on long word (4 byte) boundaries.  Zeros should be stored in all
the pad bytes.

Justification: Even-alignment causes a little extra work for files that
are used only on certain processors but allows 68000 programs to construct
and scan the data in memory and do block I/O.  Any 16-bit or greater CPU
will have faster access to aligned data.  You just add an occasional pad
field to data structures that you're going to block read/write or else
stream read/write an extra byte.  And the same source code works on all
processors.  Unspecified alignment, on the other hand, would force 68000
programs to (dis)assemble word and long word data one byte at a time.
Pretty cumbersome in a high level language.  And if you don't
conditionally compile that step out for other processors, you won't gain
anything.


Primitive Data Types / Numbers

Numeric types supported are two's complement binary integers in the format
used by the MC68000 processor - high byte first, high word first - the
reverse of 8088 and 6502 format.

    UBYTE	 8 bits unsigned
    WORD	16 bits signed
    UWORD	16 bits unsigned
    LONG	32 bits signed

The actual type definitions depend on the CPU and the compiler.  In this
document, we'll express data type definitions in the C programming
language. [See C, A Reference Manual.]  In 68000 Lattice C:

    typedef unsigned char	UBYTE;	/*  8 bits unsigned	*/
    typedef short		WORD;	/* 16 bits signed	*/
    typedef unsigned short	UWORD;	/* 16 bits unsigned	*/
    typedef long		LONG;	/* 32 bits signed	*/


Primitive Data Types / Characters

The following character set is assumed wherever characters are used, e.g.,
in text strings, IDs, and TEXT chunks (see below).  Characters are encoded
in 8-bit ASCII.  Characters in the range NUL (hex 0) through DEL (hex 7F)
are well defined by the 7-bit ASCII standard.  IFF uses the graphic group
" " (SP, hex 20) through "~" (hex 7E).

Most of the control character group hex 01 through hex 1F have no standard
meaning in IFF.  The control character LF (hex 0A) is defined as a
"newline" character.  It denotes an intentional line break, that is, a
paragraph or line terminator.  (There is no way to store an automatic line
break.  That is strictly a function of the margins in the environment the
text is placed.) The controlcharacter ESC (hex 1B) is a reserved escape
character under the rules of ANSI standard 3.64-1979 American National
Standard Additional Control Codes for Use with ASCII, ISO standard 2022,
and ISO/DIS standard 6429.2.

Characters in the range hex 7F through hex FF are not globally defined in
IFF. They are best left reserved for future standardization.  (Note that
the FORM type FTXT (formatted text) defines the meaning of these
characters within FTXT forms.)  In particular, character values hex 7F
through hex 9F are control codes while characters hex A0 through hex FF
are extended graphic characters like Å, as per the ISO and ANSI standards
cited above.  [See the supplementary document "FTXT" IFF Formatted Text.]


Primitive Data Types / Dates

A "creation date" is defined as the date and time a stream of data bytes
was created.  (Some systems call this a "last modified date".)  Editing
some data changes its creation date.  Moving the data between volumes or
machines does not.

The IFF standard date format will be one of those used in MS-DOS,
Macintosh, or AmigaDOS (probably a 32-bit unsigned number of seconds since
a reference point).  Issue: Investigate these three.


Primitive Data Types / Type IDs

A "type ID", "property name", "FORM type", or any other IFF identifier is
a 32-bit value: the concatenation of four ASCII characters in the range
" " (SP, hex 20) through '~' (hex 7E).  Spaces (hex 20) should not precede
printing characters; trailing spaces are OK.  Control characters are
forbidden.

    typedef CHAR ID[4];

IDs are compared using a simple 32-bit case-dependent equality test.  FORM
type IDs are restricted.  Since they may be stored in filename extensions
lower case letters and punctuation marks are forbidden.  Trailing spaces
are OK.

Carefully choose those four characters when you pick a new ID.  Make them
mnemonic so programmers can look at an interchange format file and figure
out what kind of data it contains.  The name space makes it possible for
developers scattered around the globe to generate ID values with minimal
collisions so long as they choose specific names like "MUS4" instead of
general ones like "TYPE" and "FILE".

Commodore Applications and Technical Support has undertaken the task of
maintaining the registry of FORM type IDs and format descriptions.  See
the IFF Registry document for more information.

Sometimes it's necessary to make data format changes that aren't backward
compatible.  As much as we work for compatibility, unintended interactions
can develop.  Since IDs are used to denote data formats in IFF, new IDs
are chosen to denote revised formats.  Since programs won't read chunks
whose IDs they don't recognize (see Chunks, below), the new IDs keep old
programs from stumbling over new data.  The conventional way to chose a
"revision" ID is to increment the last character if it's a digit or else
change the last character to a digit.  E.g., first and second revisions of
the ID "XY" would be "XY1" and "XY2".  Revisions of "CMAP" would be "CMA1"
and "CMA2".


Primitive Data Types / Chunks

Chunks are the building blocks in the IFF structure.  The form expressed
as a C typedef is:

    typedef struct {
    ID	ckID;			/* 4 character ID */
    LONG	ckSize;			/* sizeof(ckData) */
    UBYTE	ckData[/* ckSize */];
    } Chunk;

We can diagram an example chunk - a "CMAP" chunk containing 12 data bytes
- like this:

                        +------------------+   -
        ckID:           | "CMAP"           |   |
                        |------------------+   |
        ckSize:         |  12              |   |
                    -   |------------------+   |
        ckData:     |   |  0, 0, 0, 32     |  20 bytes
                   12   |------------------+   |
                  bytes |  0, 0, 64, 0     |   |
                    |   |------------------+   |
                    |   |  0, 0, 64, 0     |   |
                    -   +------------------+   -

That's 4 bytes of ckID, 4 bytes of ckSize and 12 data bytes.  The total
space used is 20 bytes.

The ckID identifies the format and purpose of the chunk.  As a rule, a
program must recognize ckID to interpret ckData.  It should skip over all
unrecognized chunks.  The ckID also serves as a format version number as
long as we pick new IDs to identify new formats of ckData (see above).

The following ckIDs are universally reserved to identify chunks with
particular IFF meanings: LIST, FORM, PROP, CAT , and "    ".  The
special ID "    " (4 spaces) is a ckID for "filler" chunks, that is,
chunks that fill space but have no meaningful contents.  The IDs "LIS1"
through "LIS9", "FOR1" through "FOR9", and "CAT1" through "CAT9" are
reserved for future "version number" variations.  All IFF-compatible
software must account for these chunk IDs.

The ckSize is a logical block size - how many data bytes are in ckData.  If
ckData is an odd number of bytes long, a 0 pad byte follows which is not
included in ckSize.  (Cf. Alignment.)  A chunk's total physical size is
ckSize rounded up to an even number plus the size of the header.  So the
smallest chunk is 8 bytes long with ckSize = 0.  For the sake of following
chunks, programs must respect every chunk's ckSize as a virtual
end-of-file for reading its ckData even if that data is malformed, e.g.,
if nested contents are truncated.

We can describe the syntax of a chunk as a regular expression with "#"
representing the ckSize, the length of the following {braced} bytes.  The
"[0]" represents a sometimes needed pad byte.  (The regular expressions in
this document are collected in Appendix A along with an explanation of
notation.)

    Chunk	::= ID #{ UBYTE* } [0]

One chunk output technique is to stream write a chunk header, stream write
the chunk contents, then random access back to the header to fill in the
size. Another technique is to make a preliminary pass over the data to
compute the size, then write it out all at once.


Primitive Data Types / Strings, String Chunks, and String Properties

In a string of ASCII text, linefeed (0x0A) denotes a forced line break
(paragraph or line terminator).  Other control characters are not used.
(Cf. Characters.)  For maximum compatibility with line editors, two
linefeed characters are often used to indicate a paragraph boundary.

The ckID for a chunk that contains a string of plain, unformatted text is
"TEXT".  As a practical matter, a text string should probably not be
longer than 32767 bytes.  The standard allows up to 2^31 - 1 bytes.  The
ckID "TEXT" is globally reserved for this use.

When used as a data property (see below), a text string chunk may be 0 to
255 characters long.  Such a string is readily converted to a C string or
a Pascal STRING[255].  The ckID of a property must have a unique property
name, not "TEXT".

When used as a part of a chunk or data property, restricted C string
format is normally used.  That means 0 to 255 characters followed by a
NULL byte (ASCII value 0).


Primitive Data Types / Data Properties (advanced topic)

Data properties specify attributes for following (non-property) chunk.  A
data property essentially says "identifier = value", for example "XY =
(10, 200)", telling something about following chunks.  Properties may only
appear inside data sections ("FORM" chunks, cf. Data Sections) and
property sections ("PROP" chunks, cf. Group PROP).

The form of a data property is a type of Chunk.  The ckID is a property
name as well as a property type.  The ckSize should be small since data
properties are intended to be accumulated in RAM when reading a file.
(256 bytes is a reasonable upper bound.)  Syntactically:

    Property	::= Chunk

When designing a data object, use properties to describe context
information like the size of an image, even if they don't vary in your
program.  Other programs will need this information.

Think of property settings as assignments to variables in a programming
language.  Multiple assignments are redundant and local assignments
temporarily override global assignments.  The order of assignments doesn't
matter as long as they precede the affected chunk.  (Cf. LISTs, CATs, and
Shared Properties.)

Each object type (FORM type) is a local name space for property IDs.
Think of a "CMAP" property in a "FORM ILBM" as the qualified ID
"ILBM.CMAP".  A "CMAP" inside some other type of FORM may not have the
same meaning.  Property IDs specified when an object type is designed (and
therefore known to all clients) are called "standard" while specialized
ones added later are "nonstandard".


Primitive Data Types / Links

Issue: A standard mechanism for "links" or "cross references" is very
desirable for things like combining images and sounds into animations.
Perhaps we'll define "link" chunk within FORMs that refer to other FORMs
or to specific chunks within the same and other FORMs.  This needs further
work. EA IFF 1985 has no standard link mechanism.

For now, it may suffice to read a list of, say, musical instruments, and
then just refer to them within a musical score by  sequence  number.


Primitive Data Types / File References

Issue: We may need a standard form for references to other files.  A "file
ref" could name a directory and a file in the same type of operating
system as the reference's originator.  Following the reference would
expect the file to be on some mounted volume, or perhaps the same
directory as the file that made the reference.  In a network environment,
a file reference could name a server, too.

Issue: How can we express operating-system independent file references?

Issue: What about a means to reference a portion of another file?  Would
this be a "file ref" plus a reference to a "link" within the target file?


Appendix A / EA IFF/ Data Sections

The first thing we need of a file is to check: Does it contain IFF data
and, if so, does it contain the kind of data we're looking for?  So we
come to the notion of a "data section".

A "data section" or IFF "FORM" is one self-contained "data object" that
might be stored in a file by itself.  It is one high level data object
such as a picture or a sound effect, and generally contains a grouping of
chunks.  The IFF structure "FORM" makes it self-identifying.  It could be
a composite object like a musical score with nested musical instrument
descriptions.

 Group FORM
 Composite FORMs
 Designing New Data Sections


Data Sections / Group FORM

A data section is a chunk with ckID "FORM" and this arrangement:

    FORM       ::= "FORM" #{ FormType (LocalChunk | FORM | LIST | CAT)* }
    FormType   ::= ID
    LocalChunk ::= Property | Chunk

The ID "FORM" is a syntactic keyword like "struct" in C.  Think of a
"struct ILBM" containing a field "CMAP".  If you see "FORM" you will know
to expect a FORM type ID (the structure name, "ILBM" in this example) and
a particular contents arrangement or "syntax" (local chunk, FORMs, LISTs,
and CAT ).  A "FORM ILBM", in particular, might contain a local chunk
"CMAP", an "ILBM.CMAP" (to use a qualified name).

So the chunk ID "FORM" indicates a data section.  It implies that the
chunk contains an ID and some number of nested chunks.  In reading a FORM,
like any other chunk, programs must respect its ckSize as a virtual
end-of-file for reading its contents, even if they're truncated.

The FORM type is a restricted ID that may not contain lower case letters
or punctuation characters.  (Cf. Type IDs.  Cf. Single Purpose Files.)

The type-specific information in a FORM is composed of its "local chunks":
data properties and other chunks.  Each FORM type is a local name space
for local chunk IDs.  So "CMAP" local chunks in other FORM types may be
unrelated to "ILBM.CMA"".  More than that, each FORM type defines semantic
scope.  If you know what a FORM ILBM is, you will know what an ILBM.CMAP
is.

Local chunks defined when the FORM type is designed (and therefore known
to all clients of this type) are called "standard" while specialized ones
added later are "nonstandard".

Among the local chunks, property chunks give settings for various details
like text font while the other chunks supply the essential information.
This distinction is not clear cut.  A property setting can be cancelled by
a later setting of the same property.  E.g., in the sequence:

    prop1 = x  (Data A)  prop1 = z  prop1 = y (Data B)

prop1 is = x for Data A, and y for Data B.  The setting prop1 = z has no
effect.

For clarity, the universally reserved chunk IDs "LIST", "FORM", "PROP",
"CAT ", "    ", "LIS1" through "LIS9", "FOR1" through "FOR9", and "CAT1"
through "CAT9" may not be FORM type IDs.

Part 5, below, talks about grouping FORMs into LISTs and CAT s.  They let
you group a bunch of FORMs but don't impose any particular meaning or
constraints on the grouping.  Read on.


Data Sections / Composite FORMs

A FORM chunk inside a FORM is a full-fledged data section.  This means you
can build a composite object such as a multi-frame animation sequence by
nesting available picture FORMs and sound effect FORMs.  You can insert
additional chunks with information like frame rate and frame count.

Using composite FORMs, you leverage on existing programs that create and
edit the component FORMs.  Those editors may even look into your composite
object to copy out its type of component.  Such editors are not allowed to
replace their component objects within your composite object.  That's
because the IFF standard lets you specify consistency requirements for the
composite FORM such as maintaining a count or a directory of the
components.  Only programs that are written to uphold the rules of your
FORM type may create or modify such FORMs.

Therefore, in designing a program that creates composite objects, you are
strongly requested to provide a facility for your users to import and
export the nested FORMs.  Import and export could move the data through a
clipboard or a file.

Here are several existing FORM types and rules for defining new ones:

 FTXT      ILBM      PICs      Other Macintosh Resource Types


Composite FORMs / FTXT

An FTXT data section contains text with character formatting information
like fonts and faces.  It has no paragraph or document formatting
information like margins and page headers.  FORM FTXT is well matched to
the text representation in Amiga's Intuition environment.  See the
supplemental document "FTXT" IFF Formatted Text.


Composite FORMs / ILBM

"ILBM" is an InterLeaved BitMap image with color map; a
machine-independent format for raster images.  FORM ILBM is the standard
image file format for the Commodore-Amiga computer and is useful in other
environments, too.  See the supplemental document "ILBM" IFF Interleaved
Bitmap.


Composite FORMs / PICS

The data chunk inside a "PICS" data section has ID "PICT" and holds a
QuickDraw picture.  Issue: Allow more than one PICT in a PICS?  See Inside
Macintosh chapter "QuickDraw" for details on PICTs and how to create and
display them on the Macintosh computer.

The only standard property for PICS is "XY", an optional property that
indicates the position of the PICT relative to "the big picture".  The
contents of an XY is a QuickDraw Point.

Note: PICT may be limited to Macintosh use, in which case there"ll be
another format for structured graphics in other environments.


Composite FORMs / Other Macintosh Resource Types

Some other Macintosh resource types could be adopted for use within IFF
files; perhaps MWRT, ICN, ICN#, and STR#.

Issue: Consider the candidates and reserve some more IDs.


Data Sections / Designing New Data Sections

Supplemental documents will define additional object types.  A supplement
needs to specify the object's purpose, its FORM type ID, the IDs and
formats of standard local chunks, and rules for generating and
interpreting the data. It's a good idea to supply typedefs and an example
source program that accesses the new object.  See "ILBM" IFF Interleaved
Bitmap for such an example.

Anyone can pick a new FORM type ID but should reserve it with Commodore
Applications and Technical Support (CAT ) at their earliest convenience.
While decentralized  format definitions and extensions are possible in
IFF, our preference is to get design consensus by committee, implement a
program to read and write it, perhaps tune the format before it becomes
locked in stone, and then publish the format with example code.  Some
organization should remain in charge of answering questions and
coordinating extensions to the format.

If it becomes necessary to incompatibly revise the design of some data
section, its FORM type ID will serve as a version number (Cf. Type IDs).
E.g., a revised "VDEO" data section could be called "VDE1".  But try to
get by with compatible revisions within the existing FORM type.

In a new FORM type, the rules for primitive data types and word-alignment
(Cf. Primitive Data Types) may be overridden for the contents of its local
chunks - but not for the chunk structure itself - if your documentation
spells out the deviations.  If machine-specific type variants are needed,
e.g., to store vast numbers of integers in reverse bit order, then outline
the conversion algorithm and indicate the variant inside each file,
perhaps via different FORM types.  Needless to say, variations should be
minimized.

In designing a FORM type, encapsulate all the data that other programs
will need to interpret your files.  E.g., a raster graphics image should
specify the image size even if your program always uses 320 x 200 pixels x
3 bitplanes. Receiving programs are then empowered to append or clip the
image rectangle, to add or drop bitplanes, etc.  This enables a lot more
compatibility.

Separate the central data (like musical notes) from more specialized
information (like note beams) so simpler programs can extract the central
parts during read-in.  Leave room for expansion so other programs can
squeeze in new kinds of information (like lyrics).  And remember to keep
the property chunks manageably short - let's say <= 256 bytes.

When designing a data object, try to strike a good tradeoff between a
super- general format and a highly-specialized one.  Fit the details to at
least one particular need, for example a raster image might as well store
pixels in the current machine's scan order.  But add the kind of
generality that makes the format usable with foreseeable hardware and
software.  E.g., use a whole byte for each red, green, and blue color
value even if this year's computer has only 4-bit video DACs.  Think ahead
and help other programs so long as the overhead is acceptable.  E.g., run
compress a raster by scan line rather than as a unit so future programs
can swap images by scan line to and from secondary storage.

Try to design a general purpose "least common multiple" format that
encompasses the needs of many programs without getting too complicated.
Be sure to leave provisions for future expansion.  Let's coalesce our uses
around a few such formats widely separated in the vast design space.  Two
factors make this flexibility and simplicity practical.  First, file
storage space is getting very plentiful, so compaction is not always a
priority.  Second, nearly any locally-performed data conversion work
during file reading and writing will be cheap compared to the I/O time.

It must be OK to copy a LIST or FORM or CAT  intact, e.g., to incorporate
it into a composite FORM.  So any kind of internal references within a
FORM must be relative references.  They could be relative to the start of
the containing FORM, relative from the referencing chunk, or a sequence
number into a collection.

With composite FORMs, you leverage on existing programs that create and
edit the components.  If you write a program that creates composite
objects, please provide a facility for users to import and export the
nested FORMs.

Finally, don't forget to specify all implied rules in detail.


App.A EA IFF/ LISTs, CATs, and Shared Properties (Advanced topics)

Data often needs to be grouped together, for example, consider a list of
icons. Sometimes a trick like arranging little images into a big raster
works, but generally they'll need to be structured as a first class group.
The objects "LIST" and "CAT " are IFF-universal mechanisms for this
purpose.  Note: LIST and CAT are advanced topics the first time reader
will want to skip.

Property settings sometimes need to be shared over a list of similar
objects. E.g., a list of icons may share one color map.  LIST provides a
means called "PROP" to do this.  One purpose of a LIST is to define the
scope of a PROP. A "CAT ", on the other hand, is simply a concatenation of
objects.

Simpler programs may skip LISTs and PROPs altogether and just handle FORMs
and CAT s.  All "fully-conforming" IFF programs also know about "CAT ",
"LIST", and "PROP".  Any program that reads a FORM inside a LIST must
process shared PROPs to correctly interpret that FORM.

 Group CAT     Group LIST     Group PROP     Properties for LIST


LISTs, CATs, and Shared Properties (Advanced topics) / Group CAT

A CAT  is just an untyped group of data objects.

Structurally, a CAT  is a chunk with chunk ID "CAT " containing a "contents
type" ID followed by the nested objects.  The ckSize of each contained
chunk is essentially a relative pointer to the next one.

    CAT		::= "CAT " #{ ContentsType (FORM | LIST | CAT)* }
    ContentsType    ::= ID	- a hint or an "abstract data type" ID

In reading a CAT , like any other chunk, programs must respect its ckSize
as a virtual end-of-file for reading the nested objects even if they're
malformed or truncated.

The "contents type" following the CAT 's ckSize indicates what kind of
FORMs are inside.  So a CAT of ILBMs would store "ILBM" there.  It's just
a hint. It may be used to store an "abstract data type".  A CAT could just
have blank contents ID ("    ") if it contains more than one kind of FORM.

CAT  defines only the format of the group.  The group's meaning is open to
interpretation.  This is like a list in LISP: the structure of cells is
predefined but the meaning of the contents as, say, an association list
depends on use.  If you need a group with an enforced meaning (an
"abstract datatype" or Smalltalk "subclass"), some consistency
constraints, or additional data chunks, use a composite FORM instead (Cf.
Composite FORMs).

Since a CAT  just means a concatenation of objects, CATs are rarely nested.
Programs should really merge CATs rather than nest them.


LISTs, CATs, and Shared Properties (Advanced topics) / Group LIST

A LIST defines a group very much like CAT  but it also gives a scope for
PROPs (see below).  And unlike CATs, LISTs should not be merged without
understanding their contents.

Structurally, a LIST is a chunk with ckID "LIST" containing a "contents
type" ID, optional shared properties, and the nested contents (FORMs,
LISTs, and CAT s), in that order.  The ckSize of each contained chunk is a
relative pointer to the next one.  A LIST is not an arbitrary linked
list - the cells are simply concatenated.

    LIST         ::= "LIST" #{ ContentsType PROP* (FORM | LIST | CAT)* }
    ContentsType ::= ID


LISTs, CATs, and Shared Properties (Advanced topics) / Group PROP

PROP chunks may appear in LISTs (not in FORMs or CATs).  They supply
shared properties for the FORMs in that LIST.  This ability to elevate
some property settings to shared status for a list of forms is useful for
both indirection and compaction.  E.g., a list of images with the same
size and colors can share one "size" property and one "color map"
property.  Individual FORMs can override the shared settings.

The contents of a PROP is like a FORM with no data chunks:

    PROP	::= "PROP" #{ FormType Property* }

It means, "Here are the shared properties for FORM type <FormType>".

A LIST may have at most one PROP of a FORM type, and all the PROPs must
appear before any of the FORMs or nested LISTs and CAT s.  You can have
subsequences of FORMs sharing properties by making each subsequence a LIST.

Scoping: Think of property settings as variable bindings in nested blocks
of a programming language.  In C this would look like:

    #define Roman           0
    #define Helvetica       1

    void main()
            {
            int font=Roman; /* The global default */
                    {
                    printf("The font number is %d\n",font);
                    }
                    {
                    int font=Helvetica;     /* local setting */
                    printf("The font number is %d\n",font);
                    }
                    {
                    printf("The font number is %d\n",font);
                    }
            }

    /*
    * Sample output:       The font number is 0
    *                      The font number is 1
    *                      The font number is 0
    */

    An IFF file could contain:

    LIST {
            PROP TEXT {
                    FONT {TimesRoman}       /* shared setting       */
                    }

            FORM TEXT {
                    FONT {Helvetica}        /* local setting        */
                    CHRS {Hello }           /* uses font Helvetica  */
                    }

            FORM TEXT {
                    CHRS {there.}           /* uses font TimesRoman */
                    }
            }

The shared property assignments selectively override the reader's global
defaults, but only for FORMs within the group.  A FORM's own property
assignments selectively override the global and group-supplied values.  So
when reading an IFF file, keep property settings on a stack.  They are
designed to be small enough to hold in main memory.

Shared properties are semantically equivalent to copying those properties
into each of the nested FORMs right after their FORM type IDs.


LISTs, CATs and Shared Properties (Advanced topics) / Properties for LIST

Optional "properties for LIST" store the origin of the list's contents in
a PROP chunk for the pseudo FORM type "LIST".  They are the properties
originating program "OPGM", processor family "OCPU", computer type "OCMP",
computer serial number or network address "OSN ", and user name "UNAM". In
our imperfect world, these could be called upon to distinguish between
unintended variations of a data format or to work around bugs in
particular originating/receiving program pairs.  Issue: Specify the format
of these properties.

A creation date could also be stored in a property, but let's ask that
file creating, editing, and transporting programs maintain the correct
date in the local file system.  Programs that move files between machine
types are expected to copy across the creation dates.


App.A EA IFF/ Standard File Structure

 File Structure Overview      Rules for Reader Programs
 Single Purpose Files         Rules for Writer Programs
 Scrap Files


Standard File Structure / File Structure Overview

An IFF file is just a single chunk of type FORM, LIST, or CAT .  Therefore
an IFF file can be recognized by its first 4 bytes: "FORM", "LIST", or
"CAT ". Any file contents after the chunk's end are to be ignored.  (Some
file transfer programs add garbage to the end of transferred files.  This
specification protects against such common damage).

The simplest IFF file would be one that does no more than encapsulate some
binary data (perhaps even an old-fashioned single-purpose binary file).
Here is a binary dump of such a minimal IFF example:

    0000: 464F524D 0000001A 534E4150 43524143    FORM....SNAPCRAC
    0010: 0000000D 68656C6C 6F2C776F 726C6421    ....hello,world!
    0020: 0A00                                   ..

The first 4 bytes indicate this is a "FORM"; the most common IFF top level
structure.  The following 4 bytes indicate that the contents totals 26
bytes. The form type is listed as "SNAP".

Our form "SNAP" contains only one chunk at the moment; a chunk of type
"CRAC". From the size ($0000000D) the amount of data must be 13 bytes.  In
this case, the data happens to correspond to the ASCII string "hello,
world!<lf>". Since the number 13 is odd, a zero pad byte is added to the
file.  At any time new chunks could be added to form SNAP without
affecting any other aspect of the file (other than the form size).  It's
that simple.

Since an IFF file can be a group of objects, programs that read/write
single objects can communicate to an extent with programs that read/write
groups. You're encouraged to write programs that handle all the objects in
a LIST or CAT .  A graphics editor, for example, could process a list of
pictures as a multiple page document, one page at a time.

Programs should enforce IFF's syntactic rules when reading and writing
files. Users should be told when a file is corrupt.  This ensures robust
data transfer.  For minor damage, you may wish to give the user the option
of using the suspect data, or cancelling.  Presumably a user could read in
a damaged file, then save whatever was salvaged to a valid file.  The
public domain IFF reader/writer subroutine package does some syntatic
checks for you.  A utility program"IFFCheck" is available that scans an
IFF file and checks it for conformance to IFF's syntactic rules.  IFFCheck
also prints an outline of the chunks in the file, showing the ckID and
ckSize of each.  This is quite handy when building IFF programs.  Example
programs are also available to show details of reading and writing IFF
files.

A merge program "IFFJoin" will be available that logically appends IFF
files into a single CAT  group.  It "unwraps" each input file that is a CAT
so that the combined file isn't nested CATs.

If we need to revise the IFF standard, the three anchoring IDs will be
used as "version numbers".  That's why IDs "FOR1" through "FOR9", "LIS1"
through "LIS9", and "CAT1" through "CAT9" are reserved.

IFF formats are designed for reasonable performance with floppy disks.  We
achieve considerable simplicity in the formats and programs by relying on
the host file system rather than defining universal grouping structures
like directories for LIST contents.  On huge storage systems, IFF files
could be leaf nodes in a file structure like a B-tree.  Let's hope the
host file system implements that for us!

There are two kinds of IFF files: single purpose files and scrap files.
They differ in the interpretation of multiple data objects and in the
file's external type.


Standard File Structure / Single Purpose Files

A single purpose IFF file is for normal "document" and "archive" storage.
This is in contrast with "scrap files" (see below) and temporary backing
storage (non-interchange files).

The external file type (or filename extension, depending on the host file
system) indicates the file's contents.  It's generally the FORM type of
the data contained, hence the restrictions on FORM type IDs.

Programmers and users may pick an "intended use" type as the filename
extension to make it easy to filter for the relevant files in a filename
requester.  This is actually a "subclass" or "subtype" that conveniently
separates files of the same FORM type that have different uses.  Programs
cannot demand conformity to its expected subtypes without overly
restricting data interchange since they cannot know about the subtypes to
be used by future programs that users will want to exchange data with.

Issue: How to generate 3-letter MS-DOS extensions from 4-letter FORM type
IDs?

Most single purpose files will be a single FORM (perhaps a composite FORM
like a musical score containing nested FORMs like musical instrument
descriptions). If it's a LIST or a CAT , programs should skip over
unrecognized objects to read the recognized ones or the first recognized
one.  Then a program that can read a single purpose file can read
something out of a "scrap file", too.


Standard File Structure / Scrap Files (not currently used)

A "scrap file" is for maximum interconnectivity in getting data between
programs; the core of a clipboard function.  Scrap files may have type
"IFF " or filename extension ".IFF".

A scrap file is typically a CAT  containing alternate representations of
the same basic information.  Include as many alternatives as you can
readily generate.  This redundancy improves interconnectivity in
situations where we can't make all programs read and write super-general
formats.  [Inside Macintosh chapter "Scrap Manager".]  E.g., a
graphically-annotated musical score might be supplemented by a stripped
down 4-voice melody and by a text (the lyrics).

The originating program should write the alternate representations in
order of "preference": most preferred (most comprehensive) type to least
preferred (least comprehensive) type.  A receiving program should either
use the first appearing type that it understands or search for its own
"preferred" type.

A scrap file should have at most one alternative of any type.  (A LIST of
same type objects is OK as one of the alternatives.)  But don't count on
this when reading; ignore extra sections of a type.  Then a program that
reads scrap files can read something out of single purpose files.


Standard File Structure / Rules for Reader Programs

Here are some notes on building programs that read IFF files.  For LIST
and PROP work, you should also read up on recursive descent parsers. [See,
for example, Compiler Construction, An Advanced Course.]

  o The standard is very flexible so many programs can exchange data.
     This implies a program has to scan the file and react to what's
     actually there in whatever order it appears.  An IFF reader program
     is a parser.

  o For interchange to really work, programs must be willing to do some
     conversion during read-in.  If the data isn't exactly what you expect,
     say, the raster is smaller than those created by your program, then
     adjust it.  Similarly, your program could crop a large picture, add
     or drop bitplanes, or create/discard a mask plane.  The program
     should give up gracefully on data that it can't convert.

  o If it doesn't start with "FORM", "LIST", or "CAT ", it's not an IFF-85
     file.

  o For any chunk you encounter, you must recognize its type ID to
     understand its contents.

  o For any FORM chunk you encounter, you must recognize its FORM type ID
     to understand the contained "local chunks".  Even if you don't
     recognize the FORM type, you can still scan it for nested FORMs,
     LISTs, and CAT s of interest.

  o Don't forget to skip the implied pad byte after every odd-length chunk,
     this is not  included in the chunk count!

  o Chunk types LIST, FORM, PROP, and CAT  are generic groups.  They always
     contain a subtype ID followed by chunks.

  o Readers ought to handle a CAT  of FORMs in a file.  You may treat the
     FORMs like document pages to sequence through, or just use the first
     FORM.

  o Many  IFF readers completely skip LISTs.  "Fully IFF-conforming"
     readers are those that handle LISTs, even if just to read the first
     FORM from a file.  If you do look into a LIST, you must process
     shared properties (in PROP chunks) properly.  The idea is to get the
     correct data or none at all.

  o The nicest readers are willing to look into unrecognized FORMs for
     nested FORM types that they do recognize.  For example, a musical
     score may contain nested instrument descriptions and animation or
     desktop publishing files may contain still pictures.   This extra
     step is highly recommended.

Note to programmers: Processing PROP chunks is not simple! You'll need
some background in interpreters with stack frames.  If this is foreign to
you, build programs that read/write only one FORM per file.  For the more
intrepid programmers, the next paragraph summarizes how to process LISTs
and PROPs.

Allocate a stack frame for every LIST and FORM you encounter and
initialize it by copying the stack frame of the parent LIST or FORM.  At
the top level, you'll need a stack frame initialized to your program's
global defaults. While reading each LIST or FORM, store all encountered
properties into the current stack frame.  In the example ShowILBM, each
stack frame has a place for a bitmap header property ILBM.BMHD and a color
map property ILBM.CMAP. When you finally get to the ILBM's BODY chunk, use
the property settings accumulated in the current stack frame.

An alternate implementation would just remember PROPs encountered,
forgetting each on reaching the end of its scope (the end of the
containing LIST).  When a FORM XXXX is encountered, scan the chunks in all
remembered PROPs XXXX, in order, as if they appeared before the chunks
actually in the FORM XXXX.  This gets trickier if you read FORMs inside of
FORMs.


Standard File Structure / Rules for Writer Programs

Here are some notes on building programs that write IFF files, which is
much easier than reading them.

   o An IFF file is a single FORM, LIST, or CAT  chunk.

   o Any IFF-85 file must start with the 4 characters "FORM", "LIST", or
      "CAT ", followed by a LONG ckSize.  There should be no data after
      the chunk end.

   o Chunk types LIST, FORM, PROP, and CAT  are generic.  They always
      contain a subtype ID followed by chunks.  These three IDs are
      universally reserved, as are "LIS1" through "LIS9", "FOR1" through
      "FOR9", "CAT1" through "CAT9", and "    ".

   o Don't forget to write a 0 pad byte after each odd-length chunk.

   o Do not try to edit a file that you don't know how to create.  Programs
      may look into a file and copy out nested FORMs of types that they
      recognize, but they should not edit and replace the nested FORMs and
      not add or remove them.  Breaking these rules could make the
      containing structure inconsistent.  You may write a new file
      containing items you copied, or copied and modified, but don't copy
      structural parts you don't understand.

   o You must adhere to the syntax descriptions in Appendix A.  E.g., PROPs
      may only appear inside LISTs.

There are at least four common techniques for writing an IFF group:

  (1)  build the data in a file mapped into virtual memory.
  (2)  build the data in memory blocks and use block I/O.
  (3)  stream write the data piecemeal and (don't forget!) random
          access back to set the group (or FORM)
          length count.
  (4)  make a preliminary pass to compute the length count then stream
          write the data.

Issue: The standard disallows "blind" chunk copying for consistency
reasons. Perhaps we can define a ckID convention for chunks that are OK to
replicate without knowledge of the contents.  Any such chunks would need
to be internally consistent, and not be bothered by changed external
references.

Issue: Stream-writing an IFF FORM can be inconvenient.  With random access
files one can write all the chunks then go back to fix up the FORM size.
With stream access, the FORM size must be calculated before the file is
written. When compression is involved, this can be slow or inconvenient.
Perhaps we can define an "END " chunk.  The stream writer would use -1
($FFFFFFFF) as the FORM size.  The reader would follow each chunk, when
the reader reaches an "END ", it would terminate the last -1 sized chunk.
Certain new IFF FORMs could require that readers understand "END ".


App.A EA IFF/ Standards Committee

The following people contributed to the design of this IFF standard:

Bob "Kodiak" Burns, Commodore-Amiga
R. J. Mical, Commodore-Amiga
Jerry Morrison, Electronic Arts
Greg Riker, Electronic Arts
Steve Shaw, Electronic Arts
Barry Walsh, Commodore-Amiga
Oct, 1988 revision by Bryce Nesbitt, and Carolyn Scheppner, Commodore-Amiga


App.A EA IFF/ Appendix A. Reference

 Type Definitions      Syntax Definitions      Example Diagrams


Appendix A. Reference / Type Definitions

The following C typedefs describe standard IFF structures.  Declarations
to use in practice will vary with the CPU and compiler.  For example,
68000 Lattice C produces efficient comparison code if we define ID as a
"LONG".  A macro "MakeID" builds these IDs at compile time.

    /* Standard IFF types, expressed in 68000 Lattice C.    */

    typedef unsigned char UBYTE;    /*  8 bits unsigned     */
    typedef short WORD;             /* 16 bits signed       */
    typedef unsigned short UWORD;   /* 16 bits unsigned     */
    typedef long LONG;              /* 32 bits signed       */

    typedef char ID[4];             /* 4 chars in " " through "~" */

    typedef struct {
      ID    ckID;
      LONG  ckSize;                 /* sizeof(ckData)       */
      UBYTE ckData[/* ckSize */];
      } Chunk;

    /* ID typedef and builder for 68000 Lattice C. */
    typedef LONG ID;                /* 4 chars in " " through "~"   */

    #define MakeID(a,b,c,d) ( (a)<<24 | (b)<<16 | (c)<<8 | (d) )

    /* Globally reserved IDs. */
    #define ID_FORM   MakeID('F','O','R','M')
    #define ID_LIST   MakeID('L','I','S','T')
    #define ID_PROP   MakeID('P','R','O','P')
    #define ID_CAT    MakeID('C','A','T',' ')
    #define ID_FILLER MakeID(' ',' ',' ',' ')


Appendix A. Reference / Syntax Definitions

Here's a collection of the syntax definitions in this document.

    Chunk        ::= ID #{ UBYTE* } [0]

    Property     ::= Chunk

    FORM         ::= 'FORM' #{ FormType (LocalChunk | FORM | LIST | CAT)* }
    FormType     ::= ID
    LocalChunk   ::= Property | Chunk

    CAT          ::= 'CAT ' #{ ContentsType (FORM | LIST | CAT)* }
    ContentsType ::= ID     - a hint or an "abstract data type" ID

    LIST         ::= 'LIST' #{ ContentsType PROP* (FORM | LIST | CAT)* }
    PROP         ::= 'PROP' #{ FormType Property* }

In this extended regular expression notation, the token '#' represents a
count of the following {braced} data bytes.  Literal items are shown in
"quotes", [square bracketed items] are optional, and "*" means 0 or more
instances.  A sometimes-needed pad byte is shown as "[0]".


Appendix A. Reference / Example Diagrams

Here's a box diagram for an example IFF file, a raster image FORM ILBM.
This FORM contains a bitmap header property chunk BMHD, a color map
property chunk CMAP, and a raster data chunk BODY.  This particular raster
is 320 x 200 pixels x 3 bit planes uncompressed.  The "0" after the CMAP
chunk represents a zero pad byte; included since the CMAP chunk has an odd
length.  The text to the right of the diagram shows the outline that would
be printed by the IFFCheck utility program for this particular file.

              +----------------------------+
              |                            |
              |  "FORM"            24070   |  FORM 24070 ILBM
              |                            |
           -  +----------------------------+
           |  |                            |
           |  |    "ILBM"                  |
           |  |                            |
           |  |  +----------------------+  |
           |  |  |  "BMHD"         20   |  |  .BMHD 20
           |  |  |----------------------|  |
           |  |  |  320, 200, 0, 0, 3,  |  |
           |  |  |  0, 0, 0, ....       |  |
           |  |  +----------------------+  |
           |  |                            |
    24070 <   |  +----------------------+  |
     bytes |  |  |  "CMAP"         21   |  |  .CMAP 21
           |  |  |----------------------|  |
           |  |  |  0, 0, 0; 32, 0, 0;  |  |
           |  |  |  64, 0, 0 ...        |  |
           |  |  +----------------------+  |
           |  |     0                      |
           |  |  +----------------------+  |
           |  |  |  "BODY"      24000   |  |
           |  |  |----------------------|  |  .BODY 24000
           |  |  |  0, 0, 0....         |  |
           |  |  +----------------------+  |
           |  |                            |
           -- +----------------------------+

This second diagram shows a LIST of two FORMs ILBM sharing a common BMHD
property and a common CMAP property.  Again, the text on the right is an
outline á la IFFCheck.

            +------------------------------+
            | "LIST"              48114    |
            +------------------------------+
            |                              |
            |   "ILBM"                     |
            |                              |
            |  +------------------------+  |
            |  |  "PROP"        62      |  | .PROP 62 ILBM
            |  +------------------------+  |
            |  |                        |  |
            |  |  "ILBM"                |  |
            |  | +--------------------+ |  |
            |  | |  "BMHD"       20   | |  | ..BMHD 20
            |  | |--------------------| |  |
            |  | |  320, 200, 0, 0, 3,| |  |
            |  | |  0, 0, 0, ....     | |  |
            |  | +--------------------+ |  |
            |  |                        |  |
            |  | +--------------------+ |  |
            |  | |  "CMAP"       21   | |  | ..CMAP 21
            |  | |--------------------| |  |
            |  | |  0, 0, 0; 32, 0, 0;| |  |
            |  | |  64, 0, 0 ....     | |  |
            |  | +--------------------+ |  |
            |  |   0                    |  |
            |  +------------------------+  |
            |                              |
            |                              |
            |  +------------------------+  |
            |  |  "FORM"        24012   |  | .FORM 24012 ILBM
            |  +------------------------+  |
            |  |                        |  |
            |  |  "ILBM"                |  |
            |  | +--------------------+ |  |
            |  | |  "BODY"    24000   | |  | ..BODY 24000
            |  | |--------------------| |  |
            |  | |  0, 0, 0....       | |  |
            |  | +--------------------+ |  |
            |  +------------------------+  |
            |                              |
            |                              |
            |  +------------------------+  |
            |  |  "FORM"        24012   |  | .FORM 24012 ILBM
            |  +------------------------+  |
            |  |                        |  |
            |  |  "ILBM"                |  |
            |  | +--------------------+ |  |
            |  | |  "BODY"    24000   | |  | ..BODY 24000
            |  | |--------------------| |  |
            |  | |  0, 0, 0....       | |  |
            |  | +--------------------+ |  |
            |  +------------------------+  |
            |                              |
            |                              |
            +------------------------------+


Amiga® RKM Devices: Appendix A - IFF: Interchange File Format

 ILBM - Interleaved Bitmap
 FTXT - Formatted Text
 SMUS - Simple Musical Score
 8SVX - 8-bit Sampled Voice


A / IFF: Interchange File Format / Third Party FORM and Chunk Specs.

 IFF FORM and Chunk Registry
 Third Party Public FORM and Chunk Specifications
 Additional Documents


Appendix A - IFF: Interchange File Format / IFF Source Code

 IFF Include Files
 Source listings of examples


A / IFF Form and Chunk Registry

The following is an alphabetical list of registered FORMs, generic chunks
(shown as (any).chunkname), and registered new chunks for existing FORMs
(shown as formname.chunkname).  The center column describes where
additional information on the FORM or chunk may be found.  Items marked
"EA_IFF" are described in the main chapters of the EA IFF specs.  Those
marked "IFF_TP" are described in the third-party specications section.
Items marked "propos" are proposals which have been submitted to CATS,
some of which are private.  And items marked with "----" are private or
yet unreleased specifications.  New chunks and FORMS should be registered
with CATS US, IFF Registry, 1200 Wilson Drive, West Chester, PA. 19380.
Please make all submissions on Amiga diskette and include your address,
phone, fax.

(any).ANNO         EA_IFF  EA IFF 85 Generic Annotation chunk
(any).AUTH         EA_IFF  EA IFF 85 Generic Author chunk
(any).CHRS         EA_IFF  EA IFF 85 Generic character string chunk
(any).CSET.doc     IFF_TP  chunk for specifying character set
(any).FVER.doc     IFF_TP  chunk for 2.0 VERSION string of an IFF file
(any).HLID.doc      ----   HotLink IDentification (Contact CATS for info)
(any).NAME         EA_IFF  EA IFF 85 Generic Name of art, music, etc. chunk
(any).TEXT         EA_IFF  EA IFF 85 Generic unformatted ASCII text chunk
(any).(c)          EA_IFF  EA IFF 85 Generic Copyright text chunk
8SVX               EA_IFF  EA IFF 85 8-bit sound sample form
8SVX.CHAN.PAN.doc  IFF_TP  Stereo chunks for 8SVX form
8SVX.SEQN.FADE.doc IFF_TP  Looping chunks for 8SVX form
ACBM.doc           IFF_TP  Amiga Contiguous Bitmap form
AHAM                ----   unregistered (???)
AIFF.doc           IFF_TP  Audio 1-32 bit samples (Mac,AppleII,Synthia Pro)
ANBM.doc           IFF_TP  Animated bitmap form (Framer, Deluxe Video)
ANIM.brush.doc     IFF_TP  ANIM brush format
ANIM.doc           IFF_TP  Cel animation form
ANIM.op6.doc       IFF_TP  Stereo (3D) Animations
ARC.proposal       propos  archive format proposal (old)
ARES                ----   unregistered (???)
ATXT                ----   temporariliy reserved
AVCF                ----   AmigaVision flow (format not yet released)
AVCF.doc           IFF_TP
AVCO                ----   AmigaVision commands (format not yet released)
AVEV                ----   AmigaVision events (format not yet released)
BANK                ----   Soundquest Editor/Librarian MIDI Sysex dump
BBSD                ----   BBS Database, F.Patnaude,Jr., Phalanx Software
C100                ----   Cloanto Italia private format
CAT                EA_IFF  EA IFF 85 group identifier
CHBM                ----   Chunky bitmap (name reserved by Eric Lavitsky)
CLIP                ----   CAT CLIP to hold various formats in clipboard
CPFM                ----   Cloanto Personal FontMaker (doc in their manual)
DCCL                ----   DCCL - DCTV paint clip
DCPA                ----   DCPA - DCTV paint palette
DCTV                ----   DCTV - DCTV raw picture file
DECK                ----   private format for Inovatronics CanDo
DR2D.doc           IFF_TP  2-D Object standard format
DRAW                ----   reserved by Jim Bayless, 12/90
FANT.doc           IFF_TP  Fantavision movie format
FIGR                ----   Deluxe Video - reserved
FNTR               EA_IFF  EA IFF 85 reserved for raster font
FNTV               EA_IFF  EA IFF 85 reserved for vector font
FORM               EA_IFF  EA IFF 85 group identifier
FTXT               EA_IFF  EA IFF 85 formatted text form
GRYP.proposal      propos  byteplane storage proposal (copyrighted)
GSCR               EA_IFF  EA IFF 85 reserved gen. music score
GUI.proposal       propos  user interface storage proposal (private)
HEAD.doc           IFF_TP  Flow -  New Horizons Software
ILBM               EA_IFF  EA IFF 85 raster bitmap form
ILBM.3DCM           ----   reserved by Haitex
ILBM.3DPA           ----   reserved by Haitex
ILBM.ASDG           ----   private ASDG application chunk
ILBM.BHBA           ----   private Photon Paint chunk (brushes)
ILBM.BHCP           ----   private Photon Paint chunk (screens)
ILBM.BHSM           ----   private Photon Paint chunk
ILBM.CLUT.doc      IFF_TP  Color Lookup Table chunk
ILBM.CMYK.doc      IFF_TP  Cyan,Magenta,Yellow, & Black cmap (Contact CATS)
ILBM.CNAM.doc       ----   Color naming chunk (Soft-Logik) (Contact CATS)
ILBM.CTBL.DYCP.doc IFF_TP  Newtek Dynamic Ham color chunks
ILBM.DCTV           ----   reserved
ILBM.DGVW           ----   private Newtek DigiView chunk
ILBM.DPI.doc       IFF_TP  Dots per inch chunk
ILBM.DPPV.doc      IFF_TP  DPaint perspective chunk (EA)
ILBM.DRNG.doc      IFF_TP  DPaint IV enhanced color cycle chunk (EA)
ILBM.EPSF.doc      IFF_TP  Encapsulated Postscript chunk
ILBM.TMAP           ----   Transparency map (temporarily reserved)
ILBM.VTAG.proposal propos  Viewmode tags chunk suggestion
ILBM.XBMI.doc      IFF_TP  eXtended BitMap Information (Contact CATS)
IOBJ                ----   reserved by Seven Seas Software
ITRF                ----   reserved
LIST               EA_IFF  EA IFF 85 group identifier
MIDI                ----   Circum Design
MOVI                ----   LIST MOVI - private format
MSCX                ----   private Music-X format
MSMP                ----   temporarily reserved
MTRX.doc           IFF_TP  Numerical data storage (MathVision - Seven Seas)
NSEQ                ----   Numerical sequence (Stockhausen GmbH)
OCMP               EA_IFF  EA IFF 85 reserved computer prop
OCPU               EA_IFF  EA IFF 85 reserved processor prop
OPGM               EA_IFF  EA IFF 85 reserved program prop
OSN                EA_IFF  EA IFF 85 reserved serial num prop
PGTB.doc           IFF_TP  Program traceback (SAS Institute)
PICS               EA_IFF  EA IFF 85 reserved Macintosh picture
PLBM               EA_IFF  EA IFF 85 reserved obsolete name
PROP               EA_IFF  EA IFF 85 group identifier
PRSP.doc           IFF_TP  DPaint IV perspective move form (EA)
PTCH                ----   Patch file format (SAS Institute)
PTXT                ----   temporarily reserved
README              ----
RGB4                ----   4-bit RGB (format not available)
RGBN-RGB8.doc      IFF_TP  RGB image forms, Turbo Silver (Impulse)
RGBX                ----   temporarily reserved
ROXN                ----   private animation form
SAMP.doc           IFF_TP  Sampled sound format
SC3D                ----   private scene format (Sculpt-3D)
SHAK                ----   private Shakespeare format
SHO1                ----   Reserved by Gary Bonham (private)
SHOW                ----   Reserved by Gary Bonham (private)
SMUS               EA_IFF  EA IFF 85 simple music score form
SYTH                ----   SoundQuest Master Librarian MIDI System driver
TCDE                ----   reserved by Merging Technologies
TDDD.doc           IFF_TP  3-D rendering data, Turbo Silver (Impulse)
UNAM               EA_IFF  EA IFF 85 reserved user name prop
USCR               EA_IFF  EA IFF 85 reserved Uhuru score
UVOX               EA_IFF  EA IFF 85 reserved Uhuru Mac voice
VDEO                ----   private Deluxe Video format
WORD.doc           IFF_TP  ProWrite document format (New Horizons)


Devices/ramdev-mountlist

/*
 * Mountlist for manually mounting the sample ramdisk driver.
 *
 * F0: and F1: are set up for the V1.3 fast file system (FFS).
 * S2: and S3: are setup for the old file system (OFS).
 *
 * After mounting, the drives must be formatted.  Be sure to
 * use the FFS flag when formatting the Fast File System
 * ramdrives:
 *
 *	;make sure "ramdev.device" is in DEVS:
 *
 *	mount f0: from mydev-mountlist
 *	format drive f0: name "Zippy" FFS
 */
F0:	   Device = ramdev.device
       Unit   = 0
       LowCyl = 0 ; HighCyl = 14
       Surfaces  = 1
       Buffers = 1
       BlocksPerTrack = 10
       Flags  = 0
       Reserved = 2
       GlobVec = -1
       BufMemType = 0
       DosType = 0x444F5301
       StackSize = 4000
       FileSystem = l:fastfilesystem
#
F1:	   Device = ramdev.device
       Unit   = 1
       LowCyl = 0 ; HighCyl = 14
       Surfaces  = 1
       Buffers = 1
       BlocksPerTrack = 10
       Flags  = 0
       Reserved = 2
       GlobVec = -1
       BufMemType = 0
       DosType = 0x444F5301
       StackSize = 4000
       FileSystem = l:fastfilesystem
#
S2:	   Device = ramdev.device
       Unit   = 2
       Flags  = 0
       Surfaces  = 1
       BlocksPerTrack = 10
       Reserved = 1
       Interleave = 0
       LowCyl = 0  ;  HighCyl = 14
       Buffers = 1
       BufMemType = 0
#
S3:	   Device = ramdev.device
       Unit   = 3
       Flags  = 0
       Surfaces  = 1
       BlocksPerTrack = 10
       Reserved = 1
       Interleave = 0
       LowCyl = 0  ;  HighCyl = 14
       Buffers = 1
       BufMemType = 0
#


Devices/ramdev.i

******************************************************************
*
*
* Copyright (C) 1986-1999, Amiga, Inc.  All rights reserved.
* Permission granted for non-commercial use
*
*****************************************************************
*
* ramdev.i -- external declarations for skeleton ramdisk device
*
*****************************************************************

;--- Assemble-time options
INFO_LEVEL  EQU 0     ; Specify amount of debugging info desired
              ; If > 0 you must link with debug.lib!
              ; You will need to run a terminal program to
              ; set the baud rate.
*INTRRUPT   SET 1     ; Remove "*" to enable fake interrupt code
AUTOMOUNT   EQU 0     ; Work with the "mount" command if 0
              ; Do it automatically if 1

;--- stack size and priority for the process we will create
MYPROCSTACKSIZE   EQU	$900
MYPROCPRI	  EQU	0   ;Devices are often 5, NOT higher

;--- Base constants
NUMBEROFTRACKS EQU  40	;<<<< Change THIS to change size of ramdisk <<<<
SECTOR	       EQU  512 ;# bytes per sector
SECSHIFT       EQU  9	;Shift count to convert byte # to sector #
SECTORSPER     EQU  10	;# Sectors per "track"

RAMSIZE       EQU   SECTOR*NUMBEROFTRACKS*SECTORSPER
            ; Use this much RAM per unit
BYTESPERTRACK EQU   SECTORSPER*SECTOR

IAMPULLING    EQU   7	  ; "I am pulling the interrupt" bit of INTCRL1
INTENABLE     EQU   4	  ; "Interrupt Enable" bit of INTCRL2
INTCTRL1      EQU   $40   ; Interrupt control register offset on board
INTCTRL2      EQU   $42   ; Interrupt control register offset on board
INTACK	      EQU   $50   ; My board's interrupt reset address
;-----------------------------------------------------------------------
;
; device command definitions (copied from devices/trackdisk.i)
;
;-----------------------------------------------------------------------
   BITDEF  TD,EXTCOM,15      ; for "extended" commands !!!

   DEVINIT
   DEVCMD   CMD_MOTOR	     ; control the disk's motor (NO-OP)
   DEVCMD   CMD_SEEK	     ; explicit seek (NO-OP)
   DEVCMD   CMD_FORMAT	     ; format disk - equated to WRITE for RAMDISK
   DEVCMD   CMD_REMOVE	     ; notify when disk changes (NO-OP)
   DEVCMD   CMD_CHANGENUM    ; number of disk changes (always 0)
   DEVCMD   CMD_CHANGESTATE  ; is there a disk in the drive? (always TRUE)
   DEVCMD   CMD_PROTSTATUS   ; is the disk write protected? (always FALSE)
   DEVCMD   CMD_RAWREAD      ; Not supported
   DEVCMD   CMD_RAWWRITE     ; Not supported
   DEVCMD   CMD_GETDRIVETYPE ; Get drive type
   DEVCMD   CMD_GETNUMTRACKS ; Get number of tracks
   DEVCMD   CMD_ADDCHANGEINT ; Add disk change interrupt (NO-OP)
   DEVCMD   CMD_REMCHANGEINT ; Remove disk change interrupt ( NO-OP)
   DEVCMD   MYDEV_END	     ; place marker -- first illegal command #

DRIVE3_5	EQU	1
DRIVE5_25	EQU	2
;-----------------------------------------------------------------------
;
; Layout of parameter packet for MakeDosNode
;
;-----------------------------------------------------------------------

    STRUCTURE MkDosNodePkt,0
   APTR    mdn_dosName	 ; Pointer to DOS file handler name
   APTR    mdn_execName   ; Pointer to device driver name
   ULONG   mdn_unit   ; Unit number
   ULONG   mdn_flags   ; OpenDevice flags
   ULONG   mdn_tableSize   ; Environment size
   ULONG   mdn_sizeBlock   ; # longwords in a block
   ULONG   mdn_secOrg	; sector origin -- unused
   ULONG   mdn_numHeads   ; number of surfaces
   ULONG   mdn_secsPerBlk   ; secs per logical block -- unused
   ULONG   mdn_blkTrack   ; secs per track
   ULONG   mdn_resBlks	 ; reserved blocks -- MUST be at least 1!
   ULONG   mdn_prefac	; unused
   ULONG   mdn_interleave   ; interleave
   ULONG   mdn_lowCyl	; lower cylinder
   ULONG   mdn_upperCyl   ; upper cylinder
   ULONG   mdn_numBuffers   ; number of buffers
   ULONG   mdn_memBufType   ; Type of memory for AmigaDOS buffers
   STRUCT  mdn_dName,5	 ; DOS file handler name "RAM0"
   LABEL   mdn_Sizeof	; Size of this structure

;-----------------------------------------------------------------------
;
; device data structures
;
;-----------------------------------------------------------------------
; maximum number of units in this device
MD_NUMUNITS   EQU   4

    STRUCTURE MyDev,LIB_SIZE
   UBYTE   md_Flags
   UBYTE   md_Pad1
   ;now longword aligned
   ULONG   md_SysLib
   ULONG   md_SegList
   ULONG   md_Base	; Base address of this device's expansion board
   STRUCT  md_Units,MD_NUMUNITS*4
   LABEL   MyDev_Sizeof

   STRUCTURE MyDevUnit,UNIT_SIZE   ;Odd # longwords
   UBYTE    mdu_UnitNum
   UBYTE    mdu_SigBit	    ; Signal bit allocated for interrupts
   ;Now longword aligned!
   APTR     mdu_Device
   STRUCT   mdu_stack,MYPROCSTACKSIZE
   STRUCT   mdu_tcb,TC_SIZE	; Task Control Block (TCB) for disk task
   ULONG    mdu_SigMask 	; Signal these bits on interrupt
   IFD	 INTRRUPT
    STRUCT   mdu_is,IS_SIZE	 ; Interrupt structure
    UWORD    mdu_pad1		;Longword align
   ENDC
   STRUCT   mdu_RAM,RAMSIZE	; RAM used to simulate disk
   LABEL    MyDevUnit_Sizeof

   ;------ state bit for unit stopped
   BITDEF   MDU,STOPPED,2

MYDEVNAME   MACRO
      DC.B   'ramdev.device',0
      ENDM


Devices/asmsupp.i

*************************************************************************
*
*	Copyright (C) 1985-1999, Amiga, Inc.  All rights reserved.
*	Permission granted for non-commercial use
*
* asmsupp.i -- random low level assembly support routines
*	       used by the sample Library & Device
*
*************************************************************************
CLEAR	MACRO		;quick way to clear a D register on 68000
    MOVEQ	#0,\1
    ENDM

;BHS	 MACRO
;	 BCC.\0  \1 ;\0 is the extension used on the macro (such as ".s")
;	 ENDM
;BLO	 MACRO
;	 BCS.\0  \1
;	 ENDM
;EVEN	 MACRO		 ; word align code stream
;	 DS.W	 0
;	 ENDM

LINKSYS MACRO		; link to a library without having to see a _LVO
    MOVE.L	A6,-(SP)
    MOVE.L	\2,A6
    JSR	_LVO\1(A6)
    MOVE.L	(SP)+,A6
    ENDM

CALLSYS MACRO		; call a library via A6 without having to see _LVO
    JSR	_LVO\1(A6)
    ENDM

XLIB	MACRO		; define a library reference without the _LVO
    XREF	_LVO\1
    ENDM
;
; Put a message to the serial port at 9600 baud.  Used as so:
;
;     PUTMSG   30,<'%s/Init: called'>
;
; Parameters can be printed out by pushing them on the stack and
; adding the appropriate C printf-style % formatting commands.
;
        XREF	KPutFmt
PUTMSG: 	MACRO	* level,msg

        IFGE	INFO_LEVEL-\1

        PEA	subSysName(PC)
        MOVEM.L A0/A1/D0/D1,-(SP)
        LEA	msg\@(pc),A0    ;Point to static format string
        LEA	4*4(SP),A1      ;Point to args
        JSR	KPutFmt
        MOVEM.L (SP)+,D0/D1/A0/A1
        ADDQ.L	#4,SP
        BRA.S	end\@

msg\@		DC.B	\2
        DC.B	10
        DC.B	0
        DS.W	0
end\@
        ENDC
        ENDM


Devices/ramdev.device.asm

*************************************************************************
*
*   Copyright (C) 1986-1999 Amiga, Inc.  All rights reserved.
*   Permission granted for non-commercial use.
*
*************************************************************************
*
* ramdev.asm -- Skeleton device code.
*
* A sample 4 unit ramdisk that can be bound to an expansion slot device,
* or used without.  Works with the Fast File System.
* This code is required reading for device driver writers.  It contains
* information not found elsewhere.  This code is somewhat old; you probably
* don't want to copy it directly.
*
* This example includes a task, though a task is not actually needed for
* a simple ram disk.  Unlike a single set of hardware registers that
* may need to be shared by multiple tasks, ram can be freely shared.
* This example does not show arbitration of hardware resources.
*
* Tested with CAPE and Metacomco
*
*	   Based on mydev.asm
*	   10/07/86 Modified by Lee Erickson to be a simple disk device
*		    using RAM to simulate a disk.
*	   02/02/88 Modified by C. Scheppner, renamed ramdev
*	   09/28/88 Repaired by Bryce Nesbitt for new release
*	   11/02/88 More clarifications
*	   02/01/89 Even more clarifications & warnings
*	   02/22/89 START/STOP fix from Marco Papa
*
* Bugs: If RTF_AUTOINIT fails, library base still left in memory.
*
*************************************************************************

   SECTION firstsection

   NOLIST
   include "exec/types.i"
   include "exec/devices.i"
   include "exec/initializers.i"
   include "exec/memory.i"
   include "exec/resident.i"
   include "exec/io.i"
   include "exec/ables.i"
   include "exec/errors.i"
   include "exec/tasks.i"
   include "hardware/intbits.i"

   include "asmsupp.i"  ;standard asmsupp.i, same as used for library
   include "ramdev.i"

   IFNE AUTOMOUNT
   include "libraries/expansion.i"
   include "libraries/configvars.i"
   include "libraries/configregs.i"
   ENDC
   LIST

ABSEXECBASE equ 4   ;Absolute location of the pointer to exec.library base

   ;------ These don't have to be external, but it helps some
   ;------ debuggers to have them globally visible
   XDEF   Init
   XDEF   Open
   XDEF   Close
   XDEF   Expunge
   XDEF   Null
   XDEF   myName
   XDEF   BeginIO
   XDEF   AbortIO

   ;Pull these _LVOs in from amiga.lib
   XLIB   AddIntServer
   XLIB   RemIntServer
   XLIB   Debug
   XLIB   InitStruct
   XLIB   OpenLibrary
   XLIB   CloseLibrary
   XLIB   Alert
   XLIB   FreeMem
   XLIB   Remove
   XLIB   AddPort
   XLIB   AllocMem
   XLIB   AddTask
   XLIB   PutMsg
   XLIB   RemTask
   XLIB   ReplyMsg
   XLIB   Signal
   XLIB   GetMsg
   XLIB   Wait
   XLIB   WaitPort
   XLIB   AllocSignal
   XLIB   SetTaskPri
   XLIB   GetCurrentBinding	;Use to get list of boards for this driver
   XLIB   MakeDosNode
   XLIB   AddDosNode
   XLIB   CopyMemQuick	;Highly optimized copy function from exec.library

   INT_ABLES	    ;Macro from exec/ables.i

;-----------------------------------------------------------------------
; The first executable location.  This should return an error
; in case someone tried to run you as a program (instead of
; loading you as a device).

FirstAddress:
        moveq	#-1,d0
        rts

;-----------------------------------------------------------------------
; A romtag structure.  After your driver is brought in from disk, the
; disk image will be scanned for this structure to discover magic constants
; about you (such as where to start running you from...).
;-----------------------------------------------------------------------

   ; Most people will not need a priority and should leave it at zero.
   ; the RT_PRI field is used for configuring the roms.  Use "mods" from
   ; wack to look at the other romtags in the system
MYPRI	EQU   0

initDDescrip:
                ;STRUCTURE RT,0
     DC.W    RTC_MATCHWORD	; UWORD RT_MATCHWORD (Magic cookie)
     DC.L    initDDescrip	; APTR	RT_MATCHTAG  (Back pointer)
     DC.L    EndCode		; APTR	RT_ENDSKIP   (To end of this hunk)
     DC.B    RTF_AUTOINIT	; UBYTE RT_FLAGS     (magic-see "Init:")
     DC.B    VERSION		; UBYTE RT_VERSION
     DC.B    NT_DEVICE		; UBYTE RT_TYPE      (must be correct)
     DC.B    MYPRI		; BYTE	RT_PRI
     DC.L    myName		; APTR	RT_NAME      (exec name)
     DC.L    idString		; APTR	RT_IDSTRING  (text string)
     DC.L    Init		; APTR	RT_INIT
           ; LABEL RT_SIZE

   ;This name for debugging use
   IFNE INFO_LEVEL  ;If any debugging enabled at all
subSysName:
    dc.b    "ramdev",0
   ENDC

   ; this is the name that the device will have
myName:      MYDEVNAME

 IFNE  AUTOMOUNT
ExLibName    dc.b 'expansion.library',0   ; Expansion Library Name
 ENDC

   ; a major version number.
VERSION:    EQU   37

   ; A particular revision.  This should uniquely identify the bits in the
   ; device.  I use a script that advances the revision number each time
   ; I recompile.  That way there is never a question of which device
   ; that really is.
REVISION:   EQU   1

   ; this is an identifier tag to help in supporting the device
   ; format is 'name version.revision (d.m.yy)',<cr>,<lf>,<null>
idString:   dc.b   'ramdev 37.1 (28.8.91)',13,10,0

   ; force word alignment
   ds.w   0

   ; The romtag specified that we were "RTF_AUTOINIT".  This means
   ; that the RT_INIT structure member points to one of these
   ; tables below.  If the AUTOINIT bit was not set then RT_INIT
   ; would point to a routine to run.

Init:
   DC.L   MyDev_Sizeof	    ; data space size
   DC.L   funcTable	    ; pointer to function initializers
   DC.L   dataTable	    ; pointer to data initializers
   DC.L   initRoutine	    ; routine to run

funcTable:
   ;------ standard system routines
   dc.l   Open
   dc.l   Close
   dc.l   Expunge
   dc.l   Null	    ;Reserved for future use!

   ;------ my device definitions
   dc.l   BeginIO
   dc.l   AbortIO

   ;------ custom extended functions
   dc.l   FunctionA
   dc.l   FunctionB

   ;------ function table end marker
   dc.l   -1

   ;The data table initializes static data structures. The format is
   ;specified in exec/InitStruct routine's manual pages.  The
   ;INITBYTE/INITWORD/INITLONG macros are in the file "exec/initializers.i".
   ;The first argument is the offset from the device base for this
   ;byte/word/long. The second argument is the value to put in that cell.
   ;The table is null terminated
   ;
dataTable:
   INITBYTE   LN_TYPE,NT_DEVICE       ;Must be LN_TYPE!
   INITLONG   LN_NAME,myName
   INITBYTE   LIB_FLAGS,LIBF_SUMUSED!LIBF_CHANGED
   INITWORD   LIB_VERSION,VERSION
   INITWORD   LIB_REVISION,REVISION
   INITLONG   LIB_IDSTRING,idString
   DC.W   0   ;terminate list

;-------- initRoutine -------------------------------------------------------
;
; FOR RTF_AUTOINIT:
;   This routine gets called after the device has been allocated.
;   The device pointer is in D0.  The AmigaDOS segment list is in a0.
;   If it returns the device pointer, then the device will be linked
;   into the device list.  If it returns NULL, then the device
;   will be unloaded.
;
; IMPORTANT:
;   If you don't use the "RTF_AUTOINIT" feature, there is an additional
;   caveat.  If you allocate memory in your Open function, remember that
;   allocating memory can cause an Expunge... including an expunge of your
;   device.  This must not be fatal.  The easy solution is don't add your
;   device to the list until after it is ready for action.
;
; This call is single-threaded by exec; please read the description for
; "Open" below.
;
; Register Usage
; ==============
; a3 -- Points to temporary RAM
; a4 -- Expansion library base
; a5 -- device pointer
; a6 -- Exec base
;----------------------------------------------------------------------
initRoutine:
   ;------ get the device pointer into a convenient A register
   PUTMSG   5,<'%s/Init: called'>
   movem.l  d1-d7/a0-a5,-(sp)   ; Preserve ALL modified registers
   move.l   d0,a5

   ;------ save a pointer to exec
   move.l   a6,md_SysLib(a5)    ;faster access than move.l 4,a6

   ;------ save pointer to our loaded code (the SegList)
   move.l   a0,md_SegList(a5)

 IFNE  AUTOMOUNT
**************************************************************************
*
* Here starts the AutoConfig stuff.  If this driver was to be tied to
* an expansion board, you would put this driver in the expansion drawer,
* and be called when BindDrivers finds a board that matches this driver.
* The Amiga, Inc. assigned product number of your board must be
* specified in the "PRODUCT=" field in the TOOLTYPES of this driver's icon.
* GetCurrentBinding() returns your (first) board.
*
   lea.l     ExLibName,A1	; Get expansion lib. name
   moveq.l   #0,D0
   CALLSYS   OpenLibrary	; Open the expansion library
   tst.l     D0
   beq	     Init_Error

   ;------ init_OpSuccess:
   move.l    D0,A4	    ;[expansionbase to A4]
   moveq     #0,D3
   lea	     md_Base(A5),A0   ; Get the Current Bindings
   moveq     #4,D0	      ; Just get address (length = 4 bytes)
   LINKLIB   _LVOGetCurrentBinding,A4
   move.l    md_Base(A5),D0      ; Get start of list
   tst.l     D0 	   ; If controller not found
   beq	     Init_End	   ; Exit and unload driver

   PUTMSG    10,<'%s/Init: GetCurrentBinding returned non-zero'>
   move.l    D0,A0	   ; Get config structure address
   move.l    cd_BoardAddr(A0),md_Base(A5); Save board base address
   bclr.b    #CDB_CONFIGME,cd_Flags(A0); Mark board as configured

;----------------------------------------------------------------------
;
; Here we build a packet describing the characteristics of our disk to
; pass to AmigaDOS.  This serves the same purpose as a "mount" command
; of this device would.  For disks, it might be useful to actually
; get this information right from the disk itself.  Just as mount,
; it could be for multiple partitions on the single physical device.
; For this example, we will simply hard code the appropriate parameters.
;
; The AddDosNode call adds things to dos's list without needing to
; use mount.  We'll mount all 4 of our units whenever we are
; started.
;
;-----------------------------------------------------------------------

;!!! If your card was successfully configured, you can mount the
;!!! units as DOS nodes

   ;------   Allocate temporary RAM to build MakeDosNode parameter packet
   move.l    #MEMF_CLEAR!MEMF_PUBLIC,d1
   move.l    #mdn_Sizeof,d0   ; Enough room for our parameter packet
   CALLSYS   AllocMem
   move.l    d0,a3	    ;:BUG: AllocMem error not checked here.

   ;-----   Use InitStruct to initialize the constant portion of packet
   move.l    d0,a2	   ; Point to memory to initialize
   moveq.l   #0,d0	   ; Don't need to re-zero it
   lea.l     mdn_Init(pc),A1
   CALLSYS   InitStruct

   lea	     mdn_dName(a3),a0     ; Get addr of Device name
   move.l    a0,mdn_dosName(a3)   ;   and save in environment

   moveq     #0,d6	      ; Now tell AmigaDOS about all units UNITNUM
Uloop:
   move.b    d6,d0	     ; Get unit number
   add.b     #$30,d0	     ; Make ASCII, minus 1
   move.b    d0,mdn_dName+2(a3)   ;   and store in name
   move.l    d6,mdn_unit(a3)      ; Store unit # in environment

;
;! Before adding to the dos list, you should really check if you
;! are about to cause a name collision.  This example does not.
;

   move.l    a3,a0
   LINKLIB   _LVOMakeDosNode,a4   ; Build AmigaDOS structures
   ;This can fail, but so what?
   move.l    d0,a0		  ; Get deviceNode address
   moveq.l   #0,d0		  ; Set device priority to 0
   moveq.l   #0,d1
*  moveq.l   #ADNF_STARTPROC,d1     ; See note below
   ;It's ok to pass a zero in here
   LINKLIB   _LVOAddDosNode,a4

; ADNF_STARTPROC will work, but only if dn_SegList is filled in
; in the SegPtr of the handler task.

   addq     #1,d6	  ; Bump unit number
   cmp.b    #MD_NUMUNITS,d6
   bls.s    Uloop	  ; Loop until all units installed

   move.l   a3,a1      ; Return RAM to system
   move.l   #mdn_Sizeof,d0
   CALLSYS  FreeMem

Init_End:

   move.l   a4,a1      ; Now close expansion library
   CALLSYS  CloseLibrary
*
*   You would normally set d0 to a NULL if your initialization failed,
*   but I'm not doing that for this demo, since it is unlikely
*   you actually have a board with any particular manufacturer ID
*   installed when running this demo.
*************************************************************************
  ENDC

   move.l   a5,d0
Init_Error:
   movem.l  (sp)+,d1-d7/a0-a5
   rts

;----------------------------------------------------------------------
;
; Here begins the system interface commands.  When the user calls
; OpenDevice/CloseDevice/RemDevice, this eventually gets translated
; into a call to the following routines (Open/Close/Expunge).
; Exec has already put our device pointer in a6 for us.
;
; IMPORTANT:
;   These calls are guaranteed to be single-threaded; only one task
;   will execute your Open/Close/Expunge at a time.
;
;   For Kickstart V33/34, the single-threading method involves "Forbid".
;   There is a good chance this will change.  Anything inside your
;   Open/Close/Expunge that causes a direct or indirect Wait() will break
;   the Forbid().  If the Forbid() is broken, some other task might
;   manage to enter your Open/Close/Expunge code at the same time.
;   Take care!
;
; Since exec has turned off task switching while in these routines
; (via Forbid/Permit), we should not take too long in them.
;
;----------------------------------------------------------------------

   ; Open sets the IO_ERROR field on an error.	If it was successfull,
   ; we should also set up the IO_UNIT and LN_TYPE fields.
   ; exec takes care of setting up IO_DEVICE.

Open:	   ; ( device:a6, iob:a1, unitnum:d0, flags:d1 )

;** Subtle point: any AllocMem() call can cause a call to this device's
;** expunge vector.  If LIB_OPENCNT is zero, the device might get expunged.
   addq.w   #1,LIB_OPENCNT(a6)  ;Fake an opener for duration of call <|>

   PUTMSG   20,<'%s/Open: called'>
   movem.l  d2/a2/a3/a4,-(sp)

   move.l   a1,a2      ; save the iob

   ;------ see if the unit number is in range	*!* UNIT 0 to 3 *!*
   cmp.l   #MD_NUMUNITS,d0
   bcc.s   Open_Range_Error   ; unit number out of range (BHS)

   ;------ see if the unit is already initialized
   move.l   d0,d2      ; save unit number
   lsl.l    #2,d0
   lea.l    md_Units(a6,d0.l),a4
   move.l   (a4),d0
   bne.s    Open_UnitOK

   ;------ try and conjure up a unit
   bsr	    InitUnit	;scratch:a3 unitnum:d2 devpoint:a6

   ;------ see if it initialized OK
   move.l   (a4),d0
   beq.s    Open_Error

Open_UnitOK:
   move.l   d0,a3      ; unit pointer in a3
   move.l   d0,IO_UNIT(a2)

   ;------ mark us as having another opener
   addq.w   #1,LIB_OPENCNT(a6)
   addq.w   #1,UNIT_OPENCNT(a3)     ;Internal bookkeeping

   ;------ prevent delayed expunges
   bclr     #LIBB_DELEXP,md_Flags(a6)

   CLEAR    d0
   move.b   d0,IO_ERROR(a2)
   move.b   #NT_REPLYMSG,LN_TYPE(a2) ;IMPORTANT: Mark IORequest as "complete"

Open_End:

   subq.w   #1,LIB_OPENCNT(a6) ;** End of expunge protection <|>
   movem.l  (sp)+,d2/a2/a3/a4
   rts

Open_Range_Error:
Open_Error:
   moveq    #IOERR_OPENFAIL,d0
   move.b   d0,IO_ERROR(a2)
   move.l   d0,IO_DEVICE(a2)    ;IMPORTANT: trash IO_DEVICE on open failure
   PUTMSG   2,<'%s/Open: failed'>
   bra.s    Open_End

;----------------------------------------------------------------------------
; There are two different things that might be returned from the Close
; routine.  If the device wishes to be unloaded, then Close must return
; the segment list (as given to Init).  Otherwise close MUST return NULL.

Close:	    ; ( device:a6, iob:a1 )
   movem.l  d1/a2-a3,-(sp)
   PUTMSG   20,<'%s/Close: called'>

   move.l   a1,a2

   move.l   IO_UNIT(a2),a3

   ;------ IMPORTANT: make sure the IORequest is not used again
   ;------ with a -1 in IO_DEVICE, any BeginIO() attempt will
   ;------ immediatly halt (which is better than a subtle corruption
   ;------ that will lead to hard-to-trace crashes!!!!!!!!!!!!!!!!!!
   moveq.l  #-1,d0
   move.l   d0,IO_UNIT(a2)      ;We're closed...
   move.l   d0,IO_DEVICE(a2)    ;customers not welcome at this IORequest!!

   ;------ see if the unit is still in use
   subq.w   #1,UNIT_OPENCNT(a3)

;!!!!!! Since this example is a RAM disk (and we don't want the contents to
;!!!!!! disappear between opens, ExpungeUnit will be skipped here.  It would
;!!!!!! be used for drivers of "real" devices
;!!!!!!   bne.s   Close_Device
;!!!!!!   bsr	  ExpungeUnit

Close_Device:
   CLEAR   d0
   ;------ mark us as having one fewer openers
   subq.w  #1,LIB_OPENCNT(a6)

   ;------ see if there is anyone left with us open
   bne.s   Close_End

   ;------ see if we have a delayed expunge pending
   btst    #LIBB_DELEXP,md_Flags(a6)
   beq.s   Close_End

   ;------ do the expunge
   bsr	   Expunge

Close_End:
   movem.l   (sp)+,d1/a2-a3
   rts				;MUST return either zero or the SegList!!!

;------- Expunge -----------------------------------------------------------
;
; Expunge is called by the memory allocator when the system is low on
; memory.
;
; There are two different things that might be returned from the Expunge
; routine.  If the device is no longer open then Expunge may return the
; segment list (as given to Init).  Otherwise Expunge may set the
; delayed expunge flag and return NULL.
;
; One other important note: because Expunge is called from the memory
; allocator, it may NEVER Wait() or otherwise take long time to complete.
;
;	A6	    - library base (scratch)
;	D0-D1/A0-A1 - scratch
;
Expunge:   ; ( device: a6 )
   PUTMSG   10,<'%s/Expunge: called'>

   movem.l  d1/d2/a5/a6,-(sp)   ; Save ALL modified registers
   move.l   a6,a5
   move.l   md_SysLib(a5),a6

   ;------ see if anyone has us open
   tst.w   LIB_OPENCNT(a5)
;!!!!!	The following line is commented out for this RAM disk demo, since
;!!!!!	we don't want the RAM to be freed after FORMAT, for example.
;   beq    1$

   ;------ it is still open.  set the delayed expunge flag
   bset    #LIBB_DELEXP,md_Flags(a5)
   CLEAR   d0
   bra.s   Expunge_End

1$:
   ;------ go ahead and get rid of us.	Store our seglist in d2
   move.l   md_SegList(a5),d2

   ;------ unlink from device list
   move.l    a5,a1
   CALLSYS   Remove		;Remove first (before FreeMem)

   ;
   ; device specific closings here...
   ;

   ;------ free our memory (must calculate from LIB_POSSIZE & LIB_NEGSIZE)
   move.l   a5,a1		;Devicebase
   CLEAR    d0
   move.w   LIB_NEGSIZE(a5),d0
   suba.l   d0,a1		;Calculate base of functions
   add.w    LIB_POSSIZE(a5),d0  ;Calculate size of functions + data area
   CALLSYS  FreeMem

   ;------ set up our return value
   move.l   d2,d0

Expunge_End:
   movem.l  (sp)+,d1/d2/a5/a6
   rts

;------- Null ---------------------------------------------------------------
Null:
   PUTMSG  1,<'%s/Null: called'>
   CLEAR   d0
   rts	    ;The "Null" function MUST return NULL.

;------- Custom ------------------------------------------------------------
;
;Two "do nothing" device-specific functions
;
FunctionA:
    add.l   d1,d0   ;Add
    rts
FunctionB:
    add.l   d0,d0   ;Double
    rts

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

InitUnit:   ; ( d2:unit number, a3:scratch, a6:devptr )
   PUTMSG   30,<'%s/InitUnit: called'>
   movem.l  d2-d4/a2,-(sp)

   ;------ allocate unit memory
   move.l   #MyDevUnit_Sizeof,d0
   move.l   #MEMF_PUBLIC!MEMF_CLEAR,d1
   LINKSYS  AllocMem,md_SysLib(a6)
   tst.l    d0
   beq	    InitUnit_End
   move.l   d0,a3

   moveq.l  #0,d0	   ; Don't need to re-zero it
   move.l   a3,a2	   ; InitStruct is initializing the UNIT
   lea.l    mdu_Init(pc),A1
   LINKSYS  InitStruct,md_SysLib(a6)

   ;!! IMPORTANT !!
   move.l   #42414400,mdu_RAM(a3)   ;Mark offset zero as ASCII "BAD "
   ;!! IMPORTANT !!

   move.b   d2,mdu_UnitNum(a3)      ;initialize unit number
   move.l   a6,mdu_Device(a3)       ;initialize device pointer

   ;------ start up the unit task.  We do a trick here --
   ;------ we set his message port to PA_IGNORE until the
   ;------ new task has a change to set it up.
   ;------ We cannot go to sleep here: it would be very nasty
   ;------ if someone else tried to open the unit
   ;------ (exec's OpenDevice has done a Forbid() for us --
   ;------ we depend on this to become single threaded).

   ;------ Initialize the stack information
   lea	    mdu_stack(a3),a0          ; Low end of stack
   move.l   a0,mdu_tcb+TC_SPLOWER(a3)
   lea	    MYPROCSTACKSIZE(a0),a0    ; High end of stack
   move.l   a0,mdu_tcb+TC_SPUPPER(a3)
   move.l   a3,-(A0)                  ; argument -- unit ptr (send on stack)
   move.l   a0,mdu_tcb+TC_SPREG(a3)
   lea	    mdu_tcb(a3),a0
   move.l   a0,MP_SIGTASK(a3)

   IFGE INFO_LEVEL-30
       move.l	a0,-(SP)
       move.l	a3,-(SP)
       PUTMSG	30,<'%s/InitUnit, unit= %lx, task=%lx'>
       addq.l	#8,sp
   ENDC

   ;------ initialize the unit's message port's list
   lea	    MP_MSGLIST(a3),a0
   NEWLIST  a0			;<- IMPORTANT! Lists MUST! have NEWLIST
                ;work magic on them before use.  (AddPort()
                ;can do this for you)

   IFD	 INTRRUPT
   move.l   a3,mdu_is+IS_DATA(a3)   ; Pass unit addr to interrupt server
   ENDC

;   Startup the task
   lea	    mdu_tcb(a3),a1
   lea	    Task_Begin(PC),a2
   move.l   a3,-(sp)      ; Preserve UNIT pointer
   lea	    -1,a3	  ; generate address error
              ; if task ever "returns" (we RemTask() it
              ; to get rid of it...)
   CLEAR   d0
   PUTMSG   30,<'%s/About to add task'>
   LINKSYS AddTask,md_SysLib(a6)
   move.l   (sp)+,a3      ; restore UNIT pointer

   ;------ mark us as ready to go
   move.l   d2,d0	  ; unit number
   lsl.l    #2,d0
   move.l   a3,md_Units(a6,d0.l)   ; set unit table
   PUTMSG   30,<'%s/InitUnit: ok'>

InitUnit_End:
   movem.l   (sp)+,d2-d4/a2
   rts

;---------------------------------------------------------------------------
FreeUnit:   ; ( a3:unitptr, a6:deviceptr )
   move.l   a3,a1
   move.l   #MyDevUnit_Sizeof,d0
   LINKSYS  FreeMem,md_SysLib(a6)
   rts

;---------------------------------------------------------------------------
ExpungeUnit:   ; ( a3:unitptr, a6:deviceptr )
   PUTMSG   10,<'%s/ExpungeUnit: called'>
   move.l   d2,-(sp)

;
; If you can expunge you unit, and each unit has it's own interrupts,
; you must remember to remove its interrupt server
;

   IFD	 INTRRUPT
   lea.l   mdu_is(a3),a1              ; Point to interrupt structure
   moveq   #INTB_PORTS,d0	      ; Portia interrupt bit 3
   LINKSYS RemIntServer,md_SysLib(a6) ;Now remove the interrupt server
   ENDC

   ;------ get rid of the unit's task.  We know this is safe
   ;------ because the unit has an open count of zero, so it
   ;------ is 'guaranteed' not in use.
   lea	 mdu_tcb(a3),a1
   LINKSYS RemTask,md_SysLib(a6)

   ;------ save the unit number
   CLEAR   d2
   move.b  mdu_UnitNum(a3),d2

   ;------ free the unit structure.
   bsr	   FreeUnit

   ;------ clear out the unit vector in the device
   lsl.l   #2,d2
   clr.l   md_Units(a6,d2.l)

   move.l  (sp)+,d2
   rts

*****************************************************************************
;
; here begins the device functions
;
;----------------------------------------------------------------------------
; cmdtable is used to look up the address of a routine that will
; implement the device command.
;
; NOTE: the "extended" commands (ETD_READ/ETD_WRITE) have bit 15 set!
; We deliberately refuse to operate on such commands.  However a driver
; that supports removable media may want to implement this.  One
; open issue is the handling of the "seclabel" area. It is probably
; best to reject any command with a non-null "seclabel" pointer.
;
cmdtable:
   DC.L   Invalid	;$00000001  ;0	CMD_INVALID
   DC.L   MyReset	;$00000002  ;1	CMD_RESET
   DC.L   RdWrt 	;$00000004  ;2	CMD_READ	(\/common)
   DC.L   RdWrt 	;$00000008  ;3	CMD_WRITE	(/\common)  ETD_
   DC.L   Update	;$00000010  ;4	CMD_UPDATE	(NO-OP)     ETD_
   DC.L   Clear 	;$00000020  ;5	CMD_CLEAR	(NO-OP)     ETD_
   DC.L   MyStop	;$00000040  ;6	CMD_STOP		    ETD_
   DC.L   Start 	;$00000080  ;7	CMD_START
   DC.L   Flush 	;$00000100  ;8	CMD_FLUSH
   DC.L   Motor 	;$00000200  ;9	TD_MOTOR	(NO-OP)     ETD_
   DC.L   Seek		;$00000400  ;A	TD_SEEK 	(NO-OP)     ETD_
   DC.L   RdWrt 	;$00000800  ;B	TD_FORMAT	(Same as write)
   DC.L   MyRemove	;$00001000  ;C	TD_REMOVE	(NO-OP)
   DC.L   ChangeNum	;$00002000  ;D	TD_CHANGENUM	(returns 0)
   DC.L   ChangeState	;$00004000  ;E	TD_CHANGESTATE	(returns 0)
   DC.L   ProtStatus	;$00008000  ;F	TD_PROTSTATUS	(returns 0)
   DC.L   RawRead	;$00010000  ;10 TD_RAWREAD	(INVALID)
   DC.L   RawWrite	;$00020000  ;11 TD_RAWWRITE	(INVALID)
   DC.L   GetDriveType	;$00040000  ;12 TD_GETDRIVETYPE (Returns 1)
   DC.L   GetNumTracks	;$00080000  ;13 TD_GETNUMTRACKS (Returns NUMTRKS)
   DC.L   AddChangeInt	;$00100000  ;14 TD_ADDCHANGEINT (NO-OP)
   DC.L   RemChangeInt	;$00200000  ;15 TD_REMCHANGEINT (NO-OP)
cmdtable_end:

; this define is used to tell which commands should be handled
; immediately (on the caller's schedule).
;
; The immediate commands are Invalid, Reset, Stop, Start, Flush
;
; Note that this method limits you to just 32 device specific commands,
; which may not be enough.
;IMMEDIATES   EQU   %00000000000000000000000111000011
;;		     --------========--------========
;;		     FEDCBA9876543210FEDCBA9876543210

;;An alternate version.  All commands that are trivially short
;;and %100 reentrant are included.  This way you won't get the
;;task switch overhead for these commands.
;;
IMMEDIATES   EQU   %11111111111111111111011111110011
;		    --------========--------========
;		    FEDCBA9876543210FEDCBA9876543210

    IFD   INTRRUPT   ; if using interrupts,
; These commands can NEVER be done "immediately" if using interrupts,
; since they would "wait" for the interrupt forever!
; Read, Write, Format
NEVERIMMED   EQU   $0000080C
    ENDC

;--------------------------------
; BeginIO starts all incoming io.  The IO is either queued up for the
; unit task or processed immediately.
;
;
; BeginIO often is given the responsibility of making devices single
; threaded... so two tasks sending commands at the same time don't cause
; a problem.  Once this has been done, the command is dispatched via
; PerformIO.
;
; There are many ways to do the threading.  This example uses the
; UNITB_ACTIVE bit.  Be sure this is good enough for your device before
; using!  Any method is ok.  If immediate access can not be obtained, the
; request is queued for later processing.
;
; Some IO requests do not need single threading, these can be performed
; immediatley.
;
; IMPORTANT:
;   The exec WaitIO() function uses the IORequest node type (LN_TYPE)
;   as a flag.	If set to NT_MESSAGE, it assumes the request is
;   still pending and will wait.  If set to NT_REPLYMSG, it assumes the
;   request is finished.  It's the responsibility of the device driver
;   to set the node type to NT_MESSAGE before returning to the user.
;
BeginIO:   ; ( iob: a1, device:a6 )

    IFGE INFO_LEVEL-1
    bchg.b	#1,$bfe001  ;Blink the power LED
    ENDC
    IFGE INFO_LEVEL-3
     clr.l    -(sp)
     move.w   IO_COMMAND(a1),2(sp)  ;Get entire word
     PUTMSG   3,<'%s/BeginIO  -- $%lx'>
     addq.l   #4,sp
    ENDC

    movem.l   d1/a0/a3,-(sp)

    move.b  #NT_MESSAGE,LN_TYPE(a1) ;So WaitIO() is guaranteed to work
    move.l  IO_UNIT(a1),a3          ;bookkeeping -> what unit to play with
    move.w  IO_COMMAND(a1),d0

    ;Do a range check & make sure ETD_XXX type requests are rejected
    cmp.w   #MYDEV_END,d0	;Compare all 16 bits
    bcc     BeginIO_NoCmd	;no, reject it.  (bcc=bhs - unsigned)

    ;------ process all immediate commands no matter what
    move.l  #IMMEDIATES,d1
    DISABLE a0			;<-- Ick, nasty stuff, but needed here.
    btst.l  d0,d1
    bne     BeginIO_Immediate

    IFD   INTRRUPT   ; if using interrupts,
     ;------ queue all NEVERIMMED commands no matter what
     move.w  #NEVERIMMED,d1
     btst    d0,d1
     bne.s   BeginIO_QueueMsg
    ENDC

    ;------ see if the unit is STOPPED.  If so, queue the msg.
    btst    #MDUB_STOPPED,UNIT_FLAGS(a3)
    bne     BeginIO_QueueMsg

    ;------ This is not an immediate command.  See if the device is
    ;------ busy.  If the device is not, do the command on the
    ;------ user schedule.  Else fire up the task.
    ;------ This type of arbitration is not really needed for a ram
    ;------ disk, but is essential for a device to reliably work
    ;------ with shared hardware
    ;------
    ;------ When the lines below are ";" commented out, the task gets
    ;------ a better workout.  When the lines are active, the calling
    ;------ process is usually used for the operation.
    ;------
    ;------ REMEMBER:::: Never Wait() on the user's schedule in BeginIO()!
    ;------ The only exception is when the user has indicated it is ok
    ;------ by setting the "quick" bit.  Since this device copies from
    ;------ ram that never needs to be waited for, this subtlely may not
    ;------ be clear.
    ;------
    bset    #UNITB_ACTIVE,UNIT_FLAGS(a3)   ;<---- comment out these
    beq.s   BeginIO_Immediate		   ;<---- lines to test task.

    ;------ we need to queue the device.  mark us as needing
    ;------ task attention.  Clear the quick flag
BeginIO_QueueMsg:
    bset    #UNITB_INTASK,UNIT_FLAGS(a3)
    bclr    #IOB_QUICK,IO_FLAGS(a1)   ;We did NOT complete this quickly
    ENABLE  a0

    IFGE INFO_LEVEL-250
     move.l  a1,-(sp)
     move.l  a3,-(sp)
     PUTMSG  250,<'%s/PutMsg: Port=%lx Message=%lx'>
     addq.l  #8,sp
    ENDC

    move.l  a3,a0
    LINKSYS  PutMsg,md_SysLib(a6)   ;Port=a0, Message=a1
    bra.s   BeginIO_End
    ;----- return to caller before completing

    ;------ Do it on the schedule of the calling process
    ;------
BeginIO_Immediate:
    ENABLE  a0
    bsr.s   PerformIO

BeginIO_End:
    PUTMSG  200,<'%s/BeginIO_End'>
    movem.l (sp)+,d1/a0/a3
    rts

BeginIO_NoCmd:
    move.b  #IOERR_NOCMD,IO_ERROR(a1)
    bra.s   BeginIO_End

;
; PerformIO actually dispatches an io request.	It might be called from
; the task, or directly from BeginIO (thus on the callers's schedule)
;
; It expects a3 to already
; have the unit pointer in it.	a6 has the device pointer (as always).
; a1 has the io request.  Bounds checking has already been done on
; the I/O Request.
;

PerformIO:   ; ( iob:a1, unitptr:a3, devptr:a6 )
    IFGE INFO_LEVEL-150
     clr.l    -(sp)
     move.w   IO_COMMAND(a1),2(sp)  ;Get entire word
     PUTMSG   150,<'%s/PerformIO -- $%lx'>
     addq.l   #4,sp
    ENDC

    moveq   #0,d0
    move.b  d0,IO_ERROR(A1)     ; No error so far
    move.b  IO_COMMAND+1(a1),d0 ;Look only at low byte
    lsl.w   #2,d0		; Multiply by 4 to get table offset
    lea.l   cmdtable(pc),a0
    move.l  0(a0,d0.w),a0

    jmp     (a0)    ;iob:a1  unit:a3  devprt:a6

;
; TermIO sends the IO request back to the user.  It knows not to mark
; the device as inactive if this was an immediate request or if the
; request was started from the server task.
;

TermIO:      ; ( iob:a1, unitptr:a3, devptr:a6 )
    PUTMSG  160,<'%s/TermIO'>
    move.w  IO_COMMAND(a1),d0

    move.w  #IMMEDIATES,d1
    btst    d0,d1
    bne.s   TermIO_Immediate	;IO was immediate, don't do task stuff...

    ;------ we may need to turn the active bit off.
    btst    #UNITB_INTASK,UNIT_FLAGS(a3)
    bne.s   TermIO_Immediate	;IO was came from task, don't clear ACTIVE...

    ;------ the task does not have more work to do
    bclr    #UNITB_ACTIVE,UNIT_FLAGS(a3)

TermIO_Immediate:
    ;------ if the quick bit is still set then we don't need to reply
    ;------ msg -- just return to the user.
    btst    #IOB_QUICK,IO_FLAGS(a1)
    bne.s   TermIO_End
    LINKSYS ReplyMsg,md_SysLib(a6)      ;a1-message
    ;(ReplyMsg sets the LN_TYPE to NT_REPLYMSG)

TermIO_End:
    rts

*****************************************************************************
;
; Here begins the functions that implement the device commands
; all functions are called with:
;   a1 -- a pointer to the io request block
;   a3 -- a pointer to the unit
;   a6 -- a pointer to the device
;
; Commands that conflict with 68000 instructions have a "My" prepended
; to them.
;----------------------------------------------------------------------

;We can't AbortIO anything, so don't touch the IORequest!
;
;AbortIO() is a REQUEST to "hurry up" processing of an IORequest.
;If the IORequest was already complete, nothing happens (if an IORequest
;is quick or LN_TYPE=NT_REPLYMSG, the IORequest is complete).
;The message must be replied with ReplyMsg(), as normal.
;
AbortIO:	; ( iob: a1, device:a6 )
    moveq   #IOERR_NOCMD,d0 ;return "AbortIO() request failed"
    rts

RawRead:	; 10 Not supported   (INVALID)
RawWrite:	; 11 Not supported   (INVALID)
Invalid:
    move.b  #IOERR_NOCMD,IO_ERROR(a1)
    bra.s   TermIO

;
; Update and Clear are internal buffering commands.  Update forces all
; io out to its final resting spot, and does not return until this is
; totally done.  Since this is automatic in a ramdisk, we simply return "Ok".
;
; Clear invalidates all internal buffers.  Since this device
; has no internal buffers, these commands do not apply.
;
Update:
Clear:
MyReset:		    ;Do nothing (nothing reasonable to do)
AddChangeInt:		    ;Do nothing
RemChangeInt:		    ;Do nothing
MyRemove:		    ;Do nothing
Seek:			    ;Do nothing
Motor:			    ;Do nothing
ChangeNum:		    ;Return zero (changecount =0)
ChangeState:		    ;Zero indicates disk inserted
ProtStatus:		    ;Zero indicates unprotected
    clr.l   IO_ACTUAL(a1)
    bra.s   TermIO

GetDriveType:		    ;make it look like 3.5" (90mm) drive
    moveq   #DRIVE3_5,d0
    move.l  d0,IO_ACTUAL(a1)
    bra.s   TermIO

GetNumTracks:
    move.l  #RAMSIZE/BYTESPERTRACK,IO_ACTUAL(a1) ;Number of tracks
    bra.s   TermIO

;
; Foo and Bar are two device specific commands that are provided just
; to show you how commands are added.  They currently return that
; no work was done.
;
Foo:
Bar:
    clr.l   IO_ACTUAL(a1)
    bra     TermIO

;---------------------------------------------------------------------------
; This device is designed so that no combination of bad
; inputs can ever cause the device driver to crash.
;---------------------------------------------------------------------------
RdWrt:
    IFGE INFO_LEVEL-200
    move.l	IO_DATA(a1),-(sp)
    move.l	IO_OFFSET(a1),-(sp)
    move.l	IO_LENGTH(a1),-(sp)
    PUTMSG	200,<'%s/RdWrt len %ld offset %ld data $%lx'>
    addq.l	#8,sp
    addq.l	#4,sp
    ENDC

    movem.l a2/a3,-(sp)
    move.l  a1,a2		;Copy iob
    move.l  IO_UNIT(a2),a3      ;Get unit pointer

*      check operation for legality
    btst.b  #0,IO_DATA+3(a2)    ;check if user's pointer is ODD
    bne.s   IO_LenErr		;bad...
    ;[D0=offset]

    move.l  IO_OFFSET(a2),d0
    move.l  d0,d1
    and.l   #SECTOR-1,d1	;Bad sector boundary or alignment?
    bne.s   IO_LenErr		;bad...
    ;[D0=offset]

*      check for IO within disc range
    ;[D0=offset]
    add.l   IO_LENGTH(a2),d0    ;Add length to offset
    bcs.s   IO_LenErr		;overflow... (important test)
    cmp.l   #RAMSIZE,d0 	;Last byte is highest acceptable total
    bhi.s   IO_LenErr		;bad... (unsigned compare)
    and.l   #SECTOR-1,d0	;Even sector boundary?
    bne.s   IO_LenErr		;bad...

*      We've gotten this far, it must be a valid request.

    IFD   INTRRUPT
     move.l   mdu_SigMask(a3),d0  ; Get signals to wait for
     LINKSYS  Wait,md_SysLib(a6)  ; Wait for interrupt before proceeding
    ENDC

    lea.l   mdu_RAM(a3),a0      ; Point to RAMDISK "sector" for I/O
    add.l   IO_OFFSET(a2),a0    ; Add offset to ram base
    move.l  IO_LENGTH(a2),d0
    move.l  d0,IO_ACTUAL(a2)    ; Indicate we've moved all bytes
    beq.s   RdWrt_end		;---deal with zero length I/O
    move.l  IO_DATA(a2),a1      ; Point to data buffer
;
;A0=ramdisk index
;A1=user buffer
;D0=length
;
    cmp.b   #CMD_READ,IO_COMMAND+1(a2)  ; Decide on direction
    BEQ.S   CopyTheBlock
    EXG     A0,A1		; For Write and Format, swap source & dest
CopyTheBlock:
    LINKSYS CopyMemQuick,md_SysLib(a6)  ;A0=source A1=dest D0=size
    ;CopyMemQuick is very fast

RdWrt_end:
    move.l  a2,a1
    movem.l (sp)+,a2/a3
    bra     TermIO	;END

IO_LenErr:
    PUTMSG  10,<'bad length'>
    move.b  #IOERR_BADLENGTH,IO_ERROR(a2)
IO_End:
    clr.l   IO_ACTUAL(a2)       ;Initially, no data moved
    bra.s   RdWrt_end

;
; the Stop command stop all future io requests from being
; processed until a Start command is received.	The Stop
; command is NOT stackable: e.g. no matter how many stops
; have been issued, it only takes one Start to restart
; processing.
;
;Stop is rather silly for a ramdisk
MyStop:
   PUTMSG   30,<'%s/MyStop: called'>
   bset   #MDUB_STOPPED,UNIT_FLAGS(a3)
   bra	 TermIO

Start:
    PUTMSG   30,<'%s/Start: called'>
    bsr.s  InternalStart
    bra   TermIO

       ;[A3=unit A6=device]
InternalStart:
    move.l  a1,-(sp)
    ;------ turn processing back on
    bclr   #MDUB_STOPPED,UNIT_FLAGS(a3)
    ;------ kick the task to start it moving
    move.b  MP_SIGBIT(a3),d1
    CLEAR   d0
    bset    d1,d0		    ;prepared signal mask
    move.l  MP_SIGTASK(a3),a1       ;:FIXED:marco-task to signal
    LINKSYS Signal,md_SysLib(a6)    ;:FIXED:marco-a6 not a3
    move.l  (sp)+,a1
    rts

;
; Flush pulls all I/O requests off the queue and sends them back.
; We must be careful not to destroy work in progress, and also
; that we do not let some io requests slip by.
;
; Some funny magic goes on with the STOPPED bit in here.  Stop is
; defined as not being reentrant.  We therefore save the old state
; of the bit and then restore it later.  This keeps us from
; needing to DISABLE in flush.	It also fails miserably if someone
; does a start in the middle of a flush. (A semaphore might help...)
;

Flush:
   PUTMSG   30,<'%s/Flush: called'>
   movem.l   d2/a1/a6,-(sp)

   move.l   md_SysLib(a6),a6

   bset   #MDUB_STOPPED,UNIT_FLAGS(a3)
   sne	 d2

Flush_Loop:
   move.l   a3,a0
   CALLSYS   GetMsg	;Steal messages from task's port

   tst.l   d0
   beq.s   Flush_End

   move.l   d0,a1
   move.b   #IOERR_ABORTED,IO_ERROR(a1)
   CALLSYS   ReplyMsg

   bra.s   Flush_Loop

Flush_End:
   move.l   d2,d0
   movem.l   (sp)+,d2/a1/a6

   tst.b   d0
   beq.s   1$

   bsr	 InternalStart
1$:
   bra	   TermIO

*****************************************************************************
;
; Here begins the task related routines
;
; A Task is provided so that queued requests may be processed at
; a later time.  This is not very justifiable for a ram disk, but
; is very useful for "real" hardware devices.  Take care with
; your arbitration of shared hardware with all the multitasking
; programs that might call you at once.
;
; Register Usage
; ==============
; a3 -- unit pointer
; a6 -- syslib pointer
; a5 -- device pointer
; a4 -- task (NOT process) pointer
; d7 -- wait mask
;----------------------------------------------------------------------

; some dos magic, useful for Processes (not us).  A process is started at
; the first  executable address  after a segment list.	We hand craft a
; segment list here.  See the the DOS technical reference if you really
; need to know more about this.
; The next instruction after the segment list is the first executable address

    cnop    0,4     ; long word align
    DC.L    16	    ; segment length -- any number will do (this is 4
            ; bytes back from the segment pointer)
myproc_seglist:
    DC.L    0	    ; pointer to next segment

Task_Begin:
    PUTMSG  35,<'%s/Task_Begin'>
    move.l  ABSEXECBASE,a6

    ;------ Grab the argument passed down from our parent
    move.l  4(sp),a3           ; Unit pointer
    move.l  mdu_Device(a3),a5  ; Point to device structure

    IFD   INTRRUPT
     ;------ Allocate a signal for "I/O Complete" interrupts
     moveq   #-1,d0	    ; -1 is any signal at all
     CALLSYS   AllocSignal
     move.b   d0,mdu_SigBit(A3)   ; Save in unit structure
     moveq   #0,d7	   ; Convert bit number signal mask
     bset   d0,d7
     move.l   d7,mdu_SigMask(A3)   ; Save in unit structure
     lea.l   mdu_is(a3),a1      ; Point to interrupt structure
     moveq   #INTB_PORTS,d0	; Portia interrupt bit 3
     CALLSYS AddIntServer	; Now install the server
     move.l   md_Base(a5),a0      ; Get board base address
*    bset.b   #INTENABLE,INTCTRL2(a0)   ; Enable interrupts
    ENDC

    ;------ Allocate a signal
    moveq   #-1,d0	    ; -1 is any signal at all
    CALLSYS AllocSignal
    move.b  d0,MP_SIGBIT(a3)
    move.b  #PA_SIGNAL,MP_FLAGS(a3) ;Make message port "live"
    ;------ change the bit number into a mask, and save in d7
    moveq   #0,d7	;Clear D7
    bset    d0,d7

    IFGE INFO_LEVEL-40
     move.l  $114(a6),-(sp)
     move.l  a5,-(sp)
     move.l  a3,-(sp)
     move.l  d0,-(sp)
     PUTMSG  40,<'%s/Signal=%ld, Unit=%lx Device=%lx Task=%lx'>
     add.l   #4*4,sp
    ENDC

    bra.s   Task_StartHere

; OK, kids, we are done with initialization.  We now can start the main loop
; of the driver.  It goes like this.  Because we had the port marked
; PA_IGNORE for a while (in InitUnit) we jump to the getmsg code on entry.
; (The first message will probably be posted BEFORE our task gets a chance
; to run)
;------     wait for a message
;------     lock the device
;------     get a message.  If no message, unlock device and loop
;------     dispatch the message
;------     loop back to get a message

    ;------ no more messages.  back ourselves out.
Task_Unlock:
    and.b   #$ff&(~(UNITF_ACTIVE!UNITF_INTASK)),UNIT_FLAGS(a3)
    ;------ main loop: wait for a new message

Task_MainLoop:
    PUTMSG   75,<'%s/++Sleep'>
    move.l  d7,d0
    CALLSYS Wait
    IFGE INFO_LEVEL-5
    bchg.b	#1,$bfe001  ;Blink the power LED
    ENDC
Task_StartHere:
    PUTMSG   75,<'%s/++Wakeup'>
    ;------ see if we are stopped
    btst    #MDUB_STOPPED,UNIT_FLAGS(a3)
    bne.s   Task_MainLoop	; device is stopped, ignore messages
    ;------ lock the device
    bset    #UNITB_ACTIVE,UNIT_FLAGS(a3)
    bne     Task_MainLoop	; device in use (immediate command?)

   ;------ get the next request
Task_NextMessage:
    move.l  a3,a0
    CALLSYS GetMsg
    PUTMSG  1,<'%s/GotMsg'>
    tst.l   d0
    beq     Task_Unlock ; no message?

    ;------ do this request
    move.l  d0,a1
    exg     a5,a6	; put device ptr in right place
    bsr     PerformIO
    exg     a5,a6	; get syslib back in a6

    bra.s   Task_NextMessage

*****************************************************************************
;
; Here is a dummy interrupt handler, with some crucial components commented
; out.	If the IFD INTRRUPT is enabled, this code will cause the device to
; wait for a level two interrupt before it will process each request
; (pressing RETURN on the keyboard will do it).  This code is normally
; disabled, and must fake or omit certain operations since there  isn't
; really any hardware for this driver.	Similar code has been used
; successfully in other, "REAL" device drivers.
;

   IFD	 INTRRUPT

;   A1 should be pointing to the unit structure upon entry! (IS_DATA)
myintr:
*      move.l	md_Base(a0),a0      ; point to board base address
*      btst.b	#IAMPULLING,INTCTRL1(a0);See if I'm interrupting
*      beq.s   myexnm	      ; if not set, exit, not mine
*      move.b	#0,INTACK(a0)      ; toggle controller's int2 bit

;      ------ signal the task that an interrupt has occurred

    move.l	mdu_Device(a1),a0   ; Get device pointer
    move.l	mdu_SigMask(a1),d0
    lea.l	mdu_tcb(a1),a1
    move.l	md_SysLib(a0),a6   ; Get pointer to system
    CALLSYS Signal

;      now clear the zero condition code so that
;      the interrupt handler doesn't call the next
;      interrupt server.
;
*      moveq   #1,d0	     clear zero flag
*      bra.s   myexit	      now exit
;
;      this exit point sets the zero condition code
;      so the interrupt handler will try the next server
;      in the interrupt chain
;
myexnm	    moveq   #0,d0	  set zero condition code
;
myexit	    rts
   ENDC

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

mdu_Init:
;   ------ Initialize the device

    INITBYTE	MP_FLAGS,PA_IGNORE  ;Unit starts with a message port
    INITBYTE	LN_TYPE,NT_MSGPORT  ;
    INITLONG	LN_NAME,myName	    ;
    INITLONG	mdu_tcb+LN_NAME,myName
    INITBYTE	mdu_tcb+LN_TYPE,NT_TASK
    INITBYTE	mdu_tcb+LN_PRI,5
    IFD   INTRRUPT
     INITBYTE	 mdu_is+LN_PRI,4      ; Int priority 4
     INITLONG	 mdu_is+IS_CODE,myintr	; Interrupt routine addr
     INITLONG	 mdu_is+LN_NAME,myName
    ENDC
    DC.W   0

 IFNE  AUTOMOUNT
mdn_Init:
*   ;------ Initialize packet for MakeDosNode

    INITLONG	mdn_execName,myName	; Address of driver name
    INITLONG	mdn_tableSize,12	; # long words in AmigaDOS env.
    INITLONG	mdn_dName,$524d0000	; Store 'RM' in name
    INITLONG	mdn_sizeBlock,SECTOR/4	; # longwords in a block
    INITLONG	mdn_numHeads,1		; RAM disk has only one "head"
    INITLONG	mdn_secsPerBlk,1	; secs/logical block, must = "1"
    INITLONG	mdn_blkTrack,SECTORSPER ; secs/track (must be reasonable)
    INITLONG	mdn_resBlks,1		; reserved blocks, MUST > 0!
    INITLONG	mdn_upperCyl,(RAMSIZE/BYTESPERTRACK)-1 ; upper cylinder
    INITLONG	mdn_numBuffers,1	; # AmigaDOS buffers to start
    DC.W   0
 ENDC

;----------------------------------------------------------------------
; EndCode is a marker that shows the end of your code.	Make sure it does not
; span hunks, and is not before the rom tag!  It is ok to put it right after
; the rom tag -- that way you are always safe.	I put it here because it
; happens to be the "right" thing to do, and I know that it is safe in this
; case (this program has only a single code hunk).
;----------------------------------------------------------------------
EndCode:    END


Devices/modules/saveilbm.c

/* saveilbm.c 05/91  C. Scheppner CBM
 *
 * High-level ILBM save routines
 */

#include "iffp/ilbm.h"
#include "iffp/ilbmapp.h"

extern struct Library *GfxBase;

/* screensave.c
 *
 * Given an ILBMInfo with a  currently available (not in use)
 *   ParseInfo->iff IFFHandle, a screen pointer, filename, and
 *   optional chunklist, will save screen as an ILBM
 * The struct Chunk *chunklist1 and 2 are for chunks you wish written
 * out other than BMHD, CMAP, and CAMG (they will be screened out
 * because they are computed and written separately).
 *
 * Note -  screensave passes NULL for transparent color and mask
 *
 * Returns 0 for success or an IFFERR (libraries/iffparse.h)
 */
LONG screensave(struct ILBMInfo *ilbm,
            struct Screen *scr,
            struct Chunk *chunklist1, struct Chunk *chunklist2,
            UBYTE *filename)
{
extern struct Library *GfxBase;
UWORD *colortable, count;
ULONG modeid;
LONG error;
int k;

    if(GfxBase->lib_Version >= 36)
    modeid=GetVPModeID(&scr->ViewPort);
    else
    modeid = scr->ViewPort.Modes & OLDCAMGMASK;

    count = scr->ViewPort.ColorMap->Count;
    if(colortable = (UWORD *)AllocMem(count << 1, MEMF_CLEAR))
    {
    for(k=0; k<count; k++)	colortable[k]=GetRGB4(scr->ViewPort.ColorMap,k);

        error = saveilbm(ilbm, &scr->BitMap, modeid,
        scr->Width, scr->Height, scr->Width, scr->Height,
        colortable, count, 4,
        mskNone, 0,
        chunklist1, chunklist2, filename);
    FreeMem(colortable,count << 1);
    }
    else error = IFFERR_NOMEM;
    return(error);
}

/* saveilbm
 *
 * Given an ILBMInfo with a currently available (not-in-use)
 *   ParseInfo->iff IFFHandle, a BitMap ptr,
 *   modeid, widths/heights, colortable, ncolors, bitspergun,
 *   masking, transparent color, optional chunklists, and filename,
 *   will save the bitmap as an ILBM.
 *
 *  if bitspergun=4,  colortable is words, each with nibbles 0RGB
 *  if bitspergun=8,  colortable is byte guns of RGBRGB etc. (like a CMAP)
 *  if bitspergun=32, colortable is ULONG guns of RGBRGB etc.
 *     Only the high eight bits of each gun will be written to CMAP.
 *     Four bit guns n will be saved as nn
 *
 * The struct Chunk *chunklist is for chunks you wish written
 * other than BMHD, CMAP, and CAMG (they will be screened out)
 * because they are calculated and written separately
 *
 * Returns 0 for success, or an IFFERR
 */
LONG saveilbm(struct ILBMInfo *ilbm,
        struct BitMap *bitmap, ULONG modeid,
        WORD width, WORD height, WORD pagewidth, WORD pageheight,
        APTR colortable, UWORD ncolors, UWORD bitspergun,
        WORD masking, WORD transparentColor,
        struct Chunk *chunklist1, struct Chunk *chunklist2,
        UBYTE *filename)
{
struct IFFHandle *iff;
struct Chunk *chunk;
ULONG chunkID;
UBYTE *bodybuf;
LONG size, error = 0L;
#define BODYBUFSZ	4096

    iff = ilbm->ParseInfo.iff;

    if(!(modeid & 0xFFFF0000))	modeid &= OLDCAMGMASK;

    if(!(bodybuf = AllocMem(BODYBUFSZ,MEMF_PUBLIC)))
    {
    message("Not enough memory\n");
    return(IFFERR_NOMEM);
    }

    if(!(error = openifile(ilbm, filename, IFFF_WRITE)))
    {
    D(bug("Opened %s for write\n",filename));

    error = PushChunk(iff, ID_ILBM, ID_FORM, IFFSIZE_UNKNOWN);

    D(bug("After PushChunk FORM ILBM - error = %ld\n", error));

        initbmhd(&ilbm->Bmhd, bitmap, masking, cmpByteRun1, transparentColor,
                    width, height, pagewidth, pageheight, modeid);

    D(bug("Error before putbmhd = %ld\n",error));

    CkErr(putbmhd(iff,&ilbm->Bmhd));

    if(colortable)	CkErr(putcmap(iff,colortable,ncolors,bitspergun));

    ilbm->camg = modeid;
    D(bug("before putcamg - error = %ld\n",error));
    CkErr(putcamg(iff,&modeid));

    D(bug("Past putBMHD, CMAP, CAMG - error = %ld\n",error));

    /* Write out chunklists 1 & 2 (if any), except for
     * any BMHD, CMAP, or CAMG (computed/written separately)
     */
    for(chunk = chunklist1; chunk; chunk = chunk->ch_Next)
        {
        D(bug("chunklist1 - have a %.4s\n",&chunk->ch_ID));
        chunkID = chunk->ch_ID;
        if((chunkID != ID_BMHD)&&(chunkID != ID_CMAP)&&(chunkID != ID_CAMG))
        {
        size = chunk->ch_Size==IFFSIZE_UNKNOWN ?
            strlen(chunk->ch_Data) : chunk->ch_Size;
        D(bug("Putting %.4s\n",&chunk->ch_ID));
        CkErr(PutCk(iff, chunkID, size, chunk->ch_Data));
        }
        }

    for(chunk = chunklist2; chunk; chunk = chunk->ch_Next)
        {
        chunkID = chunk->ch_ID;
        D(bug("chunklist2 - have a %.4s\n",&chunk->ch_ID));
        if((chunkID != ID_BMHD)&&(chunkID != ID_CMAP)&&(chunkID != ID_CAMG))
        {
        size = chunk->ch_Size==IFFSIZE_UNKNOWN ?
            strlen(chunk->ch_Data) : chunk->ch_Size;
        D(bug("Putting %.4s\n",&chunk->ch_ID));
        CkErr(PutCk(iff, chunkID, size, chunk->ch_Data));
        }
        }

    /* Write out the BODY
     */
    CkErr(putbody(iff, bitmap, NULL, &ilbm->Bmhd, bodybuf, BODYBUFSZ));

    D(bug("Past putbody - error = %ld\n",error));

    CkErr(PopChunk(iff));	/* close out the FORM */
    closeifile(ilbm);	/* and the file */
    }

    FreeMem(bodybuf,BODYBUFSZ);

    return(error);
}


Devices/modules/ilbmr.c

/* ilbmr.c --- ILBM loading routines for use with iffparse */

/*----------------------------------------------------------------------*
 * ILBMR.C  Support routines for reading ILBM files.
 * (IFF is Interchange Format File.)
 *
 * Based on code by Jerry Morrison and Steve Shaw, Electronic Arts.
 * This software is in the public domain.
 * Modified for iffparse.library 05/90
 * This version for the Amiga computer.
 *----------------------------------------------------------------------*/

#include "iffp/ilbm.h"
#include "iffp/packer.h"
#include "iffp/ilbmapp.h"

#define movmem CopyMem

#define MaxSrcPlanes (25)

extern struct Library *GfxBase;

/*---------- loadbody ---------------------------------------------------*/

LONG loadbody(iff, bitmap, bmhd)
struct IFFHandle *iff;
struct BitMap *bitmap;
BitMapHeader *bmhd;
    {
    BYTE *buffer;
    ULONG bufsize;
    LONG error = 1;

    D(bug("In loadbody\n"));

    if(!(currentchunkis(iff,ID_ILBM,ID_BODY)))
        {
        message("ILBM has no BODY\n");	/* Maybe it's a palette */
        return(IFF_OKAY);
        }

    if((bitmap)&&(bmhd))
        {
        D(bug("Have bitmap and bmhd\n"));

        bufsize = MaxPackedSize(RowBytes(bmhd->w)) << 4;
            if(!(buffer = AllocMem(bufsize,0L)))
        {
        D(bug("Buffer alloc of %ld failed\n",bufsize));
        return(IFFERR_NOMEM);
        }
        error = loadbody2(iff, bitmap, NULL, bmhd, buffer, bufsize);
        D(bug("Returned from getbody, error = %ld\n",error));
        }
    FreeMem(buffer,bufsize);
    return(error);
    }

/* like the old GetBODY */
LONG loadbody2(iff, bitmap, mask, bmhd, buffer, bufsize)
struct IFFHandle *iff;
struct BitMap *bitmap;
BYTE *mask;
BitMapHeader *bmhd;
BYTE *buffer;
ULONG bufsize;
   {
   UBYTE srcPlaneCnt = bmhd->nPlanes;   /* Haven't counted for mask plane yet*/
   WORD srcRowBytes = RowBytes(bmhd->w);
   WORD destRowBytes = bitmap->BytesPerRow;
   LONG bufRowBytes = MaxPackedSize(srcRowBytes);
   int nRows = bmhd->h;
   WORD compression = bmhd->compression;
   register int iPlane, iRow, nEmpty;
   register WORD nFilled;
   BYTE *buf, *nullDest, *nullBuf, **pDest;
   BYTE *planes[MaxSrcPlanes]; /* array of ptrs to planes & mask */
   struct ContextNode *cn;

   D(bug("srcRowBytes = %ld\n",srcRowBytes));

   cn = CurrentChunk(iff);

   if (compression > cmpByteRun1)
      return(CLIENT_ERROR);

   D(bug("loadbody2: compression=%ld srcBytes=%ld bitmapBytes=%ld\n",
        compression, srcRowBytes, bitmap->BytesPerRow));
   D(bug("loadbody2: bufsize=%ld bufRowBytes=%ld, srcPlaneCnt=%ld\n",
            bufsize, bufRowBytes, srcPlaneCnt));

   /* Complain if client asked for a conversion GetBODY doesn't handle.*/
   if ( srcRowBytes  >  bitmap->BytesPerRow  ||
         bufsize < bufRowBytes * 2  ||
         srcPlaneCnt > MaxSrcPlanes )
      return(CLIENT_ERROR);

   D(bug("loadbody2: past conversion checks\n"));

   if (nRows > bitmap->Rows)   nRows = bitmap->Rows;

   D(bug("loadbody2: srcRowBytes=%ld, srcRows=%ld, srcDepth=%ld, destDepth=%ld\n",
        srcRowBytes, nRows, bmhd->nPlanes, bitmap->Depth));

   /* Initialize array "planes" with bitmap ptrs; NULL in empty slots.*/
   for (iPlane = 0; iPlane < bitmap->Depth; iPlane++)
      planes[iPlane] = (BYTE *)bitmap->Planes[iPlane];
   for ( ;  iPlane < MaxSrcPlanes;  iPlane++)
      planes[iPlane] = NULL;

   /* Copy any mask plane ptr into corresponding "planes" slot.*/
   if (bmhd->masking == mskHasMask)
    {
          if (mask != NULL)
             planes[srcPlaneCnt] = mask;  /* If there are more srcPlanes than
               * dstPlanes, there will be NULL plane-pointers before this.*/
          else
             planes[srcPlaneCnt] = NULL;  /* In case more dstPlanes than src.*/
          srcPlaneCnt += 1;  /* Include mask plane in count.*/
          }

   /* Setup a sink for dummy destination of rows from unwanted planes.*/
   nullDest = buffer;
   buffer  += srcRowBytes;
   bufsize -= srcRowBytes;

   /* Read the BODY contents into client's bitmap.
    * De-interleave planes and decompress rows.
    * MODIFIES: Last iteration modifies bufsize.*/

   buf = buffer + bufsize;  /* Buffer is currently empty.*/
   for (iRow = nRows; iRow > 0; iRow--)
    {
          for (iPlane = 0; iPlane < srcPlaneCnt; iPlane++)
        {
         pDest = &planes[iPlane];

            /* Establish a sink for any unwanted plane.*/
            if (*pDest == NULL)
        {
            nullBuf = nullDest;
                pDest   = &nullBuf;
                }

            /* Read in at least enough bytes to uncompress next row.*/
            nEmpty  = buf - buffer;	  /* size of empty part of buffer.*/
            nFilled = bufsize - nEmpty;	  /* this part has data.*/
        if (nFilled < bufRowBytes)
        {
            /* Need to read more.*/

            /* Move the existing data to the front of the buffer.*/
            /* Now covers range buffer[0]..buffer[nFilled-1].*/
                movmem(buf, buffer, nFilled);  /* Could be moving 0 bytes.*/

                if(nEmpty > ChunkMoreBytes(cn))
            {
                       /* There aren't enough bytes left to fill the buffer.*/
                       nEmpty = ChunkMoreBytes(cn);
                       bufsize = nFilled + nEmpty;  /* heh-heh */
                       }

            /* Append new data to the existing data.*/
                if(ReadChunkBytes(iff, &buffer[nFilled], nEmpty) < nEmpty)
            return(CLIENT_ERROR);

                buf     = buffer;
            nFilled = bufsize;
            nEmpty  = 0;
            }

         /* Copy uncompressed row to destination plane.*/
            if(compression == cmpNone)
        {
                if(nFilled < srcRowBytes)  return(IFFERR_MANGLED);
            movmem(buf, *pDest, srcRowBytes);
            buf    += srcRowBytes;
                *pDest += destRowBytes;
                }
        else
        {
             /* Decompress row to destination plane.*/
                if ( unpackrow(&buf, pDest, nFilled,  srcRowBytes) )
                    /*  pSource, pDest, srcBytes, dstBytes  */
                       return(IFFERR_MANGLED);
            else *pDest += (destRowBytes - srcRowBytes);
        }
        }
    }
   return(IFF_OKAY);
   }

/* ----------- getcolors ------------- */

/* getcolors - allocates a ilbm->colortable for at least MAXAMCOLORREG
 *      and loads CMAP colors into it, setting ilbm->ncolors to number
 *      of colors actually loaded.
 */
LONG getcolors(struct ILBMInfo *ilbm)
    {
    struct IFFHandle	*iff;
    int error = 1;

    if(!(iff=ilbm->ParseInfo.iff))	return(CLIENT_ERROR);

    if(!(error = alloccolortable(ilbm)))
       error = loadcmap(iff, ilbm->colortable, &ilbm->ncolors);
    if(error) freecolors(ilbm);
    D(bug("getcolors: error = %ld\n",error));
    return(error);
    }

/* alloccolortable - allocates ilbm->colortable and sets ilbm->ncolors
 *	to the number of colors we have room for in the table.
 */

LONG alloccolortable(struct ILBMInfo *ilbm)
    {
    struct IFFHandle	*iff;
    struct	StoredProperty	*sp;

    LONG	error = CLIENT_ERROR;
    ULONG	ctabsize;
    USHORT	ncolors;

    if(!(iff=ilbm->ParseInfo.iff))	return(CLIENT_ERROR);

    if(sp = FindProp (iff, ID_ILBM, ID_CMAP))
        {
        /*
         * Compute the size table we need
         */
        ncolors = sp->sp_Size / 3;		/* how many in CMAP */
        ncolors = MAX(ncolors, MAXAMCOLORREG);

        ctabsize = ncolors * sizeof(Color4);
        if(ilbm->colortable =
           (Color4 *)AllocMem(ctabsize,MEMF_CLEAR|MEMF_PUBLIC))
            {
            ilbm->ncolors = ncolors;
            ilbm->ctabsize = ctabsize;
            error = 0L;
            }
        else error = IFFERR_NOMEM;
        }
    D(bug("alloccolortable for %ld colors: error = %ld\n",ncolors,error));
    return(error);
    }

void freecolors(struct ILBMInfo *ilbm)
    {
    if(ilbm->colortable)
        {
        FreeMem(ilbm->colortable, ilbm->ctabsize);
        }
    ilbm->colortable = NULL;
    ilbm->ctabsize = 0;
    }

/* Passed IFFHandle, pointer to colortable array, and pointer to
 * a USHORT containing number of colors caller has space to hold,
 * loads the colors and sets pNcolors to the number actually read.
 *
 * NOTE !!! - Old GetCMAP passed a pointer to a UBYTE for pNcolors
 *            This one is passed a pointer to a USHORT
 */
LONG loadcmap(struct IFFHandle *iff, WORD *colortable,USHORT *pNcolors)
    {
    register struct StoredProperty	*sp;
    register LONG			idx;
    register ULONG			ncolors;
    register UBYTE			*rgb;
    LONG				r, g, b;

    if(!(colortable))
        {
        message("No colortable allocated\n");
        return(1);
        }

    if(!(sp = FindProp (iff, ID_ILBM, ID_CMAP)))	return(1);

    rgb = sp->sp_Data;
    ncolors = sp->sp_Size / sizeofColorRegister;
    if(*pNcolors < ncolors)	ncolors = *pNcolors;
    *pNcolors = ncolors;

    idx = 0;
        while (ncolors--)
                {
                r = (*rgb++ & 0xF0) << 4;
                g = *rgb++ & 0xF0;
                b = *rgb++ >> 4;
                colortable[idx] = r | g | b;
                idx++;
                }
        return(0);
        }

/*
 * Returns CAMG or computed mode for storage in ilbm->camg
 *
 * ilbm->Bmhd structure must be initialized prior to this call.
 */
ULONG getcamg(struct ILBMInfo *ilbm)
    {
    struct IFFHandle *iff;
    struct StoredProperty *sp;
    UWORD  wide,high,deep;
    ULONG modeid = 0L;

        if(!(iff=ilbm->ParseInfo.iff))	return(0L);

    wide = ilbm->Bmhd.pageWidth;
    high = ilbm->Bmhd.pageHeight;
    deep = ilbm->Bmhd.nPlanes;

    D(bug("Getting CAMG for w=%ld h=%ld d=%ld ILBM\n",wide,high,deep));

        /*
         * Grab CAMG's idea of the viewmodes.
         */
        if (sp = FindProp (iff, ID_ILBM, ID_CAMG))
                {
                modeid = (* (ULONG *) sp->sp_Data);

                /* knock bad bits out of old-style 16-bit viewmode CAMGs
                 */
                if((!(modeid & MONITOR_ID_MASK))||
          ((modeid & EXTENDED_MODE)&&(!(modeid & 0xFFFF0000))))
                   modeid &=
            (~(EXTENDED_MODE|SPRITES|GENLOCK_AUDIO|GENLOCK_VIDEO|VP_HIDE));

                /* check for bogus CAMG like DPaintII brushes
                 * with junk in upper word and extended bit
                 * not set in lower word.
                 */
                if((modeid & 0xFFFF0000)&&(!(modeid & 0x00001000))) sp=NULL;
                }

        if(!sp) {
                /*
                 * No CAMG (or bad CAMG) present; use computed modes.
                 */
                if (wide >= 640)        modeid = HIRES;
                if (high >= 400)        modeid |= LACE;
                if (deep == 6)
                        {
                        modeid |= ilbm->EHB ? EXTRA_HALFBRITE : HAM;
                        }
        D(bug("No CAMG found - using mode $%08lx\n",modeid));
                }

    D(bug("getcamg: modeid = $%08lx\n",modeid));
    return(modeid);
    }


A / Third Party Public FORM and Chunk Specifications

 0000.CSET.doc        ANIM.brush.doc       ILBM.DPI.doc    RGBN-RGB8.doc
 0000.FVER.doc        ANIM.doc             ILBM.DPPV.doc   SAMP.doc
 8SVX.CHAN.PAN.doc    DR2D.doc             ILBM.DRNG.doc   TDDD.doc
 8SVX.SEQN.FADE.doc   FANT.doc             ILBM.EPSF.doc   WORD.doc
 ACBM.doc             HEAD.doc             MTRX.doc
 AIFF.doc             ILBM.CLUT.doc        PGTB.doc
 ANBM.doc             ILBM.CTBL.DYCP.doc   PRSP.doc


A / IFF Third Party Public Form and Chunk Specification / 0000.CSET.doc

Chunk for specifying character set

Registered by Martin Taillefer.

A chunk for use in any FORM, to specify character set used for text in
FORM.

   struct CSet {
           LONG    CodeSet;       /* 0=ECMA Latin 1 (std Amiga charset) */
           LONG    Reserved[7];   /* CBM will define additional values  */
           }


A / IFF Third Party Public Form and Chunk Specification / 0000.FVER.doc

Chunk for 2.0 VERSION string of an IFF file

Registered by Martin Taillefer.

A chunk for use in any FORM, to contain standard 2.0 version string.

$VER: name ver.rev

where "name" is the name or identifier of the file and ver.rev is a
version/revision such as 37.1

Example:

$VER: workbench.catalog 37.42


A / IFF Third Party Public Form and Chunk Specification / 8SVX.CHAN.PAN.doc

Stereo chunks for 8SVX form

                     SMUS.CHAN and SMUS.PAN Chunks
            Stereo imaging in the "8SVX" IFF 8-bit Sample Voice
            ---------------------------------------------------
                 Registered by David Jones, Gold Disk Inc.

There are two ways to create stereo imaging when playing back a digitized
sound. The first relies on the original sound being created with a stereo
sampler: two different samples are digitized simultaneously, using right
and left inputs. To play back this type of sample while maintaining the
stereo imaging, both channels must be set to the same volume. The second
type of stereo sound plays the identical information on two different
channels at different volumes. This gives the sample an absolute position
in the stereo field. Unfortunately, there are currently a number of
methods for doing this currently implemented on the Amiga, none truly
adhering to any type of standard. What I have tried to to is provide a way
of doing this consistently, while retaining compatibility with existing
(non-standard) systems. Introduced below are two optional data chunks,
CHAN and PAN. CHAN deals with sounds sampled in stereo, and PAN with
samples given stereo characteristics after the fact.

 Optional Data Chunk CHAN
 Optional Data Chunk PAN


8SVX.CHAN.PAN.doc / Optional Data Chunk CHAN

This chunk is already written by the software for a popular stereo
sampler. To maintain the ability read these samples, its implementation
here is therefore limited to maintain compatability.

The optional data chunk CHAN gives the information neccessary to play a
sample on a specified channel, or combination of channels. This chunk
would be useful for programs employing stereo recording or playback of
sampled sounds.

    #define RIGHT           4L
    #define LEFT            2L
    #define STEREO          6L

    #define ID_CHAN MakeID('C','H','A','N')

    typedef sampletype LONG;

If "sampletype" is RIGHT, the program reading the sample knows that it was
originally intended to play on a channel routed to the right speaker,
(channels 1 and 2 on the Amiga). If "sampletype" is LEFT, the left speaker
was intended (Amiga channels 0 and 3). It is left to the discretion of the
programmer to decide whether or not to play a sample when a channel on the
side designated by "sampletype" cannot be allocated.

If "sampletype" is STEREO, then the sample requires a pair of channels
routed to both speakers (Amiga pairs [0,1] and [2,3]). The BODY chunk for
stereo pairs contains both left and right information. To adhere to
existing conventions, sampling software should write first the LEFT
information, followed by the RIGHT. The LEFT and RIGHT information should
be equal in length.

Again, it is left to the programmer to decide what to do if a channel for
a stereo pair can't be allocated; wether to play the available channel
only, or to allocate another channels routed to the wrong speaker.


8SVX.CHAN.PAN.doc / Optional Data Chunk PAN

The optional data chunk PAN provides the neccessary information to create
a stereo sound using a single array of data. It is neccessary to replay
the sample simultaneously on two channels, at different volumes.

    #define ID_PAN MakeID('P','A','N',' ')

    typedef sposition Fixed; /* 0 <= sposition <= Unity */

    /* Unity is elsewhere #defined as 10000L, and
     * refers to the maximum possible volume.
     * /

    /* Please note that "Fixed" (elsewhere #defined as LONG) is used to
     * allow for compatabilty between audio hardware of different
     * resolutions.
     * /

The "sposition" variable describes a position in the stereo field. The
numbers of discrete stereo positions available is equal to 1/2 the number
of discrete volumes for a single channel.

The sample must be played on both the right and left channels. The overall
volume of the sample is determined by the "volume" field in the
Voice8Header structure in the VHDR chunk.

The left channel volume = overall volume / (Unity / sposition).
 "  right   "       "   = overall volume - left channel volume.

For example:
    If sposition = Unity, the sample is panned all the way to the left.
    If sposition = 0, the sample is panned all the way to the right.
    If sposition = Unity/2, the sample is centered in the stereo field.


A / IFF Third Party Public Form & Chunk Specification / 8SVXSEQN.FADE.doc

Looping chunks for 8SVX form

                          SEQN and FADE Chunks

       Multiple Loop Sequencing in the '8SVX' IFF 8-bit Sample Voice
       -------------------------------------------------------------
           Registered by Peter Norman, RamScan Software Pty Ltd.

Sound samples are notorious for demanding huge amounts of memory.

While earlier uses of digital sound on the Amiga were mainly in the form
of short looping waveforms for use as musical instruments, many people
today wish to record several seconds (even minutes) of sound. This of
course eats memory.

Assuming that quite often the content of these recordings is music, and
that quite often music contains several passages which repeat at given
times, "verse1 .. chorus ..  verse2 .. chorus .." etc, a useful extention
has been added to the 8SVX list of optional data chunks. It's purpose is
to conserve memory by having the computer repeat sections rather than
having several instances of a similar sound or musical passage taking up
valuable sample space.

The 'SEQN' chunk has been created to define "Multiple" loops or sections
within a single octave 8SVX MONO or STEREO waveform.

It is intended that a sampled sound player program which supports this
chunk will play sections of the waveform sequentially in an order that the
SEQN chunk specifies. This means for example, if an identical chorus
repeats throughout a recording, rather than have this chorus stored
several times along the waveform, it is only necessary to have one copy of
the chorus stored in the waveform.

A "SEQeNce" of definitions can then be set up to have the computer loop
back and repeat the chorus at the required time. The remaining choruses
stored in the waveform will no longer be necessary and can be removed.

E.g., if we had a recording of the following example, we would find that
there are several parts which simply repeat. Substantial savings can be
made by having the computer repeat sections rather than have them stored
in memory.

 EXAMPLE
 Chunk Definitions


8SVXSEQN.FADE.doc / EXAMPLE

"Haaaallelujah....Haaaallelujah...Hallelujah..Hallelujah..
Halleeeelujaaaah."

Applying a sequence to the above recording would look as follows.

Haaaallelujah....Haaaallelujah...Hallelujah..Hallelujah..Halleeeelujaaaah.
[     Loop1     ]
[     Loop2     ]
                                 [  Loop3   ]
                                 [  Loop4   ]
                                                         [     Loop5     ]
                [   Dead Space   ]          [ Dead Space ]

The DEAD SPACE can be removed. With careful editing of the multiple loop
positions, the passage can be made to sound exactly the same as the
original with far less memory required.


8SVXSEQN.FADE.doc / Chunk Definitions

 Optional Data Chunk SEQN
 Optional Data Chunk FADE


8SVXSEQN.FADE.doc / Optional Data Chunk SEQN

The optional data chunk SEQN gives the information necessary to play a
sample in a sequence of defined blocks. To have a segment repeat twice,
the definition occurs twice in the list.

This list consists of pairs of ULONG "loop start" and "end" definitions
which are offsets from the start of the waveform. The locations or values
must be LONGWORD aligned (divisable by 4).

To determine how many loop definitions in a given file, simply divide the
SEQN chunk size by 8.

E.g., if chunk size == 40 ... number of loops = (40 / 8) .. equals 5 loops.

The raw data in a file might look like this...

'S-E-Q-N' [ size ] [     Loop 1    ] [     Loop 2    ] [     Loop 3    ]

 5345514E 00000028 00000000 00000C00 00000000 00000C00 00000C08 00002000
             ^
             ^     'Haaaallelujah..' 'Haaaallelujah..'   'Hallelujah..'
             ^
             ^
             40 bytes decimal / 8 = 5 loop or segments

      [     Loop 4    ] [    Loop 5     ]'B-O-D-Y'   Size     Data

      00000C08 00002000 00002008 00003000 424F4459 000BE974 010101010101010

        'Hallelujah..'  'Halleeeelujah..'

In a waveform containing SEQN chunks, the oneShotHiSamples should be set
to 0 and the repeatHiSamples should equal the BODY length (divided by 2 if
STEREO).

Remember the locations of the start and end of each segment or loop should
be LONGWORD aligned.

If the waveform is Stereo, treat the values and locations in exactly the
same way. In other words, if a loop starts at location 400 within a Stereo
waveform, you start the sound at the 400th byte position in the left data
and the 400th byte position in the right data simultaneously.

    #define ID_SEQN MakeID('S','E','Q','N')


8SVXSEQN.FADE.doc / Optional Data Chunk FADE

The FADE chunk defines at what loop number the sound should begin to fade
away to silence. It is possible to finish a sample of music in much the
same way as commercial music does today. A FADE chunk consists of one
ULONG value which has a number in it. This number corresponds to the loop
number at which the fade should begin.

eg. You may have a waveform containing 50 loops. A FADE definition of 45
will specify that once loop 45 is reached, fading to zero volume should
begin. The rate at which this fade takes place is determined by the length
of time left to play. The playing software should do a calculation based
on the following...

Length of all remaining sequences including current sequence (in bytes)

divided by

the current playback rate in samples per second

= time remaining.

Begin stepping the volume down at a rate which will hit zero volume just
as the waveform finishes.

The raw data in a file may look like this.

 'F-A-D-E'  [ Size ]   Loop No.  'B-O-D-Y'   Size   Data..

  46414445  00000004   0000002D   424F4459 000BE974 01010101 01010101 etc
                          ^
                          Start fading when loop number 45 is reached.

    #define ID_FADE MakeID('F','A','D','E')

Although order shouldn't make much difference, it is a general rule of
thumb that SEQN should come before FADE and FADE should be last before the
BODY.

Stereo waveforms would have CHAN,SEQN,FADE,BODY in that order.


A / IFF Third Party Public Form and Chunk Specification / ACBM.doc

Amiga Contiguous Bitmap form

                IFF FORM / CHUNK DESCRIPTION

Form/Chunk ID:   FORM  ACBM  (Amiga Contiguous BitMap)
                 Chunk ABIT  (Amiga BITplanes)

Date Submitted:  05/29/86
Submitted by:    Carolyn Scheppner   CBM

 FORM
 Chunk
 Supporting Software


ACBM.doc / FORM

FORM ID:  ACBM  (Amiga Contiguous BitMap)

FORM Description:

FORM ACBM has the same format as FORM ILBM except the normal BODY chunk
(InterLeaved BitMap) is replaced by an ABIT chunk (Amiga BITplanes).

FORM Purpose:

To enable faster loading/saving of screens, especially from Basic, while
retaining the flexibility and portability of IFF format files.


ACBM.doc / Chunk

Chunk ID:   ABIT  (Amiga BITplanes)

Chunk Description:

The ABIT chunk contains contiguous bitplane data.  The chunk contains
sequential data for bitplane 0 through bitplane n.

Chunk Purpose:

To enable loading/storing of bitmaps with one DOS Read/Write per bitplane.
Significant speed increases are realized when loading/saving screens from
Basic.


ACBM.doc / Supporting Software

(Public Domain, available soon via Fish PD disk, various networks)

LoadILBM-SaveACBM (AmigaBasic)
   Loads and displays an IFF ILBM pic file (Graphicraft, DPaint, Images).
   Optionally saves the screen in ACBM format.

LoadACBM (AmigaBasic)
   Loads and display an ACBM format pic file.

SaveILBM (AmigaBasic)
   Saves a demo screen as an ILBM pic file which can be loaded into
   Graphicraft, DPaint, Images.


A / IFF Third Party Public Form and Chunk Specification / AIFF.doc

Audio 1-32 bit samples (Mac,AppleII,Synthia Pro)

provided by Steve Milne and Matt Deatherage, Apple Computer, Inc.

           AIFF: Audio Interchange File Format File

The Audio Interchange File Format (Audio IFF) provides a standard for
storing sampled sounds.  The format is quite flexible, allowing the
storage of monaural or multichannel sampled sounds at a variety of sample
rates and sample widths.

Audio IFF conforms to the "EA IFF 85: Standard for Interchange Format
Files" developed by Electronic Arts.

Audio IFF is primarily an interchange format, although application
designers should find it flexible enough to use as a data storage format
as well.  If an application does choose to use a different storage format,
it should be able to convert to and from the format defined in this
document.  This ability to convert will facilitate the sharing of sound
data between applications.

Audio IFF is the result of several meetings held with music developers
over a period of ten months during 1987 and 1988.  Apple Computer greatly
appreciates the comments and cooperation provided by all developers who
helped define this standard.

Another "EA IFF 85" sound storage format is "8SVX IFF 8-bit Sampled
Voice", by Electronic Arts.  '8SVX', which handles eight-bit monaural
samples, is intended mainly for storing sound for playback on personal
computers.  Audio IFF is intended for use with a larger variety of
computers, sampled sound instruments, sound software applications, and
high fidelity recording devices.

 Data Types                              The Marker Chunk
 Constants                               The Instrument Chunk
 Data Organization                       The MIDI Data Chunk
 Referring to Audio IFF                  Audio Recording Chunk
 File Structure                          Application Specific Chunk
 Storage of AIFF on Other Platforms      The Comments Chunk
 Local Chunk Types                       Text Chunks
 Sample Points and Sample Frames         Chunk Precedence
 Block Aligning Sound Data               Further Reference


AIFF.doc / AIFF / Data Types

A C-like language will be used to describe the data structures in this
document The data types used are listed below.

char:          8 bits signed.  A char can contain more than just ASCII
               characters.  It can contain any number from -128 to 127
               (inclusive).
unsigned char: 8 bits signed. Contains numbers from 0 to 255 (inclusive).
short:         16 bits signed.  Contains any number from -32,768 to 32,767
               (inclusive).
unsigned short:16 bits unsigned.  Contains any number from 0 to 65,535
               (inclusive).
long:          32 bits signed. Contains any number from -2,147,483,648
               to 2,147,483,647 (inclusive).
unsigned long: 32 bits unsigned. Contains any number from 0 to
               4,294,967,295 (inclusive).
extended:      80 bit IEEE Standard 754 floating point number (Standard
               Apple Numeric Environment [SANE] data type Extended)
pstring:       Pascal-style string, a one-byte count followed by text
               bytes.  The total number of bytes in this data type should
               be even.  A pad byte can be added to the end of the text to
               accomplish this.  This pad byte is not reflected in the
               count.
ID:            32 bits,the concatenation of four printable ASCII characters
               in the range ' ' (space, 0x20) through '~' (tilde, 0x7E).
               Leading spaces are not allowed in the ID but trailing spaces
               are OK.  Control characters are forbidden.


AIFF.doc / AIFF / Constants

Decimal values are referred to as a string of digits, for example 123, 0,
100 are all decimal numbers.  Hexadecimal values are preceded by a 0x -
e.g., 0x0A, 0x1, 0x64.


AIFF.doc / AIFF / Data Organization

All data is stored in Motorola 68000 format.  The bytes of multiple-byte
values are stored with the high-order bytes first.  Data is organized as
follows:

                7  6  5  4  3  2  1  0
          +-----------------------+
    char: | msb              lsb  |
          +-----------------------+

               15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
          +-----------------------+-----------------------+
    char: | msb    byte 0         |        byte 1     lsb |
          +-----------------------+-----------------------+

               15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
          +-----------------------+-----------------------+
    char: | msb    byte 0         |        byte 1         |
          +-----------------------+-----------------------+
    char: |        byte 2         |        byte 3     lsb |
          +-----------------------+-----------------------+

        Figure 1: IFF data storage formats


AIFF.doc / AIFF / Referring to Audio IFF

The official name for this standard is Audio Interchange File Format.  If
an application program needs to present the name of this format to a user,
such as in a "Save As..." dialog box, the name can be abbreviated to Audio
IFF. Referring to Audio IFF files by a four-letter abbreviation (i.e.,
'AIFF') in user-level documentation or program-generated messages should
be avoided.


AIFF.doc / AIFF / File Structure

The "EA IFF 85 Standard for Interchange Format Files" defines an overall
structure for storing data in files.  Audio IFF conforms to those portions
of "EA IFF 85" that are germane to Audio IFF.  For a more complete
discussion of "EA IFF 85", please refer to the document "EAIFF 85,
Standard for Interchange Format Files."

An "EA IFF 85" file is made up of a number of chunks of data.  Chunks are
the building blocks of "EA IFF 85" files.  A chunk consists of some header
information followed by data:

        +--------------------+
        |       ckID         |\
        +--------------------+ } header info
            |      ckSize        |/
        +--------------------+
            |                    |
            |                    |
            |       data         |
            |                    |
            |                    |
        +--------------------+

          Figure 2: IFF Chunk structure

A chunk can be represented using our C-like language in the following
manner:

    typedef struct {
    ID		ckID;		/* chunk ID		*/
    long		ckSize;		/* chunk Size		*/

    char		ckData[];	/* data			*/
    } Chunk;

The ckID describes the format of the data portion of a chunk.  A program
can determine how to interpret the chunk data by examining ckID.

The ckSize is the size of the data portion of the chunk, in bytes.  It
does not include the 8 bytes used by ckID and ckSize.

The ckData contains the data stored in the chunk.  The format of this data
is determined by ckID.  If the data is an odd number of bytes in length, a
zero pad byte must be added at the end.  The pad byte is not included in
ckSize.

Note that an array with no size specification (e.g., char ckData[];)
indicates a variable-sized array in our C-like language.  This differs
from standard C.

An Audio IFF file is a collection of a number of different types of
chunks. There is a Common Chunk which contains important parameters
describing the sampled sound, such as its length and sample rate.  There
is a Sound Data Chunk which contains the actual audio samples.  There are
several other optional chunks which define markers, list instrument
parameters, store application-specific information, etc.  All of these
chunks are described in detail in later sections of this document.

The chunks in an Audio IFF file are grouped together in a container chunk.
"EA IFF 85" Standard for Interchange Format Files  defines a number of
container chunks, but the one used by Audio IFF is called a FORM.  A FORM
has the following format:

    typedef struct {
    ID	ckID;
    long	ckSize;
    ID	formType;
    char	chunks[];
    }

The ckID is always 'FORM'.  This indicates that this is a FORM chunk.

The ckSize contains the size of data portion of the 'FORM' chunk.  Note
that the data portion has been broken into two parts, formType and
chunks[].

The formType field describes what's in the 'FORM' chunk.  For Audio IFF
files, formType is always 'AIFF'.  This indicates that the chunks within
the FORM pertain to sampled sound.  A FORM chunk of formType 'AIFF' is
called a FORM AIFF.

The chunks field are the chunks contained within the FORM.  These chunks
are called local chunks.  A FORM AIFF along with its local chunks make up
an Audio IFF file.

Here is an example of a simple Audio IFF file.  It consists of a file
containing single FORM AIFF which contains two local chunks, a Common
Chunk and a Sound Data Chunk.

                        __________________________
                      | FORM AIFF Chunk          |
                      |   ckID  = 'FORM'         |
                      |   formType = 'AIFF'      |
                      |    __________________    |
                      |   | Common Chunk     |   |
                      |   |   ckID = 'COMM'  |   |
                      |   |__________________|   |
                      |    __________________    |
                      |   | Sound Data Chunk |   |
                      |   |   ckID = 'SSND'  |   |
                      |   |__________________|   |
                      |__________________________|

                     Figure 3: Simple Audio IFF File

There are no restrictions on the ordering of local chunks within a FORM
AIFF.

A more detailed example of an Audio IFF file can be found in Appendix A.
Please refer to this example as often as necessary while reading the
remainder of this document.


AIFF.doc / AIFF / Storage of AIFF on Apple and Other Platforms

On a Macintosh, the FORM AIFF, is stored in the data fork of an Audio IFF
file. The Macintosh file type of an Audio IFF file is 'AIFF'.  This is the
same as the formType of the FORM AIFF.  Macintosh applications should not
store any information in Audio IFF file's resource fork, as this
information may not be preserved by all applications.  Applications can
use the Application Specific Chunk, defined later in this document, to
store extra information specific to their application.

Audio IFF files may be identified in other Apple file systems as well.  On
a Macintosh under MFS or HFS, the FORM AIFF is stored in the data fork of
a file with file type 'AIFF'.  This is the same as the formType of the
FORM AIFF.

On an operating system such as MS-DOS or UNIX, where it is customary to
use a file name extension, it is recommended that Audio IFF file names use
'.AIF' for the extension.

On an Apple II, FORM AIFF is stored in a file with file type $D8 and
auxiliary type $0000.  Versions 1.2 and earlier of the Audio IFF standard
used file type $CB and auxiliary type $0000.  This is incorrect; the
assignment listed in this document is the correct assignment.

On the Apple IIGS stereo data is stored with right data on even channels
and left data on odd channels.  Some portions of AIFF do not follow this
convention.  Even where it does follow the convention, AIFF usually uses
channel two for right data instead of channel zero as most Apple IIGS
standards do.  Be prepared to interpret data accordingly.


AIFF.doc / AIFF / Local Chunk Types

The formats of the different local chunk types found within a FORM AIFF
are described in the following sections, as are their ckIDs.

There are two types of chunks:  required and optional.  The Common Chunk
is required.  The Sound Data chunk is required if the sampled sound has a
length greater than zero.  All other chunks are optional.  All
applications that use FORM AIFF must be able to read the required chunks
and can choose to selectively ignore the optional chunks.  A program that
copies a FORM AIFF should copy all the chunks in the FORM AIFF, even those
it chooses not to interpret.

 The Common Chunk
 Sound Data Chunk


AIFF / Local Chunk Types / The Common Chunk

The Common Chunk describes fundamental parameters of the sampled sound.

    #define	CommonID	'COMM'	/* ckID for Common Chunk */

    typedef struct {
    ID		ckID;
    long		ckSize;

    short		numChannels;
    unsigned long	numSampleFrames;
    short		sampleSize;
    extended	sampleRate;
    } CommonChunk;

The ckID is always 'COMM'.  The ckSize is the size of the data portion of
the chunk, in bytes.  It does not include the 8 bytes used by ckID and
ckSize. For the Common Chunk, ckSize is always 18.

The numChannels field contains the number of audio channels for the sound.
A value of 1 means monophonic sound, 2 means stereo, and 4 means four
channel sound, etc.  Any number of audio channels may be represented.  For
multichannel sounds, single sample points from each channel are
interleaved. A set of interleaved sample points is called a sample frame.

The actual sound samples are stored in another chunk, the Sound Data
Chunk, which will be described shortly.

Single sample points from each channel are interleaved such that each
sample frame is a sample point from the same moment in time for each
channel available.

The numSampleFrames field contains the number of sample frames.  This is
not necessarily the same as the number of bytes nor the number of
samplepoints in the Sound Data Chunk.  The total number of sample points
in the file is numSampleFrames times numChannels.

The sampleSize is the number of bits in each sample point.  It can be any
number from 1 to 32.  The format of a sample point will be described in
the next section.

The sampleRate field is the sample rate at which the sound is to be played
back in sample frames per second.

One, and only one, Common Chunk is required in every FORM AIFF.


AIFF / Local Chunk Types / Sound Data Chunk

The Sound Data Chunk contains the actual sample frames.

    #define 	SoundDataID	'SSND'	/* ckID for Sound Data Chunk 	*/

    typedef struct {
    ID		ckID;
    long		ckSize;

    unsigned long	offset;
    unsigned long	blockSize;
    unsigned char	SoundData [];
    }  SoundDataChunk;

The ckID is always 'SSND'.  The ckSize is the size of the data portion of
the chunk, in bytes.  It does not include the 8 bytes used by ckID and
ckSize.

The offset field determines where the first sample frame in the soundData
starts.  The offset is in bytes.  Most applications won't use offset and
should set it to zero.  Use for a non-zero offset is explained in the
Block-Aligning Sound Data section below.

The blockSize is used in conjunction with offset for block-aligning sound
data.  It contains the size in bytes of the blocks that sound data is
aligned to.  As with offset, most applications won't use blockSize and
should set it to zero.  More information on blockSize is in the
Block-Aligning Sound Data section below.

The soundData field contains the sample frames that make up the sound.
The number of sample frames in the soundData is determined by the
numSampleFrames field in the Common Chunk.  Sample points and sample
frames are explained in detail in the next section.

The Sound Data Chunk is required unless the numSampleFrames field in the
Common Chunk is zero.  A maximum of one Sound Data Chunk may appear in a
FORM AIFF.


AIFF.doc / AIFF / Sample Points and Sample Frames

A large part of interpreting Audio IFF files revolves around the two
concepts of sample points and sample frames.

A sample point is a value representing a sample of a sound at a given
point in time.  Each sample point is stored as a linear, 2's-complement
value which may be from 1 to 32 bits wide, as determined by sampleSize in
the Common Chunk.

Sample points are stored in an integral number of contiguous bytes.  One-
to eight-bit wide sample points are stored in one byte, 9- to 16-bit wide
sample points are stored in two bytes, 17- to 24-bit wide sample points
are stored in three bytes, and 25- to 32-bit wide sample points are stored
in four bytes (most significant byte first).  When the width of a sample
point is not a multiple of eight bits, the sample point data is left
justified, with the remaining bits zeroed.  An example case is illustrated
in Figure 4.  A 12-bit sample point, binary 101000010111, is stored left
justified in two bytes. The remaining bits are set to zero.

     ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___
    |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
    | 1   0   1   0   0   0   0   1 | 0   1   1   1   0   0   0   0 |
    |___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|
     <---------------------------------------------> <------------->
          12 bit sample point is left justified         rightmost
                                                        4 bits are
                                                        zero padded
                      Figure 4: 12-Bit Sample Point

For multichannel sounds, single sample points from each channel are
interleaved.  A set of interleaved sample points is called a sample frame.
Single sample points from each channel are interleaved such that each
sample frame is a sample point from the same moment in time for each
channel available.  This is illustrated in Figure 5 for the stereo (two
channel) case.

                   sample      sample              sample
                   frame 0     frame 1             frame N
                 _____ _____ _____ _____         _____ _____
                | ch1 | ch2 | ch1 | ch2 | . . . | ch1 | ch2 |
                |_____|_____|_____|_____|       |_____|_____|
                             _____
                            |     | = one sample point
                            |_____|

                Figure 5: Sample Frames for Multichannel Sound

For monophonic sound, a sample frame is a single sample point.  For
multichannel sounds, you should follow the conventions in Figure 6.

                                       channel
               1          2          3          4          5          6
             _________ _________ _________ _________ _________ _________
            | left    | right   |         |         |         |         |
  stereo    |         |         |         |         |         |         |
            |_________|_________|_________|_________|_________|_________|
            | left    | right   | center  |         |         |         |
  3 channel |         |         |         |         |         |         |
            |_________|_________|_________|_________|_________|_________|
            | front   | front   | rear    | rear    |         |         |
  quad      | left    | right   | left    | right   |         |         |
            |_________|_________|_________|_________|_________|_________|
            | left    | center  | right   | surround|         |         |
  4 channel |         |         |         |         |         |         |
            |_________|_________|_________|_________|_________|_________|
            | left    | left    | center  | right   | right   |surround |
  6 channel |         | center  |         |         | center  |         |
            |_________|_________|_________|_________|_________|_________|

             Figure 6: Sample Frame Conventions for Multichannel Sound

Sample frames are stored contiguously in order of increasing time.  The
sample points within a sample frame are packed together; there are no
unused bytes between them.  Likewise, the sample frames are packed
together with no pad bytes.


AIFF.doc / AIFF / Block-Aligning Sound Data

There may be some applications that, to ensure real time recording and
playback of audio, wish to align sampled sound data with fixed-size
blocks. This alignment can be accomplished with the offset and blockSize
parameters of the Sound Data Chunk, as shown in Figure 7.

        ____________ __________________________________ ____________
       |\\ unused \\|          sample frames           |\\ unused \\|
       |____________|__________________________________|____________|
       <-- offset --><- numSampleFrames sample frames ->

    |   blockSize   |               |               |               |
    |<- bytes     ->|               |               |               |
    |_______________|_______________|_______________|_______________|
       block N-1       block N         block N+1       block N+2

                     Figure 7: Block-Aligned Sound Data

In Figure 7, the first sample frame starts at the beginning of block N.
This is accomplished by skipping the first offset bytes of the soundData.
Note too, that the soundData bytes can extend beyond valid sample frames,
allowing the soundData bytes to end on a block boundary as well.

The blockSize specifies the size in bytes of the block to which you would
align the sound data.  A blockSize of zero indicates that the sound data
does not need to be block-aligned.  Applications that don't care about
block alignment should set the blockSize and offset to zero when creating
Audio IFF files.  Applications that write block-aligned sound data should
set blockSize to the appropriate block size.  Applications that modify an
existing Audio IFF file should try to preserve alignment of the sound
data, although this is not required.  If an application does not preserve
alignment, it should set the blockSize and offset to zero.  If an
application needs to realign sound data to a different sized block, it
should update blockSize and offset accordingly.


AIFF.doc / AIFF / The Marker Chunk

The Marker Chunk contains markers that point to positions in the sound
data. Markers can be used for whatever purposes an application desires.
The Instrument Chunk, defined later in this Note, uses markers to mark
loop beginning and end points.

 Markers
 Marker Chunk Format


AIFF / The Marker Chunk / Markers

A marker has the following format.

    typedef	short		MarkerId;

    typedef	struct	{
        MarkerID	id;
        unsigned long	position;
        pstring		markerName;
    } Marker;

The id is a number that uniquely identifies that marker within a FORM
AIFF. The id can be any positive non-zero integer, as long as no other
marker within the same FORM AIFF has the same id.

The marker's position in the sound data is determined by the position
field. Markers conceptually fall between two sample frames.  A marker that
falls before the first sample frame in the sound data is at position zero,
while a marker that falls between the first and second sample frame in the
sound data is at position 1.  Note that the units for position  are sample
frames, not bytes nor sample points.

                              Sample Frames
             ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___
            |   |   |   |   |   |   |   |   |   |   |   |   |
            |___|___|___|___|___|___|___|___|___|___|___|___|
            ^                   ^                           ^
        position 0          position 5                  position 12

                 Figure 8: Sample Frame Marker Positions

The markerName field is a Pascal-style text string containing the name of
the mark.

Note: Some "EA IFF 85" files store strings a C-strings (text bytes
followed by a null terminating character) instead of Pascal-style strings.
Audio IFF uses pstrings because they are more efficiently skipped over
when scanning through chunks.  Using pstrings, a program can skip over a
string by adding the string count to the address of the first character.
C strings require that each character in the string be examined for the
null terminator.


AIFF / The Marker Chunk / Marker Chunk Format

The format for the data within a Marker Chunk is shown below.

    #define	MarkerID 	'MARK'	/* ckID for Marker Chunk */

    typedef  struct {
    ID				ckID;
    long				ckSize;

    unsigned short		numMarkers;
    Marker			Markers [];
    } MarkerChunk;

The ckID is always 'MARK'.  The ckSize is the size of the data portion of
the chunk in bytes.  It does not include the 8 bytes used by ckID and
ckSize.

The numMarkers field is the number of markers in the Marker Chunk.  If
numMarkers is non-zero, it is followed by the markers themselves.  Because
all fields in a marker are an even number of bytes, the length of any
marker will always be even.  Thus, markers are packed together with no
unused bytes between them.  The markers need not be ordered in any
particular manner.

The Marker Chunk is optional.  No more than one Marker Chunk can appear in
a FORM AIFF.


AIFF.doc / AIFF / The Instrument Chunk

The Instrument Chunk defines basic parameters that an instrument, such as
a sample, could use to play the sound data.

 Looping
 The Instrument Chunk Format


AIFF / The Instrument Chunk / Looping

Sound data can be looped, allowing a portion of the sound to be repeated
in order to lengthen the sound.  The structure below describes a loop.

    typedef struct {
    short	PlayMode;
    MarkerId beginLoop;
    MarkerId endLoop;
    } Loop;

A loop is marked with two points, a begin position and an end position.
There are two ways to play a loop, forward looping and forward/backward
looping. In the case of forward looping, playback begins at the beginning
of the sound, continues past the begin position and continues to the end
position, at which point playback starts again at the begin position.  The
segment between the begin and end positions, called the loop segment, is
played repeatedly until interrupted by a user action, such as the release
of a key on a sampling instrument.

                   ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___
    sample frames |   |   |   |<--- loop segment ---->|   |   |   |
                  |___|___|___|___|___|___|___|___|___|___|___|___|
                              ^                       ^
                        begin position           end position

                        Figure 9: Sample Frame Looping

With forward/backward looping, the loop segment is first played from the
begin position to the end position, and then played backwards from the end
position to the begin position.  This flip-flop pattern is repeated over
and over again until interrupted.

The playMode specifies which type of looping is to be performed:

    #define NoLooping		0
    #define ForwardLooping		1
    #define ForwardBackwardLooping  2

If NoLooping is specified, then the loop points are ignored during
playback.

The beginLoop is a marker id that marks the begin position of the loop
segment.

The endLoop marks the end position of a loop.  The begin position must be
less than the end position.  If this is not the case, then the loop
segment has zero or negative length and no looping takes place.


AIFF / The Instrument Chunk / The Instrument Chunk Format

The format of the data within an Instrument Chunk is described below.

   #define             InstrumentID  'INST' /*ckID for Instruments Chunk */

   typedef struct {
       ID              ckID;
       long            ckSize;

       char            baseNote;
       char            detune;
       char            lowNote;
       char            highNote;
       char            lowvelocity;
       char            highvelocity;
       short           gain;
       Loop            sustainLoop;
       Loop            releaseLoop;
   } InstrumentChunk;

The ckID is always 'INST'.  ckSize is the size of the data portion of the
chunk, in bytes.  For the Instrument Chunk, ckSize is always 20.

The baseNote is the note at which the instrument plays back the sound data
without pitch modification.  Units are MIDI (MIDI is an acronym for
Musical Instrument Digital Interface) note numbers, and are in the range 0
through 127.  Middle C is 60.

The detune field determines how much the instrument should alter the pitch
of the sound when it is played back.  Units are in cents (1/100 of a
semitone) and range from -50 to +50.  Negative numbers mean that the pitch
of the sound should be lowered, while positive numbers mean that it should
be raised.

The lowNote and highNote fields specify the suggested range on a keyboard
for playback of the sound data.  The sound data should be played if the
instrument is requested to play a note between the low and high,
inclusive.  The base note does not have to be within this range.  Units
for lowNote and highNote are MIDI note values.

The lowVelocity and highVelocity fields specify the suggested range of
velocities for playback of the sound data.  The sound data should be
played if the note-on velocity is between low and high velocity,
inclusive.  Units are MIDI velocity values, 1 (lowest velocity) through
127 (highest velocity).

The gain is the amount by which to change the gain of the sound when it is
played.  Units are decibels.  For example, 0db means no change, 6db means
double the value of each sample point, while -6db means halve the value of
each sample point.

The sustainLoop field specifies a loop that is to be played when an
instrument is sustaining a sound.

The releaseLoop field specifies a loop that is to be played when an
instrument is in the release phase of playing back a sound.  The release
phase usually occurs after a key on an instrument is released.

The Instrument Chunk is optional.  No more than one Instrument Chunk can
appear in a FORM AIFF.

ASIF Note:    The Apple IIGS Sampled Instrument Format also defines a
              chunk with ID of 'INST', which is not the same as the Audio
              IFF Instrument Chunk.  A good way to tell the two chunks
              apart in generic IFF-style readers is by the ckSize fields.
              The Audio IFF Instrument Chunk's ckSize field is always 20,
              whereas the Apple IIGS Sampled Instrument Format Instrument
              Chunk's ckSize field, for structural reasons, can never be
              20.


AIFF.doc / AIFF / The MIDI Data Chunk

The MIDI Data Chunk can be used to store MIDI data.  Please refer to
Musical Instrument Digital Interface Specification 1.0, available from the
International MIDI Association, for more details on MIDI.

The primary purpose of this chunk is to store MIDI System Exclusive
messages, although other types of MIDI data can be stored in the block as
well.  As more instruments come to market, they will likely have
parameters that have not been included in the Audio IFF specification.
The MIDI System Exclusive messages for these instruments may contain many
parameters that are not included in the Instrument Chunk.  For example, a
new sampling instrument may have more than the two loops defined in the
Instrument Chunk.  These loops will likely be represented in the MIDI
System Exclusive message for the new machine.  This MIDI System Exclusive
message can be stored in the MIDI Data Chunk.

    #define		MIDIDataID   'MIDI' /* ckID for MIDI Data Chunk */

    typedef struct {
    ID		ckID;
    long		ckSize;

    unsigned char	MIDIdata[];
    } MIDIDataChunk;

The ckID is always 'MIDI'.  ckSize of the data portion of the chunk, in
bytes. It does not include the 8 bytes used by ckID and ckSize.

The MIDIData field contains a stream of MIDI data.

The MIDI Data Chunk is optional.  Any number of MIDI Data Chunks may exist
in a FORM AIFF.  If MIDI System Exclusive messages for several instruments
are to be stored in a FORM AIFF, it is better to use one MIDI Data Chunk
per instrument than one big MIDI Data Chunk for all of the instruments.


AIFF.doc / AIFF / The Audio Recording Chunk

The Audio Recording Chunk contains information pertinent to audio
recording devices.

    #define     AudioRecordingID 'AESD'  /* ckID for Audio Recording */
                                         /*  Chunk.                 */
    typedef struct {
        ID                      ckID
        long                    ckSize;

        unsigned char   AESChannelStatusData[24];
    } AudioRecordingChunk;

The ckID is always 'AESD'. The ckSize is the size of the data portion of
the chunk, in bytes For the Audio Recording Chunk, ckSize is always 24.

The 24 bytes of AESCChannelStatusData are specified in the "AES
Recommended Practice for Digital Audio Engineering - Serial Transmission
Format for Linearly Represented Digital Audio Data", transmission of
digital audio between audio devices.  This information is duplicated in
the Audio Recording Chunk for convenience.  Of general interest would be
bits 2, 3, and 4 of byte 0, which describe recording emphasis.

The Audio Recording Chunk is optional.  No more than one Audio Recording
Chunk may appear in a FORM AIFF.


AIFF.doc / AIFF / The Application Specific Chunk

The Application Specific Chunk can be used for any purposes whatsoever by
developers and application authors.  For example, an application that
edits sounds might want to use this chunk to store editor state parameters
such as magnification levels, last cursor position, etc.

    #define	ApplicationSpecificID 'APPL' /* ckID for Application */
                         /*  Specific Chunk.     */
    typedef struct {
    ID		ckID;
    long		ckSize;
    OSType		applicationSignature;
    char		data[];
    } ApplicationSpecificChunk;

The ckID is always 'APPL'.  The ckSize is the size of the data portion of
the chunk, in bytes.  It does not include the 8 bytes used by ckID and
ckSize.

The applicationSignature identifies a particular application.  For
Macintosh applications, this will be the application's four character
signature.

The OSType field is used by applications which run on platforms from Apple
Computer, Inc.  For the Apple II, the OStype field should be set to
'pdos'. For the Macintosh, this field should be set to the four character
signature as registered with Apple Technical Support.

The data field is the data specific to the application.

The Application Specific Chunk is optional.  Any number of Application
Specific Chunks may exist in a single FORM AIFF.


AIFF.doc / AIFF / The Comments Chunk

The Comments Chunk is used to store comments in the FORM AIFF.  "EA IFF
85" has an Annotation Chunk (used in ASIF) that can be used for comments,
but the Comments Chunk has two features not found in the "EA IFF 85"
chunk.  They are a time-stamp for the comment and a link to a marker.

 Comment
 Comments Chunk Format


AIFF / The Comments Chunk / Comment

A comment consists of a time stamp, marker id, and a text count followed
by text.

    typedef struct {
    unsigned long	timeStamp;
    MarkerID	marker;
    unsigned short	count;
    char		text;
    } Comment;

The timeStamp indicates when the comment was created.  On the Amiga, units
are the number of seconds since January 1, 1978.  On the Macintosh, units
are the number of seconds since January 1, 1904.

A comment can be linked to a marker.  This allows applications to store
long descriptions of markers as a comment.  If the comment is referring to
a marker, then the marker field is the ID of that marker.  Otherwise,
marker is zero, indicating that this comment is not linked to a marker.

The count is the length of the text that makes up the comment.  This is a
16-bit quantity, allowing much longer comments than would be available
with a pstring.

The text field contains the comment itself.

The Comments Chunk is optional.  No more than one Comments Chunk may
appear in a single FORM AIFF.


AIFF / The Comments Chunk / Comments Chunk Format

    #define 	CommentID	'COMT'	/* ckID for Comments Chunk  */

    typedef struct {
    ID		ckID;
    long		ckSize;

    unsigned short  numComments;
    Comment		comments[];
    }CommentsChunk;

The ckID is always 'COMT'.  The ckSize is the size of the data portion of
the chunk, in bytes.  It does not include the 8 bytes used by ckID and
ckSize.

The numComments field contains the number of comments in the Comments
Chunk. This is followed by the comments themselves.  Comments are always
even numbers of bytes in length, so there is no padding between comments
in the Comments Chunk.

The Comments Chunk is optional.  No more than one Comments Chunk may
appear in a single FORM AIFF.


AIFF.doc / AIFF / The Text Chunks, Name, Author, Copyright, Annotation

These four chunks are included in the definition of every "EA IFF 85"
file. All are text chunks; their data portion consists solely of text.
Each of these chunks is optional.

    #define 	NameID 'NAME' 	/* ckID for Name Chunk */
    #define 	NameID 'AUTH' 	/* ckID for Author Chunk */
    #define 	NameID '(c) ' 	/* ckID for Copyright Chunk */
    #define 	NameID 'ANNO' 	/* ckID for Annotation Chunk */

    typedef struct {
    ID	ckID;
    long	ckSize;
    char 	text[];
    }TextChunk;

The ckID is either 'NAME', 'AUTH', '(c) ', or 'ANNO' depending on whether
the chunk is a Name Chunk, Author Chunk, Copyright Chunk, or  Annotation
Chunk, respectively.  For the Copyright Chunk, the 'c' is lowercase and
there is a space (0x20) after the close parenthesis.

The ckSize is the size of the data portion of the chunk, in this case the
text.

The text field contains pure ASCII characters.  it is not a pstring or a C
string.  The number of characters in text is determined by ckSize.  The
contents of text depend on the chunk, as described below:

 Name Chunk
 Author Chunk
 Copyright Chunk
 Annotation Chunk


AIFF / The Text Chunks / Name Chunk

The text contains the name of the sampled sound.  The Name Chunk is
optional.  No more than one Name Chunk may exist within a FORM AIFF.


AIFF / The Text Chunks / Author Chunk

The text contains one or more author names.  An author in this case is the
creator of a sampled sound.  The Author Chunk is optional.  No more than
one Author Chunk may exist within a FORM AIFF.


AIFF / The Text Chunks / Copyright Chunk

The Copyright Chunk contains a copyright notice for the sound.  The text
field contains a date followed by the name of the copyright owner.  The
chunk ID '(c) ' serves as the copyright character.  For example, a
Copyright Chunk containing the text "1991 Commodore-Amiga, Inc." means
"(c) 1991 Commodore-Amiga, Inc."  The Copyright Chunk is optional.  No
more than one Copyright Chunk may exist within a FORM AIFF.


AIFF / The Text Chunks / Annotation Chunk

The text contains a comment.  Use of this chunk is discouraged within a
FORM AIFF.  The more powerful Comments Chunk should be used instead.  The
Annotation Chunk is optional.  Many Annotation Chunks may exist within a
FORM AIFF.


AIFF.doc / AIFF / Chunk Precedence

Several of the local chunks for FORM AIFF may contain duplicate
information. For example, the Instrument Chunk defines loop points and
MIDI System Exclusive data in the MIDI Data Chunk may also define loop
points.  What happens if these loop points are different?  How is an
application supposed to loop the sound?  Such conflicts are resolved by
defining a precedence for chunks.  This precedence is illustrated in
Figure 10.

                       Common Chunk           Highest Precedence
                            |
                     Sound Data Chunk
                            |
                       Marker Chunk
                            |
                     Instrument Chunk
                            |
                       Comment Chunk
                            |
                        Name Chunk
                            |
                       Author Chunk
                            |
                      Copyright Chunk
                            |
                      Annotation Chunk
                            |
                   Audio Recording Chunk
                            |
                      MIDI Data Chunk
                            |
                 Application Specific Chunk   Lowest Precedence

                Figure 10: Chunk Precedence

The Common Chunk has the highest precedence, while the Application
Specific Chunk has the lowest.  Information in the Common Chunk always
takes precedence over conflicting information in any other chunk.  The
Application Specific Chunk always loses in conflicts with other chunks.
By looking at the chunk hierarchy, for example, one sees that the loop
points in the Instrument Chunk take precedence over conflicting loop
points found in the MIDI Data Chunk.

It is the responsibility of applications that write data into the lower
precedence chunks to make sure that the higher precedence chunks are
updated accordingly.

Figure 11 illustrates an example of a FORM AIFF.  An Audio IFF file is
simple a file containing a single FORM AIFF.  The FORM AIFF is stored in
the data fork of Macintosh file systems that can handle resource forks.

     _____________________________________________________________________
    | FORM AIFF                                                           |
    |                          _____________                              |
    |                    ckID |_ 'FORM' ____|                             |
    |                  ckSize |_ 176516 ____|                             |
    |  _____________ formType |_ 'AIFF' ____| __________________________  |
    | | Common           ckID |_ 'COMM' ____|                           | |
    | | Chunk          ckSize |_ 18 ________|                           | |
    | |           numChannels |_ 2 ___|_____                            | |
    | |       numSampleFrames |_ 88200 _____|                           | |
    | |            sampleSize |_ 16 __|_______________________________  | |
    | |___________ sampleRate |_ 44100.00 ____________________________| | |
    | | Marker           ckID |_ 'MARK' _____|                          | |
    | | Chunk          ckSize |_ 34 _________|                          | |
    | |            numMarkers |_ 2 ___|                                 | |
    | |                    id |_ 1 ___|_______                          | |
    | |              position |_ 44100 ___ ___|___ ___ ___ ___ ___ ___  | |
    | |            markerName | 8 |'b'|'e'|'g'|' '|'l'|'o'|'o'|'p'| 0 | | |
    | |                    id |_ 2 ___|_______                          | |
    | |              position |_ 88200 _______|___ ___ ___ ___ ___ ___  | |
    | |___________ markerName | 8 |'e'|'n'|'d'|' '|'l'|'o'|'o'|'p'| 0 | | |
    | | Instrument       ckID |_ 'INST' ______|                         | |
    | | Chunk          ckSize |_ 20 __________|                         | |
    | |              baseNote | 60|                                     | |
    | |                detune | -3|                                     | |
    | |               lowNote | 57|                                     | |
    | |              highNote | 63|                                     | |
    | |           lowVelocity | 1 |                                     | |
    | |          highVelocity |127|__                                   | |
    | |                  gain |_ 6 __|                                  | |
    | |  sustainLoop.playMode |_ 1 __|                                  | |
    | | sustainLoop.beginLoop |_ 1 __|                                  | |
    | |   sustainLoop.endLoop |_ 2 __|                                  | |
    | |  releaseLoop.playMode |_ 0 __|                                  | |
    | | releaseLoop.beginLoop |_ - __|                                  | |
    | |__ releaseLoop.endLoop |_ - __|__________________________________| |
    | | Sound            ckID |_ 'SSND' ______|                         | |
    | | Data           ckSize |_ 176408 ______|                         | |
    | | Chunk          offset |_ 0 ___________|                         | |
    | |             blockSize |_ 0 ___________|        _______ _______  | |
    | |             soundData |_ch 1 _|_ch 2 _| . . . |_ch 1 _|_ch 2 _| | |
    | |                       first sample frame   88200th sample frame | |
    | |_________________________________________________________________| |
    |_____________________________________________________________________|

                         Figure 11: Sample FORM AIFF


AIFF.doc / AIFF / Further Reference

 o    "Inside Macintosh", Volume II, Apple Computer, Inc.
 o    "Apple Numerics Manual", Second Edition, Apple Computer, Inc.
 o    "File Type Note: File Type $D8, Auxiliary Type $0002, Apple IIGS
       Sampled Instrument Format", Apple Computer, Inc.
 o    "Audio Interchange File Format v1.3",  APDA
 o    "AES Recommended Practice for Digital Audio Engineering--Serial
      Transmission Format for Linearly Represented Digital Audio Data",
      Audio Engineering Society, 60 East 42nd Street, New York, NY 10165
 o    "MIDI:  Musical Instrument Digital Interface, Specification 1.0", the
      International MIDI Association.
 o    "`EA IFF 85' Standard for Interchange Format Files", Electronic Arts
 o    "`8SVX' IFF 8-bit Sampled Voice", Electronic Arts


A / IFF Third Party Public Form and Chunk Specification / ANBM.doc

Animated bitmap form (Framer, Deluxe Video)

TITLE:  Form ANBM (animated bitmap form used by Framer, Deluxe Video)

(note from the author)

The format was designed for simplicity at a time when the IFF standard was
very new and strange to us all.  It was not designed to be a general
purpose animation format.  It was intended to be a private format for use
by DVideo, with the hope that a more powerful format would emerge as the
Amiga became more popular.

I hope you will publish this format (and we did!) so that other formats
will not inadvertantly conflict with it.

PURPOSE:  To define simple animated bitmaps for use in DeluxeVideo.

In Deluxe Video objects appear and move in the foreground with a picture
in the background.  Objects are "small" bitmaps usually saved as brushes
from DeluxePaint and pictures are large full screen bitmaps saved as files
from DeluxePaint.

Two new chunk headers are defined: ANBM and FSQN.

An animated bitmap (ANBM) is a series of bitmaps of the same size and
depth.  Each bitmap in the series is called a frame and is labeled by a
character, 'a b c ...' in the order they appear in the file.

The frame sequence chunk (FSQN) specifies the playback sequence of the
individual bitmaps to achieve animation. FSQN_CYCLE and FSQN_TOFRO specify
two algorithmic sequences.  If neither of these bits is set, an arbitrary
sequence can be used instead.

    ANBM         - identifies this file as an animated bitmap
    .FSQN        - playback sequence information
    .LIST ILBM   - LIST allows following ILBMs to share properties
    ..PROP ILBM  - properties follow
    ...BMHD      - bitmap header defines common size and depth
    ...CMAP      - colormap defines common colors
    ..FORM ILBM  - first frame follows
    ..BODY       - the first frame
       .         - FORM ILBM and BODY for each remaining frame
       .
       .

 ANBM
 FSQN
 Supporting Software


ANBM.doc / ANBM

Chunk Description:

The ANBM chunk identifes this file as an animated bitmap

Chunk Spec:

   #define ANBM    MakeID('A','N','B','M')

Disk record:

   none


ANBM.doc / FSQN

Chunk Description:

The FSQN chunk specifies the frame playback sequence

Chunk Spec:

#define FSQN    MakeID('F','S','Q','N')

/* Flags */
#define FSQN_CYCLE  0x0001 /* Ignore sequence, cycle a,b,..y,z,a,b,.. */
#define FSQN_TOFRO  0x0002 /* Ignore sequence, cycle a,b,..y,z,y,..a,b, */
/* Disk record */
typedef struct {
    WORD numframes;      /* Number of frames in the sequence */
    LONG dt;             /* Nominal time between frames in jiffies */
    WORDBITS flags;      /* Bits modify behavior of the animation */
    UBYTE sequence[80];  /* string of 'a'..'z' specifying sequence */
    } FrameSeqn;


ANBM.doc / Supporting Software

DeluxeVideo by Mike Posehn and Tom Case for Electronic Arts


A / IFF Third Party Public Form and Chunk Specification / ANIM.brush.doc

ANIM brush format

                    Dpaint Anim Brush IFF Format

             From a description by the author of DPaint,
                      Dan Silva, Electronic Arts

The "Anim Brushes" of DPaint III are saved on disk in the IFF "ANIM"
format. Basically, an ANIM Form consists of an initial ILBM which is the
first frame of the animation, and any number of subsequent "ILBM"S (which
aren't really ILBM's) each of which contains an ANHD animation header
chunk and a DLTA chunk comprised of the encoded difference between a frame
and a previous one.

To use ANIM terminology (for a description of the ANIM format, see the IFF
Anim Spec, by Gary Bonham). Anim Brushes use a "type 5" encoding, which is
a vertical, byte-oriented delta encoding (based on Jim Kent's RIFF).  The
deltas have an interleave of 1, meaning deltas are computed between
adjacent frames, rather than between frames 2 apart, which is the usual
ANIM custom for the purpose of fast hardware page-flipping.  Also, the
deltas use Exclusive Or to allow reversable play.

However, to my knowledge, all the existing Anim players in the Amiga world
will only play type 5 "Anim"s which have an interleave of 0 (i.e. 2) and
which use a Store operation rather than Exclusive Or, so no existing
programs will read Anim Brushes anyway.  The job of modifying existing
Anim readers to read Anim Brushes should be simplified, however.

Here is an outline of the structure of the IFF Form output by DPaint III
as an "Anim Brush".  The IFF Reader should of course be flexible enough to
tolerate variation in what chunks actually appear in the initial ILBM.

                  FORM ANIM
                      . FORM ILBM         first frame
                      . . BMHD
                      . . CMAP
                      . . DPPS
                      . . GRAB
                      . . CRNG
                      . . CRNG
                      . . CRNG
                      . . CRNG
                      . . CRNG
                      . . CRNG
                      . . DPAN     my own little chunk.
                      . . CAMG
                      . . BODY

                      . FORM ILBM         frame 2
                      . . ANHD                animation header chunk
                      . . DLTA                delta mode data

                      . FORM ILBM         frame 3
                      . . ANHD                animation header chunk
                      . . DLTA                delta mode data

                      . FORM ILBM         frame 4
                      . . ANHD                animation header chunk
                      . . DLTA                delta mode data
       ...
                   . FORM ILBM         frame N
                      . . ANHD                animation header chunk
                      . . DLTA                delta mode data

 DPAN Chunk Format
 ANHD Chunk Format
 RIFF


ANIM.brush.doc / DPAN chunk Format

   typedef struct {
    UWORD version;   /* current version=4 */
    UWORD nframes;   /* number of frames in the animation.*/
    ULONG flags;   /* Not used */
    } DPAnimChunk;

The version number was necessary during development. At present all I look
at is "nframes".


ANIM.brush.doc / ANHD chunk format

typedef struct {
 UBYTE operation;  /* =0  set directly
       =1  XOR ILBM mode,
       =2 Long Delta mode,
       =3 Short Delta mode
       =4 Generalize short/long Delta mode,
       =5 Byte Vertical Delta (riff)
       =74 (Eric Grahams compression mode)
   */
 UBYTE mask;      /* XOR ILBM only: plane mask where data is*/
 UWORD w,h;
 WORD x,y;
 ULONG abstime;
 ULONG reltime;
 UBYTE interleave; /* 0 defaults to 2 */
 UBYTE pad0;   /* not used */
 ULONG bits;   /* meaning of bits:
    bit# =0                 =1
    0    short data         long data
    1    store              XOR
    2    separate info      one info for
         for each plane     for all planes
    3    not RLC            RLC (run length encoded)
    4    horizontal         vertical
    5    short info offsets long info offsets
   */
 UBYTE pad[16];
 } AnimHdr;

for Anim Brushes, set:

 animHdr.operation = 5;  /* RIFF encoding */
 animHdr.interleave = 1;
 animHdr.w = curAnimBr.bmob.pict.box.w;
 animHdr.h = curAnimBr.bmob.pict.box.h;
 animHdr.reltime = 1;
 animHdr.abstime = 0;
 animHdr.bits = 4; /* indicating XOR */

- everything else is set to 0.

NOTE: the "bits" field was actually intended ( by the original creator of
the ANIM format, Gary Bonham of SPARTA, Inc.) for use with only with
compression method 4. I am using bit 2 of the bits field to indicate the
Exclusive OR operation in the context of method 5, which seems like a
reasonable generalization.

For an Anim Brush with 10 frames, there will be an initial frame followed
by 10 Delta's (i.e ILBMS containing ANHD and DLTA chunks).  Applying the
first Delta to the initial frame generates the second frame, applying the
second Delta to the second frame generates the third frame, etc.  Applying
the last Delta thus brings back the first frame.

The DLTA chunk begins with 16 LONG plane offets, of which DPaint only uses
the first 6 (at most).  These plane offsets are either the offset (in
bytes) from the beginning of the DLTA chunk to the data for the
corresponding plane, or Zero, if there was no change in that plane.  Thus
the first plane offset is either 0 or 64.


ANIM.brush.doc / RIFF

The following description of the method is based on Gary Bonham's
rewording of Jim Kent's RIFF documentation.

Compression/decompression is performed on a plane-by-plane
basis.

Each byte-column of the bitplane is compressed separately.  A
320x200 bitplane would have 40 columns of 200 bytes each.  In
general, the bitplanes are always an even number of bytes wide,
so for instance a 17x20 bitplane would have 4 columns of 20
bytes each.

Each column starts with an op-count followed by a number of
ops.  If the op-count is zero, that's ok, it just means there's
no change in this column from the last frame.  The ops are of
three kinds, and followed by a varying amount of data depending
on which kind:

     1. SKIP - this is a byte with the hi bit clear that   says
        how many rows to move the "dest" pointer forward, ie to
        skip. It is non-zero.

     2. DUMP - this is a byte with the hi bit set.  The hi bit is
        masked off and the remainder is a count of the number of
        bytes of data to XOR directly.  It is followed by the
        bytes to copy.

     3. RUN - this is a 0 byte followed by a count byte, followed
        by a byte value to repeat "count" times, XOR'ing it into
        the destination.

Bear in mind that the data is compressed vertically rather than
horizontally, so to get to the next byte in the destination  you
add the number of bytes per row instead of one.

The Format of DLTA chunks is as described in section 2.2.2 of the Anim
Spec. The encoding for type 5 is described in section 2.2.3 of the Anim
Spec.


A / IFF Third Party Public Form and Chunk Specification / ANIM.doc

Cel animation form
                              A N I M
                  An IFF Format For CEL Animations

                    Revision date:  4 May 1988
                    Prepared by:
                          SPARTA Inc.
                          23041 de la Carlota
                          Laguna Hills, Calif 92653
                          (714) 768-8161
                          contact: Gary Bonham

                    and:  Aegis Development Co.
                          2115 Pico Blvd.
                          Santa Monica, Calif 90405
                          213) 392-9972

 Introduction
 Chunk Formats


ANIM.doc / Introduction

The ANIM IFF format was developed at Sparta originally for the production
of animated video sequences on the Amiga computer.  The intent was to be
able to store, and play back, sequences of frames and to minimize both the
storage space on disk (through compression) and playback time (through
efficient de-compression algorithms). It was desired to maintain maximum
compatibility with existing IFF formats and to be able to display the
initial frame as a normal still IFF picture.

Several compression schemes have been introduced in the ANIM format. Most
of these are strictly of historical interest as the only one currently
being placed in new code is the vertical run length encoded byte encoding
developed by Jim Kent.

 ANIM Format Overview
 Recording ANIMs
 Playing ANIMs


Introduction / ANIM Format Overview

The general philosophy of ANIMs is to present the initial frame as a
normal, run-length-encoded, IFF picture.  Subsequent frames are then
described by listing only their differences from a previous frame.
Normally, the "previous" frame is two frames back as that is the frame
remaining in the hidden screen buffer when double-buffering is used.  To
better understand this, suppose one has two screens, called A and B, and
the ability to instantly switch the display from one to the other.  The
normal playback mode is to load the initial frame into A and duplicate it
into B.  Then frame A is displayed on the screen.  Then the differences
for frame 2 are used to alter screen B and it is displayed.  Then the
differences for frame 3 are used to alter screen A and it is displayed,
and so on.  Note that frame 2 is stored as differences from frame 1, but
all other frames are stored as differences from two frames back.

ANIM is an IFF FORM and its basic format is as follows (this assumes the
reader has a basic understanding of IFF format files):

                FORM ANIM
                . FORM ILBM         first frame
                . . BMHD                normal type IFF data
                . . ANHD                optional animation header
                                        chunk for timing of 1st frame.
                . . CMAP
                . . BODY
                . FORM ILBM         frame 2
                . . ANHD                animation header chunk
                . . DLTA                delta mode data
                . FORM ILBM         frame 3
                . . ANHD
                . . DLTA
                     ...

The initial FORM ILBM can contain all the normal ILBM chunks, such as
CRNG, etc.  The BODY will normally be a standard run-length-encoded data
chunk (but may be any other legal compression mode as indicated by the
BMHD).  If desired, an ANHD chunk can appear here to provide timing data
for the first frame.  If it is here, the operation field should be =0.

The subsequent FORMs ILBM contain an ANHD, instead of a BMHD, which
duplicates some of BMHD and has additional parameters pertaining to the
animation frame.  The DLTA chunk contains the data for the delta
compression modes.  If the older XOR compression mode is used, then a BODY
chunk will be here.  In addition, other chunks may be placed in each of
these as deemed necessary (and as code is placed in player programs to
utilize them).  A good example would be CMAP chunks to alter the color
palette.  A basic assumption in ANIMs is that the size of the bitmap, and
the display mode (e.g. HAM) will not change through the animation.  Take
care when playing an ANIM that if a CMAP occurs with a frame, then the
change must be applied to both buffers.

Note that the DLTA chunks are not interleaved bitmap representations, thus
the use of the ILBM form is inappropriate for these frames. However, this
inconsistency was not noted until there were a number of commercial
products either released or close to release which generated/played this
format.  Therefore, this is probably an inconsistency which will have to
stay with us.


Introduction / Recording ANIMs

To record an ANIM will require three bitmaps - one for creation of the
next frame, and two more for a "history" of the previous two frames for
performing the compression calculations (e.g. the delta mode calculations).

There are five frame-to-frame compression methods currently defined. The
first three are mainly for historical interest.  The product Aegis
VideoScape 3D utilizes the third method in version 1.0, but switched to
method 5 on 2.0.  This is the only instance known of a commercial product
generating ANIMs of any of the first three methods.  The fourth method is
a general short or long word compression scheme which has several options
including whether the compression is horizontal or vertical, and whether
or not it is XOR format.  This offers a choice to the user for the
optimization of file size and/or playback speed.  The fifth method is the
byte vertical run length encoding as designed by Jim Kent.  Do not confuse
this with Jim's RIFF file format which is different than ANIM.  Here we
utilized his compression/ decompression routines within the ANIM file
structure.

The following paragraphs give a general outline of each of the methods of
compression currently included in this spec.

 XOR Mode
 Long Delta Mode
 Short Delta Mode
 General Delta Mode
 Byte Vertical Compression


Introduction Recording ANIMs / XOR mode

This mode is the original and is included here for historical interest.
In general, the delta modes are far superior. The creation of XOR mode is
quite simple.  One simply performs an exclusive-or (XOR) between all
corresponding bytes of the new frame and two frames back.  This results in
a new bitmap with 0 bits wherever the two frames were identical, and 1
bits where they are different.  Then this new bitmap is saved using
run-length-encoding.  A major obstacle of this mode is in the time
consumed in performing the XOR upon reconstructing the image.


Introduction / Recording ANIMs / Long Delta mode

This mode stores the actual new frame long-words which are different,
along with the offset in the bitmap.  The exact format is shown and
discussed in section 2 below. Each plane is handled separately, with no
data being saved if no changes take place in a given plane.  Strings of 2
or more long-words in a row which change can be run together so offsets do
not have to be saved for each one.

Constructing this data chunk usually consists of having a buffer to hold
the data, and calculating the data as one compares the new frame,
long-word by long-word, with two frames back.


Introduction / Recording ANIMs / Short Delta mode

This mode is identical to the Long Delta mode except that short-words are
saved instead of long-words.  In most instances, this mode results in a
smaller DLTA chunk. The Long Delta mode is mainly of interest in improving
the playback speed when used on a 32-bit 68020 Turbo Amiga.


Introduction / Recording ANIMs / General Delta mode

The above two delta compression modes were hastily put together. This mode
was an attempt to provide a well-thought-out delta compression scheme.
Options provide for both short and long word compression, either vertical
or horizontal compression, XOR mode (which permits reverse playback), etc.
About the time this was being finalized, the fifth mode, below, was
developed by Jim Kent.  In practice the short-vertical-run-length-encoded
deltas in this mode play back faster than the fifth mode (which is in
essence a byte-vertical-run-length-encoded delta mode) but does not
compress as well - especially for very noisy data such as digitized
images.  In most cases, playback speed not being terrifically slower, the
better compression (sometimes 2x) is preferable due to limited storage
media in most machines.

Details on this method are contained in the Format for Method 4
sub-section within the Delta Chunk section.


Introduction / Recording ANIMs / Byte Vertical Compression

This method does not offer the many options that method 4 offers, but is
very successful at producing decent compression even for very noisy data
such as digitized images.  The method was devised by Jim Kent and is
utilized in his RIFF file format which is different than the ANIM format.
The description of this method in this document is taken from Jim's
writings.  Further, he has released both compression and decompression
code to public domain.

Details on this method are contained in the Format for Method 5
sub-section within the Delta Chunk section.


Introduction / Playing ANIMs

Playback of ANIMs will usually require two buffers, as mentioned above,
and double-buffering between them.  The frame data from the ANIM file is
used to modify the hidden frame to the next frame to be shown.  When using
the XOR mode, the usual run- length-decoding routine can be easily
modified to do the exclusive-or operation required.  Note that runs of
zero bytes, which will be very common, can be ignored, as an exclusive or
of any byte value to a byte of zero will not alter the original byte value.

The general procedure, for all compression techniques, is to first decode
the initial ILBM picture into the hidden buffer and double- buffer it into
view.  Then this picture is copied to the other (now hidden) buffer.  At
this point each frame is displayed with the same procedure.  The next
frame is formed in the hidden buffer by applying the DLTA data (or the XOR
data from the BODY chunk in the case of the first XOR method) and the new
frame is double-buffered into view.  This process continues to the end of
the file.

A master colormap should be kept for the entire ANIM which would be
initially set from the CMAP chunk in the initial ILBM.  This colormap
should be used for each frame.  If a CMAP chunk appears in one of the
frames, then this master colormap is updated and the new colormap applies
to all frames until the occurrance of another CMAP chunk.

Looping ANIMs may be constructed by simply making the last two frames
identical to the first two.  Since the first two frames are special cases
(the first being a normal ILBM and the second being a delta from the
first) one can continually loop the anim by repeating from frame three.
In this case the delta for creating frame three will modify the next to
the last frame which is in the hidden buffer (which is identical to the
first frame), and the delta for creating frame four will modify the last
frame which is identical to the second frame.

Multi-File ANIMs are also supported so long as the first two frames of a
subsequent file are identical to the last two frames of the preceeding
file.  Upon reading subsequent files, the ILBMs for the first two frames
are simply ignored, and the remaining frames are simply appended to the
preceeding frames.  This permits splitting ANIMs across multiple floppies
and also permits playing each section independently and/or editing it
independent of the rest of the ANIM.

Timing of ANIM playback is easily achieved using the vertical blank
interrupt of the Amiga.  There is an example of setting up such a timer in
the ROM Kernel Manual.  Be sure to remember the timer value when a frame
is flipped up, so the next frame can be flipped up relative to that time.
This will make the playback independent of how long it takes to decompress
a frame (so long as there is enough time between frames to accomplish this
decompression).


ANIM.doc / Chunk Formats

 ANHD Chunk
 DLTA ChunK


Chunk Formats / ANHD Chunk

The ANHD chunk consists of the following data structure:

   UBYTE operation  The compression method:
                    =0 set directly (normal ILBM BODY),
                    =1 XOR ILBM mode,
                    =2 Long Delta mode,
                    =3 Short Delta mode,
                    =4 Generalized short/long Delta mode,
                    =5 Byte Vertical Delta mode
                    =6 Stereo op 5 (third party)
                    =74 (ascii 'J') reserved for Eric Graham's
                       compression technique (details to be
                       released later).

   UBYTE mask      (XOR mode only - plane mask where each
                    bit is set =1 if there is data and =0
                    if not.)
   UWORD w,h       (XOR mode only - width and height of the
                    area represented by the BODY to eliminate
                    unnecessary un-changed data)
   WORD  x,y       (XOR mode only - position of rectangular
                    area representd by the BODY)
   ULONG abstime   (currently unused - timing for a frame
                    relative to the time the first frame
                    was displayed - in jiffies (1/60 sec))
   ULONG reltime   (timing for frame relative to time
                    previous frame was displayed - in
                    jiffies (1/60 sec))
   UBYTE interleave (unused so far - indicates how may frames
                     back this data is to modify.  =0 defaults
                     to indicate two frames back (for double
                     buffering). =n indicates n frames back.
                     The main intent here is to allow values
                     of =1 for special applications where
                     frame data would modify the immediately
                     previous frame)
   UBYTE pad0        Pad byte, not used at present.
   ULONG bits        32 option bits used by options=4 and 5.
                     At present only 6 are identified, but the
                     rest are set =0 so they can be used to
                     implement future ideas.  These are defined
                     for option 4 only at this point.  It is
                     recommended that all bits be set =0 for
                     option 5 and that any bit settings used in
                     the future (such as for XOR mode) be compatible
                     with the option 4 bit settings.   Player code
                     should check undefined bits in options 4 and 5
                     to assure they are zero.

                     The six bits for current use are:

                     bit #              set =0               set =1
                     ===============================================
                     0              short data           long data
                     1                 set                  XOR
                     2             separate info        one info list
                                   for each plane       for all planes
                     3               not RLC        RLC (run length coded)
                     4              horizontal           vertical
                     5           short info offsets   long info offsets

   UBYTE pad[16]     This is a pad for future use for future
                     compression modes.


Chunk Formats / DLTA Chunk

This chunk is the basic data chunk used to hold delta compression data.
The format of the data will be dependent upon the exact compression format
selected.  At present there are two basic formats for the overall
structure of this chunk.

 Format for methods 2 & 3
 Format for method 4
 Format for method 5


Chunk Formats / DLTA Chunk / Format for methods 2 & 3

This chunk is a basic data chunk used to hold the delta compression data.
The minimum size of this chunk is 32 bytes as the first 8 long-words are
byte pointers into the chunk for the data for each of up to 8 bitplanes.
The pointer for the plane data starting immediately following these 8
pointers will have a value of 32 as the data starts in the 33-rd byte of
the chunk (index value of 32 due to zero-base indexing).

The data for a given plane consists of groups of data words.  In Long
Delta mode, these groups consist of both short and long words - short
words for offsets and numbers, and long words for the actual data.  In
Short Delta mode, the groups are identical except data words are also
shorts so all data is short words. Each group consists of a starting word
which is an offset.  If the offset is positive then it indicates the
increment in long or short words (whichever is appropriate) through the
bitplane. In other words, if you were reconstructing the plane, you would
start a pointer (to shorts or longs depending on the mode) to point to the
first word of the bitplane.  Then the offset would be added to it and the
following data word would be placed at that position.  Then the next
offset would be added to the pointer and the following data word would be
placed at that position.  And so on...  The data terminates with an offset
equal to 0xFFFF.

A second interpretation is given if the offset is negative.  In that case,
the absolute value is the offset+2.  Then the following short-word
indicates the number of data words that follow.  Following that is the
indicated number of contiguous data words (longs or shorts depending on
mode) which are to be placed in contiguous locations of the bitplane.

If there are no changed words in a given plane, then the pointer in the
first 32 bytes of the chunk is =0.


Chunk Formats / DLTA Chunk / Format for method 4

The DLTA chunk is modified slightly to have 16 long pointers at the start.
The first 8 are as before - pointers to the start of the data for each of
the bitplanes (up to a theoretical max of 8 planes).  The next 8 are
pointers to the start of the offset/numbers data list.  If there is only
one list of offset/numbers for all planes, then the pointer to that list
is repeated in all positions so the playback code need not even be aware
of it.  In fact, one could get fancy and have some bitplanes share lists
while others have different lists, or no lists (the problems in these
schemes lie in the generation, not in the playback).

The best way to show the use of this format is in a sample playback
routine.

   SetDLTAshort(bm,deltaword)
   struct BitMap *bm;
   WORD *deltaword;
   {
      int i;
      LONG *deltadata;
      WORD *ptr,*planeptr;
      register int s,size,nw;
      register WORD *data,*dest;

      deltadata = (LONG *)deltaword;
      nw = bm->BytesPerRow >>1;

      for (i=0;i<bm->Depth;i++) {
         planeptr = (WORD *)(bm->Planes[i]);
         data = deltaword + deltadata[i];
         ptr  = deltaword + deltadata[i+8];
         while (*ptr != 0xFFFF) {
            dest = planeptr + *ptr++;
            size = *ptr++;
            if (size < 0) {
               for (s=size;s<0;s++) {
                  *dest = *data;
                  dest += nw;
               }
               data++;
            }
            else {
               for (s=0;s<size;s++) {
                  *dest = *data++;
                  dest += nw;
               }
            }
         }
      }
      return(0);
   }

The above routine is for short word vertical compression with run length
compression.  The most efficient way to support the various options is to
replicate this routine and make alterations for, say, long word or XOR.
The variable nw indicates the number of words to skip to go down the
vertical column.  This one routine could easily handle horizontal
compression by simply setting nw=1.  For ultimate playback speed, the
core, at least, of this routine should be coded in assembly language.


Chunk Formats / DLTA Chunk / Format for method 5

In this method the same 16 pointers are used as in option 4. The first 8
are pointers to the data for up to 8 planes. The second set of 8 are not
used but were retained for several reasons.  First to be somewhat
compatible with code for option 4 (although this has not proven to be of
any benefit) and second, to allow extending the format for more bitplanes
(code has been written for up to 12 planes).

Compression/decompression is performed on a plane-by-plane basis. For each
plane, compression can be handled by the skip.c code (provided Public
Domain by Jim Kent) and decompression can be handled by unvscomp.asm (also
provided Public Domain by Jim Kent).

Compression/decompression is performed on a plane-by-plane basis. The
following description of the method is taken directly from Jim Kent's code
with minor re-wording.  Please refer to Jim's code (skip.c and
unvscomp.asm) for more details:

Each column of the bitplane is compressed separately. A 320x200 bitplane
would have 40 columns of 200 bytes each. Each column starts with an
op-count followed by a number of ops.  If the op-count is zero, that's ok,
it just means there's no change in this column from the last frame. The
ops are of three classes, and followed by a varying amount of data
depending on which class:

  1. Skip ops - this is a byte with the hi bit clear that
     says how many rows to move the "dest" pointer forward,
     ie to skip. It is non-zero.
  2. Uniq ops - this is a byte with the hi bit set.  The hi
     bit is masked down and the remainder is a count of the
     number of bytes of data to copy literally.  It's of
     course followed by the data to copy.
  3. Same ops - this is a 0 byte followed by a count byte,
     followed by a byte value to repeat count times.

Do bear in mind that the data is compressed vertically rather than
horizontally, so to get to the next byte in the destination we add the
number of bytes per row instead of one!


A / IFF Third Party Public Form and Chunk Specification / DR2D.doc

2-D Object standard format

FORM DR2D

Description by Ross Cunniff and John Orr

A standard IFF FORM to describe 2D drawings has been sorely needed for a
long time.  Several commercial drawing packages have been available for
some time but none has established its file format as the Amiga standard.
The absence of a 2D drawing standard hinders the development of
applications that use 2D drawings as it forces each application to
understand several private standards instead of a single one.  Without a
standard, data exchange for both the developer and the user is difficult,
if not impossible.

The DR2D FORM fills this void.  This FORM was developed by Taliesin, Inc.
for use as the native file format for their two-dimensional structured
drawing package, ProVector.  Saxon Industries and Soft Logik Publishing
Corporation are planning to support this new FORM in the near future.

Many of the values stored in the DR2D FORM are stored as IEEE single
precision floating point numbers.  These numbers consist of 32 bits,
arranged as follows:

 _______________________________________________________________________
| s e e e e e e e | e m m m m m m m | m m m m m m m m | m m m m m m m m |
 -----------------------------------------------------------------------
  31            24  23            16  15            8   7             0

where:

    s   is the sign of the number where 1 is negative and 0 is
          positive.
    e   is the 8 bit exponent in excess 127 form.  This number
          is the power of two to which the mantissa is raised
          (Excess 127 form means that 127 is added to the
          exponent before packing it into the IEEE number.)
    m   is the 23 bit mantissa.  It ranges from 1.0000000 to
          1.999999..., where the leading base-ten one is
          assumed.

An IEEE single precision with the value of 0.0000000 has all its bits
cleared.

 The DR2D Chunks
 Simple DR2D Example
 OFNT Form


DR2D.doc / The DR2D Chunks

FORM (0x464F524D)  	/* All drawings are a FORM */

    struct FORMstruct {
        ULONG       ID;             /* DR2D */
        ULONG       Size;
    };

DR2D (0x44523244)  /* ID of 2D drawing */

The DR2D chunks are broken up into three groups: the global drawing
attribute chunks, the object attribute chunks, and the object chunks. The
global drawing attribute chunks describe elements of a 2D drawing that are
common to many objects in the drawing.  Document preferences, palette
information, and custom fill patterns are typical document-wide settings
defined in global drawing attribute chunks. The object attribute chunks
are used to set certain properties of the object chunk(s) that follows the
object attribute chunk.  The current fill pattern, dash pattern, and line
color are all set using an object attribute chunk.  Object chunks describe
the actual DR2D drawing. Polygons, text, and bitmaps are found in these
chunks.

 Global Drawing Attribute Chunk
 Object Attribute Chunks
 The Object Chunks


The DR2D Chunks / The Global Drawing Attribute Chunks

The following chunks describe global attributes of a DR2D document.

 DRHD       CMAP       DASH       FILL
 PPRF       FONS       AROW       LAYR


The Global Drawing Attribute Chunks / DRHD

DRHD (0x44524844) 	/* Drawing header */

The DRHD chunk contains the upper left and lower right extremes of the
document in (X, Y) coordinates.  This chunk is required and should only
appear once in a document in the outermost layer of the DR2D file (DR2Ds
can be nested).

    struct DRHDstruct {
        ULONG	ID;
        ULONG	Size;    		/* Always 16 */
        IEEE	XLeft, YTop,
            XRight, YBot;
    };

The point (XLeft,YTop) is the upper left corner of the project and the
point (XRight,YBot) is its lower right corner.  These coordinates not only
supply the size and position of the document in a coordinate system, they
also supply the project's orientation.  If XLeft < XRight, the X-axis
increases toward the right.  If YTop < YBot, the Y-axis increases toward
the bottom.  Other combinations are possible; for example in Cartesian
coordinates, XLeft would be less than XRight but YTop would be greater
than YBot.


The Global Drawing Attribute Chunks / PPRF

PPRF (0x50505249)   	/* Page preferences */

The PPRF chunk contains preference settings for ProVector.  Although this
chunk is not required, its use is encouraged because it contains some
important environment information.

    struct PPRFstruct {
        ULONG	ID;
        ULONG	Size;
        char	Prefs[Size];
    };

DR2D stores preferences as a concatenation of several null-terminated
strings, in the Prefs[] array.  The strings can appear in any order. The
currently supported strings are:

        Units=<unit-type>
        Portrait=<boolean>
        PageType=<page-type>
        GridSize=<number>

where:
        <unit-type> 	is either Inch, Cm, or Pica
        <boolean>   	is either True or False
        <page-type> 	is either Standard, Legal, B4, B5, A3,
                  A4, A5, or Custom
        <number>    	is a floating-point number

The DR2D FORM does not require this chunk to explicitly state all the
possible preferences.  In the absence of any particular preference string,
a DR2D reader should fall back on the default value.  The defaults are:

        Units=Inch
        Portrait=True
        PageType=Standard
        GridSize=1.0


The Global Drawing Attribute Chunks / CMAP

CMAP (0x434D4150)   	/* Color map (Same as ILBM CMAP) */

This chunk is identical to the ILBM CMAP chunk as described in the IFF
ILBM documentation.

    struct CMAPstruct {
        ULONG       ID;
        ULONG       Size;
        UBYTE       ColorMap[Size];
    };

ColorMap is an array of 24-bit RGB color values.  The 24-bit value is
spread across three bytes, the first of which contains the red intensity,
the next contains the green intensity, and the third contains the blue
intensity.  Because DR2D stores its colors with 24-bit accuracy, DR2D
readers must not make the mistake that some ILBM readers do in assuming
the CMAP chunk colors correspond directly to Amiga color registers.


The Global Drawing Attribute Chunks / FONS

FONS (0x464F4E53)   	/* Font chunk (Same as FTXT FONS chunk) */

The FONS chunk contains information about a font used in the DR2D FORM.
ProVector does not include support for Amiga fonts.  Instead, ProVector
uses fonts defined in the OFNT FORM which is documented later in this
article.

    struct FONSstruct {
        ULONG       ID;
        ULONG       Size;
        UBYTE       FontID;         /* ID the font is referenced by */
        UBYTE       Pad1;           /* Always 0 */
        UBYTE       Proportional;   /* Is it proportional? */
        UBYTE       Serif;          /* does it have serifs? */
        CHAR        Name[Size-4];   /* The name of the font */
    };

The UBYTE FontID field is the number DR2D assigns to this font. References
to this font by other DR2D chunks are made using this number.  The
Proportional and Serif fields indicate properties of this font.
Specifically, Proportional indicates if this font is proportional, and
Serif indicates if this font has serifs.  These two options were created
to allow for font substitution in case the specified font is not
available.  They are set according to these values:

    0	The DR2D writer didn't know if this font is
          proportional/has serifs.
    1	No, this font is not proportional/does not have
          serifs.
    2	Yes, this font is proportional/does have serifs.

The last field, Name[], is a NULL terminated string containing the
name of the font.


The Global Drawing Attribute Chunks / DASH

DASH (0x44415348)   	/* Line dash pattern for edges */

This chunk describes the on-off dash pattern associated with a line.

    struct DASHstruct {
        ULONG       ID;
        ULONG       Size;
        USHORT      DashID;             /* ID of the dash pattern */
        USHORT      NumDashes;          /* Should always be even */
        IEEE        Dashes[NumDashes];  /* On-off pattern */
    };

DashID is the number assigned to this specific dash pattern. References to
this dash pattern by other DR2D chunks are made using this number.

The Dashes[] array contains the actual dash pattern.  The first number in
the array (element 0) is the length of the ``on'' portion of the pattern.
The second number (element 1) specifies the ``off'' portion of the
pattern.  If there are more entries in the Dashes array, the pattern will
continue.  Even-index elements specify the length of an ``on'' span, while
odd-index elements specify the length of an ``off'' span.  There must be
an even number of entries.  These lengths are not in the same units as
specified in the PPRF chunk, but are multiples of the line width, so a
line of width 2.5 and a dash pattern of 1.0, 2.0 would have an ``on'' span
of length 1.0 x 2.5 = 2.5 followed by an ``off'' span of length 2.0 x 2.5
= 5.  The following figure shows several dash pattern examples.  Notice
that for lines longer than the dash pattern, the pattern repeats.

 Figure 1 - Dash Patterns

By convention, DashID 0 is reserved to mean `No line pattern at all', i.e.
the edges are invisible.  This DASH pattern should not be defined by a
DR2D DASH chunk.  Again by convention, a NumDashes of 0 means that the
line is solid.


The Global Drawing Attribute Chunks / AROW

AROW (0x41524F57)   	/* An arrow-head pattern */

The AROW chunk describes an arrowhead pattern.  DR2D open polygons (OPLY)
can have arrowheads attached to their endpoints.  See the description of
the OPLY chunk later in this article for more information on the OPLY
chunk.

    #define ARROW_FIRST  0x01 /* Draw an arrow on the OPLY's first point */
    #define ARROW_LAST   0x02 /* Draw an arrow on the OPLY's last point */

    struct AROWstruct {
        ULONG       ID;
        ULONG       Size;
        UBYTE       Flags;          /* Flags, from ARROW_*, above */
        UBYTE       Pad0;           /* Should always 0 */
        USHORT      ArrowID;        /* Name of the arrow head */
        USHORT      NumPoints;
        IEEE        ArrowPoints[NumPoints*2];
    };

The Flags field specifies which end(s) of an OPLY to place an arrowhead
based on the #defines above.  ArrowID is the number by which an OPLY will
reference this arrowhead pattern.

The coordinates in the array ArrowPoints[] define the arrowhead's shape.
These points form a closed polygon.  See the section on the OPLY/CPLY
object chunks for a descriptionof how DR2D defines shapes. The arrowhead
is drawn in the same coordinate system relative to the endpoint of the
OPLY the arrowhead is attached to.  The arrowhead's origin (0,0) coincides
with the OPLY's endpoint.  DR2D assumes that the arrowhead represented in
the AROW chunk is pointing to the right so the proper rotation can be
applied to the arrowhead.  The arrow is filled according to the current
fill pattern set in the ATTR object attribute chunk.


The Global Drawing Attribute Chunks / FILL

FILL (0x46494C4C)   	/* Object-oriented fill pattern */

The FILL chunk defines a fill pattern.  This chunk is only valid inside
nested DR2D FORMs.  The GRUP object chunk section of this article contans
an example of the FILL chunk.

    struct FILLstruct {
        ULONG       ID;
        ULONG       Size;
        USHORT      FillID;                 /* ID of the fill */
    };

FillID is the number by which the ATTR object attribute chunk references
fill patterns.  The FILL chunk must be the first chunk inside a nested
DR2D FORM.  A FILL is followed by one DR2D object plus any of the object
attribute chunks (ATTR, BBOX) associated with the object.

 Figure 2 - Fill Patterns

DR2D makes a ``tile'' out of the fill pattern, giving it a virtual
bounding box based on the extreme X and Y values of the FILL's object
(Fig. A).  The bounding box shown in Fig. A surrounding the pattern (the
two ellipses) is invisible to the user.  In concept, this rectangle is
pasted on the page left to right, top to bottom like floor tiles (Fig. B).
Again, the bounding boxes are not visible.  The only portion of this tiled
pattern that is visible is the part that overlaps the object (Fig. C)
being filled.  The object's path is called a clipping path, as it
``clips'' its shape from the tiled pattern (Fig. D).  Note that the fill
is only masked on top of underlying objects, so any ``holes'' in the
pattern will act as a window, leaving visible underlying objects.


The Global Drawing Attribute Chunks / LAYR

LAYR (0x4C415952)   	/* Define a layer */

A DR2D project is broken up into one or more layers.  Each DR2D object is
in one of these layers.  Layers provide several useful features. Any
particular layer can be ``turned off'', so that the objects in the layer
are not displayed.  This eliminates the unnecessary display of objects not
currently needed on the screen.  Also, the user can lock a layer to
protect the layer's objects from accidental changes.

    struct LAYRstruct {
        ULONG    ID;
        ULONG    Size;
        USHORT   LayerID;		   /* ID of the layer */
        char     LayerName[16];	   /* Null terminated and padded */
        UBYTE    Flags;		   /* Flags, from LF_*, below */
        UBYTE    Pad0;		   /* Always 0 */
    };

LayerID is the number assigned to this layer.  As the field's name
indicates, LayerName[] is the NULL terminated name of the layer. Flags is
a bit field who's bits are set according to the #defines below:

    #define LF_ACTIVE     	0x01  	/* Active for editing */
    #define LF_DISPLAYED  	0x02  	/* Displayed on the screen */

If the LF_ACTIVE bit is set, this layer is unlocked.  A set LF_DISPLAYED
bit indicates that this layer is currently visible on the screen.  A
cleared LF_DISPLAYED bit implies that LF_ACTIVE is not set. The reason for
this is to keep the user from accidentally editing layers that are
invisible.


The DR2D Chunks / The Object Attribute Chunks

 ATTR
 BBOX
 XTRN


The Object Attribute Chunks / ATTR

ATTR (0x41545452)   	/* Object attributes */

The ATTR chunk sets various attributes for the objects that follow it. The
attributes stay in effect until the next ATTR changes the attributes, or
the enclosing FORM ends, whichever comes first.

    /* Various fill types */
    #define FT_NONE         0    /* No fill                 */
    #define FT_COLOR        1    /* Fill with color from palette */
    #define FT_OBJECTS      2    /* Fill with tiled objects */

    struct ATTRstruct {
        ULONG       ID;
        ULONG       Size;
        UBYTE       FillType;    /* One of FT_*, above      */
        UBYTE       JoinType;    /* One of JT_*, below      */
        UBYTE       DashPattern; /* ID of edge dash pattern */
        UBYTE       ArrowHead;   /* ID of arrowhead to use  */
        USHORT      FillValue;   /* Color or object with which to fill */
        USHORT      EdgeValue;   /* Edge color index        */
        USHORT      WhichLayer;  /* ID of layer it's in     */
        IEEE        EdgeThick;   /* Line width              */
    };

FillType specifies what kind of fill to use on this ATTR chunk's objects.
A value of FT_NONE means that this ATTR chunk's objects are not filled.
FT_COLOR indicates that the objects should be filled in with a color.
That color's ID (from the CMAP chunk) is stored in the FillValue field.
If FillType is equal to FT_OBJECTS, FillValue contains the ID of a fill
pattern defined in a FILL chunk.

JoinType determines which style of line join to use when connecting the
edges of line segments.  The field contains one of these four values:

    /* Join types */
    #define JT_NONE         0       /* Don't do line joins */
    #define JT_MITER        1       /* Mitered join */
    #define JT_BEVEL        2       /* Beveled join */
    #define JT_ROUND        3       /* Round join */

DashPattern and ArrowHead contain the ID of the dash pattern and arrow
head for this ATTR's objects.  A DashPattern of zero means that there is
no dash pattern so lines will be invisible.  If ArrowHead is 0, OPLYs have
no arrow head.  EdgeValue is the color of the line segments.  WhichLayer
contains the ID of the layer this ATTR's objects are in.  EdgeThick is the
width of this ATTR's line segments.


The Object Attribute Chunks / BBOX

BBOX (0x42424F48)   	/* Bounding box of next object in FORM */

The BBOX chunk supplies the dimensions and position of a bounding box
surrounding the DR2D object that follows this chunk in the FORM.  A BBOX
chunk can apply to a FILL or AROW as well as a DR2D object.  The BBOX
chunk appears just before its DR2D object, FILL, or AROW chunk.

   struct BBOXstruct {
       ULONG       ID;
       ULONG       Size;
       IEEE                XMin, YMin,     /* Bounding box of obj. */
                           XMax, YMax;     /* including line width */
   };

In a Cartesian coordinate system, the point (XMin, YMin) is the
coordinate of the lower left hand corner of the bounding box and
(XMax, YMax) is the upper right.  These coordinates take into
consideration the width of the lines making up the bounding box.


The Object Attribute Chunks / XTRN

XTRN (0x5854524E)   	/* Externally controlled object */

The XTRN chunk was created primarily to allow ProVector to link DR2D
objects to ARexx functions.

    struct XTRNstruct {
        ULONG   ID;
        ULONG   Size;
        short   ApplCallBacks;            /* From #defines, below */
        short   ApplNameLength;
        char    ApplName[ApplNameLength]; /* Name of ARexx func to call */
    };

ApplName[] contains the name of the ARexx script ProVector calls when the
user manipulates the object in some way.  The ApplCallBacks field
specifies the particular action that triggers calling the ARexx script
according to the #defines listed below.

    /* Flags for ARexx script callbacks */
    #define    X_CLONE     0x0001    /* The object has been cloned */
    #define    X_MOVE      0x0002    /* The object has been moved */
    #define    X_ROTATE    0x0004    /* The object has been rotated */
    #define    X_RESIZE    0x0008    /* The object has been resized */
    #define    X_CHANGE    0x0010    /* An attribute (see ATTR) of the
                                        object has changed */
    #define    X_DELETE    0x0020    /* The object has been deleted */
    #define    X_CUT       0x0040    /* The object has been deleted, but
                                        stored in the clipboard */
    #define    X_COPY      0x0080    /* The object has been copied to the
                                        clipboard */
    #define    X_UNGROUP   0x0100    /* The object has been ungrouped */

For example, given the XTRN object:

    FORM xxxx DR2D {
            XTRN xxxx { X_RESIZE | X_MOVE, 10, "Dimension" }
            ATTR xxxx { 0, 0, 1, 0, 0, 0, 0.0 }
            FORM xxxx DR2D {
                    GRUP xxxx { 2 }
                    STXT xxxx { 0, 0.5, 1.0, 6.0, 5.0, 0.0, 4, "3.0" }
                    OPLY xxxx { 2, { 5.5, 5.5, 8.5, 5.5 } }
            }
    }

ProVector would call the ARexx script named Dimension if the user resized
or moved this object.  What exactly ProVector sends depends upon what the
user does to the object.  The following list shows what string(s)
ProVector sends according to which flag(s) are set.  The parameters are
described below.

    X_CLONE     ``appl CLONE objID dx dy''
    X_MOVE      ``appl MOVE objID dx dy''
    X_ROTATE    ``appl ROTATE objID cx cy angle''
    X_RESIZE    ``appl RESIZE objID cx cy sx sy''
    X_CHANGE    ``appl CHANGE objID et ev ft fv ew jt fn''
    X_DELETE    ``appl DELETE objID''
    X_CUT       ``appl CUT objID''
    X_COPY      ``appl COPY objID''
    X_UNGROUP   ``appl UNGROUP objID''

 where:
    appl is the name of the ARexx script
    CLONE, MOVE, ROTATE, RESIZE, etc. are literal strings
    objID is the object ID that ProVector assigns to this object
    (dx, dy) is the position offset of the CLONE or MOVE
    (cx, cy) is the point around which the object is rotated or resized
    angle is the angle (in degrees) the object is rotated
    sx and sy are the scaling factors in the horizontal and
      vertical directions, respectively.
    et is the edge type (the dash pattern index)
    ev is the edge value (the edge color index)
    ft is the fill type
    fv is the fill index
    ew is the edge weight
    jt is the join type
    fn is the font name

The X_CHANGE message reflects changes to the attributes found in the ATTR
chunk.

If the user resized the XTRN object shown above by factor of 2, ProVector
would call the ARexx script Dimension like this:

    Dimension RESIZE 1985427 7.0 4.75 2.0 2.0


The DR2D Chunks / The Object Chunks

The following chunks define the objects available in the DR2D FORM.

 VBM
 CPLY, OPLY
 GRUP
 STXT
 TPTH


The Object Chunks / VBM

VBM  (0x56424D20)   	/* Virtual BitMap */

The VBM chunk contains the position, dimensions, and file name of an ILBM
image.

    struct VBMstruct {
        IEEE        XPos, YPos,     /* Virtual coords */
                    XSize, YSize,   /* Virtual size */
                    Rotation;       /* in degrees */
        USHORT      PathLen;        /* Length of dir path */
        char        Path[PathLen];  /* Null-terminated path of file */
    };

The coordinate (XPos, YPos) is the position of the upper left hand corner
of the bitmap and the XSize and YSize fields supply the x and y dimensions
to which the image should be scaled.  Rotation tells how many degrees to
rotate the ILBM around its upper left hand corner. ProVector does not
currently support rotation of bitmaps and will ignore this value.  Path
contains the name of the ILBM file and may also contain a partial or full
path to the file.  DR2D readers should not assume the path is correct.
The full path to an ILBM on one system may not match the path to the same
ILBM on another system.  If a DR2D reader cannot locate an ILBM file based
on the full path name or the file name itself (looking in the current
directory), it should ask the user where to find the image.


The Object Chunks / CPLY, OPLY

CPLY (0x43504C59)   	/* Closed polygon */
OPLY (0x4F504C59)   	/* Open polygon */

Polygons are the basic components of almost all 2D objects in the DR2D
FORM.  Lines, squares, circles, and arcs are all examples of DR2D
polygons.  There are two types of DR2D polygons, the open polygon (OPLY)
and the closed polygon (CPLY).  The difference between a closed and open
polygon is that the computer adds a line segment connecting the endpoints
of a closed polygon so that it is a continuous path.  An open polygon's
endpoints do not have to meet, like the endpoints of a line segment.

    struct POLYstruct {
        ULONG       ID;
        ULONG       Size;
        USHORT      NumPoints;
        IEEE        PolyPoints[2*NumPoints];
    };

The NumPoints field contains the number of points in the polygon and the
PolyPoints array contains the (X, Y) coordinates of the points of the
non-curved parts of polygons.  The even index elements are X coordinates
and the odd index elements are Y coordinates.

[ Figure 3 - Bezier Curves

DR2D uses Bezier cubic sections, or cubic splines, to describe curves in
polygons.  A set of four coordinates (P1 through P4) defines the shape of
a cubic spline.  The first coordinate (P1) is the point where the curve
begins.  The line from the first to the second coordinate (P1 to P2) is
tangent to the curve at the first point.  The line from P3 to P4 is
tangent to the cubic section, where it ends at P4.

The coordinates describing the cubic section are stored in the
PolyPoints[] array with the coordinates of the normal points.  DR2D
inserts an indicator point before a set of cubic section points to
differentiate a normal point from the points that describe a curve. An
indicator point has an X value of 0xFFFFFFFF.  The indicator point's Y
value is a bit field.  If this bit field's low-order bit is set, the
points that follow the indicator point make up a cubic section.

The second lowest order bit in the indicator point's bit field is the
MOVETO flag.  If this bit is set, the point (or set of cubic section
points) starts a new polygon, or subpolygon.  This subpolygon will appear
to be completely separate from other polygons but there is an important
connection between a polygon and its subpolygon. Subpolygons make it
possible to create holes in polygons.  An example of a polygon with a hole
is the letter ``O''.  The ``O'' is a filled circular polygon with a
smaller circular polygon within it.  The reason the inner polygon isn't
covered up when the outer polygon is filled is that DR2D fills are done
using the even-odd rule.

The even-odd rule determines if a point is ``inside'' a polygon by drawing
a ray outward from that point and counting the number of path segments the
ray crosses.  If the number is even, the point is outside the object and
shouldn't be filled.  Conversely, an odd number of crossings means the
point is inside and should be filled.  DR2D only applies the even-odd rule
to a polygon and its subpolygons, so no other objects are considered in
the calculations.

Taliesin, Inc. supplied the following algorithm to illustrate the format
of DR2D polygons.  OPLYs, CPLYs, AROWs, and ProVector's outline fonts all
use the same format:

    typedef union {
        IEEE num;
        LONG bits;
    } Coord;

    #define INDICATOR       0xFFFFFFFF
    #define IND_SPLINE      0x00000001
    #define IND_MOVETO      0x00000002

    /* A common pitfall in attempts to support DR2D has
            been to fail to recognize the case when an
            INDICATOR point indicates the following
            coordinate to be the first point of BOTH a
            Bezier cubic and a sub-polygon, ie. the
            value of the flag = (IND_CURVE | IND_MOVETO) */

    Coord   Temp0, Temp1;
    int     FirstPoint, i, Increment;

    /* Initialize the path */
    NewPath();
    FirstPoint = 1;

    /* Draw the path */
    i = 0;
    while( i < NumPoints ) {
        Temp0.num = PolyPoints[2*i];    Temp1.num = PolyPoints[2*i + 1];
        if( Temp0.bits == INDICATOR ) {
            /* Increment past the indicator */
            Increment = 1;
            if( Temp1.bits & IND_MOVETO ) {
                /* Close and fill, if appropriate */
                if( ID == CPLY ) {
                    FillPath();
                }
                else {
                    StrokePath();
                }

                /* Set up the new path */
                NewPath();
                FirstPoint = 1;
            }
            if( Temp1.bits & IND_CURVE ) {
                /* The next 4 points are Bezier cubic control points */
                if( FirstPoint )
                    MoveTo( PolyPoints[2*i + 2], PolyPoints[2*i + 3] );
                else
                    LineTo( PolyPoints[2*i + 2], PolyPoints[2*i + 3] );
                CurveTo(    PolyPoints[2*i + 4], PolyPoints[2*i + 5],
                            PolyPoints[2*i + 6], PolyPoints[2*i + 7],
                            PolyPoints[2*i + 8], PolyPoints[2*i + 9] );
                FirstPoint = 0;
                /* Increment past the control points */
                Increment += 4;
            }
        }
        else {
            if( FirstPoint )
                MoveTo(     PolyPoints[2*i], PolyPoints[2*i + 1] );
            else
                LineTo(     PolyPoints[2*i], PolyPoints[2*i + 1] );
            FirstPoint = 0;

            /* Increment past the last endpoint */
            Increment = 1;
        }

        /* Add the increment */
        i += Increment;
    }

    /* Close the last path */
    if( ID == CPLY ) {
        FillPath();
    }
    else {
        StrokePath();
    }


The Object Chunks / GRUP

GRUP (0x47525550)   	/* Group */

The GRUP chunk combines several DR2D objects into one.  This chunk is only
valid inside nested DR2D FORMs, and must be the first chunk in the FORM.

    struct GROUPstruct {
        ULONG       ID;
        ULONG       Size;
        USHORT      NumObjs;
    };

The NumObjs field contains the number of objects contained in this group.
Note that the layer of the GRUP FORM overrides the layer of objects within
the GRUP.  The following example illustrates the layout of the GRUP (and
FILL) chunk.

    FORM { DR2D              /* Top-level drawing... */
             DRHD { ... }    /* Confirmed by presence of DRHD chunk */
             CMAP { ... }    /* Various other things... */
             FONS { ... }
             FORM { DR2D             /* A nested form... */
                     FILL { 1 }      /* Ah!  The fill-pattern table */
                     CPLY { ... }    /* with only 1 object */
             }
             FORM { DR2D             /* Yet another nested form */
                     GRUP { ..., 3 } /* Ah! A group of 3 objects */
                     TEXT { ... }
                     CPLY { ... }
                     OPLY { ... }
             }
             FORM { DR2D             /* Still another nested form */
                     GRUP { ..., 2 } /* A GRUP with 2 objects */
                     OPLY { ... }
                     TEXT { ... }
             }
     }


The Object Chunks / STXT

STXT (0x53545854)   		/* Simple text */

The STXT chunk contains a text string along with some information on how
and where to render the text.

    struct STXTstruct {
        ULONG       ID;
        ULONG       Size;
        UBYTE       Pad0;           /* Always 0 (for future expansion) */
        UBYTE       WhichFont;      /* Which font to use */
        IEEE        CharW, CharH,   /* W/H of an individual char */
                    BaseX, BaseY,   /* Start of baseline */
                    Rotation;       /* Angle of text (in degrees) */
        USHORT      NumChars;
        char        TextChars[NumChars];
    };

The text string is in the character array, TextChars[].  The ID of the
font used to render the text is WhichFont.  The font's ID is set in a FONS
chunk.  The starting point of the baseline of the text is (BaseX, BaseY).
This is the point around which the text is rotated.  If the Rotation field
is zero (degrees), the text's baseline will originate at (BaseX, BaseY)
and move to the right.  CharW and CharH are used to scale the text after
rotation.  CharW is the average character width and CharH is the average
character height.  The CharW/H fields are comparable to an X and Y font
size.


The Object Chunks / TPTH

TPTH (0x54505448) 		/* A text string along a path */

This chunk defines a path (polygon) and supplies a string to render along
the edge of the path.

    struct TPTHstruct {
        ULONG   ID;
        ULONG   Size;
        UBYTE   Justification;      /* see defines, below */
        UBYTE   WhichFont;          /* Which font to use */
        IEEE    CharW, CharH;       /* W/H of an individual char    */
        USHORT  NumChars;           /* Number of chars in the string */
        USHORT  NumPoints;          /* Number of points in the path */
        char    TextChars[NumChars];/* PAD TO EVEN #! */
        IEEE    Path[2*NumPoints];  /* The path on which the text lies */
    };

WhichFont contains the ID of the font used to render the text.
Justification controls how the text is justified on the line.
Justification can be one of the following values:

    #define J_LEFT          0x00    /* Left justified */
    #define J_RIGHT         0x01    /* Right justified */
    #define J_CENTER        0x02    /* Center text */
    #define J_SPREAD        0x03    /* Spread text across path */

CharW and CharH are the average width and height of the font characters
and are akin to X and Y font sizes, respectively.  A negative FontH
implies that the font is upsidedown.  Note that CharW must not be
negative.  NumChars is the number of characters in the TextChars[] string,
the string containing the text to be rendered. NumPoints is the number of
points in the Path[] array.  Path[] is the path along which the text is
rendered.  The path itself is not rendered.  The points of Path[] are in
the same format as the points of a DR2D polygon.


DR2D.doc / A Simple DR2D Example

Here is a (symbolic) DR2D FORM:

 FORM { DR2D
        DRHD 16 { 0.0, 0.0, 10.0, 8.0 }
        CMAP  6 { 0,0,0, 255,255,255 }
        FONS  9 { 1, 0, 1, 0, "Roman" } 0
        DASH 12 { 1, 2, {1.0, 1.0} }
        ATTR 14 { 0, 0, 1, 0, 0, 0, 0, 0.0 }
        BBOX 16 { 2.0, 2.0, 8.0, 6.0 }
        FORM { DR2D
              GRUP  2 { 2 }
              BBOX 16 { 3.0, 4.0, 7.0, 5.0 }
              STXT 36 { 0,1, 0.5, 1.0, 3.0, 5.0, 0.0, 12, "Hello, World" }
              BBOX 16 { 2.0, 2.0, 8.0, 6.0 }
              OPLY 42 { 5, {2.0,2.0, 8.0,2.0, 8.0,6.0, 2.0,6.0, 2.0,2.0 }
        }
 }

 Figure 4 - Simple DR2D Drawing


DR2D.doc / The OFNT FORM

 OFNT
 OFHD
 KERN
 CHDF


DR2D.doc / OFNT

OFNT	(0x4F464E54)   	/* ID of outline font file */

ProVector's outline fonts are stored in an IFF FORM called OFNT.  This
IFF is a separate file from a DR2D.  DR2D's FONS chunk refers only to
fonts defined in the OFNT form.


DR2D.doc / OFHD

OFHD	(0x4F464844)   	/* ID of OutlineFontHeaDer */

This chunk contains some basic information on the font.

    struct OFHDstruct {
        char   FontName[32];   /* Font name, null padded */
        short  FontAttrs;      /* See FA_*, below */
        IEEE   FontTop,        /* Typical height above baseline */
               FontBot,        /* Typical descent below baseline */
               FontWidth;      /* Typical width, i.e. of the letter O */
    };

    #define FA_BOLD         0x0001
    #define FA_OBLIQUE      0x0002
    #define FA_SERIF        0x0004

The FontName field is a NULL terminated string containing the name of this
font.  FontAttrs is a bit field with flags for several font attributes.
The flags, as defined above, are bold, oblique, and serif.  The unused
higher order bits are reserved for later use.  The other fields describe
the average dimensions of the characters in this font.  FontTop is the
average height above the baseline, FontBot is the average descent below
the baseline, and FontWidth is the average character width.


DR2D.doc / KERN

KERN	(0x4B45524C)   	/* Kerning pair */

The KERN chunk describes a kerning pair.  A kerning pair sets the
distance between a specific pair of characters.

    struct KERNstruct {
        short   Ch1, Ch2;   /* The pair to kern (allows for 16 bits...) */
        IEEE    XDisplace,  /* Amount to displace -left +right */
                YDisplace;  /* Amount to displace -down +up */
    };

The Ch1 and Ch2 fields contain the pair of characters to kern.  These
characters are typically stored as ASCII codes.  Notice that OFNT stores
the characters as a 16-bit value.  Normally, characters are stored as
8-bit values.  The wary programmer will be sure to cast assigns properly
to avoid problems with assigning an 8-bit value to a 16-bit variable.  The
remaining fields, XDisplace and YDisplace, supply the baseline shift from
Ch1 to Ch2.


DR2D.doc / CHDF

CHDF	(0x43484446)  	/* Character definition */

This chunk defines the shape of ProVector's outline fonts.

    struct CHDFstruct {
        short   Ch;         /* The character we're defining (ASCII) */
        short   NumPoints;  /* The number of points in the definition */
        IEEE    XWidth,     /* Position for next char on baseline - X */
                YWidth;     /* Position for next char on baseline - Y */
     /* IEEE    Points[2*NumPoints]*/       /* The actual points */
    };

    #define INDICATOR   0xFFFFFFFF  /* If X == INDICATOR, Y is an action */
    #define IND_SPLINE  0x00000001  /* Next 4 pts are spline control pts */
    #define IND_MOVETO  0x00000002    /* Start new subpoly */
    #define IND_STROKE  0x00000004  /* Stroke previous path */
    #define IND_FILL    0x00000008  /* Fill previous path */

Ch is the value (normally ASCII) of the character outline this chunk
defines.  Like Ch1 and Ch2 in the KERN chunk, Ch is stored as a 16-bit
value.  (XWidth,YWidth) is the offset to the baseline for the following
character.  OFNT outlines are defined using the same method used to define
DR2D's polygons (see the description of OPLY/CPLY for details).

Because the OFNT FORM does not have an ATTR chunk, it needed an
alternative to make fills and strokes possible.  There are two extra bits
used in font indicator points not found in polygon indicator points, the
IND_STROKE and IND_FILL bits (see defines above).  These two defines
describe how to render the current path when rendering fonts.

The current path remains invisible until the path is either filled and/or
stroked.  When the IND_FILL bit is set, the currently defined path is
filled in with the current fill pattern (as specified in the current ATTR
chunk).  A set IND_STROKE bit indicates that the currently defined path
itself should be rendered.  The current ATTR's chunk dictates the width of
the line, as well as several other attributes of the line.  These two bits
apply only to the OFNT FORM and should not be used in describing DR2D
polygons.


A / IFF Third Party Public Form and Chunk Specification / FANT.doc

Fantavision movie format

FORM FANT

/*********************************************************************/
/*                                                                   **
** - FantForm.h                                                      **
**                                                                   **
**     This is the IFF movie format for Amiga Fantavision.           **
**                                                                   **
**     (c) Copyright 1988 Broderbund Software                        **
**                                                                   **
**     - FORMAT FROZED May 5, 1988 -                                 **
**                                                                   **
**     Implemented by Steve Hales                                    **
**                                                                   **
** Overvue -                                                         **
**     This is a description of the format used for Amiga            **
**     Fantavision.  It assumes you have intimate knowledge of how   **
**     IFF-FORMs are constructed, layed out, and read.  This file    **
**     can be used as a header file.  This is fairly complete, but   **
**     I'm sure there are a few things missing.                      **
**                                                                   **
**     I can be reached in the following ways:                       **
**       UseNet:   Steve_A_Hales@cup.portal.com  OR                  **
**                 sun!cup.portal.com!Steve_A_Hales                  **
**                                                                   **
**       US Mail:  882 Hagemann Drive                                **
**                 Livermore, CA, 94550-2420                         **
**                                                                   **
**       Phone:    (415) 449-5297                                    **
**                                                                   **
**     NOTE:  I cannot, by contract, give out any code to load or    **
**            play Fantavision movies.  If that is want you want     **
**            then you will need to contact Broderbund Software      **
**            directly.  Their number is (415) 492-3200.             **
**                                                                   **
** Enjoy!  Aloha.                                                    **
**                                                                   */
/*********************************************************************/

 Misc Fantavision Structures        Polygon Types
 Frame Opcodes                      Fantavision Movie Header
 Frame Modes                        Fantavision Frame Info
 Fantavision FORM Defines           Fantavision Polygon Info
 Polygon Modes                      Fantavision High-level IFF Format

 Notes


FANT.doc / Misc Fantavision Structures

    typedef struct Rect
    {
       int left, top, right, bottom;
    };

    typedef struct Point
    {
       int h, v;
    };


FANT.doc / Frame opcodes

#define opNEXT     0  /* go on to next frame */
#define opREPEAT   1  /* repeat seqnce starting at frame Parm rep1 times */
#define opGOTO     2  /* goto frame Parm */


FANT.doc / Frame modes

#define fNORMAL    0x0000  /* redraw every frame */
#define fTRACE     0x0001  /* draw into both paged screens */
#define fLIGHTNING 0x0020  /* don't erase background */


FANT.doc / Fantavision FORM defines

#define ID_FANT    'FANT'  /* FORM type */
#define ID_FHDR    'FHDR'  /* Movie Header */
#define ID_FRAM    'FRAM'  /* Format info for a Frame */
#define ID_POLY    'POLY'  /* Format info for a Polygon */
#define ID_CSTR    'CSTR'  /* \0 terminated string */


FANT.doc / Polygon modes

#define pTYPEMASK  0x00FF  /* type mask to get just type of poly */
#define pSELECT    0x8000  /* is object selected? */
#define pOUTLINE   0x4000  /* outlined polygon using DotModeSide to
                           ** determine when to not connect a line.
                           ** ex. 0 draws on all sides, 1 will draw on
                           ** everyother side, 2 will leave every second
                           ** side blank, 3 will every third side
                           ** blank, etc. */
#define pBACKDROP  0x2000  /* polygon will be dropped into the background
                           ** during animation. */
#define pMSKBITMAP 0x1000  /* bitmap has a mask */


FANT.doc / Polygon types

#define pDELETE    0x7000  /* object is a filler (deleted from display) */
#define pFILLED    0       /* filled polygon */
#define pLINE      1       /* not-connected line polygon */
#define pLINED     2       /* connected line polygon */
#define pTEXTBLOCK 3       /* text block to draw */
#define pCIRCLEDOT 4       /* draw circle dots at vertex's using
                           ** dotSize at size. */
#define pRECTDOT   5       /* draw square dots at vertex's using
                           ** dotSize at size. */
#define pBITMAPDOT 6       /* draw dots using a bitmap at vertex's using
                           ** BitMap. */
#define pBITMAP    7       /* draw just bitmap image */

/* These are used for the pTEXTBLOCK polygon type
*/
/* Text justification
*/
#define tLEFT      0
#define tCENTER    1
#define tRIGHT     2
/* Text style
*/
#define tNORMAL    (int)(FS_NORMAL)
#define tBOLD      (int)(FSF_BOLD)
#define tITALIC    (int)(FSF_ITALIC)
#define tUNDERLINE (int)(FSF_UNDERLINED)
#define tEXTENDED  (int)(FSF_EXTENDED)


FANT.doc / Fantavision movie header

/*
** This header defines how much RAM is needed, how many frames, and sounds
** in the movie.
*/

typedef struct FantHeader
{
   int PointsPerObj;     /* number of vertexs per object */
   int ObjsPerFrame;     /* number of objects per frame */
   int ScreenDepth;      /* 0 to 6, for number of bit planes */
   int ScreenWidth;      /* in pixels */
   int ScreenHeight;     /* in pixels */
   int BackColor;        /* background color palette number */
   long SizeOfMovie;     /* RAM Size of movie, expanded */
   int pad[30];          /* padding for expanding */
   int NumberOfFrames;
   int NumberOfSounds;
   int NumberOfBitMaps;
   int Background;       /* non-zero if first bitmap is a background */
   int SpeedOfMovie;     /* 100 is normal speed, 50 is half speed, etc */
   int pad[3];           /* expansion */
};


FANT.doc / Fantavision frame info

/*
**     Each frame has this structure defined.
*/
typedef struct FrameFormat
{
   int OpCode;           /* Frame opcode */
   long Parm;            /* contains frame number for opNEXT, opREPEAT */
   char Rep1, Rep2;      /* Rep1 is repeat counter, Rep2 is not used */
   int TweenRate;        /* number of tweens per frame */

   int ChannelIndex[2];  /* -3 stop sound is this channel
                         ** -2 modify current sound
                         ** -1 no sound for this channel
                         ** (all others) is an index into the sound
                         ** list.  Which sound to use.
                         */

   int NumberOfPolys;    /* number of polygons in this frame */
   int ColorPalette[32]; /* xRGB - format 4 bits per register */
   int Pan, Tilt;        /* 0 is centered, (+-) amounts are in pixels */
   int Modes;            /* Frame modes */
   int pad;              /* expansion */
};


FANT.doc / Fantavision polygon info

/*
**     Each polygon has this structure defined.
*/
typedef struct PolyFormat
{
   int NumberOfPoints;   /* how many vertexs for this polygon */
   int Type;             /* polygon type */
   int Color;            /* palette color number (see note 1) */
   Rect Bounds;          /* enclosing rectangle of polygon */
   int Depth;            /* polygon view depth (see note 2) */
   char DotModeSize;     /* in pixels, not larger than 40 */
   char DotModeSide;     /* determines outlining features */
   int OutlineColor;     /* palette color number for outline */
   int BitMapIndex;      /* if not -1,then bitmap index into bitmap list */
   int BMRealWidth;      /* in pixels */
   int BMRealHeight;
   int TextLength;       /* length of text for pTEXTBLOCK */
   int TextJust;
   char TextSize;        /* size in pixels */
   char TextStyle;
   long pad;             /* expansion */
   Point p[];            /* array of points defining vertexs */
};


FANT.doc / Fantavision high-level IFF format

/*
FORM FANT
    FHDR

    - background -
    FORM ILBM   if Background is non-zero
        BMHD
        BODY

    - bitmap list -
    NOTE:  If a bitmap has a mask, it will be compute during load time.

    FORM ILBM   times NumberOfBitMaps
        BMHD
        BODY

    - sound list -
{   FORM 8SVX   times NumberOfSounds
        VHDR
        BODY
    SEFX    }   Default parameters for sound

    - frame list -
{   FRAM        times NumberOfFrames
    SEFX        if sound for channel 1.
    SEFX        if sound for channel 2.
    POLY        times NumberOfPolys
  { CSTR        Text of poly if PolyType = pTEXTBLOCK
    CSTR  } }   Name of font
*/


FANT.doc / Notes

/************************************************************************/
/*
** 1 - The color palette is a number from 0 to 1120.  The first 32 numbers
**     are normal RGB colors, but the rest index into a pre-defined
**     set of patterns.
**
** 2 - The view depth of each polygon determines the display order.  The
**     higher the number the closer the polygon is to the viewer.  During
**     editing, each polygon is assigned numbers in multiplies of 100,
**     but to function, any number can work.
*/


A / IFF Third Party Public Form and Chunk Specification / HEAD.doc

Flow -  New Horizons Software

TITLE:  HEAD  (FORM used by Flow - New Horizons Software, Inc.)

IFF FORM / CHUNK DESCRIPTION

Form/Chunk ID:  FORM HEAD, Chunks NEST, TEXT, FSCC

Date Submitted: 03/87
Submitted by:   James Bayless - New Horizons Software, Inc.

 FORM
 CHUNKS


HEAD.doc / FORM

FORM ID:  HEAD

FORM Description:

FORM HEAD is the file storage format of the Flow idea processor by New
Horizons Software, Inc.  Currently only the TEXT and NEST chunks are used.
There are plans to incorporate FSCC and some additional chunks for headers
and footers.


HEAD.doc / CHUNKS

CHUNK ID:  NEST

This chunk consists of only of a word (two byte) value that gives the new
current nesting level of the outline.  The initial nesting level
(outermost level) is zero.  It is necessary to include a NEST chunk only
when the nesting level changes.  Valid changes to the nesting level are
either to decrease the current value by any amount (with a minimum of 0)
or to increase it by one (and not more than one).

CHUNK ID:  TEXT

This chunk is the actual text of a heading.  Each heading has a TEXT chunk
(even if empty).  The text is not NULL terminated - the chunk size gives
the length of the heading text.

CHUNK ID: FSCC

This chunk gives the Font/Style/Color changes in the heading from the most
recent TEXT chunk.  It should occur immediately after the TEXT chunk it
modifies.  The format is identical to the FSCC chunk for the IFF form type
'WORD' (for compatibility), except that only the 'Location' and 'Style'
values are used (i.e., there can be currently only be style changes in an
outline heading).  The structure definition is:

    typedef struct {
       UWORD   Location;   /* Char location of change */
       UBYTE   FontNum;    /* Ignored */
       UBYTE   Style;      /* Amiga style bits */
       UBYTE   MiscStyle;  /* Ignored */
       UBYTE   Color;      /* Ignored */
       UWORD   pad;        /* Ignored */
    } FSCChange;

The actual chunk consists of an array of these structures, one entry for
each Style change in the heading text.


A / IFF Third Party Public Form and Chunk Specification / ILBM.CLUT.doc

Color Lookup Table chunk

amiga.dev/iff message 1527
----------
TITLE: CLUT IFF chunk proposal

"CLUT" IFF 8-Bit Color Look Up Table

Date:	July 2, 1989
From:	Justin V. McCormick
Status:	Public Proposal
Supporting Software:  FG 2.0 by Justin V. McCormick for PP&S

 Introduction
 Purpose
 Specifications
 CLUT Example
 Design Notes


ILBM.CLUT.doc / Introduction

This memo describes the IFF supplement for the new chunk "CLUT".

Description:

A CLUT (Color Look Up Table) is a special purpose data module containing
table with 256 8-bit entries.  Entries in this table can be used directly
as a translation for one 8-bit value to another.


ILBM.CLUT.doc / Purpose

To store 8-bit data look up tables in a simple format for later retrieval.
These tables are used to translate or bias 8-bit intensity, contrast,
saturation, hue, color registers, or other similar data in a reproducable
manner.


ILBM.CLUT.DOC / Specifications

/* Here is the IFF chunk ID macro for a CLUT chunk */

#define ID_CLUT MakeID('C','L','U','T')

/*
 * Defines for different flavors of 8-bit CLUTs.
 */
#define CLUT_MONO       0L   /* A Monochrome, contrast or intensity LUT */
#define CLUT_RED        1L   /* A LUT for reds               */
#define CLUT_GREEN      2L   /* A LUT for greens             */
#define CLUT_BLUE       3L   /* A LUT for blues              */
#define CLUT_HUE        4L   /* A LUT for hues               */
#define CLUT_SAT        5L   /* A LUT for saturations        */
#define CLUT_UNUSED6    6L   /* How about a Signed Data flag */
#define CLUT_UNUSED7    7L   /* Or an Assumed Negative flag  */

/* All types > 7 are reserved until formally claimed */
#define CLUT_RESERVED_BITS 0xfffffff8L

/* The struct for Color Look-Up-Tables of all types */
typedef struct
{
  ULONG type;		/* See above type defines */
  ULONG res0;		/* RESERVED FOR FUTURE EXPANSION */
  UBYTE lut[256];	/* The 256 byte look up table */
} ColorLUT;


ILBM.CLUT.doc / CLUT Example

Normally, the CLUT chunk will appear after the BMHD of an FORM ILBM before
the BODY chunk, in the same "section" as CMAPs are normally found.
However, a FORM may contain only CLUTs with no other supporting
information.

As a general guideline, it is desirable to group all CLUTs together in a
form without other chunk types between them. If you were using CLUTs to
store RGB intensity corrections, you would write three CLUTs in a row, R,
G, then B.

Here is a box diagram for a 320x200x8 image stored as an IFF ILBM with a
single CLUT chunk for intensity mapping:

          +-----------------------------------+
          |'FORM'		64284		    |     FORM 64284 ILBM
          +-----------------------------------+
          |'ILBM'				    |
          +-----------------------------------+
          | +-------------------------------+ |
          | | 'BMHD'	20		  | |     .BMHD 20
          | | 320, 200, 0, 0, 8, 0, 0, ...  | |
          | | ------------------------------+ |
          | | 'CLUT'	264	          | |     .CLUT 264
          | | 0, 0, 0; 32, 0, 0; 64,0,0; .. | |
          | +-------------------------------+ |
          | +-------------------------------+ |
          | |'BODY'		64000     | |     .BODY 64000
          | |0, 0, 0, ...			  | |
          | +-------------------------------+ |
          +-----------------------------------+


ILBM.CLUT.doc / Design Notes

I have deliberately kept this chunk simple (KISS) to facilitate
implementation.  In particular, no provision is made for expansion to
16-bit or 32-bit tables.  My reasoning is that a 16-bit table can have 64K
entries, and thus would benefit from data compression.  My suggestion
would be to propose another chunk or FORM type better suited for large
tables rather than small ones like CLUT.


A / IFF Third Party Public Form & Chunk Specification / ILBM.CTBL.DYCP.doc

Newtek Dynamic Ham color chunks

Newtek for Digiview IV (dynamic Ham)

ILBM.DYCP - dynamic color palette
3 longwords (file setup stuff)

ILBM.CTBL - array of words, one for each color (0rgb)


A / IFF Third Party Public Form and Chunk Specification / ILBM.DPI.doc

Dots per inch chunk

ILBM DPI chunk
--------------

Registered by:

Spencer Shanson
16 Genesta Rd
Plumstead
London SE18 3ES
ENGLAND

1-16-90

ILBM.DPI   Dots Per Inch   to allow output of an image at the
same resolution it was scanned at

typedef struct {
    UWORD dpi_x;
    UWORD dpi_y;
    } DPIHeader ;

For example, an image scanned at horizontal resolution of
240dpi and vertical resolution of 300dpi would be saved as:

44504920 00000004 00F0 012C
D P I    size     dpi_x dpi_y


A / IFF Third Party Public Form and Chunk Specification / ILBM.DPPV.doc

DPaint perspective chunk (EA)

IFF FORM / CHUNK DESCRIPTION

Form/Chunk ID:   Chunk DPPV  (DPaint II ILBM perspective chunk)
Date Submitted:  12/86
Submitted by:    Dan Silva

 Chunk Description
 Chunk Specification
 Supporting Software


ILBM.DPPV.doc / Chunk Description

The DPPV chunk describes the perspective state in a DPaintII ILBM.


ILBM.DPPV.doc / Chunk Specification

/* The chunk identifier DPPV */

#define ID_DPPV    MakeID('D','P','P','V')

typedef LONG LongFrac;
typedef struct ( LongFrac x,y,z; )  LFPoint;
typedef LongFrac  APoint[3];

typedef union {
   LFPoint l;
   APoint  a;
   } UPoint;

/* values taken by variable rotType */
#define ROT_EULER  0
#define ROT_INCR   1

/* Disk record describing Perspective state */

typedef struct {
   WORD     rotType;           /* rotation type */
   WORD     iA, iB, iC;        /* rotation angles (in degrees) */
   LongFrac Depth;             /* perspective depth */
   WORD     uCenter, vCenter;  /* coords of center perspective,
                                * relative to backing bitmap,
                                * in Virtual coords
                                */
   WORD     fixCoord;          /* which coordinate is fixed */
   WORD     angleStep;         /* large angle stepping amount */
   UPoint   grid;              /* gridding spacing in X,Y,Z */
   UPoint   gridReset;         /* where the grid goes on Reset */
   UPoint   gridBrCenter;      /* Brush center when grid was last on,
                                * as reference point
                                */
   UPoint   permBrCenter;      /* Brush center the last time the mouse
                                * button was clicked, a rotation performed,
                                * or motion along "fixed" axis
                                */
   LongFrac rot[3][3];         /* rotation matrix */
   } PerspState;


Supporting Software

DPaint II   by Dan Silva for Electronic Arts


A / IFF Third Party Public Form and Chunk Specification / ILBM.DRNG.doc

DPaint IV enhanced color cycle chunk (EA)

DRNG Chunk for FORM ILBM
------------------------

Submitted by Lee Taran

 Enhanced Color Cycling Capabilities
 DPaintIV DRNG Chunk


ILBM.DRNG.doc / Enhanced Color Cycling Capabilities

* DPaintIV supports a new color cycling model which does NOT
  require that color cycles contain a contiguous range of color
  registers.

For example:
  If your range looks like:  [1][3][8][2]
  then at each cycle tick
     temp = [2],
     [2] = [8],
     [8] = [3],
     [3] = [1],
     [1] = temp

* You can now cycle a single register thru a series of rgb values.
  For example:
     If your range looks like: [1] [orange] [blue] [purple]
     then at each cycle tick color register 1 will take on the
     next color in the cycle.

     ie:  t=0:  [1] = curpal[1]
          t=1:  [1] = purple
          t=2:  [1] = blue
          t=3:  [1] = orange
          t=4:  goto t=0

* You can combine rgb cycling with traditional color cycling.
  For example:
      Your range can look like:
          [1] [orange] [blue] [2] [green] [yellow]

      t=0: [1] = curpal[1], [2] = curpal[2]
      t=1: [1] = yellow,    [2] = blue
      t=2: [1] = green,     [2] = orange
      t=3: [1] = curpal[2], [2] = curpal[1]
      t=4: [1] = blue,      [2] = yellow
      t=5: [1] = orange,    [2] = green
      t=6: goto t=0

Note:
   * DPaint will save out an old style range CRNG if the range fits
     the CRNG model otherwise it will save out a DRNG chunk.
   * no thought has been given (yet) to interlocking cycles


ILBM.DRNG.doc / DPaintIV DRNG chunk

       DRNG ::= "DRNG" # { DRange DColor* DIndex* }

a <cell> is where the color or register appears within the range

The RNG_ACTIVE flags is set when the range is cyclable. A range
should only have the RNG_ACTIVE if it:
     1> contains at least one color register
     2> has a defined rate
     3> has more than one color and/or color register
If the above conditions are met then RNG_ACTIVE is a user/program
preference.  If the bit is NOT set the program should NOT cycle the
range.

The RNG_DP_RESERVED flags should always be 0!!!

typedef struct {
   UBYTE min;           /* min cell value */
   UBYTE max;           /* max cell value */
   SHORT rate;          /* color cycling rate, 16384 = 60 steps/second */
   SHORT flags;         /* 1=RNG_ACTIVE,4=RNG_DP_RESERVED */
   UBYTE ntrue;         /* number of DColor structs to follow */
   UBYTE nregs;         /* number of DIndex structs to follow */
   } DRange;

typedef struct { UBYTE cell; UBYTE r,g,b; } DColor; /* true color cell */
typedef struct { UBYTE cell; UBYTE index; } DIndex;
                                                /* color register cell */


A / IFF Third Party Public Form and Chunk Specification / ILBM.EPSF.doc

Encapsulated Postscript chunk

ILBM EPSF Chunk
---------------

Pixelations   Kevin Saltzman   617-277-5414

Chunk to hold encapsulated postscript

Used by PixelScript in their clip art.  Holds a postscript representation
of the ILBM's graphic image.

EPSF length
   ; Bounding box
   WORD lowerleftx;
   WORD lowerlefty;
   WORD upperrightx;
   WORD upperrighty;
   CHAR []    ; ascii postscript file


A / IFF Third Party Public Form and Chunk Specification / MTRX.doc

Numerical data storage (MathVision - Seven Seas)

MTRX FORM, for matrix data storage                    19-July-1990

Submitted by: Doug Houck
              Seven Seas Software

 Introduction
 Chunks


MTRX.doc / Introduction

Numerical data, as it comes from the real world, is an ill-mannered beast.
Often much is assumed about the data, such as the number of dimensions,
formatting, compression, limits, and sizes.  As such, data is not
portable. The MTRX FORM will both store the data, and completely describe
its format, such that programs no longer need to guess the parameters of a
data file.  There needs to be but one program to read ascii files and
output MTRX IFF files.

A matrix, by our definition, is composed of three types of things.
Firstly, the atomic data, such as an integer, or floating point number.
Secondly, arrays, which are simply lists of things which are all the same.
Thirdly, structures, which are lists of things which are different. Both
arrays and structures may be composed of things besides atomic data - they
may contain other structures and arrays as well.  This concept of nesting
structures may be repeated to any desired depth.

For example, a list of data pairs could be encoded as an array of
structures, where each structure contains two numbers.  A two-dimensional
array is simply an array of arrays.

Since space conservation is often desirable, there is provision for
representing each number with fewer bits, and compressing the bits
together.


MTRX.doc / Chunks

The MTRX FORM is composed of the definition of the structure, followed by
the BODY which contains the data which is defined.  Usually, there is only
one set of data, but a smarter IFF read could use the definition as a
PROPerty, with identically formatted data sets (BODYs) in a LIST.

  FORM MTRX
    definition (ARRY | STRU | DTYP)
    BODY

ARRY: The array chunk defines a counted list of similar items. The first
(required) chunk in an ARRY is ELEM, which gives the number of elements in
the array.  Optionally, there may be limits given, (LOWR and UPPR), which
could be used in scaling during sampling of the data. Lastly is the
definition of an element of the array, which may be a nested definition
like everything else.

  ARRY ::= "ARRY" #{ ELEM [LOWR] [UPPR] [PACK] ARRY|STRU|DTYP }

STRU: The structure chunk defines a counted list of dissimilar things. The
first (required) chunk in a STRU is FLDS, which gives the number of fields
in the structure.  Lastly are definitions of each field in the structure.
Again, each field may have a nested definition like everything else.

 STRU ::= "STRU" #{ FLDS ([PACK] ARRY|STRU|DTYP)* }

VALU: The value contains a datatype, and then a constant of that type. The
datatype contains the size of the constant, so this chunk has variable
size.  VALU is used in the ARRY chunk to give the scaling limits of the
array.

BODY: This is the actual data we went to so much effort to describe. It is
stored in "row-first" format, that is, items at the bottom of the nested
description are stored next to each other.  In most cases, it should be
sufficient to simply block-read the whole chunk from disk, unless the
reader needs to adjust byte-ordering or store in a more time-efficient
format in memory.  Data is assumed to be byte-aligned.

PACK: The PACK chunk is necessary when the bit length of the data is not a
multiple of 8, that is, not byte-aligned, and the user wishes to conserve
space by packing data items together.  PACK is simply a number - the
number of items to bit-pack before aligning on a byte. A PACK is in effect
for the remainder of its nested scope, or until overridden by a new
specification.  A STRU or ARRY is assumed to have a PACK of 1 by default -
it is not affected by PACKs in definitions above. A PACK of 0 means to
byte-align before processing the next definition. The PACK specifier
should be normalized.  For example, when packing a large array of 3-bit
numbers, PACK should be 8 since 3*8 = 24. In this case 8 is the smallest
PACK number which aligns on a byte naturally.

DTYP: The DataType is the most interesting chunk, as it attempts to define
every conceivable type of numeric data with 32 bits.  The 32 bits are
broken down into three fields, 1) the size in bits, 2) the Class, and 3)
SubClass. The Class makes the most major distinction, separating integers
from floating point numbers from Binary Coded Decimal and etc.  Within
each class is a SubClass, which gives the specific encoding used.
Finally, the Size tells what how much room the data occupies.  The basic
division of datatypes is given in the tree structure below.

    Class             SubClass     Size  Final Specific Type
    =====             ========     ====  ===================
     |
    Binary Unsigned - 0 ------------ 8   UByte
     |                              16   UWord
     |                              32   ULong
     |
    Binary Signed --- 0 ------------  8  Byte
     |                               16  Word
     |                               32  ULong
     |
    Real ------------Ieee38 -------- 32  Ieee Single Precision
     |                |
     |               Ieee308 ------- 64  Double Precision
     |                |              32  Truncated Double Precision
     |                |
     |               FFP ----------- 32  Motorola Fast Floating Point
     |
    Text ----------- Text0 --------- ??  Null-terminated text
     |                |
     |               CText --------- ??  Number of characters in first byte
     |                |
     |               FText --------- ??  Fixed length, space padded
     |
    BCD ------------ Nibble -------- ??
                      |
                     Character ----- ??

A design goal was to create a classification system which other people can
easily plug into.  Many data types are simply size variations on existing
data types.  For example, a 4-bit integer can be specified by giving the
size as four bits in the Signed Binary class.  Be aware that not all MTRX
readers may support your new type, but there will not be any type clashes
or ambiguities by following these rules.  If you have a truly unique Class
or SubClass, you will need to register it with Commodore to prevent
clashes.

A second design goal was to create a format which is easily decoded by
software.  By aligning fields on bytes, you have the option of redefining
the datatype as a structure, so as to avoid shifting when accessing the
fields.  Since the numbers are sequentially assigned, they are suitable as
array indicies, and may be optimized in a C switch statement.

A third design goal was allowing for naive and sophisticated readers. In
checking for a certain datatype, a naive reader can simply compare the
whole datatype with a small set of known types, which assumes that each
different Size defines a unique datatype.  Sophisticated readers will
consider the Class, SubClass and Size separately, so as to support
arbitrary size integers, and truncated Floating Point numbers, for example.

 *
 * MTRX ::= "FORM" #{ "MTRX" ARRY|STRU|DTYP BODY       } Matrix
 * ARRY ::= "ARRY" #{ ELEM [LOWR] [UPPR] [PACK] ARRY|STRU|DTYP } Array
 * STRU ::= "STRU" #{ FLDS ([PACK] ARRY|STRU|DTYP)*    } Structure
 * ELEM ::= "ELEM" #{ elements                         } Array elements
 * LOWR ::= "LOWR"  { VALU                             } Minimum limit
 * UPPR ::= "UPPR"  { VALU                             } Maximum limit
 * VALU ::=        #{ dtyp value                       } Value (in union)
 * dtyp ::=         { size, subclass, class            } Data Type (scalar)
 * DTYP ::= "DTYP" #{ dtyp                             }
 * FLDS ::= "FLDS" #{ number of fields                 } Number of Fields
 * PACK ::= "PACK" #{ units packed b4 byte alignment   } Packing
 * BODY ::= "BODY" #{ inner-first binary dump          } Data
 *
 *   [] means optional
 *   #  means the size of the unit following
 *   *  means one or more of
 *


A / IFF Third Party Public Form and Chunk Specification / PGTB.doc

Program traceback (SAS Institute)

FORM PGTB

Proposal:
        New IFF chunk type, to be named PGTB, meaning ProGram TraceBack.

 Format


PGTB.doc / Format

    'PGTB'       - chunk identifier
    length       - longword for length of chunk

    'FAIL'       - subfield giving environment at time of crash
    length       - longword length of subfield
    NameLen      - length of program name in longwords (BSTR)
    Name         - program name packed in longwords
    Environment  - copy of AttnFlags field from ExecBase,
                   gives type of processor, and existence of
                   math chip
    VBlankFreq   - copy of VBlankFrequency field from ExecBase
    PowerSupFreq - copy of PowerSupplyFrequency field from ExecBase
                   above fields may be used to determine whether
                   machine was PAL or NTSC
    Starter      - non-zero = CLI, zero = WorkBench
    GURUNum      - exception number of crash
    SegCount     - number of segments for program
    SegList      - copy of seglist for program
                   (Includes all seglist pointers, paired with
                    sizes of the segments)

    'REGS'       - register dump subfield
    length       - length of subfield in longwords
    GURUAddr     - PC at time of crash
    Flags        - copy of Condition Code Register
    DDump        - dump of data registers
    ADump        - dump of address registers

    'VERS'       - revision of program which created this file
    length       - length of subfield in longwords
    version      - main version of writing program
    revision     - minor revision level of writing program
    TBNameLen    - length of name of writing program
    TBName       - name of writing program packed in longwords (BSTR)

    'STAK'       - stack dump subfield
    length       - length of subfield in longwords
    (type)       - tells type of stack subfield, which can be any of
                   the following:

    -----------------------------------------------------------
    Info            - value 0
    StackTop        - address of top of stack
    StackPtr        - stack pointer at time of crash
    StackLen        - number of longwords on stack

    -----------------------------------------------------------
    Whole stack     - value 1
                      only used if total stack to be dumped is 8k
                      or less in size
    Stack           - dump of stack from current to top

    -----------------------------------------------------------
    Top 4k          - value 2
                      if stack used larger than 8k, this part
                      is a dump of the top 4k
    Stack           - dump of stack from top - 4k to top

    -----------------------------------------------------------
    Bottom 4k       - value 3
                      if stack used larger than 8k, this part
                      is a dump of the bottom 4k
    Stack           - dump of stack from current to current + 4k

In other words, we will dump a maximum of 8k of stack data.  This does NOT
mean the stack must be less than 8k in size to dump the entire stack, just
that the amount of stack USED be less than 8k.

    'UDAT'       - Optional User DATa chunk.  If the user assigns
                   a function pointer to the label "_ONGURU", the
                   catcher will call this routine prior to closing
                   the SnapShot file, passing one parameter on the
                   stack - an AmigaDOS file pointer to the SnapShot
                   file.  Spec for the _ONGURU routine:

                         void <function name>(fp)
                         long fp;

                   In other words, your routine must be of type 'void'
                   and must take one parameter, an AmigaDOS file
                   handle (which AmigaDOS wants to see as a LONG).
    length       - length of the UserDATa chunk, calculated after the
                   user routine terminates.


A / IFF Third Party Public Form and Chunk Specification / PRSP.doc

DPaint IV perspective move form (EA)

Submitted by Lee Taran

/* --------------------------------------------------------------------
   IFF Information:
       PRSP ::= "FORM" # {"PSRP" MOVE }
       MOVE ::= "MOVE" # { MoveState  }
 * -------------------------------------------------------------------- */

    typedef struct {
       BYTE reserved;        /* initialize to 0 */
       BYTE moveDir;         /* 0 = from point  1 = to point  */
       BYTE recordDir;       /* 0 = FORWARD,    1 = STILL, 2 = BACKWARD */
       BYTE rotationType;    /* 0 = SCREEN_RELATIVE, 1 = BRUSH_RELATIVE */
       BYTE translationType; /* 0 = SCREEN_RELATIVE, 1 = BRUSH_RELATIVE */
       BYTE cyclic;          /* 0 = NO, 1 = YES */
       SHORT distance[3];    /* x,y,z distance displacement */
       SHORT angle[3];       /* x,y,z rotation angles */
       SHORT nframes;        /* number of frames to move */
       SHORT easeout;        /* number of frames to ease out */
       SHORT easein;         /* number of frames to ease in */
       } MoveState;


A / IFF Third Party Public Form and Chunk Specification / RGBN-RGB8.doc

RGB image forms, Turbo Silver (Impulse)

                    FORM RGBN and FORM RGB8
            -----------------------

RGBN and RGB8 files are used in Impulse's Turbo Silver and Imagine. They
are almost identical to FORM ILBM's except for the BODY chunk and slight
differences in the BMHD chunk.

A CAMG chunk IS REQUIRED.

The BMHD chunk specfies the number of bitplanes as 13 for type RGBN and 25
for type RGB8, and the compression type as 4.

The FORM RGBN uses 12 bit RGB values, and the FORM RGB8 uses 24 bit RGB
values.

The BODY chunk contains RGB values, a "genlock" bit, and repeat counts. In
Silver, when "genlock" bit is set, a "zero color" is written into the
bitplanes for genlock video to show through. In Diamond and Light24
(Impulse 12 & 24 bit paint programs), the genlock bit is ignored if the
file is loaded as a picture (and the RGB color is used instead), and if
the file is loaded as a brush the genlock bit marks pixels that are not
part of the brush.

For both RGBN and RGB8 body chunks, each RGB value always has a repeat
count.  The values are written in different formats depending on the
magnitude of the repeat count.

 RGBN BODY Chunk
 RGB8 Body Chunk
 Sample BODY Code


RGBN-RGB8.doc / RGBN BODY Chunk

For each RGB value, a WORD (16-bits) is written: with the 12 RGB bits in
the MSB (most significant bit) positions; the "genlock" bit next; and then
a 3 bit repeat count. If the repeat count is greater than 7, the 3-bit
count is zero, and a BYTE repeat count follows.  If the repeat count is
greater than 255, the BYTE count is zero, and a WORD repeat count follows.
Repeat counts greater than 65536 are not supported.


RGBN-RGB8.doc / RGB8 Body Chunk

For each RGB value, a LONG-word (32 bits) is written: with the 24 RGB bits
in the MSB positions; the "genlock" bit next, and then a 7 bit repeat
count.

In a previous version of this document, there appeared the following line:

"If the repeat count is greater than 127, the same rules apply as in the
RGBN BODY."

But Impulse has never written more than a 7 bit repeat count, and when
Imagine and Light24 were written, they didn't support reading anything but
7 bit counts.


RGBN-RGB8.doc / Sample BODY Code

    if(!count) {
            if (Rgb8) {
                    fread (&w, 4, 1, RGBFile);
                    lock = w & 0x00000080;
                    rgb = w >> 8;
                    count = w & 0x0000007f;
            } else {
                    w = (UWORD) getw (RGBFile);
                    lock = w & 8;
                    rgb = w >> 4;
                    count = w & 7;
            }
            if (!count)
                    if (!(count = (UBYTE) getc (RGBFile)))
                            count = (UWORD) getw (RGBFile);
    }

The pixels are scanned from left to right across horizontal lines,
processing from top to bottom.  The (12 or 24 bit) RGB values are stored
with the red bits as the MSB's, the green bits next, and the blue bits as
the LSB's.

Special note:  As of this writing (Sep 88), Silver does NOT support
anything but black for color zero.


A / IFF Third Party Public Form and Chunk Specification / SAMP.doc

Sampled sound format

                    IFF FORM "SAMP" Sampled Sound

 Date:   Dec 3,1989
 From:   Jim Fiore and Jeff Glatt, dissidents

The form "SAMP" is a file format used to store sampled sound data in some
ways like the current standard, "8SVX". Unlike "8SVX", this new format is
not restricted to 8 bit sample data. There can be more than one waveform
per octave, and the lengths of different waveforms do not have to be
factors of 2. In fact, the lengths (waveform size) and playback mapping
(which musical notes each waveform will "play") are independently
determined for each wave- form. Furthermore, this format takes into
account the MIDI sample dump stan- dard (the defacto standard for musical
sample storage), while also incorpo- rating the ability to store Amiga
specific info (for example, the sample data that might be sent to an audio
channel which is modulating another channel).

Although this form can be used to store "sound effects" (typically oneShot
sounds played at a set pitch), it is primarily intended to correct the
many deficiencies of the "8SVX" form in regards to musical sampling.
Because the emphasis is on musical sampling, this format relies on the
MIDI (Musical Instrument Digital Interface) method of describing "sound
events" as does virtually all currently manufactured, musical samplers. In
addition, it at- tempts to incorporate features found on many professional
music samplers, in anticipation that future Amiga models will implement 16
bit sampling, and thus be able to achieve this level of performance.
Because this format is more complex than "8SVX", programming examples to
demonstrate the use of this format have been included in both C and
assembly. Also, a library of func- tions to read and write SAMP files is
available, with example applications.

SEMANTICS: When MIDI literature talks about a sample, usually it means a
collection of many sample points that make up what we call a "wave".

 Similarities and Differences from the 8SVX Form
 The SAMP Header
 The MHDR Chunk
 The NAME Chunk
 The BODY Chunk
 Structure of an Individual Sample Point
 The Waveheader Explained
 MIDI Velocity vs. Amiga Channel Volume
 An EGpoint (Envelope Generator)
 Additional User Data Section
 Converting Midi Sample Dump to SAMP
 Interpreting the Playmode
 Making A Transpose Table
 Making the Velocity Table
 The Instrument Type
 The Order of the Chunks
 Filename Conventions
 Why Does Anyone Need Such a Complicated File?


SAMP.doc / Similarities and Differences from the 8SVX Form

Like "8SVX", this new format uses headers to separate the various sections
of the sound file into chunks. Some of the chunks are exactly the same
since there wasn't a need to improve them. The chunks that remain
unchanged are as follows:

   "(c) "
   "AUTH"
   "ANNO"

Since these properties are all described in the original "8SVX" document,
please refer to that for a description of these chunks and their uses.
Like the "8SVX" form, none of these chunks are required to be in a sound
file. If they do appear, they must be padded out to an even number of
bytes.

Furthermore, two "8SVX" chunks no longer exist as they have been incorpo-
rated into the "BODY" chunk. They are:

   "ATAK"
   "RLSE"

Since each wave can be completely different than the other waves in the
sound file (one wave might be middle C on a piano, and another might be a
snare drum hit), it is necessary for each wave to have its own envelope
description, and name.

The major changes from the "8SVX" format are in the "MHDR", "NAME", and
"BODY" chunks.


SAMP.doc / The SAMP Header

At the very beginning of a sound file is the "SAMP" header. This is used
to determine if the disk file is indeed a SAMP sound file. It's attributes
are as follows:

    #define ID_SAMP MakeID('S','A','M','P')

In assembly, this looks like:

    CNOP 0,2  ;word-align

SAMP         dc.b  'SAMP'
sizeOfChunks dc.l  [sizes of all subsequent chunks summed]


SAMP.doc / The MHDR Chunk

The required "MHDR" chunk immediately follows the "SAMP" header and
consists of the following components:

    #define ID_MHDR MakeID('M','H','D','R')

      /* MHDR size is dependant on the size of the imbedded PlayMap. */

       typedef struct{
        UBYTE NumOfWaves, /* The number of waves in this file */
          Format,         /* # of ORIGINAL significant bits from 8-28 */
          Flags,          /* Various bits indicate various functions */
          PlayMode,       /* determines play MODE of the PlayMap */
          NumOfChans,
          Pad,
          PlayMap[128*4], /* a map of which wave numbers to use for
                           each of 128 possible Midi Notes. Default to 4 */
        } MHDRChunk;

The PlayMap is an array of bytes representing wave numbers. There can be a
total of 255 waves in a "SAMP" file. They are numbered from 1 to 255. A
wave number of 0 is reserved to indicate "NO WAVE". The Midi Spec 1.0
designates that there are 128 possible note numbers (pitches), 0 to 127.
The size of an MHDR's PlayMap is determined by (NumOfChans * 128). For
example, if NumOfChans = 4, then an MHDR's PlayMap is 512 bytes. There are
4 bytes in the PlayMap for EACH of the 128 Midi Note numbers. For example,
the first 4 bytes in PlayMap pertain to Midi Note #0. Of those 4 bytes,
the first byte is the wave number to play back on Amiga audio channel 0.
The second byte is the wave number to play back on Amiga audio channel 1,
etc. In this way, a single Midi Note Number could simultaneously trigger a
sound event on each of the 4 Amiga audio channels. If NumOfChans is 1,
then the PlayMap is 128 bytes and each midi note has only 1 byte in the
PlayMap. The first byte pertains to midi note #0, the second pertains to
midi note #1, etc. In this case, a player program might elect to simply
play back the PlayMap wave number on any available amiga audio channel. If
NumOfChans = 0, then there is no imbedded PlayMap in the MHDR, no midi
note assignments for the waves, and an application should play back waves
on any channel at their default sampleRates.

In effect, the purpose of the PlayMap array is to determine which (if any)
waves are to be played back for each of the 128 possible Midi Note
Numbers. Usually, the MHDR's NumOfChans will be set to 4 since the Amiga
has 4 audio channels. For the rest of this document, the NumOfChans is
assumed to be 4.

As mentioned, there can be a total of 255 waves in a "SAMP" file, numbered
from 1 to 255. A PlayMap wave number of 0 is reserved to indicate that NO
WAVE number should be played back. Consider the following example:   The
first 4 bytes of PlayMap are  1,3,0,200.

If a sample playing program receives (from the serial port or another task
perhaps) Midi Note Number 0, the following should occur:

  1) The sampler plays back wave 1 on Amiga audio channel
     number 0 (because the first PlayMap byte is 1).
  2) The sampler plays back wave 3 on Amiga audio channel
     number 1 (because the second PlayMap byte is 3).
  3) The sampler does not effect Amiga audio channel 2 in
     any way (because the third PlayMap byte is a 0).
  4) The sampler plays back wave 200 on Amiga audio channel
     number 4 (because the fourth PlayMap byte is 200).

(This assumes INDEPENDANT CHANNEL play MODE to be discussed later in this
 document.)

All four of the PlayMap bytes could even be the same wave number. This
would cause that wave to be output of all 4 Amiga channels simultaneously.

NumOfWaves is simply the number of waves in the sound file.

Format is the number of significant bits in every sample of a wave. For
example, if Format = 8, then this means that the sample data is an 8 bit
format, and that every sample of the wave can be expressed by a single
BYTE. (A 16 bit sample would need a WORD for every sample point).

Each bit of the Flags byte, when set, means the following:

Bit #0 -
   File continued on another disc. This might occur if the SAMP file
   was too large to fit on 1 floppy. The accepted practice (as incor-
   porated by Yamaha's TX sampler and Casio's FZ-1 for example) is to
   dump as much as possible onto one disc and set a flag to indicate
   that more is on another disc's file. The name of the files must
   be the related. The continuation file should have its own SAMP header
   MHDR, and BODY chunks. This file could even have its continuation
   bit set, etc. Never chop a sample wave in half. Always close the
   file on 1 disc after the last wave which can be completely saved.
   Resume with the next wave within the BODY of the continuation file.
   Also, the NumOfWaves in each file's BODY should be the number saved
   on that disc (not the total number in all combined disk files).
   See the end of this document for filename conventions.

In C, here is how the PlayMap is used when receiving a midi note-on event:

   MapOffset = (UBYTE) MidiNoteNumber * numOfChans;
   /* MidiNoteNumber is the received note number (i.e. the second byte of
     a midi note-on event. numOfChans is from the SAMP MHDR. */
   chan0waveNum = (UBYTE) playMap[MapOffset];
   chan1waveNum = (UBYTE) playMap[MapOffset+1];
   chan2waveNum = (UBYTE) playMap[MapOffset+2];
   chan3waveNum = (UBYTE) playMap[MapOffset+3];

   if (chan0waveNum != 0)
   { /* get the pointer to wave #1's data, determine the values
        that need to be passed to the audio device, and play this
        wave on Amiga audio channel #0 (if INDEPENDANT PlayMode) */
   }

   /* do the same with the other 3 channel's wave numbers */

In assembly, the "MHDR" structure looks like this:

             CNOP 0,2
MHDR        dc.b 'MHDR'
sizeOfMHDR  dc.l [this is 6 + (NumOfChans * 128) ]
NumOfWaves  dc.b [a byte count of # of waves in the file]
Format      dc.b [a byte count of # of significant bits in a sample point]
Flags       dc.b [bit mask]
PlayMode    dc.b [play MODE discussed later]
NumOfChans  dc.b [# of bytes per midi note for PlayMap]
PlayMap     ds.b [128 x NumOfChans bytes of initialized values]

and a received MidiNoteNumber is interpreted as follows:

   moveq   #0,d0
   move.b  MidiNoteNumber,d0  ;this is the received midi note #
   bmi.s   Illegal_Number     ;exit, as this is an illegal midi note #
   moveq   #0,d1
   move.b  NumOfChans,d1
   mulu.w  d1,d0              ;MidiNoteNumber x NumOfChans
   lea     PlayMap,a0
   adda.l  d0,a0
   move.b  (a0)+,chan0waveNum
   move.b  (a0)+,chan1waveNum
   move.b  (a0)+,chan2waveNum
   move.b  (a0),chan3waveNum

   tst.b   chan0waveNum
   beq.s   Chan1
 ;Now get the address of this wave number's sample data, determine the
 ;values that need to be passed to the audio device, and output the wave's
 ;data on Amiga chan 0 (assuming INDEPENDANT PlayMode).

Chan1 tst.b chan1waveNum
      beq.s Chan2
 ;do the same for the other wave numbers, etc.


SAMP.doc / The NAME Chunk

   #define ID_NAME MakeID('N','A','M','E')

If a NAME chunk is included in the file, then EVERY wave must have a name.
Each name is NULL-terminated. The first name is for the first wave, and it
is immediately followed by the second wave's name, etc. It is legal for a
wave's name to be simply a NULL byte. For example, if a file contained 4
waves and a name chunk, the chunk might look like this:

              CNOP 0,2

   Name       dc.b 'NAME'
   sizeOfName dc.l 30
              dc.b 'Snare Drum',0  ;wave 1
              dc.b 'Piano 1',0     ;wave 2
              dc.b 'Piano A4',0    ;wave 3
              dc.b 0               ;wave 4
              dc.b 0

NAME chunks should ALWAYS be padded out to an even number of bytes. (Hence
the extra NULL byte in this example). The chunk's size should ALWAYS be
even consequently. DO NOT USE the typical IFF method of padding a chunk
out to an even number of bytes, but allowing an odd number size in the
header.


SAMP.doc / The BODY Chunk

The "BODY" chunk is CONSIDERABLY different than the "8SVX" form. Like all
chunks it has an ID.

    #define ID_BODY MakeID('B','O','D','Y')

Every wave has an 80 byte waveHeader, followed by its data. The waveHeader
structure is as follows:

    typedef struct {
      ULONG  WaveSize;    /* total # of BYTES in the wave (MUST be even) */
      UWORD  MidiSampNum; /* ONLY USED for Midi Dumps */
      UBYTE  LoopType,    /* ONLY USED for Midi Dumps */
      InsType;            /* Used for searching for a certain instrument */
      ULONG  Period,      /* in nanoseconds at original pitch */
      Rate,               /* # of samples per second at original pitch */
      LoopStart,          /* an offset in BYTES (from the beginning of the
                             of the wave) where the looping portion of the
                               wave begins. Set to WaveSize if no loop. */
      LoopEnd;            /* an offset in BYTES (from the beginning of the
                             of the wave) where the looping portion of the
                             wave ends. Set to WaveSize if no loop. */
      UBYTE  RootNote,    /* the Midi Note # that plays back orig. pitch */
      VelStart;           /* 0 = NO velocity effect, 128 =
                                  negative direction, 64 = positive
                                  direction (it must be one of these 3) */
      UWORD VelTable[16]; /* contains 16 successive offset values
                                 in BYTES from the beginning of the wave */

     /* The ATAK and RLSE segments contain an EGPoint[] piece-wise
        linear envelope just like 8SVX. The structure of an EGPoint[]
        is the same as 8SVX. See that document for details. */

      ULONG  ATAKsize,    /* # of BYTES in subsequent ATAK envelope.
                                If 0, then no ATAK data for this wave. */
      RLSEsize,           /* # of BYTES in subsequent RLSE envelope
                                If 0, then no RLSE envelope follows */

     /* The FATK and FRLS segments contain an EGPoint[] piece-wise
        linear envelope for filtering purposes. This is included in
        the hope that future Amiga audio will incorporate a VCF
        (Voltage Controlled Filter). Until then, if you are doing any
        non-realtime digital filtering, you could store info here. */

     sizeOfFATK,          /* # of BYTES in FATK segment */
     sizeOfFRLS,          /* # of BYTES in FRLS segment */

     USERsize;            /*   # of BYTES in the following data
                                 segment (not including USERtype).
                                 If zero, then no user data */
     UWORD  USERtype;     /* See explanation below. If USERsize
                                = 0, then ignore this. */

    /* End of the waveHeader. */

    /* The data for any ATAK, RLSE, FATK, FRLS, USER, and the actual wave
       data for wave #1 follows in this order:
       Now list each EGPoint[] (if any) for the VCA's
       (Voltage Controlled Amp) attack portion.
       Now list each EGPoint[] for the VCA's (Voltage Controlled Amp)
       release portion.
       List EGPoints[] (if any) for FATK.
       List EGPoints[] if any for FRLS */

   /*  Now include the user data here if there is any.Just pad it out to an
   even number of bytes and have USERsize reflect that. Finally,here is the
   actual sample data for the wave. The size (in BYTES) of this data is
   WaveSize. It MUST be padded out to an even number of bytes. */

    } WaveFormInfo;

 /* END OF WAVE #1 */

 /* The waveHeader and data for the next wave would now follow. It is
    the same form as the first wave */

In assembly,  the BODY chunk looks like this:

           CNOP 0,2
BodyHEADER dc.b 'BODY'
sizeOfBody dc.l  [total bytes in the BODY chunk not counting 8 byte header]

   ; Now for the first wave
WaveSize       dc.l  ;[total # of BYTES in this wave (MUST be even)]
MidiSampNum    dc.w  ;[from Midi Sample Dump]  ; ONLY USED for Midi Dumps
LoopType       dc.b  ;[0 or 1]                 ; ONLY USED for Midi Dumps
InsType        dc.b  0
Period         dc.l  ;[period in nanoseconds at original pitch]
Rate           dc.l  ;[# of samples per second at original pitch]
LoopStart      dc.l    ;[an offset in BYTES (from the beginning of the
                       ; of the wave) to where the looping
                       ; portion of the wave begins.]
LoopEnd        dc.l    ;[an offset in BYTES (from the beginning of the
                       ; of the wave) to where the looping
                       ; portion of the wave ends]
RootNote       dc.b    ;[the Midi Note # that plays back original pitch]
VelStart       dc.b    ;[0, 64, or 128]
VelTable       dc.w    ;[first velocity offset]
               dc.w    ;[second velocity offset]...etc
               ds.w 14 ;...for a TOTAL of 16 velocity offsets

ATAKsize       dc.l  ;# of BYTES in subsequent ATAK envelope.
                     ;If 0, then no ATAK data for this wave.
RLSEsize       dc.l  ;# of BYTES in subsequent RLSE envelope
                     ;If 0, then no RLSE data
FATKsize       dc.l  ;# of BYTES in FATK segment
FRLSsize       dc.l  ;# of BYTES in FRLS segment
USERsize       dc.l  ;# of BYTES in the following User data
                     ;segment (not including USERtype).
                     ;If zero, then no user data
USERtype       dc.w  ; See explanation below. If USERsize
                  ; = 0, then ignore this.

  ;Now include the EGpoints[] (data) for the ATAK if any
  ;Now the EGpoints for the RLSE
  ;Now the EGpoints for the FATK
  ;Now the EGpoints for the FLSR
  ;Now include the user data here if there is any. Just pad
  ;it out to an even number of bytes.
  ;After the userdata (if any) is the actual sample data for
  ;the wave. The size (in BYTES) of this segment is WaveSize.
  ;It MUST be padded out to an even number of bytes.

  ; END OF WAVE #1


SAMP.doc / Structure of an Individual Sample Point

Even though the next generation of computers will probably have 16 bit
audio, and 8 bit sampling will quickly disappear, this spec has sizes
expressed in BYTES. (ie LoopStart, WaveSize, etc.) This is because each
successive address in RAM is a byte to the 68000, and so calculating
address offsets will be much easier with all sizes in BYTES. The Midi
sample dump, on the other hand, has sizes expressed in WORDS. What this
means is that if you have a 16 bit wave, for example, the WaveSize is the
total number of BYTES, not WORDS, in the wave.

Also, there is no facility for storing a compression type. This is because
sample data should be stored in linear format (as per the MIDI spec).
Currently, all music samplers, regardless of their internal method of
playing sample data must transmit and expect to receive sample dumps in a
linear format. It is up to each device to translate the linear format into
its own compression scheme. For example, if you are using an 8 bit
compression scheme that yields a 14 bit linear range, you should convert
each sample data BYTE to a decom- pressed linear WORD when you save a
sound file. Set the MHDR's Format to 14. It is up to the application to do
its own compression upon loading a file. The midi spec was set up this way
because musical samplers need to pass sample data between each other, and
computers (via a midi interface). Since there are almost as many data
compression schemes on the market as there are musical products, it was
decided that all samplers should expect data received over midi to be in
LINEAR format. It seems logical to store it this way on disc as well.
Therefore, any software program "need not know" how to decompress another
software program's SAMP file. When 16 bit sampling is eventually
implemented there won't be much need for compression on playback anyway.
The continuation Flag solves the problem of disc storage as well.

Since the 68000 can only perform math on BYTES, WORDS, or LONGS, it has
been decided that a sample point should be converted to one of these sizes
when saved in SAMP as follows:

 ORIGINAL significant bits          SAMP sample point size

          8                                 BYTE
          9 to 16                           WORD
          17 to 28                          LONG

Furthermore, the significant bits should be left-justified since it is
easier to perform math on the samples.

So, for example, an 8 bit sample point (like 8SVX) would be saved as a
BYTE with all 8 bits being significant. The MHDR's Format = 8. No
conversion is necessary.

A 12 bit sample point should be stored as a WORD with the significant bits
being numbers 4 to 15. (i.e shift the 12-bit WORD 4 places to the left).
Bits 0, 1, 2 and 3 may be zero (unless some 16-bit math was performed and
you wish to save these results). The MHDR's Format = 12. In this way, the
sample may be loaded and manipulated as a 16-bit wave, but when
transmitted via midi, it can be converted back to 12 bits (rounded and
shifted right by 4).

A 16 bit sample point would be saved as a WORD with all 16 bits being
significant. The MHDR's Format = 16. No conversion is necessary.


SAMP.doc / The Waveheader Explained

The WaveSize is, as stated, the number of BYTES in the wave's sample
table. If your sample data consisted of the following 8 bit samples:

   BYTE  100,-90,80,-60,30,35,40,-30,-35,-40,00,12,12,10

then WaveSize = 14. (PAD THE DATA OUT TO AN EVEN NUMBER OF BYTES!)

The MidiSampNum is ONLY used to hold the sample number received from a
MIDI Sample Dump. It has no bearing on where the wave should be placed in
a SAMP file. Also, the wave numbers in the PlayMap are between 1 to 255,
with 1 being the number of the first wave in the file. Remember that a
wave number of 0 is reserved to mean "no wave to play back". Likewise, the
LoopType is only used to hold info from a MIDI sample dump.

The InsType is explained at the end of this document. Often it will be set
to 0.

The RootNote is the Midi Note number that will play the wave back at it's
original, recorded pitch. For example, consider the following excerpt of a
PlayMap:

   PlayMap  {2,0,0,4       /* Midi Note #0 channel assignment */
             4,100,1,0     /* Midi Note #1    "        "  */
             1,4,0,0       /* Midi Note #2    "        "  */
             60,2,1,1...}  /* Midi Note #3    "        "  */

Notice that Midi Notes 0, 1, and 2 are all set to play wave number 4 (on
Amiga channels 3, 0, and 1 respectively). If we set wave 4's RootNote = 1,
then receiving Midi Note number 1 would play back wave 4 (on Amiga channel
0) at it's original pitch. If we receive a Midi Note number 0, then wave 4
would be played back on channel 3) a half step lower than it's original
pitch. If we receive Midi Note number 2, then wave 4 would be played (on
channel 1) a half step higher than it's original pitch. If we receive Midi
Note number 3, then wave 4 would not be played at all because it isn't
specified in the PlayMap bytes for Midi Note number 3.

The Rate is the number of samples per second of the original pitch. For
example, if Rate = 20000, then to play the wave at it's original pitch,
the sampling period would be:

   (1/20000)/.279365 = .000178977

   #define AUDIO_HARDWARE_FUDGE .279365

where .279365 is the Amiga Fudge Factor (a hardware limitation). Since the
Amiga needs to see the period in terms of microseconds, move the decimal
place to the right 6 places and our sampling period = 179 (rounded to an
integer).

In order to play the wave at higher or lower pitches, one would need to
"transpose" this period value. By specifying a higher period value, the
Amiga will play back the samples slower, and a lower pitch will be
achieved. By specifying a lower period value, the amiga will play back the
sample faster, and a higher pitch will be achieved. By specifying this
exact period, the wave will be played back exactly "as it was recorded
(sampled)". ("This period is JUST RIGHT!", exclaimed GoldiLocks.) Later, a
method of transposing pitch will be shown using a "look up" table of
periods. This should prove to be the fastest way to transpose pitch,
though there is nothing in the SAMP format that compels you to do it this
way.

The LoopStart is a BYTE offset from the beginning of the wave to where the
looping portion of the wave begins.  For example, if SampleData points to
the start of the wave, then SampleData + LoopStart is the start address of
the looping portion.  In 8SVX, the looping portion was referred to as
repeatHiSamples.  The data from the start of the wave up to the start of
the looping portion is the oneShot portion of the wave.  LoopEnd is a BYTE
offset from the beginning of the wave to where the looping portion ends.
This might be the very end of the wave in memory, or perhaps there might
be still more data after this point.  You can choose to ignore this
"trailing" data and play back the two other portions of the wave just like
an 8SVX file (except that there are no other interpolated octaves of this
wave).

VelTable contains 16 BYTE offsets from the beginning of the wave.  Each
successive value should be greater (or equal to) the preceding value.  If
VelStart = POSITIVE (64), then for each 8 increments in Midi Velocity
above 0, you move UP in the table, add this offset to the wave's beginning
address (start of oneShot), and start playback at that address. Here is a
table relating received midi note-on velocity vs. start playback address
for POSITIVE VelStart.  SamplePtr points to the beginning of the sample.

    If midi velocity = 0, then don't play a sample, this is a note off
    If midi velocity = 1 to 7, then start play at SamplePtr + VelTable[0]
    If midi velocity = 8 to 15, then start at SamplePtr + VelTable[1]
    If midi velocity = 16 to 23, then start at SamplePtr + VelTable[2]
    If midi velocity = 24 to 31, then start at SamplePtr + VelTable[3]
    If midi velocity = 32 to 39, then start at SamplePtr + VelTable[4]
    If midi velocity = 40 to 47, then start at SamplePtr + VelTable[5]
    If midi velocity = 48 to 55, then start at SamplePtr + VelTable[6]
    If midi velocity = 56 to 63, then start at SamplePtr + VelTable[7]
    If midi velocity = 64 to 71, then start at SamplePtr + VelTable[8]
    If midi velocity = 72 to 79, then start at SamplePtr + VelTable[9]
    If midi velocity = 80 to 87, then start at SamplePtr + VelTable[10]
    If midi velocity = 88 to 95, then start at SamplePtr + VelTable[11]
    If midi velocity = 96 to 103, then start at SamplePtr + VelTable[12]
    If midi velocity = 104 to 111, then start at SamplePtr + VelTable[13]
    If midi velocity = 112 to 119, then start at SamplePtr + VelTable[14]
    If midi velocity = 120 to 127, then start at SamplePtr + VelTable[15]

We don't want to specify a scale factor and use integer division to find
the sample start.  This would not only be slow, but also, it could never
be certain that the resulting sample would be a zero crossing if the start
point is calcu- lated "on the fly".  The reason for having a table is so
that the offsets can be be initially set on zero crossings via an editor.
This way, no audio "clicks" is guaranteed.  This table should provide
enough resolution.

If VelStart = NEGATIVE (128), then for each 8 increments in midi velocity,
you start from the END of VelTable, and work backwards.  Here is a table
for NEGATIVE velocity start.

    If midi velocity = 0, then don't play a sample, this is a note off
    If midi velocity = 1 to 7, then start play at SamplePtr + VelTable[15]
    If midi velocity = 8 to 15, then start at SamplePtr + VelTable[14]
    If midi velocity = 16 to 23, then start at SamplePtr + VelTable[13]
    If midi velocity = 24 to 31, then start at SamplePtr + VelTable[12]
    If midi velocity = 32 to 39, then start at SamplePtr + VelTable[11]
    If midi velocity = 40 to 47, then start at SamplePtr + VelTable[10]
    If midi velocity = 48 to 55, then start at SamplePtr + VelTable[9]
    If midi velocity = 56 to 63, then start at SamplePtr + VelTable[8]
    If midi velocity = 64 to 71, then start at SamplePtr + VelTable[7]
    If midi velocity = 72 to 81, then start at SamplePtr + VelTable[6]
    If midi velocity = 80 to 87, then start at SamplePtr + VelTable[5]
    If midi velocity = 88 to 95, then start at SamplePtr + VelTable[4]
    If midi velocity = 96 to 103, then start at SamplePtr + VelTable[3]
    If midi velocity = 104 to 111, then start at SamplePtr + VelTable[2]
    If midi velocity = 112 to 119, then start at SamplePtr + VelTable[1]
    If midi velocity = 120 to 127, then start at SamplePtr + VelTable[0]

In essence, increasing midi velocity starts playback "farther into" the
wave for POSITIVE VelStart. Increasing midi velocity "brings the start
point back" toward the beginning of the wave for NEGATIVE VelStart.

If VelStart is set to NONE (0), then the wave's playback start should not
be affected by the table of offsets.

What is the use of this feature?  As an example, when a snare drum is hit
with a soft volume, its initial attack is less pronounced than when it is
struck hard.  You might record a snare being hit hard. By setting VelStart
to a NEGATIVE value and setting up the offsets in the Table, a lower midi
velocity will "skip" the beginning samples and thereby tend to soften the
initial attack.  In this way, one wave yields a true representation of its
instrument throughout its volume range. Furthermore, stringed and plucked
instruments (violins, guitars, pianos, etc) exhibit different attacks at
different volumes. VelStart makes these kinds of waves more realistic via
a software implementation.  Also, an application program can allow the
user to enable/ disable this feature. See the section "Making the Velocity
Table" for info on how to best choose the 16 table values.


SAMP.doc / MIDI Velocity vs. Amiga Channel Volume

The legal range for Midi Velocity bytes is 0 to 127. (A midi velocity of 0
should ALWAYS be interpreted as a note off).

The legal range for Amiga channel volume is 0 to 64. Since this is half of
the midi range, a received midi velocity should be divided by 2 and add 1
(but only AFTER checking for a received midi velocity of 0).

An example of how to implement a received midi velocity in C:

    If ( ReceivedVelocity != 0 && ReceivedVelocity < 128 )
    {   /* the velocity byte of a midi message */
        If (velStart != 0)
        {
            tableEntry = ReceivedVelocity / 8;
            If (velStart == 64)
            {    /* Is it POSITIVE */
                 startOfWave = SamplePtr + velTable[tableEntry];
                             /* ^where to find the sample start point */
            }
            If (velStart == 128)
            {    /* Is it NEGATIVE */
                 startOfWave = SamplePtr + velTable[15 - tableEntry];
            }
            volume = (receivedVelocity/2 + 1;  /* playback volume */
            /* Now playback the wave */
        }
    }

In assembly,

    lea      SampleData,a0        ;the start addr of the sample data
    moveq    #0,d0
    move.b   ReceivedVelocity,d0  ;the velocity byte of a midi message
    beq      A_NoteOff            ;If zero, branch to a routine to
                                  ;process a note-off message.

    bmi      Illegal_Vol          ;exit if received velocity > 127
    ;---Check for velocity start feature ON, and direction
    move.b   VelStart,d1
    beq.s    Volume               ;skip the velocity offset routine if 0
    bmi.s    NegativeVel          ;is it NEGATIVE? (128)

    ;---Positive velocity offset
    move.l   d0,d1                ;duplicate velocity
    lsr.b    #3,d1                ;divide by 8
    add.b    d1,d1                ;x 2 because we need to fetch a word
    lea      VelTable,a1     ;start at table's HEAD
    adda.l   d1,a1                ;go forward
    move.w   (a1),d1              ;get the velocity offet
    adda.l   d1,a0          ;where to start actual playback
    bra.s    Volume

  NegativeVel:
    ;---Negative velocity offset
    move.l   d0,d1                ;duplicate velocity
    lsr.b    #3,d1                ;divide by 8
    add.b    d1,d1                ;x 2 because we need to fetch a word
    lea      VelTable+30,a1  ;start at table's END
    suba.l   d1,a1                ;go backwards
    move.w   (a1),d1              ;get the velocity offset
    adda.l   d1,a0          ;where to start actual playback

    ;---Convert Midi velocity to an Amiga volume
  Volume  lsr.b    #1,d0          ;divide by 2
          addq.b   #1,d0          ;an equivalent Amiga volume

   ;---Now a0 and d0 are the address of sample start, and volume


SAMP.doc / An EGpoint (Envelope Generator)

A single EGpoint is a 6 byte structure as follows:

EGpoint1: dc.w ;[the duration in milliseconds]
          dc.l ;[the volume factor - fixed point,16 bits to the left of the
               ;decimal point and 16 to the right.]

The volume factor is a fixed point where 1.0 ($00010000) represents the
MAXIMUM volume possible. (i.e. No volume factor should exceed this value.)
The last EGpoint in the ATAK is always the sustain point. Each EG's volume
is determined from 0.0, not as a difference from the previous EG's volume.
I hope that this clears up the ambiguity in the original 8SVX document.
So, to recreate an amplifier envelope like this:

                                /\
                               /  \____
                              /        \
                             /          \

                             |  | |   |  |
                              1  2  3   4

Stages 1, 2, and 3 would be in the ATAK data, like so:

;Stage 1
dc.w  100       ;take 100ms
dc.l  $00004000 ;go to this volume
dc.w  100
dc.l  $00008000
dc.w  100
dc.l  $0000C000
dc.w  100
dc.l  $00010000 ;the "peak" of our attack is full volume
;Stage 2
dc.w  100
dc.l  $0000C000 ;back off to this level
dc.l  100
dc.l  $00008000 ;this is where we hold (SUSTAIN) until the note
                ;is turned off. (We are now holding at stage 3)

Now the RLSE data would specify stage 4 as follows:
dc.w  100
dc.l  $00004000
dc.w  100
dc.l  $00000000 ;the volume is 0


SAMP.doc / Additional User Data Section

There is a provision for storing user data for each wave. This is where an
application can store Amiga hardware info, or other, application specific
info. The waveHeader's USERtype tells what kind of data is stored. The
current types are:

   #define SPECIFIC 0
   #define VOLMOD   1
   #define PERMOD   2
   #define LOOPING  3

   SPECIFIC (0) - application specific data. It should be stored
                  in a format that some application can immediately
                  recognize. (i.e. a "format within" the SAMP format)
                  If the USERtype is SPECIFIC, and an application
                  doesn't find some sort of header that it can re-
                  cognize, it should conclude that this data was
                  put there by "someone else", and ignore the data.

   VOLMOD (1) -   This data is for volume modulation of an Amiga
                  channel as described by the ADKCON register. This
                  data will be sent to the modulator channel of the
                  channel set to play the wave.

   PERMOD (2) -   This data is for period modulation of an Amiga
                  channel as described by the ADKCON register. This
                  data will be sent to the modulator channel of the
                  channel set to play the wave.

   LOOPING (3) -  This contains more looping points for the sample.
                  There are some samplers that allow more than just
                  one loop (Casio products primarily). Additional
                  looping info can be stored in this format:

                 UWORD numOfLoops;  /* number of loop points to follow */

                 ULONG StartLoop1,  /* BYTE offset from the beginning of
                                      the sample to the start of loop1 */
                 EndLoop1,          /* BYTE offset from the beginning of
                                      the sample to the end of loop1 */

                 StartLoop2,        /* ...etc */


SAMP.doc / Converting Midi Sample Dump to SAMP

SEMANTICS: When MIDI literature talks about a sample, usually it means a
collection of many sample points that make up what we call "a wave".
Therefore, a Midi Sample Dump sends all the sample data that makes up ONE
wave. A SAMP file is designed to hold up to 255 of these waves (midi
dumps).

The Midi Sample Dump specifies playback rate only in terms of a sample
PERIOD in nanoseconds. SAMP also expresses playback in terms of samples
per second (frequency). The Amiga needs to see its period rounded to the
nearest microsecond. If you take the sample period field of a Midi sample
Dump (the 8th, 9th, and 10th bytes of the Dump Header LSB first) which we
will call MidiSamplePer, and the Rate of a SAMP file, here is the
relationship:

   Rate = (1/MidiSamplePer) x 10E9

Also the number of samples (wave's length) in a Midi Sample Dump (the
11th, 12th, and 13th bytes of the Dump header) is expressed in WORDS.
SAMP's WaveSize is expressed in the number of BYTES. (For the incredibly
stupid), the relationship is:

   WaveSize = MidiSampleLength x 2

A Midi sample dump's LoopStart point and LoopEnd point are also in WORDS
as versus the SAMP equivalents expressed in BYTES.

A Midi sample dump's sample number can be 0 to 65535. A SAMP file can hold
up to 255 waves, and their numbers in the playmap must be 1 to 255. (A
single, Midi Sample Dump only sends info on one wave.) When recieving a
Midi Sample Dump, just store the sample number (5th and 6th bytes of the
Dump Header LSB first) in SAMP's MidiSampNum field. Then forget about this
number until you need to send the wave back to the Midi instrument from
whence it came.

A Midi Dump's loop type can be forward, or forward/backward. Amiga
hardware supports forward only. You should store the Midi Dump's LoopType
byte here, but ignore it otherwise until/unless Amiga hardware supports
"reading audio data" in various ways. If so, then the looptype is as
follows:

    forward = 0, backward/forward = 1

A Midi Dump's sample format byte is the same as SAMP's.


SAMP.doc / Interpreting the Playmode

PlayMode specifies how the bytes in the PlayMap are to be interpreted.
Remember that a PlayMap byte of 0 means "No Wave to Play".

    #define INDEPENDANT 0
    #define MULTI       1
    #define STEREO      2
    #define PAN         3

PlayMode types:

 INDEPENDANT(0)-The wave #s for a midi note are to be output on
                Amiga audio channels 0, 1, 2, and 3 respectively.
                If the NumOfChans is < 4, then only use that many channels.

 MULTI      (1)-The first wave # (first of the PlayMap bytes) for a
                midi note is to be output on any free channel. The other
                wave numbers are ignored. If all four channels are in
                play, the application can decide whether to "steal" a
                channel.

 STEREO     (2)-The first wave # (first of the PlayMap bytes) is to be
                output of the Left stereo jack (channel 1 or 3) and if
                there is a second wave number (the second of the PlayMap
                bytes), it is to be output the Right jack (channel 2 or 4).
                The other wave numbers are ignored.

 PAN        (3)-This is just like STEREO except that the volume of wave 1
                should start at its initial volume (midi velocity) and
                fade to 0. At the same rate, wave 2 should start at 0
                volume and rise to wave #1's initial level. The net
                effect is that the waves "cross" from Left to Right in
                the stereo field. This is most effective when the wave
                numbers are the same. (ie the same wave) The application
                program should set the rate. Also, the application can
                reverse the stereo direction (ie Right to Left fade).

The most important wave # to be played back by a midi note should be the
first of the PlayMap bytes. If the NumOfChans > 1, the second PlayMap byte
should be a defined wave number as well (even if it is deliberately set to
the same value as the first byte). This insures that all 4 PlayModes will
have some effect on a given SAMP file. Also, an application should allow
the user to change the PlayMode at will. The PlayMode stored in the SAMP
file is only a default or initial set-up condition.


SAMP.doc / Making A Transpose Table

In order to allow a wave to playback over a range of musical notes, (+/-
semitones), its playback rate must be raised or lowered by a set amount.
From one semitone to the next, this set amount is by a factor of the 12th
root of 2 (assuming a western, equal-tempered scale). Here is a table that
shows what factor would need to be multiplied by the sampling rate in
order to transpose the wave's pitch.

    Pitch in relation to the Root     Multiply Rate by this amount
   -------------------------------   ------------------------------
     DOWN 6     semitones              0.5
     DOWN 5 1/2 semitones              0.529731547
     DOWN 5     semitones              0.561231024
     DOWN 4 1/2 semitones              0.594603557
     DOWN 4     semitones              0.629960525
     DOWN 3 1/2 semitones              0.667419927
     DOWN 3     semitones              0.707106781
     DOWN 2 1/2 semitones              0.749153538
     DOWN 2     semitones              0.793700526
     DOWN 1 1/2 semitones              0.840896415
     DOWN 1     semitones              0.890898718
     DOWN 1/2   semitone               0.943874312
  ORIGINAL_PITCH                       1.0           /* rootnote's pitch */
     UP   1/2   semitone               1.059463094
     UP   1     semitones              1.122562048
     UP   1 1/2 semitones              1.189207115
     UP   2     semitones              1.259921050
     UP   2 1/2 semitones              1.334839854
     UP   3     semitones              1.414213562
     UP   3 1/2 semitones              1.498307077
     UP   4     semitones              1.587401052
     UP   4 1/2 semitones              1.681792830
     UP   5     semitones              1.781797436
     UP   5 1/2 semitones              1.887748625
     UP   6     semitones              2

For example, if the wave's Rate is 18000 hz, and you wish to play the wave
UP 1 semitone, then the playback rate is:

    18000 x 1.122562048 = 20206.11686 hz

The sampling period for the Amiga is therefore:

    (1/20206.11686)/.279365 = .000177151

and to send it to the Audio Device, it is rounded and expressed in micro-
seconds: 177

Obviously, this involves floating point math which can be time consuming
and impractical for outputing sound in real-time.  A better method is to
construct a transpose table that contains the actual periods already
calculated for every semitone.  The drawback of this method is that you
need a table for EVERY DIFFERENT Rate in the SAMP file.  If all the Rates
in the file happened to be the same, then only one table would be needed.
Let's assume that this is the case, and that the Rate = 18000 hz. Here is
a table containing enough entries to transpose the waves +/- 6 semitones.

  Pitch in relation to the Root     Amiga Period (assuming rate = 18000 hz)
  -----------------------------     ---------------------------------------
    Transposition_table[TRANS_TABLE_SIZE]={
    /* DOWN 6     semitones  */            398,
    /* DOWN 5 1/2 semitones  */            375,
    /* DOWN 5     semitones  */            354,
    /* DOWN 4 1/2 semitones  */            334,
    /* DOWN 4     semitones  */            316,
    /* DOWN 3 1/2 semitones  */            298,
    /* DOWN 3     semitones  */            281,
    /* DOWN 2 1/2 semitones  */            265,
    /* DOWN 2     semitones  */            251,
    /* DOWN 1 1/2 semitones  */            236,
    /* DOWN 1     semitones  */            223,
    /* DOWN 1/2   semitone   */            211,
    /* ORIGINAL_PITCH        */            199,    /* rootnote's pitch */
    /* UP   1/2   semitone   */            187,
    /* UP   1     semitones  */            177,
    /* UP   1 1/2 semitones  */            167,
    /* UP   2     semitones  */            157,
    /* UP   2 1/2 semitones  */            148,
    /* UP   3     semitones  */            141,
    /* UP   3 1/2 semitones  */            133,
     /* Since the minimum Amiga period = 127 the following
        are actually out of range. */
    /* UP   4     semitones  */            125,
    /* UP   4 1/2 semitones  */            118,
    /* UP   5     semitones  */            112,
    /* UP   5 1/2 semitones  */            105,
    /* UP   6     semitones  */            99   };

Let's assume that (according to the PlayMap) midi note #40 is set to play
wave number 3. Upon examining wave 3's structure, we discover that the
Rate = 18000, and the RootNote = 38. Here is how the Amiga sampling period
is calulated using the above 18000hz "transpose chart" in C:

   /* MidiNoteNumber is the received midi note's number (here 40) */

   #define ORIGINAL_PITCH     TRANS_TABLE_SIZE/2 + 1
  /* TRANS_TABLE_SIZE is the number of entries in the transposition table
     (dynamic, ie this can change with the application) */

  transposeAmount = (LONG) (MidiNoteNumber - rootNote);
                                             /* make it a SIGNED LONG */

  amigaPeriod     = Transposition_table[ORIGINAL_PITCH + transposeAmount];

In assembly, the 18000hz transpose chart and above example would be:

Table       dc.w  398
            dc.w  375
            dc.w  354
            dc.w  334
            dc.w  316
            dc.w  298
            dc.w  281
            dc.w  265
            dc.w  251
            dc.w  236
            dc.w  223
            dc.w  211
ORIGINAL_PITCH  dc.w  199   ; rootnote's pitch
            dc.w  187
            dc.w  177
            dc.w  167
            dc.w  157
            dc.w  148
            dc.w  141
            dc.w  133
 ; Since the minimum Amiga period = 127, the following
 ; are actually out of range.
            dc.w  125
            dc.w  118
            dc.w  112
            dc.w  105
            dc.w  99

  lea     ORIGINAL_PITCH,a0
  move.b  MidiNoteNumber,d0  ;the received note number
  sub.b   RootNote,d0        ;subtract the wave's root note
  ext.w   d0
  ext.l   d0                 ;make it a signed LONG
  add.l   d0,d0              ;x 2 in order to fetch a WORD
  adda.l  d0,a0
  move.w  (a0),d0            ;the Amiga Period (WORD)

Note that these examples don't check to see if the transpose amount is
beyond the number of entries in the transpose table. Nor do they check if
the periods in the table are out of range of the Amiga hardware.


SAMP.doc / Making the Velocity Table

The 16 entries in the velocity table should be within the oneShot portion
of the sample (ie not in the looping portion). THe first offset,
VelTable[0] should be set to zero (in order to play back from the
beginning of the data). The subsequent values should be increasing
numbers. If you are using a graphic editor, try choosing offsets that will
keep you within the initial attack portion of the wave. In practice, these
values will be relatively close together within the wave. Always set the
offsets so that when they are added to the sample start point, the
resulting address points to a sample value of zero (a zero crossing
point). This will eliminate pops and clicks at the beginning of the
playback.

In addition, the start of the wave should be on a sample with a value of
zero. The last sample of the oneShot portion and the first sample of the
looping portion should be approximately equal, (or zero points). The same
is true of the first and last samples of the looping portion. Finally, try
to keep the slopes of the end of the oneShot, the beginning of the
looping, and the end of the looping section, approximately equal. All this
will eliminate noise on the audio output and provide "seamless" looping.


SAMP.doc / The Instrument Type

Many SMUS players search for certain instruments by name.  Not only is
this slow (comparing strings), but if the exact name can't be found, then
it is very difficult and time-consuming to search for a suitable
replacement.  For this reason, many SMUS players resort to "default"
instruments even if these are nothing like the desired instruments. The
InsType byte in each waveHeader is meant to be a numeric code which will
tell an SMUS player exactly what the instrument is.  In this way, the SMUS
player can search for the correct "type" of instrument if it can't find
the desired name. The type byte is divided into 2 nibbles (4 bits for you
C programmers) with the low 4 bits representing the instrument "family" as
follows:

  1 = STRING, 2 = WOODWIND, 3 = KEYBOARD, 4 = GUITAR, 5 = VOICE,
  6 = DRUM1, 7 = DRUM2,  8 = PERCUSSION1, 9 = BRASS1, A = BRASS2,
  B = CYMBAL, C = EFFECT1, D = EFFECT2, E = SYNTH,
  F is undefined at this time

Now, the high nibble describes the particular type within that family.

For the STRING family, the high nibble is as follows:

  1 = VIOLIN BOW, 2 = VIOLIN PLUCK, 3 = VIOLIN GLISSANDO,
  4 = VIOLIN TREMULO, 5 = VIOLA BOW, 6 = VIOLA PLUCK, 7 = VIOLA GLIS,
  8 = VIOLA TREM, 9 = CELLO BOW, A = CELLO PLUCK, B = CELLO GLIS,
  C = CELLO TREM, D = BASS BOW, E = BASS PLUCK (jazz bass), F = BASS TREM

For the BRASS1 family, the high nibble is as follows:

  1 = BARITONE SAX, 2 = BARI GROWL, 3 = TENOR SAX, 4 = TENOR GROWL,
  5 = ALTO SAX, 6 = ALTO GROWL, 7 = SOPRANO SAX, 8 = SOPRANO GROWL,
  9 = TRUMPET, A = MUTED TRUMPET, B = TRUMPET DROP, C = TROMBONE,
  D = TROMBONE SLIDE, E = TROMBONE MUTE

For the BRASS2 family, the high nibble is as follows:

  1 = FRENCH HORN, 2 = TUBA, 3 = FLUGAL HORN, 4 = ENGLISH HORN

For the WOODWIND family, the high nibble is as follows:

  1 = CLARINET, 2 = FLUTE, 3 = PAN FLUTE, 4 = OBOE, 5 = PICCOLO,
  6 = RECORDER, 7 = BASSOON, 8 = BASS CLARINET, 9 = HARMONICA

For the KEYBOARD family, the high nibble is as follows:

  1 = GRAND PIANO, 2 = ELEC. PIANO, 3 = HONKYTONK PIANO, 4 = TOY PIANO,
  5 = HARPSICHORD, 6 = CLAVINET, 7 = PIPE ORGAN, 8 = HAMMOND B-3,
  9 = FARFISA ORGAN, A = HARP

For the DRUM1 family, the high nibble is as follows:

  1 = KICK, 2 = SNARE, 3 = TOM, 4 = TIMBALES, 5 = CONGA HIT,
  6 = CONGA SLAP, 7 = BRUSH SNARE, 8 = ELEC SNARE, 9 = ELEC KICK,
  A = ELEC TOM, B = RIMSHOT, C = CROSS STICK, D = BONGO, E = STEEL DRUM,
  F = DOUBLE TOM

For the DRUM2 family, the high nibble is as follows:

  1 = TIMPANI, 2 = TIMPANI ROLL, 3 = LOG DRUM

For the PERCUSSION1 family, the high nibble is as follows:

  1 = BLOCK, 2 = COWBELL, 3 = TRIANGLE, 4 = TAMBOURINE, 5 = WHISTLE,
  6 = MARACAS, 7 = BELL, 8 = VIBES, 9 = MARIMBA, A = XYLOPHONE,
  B = TUBULAR BELLS, C = GLOCKENSPEIL

For the CYMBAL family, the high nibble is as follows:

  1 = CLOSED HIHAT, 2 = OPEN HIHAT, 3 = STEP HIHAT, 4 = RIDE,
  5 = BELL CYMBAL, 6 = CRASH, 7 = CHOKE CRASH, 8 = GONG, 9 = BELL TREE,
  A = CYMBAL ROLL

 For the GUITAR family, the high nibble is as follows:

  1 = ELECTRIC, 2 = MUTED ELECTRIC, 3 = DISTORTED, 4 = ACOUSTIC,
  5 = 12-STRING, 6 = NYLON STRING, 7 = POWER CHORD, 8 = HARMONICS,
  9 = CHORD STRUM, A = BANJO, B = ELEC. BASS, C = SLAPPED BASS,
  D = POPPED BASS, E = SITAR, F = MANDOLIN
  (Note that an acoustic picked bass is found in the STRINGS - Bass Pluck)

For the VOICE family, the high nibble is as follows:

  1 = MALE AHH, 2 = FEMALE AHH, 3 = MALE OOO, 4 = FEMALE OOO,
  5 = FEMALE BREATHY, 6 = LAUGH, 7 = WHISTLE

For the EFFECTS1 family, the high nibble is as follows:

  1 = EXPLOSION, 2 = GUNSHOT, 3 = CREAKING DOOR OPEN, 4 = DOOR SLAM,
  5 = DOOR CLOSE, 6 = SPACEGUN, 7 = JET ENGINE, 8 = PROPELLER,
  9 = HELOCOPTER, A = BROKEN GLASS, B = THUNDER, C = RAIN, D = BIRDS,
  E = JUNGLE NOISES, F = FOOTSTEP

For the EFFECTS2 family, the high nibble is as follows:

  1 = MACHINE GUN, 2 = TELEPHONE, 3 = DOG BARK, 4 = DOG GROWL,
  5 = BOAT WHISTLE, 6 = OCEAN, 7 = WIND, 8 = CROWD BOOS, 9 = APPLAUSE,
  A = ROARING CROWDS, B = SCREAM, C = SWORD CLASH, D = AVALANCE,
  E = BOUNCING BALL, F = BALL AGAINST BAT OR CLUB

For the SYNTH family, the high nibble is as follows:

  1 = STRINGS, 2 = SQUARE, 3 = SAWTOOTH, 4 = TRIANGLE, 5 = SINE, 6 = NOISE

So, for example if a wave's type byte was 0x26, this would be a SNARE
DRUM. If a wave's type byte is 0, then this means "UNKNOWN" instrument.


SAMP.doc / The Order of the Chunks

The SAMP header obviously must be first in the file, followed by the MHDR
chunk. After this, the ANNO, (c), AUTH and NAME chunks may follow in any
order, though none of these need appear in the file at all. The BODY chunk
must be last.


SAMP.doc / Filename Conventions

For when it becomes necessary to split a SAMP file between floppies using
the Continuation feature, the filenames should be related. The method is
the following:

The "root" file has the name that the user chose to save under. Subsequent
files have an ascii number appended to the name to indicate what sublevel
the file is in. In this way, a program can reload the files in the proper
order.

For example, if a user saved a file called "Gurgle", the first
continuation file should be named "Gurgle1", etc.


SAMP.doc / Why Does Anyone Need Such a Complicated File?

                 (or "What's wrong with 8SVX anyway?")
In a nutshell, 8SVX is not adequate for professional music sampling. First
of all, it is nearly impossible to use multi-sampling (utilizing several,
different samples of any instrument throughout its musical range). This
very reason alone makes it impossible to realistically reproduce a musical
in- strument, as none in existance (aside from an electronic organ) uses
inter- polations of a single wave to create its musical note range.

Also, stretching a sample out over an entire octave range does grotesque
(and VERY unmusical) things to such elements as the overtone structure,
wind/percussive noises, the instrument's amplitude envelope, etc. The 8SVX
format is designed to stretch the playback in exactly this manner.

8SVX ignores MIDI which is the de facto standard of musical data
transmission. 8SVX does not allow storing data for features that are
commonplace to pro- fessional music samplers. Such features are: velocity
sample start, separate filter and envelopes for each sample, separate
sampling rates, and various playback modes like stereo sampling and
panning.

SAMP attempts to remedy all of these problems with a format that can be
used by a program that simulates these professional features in software.
The format was inspired by the capabilities of the following musical
products:

    EMU's                 EMAX, EMULATOR
    SEQUENTIAL CIRCUIT's  PROPHET 2000, STUDIO 440
    ENSONIQ's             MIRAGE
    CASIO's               FZ-1
    OBERHEIM's            DPX
    YAMAHA                TX series

So why does the Amiga need the SAMP format? Because professional
musician's are buying computers. With the firm establishment of MIDI,
musician's are buying and using a variety of sequencers, patch editors,
and scoring programs. It is now common knowledge amoung professional
musicians that the Amiga lags far behind IBM clones, Macintosh, and Atari
ST computers in both music software and hardware support. Both Commodore
and the current crop of short- sighted 3rd party Amiga developers are
pigeon-holing the Amiga as "a video computer". It is important for music
software to exploit whatever capabili- ties the Amiga offers before the
paint and animation programs, genlocks, frame-grabbers, and video
breadboxes are the only applications selling for the Amiga. Hopefully,
this format, with the SAMP disk I/O library will make it possible for
Amiga software to attain the level of professionalism that the other
machines now boast, and the Amiga lacks.


A / IFF Third Party Public Form and Chunk Specification / TDDD.doc

3-D rendering data, Turbo Silver (Impulse)

                               FORM TDDD
                               ---------
FORM TDDD is used by Impulse's Turbo Silver 3.0 for 3D rendering data.
TDDD stands for "3D data description".  The files contain object and
(optionally) observer data.

Turbo Silver's successor, "Imagine", uses an upgraded FORM TDDD when it
reads/writes object data.

Currently, in "standard IFF" terms, a FORM TDDD has only two chunk types:
an INFO chunk describing observer data;  and an OBJ chunk describing an
object heirarchy.  The INFO chunk appears only in Turbo Silver's "cell"
files, and the OBJ chunk appears in both "cell" files and "object" files.

The FORM has an (optional) INFO chunk followed by some number of OBJ
chunks.  (Note:  OBJ is followed by a space - ckID = "OBJ ")

The INFO and OBJ chunks, in turn, are made up of smaller chunks with the
standard IFF structure:  <ID> <data-size> <data>.

The INFO "sub-chunks" are relatively straightforward to interpret.

The OBJ "sub-chunks" support object heirarchies, and are slightly more
difficult to interpret.  Currently, there are 3 types of OBJ sub-chunks:
an EXTR chunk, describing an "external" object in a seperate file; a DESC
chunk, describing one node of a heirarchy; and a TOBJ chunk marking the
end of a heirarchy chain.  For each DESC chunk, there must be a
corresponding TOBJ chunk.  And an EXTR chunk is equivalent to a DESC/TOBJ
pair.

In Turbo Silver and Imagine, the structure of the object heirarchy is as
follows.  There is a head object, and its (sexist) brothers. Each brother
may have child objects.  The children may have grandchildren, and so on.
The brother nodes are kept in a doubly linked list, and each node has a
(possibly NULL) pointer to a doubly linked "child" list. The children
point to the "grandchildren" lists, and so on.  (In addition, each node
has a "back" pointer to its parent).

Each of the "head" brothers is written in a seperate OBJ chunk, along with
all its descendants.  The descendant heirarchy is supported as follows:

    for each node of a doubly linked list,

    1)  A DESC chunk is written, describing its object.
    2)  If it has children, steps 1) to 3) are performed
            for each child.
    3)  A TOBJ chunk is written, marking the end of the children.

For "external" objects, steps 1) to 3) are not performed, but an EXTR
chunk is written instead.  (This means that an external object cannot have
children unless they are stored in the same "external" file).

The TOBJ sub-chunks have zero size -- and no data.  The DESC and EXTR
sub-chunks are made up of "sub-sub-chunks", again, with the standard IFF
structure:  <ID> <data-size> <data>.

( "External" objects were used by Turbo Silver to allow a its "cell" data
files to refer to an "object" data file that is "external" to the cell
file.  Imagine abandons the idea of individual cell files, and deals only
in TDDD "object" files. Currently, Imagine does not support EXTR chunks in
TDD files.)

Reader software WILL FOLLOW the standard IFF procedure of skipping over
any un-recognized chunks -- and "sub-chunks" or "sub-sub-chunks". The
<data-size> field indicates how many bytes to skip.  In addition it WILL
OBSERVE the IFF rule that an odd <data-size> may appear, in which case the
corredponding <data> field will be padded at the end with one extra byte
to give it an even size.

 Now, on with the details


TDDD.doc / Now, on with the details

First, there are several numerical fields appearing in the data,
describing object positions, rotation angles, scaling factors, etc. They
are stored as "32-bit fractional" numbers, such that the true number is
the 32-bit number divided by 65536.  So as an example, the number 3.14159
is stored as (hexadecimal) $0003243F.  This allows the data to be
independant of any particular floating point format. And it (actually) is
the internal format used in the "integer" version of Turbo Silver.
Numbers stored in this format are called as "FRACT"s below.

Second, there are several color (or RGB) fields in the data. They are
always stored as three UBYTEs representing the red, green and blue
components of the color.  Red is always first, followed by green, and then
blue.  For some of the data chunks, Turbo Silver reads the color field
into the 24 LSB's of a LONGword.  In such cases, the 3 RGB bytes are
preceded by a zero byte in the file.

The following "typedef"s are used below:

    typedef LONG    FRACT;                /* 4 bytes */
    typedef UBYTE   COLOR[3];             /* 3 bytes */

    typedef struct vectors {
        FRACT X;          /* 4 bytes */
        FRACT Y;          /* 4 bytes */
        FRACT Z;          /* 4 bytes */
    } VECTOR;             /* 12 bytes total */

    typedef struct matrices {
        VECTOR I;         /* 12 bytes */
        VECTOR J;         /* 12 bytes */
        VECTOR K;         /* 12 bytes */
    } MATRIX;             /* 36 bytes total */

    typedef struct _tform {
        VECTOR r;         /* 12 bytes - position */
        VECTOR a;         /* 12 bytes - x axis */
        VECTOR b;         /* 12 bytes - y axis */
        VECTOR c;         /* 12 bytes - z axis */
        VECTOR s;         /* 12 bytes - size */
    } TFORM;              /*  60 bytes total */

The following structure is used in generating animated cells from a single
cell.  It can be attached to an object or to the camera.  It is also used
for Turbo Silver's "extrude along a path" feature.  (It is ignored and
forgotten by Imagine.)

    typedef struct story {
        UBYTE  Path[18];  /* 18 bytes */
        VECTOR Translate; /* 12 bytes */
        VECTOR Rotate;    /* 12 bytes */
        VECTOR Scale;     /* 12 bytes */
        UWORD  info;      /*  2 bytes */
    } STORY;              /* 56 bytes total */

The Path[] name refers to a named object in the cell data. The path object
should be a sequence of points connected with edges.  The object moves
from the first point of the first edge, to the last point of the last
edge.  The edge ordering is important.  The path is interpolated so that
the object always moves an equal distance in each frame of the animation.
If there is no path the Path[] field should be set to zeros. The Translate
vector is not currently used. The Rotate "vector" specifies rotation
angles about the X, Y, and Z axes. The Scale vector specfies X,Y, and Z
scale factors. The "info" word is a bunch of bit flags:

    ABS_TRA    0x0001    - translate in world coorinates (not used)
    ABS_ROT    0x0002    - rotation in world coorinates
    ABS_SCL    0x0004    - scaling in world coorinates
    LOC_TRA    0x0010    - translate in local coorinates (not used)
    LOC_ROT    0x0020    - rotation in local coorinates
    LOC_SCL    0x0040    - scaling in local coorinates
    X_ALIGN    0x0100    - (not used)
    Y_ALIGN    0x0200    - align Y axis to path's direction
    Z_ALIGN    0x0400    - (not used)
    FOLLOW_ME  0x1000    - children follow parent on path

 DESC sub-sub-chunks
 DESC notes
 INFO sub-chunks
 EXTR sub-sub-chunks


Details / DESC sub-sub-chunks

NAME - size 18

    BYTE    Name[18];       ; a name for the object.

    Used for camera tracking, specifying story paths, etc.

SHAP - size 4

    WORD    Shape;          ; number indicating object type
    WORD    Lamp;           ; number indicating lamp type

    Lamp numbers are composed of several bit fields:

            Bits 0-1:
        0 - not a lamp
        1 - like sunlight
        2 - like a lamp - intensity falls off with distance.
        3 - unused/reserved

            Bits 2:
                    0 - non-shadow-casting light
                    4 - shadow-casting light

            Bits 3-4:
        0  - Spherical light source
        8  - Cylindrical light source.
        16 - Conical light source.
        24 - unused/reserved

    Shape numbers are:

        0 - Sphere
        1 - Stencil         ; not supported by Imagine
        2 - Axis            ; custom objects with points/triangles
        3 - Facets          ; illegal - for internal use only
        4 - Surface         ; not supported by Imagine
        5 - Ground

    Spheres have thier radius set by the X size parameter.
    Stencils and surfaces are plane-parallelograms, with one
    point at the object's position vector; one side lying along
    the object's X axis with a length set by the X size; and
    another side starting from the position vector and going
    "Y size" units in the Y direction and "Z size" units in
    the X direction.  A ground object is an infinte plane
    perpendicular to the world Z axis.  Its Z coordinate sets
    its height, and the X and Y coordinates are only relevant
    to the position of the "hot point" used in selecting the
    object in the editor.  Custom objects have points, edges
    and triangles associated with them.  The size fields are
    relevant only for drawing the object axes in the editor.
    Shape number 3 is used internally for triangles of custom
    objects, and should never appear in a data file.

POSI - size 12

    VECTOR  Position;       ; the object's position.

    Legal coordinates are in the range -32768 to 32767 and 65535/65536.
    Currently, the ray-tracer only sees objects in the -1024 to 1024
    range.  Light sources, and the camera may be placed outside that
    range, however.

AXIS - size 36

    VECTOR  XAxis;
    VECTOR  YAxis;
    VECTOR  ZAxis;

    These are direction vectors for the object coordinate system.
    They must be "orthogonal unit vectors" - i.e. the sum of the
    squares of the vevtor components must equal one (or close to it),
    and the vectors must be perpendicular.

SIZE - size 12

    VECTOR  Size;

    See SHAP chunk above.  The sizes are used in a variety of ways
    depending on the object shape.  For custom objects, they are
    the lengths of the coordinate axes drawn in the editor.  If the
    object has its "Quickdraw" flag set, the axes lengths are also
    used to set the size of a rectangular solid that is drawn rather
    than drawing all the points and edges.

PNTS - size 2 + 12 * point count

    UWORD   PCount;         ; point count
    VECTOR  Points[];       ; points

    This chunk has all the points for custom objects.  The are
    refered to by thier position in the array.

EDGE - size 4 + 4 * edge cout

    UWORD   ECount;         ; edge count
    UWORD   Edges[][2];     ; edges

    This chunk contins the edge list for custom objects.
    The Edges[][2] array is pairs of point numbers that
    are connected by the edges.  Edges are refered to by thier
    position in the Edges[] array.

FACE - size 2 + 6 * face count

    UWORD   TCount;         ; face count
    UWORD   Connects[][3];  ; faces

    This chunk contains the triangle (face) list for custom objects.
    The Connects[][3] array is triples of edge numbers that are
    connected by triangles.

PTHD - size 2 + 6 * axis count - Imagine only

    UWORD   ACount;         ; axis count
    TFORM   PData[][3];     ; axis data

    This chunk contains the axis data for Imagine "path" objects.
    The PData array contains a TFORM structure for each point along
    the path.  The "Y size" item for the last point on the path tells
    whether the path is closed or not.  Zero means closed, non-zero
    means open.  Otherwise the Y size field is the distance along
    the path to the next path point/axis.

COLR - size 4
REFL - size 4
TRAN - size 4
SPC1 - size 4 - Imagine only

    BYTE    pad;            ; pad byte - must be zero
    COLOR   col;            ; RGB color

    These are the main object RGB color, and reflection, transmission
    and specularity coefficients.

CLST - size 2 + 3 * count
RLST - size 2 + 3 * count
TLST - size 2 + 3 * count

    UWORD   count;          ; count of colors
    COLOR   colors[];       ; colors

    These are the color, reflection and transmission coefficients
    for each face in custom objects. The count should match the
    face count in the FACE chunk. The ordering corresponds to the
    face order.

TPAR - size 64 - not written by Imagine - see TXT1 below

    FRACT   Params[16];     ; texture parameters

    This is the list of parameters for texture modules when
    texture mapping is used.
TXT1 - variable size - Imagine only

    This chunk contains texture data when texture mapping is used.

    UWORD   Flags;          ; texture flags:
                            ;    1 - TXTR_CHILDREN - apply to child objs
    TFORM   TForm;          ; local coordinates of texture axes.
    FRACT   Params[16];     ; texture parameters
    UBYTE   PFlags[16];     ; parameter flags (currently unused)
    UBYTE   Length;         ; length of texture file name
    UBYTE   Name[Length];   ; texture file name (not NULL terminated)
    UBYTE   pad;            ; (if necessary to make an even length)

BRS1 - variable size - Imagine only (version 1.0)
BRS2 - variable size - Imagine only (version 1.1)

    UWORD   Flags;          ; brush type:
                            ;    0 - Color
                            ;    1 - Reflection
                            ;    2 - Filter
                            ;    3 - Altitude
    UWORD   WFlags;         ; brush wrapping flags:
                            ;    1   WRAP_X        - wrap type
                            ;    2   WRAP_Z        - wrap type
                            ;    4   WRAP_CHILDREN - apply to children
                            ;    8   WRAP_REPEAT   - repeating brush
                            ;    16  WRAP_FLIP     - flip with repeats
    TFORM   TForm;          ; local coordinates of brush axes.
    (UWORD   FullScale;)    ; full scale value
    (UWORD   MaxSeq;)       ; highest number for sequenced brushes
    UBYTE   Length;         ; length of brush file name
    UBYTE   Name[Length];   ; brush file name (not NULL terminated)
    UBYTE   pad;            ; (if necessary to make an even length)

    The FullScale and MaxSeq items are in BRS2 chunks only.

SURF - size 5 - not written by Imagine

    BYTE    SProps[5];      ; object properties

    This chunk contains object (surface) properties used by Turbo Silver.

    SProps[0] - PRP_SURFACE ; surface type
                            ;   0 - normal
                            ;   4 - genlock
                            ;   5 - IFF brush
    SProps[1] - PRP_BRUSH   ; brush number (if IFF mapped)
    SProps[2] - PRP_WRAP    ; IFF brush wrapping type
                            ;   0 - no wrapping
                            ;   1 - wrap X
                            ;   2 - wrap Z
                            ;   3 - wrap X and Z
    SProps[3] - PRP_STENCIL ; stencil number for stencil objects
    SProps[4] - PRP_TEXTURE ; texture number if texture mapped

MTTR - size 2 - not written by Imagine - see PRP1 chunk.

    UBYTE   Type;           ; refraction type (0-4)
    UBYTE   Index;          ; custom index of refraction

    This chunk contains refraction data for transparent or glossy
    objects.  If the refraction type is 4, the object has a "custom"
    refractive index stored in the Index field.  The Index field is
    100 * (true index of refraction - 1.00) -- so it must be in the
    range of 1.00 to 3.55.  The refraction types 0-3 specify 0) Air
    - 1.00, 1) Water - 1.33, 2) Glass - 1.67 or 3) Crystal 2.00.

SPEC - size 2 - not written by Imagine - see SPC1 above.

    UBYTE   Specularity;    ; range of 0-255
    UBYTE   Hardness;       ; specular exponent (0-31)

    This chunk contains specular information.  The Specularity
    field is the amount of specular reflection -- 0 is none,
    255 is fully specular.  The "specular exponent" controls
    the "tightness" of the specular spots.  A value of zero
    gives broad specular spots and a value of 31 gives smaller
    spots.

PRP0 - size 6 - not written by Imagine

    UBYTE   Props[6];       ; more object properties

    This chunk contains object properties that programs other
    than Turbo Silver might support.

    Props[0] - PRP_BLEND    ; blending factor (0-255)
    Props[1] - PRP_SMOOTH   ; roughness factor
    Props[2] - PRP_SHADE    ; shading on/off flag
    Props[3] - PRP_PHONG    ; phong shading on/off flag
    Props[4] - PRP_GLOSSY   ; glossy on/off flag
    Props[5] - PRP_QUICK    ; Quickdraw on/off flag

    The blending factor controls the amount of dithering used
    on the object - 255 is fully dithered.  The roughness factor
    controls how rough the object should appear - 0 is smooth, 255
    is max roughness.  The shading flag is interpreted differently
    depending on whether the object is a light source or not.  For
    light sources, it sets the light to cast shadows or not.  For
    normal objects, if the flag is set, the object is always
    considered as fully lit - i.e., it's color is read directly
    from the object (or IFF brush), and is not affected by light
    sources.  The phong shading is on by default - a non-zero value
    turns it off.  The glossy flag sets the object to be glossy or
    not.  If the object is glossy, the "transmit" colors and the
    index of refraction control the amount of "sheen".  The glossy
    feature is meant to simulate something like a wax coating
    on the object with the specified index of refraction. The
    trasmission coefficients control how much light from the
    object makes it through the wax coating.
    The Quickdraw flag, if set, tells the editor not to draw
    all the points and edges for the object, but to draw a
    rectanglular solid centered at the object position, and
    with sizes detemined by the axis lengths.

PRP1 - size 8 - Imagine only

    UBYTE   IProps[8];       ; more object properties

    This chunk contains object properties that programs other
    than Imagine might support.

    IProps[0] - IPRP_DITHER   ; blending factor (0-255)
    IProps[1] - IPRP_HARD     ; hardness factor (0-255)
    IProps[2] - IPRP_ROUGH    ; roughness factor (0-255)
    IProps[3] - IPRP_SHINY    ; shinyness factor (0-255)
    IProps[4] - IPRP_INDEX    ; index of refraction
    IProps[5] - IPRP_QUICK    ; flag - Quickdraw on/off
    IProps[6] - IPRP_PHONG    ; flag - Phong shading on/off
    IProps[7] - IPRP_GENLOCK  ; flag - Genlock on/off

    The blending factor controls the amount of dithering used
    on the object - 255 is fully dithered.
    The hardness factor controls how tight the specular spot
    should be - 0 is a big soft spot, 255 is a tight hot spot
    The roughness factor controls how rough the object should
    appear - 0 is smooth, 255 is max roughness.
    The shiny factor in interaction with the object's filter
    values controls how shiny the object appears.  Setting it
    to anything but zero forces the object to be non-transparent
    since then the filter values are used in the shiny (reflection)
    calculations.  A value of 255 means maximum shinyness.

INTS - size 4 - not written by Imagine

    FRACT   Intensity;      ; light intensity

    This is the intensity field for light source objects.
    an intensity of 255 for a sun-like light fully lights
    object surfaces which are perpendicular to the direction
    to the light source.  For lamp-like light sources, the
    necessary intensity will depend on the distance to the light.

INT1 - size 12 - Imagine only

    VECTOR  Intensity;      ; light intensity

    This is like INTS above, but has seperate R, G & B intensities.

STRY - size 56 - not written by Imagine

    STORY   story;          ; a story structure for the object.

    The story structure is described above.

ANID - size 64 - Imagine only

    LONG    Cellno;         ; cell number
    TFORM   TForm;          ; object position/axes/size in that cell.

    For Imagine's "Cycle" objects, within EACH DESC chunk in the
    file - that is, for each object of the group, there will be
    a series of ANID chunks.  The cell number sequences of each
    part of the must agree with the sequence for the head object,
    and the first cell number must be zero.

FORD - size 56 + 12 * PC - Imagine only

    WORD    NumC;           ; number of cross section points
    WORD    NumF;           ; number of slices
    WORD    Flags;          ; orientation flag
    WORD    pad;            ; reserved
    MATRIX  TForm;          ; object rotation/scaling transformation
    VECTOR  Shift;          ; object translation
    VECTOR  Points[PC];     ; "Forms" editor points

    For Imagine's "Forms" objects, the "PNTS" chunk above is not
    written out, but this structure is written instead.  The point
    count is PC = NumC + 4 * NumF.  The object's real points are
    then calculated from these using a proprietary algorithm.
    The tranformation parameters above allow the axes of the
    real object be moved around relative to the "Forms" points.


Details / DESC notes

Again, most of these fields are optional, and defaults are supplied.
However, if there is a FACE chunk, there must also be a CLST chunk, an
RLST chunk and a TLST chunk -- all with matching "count" fields. The SHAP
chunk is not optional.

Defaults are:  Colors set to (240,240,240); reflection and transmission
coefficients set to zero; illegal shape; no story or special surface
types; position at (0,0,0); axes aligned to the world axes; size fields
all 32.0; intensity at 300; no name; no points/edges or faces; texture
parameters set to zero; refraction type 0 with index 1.00; specular,
hardness and roughness set to zero; blending at 255; glossy off; phong
shading on; not a light source; not brightly lit;

In Imagine, defaults are the same, but with colors (255,255,255).


Details / INFO sub-chunks

BRSH - size 82

    WORD    Number;        ; Brush number (between 0 and 7)
    CHAR    Filename[80];  ; IFF ILBM filename

    There may be more than one of these.

STNC - size 82

    Same format as BRSH chunk.

TXTR - size 82

    Same format as BRSH chunk.  The Filename field is the name of
    a code module that can be loaded with LoadSeg().

OBSV - size 28

    VECTOR  Camera;         ; Camera position
    VECTOR  Rotate;         ; Camera rotation angles
    FRACT   Focal;          ; Camera focal length

    This tells where the camera is, how it is aimed, and its
    focal length.  The rotation angles are in degrees, and specify
    rotations around the X, Y, and Z axes.  The camera looks down
    its own Y axis, with the top of the picture in the direction of
    the Z axis.  If the rotation angles are all zero, its axes
    are aligned with the world coordinate axes.  The rotations are
    performed in the order ZXY about the camera axes.  A positive
    angle rotates Y toward Z, Z toward X, and X toward Y for
    rotations about the X, Y, and Z axes respectively.  To
    understand the focal length, imagine a 320 x 200 pixel
    rectangle perpendicular to, and centered on the camera's
    Y axis.  Any objects in the infinite rectangular cone defined
    by the camera position and the 4 corners of the rectangle will
    appear in the picture.
OTRK - size 18

    BYTE    Trackname[18];

    This chunk specifies the name of an object that the camera is
    "tracked" to.  If the name is NULL, the camera doesn't track
    Otherwise, if the object is moved inside Turbo Silver, the
    camera will follow it.

OSTR - size 56

    STORY   CStory;         ; a STORY structure for the camera

    The story structure is defined above.

FADE - size 12

    FRACT   FadeAt;         ; distance to start fade
    FRACT   FadeBy;         ; distance of total fade
    BYTE    pad;            ; pad byte - must be zero
    COLOR   FadeTo;         ; RGB color to fade to

SKYC - size 8

    BYTE    pad;            ; pad byte - must be zero
    COLOR   Horizon;        ; horizon color
    BYTE    pad;            ; pad byte - must be zero
    COLOR   Zenith;         ; zenith color

AMBI - size 4

    BYTE    pad;            ; pad byte - must be zero
    COLOR   Ambient;        ; abmient light color

GLB0 - size 8

    BYTE    Props[8];       ; an array of 8 "global properties" used
                            ; by Turbo Silver.

    Props[0] - GLB_EDGING       ; edge level (globals requester)
    Props[1] - GLB_PERTURB      ; perturbance (globals requester)
    Props[2] - GLB_SKY_BLEND    ; sky blending factor (0-255)
    Props[3] - GLB_LENS         ; lens type (see below)
    Props[4] - GLB_FADE         ; flag - Sharp/Fuzzy focus (globals)
    Props[5] - GLB_SIZE         ; "apparant size" (see below)
    Props[6] - GLB_RESOLVE      ; resolve depth (globals requester)
    Props[7] - GLB_EXTRA        ; flag - genlock sky on/off

    The edging and perturbance values control the heuristics in ray
    tracing.  The sky blending factor is zero for no blending, and 255
    for full blending.  The lens type is a number from 0-4, corresponding
    to the boxes in the "camera" requester, and correspond to 0) Manual,
    1) Wide angle, 2) Normal, 3) Telephoto, and 4) Custom.  It is used
    in setting the camera's focal length if the camera is tracked to an
    object.  The Sharp/Fuzzy flag turns the "fade" feature on and off -
    non-zero means on.  The "apparant size" parameter is 100 times the
    "custom size" parameter in the camera requester.  And is used to set
    the focal length for a custom lens.  The "resolve depth" controls
    the number of rays the ray tracer will shoot for a single pixel.
    Each reflective/refractive ray increments the depth counter, and
    the count is never allowed to reach the "resolve depth".  If both
    a reflective and a refractive ray are traced, each ray gets its
    own version of the count - so theoretically, a resolve depth of
    4 could allow much more than 4 rays to be traced.  The "genlock
    sky" flag controls whether the sky will be colored, or set to
    the genlock color (color 0 - black) in the final picture.

All of the INFO sub-chunks are optional, as is the INFO chunk.
Default values are supplied if the chunks are not present.  The
defaults are:  no brushes, stencils, or textures defined; no story
for the camera; horizon and zenith and ambient light colors set
to black; fade color set to (80,80,80);  un-rotated, un-tracked
camera at (-100, -100, 100); and global properties array set to
[30, 0, 0, 0, 0, 100, 8, 0].


Details / EXTR sub-sub-chunks

MTRX - size 60

    VECTOR  Translate;      ; translation vector
    VECTOR  Scale;          ; X,Y and Z scaling factors
    MATRIX  Rotate;         ; rotation matrix

    The translation vector is i world coordinates.
    The scaling factors are with respect to local axes.
    The rotation matrix is with respect to the world axes,
    and it should be a "unit matrix".
    The rotation is such that a rotated axis's X,Y, and Z
    components are the dot products of the MATRIX's I,J,
    and K vectors with the un-rotated axis vector.

LOAD - size 80

    BYTE    Filename[80];   ; the name of the external file

    This chunk contains the name of an external object file.
    The external file should be a FORM TDDD file.  It may contain
    an any number of objects possibly grouped into heirarchy(ies).

Both of these chunks are required.


A / IFF Third Party Public Form and Chunk Specification / WORD.doc

ProWrite document format (New Horizons)

TITLE:  WORD  (word processing FORM used by ProWrite)

IFF FORM / CHUNK DESCRIPTION

Form/Chunk IDs:
   FORM   WORD
   Chunks FONT,COLR,DOC,HEAD,FOOT,PCTS,PARA,TABS,PAGE,TEXT,FSCC,PINF

Date Submitted: 03/87
Submitted by:   James Bayless - New Horizons Software, Inc.

 FORM
 Chunks


WORD.doc / FORM

FORM ID:  WORD

FORM Purpose:  Document storage (supports color, fonts, pictures)

FORM Description:

This include file describes FORM WORD and its Chunks

   /*
    *      IFF Form WORD structures and defines
    *      Copyright (c) 1987 New Horizons Software, Inc.
    *
    *      Permission is hereby granted to use this file in any and all
    *      applications.  Modifying the structures or defines included
    *      in this file is not permitted without written consent of
    *      New Horizons Software, Inc.
    */

   #include ":IFF/ILBM.h"        /* Makes use of ILBM defines */

   #define ID_WORD      MakeID('W','O','R','D')      /* Form type */

   #define ID_FONT      MakeID('F','O','N','T')      /* Chunks */
   #define ID_COLR      MakeID('C','O','L','R')
   #define ID_DOC       MakeID('D','O','C',' ')
   #define ID_HEAD      MakeID('H','E','A','D')
   #define ID_FOOT      MakeID('F','O','O','T')
   #define ID_PCTS      MakeID('P','C','T','S')
   #define ID_PARA      MakeID('P','A','R','A')
   #define ID_TABS      MakeID('T','A','B','S')
   #define ID_PAGE      MakeID('P','A','G','E')
   #define ID_TEXT      MakeID('T','E','X','T')
   #define ID_FSCC      MakeID('F','S','C','C')
   #define ID_PINF      MakeID('P','I','N','F')

   /*
    *   Special text characters for page number, date, and time
    *   Note:  ProWrite currently supports only PAGENUM_CHAR, and only in
    *      headers and footers
    */

   #define PAGENUM_CHAR   0x80
   #define DATE_CHAR      0x81
   #define TIME_CHAR      0x82


WORD.doc / Chunks

/*
 *   FONT - Font name/number table
 *   There are one of these for each font/size combination
 *   These chunks should appear at the top of the file
 *   (before document data)
 */

   typedef struct {
      UBYTE   Num;         /* 0 .. 255 */
      UWORD   Size;
   /* UBYTE   Name[];      */   /* NULL terminated, without ".font" */
   } FontID;

/*
 *   COLR - Color translation table
 *   Translates from color numbers used in file to ISO color numbers
 *   Should be at top of file (before document data)
 *   Note:  Currently ProWrite only checks these values to be its
 *      current map, it does no translation as it does for FONT chunks
 */

   typedef struct {
      UBYTE   ISOColors[8];
   } ISOColors;

/*
 *   DOC - Begin document section
 *   All text and paragraph formatting following this chunk and up to a
 *   HEAD, FOOT, or PICT chunk belong to the document section
 */

   #define PAGESTYLE_1   0      /* 1, 2, 3 */
   #define PAGESTYLE_I   1      /* I, II, III */
   #define PAGESTYLE_i   2      /* i, ii, iii */
   #define PAGESTYLE_A   3      /* A, B, C */
   #define PAGESTYLE_a   4      /* a, b, c */

   typedef struct {
      UWORD   StartPage;      /* Starting page number */
      UBYTE   PageNumStyle;   /* From defines above */
      UBYTE   pad1;
      LONG    pad2;
   } DocHdr;

/*
 *   HEAD/FOOT - Begin header/footer section
 *   All text and paragraph formatting following this chunk and up to a
 *   DOC, HEAD, FOOT, or PICT chunk belong to this header/footer
 *   Note:  This format supports multiple headers and footers, but
 *      currently ProWrite only allows a single header and footer per
 *      document
 */

   #define PAGES_NONE   0
   #define PAGES_LEFT   1
   #define PAGES_RIGHT  2
   #define PAGES_BOTH   3

   typedef struct {
      UBYTE   PageType;       /* From defines above */
      UBYTE   FirstPage;      /* 0 = Not on first page */
      LONG   pad;
   } HeadHdr;

/*
 *   PCTS - Begin picture section
 *   Note:  ProWrite currently requires NPlanes to be three (3)
 */

   typedef struct {
      UBYTE   NPlanes;      /* Number of planes used in picture bitmaps */
      UBYTE   pad;
   } PictHdr;

/*
 *   PARA - New paragraph format
 *   This chunk should be inserted first when a new section is started
 *      (DOC, HEAD, or FOOT), and again whenever the paragraph format
 *      changes
 */

   #define SPACE_SINGLE   0
   #define SPACE_DOUBLE   0x10

   #define JUSTIFY_LEFT    0
   #define JUSTIFY_CENTER  1
   #define JUSTIFY_RIGHT   2
   #define JUSTIFY_FULL    3

   #define MISCSTYLE_NONE   0
   #define MISCSTYLE_SUPER  1      /* Superscript */
   #define MISCSTYLE_SUB    2      /* Subscript */

   typedef struct {
      UWORD   LeftIndent; /* In decipoints (720 dpi) */
      UWORD   LeftMargin;
      UWORD   RightMargin;
      UBYTE   Spacing;    /* From defines above */
      UBYTE   Justify;    /* From defines above */
      UBYTE   FontNum;    /* FontNum, Style, etc. for first char in para*/
      UBYTE   Style;      /* Standard Amiga style bits */
      UBYTE   MiscStyle;  /* From defines above */
      UBYTE   Color;      /* Internal number, use COLR to translate */
      LONG    pad;
   } ParaFormat;

/*
 *   TABS - New tab stop types/locations
 *   Use an array of values in each chunk
 *   Like the PARA chunk, this should be inserted whenever the tab
 *      settings for a paragraph change
 *   Note:  ProWrite currently does not support TAB_CENTER
 */

   #define TAB_LEFT     0
   #define TAB_CENTER   1
   #define TAB_RIGHT    2
   #define TAB_DECIMAL  3

   typedef struct {
      UWORD   Position;      /* In decipoints */
      UBYTE   Type;
      UBYTE   pad;
   } TabStop;

/*
 *   PAGE - Page break
 *   Just a marker - this chunk has no data
 */

/*
 *   TEXT - Paragraph text (one block per paragraph)
 *   Block is actual text, no need for separate structure
 *   If the paragraph is empty, this is an empty chunk -- there MUST be
 *   a TEXT block for every paragraph
 *   Note:  The only ctrl characters ProWrite can currently handle in TEXT
 *   chunks are Tab and PAGENUM_CHAR, ie no Return's, etc.
 */

/*
 *   FSCC - Font/Style/Color changes in previous TEXT block
 *   Use an array of values in each chunk
 *   Only include this chunk if the previous TEXT block did not have
 *      the same Font/Style/Color for all its characters
 */

   typedef struct {
      UWORD   Location;  /* Character location in TEXT chunk of change */
      UBYTE   FontNum;
      UBYTE   Style;
      UBYTE   MiscStyle;
      UBYTE   Color;
      UWORD   pad;
   } FSCChange;

/*
 *   PINF - Picture info
 *   This chunk must only be in a PCTS section
 *   Must be followed by ILBM BODY chunk
 *   Pictures are treated independently of the document text (like a
 *      page-layout system), this chunk includes information about what
 *      page and location on the page the picture is at
 *   Note:  ProWrite currently only supports mskTransparentColor and
 *      mskHasMask masking
 */

   typedef struct {
      UWORD         Width, Height;   /* In pixels */
      UWORD         Page;         /* Which page picture is on (0..max) */
      UWORD         XPos, YPos;      /* Location on page in decipoints */
      Masking       Masking;      /* Like ILBM format */
      Compression   Compression;   /* Like ILBM format */
      UBYTE         TransparentColor;   /* Like ILBM format */
      UBYTE         pad;
   } PictInfo;

/* end */


FORM Specs from the Original EA Document / SMUS IFF Simple Musical Score

Date:	February 20, 1987 (SID _Clef and SID_Tempo added Oct, 1988)
From:	Jerry Morrison, Electronic Arts
Status:	Adopted

 Introduction
 Background
 Standard Data and Property Chunks
 Private Chunks
 Appendix A. Quick Reference
 Appendix B. SMUS Example
 Appendix C. Standards Committee


SMUS IFF Simple Musical Score / Introduction

This is a reference manual for the data interchange format "SMUS", which
stands for Simple MUsical Score.  "EA IFF 85" is Electronic Arts' standard
for interchange format files.  A FORM or "data section") such as FORM SMUS
can be an IFF file or a part of one.  [See "EA IFF 85" Electronic Arts
Interchange File Format.]

SMUS is a practical data format for uses like moving limited scores
between programs and storing theme songs for game programs.  The format
should be geared for easy read-in and playback.  So FORM SMUS uses the
compact time encoding of Common Music Notation (half notes, dotted quarter
rests, etc.). The SMUS format should also be structurally simple.  So it
has no provisions for fancy notational information needed by graphical
score editors or the more general timing (overlapping notes, etc.) and
continuous data (pitch bends, etc.) needed by performance-oriented MIDI
recorders and sequencers.  Complex music programs may wish to save in a
more complete format, but still import and export SMUS when requested.

A SMUS score can say which "instruments" are supposed play which notes.
But the score is independent of whatever output device and driver software
is used to perform the notes.  The score can contain device- and
driver-dependent instrument data, but this is just a cache.  As long as a
SMUS file stays in one environment, the embedded instrument data is very
convenient.  When you move a SMUS file between programs or hardware
configurations, the contents of this cache usually become useless.

Like all IFF formats, SMUS is a filed or "archive" format.  It is
completely independent of score representations in working memory, editing
operations, user interface, display graphics, computation hardware, and
sound hardware. Like all IFF formats, SMUS is extensible.

SMUS is not an end-all musical score format.  Other formats may be more
appropriate for certain uses.  (We'd like to design an general-use IFF
score format "GSCR".  FORM GSCR would encode fancy notational data and
performance data.  There would be a SMUS to/from GSCR converter.)

Section 2 gives important background information.  Section 3 details the
SMUS components by defining the required property score header "SHDR", the
optional text properties name "NAME", copyright "(c) ", and author "AUTH",
optional text annotation "ANNO", the optional instrument specifier "INS1",
and the track data chunk "TRAK".  Section 4 defines some chunks for
particular programs to store private information.  These are "standard"
chunks; specialized chunks for future needs can be added later.  Appendix
A is a quick-reference summary. Appendix B is an example box diagram.
Appendix C names the committee responsible for this standard.

 References


SMUS IFF Simple Musical Score / Introduction / References

"EA IFF 85" Standard for Interchange Format Files describes the underlying
conventions for all IFF files.

"8SVX" IFF 8-Bit Sampled Voice documents a data format for sampled
instruments.

MIDI: Musical Instrument Digital Interface Specification 1.0, International
MIDI Association, 1983.

SSSP: See various articles on Structured Sound Synthesis Project in
Foundations of Computer Music.

Electronic Arts(tm) is a trademark of Electronic Arts.

Amiga® is a registered trademark of Amiga, Inc.


SMUS IFF Simple Musical Score / Background

Here's some background information on score representation in general and
design choices for SMUS.

First, we'll borrow some terminology from the Structured Sound Synthesis
Project.  [See the SSSP reference.]  A "musical note" is one kind of
scheduled event.  Its properties include an event duration, an event
delay, and a timbre object.  The event duration tells the scheduler how
long the note should last. The event delay tells how long after starting
this note to wait before starting the next event.  The timbre object
selects sound driver data for the note; an "instrument" or "timbre".  A
"rest" is a sort of a null event.  Its only property is an event delay.

 Classical Event Durations
 Tracks
 Instrument Registers
 MIDI Instruments


Background / Classical Event Durations

SMUS is geared for "classical" scores, not free-form performances.  So its
event durations are classical (whole note, dotted quarter rest, etc.).
SMUS can tie notes together to build a "note event" with an unusual event
duration. The set of useful classical durations is very small.  So SMUS
needs only a handful of bits to encode an event duration.  This is very
compact.  It's also very easy to display in Common Music Notation (CMN).


Background / Tracks

The events in a SMUS score are grouped into parallel "tracks".  Each track
is a linear stream of events.

Why use tracks?  Tracks serve 4 functions:

  1. Tracks make it possible to encode event delays very compactly.  A
     "classical" score has chorded notes and sequential notes; no
     overlapping notes.  That is, each event begins either simultaneous
     with or immediately following the previous event in that track.  So
     each event delay is either 0 or the same as the event's duration.
     This binary distinction requires only one bit of storage.

  2. Tracks represent the "voice tracks" in Common Music Notation.  CMN
     organizes a score in parallel staves, with one or two "voice tracks"
     per staff.  So one or two SMUS tracks represents a
     CMN staff.

  3. Tracks are a good match to available sound hardware.  We can use
     "instrument settings" in a track to store the timbre assignments for
     that track's notes.  The instrument setting may change over the track.

     Furthermore, tracks can help to allocate notes among available output
     channels or performance devices or tape recorder "tracks".  Tracks can
     also help to adapt polyphonic data to monophonic output channels.

  4. Tracks are a good match to simple sound software.  Each track is a
     place to hold state settings like "dynamic mark pp ", "time signature
     3/4", "mute this track", etc., just as it's a context for instrument
     settings.  This is a lot like a text stream with running "font" and
     "face" properties (attributes).  Running state is usually more compact
     than, say, storing an instrument setting in every note event.  It's
     also a useful way to organize "attributes" of notes.  With "running
     track state" we can define new note attributes in an upward- and
     backward-compatible way.

     Running track state can be expanded (run decoded) while loading a
     track into memory or while playing the track.  The runtime track
     state must be reinitialized every time the score is played.

Separated vs. interleaved tracks.  Multi-track data could be stored either
as separate event streams or interleaved into one stream.  To interleave
the streams, each event has to carry a "track number" attribute.

If we were designing an editable score format, we might interleave the
streams so that nearby events are stored nearby.  This helps when
searching the data, especially if you can't fit the entire score into
memory at once.  But it takes extra storage for the track numbers and may
take extra work to manipulate the interleaved tracks.

The musical score format FORM SMUS is intended for simple loading and
playback of small scores that fit entirely in main memory.  So we chose to
store its tracks separately.

There can be up to 255 tracks in a FORM SMUS.  Each track is stored as a
TRAK chunk.  The count of tracks (the number of TRAK chunks) is recorded
in the SHDR chunk at the beginning of the FORM SMUS.  The TRAK chunks
appear in numerical order 1, 2, 3, ....  This is also priority order, most
important track first. A player program that can handle up to N parallel
tracks should read the first N tracks and ignore any others.

The different tracks in a score may have different lengths.  This is true
both of storage length and of playback duration.


Background / Instrument Registers

Instrument reference.  In SSSP, each note event points to a "timbre
object" which supplies the "instrument" (the sound driver data) for that
note.  FORM SMUS stores these pointers as a "current instrument setting"
for each track. It's just a run encoded version of the same information.
SSSP reference uses a symbol table to hold all the pointers to "timbre
object". SMUS uses INS1 chunks for the same purpose.  They name the
score's instruments.

The actual instrument data to use depends on the playback environment, but
we want the score to be independent of environment.  Different playback
environments have different audio output hardware and different sound
driver software.  And there are channel allocation issues like how many
output channels there are, which ones are polyphonic, and which I/O ports
they're connected to.  If you use MIDI to control the instruments, you get
into issues of what kind of device is listening to each MIDI channel and
what each of its presets sounds like.  If you use computer-based
instruments, you need driver- specific data like waveform tables and
oscillator parameters.

We just want some orchestration.  If the score wants a "piano", we let the
playback program find a "piano".

Instrument reference by name.  A reference from a SMUS score to actual
instrument data is normally by name.  The score simply names the
instrument, for instance "tubular bells".  It's up to the player program
to find suitable instrument data for its output devices.  (More on
locating instruments below.)

Instrument reference by MIDI channel and preset.  A SMUS score can also
ask for a specific MIDI channel number and preset number.  MIDI programs
may honor these specific requests.  But these channel allocations can
become obsolete or the score may be played without MIDI hardware.  In such
cases, the player program should fall back to instrument reference by name.

Instrument reference via instrument register.  Each reference from a SMUS
track to an instrument is via an "instrument register".  Each track
selects an instrument register which in turn points to the specific
instrument data.

Each score has an array of instrument registers.  Each track has a
"current instrument setting", which is simply an index number into this
array.  This is like setting a raster image's pixel to a specific color
number (a reference to a color value through a "color register") or
setting a text character to a specific font number (a reference to a font
through a "font register"). This is diagramed below:

         +------------+--------+--------+------------+--------+-----------+
Track 1  | Set Inst 2 |  Note  |  Note  | Set Inst 1 |  Note  |  Note...  |
     .---+------------+--------+--------+------------+--------+-----------+
    /   ______________________________________/
   /   /
  /   /
  \   \       +------------------+       +--------------------------------+
   \   `----->| "piano"          |-----> |   (internal piano data)        |
    \         +------------------+       +--------------------------------+
     `------->| "guitar"         |-----> |   (internal guitar data)       |
Instrument    +------------------+       +--------------------------------+
 Registers    | "Spanish guitar" |-----> | (internal Spanish guitar data) |
              +------------------+       +--------------------------------+
       .----->| "bass drum"      |-----> |  (internal bass drum data)     |
      /       +------------------+       +--------------------------------+
     /
     \
      \
       `-+------------+--------+--------+--------+--------+-----------+
Track 2  | Set Inst 4 |  Note  |  Note  |  Note  |  Note  |  Note...  |
         +------------+--------+--------+--------+--------+-----------+

Locating instrument data by name.  "INS1" chunks in a SMUS score name the
instruments to use for that score.  The player program uses these names to
locate instrument data.

To locate instrument data, the player performs these steps:

For each instrument register, check for a suitable instrument with the
right name?

    {"Suitable" means usable with an available output device and driver.}
    {Use case independent name comparisons.}

  1.Initialize the instrument register to point to a built-in default
    instrument.

    {Every player program must have default instruments.  Simple programs
    stop here.  For fancier programs, the default instruments are a
    backstop in case the search fails.}

  2.Check any instrument FORMs embedded in the FORM SMUS.  (This is an
    "instrument cache".)

  3.Else check the default instruments.

  4.Else search the local "instrument library".  (The library might simply
    be a disk directory.)

  5.If all else fails, display the desired instrument name and ask the
    user to pick an available one.

This algorithm can be implemented to varying degrees of fanciness.  It's
OK to stop searching after step 1, 2, 3, or 4.  If exact instrument name
matches fail, it's OK to try approximate matches.  E.g., search for any
kind of "guitar" if you can't find a "Spanish guitar".  In any case, a
player only has to search for instruments while loading a score.

When the embedded instruments are suitable, they save the program from
asking the user to insert the "right" disk in a drive and searching that
disk for the "right" instrument.  But it's just a cache.  In practice, we
rarely move scores between environments so the cache often works.  When
the score is moved, embedded instruments must be discarded (a cache miss)
and other instrument data used.

Be careful to distinguish an instrument's name from its filename--the
contents name vs. container name.  A musical instrument FORM should
contain a NAME chunk that says what instrument it really is.  Its
filename, on the other hand, is a handle used to locate the FORM.
Filenames are affected by external factors like drives, directories, and
filename character and length limits.  Instrument names are not.

Issue: Consider instrument naming conventions for consistency.  Consider a
naming convention that aids approximate matches.  E.g., we could accept
"guitar, bass1" if we didn't find "guitar, bass".  Failing that, we could
accept "guitar" or any name starting with "guitar".

Set instrument events.  If the player implements the set-instrument score
event, each track can change instrument numbers while playing.  That is,
it can switch between the loaded instruments.

Initial instrument settings.  Each time a score is played, every track's
running state information must be initialized.  Specifically, each track's
instrument number should be initialized to its track number.  Track 1 to
instrument 1, etc.  It's as if each track began with a set-instrument
event.

In this way, programs that don't implement the set-instrument event still
assign an instrument to each track.  The INS1 chunks imply these initial
instrument settings.


Background / MIDI Instruments

As mentioned above, A SMUS score can also ask for MIDI instruments.  This
is done by putting the MIDI channel and preset numbers in an INS1 chunk
with the instrument name.  Some programs will honor these requests while
others will just find instruments by name.

MIDI Recorder and sequencer programs may simply transcribe the MIDI
channel and preset commands in a recording session.  For this purpose,
set-MIDI-channel and set-MIDI-preset events can be embedded in a SMUS
score's tracks.  Most programs should ignore these events.  An editor
program that wants to exchange scores with such programs should recognize
these events.  It should let the user change them to the more general
set-instrument events.


SMUS IFF Simple Musical Score / Standard Data and Property Chunks

A FORM SMUS contains a required property "SHDR" followed by any number of
parallel "track" data chunks "TRAK".  Optional property chunks such as
"NAME", copyright "(c) ", and instrument reference "INS1" may also appear.
Any of the properties may be shared over a LIST of FORMs SMUS by putting
them in a PROP SMUS.  [See the IFF reference.]

 Required Property SHDR
 Optional Text Chunks
 Optional Property INS1
 Obsolete Property INST
 Data Chunk TRAK
 Note and Rest Events
 Set Instrument SEvent
 Set Timesignature SEvent
 Key Signature SEvent
 Dynamic Mark SEvent
 Set MIDI Channel SEvent
 Set MIDI Preset SEvent
 Instant Music Private SEvents
 End-Mark SEvents
 More SEvents To Be Defined


Standard Data and Property Chunks / Required Property SHDR

The required property "SHDR" holds an SScoreHeader as defined in these C
declarations and following documentation.  An SHDR specifies global
information for the score.  It must appear before the TRAKs in a FORM SMUS.

    #define ID_SMUS MakeID('S', 'M', 'U', 'S')
    #define ID_SHDR MakeID('S', 'H', 'D', 'R')

    typedef struct {
    UWORD tempo;	/* tempo, 128ths quarter note/minute */
    UBYTE volume;	/* overall playback volume 0 through 127 */
    UBYTE ctTrack;	/* count of tracks in the score */
    } SScoreHeader;

[Implementation details.  In the C struct definitions in this memo, fields
are filed in the order shown.  A UBYTE field is packed into an 8-bit byte.
Programs should set all "pad" fields to 0.  MakeID is a C macro defined in
the main IFF document and in the source file IFF.h.]

The field tempo gives the nominal tempo for all tracks in the score.  It
is expressed in 128ths of a quarter note per minute, i.e., 1 represents 1
quarter note per 128 minutes while 12800 represents 100 quarter notes per
minute.  You may think of this as a fixed point fraction with a 9-bit
integer part and a 7-bit fractional part (to the right of the point).  A
coarse-tempoed program may simply shift tempo right by 7 bits to get a
whole number of quarter notes per minute.  The tempo field can store tempi
in the range 0 up to 512.  The playback program may adjust this tempo,
perhaps under user control.

Actually, this global tempo could actually be just an initial tempo if
there are any "set tempo" SEvents inside the score (see TRAK, below).  Or
the global tempo could be scaled by "scale tempo" SEvents inside the
score.  These are potential extensions that can safely be ignored by
current programs.  [See More SEvents To Be Defined, below.]

The field volume gives an overall nominal playback volume for all tracks
in the score.  The range of volume values 0 through 127 is like a MIDI key
velocity value.  The playback program may adjust this volume, perhaps
under direction of a user "volume control".

Actually, this global volume level could be scaled by dynamic-mark SEvents
inside the score (see TRAK, below).

The field ctTrack holds the count of tracks, i.e., the number of TRAK
chunks in the FORM SMUS (see below).  This information helps the reader
prepare for the following data.

A playback program will typically load the score and call a driver routine
PlayScore(tracks, tempo, volume), supplying the tempo and volume from the
SHDR  chunk.


Standard Data and Property Chunks / Optional Text Chunks

Several text chunks may be included in a FORM SMUS to keep ancillary
information.

The optional property "NAME" names the musical score, for instance "Fugue
in C".

The optional property "(c) " holds a copyright notice for the score.  The
chunk ID "(c) " serves the function of the copyright characters "(c) ".
E.g., a "(c) " chunk containing "1986 Electronic Arts" means "(c) 1986
Electronic Arts".

The optional property "AUTH" holds the name of the score's author.

The chunk types "NAME", "(c) ", and "AUTH" are property chunks.  Putting
more than one NAME (or other) property in a FORM is redundant.  Just the
last NAME counts.  A property should be shorter than 256 characters.
Properties can appear in a PROP SMUS to share them over a LIST of FORMs
"SMUS".

The optional data chunk "ANNO" holds any text annotations typed in by the
author.

An ANNO chunk is not a property chunk, so you can put more than one in a
FORM SMUS.  You can make ANNO chunks any length up to 2^31 - 1 characters,
but 32767 is a practical limit.  Since they're not properties, ANNO chunks
don't belong in a PROP SMUS.  That means they can't be shared over a LIST
of FORMs SMUS.

Syntactically, each of these chunks contains an array of 8-bit ASCII
characters in the range " " (SP, hex 20) through "~" (tilde, hex 7F), just
like a standard "TEXT" chunk.  [See "Strings, String Chunks, and String
Properties" in "EA IFF 85" Electronic Arts Interchange File Format.]  The
chunk's ckSize field holds the count of characters.

    #define ID_NAME MakeID('N', 'A', 'M', 'E')
    /* NAME chunk contains a CHAR[], the musical score's name.       */

    #define ID_Copyright MakeID('(', 'c', ')', ' ')
    /* "(c) " chunk contains a CHAR[], the FORM's copyright notice.  */

    #define ID_AUTH MakeID('A', 'U', 'T', 'H')
    /* AUTH chunk contains a CHAR[], the name of the score's author. */

    #define ID_ANNO MakeID('A', 'N', 'N', 'O')
    /* ANNO chunk contains a CHAR[], author's text annotations.      */

Remember to store a 0 pad byte after any odd-length chunk.


Standard Data and Property Chunks / Optional Property INS1

The "INS1" chunks in a FORM SMUS identify the instruments to use for this
score.  A program can ignore INS1 chunks and stick with its built-in
default instrument assignments.  Or it can use them to locate instrument
data.  [See "Instrument Registers" in section 2, above.]

    #define ID_INS1 MakeID('I', 'N', 'S', '1')

    /* Values for the RefInstrument field "type".	*/
    #define INS1_Name  0    /* just use the name; ignore data1, data2  */
    #define INS1_MIDI  1    /* <data1, data2> = MIDI <channel, preset> */

    typedef struct {
    UBYTE register;	    /* set this instrument register number */
    UBYTE type;	    /* instrument reference type */
    UBYTE data1, data2; /* depends on the "type" field */
    CHAR  name[];	    /* instrument name */
    } RefInstrument;

An INS1 chunk names the instrument for instrument register number
register. The register field can range from 0 through 255.  In practice,
most scores will need only a few instrument registers.

The name field gives a text name for the instrument.  The string length
can be determined from the ckSize of the INS1 chunk.  The string is simply
an array of 8-bit ASCII characters in the range " " (SP, hex 20) through
"~" (tilde, hex 7F).

Besides the instrument name, an INS1 chunk has two data numbers to help
locate an instrument.  The use of these data numbers is controlled by the
type field. A value type = INS1_Name means just find an instrument by
name.  In this case, data1 and data2 should just be set to 0.  A value
type = INS1_MIDI means look for an instrument on MIDI channel # data1,
preset # data2.  Programs and computers without MIDI outputs will just
ignore the MIDI data.  They'll always look for the named instrument.
Other values of the type field are reserved for future standardization.

See section 2, above, for the algorithm for locating instrument data by
name.


Standard Data and Property Chunks / Obsolete Property INST

The chunk type "INST" is obsolete in SMUS.  It was revised to form the
"INS1" chunk.


Standard Data and Property Chunks / Data Chunk TRAK

The main contents of a score is stored in one or more TRAK chunks
representing parallel "tracks".  One TRAK chunk per track.

The contents of a TRAK chunk is an array of 16-bit "events" such as
"note", "rest", and "set instrument".  Events are really commands to a
simple scheduler, stored in time order.  The tracks can be polyphonic,
that is, they can contain chorded "note" events.

Each event is stored as an "SEvent" record.  ("SEvent" means "simple
musical event".)  Each SEvent has an 8-bit type field called an "sID" and
8 bits of type-dependent data.  This is like a machine language
instruction with an 8-bit opcode and an 8-bit operand.

This format is extensible since new event types can be defined in the
future. The "note" and "rest" events are the only ones that every program
must understand.  We will carefully design any new event types so that
programs can safely skip over unrecognized events in a score.

Caution: ID codes must be allocated by a central clearinghouse  to avoid
conflicts.  Commodore Applications and Technical Support provides this
clearinghouse service.

Here are the C type definitions for TRAK and "SEvent" and the currently
defined sID values.  Afterward are details on each SEvent.

  #define ID_TRAK MakeID('T', 'R', 'A', 'K')
  /* TRAK chunk contains an SEvent[].       */

  /* SEvent: Simple musical event.          */
  typedef struct {
      UBYTE sID;      /* SEvent type code   */
      UBYTE data;     /* sID-dependent data */
      } SEvent;

  /* SEvent type codes "sID".                                            */
  #define SID_FirstNote     0
  #define SID_LastNote    127 /* sIDs in the range SID_FirstNote through
                               * SID_LastNote (sign bit = 0) are notes.
                               * The sID is the MIDI tone number (pitch).*/

  #define SID_Rest        128 /* a rest (same data format as a note).    */

  #define SID_Instrument  129 /* set instrument number for this track.   */
  #define SID_TimeSig     130 /* set time signature for this track.      */
  #define SID_KeySig      131 /* set key signature for this track.       */
  #define SID_Dynamic     132 /* set volume for this track.              */
  #define SID_MIDI_Chnl   133 /* set MIDI channel number (sequencers)    */
  #define SID_MIDI_Preset 134 /* set MIDI preset number (sequencers)     */
  #define SID_Clef        135 /* inline clef change.
                               * 0=Treble, 1=Bass, 2=Alto, 3=Tenor.(new) */
  #define SID_Tempo       136 /* Inline tempo in beats per minute.(new)  */

  /* SID values 144 through 159: reserved for Instant Music SEvents.     */

  /* Remaining sID values up through 254: reserved for future
   * standardization.         */

  #define SID_Mark        255 /* sID reserved for an end-mark in RAM.    */


Standard Data and Property Chunks / Note and Rest SEvents

The note and rest SEvents SID_FirstNote through SID_Rest have the
following structure overlaid onto the SEvent structure:

  typedef struct {
      UBYTE    tone;          /* MIDI tone number 0 to 127; 128 = rest */
      unsigned chord    :1,   /* 1 = a chorded note                    */
               tieOut   :1,   /* 1 = tied to the next note or chord    */
               nTuplet  :2,   /* 0 = none, 1 = triplet, 2 = quintuplet,
                               * 3 = septuplet                         */
               dot      :1,   /* dotted note; multiply duration by 3/2 */
               division :3;   /* basic note duration is 2^-division: 0 =
                               * whole note, 1 = half note, 2 = quarter
                               * note, .... 7 = 128th note             */
      } SNote;

[Implementation details.  Unsigned ":n" fields are packed into n bits in
the order shown, most significant bit to least significant bit.  An SNote
fits into 16 bits like any other SEvent.  Warning: Some compilers don't
implement bit-packed fields properly.  E.g., Lattice 68000 C pads a group
of bit fields out to a LONG, which would make SNote take 5-bytes!  In that
situation, use the bit-field constants defined below.]

The SNote structure describes one "note" or "rest" in a track.  The field
SNote.tone, which is overlaid with the SEvent.sID field, indicates the
MIDI tone number (pitch) in the range 0 through 127.  A value of 128
indicates a rest.

The fields nTuplet, dot, and division together give the duration of the
note or rest.   The division gives the basic duration: whole note, half
note, etc. The dot indicates if the note or rest is dotted.  A dotted note
is 3/2 as long as an undotted note.  The value nTuplet (0 through 3) tells
if this note or rest is part of an N-tuplet of order 1 (normal), 3, 5, or
7; an N-tuplet of order (2 * nTuplet + 1).  A triplet note is 2/3 as long
as a normal note, while a quintuplet is 4/5 as long and a septuplet is 6/7
as long.

Putting these three fields together, the duration of the note or rest is

    2^(-division) * {1, 3/2} * {1, 2/3, 4/5, 6/7}

These three fields are contiguous so you can easily convert to your local
duration encoding by using the combined 6 bits as an index into a mapping
table.

The field chord indicates if the note is chorded with the following note
(which is supposed to have the same duration).  A group of notes may be
chorded together by setting the chord bit of all but the last one.  (In
the terminology of SSSP reference and GSCR, setting the chord bit to 1
makes the "entry delay" 0.)  A monophonic-track player can simply ignore
any SNote event whose chord bit is set, either by discarding it when
reading the track or by skipping it when playing the track.

Programs that create polyphonic tracks are expected to store the most
important note of each chord last, which is the note with the 0 chord bit.
This way, monophonic programs will play the most important note of the
chord. The most important note might be the chord's root note or its
melody note.

If the field tieOut is set, the note is tied to the following note in the
track if the following note has the same pitch.  A group of tied notes is
played as a single note whose duration is the sum of the component
durations. Actually, the tie mechanism ties a group of one or more chorded
notes to another group of one or more chorded notes.  Every note in a tied
chord should have its tieOut bit set.

Of course, the chord and tieOut fields don't apply to SID_Rest SEvents.

Programs should be robust enough to ignore an unresolved tie, i.e., a note
whose tieOut bit is set but isn't followed by a note of the same pitch. If
that's true, monophonic-track programs can simply ignore chorded notes
even in the presense of ties.  That is, tied chords pose no extra
problems.

The following diagram shows some combinations of notes and chords tied to
notes and chords.  The text below the staff has a column for each SNote
SEvent to show the pitch, chord bit, and tieOut bit.

A treble staff with chords and ties:

         |`      |`       |`      |`       |`      |`      |`      |`
         |       |        |       |        |       |       |       |
+--------|-____--|--------|-------|--------|-____--|-------|-____--|----+
|-------0|/____\0|-------0|-------|-------0|/    \0'------0'/    \0|----|
|-------0|/____\0|-------0|-____--|-------0|----------------------0|----|
|-------0'/    \0'-------0'/    \0'-------0'----------------------0'----|
+-----------------------------------------------------------------------+

Corresponding SNote values in the TRAK chunk:

Pitch:  D B G   D B G    D B G   G        D B G   B       B       D B G
chord:  c c -   c c -    c c -   -        c c -   -       -       c c -
tieOut: t t t   - - -    t t t   -        t t t   -       t       - - -

If you read the above track into a monophonic-track program, it'll strip
out the chorded notes and ignore unresolved ties.  You'll end up with:

                                                   |`      |`
                                                   |       |
+--------|`------|`-------|`------|`-------|`------|-------|-------|`---+
|--------|-------|--------|-------|--------|------0'------0'-------|----|
|--------|-____--|--------|-____--|--------|-----------------------|----|
|-------0'/    \0'-------0'/    \0'-------0'----------------------0'----|
+-----------------------------------------------------------------------+

Pitch:  G       G        G       G        G        B       B      G
chord:  -       -        -       -        -        -       -      -
tieOut: t       -        t       -       (t)       -      (t)     -

A rest event (sID = SID_Rest) has the same SEvent.data field as a note.
It tells the duration of the rest.  The chord and tieOut fields of rest
events are ignored.

Within a TRAK chunk, note and rest events appear in time order.

Instead of the bit-packed structure SNote, it might be easier to assemble
data values by or-ing constants and to disassemble them by masking and
shifting. In that case, use the following definitions.

  #define noteChord  (1<<7)          /* note is chorded to next note   */
  #define noteTieOut (1<<6)          /* tied to next note/chord        */

  #define noteNShift 4               /* shift count for nTuplet field  */
  #define noteN3     (1<<noteNShift) /* note is a triplet              */
  #define noteN5     (2<<noteNShift) /* note is a quintuplet           */
  #define noteN7     (3<<noteNShift) /* note is a septuplet            */
  #define noteNMask  noteN7          /* bit mask for the nTuplet field */

  #define noteDot    (1<<3)          /* note is dotted                 */

  #define noteD1     0               /* whole note division             */
  #define noteD2     1               /* half note division              */
  #define noteD4     2               /* quarter note division           */
  #define noteD8     3               /* eighth note division            */
  #define noteD16    4               /* sixteenth note division         */
  #define noteD32    5               /* thirty-second'th note division  */
  #define noteD64    6               /* sixty-fourth note division      */
  #define noteD128   7               /* 1/128 note division             */
  #define noteDMask  noteD128        /* bit mask for the division field */

  #define noteDurMask 0x3F           /* mask for combined duration fields*/

Note: The remaining SEvent types are optional.  A writer program doesn't
have to generate them.  A reader program can safely ignore them.


Standard Data and Property Chunks / Set Instrument SEvent

One of the running state variables of every track is an instrument number.
An instrument number is the array index of an "instrument register", which
in turn points to an instrument.  (See "Instrument Registers", in section
2.) This is like a color number in a bitmap; a reference to a color
through a "color register".

The initial setting for each track's instrument number is the track
number. Track 1 is set to instrument 1, etc.  Each time the score is
played, every track's instrument number should be reset to the track
number.

The SEvent SID_Instrument changes the instrument number for a track, that
is, which instrument plays the following notes.  Its SEvent.data field is
an instrument register number in the range 0 through 255.  If a program
doesn't implement the SID_Instrument event, each track is fixed to one
instrument.


Standard Data and Property Chunks / Set Time Signature SEvent

The SEvent SID_TimeSig sets the time signature for the track.  A "time
signature" SEvent has the following structure overlaid on the SEvent
structure:

    typedef struct {
    UBYTE    type;		/* = SID_TimeSig */
    unsigned timeNSig :5,	/* time sig. "numerator" is timeNSig + 1 */
         timeDSig :3;	/* time sig. "denominator" is 2^timeDSig:*
                 * 0 = whole note, 1 = half note, 2 =    *
                 * quarter note,....7 = 128th note 	 */
    } STimeSig;

[Implementation details.  Unsigned ":n" fields are packed into n bits in
the order shown, most significant bit to least significant bit.  An
STimeSig fits into 16 bits like any other SEvent.  Warning: Some compilers
don't implement bit-packed fields properly.  E.g., Lattice C pads a group
of bit fields out to a LONG, which would make an STimeSig take 5-bytes!
In that situation, use the bit-field constants defined below.]

The field type contains the value SID_TimeSig, indicating that this SEvent
is a "time signature" event.  The field timeNSig indicates the time
signature "numerator" is timeNSig + 1, that is, 1 through 32 beats per
measure.  The field timeDSig indicates the time signature "denominator" is
2^(timeDSig), that is each "beat" is a 2^(-timeDSig) note (see SNote
division, above).  So 4/4 time is expressed as timeNSig = 3, timeDSig = 2.

The default time signature is 4/4 time.  Be aware that the time signature
has no effect on the score's playback.  Tempo is uniformly expressed in
quarter notes per minute, independent of time signature.  (Quarter notes
per minute would equal beats per minute only if timeDSig = 2, n/4 time).
Nonetheless, any program that has time signatures should put them at the
beginning of each TRAK when creating a FORM SMUS because music editors
need them.

Instead of the bit-packed structure STimeSig, it might be easier to
assemble data values by or-ing constants and to disassemble them by
masking and shifting.  In that case, use the following definitions.

    #define timeNMask  0xF8	/* bit mask for the timeNSig field	*/
    #define timeNShift 3	/* shift count for  timeNSig field	*/
    #define timeDMask  0x07	/* bit mask for the timeDSig field	*/


Standard Data and Property Chunks / Key Signature SEvent

An SEvent SID_KeySig sets the key signature for the track.  Its data field
is a UBYTE number encoding a major key:

    data	key	music notation	data	key	music notation

     0	 C maj
     1	 G    	  #		  8	 F	  b
     2	 D    	  ##		  9	 Bb	  bb
     3	 A    	  ###		 10	 Eb	  bbb
     4	 E    	  ####		 11	 Ab	  bbbb
     5	 B    	  #####		 12	 Db	  bbbbb
     6	 F#   	  ######	 13	 Gb	  bbbbbb
     7	 C#    	  #######	 14	 Cb	  bbbbbbb

A SID_KeySig SEvent changes the key for the following notes in that track.
C major is the default key in every track before the first SID_KeySig
SEvent.


Standard Data and Property Chunks / Dynamic Mark SEvent

An SEvent SID_Dynamic represents a dynamic mark like ppp and fff in Common
Music Notation.  Its data field is a MIDI key velocity number 0 through
127. This sets a "volume control" for following notes in the track.  This
"track volume control" is scaled by the overall score volume in the SHDR
chunk.  The default dynamic level is 127 (full volume).


Standard Data and Property Chunks / Set MIDI Channel SEvent

The SEvent SID_MIDI_Chnl is for recorder programs to record the
set-MIDI-channel low level event.  The data byte contains a MIDI channel
number.  Other programs should use instrument registers instead.


Standard Data and Property Chunks / Set MIDI Preset SEvent

The SEvent SID_MIDI_Preset is for recorder programs to record the
set-MIDI-preset low level event.  The data byte contains a MIDI preset
number. Other programs should use instrument registers instead.


Standard Data and Property Chunks / Instant Music Private SEvents

Sixteen SEvents are used for private data for the Instant Music program.
SID values 144 through 159 are reserved for this purpose.  Other programs
should skip over these SEvents.


Standard Data and Property Chunks / End-Mark SEvent

The SEvent type SID_Mark is reserved for an end marker in working memory.
This event is never stored in a file.  It may be useful if you decide to
use the filed TRAK format intact in working memory.


Standard Data and Property Chunks / More SEvents To Be Defined

More SEvents can be defined in the future.  The sID codes 133 through 143
and 160 through 254 are reserved for future needs.  Caution: sID codes
must be allocated by a central "clearinghouse" to avoid conflicts.

The following SEvent types are under consideration and should not yet be
used.

Issue: A "change tempo" SEvent changes tempo during a score.  Changing the
tempo affects all tracks, not just the track containing the change tempo
event.

One possibility is a "scale tempo" SEvent SID_ScaleTempo that rescales the
global tempo:

    currentTempo := globalTempo * (data + 1) / 128

This can scale the global tempo (in the SHDR) anywhere from x1/128 to x2
in roughly 1% increments.

An alternative is two events SID_SetHTempo and SID_SetLTempo.
SID_SetHTempo gives the high byte and SID_SetLTempo gives the low byte of
a new tempo setting, in 128ths quarter note/minute.  SetHTempo
automatically sets the low byte to 0, so the SetLTempo event isn't needed
for coarse settings.  In this scheme, the SHDR's tempo is simply a
starting tempo.

An advantage of SID_ScaleTempo is that the playback program can just alter
the global tempo to adjust the overall performance time and still easily
implement tempo variations during the score.  But the "set tempo" SEvent
may be simpler to generate.

Issue: The events SID_BeginRepeat and SID_EndRepeat define a repeat span
for one track.  The span of events between a BeginRepeat and an EndRepeat
is played twice.  The SEvent.data field in the BeginRepeat event could
give an iteration count, 1 through 255 times or 0 for "repeat forever".

Repeat spans can be nested.  All repeat spans automatically end at the end
of the track.

An event SID_Ending begins a section like "first ending" or "second
ending". The SEvent.data field gives the ending number.  This SID_Ending
event only applies to the innermost repeat group.  (Consider generalizing
it.)

A more general alternative is a "subtrack" or "subscore" event.  A
"subtrack" event is essentially a "subroutine call" to another series of
SEvents.  This is a nice way to encode all the possible variations
of repeats, first endings, codas, and such.

To define a subtrack, we must demark its start and end.  One possibility
is to define a relative branch-to-subtrack event SID_BSR and a
return-from-subtrack event SID_RTS.  The 8-bit data field in the SID_BSR
event can reach as far as 512 SEvents.  A second possibility is to call a
subtrack by index number, with an IFF chunk outside the TRAK defining the
start and end of all subtracks. This is very general since a portion of
one subtrack can be used as another subtrack.  It also models the tape
recording practice of first "laying down a track" and then selecting
portions of it to play and repeat.  To embody the music theory idea of
playing a sequence like "ABBA", just compose the "main" track entirely of
subtrack events.  A third possibility is to use a numbered subtrack chunk
"STRK" for each subroutine.


SMUS IFF Simple Musical Score / Private Chunks

As in any IFF FORM, there can be private chunks in a FORM SMUS that are
designed for one particular program to store its private information.  All
IFF reader programs skip over unrecognized chunks, so the presense of
private chunks can't hurt.

Instant Music stores some global score information in a chunk of ID "IRev"
and some other information in a chunk of ID "BIAS".


SMUS IFF Simple Musical Score / Appendix A. Quick Reference

 Type Definitions
 SMUS Regular Expression


Appendix A. Quick Reference / Type Definitions

Here's a collection of the C type definitions in this memo.  In the
"struct" type definitions, fields are filed in the order shown.  A UBYTE
field is packed into an 8-bit byte.  Programs should set all "pad" fields
to 0.

    #define ID_SMUS MakeID('S', 'M', 'U', 'S')
    #define ID_SHDR MakeID('S', 'H', 'D', 'R')

    typedef struct {
    UWORD tempo;	/* tempo, 128ths quarter note/minute 		*/
    UBYTE volume;	/* overall playback volume 0 through 127 	*/
    UBYTE ctTrack;	/* count of tracks in the score			*/
    } SScoreHeader;

    #define ID_NAME MakeID('N', 'A', 'M', 'E')
    /* NAME chunk contains a CHAR[], the musical score's name.		*/

    #define ID_Copyright MakeID('(', 'c', ')', ' ')
    /* "(c) " chunk contains a CHAR[], the FORM's copyright notice.	*/

    #define ID_AUTH MakeID('A', 'U', 'T', 'H')
    /* AUTH chunk contains a CHAR[], the name of the score's author.	*/

    #define ID_ANNO MakeID('A', 'N', 'N', 'O')
    /* ANNO chunk contains a CHAR[], author's text annotations.		*/

    #define ID_INS1 MakeID('I', 'N', 'S', '1')
    /* Values for the RefInstrument field "type".			*/

    #define INS1_Name 0	/* just use the name; ignore data1, data2	*/
    #define INS1_MIDI 1	/* <data1, data2> = MIDI <channel, preset>	*/

    typedef struct {
    UBYTE register;	    /* set this instrument register number 	*/
    UBYTE type;	    /* instrument reference type 		*/
    UBYTE data1, data2; /* depends on the "type" field 		*/
    CHAR  name[];	    /* instrument name 				*/
    } RefInstrument;

    #define ID_TRAK MakeID('T', 'R', 'A', 'K')
    /* TRAK chunk contains an SEvent[].					*/

    /* SEvent: Simple musical event.					*/
    typedef struct {
    UBYTE sID;	/* SEvent type code				*/
    UBYTE data;	/* sID-dependent data				*/
    } SEvent;

    /* SEvent type codes "sID".						*/
    #define SID_FirstNote     0
    #define SID_LastNote    127	/* sIDs in the range SID_FirstNote through
                 * SID_LastNote (sign bit = 0) are notes.
                 * sID is the MIDI tone number (pitch).	*/
    #define SID_Rest        128	/* a rest (same data format as a note).	*/

    #define SID_Instrument  129	/* set instrument number for this track.*/
    #define SID_TimeSig     130	/* set time signature for this track.	*/
    #define SID_KeySig      131	/* set key signature for this track.	*/
    #define SID_Dynamic     132	/* set volume for this track.		*/
    #define SID_MIDI_Chnl   133	/* set MIDI channel number (sequencers)	*/
    #define SID_MIDI_Preset 134	/* set MIDI preset number (sequencers)	*/
    #define SID_Clef        135	/* inline clef change.			*
                 * 0=Treble, 1=Bass, 2=Alto, 3=Tenor.	*/
    #define SID_Tempo       136	/* Inline tempo in beats per minute.	*/

    /* SID values 144 through 159: reserved for Instant Music SEvents.	*/

    /* Remaining sID values up through 254: reserved for future
     * standardization.							*/

    #define SID_Mark        255	/* sID reserved for an end-mark in RAM.	*/

    /* SID_FirstNote..SID_LastNote, SID_Rest SEvents			*/

    typedef struct {
    UBYTE    tone;		/* MIDI tone number 0 to 127; 128 = rest */
    unsigned chord    :1,	/* 1 = a chorded note 			 */
             tieOut   :1,	/* 1 = tied to the next note or chord 	 */
             nTuplet  :2,	/* 0 = none, 1 = triplet, 2 = quintuplet,
                 * 3 = septuplet 			 */
             dot      :1,	/* dotted note; multiply duration by 3/2 */
             division :3;	/* basic note duration is 2-division:
                 * 0 = whole note, 1 = half note,
                 * 2 = quarter note, 7 = 128th note */
        } SNote;

    #define noteChord  (1<<7)   /* note is chorded to next note          */

    #define noteTieOut (1<<6)   /* tied to next note/chord               */

    #define noteNShift 4        /* shift count for nTuplet field         */

    #define noteN3     (1<<noteNShift)  /* note is a triplet             */
    #define noteN5     (2<<noteNShift)  /* note is a quintuplet          */
    #define noteN7     (3<<noteNShift)  /* note is a septuplet           */

    #define noteNMask  noteN7   /* bit mask for the nTuplet field        */

    #define noteDot    (1<<3)   /* note is dotted                        */

    #define noteD1     0        /* whole note division                   */
    #define noteD2     1        /* half note division                    */
    #define noteD4     2        /* quarter note division                 */
    #define noteD8     3        /* eighth note division                  */
    #define noteD16    4        /* sixteenth note division               */
    #define noteD32    5        /* thirty-secondth note division         */
    #define noteD64    6        /* sixty-fourth note division            */
    #define noteD128   7        /* 1/128 note division                   */
    #define noteDMask  noteD128 /* bit mask for the division field       */

    #define noteDurMask 0x3F    /* mask for combined duration fields     */

    /* SID_Instrument SEvent                                             */
    /* "data" value is an instrument register number 0 through 255.      */

    /* SID_TimeSig SEvent                                                */
    typedef struct {
        UBYTE    type;          /* = SID_TimeSig                         */
        unsigned timeNSig :5,   /* time sig. "numerator" is timeNSig + 1 */
                 timeDSig :3;   /* time sig. "denominator" is 2^timeDSig: *
                                 * 0 = whole note, 1 = half note, 2 =     *
                                 * quarter note,.... 7 = 128th note      */
        } STimeSig;

    #define timeNMask  0xF8     /* bit mask for the timeNSig field       */
    #define timeNShift 3        /* shift count for  timeNSig field       */

    #define timeDMask  0x07     /* bit mask for the timeDSig field       */

    /* SID_KeySig SEvent                                                 */
    /* "data" value 0 = Cmaj; 1 through 7 = G,D,A,E,B,F#,C#;             *
     * 8 through 14 = F,Bb,Eb,Ab,Db,Gb,Cb.                               */

    /* SID_Dynamic SEvent                                                */
    /* "data" value is a MIDI key velocity 0..127.                       */


Appendix A. Quick Reference / SMUS Regular Expression

Here's a regular expression summary of the FORM SMUS syntax.  This could
be an IFF file or part of one.

    SMUS      ::= "FORM" #{ "SMUS" SHDR [NAME] [Copyright] [AUTH] [IRev]
                            ANNO* INS1*  TRAK*  InstrForm* }

    SHDR      ::= "SHDR" #{ SScoreHeader    }
    NAME      ::= "NAME" #{ CHAR*   } [0]
    Copyright ::= "(c) " #{ CHAR*   } [0]
    AUTH      ::= "AUTH" #{ CHAR*   } [0]
    IRev      ::= "IRev" #{ ...     }

    ANNO      ::= "ANNO" #{ CHAR*   } [0]
    INS1      ::= "INS1" #{ RefInstrument   } [0]

    TRAK      ::= "TRAK" #{ SEvent* }
    InstrForm ::= "FORM" #{ ...     }

The token "#" represents a ckSize LONG count of the following {braced}
data bytes.  Literal items are shown in "quotes", [square bracket items]
are optional, and "*" means 0 or more replications.  A sometimes-needed
pad byte is shown as "[0]".

Actually, the order of chunks in a FORM SMUS is not as strict as this
regular expression indicates.  The SHDR, NAME, Copyright, AUTH, IRev,
ANNO, and INS1 chunks may appear in any order, as long as they precede the
TRAK chunks.

The chunk "InstrForm" represents any kind of instrument data FORM embedded
in the FORM SMUS.  For example, see the document "8SVX" IFF 8-Bit Sampled
Voice. Of course, a recipient program will ignore an instrument FORM if it
doesn't recognize that FORM type.


SMUS IFF Simple Musical Score / Appendix B. SMUS Example

Here's a box diagram for a simple example, a SMUS with two instruments and
two tracks.  Each track contains 1 note event and 1 rest event.

              +-----------------------+
              |                       |
              |   'FORM'        94    |  FORM 94 SMUS
              |                       |
           -- +-----------------------+
           |  |                       |
           |  |   'SMUS'              |
           |  |                       |
           |  |  +-----------------+  |
           |  |  | 'SHDR'       4  |  |  .SHDR 4
           |  |  |-----------------|  |
           |  |  | 12800, 127, 2   |  |
           |  |  +-----------------+  |
           |  |                       |
           |  |  +-----------------+  |
           |  |  | 'NAME'      10  |  |  .NAME 10
           |  |  |-----------------|  |
           |  |  | 'Fugue in C'    |  |
           |  |  +-----------------+  |
           |  |                       |
           |  |  +-----------------+  |
           |  |  | 'INS1'      9   |  |  .INS1 9
           |  |  |-----------------|  |
           |  |  |   1, 0, 0, 0,   |  |
           |  |  |   'Piano'       |  |
      94  <   |  +-----------------+  |
     bytes |  |    0                  |
           |  |  +-----------------+  |
           |  |  | 'INS1'      10  |  |  .INS1 10
           |  |  |-----------------|  |
           |  |  |   2, 0, 0, 0,   |  |
           |  |  |   'Guitar'      |  |
           |  |  +-----------------+  |
           |  |                       |
           |  |  +-----------------+  |
           |  |  | 'TRAK'       4  |  |  .TRAK 4
           |  |  |-----------------|  |
           |  |  | 60, 16, 128, 16 |  |
           |  |  +-----------------+  |
           |  |                       |
           |  |  +-----------------+  |
           |  |  | 'TRAK'       4  |  |  .TRAK 4
           |  |  |-----------------|  |
           |  |  | 128, 16, 60, 16 |  |
           |  |  +-----------------+  |
           |  |                       |
           -- +-----------------------+

The "0" after the first INS1 chunk is a pad byte.


SMUS IFF Simple Musical Score / Appendix C. Standards Committee

The following people contributed to the design of this SMUS standard:

Ralph Bellafatto, Cherry Lane Technologies
Geoff Brown, Uhuru Sound Software
Steve Hayes, Electronic Arts
Jerry Morrison, Electronic Arts


FORM Specifications from the Original EA Document / 8SVX IFF 8-Bit Sampled Voice

Date:	February 7, 1985 (Re-Typeset Oct, 1988 Commodore-Amiga, Inc.)
From:	Steve Hayes and Jerry Morrison, Electronic Arts
Status:	Adopted

 Introduction
 Standard Data and Property Chunks
 Appendix A. Quick Reference
 Appendix B. 8SVX Example
 Appendix C. Fibonacci Delta Compression


8SVX IFF 8-Bit Sampled Voice / Introduction

This is the IFF supplement for FORM "8SVX".  An 8SVX is an IFF "data
section" or "FORM" (which can be an IFF file or a part of one) containing
a digitally sampled audio voice consisting of 8-bit samples.  A voice can
be a one-shot sound or - with repetition and pitch scaling - a musical
instrument.  "EA IFF 85" is Electronic Arts' standard interchange file
format.  [See EA IFF 85 Standard for Interchange Format Files.]

The 8SVX format is designed for playback hardware that uses 8-bit samples
attenuated by a volume control for good overall signal-to-noise ratio.  So
a FORM 8SVX stores 8-bit samples and a volume level.

A similar data format (or two) will be needed for higher resolution
samples (typically 12 or 16 bits).  Properly converting a high resolution
sample down to 8 bits requires one pass over the data to find the minimum
and maximum values and a second pass to scale each sample into the range
-128 through 127. So it's reasonable to store higher resolution data in a
different FORM type and convert between them.

For instruments, FORM 8SVX can record a repeating waveform optionally
preceded by a startup transient waveform.  These two recorded signals can
be pre-synthesized or sampled from an acoustic instrument.  For many
instruments, this representation is compact.  FORM 8SVX is less practical
for an instrument whose waveform changes from cycle to cycle like a
plucked string, where a long sample is needed for accurate results.

FORM 8SVX can store an "envelope" or "amplitude contour" to enrich musical
notes.  A future voice FORM could also store amplitude, frequency, and
filter modulations.

FORM 8SVX is geared for relatively simple musical voices, where one
waveform per octave is sufficient, the waveforms for the different octaves
follow a factor-of-two size rule, and one envelope is adequate for all
octaves.  You could store a more general voice as a LIST containing one or
more FORMs 8SVX per octave.  A future voice FORM could go beyond one
"one-shot" waveform and one "repeat" waveform per octave.

Section 2 defines the required property sound header "VHDR", optional
properties name "NAME", copyright "(c)", and author "AUTH", the optional
annotation data chunk "ANNO", the required data chunk "BODY", and optional
envelope chunks "ATAK" and "RLSE".  These are the "standard" chunks.
Specialized chunks for private or future needs can be added later, e.g.,
to hold a frequency contour or Fourier series coefficients.  The 8SVX
syntax is summarized in Appendix A as a regular expression and in
Appendix B as an example box diagram.  Appendix C explains the optional
Fibonacci-delta compression algorithm.

 Reference


8SVX IFF 8-Bit Sampled Voice / Introduction / Reference

"EA IFF 85" Standard for Interchange Format Files describes the underlying
conventions for all IFF files.

Amiga® is a registered trademark of Commodore-Amiga, Inc.
Electronic Arts(tm) is a trademark of Electronic Arts.


8SVX IFF 8-Bit Sampled Voice / Standard Data and Property Chunks

FORM 8SVX stores all the waveform data in one body chunk "BODY".  It
stores playback parameters in the required header chunk "VHDR".  "VHDR"
and any optional property chunks "NAME", "(c) ", and "AUTH" must all
appear before the BODY chunk.  Any of these properties may be shared over
a LIST of FORMs 8SVX by putting them in a PROP 8SVX.  [See "EA IFF 85"
Standard for Interchange Format Files.]

 Background
 Required Property VHDR
 Optional Text Chunks
 Optional Data Chunks ATAK and RLSE
 Data Chunk BODY
 Other Chunks


Standard Data and Property Chunks / Background

There are two ways to use FORM 8SVX: as a one-shot sampled sound or as a
sampled musical instrument that plays "notes".  Storing both kinds of
sounds in the same kind of FORM makes it easy to play a one-shot sound as
an instrument or an instrument as a one-note sound.

A one-shot sound is a series of audio data samples with a nominal playback
rate and amplitude.  The recipient program can optionally adjust or
modulate the amplitude and playback data rate.

For musical instruments, the idea is to store a sampled (or
pre-synthesized) waveform that will be parameterized by pitch, duration,
and amplitude to play each "note".  The creator of the FORM 8SVX can
supply a waveform per octave over a range of octaves for this purpose.
The intent is to perform a pitch by selecting the closest octave's
waveform and scaling the playback data rate. An optional "one-shot"
waveform supplies an arbitrary startup transient, then a "repeat" waveform
is iterated as long as necessary to sustain the note.

A FORM 8SVX can also store an envelope to modulate the waveform.
Envelopes are mostly useful for variable-duration notes but could be used
for one-shot sounds, too.

The FORM 8SVX standard has some restrictions.  For example, each octave of
data must be twice as long as the next higher octave.  Most sound driver
software and hardware imposes additional restrictions.  E.g., the Amiga
sound hardware requires an even number of samples in each one-shot and
repeat waveform.


Standard Data and Property Chunks / Required Property VHDR

The required property "VHDR" holds a Voice8Header structure as defined in
these C declarations and following documentation.  This structure holds
the playback parameters for the sampled waveforms in the BODY chunk.  (See
"Data Chunk BODY", below, for the storage layout of these waveforms.)

#define ID_8SVX MakeID('8', 'S', 'V', 'X')
#define ID_VHDR MakeID('V', 'H', 'D', 'R')

typedef LONG Fixed;    /* A fixed-point value, 16 bits to the left of the
                          point and 16 to the right.  A Fixed is a number
                          of 2^16ths, i.e., 65536ths.                    */
#define Unity 0x10000L /* Unity = Fixed 1.0 = maximum volume             */

/* sCompression: Choice of compression algorithm applied to the samples. */
#define sCmpNone       0    /* not compressed                            */
#define sCmpFibDelta   1    /* Fibonacci-delta encoding (Appendix C)     */
                            /* Can be more kinds in the future.          */

typedef struct {
    ULONG oneShotHiSamples, /* # samples in the high octave 1-shot part */
          repeatHiSamples,  /* # samples in the high octave repeat part */
          samplesPerHiCycle;/* # samples/cycle in high octave, else 0   */
    UWORD samplesPerSec;    /* data sampling rate                       */
    UBYTE ctOctave,         /* # octaves of waveforms                   */
          sCompression;     /* data compression technique used          */
    Fixed volume;           /* playback volume from 0 to Unity (full
                             * volume). Map this value into the output
                             * hardware's dynamic range.                */
    } Voice8Header;

[Implementation details.  Fields are filed in the order shown.  The UBYTE
fields are byte-packed (2 per 16-bit word).  MakeID is a C macro defined
in the main IFF document and in the source file IFF.h.]

A FORM 8SVX holds waveform data for one or more octaves, each containing a
one-shot part and a repeat part.  The fields oneShotHiSamples and
repeatHiSamples tell the number of audio samples in the two parts of the
highest frequency octave.  Each successive (lower frequency) octave
contains twice as many data samples in both its one-shot and repeat parts.
One of these two parts can be empty across all octaves.

Note: Most audio output hardware and software has limitations.  For
example the Amiga computer has sound hardware that requires that all
one-shot and repeat parts have even numbers of samples.  Amiga sound
driver software should adjust an odd-sized waveform, ignore an odd-sized
lowest octave, or ignore odd 8SVX FORMs altogether.  Some other output
devices require all sample sizes to be powers of two.

The field samplesPerHiCycle tells the number of samples/cycle in the
highest frequency octave of data, or else 0 for "unknown".  Each
successive (lower frequency) octave contains twice as many samples/cycle.
The samplesPerHiCycle value is needed to compute the data rate for a
desired playback pitch.

Actually, samplesPerHiCycle is an average number of samples/cycle.  If the
one-shot part contains pitch bends, store the samples/cycle of the repeat
part in samplesPerHiCycle.  The division repeatHiSamples/samplesPerHiCycle
should yield an integer number of cycles.  (When the repeat waveform is
repeated, a partial cycle would come out as a higher-frequency cycle with
a "click".)

More limitations: some Amiga music drivers require samplesPerHiCycle to be
a power of two in order to play the FORM 8SVX as a musical instrument in
tune. They may even assume samplesPerHiCycle is a particular power of two
without checking.  (If samplesPerHiCycle is different by a factor of two,
the instrument will just be played an octave too low or high.)

The field samplesPerSec gives the sound sampling rate.  A program may
adjust this to achieve frequency shifts or vary it dynamically to achieve
pitch bends and vibrato.  A program that plays a FORM 8SVX as a musical
instrument would ignore samplesPerSec and select a playback rate for each
musical pitch.

The field ctOctave tells how many octaves of data are stored in the BODY
chunk.  See "Data Chunk BODY", below, for the layout of the octaves.

The field sCompression indicates the compression scheme, if any, that was
applied to the entire set of data samples stored in the BODY chunk.  This
field should contain one of the values defined above.  Of course, the
matching decompression algorithm must be applied to the BODY data before
the sound can be played.  (The Fibonacci-delta encoding scheme
sCmpFibDelta is described in Appendix C.)  Note that the whole series of
data samples is compressed as a unit.

The field volume gives an overall playback volume for the waveforms (all
octaves).  It lets the 8-bit data samples use the full range -128 through
127 for good signal-to-noise ratio.  The playback program should multiply
this value by a "volume control" and perhaps by a playback envelope (see
ATAK and RLSE, below).

Recording a one-shot sound.  To store a one-shot sound in a FORM 8SVX, set
oneShotHiSamples = number of samples, repeatHiSamples = 0 ,
samplesPerHiCycle = 0, samplesPerSec = sampling rate, and ctOctave = 1.
Scale the signal amplitude to the full sampling range -128 through 127.
Set volume so the sound will playback at the desired volume level.  If you
set the samplesPerHiCycle field properly, the data can also be used as a
musical instrument.

Experiment with data compression.  If the decompressed signal sounds OK,
store the compressed data in the BODY chunk and set sCompression to the
compression code number.

Recording a musical instrument.  To store a musical instrument in a FORM
8SVX, first record or synthesize as many octaves of data as you want to
make available for playback.  Set ctOctave to the count of octaves.  From
the recorded data, excerpt an integral number of steady state cycles for
the repeat part and set repeatHiSamples and samplesPerHiCycle.  Either
excerpt a startup transient waveform and set oneShotHiSamples, or else set
oneShotHiSamples to 0.  Remember, the one-shot and repeat parts of each
octave must be twice as long as those of the next higher octave.  Scale
the signal amplitude to the full sampling range and set volume to adjust
the instrument playback volume.  If you set the samplesPerSec field
properly, the data can also be used as a one-shot sound.

A distortion-introducing compressor like sCmpFibDelta is not recommended
for musical instruments, but you might try it anyway.

Typically, creators of FORM 8SVX record an acoustic instrument at just one
frequency.  Decimate (down-sample with filtering) to compute higher
octaves. Interpolate to compute lower octaves.

If you sample an acoustic instrument at different octaves, you may find it
hard to make the one-shot and repeat waveforms follow the factor-of-two
rule for octaves.  To compensate, lengthen an octave's one-shot part by
appending replications of the repeating cycle or prepending zeros.  (This
will have minimal impact on the sound's start time.)  You may be able to
equalize the ratio of one-shot-samples to repeat-samples across all
octaves.

Note that a "one-shot sound" may be played as a "musical instrument" and
vice-versa.  However, an instrument player depends on samplesPerHiCycle,
and a one-shot player depends on samplesPerSec.

Playing a one-shot sound.  To play any FORM 8SVX data as a one-shot sound,
first select an octave if ctOctave > 1.  (The lowest-frequency octave has
the greatest resolution.)  Play the one-shot samples then the repeat
samples, scaled by volume, at a data rate of samplesPerSec.  Of course,
you may adjust the playback rate and volume.  You can play out an
envelope, too.  (See ATAK and RLSE, below.)

Playing a musical note.  To play a musical note using any FORM 8SVX, first
select the nearest octave of data from those available.  Play the one-shot
waveform then cycle on the repeat waveform as long as needed to sustain
the note.  Scale the signal by volume, perhaps also by an envelope, and by
a desired note volume.  Select a playback data rate s samples/second to
achieve the desired frequency (in Hz):

    frequency = s / samplesPerHiCycle

for the highest frequency octave.

The idea is to select an octave and one of 12 sampling rates (assuming a
12-tone scale).  If the FORM 8SVX doesn't have the right octave, you can
decimate or interpolate from the available data.

When it comes to musical instruments, FORM 8SVX is geared for a simple
sound driver.  Such a driver uses a single table of 12 data rates to reach
all notes in all octaves.  That's why 8SVX requires each octave of data to
have twice as many samples as the next higher octave.  If you restrict
samplesPerHiCycle to a power of two, you can use a predetermined table of
data rates.


Standard Data and Property Chunks / Optional Text Chunks

Several text chunks may be included in a FORM 8SVX to keep ancillary
information.

The optional property "NAME" names the voice, for instance "tubular bells".

The optional property "(c) " holds a copyright notice for the voice.  The
chunk ID "(c) " serves as the copyright characters "(c) ".  E.g., a "(c) "
chunk containing "1986 Electronic Arts" means "(c) 1986 Electronic Arts".

The optional property "AUTH" holds the name of the instrument's "author"
or "creator".

The chunk types "NAME", "(c) ", and "AUTH" are property chunks.  Putting
more than one NAME (or other) property in a FORM is redundant.  Just the
last NAME counts.  A property should be shorter than 256 characters.
Properties can appear in a PROP 8SVX to share them over a LIST of FORMs
8SVX.

The optional data chunk "ANNO" holds any text annotations typed in by the
author.

An ANNO chunk is not a property chunk, so you can put more than one in a
FORM 8SVX.  You can make ANNO chunks any length up to 2^31 - 1 characters,
but 32767 is a practical limit.  Since they're not properties, ANNO chunks
don't belong in a PROP 8SVX.  That means they can't be shared over a LIST
of FORMs 8SVX.

Syntactically, each of these chunks contains an array of 8-bit ASCII
characters in the range " " (SP, hex 20) through "~" (tilde, hex 7F), just
like a standard "TEXT" chunk.  [See "Strings, String Chunks, and String
Properties" in "EA IFF 85" Electronic Arts Interchange File Format.] The
chunk's ckSize field holds the count of characters.

    #define ID_NAME MakeID('N', 'A', 'M', 'E')
    /* NAME chunk contains a CHAR[], the voice's name.		*/

    define ID_Copyright MakeID('(', 'c', ')', ' ')
    /* "(c) " chunk contains a CHAR[], the FORM's copyright notice.*/

    #define ID_AUTH MakeID('A', 'U', 'T', 'H')
    /* AUTH chunk contains a CHAR[], the author's name.		*/

    #define ID_ANNO MakeID('A', 'N', 'N', 'O')
    /* ANNO chunk contains a CHAR[], author's text annotations.	*/

Remember to store a 0 pad byte after any odd-length chunk.


Standard Data and Property Chunks / Optional Data Chunks ATAK and RLSE

The optional data chunks ATAK and RLSE together give a piecewise-linear
"envelope" or "amplitude contour".  This contour may be used to modulate
the sound during playback.  It's especially useful for playing musical
notes of variable durations.  Playback programs may ignore the supplied
envelope or substitute another.

    #define ID_ATAK MakeID('A', 'T', 'A', 'K')
    #define ID_RLSE MakeID('R', 'L', 'S', 'E')

    typedef struct {
        UWORD duration; /* segment duration in milliseconds, > 0 */
        Fixed dest;     /* destination volume factor             */
        } EGPoint;

    /* ATAK and RLSE chunks contain an EGPoint[],        *
     * piecewise-linear envelope.                        */
    /* The envelope defines a function of time returning *
     * Fixed values. It's used to scale the nominal      *
     * volume specified in the Voice8Header.             */

To explain the meaning of the ATAK and RLSE chunks, we'll overview the
envelope generation algorithm.  Start at 0 volume, step through the ATAK
contour, then hold at the sustain level (the last ATAK EGPoint's dest),
and then step through the RLSE contour.  Begin the release at the desired
note stop time minus the total duration of the release contour (the sum of
the RLSE EGPoints' durations).  The attack contour should be cut short if
the note is shorter than the release contour.

The envelope is a piecewise-linear function.  The envelope generator
interpolates between the EGPoints.

Remember to multiply the envelope function by the nominal voice header
volume and by any desired note volume.

Figure 1 shows an example envelope.  The attack period is described by 4
EGPoints in an ATAK chunk.  The release period is described by 4 EGPoints
in a RLSE chunk.  The sustain period in the middle just holds the final
ATAK level until it's time for the release.

        ^
(volume)|               |             |
    |       .       |             |
    |      / \      |             |
    |     /   \.__. |             |
    |    /         \|_____________|
    |   /           |             |\.__.
    |  /            |             |     \
        | /             |             |      \
        |/              |             |       \
        +-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|---------> (time)

              ATAK        sustain         RLSE

          Figure 1. Amplitude contour.

Note: The number of EGPoints in an ATAK or RLSE chunk is its ckSize /
sizeof(EGPoint).  In RAM, the playback program may terminate the array
with a 0 duration EGPoint.

Issue: Synthesizers also provide frequency contour (pitch bend), filtering
contour (wah-wah), amplitude oscillation (tremolo), frequency oscillation
(vibrato), and filtering oscillation (leslie).  In the future, we may
define optional chunks to encode these modulations.  The contours can be
encoded in linear segments.  The oscillations can be stored as segments
with rate and depth parameters.


Standard Data and Property Chunks / Data Chunk BODY

The BODY chunk contains the audio data samples.

    #define ID_BODY MakeID('B', 'O', 'D', 'Y')

    typedef character BYTE;  /* 8 bit signed number, -128 through 127. */
    /* BODY chunk contains a BYTE[], array of audio data samples.      */

The BODY contains data samples grouped by octave.  Within each octave are
one-shot and repeat portions.  Figure 2 depicts this arrangement of
samples for an 8SVX where oneShotHiSamples = 24, repeatHiSamples = 16,
samplesPerHiCycle = 8, and ctOctave = 3.  The major divisions are octaves,
the intermediate divisions separate the one-shot and repeat portions, and
the minor divisions are cycles.

        +-+-+-+-+-+---+---+---+---+---+------+------+------+------+------+
        | | | | | |   |   |   |   |   |      |      |      |      |      |
        |     |   |           |       |                    |             |
        |  O  | R |  One-shot | Repeat|       One-shot     |    Repeat   |
        |         |                   |                                  |
        |         |                   |                                  |
        |hi octave|    middle octave  |            low octave            |
        +---------+-------------------+----------------------------------+

        Figure 2. BODY subdivisions.

In general, the BODY has ctOctave octaves of data.  The highest frequency
octave comes first, comprising the fewest samples: oneShotHiSamples +
repeatHiSamples.  Each successive octave contains twice as many samples as
the next higher octave but the same number of cycles.  The lowest
frequency octave comes last with the most samples: 2^(ctOctave-1) *
(oneShotHiSamples + repeatHiSamples).

The number of samples in the BODY chunk is

        ( 2^0 + ... + 2^(ctOctave-1) ) * (oneShotHiSamples + repeatHiSamples)

Figure 3, below, looks closer at an example waveform within one octave of
a different BODY chunk.  In this example, oneShotHiSamples /
samplesPerHiCycle = 2 cycles and repeatHiSamples / samplesPerHiCycle = 1
cycle.

        ^
(volume)|              |        /\   |        /\   |
        |              |       |  \  |       |  \  |
        |     /\       |       |   \ |       |   \ |
        |    /  \    /\|       /    \|       /    \|
        +---/----\--/--+------/------+------/------+
        |\ /      \/   |\    |       |\    |       |
        | V            | \   |       | \   |       |
        |              |  \ /        |  \ /        |
        |              |   V         |   V         |
        +--------------+-------------+-------------+----> (time)
           one-shot         repeat        repeat

           Figure 3. Example waveform.

To avoid playback "clicks" the one-shot part should begin with a small
sample value, and  flow smoothly into the repeat part.  The end of the
repeat part should flow smoothly into the beginning of the next repeat
part.

If the VHDR field sCompression != sCmpNone, the BODY chunk is just an
array of data bytes to feed through the specified decompresser function.
All this stuff about sample sizes, octaves, and repeat parts applies to
the decompressed data.

Be sure to follow an odd-length BODY chunk with a 0 pad byte.


Standard Data and Property Chunks / Other Chunks

Issue: In the future, we may define an optional chunk containing Fourier
series coefficients for a repeating waveform.  An editor for this kind of
synthesized voice could modify the coefficients and regenerate the
waveform.

See the IFF Registry and the Third-Party Specification section for details
on additional 8SVX Chunks such as CHAN, PAN, SEQN and FADE.


8SVX IFF 8-Bit Sampled Voice / Appendix A. Quick Reference

 Type Definitions
 8SVX Regular Expression


Appendix A. Quick Reference / Type Definitions

#define ID_8SVX MakeID('8', 'S', 'V', 'X')
#define ID_VHDR MakeID('V', 'H', 'D', 'R')

typedef LONG Fixed;    /* A fixed-point value, 16 bits to the left of  *
                          the point and 16 to the right. A Fixed is a  *
                          number of 2^16ths, i.e., 65536ths.           */
#define Unity 0x10000L /* Unity = Fixed 1.0 = maximum volume           */

/* sCompression: Choice of compression algorithm.                    */
#define sCmpNone       0    /* not compressed                        */
#define sCmpFibDelta   1    /* Fibonacci-delta encoding (Appendix C) */
                            /* Can be more kinds in the future.      */

typedef struct {
    ULONG oneShotHiSamples, /* # samples in the high octave 1-shot part */
          repeatHiSamples,  /* # samples in the high octave repeat part */
          samplesPerHiCycle;/* # samples/cycle in high octave, else 0   */
    UWORD samplesPerSec;    /* data sampling rate                       */
    UBYTE ctOctave,         /* # octaves of waveforms                   */
          sCompression;     /* data compression technique used          */
    Fixed volume;           /* playback volume from 0 to Unity (full    *
                             * volume). Map this value into the output  *
                             * hardware's dynamic range.                */
    } Voice8Header;

#define ID_NAME MakeID('N', 'A', 'M', 'E')
/* NAME chunk contains a CHAR[], the voice's name.                     */

#define ID_Copyright MakeID('(', 'c', ')', ' ')
/* "(c) " chunk contains a CHAR[], the FORM's copyright notice.        */

#define ID_AUTH MakeID('A', 'U', 'T', 'H')
/* AUTH chunk contains a CHAR[], the author's name.                    */

#define ID_ANNO MakeID('A', 'N', 'N', 'O')
/* ANNO chunk contains a CHAR[], author's text annotations.            */

#define ID_ATAK MakeID('A', 'T', 'A', 'K')
#define ID_RLSE MakeID('R', 'L', 'S', 'E')

typedef struct {
    UWORD duration; /* segment duration in milliseconds, > 0           */
    Fixed dest;     /* destination volume factor                       */
    } EGPoint;

/* ATAK and RLSE chunks contain an EGPoint[],piecewise-linear envelope. */
/* The envelope defines a function of time returning Fixed values. It's *
 * used to scale the nominal volume specified in the Voice8Header.      */

#define ID_BODY MakeID('B', 'O', 'D', 'Y')
typedef character BYTE;     /* 8 bit signed number, -128 through 127.   */
/* BODY chunk contains a BYTE[], array of audio data samples.           */


Appendix A. Quick Reference / 8SVX Regular Expression

Here's a regular expression summary of the FORM 8SVX syntax.  This could
be an IFF file or part of one.

    8SVX     ::= "FORM" #{  "8SVX" VHDR [NAME] [Copyright] [AUTH] ANNO*
                            [ATAK] [RLSE] BODY }

    VHDR     ::= "VHDR" #{ Voice8Header     }
    NAME     ::= "NAME" #{ CHAR*    } [0]
    Copyright::= "(c) " #{ CHAR*    } [0]
    AUTH     ::= "AUTH" #{ CHAR*    } [0]
    ANNO     ::= "ANNO" #{ CHAR*    } [0]

    ATAK     ::= "ATAK" #{ EGPoint* }
    RLSE     ::= "RLSE" #{ EGPoint* }
    BODY     ::= "FORM" #{ BYTE*    } [0]

The token "#" represents a ckSize LONG count of the following {braced}
data bytes.  E.g., a VHDR's "#" should equal sizeof(Voice8Header).
Literal items are shown in "quotes", [square bracket items] are optional,
and "*" means 0 or more replications.  A sometimes-needed pad byte is
shown as "[0]".

Actually, the order of chunks in a FORM 8SVX is not as strict as this
regular expression indicates.  The property chunks VHDR, NAME, Copyright,
and AUTH may actually appear in any order as long as they all precede the
BODY chunk.  The optional data chunks ANNO, ATAK, and RLSE don't have to
precede the BODY chunk.  And of course, new kinds of chunks may appear
inside a FORM 8SVX in the future.


8SVX IFF 8-Bit Sampled Voice / Appendix B. 8SVX Example

Here's a box diagram for a simple example containing the three octave BODY
shown earlier in Figure 2.

                  +--------------------------+
                  |                          |
                  |  'FORM'            362   |  FORM 362 8SVX
                  |                          |
               -  +--------------------------+
               |  |                          |
               |  |    '8SVX'                |
               |  |                          |
               |  |  +--------------------+  |
               |  |  |  'VHDR'       20   |  |  .VHDR 20
               |  |  |--------------------|  |
               |  |  |  24, 16, 8, 10000, |  |
               |  |  |  3, 0, 1.0         |  |
               |  |  +--------------------+  |
               |  |                          |
               |  |  +--------------------+  |
               |  |  |  'NAME'       11   |  |  .NAME 11
               |  |  |--------------------|  |
               |  |  |  'bass guitar'     |  |
          368 <   |  +--------------------+  |
         bytes |  |     0                    |
               |  |  +--------------------+  |
               |  |  |  '(c) '        20  |  |
               |  |  |--------------------|  |  .(c)  20
               |  |  |'1985 Electronic    |  |
               |  |  | Arts'              |  |
               |  |  +--------------------+  |
               |  |                          |
               |  |  +--------------------+  |
               |  |  |  'BODY'      280   |  |
               |  |  |--------------------|  |  .BODY 280
               |  |  |  1, 2, 3, 4....    |  |
               |  |  +--------------------+  |
               |  |                          |
               -- +--------------------------+

The "0" after the NAME chunk is a pad byte.


8SVX IFF 8-Bit Sampled Voice / Appendix C. Fibonacci Delta Compression

This is Steve Hayes' Fibonacci Delta sound compression technique.  It's
like the traditional delta encoding but encodes each delta in a mere 4
bits.  The compressed data is half the size of the original data plus a
2-byte overhead for the initial value.  This much compression introduces
some distortion, so try it out and use it with discretion.

To achieve a reasonable slew rate, this algorithm looks up each stored
4-bit value in a table of Fibonacci numbers.  So very small deltas are
encoded precisely while larger deltas are approximated.  When it has to
make approximations, the compressor should adjust all the values (forwards
and backwards in time) for minimum overall distortion.

Here is the decompressor written in the C programming language.

    /* Fibonacci delta encoding for sound data. */
    BYTE codeToDelta[16] = {-34,-21,-13,-8,-5,-3,-2,-1,0,1,2,3,5,8,13,21};

    /* Unpack Fibonacci-delta encoded data from n byte source buffer into
     * 2*n byte dest buffer, given initial data value x.  It returns the
     * last data value x so you can call it several times to incrementally
     * decompress the data.                                             */
    short D1Unpack(source, n, dest, x)
        BYTE source[], dest[];
        LONG n;
        BYTE x;
        {
        BYTE d;
        LONG i, lim;

        lim = n << 1;
        for (i = 0; i < lim; ++i)
                { /* Decode a data nybble; high nybble then low nybble. */
                d = source[i >> 1];     /* get a pair of nybbles        */
                if (i & 1)              /* select low or high nybble?   */
                        d &= 0xf;       /* mask to get the low nybble   */
                else
                        d >>= 4;        /* shift to get the high nybble */
                x += codeToDelta[d];    /* add in the decoded delta     */
                dest[i] = x;            /* store a 1-byte sample        */
                }
        return(x);
        }

    /* Unpack Fibonacci-delta encoded data from n byte source buffer into
     * 2*(n-2) byte dest buffer. Source buffer has a pad byte, an 8-bit
     * initial value, followed by n-2 bytes comprising 2*(n-2) 4-bit
     * encoded samples.                                                 */

    void DUnpack(source, n, dest)
        BYTE source[], dest[];
        LONG n;
        {
          D1Unpack(source + 2, n - 2, dest, source[1]);
        }


A / Additional Documents

           Intro to IFF Amiga ILBM Files and Amiga Viewmodes

The IFF (Interchange File Format) for graphic images on the Amiga is
called FORM ILBM (InterLeaved BitMap).  It follows a standard parsable IFF
format.

 Sample hex dump of beginning of an ILBM
 Interpreting ILBMs
 Body Compression
 Interpreting the Scan Line Data
 How Amiga HAM mode works
 How Amiga HALFBRITE mode works
 Other Notes


Additional Info / Sample hex dump of beginning of an ILBM

Important note!  You can NOT ever depend on any particular ILBM chunk
being at any particular offset into the file!  IFF files are composed, in
their simplest form, of chunks within a FORM.  Each chunk starts starts
with a 4-letter chunkID, followed by a 32-bit length of the rest of the
chunk.  You PARSE IFF files, skipping past unneeded or unknown chunks by
seeking their length (+1 if odd length) to the next 4-letter chunkID.

0000: 464F524D 00016418 494C424D 424D4844    FORM..d.ILBMBMHD
0010: 00000014 01400190 00000000 06000100    .....@..........
0020: 00000A0B 01400190 43414D47 00000004    .....@..CAMG....
0030: 00000804 434D4150 00000030 001100EE    ....CMAP...0....
0040: EEEE0000 22000055 33333355 55550033    .... ..P000PPP.0
0050: 99885544 77777711 66EE2266 EE6688DD    ..P@ppp.`. `.`..
0060: AAAAAAAA 99EECCCC CCDDAAEE 424F4459    ............BODY
0070: 000163AC F8000F80 148A5544 2ABDEFFF    ..c.......UD*...  etc.

Interpretation:

      'F O R M' length  'I L B M''B M H D'<-start of BitMapHeader chunk
0000: 464F524D 00016418 494C424D 424D4844    FORM..d.ILBMBMHD

       length  WideHigh XorgYorg PlMkCoPd <- Planes Mask Compression Pad
0010: 00000014 01400190 00000000 06000100    .....@..........

                                             start of C-AMiGa
      TranAspt PagwPagh 'C A M G' length  <- View modes chunk
0020: 00000A0B 01400190 43414D47 00000004    .....@..CAMG....

      Viewmode 'C M A P' length  R g b R  <- Viewmode 800=HAM | 4=LACE
0030: 00000804 434D4150 00000030 001100EE    ....CMAP...0....

      g b R g  b R g b  R g b R  g b R g  <- Rgb's are for reg0 thru regN
0040: EEEE0000 22000055 33333355 55550033    .... ..P000PPP.0

      b R g b  R g b R  g b R g  b R g b
0050: 99885544 77777711 66EE2266 EE6688DD    ..P@ppp.`. `.`..

      R g b R  g b R g  b R g b 'B O D Y'
0060: AAAAAAAA 99EECCCC CCDDAAEE 424F4459    ............BODY

                                             Compacted
       length   start of body data        <- (Compression=1 above)
0070: 000163AC F8000F80 148A5544 2ABDEFFF    ..c.......UD*...
0080: FFBFF800 0F7FF7FC FF04F85A 77AD5DFE    ...........Zw.].  etc.

Notes on CAMG Viewmodes:  HIRES=0x8000  LACE=0x4  HAM=0x800  HALFBRITE=0x80


Additional Info / Interpreting ILBMs

ILBM is a fairly simple IFF FORM.  All you really need to deal with to
extract the image are the following chunks:

(Note - Also watch for AUTH Author chunks and (c) Copyright chunks
 and preserve any copyright information if you rewrite the ILBM)

   BMHD - info about the size, depth, compaction method
          (See interpreted hex dump above)

   CAMG - optional Amiga viewmodes chunk
          Most HAM and HALFBRITE ILBMs should have this chunk.  If no
          CAMG chunk is present, and image is 6 planes deep, assume
          HAM and you'll probably be right.  Some Amiga viewmodes
          flags are HIRES=0x8000, LACE=0x4, HAM=0x800, HALFBRITE=0x80.
      Note that new Amiga 2.0 ILBMs may have more complex 32-bit
      numbers (modeid) stored in the CAMG.  However, the bits
      described above should get you a compatible old viewmode.

   CMAP - RGB values for color registers 0 to n
          (each component left justified in a byte)
      If a deep ILBM (like 12 or 24 planes), there should be no CMAP
      and instead the BODY planes are interpreted as the bits of RGB
      in the order R0...Rn G0...Gn B0...Bn

   BODY - The pixel data, stored in an interleaved fashion as follows:
          (each line individually compacted if BMHD Compression = 1)
             plane 0 scan line 0
             plane 1 scan line 0
             plane 2 scan line 0
             ...
             plane n scan line 0
             plane 0 scan line 1
             plane 1 scan line 1
             etc.


Additional Info / Body Compression

The BODY contains pixel data for the image.  Width, Height, and depth
(Planes) is specified in the BMHD.

If the BMHD Compression byte is 0, then the scan line data is not
compressed. If Compression=1, then each scan line is individually
compressed as follows:

More than 2 bytes the same stored as BYTE code value n from  -1 to -127
  followed by byte to be repeated (-n) + 1 times.
Varied bytes stored as BYTE code n from 0 to 127 followed by n+1 bytes
of data.

The byte code -128 is a NOP.


Additional Info / Interpreting the Scan Line Data

If the ILBM is not HAM or HALFBRITE, then after parsing and uncompacting
if necessary, you will have N planes of pixel data.  Color register used
for each pixel is specified by looking at each pixel thru the planes.
I.e., if you have 5 planes, and the bit for a particular pixel is set in
planes 0 and 3:

       PLANE     4 3 2 1 0
       PIXEL     0 1 0 0 1

then that pixel uses color register binary 01001 = 9

The RGB value for each color register is stored in the CMAP chunk of the
ILBM, starting with register 0, with each register's RGB value stored as
one byte of R, one byte G, and one byte of B, with each component scaled
to 8-bits.  (ie. 4-bit Amiga R, G, and B components are each stored in the
high nibble of a byte.  The low nibble may also contain valid data if the
color was stored with 8-bit-per-gun color resolution).

BUT - if the picture is HAM or HALFBRITE, it is interpreted differently.
                        ===    =========

Hopefully, if the picture is HAM or HALFBRITE, the package that saved it
properly saved a CAMG chunk (look at a hex dump of your file with ACSII
interpretation - you will see the chunks - they all start with a 4-ASCII-
character chunk ID).  If the picture is 6 planes deep and has no CAMG
chunk, it is probably HAM.   If you see a CAMG chunk, the "CAMG" is
followed by the 32-bit chunk length, and then the 32-bit Amiga Viewmode
flags.

HAM pics with a 16-bit CAMG will have the 0x800 bit set in CAMG ViewModes.
HALBRITE pics will have the 0x80 bit set.

To transport a HAM or HALFBRITE picture to another machine, you must
understand how HAM and HALFBRITE work on the Amiga.


Additional Info / How Amiga HAM mode works

Amiga HAM (Hold and Modify) mode lets the Amiga display all 4096 RGB
values. In HAM mode, the bits in the two last planes describe an R G or B
modification to the color of the previous pixel on the line to create the
color of the current pixel.  So a 6-plane HAM picture has 4 planes for
specifying absolute color pixels giving up to 16 absolute colors which
would be specified in the ILBM CMAP chunk.  The bits in the last two
planes are color modification bits which cause the Amiga, in HAM mode, to
take the RGB value of the previous pixel (Hold and), substitute the 4 bits
in planes 0-3 for the previous color's R G or B component (Modify) and
display the result for the current pixel.  If the first pixel of a scan
line is a modification pixel, it modifies the RGB value of the border
color (register 0).  The color modification bits in the last two planes
(planes 4 and 5) are interpreted as follows:

   00 - no modification.  Use planes 0-3 as normal color register index
   10 - hold previous, replacing Blue component with bits from planes 0-3
   01 - hold previous, replacing Red component with bits from planes 0-3
   11 - hold previous. replacing Green component with bits from planes 0-3


Additional Info / How Amiga HALFBRITE mode works

This one is simpler.  In HALFBRITE mode, the Amiga interprets the bit in
the last plane as HALFBRITE modification.  The bits in the other planes
are treated as normal color register numbers (RGB values for each color
register is specified in the CMAP chunk).  If the bit in the last plane is
set (1), then that pixel is displayed at half brightness.  This can
provide up to 64 absolute colors.


Additional Info / Other Notes

Amiga ILBMs images must be a even number of bytes wide.  Smaller images
(such as brushes) are padded to an even byte width.

ILBMs created with Electronic Arts IBM and Amiga "DPaintII" packages are
compatible (though you may have to use a '.lbm' filename extension on an
IBM).  The ILBM graphic files may be transferred between the machines (or
between the Amiga and IBM sides your Amiga if you have a CBM Bridgeboard
card installed) and loaded into either package.


A / IFF Source Code / IFF Include Files

This section contains a variety of source code listings showing how to use
IFF files in applications.  All of these programs require the new
iffparse.library inluded with Release 2.0 of the Amiga operating system
(Kickstart V36 and greater).  There are four parts:

* IFF Include Files.  These have been updated to be compatible with the
iffparse.library.

* Link modules which provide convenient IFF handling routines such as
showilbm.c.

* Example programs showing how to use the link modules.

* Stand-alone utility and example programs.

 IFFP_Modules.README

 Makefile.SAS        8svxapp.h        debug.h       ilbmapp.h
 Makefile.Manx       amiga.h          iff.h         packer.h
 8svx.h              compiler.h       ilbm.h        smus.h


A / IFF Source Code / Source listings of examples

 24bitDemo.c    Play8SVX.c      getbitmap.c     packer.c        unpacker.c
 ILBMDemo.c     RawtoILBM.c     getdisplay.c    parse.c         clipftxt.c
 ILBMLoad.c     ScreenSave.c    ilbmr.c         saveilbm.c      cycvb.c
 ILBMtoC.c      bmprintc.c      ilbmw.c         screen.c        ilbmscan.c
 ILBMtoRaw.c    copychunks.c    loadilbm.c      screendump.c    sift.c


Devices/iffp/iff.h

/*
 *
 * iff.h:	General Definitions for IFFParse modules
 *
 * 6/27/91
 */

#ifndef IFFP_IFF_H
#define IFFP_IFF_H

#include "iffp/compiler.h"

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif
#ifndef EXEC_MEMORY_H
#include <exec/memory.h>
#endif
#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif
#ifndef UTILITY_HOOKS_H
#include <utility/hooks.h>
#endif
#ifndef LIBRARIES_IFFPARSE_H
#include <libraries/iffparse.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef MYDEBUG_H
#include "iffp/debug.h"
#endif

#ifndef NO_PROTOS
#include <clib/exec_protos.h>
#include <clib/iffparse_protos.h>
#endif

#ifndef MAX
#define	MAX(a,b)	((a) > (b) ? (a) : (b))
#endif
#ifndef MIN
#define	MIN(a,b)	((a) < (b) ? (a) : (b))
#endif
#ifndef ABS
#define	ABS(x)		((x) < 0 ? -(x) : (x))
#endif

#define CkErr(expression)  {if (!error) error = (expression);}
#define ChunkMoreBytes(cn)	(cn->cn_Size - cn->cn_Scan)
#define IS_ODD(a)		(a & 1)

#define IFF_OKAY	0L
#define	CLIENT_ERROR	1L
#define NOFILE          5L

#define message printf

/* Generic Chunk ID's we may encounter */
#define	ID_ANNO		MAKE_ID('A','N','N','O')
#define	ID_AUTH		MAKE_ID('A','U','T','H')
#define	ID_CHRS		MAKE_ID('C','H','R','S')
#define	ID_Copyright	MAKE_ID('(','c',')',' ')
#define	ID_CSET		MAKE_ID('C','S','E','T')
#define	ID_FVER		MAKE_ID('F','V','E','R')
#define	ID_NAME		MAKE_ID('N','A','M','E')
#define ID_TEXT		MAKE_ID('T','E','X','T')
#define ID_BODY		MAKE_ID('B','O','D','Y')

/* Used to keep track of allocated IFFHandle, and whether file is
 * clipboard or not, filename, copied chunks, etc.
 * This structure is included in the beginning of every
 * form-specific info structure used by the example modules.
 */
struct ParseInfo {
    /* general parse.c related */
    struct  IFFHandle *iff;		/* to be alloc'd with AllocIFF */
    UBYTE	*filename;		/* current filename of this ui */
    LONG	*propchks;		/* properties to get */
    LONG	*collectchks;		/* properties to collect */
    LONG	*stopchks;		/* stop on these (like BODY) */
    BOOL    opened;			/* this iff has been opened */
    BOOL	clipboard;		/* file is clipboard */
    BOOL	hunt;			/* we are parsing a complex file */
    BOOL	Reserved1;		/* must be zero for now */

    /* for copychunks.c - for read/modify/write programs
     * and programs that need to keep parsed chunk info
     * around after closing file.
     * Deallocated by freechunklist();
     */
    struct Chunk *copiedchunks;

    /* application may hang its own list of new chunks here
     * just to keep it with the frame.
     */
    struct Chunk *newchunks;

    ULONG	Reserved[8];
    };

/*
 * Used by some modules to save or pass a singly linked list of chunks
 */
struct Chunk {
    struct  Chunk *ch_Next;
    long	ch_Type;
    long	ch_ID;
        long    ch_Size;
        void    *ch_Data;
};

#ifndef NO_PROTOS
/* parse.c */
LONG openifile(struct ParseInfo *,UBYTE *,ULONG);
void closeifile(struct ParseInfo *);
LONG parseifile(struct ParseInfo *,
        LONG, LONG, LONG *, LONG *, LONG *);
LONG getcontext(struct IFFHandle *);
LONG nextcontext(struct IFFHandle *);
LONG currentchunkis(struct IFFHandle *, LONG type, LONG id);
LONG contextis(struct IFFHandle *, LONG type, LONG id);
UBYTE *findpropdata(struct IFFHandle *iff, LONG type, LONG id);
void initiffasstdio(struct IFFHandle *);
UBYTE *IFFerr(LONG);
LONG chkcnt(LONG *);
long PutCk(struct IFFHandle *iff, long id, long size, void *data);

/* copychunks.c */
struct Chunk *copychunks(struct IFFHandle *iff,
                 LONG *propchks, LONG *collectchks, ULONG memtype);
void freechunklist(struct Chunk *first);
struct Chunk *findchunk(struct Chunk *first, long type, long id);
long writechunklist(struct IFFHandle *iff, struct Chunk *first);
#endif /* NO_PROTOS */

#endif /* IFFP_IFF_H */


Devices/IFFP_Modules.README

            IFFP Modules - July 1991
                 version 37.5

These iffparse.library code modules and examples are designed as
replacements for the original EA IFF code.  In some modules, it has been
possible to retain much of the original code.  However, most structures
and most higher level function interfaces have changed.

On the plus side, these new modules contain many new high-level
easy-to-use functions for querying, loading, displaying, and saving ILBMs.
During their development, modules similar to these have been used inhouse
at Commodore for the 2.0 Display program and several other ILBM
applications.  The screen.c module provides powerful display-opening
functions which are 1.3-compatible yet provide a host of new options under
2.0 such as centered overscan screens, full-video display clips, border
transparency control, and autoscroll.  New modules have been added for
printing (screendump) and for preserving/adding chunks (copychunks). And
the 8SVX example now actually plays samples and instruments. In addition,
clipboard support is automatic for all applications that use the IFFP
modules because parse.c's openifile() interprets the filename -c[n] (ie.
"-c", "-c1", "-c2", etc.) as clipboard unit n.

All of the applications presented here require iffparse.library which is
distributed on Workbench 2.0.  Please note that iffparse.library is a
1.3-compatible library, and that all of these modules and examples have
been designed to take advantage of 2.0, but also work under 1.3.
Developers who wish to distribute iffparse.library on their commercial
products may execute a 2.0 Workbench license, or may get an addendum to
their 1.3 Workbench license to allow distribution of iffparse.library.

It was not necessary to port the gio IO speedup code since iffparse can
use your compiler's own buffered IO routines through the callback
stdio_stream() in parse.c.  Depending on your application, you may want to
add your own additional buffering to this stdio_stream() code.

Most of the high-level function pairs provided in these modules have been
designed to provide safe cleanup for themselves.  For example, a
loadbrush() that succeeds or fails at any point can be cleaned up via
unloadbrush.  The cleanup routines null out the appropriate pointers so
that allocations will not be freed twice.

All applications are built upon the parse.c module.  The basic concept of
using the parse.c module are:

    - Define tag-like arrays of your desired chunks (readers only)
    - Allocates one or more [form]Info structures as defined in
        iffp/[form]app.h (for example an ILBMInfo defined in
        iffp/ilbmapp.h).
    - Initialize the ParseInfo part of these structures to the desired
        chunk arrays, and to an IFFHandle allocated via iffparse
        AllocIFF().
    - Use the provided high level load/save functions, or use the
        lower level parse.c openifile(), reader-only parseifile()/
        getcontext()/nextcontext(), and closeifile().  The filename
        -c[n] may be used to read/write clipboard unit n.
    - Clean up, FreeIFF(), and deallocate [form]Info's.

IMPORTANT NOTES - Most of the higher-level load functions keep the
    IFFHandle (file or clipboard) open.  While the handle is
    open, you may use parse.c functions (such as findpropdata)
    OR direct iffparse functions (FindProp(), FindCollection())
    for accessing the gathered chunks.  However, it is not a good
    idea to keep a filehandle OR the clipboard open.  While
    a clipboard unit is open, no other applications can clip
    to the unit.  And while a file is open, you can't write the
    file back out.  So, instead of keeping the file or unit
    open, you can use copychunks (in copychunks.c) to create
    a copy of your gathered chunks, and do an early closeifile()
    (parse.c).  Then access and later write back out (if you wish)
    and deallocate your copied chunks via the routines in the
    copychunks module (findchunk, writechunklist, freechunklist).

WARNING REGARDING COMPLEX FORMS
        Regarding Complex FORMs - The parse.c module will enter complex
    formats such as CATSs, LISTs, and nested FORMs to find the FORM
    that you are interested in.  This is great.  However, if you are
        a read-modify-write program, you should warn your user when this
        occurs unless YOU are capable of recreating the complex format.
    Otherwise, your user may unknowingly destroy his complex file
    by writing over it with your program.  Example - a paint
    program could read an ILBM out of a complex LIST containing
    pictures and music, and then save it back out as a simple ILBM,
    causing the user to lose his music and other pictures.
    To determine if a complex form was entered after a load,
    check the (form)Info.ParseInfo.hunt field.  If TRUE (non-zero),
    then your file was found inside a complex format.

COMPILATION NOTES
    These modules and examples have been compiled using SAS C 5.10a
    and Manx C 5.0d, with 2.0 (37.1) include files and 2.0 amiga.lib.
    You must have at least 37.1 alib_protos.h (older versions of
    this include file contained the amiga.lib stdio protos also
    which conflict with both SAS and Manx stdio).  For Manx, I
    also had to comment out the conditional definition of abs() in
    libraries/mathffp.h.  These modules do not use mathffp, but
    the mathffp include file is pulled in by alib_protos.h.
    When compiling with Manx, a warning seems to be generated for
    each string constant assigned to a UBYTE * field, and also
    by some references to ilbm->colortable.

        LIST OF IFFP MODULES AND APPLICATIONS
                -------------------------------------
    NOTE - Some useful functions are listed with each module
        See module source code for docs on each function.

APPLICATIONS (these require linkage with modules - see Makefiles)
------------
ILBMDemo	Displays an ILBM, loads a brush, saves an ILBM, opt. print
ILBMLoad	Queries an ILBM and loads it into an existing screen
ILBMtoC		Outputs an ILBM as C source code
ILBMtoRaw	Converts an ILBM to raw plane/color file
RawtoILBM	Converts raw plane/color file (from ILBMtoRaw) to an ILBM
24bitDemo	Saves a simple 24-bit ILBM and then shows it 4 planes at
        a time (if given filename, just does the show part)
Play8SVX	Reads and plays an 8SVX sound effect or instrument
          - LoadSample, UnloadSample, PlaySample, OpenAudio,
            CloseAudio, and body load/unpack functions
ScreenSave	Save the front screen as an ILBM, with an icon

OTHER EXAMPLES (use iffparse.library directly and require no modules)
--------------
Sift		Checks and prints outline of any IFF file (uses RAWSTEP)
ILBMScan	Prints out useful info about any ILBM
ClipFTXT	Demonstrates simply clipping of FTXT to/from clipboard
cycvb.c		Dan Silva's routine for interrupt based color cycling
apack.asm	Dr. Gerald Hull's assembler replacement for packer.c

GENERAL IFFPARSE SUPPORT MODULE
-------------------------------
parse.c		File/clipboard IO and general parsing
          - openifile, closeifile, parseifile, getcontext,
            nextcontext, contextis, currentchunkis, PutCk chunk
            writing function, and IFFerr text error routine

ILBM READ MODULES
-----------------
loadilbm.c      High level ILBM load routines which are passed filenames
        (calls getbitmap)
          - loadbrush/unloadbrush,loadilbm/unloadilbm,and queryilbm
getbitmap.c	brush/bitmap loading (non-display, calls ilbmr.c)
          - createbrush/deletebrush, getbitmap/freebitmap
getdisplay.c	bitmap load/display (calls screen.c, ilbmr.c)
          - showilbm/unshowilbm, createdisplay/deletedisplay
screen.c	1.3/2.0 ECS/non-ECS compatible screen/window module
          - opendisplay, openidscreen, modefallback, clipit
ilbmr.c		Lower level ILBM body/color load routines(calls unpacker.c)
          - loadbody, loadcmap, getcolors/freecolors,
            alloccolortable, getcamg (gets or creates modeid)
unpacker.c	BODY unpacker

ILBM WRITE MODULES
------------------
saveilbm.c	High level ILBM saving routines which are passed filenames
        (calls ilbmw.c)
          - screensave and saveilbm
ilbmw.c		Lower level ILBM body/color save routines (calls packer.c)
          - InitBMHD, PutCMAP, PutBODY
packer.c	BODY packer

EXTRA MODULES
-------------
copychunks.c	Chunk cloning and chunk list writing routines
          - copychunks, findchunk, writechunklist, freechunklist
screendump.c	Screen printing module (iffparse not required)
bmprintc.c	Module to output ILBM as C code

INCLUDE FILES
-------------
iffp/#?.h	This subdirectory may be kept in your current directory
        or in your main include directory.

Thanks to Steve Walton for his code changes for Manx/SAS compatibility,
and to Bill Barton and John Bittner for their comments and suggestions.


Devices/Makefile.SAS

#MYLIBS= LIB:debug.lib

CC = lc
ASM = asm

CFLAGS = -cfistq -v -j73 -iINCLUDE:
AFLAGS = -iINCLUDE:
LFLAGS = SC BATCH ND

M      = modules/
A      = apps/

# Our iffparse support object modules to link with
IFFO      = $(M)parse.o $(M)Hook.o
ILBMRO    = $(M)ilbmr.o $(M)unpacker.o
ILBMSO    = $(M)getdisplay.o $(M)screen.o
ILBMLO    = $(M)loadilbm.o $(M)getbitmap.o
ILBMWO    = $(M)saveilbm.o $(M)ilbmw.o $(M)packer.o
ILBMO     = $(IFFO) $(ILBMRO) $(ILBMLO) $(ILBMSO) $(ILBMWO)
EXTRAO    = $(M)copychunks.o $(M)screendump.o $(M)bmprintc.o

# Our iffparse applications
APP1   = $(A)ILBMDemo/ILBMDemo
APP2   = $(A)ILBMLoad/ILBMLoad
APP3   = $(A)Play8SVX/Play8SVX
APP4   = $(A)ILBMtoC/ILBMtoC
APP5   = $(A)ILBMtoRaw/ILBMtoRaw
APP6   = $(A)ScreenSave/ScreenSave
APP7   = $(A)RawtoILBM/RawtoILBM
APP8   = $(A)24bitDemo/24bitDemo

# The object modules needed by each application example
APP1O  = $(APP1).o $(ILBMO) $(M)screendump.o $(M)copychunks.o
APP2O  = $(APP2).o $(IFFO) $(ILBMRO) $(ILBMLO) $(ILBMSO)
APP3O  = $(APP3).o $(IFFO)
APP4O  = $(APP4).o $(IFFO) $(ILBMRO) $(ILBMLO) $(M)bmprintc.o
APP5O  = $(APP5).o $(IFFO) $(ILBMRO) $(ILBMLO)
APP6O  = $(APP6).o $(IFFO) $(ILBMWO)
APP7O  = $(APP7).o $(IFFO) $(ILBMWO)
APP8O  = $(APP8).o $(IFFO) $(ILBMRO) $(ILBMLO) $(ILBMSO) $(ILBMWO)

.SUFFIXES:
.SUFFIXES:	.o .c .h .asm .i

# Make all of the applications
all:	$(APP1) $(APP2) $(APP3) $(APP4) $(APP5) $(APP6) $(APP7) $(APP8)

# Linkage for each application

$(APP1): $(APP1O)
  blink <WITH <
FROM lib:c.o $(APP1O)
LIBRARY lib:lc.lib LIB:amiga.lib $(MYLIBS)
TO $(APP1) $(LFLAGS)
<

$(APP2): $(APP2O)
  blink <WITH <
FROM lib:c.o $(APP2O)
LIBRARY lib:lc.lib LIB:amiga.lib $(MYLIBS)
TO $(APP2) $(LFLAGS)
<

$(APP3): $(APP3O)
  blink <WITH <
FROM lib:c.o $(APP3O)
LIBRARY lib:lc.lib LIB:amiga.lib $(MYLIBS)
TO $(APP3) $(LFLAGS)
<

$(APP4): $(APP4O)
  blink <WITH <
FROM lib:c.o $(APP4O)
LIBRARY lib:lc.lib LIB:amiga.lib $(MYLIBS)
TO $(APP4) $(LFLAGS)
<

$(APP5): $(APP5O)
  blink <WITH <
FROM lib:c.o $(APP5O)
LIBRARY lib:lc.lib LIB:amiga.lib $(MYLIBS)
TO $(APP5) $(LFLAGS)
<

$(APP6): $(APP6O)
  blink <WITH <
FROM lib:c.o $(APP6O)
LIBRARY lib:lc.lib LIB:amiga.lib $(MYLIBS)
TO $(APP6) $(LFLAGS)
<

$(APP7): $(APP7O)
  blink <WITH <
FROM lib:c.o $(APP7O)
LIBRARY lib:lc.lib LIB:amiga.lib $(MYLIBS)
TO $(APP7) $(LFLAGS)
<

$(APP8): $(APP8O)
  blink <WITH <
FROM lib:c.o $(APP8O)
LIBRARY lib:lc.lib LIB:amiga.lib $(MYLIBS)
TO $(APP8) $(LFLAGS)
<

.c.o:
    $(CC) $(CFLAGS) $*.c

.asm.o:
    $(ASM) $(AFLAGS) $*.asm


Devices/iffp/8svxapp.h

/* 8svxapp.h
 * - definition of EightSVXInfo structure
 * - inclusion of includes needed by modules and application
 * - application-specific definitions
 */
#ifndef EIGHTSVXAPP_H
#define EIGHTSVXAPP_H

#include "iffp/8svx.h"

#include <devices/audio.h>

#define MAXOCT 16

struct EightSVXInfo {
    /* general parse.c related */
    struct  ParseInfo ParseInfo;

    /* For convenient access to VHDR, Name, and sample.
     * Other chunks will be accessible through FindProp()
         *  (or findchunk() if the chunks have been copied)
     */
    /* 8SVX */
    Voice8Header	Vhdr;

    BYTE		*sample;
    ULONG		samplebytes;

    BYTE		*osamps[MAXOCT];
    ULONG		osizes[MAXOCT];
    BYTE		*rsamps[MAXOCT];
    ULONG		rsizes[MAXOCT];
    ULONG		spcycs[MAXOCT];

    UBYTE		name[80];

    ULONG		Reserved[8];	/* must be 0 for now */

    /* Applications may add variables here */
    };

/* referenced by modules */
extern struct Library *IFFParseBase;

#endif


Devices/iffp/debug.h

/*
 * mydebug.h - #include this file sometime after stdio.h
 * Set MYDEBUG to 1 to turn on debugging, 0 to turn off debugging
 */

#ifndef MYDEBUG_H
#define MYDEBUG_H

#define MYDEBUG	 0

#if MYDEBUG

/*
 * MYDEBUG User Options
 */

/* Set to 1 to turn second level D2(bug()) statements */
#define DEBUGLEVEL2	1

/* Set to a non-zero # of ticks if a delay is wanted after each debug message */
#define DEBUGDELAY		0

/* Always non-zero for the DDx macros */
#define DDEBUGDELAY		50

/* Set to 1 for serial debugging (link with debug.lib) */
#define KDEBUG		0

/* Set to 1 for parallel debugging (link with ddebug.lib) */
#define DDEBUG		0

#endif /* MYDEBUG */

/* Prototypes for Delay, kprintf, dprintf. Or use proto/dos.h or functions.h. */
#include <clib/dos_protos.h>
void kprintf(UBYTE *fmt,...);
void dprintf(UBYTE *fmt,...);

/*
 * D(bug()), D2(bug()), DQ((bug()) only generate code if MYDEBUG is non-zero
 *
 * Use D(bug()) for general debugging, D2(bug()) for extra debugging that
 * you usually won't need to see, DD(bug()) for debugging statements that
 * you always want followed by a delay, and DQ(bug()) for debugging that
 * you'll NEVER want a delay after (ie. debugging inside a Forbid, Disable,
 * Task, or Interrupt)
 *
 * Some example uses (all are used the same):
 * D(bug("about to do xyz. variable = $%lx\n",myvariable));
 * D2(bug("v1=$%lx v2=$%lx v3=$%lx\n",v1,v2,v3));
 * DQ(bug("in subtask: variable = $%lx\n",myvariable));
 * DD(bug("About to do xxx\n"));
 *
 * Set MYDEBUG above to 1 when debugging is desired and recompile the modules
 *  you wish to debug.  Set to 0 and recompile to turn off debugging.
 *
 * User options set above:
 * Set DEBUGDELAY to a non-zero # of ticks (ex. 50) when a delay is desired.
 * Set DEBUGLEVEL2 nonzero to turn on second level (D2) debugging statements
 * Set KDEBUG to 1 and link with debug.lib for serial debugging.
 * Set DDEBUG to 1 and link with ddebug.lib for parallel debugging.
 */

/*
 * Debugging function automaticaly set to printf, kprintf, or dprintf
 */

#if KDEBUG
#define bug kprintf
#elif DDEBUG
#define bug dprintf
#else	/* else changes all bug's to printf's */
#define bug printf
#endif

/*
 * Debugging macros
 */

/* D(bug( 	delays DEBUGDELAY if DEBUGDELAY is > 0
 * DD(bug(	always delays DDEBUGDELAY
 * DQ(bug(      (debug quick) never uses Delay.  Use in forbids,disables,ints
 * The similar macros with "2" in their names are second level debugging
 */
#if MYDEBUG    /* Turn on first level debugging */
#define D(x)  (x); if(DEBUGDELAY>0) Delay(DEBUGDELAY)
#define DD(x) (x); Delay(DDEBUGDELAY)
#define DQ(x) (x)
#if DEBUGLEVEL2 /* Turn on second level debugging */
#define D2(x)  (x); if(DEBUGDELAY>0) Delay(DEBUGDELAY)
#define DD2(x) (x); Delay(DDEBUGDELAY)
#define DQ2(x) (x)
#else  /* Second level debugging turned off */
#define D2(x) ;
#define DD2(x) ;
#define DQ2(x) ;
#endif /* DEBUGLEVEL2 */
#else  /* First level debugging turned off */
#define D(x) ;
#define DQ(x) ;
#define D2(x) ;
#define DD(x) ;
#endif

#endif /* MYDEBUG_H */


Devices/iffp/ilbmapp.h

/* ilbmapp.h
 * - definition of ILBMInfo structure
 * - inclusion of includes needed by modules and application
 * - application-specific definitions
 *
 * 07/03/91 - added ilbm->stags for screen.c
 */
#ifndef ILBMAPP_H
#define ILBMAPP_H

#include "iffp/ilbm.h"

struct ILBMInfo {
    /* general parse.c related */
    struct  ParseInfo ParseInfo;

    /* The following variables are for
     * programs using the ILBM-related modules.
     * They may be removed or replaced for
     * programs parsing other forms.
     */
    /* ILBM */
    BitMapHeader Bmhd;		/* filled in by load and save ops */
    ULONG	camg;			/* filled in by load and save ops */
    Color4	*colortable;		/* allocated by getcolors */
    ULONG	ctabsize;		/* size of colortable in bytes */
    USHORT	ncolors;		/* number of color registers loaded */
    USHORT  Reserved1;

    /* for getbitmap.c */
    struct BitMap *brbitmap;	/* for loaded brushes only */

    /* for screen.c */
    struct Screen *scr;		/* screen of loaded display   */
    struct Window *win;		/* window of loaded display   */
    struct ViewPort *vp;		/* viewport of loaded display */
    struct RastPort	*srp;		/* screen's rastport */
    struct RastPort *wrp;		/* window's rastport */
    BOOL TBState;			/* state of titlebar hiddenness */

    /* caller preferences */
    struct NewWindow *windef;	/* definition for window */
    UBYTE *stitle;		/* screen title */
    LONG stype;		/* additional screen types */
    WORD ucliptype;		/* overscan display clip type */
    BOOL EHB;		/* default to EHB for 6-plane/NoCAMG */
    BOOL Video;		/* Max Video Display Clip (non-adjustable) */
    BOOL Autoscroll;	/* Enable Autoscroll of screens */
    BOOL Notransb;		/* Borders not transparent to genlock */
    ULONG *stags;		/* Additional screen tags for 2.0 screens */

    ULONG Reserved[7];	/* must be 0 for now */

    /* Application-specific variables may go here */
    };

/* referenced by modules */

extern struct Library *IFFParseBase;

/* protos for application module(s) */

#endif


Devices/Makefile.Manx

#MYLIBS= LIB:debug.lib

CC = cc
ASM = as

CFLAGS = -IWork:manxinclude
AFLAGS =
LFLAGS =

M      = modules/
A      = apps/

# Our iffparse support object modules to link with
IFFO      = $(M)parse.o $(M)Hook.o
ILBMRO    = $(M)ilbmr.o $(M)unpacker.o
ILBMSO    = $(M)getdisplay.o $(M)screen.o
ILBMLO    = $(M)loadilbm.o $(M)getbitmap.o
ILBMWO    = $(M)saveilbm.o $(M)ilbmw.o $(M)packer.o
ILBMO     = $(IFFO) $(ILBMRO) $(ILBMLO) $(ILBMSO) $(ILBMWO)
EXTRAO    = $(M)copychunks.o $(M)screendump.o $(M)bmprintc.o

# Our iffparse applications
APP1   = $(A)ILBMDemo/ILBMDemo
APP2   = $(A)ILBMLoad/ILBMLoad
APP3   = $(A)Play8SVX/Play8SVX
APP4   = $(A)ILBMtoC/ILBMtoC
APP5   = $(A)ILBMtoRaw/ILBMtoRaw
APP6   = $(A)ScreenSave/ScreenSave
APP7   = $(A)RawtoILBM/RawtoILBM
APP8   = $(A)24bitDemo/24bitDemo

# The object modules needed by each application example
APP1O  = $(APP1).o $(ILBMO) $(M)screendump.o $(M)copychunks.o
APP2O  = $(APP2).o $(IFFO) $(ILBMRO) $(ILBMLO) $(ILBMSO)
APP3O  = $(APP3).o $(IFFO)
APP4O  = $(APP4).o $(IFFO) $(ILBMRO) $(ILBMLO) $(M)bmprintc.o
APP5O  = $(APP5).o $(IFFO) $(ILBMRO) $(ILBMLO)
APP6O  = $(APP6).o $(IFFO) $(ILBMWO)
APP7O  = $(APP7).o $(IFFO) $(ILBMWO)
APP8O  = $(APP8).o $(IFFO) $(ILBMRO) $(ILBMLO) $(ILBMSO) $(ILBMWO)

.SUFFIXES:
.SUFFIXES:	.o .c .h .asm .i

# Make all of the applications
all:	$(APP1) $(APP2) $(APP3) $(APP4) $(APP5) $(APP6) $(APP7) $(APP8)

# Linkage for each application

$(APP1): $(APP1O)
    ln -o $(APP1) $(LFLAGS) $(APP1O) -lc +l amiga.lib

$(APP2): $(APP2O)
    ln -o $(APP2) $(LFLAGS) $(APP2O) -lc +l amiga.lib

$(APP3): $(APP3O)
    ln -o $(APP3) $(LFLAGS) $(APP3O) -lc +l amiga.lib

$(APP4): $(APP4O)
    ln -o $(APP4) $(LFLAGS) $(APP4O) -lc +l amiga.lib

$(APP5): $(APP5O)
    ln -o $(APP5) $(LFLAGS) $(APP5O) -lc +l amiga.lib

$(APP6): $(APP6O)
    ln -o $(APP6) $(LFLAGS) $(APP6O) -lc +l amiga.lib

$(APP7): $(APP7O)
    ln -o $(APP7) $(LFLAGS) $(APP7O) -lc +l amiga.lib

$(APP8): $(APP8O)
    ln -o $(APP8) $(LFLAGS) $(APP8O) -lc +l amiga.lib

.c.o:
    cc $(CFLAGS) -o $*.o $*.c

.asm.o:
    as $(AFLAGS) -o $*.o $*.asm


Devices/iffp/amiga.h

/* IFF application include files
 */

#ifndef  AMIGA_H
#define  AMIGA_H

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/libraries.h>

#include <libraries/dos.h>

#include <intuition/intuition.h>
#include <intuition/screens.h>

#include <graphics/view.h>
#include <graphics/displayinfo.h>
#include <graphics/videocontrol.h>
#include <graphics/gfxmacros.h>

#include <libraries/iffparse.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/iffparse_protos.h>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "iffp/debug.h"

#endif


Devices/iffp/packer.h

#ifndef PACKER_H
#define PACKER_H
/*----------------------------------------------------------------------*
 * PACKER.H  typedefs for Data-Compresser.  		        1/22/86
 *
 * This module implements the run compression algorithm "cmpByteRun1"; the
 * same encoding generated by Mac's PackBits.
 *
 * By Jerry Morrison and Steve Shaw, Electronic Arts.
 * This software is in the public domain.
 *
 * This version for the Amiga computer.
 *----------------------------------------------------------------------*/

#include <exec/types.h>

/* This macro computes the worst case packed size of a "row" of bytes. */
#define MaxPackedSize(rowSize)  ( (rowSize) + ( ((rowSize)+127) >> 7 ) )

/* Given POINTERS to POINTER variables, packs one row, updating the source
 * and destination pointers. Returns the size in bytes of the packed row.
 * ASSUMES destination buffer is large enough for the packed row.
 * See MaxPackedSize. */
extern LONG PackRow(BYTE **, BYTE **, LONG);
        /*  pSource, pDest,   rowSize */

/* Given POINTERS to POINTER variables, unpacks one row, updating the source
 * and destination pointers until it produces dstBytes bytes (i.e., the
 * rowSize that went into PackRow).
 * If it would exceed the source's limit srcBytes or if a run would overrun
 * the destination buffer size dstBytes, it stops and returns TRUE.
 * Otherwise, it returns FALSE (no error). */
extern BOOL UnPackRow(BYTE **, BYTE **, WORD,     WORD);
          /*  pSource, pDest,   srcBytes, dstBytes  */

BYTE *PutDump(BYTE *, int);
BYTE *PutRun(BYTE *,int,int);
LONG PackRow(BYTE **,BYTE **,LONG);
BOOL UnPackRow(BYTE **,BYTE **,WORD,WORD);

#endif


Devices/iffp/8svx.h

/*-----------------------------------------------------------------------*
 * 8SVX.H  Definitions for 8-bit sampled voice (VOX).   2/10/86
 *
 * By Jerry Morrison and Steve Hayes, Electronic Arts.
 * This software is in the public domain.
 *
 * Modified for use with iffparse.library 05/91 - CAS_CBM
 *
 * This version for the Amiga computer.
 *----------------------------------------------------------------------*/
#ifndef EIGHTSVX_H
#define EIGHTSVX_H

#ifndef COMPILER_H
#include "iffp/compiler.h"
#endif

#include "iffp/iff.h"

#define ID_8SVX      MAKE_ID('8', 'S', 'V', 'X')
#define ID_VHDR      MAKE_ID('V', 'H', 'D', 'R')

#define ID_ATAK      MAKE_ID('A', 'T', 'A', 'K')
#define ID_RLSE      MAKE_ID('R', 'L', 'S', 'E')

/* defined in iffp/iff.h
#define ID_NAME      MAKE_ID('N', 'A', 'M', 'E')
#define ID_Copyright MAKE_ID('(', 'c', ')', ' ')
#define ID_AUTH      MAKE_ID('A', 'U', 'T', 'H')
#define ID_ANNO      MAKE_ID('A', 'N', 'N', 'O')
#define ID_BODY      MAKE_ID('B', 'O', 'D', 'Y')
*/

/* ---------- Voice8Header ---------------------------------------------*/
typedef LONG Fixed;	/* A fixed-point value, 16 bits to the left of
             * the point and 16 to the right. A Fixed is a
             * number of 2**16ths, i.e. 65536ths. */
#define Unity 0x10000L	/* Unity = Fixed 1.0 = maximum volume */

/* sCompression: Choice of compression algorithm applied to the samples. */
#define sCmpNone       0	/* not compressed */
#define sCmpFibDelta   1	/* Fibonacci-delta encoding (Appendix C) */
                /* Could be more kinds in the future. */
typedef struct {
    ULONG oneShotHiSamples,	/* # samples in the high octave 1-shot part */
          repeatHiSamples,	/* # samples in the high octave repeat part */
          samplesPerHiCycle;	/* # samples/cycle in high octave, else 0 */
    UWORD samplesPerSec;	/* data sampling rate */
    UBYTE ctOctave,		/* # of octaves of waveforms */
          sCompression;		/* data compression technique used */
    Fixed volume;		/* playback nominal volume from 0 to Unity
                 * (full volume). Map this value into
                 * the output hardware's dynamic range.
                 */
    } Voice8Header;

/* ---------- NAME -----------------------------------------------------*/
/* NAME chunk contains a CHAR[], the voice's name. */

/* ---------- Copyright ------------------------------------------------*/
/* "(c) " chunk contains a CHAR[], the FORM's copyright notice. */

/* ---------- AUTH -----------------------------------------------------*/
/* AUTH chunk contains a CHAR[], the author's name. */

/* ---------- ANNO -----------------------------------------------------*/
/* ANNO chunk contains a CHAR[], the author's text annotations. */

/* ---------- Envelope ATAK & RLSE -------------------------------------*/
typedef struct {
    UWORD duration;	/* segment duration in milliseconds, > 0 */
    Fixed dest;		/* destination volume factor */
    } EGPoint;

/* ATAK and RLSE chunks contain an EGPoint[], piecewise-linear envelope. */

/* The envelope defines a function of time returning Fixed values.
 * It's used to scale the nominal volume specified in the Voice8Header.
 */

/* ---------- BODY -----------------------------------------------------*/
/* BODY chunk contains a BYTE[], array of audio data samples. */
/* (8-bit signed numbers, -128 through 127.) */

/* ---------- 8SVX Writer Support Routines -----------------------------*/

/* Just call this macro to write a VHDR chunk. */
#define PutVHDR(iff, vHdr)  \
    PutCk(iff, ID_VHDR, sizeof(Voice8Header), (BYTE *)vHdr)

#endif


Devices/iffp/compiler.h

#ifndef COMPILER_H
#define COMPILER_H
/*** compiler.h *********************************************************/
/*  Steve Shaw							1/29/86 */
/*  Portability file to handle compiler idiosyncrasies.			*/
/*                                                                      */
/* This software is in the public domain.                               */
/* modified 05/91 for use with iffparse - CAS_CBM                       */
/************************************************************************/

#ifndef EXEC_TYPES_H
#include "exec/types.h"
#endif

/*
#define NO_PROTOS
*/

#endif COMPILER_H


Devices/iffp/ilbm.h

/*
 *
 * ilbm.h:	Definitions for IFFParse ILBM reader.
 *
 * 6/27/91
 */

#ifndef IFFP_ILBM_H
#define IFFP_ILBM_H

#ifndef IFFP_IFF_H
#include "iffp/iff.h"
#endif

#ifndef INTUITION_INTUITION_H
#include <intuition/intuition.h>
#endif
#ifndef GRAPHICS_VIDEOCONTROL_H
#include <graphics/videocontrol.h>
#endif

#ifndef NO_PROTOS
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
#include <clib/alib_protos.h>
#endif

/*  IFF types we may encounter  */
#define	ID_ILBM		MAKE_ID('I','L','B','M')

/* ILBM Chunk ID's we may encounter
 * (see iffp/iff.h for some other generic chunks)
 */
#define	ID_BMHD		MAKE_ID('B','M','H','D')
#define	ID_CMAP		MAKE_ID('C','M','A','P')
#define	ID_CRNG		MAKE_ID('C','R','N','G')
#define	ID_CCRT		MAKE_ID('C','C','R','T')
#define	ID_GRAB		MAKE_ID('G','R','A','B')
#define	ID_SPRT		MAKE_ID('S','P','R','T')
#define	ID_DEST		MAKE_ID('D','E','S','T')
#define	ID_CAMG		MAKE_ID('C','A','M','G')

/* Use this constant instead of sizeof(ColorRegister). */
#define sizeofColorRegister  3

typedef WORD Color4;   /* Amiga RAM version of a color-register,
          * with 4 bits each RGB in low 12 bits.*/

/* Maximum number of bitplanes storable in BitMap structure */
#define MAXAMDEPTH 8
#define MAXAMCOLORREG 32

/* Maximum planes we can save */
#define MAXSAVEDEPTH 24

/* convert width to BytesPerRow */
#define	BytesPerRow(w)	((w) + 15 >> 4 << 1)
#define BitsPerRow(w)	((w) + 15 >> 4 << 4)

/* Flags that should be masked out of old 16-bit CAMG before save or use.
 * Note that 32-bit mode id (non-zero high word) bits should not be twiddled
 */
#define BADFLAGS  (SPRITES|VP_HIDE|GENLOCK_AUDIO|GENLOCK_VIDEO)
#define OLDCAMGMASK  (~BADFLAGS)

/*  Masking techniques  */
#define	mskNone			0
#define	mskHasMask		1
#define	mskHasTransparentColor	2
#define	mskLasso		3

/*  Compression techniques  */
#define	cmpNone			0
#define	cmpByteRun1		1

#define RowBytes(w)	((((w) + 15) >> 4) << 1)

/* ---------- BitMapHeader ---------------------------------------------*/
/*  Required Bitmap header (BMHD) structure describes an ILBM */
typedef struct {
    UWORD	w, h;		/* Width, height in pixels */
    WORD	x, y;		/* x, y position for this bitmap  */
    UBYTE	nPlanes;	/* # of planes (not including mask) */
    UBYTE	masking;	/* a masking technique listed above */
    UBYTE	compression;	/* cmpNone or cmpByteRun1 */
    UBYTE	reserved1;	/* must be zero for now */
    UWORD	transparentColor;
    UBYTE	xAspect, yAspect;
    WORD	pageWidth, pageHeight;
} BitMapHeader;

/* ---------- ColorRegister --------------------------------------------*/
/* A CMAP chunk is a packed array of ColorRegisters (3 bytes each). */
typedef struct {
    UBYTE red, green, blue;   /* MUST be UBYTEs so ">> 4" won't sign extend.*/
    } ColorRegister;

/* ---------- Point2D --------------------------------------------------*/
/* A Point2D is stored in a GRAB chunk. */
typedef struct {
    WORD x, y;      /* coordinates (pixels) */
    } Point2D;

/* ---------- DestMerge ------------------------------------------------*/
/* A DestMerge is stored in a DEST chunk. */
typedef struct {
    UBYTE depth;   /* # bitplanes in the original source */
    UBYTE pad1;      /* UNUSED; for consistency store 0 here */
    UWORD planePick;   /* how to scatter source bitplanes into destination */
    UWORD planeOnOff;   /* default bitplane data for planePick */
    UWORD planeMask;   /* selects which bitplanes to store into */
    } DestMerge;

/* ---------- SpritePrecedence -----------------------------------------*/
/* A SpritePrecedence is stored in a SPRT chunk. */
typedef UWORD SpritePrecedence;

/* ---------- Camg Amiga Viewport Mode ---------------------------------*/
/* A Commodore Amiga ViewPort->Modes is stored in a CAMG chunk. */
/* The chunk's content is declared as a LONG. */
typedef struct {
   ULONG ViewModes;
   } CamgChunk;

/* ---------- CRange cycling chunk -------------------------------------*/
#define RNG_NORATE  36   /* Dpaint uses this rate to mean non-active */
/* A CRange is store in a CRNG chunk. */
typedef struct {
    WORD  pad1;              /* reserved for future use; store 0 here */
    WORD  rate;      /* 60/sec=16384, 30/sec=8192, 1/sec=16384/60=273 */
    WORD  active;     /* bit0 set = active, bit 1 set = reverse */
    UBYTE low, high;   /* lower and upper color registers selected */
    } CRange;

/* ---------- Ccrt (Graphicraft) cycling chunk -------------------------*/
/* A Ccrt is stored in a CCRT chunk. */
typedef struct {
   WORD  direction;  /* 0=don't cycle, 1=forward, -1=backwards */
   UBYTE start;      /* range lower */
   UBYTE end;        /* range upper */
   LONG  seconds;    /* seconds between cycling */
   LONG  microseconds; /* msecs between cycling */
   WORD  pad;        /* future exp - store 0 here */
   } CcrtChunk;

/* If you are writing all of your chunks by hand,
 * you can use these macros for these simple chunks.
 */
#define putbmhd(iff, bmHdr)  \
    PutCk(iff, ID_BMHD, sizeof(BitMapHeader), (BYTE *)bmHdr)
#define putgrab(iff, point2D)  \
    PutCk(iff, ID_GRAB, sizeof(Point2D), (BYTE *)point2D)
#define putdest(iff, destMerge)  \
    PutCk(iff, ID_DEST, sizeof(DestMerge), (BYTE *)destMerge)
#define putsprt(iff, spritePrec)  \
    PutCk(iff, ID_SPRT, sizeof(SpritePrecedence), (BYTE *)spritePrec)
#define putcamg(iff, camg)  \
    PutCk(iff, ID_CAMG, sizeof(CamgChunk),(BYTE *)camg)
#define putcrng(iff, crng)  \
    PutCk(iff, ID_CRNG, sizeof(CRange),(BYTE *)crng)
#define putccrt(iff, ccrt)  \
    PutCk(iff, ID_CCRT, sizeof(CcrtChunk),(BYTE *)ccrt)

#ifndef NO_PROTOS
/* unpacker.c */
BOOL unpackrow(BYTE **pSource, BYTE **pDest, WORD srcBytes0, WORD dstBytes0);

/* packer.c */
LONG packrow(BYTE **pSource, BYTE **pDest, LONG rowSize);

/* ilbmr.c  ILBM reader routines */
LONG loadbody(struct IFFHandle *iff, struct BitMap *bitmap,
        BitMapHeader *bmhd);
LONG loadbody2(struct IFFHandle *iff, struct BitMap *bitmap,
        BYTE *mask, BitMapHeader *bmhd,
        BYTE *buffer, ULONG bufsize);
LONG loadcmap(struct IFFHandle *, WORD *colortable, USHORT *pNcolors);
LONG getcolors(struct ILBMInfo *ilbm);
void freecolors(struct ILBMInfo *ilbm);
LONG alloccolortable(struct ILBMInfo *ilbm);
ULONG getcamg(struct ILBMInfo *ilbm);

/* ilbmw.c  ILBM writer routines */
long initbmhd(BitMapHeader *bmhd, struct BitMap *bitmap,
              WORD masking, WORD compression, WORD transparentColor,
              WORD width, WORD height, WORD pageWidth, WORD pageHeight,
              ULONG modeid);
long putcmap(struct IFFHandle *iff,APTR colortable,UWORD ncolors,UWORD bitspergun);
long putbody(struct IFFHandle *iff, struct BitMap *bitmap,
        BYTE *mask, BitMapHeader *bmHdr,
        BYTE *buffer, LONG bufsize);

/* getdisplay.c (used to load a display) */
LONG showilbm(struct ILBMInfo *ilbm, UBYTE *filename);
void unshowilbm(struct ILBMInfo *ilbm);
LONG createdisplay(struct ILBMInfo *);
void deletedisplay(struct ILBMInfo *);
LONG getdisplay(struct ILBMInfo *);
void freedisplay(struct ILBMInfo *);

/* getbitmap.c (used if just loading brush or bitmap) */
LONG createbrush(struct ILBMInfo *);
void deletebrush(struct ILBMInfo *);
LONG getbitmap(struct ILBMInfo *);
void freebitmap(struct ILBMInfo *);

/* screen.c (opens 1.3 or 2.0 screen) */
struct Screen *openidscreen(struct ILBMInfo *,SHORT,SHORT,SHORT,ULONG);
struct Window *opendisplay(struct ILBMInfo *,SHORT,SHORT,SHORT,ULONG);
ULONG  modefallback(ULONG, SHORT, SHORT, SHORT);
void clipit(SHORT wide, SHORT high, struct Rectangle *spos,
    struct Rectangle *dclip, struct Rectangle *txto,
    struct Rectangle *stdo,struct Rectangle *maxo,
    struct Rectangle * uclip);
void closedisplay(struct ILBMInfo *);
void modeErrorMsg(ULONG,ULONG);

/* loadilbm.c */
LONG loadbrush(struct ILBMInfo *ilbm, UBYTE *filename);
void unloadbrush(struct ILBMInfo *ilbm);

LONG queryilbm(struct ILBMInfo *ilbm, UBYTE *filename);

LONG loadilbm(struct ILBMInfo *ilbm, UBYTE *filename);
void unloadilbm(struct ILBMInfo *ilbm);

/* saveilbm.c */
LONG screensave(struct ILBMInfo *ilbm,
            struct Screen *scr,
            struct Chunk *chunklist1, struct Chunk *chunklist2,
            UBYTE *filename);

LONG saveilbm(struct ILBMInfo *ilbm,
        struct BitMap *bitmap, ULONG modeid,
        WORD width, WORD height, WORD pagewidth, WORD pageheight,
        APTR colortable, UWORD count, UWORD bitspergun,
                WORD masking, WORD transparentColor,
        struct Chunk *chunklist1, struct Chunk *chunklist2,
        UBYTE *filename);

/* screendump.c (print screen or brush) */
int screendump(struct Screen *scr,
     UWORD srcx, UWORD srcy, UWORD srcw, UWORD srch,
     LONG destcols, UWORD special);

/* bmprintc.c (write C source for ILBM) */
void BMPrintCRep(struct BitMap *bm, FILE *fp, UBYTE *name, UBYTE *fmt);

#endif /* NO_PROTOS */

#endif /* IFFP_ILBM_H */


Devices/iffp/smus.h

/*----------------------------------------------------------------------*
 * SMUS.H  Definitions for Simple MUSical score.   2/12/86
 *
 * By Jerry Morrison and Steve Hayes, Electronic Arts.
 * This software is in the public domain.
 *
 * Modified for use with iffparse.library 05/91 - CAS_CBM
 *
 * This version for the Amiga computer.
 *----------------------------------------------------------------------*/

#ifndef SMUS_H
#define SMUS_H

#ifndef COMPILER_H
#include "iffp/compiler.h"
#endif

#include "iffp/iff.h"

#define ID_SMUS      MAKE_ID('S', 'M', 'U', 'S')
#define ID_SHDR      MAKE_ID('S', 'H', 'D', 'R')

/* Now defined in iffp/iff.h as generic chunks
#define ID_NAME      MAKE_ID('N', 'A', 'M', 'E')
#define ID_Copyright MAKE_ID('(', 'c', ')', ' ')
#define ID_AUTH      MAKE_ID('A', 'U', 'T', 'H')
#define ID_ANNO      MAKE_ID('A', 'N', 'N', 'O')
*/

#define ID_INS1      MAKE_ID('I', 'N', 'S', '1')
#define ID_TRAK      MAKE_ID('T', 'R', 'A', 'K')

/* ---------- SScoreHeader ---------------------------------------------*/
typedef struct {
    UWORD tempo;	/* tempo, 128ths quarter note/minute */
    UBYTE volume;	/* playback volume 0 through 127 */
    UBYTE ctTrack;	/* count of tracks in the score */
    } SScoreHeader;

/* ---------- NAME -----------------------------------------------------*/
/* NAME chunk contains a CHAR[], the musical score's name. */

/* ---------- Copyright (c) --------------------------------------------*/
/* "(c) " chunk contains a CHAR[], the FORM's copyright notice. */

/* ---------- AUTH -----------------------------------------------------*/
/* AUTH chunk contains a CHAR[], the name of the score's author. */

/* ---------- ANNO -----------------------------------------------------*/
/* ANNO chunk contains a CHAR[], the author's text annotations. */

/* ---------- INS1 -----------------------------------------------------*/
/* Constants for the RefInstrument's "type" field. */
#define INS1_Name  0	/* just use the name; ignore data1, data2 */
#define INS1_MIDI  1	/* <data1, data2> = MIDI <channel, preset> */

typedef struct {
    UBYTE iRegister;	/* set this instrument register number */
    UBYTE type;		/* instrument reference type (see above) */
    UBYTE data1, data2;	/* depends on the "type" field */
    char name[60];	/* instrument name */
    } RefInstrument;

/* ---------- TRAK -----------------------------------------------------*/
/* TRAK chunk contains an SEvent[]. */

/* SEvent: Simple musical event. */
typedef struct {
    UBYTE sID;		/* SEvent type code */
    UBYTE data;		/* sID-dependent data */
    } SEvent;

/* SEvent type codes "sID". */
#define SID_FirstNote     0
#define SID_LastNote    127	/* sIDs in the range SID_FirstNote through
                 * SID_LastNote (sign bit = 0) are notes. The
                 * sID is the MIDI tone number (pitch). */
#define SID_Rest        128	/* a rest; same data format as a note. */

#define SID_Instrument  129	/* set instrument number for this track. */
#define SID_TimeSig     130	/* set time signature for this track. */
#define SID_KeySig	131	/* set key signature for this track. */
#define SID_Dynamic	132	/* set volume for this track. */
#define SID_MIDI_Chnl	133	/* set MIDI channel number (sequencers) */
#define SID_MIDI_Preset	134	/* set MIDI preset number (sequencers) */
#define SID_Clef        135     /* inline clef change.
                                 * 0=Treble, 1=Bass, 2=Alto, 3=Tenor. */
#define SID_Tempo       136     /* Inline tempo change in beats per minute.*/

/* SID values 144 through 159: reserved for Instant Music SEvents. */

/* The remaining sID values up through 254: reserved for future
 * standardization. */
#define SID_Mark        255	/* SID reserved for an end-mark in RAM. */

/* ---------- SEvent FirstNote..LastNote or Rest -----------------------*/
typedef struct {
    unsigned tone     :8,	/* MIDI tone number 0 to 127; 128 = rest */
             chord    :1,	/* 1 = a chorded note */
             tieOut   :1,	/* 1 = tied to the next note or chord */
             nTuplet  :2,	/* 0 = none, 1 = triplet, 2 = quintuplet,
                 * 3 = septuplet */
             dot      :1,	/* dotted note; multiply duration by 3/2 */
             division :3;	/* basic note duration is 2**-division:
                 * 0 = whole note, 1 = half note, 2 = quarter
                 * note, ... 7 = 128th note */
    } SNote;

/* Warning: An SNote is supposed to be a 16-bit entity.
 * Some C compilers will not pack bit fields into anything smaller
 * than an int. So avoid the actual use of this type unless you are certain
 * that the compiler packs it into a 16-bit word.
 */

/* You may get better object code by masking, ORing, and shifting using the
 * following definitions rather than the bit-packed fields, above. */
#define noteChord  (1<<7)	/* note is chorded to next note */

#define noteTieOut (1<<6)	/* note/chord is tied to next note/chord */

#define noteNShift 4			/* shift count for nTuplet field */
#define noteN3     (1<<noteNShift)	/* note is a triplet */
#define noteN5     (2<<noteNShift)	/* note is a quintuplet */
#define noteN7     (3<<noteNShift)	/* note is a septuplet */
#define noteNMask  noteN7		/* bit mask for the nTuplet field */

#define noteDot    (1<<3)		/* note is dotted */

#define noteDShift 0			/* shift count for division field */
#define noteD1     (0<<noteDShift)	/* whole note division */
#define noteD2     (1<<noteDShift)	/* half note division */
#define noteD4     (2<<noteDShift)	/* quarter note division */
#define noteD8     (3<<noteDShift) 	/* eighth note division */
#define noteD16    (4<<noteDShift) 	/* sixteenth note division */
#define noteD32    (5<<noteDShift) 	/* thirty-secondth note division */
#define noteD64    (6<<noteDShift) 	/* sixty-fourth note division */
#define noteD128   (7<<noteDShift) 	/* 1/128 note division */
#define noteDMask  noteD128		/* bit mask for the division field */

#define noteDurMask 0x3F		/* bit mask for all duration fields
                     * division, nTuplet, dot */

/* Field access: */
#define IsChord(snote)	(((UWORD)snote) & noteChord)
#define IsTied(snote) 	(((UWORD)snote) & noteTieOut)
#define NTuplet(snote) 	((((UWORD)snote) & noteNMask) >> noteNShift)
#define IsDot(snote) 	(((UWORD)snote) & noteDot)
#define Division(snote) ((((UWORD)snote) & noteDMask) >> noteDShift)

/* ---------- TimeSig SEvent -------------------------------------------*/
typedef struct {
    unsigned type     :8,	/* = SID_TimeSig */
             timeNSig :5,	/* time signature "numerator" timeNSig + 1 */
             timeDSig :3;	/* time signature "denominator" is
                 * 2**timeDSig: 0 = whole note, 1 = half
                 * note, 2 = quarter note, ...
                 * 7 = 128th note */
    } STimeSig;

#define timeNMask  0xF8		/* bit mask for timeNSig field */
#define timeNShift 3		/* shift count for timeNSig field */

#define timeDMask  0x07		/*  bit mask for timeDSig field */

/* Field access: */
#define TimeNSig(sTime)  ((((UWORD)sTime) & timeNMask) >> timeNShift)
#define TimeDSig(sTime)   (((UWORD)sTime) & timeDMask)

/* ---------- KeySig SEvent --------------------------------------------*/
/* "data" value 0 = Cmaj; 1 through 7 = G,D,A,E,B,F#,C#;
 * 8 through 14 = F,Bb,Eb,Ab,Db,Gb,Cb.					*/

/* ---------- Dynamic SEvent -------------------------------------------*/
/* "data" value is a MIDI key velocity 0..127. */

/* ---------- SMUS Writer Support Routines -----------------------------*/

/* Just call this to write a SHDR chunk. */
#define PutSHDR(iff, ssHdr)  \
    PutCk(iff, ID_SHDR, sizeof(SScoreHeader), (BYTE *)ssHdr)

#endif


Devices/apps/24bitDemo/24bitDemo.c

/* 24bitDemo.c 05/91  C. Scheppner CBM
 *
 * Example which creates a 24-bit raster, saves it as a 24-bit ILBM,
 *   then loads it as a brush and shows it to you 4 planes at a time
 *   Optionally (if given a filename) just displays 4 planes at a time.
 *
 * requires linkage with several IFF modules
 * see Makefile
 */

#include "iffp/ilbmapp.h"

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

void cleanup(void);
void bye(UBYTE *s,int error);

#define MINARGS 1
char *vers = "\0$VER: 24bitDemo 37.5";
char *Copyright = "24bitDemo v37.5 (Freely Redistributable)";
char *usage = "Usage: 24bitDemo [loadname] (saves/loads if no loadname given)";

struct Library *IntuitionBase  = NULL;
struct Library *GfxBase        = NULL;
struct Library *IFFParseBase   = NULL;

/* Note - these fields are also available in the ILBMInfo structure */
struct   Screen         *scr;         /* for ptr to screen structure */
struct   Window         *win;         /* for ptr to window structure */
struct   RastPort       *wrp;         /* for ptr to RastPort  */
struct   ViewPort       *vp;          /* for ptr to Viewport  */

struct   NewWindow      mynw = {
   0, 0,                                  /* LeftEdge and TopEdge */
   0, 0,                          	  /* Width and Height */
   -1, -1,                                /* DetailPen and BlockPen */
   VANILLAKEY|MOUSEBUTTONS,               /* IDCMP Flags with Flags below */
   BACKDROP|BORDERLESS|SMART_REFRESH|NOCAREREFRESH|ACTIVATE|RMBTRAP,
   NULL, NULL,                            /* Gadget and Image pointers */
   NULL,                                  /* Title string */
   NULL,                                  /* Screen ptr null till opened */
   NULL,                                  /* BitMap pointer */
   50, 20,                                /* MinWidth and MinHeight */
   0 , 0,                                 /* MaxWidth and MaxHeight */
   CUSTOMSCREEN                           /* Type of window */
   };

BOOL   FromWb;

/* ILBM Property chunks to be grabbed
 * List BMHD, CMAP and CAMG first so we can skip them when we write
 * the file back out (they will be written out with separate code)
 */
LONG	ilbmprops[] = {
        ID_ILBM, ID_BMHD,
        ID_ILBM, ID_CMAP,
        ID_ILBM, ID_CAMG,
        ID_ILBM, ID_CCRT,
        ID_ILBM, ID_AUTH,
        ID_ILBM, ID_Copyright,
        TAG_DONE
        };

/* ILBM Collection chunks (more than one in file) to be gathered */
LONG	ilbmcollects[] = {
        ID_ILBM, ID_CRNG,
        TAG_DONE
        };

/* ILBM Chunk to stop on */
LONG	ilbmstops[] = {
        ID_ILBM, ID_BODY,
        TAG_DONE
        };

UBYTE nomem[]  = "Not enough memory\n";
UBYTE noiffh[] = "Can't alloc iff\n";

/* For our allocated ILBM frames */
struct ILBMInfo  *ilbm[2];

#define SCRPLANES 4

USHORT colortable[32];
USHORT cstarts[]= { 0x000, 0x800, 0x000, 0x080, 0x000, 0x008 };
USHORT coffs[]	= { 0x100, 0x100, 0x010, 0x010, 0x001, 0x001 };

UBYTE *ilbmname = "RAM:24bit.ilbm";
UBYTE *rgbnames[]={"R0","R1","R2","R3","R4","R5","R6","R7",
           "G0","G1","G2","G3","G4","G5","G6","G7",
           "B0","B1","B2","B3","B4","B5","B6","B7" };

UBYTE *endtext1 = "Displayed 24 planes, 4 at a time.";
UBYTE *endtext2 = "Press mousebutton or key to exit.";

/*
 * MAIN
 */
void main(int argc, char **argv)
   {
    struct RastPort *rp = NULL;
    struct BitMap dummy = {0};
    struct BitMap *bm = NULL, *xbm, *sbm;
    LONG	error = 0L;
    USHORT	width, height, depth, pwidth, pheight, pmode, extra, rgb;
    ULONG 	plsize;
    UBYTE	*tpp;
    BOOL	DoSave = TRUE;
    int 	k, p, s, n;

   FromWb = argc ? FALSE : TRUE;

   if((argc > 1)&&(argv[argc-1][0]=='?'))
    {
    printf("%s\n%s\n",Copyright,usage);
        bye("",RETURN_OK);
    }

   if(argc==2)
    {
    ilbmname = argv[1];
    DoSave = FALSE;
    }

   /* Open Libraries */

   if(!(IntuitionBase = OpenLibrary("intuition.library", 0)))
      bye("Can't open intuition library.\n",RETURN_WARN);

   if(!(GfxBase = OpenLibrary("graphics.library",0)))
      bye("Can't open graphics library.\n",RETURN_WARN);

   if(!(IFFParseBase = OpenLibrary("iffparse.library",0)))
      bye("Can't open iffparse library.\n",RETURN_WARN);

/*
 * Alloc ILBMInfo structs
 */
    if(!(ilbm[0] = (struct ILBMInfo *)
    AllocMem(sizeof(struct ILBMInfo),MEMF_PUBLIC|MEMF_CLEAR)))
        bye(nomem,RETURN_FAIL);
    if(!(ilbm[1] = (struct ILBMInfo *)
    AllocMem(sizeof(struct ILBMInfo),MEMF_PUBLIC|MEMF_CLEAR)))
        bye(nomem,RETURN_FAIL);

/*
 * Here we set up our ILBMInfo fields for our
 * application.
 * Above we have defined the propery and collection chunks
 * we are interested in (some required like BMHD)
 */

    ilbm[0]->ParseInfo.propchks		= ilbmprops;
    ilbm[0]->ParseInfo.collectchks	= ilbmcollects;
    ilbm[0]->ParseInfo.stopchks		= ilbmstops;

    ilbm[0]->windef	= &mynw;

    *ilbm[1] = *ilbm[0];

/*
 * Alloc IFF handles for frame
 */
    if(!(ilbm[0]->ParseInfo.iff = AllocIFF())) bye(noiffh,RETURN_FAIL);
    if(!(ilbm[1]->ParseInfo.iff = AllocIFF())) bye(noiffh,RETURN_FAIL);

/* for saving our demo 24-bit ILBM */

    width  = 320;
    height = 200;
    depth  = 24;

    /* Page width, height, and mode for saved ILBM */
    pwidth  = width  < 320 ? 320 : width;
    pheight = height < 200 ? 200 : height;
    pmode   = pwidth >= 640  ? HIRES : 0L;
    pmode  |= pheight >= 400 ? LACE  : 0L;

    plsize = RASSIZE(width,height);

    if(!DoSave)	goto nosave;

    /*
     * Allocate Bitmap and planes
     */
    extra = depth > 8 ? depth - 8 : 0;
    if(ilbm[0]->brbitmap = AllocMem(sizeof(struct BitMap) + (extra<<2),
                MEMF_CLEAR))
    {
    bm = ilbm[0]->brbitmap;
        InitBitMap(bm,depth,width,height);
        for(k=0, error=0; k<depth && (!error); k++)
            {
            if(!(bm->Planes[k] = AllocRaster(width,height)))
            error = IFFERR_NOMEM;
            if(! error)
        {
                BltClear(bm->Planes[k], RASSIZE(width,height),0);
                }
        }

    if(!error)
        {
        if(!(rp = AllocMem(sizeof(struct RastPort),MEMF_CLEAR)))
        error = IFFERR_NOMEM;
        else
        {
        InitRastPort(rp);
        rp->BitMap = bm;
        rp->Mask = 0x01;	/* we'll render 1 plane at a time */
        SetAPen(rp,1);
        SetDrMd(rp,JAM1);
        }
        }

    if(!error)
        {
        /* Put something recognizable in the planes.
         * Our bitmap is not part of a screen or viewport
         * so we can fiddle with the pointers and depth
         */
        tpp = bm->Planes[0];	/* save first plane pointer */
        bm->Depth = 1;
        for(k=0; k<depth; k++)	/* swap in planeptrs 1 at a time */
        {
        bm->Planes[0] = bm->Planes[k];
        Move(rp,k * 10, (k * 8) + 8);	/* render rgb bitname text */
        Text(rp, rgbnames[k], 2);
        }
        bm->Depth = depth;		/* restore depth */
        bm->Planes[0] = tpp;	/* and first pointer */

        /* Save the 24-bit ILBM */
        printf("Saving %s\n",ilbmname);
        error = saveilbm(ilbm[0], ilbm[0]->brbitmap, pmode,
                width,  height, pwidth, pheight,
                NULL, 0, 0,	/* colortable */
        mskNone, 0,	/* masking, transparent */
        NULL, NULL, 	/* chunklists */
        ilbmname);
        }

    /* Free our bitmap */
        for(k=0; k<depth; k++)
            {
            if(ilbm[0]->brbitmap->Planes[k])
            FreeRaster(ilbm[0]->brbitmap->Planes[k],width,height);
        }
    FreeMem(ilbm[0]->brbitmap, sizeof(struct BitMap) + (extra << 2));
    ilbm[0]->brbitmap = NULL;
    if(rp)	FreeMem(rp, sizeof(struct RastPort));
    }

    if(error)
    {
    printf("%s\n",IFFerr(error));
    bye(" ", RETURN_FAIL);
    }

nosave:

/* Normally you would use showilbm() to open an appropriate acreen
 * and display an ILBM in it.  However, this is a 24-bit ILBM
 * so we will load it as a brush (bitmap).
 * Here we are demonstrating
 *  - first querying an ILBM to get its BMHD and CAMG (real or computed)
 *  - then opening our own display
 *  - then loading the 24-bit ILBM as a brush (bitmap) and displaying
 *	it 4 planes at a time in our 4-plane screen.
 */

    printf("Attempting to load %s as a bitmap and display 4 planes at a time\n",
        ilbmname);

    if(!(error = queryilbm(ilbm[0],ilbmname)))
    {
    D(bug("24bitDemo: after query, this ILBM is %ld x %ld x %ld,modeid=$%lx\n",
          ilbm[0]->Bmhd.w, ilbm[0]->Bmhd.h, ilbm[0]->Bmhd.nPlanes, ilbm[0]->camg));

    /* Note - you could use your own routines to open your
     * display, but if so, you must initialize ilbm[0]->scr,
     * ilbm[0]->win, ilbm[0]->wrp, ilbm[0]->srp, and ilbm[0]->vp for your
         * display.  Here we will use opendisplay() which will initialize
     * those fields.
     */

    if(!(opendisplay(ilbm[0],
            MAX(ilbm[0]->Bmhd.pageWidth, ilbm[0]->Bmhd.w),
            MAX(ilbm[0]->Bmhd.pageHeight,ilbm[0]->Bmhd.h),
            MIN(ilbm[0]->Bmhd.nPlanes, SCRPLANES),
            ilbm[0]->camg)))
        {
        printf("Failed to open display\n");
        }
    else
        {
        D(bug("24bitDemo: opendisplay (%ld planes) successful\n",SCRPLANES));

        scr = ilbm[0]->scr;
        win = ilbm[0]->win;
        wrp = ilbm[0]->wrp;
        vp  = ilbm[0]->vp;

        if(!(error = loadbrush(ilbm[1], ilbmname)))
        {
            D(bug("24bitDemo: loadbrush successful\n"));

        /* Note - we don't need to examine or copy any
         * chunks from the file, so we will close file now
         */
        closeifile(ilbm[0]);
        ScreenToFront(ilbm[0]->scr);

        xbm = &dummy;		/* spare bitmap */
        sbm = &scr->BitMap;	/* screen's bitmap */
        bm = ilbm[1]->brbitmap;	/* the 24-plane bitmap */
        depth = bm->Depth;

            InitBitMap(xbm,SCRPLANES,scr->Width,scr->Height);

        /* Show the 24 planes */
        for(p=0; p<depth; p+=SCRPLANES)	/* 4 at a time */
            {
            SetRast(&scr->RastPort, 0);
            for(s=0; s<SCRPLANES; s++)
            {
            if((p+s) < depth) xbm->Planes[s] = bm->Planes[p+s];
            else  		  xbm->Planes[s] = NULL, xbm->Depth--;
            }
            /* Blit planes to the screen */
            BltBitMap(xbm, 0, 0,
                  sbm, 0, 0,
                  scr->Width, scr->Height,
                  0xC0, 0x0F, NULL);

            /* Emulate 8-bit color with 4-bit per gun colors
             * by using each rgb value twice
             */
            for(n=0, rgb=cstarts[p /SCRPLANES]; n < 16; n++)
            {
            if(!n)	colortable[n] = 0xFFF;
            else	colortable[n] = rgb;
            /* bump gun for every 2 planes since
             * we only have 8 bits per gun
             */
            if(n & 1)  rgb += coffs[ p / SCRPLANES];
            }
            LoadRGB4(vp, colortable, 16);
            Delay(50);
            }

        SetRast(&scr->RastPort, 0);

        SetAPen(wrp, 1);
        Move(wrp, 24, 80);
        Text(wrp, endtext1, strlen(endtext1));
        Move(wrp, 24, 120);
        Text(wrp, endtext2, strlen(endtext2));

        Wait(1<<win->UserPort->mp_SigBit);
        unloadbrush(ilbm[1]);	/* deallocs colors, closeifile if needed */
        }
        closedisplay(ilbm[0]);
        printf("Done\n");
         }
          }

    if(error)	printf("%s\n",IFFerr(error));

    cleanup();
    exit(RETURN_OK);
    }

void bye(UBYTE *s,int error)
   {
   if((*s)&&(!FromWb)) printf("%s\n",s);
   cleanup();
   exit(error);
   }

void cleanup()
   {
   if(ilbm[0])
    {
    if(ilbm[0]->ParseInfo.iff) 	FreeIFF(ilbm[0]->ParseInfo.iff);
    FreeMem(ilbm[0],sizeof(struct ILBMInfo));
    }
   if(ilbm[1])
    {
    if(ilbm[1]->ParseInfo.iff) 	FreeIFF(ilbm[1]->ParseInfo.iff);
    FreeMem(ilbm[1],sizeof(struct ILBMInfo));
    }

   if(GfxBase) 	     	CloseLibrary(GfxBase);
   if(IntuitionBase) 	CloseLibrary(IntuitionBase);
   if(IFFParseBase)  	CloseLibrary(IFFParseBase);
   }


Devices/apps/Play8SVX/Play8SVX.c

/** Play8SVX.c **************************************************************
 *
 * Read and play sound sample from an IFF file.  21Jan85
 *
 * By Steve Hayes, Electronic Arts.
 * This software is in the public domain.
 *
 * Modified 05/91 for use with iffparse & to play notes - CAS_CBM
 * requires linkage with several IFF modules - see Makefile
 ****************************************************************************/

#include "iffp/8svxapp.h"

#include <exec/execbase.h>
#include <graphics/gfxbase.h>
#include <clib/alib_protos.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

/* prototypes for our functions */
void cleanup(void);
void bye(UBYTE *s,int error);
void DUnpack(BYTE source[], LONG n, BYTE dest[]);
BYTE D1Unpack(BYTE source[], LONG n, BYTE dest[], BYTE x);
LONG LoadSample(struct EightSVXInfo *esvx, UBYTE *filename);
void UnloadSample(struct EightSVXInfo *esvx);
LONG LoadSBody(struct EightSVXInfo *esvx);
void UnloadSBody(struct EightSVXInfo *esvx);

LONG ShowSample(struct EightSVXInfo *esvx);

LONG OpenAudio(void);
void CloseAudio(void);
LONG PlaySample(struct EightSVXInfo *esvx,
        LONG octave, LONG note, UWORD volume, ULONG delay);

struct IOAudio *playbigsample(struct IOAudio *aio0, struct IOAudio *aio1,
        BYTE *samptr, LONG ssize, ULONG period, UWORD volume);

#define MINARGS 2
char *vers = "\0$VER: Play8SVX 37.5";
char *Copyright = "Play8SVX v37.5 (Freely Redistributable)";
char *usage = "Usage: Play8SVX 8SVXname";

/* globals */
struct Library *IFFParseBase   = NULL;
struct Library *GfxBase = NULL;

BOOL   FromWb;

/* 8SVX Property chunks to be grabbed
 */
LONG	esvxprops[] = {
        ID_8SVX, ID_VHDR,
        ID_8SVX, ID_NAME,
        ID_8SVX, ID_ATAK,
        ID_8SVX, ID_RLSE,
        ID_8SVX, ID_AUTH,
        ID_8SVX, ID_Copyright,
        TAG_DONE
        };

/* 8SVX Collection chunks (more than one in file) to be gathered */
LONG	esvxcollects[] = {
        ID_8SVX, ID_ANNO,
        TAG_DONE
        };

/* 8SVX Chunk to stop on */
LONG	esvxstops[] = {
        ID_8SVX, ID_BODY,
        TAG_DONE
        };

UBYTE nomem[]  = "Not enough memory\n";
UBYTE noiffh[] = "Can't alloc iff\n";

/* For our allocated EightSVXInfo */
struct EightSVXInfo  *esvx = NULL;

/*
 * MAIN
 */
void main(int argc, char **argv)
   {
   UBYTE *esvxname=NULL;
   ULONG oct;
   LONG error=0L;

   FromWb = argc ? FALSE : TRUE;

   if((argc<MINARGS)||(argv[argc-1][0]=='?'))
    {
    printf("%s\n%s\n",Copyright,usage);
        bye("",RETURN_OK);
    }

   esvxname = argv[1];

/* Open Libraries */
   if(!(IFFParseBase = OpenLibrary("iffparse.library",0)))
      bye("Can't open iffparse library.\n",RETURN_WARN);

/*
 * Alloc one EightSVXInfo struct
 */
    if(!(esvx = (struct EightSVXInfo *)
    AllocMem(sizeof(struct EightSVXInfo),MEMF_PUBLIC|MEMF_CLEAR)))
        bye(nomem,RETURN_FAIL);

/*
 * Here we set up our EightSVXInfo fields for our
 * application.
 * Above we have defined the propery and collection chunks
 * we are interested in (some required like VHDR).
 * We want to stop on BODY.
 */
    esvx->ParseInfo.propchks	= esvxprops;
    esvx->ParseInfo.collectchks	= esvxcollects;
    esvx->ParseInfo.stopchks	= esvxstops;
/*
 * Alloc the IFF handle for the frame
 */
    if(!(esvx->ParseInfo.iff = AllocIFF())) bye(noiffh,RETURN_FAIL);

    if(!(error = LoadSample(esvx, esvxname)))
    {
    ShowSample(esvx);

    if(!(error = OpenAudio()))
        {
        /* If we think this is a sound effect, play it as such (note=-1) */
        if((esvx->Vhdr.ctOctave==1)&&(esvx->Vhdr.samplesPerSec)
        &&(esvx->Vhdr.oneShotHiSamples)&&(!esvx->Vhdr.repeatHiSamples))
        {
        PlaySample(esvx,0,-1,64,0);
        }
        /* Else play it like an instrument */
        else
        {
            for(oct=0; oct < esvx->Vhdr.ctOctave; oct++)
            {
                PlaySample(esvx,oct,0,64,50);
                PlaySample(esvx,oct,4,64,50);
                PlaySample(esvx,oct,7,64,50);
            }
        }
        CloseAudio();
        }
        else printf("error opening audio device\n");
    }
    else
        printf("%s\n",IFFerr(error));

    cleanup();
    exit(RETURN_OK);
    }

void bye(UBYTE *s,int error)
   {
   if((*s)&&(!FromWb)) printf("%s\n",s);
   cleanup();
   exit(error);
   }

void cleanup()
   {
   if(esvx)
    {
    DD(bug("About to UnloadSample\n"));
    UnloadSample(esvx);

    DD(bug("About to FreeIFF\n"));
    if(esvx->ParseInfo.iff) 	FreeIFF(esvx->ParseInfo.iff);

    DD(bug("About to free EightSVXInfo\n"));
        FreeMem(esvx,sizeof(struct EightSVXInfo));
    }

   if(IFFParseBase)  	CloseLibrary(IFFParseBase);
   }

/** ShowSample() **********************************************
 *
 * Show sample information after calling LoadSample()
 *
 *************************************************************************/
LONG ShowSample(struct EightSVXInfo *esvx)
    {
    LONG error = 0L;
    BYTE *buf;
    Voice8Header *vhdr;

    if(!esvx)			return(CLIENT_ERROR);
    if(!(buf = esvx->sample))	return(CLIENT_ERROR);

    /* LoadSample copied VHDR and NAME (if any) to our esvx frame */
    vhdr = &esvx->Vhdr;
    if(esvx->name[0]) printf("\nNAME: %s",esvx->name);

    printf("\n\nVHDR Info:");
    printf("\noneShotHiSamples=%ld", vhdr->oneShotHiSamples);
    printf("\nrepeatHiSamples=%ld", vhdr->repeatHiSamples);
    printf("\nsamplesPerHiCycle=%ld", vhdr->samplesPerHiCycle);
    printf("\nsamplesPerSec=%ld", vhdr->samplesPerSec);
    printf("\nctOctave=%ld", vhdr->ctOctave);
    printf("\nsCompression=%ld", vhdr->sCompression);
    printf("\nvolume=0x%lx", vhdr->volume);
    printf("\nData = %3ld %3ld %3ld %3ld %3ld %3ld %3ld %3ld",
           buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7]);
    printf("\n       %3ld %3ld %3ld %3ld %3ld %3ld %3ld %3ld ...\n",
           buf[8+0],buf[8+1],buf[8+2],buf[8+3],buf[8+4],buf[8+5],
           buf[8+6],buf[8+ 7]);

    return(error);
    }

/* OpenAudio
 *
 * Opens audio device for one audio channel, 2 IO requests
 * Returns 0 for success
 *
 * Based on code by Dan Baker
 */

UBYTE           whichannel[] = { 1,2,4,8 };

/* periods for scale starting at   65.40Hz (C) with 128 samples per cycle
 *                            or  130.81Hz (C) with  64 samples per cycle
 *                            or  261.63Hz (C) with  32 samples per cycle
 *                            or  523.25Hz (C) with  16 samples per cycle
 *                            or 1046.50Hz (C) with   8 samples per cycle
 *                            or 2093.00Hz (C) with   4 samples per cycle
 */

UWORD   per_ntsc[12]= { 428, 404, 380, 360,
            340, 320, 302, 286,
            270, 254, 240, 226 };

/* periods adjusted for system clock frequency */
UWORD   per[12];

/* Note - these values 3579545 NTSC, 3546895 PAL */
#define NTSC_CLOCK 3579545L
#define PAL_CLOCK  3546895L

#define AIOCNT 4
struct 	IOAudio *aio[AIOCNT] = {NULL}; 	  /* Ptrs to IO blocks for commands  */

struct 	MsgPort *port;   	/* Pointer to a port so the device can reply */
BOOL	devopened;
ULONG	clock = NTSC_CLOCK;     /* Will check for PAL and change if necessary */

LONG OpenAudio()
{
extern	struct ExecBase *SysBase;
LONG 	error=0L;
ULONG   period;
int	k;

if(devopened)	return(-1);

/*-------------------------------------------------------------------------*/
/* Ask the system if we are PAL or NTSC and set clock constant accordingly */
/*-------------------------------------------------------------------------*/
if(GfxBase=OpenLibrary("graphics.library",0L))
    {
    if(((struct GfxBase *)GfxBase)->DisplayFlags & PAL)
        clock = PAL_CLOCK;
    else
        clock = NTSC_CLOCK;
    CloseLibrary((struct Library *) GfxBase);
    }

printf("OpenAudio: For period calculations, clock=%ld\n", clock);

/* calculate period values for one octave based on system clock */
for(k=0; k<12; k++)
    {
    period = ((per_ntsc[k] * clock) + (NTSC_CLOCK >> 1)) / NTSC_CLOCK;
    per[k] = period;
    D(bug("per[%ld]=%ld ",k,per[k]));
    }
D(bug("\n"));

/*-------------------------------------------------------------------*/
/* Create a reply port so the audio device can reply to our commands */
/*-------------------------------------------------------------------*/
if(!(port=CreatePort(0,0)))
    { error = 1; goto bailout; }

/*--------------------------------------------------------------------------*/
/*  Create audio I/O blocks so we can send commands to the audio device     */
/*--------------------------------------------------------------------------*/
for(k=0; k<AIOCNT; k++)
    {
    if(!(aio[k]=(struct IOAudio *)CreateExtIO(port,sizeof(struct IOAudio))))
    { error = k+2; goto bailout; }
    }

/*----------------------------------------------------------------------*/
/* Set up the audio I/O block for channel allocation:                   */
/* ioa_Request.io_Message.mn_ReplyPort is the address of a reply port.  */
/* ioa_Request.io_Message.mn_Node.ln_Pri sets the precedence (priority) */
/*   of our use of the audio device. Any tasks asking to use the audio  */
/*   device that have a higher precedence will steal the channel from us.*/
/* ioa_Request.io_Command is the command field for IO.                  */
/* ioa_Request.io_Flags is used for the IO flags.                       */
/* ioa_AllocKey will be filled in by the audio device if the allocation */
/*   succeeds. We must use the key it gives for all other commands sent.*/
/* ioa_Data is a pointer to the array listing the channels we want.     */
/* ioa_Length tells how long our list of channels is.                   */
/*----------------------------------------------------------------------*/
aio[0]->ioa_Request.io_Command               = ADCMD_ALLOCATE;
aio[0]->ioa_Request.io_Flags                 = ADIOF_NOWAIT;
aio[0]->ioa_AllocKey                         = 0;
aio[0]->ioa_Data                             = whichannel;
aio[0]->ioa_Length                           = sizeof(whichannel);

/*-----------------------------------------------*/
/* Open the audio device and allocate a channel  */
/*-----------------------------------------------*/
if(!(OpenDevice("audio.device",0L, (struct IORequest *) aio[0] ,0L)))
    devopened = TRUE;
else { error = 5; goto bailout; }

/* Clone the flags, channel allocation, etc. into other IOAudio requests */
for(k=1; k<AIOCNT; k++)	*aio[k] = *aio[0];

bailout:
if(error)
    {
    printf("OpenAudio errored out at step %ld\n",error);
    CloseAudio();
    }
return(error);
}

/* CloseAudio
 *
 * Close audio device as opened by OpenAudio, null out pointers
 */
void CloseAudio()
{
int k;

D(bug("Closing audio device...\n"));

/* Note - we know we have no outstanding audio requests */
if(devopened)
    {
    CloseDevice((struct IORequest *) aio[0]);
    devopened = FALSE;
    }

for(k=0; k<AIOCNT; k++)
    {
    if(aio[k]) 	DeleteExtIO(aio[k]), aio[k] = NULL;
    }

if(port)   	DeletePort(port),  port = NULL;
}

/** PlaySample() **********************************************
 *
 * Play a note in octave for delay/50ths of a second
 * OR Play a sound effect (set octave and note to 0, -1)
 *
 * Requires successful OpenAudio() called previously
 *
 * When playing notes:
 * Expects note values between 0 (C) and 11 (B#)
 * Uses largest octave sample in 8SVX as octave 0, next smallest
 *   as octave 1, etc.
 *
 * Notes - this simple example routine does not do ATAK and RLSE)
 *       - use of Delay for timing is simplistic, synchronous, and does
 *		not take into account that the oneshot itself may be
 *		longer than the delay.
 *         Use timer.device for more accurate asynchronous delays
 *
 *************************************************************************/
/* Max playable sample in one IO request is 128K */
#define MAXSAMPLE 131072

LONG	PlaySample(struct EightSVXInfo *esvx,
            LONG octave, LONG note, UWORD volume, ULONG delay)
{
/* pointers to outstanding requests */
struct		IOAudio	*aout0=NULL, *aout1=NULL;
ULONG		period;
LONG		osize, rsize;
BYTE		*oneshot, *repeat;

if(!devopened)	return(-1);

if(note > 11) note=0;

if( note == -1 ) period = clock / esvx->Vhdr.samplesPerSec;
else 		 period = per[note]; /* table set up by OpenAudio */

if(octave > esvx->Vhdr.ctOctave) octave = 0;
if(volume > 64)	volume = 64;

oneshot = esvx->osamps[octave];
osize   = esvx->osizes[octave];
repeat  = esvx->rsamps[octave];
rsize   = esvx->rsizes[octave];

D(bug("oneshot $%lx size %ld, repeat $%lx size %ld\n",
    oneshot, osize, repeat, rsize));

/*------------------------------------------------------------*/
/* Set up audio I/O blocks to play a sample using CMD_WRITE.  */
/* Set up one request for the oneshot and one for repeat      */
/* (all ready for simple case, but we may not need both)      */
/* The io_Flags are set to ADIOF_PERVOL so we can set the     */
/*    period (speed) and volume with the our sample;          */
/* ioa_Data points to the sample; ioa_Length gives the length */
/* ioa_Cycles tells how many times to repeat the sample       */
/* If you want to play the sample at a given sampling rate,   */
/* set ioa_Period = clock/(given sampling rate)               */
/*------------------------------------------------------------*/
aio[0]->ioa_Request.io_Command             =CMD_WRITE;
aio[0]->ioa_Request.io_Flags               =ADIOF_PERVOL;
aio[0]->ioa_Data                           =oneshot;
aio[0]->ioa_Length                         =osize;
aio[0]->ioa_Period                         =period;
aio[0]->ioa_Volume                         =volume;
aio[0]->ioa_Cycles                         =1;

aio[2]->ioa_Request.io_Command             =CMD_WRITE;
aio[2]->ioa_Request.io_Flags               =ADIOF_PERVOL;
aio[2]->ioa_Data                           =repeat;
aio[2]->ioa_Length                         =rsize;
aio[2]->ioa_Period                         =period;
aio[2]->ioa_Volume                         =volume;
aio[2]->ioa_Cycles                         =0;	/* repeat until stopped */

/*---------------------------------------------------*/
/* Send the command to start a sound using BeginIO() */
/* Go to sleep and wait for the sound to finish with */
/* WaitIO() to wait and get the get the ReplyMsg     */
/*---------------------------------------------------*/
printf("Starting tone O len %ld for %0ld cyc, R len %ld for %0ld cyc, per=%ld...",
        osize, aio[0]->ioa_Cycles, rsize, aio[1]->ioa_Cycles, period);

if(osize)
    {
    /* Simple case for oneshot sample <= 128K (ie. most samples) */
    if(osize <= MAXSAMPLE)	BeginIO((struct IORequest *)(aout0=aio[0]));

    /* Note - this else case code is for samples >128K */
    else
    {
    *aio[1] = *aio[0];
    aout0 = playbigsample(aio[0],aio[1],oneshot,osize,period,volume);
    }
     }

if(rsize)
    {
    /* Simple case for oneshot sample <= 128K (ie. most samples) */
    if(rsize <= MAXSAMPLE)	BeginIO((struct IORequest *)(aout1=aio[2]));

    /* Note - this else case code is for samples >128K */
    else
    {
    *aio[3] = *aio[2];
    aout1 = playbigsample(aio[2],aio[3],repeat,rsize,period,volume);
    }
     }

if(delay)	Delay(delay);	/* crude timing for notes */

/* Wait for any requests we still have out */
if(aout0) WaitIO(aout0);

if(aout1)
   {
   if(note >= 0) AbortIO(aout1);	/* if a note, stop it now */
   WaitIO(aout1);
   }

printf("Done\n");
}

/** playbigsample() ********************************************************
 *
 *  called by playsample to deal with samples > 128K
 *
 *  wants pointers to two ready-to-use IOAudio iorequest blocks
 *
 *  returns pointer to the IOAudio request that is still out
 *   or NULL if none (error)
 *************************************************************************/

struct IOAudio *playbigsample(struct IOAudio *aio0, struct IOAudio* aio1,
            BYTE *samptr, LONG ssize, ULONG period, UWORD volume)
{
struct IOAudio *aio[2];
LONG   size;
int    req=0, reqn=1;	/* current and next IOAudio request indexes */

if((!aio0)||(!aio1)||(ssize < MAXSAMPLE))	return(NULL);

aio[req]  = aio0;
aio[reqn] = aio1;

/* start the first 128 K playing */
aio[req]->ioa_Request.io_Command             =CMD_WRITE;
aio[req]->ioa_Request.io_Flags               =ADIOF_PERVOL;
aio[req]->ioa_Data                           =samptr;
aio[req]->ioa_Length			     =MAXSAMPLE;
aio[req]->ioa_Period                         =period;
aio[req]->ioa_Volume                         =volume;
aio[req]->ioa_Cycles                         =1;
BeginIO((struct IORequest*)aio[req]);

for(samptr=samptr + MAXSAMPLE, size = ssize - MAXSAMPLE;
    size > 0;
        samptr += MAXSAMPLE)
    {
    /* queue the next piece of sample */
    reqn = req ^ 1;	/* alternate IO blocks 0 and 1 */
    aio[reqn]->ioa_Request.io_Command             =CMD_WRITE;
    aio[reqn]->ioa_Request.io_Flags               =ADIOF_PERVOL;
    aio[reqn]->ioa_Data                           =samptr;
    aio[reqn]->ioa_Length = (size > MAXSAMPLE) ? MAXSAMPLE : size;
    aio[reqn]->ioa_Period                         =period;
    aio[reqn]->ioa_Volume                         =volume;
    aio[reqn]->ioa_Cycles                         =1;
    BeginIO((struct IORequest*)aio[reqn]);

    /* Wait for previous request to finish */
    WaitIO(aio[req]);
    /* decrement size */
    size = (size > MAXSAMPLE) ? size-MAXSAMPLE : 0;
    req = reqn;		/* switch between aio[0] and aio[1] */
    }
return(aio[reqn]);
}

/** LoadSample() **********************************************************
 *
 * Read 8SVX, given an initialized EightSVXInfo with not-in-use IFFHandle,
 *   and filename.  Leaves the IFFHandle open so you can FindProp()
 *   additional chunks or copychunks().  You must UnloadSample()
 *   when done.  UnloadSample will closeifile if the file is still
 *   open.
 *
 * Fills in esvx->Vhdr and Name, and allocates/loads esvx->sample,
 *   setting esvx->samplebytes to size for deallocation.
 *
 * Returns 0 for success of an IFFERR (libraries/iffparse.h)
 *************************************************************************/
LONG LoadSample(struct EightSVXInfo *esvx, UBYTE *filename)
    {
    struct IFFHandle *iff;
    struct StoredProperty *sp;
    Voice8Header *vhdr;
    BYTE *oneshot, *repeat;
    ULONG osize, rsize, spcyc;
    int oct;
    LONG error = 0L;

    D(bug("LoadSample:\n"));

    if(!esvx)				return(CLIENT_ERROR);
    if(!(iff=esvx->ParseInfo.iff))	return(CLIENT_ERROR);

    if(!(error = openifile((struct ParseInfo *)esvx, filename, IFFF_READ)))
    {
    printf("Reading '%s'...\n",filename);
    error = parseifile((struct ParseInfo *)esvx,
            ID_FORM, ID_8SVX,
            esvx->ParseInfo.propchks,
            esvx->ParseInfo.collectchks,
            esvx->ParseInfo.stopchks);

    D(bug("LoadSample: after parseifile - error = %ld\n",error));

    if((!error)||(error == IFFERR_EOC)||(error == IFFERR_EOF))
        {
        if(contextis(iff,ID_8SVX,ID_FORM))
        {
        D(bug("LoadSample: context is 8SVX\n"));
        if(!(sp = FindProp(iff,ID_8SVX,ID_VHDR)))
            {
            message("No 8SVX.VHDR!");
            error = IFFERR_SYNTAX;
            }
        else
            {
            D(bug("LoadSample: Have VHDR\n"));
            /* copy Voice8Header into frame */
            vhdr = (Voice8Header *)(sp->sp_Data);
            *(&esvx->Vhdr) = *vhdr;
            /* copy name if any */
            esvx->name[0]='\0';
            if(sp = FindProp(iff,ID_8SVX,ID_NAME))
            {
            strncpy(esvx->name,sp->sp_Data,sp->sp_Size);
            esvx->name[MIN(sp->sp_Size,79)] = '\0';
            }
                error = LoadSBody(esvx);
            D(bug("LoadSample: After LoadSBody - error = %ld\n",error));
            if(!error)
            {
            osize   = esvx->Vhdr.oneShotHiSamples;
            rsize   = esvx->Vhdr.repeatHiSamples;
            spcyc	= esvx->Vhdr.samplesPerHiCycle;
            if(!spcyc) spcyc = esvx->Vhdr.repeatHiSamples;
            if(!spcyc) spcyc = 8;

            oneshot = esvx->sample;

            for(oct = esvx->Vhdr.ctOctave-1; oct >= 0;
                 oct--, oneshot+=(osize+rsize),
                    osize <<= 1, rsize <<=1, spcyc <<=1)
                    {
                    repeat  = oneshot + osize;
                esvx->osizes[oct] = osize;
                if(osize) esvx->osamps[oct] = oneshot;
                else      esvx->osamps[oct] = 0;
                esvx->rsizes[oct] = rsize;
                if(rsize) esvx->rsamps[oct] = repeat;
                else      esvx->rsamps[oct] = 0;
                esvx->spcycs[oct] = spcyc;

             D(bug("oneshot $%lx size %ld, repeat $%lx size %ld\n",
                oneshot, osize, repeat, rsize));

                }
                }
            }
        }
        else
        {
        message("Not an 8SVX\n");
        error = NOFILE;
        }
        }
    }

    if(error)
    {
    closeifile((struct ParseInfo *)esvx);
    UnloadSample(esvx);
    }
    return(error);
    }

/** UnloadSample() *******************************************************
 *
 * Frees and closes everything opened/alloc'd by LoadSample()
 *
 *************************************************************************/
void UnloadSample(struct EightSVXInfo *esvx)
    {
    if(esvx)
    {
    UnloadSBody(esvx);
    closeifile((struct ParseInfo *)esvx);
    }
    }

/** LoadSBody() ***********************************************************
 *
 * Read a 8SVX Sample BODY into RAM.
 *
 *************************************************************************/
LONG LoadSBody(struct EightSVXInfo *esvx)
    {
    struct IFFHandle *iff;
    LONG sbytes, rlen, error = 0L;
    ULONG memtype;
    Voice8Header *vhdr = &esvx->Vhdr;
    BYTE *t;

    D(bug("LoadSBody:\n"));

    if(!(iff=esvx->ParseInfo.iff))	return(CLIENT_ERROR);
    if(!esvx)				return(CLIENT_ERROR);

    if(!(currentchunkis(iff,ID_8SVX,ID_BODY)))
    {
    message("LoadSBody: not at BODY!");
    return(IFFERR_READ);
    }

    sbytes  = ChunkMoreBytes(CurrentChunk(iff));

    /* if we have to decompress, let's just load it into public mem */
    memtype = vhdr->sCompression ? MEMF_PUBLIC : MEMF_CHIP;

    D(bug("LoadSBody: samplebytes=%ld, compression=%ld\n",
            sbytes,vhdr->sCompression));

    if(!(esvx->sample = (BYTE *)AllocMem(sbytes, memtype)))
    {
        error = CLIENT_ERROR;
    }
    else
    {
    D(bug("LoadSBody: have load buffer\n"));
    esvx->samplebytes = sbytes;
        if(rlen=ReadChunkBytes(iff,esvx->sample,sbytes) != sbytes)
        error = IFFERR_READ;

    if(error)
        {
        D(bug("LoadSBody: ReadChunkBytes error = %ld, read %ld bytes\n",
            error));
        UnloadSample(esvx);
        }
    else if (vhdr->sCompression) /* Decompress, if needed. */
        {
            if(t = (BYTE *)AllocMem(sbytes<<1, MEMF_CHIP))
        {
        D(bug("LoadSBody: have decompression buffer\n"));
                DUnpack(esvx->sample, sbytes, t);
                FreeMem(esvx->sample, sbytes);
                esvx->sample = t;
                esvx->samplebytes = sbytes << 1;
        }
        else
        {
        UnloadSample(esvx);
        error = IFFERR_NOMEM;
        }
        }
    }
    return(error);
    }

/** UnloadSBody() ********************************************************
 *
 * Deallocates esvx->smaple
 *
 *************************************************************************/
void UnloadSBody(struct EightSVXInfo *esvx)
    {
    if(esvx)
    {
    if(esvx->sample)
        {
        DD(bug("About to free SBody\n"));
        FreeMem(esvx->sample,esvx->samplebytes);
        esvx->sample = NULL;
        }
    esvx->samplebytes = NULL;
    }
    }

/* DUnpack.c --- Fibonacci Delta decompression by Steve Hayes */

/* Fibonacci delta encoding for sound data */
BYTE codeToDelta[16] = {-34,-21,-13,-8,-5,-3,-2,-1,0,1,2,3,5,8,13,21};

/* Unpack Fibonacci-delta encoded data from n byte source
 * buffer into 2*n byte dest buffer, given initial data
 * value x.  It returns the lats data value x so you can
 * call it several times to incrementally decompress the data.
 */

BYTE D1Unpack(BYTE source[], LONG n, BYTE dest[], BYTE x)
   {
   BYTE d;
   LONG i, lim;

   lim = n << 1;
   for (i=0; i < lim; ++i)
      {
      /* Decode a data nibble, high nibble then low nibble */
      d = source[i >> 1];    /* get a pair of nibbles */
      if (i & 1)             /* select low or high nibble */
         d &= 0xf;           /* mask to get the low nibble */
      else
         d >>= 4;            /* shift to get the high nibble */
      x += codeToDelta[d];   /* add in the decoded delta */
      dest[i] = x;           /* store a 1 byte sample */
      }
   return(x);
   }

/* Unpack Fibonacci-delta encoded data from n byte
 * source buffer into 2*(n-2) byte dest buffer.
 * Source buffer has a pad byte, an 8-bit initial
 * value, followed by n-2 bytes comprising 2*(n-2)
 * 4-bit encoded samples.
 */

void DUnpack(source, n, dest)
BYTE source[], dest[];
LONG n;
   {
   D1Unpack(source+2, n-2, dest, source[1]);
   }


Devices/modules/getbitmap.c

/*----------------------------------------------------------------------*
 * GETBITMAP.C  Support routines for reading ILBM files.
 * (IFF is Interchange Format File.)
 *
 * Based on code by Jerry Morrison and Steve Shaw, Electronic Arts.
 * This software is in the public domain.
 * Modified for iffparse.library by CBM 04/90
 * This version for the Amiga computer.
 *----------------------------------------------------------------------*/

#include "iffp/ilbm.h"
#include "iffp/packer.h"
#include "iffp/ilbmapp.h"

/* createbrush
 *
 * Passed an initialized ILBMInfo with a parsed IFFHandle (chunks parsed,
 * stopped at BODY),
 * gets the bitmap and colors
 * Sets up ilbm->brbitmap, ilbm->colortable, ilbm->ncolors
 * Returns 0 for success
 */
LONG createbrush(struct ILBMInfo *ilbm)
    {
    int error;

    error 			= getbitmap(ilbm);
    if(!error) error 	= loadbody(ilbm->ParseInfo.iff,
                        ilbm->brbitmap,&ilbm->Bmhd);
    if(!error) 		getcolors(ilbm);
    if(error)  		deletebrush(ilbm);
    return(error);
    }

/* deletebrush
 *
 * closes and deallocates created brush bitmap and colors
 */
void deletebrush(ilbm)
struct ILBMInfo		*ilbm;
    {
    freebitmap(ilbm);
    freecolors(ilbm);
    }

/* getbitmap
 *
 * Passed an initialized ILBMInfo with parsed IFFHandle (chunks parsed,
 * stopped at BODY), allocates a BitMap structure and planes just large
 * enough for the BODY.  Generally used for brushes but may be used
 * to load backgrounds without displaying, or to load deep ILBM's.
 * Sets ilbm->brbitmap.  Returns 0 for success.
 */
LONG getbitmap(struct ILBMInfo *ilbm)
    {
    struct IFFHandle	*iff;
    BitMapHeader	*bmhd;
    USHORT			wide, high;
    LONG  error = NULL;
    int k, extra=0;
    BYTE deep;

    if(!(iff=ilbm->ParseInfo.iff))	return(CLIENT_ERROR);

    ilbm->brbitmap = NULL;

    if (!( bmhd = (BitMapHeader *)
            findpropdata(iff, ID_ILBM, ID_BMHD)))
        {
        message("No ILBM.BMHD chunk!\n");
        return(IFFERR_SYNTAX);
        }

    *(&ilbm->Bmhd) = *bmhd;	/* copy contents of BMHD */

    wide = BitsPerRow(bmhd->w);
    high = bmhd->h;
    deep = bmhd->nPlanes;

    ilbm->camg = getcamg(ilbm);

    D(bug("allocbitmap: bmhd=$%lx wide=%ld high=%ld deep=%ld\n",
            bmhd,wide,high,deep));
    /*
     * Allocate Bitmap and planes
     */
        extra = deep > 8 ? deep - 8 : 0;
    if(ilbm->brbitmap = AllocMem(sizeof(struct BitMap)+(extra<<2),MEMF_CLEAR))
        {
        InitBitMap(ilbm->brbitmap,deep,wide,high);
        for(k=0; k<deep && (!error); k++)
            {
            if(!(ilbm->brbitmap->Planes[k] = AllocRaster(wide,high)))
                        error = 1;
            if(! error)
            BltClear(ilbm->brbitmap->Planes[k],RASSIZE(wide,high),0);
            }

        if(error)
            {
            message("Failed to allocate raster\n");
            freebitmap(ilbm);
            }
        }
    else error = 1;
    return(error);
    }

/* freebitmap
 *
 * deallocates ilbm->brbitmap BitMap structure and planes
 */
void freebitmap(struct ILBMInfo * ilbm)
    {
    int k, extra=0;

    if(ilbm->brbitmap)
        {
        for(k=0; k< ilbm->brbitmap->Depth; k++)
            {
            if(ilbm->brbitmap->Planes[k])
                FreeRaster(ilbm->brbitmap->Planes[k],
                    (USHORT)(ilbm->brbitmap->BytesPerRow << 3),
                    ilbm->brbitmap->Rows);
            }

            extra = ilbm->brbitmap->Depth > 8 ? ilbm->brbitmap->Depth - 8 : 0;
        FreeMem(ilbm->brbitmap,sizeof(struct BitMap) + (extra << 2));
        ilbm->brbitmap = NULL;
        }
    }

/* end */


Devices/modules/packer.c

/*----------------------------------------------------------------------*
 * packer.c Convert data to "cmpByteRun1" run compression.     11/15/85
 *
 * By Jerry Morrison and Steve Shaw, Electronic Arts.
 * This software is in the public domain.
 *
 *	control bytes:
 *	 [0..127]   : followed by n+1 bytes of data.
 *	 [-1..-127] : followed by byte to be repeated (-n)+1 times.
 *	 -128       : NOOP.
 *
 * This version for the Amiga computer.
 *----------------------------------------------------------------------*/
#include "iffp/packer.h"

#define DUMP	0
#define RUN	1

#define MinRun 3
#define MaxRun 128
#define MaxDat 128

/* When used on global definitions, static means private.
 * This keeps these names, which are only referenced in this
 * module, from conficting with same-named objects in your program.
 */
static LONG putSize;
static char buf[256];	/* [TBD] should be 128?  on stack?*/

#define GetByte()	(*source++)
#define PutByte(c)	{ *dest++ = (c);   ++putSize; }

static BYTE *PutDump(dest, nn)  BYTE *dest;  int nn; {
    int i;

    PutByte(nn-1);
    for(i = 0;  i < nn;  i++)   PutByte(buf[i]);
    return(dest);
    }

static BYTE *PutRun(dest, nn, cc)   BYTE *dest;  int nn, cc; {
    PutByte(-(nn-1));
    PutByte(cc);
    return(dest);
    }

#define OutDump(nn)   dest = PutDump(dest, nn)
#define OutRun(nn,cc) dest = PutRun(dest, nn, cc)

/*----------- packrow --------------------------------------------------*/
/* Given POINTERS TO POINTERS, packs one row, updating the source and
 * destination pointers.  RETURNs count of packed bytes.
 */
LONG packrow(BYTE **pSource, BYTE **pDest, LONG rowSize)
    {
    BYTE *source, *dest;
    char c,lastc = '\0';
    BOOL mode = DUMP;
    short nbuf = 0;		/* number of chars in buffer */
    short rstart = 0;		/* buffer index current run starts */

    source = *pSource;
    dest = *pDest;
    putSize = 0;
    buf[0] = lastc = c = GetByte();  /* so have valid lastc */
    nbuf = 1;   rowSize--;	/* since one byte eaten.*/

    for (;  rowSize;  --rowSize) {
    buf[nbuf++] = c = GetByte();
    switch (mode) {
        case DUMP:
            /* If the buffer is full, write the length byte,
               then the data */
            if (nbuf>MaxDat) {
                OutDump(nbuf-1);
                buf[0] = c;
                nbuf = 1;   rstart = 0;
                break;
                }

            if (c == lastc) {
                if (nbuf-rstart >= MinRun) {
                if (rstart > 0) OutDump(rstart);
                mode = RUN;
                }
                else if (rstart == 0)
                mode = RUN;	/* no dump in progress,
                so can't lose by making these 2 a run.*/
                }
            else  rstart = nbuf-1;		/* first of run */
            break;

        case RUN: if ( (c != lastc)|| ( nbuf-rstart > MaxRun)) {
                /* output run */
               OutRun(nbuf-1-rstart,lastc);
                buf[0] = c;
                nbuf = 1; rstart = 0;
                mode = DUMP;
                }
            break;
        }

    lastc = c;
    }

    switch (mode) {
    case DUMP: OutDump(nbuf); break;
    case RUN: OutRun(nbuf-rstart,lastc); break;
    }
    *pSource = source;
    *pDest = dest;
    return(putSize);
    }


Devices/modules/unpacker.c

#include "iffp/ilbm.h"
#include "iffp/packer.h"

/*----------------------------------------------------------------------*
 * unpacker.c Convert data from "cmpByteRun1" run compression. 11/15/85
 *
 * Based on code by Jerry Morrison and Steve Shaw, Electronic Arts.
 * This software is in the public domain.
 *
 *	control bytes:
 *	 [0..127]   : followed by n+1 bytes of data.
 *	 [-1..-127] : followed by byte to be repeated (-n)+1 times.
 *	 -128       : NOOP.
 *
 * This version for the Amiga computer.
 *----------------------------------------------------------------------*/

/*----------- UnPackRow ------------------------------------------------*/

#define UGetByte()	(*source++)
#define UPutByte(c)	(*dest++ = (c))

/* Given POINTERS to POINTER variables, unpacks one row, updating the source
 * and destination pointers until it produces dstBytes bytes.
 */

BOOL unpackrow(BYTE **pSource, BYTE **pDest, WORD srcBytes0, WORD dstBytes0)
    {
    register BYTE *source = *pSource;
    register BYTE *dest   = *pDest;
    register WORD n;
    register BYTE c;
    register WORD srcBytes = srcBytes0, dstBytes = dstBytes0;
    BOOL error = TRUE;	/* assume error until we make it through the loop */
    WORD minus128 = -128;  /* get the compiler to generate a CMP.W */

    while( dstBytes > 0 )  {
    if ( (srcBytes -= 1) < 0 )  goto ErrorExit;
        n = UGetByte();

        if (n >= 0) {
        n += 1;
        if ( (srcBytes -= n) < 0 )  goto ErrorExit;
        if ( (dstBytes -= n) < 0 )  goto ErrorExit;
        do {  UPutByte(UGetByte());  } while (--n > 0);
        }

        else if (n != minus128) {
        n = -n + 1;
        if ( (srcBytes -= 1) < 0 )  goto ErrorExit;
        if ( (dstBytes -= n) < 0 )  goto ErrorExit;
        c = UGetByte();
        do {  UPutByte(c);  } while (--n > 0);
        }
    }
    error = FALSE;	/* success! */

  ErrorExit:
    *pSource = source;  *pDest = dest;
    return(error);
    }

/* end */


Devices/apps/ILBMDemo/ILBMDemo.c

/* ILBMDemo.c  05/91   C. Scheppner CBM
 *
 * Demonstrates displaying an ILBM, loading a brush,
 *   saving an ILBM, and optionally printing a screen (CTRL-p)
 *   Use -c (or -c1, -c2, etc) as filename to read from or save to clipboard.
 *
 * requires linkage with several iffp modules - see Makefile
 */

#include "iffp/ilbmapp.h"

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

void chkmsg(void);
void cleanup(void);
void bye(UBYTE *s,int error);

#define SAVECHANGES

#define MINARGS 3
char *vers = "\0$VER: ILBMDemo 37.5";
char *Copyright = "ILBMDemo v37.5 (Freely Redistributable)";
char *usage =
"Usage: ILBMDemo sourceilbm destilbm [brushname]  (CTRL-p to print screen)\n"
"Displays source, optionally loads and blits brush, saves to dest\n"
"Use filename -c[unit] (ie. -c, -c1, -c2, etc.) for clipboard\n";

char *savename;

struct Library *IntuitionBase  = NULL;
struct Library *GfxBase        = NULL;
struct Library *IFFParseBase   = NULL;

/* Note - these fields are also available in the ILBMInfo structure */
struct   Screen         *scr;         /* for ptr to screen structure */
struct   Window         *win;         /* for ptr to window structure */
struct   RastPort       *wrp;         /* for ptr to RastPort  */
struct   ViewPort       *vp;          /* for ptr to Viewport  */

struct   IntuiMessage   *msg;

struct   NewWindow      mynw = {
   0, 0,                                  /* LeftEdge and TopEdge */
   0, 0,                          	  /* Width and Height */
   -1, -1,                                /* DetailPen and BlockPen */
   VANILLAKEY|MOUSEBUTTONS,               /* IDCMP Flags with Flags below */
   BACKDROP|BORDERLESS|SMART_REFRESH|NOCAREREFRESH|ACTIVATE|RMBTRAP,
   NULL, NULL,                            /* Gadget and Image pointers */
   NULL,                                  /* Title string */
   NULL,                                  /* Screen ptr null till opened */
   NULL,                                  /* BitMap pointer */
   50, 20,                                /* MinWidth and MinHeight */
   0 , 0,                                 /* MaxWidth and MaxHeight */
   CUSTOMSCREEN                           /* Type of window */
   };

BOOL   FromWb, Done;

/* ILBM Property chunks to be grabbed
 * List BMHD, CMAP and CAMG first so we can skip them when we write
 * the file back out (they will be written out with separate code)
 */
LONG	ilbmprops[] = {
        ID_ILBM, ID_BMHD,
        ID_ILBM, ID_CMAP,
        ID_ILBM, ID_CAMG,
        ID_ILBM, ID_CCRT,
        ID_ILBM, ID_AUTH,
        ID_ILBM, ID_Copyright,
        TAG_DONE
        };

/* ILBM Collection chunks (more than one in file) to be gathered */
LONG	ilbmcollects[] = {
        ID_ILBM, ID_CRNG,
        TAG_DONE
        };

/* ILBM Chunk to stop on */
LONG	ilbmstops[] = {
        ID_ILBM, ID_BODY,
        TAG_DONE
        };

/* For test of adding new chunks to saved FORM */
struct Chunk newchunks[2] = {
    {
    &newchunks[1],
    ID_ILBM, ID_AUTH, IFFSIZE_UNKNOWN,
    "CAS_CBM"},
    {
    NULL,
    ID_ILBM, ID_NAME, IFFSIZE_UNKNOWN,
    "Untitled No. 27"},
    };

UBYTE nomem[]  = "Not enough memory\n";
UBYTE noiffh[] = "Can't alloc iff\n";

/* our indexes to reference our frames
 * DEFault, BRUsh, and SCReen
 */
#define DEF	0
#define BRU	1
#define SCR	2
#define UICOUNT 3

/* For our ILBM frames */
struct ILBMInfo  *ilbms[UICOUNT]  = { NULL };

/*
 * MAIN
 */
void main(int argc, char **argv)
   {
#ifdef SAVECHANGES
   struct Chunk *chunk;
   CamgChunk *camg;
   LONG saverror;
#endif
   UBYTE *ilbmname=NULL, *brushname=NULL, ans, c;
   BPTR lock;
   LONG error;

   FromWb = argc ? FALSE : TRUE;

   if((argc<MINARGS)||(argv[argc-1][0]=='?'))
    {
    printf("%s\n%s\n",Copyright,usage);
        bye("",RETURN_OK);
    }

   switch(argc)
      {
      case 4:
         brushname	= argv[3];
      case 3:
         savename	= argv[2];
         ilbmname	= argv[1];
         break;
      }

   /* if dest not clipboard, warn if dest file already exists */
   if(strcmp(savename,"-c"))
    {
    if(lock = Lock(savename,ACCESS_READ))
        {
        UnLock(lock);
        printf("Dest file \"%s\" already exists.  Overwrite (y or n) ? ",
            savename);
        ans = 0;
        while((c = getchar()) != '\n') if(!ans)  ans = c | 0x20;
        if(ans == 'n')   bye("Exiting.\n",RETURN_OK);
        }
    }

   /* Open Libraries */

   if(!(IntuitionBase = OpenLibrary("intuition.library", 0)))
      bye("Can't open intuition library.\n",RETURN_WARN);

   if(!(GfxBase = OpenLibrary("graphics.library",0)))
      bye("Can't open graphics library.\n",RETURN_WARN);

   if(!(IFFParseBase = OpenLibrary("iffparse.library",0)))
      bye("Can't open iffparse library.\n",RETURN_WARN);

/*
 * Alloc three ILBMInfo structs (one each for defaults, screen, brush)
 */
    if(!(ilbms[0] = (struct ILBMInfo *)
    AllocMem(UICOUNT * sizeof(struct ILBMInfo),MEMF_PUBLIC|MEMF_CLEAR)))
        bye(nomem,RETURN_FAIL);
    else
    {
    ilbms[BRU] = ilbms[0] + 1;
    ilbms[SCR] = ilbms[0] + 2;
    }

/*
 * Here we set up default ILBMInfo fields for our
 * application's frames.
 * Above we have defined the propery and collection chunks
 * we are interested in (some required like BMHD)
 * Since all of our frames are for ILBM's, we'll initialize
 * one default frame and clone the others from it.
 */
    ilbms[DEF]->ParseInfo.propchks	= ilbmprops;
    ilbms[DEF]->ParseInfo.collectchks	= ilbmcollects;
    ilbms[DEF]->ParseInfo.stopchks	= ilbmstops;

    ilbms[DEF]->windef	= &mynw;
/*
 * Initialize our working ILBM frames from our default one
 */
    *ilbms[SCR] = *ilbms[DEF];	/* for our screen */
    *ilbms[BRU] = *ilbms[DEF];	/* for our brush  */

/*
 * Alloc two IFF handles (one for screen frame, one for brush frame)
 */
    if(!(ilbms[SCR]->ParseInfo.iff = AllocIFF())) bye(noiffh,RETURN_FAIL);
    if(!(ilbms[BRU]->ParseInfo.iff = AllocIFF())) bye(noiffh,RETURN_FAIL);

/* Load and display an ILBM
 */
    if(error = showilbm(ilbms[SCR],ilbmname))
    {
    printf("Can't load background \"%s\"\n",ilbmname);
    bye("",RETURN_WARN);
    }

    /* These were set up by our successful showilbm() above */
    win = ilbms[SCR]->win;	/* our window */
    wrp = ilbms[SCR]->wrp;	/* our window's RastPort */
    scr = ilbms[SCR]->scr;	/* our screen */
    vp  = ilbms[SCR]->vp;		/* our screen's ViewPort */

    ScreenToFront(scr);

 /* Now let's load a brush and blit it into the window
  */
    if(brushname)
    {
    if (error = loadbrush(ilbms[BRU],brushname))
        {
        printf("Can't load brush \"%s\"\n",brushname);
        bye("",RETURN_WARN);
        }
    else	/* Success */
        {
        D(bug("About to Blt bitmap $%lx to rp $%lx, w=%ld h=%ld\n",
        ilbms[BRU]->brbitmap,wrp,ilbms[BRU]->Bmhd.w,ilbms[BRU]->Bmhd.h));
            BltBitMapRastPort(ilbms[BRU]->brbitmap,0,0,
                             wrp,0,0,
                             ilbms[BRU]->Bmhd.w, ilbms[BRU]->Bmhd.h,
                             0xC0);
             }
    }

#ifdef SAVECHANGES

 /* This code is an example for Read/Modify/Write programs
  *
  * We copy off the parsed chunks we want to preserve,
  * close the IFF read file, reopen it for write,
  * and save a new ILBM which
  * will include the chunks we have preserved, but
  * with newly computed and set-up BMHD, CMAP, and CAMG.
  */

   if(!(ilbms[SCR]->ParseInfo.copiedchunks =
    copychunks(ilbms[SCR]->ParseInfo.iff,
           ilbmprops, ilbmcollects,
           MEMF_PUBLIC)))
        printf("error cloning chunks\n");
   else
    {
        /* we can close the file now */
       closeifile(ilbms[SCR]);

       printf("Test of copychunks and findchunk:\n");

       /* Find copied CAMG chunk if any */
       if(chunk = findchunk(ilbms[SCR]->ParseInfo.copiedchunks,ID_ILBM,ID_CAMG))
        {
        camg = (CamgChunk *)chunk->ch_Data;
        printf("CAMG: $%08lx\n",camg->ViewModes);
        }
        else printf("No CAMG found\n");

       /* Find copied CRNG chunks if any */
       if(chunk = findchunk(ilbms[SCR]->ParseInfo.copiedchunks,ID_ILBM,ID_CRNG))
        {
           while((chunk)&&(chunk->ch_ID == ID_CRNG))
        {
        printf("Found a CRNG chunk\n");
        chunk = chunk->ch_Next;
        }
        }
       else printf("No CRNG chunks found\n");
    }

    printf("\nAbout to save screen as %s, adding NAME and AUTH chunks\n",
        savename);

    if(saverror = screensave(ilbms[SCR], ilbms[SCR]->scr,
                ilbms[SCR]->ParseInfo.copiedchunks,
                newchunks,
                savename))
            printf("%s\n",IFFerr(saverror));

#endif

   Done = FALSE;
   while(!Done)
      {
      Wait(1<<win->UserPort->mp_SigBit);
      chkmsg();
      }

   cleanup();
   exit(RETURN_OK);
   }

void chkmsg(void)
    {
    LONG  error;
    ULONG class;
    UWORD code;
    WORD  mousex, mousey;

    while(msg = (struct IntuiMessage *)GetMsg(win->UserPort))
    {
    class = msg->Class;
          code  = msg->Code;
          mousex = msg->MouseX;
          mousey = msg->MouseY;

          ReplyMsg(msg);
          switch(class)
           {
        case MOUSEBUTTONS:
        switch(code)
        {
        /* emulate a close gadget */
        case SELECTDOWN:
           if((mousex < 12)&&(mousey < 12))	Done = TRUE;
           break;
        default:
           break;
        }
            case VANILLAKEY:
            switch(code)
                   {
        /* also quit on CTRL-C, CTRL-D, or q */
                   case 'q': case 0x04: case 0x03:
                  Done = TRUE;
                  break;
        case 0x10:	/* CTRL-p means print */

          /* Print the whole screen */
          if(error=screendump(ilbms[SCR]->scr,
                0,0,
                ilbms[SCR]->scr->Width,
                ilbms[SCR]->scr->Height,
                0,0))
            printf("Screendump printer error=%ld\n",error);
          break;

                   default:
                  break;
        }
            default:
            break;
            }
          }
    }

void bye(UBYTE *s,int error)
   {
   if((*s)&&(!FromWb)) printf("%s\n",s);
   cleanup();
   exit(error);
   }

void cleanup()
   {
   if(ilbms[SCR])
    {
       if(ilbms[SCR]->scr)		unshowilbm(ilbms[SCR]);
#ifdef SAVECHANGES
       freechunklist(ilbms[SCR]->ParseInfo.copiedchunks);
#endif
       if(ilbms[SCR]->ParseInfo.iff)	FreeIFF(ilbms[SCR]->ParseInfo.iff);
    }

   if(ilbms[BRU])
    {
       if(ilbms[BRU]->brbitmap)	unloadbrush(ilbms[BRU]);
       if(ilbms[BRU]->ParseInfo.iff) 	FreeIFF(ilbms[BRU]->ParseInfo.iff);
    }

   if(ilbms[0])
    {
    FreeMem(ilbms[0],UICOUNT * sizeof(struct ILBMInfo));
    }

   if(GfxBase) 	     CloseLibrary(GfxBase);
   if(IntuitionBase) CloseLibrary(IntuitionBase);
   if(IFFParseBase)  CloseLibrary(IFFParseBase);
   }


Devices/apps/RawtoILBM/RawtoILBM.c

/* RawtoILBM
 * Converts raw file (from ILBMtoRaw) into an ILBM
 * Requires linkage with several iffparse modiules - See Makefile
 */

#include "iffp/ilbmapp.h"

#include <intuition/intuitionbase.h>
#include <workbench/workbench.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

char *vers = "\0$VER: RawtoILBM 37.5";
char *Copyright =
  "RawtoILBM v37.5 - converts raw file to ILBM - Freely Redistributable";
#define MINARGS 6
char *usage = "Usage: RawtoILBM rawname ilbmname width height depth\n";

void bye(UBYTE *s,int e);
void cleanup(void);

struct Library	*IntuitionBase = NULL;
struct Library	*GfxBase = NULL;
struct Library	*IFFParseBase = NULL;

struct ILBMInfo ilbm = {0};

USHORT	colortable[MAXAMCOLORREG];

BOOL fromWB;

void main(int argc, char **argv)
    {
    LONG	error = 0L, rawfile, rlen;
    USHORT	width, height, depth, pwidth, pheight, pmode, extra;
    ULONG 	plsize;
    char        *rawname,*ilbmname;
    int 	k;

    fromWB = (argc==0) ? TRUE : FALSE;

    if(!(IntuitionBase = OpenLibrary("intuition.library", 0)))
      bye("Can't open intuition library.\n",RETURN_WARN);

    if(!(GfxBase = OpenLibrary("graphics.library",0)))
      bye("Can't open graphics library.\n",RETURN_WARN);

    if(!(IFFParseBase = OpenLibrary("iffparse.library",0)))
      bye("Can't open iffparse library.\n",RETURN_WARN);

    if(!(ilbm.ParseInfo.iff = AllocIFF()))
      bye(IFFerr(IFFERR_NOMEM),RETURN_WARN);

    if(argc==MINARGS)                 /* Passed filenames via command line  */
          {
          rawname  = argv[1];
          ilbmname = argv[2];
    width  = atoi(argv[3]);
    height = atoi(argv[4]);
    depth  = atoi(argv[5]);

    /* Page width, height, and mode for saved ILBM */
    pwidth  = width  < 320 ? 320 : width;
    pheight = height < 200 ? 200 : height;
    pmode	= pwidth >= 640  ? HIRES : 0L;
    pmode  |= pheight >= 400 ? LACE  : 0L;

    plsize = RASSIZE(width,height);
    }
    else
    {
    printf("%s\n%s\n",Copyright,usage);
    bye("\n",RETURN_OK);
    }

    if(!(rawfile = Open(rawname,MODE_OLDFILE)))
    {
    printf("Can't open raw file '%s'\n",rawname);
    bye(" ",RETURN_WARN);
    }

    /*
     * Allocate Bitmap and planes
     */
     extra = depth > 8 ? depth - 8 : 0;
     if(ilbm.brbitmap = AllocMem(sizeof(struct BitMap) + (extra<<2),
                MEMF_CLEAR))
        {
        InitBitMap(ilbm.brbitmap,depth,width,height);
        for(k=0, error=0, rlen=1; k<depth && (!error) && (rlen >0); k++)
            {
            if(!(ilbm.brbitmap->Planes[k] = AllocRaster(width,height)))
            error = IFFERR_NOMEM;
            if(! error)
        {
                BltClear(ilbm.brbitmap->Planes[k], RASSIZE(width,height),0);
        /* Read a plane */
        rlen = Read(rawfile,ilbm.brbitmap->Planes[k],plsize);
                }
        }

    /* get colortable */
    if((!error)&&(rlen > 0))
        rlen=Read(rawfile,colortable,(MIN(1<<depth,MAXAMCOLORREG)<<1));

        if((error)||(rlen<=0))
            {
        if(rlen <= 0)  	printf("Error loading raw file - check dimensions\n");
            else 		printf("Error allocating planes\n");
        }
    else
        {
        error = saveilbm(&ilbm, ilbm.brbitmap, pmode,
                width,  height, pwidth, pheight,
                colortable, MIN(1<<depth,MAXAMCOLORREG), 4,    /* colors */
        mskNone, 0,		/* masking. transColor */
        NULL, NULL,		/* additional chunk lists */
        ilbmname);
        }

        for(k=0; k<depth; k++)
            {
            if(ilbm.brbitmap->Planes[k])
            FreeRaster(ilbm.brbitmap->Planes[k],width,height);
        }
    FreeMem(ilbm.brbitmap, sizeof(struct BitMap) + (extra << 2));
    }

    Close(rawfile);

    if(error)
    {
    printf("%s\n",IFFerr(error));
    bye(" ", RETURN_FAIL);
    }
    else bye("",RETURN_OK);
    }

void bye(UBYTE *s,int e)
    {
    if(s&&(*s)) printf("%s\n",s);
    if ((fromWB)&&(*s))    /* Wait so user can read messages */
        {
        printf("\nPRESS RETURN TO EXIT\n");
        while(getchar() != '\n');
        }
    cleanup();
    exit(e);
    }

void cleanup()
    {
    if(ilbm.ParseInfo.iff)	FreeIFF(ilbm.ParseInfo.iff);

    if(GfxBase)		CloseLibrary(GfxBase);
    if(IntuitionBase)	CloseLibrary(IntuitionBase);
    if(IFFParseBase)	CloseLibrary(IFFParseBase);
    }


Devices/modules/getdisplay.c

/*----------------------------------------------------------------------*
 * GETDISPLAY.C  Support routines for reading/displaying ILBM files.
 * (IFF is Interchange Format File.)
 *
 * Based on code by Jerry Morrison and Steve Shaw, Electronic Arts.
 * This software is in the public domain.
 * Modified for iffparse.library by CBM 04/90
 * This version for the Amiga computer.
 *----------------------------------------------------------------------*/

#include "iffp/ilbm.h"
#include "iffp/packer.h"
#include "iffp/ilbmapp.h"

extern struct Library *GfxBase;

/* showilbm
 *
 * Passed an ILBMInfo initilized with with a not-in-use ParseInfo.iff
 *   IFFHandle and desired propchks, collectchks, stopchks, and a filename,
 *   will load and display an ILBM, initializing ilbm->Bmhd, ilbm->camg,
 *   ilbm->scr, ilbm->win, ilbm->vp, ilbm->srp, ilbm->wrp,
 *   ilbm->colortable, and ilbm->ncolors.
 *
 *   Note that ncolors may be more colors than you can LoadRGB4.
 *   Use MIN(ilbm->ncolors,MAXAMCOLORREG) for color count if you change
 *   the colors yourself using 1.3/2.0 functions.
 *
 * Returns 0 for success or an IFFERR (libraries/iffparse.h)
 */

LONG showilbm(struct ILBMInfo *ilbm, UBYTE *filename)
{
LONG error = 0L;

    if(!(ilbm->ParseInfo.iff))	return(CLIENT_ERROR);

    if(!(error = openifile((struct ParseInfo *)ilbm, filename, IFFF_READ)))
    {
    D(bug("showilbm: openifile successful\n"));

    error = parseifile((struct ParseInfo *)ilbm,
                ID_FORM, ID_ILBM,
                ilbm->ParseInfo.propchks,
                ilbm->ParseInfo.collectchks,
                ilbm->ParseInfo.stopchks);

    if((!error)||(error == IFFERR_EOC)||(error == IFFERR_EOF))
        {
        D(bug("showilbm: parseifile successful\n"));

        if(contextis(ilbm->ParseInfo.iff,ID_ILBM,ID_FORM))
        {
            if(error = createdisplay(ilbm))	deletedisplay(ilbm);
        }
        else
        {
        closeifile((struct ParseInfo *)ilbm);
        message("Not an ILBM\n");
        error = NOFILE;
        }
        }
    }
    return(error);
}

/* unshowilbm
 *
 * frees and closes everything alloc'd/opened by showilbm
 */
void unshowilbm(struct ILBMInfo *ilbm)
{
    deletedisplay(ilbm);
    closeifile((struct ParseInfo *)ilbm);
}

/* createdisplay
 *
 * Passed a initialized ILBMInfo with parsed IFFHandle (chunks parsed,
 * stopped at BODY),
 * opens/allocs the display and colortable, and displays the ILBM.
 *
 * If successful, sets up ilbm->Bmhd, ilbm->camg, ilbm->scr, ilbm->win,
 *   ilbm->vp,  ilbm->wrp, ilbm->srp and also ilbm->colortable and
 *   ilbm->ncolors.
 *
 * Note that ncolors may be more colors than you can LoadRGB4.
 * Use MIN(ilbm->ncolors,MAXAMCOLORREG) for color count if you change
 *   the colors yourself using 1.3/2.0 functions.
 *
 * Returns 0 for success or an IFFERR (libraries/iffparse.h)
 */

LONG createdisplay(struct ILBMInfo *ilbm)
    {
    int error;

    D(bug("createdisplay:\n"));

    error 			= getdisplay(ilbm);

    D(bug("createdisplay: after getdisplay, error = %ld\n", error));

    if(!error) 	error 	= loadbody(ilbm->ParseInfo.iff,
                        &ilbm->scr->BitMap,&ilbm->Bmhd);

    D(bug("createdisplay: after loadbody, error = %ld\n", error));

    if(!error)
        {
        if(!(getcolors(ilbm)))
           LoadRGB4(ilbm->vp, ilbm->colortable,
                MIN(ilbm->ncolors,MAXAMCOLORREG));
        }
    if(error)  deletedisplay(ilbm);
    return(error);
    }

/* deletedisplay
 *
 * closes and deallocates created display and colors
 */
void deletedisplay(struct ILBMInfo *ilbm)
    {
    freedisplay(ilbm);
    freecolors(ilbm);
    }

/* getdisplay
 *
 * Passed an initialized ILBMInfo with a parsed IFFHandle (chunks parsed,
 * stopped at BODY),
 * gets the dimensions and mode for the display and calls the external
 * routine opendisplay().  Our opendisplay() is in the screen.c
 * module.  It opens a 2.0 or 1.3, ECS or non-ECS screen and window.
 * It also does 2.0 overscan centering based on the closest user prefs.
 *
 * If successful, sets up ilbm->Bmhd, ilbm->camg, ilbm->scr, ilbm->win,
 *   ilbm->vp, ilbm->wrp, ilbm->srp
 *
 * Returns 0 for success or an IFFERR (libraries/iffparse.h)
 */
LONG getdisplay(struct ILBMInfo *ilbm)
    {
    struct IFFHandle *iff;
    BitMapHeader *bmhd;
    ULONG				modeid;
    UWORD				wide, high, deep;

    if(!(iff=ilbm->ParseInfo.iff))	return(CLIENT_ERROR);

    if(!(bmhd = (BitMapHeader *)findpropdata(iff, ID_ILBM, ID_BMHD)))
        {
        message ("No ILBM.BMHD chunk\n");
        return(IFFERR_SYNTAX);
        }

    *(&ilbm->Bmhd)	= *bmhd;

        wide = (RowBytes(bmhd->w)) >= (RowBytes(bmhd->pageWidth)) ?
                bmhd->w : bmhd->pageWidth;
        high = MAX(bmhd->h, bmhd->pageHeight);
        deep = MIN(bmhd->nPlanes,MAXAMDEPTH);

    ilbm->camg = modeid = getcamg(ilbm);

    /*
     * Open the display
     */
    if(!(opendisplay(ilbm,wide,high,deep,modeid)))
        {
        message("Failed to open display.\n");
        return(1);
        }
    return(0);
    }

/* freedisplay
 *
 * closes and deallocates display from getdisplay (not colors)
 */
void freedisplay(struct ILBMInfo *ilbm)
    {
    closedisplay(ilbm);
    }


Devices/modules/parse.c

/*
 * parse.c - iffparse file IO support module
 *   based on some of looki.c by Leo Schwab
 *
 * The filename for clipboard is -c or -cUnit as in -c0 -c1 etc. (default 0)
 */

#include <exec/types.h>

#include "iffp/iff.h"

/* local function prototypes */

LONG stdio_stream(struct Hook *, struct IFFHandle *, struct IFFStreamCmd *);

UBYTE *omodes[2] = {"r","w"};

/* openifile
 *
 * Passed a ParseInfo structure with a not-in-use IFFHandle, filename
 *   ("-c" or -cUnit like "-c1" for clipboard), and IFF open mode
 *   (IFFF_READ or IFFF_WRITE) opens file or clipboard for use with
 *   iffparse.library support modules.
 *
 * Returns 0 for success or an IFFERR (libraries/iffparse.h)
 */

LONG openifile(struct ParseInfo *pi, UBYTE *filename, ULONG iffopenmode)
{
    struct IFFHandle	*iff;
    BOOL	cboard;
    ULONG 	unit = PRIMARY_CLIP;
    LONG 	error;

    if(!pi)			return(CLIENT_ERROR);
        if(!(iff=pi->iff))	return(CLIENT_ERROR);

    cboard = (*filename == '-'  &&  filename[1] == 'c');
     if(cboard && filename[2])	unit = atoi(&filename[2]);

    if (cboard)
        {
        /*
         * Set up IFFHandle for Clipboard I/O.
         */
        pi->clipboard = TRUE;
        if (!(iff->iff_Stream =
                (ULONG)OpenClipboard(unit)))
            {
            message("Clipboard open of unit %ld failed.\n",unit);
            return(NOFILE);
            }
        InitIFFasClip(iff);
        }
    else
        {
        pi->clipboard = FALSE;
        /*
         * Set up IFFHandle for buffered stdio I/O.
         */
        if (!(iff->iff_Stream = (ULONG)
           fopen(filename, omodes[iffopenmode & 1])))
            {
            message("%s: File open failed.\n",filename);
            return(NOFILE);
            }
        else initiffasstdio(iff);
        }

    D(bug("%s file opened: \n", cboard ? "[Clipboard]" : filename));

    pi->filename = filename;

    error=OpenIFF(iff, iffopenmode);

    pi->opened = error ? FALSE : TRUE;	/* currently open handle */

    D(bug("OpenIFF error = %ld\n",error));
    return(error);
}

/* closeifile
 *
 * closes file or clipboard opened with openifile, and frees all
 *   iffparse context parsed by parseifile.
 *
 * Note - You should closeifile as soon as possible if using clipboard
 *   ("-c[n]").  You also need to closeifile if, for example, you wish to
 *   reopen the file to write changes back out.  See the copychunks.c
 *   module for routines which allow you clone the chunks iffparse has
 *   gathered so that you can closeifile and still be able to modify and
 *   write back out gathered chunks.
 *
 */

void closeifile(struct ParseInfo *pi)
{
struct IFFHandle *iff;

    D(bug("closeifile:\n"));

    if(!pi)			return;
        if(!(iff=pi->iff))	return;

    DD(bug("closeifile: About to CloseIFF if open, iff=$%lx, opened=%ld\n",
            iff, pi->opened));

    if(pi->opened)	CloseIFF(iff);

    DD(bug("closeifile: About to close %s, stream=$%lx\n",
            pi->clipboard ? "clipboard" : "file", iff->iff_Stream));
    if(iff->iff_Stream)
        {
        if (pi->clipboard)
           CloseClipboard((struct ClipHandle *)(iff->iff_Stream));
        else
           fclose ((FILE *)(iff->iff_Stream));
        }

    iff->iff_Stream = NULL;
    pi->clipboard = NULL;
    pi->opened = NULL;
}

/* parseifile
 *
 * Passed a ParseInfo with an initialized and open IFFHandle,
 *  grouptype (like ID_FORM), groupid (like ID_ILBM),
 *  and TAG_DONE terminated longword arrays of type,id
 *  for chunks to be grabbed, gathered, and stopped on
 *  (like { ID_ILBM, ID_BMHD, ID_ILBM, ID_CAMG, TAG_DONE })
 *  will parse an IFF file, grabbing/gathering and stopping
 *  on specified chunk.
 *
 * Note - you can call getcontext() (to continue after a stop chunk) or
 *  nextcontext() (after IFFERR_EOC, to parse next form in the same file)
 *  if you wish to continue parsing the same IFF file.  If parseifile()
 *  has to delve into a complex format to find your desired FORM, the
 *  pi->hunt flag will be set.  This should be a signal to you that
 *  you may not have the capability to simply modify and rewrite
 *  the data you have gathered.
 *
 * Returns 0 for success else and IFFERR (libraries/iffparse.h)
 */

LONG parseifile(pi,groupid,grouptype,propchks,collectchks,stopchks)
struct	ParseInfo *pi;
LONG groupid, grouptype;
LONG *propchks, *collectchks, *stopchks;
{
struct IFFHandle *iff;
register struct ContextNode	*cn;
LONG			error = 0L;

        if(!(iff=pi->iff))	return(CLIENT_ERROR);

    if(!iff->iff_Stream)	return(IFFERR_READ);

    pi->hunt = FALSE;

    /*
     * Declare property, collection and stop chunks.
     */
    if (propchks)
      if (error = PropChunks (iff, propchks, chkcnt(propchks)))
        return (error);
    if (collectchks)
      if (error =
          CollectionChunks(iff, collectchks, chkcnt(collectchks)))
        return (error);
    if (stopchks)
      if (error = StopChunks (iff, stopchks, chkcnt(stopchks)))
        return (error);

    /*
     * We want to stop at the end of an ILBM context.
     */
    if (grouptype)
      if (error = StopOnExit (iff, grouptype, groupid))
        return(error);

    /*
     * Take first parse step to enter main chunk.
     */
    if (error = ParseIFF (iff, IFFPARSE_STEP))
        return(error);

    /*
     * Test the chunk info to see if simple form of type we want (ILBM).
     */
    if (!(cn = CurrentChunk (iff)))
        {
        /*
         * This really should never happen.  If it does, it means
         * our parser is broken.
         */
        message("Parsing error; no top chunk!\n");
        return(NOFILE);
        }

    if (cn->cn_ID != groupid  ||  cn->cn_Type != grouptype)
        {

        D(bug("This is a(n) %.4s.%.4s.  Looking for embedded %.4s's...\n",
          &cn->cn_Type, &cn->cn_ID, &grouptype));

        pi->hunt = TRUE;	/* Warning - this is a complex file */
        }

    if(!error)	error = getcontext(iff);
    return(error);
}

/* chkcnt
 *
 * simply counts the number of chunk pairs (type,id) in array
 */
LONG chkcnt(LONG *taggedarray)
{
LONG k = 0;

    while(taggedarray[k] != TAG_DONE) k++;
    return(k>>1);
}

/* currentchunkis
 *
 * returns the ID of the current chunk (like ID_CAMG)
 */
LONG currentchunkis(struct IFFHandle *iff, LONG type, LONG id)
{
register struct ContextNode	*cn;
LONG result = 0;

    if (cn = CurrentChunk (iff))
        {
        if((cn->cn_Type == type)&&(cn->cn_ID == id)) result = 1;
        }
    return(result);
}

/* contextis
 *
 * returns the enclosing context of the current chunk (like ID_ILBM)
 */
LONG contextis(struct IFFHandle *iff, LONG type, LONG id)
{
register struct ContextNode	*cn;
LONG result = 0;

       if (cn = (CurrentChunk (iff)))
           {
           if (cn = (ParentChunk(cn)))
               {
               if((cn->cn_Type == type)&&(cn->cn_ID == id)) result = 1;
               }
       }

    D(bug("This is a %.4s %.4s\n",&cn->cn_Type,&cn->cn_ID));

    return(result);
}

/* getcontext()
 *
 * Continues to gather the context which was specified to parseifile(),
 *  stopping at specified stop chunk, or end of context, or EOF
 *
 * Returns 0 (stopped on a stop chunk)
 *      or IFFERR_EOC (end of context, not an error)
 *      or IFFER_EOF (end of file)
 */
LONG getcontext(iff)
struct	IFFHandle *iff;
{
    LONG error = 0L;

    /* Based on our parse initialization,
     * ParseIFF() will return on a stop chunk (error = 0)
     * or end of context for an ILBM FORM (error = IFFERR_EOC)
     * or end of file (error = IFFERR_EOF)
     */
    return(error = ParseIFF(iff, IFFPARSE_SCAN));
}

/* nextcontext
 *
 * If you have finished parsing and reading your context (IFFERR_EOC),
 *   nextcontext will enter the next context contained in the file
 *   and parse it.
 *
 * Returns 0 or an IFFERR such as IFFERR_EOF (end of file)
 */

LONG nextcontext(iff)
struct	IFFHandle *iff;
{
    LONG error = 0L;

    error = ParseIFF(iff, IFFPARSE_STEP);

    D(bug("nextcontext: Got through next step\n"));

    return(error);
}

/* findpropdata
 *
 * finds specified chunk parsed from IFF file, and
 *   returns pointer to its sp_Data (or 0 for not found)
 */
UBYTE *findpropdata(iff, type, id)
struct IFFHandle	*iff;
LONG type, id;
    {
    register struct StoredProperty	*sp;

    if(sp = FindProp (iff, type, id)) return(sp->sp_Data);
    return(0);
    }

/*
 * File I/O hook functions which the IFF library will call.
 * A return of 0 indicates success (no error).
 *
 * Iffparse.library calls this code via struct Hook and Hook.asm
 */
static LONG
stdio_stream (hook, iff, actionpkt)
struct Hook		*hook;
struct IFFHandle	*iff;
struct IFFStreamCmd	*actionpkt;
{
    register FILE	*stream;
    register LONG	nbytes;
    register int	actual;
    register UBYTE	*buf;
    long	len;

    stream	= (FILE *) iff->iff_Stream;
    if(!stream)	return(1);

    nbytes	= actionpkt->sc_NBytes;
    buf	= (UBYTE *) actionpkt->sc_Buf;

    switch (actionpkt->sc_Command) {
    case IFFSCC_READ:
        do {
            actual = nbytes > 32767 ? 32767 : nbytes;
            if ((len=fread (buf, 1, actual, stream)) != actual)
                break;
            nbytes -= actual;
            buf += actual;
        } while (nbytes > 0);
        return (nbytes ? IFFERR_READ : 0 );

    case IFFSCC_WRITE:
        do {
            actual = nbytes > 32767 ? 32767 : nbytes;
            if ((len=fwrite (buf, 1, actual, stream)) != actual)
                break;
            nbytes -= actual;
            buf += actual;
        } while (nbytes > 0);
        return (nbytes ? IFFERR_WRITE : 0);

    case IFFSCC_SEEK:
        return ((fseek (stream, nbytes, 1) == -1) ? IFFERR_SEEK : 0);

    default:
        /*  No _INIT or _CLEANUP required.  */
        return (0);
    }
}

/* initiffasstdio (ie. init iff as stdio)
 *
 * sets up hook callback for the file stream handler above
 */
void initiffasstdio (iff)
struct IFFHandle *iff;
{
    extern LONG		HookEntry();
    static struct Hook	stdiohook = {
        { NULL },
        (ULONG (*)()) HookEntry,
        (ULONG (*)()) stdio_stream,
        NULL
    };

    /*
     * Initialize the IFF structure to point to the buffered I/O
     * routines.  Unbuffered I/O is terribly slow.
     */
    InitIFF (iff, IFFF_FSEEK | IFFF_RSEEK, &stdiohook);
}

/*
 * IFFerr
 *
 * Returns pointer to IFF Error string or NULL (no error)
 */
UBYTE *IFFerr(error)
LONG	error;
{
    /*
     * English error messages for possible IFFERR_#? returns from various
     * IFF routines.  To get the index into this array, take your IFFERR
     * code, negate it, and subtract one.
     *  idx = -error - 1;
     */
    static UBYTE	*errormsgs[] = {
        "End of file (not an error).",
        "End of context (not an error).",
        "No lexical scope.",
        "Insufficient memory.",
        "Stream read error.",
        "Stream write error.",
        "Stream seek error.",
        "File is corrupt.",
        "IFF syntax error.",
        "Not an IFF file.",
        "Required hook vector missing.",
        "Return to client."
    };
    static UBYTE unknown[32];
    static UBYTE client[] = "Client error";
    static UBYTE nofile[] = "File not found or wrong type";

    if (error < 0)
        {
        return(errormsgs[(-error) - 1]);
        }
    else if(error = CLIENT_ERROR)
        {
        return(client);
        }
    else if(error = NOFILE)
        {
        return(nofile);
        }
    else if(error)
        {
        sprintf(unknown,"Unknown error %ld",error);
        return(unknown);
        }
    else return(NULL);
}

/*
 * PutCk
 *
 * Writes one chunk of data to an iffhandle
 *
 */
long PutCk(struct IFFHandle *iff, long id, long size, void *data)
    {
    long error = 0, wlen;

    D(bug("PutCk: asked to push chunk \"%.4s\" ($%lx) length %ld\n",&id,id,size));

    if(error=PushChunk(iff, 0, id, size))
    {
    D(bug("PutCk: PushChunk of %.4s, error = %s, size = %ld\n",
        id, IFFerr(error), id));
    }
    else
    {
    D(bug("PutCk: PushChunk of %.4s, error = %ld\n",&id, error));

    /* Write the actual data */
    if((wlen = WriteChunkBytes(iff,data,size)) != size)
        {
        D(bug("WriteChunkBytes error: size = %ld, wrote %ld\n",size,wlen));
        error = IFFERR_WRITE;
        }
    else error = PopChunk(iff);
    D(bug("PutCk: After PopChunk - error = %ld\n",error));
    }
    return(error);
    }


Devices/other/clipftxt.c

;/* clipftxt.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -j73 clipftxt.c
Blink FROM LIB:c.o,clipftxt.o TO clipftxt LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit

*
* clipftxt.c:	Writes ASCII text to clipboard unit as FTXT
*		(All clipboard data must be IFF)
*
* Usage: clipftxt unitnumber
*
* To convert to an example of reading only, comment out #define WRITEREAD
*/

#include <exec/types.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <libraries/iffparse.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/iffparse_protos.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

/* Causes example to write FTXT first, then read it back
 * Comment out to create a reader only
 */
#define WRITEREAD

#define MINARGS 2

/* 2.0 Version string for c:Version to find */
UBYTE vers[] = "\0$VER: clipftxt 37.2";

UBYTE usage[] = "Usage: clipftxt unitnumber (use zero for primary unit)";

/*
 * Text error messages for possible IFFERR_#? returns from various
 * IFF routines.  To get the index into this array, take your IFFERR code,
 * negate it, and subtract one.
 *  idx = -error - 1;
 */
char	*errormsgs[] = {
    "End of file (not an error).",
    "End of context (not an error).",
    "No lexical scope.",
    "Insufficient memory.",
    "Stream read error.",
    "Stream write error.",
    "Stream seek error.",
    "File is corrupt.",
    "IFF syntax error.",
    "Not an IFF file.",
    "Required call-back hook missing.",
    "Return to client.  You should never see this."
};

#define RBUFSZ 512

#define  ID_FTXT	MAKE_ID('F','T','X','T')
#define  ID_CHRS	MAKE_ID('C','H','R','S')

struct Library *IFFParseBase;

UBYTE mytext[]="This FTXT written to clipboard by clipftxt example.\n";

void main(int argc, char **argv)
{
    struct IFFHandle	*iff = NULL;
    struct ContextNode  *cn;
    long		error=0, unitnumber=0, rlen;
    int textlen;
    UBYTE readbuf[RBUFSZ];

        /* if not enough args or '?', print usage */
        if(((argc)&&(argc<MINARGS))||(argv[argc-1][0]=='?'))
        {
            printf("%s\n",usage);
            exit(RETURN_WARN);
            }

    unitnumber = atoi(argv[1]);

    if (!(IFFParseBase = OpenLibrary ("iffparse.library", 0L)))
        {
        puts("Can't open iff parsing library.");
        goto bye;
        }

    /*
     * Allocate IFF_File structure.
     */
    if (!(iff = AllocIFF ()))
        {
        puts ("AllocIFF() failed.");
        goto bye;
        }

    /*
     * Set up IFF_File for Clipboard I/O.
     */
    if (!(iff->iff_Stream = (ULONG) OpenClipboard (unitnumber)))
        {
        puts ("Clipboard open failed.");
        goto bye;
        }
    else printf("Opened clipboard unit %ld\n",unitnumber);

    InitIFFasClip (iff);

#ifdef WRITEREAD

    /*
     * Start the IFF transaction.
     */
    if (error = OpenIFF (iff, IFFF_WRITE))
        {
        puts ("OpenIFF for write failed.");
        goto bye;
        }

    /*
     * Write our text to the clipboard as CHRS chunk in FORM FTXT
     *
     * First, write the FORM ID (FTXT)
     */
        if(!(error=PushChunk(iff, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN)))
        {
        /* Now the CHRS chunk ID followed by the chunk data
         * We'll just write one CHRS chunk.
         * You could write more chunks.
         */
            if(!(error=PushChunk(iff, 0, ID_CHRS, IFFSIZE_UNKNOWN)))
            {
            /* Now the actual data (the text) */
            textlen = strlen(mytext);
            if(WriteChunkBytes(iff, mytext, textlen) != textlen)
                {
                puts("Error writing CHRS data.");
                error = IFFERR_WRITE;
                }
            }
        if(!error) error = PopChunk(iff);
        }
    if(!error) error = PopChunk(iff);

    if(error)
        {
        printf ("IFF write failed, error %ld: %s\n",
            error, errormsgs[-error - 1]);
        goto bye;
        }
    else printf("Wrote text to clipboard as FTXT\n");

    /*
     * Now let's close it, then read it back
     * First close the write handle, then close the clipboard
     */
    CloseIFF(iff);
    if (iff->iff_Stream) CloseClipboard ((struct ClipboardHandle *)
                        iff->iff_Stream);

    if (!(iff->iff_Stream = (ULONG) OpenClipboard (unitnumber)))
        {
        puts ("Reopen of Clipboard failed.");
        goto bye;
        }
    else printf("Reopened clipboard unit %ld\n",unitnumber);

#endif /* WRITEREAD */

    if (error = OpenIFF (iff, IFFF_READ))
        {
        puts ("OpenIFF for read failed.");
        goto bye;
        }

    /* Tell iffparse we want to stop on FTXT CHRS chunks */
    if (error = StopChunk(iff, ID_FTXT, ID_CHRS))
        {
        puts ("StopChunk failed.");
        goto bye;
        }

    /* Find all of the FTXT CHRS chunks */
    while(1)
        {
        error = ParseIFF(iff,IFFPARSE_SCAN);
        if(error == IFFERR_EOC) continue;	/* enter next context */
        else if(error) break;

        /* We only asked to stop at FTXT CHRS chunks
         * If no error we've hit a stop chunk
         * Read the CHRS chunk data
         */
        cn = CurrentChunk(iff);

        if((cn)&&(cn->cn_Type == ID_FTXT)&&(cn->cn_ID == ID_CHRS))
            {
            printf("CHRS chunk contains:\n");
            while((rlen = ReadChunkBytes(iff,readbuf,RBUFSZ)) > 0)
                {
                Write(Output(),readbuf,rlen);
                }
            if(rlen < 0)	error = rlen;
            }
        }

    if((error)&&(error != IFFERR_EOF))
        {
        printf ("IFF read failed, error %ld: %s\n",
            error, errormsgs[-error - 1]);
        }

bye:
    if (iff) {
        /*
         * Terminate the IFF transaction with the stream.  Free
         * all associated structures.
         */
        CloseIFF (iff);

        /*
         * Close the clipboard stream
         */
        if (iff->iff_Stream)
                CloseClipboard ((struct ClipboardHandle *)
                        iff->iff_Stream);
        /*
         * Free the IFF_File structure itself.
         */
        FreeIFF (iff);
        }
    if (IFFParseBase)	CloseLibrary (IFFParseBase);

    exit (RETURN_OK);
}


Devices/apps/ILBMLoad/ILBMLoad.c

/* ILBMLoad.c 05/91  C. Scheppner CBM
 *
 * Example which
 *  - first queries an ILBM to determine size and mode
 *  - then opens an appropriate screen and window
 *  - then loads the ILBM into the already opened screen
 *
 * For clipboard, use filename -c[unit] (like -c, -c1, -c2, etc.)
 *
 * requires linkage with several IFF modules
 * see Makefile
 */

#include "iffp/ilbmapp.h"

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

void cleanup(void);
void bye(UBYTE *s,int error);

#define MINARGS 2
char *vers = "\0$VER: ILBMLoad 37.5";
char *Copyright = "ILBMLoad v37.5 (Freely Redistributable)";
char *usage = "Usage: ILBMLoad ilbmname (-c[unit] for clipboard";

struct Library *IntuitionBase  = NULL;
struct Library *GfxBase        = NULL;
struct Library *IFFParseBase   = NULL;

/* Note - these fields are also available in the ILBMInfo structure */
struct   Screen         *scr;         /* for ptr to screen structure */
struct   Window         *win;         /* for ptr to window structure */
struct   RastPort       *wrp;         /* for ptr to RastPort  */
struct   ViewPort       *vp;          /* for ptr to Viewport  */

struct   IntuiMessage   *msg;

struct   NewWindow      mynw = {
   0, 0,                                  /* LeftEdge and TopEdge */
   0, 0,                          	  /* Width and Height */
   -1, -1,                                /* DetailPen and BlockPen */
   VANILLAKEY|MOUSEBUTTONS,               /* IDCMP Flags with Flags below */
   BACKDROP|BORDERLESS|SMART_REFRESH|NOCAREREFRESH|ACTIVATE|RMBTRAP,
   NULL, NULL,                            /* Gadget and Image pointers */
   NULL,                                  /* Title string */
   NULL,                                  /* Screen ptr null till opened */
   NULL,                                  /* BitMap pointer */
   50, 20,                                /* MinWidth and MinHeight */
   0 , 0,                                 /* MaxWidth and MaxHeight */
   CUSTOMSCREEN                           /* Type of window */
   };

BOOL   FromWb;

/* ILBM Property chunks to be grabbed
 * List BMHD, CMAP and CAMG first so we can skip them when we write
 * the file back out (they will be written out with separate code)
 */
LONG	ilbmprops[] = {
        ID_ILBM, ID_BMHD,
        ID_ILBM, ID_CMAP,
        ID_ILBM, ID_CAMG,
        ID_ILBM, ID_CCRT,
        ID_ILBM, ID_AUTH,
        ID_ILBM, ID_Copyright,
        TAG_DONE
        };

/* ILBM Collection chunks (more than one in file) to be gathered */
LONG	ilbmcollects[] = {
        ID_ILBM, ID_CRNG,
        TAG_DONE
        };

/* ILBM Chunk to stop on */
LONG	ilbmstops[] = {
        ID_ILBM, ID_BODY,
        TAG_DONE
        };

UBYTE nomem[]  = "Not enough memory\n";
UBYTE noiffh[] = "Can't alloc iff\n";

/* For our allocated ILBM frame */
struct ILBMInfo  *ilbm;

/*
 * MAIN
 */
void main(int argc, char **argv)
   {
   UBYTE *ilbmname=NULL;
   LONG error = 0L;

   FromWb = argc ? FALSE : TRUE;

   if((argc<MINARGS)||(argv[argc-1][0]=='?'))
    {
    printf("%s\n%s\n",Copyright,usage);
        bye("",RETURN_OK);
    }

   ilbmname = argv[1];

   /* Open Libraries */

   if(!(IntuitionBase = OpenLibrary("intuition.library", 0)))
      bye("Can't open intuition library.\n",RETURN_WARN);

   if(!(GfxBase = OpenLibrary("graphics.library",0)))
      bye("Can't open graphics library.\n",RETURN_WARN);

   if(!(IFFParseBase = OpenLibrary("iffparse.library",0)))
      bye("Can't open iffparse library.\n",RETURN_WARN);

/*
 * Alloc one ILBMInfo struct
 */
    if(!(ilbm = (struct ILBMInfo *)
    AllocMem(sizeof(struct ILBMInfo),MEMF_PUBLIC|MEMF_CLEAR)))
        bye(nomem,RETURN_FAIL);

/*
 * Here we set up our ILBMInfo fields for our
 * application.
 * Above we have defined the propery and collection chunks
 * we are interested in (some required like BMHD)
 */

    ilbm->ParseInfo.propchks	= ilbmprops;
    ilbm->ParseInfo.collectchks	= ilbmcollects;
    ilbm->ParseInfo.stopchks	= ilbmstops;

    ilbm->windef	= &mynw;

/*
 * Alloc IFF handle for frame
 */
    if(!(ilbm->ParseInfo.iff = AllocIFF())) bye(noiffh,RETURN_FAIL);

/* Normally you would use showilbm() to open an appropriate acreen
 * and display an ILBM in it.
 *
 * However, here we are demonstrating
 *  - first querying an ILBM to get its BMHD and CAMG (real or computed)
 *  - then opening our own display
 *  - then loading the ILBM into it
 */

    if(!(error = queryilbm(ilbm,ilbmname)))
    {
    D(bug("ilbmload: after query, this ILBM is %ld x %ld x %ld, modeid=$%lx\n",
        ilbm->Bmhd.w, ilbm->Bmhd.h, ilbm->Bmhd.nPlanes, ilbm->camg));

    /* Note - you could use your own routines to open your
     * display, but if so, you must initialize ilbm->scr,
     * ilbm->win, ilbm->wrp, ilbm->srp, and ilbm->vp for your display.
     * Here we will use opendisplay() which will initialize
     * those fields.
     */
    if(!(opendisplay(ilbm,
            MAX(ilbm->Bmhd.pageWidth, ilbm->Bmhd.w),
            MAX(ilbm->Bmhd.pageHeight,ilbm->Bmhd.h),
            MIN(ilbm->Bmhd.nPlanes,MAXAMDEPTH),
            ilbm->camg)))
        {
        printf("Failed to open display\n");
        }
    else
        {
        D(bug("ilbmload: opendisplay successful\n"));

        scr = ilbm->scr;
        win = ilbm->win;

        if(!(error = loadilbm(ilbm, ilbmname)))
        {
            D(bug("ilbmload: loadilbm successful\n"));

        /* Note - we don't need to examine or copy any
         * chunks from the file, so we will close file now
         */
        closeifile(ilbm);
        ScreenToFront(ilbm->scr);
        Wait(1<<win->UserPort->mp_SigBit);
        unloadilbm(ilbm);	/* deallocs colors, closeifile if needed */
        }
        closedisplay(ilbm);
         }
          }

    if(error)	printf("%s\n",IFFerr(error));

    cleanup();
    exit(RETURN_OK);
    }

void bye(UBYTE *s,int error)
   {
   if((*s)&&(!FromWb)) printf("%s\n",s);
   cleanup();
   exit(error);
   }

void cleanup()
   {
   if(ilbm)
    {
    if(ilbm->ParseInfo.iff) 	FreeIFF(ilbm->ParseInfo.iff);
    FreeMem(ilbm,sizeof(struct ILBMInfo));
    }

   if(GfxBase) 	     	CloseLibrary(GfxBase);
   if(IntuitionBase) 	CloseLibrary(IntuitionBase);
   if(IFFParseBase)  	CloseLibrary(IFFParseBase);
   }


Devices/apps/ScreenSave/ScreenSave.c

/* ScreenSave
 * Saves front screen as an ILBM
 * Requires linkage with several iffparse modiules - See Makefile
 */

#include "iffp/ilbmapp.h"

#include <intuition/intuitionbase.h>
#include <workbench/workbench.h>

#include <clib/icon_protos.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

char *vers = "\0$VER: screensave 37.5";
char *Copyright =
  "screensave v37.5 - supports new modes - Freely Redistributable";
char *usage =
 "Usage: screensave filename (filename -c[unit] for clipboard)\n"
 "Options: QUIET, NODELAY, NOICON, SEQUENCE (sequence adds a number to name)\n"
 "Saves front screen after 10-sec delay (unless NODELAY).\n";

int mygets(char *s);
void bye(UBYTE *s,int e);
void cleanup(void);

struct Library	*IntuitionBase = NULL;
struct Library	*GfxBase = NULL;
struct Library	*IconBase = NULL;
struct Library	*IFFParseBase = NULL;

struct ILBMInfo ilbm = {0};

BOOL fromWB, Quiet, NoDelay, NoIcon, Sequence;

#define INBUFSZ 128
char nbuf[INBUFSZ];

/* Data for project icon for saved ILBM
 *
 */
UWORD ILBMI1Data[] =
{
/* Plane 0 */
    0x0000,0x0000,0x0000,0x0001,0x0000,0x0000,0x0000,0x0003,
    0x0FFF,0xFFFF,0xFFFF,0xFFF3,0x0FFF,0x0000,0x0000,0xFFF3,
    0x0FFC,0x0000,0x0000,0x3FF3,0x0FE0,0x0E80,0xF800,0x07F3,
    0x0F80,0x1C01,0x8C00,0x01F3,0x0F00,0x0001,0x8C00,0x00F3,
    0x0600,0x0000,0x0600,0x0063,0x0600,0x0003,0xBC00,0x0063,
    0x0600,0x0001,0xFC00,0x0063,0x0600,0x0000,0xFC00,0x0063,
    0x0600,0x1FC1,0xFE40,0x0063,0x0600,0x1DC1,0xFE20,0x0063,
    0x0600,0x1CE3,0xFF12,0x0063,0x0F00,0x1CE0,0x004F,0xC0F3,
    0x0F80,0x1CE0,0x002F,0x01F3,0x0FE0,0x0E78,0x423D,0x07F3,
    0x0FFC,0x0000,0x0000,0x3FF3,0x0FFF,0x0000,0x0000,0xFFF3,
    0x0FFF,0xFFFF,0xFFFF,0xFFF3,0x0000,0x0000,0x0000,0x0003,
    0x7FFF,0xFFFF,0xFFFF,0xFFFF,
/* Plane 1 */
    0xFFFF,0xFFFF,0xFFFF,0xFFFE,0xD555,0x5555,0x5555,0x5554,
    0xD000,0x0000,0x0000,0x0004,0xD3FC,0xFFFF,0xFFFF,0x3FC4,
    0xD3C0,0x0000,0x0000,0x03C4,0xD300,0x0100,0xF800,0x00C4,
    0xD300,0x0381,0xFC00,0x00C4,0xD080,0x0701,0xFC00,0x0104,
    0xD180,0xF883,0xFE00,0x0194,0xD181,0xDF80,0x4700,0x0194,
    0xD181,0xDF82,0x0180,0x0194,0xD180,0x6F82,0x00C0,0x0194,
    0xD180,0x0002,0x0020,0x0194,0xD180,0x0000,0x0000,0x0194,
    0xD180,0x0000,0x0002,0x0194,0xD080,0x0000,0xCC46,0xC104,
    0xD300,0x0000,0xCC2F,0x00C4,0xD300,0x0E78,0x883D,0x00C4,
    0xD3C0,0x0000,0x0000,0x03C4,0xD3FC,0xFFFF,0xFFFF,0x3FC4,
    0xD000,0x0000,0x0000,0x0004,0xD555,0x5555,0x5555,0x5554,
    0x8000,0x0000,0x0000,0x0000,
};

struct Image ILBMI1 =
{
    0, 0,			/* Upper left corner */
    64, 23, 2,			/* Width, Height, Depth */
    ILBMI1Data,			/* Image data */
    0x0003, 0x0000,		/* PlanePick, PlaneOnOff */
    NULL			/* Next image */
};

UBYTE *ILBMTools[] =
{
    "FILETYPE=ILBM",
    NULL
};

struct DiskObject ILBMobject =
{
    WB_DISKMAGIC,		/* Magic Number */
    WB_DISKVERSION,		/* Version */
    {				/* Embedded Gadget Structure */
    NULL,			/* Next Gadget Pointer */
    0, 0, 64, 24,		/* Left,Top,Width,Height */
    GADGIMAGE | GADGBACKFILL,	/* Flags */
    RELVERIFY | GADGIMMEDIATE,		/* Activation Flags */
    BOOLGADGET,		/* Gadget Type */
    (APTR)&ILBMI1,	/* Render Image */
    NULL,			/* Select Image */
    NULL,			/* Gadget Text */
    NULL,			/* Mutual Exclude */
    NULL,			/* Special Info */
    0,			/* Gadget ID */
    NULL,			/* User Data */
    },
    WBPROJECT,			/* Icon Type */
    "Display",			/* Default Tool */
    ILBMTools,			/* Tool Type Array */
    NO_ICON_POSITION,		/* Current X */
    NO_ICON_POSITION,		/* Current Y */
    NULL,			/* Drawer Structure */
    NULL,			/* Tool Window */
    0				/* Stack Size */
};

void main(int argc, char **argv)
   {
   struct Screen   *frontScreen;
   LONG		error = 0L, seqlock;
   char         *filename;
   int l, k;

   fromWB = (argc==0) ? TRUE : FALSE;

   if(!(IntuitionBase = OpenLibrary("intuition.library", 0)))
      bye("Can't open intuition library.\n",RETURN_WARN);

   if(!(GfxBase = OpenLibrary("graphics.library",0)))
      bye("Can't open graphics library.\n",RETURN_WARN);

   if(!(IFFParseBase = OpenLibrary("iffparse.library",0)))
      bye("Can't open iffparse library.\n",RETURN_WARN);

   if(!(IconBase = OpenLibrary("icon.library",0)))
      bye("Can't open icon library.\n",RETURN_WARN);

   if(!(ilbm.ParseInfo.iff = AllocIFF()))
      bye(IFFerr(IFFERR_NOMEM),RETURN_WARN);

   if(argc>1)                 /* Passed filename via command line  */
      {
      if(argv[1][0]=='?')
        {
        printf("%s\n%s\n",Copyright,usage);
        bye("\n",RETURN_OK);
        }
      else filename = argv[1];

      NoDelay = NoIcon = Quiet = Sequence = FALSE;
      for(k=2; k < (argc); k++)
    {
    if(!(stricmp(argv[k],"NODELAY")))	NoDelay  = TRUE;
    else if(!(stricmp(argv[k],"NOICON")))	NoIcon   = TRUE;
    else if(!(stricmp(argv[k],"QUIET")))	Quiet    = TRUE;
    else if(!(stricmp(argv[k],"SEQUENCE")))	Sequence = TRUE;
    }
      if(Sequence)
    {
    for(k=1; k<9999; k++)
        {
        sprintf(nbuf,"%s%04ld",filename,k);
        if(seqlock = Lock(nbuf,ACCESS_READ))	UnLock(seqlock);
        else break;
        }
    filename = nbuf;
    }
      }
   else
      {
      printf("%s\n%s\n",Copyright,usage);
      printf("Enter filename for save: ");
      l = mygets(&nbuf[0]);

      if(l==0)                /* No filename - Exit */
         {
         bye("\nScreen not saved, filename required\n",RETURN_FAIL);
         }
      else
         {
         filename = &nbuf[0];
         }
      }

   if(!NoDelay)	Delay(500);

   Forbid();
   frontScreen  = ((struct IntuitionBase *)IntuitionBase)->FirstScreen;
   Permit();

   if(error = screensave(&ilbm, frontScreen,
                NULL, NULL,
                filename))
    {
    printf("%s\n",IFFerr(error));
    }
   else
    {
          if(!Quiet) printf("Screen saved as %s... ",filename);
    if((!NoIcon)&&(filename[0]!='-')&&(filename[1]!='c')) /* not clipboard */
        {
              if(!(PutDiskObject(filename,&ILBMobject)))
                {
                bye("Error saving icon\n",RETURN_WARN);
                }
           if(!Quiet) printf("Icon saved\n");
        }
    else if(!Quiet) printf("\n");
          bye("",RETURN_OK);
          }
    }

void bye(UBYTE *s,int e)
   {
   if(s&&(*s)) printf("%s\n",s);
   if ((fromWB)&&(*s))    /* Wait so user can read messages */
      {
      printf("\nPRESS RETURN TO EXIT\n");
      mygets(&nbuf[0]);
      }
   cleanup();
   exit(e);
   }

void cleanup()
   {
   if(ilbm.ParseInfo.iff)	FreeIFF(ilbm.ParseInfo.iff);

   if(GfxBase)		CloseLibrary(GfxBase);
   if(IntuitionBase)	CloseLibrary(IntuitionBase);
   if(IconBase)		CloseLibrary(IconBase);
   if(IFFParseBase)	CloseLibrary(IFFParseBase);
   }

int mygets(char *s)
   {
   int l = 0, max = INBUFSZ - 1;

   while (((*s = getchar()) !='\n' )&&(l < max)) s++, l++;
   *s = NULL;
   return(l);
   }


Devices/other/cycvb.c

/*
 * cycvb.c --- Dan Silva's DPaint color cycling interrupt code
 *
 *    Use this fragment as an example for interrupt driven color cycling
 *    If compiled with SAS, include flags -v -y on LC2
 */

#include <exec/types.h>
#include <exec/interrupts.h>
#include <graphics/view.h>
#include <iff/compiler.h>

#define MAXNCYCS 4
#define NO  FALSE
#define YES TRUE
#define LOCAL static

typedef struct {
    SHORT count;
    SHORT rate;
    SHORT flags;
    UBYTE low, high;  /* bounds of range */
    } Range;

/* Range flags values */
#define RNG_ACTIVE  1
#define RNG_REVERSE 2
#define RNG_NORATE 36  /* if rate == NORATE, don't cycle */

/* cycling frame rates */
#define OnePerTick   16384
#define OnePerSec    OnePerTick/60

extern Range  cycles[];
extern BOOL   cycling[];
extern WORD   cycols[];
extern struct ViewPort *vport;
extern SHORT  nColors;

MyVBlank()  {
   int i,j;
   LOCAL  Range *cyc;
   LOCAL  WORD  temp;
   LOCAL  BOOL  anyChange;

#ifdef IS_AZTEC
#asm
       movem.l  a2-a7/d2-d7,-(sp)
       move.l   a1,a4
#endasm
#endif

   if (cycling)  {
      anyChange = NO;
      for (i=0; i<MAXNCYCS; i++)  {
         cyc = &cycles[i];
         if ( (cyc->low == cyc->high) ||
              ((cyc->flags&RNG_ACTIVE) == 0) ||
              (cyc->rate == RNG_NORATE) )
                 continue;

         cyc->count += cyc->rate;
         if (cyc->count >= OnePerTick)  {
            anyChange = YES;
            cyc->count -= OnePerTick;

            if (cyc->flags&RNG_REVERSE)  {
               temp = cycols[cyc->low];
               for (j=cyc->low; j < cyc->high; j++)
                  cycols[j] = cycols[j+1];
               cycols[cyc->low] = temp;
               }
            else  {
               temp = cycols[cyc->high];
               for (j=cyc->high; j > cyc->low; j--)
                  cycols[j] = cycols[j-1];
               cycols[cyc->low] = temp;
               }
            }
         }
      if (anyChange) LoadRGB4(vport,cycols,nColors);
      }

#ifdef IS_AZTEC
      ;   /* this is necessary */
#asm
      movem.l  (sp)+,a2-a7/d2-d7
#endasm
#endif

   return(0);  /* interrupt routines have to do this */
   }

/*
 *  Code to install/remove cycling interrupt handler
 */

LOCAL char myname[] = "MyVB";  /* Name of interrupt handler */
LOCAL struct Interrupt intServ;

typedef void (*VoidFunc)();

StartVBlank()  {
#ifdef IS_AZTEC
   intServ.is_Data = GETAZTEC();  /* returns contents of register a4 */
#else
   intServ.is_Data = NULL;
#endif
   intServ.is_Code = (VoidFunc)&MyVBlank;
   intServ.is_Node.ln_Succ = NULL;
   intServ.is_Node.ln_Pred = NULL;
   intServ.is_Node.ln_Type = NT_INTERRUPT;
   intServ.is_Node.ln_Pri  = 0;
   intServ.is_Node.ln_Name = myname;
   AddIntServer(5,&intServ);
   }

StopVBlank() { RemIntServer(5,&intServ); }

/**/


Devices/apps/ILBMtoC/ILBMtoC.c

/*--------------------------------------------------------------*/
/*								*/
/* ILBMtoC: reads in ILBM, prints out ascii representation, 	*/
/*  for including in C files. 					*/
/*                                                              */
/* Based on ILBMDump.c by Jerry Morrison and Steve Shaw,	*/
/* Electronic Arts.           					*/
/* Jan 31, 1986							*/
/*                                                              */
/* This software is in the public domain.                       */
/* This version for the Amiga computer.                         */
/*                                                              */
/*  Callable from CLI ONLY					*/
/*  modified 05-91 for use wuth iffparse modules		*/
/*  Requires linkage with several other modules - see Makefile  */
/*--------------------------------------------------------------*/

#include "iffp/ilbmapp.h"

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

char *vers = "\0$VER: ILBMtoC 37.5";
char *Copyright = "ILBMtoC v37.5 (Freely Redistributable)";

void GetSuffix(UBYTE *to, UBYTE *fr);
void bye(UBYTE *s, int e);
void cleanup(void);

struct Library *IFFParseBase = NULL;
struct Library *GfxBase = NULL;

/* ILBM frame */
struct ILBMInfo ilbm = {0};

/* ILBM Property chunks to be grabbed - only BMHD needed for this app
 */
LONG	ilbmprops[] = {
        ID_ILBM, ID_BMHD,
        TAG_DONE
        };

/* ILBM Collection chunks (more than one in file) to be gathered */
LONG	*ilbmcollects = NULL;	/* none needed for this app */

/* ILBM Chunk to stop on */
LONG	ilbmstops[] = {
        ID_ILBM, ID_BODY,
        TAG_DONE
        };

UBYTE defSwitch[] = "b";

/** main() ******************************************************************/

void main(int argc, char **argv)
    {
    UBYTE *sw;
    FILE *fp;
    LONG error=NULL;
    UBYTE *ilbmname, name[80], fname[80];

    if ((argc < 2)||(argv[argc-1][0]=='?'))
    {
    printf("Usage from CLI: 'ILBMtoC filename switch-string'\n");
    printf(" where switch-string = \n");
    printf("  <nothing> : Bob format (default)\n");
    printf("  s         : Sprite format (with header and trailer words)\n");
    printf("  sn        : Sprite format (No header and trailer words)\n");
    printf("  a         : Attached sprite (with header and trailer)\n");
    printf("  an        : Attached sprite (No header and trailer)\n");
    printf(" Add 'c' to switch list to output CR's with LF's   \n");
    exit(RETURN_OK);
    }

    if(!(GfxBase = OpenLibrary("graphics.library",0)))
    bye("Can't open graphics.library",RETURN_FAIL);

    if(!(IFFParseBase = OpenLibrary("iffparse.library",0)))
    bye("Can't open iffparse.library",RETURN_FAIL);

/*
 * Here we set up default ILBMInfo fields for our
 * application's frames.
 * Above we have defined the propery and collection chunks
 * we are interested in (some required like BMHD)
 */
    ilbm.ParseInfo.propchks      = ilbmprops;
    ilbm.ParseInfo.collectchks   = ilbmcollects;
    ilbm.ParseInfo.stopchks      = ilbmstops;
    if(!(ilbm.ParseInfo.iff = AllocIFF()))
        bye(IFFerr(IFFERR_NOMEM),RETURN_FAIL);	/* Alloc an IFFHandle */

    sw = (argc>2) ? (UBYTE *)argv[2] : defSwitch;
    ilbmname = argv[1];

    if (error = loadbrush(&ilbm,ilbmname))
        {
        printf("Can't load ilbm \"%s\", ifferr=%s\n",ilbmname,IFFerr(error));
        bye("",RETURN_WARN);
        }
    else /* Successfully loaded ILBM */
    {
    printf(" Creating file %s.c \n",argv[1]);
    GetSuffix(name,argv[1]);
    strcpy(fname,argv[1]);
    strcat(fname,".c");
    fp = fopen(fname,"w");
    if(fp)
        {
        BMPrintCRep(ilbm.brbitmap,fp,name,sw);
        fclose(fp);
        }
    else  printf("Couldn't open output file: %s. \n", fname);
    unloadbrush(&ilbm);
    }
    printf("\n");
    bye("",RETURN_OK);
    }

/* this copies part of string after the last '/' or ':' */
void GetSuffix(to, fr) UBYTE *to, *fr; {
    int i;
    UBYTE c,*s = fr;
    for (i=0; ;i++) {
    c = *s++;
    if (c == 0) break;
    if (c == '/') fr = s;
    else if (c == ':') fr = s;
    }
    strcpy(to,fr);
    }

void bye(UBYTE *s, int e)
    {
    if(s&&(*s))	printf("%s\n",s);
    cleanup();
    exit(e);
    }

void cleanup()
    {
    if(ilbm.ParseInfo.iff)		FreeIFF(ilbm.ParseInfo.iff);

    if(IFFParseBase)	CloseLibrary(IFFParseBase);
    if(GfxBase)		CloseLibrary(GfxBase);
    }


Devices/modules/bmprintc.c

/*--------------------------------------------------------------*/
/*								*/
/*			bmprintc.c				*/
/*								*/
/* print out a C-language representation of data for bitmap	*/
/*								*/
/* By Jerry Morrison and Steve Shaw, Electronic Arts.		*/
/* This software is in the public domain.			*/
/*								*/
/* This version for the Amiga computer.				*/
/* Cleaned up and modified a bit by Chuck McManis, Aug 1988	*/
/* Modified 05/91 by CBM for use with iffparse modules          */
/*								*/
/*--------------------------------------------------------------*/

#include "iffp/ilbmapp.h"
#include <stdio.h>

#define NO  0
#define YES 1

void PSprite(struct BitMap *bm, FILE *fp, UBYTE *name, int p, BOOL dohead);
void PrCRLF(FILE *fp);
void PrintBob(struct BitMap *bm, FILE *fp, UBYTE *name);
void PrintSprite(struct BitMap *bm, FILE *fp, UBYTE *name,
         BOOL attach, BOOL dohdr);

static BOOL doCRLF;
char sp_colors[] = ".oO@";

void PrCRLF(FILE *fp)
{
    if (doCRLF)
        fprintf(fp, "%c%c", 0xD, 0xA);
    else
        fprintf(fp, "\n");
}

void PrintBob(struct BitMap *bm, FILE *fp, UBYTE *name)
{
    register UWORD 	*wp;	/* Pointer to the bitmap data */

    short 	p,i,j,nb;	/* temporaries */
    short 	nwords = (bm->BytesPerRow/2)*bm->Rows;

    fprintf(fp, "/*----- bitmap : w = %ld, h = %ld ------ */",
            bm->BytesPerRow*8, bm->Rows);

    PrCRLF(fp);

    for (p = 0; p < bm->Depth; ++p) {	/* For each bit plane */
        wp = (UWORD *)bm->Planes[p];
        fprintf(fp, "/*------ plane # %ld: --------*/", p);
        PrCRLF(fp);
        fprintf(fp, "UWORD %s%c[%ld] = { ", name, (p?('0'+p):' '), nwords);
        PrCRLF(fp);
        for (j = 0; j < bm->Rows; j++, wp += (bm->BytesPerRow >> 1)) {
            fprintf(fp, "	");
            for (nb = 0; nb < (bm->BytesPerRow) >> 1; nb++)
                fprintf(fp, "0x%04x,", *(wp+nb));
            if (bm->BytesPerRow <= 6) {
                 fprintf(fp, "\t/* ");
                for (nb = 0; nb < (bm->BytesPerRow) >> 1; nb++)
                    for (i=0 ; i<16; i++)
                        fprintf(fp, "%c",
                        (((*(wp+nb)>>(15-i))&1) ? '*' : '.'));
                fprintf(fp, " */");
            }
            PrCRLF(fp);

        }
        fprintf(fp,"	};");
        PrCRLF(fp);
    }
}

void PSprite(struct BitMap *bm, FILE *fp, UBYTE *name, int p, BOOL dohead)
{
    UWORD 	*wp0, *wp1;	/* Pointer temporaries 	*/
    short 	i, j, nwords,	/* Counter temporaries 	*/
        color;		/* pixel color		*/
    short 	wplen = bm->BytesPerRow/2;

    nwords =  2*bm->Rows + (dohead?4:0);
    wp0 = (UWORD *)bm->Planes[p];
    wp1 = (UWORD *)bm->Planes[p+1];

    fprintf(fp, "UWORD %s[%ld] = {", name, nwords);
    PrCRLF(fp);

    if (dohead) {
        fprintf(fp,"  0x0000, 0x0000, /* VStart, VStop */");
        PrCRLF(fp);
    }
    for (j=0 ; j < bm->Rows; j++) {
        fprintf(fp, "  0x%04x, 0x%04x", *wp0, *wp1);
        if (dohead || (j != bm->Rows-1)) {
            fprintf(fp, ",");
        }
        fprintf(fp, "\t/*  ");
        for (i = 0; i < 16; i++) {
            color = ((*wp1 >> (14-i)) & 2) + ((*wp0 >> (15-i)) & 1);
            fprintf(fp, "%c", sp_colors[color]);
        }
        fprintf(fp,"  */");
        PrCRLF(fp);
        wp0 += wplen;
        wp1 += wplen;
    }
    if (dohead)
        fprintf(fp, "  0x0000, 0x0000 }; /* End of Sprite */");
    else
        fprintf(fp," };");
    PrCRLF(fp);
    PrCRLF(fp);
}

void PrintSprite(struct BitMap *bm, FILE *fp, UBYTE *name,
         BOOL attach, BOOL dohdr)
{
    fprintf(fp,"/*----- Sprite format: h = %ld ------ */", bm->Rows);
    PrCRLF(fp);

    if (bm->Depth > 1) {
        fprintf(fp, "/*--Sprite containing lower order two planes:   */");
        PrCRLF(fp);
        PSprite(bm, fp, name, 0, dohdr);
    }
    if (attach && (bm->Depth > 3) ) {
        strcat(name, "1");
        fprintf(fp, "/*--Sprite containing higher order two planes:   */");
        PrCRLF(fp);
        PSprite(bm, fp, name, 2, dohdr);
    }
}

#define BOB 	0
#define SPRITE 	1

/* BMPrintCRep
 * Passed pointer to BitMap structure, C filehandle opened for write,
 * name associated with file, and string describing the output
 * format desired (see cases below), outputs C representation of the ILBM.
 */
void BMPrintCRep(struct BitMap *bm, FILE *fp, UBYTE *name, UBYTE *fmt)
{
    BOOL attach, doHdr;
    char c;
    SHORT type;

    doCRLF = NO;
    doHdr = YES;
    type = BOB;
    attach = NO;
    while ( (c=*fmt++) != 0 )
        switch (c) {
            case 'b':
                type = BOB;
                break;
            case 's':
                type = SPRITE;
                attach = NO;
                break;
            case 'a':
                type = SPRITE;
                attach = YES;
                break;
            case 'n':
                doHdr = NO;
                break;
            case 'c':
                doCRLF = YES;
                break;
        }
    switch(type) {
        case BOB:
            PrintBob(bm, fp, name);
            break;
        case SPRITE:
            PrintSprite(bm, fp, name, attach, doHdr);
            break;
    }
}


Devices/modules/ilbmw.c

/*----------------------------------------------------------------------*
 * ILBMW.C  Support routines for writing ILBM files using IFFParse.
 * (IFF is Interchange Format File.)
 *
 * Based on code by Jerry Morrison and Steve Shaw, Electronic Arts.
 * This software is in the public domain.
 *
 * This version for the Amiga computer.
 *----------------------------------------------------------------------*/

#include "iffp/ilbm.h"
#include "iffp/packer.h"

#include <graphics/gfxbase.h>

extern struct Library *GfxBase;

/*---------- initbmhd -------------------------------------------------*/
long initbmhd(BitMapHeader *bmhd, struct BitMap *bitmap,
          WORD masking, WORD compression, WORD transparentColor,
          WORD width, WORD height, WORD pageWidth, WORD pageHeight,
          ULONG modeid)
    {
    extern struct Library *GfxBase;
    struct DisplayInfo DI;

    WORD rowBytes = bitmap->BytesPerRow;

    D(bug("In InitBMHD\n"));

    bmhd->w = width;
    bmhd->h = height;
    bmhd->x = bmhd->y = 0;	/* Default position is (0,0).*/
    bmhd->nPlanes = bitmap->Depth;
    bmhd->masking = masking;
    bmhd->compression = compression;
    bmhd->reserved1 = 0;
    bmhd->transparentColor = transparentColor;
    bmhd->pageWidth = pageWidth;
    bmhd->pageHeight = pageHeight;

    bmhd->xAspect = 0;	/* So we can tell when we've got it */
    if(GfxBase->lib_Version >=36)
    {
       if(GetDisplayInfoData(NULL, (UBYTE *)&DI,
        sizeof(struct DisplayInfo), DTAG_DISP, modeid))
        {
            bmhd->xAspect =  DI.Resolution.x;
            bmhd->yAspect =  DI.Resolution.y;
        }
    }

    /* If running under 1.3 or GetDisplayInfoData failed, use old method
     * of guessing aspect ratio
     */
    if(! bmhd->xAspect)
    {
        bmhd->xAspect =  44;
        bmhd->yAspect =
        ((struct GfxBase *)GfxBase)->DisplayFlags & PAL ? 44 : 52;
        if(modeid & HIRES)	bmhd->xAspect = bmhd->xAspect >> 1;
        if(modeid & LACE)	bmhd->yAspect = bmhd->yAspect >> 1;
    }

    return( IS_ODD(rowBytes) ? CLIENT_ERROR : IFF_OKAY );
    }

/*---------- putcmap ---------------------------------------------------*/
/* This function will accept a table of color values in one of the
 * following forms:
 *  if bitspergun=4,  colortable is words, each with nibbles 0RGB
 *  if bitspergun=8,  colortable is bytes of RGBRGB etc. (like a CMAP)
 *  if bitspergun=32, colortable is ULONGS of RGBRGB etc.
 *     (only the high eight bits of each gun will be written to CMAP)
 */
long putcmap(struct IFFHandle *iff, APTR colortable,
         UWORD ncolors, UWORD bitspergun)
   {
   long error, offs;
   WORD  *tabw;
   UBYTE *tab8;
   ColorRegister cmapReg;

   D(bug("In PutCMAP\n"));

   if((!iff)||(!colortable))	return(CLIENT_ERROR);

   /* size of CMAP is 3 bytes * ncolors */
   if(error = PushChunk(iff, NULL, ID_CMAP, ncolors * sizeofColorRegister))
    return(error);

   D(bug("Pushed ID_CMAP, error = %ld\n",error));

   if(bitspergun == 4)
    {
       /* Store each 4-bit value n as nn */
    tabw = (UWORD *)colortable;
       for( ;  ncolors;  --ncolors )
        {
              cmapReg.red    = ( *tabw >> 4 ) & 0xf0;
              cmapReg.red   |= (cmapReg.red >> 4);

              cmapReg.green  = ( *tabw      ) & 0xf0;
              cmapReg.green |= (cmapReg.green >> 4);

              cmapReg.blue   = ( *tabw << 4 ) & 0xf0;
              cmapReg.blue  |= (cmapReg.blue >> 4);

              if((WriteChunkBytes(iff, (BYTE *)&cmapReg, sizeofColorRegister))
                != sizeofColorRegister)
                        return(IFFERR_WRITE);
              ++tabw;
              }
    }
   else if((bitspergun == 8)||(bitspergun == 32))
    {
    tab8 = (UBYTE *)colortable;
    offs = (bitspergun == 8) ? 1 : 4;
       for( ;  ncolors;  --ncolors )
        {
        cmapReg.red   = *tab8;
        tab8 += offs;
        cmapReg.green = *tab8;
        tab8 += offs;
        cmapReg.blue  = *tab8;
        tab8 += offs;
              if((WriteChunkBytes(iff, (BYTE *)&cmapReg, sizeofColorRegister))
                != sizeofColorRegister)
                        return(IFFERR_WRITE);
        }
    }
   else (error = CLIENT_ERROR)

   D(bug("Wrote registers, error = %ld\n",error));

   error = PopChunk(iff);
   return(error);
   }

/*---------- putbody ---------------------------------------------------*/
/* NOTE: This implementation could be a LOT faster if it used more of the
 * supplied buffer. It would make far fewer calls to IFFWriteBytes (and
 * therefore to DOS Write). */
long putbody(struct IFFHandle *iff, struct BitMap *bitmap, BYTE *mask,
         BitMapHeader *bmhd, BYTE *buffer, LONG bufsize)
   {
   long error;
   LONG rowBytes = bitmap->BytesPerRow;
   int dstDepth = bmhd->nPlanes;
   UBYTE compression = bmhd->compression;
   int planeCnt;		/* number of bit planes including mask */
   register int iPlane, iRow;
   register LONG packedRowBytes;
   BYTE *buf;
   BYTE *planes[MAXSAVEDEPTH + 1]; /* array of ptrs to planes & mask */

   D(bug("In PutBODY\n"));

   if ( bufsize < MaxPackedSize(rowBytes)  ||	/* Must buffer a comprsd row*/
        compression > cmpByteRun1  ||		/* bad arg */
    bitmap->Rows != bmhd->h   ||		/* inconsistent */
    rowBytes != RowBytes(bmhd->w)  ||	/* inconsistent*/
    bitmap->Depth < dstDepth   ||		/* inconsistent */
    dstDepth > MAXSAVEDEPTH )		/* too many for this routine*/
      return(CLIENT_ERROR);

   planeCnt = dstDepth + (mask == NULL ? 0 : 1);

   /* Copy the ptrs to bit & mask planes into local array "planes" */
   for (iPlane = 0; iPlane < dstDepth; iPlane++)
      planes[iPlane] = (BYTE *)bitmap->Planes[iPlane];
   if (mask != NULL)
      planes[dstDepth] = mask;

   /* Write out a BODY chunk header */
   if(error = PushChunk(iff, NULL, ID_BODY, IFFSIZE_UNKNOWN)) return(error);

   /* Write out the BODY contents */
   for (iRow = bmhd->h; iRow > 0; iRow--)  {
      for (iPlane = 0; iPlane < planeCnt; iPlane++)  {

         /* Write next row.*/
         if (compression == cmpNone) {
        if(WriteChunkBytes(iff,planes[iPlane],rowBytes) != rowBytes)
        error = IFFERR_WRITE;
            planes[iPlane] += rowBytes;
            }

         /* Compress and write next row.*/
         else {
            buf = buffer;
            packedRowBytes = packrow(&planes[iPlane], &buf, rowBytes);
        if(WriteChunkBytes(iff,buffer,packedRowBytes) != packedRowBytes)
        error = IFFERR_WRITE;
            }

         if(error)	return(error);
         }
      }

   /* Finish the chunk */
   error = PopChunk(iff);
   return(error);
   }


Devices/other/ilbmscan.c

;/* ilbmscan.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -j73 ilbmscan.c
Blink FROM LIB:c.o,ilbmscan.o TO ilbmscan LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit

*
* ilbmscan.c:	Prints the size, aspect, mode, etc. of ILBM's
*		Scans through an IFF file for all ILBM's
*
* Usage: ilbmscan -c		; For clipboard scanning
*    or  ilbmscan <file>	; For DOS file scanning
*
* Based on sift.c by by Stuart Ferguson and Leo Schwab
*/

#include <exec/types.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <libraries/iffparse.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/iffparse_protos.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

/*  The structure of a FORM ILBM 'BMHD' and 'CAMG' chunks
 *  Such structures are defined in the spec for a FORM
 *  and may also be provided in include files
 */
/*  Bitmap header (BMHD) structure  */
typedef struct {
        UWORD   w, h;           /*  Width, height in pixels */
        WORD    x, y;           /*  x, y position for this bitmap  */
        UBYTE   nplanes;        /*  # of planes  */
        UBYTE   Masking;
        UBYTE   Compression;
        UBYTE   pad1;
        UWORD   TransparentColor;
        UBYTE   XAspect, YAspect;
        WORD    PageWidth, PageHeight;
} BitMapHeader;

/* Commodore Amiga (CAMG) Viewmodes structure */
typedef struct {
   ULONG ViewModes;
   } CamgChunk;

#define ID_ILBM         MAKE_ID('I','L','B','M')
#define ID_BMHD         MAKE_ID('B','M','H','D')
#define ID_CMAP         MAKE_ID('C','M','A','P')
#define ID_CAMG         MAKE_ID('C','A','M','G')
#define ID_BODY         MAKE_ID('B','O','D','Y')

void PrintILBMInfo(struct IFFHandle *);

#define MINARGS 2

/* 2.0 Version string for c:Version to find */
UBYTE vers[] = "\0$VER: ilbmscan 37.3";

UBYTE usage[] = "Usage: ilbmscan IFFfilename (or -c for clipboard)";

/*
 * Text error messages for possible IFFERR_#? returns from various
 * IFF routines.  To get the index into this array, take your IFFERR code,
 * negate it, and subtract one.
 *  idx = -error - 1;
 */
char	*errormsgs[] = {
    "End of file (not an error).",
    "End of context (not an error).",
    "No lexical scope.",
    "Insufficient memory.",
    "Stream read error.",
    "Stream write error.",
    "Stream seek error.",
    "File is corrupt.",
    "IFF syntax error.",
    "Not an IFF file.",
    "Required call-back hook missing.",
    "Return to client.  You should never see this."
};

struct Library *IFFParseBase;

void main(int argc, char **argv)
{
    struct IFFHandle	*iff = NULL;
    long		error;
    short		cbio;

        /* if not enough args or '?', print usage */
        if(((argc)&&(argc<MINARGS))||(argv[argc-1][0]=='?'))
        {
            printf("%s\n",usage);
            exit(RETURN_OK);
            }

    /*
     * Check to see if we are doing I/O to the Clipboard.
     */
    cbio = (argv[1][0] == '-'  &&  argv[1][1] == 'c');

    if (!(IFFParseBase = OpenLibrary ("iffparse.library", 0L)))
        {
        printf("Can't open iff parsing library.");
        goto bye;
        }

    /*
     * Allocate IFF_File structure.
     */
    if (!(iff = AllocIFF ()))
        {
        printf ("AllocIFF() failed.");
        goto bye;
        }

    /*
     * Internal support is provided for both AmigaDOS files, and the
     * clipboard.device.  This bizarre 'if' statement performs the
     * appropriate machinations for each case.
     */
    if (cbio)
        {
        /*
         * Set up IFF_File for Clipboard I/O.
         */
        if (!(iff->iff_Stream =
                (ULONG) OpenClipboard (PRIMARY_CLIP)))
            {
            printf("Clipboard open failed.");
            goto bye;
            }
        InitIFFasClip (iff);
        }
    else
        {
        /*
         * Set up IFF_File for AmigaDOS I/O.
         */
        if (!(iff->iff_Stream = Open (argv[1], MODE_OLDFILE)))
            {
            printf("File open failed.");
            goto bye;
            }
        InitIFFasDOS (iff);
        }

    /*
     * Start the IFF transaction.
     */
    if (error = OpenIFF (iff, IFFF_READ))
        {
        printf("OpenIFF failed.");
        goto bye;
        }

    /* We want to collect BMHD and CAMG */
    PropChunk(iff, ID_ILBM, ID_BMHD);
    PropChunk(iff, ID_ILBM, ID_CAMG);
    PropChunk(iff, ID_ILBM, ID_CMAP);

    /* Stop at the BODY */
    StopChunk(iff, ID_ILBM, ID_BODY);

    /* And let us know (IFFERR_EOC) when leaving a FORM ILBM */
    StopOnExit(iff,ID_ILBM, ID_FORM);

    /* Do the scan.
     * The while(1) will let us delve into more complex formats
     * to find FORM ILBM's
     */
    while (1)
        {
        error = ParseIFF(iff, IFFPARSE_SCAN);
        /*
         * Since we're only interested in when we enter a context,
         * we "discard" end-of-context (_EOC) events.
         */
        if (error == IFFERR_EOC)
            {
            printf("Exiting FORM ILBM\n\n");
            continue;
            }
        else if (error)
            /*
             * Leave the loop if there is any other error.
             */
            break;

        /*
         * If we get here, error was zero
         * Since we did IFFPARSE_SCAN, zero error should mean
         * we are at our Stop Chunk (BODY)
         */
        PrintILBMInfo(iff);
        }

    /*
     * If error was IFFERR_EOF, then the parser encountered the end of
     * the file without problems.  Otherwise, we print a diagnostic.
     */
    if (error == IFFERR_EOF)
        printf("File scan complete.\n");
    else
        printf("File scan aborted, error %ld: %s\n",
            error, errormsgs[-error - 1]);

bye:
    if (iff) {
        /*
         * Terminate the IFF transaction with the stream.  Free
         * all associated structures.
         */
        CloseIFF (iff);

        /*
         * Close the stream itself.
         */
        if (iff->iff_Stream)
            if (cbio)
                CloseClipboard ((struct ClipboardHandle *)
                        iff->iff_Stream);
            else
                Close (iff->iff_Stream);

        /*
         * Free the IFF_File structure itself.
         */
        FreeIFF (iff);
        }
    if (IFFParseBase)	CloseLibrary (IFFParseBase);

    exit (RETURN_OK);
}

void
PrintILBMInfo(iff)
struct IFFHandle *iff;
{
    struct StoredProperty	*sp;
    BitMapHeader 	*bmhd;
    CamgChunk	*camg;

    /*
     * Get a pointer to the stored propery BMHD
     */
    if (!(sp = FindProp(iff, ID_ILBM, ID_BMHD)))
        printf("No BMHD found\n");
    else
        {
        /* If property is BMHD, sp->sp_Data is ptr to data in BMHD */
        bmhd = (BitMapHeader *)sp->sp_Data;
        printf("BMHD: Width      = %ld\n",bmhd->w);
        printf("      Height     = %ld\n",bmhd->h);
        printf("      PageWidth  = %ld\n",bmhd->PageWidth);
        printf("      PageHeight = %ld\n",bmhd->PageHeight);
        printf("      nplanes    = %ld\n",bmhd->nplanes);
               printf("      Masking    = %ld\n",bmhd->Masking);
                printf("      Compression= %ld\n",bmhd->Compression);
        printf("      TransColor = %ld\n",bmhd->TransparentColor);
        printf("      X/Y Aspect = %ld/%ld\n",bmhd->XAspect,bmhd->YAspect);
        }

    /*
     * Get a pointer to the stored propery CMAP
     */
    if (!(sp = FindProp(iff, ID_ILBM, ID_CMAP)))
        printf("No CMAP found\n");
    else
        {
        /* If property is CMAP, sp->sp_Data is ptr to data in CMAP */
        printf("CMAP: contains RGB values for %ld registers\n",
                sp->sp_Size / 3);
        }

    /*
     * Get a pointer to the stored propery CAMG
     */
    if (!(sp = FindProp(iff, ID_ILBM, ID_CAMG)))
        printf("No CAMG found\n");
    else
        {
        /* If property is CAMG, sp->sp_Data is ptr to data in CAMG */
        camg = (CamgChunk *)sp->sp_Data;
        printf("CAMG: ModeID     = $%08lx\n\n",camg->ViewModes);
        }

}


Devices/apps/ILBMtoRaw/ILBMtoRaw.c

/*--------------------------------------------------------------*/
/*								*/
/* ILBMtoRaw: reads in ILBM, writes out raw file (raw planes, 	*/
/*  followed by colormap) 					*/
/*                                                              */
/* Based on ILBMRaw.c by Jerry Morrison and Steve Shaw,		*/
/* Electronic Arts.           					*/
/* Jan 31, 1986							*/
/*                                                              */
/* This software is in the public domain.                       */
/* This version for the Amiga computer.                         */
/*                                                              */
/*  Callable from CLI ONLY					*/
/*  modified 05-91 for use wuth iffparse modules		*/
/*  Requires linkage with several other modules - see Makefile  */
/*--------------------------------------------------------------*/

#include "iffp/ilbmapp.h"

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

char *vers = "\0$VER: ILBMtoRaw 37.5";
char *Copyright = "ILBMtoRaw v37.5 (Freely Redistributable)";

void bye(UBYTE *s, int e);
void cleanup(void);

LONG SaveBitMap(UBYTE *name, struct BitMap *bm, SHORT *cols, int ncols);

struct Library *IFFParseBase = NULL;
struct Library *GfxBase = NULL;

/* ILBM frame */
struct ILBMInfo ilbm = {0};

/* ILBM Property chunks to be grabbed - BMHD and CMAP needed for this app
 */
LONG	ilbmprops[] = {
        ID_ILBM, ID_BMHD,
        ID_ILBM, ID_CMAP,
        TAG_DONE
        };

/* ILBM Collection chunks (more than one in file) to be gathered */
LONG	*ilbmcollects = NULL;	/* none needed for this app */

/* ILBM Chunk to stop on */
LONG	ilbmstops[] = {
        ID_ILBM, ID_BODY,
        TAG_DONE
        };

/** main() ******************************************************************/

void main(int argc, char **argv)
    {
    LONG error=NULL;
    UBYTE *ilbmname, fname[80], buf[24];

    if ((argc < 2)||(argv[argc-1][0]=='?'))
    bye("Usage from CLI: 'ILBMtoRaw filename'\n",RETURN_OK);

    if(!(GfxBase = OpenLibrary("graphics.library",0)))
    bye("Can't open graphics.library",RETURN_FAIL);

    if(!(IFFParseBase = OpenLibrary("iffparse.library",0)))
    bye("Can't open iffparse.library",RETURN_FAIL);

/*
 * Here we set up default ILBMInfo fields for our
 * application's frames.
 * Above we have defined the propery and collection chunks
 * we are interested in (some required like BMHD)
 */
    ilbm.ParseInfo.propchks      = ilbmprops;
    ilbm.ParseInfo.collectchks   = ilbmcollects;
    ilbm.ParseInfo.stopchks      = ilbmstops;
    if(!(ilbm.ParseInfo.iff = AllocIFF()))
        bye(IFFerr(IFFERR_NOMEM),RETURN_FAIL);	/* Alloc an IFFHandle */

    ilbmname = argv[1];

    /* Load as a brush since we don't need to display it */
    if (error = loadbrush(&ilbm,ilbmname))
        {
        printf("Can't load ilbm \"%s\", ifferr=%s\n",ilbmname,IFFerr(error));
        bye("",RETURN_WARN);
        }
    else /* Successfully loaded ILBM */
    {
        strcpy(fname,argv[1]);

    if(ilbm.camg & HAM)	strcat(fname, ".ham");
    if(ilbm.camg & EXTRA_HALFBRITE)	strcat(fname, ".ehb");

    if(ilbm.camg & HIRES)	strcat(fname, ".hi");
    else strcat(fname, ".lo");

    if(ilbm.camg & LACE)	strcat(fname, ".lace");

    strcat(fname,".");
    sprintf(buf,"%d",ilbm.Bmhd.w);
    strcat(fname,buf);
    strcat(fname,"x");
    sprintf(buf,"%d",ilbm.Bmhd.h);
    strcat(fname,buf);
    strcat(fname,"x");
    sprintf(buf,"%d",ilbm.brbitmap->Depth);
    strcat(fname, buf);
    printf(" Creating file %s \n", fname);
    error=SaveBitMap(fname, ilbm.brbitmap, ilbm.colortable, ilbm.ncolors);

    unloadbrush(&ilbm);
    }

    if(error)	bye(IFFerr(error),RETURN_WARN);
    else	bye("",RETURN_OK);
    }

/* SaveBitMap (as raw planes and colortable)
 *
 * Given filename, bitmap structure, and colortable pointer,
 * writes out raw bitplanes and colortable (not an ILBM)
 * Returns 0 for success
 */

LONG SaveBitMap(UBYTE *name, struct BitMap *bm, SHORT *cols, int ncols)
    {
    SHORT i;
    LONG nb,plsize;

    LONG file = Open( name, MODE_NEWFILE);
    if( file == 0 )
    {
    printf(" couldn't open %s \n",name);
    return(CLIENT_ERROR);	/* couldnt open a load-file */
    }
    plsize = bm->BytesPerRow*bm->Rows;
    for (i=0; i<bm->Depth; i++)
    {
    nb =  Write(file, bm->Planes[i], plsize);
    if (nb<plsize) break;
    }
    if(nb>0)	nb=Write(file, cols, (1<<bm->Depth)*2);	/* save color map */
    Close(file);
    return(nb >= 0 ? 0L : IFFERR_WRITE);
    }

void bye(UBYTE *s, int e)
    {
    if(s&&(*s))	printf("%s\n",s);
    cleanup();
    exit(e);
    }

void cleanup()
    {
    if(ilbm.ParseInfo.iff)		FreeIFF(ilbm.ParseInfo.iff);

    if(IFFParseBase)	CloseLibrary(IFFParseBase);
    if(GfxBase)		CloseLibrary(GfxBase);
    }


Devices/modules/copychunks.c

/* copychunks
 *
 * For Read/Modify/Write programs and other programs that need
 *   to close the IFF file but still reference gathered chunks.
 * Copies your gathered property and collection chunks
 *   from an iff context so that IFF handle may be
 *   closed right after parsing (allowing file or clipboard to
 *   to be reopened for read or write by self or other programs)
 *
 * The created list of chunks can be modified and written
 *   back out to a new handle with writechunklist().
 *
 * If you have used copychunks(), remember to free the copied
 *   chunks with freechunklist(), when ready, to deallocate them.
 *
 * Note that this implementation is flat and is suitable only
 *   for simple FORMs.
 */

#include "iffp/iff.h"

/* copychunks()
 *
 * Copies chunks specified in propchks and collectchks
 *   FROM an already-parsed IFFHandle
 *   TO a singly linked list of Chunk structures,
 * and returns a pointer to the start of the list.
 *
 * Generally you would store this pointer in parseInfo.copiedchunks.
 *
 * You must later free the list of copied chunks by calling
 *   FreeChunkList().
 *
 * Reorders collection chunks so they appear in SAME ORDER
 * in chunk list as they did in the file.
 *
 * Returns 0 for failure
 */
struct Chunk *copychunks(struct IFFHandle *iff,
            LONG *propchks, LONG *collectchks,
            ULONG memtype)
    {
    struct Chunk *chunk, *first=NULL, *prevchunk = NULL;
    struct StoredProperty *sp;
    struct CollectionItem *ci, *cii;
    long error;
    int k, kk, bk;

    if(!iff)	return(NULL);

    /* Copy gathered property chunks */
    error = 0;
    for(k=0; (!error) && (propchks) && (propchks[k] != TAG_DONE); k+=2)
    {
    if(sp=FindProp(iff,propchks[k],propchks[k+1]))
        {
        D(bug("copying %.4s.%.4s chunk\n",&propchks[k],&propchks[k+1]));

        if(chunk=(struct Chunk *)
            AllocMem(sizeof(struct Chunk),memtype|MEMF_CLEAR))
        {
        chunk->ch_Type = propchks[k];
        chunk->ch_ID   = propchks[k+1];
        if(chunk->ch_Data = AllocMem(sp->sp_Size,memtype))
            {
            chunk->ch_Size = sp->sp_Size;
            CopyMem(sp->sp_Data,chunk->ch_Data,sp->sp_Size);
            if(prevchunk)	prevchunk->ch_Next = chunk;
            else 		first = chunk;
            prevchunk = chunk;
            }
        else
            {
            FreeMem(chunk,sizeof(struct Chunk));
            chunk=NULL;
            error = 1;
            }
        }
        else error = 1;
        }
    }

    /* Copy gathered collection chunks in reverse order */
    for(k=0; (!error) && (collectchks) && (collectchks[k] != TAG_DONE); k+=2)
    {
    if(ci=FindCollection(iff,collectchks[k],collectchks[k+1]))
        {
        D(bug("copying %.4s.%.4s collection\n",&collectchks[k],&collectchks[k+1]));
        for(cii=ci, bk=0; cii; cii=cii->ci_Next)	bk++;

        D(bug(" There are %ld of these, first is at $%lx\n",bk,ci));

        for( bk; bk; bk--)
        {
         for(kk=1, cii=ci; kk<bk; kk++) cii=cii->ci_Next;

        D(bug("  copying number %ld\n",kk));

            if(chunk=(struct Chunk *)
            AllocMem(sizeof(struct Chunk),memtype|MEMF_CLEAR))
            {
            chunk->ch_Type = collectchks[k];
            chunk->ch_ID   = collectchks[k+1];
            if(chunk->ch_Data = AllocMem(cii->ci_Size,memtype))
                {
                chunk->ch_Size = cii->ci_Size;
                CopyMem(cii->ci_Data,chunk->ch_Data,cii->ci_Size);
                if(prevchunk)	prevchunk->ch_Next = chunk;
                else 		first = chunk;
                prevchunk = chunk;
                }
            else
                {
                FreeMem(chunk,sizeof(struct Chunk));
                chunk=NULL;
                error = 1;
                }
            }
            else error = 1;
        }
        }
    }

    if(error)
    {
    if(first) freechunklist(first);
    first = NULL;
    }

    return(first);
    }

/* freechunklist - Free a dynamically allocated Chunk list and
 *   all of its ch_Data.
 *
 * Note - if a chunk's ch_Size is IFFSIZE_UNKNOWN, its ch_Data
 *   will not be deallocated.
 */
void freechunklist(struct Chunk *first)
    {
    struct Chunk *chunk, *next;

    chunk = first;
    while(chunk)
    {
    next = chunk->ch_Next;
    if((chunk->ch_Data)&&(chunk->ch_Size != IFFSIZE_UNKNOWN))
        FreeMem(chunk->ch_Data,chunk->ch_Size);
    FreeMem(chunk, sizeof(struct Chunk));
    chunk = next;
    }
    }

/* findchunk - find first matching chunk in list of struct Chunks
 *    example  finchunk(pi->copiedchunks,ID_ILBM,ID_CRNG);
 *
 * returns struct Chunk *, or NULL if none found
 */
struct Chunk *findchunk(struct Chunk *first, long type, long id)
    {
    struct Chunk *chunk;

    for(chunk=first; chunk; chunk=chunk->ch_Next)
    {
    if((chunk->ch_Type == type)&&(chunk->ch_ID == id)) return(chunk);
    }
    return(NULL);
    }

/* writechunklist - write out list of struct Chunk's
 * If data is a null terminated string, you may use
 * IFFSIZE_UNKNOWN as the ch_Szie and strlen(chunk->ch_Data)
 * will be used here as size.
 *
 * Returns 0 for success or an IFFERR
 */
long writechunklist(struct IFFHandle *iff, struct Chunk *first)
    {
    struct Chunk *chunk;
    long size, error = 0;

    D(bug("writechunklist: first chunk pointer = $%lx\n",first));

    for(chunk=first; chunk && (!error); chunk=chunk->ch_Next)
    {
    size  = (chunk->ch_Size == IFFSIZE_UNKNOWN) ?
            strlen(chunk->ch_Data) :  chunk->ch_Size;
    error = PutCk(iff, chunk->ch_ID, size, chunk->ch_Data);
    D(bug("writechunklist: put %.4s size=%ld, error=%ld\n",
                &chunk->ch_ID,size, error));
    }
    return(error);
    }


Devices/modules/loadilbm.c

/* loadilbm.c 05/91  C. Scheppner CBM
 *
 * High-level ILBM load routines
 */

#include "iffp/ilbm.h"
#include "iffp/ilbmapp.h"

extern struct Library *GfxBase;

/* loadbrush
 *
 * Passed an initialized ILBMInfo with a not-in-use ParseInfo.iff
 *   IFFHandle and desired propchks, collectchks, and stopchks, and filename,
 *   will load an ILBM as a brush, setting up ilbm->Bmhd, ilbm->camg,
 *   ilbm->brbitmap, ilbm->colortable, and ilbm->ncolors
 *
 *   Note that ncolors may be more colors than you can LoadRGB4.
 *   Use MIN(ilbm->ncolors,MAXAMCOLORREG) for color count if you change
 *   the colors yourself using 1.3/2.0 functions.
 *
 * Returns 0 for success or an IFFERR (libraries/iffparse.h)
 */

LONG loadbrush(struct ILBMInfo *ilbm, UBYTE *filename)
{
LONG error = 0L;

    if(!(ilbm->ParseInfo.iff))	return(CLIENT_ERROR);

    if(!(error = openifile((struct ParseInfo *)ilbm, filename, IFFF_READ)))
    {
    error = parseifile((struct ParseInfo *)ilbm,
                ID_FORM, ID_ILBM,
                ilbm->ParseInfo.propchks,
                ilbm->ParseInfo.collectchks,
                ilbm->ParseInfo.stopchks);
    if((!error)||(error == IFFERR_EOC)||(error == IFFERR_EOF))
        {
        if(contextis(ilbm->ParseInfo.iff,ID_ILBM,ID_FORM))
        {
            if(error = createbrush(ilbm))   deletebrush(ilbm);
        }
        else
        {
        closeifile((struct ParseInfo *)ilbm);
        message("Not an ILBM\n");
        error = NOFILE;
        }
        }
    }
    return(error);
}

/* unloadbrush
 *
 * frees and close everything alloc'd/opened by loadbrush
 */
void unloadbrush(struct ILBMInfo *ilbm)
{
    closeifile((struct ParseInfo *)ilbm);
    deletebrush(ilbm);
}

/* queryilbm
 *
 * Passed an initilized ILBMInfo with a not-in-use IFFHandle,
 *   and a filename,
 *   will open an ILBM, fill in ilbm->camg and ilbm->bmhd,
 *   and close the ILBM.
 *
 * This allows you to determine if the ILBM is a size and
 *   type you want to deal with.
 *
 * Returns 0 for success or an IFFERR (libraries/iffparse.h)
 */

/* query just wants these chunks */
LONG queryprops[] = { ID_ILBM, ID_BMHD,
              ID_ILBM, ID_CAMG,
                      TAG_DONE };

/* scan can stop when a CMAP or BODY is reached */
LONG querystops[] = { ID_ILBM, ID_CMAP,
              ID_ILBM, ID_BODY,
              TAG_DONE };

LONG queryilbm(struct ILBMInfo *ilbm, UBYTE *filename)
{
LONG error = 0L;
BitMapHeader *bmhd;

    if(!(ilbm->ParseInfo.iff))	return(CLIENT_ERROR);

    if(!(error = openifile((struct ParseInfo *)ilbm, filename, IFFF_READ)))
    {
    D(bug("queryilbm: openifile successful\n"));

    error = parseifile((struct ParseInfo *)ilbm,
            ID_FORM, ID_ILBM,
            queryprops, NULL, querystops);

    D(bug("queryilbm: after parseifile, error = %ld\n",error));

    if((!error)||(error == IFFERR_EOC)||(error == IFFERR_EOF))
        {
        if(contextis(ilbm->ParseInfo.iff,ID_ILBM,ID_FORM))
        {
        if(bmhd = (BitMapHeader*)
            findpropdata(ilbm->ParseInfo.iff,ID_ILBM,ID_BMHD))
            {
            *(&ilbm->Bmhd) = *bmhd;
            ilbm->camg = getcamg(ilbm);
            }
        else error = NOFILE;
        }
        else
        {
        message("Not an ILBM\n");
        error = NOFILE;
        }
        }
    closeifile(ilbm);
    }
    return(error);
}

/* loadilbm
 *
 * Passed a not-in-use IFFHandle, an initialized ILBMInfo, and filename,
 *   will load an ILBM into your already opened ilbm->scr, setting up
 *   ilbm->Bmhd, ilbm->camg, ilbm->colortable, and ilbm->ncolors
 *   and loading the colors into the screen's viewport
 *
 *   Note that ncolors may be more colors than you can LoadRGB4.
 *   Use MIN(ilbm->ncolors,MAXAMCOLORREG) for color count if you change
 *   the colors yourself using 1.3/2.0 functions.
 *
 * Returns 0 for success or an IFFERR (libraries/iffparse.h)
 *
 * NOTE - loadilbm() keeps the IFFHandle open so you can copy
 *   or examine other chunks.  You must call closeifile(iff,ilbm)
 *   to close the file and deallocate the parsed context
 *
 */

LONG loadilbm(struct ILBMInfo *ilbm, UBYTE *filename)
{
LONG error = 0L;

    D(bug("loadilbm:\n"));

    if(!(ilbm->ParseInfo.iff))	return(CLIENT_ERROR);
    if(!ilbm->scr)		return(CLIENT_ERROR);

    if(!(error = openifile((struct ParseInfo *)ilbm, filename, IFFF_READ)))
    {
    D(bug("loadilbm: openifile successful\n"));

    error = parseifile((struct ParseInfo *)ilbm,
            ID_FORM, ID_ILBM,
            ilbm->ParseInfo.propchks,
            ilbm->ParseInfo.collectchks,
            ilbm->ParseInfo.stopchks);

    D(bug("loadilbm: after parseifile, error = %ld\n",error));

    if((!error)||(error == IFFERR_EOC)||(error == IFFERR_EOF))
        {
        if(contextis(ilbm->ParseInfo.iff,ID_ILBM,ID_FORM))
        {
            error = loadbody(ilbm->ParseInfo.iff,
                    &ilbm->scr->BitMap, &ilbm->Bmhd);

        D(bug("loadilbm: after loadbody, error = %ld\n",error));

        if(!error)
            {
            if(!(getcolors(ilbm)))
                LoadRGB4(&ilbm->scr->ViewPort,ilbm->colortable,
                    MIN(ilbm->ncolors,MAXAMCOLORREG));
            }
        }
        else
        {
        closeifile((struct ParseInfo *)ilbm);
        message("Not an ILBM\n");
        error = NOFILE;
        }
        }
    }
    return(error);
}

/* unloadilbm
 *
 * frees and closes everything allocated by loadilbm
 */
void unloadilbm(struct ILBMInfo *ilbm)
{
    closeifile((struct ParseInfo *)ilbm);
    freecolors(ilbm);
}


Devices/modules/screendump.c

/*
 * screendump.c    - routine to dump rastport (iffparse not required)
 *
 */

#include <exec/types.h>
#include <intuition/screens.h>
#include <devices/printer.h>

#ifndef NO_PROTOS
#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#endif

/* screendump
 *
 * Passed a screen pointer, source x, source y, width, height,
 *   destcols and io_Special flags, will print part or all of a screen.
 *
 * If 0 is passed for BOTH destcols and special, screendump()
 *   assumes you want IT to compute suitable values.
 * In this case:
 *   1. If srcx and srcy are 0, and srcw and srch are same as
 *      screen width and height, screendump will set destcols=0,
 *      and special = SPECIAL_FULLCOLS|SPECIAL_ASPECT
 *	for a full width aspected dump.
 *
 *   2. If srcx or srcy are nonzero, or srcw or srch are different
 *      from screen width or height, screendump will print a
 *      fractional size dump relative to the size whole screendump
 *      would have been.
 *
 * Returns 0 for success or printer io_Error (devices/printer.h)
 */

int screendump(struct Screen *scr,
        UWORD srcx, UWORD srcy, UWORD srcw, UWORD srch,
        LONG destcols, UWORD iospecial)
    {
    struct IODRPReq *iodrp;
    struct MsgPort  *printerPort;
    struct ViewPort *vp;
    ULONG tmpl;
    int error = PDERR_BADDIMENSION;

    if(!scr)	return(error);

    if((!destcols)&&(!iospecial))
    {
    /* Then we compute what they should be */
    if((!srcx)&&(!srcy)&&(srcw==scr->Width)&&(srch==scr->Height))
        {
        iospecial = SPECIAL_FULLCOLS|SPECIAL_ASPECT;
        }
    else
        {
        iospecial = SPECIAL_FRACCOLS|SPECIAL_ASPECT;
        tmpl = srcw;
        tmpl = tmpl << 16;
        destcols = (tmpl / scr->Width) << 16;
        }
    }

    if(printerPort = CreatePort(0,0))
    {
    if(iodrp=
       (struct IODRPReq *)CreateExtIO(printerPort,sizeof(struct IODRPReq)))
        {
        if(!(error=OpenDevice("printer.device",0,iodrp,0)))
        {
                vp = &scr->ViewPort;
                iodrp->io_Command = PRD_DUMPRPORT;
                iodrp->io_RastPort = &scr->RastPort;
                iodrp->io_ColorMap = vp->ColorMap;
                iodrp->io_Modes = (ULONG)vp->Modes;
             iodrp->io_SrcX = srcx;
            iodrp->io_SrcY = srcy;
                iodrp->io_SrcWidth = srcw;
                iodrp->io_SrcHeight = srch;
            iodrp->io_DestCols = destcols;
    /*  	iodrp->io_DestRows = 0; cleared by allocation */
                iodrp->io_Special = iospecial;

                error = DoIO(iodrp);

                CloseDevice(iodrp);
                }
        DeleteExtIO(iodrp);
          }
          DeletePort(printerPort);
          }
    return(error);
    }


Devices/other/sift.c

;/* sift.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -j73 sift.c
Blink FROM LIB:c.o,sift.o TO sift LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit

*
* sift.c:	Takes any IFF file and tells you what's in it.  Verifies
*		syntax and all that cool stuff.
*
* Usage: sift -c		; For clipboard scanning
*    or  sift <file>		; For DOS file scanning
*
* Reads the specified stream and prints an IFFCheck-like listing of the
* contents of the IFF file, if any.  Stream is a DOS file for <file>
* argument, or is the clipboard's primary clip for -c.
* This program must be run from a CLI.
*
* Based on original sift.c by by Stuart Ferguson and Leo Schwab
*/

#include <exec/types.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <libraries/iffparse.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/iffparse_protos.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

#define MINARGS 2

/* 2.0 Version string for c:Version to find */
UBYTE vers[] = "\0$VER: sift 37.1";

UBYTE usage[] = "Usage: sift IFFfilename (or -c for clipboard)";

/* proto for our function */
void PrintTopChunk (struct IFFHandle *);

/*
 * Text error messages for possible IFFERR_#? returns from various
 * IFF routines.  To get the index into this array, take your IFFERR code,
 * negate it, and subtract one.
 *  idx = -error - 1;
 */
char	*errormsgs[] = {
    "End of file (not an error).",
    "End of context (not an error).",
    "No lexical scope.",
    "Insufficient memory.",
    "Stream read error.",
    "Stream write error.",
    "Stream seek error.",
    "File is corrupt.",
    "IFF syntax error.",
    "Not an IFF file.",
    "Required call-back hook missing.",
    "Return to client.  You should never see this."
};

struct Library *IFFParseBase;

void main(int argc, char **argv)
{
    struct IFFHandle	*iff = NULL;
    long		error;
    short		cbio;

        /* if not enough args or '?', print usage */
        if(((argc)&&(argc<MINARGS))||(argv[argc-1][0]=='?'))
        {
            printf("%s\n",usage);
            goto bye;
            }

    /*
     * Check to see if we are doing I/O to the Clipboard.
     */
    cbio = (argv[1][0] == '-'  &&  argv[1][1] == 'c');

    if (!(IFFParseBase = OpenLibrary ("iffparse.library", 0L)))
        {
        puts("Can't open iff parsing library.");
        goto bye;
        }

    /*
     * Allocate IFF_File structure.
     */
    if (!(iff = AllocIFF ()))
        {
        puts ("AllocIFF() failed.");
        goto bye;
        }

    /*
     * Internal support is provided for both AmigaDOS files, and the
     * clipboard.device.  This bizarre 'if' statement performs the
     * appropriate machinations for each case.
     */
    if (cbio)
        {
        /*
         * Set up IFF_File for Clipboard I/O.
         */
        if (!(iff->iff_Stream =
                (ULONG) OpenClipboard (PRIMARY_CLIP)))
            {
            puts ("Clipboard open failed.");
            goto bye;
            }
        InitIFFasClip (iff);
        }
    else
        {
        /*
         * Set up IFF_File for AmigaDOS I/O.
         */
        if (!(iff->iff_Stream = Open (argv[1], MODE_OLDFILE)))
            {
            puts ("File open failed.");
            goto bye;
            }
        InitIFFasDOS (iff);
        }

    /*
     * Start the IFF transaction.
     */
    if (error = OpenIFF (iff, IFFF_READ))
        {
        puts ("OpenIFF failed.");
        goto bye;
        }

    while (1)
        {
        /*
         * The interesting bit.  IFFPARSE_RAWSTEP permits us to
         * have precision monitoring of the parsing process, which
         * is necessary if we wish to print the structure of an
         * IFF file.  ParseIFF() with _RAWSTEP will return the
         * following things for the following reasons:
         *
         * Return code:			Reason:
         * 0				Entered new context.
         * IFFERR_EOC			About to leave a context.
         * IFFERR_EOF			Encountered end-of-file.
         * <anything else>		A parsing error.
         */
        error = ParseIFF (iff, IFFPARSE_RAWSTEP);

        /*
         * Since we're only interested in when we enter a context,
         * we "discard" end-of-context (_EOC) events.
         */
        if (error == IFFERR_EOC)
            continue;
        else if (error)
            /*
             * Leave the loop if there is any other error.
             */
            break;

        /*
         * If we get here, error was zero.
         * Print out the current state of affairs.
         */
        PrintTopChunk (iff);
        }

    /*
     * If error was IFFERR_EOF, then the parser encountered the end of
     * the file without problems.  Otherwise, we print a diagnostic.
     */
    if (error == IFFERR_EOF)
        puts ("File scan complete.");
    else
        printf ("File scan aborted, error %ld: %s\n",
            error, errormsgs[-error - 1]);

bye:
    if (iff) {
        /*
         * Terminate the IFF transaction with the stream.  Free
         * all associated structures.
         */
        CloseIFF (iff);

        /*
         * Close the stream itself.
         */
        if (iff->iff_Stream)
            if (cbio)
                CloseClipboard ((struct ClipboardHandle *)
                        iff->iff_Stream);
            else
                Close (iff->iff_Stream);

        /*
         * Free the IFF_File structure itself.
         */
        FreeIFF (iff);
        }
    if (IFFParseBase)	CloseLibrary (IFFParseBase);

    exit (RETURN_OK);
}

void
PrintTopChunk (iff)
struct IFFHandle *iff;
{
    struct ContextNode	*top;
    short			i;
    char			idbuf[5];

    /*
     * Get a pointer to the context node describing the current context.
     */
    if (!(top = CurrentChunk (iff)))
        return;

    /*
     * Print a series of dots equivalent to the current nesting depth of
     * chunks processed so far.  This will cause nested chunks to be
     * printed out indented.
     */
    for (i = iff->iff_Depth;  i--; )
        printf (". ");

    /*
     * Print out the current chunk's ID and size.
     */
    printf ("%s %ld ", IDtoStr (top->cn_ID, idbuf), top->cn_Size);

    /*
     * Print the current chunk's type, with a newline.
     */
    puts (IDtoStr (top->cn_Type, idbuf));
}


Amiga® Hardware Reference Manual: Contents

   PREFACE
  Chapters                       Appendices
  --------                       ----------
  1  Introduction                  A  REGISTER SUMMARY ALPHABETICAL ORDER
  2  COPROCESSOR HARDWARE          B  REGISTER SUMMARY ADDRESS ORDER
  3  PLAYFIELD HARDWARE            C  ENHANCED CHIP SET
  4  SPRITE HARDWARE               D  SYSTEM MEMORY MAPS
  5  AUDIO HARDWARE                E  I/O CONNECTORS AND INTERFACES
  6  BLITTER HARDWARE              F  8520 COMPLEX INTERFACE ADAPTERS
  7  SYSTEM CONTROL HARDWARE       G  KEYBOARD INTERFACE
  8  INTERFACE HARDWARE            H  EXTERNAL DISK CONNECTOR INTERFACE
                                   I  HARDWARE EXAMPLE INCLUDE FILE
   LIST OF FIGURES     GLOSSARY    J  CUSTOM CHIP PIN ALLOCATION LIST
   LIST OF TABLES      INDEX       K  ZORRO EXPANSION BUS


Amiga® Hardware Reference Manual: Preface

The Amiga Technical Reference Series is the official guide to programming
Amiga computers.  This revised edition of the Amiga Hardware
Reference Manual provides detailed information about the Amiga's graphics
and audio hardware, and how the Amiga talks to the outside world through
peripheral devices. This edition has been updated for version 2.0 of the
Amiga operating system and covers the newest Amiga computer systems
including the A3000.

This book is intended for the following audiences:

   *  Assembly language programmers who need a more direct way of
      interacting with the Amiga than the routines provided in the system
      software.

   *  Designers who want to interface new peripherals to the Amiga.

   *  Anyone who wants to know how the Amiga hardware works.

Here is a brief overview of the contents:

       Chapter 1, Introduction . An overview of the hardware and
      survey of the Amiga's graphics and audio features.

       Chapter 2, Coprocessor Hardware . Using the Copper coprocessor
      to control the entire graphics and audio system; directing
      mid-screen modifications in graphics displays and directing
      register changes during the time between displays.

       Chapter 3, Playfield Hardware . Creating, displaying and
      scrolling the playfields, one of the basic display elements of
      the Amiga; how the Amiga produces multi-color, bitmapped
      displays.

       Chapter 4, Sprite Hardware . Using the eight sprite direct
      memory access (DMA) channels to make sprite movable objects;
      creating their data structures, displaying and moving them,
      reusing the DMA channels.

       Chapter 5, Audio Hardware . Overview of sampled sound; how to
      produce quality sound, simple and complex sounds, and modulated
      sounds.

       Chapter 6, Blitter Hardware . Using the blitter DMA channel to
      create animation effects and draw lines into playfields.

       Chapter 7, System Control Hardware . Using the control
      registers to define depth arrangement of graphics objects,
      detect collisions between graphics objects, control direct
      memory access, and control interrupts.

       Chapter 8, Interface Hardware . How the Amiga talks to the
      outside world through controller ports, keyboard, audio jacks
      and video connectors, serial and parallel interfaces;
      information about the disk controller and RAM expansion slot.

      Appendices. Alphabetical and address-order listings of all the
      graphics and audio system registers and the functions of their
      bits. Also included is a special section on the Amiga's Enhanced
      Chip Set (ECS), system memory maps, descriptions of internal and
      external connectors, specifications for the peripheral interface
      ports, keyboard, and an introduction to the Amiga's Zorro
      expansion bus with detailed specifications for hardware add-on
      designers.

We suggest that you use this book according to your level of familiarity
with the Amiga system.  Here are some suggestions:

   *  If this is your initial exposure to the Amiga, read chapter 1, which
      gives a survey of all the hardware features and a brief rundown of
      graphics and audio effects created by hardware interaction.

   *  If you are already familiar with the system and want to acquaint
      yourself with how the various bits in the hardware registers govern
      the way the system functions, browse through chapters 2 through 8.
      Examples are included in these chapters.

   *  For advanced users, the appendices give a concise summary of the
      entire register set and the uses of the individual bits.  Once you
      are familiar with the effects of changes in the various bits, you may
      wish to refer more often to the appendices than to the explanatory
      chapters.

The other manuals in this series are the Amiga User Interface Style Guide,
an application design specification and reference work for Amiga
programmers, the Amiga ROM Kernel Reference Manual: Includes and Autodocs,
an alphabetically organized reference of ROM function summaries and Amiga
system include files, the Amiga ROM Kernel Reference Manual: Libraries
and the Amiga ROM Kernel Reference Manual: Devices  with tutorial-style
chapters on the use of each Amiga system library and device.


Amiga® Hardware Reference Manual: 1 Introduction

The Amiga family of computers consists of several models, each of which
has been designed on the same premise -- to provide the user with a
low-cost computer that features high-cost performance.  The Amiga does
this through the use of custom silicon hardware that yields advanced
graphics and sound features.

There are four basic models that make up the Amiga computer family: the
A500, A1000, A2000, and A3000.  Though the models differ in price and
features, they have a common hardware nucleus that makes them software
compatible with one another.  This chapter describes the Amiga's hardware
components and gives a brief overview of its graphics and sound features.

 Components of the Amiga          Applications & Technical Support (CATS)
 About the Examples               Error Reports
 General Development Guidelines


1 Introduction / Components of the Amiga

These are the hardware components of the Amiga:

*  Motorola MC68000 16/32-bit main processor.  The Amiga also supports the
   68010, 68020, and 68030 processors as an option. The A1000, A500 and
   A2000 contain the 68000, while the A3000 utilizes the 68030 processor.

*  Custom graphics and audio chips with DMA capability.  All Amiga models
   are equipped with three custom chips named Paula, Agnus, and Denise
   which provide for superior color graphics, digital audio, and
   high-performance interrupt and I/O handling.  The custom chips can
   access up to 2MB of memory directly without using the 68000 CPU.

*  From 256K to 2 MB of RAM expandable to a total of 8 MB (over a gigabyte
   on the Amiga 3000).

*  512K of system ROM containing a real time, multitasking operating
   system with sound, graphics, and animation support routines. (V1.3 and
   earlier versions of the OS used 256K of system ROM.)

*  Built-in 3.5 inch double sided disk drive with expansion floppy disk
   ports for connecting up to three additional disk drives (either 3.5
   inch or 5.25 inch, double sided).

*  SCSI disk port for connecting additional SCSI disk drives (A3000 Only).

*  Fully programmable parallel and RS-232-C serial ports.

*  Two button opto-mechanical mouse and two reconfigurable controller
   ports (for mice, joysticks, light pens, paddles, or custom
   controllers).

*  A professional keyboard with numeric keypad, 10 function keys, and
   cursor keys.  A variety of international keyboards are also supported.

*  Ports for analog or digital RGB output (all models), monochrome video
   (A500 and A2000), composite video (A1000), and VGA-style multiscan
   video (A3000).

*  Ports for left and right stereo audio from four special purpose audio
   channels.

*  Expansion options that allow you to add RAM, additional disk drives
   (floppy or hard), peripherals, or coprocessors.

 The MC68000 and the Amiga Custom Chips
 Amiga Memory System
 Peripherals
 System Expandability and Adaptability
 VCR and Direct Camera Interface
 Amiga System Block Diagram


1 / Components of the Amiga / The MC68000 and the Amiga Custom Chips

The Motorola MC68000 microprocessor is the CPU used in the A1000, the
A500, and the A2000.  The 68000 is a 16/32-bit microprocessor; internal
registers are 32 bits wide, while the data bus and ALU are 16 bits.  The
68000's system clock speed is 7.15909 MHz on NTSC systems (USA) or 7.09379
MHz on PAL systems (Europe).  These speeds can vary when using an external
system clock, such as from a genlock board.

The 68000 has an address space of 16 megabytes.  In the Amiga, the 68000
can address up to 9 megabytes of random access memory (RAM).

In the A3000, the Motorola MC68030 microprocessor is the CPU.  This is a
full 32-bit microprocessor with a system clock speed of 16 or 25
megahertz. The 68030 has an address space of 4 gigabytes.  In the A3000,
over a gigabyte of RAM can be addressed.

In addition to the 680x0, all Amiga models contain special purpose
hardware known as the custom chips that greatly enhance system
performance. The term custom chips refers to the three integrated circuits
which were designed specifically for the Amiga computer.  These three
custom chips, named Paula, Agnus, and Denise, each contain the logic to
handle a specific set of tasks such as video, audio, or I/O.

Because the custom chips have DMA capability, they can access memory
without using the 680x0 CPU - this frees the CPU for other types of
operations. The division of labor between the custom chips and the 680x0
gives the Amiga its power; on most other systems the CPU has to do
everything.

The memory shared between the Amiga's CPU and the custom chips is called
Chip memory.  The more Chip memory the Amiga has, the more graphics,
audio, and I/O data it can operate on without the CPU being involved. All
Amigas can access at least 512K of Chip memory.

The latest version of the custom chips, known as the Enhanced Chip Set or
ECS, can handle up to 2 MB of memory and has other advanced features.  For
more details about the Enhanced Chip Set, refer to  Appendix C .

Although there are different versions of the Amiga's custom chips, all
versions have some common features.  Among other functions, the custom
chips provide the following:

*  Bitplane generated, high resolution graphics capable of supporting both
   PAL and NTSC video standards.

      NTSC systems.
      -------------
      On NTSC systems, the Amiga typically produces a 320 by 200
      non-interlaced or 320 by 400 interlaced display in 32 colors. A
      high resolution mode provides a 640 by 200 non-interlaced or 640
      by 400 interlaced display in 16 colors.

      PAL systems.
      ------------
      On PAL systems, the Amiga typically produces a 320 by 256
      non-interlaced or 320 by 512 interlaced display in 32 colors.
      High resolution mode provides a 640 by 256 non-interlaced or 640
      by 512 interlaced display in 16 colors.

   The design of the Amiga's display system is very flexible and there are
   many other modes available.  Hold-and-modify (HAM) mode allows for the
   display of up to 4,096 colors on screen simultaneously.  Overscan mode
   allows the creation of higher resolution displays specially suited for
   video and film applications.  Displays of arbitrary size, larger than
   the visible viewing area can be created.  Amigas which contain the
   Enhanced Chip Set (ECS) support Productivity mode giving displays of
   640 by 480, non-interlaced with 4 colors from a pallette of 64.

*  A custom graphics coprocessor, called the Copper, that allows changes
   to most of the special purpose registers in synchronization with the
   position of the video beam.  This allows such special effects as
   mid-screen changes to the color palette, splitting the screen into
   multiple horizontal slices each having different video resolutions and
   color depths, beam-synchronized interrupt generation for the 680x0, and
   more. The coprocessor can trigger many times per screen, in the middle
   of lines, and at the beginning or during the blanking interval. The
   coprocessor itself can directly affect most of the registers in the
   other custom chips, freeing the 680x0 for general computing tasks.

*  32 system color registers, each of which contains a 12-bit number as
   four bits of red, four bits of green, and four bits of blue intensity
   information.  This allows a system color palette of 4,096 different
   choices of color for each register.

*  Eight reusable 16-bit wide sprites with up to 15 color choices per
   sprite pixel (when sprites are paired).  A sprite is an easily movable
   graphics object whose display is entirely independent of the background
   (called a playfield); sprites can be displayed over or under this
   background.  A sprite is 16 low resolution pixels wide and an arbitrary
   number of lines tall. After producing the last line of a sprite on the
   screen, a sprite DMA channel may be used to produce yet another sprite
   image elsewhere on screen (with at least one horizontal line between
   each reuse of a sprite processor). Thus, many small sprites can be
   produced by simply reusing the sprite processors appropriately.

*  Dynamically controllable inter-object priority, with collision
   detection. This means that the system can dynamically control the video
   priority between the sprite objects and the bitplane backgrounds
   (playfields). You can control which object or objects appear over or
   under the background at any time.  Additionally, you can use system
   hardware to detect collisions between objects and have your program
   react to such collisions.

*  Custom bit blitter used for high speed data movement, adaptable to
   bitplane animation.  The blitter has been designed to efficiently
   retrieve data from up to three sources, combine the data in one of 256
   different possible ways, and optionally store the combined data in a
   destination area. The bit blitter, in a special mode, draws patterned
   lines into rectangularly organized memory regions at a speed of about 1
   million dots per second; and it can efficiently handle area fill.

*  Audio consisting of four digital channels with independently
   programmable volume and sampling rate.  The audio channels retrieve
   their control and sample data via DMA.  Once started, each channel can
   automatically play a specified waveform without further processor
   interaction.  Two channels are directed into each of the two stereo
   audio outputs.  The audio channels may be linked together to provide
   amplitude or frequency modulation or both forms of modulation
   simultaneously.

*  DMA controlled floppy disk read and write on a full track basis.  This
   means that the built-in disk can read over 5600 bytes of data in a
   single disk revolution (11 sectors of 512 bytes each).


1 / Components of the Amiga / Amiga Memory System

As mentioned previously, the custom chips have DMA access to RAM which
allows them to perform graphics, audio, and I/O chores independently of
the CPU.  This shared memory that both the custom chips and the CPU can
access directly is called Chip memory.

The custom chips and the 680x0 CPU share Chip memory on a fully
interleaved basis.  Since the 680x0 only needs to access the Chip memory
bus during each alternate clock cycle in order to run full speed, the rest
of the time the Chip memory bus is free for other activities.  The custom
chips use the memory bus during these free cycles, effectively allowing
the CPU to run at full speed most of the time.

There are some occasions though when the custom chips steal memory cycles
from the 680x0.  In the higher resolution video modes, some or all of the
cycles normally used for processor access are needed by the custom chips
for video refresh.  In that case, the Copper and the blitter in the custom
chips steal time from the 680x0 for jobs they can do better than the
680x0.  Thus, the system DMA channels are designed with maximum
performance in mind.

Even when such cycle stealing occurs, it only blocks the 680x0's access to
the internal, shared memory.  When using ROM or external memory, also
known as Fast memory, the 680x0 always runs at full speed.

The DMA capabilities of the custom chips vary depending on the version of
the chips and the Amiga model.  The original custom chip set found in the
A1000 could access the first 512K of RAM.  Most A1000s have only 512K of
RAM so some of the Chip RAM is used up for operating system overhead.

A later version of the custom chips found in early A500s and A2000s
replaced the original Agnus chip (8361) with a newer version called Fat
Agnus (8370/8371).  The Fat Agnus chip has DMA access to 512K of Chip
memory, just like the original Agnus, but also allows an additional 512K
of internal slow memory or pseudo-fast memory located at ($00C0 0000).
Since the slow memory can be used for operating system overhead, this
allows all 512K of Chip memory to be used by the custom chips.

The name slow memory comes from the fact that bus contention with the
custom chips can still occur even though only the CPU can access the
memory.  Since slow memory is arbitrated by the same gate that controls
Chip memory, the custom chips can block processor access to slow memory in
the higher resolution video modes.

The latest version of Agnus and the custom chips found in most A500s and
A2000s is known as the Enhanced Chip Set or ECS.  ECS Fat Agnus (8372A)
can access up to one megabyte of Chip memory.  It is pin compatible with
the original Fat Agnus (8370/8371) found in earlier A500 and A2000 models.
In addition, ECS Fat Agnus supports both the NTSC and PAL video standards
on a single chip.

In the A3000, the Enhanced Chip Set can access up to two megabytes of Chip
memory.

The amount of Chip memory is important since it determines how much
graphics, audio, and disk data the custom chips can operate on without the
680x0 CPU. Table 1-1 summarizes the basic memory configurations of the
Amiga.

                  Chip RAM     Maximum    Total RAM     Maximum
                (base model)   Chip RAM  (base model)  Total RAM
                ------------   --------  ------------  ---------
     Amiga 1000     256K        512K        256K          9 MB
     Amiga  500     512K        1 MB        1 MB          9 MB
     Amiga 2000     512K        1 MB        1 MB          9 MB
     Amiga 3000     1 MB        2 MB        2 MB     over 1 GB

                Table 1-1: Summary of Amiga Memory Configurations

Another primary feature of the Amiga hardware is the ability to
dynamically control which part of the Chip memory is used for the
background display, audio, and sprites.  The Amiga is not limited to a
small, specific area of RAM for a frame buffer.  Instead, the system
allows display bitplanes, sprite processor control lists, coprocessor
instruction lists, or audio channel control lists to be located anywhere
within Chip memory.

This same region of memory can be accessed by the bit blitter.  This
means, for example, that the user can store partial images at scattered
areas of Chip memory and use these images for animation effects by rapidly
replacing on screen material while saving and restoring background images.
In fact, the Amiga includes firmware support for display definition and
control as well as support for animated objects embedded within playfields.


1 / Components of the Amiga / Peripherals

Floppy disk storage is provided by a built-in, 3.5 inch floppy disk drive.
Disks are 80 track, double sided, and formatted as 11 sectors per track,
512 bytes per sector (over 900,000 bytes per disk).  The disk controller
can read and write 320/360K IBM PC(TM) (MS-DOS(TM)) formatted 3.5 or 5.25
inch disks, and 640/720K IBM PC (MS-DOS) formatted 3.5 inch disks.

Up to three extra 3.5 inch or 5.25 inch disk drives can be added to the
Amiga.  The A2000 and A3000 also provide room to mount floppy or hard
disks internally.  The A3000 has a built-in hard disk drive and an
on-board SCSI controller which can handle two internal drives and up to
seven external SCSI devices.

The Amiga has a full complement of dedicated I/O connectors.  The
circuitry for some of these peripherals resides on the Paula custom chip
while the Amiga's two 8520 CIA chips handle other I/O chores not
specifically assigned to any of the custom chips.  These include modem
control, disk status sensing, disk motor and stepping control, ROM enable,
parallel input/output interface, and keyboard interface.

The Amiga includes a standard RS-232-C serial port for external serial
input/output devices such as a modem, MIDI interface, or printer. A
programmable, Centronics-compatible parallel port supports parallel
printers, audio digitizers, and other peripherals.

The Amiga also includes a two-button, opto-mechanical mouse plus a
keyboard with numeric keypad, cursor controls, and 10 function keys in the
base system. A variety of international keyboards are supported.  Many
other input options are available.  Other types of controllers can be
attached through the two controller ports on the base unit including
joysticks, keypads, trackballs, light pens, and graphics tablets.


1 / Components of the Amiga / System Expandability and Adaptability

New peripheral devices may be easily added to all Amiga models. These
devices are automatically recognized and used by system software through a
well defined, well documented linking procedure called AUTOCONFIG(TM).
AUTOCONFIG is short for automatic configuration and is the process which
allows memory or I/O space for an expansion board to be dynamically
allocated by the system at boot time.  Unlike some other systems, there is
no need to set DIP switches to select an address space from a fixed range
reserved for expansion devices.

On the A500 and A1000 models, peripheral devices can be added using the
Amiga's 86-pin expansion connector.  Peripherals that can be added include
hard disk controllers and drives, or additional external RAM.  Extra
floppy disk units may be added from a connector at the rear of the unit.

The A2000 and A3000 models provide the user with the same features as the
A500 or A1000, but with the added convenience of simple and extensive
expandability through the Amiga's 100-pin Zorro expansion bus.

The A2000 contains 7 internal slots and the A3000 contains 4 internal
slots plus a SCSI disk controller that allow many types of expansion
devices to be quickly and easily added inside the machine. Available
options include RAM boards, coprocessors, hard disk controllers, video
cards, and I/O ports.

The A2000 and A3000 also support the special Bridgeboard(TM) coprocessor
card.  This provides a complete IBM PC(TM) on a card and allows the Amiga
to run MS-DOS(TM) compatible software, while simultaneously running native
Amiga software.  In addition, both machines have expansion slots capable
of supporting standard, IBM PC(TM) style boards.


1 / Components of the Amiga / VCR and Direct Camera Interface

In addition to the connectors for monochrome composite, and analog or
digital RGB monitors, the Amiga can be expanded to include a VCR or camera
interface. The system is capable of synchronizing with an external video
source and replacing the system background color with the external image.
This allows development of fully integrated video images with computer
generated graphics. Laser disk input is accepted in the same manner.

The A2000 and A3000 models also provide a special internal slot designed
for video applications.  This allows the Amiga to use low-cost video
expansion boards such as genlocks and frame-grabbers.


1 / Components of the Amiga / Amiga System Block Diagram

The diagram below highlights the major hardware components of the Amiga's
architecture.  Notice that there are two separate buses, one that only the
CPU can access (Fast memory) and another one that the custom chips share
with the CPU (Chip memory).

     Figure 1-1: Block Diagram for the Amiga Computer Family


1 Introduction / About the Examples

The examples in this book all demonstrate direct manipulation of the Amiga
hardware.  However, as a general rule, it is not permissible to directly
access the hardware in the Amiga unless your software either has full
control of the system, or has arbitrated via the OS for exclusive access
to the particular parts of the hardware you wish to control.

Almost all of the hardware discussed in this manual, most notably the
Blitter, Copper, playfield, sprite, CIA, trackdisk, and system control
hardware, are in either exclusive or arbitrated use by portions of the
Amiga OS in any running Amiga system.  Additional hardware, such as the
audio, parallel, and serial hardware, may be in use by applications which
have allocated their use through the system software.

Before attempting to directly manipulate any part of the hardware in the
Amiga's multitasking environment, your application must first be granted
exclusive access to that hardware by the operating system library, device,
or resource which arbitrates its ownership.  The operating system
functions for requesting and receiving control of parts of the Amiga
hardware are varied and are not within the scope of this manual.
Generally such functions, when available, will be found in the library,
device, or resource which manages that portion of the Amiga hardware in
the multitasking environment.  The following list will help you to find
the appropriate operating system functions or mechanisms which may exist
for arbitrated access to the hardware discussed in this manual.

   Hardware component            Amiga system module that controls it
   ------------------            ------------------------------------
   Copper, Playfield, Sprite, Blitter................graphics.library
   Audio.................................................audio.device
   Trackdisk..........................trackdisk.device, disk.resource
   Serial................................serial.device, misc.resource
   Parallel..............parallel.device, cia.resource, misc.resource
   Gameport.............input.device, gameport.device, potgo.resource
   Keyboard.............................input.device, keyboard.device
   System Control.........graphics.library, exec.library (interrupts)

Most of the examples in this book use the hw_examples.i file (see
 Appendix I ) to define the chip register names.  Hw_examples.i
uses the system include file hardware/custom.i to define the chip
structures and relative addresses. The values defined in hardware/custom.i
and hw_examples.i are offsets from the base of the chip register address
space. In general, this base value is defined as _custom and is resolved
during linking with the linker library amiga.lib.  (_ciaa and _ciab are
also resolved in this way.)

Normally, the base address is loaded into an address register and the
offsets given by hardware/custom.i and hw_examples.i are then used to
access the correct register.  (One exception to this rule is the Copper
which uses only the offset access the registers.)

For example, in assembler:

        INCLUDE "exec/types.i"
        INCLUDE "hardware/custom.i"

        XREF    _custom                 ; External reference...

Start:  lea     _custom,a0              ; Use a0 as base register and
        move.w  #$7FFF,intena(a0)       ; use the name intena as an offset
                                        ; to disable all interrupts

In C, you would use the structure definitions in hardware/custom.h For
example:

  #include        "exec/types.h"
  #include        "hardware/custom.h"

  extern  struct  Custom  custom;

  /* You may need to define the above external as
  **  extern struct Custom far custom;
  **  Check you compiler manual.
  */

  main()
  {
      custom.intena = 0x7FFF;         /* Disable all interrupts */
  }

The Amiga hardware include files are generally supplied with your compiler
or assembler.  Listings of the hardware include files may also be found in
the Amiga ROM Kernel Manual: Includes and Autodocs. Generally, the include
file label names are very similar to the equivalent hardware register list
names with the following typical differences.

*  Address registers which have low word and high word components are
   generally listed as two word sized registers in the hardware register
   list, with each register name containing either a suffix or embedded
   "L" or "H" for low and high.  The include file label for the same
   register will generally treat the whole register as a longword (32 bit)
   register, and therefore will not contain the "L" or "H" distinction.

*  Related sequential registers which are given individual names with
   number suffixes in the hardware register list, are generally referenced
   from a single base register definition in the include files.  For
   example, the color registers in the hardware list (COLOR00, COLOR01,
   etc.) would be referenced from the "color" label defined in
   hardware/custom.i (color+0, color+2, etc.).

*  Examples of how to define the correct register offset can be found in
   the hw_examples.i file listed in  Appendix I .

Except as noted, 68000 assembly language examples have been assembled
under the Innovatronics CAPE assembler V2.x, the HiSoft Devpac assembler
V1.2, and the Lake Forest Logic ADAPT assembler 1.0.  No substantial
changes should be required to switch between assemblers.


1 Introduction / General Development Guidelines

The Amiga is available in a variety of models and configurations, and is
further diversified by a wealth of add-on expansion peripherals and
processor replacements.  In addition, even standard Amiga hardware such as
the keyboard and floppy disks, are supplied by a number of different
manufacturers and may vary subtly in both their timing and in their
ability to perform outside of their specified capabilities.

The Amiga operating system is designed to operate the Amiga hardware
within spec, adapt to different hardware and RAM configurations, and
generally provide upward compatibility with any future hardware upgrades
or "add ons" envisioned by the designers. For maximum upward
compatibility, it is strongly suggested that programmers deal with the
hardware through the commands and functions provided by the Amiga
operating system.

If you find it necessary to program the hardware directly, then it is your
responsibility to write code which will work properly on various models and
configurations.  Be sure to properly request and gain control of the
hardware you are manipulating, and be especially careful in the following
areas:

*  The environment of the Amiga computer is quite different than that of
   many other systems.  The Amiga is a multitasking platform, which
   means multiple programs can run on a single machine simultaneously.
   However, for multitasking to work correctly, care must be taken to
   ensure that programs do not interfere with one another.  It also
   means that certain guidelines must be followed during programming.

*  Remember that memory, peripheral configurations, and ROMs differ
   between models and between individual systems.  Do not make
   assumptions about memory address ranges, storage device names, or the
   locations of system structures or code.  Never call ROM routines
   directly.  Beware of any example code you find that calls routines at
   addresses in the $F0 0000 - $FF FFFF range.  These are ROM routines
   and they will move with every OS release.  The only supported
   interface to system ROM code is through the library, device, and
   resource calls.

*  Never assume library bases or structures will exist at any particular
   memory location.  The only absolute address in the system is $0000
   0004, which contains a pointer to the exec.library base. Do not modify
   or depend on the format of private system structures. This includes the
   poking of copper lists, memory lists, and library bases.

*  Never assume that programs can access hardware resources directly. Most
   hardware is controlled by system software that will not respond well to
   interference from other programs.  Shared hardware requires programs to
   use the proper sharing protocols.  Use the defined interface; it is the
   best way to ensure that your software will continue to operate on
   future models of the Amiga.

*  Never access shared data structures directly without the proper mutual
   exclusion (locking).  Remember that other tasks may be accessing the
   same structures.

*  All data for the custom chips must reside in Chip memory (type
   MEMF_CHIP).  This includes bitplanes, sound samples, trackdisk buffers,
   and images for sprites, bobs, pointers, and gadgets.  The AllocMem()
   call takes a flag for specifying the type of memory. A program that
   specifies the wrong type of memory may appear to run correctly because
   many Amigas have only Chip memory.  (On all models of the Amiga, the
   first 512K of memory is Chip memory and in some later models, Chip
   memory may occupy the first one or two megabytes).

   However, once expansion memory has been added to an Amiga (type
   MEMF_FAST), any memory allocations will be made in the expansion memory
   area by default.  Hence, a program can run correctly on an unexpanded
   Amiga which has only Chip memory while crashing on an Amiga which has
   expanded memory.  A developer with only Chip memory may fail to notice
   that memory was incorrectly specified.

   Most compilers have options to mark specific data structures or object
   modules so that they will load into Chip RAM.  Some older compilers
   provide the Atom utility for marking object modules.  If this method is
   unacceptable, use the AllocMem() call to dynamically allocate Chip
   memory, and copy your data there.

   When making allocations that do not require Chip memory, do not
   explicitly ask for Fast memory.  Instead ask for memory type
   MEMF_PUBLIC or 0L as appropriate.  If Fast memory is available, you
   will get it.

*  Never use software delay loops!  Under the multitasking operating
   system, the time spent in a loop can be better used by other tasks.
   Even ignoring the effect it has on multitasking, timing loops are
   inaccurate and will wait different amounts of time depending on the
   specific model of Amiga computer.  The timer.device provides
   precision timing for use under the multitasking system and it works
   the same on all models of the Amiga.  The AmigaDOS Delay() function
   or the graphics.library/WaitTOF() function provide a simple interface
   for longer delays.  The 8520 I/O chips provide timers for developers
   who are bypassing the operating system (see the Amiga Hardware
   Reference Manual for more information).

 68010/020/030/040 Compatibility
 Hardware Programming Guidelines
 Additional Assembler Guidelines


1 / General Development Guidelines / 68010/020/030/040 Compatibility

Special care must be taken to be compatible with the entire family of
68000 processors:

*  Do not use the upper 8 bits of a pointer for storing unrelated
   information.  The 68020, 68030, and 68040 use all 32 bits for
   addressing.

*  Do not use signed variables or signed math for addresses.

*  Do not use software delay loops, and do not make assumptions about the
   order in which asynchronous tasks will finish.

*  The stack frame used for exceptions is different on each member of the
   68000 family.  The type identification in the frame must be checked! In
   addition, the interrupt autovectors may reside in a different location
   on processors with a VBR register.

*  Do not use the MOVE SR,<dest> instruction!  This 68000 instruction acts
   differently on other members of the 68000 family.  If you want to get a
   copy of the processor condition codes, use the exec.library/GetCC()
   function.

*  Do not use the CLR instruction on a hardware register which is
   triggered by Write access.  The 68020 CLR instruction does a single
   Write access. The 68000 CLR instruction does a Read access first,
   then a Write access. This can cause a hardware register to be
   triggered twice.  Use MOVE.x #0, <address> instead.

*  Self-modifying code is strongly discouraged.  All 68000 family
   processors have a pre-fetch feature.  This means the CPU loads
   instructions ahead of the current program counter.  Hence, if your code
   modifies or decrypts itself just ahead of the program counter, the
   pre-fetched instructions may not match the modified instructions. The
   more advanced processors prefetch more words.  If self-modifying code
   must be used, flushing the cache is the safest way to prevent troubles.

*  The 68020, 68030, and 68040 processors all have instruction caches.
   These caches store recently used instructions, but do not monitor
   writes.  After modifying or directly loading instructions, the cache
   must be flushed.  See the exec.library/CacheClearU() Autodoc for more
   details.  If your code takes over the machine, flushing the cache will
   be trickier.  You can account for the current processors, and hope the
   same techniques will work in the future:

        CACRF_ClearI    EQU      $0008  ;Bit for clear instruction cache
                        ;
                        ;Supervisor mode only.	Use only if you have taken
                        ;over the machine.  Read and store the ExecBase
                        ;processor AttnFlags flags at boot time, call this
                        ;code only if the "68020 or better" bit was set.
                        ;
        ClearICache:    dc.w    $4E7A,$0002   ;MOVEC CACR,D0
                        tst.w   d0            ;movec does not affect CC's
                        bmi.s   cic_040       ;A 68040 with enabled cache!
                        ori.w   #CACRF_ClearI,d0
                        dc.w    $4E7B,$0002   ;MOVEC D0,CACR
                        bra.s   cic_exit
        cic_040:        dc.w    $f4b8         ;CPUSHA (IC)
        cic_exit:


1 / General Development Guidelines / Hardware Programming Guidelines

*  If you find it necessary to program the hardware directly, then it is
   your responsibility to write code that will work correctly on the
   various models and configurations of the Amiga.  Be sure to properly
   request and gain control of the hardware resources you are
   manipulating, and be especially careful in the following areas:

*  Kickstart 2.0 uses the 8520 Complex Interface Adaptor (CIA) chips
   differently than 1.3 did.  To ensure compatibility, you must always
   ask for CIA access using the cia.resource/AddICRVector() and
   RemICRVector() functions.  Do not make assumptions about what the
   system might be using the CIA chips for.  If you write directly to
   the CIA chip registers, do not expect system services such as the
   trackdisk.device to function.  If you are leaving the system up, do
   not read or write to the CIA Interrupt Control Registers directly;
   use the cia.resource/AbleICR(), and SetICR() functions.  Even if you
   are taking over the machine, do not assume the initial contents of
   any of the CIA registers or the state of any enabled interrupts.

*  All custom chip registers are Read-only or Write-only.  Do not read
   Write-only registers, and do not write to Read-only registers.

*  Never write data to, or interpret data from the unused bits or
   addresses in the custom chip space.  To be software-compatible with
   future chip revisions, all undefined bits must be set to zeros on
   writes, and must be masked out on reads before interpreting the
   contents of the register.

*  Never write past the current end of custom chip space.  Custom chips
   may be extended or enhanced to provide additional registers, or to
   use bits that are currently undefined in existing registers.

*  Never read, write, or use any currently undefined address ranges or
   registers.  The current and future usage of such areas is reserved by
   Amiga, Inc. and is subject to change.

*  Never assume that a hardware register will be initialized to any
   particular value.  Different versions of the OS may leave registers set
   to different values.  Check the Amiga Hardware Reference Manual to
   ensure that you are setting up all the registers that affect your code.


1 / General Development Guidelines / Additional Assembler Guidelines

If you are writing in assembly language there are some extra rules to keep
in mind in addition to those listed above.

*  Never use the TAS instruction on the Amiga.  System DMA can conflict
   with this instruction's special indivisible read-modify-write cycle.

*  System functions must be called with register A6 containing the library
   or device base.  Libraries and devices assume A6 is valid at the time
   of any function call.  Even if a particular function does not currently
   require its base register, you must provide it for compatibility with
   future system software releases.

*  Except as noted, system library functions use registers D0, D1, A0, and
   A1 as scratch registers and you must consider their former contents to
   be lost after a system library call.  The contents of all other
   registers will be preserved.  System functions that provide a result
   will return the result in D0.

*  Never depend on processor condition codes after a system call. The
   caller must test the returned value before acting on a condition code.
   This is usually done with a TST or MOVE instruction.

*  If you are programming at the hardware level, you must follow hardware
   interfacing specifications.  All hardware is not the same.  Do not
   assume that low level hacks for speed or copy protection will work on
   all drives, or all keyboards, or all systems, or future systems.  Test
   your software on many different systems, with different processors, OS,
   hardware, and RAM configurations.


1 Introduction / Applications & Technical Support (CATS)

Commodore maintains a technical support group dedicated to helping
developers achieve their goals with the Amiga.  Currently, technical
support programs are available to meet the needs of both smaller,
independent software developers and larger corporations. Subscriptions to
Commodore's technical support publication, Amiga Mail, is available to
anyone with an interest in the latest news, Commodore software and
hardware changes, and tips for developers.

To request an application for Commodore's developer support program, or a
list of CATS technical publications send a self-addressed, stamped, 9" x
12" envelope to:

          CATS-Information
          1200 West Wilson Drive
          West Chester, PA  19380-4231


1 Introduction / Error Reports

In a complex technical manual, errors are often found after publication.
When errors in this manual are found, they will be corrected in a
subsequent printing.  Updates will be published in Amiga Mail, Commodore's
technical support publication.

Bug reports can be sent to Commodore electronically or by mail.  Submitted
reports must be clear, complete, and concise.  Reports must include a
telephone number and enough information so that the bug can be quickly
verified from your report (i.e., please describe the bug and the steps
that produced it).

          Amiga Software Engineering Group
          ATTN: BUG REPORTS
          Commodore Business Machines
          1200 Wilson Drive
          West Chester, PA  19380-4231
          USA

          BIX: amiga.com/bug.reports      (Commercial developers)
               amiga.cert/bug.reports     (Certified developers)
               amiga.dev/bugs             (Others)

               USENET: bugs@commodore.COM  or  uunet!cbmvax!bugs


Amiga® Hardware Reference Manual:A Register Summary Alphabetical Order

This appendix contains the definitive summary, in alphabetical order, of
the Amiga's custom chip register set and the usages of the individual bits.

The addresses shown here are used by the special custom chips (named
"Paula", "Agnus", and "Denise") for transferring data among themselves.
Also, the Copper uses these addresses for writing to the special chip
registers. To write to these registers with the 680x0, calculate the 680x0
address using this formula:

          680x0 address = (chip address) + $DFF000

For example, for the 680x0 to write to ADKCON (address = $09E), the
address would be $DFF09E.  No other access address is valid.  Do not
attempt to access any documented or unused registers.

All of the "pointer" type registers are organized as 32 bits on a long
word boundary.  These registers may be written with one MOVE.L
instruction. The lowest bit of all pointers must be written as zero.  The
custom chips can only access Chip memory; using a non-Chip address will
fail (See the AllocMem() documentation or your compiler manual for more
information on Chip memory).  Disk data, sprite data, bitplane data, audio
data, copper lists and anything that will be blitted or accessed by custom
chip DMA must be located in chip memory.

When strobing any register which responds to either a read or a write,
(for example copjmp2) be sure to use a MOVE.W, not CLR.W.  The CLR
instruction causes a read and a clear (two accesses) on a 68000, but only
a single access on 68020 processors.  This will give different results on
different processors.

   Warning:
   --------
   Registers are either read-only or write-only. In the following
   descriptions, if a register is marked as a read-only register, only
   read its contents.  Do not attempt to write to a read-only register,
   as this will cause unpredictable results.  If a register is marked as
   a write-only register, do not attempt to read from it, as this may
   trash the register and crash the system.

If a bit is described as unused in a write-only register, be sure to keep
that bit clear when writing values to that register.  Similarly, do not
rely on the values of unused bits when reading from a read only register.
Further, do not write to an address or register that is not documented or
defined in this appendix.  Setting unused bits in a write-only register,
reading unused bits from a read only register and writing to undocumented
registers or addresses may cause serious future software incompatibility
if those bits or addresses are implemented in the future by Amiga, Inc.

   About the ECS registers.
   ------------------------
   Registers denoted with an "(E)" in the chip column means that those
   registers have been changed the Enhanced Chip Set(ECS).  The ECS is
   found in the A3000, and is installable in the A500 and A2000.
   Certain ECS registers are completely new, others have been extended
   in their functionality.  See the  register map in Appendix C  for
   information on which ECS registers are new and which have been
   modified.

 ADKCON      BLTSIZH     COP1LCH     DSKDAT      JOY1DAT     STRHOR
 ADKCONR     BLTxDAT     COP1LCL     DSKDATR     JOYTEST     STRLONG
 AUDxDAT     BLTxMOD     COP2LCH     DSKLEN      POT0DAT     STRVBL
 AUDxLCH     BLTxPTH     COP2LCL     DSKPTH      POT1DAT     VBSTOP
 AUDxLCL     BLTxPTL     COPCON      DSKPTL      POTGO       VBSTRT
 AUDxLEN     BPL1MOD     COPINS      DSKSYNC     POTGOR      VHPOSR
 AUDxPER     BPL2MOD     COPJMP1     HBSTOP      REFPTR      VHPOSW
 AUDxVOL     BPLCON0     COPJMP2     HBSTRT      SERDAT      VPOSR
 BEAMCON0    BPLCON1     DDFSTOP     HCENTER     SERDATR     VPOSW
 BLTAFWM     BPLCON2     DDFSTRT     HSSTOP      SERPER      VSSTOP
 BLTALWM     BPLCON3     DENISEID    HSSTRT      SPRxCTL     VSSTRT
 BLTCON0     BPLxDAT     DIWHIGH     HTOTAL      SPRxDATA    VTOTAL
 BLTCON1     BPLxPTH     DIWSTOP     INTENA      SPRxDATB
 BLTCON0L    BPLxPTL     DIWSTRT     INTENAR     SPRxPOS
 BLTDDAT     CLXCON      DMACON      INTREQ      SPRxPTH
 BLTSIZE     CLXDAT      DMACONR     INTREQR     SPRxPTL
 BLTSIZV     COLORxx     DSKBYTR     JOY0DAT     STREQU


A Register Summary / ADKCON, ADKCONR

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
ADKCON     09E      W       P      Audio, disk, control write
ADKCONR    010      R       P      Audio, disk, control read

            BIT#   USE
            ----   ------------------------------------
            15     SET/CLR    Set/clear control bit. Determines if bits
                              written with a 1 get set or cleared. Bits
                              written with a zero are always unchanged.
            14-13  PRECOMP 1-0

                       CODE  PRECOMP VALUE
                       ----  -------------
                        00   none
                        01   140 ns
                        10   280 ns
                        11   560 ns

            12     MFMPREC       ( 1=MFM precomp 0=GCR precomp)
            11     UARTBRK        Forces a UART break (clears TXD) if true.
            10     WORDSYNC       Enables disk read synchronizing on a word
                              equal to DISK SYNC CODE, located in
                              address (3F)*2.
            09 MSBSYNC        Enables disk read synchronizing on the MSB
                              (most significant bit). Appl type GCR.
            08 FAST   Disk data clock rate control 1=fast(2us) 0=slow(4us).
                      (fast for MFM, slow for MFM or GCR)

            07 USE3PN Use audio channel 3 to modulate nothing.
            06 USE2P3 Use audio channel 2 to modulate period of channel 3.
            05 USE1P2 Use audio channel 1 to modulate period of channel 2.
            04 USE0P1 Use audio channel 0 to modulate period of channel 1.

            03 USE3VN Use audio channel 3 to modulate nothing.
            02 USE2V3 Use audio channel 2 to modulate volume of channel 3.
            01 USE1V2 Use audio channel 1 to modulate volume of channel 2.
            00 USE0V1 Use audio channel 0 to modulate volume of channel 1.

                NOTE:  If both period and volume are modulated on the
                same channel, the period and volume will be alternated.
                First word xxxxxxxx V6-V0 , Second word P15-P0 (etc)


A Register Summary / AUDxDAT

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
AUDxDAT    0AA      W       P      Audio channel x data

                 This register is the audio channel x (x=0,1,2,3)
                 DMA data buffer.  It contains 2 bytes of data that
                 are each 2's complement and are outputted
                 sequentially (with digital-to-analog conversion)
                 to the audio output pins.  (LSB = 3 MV)  The DMA
                 controller automatically transfers data to this
                 register from RAM.  The processor can also write
                 directly to this register.  When the DMA data is
                 finished (words outputted=length) and the data in
                 this register has been used, an audio channel
                 interrupt request is set.


A Register Summary / AUDxLCH, AUDxLCL

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
AUDxLCH    0A0      W      A( E )  Audio channel x location (high 3 bits,
                                       5 bits if ECS)
AUDxLCL    0A2      W       A      Audio channel x location (low 15 bits)

                 This pair of registers contains the 18 bit starting
                 address (location) of audio channel x (x=0,1,2,3) DMA
                 data. This is not a pointer register and therefore needs
                 to be reloaded only if a different memory location is to
                 be outputted.


A Register Summary / AUDxLEN

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
AUDxLEN    0A4      W       P      Audio channel x length

                 This register contains the length (number of words) of
                 audio channel x DMA data.


A Register Summary / AUDxPER

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
AUDxPER    0A6      W      P( E )  Audio channel x Period

                 This register contains the period (rate) of
                 audio channel x DMA data transfer.
                 The minimum period is 124 color clocks. This means
                 that the smallest number that should be placed in
                 this register is 124 decimal.  This corresponds to
                 a maximum sample frequency of 28.86 khz.


A Register Summary / AUDxVOL

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
AUDxVOL    0A8      W       P      Audio channel x volume

                 This register contains the volume setting for
                 audio channel x.  Bits 6,5,4,3,2,1,0 specify 65
                 linear volume levels as shown below.

                 Bit#    Use
                 ----    --------------------------
                  15-07  Not used
                  06     Forces volume to max (64 ones, no zeros)
                  05-00  Sets one of 64 levels (000000=no output
                         (111111=63 1s, one 0)


A Register Summary / BEAMCON0

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
BEAMCON0   1DC      W      A( E ) Beam counter control register (SHRES,PAL)


A Register Summary / BLTAFWM, BLTALWM

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
BLTAFWM    044      W       A      Blitter first-word mask for source A
BLTALWM    046      W       A      Blitter last-word mask for source A

                 The patterns in these two registers are ANDed with
                 the first and last words of each line of data from
                 source A into the blitter. A zero in any bit
                 overrides data from source A.  These registers
                 should be set to all 1s for fill mode or for
                 line-drawing mode.


A Register Summary / BLTCON0, BLTCON1

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
BLTCON0    040      W       A      Blitter control register 0
BLTCON1    042      W      A( E )  Blitter control register 1

                 These two control registers are used together to
                 control blitter operations.  There are two basic
                 modes, area and line, which are selected by bit
                 0 of BLTCON1, as shown below.

                    AREA MODE ("normal")
                 -------------------------
                 BIT# BLTCON0     BLTCON1
                 ---- -------     -------
                 15   ASH3        BSH3
                 14   ASH2        BSH2
                 13   ASH1        BSH1
                 12   ASA0        BSH0
                 11   USEA         X
                 10   USEB         X
                 09   USEC         X
                 08   USED         X
                 07   LF7          DOFF
                 06   LF6          X
                 05   LF5          X
                 04   LF4         EFE
                 03   LF3         IFE
                 02   LF2         FCI
                 01   LF1         DESC
                 00   LF0         LINE(=0)

                 ASH3-0  Shift value of A source
                 BSH3-0  Shift value of B source
                 USEA    Mode control bit to use source A
                 USEB    Mode control bit to use source B
                 USEC    Mode control bit to use source C
                 USED    Mode control bit to use destination D
                 LF7-0   Logic function minterm select lines
                 EFE     Exclusive fill enable
                 IFE     Inclusive fill enable
                 FCI     Fill carry input
                 DESC    Descending (decreasing address) control bit
                 LINE    Line mode control bit (set to 0)

                 LINE DRAW       LINE MODE (line draw)
                 LINE DRAW     ------------------------------
                 LINE DRAW     BIT# BLTCON0     BLTCON1
                 LINE DRAW     ---- -------     -------
                 LINE DRAW     15   START3      TEXTURE3
                 LINE DRAW     14   START2      TEXTURE2
                 LINE DRAW     13   START1      TEXTURE1
                 LINE DRAW     12   START0      TEXTURE0
                 LINE DRAW     11    1              0
                 LINE DRAW     10    0              0
                 LINE DRAW     09    1              0
                 LINE DRAW     08    1              0
                 LINE DRAW     07   LF7             0
                 LINE DRAW     06   LF6            SIGN
                 LINE DRAW     05   LF5             0 (Reserved)
                 LINE DRAW     04   LF4            SUD
                 LINE DRAW     03   LF3            SUL
                 LINE DRAW     02   LF2            AUL
                 LINE DRAW     01   LF1            SING
                 LINE DRAW     00   LF0            LINE(=1)
                 LINE DRAW
                 LINE DRAW     START3-0  Starting point of line
                 LINE DRAW               (0 thru 15 hex)

                 LINE DRAW     LF7-0     Logic function minterm
                 LINE DRAW     select lines should be preloaded
                 LINE DRAW     with 4A to select the equation
                 LINE DRAW     D=(AC+ABC).  Since A contains a
                 LINE DRAW     single bit true (8000), most bits
                 LINE DRAW     will pass the C field unchanged
                 LINE DRAW     (not A and C), but one bit will
                 LINE DRAW     invert the C field and combine it
                 LINE DRAW     with texture (A and B and not C).
                 LINE DRAW     The A bit is automatically moved
                 LINE DRAW     across the word by the hardware.
                 LINE DRAW
                 LINE DRAW     LINE   Line mode control bit (set to 1)
                 LINE DRAW     SIGN   Sign flag
                 LINE DRAW     0      Reserved for new mode
                 LINE DRAW     SING   Single bit per horizontal line for
                 LINE DRAW            use with subsequent area fill
                 LINE DRAW     SUD    Sometimes up or down (=AUD*)
                 LINE DRAW     SUL    Sometimes up or left
                 LINE DRAW     AUL    Always up or left

                 LINE DRAW     The 3 bits above select the octant
                 LINE DRAW     for line drawing:

                 LINE DRAW            OCT     SUD  SUL  AUL
                 LINE DRAW            ---     ---  ---  ---
                 LINE DRAW             0       1    1    0
                 LINE DRAW             1       0    0    1
                 LINE DRAW             2       0    1    1
                 LINE DRAW             3       1    1    1
                 LINE DRAW             4       1    0    1
                 LINE DRAW             5       0    1    0
                 LINE DRAW             6       0    0    0
                 LINE DRAW             7       1    0    0

                 LINE DRAW     The "B" source is used for
                 LINE DRAW     texturing the drawn lines.


A Register Summary / BLTCON0L

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
BLTCON0L   05A      W     A( E ) Blitter control 0, lower 8 bits (minterms)


A Register Summary / BLTDDAT

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
BLTDDAT    ---      -      ----  Blitter destination data register

                 This register holds the data resulting from each
                 word of blitter operation until it is sent to a
                 RAM destination.  This is a dummy address and
                 cannot be read by the micro.  The transfer is
                 automatic during blitter operation.


A Register Summary / BLTSIZE, BLTSIZV, BLTSIZH

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
BLTSIZE    058      W       A      Blitter start and size (window width,
                                       height)

                 This register contains the width and height of
                 the blitter operation (in line mode, width must
                 = 2, height = line length).  Writing to this
                 register will start the blitter, and should be
                 done last, after all pointers and control
                 registers have been initialized.

                 BIT#  15,14,13,12,11,10,09,08,07,06,05,04,03,02,01,00
                       -----------------------------------------------
                       h9 h8 h7 h6 h5 h4 h3 h2 h1 h0,w5 w4 w3 w2 w1 w0

                 h=height=vertical lines (10 bits=1024 lines max)
                 w=width =horizontal pixels (6 bits=64
                                      words=1024 pixels max)

                 LINE DRAW   BLTSIZE controls the line length and starts
                 LINE DRAW   the line draw when written to.  The h field
                 LINE DRAW   controls the line length (10 bits gives
                 LINE DRAW   lines up to 1024 dots long).  The w field
                 LINE DRAW   must be set to 02 for all line drawing.

BLTSIZV    05C      W      A( E ) Blitter V size (for 15 bit vertical size)
BLTSIZH    05E      W      A( E ) Blitter H size and start (for 11 bit
                                      H size)


A Register Summary / BLTxDAT

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
BLTxDAT    074      W       A     Blitter source x data register

                 This register holds source x (x=A,B,C) data for
                 use by the blitter. It is normally loaded by the
                 blitter DMA channel; however, it may also be
                 preloaded by the microprocessor.

                 LINE DRAW   BLTADAT is used as an index register
                 LINE DRAW   and must be preloaded with 8000.
                 LINE DRAW   BLTBDAT is used for texture; it must
                 LINE DRAW   be preloaded with FF if no texture
                 LINE DRAW   (solid line) is desired.


A Register Summary / BLTxMOD

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
BLTxMOD    064      W       A     Blitter modulo x

                 This register contains the modulo for blitter
                 source (x=A,B,C) or destination (x=D).  A modulo
                 is a number that is automatically added to the
                 address at the end of each line, to make the
                 address point to the start of the next line.  Each
                 source or destination has its own modulo, allowing
                 each to be a different size, while an identical
                 area of each is used in the blitter operation.

                 LINE DRAW   BLTAMOD and BLTBMOD are used as slope
                 LINE DRAW   storage registers and must be preloaded
                 LINE DRAW   with the values (4Y-4X) and (4Y)
                 LINE DRAW   respectively.  Y/X= line slope.
                 LINE DRAW   BLTCMOD and BLTDMOD must both be
                 LINE DRAW   preloaded with the width (in bytes)
                 LINE DRAW   of the image into which the line is
                 LINE DRAW   being drawn (normally two times the
                 LINE DRAW   screen width in words).


A Register Summary / BLTxPTH, BLTxPTL

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
BLTxPTH    050      W      A( E ) Blitter pointer to x (high 3 bits,
                                      5 bits if ECS)
BLTxPTL    052      W       A     Blitter pointer to x (low 15 bits)

                 This pair of registers contains the 18-bit address
                 of blitter source (x=A,B,C) or destination (x=D)
                 DMA data.  This pointer must be preloaded with the
                 starting address of the data to be processed by
                 the blitter. After the blitter is finished, it
                 will contain the last data address (plus increment
                 and modulo).

                 LINE DRAW   BLTAPTL is used as an accumulator
                 LINE DRAW   register and must be preloaded with
                 LINE DRAW   the starting value of (2Y-X) where
                 LINE DRAW   Y/X is the line slope.  BLTCPT and
                 LINE DRAW   BLTDPT (both H and L) must be
                 LINE DRAW   preloaded with the starting address
                 LINE DRAW   of the line.


A Register Summary / BPL1MOD, BPL2MOD

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
BPL1MOD    108      W       A     Bitplane modulo (odd planes)
BPL2MOD    10A      W       A     Bitplane modulo (even planes)

                 These registers contain the modulos for the odd
                 and even bitplanes.  A modulo is a number that is
                 automatically added to the address at the end of
                 each line, so that the address then points to the
                 start of the next line.
                 Since they have separate modulos, the odd and even
                 bitplanes may have sizes that are different from
                 each other, as well as different from the display
                 window size.


A Register Summary / BPLCON0, BPLCON1, BPLCON2, BPLCON3

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
BPLCON0    100      W     A D( E ) Bitplane control register (misc.
                                       control bits)
BPLCON1    102      W       D      Bitplane control register
                                       (horizontal scroll control)
BPLCON2    104      W       D( E ) Bitplane control register
                                       (video priority control)

                 These registers control the operation of the
                 bitplanes and various aspects of the display.

                 BIT#     BPLCON0    BPLCON1    BPLCON2
                 ----     --------   --------   --------
                 15       HIRES       X           X
                 14       BPU2        X           X
                 13       BPU1        X           X
                 12       BPU0        X           X
                 11       HOMOD       X           X
                 10       DBLPF       X           X
                 09       COLOR       X           X
                 08       GAUD        X           X
                 07        X         PF2H3        X
                 06        X         PF2H2      PF2PRI
                 05        X         PF2H1      PF2P2
                 04        X         PF2H0      PF2P1
                 03       LPEN       PF1H3      PF2P0
                 02       LACE       PF1H2      PF1P2
                 01       ERSY       PF1H1      PF1P1
                 00        X         PF1H0      PF1P0

               HIRES=High-resolution (70 ns pixels)
               BPU  =Bitplane use code 000-110 (NONE through 6 inclusive)
               HOMOD=Hold-and-modify mode (1 = Hold-and-modify mode (HAM);
                       0 = Extra Half Brite (EHB) if HAM=0 and BPU=6
                       and DBLPF=0 then bitplane 6 controls an intensity
                       reduction in the other five bitplanes)
               DBLPF=Double playfield (PF1=odd PF2=even bitplanes)
               COLOR=Composite video COLOR enable
               GAUD=Genlock audio enable (muxed on BKGND pin
                       during vertical blanking
               LPEN =Light pen enable (reset on power up)
               LACE =Interlace enable (reset on power up)
               ERSY =External resync (HSYNC, VSYNC pads become
                       inputs) (reset on power up)
               PF2PRI=Playfield 2 (even planes) has priority over
                       (appears in front of) playfield 1
                       (odd planes).
               PF2P=Playfield 2 priority code (with respect
                       to sprites)
               PF1P=Playfield 1 priority code (with respect
                       to sprites)
               PF2H=Playfield 2 horizontal scroll code
               PF1H=Playfield 1 horizontal scroll code

BPLCON3    106      W      D( E ) Bitplane control (enhanced features)


A Register Summary / BPLxDAT

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
BPLxDAT    110      W       D     Bitplane x data (parallel-to-serial
                                      convert)

                 These registers receive the DMA data fetched from
                 RAM by the bitplane address pointers described
                 above.  They may also be written by either
                 microprocessor.  They act as a six-word parallel-
                 to-serial buffer for up to six memory bitplanes
                 (x=1-6).  The parallel-to-serial conversion is
                 triggered whenever bitplane #1 is written,
                 indicating the completion of all bitplanes for
                 that word (16 pixels).  The MSB is output first,
                 and is, therefore, always on the left.


A Register Summary / BPLxPTH, BPLxPTL

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
BPLxPTH    0E0      W       A     Bitplane x pointer (high 3 bits)
BPLxPTL    0E2      W       A     Bitplane x pointer (low 15 bits)

                 This pair of registers contains the 18-bit pointer to
                 the address of bitplane x (x=1,2,3,4,5,6) DMA data.
                 This pointer must be reinitialized by the processor
                 or copper to point to the beginning of bitplane data
                 every vertical blank time.


A Register Summary / CLXCON

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
CLXCON     098      W       D     Collision control

                 This register controls which bitplanes are
                 included (enabled) in collision detection and
                 their required state if included.  It also controls
                 the individual inclusion of odd-numbered sprites
                 in the collision detection by logically OR-ing
                 them with their corresponding even-numbered sprite.

                 BIT#  FUNCTION  DESCRIPTION
                 ----  --------  ------------------------------
                 15    ENSP7     Enable sprite 7 (ORed with sprite 6)
                 14    ENSP5     Enable sprite 5 (ORed with sprite 4)
                 13    ENSP3     Enable sprite 3 (ORed with sprite 2)
                 12    ENSP1     Enable sprite 1 (ORed with sprite 0)
                 11    ENBP6     Enable bitplane 6 (match required
                                 for collision)
                 10    ENBP5     Enable bitplane 5 (match required
                                 for collision)
                 09    ENBP4     Enable bitplane 4 (match required
                                 for collision)
                 08    ENBP3     Enable bitplane 3 (match required
                                 for collision)
                 07    ENBP2     Enable bitplane 2 (match required
                                 for collision)
                 06    ENBP1     Enable bitplane 1 (match required
                                 for collision)
                 05    MVBP6     Match value for bitplane 6 collision
                 04    MVBP5     Match value for bitplane 5 collision
                 03    MVBP4     Match value for bitplane 4 collision
                 02    MVBP3     Match value for bitplane 3 collision
                 01    MVBP2     Match value for bitplane 2 collision
                 00    MVBP1     Match value for bitplane 1 collision

                       NOTE:  Disabled bitplanes cannot prevent
                       collisions.  Therefore if all bitplanes are
                       disabled, collisions will be continuous,
                       regardless of the match values.


A Register Summary / CLXDAT

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
CLXDAT     00E      R       D     Collision data register (read and clear)

                 This address reads (and clears) the collision
                 detection register. The bit assignments are below.

                 NOTE: Playfield 1 is all odd-numbered enabled
                       bitplanes.  Playfield 2 is all even-numbered
                       enabled bitplanes

                 BIT#   COLLISIONS REGISTERED
                 -----  --------------------------
                 15     not used
                 14     Sprite 4 (or 5) to sprite 6 (or 7)
                 13     Sprite 2 (or 3) to sprite 6 (or 7)
                 12     Sprite 2 (or 3) to sprite 4 (or 5)
                 11     Sprite 0 (or 1) to sprite 6 (or 7)
                 10     Sprite 0 (or 1) to sprite 4 (or 5)
                 09     Sprite 0 (or 1) to sprite 2 (or 3)
                 08     Playfield 2 to sprite 6 (or 7)
                 07     Playfield 2 to sprite 4 (or 5)
                 06     Playfield 2 to sprite 2 (or 3)
                 05     Playfield 2 to sprite 0 (or 1)
                 04     Playfield 1 to sprite 6 (or 7)
                 03     Playfield 1 to sprite 4 (or 5)
                 02     Playfield 1 to sprite 2 (or 3)
                 01     Playfield 1 to sprite 0 (or 1)
                 00     Playfield 1 to playfield 2


A Register Summary / COLORxx

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
COLORxx    180      W       D     Color table xx

                 There are 32 of these registers (xx=00-31) and they
                 are sometimes collectively called the "color
                 palette."  They contain 12-bit codes representing
                 red, green, and blue colors for RGB systems.
                 One of these registers at a time is selected
                 (by the BPLxDAT serialized video code)
                 for presentation at the RGB video output pins.
                 The table below shows the color register bit usage.

                 BIT# 15,14,13,12,11,10,09,08,07,06,05,04,03,02,01,00
                      ----------- ----------- ----------- -----------
                 RGB  X  X  X  X  R3 R2 R1 R0 G3 G2 G1 G0 B3 B2 B1 B0

                 B=blue, G=green, R=red,


A Register Summary / COP1LCH, COP1LCL, COP2LCH, COP2LCL

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
COP1LCH    080      W      A( E ) Copper first location register
                                      (high 3 bits, high 5 bits if ECS)
COP1LCL    082      W       A     Copper first location register
                                      (low 15 bits)
COP2LCH    084      W      A( E ) Copper second location register
                                      (high 3 bits, high 5 bits if ECS)
COP2LCL    086      W       A     Copper second location register
                                      (low 15 bits)

                 These registers contain the jump addresses
                 described above.


A Register Summary / COPCON

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
COPCON     02E      W      A( E ) Copper control register

                 This is a 1-bit register that when set true, allows
                 the Copper to access the blitter hardware. This
                 bit is cleared by power-on reset, so that the Copper
                 cannot access the blitter hardware. See Appendix C
                 for ECS operation.

                 BIT#    NAME      FUNCTION
                 ----    -------   ------------------
                  01     CDANG     Copper danger mode. Allows Copper
                                   access to blitter if true.


A Register Summary / COPINS

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
COPINS     08C      W       A     Copper instruction fetch identify

                 This is a dummy address that is generated by the
                 Copper whenever it is loading instructions into
                 its own instruction register. This actually occurs
                 every Copper cycle except for the second (IR2)
                 cycle of the MOVE instruction. The three types
                 of instructions are shown below.

                 MOVE    Move immediate to destination.
                 WAIT    Wait until beam counter is equal to, or
                         greater than.  (keeps Copper off of bus
                         until beam position has been reached).
                 SKIP    Skip if beam counter is equal to or greater
                         than (skips following MOVE instruction unless
                         beam position has been reached).

                           MOVE         WAIT UNTIL      SKIP IF
                         --------       -----------    ------------
                 BIT#    IR1   IR2      IR1    IR2     IR1     IR2
                 ----    ----  ----     ----   ----    ----    ----
                 15       X    RD15     VP7    BFD *   VP7    BFD *
                 14       X    RD14     VP6    VE6     VP6    VE6
                 13       X    RD13     VP5    VE5     VP5    VE5
                 12       X    RD12     VP4    VE4     VP4    VE4
                 11       X    RD11     VP3    VE3     VP3    VE3
                 10       X    RD10     VP2    VE2     VP2    VE2
                 09       X    RD09     VP1    VE1     VP1    VE1
                 08      DA8   RD08     VP0    VE0     VP0    VE0
                 07      DA7   RD07     HP8    HE8     HP8    HE8
                 06      DA6   RD06     HP7    HE7     HP7    HE7
                 05      DA5   RD05     HP6    HE6     HP6    HE6
                 04      DA4   RD04     HP5    HE5     HP5    HE5
                 03      DA3   RD03     HP4    HE4     HP4    HE4
                 02      DA2   RD02     HP3    HE3     HP3    HE3
                 01      DA1   RD01     HP2    HE2     HP2    HE2
                 00       0    RD00      1      0       1      1

                 IR1=First instruction register
                 IR2=Second instruction register
                 DA =Destination address for MOVE instruction.  Fetched
                     during IR1 time, used during IR2 time on RGA bus.
                 RD =RAM data moved by MOVE instruction at IR2 time
                     directly from RAM to the address given by the
                     DA field.
                 VP =Vertical beam position comparison bit.
                 HP =Horizontal beam position comparison bit.
                 VE =Enable comparison (mask bit).
                 HE =Enable comparison (mask bit).

                * NOTE BFD=Blitter finished disable. When this bit
                           is true, the Blitter Finished flag will
                           have no effect on the Copper. When this
                           bit is zero, the Blitter Finished flag
                           must be true (in addition to the rest of
                           the bit comparisons) before the Copper
                           can exit from its wait state or skip
                           over an instruction.  Note that the V7
                           comparison cannot be masked.

                 The Copper is basically a two-cycle machine that
                 requests the bus only during odd memory cycles
                 (4 memory cycles per instruction).  This prevents
                 collisions with display, audio, disk, refresh, and
                 sprites, all of which use only even cycles.  It
                 therefore needs (and has) priority over only the
                 blitter and microprocessor.

                 There are only three types of instructions:
                 MOVE immediate, WAIT until, and SKIP if.  All
                 instructions (except for WAIT) require two bus
                 cycles (and two instruction words).  Since only
                 the odd bus cycles are requested, four memory
                 cycle times are required per instruction
                 (memory cycles are 280 ns.)

                 There are two indirect jump registers,  COP1LC  and
                  COP2LC .  These are 18-bit pointer registers whose
                 contents are used to modify the program counter for
                 initialization or jumps.  They are transferred to
                 the program counter whenever strobe addresses
                  COPJMP1  or  COPJMP2  are written.  In addition,
                  COP1LC  is automatically used at the beginning of
                 each vertical blank time.

                 It is important that one of the jump registers be
                 initialized and its jump strobe address hit after
                 power-up but before Copper DMA is initialized.
                 This insures a determined startup address and state.


A Register Summary / COPJMP1, COPJMP2

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
COPJMP1    088      S       A     Copper restart at first location
COPJMP2    08A      S       A     Copper restart at second location

                 These addresses are strobe addresses.  When written
                 to, they cause the Copper to jump indirect using
                 the address contained in the first or second
                 location registers described below. The Copper
                 itself can write to these addresses, causing its
                 own jump indirect.


A Register Summary / DDFSTOP, DDFSTRT

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
DDFSTOP    094      W       A    Display data fetch stop (horiz. position)
DDFSTRT    092      W       A    Display data fetch start (horiz. position)

                 These registers control the horizontal timing of the
                 beginning and end of the bitplane DMA display data
                 fetch.  The vertical bitplane DMA timing is identical
                 to the display windows described above.
                 The bitplane modulos are dependent on the bitplane
                 horizontal size and on this data-fetch window size.

                 Register bit assignment
                 -------------------------
                 BIT#  15,14,13,12,11,10,09,08,07,06,05,04,03,02,01,00
                       -----------------------------------------------
                 USE    X  X  X  X  X  X  X  X H8 H7 H6 H5 H4 H3  X  X

                  (Always set X bits to 0 to maintain upward compatibility)

                 The tables below show the start and stop timing for
                 different register contents.

                    DDFSTRT (left edge of display data fetch)
                    ----------------------------------------
                         PURPOSE        H8,H7,H6,H5,H4
                     -----------------  --------------
                     Extra wide (max) *  0  0  1  0  1
                     Wide                0  0  1  1  0
                     Normal              0  0  1  1  1
                     Narrow              0  1  0  0  0

                     DDFSTOP (right edge of display data fetch)
                     ------------------------------------------
                          PURPOSE        H8,H7,H6,H5,H4
                     ------------------  --------------
                     Narrow               1  1  0  0  1
                     Normal               1  1  0  1  0
                     Wide (max)           1  1  0  1  1


A Register Summary / DENISEID

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
DENISEID   07C      R      D( E ) Chip revision level for Denise
                                      (video out chip)


A Register Summary / DIWHIGH, DIWSTOP, DIWSTRT

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
DIWHIGH    1E4      W     A,D( E ) Display window -  upper bits for
                                       start, stop

DIWSTOP    090      W       A      Display window stop (lower right
                                       vertical-horizontal position)
DIWSTRT    08E      W       A      Display window start (upper left
                                       vertical-horizontal position)

                 These registers control display window size and position
                 by locating the upper left and lower right corners.

                 BIT# 15,14,13,12,11,10,09,08,07,06,05,04,03,02,01,00
                      -----------------------------------------------
                 USE  V7 V6 V5 V4 V3 V2 V1 V0 H7 H6 H5 H4 H3 H2 H1 H0

                 DIWSTRT is vertically restricted to the upper 2/3
                 of the display (V8=0) and horizontally restricted to
                 the left 3/4 of the display (H8=0).

                 DIWSTOP is vertically restricted to the lower 1/2
                 of the display (V8=/=V7) and horizontally restricted
                 to the right 1/4 of the display (H8=1).


A Register Summary / DMACON, DMACONR

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
DMACON     096      W     A D P   DMA control write (clear or set)
DMACONR    002      R     A   P   DMA control (and blitter status) read

                 This register controls all of the DMA channels and
                 contains blitter DMA status bits.

                 BIT#  FUNCTION    DESCRIPTION
                 ----  ---------   -----------------------------------
                 15    SET/CLR     Set/clear control bit. Determines
                                   if bits written with a 1 get set or
                                   cleared.  Bits written with a zero
                                   are unchanged.
                 14    BBUSY       Blitter busy status bit (read only)
                 13    BZERO       Blitter logic  zero status bit
                                   (read only).
                 12    X
                 11    X
                 10    BLTPRI      Blitter DMA priority
                                   (over CPU micro) (also called
                                   "blitter nasty") (disables /BLS
                                   pin, preventing micro from
                                   stealing any bus cycles while
                                   blitter DMA is running).
                 09    DMAEN       Enable all DMA below
                 08    BPLEN       Bitplane DMA enable
                 07    COPEN       Copper DMA enable
                 06    BLTEN       Blitter DMA enable
                 05    SPREN       Sprite DMA enable
                 04    DSKEN       Disk DMA enable
                 03    AUD3EN      Audio channel 3 DMA enable
                 02    AUD2EN      Audio channel 2 DMA enable
                 01    AUD1EN      Audio channel 1 DMA enable
                 00    AUD0EN      Audio channel 0 DMA enable


A Register Summary / DSKBYTR

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
DSKBYTR    01A      R       P     Disk data byte and status read

                 This register is the disk-microprocessor data
                 buffer.  Data from the disk (in read mode) is
                 loaded into this register one byte at a time, and
                 bit 15 (DSKBYT) is set true.

                 BIT#
                 ----  ---------  --------------------------------
                 15    DSKBYT     Disk byte ready (reset on read)
                 14    DMAON      Mirror of bit 15 (DMAEN) in  DSKLEN ,
                                  ANDed with Bit09 (DMAEN) in  DMACON
                 13    DISKWRITE  Mirror of bit 14 (WRITE) in  DSKLEN
                 12    WORDEQUAL  This bit true only while the
                                   DSKSYNC  register equals the data
                                  from disk.
                 11-08  X         Not used
                 07-00 DATA       Disk byte data


A Register Summary / DSKDAT, DSKDATR

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
DSKDAT     026      W       P     Disk DMA data write
DSKDATR    008      ER      P     Disk DMA data read (early read dummy
                                      address)

                 This register is the disk DMA data buffer. It
                 contains two bytes of data that are either sent
                 (written) to or received (read) from the disk.
                 The write mode is enabled by bit 14 of the LENGTH
                 register. The DMA controller automatically
                 transfers data to or from this register and RAM,
                 and when the DMA data is finished (length=0) it
                 causes a disk block interrupt. See interrupts below.


A Register Summary / DSKLEN

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
DSKLEN     024      W       P     Disk length

                 This register contains the length (number of words)
                 of disk DMA data. It also contains two control
                 bits, a DMA enable bit, and a DMA direction
                 (read/write) bit.

                 BIT#  FUNCTION      DESCRIPTION
                 ----  -----------   --------------------------------
                 15    DMAEN         Disk DMA enable
                 14    WRITE         Disk write (RAM to disk) if 1
                 13-0  LENGTH        Length (# of words) of DMA data.


A Register Summary / DSKPTH, DSKPTL

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
DSKPTH     020      W      A( E ) Disk pointer (high 3 bits,
                                      high 5 bits if ECS)
DSKPTL     022      W       A     Disk pointer (low 15 bits)

                 This pair of registers contains the 18-bit
                 address of disk DMA data. These address registers
                 must be initialized by the processor or Copper
                 before disk DMA is enabled.


A Register Summary / DSKSYNC

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
DSKSYNC    07E      W       P     Disk sync register

                 holds the match code for disk read synchronization.
                 See  ADKCON  bit 10.


A Register Summary / HBSTOP, HBSTRT, HCENTER, HSSTOP, HSSTRT, HTOTAL

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
HBSTOP     1C6      W      A( E ) Horizontal line position for HBLANK stop
HBSTRT     1C4      W      A( E ) Horizontal line position for HBLANK start
HCENTER    1E2      W      A( E ) Horizontal position for Vsync on interlace
HSSTOP     1C2      W      A( E ) Horizontal line position for HSYNC stop
HSSTRT     1DE      W      A( E ) Horizontal sync start (VARHSY)
HTOTAL     1C0      W      A( E ) Highest number count, horiz. line
                                     (VARBEAMEN=1)


A Register Summary / INTENA, INTENAR

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
INTENA     09A      W       P    Interrupt enable bits (clear or set bits)
INTENAR    01C      R       P    Interrupt enable bits (read)

                 This register contains interrupt enable bits. The bit
                 assignment for both the request and enable registers
                 is given below.

                 BIT#  FUNCT  LEVEL DESCRIPTION
                 ----  ------ ----- ----------------------------------
                 15    SET/CLR     Set/clear control bit. Determines if
                                   bits written with a 1 get set or
                                   cleared. Bits written with a zero
                                   are always unchanged.
                 14    INTEN       Master interrupt (enable only,
                                     no request)
                 13    EXTER   6   External interrupt
                 12    DSKSYN  5   Disk sync register ( DSKSYNC )
                                     matches disk data
                 11    RBF     5   Serial port receive buffer full
                 10    AUD3    4   Audio channel 3 block finished
                 09    AUD2    4   Audio channel 2 block finished
                 08    AUD1    4   Audio channel 1 block finished
                 07    AUD0    4   Audio channel 0 block finished
                 06    BLIT    3   Blitter finished
                 05    VERTB   3   Start of vertical blank
                 04    COPER   3   Copper
                 03    PORTS   2   I/O ports and timers
                 02    SOFT    1   Reserved for software-initiated
                                     interrupt
                 01    DSKBLK  1   Disk block finished
                 00    TBE     1   Serial port transmit buffer empty


A Register Summary / INTREQ, INTREQR

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
INTREQ     09C      W       P   Interrupt request bits (clear or set)
INTREQR    01E      R       P   Interrupt request bits (read)

                 This register contains interrupt request bits (or
                 flags).  These bits may be polled by the processor;
                 if enabled by the bits listed in the above register,
                 they may cause processor interrupts.  Both a set and
                 clear operation are required to load arbitrary data
                 into this register.  These status bits are not
                 automatically reset when the interrupt is serviced,
                 and must be reset when desired by writing to this
                 address.  The bit assignments are identical to the
                  enable register .


A Register Summary / JOY0DAT, JOY1DAT

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
JOY0DAT    00A      R       D     Joystick-mouse 0 data (left vertical,
                                      horizontal)
JOY1DAT    00C      R       D     Joystick-mouse 1 data (right vertical,
                                      horizontal)

                 These addresses each read a pair of 8-bit mouse
                 counters.  0=left controller pair, 1=right
                 controller pair (four counters total).  The bit
                 usage for both left and right addresses is shown
                 below.  Each counter is clocked by signals from
                 two controller pins.  Bits 1 and 0 of each counter
                 may be read to determine the state of these two
                 clock pins.  This allows these pins to double as
                 joystick switch inputs.

                 Mouse counter usage:
                 (pins 1,3=Yclock, pins 2,4=Xclock)

                 BIT# 15,14,13,12,11,10,09,08  07,06,05,04,03,02,01,00
                      -----------------------  -----------------------
                 0DAT Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0  X7 X6 X5 X4 X3 X2 X1 X0
                 1DAT Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0  X7 X6 X5 X4 X3 X2 X1 X0

                 The following table shows the mouse/joystick
                 connector pin usage.  The pins (and their functions)
                 are sampled (multiplexed) into the DENISE chip
                 during the clock times shown in the table.
                 This table is for reference only and should
                 not be needed by the programmer.  (Note that the
                 joystick functions are all "active low" at the
                 connector pins.)

                                            Sampled by DENISE
                 Conn   Joystick  Mouse     -----------------
                 Pin    Function  Function  Pin  Name  Clock
                 ----   --------  --------  ---  ----  -----
                 L1     FORW*        Y      38   M0V at CCK
                 L3     LEFT*        YQ     38   M0V at CCK*
                 L2     BACK*        X       9   M0H at CCK
                 L4     RIGH*        XQ      9   M0H at CCK*
                 R1     FORW*        Y      39   M1V at CCK
                 R3     LEFT*        YQ     39   M1V at CCK*
                 R2     BACK*        X       8   M1H at CCK
                 R4     RIGH*        XQ      8   M1H at CCK*

                 After being sampled, these connector pin signals
                 are used in quadrature to clock the mouse counters.
                 The LEFT and RIGHT joystick functions (active high)
                 are directly available on the Y1 and X1 bits of
                 each counter.  In order to recreate the FORWARD
                 and BACK joystick functions, however, it is
                 necessary to logically combine (exclusive OR)
                 the lower two bits of each counter.
                 This is illustrated in the following table.

                 To detect              Read these counter bits
                 --------               ----------------
                 Forward                 Y1 xor Y0 (BIT#09 xor BIT#08)
                 Left                    Y1
                 Back                    X1 xor X0 (BIT#01 xor BIT#00)
                 Right                   X1


A Register Summary / JOYTEST

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
JOYTEST    036      W       D     Write to all four joystick-mouse counters
                                  at once.

                 Mouse counter write test data:

                 BIT#  15,14,13,12,11,10,09,08  07,06,05,04,03,02,01,00
                       -----------------------  -----------------------
                 0DAT  Y7 Y6 Y5 Y4 Y3 Y2 xx xx  X7 X6 X5 X4 X3 X2 xx xx
                 1DAT  Y7 Y6 Y5 Y4 Y3 Y2 xx xx  X7 X6 X5 X4 X3 X2 xx xx


A Register Summary / POT0DAT, POT1DAT

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
POT0DAT    012      R      P( E ) Pot counter data left pair (vert,horiz.)
POT1DAT    014      R      P( E ) Pot counter data right pair (vert,horiz.)

                 These addresses each read a pair of 8-bit pot counters.
                 (Four counters total.) The bit assignment for both
                 addresses is shown below. The counters are stopped by
                 signals from two controller connectors (left-right)
                 with two pins each.

                 BIT#  15,14,13,12,11,10,09,08  07,06,05,04,03,02,01,00
                 ----- ------------------------ -----------------------
                 RIGHT Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0  X7 X6 X5 X4 X3 X2 X1 X0
                 LEFT  Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0  X7 X6 X5 X4 X3 X2 X1 X0

                           CONNECTORS                PAULA
                         --------------------    ----------------
                         Loc. Dir. Sym   Pin     Pin#    Pin Name
                         ----  --- ----  ----    ----    --------
                         RIGHT  Y   RY    9      36      (POT1Y)
                         RIGHT  X   RX    5      35      (POT1X)
                         LEFT   Y   LY    9      33      (POT0Y)
                         LEFT   X   LX    5      32      (POT0X)


A Register Summary / POTGO, POTGOR

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
POTGO      034      W       P     Pot port data write and start.

POTGOR     016      R       P     Pot port data read
                                      (formerly called POTINP).

                 This register controls a 4-bit bi-directional I/O port
                 that shares the same four pins as the four pot counters
                 above.

                 BIT#  FUNCT   DESCRIPTION
                 ----  ---------------------------------------
                 15    OUTRY   Output enable for Paula pin 36
                 14    DATRY   I/O data Paula pin 36
                 13    OUTRX   Output enable for Paula pin 35
                 12    DATRX   I/O data Paula pin 35
                 11    OUTLY   Output enable for Paula pin 33
                 10    DATLY   I/O data Paula pin 33
                 09    OUTLX   Output enable for Paula pin 32
                 08    DATLX   I/O data Paula pin 32
                 07-01   0     Reserved for chip ID code (presently 0)
                 00    START   Start pots (dump capacitors, start
                                 counters)


A Register Summary / REFPTR

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
REFPTR     028      W       A      Refresh pointer

                 This register is used as a dynamic RAM refresh
                 address generator. It is writeable for test
                 purposes only, and should never be written by
                 the microprocessor.


A Register Summary / SERDAT, SERDATR

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
SERDAT     030      W       P      Serial port data and stop bits write
                                       (transmit data buffer)

                 This address writes data to a transmit data buffer.
                 Data from this buffer is moved into a serial shift
                 register for output transmission whenever it is
                 empty.  This sets the interrupt request TBE
                 (transmit buffer empty). A stop bit must be
                 provided as part of the data word. The length of
                 the data word is set by the position of the stop
                 bit.

                 BIT# 15,14,13,12,11,10,09,08,07,06,05,04,03,02,01,00
                      -----------------------------------------------
                 USE   0  0  0  0  0  0  S D8 D7 D6 D5 D4 D3 D2 D1 D0

                 Note:  S = stop bit = 1, D = data bits.

SERDATR    018      R       P      Serial port data and status read
                                       (receive data buffer)

                 This address reads data from a receive data buffer.
                 Data in this buffer is loaded from a receiving
                 shift register whenever it is full.  Several
                 interrupt request bits are also read at this
                 address, along with the data, as shown below.

                 BIT#  SYM          FUNCTION
                 ----  ----         -----------------------
                 15    OVRUN        Serial port receiver overrun.
                                    Reset by resetting bit 11 of
                                     INTREQ .
                 14    RBF          Serial port receive buffer full
                                    (mirror).
                 13    TBE          Serial port transmit buffer
                                    empty (mirror).
                 12    TSRE         Serial port transmit shift
                                    register empty.
                                    Reset by loading into buffer.
                 11    RXD          RXD pin receives UART serial
                                    data for direct bit test by
                                    the microprocessor.
                 10     0           Not used
                 09    STP          Stop bit
                 08  STP-DB8        Stop bit if LONG, data bit if
                                    not.
                 07    DB7          Data bit
                 06    DB6          Data bit
                 05    DB5          Data bit
                 04    DB4          Data bit
                 03    DB3          Data bit
                 02    DB2          Data bit
                 01    DB1          Data bit
                 00    DB0          Data bit


A Register Summary / SERPER

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
SERPER     032      W       P      Serial port period and control

                 This register contains the control bit LONG referred to
                 above, and a 15-bit number defining the serial port
                 baud rate. If this number is N, then the baud rate is
                 1 bit every (N+1)*.2794  microseconds.

                 BIT#   SYM     FUNCTION
                 -----  ----    ---------------
                 15     LONG    Defines serial receive as 9-bit word.
                 14-00  RATE    Defines baud rate=1/((N+1)*.2794 microsec.)


A Register Summary / SPRxCTL, SPRxPOS

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
SPRxCTL    142      W     A D( E ) Sprite x vert stop position and
                                       control data
SPRxPOS    140      W      A D     Sprite x vert-horiz start position data

                 These two registers work together as position, size and
                 feature sprite-control registers.  They are usually loaded
                 by the sprite DMA channel during horizontal blank;
                 however, they may be loaded by either processor at any
                 time.  SPRxPOS register:

                 BIT#   SYM      FUNCTION
                 ----   ----     -----------------------------
                 15-08  SV7-SV0  Start vertical value. High bit(SV8) is
                                 in SPRxCTL register below.
                 07-00  SH8-SH1  Start horizontal value. Low bit(SH0) is
                                 in SPRxCTL register below.

                 SPRxCTL register (writing this address disables sprite
                                   horizontal comparator circuit):

                 BIT#    SYM       FUNCTION
                 ----    --------  -----------------------------
                 15-08   EV7-EV0   End (stop) vertical value low 8 bits
                 07      ATT       Sprite attach control bit (odd sprites)
                 06-04    X        Not used
                 02      SV8       Start vertical value high bit
                 01      EV8       End (stop) vertical value high bit
                 00      SH0       Start horizontal value low bit


A Register Summary / SPRxDATA, SPRxDATB

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
SPRxDATA   144      W       D     Sprite x image data register A
SPRxDATB   146      W       D     Sprite x image data register B

                 These registers buffer the sprite image data. They are
                 usually loaded by the sprite DMA channel but may be
                 loaded by either processor at any time.  When a
                 horizontal comparison occurs, the buffers are dumped
                 into shift registers and serially outputted to the
                 display, MSB first on the left.

                 NOTE: Writing to the A buffer enables (arms) the sprite.
                 Writing to the SPRxCTL register disables the sprite.
                 If enabled, data in the A and B buffers will be outputted
                 whenever the beam counter equals the sprite horizontal
                 position value in the  SPRxPOS  register.


A Register Summary / SPRxPTH, SPRxPTL

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
SPRxPTH    120      W       A     Sprite x pointer (high 3 bits)
SPRxPTL    122      W       A     Sprite x pointer (low 15 bits)

                 This pair of registers contains the 18-bit address
                 of sprite x (x=0,1,2,3,4,5,6,7) DMA data. These address
                 registers must be initialized by the processor or Copper
                 every vertical blank time.


A Register Summary / STREQU, STRHOR, STRLONG, STRVBL

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
STREQU     038      S       D     Strobe for horizontal sync with VB
                                      and EQU
STRHOR     03C      S      D P    Strobe for horizontal sync
STRLONG    03E      S      D( E ) Strobe for identification of long
                                      horizontal line

                 One of the first three strobe addresses above is
                 placed on the destination address bus during the
                 first refresh time slot.  The fourth strobe shown
                 above is used during the second refresh time slot of
                 every other line to identify lines with long counts
                 (228).  There are four refresh time slots, and any
                 not used for strobes will leave a null (FF) address
                 on the destination address bus.

STRVBL     03A      S       D     Strobe for horizontal sync with VB
                                  (vertical blank)


A Register Summary / VBSTOP, VBSTRT

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
VBSTOP     1CE      W      A( E ) Vertical line for VBLANK stop
VBSTRT     1CC      W      A( E ) Vertical line for VBLANK start


A Register Summary / VHPOSR, VHPOSW

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
VHPOSR     006      R       A     Read vertical and horizontal position of
                                      beam or lightpen
VHPOSW     02C      W       A     Write vertical and horizontal position
                                      of beam or lightpen

                 BIT# 15,14,13,12,11,10,09,08,07,06,05,04,03,02,01,00
                      -----------------------------------------------
                 USE  V7 V6 V5 V4 V3 V2 V1 V0,H8 H7 H6 H5 H4 H3 H2 H1

                 RESOLUTION = 1/160 of screen width (280 ns)


A Register Summary / VPOSR, VPOSW

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
VPOSR      004      R      A( E ) Read vertical most significant bit
                                      (and frame flop)
VPOSW      02A      W       A     Write vertical most significant bit
                                      (and frame flop)

                 BIT# 15,14,13,12,11,10,09,08,07,06,05,04,03,02,01,00
                      -----------------------------------------------
                 USE  LOF-- -- -- -- -- -- --,-- -- -- -- -- -- -- V8

                 LOF=Long frame (auto toggle control bit in  BPLCON0 )


A Register Summary / VSSTOP, VSSTRT, VTOTAL

                          Agnus/
                  Read/   Denise/
Register Address  Write   Paula         Function
-------- -------  -----   -------       --------
VSSTOP     1CA      W      A( E ) Vertical line position for VSYNC stop
VSSTRT     1E0      W      A( E ) Vertical sync start   (VARVSY)
VTOTAL     1C8      W      A( E ) Highest numbered vertical line
                                      (VARBEAMEN=1)


Amiga® Hardware Reference Manual: 2 Coprocessor Hardware

In this chapter, you will learn how to use the Amiga's graphics
coprocessor (or Copper) and its simple instruction set to organize
mid-screen register value modifications and pointer register set-up during
the  vertical blanking  interval. The chapter shows how to organize Copper
instructions into Copper lists, how to use Copper lists in interlaced
mode, and how to use the Copper with the blitter. The Copper is discussed
in this chapter in a general fashion. The chapters that deal with
playfields, sprites, audio, and the blitter contain more specific
suggestions for using the Copper.

About the Copper              Putting Together a Copper Instruction List
What is a Copper Instruction? Starting and Stopping the Copper
The MOVE Instruction          Advanced Topics
The WAIT Instruction          Summary of Copper Instructions
Using the Copper Registers


2 Coprocessor Hardware / About the Copper

The Copper is a general purpose coprocessor that resides in one of the
Amiga's custom chips. It retrieves its instructions via direct memory
access (DMA). The Copper can control nearly the entire graphics system,
freeing the 680x0 to execute program logic; it can also directly affect
the contents of most of the chip control registers. It is a very powerful
tool for directing mid-screen modifications in graphics displays and for
directing the register changes that must occur during the
 vertical blanking  periods.  Among other things, it can control register
updates, reposition sprites, change the color palette, update the audio
channels, and control the blitter.

One of the features of the Copper is its ability to  WAIT  for a specific
video beam position, then  MOVE  data into a system register. During the
 WAIT  period, the Copper examines the contents of the video beam position
counter directly. This means that while the Copper is waiting for the beam
to reach a specific position, it does not use the memory bus at all.
Therefore, the bus is freed for use by the other DMA channels or by the
680x0.

When the  WAIT  condition has been satisfied, the Copper steals memory
cycles from either the blitter or the 680x0 to move the specified data
into the selected special-purpose register.

The Copper is a two-cycle processor that requests the bus only during
odd-numbered memory cycles. This prevents collision with audio, disk,
refresh, sprites, and most low resolution display DMA access, all of which
use only the even-numbered memory cycles. The Copper, therefore, needs
priority over only the 680x0 and the blitter (the DMA channel that handles
animation, line drawing, and polygon filling).

As with all the other DMA channels in the Amiga system, the Copper can
retrieve its instructions only from the chip RAM area of system memory.


2 Coprocessor Hardware / What is a Copper Instruction?

As a coprocessor, the Copper adds its own instruction set to the
instructions already provided by the 680x0 CPU. The Copper has only three
instructions, but you can do a lot with them:

*   WAIT  for aspecific screen position specified as x and y coordinates.

*   MOVE  animmediate data value into one of the special-purpose
   registers.

*   SKIP . the next instruction if the video beam has already reached
   a specified screen position.

All Copper instructions consist of two 16-bit words in sequential memory
locations. Each time the Copper fetches an instruction, it fetches both
words.

The  MOVE  and  SKIP . instructions require two memory cycles and two
instruction words each. Because only the odd memory cycles are requested by
the Copper, four memory cycle times are required per instruction.  The
 WAIT  instruction requires three memory cycles and six memory cycle
times; it takes one extra memory cycle to wake up.

Although the Copper can directly affect only machine registers, it can also
affect memory indirectly by setting up a blitter operation.  More
information about how to use the Copper in controlling the blitter can be
found in the sections called  Control Register  and
 Using the Copper with the Blitter .

The  WAIT  and  MOVE  instructions are described below. The  SKIP
instruction is described in the "Advanced Topics" section.


2 Coprocessor Hardware / The MOVE Instruction

The MOVE instruction transfers data from RAM to a register destination.
The transferred data is contained in the second word of the MOVE
instruction; the first word contains the address of the destination
register. This procedure is shown in detail in the section called
 Summary of Copper Instructions .

     FIRST MOVE INSTRUCTION WORD (IR1)
     ---------------------------------
     Bit 0           Always set to 0.

     Bits 8 - 1      Register destination address (DA8-1).

     Bits 15 - 9     Not used, but should be set to 0.

     SECOND MOVE INSTRUCTION WORD (IR2)
     ----------------------------------
     Bits 15 - 0     16 bits of data to be transferred (moved)
                     to the register destination.

The Copper can store data into the following registers:

   *  Any register whose address is $20 or above.  (Hexadecimal numbers
      are distinguished from decimal numbers by the $ prefix.)

   *  Any register whose address is between $10 and $20 if the Copper
      danger bit is a 1. The Copper danger bit is in the Copper's control
      register,  COPCON , which is described in the "Control Register"
      section.

   *  The Copper cannot write into any register whose address is lower
      than $10.

 Appendix B  contains all of the machine register addresses.

The following example MOVE instructions set bitplane pointer 1 to $21000
and bitplane pointer 2 to $25000.  (All sample code segments are in
assembly language.)

        DC.W    $00E0,$0002     ;Move $0002 to register $0E0 (BPL1PTH)
        DC.W    $00E2,$1000     ;Move $1000 to register $0E2 (BPL1PTL)
        DC.W    $00E4,$0002     ;Move $0002 to register $0E4 (BPL2PTH)
        DC.W    $00E6,$5000     ;Move $5000 to register $0E6 (BPL2PTL)

Normally, the appropriate assembler ".i" files are included so that names,
rather than addresses, may be used for referencing hardware registers.  It
is strongly recommended that you reference all hardware addresses via their
defined names in the system include files.  This will allow you to more
easily adapt your software to take advantage of future hardware or
enhancements.  For example:

        INCLUDE "hardware/custom.i"

        DC.W    bplpt+$00,$0002 ;Move $0002 into register $0E0 (BPL1PTH)
        DC.W    bplpt+$02,$1000 ;Move $1000 into register $0E2 (BPL1PTL)
        DC.W    bplpt+$04,$0002 ;Move $0002 into register $0E4 (BPL2PTH)
        DC.W    bplpt+$06,$5000 ;Move $5000 into register $0E6 (BPL2PTL)

For use in the hardware manual examples, we have made a special include
file (see  Appendix I ) that defines all of the hardware register names
based off of the "hardware/custom.i" file.  This was done to make the
examples easier to read from a hardware point of view.  Most of the
examples in this manual are here to help explain the hardware and are, in
most cases, not useful without modification and a good deal of additional
code.


2 Coprocessor Hardware / The WAIT Instruction

The WAIT instruction causes the Copper to wait until the video beam
counters are equal to (or greater than) the coordinates specified in the
instruction. While waiting, the Copper is off the bus and not using memory
cycles.

The first instruction word contains the vertical and horizontal
coordinates of the beam position. The second word contains enable bits
that are used to form a "mask" that tells the system which bits of the
beam position to use in making the comparison.

     FIRST WAIT INSTRUCTION WORD (IR1)
     ---------------------------------
     Bit 0           Always set to 1.

     Bits 15 - 8      Vertical beam position  (called VP).

     Bits 7 - 1       Horizontal beam position  (called HP).

     SECOND WAIT INSTRUCTION WORD (IR2)
     ----------------------------------
     Bit 0           Always set to 0.

     Bit 15          The  blitter-finished-disable bit .  Normally, this
                     bit is a 1. (See the "Advanced Topics" section below.)

     Bits 14 - 8     Vertical position compare enable bits (called VE).

     Bits 7 - 1      Horizontal position compare enable bits (called HE).

The following example WAIT instruction waits for scan line 150 ($96) with
the horizontal position masked off.

        DC.W    $9601,$FF00     ;Wait for line 150,
                                ;   ignore horizontal counters.

The following example WAIT instruction waits for scan line 255 and
horizontal position 254. This event will never occur, so the Copper stops
until the next  vertical blanking  interval begins.

        DC.W    $FFFF,$FFFE     ;Wait for line 255,
                                ;   H = 254 (ends Copper list).

To understand why position VP=$FF HP=$FE will never occur, you must look
at the comparison operation of the Copper and the size restrictions of the
position information. Line number 255 is a valid line to wait for, in fact
it is the maximum value that will fit into this field. Since 255 is the
maximum number, the next line will wrap to zero (line 256 will appear as a
zero in the comparison.) The line number will never be greater than $FF.
The horizontal position has a maximum value of $E2.  This means that the
largest number that will ever appear in the comparison is $FFE2. When
waiting for $FFFE, the line $FF will be reached, but the horizontal
position $FE will never happen. Thus, the position will never reach $FFFE.

You may be tempted to wait for horizontal position $FE (since it will
never happen), and put a smaller number into the vertical position field.
This will not lead to the desired result. The comparison operation is
waiting for the beam position to become greater than or equal to the
entered position. If the vertical position is not $FF, then as soon as the
line number becomes higher than the entered number, the comparison will
evaluate to true and the wait will end.

The following notes on horizontal and vertical beam position apply to both
the WAIT instruction and to the  SKIP . instruction. The  SKIP  instruction
is described below in the  Advanced Topics  section.

 Horizontal Beam Position
 Vertical Beam Position
 The Comparison Enable Bits


2 / The WAIT Instruction / Horizontal Beam Position

The horizontal beam position has a value of $0 to $E2. The least
significant bit is not used in the comparison, so there are 113 positions
available for Copper operations. This corresponds to 4 pixels in low
resolution and 8 pixels in high resolution. Horizontal blanking falls in
the range of $0F to $35. The standard screen (320 pixels wide) has an
unused horizontal portion of $04 to $47 (during which only the background
color is displayed).

All lines are not the same length in NTSC. Every other line is a long line
(228  color clocks , 0-$E3), with the others being 227  color clocks
long. In PAL, they are all 227 long. The display sees all these lines as
227 1/2  color clocks  long, while the Copper sees alternating long and
short lines.


2 / The WAIT Instruction / Vertical Beam Position

The vertical beam position can be resolved to one line, with a maximum
value of 255. There are actually 262 NTSC (312 PAL) possible vertical
positions. Some minor complications can occur if you want something to
happen within these last six or seven scan lines. Because there are only
eight bits of resolution for vertical beam position (allowing 256
different positions), one of the simplest ways to handle this is shown
below.

     Copper Instruction           Explanation
    --------------------          -----------
     WAIT  for position (0,255)   At this point, the vertical
                                  counter appears to wrap to 0
                                  because the comparison works
                                  on the least significant bits
                                  of the vertical count

     WAIT  for any horizontal       Thus the total of 256 + 6 = 262
    position with vertical        lines of video beam travel during
    position 0 through 5,         which  Copper instructions  can be
    covering the last 6 lines     executed
    of the scan before
     vertical blanking  occurs.

    Note that the vertical is like the horizontal.
    ----------------------------------------------
    There are alternating long and short lines, there are also long and
    short fields (interlace only). In NTSC, the fields are 262, then 263
    lines and in PAL, 312, then 313 lines.  This alternation of lines and
    fields produces the standard NTSC 4 field repeating pattern:

          short field ending on short line
          long  field ending on  long line
          short field ending on  long line
          long  field ending on short line
          and back to the beginning...

One horizontal count takes one cycle of the system clock (processor is
twice this).

          NTSC- 3,579,545 Hz
          PAL - 3,546,895 Hz
          genlocked- basic clock frequency plus or minus about 2%


2 / The WAIT Instruction / The Comparison Enable Bits

Bits 14-1 are normally set to all 1s. The use of the comparison enable
bits is described later in the  Advanced Topics  section.


2 Coprocessor Hardware / Using the Copper Registers

There are several machine registers and strobe addresses dedicated to the
Copper:

 Location Registers
 Jump Address Strobes
 Control Register


2 / Using the Copper Registers / Location Registers

The Copper has two sets of location registers:

          COP1LCH High 3 bits of first Copper list address.
          COP1LCL Low 16 bits of first Copper list address.
          COP2LCH High 3 bits of second Copper list address.
          COP2LCL Low 16 bits of second Copper list address.

In accessing the hardware directly, you often have to write to a pair of
registers that contains the address of some data. The register with the
lower address always has a name ending in "H" and contains the most
significant data, or high 3 bits of the address. The register with the
higher address has a name ending in "L" and contains the least significant
data, or low 15 bits of the address. Therefore, you write the 18-bit
address by moving one long word to the register whose name ends in "H."
This is because when you write long words with the 680x0, the most
significant word goes in the lower addressed word.

In the case of the Copper location registers, you write the address to
COP1LCH. In the following text, for simplicity, these addresses are
referred to as COP1LC or COP2LC.

The Copper location registers contain the two indirect jump addresses used
by the Copper. The Copper fetches its instructions by using its program
counter and increments the program counter after each fetch. When a
 jump address strobe  is written, the corresponding location register is
loaded into the Copper program counter. This causes the Copper to jump to
a new location, from which its next instruction will be fetched.
Instruction fetch continues sequentially until the Copper is interrupted
by another  jump address strobe .

   About Copper restart.
   ---------------------
   At the start of each  vertical blanking  interval, COP1LC is
   automatically used to start the program counter.  That is, no matter
   what the Copper is doing, when the end of  vertical blanking  occurs,
   the Copper is automatically forced to restart its operations at the
   address contained in COP1LC.


2 / Using the Copper Registers / Jump Strobe Address

When you write to a Copper strobe address, the Copper reloads its program
counter from the corresponding  location register . The Copper can write
its own location registers and strobe addresses to perform programmed
jumps. For instance, you might  MOVE  an indirect address into the
 COP2LC  location register. Then, any  MOVE  instruction that addresses
COPJMP2 strobes this indirect address into the program counter.

There are two jump strobe addresses:

     COPJMP1/Restart Copper from address contained in  COP1LC .
     COPJMP2/Restart Copper from address contained in  COP2LC .


2 / Using the Copper Registers / Control Register

The Copper can access some special-purpose registers all of the time, some
registers only when a special control bit is set to a 1, and some registers
not at all.  The registers that the Copper can always affect are numbered
$80 through $FF inclusive.  (See  Appendix B  for a list of registers in
address order.) Those it cannot affect at all are numbered $00 to $3E
inclusive.  The Copper control register is within this group ($00 to $3E).
The rest of the registers, from $40 to $7E, are protected by a bit in the
Copper control register.

In the Copper control register, called COPCON, only bit 1 is currently in
use by the system. This bit, called CDANG (for Copper Danger Bit) protects
all registers numbered between $40 and $7E inclusive. This range includes
the blitter control registers. When CDANG is 0, these registers cannot be
written by the Copper. When CDANG is 1, these registers can be written by
the Copper. Preventing the Copper from accessing the blitter control
registers prevents a runaway Copper (caused by a poorly formed instruction
list) from accidentally affecting system memory.

   Warning:
   --------
   Keep in mind that the CDANG bit is cleared after a reset.


2 Coprocessor Hardware / Putting Together a Copper Instruction List

The Copper instruction list contains all the register resetting done
during the  vertical blanking  interval and the register modifications
necessary for making mid-screen alterations. As you are planning what will
happen during each display field, you may find it easier to think of each
aspect of the display as a separate subsystem, such as playfields,
sprites, audio, interrupts, and so on. Then you can build a separate list
of things that must be done for each subsystem individually at each video
beam position.

When you have created all these intermediate lists of things to be done,
you must merge them together into a single instruction list to be executed
by the Copper once for each display frame. The alternative is to create
this all-inclusive list directly, without the intermediate steps.

For example, the  bitplane pointers  used in playfield displays and the
 sprite pointers  must be rewritten during the vertical blanking  interval
so the data will be properly retrieved when the screen display starts
again. This can be done with a Copper instruction list that does the
following:

    WAIT  until first line of the display
    MOVE  data to bitplane pointer 1
    MOVE  data to bitplane pointer 2
    MOVE  data to sprite pointer 1, and so on.

As another example, the  sprite DMA channels  that create movable objects
can be reused multiple times during the same display field. You can change
the size and shape of the reuses of a sprite; however, every multiple
reuse normally uses the same set of colors during a full display frame.
You can change sprite colors mid-screen with a Copper instruction list
that waits until the last line of the first use of the sprite processor
and changes the colors before the first line of the next use of the same
sprite processor:

    WAIT  for first line of display
    MOVE  firstcolor1 to COLOR17
    MOVE  firstcolor2 to COLOR18
    MOVE  firstcolor3 to COLOR19
    WAIT  for last line +1 of sprite's first use
    MOVE  secondcolor1 to COLOR17
    MOVE  secondcolor2 to COLOR18
    MOVE  secondcolor3 to COLOR19, and so on.

As you create Copper instruction lists, note that the final list must be
in the same order as that in which the video beam creates the display. The
video beam traverses the screen from position (0,0) in the upper left hand
corner of the screen to the end of the display (226,262) NTSC (or
(226,312) PAL) in the lower right hand corner. The first 0 in (0,0)
represents the x position. The second 0 represents the y position. For
example, an instruction that does something at position (0,100) should
come after an instruction that affects the display at position (0,60).

Note that given the form of the  WAIT  instruction, you can sometimes get
away with not sorting the list in strict video beam order.  The  WAIT
instruction causes the Copper to wait until the value in the beam counter
is equal to or greater than the value in the instruction.

This means, for example, if you have instructions following each other
like this:

    WAIT  for position (64,64)
    MOVE  data

    WAIT  for position (60,60)
    MOVE  data

then the Copper will perform both moves, even though the instructions are
out of sequence.  The "greater than" specification prevents the Copper
from locking up if the beam has already passed the specified position.  A
side effect is that the second  MOVE  below will be performed:

    WAIT  for position (60,60)
    MOVE  data

    WAIT  for position (60,60)
    MOVE  data

At the time of the second  WAIT  in this sequence, the beam counters will
be greater than the position shown in the instructions. Therefore, the
second  MOVE  will also be performed.

Note also that the above sequence of instructions could just as easily be

    WAIT  for position (60,60)
    MOVE  data
    MOVE  data

because multiple  MOVE s can follow a single  WAIT .

 Complete Sample Copper List


2 / Putting Together a Copper List / Complete Sample Copper List

The following example shows a complete Copper list. This list is for two
bitplanes -- one at $21000 and one at $25000. At the top of the screen,
the  color registers  are loaded with the following values:

          Register        Color
          --------        -----
          COLOR00         white
          COLOR01         red
          COLOR02         green
          COLOR03         blue

At line 150 on the screen, the  color registers  are reloaded:

          Register        Color
          --------        -----
          COLOR00         black
          COLOR01         yellow
          COLOR02         cyan
          COLOR03         magenta

The complete Copper list follows.

;
; Notes: 1. Copper lists must be in Chip RAM.
;        2. Bitplane addresses used in the example are arbitrary.
;        3. Destination register addresses in Copper move instructions
;           are offsets from the base address of the custom chips.
;        4. As always, hardware manual examples assume that your
;           application has taken full control of the hardware, and is not
;           conflicting with operating system use of the same hardware.
;        5. Many of the examples just pick memory addresses to be used.
;           Normally you would need to allocate the required type of
;           memory from the system with AllocMem()
;        6. As stated earlier, the code examples are mainly to help
;           clarify the way the hardware works.
;        7. The following INCLUDE files are required by all example code
;           in this chapter.
;
        INCLUDE "exec/types.i"
        INCLUDE "hardware/custom.i"
        INCLUDE "hardware/dmabits.i"
        INCLUDE "hardware/hw_examples.i"

COPPERLIST:
;
;  Set up pointers to two bitplanes
;
        DC.W    BPL1PTH,$0002   ;Move $0002 into register $0E0 (BPL1PTH)
        DC.W    BPL1PTL,$1000   ;Move $1000 into register $0E2 (BPL1PTL)
        DC.W    BPL2PTH,$0002   ;Move $0002 into register $0E4 (BPL2PTH)
        DC.W    BPL2PTL,$5000   ;Move $5000 into register $0E6 (BPL2PTL)
;
;  Load color registers
;
        DC.W    COLOR00,$0FFF   ;Move white into register $180 (COLOR00)
        DC.W    COLOR01,$0F00   ;Move red into register   $182 (COLOR01)
        DC.W    COLOR02,$00F0   ;Move green into register $184 (COLOR02)
        DC.W    COLOR03,$000F   ;Move blue into register  $186 (COLOR03)
;
;   Specify 2 Lores bitplanes
;
        DC.W    BPLCON0,$2200   ;2 lores planes, coloron
;
;  Wait for line 150
;
        DC.W    $9601,$FF00     ;Wait for line 150, ignore horiz. position
;
;  Change color registers mid-display
;
        DC.W    COLOR00,$0000  ;Move black into register $0180 (COLOR00)
        DC.W    COLOR01,$0FF0  ;Move yellow into register $0182 (COLOR01)
        DC.W    COLOR02,$00FF  ;Move cyan into register $0184 (COLOR02)
        DC.W    COLOR03,$0F0F  ;Move magenta into register $0186 (COLOR03)
;
; End Copper list by waiting for the impossible
;
        DC.W    $FFFF,$FFFE    ;Wait for line 255, H = 254 (never happens)

For more information about  color registers , see Chapter 3, "Playfield
Hardware."


2 Coprocessor Hardware / Starting and Stopping the Copper

 Starting the Copper After Reset
 Stopping the Copper


2 / Starting and Stopping the Copper / Starting the Copper After Reset

At power-on or reset time, you must initialize one of the Copper
 location registers (COP1LC or COP2LC)  and write to its  strobe address
before Copper DMA is turned on. This ensures a known start address and
known state. Usually,  COP1LC  is used because this particular register is
reused during each vertical blanking  time. The following sequence of
instructions shows how to initialize a  location register . It is assumed
that the user has already created the correct  Copper instruction list  at
location "mycoplist."

;
; Install the copper list
;
     LEA     CUSTOM,a1           ; a1 = address of custom chips
     LEA     MYCOPLIST(pc),a0    ; Address of our copper list
     MOVE.L  a0,COP1LC(a1)       ; Write whole longword address
     MOVE.W  COPJMP1(a1),d0      ; Causes copper to load PC from  COP1LC
;
; Then enable copper and raster dma
;
     MOVE.W  #(DMAF_SETCLR!DMAF_COPPER!DMAF_RASTER!DMAF_MASTER),DMACON(a1)
;

Now, if the contents of  COP1LC  are not changed, every time
 vertical blanking  occurs the Copper will restart at the same location
for each subsequent video screen. This forms a repeatable loop which, if
the list is correctly formulated, will cause the displayed screen to be
stable.


2 / Starting and Stopping the Copper / Stopping the Copper

No stop instruction is provided for the Copper. To ensure that it will
stop and do nothing until the screen display ends and the program counter
starts again at the top of the instruction list, the last instruction
should be to  WAIT  for an event that cannot occur. A typical instruction
is to  WAIT  for VP = $FF and HP = $FE. An HP of greater than $E2 is not
possible. When the screen display ends and  vertical blanking  starts, the
Copper will automatically be pointed to the top of its instruction list,
and this final  WAIT  instruction never finishes.

You can also stop the Copper by disabling its ability to use DMA for
retrieving instructions or placing data. The register called  DMACON
controls all of the DMA channels. Bit 7, COPEN, enables Copper DMA when
set to 1.

For information about  controlling the DMA , see Chapter 7, "System
Control Hardware."


2 Coprocessor Hardware / Advanced Topics

 The SKIP Instruction
 Copper Loops and Branches and Comparison Enable
 A Copper Loop Example
 Using the Copper in Interlaced Mode
 Using the Copper with the Blitter
 The Copper and the 680x0


2 / Advanced Topics / The SKIP Instruction

The SKIP instruction causes the Copper to skip the next instruction if the
video beam counters are equal to or greater than the value given in the
instruction.

The contents of the SKIP instruction's words are shown below. They are
identical to the  WAIT  instruction, except that bit 0 of the second
instruction word is a 1 to identify this as a SKIP instruction.

          FIRST SKIP INSTRUCTION WORD (IR1)
          ---------------------------------
          Bit 0           Always set to 1.

          Bits 15 - 8      Vertical position  (called VP).

          Bits 7 - 1       Horizontal position  (called HP).

                          Skip if the beam counter is equal to or
                          greater than these combined bits
                          (bits 15 through 1).

          SECOND SKIP INSTRUCTION WORD (IR2)
          ----------------------------------
          Bit 0           Always set to 1.

          Bit 15          The  blitter-finished-disable bit .
                          (See "Using the Copper with the Blitter"
              below.)

          Bits 14 - 8     Vertical position compare enable bits
                          (called VE).

          Bits 7 - 1      Horizontal position compare enable bits
                          (called HE).

The notes about  horizontal  and  vertical beam position  found in the
discussion of the  WAIT  instruction apply also to the SKIP instruction.

The following example SKIP instruction skips the instruction following it
if VP ( vertical beam position ) is greater than or equal to 100 ($64).

        DC.W    $6401,$FF01     ;If VP >= 100,
                                ;  skip next instruction (ignore HP)


2 / Advanced Topics / Copper Loops and Branches and Comparison Enable

You can change the value in the  location registers  at any time and use
this value to construct loops in the instruction list. Before the next
 vertical blanking  time, however, the  COP1LC  registers must be
repointed to the beginning of the appropriate Copper list. The value in
the  COP1LC  location registers will be restored to the Copper's program
counter at the start of the  vertical blanking  period.

Bits 14-1 of instruction word 2 in the  WAIT  and  SKIP . instructions
specify which bits of the horizontal and vertical position are to be used
for the beam counter comparison. The position in instruction word 1 and
the compare enable bits in instruction word 2 are tested against the
actual beam counters before any further action is taken. A position bit in
instruction word 1 is used in comparing the positions with the actual beam
counters if and only if the corresponding enable bit in instruction word 2
is set to 1. If the corresponding enable bit is 0, the comparison is
always true. For instance, if you care only about the value in the last
four bits of the vertical position, you set only the last four compare
enable bits, bits (11-8) in instruction word 2.

Not all of the bits in the beam counter may be masked.  If you look at the
description of the IR2 (second instruction word) you will notice that bit
15 is the  blitter-finished-disable bit . This bit is not part of the beam
counter comparison mask, it has its own meaning in the Copper  WAIT
instruction. Thus, you can not mask the most significant bit in  WAIT  or
 SKIP  instructions. In most situations this limitation does not come into
play, however, the following example shows how to deal with it.


2 / Advanced Topics / A Copper Loop Example

This example will instruct the Copper to issue an interrupt every 16 scan
lines.  It might seem that the way to do this would be to use a mask of
$0F and then compare the result with $0F. This should compare "true" for
$1F, $2F, $3F, etc. Since the test is for greater than or equal to, this
would seem to allow checking for every 16th scan line. However, the
highest order bit cannot be masked, so it will always appear in the
comparisons. When the Copper is waiting for $0F and the vertical position
is past 128 (hex $80), this test will always be true. In this case, the
minimum value in the comparison will be $80, which is always greater than
$0F, and the interrupt will happen on every scan line. Remember, the
Copper only checks for greater than or equal to.

In the following example, the Copper lists have been made to loop. The
 COP1LC and COP2LC  values are either set via the CPU or in the Copper
list before this section of Copper code. Also, it is assumed that you have
correctly installed an interrupt server for the Copper interrupt that will
be generated every 16 lines. Note that these are non-interlaced scan lines.

Here's how it works.  Both loops are, for the most part, exactly the same.
In each, the Copper waits until the vertical position register has $xF
(where x is any hex digit) in it, at which point we issue a Copper
interrupt to the Amiga hardware. To make sure that the Copper does not
loop back before the vertical position has changed and cause another
interrupt on the same scan line, wait for the horizontal position to be
$E2 after each interrupt. Position $E2 is horizontal position 113 for the
Copper and the last real horizontal position available. This will force
the Copper to the next line before the next  WAIT . The loop is executed
by writing to the  COPJMP1  register. This causes the Copper to jump to
the address that was initialized in  COP1LC .

The masking problem described above makes this code fail after vertical
position 127.  A separate loop must be executed when vertical position is
greater than or equal 127. When the vertical position becomes greater than
or equal to 127, the the first loop instruction is skipped, dropping the
Copper into the second loop. The second loop is much the same as the
first, except that it waits for $xF with the high bit set (binary
1xxx1111). This is true for both the vertical and the horizontal  WAIT
instructions. To cause the second loop, write to the  COPJMP2  register.
The list is put into an infinite wait when VP >= 255 so that it will end
before the vertical blank. At the end of the  vertical blanking  period
 COP1LC  is written to by the operating system, causing the first loop to
start up again.

    COP1LC  is written at the end of  vertical blanking .
   ------------------------------------------------------
   The  COP1LC  register is written at the end of the  vertical blanking
   period by a graphics interrupt handler which is in the vertical blank
   interrupt server chain.  As long as this server is intact,  COP1LC
   will be correctly strobed at the end of each vertical blank.

;
;  This is the data for the Copper list.
;
;  It is assumed that COPPERL1 is loaded into  COP1LC  and
;  that COPPERL2 is loaded into  COP2LC  by some other code.
;
COPPERL1:
        DC.W    $0F01,$8F00   ; Wait for VP=0xxx1111
        DC.W    INTREQ,$8010  ; Set the copper interrupt bit...

        DC.W    $00E3,$80FE   ; Wait for Horizontal $E2
                              ; This is so the line gets finished before
                              ; we check if we are there  (The wait above)

        DC.W    $7F01,$7F01   ; Skip if VP>=127
        DC.W    COPJMP1,$0    ; Force a jump to  COP1LC

COPPERL2:
        DC.W    $8F01,$8F00   ; Wait for VP=1xxx1111
        DC.W    INTREQ,$8010  ; Set the copper interrupt bit...

        DC.W    $80E3,$80FE   ; Wait for Horizontal $E2
                              ; This is so the line gets finished before
                              ; we check if we are there  (The wait above)

        DC.W    $FF01,$FE01   ; Skip if VP>=255
        DC.W    COPJMP2,$0    ; Force a jump to  COP2LC

; Whatever cleanup copper code that might be needed here...
; Since there are 262 lines in NTSC, and we stopped at 255, there is a
; bit of time available

        DC.W    $FFFF,$FFFE     ; End of Copper list
;


2 / Advanced Topics / Using the Copper In Interlaced Mode

An interlaced bitplane display has twice the normal number of vertical
lines on the screen.  Whereas a normal NTSC display has 262 lines, an
interlaced NTSC display has 524 lines.  PAL has 312 lines normally and 625
in interlaced mode.  In interlaced mode, the video beam scans the screen
twice from top to bottom, displaying, in the case of NTSC, 262 lines at a
time. During the first scan, the odd-numbered lines are displayed.  During
the second scan, the even-numbered lines are displayed and interlaced with
the odd-numbered ones.  The scanning circuitry thus treats an interlaced
display as two display fields, one containing the even-numbered lines and
one containing the odd-numbered lines. Figure 2-1 shows how an interlaced
display is stored in memory.

         Odd field             Even field
         (time t)           (time t + 16.6ms)       Data in Memory
     -----------------      -----------------      -----------------
                                                   _________________
                                                  |                 |
                                                  |        1        |
                                                  |_________________|
                                                  |                 |
     _________________      _________________     |        2        |
    |                 |    |                 |    |_________________|
    |        1        |    |        2        |    |                 |
    |_________________|    |_________________|    |        3        |
    |                 |    |                 |    |_________________|
    |        3        |    |        4        |    |                 |
    |_________________|    |_________________|    |        4        |
    |                 |    |                 |    |_________________|
    |        5        |    |        6        |    |                 |
    |_________________|    |_________________|    |        5        |
                                                  |_________________|
                                                  |                 |
                                                  |        6        |
                                                  |_________________|

                 Figure 2-1: Interlaced Bitplane in RAM

The system retrieves data for bitplane displays by using pointers to the
starting address of the data in memory. As you can see, the starting
address for the even-numbered fields is one line greater than the starting
address for the odd-numbered fields. Therefore, the bitplane pointer must
contain a different value for alternate fields of the interlaced display.

Simply, the organization of the data in memory matches the apparent
organization on the screen (i.e., odd and even lines are interlaced
together). This is accomplished by having a separate
 Copper instruction list  for each field to manage displaying the data.

To get the Copper to execute the correct list, you set an interrupt to the
680x0 just after the first line of the display. When the interrupt is
executed, you change the contents of the  COP1LC  location register to
point to the second list. Then, during the  vertical blanking  interval,
 COP1LC  will be automatically reset to point to the original list.

For more information about  interlaced displays , see Chapter 3,
"Playfield Hardware."


2 / Advanced Topics / Using the Copper with the Blitter

If the Copper is used to start up a sequence of blitter operations, it
must wait for the blitter-finished interrupt before starting another
blitter operation. Changing blitter registers while the blitter is
operating causes unpredictable results. For just this purpose, the  WAIT
instruction includes an additional control bit, called BFD (for blitter
finished disable). Normally, this bit is a 1 and only the beam counter
comparisons control the  WAIT .

When the BFD bit is a 0, the logic of the Copper  WAIT  instruction is
modified. The Copper will  WAIT  until the beam counter comparison is true
and the blitter has finished. The blitter has finished when the
blitter-finished flag is set. This bit should be unset with caution. It
could possibly prevent some screen displays or prevent objects from being
displayed correctly.

For more information about using the blitter, see
 Chapter 6, Blitter Hardware .


2 / Advanced Topics / The Copper and the 680x0

On those occasions when the Copper's instructions do not suffice, you can
interrupt the 680x0 and use its instruction set instead. The 680x0 can
poll for interrupt flags set in the  INTREQ  register by various devices.
To interrupt the 680x0, use the Copper  MOVE  instruction to store a 1
into the following bits of  INTREQ :

               Table 2-1: Interrupting the 680x0

     Bit Number      Name      Function
     ----------      ----      --------
        15          SET/CLR    Set/Clear control bit.  Determines
                               if bits written with a 1 get set
                               or cleared.

         4           COPEN     Coprocessor interrupting 680x0.

See Chapter 7, "System Control Hardware," for more information about
 interrupts .


2 Coprocessor Hardware / Summary of Copper Instructions

The table below shows a summary of the bit positions for each of the
 Copper instructions . See  Appendix A  for a summary of all registers.

             Table 2-2: Copper Instruction Summary

                   Move             Wait             Skip
                   ----             ----             ----
     Bit#       IR1    IR2       IR1    IR2       IR1    IR2
     ----       ---    ---       ---    ---       ---    ---
     15         X      RD15      VP7    BFD       VP7    BFD
     14         X      RD14      VP6    VE6       VP6    VE6
     13         X      RD13      VP5    VE5       VP5    VE5
     12         X      RD12      VP4    VE4       VP4    VE4
     11         X      RD11      VP3    VE3       VP3    VE3
     10         X      RD10      VP2    VE2       VP2    VE2
     09         X      RD09      VP1    VE1       VP1    VE1
     08         DA8    RD08      VP0    VE0       VP0    VE0
     07         DA7    RD07      HP8    HE8       HP8    HE8
     06         DA6    RD06      HP7    HE7       HP7    HE7
     05         DA5    RD05      HP6    HE6       HP6    HE6
     04         DA4    RD04      HP5    HE5       HP5    HE5
     03         DA3    RD03      HP4    HE4       HP4    HE4
     02         DA2    RD02      HP3    HE3       HP3    HE3
     01         DA1    RD01      HP2    HE2       HP2    HE2
     00         0      RD00      1      0         1      1

     X = don't care, but should be a 0 for upward compatibility
     IR1 = first instruction word
     IR2 = second instruction word
     DA = destination address
     RD = RAM data to be moved to destination register
     VP =  vertical beam position  bit
     HP =  horizontal beam position  bit
     VE = enable comparison (mask bit)
     HE = enable comparison (mask bit)
     BFD =  blitter-finished disable

   ECS Copper.
   -----------
   For information relating to the Copper in the Enhanced Chip
   Set (ECS), see  Appendix C .


Amiga® Hardware Reference Manual: B Register Summary Address Order

This appendix contains information about the register set in address order.

The following codes and abbreviations are used in this appendix:

  &        Register used by DMA channel only.

  %        Register used by DMA channel usually, processors sometimes.

  +        Address register pair.  Must be an even address pointing to chip
           memory.

  *        Address not writable by the Copper.

  ~        Address not writable by the Copper unless the "copper danger
           bit",  COPCON  is set true.

  A,D,P    A=Agnus chip, D=Denise chip, P=Paula chip.

  W,R      W=write-only; R=read-only,

  ER       Early read. This is a DMA data transfer to RAM, from either the
           disk or the blitter.  RAM timing requires data to be on the bus
           earlier than microprocessor read cycles. These transfers are
           therefore initiated by Agnus timing, rather than a read address
           on the destination address bus.

  S        Strobe (write address with no register bits).  Writing the
           register causes the effect.

  PTL,PTH  Chip memory pointer that addresses DMA data.  Must be reloaded
           by a processor before use (vertical blank for bitplane and
           sprite pointers, and prior to starting the blitter for blitter
           pointers).

  LCL,LCH  Chip memory location (starting address) of DMA data.  Used to
           automatically restart pointers, such as the Copper program
           counter (during vertical blank) and the audio sample counter
           (whenever the audio length count is finished).

  MOD      15-bit modulo. A number that is automatically added to the
           memory address at the end of each line to generate the address
           for the beginning of the next line. This allows the blitter (or
           the display window) to operate on (or display) a window of data
           that is smaller than the actual picture in memory (memory map).
           Uses 15 bits, plus sign extend.

   About the ECS registers.
   ------------------------
   Registers denoted with an "(E)" in the chip column means that
   those registers have been changed in the Enhanced Chip Set
   (ECS).  The ECS is found in the A3000, and is installable in the
   A500 and A2000.  Certain ECS registers are completely new,
   others have been extended in their functionality. See the
    register map  in Appendix C for information on which ECS
   registers are new and which have been modified.

----------------------------------------------------------------------
NAME        ADD  R/W  CHIP    FUNCTION
----------------------------------------------------------------------
 BLTDDAT   & *000  ER  A       Blitter destination early read
                                   (dummy address)
 DMACONR     *002  R   AP      DMA control (and blitter status) read
 VPOSR       *004  R   A( E )  Read vert most signif. bit (and frame flop)
 VHPOSR      *006  R   A       Read vert and horiz. position of beam
 DSKDATR   & *008  ER  P       Disk data early read (dummy address)
 JOY0DAT     *00A  R   D       Joystick-mouse 0 data (vert,horiz)
 JOY1DAT     *00C  R   D       Joystick-mouse 1 data (vert,horiz)
 CLXDAT      *00E  R   D       Collision data register (read and clear)
 ADKCONR     *010  R   P       Audio, disk control register read
 POT0DAT     *012  R   P( E )  Pot counter pair 0 data (vert,horiz)
 POT1DAT     *014  R   P( E )  Pot counter pair 1 data (vert,horiz)
 POTGOR      *016  R   P       Pot port data read (formerly POTINP)
 SERDATR     *018  R   P       Serial port data and status read
 DSKBYTR     *01A  R   P       Disk data byte and status read
 INTENAR     *01C  R   P       Interrupt enable bits read
 INTREQR     *01E  R   P       Interrupt request bits read
 DSKPTH    + *020  W   A( E )  Disk pointer (high 3 bits, 5 bits if ECS)
 DSKPTL    + *022  W   A       Disk pointer (low 15 bits)
 DSKLEN      *024  W   P       Disk length
 DSKDAT    & *026  W   P       Disk DMA data write
 REFPTR    & *028  W   A       Refresh pointer
 VPOSW       *02A  W   A       Write vert most signif. bit (and frame flop)
 VHPOSW      *02C  W   A       Write vert and horiz position of beam
 COPCON      *02E  W   A( E )  Coprocessor control register (CDANG)
 SERDAT      *030  W   P       Serial port data and stop bits write
 SERPER      *032  W   P       Serial port period and control
 POTGO       *034  W   P       Pot port data write and start
 JOYTEST     *036  W   D       Write to all four joystick-mouse counters
                               at once
 STREQU    & *038  S   D       Strobe for horiz sync with VB and EQU
 STRVBL    & *03A  S   D       Strobe for horiz sync with VB (vert. blank)
 STRHOR    & *03C  S   DP      Strobe for horiz sync
 STRLONG   & *03E  S   D( E )  Strobe for identification of long
                                   horiz. line.
 BLTCON0     ~040  W   A       Blitter control register 0
 BLTCON1     ~042  W   A( E )  Blitter control register 1
 BLTAFWM     ~044  W   A       Blitter first word mask for source A
 BLTALWM     ~046  W   A       Blitter last word mask for source A
 BLTCPTH   + ~048  W   A       Blitter pointer to source C (high 3 bits)
 BLTCPTL   + ~04A  W   A       Blitter pointer to source C (low 15 bits)
 BLTBPTH   + ~04C  W   A       Blitter pointer to source B (high 3 bits)
 BLTBPTL   + ~04E  W   A       Blitter pointer to source B (low 15 bits)
 BLTAPTH   + ~050  W   A( E )  Blitter pointer to source A (high 3 bits)
 BLTAPTL   + ~052  W   A       Blitter pointer to source A (low 15 bits)
 BLTDPTH   + ~054  W   A       Blitter pointer to destination D
                                   (high 3 bits)
 BLTDPTL   + ~056  W   A       Blitter pointer to destination D
                                   (low 15 bits)
 BLTSIZE     ~058  W   A       Blitter start and size (window width,height)
 BLTCON0L    ~05A  W   A( E )  Blitter control 0, lower 8 bits (minterms)
 BLTSIZV     ~05C  W   A( E )  Blitter V size (for 15 bit vertical size)
 BLTSIZH     ~05E  W   A( E )  Blitter H size and start (for 11 bit H size)
 BLTCMOD     ~060  W   A       Blitter modulo for source C
 BLTBMOD     ~062  W   A       Blitter modulo for source B
 BLTAMOD     ~064  W   A       Blitter modulo for source A
 BLTDMOD     ~066  W   A       Blitter modulo for destination D
             ~068
             ~06A
             ~06C
             ~06E
 BLTCDAT   % ~070  W   A       Blitter source C data register
 BLTBDAT   % ~072  W   A       Blitter source B data register

 BLTADAT   % ~074  W   A       Blitter source A data register
             ~076
 SPRHDAT     ~078  W   A( E )  Ext. logic UHRES sprite pointer and data id
             ~07A
 DENISEID    ~07C  R   D( E )  Chip revision level for Denise
                                   (video out chip)
 DSKSYNC     ~07E  W   P       Disk sync pattern register for disk read
 COP1LCH   +  080  W   A( E )  Coprocessor first location register
                                  (high 3 bits, high 5 bits if ECS)
 COP1LCL   +  082  W   A       Coprocessor first location register
                                  (low 15 bits)
 COP2LCH   +  084  W   A( E )  Coprocessor second location register
                                  (high 3 bits, high 5 bits if ECS)
 COP2LCL   +  086  W   A       Coprocessor second location register
                                  (low 15 bits)
 COPJMP1      088  S   A       Coprocessor restart at first location
 COPJMP2      08A  S   A       Coprocessor restart at second location
 COPINS       08C  W   A       Coprocessor instruction fetch identify
 DIWSTRT      08E  W   A       Display window start (upper left
                                  vert-horiz position)
 DIWSTOP      090  W   A       Display window stop (lower right
                                  vert.-horiz. position)
 DDFSTRT      092  W   A       Display bitplane data fetch start
                                  (horiz. position)
 DDFSTOP      094  W   A       Display bitplane data fetch stop
                                  (horiz. position)
 DMACON       096  W   ADP     DMA control write (clear or set)
 CLXCON       098  W   D       Collision control
 INTENA       09A  W   P       Interrupt enable bits (clear or
                                  set bits)
 INTREQ       09C  W   P       Interrupt request bits (clear or
                                  set bits)
 ADKCON       09E  W   P       Audio, disk, UART control
 AUD0LCH   +  0A0  W   A( E )  Audio channel 0 location (high 3 bits,
                                   5 if ECS)
 AUD0LCL   +  0A2  W   A       Audio channel 0 location (low 15 bits)
 AUD0LEN      0A4  W   P       Audio channel 0 length
 AUD0PER      0A6  W   P( E )  Audio channel 0 period
 AUD0VOL      0A8  W   P       Audio channel 0 volume
 AUD0DAT   &  0AA  W   P       Audio channel 0 data
              0AC
              0AE
 AUD1LCH   +  0B0  W   A       Audio channel 1 location (high 3 bits)
 AUD1LCL   +  0B2  W   A       Audio channel 1 location (low 15 bits)
 AUD1LEN      0B4  W   P       Audio channel 1 length
 AUD1PER      0B6  W   P       Audio channel 1 period
 AUD1VOL      0B8  W   P       Audio channel 1 volume
 AUD1DAT   &  0BA  W   P       Audio channel 1 data
              0BC
              0BE
 AUD2LCH   +  0C0  W   A       Audio channel 2 location (high 3 bits)
 AUD2LCL   +  0C2  W   A       Audio channel 2 location (low 15 bits)
 AUD2LEN      0C4  W   P       Audio channel 2 length
 AUD2PER      0C6  W   P       Audio channel 2 period
 AUD2VOL      0C8  W   P       Audio channel 2 volume
 AUD2DAT   &  0CA  W   P       Audio channel 2 data
              0CC
              0CE
 AUD3LCH   +  0D0  W   A       Audio channel 3 location (high 3 bits)
 AUD3LCL   +  0D2  W   A       Audio channel 3 location (low 15 bits)
 AUD3LEN      0D4  W   P       Audio channel 3 length
 AUD3PER      0D6  W   P       Audio channel 3 period
 AUD3VOL      0D8  W   P       Audio channel 3 volume
 AUD3DAT   &  0DA  W   P       Audio channel 3 data
              0DC
              0DE
 BPL1PTH   +  0E0  W   A       Bitplane 1 pointer (high 3 bits)
 BPL1PTL   +  0E2  W   A       Bitplane 1 pointer (low 15 bits)
 BPL2PTH   +  0E4  W   A       Bitplane 2 pointer (high 3 bits)
 BPL2PTL   +  0E6  W   A       Bitplane 2 pointer (low 15 bits)
 BPL3PTH   +  0E8  W   A       Bitplane 3 pointer (high 3 bits)
 BPL3PTL   +  0EA  W   A       Bitplane 3 pointer (low 15 bits)
 BPL4PTH   +  0EC  W   A       Bitplane 4 pointer (high 3 bits)
 BPL4PTL   +  0EE  W   A       Bitplane 4 pointer (low 15 bits)
 BPL5PTH   +  0F0  W   A       Bitplane 5 pointer (high 3 bits)
 BPL5PTL   +  0F2  W   A       Bitplane 5 pointer (low 15 bits)
 BPL6PTH   +  0F4  W   A       Bitplane 6 pointer (high 3 bits)
 BPL6PTL   +  0F6  W   A       Bitplane 6 pointer (low 15 bits)
              0F8
              0FA
              0FC
              0FE
 BPLCON0      100  W   AD( E ) Bitplane control register
                                   (misc. control bits)
 BPLCON1      102  W   D       Bitplane control reg.
                                   (scroll value PF1, PF2)
 BPLCON2      104  W   D( E )  Bitplane control reg. (priority control)
 BPLCON3      106  W   D( E )  Bitplane control (enhanced features)

 BPL1MOD      108  W   A       Bitplane modulo (odd planes)
 BPL2MOD      10A  W   A       Bitplane modulo (even planes)
              10C
              10E
 BPL1DAT   &  110  W   D       Bitplane 1 data (parallel-to-serial convert)
 BPL2DAT   &  112  W   D       Bitplane 2 data (parallel-to-serial convert)
 BPL3DAT   &  114  W   D       Bitplane 3 data (parallel-to-serial convert)
 BPL4DAT   &  116  W   D       Bitplane 4 data (parallel-to-serial convert)
 BPL5DAT   &  118  W   D       Bitplane 5 data (parallel-to-serial convert)
 BPL6DAT   &  11A  W   D       Bitplane 6 data (parallel-to-serial convert)
              11C
              11E
 SPR0PTH   +  120  W   A       Sprite 0 pointer (high 3 bits)
 SPR0PTL   +  122  W   A       Sprite 0 pointer (low 15 bits)
 SPR1PTH   +  124  W   A       Sprite 1 pointer (high 3 bits)
 SPR1PTL   +  126  W   A       Sprite 1 pointer (low 15 bits)
 SPR2PTH   +  128  W   A       Sprite 2 pointer (high 3 bits)
 SPR2PTL   +  12A  W   A       Sprite 2 pointer (low 15 bits)
 SPR3PTH   +  12C  W   A       Sprite 3 pointer (high 3 bits)
 SPR3PTL   +  12E  W   A       Sprite 3 pointer (low 15 bits)
 SPR4PTH   +  130  W   A       Sprite 4 pointer (high 3 bits)
 SPR4PTL   +  132  W   A       Sprite 4 pointer (low 15 bits)
 SPR5PTH   +  134  W   A       Sprite 5 pointer (high 3 bits)
 SPR5PTL   +  136  W   A       Sprite 5 pointer (low 15 bits)
 SPR6PTH   +  138  W   A       Sprite 6 pointer (high 3 bits)
 SPR6PTL   +  13A  W   A       Sprite 6 pointer (low 15 bits)
 SPR7PTH   +  13C  W   A       Sprite 7 pointer (high 3 bits)
 SPR7PTL   +  13E  W   A       Sprite 7 pointer (low 15 bits)
 SPR0POS   %  140  W   AD      Sprite 0 vert-horiz start position
                                  data
 SPR0CTL   %  142  W   AD( E ) Sprite 0 vert stop position and
                                  control data
 SPR0DATA  %  144  W   D       Sprite 0 image data register A
 SPR0DATB  %  146  W   D       Sprite 0 image data register B
 SPR1POS   %  148  W   AD      Sprite 1 vert-horiz start position
                                  data
 SPR1CTL   %  14A  W   AD      Sprite 1 vert stop position and
                                  control data
 SPR1DATA  %  14C  W   D       Sprite 1 image data register A
 SPR1DATB  %  14E  W   D       Sprite 1 image data register B
 SPR2POS   %  150  W   AD      Sprite 2 vert-horiz start position
                                  data
 SPR2CTL   %  152  W   AD      Sprite 2 vert stop position and
                                  control data
 SPR2DATA  %  154  W   D       Sprite 2 image data register A
 SPR2DATB  %  156  W   D       Sprite 2 image data register B
 SPR3POS   %  158  W   AD      Sprite 3 vert-horiz start position
                                  data
 SPR3CTL   %  15A  W   AD      Sprite 3 vert stop position and
                                  control data
 SPR3DATA  %  15C  W   D       Sprite 3 image data register A
 SPR3DATB  %  15E  W   D       Sprite 3 image data register B
 SPR4POS   %  160  W   AD      Sprite 4 vert-horiz start position
                                  data
 SPR4CTL   %  162  W   AD      Sprite 4 vert stop position and
                                  control data
 SPR4DATA  %  164  W   D       Sprite 4 image data register A
 SPR4DATB  %  166  W   D       Sprite 4 image data register B
 SPR5POS   %  168  W   AD      Sprite 5 vert-horiz start position
                                  data
 SPR5CTL   %  16A  W   AD      Sprite 5 vert stop position and
                                  control data
 SPR5DATA  %  16C  W   D       Sprite 5 image data register A
 SPR5DATB  %  16E  W   D       Sprite 5 image data register B
 SPR6POS   %  170  W   AD      Sprite 6 vert-horiz start position
                                  data
 SPR6CTL   %  172  W   AD      Sprite 6 vert stop position and
                                  control data
 SPR6DATA  %  174  W   D       Sprite 6 image data register A
 SPR6DATB  %  176  W   D       Sprite 6 image data register B
 SPR7POS   %  178  W   AD      Sprite 7 vert-horiz start position
                                  data
 SPR7CTL   %  17A  W   AD      Sprite 7 vert stop position and
                                  control data
 SPR7DATA  %  17C  W   D       Sprite 7 image data register A
 SPR7DATB  %  17E  W   D       Sprite 7 image data register B
 COLOR00      180  W   D       Color table 00
 COLOR01      182  W   D       Color table 01
 COLOR02      184  W   D       Color table 02
 COLOR03      186  W   D       Color table 03
 COLOR04      188  W   D       Color table 04
 COLOR05      18A  W   D       Color table 05
 COLOR06      18C  W   D       Color table 06
 COLOR07      18E  W   D       Color table 07
 COLOR08      190  W   D       Color table 08
 COLOR09      192  W   D       Color table 09
 COLOR10      194  W   D       Color table 10
 COLOR11      196  W   D       Color table 11
 COLOR12      198  W   D       Color table 12
 COLOR13      19A  W   D       Color table 13
 COLOR14      19C  W   D       Color table 14
 COLOR15      19E  W   D       Color table 15
 COLOR16      1A0  W   D       Color table 16
 COLOR17      1A2  W   D       Color table 17
 COLOR18      1A4  W   D       Color table 18
 COLOR19      1A6  W   D       Color table 19
 COLOR20      1A8  W   D       Color table 20
 COLOR21      1AA  W   D       Color table 21
 COLOR22      1AC  W   D       Color table 22
 COLOR23      1AE  W   D       Color table 23
 COLOR24      1B0  W   D       Color table 24
 COLOR25      1B2  W   D       Color table 25
 COLOR26      1B4  W   D       Color table 26
 COLOR27      1B6  W   D       Color table 27
 COLOR28      1B8  W   D       Color table 28
 COLOR29      1BA  W   D       Color table 29
 COLOR30      1BC  W   D       Color table 30
 COLOR31      1BE  W   D       Color table 31

 HTOTAL       1C0  W   A( E )  Highest number count, horiz line
                                   (VARBEAMEN=1)
 HSSTOP       1C2  W   A( E )  Horizontal line position for HSYNC stop
 HBSTRT       1C4  W   A( E )  Horizontal line position for HBLANK start
 HBSTOP       1C6  W   A( E )  Horizontal line position for HBLANK stop
 VTOTAL       1C8  W   A( E )  Highest numbered vertical line
                                   (VARBEAMEN=1)
 VSSTOP       1CA  W   A( E )  Vertical line position for VSYNC stop
 VBSTRT       1CC  W   A( E )  Vertical line for VBLANK start
 VBSTOP       1CE  W   A( E )  Vertical line for VBLANK stop

              1D0              Reserved
              1D2              Reserved
              1D4              Reserved
              1D6              Reserved
              1D8              Reserved
              1DA              Reserved

 BEAMCON0     1DC  W   A( E )  Beam counter control register (SHRES,PAL)
 HSSTRT       1DE  W   A( E )  Horizontal sync start (VARHSY)
 VSSTRT       1E0  W   A( E )  Vertical sync start   (VARVSY)
 HCENTER      1E2  W   A( E )  Horizontal position for Vsync on interlace
 DIWHIGH      1E4  W   AD( E ) Display window -  upper bits for start, stop

 RESERVED     1110X
 RESERVED     1111X
 NO-OP(NULL)  1FE


Amiga® Hardware Reference Manual: 3 Playfield Hardware

The screen display of the Amiga consists of two basic parts -- playfields,
which are sometimes called backgrounds, and sprites, which are easily
movable graphics objects. This chapter describes how to directly access
hardware registers to form playfields.  The chapter begins with a brief
overview of playfield features and covers the following major topics:

   *  Forming a single "basic" playfield, which is a playfield the same
      size as the display screen.  This section includes concepts that are
      fundamental to forming any playfield.
   *  Forming a dual-playfield display in which one playfield is
      superimposed upon another.  This procedure differs from that of
      forming a basic playfield in some details.
   *  Forming playfields of various sizes and displaying only part of a
      larger playfield.
   *  Moving playfields by scrolling them vertically and horizontally.
   *  Advanced topics to help you use playfields in special situations.

For information about  movable sprite objects , see Chapter 4, Sprite
Hardware.  There are also movable playfield objects, which are subsections
of a playfield.  To move portions of a playfield, you use a technique
called  playfield animation , which is described in Chapter 6, Blitter
Hardware.

For information relating to the playfield hardware in the Enhanced Chip
Set (ECS), such as  SuperHires Mode ,  programmable scan rates  and
 synchronization , see Appendix C.

 About Amiga Playfields
 Forming a Basic Playfield
 Forming a Dual-playfield Display
 Bitplanes and Display Windows of All Sizes
 Moving (Scrolling) Playfields
 Advanced Topics
 Summary of Playfield Registers
 Summary of Color Selection Registers


3 Playfield Hardware / About Amiga Playfields

A playfield forms the basic foundation of an Amiga display and determines
its fundamental characteristics.  To form a playfield, you program the
hardware registers of the custom chips with the basic parameters of the
type of display you want.  Forming a playfield involves selecting the
number of colors, setting up a color table and bitplanes, and selecting
the resolution and display mode.

To understand how Amiga playfields work, it will be helpful to review how
the Amiga's video displays are produced.

 How the Amiga's Video Display is Produced


3 / About Amiga Playfields / How Amiga's Video Display is Produced

The Amiga produces its video displays with raster display techniques. The
picture you see on the screen is made up of a series of horizontal video
lines displayed one after the other.  Each horizontal video line is made
up of a series of pixels.  You create a graphic display by defining one or
more bitplanes in memory and filling them with "1"s and "0"s.  The
combination of the "1"s and "0"s will determine the colors in your display.

        _________________________
    |  |                         |
    |  | ->->->->->->->->->->->- |
    |  | ----------------------- |  Each line represents one sweep of an
    |  | ----------------------- |  electron beam which is "painting" the
    |  |         -------         |  picture as it goes along.
    |  |         -------         |
    |  |      Video Picture      |  The video beam produces each line by
    |  |         -------         |  sweeping from left to right.  It
    |  |         -------         |  produces the full screen by sweeping
    |  | ----------------------- |  the beam from the top to the bottom,
    |  | ----------------------- |  one line at a time.
    |  | ----------------------- |
   \|/ |_________________________|

          Figure 3-1: How the Video Display Picture Is Produced

The video beam produces about 262 video lines from top to bottom, of which
200 normally are visible on the screen with an NTSC system.  With a PAL
system, the beam produces 312 lines, of which 256 are normally visible.
Each complete set of lines (262/NTSC or 312/PAL) is called a display
field. The field time, i.e. the time required for a complete display field
to be produced, is approximately 1/60th of a second for an NTSC system and
approximately 1/50th of a second for PAL. Between display fields, the
video beam traverses the lines that are not visible on the screen and
returns to the top of the screen to produce another display field.

The display area is defined as a grid of pixels.  A pixel is a single
picture element, the smallest addressable part of a screen display.  The
drawings below show what a pixel is and how pixels form displays.

        _________________________
       |                         |
       |                         |
       |    ‘<- - - - - - - - - -|- The picture is formed from many
       |                         |  elements.  Each element is called
       |                         |  a pixel.
       |                         |
       |                         |
       |                         |
       |               ‘         |
       |              ‘‘‘<- - - -|- Pixels are used together to build
       |               ‘         |  larger graphic objects.
       |                         |
       |_________________________|

        _________________________      _________________________
       |                         |    |                         |
       |      _                  |    |                         |
       |<- - |_| - - - - - - - ->|    |<- - - ‘ - - - - - - - ->|
       |                         |    |                         |
       |  320 pixels             |    |   640 pixels            |
       |                         |    |                         |
       |                         |    |                         |
       |                         |    |                         |
       |                         |    |                         |
       |                         |    |                         |
       |                         |    |                         |
       |                         |    |                         |
       |_________________________|    |_________________________|

     In normal resolution mode, 320   In high resolution mode, 640
     pixels fill a horizontal line.   pixels fill a horizontal line.

                     Figure 3-2: What Is a Pixel?

The Amiga offers a choice in both horizontal and vertical resolutions.
Horizontal resolution can be adjusted to operate in low resolution or high
resolution mode. Vertical resolution can be adjusted to operate in
interlaced or non-interlaced mode.

*  In low resolution mode, the normal playfield has a width of 320
   pixels.

*  High resolution mode gives finer horizontal resolution -- 640 pixels
   in the same physical display area.

*  In non-interlaced mode, the normal NTSC playfield has a height of 200
   video lines.   The normal PAL screen has a height of 256 video lines.

*  Interlaced mode gives finer vertical resolution -- lines in the same
   physical display area in NTSC and 512 for PAL.

These modes can be combined, so you can have, for instance, an interlaced,
high resolution display.

Note that the dimensions referred to as "normal" in the previous paragraph
are nominal dimensions and represent the normal values you should expect
to use.  Actually, you can display larger playfields; the
 maximum dimensions  are given in the section called
 Bitplanes and Playfields of All Sizes . Also, the dimensions of the
playfield in memory are often larger than the playfield displayed on the
screen. You choose which part of this larger memory picture to display by
specifying a different size for the display window.

A playfield taller than the screen can be scrolled, or moved smoothly, up
or down.  A playfield wider than the screen can be scrolled horizontally,
from left to right or right to left.  Scrolling is described in the
section called  Moving (Scrolling) Playfields .

In the Amiga graphics system, you can have up to thirty-two different
colors in a single playfield, using normal display methods. You can
control the color of each individual pixel in the playfield display by
setting the bit or bits that control each pixel. A display formed in this
way is called a bitmapped display.

For instance, in a two-color display, the color of each pixel is
determined by whether a single bit is on or off. If the bit is 0, the
pixel is one user-defined color; if the bit is 1, the pixel is another
color. For a four-color display, you build two bitplanes in memory. When
the playfield is displayed, the two bitplanes are overlapped, which means
that each pixel is now two bits deep. You can combine up to five bitplanes
in this way. Displays made up of three, four, or five bitplanes allow a
choice of eight, sixteen, or thirty-two colors, respectively.

The color of a pixel is always determined by the binary combination of the
bits that define it. When the system combines bitplanes for display, the
combination of bits formed for each pixel corresponds to the number of a
color register. This method of coloring pixels is called color
indirection. The Amiga has thirty-two color registers, each containing
bits defining a user-selected color (from a total of 4,096 possible
colors).

Figure 3-3 shows how the combination of up to five bitplanes forms a code
that selects which one of the thirty-two registers to use to display the
color of a playfield pixel.

     _______________
    |
    | ‘          bit-plane 5
    | _\_____________
    ||  \
    || ‘ \        bit-plane 4
     | _\_\_____________
     ||  \ \
     || ‘ \ \      bit-plane 3
      | _\_\_\___________                   Bits from
      ||  \ \ \                               planes     Color
      || ‘ \ \ \    bit-plane 2             5,4,3,2,1  Registers
       | _\_\_\_\__________
       ||  \ \ \ \                                     _________
       || ‘ \ \ \ \  bit-plane 1              00000   |_________|
        | ^\ \ \ \ \                          00001   |_________|
        | | \ \ \ \ \                         00010   |_________|
        | |  \ \ \ \ \                        00011   |_________|
          |   \ \ \ \ \  ___  _ _ _ _ _       00100   |_________|
          |    \ \ \ \ \|   |          |        -     |         |
         One    \ \ \ \ | 1 |                   -     |    |    |
        Pixel    \ \ \ \|___|          |        -     |         |
                  \ \ \ \|   |                  -     |    |    |
                   \ \ \ | 1 |         |        -     |         |
                    \ \ \|___|                  -     |   \|/   |
                     \ \ \|   |        |    \   -     |_________|
                      \ \ | 0 |         - - - 11000   |#########|
                       \ \|___|        |    / 11001   |_________|
                        \ \|   |              11010   |_________|
                         \ | 0 |       |      11011   |_________|
                          \|___|              11100   |_________|
                           \|   |      |      11101   |_________|
                            | 0 |             11110   |_________|
                            |___| _ _ _|      11111   |_________|

           Figure 3-3: How Bitplanes Select a Color

Values in the highest numbered bitplane have the highest significance in
the binary number. As shown in Figure 3-4, the value in each pixel in the
highest-numbered bitplane forms the leftmost digit of the number. The
value in the next highest-numbered bitplane forms the next bit, and so on.

     SAMPLE DATA FOR
       FOUR PIXELS

      1   1   0   0          Data in bitplane 5 -- most significant
      1   0   1   0          Data in bitplane 4
      1   0   0   1          Data in bitplane 3
      0   1   1   1          Data in bitplane 2
      0   0   1   0          Data in bitplane 1 -- least significant

      |   |   |   |
      |   |   |   |
      |   |   |   |_________________ Value 6 -- COLOR6
      |   |   |_____________________ Value 11 -- COLOR11
      |   |_________________________ Value 18 -- COLOR18
      |_____________________________ Value 28 -- COLOR28

     Figure 3-4: Significance of Bitplane Data in Selecting Colors

You also have the choice of defining two separate playfields, each formed
from up to three bitplanes. Each of the two playfields uses a separate set
of eight different colors. This is called  dual-playfield mode .


3 Playfield Hardware / Forming a Basic Playfield

To get you started, this section describes how to directly access hardware
registers to form a single basic playfield that is the same size as the
video screen. Here, "same size" means that the playfield is the same size
as the actual display window. This will leave a small border between the
playfield and the edge of the video screen. The playfield usually does not
extend all the way to the edge of the physical display.

To form a playfield, you need to define these characteristics:

   *  Height and width of the playfield and size of the display window
      (that is, how much of the playfield actually appears on the screen).
   *  Color of each pixel in the playfield.
   *  Horizontal resolution.
   *  Vertical resolution, or interlacing.
   *  Data fetch and modulo, which tell the system how much data to put on
      a horizontal line and how to fetch data from memory to the screen.

In addition, you need to allocate memory to store the playfield, set
pointers to tell the system where to find the data in memory, and
(optionally) write a Copper routine to handle redisplay of the playfield.

 Height and Width of the Playfield
 Bitplanes and Color
 Selecting Horizontal and Vertical Resolution
 Allocating Memory for Bitplanes
 Coding the Bitplanes for Correct Coloring
 Defining the Size of the Display Window
 Telling the System How to Fetch and Display Data
 Displaying and Redisplaying the Playfield
 Enabling the Color Display
 Basic Playfield Summary
 Example of Forming a Basic LORES Playfield
 Example of Forming a Basic HIRES Playfield


3 / Forming a Basic Playfield / Height and Width of the Playfield

To create a playfield that is the same size as the screen, you can use a
width of either 320 pixels or 640 pixels, depending upon the resolution
you choose. The height is either 200 or 400 lines for NTSC, 256 or 512
lines for PAL, depending upon whether or not you choose interlaced mode.


3 / Forming a Basic Playfield / Bitplanes and Color

You define playfield color by:

   1. Deciding how many colors you need and how you want to color
      each pixel.
   2. Loading the colors into the color registers.
   3. Allocating memory for the number of bitplanes you need and setting
      a pointer to each bitplane.
   4. Writing instructions to place a value in each bit in the bitplanes
      to give you the correct color.

Table 3-1 shows how many bitplanes to use for the color selection you need.

                    Number of     Number of
                     Colors       Bitplanes
                    ---------     ---------
                      1 - 2           1
                      3 - 4           2
                      5 - 8           3
                     9 - 16           4
                    17 - 32           5

           Table 3-1: Colors in a Single Playfield

 The Color Table
 Selecting the Number of Bitplanes


3 / / Bitplanes and Color / The Color Table

The color table contains 32 registers, and you may load a different color
into each of the registers. Here is a condensed view of the contents of
the color table:

     Register Name   Contents                Meaning
     -------------   --------                -------
       COLOR00        12 bits        User-defined color for the
                                     background area and borders.

       COLOR01        12 bits        User-defined color number 1
                                     (For example, the alternate color
                                     selection for a two-color playfield).

       COLOR02        12 bits        User-defined color number 2.

          .              .
          .              .
          .	         .

       COLOR31	      12 bits	     User-defined color number 31.

              Table 3-2: Portion of the Color Table

 COLOR00  is always reserved for the background color. The background color
shows in any area on the display where there is no other object present
and is also displayed outside the defined display window, in the border
area.

   Genlocks and the background color.
   ---------------------------------
   If you are using the optional genlock board for  video input  from a
   camera, VCR, or laser disk, the background color will be replaced by
   the incoming video display.

Twelve bits of color selection allow you to define, for each of the 32
registers, one of 4,096 possible colors, as shown in Table 3-3.

                  Bits            Color
                  ----            -----
                  Bits 15 - 12    Unused
                  Bits 11 - 8     Red
                  Bits 7 - 4      Green
                  Bits 3 - 0      Blue

       Table 3-3: Contents of the Color Registers

Table 3-4 shows some sample color register bit assignments and the
resulting colors. At the end of the chapter is a more extensive
 Color Register list .

            Contents of the       Resulting
            Color Register          Color
            ---------------       ---------
                 $FFF               White
                 $6FE               Sky blue
                 $DB9               Tan
                 $000               Black

        Table 3-4: Sample Color Register Contents

Some sample instructions for loading the color registers are shown below:

   LEA     CUSTOM,a0              ; Get base address of custom hardware...
   MOVE.W  #$FFF,COLOR00(a0)      ; Load white into color register 0
   MOVE.W  #$6FE,COLOR01(a0)      ; Load sky blue into color register 1

   The color registers are write-only.
   ----------------------------------
   Only by looking at the screen can you find out the contents of
   each color register.  As a standard practice, then, for these
   and certain other write-only registers, you may wish to keep a
   "back-up" or "shadow" copy in RAM.  As you write to the color
   register itself, you should update this RAM copy.  If you do so,
   you will always know the value each register contains.


3 / / Bitplanes and Color / Selecting the Number of Bitplanes

After deciding how many colors you want and how many bitplanes are
required to give you those colors, you tell the system how many bitplanes
to use.

You select the number of bitplanes by writing the number into the register
 BPLCON0  (for Bitplane Control Register 0) The relevant bits are bits 14,
13, and 12, named BPU2, BPU1, and BPU0 (for "Bitplanes Used"). Table 3-5
shows the values to write to these bits and how the system assigns
bitplane numbers.

          Table 3-5: Setting the Number of Bitplanes

                    Number of     Name(s) of
          Value     Bitplanes     Bitplanes
          -----     ---------     ----------
           000       None *
           001         1           PLANE 1
           010         2           PLANES 1 and 2
           011         3           PLANES 1 - 3
           100         4           PLANES 1 - 4
           101         5           PLANES 1 - 5
           110         6           PLANES 1 - 6 **
           111                     Value not used.

     *  Shows only a background color; no playfield is visible.

     ** Sixth bitplane is used only in  dual-playfield mode  and in
         hold-and-modify mode  (described in the section called
        Advanced Topics.

   About the  BPLCON0  register.
   ----------------------------
   The bits in the  BPLCON0  register cannot be set independently.  To set
   any one bit, you must reload them all.

The following example shows how to tell the system to use two low
resolution bitplanes.

        MOVE.W  #$2200,BPLCON0+CUSTOM   ; Write to it

Because register  BPLCON0  is used for setting other characteristics of the
display and the bits are not independently settable, the example above
also sets other parameters (all of these parameters are described later
in the chapter).

   *   Hold-and-modify mode is turned off.
   *   Single-playfield mode is set.
   *   Composite video color is enabled.  (Not applicable in all models.)
   *   Genlock audio is disabled.
   *   Light pen is disabled.
   *   Interlaced mode is disabled.
   *   External resynchronization is disabled. (genlock)


3 / Basic Playfield / Selecting Horizontal and Vertical Resolution

Standard home television screens are best suited for low resolution
displays. Low resolution mode provides 320 pixels for each horizontal
line. High resolution monochrome and RGB monitors can produce displays in
high resolution mode, which provides 640 pixels for each horizontal line.
If you define an object in low resolution mode and then display it in high
resolution mode, the object will be only half as wide.

To set horizontal resolution mode, you write to bit 15, HIRES, in register
 BPLCON0 :

   High resolution mode -- write 1 to bit 15.
   Low resolution mode -- write 0 to bit 15.

Note that in high resolution mode, you can have up to four bitplanes in
the playfield and, therefore, up to 16 colors.

Interlaced mode allows twice as much data to be displayed in the same
vertical area as in non-interlaced mode. This is accomplished by doubling
the number of lines appearing on the video screen. The following table
shows the number of lines required to fill a normal, non-overscan screen.

                              NTSC      PAL
                              ----      ---
          Non-interlaced      200       256
          Interlaced          400       512

        Table 3-6: Lines in a Normal Playfield

In interlaced mode, the scanning circuitry vertically offsets the start of
every other field by half a scan line.

           _____________________
  line 1 _|_____________________|_
          |_____________________| \
          |      _________      |  \
          |      _________      |   \
          |                     |    \
          |      Odd Field      |     \   _____________________
          |      _________      |      \_|_____________________|_ Line 1
          |      _________      |       _|_|___________________|_ Line 2
          |_____________________|      / |                     |
          |_____________________|     /  | |                   |
          |_____________________|    /   |    Video Display    |
                                    /    | | (400 lines NTSC   |
           _____________________   /     |    512 lines PAL)   |
  line 2 _|_____________________|_/      | |                   |
          |_____________________|        |                     |
          |      _________      |        |\|/                  |
          |      _________      |        |_____________________|
          |                     |
          |      Even Field     |      Same physical space as used
          |      _________      |       by a 200-line (256) PAL),
          |      _________      |         noninterlaced display.
          |_____________________|
          |_____________________|
          |_____________________|

                         Figure 3-5: Interlacing

Even though interlaced mode requires a modest amount of extra work in
setting registers (as you will see later on in this section), it provides
fine tuning that is needed for certain graphics effects. Consider the
diagonal line in Figure 3-6 as it appears in non-interlaced and interlaced
modes. Interlacing eliminates much of the jaggedness or "staircasing" in
the edges of the line.

              ___________________        ___________________
             |#|#| | | | | | | | |      |#|#|_|_|_|_|_|_|_|_|
             |#|#|_|_|_|_|_|_|_|_|      |_|#|#|_|_|_|_|_|_|_|
             | | |#|#| | | | | | |      |_|_|#|#|_|_|_|_|_|_|
             |_|_|#|#|_|_|_|_|_|_|      |_|_|_|#|#|_|_|_|_|_|
             | | | | |#|#| | | | |      |_|_|_|_|#|#|_|_|_|_|
             |_|_|_|_|#|#|_|_|_|_|      |_|_|_|_|_|#|#|_|_|_|
             | | | | | | |#|#| | |      |_|_|_|_|_|_|#|#|_|_|
             |_|_|_|_|_|_|#|#|_|_|      |_|_|_|_|_|_|_|#|#|_|
             | | | | | | | | |#|#|      |_|_|_|_|_|_|_|_|#|#|
             |_|_|_|_|_|_|_|_|#|#|      |_|_|_|_|_|_|_|_|_|#|

                non-interlaced               interlaced

         Figure 3-6: Effect of Interlaced Mode on Edges of Object

When you use the special blitter DMA channel to draw lines or polygons
onto an interlaced playfield, the playfield is treated as one display,
rather than as odd and even fields. Therefore, you still get the smoother
edges provided by interlacing.

To set interlaced or non-interlaced mode, you write to bit 2, LACE, in
register  BPLCON0 :

   Interlaced mode -- write 1 to bit 2.
   Non-interlaced mode -- write 0 to bit 2.

As explained above in  Setting the Number of Bitplanes , bits in
 BPLCON0  are not independently settable.

The following example shows how to specify high resolution and interlaced
modes.

        MOVE.W  #$A204,BPLCON0+CUSTOM   ; Write to it

The example above also sets the following parameters that are also
controlled through register  BPLCON0 :

   *   High resolution mode is enabled.
   *   Two bitplanes are used.
   *   Hold-and-modify mode is disabled.
   *   Single-playfield mode is enabled.
   *   Composite video color is enabled.
   *   Genlock audio is disabled.
   *   Light pen is disabled.
   *   Interlaced mode is enabled.
   *   External resynchronization is disabled.

The amount of memory you need to allocate for each bitplane depends upon
the resolution modes you have selected, because high resolution or
interlaced playfields contain more data and require larger bitplanes.


3 / Forming a Basic Playfield / Allocating Memory for Bitplanes

After you set the number of bitplanes and specify resolution modes, you
are ready to allocate memory. A bitplane consists of an end-to-end
sequence of words at consecutive memory locations. When operating under
the Amiga operating system, use a system call such as AllocMem() to remove
a block of memory from the free list and make it available to the program.

A specialized allocation function named AllocRaster() in the
graphics.library is recommended for all bitplane allocations.
AllocRaster() will pad the allocation to properly align scan lines
for the hardware.

If the machine has been taken over, simply reserve an area of memory for
the bitplanes. Next, set the bitplane pointer registers ( BPLxPTH/BPLxPTL )
to point to the starting memory address of each bitplane you are using.
The starting address is the memory word that contains the bits of the
upper left-hand corner of the bitplane.

Tables 3-7 and 3-8 show how much memory is needed for basic playfield
modes under NTSC and PAL, respectively. You may need to balance your color
and resolution requirements against the amount of available memory you
have.

          Table 3-7: Playfield Memory Requirements, NTSC

                                           Number of Bytes
          Picture Size         Modes        per Bitplane
          ------------         -----       ---------------
           320 X 200      Low resolution,       8,000
                          non-interlaced

           320 X 400      Low resolution,      16,000
                          interlaced

           640 X 200      High resolution,     16,000
                          non-interlaced

           640 X 400      High resolution,     32,000
                          interlaced

Keep in mind that the number of bytes you allocate for a bitplane must be
even.

          Table 3-8: Playfield Memory Requirements, PAL

                                           Number of Bytes
          Picture Size         Modes        per Bitplane
          ------------         -----       ---------------
           320 X 256      Low resolution,       8,192
                          non-interlaced

           320 X 512      Low resolution,      16,384
                          interlaced

           640 X 256      High resolution,     16,384
                          non-interlaced

           640 X 512      High resolution,     32,768
                          interlaced

 NTSC Example of Bitplane Size


3 / / Allocating Memory for Bitplanes / NTSC Example of Bitplane Size

For example, using a normal, NTSC, low resolution, non-interlaced display
with 320 pixels across each display line and a total of 200 display lines,
each line of the bitplane requires 40 bytes (320 bits divided by 8 bits
per byte = 40). Multiply the 200 lines times 40 bytes per line to get
8,000 bytes per bitplane as given above.

A low resolution, non-interlaced playfield made up of two bitplanes
requires 16,000 bytes of memory area. The memory for each bitplane must be
continuous, so you need to have two 8,000-byte blocks of available memory.
Figure 3-7 shows an 8,000-byte memory area organized as 200 lines of 40
bytes each, providing 1 bit for each pixel position in the display plane.

  _______________________________         _______________________________
 |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| ----> |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|

         Memory Location N                     Memory Location N+38
  _______________________________         _______________________________
 |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| ----> |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|

       Memory Location N+40          |         Memory Location N+78
                                     |
                                     |
                                    \|/
  _______________________________         _______________________________
 |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| ----> |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|

      Memory Location N+7960                  Memory Location N+7998

          Figure 3-7: Memory Organization for a Basic Bitplane

Access to bitplanes in memory is provided by two address registers,
 BPLxPTH and BPLxPTL , for each bitplane (12 registers in all). The "x"
position in the name holds the bitplane number; for example BPL1PTH and
BPL1PTL hold the starting address of PLANE 1. Pairs of registers with
names ending in PTH and PTL contain 19-bit addresses. 68000 programmers
may treat these as one 32-bit address and write to them as one long word.
You write to the high order word, which is the register whose name ends in
"PTH."

The example below shows how to set the bitplane pointers. Assuming two
bitplanes, one at $21000 and the other at $25000, the processor sets
BPL1PT to $21000 and BPL2PT to $25000. Note that this is usually the
Copper's task.

;
; Since the bitplane pointer registers are mapped as full 680x0 long-word
; data, we can store the addresses with a 32-bit move...
;
   LEA     CUSTOM,a0              ; Get base address of custom hardware...
   MOVE.L  $21000,BPL1PTH(a0)     ; Write bitplane 1 pointer
   MOVE.L  $25000,BPL2PTH(a0)     ; Write bitplane 2 pointer

Note that the memory requirements given here are for the playfield only.
You may need to allocate additional memory for other parts of the display
--  sprites ,  audio ,  animation  -- and for your application programs.
Memory allocation for other parts of the display is discussed in the
chapters describing those topics.


3 / Basic Playfield / Coding the Bitplanes For Correct Coloring

After you have specified the number of bitplanes and set the bitplane
pointers, you can actually write the color register codes into the
bitplanes.

 A One- or Two-Color Playfield
 A Playfield of Three or More Colors


3 / / Coding For Correct Coloring / A One- or Two-Color Playfield

For a one-color playfield, all you need do is write "0"s in all the bits
of the single bitplane as shown in the example below. This code fills a
low resolution bitplane with the background color ( COLOR00 ) by writing
all "0"s into its memory area. The bitplane starts at $21000 and is 8,000
bytes long.

        LEA     $21000,a0       ; Point at bitplane
        MOVE.W  #2000,d0        ; Write 2000 longwords = 8000 bytes
LOOP:   MOVE.L  #0,(a0)+        ; Write out a zero
        DBRA    d0,LOOP         ; Decrement counter and loop until done...

For a two-color playfield, you define a bitplane that has "0"s where you
want the background color and "1"s where you want the color in register 1.
The following example code is identical to the last example, except the
bitplane is filled with $FF00FF00 instead of all 0's. This will produce
two colors.

        LEA     $21000,a0        ; Point at bitplane
        MOVE.W  #2000,d0         ; Write 2000 longwords = 8000 bytes
LOOP:   MOVE.L  #$FF00FF00,(a0)+ ; Write out $FF00FF00
        DBRA    d0,LOOP        	; Decrement counter and loop until done...


3 / / Correct Coloring / A Playfield of Three or More Colors

For three or more colors, you need more than one bitplane. The task here
is to define each bitplane in such a way that when they are combined for
display, each pixel contains the correct combination of bits. This is a
little more complicated than a playfield of one bitplane. The following
examples show a four-color playfield, but the basic idea and procedures
are the same for playfields containing up to 32 colors.

Figure 3-8 shows two bitplanes forming a four-color playfield:

        Image in                          Results in a display
       bitplane 2            _____          similar to this:
                            |     |
            +---------------- 0 1 | Color 1 -------+
            |               |___ _|                |
            |                   |                  |
            |                   |                  |
          +---+               +---+                |
     0 0 0|0 0|0 0 0     0 0 0|1 1|0 0 0          ***
          |   |               |   |               ***
     0 0 0|0 0|0 0 0     0 0 0|1 1|0 0 0          ***
          |   |               |   |               ***
     0 0 0|0 0|0 0 0     0 0 0|1 1|0 0 0          ***
          +---+               +---+               ***
     1 1 1 0 0 1 1 1     1 1 1 0 0 1 1 1    ······   ······
                                            ······   ······
     1 1 1 0 0 1 1 1     1 1 1 0 0 1 1 1    ······  \······
          +---+               +---+               ···\
     0 0 0|1 1|0 0 0     0 0 0|1 1|0 0 0          ··· \
          |   |               |   |               ···  \
     0 0 0|1 1|0 0 0     0 0 0|1 1|0 0 0          ···   \__   Color 00
          |   |               |   |               ···       (background)
     0 0 0|1 1|0 0 0     0 0 0|1 1|0 0 0          ···
          +---+               +---+                |
            |                   |                  |
            |                ___|_                 |
            |               |     |                |
            +---------------- 1 1 | Color 3 -------+
                            |_____|

                 Figure 3-8: Combining Bitplanes

You place the correct "1"s and "0"s in both bitplanes to give each pixel
in the picture above the correct color.

In a single playfield you can combine up to five bitplanes in this way.
Using five bitplanes allows a choice of 32 different colors for any single
pixel. The playfield  color selection charts  at the end of this chapter
summarize the bit combinations for playfields made from four and five
bitplanes.


3 / Forming Basic Playfield / Defining the Size of the Display Window

After you have completely defined the playfield, you need to define the
size of the display window, which is the actual size of the on-screen
display. Adjustment of display window size affects the entire display
area, including the border and the  sprites , not just the playfield. You
cannot display objects outside of the defined display window. Also, the
size of the border around the playfield depends on the size of the display
window.

The basic playfield described in this section is the same size as the
screen display area and also the same size as the display window. This is
not always the case; often the display window is smaller than the actual
"big picture" of the playfield as defined in memory (the raster).

A display window that is smaller than the playfield allows you to
displaysome segment of a large playfield or  scroll the playfield  through
the window. You can also define display windows larger than the basic
playfield.  These larger playfields and different-sized display windows
are described in the section below called
 Bitplanes and Display Windows of All Sizes .

You define the size of the display window by specifying the vertical and
horizontal positions at which the window starts and stops and writing
these positions to the display window registers. The resolution of
vertical start and stop is one scan line. The resolution of horizontal
start and stop is one low resolution pixel. Each position on the screen
defines the horizontal and vertical position of some pixel, and this
position is specified by the x and y coordinates of the pixel. This
document shows the x and y coordinates in this form:  (x,y).

Although the coordinates begin at (0,0) in the upper left-hand corner of
the screen, the first horizontal position normally used is $81 and the
first vertical position is $2C. The horizontal and vertical starting
positions are the same both for NTSC and for PAL.

The hardware allows you to specify a starting position before ($81,$2C),
but part of the display may not be visible. The difference between the
absolute starting position of (0,0) and the normal starting position of
($81,$2C) is the result of the way many video display monitors are
designed.

To overcome the distortion that can occur at the extreme edges of the
screen, the scanning beam sweeps over a larger area than the front face of
the screen can display. A starting position of ($81,$2C) centers a normal
size display, leaving a border of eight low resolution pixels around the
display window. Figure 3-9 shows the relationship between the normal
display window, the visible screen area, and the area actually covered by
the scanning beam.

  ($81,$2C) __
              \
       (0,0) __\
               \\
                \\
                 +\----------------------------+
                 |#\###########################|
                 |##\##########################|
                 |###+---------------------+###|
                 |###|  _ _ _ _ _ _ _ _ _  |###|  __ visible screen
                 |###| |   |             | |###| /     boundaries
                 |###|     |               |###|/
                 |###| |----- 320 -------| |###/
                 |###|     |               |##/|
                 |###| |   |             | |#/#|
                 |###|     |               |/##|
                 |###| |                 | |###|
                 |###|    200              |###|
                 |###| |                 | |###|
                 |###|     |               |###|
                 |###| |   |             | |###|
                 |###|     |               |###|
                 |###| |_ _|_ _ _ _ _ _ _| |###|
                 |###|  \               /  |###|
                 |###+---\-------------/---+###|
                 |########\###########/########|
                 |#########\#########/#########|
                 +----------\-------/----------+
                             \     /
                              \   /
                          display window
                 starting and stopping positions

          Figure 3-9: Positioning the On-screen Display

 Setting the Display Window Starting Position
 Setting the Display Window Stopping Position


3 / / Size Display Window / Setting Display Window Starting Position

A horizontal starting position of approximately $81 and a vertical
starting position of approximately $2C centers the display on most
standard television screens. If you select high resolution mode (640
pixels horizontally) or interlaced mode (400 lines NTSC, 512 PAL) the
starting position does not change. The starting position is always
interpreted in low resolution, non-interlaced mode. In other words, you
select a starting position that represents the correct coordinates in low
resolution, non-interlaced mode.

The register  DIWSTRT  (for "Display Window Start") controls the display
window starting position. This register contains both the horizontal and
vertical components of the display window starting positions, known
respectively as HSTART and VSTART. The following example sets DIWSTRT for
a basic playfield. You write $2C for VSTART and $81 for HSTART.

     LEA     CUSTOM,a0            ; Get base address of custom hardware...
     MOVE.W  #$2C81,DIWSTRT(a0)   ; Display window start register...


3 / / Size Display Window / Setting Display Window Stopping Position

You also need to set the display window stopping position, which is the
lower right-hand corner of the display window. If you select high
resolution or interlaced mode, the stopping position does not change. Like
the starting position, it is interpreted in low resolution, non-interlaced
mode.

The register  DIWSTOP  (for Display Window Stop) controls the display window
stopping position. This register contains both the horizontal and vertical
components of the display window stopping positions, known respectively as
HSTOP and VSTOP. The instructions below show how to set HSTOP and VSTOP
for the basic playfield, assuming a starting position of ($81,$2C). Note
that the HSTOP value you write is the actual value minus 256 ($100). The
HSTOP position is restricted to the right-hand side of the screen. The
normal HSTOP value is ($1C1) but is written as ($C1). HSTOP is the same
both for NTSC and for PAL.

The VSTOP position is restricted to the lower half of the screen. This is
accomplished in the hardware by forcing the MSB of the stop position to be
the complement of the next MSB. This allows for a VSTOP position greater
than 256 ($100) using only 8 bits. Normally, the VSTOP is set to ($F4) for
NTSC, ($2C) for PAL.

   The normal NTSC  DIWSTRT  is ($2C81).
   The normal NTSC DIWSTOP is ($F4C1).

   The normal PAL  DIWSTRT  is ($2C81).
   The normal PAL DIWSTOP is ($2CC1).

The following example sets DIWSTOP for a basic playfield to $F4 for the
vertical position and $C1 for the horizontal position.

  LEA     CUSTOM,a0               ; Get base address of custom hardware...
  MOVE.W  #$F4C1,DIWSTOP(a0)      ; Display window stop register...

            Table 3-9:  DIWSTRT  and DIWSTOP Summary

                  Nominal Values            Possible Values
                  --------------            ---------------

                 NTSC          PAL          MIN          MAX
                 ----          ---          ---          ---
    DIWSTRT :
   ----------
       VSTART    $2C           $2C          $00          $FF
       HSTART    $81           $81          $00          $FF
     DIWSTOP:
     --------
        VSTOP    $F4           $2C (=$12C)  $80          $7F (=$17F)
        HSTOP    $C1           $C1          $00 (=$100)  $FF (=$1FF)

The minimum and maximum values for display windows have been extended
in the enhanced version of the Amiga's custom chip set (ECS).  See
Appendix C, Enhanced Chip Set for more information about the
 display window registers .


3 / Basic Playfield / Telling the System How to Fetch and Display Data

After defining the size and position of the display window, you need to
give the system the on-screen location for data fetched from memory. To do
this, you describe the horizontal positions where each line starts and
stops and write these positions to the data-fetch registers. The
data-fetch registers have a four-pixel resolution (unlike the display
window registers, which have a one-pixel resolution). Each position
specified is four pixels from the last one. Pixel 0 is position 0; pixel 4
is position 1, and so on.

The data-fetch start and display window starting positions interact with
each other. It is recommended that data-fetch start values be restricted
to a programming resolution of 16 pixels (8 clocks in low resolution mode,
4 clocks in high resolution mode). The hardware requires some time after
the first data fetch before it can actually display the data. As a result,
there is a difference between the value of window start and data-fetch
start of 4.5  color clocks.

   The normal low resolution DDFSTRT is ($0038).
   The normal high resolution DDFSTRT is ($003C).

Recall that the hardware resolution of display window start and stop is
twice the hardware resolution of data fetch:

          $81
          ---  - 8.5 = $38
           2

          $81
          ---  - 4.5 = $3C
           2

The relationship between data-fetch start and stop is

   DDFSTRT = DDFSTOP - (8 * (word count - 1)) for low resolution
   DDFSTRT = DDFSTOP - (4 * (word count - 2)) for high resolution

The normal low resolution DDFSTOP is ($00D0). The normal high resolution
DDFSTOP is ($00D4).

The following example sets data-fetch start to $0038 and data-fetch stop
to $00D0 for a basic playfield.

        LEA     CUSTOM,a0               ; Point to base hardware address
        MOVE.W  #$0038,DDFSTRT(a0)      ; Write to DDFSTRT
        MOVE.W  #$00D0,DDFSTOP(a0)      ; Write to DDFSTOP

You also need to tell the system exactly which bytes in memory belong on
each horizontal line of the display. To do this, you specify the modulo
value. Modulo refers to the number of bytes in memory between the last
word on one horizontal line and the beginning of the first word on the
next line. Thus, the modulo enables the system to convert bitplane data
stored in linear form (each data byte at a sequentially increasing memory
address) into rectangular form (one "line" of sequential data followed by
another line). For the basic playfield, where the playfield in memory is
the same size as the display window, the modulo is zero because the memory
area contains exactly the same number of bytes as you want to display on
the screen. Figures 3-10 and 3-11 show the basic bitplane layout in memory
and how to make sure the correct data is retrieved.

The bitplane address pointers ( BPLxPTH and BPLxPTL ) are used by the
system to fetch the data to the screen. These pointers are dynamic; once
the data fetch begins, the pointers are continuously incremented to point
to the next word to be fetched (data is fetched two bytes at a time). When
the end-of-line condition is reached (defined by the data-fetch register,
DDFSTOP) the modulo is added to the bitplane pointers, adjusting the
pointer to the first word to be fetched for the next horizontal line.

  _______________________________________________________________________
 |                                                                       |
 |   Data for line 1:                                                    |
 |                                                                       |
 | Location:     START      START+2       START+4    ...      START+38   |
 |               -----      -------       -------             --------   |
 |              leftmost   next word     next word          last display |
 |            display word                                      word     |
 |                                                                       |
 |                                                               /|\     |
 |                       Screen data fetch stops (DDFSTOP) for    |      |
 |                       each horizontal line after the last      |      |
 |                       word on the line has been fetched________|      |
 |_______________________________________________________________________|

        Figure 3-10: Data Fetched for the First Line When Modulo = 0

After the first line is fetched, the bitplane pointers
 BPLxPTH and BPLxPTL  contain the value START+40. The modulo (in this
case, 0) is added to the current value of the pointer, so when the pointer
begins the data fetch for the next line, it fetches the data you want on
that line. The data for the next line begins at memory location START+40.

  _______________________________________________________________________
 |                                                                       |
 |   Data for line 2:                                                    |
 |                                                                       |
 | Location:    START+40     START+42     START+44    ...     START+78   |
 |              --------     --------     --------            --------   |
 |              leftmost     next word    next word         last display |
 |            display word                                      word     |
 |_______________________________________________________________________|

       Figure 3-11: Data Fetched for the Second Line When Modulo = 0

Note that the pointers always contain an even number, because data is
fetched from the display a word at a time.

There are two modulo registers -- BPL1MOD for the odd-numbered bitplanes
and BPL2MOD for the even-numbered bitplanes. This allows for differing
modulos for each playfield in  dual-playfield mode . For normal
applications, both BPL1MOD and BPL2MOD will be the same.

The following example sets the modulo to 0 for a low resolution playfield
with one bitplane. The bitplane is odd-numbered.

        MOVE.W  #0,BPL1MOD+CUSTOM       ; Set modulo to 0

 Data Fetch in High resolution Mode
 Modulo in Interlaced Mode


3 / / How to Fetch and Display Data / in High resolution Mode

When you are using high resolution mode to display the basic playfield,
you need to fetch 80 bytes for each line, instead of 40.


3 / / How to Fetch and Display Data / Modulo in Interlaced Mode

For interlaced mode, you must redefine the modulo, because interlaced mode
uses two separate scannings of the video screen for a single display of
the playfield. During the first scanning, the odd-numbered lines are
fetched to the screen; and during the second scanning, the even-numbered
lines are fetched.

The bitplanes for a full-screen-sized, interlaced display are 400 NTSC
(512 PAL), rather than 200 NTSC (256 PAL), lines long. Assuming that the
playfield in memory is the normal 320 pixels wide, data for the interlaced
picture begins at the following locations (these are all byte addresses):

                    Line 1   START
                    Line 2   START+40
                    Line 3   START+80
                    Line 4   START+120

and so on. Therefore, you use a modulo of 40 to skip the lines in the
other field. For odd fields, the bitplane pointers begin at START. For
even fields, the bitplane pointers begin at START+40.

You can use the Copper to handle resetting of the bitplane pointers for
interlaced displays.


3 / Basic Playfield / Displaying and Redisplaying the Playfield

You start playfield display by making certain that the bitplane pointers
are set and bitplane DMA is turned on. You turn on bitplane DMA by writing
a 1 to bit BPLEN in the  DMACON  (for DMA control) register. See Chapter
7, System Control Hardware, for instructions on setting this register.

Each time the playfield is redisplayed, you have to reset the bitplane
pointers. Resetting is necessary because the pointers have been
incremented to point to each successive word in memory and must be
repointed to the first word for the next display. You write
 Copper instructions  to handle the redisplay or perform this operation as
part of a  vertical blanking  task.


3 / Forming a Basic Playfield / Enabling the Color Display

The stock A1000 has a color composite output and requires bit 9 (COLOR_ON)
set in  BPLCON0  to create a color composite display signal. Without the
addition of specialized hardware, the A500, A2000 and A3000 cannot
generate color composite output.

   NOTE:
   -----
   The color burst enable does not affect the RGB video signal. RGB
   video is correctly generated regardless of the output of the
   composite video signal.


3 / Forming a Basic Playfield / Basic Playfield Summary

The steps for defining a basic playfield are summarized below:

1. Define Playfield Characteristics
   --------------------------------
   a.  Specify color  for each pixel:

      * Load desired colors in color table registers.

      * Define color of each pixel in terms of the binary value
        that points at the desired color register.

      * Build bitplanes and set bitplane registers:

           Bits 12-14 in  BPLCON0  - number of bitplanes ( BPU2 - BPU0 ).
            BPLxPTH  - pointer to bitplane starting position in memory
                   (written as a long word).

   b.  Specify resolution :

      * Low resolution:

          320 pixels in each horizontal line.
          Clear bit 15 in register  BPLCON0  ( HIRES ).

      * High resolution:

          640 pixels in each horizontal line.
          Set bit 15 in register  BPLCON0  ( HIRES ).

   c.  Specify interlaced or non-interlaced mode :

      * Interlaced mode:

          400 vertical lines for NTSC, 512 for PAL.
          Set bit 2 in register  BPLCON0  ( LACE ).

      * Non-interlaced mode:

          200 vertical lines for NTSC, 256 for PAL.
          Clear bit 2 in  BPLCON0  ( LACE ).

2.  Allocate Memory . To calculate data-bytes in the total bitplanes,
   -----------------  use the following formula:

          Bytes per line * lines in playfield * number of bitplanes

3.  Define Size of Display Window .
   -------------------------------
   * Write start position of display window in  DIWSTRT :

      Horizontal position in bits 0 through 7 (low order bits).
      Vertical position in bits 8 through 15 (high order bits).

   * Write stop position of display window in  DIWSTOP :

      Horizontal position in bits 0 through 7.
      Vertical position in bits 8 through 15.

4.  Define Data Fetch . Set registers  DDFSTRT  and  DDFSTOP :
   -------------------
   * For  DDFSTRT , use the horizontal position as shown in
      Setting the Display Window Starting Position .

   * For  DDFSTOP , use the horizontal position as shown in
      Setting the Display Window Stopping Position .

5.  Define Modulo . Set registers  BPL1MOD and BPL2MOD .  Set modulo to 0
   ---------------  for non-interlaced, 40 for interlaced.

6. Write Copper Instructions To Handle  Redisplay .
   -----------------------------------------------

7.  Enable Color Display .For the A1000: set bit 9 in  BPLCON0  to enable the
   ---------------------- the color display on a composite video monitor.
                          RGB video is not affected.  Only the A1000 has
                          color composite video output, other Amiga models
                          cannot enable this feature using standard
                          hardware.


3 Playfield Hardware / Forming a Dual-playfield Display

For more flexibility in designing your background display, you can specify
two playfields instead of one.  In dual-playfield mode, one playfield is
displayed directly in front of the other.  For example, a computer game
display might have some action going on in one playfield in the
background, while the other playfield is showing a control panel in the
foreground. You can then change either the foreground or the background
without having to redesign the entire display. You can also move the two
playfields independently.

A dual-playfield display is similar to a single-playfield display,
differing only in these aspects:

   *  Each playfield in a dual display is formed from one, two or three
      bitplanes.

   *  The colors in each playfield (up to seven plus transparent) are
      taken from different sets of color registers.

   *  You must set a bit to activate dual-playfield mode.

Figure 3-12 shows a dual-playfield display.

     Figure 3-12: A Dual-playfield Display

In Figure 3-12, one of the colors in each playfield is "transparent"
(color 0 in playfield 1 and color 8 in playfield 2). You can use
transparency to allow selected features of the background playfield to
show through.

In dual-playfield mode, each playfield is formed from up to three
bitplanes.  Color registers 0 through 7 are assigned to playfield 1,
depending upon how many bitplanes you use.  Color registers 8 through 15
are assigned to playfield 2.

 Bitplane Assignment in Dual-Playfield Mode
 Color Registers in Dual-Playfield Mode
 Dual-Playfield Priority and Control
 Activating Dual-Playfield Mode
 Dual Playfield Summary


3 / Dual-playfield / Bitplane Assignment in Dual-Playfield Mode

The three odd-numbered bitplanes (1, 3, and 5) are grouped together by the
hardware and may be used in playfield 1. Likewise, the three even-numbered
bitplanes (2, 4, and 6) are grouped together and may be used in playfield
2. The bitplanes are assigned alternately to each playfield, as shown in
Figure 3-13.

   About dual-playfield bitplanes.
   -------------------------------
   In high resolution mode, you can have up to two bitplanes in each
   playfield -- bitplanes 1 and 3 in playfield 1 and bitplanes 2 and 4
   in playfield 2.

        Number of
        Bitplanes
       "turned on."     Plafield 1 *            Playfield 2 *
       ------------------------------------------------------
            0              none                     none
                       ____________
                      |            |
            1         | 1          |
                      |            |
                      |____________|
                       ____________            ____________
                      |            |          |            |
            2         | 1          |          | 2          |
                      |            |          |            |
                      |____________|          |____________|
                       ____________            ____________
                      |            |          |            |
            3         | 1 _________|__        | 2          |
                      |  |            |       |            |
                      |__| 3          |       |____________|
                         |            |
                         |____________|
                       ____________            ____________
                      |            |          |            |
            4         | 1 _________|__        | 2 _________|__
                      |  |            |       |  |            |
                      |__| 3          |       |__| 4          |
                         |            |          |            |
                         |____________|          |____________|
                       ____________            ____________
                      |            |          |            |
            5         | 1 _________|__        | 2 _________|__
                      |  |            |       |  |            |
                      |__| 3 _________|__     |__| 4          |
                         |  |            |       |            |
                         |__| 5          |       |____________|
                            |            |
                            |____________|
                       ____________            ____________
                      |            |          |            |
            6         | 1 _________|__        | 2 _________|__
                      |  |            |       |  |            |
                      |__| 3 _________|__     |__| 4 _________|__
                         |  |            |       |  |            |
                         |__| 5          |       |__| 6          |
                            |            |          |            |
                            |____________|          |____________|

                    * Note: Either playfield may be placed "in front of"
                            or "behind" the other using the "swap-bit."

        Figure 3-13: How Bitplanes Are Assigned to Dual Playfields


3 / Dual-playfield Display / Color Registers in Dual-Playfield Mode

When you are using dual playfields, the hardware interprets color numbers
for playfield 1 from the bit combinations of bitplanes 1, 3, and 5.  Bits
from PLANE 5 have the highest significance and form the most significant
digit of the color register number. Bits from PLANE 0 have the lowest
significance. These bit combinations select the first eight color
registers from the color palette as shown in Table 3-10.

                             PLAYFIELD 1

                          Bit          Color
                      Combination     Selected
                      -----------     --------
                          000     Transparent mode
                          001          COLOR1
                          010          COLOR2
                          011          COLOR3
                          100          COLOR4
                          101          COLOR5
                          110          COLOR6
                          111          COLOR7

     Table 3-10: Playfield 1 Color Registers -- Low resolution Mode

The hardware interprets color numbers for playfield 2 from the bit
combinations of bitplanes 2, 4, and 6. Bits from PLANE 6 have the highest
significance. Bits from PLANE 2 have the lowest significance. These bit
combinations select the color registers from the second eight colors in
the color table as shown in Table 3-11.

                             PLAYFIELD 2

                          Bit          Color
                      Combination     Selected
                      -----------     --------
                          000     Transparent mode
                          001          COLOR9
                          010          COLOR10
                          011          COLOR11
                          100          COLOR12
                          101          COLOR13
                          110          COLOR14
                          111          COLOR15

     Table 3-11: Playfield 2 Color Registers -- Low resolution Mode

Combination 000 selects transparent mode, to show the color of whatever
object (the other playfield, a sprite, or the background color) may be
"behind" the playfield.

Table 3-12 shows the color registers for high resolution, dual-playfield
mode.

                             PLAYFIELD 1

                          Bit          Color
                      Combination     Selected
                      -----------     --------
                          00      Transparent mode
                          01           COLOR1
                          10           COLOR2
                          11           COLOR3

                             PLAYFIELD 2

                          Bit          Color
                      Combination     Selected
                      -----------     --------
                          00      Transparent mode
                          01           COLOR9
                          10           COLOR10
                          11           COLOR11

     Table 3-12: Playfields 1 and 2 Color Registers -- High resolution Mode


3 / Dual-playfield Display / Dual-Playfield Priority and Control

Either playfield 1 or 2 may have priority; that is, either one may be
displayed in front of the other. Playfield 1 normally has priority. The
bit known as PF2PRI (bit 6) in register  BPLCON2  is used to control
priority. When PF2PRI = 1, playfield 2 has priority over playfield 1. When
PF2PRI = 0, playfield 1 has priority.

You can also control the relative  priority of playfields  and  sprites .
Chapter 7, System Control Hardware, shows you how to control the priority
of these objects.

You can control the two playfields separately as follows:

   *  They can have  different-sized  representations in memory, and
      different portions of each one can be selected for display.

   *  They can be  scrolled  separately.

   An important warning.
   ---------------------
   You must take special care when scrolling one playfield and holding
   the other stationary. When you are scrolling low resolution
   playfields, you must fetch one word more than the width of the
   playfield you are trying to scroll (two words more in high resolution
   mode) in order to provide some data to display when the actual
   scrolling takes place. Only one data-fetch start register and one
   data-fetch stop register are available, and these are shared by both
   playfields. If you want to scroll one playfield and hold the other,
   you must adjust the data-fetch start and data-fetch stop to handle
   the playfield being scrolled. Then, you must adjust the modulo and
   the bitplane pointers of the playfield that is not being scrolled to
   maintain its position on the display. In low resolution mode, you
   adjust the pointers by -2 and the modulo by -2. In high resolution
   mode, you adjust the pointers by -4 and the modulo by -4.


3 / Forming a Dual-playfield Display / Activating Dual-Playfield Mode

Writing a 1 to bit 10 (called DBLPF) of the bitplane control register
 BPLCON0  selects dual-playfield mode. Selecting dual-playfield mode changes
both the way the hardware groups the bitplanes for color interpretation --
all odd-numbered bitplanes are grouped together and all even-numbered
bitplanes are grouped together, and the way hardware can move the
bitplanes on the screen.


3 / Forming a Dual-playfield Display / Dual Playfield Summary

The steps for defining dual playfields are almost the same as those for
defining the basic playfield. Only in the following steps does the
dual-playfield creation process differ from that used for the basic
playfield:

   *   Loading colors into the registers .
      -----------------------------------
      Keep in mind that color registers 0-7 are used by playfield 1
      and registers 8 through 15 are used by playfield 2 (if there are
      three bitplanes in each playfield).

   *   Building bitplanes .
      --------------------
      Recall that playfield 1 is formed from PLANES 1, 3, and 5 and
      playfield 2 from PLANES 2, 4, and 6.

   *   Setting the modulo registers .
      ------------------------------
      Write the modulo to both  BPL1MOD and BPL2MOD  as you will be
      using both odd- and even-numbered bitplanes.

These steps are added:

   *   Defining priority .
      -------------------
      If you want playfield 2 to have priority, set bit 6 (PF2PRI)
      in  BPLCON2  to 1.

   *   Activating dual-playfield mode .
      --------------------------------
      Set bit 10 ( DBLPF ) in  BPLCON0  to 1.


3 Playfield Hardware / Bitplanes and Display Windows of All Sizes

You have seen how to form single and dual playfields in which the
playfield in memory is the same size as the display window. This section
shows you how to define and use a playfield whose big picture in memory is
larger than the display window, how to define display windows that are
larger or smaller than the normal playfield size, and how to move the
display window in the big picture.

 When the Big Picture is Larger than the Display Window
 Maximum Display Window Size


3 / All Sizes / When the Big Picture is Larger than the Display Window

If you design a memory picture larger than the display window, you must
choose which part of it to display. Displaying a portion of a larger
playfield differs in the following ways from displaying the basic
playfields described up to now:

   *  If the big picture in memory is larger than the display window,
      you must respecify the modulos. The modulo must be some value
      other than 0.

   *  You must allocate more memory for the larger memory picture.

 Specifying the Modulo
 Specifying the Data Fetch
 Memory Allocation
 Selecting the Display Window Starting Position
 Selecting the Stopping Position


3 / / When Picture is Larger than Window / Specifying the Modulo

For a memory picture wider than the display window, you need to respecify
the modulo so that the correct data words are fetched for each line of the
display. As an example, assume the display window is the standard 320
pixels wide, so 40 bytes are to be displayed on each line. The big picture
in memory, however, is exactly twice as wide as the display window, or 80
bytes wide. Also, assume that you wish to display the left half of the big
picture. Figure 3-14 shows the relationship between the big picture and
the picture to be displayed.

       START                                                 START+78
          __________________________|___________________________
         |                          |                           |
         |<-------------------------+-------------------------->|
         |       Width of the bit-plane defined in RAM          |
         |                          |                           |
         |<------------------------>|                           |
         | Width of defined screen  |                           |
         | on which bit-plane data  |                           |
         |      is to appear        |                           |
         |                          |                           |
         |                          |                           |

           Figure 3-14: Memory Picture Larger than the Display

Because 40 bytes are to be fetched for each line, the data fetch for line
1 is as shown in Figure 3-15.

  _______________________________________________________________________
 |                                                                       |
 |   Data for line 1:                                                    |
 |                                                                       |
 | Location:     START      START+2       START+4    ...      START+38   |
 |               -----      -------       -------             --------   |
 |              leftmost   next word     next word          last display |
 |            display word                                      word     |
 |                                                                       |
 |                                                               /|\     |
 |                       Screen data fetch stops ( DDFSTOP ) for  |      |
 |                       each horizontal line after the last      |      |
 |                       word on the line has been fetched________|      |
 |_______________________________________________________________________|

        Figure 3-15: Data Fetch for the First Line When Modulo = 40

At this point,  BPLxPTH and BPLxPTL  contain the value START+40. The
modulo, which is 40, is added to the current value of the pointer so that
when it begins the data fetch for the next line, it fetches the data that
you intend for that line. The data fetch for line 2 is shown in Figure
3-16.

  _______________________________________________________________________
 |                                                                       |
 |   Data for line 2:                                                    |
 |                                                                       |
 | Location:    START+80     START+82     START+84    ...     START+118  |
 |              --------     --------     --------            ---------  |
 |              leftmost     next word    next word         last display |
 |            display word                                      word     |
 |_______________________________________________________________________|

        Figure 3-16: Data Fetch for the Second Line When Modulo = 40

To display the right half of the big picture, you set up
 vertical blanking  routine to start the bitplane pointers at location
START+40 rather than START with the modulo remaining at 40. The data
layout is shown in Figures 3-17 and 3-18.

  _______________________________________________________________________
 |                                                                       |
 |   Data for line 1:                                                    |
 |                                                                       |
 | Location:    START+40     START+42     START+44    ...     START+78   |
 |              --------     --------     --------            --------   |
 |              leftmost     next word    next word         last display |
 |            display word                                      word     |
 |_______________________________________________________________________|

    Figure 3-17: Data Layout for First Line -- Right Half of Big Picture

Now, the bitplane pointers contain the value START+80. The modulo (40) is
added to the pointers so that when they begin the data fetch for the
second line, the correct data is fetched.

  _______________________________________________________________________
 |                                                                       |
 |   Data for line 2:                                                    |
 |                                                                       |
 | Location:    START+120    START+122    START+124    ...    START+158  |
 |              ---------    ---------    ---------           ---------  |
 |              leftmost     next word    next word         last display |
 |            display word                                      word     |
 |_______________________________________________________________________|

    Figure 3-18: Data Layout for Second Line -- Right Half of Big Picture

Remember, in high resolution mode, you need to fetch twice as many bytes
as in low resolution mode. For a normal-sized display, you fetch 80 bytes
for each horizontal line instead of 40.


3 / / When Picture is Larger than Window / Specifying the Data Fetch

The data-fetch registers specify the beginning and end positions for data
placement on each horizontal line of the display. You specify  data fetch
in the same way as shown in the section called "Forming a Basic Playfield."


3 / / When Picture is Larger than Display Window / Memory Allocation

For larger memory pictures, you need to allocate more memory. Here is a
formula for calculating memory requirements in general:

     bytes per line * lines in playfield * # of bitplanes

The number of bytes must be even.  Thus, if the wide playfield described
in this section is formed from two bitplanes, it requires:

            80 * 200 * 2 = 32,000 bytes of memory

Recall that this is the memory requirement for the playfield alone. You
need more memory for any  sprites ,  animation ,  audio , or application
programs you are using.

The amount of Chip memory is one of the basic constraints on the size of
playfields.  For instance, a playfield 2000 by 2000 pixels with five
bitplanes would exceed even the two megabytes of Chip memory possible on
an Amiga 3000.  Another constraint on playfield size is the bit plane
modulos which limit the width (but not the height) of a playfield to
262,144 pixels.

As a practical matter, the blitter size registers also limit the size of
playfields (unless the 680x0 CPU is used for drawing operations).  With
the original chip set the largest area the blitter can draw in is 1008 by
1024.  With the Enhanced Chip Set (ECS), the largest area the blitter can
draw in is increased to 16368 by 16384 pixels.  For more information on
ECS and  blitter limits  refer to Appendix C, Enhanced Chip Set.


3 / / Picture Larger / Selecting the Display Window Starting Position

The display window starting position is the horizontal and vertical
coordinates of the upper left-hand corner of the display window. One
register,  DIWSTRT , holds both the horizontal and vertical coordinates,
known as HSTART and VSTART. The eight bits allocated to HSTART are
assigned to the first 256 positions, counting from the leftmost possible
position. Thus, you can start the display window at any pixel position
within this range.

      0                         255                      511 ($1FF)
       __________________________|___________________________
      |                          |                           |
      |                          |                           |
      |<------------------------>|                           |
      |        HSTART of         |                           |
      |  DISPLAY WINDOW occurs   |                           |
      |     is this region       |                           |
      |                          |                           |
      |                          |                           |
      |                          |                           |
      |                          |                           |
      |                          |                           |
      |                          |                           |
      |                          |                           |
      |__________________________|___________________________|

      Figure 3-19: Display Window Horizontal Starting Position

The eight bits allocated to VSTART are assigned to the first 256 positions
counting down from the top of the display.

       ______________________________________________________
      |                                  /|\                 |  0
      |                                   |                  |
      |                         VSTART of |                  |
      |                    DISPLAY WINDOW |                  |
      |                         occurs in |                  |
      |                       this region |                  |
      |                                   |                  |
      |                                   |                  |
      |                                  \|/                 |
      |------------------------------------------------------+- 255
      |                                                      |
 262 -+------------------- (NTSC)                            |
      |                                                      |
      |______________________________________________________|  383 ($17F)

       Figure 3-20: Display Window Vertical Starting Position

Recall that you select the values for the starting position as if the
display were in low resolution, non-interlaced mode. Keep in mind, though,
that for interlaced mode the display window should be an even number of
lines in height to allow for equal-sized odd and even fields.

To set the display window starting position, write the value for HSTART
into bits 0 through 7 and the value for VSTART into bits 8 through 15 of
 DIWSTRT .


3 / / Picture is Larger than Window / Selecting the Stopping Position

The stopping position for the display window is the horizontal and
vertical coordinates of the lower right-hand corner of the display window.
One register,  DIWSTOP , contains both coordinates, known as HSTOP and
VSTOP.

See the notes in the "Forming a Basic Playfield" section for instructions
on setting these registers.

      0                         255                      511 ($1FF)
       __________________________|___________________________
      |                          |                           |
      |                          |                           |
      |                          |<------------------------->|
      |                          |        HSTOP of           |
      |                          |   DISPLAY WINDOW occurs   |
      |                          |      is this region       |
      |                          |                           |
      |                          |                           |
      |                          |                           |
      |                          |                           |
      |                          |                           |
      |                          |                           |
      |                          |                           |
      |__________________________|___________________________|

      Figure 3-21: Display Window Horizontal Stopping Position

Select a value that represents the correct position in low resolution,
non-interlaced mode.

       ______________________________________________________
      |                                                      |  0
      |                                                      |
      |                                                      |
      |------------------------------------------------------+- 128
      |                             /|\                      |
      |                              |                       |
      |                              | VSTOP of              |
      |                              | DISPLAY WINDOW        |
      |                              | occurs in             |
      |                              | this region           |
 262 -+------------------- (NTSC)    |                       |
      |                              |                       |
      |                              |                       |
      |                             \|/                      |  383 ($17F)
       ------------------------------------------------------

       Figure 3-22: Display Window Vertical Stopping Position

To set the display window stopping position, write HSTOP into bits 0
through 7 and VSTOP into bits 8 through 15 of  DIWSTOP .


3 / Bitplanes and Windows of All Sizes / Maximum Display Window Size

The maximum size of a playfield display is determined by the maximum
number of lines and the maximum number of columns. Vertically, the
restrictions are simple. No data can be displayed in the
 vertical blanking  area. The following table shows the allowable vertical
display area.

                              NTSC                 PAL
                              ----                 ---

     Vertical Blank Start     0                    0
      Vertical Blank Stop     $15 (21)             $1D (29)

                              NTSC     NTSC        PAL      PAL
                              Normal   Interlaced  Normal   Interlaced
                              ------   ----------  ------   ----------
        Displayable lines
          of screen video     241      483         283      567
                                       =525-(21*2)          =625-(29*2)

        Table 3-13: Maximum Allowable Vertical Screen Video

Horizontally, the situation is similar. Strictly speaking, the hardware
sets a rightmost limit to  DDFSTOP  of ($D8) and a leftmost limit to
 DDFSTRT  of ($18). This gives a maximum of 25 words fetched in low
resolution mode. In high resolution mode the maximum here is 49 words,
because the rightmost limit remains ($D8) and only one word is fetched at
this limit. However, horizontal blanking actually limits the displayable
video to 368 low resolution pixels (23 words). These numbers are the same
both for NTSC and for PAL. In addition, it should be noted that using a
data-fetch start earlier than ($38) will disable some  sprites .

        Table 3-14: Maximum Allowable Horizontal Screen Video

                                   Lores            Hires
                                   -----            -----
         DDFSTRT  (standard)       $0038            $003C
         DDFSTOP  (standard)       $00D0            $00D4

         DDFSTRT  (hw limits)      $0018            $0018
         DDFSTOP  (hw limits)      $00D8            $00D8

         max words fetched         25               49
         max display pixels        368 (low res)

The limits on the display window starting and stopping positions described
in this section apply to the Amiga's original custom chip set. In the
Enhanced Chip Set (ECS), the limits for playfield display windows have
been changed.  For more information on  ECS and playfield display windows
refer to Appendix C, Enhanced Chip Set.


3 Playfield Hardware / Moving (Scrolling) Playfields

If you want a background display that moves, you can design a playfield
larger than the display window and scroll it. If you are using dual
playfields, you can scroll them separately.

In vertical scrolling, the playfield appears to move smoothly up or down
on the screen. All you need do for vertical scrolling is progressively
increase or decrease the starting address for the bitplane pointers by the
size of a horizontal line in the playfield. This has the effect of showing
a lower or higher part of the picture each field time.

In horizontal scrolling the playfield appears to move from right-to-left
or left-to-right on the screen. Horizontal scrolling works differently
from vertical scrolling -- you must arrange to fetch one more word of data
for each display line and delay the display of this data.

For either type of scrolling, resetting of pointers or data-fetch
registers can be handled by the Copper during the  vertical blanking
interval.

 Vertical Scrolling
 Horizontal Scrolling
 Scrolling Playfield Summary


3 / Moving (Scrolling) Playfields / Vertical Scrolling

You can scroll a playfield upward or downward in the window. Each time you
display the playfield, the bitplane pointers start at a progressively
higher or lower place in the big picture in memory. As the value of the
pointer increases, more of the lower part of the picture is shown and the
picture appears to scroll upward. As the value of the pointer decreases,
more of the upper part is shown and the picture scrolls downward. On an
NTSC system, with a display that has 200 vertical lines, each step can be
as little as 1/200th of the screen. In interlaced mode each step could be
1/400th of the screen if clever manipulation of the pointers is used, but
it is recommended that scrolling be done two lines at a time to maintain
the odd/even field relationship. Using a PAL system with 256 lines on the
display, the step can be 1/256th of a screen, or 1/512th of a screen in
interlace.

     Figure 3-23: Vertical Scrolling

To set up a playfield for vertical scrolling, you need to form bitplanes
tall enough to allow for the amount of scrolling you want, write software
to calculate the bitplane pointers for the scrolling you want, and allow
for the Copper to use the resultant pointers.

Assume you wish to scroll a playfield upward one line at a time. To
accomplish this, before each field is displayed, the bitplane pointers
have to increase by enough to ensure that the pointers begin one line
lower each time. For a normal-sized, low resolution display in which the
modulo is 0, the pointers would be incremented by 40 bytes each time.


3 / Moving (Scrolling) Playfields / Horizontal Scrolling

You can scroll playfields horizontally from left to right or right to left
on the screen. You control the speed of scrolling by specifying the amount
of delay in pixels. Delay means that an extra word of data is fetched but
not immediately displayed. The extra word is placed just to the left of
the window's leftmost edge and before normal data fetch. As the display
shifts to the right, the bits in this extra word appear on-screen at the
left-hand side of the window as bits on the right-hand side disappear
off-screen. For each pixel of delay, the on-screen data shifts one pixel
to the right each display field. The greater the delay, the greater the
speed of scrolling. You can have up to 15 pixels of delay. In high
resolution mode, scrolling is in increments of 2 pixels. Figure 3-24 shows
how the delay and extra data fetch combine to cause the scrolling effect.

     Figure 3-24: Horizontal Scrolling

   NOTE: Fetching an extra word for scrolling will disable some  sprites .

To set up a playfield for horizontal scrolling, you need to:

   *  Define bitplanes wide enough to allow for the scrolling you need.
   *  Set the data-fetch registers to correctly place each horizontal
      line, including the extra word, on the screen.
   *  Set the delay bits.
   *  Set the modulo so that the bitplane pointers begin at the correct
      word for each line.
   *  Write  Copper instructions  to handle the changes during the
       vertical blanking  interval.

 Specifying Data Fetch in Horizontal Scrolling
 Specifying the Modulo in Horizontal Scrolling
 Specifying Amount of Delay


3 / / Horiz. Scrolling / Specifying Data Fetch in Horizontal Scrolling

The normal data-fetch start for non-scrolled displays is ($38). If
horizontal scrolling is desired, then the data fetch must start one word
sooner ( DDFSTRT  = $0030). Incidentally, this will disable  sprite 7 .
 DDFSTOP  remains unchanged. Remember that the settings of the data-fetch
registers affect both playfields.


3 / / Horiz. Scrolling / Specifying the Modulo in Horizontal Scrolling

As always, the modulo is two counts less than the difference between the
address of the next word you want to fetch and the address of the last
word that was fetched. As an example for horizontal scrolling, let us
assume a 40-byte display in an 80-byte "big picture." Because horizontal
scrolling requires a data fetch of two extra bytes, the data for each line
will be 42 bytes long.

       START                     START+38                    START+78
          __________________________|___________________________
         |                          |                           |
         |                          |                           |
         |<--DISPLAY WINDOW width-->|                           |
         |                          |                           |
         |                          |                           |
         |                          |                           |
         |                          |                           |
         |<----------------MEMORY PICTURE width---------------->|
         |                          |                           |
         |                          |                           |

        Figure 3-25: Memory Picture Larger Than the Display Window

  _______________________________________________________________________
 |                                                                       |
 |   Data for line 1:                                                    |
 |                                                                       |
 | Location:     START        START+2      START+4    ...     START+40   |
 |               -----        -------      -------            --------   |
 |              leftmost     next word    next word         last display |
 |            display word                                      word     |
 |_______________________________________________________________________|

           Figure 3-26: Data for Line 1 - Horizontal Scrolling

At this point, the bitplane pointers contain the value START+42. Adding
the modulo of 38 gives the correct starting point for the next line.

  _______________________________________________________________________
 |                                                                       |
 |   Data for line 2:                                                    |
 |                                                                       |
 | Location:    START+80     START+82     START+84    ...     START+120  |
 |              --------     --------     --------            ---------  |
 |              leftmost     next word    next word         last display |
 |            display word                                      word     |
 |_______________________________________________________________________|

           Figure 3-27: Data for Line 2 -- Horizontal Scrolling

In the  BPLxMOD  registers you set the modulo for each bitplane used.


3 / / Horizontal Scrolling / Specifying Amount of Delay

The amount of delay in horizontal scrolling is controlled by bits 7-0 in
BPLCON1. You set the delay separately for each playfield; bits 3-0 for
playfield 1 (bitplanes 1, 3, and 5) and bits 7-4 for playfield 2
(bitplanes 2, 4, and 6).

   Warning:
   --------
   Always set all six bits, even if you have only one playfield.  Set
   3-0 and 7-4 to the same value if you are using only one playfield.

The following example sets the horizontal scroll delay to 7 for both
playfields.

        MOVE.W  #$77,BPLCON1+CUSTOM


3 / Moving (Scrolling) Playfields / Scrolling Playfield Summary

The steps for defining a scrolled playfield are the same as those for
defining the basic playfield, except for the following steps:

   *   Defining the data fetch .
      -------------------------
      Fetch one extra word per horizontal line and start it 16 pixels
      before the normal (unscrolled) data-fetch start.

   *   Defining the modulo .
      ---------------------
      The modulo is two counts less than when there is no scrolling.

These steps are added:

   *  For  vertical scrolling , reset the bitplane pointers
      -----------------------------------------------------
      for the amount of the scrolling increment.
      -----------------------------------------
      Reset  BPLxPTH and BPLxPTL  during the  vertical blanking  interval.

   *  For  horizontal scrolling , specify the delay.
      ---------------------------------------------
      Set bits 7-0 in  BPLCON1  for 0 to 15 bits of delay.


3 Playfield Hardware / Advanced Topics

This section describes features that are used less often or are optional.

 Interactions Among Playfields and Other Objects
 Hold-And-Modify Mode
 Forming a Display with Several Different Playfields
 Using an External Video Source


3 / Advanced Topics / Interactions Among Playfields and Other Objects

Playfields share the display with sprites. Chapter 7, System Control
Hardware, shows how playfields can be given different
 video display priorities  relative to the sprites and how playfields can
 collide  with (overlap) the sprites or each other.


3 / Advanced Topics / Hold-And-Modify Mode

This is a special mode that allows you to produce up to 4,096 colors on
the screen at the same time. Normally, as each value formed by the
combination of bitplanes is selected, the data contained in the selected
color register is loaded into the color output circuit for the pixel being
written on the screen. Therefore, each pixel is colored by the contents of
the selected color register.

In hold-and-modify mode, however, the value in the color output circuitry
is held, and one of the three components of the color (red, green, or
blue) is modified by bits coming from certain preselected bitplanes. After
modification, the pixel is written to the screen.

The hold-and-modify mode allows very fine gradients of color or shading to
be produced on the screen. For example, you might draw a set of 16 vases,
each a different color, using all 16 colors in the color palette. Then,
for each vase, you use hold-and-modify to very finely shade or highlight
or add a completely different color to each of the vases. Note that a
particular hold-and-modify pixel can only change one of the three color
values at a time. Thus, the effect has a limited control.

In hold and modify mode, you use all six bitplanes. Planes 5 and 6 are
used to modify the way bits from planes 1 - 4 are treated, as follows:

   *  If the 6-5 bit combination from planes 6 and 5 for any given pixel is
      00,  normal color selection procedure is followed. Thus, the bit
      combinations from planes 4 - 1, in that order of significance, are
      used to choose one of 16 color registers (registers 0 - 15).

      If only five bitplanes are used, the data from the sixth plane is
      automatically supplied with the value as 0.

   *  If the 6-5 bit combination is 01, the color of the pixel immediately
      to the left of this pixel is duplicated and then modified. The bit
      combinations from planes 4 - 1 are used to replace the four
      "blue" bits in the corresponding color register.

   *  If the 6-5 bit combination is 10, the color of the pixel immediately
      to the left of this pixel is duplicated and then modified. The bit
      combinations from planes 4 - 1 are used to replace the four "red"
      bits.

   *  If the 6-5 bit combination is 11, the color of the pixel immediately
      to the left of this pixel is duplicated and then modified. The bit
      combinations from planes 4 - 1 are used to replace the four
      "green" bits.

Using hold-and-modify mode, it is possible to get by with defining only
one color register, which is  COLOR00 , the color of the background. You
treat the entire screen as a modification of that original color,
according to the scheme above.

Bit 11 of register  BPLCON0  selects hold-and-modify mode. The following
bits in  BPLCON0  must be set for hold-and-modify mode to be active:

   *  Bit HOMOD, bit 11, is 1.
   *  Bit  DBLPF , bit 10, is 0 (single-playfield mode specified).
   *  Bit  HIRES , bit 15, is 0 (low resolution mode specified).
   *  Bits  BPU2, BPU1, and BPU0  - bits 14, 13, and 12, are 101 or 110
                                    (five or six bitplanes active).

     HAM_playfield.asm


3 / Adv. Topics / Forming a Display with Several Different Playfields

The graphics library provides the ability to split the screen into several
"ViewPorts" each with its own colors and resolutions. See the Amiga ROM
Kernel Manual: Libraries for more information.


3 / Advanced Topics / Using an External Video Source

External and internal genlocks are available for the Amiga as an option. A
genlock allows you to bring in your graphics display from an external
video source (such as a VCR, camera, or laser disk player). When you use
genlock, the background color is replaced by the display from this
external video source. For more information, see the instructions
furnished with your genlock.


3 Playfield Hardware / Summary of Playfield Registers

This section summarizes the registers used in this chapter and the meaning
of their bit settings. The  color registers  are summarized in the next
section. See  Appendix A  for a summary of all registers.

BPLCON0 - Bitplane Control

   (Warning: Bits in this register cannot be independently set.)

   Bit 0 - unused

   Bit 1 - ERSY (external synchronization enable)
      1 = External synchronization enabled (allows genlock
          synchronization to occur)
      0 = External synchronization disabled

   Bit 2 -  LACE  (interlace enable)
      1 = interlaced mode enabled
      0 = non-interlaced mode enabled

   Bit 3 -  LPEN  (light pen enable)

   Bits 4-7 not used (make 0)

   Bit 8 - GAUD (genlock audio enable)
      1 = Genlock audio enabled
      0 = Genlock audio disabled
      (This bit also appears on Denise pin ZD during blanking period)

   Bit 9 -  COLOR_ON  (color enable)
      1 = composite video color-burst enabled
      0 = composite video color-burst disabled

   Bit 10 -  DBLPF  (double-playfield enable)
      1 = dual playfields enabled
      0 = single playfield enabled

   Bit 11 -  HOMOD  (hold-and-modify enable)
      1 = hold-and-modify enabled
      0 = hold-and-modify disabled; extra-half brite ( EHB ) enabled
          if  DBLPF =0 and  BPUx =6

   Bits 14, 13, 12 -  BPU2, BPU1, BPU0
      Number of bitplanes used.

      000 = only a background color
      001 = 1 bitplane, PLANE 1
      010 = 2 bitplanes, PLANES 1 and 2
      011 = 3 bitplanes, PLANES 1 - 3
      100 = 4 bitplanes, PLANES 1 - 4
      101 = 5 bitplanes, PLANES 1 - 5
      110 = 6 bitplanes, PLANES 1 - 6
      111 not used

   Bit 15 -  HIRES  (high resolution enable)
      1 = high resolution mode
      0 = low resolution mode

 BPLCON1  - Bitplane Control

   Bits 3-0 - PF1H(3-0)  Playfield 1 delay

   Bits 7-4 - PF2H(3-0)  Playfield 2 delay

   Bits 15-8 not used

 BPLCON2  - Bitplane Control

   Bit 6 - PF2PRI
      1 = Playfield 2 has priority
      0 = Playfield 1 has priority

   Bits 0-5  Playfield sprite priority

   Bits 7-15  not used

 DDFSTRT  - Data-fetch Start
   (Beginning position for data fetch)

   Bits 15-8 - not used

   Bits 7-2 - pixel position H8-H3 (bit H3 only respected in Hires Mode.)

   Bits 1-0 - not used

 DDFSTOP  - Data-fetch Stop
   (Ending position for data fetch)

   Bits 15-8 - not used

   Bits 7-2 - pixel position H8-H3 (bit H3 only respected in Hires Mode.)

   Bits 1-0 - not used

 BPLxPTH  - Bitplane Pointer
   (Bitplane pointer high word, where x is the bitplane number)

 BPLxPTL  - Bitplane Pointer
   (Bitplane pointer low word, where x is the bitplane number)

 DIWSTRT  - Display Window Start
   (Starting vertical and horizontal coordinates)

   Bits 15-8 - VSTART (V7-V0)

   Bits 7-0 - HSTART (H7-H0)

 DIWSTOP  - Display Window Stop
   (Ending vertical and horizontal coordinates)

   Bits 15-8 - VSTOP (V7-V0)

   Bits 7-0 - HSTOP (H7-H0)

 BPL1MOD  - Bitplane Modulo
   (Odd-numbered bitplanes, playfield 1)

 BPL2MOD  - Bitplane Modulo
   (Even-numbered bitplanes, playfield 2)


3 Playfield Hardware / Summary of Color Selection Registers

This section contains summaries of the playfield color selection registers
including color register contents, example colors, and the differences in
color selection in high resolution and low resolution modes. The Amiga has
32 color registers and each one has 4 bits of red, 4 bits of green, and 4
bits of blue information.  Table 3-15 shows the bit assignments of each
color register.  All color registers are write-only.

              Color Register Bits           Contents
              -------------------           --------
                   15 - 12           Unused (set these to 0)
                   11 -  8                  Red data
                    7 -  4                 Green data
                    3 -  0                  Blue data

                 Table 3-15: Color Register Contents

 Some Sample Color Register Contents
 Color Selection in Low Resolution Mode
 Color Selection in High Resolution Mode
 Color Selection in Hold-And-Modify Mode
 Color Selection in Extra Half Brite (EHB) Mode


3 / Color Selection Registers / Some Sample Color Register Contents

Table 3-16 shows a variety of colors and the hexadecimal values to load
into the color registers for these colors.

               Value   Color           Value   Color
               -----   -----           -----   -----
               $FFF    White           $1FB    Light aqua
               $D00    Brick red       $6FE    Sky blue
               $F00    Red             $6CE    Light blue
               $F80    Red-orange      $00F    Blue
               $F90    Orange          $61F    Bright blue
               $FB0    Golden orange   $06D    Dark blue
               $FD0    Cadmium yellow  $91F    Purple
               $FF0    Lemon yellow    $C1F    Violet
               $BF0    Lime green      $F1F    Magenta
               $8E0    Light green     $FAC    Pink
               $0F0    Green           $DB9    Tan
               $2C0    Dark green      $C80    Brown
               $0B1    Forest green    $A87    Dark brown
               $0BB    Blue green      $CCC    Light grey
               $0DB    Aqua            $999    Medium grey
                                       $000    Black

            Table 3-16: Some Register Values and Resulting Colors


3 / Color Selection Registers / Color Selection in Low Resolution Mode

Table 3-17 shows playfield color selection in low resolution mode. If the
bit combinations from the playfields are as shown, the color is taken from
the color register number indicated.

             Single Playfield                  DualPlayfields
                                                                  Color
       Normal Mode       Hold-and-modify Mode                    Register
  (Bitplanes 5,4,3,2,1)  (Bitplanes 4,3,2,1)                      Number
  -----------------------------------------------------------------------

                                                 Playfield 1
                                              (Bitplanes 5,3,1)

          00000                 0000                 000            0 *
          00001                 0001                 001            1
          00010                 0010                 010            2
          00011                 0011                 011            3
          00100                 0100                 100            4
          00101                 0101                 101            5
          00110                 0100                 110            6
          00111                 0111                 111            7

                                                 Playfield 2
                                              (Bitplanes 6,4,2)

          01000                 1000                 000 **         8
          01001                 1001                 001            9
          01010                 1010                 010           10
          01011                 1011                 011           11
          01100                 1100                 100           12
          01101                 1101                 101           13
          01110                 1110                 110           14
          01111                 1111                 111           15
          10000                  -                    -            16
          10001                  -                    -            17
          10010                  -                    -            18
          10011                  -                    -            19
          10100                 NOT                  NOT           20
          10101                 USED                 USED          21
          10110                 IN                   IN            22
          10111                 THIS                 THIS          23
          11000                 MODE                 MODE          24
          11001                  -                    -            25
          11010                  -                    -            26
          11011                  -                    -            27
          11100                  -                    -            28
          11101                  -                    -            29
          11110                  -                    -            30
          11111                  -                    -            31

  ________________

  * Color register 0 always defines the background color.
  ** Selects ``transparent'' mode instead of selecting color register 8.

               Table 3-17: Low resolution Color Selection


3 / Color Selection / Color Selection in High Resolution Mode

Table 3-18 shows playfield color selection in high resolution mode. If the
bit combinations from the playfields are as shown, the color is taken from
the color register number indicated.

               Single               Dual               Color
              Playfield          Playfields           Register
         (Bitplanes 4,3,2,1)                           Number
         -----------------------------------------------------

                                 Playfield 1
                               (Bitplanes 3,1)

                0000                 00 *                0 **
                0001                 01                  1
                0010                 10                  2
                0011                 11                  3

                0100                  -                  4
                0101              NOT USED               5
                0110            IN THIS MODE             6
                0111                  -                  7

                                 Playfield 2
                               (Bitplanes 4,2)

                1000                 00 *                8
                1001                 01                  9
                1010                 10                 10
                1011                 11                 11

                1100                  -                 12
                1101              NOT USED              13
                1110            IN THIS MODE            14
                1111                  -                 15

         ________________

         * Selects "transparent" mode.

         ** Color register 0 always defines the background color.

                 Table 3-18: High resolution Color Selection


3 / Color Selection / Color Selection in Hold-And-Modify Mode

In hold-and-modify mode, the color register contents are changed as shown
in Table 3-19.  This mode is in effect only if bit 10 of  BPLCON0  = 1.

  Bitplane 6  Bitplane 5                Result
  ----------  ----------                ------
      0           0      Normal operation     (use color register itself)
      0           1      Hold green and red   B = Bitplane 4-1 contents
      1           0      Hold green and blue  R = Bitplane 4-1 contents
      1           1      Hold blue and red    G = Bitplane 4-1 contents

      Table 3-19: Color Selection in Hold-and-modify Mode


3 / Color Selection / Color Selection in Extra Half Brite (EHB) Mode

The Amiga has a special mode called Extra Half Brite or EHB mode which
doubles the maximum number of colors that can be displayed at one time. To
use EHB mode, you must set up six bitplanes.  Then set  BPU =6 (bits 12,
13 and 14) in the  BPLCON0  register. Set  HOMOD =0 (bit 11) and  DBLPF =0
(bit 10) in  BPLCON0 .  In this mode, the information in bitplane 6
controls an intensity reduction in the other 5 bitplanes. The color
register output selected by the first five bitplanes is shifted to
half-intensity by the sixth bitplane. This allows 64 colors to be
displayed at one time instead of the usual 32.

   ECS playfield registers.
   -----------------------
   For  information  concerning the playfield hardware and the Enhanced
   Chip Set, see Appendix C.


Amiga® Hardware Reference Manual: C Enhanced Chip Set

This appendix contains information on the Enhanced Chip Set (ECS).  The
Enhanced Chip Set consists of the Agnus (8372-R3) and Denise (8373-R3)
custom Amiga chips.  These chip revisions support advanced features in
addition to all of the standard features previously available.

The ECS is standard in the A3000.  The enhanced Agnus and Denise chips are
plug-compatible replacements for the originals in the A500 or A2000. There
are no provisions for installing the ECS in the original A1000.  The
A2000, when jumpered for one megabyte of chip memory, will function
normally with the ECS chips installed, under both V1.3 and V2.0 Amiga
System software.

The ECS chips are designed to function with either NTSC or PAL Amigas.
However, the chips from the US factory are configured for NTSC mode.  In
order to use them on a PAL system, you may have to reset the motherboard
jumpers for proper performance.

 New Features of the Enhanced Chip Set
 ECS Hardware and the Graphics Library
 ECS Registers


C Enhanced Chip Set / New Features of the Enhanced Chip Set

The new features of the Enhanced Chip Set are as follows:

 New Memory Limits         New Monitor Scan Rates
 New Blitter Range         New Genlock Capabilities
 New Mode Resolutions      Built-in A2024 support


C / New Features of the Enhanced Chip Set / New Memory Limits

The A3000 has 1 MB of Chip memory, and with proper jumpering of the
motherboard, an additional 1 MB can be added.  On the A2000, the enhanced
Agnus can access up to 1 megabyte of Chip memory with proper jumpering of
the motherboard.  This provides programs with more blitter-accessible
memory for animation and graphics applications.


C / New Features of the Enhanced Chip Set / New Blitter Range

The enhanced Agnus provides rectangular  blits  up to 32k by 32k pixels in
size.


C / New Features of the Enhanced Chip Set / New Mode Resolutions

The enhanced Denise chip provides the new  SuperHires mode  with up to 1280
horizontal pixels per scanline on a standard NTSC or PAL display.

All of the standard display resolutions and depths of the original chip
set are supported with the ECS.


C / New Features of the Enhanced Chip Set / New Monitor Scan Rates

The V2.0 Kickstart and ECS chips support a new high resolution
Productivity mode.  With the addition of a  multi-sync monitor , this mode
allows 640 x 480, non-interlaced screens in up to four colors. All
programs which open and operate in the Workbench screen will automatically
benefit from Productivity text and graphics. In addition, new programs can
open their own Productivity screens in a system standard fashion.


C / New Features of the Enhanced Chip Set / New Genlock Capabilities

The enhanced Denise chip provides the following four  new genlock
features:

   *  Chromakey
   *  BitPlaneKey
   *  BorderBlank
   *  BorderNotTransparent

ChromaKey allows any color register to control the video overlay.
BitPlaneKey allows any bitplane to enable the video overlay. BorderBlank
creates a transparent "frame" surrounding the active area.
BorderNotTransparent makes an opaque "frame" surrounding the active area.


C / New Features of the Enhanced Chip Set / Built-in A2024 Support

Version 2.0 Kickstart ROMS have built-in support for the A2024
scan-converter monitor which displays 1008 x 800 pixels (1008 x 1024 in
PAL mode) in four monochrome levels, non-interlaced.  In conjunction with
1 megabyte of Chip memory, this allows very high resolution Workbench
screens, as well as support for "full page" text and CAD applications.


C Enhanced Chip Set / ECS Hardware and the Graphics Library

The Enhanced Chip Set consists of compatible revisions to the Agnus and
Denise custom chips.  The V36 graphics.library software makes it possible
for these chips to display images in new resolutions, at new monitor scan
rates and with new sprite and genlock abilities.

With the enhanced Agnus, the V36 graphics.library supports the new
programmable scan rate registers to provide multi-sync and bi-sync monitor
capability. The new SuperHires mode provides 35ns pixel rates and sprite
positioning at 70ns rates.  Support for big blits (up to 32k x 32k) is
provided for all graphics functions if the ECS Agnus is present.

With the enhanced Denise, the V36 graphics.library provides display window
start and stop with explicit control over larger ranges than was possible
before.  There are new color register interpretations as part of the
SuperHires mode.  Genlock control has been expanded for more flexibility.
Borders may be explicitly transparent or opaque, color registers other
than zero can control video overlay and a bitplane mask may be used for
special-purpose video masking concurrently with the other genlock features.

   Warning:
   --------
   With these new features come certain  new responsibilities when
   using the graphics.library.

 Determining Chip Revisions
 SuperHires Mode
 SuperHires Mode and the Denise Color Registers
 SuperHires 70ns Sprite Positioning
 Multi-Sync and Bi-Sync Monitors
 New BEAMCON0 Register
 Display Window Specification
 Genlock Extensions
 Big Blits
 Other ECS Modifications
 Interpretational Differences


C / ECS Hardware and the Graphics Library / Determining Chip Revisions

The V36 graphics.library field GfxBase->ChipRevBits0 contains bit
definitions to tell you whether ECS is currently installed and activated.
These bits are derived from the new or changed registers in the ECS chips.

The bit GFXF_HR_AGNUS indicates that enhanced HiRes Agnus is installed.
This is derived from the Agnus VPOSR register.  The VPOSR register is
defined as follows:

   VPOSR - Read vertical most significant bits (and frame flop)

    Bit   15 14 13 12 11 10 09 08  07 06 05 04 03  02 01 00
    Use  LOF I6 I5 I4 I3 I2 I1 I0 LOL -- -- -- -- v10 v9 V8

I0-I6 (bits 8-14) provide the chip identification. At present there are
four possible settings.  A value of 20 or 30 indicates that the enhanced
Hires Agnus is present.

   8361 (regular NTSC) or 8370 (fat NTSC) = 10 for NTSC Agnus
   8367 (regular PAL)  or 8371 (fat PAL)  = 00 for PAL Agnus
   8368 (hr)           or 8372 (fat-hr)   = 20 for PAL, 30 for NTSC

Similarly, the graphics.library flag GFXF_HR_DENISE is derived from the
Denise register DENISEID.  This is a new register which can have one of
two values.  The original Denise (8362) does not have this register, so
whatever value is left over on the bus from the last cycle will be there.
The enhanced HighRes Denise (8373) will return $FC in the lower 8 bits.
The upper 8 bits are reserved.


C / ECS Hardware and the Graphics Library / SuperHires Mode

SuperHires mode provides a 35ns pixel display rate - twice the horizontal
resolution of Hires mode, and four times the Lores rates. The nominal
resolution of a SuperHires viewport is 1280 pixels. The maximum plane
depth for a SuperHires viewport is 2 bitplanes which saturates DMA
bandwidth as much as four Hires bitplanes. This mode is controlled by the
graphics.library by writing to the BPLCON0 register in the LOF copperlist
(/SHF if interlaced).

   BPLCON0  chg  W  A,D  Bitplane control register (misc control bits)

            Bit      Use
            ---      ---
            15       HIRES       Set it to zero if SHRES enabled
            14       BPU2 \
            13       BPU1  }     Depth of SuperHires mode (1 or 2)
            12       BPU0 /
            11       HAM         Incompatible w/ SuperHires mode
            10       DPF         Compatible with SuperHires mode
            09
            08
            07
            06       SHRES       SuperHires 35ns pixel enable bit
            05       BPLHWRM
            04       SPRHWRM
            03       LPEN        Compatible with SuperHires mode
            02       LACE        Compatible with SuperHires mode
            01
            00

   Warning:
   --------
   Programmers must not rely on interpreting ViewPort->Modes bits
   directly when determining the mode of a ViewPort.

   Beginning with the V36 graphics.library, the ViewPort->Modes field is
   used for backward compatibility only.

   Under V1.3 and earlier the ViewPort->Modes field mirrored some of the
   BPLCON0 bits most notably Hires and Lace. However, other logical
   defines in this field such as the Viewport->Modes PF2PRI bit conflict
   with the SHRES bit assignment in the actual hardware.

   For this reason, in release 2.0 of the operating system
   (graphics.library V36 and later), programmers will need to use the
   new DataBase/ModeID scheme to determine their ViewPort's mode, and to
   specify a mode when creating, cloning, or copying ViewPorts.


C / ECS Graphics Library / SuperHires Mode and Denise Color Registers

SuperHires mode has a coarser granularity of color control than either
Hires or Lores modes.  This is because the timing of color conversions at
these very high pixel rates requires special "tricks".  There are only two
bits of red, green and blue color resolution per hires pixel.

In order to decode sprite and bitplane color information in SuperHires
mode, certain multiplexing occurs in the use of the registers. Instead of
4 bits of red, green, and blue for bitplane registers 0-3 stored as 0x0RGB
in four color registers, SuperHires bitplane colors are specially encoded
in the sixteen lower color registers:

                              R    G    B
                             ---- ---- ----
      Bitplane (Color 0) :   ab-- cd-- ef--
      Bitplane (Color 1) :   gh-- ij-- kl--
      Bitplane (Color 2) :   mn-- op-- qr--
      Bitplane (Color 3) :   st-- uv-- wx--

      BIT  15  14  13  12  11  10  09  08  07  06  05  04  03  02  01  00

   C  00   .   .   .   .   a   b   a   b   c   d   c   d   e   f   e   f
   O  01   .   .   .   .   g   h   a   b   i   j   c   d   k   l   e   f
   L  02   .   .   .   .   m   n   a   b   o   p   c   d   q   r   e   f
   O  03   .   .   .   .   s   t   a   b   u   v   c   d   w   x   e   f
   R  04   .   .   .   .   a   b   g   h   c   d   i   j   e   f   k   l
      05   .   .   .   .   g   h   g   h   i   j   i   j   k   l   k   l
   R  06   .   .   .   .   m   n   g   h   o   p   i   j   q   r   k   l
   E  07   .   .   .   .   s   t   g   h   u   v   i   j   w   x   k   l
   G  08   .   .   .   .   a   b   m   n   c   d   o   p   e   f   q   r
   I  09   .   .   .   .   g   h   m   n   i   j   o   p   k   l   q   r
   S  0A   .   .   .   .   m   n   m   n   o   p   o   p   q   r   q   r
   T  0B   .   .   .   .   s   t   m   n   u   v   o   p   w   x   q   r
   E  0C   .   .   .   .   a   b   s   t   c   d   u   v   e   f   w   x
   R  0D   .   .   .   .   g   h   s   t   i   j   u   v   k   l   w   x
      0E   .   .   .   .   m   n   s   t   o   p   u   v   q   r   w   x
      0F   .   .   .   .   s   t   s   t   u   v   u   v   w   x   w   x

SuperHires sprites are encoded in the upper sixteen color registers using
a similar scheme:

                            R    G    B
                           ---- ---- ----
      Sprite (Color 16) :   AB-- CD-- EF--
      Sprite (Color 17) :   GH-- IJ-- KL--
      Sprite (Color 18) :   MN-- OP-- QR--
      Sprite (Color 19) :   ST-- UV-- WX--

      BIT  15  14  13  12  11  10  09  08  07  06  05  04  03  02  01 00

   C  10   .   .   .   .   A   B   A   B   C   D   C   D   E   F   E   F
   O  11   .   .   .   .   G   H   A   B   I   J   C   D   K   L   E   F
   L  12   .   .   .   .   M   N   A   B   O   P   C   D   Q   R   E   F
   O  13   .   .   .   .   S   T   A   B   U   V   C   D   W   X   E   F
   R  14   .   .   .   .   A   B   G   H   C   D   I   J   E   F   K   L
      15   .   .   .   .   G   H   G   H   I   J   I   J   K   L   K   L
   R  16   .   .   .   .   M   N   G   H   O   P   I   J   Q   R   K   L
   E  17   .   .   .   .   S   T   G   H   U   V   I   J   W   X   K   L
   G  18   .   .   .   .   A   B   M   N   C   D   O   P   E   F   Q   R
   I  19   .   .   .   .   G   H   M   N   I   J   O   P   K   L   Q   R
   S  1A   .   .   .   .   M   N   M   N   O   P   O   P   Q   R   Q   R
   T  1B   .   .   .   .   S   T   M   N   U   V   O   P   W   X   Q   R
   E  1C   .   .   .   .   A   B   S   T   C   D   U   V   E   F   W   X
   R  1D   .   .   .   .   G   H   S   T   I   J   U   V   K   L   W   X
      1E   .   .   .   .   M   N   S   T   O   P   U   V   Q   R   W   X
      1F   .   .   .   .   S   T   S   T   U   V   U   V   W   X   W   X

   About SuperHires color.
   -----------------------
   SuperHires color encryption is not reflected in the ColorTable.
   The color encoding is, however, reflected in the ViewPort's
   copper lists generated by graphics via MakeVPort(), SetRGB4(), etc.

Keep in mind that because of the loss of lower bits of precision in
specifying SuperHires colors, pastel colors in a closely graduated color
scheme may be visually difficult to distinguish from each other.


C / ECS Hardware Graphics Library / SuperHires 70ns Sprite Positioning

SuperHires mode has a finer granularity of sprite positioning than either
Hires or Lores modes.  This allows for positioning the sprite every other
SuperHires pixel on 70ns boundaries.  The ECS registers SPRxPOS and
SPRxCTL work together as position, size and sprite feature control
registers.  They are usually loaded by the sprite DMA channel, during
horizontal blank, however they may be loaded by the processor.

The two registers are defined as follows:

   SPRxPOS W   A D     Sprite x vertical-horiz start position data

        Bit      Use
        ----     ----
        15-08
        07-00  SH8-SH1  Start horizontal value. Low bit (SH0) in SPRxCTL.

   SPRxCTL W   A D     Sprite x position and control data

        Bit      Use
        ----     ----
        15-08
        07
        06
        05
        04      SHSH1     Start horizontal (SHR mode) 70ns increment
        03      SHSH0     Start horizontal (SHR mode) 35ns (unimplemented)
        02
        01
        00      SH0       Start horiz. value Low bit 140 ns increment

   Note: bits 3 and  4 are in the ECS chips only.

   Warning:
   --------
   70ns sprite positions are only available in SuperHires mode.
   Attempting to use 70ns sprite positioning with Hires mode under
   the current system may lead to unpredictable results.


C / ECS Hardware and Graphics Library / Multi-Sync and Bi-Sync Monitors

The enhanced Agnus now includes registers for setting a standard
programmable scan rate. The scan rates supported in the  V36
graphics.library include:

   NTSC (525 lines, 227.5 colorclocks per scan line)
   PAL  (625 lines, 227.5 colorclocks per scan line)
   VGA  (525 lines, 114.0 colorclocks per scan line)

The V36 graphics.library controls the variable number of colorclocks on
each horizontal scan line with a combination of registers.  Each
combination of registers provides a different frequency of scan rate and
number of lines per display field:

   HTOTAL    W   A     Highest number count in horizontal line

         Bit  15 14 13 12 11 10 09 08 07 06 05 04 03 02 10 00
         Use   0  0  0  0  0  0  0  0 h8 h7 h6 h5 h4 h3 h2 h1

The value in this register represents the number of 280ns increments on
the horizontal line.

   VTOTAL    W   A     Highest numbered vertical line

VTOTAL contains the line number at which to reset the vertical position
counter.  This value represents the number of lines in a field(+1). The
exception is if the INTERLACE bit is set (BPLCON0). In this case this
value represents the number of lines in the long field (+2) and the number
of lines in the short field (+1).

Programmable synchronization is implemented through five new enhanced
Agnus registers:

   VSSTRT    W   A     Vertical line position for VSYNC  start
   VSSTOP    W   A     Vertical line position for VSYNC  stop
   HSSTRT    W   A     Horizontal line position for HSYNC  start
   HSSTOP    W   A     Horizontal line position for HSYNC  stop
   HCENTER   W   A     Horizontal position for Vsync on interlace

A reasonable composite can be generated by setting HCENTER half a
horizontal line from HSSTRT, and HBSTOP at (HSSTOP-HSSTRT) before HCENTER,
with HBSTRT at (HSSTOP-HSSTRT) before HSSTRT.

Programmable blanking is implemented through four new ECS Agnus registers:

   HBSTRT    W   A     Horizontal line position for HBLANK start
   HBSTOP    W   A     Horizontal line position for HBLANK stop
   VBSTRT    W   A     Vertical   line position for VBLANK start
   VBSTOP    W   A     Vertical   line position for VBLANK stop


C / ECS Hardware and the Graphics Library / New BEAMCON0 Register

A new register in the enhanced Agnus, BEAMCON0, provides a programmable
signal generator.

   BEAMCON0  W   A     Beam counter control register

           Bit     Use
           ---     ---
           15
           14    HARDDIS    Disable hardwired vertical/horizontal blank
           13    LPENDIS    Ignore latched pen value on vertical pos read
           12    VARVBEN    Use VBSTRT/STOP disable hard window stop
           11    LOLDIS     Disable long line/short line toggle
           10    CSCBEN     Composite sync redirection
            9    VARVSYEN   Variable vertical sync enable
            8    VARHSYEN   Variable horizontal sync enable
            7    VARBEAMEN  Variable beam counter comparator enable
            6    DUAL       Special ultra resolution mode enable
            5    PAL        Programmable pal mode enable
            4    VARCSYEN   Variable composite sync
            3    BLANKEN    Composite blank redirection
            2    CSYTRUE    Polarity control for C sync pin
            1    VSYTRUE    Polarity control for V sync pin
            0    HSYTRUE    Polarity control for H sync pin

   Warning:
   --------
   Programmable changes between PAL and NTSC modes are new for V2.0.
   They rely on hardware sync and blank in the Agnus/Denise chip set to
   guarantee necessary signals for a correctly displayed picture.

   Other modes, such as VGA (31 KHz programmable mode) disable the hard
   stops on display sync and blank.  Do not write to this register.

   Incorrectly writing directly to BEAMCON0 has the (remote) possibility
   of destroying your multisync monitor.


C / ECS Hardware and Graphics Library / Display Window Specification

The new graphics.library and the ECS provide a more powerful display
window specification.  The registers DIWSTRT and DIWSTOP control the
display window size and position:

   DIWSTRT   W   A D     Display Window Start (upper left  vert-hor pos)
   DIWSTOP   W   A D     Display Window Stop  (lower right vert-hor pos)

         Bit   15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
         Use   V7 V6 V5 V4 V3 V2 V1 V0 H7 H6 H5 H4 H3 H2 H1 H0

The way these two registers work has changed.  DIWSTRT used to be
vertically restricted to the upper 2/3 of the display (V8=0), and
horizontally restricted to the left 3/4 of the display (H8=0). DIWSTOP
used to be vertically restricted to the lower 1/2 of the display and
horizontally restricted to the right 1/4 of the display (H8=1).

The V36 graphics.library now supports explicit display window start and
stop positions within a larger and more useful range of values, via
control of the the new DIWHIGH register in the ViewPort copper lists:

   DIWHIGH   W   A D     Display Window upper bits for  start,stop

           Bit     Use
           ---     ---
           15       0
           14       0
           13       H8      Horizontal stop, most significant bit.
           12       0
           11       0
           10       V10 \
            9       V9   }  Vertical stop, most significant 3 bits.
            8       V8  /
            7       0
            6       -
            5       H8      Horizontal start, most significant bit.
            4       0
            3       0
            2       V10 \
            1       V9   }  Vertical stop, most significant 3 bits.
            0       V8  /

This is an added register for the ECS chips, and allows larger start and
stop ranges.  If it is not written, the old scheme for DIWSTRT and DIWSTOP
described above holds.  If this register is written last in a sequence of
setting the display window, it sets direct start and stop positions
anywhere on the screen.

   A note on ECS compatibility.
   ----------------------------
   With the enhanced Denise chip present, the graphics.library will set
   up copperlists using the new, explicit display window controls.
   Programs which consistently call MakeVPort(), MrgCop() and Loadview()
   when changing the vertical position of their ViewPort (DxOffset) will
   continue to behave normally.

   Programs which failed to call MakeVPort() when moving the ViewPort
   vertically may not be displayed correctly on a system with ECS.


C / ECS Hardware and the Graphics Library / Genlock Extensions

The V36 graphics.library supports the new genlock capabilities of the
enhanced Denise chip in PAL or NTSC modes.  Any color registers may be
chosen as controlling video overlay (COLORKEY).  A single bitplane may be
chosen to control video overlay as well (BITPLANEKEY). The border areas
surrounding the active display window may also be set to be opaque or
transparent.

   BPLCON0   W   A,D     Bitplane control (miscellaneous control bits)
   BPLCON1   W     D     Bitplane control (horizontal scroll control)
   BPLCON2   W     D     Bitplane control (video priority control)
   BPLCON3   W     D     Bitplane control (enhanced features)

   Bit    BPLCON0   BPLCON1   BPLCON2   BPLCON3
   ----   --------  --------  --------  --------
   15
   14                          ZDBPSEL2 \
   13                          ZDBPSEL1  }         Select bitplane
   12                          ZDBPSEL0 /
   11                          ZDBPEN              Use BITPLANEKEY
   10                          ZDCTEN              Use COLORKEY
   09                          KILLEHB             Kill halfbrite
   08
   07
   06
   05                                   BRDRBLNK   Border blank
   04                                   BRDNTRAN   Border opaque
   03
   02
   01
   00     ENBPLCN3                                 Enable new BLPCON3
                                                     register.

The ECS genlock features are enabled on a ViewPort by ViewPort basis.

   Warning:
   --------
   Genlock has been designed to work with NTSC and PAL modes only.
   Genlock and 31 KHz programmable scan rates are not compatible modes.


C / ECS Hardware and the Graphics Library / Big Blits

The V36 graphics.library supports the ECS Agnus Blitter enhancements,
which provide for contiguous blits of up to 32768 x 32768 pixels at a
time.  Under the original chip set 1024 x 1024 was the maximum:

   BLTSIZE   W   A    Old Blitter size and start (window width, height)

        Bit   15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
        Use   h9 h8 h7 h6 h5 h4 h3 h2 h1 h0 w5 w4 w3 w2 w1 w0

            h = Height (10 bit height = 1024 lines  max)
            w = Width  (6 bit width  = 1024 pixels max)

Two new registers have been added which make larger blits possible:

   BLTSIZV   W   A       ECS Blitter V size

         Bit   15 14  12  12  11  10  09 08 07 06 05 04 03 02 01 00
         Use    0 h14 h13 h12 h11 h10 h9 h8 h7 h6 h5 h4 h3 h2 h1 h0

            h = Height (15 bit height = 32768 lines  max)

   BLTSIZH   W   A       ECS Blitter Horizontal size & start

         Bit   15 14  13  12  11  10  09 08 07 06 05 04 03 02 01 00
         Use    0  0   0   0   0  w10 w9 w8 w7 w6 w5 w4 w3 w2 w1 w0

            w = Width  (11 bit width  = 32768 pixels max)

With these two registers, blits up to 32K by 32K are now possible - much
larger than the original chip set could accept. The original commands are
retained for compatibility.  BLTSIZV should be written first, followed by
BLTSIZH, which starts the blitter.

The existence of the enhanced Agnus Blitter is reflected in the state of
the GfxBase->ChipRevBits bit definition GFXB_BIG_BLITS and is initialized
by the graphics.library at powerup. Note that the <hardware/blits.h>
constant MAXBYTESPERROW has been redefined to reflect the larger range of
legal blitter operations.

   About RastPort Sizes.
   ---------------------
   If the ECS Blitter is accessible, the graphics.library supports its
   use for all graphics functions including areafill, gels, line and
   ellipse drawing functions.

   If the ECS Blitter is not installed, programmers should limit the
   absolute size of their RastPorts to values that the old BLTSIZE
   register can address.


C / ECS Hardware and the Graphics Library / Other ECS Modifications

The preceding sections cover most of the ECS registers appearing in the
ECS register map.  This section briefly describes the remaining
modifications to the Enhanced Chip Set registers.

The following registers now have two additional bits for addressing larger
segments of memory, when the Enhanced Chip Set is present:

   DSKPTH    020   W   A      Disk pointer
                                  (high 5 bits, was 3 bits)
   BLTxPTH   050   W   A      Blitter pointer to x
                                  (high 5 bits, was 3 bits)
   COP1LCH   080   W   A      Coprocessor 1st location
                                  (high 5 bits,was 3 bits)
   COP2LCH   084   W   A      Coprocessor 2nd location
                                  (high 5 bits,was 3 bits)
   AUDxLCH   0A0   W   A      Audio channel x location
                                  (high 5 bits was 3 bits)

The Strobe Long Line register (STRLONG) can be disabled if the Disable
Long Line (LOLDIS) bit is set in the BEAMCON0 register.

   STRLONG   03E   S   D      Strobe for identification of long horiz line

See the Multi-Sync and Bi-Sync Monitors section in this appendix for the
bit descriptions in BEAMCON0.

Bit 7 (DOFF) of the BLTCON1 register, when set, disables the output of the
Blitter hardware on channel D.

   BLTCON1   042   W   A      Blitter control register 1

This allows inputs to channels A, B and C and certain address modification
if necessary, without the Blitter outputting over channel D.

The BLTCON0L register writes the low bits of BLTCON0, thereby expediting
the set up of some blits and generally speeding up the software, since the
upper bits are often the same.

   BLTCON0L  05A   W   A      Blitter control 0, lower 8 bits (minterms)


C / ECS Hardware and Graphics Library / Interpretational Differences

The following registers have the same functionality as the standard chip
set, however, their behavior is interpreted differently.

The POT0 and POT1 registers each read a pair of 8-bit pot counters as
before.

   POT0DAT   012   R   P      Pot counter data left pair
                                  (vertical, horiz)
   POT1DAT   014   R   P      Pot counter data right pair
                                  (vertical, horiz)

However, with programmable scan rates, the values read from these
registers will differ. Generally, the faster the scan rate, the smaller
these values become. Adjustments to the scan rate are reflected in these
values. See Appendix A for more detail on standard operation of these
registers.

Another register where the interpretation has been extended for the ECS is
COPCON.

   COPCON    02E   W   A      Coprocessor control

This 1-bit register, the danger bit (CDANG), when set allows the
Coprocessor to write to the Blitter hardware. In the standard chip set, if
this is set, the Copper can access the address range from $DFF03E through
$DFF07E.  Now, in the ECS, if this bit is set, the Copper can access all
of the Amiga chip registers.  If this bit is clear, the Copper can access
the address range from $DFF03E through $DFF07E, the same range as when the
danger bit is set in the standard chip set.

The AUDxPER register is another register value that varies according to
the programmable scan rate.

   AUDxPER   0A6   W   P      Audio channel x period

With programmable scan rates, the maximum value read from this register
will differ. Generally, the faster the scan rate, the smaller the maximum
period becomes. Adjustments to the scan rate are reflected in this maximum
value.

For more information on the AUDxPER register, and any other register in
the Amiga standard chip set, see  Appendix A  and  Appendix B .


C Enhanced Chip Set / ECS Registers

The register map listed below shows the changes and new registers in the
Amiga's Enhanced Chip Set.

---------------------------------------------------------------------------
ADD  REGISTER V2.0 R/W CHIP            FUNCTION
---------------------------------------------------------------------------
004  VPOSR    chg   R  A   Read vertical most sig. bits (and frame flop)
012  POT0DAT  chg   R  P   Pot counter data left pair (vertical, horiz)
014  POT1DAT  chg   R  P   Pot counter data right pair (vertical, horiz)
020  DSKPTH   chg   W  A   Disk pointer (high 5 bits, was 3 bits)
02E  COPCON   chg   W  A   Coprocessor control
03E  STRLONG  chg   S  D   Strobe for identification of long horiz line
042  BLTCON1  chg   W  A   Blitter control register 1
050  BLTxPTH  chg   W  A   Blitter pointer to x (high 5 bits, was 3 bits)
05A  BLTCON0L new   W  A   Blitter control 0, lower 8 bits (minterms)
05C  BLTSIZV  new   W  A   Blitter V size (for 15 bit vertical size)
05E  BLTSIZH  new   W  A   Blitter H size and start (for 11 bit H size)
07C  DENISEID new   R  D   Chip revision level for Denise (video out chip)
080  COP1LCH  chg   W  A   Coprocessor 1st location(high 5 bits,was 3 bits)
084  COP2LCH  chg   W  A   Coprocessor 2nd location(high 5 bits,was 3 bits)
0A0  AUDxLCH  chg   W  A   Audio channel x location(high 5 bits was 3 bits)
0A6  AUDxPER  chg   W  P   Audio channel x period
100  BPLCON0  chg   W  A,D Bitplane control (miscellaneous control bits)
104  BPLCON2  chg   W  D   Bitplane control (video priority control)
106  BPLCON3  new   W  D   Bitplane control (enhanced features)
142  SPRxCTL  chg   W  A   Sprite x position and control data
1C0  HTOTAL   new   W  A   Highest number count, horiz line (VARBEAMEN=1)
1C2  HSSTOP   new   W  A   Horizontal line position for HSYNC stop
1C4  HBSTRT   new   W  A   Horizontal line position for HBLANK start
1C6  HBSTOP   new   W  A   Horizontal line position for HBLANK stop
1C8  VTOTAL   new   W  A   Highest numbered vertical line  (VARBEAMEN=1)
1CA  VSSTOP   new   W  A   Vertical line position for VSYNC stop
1CC  VBSTRT   new   W  A   Vertical line for VBLANK start
1CE  VBSTOP   new   W  A   Vertical line for VBLANK stop
1DC  BEAMCON0 new   W  A   Beam counter control register (SHRES,UHRES,PAL)
1DE  HSSTRT   new   W  A   Horizontal sync start (VARHSY)
1E0  VSSTRT   new   W  A   Vertical sync start   (VARVSY)
1E2  HCENTER  new   W  A   Horizontal position for Vsync on interlace
1E4  DIWHIGH  new   W  A,D Display window -  upper bits for start, stop
---------------------------------------------------------------------------
A=Agnus chip, D=Denise chip, P=Paula chip, W=Write, R=Read, S=Strobe


Amiga® Hardware Reference Manual: 4 Sprite Hardware

This chapter discusses sprites which are special graphic objects that are
easy to define and easy to animate.  The following sprite topics are
covered:

   *  Defining the size, shape, color, and screen position of sprites.

   *  Displaying and moving sprites.

   *  Combining sprites for more complex images, additional width, or
      additional colors.

   *  Reusing a sprite DMA channel multiple times within a display field
      to create more than eight sprites on the screen at one time.

 What are Sprites?                Overlapped Sprites
 Forming a Sprite                 Attached Sprites
 Displaying a Sprite              Manual Mode
 Moving a Sprite                  Sprite Hardware Details
 Creating Additional Sprites      Summary of Sprite Registers
 Reusing Sprite DMA Channels      Summary of Sprite Color Registers


4 Sprite Hardware / What are Sprites?

Sprites are graphic objects that are created and moved independently of
the playfield display and independently of each other. Together with
playfields, sprites form the graphics display of the Amiga.  You can
create more complex  animation  effects by using the blitter, which is
described in the chapter called "Blitter Hardware." Sprites are produced
on-screen by eight special-purpose sprite  DMA channels . Basic sprites
are 16 pixels wide and any number of lines high. You can choose from three
colors for a sprite's pixels, and a pixel may also be transparent, showing
any object behind the sprite. For larger or more complex objects, or for
more color choices, you can  combine sprites .

Sprite DMA channels can be  reused  several times within the same display
field. Thus, you are not limited to having only eight sprites on the
screen at the same time.


4 Sprite Hardware / Forming a Sprite

To form a sprite, you must first define it and then create a formal data
structure in memory. You define a sprite by specifying its characteristics:

   *  On-screen width of up to 16 pixels.
   *  Unlimited height.
   *  Any shape.
   *  A combination of three colors, plus transparent.
   *  Any position on the screen.

 Screen Position       Sprite Color
 Size of Sprites       Designing a Sprite
 Shape of Sprites      Building the Data Structure


4 / Forming a Sprite / Screen Position

A sprite's screen position is defined as a set of X,Y coordinates.
Position (0,0), where X = 0 and Y = 0, is the upper left-hand corner of
the display. You define a sprite's location by specifying the coordinates
of its upper left-hand pixel. Sprite position is always defined as though
the display modes were low resolution and non-interlaced. The X,Y
coordinate system and definition of a sprite's position are graphically
represented in Figure 4-1. Notice that because of display overscan,
position (0,0) (that is, X = 0, Y = 0) is not normally in a viewable
region of the screen.

       (0,0) __
               \
                \
                 +-----------------------------+
                 |###############|#############|
                 |###############|#############|
                 |###+-----------|---------+###|
                 |###|                     |###|  __ visible screen
                 |###|        Y axis       |###| /     boundaries
                 |###|                     |###|/
                 |###|           |         |###/
                 |###|           |         |##/|
                 |###|           |         |#/#|
                 |----- X axis --+---+     |/##|
                 |###|           |/*\|     |###|
                 |###|           |***|     |###|
                 |###|           |\*/|     |###|
                 |###|           +---+     |###|
                 |###|                     |###|
                 |###|                     |###|
                 |###|                     |###|
                 |###|                     |###|
                 |###+---------------------+###|
                 |#############################|
                 |#############################|
                 +-----------------------------+

          Figure 4-1: Defining Sprite On-screen Position

The amount of viewable area is also affected by the size of the
 playfield display window  (defined by the values in  DDFSTRT ,  DDFSTOP ,
 DIWSTRT ,  DIWSTOP , etc.). See the "Playfield Hardware" chapter for more
information about  overscan and display windows .

 Horizontal Position
 Vertical Position
 Clipped Sprites


4 / / Screen Position / Horizontal Position

A sprite's horizontal position (X value) can be at any pixel on the screen
from 0 to 447. To be visible, however, an object must be within the
boundaries of the  playfield display window . In the examples in this
chapter, a window with horizontal positions from pixel 64 to pixel 383 is
used (that is, each line is 320 pixels long).  Larger or smaller windows
can be defined as required, but it is recommended that you read the
"Playfield Hardware chapter" before attempting to do so. A larger area is
actually scanned by the video beam but is not usually visible on the
screen.

If you specify an X value for a sprite that takes it outside the display
window, then part or all of the sprite may not appear on the screen. This
is sometimes desirable; such a sprite is said to be " clipped ."

To make a sprite appear in its correct on-screen horizontal position in
the display window, simply add its left offset to the desired X value. In
the example given above, this would involve adding 64 to the X value. For
example, to make the upper leftmost pixel of a sprite appear at a position
94 pixels from the left edge of the screen, you would perform this
calculation:

 Desired X position + horizontal-offset of display window ~= 94 + 64 = 158

Thus, 158 becomes the X value, which will be written into the
 data structure .

   Counting Pixels.
   ----------------
   The X position represents the location of the very first (leftmost)
   pixel in the full 16-bit wide sprite. This is always the case, even
   if the leftmost pixels are specified as transparent and do not appear
   on the screen.

If the sprite shown in Figure 4-2 were located at an X value of 158, the
actual image would begin on-screen four pixels later at 162.  The first
four pixels in this sprite are transparent and allow the background to
show through.

                |-- 4 --|
                |pixels |
                 _______________________________
                |_|_|_|_|_|_|_|#|_|_|_|_|_|_|_|_|
                |_|_|_|_|_|_|o|#|o|_|_|_|_|_|_|_|
                |_|_|_|_|_|o|o|#|o|o|_|_|_|_|_|_|
                |_|_|_|_|#|#|#|_|#|#|#|_|_|_|_|_|
                |_|_|_|_|_|o|o|#|o|o|_|_|_|_|_|_|
                |_|_|_|_|_|_|o|#|o|_|_|_|_|_|_|_|
                |_|_|_|_|_|_|_|#|_|_|_|_|_|_|_|_|
                |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|

                |                               |
                |--------- 16 pixels -----------|

                 Figure 4-2: Position of Sprites


4 / / Screen Position / Vertical Position

You can select any position from line 0 to line 262 for the topmost edge
of the sprite. In the examples in this chapter, an NTSC window with
vertical positions from line 44 to line 243 is used. This allows the
normal display height of 200 lines in non-interlaced mode. If you specify
a vertical position (Y value) of less than 44 (i.e., above the top of the
display window) the top edge of the sprite may not appear on screen.

To make a sprite appear in its correct on-screen vertical position, add
the Y value to the desired position. Using the above numbers, add 44 to
the desired Y position. For example, to make the upper leftmost pixel
appear 25 lines below the top edge of the screen, perform this calculation:

 Desired Y position + vertical-offset of the display window = 25 + 44 = 69

Thus, 69 is the Y value you will write into the  data structure .


4 / / Screen Position / Clipped Sprites

As noted above, sprites will be partially or totally clipped if they pass
across or beyond the boundaries of the display window. The values of 64
(horizontal) and 44 (vertical) are "normal" for a centered display on a
standard NTSC video monitor. See Chapter 3, "Playfield Hardware," for more
information on  display offsets .  Information on PAL displays will be
found there. If you choose other values to establish your display window,
your sprites will be clipped accordingly.


4 / Forming a Sprite / Size of Sprites

Sprites are 16 pixels wide and can be almost any height you wish -- as
short as one line or taller than the screen. You would probably move a
very tall sprite vertically to display a portion of it at a time.

Sprite size is based on a pixel that is 1/320th of a screen's width,
1/200th of a NTSC screen's height, or 1/256 of a PAL screen's height. This
pixel size corresponds to the low resolution and non-interlaced modes of
the normal full-size playfield. Sprites, however, are independent of
playfield modes of display, so changing the resolution or interlace mode
of the playfield has no effect on the size or resolution of a sprite.


4 / Forming a Sprite / Shape of Sprites

A sprite can have any shape that will fit within the 16-pixel width. You
define a sprite's shape by specifying which pixels actually appear in each
of the sprite's locations. For example, Figures 4-3 and 4-4 show a
spaceship whose shape is marked by Xs. The first figure shows only the
spaceship as you might sketch it out on graph paper. The second figure
shows the spaceship within the 16-pixel width. The 0s around the spaceship
mark the part of the sprite not covered by the spaceship and transparent
when displayed.

                               XX
                             XXXXXX
                           XXXXXXXXXX
                           XXXXXXXXXX
                             XXXXXX
                               XX

                  Figure 4-3: Shape of Spaceship

                        0000XX0000000000
                        00XXXXXX00000000
                        XXXXXXXXXX000000
                        XXXXXXXXXX000000
                        00XXXXXX00000000
                        0000XX0000000000

          Figure 4-4: Sprite with Spaceship Shape Defined

In this example, the widest part of the shape is ten pixels and the shape
is shifted to the left of the sprite. Whenever the shape is narrower than
the sprite, you can control which part of the sprite is used to define the
shape. This particular shape could also start at any of the pixels from
2-7 instead of pixel 1.


4 / Forming a Sprite / Sprite Color

When sprites are used individually (that is, not attached as described in
the  Attached Sprites  section), each pixel can be one of three colors
or transparent.  Color selection in similar to the method used for
playfield colors. Figure 4-5 shows how the color of each pixel in a sprite
is determined.

                                                 high-order word of
                                                  sprite data line
   _______________________________
  |            _|#|_              |    _ _0 0 0 0 0 1 1 1 0 1 1 1 0 0 0 0
  |          _|o|#|o|_            |   |
  |_ _ _ _ _|o|o|#|o|o|_ _ _ _ _ _|       |
  |_|_|_|_|#|#|#|_|#|#|#|_|_|_|_|_|- -|   |
  |    |    |o|o|#|o|o|           |       |
  |    |      |o|#|o|             |   |_ _|_0 0 0 0 0 1 1 1 0 1 1 1 0 0 0 0
  |____|________|#|_______________|       |
       |                                  | |      low-order word of
       |                                  | |      sprite data line
                                          | |
  transparent                             | |
                 Forms a binary code,
                   used as the color  --> 0 0
                 choice from a group
                  of color registers.

                   Figure 4-5: Sprite Color Definition

The 0s and 1s in the two  data words  that define each line of a sprite in
the  data structure  form a binary number. This binary number points to
one of the four  color registers  assigned to that particular sprite
 DMA channel. The eight sprites use system color registers 16 - 31. For
purposes of color selection, the eight sprites are organized into pairs
and each pair uses four of the  color registers  as shown in Figure 4-6.

   About sprite  color registers .
   -------------------------------
   The color value of the first register in each group of four registers
   is ignored by sprites. When the sprite bits select this register, the
   "transparent" value is used.

                 00  Unused
                 01  Unused
                       ·
                       ·
                       ·         _
                 16  Unused   00  |
                 17  Color 1  01  |
                 18  Color 2  10  |-- Sprites 0 and 1
                 19  Color 3  11 _|
                 20  Unused   00  |
                 21  Color 1  01  |
                 22  Color 2  10  |-- Sprites 2 and 3
                 23  Color 3  11 _|
                 24  Unused   00  |
                 25  Color 1  01  |
                 26  Color 2  10  |-- Sprites 4 and 5
                 27  Color 3  11 _|
                 28  Unused   00  |
                 29  Color 1  01  |
                 30  Color 2  10  |-- Sprites 6 and 7
                 31  Color 3  11 _|

               Figure 4-6: Color Register Assignments

If you require certain colors in a sprite, you will want to load the
sprite's  color registers  with those colors. The "Playfield Hardware"
chapter contains instructions on loading  color registers .

The binary number 00 is special in this color scheme. A pixel whose value
is 00 becomes transparent and shows the color of any other sprite or play-
field that has lower video priority. An object with low priority appears
"behind" an object with higher priority. Each sprite has a fixed video
priority with respect to all the other sprites. You can vary the priority
between sprites and playfields. (See Chapter 7, "System Control Hardware,"
for more information about  sprite priority .)


4 / Forming a Sprite / Designing a Sprite

For design purposes, it is convenient to lay out the sprite on paper
first. You can show the desired colors as numbers from 0 to 3. For
example, the spaceship shown above might look like this:

                        0000122332210000
                        0001223333221000
                        0012223333222100
                        0001223333221000
                        0000122332210000

The next step is to convert the numbers 0-3 into binary numbers, which
will be used to build the  color descriptor words  of the sprite
 data structure . The next section shows how to do this.


4 / Forming a Sprite / Building the Data Structure

After defining the sprite, you need to build its data structure, which is
a series of 16-bit words in a contiguous memory area. Some of the words
contain position and control information and some contain color
descriptions. To create a sprite's data structure, you need to:

   *  Write the  horizontal  and  vertical position  of the sprite into
      the first control word.

   *  Write the vertical stopping position into the second control word.

   *  Translate the decimal color numbers 0 - 3  in your sprite grid
      picture into binary color numbers. Use the binary values to build
      color descriptor (data) words and write these words into the data
      structure.

   *  Write the control words that indicate the end of the sprite data
      structure.

   Warning:
   --------
   Sprite data, like all other data accessed by the custom chips, must
   be loaded into Chip RAM. Be sure all of your sprite data structures
   are word aligned in Chip Memory.

Table 4-1 shows a sprite data structure with the memory location and
function of each word:

 Memory
 Location   16-bit Word                 Function
 --------   -----------                 --------
   N     Sprite control word 1       Vertical and horizontal start position
   N+1   Sprite control word 2       Vertical stop position
   N+2   Color descriptor low word   Color bits for line 1
   N+3   Color descriptor high word  Color bits for line 1
   N+4   Color descriptor low word   Color bits for line 2
   N+5   Color descriptor high word  Color bits for line 2
                  -
                  -
                  -
         End-of-data words           Two words indicating
                                     the next usage of this sprite

              Table 4-1: Sprite Data Structure

All memory addresses for sprites are word addresses. You will need enough
contiguous memory to provide room for two words for the control
information, two words for each horizontal line in the sprite, and two
end-of-data words.

Because this data structure must be accessible by the special-purpose
chips, you must ensure that this data is located within chip memory.

Figure 4-7 shows how the data structure relates to the sprite.

          <- - - - 16 bits - - - - ->
          ___________________________  __
      |  |                           |   |    Each group of words
         |      VSTART, HSTART       |   |    defines one vertical
      |  |---------------------------|   |    usage of a sprite.
         |    VSTOP, control bits    |   |--- Each one contains the
      |  |___________________________|   |    starting location and
                                         |    physical appearance
      |   ___________________________  - | -  of this sprite image.
         |                           |   |  |
      |  | low word of data, line 1  |   |
         |---------------------------|   |  |
      |  | high word of data, line 1 |   |
         |___________________________|   |  |
      |                                  |
               ------                    |  |
  increasing   ------  data describing   |       Pairs of words
  addresses    ------  central lines     |  |- - containing color
               ------  if this sprite    |       information for
      |        ------                    |  |    pixel lines.
          ___________________________    |
      |  |                           |   |  |
         | low word of data, line 1  |   |
      |  |---------------------------|   |  |
         | high word of data, line 1 |   |
      |  |___________________________| __|  |
                                       - - -
      |   ___________________________
         |                           |        Last word pair contains
      |  |     0000000000000000      |        all zeros if this sprite
         |---------------------------|- - - - processor is to used
      |  |     0000000000000000      |        only once vertically in
     \|/ |___________________________|        the display frame.

            Part of a screen display
            _______________________
           |                       |
           |                       |
           |                       |
           |                       |
           |                       |
           |          HSTART       |
           |                       |
           |            |          |            Each word pair
           |                       |          ___________________
           |  VSTART _ _|  _       |         |                   |
           |             _/_\_  _ _|_ _      | low word of pair  |
           |            |_____| _ _|_ _ <----|-------------------|
           |   VSTOP _ _  \_/      |         | high word of pair |
           |            |     |    |         |___________________|
           |                       |
           |            |<--->|    |          describes one video
           |_______________________|          line of the sprite

                    Figure 4-7: Data Structure Layout

 Sprite Control Word 1 : SPRxPOS      Sprite Color Descriptor Words
 Sprite Control Word 2 : SPRxCTL      End-of-data Words


4 / / Building the Data Structure / Sprite Control Word 1 : SPRxPOS

This word ( SPR?POS ) contains the vertical (VSTART) and horizontal
(HSTART) starting position for the sprite. This is where the topmost line
of the sprite will be positioned.

          Bits 15-8 contain the low 8 bits of VSTART
          Bits 7-0 contain the high 8 bits of HSTART


4 / / Building the Data Structure / Sprite Control Word 2 : SPRxCTL

This word contains the vertical stopping position of the sprite on the
screen (i.e., the line AFTER the last displayed row of the sprite). It
also contains some data having to do with  sprite attachment , which is
described later on.

                                SPRxCTL
                               ---------
          Bits 15-8       The low eight bits of VSTOP
          Bit 7           (Used in attachment)
          Bits 6-3        Unused (make zero)
          Bit 2           The VSTART high bit
          Bit 1           The VSTOP high bit
          Bit 0           The HSTART low bit

The value (VSTOP - VSTART) defines how many scan lines high the sprite
will be when it is displayed.


4 / / Building the Data Structure / Sprite Color Descriptor Words

It takes two color descriptor (data) words to describe each horizontal
line of a sprite; the high order word and the low order word. To calculate
how many color descriptor words you need, multiply the height of the
sprite in lines by 2. The bits in the high order color descriptor word
contribute the leftmost digit of the binary color selector number for each
pixel; the low order word contributes the rightmost digit.

To form the color descriptor words, you first need to form a picture of
the sprite, showing the color of each pixel as a number from 0 - 3. Each
number represents one of the colors in the sprite's  color registers . For
example, here is the spaceship sprite again:

                        0000122332210000
                        0001223333221000
                        0012223333222100
                        0001223333221000
                        0000122332210000

Next, you translate each of the numbers in this picture into a binary
number. The first line in binary is shown below. The binary numbers are
represented vertically with the low digit in the top line and the high
digit right below it. This is how the two color descriptor words for each
sprite line are written in memory.

          0 0 0 0 1 0 0 1 1 0 0 1 0 0 0 0    <- Low Sprite Word

          0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0    <- High Sprite Word

The first line above becomes the color descriptor low word for line 1 of
the sprite. The second line becomes the color descriptor high word. In
this fashion, you translate each line in the sprite into binary 0s and 1s.
See  Figure 4-7 .

Each of the binary numbers formed by the combination of the two data words
for each line refers to a specific  color register  in that particular
sprite channel's segment of the color table. Sprite channel 0, for
example, takes its colors from registers 17 - 19. The binary numbers
corresponding to the  color registers  for sprite  DMA channel 0 are shown
in Table 4-2.

               Binary Number        Color Register Number
               -------------        ---------------------
                    00                   Transparent
                    01                       17
                    10                       18
                    11                       19

                  Table 4-2: Sprite Color Registers

Recall that binary 00 always means transparent and never refers to a color
except background.


4 / / Building the Data Structure / End-of-data Words

When the vertical position of the  beam counter  is equal to the VSTOP
value in the sprite  control words , the next two words fetched from the
sprite data structure are written into the sprite  control registers
instead of being sent to the  color registers . These two words are
interpreted by the hardware in the same manner as the original words that
were first loaded into the  control registers . If the VSTART value
contained in these words is lower than the current beam position, this
sprite will not be reused in this display field. For consistency, the
value 0 should be used for both words when ending the usage of a sprite.
 Sprite reuse  is discussed later.

The following data structure is for the spaceship sprite. It will be
located at V = 65 and H = 128 on the normally visible part of the
screen.

SPRITE:
        DC.W    $6D60,$7200     ;VSTART, HSTART, VSTOP
        DC.W    $0990,$07E0     ;First pair of descriptor words
        DC.W    $13C8,$0FF0
        DC.W    $23C4,$1FF8
        DC.W    $13C8,$0FF0
        DC.W    $0990,$07E0
        DC.W    $0000,$0000     ;End of sprite data


4 Sprite Hardware / Displaying a Sprite

After building the  data structure , you need to tell the system to
display it. This section describes the display of sprites in
 automatic mode  . In this mode, once the sprite DMA channel begins to
retrieve and display the data, the display continues until the VSTOP
position is reached.  Manual mode  is described later on in this chapter.

The following steps are used in displaying the sprite:

   1. Decide which of the eight sprite DMA channels to use (making certain
      that the chosen channel is available).

   2. Set the sprite pointers to tell the system where to find the sprite
      data.

   3. Turn on sprite direct memory access if it is not already on.

   4. For each subsequent display field, during the  vertical blanking
      interval, rewrite the sprite pointers.

   About sprite DMA.
   -----------------
   If sprite DMA is turned off while a sprite is being displayed (that
   is, after VSTART but before VSTOP), the system will continue to
   display the line of sprite data that was most recently fetched. This
   causes a vertical bar to appear on the screen. It is recommended that
   sprite DMA be turned off only during  vertical blanking  or during some
   portion of the display where you are sure that no sprite is being
   displayed.

     Selecting a DMA Channel and Setting the Pointers
     Resetting the Address Pointers
     Sprite Display Example


4 / Displaying Sprite / Selecting DMA Channel and Setting Pointers

In deciding which DMA channel to use, you should take into consideration
the colors assigned to the sprite and the  sprites video priority .

The sprite DMA channel uses two pointers to read in sprite  data  and
 control words . During the  vertical blanking  interval before the first
display of the sprite, you need to write the sprite's memory address into
these pointers. The pointers for each sprite are called SPRxPTH and
SPRxPTL, where "x" is the number of the sprite DMA channel. SPRxPTH
contains the high three bits of the memory address of the first word in
the sprite and SPRxPTL contains the low sixteen bits. The least
significant bit of SPRxPTL is ignored, as sprite data must be word
aligned. Thus, only fifteen bits of SPRxPTL are used. As usual, you can
write a long word into SPRxPTH.

In the following example the processor initializes the data pointers for
sprite 0. Normally, this is done by the Copper. The sprite is at address
$20000.

     MOVE.L  #$20000,SPR0PTH+CUSTOM  ;Write $20000 to sprite 0 pointer...

These pointers are dynamic; they are incremented by the sprite DMA channel
to point first to the  control words , then to the  data words , and
finally to the  end-of-data words . After reading in the sprite control
information and storing it in other registers, they proceed to read in the
 color descriptor words . The  color descriptor words  are stored in
sprite data registers, which are used by the sprite DMA channel to display
the data on screen. For more information about how the sprite DMA channels
handle the display, see the  Hardware Details  section below.


4 / Displaying a Sprite / Resetting the Address Pointers

For one single display field, the system will automatically read the
 data structure  and produce the sprite on-screen in the colors that are
specified in the sprite's  color registers . If you want the sprite to be
displayed in subsequent display fields, you must rewrite the contents of
the sprite pointers during each  vertical blanking  interval. This is
necessary because during the display field, the pointers are incremented
to point to the data which is being fetched as the screen display
progresses.

The rewrite becomes part of the  vertical blanking  routine, which can be
handled by instructions in the Copper lists.


4 Sprite Hardware / Moving a Sprite

A sprite generated in  automatic mode  can be moved by specifying a
different position in the  data structure . For each display field, the
data is reread and the sprite redrawn. Therefore, if you change the
position data before the sprite is redrawn, it will appear in a new
position and will seem to be moving.

You must take care that you are not moving the sprite (that is, changing
 control word  data) at the same time that the system is using that data
to find out where to display the object. If you do so, the system might
find the start position for one field and the stop position for the
following field as it retrieves data for display. This would cause a
"glitch" and would mess up the screen. Therefore, you should change the
content of the  control words  only during a time when the system is not
trying to read them. Usually, the  vertical blanking  period is a safe
time, so moving the sprites becomes part of the  vertical blanking  tasks
and is handled by the Copper as shown in the example below.

As sprites move about on the screen, they can collide with each other or
with either of the two playfields. You can use the hardware to detect
these collisions and exploit this capability for special effects. In
addition, you can use collision detection to keep a moving object within
specified on-screen boundaries.  Collision Detection  is described in
Chapter 7, "System Control Hardware."

     sprite_move.asm


4 Sprite Hardware / Creating Additional Sprites

To use additional sprites, you must create a  data structure  for each one
and arrange the display as shown in the previous section, naming the
pointers  SPR1PTH and SPR1PTL  for sprite DMA channel 1,
 SPR2PTH and SPR2PTL  for sprite DMA channel 2, and so on.

   About sprite DMA.
   -----------------
   When you enable sprite DMA for one sprite, you enable DMA for all the
   sprites and place them all in  automatic mode . Thus, you do not need
   to repeat this step when using additional sprite DMA channels.

Once the sprite DMA channels are enabled, all eight sprite pointers must
be initialized to either a real sprite or a safe null sprite. An
uninitialized sprite could cause spurious sprite video to appear.

Remember that some sprites can become unusable when additional DMA cycles
are allocated to displaying the screen, for example when an extra
 wide display  or  horizontal scrolling  is enabled (see
 Figure 6-9: DMA Time Slot Allocation ).

Also, recall that each pair of sprites takes its color from different
color registers, as shown in Table 4-3.

                Table 4-3: Color Registers for Sprite Pairs

                    Sprite Numbers    Color Registers
                    --------------    ---------------
                       0 and 1            17 - 19
                       2 and 3            21 - 23
                       4 and 5            25 - 27
                       6 and 7            29 - 31

   Warning:
   --------
   Some sprites become unusable when additional DMA cycles are allocated
   to displaying the screen, e.g. when enabling an extra  wide display  or
    horizontal scrolling. (See  Figure 6-9: DMA Time Slot Allocation .)

 Sprite Priority


4 / Creating Additional Sprites / Sprite Priority

When you have more than one sprite on the screen, you may need to take
into consideration their relative video priority, that is, which sprite
appears in front of or behind another. Each sprite has a fixed video
priority with respect to all the others. The lowest numbered sprite has
the highest priority and appears in front of all other sprites; the
highest numbered sprite has the lowest priority. This is illustrated in
Figure 4-8.

   More about priorities.
   ----------------------
   See Chapter 7, "System Control Hardware," for more information
   on  sprite priorities .
                                           _______
                                          |       |
                                       ___|___  7 |
                                      |       |___|
                                   ___|___  6 |
                                  |       |___|
                               ___|___  5 |
                              |       |___|
                           ___|___  4 |
                          |       |___|
                       ___|___  3 |
                      |       |___|
                   ___|___  2 |
                  |       |___|
               ___|___  1 |
              |       |___|
              |     0 |
              |_______|

                   Figure 4-8: Sprite Priority


4 Sprite Hardware / Reusing Sprite DMA Channels

Each of the eight sprite  DMA channels  can produce more than one
independently controllable image. There may be times when you want more
than eight objects, or you may be left with fewer than eight objects
because you have  attached  some of the sprites to produce more colors or
larger objects or  overlapped  some to produce more complex images. You
can reuse each sprite  DMA channel  several times within the same display
field, as shown in Figure 4-9.

          Part of a screen display
          ________________________
         |                        |
         |              _         |
         |            _|_|_       |
         |            \___/_ _ _ _|_ _     Each image of this sprite may
         |     _ _ _ _ _ _ _ _ _ _|_ _ <-- be placed at any desired spot,
         |   _/_\_                |        horizontally or vertically.
         |  |_____|               |        however, at least one video
         |    \_/_ _ _ _ _ _ _ _ _|_ _     line must seperate the bottom
         |             _ _ _ _ _ _|_ _ <-- of one usage of a sprite from
         |           /\           |        the starting point of the next
         |           \/           |        usage.
         |                        |
         |                        |
         |                        |
         |                        |
         |                        |
         |________________________|

               Figure 4-9: Typical Example of Sprite Reuse

In single-sprite usage, two all-zero words are placed at the end of the
 data structure  to stop the DMA channel from retrieving any more data for
that particular sprite during that display field. To reuse a DMA channel,
you replace this pair of zero words with another complete sprite
 data structure , which describes the reuse of the DMA channel at a
position lower on the screen than the first use. You place the two
all-zero words at the end of the  data structure  that contains the
information for all usages of the DMA channel. For example, Figure 4-10
shows the  data structure  that describes the picture above.

              SPRITE DISPLAY LIST
          ___________________________ - -
      |  |                           |   |
         |___________________________|
      |  |                           |   |
         |___________________________|
      |                                  |
          ___________________________
      |  |                           |   |
         |___________________________|
      |  |                           |   |
         |___________________________|          Data describing the
      |                                  |- - - first vertical usage of
               ------                           this sprite
      |        ------                    |
               ------
      |   ___________________________    |
         |                           |
      |  |___________________________|   |
         |                           |
      |  |___________________________|   |
                                      - -
  Increasing
  RAM memory
  addresses
          ___________________________ - -
      |  |                           |   |      Data describing the
         |___________________________|          second vertical usage of
      |  |                           |   |- - - this sprite. Contents of
         |___________________________|          vertical start word must
      |                                  |      be at least one video
          ___________________________           line below actual end of
      |  |                           |   |      preceding usage.
         |___________________________|
      |  |                           |   |
         |___________________________|
      |                                  |
               ------
      |        ------                    |
               ------
      |   ___________________________    |
         |                           |
      |  |___________________________|   |- - - End-of-data words ending
         |                           |          the usage of this sprite
     \|/ |___________________________|   |
                                      - -

          Figure 4-10: Typical Data Structure for Sprite Re-use

The only restrictions on the reuse of sprites during a single display
field is that the bottom line of one usage of a sprite must be separated
from the top line of the next usage by at least one horizontal scan line.
This restriction is necessary because only two DMA cycles per horizontal
scan line are allotted to each of the eight channels. The sprite channel
needs the time during the blank line to fetch the  control word
describing the next usage of the sprite.

The following example displays the spaceship sprite and then redisplays it
as a different object. Only the sprite data list is affected, so only the
data list is shown here. However, the sprite looks best with the
 color registers  set as shown in the example.

        LEA     CUSTOM,a0
        MOVE.W  #$0F00,COLOR17(a0)      ;Color 17 = red
        MOVE.W  #$0FF0,COLOR18(a0)      ;Color 18 = yellow
        MOVE.W  #$0FFF,COLOR19(a0)      ;Color 19 = white
SPRITE:
        DC.W    $6D60,$7200
        DC.W    $0990,$07E0
        DC.W    $13C8,$0FF0
        DC.W    $23C4,$1FF8
        DC.W    $13C8,$0FF0
        DC.W    $0990,$07E0
        DC.W    $8080,$8D00     ;VSTART, HSTART, VSTOP for new sprite
        DC.W    $1818,$0000
        DC.W    $7E7E,$0000
        DC.W    $7FFE,$0000
        DC.W    $FFFF,$2000
        DC.W    $FFFF,$2000
        DC.W    $FFFF,$3000
        DC.W    $FFFF,$3000
        DC.W    $7FFE,$1800
        DC.W    $7FFE,$0C00
        DC.W    $3FFC,$0000
        DC.W    $0FF0,$0000
        DC.W    $03C0,$0000
        DC.W    $0180,$0000
        DC.W    $0000,$0000     ;End of sprite data


4 Sprite Hardware / Overlapped Sprites

For more complex or larger moving objects, you can overlap sprites.
Overlapping simply means that the sprites have the same or relatively
close screen positions. A relatively close screen position can result in
an object that is wider than 16 pixels.

The built-in  sprite video priority  ensures that one sprite appears to be
behind the other when sprites are overlapped. The priority circuitry gives
the lowest-numbered sprite the highest priority and the highest numbered
sprite the lowest priority. Therefore, when designing displays with
overlapped sprites, make sure the "foreground" sprite has a lower number
than the "background" sprite. In Figure 4-11, for example, the cage should
be generated by a lower-numbered sprite  DMA channel  than the monkey.

     Figure 4-11: Overlapping Sprites (Not Attached)

You can create a wider sprite display by placing two sprites next to each
other. For instance, Figure 4-12 shows the spaceship sprite and how it can
be made twice as large by using two sprites placed next to each other.

    (128,65)               (128,65)       (144,65)
       |_ _ _ __ _ _ _        |_ _ _ _ _ _ __|__ _ _ _ _ _ _
       |     /  \     |       |           /  |  \           |
          __/____\__                     /       \
       | |          | |       |         /    |    \         |
         |          |              ____/___________\____
       | |__________| |       |   |          |          |   |
            \    /                |                     |
       |_ _ _\__/_ _ _|       |   |          |          |   |
                                  |                     |
                              |   |__________|__________|   |
                                       \           /
                              |         \    |    /         |
                                         \       /
                              |_ _ _ _ _ _\__|__/_ _ _ _ _ _|

                                  Sprite 0       Sprite 1

         Figure 4-12: Placing Sprites Next to Each Other


4 Sprite Hardware / Attached Sprites

You can create sprites that have fifteen possible color choices (plus
transparent) instead of three (plus transparent), by "attaching" two
sprites. To create attached sprites, you must:

   *  Use two channels per sprite, creating two sprites of the same
      size and located at the same position.

   *  Set a bit called  ATTACH  in the  second sprite control word .

The fifteen colors are selected from the full range of  color registers
available to sprites -- registers 17 through 31. The extra color choices
are possible because each pixel contains four bits instead of only two as
in the normal, unattached sprite. Each sprite in the attached pair
contributes two bits to the binary color selector number. For example, if
you are using sprite  DMA channels  0 and 1, the high and low order
 color descriptor words  for line 1 in both  data structures  are combined
into line 1 of the attached object.

Sprites can be attached in the following combinations:

                       Sprite 1 to sprite 0
                       Sprite 3 to sprite 2
                       Sprite 5 to sprite 4
                       Sprite 7 to sprite 6

Any or all of these attachments can be active during the same display
field. As an example, assume that you wish to have more colors in the
spaceship sprite and you are using sprite  DMA channels  0 and 1. There
are five colors plus transparent in this sprite.

                         0000154444510000
                         0001564444651000
                         0015676446765100
                         0001564444651000
                         0000154444510000

The first line in this sprite requires the four  data words  shown in
Table 4-4 to form the correct binary color selector numbers.

        Table 4-4:  Data Words  for First Line of Spaceship Sprite

                           Pixel Number
                           ------------

           15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
   ----------------------------------------------------------------------
   Line 1   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   Line 2   0   0   0   0   0   1   1   1   1   1   1   0   0   0   0   0
   Line 3   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
   Line 4   0   0   0   0   1   1   0   0   0   0   1   1   0   0   0   0

The highest numbered sprite (number 1, in this example) contributes the
highest order bits (leftmost) in the binary number. The high order
 data word  in each sprite contributes the leftmost digit. Therefore, the
lines above are written to the sprite  data structures  as follows:

        Line 1    Sprite 1 high order word for sprite line 1
        Line 2    Sprite 1 low order word for sprite line 1
        Line 3    Sprite 0 high order word for sprite line 1
        Line 4    Sprite 0 low order word for sprite line 1

See  Figure 4-7  for the order these words are stored in memory. Remember
that this data is contained in two sprite structures.

The binary numbers 0 through 15 select registers 17 through 31 as shown in
Table 4-5.

          Table 4-5: Color Registers in Attached Sprites

            Decimal        Binary     Color Register
            Number         Number         Number
            -------        ------     --------------
               0            0000            16 *
               1            0001            17
               2            0010            18
               3            0011            19
               4            0100            20
               5            0101            21
               6            0110            22
               7            0111            23
               8            1000            24
               9            1001            25
              10            1010            26
              11            1011            27
              12            1100            28
              13            1101            29
              14            1110            30
              15            1111            31

              * Unused; yields transparent pixel.

Attachment is in effect only when the  ATTACH  bit, bit 7 in sprite
 control word 2 , is set to 1 in the  data structure  for the odd-numbered
sprite. So, in this example, you set bit 7 in sprite  control word 2  in
the  data structure  for sprite 1.

When the sprites are moved, the Copper list must keep them both at exactly
the same position relative to each other. If they are not kept together on
the screen, their pixels will change color. Each sprite will revert to
three colors plus transparent, but the colors may be different than if
they were ordinary, unattached sprites. The color selection for the lower
numbered sprite will be from color registers 17-19. The color selection
for the higher numbered sprite will be from color registers 20, 24, and 28.

The following  data structure  is for the six-color spaceship made with two
attached sprites.

SPRITE0:
        DC.W    $6D60,$7200     ;VSTART = 65, HSTART = 128
        DC.W    $0C30,$0000     ;First  color descriptor word
        DC.W    $1818,$0420
        DC.W    $342C,$0E70
        DC.W    $1818,$0420
        DC.W    $0C30,$0000
        DC.W    $0000,$0000     ;End of sprite 0
SPRITE1:
        DC.W    $6D60,$7280     ;Same as sprite 0 except  attach  bit on
        DC.W    $07E0,$0000     ;First descriptor word for sprite 1
        DC.W    $0FF0,$0000
        DC.W    $1FF8,$0000
        DC.W    $0FF0,$0000
        DC.W    $07E0,$0000
        DC.W    $0000,$0000     ;End of sprite 1


4 Sprite Hardware / Manual Mode

It is almost always best to load sprites using the  automatic  DMA
channels. Sometimes, however, it is useful to load these registers
directly from one of the microprocessors. Sprites may be activated
"manually" whenever they are not being used by a DMA channel. The same
sprite that is showing a DMA-controlled icon near the top of the screen
can also be reloaded manually to show a vertical colored bar near the
bottom of the screen. Sprites can be activated manually even when the
sprite DMA is turned off.

You display sprites manually by writing to the sprite data registers
 SPRxDATB and SPRxDATA , in that order. You write to  SPRxDATA  last because
that address "arms" the sprite to be output at the next horizontal
comparison. The data written will then be displayed on every line, at the
horizontal position given in the "H" portion of the position registers
 SPRxPOS  and  SPRxCTL . If the data is unchanged, the result will be a
vertical bar. If the data is reloaded for every line, a complex sprite can
be produced.

The sprite can be terminated ("disarmed") by writing to the  SPRxCTL
register. If you write to the  SPRxPOS  register, you can manually move the
sprite horizontally at any time, even during normal sprite usage.


4 Sprite Hardware / Sprite Hardware Details

Sprites are produced by the circuitry shown in Figure 4-13. This figure
shows in block form how a pair of  data words  becomes a set of pixels
displayed on the screen.

     Figure 4-13: Sprite Control Circuitry

The circuitry elements for sprite display are explained below.

*  Sprite data registers.
   ----------------------
   The registers  SPRxDATA and SPRxDATB  hold the bit patterns that
   describe one horizontal line of a sprite for each of the eight
   sprites. A line is 16 pixels wide, and each line is defined by two
   words to provide selection of three colors and transparent.

*  Parallel-to-serial converters.
   ------------------------------
   Each of the 16 bits of the sprite data bit pattern is individually
   sent to the color select circuitry at the time that the pixel
   associated with that bit is being displayed on-screen.

   Immediately after the data is transferred from the sprite data
   registers, each parallel-to-serial converter begins shifting the bits
   out of the converter, most significant (leftmost) bit first. The
   shift occurs once during each low resolution pixel time and continues
   until all 16 bits have been transferred to the display circuitry. The
   shifting and data output does not begin again until the next time
   this converter is loaded from the data registers.

   Because the video image is produced by an electron beam that is being
   swept from left to right on the screen, the bit image of the data
   corresponds exactly to the image that actually appears on the screen
   (most significant data on the left).

*  Sprite serial video data.
   -------------------------
   Sprite data goes to the  priority circuit to establish the priority
   between sprites and playfields.

*  Sprite position registers.
   --------------------------
   These registers, called  SPRxPOS , contain the horizontal position
   value (X value) and vertical position value (Y value) for each of the
   eight sprites.

*  Sprite control registers.
   -------------------------
   These registers, called  SPRxCTL , contain the stopping position for
   each of the eight sprites and whether or not a sprite is  attached.

*  Beam counter.
   -------------
   The  beam counter  tells the system the current location of the video
   beam that is producing the picture.

*  Comparator.
   -----------
   This device compares the value of the beam counter to the Y value in
   the position register  SPRxPOS . If the beam has reached the position
   at which the leftmost upper pixel of the sprite is to appear, the
   comparator issues a load signal to the serial-to-parallel converter
   and the sprite display begins.

Figure 4-13 shows the following:

*  Writing to the sprite control registers disables the horizontal
   comparator circuitry. This prevents the system from sending any
   output from the data registers to the serial converter or to the
   screen.

*  Writing to the sprite A data register enables the horizontal
   comparator. This enables output to the screen when the horizontal
   position of the video beam equals the horizontal value in the
   position register.

*  If the comparator is enabled, the sprite data will be sent to the
   display, with the leftmost pixel of the sprite data placed at the
   position defined in the horizontal part of  SPRxPOS .

*  As long as the comparator remains enabled, the current contents of
   the sprite data register will be output at the selected horizontal
   position on a video line.

*  The data in the sprite data registers does not change. It is either
   rewritten by the user or modified under DMA control.

The components described above produce the automatic DMA display as
follows: When the sprites are in DMA mode, the 18-bit sprite pointer
register (composed of  SPRxPTH and SPRxPTL ) is used to read the first two
words from the sprite  data structure . These words contain the starting
and stopping position of the sprite. Next, the pointers write these words
into  SPRxPOS  and  SPRxCTL . After this write, the value in the pointers
points to the address of the first  data word  (low word of data for line
1 of the sprite.)

Writing into the  SPRxCTL  register disabled the sprite. Now the sprite
DMA channel will wait until the vertical beam counter value is the same as
the data in the VSTART (Y value) part of  SPRxPOS . When these values
match, the system enables the sprite data access.

The sprite DMA channel examines the contents of VSTOP (from  SPRxCTL ,
which is the location of the line after the last line of the sprite) and
VSTART (from  SPRxPOS ) to see how many lines of sprite data are to be
fetched. Two words are fetched per line of sprite height, and these words
are written into the sprite data registers. The first word is stored in
 SPRxDATA  and the second word in  SPRxDATB .

The fetch and store for each horizontal scan line occurs during a
horizontal blanking interval, far to the left of the start of the screen
display. This arms the sprite horizontal comparators and allows them to
start the output of the sprite data to the screen when the horizontal beam
count value matches the value stored in the HSTART (X value) part of
 SPRxPOS .

If the count of VSTOP - VSTART equals zero, no sprite output occurs. The
next data word pair will be fetched, but it will not be stored into the
sprite data registers. It will instead become the next pair of data words
for  SPRxPOS  and  SPRxCTL .

When a sprite is used only once within a single display field, the final
pair of data words, which follow the sprite  color descriptor words , is
loaded automatically as the next contents of the  SPRxPOS  and  SPRxCTL
registers. To stop the sprite after that first data set, the pair of words
should contain all zeros.

Thus, if you have formed a sprite pattern in memory, this same pattern
will be produced as pixels automatically under DMA control one line at a
time.


4 Sprite Hardware / Summary of Sprite Registers

There are eight complete sets of registers used to describe the sprites.
Each set consists of five registers. Only the registers for sprite 0 are
described here. All of the others are the same, except for the name of the
register, which includes the appropriate number.

 Pointers
 Control Registers
 Data Registers


4 / Summary of Sprite Registers / Pointers

Pointers are registers that are used by the system to point to the current
data being used. During a screen display, the registers are incremented to
point to the data being used as the screen display progresses. Therefore,
pointer registers must be freshly written during the start of the
 vertical blanking  period.

 SPR0PTH and SPR0PTL


4 / / Pointers / SPR0PTH and SPR0PTL

This pair of registers contains the 32-bit word address of Sprite 0 DMA
data.

Pointer register names for the other sprites are:

                    SPR1PTH    SPR1PTL
                    SPR2PTH    SPR2PTL
                    SPR3PTH    SPR3PTL
                    SPR4PTH    SPR4PTL
                    SPR5PTH    SPR5PTL
                    SPR6PTH    SPR6PTL
                    SPR7PTH    SPR7PTL


4 / Summary of Sprite Registers / Control Registers

 SPR0POS
 SPR0CTL


4 / / Control Registers / SPR0POS

This is the sprite 0 position register. The  word  written into this
register controls the position on the screen at which the upper left-hand
corner of the sprite is to be placed. The most significant bit of the
first  data word  will be placed in this position on the screen.

   Sprite placement resolution.
   ----------------------------
   The sprites have a placement resolution on a full screen of 320 by
   200 NTSC (320 by 256 PAL). The sprite resolution is independent of
   the bitplane resolution.

Bit positions:

   *  Bits 15-8 specify the vertical start position, bits V7 - V0.
   *  Bits 7-0 specify the horizontal start position, bits H8 - H1.

   Warning:
   --------
   This register is normally only written by the sprite  DMA channel
   itself. See the details above regarding the organization of the
   sprite data.  This register is usually updated directly by DMA.


4 / / Control Registers / SPR0CTL

This register is normally used only by the sprite  DMA channel . It
contains control information that is used to control the sprite data-fetch
process. Bit positions:

   *  Bits 15-8 specify vertical stop position for a sprite image,
      bits V7 - V0.

   *  Bit 7 is the attach bit. This bit is valid only for odd-numbered
      sprites. It indicates that sprites 0, 1 (or 2,3 or 4,5 or 6,7)
      will, for color interpretation, be considered as paired, and as
      such will be called four bits deep. The odd-numbered (higher
      number) sprite contains bits with the higher binary significance.

      During attach mode, the  attached sprites  are normally moved
      horizontally and vertically together under processor control.
      This allows a greater selection of colors within the boundaries
      of the sprite itself. The sprites, although attached, remain
      capable of independent motion, however, and they will assume
      this larger color set only when their edges overlay one another.

   *  Bits 6-3 are reserved for future use (make zero).
   *  Bit 2 is bit V8 of vertical start.
   *  Bit 1 is bit V8 of vertical stop.
   *  Bit 0 is bit H0 of horizontal start.

Position and control registers for the other sprites work the same way as
described above for sprite 0.  The register names for the other sprites
are:

                    SPR1POS    SPR1CTL
                    SPR2POS    SPR2CTL
                    SPR3POS    SPR3CTL
                    SPR4POS    SPR4CTL
                    SPR5POS    SPR5CTL
                    SPR6POS    SPR6CTL
                    SPR7POS    SPR7CTL


4 / Summary of Sprite Registers / Data Registers

The following registers ( SPR0DATA and SPR0DATB ), although defined in the
address space of the main processor, are normally used only by the display
processor. They are the holding registers for the data obtained by DMA
cycles.

          SPR0DATA, SPR0DATB      data registers for Sprite 0
          SPR1DATA, SPR1DATB      data registers for Sprite 1
          SPR2DATA, SPR2DATB      data registers for Sprite 2
          SPR3DATA, SPR3DATB      data registers for Sprite 3
          SPR4DATA, SPR4DATB      data registers for Sprite 4
          SPR5DATA, SPR5DATB      data registers for Sprite 5
          SPR6DATA, SPR6DATB      data registers for Sprite 6
          SPR7DATA, SPR7DATB      data registers for Sprite 7


4 Sprite Hardware / Summary of Sprite Color Registers

Sprite  data words  are used to select the color of the sprite pixels from
the system color register set as indicated in the following tables.

If the bit combinations from single sprites are as shown in Table 4-6,
then the colors will be taken from the registers shown.

          Table 4-6: Color Registers for Single Sprites

                     Single Sprites
                     --------------

               Sprite     Value    Color Register
               ------     -----    --------------
               0 or 1      00        Not used *
                           01            17
                           10            18
                           11            19

               2 or 3      00        Not used *
                           01            21
                           10            22
                           11            23

               4 or 5      00        Not used *
                           01            25
                           10            26
                           11            27

               6 or 7      00        Not used *
                           01            29
                           10            30
                           11            31

               * Selects transparent mode.

If the bit combinations from  attached sprites  are as shown in Table 4-7,
then the colors will be taken from the registers shown.

           Table 4-7: Color Registers for  Attached Sprites

                      Attached Sprites
                     ------------------

               Value               Color Register
               -----               --------------
               0000           Selects transparent mode
               0001                      17
               0010                      18
               0011                      19
               0100                      20
               0101                      21
               0110                      22
               0111                      23
               1000                      24
               1001                      25
               1010                      26
               1011                      27
               1100                      28
               1101                      29
               1110                      30
               1111                      31

 Interactions Among Sprites and Other Objects


4 / Color Registers / Interactions Among Sprites and Other Objects

Playfields share the display with sprites. Chapter 7, "System Control
Hardware," shows how playfields can be given different video
 display priorities  relative to the sprites and how playfields can
 collide  with (overlap) the sprites or each other.

   ECS Sprites.
   -----------
   For information relating to sprites in the Enhanced Chip Set (ECS),
   such as  SuperHires sprites  and  SuperHires sprite positioning ,
   see Appendix C.


Amiga® Hardware Reference Manual: D System Memory Maps

A true software memory map, showing system utilization of the various
sections of RAM and free space is not provided, nor possible with the
Amiga.

All memory is dynamically allocated by the memory manager at boot time,
and the actual locations of system structures may change from
release-to-release, machine-to-machine, or boot-to-boot (see the
AllocMem() function  in the exec.library for more details).

Likewise, Amiga applications are compiled in such a way that they can be
dynamically relocated at run time by the system loader.

To find the location of system structures, application software should use
the function interface provided in the operating system.  If this is not
possible then the address of a data structure should be obtained by
searching the lists of system structures maintained by Exec.  The first
step is to fetch the address of the exec.library from location 4; this is
the only absolute memory location in the system.  All other system data
structures are indirectly linked to this base address.

Though a detailed system memory map is not possible, this section does
present the general layout of memory areas within the current generation
of Amiga computers. To ensure maximum compatibility, avoid relying on the
address ranges given here.  Instead use the system provided interfaces to
ask for the system reources you need.

 A1000, A500 and A2000 Memory Map
 A3000 Memory Map


D System Memory Maps / A1000, A500 and A2000 Memory Map

Address Range           Description
-----------------       ------------------------------------------------
00 0000 - 03 FFFF       256K Chip RAM (A1000 Chip RAM,
                            1st 256K for A500/A2000)

04 0000 - 07 FFFF       256K bytes of Chip RAM (2nd 256K for A500/A2000)

08 0000 - 0F FFFF       512K  Extended chip RAM  (to 1 MB for A2000).

10 0000 - 1F FFFF       Reserved. Do not use.

20 0000 - 9F FFFF       Primary  8 MB Auto-config space .

A0 0000 - BE FFFF       Reserved. Do not use.

BF D000 - BF DF00        8520-B  (access at even-byte addresses only)
    -         -
BF E001 - BF EF01        8520-A  (access at odd-byte addresses only)
    -         -
                        The underlined digit chooses which of the
                         16 internal registers  of the 8520 is to be
                        accessed.  See Appendix F.

C0 0000 - DF EFFF       Reserved.  Do not use.
   |
   | C0 0000 - D7 FFFF  Internal expansion (slow) memory (on some systems).
   |
   | D8 0000 - DB FFFF  Reserved.  Do not use.
   |
   | DC 0000 - DC FFFF  Real time clock (not accessable on all systems).
   |
   | DF F000 - DF FFFF  Chip registers.  See  Appendix A  and  Appendix B .
   +--

E0 0000 - E7 FFFF       Reserved.  Do not use.

E8 0000 - E8 FFFF        Auto-config space .  Boards appear here before
                        the system relocates them to their final address.

E9 0000 - EF FFFF       Secondary  auto-config space  (usually 64K I/O
                        boards).

F0 0000 - FB FFFF       Reserved.  Do not use.

FC 0000 - FF FFFF       256K System ROM.


D System Memory Maps / A3000 Memory Map

Address Range				Description
-----------------------		-------------------------------
$0000 0000 - $001F FFFF		Amiga  Chip Memory

$0020 0000 - $009F 0000		 Zorro II Memory Expansion Space

$00A0 0000 - $00B7 FFFF		 Zorro II I/O Expansion Space

$00B8 0000 - $00BE FFFF		Reserved

$00BF 0000 - $00BF FFFF		 CIA Ports & Timers

$00C0 0000 - $00C7 FFFF		Expansion Memory

$00C8 0000 - $00D7 FFFF		Reserved

$00D8 0000 - $00DB FFFF		Reserved

$00DC 0000 - $00DD FFFF		Memory Mapped Clock

$00DD 0000 - $00DE FFFF		SCSI Control

$00DE 0000 - $00DE FFFF		Motherboard Resources

$00DF 0000 - $00DF FFFF		Amiga  Chip Registers

$00E0 0000 - $00E7 FFFF		Reserved

$00E8 0000 - $0EFF FFFF		 Zorro II I/O & Configuration

$00F0 0000 - $00F7 FFFF		Diagnostic ROM (Reserved)

$00F8 0000 - $00FF FFFF		High ROM (512K)

$0100 0000 - $03FF FFFF		Reserved

$0400 0000 - $07FF FFFF         Motherboard Fast RAM

$0800 0000 - $0FFF FFFF 	Coprocessor Slot Expansion

$1000 0000 - $7FFF FFFF		Zorro III Expansion

$8000 0000 - $FEFF FFFF		Reserved

$FF00 0000 - $FF00 FFFF		 Zorro III Configuration Unit

$FF01 0000 - $FFFF FFFF		Reserved

         32-BIT ADDRESS SPACE                HIGH MEMORY
            (4 GIGABYTES)                    (16 MBYTES)
 $FFFF FFFF  ____________ _ _ _
            |____________|_     $FFFF FFFF  ____________
            |            | \               |            |
            |            |                 |            |
            |            |   \            /            /
            |            |                \            \
            |            |    |            \            \
            |            |                  \            \
            |            |    |             /            /
            |            |                 |            |
            |  Reserved  |    |            |  Reserved  |
            |            |                 |            |
            |            |    | $FF01 0000 |------------|
            |            |                 |  Zorro III |
            |            |    |            |Config. Unit|
            |            |      $FF00 0000 |____________|
            |            |    |_ _ _
            |            |
            |            |
            |            |     _ _ _         LOW MEMORY
            |            |    |             (256 MBYTES)
 $8000 0000 |------------|      $0FFF FFFF  ____________
            |            |    |            |            |
            |            |                 |            |
            |            |    |            | Coprocessor|
            |            |                 |    Slot    |
            |            |    |            |  Expansion |
            |  Zorro III |                 |            |
            |  Expansion |    | $0800 0000 |------------|
            |            |                 | Motherboard|
            |            |   /             |  Fast RAM  |
            |            |      $0700 0000 |------------|
            |            | /               |            |
 $1000 0000 |------------|-                |  Reserved  |
            |            |                 |            |
            |            |      $0100 0000 |------------|- -    - -
            | Low Memory |                 |   24-bit   |   \  /
            |(256 MBytes)|                 |   Address  |    \/ (continued
            |            |                 |   Space    |    /\   below)
 $0000 0000 |____________|_ _ _ $0000 0000 |____________|_ _/  \_
                                                                    |

                   _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|
                  |

                  |
                               _ _ _     HIGH I/O REGISTERS
                  |           |
                                  $DF FFFF  ____________
                 \|/          |            |            |
                                           | Amiga Chips|
       (continued from above) |   $DF 0000 |------------|
                                           | Motherboard|
        24-BIT ADDRESS SPACE  |            |  Resources |
            (16 MBYTES)           $DE 0000 |------------|
 $00FF FFFF  ____________     |            |SCSI Control|
            |            |        $DD 0000 |------------|
            |  High ROM  |    |            |   Memory-  |
 $00F8 0000 |------------|                 |   mapped   |
            | Diagnostic |    |            |   clock    |
            |    ROM     |        $DC 0000 |------------|
 $00F0 0000 |------------|    |            |  Reserved  |
            |Zorro II I/O|        $DD 0000 |------------|
            | and config.|   /             |  Reserved  |
 $00E8 0000 |------------|        $DA 0000 |------------|
            |  Reserved  | /               |  Reserved  |
 $00E0 0000 |------------|-       $D9 0000 |------------|
            |  High I/O  |                 |  Reserved  |
            |  registers |        $D8 0000 |____________|
 $00D8 0000 |------------|- - - -
            |            |
            |  Reserved  |
            |            |
 $00C8 0000 |------------|
            | Ranger RAM |
 $00C0 0000 |------------|- - - -
            |   Low I/O  |        $BF FFFF  ____________
            |  registers |                 |            |
 $00B8 0000 |------------|-                | CIA Ports  |
            |            | \               | and Timers |
            |Zorro II I/O|        $BF 0000 |------------|
            | Expansion  |   \             |  Reserved  |
            |            |        $BE 0000 |------------|
 $00A0 0000 |------------|    |            |  Reserved  |
            |            |        $BD 0000 |------------|
            |  Zorro II  |    |            |  Reserved  |
            |   Memory   |        $BC 0000 |------------|
            | Expansion  |    |            |  Reserved  |
            |            |        $BB 0000 |------------|
 $0020 0000 |------------|    |            |  Reserved  |
            |  Standard  |        $BA 0000 |------------|
            |  Chip RAM  |    |            |  Reserved  |
            |   (Up to   |        $B9 0000 |------------|
            |  2 MBytes) |    |            |  Reserved  |
 $0000 0000 |____________|        $B8 0000 |____________|
                              |_ _ _

                 Figure D-1: Amiga 3000 Memory Map


Amiga® Hardware Reference Manual: 5 Audio Hardware

This chapter shows you how to directly access the audio hardware to
produce sounds. The major topics in this chapter are:

   *  A brief overview of how a computer produces sound.

   *  How to produce simple steady and changing sounds and more
      complex ones.

   *  How to use the audio channels for special effects, wiring them
      for stereo sound if desired, or using one channel to modulate
      another.

   *  How to produce quality sound within the system limitations.

A section at the end of the chapter gives you values to use for creating
musical notes on the equal-tempered musical scale.

This chapter is not a tutorial on computer sound synthesis; a thorough
description of creating sound on a computer would require a far longer
document.  The purpose here is to point the way and show you how to use
the Amiga's features. Computer sound production is fun but complex, and it
usually requires a great deal of trial and error on the part of the
user -- you use the instructions to create some sound and play it back,
readjust the parameters and play it again, and so on.

The following works are recommended for more information on
creating music with computers:

   *  Wayne A. Bateman, Introduction to Computer Music
      (New York: John Wiley and Sons, 1980).

   *  Hal Chamberlain, Musical Applications of Microprocessors
      (Rochelle Park, New Jersey:  Hayden, 1980).

 Introducing Sound Generation      Using Direct (Non-DMA) Audio Output
 Forming and Playing a Sound       The Equal-tempered Musical Scale
 Producing Complex Sounds          Decibel Values for Volume Ranges
 Producing High-quality Sound      The Audio State Machine


5 Audio Hardware / Introducing Sound Generation

Sound travels through air to your ear drums as a repeated cycle of air
pressure variations, or sound waves. Sounds can be represented as graphs
that model how the air pressure varies over time. The attributes of a
sound, as you hear it, are related to the shape of the graph. If the
waveform is regular and repetitive, it will sound like a tone with steady
pitch (highness or lowness), such as a single musical note. Each
repetition of a waveform is called a cycle of the sound. If the waveform
is irregular, the sound will have little or no pitch, like a loud clash or
rushing water. How often the waveform repeats (its frequency) has an
effect upon its pitch; sounds with higher frequencies are higher in pitch.
Humans can hear sounds that have a frequency of between 20 and 20,000
cycles per second. The amplitude of the waveform (highest point on the
graph), is related to the perceived loudness of the sound. Finally, the
general shape of the waveform determines its tone quality, or timbre.
Figure 5-1 shows a particular kind of waveform, called a sine wave, that
represents one cycle of a simple tone.

     Figure 5-1: Sine Waveform

In electronic sound recording and output devices, the attributes of sounds
are represented by the parameters of amplitude and frequency.  Frequency
is the number of cycles per second, and the most common unit of frequency
is the Hertz (Hz), which is 1 cycle per second.  Large values, or high
frequencies, are measured in kilohertz (KHz) or megahertz (MHz).

Frequency is strongly related to the perceived pitch of a sound.  When
frequency increases, pitch rises. This relationship is exponential. An
increase from 100 Hz to 200 Hz results in a large rise in pitch, but an
increase from 1,000 Hz to 1,100 Hz is hardly noticeable. Musical pitch is
represented in octaves. A tone that is one octave higher than another has
a frequency twice as high as that of the first tone, and its perceived
pitch is twice as high.

The second parameter that defines a waveform is its amplitude. In an
electronic circuit, amplitude relates to the voltage or current in the
circuit. When a signal is going to a speaker, the amplitude is expressed
in watts. Perceived sound intensity is measured in decibels (db). Human
hearing has a range of about 120 db; 1 db is the faintest audible sound.
Roughly every 10 db corresponds to a doubling of sound, and 1 db is the
smallest change in amplitude that is noticeable in a moderately loud
sound. Volume, which is the amplitude of the sound signal which is output,
corresponds logarithmically to decibel level.

The frequency and amplitude parameters of a sine wave are completely
independent. When sound is heard, however, there is interaction between
loudness and pitch. Lower-frequency sounds decrease in loudness much
faster than high-frequency sounds.

The third attribute of a sound, timbre, depends on the presence or absence
of overtones, or harmonics. Any complex waveform is actually a mixture of
sine waves of different amplitudes, frequencies, and phases (the starting
point of the waveform on the time axis). These component sine waves are
called harmonics. A square waveform, for example, has an infinite number
of harmonics.

In summary, all steady sounds can be described by their frequency, overall
amplitude, and relative harmonic amplitudes. The audible equivalents of
these parameters are pitch, loudness, and timbre, respectively. Changing
sound is a steady sound whose parameters change over time.

In electronic production of sound, an analog device, such as a tape
recorder, records sound waveforms and their cycle frequencies as a
continuously variable representation of air pressure. The tape recorder
then plays back the sound by sending the waveforms to an amplifier where
they are changed into analog voltage waveforms. The amplifier sends the
voltage waveforms to a loudspeaker, which translates them into air
pressure vibrations that the listener perceives as sound.

A computer cannot store analog waveform information. In computer
production of sound, a waveform has to be represented as a finite string
of numbers. This transformation is made by dividing the time axis of the
graph of a single waveform into equal segments, each of which represents a
short enough time so the waveform does not change a great deal. Each of
the resulting points is called a sample. These samples are stored in
memory, and you can play them back at a frequency that you determine. The
computer feeds the samples to a digital-to-analog converter (DAC), which
changes them into an analog voltage waveform. To produce the sound, the
analog waveforms are sent first to an amplifier, then to a loudspeaker.

Figure 5-2 shows an example of a sine wave, a square wave, and a triangle
wave, along with a table of samples for each.

               Figure 5-2: Digitized Amplitude Values

                 TIME    SINE    SQUARE   TRIANGLE
                 ----    ----    ------   --------
                   0        0      100        0
                   1       39      100       20
                   2       75      100       40
                   3      103      100       60
                   4      121      100       80
                   5      127      100      100
                   6      121      100       80
                   7      103      100       60
                   8       75      100       40
                   9       39      100       20
                  10        0     -100        0
                  11      -39     -100      -20
                  12      -75     -100      -40
                  13     -103     -100      -60
                  14     -121     -100      -80
                  15     -127     -100     -100
                  16     -121     -100      -80
                  17     -103     -100      -60
                  18      -75     -100      -40
                  19      -39     -100      -20
   Note:
   -----
   The illustrations are not to scale and there are fewer dots in the
   wave forms than there are samples in the table. The amplitude axis
   values 127 and -128 represent the high and low limits on relative
   amplitude.

 The Amiga Sound Hardware


5 / Introducing Sound Generation / The Amiga Sound Hardware

The Amiga has four hardware sound channels. You can independently program
each of the channels to produce complex sound effects. You can also attach
channels so that one channel  modulates  the sound of another or combine
two channels for stereo effects.

Each audio channel includes an eight-bit  digital-to-analog converter
driven by a direct memory access (DMA) channel. The audio DMA can retrieve
two data samples during each horizontal video scan line. For simple,
steady tones, the DMA can automatically play a waveform repeatedly; you
can also program all kinds of complex sound effects.

There are two methods of basic sound production on the Amiga -- automatic
(DMA) sound generation and  direct (non-DMA)  sound generation. When you
use automatic sound generation, the system retrieves data automatically by
direct memory access.


5 Audio Hardware / Forming and Playing a Sound

This section shows you how to create a simple, steady sound and play it.
Many basic concepts that apply to all sound generation on the Amiga are
introduced in this section.

To produce a steady tone, follow these basic steps:

   1. Decide which channel to use.
   2. Define the waveform and create the sample table in memory.
   3. Set registers telling the system where to find the data and the
      length of the data.
   4. Select the volume at which the tone is to be played.
   5. Select the sampling period, or output rate of the data.
   6. Select an audio channel and start up the DMA.

 Deciding Which Channel to Use          Playing the Waveform
 Creating the Waveform Data             Stopping the Audio Dma
 Telling the System About the Data      Audio Summary
 Selecting the Volume                   Audio Example
 Selecting the Data Output Rate


5 / Forming and Playing a Sound / Deciding Which Channel to Use

The Amiga has four audio channels. Channels 1 and 2 are connected to the
left-side stereo output jack. Channels 0 and 3 are connected to the
right-side output jack. Select a channel on the side from which the output
is to appear.


5 / Forming and Playing a Sound / Creating the Waveform Data

The waveform used as an example in this section is a simple sine wave,
which produces a pure tone. To conserve memory, you normally define only
one full cycle of a waveform in memory. For a steady, unchanging sound,
the values at the waveform's beginning and ending points and the trend or
slope of the data at the beginning and end should be closely related. This
ensures that a continuous repetition of the waveform sounds like a
continuous stream of sound.

Sound data is organized as a set of eight-bit data items; each item is a
sample from the waveform. Each data word retrieved for the audio channel
consists of two samples. Sample values can range from -128 to +127.

As an example, the data set shown below produces a close approximation to
a sine wave.

   About the sample data.
   ----------------------
   The data is stored in byte address order with the first digitized
    amplitude  value at the lowest byte address, the second at the next
   byte address, and so on. Also, note that the first byte of data must
   start at a word-address boundary.  This is because the audio DMA
   retrieves one word (16 bits) at a time and uses the sample it reads
   as two bytes of data.

To use audio channel 0, write the address of "audiodata" into AUD0LC,
where the audio data is organized as shown below.  For simplicity,
"AUDxLC" in the table below stands for the combination of the two actual
location registers ( AUDxLCH and AUDxLCL ).  For the  audio DMA  channels
to be able to retrieve the data, the data address to which AUD0LC points
must be somewhere in chip RAM.

    Table 5-1: Sample Audio Data Set for Channel 0

     audiodata --->  AUD0LC *        100      98
                     AUD0LC + 2 **    92      83
                     AUD0LC + 4       71      56
                     AUD0LC + 6       38      20
                     AUD0LC + 8        0     -20
                     AUD0LC + 10     -38     -56
                     AUD0LC + 12     -71     -83
                     AUD0LC + 14     -92     -83
                     AUD0LC + 16    -100     -98
                     AUD0LC + 18     -92     -83
                     AUD0LC + 20     -71     -56
                     AUD0LC + 22     -38     -20
                     AUD0LC + 24       0      20
                     AUD0LC + 26      38      56
                     AUD0LC + 28      71      83
                     AUD0LC + 30      92      98
     Notes:
     ------
     * Audio data is located on a word-address boundary.
     ** AUD0LC stands for  AUD0LCL and AUD0LCH .


5 / Forming and Playing a Sound / Telling the System About the Data

In order to retrieve the sound data for the audio channel, the system needs
to know where the data is located and how long (in words) the data is.

The location registers  AUDxLCH and AUDxLCL  contain the high three bits
and the low fifteen bits, respectively, of the starting address of the
audio data. Since these two register addresses are contiguous, writing a
long word into AUDxLCH moves the audio data address into both locations.
The "x" in the register names stands for the number of the audio channel
where the output will occur. The channels are numbered 0, 1, 2, and 3.

These registers are location registers, as distinguished from pointer
registers. You need to specify the contents of these registers only once;
no resetting is necessary when you wish the audio channel to keep on
repeating the same waveform. Each time the system retrieves the last audio
word from the data area, it uses the contents of these location registers
to again find the start of the data. Assuming the first word of data
starts at location "audiodata" and you are using channel 0, here is how to
set the location registers:

WHERE0DATA:
        LEA     CUSTOM,a0       ; Base chip address...
        LEA     AUDIODATA,a1
        MOVE.L  a1,AUD0LCH(a0)  ;Put address (32 bits)
                                ;  into location register.

The length of the data is the number of samples in your waveform divided
by 2, or the number of words in the data set. Using the sample data set
above, the length of the data is 16 words. You write this length into the
audio data length register for this channel. The length register is called
AUDxLEN, where "x" refers to the channel number. You set the length
register AUD0LEN to 16 as shown below.

SETAUD0LENGTH:
        LEA     CUSTOM,a0       ; Base chip address
        MOVE.W  #16,AUD0LEN(a0) ; Store the length...


5 / Forming and Playing a Sound / Selecting the Volume

The volume you set here is the overall volume of all the sound coming from
the audio channel. The relative loudness of sounds, which will concern you
when you combine notes, is determined by the  amplitude  of the wave form.
There is a six-bit volume register for each audio channel. To control the
volume of sound that will be output through the selected audio channel,
you write the desired value into the register AUDxVOL, where "x" is
replaced by the channel number. You can specify values from 64 to 0. These
volume values correspond to decibel levels. At the end of this chapter is
a table showing the  decibel value  for each of the 65 volume levels.

For a typical output at volume 64, with maximum data values of -128 to
127, the voltage output is between +.4 volts and -.4 volts. Some volume
levels and the corresponding decibel values are shown in Table 5-2.

                Table 5-2: Volume Values

          Volume  Decibel Value
          ------  -------------
            64         0         (maximum volume)
            48        -2.5
            32        -6.0
            16        -12.0      (12 db down from the volume
                                  at maximum level)

For any volume setting from 64 to 0, you write the value into bits 5-0 of
AUD0VOL. For example:

SETAUD0VOLUME:
        LEA     CUSTOM,a0
        MOVE.W  #48,AUD0VOL(a0)

The decibels are shown as negative values from a maximum of 0 because this
is the way a recording device, such as a tape recorder, shows the
recording level. Usually, the recorder has a dial showing 0 as the optimum
recording level. Anything less than the optimum value is shown as a minus
quantity.


5 / Forming and Playing a Sound / Selecting the Data Output Rate

The pitch of the sound produced by the waveform depends upon its
frequency. To tell the system what frequency to use, you need to specify
the sampling period. The sampling period specifies the number of system
clock  ticks , or timing intervals, that should elapse between each sample
(byte of audio data) fed to the  digital-to-analog converter  in the audio
channel. There is a  period register  for each audio channel. The value of
the  period register  is used for count-down purposes; each time the
register counts down to 0, another sample is retrieved from the waveform
data set for output. In units, the period value represents clock ticks per
sample. The minimum period value you should use is 124 ticks per sample
NTSC (123 PAL) and the maximum is 65535. These limits apply to both PAL and
NTSC machines. For high-quality sound, there are other constraints on the
sampling period (see the section called  Producing High-quality Sound ).

   The period is inversely proportional to the frequency.
   ------------------------------------------------------
   A low period value corresponds to a higher frequency sound and a
   high period value corresponds to a lower frequency sound.

 Limitations on Selection of Sampling Period
 Specifying the Period Value


5 / / Data Output Rate / Limitations on Selection of Sampling Period

The  sampling period  is limited by the number of DMA cycles allocated to
an audio channel. Each audio channel is allocated one DMA slot per
horizontal scan line of the screen display. An audio channel can retrieve
two data samples during each horizontal scan line. The following
calculation gives the maximum sampling rate in samples per second.

   2 samples/line * 262.5 lines/frame * 59.94 frames/second = 31,469
                                                            samples/second

The figure of 31,469 is a theoretical maximum. In order to save buffers,
the hardware is designed to handle 28,867 samples/second. The system
timing interval is 279.365 nanoseconds, or .279365 microseconds. The
maximum sampling rate of 28,867 samples per second is 34.642 microseconds
per sample (1/28,867 = .000034642). The formula for calculating the
 sampling period  is:

                  sample interval     clock constant
   Period value = --------------- = ------------------
                  clock interval    samples per second

Thus, the minimum period value is derived by dividing 34.642 microseconds
per sample by the number of microseconds per interval:

                      34.642 microseconds/sample
   Minumum period = ------------------------------ = 124 timing
                    0.279365 microseconds/interval   intervals/sample

or:

                    3,579,545 ticks/second
   Minumum period = ----------------------  = 124 ticks/sample
                    28,867 samples/second

Therefore, a value of at least 124 must be written into the
 period register  to assure that the audio system DMA will be able to
retrieve the next data sample. If the period value is below 124, by the
time the cycle count has reached 0, the audio DMA will not have had
enough time to retrieve the next data sample and the previous sample will
be reused.

28,867 samples/second is also the maximum sampling rate for PAL systems.
Thus, for PAL systems, a value of at least 123 ticks/sample must be
written into the  period register .

                       Clock Values
                       ------------

                      NTSC        PAL     units
                      ----        ---     -----
   Clock Constant    3579545    3546895   ticks per second
   Clock Interval   0.279365   0.281937   microseconds per interval

   NOTE:
   -----
   The Clock Interval is derived from the clock constant, where:

                                      1
               clock interval = --------------
                                clock constant

   then scale the result to microseconds. In all of these calculations
   "ticks" and "timing intervals" refer to the same thing.


5 / / Selecting the Data Output Rate / Specifying the Period Value

After you have selected the desired interval between data samples, you can
calculate the value to place in the period register by using the period
formula:

                  desired interval     clock constant
   Period value = ---------------- = ------------------
                   clock interval    samples per second

As an example, say you wanted to produce a 1 KHz sine wave, using a table
of eight data samples (four data words) (see Figure 5-3).

     Figure 5-3: Example Sine Wave

                    Sampled Values:     0
                                       90
                                      127
                                       90
                                        0
                                      -90
                                     -127
                                      -90

To output the series of eight samples at 1 KHz (1,000 cycles per second),
each full cycle is output in 1/1000th of a second. Therefore, each
individual value must be retrieved in 1/8th of that time. This translates
to 1,000 microseconds per waveform or 125 microseconds per sample. To
correctly produce this waveform, the period value should be:

                     125 microseconds/sample
   Period value = ------------------------------ = 447 timing
                  0.279365 microseconds/interval   intervals/sample

To set the period register, you must write the period value into the
register AUDxPER, where "x" is the number of the channel you are using.
For example, the following instruction shows how to write a period value
of 447 into the period register for channel 0.

SETAUD0PERIOD:
        LEA     CUSTOM,a0
        MOVE.W  #447,AUD0PER(a0)

To produce high-quality sound, avoiding  aliasing distortion , you
should observe the limitations on period values that are discussed in
the section called "Producing Quality Sound."

For the relationship between period and musical pitch, see the section
at the end of the chapter, which contains a listing of the
 equal-tempered musical scale .


5 / Forming and Playing a Sound / Playing the Waveform

After you have defined the audio data  location ,  length ,  volume  and
 period , you can play the waveform by starting the DMA for that audio
channel. This starts the output of sound. Once started, the DMA continues
until you specifically stop it. Thus, the waveform is played over and over
again, producing the steady tone. The system uses the value in the
 location registers  each time it replays the waveform.

For any audio DMA to occur (or any other DMA, for that matter), the
DMAEN bit in  DMACON  must be set. When both DMAEN and AUDxEN are set, the
DMA will start for channel x. All these bits and their meanings are shown
in table 5-3.

         Table 5-3: DMA and Audio Channel Enable Bits

              DMACON  Register
             ---------------

          Bit     Name      Function
          ---     ----      --------
         15       SET/CLR   When this bit is written as a 1, it
                            sets any bit in DMACONW for which
                            the corresponding bit position is
                            also a 1, leaving all other bits alone.

          9       DMAEN     Only while this bit is a 1 can
                            any direct memory access occur.

          3       AUD3EN    Audio channel 3 enable.
          2       AUD2EN    Audio channel 2 enable.
          1       AUD1EN    Audio channel 1 enable.
          0       AUD0EN    Audio channel 0 enable.

For example, if you are using channel 0, then you write a 1 into bit 9 to
enable DMA and a 1 into bit 0 to enable the audio channel, as shown below.

BEGINCHAN0:
        LEA     CUSTOM,a0
        MOVE.W  #(DMAF_SETCLR!DMAF_AUD0!DMAF_MASTER),DMACON(a0)


5 / Forming and Playing a Sound / Stopping the Audio Dma

You can stop the channel by writing a 0 into the  AUDxEN  bit at any time.
However, you cannot resume the output at the same point in the waveform by
just writing a 1 in the bit again. Enabling an audio channel almost always
starts the data output again from the top of the list of data pointed to
by the  location registers  for that channel. If the channel is disabled
for a very short time (less than two  sampling periods ) it may stay on
and thus continue from where it left off.

The following example shows how to stop audio DMA for one channel.

STOPAUDCHAN0:
        LEA     CUSTOM,a0
        MOVE.W  #(DMAF_AUD0),DMACON(a0)


5 / Forming and Playing a Sound / Audio Summary

These are the steps necessary to produce a steady tone:

   1. Define the waveform.
   2. Create the data set containing the pairs of data samples (data
      words). Normally, a data set contains the definition of one
      waveform.
   3. Set the location registers:

          AUDxLCH  (high three bits)
          AUDxLCL  (low fifteen bits)

   4. Set the length register,  AUDxLEN , to the number of data words to
      be retrieved before starting at the address currently in  AUDxLC .
   5. Set the volume register,  AUDxVOL .
   6. Set the period register,  AUDxPER
   7. Start the audio DMA by writing a 1 into bit 9,  DMAEN  , along with
      a 1 in the  SET/CLR  bit and a 1 in the position of the  AUDxEN  bit
      of the channel or channels you want to start.


5 Audio Hardware / Producing Complex Sounds

In addition to simple tones, you can create more complex sounds, such as
different musical notes joined into a one-voice melody, different notes
played at the same time, or modulated sounds.

 Joining Tones
 Playing Multiple Tones at the Same Time
 Modulating Sound


5 / Producing Complex Sounds / Joining Tones

Tones are joined by writing the  location  and  length registers ,
starting the audio output, and rewriting the registers in preparation for
the next audio waveform that you wish to connect to the first one. This is
made easy by the timing of the  audio interrupts  and the existence of
back-up registers. The  location  and  length registers  are read by the
DMA channel before audio output begins. The DMA channel then stores the
values in back-up registers.

Once the original registers have been read by the DMA channel, you can
change their values without disturbing the operation you started with the
original register contents. Thus, you can write the contents of these
registers, start an audio output, and then rewrite the registers in
preparation for the next waveform you want to connect to this one.

 Interrupts  occur immediately after the audio DMA channel has read the
 location  and  length registers  and stored their values in the back-up
registers. Once the  interrupt  has occurred, you can rewrite the
registers with the location and length for the next waveform segment. This
combination of back-up registers and  interrupt  timing lets you keep one
step ahead of the audio DMA channel, allowing your sound output to be
continuous and smooth.

If you do not rewrite the registers, the current waveform will be
repeated. Each time the  length counter  reaches zero, both the  location
and  length registers  are reloaded with the same values to continue the
audio output.

 Audio DMA Example


5 / / Joining Tones / Audio DMA Example

This example details the system audio DMA action in a step-by-step
fashion.

Suppose you wanted to join together a sine and a triangle waveform,
end-to-end, for a special audio effect, alternating between them. The
following sequence shows the action of your program as well as its
interaction with the audio DMA system. The example assumes that the
 period ,  volume , and  length  of the data set remains the same for the
sine wave and the triangle wave.

                         Interrupt Program
                         -----------------
If (wave = triangle)
               write  AUD0LCL  with address of sine wave data.

Else if (wave = sine)
               write  AUD0LCL  with address of triangle wave data.

                          Main Program
                          ------------

1. Set up  volume ,  period , and  length .
2. Write  AUD0LCL  with address of sine wave data.
3. Start DMA.
4. Continue with something else.

                         System Response
                         ---------------

As soon as DMA starts,

   a. Copy to "back-up" length register from  AUD0LEN .
   b. Copy to "back-up" location register from  AUD0LCL  (will be used
      as a pointer showing current data word to fetch).
   c. Create an  interrupt  for the 680x0 saying that it has completed
      retrieving working copies of  length  and  location registers .
   d. Start retrieving audio data each allocated DMA time slot.


5 / Producing Complex Sounds / Playing Multiple Tones at the Same Time

You can play multiple tones either by using several channels independently
or by summing the samples in several data sets, playing the summed data
sets through a single channel.

Since all four audio channels are independently programmable, each channel
has its own data set; thus a different tone or musical note can be played
on each channel.


5 / Producing Complex Sounds / Modulating Sound

To provide more complex audio effects, you can use one audio channel to
modulate another. This increases the range and type of effects that can be
produced. You can modulate a channel's frequency or  amplitude , or do
both types of modulation on a channel at the same time.

 Amplitude  modulation affects the  volume  of the waveform. It is often
used to produce vibrato or tremolo effects. Frequency modulation affects
the  period  of the waveform. Although the basic waveform itself remains
the same, the pitch is increased or decreased by frequency modulation.

The system uses one channel to modulate another when you attach two
channels. The attach bits in the ADKCON register control how the data from
an audio channel is interpreted (see the table below). Normally, each
channel produces sound when it is enabled. If the "attach"  bit for an
audio channel is set, that channel ceases to produce sound and its data is
used to modulate the sound of the next higher-numbered channel. When a
channel is used as a modulator, the words in its data set are no longer
treated as two individual bytes. Instead, they are used as "modulator"
words. The data words from the modulator channel are written into the
corresponding registers of the modulated channel each time the
 period register  of the modulator channel times out.

To modulate only the  amplitude  of the audio output, you must attach a
channel as a volume modulator. Define the modulator channel's data set as
a series of words, each containing  volume  information in the following
format:

                    Bits      Function
                    ----      --------
                    15 - 7    Not used
                    6 - 0     Volume information, V6 - V0

To modulate only the frequency, you must attach a channel as a period
modulator. Define the modulator channel's data set as a series of words,
each containing  period  information in the following format:

                    Bits      Function
                    ----      --------
                    15 - 0    Period information, P15 - P0

If you want to modulate both  period  and  volume  on the same channel,
you need to attach the channel as both a period and volume modulator. For
instance, if channel 0 is used to modulate both the  period  and frequency
of channel 1, you set two attach bits -- bit 0 to modulate the  volume
and bit 4 to modulate the  period . When  period  and  volume  are both
modulated, words in the modulator channel's data set are defined
alternately as  volume  and  period  information.

The sample set of data in Table 5-4 shows the differences in
interpretation of data when a channel is used directly for audio, when it
is attached as volume modulator, when it is attached as a period
modulator, and when it is attached as a modulator of both  volume  and
 period .

             Table 5-4: Data Interpretation in Attach Mode

           Independent        Modulating
   Data       (not               Both              Modulating  Modulating
   Words   Modulating)      Period and Volume      Period Only Volume Only
   -----   -----------      -----------------      ----------- -----------
   Word 1  |data|data|  |volume for other channel|  |period|    |volume|
   Word 2  |data|data|  |period for other channel|  |period|    |volume|
   Word 3  |data|data|  |volume for other channel|  |period|    |volume|
   Word 4  |data|data|  |period for other channel|  |period|    |volume|

The lengths of the data sets of the modulator and the modulated channels
are completely independent.

Channels are attached by the system in a predetermined order, as shown in
Table 5-5. To attach a channel as a modulator, you set its attach bit to
1. If you set either the  volume  or  period  attach bits for a channel,
that channel's audio output will be disabled; the channel will be attached
to the next higher channel, as shown in Table 5-5. Because an attached
channel always modulates the next higher numbered channel, you cannot
attach channel 3. Writing a 1 into channel 3's modulate bits only disables
its audio output.

             Table 5-5: Channel Attachment for Modulation

                        ADKCON Register
                        ---------------
        Bit    Name     Function
        ---    ----     --------
         7    ATPER3    Use audio channel 3 to modulate nothing
                          (disables audio output of channel 3)
         6    ATPER2    Use audio channel 2 to modulate period
                          of channel 3
         5    ATPER1    Use audio channel 1 to modulate period
                          of channel 2
         4    ATPER0    Use audio channel 0 to modulate period
                          of channel 1
         3    ATVOL3    Use audio channel 3 to modulate nothing
                          (disables audio output of channel 3)
         2    ATVOL2    Use audio channel 2 to modulate volume
                          of channel 3
         1    ATVOL1    Use audio channel 1 to modulate volume
                          of channel 2
         0    ATVOL0    Use audio channel 0 to modulate volume
                          of channel 1


5 Audio Hardware / Producing High-quality Sound

When trying to create high-quality sound, you need to consider the
following factors:

   *  Waveform transitions.
   *  Sampling rate.
   *  Efficiency.
   *  Noise reduction.
   *  Avoidance of aliasing distortion.
   *  Limitations of the low pass filter.

 Making Waveform Transitions      Noise Reduction
 Sampling Rate                    Aliasing Distortion
 Efficiency                       Low-Pass Filter


5 / Producing High-quality Sound / Making Waveform Transitions

To avoid unpleasant sounds when you change from one waveform to another,
you need to make the transitions smooth. You can avoid "clicks" by making
sure the waveforms start and end at approximately the same value. You can
avoid "pops" by starting a waveform only at a zero-crossing point. You can
avoid "thumps" by arranging the average  amplitude  of each wave to be
about the same value. The average  amplitude  is the sum of the bytes in
the waveform divided by the number of bytes in the waveform.


5 / Producing High-quality Sound / Sampling Rate

If you need high precision in your frequency output, you may find that the
frequency you wish to produce is somewhere between two available sampling
rates, but not close enough to either rate for your requirements. In those
cases, you may have to adjust the length of the audio data table in
addition to altering the sampling rate.

For higher frequencies, you may also need to use audio data tables that
contain more than one full cycle of the audio waveform to reproduce the
desired frequency more accurately, as illustrated in Figure 5-4.

     Figure 5-4: Waveform with Multiple Cycles


5 / Producing High-quality Sound / Efficiency

A certain amount of overhead is involved in the handling of audio DMA.
If you are trying to produce a smooth continuous audio synthesis, you
should try to avoid as much of the system control overhead as possible.
Basically, the larger the audio buffer you provide to the system, the less
often it will need to  interrupt  to reset the pointers to the top of the
next buffer and, coincidentally, the lower the amount of system
interaction that will be required. If there is only one waveform buffer,
the hardware automatically resets the pointers, so no software overhead is
used for resetting them.

The  Joining Tones  section illustrated how you could join "ends" of tones
together by responding to  interrupts  and changing the values of the
 location registers  to splice tones together. If your system is heavily
loaded, it is possible that the response to the  interrupt  might not
happen in time to assure a smooth audio transition. Therefore, it is
advisable to utilize the longest possible audio table where a smooth
output is required. This takes advantage of the audio DMA capability as
well as minimizing the number of  interrupts  to which the 680x0 must
respond.


5 / Producing High-quality Sound / Noise Reduction

To reduce noise levels and produce an accurate sound, try to use the full
range of -128 to 127 when you represent a waveform. This reduces how much
noise (quantization error) will be added to the signal by using more bits
of precision. Quantization noise is caused by the introduction of
round-off error. If you are trying to reproduce a signal, such as a sine
wave, you can represent the  amplitude  of each sample with only so many
digits of accuracy. The difference between the real number and your
approximation is round-off error, or noise.

By doubling the  amplitude , you create half as much noise because the
size of the steps of the wave form stays the same and is therefore a
smaller fraction of the amplitude.

In other words, if you try to represent a waveform using, for example, a
range of only +3 to -3, the size of the error in the output would be
considerably larger than if you use a range of +127 to -128 to represent
the same signal. Proportionally, the digital value used to represent the
waveform  amplitude  will have a lower error. As you increase the number
of possible sample levels, you decrease the relative size of each step
and, therefore, decrease the size of the error.

To produce quiet sounds, continue to define the waveform using the full
range, but adjust the  volume . This maintains the same level of accuracy
(signal-to-noise ratio) for quiet sounds as for loud sounds.


5 / Producing High-quality Sound / Aliasing Distortion

When you use sampling to produce a waveform, a side effect is caused when
the sampling rate "beats" or combines with the frequency you wish to
produce. This produces two additional frequencies, one at the sampling
rate plus the desired frequency and the other at the sampling rate minus
the desired frequency. This phenomenon is called aliasing distortion.

Aliasing distortion is eliminated when the sampling rate exceeds the
output frequency by at least 7 KHz. This puts the beat frequency outside
the range of the  low-pass filter , cutting off the undesirable
frequencies. Figure 5-5 shows a frequency domain plot of the anti-aliasing
 low-pass filter  used in the system.

      /|\
       |
   0db |________ filter
       |        \ response
       |         \
       |          \
       |           \      filter passes all frequences below about 5kHz.
       |            \
 -30db |_____________\_____ ___________________________________________\
                 |         |         |         |         |         |   /
                5kHz     10kHz     15kHz     20kHz     25kHz     30kHz

           Figure 5-5: Frequency Domain Plot of Low-Pass Filter

Figure 5-6 shows that it is permissible to use a 12 KHz sampling rate to
produce a 4 KHz waveform. Both of the beat frequencies are outside the
range of the filter, as shown in these calculations:

                         12 + 4 = 16 KHz
                         12 - 4 = 8 KHz

      /|\  filter            12kHz sampling frequencey
       |  response             |
   0db |________               |
       |        \     Diff.    |      Sum
       |       | \     |       |       |
       |       |  \    |       |       |
       |       |   \   |       |       |
       |   4kHz|    \  |       |       |
 -30db |_______|_____\_|___ ___|_______|_______________________________\
               | |         |         |         |         |         |   /
                5kHz     10kHz     15kHz     20kHz     25kHz     30kHz
               |
               |
       desired output frequency

          Figure 5-6: Noise-free Output (No Aliasing Distortion)

You can see in Figure 5-7 that is unacceptable to use a 10 KHz sampling
rate to produce a 4 KHz waveform. One of the beat frequencies (10 - 4) is
within the range of the filter, allowing some of that undesirable
frequency to show up in the audio output.

      /|\  filter        10kHz sampling frequencey
       |  response         |
   0db |________           |
       |        \ Diff.    |      Sum
       |       | \ |       |       |
       |       |  \|       |       |
       |       |   \       |       |
       |   4kHz|   |\      |       |
 -30db |_______|___|_\_____|_______|___________________________________\
               | |         |         |         |         |         |   /
                5kHz     10kHz     15kHz     20kHz     25kHz     30kHz
               |
               |
       desired output frequency

                   Figure 5-7: Some Aliasing Distortion

All of this gives rise to the following equation, showing that the
sampling frequency must exceed the output frequency by at least 7 KHz, so
that the beat frequency will be above the cutoff range of the
 anti-aliasing filter :

   Minimum sampling rate = highest frequency component + 7 KHz

The frequency component of the equation is stated as "highest frequency
component" because you may be producing a complex waveform with multiple
frequency elements, rather than a pure sine wave.


5 / Producing High-quality Sound / Low-Pass Filter

The system includes a low-pass filter that eliminates
 aliasing distortion  as described above. This filter becomes active
around 4 KHz and gradually begins to attenuate (cut off) the signal.
Generally, you cannot clearly hear frequencies higher than 7 KHz.
Therefore, you get the most complete frequency response in the frequency
range of 0 - 7 KHz. If you are making frequencies from 0 to 7 KHz, you
should select a sampling rate no less than 14 KHz, which corresponds to a
 sampling period  in the range 124 to 256.

At a  sampling period  around 320, you begin to lose the higher frequency
values between 0 KHz and 7 KHz, as shown in Table 5-6.

          Table 5-6: Sampling Rate and Frequency Relationship

                            Sampling    Sampling    Maximum Output
                             Period    Rate (KHz)   Frequency (KHz)
                            --------   ----------   ---------------
     Maximum sampling rate    124         29              7
     Minimum sampling rate    256         14              7
       for 7 KHz output
     Sampling rate too low    320         11              4
       for 7 KHz output

In A2000's with 2 layer motherboards and later A500 models there is a
control bit that allows the audio output to bypass the low pass filter.
This control bit is the same output bit of the  8520 CIA  that controls
the brightness of the red "power" LED (CIA A $BFE001 - Bit 1: /LED).
Bypassing the filter allows for improved sound in some applications, but
an external filter with an appropriate cutoff frequency may be required.


5 Audio Hardware / Using Direct (Non-DMA) Audio Output

It is possible to create sound by writing audio data one word at a time to
the audio output addresses, instead of setting up a list of audio data in
memory. This method of controlling the output is more processor-intensive
and is therefore not recommended.

To use direct audio output, do not enable the DMA for the audio channel
you wish to use; this changes the timing of the  interrupts . The normal
 interrupt  occurs after a data address has been read; in direct audio
output, the  interrupt  occurs after one data word has been output.

Unlike in the DMA-controlled automatic data output, in direct audio
output, if you do not write a new set of data to the output addresses
before two sampling intervals have elapsed, the audio output will cease
changing. The last value remains as an output of the
 digital-to-analog converter .

The  volume  and  period registers  are set as usual.


5 Audio Hardware / The Equal-tempered Musical Scale

Table 5-7 gives a close approximation of the equal-tempered scale over one
octave when the sample size is 16 bytes.  The " Period " column gives the
period count you enter into the  period register . The length register
 AUDxLEN  should be set to 8  (16 bytes = 8 words). The sample should
represent one cycle of the waveform.

         Table 5-7: Equal-tempered Octave for a 16 Byte Sample

        NTSC    PAL              Ideal   Actual NTSC  Actual PAL
       Period  Period   Note   Frequency  Frequency   Frequency
       ------  ------   ----   --------- -----------  ----------
        254     252      A       880.0      880.8       879.7
        240     238      A#      932.3      932.2       931.4
        226     224      B       987.8      989.9       989.6
        214     212      C      1046.5     1045.4      1045.7
        202     200      C#     1108.7     1107.5      1108.4
        190     189      D      1174.7     1177.5      1172.9
        180     178      D#     1244.5     1242.9      1245.4
        170     168      E      1318.5     1316.0      1319.5
        160     159      F      1396.9     1398.3      1394.2
        151     150      F#     1480.0     1481.6      1477.9
        143     141      G      1568.0     1564.5      1572.2
        135     133      G#     1661.2     1657.2      1666.8

The table above shows the  period values  to use with a 16 byte sample to
make tones in the second octave above middle C.   To generate the tones in
the lower octaves, there are two methods you can use, doubling the period
value or doubling the sample size.

When you double the  period , the time between each sample is doubled so
the sample takes twice as long to play.  This means the frequency of the
tone generated is cut in half which gives you the next lowest octave.
Thus, if you play a C with a  period value  of 214, then playing the same
sample with a  period value  of 428 will play a C in the next lower octave.

Likewise, when you double the sample size, it will take twice as long to
play back the whole sample and the frequency of the tone generated will be
in the next lowest octave.  Thus, if you have an 8 byte sample and a 16
byte sample of the same waveform played at the same speed, the 16 byte
sample will be an octave lower.

A sample for an equal-tempered scale typically represents one full cycle
of a note.  To avoid  aliasing distortion  with these samples you should
use  period values  in the range 124-256 only.   Periods  from 124-256
correspond to playback rates in the range 14-28K samples per second which
makes the most effective use of the Amiga's 7 KHz  cut-off filter  to
prevent noise. To stay within this range you will need a different sample
for each octave.

If you cannot use a different sample for each octave, then you will have
to adjust the  period value  over its full range 124-65536.  This is
easier for the programmer but can produce undesirable high-frequency noise
in the resulting tone.  Read the section called  Aliasing Distortion  for
more about this.

The values in Table 5-7 were generated using the formula shown below.  To
calculate the tone generated with a given sample size and  period  use:

                  Clock Constant         3579545
   Frequency = --------------------- = ----------- = 880.8 Hz
               Sample Bytes * Period   16 * Period

The clock constant in an NTSC system is 3579545 ticks per second.  In a
PAL system, the clock constant is 3546895 ticks per second. Sample bytes
is the number of bytes in one cycle of the waveform sample. (The clock
constant is derived from dividing the system clock value by 2. The value
will vary when using an external system clock, such as a genlock.)

Using the formula above you can generate the values needed for the
even-tempered scale for any arbitrary sample.  Table 5-8 gives a close
approximation of a five octave even tempered-scale using five samples. The
values were derived using the formula above.  Notice that in each octave
 period values  are the same but the sample size is halved.  The samples
listed represent a simple triangular wave form.

               Table 5-8: Five Octave Even-tempered Scale

         NTSC    PAL              Ideal   Actual NTSC  Actual PAL
        Period  Period   Note   Frequency  Frequency   Frequency
        ------  ------   ----   --------- -----------  ----------
         254     252      A       55.00      55.05       54.98
         240     238      A#      58.27      58.26       58.21
         226     224      B       61.73      61.87       61.85
         214     212      C       65.40      65.34       65.35
         202     200      C#      69.29      69.22       69.27
         190     189      D       73.41      73.59       73.30
         180     178      D#      77.78      77.68       77.83
         170     168      E       82.40      82.25       82.47
         160     159      F       87.30      87.39       87.13
         151     150      F#      92.49      92.60       92.36
         143     141      G       98.00      97.78       98.26
         135     133      G#     103.82     103.57      104.17

               Sample size = 256 bytes,  AUDxLEN  = 128

         254     252      A      110.00     110.10      109.96
         240     238      A#     116.54     116.52      116.43
         226     224      B      123.47     123.74      123.70
         214     212      C      130.81     130.68      130.71
         202     200      C#     138.59     138.44      138.55
         190     189      D      146.83     147.18      146.61
         180     178      D#     155.56     155.36      155.67
         170     168      E      164.81     164.50      164.94
         160     159      F      174.61     174.78      174.27
         151     150      F#     184.99     185.20      184.73
         143     141      G      196.00     195.56      196.52
         135     133      G#     207.65     207.15      208.35

               Sample size = 128 bytes,  AUDxLEN  = 64

         254     252      A      220.00     220.20      219.92
         240     238      A#     233.08     233.04      232.86
         226     224      B      246.94     247.48      247.41
         214     212      C      261.63     261.36      261.42
         202     200      C#     277.18     276.88      277.10
         190     189      D      293.66     294.37      293.23
         180     178      D#     311.13     310.72      311.35
         170     168      E      329.63     329.00      329.88
         160     159      F      349.23     349.56      348.55
         151     150      F#     369.99     370.40      369.47
         143     141      G      392.00     391.12      393.05
         135     133      G#     415.30     414.30      416.70

                Sample size = 64 bytes,  AUDxLEN  = 32

         254     252      A      440.0      440.4       439.8
         240     238      A#     466.16     466.09      465.72
         226     224      B      493.88     494.96      494.82
         214     212      C      523.25     522.71      522.83
         202     200      C#     554.37     553.77      554.20
         190     189      D      587.33     588.74      586.46
         180     178      D#     622.25     621.45      622.70
         170     168      E      659.26     658.00      659.76
         160     159      F      698.46     699.13      697.11
         151     150      F#     739.99     740.80      738.94
         143     141      G      783.99     782.24      786.10
         135     133      G#     830.61     828.60      833.39

                Sample size = 32 bytes,  AUDxLEN  = 16

         254     252      A      880.0      880.8       879.7
         240     238      A#     932.3      932.2       931.4
         226     224      B      987.8      989.9       989.6
         214     212      C      1046.5    1045.4      1045.7
         202     200      C#     1108.7    1107.5      1108.4
         190     189      D      1174.7    1177.5      1172.9
         180     178      D#     1244.5    1242.9      1245.4
         170     168      E      1318.5    1316.0      1319.5
         160     159      F      1396.9    1398.3      1394.2
         151     150      F#     1480.0    1481.6      1477.9
         143     141      G      1568.0    1564.5      1572.2
         135     133      G#     1661.2    1657.2      1666.8

                Sample size = 16 bytes,  AUDxLEN  = 8

                            256 Byte Sample
                            ---------------

      0   2   4   6   8  10  12  14  16  18  20  22  24  26  28  30
     32  34  36  38  40  42  44  46  48  50  52  54  56  58  60  62
     64  66  68  70  72  74  76  78  80  82  84  86  88  90  92  94
     96  98 100 102 104 106 108 110 112 114 116 118 120 122 124 126
    128 126 124 122 120 118 116 114 112 110 108 106 104 102 100  98
     96  94  92  90  88  86  84  82  80  78  76  74  72  70  68  66
     64  62  60  58  56  54  52  50  48  46  44  42  40  38  36  34
     32  30  28  26  24  22  20  18  16  14  12  10   8   6   4   2
      0  -2  -4  -6  -8 -10 -12 -14 -16 -18 -20 -22 -24 -26 -28 -30
    -32 -34 -36 -38 -40 -42 -44 -46 -48 -50 -52 -54 -56 -58 -60 -62
    -64 -66 -68 -70 -72 -74 -76 -78 -80 -82 -84 -86 -88 -90 -92 -94
    -96 -98-100-102-104-106-108-110-112-114-116-118-120-122-124-126
   -127-126-124-122-120-118-116-114-112-110-108-106-104-102-100 -98
    -96 -94 -92 -90 -88 -86 -84 -82 -80 -78 -76 -74 -72 -70 -68 -66
    -64 -62 -60 -58 -56 -54 -52 -50 -48 -46 -44 -42 -40 -38 -36 -34
    -32 -30 -28 -26 -24 -22 -20 -18 -16 -14 -12 -10  -8  -6  -4  -2

                            128 Byte Sample
                            ---------------

      0   4   8  12  16  20  24  28  32  36  40  44  48  52  56  60
     64  68  72  76  80  84  88  92  96 100 104 108 112 116 120 124
    128 124 120 116 112 108 104 100  96  92  88  84  80  76  72  68
     64  60  56  52  48  44  40  36  32  28  24  20  16  12   8   4
      0   4   8  12  16  20  24  28  32  36  40  44  48  52  56  60
     64  68  72  76  80  84  88  92  96 100 104 108 112 116 120 124
   -127-124-120-116-112-108-104-100 -96 -92 -88 -84 -80 -76 -72 -68
    -64 -60 -56 -52 -48 -44 -40 -36 -32 -28 -24 -20 -16 -12  -8  -4

                             64 Byte Sample
                             --------------

      0   8  16  24  32  40  48  56  64  72  80  88  96 104 112 120
    128 120 112 104  96  88  80  72  64  56  48  40  32  24  16   8
      0  -8 -16 -24 -32 -40 -48 -56 -64 -72 -80 -88 -96-104-112-120
   -127-120-112-104 -96 -88 -80 -72 -64 -56 -48 -40 -32 -24 -16  -8

                             32 Byte Sample
                             --------------

      0  16  32  48  64  80  96 112 128 112  96  80  64  48  32  16
      0 -16 -32 -48 -64 -80 -96-112-127-112 -96 -80 -64 -48 -32 -16

                             16 Byte Sample
                             --------------

      0  32  64  96 128  96  64  32   0 -32 -64 -96-127 -96 -64 -32


5 Audio Hardware / Decibel Values for Volume Ranges

Table 5-9 provides the corresponding decibel values for the  volume
ranges of the Amiga system.

             Table 5-9: Decibel Values and Volume Ranges

            Volume  Decibel Value    Volume  Decibel Value
            ------  -------------    ------  -------------
              64         0.0           32        -6.0
              63        -0.1           31        -6.3
              62        -0.3           30        -6.6
              61        -0.4           29        -6.9
              60        -0.6           28        -7.2
              59        -0.7           27        -7.5
              58        -0.9           26        -7.8
              57        -1.0           25        -8.2
              56        -1.2           24        -8.5
              55        -1.3           23        -8.9
              54        -1.5           22        -9.3
              53        -1.6           21        -9.7
              52        -1.8           20       -10.1
              51        -2.0           19       -10.5
              50        -2.1           18       -11.0
              49        -2.3           17       -11.5
              48        -2.5           16       -12.0
              47        -2.7           15       -12.6
              46        -2.9           14       -13.2
              45        -3.1           13       -13.8
              44        -3.3           12       -14.5
              43        -3.5           11       -15.3
              42        -3.7           10       -16.1
              41        -3.9            9       -17.0
              40        -4.1            8       -18.1
              39        -4.3            7       -19.2
              38        -4.5            6       -20.6
              37        -4.8            5       -22.1
              36        -5.0            4       -24.1
              35        -5.2            3       -26.6
              34        -5.5            2       -30.1
              33        -5.8            1       -36.1
                                        0   Minus infinity


5 Audio Hardware / The Audio State Machine

For an explanation of the various states, refer to Figure 5-8. There is
one audio state machine for each channel. The machine has eight states and
is clocked at the clock constant rate (3.58 MHz NTSC). Three of the states
are basically unused and just transfer back to the idle (000) state. One
of the paths out of the idle state is designed for interrupt-driven
operation (processor provides the data), and the other path is designed
for DMA-driven operation (the "Agnus" special chip provides the data).

In interrupt-driven operation, transfer to the main loop (states 010 and
011) occurs immediately after data is written by the processor. In the 010
state the upper byte is output, and in the 011 state the lower byte is
output. Transitions such as 010->011->010 occur whenever the period
counter counts down to one. The period counter is reloaded at these
transitions. As long as the  interrupt  is cleared by the processor in
time, the machine remains in the main loop. Otherwise, it enters the idle
state.  Interrupts  are generated on every word transition (011->010).

In DMA-driven operation, transition to the 001 state occurs and DMA
requests are sent to Agnus as soon as DMA is turned on. Because of
pipelining in Agnus, the first data word must be thrown away. State 101 is
entered as soon as this word arrives; a request for the next data word has
already gone out. When the data arrives, state 010 is entered and the main
loop continues until the DMA is turned off. The length counter counts down
once with each word that comes in. When it finishes, a DMA restart request
goes to Agnus along with the regular DMA request. This tells Agnus to
reset the pointer to the beginning of the table of data. Also, the length
counter is reloaded and an  interrupt  request goes out soon after the
length counter finishes (counts to one). The request goes out just as the
last word of the waveform starts its output.

DMA requests and restart requests are transferred to Agnus once each
horizontal line, and the data comes back about 14 clock cycles later (the
duration of a clock cycle is 280 ns).

In attach mode, things run a little differently. In attach volume,
requests occur as they do in normal operation (on the 011->010
transition). In attach period, a set of requests occurs on the 010->011
transition. When both attach period and attach volume are high, requests
occur on both transitions.

If the sampling rate is set much higher than the normal maximum sampling
rate (approximately 29 KHz), the two samples in the buffer register will
be repeated. If the  filter  on the Amiga is bypassed and the  volume  is
set to the maximum ($40), this feature can be used to make modulated
carriers up to 1.79 MHz. The modulation is placed in the memory map, with
plus values in the even bytes and minus values in the odd bytes.

The symbols used in the state diagram are explained in the following list.
Upper-case names indicate external signals; lower-case names indicate
local signals.

   AUDxON      DMA on "x" indicates channel number (signal from  DMACON ).

   AUDxIP       Audio interrupt  pending (input to channel from interrupt
               circuitry).

   AUDxIR       Audio interrupt  request (output from channel to interrupt
               circuitry)

   intreq1     Interrupt request that combines with intreq2 to form
               AUDxIR..

   intreq2     Prepare for interrupt request. Request comes out after the
               next 011->010 transition in normal operation.

   AUDxDAT     Audio data load signal. Loads 16 bits of data to audio
               channel.

   AUDxDR      Audio DMA request to Agnus for one word of data.

   AUDxDSR     Audio DMA request to Agnus to reset pointer to start of
               block.

   dmasen      Restart request enable.

   percntrld   Reload period counter from back-up latch typically written
               by processor with  AUDxPER  (can also be written by attach
               mode).

   percount    Count period counter down one latch.

   perfin      Period counter finished (value = 1).

   lencntrld   Reload length counter from back-up latch.

   lencount    Count length counter down one notch.

   lenfin      Length counter finished (value = 1).

   volcntrld   Reload volume counter from back-up latch.

   pbufld1     Load output buffer from holding latch written to by AUDxDAT.

   pbufld2     Like pbufld1, but only during 010->011 with attach period.

   AUDxAV      Attach volume. Send data to volume latch of next channel
               instead of to D->A converter.

   AUDxAP      Attach period. Send data to period latch of next channel
               instead of to the D->A converter.

   penhi       Enable the high 8 bits of data to go to the D->A converter.

   napnav      /AUDxAV * /AUDxAP + AUDxAV -- no attach stuff or else attach
               volume. Condition for normal DMA and interrupt requests.

   sq2,1,0     The name of the state flip-flops, MSB to LSB.

     Figure 5-8: Audio State Diagram

   ECS Audio.
   ----------
   For information on the audio hardware in the Enhanced Chip Set,
   see the  ECS register map  in Appendix C.


Amiga® Hardware Reference Manual: E I/O Connectors And Interfaces

This appendix consists of four distinct parts, related to the way in which
the Amiga talks to the outside world.

The first part specifies the pinouts of the externally accessible
connectors and the power available at each connector. It does not,
however, provide timing or loading information.

The second part briefly describes the functions of those pins whose
purpose may not be evident.

The third part contains a list of the connections for certain internal
connectors, notably the disk.

The fourth part specifies how various signals relate to the available
ports of the 8520. This information enables the programmer to relate the
port addresses to the outside-world items (or internal control signals)
that are to be affected.

The third and fourth parts are primarily for the use of the systems
programmer and should generally not be utilized by applications
programmers.

Systems software normally is configured to handle the setting of
particular signals, no matter how the physical connections may change. In
other words, if you have a version of the system software that matches the
revision level of the machine (normally a true condition), when you ask
that a particular bit be set, you don't care which port that bit is
connected to. Thus, applications programmers should rely on system
documentation rather than going directly to the ports.

   Warning:
   --------
   In a multitasking operating system, many different tasks may be
   competing for the use of the system resources. Application
   programmers should follow the established rules for resource access
   in order to assure compatibility of their software with the system.
   Don't just hit the hardware registers directly, ask the system for
   exclusive control first.

 Part 1 - Amiga I/O Connector Pins
 Part 2 - Explanation of Amiga I/O Connectors
 Part 3 - Internal Connectors
 Part 4 - Port Signal Assignments for 8520 CIAS


E I/O Connectors And Interfaces / Part 1 - Amiga I/O Connector Pins

This is a list of the I/O connections to the outside world on the Amiga.

 RS232 and MIDI Port         External Disk
 Parallel Port               External SCSI Disk
 Keyboard                    RAMEX
 Video                       Expansion
 Video Display Enhancer      Joy Sticks
 RF Monitor


E / Amiga I/O Connector Pins / RS232 and MIDI Port

RS232 and MIDI Port
-------------------

                   A500/
                   A2000/ CBM
PIN  RS232  A1000  A3000  PCs   HAYES  DESCRIPTION
---------------------------------------------------
1    GND    GND    GND    GND   GND    FRAME GROUND
2    TXD    RXD    RXD    RXD   RXD    TRANSMIT DATA
3    RXD    RXD    RXD    RXD   RXD    RECEIVE DATA
4    RTS    RTS    RTS    RTS   -      REQUEST TO SEND
5    CTS    CTS    CTS    CTS   CTS    CLEAR TO SEND
6    DSR    DSR    DSR    DSR   DSR    DATA SET READY
7    GND    GND    GND    GND   GND    SYSTEM GROUND
8    CD     CD     CD     DCD   DCD    CARRIER DETECT
9    -      -      +12v   +12v  -      + 12 VOLT POWER
10   -      -      -12v   -12v  -      - 12 VOLT POWER
11   -      -      AUDO   -     -      AUDIO OUTPUT  (A500, A2000, A3000)
12   S.SD   -      -      -     SI     SPEED INDICATE
13   S.CTS  -      -      -     -
14   S.TXD  -5Vdc  -      -     -      - 5 VOLT POWER
15   TXC    AUDO   -      -     -      AUDIO OUTPUT  (A1000)
16   S.RXD  AUDI   -      -     -      AUDIO INPUT  (A1000)
17   RXC    EB     -      -     -      BUFFERED PORT CLOCK 716kHz
18   -      INT2*  AUDI   -     -      INTERRUPT LINE A1000/AUDIO INPUT
                                           (A500, 2000, 3000)
19   S.RTS  -      -      -     -
20   DTR    DTR    DTR    DTR DTR      DATA TERMINAL READY
21   SQD    +5            -     -      + 5 VOLT POWER
22   RI     -      RI     RI    RI     RING INDICATOR
23   SS     +12Vdc -      -     -      +12 VOLT POWER
24   TXC1   C2*    -      -     -      3.58 MHZ CLOCK
25   -      RESB*  -      -     -      BUFFERED SYSTEM RESET


E / Amiga I/O Connector Pins / Parallel Port

Parallel (Centronics) Port
--------------------------

   PIN     A1000       A500/A2000/A3000    Commodore PCs
   ---     -----       ----------------   -------------
   1       DRDY*           STROBE*         STROBE*
   2       Data 0          Data 0          Data 0
   3       Data 1          Data 1          Data 1
   4       Data 2          Data 2          Data 2
   5       Data 3          Data 3          Data 3
   6       Data 4          Data 4          Data 4
   7       Data 5          Data 5          Data 5
   8       Data 6          Data 6          Data 6
   9       Data 7          Data 7          Data 7
   10      ACK*            ACK*            ACK*
   11      BUSY (data)     BUSY            BUSY
   12      POUT (clk)      POUT            POUT
   13      SEL             SEL             SEL
   14      GND             +5v pullup      AUTOFDXT
   15      GND             NC              ERROR*
   16      GND             RESET*          INIT*
   17      GND             GND             SLCT IN*
   18-22   GND             GND             GND
   23      + 5             GND             GND
   24      NC              GND             GND
   25      Reset*          GND             GND


E / Amiga I/O Connector Pins / Keyboard

KEYBOARD ...RJ11 (Not Applicable to the A500)
---------------------------------------------

       A1000       A2000/A3000
       -----       -----------
   1   +5 Volts       KCLK
   2   CLOCK          KDAT
   3   DATA           NC
   4   GND            GND
   5                  +5 Volts


E / Amiga I/O Connector Pins / Video

Video ...DB23 MALE
------------------
For A500, A1000, A2000 and A3000 unless otherwise stated

   1   XCLK*               13   GNDRTN (Return for XCLKEN*)
   2   XCLKEN*             14   ZD*
   3   RED                 15   C1*
   4   GREEN               16   GND
   5   BLUE                17   GND
   6   DI                  18   GND
   7   DB                  19   GND
   8   DG                  20   GND
   9   DR                  21   -5 VOLT POWER(A1000,A2000,A3000)
   10  CSYNC*                   -12 VOLT POWER (A500)
   11  HSYNC*              22   +12 VOLT POWER
   12  VSYNC*              23   +5 VOLT POWER


E / Amiga I/O Connector Pins / Video Display Enhancer

Video Display Enhancer - DB 15 Female (A3000 ONLY)
--------------------------------------------------

   1   RED VIDEO
   2   GREEN VIDEO
   3   BLUE VIDEO
   4   MONITOR ID BIT 2 (NOT USED)
   5   GROUND
   6   RED RETURN (GROUND)
   7   GREEN RETURN (GROUND)
   8   BLUE RETURN (GROUND)
   9   KEY (NO PIN)
   10  SYNC RETURN (GROUND)
   11  MONITOR ID BIT 0 (NOT USED)
   12  MONITOR ID BIT 1 (NOT USED)
   13  HORIZONTAL SYNC
   14  VERTICAL SYNC
   15  NOT USED


E / Amiga I/O Connector Pins / RF Monitor

RF Monitor ...8 PIN DIN  (J2) (A1000 Only)
-----------------------------------------

   1   N.C.
   2   GND
   3   AUDIO LEFT
   4   COMP VIDEO
   5   GND
   6   N.C.
   7   +12 VOLT POWER
   8   AUDIO RIGHT


E / Amiga I/O Connector Pins / External Disk

EXTERNAL DISK ...DB23 FEMALE
----------------------------

For A1000, A500, A2000 and A3000 with A2000 and A3000 differences noted.

1   RDY*                             13  SIDEB*
2   DKRD*                            14  WPRO*
3   GND                              15  TK0*
4   GND                              16  DKWEB*
5   GND                              17  DKWDB*
6   GND                              18  STEPB*
7   GND                              19  DIRB
8   MTRXD*                           20  SEL3B* (A2000/A3000 not used (1))
9   SEL2B* (A2000/A3000 SEL3B* (1))  21  SEL1B* (A2000/A3000 SEL2B* (1))
10  DRESB*                           22  INDEX*
11  CHNG*                            23  +12
12  +5

(1)  SEL1B*  is not drive 1, but rather the first external drive.  Not
    all select lines may be implemented.


E / Amiga I/O Connector Pins / External SCSI Disk

EXTERNAL SCSI DISK 	DB25 FEMALE (A3000 ONLY)
------------------------------------------------

   1       REQ             14      GROUND
   2       MSG*            15      C/D
   3       I/O             16      GROUND
   4       RST*            17      ATN*
   5       ACK*            18      GROUND
   6       BSY*            19      SEL*
   7       GROUND          20      PARITY
   8       DATA0           21      DATA1
   9       GROUND          22      DATA2
   10      DATA3           23      DATA4
   11      DATA5           24      GROUND
   12      DATA6           25      TERMINATION POWER
   13      DATA7

See the ANSI (American National Standard Institute ) standard SCSI (Small
Computer Standard Interface) Specification for more information.


E / Amiga I/O Connector Pins / RAMEX

RAMEX ...60 PIN EDGE (.156)  (P1) (A1000 only)
----------------------------------------------

   1   gnd               A   gnd
   2   D15               B   D14
   3   +5                C   +5
   4   D12               D   D13
   5   gnd               E   gnd
   6   D11               F   D10
   7   +5                H   +5
   8   D8                J   D9
   9   gnd               K   gnd
   10  D7                L   D6
   11  +5                M   +5
   12  D4                N   D5
   13  gnd               P   gnd
   14  D3                R   D2
   15  +5                S   +5
   16  D0                T   D1
   17  gnd               U   gnd
   18  DRA4              V   DRA3
   19  DRA5              W   DRA2
   20  DRA6              X   DRA1
   21  DRA7              Y   DRA0
   22  gnd               Z   gnd
   23  RAS*              AA  RRW*
   24  gnd               BB  gnd
   25  gnd               CC  gnd
   26  CASU0*            DD  CASU1*
   27  gnd               EE  gnd
   28  CASL0*            FF  CASL1*
   29  +5                HH  +5
   30  +5                JJ  +5


E / Amiga I/O Connector Pins / Expansion

EXPANSION ...86 PIN EDGE (.1) (P2)
----------------------------------

See Appendix K for the  100 pin  Zorro II and Zorro III bus connector

   PIN     A500    A1000   A2000   A2000b  FUNCTION
   ---     ----    -----   -----   ------  --------
   1       x       x       x       x       ground
   2       x       x       x       x       ground
   3       x       x       x       x       ground
   4       x       x       x       x       ground
   5       x       x       x       x       +5VDC
   6       x       x       x       x       +5VDC
   7       x       x       x       x       No Connect
   8       x       x       x       x       -5VDC
   9       x       x                       No Connect
                           x       x       28MHz Clock
   10      x       x       x       x       +12VDC
   11      x       x       x               No Connect
                                   x       /COPCFG (Configuration Out)
   12      x       x       x       x       CONFIG IN, Grounded
   13      x       x       x       x       Ground
   14      x       x       x       x       /C3 Clock
   15      x       x       x       x       CDAC Clock
   16      x       x       x       x       /C1 Clock
   17      x       x       x       x       /OVR
   18      x       x       x       x       RDY
   19      x       x       x       x       /INT2
   20              x                       /PALOPE
           x               x               No Connect
                                   x       /BOSS
   21      x       x       x       x       A5
   22      x       x       x       x       /INT6
   23      x       x       x       x       A6
   24      x       x       x       x       A4
   25      x       x       x       x       ground
   26      x       x       x       x       A3
   27      x       x       x       x       A2
   28      x       x       x       x       A7
   29      x       x       x       x       A1
   30      x       x       x       x       A8
   31      x       x       x       x       FC0
   32      x       x       x       x       A9
   33      x       x       x       x       FC1
   34      x       x       x       x       A10
   35      x       x       x       x       FC2
   36      x       x       x       x       A11
   37      x       x       x       x       Ground
   38      x       x       x       x       A12
   39      x       x       x       x       A13
   40      x       x       x       x       /IPL0
   41      x       x       x       x       A14
   42      x       x       x       x       /IPL1
   43      x       x       x       x       A15
   44      x       x       x       x       /IPL2
   45      x       x       x       x       A16
   46      x       x       x       x       BEER*
   47      x       x       x       x       A17
   48      x       x       x       x       /VPA
   49      x       x       x       x       Ground
   50      x       x       x       x       E Clock
   51      x       x       x       x       /VMA
   52      x       x       x       x       A18
   53      x       x       x       x       RST
   54      x       x       x       x       A19
   55      x       x       x       x       /HLT
   56      x       x       x       x       A20
   57      x       x       x       x       A22
   58      x       x       x       x       A21
   59      x       x       x       x       A23
   60      x       x       x               /BR
                                   x       /CBR
   61      x       x       x       x       Ground
   62      x       x       x       x       /BGACK
   63      x       x       x       x       D15
   64      x       x       x               /BG
                                   x       /CBG
   65      x       x       x       x       D14
   66      x       x       x       x       /DTACK
   67      x       x       x       x       D13
   68      x       x       x       x       R/W
   69      x       x       x       x       D12
   70      x       x       x       x       /LDS
   71      x       x       x       x       D11
   72      x       x       x       x       /UDS
   73      x       x       x       x       Ground
   74      x       x       x       x       /AS
   75      x       x       x       x       D0
   76      x       x       x       x       D10
   77      x       x       x       x       D1
   78      x       x       x       x       D9
   79      x       x       x       x       D2
   80      x       x       x       x       D8
   81      x       x       x       x       D3
   82      x       x       x       x       D7
   83      x       x       x       x       D4
   84      x       x       x       x       D6
   85      x       x       x       x       Ground
   86      x       x       x       x       D5


E / Amiga I/O Connector Pins / Joy Sticks

JOY STICKS ...DB9 male
----------------------

   USAGE   JOYSTICK        MOUSE
   -----   --------        -----
   1       FORWARD*        (MOUSE V)
   2       BACK*           (MOUSE H)
   3       LEFT*           (MOUSE VQ)
   4       RIGHT*          (MOUSE HQ)
   5       POT X           (or button 3 ... if used )
   6       FIRE*           (or button 1)
   7       +5
   8       GND
   9       POT Y           (or button 2 )


E I/O Connectors And Interfaces / Explanation of Amiga I/O Connectors

 Parallel Connector Interface Specification
 Serial Interface Connector Specification
 Game Controller Connector Interface Specification
 External Disk Interface Connector Specification


E / Explanation of I/O Connectors / Parallel Interface Specification

The 25-pin D-type connector with pins (DB25P=male for the A1000, female
for A500/A2000 and IBM compatibles) at the rear of the Amiga is nominally
used to interface to parallel printers.  In this capacity, data flows from
the Amiga to the printer.  This interface may also be used for input or
bidirectional data transfers.  The implementation is similar to
Centronics, but the pin assignment and drive characteristics vary
significantly from that specification (see Pin Assignment).  Signal names
correspond to those used in the other places in this appendix, when
possible.

 Pin Assignment (J8)
 Interface Timing, Output Cycle
 Interface Timing, Input Cycle


E / / Parallel Interface Specification / Pin Assignment (J8)

   NAME    DIR   NOTES
   ----    ---   ------------------------
   DRDY*    O    Output-data-ready signal to parallel device in
                 output mode, used in conjunction with ACK* (pin 10)
                 for a two-line asynchronous handshake.  Functions
                 as input data accepted from Amiga in input mode
                 (similar to ACK* in output mode).  See  timing diagrams
                 in the following section.
   D0      I/O   +
   D1      I/O   |
   D2      I/O   |
   D3      I/O   | D0-D7 comprise an eight-bit bidirectional bus
   D4      I/O   | for communication with parallel devices,
   D5      I/O   | nominally, a printer.
   D6      I/O   |
   D7      I/O   +
   ACK*     I    Output-data-acknowledge from parallel device in
                 output mode, used in conjunction with DRDY* (pin 1)
                 for a two-line asynchronous handshake.  Functions as
                 input-data-ready from parallel device in input mode
                 (similar to DRDY* in output mode).
                 See  timing diagrams .  The 8520 can be programmed to
                 conditionally generate a level 2 interrupt to the
                 680x0 whenever the ACK* input goes active.
   BUSY    I/O   This is a general purpose I/O pin also connected to a
                 serial data I/O pin (serial clock on pin 12).
                 Note: Nominally used to indicate printer buffer full.
   POUT    I/O   This is a general purpose I/O pin to a
                 serial clock I/O pin (serial data on pin 11).
                 Note: Nominally used to indicate printer paper out.
   SEL     I/O   This is a general purpose I/O pin.
                 Note:  nominally a select output from the parallel
                 device to the Amiga.  On the A500/A2000 also shared
                 with RS232 "ring indicator" signal.

   RESET*   O    Amiga system reset


E / / Parallel Interface Specification / Interface Timing Output Cycle

           PA<7:0>___ _________________________________________ __
           PB<7:0>___X_________________________________________X__
                     |<-- T1 --->|                             |
                                 |        |<-------- T2 ------>|
                  _______________V        V________________________
           DRDY*                 |________|
             Output data ready   |<- T3 ->|
                                 |<--- T4 --->|
                  ____________________________|<- T5 -->|__________
           ACK*                               |_________|
             Output data acknowledge

                   Microseconds
                   Min Typ Max
                   --- --- ---
               T1: 4.3 -x- 5.3         Output data setup to ready delay.
               T2: nsp -x- upc         Output data hold time.
               T3: nsp 1.4 nsp         Output data ready width.
               T4:  0  -x- upc         Ready to acknowledge delay.
               T5: nsp -x- upc         Acknowledge width.

                   nsp = not specified
                   upc = under program control


E / / Parallel Interface Specification / Interface Timing, Input Cycle

           PA<7:0>___ _________________________________________ __
           PB<7:0>___X_________________________________________X__
                     |<-- T1 --->|
                                 |               T2 -->|<----->|
                  _______________V         ____________|__________
           ACK*                  |________|            |
             Input data ready    |<- T3 ->|            |
                                 |<-- T4 --->|
                  ___________________________|<- T5 -->|__________
           DRDY*                             |_________|
             Input data acknowledge

                   Microseconds
                   Min Typ Max
                   --- --- ---
               T1:  0  -x- upc         Input data setup time.
               T2: nsp -x- upc         Input data hold time.
               T3: nsp -x- upc         Input data ready width.
               T4: upc -x- upc         Input data ready to data
                                         acknowledge delay.
               T5: nsp 1.4 nsp         Input data acknowledge width.

                   nsp = not specified
                   upc = under program control


E / Explanation of I/O Connectors / Serial Interface Specification

This 25-pin D-type connector with sockets (DB25S=female) is used to
interface to RS-232-C standard signals.  Signal names correspond to those
used in other places in this appendix, when possible.

   WARNING:
   --------
   Pins on the RS232 connector other than these standard ones described
   below may be connected to power or other non-RS232 standard signals.
   When making up RS232 cables, connect only those pins actually used
   for a particular application.  Avoid generic 25-connector "straight-
   thru" cables.

 Pin Assignment (J6)
 Timing
 Electrical Characteristics


E / / Serial Interface Specification / Pin Assignment (J6)

              RS-232-C

   NAME   DIR  STD  NOTES
   ----   ---  ---  --------------------------
   FGND         y   Frame ground -- do not tie to signal ground
   TXD     O    y   Transmit data
   RXD     I    y   Receive data
   RTS     O    y   Request to send
   CTS     I    y   Clear to send
   DSR     I    y   Data set ready
   GND          y   Signal ground -- do not tie to frame ground
   CD      I    y   Carrier detect
   -5V          n*  50 ma maximum   *** WARNING -5V ***
   AUDO    O    n*  Audio output from left (channels 0, 3) port,
                    intended to send audio to the modem.
   AUDI    I    n*  Audio input to right (channels 1, 2) port,
                    intended to receive audio from the modem; this
                    input is mixed with the analog output of the
                    right (channels 1, 2). It is not digitized or
                    used by the computer in any way.
   DTR     O    y   Data terminal ready.
   RI      I    y   Ring Indicator (A500/A2000 only) shared with printer
                    "select" signal.
   RESB*   O    n*  Amiga system reset.

NOTES:
     n*:  See  warning  above
     See part 1 of this appendix for  pin numbers .


E / / Serial Interface Specification / Timing

Maximum operating frequency is 19.2 KHz.  Refer to EIA standard RS-232-C
for operating and installation specifications.  A rate of 31.25 KHz will
be supported through the use of a MIDI adapter.

Modem control signals ( CTS, RTS, DTR, DSR, CD ) are completely under
software control.  The modem control lines have no hardware affect on and
are completely asynchronous to  TXD and RXD .


E / / Serial Interface Specification / Electrical Characteristics

   OUTPUTS    MIN   TYP     MAX
   -------    ---   ---     ---
   Vo(-):   -13.2   -x-    -2.5    V      Negative output voltage range
   Vo(+):     8.0   -x-    13.2    V      Positive output voltage range
   Io:        -x-   -x-    10.0    ma     Output current

   INPUTS     MIN   TYP     MAX
   -------    ---   ---     ---
   Vi(+):     3.0   -x-    25.0    V      Positive input voltage range
   Vi(-):   -25.0   -x-     0.5    V      Negative input voltage range
   Vhys:      -x-   1.0     -x-    V      Input hysteresis voltage
   Ii:        0.3   -x-    10.0    ma     Input current

Unconnected inputs are interpreted the same as positive input voltages.


E / Explanation of I/O Connectors / Game Controller Interface Spec

The two 9-pin D-type connectors with pins (male) are used to
interface to four types of devices:

    1.  Mouse or trackball, 3 buttons max.
    2.  Digital joystick, 2 buttons max.
    3.  Proportional (pot or proportional joystick), 2 buttons max.
    4.  Light pen, including pen-pressed-to-screen button.

The connector pin assignments are discussed in sections organized
by similar hardware and/or software operating requirements as shown
in the previous list.  Signal names follow those used elsewhere
in this appendix, when possible.

    J11 is the right controller port connector ( JOY1DAT , POT1DAT ).
    J12 is the left controller port connector ( JOY0DAT , POT0DAT ).

   NOTE:
   -----
   While most of the hardware discussed below is directly accessible,
   hardware should be accessed through ROM kernel software. This will
   keep future hardware changes transparent to the user.

 Mouse/Trackball        Proportional Controllers
 Digital Joysticks      Light Pen
 Fire Buttons


E / / Game Controller Interface Specification / Mouse/Trackball

A mouse or trackball is a device that translates planar motion into pulse
trains.  Quadrature techniques are employed to preserve the direction as
well as magnitude of displacement.  The registers  JOY0DAT and JOY1DAT
become counter registers, with y displacement in the high byte and x in
the low byte.  Movement causes the following action:

        Up:    y decrements
        Down:  y increments
        Right: x increments
        Left:  x decrements

To determine displacement,  JOYxDAT  is read twice with corresponding x and
y values subtracted (careful, modulo 128 arithmetic).  Note that if either
count changes by more than 127, both distance and direction become
ambiguous.  There is a relationship between the sampling interval and the
maximum speed (that is, change in distance) that can be resolved as
follows:

     Velocity < Distance(max) / SampleTime

     Velocity < SQRT(DeltaX**2 + DeltaY**2) / SampleTime

For an Amiga with a 200 count-per-inch mouse sampling during each vertical
blanking interval, the maximum velocity in either the X or Y direction
becomes:

    Velocity < (128 Counts * 1 inch/200 Counts) / .017 sec = 38 in/sec

which should be sufficient for most users.

   NOTE:
   -----
   The Amiga software is designed to do mouse update cycles during
   vertical blanking.  The horizontal and vertical counters are always
   valid and may be read at any time.

CONNECTOR PIN USAGE FOR MOUSE/TRACKBALL QUADRATURE INPUTS
---------------------------------------------------------

 PIN   MNEMONIC   DESCRIPTION                    HARDWARE REGISTER/NOTES
 ---   --------   -----------                    -----------------------
 1        V       Vertical pulses                JOY[0/1]DAT<15:8>
 2        H       Horizontal pulses              JOY[0/1]DAT(7:0>
 3        VQ      Vertical quadrature pulses     JOY[0/1]DAT<15:8>
 4        HQ      Horizontal quadrature pulses   JOY[0/1]DAT<7:0>
 5       UBUT*    Unused mouse button            See  Proportional Inputs .
 6       LBUT*    Left mouse button              See  Fire Button .
 7       +5V      +5V, current limited
 8      Ground
 9       RBUT*    Right mouse button             See  Proportional Inputs .


E / / Game Controller Interface Specification / Digital Joysticks

A joystick is a device with four normally opened switches arranged 90
degrees apart.  The  JOY[0/1]DAT  registers become encoded switch input
ports as follows:

        Forward:  bit#9 xor bit#8
        Left:     bit#9
        Back:     bit#1 xor bit#0
        Right:    bit#1

Data is encoded to facilitate the mouse/trackball operating mode.

   NOTE:
   -----
   The right and left direction inputs are also designed to be right and
   left buttons, respectively, for use with proportional inputs.  In
   this case, the forward and back inputs are not used, while right and
   left become button inputs rather than joystick inputs.

The  JOY[0/1]DAT  registers are always valid and may be read at any time.

CONNECTOR PIN USAGE FOR DIGITAL JOYSTICK INPUTS
-----------------------------------------------

   PIN   MNEMONIC   DESCRIPTION                 HARDWARE REGISTER/NOTES
   ---   --------   -----------                 -----------------------
   1      FORWARD*  Forward joystick switch     JOY[0/1]DAT<9 xor 8>
   2      BACK*     Back joystick switch        JOY[0/1]DAT(1 xor 0>
   3      LEFT*     Left joystick switch        JOY[0/1]DAT<9>
   4      RIGHT*    Right joystick switch       JOY[0/1]DAT<1>
   5      Unused
   6      FIRE*     Left mouse button           See  Fire Button .
   7      +5V       125ma max, 200ma surge      Total both ports.
   8      Ground
   9      Unused


E / / Game Controller Interface Specification / Fire Buttons

The fire buttons are normally opened switches routed to the 8520 adapter
PRA0 as follows:

        PRA0 bit 7 = Fire* left controller port
        PRA0 bit 6 = Fire* right controller port

Before reading this register, the corresponding bits of the data direction
register must be cleared to define input mode:

        DDRA0<7:6> cleared as appropriate

   NOTE:
   -----
   Do not disturb the settings of other bits in DDRA0 (Use of ROM kernel
   calls is recommended).

Fire buttons are always valid and may be read at any time.

CONNECTOR PIN USAGE FOR FIRE BUTTON INPUTS
------------------------------------------

   PIN   MNEMONIC   DESCRIPTION
   ---   --------   -----------
   1      -x-
   2      -x-
   3      -x-
   4      -x-
   5      -x-
   6      FIRE*     Left mouse button/fire button
   7      -x-
   8      ground
   9      -x-

            ___________                   ___________
   PORT 0  /           \         PORT 1  /           \
          |  o o o o o  |               |  o o o o o  |
           \  6        /                 \  6        /
            \ o o o o /                   \ o o o o /
             \|______/                     \|______/
   FIRE 0\
   _ _ _ _ _ _|                             |
  |                              FIRE 1\
         _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|
  | 7   |                                                   0
     ___v___________________________________________________
  | |       |       |                                       | PRA
    |FIRE 1\|FIRE 0\|                                       | $BFE001
  | |_______|___ ___|_______|_______|_______|_______|_______|
                ^
  |_ _ _ _ _ _ _|

     _______________________________________________________
    |       |       |                                       | Data
    |   0   |   0   |   0       0       0       0       0   | direction
    |_______|_______|_______|_______|_______|_______|_______| DDRA
                                                              $BFE201
        IN      IN     OUT     OUT     OUT     OUT     OUT

                 Figure E-1: Reading Fire Buttons


E / / Game Controller Interface Spec / Proportional Controllers

Resistive (potentiometer) element linear taper proportional controllers
are supported up to 528k Ohms max (470k +/- 10% recommended).  The
 JOY[0/1]DAT  registers contain digital translation values for y in the
high byte and x in the low byte. A higher count value indicates a higher
external resistance. The Amiga performs an integrating analog-to-digital
conversion as follows:

    1.  For the first 7 (NTSC) or 8 (PAL) horizontal display lines,
    the analog input capacitors are discharged and the positions
    counters reflected in the  POT[O/1]DAT  registers are held reset.

    For the remainder of the display field, the input capacitors are
    allowed to recharge through the resistive element in the external
    control device.

    2.  The gradually increasing voltage is continuously compared to
    an internal reference level while counter keeps track of the
    number of lines since the end of the reset interval.

    3.  When the input voltage finally exceeds the  internal threshold
    for a given input channel, the current counter value is latched
    into the  POT[O/1]DAT  register corresponding to that channel.

    4.  During the vertical blanking interval, the  software examines
    the resulting  POT[O/1]DAT  register values and interprets the
    counts in terms of joystick position.

   NOTE:
   -----
   The POTY and POTX inputs are designated as "right mouse button" and
   "unused mouse button" respectively.  An opened switch corresponds to
   high resistance, a closed switch to a low resistance.  The buttons
   are also available in  POTGO and POTGOR  registers.  It is recommended
   that ROM kernel calls be used for future hardware compatibility.

It is important to realize that the proportional controller is more of a
"pointing" device than an absolute position input.  It is up to the
software to provide the calibration, range limiting and averaging
functions needed to support the application's control requirements.

The  POT[0/1]DAT  registers are typically read during video blanking, but
MAY be available prior to that.

CONNECTOR PIN USAGE FOR PROPORTIONAL INPUTS
-------------------------------------------

   PIN  MNEMONIC  DESCRIPTION              HARDWARE REGISTER/NOTES
   ---  --------  -----------              -----------------------
   1    XBUT      Extra Button
   2    Unused
   3     LBUT*    Left button              See  Digital Joystick
   4     RBUT*    Right button             See  Digital Joystick
   5     POTX     X analog in              POT[0/1]DAT<7:0>, POTGO, POTGOR
   6    Unused
   7     +5V      125ma max, 200 ma surge
   8    Ground
   9     POTY     Y analog in              POT[0,1]DAT<15:8>, POTGO, POTGOR

               ___________
      PORT 0  /         5 \        POT0X
             |  o o o o o -|- - - - - - - -
              \        9  /  POT0Y         |
               \ o o o o-/- - - -
                \_______/        |         |
                             ____v____ ____v____
                            |         |         |
                            |  POT0Y  |  POT0X  | POT0DAT
                            | COUNTER | COUNTER | DFF012
                            |_________|_________|

               ___________
      PORT 1  /         5 \        POT1X
             |  o o o o o -|- - - - - - - -
              \        9  /  POT1Y         |
               \ o o o o-/- - - -
                \_______/        |         |
                             ____v____ ____v____
                            |         |         |
                            |  POT1Y  |  POT1X  | POT0DAT
                            | COUNTER | COUNTER | DFF014
                            |_________|_________|

                             _________________
                            |               | | POTGO
                            |_______________|_| DFF034

                             _________________
                            |                 | POTINP
                            |_________________| DFF016

                 Figure E-2: Pot Counters


E / / Game Controller Interface Specification / Light Pen

A light pen is an optoelectronic device whose light-sensitive portion is
placed in proximity to a CRT.  As the electron beam sweeps past the light
pen, a trigger pulse is generated which can be enabled to latch the
horizontal and vertical beam positions.  There is no hardware bit to
indicate this trigger, but this can be determined in the  two ways  as
shown in chapter 8, "Interface Hardware."

Light pen position is usually read during blanking, but MAY be available
prior to that.

CONNECTOR PIN USAGE FOR LIGHT PEN INPUTS
----------------------------------------

   PIN   MNEMONIC   DESCRIPTION              HARDWARE REGISTER/NOTES
   ---   --------   -----------              -----------------------
   1     Unused
   2     Unused
   3     Unused
   4     Unused
   5     LPENPR*    Light pen pressed        See  Proportional Inputs
   6     LPENTG*    Light pen trigger        VPOSR, VHPOSR
   7      +5V       125ma max, 200 ma surge  Both ports
   8     Ground
   9     Unused

   * Note: depending on the maker, the light pen input may be either.

             _____________________________
            |                             | VPOSR read only
            |                             | DFF004
            |_____________________________|

             _____________________________
            |                             | VHPOSR read only
            |                             | DFF006
            |_____________________________|

             _____________________________
            |                             | BPLCON0 write only
            |                      |      | DFF104
            |_|_|_|_|_|_|_|_|_|_|_|||_|_|_|

            15                     3     0
                                   ^
                                   |_ _ _ _ light pen enable

             _____________________________
            |                             | POTINP read only
            |                             | DFF104
            |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
                         ^
            15           |               0

                         | PEN PRESS = POT0X

                         |_ _ _ _ _ _ _ _
                                         |
                         ___________
                PORT 1  /         5 \    |
                       |  o o o o o -|- -
                        \  6        /
                         \ o o o o /
                          \|______/
               light
                pen _ _ _ _|

             _ _ _ _ _
                      |

                      |
                     _v_ _ _ latches V & H positions

                 Figure E-3: Light Pen


E / Explanation of Connectors / External Disk Interface Specification

The 23-pin D-type connector with sockets (DB23S) at the rear of the Amiga
is nominally used to interface to MFM devices.

 Pin Assignment (J7)
 Identification Mode
 Limitations


E / / External Disk Interface Specification / Pin Assignment (J7)

   PIN NAME    DIR   NOTES
   --- ----    ---   -----
   1   RDY*    I/O   If motor on, indicates disk installed and up to
                     speed.  If motor not on,  identification mode . See
                     below.
   2   DKRD*    I    MFM input data to Amiga.
   3   GND
   4   GND
   5   GND
   6   GND
   7   GND
   8   MTRXD*   OC   Motor on data, clocked into drive's motor-on
                     flip-flop by the active transition of SELxB*.
                     Guaranteed setup time is 1.4 usec.
                     Guaranteed hold time is 1.4 usec.
   9   SEL2B*   OC   Select drive 2.*
   10  DRESB*   OC   Amiga system reset.  Drives should reset their
                     motor-on flip-flops and set their write-protect
                     flip-flops.
   11  CHNG*   I/O   Note: Nominally used as an open collector input.
                     Drive's change flop is set at power up or when no
                     disk is not installed.  Flop is reset when drive is
                     selected and the head stepped, but only if a disk
                     is installed.
   12  +5V           270 ma maximum; 410 ma surge
                     When below 3.75V, drives are required to reset their
                     motor-on flops, and set their write-protect flops.
   13  SIDEB*   O    Side 1 if active, side 0 if inactive
   14  WPRO*   I/O   Asserted by selected, write-protected disk.
   15  TK0*    I/O   Asserted by selected drive when read/write head
                     is positioned over track 0.
   16  DKWEB*   OC   Write gate (enable) to drive.
   17  DKWDB*   OC   MFM output data from Amiga.
   18  STEPB*   OC   Selected drive steps one cylinder in the direction
                     indicated by DIRB.
   19  DIRB     OC   Direction to step the head.  Inactive to step
                     towards center of disk (higher-numbered tracks).
   20  SEL3B*   OC   Select drive 3. *
   21  SEL1B*   OC   Select drive 1. *
   22  INDEX*  I/O   Index is a pulse generated once per disk revolution,
                     between the end and beginning of cylinders.  The
                     8520 can be programmed to conditionally generate a
                     level 6 interrupt to the 680x0 whenever the INDEX*
                     input goes active.
   23  +12V          160 ma maximum; 540 ma surge.

   * Note: the drive select lines are shifted as they pass through
           a string of daisy chained devices. Thus the signal that appears
           as drive 2 select at the first drive shows up as drive 1 select
           at the second drive and so on...


E / / External Disk Interface Specification / Identification Mode

An identification mode is provided for reading a 32-bit serial
identification data stream from an external device.  To initialize this
mode, the motor must be turned on, then off.  See pin 8,  MTRXD*  for a
discussion of how to turn the motor on and off.  The transition from motor
on to motor off reinitializes the serial shift register. After
initialization, the  SELxB*  signal should be left in the inactive state.
Now enter a loop where  SELxB*  is driven active, read serial input data
on  RDY*  (pin 1), and drive  SELxB*  inactive.  Repeat this loop a total
of 32 times to read in 32 bits of data.  The most significant bit is
received first.

DEFINED IDENTIFICATIONS
-----------------------

   $0000 0000 - no drive present.
   $FFFF FFFF - Amiga standard 3.25 diskette.
   $5555 5555 - 48 TPI double-density, double-sided.

As with other peripheral ID's, users should contact Amiga, Inc.
for ID assignment.

The serial input data is active low and must therefore be inverted
to be consistent with the above table.


E / / External Disk Interface Specification / Limitations

1.  The total cable length, including daisy chaining, must not exceed
    1 meter.
2.  A maximum of 3 external devices may reside on this interface,
    but specific implementations may support fewer external devices.
3.  Each device must provide a 1000-Ohm pull-up resistor on those
    outputs driven by an open-collector device on the Amiga
    (pins 8-10, 16-21).
4.  The system provides power for only the first external device in
    the daisy chains.


E I/O Connectors And Interfaces / Part 3 - Internal Connectors

 Internal Disk
 Internal Disk Power
 Internal SCSI Disk


E / Internal Connectors / Internal Disk

INTERNAL DISK ...34 PIN RIBBON  (J10)
-------------------------------------

   1   GND            18   DIRB
   2   CHNG*          19   GND
   3   GND            20   STEPB*
   4   MTR0D*(led)    21   GND
   5   GND            22   DKWDB*
   6   N.C.           23   GND
   7   GND            24   DKWEB*
   8   INDEX*         25   GND
   9   GND            26   TK0*
   10  SEL0B*         27   GND
   11  GND            28   WPRO*
   12  N.C.           29   GND
   13  GND            30   DKRD*
   14  N.C.           31   GND
   15  GND            32   SIDEB*
   16  MTR0D*         33   GND
   17  GND            34   RDY*


E / Internal Connectors / Internal Disk Power

INTERNAL DISK POWER ...4 PIN STRAIGHT  (J13)
--------------------------------------------

   1   +12  (some drives are +5 only)
   2   GND
   3   GND
   4   +5


E / Internal Connectors / Internal SCSI Disk

INTERNAL SCSI DISK ...50 PIN CONNECTOR (A3000 MOTHERBOARD)
------------------------------------------------

   2    DATA 0             26   TERMINATION POWER
   4    DATA 1             28   GROUND
   6    DATA 2             30   GROUND
   8    DATA 3             32   ATN*
   10   DATA 4             34   N.C.
   12   DATA 5             36   BSY
   14   DATA 6             38   ACK*
   16   DATA 7             40   RST*
   18   PARITY             42   MSG*
   20   GROUND             44   SEL*
   22   GROUND             46   C/D
   24   GROUND             48   REQ*
                           50   I/O

(ALL ODD-NUMBERED PINS, EXCEPT PIN 25, ARE CONNECTED TO GROUND. PIN 25 IS
OPEN)

See the ANSI standard SCSI (Small Computer Standard Interface)
Specification for more information.


E Connectors And Interfaces / Port Signal Assignments for 8520 CIAS

CIA-A Address BFEx01  data bits 7-0  (A12*) (int2)
--------------------------------------------------

   PA7..game port 1, pin 6 (fire button*)
   PA6..game port 0, pin 6 (fire button*)
   PA5.. RDY*      disk ready*
   PA4.. TK0*      disk track 00*
   PA3.. WPRO*     write protect*
   PA2.. CHNG*     disk change*
   PA1..LED*       led light (0=bright)/audio filter control (A500 & A2000)
   PA0..OVL        ROM/RAM overlay bit

   SP... KDAT      keyboard data
   CNT.. KCLK      keyboard clock
   PB7..P7         data 7
   PB6..P6         data 6
   PB5..P5         data 5     Centronics parallel interface
   PB4..P4         data 4          data
   PB3..P3         data 3
   PB2..P2         data 2
   PB1..P1         data 1
   PB0..P0  data 0

   PC... drdy*                Centronics control
   F.... ack*

CIA-B Address BFDx00  data bits 15-8   (A13*) (int6)
-----------------------------------------------------

   PA7..com line  DTR* , driven output
   PA6..com line  RTS* , driven output
   PA5..com line carrier detect*
   PA4..com line  CTS*
   PA3..com line  DSR*
   PA2.. SEL       Centronics control
   PA1.. POUT +--- paper out ------------+
   PA0.. BUSY | +--busy    -------------+ |
              | |                       | |
   SP... BUSY | +- commodore serial bus + |
   CNT.. POUT +----commodore serial bus --+

   PB7.. MTR*      motor
   PB6.. SEL3*     select external 3rd drive
   PB5.. SEL2*     select external 2nd drive
   PB4.. SEL1*     select external 1st drive
   PB3.. SEL0*     select internal drive
   PB2.. SIDE*     side select*
   PB1.. DIR       direction
   PB0.. STEP*     step*

   PC...not used
   F.... INDEX*    disk index pulse*


Amiga® Hardware Reference Manual: 6 Blitter Hardware

This chapter covers the operation of the Amiga's blitter, the high speed
line drawing and block movement component of the system. The discussion is
divided into three parts: blitter basics, blitter area fill mode, and
blitter line draw mode.  Some example blitter operations are listed at the
end of the chapter.

For information concerning the blitter hardware in the Enhanced Chip Set,
see  Appendix C .

 What is the Blitter?           Interrupt Flag
 Memory Layout                  Zero Flag
 DMA Channels                   Pipeline Register
 Function Generator             Line Mode
 Shifts and Masks               Blitter Speed
 Descending Mode                Blitter Operations and System DMA
 Copying Arbitrary Regions      Blitter Block Diagram
 Area Fill Mode                 Blitter Key Points
 Blitter Done Flag


6 Blitter Hardware / What is the Blitter?

The blitter is one of the two coprocessors in the Amiga.  Part of the
Agnus chip, it is used to copy rectangular blocks of memory around and to
draw lines.  When copying memory, it is approximately twice as fast as the
68000, able to move almost four megabytes per second.  It can draw lines
at almost a million pixels per second.

In block move mode, the blitter can perform any logical operation on up to
three source areas, it can  shift  up to two of the source areas by one to
fifteen bits, it can  fill  outlined shapes, and it can  mask  the first
and last words of each raster row.  In  line mode , any pattern can be
imposed on a line, or the line can be drawn such that only one pixel per
horizontal line is set.

The blitter can only access Chip memory -- that portion of memory
accessible by the display hardware.  Attempting to use the blitter to read
or write Fast or other non-Chip memory may result in destruction of the
contents of Chip memory.

A "blit" is a single operation of the blitter -- perhaps the drawing of a
line or movement of a block of memory.  A blit is performed by
initializing the blitter registers with appropriate values and then
starting the blitter by writing the  BLTSIZE  register. As the blitter is
an asynchronous coprocessor, the 680x0 CPU continues to run as the blit is
executing.


6 Blitter Hardware / Memory Layout

The blitter is a word blitter, not a bit blitter.  All data fetched,
modified, and written are in full 16-bit words.  Through careful
programming, the blitter can do many "bit" type operations.

The blitter is particularly well suited to graphics operations.  As an
example, a 320 by 200 screen set up to display 16 colors is organized as
four bitplanes of 8,000 bytes each.  Each bitplane consists of 200 rows of
40 bytes or 20 16-bit words.  (From here on, a "word" will mean a 16-bit
word.)


6 Blitter Hardware / DMA Channels

The blitter has four DMA channels -- three source channels, labeled A, B,
and C, and one destination channel, called D.  Each of these channels has
separate address pointer, modulo and data registers and an enable bit. Two
have  shift registers , and one has a first and last word  mask register .
All four share a single blit size register.

The address pointer registers are each composed of two words, named
BLTxPTH and BLTxPTL.  (Here and later, in referring to a register, any "x"
in the name should be replaced by the channel label, A, B, C, or D.) The
two words of each register are adjacent in the 68000 address space, with
the high address word first, so they can both be written with one 32-bit
write from the processor. The pointer registers should be written with an
address in bytes.  Because the blitter works only on words, the least
significant bit of the address is ignored.  Because only Chip memory is
accessible, some of the most significant bits will be ignored as well.  On
machines with 512 KB of Chip memory, the most significant 13 bits are
ignored.  On machines with more Chip memory, fewer bits will are ignored.
A valid, even, Chip memory address should always be written to these
registers.

   Set unused bits to zero.
   ------------------------
   Be sure to write zeros to all unused bits in the custom chip
   registers. These bits may be used by later versions of the custom
   chips.  Writing non-zero values to these bits may cause unexpected
   results on future machines.

Each of the DMA channels can be independently enabled or disabled.  The
enable bits are bits SRCA, SRCB, SRCC, and DEST in control register zero
( BLTCON0 ).

When disabled, no memory cycles will be executed for that channel and, for
a source channel, the constant value stored in the data register of that
channel will be used for each blitter cycle.  For this purpose, each of
the three source channels have preloadable data registers, called BLTxDAT.

Images in memory are usually stored in a linear fashion; each word of data
on a line is located at an address that is one greater than the word on
its left. i.e.  Each line is a "plus one" continuation of the previous
line.

                   __________________________________
                  |    |    |    |    |    |    |    |
                  | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
                  |____|____|____|____|____|____|____|
                  |    |    |    |    |    |    |    |
                  | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
                  |____|____|____|____|____|____|____|
                  |    |    |    |    |    |    |    |
                  | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
                  |____|____|____|____|____|____|____|
                  |    |    |    |    |    |    |    |
                  | 41 | 42 | 43 | 44 | 45 | 46 | 47 |
                  |____|____|____|____|____|____|____|
                  |    |    |    |    |    |    |    |
                  | 48 | 49 | 50 | 51 | 52 | 53 | 54 |
                  |____|____|____|____|____|____|____|
                  |    |    |    |    |    |    |    |
                  | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
                  |____|____|____|____|____|____|____|

               Figure 6-1: How Images are Stored in Memory

The map in Figure 6-1 represents a single bitplane (one bit of color) of
an image at word addresses 20 through 61. Each of these addresses accesses
one word (16 pixels) of a single bitplane. If this image required sixteen
colors, four bitplanes like this would be required in memory, and four
copy (move) operations would be required to completely move the image.

The blitter is very efficient at copying such blocks because it needs to
be told only the starting address (20), the destination address, and the
size of the block (height = 6, width = 7). It will then automatically move
the data, one word at a time, whenever the data bus is available. When the
transfer is complete, the blitter will signal the processor with a  flag
and an interrupt.

   NOTE:
   -----
   This copy (move) operation operates on memory and may or may not
   change the memory currently being used for display.

All data copy blits are performed as rectangles of words, with a given
width and height.  All four DMA channels use a single blit size register,
called BLTSIZE, used for both the width and height.  The width can take a
value of from 1 to 64 words (16 to 1024 bits).  The height can run from 1
to 1024 rows.  The width is stored in the least significant six bits of
the BLTSIZE register.  If a value of zero is stored, a width count of 64
words is used.  This is the only parameter in the blitter that is given in
words.  The height is stored in the upper ten bits of the BLTSIZE
register, with zero representing a height of 1024 rows.  Thus, the largest
blit possible with the current Amiga blitter is 1024 by 1024 pixels.
However,  shifting  and  masking  operations may require an extra word be
fetched for each raster scan line, making the maximum practical horizontal
width 1008 pixels.

   Blitter counting.
   -----------------
   To emphasize the above paragraph:  Blit width is in words with a
   zero representing 64 words.  Blit height is in lines with a zero
   representing 1024 lines.

The blitter also has facilities, called modulos, for accessing images
smaller than the entire bitplane.  Each of the four DMA channels has a
16-bit modulo register called BLTxMOD.  As each word is fetched (or
written) for an enabled channel, the address pointer register is
incremented by two (two bytes, or one word). After each row of the blit is
completed, the signed 16-bit modulo value for that DMA channel is added to
the address pointer.  (A row is defined by the width stored in BLTSIZE.)

   About blitter modulos.
   ----------------------
   The modulo values are in bytes, not words.  Since the blitter can
   only operate on words, the least significant bit is ignored.  The
   value is sign-extended to the full width of the address pointer
   registers.  Negative modulos can be useful in a variety of ways, such
   as repeating a row by setting the modulo to the negative of the width
   of the bitplane.

As an example, suppose we want to operate on a section of a full 320 by
200 pixel bitmap that started at row 13, byte 12 (where both are numbered
from zero) and the section is 10 bytes wide.  We would initialize the
pointer register to the address of the bitplane plus 40 bytes per row
times 13 rows, plus 12 bytes to get to the correct horizontal position. We
would set the width to 5 words (10 bytes). At the end of each row, we
would want to skip over 30 bytes to get to the beginning of the next row,
so we would use a modulo value of 30. In general, the width (in words)
times two plus the modulo value (in bytes) should equal the full width, in
bytes, of the bitplane containing the image.

These calculations are illustrated in Figure 6-1 which shows the required
values used in the blitter registers BLTxMOD and BLTxPTR (BLTxPTH and
BLTxPTL).

   About the blitter and ECS.
   --------------------------
   The blitter size and pointer registers have increased range under the
   Enhanced Chip Set (ECS). With the original version of the Amiga's
   custom chips, blits were limited to 1008 by 1024 pixels.  With the
   ECS version of the custom chips, up to  32K by 32K pixel blits  are
   possible.  Refer to Appendix C for more information on ECS and the
   blitter registers.

   <Mem_Addr> = Address (0,0)
         \
          \
           \              BYTE (COLUMN) NUMBER
            \
             \  0        10        20        30       39
              \ |         |         |         |        |
               +----------------------------------------+ - -
              0|········································|    |
              1|········································|
              2|········································|    |
              3|········································|
              4|········································|    |
              5|········································|
              6|········································|    |
              7|········································|
              8|········································|    |
              9|········································|
         ROW 10|········································|    |
      NUMBER 11|········································|
             12|········································|    |- - window
             13|············##########··················|         bitmap
             14|············##########··················|    |
             15|· skip left ##########··· skip right ···|
             16|<---------->##########<---------------->|    |
             17| = 12 bytes ##########··· = 18 bytes ···|
             18|············##########··················|    |
             19|·················\······················|
             20|··················\·····················|    |
              -|···················\····················|
              -|····················\···················|    |
              -|·····················\··················|
              -|······················\················|    |
               +-----------------------\------------\---+ - -
                                        \            \
                                         \            \
                                  image to manipulate  \
                                                        \
                                                      one byte
      BLTxPTR = <Mem_Addr> + (40*13) + 12
              = <Mem_Addr> + 532

      BLTxMOD = 12 + 18
              = 30 bytes

              Figure 6-2: BLTxPTR and BLTxMOD calculations

   NOTE:
   -----
   The blitter can be used to process linear rather than rectangular
   regions by setting the horizontal or vertical count in BLTSIZE to 1.

Because each DMA channel has its own modulo register, data can be moved
among bitplanes of different widths.  This is most useful when moving
small images into larger screen bitplanes.


6 Blitter Hardware / Function Generator

The blitter can combine the data from the three source  DMA channels  in
up to 256 different ways to generate the values stored by the destination
 DMA channel . These sources might be one bitplane from each of three
separate graphics images.  While each of these sources is a rectangular
region composed of many points, the same logic operation will be performed
on each point throughout the rectangular region.  Thus, for purposes of
defining the blitter logic operation it is only necessary to consider what
happens for all of the possible combinations of one bit from each of the
three sources.

There are eight possible combinations of values of the three bits, for
each of which we need to specify the corresponding destination bit as a
zero or one. This can be visualized with a standard truth table, as shown
below. We have listed the three source channels, and the possible values
for a single bit from each one.

         A       B       C       D  BLTCON0  position   Minterm
         -       -       -       - ------------------ ---------
                                                        ___
         0       0       0       ?         0            ABC
                                                        __
         0       0       1       ?         1            ABC
                                                        _ _
         0       1       0       ?         2            ABC
                                                        _
         0       1       1       ?         3            ABC
                                                         __
         1       0       0       ?         4            ABC
                                                         _
         1       0       1       ?         5            ABC
                                                          _
         1       1       0       ?         6            ABC

         1       1       1       ?         7            ABC

This information is collected in a standard format, the LF (Logic
Function) control byte in the  BLTCON0  register. This byte programs the
blitter to perform one of the 256 possible logic operations on three
sources for a given blit.

To calculate the LF control byte in  BLTCON0 , fill in the truth table
with desired values for D, and read the function value from the bottom of
the table up.

For example, if we wanted to set all bits in the destination where the
corresponding A source bit is 1 or the corresponding B source bit is 1, we
would fill in the last four entries of the truth table with 1 (because the
A bit is set) and the third, fourth, seven, and eight entries with 1
(because the B bit is set), and all others (the first and second) with 0,
because neither A nor B is set.  Then, we read the truth table from the
bottom up, reading 11111100, or $FC.

For another example, an LF control byte of $80 ( = 1000 0000 binary) turns
on bits only for those points of the D destination rectangle where the
corresponding bits of A, B, and C sources were all on (ABC = 1, bit 7 of
LF on). All other points in the rectangle, which correspond to other
combinations for A, B, and C, will be 0. This is because bits 6 through 0
of the LF control byte, which specify the D output for these situations,
are set to 0.

 Designing the LF Control Byte with Minterms
 Designing the LF Control Byte with Venn Diagrams


6 / Function Generator / Designing the LF Control Byte with Minterms

One approach to designing the LF control byte uses logic equations. Each
of the rows in the  truth table  corresponds to a "minterm", which is a
particular assignment of values to the A, B, and C bits.  For instance,
the first minterm is usually written:
     ___
     ABC

or "not A and not B and not C".  The last is written as ABC.

   Blitter logic.
   --------------
   Two terms that are adjacent are AND'ed, and two terms that are
   separated by "+" are OR'ed. AND has a higher precedence, so AB + BC
   is equal to (AB) + (BC).

Any function can be written as a sum of minterms.  If we wanted to
calculate the function where D is one when the A bit is set and the C bit
is clear, or when the B bit is set, we can write that as:
      _
     AC + B

or "A and not C or B".  Since "1 and A" is "A":
          _
     D = AC + B
             _
     D = A(1)C + (1)B(1)
                  _                  _
Since either A or A is true (1 = A + A), and similarly for B, and C; we
can expand the above equation further:
             _
     D = A(1)C + (1)B(1)
               _ _        _       _
     D = A(B + B)C + (A + A)B(C + C)
           _    __          _    _      _
     D = ABC + ABC + AB(C + C) + AB(C + C)
           _    __           _   _     _ _
     D = ABC + ABC + ABC + ABC + ABC + ABC

After eliminating duplicates, we end up with the five minterms:
      _         _    __         _     _ _
     AC + B = ABC + ABC + ABC + ABC + ABC

These correspond to  BLTCON0  bit positions of 6, 4, 7, 3, and 2,
according to our  truth table , which we would then set, and clear the
rest.

The wide range of logic operations allow some sophisticated graphics
techniques.  For instance, you can move the image of a car across some
pre-existing building images with a few blits. Producing this effect
requires predrawn images of the car, the buildings (or background), and a
car "mask" that contains bits set wherever the car image is not
transparent.  This mask can be visualized as the shadow of the car from a
light source at the same position as the viewer.

   About mask bitplanes.
   ---------------------
   The mask for the car need only be a single bitplane regardless of the
   depth of the background bitplane. This mask can be used in turn on
   each of the background bitplanes.

To animate the car, first save the background image where the car will be
placed. Next copy the car to its first location with another blit.  Your
image is now ready for display.  To create the next image, restore the old
background, save the next portion of the background where the car will be,
and redraw the car, using three separate blits. (This technique works best
with beam-synchronized blits or double buffering.)

To temporarily save the background, copy a rectangle of the background
(from the A channel, for instance) to some backup buffer (using the D
channel). In this case, the function we would use is "A", the standard
copy function.  From Table 6-1, we note that the corresponding LF code has
a value of $F0.

To draw the car, we might use the A  DMA channel  to fetch the car mask,
the B  DMA channel  to fetch the actual car data, the C DMA channel to
fetch the background, and the D DMA channel  to write out the new image.

   Warning:
   --------
   We must fetch the destination background before we write it, as only
   a portion of a destination word might need to be modified, and there
   is no way to do a write to only a portion of a word.

When blitting the car to the background we would want to use a function
that, whenever the car mask (fetched with  DMA channel  A) had a bit set,
we would pass through the car data from B, and whenever A did not have a
bit set, we would pass through the original background from C.  The
corresponding function, commonly referred to as the cookie-cut function,
      _
is AB+AC, which works out to an LF code value of $CA.

To restore the background and prepare for the next frame, we would copy
the information saved in the first step back, with the standard copy
function ($F0).

If you shift the data and the mask to a new location and repeat the above
three steps over and over, the car will appear to move across the
background (the buildings).

   NOTE:
   -----
   This may not be the most effective method of animation, depending on
   the application, but the cookie-cut function will appear often.

Table 6-1 lists some of the most common functions and their values, for
easy reference.

                Table 6-1: Table of Common Minterm Values

          Selected      BLTCON0             Selected      BLTCON0
          Equation      LF Code            Equation      LF Code
          --------      -------            --------      -------
          D = A           $F0              D =  AB         $C0
              _                                  _
          D = A           $0F              D =  AB         $30
                                                _
          D = B           $CC              D =  AB         $0C
              _                                 __
          D = B           $33              D =  AB         $03

          D = C           $AA              D =  BC         $88
              _                                  _
          D = C           $55              D =  BC         $44
                                                _
          D = AC          $A0              D =  BC         $22
               _                                __
          D = AC          $50              D =  AC         $11
              _                                     _
          D = AC          $0A              D =  A + B      $F3
              _                                 _   _
          D = AC          $05              D =  A + B      $3F
                                                    _
          D = A + B       $FC              D =  A + C      $F5
              _                                 _   _
          D = A + B       $CF              D =  A + C      $5F
                                                    _
          D = A + C       $FA              D =  B + C      $DD
              _                                 _   _
          D = A + C       $AF              D =  B + C      $77
                                                     _
          D = B + C       $EE              D =  AB + AC    $CA
              _
          D = B + C       $BB


6 / Function Generator / Designing LF Control Byte with Venn Diagrams

Another way to arrive at a particular function is through the use of Venn
diagrams:
                         ______  0 ______
                        /      \  /      \
                       /        \/        \
                      /         /\         \
                     /   A     /  \     B   \
                    |    -    |    |    -    |
                    |         |  6 |         |
                    |         |    |         |
                    |       4 |____| 2       |
                    |        /|    |\        |
                    |       / |  7 | \       |
                     \     /   \  /   \     /
                      \   /  5  \/  3  \   /
                       \ |      /\      | /
                        \|_____/  \_____|/
                         |              |
                         |       1      |
                         |              |
                         |              |
                          \            /
                           \     C    /
                            \    -   /
                             \______/

             Figure 6-3: Blitter Minterm Venn Diagram

1. To select a function D=A (that is, destination = A source only),
   select only the  minterms  that are totally enclosed by the A-circle in
   the Figure above.  This is the set of  minterms  7, 6, 5, and 4. When
   written as a set of 1s for the selected  minterms  and 0s for those not
   selected, the value becomes:

               Minterm Number      7 6 5 4 3 2 1 0
               Selected Minterms   1 1 1 1 0 0 0 0
                                  -----------------
                                        F   0       equals $F0

2. To select a function that is a combination of two sources, look for
   the  minterms  by both of the circles (their intersection).  For
   example, the combination AB (A "and" B) is represented by the area
   common to both the A and B circles, or  minterms  7 and 6.

               Minterm Numbers     7 6 5 4 3 2 1 0
               Selected Minterms   1 1 0 0 0 0 0 0
                                  -----------------
                                        C   0       equals $C0

3. To use a function that is the inverse, or "not", of one of the sources,
           _
   such as A,

   take all of the  minterms  not enclosed by
   the circle represented by A on the above Figure.  In this case, we
   have  minterms  0, 1, 2, and 3.

               Minterm Numbers     7 6 5 4 3 2 1 0
               Selected Minterms   0 0 0 0 1 1 1 1
                                  -----------------
                                        0   F       equals $0F

4. To combine  minterms , or "or" them,  "or" the values together. For
   example, the equation AB+BC becomes

               Minterm Numbers     7 6 5 4 3 2 1 0
               AB                  1 1 0 0 0 0 0 0
               BC                  1 0 0 0 1 0 0 0
              -------------------------------------
               AB+BC               1 1 0 0 1 0 0 0
                                        C   8       equals $C8


6 Blitter Hardware / Shifts and Masks

Up to now we have dealt with the blitter only in moving words of memory
around and combining them with logic operations.  This is sufficient for
 moving graphic images  around, so long as the images stay in the same
position relative to the beginning of a word.  If our car image has its
leftmost pixel on the second pixel from the left, we can easily draw it on
the screen in any position where the leftmost pixel also starts two pixels
from the beginning of some word.  But often we want to draw that car
shifted left or right by a few pixels. To this end, both the A and B
 DMA channels  have a barrel shifter that can shift an image between 0 and
15 bits.

This shifting operation is completely free; it requires no more time to
execute a blit with shifts than a blit without shifts, as opposed to
shifting with the 680x0.  The shift is normally towards the right. This
shifter allows movement of images on pixel boundaries, even though the
pixels are addressed 16 at a time by each word address of the bitplane
image.

So if the incoming data is shifted to the right, what is shifted in
from the left?  For the first word of the blit, zeros are shifted in; for
each subsequent word of the same blit, the data shifted out from the
previous word is shifted in.

The shift value for the A channel is set with bits 15 through 12 of
 BLTCON0 ; the B shift value is set with bits 15 through 12 of  BLTCON1 .
For most operations, the same value will be used for both shifts.  For
shifts of greater than fifteen bits, load the  address register pointer
of the destination with a higher address; a shift of 100 bits would
require the  destination pointer  to be advanced 100/16 or 6 words (12
bytes), and a right shift of the remaining 4 bits to be used.

As an example, let us say we are doing a blit that is three words wide,
two words high, and we are using a shift of 4 bits.  For simplicity, let
us assume we are doing a straight copy from A to D.  The first word that
will be written to D is the first word fetched from A, shifted right four
bits with zeros shifted in from the left.  The second word will be the
second word fetched from the A, shifted right, with the least significant
(rightmost) four bits of the first word shifted in. Next, we will write
the first word of the second row fetched from A, shifted four bits, with
the least significant four bits of the last word from the first row
shifted in. This would continue until the blit is finished.

On shifted blits, therefore, we only get zeros shifted in for the first
word of the first row. On all other rows the blitter will shift in the
bits that it shifted out of the previous row. For most graphics
applications, this is undesirable.  For this reason, the blitter has the
ability to mask the first and last word of each row coming through the A
 DMA channel .

Thus, it is possible to extract rectangular data from a source whose right
and left edges are between word boundaries. These two registers are called
BLTAFWM and BLTALWM, for blitter A channel first and last word masks.
When not in use, both should be initialized to all ones ($FFFF).

   A note about fonts.
   -------------------
   Text fonts on the Amiga are stored in a packed bitmap.  Individual
   characters from the font are extracted using the blitter, masking out
   unwanted bits.  The character may then be positioned to any pixel
   alignment by shifting it the appropriate amount.

These masks are "anded" with the source data, before any shifts are
applied. Only when there is a 1 bit in the first-word mask will that bit
of source A actually appear in the logic operation. The first word of each
row is anded with BLTAFWM, and the last word is "anded" with BLTALWM.  If
the width of the row is a single word, both masks are applied
simultaneously.

The masks are also useful for extracting a certain range of "columns" from
some bitplane.  Let us say we have, for example, a predrawn rectangle
containing text and graphics that is 23 pixels wide.  The leftmost edge is
the leftmost bit in its bitmap, and the bitmap is two words wide.  We wish
to render this rectangle starting at pixel position 5 into our 320 by 200
screen bitmap, without disturbing anything that lies outside of the
rectangle.

                 |<--------- two word source bitmap -------->|
                 |                                           |
                 |<--- extract a 32-bit image --->|          |
                 |                                |          |
                 |<--- 16-bit word -->|           |          |
                 |____________________|___________|__________|
                 |                                           |
    source       | 00000000  00000000     00000000  00000000 |
    DMA B        | 11111111  11111111     11111111  11111111 |
                 | 10101010  01010101     10101010  01010101 |
                 |___________________________________________|
                       |         |          |         |
                 Source is passed through mask when it is one,
                     outherwise the destination is copied.
                       |         |          |         |
                  _____v_________v____   ___v_________v______
                 |                    | |                    |
    mask on      | 11111111  11111111 | | 11111110  00000000 |
    DMA A        |  first word mask   | |  second word mask  |
                 |____________________| |____________________|
                       |         |          |  ||     |
                       |         |          |  |-     -
                  _____v_________v__________v__v_____________
    final        |                                           |
    destination  | 00000000  00000000     00000000  11111111 |
    DMA D        | 11111111  11111111     11111111  11111111 |
    (points to   | 10101010  01010101     10101010  11111111 |
    same address |___________________________________________|
    as DMA C)                                   ^   ^  ^   ^
                       -         -         -    |   |  |   | <-+
                  _____|_________|_________|____|___|__|___|_  |
    destination  |                                           | |
    before blit  | 00000000  00000000     00000000  00000000 | |
    DMA C        | 11111111  11111111     11111111  11111111 | |
    (to be       | 10101010  01010101     10101010  01010101 | |
    overwritten) |___________________________________________| |
                                                               |
                 Destination does not change where mask is 0 --+

                   Figure 6-4: Extracting a Range of Columns

To do this, we point the B  DMA channel  at the bitmap containing the
source image, and the D  DMA channel  at the screen bitmap. We use a shift
value of 5.  We also point the C  DMA channel  at the screen bitmap. We
use a blit width of 2 words. What we need is a simple copy operation,
except we wish to leave the first five bits of the first word, and the
last four bits (2 times 16, less 23, less 5) of the last word alone. The A
 DMA channel  comes to the rescue.  We preload the A  data register  with
$FFFF (all ones), and use a first word mask with the most significant five
bits set to zero ($07FF) and a last word mask with the least significant
four bits set to zero ($FFF0).  We do not enable the A  DMA channel , but
only the B, C, and D channels, since we want to use the A channel as a
simple row mask. We then wish to pass the B (source) data along wherever
the A channel is 1 (for a  minterm  of AB) and pass along the original
destination data (from the C channel) wherever A is 0
                    _
(for a  minterm  of AC),
                                               _
yielding our classic cookie-cut function of AB+AC, or $CA.

   About disabling.
   ----------------
   Even though the A channel is disabled, we use it in our logic
   function and preload the  data register .  Disabling a channel simply
   turns off the memory fetches for that channel; all other operations
   are still performed, only from a constant value stored in the
   channel's  data register .

An alternative but more subtle way of accomplishing the same thing is to
use an A shift of five, a first word mask of all ones, and a last word
mask with the rightmost nine bits set to zero.  All other registers remain
the same.

   Warning:
   --------
   Be sure to load the blitter immediate  data registers  only after
   setting the shift count in  BLTCON0/BLTCON1 , as loading the
    data registers  first will lead to unpredictable results. For instance,
   if the last person left BSHIFT to be "4", and I load BDATA with "1" and
   then change BSHIFT to "2", the resulting BDATA that is used is
   "1<<4", not "1<<2". The act of loading one of the  data registers
   "draws" the data through the machine and shifts it.


6 Blitter Hardware / Descending Mode

Our standard memory copy blit works fine if the source does not overlap
the destination.  If we want to move an image one row down (towards
increasing addresses), however, we run into a problem -- we overwrite the
second row before we get a chance to copy it!  The blitter has a special
mode of operation -- descending mode -- that solves this problem nicely.

Descending mode is turned on by setting bit one of  BLTCON1  (defined as
BLITREVERSE). If you use descending mode the address pointers will be
decremented by two (bytes) instead of incremented by two for each word
fetched.  In addition, the modulo values will be subtracted rather than
added.   Shifts  are then towards the left, rather than the right, the
first word  mask  masks the last word in a row (which is still the first
word fetched), and the last word  mask  masks the first word in a row.

Thus, for a standard memory copy, the only difference in blitter setup
(assuming no  shifting  or  masking ) is to initialize the
 address pointer registers  to point to the last word in a block, rather
than the first word.  The  modulo values ,  blit size , and all other
parameters should be set the same.

   NOTE:
   -----
   This differs from predecrement versus postincrement in the 680x0,
   where an address register would be initialized to point to the word
   after the last, rather than the last word.

Descending mode is also necessary for  area filling , which will be
covered in a later section.


6 Blitter Hardware / Copying Arbitrary Regions

One of the most common uses of the blitter is to move arbitrary rectangles
of data from one bitplane to another, or to different positions within a
bitplane. These rectangles are usually on arbitrary bit coordinates, so
 shifting  and  masking  are necessary. There are further complications.
It may take several readings and some experimentation before everything in
this section can be understood.

A source image that spans only two words may, when copied with certain
 shifts , span three words.  Our 23 pixel wide rectangle above, for
instance, when  shifted  12 bits, will span three words. Alternatively, an
image spanning three words may fit in two for certain  shifts .  Under all
such circumstances, the blit size should be set to the larger of the two
values, such that both source and destination will fit within the blit
size.  Proper  masking  should be applied to mask out unwanted data.

Some general guidelines for copying an arbitrary region are as follows.

1. Use the A  DMA channel , disabled, preloaded with all ones and the
   appropriate  mask  and  shift values , to mask the  cookie-cut  function.
   Use the B channel to fetch the source data, the C channel to fetch
   the destination data, and the D channel to write the destination
   data.  Use the  cookie-cut  function $CA.

2. If  shifting , always use ascending mode if bit shifting to the right,
   and use  descending mode  if bit shifting to the left.

   NOTE:
   -----
   These shifts are the shifts of the bit position of the leftmost edge
   within a word, rather than  absolute shifts , as explained previously.

3. If the source and destination overlap, use ascending mode if the
   destination has a lower memory address (is higher on the display) and
    descending mode  otherwise.

4. If the source spans more words than the destination, use the same
    shift  value for the A channel as for the source B channel and set the
   first and last word  masks  as if they were masking the B source data.

5. If the destination spans more words than the source, use a  shift
   value of zero for the A channel and set the first and last word  masks
   as if they were masking the destination D data.

6. If the source and destination span the same number of words, use the
   A channel to  mask  either the source, as in 4, or the destination, as
   in 5.

   Warning:
   --------
   Conditions 2 and 3 can be contradictory if, for instance, you are
   trying to move an image one pixel down and to the right.  In this
   case, we would want to use  descending mode  so our destination does
   not overwrite our source before we use the source, but we would want
   to use ascending mode for the right  shift .  In some situations, it is
   possible to get around general guideline 2 above with clever  masking .
   But occasionally just  masking  the first or last word may not be
   sufficient; it may be necessary to mask more than 16 bits on one or
   the other end. In such a case, a mask can be built in memory for a
   single raster row, and the A  DMA channel  enabled to explicitly fetch
   this mask. By setting the A modulo value to the negative of the width
   of the mask, the mask will be repeatedly fetched for each row.


6 Blitter Hardware / Area Fill Mode

In addition to copying data, the blitter can simultaneously perform a fill
operation during the copy.  The fill operation has only one restriction --
the area to fill must be defined first by drawing untextured lines with
only one bit set per horizontal row.  A special  line draw mode  is
available for this operation.  Use a standard copy blit (or any other
blit, as area fills take place after all  shifts ,  masks  and logical
combination of sources).   Descending mode  must be used. Set either the
inclusive-fill-enable bit (FILL_OR, or bit 3) or the exclusive-fill-enable
bit (FILL_XOR, or bit 4) in  BLTCON1 . The inclusive fill mode fills
between lines, leaving the lines intact. The exclusive fill mode fills
between lines, leaving the lines bordering the right edge of filled
regions but deleting the lines bordering the left edge. Exclusive fill
yields filled shapes one pixel narrower than the same pattern filled with
inclusive fill.

For instance, the pattern:

    00100100-00011000

filled with inclusive fill, yields:

    00111100-00011000

with exclusive fill, the result would be

    00011100-00001000

(Of course, fills are always done on full 16-bit words.)

There is another bit (FILL_CARRYIN or bit 3 in  BLTCON1 ) that forces the
area "outside" the lines be filled; for the above example, with inclusive
fill, the output would be

    11100111-11111111

with exclusive fill, the output would be

    11100011-11110111

             before                          after
     ______________________          ______________________
    |                      |        |                      |
    |                      |        |                      |
    |                      |        |                      |
    |   1   1      1   1   |        |   11111      11111   |
    |    1  1       1  1   |        |    1111       1111   |
    |     1 1        1 1   |        |     111        111   |
    |      11         11   |        |      11         11   |
    |     1 1        1 1   |        |     111        111   |
    |    1  1       1  1   |        |    1111       1111   |
    |   1   1      1   1   |        |   11111      11111   |
    |                      |        |                      |
    |                      |        |                      |
    |______________________|        |______________________|

           Figure 6-5: Use of the FCI Bit - Bit Is a 0

If the FCI bit is a 1 instead of a 0, the area outside the lines is filled
with 1s and the area inside the lines is left with 0s in between.

             before                          after
     ______________________          ______________________
    |                      |        |                      |
    |                      |        |                      |
    |                      |        |                      |
    |   1   1      1   1   |        | 111   1111111   11   |
    |    1  1       1  1   |        | 1111  11111111  11   |
    |     1 1        1 1   |        | 11111 111111111 11   |
    |      11         11   |        | 111111111111111111   |
    |     1 1        1 1   |        | 11111 111111111 11   |
    |    1  1       1  1   |        | 1111  11111111  11   |
    |   1   1      1   1   |        | 111   1111111   11   |
    |                      |        |                      |
    |                      |        |                      |
    |______________________|        |______________________|

           Figure 6-6: Use of the FCI Bit - Bit Is a 1

If you wish to produce very sharp, single-point vertices, exclusive-fill
enable must be used. Figure 6-7 shows how a single-point vertex is
produced using exclusive-fill enable.

             before                   after exclusive fill
     ______________________          ______________________
    |                      |        |                      |
    |                      |        |                      |
    |                      |        |                      |
    |   1   1      1   1   |        |    1111       1111   |
    |    1  1       1  1   |        |     111        111   |
    |     1 1        1 1   |        |      11         11   |
    |      11         11   |        |       1          1   |
    |     1 1        1 1   |        |      11         11   |
    |    1  1       1  1   |        |     111        111   |
    |   1   1      1   1   |        |    1111       1111   |
    |                      |        |                      |
    |                      |        |                      |
    |______________________|        |______________________|

             Figure 6-7: Single-Point Vertex Example

The blitter uses the fill carry-in bit as the starting fill state
beginning at the rightmost edge of each line.  For each "1" bit in the
source area, the blitter flips the fill state, either filling or not
filling the space with ones.  This continues for each line until the left
edge of the blit is reached, at which point the filling stops.


6 Blitter Hardware / Blitter Done Flag

When the  BLTSIZE  register is written the blit is started.  The processor
does not stop while the blitter is working, though; they can both work
concurrently, and this provides much of the speed evident in the Amiga.
This does require some amount of care when using the blitter.

A blitter done flag, also called the blitter busy flag, is provided as
DMAF_BLTDONE (bit 14) in  DMACONR .  This flag is set when a blit is in
progress.

   About the blitter done flag.
   ----------------------------
   If a blit has just been started but has been locked out of memory
   access because of, for instance, display fetches, this bit may not
   yet be set.  The processor, on the other hand, may be running
   completely uninhibited out of Fast memory or its internal cache, so
   it will continue to have memory cycles.

The solution is to read a chip memory or hardware register address with
the processor before testing the bit.  This can easily be done with the
sequence:

        btst.b  #DMAB_BLTDONE-8,DMACONR(a1)
        btst.b  #DMAB_BLTDONE-8,DMACONR(a1)

where a1 has been preloaded with the address of the hardware registers.
The first "test" of the blitter done bit may not return the correct
result, but the second will.

   NOTE:
   -----
   Starting with the Fat Agnus the blitter busy bit has been "fixed" to
   be set as soon as you write to  BLTSIZE  to start the blit, rather than
   when the blitter gets its first DMA cycle.  However, not all machines
   will use these newer chips, so it is best to rely on the above method
   of testing.

 Multitasking and the Blitter


6 / Blitter Done Flag / Multitasking and the Blitter

When a blit is in progress, none of the blitter registers should be
written.  For details on arbitration of blitter access in the system,
please refer to the ROM Kernel Manual.  In particular, read the discussion
about the OwnBlitter() and DisownBlitter() functions.  Even after the
blitter has been "owned", a blit may still be finishing up, so the blitter
 done flag  should be checked before using it even the first time.  Use of
the ROM kernel function WaitBlit() is recommended.

You should also check the blitter  done flag  before using results of a
blit.  The blit may not be finished, so the data may not be ready yet.
This can lead to difficult to find bugs, because a 68000 may be slow
enough for a blit to finish without checking the  done flag , while a
68020, perhaps running out of its cache, may be able to get at the data
before the blitter has finished writing it.

Let us say that we have a subroutine that displays a text box on top of
other imagery temporarily.  This subroutine might allocate a chunk of
memory to hold the original screen image while we are displaying our text
box, then draw the text box.  On exit, the subroutine might blit the
original imagery back and then free the allocated memory.  If the memory
is freed before the blitter  done flag  is checked, some other process
might allocate that memory and store new data into it before the blit is
finished, trashing the blitter source and, thus, the screen imagery being
restored.


6 Blitter Hardware / Interrupt Flag

The blitter also has an interrupt flag that is set whenever a blit
finishes.  This flag,  INTF_BLIT , can generate a 680x0 interrupt if
enabled. For more information on  interrupts , see Chapter 7: "System
Control Hardware."


6 Blitter Hardware / Zero Flag

A blitter zero flag is provided that can be tested to determine if the
logic operation selected has resulted in zero bits for all destination
bits, even if those destination bits are not written due to the D
 DMA channel  being disabled.  This feature is often useful for
 collision detection , by performing a logical "and" on two source images
to test for overlap. If the images do not overlap, the zero flag will stay
true.

The Zero flag is only valid after the blitter has completed its operation
and can be read from bit (13) DMAF_BLTNZERO of the  DMACONR  register.


6 Blitter Hardware / Pipeline Register

The blitter performs many operations in each cycle --  shifting  and
 masking  source words, logical combination of sources, and  area fill
and zero detect on the output.  To enable so many things to take place so
quickly, the blitter is pipelined. This means that rather than performing
all of the above operations in one blitter cycle, the operations are
spread over two blitter cycles. (Here "cycle" is used very loosely for
simplicity.) To clarify this, the blitter can be imagined as two chips
connected in series. Every cycle, a new set of source operations come in,
and the first chip performs its operations on the data.  It then passes
the half-processed data to the second chip to be finished during the next
cycle, when the first chip will be busy at work on the next set of data.
Each set of data takes two "cycles" to get through the two chips,
overlapped so a set of data can be pumped through each cycle.

What all this means is that the first two sets of sources are fetched
before the first destination is written.  This allows you to  shift  a
bitmap up to one word to the right using ascending mode, for instance,
even though normally parts of the destination would be overwritten before
they were fetched.

    USE Code
       in        Active
    BLTCON0     Channels             Cycle Sequence
   ---------    --------             --------------
       F        A B C D     A0 B0 C0 -  A1 B1 C1 D0 A2 B2 C2 D1 D2
       E        A B C       A0 B0 C0 A1 B1 C1 A2 B2 C2
       D        A B   D     A0 B0 -  A1 B1 D0 A2 B2 D1 -  D2
       C        A B         A0 B0 -  A1 B1 -  A2 B2
       B        A   C D     A0 C0 -  A1 C1 D0 A2 C2 D1 -  D2
       A        A   C       A0 C0 A1 C1 A2 C2
       9        A     D     A0 -  A1 D0 A2 D1 -  D2
       8        A           A0 -  A1 -  A2
       7          B C D     B0 C0 -  -  B1 C1 D0 -  B2 C2 D1 -  D2
       6          B C       B0 C0 -  B1 C1 -  B2 C2
       5          B   D     B0 -  -  B1 D0 -  B2 D1 -  D2
       4          B         B0 -  -  B1 -  -  B2
       3            C D     C0 -  -  C1 D0 -  C2 D1 -  D2
       2            C       C0 -  C1 -  C2
       1              D     D0 -  D1 -  D2
       0         none       -  -  -  -

       Table 6-2: Typical Blitter Cycle Sequence

Here are a few caveats to keep in mind about Table 6-2.

*  No fill.
*  No competing bus activity.
*  Three-word blit.
*  Typical operation involves fetching all sources twice before the
   first destination becomes available. This is due to internal
   pipelining. Care must be taken with overlapping source and
   destination regions.

   Warning:
   --------
   This Table is only meant to be an illustration of the typical order
   of blitter cycles on the bus. Bus cycles are dynamically allocated
   based on blitter operating mode; competing bus activity from
   processor, bitplanes, and other  DMA channels ; and other factors.
   Amiga, Inc. does not guarantee the accuracy of or future
   adherence to this chart. We reserve the right to make product
   improvements or design changes in this area without notice.


6 Blitter Hardware / Line Mode

In addition to all of the functions described above, the blitter can draw
patterned lines.  The line draw mode is selected by setting bit 0
(LINEMODE) of  BLTCON1 , which changes the meaning of some other bits in
BLTCON0  and  BLTCON1 .  In line draw mode, the blitter can draw lines up
to 1024 pixels long, it can draw them in a variety of modes, with a
variety of textures, and can even draw them in a special way for simple
 area fill .

Many of the blitter registers serve other purposes in line-drawing mode.
Consult  Appendix A  for more detailed descriptions of the use of these
registers and control bits.  You should also see Appendix C for the
 new limits  on line-drawing mode in the Enhanced Chip Set (ECS).

In line mode, the blitter draws a line from one point to another, which
can be viewed as a vector.  The direction of the vector can lie in any of
the following eight octants.  (In the following diagram, the standard
Amiga convention is used, with x increasing towards the right and y
increasing down.) The number in parenthesis is the octant numbering; the
other number represents the value that should be placed in bits 4 through
2 of  BLTCON1 .

                               |
                               |
                      \   (2)  |  (1)   /
                       \       |       /
                        \   3  |  1   /
                         \     |     /
                          \    |    /
                     (3)   \   |   /   (0)
                            \  |  /
                        7    \ | /    6
                              \|/
                  -------------*-------------
                              /|\
                        5    / | \    4
                            /  |  \
                     (4)   /   |   \   (7)
                          /    |    \
                         /     |     \
                        /   2  |  0   \
                       /       |       \
                      /   (5)  |  (6)   \
                               |
                               |

              Figure 6-8: Octants for Line Drawing

Line drawing based on octants is a simplification that takes advantage of
symmetries between x and -x, y and -y. The following Table lists the
octant number and corresponding values:

      Table 6-3:  BLTCON1  Code Bits for Octant Line Drawing

                BLTCON1  Code Bits      Octant #
               -------------------       --------
                     4  3  2
                     -  -  -
                     1  1  0               0
                     0  0  1               1
                     0  1  1               2
                     1  1  1               3
                     1  0  1               4
                     0  1  0               5
                     0  0  0               6
                     1  0  0               7

We initialize  BLTCON1  bits 4 through 2 according to the above Table.
Now, we introduce the variables dx and dy and set them to the absolute
values of the difference between the x coordinates and the y coordinates
of the endpoints of the line, respectively.

dx = abs(x2 - x1) ;
dy = abs(y2 - y1) ;

Now, we rearrange them if necessary so dx is greater than dy.

if (dx < dy)
        {
        temp = dx ;
        dx = dy ;
        dy = temp ;
        }

Alternately, set dx and dy as follows:

dx = max(abs(x2 - x1), abs(y2 - y1)) ;
dy = min(abs(x2 - x1), abs(y2 - y1)) ;

These calculations have the effect of "normalizing" our line into octant
0; since we have already informed the blitter of the real octant to use,
it has no difficulty drawing the line.

We initialize the A  pointer register  to 4 * dy - 2 * dx. If this value
is negative, we set the sign bit (SIGNFLAG in  BLTCON1 ), otherwise we
clear it.  We set the A   modulo register  to 4 * (dy - dx) and the B
 modulo register  to 4 * dy.

The A  data register  should be preloaded with $8000. Both word  masks
should be set to $FFFF. The A  shift  value should be set to the x
coordinate of the first point (x1) modulo 15.

The B  data register  should be initialized with the line texture pattern,
if any, or $FFFF for a solid line. The B  shift  value should be set to
the bit number at which to start the line texture (zero means the last
significant bit.)

The C and D  pointer registers  should be initialized to the word
containing the first pixel of the line; the C and D  modulo registers
should be set to the width of the bitplane in bytes.

The SRCA, SRCC, and DEST bits of  BLTCON0  should be set to one, and the
SRCB flag should be set to zero.  The OVFLAG should be cleared. If only a
single bit per horizontal row is desired, the ONEDOT bit of  BLTCON1
should be set; otherwise it should be cleared.

The logic function remains.  The C  DMA channel  represents the original
source, the A channel the bit to set in the line, and the B channel the
pattern to draw.  Thus, to draw a line, the function
        _
   AB + A

is the most common.  To draw the line using exclusive-or mode, so it can
be easily erased by drawing it again, the function
     _   _
   ABC + AC

can be used.

We set the blit height to the length of the line, which is dx + 1. The
width must be set to two for all line drawing.  (Of course, the  BLTSIZE
register should not be written until the very end, when all other
registers have been filled.)

 Register Summary for Line Mode


6 / Line Mode / Register Summary for Line Mode

Preliminary setup:

   The line goes from (x1,y1) to (x2,y2).

   dx = max(abs(x2 - x1), abs(y2 - y1)) ;
   dy = min(abs(x2 - x1), abs(y2 - y1)) ;

Register setup:

   BLTADAT  = $8000
   BLTBDAT  = line texture pattern ($FFFF for a solid line)

   BLTAFWM  = $FFFF
   BLTALWM  = $FFFF

   BLTAMOD  = 4 * (dy - dx)
   BLTBMOD  = 4 * dy
   BLTCMOD  = width of the bitplane in bytes
   BLTDMOD  = width of the bitplane in bytes

   BLTAPT   = (4 * dy) - (2 * dx)
   BLTBPT   = unused
   BLTCPT   = word containing the first pixel of the line
   BLTDPT   = word containing the first pixel of the line

   BLTCON0  bits 15-12 = x1 modulo 15
   BLTCON0  bits SRCA, SRCC, and SRCD = 1
   BLTCON0  bit  SRCB = 0
            If exclusive-or line mode:                  _   _
                     then BLTCON0  LF control byte  = ABC + AC
                                                           _
                     else BLTCON0  LF control byte  = AB + AC

   BLTCON1  bit  LINEMODE  = 1
   BLTCON1  bit  OVFLAG  = 0
   BLTCON1  bits 4-2 =  octant number  from table
   BLTCON1  bits 15-12 = start bit for line texture (0 = last significant
            If (((4 * dy) - (2 * dx)) < 0):                bit)
                     then  BLTCON1  bit  SIGNFLAG  = 1
                     else  BLTCON1  bit  SIGNFLAG  = 0
            If one pixel/row:
                     then  BLTCON1  bit  ONEDOT  = 1
                     else  BLTCON1  bit  ONEDOT  = 0

   BLTSIZE  bits 15-6 = dx + 1
   BLTSIZE  bits  5-0 = 2

   Warning:
   --------
   You must set the  BLTSIZE  register last as it starts the blit.


6 Blitter Hardware / Blitter Speed

The speed of the blitter depends entirely on which  DMA channels  are
enabled.  You might be using a  DMA channel  as a constant, but unless it
is enabled, it does not count against you.  The minimum blitter cycle is
four ticks; the maximum is eight ticks.  Use of the A register is always
free. Use of the B register always adds two ticks to the blitter cycle.
Use of either C or D is free, but use of both adds another two ticks.
Thus, a copy cycle, using A and D, takes four clock ticks per cycle; a
copy cycle using B and D takes six ticks per cycle, and a generalized bit
copy using B, C, and D takes eight ticks per cycle. When in  line mode ,
each pixel takes eight ticks.

The system clock speed for NTSC Amigas is 7.16 megahertz (PAL Amigas 7.09
megahertz). The clock for the blitter is the system clock.  To calculate
the total time for the blit in microseconds, excluding setup and DMA
contention, you use the equation (for NTSC):

       n * H * W
   t = ---------
         7.16

For PAL:

       n * H * W
   t = ---------
         7.09

where t is the time in microseconds, n is the number of clocks per cycle,
and H and W are the height and width (in words) of the blit, respectively.

For instance, to copy one bitplane of a 320 by 200 screen to another
bitplane, we might choose to use the A and D channels.  This would require
four ticks per blitter cycle, for a total of

   4 * 200 * 20
   ------------ = 2235 microseconds.
       7.16

These timings do not take into account blitter setup time, which is the
time required to calculate and load the blitter registers and start the
blit.  They also ignore DMA contention.


6 Blitter Hardware / Blitter Operations and System DMA

The operations of the blitter affect the performance of the rest of the
system. The following sections explain how system performance is affected
by blitter direct memory access priority, DMA time slot allocation, bus
sharing between the 680x0 and the display hardware, the operations of the
blitter and Copper, and different playfield display sizes.

The blitter performs its various data-fetch, modify, and store operations
through DMA sequences, and it shares memory access with other devices in
the system. Each device that accesses memory has a priority level assigned
to it, which indicates its importance relative to other devices.

Disk DMA, audio DMA, display DMA, and sprite DMA all have the highest
priority level.  Display DMA has  priority  over sprite DMA under certain
circumstances.  Each of these four devices is allocated a group of time
slots during each horizontal scan of the video beam. If a device does not
request one of its allocated time slots, the slot is open for other uses.
These devices are given first priority because missed DMA cycles can cause
lost data, noise in the sound output, or on-screen interruptions.

The Copper has the next priority because it has to perform its operations
at the same time during each display frame to remain synchronized with the
display beam sweeping across the screen.

The lowest priorities are assigned to the blitter and the 68000, in that
order. The blitter is given the higher priority because it performs data
copying, modifying, and line drawing operations operations much faster
than the 68000.

During a horizontal scan line (about 63 microseconds), there are 227.5
"color clocks", or memory access cycles.  A memory cycle is approximately
280 ns in duration.  The total of 227.5 cycles per horizontal line
includes both display time and non-display time.  Of this total time, 226
cycles are available to be allocated to the various devices that need
memory access.

The time-slot allocation per horizontal line is:

      4 cycles for memory refresh
      3 cycles for disk DMA
      4 cycles for audio DMA (2 bytes per channel)
     16 cycles for sprite DMA (2 words per channel)
     80 cycles for bitplane DMA (even- or odd-numbered slots
          according to the display size used)

Figure 6-9 shows one complete horizontal scan line and how the clock
cycles are allocated.

     Figure 6-9: DMA Time Slot Allocation

The 68000 uses only the even-numbered memory access cycles. The 68000
spends about half of a complete processor instruction time doing internal
operations and the other half accessing memory. Therefore, the allocation
of alternate memory cycles to the 68000 makes it appear to the 68000 that
it has the memory all of the time, and it will run at full speed.

Some 68000 instructions do not match perfectly with the allocation of even
cycles and cause cycles to be missed. If cycles are missed, the 68000 must
wait until its next available memory slot before continuing. However, most
instructions do not cause cycles to be missed, so the 68000 runs at full
speed most of the time if there is no blitter DMA interference.

Figure 6-10 illustrates the normal cycle of the 68000.

   Avoid the TAS instruction.
   --------------------------
   The 68000 test-and-set instruction (TAS) should never be used in the
   Amiga; the indivisible read-modify-write cycle that is used only in
   this instruction will not fit into a DMA memory access slot.

      |                                                       |
      |<- - - - - - - - average 68000 cycle - - - - - - - - ->|
      |                                                       |
      |                                                       |
      |                           |                           |
      |<- - - - internal  - - - ->|<- - - - - memory  - - - ->|
      |         operation         |           access          |
      |         portion           |           portion         |
      |                           |                           |
      |                           |                           |
      |        odd cycle,         |         even cycle,       |
      |        assigned to        |         available to      |
      |        other devices      |         the 68000         |
      |                           |                           |
      |                           |                           |
      |                           |                           |
      |                           |                           |

                   Figure 6-10: Normal 68000 Cycle

If the display contains four or fewer low resolution bitplanes, the 68000
can be granted alternate memory cycles (if it is ready to ask for the
cycle and is the highest priority item at the time). However, if there are
more than four bitplanes, bitplane DMA will begin to steal cycles from the
68000 during the display.

During the display time for a six bitplane display (low resolution, 320
pixels wide), 160 time slots will be taken by bitplane DMA for each
horizontal line. As you can see from Figure 6-11, bitplane DMA steals 50
percent of the open slots that the processor might have used if there were
only four bitplanes displayed.

                          - timing cycle -
      T                                                     T + 7

      +               *               +               *
   _______________________________________________________________
  |       |       |       |       |       |       |       |       |
  |       |   4   |   6   |   2   |       |   3   |   5   |   1   |
  |_______|_______|_______|_______|_______|_______|_______|_______|

       Figure 6-11: Time Slots Used by a Six Bitplane Display

If you specify four high resolution bitplanes (640 pixels wide), bitplane
DMA needs all of the available memory time slots during the display time
just to fetch the 40 data words for each line of the four bitplanes
(40 * 4 = 160 time slots).  This effectively locks out the 68000 (as well
as the blitter or Copper) from any memory access during the display,
except during horizontal and  vertical blanking .

                          - timing cycle -
      T                                                     T + 7

   _______________________________________________________________
  |       |       |       |       |       |       |       |       |
  |   4   |   2   |   3   |   1   |   4   |   2   |   3   |   1   |
  |_______|_______|_______|_______|_______|_______|_______|_______|

      Figure 6-12: Time Slots Used by a High Resolution Display

Each horizontal line in a normal, full-sized display contains 320 pixels
in low resolution mode or 640 pixels in high resolution mode.  Thus,
either 20 or 40 words will be fetched during the horizontal line display
time. If you want to  scroll a playfield , one extra data word per line must
be fetched from the memory.

 Display size  is adjustable (see Chapter 3, "Playfield Hardware"), and
bitplane DMA takes precedence over sprite DMA.  As shown in  Figure 6-9
larger displays may block out one or more of the highest-numbered sprites,
especially with scrolling.

As mentioned above, the blitter normally has a higher priority than the
processor for DMA cycles.  There are certain cases, however, when the
blitter and the 68000 can share memory cycles. If given the chance, the
blitter would steal every available Chip memory cycle. Display, disk, and
audio DMA take precedence over the blitter, so it cannot block them from
bus access.  Depending on the setting of the blitter DMA mode bit,
commonly referred to as the "blitter-nasty" bit, the processor may be
blocked from bus access.  This bit is called DMAF_BLITHOG (bit 10) and is
in register  DMACON .

If DMAF_BLITHOG is a 1, the blitter will keep the bus for every available
Chip memory cycle.  This could potentially be every cycle (ROM and Fast
memory are not typically Chip memory cycles).

If DMAF_BLITHOG is a 0, the DMA manager will monitor the 68000 cycle
requests.  If the 68000 is unsatisfied for three consecutive memory
cycles, the blitter will release the bus for one cycle.


6 Blitter Hardware / Blitter Block Diagram

Figure 6-13 shows the basic building blocks for a single bit of a 16-bit
wide operation of the blitter.  It does not cover the line-drawing
hardware.

     Figure 6-13: Blitter Block Diagram

*  The upper left corner shows how the first-- and last-- word  masks  are
   applied to the incoming A-source data.  When the blit shrinks to one
   word wide, both  masks  are applied.

*  The shifter (upper right and center left) drawing illustrates how 16
   bits of data is taken from a specified position within a 32-bit
   register, based on the A  shift  or B  shift  values shown in  BLTCON0
   and  BLTCON1 .

*  The  minterm  generator (center right) illustrates how the  minterm
   select bits either allow or inhibit the use of a specific  minterm .

*  The drawing shows how the fill operation works on the data generated
   by the  minterm  combinations.  Fill operations can be performed
   simultaneously with other complex logic operations.

*  At the bottom, the drawing shows that data generated for the
   destination can be prevented from being written to a destination by
   using one of the blitter control bits.

*  Not shown on this diagram is the logic for zero detection, which
   looks at every bit generated for the destination.  If there are any
   1-bits generated, this logic indicates that the area of the blit
   contained at least one 1-bit (zero detect is false.)


6 Blitter Hardware / Blitter Key Points

This is a list of some key points that should be remembered when
programming the blitter.

*  Write  BLTSIZE  last; writing this register starts the blit.

*  Modulos and pointers are in bytes; width is in words and height is in
   pixels.  The least significant bit of all pointers and modulos is
   ignored.

*  The order of operations in the blitter is  masking ,  shifting , logical
   combination of sources,  area fill , and  zero flag  setting.

*  In ascending mode, the blitter increments the pointers, adds the
   modulos, and  shifts  to the right.

*  In  descending mode , the blitter decrements the pointers, subtracts
   the modulos, and shifts to the left.

*   Area fill  only works correctly in  descending mode .

*  Check  BLTDONE  before writing blitter registers or using the results
   of a blit.

*   Shifts  are done on immediate data as soon as it is loaded.

    ECS blitter .
   -------------
   For information relating to the blitter hardware in the Enhanced Chip
   Set, see  Appendix C .

 Example:  Clearmem
 Example:  Simpleline
 Example:  Rotatebits


Amiga® Hardware Reference Manual: F 8520 Complex Interface Adapters

This appendix contains information about the 8520 Complex Interface
Adapter (CIA) chips which handle the serial, parallel, keyboard and other
Amiga I/O activities. Each Amiga system contains two 8520 Complex
Interface Adapter (CIA) chips. Each chip has 16 general purpose
input/output pins, plus a serial shift register, three timers, an output
pulse pin and an edge detection input. In the Amiga system various tasks
are assigned to the chip's capabilities as follows:

CIAA Address Map
---------------------------------------------------------------------------
 Byte    Register                  Data bits
Address    Name     7     6     5     4     3     2     1    0
---------------------------------------------------------------------------
BFE001    pra     /FIR1 /FIR0  /RDY /TK0  /WPRO /CHNG /LED  OVL
BFE101    prb     Parallel port
BFE201    ddra    Direction for port A (BFE001);1=output (set to 0x03)
BFE301    ddrb    Direction for port B (BFE101);1=output (can be in or out)
BFE401    talo    CIAA timer A low byte (.715909 Mhz NTSC; .709379 Mhz PAL)
BFE501    tahi    CIAA timer A high byte
BFE601    tblo    CIAA timer B low byte (.715909 Mhz NTSC; .709379 Mhz PAL)
BFE701    tbhi    CIAA timer B high byte
BFE801    todlo   50/60 Hz event counter bits 7-0 (VSync or line tick)
BFE901    todmid  50/60 Hz event counter bits 15-8
BFEA01    todhi   50/60 Hz event counter bits 23-16
BFEB01            not used
BFEC01    sdr     CIAA serial data register (connected to keyboard)
BFED01    icr     CIAA interrupt control register
BFEE01    cra     CIAA control register A
BFEF01    crb     CIAA control register B

Note:  CIAA can generate interrupt INT2.

CIAB Address Map
---------------------------------------------------------------------------
 Byte     Register                   Data bits
Address     Name     7     6     5     4     3     2     1     0
---------------------------------------------------------------------------
BFD000    pra     /DTR  /RTS  /CD   /CTS  /DSR   SEL   POUT  BUSY
BFD100    prb     /MTR  /SEL3 /SEL2 /SEL1 /SEL0 /SIDE  DIR  /STEP
BFD200    ddra    Direction for Port A (BFD000);1 = output (set to 0xFF)
BFD300    ddrb    Direction for Port B (BFD100);1 = output (set to 0xFF)
BFD400    talo    CIAB timer A low byte (.715909 Mhz NTSC; .709379 Mhz PAL)
BFD500    tahi    CIAB timer A high byte
BFD600    tblo    CIAB timer B low byte (.715909 Mhz NTSC; .709379 Mhz PAL)
BFD700    tbhi    CIAB timer B high byte
BFD800    todlo   Horizontal sync event counter bits 7-0
BFD900    todmid  Horizontal sync event counter bits 15-8
BFDA00    todhi   Horizontal sync event counter bits 23-16
BFDB00            not used
BFDC00    sdr     CIAB serial data register (unused)
BFDD00    icr     CIAB interrupt control register
BFDE00    cra     CIAB Control register A
BFDF00    crb     CIAB Control register B

Note:  CIAB can generate INT6.

 Chip Register Map                    Interrupt Control Register (ICR)
 Register Functional Description      Control Registers
 Time of Day Clock                    Port Signal Assignments
 Serial Shift Register (SDR)          Hardware Connection Details


F 8520 Complex Interface Adapters / Chip Register Map

Each 8520 has 16 registers that you may read or write.  Here is the list
of registers and the access address of each within the memory space
dedicated to the 8520:

                       Register
   RS3  RS2  RS1  RS0  #(hex)  NAME      MEANING
   -----------------------------------------------------------------
    0    0    0    0     0     pra       Peripheral data register A
    0    0    0    1     1     prb       Peripheral data register B
    0    0    1    0     2     ddra      Data  direction register A
    0    0    1    1     3     ddrb      Direction register B
    0    1    0    0     4     talo      Timer A  low register
    0    1    0    1     5     tahi      Timer A  high register
    0    1    1    0     6     tblo      Timer B  low register
    0    1    1    1     7     tbhi      Timer B  high register
    1    0    0    0     8     todlow    Event LSB
    1    0    0    1     9     todmid    Event 8-15
    1    0    1    0     A     todhi     Event MSB
    1    0    1    1     B               No connect
    1    1    0    0     C     sdr       Serial data register
    1    1    0    1     D     icr       Interrupt control register
    1    1    1    0     E     cra       Control register A
    1    1    1    1     F     crb       Control register B
   -----------------------------------------------------------------


F 8520 Complex Interface Adapters / Register Functional Description

 I/O Ports (PRA, PRB, DDRA, DDRB)
 Handshaking
 Interval Timers (Timer A, Timer B)
 Input Modes
 Bit Names on Read-Register
 Bit Names on Write-Register


F / Register Functional Description / I/O Ports (PRA, PRB, DDRA, DDRB)

Ports A and B each consist of an 8-bit peripheral data register (PR) and
an 8-bit data direction register (DDR).  If a bit in the DDR is set to a
1, the corresponding bit position in the PR becomes an output.  If a DDR
bit is set to a 0, the corresponding PR bit is defined as an input.

When you READ a PR register, you read the actual current state of the I/O
pins (PA0-PA7, PB0-PB7, regardless of whether you have set them to be
inputs or outputs.

Ports A and B have passive pull-up devices as well as active pull-ups,
providing both CMOS and TTL compatibility.  Both ports have two TTL load
drive capability.

In addition to their normal I/O operations, ports PB6 and PB7 also provide
 timer  output functions.


F / Register Functional Description / Handshaking

Handshaking occurs on data transfers using the PC output pin and the FLAG
input pin.  PC will go low on the third cycle after a  port B  access.
This signal can be used to indicate "data ready" at  port B  or "data
accepted" from  port B . Handshaking on 16-bit data transfers (using both
 ports A and B ) is possible by always reading or writing  port A  first.
FLAG is a negative edge-sensitive input that can be used for receiving the
PC output from another 8520 or as a general- purpose interrupt input.  Any
negative transition on FLAG will set the FLAG interrupt bit.

        REG  NAME   D7   D6   D5   D4   D3   D2   D1   D0
        ---  ----   ---- ---- ---- ---- ---- ---- ---- ----
         0   PRA    PA7  PA6  PA5  PA4  PA3  PA2  PA1  PA0
         1   PRB    PB7  PB6  PB5  PB4  PB3  PB2  PB1  PB0
         2   DDRA   DPA7 DPA6 DPA5 DPA4 DPA3 DPA2 DPA1 DPA0
         3   DDRB   DPB7 DPB6 DPB5 DPB4 DPB3 DPB2 DPB1 DPB0


F / Register Functional Description / Interval Timers (Timer A, B)

Each interval timer consists of a 16-bit read-only timer counter and a
16-bit write-only timer latch.  Data written to the timer is latched into
the timer latch, while data read from the timer is the present contents of
the timer counter.

The latch is also called a prescalar in that it represents the countdown
value which must be counted before the timer reaches an underflow (no more
counts) condition.  This latch (prescalar) value is a divider of the input
clocking frequency. The timers can be used independently or linked for
extended operations.  Various timer operating modes allow generation of
long time delays, variable width pulses, pulse trains, and variable
frequency waveforms.  Utilizing the CNT input, the timers can count
external pulses or measure frequency, pulse width, and delay times of
external signals.

Each timer has an associated  control register , providing independent
control over each of the following functions:

 Start/Stop        One-shot/continuous
 PB on/off         Force load
 Toggle/pulse


F / / Interval Timers (Timer A, Timer B) / Start/Stop

A control bit (CRx0) allows the timer to be started or stopped by the
microprocessor at any time.


F / / Interval Timers (Timer A, Timer B) / PB on/off

A control bit (CRx1) allows the timer output to appear on a  port B
output line (PB6 for timer A and PB7 for timer B).  This function
overrides the  DDRB  control bit and forces the appropriate PB line to
become an output.


F / / Interval Timers (Timer A, Timer B) / Toggle/pulse

A control bit (CRx2) selects the output applied to  port B  while the PB
on/off bit is ON.  On every timer underflow, the output can either toggle
or generate a single positive pulse of one cycle duration.  The toggle
output is set high whenever the timer is started, and set low by  RES .


F / / Interval Timers (Timer A, Timer B) / One-shot/continuous

A control bit (CRx3) selects either timer mode.  In one-shot mode, the
timer will count down from the latched value to zero, generate an
interrupt, reload the latched value, then stop. In continuous mode, the
timer will count down from the latched value to zero, generate an
interrupt, reload the latched value, and repeat the procedure continuously.

In one-shot mode, a write to timer-high (register 5 for timer A, register
7 for Timer B) will transfer the timer latch to the counter and initiate
counting regardless of the start bit.


F / / Interval Timers (Timer A, Timer B) / Force load

A strobe bit (CRx4) allows the timer latch to be loaded into the timer
counter at any time, whether the timer is running or not.


F / Register Functional Description / Input Modes

Control bits (CRA5, CRB5-6) allow selection of the clock used to decrement
the timer.  Timer A  can count 02 clock pulses or external pulses applied
to the CNT pin.   Timer B  can count 02 pulses, external CNT pulses,
 timer A  underflow pulses, or  timer A  underflow pulses while the CNT
pin is held high.

The timer latch is loaded into the timer on any timer underflow, on a
force load, or following a write to the high byte of the pre- scalar while
the timer is stopped.  If the timer is running, a write to the high byte
will load the timer latch but not the counter.


F / Register Functional Description / Bit Names on Read-Register

        REG  NAME   D7   D6   D5   D4   D3   D2   D1   D0
        ---  ----   ---- ---- ---- ---- ---- ---- ---- ----
         4   TALO   TAL7 TAL6 TAL5 TAL4 TAL3 TAL2 TAL1 TAL0
         5   TAHI   TAH7 TAH6 TAH5 TAH4 TAH3 TAH2 TAH1 TAH0
         6   TBLO   TBL7 TBL6 TBL5 TBL4 TBL3 TBL2 TBL1 TBL0
         7   TBHI   TBH7 TBH6 TBH5 TBH4 TBH3 TBH2 TBH1 TBH0


F / Register Functional Description / Bit Names on Write-Register

        REG  NAME   D7   D6   D5   D4   D3   D2   D1   D0
        ---  ----   ---- ---- ---- ---- ---- ---- ---- ----
         4   TALO   PAL7 PAL6 PAL5 PAL4 PAL3 PAL2 PAL1 PAL0
         5   TAHI   PAH7 PAH6 PAH5 PAH4 PAH3 PAH2 PAH1 PAH0
         6   TBLO   PBL7 PBL6 PBL5 PBL4 PBL3 PBL2 PBL1 PBL0
         7   TBHI   PBH7 PBH6 PBH5 PBH4 PBH3 PBH2 PBH1 PBH0


F 8520 Complex Interface Adapters / Time of Day Clock

TOD consists of a 24-bit binary counter.  Positive edge transitions on
this pin cause the binary counter to increment.  The TOD pin has a passive
pull-up on it.

A programmable alarm is provided for generating an interrupt at a desired
time. The alarm registers are located at the same addresses as the
corresponding TOD registers.  Access to the alarm is governed by a
 control register  bit (CRB7).  The alarm is write-only; any read of a TOD
address will read time regardless of the state of the ALARM access bit.

A specific sequence of events must be followed for proper setting and
reading of TOD.  TOD is automatically stopped whenever a write to the
register occurs.  The clock will not start again until after a write to
the  LSB event  register.  This assures that TOD will always start at the
desired time.

Since a carry from one stage to the next can occur at any time with
respect to a read operation, a latching function is included to keep all
TOD information constant during a read sequence. All TOD registers latch
on a read of  MSB event  and remain latched until after a read of
 LSB event . The TOD clock continues to count when the output registers
are latched. If only one register is to be read, there is no carry problem
and the register can be read "on the fly" provided that any read of
 MSB event  is followed by a read of  LSB Event  to disable the latching.

 Bit Names for Write Time/Alarm or Read Time


F / Time of Day Clock / Bit Names for Write Time/Alarm or Read Time

        REG  NAME
        ---  ----
         8   LSB Event    E7   E6   E5   E4   E3   E2   E1   E0
         9   Event 8-15   E15  E14  E13  E12  E11  E10  E9   E8
         A   MSB Event    E23  E22  E21  E20  E19  E18  E17  E16

        WRITE
        CRB7 = 0
        CRB7 = 1 ALARM


F 8520 Complex Interface Adapters / Serial Shift Register (SDR)

The serial port is a buffered, 8-bit synchronous shift register. A control
bit (CRA6) selects input or output mode.  In the Amiga system one shift
register is used for the keyboard, and the other is unassigned.  Note that
the RS-232 compatible serial port is controlled by the  Paula chip ; see
chapter 8 for details.

 Input Mode
 Output Mode
 Bidirectional Feature


F / Serial Shift Register (SDR) / Input Mode

In input mode, data on the SP pin is shifted into the shift register on
the rising edge of the signal applied to the CNT pin. After eight CNT
pulses, the data in the shift register is dumped into the serial data
register and an interrupt is generated.


F / Serial Shift Register (SDR) / Output Mode

In the output mode,  Timer A  is used as the baud rate generator. Data is
shifted out on the SP pin at 1/2 the underflow rate of  Timer A .  The
maximum baud rate possible is 02 divided by 4, but the maximum usable baud
rate will be determined by line loading and the speed at which the
receiver responds to input data.

To begin transmission, you must first set up  Timer A  in continuous mode,
and start the timer.  Transmission will start following a write to the
serial data register.  The clock signal derived from  Timer A  appears as
an output on the CNT pin.  The data in the serial data register will be
loaded into the shift register, then shifted out to the SP pin when a CNT
pulse occurs.  Data shifted out becomes valid on the next falling edge of
CNT and remains valid until the next falling edge.

After eight CNT pulses, an interrupt is generated to indicate that more
data can be sent.  If the serial data register was reloaded with new
information prior to this interrupt, the new data will automatically be
loaded into the shift register and transmission will continue.

If no further data is to be transmitted after the eighth CNT pulse, CNT
will return high and SP will remain at the level of the last data bit
transmitted.

SDR data is shifted out MSB first.  Serial input data should appear in
this same format.


F / Serial Shift Register (SDR) / Bidirectional Feature

The bidirectional capability of the shift register and CNT clock allows
many 8520s to be connected to a common serial communications bus on
which one 8520 acts as a master, sourcing data and shift clock, while
all other 8520 chips act as slaves.     Both CNT and SP outputs are open
drain to allow such a common bus.  Protocol for master/slave selection
can be transmitted over the serial bus or via dedicated handshake lines.

        REG  NAME       D7   D6   D5   D4   D3   D2   D1   D0
        ---  ----       ---- ---- ---- ---- ---- ---- ---- ----
        C     SDR       S7   S6   S5   S4   S3   S2   S1   S0


F 8520 Complex Interface Adapters / Interrupt Control Register (ICR)

There are five sources of interrupts on the 8520:

   - Underflow from Timer A  (timer counts down past 0)
   - Underflow from Timer B
   - TOD alarm
   - Serial port full/empty
   - Flag

A single register provides masking and interrupt information.  The
interrupt control register consists of a write-only MASK register and a
read-only DATA register.  Any interrupt will set the corresponding bit in
the DATA register.  Any interrupt that is enabled by a 1-bit in that
position in the MASK will set the IR bit (MSB) of the DATA register and
bring the  IRQ  pin low.  In a multichip system, the IR bit can be polled to
detect which chip has generated an interrupt request.

When you read the DATA register, its contents are cleared (set to 0), and
the  IRQ  line returns to a high state.  Since it is cleared on a read, you
must assure that your interrupt polling or interrupt service code can
preserve and respond to all bits which may have been set in the DATA
register at the time it was read.  With proper preservation and response,
it is easily possible to intermix polled and direct interrupt service
methods.

You can set or clear one or more bits of the MASK register without
affecting the current state of any of the other bits in the register. This
is done by setting the appropriate state of the MSBit, which is called the
set/clear bit.  In bits 6-0, you yourself form a mask that specifies which
of the bits you wish to affect.  Then, using bit 7, you specify HOW the
bits in corresponding positions in the mask are to be affected.

*  If bit 7 is a 1, then any bit 6-0 in your own mask byte which is set
   to a 1 sets the corresponding bit in the MASK register.  Any bit that
   you have set to a 0 causes the MASK register bit to remain in its
   current state.

*  If bit 7 is a 0, then any bit 6-0 in your own mask byte which is set
   to a 1 clears the corresponding bit in the MASK register.  Again, any
   0 bit in your own mask byte causes no change in the contents of the
   corresponding MASK register bit.

If an interrupt is to occur based on a particular condition, then that
corresponding MASK bit must be a 1.

Example:  Suppose you want to set the  Timer A  interrupt bit (enable the
 Timer A  interrupt), but want to be sure that all other interrupts are
cleared.  Here is the sequence you can use:

        INCLUDE "hardware/cia.i"
        XREF    _ciaa                   ; From amiga.lib
        lea     _ciaa,a0                ; Defined in amiga.lib
        move.b  #%01111110,ciaicr(a0)

MSB is 0, means clear any bit whose value is 1 in the rest of the byte

        INCLUDE "hardware/cia.i"
        XREF    _ciaa                   ; From amiga.lib
        lea     _ciaa,a0                ; Defined in amiga.lib
        move.b  #%10000001,ciaicr(a0)

MSB is 1, means set any bit whose value is 1 in the rest of the byte (do
not change any values wherein the written value bit is a zero)

 Read Interrupt Control Register
 Write Interrupt Control Mask


F / Interrupt Control Register (ICR) / Read Interrupt Control Register

        REG  NAME       D7   D6   D5   D4   D3   D2   D1  D0
        ---  ----       ---- ---- ---- ---- ---- ---- --- ---
        D    ICR        IR    0    0   FLG  SP   ALRM TB  TA


F / Interrupt Control Register (ICR) / Write Interrupt Control Mask

        REG  NAME       D7   D6   D5   D4   D3   D2   D1  D0
        ---  ----       ---- ---- ---- ---- ---- ---- --- ---
        D     ICR       S/C   x    x   FLG  SP   ALRM TB  TA


F 8520 Complex Interface Adapters / Control Registers

There are two control registers in the 8520, CRA and CRB.  CRA is
associated with  Timer A  and CRB is associated with  Timer B .  The
format of the registers is as follows:

 Control Register A
 Bitmap of Register CRA
 Control Register B
 Bitmap of Register CRB


F / Control Registers / Control Register A

  BIT  NAME     FUNCTION
  ---  ----     --------
   0   START    1 = start Timer A, 0 = stop Timer A.
                    This bit is automatically reset (= 0) when
                    underflow occurs during one-shot mode.
   1   PBON     1 = Timer A output on PB6, 0 = PB6 is normal operation.
   2   OUTMODE  1 = toggle, 0 = pulse.
   3   RUNMODE  1 = one-shot mode, 0 = continuous mode.
   4   LOAD     1 = force load (this is a strobe input, there is no
                    data storage;  bit 4 will always read back a zero
                    and writing a 0 has no effect.)
   5   INMODE   1 = Timer A counts positive CNT transitions,
                0 = Timer A counts 02 pulses.
   6   SPMODE   1 = Serial port=output (CNT is the source of the shift
                    clock)
                0 = Serial port=input  (external shift clock is
                    required)
   7   UNUSED


F / Control Registers / Bitmap of Register CRA

REG# NAME UNUSED  SPMODE  INMODE  LOAD   RUNMODE  OUTMODE   PBON    START
---- ---- ------  ------  ------  ----   -------  -------   ----    -----
 E   CRA  unused  0=input  0=02  1=force  0=cont. 0=pulse  0=PB6OFF 0=stop
          unused  1=output 1=CNT   load   1=one-  1=toggle 1=PB6ON  1=start
                                 (strobe)   shot

                           |<--------  Timer  A Variables --------------->|

All unused register bits are unaffected by a write and forced to 0 on a
read.


F / Control Registers / Control Register B

   CONTROL REGISTER B:

  BIT  NAME     FUNCTION
  ---  ----     --------
   0   START    1 = start Timer B, 0 = stop Timer B.
                    This bit is automatically reset (= 0) when
                    underflow occurs during one-shot mode.
   1   PBON     1 = Timer B output on PB7, 0 = PB7 is normal
                    operation.
   2   OUTMODE  1 = toggle, 0 = pulse.
   3   RUNMODE  1 = one-shot mode, 0 = continuous mode.
   4   LOAD     1 = force load (this is a strobe input, there is no
                    data storage;  bit 4 will always read back a
                    zero and writing a 0 has no effect.)
  6,5  INMODE   Bits CRB6 and CRB5 select one of four possible
                input modes for Timer B, as follows:

                CRB6  CRB5   Mode Selected
                ----  ----   ---------------------------------------
                 0     0     Timer B counts 02 pulses
                 0     1     Timer B counts positive CNT transitions
                 1     0     Timer B counts Timer A underflow pulses
                 1     1     Timer B counts Timer A underflow pulses
                               while CNT pin is held high.

   7   ALARM     1 = writing to TOD registers sets Alarm
                 0 = writing to TOD registers sets TOD clock.
                     Reading TOD registers always reads TOD clock,
                     regardless of the state of the Alarm bit.


F / Control Registers / Bitmap Of Register CRB

REG# NAME ALARM    INMODE     LOAD      RUNMODE  OUTMODE  PBON    START
---- ---- -----    ------     ----      -------  -------  ----    -----
 F   CRB  0=TOD    00=02      1=force   0=cont.  0=pulse  0=PB7OFF 0=stop
          1=Alarm  01=CNT       load    1=one-   1=toggle 1=PB7ON  1=start
                   10=Timer A  (strobe)   shot
                   11=CNT+
                     Timer A

                   |<---------------  Timer B  Variables ------------>|

All unused register bits are unaffected by a write and forced to 0 on a
read.


F 8520 Complex Interface Adapters / Port Signal Assignments

This part specifies how various signals relate to the available ports of
the 8520.  This information enables the programmer to relate the port
addresses to the outside-world items (or internal control signals) which
are to be affected.  This part is primarily for the use of the systems
programmer and should generally not be used by applications programmers.
Systems software normally is configured to handle the setting of
particular signals, no matter how the physical connections may change.

   Warning:
   --------
   In a multitasking operating system, many different tasks may be
   competing for the use of the system resources.  Applications
   programmers should follow the established rules for resource access
   in order to assure compatibility of their software with the system.

CIA-A  Address BFEr01  data bits 7-0  (A12*) (INT2)

PA7..game port 1, pin 6 (fire button*)
PA6..game port 0, pin 6 (fire button*)
PA5.. RDY*      disk ready*
PA4.. TK0*      disk track 00*
PA3.. WPRO*     write protect*
PA2.. CHNG*     disk change*
PA1..LED*       led light (0=bright)
PA0..OVL        memory overlay bit
SP... KDAT      keyboard data
CNT.. KCLK      keyboard clock
PB7..P7         data 7
PB6..P6         data 6
PB5..P5         data 5     Centronics parallel interface
PB4..P4         data 4          data
PB3..P3         data 3
PB2..P2         data 2
PB1..P1         data 1
PB0..P0         data 0
PC... drdy*                Centronics control
F.... ack*

CIA-B  Address BFDr00  data bits 15-8   (A13*) (INT6)

PA7..com line  DTR* , driven output
PA6..com line  RTS* , driven output
PA5..com line carrier detect*
PA4..com line  CTS*
PA3..com line  DSR*
PA2.. SEL       centronics control
PA1.. POUT      paper out ---+
PA0.. BUSY      busy    ---+ |
                           | |
SP... BUSY      commodore -+ |
CNT.. POUT      commodore ---+

PB7.. MTR*      motor
PB6.. SEL3*     select external 3rd drive
PB5.. SEL2*     select external 2nd drive
PB4.. SEL1*     select external 1st drive
PB3.. SEL0*     select internal drive
PB2.. SIDE*     side select*
PB1.. DIR       direction
PB0.. STEP*     step*   (3.0 milliseconds minimum)

PC...not used
F.... INDEX*    disk index*

     8520_timing.asm


F 8520 Complex Interface Adapters / Hardware Connection Details

The system hardware selects the CIAs when the upper three address bits are
101.  Furthermore, CIAA is selected when A12 is low, A13 high; CIAB is
selected when A12 is high, A13 low.  CIAA communicates on data bits 7-0,
CIAB communicates on data bits 15-8.

Address bits A11, A10, A9, and A8 are used to specify which of the 16
internal registers you want to access.  This is indicated by "r" in the
address.  All other bits are don't cares.  So, CIAA is selected by the
following binary address:  101x xxxx xx01 rrrr xxxx xxx0. CIAB address:
101x xxxx xx10 rrrr xxxx xxx1

With future expansion in mind, we have decided on the following addresses:
CIAA = BFEr01; CIAB = BFDr00.  Software must use byte accesses to these
address, and no other.

 Interface Signals


F / Hardware Connection Details / Interface Signals

 Clock input                   DB7-DB0 - data bus inputs/outputs
 CS - chip-select input        IRQ - interrupt request output
 R/W - read/write input        RES - reset input
 RS3-RS0 - address inputs


F / / Interface Signals / Clock input

The 02 clock is a TTL compatible input used for internal device operation
and as a timing reference for communicating with the system data bus.  On
the Amiga, this is connected to the 680x0 "E" clock.  The "E" clock runs
at 1/10 of the CPU clock.  This works out to .715909 Mhz for NTSC or
.709379 Mhz for PAL.


F / / Interface Signals / CS - chip-select input

The CS input controls the activity of the 8520.  A low level on CS while
02 is high causes the device to respond to signals on the  R/W  and address
( RS ) lines.  A high on CS prevents these lines from controlling the 8520.
The CS line is normally activated (low) at 02 by the appropriate address
combination.


F / / Interface Signals / R/W - read/write input

The R/W signal is normally supplied by the microprocessor and controls the
direction of data transfers of the 8520.  A high on R/W indicates a read
(data transfer out of the 8520), while a low indicates a write (data
transfer into the 8520).


F / / Interface Signals / RS3-RS0 - address inputs

The address inputs select the internal registers as described by the
 register map


F / / Interface Signals / DB7-DB0 - data bus inputs/outputs

The eight data bus output pins transfer information between the 8520 and
the system data bus.  These pins are high impedance inputs unless  CS  is
low and  R/W  and 02 are high, to read the device.  During this read, the
data bus output buffers are enabled, driving the data from the selected
register onto the system data bus.


F / / Interface Signals / IRQ - interrupt request output

IRQ is an open drain output normally connected to the processor interrupt
input.  An external pull-up resistor holds the signal high, allowing
multiple IRQ outputs to be connected together.  The IRQ output is normally
off (high impedance) and is activated low as indicated in the functional
description.


F / / Interface Signals / RES - reset input

A low on the RES pin resets all internal registers.  The port pins are set
as inputs and port registers to zero (although a read of the ports will
return all highs because of passive pull-ups). The timer control registers
are set to zero and the timer latches to all ones.  All other registers
are reset to zero.


Amiga® Hardware Reference Manual: 7 System Control Hardware

This chapter covers the control hardware of the Amiga system, including
the following topics:

   *  How playfield priorities may be specified relative to the sprites
   *  How collisions between objects are sensed
   *  How system direct memory access (DMA) is controlled
   *  How interrupts are controlled and sensed
   *  How reset and early powerup are controlled

 Video Priorities             Interrupts
 Collision Detection          DMA Control
 Beam Position Detection      Reset and Early Startup Operation


7 System Control Hardware / Video Priorities

You can control the priorities of various objects on the screen to give
the illusion of three dimensions. The section below shows how playfield
priority may be changed relative to sprites.

 Fixed Sprite Priorities      Understanding Video Priorities
 How Sprites are Grouped      Setting the Priority Control Register


7 / Video Priorities / Fixed Sprite Priorities

You cannot change the relative priorities of the sprites. They will always
appear on the screen with the lower-numbered sprites appearing in front of
(having higher screen priority than) the higher-numbered sprites. This is
shown in Figure 7-1. Each box represents the image of the sprite number
shown in that box.
                                           _______
                                          |       |
                                       ___|___  7 |
                                      |       |___|
                                   ___|___  6 |
                                  |       |___|
                               ___|___  5 |
                              |       |___|
                           ___|___  4 |
                          |       |___|
                       ___|___  3 |
                      |       |___|
                   ___|___  2 |
                  |       |___|
               ___|___  1 |
              |       |___|
              |     0 |
              |_______|

            Figure 7-1: Inter-Sprite Fixed Priorities


7 / Video Priorities / How Sprites are Grouped

For playfield priority and collision purposes only, sprites are treated as
four groups of two sprites each. The groups of sprites are:

     Sprites 0 and 1
     Sprites 2 and 3
     Sprites 4 and 5
     Sprites 6 and 7


7 / Video Priorities / Understanding Video Priorities

The concept of video priorities is easy to understand if you imagine that
four fingers of one of your hands represent the four pairs of sprites and
two fingers of your other hand represent the two playfields. Just as you
cannot change the sequence of the four fingers on the one hand, neither
can you change the  relative priority  of the sprites. However, just as
you can intertwine the two fingers of one hand in many different ways
relative to the four fingers of the other hand, so can you position the
playfields in front of or behind the sprites. This is illustrated in
Figure 7-2.

     Figure 7-2: Analogy for Video Priority

Five possible positions can be chosen for each of the two "playfield
fingers." For example, you can place playfield 1 on top of sprites 0 and 1
(0), between sprites 0 and 1 and sprites 2 and 3 (1), between sprites 2
and 3 and sprites 4 and 5 (2), between sprites 4 and 5 and sprites 6 and 7
(3), or beneath sprites 6 and 7 (4). You have the same possibilities for
playfield 2.

The numbers 0 through 4 shown in parentheses in the preceding paragraph
are the actual values you use to select the playfield priority positions.
See next section  Setting the Priority Control Register .

You can also control the priority of playfield 2 relative to playfield 1.
This gives you additional choices for the way you can design the
 screen priorities .


7 / Video Priorities / Setting the Priority Control Register

This register lets you define how objects will pass in front of each other
or hide behind each other. Normally, playfield 1 appears in front of
playfield 2. The PF2PRI bit reverses this relationship, making playfield 2
more important. You control the video priorities by using the bits in
BPLCON2 (for "bitplane control register number 2") as shown in Table
7-1.

                  Table 7-1: Bits in BPLCON2

             Bit
            Number         Name           Function
            ------         ----           --------
             15-7                      Not used (keep at 0)

                6     PF2PRI           Playfield 2 priority

              5-3     PF2P2 - PF2P0    Playfield 2 placement with
                                       respect to the sprites

              2-0     PF1P2 - PF1P0    Playfield 1 placement with
                                       respect to the sprites

The binary values that you give to bits PF1P2-PF1P0 determine where
playfield 1 occurs in the priority chain as shown in Table 7-2. This
matches the description given in the previous section.

   Be careful:
   -----------
   PF2P2 - PF2P0, bits 5-3, are the priority bits for normal (non-dual)
   playfields.

  Table 7-2: Priority of Playfields Based on Values of Bits PF1P2-PF1P0

             Value                 Placement
             -----                 ---------
                    (from most important to least important)

              000     PF1     SP01    SP23    SP45    SP67
              001     SP01    PF1     SP23    SP45    SP67
              010     SP01    SP23    PF1     SP45    SP67
              011     SP01    SP23    SP45    PF1     SP67
              100     SP01    SP23    SP45    SP67    PF1

In this table, PF1 stands for playfield 1, and SP01 stands for the
 group of sprites  numbered 0 and 1. SP23 stands for sprites 2 and 3 as a
group; SP45 stands for sprites 4 and 5 as a group; and SP67 stands for
sprites 6 and 7 as a group.

Bits PF2P2-PF2P0 let you position playfield 2 among the sprite priorities
in exactly the same way. However, it is the PF2PRI bit that determines
which of the two playfields appears in front of the other on the screen.
Here is a sample of possible BPLCON2 register contents that would create
something a little unusual:

              BITS    15-7    PF2PRI  PF2P2-0 PF1P2-0
              VALUE     0s      1       010     000

This will result in a sprite/playfield priority placement of:

                PF1  SP01  SP23  PF2  SP45  SP67

In other words, where objects pass across each other, playfield 1 is in
front of sprite 0 or 1; and sprites 0 through 3 are in front of playfield
2. However, playfield 2 is in front of playfield 1 in any area where they
overlap and where playfield 2 is not blocked by sprites 0 through 3.

Figure 7-3 shows one use of sprite/playfield priority. The single sprite
object shown on the diagram is sprite 0. The sprite can "fly" across
playfield 2, but when it crosses playfield 1 the sprite disappears behind
that playfield. The result is an unusual video effect that causes the
object to disappear when it crosses an invisible boundary on the screen.

    +---------------------+    +---------------------+
    |#####################|    |                     |
    |#####################|    |                     |
    |#####################|    |      ·········      |
    |#####################|    |      ·········      |
    |####                 |    |·····················|         __
    |####                 |    |·····················|        /  \
    |####                 |    |·····················|     __/____\__
    |####                 |    |·····················|    |          |
    |####                 |    |·····················|    |__________|
    |####                 |    |·····················|       \    /
    |####                 |    |·····················|        \__/
    |####                 |    |·····················|
    |#####################|    |      ·········      |      Sprite 0
    |#####################|    |      ·········      |
    |#####################|    |                     |
    |#####################|    |                     |
    +---------------------+    +---------------------+

          Playfield 1                Playfield 2

    +---------------------+
    |#####################|
    |#####################|
    |######·········######|
    |######·-·-·-·-·######|- - - - -
    |···|·__··············|
    |····/  \·············|    When everything is displayed together.
    |···|____\__··········|    sprite 0 is more important than playfield 2
    |····       |·········|    but less important than playfield 1.
    |···|____ __|·········|    So even though you can't see the boundary,
    |····    /············|    the sprite disappears "behind" the
    |···|\__/·············|    invisible PF1 boundary.
    |·····················|
    |######·-·-·-·-·######|- - - - -
    |######·········######|
    |#####################|
    |#####################|
    +---------------------+

                  Figure 7-3: Sprite/Playfield Priority


7 System Control Hardware / Collision Detection

You can use the hardware to detect collisions between one  sprite group
and another  sprite group , any  sprite group  and either of the
playfields, the two playfields, or any combination of these items.

The first kind of collision is typically used in a game operation to
determine if a missile has collided with a moving player. The second kind
of collision is typically used to keep a moving object within specified
on-screen boundaries. The third kind of collision detection allows you to
define sections of playfield as individual objects, which you may move
using the blitter. This is called playfield animation. If one playfield is
defined as the backdrop or playing area and the other playfield is used to
define objects (in addition to the sprites), you can sense collisions
between the playfield-objects and the sprites or between the
playfield-objects and the other playfield.

 How Collisions are Determined
 How To Interpret the Collision Data
 How Collision Detection is Controlled


7 / Collision Detection / How Collisions are Determined

The video output is formed when the input data from all of the bitplanes
and the sprites is combined into a common data stream for the display. For
each of the pixel positions on the screen, the color of the highest
priority object is displayed. Collisions are detected when two or more
objects attempt to overlap in the same pixel position. This will set a bit
in the  collision data register .


7 / Collision Detection / How To Interpret the Collision Data

The collision data register, CLXDAT, is read-only, and its contents are
automatically cleared to 0 after it is read.  Its bits are as shown in
Table 7-3.

                Table 7-3: CLXDAT Bits

          Bit Number      Collisions Registered
          ----------      ---------------------
              15      not used
              14      Sprite 4 (or 5) to sprite 6 (or 7)
              13      Sprite 2 (or 3) to sprite 6 (or 7)
              12      Sprite 2 (or 3) to sprite 4 (or 5)
              11      Sprite 0 (or 1) to sprite 6 (or 7)
              10      Sprite 0 (or 1) to sprite 4 (or 5)
              9       Sprite 0 (or 1) to sprite 2 (or 3)
              8       Even bitplanes to sprite 6 (or 7)
              7       Even bitplanes to sprite 4 (or 5)
              6       Even bitplanes to sprite 2 (or 3)
              5       Even bitplanes to sprite 0 (or 1)
              4       Odd  bitplanes to sprite 6 (or 7)
              3       Odd  bitplanes to sprite 4 (or 5)
              2       Odd  bitplanes to sprite 2 (or 3)
              1       Odd  bitplanes to sprite 0 (or 1)
              0       Even bitplanes to odd bitplanes

   About odd-numbered sprites.
   ---------------------------
   The numbers in parentheses in Table 7-3 refer to collisions that will
   register only if you want them to show up. The
    collision control register  described below lets you either ignore or
   include the odd-numbered sprites in the collision detection.

Notice that in this table, collision detection does not change when you
select either single- or dual-playfield mode. Collision detection depends
only on the actual bits present in the odd-numbered or even-numbered
bitplanes. The  collision control register  specifies how to handle the
bitplanes during collision detect.


7 / Collision Detection / How Collision Detection is Controlled

The collision control register, CLXCON, contains the bits that define
certain characteristics of collision detection. Its bits are shown in
Table 7-4.

                  Table 7-4: CLXCON Bits

    Bit
   Number    Name      Function
   ------    ----      --------
     15      ENSP7     Enable sprite 7 (OR with sprite 6)
     14      ENSP5     Enable sprite 5 (OR with sprite 4)
     13      ENSP3     Enable sprite 3 (OR with sprite 2)
     12      ENSP1     Enable sprite 1 (OR with sprite 0)
     11      ENBP6     Enable bitplane 6 (match required for collision)
     10      ENBP5     Enable bitplane 5 (match required for collision)
     9       ENBP4     Enable bitplane 4 (match required for collision)
     8       ENBP3     Enable bitplane 3 (match required for collision)
     7       ENBP2     Enable bitplane 2 (match required for collision)
     6       ENBP1     Enable bitplane 1 (match required for collision)
     5       MVBP6     Match value for bitplane 6 collision
     4       MVBP5     Match value for bitplane 5 collision
     3       MVBP4     Match value for bitplane 4 collision
     2       MVBP3     Match value for bitplane 3 collision
     1       MVBP2     Match value for bitplane 2 collision
     0       MVBP1     Match value for bitplane 1 collision

Bits 15-12 let you specify that collisions with a sprite pair are to
include the odd-numbered sprite of a pair of sprites.  The even-numbered
sprites always are included in the collision detection. Bits 11-6 let you
specify whether to include or exclude specific bitplanes from the
collision detection. Bits 5-0 let you specify the polarity (true-false
condition) of bits that will cause a collision. For example, you may wish
to register collisions only when the object collides with "something
green" or "something blue." This feature, along with the collision enable
bits, allows you to  specify the exact bits, and their polarity, for the
collision to be registered.

   NOTE:
   -----
   This register is write-only. If all bitplanes are excluded
   (disabled), then a bitplane collision will always be detected.


7 System Control Hardware / Beam Position Detection

Sometimes you might want to synchronize the 680x0 processor to the video
beam that is creating the screen display. In some cases, you may also wish
to update a part of the display memory after the system has already
accessed the data from the memory for the display area.

The address for accessing the beam counter is provided so that you can
determine the value of the video beam counter and perform certain
operations based on the beam position.

   NOTE:
   -----
   The Copper is already capable of watching the display position
   for you and doing certain register-based operations automatically.
   Refer to the  Copper Interrupts  section and
    Chapter 2, Coprocessor Hardware  for further information.

In addition, when you are using a light pen, this same address is used to
read the  light pen position  rather than the beam position. This is
described fully in Chapter 8, "Interface Hardware."

 Using the Beam Position Counter


7 / Beam Position Detection / Using the Beam Position Counter

There are four addresses that access the beam position counter. Their
usage is described in Table 7-5.

          Table 7-5: Contents of the Beam Position Counter

  VPOSR   Read-only   Read the high bit of the vertical position (V8) and
                      the frame-type bit.

          Bit 15      LOF (Long-frame bit). Used to initialize interlaced
                      displays.

          Bits 14-1   Unused

          Bit 0       High bit of the vertical position (V8).  Allows PAL
                      line counts (313) to appear in PAL versions of the
                      Amiga.

  VHPOSR  Read-only   Read vertical and horizontal position of the counter
                      that is producing the beam on the screen (also
                      reads the light pen).

          Bits 15-8   Low bits of the vertical position, bits V7-V0

          Bits  7-0   The horizontal position, bits H8-H1.  Horizontal
                      resolution is 1/160th of the screen width.

  VPOSW   Write only  Bits same as VPOSR above.

  VHPOSW  Write only  Bits same as VHPOSR above.  Used for counter
                      synchronization with chip test patterns.

As usual, the address pairs VPOSR,VHPOSR and VPOSW,VHPOSW can be read from
and written to as long words, with the most significant addresses being
VPOSR and VPOSW.


7 System Control Hardware / Interrupts

This system supports the full range of 680x0 processor interrupts. The
various kinds of interrupts generated by the hardware are brought into the
peripherals chip and are translated into six of the seven available
interrupts of the 680x0.

 Nonmaskable Interrupt                       Interrupt Control Registers
 Maskable Interrupts                         Setting and Clearing Bits
 User Interface to the Interrupt System


7 / Interrupts / Nonmaskable Interrupt

Interrupt level 7 is the nonmaskable interrupt and is not generated
anywhere in the current system. The raw interrupt lines of the 680x0, IPL2
through IPL0, are brought out to the expansion connector and can be used
to generate this  level 7 interrupt  for debugging purposes.


7 / Interrupts / Maskable Interrupts

Interrupt levels 1 through 6  are generated. Control registers within the
peripherals chip allow you to mask certain of these sources and prevent
them from generating a 680x0 interrupt.


7 / Interrupts / User Interface to the Interrupt System

The system software has been designed to correctly handle all system
hardware interrupts at levels 1 through 6. A separate set of input
lines, designated INT2* and INT6* have been routed to the expansion
connector for use by external hardware for interrupts. These are known as
the external low- and external high-level interrupts.

These interrupt lines are connected to the peripherals chip and create
 interrupt levels 2 and 6 , respectively. It is recommended that you take
advantage of the interrupt handlers built into the operating system by
using these external interrupt lines rather than generating interrupts
directly on the processor interrupt lines.


7 / Interrupts / Interrupt Control Registers

There are two interrupt registers, interrupt enable (mask) and interrupt
request (status). Each register has both a read and a write address.  The
names of the interrupt addresses are:

    INTENA
      Interrupt0 enable (mask) - write only. Sets or clears specific
      bits of INTENA.

    INTENAR
      Interrupt enable (mask) read - read only. Reads contents of INTENA.

    INTREQ
      Interrupt request (status) - write only. Used by the processor
      to force a certain kind of interrupt to be processed (software
      interrupt). Also used to clear interrupt request flags once the
      interrupt process is completed.

    INTREQR
      Interrupt request (status) read - read only. Contains the bits
      that define which items are requesting interrupt service.

      The bit positions in the interrupt request register correspond
      directly to those same positions in the interrupt enable
      register. The only difference between the read-only and the
      write-only addresses shown above is that  bit 15  has no meaning
      in the read-only addresses.


7 / Interrupts / Setting and Clearing Bits

Below are the meanings of the bits in the interrupt control registers and
how you use them.

 Set and Clear                    Audio Interrupts
 Master Interrupt Enable          Blitter Interrupt
 External Interrupts              Disk Interrupt
 Vertical Blanking Interrupt      Serial Port Interrupts
 Copper Interrupt

     Figure 7-4: Interrupt Priorities


7 / / Setting and Clearing Bits / Set and Clear

The  interrupt registers , as well as the  DMA control register , use a
special way of selecting which of the bits are to be set or cleared. Bit
15 of these registers is called the SET/CLR bit.

When you wish to set a bit (make it a 1), you must place a 1 in the
position you want to set and a 1 into position 15.

When you wish to clear a bit (make it a 0), you must place a 1 in the
position you wish to clear and a 0 into position 15.

Positions 14-0 are bit selectors. You write a 1 to any one or more bits to
select that bit. At the same time you write a 1 or 0 to bit 15 to either
set or clear the bits you have selected. Positions 14-0 that have 0 value
will not be affected when you do the write. If you want to set some bits
and clear others, you will have to write this register twice (once for
setting some bits, once for clearing others).


7 / / Setting and Clearing Bits / Master Interrupt Enable

Bit 14 of the  interrupt registers  (INTEN) is for interrupt enable. This
is the master interrupt enable bit. If this bit is a 0, it disables all
other interrupts. You may wish to clear this bit to temporarily disable
all interrupts to do some critical processing task.

   Warning:
   --------
   This bit is used for enable/disable only. It creates no interrupt
   request.


7 / / Setting and Clearing Bits / External Interrupts

Bits 13 and 3 of the  interrupt registers  are reserved for external
interrupts.

Bit 13, EXTER, becomes a 1 when the system line called INT6* becomes a
logic 0. Bit 13 generates a  level 6 interrupt .

Bit 3, PORTS, becomes a 1 when the system line called INT2* becomes a
logic 0. Bit 3 causes a  level 2 interrupt .


7 / / Setting and Clearing Bits / Vertical Blanking Interrupt

Bit 5, VERTB, causes an interrupt at line 0 (start of vertical blank) of
the video display frame. The system is often required to perform many
different tasks during the vertical blanking interval. Among these tasks
are the updating of various pointer registers, rewriting lists of Copper
tasks when necessary, and other system-control operations.

The minimum time of vertical blanking is 20 horizontal scan lines for an
NTSC system and 25 horizontal scan lines for a PAL system. The range
starts at line 0 and ends at line 20 for NTSC or line 25 for PAL. After
the minimum vertical blanking range, you can control where the display
actually starts by using the  DIWSTRT  (display window start) register
to extend the effective vertical blanking time. See Chapter 3, "Playfield
Hardware," for more information on  DIWSTRT .

If you find that you still require additional time during vertical
blanking, you can use the Copper to create a  level 3 interrupt . This
Copper interrupt would be timed to occur just after the last line of
display on the screen (after the display window stop which you have
defined by using the  DIWSTOP  register).


7 / / Setting and Clearing Bits / Copper Interrupt

Bit 4, COPER, is used by the Copper to issue a  level 3 interrupt . The
Copper can change the content of any of the bits of this register, as it
can write any value into most of the machine registers. However, this bit
has been reserved for specifically identifying the Copper as the interrupt
source.

Generally, you use this bit when you want to sense that the display beam
has reached a specific position on the screen, and you wish to change
something in memory based on this occurrence.


7 / / Setting and Clearing Bits / Audio Interrupts

Bits 10 - 7, AUD3 - 0, are assigned to the audio channels. They are called
AUD3, AUD2, AUD1, and AUD0 and are assigned to channels 3, 2, 1, and 0,
respectively.

This  level 4 interrupt  signals "audio block done." When the audio DMA is
operating in  automatic mode , this interrupt occurs when the last word in
an audio data stream has been accessed. In  manual mode , it occurs when
the  audio data register  is ready to accept another word of data.

See Chapter 5, "Audio Hardware," for more information about
 interrupt generation and timing .


7 / / Setting and Clearing Bits / Blitter Interrupt

Bit 6, BLIT, signals "blitter finished." If this bit is a 1, it indicates
that the blitter has completed the requested data transfer. The blitter is
now ready to accept another task. This bit generates a  level 3 interrupt .


7 / / Setting and Clearing Bits / Disk Interrupt

Bits 12 and 1 of the  interrupt registers  are assigned to disk interrupts.

Bit 12, DSKSYN, indicates that the  sync register  matches disk data. This
bit generates a  level 5 interrupt .

Bit 1, DSKBLK, indicates "disk block finished." It is used to indicate
that the specified disk DMA task that you have requested has been
completed. This bit generates a  level 1 interrupt .

More information about disk data transfer and  interrupts  may be found
in Chapter 8, "Interface Hardware."


7 / / Setting and Clearing Bits / Serial Port Interrupts

The following serial interrupts are associated with the specified bits of
the  interrupt registers .

Bit 11, RBF (for receive buffer full), specifies that the input buffer of
the UART has data that is ready to read. This bit generates a
 level 5 interrupt .

Bit 0, TBE (for "transmit buffer empty"), specifies that the output
buffer of the UART needs more data and data can now be written into this
buffer. This bit generates a  level 1 interrupt .


7 / / Setting and Clearing Bits / Figure 7-4: Interrupt Priorities

               Exec
Hardware     Software
Priority     Priority     Description                  Name
--------     --------     -----------                  ----
           ____
          |     1         transmitter buffer empty     TBE
          |
   1 -----|     2         disk block complete          DSKBLK
          |
          |     3         software interrupt           SOFTINT
          |----
   2 -----|     4         external INT2 & CIAA         PORTS
          |----
          |     5         graphics coprocessor         COPER
          |
   3 -----|     6         vertical blank interval      VERTB
          |
          |     7         blitter finished             BLIT
          |----
          |     8         audio channel 2              AUD2
          |
          |     9         audio channel 0              AUD0
   4 -----|
          |     10        audio channel 3              AUD3
          |
          |     11        audio channel 1              AUD1
          |----
          |     12        receiver buffer full         RBF
   5 -----|
          |     13        disk sync pattern found      DSKSYNC
          |----
          |     14        external INT6 & CIAB         EXTER
   6 -----|
          |     15        special (master enable)      INTEN
          |----
   7 -----|____ --        non-maskable interrupt       NMI


7 System Control Hardware / DMA Control

Many different direct memory access (DMA) functions occur during system
operation. There is a read address as well as a write address to the DMA
control register so you can tell which DMA channels are enabled.

The address names for the DMA registers are as follows:

   DMACONR - Direct Memory Access Control - read-only.
   DMACON  - Direct Memory Access Control - write-only.

The contents of this register are shown in Table 7-6 (bit on if enabled).

   Bit
  Number     Name      Function
  ------     ----      --------
    15      SET/CLR    The set/reset control bit. See
                        description of bit 15 .

    14      BBUSY      Blitter busy status - read-only

    13      BZERO      Blitter zero status - read-only. Remains 1 if,
                       during a blitter operation, the blitter output
                       was always zero.

    12, 11             Unassigned

    10      BLTPRI     Blitter priority.  Also known as "blitter-nasty."
                       When this is a 1, the blitter has full (instead
                       of partial) priority over the 680x0.

    9       DMAEN      DMA enable.  This is a master DMA enable bit.
                       It enables the DMA for all of the channels at
                       bits 8-0.

    8       BPLEN      Bitplane DMA enable

    7       COPEN      Coprocessor DMA enable

    6       BLTEN      Blitter DMA enable

    5       SPREN      Sprite DMA enable

    4       DSKEN       Disk DMA enable

    3-0     AUDxEN     Audio DMA enable for channels 3-0 (x = 3 - 0).

            Table 7-6: Contents of DMA Control Register

For more information on using the DMA, see the following chapters:

   Copper     Chapter 2: Coprocessor Hardware
   Bitplanes  Chapter 3: Playfield Hardware
   Sprites    Chapter 4: Sprite Hardware
   Audio      Chapter 5: Audio Hardware
   Blitter    Chapter 6: Blitter Hardware
   Disk       Chapter 8: Interface Hardware

Processor Access To Chip Memory
-------------------------------
The Amiga chips access Chip memory directly via DMA, rather than utilizing
traditional bus arbitration mechanisms. Therefore, processor supplied
features for multiprocessor support, such as the 68000 TAS (test and set)
instruction, cannot serve their intended purpose and are not supported by
the Amiga architecture.


7 System Control Hardware / Reset and Early Startup Operation

When the Amiga is turned on or externally reset, the memory map is in a
special state.  An additional copy of the system ROM responds starting at
memory location $00000000.  The system RAM that would normally be located
at this address is not available.  On some Amiga models, portions of the
RAM still respond.  On other models, no RAM responds.  Software must
assume that memory is not available.  The OVL bit in one of the 8520 Chips
disables the overlay (See  Appendix F  for the bit location).

The Amiga System ROM contains an ID code as the first word.  The value of
the ID code may change in the future.  The second word of the ROM contains
a JMP instruction ($4ef9).  The next two words are used as the initial
program counter by the 680x0 processor.

The 68000 RESET instruction works much like external reset or power on.
All memory and AUTOCONFIG(TM) cards disappear, and the ROM image appears
at location $00000000.  The difference is that the CPU continues execution
with the next instruction.  Since RAM may not be available, special care
is needed to write reboot code that will reliably reboot all Amiga models.

     coldreboot.asm


Amiga® Hardware Reference Manual: G Keyboard Interface

This appendix contains the keyboard interface specification for A1000,
A500, A2000 and A3000.

The keyboard plugs into the Amiga computer via a cable with four
 primary connections .  The four wires provide 5-volt power, ground, and
signals called KCLK (keyboard clock) and KDAT (keyboard data).  KCLK is
unidirectional and always driven by the keyboard; KDAT is driven by both
the keyboard and the computer.  Both signals are open-collector; there are
pullup resistors in both the keyboard (inside the keyboard microprocessor)
and the computer.

 Keyboard Communications      Reset Warning
 Keycodes                     Hard Reset
 Caps Lock Key                Matrix Table
 Out-of-Sync Condition        Special Codes
 Power-Up Sequence


G Keyboard Interface / Keyboard Communications

The keyboard transmits 8-bit data words serially to the main unit. Before
the transmission starts, both KCLK and KDAT are high.  The keyboard starts
the transmission by putting out the first data bit (on KDAT), followed by
a pulse on KCLK (low then high); then it puts out the second data bit and
pulses KCLK until all eight data bits have been sent.  After the end of
the last KCLK pulse, the keyboard pulls KDAT high again.

When the computer has received the eighth bit, it must pulse KDAT low for
at least 1 (one) microsecond, as a handshake signal to the keyboard.  The
handshake detection on the keyboard end will typically use a hardware
latch.  The keyboard must be able to detect pulses greater than or equal
to 1 microsecond.  Software MUST pulse the line low for 85 microseconds to
ensure compatibility with all keyboard models.

All codes transmitted to the computer are rotated one bit before
transmission.  The transmitted order is therefore 6-5-4-3-2-1-0-7. The
reason for this is to transmit the  up/down flag  last, in order to cause
a key-up code to be transmitted in case the keyboard is forced to restore
 lost sync  (explained in more detail below).

The KDAT line is active low; that is, a high level (+5V) is interpreted as
0, and a low level (0V) is interpreted as 1.

             _____   ___   ___   ___   ___   ___   ___   ___   _________
        KCLK      \_/   \_/   \_/   \_/   \_/   \_/   \_/   \_/
             ___________________________________________________________
        KDAT    \_____X_____X_____X_____X_____X_____X_____X_____/
                  (6)   (5)   (4)   (3)   (2)   (1)   (0)   (7)

                 First                                     Last
                 sent                                      sent

The keyboard processor sets the KDAT line about 20 microseconds before it
pulls KCLK low.  KCLK stays low for about 20 microseconds, then goes high
again.  The processor waits another 20 microseconds before changing KDAT.

Therefore, the bit rate during transmission is about 60 microseconds per
bit, or 17 kbits/sec.


G Keyboard Interface / Keycodes

Each key has a keycode associated with it (see accompanying  table ).
Keycodes are always 7 bits long.  The eighth bit is a "key-up"/"key-down"
flag; a 0 (high level) means that the key was pushed down, and a 1 (low
level) means the key was released (the  Caps Lock key  is different -- see
below).

For example, here is a diagram of the "B" key being pushed down. The
keycode for "B" is $35 = 00110101; due to the rotation of the byte, the
bits transmitted are 01101010.

             _____   ___   ___   ___   ___   ___   ___   ___   _________
        KCLK      \_/   \_/   \_/   \_/   \_/   \_/   \_/   \_/
             _________             _____       _____       _____________
        KDAT          \___________/     \_____/     \_____/
                   0     1     1     0     1     0     1     0

In the next example, the B key is released.  The keycode is still $35,
except that bit 7 is set to indicate "key-up," resulting in a code of $B5
= 10110101.  After rotating, the transmission will be 01101011:

             _____   ___   ___   ___   ___   ___   ___   ___   _________
        KCLK      \_/   \_/   \_/   \_/   \_/   \_/   \_/   \_/
             _________             _____       _____             _______
        KDAT          \___________/     \_____/     \___________/
                   0     1     1     0     1     0     1     1


G Keyboard Interface / Caps Lock Key

This key is different from all the others in that it generates a keycode
only when it is pushed down, never when it is released. However, the
up/down bit is still used.  When pushing the Caps Lock key turns on the
Caps Lock LED, the up/down bit will be 0; when pushing Caps Lock shuts off
the LED, the up/down bit will be 1.


G Keyboard Interface / Out-of-Sync Condition

Noise or other glitches may cause the keyboard to get out of sync with the
computer.  This means that the keyboard is finished transmitting a code,
but the computer is somewhere in the middle of receiving it.

If this happens, the keyboard will not receive its handshake pulse at the
end of its transmission.  If the handshake pulse does not arrive within
143 ms of the last clock of the transmission, the keyboard will assume
that the computer is still waiting for the rest of the transmission and is
therefore out of sync.  The keyboard will then attempt to restore sync by
going into "resync mode."  In this mode, the keyboard clocks out a 1 and
waits for a handshake pulse. If none arrives within 143 ms, it clocks out
another 1 and waits again.  This process will continue until a handshake
pulse arrives.

Once sync is restored, the keyboard will have clocked a garbage character
into the computer.  That is why the  key-up/key-down flag  is always
transmitted last.  Since the keyboard clocks out 1's to restore sync, the
garbage character thus transmitted will appear as a key release, which is
less dangerous than a key hit.

Whenever the keyboard detects that it has lost sync, it will assume that
the computer failed to receive the keycode that it had been trying to
transmit.  Since the computer is unable to detect lost sync, it is the
keyboard's responsibility to inform the computer of the disaster.  It does
this by transmitting a "lost sync" code (value $F9 = 11111001) to the
computer. Then it retransmits the code that had been garbled.

   About Lost Sync.
   ----------------
   The only reason to transmit the "lost sync" code to the computer is
   to alert the software that something may be screwed up. The "lost
   sync" code does not help the recovery process, because the garbage
   key code can't be deleted, and the correct key code could simply be
   retransmitted without telling the computer that there was an error in
   the previous one.


G Keyboard Interface / Power-Up Sequence

There are two possible ways for the keyboard to be powered up under normal
circumstances: <1> the computer can be turned on with the keyboard plugged
in, or <2> the keyboard can be plugged into an already "on" computer.  The
keyboard and computer must handle either case without causing any upset.

The first thing the keyboard does on power-up is to perform a self-test.
This involves a ROM checksum test, simple RAM test, and watchdog timer
test.  Whenever the keyboard is powered up (or  restarted  -- see below), it
must not transmit anything until it has achieved synchronization with the
computer. The way it does this is by slowly  clocking out 1 bits , as
described above, until it receives a handshake pulse.

If the keyboard is plugged in before power-up, the keyboard may continue
this process for several minutes as the computer struggles to boot up and
get running.  The keyboard must continue clocking out 1s for however long
is necessary, until it receives its handshake.

If the keyboard is plugged in after power-up, no more than eight clocks
will be needed to achieve sync.  In this case, however, the computer may
be in any state imaginable but must not be adversely affected by the
 garbage character  it will receive.  Again, because it receives a key
release, the damage should be minimal.  The keyboard driver must
anticipate this happening and handle it, as should any application that
uses raw keycodes.

   Warning:
   --------
   The keyboard must not transmit a " lost sync " code after
   re-synchronizing due to a power-up or  restart ; only after
   re-synchronizing due to a handshake time-out.

Once the keyboard and computer are in sync, the keyboard must inform the
computer of the results of the self-test.  If the self-test failed for any
reason, a "selftest failed" code (value $FC = 11111100) is transmitted
(the keyboard does not wait for a handshake pulse after sending the
"selftest failed" code).  After this, the keyboard processor goes into a
loop in which it blinks the Caps Lock LED to inform the user of the
failure.  The blinks are coded as bursts of one, two, three, or four
blinks, approximately one burst per second:

     One blink        ROM checksum failure.
     Two blinks       RAM test failed.
     Three blinks     Watchdog timer test failed.
     Four blinks      A short exists between two row lines or one of
                          the seven special keys (not implemented).

If the self-test succeeds, then the keyboard will proceed to transmit any
keys that are currently down.  First, it sends an "initiate power-up key
stream" code (value $FD = 11111101), followed by the key codes of all
depressed keys (with keyup/down set to "down" for each key).  After all
keys are sent (usually there won't be any at all), a "terminate key
stream" code (value $FE = 11111110) is sent.  Finally, the Caps Lock LED
is shut off. This marks the end of the start-up sequence, and normal
processing commences.

The usual sequence of events will therefore be:  power-up; synchronize;
transmit "initiate power-up key stream" ($FD); transmit "terminate key
stream" ($FE).


G Keyboard Interface / Reset Warning

   About Reset Warning.
   -------------------
   This feature is available on some A1000 and A2000 keyboards. You
   cannot rely on this feature for all Amigas.

The keyboard has the additional task of resetting the computer on the
command of the user.  The user initiates Reset Warning by simultaneously
pressing the Ctrl key and the two Amiga keys.

The keyboard responds to this input by syncing up any pending transmit
operations.  The keyboard then sends a "reset warning" to the Amiga.  This
action alerts the Amiga software to finish up any pending operations (such
as disk DMA) and prepare for reset.

A specific sequence of operations ensure that the Amiga is in a state
where it can respond to the reset warning.  The keyboard sends two actual
"reset warning" keycodes.  The Amiga must handshake to the first code like
any normal keystroke, else the keyboard goes directly to  Hard Reset .  On
the second "reset warning" code the Amiga must drive KDAT low within 250
milliseconds, else the keyboard goes directly to  Hard Reset .  If all
the  tests  are passed, the Amiga has 10 full seconds to do emergency
processing.  When the Amiga pulls KDAT high again, the keyboard finally
asserts  hard reset .

If the Amiga fails to pull KDAT high within 10 seconds,  Hard Reset  is
asserted anyway.


G Keyboard Interface / Hard Reset

   About Hard Reset.
   -----------------
   Hard Reset happens after  Reset Warning . Valid for all keyboards
   except the Amiga 500.

The keyboard Hard Resets the Amiga by pulling KCLK low and starting a 500
millisecond timer.   When one or more of the keys is released and 500
milliseconds have passed, the keyboard will release KCLK. 500 milliseconds
is the minimum time KCLK must be held low.  The maximum KCLK time depends
on how long the user holds the three  reset keys  down.  Circuitry on the
Amiga motherboard detects the 500 millisecond KCLK pulse.

After releasing KCLK, the keyboard jumps to its start-up code (internal
RESET).  This will initialize the keyboard in the same way as cold
 power-on .

   NOTE:
   -----
   The keyboard must resend the " powerup key stream "!


G Keyboard Interface / Matrix Table

              Row 5   Row 4   Row 3   Row 2   Row 1   Row 0
   Column    (Bit 7) (Bit 6) (Bit 5) (Bit 4) (Bit 3) (Bit 2)
           +-------+-------+-------+-------+-------+-------+
     15    |(spare)|(spare)|(spare)|(spare)|(spare)|(spare)|
   (PD.7)  |       |       |       |       |       |       |
           | (0E)  | (1C)  | (2C)  | (47)  | (48)  | (49)  |
           +-------+-------+-------+-------+-------+-------+
     14    |   *   |<SHIFT>| CAPS  |  TAB  |   ~   |  ESC  |
   (PD.6)  |note 1 |note 2 | LOCK  |       |   `   |       |
           | (5D)  | (30)  | (62)  | (42)  | (00)  | (45)  |
           +-------+-------+-------+-------+-------+-------+
     13    |   +   |   Z   |   A   |   Q   |   !   |   (   |
   (PD.5)  |note 1 |       |       |       |   1   |note 1 |
           | (5E)  | (31)  | (20)  | (10)  | (01)  | (5A)  |
           +-------+-------+-------+-------+-------+-------+
     12    |  9    |   X   |   S   |   W   |   @   |  F1   |
   (PD.4)  |note 3 |       |       |       |   2   |       |
           | (3F)  | (32)  | (21)  | (11)  | (02)  | (50)  |
           +-------+-------+-------+-------+-------+-------+
     11    |  6    |   C   |   D   |   E   |   #   |  F2   |
   (PD.3)  |note 3 |       |       |       |   3   |       |
           | (2F)  | (33)  | (22)  | (12)  | (03)  | (51)  |
           +-------+-------+-------+-------+-------+-------+
     10    |  3    |   V   |   F   |   R   |   $   |  F3   |
   (PD.2)  |note 3 |       |       |       |   4   |       |
           | (1F)  | (34)  | (23)  | (13)  | (04)  | (52)  |
           +-------+-------+-------+-------+-------+-------+
      9    |  .    |   B   |   G   |   T   |   %   |  F4   |
   (PD.1)  |note 3 |       |       |       |   5   |       |
           | (3C)  | (35)  | (24)  | (14)  | (05)  | (53)  |
           +-------+-------+-------+-------+-------+-------+
      8    |  8    |   N   |   H   |   Y   |   ^   |  F5   |
   (PD.0)  |note 3 |       |       |       |   6   |       |
           | (3E)  | (36)  | (25)  | (15)  | (06)  | (54)  |
           +-------+-------+-------+-------+-------+-------+
      7    |  5    |   M   |   J   |   U   |   &   |   )   |
   (PC.7)  |note 3 |       |       |       |   7   |note 1 |
           | (2E)  | (37)  | (26)  | (16)  | (07)  | (5B)  |
           +-------+-------+-------+-------+-------+-------+
      6    |  2    |   <   |   K   |   I   |   *   |  F6   |
   (PC.6)  |note 3 |   ,   |       |       |   8   |       |
           | (1E)  | (38)  | (27)  | (17)  | (08)  | (55)  |
           +-------+-------+-------+-------+-------+-------+
      5    | ENTER |   >   |   L   |   O   |   (   |   /   |
   (PC.5)  |note 3 |   .   |       |       |   9   |note 1 |
           | (43)  | (39)  | (28)  | (18)  | (09)  | (5C)  |
           +-------+-------+-------+-------+-------+-------+
      4    |  7    |   ?   |   :   |   P   |   )   |  F7   |
   (PC.4)  |note 3 |   /   |   ;   |       |   0   |       |
           | (3D)  | (3A)  | (29)  | (19)  | (0A)  | (56)  |
           +-------+-------+-------+-------+-------+-------+
      3    |  4    |(spare)|   "   |   {   |   _   |  F8   |
   (PC.3)  |note 3 |       |   '   |   [   |   -   |       |
           | (2D)  | (3B)  | (2A)  | (1A)  | (0B)  | (57)  |
           +-------+-------+-------+-------+-------+-------+
      2    |  1    | SPACE | <RET> |   }   |   +   |  F9   |
   (PC.2)  |note 3 |  BAR  |note 2 |   ]   |   =   |       |
           | (1D)  | (40)  | (2B)  | (1B)  | (0C)  | (58)  |
           +-------+-------+-------+-------+-------+-------+
      1    |  0    | BACK  |  DEL  |RETURN |   |   |  F10  |
   (PC.1)  |note 3 | SPACE |       |       |   \   |       |
           | (0F)  | (41)  | (46)  | (44)  | (0D)  | (59)  |
           +-------+-------+-------+-------+-------+-------+
      0    |  -    | CURS  | CURS  | CURS  | CURS  | HELP  |
   (PC.0)  |note 3 | DOWN  | RIGHT | LEFT  |  UP   |       |
           | (4A)  | (4D)  | (4E)  | (4F)  | (4C)  | (5F)  |
           +-------+-------+-------+-------+-------+-------+

   note 1: A500, A2000 and A3000 keyboards only (numeric pad )
   note 2: International keyboards only (these keys are cutouts of the
           larger key on the US ASCII version.)  The key that generates
           $30 is cut out of the left Shift key.  Key $2B is cut out of
           return.  These keys are labeled with country-specific markings.
   note 3: Numeric pad.

The following table shows which keys are independently readable.  These
keys never generate ghosts or phantoms.

        (Bit 6) (Bit 5) (Bit 4) (Bit 3) (Bit 2) (Bit 1) (Bit 0)
       +-------+-------+-------+-------+-------+-------+-------+
       | LEFT  | LEFT  | LEFT  | CTRL  | RIGHT | RIGHT | RIGHT |
       | AMIGA | ALT   | SHIFT |       | AMIGA |  ALT  | SHIFT |
       | (66)  | (64)  | (60)  | (63)  | (67)  | (65)  | (61)  |
       +-------+-------+-------+-------+-------+-------+-------+


G Keyboard Interface / Special Codes

The special codes that the keyboard uses to communicate with the main unit
are summarized here.

   About the special codes.
   ------------------------
   The special codes are 8-bit numbers; there is no  up/down flag
   associated with them.  However, the  transmission bit order  is the
   same as previously described.

        Code       Name            Meaning
        --------------------------------------------------------------
        78       Reset warning .  Ctrl-Amiga-Amiga has been hit -
                computer will be reset in 10 seconds. (see text)
        F9      Last key code bad, next code is the same code
                   retransmitted (used when keyboard and main unit
                   get  out of sync ).
        FA      Keyboard output buffer overflow
        FB      Unused (was controller failure)
        FC      Keyboard  selftest failed
        FD      Initiate  power-up key stream  (keys pressed at powerup)
        FE      Terminate  power-up key stream
        FF      Unused (was interrupt)


Amiga® Hardware Reference Manual: 8 Interface Hardware

This chapter covers the interface hardware through which the Amiga talks
to the outside world, including the following features:

  * Two multiple purpose mouse/joystick/light pen control ports
  * Disk controller (for floppy disk drives & other MFM and GCR devices)
  * Keyboard
  * Centronics compatible parallel I/O interface (for printers)
  * RS232-C compatible serial interface (for external modems or other
      serial devices)
  * Video output connectors (RGB, monochrome, NTSC, RF modulator, video
      slot)

 Controller Port Interface      Serial I/O Interface
 Floppy Disk Controller         Parallel I/O Interface
 The Keyboard                   Display Output Connections


8 Interface Hardware / Controller Port Interface

Each Amiga has two  nine-pin connectors  that can be used for input or
output with a variety of controllers.  Usually, the  nine-pin connectors
are used with a mouse or joystick but they will also accept input from
light pens, paddles, trackballs, and other popular input devices.

Figure 8-1 shows one of the two connectors and the corresponding face-on
view of a standard controller plug, while table 8-1 gives the pin
assignments for some typical controllers.

     Figure 8-1: Controller Plug and Computer Connector

                  Table 8-1: Typical Controller Connections

                       Mouse,
                     Trackball,  Proportional      X-Y
                      Driving     Controller   Proportional
  Pin    Joystick    Controller     (Pair)       Joystick    Light Pen
  ---    --------    ----------  ------------  ------------  ---------
  1      Forward     V-pulse       ---           Button 3**  ---

  2      Back        H-pulse       ---           ---         ---

  3      Left        VQ-pulse      Left button   Button 1    ---

  4      Right       HQ-pulse      Right button  Button 2    ---

  5*     ---         Middle        Right POT     POT X       Pen pressed
                     button**                                to screen

  6*     Button 1    Left button   ---           ---         Beam trigger

  7      ---         +5V           +5V           +5V         +5V

  8      GND         GND           GND           GND         GND

  9*     Button 2**  Right button  Left POT      POT Y       Button 2**

                *  These pins may also be configured as outputs
                ** These buttons are optional

 Registers Used with the Controller Port
 Reading Mouse/Trackball Controllers
 Reading Digital Joystick Controllers
 Reading Proportional Controllers
 Reading a Light Pen
 Digital I/O on the Controller Port


8 / Controller Port Interface / Registers used with Controller Port

The Amiga chip registers that handle the  controller port  I/O are listed
below.

   JOY0DAT  ($DFF00A)  Counter for digital (mouse) input (port 1)
   JOY1DAT  ($DFF00C)  Counter for digital (mouse) input (port 2)
   CIAAPRA  ($BFE001)  Input and output for pin 6 (port 1 & 2 fire buttons)
   POT0DAT  ($DFF012)  Counter for proportional input (port 1)
   POT1DAT  ($DFF014)  Counter for proportional input (port 2)
   POTGO    ($DFF034)  Write proportional pin values and start counters
   POTGOR   ($DFF016)  Read proportional pin values
   BPLCON0  ($DFF100)  Bit 3  enables the light pen  latch
   VPOSR    ($DFF004)  Read  light pen position  (high order bits)
   VHPOSR   ($DFF006)  Read  light pen position  (low order bits)


8 / Controller Port Interface / Reading Mouse/Trackball Controllers

Pulses entering the mouse inputs are converted to separate horizontal and
vertical counts.  The 8 bit wide horizontal and vertical
 counter registers  can track mouse movement without processor
intervention.

The mouse uses quadrature inputs.  For each direction, a mechanical wheel
inside the mouse will produce two pulse trains, one 90 degrees out of
phase with the other (see Figure 8-2 for details).  The phase relationship
determines direction.

  Case 1: Count Up:
          ________            ________            ________            __
         /        \          /        \          /        \          /
  V  ___/          \________/          \________/          \________/
               ________            ________            ________
              /        \          /        \          /        \
  VQ ________/          \________/          \________/          \_______
          ___       ___       ___       ___       ___       ___       __
         /   \     /   \     / 1 \  0  /   \     /   \     /   \     /
  D0 ___/     \___/     \___/     \___/     \___/     \___/     \___/
     ________            ________            ________            _______
             \          /      1 \  0       /        \          /
  D1          \________/          \________/          \________/

  Case 2: Count Down:
          ________            ________            ________            __
         /        \          /        \          /        \          /
  V  ___/          \________/          \________/          \________/
     ________            ________            ________            _______
             \          /        \          /        \          /
  VQ          \________/          \________/          \________/
     ___       ___       ___       ___       ___       ___       ___
        \     /   \     /   \     /   \     /   \     /   \     /   \
  D0     \___/     \___/     \___/     \___/     \___/     \___/     \__
               ________            ________            ________
              /        \          /        \          /        \
  D1 ________/          \________/          \________/          \_______
          ___
             \
  D2          \___ etc           V    VQ   :   D1   D0
                                 ---------------------
                                 0    0    :    1    0
                                 0    1    :    0    1
                                 1    0    :    1    1
                                 1    1    :    0    0

                       Figure 8-2: Mouse Quadrature

The counters increment when the mouse is moved to the right or "down"
(toward you).

The counters decrement when the mouse is moved to the left or "up" (away
from you).

 Reading the Counters
 Counter Limitations
 Mouse Buttons


8 / / Reading Mouse/Trackball Controllers / Reading the Counters

The mouse/trackball counter contents can be accessed by reading register
addresses named  JOY0DAT and JOY1DAT .  These registers contain counts for
ports 1 and 2 respectively.

The contents of each of these 16-bit registers are as follows:

   Bits 15-8     Mouse/trackball vertical count
   Bits  7-0     Mouse/trackball horizontal count


8 / / Reading Mouse/Trackball Controllers / Counter Limitations

These  counters  will "wrap around" in either the positive or negative
direction. If you wish to use the mouse to control something that is
happening on the screen, you must read the  counters  at least once each
 vertical blanking  period and save the previous contents of the
registers. Then you can subtract from the previous readings to determine
direction of movement and speed.

The mouse produces about 200 count pulses per inch of movement in either a
horizontal or vertical direction.  Vertical blanking  happens once each
1/60th of a second. If you read the mouse once each  vertical blanking
period, you will most likely find a count difference (from the previous
count) of less than 127. Only if a user moves the mouse at a speed of more
than 38 inches per second will the  counter  values wrap.  Fast-action
games may need to read the mouse register twice per frame to prevent
 counter  overrun.

If you subtract the current count from the previous count, the absolute
value of the difference will represent the speed. The sign of the
difference (positive or negative) lets you determine which direction the
mouse is traveling.

The easiest way to calculate mouse velocity is with 8-bit signed
arithmetic. The new value of a  counter  minus the previous value will
represent the number of mouse counts since the last check. The example
shown in Table 8-2 presents an alternate method.  It treats both counts as
unsigned values, ranging from 0 to 255.  A count of 100 pulses is measured
in each case.

         Table 8-2: Determining the Direction of the Mouse

                Previous    Current
                 Count       Count     Direction
                --------    -------    ---------
                  200         100      Up (Left)
                  100         200     Down (Right)
                  200          45       Down *
                   45         200        Up **

   Notes for Table 8-2:

   *  Because 200-45 = 155, which is more than 127, the true count must
      be 255 - ( 200-45) = 100; the direction is down.

   ** 45 - 200 = -155.  Because the absolute value of -155 exceeds 127,
      the true count must be  255 + (-155) = 100; the direction is up.


8 / / Reading Mouse/Trackball Controllers / Mouse Buttons

There are two buttons on the standard Amiga mouse. However, the control
circuitry and software support up to three buttons.

   *  The left button on the Amiga mouse is connected to  CIAAPRA
      ($BFE001). Port 1 uses bit 6 and port 2 uses bit 7. A logic
      state of 1 means "switch open." A logic state of 0 means "switch
      closed." (See  Appendix F  for more information.)

   *  Button 2 (right button on Amiga mouse) is connected to pin 9 of
      the  controller ports , one of the proportional pins.  See
       Digital Input/Output on the Controller Port  for details.

   *  Button 3, when used, is connected to pin 5, the other
      proportional  controller input .


8 / Controller Port Interface / Reading Digital Joystick Controllers

Digital joysticks contain four directional switches.  Each switch can be
individually activated by the control stick.  When the stick is pressed
diagonally, two adjacent switches are activated.  The total number of
possible directions from a digital joystick is 8.  All digital joysticks
have at least one fire button.

Digital joystick switches are of the normally open type.  When the
switches are pressed, the input line is shorted to ground.  An open switch
reads as "1", a closed switch as "0".

Reading the joystick input data logic states is not so simple, however,
because the data registers for the joysticks are the same as the counters
that are used for the  mouse or trackball  controllers. The joystick
registers are named  JOY0DAT and JOY1DAT .

Table 8-3 shows how to interpret the data once you have read it from these
registers. The true logic state of the switch data in these registers is
"1 = switch closed."

   Data Bit                  Interpretation
   --------                  --------------
      1            True logic state of "right" switch.
      9            True logic state of "left"  switch.
   1 (XOR) 0       You must calculate the exclusive-or of bits 1 and 0
                     to obtain the logic state of the "back" switch.
   9 (XOR) 8       You must calculate the exclusive-or of bits 9 and 8
                     to obtain the logic state of the "forward" switch.

   Table 8-3: Interpreting Data from  JOY0DAT and JOY1DAT

The fire buttons for ports 0 and 1 are connected to bits 6 and 7 of
 CIAAPRA  ($BFE001).  A 0 here indicates the switch is closed.

Some, but not all, joysticks have a second button.  We encourage the use
of this button if the function the button controls is duplicated via the
keyboard or another mechanism.  This button may be read in the same manner
as the right  mouse button .

     Figure 8-3: Joystick to Counter Connections


8 / Controller Port Interface / Reading Proportional Controllers

Each of the game  controller ports  can handle two variable-resistance
input devices, also known as proportional input devices. This section
describes how the positions of the proportional input devices can be
determined. There are two common types of proportional controllers:  the
"paddle" controller pair and the X-Y proportional joystick. A paddle
controller pair consists of two individual enclosures, each containing a
single resistor and fire-button and each connected to a common
 controller port  input connector. Typical connections are shown in Figure
8-4.

    LEFT PADDLE                          RIGHT PADDLE

          resistive element                    resistive element

     ____/\  /\  /\  /\  /\____           ____/\  /\  /\  /\  /\____
    |      \/  \/  \/  \/                |      \/  \/  \/  \/
    |+5           ^                      |+5           ^
    |             |_ _ _ _ _ _           |             |_ _ _ _ _ _
                              |                                    |
  pin 7                     pin 9      pin 7                     pin 9

    |                         |          |                         |
    |<- - - fire button - - ->|          |<- - - fire button - - ->|
    |                         |          |                         |

  pin 8                     pin 3      pin 8                     pin 3

                Figure 8-4: Typical Paddle Wiring Diagram

In an X-Y proportional joystick, the resistive elements are connected
individually to the X and Y axes of a single controller stick.

 Reading Proportional Controller Buttons
 Interpreting Proportional Controller Position
 Proportional Controller Registers
 Potentiometer Specifications


8 / / Reading Controllers / Reading Proportional Controller Buttons

For the paddle controllers, the left and right joystick direction lines
serve as the fire buttons for the left and right paddles.


8 / / Reading Controllers / Interpreting Controller Position

Interpreting the position of the proportional controller normally requires
some preliminary work during the  vertical blanking  interval.

During  vertical blanking , you write a value into an address called
 POTGO . For a standard X-Y joystick, this value is hex 0001. Writing to
this register starts the operation of some special hardware that reads the
potentiometer values and sets the values contained in the  POT registers
(described below) to zero.

The read circuitry stays in a reset state for the first seven or eight
horizontal video scan lines. Following the reset interval, the circuit
allows a charge to begin building up on a timing capacitor whose charge
rate will be controlled by the position of the external controller
resistance. For each horizontal scan line thereafter, the circuit compares
the charge on the timing capacitor to a preset value. If the charge is
below the preset, the  POT counter  is incremented. If the charge is above
the preset, the counter value will be held until the next  POTGO  is
issued.

     Figure 8-5: Effects of Resistance on Charging Rate

You normally issue  POTGO  at the beginning of a video screen, then read
the values in the  POT registers  during the next  vertical blanking
period, just before issuing  POTGO  again.

Nothing in the system prevents the counters from overflowing (wrapping
past a count of 255). However, the system is designed to insure that the
counter cannot overflow within the span of a single screen. This allows
you to know for certain whether an overflow is indicated by the controller.


8 / / Reading Controllers / Proportional Controller Registers

The following registers are used for the proportional controllers:

   POT0DAT  - port 1 data (vertical/horizontal)
   POT1DAT  - port 2 data (vertical/horizontal)

   Bit positions:

   Bits 15-8   POT0Y value or POT1Y value
   Bits 7-0    POT0X value or POT1X value

All counts are reset to zero when  POTGO  is written with bit zero high.
Counts are normally read one frame after the scan circuitry is enabled.


8 / / Reading Proportional Controllers / Potentiometer Specifications

The resistance of the potentiometers should be a linear taper. Based on
the design of the integrating analog-to-digital converter used, the
maximum resistance should be no more than 528K (470K +/- 10 percent is
suggested) for either the X or Y pots. This is based on a charge capacitor
of 0.047uf, +/- 10 percent, and a maximum time of 16.6 milliseconds for
charge to full value, ie. one video frame time.

All potentiometers exhibit a certain amount of "jitter". For acceptable
results on a wide base of configurations, several input readings will need
to be averaged.

     Figure 8-6: Potentiometer Charging Circuit


8 / Controller Port Interface / Reading A Light Pen

A light pen can be connected to one of the  controller ports . On the
A1000, the light pen must be connected to port 1. Changing ports requires
a minor internal modification. On the A500, A2000 and A3000 the default is
port 2. An internal jumper can select port 1.  Regardless of the port
used, the light pen design is the same.

The signal called "pen-pressed-to-screen" is typically actuated by a
switch in the nose of the light pen. Note that this switch is connected to
one of the potentiometer inputs and must be read as same as the right or
middle  mouse button .

The principles of light pen operation are as follows:

   1. Just as the system exits  vertical blank , the capture circuitry
      for the light pen is automatically enabled.

   2. The video beam starts to create the picture, sweeping from left
      to right for each horizontal line as it paints the picture from
      the top of the screen to the bottom.

   3. The sensors in the light pen see a pulse of light as the video
      beam passes by. The pen converts this light pulse into an
      electrical pulse on the "Beam Trigger" line (pin 6).

   4. This trigger signal tells the internal circuitry to capture and
      save the current contents of the beam register,  VPOSR . This
      allows you to determine where the pen was placed by reading the
      exact horizontal and vertical value of the counter beam at the
      instant the beam passed the light pen.

 Reading the Light Pen Registers


8 / / Reading A Light Pen / Reading the Light Pen Registers

The light pen register is at the same address as the beam counters. The
bits are as follows:

   VPOSR:     Bit 15       Long frame/short frame.  0=short frame
              Bits 14-1    Chip ID code.  Do not depend on value!
              Bit 0        V8 (most significant bit of vertical position)

   VHPOSR:    Bits 15-8    V7-V0 (vertical position)
              Bits 7-0     H8-H1 (horizontal position)

The software can refer to this register set as a long word whose address
is VPOSR.

The positional resolution of these registers is as follows:

   Vertical      1 scan line in non-interlaced mode
                 2 scan lines in interlaced mode (However, if you know
                 which interlaced frame is under display, you can
                 determine the correct position)

   Horizontal    2 low resolution pixels in either high or low resolution

The quality of the light pen will determine the amount of short-term
jitter.  For most applications, you should average several readings
together.

To enable the light pen input, write a 1 into bit 3 (LPEN) of  BPLCON0 .
Once the light pen input is enabled and the light pen issues a trigger
signal, the value in VPOSR is frozen. If no trigger is seen, the counters
latch at the end of the display field. It is impossible to read the
current beam location while the VPOSR register is latched. This freeze is
released at the end of internal  vertical blanking  (vertical position
20). There is no single bit in the system that indicates a light pen
trigger. To determine if a trigger has occurred, use one of these methods:

   1. Read (long) VPOSR twice.

   2. If both values are not the same, the light pen has not triggered
      since the last top-of-screen (V = 20).

   3. If both values are the same, mask off the upper 15 bits of the
      32-bit word and compare it with the hex value of $10500 (V = 261).

   4. If the VPOSR value is greater than $10500, the light pen has not
      triggered since the last top-of-screen. If the value is less,
      the light pen has triggered and the value read is the screen
      position of the light pen.

A somewhat simplified method of determining the truth of the light pen
value involves instructing the system software to read the register only
during the internal  vertical blanking  period of 0 < V20:

   1. Read (long) VPOSR once, during the period of 0 < V20.

   2. Mask off the upper 15 bits of the 32-bit word and compare it
      with the hex value of $10500 (V = 261).

   3. If the VPOSR value is greater than $10500, the light pen has not
      triggered since the last top-of-screen. If the value is less,
      the light pen has triggered and the value read is the screen
      position of the light pen.

Note that when the light pen latch is enabled, the VPOSR register may be
latched at any time, and cannot be relied on as a counter.  This behavior
may cause problems with software that attempts to derive timing based on
VPOSR ticks.


8 / Controller Port Interface / Digital I/O On The Controller Port

The Amiga can read and interpret many different and nonstandard
controllers. The control lines built into the POTGO register (address
$DFF034) can redefine the functions of some of the  controller port  pins.

Table 8-4 is the POTGO register bit description. POTGO ($DFF034) is the
write-only address for the pot control register. POTGOR (formerly POTINP)
($DFF016) is the read-only address for the pot control register. The
pot-control register controls a four-bit bidirectional I/O port that
shares the same four pins as the four pot inputs.

     Table 8-4: POTGO ($DFF034) and POTGOR ($DFF016) Registers

       Bit
       Number  Name    Function
       ------  ----    --------
       15      OUTRY   Output enable for bit 14 (1=output)
       14      DATRY   data for port 2, pin 9
       13      OUTRX   Output enable for bit 12
       12      DATRX   data for port 2, pin 5
       11      OUTLY   Output enable for bit 10
       10      DATLY   data for port 1, pin 9 (right  mouse button )
       09      OUTLX   Output enable for bit 8
       08      DATLX   data for port 1, pin 5 (middle  mouse button )
       07-01   X       chip revision identification number
       00      START   Start pots (dump capacitors, start counters)

Instead of using the pot pins as variable-resistive inputs, you can use
these pins as a four-bit input/output port.  This provides you with two
additional pins on each of the two  controller ports  for general purpose
I/O.

If you set the output enable for any pin to a 1, the Amiga disconnects the
potentiometer control circuitry from the port, and configures the pin for
output.  The state of the data bit controls the logic level on the output
pin.  This register must be written to at the POTGO address, and read
from the POTGOR address. There are large capacitors on these lines, and
it can take up to 300 microseconds for the line to change state.

To use the entire register as an input, sensing the current state of the
pot pins, write all 0s to POTGO.  Thereafter you can read the current
state by using read-only address POTGOR.  Note that bits set as inputs
will be connected to the proportional counters (See the description of the
START bit in POTGO).

These lines can also be used for button inputs.  A button is a normally
open switch that shorts to ground.  The Amiga must provide a pull-up
resistance on the sense pin.  To do this, set the proper pin to output,
and drive the line high (set both OUT... and DAT... to 1).  Reading
POTGOR will produce a 0 if the button is pressed, a 1 if it is not.

The joystick fire buttons can also be configured as outputs.   CIAADDRA
($BFE201) contains a mask that corresponds one-to-one with the data read
register,  CIAAPRA  ($BFE001). Setting a 1 in the direction position makes
the corresponding bit an output.  See Appendix F for more details.


8 Interface Hardware / Floppy Disk Controller

The built-in disk controller in the system can handle up to four MFM-type
devices.  Typically these are double-sided, double-density, 3.5" (90mm) or
5.25" disk drives.  One 3.5" drive is installed in the basic unit.

The controller is extremely flexible.  It can DMA an entire track of raw
MFM data into memory in a single disk revolution.  Special registers allow
the CPU to synchronize with specific data, or read input a byte at a time.
The controller can read and write virtually any double-density MFM encoded
disk, including the Amiga V1.0 format, IBM PC (MS-DOS) 5.25", IBM PC
(MS-DOS) 3.5" and most CP/M (TM) formatted disks.  The controller has
provisions for reading and writing most disk using the Group Coded
Recording (GCR) method, including Apple II (TM) disks.  With motor speed
tricks, the controller can read and write Commodore 1541/1571 format
diskettes.

 Registers Used by the Disk Subsystem
 Disk Subsystem Timing
 Disk Interrupts


8 / Floppy Disk Controller / Registers Used by the Disk Subsystem

The disk subsystem uses two ports on the system's  8520 CIA  chips, and
several registers in the Paula chip:

   CIAAPRA    ($BFE001)    four input bits for disk sensing
   CIABPRB    ($BFD100)    eight output bits for disk selection, control
                             and stepping
   ADKCON     ($DFF09E)    control bits (write only register)
   ADKCONR    ($DFF010)    control bits (read only register)
   DSKPTH     ($DFF020)    DMA pointer (32 bits)
   DSKLEN     ($DFF024)    length of DMA
   DSKBYTR    ($DFF01A)    Disk data byte and status read
   DSKSYNC    ($DFF07E)    Disk sync finder; holds a match word


8 / Floppy Disk Controller / Disk Subsystem Timing

Figures 8-7, 8-8 and 8-9 show the timing parameters of the Amiga's floppy
disk subsystem with a Chinon drive. Keep in mind that this information can
change with floppy drives from other vendors.  To ensure compatibility
with future versions of the system, you should avoid using this
information in applications.

             500ms min
           |<--------->|
         __            |
  MOTOR    |           |
  ON       |___________________________________________________________

         __            |                                       ________
  DRIVE    |           |                                      |
  SELECT   |__________________________________________________|

           |           |                         1.2ms min    |
           |           |                    |<--------------->|
         _____    ___________________________________    ______________
  STEP        |  |                                   |  |
           |  |__|     |                    |        |__|
           |           |                    |
           |  -->|     |<--18ms min         | 1.3ms min |
        -->|           |<--1us min          |<--------->|
         ______________                      __________________________
  WRITE                |                    |
  GATE                 |____________________|
                                               1.2ms min
                 -->|  |<--1000us min       |<---------->|
         ___________   |   (see text)       |             _____________
  SIDE              |  |                    |            |
  SELECT            |____________________________________|

             8us max-->|  |<--        -->|  |<--8us max
         ______________________________________________________________
  WRITE                   |  |  |  |  |  |
  DATA                 |  |__|__|__|__|__|  |

                 Figure 8-7: Chinon Write Timing Diagram

         ____                                                   _______
  DRIVE      |                                                 |
  SELECT     |_________________________________________________|

             |      |            |      | 3ms  |            |  |
             |  t   | 18 ms min  |      | min  | 18 ms min  |  |
             |<---->|<---------->|      |<---->|<---------->|  |<-t
         ________    _________    ___    ___    _________    __________
  STEP           |  |         |  |   |  |   |  |         |  |
                 |__|         |__|   |__|   |__|         |__|

              |  t  |  t  |  t   |   |  |      |  t  |  t   |
              |<--->|<--->|<---->| ->|  |<-t   |<--->|<---->|
               ___________       |                    _________________
  DIRECTION   |           |      |                   |
  SELECT _____|     |     |__________________________|
                    | 4ms
                    | max  |     |  |
                    |<---->|   ->|  |<-t
         __________________          __________________________________
                           |        |
  TRACK 00                 |________|

                 Figure 8-8: Chinon Access Timing Diagram

         __
  DRIVE    |
  SELECT   |___________________________________________________________

        -->|     |<--1us min
         _____    _____________________________________________________
  STEP        |  |
           |  |__|
           |         18ms min
           |     |<------------->|
           |     |   1us min     |
           |<------------------->|
         ________________________         _____________________________
  WRITE                          |       |
  GATE     |     |               |_______|
           |     | 1000us min  |             1.2ms min
           |     | (see text)->| |<--    |<------------>|
         ______________________  |       |               ______________
  SIDE                         |         |              |
  SELECT   |  -->|  |<--18ms   |________________________|
           |     |  |    max
           |1us min |                    |  |           |  |  1000us min
           |<------>|        1.2ms max-->|  |<--     -->|  |<-(see text)
         ______________________________________________________________
  VALID             |  |  |  |              |  |  |  |  |  |  |  |  |  |
  READ DATA         |__|__|__|              |__|__|__|__|  |__|__|__|__|

                  Figure 8-8: Chinon Read Timing Diagram

 CIAAPRA/CIABPRB - Disk selection, control and sensing
 Disk DMA Channel Control
 DSKPTH - Pointer to Data
 DSKLEN - Length, Direction, DMA Enable
 DSKBYTR - Disk Data Byte and Status Read (read-only)
 ADKCON and ADKCONR - Audio and Disk Control Register
 DSKSYNC - Disk Input Synchronizer


8 / / Disk Timing / CIAAPRA/PRB - Disk selection, control and sensing

The following table lists how 8520 chip bits used by the disk subsystem.
Bits labeled  PA  are input bits in CIAAPRA ($BFE001).  Bits labeled
 PB  are output bits located in CIAAPRB ($BFD100).  More information on
how the 8520 chips operate can be found in Appendix F.

                   Table 8-5: Disk Subsystem

Bit   Name         Function
---   ----         --------
PA5   DSKRDY*      Disk ready (active low). The drive will pull this line
                   low when the motor is known to be rotating at full
                   speed.  This signal is only valid when the motor is ON,
                   at other times configuration information may obscure
                   the meaning of this input.

PA4   DSKTRACK0*   Track zero detect.  The drive will pull this line low
                   when the disk heads are positioned over track zero.
                   Software must not attempt to step outwards when this
                   signal is active.  Some drives will refuse to step,
                   others will attempt the step, possibly causing
                   alignment damage.  All new drives must refuse to step
                   outward in this condition.

PA3   DSKPROT*     Disk is write protected (active low).

PA2   DSKCHANGE*   Disk has been removed from the drive.  The signal goes
                   low whenever a disk is removed.  It remains low until
                   a disk is inserted AND a step pulse is received.
      ---------

PB7   DSKMOTOR*    Disk motor control (active low).  This signal is
                   nonstandard on the Amiga system.  Each drive will latch
                   the motor signal at the time its select signal turns
                   on.  The disk drive motor will stay in this state until
                   the next time select turns on.  DSKMOTOR* also controls
                   the activity light on the front of the disk drive.

                   All software that selects drives must set up the motor
                   signal before selecting any drives.  The drive will
                   "remember" the state of its motor when it is not
                   selected.  All drive motors turn off after system
                   reset.

                   After turning on the motor, software must further wait
                   for one half second (500ms), or for the DSKRDY* line to
                   go low.

PB6   DSKSEL3*     Select drive 3 (active low).

PB5   DSKSEL2*     Select drive 2 (active low).

PB4   DSKSEL1*     Select drive 1 (active low).

PB3   DSKSEL0*     Select drive 0 (internal drive) (active low).

PB2   DSKSIDE      Specify which disk head to use.  Zero indicates the
                   upper head.  DSKSIDE must be stable for 100
                   microseconds before writing. After writing, at least
                   1.3 milliseconds must pass before switching DSKSIDE.

PB1   DSKDIREC     Specify the direction to seek the heads.  Zero implies
                   seek towards the center spindle.  Track zero is at the
                   outside of the disk.  This line must be set up before
                   the actual step pulse, with a separate write to the
                   register.

PB0   DSKSTEP*     Step the heads of the disk.  This signal must always be
                   used as a quick pulse (high, momentarily low, then
                   high).

                   The drives used for the Amiga are guaranteed to get to
                   the next track within 3 milliseconds.  Some drives will
                   support a much faster rate, others will fail.  Loops
                   that decrement a counter to provide delay are not
                   acceptable.  See  Appendix F  for a better solution.

                   When reversing directions, a minimum of 18 milliseconds
                   delay is required from the last step pulse.  Settle
                   time for Amiga drives is specified at 15 milliseconds.

FLAG  DSKINDEX*    Disk index pulse ($BFDD00, bit 4).  Can be used to
                   create a level 6  interrupt .  See  Appendix F  for
                   details.


8 / / Disk Subsystem Timing / Disk DMA Channel Control

Data is normally transferred to the disk by direct memory access (DMA).
The disk DMA is controlled by four items:

   *  Pointer to the area into which or from which the data is to be
      moved

   *  Length of data to be moved by DMA

   *  Direction of data transfer (read/write)

   *  DMA enable


8 / / Disk Subsystem Timing / DSKPTH - Pointer to Data

You specify the 32-bit wide address from which or to which the data is to
be transferred. The lowest bit of the address must be zero, and the buffer
must be in Chip memory.  The value must be written as a single long word
to the DSKPTH register ($DFF020).


8 / / Disk Subsystem Timing / DSKLEN - Length, Direction, DMA Enable

All of the control bits relating to this topic are contained in a
write-only register, called DSKLEN:

           Table 8-6: DSKLEN Register ($DFF024)

       Bit
       Number  Name    Usage
       ------  ----    -----
       15      DMAEN   Secondary disk DMA enable
       14      WRITE   Disk write (RAM -> disk if 1)
       13-0    LENGTH  Number of words to transfer

The hardware requires a special sequence in order to start DMA to the
disk.  This sequence prevents accidental writes to the disk.
In short, the DMAEN bit in the DSKLEN register must be turned on twice
in order to actually enable the disk DMA hardware.
Here is the sequence you should follow:

   1. Enable disk DMA in the  DMACON  register (See Chapter 7 for more
      information)
   2. Set DSKLEN to $4000, thereby forcing the DMA for the disk to be
      turned off.
   3. Put the value you want into the DSKLEN register.
   4. Write this value again into the DSKLEN register. This actually
      starts the DMA.
   5. After the DMA is complete, set the DSKLEN register back to
      $4000, to prevent accidental writes to the disk.

As each data word is transferred, the length value is decremented. After
each transfer occurs, the value of the pointer is incremented. The pointer
points to the the next word of data to written or read. When the length
value counts down to 0, the transfer stops.

The recommended method of reading from the disk is to read an entire track
into a buffer and then search for the sector(s) that you want. Using the
 DSKSYNC  register (described below) will guarantee word alignment of the
data.  With this process you need to read from the disk only once for the
entire track.  In a high speed loader, the step to the next head can occur
while the previous track is processed and checksummed. With this method
there are no time-critical sections in reading data, other high-priority
subsystems (such as graphics or audio) are be allowed to run.

If you have too little memory for track buffering (or for some other
reason decide not to read a whole track at once), the disk hardware
supports a limited set of sector-searching facilities. There is a register
that may be polled to examine the disk input stream.

There is a hardware bug that causes the last three bits of data sent to
the disk to be lost. Also, the last word in a disk-read DMA operation may
not come in (that is, one less word may be read than you asked for).


8 / / Timing / DSKBYTR - Disk Data Byte and Status Read (read-only)

This register is the disk-microprocessor data buffer. In read mode, data
from the disk is placed into this register one byte at a time.  As each
byte is received into the register, the DSKBYT bit is set true. DSKBYT is
cleared when the DSKBYTR register is read.

DSKBYTR may be used to synchronize the processor to the disk rotation
before issuing a read or write under DMA control.

                 Table 8-7: DSKBYTR Register

     Bit
     Number  Name       Function
     ------  ----       --------
     15      DSKBYT     When set, indicates that this register contains
                        a valid byte of data (reset by reading this
                        register).

     14      DMAON      Indicates when DMA is actually enabled.  All the
                        various DMA bits must be true.  This means the
                        DMAEN bit in  DSKLEN , and the DSKEN & DMAEN bits
                        in  DMACON .

     13      DISKWRITE  The disk write bit (in  DSKLEN ) is enabled.

     12      WORDEQUAL  Indicates the  DSKSYNC  register equals the disk
                        input stream.  This bit is true only while the
                        input stream matches the sync register (as
                        little as two microseconds).

     11-8               Currently unused; don't depend on read value.

     7-0     DATA       Disk byte data.


8 / / Timing / ADKCON and ADKCONR - Audio and Disk Control Register

ADKCON is the write-only address and ADKCONR is the read-only address for
this register.  Not all of the bits are dedicated to the disk.  Bit 15 of
this register allows independent setting or clearing of any bit or bits.
If bit 15 is a one on a write, any ones in positions 0-14 will set the
corresponding bit.  If bit 15 is a zero, any ones will clear the
corresponding bit.

               Table 8-8: ADKCON and ADKCONR Register

     Bit
     Number  Name       Function
     ------  ----       --------
     15      SET/CLR    Control bit that allows setting or clearing of
                        individual bits without affecting the rest of
                        the register.

                        If bit 15 is a 1, the specified bits are set.
                        If bit 15 is a 0, the specified bits are cleared.

     14      PRECOMP1   MSB of Precompensation specifier
     13      PRECOMP0   LSB of Precompensation specifier

                        Value of 00 selects none.
                        Value of 01 selects 140 ns.
                        Value of 10 selects 280 ns.
                        Value of 11 selects 560 ns.

     12      MFMPREC    Value of 0 selects GCR Precompensation.
                        Value of 1 selects MFM Precompensation.

     10      WORDSYNC   Value of 1 enables synchronizing and starting of
                        DMA on disk read of a word.  The word on which to
                        synchronize must be written into the  DSKSYNC
                        address ($DFF07E).  This capability is highly
                        useful.

     9       MSBSYNC    Value of 1 enables sync on most significant bit
                        of the input (usually used for GCR).

     8       FAST       Value of 1 selects two microseconds per bit cell
                        (usually MFM).  Data must be valid raw MFM.
                        0 selects four microseconds per bit (usually GCR).

     7-0                These bits are used by the audio subsystem for
                        volume and frequency modulation.

The raw MFM data that must be presented to the disk controller will be
twice as large as the unencoded data.  The following table shows the
relationship:

               1 -> 01
               0 -> 10   ;if following a 0
               0 -> 00   ;if following a 1

With clever manipulation, the blitter can be used to encode and decode the
MFM.

In one common form of GCR recording, each data byte always has the most
significant bit set to a 1.  MSBSYNC, when a 1, tells the disk controller
to look for this sync bit on every disk byte. When reading a GCR formatted
disk, the software must use a translate table called a nybble-izer to
assure that data written to the disk does not have too many consecutive
1's or 0's.


8 / / Disk Subsystem Timing / DSKSYNC - Disk Input Synchronizer

The DSKSYNC register is used to synchronize the input stream.  This is
highly useful when reading disks. If the WORDSYNC bit is enabled in
 ADKCON , no data is transferred until a word is found in the input stream
that matches the word in the DSKSYNC register.  On read, DMA will start
with the following word from the disk.  During disk read DMA, the
controller will resync every time the word match is found.  Typically the
DSKSYNC will be set to the magic MFM sync mark value, $4489.

In addition, the DSKSYNC bit in  INTREQ  is set when the input stream
matches the DSKSYNC register. The DSKSYNC bit in  INTREQ  is independent
of the WORDSYNC enable.


8 / Floppy Disk Controller / Disk Interrupts

The disk controller can issue three kinds of interrupts:

   *   DSKSYNC  (level 5,  INTREQ  bit 12) -- input stream matches the
                                             DSKSYNC register.
   *   DSKBLK  (level 1,  INTREQ  bit 1) -- disk DMA has completed.
   *   INDEX  (level 6, 8520 Flag pin) -- index sensor triggered.

Interrupts are explained further in the section
 Length, Direction, DMA Enable .

See Chapter 7, "System Control Hardware," for more information about
  interrupts .

See  Appendix F  for more information on the 8520.


8 Interface Hardware / The Keyboard

The keyboard is interfaced to the system via the serial  shift register
on one of the 8520 CIA chips.  The keyboard data line (KDAT) is connected
to the  SP pin , the keyboard clock (KCLK) is connected to the  CNT pin .
 Appendix G  contains a full description of the interface.

 How the Keyboard Data is Received
 Type of Data Received
 Limitations of the Keyboard


8 / The Keyboard / How the Keyboard Data is Received

The  CNT line  is used as a clock for the keyboard. On each transition of
this line, one bit of data is clocked in from the keyboard. The keyboard
sends this clock when each data bit is stable on the  SP line . The clock
is an active low pulse. The rising edge of this pulse clocks in the data.

After a data byte has been received from the keyboard, an  interrupt  from
the 8520 is issued to the processor.  The keyboard waits for a handshake
signal from the system before transmitting any more keystrokes. This
handshake is issued by the processor pulsing the  SP line  low then high.
While some keyboards can detect a 1 microsecond handshake pulse, the pulse
must be at least 85 microseconds for operation with all models of Amiga
keyboards.

If another keystroke is received before the previous one has been accepted
by the processor, the keyboard microprocessor holds keys in a 10 keycode
type-ahead buffer.


8 / The Keyboard / Type of Data Received

The keyboard data is not received in the form of ASCII characters.
Instead, for maximum versatility, it is received in the form of keycodes.
These codes include both the down and up transitions of the keys. This
allows your software to use both sets of information to determine exactly
what is happening on the keyboard.

Here is a list of the hexadecimal values that are assigned to the
keyboard. A downstroke of the key transmits the value shown here. An
upstroke of the key transmits this value plus $80. The picture of the
keyboard shows the positions that correspond to the description in the
sections below.

Note that raw keycodes provide positional information only, the legend
which is printed on top of the keys changes from country to country.

 RAW Keycodes -> 00-3F hex
 RAW Keycodes -> 40-5F hex  (Codes common to all keyboards)
 RAW Keycodes -> 60-67 hex  (Key codes for qualifier keys)
 F0-FF hex


8 / / Type of Data Received / RAW Keycodes -> 00-3F hex

These are key codes assigned to specific positions on the main body of the
keyboard.  The letters on the tops of these keys are different for each
country; not all countries use the QWERTY key layout. These keycodes are
best described positionally as shown in Figure 8-10 and Figure 8-11.  The
international keyboards have two more keys that are "cut out" of larger
keys on the USA version.  These are $30, cut out from the the left shift,
and $2B, cut out from the return key.

     Figure 8-10: The Amiga 1000 Keyboard

     Figure 8-11: The Amiga 500/2000/3000 Keyboard


8 / / Type Of Data Received / RAW Keycodes -> 40-5F hex

Codes common to all keyboards

   40      Space
   41      Backspace
   42      Tab
   43      Numeric Pad "ENTER"
   44      Return
   45      Escape
   46      Delete
   4A      Numeric pad minus
   4C      Cursor up
   4D      Cursor down
   4E      Cursor right
   4F      Cursor left
   50-59   Function keys F1-F10
   5A      Numeric pad left parenthesis
   5B      Numeric pad right parenthesis
   5C      Numeric pad slash "/"
   5D      Numeric pad asterisk
   5E      Numeric pad plus
   5F      Help


8 / / Type Of Data Received / RAW Keycodes -> 60-67 hex

Key codes for qualifier keys

   60      Left Shift
   61      Right Shift
   62      Caps Lock
   63      Control
   64      Left Alt
   65      Right Alt
   66      Left Amiga (or Commodore key)
   67      Right Amiga


8 / / Type Of Data Received / F0-FF hex

These key codes are used for keyboard to 680x0 communication, and are not
associated with a keystroke. They have no key transition flag, and are
therefore described completely by 8-bit codes:

   78      Reset warning.  Ctrl-Amiga-Amiga has been pressed. The
           keyboard will wait a maximum of 10 seconds before
           resetting the machine. (Not available on all keyboard
           models)

   F9      Last key code bad, next key is same code retransmitted

   FA      Keyboard key buffer overflow

   FC      Keyboard self-test fail.  Also, the caps-lock LED will
           blink to indicate the source of the error.  Once for ROM
           failure, twice for RAM failure and three times if the
           watchdog timer fails to function.

   FD      Initiate power-up key stream (for keys held or stuck at
           power on)

   FE      Terminate power-up key stream.

These key codes will usually be filtered out by keyboard drivers.


8 / The Keyboard / Limitations Of The Keyboard

The Amiga keyboard is a matrix of rows and columns with a key switch at
each intersection (see  Appendix G  for a diagram of the matrix). Because
of this, the keyboard is subject to a phenomenon called "phantom
keystrokes." While this is generally not a problem for typing, games may
require several keys be independently held down at once. By examining the
matrix, you can determine which keys may interfere with each other, and
which ones are always safe.

Phantom keystrokes occur when certain combinations of keys pressed are
pressed simultaneously.  For example, hold the "A" and "S" keys down
simultaneously.  Notice that "A" and "S" are transmitted.  While still
holding them down, press "Z".  On the original Amiga 1000 keyboard, both
the "Z" and a ghost "X" would be generated. Starting with the Amiga 500,
the controller was upgraded to notice simple phantom situations like the
one above; instead of generating a ghost, the controller will hold off
sending any character until the matrix has cleared (releasing "A" or "S"
would clear the matrix).  Some high-end Amiga keyboards may implement true
"N-key rollover," where any combination of keys can be detected
simultaneously.

All of the keyboards are designed so that phantoms will not happen during
normal typing, only when unusual key combinations like the one just
described are pressed.  Normally, the keyboard will appear to have "N-key
rollover," which means that you will run out of fingers before generating
a ghost character.

   About the qualifier keys.
   -------------------------
   Seven keys are not part of the matrix, and will never contribute to
   generating phantoms. These keys are:  Ctrl, the two Shift keys, the
   two Amiga keys, and the two Alt keys.


8 Interface Hardware / Serial I/O Interface

A 25-pin connector on the back panel of the computer serves as the general
purpose  serial interface . This connector can drive a wide range of
different peripherals, including an external modem or a serial printer.

For pin connections, see  Appendix E .

 Introduction To Serial Circuitry   Contents Of The Receive Data Register
 Setting The Baud Rate              How Output Data Is Transmitted
 Setting The Receive Mode           Specifying The Register Contents


8 / Serial I/O Interface / Introduction To Serial Circuitry

The Paula custom chip contains a Universal Asynchronous
Receiver/Transmitter, or UART. This UART is programmable for any rate from
110 to over 1,000,000 bits per second.  It can receive or send data with a
programmable length of eight or nine bits.

The UART implementation provides a high degree of software control. The
UART is capable of detecting overrun errors, which occur when some other
system sends in data faster than you remove it from the data-receive
register.  There are also status bits and interrupts for the conditions of
receive buffer full and transmit buffer empty.  An additional status bit
is provided that indicates "all bits have been shifted out". All of these
topics are discussed in folowing sections.


8 / Serial I/O Interface / Setting The Baud Rate

The rate of transmission (the baud rate) is controlled by the contents of
the register named  SERPER .  Bits 14-0 of  SERPER  are the baud-rate
divider bits.

All timing is done on the basis of a "color clock," which is 279.36ns long
on NTSC machines and 281.94ns on PAL machines.  If the  SERPER  divisor is
set to the number N, then N+1 color clocks occur between samples of the
state of the input pin (for receive) or between transmissions of output
bits (for transmit).  Thus  SERPER =(3,579,545/baud)-1. On a PAL machine,
 SERPER =(3,546,895/baud)-1.  For example, the proper  SERPER  value for
9600 baud on an NTSC machine is (3,579,545/9600)-1=371.

With a cable of a reasonable length, the maximum reliable rate is on the
order of 150,000-250,000 bits per second.  Maximum rates will vary between
machines.  At these high rate it is not possible to handle the overhead of
interrupts.  The receiving end will need to be in a tight read loop.
Through the use of low speed control information and high-speed bursts, a
very inexpensive communication network can be built.


8 / Serial I/O Interface / Setting The Receive Mode

The number of bits that are to be received before the system tells you
that the receive register is full may be defined either as eight or nine
(this allows for 8 bit transmission with parity).  In either case, the
receive circuitry expects to see one start bit, eight or nine data bits,
and at least one stop bit.

Receive mode is set by bit 15 of the write-only  SERPER  register. Bit 15
is a 1 if you chose nine data bits for the receive-register full signal,
and a 0 if you chose eight data bits. The normal state of this bit for
most receive applications is a 0.


8 / Serial I/O Interface / Contents Of The Receive Data Register

The serial input data-receive register is 16 bits wide.  It contains the 8
or 9 bit input data and status bits.

The data is received, one bit at a time, into an internal
serial-to-parallel  shift register .  When the proper number of bit times
have elapsed, the contents of this register are transferred to the serial
data read register (SERDATR) shown in Table 8-10, and you are signaled
that there is data ready for you.

Immediately after the transfer of data takes place, the
 receive shift register  again becomes ready to accept new data. After
receiving the receiver-full interrupt, you will have up to one full
character-receive time (8 to 10 bit times) to accept the data and clear
the interrupt. If the interrupt is not cleared in time, the OVERRUN bit is
set.

Table 8-9 shows the definitions of the various bit positions within
SERDATR.

               Table 8-9: SERDATR /  ADKCON  Registers

   SERDATR
   -------

   Bit
   Number  Name    Function
   ------  ----    --------
   15      OVRUN    OVERRUN
                    (Mirror -- also appears in the interrupt request
                    register.) Indicates that another byte of data was
                    received before the previous byte was picked up by the
                    processor.  To prevent this condition, it is necessary
                    to reset INTF_RBF (bit 11, receive-buffer-full) in
                     INTREQ .

   14      RBF      READ BUFFER FULL
                    (Mirror -- also appears in the interrupt request
                    register.) When this bit is 1, there is data ready to
                    be picked up by the processor.  After reading the
                    contents of this data register, you must reset the
                    INTF_RBF bit in  INTREQ  to prevent an overrun.

   13      TBE      TRANSMIT BUFFER EMPTY
                    (Not a mirror -- interrupt occurs when the buffer
                    becomes empty.)  When bit 14 is a 1, the data in the
                    output data register ( SERDAT ) has been transferred to
                    the  serial output shift register , so  SERDAT  is ready
                    to accept another output word.  This is also true when
                    the buffer is empty.

                    This bit is normally used for full-duplex operation.

   12      TSRE     TRANSMIT SHIFT REGISTER EMPTY
                    When this bit is a 1, the  output shift register  has
                    completed its task, all data has been transmitted, and
                    the register is now idle.  If you stop writing data
                    into the output register ( SERDAT ), then this bit will
                    become a 1 after both the word currently in the
                     shift register  and the word placed into  SERDAT  have
                    been transmitted.

                    This bit is normally used for half-duplex operation.

   11      RXD      Direct read of  RXD pin  on Paula chip.

   10               Not used at this time.

   9       STP      Stop bit if 9 data bits are specified for receive.

   8       STP      Stop bit if 8 data bits are specified for receive.
                            OR
           DB8      9th data bit if 9 bits are specified for receive.

   7-0     DB7-DB0  Low 8 data bits of received data.  Data is TRUE (data
                    you read is the same polarity as the data expected).

    ADKCON
   --------

   Bit
   Number  Name     Function
   ------  ----     --------
   15      SET/CLR  Allows setting or clearing individual bits.

                    If bit 15 is a 1 specified bits are set.
                    If bit 15 is a 0 specified bits are cleared.

   11      UARTBRK  Force the transmit pin to zero.


8 / Serial I/O Interface / How Output Data Is Transmitted

You send data out on the transmit lines by writing into the serial data
output register (SERDAT).  This register is write-only.

Data will be sent out at the same rate as you have established for the
read.  Immediately after you write the data into this register, the system
will begin the transmission at the baud rate you selected.

At the start of the operation, this data is transferred from SERDAT into
an internal serial  shift register .  When the transfer to the serial
 shift register  has been completed, SERDAT can accept new data; the TBE
interrupt signals this fact.

Data will be moved out of the  shift register , one bit during each time
interval, starting with the least significant bit. The shifting continues
until all 1 bits have been shifted out. Any number or combination of data
and stop bits may be specified this way.

SERDAT is a 16-bit register that allows you to control the format
(appearance) of the transmitted data. To form a typical data sequence,
such as one start bit, eight data bits, and one stop bit, you write into
SERDAT the contents shown in Figures 8-12 and 8-13.

       15        9 8 7             0
     _________________________________
                                                         |     |
       0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 - - - - - - - - - ->|  1  |
     _________________________________                   |     |

                                                         one bit

                                 All zeros from last shift -

    Figure 8-12: Starting Appearance of SERDAT and Shift Register

                   15        9 8 7                 0
                 __________________________________
                                 |                 |
                   0 0 0 0 0 0 1 |<- 8 bits data ->|
                 ________________|_________________|

                                - - - - - - - - - ->

                     Data gets shfted out this way.

           Figure 8-13: Ending Appearance of Shift Register

The register stops shifting and signals "shift register empty" (TSRE) when
there is a 1 bit present in the bit-shifted-out position and the rest of
the contents of the  shift register  are 0s. When new nonzero contents are
loaded into this register, shifting begins again.


8 / Serial I/O Interface / Specifying The Register Contents

The data to be transmitted is placed in the output register ( SERDAT ).
Above the data bits, 1 bits must be added as stop bits. Normally, either
one or two stop bits are sent.

The transmission of the start bit is independent of the contents of this
register. One start bit is automatically generated before the first data
bit (bit 0) is sent.

Writing this register starts the data transmission. If this register is
written with all zeros, no data transmission is initiated.


8 Interface Hardware / Parallel I/O Interface

The general-purpose bi-directional  parallel interface  is a 25-pin
connector on the back panel of the computer. This connector is generally
used for a parallel printer.

For each data byte written to the parallel port register, the hardware
automatically generates a pulse on the data ready pin.  The acknowledge
pulse from the parallel device is hooked up to an interrupt. For pin
connections and timing, see  Appendix E  and  Appendix F .


8 Interface Hardware / Display Output Connections

All Amigas provide a 23-pin connector on the back.  This jack contains
video outputs and inputs for external genlock devices. Two separate type
of RGB video are available on the connector:

   *  RGB Monitors ("analog RGB"). Provides four outputs; Red (R),
      Green (G), Blue (B), and Sync (S). They can generate up to 4,096
      different colors on-screen simultaneously using the circuitry
      presently available on the Amiga.

   *  Digital RGB Monitors. Provides four outputs, distinct from those
      shown above, named Red (R), Green (G), Blue (B), Half-Intensity
      (I), and Sync (S).  All output levels are logic levels (0 or 1).
      On some monitors these outputs allow up to 15 possible color
      combinations, where the values 0000 and 0001 map to the same
      output value (Half intensity with no color present is the same
      as full intensity, no color). Some monitors arbitrarily map the
      16 combinations to 16 arbitrary colors.

   Note that the sync signals from the Amiga are unbuffered.  For use
   with any device that presents a heavy load on the sync outputs,
   external buffers will be required.

The Amiga 500 and 2000 provide a full-bandwidth monochrome video jack for
use with inexpensive monochrome monitors.  The Amiga colors are combined
into intensities based on the following table:

                       Red     Green   Blue
                       ---     -----   ----
                       30%      60%    10%

The A3000 is not equipped with a monochrome video jack.

The Amiga 1000 provides an RF modulator jack.  An adapter is available
that allows all Amiga models to use a television set for display.  Stereo
sound is available on the jack, but will generally be combined into
monaural sound for the TV set.

The Amiga 1000 provides a color composite video jack.  This is suitable
for recording directly with a VCR, but the output is not broadcast
quality. For use on a monochrome monitor, the color information often has
undesired effects; careful color selection or a modification to the
internal circuitry can improve the results.  The A500, A2000 and A3000 do
not have a color composite video jack. High quality composite adapters for
the A500, A1000, A2000 and A3000 plug into the 23 pin RGB port.

The Amiga 2000 and 3000 provide a special "video slot" that contains many
more signals than are available elsewhere:  all the 23-pin RGB port
signals, the unencoded digital video, light pen, power, audio, colorburst,
pixel switch, sync, clock signals, etc.


Amiga® Hardware Reference Manual: H External Disk Connector Interface

The 23-pin female connector at the rear of the main computer unit is used
to interface to and control devices that generate and receive MFM data.
This interface can be reached either as a resource or under the control of
a driver. The following pages describe the interface in both cases.

 Summary Table
 Signals When Driving a Disk
 Device I.D.


H External Disk Connector Interface / Summary Table

     Pin #   Name        Note
     -----   ----        ----
     1       RDY-        I/O     ID and ready
     2       DKRD-       I       MFM input
     3       GRND        G       -
     4       GRND        G       -
     5       GRND        G       -
     6       GRND        G       -
     7       GRND        G       -
     8       MTRXD-      O       Motor control.
     9       SEL2B-      O*      Select drive 2
     10      DRESB-      O       Reset
     11      CHNG-       I/O     Disk changed
     12      +5v         PWR     540 mA average 870 mA surge
     13      SIDEB-      O       Side 1 if low
     14      WPRO-       I/O     Write protect
     15      TK0-        I/O     Track 0
     16      DKWEB-      O       Write gate
     17      DKWDB-      O       Write data
     18      STEPB-      O       Step
     19      DIRB        O       Direction (high is out)
     20      SEL3B-      O*      Select drive 3
     21      SEL1B-      O*      Select drive 1
     22      INDEX-      I/O     Index
     23      +12v        PWR     120 mA average 370 mA surge

   Key to Class:

        G       ground, note connector shield grounded.
        I       input pulled up to 5v by 1K ohm.
        I/O     input in driver, but bidirectional input (1k pullup)
        O       output pulled though 1K to 5v
        O*      output, separates resources.
        PWR     available for external use, but currently used up by
                external drive.


H External Disk Connector Interface / Signals When Driving a Disk

The following describes the interface under driver control.

SEL1B-, SEL2B-, SEL3B-

   Select lines for the three external disk drives active low.

TK0-

   A selected drive pulls this signal low whenever its read-write head
   is on track 00.

RDY-

   When a disk drive's motor is on, this line indicates the selected
   disk is installed and rotating at speed. The driver ignores this
   signal. When the motor is off this is used as a  ID  data line. See
   below.

WPRO- (Pin #14)

   A selected drive pulls this signal low whenever it has a
   write-protected diskette installed.

INDEX- (Pin #22)

   A selected drive pulses this signal low once for each revolution of
   its motor.

SIDEB- (Pin #13)

   The system drives this signal to all disk drives -- low for side 1,
   high for side 0.

STEPB- (Pin #18)

   Pulsed to step the selected drive's head.

DIRB (Pin #19)

   The system drives this signal high or low to tell the selected drive
   which way to step when the STEPB- pulse arrives. Low means step in
   (to higher-numbered track); high means step out.

DKRD- (Pin #2)

   A selected drive will put out read data on this line.

DKWDB- (Pin #17)

   The system drives write data to all disks via this signal. The data
   is only written when DKWEB- is active (low). Data is written only to
   selected drives.

DKWEB- (Pin #16)

   This signal causes a selected drive to start writing data (provided
   by DKWDB-) onto the disk.

CHNG- (Pin #11)

   A selected drive will drive this signal low whenever its internal
   "disk change" latch is set. This latch is set when the drive is first
   powered on, or whenever there is no diskette in the drive. To reset
   the latch, the system must select the drive, and step the head. Of
   course, the latch will not reset if there is no diskette installed.

MTRXD- (Pin #8)

   This is the motor control line for all four disk drives. When the
   system wants to turn on a disk drive motor, it first deselects the
   drive (if selected), pulls MTRXD- low, and selects the drive. To turn
   the motor off, the system deselects the drive, pulls MTRXD- high, and
   selects the drive. The system will always set MTRXD- at least 1.4
   microseconds before it selects the drive, and will not change MTRXD-
   for at least 1.4 microseconds after selecting the drive. All external
   drives must have logic equivalent to a D flip-flop, whose D input is
   the MTRXD- signal, and whose clock input is activated by the
   off-to-on (high-to-low) transition of its SELxB- signal. As noted
   above, both the setup and hold times of MTRXD- with respect to SELxB-
   will always be at least 1.4 microseconds. The output of this
   flip-flop controls the disk drive motor. Thus, the system can control
   all four motors using only one signal on the cable (MTRXD-).

DRESB- (Pin #10)

   This signal is a buffered version of the system reset signal. Three
   things can make it go active (low):

   *  System power-up (DRESB- will go low for approximately one
      second);

   *  System CPU executes a  RESET  instruction (DRESB- will go low for
      approximately 17 microseconds);

   *   Hard reset  from keyboard (lasts as long as keyboard reset is
      held down).

   External disk drives should respond to DRESB- by shutting off their
   motor flip-flops and write protecting themselves.

A level of 3.75v or below on the 5v+ requires external disks to
write-protect and reset the motor on line.


H External Disk Connector Interface / Device I.D.

This interface supports a method of establishing the type of disk(s)
attached. The I.D. sequence is as follows.

  1. Drive  MTRXD-  low: Turn on the disk drive motor.
  2. Drive  SELxB-  low: Activate drive select x, where x is the number of
       the selected drive.
  3. Drive  SELxB-  high: Deactivate drive select x..
  4. Drive  MTRXD-  high: Turn off disk drive motor.
  5. Drive  SELxB-  low: Activate drive select x.
  6. Drive  SELxB-  high: Deactivate drive select x.
  7. Drive  SELxB-  low: Activate drive select x.
  8. Read and save state of  RDY .
  9. Drive  SELxB-  high: Deactivate drive select x.

Repeat steps 7 through 9, 31 more times for a total of 32 iterations, in
order to read 32 bits of data. The most significant bit is read first.

Steps 1 through 4 in the algorithm above turn on and off the disk drive
motor. This initializes the  serial shift register . After initialization,
the  SELxB  signal is driven (first active then) inactive as in steps 5
and 6. Keep in mind that the  SELxB  signal is active-low.

Steps 7, 8 and 9 form a loop where (7) the  SELxB  signal is driven active
(low), (8) the serial input data is read on  RDY  (pin 1) and (9) the
 SELxB  signal is again driven high (inactive).  This loop is performed 32
times, once for each of the bits in the input stream that comprise the
device I.D.

Convert the 32 values of  RDY-  into a two 16-bit word. The most
significant bit is the first value and so on. This 32-bit quantity is the
device I.D..

The following I.D.s are defined:

  0000 0000 0000 0000 0000 0000 0000 0000  Reserved ($0000 0000)
  1111 1111 1111 1111 1111 1111 1111 1111  Amiga standard 3.25($FFFF FFFF)
  1010 1010 1010 1010 1010 1010 1010 1010  Reserved ($AAAA AAAA)
  0101 0101 0101 0101 0101 0101 0101 0101  48 TPI double-density,
                                           double-sided ($5555 5555)
  1000 0000 0000 0000 1000 0000 0000 0000  Reserved ($8000 8000)
  0111 1111 1111 1111 0111 1111 1111 1111  Reserved ($7FFF 7FFF)
  0000 1111 xxxx xxxx 0000 1111 xxxx xxxx  Available for users ($0Fxx 0Fxx)
  1111 0000 xxxx xxxx 1111 0000 xxxx xxxx  Extension reserved ($F0xx F0xx)
  xxxx 0000 0000 0000 xxxx 0000 0000 0000  Reserved ($x000 x000)
  xxxx 1111 1111 1111 xxxx 1111 1111 1111  Reserved ($x000 x000)
  0011 0011 0011 0011 0011 0011 0011 0011  Reserved ($3333 3333)
  1100 1100 1100 1100 1100 1100 1100 1100  Reserved ($CCCC CCCC)


Hard_examples/hw_examples.i

;
; hw_examples.i
;
; This appendix contains an include file that maps the hardware
; register names, given in Appendix A and Appendix B, to names that can
; be resolved by the standard include files. Use of these names in code
; sections of this manual places the emphasis on what the code is
; doing, rather than getting bogged down in include file names.
;
; All code examples in this manual reference the names given in this
; file.
;
                        IFND    HARDWARE_HW_EXAMPLES_I
HARDWARE_HW_EXAMPLES_I  SET     1
**
**       Filename: hardware/hw_examples.i
**      $Release: 1.3 $
**
**      (C) Copyright 1985-1999 Amiga, Inc.
**          All Rights Reserved
**
*******************************************************************************

        IFND    HARDWARE_CUSTOM_I
        INCLUDE "hardware/custom.i"
        ENDC

*******************************************************************************
*
*  This include file is designed to be used in conjunction with the hardware
*  manual examples.  This file defines the register names based on the
*  hardware/custom.i definition file.  There is no C-Language version of this
*  file.
*
*******************************************************************************
*
* This instruction for the copper will cause it to wait forever since
* the wait command described in it will never happen.
*
COPPER_HALT     equ     $FFFFFFFE
*
*******************************************************************************
*
* This is the offset in the 680x0 address space to the custom chip registers
* It is the same as  _custom  when linking with AMIGA.lib
*
CUSTOM          equ     $DFF000
*
* Various control registers
*
DMACONR         equ     dmaconr         ; Just capitalization...
VPOSR           equ     vposr           ;  "         "
VHPOSR          equ     vhposr          ;  "         "
JOY0DAT         equ     joy0dat         ;  "         "
JOY1DAT         equ     joy1dat         ;  "         "
CLXDAT          equ     clxdat          ;  "         "
ADKCONR         equ     adkconr         ;  "         "
POT0DAT         equ     pot0dat         ;  "         "
POT1DAT         equ     pot1dat         ;  "         "
POTINP          equ     potinp          ;  "         "
SERDATR         equ     serdatr         ;  "         "
INTENAR         equ     intenar         ;  "         "
INTREQR         equ     intreqr         ;  "         "
REFPTR          equ     refptr          ;  "         "
VPOSW           equ     vposw           ;  "         "
VHPOSW          equ     vhposw          ;  "         "
SERDAT          equ     serdat          ;  "         "
SERPER          equ     serper          ;  "         "
POTGO           equ     potgo           ;  "         "
JOYTEST         equ     joytest         ;  "         "
STREQU          equ     strequ          ;  "         "
STRVBL          equ     strvbl          ;  "         "
STRHOR          equ     strhor          ;  "         "
STRLONG         equ     strlong         ;  "         "
DIWSTRT         equ     diwstrt         ;  "         "
DIWSTOP         equ     diwstop         ;  "         "
DDFSTRT         equ     ddfstrt         ;  "         "
DDFSTOP         equ     ddfstop         ;  "         "
DMACON          equ     dmacon          ;  "         "
INTENA          equ     intena          ;  "         "
INTREQ          equ     intreq          ;  "         "
*
* Disk control registers
*
DSKBYTR         equ     dskbytr         ; Just capitalization...
DSKPT           equ     dskpt           ;  "         "
DSKPTH          equ     dskpt
DSKPTL          equ     dskpt+$02
DSKLEN          equ     dsklen          ;  "         "
DSKDAT          equ     dskdat          ;  "         "
DSKSYNC         equ     dsksync         ;  "         "
*
* Blitter registers
*
BLTCON0         equ     bltcon0         ; Just capitalization...
BLTCON1         equ     bltcon1         ;  "         "
BLTAFWM         equ     bltafwm         ;  "         "
BLTALWM         equ     bltalwm         ;  "         "
BLTCPT          equ     bltcpt          ;  "         "
BLTCPTH         equ     bltcpt
BLTCPTL         equ     bltcpt+$02
BLTBPT          equ     bltbpt          ;  "         "
BLTBPTH         equ     bltbpt
BLTBPTL         equ     bltbpt+$02
BLTAPT          equ     bltapt          ;  "         "
BLTAPTH         equ     bltapt
BLTAPTL         equ     bltapt+$02
BLTDPT          equ     bltdpt          ;  "         "
BLTDPTH         equ     bltdpt
BLTDPTL         equ     bltdpt+$02
BLTSIZE         equ     bltsize         ;  "         "
BLTCMOD         equ     bltcmod         ;  "         "
BLTBMOD         equ     bltbmod         ;  "         "
BLTAMOD         equ     bltamod         ;  "         "
BLTDMOD         equ     bltdmod         ;  "         "
BLTCDAT         equ     bltcdat         ;  "         "
BLTBDAT         equ     bltbdat         ;  "         "
BLTADAT         equ     bltadat         ;  "         "
BLTDDAT         equ     bltddat         ;  "         "
*
* Copper control registers
*
COPCON          equ     copcon          ; Just capitalization...
COPINS          equ     copins          ;  "         "
COPJMP1         equ     copjmp1         ;  "         "
COPJMP2         equ     copjmp2         ;  "         "
COP1LC          equ     cop1lc          ;  "         "
COP1LCH         equ     cop1lc
COP1LCL         equ     cop1lc+$02
COP2LC          equ     cop2lc          ;  "         "
COP2LCH         equ     cop2lc
COP2LCL         equ     cop2lc+$02
*
*
* Audio channel registers
*
ADKCON          equ     adkcon          ; Just capitalization...

AUD0LC          equ     aud0
AUD0LCH         equ     aud0
AUD0LCL         equ     aud0+$02
AUD0LEN         equ     aud0+$04
AUD0PER         equ     aud0+$06
AUD0VOL         equ     aud0+$08
AUD0DAT         equ     aud0+$0A

AUD1LC          equ     aud1
AUD1LCH         equ     aud1
AUD1LCL         equ     aud1+$02
AUD1LEN         equ     aud1+$04
AUD1PER         equ     aud1+$06
AUD1VOL         equ     aud1+$08
AUD1DAT         equ     aud1+$0A

AUD2LC          equ     aud2
AUD2LCH         equ     aud2
AUD2LCL         equ     aud2+$02
AUD2LEN         equ     aud2+$04
AUD2PER         equ     aud2+$06
AUD2VOL         equ     aud2+$08
AUD2DAT         equ     aud2+$0A

AUD3LC          equ     aud3
AUD3LCH         equ     aud3
AUD3LCL         equ     aud3+$02
AUD3LEN         equ     aud3+$04
AUD3PER         equ     aud3+$06
AUD3VOL         equ     aud3+$08
AUD3DAT         equ     aud3+$0A
*
*
*  The bitplane registers
*
BPL1PT          equ     bplpt+$00
BPL1PTH         equ     bplpt+$00
BPL1PTL         equ     bplpt+$02
BPL2PT          equ     bplpt+$04
BPL2PTH         equ     bplpt+$04
BPL2PTL         equ     bplpt+$06
BPL3PT          equ     bplpt+$08
BPL3PTH         equ     bplpt+$08
BPL3PTL         equ     bplpt+$0A
BPL4PT          equ     bplpt+$0C
BPL4PTH         equ     bplpt+$0C
BPL4PTL         equ     bplpt+$0E
BPL5PT          equ     bplpt+$10
BPL5PTH         equ     bplpt+$10
BPL5PTL         equ     bplpt+$12
BPL6PT          equ     bplpt+$14
BPL6PTH         equ     bplpt+$14
BPL6PTL         equ     bplpt+$16

BPLCON0         equ     bplcon0         ; Just capitalization...
BPLCON1         equ     bplcon1         ;  "         "
BPLCON2         equ     bplcon2         ;  "         "
BPL1MOD         equ     bpl1mod         ;  "         "
BPL2MOD         equ     bpl2mod         ;  "         "

DPL1DATA        equ     bpldat+$00
DPL2DATA        equ     bpldat+$02
DPL3DATA        equ     bpldat+$04
DPL4DATA        equ     bpldat+$06
DPL5DATA        equ     bpldat+$08
DPL6DATA        equ     bpldat+$0A
*
*
* Sprite control registers
*
SPR0PT          equ     sprpt+$00
SPR0PTH         equ     SPR0PT+$00
SPR0PTL         equ     SPR0PT+$02
SPR1PT          equ     sprpt+$04
SPR1PTH         equ     SPR1PT+$00
SPR1PTL         equ     SPR1PT+$02
SPR2PT          equ     sprpt+$08
SPR2PTH         equ     SPR2PT+$00
SPR2PTL         equ     SPR2PT+$02
SPR3PT          equ     sprpt+$0C
SPR3PTH         equ     SPR3PT+$00
SPR3PTL         equ     SPR3PT+$02
SPR4PT          equ     sprpt+$10
SPR4PTH         equ     SPR4PT+$00
SPR4PTL         equ     SPR4PT+$02
SPR5PT          equ     sprpt+$14
SPR5PTH         equ     SPR5PT+$00
SPR5PTL         equ     SPR5PT+$02
SPR6PT          equ     sprpt+$18
SPR6PTH         equ     SPR6PT+$00
SPR6PTL         equ     SPR6PT+$02
SPR7PT          equ     sprpt+$1C
SPR7PTH         equ     SPR7PT+$00
SPR7PTL         equ     SPR7PT+$02
;
; Note:  SPRxDATB is defined as being +$06 from SPRxPOS.
; sd_datab should be defined as $06, however, in the 1.3 assembler
; include file hardware/custom.i it is incorrectly defined as $08.
;
SPR0POS         equ     spr+$00
SPR0CTL         equ     SPR0POS+sd_ctl
SPR0DATA        equ     SPR0POS+sd_dataa
SPR0DATB        equ     SPR0POS+$06     ; should use sd_datab ...

SPR1POS         equ     spr+$08
SPR1CTL         equ     SPR1POS+sd_ctl
SPR1DATA        equ     SPR1POS+sd_dataa
SPR1DATB        equ     SPR1POS+$06     ; should use sd_datab ...

SPR2POS         equ     spr+$10
SPR2CTL         equ     SPR2POS+sd_ctl
SPR2DATA        equ     SPR2POS+sd_dataa
SPR2DATB        equ     SPR2POS+$06     ; should use sd_datab ...

SPR3POS         equ     spr+$18
SPR3CTL         equ     SPR3POS+sd_ctl
SPR3DATA        equ     SPR3POS+sd_dataa
SPR3DATB        equ     SPR3POS+$06     ; should use sd_datab ...

SPR4POS         equ     spr+$20
SPR4CTL         equ     SPR4POS+sd_ctl
SPR4DATA        equ     SPR4POS+sd_dataa
SPR4DATB        equ     SPR4POS+$06     ; should use sd_datab ...

SPR5POS         equ     spr+$28
SPR5CTL         equ     SPR5POS+sd_ctl
SPR5DATA        equ     SPR5POS+sd_dataa
SPR5DATB        equ     SPR5POS+$06     ; should use sd_datab ...

SPR6POS         equ     spr+$30
SPR6CTL         equ     SPR6POS+sd_ctl
SPR6DATA        equ     SPR6POS+sd_dataa
SPR6DATB        equ     SPR6POS+$06     ; should use sd_datab ...

SPR7POS         equ     spr+$38
SPR7CTL         equ     SPR7POS+sd_ctl
SPR7DATA        equ     SPR7POS+sd_dataa
SPR7DATB        equ     SPR7POS+$06     ; should use sd_datab ...
*
* Color registers...
*
COLOR00         equ     color+$00
COLOR01         equ     color+$02
COLOR02         equ     color+$04
COLOR03         equ     color+$06
COLOR04         equ     color+$08
COLOR05         equ     color+$0A
COLOR06         equ     color+$0C
COLOR07         equ     color+$0E
COLOR08         equ     color+$10
COLOR09         equ     color+$12
COLOR10         equ     color+$14
COLOR11         equ     color+$16
COLOR12         equ     color+$18
COLOR13         equ     color+$1A
COLOR14         equ     color+$1C
COLOR15         equ     color+$1E
COLOR16         equ     color+$20
COLOR17         equ     color+$22
COLOR18         equ     color+$24
COLOR19         equ     color+$26
COLOR20         equ     color+$28
COLOR21         equ     color+$2A
COLOR22         equ     color+$2C
COLOR23         equ     color+$2E
COLOR24         equ     color+$30
COLOR25         equ     color+$32
COLOR26         equ     color+$34
COLOR27         equ     color+$36
COLOR28         equ     color+$38
COLOR29         equ     color+$3A
COLOR30         equ     color+$3C
COLOR31         equ     color+$3E

*******************************************************************************
**
**
                        ENDC    ; HARDWARE_HW_EXAMPLES_I


Amiga® Hardware Reference Manual: List of Figures

 Figure 1-1: Block Diagram for the Amiga Computer Family
 Figure 2-1: Interlaced Bitplane in RAM
 Figure 3-1: How the Video Display Picture Is Produced
 Figure 3-2: What Is a Pixel?
 Figure 3-3: How Bitplanes Select a Color
 Figure 3-4: Significance of Bitplane Data in Selecting Colors
 Figure 3-5: Interlacing
 Figure 3-6: Effect of Interlaced Mode on Edges of Objects
 Figure 3-7: Memory Organization for a Basic Bitplane
 Figure 3-8: Combining Bitplanes
 Figure 3-9: Positioning the On-screen Display
 Figure 3-10: Data Fetched for the First Line When Modulo = 0
 Figure 3-11: Data Fetched for the Second Line When Modulo = 0
 Figure 3-12: A Dual-playfield Display
 Figure 3-13: How Bitplanes Are Assigned to Dual Playfields
 Figure 3-14: Memory Picture Larger than the Display
 Figure 3-15: Data Fetch for the First Line When Modulo = 40
 Figure 3-16: Data Fetch for the Second Line When Modulo = 40
 Figure 3-17: Data Layout for First Line -- Right Half of Big Picture
 Figure 3-18: Data Layout for Second Line -- Right Half of Big Picture
 Figure 3-19: Display Window Horizontal Starting Position
 Figure 3-20: Display Window Vertical Starting Position
 Figure 3-21: Display Window Horizontal Stopping Position
 Figure 3-22: Display Window Vertical Stopping Position
 Figure 3-23: Vertical Scrolling
 Figure 3-24: Horizontal Scrolling
 Figure 3-25: Memory Picture Larger Than the Display Window
 Figure 3-26: Data for Line 1 - Horizontal Scrolling
 Figure 3-27: Data for Line 2 - Horizontal Scrolling
 Figure 4-1: Defining Sprite On-screen Position
 Figure 4-2: Position of Sprites
 Figure 4-3: Shape of Spaceship
 Figure 4-4: Sprite with Spaceship Shape Defined
 Figure 4-5: Sprite Color Definition
 Figure 4-6: Color Register Assignments
 Figure 4-7: Data Structure Layout
 Figure 4-8: Sprite Priority
 Figure 4-9: Typical Example of Sprite Reuse
 Figure 4-10: Typical Data Structure for Sprite Re-use
 Figure 4-11: Overlapping Sprites (Not Attached)
 Figure 4-12: Placing Sprites Next to Each Other
 Figure 4-13: Sprite Control Circuitry
 Figure 5-1: Sine Waveform
 Figure 5-2: Digitized Amplitude Values
 Figure 5-3: Example Sine Wave
 Figure 5-4: Waveform with Multiple Cycles
 Figure 5-5: Frequency Domain Plot of Low-Pass Filter
 Figure 5-6: Noise-free Output (No Aliasing Distortion)
 Figure 5-7: Some Aliasing Distortion
 Figure 5-8: Audio State Diagram
 Figure 6-1: How Images are Stored in Memory
 Figure 6-2: BLTxPTR and BLTxMOD calculations
 Figure 6-3: Blitter Minterm Venn Diagram
 Figure 6-4: Extracting a Range of Columns
 Figure 6-5: Use of the FCI Bit - Bit Is a 0
 Figure 6-6: Use of the FCI Bit - Bit Is a 1
 Figure 6-7: Single-Point Vertex Example
 Figure 6-8: Octants for Line Drawing
 Figure 6-9: DMA Time Slot Allocation
 Figure 6-10: Normal 68000 Cycle
 Figure 6-11: Time Slots Used by a Six Bitplane Display
 Figure 6-12: Time Slots Used by a High Resolution Display
 Figure 6-13: Blitter Block Diagram
 Figure 7-1: Inter-Sprite Fixed Priorities
 Figure 7-2: Analogy for Video Priority
 Figure 7-3: Sprite/Playfield Priority
 Figure 7-4: Interrupt Priorities
 Figure 8-1: Controller Plug and Computer Connector
 Figure 8-2: Mouse Quadrature
 Figure 8-3: Joystick to Counter Connections
 Figure 8-4: Typical Paddle Wiring Diagram
 Figure 8-5: Effects of Resistance on Charging Rate
 Figure 8-6: Potentiometer Charging Circuit
 Figure 8-7: Chinon Write Timing Diagram
 Figure 8-8: Chinon Access Timing Diagram
 Figure 8-9: Chinon Read Timing Diagram
 Figure 8-10: The Amiga 1000 Keyboard
 Figure 8-11: The Amiga 500/2000/3000 Keyboard
 Figure 8-12: Starting Appearance of SERDAT and Shift Register
 Figure 8-13: Ending Appearance of Shift Register
 Figure D-1: Amiga 3000 Memory Map
 Figure E-1: Reading Fire Buttons
 Figure E-2: Pot Counters
 Figure E-3: Light Pen
 Figure K-1: Expansion Memory Map
 Figure K-2: A2000 vs A3000 Bus Termination
 Figure K-3: Expansion Bus Clocks
 Figure K-4: Zorro II Bus Arbitration
 Figure k-5: Basic Zorro III Cycle
 Figure K-6: Multiple Transfer Cycles
 Figure K-7: Zorro III Bus Arbitration
 Figure K-8: Interrupt Vector Cycle
 Figure K-9: Zorro II Within Zorro III
 Figure K-10: Read Cycle Timing
 Figure K-11: Write Cycle Timing
 Figure K-12: Multiple Transfer Cycle Timing
 Figure K-13: Quick Interrupt Cycle Timing
 Figure K-14: Basic Zorro III Pic
 Figure K-15: Pic with ISA Option
 Figure K-16: Pic with Video Option
 Figure K-17: Configuration Register Map


Amiga® Hardware Reference Manual: Glossary

A                                         I
 address                                   interlace mode
 Agnus                                     interrupt
 aliasing distortion                      J
 Alt keys                                  joystick
 Amiga keys                               L
 AmigaDOS                                  light pen
 amplitude                                 local bus
 amplitude modulation                      longword
 arbitration                               low
 asserted                                  low resolution (Lores)
 atomic cycle                             M
 attach mode                               manual mode
 AUTOCONFIG(TM)                            master
 automatic mode                            MIDI
B                                          microsecond (us)
 backplane                                 millisecond (ms)
 barrel shifter                            minterm
 baud rate                                 modulo
 beam counters                             motherboard
 bitmap                                    mouse
 bitplane                                  multitasking
 bitplane animation                       N
 blanking interval                         nanosecond (ns)
 blitter                                   negated
 burst                                     non-interlaced mode
 bus cycle                                 NTSC
 bus hogging                               nybble
 bus starvation                           O
 byte                                      overscan area
C                                         P
 Chip RAM                                  paddle controller
 clear                                     PAL
 CLI                                       parallel port
 clipping                                  Paula
 clock                                     PIC
 collision                                 pitch
 color descriptor words                    pixels
 color indirection                         playfield
 color palette                             playfield object
 color register                            playfield animation
 color table                               pointer register
 Command Line Interface (Shell or CLI)     polarity
 composite video                           potentiometer
 controller                               Q
 coordinates                               quantization noise
 copper                                   R
 coprocessor                               RAM
 cursor keys                               raster
 cycle strobe                              read-only
D                                          request
 data                                      resolution
 data fetch                                ROM
 delay                                    S
 Denise                                    sample
 depth                                     sampling rate
 device                                    sampling period
 Digital-to-Analog Converter (DAC)         scroll
 Direct Memory Access (DMA)                SCSI
 display field                             serial port
 display mode                              set
 display time                              Shell
 display window                            slave
 DMA                                       slot
 DMA latency                               sprite
 dual-playfield mode                       strobe address
E                                         T
 Enhanced Chip Set (ECS)                   task
 equal-tempered scale                      termination
 Exec                                      timbre
F                                          timeout
 Fast RAM                                  transparent
 font                                      tri-state
 frequency                                U
 frequency modulation                      UART
G                                         V
 genlock                                   video priority
 grant                                     video display
H                                         W
 HAM                                       write-only
 hidden cycles                             word
 high                                     Z
 high resolution (Hires)                   Zorro
 hold-and-modify (HAM)


Glossary / address

A byte-numbered memory location.  The Zorro II bus is based on a 24-bit
address, the Zorro III bus on a 32-bit address.


Glossary / Agnus

One of the three main Amiga custom chips.  Contains the blitter, copper,
and DMA circuitry.


Glossary / aliasing distortion

A side effect of sound sampling, where two additional frequencies are
produced, distorting the sound output.


Glossary / Alt keys

Two keys on the keyboard to the left and right of the Amiga keys.


Glossary / Amiga keys

Two keys on the keyboard to the left and right of the space bar.


Glossary / AmigaDOS

The disk operating system (DOS) used by Amiga computers.


Glossary / amplitude

In audio applications, the voltage or current output expressed as volume
from a sound speaker.


Glossary / amplitude modulation

In audio applications, a means of producing complex audio effects by using
one audio channel to alter the amplitude of another.


Glossary / arbitration

The unambiguous selection of one request out of a number of possible
simultaneous requests for a resource.  There are two kinds of arbitration
in a Zorro III system; bus arbitration and quick interrupt arbitration.


Glossary / asserted

The active state of a state, regardless of its logic sense.


Glossary / atomic cycle

A cycle or set of cycles that are uninterruptable, and thus treated as a
unit; both Multiple Transfer and LOCKed cycles are considered atomic under
the Zorro III bus.


Glossary / attach mode

1. With sprites, a mode in which a sprite uses two DMA channels for
additional colors.   2. In sound production, combining two audio channels
for frequency/amplitude modulation or for stereo sound.


Glossary / AUTOCONFIG(TM)

>From "automatic configuration," the Zorro bus specification for how
software and hardware cooperate to permit PIC addresses to be set by
software and PIC type information to be determined by software.


Glossary / automatic mode

1. With sprites, the normal mode in which the sprite DMA channel
automatically retrieves and displays all of the data for a sprite.   2. In
audio applications, the normal mode in which the audio DMA channels
automatically retrieve sound data.


Glossary / backplane

The cage or motherboard subsection into which PICs are inserted.  The
Amiga 2000 and Amiga 3000 computers have integral backplanes, the Amiga
500 and Amiga 1000 computers require add-on backplane cages for Zorro II
compatibility.


Glossary / barrel shifter

Blitter circuit that allows movement of images on pixel boundaries.


Glossary / baud rate

Rate of data transmission through a serial port.


Glossary / beam counters

Registers that keep track of the position of the video beam.


Glossary / bitmap

An image made up of pixels.  A bitmap is a complete definition for a video
display consisting of one or more bitplanes stored in memory.


Glossary / bitplane

A contiguous area of memory set aside for the video display and logically
organized as if it were a rectangular shape.  All displays consist of one
or more bitplanes; each additional bitplane doubles the number of colors
that can be displayed.


Glossary / bitplane animation

A means of animating the display by moving around blocks of playfield data
with the blitter.


Glossary / blanking interval

Time period when the video beam is outside the display area.


Glossary / blitter

An Amiga coprocessor with its own DMA channel used for data copying and
line drawing.


Glossary / burst

A short name for Multiple Transfer Cycle mode.  Essentially, within one
full Zorro III cycle there can be any number of Multiple Transfer Cycles.
Each full cycle has a complete 32-bit address supplied and a complete
32-bit datum transferred.  Each burst cycle supplies only the 8-bit page
address, but transfers a complete 32-bit datum faster than the standard
full cycle would allow.


Glossary / bus cycle

One complete bus transaction, indicated by the assertion of at least one
cycle strobe.  For any single bus cycle, there is one address, one data
value, one data direction, and one cycle type in effect.


Glossary / bus hogging

When a bus master takes over the bus for an undue amount of time.  The
Zorro II bus leaves it completely up to the individual PIC to avoid bus
hogging; the Zorro III bus schedules PICs with the bus controller to
evenly distribute the bus load.


Glossary / bus starvation

When a master can't get access to the bus, it is said to be starved.  On
the Zorro II bus, two busy masters can completely starve a third master.
Complete starvation is impossible on the Zorro III bus, though a bus
hogging Zorro II card can cause similar symptoms.


Glossary / byte

A collection of eight signals into a logical group, and the smallest
independently addressable quantity on the Zorro bus.


Glossary / Chip RAM

The area of memory accessible to the Amiga's custom chip set used for
graphics and sound data.  The amount of Chip RAM varies from 512K to 2
megabytes depending on the Amiga model.  See  Fast RAM .


Glossary / clear

1. To change a bit or flag to 0, its off or disabled state. Opposite of
set.   2. To erase a screen or window display.


Glossary / clipping

When a portion of a sprite is outside the display window and thus is not
visible.


Glossary / clock

A free running signal driven at a fixed frequency to the bus, used mainly
for clocking state machines on Zorro II cards.


Glossary / collision

A means of detecting when sprites, playfields, or playfield objects
attempt to overlap in the same pixel position or attempt to cross some
pre-defined boundary.


Glossary / color descriptor words

Pairs of words that define each line of a sprite.


Glossary / color indirection

The method used by the Amiga for coloring individual pixels.  For each
pixel, a binary number is formed from corresponding bits in each bitplane
which refers to one of the 32 color registers.


Glossary / color register

One of 32 hardware registers containing colors that you can define.  In
general, each color register can be set to one of 4,096 colors from the
Amiga's palette.


Glossary / color table

The set of 32 color registers.


Glossary / Command Line Interface (Shell or CLI)

A means of communicating with a computer by typing commands at the
keyboard. On the Amiga, this is called the Shell and, along with Workbench
and ARexx, is one of the three built-in user interfaces.  Before the Shell
was available, this interface was called the CLI.


Glossary / composite video

A video signal, transmitted over a single coaxial cable, which includes
both picture and sync information.


Glossary / controller

Hardware device, such as a mouse, joystick, or light pen, used to move the
pointer or furnish other input to the system.


Glossary / coordinates

A pair of numbers shown in the form (x,y), where x is an offset from the
left side of the display or display window and y is an offset from the top.


Glossary / copper

Display-synchronized coprocessor that resides on one of the Amiga custom
chips and directs the graphics display.


Glossary / coprocessor

An extra processor that enhances system performance by doing a specialized
task, such as graphics or math, very quickly.  This frees the main
processor to do other work.  Every Amiga has at least three coprocessor
chips named Paula, Agnus, and Denise to handle graphics and audio.


Glossary / cursor keys

The four keys with directional arrows on them (found below the Del and
Help keys on the Amiga).


Glossary / cycle strobe

A bus signal that defines the boundary of a bus cycle; the Zorro II and
Zorro III modes on a Zorro III bus each have their own cycle strobes.  The
current bus master always asserts the cycle strobes.


Glossary / data

The contents of a memory location.  The main purpose of a bus cycle is to
transfer data between two locations.  The Zorro II bus is based on a
16-bit data path, the Zorro III bus is based on a 32-bit data path.


Glossary / data fetch

The number of words fetched for each line of the display.


Glossary / delay

In playfield horizontal scrolling, specifies how many pixels the picture
will shift for each display field.  Delay controls the speed of scrolling.


Glossary / Denise

One of the three main Amiga custom chips.  Contains the circuitry for the
color pallete, sprites, and video output.


Glossary / depth

Number of bitplanes in a display.  Each additional bitplane doubles the
number of colors that can be displayed.


Glossary / device

A PIC; e.g., a Zorro bus master or bus slave.


Glossary / Digital-to-Analog Converter (DAC)

A device that converts a binary quantity to an analog level.


Glossary / Direct Memory Access (DMA)

.nh An arrangement that allows coprocessors or other system devices to
read or write memory directly, without having to interrupt the main
processor. Devices that have direct access to Zorro III slaves are said to
have DMA capability.  These devices are also called masters. .hy 14


Glossary / display field

One complete scanning of the video beam from top to bottom of the video
display screen.


Glossary / display mode

One of the basic types of display; for example, high or low resolution,
interlaced or non-interlaced, single or dual playfield.


Glossary / display time

The amount of time to produce one display field, approximately 1/60th of a
second.


Glossary / display window

The portion of the bitmap selected for display. Also, the actual size of
the on-screen display.


Glossary / DMA latency

This is the time between a bus request and a bus grant as seen by a PIC
wishing to become bus master.


Glossary / dual-playfield mode

A display mode that allows you to manage two separate display memories,
giving you two separately controllable displays at the same time.


Glossary / Enhanced Chip Set (ECS)

The upgraded versions of the Amiga's Agnus and Denise coprocessor chips.
The ECS offers new display modes and expands the Amiga's graphic
capabilities. Many of the benefits of the ECS are available only in
conjunction with Release 2 of the operating system.


Glossary / equal-tempered scale

A musical scale in which the frequency of each tone is the 12th root of 2
higher than the tone below it.  The equal-tempered scale is used in almost
all musical styles.


Glossary / Exec

The Amiga system module which manages memory and performs other important
low-level tasks.


Glossary / Fast RAM

General-purpose memory used for programs and data; as opposed to Chip RAM.


Glossary / font

A set of letters, numbers, and symbols sharing the same size and design.


Glossary / frequency

In audio applications, the number of times per second a waveform repeats.


Glossary / frequency modulation

In audio applications, a means of producing complex sounds by using one
audio channel to affect the period of the waveform produced by another
channel.


Glossary / genlock

An optional feature of the Amiga that allows you to combine an external
video source with Amiga's graphic display.


Glossary / grant

The result of an arbitrated set of requests is a single grant; there are
grants given for both the bus and quick interrupts.


Glossary / hidden cycles

Cycles that occur on the local bus of a system, but can't be seen by
devices on the expansion bus.


Glossary / high

A signal driven to a logical +5V state is said to be high.


Glossary / high resolution (Hires)

A horizontal display mode in which 640 pixels are displayed across a
horizontal line in a normal-sized display.  On the Amiga a high resolution
display is often called Hires.


Glossary / hold-and-modify (HAM)

A display mode that gives you extended color selection.  Normally, the
Amiga supports up to 32 different colors from a palette of 4,096.
Hold-and-modify (HAM mode) allows all 4,096 colors on the screen at one
time by placing some restrictions on which colors may be displayed near
each other.


Glossary / interlace mode

A vertical display mode where 400 lines are displayed from top to bottom
of the video display in a normal-size display.


Glossary / interrupt

An asynchronous line driven by a PIC to notify the CPU of some event,
usually some hardware event governed by that PIC.


Glossary / joystick

A controller device with a handle that swings up, down, left, or right,
used to position something on the screen.


Glossary / light pen

A controller device consisting of a stylus and tablet used for drawing
something on the screen.


Glossary / local bus

The main system bus of an Amiga computer is called the local bus.  In
general, the main CPU, video chips, chip memory, and any other built-in
resources are on the local bus.  The bus controller sits on both the local
and expansion buses and manages the communications between them.


Glossary / longword

Based on the Motorola conventions, a longword is equal to 4 bytes.


Glossary / low

A signal driven to a logical +0V state is said to be low.


Glossary / low resolution (Lores)

A horizontal display mode in which 320 pixels are displayed across a
horizontal line in a normal-sized display. On the Amiga, a low resolution
display is often called Lores.


Glossary / manual mode

Non-DMA output.  In sprites, a mode in which each line of a sprite is
written in a separate operation.  In audio applications, a mode in which
audio data words are written one at a time to the output channel.


Glossary / master

The device currently generating addresses for the expansion bus.  There is
only one master on the bus at a time, this being insured by the bus
arbitration logic.  The master also drives data on writes, the read,
cycle, and data strobes, and several other signals.


Glossary / MIDI

A communications standard which allows electronic music devices to share
information.  MIDI stands for Musical Instrument Digital Interface and is
endorsed by the majority of musical instrument manufacturers.


Glossary / microsecond (us)

One millionth of second (1/1,000,000).


Glossary / millisecond (ms)

One thousandth of second (1/1,000).


Glossary / minterm

One of eight possible logical combinations of data bits from three
different data sources.


Glossary / modulo

A number defining which data in memory belongs on each horizontal line of
the display.  Refers to the number of bytes in memory between the last
word on one horizontal line and the beginning of the first word on the
next line.


Glossary / motherboard

The main system circuit board for any Amiga computer.  Resources on the
local bus of a machine are often called motherboard resources.


Glossary / mouse

A controller device that can be rolled around to move something on the
screen; also has buttons to give other forms of input.


Glossary / multitasking

The ability to perform more than one operation, or task, at a time.


Glossary / nanosecond (ns)

One billionth of a second  (1/1,000,000,000).


Glossary / negated

The inactive state of a signal, regardless of its logic sense.


Glossary / non-interlaced mode

A display mode in which 200 lines are displayed from top to bottom of the
video display in a normal-sized display.


Glossary / NTSC

Short for National Television Standards Committee specification for
composite video.  NTSC is the standard used for video broadcasting in the
US.  Other video standards include PAL, used widely in Europe, and SECAM.
When the Amiga is operating in an NTSC environment, the base crytal
frequency is 28.63636 MHz.


Glossary / nybble

A collection of four bits; one half of a byte. AUTOCONFIG(TM) ROMs are
physically nybble-wide.


Glossary / overscan area

The normally unused area surrounding a standard-size computer display. The
overscan area is important in video applications.


Glossary / paddle controller

A game controller that uses a potentiometer (variable resistor) to
position objects on the screen.


Glossary / PAL

Short for Phase Alternate Line.  PAL is the video broadcast standard
widely used in Europe.  Although PAL is similar to the NTSC standard used
in the US, the two systems are incompatible.  Under PAL, the base Amiga
crystal frequency is 28.37516 Mhz.


Glossary / parallel port

A connector on the back of the Amiga that allows extra equipment such as a
printer to be attached.  The parallel port transfers data one complete
byte (8 bits) at a time, in contrast to the serial port which sends a
single bit at a time.


Glossary / Paula

One of the three main Amiga custom chips, Paula contains audio, disk, and
interrupt circuitry.


Glossary / PIC

Plug-In Card.  Any Amiga expansion card is called a PIC for short.


Glossary / pitch

1. The quality of a sound expressed as its highness or lowness.   2. The
number of characters printed in a horizontal inch.


Glossary / pixels

The dots of light that make up the Amiga screen display.  A pixel is the
smallest unit of of display information for a given screen.


Glossary / playfield

The background for all the other display elements on the Amiga.
Playfields provide the hardware-level logic for creating the Amiga's
display.


Glossary / playfield object

Subsection of a playfield that is used in playfield animation.


Glossary / pointer register

Register that is continuously incremented to point to a series of memory
locations.


Glossary / polarity

True or false state of a bit.


Glossary / potentiometer

An electrical analog device used to adjust some variable value.


Glossary / quantization noise

In audio applications, noise introduced by round-off errors when you are
trying to reproduce a signal by approximation.


Glossary / RAM

Short for random access memory.  RAM is the part of the Amiga's memory
which can be used for data storage and is directly accessible by the CPU.
RAM storage is volatile, meaning that data in RAM is lost when the Amiga
is rebooted or turned off; as opposed to ROM memory which is permanent.


Glossary / raster

The area in memory that completely defines a bitmap display.


Glossary / read-only

Describes a register or memory area that can be read but not written.


Glossary / request

Asking for the use of some resource; the Zorro III bus has two kinds of
requests, bus requests and quick interrupt requests.


Glossary / resolution

The number of pixels associated with a particular display mode.  For
example, a normal NTSC Hires screen has a resolution of 640 (horizontal)
by 200 (vertical) pixels.


Glossary / ROM

Short for read-only memory.  ROM is the part of the Amiga's memory which
is permanent, or non-volatile.  The Amiga's operating system is stored in
ROM.


Glossary / sample

In audio applications, a single discrete data item which represents a
waveform amplitude at a given instant.  A group of samples taken over time
is used to represent a waveform in the Amiga's memory.


Glossary / sampling rate

The number of samples played per second.  Also used to mean the rate at
which the samples were originally recorded.


Glossary / sampling period

The value that determines how many clock cycles it takes to play one data
sample.


Glossary / scroll

.nh To move a playfield smoothly in a vertical or horizontal direction.


Glossary / SCSI

Acronym for Small Computer System Interface.  SCSI is a standard interface
protocol for connecting peripherals, especially hard disk drives and other
mass storage devices, to computers.

.hy 14


Glossary / serial port

A connector on the back of the Amiga that allows extra equipment such as a
printer to be attached.  The serial port transfers data one single bit at
a time in contrast to the parallel port which sends one complete byte (8
bits) at a time.


Glossary / set

To change a bit or flag to 1, its on or enabled state.; as opposed to
clear.


Glossary / Shell

The command line interface used to send typed commands to the Amiga.  One
of the three user interfaces built into the Amiga.


Glossary / slave

The device currently responding to the address on the expansion bus. There
is only one slave on the bus at a time; an error is signalled by the bus
collision detect logic if multiple slaves respond to the same address.
The slave also drives data on reads, the transfer acknowledge strobe, and
several other signals.


Glossary / slot

A physical port on a Zorro backplane, which supplies independent /SLAVEn
/BRn, and /BGn lines, chained /CFGINn and /CFGOUTn lines, and is
mechanically manifested as a 100 pin single-piece connector.


Glossary / sprite

Easily movable graphics object that is produced by one of the eight sprite
DMA channels and is independent of the playfield display.


Glossary / strobe address

An address you put out to the bus in order to cause some other action to
take place; the actual data written or read is ignored.


Glossary / task

A software function spawned by a process.  Each task is an operating
system module or application program which is running and that has full
control over its own virtual 68000 machine.


Glossary / termination

Circuitry attached to a bus signal in order to minimize annoying analog
things like ringing, reflections, crosstalk, and possibly random logic
conditions which can arise when a bus is undriven.


Glossary / timbre

The distinctive quality of a sound produced by its overtones.


Glossary / timeout

A bus cycle terminated by the bus controller instead of by a responding
slave device.  If no slave responds to a bus cycle within a reasonable
time period, the bus controller will terminate the cycle to prevent lockup
of the system.


Glossary / transparent

In graphics, a special color register definition that allows a background
color to show through.  Used in dual-playfield mode.


Glossary / tri-state

A signal driven to a high impedence condition is said to be tri-stated.


Glossary / UART

The circuit that controls the serial link to peripheral devices, short for
Universal Asynchronous Receiver/Transmitter.


Glossary / video priority

Defines which graphic objects (playfields and sprites) are shown in the
foreground and which objects are shown in the background when they occupy
the same area of the display.  Higher-priority objects appear in front of
lower-priority objects.


Glossary / video display

Everything that appears on the screen of a video monitor or television.


Glossary / write-only

Describes a register that can be written to but cannot be read.


Glossary / word

Based on the Motorola conventions, a word is equal to 2 bytes.


Glossary / Zorro

The name given to the Amiga bus specification.  "Zorro I" refers to the
original design for A1000 backplane boxes, "Zorro II" refers to the
modification to this specification used for the A2000 and compatible
backplanes, and "Zorro III" refers to the Zorro II compatible bus
specification first used in the Amiga 3000 computer.


Amiga® Hardware Reference Manual: J Custom Chip Pin Allocation List

This section gives the pin assignments used by the Amiga's custom chip set.

NOTE:  * Means an active low signal.

 Original Agnus Pin Assignment      Paula Pin Assignment
 Denise Pin Assignment              Fat Agnus Pin Assignment


J Custom Chip Pin Allocation List / Original Agnus Pin Assignment

   PIN #      DESIGNATION     FUNCTION                DEFINITION
   -----      -----------     ------------------      ----------
    01-09     D8-D0           Data bus lines 8 to 0       I/O
    10        VCC             +5 Volt                     I
    11        RES*            System reset                I
    12        INT3*           Interrupt level 3           O
    13        DMAL            DMA request line            I
    14        BLS*            Blitter slowdown            I
    15        DBR*            Data bus request            O
    16        ARW*            Agnus RAM write             O
    17-24     RGA8-RGA1       Register address bus 8-1    I/O
    25        CCK             Color clock                 I
    26        CCKQ            Color clock delay           I
    27        VSS             Ground                      I
    28-36     DRA0-DRA8       DRAM address bus 0 to 8     O
    37        LP*             Light pen input             I
    38        VSY*            Vertical sync               I/O
    39        CSY*            Composite sync              O
    40        HSY*            Horizontal sync             I/O
    41        VSS             Ground                      I
    42-48     D15-D9          Data bus lines 15 to 9      I/O


J Custom Chip Pin Allocation List / Denise Pin Assignment

   PIN #      DESIGNATION     FUNCTION                DEFINITION
   -----      -----------     ------------------      ----------
    01-07     D6-D0           Data bus lines 6 to 0       I/O
    08        M1H             Mouse 1 horizontal          I
    09        M0H             Mouse 0 horizontal          I
    10-17     RGA8-RGA1       Register address bus 8-1    I
    18        BURST*          Color burst                 O
    19        VCC             +5 Volt                     I
    20-23     R0-R3           Video red bits 0-3          O
    24-27     B0-B3           Video blue bits 0-3         O
    28-31     G0-G3           Video green bits 0-3        O
    32        /CSYNC          Composite sync              I
    33        ZD*             Background indicator        O
    34        N/C             Not connected               N/C (old Denise)
              CDAC            CDAC clock                  I   (ECS Denise)
    35        7M              7.15909  MHZ                I
    36        CCK             Color clock                 I
    37        VSS             Ground                      I
    38        M0V             Mouse 0 vertical            I
    39        M1V             Mouse 1 vertical            I
    40-48     D15-D7          Data bus lines 15 to 7      I/O


J Custom Chip Pin Allocation List / Paula Pin Assignment

   PIN #      DESIGNATION     FUNCTION                DEFINITION
   -----      -----------     ------------------      ----------
    01-07     D8-D2           Data bus lines 8 to 2       I/O
    08        VSS             Ground                      I
    09-10     D1-D0           Data bus lines 1 and 0      I/O
    11        RES*            System reset                I
    12        DMAL            DMA request line            O
    13-15     IPL0*-IPL2      Interrupt lines 0-2         O
    16        INT2*           Interrupt level 2           I
    17        INT3*           Interrupt level 3           I
    18        INT6*           Interrupt level 6           I
    19-26     RGA8-RGA1       Register address bus 8-1    I
    27        VCC             +5 Volt                     I
    28        CCK             Color clock                 I
    29        CCKQ            Color clock delay           I
    30        AUDB            Right audio                 O
    31        AUDA            Left audio                  O
    32        POT0X           Pot 0X                      I/O
    33        POT0Y           Pot 0Y                      I/O
    34        VSSANA          Analog ground               I
    35        POT1X           Pot 1X                      I/O
    36        POT1Y           Pot 1Y                      I/O
    37        DKRD*           Disk read data              I
    38        DKWD*           Disk write data             O
    39        DKWE            Disk write enable           O
    40        TXD             Serial transmit data        O
    41        RXD             Serial receive data         I
    42-48     D15-D9          Data bus lines 15 to 9      I/O


J Custom Chip Pin Allocation List / Fat Agnus Pin Assignment

   PIN #      DESIGNATION     FUNCTION                DEFINITION
   -----      -----------     ------------------      ----------
    01-14     RD15-RD2        Register bus lines 15 to 2  I/O
    17        INT3*           Blitter ready interrupt     O
    18        DMAL            Request audio/disk DMA      I
    18        RD1             Register bus line 1         I/O
    18        RST*            Reset                       I
    19        BLS*            Blitter slowdown            I
    20        DBR*            Data bus request            O
    21        RRW             DRAM Write/Read             O
    22        PRW             Processor Write/Read        I
    23        RGEN*           RG Enable                   I
    24        AS*             Address Strobe              I
    25        RAMEN*          RAM Enable                  I
    26-33     RGA8-RGA1       Register address bus 8-1    O
    34        28MHZ           Master clock                I
    35        XCLK            Alternate master clock      I
    36        XCLKEN*         Master clock enable         I
    37        CDAC*           Inverted shifted 7MHZ clk   O
    38        7MHZ            28MHZ clk divided by four   O
    39        CCKQ            Color clock delay           O
    40        CCK             Color clock                 O
    41        TEST            Test - access registers     I (old Fat Agnus)
              NTSC/PAL        Select video environment    I (ECS Fat Agnus)
    43-51     MA0-MA8         Output bus lines 0 to 8     O
    52        LDS*            Lower data strobe           I
    53        UDS*            Upper data strobe           I
    54        CASL*           Column addr strobe lower    O
    55        CASU*           Column addr strobe upper    O
    56        RAS1*           Row address strobe one      O
    57        RAS0*           Row address strobe zero     O
    59-77     A19-A1          Address bus lines 19 to 1   I
    78        LP*             Light pen                   O
    79        VSY*            Vertical synch              I/O
    80        CSY*            Composite video synch       O
    81        HSY*            Horizontal synch            I/O
    84        RD0             Register bus line 0         I/O


Amiga® Hardware Reference Manual: List of Tables

 Table 1-1: Summary of Amiga Memory Configurations
 Table 2-1: Interrupting the 680x0
 Table 2-2: Copper Instruction Summary
 Table 3-1: Colors in a Single Playfield
 Table 3-2: Portion of the Color Table
 Table 3-3: Contents of the Color Registers
 Table 3-4: Sample Color Register Contents
 Table 3-5: Setting the Number of Bitplanes
 Table 3-6: Lines in a Normal Playfield
 Table 3-7: Playfield Memory Requirements, NTSC
 Table 3-8: Playfield Memory Requirements, PAL
 Table 3-9: DIWSTRT and DIWSTOP Summary
 Table 3-10: Playfield 1 Color Registers -- Low resolution Mode
 Table 3-11: Playfield 2 Color Registers -- Low resolution Mode
 Table 3-12: Playfields 1 and 2 Color Registers -- High resolution Mode
 Table 3-13: Maximum Allowable Vertical Screen Video
 Table 3-14: Maximum Allowable Horizontal Screen Video
 Table 3-15: Color Register Contents
 Table 3-16: Some Register Values and Resulting Colors
 Table 3-17: Low resolution Color Selection
 Table 3-18: High resolution Color Selection
 Table 3-19: Color Selection in Hold-and-modify Mode
 Table 4-1: Sprite Data Structure
 Table 4-2: Sprite Color Registers
 Table 4-3: Color Registers for Sprite Pairs
 Table 4-4: Data Words for First Line of Spaceship Sprite
 Table 4-5: Color Registers in Attached Sprites
 Table 4-6: Color Registers for Single Sprites
 Table 4-7: Color Registers for Attached Sprites
 Table 5-1: Sample Audio Data Set for Channel 0
 Table 5-2: Volume Values
 Table 5-3: DMA and Audio Channel Enable Bits
 Table 5-4: Data Interpretation in Attach Mode
 Table 5-5: Channel Attachment for Modulation
 Table 5-6: Sampling Rate and Frequency Relationship
 Table 5-7: Equal-tempered Octave for a 16 Byte Sample
 Table 5-8: Five Octave Even-tempered Scale
 Table 5-9: Decibel Values and Volume Ranges
 Table 6-1: Table of Common Minterm Values
 Table 6-2: Typical Blitter Cycle Sequence
 Table 6-3: BLTCON1 Code Bits for Octant Line Drawing
 Table 7-1: Bits in BPLCON2
 Table 7-2: Priority of Playfields Based on Values of Bits PF1P2-PF1P0
 Table 7-3: CLXDAT Bits
 Table 7-4: CLXCON Bits
 Table 7-5: Contents of the Beam Position Counter
 Table 7-6: Contents of DMA Control Register
 Table 8-1: Typical Controller Connections
 Table 8-2: Determining the Direction of the Mouse
 Table 8-3: Interpreting Data from JOY0DAT and JOY1DAT
 Table 8-4: POTGO ($DFF034) and POTINP ($DFF016) Registers
 Table 8-5: Disk Subsystem
 Table 8-6: DSKLEN Register ($DFF024)
 Table 8-7: DSKBYTR Register
 Table 8-8: ADKCON and ADKCONR Register
 Table 8-9: SERDATR / ADKCON Registers
 Table K-1: Memory Space Type Codes


Amiga® Hardware Reference Manual: Index

          Misc.       Note: Numbers will refer to page numbers in
           A                the `Amiga® Hardware Reference Manual'
           B                3rd edition, ISBN 0-201-56776-8
           C
           D
        E F G H
         I J K
        L M N O
           P
          R S
       T U V W Z


Numbers Index

$00C00000, 5
60 Pin Edge Connector, 321
68000, -->
68010, 1
68020, 1 , 187
68030, 1
680x0, -->
8361, 5
8370, 5
8371, 5
8372A, 5
8520, -->
86 Pin Edge Connector, 322


68000 Index

68000, 2 , 187
  normal cycle, 196
  test-and-set instruction, 196


680x0 Index

680x0, 19 , 25 , 35 , 194 , 223
  instead of Copper, 35
  interrupting, 35 , 217
  shared memory, 4
  synchronizing with the video beam, 216


8520 Index

8520, 157 , 223 , 241 , 244 , 251 , 339
  alarm, 344
  handshaking, 341
  input modes, 343
  interval timers, 341
    continuous, 342
    force load, 342
    one-shot, 342
    PB on/off, 342
    start/stop, 342
    Toggle/pulse, 342
  I/O ports, 341
  read bit names, 343
  register map, 340
  signal assignments, 337
  time-of-day clock, 344
  write bit names, 343


A Index

A1000, -->
A2000, 1 , 5 , 6 , 7 , 7 , 63 , 157 , 238 , 260
A3000, -->
A500, 1 , 5 , 7 , 63 , 157 , 238 , 260
Address Registers, 10
ADKCON, -->
Agnus, -->
Alarm, 344
Aliasing, audio, 154
AllocMem(), 52
Amiga OS, 9
Amplitude Modulation, 4
Animated Objects, 6
Animation, 176
Apple II, 241
Area Fill, 4 , 184
ATTACH, 120
Attachment - audio, 150 , sprites, 120
Audio, -->
Audio Channel, 19
AUDx, 220
AUDxEN, 144 , 222
AUDxLCH, 138 , 298
AUDxLCL, 138
AUDxLEN, 139
AUDxPER, 143 , 298
AUDxVOL, 139
AUTOCONFIG, 7 , 223 , 431


A1000 Index

A1000, 1 , 5 , 7 , 63 , 64 , 238 , 260
  expansion port, 321


A3000 Index

A3000, 1 , 6 , 7 , 7 , 260
  expansion bus, 383


ADKCON Index

ADKCON, 241 , 250 , 256
  disk control bits, 249
  in audio, 149-150


Agnus Index

Agnus, 2 , 5 , 164-165 , 169
  ECS fat Agnus, 295
  fat agnus, 187


Audio Index

Audio, 4 , 9 , 20
  aliasing distortion, 154
  amplitude modulation, 4
  channels - attaching, 149 , 164 , choosing, 137
  data, 137
  data length registers, 139
  data location registers, 138 , 139
  data output rate, 140
  decibel values, 140
  DMA, 138 , 144 , 147 , 164
  equal-tempered scale, 158
  frequency modulation, 4
  in ECS, 310
  interrupts, 147 , 220
  joining tones, 147
  low-pass filter, 154
  modulation, 164
    amplitude, 149
    frequency, 149
  noise reduction, 154
  non-DMA output, 157
  period, 140
  period register, 143
  playing multiple tones, 149
  producing a steady tone, 145
  sampling period, 141
  sampling rate, 141 , 152 , 156 , 164
  state machine, 164
  stopping, 145
  system overhead, 153
  volume, 139 , 163
  volume registers, 139
  waveform transitions, 152


B Index

Background color, 46
Barrel Shifter, 179
BBUSY, 222
Beam comparator, 124
Beam position, -->
Beam position counter, 216
BEAMCON0, 298 , 305
Bitplanes, -->
Blitter, -->
Blitter Busy, 186
Blitter registers - in line-drawing mode, 189
Blitter shifting, 179
BLTAxWM, 180
BLTCON0, -->
BLTCON0L, 298
BLTCON1, -->
BLTEN, 222
BLTPRI, 222
BLTSIZE, 169 , 171-173 , 186-187 , 191 , 308
BLTSIZH, 298
BLTSIZV, 298 , 308
BLTxDAT, 170
BLTxMOD, 172
BLTxPTH, 170 , 298
BLTxPTL, 170
BPL1MOD, 62 , 64
BPL2MOD, 62 , 64
BPLCON0, -->
BPLCON1 - setting scrolling delay, 85
BPLCON2, -->
BPLCON3, 298
BPLCONx, 90 , 307
BPLEN, 222
BPLxMOD, 84 , 91
BPLxPT, 91
BPLxPTH, 52 , 54 , 61 , 74
BPLxPTL, 52 , 54 , 61 , 74
BPUx, 48 , 87 , 90
Bridgeboard, 7
BZERO, 222


Beam position Index

Beam position
  comparison enable bits, 24
  detection of, 216
  in Copper use, 31
  registers, 216
  vertical, 23 , 24


Bitplanes Index

Bitplanes
  coloring, 55
  DMA, 62
  in dual-playfield mode, 68
  setting the number of, 48
  setting the pointers, 54


Blitter Index

Blitter, 4 , 6 , 9 , 19
  address scanning, 173
  addressing, 170
  animation, 176
  area fill, 4 , 184
  area filling - exclusive, 184 , inclusive, 184
  blit time, 193
  blitter done flag, 186
  blitter-finished disable bit (BFD), 35
  blitter-nasty bit, 198
  block transfers, 171 , 183
  BLTSIZE, 187
  bus sharing, 194
  clock, 193
  cookie-cut, 176 , 181 , 183
  copying, 169 , 183
  cycle time, 193
  data fetch, 170
  data overlap, 182
  descending mode, 182-183
  DisownBlitter(), 187
  DMA enable, 181 , 184 , 187
  DMA priority, 194
  DMA time slots, 194
  equation-to-minterm conversion, 175
  example, 200
  FILL_CARRYIN bit, 185
  height, 171
  immediate data, 170 , 182
  in ECS, 296
  interrupts, 187 , 220
  LF control byte, 174
  line drawing, 4
    logic function, 191
    octants, 190
    registers, 189
  line drawing mode, 189
  line texture, 191
  linear data, 173
  logic equations, 175
  logic operations, 174
  masking, 181 , 183-184
  minterms, 175
  modulo, 172
  modulo registers, 172
  octants, 189
  OwnBlitter(), 187
  packed font, 180
  pipelined, 188
  pointer registers, 170
  sequence of bus cycles, 188
  shifting, 182 , 183
  size of blit, 171
  starting operation, 169
  text, 180
  truth-table, 174
  Venn Diagrams, 178
  WaitBlit(), 187
  width, 171
  with the Copper, 35
  zero detection, 187


BLTCON0 Index

BLTCON0, 182
  DMA enable, 170
  in line drawing, 189 , 191
  in logic operations, 174
  in shift control, 179


BLTCON1 Index

BLTCON1, 182 , 189 , 298
  in area fill, 184
  in blitter addressing, 182
  in line drawing, 189-191
  in shift control, 179


BPLCON0 Index

BPLCON0, 87 , 229 , 298 , 300
  enabling color, 63
  in dual-playfield mode, 72
  in hold-and-modify mode, 87
  in interlacing, 51
  in resolution mode, 49
  in the Enhanced Chip Set, 300
  selecting bitplanes, 48
  setting bits, 48
  with light pen, 239


BPLCON2 Index

BPLCON2, 72 , 210 , 298
  in dual-playfield priority, 71


C Index

Cache, 187 , 388
CDANG, 26
Chip Memory, 5-6 , 20 , 105 , 138 , 169 , 170 , 186 , 223 , 246 , 296
CIA, 9 , 157 , 241 , 251 , 339
CIAA - address map, 339
CIAADDRA, 241
CIAAPRA, -->
CIAB - address map, 340
CIABPRB - disk, 244
Clock, -->
Clock Constant, 141 , 159
Clock cycle, 4
Clock Interval, 141
CLXCON, 215
CLXDAT, 214
CNT, 251
Collision, -->
Collision Detection, 4
Color, -->
Color Clock, 60 , 194 , 255 , 304
Color Palette, 3 , 19
Color Registers, 3
Color registers, -->
Color selection, -->
COLOR00, 46 , 55
COLOR_ON, 90
COLORx, 10 , 27 , 28 , 46 , 70-71 , 87
Comparator, 124
Composite Video, 7
Control Register, -->
Controller Port, -->
Controllers, -->
COP1LC, 25 , 30 , 32 , 32 , 35
COP1LCH, 25 , 298
COP1LCL, 25
COP2LC, 25 , 26 , 32
COP2LCH, 25 , 298
COP2LCL, 25
COPCON, 26 , 298
COPEN, 30 , 35 , 222
COPJMP1, 26
COPJMP2, 26
Copper, -->
Coprocessor -  19 , see  Copper
Copying data, 169
CP/M, 241
CTRL-AMIGA-AMIGA, 253
Custom Chips, -->


CIAAPRA Index

CIAAPRA, 229 , 232 , 233 , 241 , 241
  disk, 244


Clock Index

Clock, 260
  8520, 344
  alarm, 344
  audio, 140 , 141 , 142 , 159 , 164
  blitter, 193 , 194
  color, 194 , 255
  keyboard, 251
  system, 2 , 193


Collision Index

Collision, 213
  control register, 215
  detection register, 214


Color Index

Color
  attached sprites, 122
  background color, 46
  color indirection, 42
  color table, 46
  enabling, 63
  in dual-playfield mode, 70
  in hold-and-modify mode, 86
  in SuperHires mode, 301
  in the Enhanced Chip Set, 301
  sample register contents, 92
  sprites, 102


Color registers Index

Color registers
  contents, 46
  loading, 47
  names of registers, 46
  sprites, 130


Color selection Index

Color selection
  in high resolution mode, 94
  in hold-and-modify mode, 95
  in low resolution mode, 93


Control register Index

Control Register, 348
  register A, 348
    bitmap, 349
  register B, 349
    bitmap, 350


Controller Port Index

Controller Port
  connection chart, 228
  joystick, 232
  mouse, 229
  output to, 240
  registers, 229
  trackball, 229


Controllers Index

Controllers
  light pen, 238
  potentiometers, 236
  proportional - registers, 236
  special, 241
  types, 6


Copper Index

Copper, 9 , 19 , 45 , 54 , 62 , 64 , 65 , 80 , 81 , 82 , 110 , 122 , 194 ,
        197 , 216 , 219
  affecting registers, 26
  at reset, 30
  bus cycles used, 20
  comparison enable, 32
  control register, 26
  danger bit (CDANG), 26
  DMA, 30 , 30
  features, 19
  horizontal beam position, 23
  in interlaced mode, 34
  in memory operations, 20
  in vertical blanking interrupts, 219
  instruction fetch, 25
  instruction lists, 26 , 28
  instructions
    description, 20
    ordering, 27
    summary, 36
  interrupt, 219
  interrupting the 680x0, 35
  jump, 25
  jump strobe addresses, 26
  location registers, 25 , 30 , 32
  loops and branches, 32
  memory cycles, 22
  MOVE instruction, 21
  MOVE to registers, 21
  registers, 25
  resolution, 23 , 24
  SKIP instruction, 31 , 32
  starting, 26 , 30
  stopping, 30
  strobe address, 26
  vertical beam position, 24
  WAIT instruction, 22 , 30 , 32
  with sprites, 113
  with the blitter, 26 , 35


Custom Chips Index

Custom Chips, 2 , 170 , 255
  control registers, 19
  register, 263
  steal cycles, 4


D Index

Data-fetch, -->
DBLPF, 87 , 90
DDFSTOP, 60-61 , 80 , 82 , 91 , 99
DDFSTRT, 60 , 80 , 82 , 91 , 99
Decibel values, 163
Denise, 2 , 297
DENISEID, 298
Descending Mode - blitter, 182
DEST, 170
Digital Joystick - connection, 329 ,fire buttons, 329
Disk, -->
Disk Port, 320
Display - size of, 57
Display DMA, 20
Display field, 40
Display memory, 57
Display modes, 41
Display window, -->
DIWHIGH, 298 , 306
DIWSTOP, 59 , 78 , 91 , 99 , 219 , 306
DIWSTRT, 58 , 59 , 76 , 91 , 99 , 219 , 306
DMA, -->
DMA Contention, 193
DMA Priority, 194
DMAB_BLTDONE, 186
DMACON, -->
DMACONR, 222
DMAEN, 144 , 222 , 247
DMAF_BLITHOG, 198
DMAF_BLTNZERO, 187
DSK, 244
DSKBLK, 220
DSKBYTR, 241 , 248
DSKCHANGE, 244
DSKDIREC, 244
DSKEN, 222
DSKINDEX, 244
DSKLEN, 241 , 246-247
DSKMOTOR, 244
DSKPROT, 244
DSKPTH, 241 , 246 , 298
DSKRDY, 244
DSKSELx, 244
DSKSIDE, 244
DSKSTEP, 244
DSKSYN, 220
DSKSYNC, 241 , 247 , 250
DSKTRACK0, 244
Dual Playfield, -->


Data-fetch Index

Data-fetch
  high resolution, 62
  in basic playfield, 60
  in horizontal scrolling, 82
  start - normal, 60
  stop - normal, 60


Disk Index

Disk, 20
  controller, 6 , 241
  DMA, 246
  DMA pointer registers, 246
  drives, 6
  external
    identification, 335
    interface, 334
    limitations, 335
    pins, 334
  external connector, 367
    device ID, 370
    pins, 367
    signals, 368
  floppy, 4
  input stream synchronization register (DSKSYNC), 250
  internal - pins, 336 ,power, 336
  interrupts, 220 , 250
  MFM Encoding, 250
  read data register, 248
  write, 246


Display window Index

Display window
  positioning, 57
  size - maximum, 79 , 306 ,normal, 58
  starting position - horizontal, 58 , 77 , 306 ,vertical, 58 , 77 , 306
  stopping position - horizontal, 59 , 78 , 306 ,vertical, 59 , 79 , 306


DMA Index

DMA, 4 , 207
  audio, 137 , 138 , 141 , 144 , 145 , 147 , 148 , 157 , 164-165 ,
         194 , 220
  bitplanes, 62
  blitter, 50 , 170-173 , 174 , 176 , 179-181 , 183-184 , 187 , 189 ,
           191 , 193 , 194 , 196-198
  control, 222
  control register, 218 , 222
  copper, 19-20 , 30
  disk, 4 , 194 , 220 , 241 , 246 , 247 , 250
  display, 20 , 194 , 300
  playfield, 62
  sprites, 4 , 27 , 97 , 102 , 108 , 109 , 110 , 115 , 116-117 , 118 ,
           120-121 , 123 , 126 , 127 , 128 , 194


DMACON Index

DMACON, 222 , 247
  blitter done, 186
  DMAF_BLITHOG bit, 198
  in audio, 144
  in playfields, 62
  stopping the Copper, 30
  zero detection, 187


Dual Playfield Index

Dual Playfield, 44
  bitplane assignment, 68
  description, 67
  enabling, 72
  high resolution colors, 71
  in high resolution mode, 71
  low resolution colors, 70
  priority, 71
  scrolling, 71


E,F,G,H Index

ECS - sprites, 302 , 303
ECS Registers, 298
Enhanced Chip Set, -->
Examples, 9
Expansion Boards, 7
Expansion Bus, 383
Expansion Connector, 7 , 385
External interrupts, 219

FAST, 249
Fast Memory, 5
Fat Agnus, 5 , 187
Field time, 40
Floppy Disk, 4 , 241 , See   DISK
Frame Buffer, 6
Frequency Modulation, 4

Game Controller Port, 327
GAUD, 89
GCR, 250
Genlock, -->
HAM, 86

Hardware Connection, -->
HBSTOP, 298
HBSTRT, 298
HCENTER, 298
High resolution, -->
HIRES, 87
Hold-And-Modify, 3 , 86
HOMOD, 87 , 90
Horizontal blanking interval, 23 , 304
HSSTOP, 298
HSSTRT, 298
HSTART, 59 , 91 , 107 , 107 , 113
HSTOP, 59 , 78 , 91
HTOTAL, 298 , 304


Enhanced Chip Set Index

Enhanced Chip Set, 295
  blitter, 296
  ECS Registers, 298
  memory, 296


Genlock Index

Genlock, 2 , 49 , 51 , 89 , 159 , 260
  effect on background color, 46
  in ECS, 296
  in playfield register, 89


Hardware Connection Index

Hardware Connection, 353
  address inputs, 354
  chip select, 353
  clock input, 353
  data bus I/O, 354
  interrupt request, 354
  read/write input, 353
  reset input, 354


High resolution Index

High resolution
  color selection, 49 , 94
  memory requirements, 52
  SuperHires, 300
  with dual playfields, 71
  with ECS, 296


I,J,K Index

IBM PC, 6 , 7 , 241
Include Files, 10 , 22 , 373
INTEN, 218
INTENA, 217
INTENAR, 217
Interlaced mode, -->
Interleaved Memory, 4
Internal Slots, 7
Interrupt, -->
Interrupt Control Register, -->
Interrupts - during vertical blanking, 219
INTF_BLIT, 187
INTREQ, 35 , 218
INTREQR, 218

Joy stick port, 323
JOY0DAT/JOY1DAT, -->
Joystick, -->
JOYxDAT, 229

Keyboard, -->
Keyboard Port, 319


Interlaced mode Index

Interlaced mode
  Copper in, 34
  memory requirements, 52
  modulo, 62
  setting interlaced mode, 49


Interrupt Index

Interrupt, 26 , 35 , 35 , 207 , 217
  8520, 251
  audio, 147 , 148 , 153 , 157 , 164-165 , 220
  beam synchronized, 3
  blitter, 35 , 171 , 187 , 220
  control registers, 217
  copper, 25 , 32 , 216 , 219
  disk, 220 , 245 , 250
  external, 219
  graphics, 33
  interrupt enable bit, 218
  interrupt lines, 217
  maskable, 217
  nonmaskable, 217
  parallel, 259
  priorities, 221
  registers, 218
  serial, 255 , 256 , 258
  serial port, 220
  setting and clearing bits, 218
  vertical blanking, 219


Interrupt Control Register Index

Interrupt Control Register, 346
  read, 347
  write, 347


JOY0DAT/JOY1DAT Index

JOY0DAT/JOY1DAT
  with joystick, 232
  with mouse/trackball, 230


Joystick Index

Joystick
  connections, 228
  port, 323
  reading, 232


Keyboard Index

Keyboard, 251 , 357
  Caps lock, 359
  communications, 357
  errors, 359
  ghosting, 253
  hard reset, 361
  keycodes, 358
    transmission, 358
  matrix, 362
  out-of-sync, 359
  power up, 360
  raw keycodes, 251
  reading, 251
  reset warning, 361
  self test, 360
  signals, 6 , 357
  special codes, 364
  timing diagram, 358


L,M,N,O Index

LACE, 51
LED - caps-lock, 253
Light Pen, -->
Line Drawing, -->
Low resolution - color selection, 93
LPEN, 89

Manual mode - in sprites, 123
Memory - adding, 7 ,blitter access to, 169
Memory allocation, -->
Memory Allocation - playfields, 76
Memory allocation - sprite data, 105
Memory Cycle Time, 194
Memory map, 388
MFM Encoding, 241 , 250
MFMPREC, 249
MIDI, 318
Minterms, 175
Modulation - amplitude, 149 ,frequency, 149
Modulo, -->
Monitors -  260 , See  Video
Mouse - connections, 228 ,reading, 229
Mouse Port, 328
MOVE, 19 , 20 , 21
MSBSYNC, 249-250
MS-DOS, 6 , 7 , 241
Multiprocessor, 223
Multitasking, 9

Noise - audio, 154
NTSC, -->

Octants, 189
OVERRUN, 256
Overscan, 3 , 57 , 99


Light Pen Index

Light Pen, 333
  connections, 228
  pins, 333
  reading, 238
  registers, 238


Line Drawing Index

Line Drawing, 4 , 189
  length, 191
  logic function, 191
  octants, 189
  registers, 191


Memory allocation Index

Memory allocation
  audio, 137
  formula for playfields, 76
  playfields, 52


Modulo Index

Modulo
  blitter, 172
  in basic playfield, 60-62
  in horizontal scrolling, 82
  in interlaced mode, 62
  in larger playfield, 73


NTSC Index

NTSC, 62 , 100 , 100
  audio, 140 , 141 , 158-159
  blitter, 193
  clock, 2
  playfield, 49 , 52 , 57 , 58
  serial baud rate, 255
  sprites, 100 , 100
  vertical blank, 219
  video, 3 , 24 , 27 , 34 , 40-41 , 45 , 304


P Index

Packed Font, 180
Paddle Controller - connections, 228 ,reading, 234
PAL, -->
Parallel, 9
Parallel Port, -->
Paula, 2 , 6 , 255
Peripherals, 6 , 7
Pipeline, 188
Pixels - definition, 40 ,in sprites, 101 , 101
Playfield, 4 , 6 , 9
Playfields, -->
Playfield-sprite priority, 209
Port Signal Assignments, 350
Ports, -->
POT0DAT, 236 , 298
POT1DAT, 236 , 298
POTGO, 229
POTGO / POTINP, -->
POTGOR, 229
POTINP - name changed to POTGOR, 240
POTxDAT, 229
Power up operation, 223
PRECOMPx, 249
Priority, -->
Productivity mode, 3
Proportional Controller, 331  - pins, 332
Proportional Controllers - reading, 234
Proportional Joystick - connections, 228 ,reading, 234


PAL Index

PAL, 3 , 62
  audio, 140 , 141 , 158-159
  beam position, 216
  blitter, 193
  clock, 2
  playfield, 49 , 52 , 57 , 58
  serial baud rate, 255
  sprites, 100
  vertical blank, 219
  video, 3 , 24 , 34 , 40-41 , 45 , 304


Parallel Port Index

Parallel Port, 227 , 259 , 319
  pin assignment, 324
  specification, 324
  timing - input, 325 ,output, 325


Playfields Index

Playfields
  allocating memory, 52 , 61
  bitplane pointers, 54
  collision, 213
  color of pixels, 42-44
  color register contents, 92
  color table, 46
  coloring the bitplanes, 45 , 55
  colors in a single playfield, 45
  defining a scrolled playfield, 85
  defining display window, 57
  defining dual playfields, 72
  defining the basic playfield, 63
  display window size - maximum, 79 ,normal, 58
  displaying, 62
  dual-playfield mode, 67
  enabling DMA, 62
  fetching data, 60-61 , 80
  forming, 44
  high resolution, 41
    color selection, 94
    example, 66
  hold-and-modify, 95
  hold-and-modify mode, 86
  interlaced, 41
  interlaced example, 66
  low resolution, 41
    colors, 93
  memory required, 52 , 76
  modulo registers, 62
  multiple-playfield display, 89
  non-interlaced, 42
  normal, 42
  pointer registers, 54 , 61 , 74
  priority, 210
  register summary, 89
  scrolling - horizontal, 82 ,vertical, 81
  selecting bitplanes, 48
  setting resolution mode, 49
  specifying modulo, 60-62 , 73
  specifying the data fetch, 76
  with external video source, 89
  with genlock, 89
  with larger display memory, 73


Ports Index

Ports
  controller, 227
  disk, 241
  parallel, 259
  serial, 255
  video, 260


POTGO / POTINP Index

POTGO / POTINP
  as digital I/O, 240
  as proportional inputs, 234


Priority Index

Priority
  dual playfields, 71
  playfield-sprite, 209
  priority control register, 210
  sprites, 207


R,S Index

RAM, -->
RAMEX, 321
Reboot, 223-224
Refresh, 20
Reset, 223
Resolution - setting, 49
RF Modulator, 260
RF Monitor, 320
RGB - analog, 260 ,digital, 260
RGB Video, 7 , 49 , 63 , 64
ROM, 1 , 6 , 223 , 253
RS-232, 6 , 255
RS-232 and MIDI, 318

Sampling - period, 141 ,rate, 152
Scrolling, -->
SCSI Disk Port, 321
SCSI internal disk - pins, 336
SERDAT, 258 , 259
SERDATR, 256
Serial, 9
Serial Port, -->
Serial Shift Register, -->
SERPER, 255
SET/CLR, 35 , 144 , 145 , 218 , 222 , 249 , 257
Shifting - blitter, 182
SKIP, 20
Slow Memory, 5
Sound generation, 134
SPREN, 222
Sprite, 3 , 9 , 19-20
Sprite Colors, 27
Sprite DMA, 27
Sprites, -->
SPRxCTL, 107 , 123 , 124 , 126 , 128-129 , 298 , 303
SPRxDATA, 123 , 126 , 129
SPRxDATB, 123 , 126 , 129
SPRxPOS, 107 , 123 , 124 , 126 , 127-128 , 129 , 303
SPRxPT, 114
SPRxPTH, 110 , 126 , 127
SPRxPTL, 110 , 126 , 127
SRCA, 170
SRCB, 170
SRCD, 170
Stereo, 4
STRLONG, 298
System Clock, 2
System Control Hardware, 9


RAM Index

RAM, 21 , 47
  address space, 2
  at startup, 223
  chip, 6 , 20 , 138
  disk, 246
  expansion, 2 , 7
  keyboard, 253


Scrolling Index

Scrolling
  data fetch, 82
  delay, 85
  horizontal, 82
  in dual-playfield mode, 71
  in high resolution mode, 82
  modulo, 82
  vertical, 81


Serial Port Index

Serial Port, 255
  characteristics, 327
  pin assignment, 326
  specification, 326
  timing, 327


Serial Shift Register Index

Serial Shift Register, 345
  bidirectional feature, 346
  input mode, 345
  output mode, 345


Sprites Index

Sprites
  address pointers, 110
  arming and disarming, 123
  attached
    color registers, 131
    colors, 122
    control word, 120
    copper list, 122
    data words, 121 , 123
  clipped, 100
  collision, 113 , 213
  color, 102 , 302
  color registers used, 102-103
  comparator, 124 , 126
  control registers, 124 , 126 , 127
  control words, 107 , 107
  data registers, 126 , 129
  data structure, 104
  data words, 107
  designing, 104
  displaying - example, 111 ,steps in, 109
  DMA, 110 , 114
  end-of-data words, 108
  Enhanced Chip Set, 302 , 303
  forming, 98
  manual mode, 123
  memory requirements, 105
  moving, 113
  overlapped, 118
  parallel-to-serial converters, 124
  pixels in sprites, 101 , 101
  pointer registers, 127
    initializing, 110
    resetting, 110
  position registers, 124 , 126
  priorities, 207
  priority, 115 , 118 , 210
  reuse, 114 , 116
  screen position - horizontal, 98 , 107 ,vertical, 100
  shape, 101
  size, 101
  vertical position, 107 , 107
  with copper, 113


T,U,V,W,Z Index

TAS, 196 , 223
Trackball, -->
Trackdisk, 9
TSRE, 259

UART, 255
UARTBRK, 257

VBSTOP, 298
VBSTRT, 298
VCR, 46
Vertical Blanking, 30 , 30 , 32 , 304
VGA, 304
VHPOSR, -->
VHPOSW - with beam counter, 216
Video, -->
Video Beam Position, 26
Video Input, 46
Video Port, 319
Volume, 139
VPOSR, -->
VPOSW - with beam counter, 216
VSSTOP, 298
VSSTRT, 298
VSTART, 59 , 91 , 107 , 107 , 108 , 113
VSTOP, 59 , 78 , 91 , 107 , 108 , 113
VTOTAL, 298 , 304

WAIT, 19 , 20
Waveform, 4
Waveforms - audio, 134
WORDSYNC, 249 , 250

Zero Detection, 187
Zorro Expansion Bus, -->


Trackball Index

Trackball, 328
  connections, 228
  reading, 229


VHPOSR Index

VHPOSR, 229
  with beam counter, 216
  with light pen, 238


Video Index

Video
  analog RGB, 260
  beam position, 3 , 23
  camera input, 7
  composite, 260
  digital RGB, 260
  external sources, 89
  interrupt, 3
  laser disk input, 7
  monitors, 7
  monochrome, 260
  output, 260
  priority, 4
  RF modulator, 260
  RGB, 49 , 63 , 64
  synchronization, 3
  VCR input, 7
  video slot, 260


VPOSR Index

VPOSR, 229 , 298 , 299
  in playfields, 66
  with beam counter, 216
  with light pen, 238-239


Zorro Expansion Bus Index

Zorro Expansion Bus, 383
  A2000, 384 , 387 , 387 , 387 , 391
  A3000, 384 , 387 , 387 , 387
  autoconfiguration, 431
  mechanical specifications, 427
  memory mapping, 388
  multiple transfer timing, 420
  quick interrupt timing, 422
  read timing, 416
  write timing, 418
  Zorro II signals, 391 , 437-439
  Zorro III signals, 409 , 437-439


Amiga® Hardware Reference Manual: K Zorro Expansion Bus

This appendix describes the complete Zorro III bus, first implemented in
the Amiga 3000 computer.  The Zorro III bus is a performance 32-bit
expansion bus that is also upward compatible with the Zorro II bus (Amiga
2000 expansion bus).  The main intent of the Zorro III bus is to allow
fast 32-bit peripherals and memory devices to be added to a high
performance Amiga, such as the Amiga 3000, while at the same time allowing
standard Zorro II devices to be used wherever they make sense in such a
system.  This compatibility also insures that the Amiga 3000 will have a
number of hardware and software compatible expansion devices available
upon introduction, and that Amiga 2000 owners will be able to take their
expansion card investment along with them should they migrate to a higher
performance Amiga.

 General                         Electrical Specifications
 Zorro II Compatibility          Mechanical Specifications
 Zorro III Bus Architecture      AUTOCONFIG(TM)
 Signal Description              Physical and Logical Signal Names
 Timing                          Zorro III Implementations


K Zorro Expansion Bus / General

 Intended Audience      Amiga Bus History      The Zorro III Rationale


K / General / Intended Audience

This appendix was written primarily for hardware engineers interested in
designing Plug-In Cards for the Zorro III expansion bus.  While it may
occasionally be of use to software engineers interfacing to such Zorro III
PICs, Amiga system software provides an interface layer
(expansion.library in the Amiga OS) which manages the needs of most
card-level software. A reasonable level of microcomputer knowledge is
prerequisite to get much meaning out of these pages.  A good understanding
of the Motorola 680x0 processors will be quite useful, as will be an
understanding of the Zorro II expansion bus used on earlier Amiga
computers such as the Amiga 2000.


K / General / Amiga Bus History

The original Amiga computer, the Amiga 1000, was introduced in 1985. While
it had no built-in standard for expandability, the capability for some
form of expansion was considered extremely important; personal computer
history up to that date had shown several times that an open hardware
expansion capability was often critical to a personal computer's success
and to its capability to adapt to new or unusual applications. The A1000
was designed with a connector giving access to the internal 68000 bus and
a few other system signals. Shortly after introduction, the formal
expansion specification for a card chassis that would connect to the A1000
was published.   This bus became commonly known as the Zorro bus*.  While
the backplane specification was very easy to implement with 1985 PAL
technology based on the existing 68000 signals, the specification did
incorporate a number of advanced features.   Far more sophisticated than
the IBM-XT/AT and Apple II buses in common use at the time, the Zorro bus
allowed any slot to master the bus, and it linked expansion cards with the
system software. Addressing jumpers were eliminated, the card's address
instead being assigned by software, and cards could easily be identified
by software and linked with appropriate driver programs, all with a
minimum of user intervention.

With the introduction of the Amiga 2000 system, the Zorro bus was changed
slightly.  Additional discrete interrupt lines were added, replacing the
encoded lines that couldn't easily be used by any bus resident device.  As
it turns out, these additional encoded lines weren't any more useful, as
they couldn't be disabled by software, and as such, they're no longer
considered an official part of the Zorro II bus specification (they are
supported as part of Zorro III).  Finally, the form factor was changed to
match that of the IBM PC-AT card, acting as both a cost reduction and
allowing the Zorro II bus to offer the PC-AT bus as one optional secondary
bus extension.  This modified specification became commonly known as the
Zorro II bus, and it's the Amiga bus standard that's been in use for most
of the Amiga's life.  And it's a bus standard that will continue to be
important.

 * The original "Zorro" name comes from the code name of one of the A1000
   prototype boards.  The "Zorro" board was the one that followed the
   "Lorraine," and was the board in the works when much of the expansion
   specifications were worked up.  Since everyone uses the "Zorro" name,
   and no one's suggested a better name, we've stuck with it.


K / General / The Zorro III Rationale

With the creation of the Amiga 3000, it became clear that the Zorro II bus
would not be adequate to support all of that system's needs. The Zorro II
bus would continue to be quite useful, as the current Amiga expansion
standard, and so it would have to be supported.   A few unused pins on the
Zorro II bus and the option of a bus controller custom LSI, gave rise to
the Zorro III design, which supports the following features:

   *   Compatibility  with all Zorro II devices.
   *  Full  32-bit address  path for new devices.
   *  Full  32-bit data  path for new devices.
   *   Bus speed independent  of host system CPU speed.
   *   High speed  bus block transfer mode.
   *   Bus locking  for multiprocessor support.
   *   Cache disable  for simple cache support.
   *   Fair arbitration  for all bus masters.
   *   Cycle-by-cycle  bus arbitration mode.
   *   High speed interrupt  mode.

Some of the advanced features, such as  burst modes , are designed in such
a way as to make them optional; both master and slave arbitrate for them.
In addition, it is possible with a bit of extra cleverness, to design a
card that automatically configures itself for either Zorro II or Zorro III
operation, depending on the status of a sensing pin on the bus.

The Zorro III bus is physically based on the same  100-pin  single piece
connector as the Zorro II bus.  While some bus signals remain unchanged
throughout bus operation, other signals change based on the specific bus
mode in effect at any time.  The bus is geographically mapped into three
main sections: Zorro II Memory Space, Zorro II I/O Space, and Zorro III
Space. The  memory map , in Figure K-1 shows how these three spaces are
mapped in the A3000 system.  The Zorro II space is limited to a 16
megabyte region, and since it has DMA access by convention to chip memory,
it is in the original 68000 memory map for any bus implementation.  The
Zorro III space can physically be anywhere in 32-bit memory.

      $80000000  ____________       _ _ _ ____________  $01000000
                |            |           |            |
                |            |     |     | Motherboard|
                |            |           |     ROM    |
                |            |     |     |------------| $00F00000
                |            |           |Zorro II I/O|
                | Zorro III  |     |     |------------| $00E80000
                | expansion  |           |    A2000   |
                |   space    |     |     | motherboard|
                |            |           |  register  |
                |            |     |     |    space   |
                |            |           |------------| $00B80000
                |            |     |     |  Zorro II  |
                |            |           |  expansion |
                |            |     |     |    space   |
      $10000000 |------------|           |------------| $00A00000
                |   32-bit   |     |     |            |
                |   memory   |           |  Zorro II  |
                | expansion  |     |     |   memory   |
                |   space    |           |  expansion |
      $08000000 |------------|    /      |    space   |
                |   A3000    |           |            |
                | motherboard|  /        |------------| $00200000
                |   space    |           | Amiga Chip |
      $01000000 |____________|/          |   memory   |
      $00000000 |____________|_ _ _ _ _ _|____________| $00000000

                   Figure K-1: Expansion Memory Map

The Zorro III bus functions in one of two different major modes, depending
on the memory address on the bus.  All bus cycles start with a 32-bit
address, since the full 32-bit address is required for proper cycle
typing.  If the address is determined to be in Zorro II space, a Zorro II
compatible cycle is initiated, and all responding slave devices are
expected to be Zorro II compatible 16-bit PICs.  Should a Zorro III
address be detected, the cycle completes when a Zorro III slave responds
or the bus times out, as driven by the motherboard logic.  It is very
important that no Zorro III device respond in Zorro III mode to a Zorro II
bus access; the two types of cycles make very different use of many of the
expansion bus lines, and serious buffer contention can result if the cycle
types are somehow mixed up.   The Zorro III bus of course started with the
Zorro II bus as its necessary base, but the Zorro III bus mechanisms were
designed as much as possible to solve specific needs for high end Amiga
systems, rather than extend any particular Zorro II philosophy when that
philosophy no longer made any sense.  There are actually several
variations of the basic Zorro III cycle, though they all work on the same
principles. The variations are for optimization of cycle times and for
service of interrupt vectors.  But all of this in due time.


K Zorro Expansion Bus / Zorro II Compatibility

The A3000 bus is a rather extensive superset of the A2000 bus design.  The
compatibility is based on distinct bus modes, rather than a simple
extension to the existing bus mechanisms. Through the use of an integrated
bus controller (the  Fat Buster chip ), the expansion bus configures itself
differently for the 16-bit A2000-compatible Zorro II modes than the 32-bit
Zorro III modes.  As a result, while there are still only  100 pins  on the
expansion bus, some pins change function considerably depending on the bus
activity that's currently in progress.  While the Zorro II modes of the
Zorro III bus are as compatible as possible with the Zorro II bus
specification (especially the A2000 implementation of this specification),
there are some small differences between the two expansion buses.

Aside from these differences, in general, it's important to understand the
Zorro II bus in order to understand the Zorro III bus.  The general
features of the A3000 bus, like  autoconfiguration , the master-slave bus
architecture, and the physical attributes come from the Zorro II expansion
bus.  Other features of the Zorro III bus address shortcomings of the
Zorro II architecture, but Zorro II has a hand in how some of these
shortcomings are solved under Zorro III.  Those with a full understanding
of the Zorro II bus will mainly be concerned with the possible bus
incompatibilities listed here.

 Changes from the A2000 Bus      Signal Description
 Zorro II Bus Architecture


K / Zorro II Compatibility / Changes from the A2000 Bus

While much effort has been made to assure that the Zorro II mode of the
A3000 bus is as compatible as possible with the A2000 bus, there are a
few points to consider here.  Primarily, the A3000's Zorro II modes are
driven with a state machine that emulates the  68000 bus  protocol.
This emulation must be based on the published Motorola specifications
detailing 68000 bus behavior. While this has the interesting effect of
changing the Zorro II bus from CPU dependent to CPU independent,
there's some margin for trouble.  Zorro II PICs also designed to these
specifications should have no trouble in the A3000 bus in most cases.
However, anything designed based on observed 68000 behavior rather than
documented 68000 operation is at serious risk of failing in an A3000
bus, as one might expect. There are also actual documented differences,
which are listed below.

 6800 Bus Interface                          Intelligent Cycle Spacing
 Bus Memory Mapping and Cache Support        Bus Drive and Termination
 Bus Synchronization Delays                  DMA Latency and Overlap
 Zorro II Master Access to Local Slaves      Power Supply Differences
 Bus Arbitration and Fairness


K / / Changes from the A2000 Bus / 6800 Bus Interface

A major difference between the A3000 expansion bus in Zorro II mode and
the A2000 bus is the absence of the signals /VPA and /VMA, which comprise
the 6800/6502 peripheral support mechanism that's part of the 68000 bus
interface.  This mechanism was never a supported part of the Zorro II
specification, however, and it should not be used by any PIC.  Any Zorro
II PIC that depends on /VPA or /VMA will not work in the A3000 bus.  It
was, in fact, impossible to legally use this on the A2000 bus.  The
 E clock  is, however, supported on the Zorro III bus, though its duty
cycle may vary in some situations.


K / / Changes from A2000 Bus / Bus Memory Mapping and Cache Support

Another change to the Zorro II implementation is that the  bus mapping
logic works a little differently.  Zorro II address space is broken up
into memory and I/O address space.  Memory space is the standard 8
megabyte space from $00200000-$009FFFFF.  The I/O address space is mapped
at $00E80000-$00EFFFFF, and a new 1.5 megabyte section (previously
reserved for motherboard devices) from $00A00000-$00B7FFFF.  Zorro II
cycles are not generated for non-Zorro II address space, even for 68000
space resources on the local bus.  So, for example, a CPU access to chip
memory would be visible to a Zorro II PIC in an A2000 backplane, but
invisible to that same PIC in an A3000 backplane.  Since this extra
information on the Zorro II backplane can't be legally used by any PIC
anyway, it should not be used by any existing A2000 PICs.

The reason for the two distinct mapping regions is for  cache support  of
Zorro II PICs.  All access by the local bus* master to Zorro II memory
space results in the local bus cache enable signal being driven and a full
port read (e.g., both bytes) regardless of the actual data transfer size
being requested.  A local bus access to Zorro II I/O space results in the
local bus cache disable signal being driven and the data strobes for reads
indicating the requested transfer size.  This cache mapping mechanism was
first implemented in the A2630 coprocessor card, so it's not an entirely
new concept.

 * The local bus, motherboard bus, and CPU bus are the same thing; the
   immediate 680x0 bus connected directly to the CPU in an Amiga
   computer. Current Amiga computers typically support three distinct
   buses; the expansion bus, local bus, and chip bus.  From the point of
   view of the expansion bus, the local and chip buses appear as a
   unified device which may be master or slave to the expansion bus.


K / / Changes from the A2000 Bus / Bus Synchronization Delays

Due to the  asynchronous  nature of the local-to-expansion bus interface
for Zorro II cycles, extra wait states may occasionally be added for local
to expansion or expansion to local cycles.  These are generally manifested
as delays between consecutive cycles, since the bus controller is not
going to require extra waiting during the cycle -- things will have
already been synchronized at that point.  The synchronization problems get
more difficult for Zorro II master access to local bus slaves, and as a
result, wait states here are very common.  The actual number of wait
states generated in any case will be based on the particular
implementation.


K / / Changes from A2000 Bus / Zorro II Master Access to Local Slaves

The only supported local bus resource that's guaranteed accessible to a
Zorro II expansion bus master as a slave device is chip bus memory.  All
I/O devices are implementation dependent and not supportable via DMA.  Any
attempted access to unsupported local bus resources as expansion slaves
will result in an  error  condition being signaled on both the local and
the expansion buses.  Most other local bus resources, such as local bus
fast memory, are located outside of Zorro II space on most systems and
obviously not available to Zorro II masters.


K / / Changes from the A2000 Bus / Bus Arbitration and Fairness

The Zorro II bus is now arbitrated fairly.  The normal slot-based order of
precedence is given to requesting devices, just as in the A2000
implementation.  As always, once a bus master assumes bus mastership, it
has the bus for as long as it wants the bus (of course, trouble can result
if a device takes the bus over for too long).  Once a master gives up the
bus, it will not be granted it back until all subsequent requests have
been serviced.

Bus arbitration at its best will be slightly slower than in the A2000
implementation, due to the fairness logic, but it is impossible to jam the
arbiter with  asynchronous  bus requests as in the A2000.  The new style
arbiter also holds off bus grants while hidden local bus cycles are in
progress, so there's no guarantee of a minimum time between bus request
and bus grant specified.


K / / Changes from the A2000 Bus / Intelligent Cycle Spacing

In order to permit a free intermix of Zorro II and Zorro III cycles, the
bus control logic is capable of making intelligent decisions when spacing
bus cycles.  In somc cases, a Zorro II cycle has some component that would
naturally extend into a following cycle.  The cycle spacing logic detects
such a condition, and refuses to start a new cycle until the current one
is complete, even if this extends beyond the defined bounds of a Zorro II
cycle.

For Zorro II PICs that really follow the Zorro II specifications, this
should have no effect.  However, any Zorro II PIC that holds signals much
beyond the end of a cycle, especially critical signals like  /SLAVE  and
 /DTACK , will likely incur additional wait states on the Zorro III bus.
This is not intended as a license for making sloppy expansion card
designs, just an acknowledgement that some Zorro II devices may cause a
conflict with the faster Zorro III bus  timings . The best approach is to
make them work, even with a possible performance penalty.


K / / Changes from the A2000 Bus / Bus Drive and Termination

Finally, the Zorro III bus uses different bus termination than that in the
A2000.  The Zorro II specification didn't specify the termination
expected; backplanes were built that didn't even have termination.  The
A2000 bus used a circuit consisting of a capacitor in series with a
resistor to ground for most of the bus signals.  This has good reflection
cancelling properties without increasing crosstalk (a major concern on the
2-layer A2000 motherboard), but it does slow operations down measureably.

The main reason for the change on the A3000 backplane is to support the
faster Zorro III bus modes.  The multi-layer A3000 motherboard permits a
reasonably high current bus without undue crosstalk.  The thevenin
termination makes switching logic levels start from a midpoint instead of
a rail, especially for a bus coming out of tri-state (which, based on the
Zorro III design, happens constantly). This should not cause problems with
Zorro II cards, but it's conceivable that some cards may need to be
adjusted to work in this bus (the Zorro III bus requires somewhat higher
current capability than the Zorro II bus does.  The A3000 does not support
enough slots for loading to be a likely problem, but future Zorro III
backplanes will have more slots and make this an important consideration).

                                                    o  +5V
                                                    |
                                                    |
                |\                                  \
      LS or ALS | \____                             /
         Driver | /    |                            \  220W
                |/    _|_                           /
                      ___ 0.01mF                    \
                       |                            /
                       |                     |\     |
                       \            F Driver | \____|
                       /                     | /    |
                       \  1KW                |/     |
                       /                            \
                       \                            /
      a) A2000 Bus     /                            \  330W
         Termination   |                            /
                     __|__                          \
                      ___          b) A3000 Bus     /
                       _              Termination   |
                                                  __|__
                                                   ___
                                                    _

            Figure K-2: A2000 vs. A3000 Bus Termination


K / / Changes from the A2000 Bus / DMA Latency and Overlap

Zorro II bus masters in a Zorro III backplane will, in many cases, receive
a bus grant much sooner than they would in a standard Zorro II backplane.
Additionally, in some cases, expansion bus cycles will overlap local bus
cycles.  The latency incurred on the Zorro II bus during heavy custom chip
activity has been greatly reduced for any Zorro III bus master. This
should be transparent to the card in question, though keep this in mind.


K / / Changes from the A2000 Bus / Power Supply Differences

The Zorro II bus is defined as supplying  +5VDC  @ 2 Amps to each slot,
with one slot per backplane supplying 5.0VDC @ 4.0 Amps.  The Zorro III bus
only provides the 5.0VDC @ 2.0 Amps for each slot.


K / Zorro II Compatibility / Zorro II Bus Architecture

The Zorro II bus is a simple extension of the 68000 processor bus.  Those
without a working knowledge of the 68000 local bus will find The 68000
User's Manual from Motorola an excellent reference for many Zorro II
issues.  The A500/A2000 Technical Reference Manual from Commodore-Amiga is
also required reading for any Zorro II design issues, as it includes a
complete description of all the Amiga details that aren't part
of the 68000 specification.

The basic Zorro II bus is a buffered version of the 68000 processor bus,
physically provided on a  100-pin  one-piece connector. The bus is 16 bits
wide, and provides 24 bits of addressing information.  A bus cycle looks
exactly like a 68000 bus cycle.  The cycle is defined by an address
strobe, terminated by a data transfer strobe, and qualified by a
read/write strobe, some memory space qualifiers, and one or two byte
selection strobes.  The basic bus cycle runs for a total of four cycles of
a 7.16MHz clock, though it can be extended to add wait states when
required.

The Zorro II bus adds a number of features to the basic 68000 CPU bus.  It
supplies some Amiga system signals that are useful for expansion card
designs, such as many of the Amiga system clocks.  The bus provides a
default data transfer signal, which expansion cards can easily use and
modify rather than go to the trouble of creating their own.  It provides a
number of discrete interrupt lines which are mixed to provide the 68000
with its standard encoded interrupts.  The 68000 bus arbitration protocol
is used to allow multiple bus masters; arbitration of the bus requests
are managed by the Zorro II bus controller to avoid contention between
multiple masters. And, of course, the bus supplies a number of supply
voltages for  powering  cards.

A powerful aspect of the Zorro II bus is its convention for automatically
configuring expansion cards, AUTOCONFIG(TM)  On system powerup, the system
software interrogates each board to determine what kind of board is
installed and how much memory space it needs on the bus.  The software
then tells each board where to reside in memory.  The bus provides
hardware lines to allow the boards to be configured in a daisy chained
fashion regardless of which slots they occupy and to prevent damage to
boards if accidently configured to reside at the same memory location.
Firmware standards also permit software to autoboot or autoinitialize any
board, to match soft-loaded device drivers with individual boards, and to
link memory boards into the appropriate system memory lists.


K / Zorro II Compatibility / Signal Description

The Zorro II bus can be broken down into various logical signal groups.
Some of these groups are unchanged in the Zorro III bus modes, others are
drastically different.  This section makes note of the original Zorro II
name for each signal and the current Zorro III  physical pin name  for each
signal, where different.  Some of this information will be repeated in the
Zorro III sections, where appropriate; nothing in this section is
considered critical to understanding the Zorro III bus, but it is useful.
As previously mentioned, the A2000 bus  signals unsupported  by the
Zorro II specification have been deleted from the Zorro III specification
and the A3000 implementation of Zorro III; this section will, however,
document those signals for reference purposes. Please see the
 Physical and Logical Signal Names  section for a complete list with pin
numbers of the various logical signals that appear on the physical bus
during the different phases of the Zorro II and Zorro III bus cycles.

 Power Connections           Slot Control Signals
 Clock Signals               DMA Control Signals
 System Control Signals      Addressing and Control Signals


K / / Signal Description / Power Connections

The Zorro III expansion bus provides several different  voltages  designed
to supply expansion devices.  There are no changes here that affect Zorro
II cards.

Digital Ground (Ground)
   This is the digital supply ground used by all expansion cards as the
   return path for all expansion supplies.

Main Supply (+5VDC)
   This is the main power supply for all expansion cards, and it is
   capable of sourcing large currents; each expansion slot can draw up
   to 2.0 Amps @ +5VDC. The extra power for one card in any backplane
   drawing up to  4.0 Amps  @ +5VDC is no longer supported.

Negative Supply (-5VDC)
   This is a negative version of the main supply, for small current
   loads only. There is no maximum load specified for the Zorro II bus
   on a per-slot basis; the A2000 implementation specifies  0.3 Amps @
   -5VDC for the entire system.

High Voltage Supply (+12VDC)
   This is a higher voltage supply, useful for communications cards and
   other devices requiring greater than digital voltage levels.  This is
   intended for relatively small current loads only. There is no maximum
   load specified for the Zorro II bus on a per-slot basis; the A2000
   implementation specifies 8.0 Amps @ +12VDC for the entire system,
   most of which is normally devoted to floppy and hard disk drive
   motors, not slots.

Negative High Supply (-12VDC)
   Negative version of the high voltage supply, also commonly used in
   communications applications, and similarly intended for small loads
   only. There is no maximum load specified for the Zorro II bus on a
   per-slot basis; the A2000 implementation specifies 0.3 Amps @ -12VDC
   for the entire.


K / / Signal Description / Clock Signals

The Zorro III expansion bus provides  clock signals  for expansion boards.
These clocks are for  synchronous  Zorro II designs and for other
synchronous activity such as bus arbitration.  While originally based on
Amiga local bus clocks, these have no guaranteed relationship to any local
bus activity in newer Amiga computers, but are maintained in Amiga
computers as part of the expansion bus specification.  The relationship
between these clocks is illustrated in Figure K-3.

/C1 Clock
   This is a 3.58 MHz clock (3.55 MHz on PAL systems) that's synched to
   the falling edge of the 7M system clock.

/C3 Clock
   This is a 3.58 MHz clock (3.55 MHz on PAL systems) that's synched to
   the rising edge of the 7M system clock.

CDAC Clock
   This is a 7.16 MHz system clock (7.09 MHz on PAL systems) which
   trails the 7M clock by 90 degrees (approximately 35ns).

E Clock
   This is the 68000 generated "E" clock, used for 6800 family
   peripherals driven by "E" and 6502 peripherals driven by phi(2).
   This clock is four 7M clocks high, six clocks low, as per the 68000
   spec.  Note that the bus does not support the rest of the 68000's
   6800/6502 compatible interface; there may be better ways to clock
   such devices.

E7M Clock
   This is the 7.16 MHz system clock (7.09 MHz on PAL systems).  This
   clock forms the basis for all  Zorro II/68000  compatible activity, and
   for various other system functions, such as bus arbitration.

           140ns
         |<----->|
      ___     ___     ___     ___     ___     ___     ___     ___     _
 C7M |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
     |   |___|   |___|   |___|   |___|   |___|   |___|   |___|   |___|

         |   | 75|   |
         | ->| ns|<- |
         | | |   |   |
     35->| |<-   |   |
     ns ___  |  ___  |  ___     ___     ___     ___     ___     ___
CDAC   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
     __|   |___|   |___|   |___|   |___|   |___|   |___|   |___|   |___
         |       |
         |   |   |   |
     ____    |    _______         _______         _______         _____
 /C1     |       |       |       |       |       |       |       |
         |_______|       |_______|       |_______|       |_______|

         |   |   |   |
      _______    |    _______         _______         _______         _
 /C3 |       |       |       |       |       |       |       |       |
     |       |_______|       |_______|       |_______|       |_______|
         |
         |   |   |   |
     ____    |   |   |                                    _____________
   E     |                                               |
         |_______________________________________________|

                     Figure K-3: Expansion Bus Clocks


K / / Signal Description / System Control Signals

The signals in this group are available for various types of system
control; most of these have an immediate or near immediate effect on
expansion cards and/or the system CPU itself.

Bus Error (/BERR)
   This is a general indicator of a bus fault condition.  Any expansion
   card capable of detecting a hardware error relating directly to that
   card can assert /BERR when that bus error condition is detected,
   especially any sort of harmful hardware error condition.  This signal
   is the strongest possible indicator of a bad situation, as it causes
   all PICs to get  off the bus, and will usually generate a level 2
   exception on the host CPU. For any condition that can be handled in
   software and doesn't pose an immediate threat to hardware,
   notification via a standard processor interrupt  is the better
   choice.  The bus controller will drive /BERR in the event of a
   detected bus collision or DMA error (an attempt by a bus master to
   access local bus resources it doesn't have valid access permission
   for). All cards must monitor /BERR and be prepared to tri-state all
   of their on-bus output buffers whenever this signal is asserted.  The
   current bus master should, if possible, retry the bus cycle after
   /BERR is negated unless conditions warrant otherwise.  Since any
   number of devices may assert /BERR, and all bus cards must monitor
   it, any device that drives /BERR must drive with an  open collector  or
   similar device capable of sinking at least 12ma, and any device that
   monitors /BERR should place a minimal load on it  (1 "F" type load or
   less).  This signal is pulled high by a passive backplane resistor.

System Reset (/RST, /BUSRST) := ( /RESET, /IORST ) for Zorro III
   The bus supplies two versions of the system reset signal.  The /RST
   signal is bidirectional and unbuffered, allowing an expansion card to
   hard reset the system.  It should only be used by boards that need
   this reset capability, and is driven only by an  open collector  or
   similar device.  The /BUSRST signal is a buffered output-only version
   of the reset signal that should be used as the normal reset input to
   boards not concerned with resetting the system on their own.  All
   expansion devices are required to reset their  autoconfiguration  logic
   when /BUSRST is asserted.  This signal is pulled high by a passive
   backplane resistor.

System Halt (/HLT)
   This signal is similar to the 68000 processor halt signal, and is
   driven by a PIC with an  open-collector  or similar gate only. Its main
   use is to indicate a full-system reset.  Based on the 68000
   conventions, an I/O-only reset, such as initiated by the 680x0 RESET
   instruction, will drive only /RST and /BUSRST on the bus.  A
   full-system reset, such as a powerup reset or a keyboard reset,
   drives /HLT low as well.  PICs that wish to reset the system CPU as
   well as the bus and I/O devices drive /RST and /HLT, some bus devices
   such as processor cards may internally reset only on full-system
   resets.  This signal is pulled high by a passive backplane resistor.

System Interrupts
   Six of the decoded, level sensitive 680x0 interrupt inputs were
   originally available on the expansion bus, and these are labelled as
   /INT2, /INT6, /EINT1, /EINT4, /EINT5, /EINT7 on the Zorro II bus.
   Only the /INT2 and /INT6 interrupt inputs are actually supported by
   Amiga, Inc. as part of the Zorro II specification; the A2000
   hardware did not provide the software with the required support
   mechanisms for the safe use of these lines. Each of these interrupt
   lines are shared by wired ORing, thus each line must be driven by an
    open-collector  or equivalent output type, and all are pulled high by
   passive backplane resistors.


K / / Signal Description / Slot Control Signals

This group of signals is responsible for the control of operations between
expansion slots.

Slave (/SLAVEn)
   Each slot has its own /SLAVE output, driven actively, all of which go
   into the collision detect circuitry.  The "n" refers to the expansion
   slot number of the particular /SLAVE signal. Whenever a Zorro II PIC
   is responding to an address on the bus, it must assert its /SLAVE
   output within 35ns of  /AS  asserted. The /SLAVE output must be negated
   at the end of a cycle within 50ns of  /AS  negated.  Late /SLAVE
   assertion on a Zorro II bus can result in loss of data setup times
   and other problems.  A late /SLAVE negation for Zorro II cards can
   cause a collision to be detected on the following cycle.  While the
   Zorro III sloppy cycle logic eliminates this fatal condition, late
   /SLAVE negation can nonetheless slow system performance
   unnecessarily.  If more than one /SLAVE output occurs for the same
   address, or if a PIC asserts its /SLAVE output for an address
   reserved by the local bus, a collision is registered and results in
    /BERR  being asserted.

Configuration Chain (/CFGINn, /CFGOUTn)
   The slot configuration mechanism uses the bus signals /CFGOUTn and
   /CFGINn, where "n" refers to the expansion slot number. Each slot has
   its own version of each, which make up the configuration chain
   between slots.  Each subsequent /CFGIN is a result of all previous
   /CFGOUTs, going from slot 0 to the last slot on the expansion bus.
   During the  AUTOCONFIG  process, an unconfigured Zorro PIC responds to
   the 64K address space starting at $00E80000 if its /CFGIN signal is
   asserted.  All unconfigured PICs start up with /CFGOUT negated.  When
   configured, or told to "shut up," a PIC will assert its /CFGOUT,
   which results in the /CFGIN of the next slot being asserted.  The
   backplane passes on the state of the previous /CFGOUT to the next
   /CFGIN for any slot not occupied by a PIC, so there's no need to
   sequentially populate the expansion bus slots.

Data Output Enable (DOE)
   This signal is used by an expansion card to enable the buffers on the
   data bus. The main Zorro II use of this line is to keep PICs from
   driving data on the bus until any other device is completely off the
   bus and the bus buffers are pointing in the correct direction.  This
   prevents any contention on the data bus.


K / / Signal Description / DMA Control Signals

There are various signals on the expansion bus that coordinate the
arbitration of bus masters.  Native Zorro III bus masters use some of the
same  logical signals , but their arbitration protocol is considerably
different.

PIC is DMA Owner (/OWN)
   This signal is asserted by an expansion bus DMA device when it
   becomes bus master. This output is to be treated as a wired-OR output
   between all expansion slots, any of which may have a PIC signaling
   bus mastership.  Thus, this should be driven with an  open-collector
   or similar output by any PIC using it.  This signal is the main basis
   for data direction calculations between the local and expansion
   busses, and is pulled up by a backplane resistor.

Slot Specific Bus Arbitration (/BRn, /BGn)
   These are the slot-specific /BRn and /BGn signals, where "n" refers
   to the expansion slot number. The bus request from each board is
   taken in by the bus controller and ultimately used to take over the
   system from 680x0 on the local bus.  The bus controller eventually
   returns one bus grant to the winner among all requesting PICs.  From
   the point of view of the individual PIC, the protocol is very similar
   to that of the 68000 arbitration mechanism.  The PIC asserts /BRn on
   the rising edge of  7M ; some time later, /BGn is returned on the
   falling edge of  7M .  The PIC waits for all bus activity to finish,
   asserts /OWN followed by /BGACK, then negates /BRn, assuming bus
   mastership. It retains mastership until it negates /BGACK followed by
   /OWN.

         ___     ___     ___     ___     ___     ___     ___     ___     _
    C7M |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
        |   |___|   |___|   |___|\  |___|   |___|\  |___|   |___|   |___|
                                  \               |
        ________                   \           ___|_______________________
    /BR         |                   |         |   |
                |___________________|_________|  /
                                    |           /
        _________________________   |          /  ________________________
    /BG                          |<-+         +->|
                                 |_______________|

         _________________________________________________________________
Signals |                           |           |                 |
        |___________________________|           |_________________|

        _________________________________                               __
   /OWN                                  |                             |
                                         |_____________________________|

        _____________________________________                        _____
 /BGACK                                      |                      |
                                             |______________________|

                   Figure K-4: Zorro II Bus Arbitration

Bus Grant Acknowledge (/BGACK)
   Any Zorro II PIC that receives a bus grant asserts this signal as
   long as it maintains bus mastery.  This signal may never be asserted
   until the bus grant has been received,  /AS  is negated,  /DTACK
   is negated, and /BGACK itself is negated, indicating that all other
   potential bus masters have relinquished the bus.  This output is
   driven as a wired-OR output, so all PICs must drive it with an
    open collector  or equivalent device, and a passive pullup is supplied
   by the backplane.

Bus Want/Clear (/GBG) := ( /BCLR ) for Zorro III
   This signal is asserted by the bus controller to indicate that a PIC
   wants to master the bus. A bus master assumes that the host CPU wants
   the bus, and that any time wasted as master is stealing time from the
   CPU.  To avoid such waste, a master should use  cache  or FIFO to grab
   slow-coming data, and then transfer it all at once.    /BCLR  is
   asserted to indicate that additionally, another PIC wants the bus,
   and the current bus master should get off as soon as possible.  This
   signal is equivalent to /GBG on the A2000 bus.


K / / Signal Description / Addressing and Control Signals

These signals are various items used for the addressing of devices in
Zorro II mode by the local bus and any expansion DMA devices.  Most of
these signals are very much like 68000 generated bus signals
bi-directionally buffered to allow any DMA device on the bus to drive the
local bus when such a device is the bus master.

Read Enable (READ)
   This is the read enable for the bus, which is equivalent to the
   68000's R/W output.  READ asserted during a bus cycle indicates a
   read cycle, READ negated indicates a write cycle.  Note that this
   signal may become valid in a cycle earlier than a 68000 R/W line
   would, but it  remains valid at least as long at the cycle's end.

Address Bus (A1-A23)
   This is logically equivalent to the 68000's address bus, providing 16
   megabytes of address space, although much of that space is not
   assigned to the expansion bus (see the memory map in  Figure K-1 .

Address Strobe  (/AS) := ( /CCS ) for Zorro III
   This is equivalent to the 68000 /AS, called  /CCS , for Compatibility
   Cycle Strobe, in the Zorro III nomenclature.  The falling edge of
   this strobe indicates that addresses are valid, the READ line is
   valid, and a Zorro II cycle is starting.  The rising edge signals the
   end of a Zorro II bus cycle, signaling the current slave to negate
   all slave-driven signals as quickly as possible.  Note that  /CCS ,
   like /AS, can stay asserted during a read-modify-write access over
   multiple cycle boundaries.  To correctly support such cycles, a
   device must consider both the state of  /CCS  and the state of the data
   strobes.  Many current Zorro II cards don't correctly support this
   680x0 style bus lock.

Data Bus (D0-D15)
   This is a buffered version of the 680x0 data bus, providing 16 bits
   of data accessible by word or either byte.  A PIC uses the  DOE  signal
   to determine when the bus is to be driven on reads, and the data
   strobes to determine when data is valid on writes.

Data Strobes (/UDS, /LDS) := ( /DS3, /DS2 ) for Zorro III
   These strobes fall on data valid during writes, and indicate byte
   select for both reads and writes.  The lower strobe is used for the
   lower byte (even byte), the upper strobe is used for the upper byte
   (odd byte).  There is one slight difference between these lines and
   the 68000 data strobes.  On reads of Zorro II memory space, both  /DS3
   and  /DS2  will be asserted, no matter what the actual size of the
   requested transfer is.  This is required to support caching of the
   Zorro II memory space.  For Zorro II I/O space, these strobes
   indicate the actual, requested byte enables, just as would a 68000
   bus master.

Data Transfer Acknowledge (/DTACK)
   This signal is used to normally terminate both Zorro bus cycles.  For
   Zorro II modes, it is equivalent to the 68000's Data Transfer
   Acknowledge input. It can be asserted by the bus slave during a Zorro
   II cycle at any time, but won't be sampled by the bus master until
   the falling edge of the S4 state on the bus.  Data will
   subsequently be latched on the S6 falling edge after this,
   and the cycle terminated with /AS negated during S7.  If a
   Zorro II slave does nothing, this /DTACK will be driven by the bus
   controller with no wait states, making the bus essentially a 4-cycle
    synchronous  bus.  Any slow device on the bus that needs wait states
   has two options.  It can modify the automatic /DTACK negating XRDY to
   hold off /DTACK.  Alternately, it may assert /OVR to inhibit the bus
   controller's generation of /DTACK, allowing the slave to create its
   own /DTACK.  Any /DTACK supplied by a slave must be driven with an
    open-collector  or similar type output; the backplane provides a
   passive pullup.

Processor Status (FC0-FC2)
   These signals are the cycle type or memory space bits, equivalent for
   the most part with the 68000 Processor Status outputs.  They function
   mainly as extensions to the bus address, indicating which type of
   access is taking place.  For Zorro II devices, any use of these lines
   must be gated with  /BGACK , since they are not driven valid by Zorro
   II bus masters.  However, when operating on the Zorro III backplane,
   Zorro II masters that don't drive the function codes will be seen
   generating an FC1 = 0, which results in a valid memory access.  Zorro
   II cycles are not generated for invalid memory spaces when the CPU is
   the bus master.

/DTACK Override (/OVR)
   This signal is driven by a Zorro II slave to allow that slave to
   prevent the bus controller's /DTACK generation.  This allows the
   slave to generate its own /DTACK.  The previous use of this line to
   disable motherboard memory mapping, which was unsupported on the
   A2000 expansion bus, has now been completely removed.  The use of
   XDRY or /OVR in combination with /DTACK is completely up to the board
   designer -- both methods are equally valid ways for a slave to delay
   /DTACK.  In  Zorro III mode , this pin is used for something completely
   different.

External Ready (XRDY)
   This active high signal allows a slave to delay the bus controller's
   assertion of /DTACK, in order to add wait states.  XRDY must be
   negated within 60ns of the bus master's assertion of /AS, and it will
   remain negated until the slave wants /DTACK.  The /DTACK signal will
   be asserted by the bus controller shortly following the assertion of
   XRDY, providing the bus cycle is a S4 or later.  XRDY is a wired-OR
   from all PICs, and as such, must be driven by an  open collector  or
   equivalent output.  In  Zorro III mode , this pin is used for something
   completely different.


K Zorro Expansion Bus / Zorro III Bus Architecture

While the Zorro II bus design was based in large part on an already
existing bus cycle, the 68000 cycle, the Zorro III bus design had a much
different set of preconditions.  It is not modeled after any particular
CPU specific bus protocol, but instead it's a logical outgrowth of both
the need to support Zorro II cards on the same bus and the need to achieve
various modern feature and preformance goals.  These goals were summarized
in the Zorro Expansion Bus  Introduction , now they'll be covered in
greater detail here.

 Basic Zorro III Bus Cycles       Quick Bus Arbitration
 Advanced Mode Support Logic      Quick Interrupts
 Multiple Transfer Cycles         Compatibility With Zorro II Devices


K / Zorro III Bus Architecture / Basic Zorro III Bus Cycles

The basic Zorro III bus cycle is a  multiplexed  address/data cycle which
supplies a full 32 bits worth of address and data per simple cycle.  The
cycle is a fully  asynchronous  cycle.  The bus master for a given cycle
supplies strobes to indicate when address is valid, write data is valid,
and read data may be driven.  In return, the bus slave for a cycle
supplies a strobe to indicate that it is responding to a bus address, and
a strobe to indicate that it is done with the bus data for a write cycle,
or has supplied valid bus data for a read cycle.  The minimum theoretical
bus speed is governed only by setup and hold time requirements for the
various bus signals.  Actual bus speeds are always a function of the bus
master and bus slave active for a given cycle.  This is considerably
different than the Zorro II bus, and for several good reasons, which are
explained below.

 Design Goals      Simple Bus Cycle Operation


K / / Basic Zorro III Bus Cycles / Design Goals

For any computer bus, there are two basic possibilities concerning the
fundamental operation of the bus; it's either synchronous or asynchronous.
The difference is simple -- the synchronous bus is ultimately tied to a
clock of some sort, while the asynchronous bus has no defined relationship
to any clock signal.  While Motorola specifies the 68000 bus cycle as an
asynchronous cycle, they're really referring to the fact that most 68000
inputs are internally synchronized with the bus clock, and therefore,
synchronous setup times on the bus do not have to be met to avoid
metastability.

But the  68000 bus, and the Zorro II bus  by extension, are synchronous
buses, based on a single bus clock (called  E7M  on the Zorro II bus).
Most Zorro II signals are asserted relative to an edge of the bus clock,
and most Zorro II inputs are sampled on an edge of the bus clock.  The
minimum Zorro II cycle is four bus clocks long, and every wait state
added, regardless of the method, will result in a single additional bus
clock wait, regardless of the asynchronous appearance of the  termination
and wait signals on the Zorro II bus.

The Zorro III bus is a fully asynchronous bus, in that all bus events are
driven by strobes, and there is no reference clock.  The choice of an
asynchronous versus a synchronous bus design is governed by the intended
application of the bus.  Synchronous designs are preferred when a CPU and
a memory system (e.g., master and slave) can be very tightly coupled to
each other.  Such designs generally require a tight adherence to  timing
based on the specific CPU.  This is optimal for tightly coupled systems,
such the fast memory on the A3000 local bus.  Synchronous designs can also
be easier to do accurately, as the designer can use clock edges for
scheduling events, and there's never any need to waste time in
synchronizers to achieve a reliable design.

The design goals for an expansion bus are considerably different. While a
fast memory circuit on a system motherboard can change for every new and
better design, it's not feasible to require redesign of any significant
number of expansion cards every time an improved motherboard design is
created.  And while a synchronous transfer can be optimal for matched
clocks, it can be very inefficient for mismatched CPU and expansion
clocks, as synchronizer delays must be introduced for any reliable
operation.  The A3000 project started with the need to support CPU systems
at 16MHz and at 25MHz, and it's obvious that the growth of CPU clock speed
will be here for some time to come.  Zorro III cards are based on
asynchronous handshaking between master and slave in both directions. This
means that, as long as masters and slaves manage their own needs, any
slave can work with any master.  But as masters and slaves improve with
technology, bus transfer speeds can automatically increase, without
rendering any slower cards obsolete.  The Zorro III bus attempts to
address the needs of device expansion as much as the needs of memory
expansion.


K / / Basic Zorro III Bus Cycles / Simple Bus Cycle Operation

The normal Zorro III bus cycle is quite different than the Zorro II bus in
many respects. Figure K-5 shows the basic cycle.  There is no bus clock
visible on the expansion bus; the standard Zorro II clocks are still
active during Zorro III cycles, but they have no relationship to the Zorro
II bus cycle.  Every bus event is based on a relationship to a particular
bus strobe, and strobes are alternately supplied by master and slave.

           ______      READ CYCLE       ______      WRITE CYCLE       ____
      /FCS       \                     /      \                      /
                  \___________________/        \____________________/

               address     data from slave  address   data from master
                 _|_      ___________|___     _|_      _____|_______
 AD31..AD8 _____/ | \____/        /  |   \___/ | \____/     |       \_____
                \___/    \________\______/   \___/    \_____________/
                 _______________________      _______________________
  SA7..SA2 _____/                       \____/                       \____
  FC2..FC0      \_______________________/    \_______________________/
           __________________________________                         ____
      READ     /                             \                       /
           ___/                               \_____________________/
           ___________                   __________                   ____
    /SLAVE            \                 /          \                 /
                       \_______________/            \_______________/
                         ______________               ______________
       DOE              /              \             /              \
           ____________/                \___________/                \____
           _______________               ______________               ____
/DS3../DS0                \             /              \             /
                           \___________/                \___________/
           _____________________         ____________________         ____
                                \       /                    \       /
    /DTACK                       \_____/                      \_____/

                    Figure K-5: Basic Zorro III Cycles

A Zorro III cycle begins when the bus master simultaneously drives
addressing information on the address bus and memory space codes on the
 FCn  lines, quickly following that with the assertion of the Full Cycle
Strobe,  /FCS ; this is called the address phase of the bus.  Any active
slaves will latch the bus address on the falling edge of  /FCS , and the
bus master will tri-state the addressing information very shortly after
 /FCS  is asserted. It's necessary only to latch  A31-A8 ; the low order
 A7-A2  addresses and @" FCn " link K-4-6 28} codes are non-multiplexed.

As quickly as possible after  /FCS  is asserted, a slave device will
respond to the bus address by asserting its  /SLAVEn  line, and possibly
other special-purpose signals.  The  autoconfiguration  process assigns a
unique address range to each PIC base on its needs, just as on the Zorro
II bus. Only one slave may respond to any given bus address; the bus
controller will generate a  /BERR  signal if more than one slave responds
to an address, or if a single slave responds to an address reserved for
the local bus (this is called a bus collision, and should never happen in
normal operation). Slaves don't usually respond to CPU memory space or
other reserved memory space types, as indicated by the  memory space  code
on the  FCn  lines (see the  Signal Description  section following this
section for details).

The data phase is the next part of the cycle, and it's started when the
bus master asserts  DOE  onto the bus, indicating that data operations can
be started.  The strobes are the same for both read and write cycles, but
the data transfer direction is different.

For a read cycle, the bus master drives at least one of the data strobes
 /DSn , indicating the physical transfer size requested (however, cachable
slaves must always supply all 32 bits of data).  The slave responds by
driving data onto the bus, and then asserting  /DTACK . The bus master
then terminates the cycle by negating  /FCS , at which point the slave
will negate its  /SLAVEn  line and tri-state its data. The cycle is done
at this point. There are a few actions that modify a cycle  termination ,
those will be covered in later sections.

The write cycle starts out the same way, up until  DOE  is asserted.  At
this point, it's the master that must drive data onto the bus, and then
assert at least one  /DSn  line to indicate to the slave that data is
valid and which data bytes are being written.  The slave has the data for
its use until it terminates the cycle by asserting  /DTACK , at which
point the master can negate  /FCS  and tri-state its data at any point.
For maximum bus bandwidth, the slave can latch data on the falling edge of
the logically ORed data strobes; the bus master doesn't sample  /DTACK
until after the data strobes are asserted, so a slave can actually assert
 /DTACK  any time after  /FCS .


K / Zorro III Bus Architecture / Advanced Mode Support Logic

The Zorro III bus provides support for some more advanced operations that
weren't generally handled correctly on the Zorro II bus.  Amiga computers
have traditionally been supporting features that the more mainstream
personal computers haven't.  High speed DMA transfers and expansion
coprocessors such as the Bridge Cards have been with the Amiga since the
early days, and high performance main system CPUs with cache memory are
now becoming common.  The Zorro II bus never properly or easily supported
such devices; the Zorro III bus attempts to make support of cache and
coprocessor both possible and relatively straightforward.  Other new
features are covered in later sections.

 Bus Locking      Cache Support


K / / Advanced Mode Support Logic / Bus Locking

The first advanced modification of the basic bus cycle is bus locking, via
the /LOCK signal.  Bus locking is a hardware convention that allows a bus
master to guarantee several cycles will be atomic on the bus. This is
necessary to support the sharing of special "mail-box" memory between a
bus master and an alternate PIC-based processor; Bridge Cards are an
example of this kind of device. The Zorro II bus itself supports bus
locking via the 68000 convention.  However, the 68000 style of bus locking
is often difficult to implement, and support for it was often ignored in
Zorro II designs, especially those not directly concerned with
multiprocessor support.

The Zorro III mechanism involves no change to the basic bus cycle, other
than the monitoring of this /LOCK signal, and as such is much more
reasonable to support.  The /LOCK signal is asserted by a bus master at
address time and maintained across cycles to lock out shared memory
coprocessors, allowing hardware backed semaphores to easily be used
between such coprocessors.  We expect multiprocessing will be a greater
concern on the Zorro III bus than it is at present;  video coprocessors,
RISC devices, and special purpose processors for image processing or
mathematics should find a comfortable home on the Zorro III bus.


K / / Advanced Mode Support Logic / Cache Support

The other advanced cycle modifier on the Zorro III bus is the cache
inhibit line,  /CINH .  On the Zorro II bus, there was originally no
caching envisioned, and therefore no real support for caching of Zorro II
PICs. First in the A2630 and later in the Zorro III bus' emulation of
Zorro II, conventions were adopted to permit caching of Zorro II cards.
These conventions aren't perfect; MMU tables will sometimes have to
supplant this geographic mapping.  While Zorro III doesn't have any cache
consistency mechanisms for managing caches between several caching bus
masters, it does allow cards that absolutely must not be cached to assert
a cache inhibit line,  /CINH , on a per-cycle basis (asserted at slave
time by a responding slave).  This cache management is basically the
lowest level of a cache management system, mainly useful for support of
I/O and other devices that shouldn't be cached.  Software will be required
for the higher levels of cache management.


K / Zorro III Bus Architecture / Multiple Transfer Cycles

The multiplexed address/data design of the Zorro III bus has some definite
advantages.  It allows Zorro III cards to use the same  100-pin  connector
as the Zorro II cards, which results in every bus slot being a 32-bit
slot, even if there's an alternate connector in-line with any or all of
the system slots; current alternate connectors include  Amiga Video  and
 PC-AT  (now sometimes called ISA, for Industry Standard Architecture, now
that it's basically beyond the control of IBM)  compatible connectors .
This design also makes implementation of the bus controller for a system
such as the A3000 simpler.  And it can result in lower cost for Zorro III
PICs in many cases.

The main disadvantage of the multiplexed bus is that the multiplexing can
waste time.  The address access time is the same for multiplexed and
non-multiplexed buses, but because of the multiplexing time, Zorro III
PICs must wait until data time to assert data, which places a fixed limit
on how soon data can be valid.  The Zorro III Multiple Transfer Cycle is a
special mode designed to allow the bus to approach the speed of a
non-multiplexed design.  This mode is especially effective for high speed
transfers between memory and I/O cards.

As the name implies, the Multiple Transfer Cycle is an extension of the
basic full cycle that results in multiple 32-bit transfers. It starts with
a normal full cycle address phase transaction, where the bus master drives
the 32-bit address and asserts the  /FCS  signal.  A master capable of
supporting a Multiple Transfer Cycle will also assert  /MTCR  at the same
time as  /FCS . The slave latches the address and responds by asserting
its  /SLAVEn  line.  If the slave is capable of multiple transfers, it'll
also assert  /MTACK , indicating to the bus master that it's capable of
this extended cycle form.  If either  /MTCR  or  /MTACK  is negated for a
cycle, that cycle will be a basic full cycle.

           ______                                                 ________
      /FCS       \                                               /
                  \_____________________________________________/

              address      data from slave    data from master
              ___|__     _____|_______|_________|___________|___
 AD31..AD8 __/   |  \___/   / | \   / | \   /   |   \   /   |   \_________
             \______/   \___\___/___\___/___\_______/___\_______/
           _______________       ___       ___       ___       ___________
     /MTCR                \     /   \     /   \     /   \     /
                           \___/     \___/     \___/     \___/
              _______________________________________________
  SA7..SA2 __/                 \   /     \   /     \   /     \____________
  FC2..FC0   \_________________/___\_____/___\_____/___\_____/
           ________________________________                     __________
      READ                                 \                   /
                                            \_________________/
                        ______________________________________
       DOE             /                                      \
           ___________/                                        \__________
           _______________       ___       ___       ___       ___________
/DS3../DS0                \     /   \     /   \     /   \     /
                           \___/     \___/     \___/     \___/
           ___________                                 ___________________
    /MTACK            \                               /
                       \_____________________________/
           __________________      ____      ____      ____      _________
    /DTACK                   \    /    \    /    \    /    \    /
                              \__/      \__/      \__/      \__/

                   Figure K-6: Multiple Transfer Cycles

Assuming the multiple transfer handshake goes through, the multiple cycle
continues to look similar to the basic cycle into the data phase.  The bus
master asserts  DOE  (possibly with write data) and the appropriate
 /DSn , then the slave responds with  /DTACK  (possibly with read data at
the same time), just as usual. Following this, however, the cycle's
character changes. Instead of terminating the cycle by negating  /FCS ,
 /DSn , and  DOE , the master negates  /DSn  and  /MTCR , but maintains
 /FCS  and  DOE . The slave continues to assert  /SLAVEn , and the bus
goes into what's called a short cycle.

The short cycle begins with the bus master driving the low order address
lines  A7-A2 ; these are the non-multiplexed addresses and can change
without a new address phase being required (this is essentially a page
mode, fully random accesses on this 256-byte page). The  READ  line may
also change at this time.  The master will then assert  /MTCR  to indicate
to the slave that the short cycle is starting.  For reads, the appropriate
 /DSn  are asserted simultaneously with  /MTCR , for writes, data and
 /DSn  are asserted slightly after  /MTCR . The slave will supply data for
reads, then assert  /DTACK , and the bus will terminate the short cycle
and start into either another short cycle or a full cycle, depending on
the multiple cycle handshaking that has taken place.

The question of whether a subsequent cycle will be a full cycle or a short
cycle is answered by multiple cycle arbitration.  If the master can't
sustain another short cycle, it will negate  /FCS  and  DOE  along with
 /MTCR  at the end of the current short cycle, terminating the full cycle
as well. The master always samples the state of  /MTACK  on the falling
edge of  /MTCR .  If a slave can't support additional short cycles, it
negates  /MTACK  one short cycle ahead of time.  On the following short
cycle, the bus master will see that no more short cycles can be handled by
the slave, and fully terminate the multiple transfer cycle once this last
short cycle is done.

PICs aren't absolutely required to support Multiple Transfer Cycles,
though it is a highly recommended feature, especially for memory boards.
And of course, all PICs must act intelligently about such cycles on the
bus; a card doesn't request or acknowledge any Multiple Transfer Cycle it
can't support.


K / Zorro III Bus Architecture / Quick Bus Arbitration

The Zorro II bus does an adequate job of supporting multiple bus masters,
and the Zorro III bus extends this somewhat by introducing
 fair arbitration  to Zorro II cards.  However, some desirable features
cannot be added directly to the Zorro II arbitration protocol.
Specifically, Zorro III bus arbitration is much faster than the Zorro II
style, it prohibits bus hogging that's possible under the Zorro II
protocol, and it supports intelligent bus load balancing.

Load balancing requires a bit of explanation.  A good analogy is to that
of software multitasking; there, an operating system attempts to slice up
CPU time between all tasks that need such time; here, a bus controller
attempts to slice up bus time between all masters that need such time.
With preemptive multitasking such as in the Amiga and UNIX OSs,  equal CPU
time can be granted to every task (possibly modified by priority levels),
and such scheduling is completely under control of the OS; no task can hog
the CPU time at the expense of all others.  An alternate multitasking
scheme is a popular add-on to some originally non-multitasking operating
systems lately. In this scheme, each task has the CPU until it decides to
give up the CPU, basically making the effectiveness of the CPU sharing at
the mercy of each task.  This is exactly the same situation with masters
on the Zorro II bus. The Zorro III arbitration mechanism attempts to make
bus scheduling under the control of the bus controller, with masters each
being scheduled on a cycle-by-cycle basis.

When a Zorro III PIC wants to master the bus, it registers with the bus
controller.  This tells the bus controller to include that PIC in its
scheduling of the expansion bus.  There may be any number of other PICs
registered with the bus controller at any given time.  The CPU is always
scheduled expansion bus time, and other local bus devices, such as a hard
disk controller, may be registered from time to time.

Once registered, a PIC sits idle until it receives a grant from the bus
controller.  A grant is permission from the bus controller that allows the
PIC to master the Zorro III bus for one full cycle.  A PIC always gets one
full cycle of bus time when given a grant, and assuming it stays
registered, it may receive additional full cycles.  Within the full cycle,
the PIC may run any number of  Multiple Transfer Cycles , assuming of
course the responding slave supports such cycles.  For multiprocessor
support, a PIC will be granted multiple atomic full cycles if it locks the
bus.  This feature is only for support of hardware semaphores and other
such multiprocessor needs; it is not intended as a means of bus hogging!

        ___     ___     ___     ___     ___     ___     ___     ___     __
   C7M |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
       |   |___|   |___|   |___|   |___|   |___|   |___|   |___|   |___|

                Register                       Unregister
       ________         _______________________         __________________
  /BRn         |       |                       |       |
               |_______|                       |_______|
       __________________________        _________________________________
  /BGn                           |      |
                                 |______|
       ______________________________                      _______________
  /FCS                               |                    |
                                     |____________________|
       _____________________                                ______________
  /OWN                      |                              |
                            |______________________________|
       _______________________                                ____________
/BGACK                        |                              |
                              |______________________________|

                  Figure K-7: Zorro III Bus Arbitration

Figure K-7 shows the basics of Zorro III bus arbitration. While it uses
some of the same signals as the  680x0 inspired Zorro II bus  arbitration
mechanism, it has nothing to do with 680x0 bus arbitration; the  /BRn  and
 /BGn  signals should be thought of as completely new signals.  In order
to register with the bus controller as a bus master, a PIC asserts its
private  /BRn  strobe on the rising edge of the  7M  clock, and negates it
on the next rising edge.  The bus controller will indicate mastership to a
registered bus master by asserting its  /BGn .

Once granted the bus, the PIC drives only the standard cycle signals:
addresses,  /FCS , /EDSn, data, etc. in a full cycle. The bus controller
manages the assertion of  /OWN  and  /BGACK , which are important only for
bus management and Zorro II support.  While a scheduling scheme isn't part
of this bus specification, the bus master will only be guaranteed one bus
cycle at a time. The  /BGn  line is negated shortly after the master
asserts  /FCS  unless the bus controller is planning to grant multiple
full cycles to the master. A locked bus will force the controller to grant
multiple full cycles. Any master that works better with multiple cycles,
such as devices with buffers to empty into memory, should run a
 Multiple Transfer Cycle  to transfer several longwords during the same
full cycle.  For this reason, slave cards are encouraged to support
 Multiple Transfer Cycles , even if they don't necessarily run any faster
during them.

Once a registered bus master has no more work to do, it unregisters with
the bus controller. This works just like registering -- the PIC asserts
 /BRn  on the rise of  7M , then negates it on next rising  7M .  This is
best done during the last cycle the bus master requires on the bus.  If a
registered master gets a grant before unregistering and has no work to do,
it can unregister without asserting  /FCS , to give back the bus without
runing a cycle. It's always far better to make sure that the master
unregisters as quickly as possible.  Bus timeout causes an automatic
unregistering of the registered master that was granted that timed-out
cycle; this guarantees that an inactive registered master can't drag down
the system. If a master sees a  /BERR  during a cycle, it should terminate
that cycle immediately and re-try the same cycle.  If the retried cycle
results in a  /BERR  as well, nothing more can be done in hardware;
notification of the driver program is the usual recourse.

The bus controller may have to mix Zorro II style bus arbitration in with
Zorro III arbitration, as Zorro II and Zorro III cards can be freely mixed
in a backplane.  Because of this,  Multiple Transfer Cycles , and the
self-timed nature of Zorro III cards, there's no way to guarantee the
latency between bus grants for a Zorro III card.  The bus controller does,
however, make sure that all masters are  fairly  scheduled so that no
starvation occurs, if at all possible.  Zorro III cards must use Zorro III
style bus arbitration; although current Zorro III backplanes can't
differentiate between Zorro II and Zorro III cards when they request
(other than by the request mechanism), it can't be assumed that a
backplane will support Zorro III cycles with Zorro II mastering, or
visa-versa.


K / Zorro III Bus Architecture / Quick Interrupts

While the Zorro II bus has always supported shared interrupts, the Zorro
III bus supports a mechanism wherein the interrupting PIC can supply its
own vector.  This has the potential to make such vectored interrupts much
faster than conventional Zorro II chained interrupts, arbitrating the
interrupting device in hardware instead of software.

A PIC supporting quick interrupts has on-board  registers  to store one or
more vector numbers; the numbers are obtained from the OS by the device
driver for the PIC, and the PIC/driver combination must be able to handle
the situation in which no additional vectors are available.  During system
operation, this PIC will interrupt the system in the normal manner, by
asserting one of the bus interrupt lines.  This interrupt will cause an
interrupt vector cycle to take place on the bus.  This cycle arbitrates in
hardware between all PICs asserting that interrupt, and it's a completely
different type of Zorro III cycle, as illustrated in Figure K-8.

              _____     POLL PHASE                 VECTOR PHASE      _____
         /FCS      \                                                /
                    \______________________________________________/
              _______                 _____                          _____
        /MTCR        \               /     \                        /
                      \_____________/       \______________________/
              ____________            _____                          _____
       /SLAVE             \          /     \                        /
                           \________/       \______________________/
                   ____________________
   AD19..AD16 ____/                    \__________________________________
SA3,SA2,/LOCK     \____________________/
                                             ______________________
          DOE                               /                      \
              _____________________________/                        \_____
              _____________________________                          _____
         /DS0                              \                        /
                                            \______________________/

                                                         data from slave
                                              _________________|_____
     SD7..SD0 _______________________________/            /    |     \____
                                             \____________\__________/
              ____________________________________________            ____
       /DTACK                                             \          /
                                                           \________/

                    Figure K-8: Interrupt Vector Cycle

The bus controller will start an interrupt vector cycle in response to an
interrupt asserted by any PIC.  This cycle starts with  /FCS  and  /MTCR
asserted, a FC code of 7 (CPU space), a CPU space cycle type, given by
address lines  A16-A19 , of 15, and the interrupt number, which is on
 A1-A3  (A1 is on the  /LOCK  line, as in Zorro II cycles). The interrupt
numbers 2 and 6 are currently defined, corresponding to  /INT2 and /INT6
respectively; all others are reserved for future use.  At this point,
called the polling phase, any PIC that has asserted an interrupt and wants
to supply a vector will decode the FC lines, the cycle type, match its
interrupt number against the one on the bus, and assert  /SLAVEn  if a
match occurs. Shortly thereafter, the  /MTCR  line is negated, and the
slaves all negate  /SLAVEn . But the cycle doesn't end.

The next step is called the vector phase.  The bus controller asserts one
 /SLAVEn  back to one of the interrupting PICs, along with  /MTCR  and
 /DS0 , but no addresses are supplied. That PIC will then assert its 8 bit
vector onto the logical  D0-D7  (physically AD15-AD8) of the 32-bit data
bus and  /DTACK , as quickly as possible, thus terminating the cycle. The
speed here is very critical; an automatic autovector timeout will occur
very quickly, as any actual waiting that's required for the quick
interrupt vector is potentially delaying the autovector response for Zorro
II style interrupts.  A PIC stops driving its interrupt when it gets the
response cycle; it must also be possible for this interrupt to be cleared
in software (e.g., the PIC must make choice of vectoring vs. autovectoring
a software issue).


K / Zorro III Bus Architecture / Compatibility With Zorro II Devices

As detailed in the  Zorro II Compatibility  section, the Zorro III bus
supports a bus cycle mode very similar to the  68000-based Zorro II bus ,
and is expected to be compatible with all properly designed Zorro II PICs.
As shown in  Figure K-1 , Zorro II and Zorro III expansion spaces are
geographically mapped on the Zorro III bus. The mapping logic resides on
the bus, and operates on the bus address presented for any cycle.  Every
cycle starts out assuming a Zorro III cycle, but the mapping logic will
inscribe a Zorro II cycle within the Zorro III cycle if the address range
is right. Figure K-9 details the bus action for this mode.

           _____        READ CYCLE       ___       WRITE CYCLE        __
      /FCS      \                       /   \                        /
                 \_____________________/     \______________________/

                    /FCS sample edge
           __    __ /  __    __    __    __    __    __    __    __    _
      CDAC   |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
             |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|

            /DTACK sample edge        data latch edge
           _    __    __    __\   __ /  __    __    __    __    __    __
        7M  |  |30|  |32|  |34|  |36|  |  |  |30|  |32|  |34|  |36|  |
            |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|
                   31    33    35    37          31    33    35    37
           __________                 ____________                 _____
      /CCS           \               /            \               /
                      \_____________/              \_____________/

              address   data from slave   address    data from master
                _|_     ____________|__     _|_      _______|________
AD31..AD24 ____/ | \___/         /  |  \___/ | \____/       |        \__
               \___/   \_________\_____/   \___/    \________________/
                ______________________      _________________________
 AD23..AD8 ____/                      \____/                         \__
  SA7..SA2     \______________________/    \_________________________/
           ________________________________                           __
      READ    /                            \                         /
           __/                              \_______________________/
           _____________             _________________              ____
    /SLAVE              \           /                 \            /
                         \_________/                   \__________/
                              _______                        _______
       DOE                   /       \                      /       \
           _________________/         \____________________/         \__
           __________               _______________________        _____
 /DS3,/DS2           \             /                       \      /
                      \___________/                         \____/
           ___________________        _______________________        ___
    /DTACK                    \      /                       \      /
                               \____/                         \____/

                   Figure K-9 Zorro II Within Zorro III

The cycle starts out with the usual address phase activity; the bus master
asserts  /FCS  after asserting the full 32-bit address onto the address
bus. The bus decoder maps the bus address  asynchronously  and quickly, so
that by the time  /FCS  is asserted, the memory space is determined.  A
Zorro II space access will cause  A8-A23  to remain asserted, rather than
being tri-stated along with  A24-A31 , as the Zorro III cycle normally
does. The bus controller synchs the  asynchronous   /FCS  on the falling
edge of CDAC, then drives  /CCS  (the  /AS  equivalent) out on the rising
edge of  7M , based on that synched  /FCS . For a read cycle,  /DS3
and/or  /DS2  (the  /UDS  and  /LDS  replacements, respectively) would be
asserted along with  /CCS ; write cycles see those lines asserted on the
next rising edge of  7M , at S4 time. The  DOE  line is also asserted at
the start of S4.

The bus controller starts to sample  /DTACK  on the falling edge of  7M
between S4 and S5, adding wait states until  /DTACK  is encountered. As
per Zorro II specs, the PIC need not create a  /DTACK  unless it needs
that level of control; there are Zorro II signals to delay the
controller-generated  /DTACK , or take it over when necessary.  The
controller will drive its automatic  /DTACK  at the start of S4, leaving
plenty of time for the sampling to come at S5.  Once a  /DTACK  is
encountered, cycle  termination  begins.  The controller latches data on
the falling  7M  edge between S6 and S7, and also negates  /CCS  and the
 /DSn  at this time. Shortly thereafter, the controller negates  /DTACK
(when controlling it),  DOE , and tri-states the data bus, getting ready
for the next cycle.


K Zorro Expansion Bus / Signal Description

The signals detailed here are the Zorro III mode signals.  While some of
this information is the same as in the Zorro II  signal description  in the
Zorro II Compatibility section, many bus signals that seem alike behave
differently in Zorro III mode than Zorro II mode.  These can be a very
important differences; thus the complete set of signals is detailed here.

 Power Connections           DMA Control Signals
 Clock Signals               Address And Related Control Signals
 System Control Signals      Data And Related Control Signals
 Slot Control Signals


K / Signal Description / Power Connections

The expansion bus provides several different voltages designed to supply
expansion devices.  These are basically the same for the Zorro III bus as
they were for the Zorro II bus, with the exception of one pin, and that
the specification has been clarified a bit.  Note that all Zorro III PICs
must list their power consumption specifications.

Digital Ground (Ground)
   This is the digital supply ground used by all expansion cards as the
   return path for all expansion supplies.

Main Supply (+5VDC)
   This is the main power supply for all expansion cards, and it is
   capable of sourcing large currents; each PIC can draw up to
   2.0 Amps @ +5VDC.

Negative Supply (-5VDC)
   This is a negative version of the main supply, for small current
   loads only; each PIC can draw up to 60 mA @ -5VDC.

High Voltage Supply (+12VDC)
   This is a higher voltage supply, useful for communications cards and
   other devices requiring greater that digital voltage levels.  This is
   intended for relatively small current loads only; each PIC can draw
   up to 500mA @ +12VDC.

Negative High Supply (-12VDC)
   Negative version of the high voltage supply, also used in
   communications applications, and similarly intended for small loads
   only; each PIC can draw up to 60 mA @ -12VDC.


K / Signal Description / Clock Signals

The expansion bus provides clock signals for expansion boards.  The main
use for these clocks on Zorro III cards is bus arbitration clocking. There
is no relationship between any of these clocks and normal Zorro III bus
activity. The relationship between these clocks is illustrated in
 Figure K-3 .

/C1 Clock
   This is a 3.58 MHz clock (3.55 MHz on PAL systems) that's synched to
   the falling edge of the 7M system clock.

/C3 Clock
   This is a 3.58 MHz clock (3.55 MHz on PAL systems) that's synched to
   the rising edge of the 7M system clock.

CDAC Clock
   This is a 7.16 MHz system clock (7.09 MHz on PAL systems) which
   trails the 7M clock by 90 degrees (approximately 35ns).

E Clock
   This is the 68000 generated "E" clock, used for 6800 family
   peripherals driven by "E" and 6502 peripherals driven by phi(2). This
   clock is four 7M clocks high, six clocks low, as per the 68000 spec.

7M Clock
   This is the 7.16 MHz system clock (7.09 MHz on PAL systems).  This
   clock drives the bus master registration mechanism for Zorro III bus
   masters.


K / Signal Description / System Control Signals

The signals in this group are available for various types of system
control; most of these have an immediate or near immediate effect on
expansion cards and/or the system CPU itself.

Hardware Bus Error/Interrupt (/BERR)
   This is a general indicator of a bus fault or special condition of
   some kind. Any expansion card capable of detecting a hardware error
   relating directly to that card can assert /BERR when that bus error
   condition is detected, especially any sort of harmful hardware error
   condition.  This signal is the strongest possible indicator of a bad
   situation, as it causes all PICs to get off the bus, and will usually
   generate a level 2 exception on the host CPU. For any condition that
   can be handled in software and doesn't pose an immediate threat to
   hardware, notification via a standard processor interrupt is the
   better choice.  The bus controller will drive /BERR in the event of a
   detected bus collision or DMA error (an attempt by a bus master to
   access local bus resources it doesn't have valid access permission
   for). All cards must monitor /BERR and be prepared to tri-state all
   of their on-bus output buffers whenever this signal is asserted. An
   expansion bus master will attempt to retry a cycle aborted by a
   single /BERR and notify system software in the case of two subsequent
   /BERR results.   Since any number of devices may assert /BERR, and
   all bus cards must monitor it, any device that drives /BERR must
   drive with an  open collector  or similar device, and any device that
   monitors /BERR should place a minimal load on it.  This signal is
   pulled high by a passive backplane resistor.

Note that, especially for the slave device being addressed, that /BERR
alone is not always necessarily an indication of a bus failure in the pure
sense, but may indicate some other kind of unusual condition.  Therefore,
a device should still respond to the bus address, if otherwise
appropriate, when a /BERR condition is indicated.  It simply tri-states is
bus buffers and other outputs, and waits for a change in the bus state.
If the /BERR signal is negated with the cycle unterminated, the special
condition has been resolved and the slave responds to the rest of the
cycle as it normally would have. If the cycle is terminated by the bus
master, the resolution of the special condition has indicated that the
addressed slave is not needed, and so the cycle terminates without the
slave being used.

System Reset (/RESET, /IORST)
   The bus supplies two versions of the system reset signal.  The /RESET
   signal is bi-directional and unbuffered, allowing an expansion card
   to hard reset the system.  It should only be used by boards that need
   this reset capability, and is driven only by an  open collector  or
   similar device.  The /IORST signal is a buffered output-only version
   of the reset signal that should be used as the normal reset input to
   boards not concerned with resetting the system on their own.  All
   expansion devices are required to reset their  autoconfiguration  logic
   when /IORST is asserted.  These signals are pulled high by passive
   backplane resistors.

System Halt (/HLT)
   This signal is driven, along with /RESET, to assert a full-system
   reset.  A full-system reset is asserted on a powerup reset or a
   keyboard reset; any PIC that needs to differentiate between full
   system and I/O reset should monitor /HLT and /IORST unless it also
   needs to drive a reset condition.  This is driven with an
    open-collector  output, or the equivalent, and pulled up by a
   backplane resistor.

System Interrupts
   Two of the decoded, level-sensitive 680x0 interrupt inputs are
   available on the expansion bus, and these are labeled as /INT2 and
   /INT6. Each of these interrupt lines is shared by wired ORing, thus
   each line must be driven by an  open-collector  or equivalent output
   type.  Zorro III interrupts can be handled Zorro II style, via
   autovectors and daisy-chained polling, or they can be vectored using
   the  quick interrupt  protocol described in the Bus Architecture
   section.   Zorro II and Zorro III systems originally provided /INT1,
   /INT4, /INT5, and /INT7 lines as well, but as these were never
   properly supportable by system software, they have been eliminated.
   Those lines are considered reserved for future use in a Zorro III
   system.


K / Signal Description / Slot Control Signals

This group of signals is responsible for the control of operations between
expansion slots.

Slave (/SLAVEn)
   Each slot has its own /SLAVEn output, driven actively, all of which
   go into the collision detect circuitry.  The "n" refers to the
   expansion slot number of the particular /SLAVE signal. Whenever a
   Zorro III PIC is responding to an address on the bus, it must assert
   its /SLAVEn output very quickly.  If more than one /SLAVEn output
   occurs for the same address, or if a PIC asserts its /SLAVEn output
   for an address reserved by the local bus, a collision is registered
   and the bus controller asserts  /BERR .  The bus controller will assert
   /SLAVEn back to the interrupting device selected during a
    Quick Interrupt cycle , so any device supporting  Quick Interrupts
   must be capable of tri-stating its /SLAVEn; all others can drive
   SLAVEn with a normal active output.

Configuration Chain (/CFGINn, /CFGOUTn)
   The slot configuration mechanism uses the bus signals /CFGOUTn and
   /CFGINn, where "n" refers to the slot number.  Each slot has its own
   version of both signals, which make up the configuration chain
   between slots.  Each subsequent /CFGINn is a result of all previous
   /CFGOUTs, going from slot 0 to the last slot on the expansion bus.
   During the  autoconfiguration  process, an unconfigured Zorro III PIC
   responds to the 64K address space starting at either $00E80000 or
   $FF000000 if its /CFGINN signal is asserted.  All unconfigured PICs
   start up with /CFGOUTn negated. When configured, or told to "shut up"
   a PIC will assert its /CFGOUTn, which results in the /CFGINn of the
   next slot being asserted. Backplane logic automatically passes on the
   state of the previous /CFGOUTn to the next /CFGINn for any slot not
   occupied by a PIC, so there's no need to sequentially populate the
   expansion bus slots.

Backplane Type Sense (SenseZ3)
   This line can be used by the PIC to determine the backplane type.  It
   is grounded on a Zorro II backplane, but floating on a Zorro III
   backplane.  The Zorro III PIC connects this signal to a 1K pullup
   resistor to generate a real logic level for this line.  It's
   possible, though more complicated, to build a Zorro III PIC that can
   actually run in Zorro II mode when in a Zorro II backplane.  It's
   hardly necessary or required to support this backward compatibility
   mechanism, and in many cases it will be impractical.  The Zorro III
   specification does require that this signal be used, at least, to
   shut the card down and pass /CFGIN to /CFGOUT when in a Zorro II
   backplane.


K / Signal Description / DMA Control Signals

There are various signals on the expansion bus that coordinate the
arbitration of bus masters.  Zorro II bus masters use some of the same
logical signals, but their arbitration protocol is considerably different.

PIC is DMA Owner (/OWN)
   This is asserted by the bus controller when a master is about to go
   on the bus and indicates that some master owns the bus. Zorro II bus
   masters drive this, and some Zorro III slaves may find a need to
   monitor it, or /BGACK, to determine who's the bus master. This is
   ordinarily not important to Zorro III PICs, and they may not drive
   this line.

Slot Specific Bus Arbitration (/BRn, /BGn)
   These are the slot-specific /BRn and /BGn signals, where "n" refers
   to the expansion slot number. The bus request from each board is
   taken in by the bus controller and ultimately used to take over the
   system from the primary bus master, which is always the local master.
   Zorro III PICs toggle /BRn to register or unregister as a master with
   the bus controller.  /BGn is asserted to one registered PIC at a
   time, on a cycle by cycle basis, to indicate to the PIC that it gets
   the bus for one full cycle.

Bus Grant Acknowledge (/BGACK)
   Asserted by the bus controller when a master is about to go on the
   bus.  As with /OWN, most Zorro III PICs ignore this signal, and none
   may drive it.

Bus Want/Clear (/BCLR)
   This signal is asserted by the bus controller to indicate that a PIC
   wants to master the bus; Zorro III cards can use this to determine if
   any Zorro II bus requests are pending; Zorro III bus requests don't
   affect /BCLR.


K / Signal Description / Address And Related Control Signals

These signals are various items used for the addressing of devices in
Zorro III mode by bus masters either on the bus or from the local bus.
The bus controller translates local bus signals (68030 protocol on the
A3000) into Zorro III signals; masters are responsible for creating the
appropriate signals via their own bus control logic.

Read Enable (READ)
   Read enable for the bus; READ is asserted by the bus master during a
   bus cycle to indicate a read cycle, READ is negated to indicate a
   write cycle. READ is asserted at address time, prior to /FCS, for a
   full cycle, and prior to  /MTCR  for a short cycle.  READ stays valid
   throughout the cycle; no latching required.

Multiplexed Address Bus (A8-A31)
   These signals are driven by the bus master during address time, prior
   to the assertion of /FCS.  Any responding slave must latch as many of
   these lines as it needs on the falling edge of /FCS, as they're
   tri-stated very shortly after /FCS goes low.  These addresses always
   include all configuration address bits for normal cycles, and the
   cycle type information for  Quick Interrupt cycles .

Short Address Bus (A2-A7)
   These signals are driven by the bus master during address time, prior
   to the assertion of /FCS, for full cycles, and prior to the assertion
   of  /MTCR  for short cycles.  They stay valid for the entire full or
   short cycle, and as such do not need to be latched by responding
   slaves.

Memory Space (FC0-FC2)
   The memory space bits are an extension to the bus address, indicating
   which type of access is taking place. Zorro III PICs must pay close
   attention to valid memory space types, as the space type can change
   the type of the cycle driven by the current bus master.  The encoding
   is the same as the valid Motorola function codes for normal accesses.
   These are driven at address time, and like the low short address, are
   valid for an entire short or full cycle.

      FC0 FC1  FC2  Address   Space Type                 Z3 Response
      -------  ---  -------   ----------                 -----------
         0      0      0      Reserved                   None
         0      0      1      User Data Spce             Memory
         0      1      0      User Program Space         Memory
         0      1      1      Reserved                   None
         1      0      0      Reserved                   None
         1      0      1      Supervisor Data Space      Memory
         1      1      0      Superviser Program Space   Memory
         1      1      1      CPU Space                  Interrupts

                Table K-1: Memory Space Type Codes

Compatibility Cycle Strobe (/CCS)
   This is equivalent to the Zorro II address strobe,  /AS .  A Zorro III
   PIC doesn't use this for normal operation, but may use it during the
    autoconfiguration  process if configuring at the Zorro II address.
    AUTOCONFIG  cycles at $00E8xxxx always look like Zorro II cycles,
   though /FCS and the full Zorro III address is available, so a card
   can use either Zorro II or Zorro III addressing to start the cycle.
   However, using the /CCS strobe can save the designer the need to
   compare the upper 8 bits of the address.  Data must be driven Zorro
   II style, though if the  /DSn  lines are respected for reads,  /CINH  is
   asserted, and  /MTACK  is negated, the resulting Zorro III cycle will
   fit within the expected Zorro II cycle generated by the bus
   controller.  Yes, that should sound weird; it's based on the mapping
   of Zorro II vs. Zorro III signals, and of course the fact that /FCS
   always starts any cycle. Also note that a bus cycle with /CCS
   asserted and /FCS negated is always a Zorro II PIC-as-master cycle.
   Many Zorro III cards will instead configure at the alternate
   $FF00xxxx base address, fully in Zorro III mode, and thus completely
   ignore this signal.

Full Cycle Strobe (/FCS)
   This is the standard Zorro III full cycle strobe.  This is asserted
   by the bus master shortly after addresses are valid on the bus, and
   signals the start of any kind of Zorro III bus cycle.  Shortly after
   this line is asserted, all the multiplexed addresses will go invalid,
   so in general, all slaves latch the bus address on the falling edge
   of /FCS.  Also,  /BGn  line is negated for a Zorro III mastered cycle
   shortly after /FCS is asserted by the master.


K / Signal Description / Data And Related Control Signals

The data time signals here manage the actual transfer of data between
master and slave for both full and short cycle types.  The burst mode
signals are here too, as they're basically data phase signals even through
they don't only concern the transfer of data.

Data Output Enable (DOE)
   This signal is used by an expansion card to enable the buffers on the
   data bus.  The bus master drives this line is to keep slave PICs from
   driving data on the bus until data time.

Data Bus (D0-D31)
   This is the Zorro III data bus, which is driven by either the master
   or the slave when DOE is asserted by the master (based on  READ ).
   It's valid for reads when /DTACK is asserted by the slave; on writes
   when at least one of /DSn is asserted by the master, for all cycle
   types.

Data Strobes (/DSn)
   These strobes fall during data time; /DS3 strobes D24-D31, while /DS0
   strobes D0-D7. For write cycles, these lines signal data valid on the
   bus.  At all times, they indicate which bytes in the 32-bit data word
   the bus master is actually interested in.  For cachable reads, all
   four bytes must be returned, regardless of the value of the sizing
   strobes.  For writes, only those bytes corresponding to asserted /DSN
   are written.  Only contiguous byte cycles are supported; e.g.,
   /DS3-0 = 2, 4, 5, 6, or 10 is invalid.

Data Transfer Acknowledge (/DTACK)
   This signal is used to normally terminate a Zorro III cycle.  The
   slave is always responsible for driving this signal.  For a read
   cycle, it asserts /DTACK as soon as it has driven valid data onto the
   data bus.  For a write cycle, it asserts /DTACK as soon as it's done
   with the data.  Latching the data on writes may be a good idea; that
   can allow a slave to end the cycle before it has actually finished
   writing the data to its local memory.

Cache Inhibit (/CINH)
   This line is asserted at the same time as  /SLAVEn  to indicate to the
   bus master that the cycle must not be  cached .  If a device doesn't
   support caching, it must assert /CINH and actually obey the /DSn byte
   strobes for read cycles.  Conversely, if the device supports caching,
   /CINH is negated and the device returns all four bytes valid on
   reads, regardless of the actual supplied /DSn strobes.

Multiple Cycle Transfers (/MTCR, /MTACK)
   These lines comprise the  Multiple Transfer Cycle  handshake signals.
   The bus master asserts /MTCR at the start of data time if it's
   capable of supporting  Multiple Transfer Cycles , and the slave asserts
   /MTACK with  /SLAVEn  if it's capable of supporting
    Multiple Transfer Cycles .  If the handshake goes through, /MTCR
   strobes in the short address and write data as long as the full cycle
   continues.


K Zorro Expansion Bus / Timing

Some of this information is considered preliminary.  Nothing is expected
to get any more speed critical, but as mentioned previously, the testing
of Zorro III designs has just started at the time of this writing, final
bus controllers are not yet available, and only a few PIC designs have
even been conceived.

This section covers the various timing specifications in detail for
different Zorro III operations.  It's important to realize that this
timing information is a specification.  Actual Zorro III systems may offer
much more relaxed timings.  Today.  The whole point of the specification
is that as long as all Zorro III PICs and all Zorro III backplanes base
things on the timings given here, they'll always work together nicely.
Any design based on the actual characteristics of any particular backplane
will very likely wind up working only on that particular backplane.

The philosophy of timing on the Zorro III bus is to keep things as simple
as possible without compromising the performance goals of the bus.  Zorro
III PICs are expected to be based on F-Series or ACT-series TTL logic,
fast PALs, and possibly full custom chip designs.  It's very unlikely the
designer will meet any of these specifications with the LS parts left over
from old Zorro II card designs.

 Standard Read Cycle Timing       Multiple Transfer Cycle Timing
 Standard Write Cycle Timing      Quick Interrupt Cycle Timing


K / Timing / Standard Read Cycle Timing

   No.  Name                                   Symbol  Min     Max
   ---  ----                                   ------  ---     ---
   1    Address setup to  /FCS                 TAFS    15ns     --
   2    Address hold from  /FCS                THAF    10ns     --
   3    /FCS  to  /SLAVEn  delay               TSLV     --     25ns
   4    /FCS  to  DOE  delay                   TDOE    30ns     --
   5    DOE  to  /DSn  delay                   TDS     10ns     --
   6    Data setup to  /DTACK                  TRDS    0ns      --
   7    /DTACK  to  /FCS  off                  TOFF    10ns     --
   8    Master signal hold from  /FCS  off     THMC    0ns     5ns
   9    Slave signal hold from  /FCS  off      THSC    0ns     15ns
   11   /FCS  to  /CCS  delay                  TCCS    35ns    175ns
   12   /CCS  off to  /FCS  off                TOVL    40ns     --

         ______                                                ___________
    /FCS       \ |   |                                        /
                \____________________________________________/ |   |    |
                                                               |   |    |
              2->|   |<-                                    8->|   |<-  |
             _________                                         |   |    |
  A31-A8 ___/         \___________________________________________________
            \_________/
                                                               |   |    |
          1->|   |<-                                           |   |    |
             _____________________________________________________ |    |
   A7-A2 ___/                                                     \_______
            \_____________________________________________________/
                                                                   |    |
             |   |                                             |   |    |
         _________________________________________________________________
    READ    /                                                    \
         __/ |   |    |                                        |  \_______
                 |    |                                        |
              3->|    |<-                                      |<---9-->|
         ___________  |                                        |        __
 /SLAVEn            \ |                                        |   |   /
                 |   \________________________________________________/ |
                 |                                                      |
                 |<----4--->|                                  |   |    |
                 |          _____________________________________  |    |
     DOE         |         /                                     \ |    |
         _________________/ |                                     \_______
                            |                                  |
                 |       5->|    |<-                           |   |    |
         ______________________  |                             |   _______
    /DSn                       \ |                                /
                                \________________________________/      |
                 |                                                 |    |
                 |                                |            |   |    |
                 |                                _____________________ |
  D31-D0 ________________________________________/                     \__
                                                 \_____________________/
                 |                            |                         |
                 |                         6->|   |<-          |   |    |
         ___________________________________  |   |            |   |    __
  /DTACK                                    \ |<------7------->|   |   /
                 |     |                     \________________________/ |
             11->|     |<-                                              |
                 |     |                              12->|    |<- |    |
         ____________  |                                  ________________
    /CCS             \ |                                 /
                 |    \_________________________________/ |    |   |    |
                 |                                        |    |   |    |
                 |     |                                  |    |   |    |

                      Figure K-10: Read Cycle Timing


K / Timing / Standard Write Cycle Timing

   No.  Name                                   Symbol  Min     Max
   ---  ----                                   ------  ---     ---
   1    Address setup to  /FCS                 TAFS    15ns     --
   2    Address hold from  /FCS                THAF    10ns     --
   3    /FCS  to  /SLAVEn  delay               TSLV     --     25ns
   4    /FCS  to  DOE  delay                   TDOE    30ns     --
   5    DOE  to  /DSn  delay                   TDS     10ns     --
   7    /DTACK  to  /FCS  off                  TOFF    10ns     --
   8    Master signal hold from  /FCS  off     THMC    0ns     5ns
   9    Slave signal hold from  /FCS  off      THSC    0ns     15ns
   10   Write data setup to  /DSn              TWDS    5ns      --
   11   /FCS  to  /CCS  delay                  TCCS    35ns    175ns
   12   /CCS  off to  /FCS  off                TOVL    40ns     --

         ______                                                ___________
    /FCS       \ |   |                                        /
                \____________________________________________/ |   |    |
                                                               |   |    |
              2->|   |<-                                    8->|   |<-  |
             _________                                         |   |    |
  A31-A8 ___/         \___________________________________________________
            \_________/
                                                               |   |    |
          1->|   |<-                                           |   |    |
             _____________________________________________________ |    |
   A7-A2 ___/                                                     \_______
            \_____________________________________________________/
                                                                   |    |
         __  |                                                 |   _______
    READ   \ |                                                 |  /
         ___\____________________________________________________/________

              3->|    |<-                                      |<---9-->|
         ___________  |                                        |        __
 /SLAVEn            \ |                                        |   |   /
                 |   \________________________________________________/ |
                 |                                                      |
                 |<---4--->|                                   |   |    |
                 |         ______________________________________  |    |
     DOE         |        /                                      \ |    |
         ________________/ |                                      \_______
                           |     |                             |
                 |      5->|     |<-                           |   |    |
         _________________________                             |   _______
    /DSn                          \                               /
                                 | \_____________________________/      |
                 |            |  |                                 |    |
                 |        10->|  |<-                               |    |
                 |            ____________________________________ |    |
  D31-D0 ____________________/                                    \_______
                             \____________________________________/
                 |                                                 |    |
                 |            |               |                |   |    |
         ___________________________________  |<------7------->|   |    __
  /DTACK                                    \ |                |   |   /
                 |     |                     \________________________/ |
             11->|     |<-                                              |
                 |     |                              12->|    |<- |    |
         ____________  |                                  ________________
    /CCS             \ |                                 /
                 |    \_________________________________/ |    |   |    |
                 |                                        |    |   |    |
                 |     |                                  |    |   |    |

                     Figure K-11: Write Cycle Timing


K / Timing / Multiple Transfer Cycle Timing

   No.  Name                                   Symbol  Min     Max
   ---  ----                                   ------  ---     ---
   1    Address setup to  /FCS                 TAFS    15ns     --
   2    Address hold from  /FCS                THAF    10ns     --
   3    /FCS  to  /SLAVEn ,  /MTACK  delay     TSLV     --     25ns
   4    /FCS  to  DOE  delay                   TDOE    30ns     --
   5    DOE  to  /DSn ,  /MTCR  delay          TDS     10ns     --
   6    Data setup to  /DTACK                  TRDS    0ns      --
   7    /DTACK  to  /FCS ,  /MTCR  off         TOFF    10ns     --
   8    Master signal hold from  /FCS  off     THMC    0ns     5ns
   9    Slave signal hold from  /FCS  off      THSC    0ns     15ns
   10   Write data setup to  /DSn              TWDS    5ns      --
   13   Address,  READ  setup to  /MTCR        TAMS    5ns      --
   14   /MTCR  off to  /MTCR  on               TREF    10ns     --
   15   Address,  READ  hold from  /MTCR       THAM    0ns      --
   16   /MTACK  off to  /MTCR                  TBCD    10ns     --
   17   Slave signal hold from  /MTCR  off     THSM    0ns     5ns

         ______                                                ___________
    /FCS       \ |   |                                        /
                \____________________________________________/ |   |    |
                                                               |   |    |
              2->|   |<-                                    8->|   |<-  |
             _________                                         |   |    |
  A31-A8 ___/         \___________________________________________________
            \_________/
                                                               |   |    |
          1->|   |<-             13->|   |<-                   |   |    |
             ______________________  _____________  ______________ |    |
   A7-A2 ___/                      \/             \/              \_______
            \______________________/\_____________/\______________/
                                                                   |    |
             |   |                   |   |     |<-14-->|   15->|   |<-  |
         ________________  |        ___  |     |  ___  |       ___________
   /MTCR                 \ |       /   \ |     | /   \ |      /
                          \_______/     \_______/     \______/ |        |
                 |                   |                         |<--17-->|
                 |         |         |                 |       |        |
         __________________________  |             _______________________
    READ                           \ |            /
                 |         |        \____________/             |        |
              3->|   |<-   |                           |       |<---9-->|
         __________  |     |                           |       |        __
 /SLAVEn           \ |                                                 /
                    \_________________________________________________/ |
                 |                                                      |
                 |   |     |                   16->|   |<-     |   |    |
         __________  |     |                       _______________________
  /MTACK           \ |                            /
                    \____________________________/ |   |
                 |                                 |   |       |   |    |
              4->|    |<-  |                                   |   |    |
                 |    |  ________________________________________  |    |
     DOE         |    | /                                        \ |
         ______________/   |                                   |  \_______
                           |                                   |
                 | 5->|    |<-                                 |   |    |
         ________________  |        ___  |        ___          ___________
    /DSn                 \ |       /   \ |       /   \        /
                          \_______/     \_______/     \______/ |
                 |    |                |                       |   |    |
                 |    |    |   |   10->| |<-                   |   |    |
                               ______  ___________        ________ |
  D31-D0 _____________________/      \/           \______/        \_______
                              \______/\___________/      \________/
                 |    |                                            |    |
                 |    |   6->| |<-                       |<-7->|   |    |
         __________________  | |      ___           ___  |     | _________
  /DTACK                   \ |       /   \         /   \ |      /
                            \_______/     \_______/     \______/
                 |    |                                            |    |
                 |    |      |                           |         |    |

               Figure K-12: Multiple Transfer Cycle Timing


K / Timing / Quick Interrupt Cycle Timing

   No.  Name                                   Symbol  Min     Max
   ---  ----                                   ------  ---     ---
   1    Address setup to  /FCS                 TAFS    15ns     --
   2    Address hold from  /FCS                THAF    10ns     --
   3    /FCS  to  /SLAVEn  delay               TSLV     --     25ns
   5    DOE  to  /DSn  delay                   TDS     10ns     --
   6    Data setup to  /DTACK                  TRDS    0ns      --
   7     /DTACK  to  /FCS  off                 TOFF    10ns     --
   8    Master signal hold from  /FCS  off     THMC    0ns     5ns
   9    Slave signal hold from  /FCS  off      THSC    0ns     15ns
   14   /MTCR  off to  /MTCR  on               TREF    10ns     --
   17   Slave signal hold from  /MTCR  off     THSM    0ns     5ns
   18   Poll Phase time                        TPOL    30ns    100ns
   19   Vector Phase start to  /DTACK  time    TVEC     --     100ns

         ______                                                ___________
    /FCS       \ |   |                                        /
                \____________________________________________/ |   |    |
                                                               |   |    |
              2->|   |<-                                    8->|   |<-  |
             _________                                         |   |    |
  A31-A8 ___/         \___________________________________________________
            \_________/
                                                               |   |    |
          1->|   |<-                                           |   |    |
             _____________________________________________________ |    |
   A7-A2 ___/                                                     \_______
            \_____________________________________________________/
                                                                   |    |
             |   |<------18-------->| 14  |<- |                |   |    |
         ______  |                  ____->|   |<-19            ___________
    READ       \ |                 /    \ |   |               /
                \_________________/ |    \___________________/ |
                                    | |                        |
              3->|    |<-       17->| |<- |   |                |<---9-->|
         ___________  |               __  |   |                ___________
 /SLAVEn            \ |              /  \ |                   /
                     \______________/ |  \___________________/          |
                 |                    |                        |   |    |
                 |    |               |   |   |                |   |    |
                 |                    ___________________________  |    |
     DOE                             /                           \ |    |
         ___________________________/ |   |                       \_______
                                      |   |   |                |
                 |                 5->|   |<- |                |   |    |
         _______________________________  |   |                |   _______
    /DSn                                \ |                       /
                                         \_______________________/      |
                 |                                                 |    |
                 |                        |   |   |            |   |    |
                 |                            |   _____________________ |
  D31-D0 ________________________________________/                     \__
                                                 \_____________________/
                 |                            |                         |
                 |                         6->|   |<-          |   |    |
         ___________________________________  |   |            |   |    __
  /DTACK                                    \ |<------7------->|   |   /
                 |                           \________________________/
                 |                                                      |
                 |                            |                |   |    |

                Figure K-13: Quick Interrupt Cycle Timing


K Zorro Expansion Bus / Electrical Specifications

The Zorro III bus has a number of electrical specifications that are very
important for PIC designers to consider, along with the  timing
parameters of course.  It's extremely important to base designs on the
specification of the backplane, rather than the actual behavior of the
backplane.  New backplanes for new machines are designed to conform to the
specification, they are not necessarily based on previous designs.  This
is especially important with the Zorro III bus, since timing is far more
critical than in the past, and the bus controller is designed from this
specification, rather than the reverse, as in the Amiga 2000.

 Expansion Bus Loading     Temperature Range     Slot Power Availability


K / Electrical Specifications / Expansion Bus Loading

The Zorro III bus loading is specified based on typical TTL family "F"
series buffer devices, though in reality, compatible CMOS devices are
likely to be used in some bus controllers or PICs.   Thus, it's important
to accept the TTL levels as a minimum voltage level, and make sure that
all inputs are the appropriate TTL levels, while outputs can be at TTL or
CMOS voltage levels as long as they provide the required source and sink.

While some A2000 designs used "LS" or "ALS" buffers instead of "F," the
bus will generally work with these older cards, at least with current
backplane designs such as the A3000 backplane.  However, Zorro III designs
must exactly obey these loading rules; it's very probable that some future
Zorro III machines will have a large number of slots.  In such machines,
PICs built on the Zorro II specification will still work in a lightly
loaded bus, but may not function in a fully loaded bus.  All Zorro III
PICs built to spec will work in any Zorro III backplane, without any
loading problems, if all loading and  timing  rules are followed by the
PIC designer. The bus signals are divided up into the four groups shown in
Table K-2, based on the loading characteristics of the particular signal.
The signals in each group are given here. Standard Signals

The majority of signals on the bus are in this group.  These are bussed
signals, driven actively on the bus by F-series (or compatible) drivers
such as 74F245, usually tri-stated when ownership of the signal changed
for master and slave, and generally terminated with a 220(omega)/330(omega)
thevenin terminator.  PICs can apply two standard loads to each of these
signals when necessary.

        /FCS      /CCS       /DS0-/DS3   /LOCK
        A2-A7     AD8-AD31   SD0-SD7     READ
        FC0-FC2   DOE        /IORST      /BCLR
        /MTCR     /MTACK

 Clock Signals      Open Collector Signals      Non-bussed Signals


K / / Expansion Bus Loading / Clock Signals

All clock signals on the bus are in this group.  Many designs are very
sensitive to clock delay, skew, and rise/fall times, so loading on the
clock lines must be kept to a minimum.  These are bussed signals, actively
driven by the backplane, and source terminated with a low value series
resistor. PICs can apply one standard load to each of these signals when
necessary. Zorro II cards have the same clock rules, so there should never
be clocking problems when using either card type in a backplane.

        /C3       CDAC        /C1         7M
        E Clock


K / / Expansion Bus Loading / Open Collector Signals

Many of the bus signals are shared via open collector or open drain
outputs rather than via tri-stated signals; this is of course required for
some  asynchronous  things like the shared interrupt lines, and it works
well for other types of signals as well.  Of course, a backplane resistor
pulls these lines high, PICs only drive the line low.

        /OWN      /BGACK     /CINH       /BERR
        /DTACK    /RESET     /INT2       /INT6
        /HLT


K / / Expansion Bus Loading / Non-bussed Signals

The non-bussed, or slot specific, signals are involved with only one slot
on the bus (e.g., each slot has its own copy).  As a result, the drive
requirements are much less for these signals.  The backplane provides
pullups or pulldowns, as required by the specific signal.

        /CFGINn   /CFGOUTn   /BRn        /BGn
        SenseZ3   /SLAVEn


K / Electrical Specifications / Slot Power Availability

The system power for the Zorro III bus is totally based on the slot
configurations.  A backplane is always free to supply extra power, but it
must meet the minimum requirements specified here.  All PICs must be
designed with the minimum specifications in mind, especially the
tolerances.

    Pin	Supply
        ---     ------
    5,6     +5VDC  +/- 5% @ 2 Amps
    8       -5VDC  +/- 5% @ 60 mA
    10      +12VDC  +/- 5% @ 500mA
    20      -12VDC  +/- 5% @ 60mA


K / Electrical Specifications / Temperature Range

The Zorro III bus is specified for operation over a temperature range
of 0 degrees Celsius to 70 degrees Celsius.


K Zorro Expansion Bus / Mechanical Specifications

This section covers the various mechanical details of Zorro III cards.

For Zorro II cards, the mechanical specifications are given in the
A500/A2000 Technical Reference Manual.

 Basic Zorro III PIC      PIC With Isa Option      PIC With Video Option


K / Mechanical Specifications / Basic Zorro III PIC

This drawing shows the basic Zorro III PIC.  All of the dimensions are in
millimeters.

        |<----------------------- 337.19 -------------------------->|
        |                                                 7.62 -->| |<--

  ----- +-----------------------------------------------------------+
  ^     |                                                         | |
  |     |---+                                         DIA 3.5 __    |
  |     |   |                                                   \---|
  |  -- |-o |                                                   |\| |
  |  ^  |   |                                                   | o-| --
  |  |  |---+                                                   | | |  ^
     |  |                                                       +---|  |
114.5|  |                                     10x12mm (3 PL) __/  | |
     |  |                                                           | 60
  |     |                                                         | |
  |100.5|                                                           |  |
  |     |                                                       +---|  |
  |  |  |                                                       | | |  v
  |  |  |                                                       | o-| --
  |  |  |                                                       |   |
  |  |  |       |<-- 129.26±0.1 -->|                            +---| 22.4
  |  |  |       |                  |                                |
  v  v  |                                                           |
  ----- +-------+ #              # +--------------------------------+ --
                | #              # |                                   ^
                +------------------+                                |  |

                  |<-- 124.46 -->|<------------ 165.735 ----------->|

                     Figure K-14: Basic Zorro III PIC


K / Mechanical Specifications / PIC with ISA Option

This drawing shows the basic Zorro III PIC, with both Zorro III and the
 ISA  Bus fingers specified.  All of the dimensions are in millimeters.

        |<----------------------- 337.19 -------------------------->|
        |                                                 7.62 -->| |<--

  ----- +-----------------------------------------------------------+
  ^     |                                                         | |
  |     |---+                                         DIA 3.5 __    |
  |     |   |                                                   \---|
  |  -- |-o |                                                   |\| |
  |  ^  |   |                                                   | o-| --
  |  |  |---+                                                   | | |  ^
     |  |                                                       +---|  |
114.5|  |                                     10x12mm (3 PL) __/  | |
     |  |                                                           | 60
  |     |                                                         | |
  |100.5|                                                           |  |
  |     |                                                       +---|  |
  |  |  |                                                       | | |  v
  |  |  |                                                       | o-| --
  |  |  |                             47.38±0.1     81.0±0.1    |   |
  |  |  |       |<-- 129.26±0.1 -->|  |<----->|  |<---------->| +---| 22.4
  |  |  |       |                  |  |       |  |            |     |
  v  v  |                                                           |
  ----- +-------+ #              # +--+ #   # +--+ #        # +-----+ --
                | #              # |  | #   # |  | #        # |        ^
                +------------------+  +-------+  +------------+     |  |
                                                   |        |       |
                  |              |      |   |      |<-76.2->| 23.495|<--
                  |              |      |   |                       |
                  |              | 43.18|<->|<----- 109.855 ------->|
                  |              |                                  |
                  |<-- 124.46 -->|<------------ 165.735 ----------->|

                     Figure K-15: PIC with ISA Option


K / Mechanical Specifications / PIC with Video Option

This drawing shows the basic Zorro III PIC, with both Zorro III and the
Amiga Video Slot fingers specified.  All of the dimensions are in
millimeters. Please consult the A500/A2000 Technical Reference Manual for
the form factor specification of a video-only card that will fit both
Amiga 2000 and Amiga 3000 computers.

        |<----------------------- 337.19 -------------------------->|
        |                                                 7.62 -->| |<--

  ----- +-----------------------------------------------------------+
  ^     |                                                         | |
  |     |---+                                         DIA 3.5 __    |
  |     |   |                                                   \---|
  |  -- |-o |                                                   |\| |
  |  ^  |   |                                                   | o-| --
  |  |  |---+                                                   | | |  ^
     |  |                                                       +---|  |
114.5|  |                                     10x12mm (3 PL) __/  | |
     |  |                                                           | 60
  |     |                                                         | |
  |100.5|                                                           |  |
  |     |                                                       +---|  |
  |  |  |                                                       | | |  v
  |  |  |                                                       | o-| --
  |  |  |                                  47.38±0.1  47.38±0.1 |   |
  |  |  |       |<-- 129.26±0.1 -->|       |<----->|  |<----->| +---| 22.4
  |  |  |       |                  |       |       |  |       |     |
  v  v  |                                                           |
  ----- +-------+ #              # +-------+ #   # +--+ #   # +-----+ --
                | #              # |       | #   # |  | #   # |        ^
                +------------------+       +-------+  +-------+     |  |
                                                        |   |       |
                  |              |           |   | 43.18|<->| 23.495|<--
                  |              |           |   |                  |
                  |              |      43.18|<->|<---- 76.835 ---->|
                  |              |                                  |
                  |<-- 124.46 -->|<------------ 165.735 ----------->|

                    Figure K-16: PIC with Video Option


K Zorro Expansion Bus / AUTOCONFIG(TM)

 The Autoconfig Mechanism      Register Bit Assignments


K / AUTOCONFIG(TM) / The Autoconfig Mechanism

The AUTOCONFIG mechanism used for the Zorro III bus is an extension of the
original Zorro II configuration mechanism.  The main reason for this is
that the Zorro II mechanism works so well, there was little need to change
anything.  The changes are simply support for new hardware features on the
Zorro III bus.

Amiga autoconfiguration is surprisingly simple.  When an Amiga powers up
or resets, every card in the system goes to its unconfigured state.  At
this point, the most important signals in the system are  /CFGINn  and
 /CFGOUTn .  As long as a card's  /CFGINn  line is negated, that card sits
quietly and does nothing on the bus (though memory cards should continue
to refresh even through reset, and any local board activities that don't
concern the bus may take place after  /RESET  is negated). As part of the
unconfigured state,  /CFGOUTn  is negated by the PIC immediately on reset.

The configuration process begins when a card's  /CFGINn  line is asserted,
either by the backplane, if it's the first slot, or via the configuration
chain, if it's a later card.  The configuration chain simply ensures that
only one unconfigured card will see an asserted  /CFGINn  at one time.  An
unconfigured card that sees its  /CFGINn  line asserted will respond to a
block of memory called configuration space. In this block, the PIC will
assert a set of read-only registers, followed by a set of write-only
registers (the read-only registers are also known as AUTOCONFIG ROM).
Starting at the base of this block, the read registers describe the
device's size, type, and other requirements.  The operating system reads
these, and based on them, decides what should be written to the board.
Some write information is optional, but a board will always be assigned a
base address or be told to shut up.  The act of writing the final bit of
base address, or writing anything to a shutup address, will cause the PIC
to assert its  /CFGOUTn , enabling the next board in the configuration
chain.

The Zorro II configuration space is the 64K memory block $00E8xxxx, which
of course is driven with 16-bit Zorro II cycles; all Zorro II cards
configure there.  The Zorro III configuration space is the 64K memory
block beginning at $FF00xxxx, which is always driven with 32-bit Zorro III
cycles (PICs need only decode  A31-A24  during configuration).  A Zorro III
PIC can configure in Zorro II or Zorro III configuration space, at the
designer's discretion, but not both at once. All read registers physically
return only the top 4 bits of data, on  D31-D28  for either bus mode. Write
registers are written to support nybble, byte, and word registers for the
same register, again based on what works best in hardware.  This design
attempts to map into real hardware as simply as possible. Every AUTOCONFIG
register is logically considered to be 8 bits wide; the 8 bits actually
being nybbles from two paired addresses.

           $00E80000
            _______
           |#| | | |           a) Zorro II Style Mapping
           |#|_|_|_|

           | |_______________________________
           |_________________                |
                             |               |
                              _______________________________
                             |   |   |   |   |   |   |   |   |
                     (00|02) | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
                             |___|___|___|___|___|___|___|___|

            _________________________________|               |
           |  _______________________________________________|
           | |
           | |
            _______
           |#| | | |
           |#|_|_|_|

           $00E80002

               $FF000000
            _______________
           |#| | | | | | | |       b) Zorro III Style Mapping
           |#|_|_|_|_|_|_|_|

           | |_______________________________
           |_________________                |
                             |               |
                              _______________________________
                             |   |   |   |   |   |   |   |   |
                    (00|100) | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
                             |___|___|___|___|___|___|___|___|

            _________________________________|               |
           |  _______________________________________________|
           | |
           | |
            _______________
           |#| | | | | | | |
           |#|_|_|_|_|_|_|_|

               $FF000100

               Figure K-17: Configuration Register Mapping

The register mappings for the two different blocks are shown in Figure
K-17. All the bit patterns mentioned in the following sections are logical
values. To avoid ambiguity, all registers are referred to by the number of
the first register in the pair, since the first pair member is the same
for both mapping schemes. In the actual implementation of these registers,
all read registers except for the 00 register are physically complemented;
eg, the logical value of register 3C is always 0, which means in hardware,
the upper nybbles of locations $00E8003C and $00E8003E, or $FF00003C and
$FF00013C, both return all 1s.


K / AUTOCONFIG(TM) / Register Bit Assignments

The actual register assignments are below.  Most of the registers are the
same as for the Zorro II bus, and are included here for completeness.  The
Amiga OS software names for these registers in the ExpansionRom or
ExpansionControl structures are included.

Reg    ZII    ZIII    Bit
---    ---    ----    ---
00     02     100     7,6     These bits encode the PIC type:
--     (er_Type)
                                00      Reserved
                                01      Reserved
                                10      Zorro III
                                11      Zorro II

                      5       If this bit is set, the PIC's memory will
                              be linked into the system free pool.  The
                              Zorro III register 08 may modify the size
                              of the linked memory.

                      4       Setting this bit tells the OS to read an
                              autoboot ROM.

                      3       This bit is set to indicate that the next
                              board is related to this one; often
                              logically separate PICs are physically
                              located on the same card.

                      2-0     These bits indicate the configuration size
                              of the PIC.  This size can be modified for
                              the Zorro III cards by the size extension
                              bit, which is the new meaning of bit 5 in
                              register 08.

                                Bits    Unextended      Extended
                                ----    ----------      --------
                                000     8 megabytes     16 megabytes
                                001     64 kilobytes    32 megabytes
                                010     128 kilobytes   64 megabytes
                                011     256 kilobytes   128 megabytes
                                100     512 kilobytes   256 megabytes
                                101     1 megabyte      512 megabytes
                                110     2 megabytes     1 gigabyte
                                111     4 megabytes     RESERVED

04     06     104     7-0     The device's product number, which is
--     (er_Product)           completely up to the manufacturer. This is
                              generally unique between different
                              products, to help in identification of
                              system cards, and it must be unique between
                              devices using the automatic driver binding
                              features.

08     0A     108     7       This was originally an indicator to place
--     (er_Flags)             the card in the 8 megabyte Zorro II space,
                              when set, or anywhere it'll fit, if
                              cleared.  Under the Zorro III spec, this is
                              set to indicate that the board is basically
                              a memory device, cleared to indicate that
                              the board is basically an I/O device.

                      6       This bit is set to indicate that the board
                              can't be shut up by software, cleared to
                              indicate that the board can be shut up.

                      5       This is the size extension bit.  If
                              cleared, the size bits in register 00 mean
                              the same as under Zorro II, if set, the
                              size bits indicate a new size. The most
                              common new Zorro III sizes are the smaller
                              ones; all new sized cards get aligned on
                              their natural boundaries.

                      4       Reserved, must be 1 for all Zorro III cards.

                      3-0     These bits indicate a board's sub-size; the
                              amount of memory actually required by a
                              PIC.  For memory boards that auto-link,
                              this is the actual amount of memory that
                              will be linked into the system free memory
                              pool. A memory card, with memory starting
                              at the base address, can be automatically
                              sized by the Operating System.  This
                              sub-size option is intended to support
                              cards with variable setups without
                              requiring variable physical configuration
                              capability on such cards.  It also may
                              greatly simplify a Zorro III design, since
                              16-megabyte cards and up can be designed
                              with a single latch and comparator for base
                              address matching, while 8 megabyte and
                              smaller PICs require large latch/comparator
                              circuits not available in standard TTL
                              packages.

                                Bits    Encoding
                                ----    --------
                                0000    Logical size matches physical size
                                0001    Automatically sized by the
                                           Operating System
                                0010    64 kilobytes
                                0011    128 kilobytes
                                0100    256 kilobytes
                                0101    512 kilobytes
                                0110    1 megabyte
                                0111    2 megabytes
                                1000    4 megabytes
                                1001    6 megabytes
                                1010    8 megabytes
                                1011    10 megabytes
                                1100    12 megabytes
                                1101    14 megabytes
                                1110    Reserved
                                1111    Reserved

                              For boards that wish to be automatically
                              sized by the operating system, a few rules
                              apply.  The memory is sized in 512K
                              increments, and grows from the base address
                              upward.  Memory wraps are detected, but the
                              design must insure that its data bus
                              doesn't float when the sizing routine
                              addresses memory locations that aren't
                              physically present on the board; data bus
                              pullups or pulldowns are recommended.  This
                              feature is designed to allow boards to be
                              easily upgraded with additional or
                              increased density memoried without the need
                              for memory configuration jumpers.

0C     0E     10C     7-0     Reserved, must be 0.
--     (er_Reserved03)

10     12     110     7-0     Manufacturer's number, high byte.
--
14     16     114     7-0     Manufacturer's number, low bytes.  These
--     (er_Manufacturer)      are unique, and can only be assigned by
                              Commodore (CATS).

18     1A     118     7-0     Optional serial number, byte 0 (msb)
--
1C     1E     11C     7-0     Optional serial number, byte 1
--
20     22     120     7-0     Optional serial number, byte 2
--
24     26     124     7-0     Optional serial number, byte 3 (lsb)
--     (er_SerialNumber)      This is for the manufacturer's use and can
                              contain anything at all.  The main intent
                              is to allow  a manufacturer to uniquely
                              identify individual cards, but it can
                              certainly be used for revision information
                              or other data.

28     2A     128     7-0     Optional ROM vector, high byte.
--
2C     2E     12C     7-0     Optional ROM vector, low byte.
--     (er_InitDiagVec)       If the ROM address valid bit (bit 4 of
                              register (00|02)) is set, these two
                              registers provide the sixteen bit offset
                              from the board's base at which the start of
                              the ROM code is located.  If the ROM
                              address valid bit is cleared, these
                              registers are ignored.

30     32     130     7-0     Reserved, must be 0.  Unsupported base
--     (er_Reserved0c)        register reset register under Zorro II*.

34     36     134     7-0     Reserved, must be 0.
--     (er_Reserved0d)

38     3A     138     7-0     Reserved, must be 0.
--     (er_Reserved0e)

3C     3E     13C     7-0     Reserved, must be 0.
--     (er_Reserved0f)

40     42     140     7-0     Reserved, must be 0.  Unsupported control
--     (ec_Interrupt)         state register under Zorro II**.

44     46     144     7-0     High order base address register, write only.
--
48     4A     148     7-0     Low order base address register, write only.
--     (ec_Z3_HighByte)       The high order register takes bits 31-24 of
       (ec_BaseAddress)       the board's configured address, the low
                              order register takes bits 23-16.  For Zorro
                              III boards configured in the Zorro II
                              space, the configuration address is written
                              both nybble and byte wide, with the
                              ordering:

                                Reg   Nybble     Byte
                                ---   ------     ----
                                46    A27-A24    N/A
                                44    A31-A28    A31-A24
                                4A    A19-A16    N/A
                                48    A23-A20    A23-A16

                              Note that writing to register 48 actually
                              configures the board for both Zorro II and
                              Zorro III boards in the Zorro II
                              configuration block.  For Zorro III PICs in
                              the Zorro III configuration block, the
                              action is slightly different. The software
                              will actually write the configuration as
                              byte and word wide accesses:

                                Reg   Byte       Word
                                ---   ----       ----
                                48    A23-A16    N/A
                                44    A31-A24    A31-A16

                              The actual configuration takes place when
                              register 44 is written, thus supporting any
                              physical size of configuration register.

4C     4E     14C     7-0     Shut up register, write only.  Anything
--     (ec_Shutup)            written to 4C will cause a board that
                              supports shut-up to completely disappear
                              until the next reset.

50     52     150     7-0     Reserved, must be 0.
--
54     56     154     7-0     Reserved, must be 0.
--
58     5A     158     7-0     Reserved, must be 0.
--
5C     5E     15C     7-0     Reserved, must be 0.
--
60     62     160     7-0     Reserved, must be 0.
--
64     66     164     7-0     Reserved, must be 0.
--
68     6A     168     7-0     Reserved, must be 0.
--
6C     6E     16C     7-0     Reserved, must be 0.
--
70     72     170     7-0     Reserved, must be 0.
--
74     76     174     7-0     Reserved, must be 0.
--
78     7A     178     7-0     Reserved, must be 0.
--
7C     7E     17C     7-0     Reserved, must be 0.
--

 *  The original Zorro specifications called for a few registers, like
    these, that remained active after configuration.  Support for this is
    impossible, since the configuration registers generally disappear
    when a board is configured, and absolutely must move out of the
    $00E8xxxx space.  So since these couldn't really be implemented in
    hardware, system software has never supported them.  They're included
    here for historical purposes.

 ** IBID


K Zorro Expansion Bus / Physical and Logical Signal Names

The Amiga 3000 Bus signals vary based on the particular bus mode in
effect. This table lists each physical pin by physical name, and then by
the logical names for Zorro II mode, Zorro III mode, address phase, and
Zorro III data mode, data phase.

   PIN     Physical        Zorro II        Zorro III       Zorro III
   NO.     Name            Name            Address Phase   Data Phase
   ---     --------        --------        -------------   ----------
   1       Ground          Ground          Ground          Ground
   2       Ground          Ground          Ground          Ground
   3       Ground          Ground          Ground          Ground
   4       Ground          Ground          Ground          Ground
   5       +5VDC           +5VDC           +5VDC           +5VDC
   6       +5VDC           +5VDC           +5VDC           +5VDC
   7       /OWN            /OWN            /OWN            /OWN
   8       -5VDC           -5VDC           -5VDC           -5VDC
   9       /SLAVEn         /SLAVEn         /SLAVEn         /SLAVEn
   10      +12VDC          +12VDC          +12VDC          +12VDC
   11      /CFGOUTn        /CFGOUTn        /CFGOUTn        /CFGOUTn
   12      /CFGINn         /CFGINn         /CFGINn         /CFGINn
   13      Ground          Ground          Ground          Ground
   14      /C3             /C3 Clock       /C3 Clock       /C3 Clock
   15      CDAC            CDAC Clock      CDAC Clock      CDAC Clock
   16      /C1             /C1 Clock       /C1 Clock       /C1 Clock
   17      /CINH           /OVR            /CINH           /CINH
   18      /MTCR           XRDY            /MTCR           /MTCR
   19      /INT2           /INT2           /INT2           /INT2
   20      -12VDC          -12VDC          -12VDC          -12VDC
   21      A5              A5              A5              A5
   22      /INT6           /INT6           /INT6           /INT6
   23      A6              A6              A6              A6
   24      A4              A4              A4              A4
   25      Ground          Ground          Ground          Ground
   26      A3              A3              A3              A3
   27      A2              A2              A2              A2
   28      A7              A7              A7              A7
   29      /LOCK           A1              /LOCK           /LOCK
   30      AD8             A8              A8              D0
   31      FC0             FC0             FC0             FC0
   32      AD9             A9              A9              D1
   33      FC1             FC1             FC1             FC1
   34      AD10            A10             A10             D2
   35      FC2             FC2             FC2             FC2
   36      AD11            A11             A11             D3
   37      Ground          Ground          Ground          Ground
   38      AD12            A12             A12             D4
   39      AD13            A13             A13             D5
   40      Reserved        (/EINT7)        Reserved        Reserved
   41      AD14            A14             A14             D6
   42      Reserved        (/EINT5)        Reserved        Reserved
   43      AD15            A15             A15             D7
   44      Reserved        (/EINT4)        Reserved        Reserved
   45      AD16            A16             A16             D8
   46      /BERR           /BERR           /BERR           /BERR
   47      AD17            A17             A17             D9
   48      /MTACK          (/VPA)          /MTACK          /MTACK
   49      Ground          Ground          Ground          Ground
   50      E Clock         E Clock         E Clock         E Clock
   51      /DS0            (/VMA)          /DS0            /DS0
   52      AD18            A18             A18             D10
   53      /RESET          /RST            /RESET          /RESET
   54      AD19            A19             A19             D11
   55      /HLT            /HLT            /HLT            /HLT
   56      AD20            A20             A20             D12
   57      AD22            A22             A22             D14
   58      AD21            A21             A21             D13
   59      AD23            A23             A23             D15
   60      /BRn            /BRn            /BRn            /BRn
   61      Ground          Ground          Ground          Ground
   62      /BGACK          /BGACK          /BGACK          /BGACK
   63      AD31            D15             A31             D31
   64      /BGn            /BGn            /BGn            /BGn
   65      AD30            D14             A30             D30
   66      /DTACK          /DTACK          /DTACK          /DTACK
   67      AD29            D13             A29             D29
   68      READ            READ            READ            READ
   69      AD28            D12             A28             D28
   70      /DS2            /LDS            /DS2            /DS2
   71      AD27            D11             A27             D27
   72      /DS3            /UDS            /DS3            /DS3
   73      Ground          Ground          Ground          Ground
   74      /CCS            /AS             /CCS            /CCS
   75      SD0             D0              Reserved        D16
   76      AD26            D10              A26            D26
   77      SD1             D1              Reserved        D17
   78      AD25            D9              A25             D25
   79      SD2             D2              Reserved        D18
   80      AD24            D8              A24             D24
   81      SD3             D3              Reserved        D19
   82      SD7             D7              Reserved        D23
   83      SD4             D4              Reserved        D20
   84      SD6             D6              Reserved        D22
   85      Ground          Ground          Ground          Ground
   86      SD5             D5              Reserved        D21
   87      Ground          Ground          Ground          Ground
   88      Ground          Ground          Ground          Ground
   89      Ground          Ground          Ground          Ground
   90      Ground          Ground          Ground          Ground
   91      SenseZ3         Ground          SenseZ3         SenseZ3
   92      7M              E7M             7M              7M
   93      DOE             DOE             DOE             DOE
   94      /IORST          /BUSRST         /IORST          /IORST
   95      /BCLR           /GBG            /BCLR           /BCLR
   96      Reserved        (/EINT1)        Reserved        Reserved
   97      /FCS            No Connect      /FCS            /FCS
   98      /DS1            No Connect      /DS1            /DS1
   99      Ground          Ground          Ground          Ground
   100     Ground          Ground          Ground          Ground


K Zorro Expansion Bus / Zorro III Implementations

Functionally, there are two possible implementation levels in existance
for the Zorro III bus.  All of the features described in this chapter are
required for a full compliance Zorro III bus.  However, the original Amiga
3000 computers were shipped with a bus controller that supported only a
subset of the Zorro III specification published here.  This is, however,
upgradable.

The A3000 implementation of the Zorro III bus is driven by a custom
controller chip called Fat Buster.  The specification of this chip and the
A3000 hardware are fully capable of supporting the complete Zorro III bus,
but the initial silicon on Fat Buster, called the Level 1 Fat Buster,
omits some features.  Missing are: support of  Multiple Transfer Cycles ;
support for Zorro III style bus arbitration; support for
 Quick Interrupts .

The Level 2 version of Fat Buster has been in testing for some time at
Commodore in West Chester, PA. Any developers who immediately intend to
design PICs supporting these features are urged to contact Amiga, Inc.
 Technical Support /Amiga Developer Support for more information on
obtaining samples of this part for use in A3000 systems. These parts are
likely to be introduced into production, and available as part of an A3000
upgrade, very soon.  All Buster chip revisions "13G" and earlier support
the Level 1 features.  Buster chip revisions "13H" and later support Level
2 features and improved Level 1 features as well.


Hard_examples/lores_playfield.asm

;
; lores_playfield.asm
;
; This example sets up a 320 x 200 playfield with one bitplane, which
; is located at $21000. Also, a Copper list is set up at $20000.
;
; This example relies on the include file hw_examples.i.
;
        LEA     CUSTOM,a0               ; a0 points at custom chips
        MOVE.W  #$1200,BPLCON0(a0)      ; One bitplane, enable composite color
        MOVE.W  #0,BPLCON1(a0)          ; Set horizontal scroll value to 0
        MOVE.W  #0,BPL1MOD(a0)          ; Set modulo to 0 for all odd bitplanes
        MOVE.W  #$0038,DDFSTRT(a0)      ; Set data-fetch start to $38
        MOVE.W  #$00D0,DDFSTOP(a0)      ; Set data-fetch stop to $D0
        MOVE.W  #$2C81,DIWSTRT(a0)      ; Set DIWSTRT to $2C81
        MOVE.W  #$F4C1,DIWSTOP(a0)      ; Set DIWSTOP to $F4C1
        MOVE.W  #$0F00,COLOR00(a0)      ; Set background color to red
        MOVE.W  #$0FF0,COLOR01(a0)      ; Set color register 1 to yellow
;
;  Fill bitplane with $FF00FF00 to produce stripes
;
        MOVE.L  #$21000,a1      ; Point at beginning of bitplane
        MOVE.L  #$FF00FF00,d0   ; We will write $FF00FF00 long words
        MOVE.W  #2000,d1        ; 2000 long words = 8000 bytes
;
LOOP:   MOVE.L  d0,(a1)+        ; Write a long word
        DBRA    d1,LOOP         ; Decrement counter and loop until done...
;
;  Set up Copper list at $20000
;
        MOVE.L  #$20000,a1      ; Point at Copper list destination
        LEA     COPPERL(pc),a2  ; Point a2 at Copper list data
CLOOP:  MOVE.L  (a2),(a1)+      ; Move a word
        CMPI.L  #$FFFFFFFE,(a2)+        ; Check for last longword of Copper list
        BNE     CLOOP           ; Loop until entire copper list is moved
;
;  Point Copper at Copper list
;
        MOVE.L  #$20000,COP1LCH(a0)     ; Write to Copper location register
        MOVE.W  COPJMP1(a0),d0  ; Force copper to $20000
;
;  Start DMA
;
        MOVE.W  #(DMAF_SETCLR!DMAF_COPPER!DMAF_RASTER!DMAF_MASTER),DMACON(a0)
                        ; Enable bitplane and Copper DMA
        BRA     ....    ; Go do next task
;
;  This is the data for the Copper list.
;
COPPERL:
        DC.W    BPL1PTH,$0002   ; Move $0002 to address $0E0    (BPL1PTH)
        DC.W    BPL1PTL,$1000   ; Move $1000 to address $0E2    (BPL1PTL)
        DC.W    $FFFF,$FFFE     ; End of Copper list
;


Hard_examples/hires_playfield.asm

;
; hires_payfield.asm
;
; This example sets up a high resolution, interlaced display with one
; bitplane.  This example also relies on the include file hw_examples.i.

;
        LEA     CUSTOM,a0               ; Address of custom chips
        MOVE.W  #$9204,BPLCON0(a0)      ; Hires, one bitplane, interlaced
        MOVE.W  #0,BPLCON1(a0)          ; Horizontal scroll value = 0
        MOVE.W  #80,BPL1MOD(a0)         ; Modulo = 80 for odd bitplanes
        MOVE.W  #80,BPL2MOD(a0)         ; Ditto for even bitplanes
        MOVE.W  #$003C,DDFSTRT(a0)      ; Set data-fetch start for Hires
        MOVE.W  #$00D4,DDFSTOP(a0)      ; Set data-fetch stop
        MOVE.W  #$2C81,DIWSTRT(a0)      ; Set display window start
        MOVE.W  #$F4C1,DIWSTOP(a0)      ; Set display window stop
;
;  Set up color registers
;
        MOVE.W  #$000F,COLOR00(a0)      ; Background color = blue
        MOVE.W  #$0FFF,COLOR01(a0)      ; Foreground color = white
;
;  Set up bitplane at $20000
;
        LEA     $20000,a1       ; Point a1 at bitplane
        LEA     CHARLIST(pc),a2 ; a2 points at character data
        MOVE.W  #400,d1         ; Write 400 lines of data
        MOVE.W  #20,d0          ; Write 20 long words per line
L1:
        MOVE.L  (a2),(a1)+      ; Write a long word
        DBRA    d0,L1           ; Decrement counter and loop until full...
;
        MOVE.W  #20,d0          ; Reset long word counter
        ADDQ.L  #4,a2           ; Point at next word in char list
        CMPI.L  #$FFFFFFFF,(a2) ; End of char list?
        BNE     L2
        LEA     CHARLIST(pc),a2 ; Yes, reset a2 to beginning of list
L2:     DBRA    d1,L1           ; Decrement line counter and loop until done...
;
;  Start DMA
;
        MOVE.W  #(DMAF_SETCLR!DMAF_RASTER!DMAF_MASTER),DMACON(a0)
                                ; Enable bitplane DMA only, no Copper

; Because this example has no Copper list, it sits in a loop waiting
; for the vertical blanking interval.  When it comes, you check the LOF
; ( long frame ) bit in VPOSR.  If LOF = 0, this is a short frame and the
; bitplane pointers are set to point to $20050.  If LOF = 1, then this is
; a long frame and the bitplane pointers are set to point to $20000.  This
; keeps the long and short frames in the right relationship to each other.

VLOOP:  MOVE.W  INTREQR(a0),d0          ; Read interrupt requests
        AND.W   #$0020,d0               ; Mask off all but vertical blank
        BEQ     VLOOP                   ; Loop until vertical blank comes
        MOVE.W  #$0020,INTREQ(a0)       ; Reset vertical interrupt
        MOVE.W  VPOSR(a0),d0            ; Read LOF bit into d0 bit 15
        BPL     VL1                     ; If LOF = 0, jump
        MOVE.L  #$20000,BPL1PTH(a0)     ; LOF = 1, point to $20000
        BRA     VLOOP                   ; Back to top
VL1:
        MOVE.L  #$20050,BPL1PTH(a0)     ; LOF = 0, point to $20050
        BRA     VLOOP                   ; Back to top
;
;  Character list
;
CHARLIST:
        DC.L    $18FC3DF0,$3C6666D8,$3C66C0CC,$667CC0CC
        DC.L    $7E66C0CC,$C36666D8,$C3FC3DF0,$00000000
        DC.L    $FFFFFFFF


Hard_examples/HAM_playfield.asm

;
; HAM_playfield.asm
;
; The following example code generates a six-bitplane display with
; hold-and-modify mode turned on. All 32 color registers are loaded
; with black to prove that the colors are being generated by
; hold-and-modify. The equates are the usual and are not repeated here.

;  First, set up the control registers.
;
        LEA     CUSTOM,a0               ; Point a0 at custom chips
        MOVE.W  #$6A00,BPLCON0(a0)      ; Six bitplanes, hold-and-modify mode
        MOVE.W  #0,BPLCON1(a0)          ; Horizontal scroll = 0
        MOVE.W  #0,BPL1MOD(a0)          ; Modulo for odd bitplanes = 0
        MOVE.W  #0,BPL2MOD(a0)          ; Ditto for even bitplanes
        MOVE.W  #$0038,DDFSTRT(a0)      ; Set data-fetch start
        MOVE.W  #$00D0,DDFSTOP(a0)      ; Set data-fetch stop
        MOVE.W  #$2C81,DIWSTRT(a0)      ; Set display window start
        MOVE.W  #$F4C1,DIWSTOP(a0)      ; Set display window stop
;
;  Set all color registers = black to prove that hold-and-modify mode is working.
;
        MOVE.W  #32,d0                  ; Initialize counter
        LEA     CUSTOM+COLOR00,a1       ; Point a1 at first color register
CREGLOOP:
        MOVE.W  #$0000,(a1)+            ; Write black to a color register
        DBRA    d0,CREGLOOP             ; Decrement counter and loop til done...
;
;  Fill six bitplanes with an easily recognizable pattern.
;
;  NOTE:  This is just for example use.  Normally these bitplanes would
;         need to be allocated from the system MEMF_CHIP memory pool.
;
        MOVE.W  #2000,d0                ; 2000 longwords per bitplane
        MOVE.L  #$21000,a1              ; Point a1 at bitplane 1
        MOVE.L  #$23000,a2              ; Point a2 at bitplane 2
        MOVE.L  #$25000,a3              ; Point a3 at bitplane 3
        MOVE.L  #$27000,a4              ; Point a4 at bitplane 4
        MOVE.L  #$29000,a5              ; Point a5 at bitplane 5
        MOVE.L  #$2B000,a6              ; Point a6 at bitplane 6
FPLLOOP:
        MOVE.L  #$55555555,(a1)+        ; Fill bitplane 1 with $55555555
        MOVE.L  #$33333333,(a2)+        ; Fill bitplane 2 with $33333333
        MOVE.L  #$0F0F0F0F,(a3)+        ; Fill bitplane 3 with $0F0F0F0F
        MOVE.L  #$00FF00FF,(a4)+        ; Fill bitplane 4 with $00FF00FF
        MOVE.L  #$CF3CF3CF,(a5)+        ; Fill bitplane 5 with $CF3CF3CF
        MOVE.L  #$3CF3CF3C,(a6)+        ; Fill bitplane 6 with $3CF3CF3C
        DBRA    d0,FPLLOOP              ; Decrement counter and loop til done...
;
;  Set up a Copper list at $20000.
;
;  NOTE:  As with the bitplanes, the copper list location should be allocated
;         from the system MEMF_CHIP memory pool.
;
        MOVE.L  #$20000,a1              ; Point a1 at Copper list destination
        LEA     COPPERL(pc),a2          ; Point a2 at Copper list image
CLOOP:  MOVE.L  (a2),(a1)+              ; Move a long word...
        CMPI.L  #$FFFFFFFE,(a2)+        ; Check for end of Copper list
        BNE     CLOOP                   ; Loop until entire Copper list moved
;
;  Point Copper at Copper list.
;
        MOVE.L  #$20000,COP1LCH(a0)     ; Load Copper jump register
        MOVE.W  COPJMP1(a0),d0          ; Force load into Copper P.C.
;
;  Start DMA.
;
        MOVE.W  #$8380,DMACON(a0)       ; Enable bitplane and Copper DMA

        BRA     .....next stuff to do.....
;
;  Copper list for six bitplanes.  Bitplane 1 is at $21000; 2 is at $23000;
;  3 is at $25000; 4 is at $27000; 5 is at $29000; 6 is at $2B000.
;
;  NOTE:  These bitplane addresses are for example purposes only.
;         See note above.
;
COPPERL:
        DC.W    BPL1PTH,$0002   ; Bitplane 1 pointer = $21000
        DC.W    BPL1PTL,$1000
        DC.W    BPL2PTH,$0002   ; Bitplane 2 pointer = $23000
        DC.W    BPL2PTL,$3000
        DC.W    BPL3PTH,$0002   ; Bitplane 3 pointer = $25000
        DC.W    BPL3PTL,$5000
        DC.W    BPL4PTH,$0002   ; Bitplane 4 pointer = $27000
        DC.W    BPL4PTL,$7000
        DC.W    BPL5PTH,$0002   ; Bitplane 5 pointer = $29000
        DC.W    BPL5PTL,$9000
        DC.W    BPL6PTH,$0002   ; Bitplane 6 pointer = $2B000
        DC.W    BPL6PTL,$B000
        DC.W    $FFFF,$FFFE     ; Wait for the impossible, i.e., quit


Hard_examples/sprite_display.asm

;
; sprite_display.asm
;
; This example displays the spaceship sprite at location V = 65,
; H = 128. Remember to include the file hw_examples.i.
;
; First, we set up a single bitplane.
;
        LEA     CUSTOM,a0               ;Point a0 at custom chips
        MOVE.W  #$1200,BPLCON0(a0)      ;1 bitplane color is on
        MOVE.W  #$0000,BPL1MOD(a0)      ;Modulo = 0
        MOVE.W  #$0000,BPLCON1(a0)      ;Horizontal scroll value = 0
        MOVE.W  #$0024,BPLCON2(a0)      ;Sprites have priority over playfields
        MOVE.W  #$0038,DDFSTRT(a0)      ;Set data-fetch start
        MOVE.W  #$00D0,DDFSTOP(a0)      ;Set data-fetch stop

; Display window definitions.

        MOVE.W  #$2C81,DIWSTRT(a0)      ;Set display window start
                                        ;Vertical start in high byte.
                                        ;Horizontal start * 2 in low byte.
        MOVE.W  #$F4C1,DIWSTOP(a0)      ;Set display window stop
                                        ;Vertical stop in high byte.
                                        ;Horizontal stop * 2 in low byte.
;
; Set up color registers.
;
        MOVE.W  #$0008,COLOR00(a0)      ;Background color = dark blue
        MOVE.W  #$0000,COLOR01(a0)      ;Foreground color = black
        MOVE.W  #$0FF0,COLOR17(a0)      ;Color 17 = yellow
        MOVE.W  #$00FF,COLOR18(a0)      ;Color 18 = cyan
        MOVE.W  #$0F0F,COLOR19(a0)      ;Color 19 = magenta
;
; Move Copper list to $20000.
;
        MOVE.L  #$20000,a1              ;Point A1 at Copper list destination
        LEA     COPPERL(pc),a2          ;Point A2 at Copper list source
CLOOP:
        MOVE.L  (a2),(a1)+              ;Move a long word
        CMP.L   #$FFFFFFFE,(a2)+        ;Check for end of list
        BNE     CLOOP                   ;Loop until entire list is moved
;
; Move sprite to $25000.
;
        MOVE.L  #$25000,a1              ;Point A1 at sprite destination
        LEA     SPRITE(pc),a2           ;Point A2 at sprite source
SPRLOOP:
        MOVE.L  (a2),(a1)+              ;Move a long word
        CMP.L   #$00000000,(a2)+        ;Check for end of sprite
        BNE     SPRLOOP                 ;Loop until entire sprite is moved
;
; Now we write a dummy sprite to $30000, since all eight sprites are activated
; at the same time and we're only going to use one.  The remaining sprites
; will point to this dummy sprite data.
;
        MOVE.L  #$00000000,$30000       ;Write it
;
; Point Copper at Copper list.
;
        MOVE.L  #$20000,COP1LC(a0)
;
; Fill bitplane with $FFFFFFFF.
;
        MOVE.L  #$21000,a1              ;Point A1 at bitplane
        MOVE.W  #1999,d0                ;2000-1(for dbf) long words = 8000 bytes
FLOOP
        MOVE.L  #$FFFFFFFF,(a1)+        ;Move a long word of $FFFFFFFF
        DBF     d0,FLOOP                ;Decrement, repeat until false.
;
; Start DMA.
;
         MOVE.W  d0,COPJMP1(a0)         ;Force load into Copper
                                        ;  program counter
        MOVE.W  #$83A0,DMACON(a0)       ;Bitplane, Copper, and sprite DMA
        RTS                             ;..return to rest of program..

;
; This is a Copper list for one bitplane, and 8 sprites.
; The bitplane lives at $21000.
; Sprite 0 lives at $25000; all others live at $30000 (the dummy sprite).
;
COPPERL:
        DC.W    BPL1PTH,$0002           ;Bitplane 1 pointer = $21000
        DC.W    BPL1PTL,$1000
        DC.W    SPR0PTH,$0002           ;Sprite 0 pointer = $25000
        DC.W    SPR0PTL,$5000
        DC.W    SPR1PTH,$0003           ;Sprite 1 pointer = $30000
        DC.W    SPR1PTL,$0000
        DC.W    SPR2PTH,$0003           ;Sprite 2 pointer = $30000
        DC.W    SPR2PTL,$0000
        DC.W    SPR3PTH,$0003           ;Sprite 3 pointer = $30000
        DC.W    SPR3PTL,$0000
        DC.W    SPR4PTH,$0003           ;Sprite 4 pointer = $30000
        DC.W    SPR4PTL,$0000
        DC.W    SPR5PTH,$0003           ;Sprite 5 pointer = $30000
        DC.W    SPR5PTL,$0000
        DC.W    SPR6PTH,$0003           ;Sprite 6 pointer = $30000
        DC.W    SPR6PTL,$0000
        DC.W    SPR7PTH,$0003           ;Sprite 7 pointer = $30000
        DC.W    SPR7PTL,$0000
        DC.W    $FFFF,$FFFE             ;End of Copper list
;
; Sprite data for spaceship sprite.  It appears on the screen at V=65 and H=128.
;
SPRITE:
        DC.W    $6D60,$7200             ;VSTART, HSTART, VSTOP
        DC.W    $0990,$07E0             ;First pair of descriptor words
        DC.W    $13C8,$0FF0
        DC.W    $23C4,$1FF8
        DC.W    $13C8,$0FF0
        DC.W    $0990,$07E0
        DC.W    $0000,$0000             ;End of sprite data


Hard_examples/sprite_move.asm

;
; sprite_move.asm
;
; In this example of moving a sprite, the spaceship is bounced around
; on the screen, changing  direction whenever it reaches an edge.
;
; The sprite position data, containing VSTART and HSTART, lives in
; memory at $25000. VSTOP is located at $25002. You write to these
; locations to move the sprite. Once during each frame, VSTART is
; incremented (or decremented) by 1 and HSTART by 2. Then a new VSTOP
; is calculated, which will be the new VSTART + 6.
;
        MOVE.B  #151,d0         ;Initialize horizontal count
        MOVE.B  #194,d1         ;Initialize vertical count
        MOVE.B  #64,d2          ;Initialize horizontal position
        MOVE.B  #44,d3          ;Initialize vertical position
        MOVE.B  #1,d4           ;Initialize horizontal increment value
        MOVE.B  #1,d5           ;Initialize vertical increment value
;
;Here we wait for the start of the screen updating.
;This ensures a glitch-free display.
;
        LEA     CUSTOM,a0       ;Set custom chip base pointer
VLOOP:
        MOVE.B  VHPOSR(a0),d6   ;Read Vertical beam position.
;Only insert the following line if you are using a PAL machine.
;       CMP.B   #$20,d6         ;Compare with end of PAL screen.
        BNE.S   VLOOP           ;Loop if not end of screen.
;Alternatively you can use the following code:
;VLOOP:
;       MOVE.W  INTREQR(a0),d6          ;Read interrupt request word
;       AND.W   #$0020,d6               ;Mask off all but vertical blank bit
;       BEQ     VLOOP                   ;Loop until bit is a 1
;       MOVE.W  #$0020,INTREQ(a0)       ;Vertical bit is on, so reset it
;
;Please note that this will only work if you have turned OFF the Vertical
;blanking interrupt enable (not recommended for long periods).

        ADD.B   d4,d2           ;Increment horizontal value
        SUBQ.B  #1,d0           ;Decrement horizontal counter
        BNE     L1
        MOVE.B  #151,d0         ;Count exhausted, reset to 151
        EOR.B   #$FE,d4         ;Negate the increment value
L1:     MOVE.B  d2,$25001       ;Write new HSTART value to sprite
        ADD.B   d5,d3           ;Increment vertical value
        SUBQ.B  #1,d1           ;Decrement vertical counter
        BNE     L2
        MOVE.B  #194,d1         ;Count exhausted, reset to 194
        EOR.B   #$FE,d5         ;Negate the increment value
L2:     MOVE.B  d3,$25000       ;Write new VSTART value to sprite
        MOVE.B  d3,d6           ;Must now calculate new VSTOP
        ADD.B   #6,d6           ;VSTOP always VSTART+6 for spaceship
        MOVE.B  d6,$25002       ;Write new VSTOP to sprite
        BRA     VLOOP           ;Loop forever


Hard_examples/sinewave.asm

;
; sinewave.asm
;
; In this example, which gathers together all of the program segments
; from the Audio Hardware sections, a sine wave is played through
; channel 0. The example assumes exclusive access to the Audio
; hardware, and will not work directly in a multitasking environment.
;
MAIN:
        LEA     CUSTOM,a0       ; Custom chip base address
        LEA     SINEDATA(pc),a1 ;Address of data to
                                ;  audio location register 0

WHERE0DATA:
        MOVE.L  a1,AUD0LCH(a0)  ;The 680x0 writes this as though it were a
                                ;  32-bit register at the low-bits location
                                ;  (common to all locations and pointer
                                ;  registers in the system).

SETAUD0LENGTH:
        MOVE.W  #4,AUD0LEN(a0)  ;Set length in words

SETAUD0VOLUME:
        MOVE.W  #64,AUD0VOL(a0) ;Use maximum volume

SETAUD0PERIOD:
        MOVE.W  #447,AUD0PER(a0)

BEGINCHAN0:
        MOVE.W  #(DMAF_SETCLR!DMAF_AUD0!DMAF_MASTER),DMACON(a0)

        RTS                     ; Return to main code...

        DS.W    0               ; Be sure word-aligned

SINEDATA:                       ; Audio data must be in Chip memory
        DC.B    0, 90, 127, 90, 0, -90, -127, -90
        END


Hard_examples/clearmem.asm

;
; clearmem.asm
;
;   Blitter example---memory clear (link with amiga.lib)
;
        include 'exec/types.i'
        include 'hardware/custom.i'
        include 'hardware/dmabits.i'
        include 'hardware/blit.i'
        include 'hardware/hw_examples.i"

        xref    _custom

;
;   Wait for previous blit to complete.
;
waitblit:
        btst.b  #DMAB_BLTDONE-8,DMACONR(a1)
waitblit2:
        btst.b  #DMAB_BLTDONE-8,DMACONR(a1)
        bne     waitblit2
        rts
;
;   This routine uses a side effect in the blitter.  When each
;   of the blits is finished, the pointer in the blitter is pointing
;   to the next word to be blitted.
;
;   When this routine returns, the last blit is started and might
;   not be finished, so be sure to call waitblit above before
;   assuming the data is clear.
;
;   a0 = pointer to first word to clear
;   d0 = number of bytes to clear (must be even)
;
        xdef    clearmem
clearmem:
        lea     _custom,a1      ; Get pointer to chip registers
        bsr     waitblit        ; Make sure previous blit is done
        move.l  a0,BLTDPT(a1)   ; Set up the D pointer to the region to clear
        clr.w   BLTDMOD(a1)     ; Clear the D modulo (don't skip no bytes)
        asr.l   #1,d0           ; Get number of words from number of bytes
        clr.w   BLTCON1(a1)     ; No special modes
        move.w  #DEST,BLTCON0(a1)       ; only enable destination
;
;   First we deal with the smaller blits
;
        moveq   #$3f,d1         ; Mask out mod 64 words
        and.w   d0,d1
        beq     dorest          ; none?  good, do one blit
        sub.l   d1,d0           ; otherwise remove remainder
        or.l    #$40,d1         ; set the height to 1, width to n
        move.w  d1,BLTSIZE(a1)  ; trigger the blit
;
;   Here we do the rest of the words, as chunks of 128k
;
dorest:
        move.w  #$ffc0,d1       ; look at some more upper bits
        and.w   d0,d1           ; extract 10 more bits
        beq     dorest2         ; any to do?
        sub.l   d1,d0           ; pull of the ones we're doing here
        bsr     waitblit        ; wait for prev blit to complete
        move.w  d0,BLTSIZE(a1)  ; do another blit
dorest2:
        swap    d0              ; more?
        beq     done            ; nope.
        clr.w   d1              ; do a 1024x64 word blit (128K)
keepon:
        bsr     waitblit        ; finish up this blit
        move.w  d1,BLTSIZE(a1)  ; and again, blit
        subq.w  #1,d0           ; still more?
        bne     keepon          ; keep on going.
done:
        rts                     ; finished.  Blit still in progress.
        end


Hard_examples/simpleline.asm

;
; simpleline.asm
;
;   This example uses the line draw mode of the blitter
;   to draw a line.  The line is drawn with no pattern
;   and a simple `or' blit into a single bitplane.
;   (Link with amiga.lib)
;
;   Input:  d0=x1 d1=y1 d2=x2 d3=y2 d4=width a0=aptr
;
        include 'exec/types.i'
        include 'hardware/custom.i'
        include 'hardware/blit.i'
        include 'hardware/dmabits.i'

        include 'hardware/hw_examples.i'
;
        xref    _custom
;
        xdef    simpleline
;
;   Our entry point.
;
simpleline:
        lea     _custom,a1      ; snarf up the custom address register
        sub.w   d0,d2           ; calculate dx
        bmi     xneg            ; if negative, octant is one of [3,4,5,6]
        sub.w   d1,d3           ; calculate dy   ''   is one of [1,2,7,8]
        bmi     yneg            ; if negative, octant is one of [7,8]
        cmp.w   d3,d2           ; cmp |dx|,|dy|  ''   is one of [1,2]
        bmi     ygtx            ; if y>x, octant is 2
        moveq.l #OCTANT1+LINEMODE,d5    ; otherwise octant is 1
        bra     lineagain       ; go to the common section
ygtx:
        exg     d2,d3           ; X must be greater than Y
        moveq.l #OCTANT2+LINEMODE,d5    ; we are in octant 2
        bra     lineagain       ; and common again.
yneg:
        neg.w   d3              ; calculate abs(dy)
        cmp.w   d3,d2           ; cmp |dx|,|dy|, octant is [7,8]
        bmi     ynygtx          ; if y>x, octant is 7
        moveq.l #OCTANT8+LINEMODE,d5    ; otherwise octant is 8
        bra     lineagain
ynygtx:
        exg     d2,d3           ; X must be greater than Y
        moveq.l #OCTANT7+LINEMODE,d5    ; we are in octant 7
        bra     lineagain
xneg:
        neg.w   d2              ; dx was negative! octant is [3,4,5,6]
        sub.w   d1,d3           ; we calculate dy
        bmi     xyneg           ; if negative, octant is one of [5,6]
        cmp.w   d3,d2           ; otherwise it's one of [3,4]
        bmi     xnygtx          ; if y>x, octant is 3
        moveq.l #OCTANT4+LINEMODE,d5    ; otherwise it's 4
        bra     lineagain
xnygtx:
        exg     d2,d3           ; X must be greater than Y
        moveq.l #OCTANT3+LINEMODE,d5    ; we are in octant 3
        bra     lineagain
xyneg:
        neg.w   d3              ; y was negative, in one of [5,6]
        cmp.w   d3,d2           ; is y>x?
        bmi     xynygtx         ; if so, octant is 6
        moveq.l #OCTANT5+LINEMODE,d5    ; otherwise, octant is 5
        bra     lineagain
xynygtx:
        exg     d2,d3           ; X must be greater than Y
        moveq.l #OCTANT6+LINEMODE,d5    ; we are in octant 6
lineagain:
        mulu.w  d4,d1           ; Calculate y1 * width
        ror.l   #4,d0           ; move upper four bits into hi word
        add.w   d0,d0           ; multiply by 2
        add.l   d1,a0           ; ptr += (x1 >> 3)
        add.w   d0,a0           ; ptr += y1 * width
        swap    d0              ; get the four bits of x1
        or.w    #$BFA,d0        ; or with USEA, USEC, USED, F=A+C
        lsl.w   #2,d3           ; Y = 4 * Y
        add.w   d2,d2           ; X = 2 * X
        move.w  d2,d1           ; set up size word
        lsl.w   #5,d1           ; shift five left
        add.w   #$42,d1         ; and add 1 to height, 2 to width
        btst    #DMAB_BLTDONE-8,DMACONR(a1)     ; safety check
waitblit:
        btst    #DMAB_BLTDONE-8,DMACONR(a1)     ; wait for blitter
        bne     waitblit
        move.w  d3,BLTBMOD(a1)  ; B mod = 4 * Y
        sub.w   d2,d3
        ext.l   d3
        move.l  d3,BLTAPT(a1)   ; A ptr = 4 * Y - 2 * X
        bpl     lineover        ; if negative,
        or.w    #SIGNFLAG,d5    ; set sign bit in con1
lineover:
        move.w  d0,BLTCON0(a1)  ; write control registers
        move.w  d5,BLTCON1(a1)
        move.w  d4,BLTCMOD(a1)  ; C mod = bitplane width
        move.w  d4,BLTDMOD(a1)  ; D mod = bitplane width
        sub.w   d2,d3
        move.w  d3,BLTAMOD(a1)  ; A mod = 4 * Y - 4 * X
        move.w  #$8000,BLTADAT(a1)      ; A data = 0x8000
        moveq.l #-1,d5          ; Set masks to all ones
        move.l  d5,BLTAFWM(a1)  ; we can hit both masks at once
        move.l  a0,BLTCPT(a1)   ; Pointer to first pixel to set
        move.l  a0,BLTDPT(a1)
        move.w  d1,BLTSIZE(a1)  ; Start blit
        rts                     ; and return, blit still in progress.
        end


Hard_examples/rotatebits.asm

;
; rotatebits.asm
;
;   Here we rotate bits.  This code takes a single raster row of a
;   bitplane, and `rotates' it into an array of 16-bit words, setting
;   the specified bit of each word in the array according to the
;   corresponding bit in the raster row.  We use the line mode in
;   conjunction with patterns to do this magic. Link this code with amiga.lib.
;
;   Input:  d0 contains the number of words in the raster row.  d1
;   contains the number of the bit to set (0..15).  a0 contains a
;   pointer to the raster data, and a1 contains a pointer to the
;   array we are filling; the array must be at least (d0)*16 words
;   (or (d0)*32 bytes) long.
;
;
        include 'exec/types.i'
        include 'hardware/custom.i'
        include 'hardware/blit.i'
        include 'hardware/dmabits.i'

        include 'hardware/hw_examples.i'
;
        xref    _custom
;
        xdef    rotatebits
;
;
;   Our entry point.
;
rotatebits:
        lea     _custom,a2      ; We need to access the custom registers
        tst     d0              ; if no words, just return
        beq     gone
        lea     DMACONR(a2),a3  ; get the address of dmaconr
        moveq.l #DMAB_BLTDONE-8,d2      ; get the bit number BLTDONE
        btst    d2,(a3)         ; check to see if we're done
wait1:
        btst    d2,(a3)         ; check again.
        bne     wait1           ; not done?  Keep waiting
        moveq.l #-30,d3         ; Line mode:  aptr = 4Y-2X, Y=0; X=15
        move.l  d3,BLTAPT(a2)
        move.w  #-60,BLTAMOD(a2)        ; amod = 4Y-4X
        clr.w   BLTBMOD(a2)     ; bmod = 4Y
        move.w  #2,BLTCMOD(a2)  ; cmod = width of bitmap (2)
        move.w  #2,BLTDMOD(a2)  ; ditto
        ror.w   #4,d1           ; grab the four bits of the bit number
        and.w   #$f000,d1       ; mask them out
        or.w    #$bca,d1        ; USEA, USEC, USED, F=AB+~AC
        move.w  d1,BLTCON0(a2)  ; stuff it
        move.w  #$f049,BLTCON1(a2)      ; BSH=15, SGN, LINE
        move.w  #$8000,BLTADAT(a2)      ; Initialize A dat for line
        move.w  #$ffff,BLTAFWM(a2)      ; Initialize masks
        move.w  #$ffff,BLTALWM(a2)
        move.l  a1,BLTCPT(a2)   ; Initialize pointer
        move.l  a1,BLTDPT(a2)
        lea     BLTBDAT(a2),a4  ; For quick access, we grab these two
        lea     BLTSIZE(a2),a5  ; addresses
        move.w  #$402,d1        ; Stuff bltsize; width=2, height=16
        move.w  (a0)+,d3        ; Get next word
        bra     inloop          ; Go into the loop
again:
        move.w  (a0)+,d3        ; Grab another word
        btst    d2,(a3)         ; Check blit done
wait2:
        btst    d2,(a3)         ; Check again
        bne     wait2           ; oops, not ready, loop around
inloop:
        move.w  d3,(a4)         ; stuff new word to make vertical
        move.w  d1,(a5)         ; start the blit
        subq.w  #1,d0           ; is that the last word?
        bne     again           ; keep going if not
gone:
        rts
        end


Hard_examples/8520_timing.asm

;
; 8520_timing.asm
;
; A complete 8520 timing example.  This blinks the power light at (exactly)
; 3 milisecond intervals.  It takes over the machine, so watch out!
;
; The base Amiga crytal frequencies are:
;           NTSC    28.63636  MHz
;           PAL     28.37516  MHz
;
; The two 16 bit timers on the 8520 chips each count down at 1/10 the CPU
; clock, or 0.715909 MHz.  That works out to 1.3968255 microseconds per count.
; Under PAL the countdown is slightly slower, 0.709379 MHz.
;
; To wait 1/100 second would require waiting 10,000 microseconds.
; The timer register would be set to (10,000 / 1.3968255 = 7159).
;
; To wait 3 miliseconds would require waiting 3000 microseconds.
; The register would be set to (3000 / 1.3968255 = 2148).
;
        INCLUDE "hardware/cia.i"
        INCLUDE "hardware/custom.i"
;
        XREF    _ciaa
        XREF    _ciab
        XREF    _custom
;
        lea     _custom,a3              ; Base of custom chips
        lea     _ciaa,a4                ; Get base address if CIA-A
;
        move.w  #$7fff,dmacon(a3)       ; Kill all chip interrupts
;
;----Setup, only do once
;----This sets all bits needed for timer A one-shot mode.
        move.b  ciacra(a4),d0           ;Set control register A on CIAA
        and.b   #%11000000,d0           ;Don't trash bits we are not
        or.b    #%00001000,d0           ;using...
        move.b  d0,ciacra(a4)
        move.b  #%01111111,ciaicr(a4)   ;Clear all 8520 interrupts
;
;----Set time (low byte THEN high byte)
;----And the low order with $ff
;----Shift the high order by 8
;
TIME    equ     2148
        move.b  #(TIME&$FF),ciatalo(a4)
        move.b  #(TIME>>8),ciatahi(a4)
;
;----Wait for the timer to count down
busy_wait:
        btst.b  #0,ciaicr(a4)           ;Wait for timer expired flag
        beq.s   busy_wait
        bchg.b  #CIAB_LED,ciapra(a4)    ;Blink light
        bset.b  #0,ciacra(a4)           ;Restart timer
        bra.s   busy_wait

        END


Hard_examples/coldreboot.asm

;
; coldboot.asm
;
; Here is a source code listing of the only supported reboot code:
;

*   NAME
*       ColdReboot - Official code to reset any Amiga (Version 2)
*
*   SYNOPSIS
*       ColdReboot()
*       void ColdReboot(void);
*
*   FUNCTION
*       Reboot the machine.  All external memory and peripherals will be
*       RESET, and the machine will start its power up diagnostics.
*
*       Rebooting an Amiga in software is very tricky.  Differing memory
*       configurations and processor cards require careful treatment.  This
*       code represents the best available general purpose reset.  The
*       MagicResetCode must be used exactly as specified here. The code
*       _must_ be longword aligned.  Failure to duplicate the code EXACTLY
*       may result in improper operation under certain system configurations.
*
*   RESULT
*	This function never returns.

                    INCLUDE "exec/types.i"
                    INCLUDE "exec/libraries.i"

                    XDEF    _ColdReboot
                    XREF    _LVOSupervisor

ABSEXECBASE         EQU 4           ;Pointer to the Exec library base
MAGIC_ROMEND        EQU $01000000   ;End of Kickstart ROM
MAGIC_SIZEOFFSET    EQU -$14        ;Offset from end of ROM to Kickstart size
V36_EXEC            EQU 36          ;Exec with the ColdReboot() function
TEMP_ColdReboot     EQU -726        ;Offset of the V36 ColdReboot function

_ColdReboot:    move.l  ABSEXECBASE,a6
                cmp.w   #V36_EXEC,LIB_VERSION(a6)
                blt.s   old_exec
                jmp     TEMP_ColdReboot(a6)     ;Let Exec do it...
                ;NOTE: Control flow never returns to here

;---- manually reset the Amiga ---------------------------------------------
old_exec:       lea.l   GoAway(pc),a5           ;address of code to execute
                jsr     _LVOSupervisor(a6)      ;trap to code at (a5)...
                ;NOTE: Control flow never returns to here

;-------------- MagicResetCode ---------DO NOT CHANGE-----------------------
                CNOP    0,4                     ;IMPORTANT! Longword align!
GoAway:         lea.l   MAGIC_ROMEND,a0         ;(end of ROM)
                sub.l   MAGIC_SIZEOFFSET(a0),a0 ;(end of ROM)-(ROM size)=PC
                move.l  4(a0),a0                ;Get Initial Program Counter
                subq.l  #2,a0                   ;now points to second RESET
                reset                           ;first RESET instruction
                jmp     (a0)                    ;CPU Prefetch executes this
                ;NOTE: the RESET and JMP instructions must share a longword!
;---------------------------------------DO NOT CHANGE-----------------------
                END


Includes and Autodocs 2.0

 Includes (dir)  - System Header Files
 Autodocs (dir)  - System Autodocs
 References (dir)  - System References
 FD (dir)  - System FD Files
 Text_Autodocs (dir)  - System Autodocs in text format


System Header Files 2.0

 clib (dir)         graphics (dir)       resources (dir)
 devices (dir)      hardware (dir)       rexx (dir)
 dos (dir)          intuition (dir)      utility (dir)
 exec (dir)         libraries (dir)      workbench (dir)


clib

 alib_protos.h             intuition_protos.h
 alib_stdio_protos.h       keymap_protos.h
 all_protos.h              layers_protos.h
 asl_protos.h              macros.h
 battclock_protos.h        mathffp_protos.h
 battmem_protos.h          mathieeedoubbas_protos.h
 cia_protos.h              mathieeedoubtrans_protos.h
 commodities_protos.h      mathieeesingbas_protos.h
 console_protos.h          mathieeesingtrans_protos.h
 diskfont_protos.h         mathtrans_protos.h
 disk_protos.h             misc_protos.h
 dos_protos.h              potgo_protos.h
 exec_protos.h             ramdrive_protos.h
 expansion_protos.h        rexxsyslib_protos.h
 gadtools_protos.h         timer_protos.h
 graphics_protos.h         translator_protos.h
 icon_protos.h             utility_protos.h
 iffparse_protos.h         wb_protos.h
 input_protos.h


devices

 audio.h          gameport.h        keymap.h        prtgfx.h
 audio.i          gameport.i        keymap.i        prtgfx.i
 bootblock.h      hardblocks.h      narrator.h      scsidisk.h
 bootblock.i      hardblocks.i      narrator.i      scsidisk.i
 clipboard.h      input.h           parallel.h      serial.h
 clipboard.i      input.i           parallel.i      serial.i
 console.h        inputevent.h      printer.h       timer.h
 console.i        inputevent.i      printer.i       timer.i
 conunit.h        keyboard.h        prtbase.h       trackdisk.h
 conunit.i        keyboard.i        prtbase.i       trackdisk.i


dos

 datetime.h       dosextens.i      exall.i            record.h
 datetime.i       doshunks.h       filehandler.h      record.i
 dos.h            doshunks.i       filehandler.i      stdio.h
 dos.i            dostags.h        notify.h           stdio.i
 dosasl.h         dostags.i        notify.i           var.h
 dosasl.i         dos_lib.i        rdargs.h           var.i
 dosextens.h      exall.h          rdargs.i


exec

 ables.i         execbase.i          lists.h         resident.i
 alerts.h        exec_lib.i          lists.i         semaphores.h
 alerts.i        initializers.h      macros.i        semaphores.i
 devices.h       initializers.i      memory.h        strings.i
 devices.i       interrupts.h        memory.i        tasks.h
 errors.h        interrupts.i        nodes.h         tasks.i
 errors.i        io.h                nodes.i         types.h
 exec.h          io.i                ports.h         types.i
 exec.i          libraries.h         ports.i
 execbase.h      libraries.i         resident.h


graphics

 clip.h             gels.i           layers.i        sprite.i
 clip.i             gfx.h            monitor.h       text.h
 collide.h          gfx.i            monitor.i       text.i
 copper.h           gfxbase.h        rastport.h      videocontrol.h
 copper.i           gfxbase.i        rastport.i      videocontrol.i
 display.h          gfxmacros.h      regions.h       view.h
 display.i          gfxnodes.h       regions.i       view.i
 displayinfo.h      gfxnodes.i       scale.h
 displayinfo.i      graphint.h       scale.i
 gels.h             layers.h         sprite.h


hardware

 adkbits.h      cia.h         dmabits.h
 adkbits.i      cia.i         dmabits.i
 blit.h         custom.h      intbits.h
 blit.i         custom.i      intbits.i


intuition

 cghooks.h       gadgetclass.h      intuition.h          preferences.h
 cghooks.i       gadgetclass.i      intuition.i          preferences.i
 classes.h       icclass.h          intuitionbase.h      screens.h
 classes.i       icclass.i          intuitionbase.i      screens.i
 classusr.h      imageclass.h       iobsolete.h          sghooks.h
 classusr.i      imageclass.i       iobsolete.i          sghooks.i


libraries

 asl.h              dosextens.h          iffparse.i
 asl.i              dosextens.i          mathffp.h
 commodities.h      dos_lib.i            mathieeedp.h
 commodities.i      expansion.h          mathieeesp.h
 configregs.h       expansion.i          mathlibrary.h
 configregs.i       expansionbase.h      mathlibrary.i
 configvars.h       expansionbase.i      mathresource.h
 configvars.i       filehandler.h        mathresource.i
 diskfont.h         filehandler.i        translator.h
 diskfont.i         gadtools.h           translator.i
 dos.h              gadtools.i
 dos.i              iffparse.h


resources

 battclock.h              cia.h               misc.h
 battclock.i              cia.i               misc.i
 battmem.h                ciabase.h           potgo.h
 battmem.i                ciabase.i           potgo.i
 battmembitsamiga.h       disk.h
 battmembitsamiga.i       disk.i
 battmembitsamix.h        filesysres.h
 battmembitsamix.i        filesysres.i
 battmembitsshared.h      mathresource.h
 battmembitsshared.i      mathresource.i


rexx

 errors.h      rexxio.h      rxslib.h      storage.h
 errors.i      rexxio.i      rxslib.i      storage.i


utility

 date.h      hooks.h      tagitem.h      utility.i
 date.i      hooks.i      tagitem.i


workbench

 icon.h      startup.h      workbench.h
 icon.i      startup.i      workbench.i


Autodocs 2.0

Link Libraries
--------------
 amiga_lib.doc      ddebug_lib.doc      debug_lib.doc

Shared Libraries
----------------
 asl.doc              icon.doc                   mathieeesingbas.doc
 commodities.doc      iffparse.doc               mathieeesingtrans.doc
 diskfont.doc         intuition.doc              mathtrans.doc
 dos.doc              keymap.doc                 rexxsyslib.doc
 exec.doc             layers.doc                 translator.doc
 expansion.doc        mathffp.doc                utility.doc
 gadtools.doc         mathieeedoubbas.doc        wb.doc
 graphics.doc         mathieeedoubtrans.doc

Devices
-------
 audio.doc          gameport.doc      narrator.doc      serial.doc
 clipboard.doc      input.doc         parallel.doc      timer.doc
 console.doc        keyboard.doc      printer.doc       trackdisk.doc

Resources
---------
 battclock.doc      cia.doc       filesysres.doc      potgo.doc
 battmem.doc        disk.doc      misc.doc


System References 2.0

 FuncIndex  - Function Index
 Function.offs  - Function Offsets
 IncludeXREF  - Include File Cross Reference
 Structure.offs  - Structure Offsets
 StructIndex  - Structure Index


Include File Cross Reference 2.0

  A    B    C    D    E    F    G    H    I    J    K    L    M
  N    O    P    Q    R    S    T    U    V    W    X    Y    Z


System FD Files 2.0

 asl_lib.fd             icon_lib.fd                  potgo_lib.fd
 battclock_lib.fd       iffparse_lib.fd              ramdrive_lib.fd
 battmem_lib.fd         input_lib.fd                 rexxsyslib_lib.fd
 cia_lib.fd             intuition_lib.fd             timer_lib.fd
 commodities_lib.fd     keymap_lib.fd                translator_lib.fd
 console_lib.fd         layers_lib.fd                utility_lib.fd
 disk_lib.fd            mathffp_lib.fd               wb_lib.fd
 diskfont_lib.fd        mathieeedoubbas_lib.fd
 dos_lib.fd             mathieeedoubtrans_lib.fd
 exec_lib.fd            mathieeesingbas_lib.fd
 expansion_lib.fd       mathieeesingtrans_lib.fd
 gadtools_lib.fd        mathtrans_lib.fd
 graphics_lib.fd        misc_lib.fd


Text_Autodocs 2.0

Link Libraries
--------------
 amiga_lib.doc      ddebug_lib.doc      debug_lib.doc

Shared Libraries
----------------
 asl.doc              icon.doc                   mathieeesingbas.doc
 commodities.doc      iffparse.doc               mathieeesingtrans.doc
 diskfont.doc         intuition.doc              mathtrans.doc
 dos.doc              keymap.doc                 rexxsyslib.doc
 exec.doc             layers.doc                 translator.doc
 expansion.doc        mathffp.doc                utility.doc
 gadtools.doc         mathieeedoubbas.doc        wb.doc
 graphics.doc         mathieeedoubtrans.doc

Devices
-------
 audio.doc          gameport.doc      narrator.doc      serial.doc
 clipboard.doc      input.doc         parallel.doc      timer.doc
 console.doc        keyboard.doc      printer.doc       trackdisk.doc

Resources
---------
 battclock.doc      cia.doc       filesysres.doc      potgo.doc
 battmem.doc        disk.doc      misc.doc


Includes/clib/alib_protos.h

#ifndef  CLIB_ALIB_PROTOS_H
#define  CLIB_ALIB_PROTOS_H
/*
**	$Filename: clib/alib_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.4 $
**	$Date: 91/11/06 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif
#ifndef  DEVICES_TIMER_H
#include <devices/timer.h>
#endif
#ifndef  LIBRARIES_COMMODITIES_H
#include <libraries/commodities.h>
#endif
#ifndef  UTILITY_HOOKS_H
#include <utility/hooks.h>
#endif
#ifndef  INTUITION_CLASSUSR_H
#include <intuition/classusr.h>
#endif

/*  Exec support functions */

void BeginIO( struct IORequest *ioReq );
struct IORequest *CreateExtIO( struct MsgPort *port, long ioSize );
struct MsgPort *CreatePort( STRPTR name, long pri );
struct IOStdReq *CreateStdIO( struct MsgPort *port );
struct Task *CreateTask( STRPTR name, long pri, APTR initPC,
    unsigned long stackSize );
void DeleteExtIO( struct IORequest *ioReq );
void DeletePort( struct MsgPort *ioReq );
void DeleteStdIO( struct IOStdReq *ioReq );
void DeleteTask( struct Task *task );
void NewList( struct List *list );

/* Graphics support functions in amiga.lib */

void AddTOF( struct Isrvstr *i, long (*p)(), long a );
void RemTOF( struct Isrvstr *i );
void waitbeam( long b );

/* math support functions in amiga.lib */

FLOAT afp( BYTE *string );
void arnd( long place, long exp, BYTE *string );
FLOAT dbf( unsigned long exp, unsigned long mant );
LONG fpa( FLOAT fnum, BYTE *string );
void fpbcd( FLOAT fnum, BYTE *string );

/* Timer support functions in amiga.lib (V36 and higher only) */

LONG TimeDelay( long unit, unsigned long secs, unsigned long microsecs );
LONG DoTimer( struct timeval *, long unit, long command );

/*  Commodities functions in amiga.lib (V36 and higher only) */

void ArgArrayDone( void );
UBYTE **ArgArrayInit( long argc, UBYTE **argv );
LONG ArgInt( UBYTE **tt, STRPTR entry, long defaultval );
STRPTR ArgString( UBYTE **tt, STRPTR entry, STRPTR defaulstring );
CxObj *HotKey( STRPTR description, struct MsgPort *port, long id );
struct InputEvent *InvertString( STRPTR str, struct KeyMap *km );
void FreeIEvents( struct InputEvent *events );

/* Commodities Macros */

/* CxObj *CxCustom(LONG(*)(),LONG id)(A0,D0) */
/* CxObj *CxDebug(LONG id)(D0) */
/* CxObj *CxFilter(STRPTR description)(A0) */
/* CxObj *CxSender(struct MsgPort *port,LONG id)(A0,D0) */
/* CxObj *CxSignal(struct Task *task,LONG signal)(A0,D0) */
/* CxObj *CxTranslate(struct InputEvent *ie)(A0) */

/*  ARexx support functions in amiga.lib */

BOOL CheckRexxMsg( struct Message *rexxmsg );
LONG GetRexxVar( struct Message *rexxmsg, UBYTE *name, UBYTE **result );
LONG SetRexxVar( struct Message *rexxmsg, UBYTE *name, UBYTE *value,
    long length );

/*  Intuition hook and boopsi support functions in amiga.lib  */
/*  These functions require ROM V36 and higher only. */

ULONG callHookPkt( struct Hook *hookPtr, Object *obj, APTR message );
ULONG callHook( struct Hook *hookPtr, Object *obj, ... );
ULONG DoMethodA( Object *obj, Msg *message );
ULONG DoMethod( Object *obj, unsigned long MethodID, ... );
ULONG DoSuperMethodA( struct IClass *cl, Object *obj, Msg *message );
ULONG DoSuperMethod( struct IClass *cl, Object *obj, unsigned long MethodID,
    ... );
ULONG CoerceMethodA( struct IClass *cl, Object *obj, Msg *message );
ULONG CoerceMethod( struct IClass *cl, Object *obj, unsigned long MethodID,
    ... );
ULONG SetSuperAttrs( struct IClass *cl, Object *obj, unsigned long Tag1,
    ... );
#endif	 /* CLIB_ALIB_PROTOS_H */


Includes/clib/intuition_protos.h

#ifndef  CLIB_INTUITION_PROTOS_H
#define  CLIB_INTUITION_PROTOS_H
/*
**	$Filename: clib/intuition_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.9 $
**	$Date: 91/11/08 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  INTUITION_INTUITION_H
#include <intuition/intuition.h>
#endif
/* Public functions OpenIntuition() and Intuition() are intentionally */
/* not documented. */
void OpenIntuition( void );
void Intuition( struct InputEvent *iEvent );
UWORD AddGadget( struct Window *window, struct Gadget *gadget,
    unsigned long position );
BOOL ClearDMRequest( struct Window *window );
void ClearMenuStrip( struct Window *window );
void ClearPointer( struct Window *window );
BOOL CloseScreen( struct Screen *screen );
void CloseWindow( struct Window *window );
LONG CloseWorkBench( void );
void CurrentTime( ULONG *seconds, ULONG *micros );
BOOL DisplayAlert( unsigned long alertNumber, UBYTE *string,
    unsigned long height );
void DisplayBeep( struct Screen *screen );
BOOL DoubleClick( unsigned long sSeconds, unsigned long sMicros,
    unsigned long cSeconds, unsigned long cMicros );
void DrawBorder( struct RastPort *rp, struct Border *border, long leftOffset,
    long topOffset );
void DrawImage( struct RastPort *rp, struct Image *image, long leftOffset,
    long topOffset );
void EndRequest( struct Requester *requester, struct Window *window );
struct Preferences *GetDefPrefs( struct Preferences *preferences, long size );
struct Preferences *GetPrefs( struct Preferences *preferences, long size );
void InitRequester( struct Requester *requester );
struct MenuItem *ItemAddress( struct Menu *menuStrip,
    unsigned long menuNumber );
BOOL ModifyIDCMP( struct Window *window, unsigned long flags );
void ModifyProp( struct Gadget *gadget, struct Window *window,
    struct Requester *requester, unsigned long flags,
    unsigned long horizPot, unsigned long vertPot,
    unsigned long horizBody, unsigned long vertBody );
void MoveScreen( struct Screen *screen, long dx, long dy );
void MoveWindow( struct Window *window, long dx, long dy );
void OffGadget( struct Gadget *gadget, struct Window *window,
    struct Requester *requester );
void OffMenu( struct Window *window, unsigned long menuNumber );
void OnGadget( struct Gadget *gadget, struct Window *window,
    struct Requester *requester );
void OnMenu( struct Window *window, unsigned long menuNumber );
struct Screen *OpenScreen( struct NewScreen *newScreen );
struct Window *OpenWindow( struct NewWindow *newWindow );
ULONG OpenWorkBench( void );
void PrintIText( struct RastPort *rp, struct IntuiText *iText, long left,
    long top );
void RefreshGadgets( struct Gadget *gadgets, struct Window *window,
    struct Requester *requester );
UWORD RemoveGadget( struct Window *window, struct Gadget *gadget );
/* The official calling sequence for ReportMouse is given below. */
/* Note the register order.  For the complete story, read the ReportMouse */
/* autodoc. */
void ReportMouse( long flag, struct Window *window );
void ReportMouse1( struct Window *window, long flag );
BOOL Request( struct Requester *requester, struct Window *window );
void ScreenToBack( struct Screen *screen );
void ScreenToFront( struct Screen *screen );
BOOL SetDMRequest( struct Window *window, struct Requester *requester );
BOOL SetMenuStrip( struct Window *window, struct Menu *menu );
void SetPointer( struct Window *window, UWORD *pointer, long height,
    long width, long xOffset, long yOffset );
void SetWindowTitles( struct Window *window, UBYTE *windowTitle,
    UBYTE *screenTitle );
void ShowTitle( struct Screen *screen, long showIt );
void SizeWindow( struct Window *window, long dx, long dy );
struct View *ViewAddress( void );
struct ViewPort *ViewPortAddress( struct Window *window );
void WindowToBack( struct Window *window );
void WindowToFront( struct Window *window );
BOOL WindowLimits( struct Window *window, long widthMin, long heightMin,
    unsigned long widthMax, unsigned long heightMax );
/*--- start of next generation of names -------------------------------------*/
struct Preferences *SetPrefs( struct Preferences *preferences, long size,
    long inform );
/*--- start of next next generation of names --------------------------------*/
LONG IntuiTextLength( struct IntuiText *iText );
BOOL WBenchToBack( void );
BOOL WBenchToFront( void );
/*--- start of next next next generation of names ---------------------------*/
BOOL AutoRequest( struct Window *window, struct IntuiText *body,
    struct IntuiText *posText, struct IntuiText *negText,
    unsigned long pFlag, unsigned long nFlag, unsigned long width,
    unsigned long height );
void BeginRefresh( struct Window *window );
struct Window *BuildSysRequest( struct Window *window, struct IntuiText *body,
    struct IntuiText *posText, struct IntuiText *negText,
    unsigned long flags, unsigned long width, unsigned long height );
void EndRefresh( struct Window *window, long complete );
void FreeSysRequest( struct Window *window );
void MakeScreen( struct Screen *screen );
void RemakeDisplay( void );
void RethinkDisplay( void );
/*--- start of next next next next generation of names ----------------------*/
APTR AllocRemember( struct Remember **rememberKey, unsigned long size,
    unsigned long flags );
/* Public function AlohaWorkbench() is intentionally not documented */
void AlohaWorkbench( long wbport );
void FreeRemember( struct Remember **rememberKey, long reallyForget );
/*--- start of 15 Nov 85 names ------------------------*/
ULONG LockIBase( unsigned long dontknow );
void UnlockIBase( unsigned long ibLock );
/*--- functions in V33 or higher (distributed as Release 1.2) ---*/
LONG GetScreenData( APTR buffer, unsigned long size, unsigned long type,
    struct Screen *screen );
void RefreshGList( struct Gadget *gadgets, struct Window *window,
    struct Requester *requester, long numGad );
UWORD AddGList( struct Window *window, struct Gadget *gadget,
    unsigned long position, long numGad, struct Requester *requester );
UWORD RemoveGList( struct Window *remPtr, struct Gadget *gadget,
    long numGad );
LONG ActivateWindow( struct Window *window );
void RefreshWindowFrame( struct Window *window );
BOOL ActivateGadget( struct Gadget *gadgets, struct Window *window,
    struct Requester *requester );
void NewModifyProp( struct Gadget *gadget, struct Window *window,
    struct Requester *requester, unsigned long flags,
    unsigned long horizPot, unsigned long vertPot,
    unsigned long horizBody, unsigned long vertBody, long numGad );
/*--- functions in V36 or higher (distributed as Release 2.0) ---*/
LONG QueryOverscan( unsigned long displayID, struct Rectangle *rect,
    long oScanType );
void MoveWindowInFrontOf( struct Window *window,
    struct Window *behindWindow );
void ChangeWindowBox( struct Window *window, long left, long top, long width,
    long height );
struct Hook *SetEditHook( struct Hook *hook );
LONG SetMouseQueue( struct Window *window, unsigned long queueLength );
void ZipWindow( struct Window *window );
/*--- public screens ---*/
struct Screen *LockPubScreen( UBYTE *name );
void UnlockPubScreen( UBYTE *name, struct Screen *screen );
struct List *LockPubScreenList( void );
void UnlockPubScreenList( void );
UBYTE *NextPubScreen( struct Screen *screen, UBYTE *namebuf );
void SetDefaultPubScreen( UBYTE *name );
UWORD SetPubScreenModes( unsigned long modes );
UWORD PubScreenStatus( struct Screen *screen, unsigned long statusFlags );

struct RastPort *ObtainGIRPort( struct GadgetInfo *gInfo );
void ReleaseGIRPort( struct RastPort *rp );
void GadgetMouse( struct Gadget *gadget, struct GadgetInfo *gInfo,
    WORD *mousePoint );
void GetDefaultPubScreen( UBYTE *nameBuffer );
LONG EasyRequestArgs( struct Window *window, struct EasyStruct *easyStruct,
    ULONG *idcmpPtr, APTR args );
LONG EasyRequest( struct Window *window, struct EasyStruct *easyStruct,
    ULONG *idcmpPtr, ... );
struct Window *BuildEasyRequestArgs( struct Window *window,
    struct EasyStruct *easyStruct, unsigned long idcmp, APTR args );
struct Window *BuildEasyRequest( struct Window *window,
    struct EasyStruct *easyStruct, unsigned long idcmp, ... );
LONG SysReqHandler( struct Window *window, ULONG *idcmpPtr, long waitInput );
struct Window *OpenWindowTagList( struct NewWindow *newWindow,
    struct TagItem *tagList );
struct Window *OpenWindowTags( struct NewWindow *newWindow,
    unsigned long tag1Type, ... );
struct Screen *OpenScreenTagList( struct NewScreen *newScreen,
    struct TagItem *tagList );
struct Screen *OpenScreenTags( struct NewScreen *newScreen,
    unsigned long tag1Type, ... );

/*	new Image functions */
void DrawImageState( struct RastPort *rp, struct Image *image, long leftOffset,
    long topOffset, unsigned long state, struct DrawInfo *drawInfo );
BOOL PointInImage( unsigned long point, struct Image *image );
void EraseImage( struct RastPort *rp, struct Image *image, long leftOffset,
    long topOffset );

APTR NewObjectA( struct IClass *classPtr, UBYTE *classID,
    struct TagItem *tagList );
APTR NewObject( struct IClass *classPtr, UBYTE *classID, unsigned long tag1,
    ... );

void DisposeObject( APTR object );
ULONG SetAttrsA( APTR object, struct TagItem *tagList );
ULONG SetAttrs( APTR object, unsigned long tag1, ... );

ULONG GetAttr( unsigned long attrID, APTR object, ULONG *storagePtr );

/*	special set attribute call for gadgets */
ULONG SetGadgetAttrsA( struct Gadget *gadget, struct Window *window,
    struct Requester *requester, struct TagItem *tagList );
ULONG SetGadgetAttrs( struct Gadget *gadget, struct Window *window,
    struct Requester *requester, unsigned long tag1, ... );

/*	for class implementors only */
APTR NextObject( APTR objectPtrPtr );
struct IClass *MakeClass( UBYTE *classID, UBYTE *superClassID,
    struct IClass *superClassPtr, unsigned long instanceSize,
    unsigned long flags );
void AddClass( struct IClass *classPtr );

struct DrawInfo *GetScreenDrawInfo( struct Screen *screen );
void FreeScreenDrawInfo( struct Screen *screen, struct DrawInfo *drawInfo );

BOOL ResetMenuStrip( struct Window *window, struct Menu *menu );
void RemoveClass( struct IClass *classPtr );
BOOL FreeClass( struct IClass *classPtr );
#endif	 /* CLIB_INTUITION_PROTOS_H */


Includes/clib/alib_stdio_protos.h

#ifndef  CLIB_ALIB_STDIO_PROTOS_H
#define  CLIB_ALIB_STDIO_PROTOS_H
/*
**	$Filename: clib/alib_stdio_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.1 $
**	$Date: 91/11/04 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif
/* functions that duplicate those in a typical C library */
LONG printf( STRPTR fmt, ... );
LONG sprintf( STRPTR buffer, STRPTR fmt, ... );
LONG fclose( long stream );
LONG fgetc( long stream );
LONG fprintf( long stream, STRPTR fmt, ... );
LONG fputc( long c, long stream );
LONG fputs( UBYTE *s, long stream );
LONG getchar( void );
LONG putchar( long c );
LONG puts( BYTE *s );
ULONG FastRand( unsigned long seed );
UWORD RangeRand( unsigned long maxValue );
#endif	 /* CLIB_ALIB_STDIO_PROTOS_H */


Includes/clib/keymap_protos.h

#ifndef  CLIB_KEYMAP_PROTOS_H
#define  CLIB_KEYMAP_PROTOS_H
/*
**	$Filename: clib/keymap_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.4 $
**	$Date: 90/07/19 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  DEVICES_INPUTEVENT_H
#include <devices/inputevent.h>
#endif
#ifndef  DEVICES_KEYMAP_H
#include <devices/keymap.h>
#endif
/*--- functions in V36 or higher (distributed as Release 2.0) ---*/
void SetKeyMapDefault( struct KeyMap *keyMap );
struct KeyMap *AskKeyMapDefault( void );
WORD MapRawKey( struct InputEvent *event, STRPTR buffer, long length,
    struct KeyMap *keyMap );
LONG MapANSI( STRPTR string, long count, STRPTR buffer, long length,
    struct KeyMap *keyMap );
#endif	 /* CLIB_KEYMAP_PROTOS_H */


Includes/clib/all_protos.h

#include	<clib/alib_protos.h>
#include	<clib/alib_stdio_protos.h>
#include	<clib/asl_protos.h>
#include	<clib/battclock_protos.h>
#include	<clib/battmem_protos.h>
#include	<clib/cia_protos.h>
#include	<clib/commodities_protos.h>
#include	<clib/console_protos.h>
#include	<clib/diskfont_protos.h>
#include	<clib/dos_protos.h>
#include	<clib/exec_protos.h>
#include	<clib/expansion_protos.h>
#include	<clib/gadtools_protos.h>
#include	<clib/graphics_protos.h>
#include	<clib/icon_protos.h>
#include	<clib/iffparse_protos.h>
#include	<clib/input_protos.h>
#include	<clib/intuition_protos.h>
#include	<clib/keymap_protos.h>
#include	<clib/layers_protos.h>
#include	<clib/macros.h>
#include	<clib/mathffp_protos.h>
#include	<clib/mathieeedoubbas_protos.h>
#include	<clib/mathieeedoubtrans_protos.h>
#include	<clib/mathieeesingbas_protos.h>
#include	<clib/mathieeesingtrans_protos.h>
#include	<clib/mathtrans_protos.h>
#include	<clib/misc_protos.h>
#include	<clib/potgo_protos.h>
#include	<clib/ramdrive_protos.h>
#include	<clib/timer_protos.h>
#include	<clib/translator_protos.h>
#include	<clib/utility_protos.h>
#include	<clib/wb_protos.h>


Includes/clib/layers_protos.h

#ifndef  CLIB_LAYERS_PROTOS_H
#define  CLIB_LAYERS_PROTOS_H
/*
**	$Filename: clib/layers_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.6 $
**	$Date: 90/12/09 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif
#ifndef  GRAPHICS_LAYERS_H
#include <graphics/layers.h>
#endif
#ifndef  GRAPHICS_CLIP_H
#include <graphics/clip.h>
#endif
#ifndef  GRAPHICS_RASTPORT_H
#include <graphics/rastport.h>
#endif
#ifndef  GRAPHICS_REGIONS_H
#include <graphics/regions.h>
#endif
void InitLayers( struct Layer_Info *li );
struct Layer *CreateUpfrontLayer( struct Layer_Info *li, struct BitMap *bm,
    long x0, long y0, long x1, long y1, long flags, struct BitMap *bm2 );
struct Layer *CreateBehindLayer( struct Layer_Info *li, struct BitMap *bm,
    long x0, long y0, long x1, long y1, long flags, struct BitMap *bm2 );
LONG UpfrontLayer( long dummy, struct Layer *layer );
LONG BehindLayer( long dummy, struct Layer *layer );
LONG MoveLayer( long dummy, struct Layer *layer, long dx, long dy );
LONG SizeLayer( long dummy, struct Layer *layer, long dx, long dy );
void ScrollLayer( long dummy, struct Layer *layer, long dx, long dy );
LONG BeginUpdate( struct Layer *l );
void EndUpdate( struct Layer *layer, unsigned long flag );
LONG DeleteLayer( long dummy, struct Layer *layer );
void LockLayer( long dummy, struct Layer *layer );
void UnlockLayer( struct Layer *layer );
void LockLayers( struct Layer_Info *li );
void UnlockLayers( struct Layer_Info *li );
void LockLayerInfo( struct Layer_Info *li );
void SwapBitsRastPortClipRect( struct RastPort *rp, struct ClipRect *cr );
struct Layer *WhichLayer( struct Layer_Info *li, long x, long y );
void UnlockLayerInfo( struct Layer_Info *li );
struct Layer_Info *NewLayerInfo( void );
void DisposeLayerInfo( struct Layer_Info *li );
LONG FattenLayerInfo( struct Layer_Info *li );
void ThinLayerInfo( struct Layer_Info *li );
LONG MoveLayerInFrontOf( struct Layer *layer_to_move,
    struct Layer *other_layer );
struct Region *InstallClipRegion( struct Layer *layer,
    struct Region *region );
LONG MoveSizeLayer( struct Layer *layer, long dx, long dy, long dw, long dh );
struct Layer *CreateUpfrontHookLayer( struct Layer_Info *li, struct BitMap *bm,
    long x0, long y0, long x1, long y1, long flags, struct Hook *hook,
    struct BitMap *bm2 );
struct Layer *CreateBehindHookLayer( struct Layer_Info *li, struct BitMap *bm,
    long x0, long y0, long x1, long y1, long flags, struct Hook *hook,
    struct BitMap *bm2 );
struct Hook *InstallLayerHook( struct Layer *layer, struct Hook *hook );
#endif	 /* CLIB_LAYERS_PROTOS_H */


Includes/clib/asl_protos.h

#ifndef  CLIB_ASL_PROTOS_H
#define  CLIB_ASL_PROTOS_H
/*
**	$Filename: clib/asl_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.2 $
**	$Date: 91/01/23 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif
#ifndef  UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif
#ifndef  LIBRARIES_ASL_H
#include <libraries/asl.h>
#endif
/*--- functions in V36 or higher (distributed as Release 2.0) ---*/

struct FileRequester *AllocFileRequest( void );
void FreeFileRequest( struct FileRequester *fileReq );
BOOL RequestFile( struct FileRequester *fileReq );
APTR AllocAslRequest( unsigned long type, struct TagItem *tagList );
APTR AllocAslRequestTags( unsigned long type, Tag Tag1, ... );
void FreeAslRequest( APTR request );
BOOL AslRequest( APTR request, struct TagItem *tagList );
BOOL AslRequestTags( APTR request, Tag Tag1, ... );
#endif	 /* CLIB_ASL_PROTOS_H */


Includes/clib/macros.h

#ifndef CLIB_MACROS_H
#define CLIB_MACROS_H
/*
**	$Filename: clib/macros.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.0 $
**	$Date: 90/11/30 $
**
**	C prototypes
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#define MAX(a,b)    ((a)>(b)?(a):(b))
#define MIN(a,b)    ((a)<(b)?(a):(b))
#define ABS(x)	    ((x<0)?(-(x)):(x))

#endif	/* CLIB_MACROS_H */


Includes/clib/battclock_protos.h

#ifndef  CLIB_BATTCLOCK_PROTOS_H
#define  CLIB_BATTCLOCK_PROTOS_H
/*
**	$Filename: clib/battclock_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.3 $
**	$Date: 90/05/03 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif
void ResetBattClock( void );
ULONG ReadBattClock( void );
void WriteBattClock( unsigned long time );
#endif	 /* CLIB_BATTCLOCK_PROTOS_H */


Includes/clib/mathffp_protos.h

#ifndef  CLIB_MATHFFP_PROTOS_H
#define  CLIB_MATHFFP_PROTOS_H
/*
**	$Filename: clib/mathffp_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.4 $
**	$Date: 90/05/03 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif
LONG SPFix( FLOAT parm );
FLOAT SPFlt( long integer );
LONG SPCmp( FLOAT leftParm, FLOAT rightParm );
LONG SPTst( FLOAT parm );
FLOAT SPAbs( FLOAT parm );
FLOAT SPNeg( FLOAT parm );
FLOAT SPAdd( FLOAT leftParm, FLOAT rightParm );
FLOAT SPSub( FLOAT leftParm, FLOAT rightParm );
FLOAT SPMul( FLOAT leftParm, FLOAT rightParm );
FLOAT SPDiv( FLOAT leftParm, FLOAT rightParm );
/*--- functions in V33 or higher (distributed as Release 1.2) ---*/
FLOAT SPFloor( FLOAT parm );
FLOAT SPCeil( FLOAT parm );
#endif	 /* CLIB_MATHFFP_PROTOS_H */


Includes/clib/battmem_protos.h

#ifndef  CLIB_BATTMEM_PROTOS_H
#define  CLIB_BATTMEM_PROTOS_H
/*
**	$Filename: clib/battmem_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.5 $
**	$Date: 91/03/04 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif
void ObtainBattSemaphore( void );
void ReleaseBattSemaphore( void );
ULONG ReadBattMem( APTR buffer, unsigned long offset, unsigned long length );
ULONG WriteBattMem( APTR buffer, unsigned long offset, unsigned long length );
#endif	 /* CLIB_BATTMEM_PROTOS_H */


Includes/clib/mathieeedoubbas_protos.h

#ifndef  CLIB_MATHIEEEDOUBBAS_PROTOS_H
#define  CLIB_MATHIEEEDOUBBAS_PROTOS_H
/*
**	$Filename: clib/mathieeedoubbas_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.3 $
**	$Date: 90/11/07 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif
LONG IEEEDPFix( DOUBLE parm );
DOUBLE IEEEDPFlt( long integer );
LONG IEEEDPCmp( DOUBLE leftParm, DOUBLE rightParm );
LONG IEEEDPTst( DOUBLE parm );
DOUBLE IEEEDPAbs( DOUBLE parm );
DOUBLE IEEEDPNeg( DOUBLE parm );
DOUBLE IEEEDPAdd( DOUBLE leftParm, DOUBLE rightParm );
DOUBLE IEEEDPSub( DOUBLE leftParm, DOUBLE rightParm );
DOUBLE IEEEDPMul( DOUBLE factor1, DOUBLE factor2 );
DOUBLE IEEEDPDiv( DOUBLE dividend, DOUBLE divisor );
/*--- functions in V33 or higher (distributed as Release 1.2) ---*/
DOUBLE IEEEDPFloor( DOUBLE parm );
DOUBLE IEEEDPCeil( DOUBLE parm );
#endif	 /* CLIB_MATHIEEEDOUBBAS_PROTOS_H */


Includes/clib/cia_protos.h

#ifndef  CLIB_CIA_PROTOS_H
#define  CLIB_CIA_PROTOS_H
/*
**	$Filename: clib/cia_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.7 $
**	$Date: 90/07/19 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif
#ifndef  EXEC_INTERRUPTS_H
#include <exec/interrupts.h>
#endif
#ifndef  EXEC_LIBRARIES_H
#include <exec/libraries.h>
#endif
struct Interrupt *AddICRVector( struct Library *resource, long iCRBit,
    struct Interrupt *interrupt );
void RemICRVector( struct Library *resource, long iCRBit,
    struct Interrupt *interrupt );
WORD AbleICR( struct Library *resource, long mask );
WORD SetICR( struct Library *resource, long mask );
#endif	 /* CLIB_CIA_PROTOS_H */


Includes/clib/mathieeedoubtrans_protos.h

#ifndef  CLIB_MATHIEEEDOUBTRANS_PROTOS_H
#define  CLIB_MATHIEEEDOUBTRANS_PROTOS_H
/*
**	$Filename: clib/mathieeedoubtrans_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.3 $
**	$Date: 90/11/07 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif
DOUBLE IEEEDPAtan( DOUBLE parm );
DOUBLE IEEEDPSin( DOUBLE parm );
DOUBLE IEEEDPCos( DOUBLE parm );
DOUBLE IEEEDPTan( DOUBLE parm );
DOUBLE IEEEDPSincos( DOUBLE *pf2, DOUBLE parm );
DOUBLE IEEEDPSinh( DOUBLE parm );
DOUBLE IEEEDPCosh( DOUBLE parm );
DOUBLE IEEEDPTanh( DOUBLE parm );
DOUBLE IEEEDPExp( DOUBLE parm );
DOUBLE IEEEDPLog( DOUBLE parm );
DOUBLE IEEEDPPow( DOUBLE exp, DOUBLE arg );
DOUBLE IEEEDPSqrt( DOUBLE parm );
FLOAT IEEEDPTieee( DOUBLE parm );
DOUBLE IEEEDPFieee( FLOAT single );
DOUBLE IEEEDPAsin( DOUBLE parm );
DOUBLE IEEEDPAcos( DOUBLE parm );
DOUBLE IEEEDPLog10( DOUBLE parm );
#endif	 /* CLIB_MATHIEEEDOUBTRANS_PROTOS_H */


Includes/clib/commodities_protos.h

#ifndef  CLIB_COMMODITIES_PROTOS_H
#define  CLIB_COMMODITIES_PROTOS_H
/*
**	$Filename: clib/commodities_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.6 $
**	$Date: 91/11/12 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif
#ifndef  EXEC_NODES_H
#include <exec/nodes.h>
#endif
#ifndef  LIBRARIES_COMMODITIES_H
#include <libraries/commodities.h>
#endif
#ifndef  DEVICES_INPUTEVENT_H
#include <devices/inputevent.h>
#endif
#ifndef  DEVICES_KEYMAP_H
#include <devices/keymap.h>
#endif
/*--- functions in V36 or higher (distributed as Release 2.0) ---*/

/*  OBJECT UTILITIES */

CxObj *CreateCxObj( unsigned long type, long arg1, long arg2 );
CxObj *CxBroker( struct NewBroker *nb, LONG *error );
LONG ActivateCxObj( CxObj *co, long true );
void DeleteCxObj( CxObj *co );
void DeleteCxObjAll( CxObj *co );
ULONG CxObjType( CxObj *co );
LONG CxObjError( CxObj *co );
void ClearCxObjError( CxObj *co );
void SetCxObjPri( CxObj *co, long pri );

/*  OBJECT ATTACHMENT */

void AttachCxObj( CxObj *headObj, CxObj *co );
void EnqueueCxObj( CxObj *headObj, CxObj *co );
void InsertCxObj( CxObj *headObj, CxObj *co, CxObj *pred );
void RemoveCxObj( CxObj *co );

/*  TYPE SPECIFIC */

void SetTranslate( CxObj *translator, struct InputEvent *events );
void SetFilter( CxObj *filter, STRPTR text );
void SetFilterIX( CxObj *filter, IX *ix );
LONG ParseIX( STRPTR description, IX *ix );

/*  COMMON MESSAGE */

ULONG CxMsgType( CxMsg *cxm );
APTR CxMsgData( CxMsg *cxm );
LONG CxMsgID( CxMsg *cxm );

/*  MESSAGE ROUTING */

void DivertCxMsg( CxMsg *cxm, CxObj *headobj, CxObj *ret );
void RouteCxMsg( CxMsg *cxm, CxObj *co );
void DisposeCxMsg( CxMsg *cxm );

/*  INPUT EVENT HANDLING */

BOOL InvertKeyMap( unsigned long ansicode, struct InputEvent *event,
    struct KeyMap *km );
void AddIEvents( struct InputEvent *events );
#endif	 /* CLIB_COMMODITIES_PROTOS_H */


Includes/clib/mathieeesingbas_protos.h

#ifndef  CLIB_MATHIEEESINGBAS_PROTOS_H
#define  CLIB_MATHIEEESINGBAS_PROTOS_H
/*
**	$Filename: clib/mathieeesingbas_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.3 $
**	$Date: 90/11/07 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif
LONG IEEESPFix( FLOAT parm );
FLOAT IEEESPFlt( long integer );
LONG IEEESPCmp( FLOAT leftParm, FLOAT rightParm );
LONG IEEESPTst( FLOAT parm );
FLOAT IEEESPAbs( FLOAT parm );
FLOAT IEEESPNeg( FLOAT parm );
FLOAT IEEESPAdd( FLOAT leftParm, FLOAT rightParm );
FLOAT IEEESPSub( FLOAT leftParm, FLOAT rightParm );
FLOAT IEEESPMul( FLOAT leftParm, FLOAT rightParm );
FLOAT IEEESPDiv( FLOAT dividend, FLOAT divisor );
FLOAT IEEESPFloor( FLOAT parm );
FLOAT IEEESPCeil( FLOAT parm );
#endif	 /* CLIB_MATHIEEESINGBAS_PROTOS_H */


Includes/clib/console_protos.h

#ifndef  CLIB_CONSOLE_PROTOS_H
#define  CLIB_CONSOLE_PROTOS_H
/*
**	$Filename: clib/console_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.6 $
**	$Date: 90/11/07 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  EXEC_LIBRARIES_H
#include <exec/libraries.h>
#endif
#ifndef  DEVICES_INPUTEVENT_H
#include <devices/inputevent.h>
#endif
#ifndef  DEVICES_KEYMAP_H
#include <devices/keymap.h>
#endif
struct InputEvent *CDInputHandler( struct InputEvent *events,
    struct Library *consoleDevice );
LONG RawKeyConvert( struct InputEvent *events, STRPTR buffer, long length,
    struct KeyMap *keyMap );
/*--- functions in V36 or higher (distributed as Release 2.0) ---*/
#endif	 /* CLIB_CONSOLE_PROTOS_H */


Includes/clib/mathieeesingtrans_protos.h

#ifndef  CLIB_MATHIEEESINGTRANS_PROTOS_H
#define  CLIB_MATHIEEESINGTRANS_PROTOS_H
/*
**	$Filename: clib/mathieeesingtrans_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.3 $
**	$Date: 90/11/07 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif
FLOAT IEEESPAtan( FLOAT parm );
FLOAT IEEESPSin( FLOAT parm );
FLOAT IEEESPCos( FLOAT parm );
FLOAT IEEESPTan( FLOAT parm );
FLOAT IEEESPSincos( FLOAT *cosptr, FLOAT parm );
FLOAT IEEESPSinh( FLOAT parm );
FLOAT IEEESPCosh( FLOAT parm );
FLOAT IEEESPTanh( FLOAT parm );
FLOAT IEEESPExp( FLOAT parm );
FLOAT IEEESPLog( FLOAT parm );
FLOAT IEEESPPow( FLOAT exp, FLOAT arg );
FLOAT IEEESPSqrt( FLOAT parm );
FLOAT IEEESPTieee( FLOAT parm );
FLOAT IEEESPFieee( FLOAT parm );
FLOAT IEEESPAsin( FLOAT parm );
FLOAT IEEESPAcos( FLOAT parm );
FLOAT IEEESPLog10( FLOAT parm );
#endif	 /* CLIB_MATHIEEESINGTRANS_PROTOS_H */


Includes/clib/diskfont_protos.h

#ifndef  CLIB_DISKFONT_PROTOS_H
#define  CLIB_DISKFONT_PROTOS_H
/*
**	$Filename: clib/diskfont_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.2 $
**	$Date: 90/07/19 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  DOS_DOS_H
#include <dos/dos.h>
#endif
#ifndef  LIBRARIES_DISKFONT_H
#include <libraries/diskfont.h>
#endif
struct TextFont *OpenDiskFont( struct TextAttr *textAttr );
LONG AvailFonts( STRPTR buffer, long bufBytes, long flags );
/*--- functions in V34 or higher (distributed as Release 1.3) ---*/
struct FontContentsHeader *NewFontContents( BPTR fontsLock, STRPTR fontName );
void DisposeFontContents( struct FontContentsHeader *fontContentsHeader );
/*--- functions in V36 or higher (distributed as Release 2.0) ---*/
struct DiskFontHeader *NewScaledDiskFont( struct TextFont *sourceFont,
    struct TextAttr *destTextAttr );
#endif	 /* CLIB_DISKFONT_PROTOS_H */


Includes/clib/mathtrans_protos.h

#ifndef  CLIB_MATHTRANS_PROTOS_H
#define  CLIB_MATHTRANS_PROTOS_H
/*
**	$Filename: clib/mathtrans_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.2 $
**	$Date: 90/11/07 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif
FLOAT SPAtan( FLOAT parm );
FLOAT SPSin( FLOAT parm );
FLOAT SPCos( FLOAT parm );
FLOAT SPTan( FLOAT parm );
FLOAT SPSincos( FLOAT *cosResult, FLOAT parm );
FLOAT SPSinh( FLOAT parm );
FLOAT SPCosh( FLOAT parm );
FLOAT SPTanh( FLOAT parm );
FLOAT SPExp( FLOAT parm );
FLOAT SPLog( FLOAT parm );
FLOAT SPPow( FLOAT power, FLOAT arg );
FLOAT SPSqrt( FLOAT parm );
FLOAT SPTieee( FLOAT parm );
FLOAT SPFieee( FLOAT parm );
/*--- functions in V31 or higher (distributed as Release 1.1) ---*/
FLOAT SPAsin( FLOAT parm );
FLOAT SPAcos( FLOAT parm );
FLOAT SPLog10( FLOAT parm );
#endif	 /* CLIB_MATHTRANS_PROTOS_H */


Includes/clib/disk_protos.h

#ifndef  CLIB_DISK_PROTOS_H
#define  CLIB_DISK_PROTOS_H
/*
**	$Filename: clib/disk_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.1 $
**	$Date: 91/02/19 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  RESOURCES_DISK_H
#include <resources/disk.h>
#endif
BOOL AllocUnit( long unitNum );
void FreeUnit( long unitNum );
struct DiskResourceUnit *GetUnit( struct DiskResourceUnit *unitPointer );
void GiveUnit( void );
LONG GetUnitID( long unitNum );
/*------ new for V37 ------*/
LONG ReadUnitID( long unitNum );
#endif	 /* CLIB_DISK_PROTOS_H */


Includes/clib/misc_protos.h

#ifndef  CLIB_MISC_PROTOS_H
#define  CLIB_MISC_PROTOS_H
/*
**	$Filename: clib/misc_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.2 $
**	$Date: 90/11/07 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif
UBYTE *AllocMiscResource( unsigned long unitNum, UBYTE *name );
void FreeMiscResource( unsigned long unitNum );
#endif	 /* CLIB_MISC_PROTOS_H */


Includes/clib/dos_protos.h

#ifndef  CLIB_DOS_PROTOS_H
#define  CLIB_DOS_PROTOS_H
/*
**	$Filename: clib/dos_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.26 $
**	$Date: 91/11/08 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  DOS_DOS_H
#include <dos/dos.h>
#endif
#ifndef  DOS_DOSEXTENS_H
#include <dos/dosextens.h>
#endif
#ifndef  DOS_RECORD_H
#include <dos/record.h>
#endif
#ifndef  DOS_RDARGS_H
#include <dos/rdargs.h>
#endif
#ifndef  DOS_DOSASL_H
#include <dos/dosasl.h>
#endif
#ifndef  DOS_VAR_H
#include <dos/var.h>
#endif
#ifndef  DOS_NOTIFY_H
#include <dos/notify.h>
#endif
#ifndef  DOS_DATETIME_H
#include <dos/datetime.h>
#endif
BPTR Open( STRPTR name, long accessMode );
LONG Close( BPTR file );
LONG Read( BPTR file, APTR buffer, long length );
LONG Write( BPTR file, APTR buffer, long length );
BPTR Input( void );
BPTR Output( void );
LONG Seek( BPTR file, long position, long offset );
LONG DeleteFile( STRPTR name );
LONG Rename( STRPTR oldName, STRPTR newName );
BPTR Lock( STRPTR name, long type );
void UnLock( BPTR lock );
BPTR DupLock( BPTR lock );
LONG Examine( BPTR lock, struct FileInfoBlock *fileInfoBlock );
LONG ExNext( BPTR lock, struct FileInfoBlock *fileInfoBlock );
LONG Info( BPTR lock, struct InfoData *parameterBlock );
BPTR CreateDir( STRPTR name );
BPTR CurrentDir( BPTR lock );
LONG IoErr( void );
struct MsgPort *CreateProc( STRPTR name, long pri, BPTR segList,
    long stackSize );
void Exit( long returnCode );
BPTR LoadSeg( STRPTR name );
void UnLoadSeg( BPTR seglist );
struct MsgPort *DeviceProc( STRPTR name );
LONG SetComment( STRPTR name, STRPTR comment );
LONG SetProtection( STRPTR name, long protect );
struct DateStamp *DateStamp( struct DateStamp *date );
void Delay( long timeout );
LONG WaitForChar( BPTR file, long timeout );
BPTR ParentDir( BPTR lock );
LONG IsInteractive( BPTR file );
LONG Execute( STRPTR string, BPTR file, BPTR file2 );
/*--- functions in V36 or higher (distributed as Release 2.0) ---*/
/*	DOS Object creation/deletion */
APTR AllocDosObject( unsigned long type, struct TagItem *tags );
APTR AllocDosObjectTagList( unsigned long type, struct TagItem *tags );
APTR AllocDosObjectTags( unsigned long type, unsigned long tag1type, ... );
void FreeDosObject( unsigned long type, APTR ptr );
/*	Packet Level routines */
LONG DoPkt( struct MsgPort *port, long action, long arg1, long arg2, long arg3,
    long arg4, long arg5 );
LONG DoPkt0( struct MsgPort *port, long action );
LONG DoPkt1( struct MsgPort *port, long action, long arg1 );
LONG DoPkt2( struct MsgPort *port, long action, long arg1, long arg2 );
LONG DoPkt3( struct MsgPort *port, long action, long arg1, long arg2,
    long arg3 );
LONG DoPkt4( struct MsgPort *port, long action, long arg1, long arg2,
    long arg3, long arg4 );
void SendPkt( struct DosPacket *dp, struct MsgPort *port,
    struct MsgPort *replyport );
struct DosPacket *WaitPkt( void );
void ReplyPkt( struct DosPacket *dp, long res1, long res2 );
void AbortPkt( struct MsgPort *port, struct DosPacket *pkt );
/*	Record Locking */
BOOL LockRecord( BPTR fh, unsigned long offset, unsigned long length,
    unsigned long mode, unsigned long timeout );
BOOL LockRecords( struct RecordLock *recArray, unsigned long timeout );
BOOL UnLockRecord( BPTR fh, unsigned long offset, unsigned long length );
BOOL UnLockRecords( struct RecordLock *recArray );
/*	Buffered File I/O */
BPTR SelectInput( BPTR fh );
BPTR SelectOutput( BPTR fh );
LONG FGetC( BPTR fh );
LONG FPutC( BPTR fh, unsigned long ch );
LONG UnGetC( BPTR fh, long character );
LONG FRead( BPTR fh, APTR block, unsigned long blocklen,
    unsigned long number );
LONG FWrite( BPTR fh, APTR block, unsigned long blocklen,
    unsigned long number );
STRPTR FGets( BPTR fh, STRPTR buf, unsigned long buflen );
LONG FPuts( BPTR fh, STRPTR str );
void VFWritef( BPTR fh, STRPTR format, LONG *argarray );
void FWritef( BPTR fh, STRPTR format, ... );
LONG VFPrintf( BPTR fh, STRPTR format, LONG *argarray );
LONG FPrintf( BPTR fh, STRPTR format, ... );
LONG Flush( BPTR fh );
LONG SetVBuf( BPTR fh, STRPTR buff, long type, long size );
/*	DOS Object Management */
BPTR DupLockFromFH( BPTR fh );
BPTR OpenFromLock( BPTR lock );
BPTR ParentOfFH( BPTR fh );
BOOL ExamineFH( BPTR fh, struct FileInfoBlock *fib );
LONG SetFileDate( STRPTR name, struct DateStamp *date );
LONG NameFromLock( BPTR lock, STRPTR buffer, long len );
LONG NameFromFH( BPTR fh, STRPTR buffer, long len );
WORD SplitName( STRPTR name, unsigned long seperator, STRPTR buf, long oldpos,
    long size );
LONG SameLock( BPTR lock1, BPTR lock2 );
LONG SetMode( BPTR fh, long mode );
LONG ExAll( BPTR lock, struct ExAllData *buffer, long size, long data,
    struct ExAllControl *control );
LONG ReadLink( struct MsgPort *port, BPTR lock, STRPTR path, STRPTR buffer,
    unsigned long size );
LONG MakeLink( STRPTR name, long dest, long soft );
LONG ChangeMode( long type, BPTR fh, long newmode );
LONG SetFileSize( BPTR fh, long pos, long mode );
/*	Error Handling */
LONG SetIoErr( long result );
BOOL Fault( long code, STRPTR header, STRPTR buffer, long len );
BOOL PrintFault( long code, STRPTR header );
LONG ErrorReport( long code, long type, unsigned long arg1,
    struct MsgPort *device );
/*	Process Management */
struct CommandLineInterface *Cli( void );
struct Process *CreateNewProc( struct TagItem *tags );
struct Process *CreateNewProcTagList( struct TagItem *tags );
struct Process *CreateNewProcTags( unsigned long tag1type, ... );
LONG RunCommand( BPTR seg, long stack, STRPTR paramptr, long paramlen );
struct MsgPort *GetConsoleTask( void );
struct MsgPort *SetConsoleTask( struct MsgPort *task );
struct MsgPort *GetFileSysTask( void );
struct MsgPort *SetFileSysTask( struct MsgPort *task );
STRPTR GetArgStr( void );
BOOL SetArgStr( STRPTR string );
struct Process *FindCliProc( unsigned long num );
ULONG MaxCli( void );
BOOL SetCurrentDirName( STRPTR name );
BOOL GetCurrentDirName( STRPTR buf, long len );
BOOL SetProgramName( STRPTR name );
BOOL GetProgramName( STRPTR buf, long len );
BOOL SetPrompt( STRPTR name );
BOOL GetPrompt( STRPTR buf, long len );
BPTR SetProgramDir( BPTR lock );
BPTR GetProgramDir( void );
/*	Device List Management */
LONG SystemTagList( STRPTR command, struct TagItem *tags );
LONG System( STRPTR command, struct TagItem *tags );
LONG SystemTags( STRPTR command, unsigned long tag1type, ... );
LONG AssignLock( STRPTR name, BPTR lock );
BOOL AssignLate( STRPTR name, STRPTR path );
BOOL AssignPath( STRPTR name, STRPTR path );
BOOL AssignAdd( STRPTR name, BPTR lock );
LONG RemAssignList( STRPTR name, BPTR lock );
struct DevProc *GetDeviceProc( STRPTR name, struct DevProc *dp );
void FreeDeviceProc( struct DevProc *dp );
struct DosList *LockDosList( unsigned long flags );
void UnLockDosList( unsigned long flags );
struct DosList *AttemptLockDosList( unsigned long flags );
BOOL RemDosEntry( struct DosList *dlist );
LONG AddDosEntry( struct DosList *dlist );
struct DosList *FindDosEntry( struct DosList *dlist, STRPTR name,
    unsigned long flags );
struct DosList *NextDosEntry( struct DosList *dlist, unsigned long flags );
struct DosList *MakeDosEntry( STRPTR name, long type );
void FreeDosEntry( struct DosList *dlist );
BOOL IsFileSystem( STRPTR name );
/*	Handler Interface */
BOOL Format( STRPTR filesystem, STRPTR volumename, unsigned long dostype );
LONG Relabel( STRPTR drive, STRPTR newname );
LONG Inhibit( STRPTR name, long onoff );
LONG AddBuffers( STRPTR name, long number );
/*	Date, Time Routines */
LONG CompareDates( struct DateStamp *date1, struct DateStamp *date2 );
LONG DateToStr( struct DateTime *datetime );
LONG StrToDate( struct DateTime *datetime );
/*	Image Management */
BPTR InternalLoadSeg( BPTR fh, BPTR table, LONG *funcarray, LONG *stack );
void InternalUnLoadSeg( BPTR seglist, void (*freefunc)() );
BPTR NewLoadSeg( STRPTR file, struct TagItem *tags );
BPTR NewLoadSegTagList( STRPTR file, struct TagItem *tags );
BPTR NewLoadSegTags( STRPTR file, unsigned long tag1type, ... );
LONG AddSegment( STRPTR name, BPTR seg, long system );
struct Segment *FindSegment( STRPTR name, struct Segment *seg, long system );
LONG RemSegment( struct Segment *seg );
/*	Command Support */
LONG CheckSignal( long mask );
struct RDArgs *ReadArgs( STRPTR template, LONG *array, struct RDArgs *args );
LONG FindArg( STRPTR keyword, STRPTR template );
LONG ReadItem( STRPTR name, long maxchars, struct CSource *cSource );
LONG StrToLong( STRPTR string, LONG *value );
LONG MatchFirst( STRPTR pat, struct AnchorPath *anchor );
LONG MatchNext( struct AnchorPath *anchor );
void MatchEnd( struct AnchorPath *anchor );
LONG ParsePattern( STRPTR pat, STRPTR buf, long buflen );
BOOL MatchPattern( STRPTR pat, STRPTR str );
void FreeArgs( struct RDArgs *args );
STRPTR FilePart( STRPTR path );
STRPTR PathPart( STRPTR path );
BOOL AddPart( STRPTR dirname, STRPTR filename, unsigned long size );
/*	Notification */
BOOL StartNotify( struct NotifyRequest *notify );
void EndNotify( struct NotifyRequest *notify );
/*	Environment Variable functions */
BOOL SetVar( STRPTR name, STRPTR buffer, long size, long flags );
LONG GetVar( STRPTR name, STRPTR buffer, long size, long flags );
LONG DeleteVar( STRPTR name, unsigned long flags );
struct LocalVar *FindVar( STRPTR name, unsigned long type );
LONG CliInitNewcli( struct DosPacket *dp );
LONG CliInitRun( struct DosPacket *dp );
LONG WriteChars( STRPTR buf, unsigned long buflen );
LONG PutStr( STRPTR str );
LONG VPrintf( STRPTR format, LONG *argarray );
LONG Printf( STRPTR format, ... );
/* these were unimplemented until dos 36.147 */
LONG ParsePatternNoCase( STRPTR pat, STRPTR buf, long buflen );
BOOL MatchPatternNoCase( STRPTR pat, STRPTR str );
/* this was added for V37 dos, returned 0 before then. */
BOOL SameDevice( BPTR lock1, BPTR lock2 );
#endif	 /* CLIB_DOS_PROTOS_H */


Includes/clib/potgo_protos.h

#ifndef  CLIB_POTGO_PROTOS_H
#define  CLIB_POTGO_PROTOS_H
/*
**	$Filename: clib/potgo_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.3 $
**	$Date: 90/11/07 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif
UWORD AllocPotBits( unsigned long bits );
void FreePotBits( unsigned long bits );
void WritePotgo( unsigned long word, unsigned long mask );
#endif	 /* CLIB_POTGO_PROTOS_H */


Includes/clib/exec_protos.h

#ifndef  CLIB_EXEC_PROTOS_H
#define  CLIB_EXEC_PROTOS_H
/*
**	$Filename: clib/exec_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.11 $
**	$Date: 91/11/06 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif
#ifndef  EXEC_TASKS_H
#include <exec/tasks.h>
#endif
/*------ misc ---------------------------------------------------------*/
ULONG Supervisor( unsigned long (*userFunction)() );
/*------ special patchable hooks to internal exec activity ------------*/
/*------ module creation ----------------------------------------------*/
void InitCode( unsigned long startClass, unsigned long version );
void InitStruct( APTR initTable, APTR memory, unsigned long size );
struct Library *MakeLibrary( APTR funcInit, APTR structInit,
    unsigned long (*libInit)(), unsigned long dataSize,
    unsigned long segList );
void MakeFunctions( APTR target, APTR functionArray,
    unsigned long funcDispBase );
struct Resident *FindResident( UBYTE *name );
APTR InitResident( struct Resident *resident, unsigned long segList );
/*------ diagnostics --------------------------------------------------*/
void Alert( unsigned long alertNum );
void Debug( unsigned long flags );
/*------ interrupts ---------------------------------------------------*/
void Disable( void );
void Enable( void );
void Forbid( void );
void Permit( void );
ULONG SetSR( unsigned long newSR, unsigned long mask );
APTR SuperState( void );
void UserState( APTR sysStack );
struct Interrupt *SetIntVector( long intNumber, struct Interrupt *interrupt );
void AddIntServer( long intNumber, struct Interrupt *interrupt );
void RemIntServer( long intNumber, struct Interrupt *interrupt );
void Cause( struct Interrupt *interrupt );
/*------ memory allocation --------------------------------------------*/
APTR Allocate( struct MemHeader *freeList, unsigned long byteSize );
void Deallocate( struct MemHeader *freeList, APTR memoryBlock,
    unsigned long byteSize );
APTR AllocMem( unsigned long byteSize, unsigned long requirements );
APTR AllocAbs( unsigned long byteSize, APTR location );
void FreeMem( APTR memoryBlock, unsigned long byteSize );
ULONG AvailMem( unsigned long requirements );
struct MemList *AllocEntry( struct MemList *entry );
void FreeEntry( struct MemList *entry );
/*------ lists --------------------------------------------------------*/
void Insert( struct List *list, struct Node *node, struct Node *pred );
void AddHead( struct List *list, struct Node *node );
void AddTail( struct List *list, struct Node *node );
void Remove( struct Node *node );
struct Node *RemHead( struct List *list );
struct Node *RemTail( struct List *list );
void Enqueue( struct List *list, struct Node *node );
struct Node *FindName( struct List *list, UBYTE *name );
/*------ tasks --------------------------------------------------------*/
APTR AddTask( struct Task *task, APTR initPC, APTR finalPC );
void RemTask( struct Task *task );
struct Task *FindTask( UBYTE *name );
BYTE SetTaskPri( struct Task *task, long priority );
ULONG SetSignal( unsigned long newSignals, unsigned long signalSet );
ULONG SetExcept( unsigned long newSignals, unsigned long signalSet );
ULONG Wait( unsigned long signalSet );
void Signal( struct Task *task, unsigned long signalSet );
BYTE AllocSignal( long signalNum );
void FreeSignal( long signalNum );
LONG AllocTrap( long trapNum );
void FreeTrap( long trapNum );
/*------ messages -----------------------------------------------------*/
void AddPort( struct MsgPort *port );
void RemPort( struct MsgPort *port );
void PutMsg( struct MsgPort *port, struct Message *message );
struct Message *GetMsg( struct MsgPort *port );
void ReplyMsg( struct Message *message );
struct Message *WaitPort( struct MsgPort *port );
struct MsgPort *FindPort( UBYTE *name );
/*------ libraries ----------------------------------------------------*/
void AddLibrary( struct Library *library );
void RemLibrary( struct Library *library );
struct Library *OldOpenLibrary( UBYTE *libName );
void CloseLibrary( struct Library *library );
APTR SetFunction( struct Library *library, long funcOffset,
    unsigned long (*newFunction)() );
void SumLibrary( struct Library *library );
/*------ devices ------------------------------------------------------*/
void AddDevice( struct Device *device );
void RemDevice( struct Device *device );
BYTE OpenDevice( UBYTE *devName, unsigned long unit,
    struct IORequest *ioRequest, unsigned long flags );
void CloseDevice( struct IORequest *ioRequest );
BYTE DoIO( struct IORequest *ioRequest );
void SendIO( struct IORequest *ioRequest );
BOOL CheckIO( struct IORequest *ioRequest );
BYTE WaitIO( struct IORequest *ioRequest );
void AbortIO( struct IORequest *ioRequest );
/*------ resources ----------------------------------------------------*/
void AddResource( APTR resource );
void RemResource( APTR resource );
APTR OpenResource( UBYTE *resName );
/*------ private diagnostic support -----------------------------------*/
/*------ misc ---------------------------------------------------------*/
void RawDoFmt( UBYTE *formatString, APTR dataStream, void (*putChProc)(),
    APTR putChData );
ULONG GetCC( void );
ULONG TypeOfMem( APTR address );
ULONG Procure( struct Semaphore *semaport, struct Message *bidMsg );
void Vacate( struct Semaphore *semaport );
struct Library *OpenLibrary( UBYTE *libName, unsigned long version );
/*--- functions in V33 or higher (distributed as Release 1.2) ---*/
/*------ signal semaphores (note funny registers)----------------------*/
void InitSemaphore( struct SignalSemaphore *sigSem );
void ObtainSemaphore( struct SignalSemaphore *sigSem );
void ReleaseSemaphore( struct SignalSemaphore *sigSem );
ULONG AttemptSemaphore( struct SignalSemaphore *sigSem );
void ObtainSemaphoreList( struct List *sigSem );
void ReleaseSemaphoreList( struct List *sigSem );
struct SignalSemaphore *FindSemaphore( UBYTE *sigSem );
void AddSemaphore( struct SignalSemaphore *sigSem );
void RemSemaphore( struct SignalSemaphore *sigSem );
/*------ kickmem support ----------------------------------------------*/
ULONG SumKickData( void );
/*------ more memory support ------------------------------------------*/
ULONG AddMemList( unsigned long size, unsigned long attributes,
    unsigned long pri, APTR base, UBYTE *name );
void CopyMem( APTR source, APTR dest, unsigned long size );
void CopyMemQuick( APTR source, APTR dest, unsigned long size );
/*------ cache --------------------------------------------------------*/
/*--- functions in V36 or higher (distributed as Release 2.0) ---*/
void CacheClearU( void );
void CacheClearE( APTR address, unsigned long length, unsigned long caches );
ULONG CacheControl( unsigned long cacheBits, unsigned long cacheMask );
/*------ misc ---------------------------------------------------------*/
APTR CreateIORequest( struct MsgPort *port, unsigned long size );
void DeleteIORequest( APTR iorequest );
struct MsgPort *CreateMsgPort( void );
void DeleteMsgPort( struct MsgPort *port );
void ObtainSemaphoreShared( struct SignalSemaphore *sigSem );
/*------ even more memory support -------------------------------------*/
APTR AllocVec( unsigned long byteSize, unsigned long requirements );
void FreeVec( APTR memoryBlock );
APTR CreatePrivatePool( unsigned long requirements, unsigned long puddleSize,
    unsigned long puddleThresh );
void DeletePrivatePool( APTR poolHeader );
APTR AllocPooled( unsigned long memSize, APTR poolHeader );
void FreePooled( APTR memory, APTR poolHeader );
/*------ misc ---------------------------------------------------------*/
ULONG AttemptSemaphoreShared( struct SignalSemaphore *sigSem );
void ColdReboot( void );
void StackSwap( struct StackSwapStruct *newStack );
/*------ task trees ---------------------------------------------------*/
void ChildFree( APTR tid );
void ChildOrphan( APTR tid );
void ChildStatus( APTR tid );
void ChildWait( APTR tid );
/*------ future expansion ---------------------------------------------*/
APTR CachePreDMA( APTR address, ULONG *length, unsigned long flags );
APTR CachePostDMA( APTR address, ULONG *length, unsigned long flags );
#endif	 /* CLIB_EXEC_PROTOS_H */


Includes/clib/ramdrive_protos.h

#ifndef  CLIB_RAMDRIVE_PROTOS_H
#define  CLIB_RAMDRIVE_PROTOS_H
/*
**	$Filename: clib/ramdrive_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.3 $
**	$Date: 90/11/07 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif
/*--- functions in V34 or higher (distributed as Release 1.3) ---*/
STRPTR KillRAD0( void );
/*--- functions in V36 or higher (distributed as Release 2.0) ---*/
STRPTR KillRAD( unsigned long unit );
#endif	 /* CLIB_RAMDRIVE_PROTOS_H */


Includes/clib/expansion_protos.h

#ifndef  CLIB_EXPANSION_PROTOS_H
#define  CLIB_EXPANSION_PROTOS_H
/*
**	$Filename: clib/expansion_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.7 $
**	$Date: 91/10/31 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif
/*--- functions in V33 or higher (distributed as Release 1.2) ---*/
void AddConfigDev( struct ConfigDev *configDev );
/*--- functions in V36 or higher (distributed as Release 2.0) ---*/
BOOL AddBootNode( long bootPri, unsigned long flags,
    struct DeviceNode *deviceNode, struct ConfigDev *configDev );
/*--- functions in V33 or higher (distributed as Release 1.2) ---*/
void AllocBoardMem( unsigned long slotSpec );
struct ConfigDev *AllocConfigDev( void );
APTR AllocExpansionMem( unsigned long numSlots, unsigned long slotAlign );
void ConfigBoard( APTR board, struct ConfigDev *configDev );
void ConfigChain( APTR baseAddr );
struct ConfigDev *FindConfigDev( struct ConfigDev *oldConfigDev,
    long manufacturer, long product );
void FreeBoardMem( unsigned long startSlot, unsigned long slotSpec );
void FreeConfigDev( struct ConfigDev *configDev );
void FreeExpansionMem( unsigned long startSlot, unsigned long numSlots );
UBYTE ReadExpansionByte( APTR board, unsigned long offset );
void ReadExpansionRom( APTR board, struct ConfigDev *configDev );
void RemConfigDev( struct ConfigDev *configDev );
void WriteExpansionByte( APTR board, unsigned long offset,
    unsigned long byte );
void ObtainConfigBinding( void );
void ReleaseConfigBinding( void );
void SetCurrentBinding( struct CurrentBinding *currentBinding,
    unsigned long bindingSize );
ULONG GetCurrentBinding( struct CurrentBinding *currentBinding,
    unsigned long bindingSize );
struct DeviceNode *MakeDosNode( APTR parmPacket );
BOOL AddDosNode( long bootPri, unsigned long flags,
    struct DeviceNode *deviceNode );
/*--- functions in V36 or higher (distributed as Release 2.0) ---*/
#endif	 /* CLIB_EXPANSION_PROTOS_H */


Includes/clib/rexxsyslib_protos.h

#ifndef  CLIB_REXXSYSLIB_PROTOS_H
#define  CLIB_REXXSYSLIB_PROTOS_H
/*
**	$Filename: clib/rexxsyslib_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.3 $
**	$Date: 91/02/19 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
/*--- functions in V33 or higher (distributed as Release 1.2) ---*/
#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif
#ifndef  REXX_RXSLIB_H
#include <rexx/rxslib.h>
#endif
#ifndef  REXX_REXXIO_H
#include <rexx/rexxio.h>
#endif

UBYTE *CreateArgstring( UBYTE *string, unsigned long length );
void DeleteArgstring( UBYTE *argstring );
ULONG LengthArgstring( UBYTE *argstring );
struct RexxMsg *CreateRexxMsg( struct MsgPort *port, UBYTE *extension,
    UBYTE *host );
void DeleteRexxMsg( struct RexxMsg *packet );
void ClearRexxMsg( struct RexxMsg *msgptr, unsigned long count );
BOOL FillRexxMsg( struct RexxMsg *msgptr, unsigned long count,
    unsigned long mask );
BOOL IsRexxMsg( struct RexxMsg *msgptr );

void LockRexxBase( unsigned long resource );
void UnlockRexxBase( unsigned long resource );

#endif	 /* CLIB_REXXSYSLIB_PROTOS_H */


Includes/clib/gadtools_protos.h

#ifndef  CLIB_GADTOOLS_PROTOS_H
#define  CLIB_GADTOOLS_PROTOS_H
/*
**	$Filename: clib/gadtools_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.2 $
**	$Date: 90/05/02 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif
#ifndef  INTUITION_INTUITION_H
#include <intuition/intuition.h>
#endif
#ifndef  UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif
#ifndef  LIBRARIES_GADTOOLS_H
#include <libraries/gadtools.h>
#endif
/*--- functions in V36 or higher (distributed as Release 2.0) ---*/

/* Gadget Functions */

struct Gadget *CreateGadgetA( unsigned long kind, struct Gadget *gad,
    struct NewGadget *ng, struct TagItem *taglist );
struct Gadget *CreateGadget( unsigned long kind, struct Gadget *gad,
    struct NewGadget *ng, Tag tag1, ... );
void FreeGadgets( struct Gadget *gad );
void GT_SetGadgetAttrsA( struct Gadget *gad, struct Window *win,
    struct Requester *req, struct TagItem *taglist );
void GT_SetGadgetAttrs( struct Gadget *gad, struct Window *win,
    struct Requester *req, Tag tag1, ... );

/* Menu functions */

struct Menu *CreateMenusA( struct NewMenu *newmenu, struct TagItem *taglist );
struct Menu *CreateMenus( struct NewMenu *newmenu, Tag tag1, ... );
void FreeMenus( struct Menu *menu );
BOOL LayoutMenuItemsA( struct MenuItem *firstitem, APTR vi,
    struct TagItem *taglist );
BOOL LayoutMenuItems( struct MenuItem *firstitem, APTR vi, Tag tag1, ... );
BOOL LayoutMenusA( struct Menu *firstmenu, APTR vi, struct TagItem *taglist );
BOOL LayoutMenus( struct Menu *firstmenu, APTR vi, Tag tag1, ... );

/* Misc Event-Handling Functions */

struct IntuiMessage *GT_GetIMsg( struct MsgPort *iport );
void GT_ReplyIMsg( struct IntuiMessage *imsg );
void GT_RefreshWindow( struct Window *win, struct Requester *req );
void GT_BeginRefresh( struct Window *win );
void GT_EndRefresh( struct Window *win, long complete );
struct IntuiMessage *GT_FilterIMsg( struct IntuiMessage *imsg );
struct IntuiMessage *GT_PostFilterIMsg( struct IntuiMessage *imsg );
struct Gadget *CreateContext( struct Gadget **glistptr );

/* Rendering Functions */

void DrawBevelBoxA( struct RastPort *rport, long left, long top, long width,
    long height, struct TagItem *taglist );
void DrawBevelBox( struct RastPort *rport, long left, long top, long width,
    long height, Tag tag1, ... );

/* Visuals Functions */

APTR GetVisualInfoA( struct Screen *screen, struct TagItem *taglist );
APTR GetVisualInfo( struct Screen *screen, Tag tag1, ... );
void FreeVisualInfo( APTR vi );
#endif	 /* CLIB_GADTOOLS_PROTOS_H */


Includes/clib/timer_protos.h

#ifndef  CLIB_TIMER_PROTOS_H
#define  CLIB_TIMER_PROTOS_H
/*
**	$Filename: clib/timer_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.6 $
**	$Date: 91/01/25 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  DEVICES_TIMER_H
#include <devices/timer.h>
#endif
void AddTime( struct timeval *dest, struct timeval *src );
void SubTime( struct timeval *dest, struct timeval *src );
LONG CmpTime( struct timeval *dest, struct timeval *src );
ULONG ReadEClock( struct EClockVal *dest );
void GetSysTime( struct timeval *dest );
#endif	 /* CLIB_TIMER_PROTOS_H */


Includes/clib/graphics_protos.h

#ifndef  CLIB_GRAPHICS_PROTOS_H
#define  CLIB_GRAPHICS_PROTOS_H
/*
**	$Filename: clib/graphics_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  GRAPHICS_GFX_H
#include <graphics/gfx.h>
#endif
#ifndef  GRAPHICS_DISPLAYINFO_H
#include <graphics/displayinfo.h>
#endif
#ifndef  GRAPHICS_GELS_H
#include <graphics/gels.h>
#endif
#ifndef  GRAPHICS_RASTPORT_H
#include <graphics/rastport.h>
#endif
#ifndef  GRAPHICS_VIEW_H
#include <graphics/view.h>
#endif
#ifndef  GRAPHICS_COPPER_H
#include <graphics/copper.h>
#endif
#ifndef  GRAPHICS_CLIP_H
#include <graphics/clip.h>
#endif
#ifndef  GRAPHICS_REGIONS_H
#include <graphics/regions.h>
#endif
#ifndef  GRAPHICS_SPRITE_H
#include <graphics/sprite.h>
#endif
#ifndef  GRAPHICS_TEXT_H
#include <graphics/text.h>
#endif
#ifndef  HARDWARE_BLIT_H
#include <hardware/blit.h>
#endif
/*------ BitMap primitives ------*/
LONG BltBitMap( struct BitMap *srcBitMap, long xSrc, long ySrc,
    struct BitMap *destBitMap, long xDest, long yDest, long xSize,
    long ySize, unsigned long minterm, unsigned long mask,
    PLANEPTR tempA );
void BltTemplate( PLANEPTR source, long xSrc, long srcMod,
    struct RastPort *destRP, long xDest, long yDest, long xSize,
    long ySize );
/*------ Text routines ------*/
void ClearEOL( struct RastPort *rp );
void ClearScreen( struct RastPort *rp );
WORD TextLength( struct RastPort *rp, STRPTR string, unsigned long count );
LONG Text( struct RastPort *rp, STRPTR string, unsigned long count );
LONG SetFont( struct RastPort *rp, struct TextFont *textFont );
struct TextFont *OpenFont( struct TextAttr *textAttr );
void CloseFont( struct TextFont *textFont );
ULONG AskSoftStyle( struct RastPort *rp );
ULONG SetSoftStyle( struct RastPort *rp, unsigned long style,
    unsigned long enable );
/*------	Gels routines ------*/
void AddBob( struct Bob *bob, struct RastPort *rp );
void AddVSprite( struct VSprite *vSprite, struct RastPort *rp );
void DoCollision( struct RastPort *rp );
void DrawGList( struct RastPort *rp, struct ViewPort *vp );
void InitGels( struct VSprite *head, struct VSprite *tail,
    struct GelsInfo *gelsInfo );
void InitMasks( struct VSprite *vSprite );
void RemIBob( struct Bob *bob, struct RastPort *rp, struct ViewPort *vp );
void RemVSprite( struct VSprite *vSprite );
void SetCollision( unsigned long num,
    void (*routine)(struct VSprite *vSprite, APTR),
    struct GelsInfo *gelsInfo );
void SortGList( struct RastPort *rp );
void AddAnimOb( struct AnimOb *anOb, struct AnimOb **anKey,
    struct RastPort *rp );
void Animate( struct AnimOb **anKey, struct RastPort *rp );
BOOL GetGBuffers( struct AnimOb *anOb, struct RastPort *rp, long flag );
void InitGMasks( struct AnimOb *anOb );
/*------	General graphics routines ------*/
void DrawEllipse( struct RastPort *rp, long xCenter, long yCenter, long a,
    long b );
LONG AreaEllipse( struct RastPort *rp, long xCenter, long yCenter, long a,
    long b );
void LoadRGB4( struct ViewPort *vp, UWORD *colors, long count );
void InitRastPort( struct RastPort *rp );
void InitVPort( struct ViewPort *vp );
void MrgCop( struct View *view );
void MakeVPort( struct View *view, struct ViewPort *vp );
void LoadView( struct View *view );
void WaitBlit( void );
void SetRast( struct RastPort *rp, unsigned long pen );
void Move( struct RastPort *rp, long x, long y );
void Draw( struct RastPort *rp, long x, long y );
LONG AreaMove( struct RastPort *rp, long x, long y );
LONG AreaDraw( struct RastPort *rp, long x, long y );
LONG AreaEnd( struct RastPort *rp );
void WaitTOF( void );
void QBlit( struct bltnode *blit );
void InitArea( struct AreaInfo *areaInfo, APTR vectorBuffer,
    long maxVectors );
void SetRGB4( struct ViewPort *vp, long index, unsigned long red,
    unsigned long green, unsigned long blue );
void QBSBlit( struct bltnode *blit );
void BltClear( PLANEPTR memBlock, unsigned long byteCount,
    unsigned long flags );
void RectFill( struct RastPort *rp, long xMin, long yMin, long xMax,
    long yMax );
void BltPattern( struct RastPort *rp, PLANEPTR mask, long xMin, long yMin,
    long xMax, long yMax, unsigned long maskBPR );
ULONG ReadPixel( struct RastPort *rp, long x, long y );
LONG WritePixel( struct RastPort *rp, long x, long y );
BOOL Flood( struct RastPort *rp, unsigned long mode, long x, long y );
void PolyDraw( struct RastPort *rp, long count, WORD *polyTable );
void SetAPen( struct RastPort *rp, unsigned long pen );
void SetBPen( struct RastPort *rp, unsigned long pen );
void SetDrMd( struct RastPort *rp, unsigned long drawMode );
void InitView( struct View *view );
void CBump( struct UCopList *copList );
void CMove( struct UCopList *copList, APTR destination, long data );
void CWait( struct UCopList *copList, long v, long h );
LONG VBeamPos( void );
void InitBitMap( struct BitMap *bitMap, long depth, long width, long height );
void ScrollRaster( struct RastPort *rp, long dx, long dy, long xMin, long yMin,
    long xMax, long yMax );
void WaitBOVP( struct ViewPort *vp );
WORD GetSprite( struct SimpleSprite *sprite, long num );
void FreeSprite( long num );
void ChangeSprite( struct ViewPort *vp, struct SimpleSprite *sprite,
    PLANEPTR newData );
void MoveSprite( struct ViewPort *vp, struct SimpleSprite *sprite, long x,
    long y );
void LockLayerRom( struct Layer *layer );
void UnlockLayerRom( struct Layer *layer );
void SyncSBitMap( struct Layer *layer );
void CopySBitMap( struct Layer *layer );
void OwnBlitter( void );
void DisownBlitter( void );
struct TmpRas *InitTmpRas( struct TmpRas *tmpRas, PLANEPTR buffer,
    long size );
void AskFont( struct RastPort *rp, struct TextAttr *textAttr );
void AddFont( struct TextFont *textFont );
void RemFont( struct TextFont *textFont );
PLANEPTR AllocRaster( unsigned long width, unsigned long height );
void FreeRaster( PLANEPTR p, unsigned long width, unsigned long height );
void AndRectRegion( struct Region *region, struct Rectangle *rectangle );
BOOL OrRectRegion( struct Region *region, struct Rectangle *rectangle );
struct Region *NewRegion( void );
BOOL ClearRectRegion( struct Region *region, struct Rectangle *rectangle );
void ClearRegion( struct Region *region );
void DisposeRegion( struct Region *region );
void FreeVPortCopLists( struct ViewPort *vp );
void FreeCopList( struct CopList *copList );
void ClipBlit( struct RastPort *srcRP, long xSrc, long ySrc,
    struct RastPort *destRP, long xDest, long yDest, long xSize,
    long ySize, unsigned long minterm );
BOOL XorRectRegion( struct Region *region, struct Rectangle *rectangle );
void FreeCprList( struct cprlist *cprList );
struct ColorMap *GetColorMap( long entries );
void FreeColorMap( struct ColorMap *colorMap );
ULONG GetRGB4( struct ColorMap *colorMap, long entry );
void ScrollVPort( struct ViewPort *vp );
struct CopList *UCopperListInit( struct UCopList *uCopList, long n );
void FreeGBuffers( struct AnimOb *anOb, struct RastPort *rp, long flag );
void BltBitMapRastPort( struct BitMap *srcBitMap, long xSrc, long ySrc,
    struct RastPort *destRP, long xDest, long yDest, long xSize,
    long ySize, unsigned long minterm );
BOOL OrRegionRegion( struct Region *srcRegion, struct Region *destRegion );
BOOL XorRegionRegion( struct Region *srcRegion, struct Region *destRegion );
BOOL AndRegionRegion( struct Region *srcRegion, struct Region *destRegion );
void SetRGB4CM( struct ColorMap *colorMap, long index, unsigned long red,
    unsigned long green, unsigned long blue );
void BltMaskBitMapRastPort( struct BitMap *srcBitMap, long xSrc, long ySrc,
    struct RastPort *destRP, long xDest, long yDest, long xSize,
    long ySize, unsigned long minterm, PLANEPTR bltMask );
BOOL AttemptLockLayerRom( struct Layer *layer );
/*--- functions in V36 or higher (distributed as Release 2.0) ---*/
APTR GfxNew( unsigned long gfxNodeType );
void GfxFree( APTR gfxNodePtr );
void GfxAssociate( APTR associateNode, APTR gfxNodePtr );
void BitMapScale( struct BitScaleArgs *bitScaleArgs );
UWORD ScalerDiv( unsigned long factor, unsigned long numerator,
    unsigned long denominator );
WORD TextExtent( struct RastPort *rp, STRPTR string, long count,
    struct TextExtent *textExtent );
ULONG TextFit( struct RastPort *rp, STRPTR string, unsigned long strLen,
    struct TextExtent *textExtent, struct TextExtent *constrainingExtent,
    long strDirection, unsigned long constrainingBitWidth,
    unsigned long constrainingBitHeight );
APTR GfxLookUp( APTR associateNode );
BOOL VideoControl( struct ColorMap *colorMap, struct TagItem *tagarray );
struct MonitorSpec *OpenMonitor( STRPTR monitorName,
    unsigned long displayID );
BOOL CloseMonitor( struct MonitorSpec *monitorSpec );
DisplayInfoHandle FindDisplayInfo( unsigned long displayID );
ULONG NextDisplayInfo( unsigned long displayID );
ULONG GetDisplayInfoData( DisplayInfoHandle handle, UBYTE *buf,
    unsigned long size, unsigned long tagID, unsigned long displayID );
void FontExtent( struct TextFont *font, struct TextExtent *fontExtent );
LONG ReadPixelLine8( struct RastPort *rp, unsigned long xstart,
    unsigned long ystart, unsigned long width, UBYTE *array,
    struct RastPort *tempRP );
LONG WritePixelLine8( struct RastPort *rp, unsigned long xstart,
    unsigned long ystart, unsigned long width, UBYTE *array,
    struct RastPort *tempRP );
LONG ReadPixelArray8( struct RastPort *rp, unsigned long xstart,
    unsigned long ystart, unsigned long xstop, unsigned long ystop,
    UBYTE *array, struct RastPort *temprp );
LONG WritePixelArray8( struct RastPort *rp, unsigned long xstart,
    unsigned long ystart, unsigned long xstop, unsigned long ystop,
    UBYTE *array, struct RastPort *temprp );
LONG GetVPModeID( struct ViewPort *vp );
LONG ModeNotAvailable( unsigned long modeID );
WORD WeighTAMatch( struct TextAttr *reqTextAttr,
    struct TextAttr *targetTextAttr, struct TagItem *targetTags );
void EraseRect( struct RastPort *rp, long xMin, long yMin, long xMax,
    long yMax );
ULONG ExtendFont( struct TextFont *font, struct TagItem *fontTags );
void StripFont( struct TextFont *font );
#endif	 /* CLIB_GRAPHICS_PROTOS_H */


Includes/clib/translator_protos.h

#ifndef  CLIB_TRANSLATOR_PROTOS_H
#define  CLIB_TRANSLATOR_PROTOS_H
/*
**	$Filename: clib/translator_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.1 $
**	$Date: 90/11/07 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif
LONG Translate( STRPTR inputString, long inputLength, STRPTR outputBuffer,
    long bufferSize );
#endif	 /* CLIB_TRANSLATOR_PROTOS_H */


Includes/clib/icon_protos.h

#ifndef  CLIB_ICON_PROTOS_H
#define  CLIB_ICON_PROTOS_H
/*
**	$Filename: clib/icon_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.1 $
**	$Date: 91/03/01 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
/*--- functions in V36 or higher (distributed as Release 2.0) ---*/
#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif
#ifndef  WORKBENCH_WORKBENCH_H
#include <workbench/workbench.h>
#endif
LONG GetIcon( UBYTE *name, struct DiskObject *icon,
    struct FreeList *freelist );
BOOL PutIcon( UBYTE *name, struct DiskObject *icon );
void FreeFreeList( struct FreeList *freelist );
BOOL AddFreeList( struct FreeList *freelist, APTR mem, unsigned long size );
struct DiskObject *GetDiskObject( UBYTE *name );
BOOL PutDiskObject( UBYTE *name, struct DiskObject *diskobj );
void FreeDiskObject( struct DiskObject *diskobj );
UBYTE *FindToolType( UBYTE **toolTypeArray, UBYTE *typeName );
BOOL MatchToolValue( UBYTE *typeString, UBYTE *value );
UBYTE *BumpRevision( UBYTE *newname, UBYTE *oldname );
struct DiskObject *GetDefDiskObject( long type );
BOOL PutDefDiskObject( struct DiskObject *diskObject );
struct DiskObject *GetDiskObjectNew( UBYTE *name );
BOOL DeleteDiskObject( UBYTE *name );
#endif	 /* CLIB_ICON_PROTOS_H */


Includes/clib/utility_protos.h

#ifndef  CLIB_UTILITY_PROTOS_H
#define  CLIB_UTILITY_PROTOS_H
/*
**	$Filename: clib/utility_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.6 $
**	$Date: 91/02/13 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif
#ifndef  UTILITY_DATE_H
#include <utility/date.h>
#endif
#ifndef  UTILITY_HOOKS_H
#include <utility/hooks.h>
#endif
/* *** TagItem FUNCTIONS *** */
struct TagItem *FindTagItem( Tag tagVal, struct TagItem *tagList );
ULONG GetTagData( Tag tagVal, unsigned long defaultVal,
    struct TagItem *tagList );
ULONG PackBoolTags( unsigned long initialFlags, struct TagItem *tagList,
    struct TagItem *boolMap );
struct TagItem *NextTagItem( struct TagItem **tagListPtr );
void FilterTagChanges( struct TagItem *newTagList, struct TagItem *oldTagList,
    long apply );
void MapTags( struct TagItem *tagList, struct TagItem *mapList,
    long includeMiss );
struct TagItem *AllocateTagItems( unsigned long numItems );
struct TagItem *CloneTagItems( struct TagItem *tagList );
void FreeTagItems( struct TagItem *tagList );
void RefreshTagItemClones( struct TagItem *cloneList,
    struct TagItem *origList );
BOOL TagInArray( Tag tagVal, Tag *tagArray );
LONG FilterTagItems( struct TagItem *tagList, Tag *filterArray, long logic );

/* *** HOOK FUNCTIONS *** * */
ULONG CallHookPkt( struct Hook *hook, APTR object, APTR paramPacket );

/* *** DATE FUNCTIONS *** * */
void Amiga2Date( unsigned long amigaTime, struct ClockData *date );
ULONG Date2Amiga( struct ClockData *date );
ULONG CheckDate( struct ClockData *date );

/* *** 32 BIT MATH FUNCTIONS *** * */
LONG SMult32( long factor1, long factor2 );
ULONG UMult32( unsigned long factor1, unsigned long factor2 );
/* NOTE: Quotient:Remainder returned in d0:d1 */
LONG SDivMod32( long dividend, long divisor );
ULONG UDivMod32( unsigned long dividend, unsigned long divisor );

/* *** International string routines *** */
LONG Stricmp( UBYTE *string1, UBYTE *string2 );
LONG Strnicmp( UBYTE *string1, UBYTE *string2, long length );
UBYTE ToUpper( unsigned long character );
UBYTE ToLower( unsigned long character );
#endif	 /* CLIB_UTILITY_PROTOS_H */


Includes/clib/iffparse_protos.h

#ifndef  CLIB_IFFPARSE_PROTOS_H
#define  CLIB_IFFPARSE_PROTOS_H
/*
**	$Filename: clib/iffparse_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 33.2 $
**	$Date: 90/12/13 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif
/*--- functions in V33 or higher (distributed as Release 1.2) ---*/
/*------ Basic functions ------*/
struct IFFHandle *AllocIFF( void );
LONG OpenIFF( struct IFFHandle *iff, long rwMode );
LONG ParseIFF( struct IFFHandle *iff, long control );
void CloseIFF( struct IFFHandle *iff );
void FreeIFF( struct IFFHandle *iff );
/*------ Read/Write functions ------*/
LONG ReadChunkBytes( struct IFFHandle *iff, APTR buf, long size );
LONG WriteChunkBytes( struct IFFHandle *iff, APTR buf, long size );
LONG ReadChunkRecords( struct IFFHandle *iff, APTR buf, long bytesPerRecord,
    long nRecords );
LONG WriteChunkRecords( struct IFFHandle *iff, APTR buf, long bytesPerRecord,
    long nRecords );
/*------ Context entry/exit ------*/
LONG PushChunk( struct IFFHandle *iff, long type, long id, long size );
LONG PopChunk( struct IFFHandle *iff );
/*------ Low-level handler installation ------*/
LONG EntryHandler( struct IFFHandle *iff, long type, long id, long position,
    struct Hook *handler, APTR object );
LONG ExitHandler( struct IFFHandle *iff, long type, long id, long position,
    struct Hook *handler, APTR object );
/*------ Built-in chunk/property handlers ------*/
LONG PropChunk( struct IFFHandle *iff, long type, long id );
LONG PropChunks( struct IFFHandle *iff, LONG *propArray, long nProps );
LONG StopChunk( struct IFFHandle *iff, long type, long id );
LONG StopChunks( struct IFFHandle *iff, LONG *propArray, long nProps );
LONG CollectionChunk( struct IFFHandle *iff, long type, long id );
LONG CollectionChunks( struct IFFHandle *iff, LONG *propArray, long nProps );
LONG StopOnExit( struct IFFHandle *iff, long type, long id );
/*------ Context utilities ------*/
struct StoredProperty *FindProp( struct IFFHandle *iff, long type, long id );
struct CollectionItem *FindCollection( struct IFFHandle *iff, long type,
    long id );
struct ContextNode *FindPropContext( struct IFFHandle *iff );
struct ContextNode *CurrentChunk( struct IFFHandle *iff );
struct ContextNode *ParentChunk( struct ContextNode *contextNode );
/*------ LocalContextItem support functions ------*/
struct LocalContextItem *AllocLocalItem( long type, long id, long ident,
    long dataSize );
APTR LocalItemData( struct LocalContextItem *localItem );
void SetLocalItemPurge( struct LocalContextItem *localItem,
    struct Hook *purgeHook );
void FreeLocalItem( struct LocalContextItem *localItem );
struct LocalContextItem *FindLocalItem( struct IFFHandle *iff, long type,
    long id, long ident );
LONG StoreLocalItem( struct IFFHandle *iff, struct LocalContextItem *localItem,
    long position );
void StoreItemInContext( struct IFFHandle *iff,
    struct LocalContextItem *localItem,
    struct ContextNode *contextNode );
/*------ IFFHandle initialization ------*/
void InitIFF( struct IFFHandle *iff, long flags, struct Hook *streamHook );
void InitIFFasDOS( struct IFFHandle *iff );
void InitIFFasClip( struct IFFHandle *iff );
/*------ Internal clipboard support ------*/
struct ClipboardHandle *OpenClipboard( long unitNum );
void CloseClipboard( struct ClipboardHandle *clipboard );
/*------ Miscellaneous ------*/
LONG GoodID( long id );
LONG GoodType( long type );
STRPTR IDtoStr( long id, STRPTR buf );
#endif	 /* CLIB_IFFPARSE_PROTOS_H */


Includes/clib/wb_protos.h

#ifndef  CLIB_WB_PROTOS_H
#define  CLIB_WB_PROTOS_H
/*
**	$Filename: clib/wb_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.3 $
**	$Date: 91/03/04 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
/*--- functions in V36 or higher (distributed as Release 2.0) ---*/
#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif
#ifndef  WORKBENCH_WORKBENCH_H
#include <workbench/workbench.h>
#endif
#ifndef  INTUITION_INTUITION_H
#include <intuition/intuition.h>
#endif
#ifndef  UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

struct AppWindow *AddAppWindowA( unsigned long id, unsigned long userdata,
    struct Window *window, struct MsgPort *msgport,
    struct TagItem *taglist );
struct AppWindow *AddAppWindow( unsigned long id, unsigned long userdata,
    struct Window *window, struct MsgPort *msgport, Tag tag1, ... );

BOOL RemoveAppWindow( struct AppWindow *appWindow );

struct AppIcon *AddAppIconA( unsigned long id, unsigned long userdata,
    UBYTE *text, struct MsgPort *msgport, struct FileLock *lock,
    struct DiskObject *diskobj, struct TagItem *taglist );
struct AppIcon *AddAppIcon( unsigned long id, unsigned long userdata,
    UBYTE *text, struct MsgPort *msgport, struct FileLock *lock,
    struct DiskObject *diskobj, Tag tag1, ... );

BOOL RemoveAppIcon( struct AppIcon *appIcon );

struct AppMenuItem *AddAppMenuItemA( unsigned long id, unsigned long userdata,
    UBYTE *text, struct MsgPort *msgport, struct TagItem *taglist );
struct AppMenuItem *AddAppMenuItem( unsigned long id, unsigned long userdata,
    UBYTE *text, struct MsgPort *msgport, Tag tag1, ... );

BOOL RemoveAppMenuItem( struct AppMenuItem *appMenuItem );

#endif	 /* CLIB_WB_PROTOS_H */


Includes/clib/input_protos.h

#ifndef  CLIB_INPUT_PROTOS_H
#define  CLIB_INPUT_PROTOS_H
/*
**	$Filename: clib/input_protos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.2 $
**	$Date: 90/11/07 $
**
**	C prototypes. For use with 32 bit integers only.
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif
/*--- functions in V36 or higher (distributed as Release 2.0) ---*/
UWORD PeekQualifier( void );
#endif	 /* CLIB_INPUT_PROTOS_H */


Includes/devices/audio.h

#ifndef DEVICES_AUDIO_H
#define DEVICES_AUDIO_H
/*
**	$Filename: devices/audio.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.3 $
**	$Date: 90/08/29 $
**
**	audio.device include file
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_IO_H
#include "exec/io.h"
#endif

#define AUDIONAME		"audio.device"

#define ADHARD_CHANNELS		4

#define ADALLOC_MINPREC		-128
#define ADALLOC_MAXPREC		127

#define ADCMD_FREE		(CMD_NONSTD+0)
#define ADCMD_SETPREC		(CMD_NONSTD+1)
#define ADCMD_FINISH		(CMD_NONSTD+2)
#define ADCMD_PERVOL		(CMD_NONSTD+3)
#define ADCMD_LOCK		(CMD_NONSTD+4)
#define ADCMD_WAITCYCLE		(CMD_NONSTD+5)
#define ADCMD_ALLOCATE		32

#define ADIOB_PERVOL		4
#define ADIOF_PERVOL		(1<<4)
#define ADIOB_SYNCCYCLE		5
#define ADIOF_SYNCCYCLE		(1<<5)
#define ADIOB_NOWAIT		6
#define ADIOF_NOWAIT		(1<<6)
#define ADIOB_WRITEMESSAGE	7
#define ADIOF_WRITEMESSAGE	(1<<7)

#define ADIOERR_NOALLOCATION	-10
#define ADIOERR_ALLOCFAILED	-11
#define ADIOERR_CHANNELSTOLEN	-12

struct IOAudio {
    struct IORequest ioa_Request;
    WORD ioa_AllocKey;
    UBYTE *ioa_Data;
    ULONG ioa_Length;
    UWORD ioa_Period;
    UWORD ioa_Volume;
    UWORD ioa_Cycles;
    struct Message ioa_WriteMsg;
};

#endif	/* DEVICES_AUDIO_H */


Includes/devices/gameport.h

#ifndef DEVICES_GAMEPORT_H
#define DEVICES_GAMEPORT_H
/*
**	$Filename: devices/gameport.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.1 $
**	$Date: 90/11/05 $
**
**	GamePort device command definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef	EXEC_TYPES_H
#include	"exec/types.h"
#endif

#ifndef	EXEC_IO_H
#include	"exec/io.h"
#endif

/******	 GamePort commands ******/
#define	 GPD_READEVENT	   (CMD_NONSTD+0)
#define	 GPD_ASKCTYPE	   (CMD_NONSTD+1)
#define	 GPD_SETCTYPE	   (CMD_NONSTD+2)
#define	 GPD_ASKTRIGGER	   (CMD_NONSTD+3)
#define	 GPD_SETTRIGGER	   (CMD_NONSTD+4)

/******	 GamePort structures ******/

/* gpt_Keys */
#define	 GPTB_DOWNKEYS	   0
#define	 GPTF_DOWNKEYS	   (1<<0)
#define	 GPTB_UPKEYS	   1
#define	 GPTF_UPKEYS	   (1<<1)

struct GamePortTrigger {
   UWORD gpt_Keys;	   /* key transition triggers */
   UWORD gpt_Timeout;	   /* time trigger (vertical blank units) */
   UWORD gpt_XDelta;	   /* X distance trigger */
   UWORD gpt_YDelta;	   /* Y distance trigger */
};

/****** Controller Types ******/
#define	 GPCT_ALLOCATED	   -1	 /* allocated by another user */
#define	 GPCT_NOCONTROLLER 0

#define	 GPCT_MOUSE	   1
#define	 GPCT_RELJOYSTICK  2
#define	 GPCT_ABSJOYSTICK  3

/****** Errors ******/
#define	 GPDERR_SETCTYPE   1	 /* this controller not valid at this time */

#endif	/* DEVICES_GAMEPORT_H */


Includes/devices/keymap.h

#ifndef	DEVICES_KEYMAP_H
#define	DEVICES_KEYMAP_H
/*
**	$Filename: devices/keymap.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.3 $
**	$Date: 90/04/13 $
**
**	key map definitions for keymap.resource, keymap.library, and
**	console.device
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_NODES_H
#include	"exec/nodes.h"
#endif
#ifndef EXEC_LISTS_H
#include	"exec/lists.h"
#endif

struct	 KeyMap {
    UBYTE   *km_LoKeyMapTypes;
    ULONG   *km_LoKeyMap;
    UBYTE   *km_LoCapsable;
    UBYTE   *km_LoRepeatable;
    UBYTE   *km_HiKeyMapTypes;
    ULONG   *km_HiKeyMap;
    UBYTE   *km_HiCapsable;
    UBYTE   *km_HiRepeatable;
};

struct	KeyMapNode {
    struct Node kn_Node;	/* including name of keymap */
    struct KeyMap kn_KeyMap;
};

/* the structure of keymap.resource */
struct	KeyMapResource {
    struct Node kr_Node;
    struct List kr_List;	/* a list of KeyMapNodes */
};

/* Key Map Types */
#define  KC_NOQUAL   0
#define  KC_VANILLA  7		/* note that SHIFT+ALT+CTRL is VANILLA */
#define  KCB_SHIFT   0
#define  KCF_SHIFT   0x01
#define  KCB_ALT     1
#define  KCF_ALT     0x02
#define  KCB_CONTROL 2
#define  KCF_CONTROL 0x04
#define  KCB_DOWNUP  3
#define  KCF_DOWNUP  0x08

#define  KCB_DEAD    5		/* may be dead or modified by dead key: */
#define  KCF_DEAD    0x20	/*   use dead prefix bytes		*/

#define  KCB_STRING  6
#define  KCF_STRING  0x40

#define  KCB_NOP     7
#define  KCF_NOP     0x80

/* Dead Prefix Bytes */
#define DPB_MOD	0
#define DPF_MOD	0x01
#define DPB_DEAD	3
#define DPF_DEAD	0x08

#define DP_2DINDEXMASK	0x0f	/* mask for index for 1st of two dead keys */
#define DP_2DFACSHIFT	4	/* shift for factor for 1st of two dead keys */

#endif	/* DEVICES_KEYMAP_H */


Includes/devices/prtgfx.h

#ifndef DEVICES_PRTGFX_H
#define DEVICES_PRTGFX_H
/*
**	$Filename: devices/prtgfx.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.12 $
**	$Date: 90/07/26 $
**
**	printer.device structure definitions
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef  EXEC_TYPES_H
#include "exec/types.h"
#endif

#define	PCMYELLOW	0		/* byte index for yellow */
#define	PCMMAGENTA	1		/* byte index for magenta */
#define	PCMCYAN		2		/* byte index for cyan */
#define	PCMBLACK	3		/* byte index for black */
#define PCMBLUE		PCMYELLOW	/* byte index for blue */
#define PCMGREEN	PCMMAGENTA	/* byte index for green */
#define PCMRED		PCMCYAN		/* byte index for red */
#define PCMWHITE	PCMBLACK	/* byte index for white */

union colorEntry {
    ULONG colorLong;	/* quick access to all of YMCB */
    UBYTE colorByte[4];	/* 1 entry for each of YMCB */
    BYTE colorSByte[4];	/* ditto (except signed) */
};

struct PrtInfo { /* printer info */
    int (*pi_render)();		/* PRIVATE - DO NOT USE! */
    struct RastPort *pi_rp;		/* PRIVATE - DO NOT USE! */
    struct RastPort *pi_temprp;	/* PRIVATE - DO NOT USE! */
    UWORD *pi_RowBuf;		/* PRIVATE - DO NOT USE! */
    UWORD *pi_HamBuf;		/* PRIVATE - DO NOT USE! */
    union colorEntry *pi_ColorMap;	/* PRIVATE - DO NOT USE! */
    union colorEntry *pi_ColorInt;	/* color intensities for entire row */
    union colorEntry *pi_HamInt;	/* PRIVATE - DO NOT USE! */
    union colorEntry *pi_Dest1Int;	/* PRIVATE - DO NOT USE! */
    union colorEntry *pi_Dest2Int;	/* PRIVATE - DO NOT USE! */
    UWORD *pi_ScaleX;		/* array of scale values for X */
    UWORD *pi_ScaleXAlt;		/* PRIVATE - DO NOT USE! */
    UBYTE *pi_dmatrix;		/* pointer to dither matrix */
    UWORD *pi_TopBuf;		/* PRIVATE - DO NOT USE! */
    UWORD *pi_BotBuf;		/* PRIVATE - DO NOT USE! */

    UWORD pi_RowBufSize;		/* PRIVATE - DO NOT USE! */
    UWORD pi_HamBufSize;		/* PRIVATE - DO NOT USE! */
    UWORD pi_ColorMapSize;		/* PRIVATE - DO NOT USE! */
    UWORD pi_ColorIntSize;		/* PRIVATE - DO NOT USE! */
    UWORD pi_HamIntSize;		/* PRIVATE - DO NOT USE! */
    UWORD pi_Dest1IntSize;		/* PRIVATE - DO NOT USE! */
    UWORD pi_Dest2IntSize;		/* PRIVATE - DO NOT USE! */
    UWORD pi_ScaleXSize;		/* PRIVATE - DO NOT USE! */
    UWORD pi_ScaleXAltSize;		/* PRIVATE - DO NOT USE! */

    UWORD pi_PrefsFlags;		/* PRIVATE - DO NOT USE! */
    ULONG pi_special;		/* PRIVATE - DO NOT USE! */
    UWORD pi_xstart;		/* PRIVATE - DO NOT USE! */
    UWORD pi_ystart;		/* PRIVATE - DO NOT USE! */
    UWORD pi_width;			/* source width (in pixels) */
    UWORD pi_height;		/* PRIVATE - DO NOT USE! */
    ULONG pi_pc;			/* PRIVATE - DO NOT USE! */
    ULONG pi_pr;			/* PRIVATE - DO NOT USE! */
    UWORD pi_ymult;			/* PRIVATE - DO NOT USE! */
    UWORD pi_ymod;			/* PRIVATE - DO NOT USE! */
    WORD pi_ety;			/* PRIVATE - DO NOT USE! */
    UWORD pi_xpos;			/* offset to start printing picture */
    UWORD pi_threshold;		/* threshold value (from prefs) */
    UWORD pi_tempwidth;		/* PRIVATE - DO NOT USE! */
    UWORD pi_flags;			/* PRIVATE - DO NOT USE! */
};

#endif	/* DEVICES_PRTGFX_H */


Includes/devices/audio.i

    IFND	DEVICES_AUDIO_I
DEVICES_AUDIO_I SET	1
**
**	$Filename: devices/audio.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.3 $
**	$Date: 90/08/29 $
**
**	audio.device include file
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND	EXEC_IO_I
    INCLUDE	"exec/io.i"
    ENDC

AUDIONAME MACRO
        DC.B	'audio.device',0
    ENDM

ADHARD_CHANNELS		EQU	4

ADALLOC_MINPREC		EQU	-128
ADALLOC_MAXPREC		EQU	127

ADCMD_FREE		EQU	CMD_NONSTD+0
ADCMD_SETPREC		EQU	CMD_NONSTD+1
ADCMD_FINISH		EQU	CMD_NONSTD+2
ADCMD_PERVOL		EQU	CMD_NONSTD+3
ADCMD_LOCK		EQU	CMD_NONSTD+4
ADCMD_WAITCYCLE		EQU	CMD_NONSTD+5
ADCMD_ALLOCATE		EQU	32

ADIOB_PERVOL		EQU	4
ADIOF_PERVOL		EQU	1<<4
ADIOB_SYNCCYCLE		EQU	5
ADIOF_SYNCCYCLE		EQU	1<<5
ADIOB_NOWAIT		EQU	6
ADIOF_NOWAIT		EQU	1<<6
ADIOB_WRITEMESSAGE	EQU	7
ADIOF_WRITEMESSAGE	EQU	1<<7

ADIOERR_NOALLOCATION	EQU	-10
ADIOERR_ALLOCFAILED	EQU	-11
ADIOERR_CHANNELSTOLEN	EQU	-12

    STRUCTURE	IOAudio,IO_SIZE
    WORD	ioa_AllocKey
    APTR	ioa_Data
    ULONG	ioa_Length
    UWORD	ioa_Period
    UWORD	ioa_Volume
    UWORD	ioa_Cycles
    STRUCT	ioa_WriteMsg,MN_SIZE
    LABEL	ioa_SIZEOF

    ENDC	; DEVICES_AUDIO_I


Includes/devices/gameport.i

    IFND	DEVICES_GAMEPORT_I
DEVICES_GAMEPORT_I	SET	1
**
**	$Filename: devices/gameport.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.1 $
**	$Date: 90/11/05 $
**
**	Game Port device command definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

   IFND  EXEC_TYPES_I
   INCLUDE  "exec/types.i"
   ENDC

   IFND	 EXEC_IO_I
   INCLUDE  "exec/io.i"
   ENDC

******* GamePort commands *******
   DEVINIT

   DEVCMD   GPD_READEVENT
   DEVCMD   GPD_ASKCTYPE
   DEVCMD   GPD_SETCTYPE
   DEVCMD   GPD_ASKTRIGGER
   DEVCMD   GPD_SETTRIGGER

******* GamePort structures *******

*  gpt_Keys
   BITDEF	GPT,DOWNKEYS,0
   BITDEF	GPT,UPKEYS,1

 STRUCTURE  GamePortTrigger,0
       UWORD   gpt_Keys	       ;key transition triggers
       UWORD   gpt_Timeout     ;time trigger (vertical blank units)
       UWORD   gpt_XDelta      ;X distance trigger
       UWORD   gpt_YDelta      ;Y distance trigger
       LABEL   gpt_SIZEOF

******* Controller Types ******
GPCT_ALLOCATED	  EQU	-1     ; allocated by another user
GPCT_NOCONTROLLER EQU	0

GPCT_MOUSE	  EQU	1
GPCT_RELJOYSTICK  EQU	2
GPCT_ABSJOYSTICK  EQU	3

******* Errors ******
GPDERR_SETCTYPE	  EQU	1      ; this controller not valid at this time

    ENDC	; DEVICES_GAMEPORT_I


Includes/devices/keymap.i

    IFND	DEVICES_KEYMAP_I
DEVICES_KEYMAP_I	SET	1
**
**	$Filename: devices/keymap.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.3 $
**	$Date: 90/04/13 $
**
**	key map definitions for keymap.resource, keymap.library, and
**	console.device
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

       IFND	EXEC_NODES_I
       INCLUDE	"exec/nodes.i"
       ENDC
       IFND	EXEC_LISTS_I
       INCLUDE	"exec/lists.i"
       ENDC

 STRUCTURE  KeyMap,0
   APTR  km_LoKeyMapTypes
   APTR  km_LoKeyMap
   APTR  km_LoCapsable
   APTR  km_LoRepeatable
   APTR  km_HiKeyMapTypes
   APTR  km_HiKeyMap
   APTR  km_HiCapsable
   APTR  km_HiRepeatable
   LABEL km_SIZEOF

 STRUCTURE	KeyMapNode,0
    STRUCT  kn_Node,LN_SIZE	; including name of keymap
    STRUCT  kn_KeyMap,km_SIZEOF
    LABEL   kn_SIZEOF

;------ the structure of keymap.resource
 STRUCTURE	KeyMapResource,0
    STRUCT  kr_Node,LN_SIZE
    STRUCT  kr_List,LH_SIZE	; a list of KeyMapNodes
    LABEL   kr_SIZEOF

KCB_NOP     EQU   7
KCF_NOP     EQU   $80

KC_NOQUAL   EQU   0
KC_VANILLA  EQU   7	      ; note that SHIFT+ALT+CTRL is VANILLA
KCB_SHIFT   EQU   0
KCF_SHIFT   EQU   $01
KCB_ALT     EQU   1
KCF_ALT     EQU   $02
KCB_CONTROL EQU   2
KCF_CONTROL EQU   $04
KCB_DOWNUP  EQU   3
KCF_DOWNUP  EQU   $08
KCB_DEAD    EQU   5		; may be dead or modified by dead key:
KCF_DEAD    EQU   $20		;   use dead prefix bytes

KCB_STRING  EQU   6
KCF_STRING  EQU   $40

;------ Dead Prefix Bytes
DPB_MOD	EQU	0
DPF_MOD	EQU	$01
DPB_DEAD	EQU	3
DPF_DEAD	EQU	$08

DP_2DINDEXMASK	EQU	$0F	; mask for index for 1st of two dead keys
DP_2DFACSHIFT	EQU	4	; shift for factor for 1st of two dead keys

    ENDC	; DEVICES_KEYMAP_I


Includes/devices/prtgfx.i

    IFND	DEVICES_PRTGFX_I
DEVICES_PRTGFX_I	SET	1
**
**	$Filename: devices/prtgfx.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.12 $
**	$Date: 90/07/26 $
**
**	printer.device structure definitions
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND  EXEC_TYPES_I
    INCLUDE  "exec/types.i"
    ENDC

PCMYELLOW	EQU	0		; byte index for yellow
PCMMAGENTA	EQU	1		; byte index for magenta
PCMCYAN		EQU	2		; byte index for cyan
PCMBLACK	EQU	3		; byte index for black
PCMBLUE		EQU	PCMYELLOW	; byte index for blue
PCMGREEN	EQU	PCMMAGENTA	; byte index for green
PCMRED		EQU	PCMCYAN		; byte index for red
PCMWHITE	EQU	PCMBLACK	; byte index for white

    STRUCTURE	colorEntry,0
        LABEL	colorLong	; quick access to all of YMCB
        LABEL	colorSByte	; 1 entry for each of YMCB
        STRUCT	colorByte,4	; ditto (except signed)
        LABEL	ce_SIZEOF

    STRUCTURE	PrtInfo,0
        APTR	pi_render	; PRIVATE - DO NOT USE!
        APTR	pi_rp		; PRIVATE - DO NOT USE!
        APTR	pi_temprp	; PRIVATE - DO NOT USE!
        APTR	pi_RowBuf	; PRIVATE - DO NOT USE!
        APTR	pi_HamBuf	; PRIVATE - DO NOT USE!
        APTR	pi_ColorMap	; PRIVATE - DO NOT USE!
        APTR	pi_ColorInt	; color intensities for entire row
        APTR	pi_HamInt	; PRIVATE - DO NOT USE!
        APTR	pi_Dest1Int	; PRIVATE - DO NOT USE!
        APTR	pi_Dest2Int	; PRIVATE - DO NOT USE!
        APTR	pi_ScaleX	; array of scale values for X
        APTR	pi_ScaleXAlt	; PRIVATE - DO NOT USE!
        APTR	pi_dmatrix	; pointer to dither matrix
        APTR	pi_TopBuf	; PRIVATE - DO NOT USE!
        APTR	pi_BotBuf	; PRIVATE - DO NOT USE!

        UWORD	pi_RowBufSize	; PRIVATE - DO NOT USE!
        UWORD	pi_HamBufSize	; PRIVATE - DO NOT USE!
        UWORD	pi_ColorMapSize	; PRIVATE - DO NOT USE!
        UWORD	pi_ColorIntSize	; PRIVATE - DO NOT USE!
        UWORD	pi_HamIntSize	; PRIVATE - DO NOT USE!
        UWORD	pi_Dest1IntSize	; PRIVATE - DO NOT USE!
        UWORD	pi_Dest2IntSize	; PRIVATE - DO NOT USE!
        UWORD	pi_ScaleXSize	; PRIVATE - DO NOT USE!
        UWORD	pi_ScaleXAltSize ; PRIVATE - DO NOT USE!

        UWORD	pi_PrefsFlags	; PRIVATE - DO NOT USE!
        ULONG	pi_special	; PRIVATE - DO NOT USE!
        UWORD	pi_xstart	; PRIVATE - DO NOT USE!
        UWORD	pi_ystart	; PRIVATE - DO NOT USE!
        UWORD	pi_width	; source width (in pixels)
        UWORD	pi_height	; PRIVATE - DO NOT USE!
        ULONG	pi_pc		; PRIVATE - DO NOT USE!
        ULONG	pi_pr		; PRIVATE - DO NOT USE!
        UWORD	pi_ymult	; PRIVATE - DO NOT USE!
        UWORD	pi_ymod		; PRIVATE - DO NOT USE!
        UWORD	pi_ety		; PRIVATE - DO NOT USE!
        UWORD	pi_xpos		; offset to start printing from
        UWORD	pi_threshold	; copy of threshold value (from prefs)
        UWORD	pi_tempwidth	; PRIVATE - DO NOT USE!
        UWORD	pi_flags	; PRIVATE - DO NOT USE!
        LABEL	prtinfo_SIZEOF

    ENDC	; DEVICES_PRTGFX_I


Includes/devices/bootblock.h

#ifndef DEVICES_BOOTBLOCK_H
#define DEVICES_BOOTBLOCK_H
/*
**	$Filename: devices/bootblock.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.6 $
**	$Date: 90/11/05 $
**
**	floppy BootBlock definition
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include	"exec/types.h"
#endif

struct BootBlock {
    UBYTE	bb_id[4];		/* 4 character identifier */
    LONG	bb_chksum;		/* boot block checksum (balance) */
    LONG	bb_dosblock;		/* reserved for DOS patch */
};

#define		BOOTSECTS	2	/* 1K bootstrap */

#define BBID_DOS	{ 'D', 'O', 'S', '\0' }
#define BBID_KICK	{ 'K', 'I', 'C', 'K' }

#define BBNAME_DOS	0x444F5300	/* 'DOS\0' */
#define BBNAME_KICK	0x4B49434B	/* 'KICK' */

#endif	/* DEVICES_BOOTBLOCK_H */


Includes/devices/hardblocks.h

#ifndef	DEVICES_HARDBLOCKS_H
#define	DEVICES_HARDBLOCKS_H
/*
**	$Filename: devices/hardblocks.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.3 $
**	$Date: 91/08/23 $
**
**	File System identifier blocks for hard disks
**
**	(C) Copyright 1988-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include "exec/types.h"
#endif /* EXEC_TYPES_H */

/*--------------------------------------------------------------------
 *
 *	This file describes blocks of data that exist on a hard disk
 *	to describe that disk.	They are not generically accessable to
 *	the user as they do not appear on any DOS drive.  The blocks
 *	are tagged with a unique identifier, checksummed, and linked
 *	together.  The root of these blocks is the RigidDiskBlock.
 *
 *	The RigidDiskBlock must exist on the disk within the first
 *	RDB_LOCATION_LIMIT blocks.  This inhibits the use of the zero
 *	cylinder in an AmigaDOS partition: although it is strictly
 *	possible to store the RigidDiskBlock data in the reserved
 *	area of a partition, this practice is discouraged since the
 *	reserved blocks of a partition are overwritten by "Format",
 *	"Install", "DiskCopy", etc.  The recommended disk layout,
 *	then, is to use the first cylinder(s) to store all the drive
 *	data specified by these blocks: i.e. partition descriptions,
 *	file system load images, drive bad block maps, spare blocks,
 *	etc.
 *
 *	Though only 512 byte blocks are currently supported by the
 *	file system, this proposal tries to be forward-looking by
 *	making the block size explicit, and by using only the first
 *	256 bytes for all blocks but the LoadSeg data.
 *
 *------------------------------------------------------------------*/

/*
 *  NOTE
 *	optional block addresses below contain $ffffffff to indicate
 *	a NULL address, as zero is a valid address
 */
struct RigidDiskBlock {
    ULONG   rdb_ID;		/* 4 character identifier */
    ULONG   rdb_SummedLongs;	/* size of this checksummed structure */
    LONG    rdb_ChkSum;		/* block checksum (longword sum to zero) */
    ULONG   rdb_HostID;		/* SCSI Target ID of host */
    ULONG   rdb_BlockBytes;	/* size of disk blocks */
    ULONG   rdb_Flags;		/* see below for defines */
    /* block list heads */
    ULONG   rdb_BadBlockList;	/* optional bad block list */
    ULONG   rdb_PartitionList;	/* optional first partition block */
    ULONG   rdb_FileSysHeaderList; /* optional file system header block */
    ULONG   rdb_DriveInit;	/* optional drive-specific init code */
                /* DriveInit(lun,rdb,ior): "C" stk & d0/a0/a1 */
    ULONG   rdb_Reserved1[6];	/* set to $ffffffff */
    /* physical drive characteristics */
    ULONG   rdb_Cylinders;	/* number of drive cylinders */
    ULONG   rdb_Sectors;	/* sectors per track */
    ULONG   rdb_Heads;		/* number of drive heads */
    ULONG   rdb_Interleave;	/* interleave */
    ULONG   rdb_Park;		/* landing zone cylinder */
    ULONG   rdb_Reserved2[3];
    ULONG   rdb_WritePreComp;	/* starting cylinder: write precompensation */
    ULONG   rdb_ReducedWrite;	/* starting cylinder: reduced write current */
    ULONG   rdb_StepRate;	/* drive step rate */
    ULONG   rdb_Reserved3[5];
    /* logical drive characteristics */
    ULONG   rdb_RDBBlocksLo;	/* low block of range reserved for hardblocks */
    ULONG   rdb_RDBBlocksHi;	/* high block of range for these hardblocks */
    ULONG   rdb_LoCylinder;	/* low cylinder of partitionable disk area */
    ULONG   rdb_HiCylinder;	/* high cylinder of partitionable data area */
    ULONG   rdb_CylBlocks;	/* number of blocks available per cylinder */
    ULONG   rdb_AutoParkSeconds; /* zero for no auto park */
    ULONG   rdb_HighRDSKBlock;	/* highest block used by RDSK */
                /* (not including replacement bad blocks) */
    ULONG   rdb_Reserved4;
    /* drive identification */
    char    rdb_DiskVendor[8];
    char    rdb_DiskProduct[16];
    char    rdb_DiskRevision[4];
    char    rdb_ControllerVendor[8];
    char    rdb_ControllerProduct[16];
    char    rdb_ControllerRevision[4];
    ULONG   rdb_Reserved5[10];
};

#define	IDNAME_RIGIDDISK	0x5244534B	/* 'RDSK' */

#define	RDB_LOCATION_LIMIT	16

#define	RDBFB_LAST	0	/* no disks exist to be configured after */
#define	RDBFF_LAST	0x01L	/*   this one on this controller */
#define	RDBFB_LASTLUN	1	/* no LUNs exist to be configured greater */
#define	RDBFF_LASTLUN	0x02L	/*   than this one at this SCSI Target ID */
#define	RDBFB_LASTTID	2	/* no Target IDs exist to be configured */
#define	RDBFF_LASTTID	0x04L	/*   greater than this one on this SCSI bus */
#define	RDBFB_NORESELECT 3	/* don't bother trying to perform reselection */
#define	RDBFF_NORESELECT 0x08L	/*   when talking to this drive */
#define	RDBFB_DISKID	4	/* rdb_Disk... identification valid */
#define	RDBFF_DISKID	0x10L
#define	RDBFB_CTRLRID	5	/* rdb_Controller... identification valid */
#define	RDBFF_CTRLRID	0x20L
                /* added 7/20/89 by commodore: */
#define RDBFB_SYNCH	6	/* drive supports scsi synchronous mode */
#define RDBFF_SYNCH	0x40L	/* CAN BE DANGEROUS TO USE IF IT DOESN'T! */

/*------------------------------------------------------------------*/
struct BadBlockEntry {
    ULONG   bbe_BadBlock;	/* block number of bad block */
    ULONG   bbe_GoodBlock;	/* block number of replacement block */
};

struct BadBlockBlock {
    ULONG   bbb_ID;		/* 4 character identifier */
    ULONG   bbb_SummedLongs;	/* size of this checksummed structure */
    LONG    bbb_ChkSum;		/* block checksum (longword sum to zero) */
    ULONG   bbb_HostID;		/* SCSI Target ID of host */
    ULONG   bbb_Next;		/* block number of the next BadBlockBlock */
    ULONG   bbb_Reserved;
    struct BadBlockEntry bbb_BlockPairs[61]; /* bad block entry pairs */
    /* note [61] assumes 512 byte blocks */
};

#define	IDNAME_BADBLOCK		0x42414442	/* 'BADB' */

/*------------------------------------------------------------------*/
struct PartitionBlock {
    ULONG   pb_ID;		/* 4 character identifier */
    ULONG   pb_SummedLongs;	/* size of this checksummed structure */
    LONG    pb_ChkSum;		/* block checksum (longword sum to zero) */
    ULONG   pb_HostID;		/* SCSI Target ID of host */
    ULONG   pb_Next;		/* block number of the next PartitionBlock */
    ULONG   pb_Flags;		/* see below for defines */
    ULONG   pb_Reserved1[2];
    ULONG   pb_DevFlags;	/* preferred flags for OpenDevice */
    UBYTE   pb_DriveName[32];	/* preferred DOS device name: BSTR form */
                /* (not used if this name is in use) */
    ULONG   pb_Reserved2[15];	/* filler to 32 longwords */
    ULONG   pb_Environment[17];	/* environment vector for this partition */
    ULONG   pb_EReserved[15];	/* reserved for future environment vector */
};

#define	IDNAME_PARTITION	0x50415254	/* 'PART' */

#define	PBFB_BOOTABLE	0	/* this partition is intended to be bootable */
#define	PBFF_BOOTABLE	1L	/*   (expected directories and files exist) */
#define	PBFB_NOMOUNT	1	/* do not mount this partition (e.g. manually */
#define	PBFF_NOMOUNT	2L	/*   mounted, but space reserved here) */

/*------------------------------------------------------------------*/
struct FileSysHeaderBlock {
    ULONG   fhb_ID;		/* 4 character identifier */
    ULONG   fhb_SummedLongs;	/* size of this checksummed structure */
    LONG    fhb_ChkSum;		/* block checksum (longword sum to zero) */
    ULONG   fhb_HostID;		/* SCSI Target ID of host */
    ULONG   fhb_Next;		/* block number of next FileSysHeaderBlock */
    ULONG   fhb_Flags;		/* see below for defines */
    ULONG   fhb_Reserved1[2];
    ULONG   fhb_DosType;	/* file system description: match this with */
                /* partition environment's DE_DOSTYPE entry */
    ULONG   fhb_Version;	/* release version of this code */
    ULONG   fhb_PatchFlags;	/* bits set for those of the following that */
                /*   need to be substituted into a standard */
                /*   device node for this file system: e.g. */
                /*   0x180 to substitute SegList & GlobalVec */
    ULONG   fhb_Type;		/* device node type: zero */
    ULONG   fhb_Task;		/* standard dos "task" field: zero */
    ULONG   fhb_Lock;		/* not used for devices: zero */
    ULONG   fhb_Handler;	/* filename to loadseg: zero placeholder */
    ULONG   fhb_StackSize;	/* stacksize to use when starting task */
    LONG    fhb_Priority;	/* task priority when starting task */
    LONG    fhb_Startup;	/* startup msg: zero placeholder */
    LONG    fhb_SegListBlocks;	/* first of linked list of LoadSegBlocks: */
                /*   note that this entry requires some */
                /*   processing before substitution */
    LONG    fhb_GlobalVec;	/* BCPL global vector when starting task */
    ULONG   fhb_Reserved2[23];	/* (those reserved by PatchFlags) */
    ULONG   fhb_Reserved3[21];
};

#define	IDNAME_FILESYSHEADER	0x46534844	/* 'FSHD' */

/*------------------------------------------------------------------*/
struct LoadSegBlock {
    ULONG   lsb_ID;		/* 4 character identifier */
    ULONG   lsb_SummedLongs;	/* size of this checksummed structure */
    LONG    lsb_ChkSum;		/* block checksum (longword sum to zero) */
    ULONG   lsb_HostID;		/* SCSI Target ID of host */
    ULONG   lsb_Next;		/* block number of the next LoadSegBlock */
    ULONG   lsb_LoadData[123];	/* data for "loadseg" */
    /* note [123] assumes 512 byte blocks */
};

#define	IDNAME_LOADSEG		0x4C534547	/* 'LSEG' */

#endif	/* DEVICES_HARDBLOCKS_H */


Includes/devices/narrator.h

#ifndef DEVICES_NARRATOR_H
#define DEVICES_NARRATOR_H
/*
**	$Filename: devices/narrator.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.7 $
**	$Date: 91/03/12 $
**
**	V37 Narrator device C language include file
**
**	Copyright 1990, 1991 Joseph Katz/Mark Barton.
**	All rights reserved.
**
**	This include file (narrator.h) may be freely distributed
**	as long as the above copyright notice remains intact.
**
*/

#ifndef EXEC_IO_H
#include "exec/io.h"
#endif

        /*	    Device Options	*/

#define NDB_NEWIORB	0	/* Use new extended IORB		*/
#define NDB_WORDSYNC	1	/* Generate word sync messages		*/
#define NDB_SYLSYNC	2	/* Generate syllable sync messages	*/

#define NDF_NEWIORB	(1 << NDB_NEWIORB)
#define NDF_WORDSYNC	(1 << NDB_WORDSYNC)
#define NDF_SYLSYNC	(1 << NDB_SYLSYNC)

        /*	    Error Codes		*/

#define ND_NoMem	-2	/* Can't allocate memory		*/
#define ND_NoAudLib	-3	/* Can't open audio device		*/
#define ND_MakeBad	-4	/* Error in MakeLibrary call		*/
#define ND_UnitErr	-5	/* Unit other than 0			*/
#define ND_CantAlloc	-6	/* Can't allocate audio channel(s)	*/
#define ND_Unimpl	-7	/* Unimplemented command		*/
#define ND_NoWrite	-8	/* Read for mouth without write first	*/
#define ND_Expunged	-9	/* Can't open, deferred expunge bit set	*/
#define ND_PhonErr     -20	/* Phoneme code spelling error			*/
#define ND_RateErr     -21	/* Rate out of bounds			*/
#define ND_PitchErr    -22	/* Pitch out of bounds				*/
#define ND_SexErr      -23	/* Sex not valid			*/
#define ND_ModeErr     -24	/* Mode not valid			*/
#define ND_FreqErr     -25	/* Sampling frequency out of bounds	*/
#define ND_VolErr      -26	/* Volume out of bounds		*/
#define ND_DCentErr    -27	/* Degree of centralization out of bounds */
#define ND_CentPhonErr -28	/* Invalid central phon			*/

        /* Input parameters and defaults */

#define DEFPITCH    110		/* Default pitch			*/
#define DEFRATE     150		/* Default speaking rate (wpm)			*/
#define DEFVOL	    64		/* Default volume (full)		*/
#define DEFFREQ     22200	/* Default sampling frequency (Hz)	*/
#define MALE	    0		/* Male vocal tract			*/
#define FEMALE	    1		/* Female vocal tract			*/
#define NATURALF0   0		/* Natural pitch contours		*/
#define ROBOTICF0   1		/* Monotone pitch			*/
#define MANUALF0    2		/* Manual setting of pitch contours	*/
#define DEFSEX	    MALE	/* Default sex					*/
#define DEFMODE     NATURALF0	/* Default mode			*/
#define	DEFARTIC    100		/* 100% articulation (normal)		*/
#define DEFCENTRAL  0		/* No centralization			*/
#define DEFF0PERT   0		/* No F0 Perturbation			*/
#define DEFF0ENTHUS 32		/* Default F0 enthusiasm (in 32nds)	*/
#define DEFPRIORITY 100		/* Default speaking priority		*/

            /*	Parameter bounds	*/

#define MINRATE     40		/* Minimum speaking rate		*/
#define MAXRATE     400		/* Maximum speaking rate		*/
#define MINPITCH    65		/* Minimum pitch			*/
#define MAXPITCH    320		/* Maximum pitch			*/
#define MINFREQ     5000	/* Minimum sampling frequency		*/
#define MAXFREQ     28000	/* Maximum sampling frequency		*/
#define MINVOL	    0		/* Minimum volume			*/
#define MAXVOL	    64		/* Maximum volume			*/
#define MINCENT      0		/* Minimum degree of centralization	*/
#define MAXCENT    100		/* Maximum degree of centralization	*/

        /*    Standard Write request	*/

struct narrator_rb {
    struct IOStdReq  message;	/* Standard IORB		*/
    UWORD	rate;			/* Speaking rate (words/minute) */
    UWORD	pitch;			/* Baseline pitch in Hertz		*/
    UWORD	mode;			/* Pitch mode			*/
    UWORD	sex;			/* Sex of voice			*/
    UBYTE	*ch_masks;		/* Pointer to audio alloc maps	*/
    UWORD	nm_masks;		/* Number of audio alloc maps	*/
    UWORD	volume;			/* Volume. 0 (off) thru 64	*/
    UWORD	sampfreq;		/* Audio sampling freq			*/
    UBYTE	mouths;			/* If non-zero, generate mouths */
    UBYTE	chanmask;		/* Which ch mask used (internal)*/
    UBYTE	numchan;		/* Num ch masks used (internal) */
    UBYTE	flags;			/* New feature flags		*/
    UBYTE	F0enthusiasm;		/* F0 excursion factor		*/
    UBYTE	F0perturb;		/* Amount of F0 perturbation	*/
    BYTE	F1adj;			/* F1 adjustment in ±5% steps	*/
    BYTE	F2adj;				/* F2 adjustment in ±5% steps	*/
    BYTE	F3adj;			/* F3 adjustment in ±5% steps	*/
    BYTE	A1adj;			/* A1 adjustment in decibels	*/
    BYTE	A2adj;			/* A2 adjustment in decibels	*/
    BYTE	A3adj;			/* A3 adjustment in decibels	*/
    UBYTE	articulate;		/* Transition time multiplier	*/
    UBYTE	centralize;		/* Degree of vowel centralization */
    char	*centphon;		/* Pointer to central ASCII phon  */
    BYTE	AVbias;			/* AV bias			*/
    BYTE	AFbias;			/* AF bias			*/
    BYTE	priority;		/* Priority while speaking	*/
    BYTE	pad1;			/* For alignment		*/
    };

        /*    Standard Read request	*/

struct mouth_rb {
    struct	narrator_rb voice;	/* Speech IORB			*/
    UBYTE	width;			/* Width (returned value)	*/
    UBYTE	height;			/* Height (returned value)	*/
    UBYTE	shape;			/* Internal use, do not modify	*/
    UBYTE	sync;			/* Returned sync events		*/
    };

#endif	/* DEVICES_NARRATOR_H */


Includes/devices/scsidisk.h

#ifndef	DEVICES_SCSIDISK_H
#define	DEVICES_SCSIDISK_H
/*
**	$Filename: devices/scsidisk.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.2 $
**	$Date: 90/11/07 $
**
**	SCSI exec-level device command
**
**	(C) Copyright 1988-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include "exec/types.h"
#endif /* EXEC_TYPES_H */

/*--------------------------------------------------------------------
 *
 *   SCSI Command
 *	Several Amiga SCSI controller manufacturers are converging on
 *	standard ways to talk to their controllers.  This include
 *	file describes an exec-device command (e.g. for hddisk.device)
 *	that can be used to issue SCSI commands
 *
 *   UNIT NUMBERS
 *	Unit numbers to the OpenDevice call have encoded in them which
 *	SCSI device is being referred to.  The three decimal digits of
 *	the unit number refer to the SCSI Target ID (bus address) in
 *	the 1's digit, the SCSI logical unit (LUN) in the 10's digit,
 *	and the controller board in the 100's digit.
 *
 *	Examples:
 *		  0	drive at address 0
 *		 12	LUN 1 on multiple drive controller at address 2
 *		104	second controller board, address 4
 *		 88	not valid: both logical units and addresses
 *			range from 0..7.
 *
 *   CAVEATS
 *	Original 2090 code did not support this command.
 *
 *	Commodore 2090/2090A unit numbers are different.  The SCSI
 *	logical unit is the 100's digit, and the SCSI Target ID
 *	is a permuted 1's digit: Target ID 0..6 maps to unit 3..9
 *	(7 is reserved for the controller).
 *
 *	    Examples:
 *		  3	drive at address 0
 *		109	drive at address 6, logical unit 1
 *		  1	not valid: this is not a SCSI unit.  Perhaps
 *			it's an ST506 unit.
 *
 *	Some controller boards generate a unique name (e.g. 2090A's
 *	iddisk.device) for the second controller board, instead of
 *	implementing the 100's digit.
 *
 *	There are optional restrictions on the alignment, bus
 *	accessability, and size of the data for the data phase.
 *	Be conservative to work with all manufacturer's controllers.
 *
 *------------------------------------------------------------------*/

#define	HD_SCSICMD	28	/* issue a SCSI command to the unit */
                /* io_Data points to a SCSICmd */
                /* io_Length is sizeof(struct SCSICmd) */
                /* io_Actual and io_Offset are not used */

struct SCSICmd {
    UWORD  *scsi_Data;		/* word aligned data for SCSI Data Phase */
                /* (optional) data need not be byte aligned */
                /* (optional) data need not be bus accessable */
    ULONG   scsi_Length;	/* even length of Data area */
                /* (optional) data can have odd length */
                /* (optional) data length can be > 2**24 */
    ULONG   scsi_Actual;	/* actual Data used */
    UBYTE  *scsi_Command;	/* SCSI Command (same options as scsi_Data) */
    UWORD   scsi_CmdLength;	/* length of Command */
    UWORD   scsi_CmdActual;	/* actual Command used */
    UBYTE   scsi_Flags;		/* includes intended data direction */
    UBYTE   scsi_Status;	/* SCSI status of command */
    UBYTE  *scsi_SenseData;	/* sense data: filled if SCSIF_[OLD]AUTOSENSE */
                /* is set and scsi_Status has CHECK CONDITION */
                /* (bit 1) set */
    UWORD   scsi_SenseLength;	/* size of scsi_SenseData, also bytes to */
                /* request w/ SCSIF_AUTOSENSE, must be 4..255 */
    UWORD   scsi_SenseActual;	/* amount actually fetched (0 means no sense) */
};

/*----- scsi_Flags -----*/
#define	SCSIF_WRITE		0	/* intended data direction is out */
#define	SCSIF_READ		1	/* intended data direction is in */
#define	SCSIB_READ_WRITE	0	/* (the bit to test) */

#define	SCSIF_NOSENSE		0	/* no automatic request sense */
#define	SCSIF_AUTOSENSE		2	/* do standard extended request sense */
                    /* on check condition */
#define	SCSIF_OLDAUTOSENSE	6	/* do 4 byte non-extended request */
                    /* sense on check condition */
#define	SCSIB_AUTOSENSE		1	/* (the bit to test) */
#define	SCSIB_OLDAUTOSENSE	2	/* (the bit to test) */

/*----- SCSI io_Error values -----*/
#define	HFERR_SelfUnit		40	/* cannot issue SCSI command to self */
#define	HFERR_DMA		41	/* DMA error */
#define	HFERR_Phase		42	/* illegal or unexpected SCSI phase */
#define	HFERR_Parity		43	/* SCSI parity error */
#define	HFERR_SelTimeout	44	/* Select timed out */
#define	HFERR_BadStatus		45	/* status and/or sense error */

/*----- OpenDevice io_Error values -----*/
#define	HFERR_NoBoard		50	/* Open failed for non-existant board */

#endif	/* DEVICES_SCSIDISK_H */


Includes/devices/bootblock.i

    IFND	DEVICES_BOOTBLOCK_I
DEVICES_BOOTBLOCK_I	SET	1
**
**	$Filename: devices/bootblock.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.6 $
**	$Date: 90/11/05 $
**
**	floppy BootBlock definition
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND	EXEC_TYPES_I
    INCLUDE	"exec/types.i"
    ENDC

 STRUCTURE BB,0
    STRUCT	BB_ID,4			; 4 character identifier
    LONG	BB_CHKSUM		; boot block checksum (balance)
    LONG	BB_DOSBLOCK		; reserved for DOS patch
    LABEL	BB_ENTRY		; bootstrap entry point
    LABEL	BB_SIZE

BOOTSECTS	EQU	2		; 1K bootstrap

BBID_DOS	macro			; something that is bootable
        dc.b	'DOS',0
        endm

BBID_KICK	macro			; firmware image disk
        dc.b	'KICK'
        endm

BBNAME_DOS	EQU	$444F5300	; 'DOS\0'
BBNAME_KICK	EQU	$4B49434B	; 'KICK'

    ENDC	; DEVICES_BOOTBLOCK_I


Includes/devices/hardblocks.i

    IFND	DEVICES_HARDBLOCKS_I
DEVICES_HARDBLOCKS_I	SET	1
**
**	$Filename: devices/hardblocks.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.3 $
**	$Date: 91/08/23 $
**
**	File System identifier blocks for hard disks
**
**	(C) Copyright 1988-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND	EXEC_TYPES_I
    INCLUDE	"exec/types.i"
    ENDC

;---------------------------------------------------------------------
;
;	This file describes blocks of data that exist on a hard disk
;	to describe that disk.	They are not generically accessable to
;	the user as they do not appear on any DOS drive.  The blocks
;	are tagged with a unique identifier, checksummed, and linked
;	together.  The root of these blocks is the RigidDiskBlock.
;
;	The RigidDiskBlock must exist on the disk within the first
;	RDB_LOCATION_LIMIT blocks.  This inhibits the use of the zero
;	cylinder in an AmigaDOS partition: although it is strictly
;	possible to store the RigidDiskBlock data in the reserved
;	area of a partition, this practice is discouraged since the
;	reserved blocks of a partition are overwritten by "Format",
;	"Install", "DiskCopy", etc.  The recommended disk layout,
;	then, is to use the first cylinder(s) to store all the drive
;	data specified by these blocks: i.e. partition descriptions,
;	file system load images, drive bad block maps, spare blocks,
;	etc.
;
;	Though only 512 byte blocks are currently supported by the
;	file system, this proposal tries to be forward-looking by
;	making the block size explicit, and by using only the first
;	256 bytes for all blocks but the LoadSeg data.
;
;---------------------------------------------------------------------

;
;   NOTE
;	optional block addresses below contain $ffffffff to indicate
;	a NULL address
;
 STRUCTURE	RigidDiskBlock,0
    ULONG   rdb_ID		; 4 character identifier
    ULONG   rdb_SummedLongs	; size of this checksummed structure
    LONG    rdb_ChkSum		; block checksum (longword sum to zero)
    ULONG   rdb_HostID		; SCSI Target ID of host
    ULONG   rdb_BlockBytes	; size of disk blocks
    ULONG   rdb_Flags		; see below for defines
    ; block list heads
    ULONG   rdb_BadBlockList	; optional bad block list
    ULONG   rdb_PartitionList	; optional first partition block
    ULONG   rdb_FileSysHeaderList ; optional fule system header block
    ULONG   rdb_DriveInit	; optional drive-specific init code
                ; DriveInit(lun,rdb,ior): "C" stk & d0/a0/a1
    STRUCT  rdb_Reserved1,6*4	; set to $ffffffff
    ; physical drive characteristics
    ULONG   rdb_Cylinders	; number of drive cylinders
    ULONG   rdb_Sectors		; sectors per track
    ULONG   rdb_Heads		; number of drive heads
    ULONG   rdb_Interleave	; interleave
    ULONG   rdb_Park		; landing zone cylinder
    STRUCT  rdb_Reserved2,3*4
    ULONG   rdb_WritePreComp	; starting cylinder: write precompensation
    ULONG   rdb_ReducedWrite	; starting cylinder: reduced write current
    ULONG   rdb_StepRate	; drive step rate
    STRUCT  rdb_Reserved3,5*4
    ; logical drive characteristics
    ULONG   rdb_RDBBlocksLo	; low block of range reserved for hardblocks
    ULONG   rdb_RDBBlocksHi	; high block of range for these hardblocks
    ULONG   rdb_LoCylinder	; low cylinder of partitionable disk area
    ULONG   rdb_HiCylinder	; high cylinder of partitionable data area
    ULONG   rdb_CylBlocks	; number of blocks available per cylinder
    ULONG   rdb_AutoParkSeconds	; zero for no auto park
    ULONG   rdb_HighRDSKBlock	; highest block used by RDSK
                ; (not including replacement bad blocks)
    STRUCT  rdb_Reserved4,1*4
    ; drive identification
    STRUCT  rdb_DiskVendor,8
    STRUCT  rdb_DiskProduct,16
    STRUCT  rdb_DiskRevision,4
    STRUCT  rdb_ControllerVendor,8
    STRUCT  rdb_ControllerProduct,16
    STRUCT  rdb_ControllerRevision,4
    STRUCT  rdb_Reserved5,10*4

    LABEL   RigidDiskBlock_SIZEOF

IDNAME_RIGIDDISK	EQU	(('R'<<24)!('D'<<16)!('S'<<8)!('K'))

RDB_LOCATION_LIMIT	EQU	16

    BITDEF  RDBF,LAST,0		; no disks exist to be configured after
                ;   this one on this controller
    BITDEF  RDBF,LASTLUN,1	; no LUNs exist to be configured greater
                ;   than this one at this SCSI Target ID
    BITDEF  RDBF,LASTTID,2	; no Target IDs exist to be configured
                ;   greater than this one on this SCSI bus
    BITDEF  RDBF,NORESELECT,3	; don't bother trying to perform reselection
                ;   when talking to this drive
    BITDEF  RDBF,DISKID,4	; rdb_Disk... identification valid
    BITDEF  RDBF,CTRLRID,5	; rdb_Controller... identification valid
                ; added 7/20/89 by commodore:
    BITDEF  RDBF,SYNCH,6	; drive supports scsi synchronous mode
                ; CAN BE DANGEROUS TO USE IF IT DOESN'T!

;---------------------------------------------------------------------
 STRUCTURE	BadBlockEntry,0
    ULONG   bbe_BadBlock	; block number of bad block
    ULONG   bbe_GoodBlock	; block number of replacement block
    LABEL   BadBlockEntry_SIZEOF

 STRUCTURE	BadBlockBlock,0
    ULONG   bbb_ID		; 4 character identifier
    ULONG   bbb_SummedLongs	; size of this checksummed structure
    LONG    bbb_ChkSum		; block checksum (longword sum to zero)
    ULONG   bbb_HostID		; SCSI Target ID of host
    ULONG   bbb_Next		; block number of the next BadBlockBlock
    ULONG   bbb_Reserved
    STRUCT  bbb_BlockPairs,61*BadBlockEntry_SIZEOF ; bad block entry pairs
    ; note 61 assumes 512 byte blocks
    ; there is no BadBlockBlock_SIZEOF: try rdb_BlockBytes

IDNAME_BADBLOCK		EQU	(('B'<<24)!('A'<<16)!('D'<<8)!('B'))

;---------------------------------------------------------------------
 STRUCTURE	PartitionBlock,0
    ULONG   pb_ID		; 4 character identifier
    ULONG   pb_SummedLongs	; size of this checksummed structure
    LONG    pb_ChkSum		; block checksum (longword sum to zero)
    ULONG   pb_HostID		; SCSI Target ID of host
    ULONG   pb_Next		; block number of the next PartitionBlock
    ULONG   pb_Flags		; see below for defines
    STRUCT  pb_Reserved1,2*4
    ULONG   pb_DevFlags		; preferred flags for OpenDevice
    STRUCT  pb_DriveName,32	; preferred DOS device name: BSTR form
                ; (not used if this name is in use)
    STRUCT  pb_Reserved2,15*4	; filler to 32 longwords
    STRUCT  pb_Environment,17*4	; environment vector for this partition
    STRUCT  pb_EReserved,15*4	; reserved for future environment vector
    LABEL   PartitionBlock_SIZEOF

IDNAME_PARTITION	EQU	(('P'<<24)!('A'<<16)!('R'<<8)!('T'))

    BITDEF  PBF,BOOTABLE,0	; this partition is intended to be bootable
                ;   (expected directories and files exist)
    BITDEF  PBF,NOMOUNT,1	; do not mount this partition (e.g. manually
                ;   mounted, but space reserved here)

;---------------------------------------------------------------------
 STRUCTURE	FileSysHeaderBlock,0
    ULONG   fhb_ID		; 4 character identifier
    ULONG   fhb_SummedLongs	; size of this checksummed structure
    LONG    fhb_ChkSum		; block checksum (longword sum to zero)
    ULONG   fhb_HostID		; SCSI Target ID of host
    ULONG   fhb_Next		; block number of the next FileSysHeaderBlock
    ULONG   fhb_Flags		; see below for defines
    STRUCT  fhb_Reserved1,2*4
    ULONG   fhb_DosType		; file system description: match this with
                ; partition environment's DE_DOSTYPE entry
    ULONG   fhb_Version		; release version of this code
    ULONG   fhb_PatchFlags	; bits set for those of the following that
                ;   need to be substituted into a standard
                ;   device node for this file system: e.g.
                ;   $180 to substitute SegList & GlobalVec
    ULONG   fhb_Type		; device node type: zero
    ULONG   fhb_Task		; standard dos "task" field: zero
    ULONG   fhb_Lock		; not used for devices: zero
    ULONG   fhb_Handler		; filename to loadseg: zero placeholder
    ULONG   fhb_StackSize	; stacksize to use when starting task
    LONG    fhb_Priority	; task priority when starting task
    LONG    fhb_Startup		; startup msg: zero placeholder
    LONG    fhb_SegListBlocks	; first of linked list of LoadSegBlocks:
                ;   note that this entry requires some
                ;   processing before substitution
    LONG    fhb_GlobalVec	; BCPL global vector when starting task
    STRUCT  fhb_Reserved2,23*4	; (those reserved by PatchFlags)
    STRUCT  fhb_Reserved3,21*4
    LABEL   FileSysHeader_SIZEOF

IDNAME_FILESYSHEADER	EQU	(('F'<<24)!('S'<<16)!('H'<<8)!('D'))

;---------------------------------------------------------------------
 STRUCTURE	LoadSegBlock,0
    ULONG   lsb_ID		; 4 character identifier
    ULONG   lsb_SummedLongs	; size of this checksummed structure
    LONG    lsb_ChkSum		; block checksum (longword sum to zero)
    ULONG   lsb_HostID		; SCSI Target ID of host
    ULONG   lsb_Next		; block number of the next FileSysBlock
    STRUCT  lsb_LoadData,123*4	; data for "loadseg"
    ; note 123 assumes 512 byte blocks
    ; there is no LoadSegBlock_SIZEOF: try rdb_BlockBytes

IDNAME_LOADSEG		EQU	(('L'<<24)!('S'<<16)!('E'<<8)!('G'))

    ENDC


Includes/devices/narrator.i

    IFND DEVICES_NARRATOR_I
DEVICES_NARRATOR_I	SET 1
**
**	$Filename: devices/narrator.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.7 $
**	$Date: 91/03/12 $
**
**	V37 Narrator device ASM include file
**
**	Copyright 1990, 1991 Joseph Katz/Mark Barton.
**	All rights reserved.
**
**	This include file (narrator.i) may be freely distributed
**	as long as the above copyright notice remains intact.
**

    IFND	EXEC_IO_I
    INCLUDE "exec/io.i"
    ENDC

*		;------	Default values, user parms, and general constants

DEFPITCH	EQU	110		;DEFAULT PITCH
DEFRATE	EQU	150		;DEFAULT RATE
DEFVOL		EQU	64		;DEFAULT VOLUME (FULL)
DEFFREQ	EQU	22200		;DEFAULT SAMPLING FREQUENCY
NATURALF0	EQU	0		;NATURAL F0 CONTOURS
ROBOTICF0	EQU	1		;MONOTONE PITCH
MANUALF0	EQU	2		;MANUAL SETTING OF PITCH
MALE		EQU	0		;MALE SPEAKER
FEMALE		EQU	1		;FEMALE SPEAKER
DEFSEX		EQU	MALE		;DEFAULT SEX
DEFMODE	EQU	NATURALF0	;DEFAULT MODE
DEFARTIC	EQU	100		;DEFAULT ARTICULATION 100%
DEFCENTRAL	EQU	0		;DEFAULT PERCENTAGE OF CENTRALIZATION=0
DEFF0PERT	EQU	0		;DEFAULT F0 PERTURBATION
DEFF0ENTHUS	EQU	32		;DEFAULT F0 ENTHUSIASM (in 32nds)
DEFPRIORITY	EQU	100		;DEFAULT SPEAKING PRIORITY

*		;------	Parameter bounds

MINRATE	EQU	 40		;MINIMUM SPEAKING RATE
MAXRATE	EQU	400		;MAXIMUM SPEAKING RATE
MINPITCH	EQU	 65		;MINIMUM PITCH
MAXPITCH	EQU	320		;MAXIMUM PITCH
MINFREQ	EQU    5000		;MINIMUM SAMPLING FREQUENCY
MAXFREQ	EQU   28000		;MAXIMUM SAMPLING FREQUENCY
MINVOL		EQU	  0		;MINIMUM VOLUME
MAXVOL		EQU	 64		;MAXIMUM VOLUME
MINCENT	EQU	  0		;MINIMUM DEGREE OF CENTRALIZATION
MAXCENT	EQU	100		;MAXIMUM DEGREE OF CENTRALIZATION

*		;------	Driver error codes

ND_NotUsed	EQU	 -1		;
ND_NoMem	EQU	 -2		;Can't allocate memory
ND_NoAudLib	EQU	 -3		;Can't open audio device
ND_MakeBad	EQU	 -4		;Error in MakeLibrary call
ND_UnitErr	EQU	 -5		;Unit other than 0
ND_CantAlloc	EQU	 -6		;Can't allocate the audio channel
ND_Unimpl	EQU	 -7		;Unimplemented command
ND_NoWrite	EQU	 -8		;Read for mouth shape without write
ND_Expunged	EQU	 -9		;Can't open, deferred expunge bit set
ND_PhonErr	EQU	-20		;Phoneme code spelling error
ND_RateErr	EQU	-21		;Rate out of bounds
ND_PitchErr	EQU	-22		;Pitch out of bounds
ND_SexErr	EQU	-23		;Sex not valid
ND_ModeErr	EQU	-24		;Mode not valid
ND_FreqErr	EQU	-25		;Sampling freq out of bounds
ND_VolErr	EQU	-26		;Volume out of bounds
ND_DCentErr	EQU	-27		;Degree of centralization out of bounds
ND_CentPhonErr	EQU	-28		;Invalid central phon

*		;------ Bit/field definitions of "flags" field of IORB.

NDB_NEWIORB	EQU	0		;Use new IORB flag
NDB_WORDSYNC	EQU	1		;Generate word sync messages
NDB_SYLSYNC	EQU	2		;Generate syllable sync messages

NDF_NEWIORB	EQU	(1<<NDB_NEWIORB)
NDF_WORDSYNC	EQU	(1<<NDB_WORDSYNC)
NDF_SYLSYNC	EQU	(1<<NDB_SYLSYNC)

*		;------ Write IORequest block

 STRUCTURE NDI,IOSTD_SIZE
    UWORD	NDI_RATE		;Speaking rate in words/minute
    UWORD	NDI_PITCH		;Baseline pitch in Hertz
    UWORD	NDI_MODE		;F0 mode
    UWORD	NDI_SEX			;Speaker sex
    APTR	NDI_CHMASKS		;Pointer to audio channel masks
    UWORD	NDI_NUMMASKS		;Size of channel masks array
    UWORD	NDI_VOLUME		;Channel volume
    UWORD	NDI_SAMPFREQ		;Sampling frequency
    UBYTE	NDI_MOUTHS		;Generate mouths? (Boolean value)
    UBYTE	NDI_CHANMASK		;Actual channel mask used (internal use)
    UBYTE	NDI_NUMCHAN		;Number of channels used (internal use)
    UBYTE	NDI_FLAGS		;New feature flags
    UBYTE	NDI_F0ENTHUSIASM	;F0 excursion factor
    BYTE	NDI_F0PERTURB		;Amount of F0 perturbation
    BYTE	NDI_F1ADJ		;F1 adjustment in ±5% steps
    BYTE	NDI_F2ADJ		;F2 adjustment in ±5% steps
    BYTE	NDI_F3ADJ		;F3 adjustment in ±5% steps
    BYTE	NDI_A1ADJ		;A1 adjustment in decibels
    BYTE	NDI_A2ADJ		;A2 adjustment in decibels
    BYTE	NDI_A3ADJ		;A3 adjustment in decibels
    UBYTE	NDI_ARTICULATE		;Transition time multiplier
    UBYTE	NDI_CENTRALIZE		;Degree of vowel centralization
    APTR	NDI_CENTPHON		;Ptr to ASCII central phon code
    BYTE	NDI_AVBIAS		;AV bias
    BYTE	NDI_AFBIAS		;AF bias
    BYTE	NDI_PRIORITY		;Priority while speaking
    BYTE	NDI_PAD1		;For alignment
    LABEL	NDI_SIZE		;Size of Narrator IORequest block

*		;------	Mouth read IORB

 STRUCTURE MRB,NDI_SIZE
    UBYTE	MRB_WIDTH		;Mouth width
    UBYTE	MRB_HEIGHT		;Mouth height
    UBYTE	MRB_SHAPE		;Compressed shape (height/width)
    UBYTE	MRB_SYNC		;Sync events
    LABEL	MRB_SIZE

    ENDC	; DEVICES_NARRATOR_I


Includes/devices/scsidisk.i

    IFND	DEVICES_SCSIDISK_I
DEVICES_SCSIDISK_I	EQU	1
**
**	$Filename: devices/scsidisk.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.2 $
**	$Date: 90/11/07 $
**
**	SCSI exec-level device command
**
**	(C) Copyright 1988-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND EXEC_TYPES_I
    INCLUDE "exec/types.i"
    ENDC ; EXEC_TYPES_I

;---------------------------------------------------------------------
;
;   SCSI Command
;	Several Amiga SCSI controller manufacturers are converging on
;	standard ways to talk to their controllers.  This include
;	file describes an exec-device command (e.g. for hddisk.device)
;	that can be used to issue SCSI commands
;
;   UNIT NUMBERS
;	Unit numbers to the OpenDevice call have encoded in them which
;	SCSI device is being referred to.  The three decimal digits of
;	the unit number refer to the SCSI Target ID (bus address) in
;	the 1's digit, the SCSI logical unit (LUN) in the 10's digit,
;	and the controller board in the 100's digit.
;
;	Examples:
;		  0	drive at address 0
;		 12	LUN 1 on multiple drive controller at address 2
;		104	second controller board, address 4
;		 88	not valid: both logical units and addresses
;			range from 0..7.
;
;   CAVEATS
;	Original 2090 code did not support this command.
;
;	Commodore 2090/2090A unit numbers are different.  The SCSI
;	logical unit is the 100's digit, and the SCSI Target ID
;	is a permuted 1's digit: Target ID 0..6 maps to unit 3..9
;	(7 is reserved for the controller).
;
;	    Examples:
;		  3	drive at address 0
;		109	drive at address 6, logical unit 1
;		  1	not valid: this is not a SCSI unit.  Perhaps
;			it's an ST506 unit.
;
;	Some controller boards generate a unique name (e.g. 2090A's
;	iddisk.device) for the second controller board, instead of
;	implementing the 100's digit.
;
;	There are optional restrictions on the alignment, bus
;	accessability, and size of the data for the data phase.
;	Be conservative to work with all manufacturer's controllers.
;
;---------------------------------------------------------------------

HD_SCSICMD	EQU	28	; issue a SCSI command to the unit
                ; io_Data points to a SCSICmd
                ; io_Length is sizeof(struct SCSICmd)
                ; io_Actual and io_Offset are not used

 STRUCTURE	SCSICmd,0
    APTR    scsi_Data		; word aligned data for SCSI Data Phase
                ; (optional) data need not be byte aligned
                ; (optional) data need not be bus accessable
    ULONG   scsi_Length		; even length of Data area
                ; (optional) data can have odd length
                ; (optional) data length can be > 2**24
    ULONG   scsi_Actual		; actual Data used
    APTR    scsi_Command	; SCSI Command (same options as scsi_Data)
    UWORD   scsi_CmdLength	; length of Command
    UWORD   scsi_CmdActual	; actual Command used
    UBYTE   scsi_Flags		; includes intended data direction
    UBYTE   scsi_Status		; SCSI status of command
    APTR    scsi_SenseData	; sense data: filled if SCSIF_[OLD]AUTOSENSE
                ; is set and scsi_Status has CHECK CONDITION
                ; (bit 1) set
    UWORD   scsi_SenseLength	; size of scsi_SenseData, also bytes to
                ; request w/ SCSIF_AUTOSENSE, must be 4..255
    UWORD   scsi_SenseActual	; amount actually fetched (0 means no sense)
    LABEL   scsi_SIZEOF

;------ scsi_Flags ------
SCSIF_WRITE		EQU	0	; intended data direction is out
SCSIF_READ		EQU	1	; intended data direction is in
SCSIB_READ_WRITE	EQU	0	; (the bit to test)

SCSIF_NOSENSE		EQU	0	; no automatic request sense
SCSIF_AUTOSENSE		EQU	2	; do standard extended request sense
                    ; on check condition
SCSIF_OLDAUTOSENSE	EQU	6	; do 4 byte non-extended request
                    ; sense on check condition
SCSIB_AUTOSENSE		EQU	1	; (the bit to test)
SCSIB_OLDAUTOSENSE	EQU	2	; (the bit to test)

;------ SCSI io_Error values ------
HFERR_SelfUnit		EQU	40	; cannot issue SCSI command to self
HFERR_DMA		EQU	41	; DMA error
HFERR_Phase		EQU	42	; illegal or unexpected SCSI phase
HFERR_Parity		EQU	43	; SCSI parity error
HFERR_SelTimeout	EQU	44	; Select timed out
HFERR_BadStatus		EQU	45	; status and/or sense error

;------ OpenDevice io_Error values ------
HFERR_NoBoard		EQU	50	; Open failed for non-existant board

    ENDC	; DEVICES_SCSIDISK_I


Includes/devices/clipboard.h

#ifndef     DEVICES_CLIPBOARD_H
#define     DEVICES_CLIPBOARD_H
/*
**	$Filename: devices/clipboard.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.5 $
**	$Date: 90/11/02 $
**
**	clipboard.device structure definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef	EXEC_TYPES_H
#include	"exec/types.h"
#endif
#ifndef	EXEC_NODES_H
#include	"exec/nodes.h"
#endif
#ifndef	EXEC_LISTS_H
#include	"exec/lists.h"
#endif
#ifndef	EXEC_PORTS_H
#include	"exec/ports.h"
#endif

#define	CBD_POST		(CMD_NONSTD+0)
#define	CBD_CURRENTREADID	(CMD_NONSTD+1)
#define	CBD_CURRENTWRITEID	(CMD_NONSTD+2)
#define	CBD_CHANGEHOOK		(CMD_NONSTD+3)

#define	CBERR_OBSOLETEID	1

struct ClipboardUnitPartial {
    struct  Node cu_Node;	/* list of units */
    ULONG   cu_UnitNum;		/* unit number for this unit */
    /* the remaining unit data is private to the device */
};

struct IOClipReq {
    struct Message io_Message;
    struct Device *io_Device;	/* device node pointer	*/
    struct ClipboardUnitPartial *io_Unit; /* unit node pointer */
    UWORD   io_Command;		/* device command */
    UBYTE   io_Flags;		/* including QUICK and SATISFY */
    BYTE    io_Error;		/* error or warning num */
    ULONG   io_Actual;		/* number of bytes transferred */
    ULONG   io_Length;		/* number of bytes requested */
    STRPTR  io_Data;		/* either clip stream or post port */
    ULONG   io_Offset;		/* offset in clip stream */
    LONG    io_ClipID;		/* ordinal clip identifier */
};

#define	PRIMARY_CLIP	0	/* primary clip unit */

struct SatisfyMsg {
    struct Message sm_Msg;	/* the length will be 6 */
    UWORD   sm_Unit;		/* which clip unit this is */
    LONG    sm_ClipID;		/* the clip identifier of the post */
};

struct ClipHookMsg {
    ULONG   chm_Type;		/* zero for this structure format */
    LONG    chm_ChangeCmd;	/* command that caused this hook invocation: */
                /*   either CMD_UPDATE or CBD_POST */
    LONG    chm_ClipID;		/* the clip identifier of the new data */
};

#endif	/* DEVICES_CLIPBOARD_H */


Includes/devices/input.h

#ifndef DEVICES_INPUT_H
#define DEVICES_INPUT_H
/*
**	$Filename: devices/input.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.0 $
**	$Date: 90/05/01 $
**
**	input device command definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef	    EXEC_IO_H
#include "exec/io.h"
#endif

#define	 IND_ADDHANDLER	   (CMD_NONSTD+0)
#define	 IND_REMHANDLER	   (CMD_NONSTD+1)
#define	 IND_WRITEEVENT	   (CMD_NONSTD+2)
#define	 IND_SETTHRESH	   (CMD_NONSTD+3)
#define	 IND_SETPERIOD	   (CMD_NONSTD+4)
#define	 IND_SETMPORT	   (CMD_NONSTD+5)
#define	 IND_SETMTYPE	   (CMD_NONSTD+6)
#define	 IND_SETMTRIG	   (CMD_NONSTD+7)

#endif	/* DEVICES_INPUT_H */


Includes/devices/parallel.h

#ifndef DEVICES_PARALLEL_H
#define DEVICES_PARALLEL_H
/*
**	$Filename: devices/parallel.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.1 $
**	$Date: 90/05/10 $
**
**	parallel.device I/O request structure information
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All rights reserved.
*/

#ifndef   EXEC_IO_H
#include "exec/io.h"
#endif	 /* !EXEC_IO_H */

 struct  IOPArray {
    ULONG PTermArray0;
    ULONG PTermArray1;
};

/******************************************************************/
/* CAUTION !!  IF YOU ACCESS the parallel.device, you MUST (!!!!) use
   an IOExtPar-sized structure or you may overlay innocent memory !! */
/******************************************************************/

 struct   IOExtPar {
    struct	 IOStdReq IOPar;

/*     STRUCT	MsgNode
*   0	APTR	 Succ
*   4	APTR	 Pred
*   8	UBYTE	 Type
*   9	UBYTE	 Pri
*   A	APTR	 Name
*   E	APTR	 ReplyPort
*  12	UWORD	 MNLength
*     STRUCT   IOExt
*  14	APTR	 io_Device
*  18	APTR	 io_Unit
*  1C	UWORD	 io_Command
*  1E	UBYTE	 io_Flags
*  1F	UBYTE	 io_Error
*     STRUCT   IOStdExt
*  20	ULONG	 io_Actual
*  24	ULONG	 io_Length
*  28	APTR	 io_Data
*  2C	ULONG	 io_Offset
*  30 */
    ULONG	io_PExtFlags;	 /* (not used) flag extension area */
    UBYTE	io_Status;	 /* status of parallel port and registers */
    UBYTE	io_ParFlags;	 /* see PARFLAGS bit definitions below */
    struct	IOPArray io_PTermArray; /* termination character array */
};

#define	PARB_SHARED	5	   /* ParFlags non-exclusive access bit */
#define	PARF_SHARED	(1<<5)	   /*	 "     non-exclusive access mask */
#define PARB_SLOWMODE	4	   /*	 "     slow printer bit */
#define PARF_SLOWMODE	(1<<4)	   /*	 "     slow printer mask */
#define PARB_FASTMODE	3	   /*	 "     fast I/O mode selected bit */
#define PARF_FASTMODE	(1<<3)	   /*	 "     fast I/O mode selected mask */
#define PARB_RAD_BOOGIE	3	   /*	 "     for backward compatibility */
#define PARF_RAD_BOOGIE	(1<<3)	   /*	 "     for backward compatibility */

#define PARB_ACKMODE	2	   /*	 "     ACK interrupt handshake bit */
#define PARF_ACKMODE	(1<<2)	   /*	 "     ACK interrupt handshake mask */

#define PARB_EOFMODE	1	   /*	 "     EOF mode enabled bit */
#define PARF_EOFMODE	(1<<1)	   /*	 "     EOF mode enabled mask */

#define IOPARB_QUEUED	6	   /* IO_FLAGS rqst-queued bit */
#define IOPARF_QUEUED	(1<<6)	   /*	 "     rqst-queued mask */
#define	IOPARB_ABORT	5	   /*	 "     rqst-aborted bit */
#define	IOPARF_ABORT	(1<<5)	   /*	 "     rqst-aborted mask */
#define	IOPARB_ACTIVE	4	   /*	 "     rqst-qued-or-current bit */
#define	IOPARF_ACTIVE	(1<<4)	   /*	 "     rqst-qued-or-current mask */
#define	IOPTB_RWDIR	3	   /* IO_STATUS read=0,write=1 bit */
#define	IOPTF_RWDIR	(1<<3)	   /*	 "     read=0,write=1 mask */
#define	IOPTB_PARSEL	2	   /*	 "     printer selected on the A1000 */
#define	IOPTF_PARSEL	(1<<2)	   /* printer selected & serial "Ring Indicator"
                      on the A500 & A2000.  Be careful when
                      making cables */
#define	IOPTB_PAPEROUT 1	   /*	 "     paper out bit */
#define	IOPTF_PAPEROUT (1<<1)	   /*	 "     paper out mask */
#define	IOPTB_PARBUSY  0	   /*	 "     printer in busy toggle bit */
#define	IOPTF_PARBUSY  (1<<0)	   /*	 "     printer in busy toggle mask */
/* Note: previous versions of this include files had bits 0 and 2 swapped */

#define PARALLELNAME		"parallel.device"

#define PDCMD_QUERY		(CMD_NONSTD)
#define PDCMD_SETPARAMS	(CMD_NONSTD+1)

#define ParErr_DevBusy			1
#define ParErr_BufTooBig	2
#define ParErr_InvParam	3
#define ParErr_LineErr		4
#define ParErr_NotOpen		5
#define ParErr_PortReset	6
#define ParErr_InitErr			7

#endif	/* DEVICES_PARALLEL_H */


Includes/devices/serial.h

#ifndef DEVICES_SERIAL_H
#define DEVICES_SERIAL_H
/*
**	$Filename: devices/serial.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 33.6 $
**	$Date: 90/11/06 $
**
**	external declarations for the serial device
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef   EXEC_IO_H
#include "exec/io.h"
#endif /* EXEC_IO_H */

           /* array of termination char's */
           /* to use,see serial.doc setparams */

 struct  IOTArray {
    ULONG TermArray0;
    ULONG TermArray1;
};

#define SER_DEFAULT_CTLCHAR 0x11130000	/* default chars for xON,xOFF */
/* You may change these via SETPARAMS.	At this time, parity is not
   calculated for xON/xOFF characters.	You must supply them with the
   desired parity. */

/******************************************************************/
/* CAUTION !!  IF YOU ACCESS the serial.device, you MUST (!!!!) use an
   IOExtSer-sized structure or you may overlay innocent memory !! */
/******************************************************************/

 struct  IOExtSer {
    struct	 IOStdReq IOSer;

/*     STRUCT	MsgNode
*   0	APTR	 Succ
*   4	APTR	 Pred
*   8	UBYTE	 Type
*   9	UBYTE	 Pri
*   A	APTR	 Name
*   E	APTR	 ReplyPort
*  12	UWORD	 MNLength
*     STRUCT   IOExt
*  14	APTR	 io_Device
*  18	APTR	 io_Unit
*  1C	UWORD	 io_Command
*  1E	UBYTE	 io_Flags
*  1F	UBYTE	 io_Error
*     STRUCT   IOStdExt
*  20	ULONG	 io_Actual
*  24	ULONG	 io_Length
*  28	APTR	 io_Data
*  2C	ULONG	 io_Offset
*
*  30 */
   ULONG   io_CtlChar;	  /* control char's (order = xON,xOFF,INQ,ACK) */
   ULONG   io_RBufLen;	  /* length in bytes of serial port's read buffer */
   ULONG   io_ExtFlags;   /* additional serial flags (see bitdefs below) */
   ULONG   io_Baud;	  /* baud rate requested (true baud) */
   ULONG   io_BrkTime;	  /* duration of break signal in MICROseconds */
   struct  IOTArray io_TermArray; /* termination character array */
   UBYTE   io_ReadLen;	  /* bits per read character (# of bits) */
   UBYTE   io_WriteLen;   /* bits per write character (# of bits) */
   UBYTE   io_StopBits;   /* stopbits for read (# of bits) */
   UBYTE   io_SerFlags;   /* see SerFlags bit definitions below  */
   UWORD   io_Status;
};
   /* status of serial port, as follows:
*		   BIT	ACTIVE	FUNCTION
*		    0	 ---	reserved
*		    1	 ---	reserved
*		    2	 high	Connected to parallel "select" on the A1000.
*				Connected to both the parallel "select" and
*				serial "ring indicator" pins on the A500
*				& A2000.  Take care when making cables.
*		    3	 low	Data Set Ready
*		    4	 low	Clear To Send
*		    5	 low	Carrier Detect
*		    6	 low	Ready To Send
*		    7	 low	Data Terminal Ready
*		    8	 high	read overrun
*		    9	 high	break sent
*		   10	 high	break received
*		   11	 high	transmit x-OFFed
*		   12	 high	receive x-OFFed
*		13-15		reserved
*/

#define   SDCMD_QUERY		CMD_NONSTD	/* $09 */
#define   SDCMD_BREAK	       (CMD_NONSTD+1)	/* $0A */
#define   SDCMD_SETPARAMS      (CMD_NONSTD+2)	/* $0B */

#define SERB_XDISABLED	7	/* io_SerFlags xOn-xOff feature disabled bit */
#define SERF_XDISABLED	(1<<7)	/*    "     xOn-xOff feature disabled mask */
#define	SERB_EOFMODE	6	/*    "     EOF mode enabled bit */
#define	SERF_EOFMODE	(1<<6)	/*    "     EOF mode enabled mask */
#define	SERB_SHARED	5	/*    "     non-exclusive access bit */
#define	SERF_SHARED	(1<<5)	/*    "     non-exclusive access mask */
#define SERB_RAD_BOOGIE 4	/*    "     high-speed mode active bit */
#define SERF_RAD_BOOGIE (1<<4)	/*    "     high-speed mode active mask */
#define	SERB_QUEUEDBRK	3	/*    "     queue this Break ioRqst */
#define	SERF_QUEUEDBRK	(1<<3)	/*    "     queue this Break ioRqst */
#define	SERB_7WIRE	2	/*    "     RS232 7-wire protocol */
#define	SERF_7WIRE	(1<<2)	/*    "     RS232 7-wire protocol */
#define	SERB_PARTY_ODD	1	/*    "     parity feature enabled bit */
#define	SERF_PARTY_ODD	(1<<1)	/*    "     parity feature enabled mask */
#define	SERB_PARTY_ON	0	/*    "     parity-enabled bit */
#define	SERF_PARTY_ON	(1<<0)	/*    "     parity-enabled mask */

/* These now refect the actual bit positions in the io_Status UWORD */
#define	IO_STATB_XOFFREAD 12	   /* io_Status receive currently xOFF'ed bit */
#define	IO_STATF_XOFFREAD (1<<12)  /*	 "     receive currently xOFF'ed mask */
#define	IO_STATB_XOFFWRITE 11	   /*	 "     transmit currently xOFF'ed bit */
#define	IO_STATF_XOFFWRITE (1<<11) /*	 "     transmit currently xOFF'ed mask */
#define	IO_STATB_READBREAK 10	   /*	 "     break was latest input bit */
#define	IO_STATF_READBREAK (1<<10) /*	 "     break was latest input mask */
#define	IO_STATB_WROTEBREAK 9	   /*	 "     break was latest output bit */
#define	IO_STATF_WROTEBREAK (1<<9) /*	 "     break was latest output mask */
#define	IO_STATB_OVERRUN 8	   /*	 "     status word RBF overrun bit */
#define	IO_STATF_OVERRUN (1<<8)	   /*	 "     status word RBF overrun mask */

#define	SEXTB_MSPON	1	/* io_ExtFlags. Use mark-space parity, */
                /*	    instead of odd-even. */
#define	SEXTF_MSPON	(1<<1)	/*    "     mark-space parity mask */
#define	SEXTB_MARK	0	/*    "     if mark-space, use mark */
#define	SEXTF_MARK	(1<<0)	/*    "     if mark-space, use mark mask */

#define SerErr_DevBusy	       1
#define SerErr_BaudMismatch    2 /* baud rate not supported by hardware */
#define SerErr_BufErr	       4 /* Failed to allocate new read buffer */
#define SerErr_InvParam        5
#define SerErr_LineErr	       6
#define SerErr_ParityErr       9
#define SerErr_TimerErr       11 /*(See the serial/OpenDevice autodoc)*/
#define SerErr_BufOverflow    12
#define SerErr_NoDSR	      13
#define SerErr_DetectedBreak  15

#ifdef DEVICES_SERIAL_H_OBSOLETE
#define SerErr_InvBaud	       3	/* unused */
#define SerErr_NotOpen	       7	/* unused */
#define SerErr_PortReset       8	/* unused */
#define SerErr_InitErr	      10	/* unused */
#define SerErr_NoCTS	      14	/* unused */

/* These defines refer to the HIGH ORDER byte of io_Status.  They have
   been replaced by the new, corrected ones above */
#define	IOSTB_XOFFREAD	4	/* iost_hob receive currently xOFF'ed bit */
#define	IOSTF_XOFFREAD	(1<<4)	/*    "     receive currently xOFF'ed mask */
#define	IOSTB_XOFFWRITE 3	/*    "     transmit currently xOFF'ed bit */
#define	IOSTF_XOFFWRITE (1<<3)	/*    "     transmit currently xOFF'ed mask */
#define	IOSTB_READBREAK 2	/*    "     break was latest input bit */
#define	IOSTF_READBREAK (1<<2)	/*    "     break was latest input mask */
#define	IOSTB_WROTEBREAK 1	/*    "     break was latest output bit */
#define	IOSTF_WROTEBREAK (1<<1) /*    "     break was latest output mask */
#define	IOSTB_OVERRUN	0	/*    "     status word RBF overrun bit */
#define	IOSTF_OVERRUN	(1<<0)	/*    "     status word RBF overrun mask */

#define	IOSERB_BUFRREAD 7	/* io_Flags from read buffer bit */
#define	IOSERF_BUFRREAD (1<<7)	/*    "     from read buffer mask */
#define	IOSERB_QUEUED	6	/*    "     rqst-queued bit */
#define	IOSERF_QUEUED	(1<<6)	/*    "     rqst-queued mask */
#define	IOSERB_ABORT	5	/*    "     rqst-aborted bit */
#define	IOSERF_ABORT	(1<<5)	/*    "     rqst-aborted mask */
#define	IOSERB_ACTIVE	4	/*    "     rqst-qued-or-current bit */
#define	IOSERF_ACTIVE	(1<<4)	/*    "     rqst-qued-or-current mask */
#endif

#define SERIALNAME     "serial.device"

#endif /* DEVICES_SERIAL_H */


Includes/devices/clipboard.i

    IFND	DEVICES_CLIPBOARD_I
DEVICES_CLIPBOARD_I  EQU   1
**
**	$Filename: devices/clipboard.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.5 $
**	$Date: 90/11/02 $
**
**	clipboard.device structure definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND	EXEC_TYPES_I
    INCLUDE	"exec/types.i"
    ENDC
    IFND	EXEC_NODES_I
    INCLUDE	"exec/nodes.i"
    ENDC
    IFND	EXEC_LISTS_I
    INCLUDE	"exec/lists.i"
    ENDC
    IFND	EXEC_PORTS_I
    INCLUDE	"exec/ports.i"
    ENDC
    IFND	EXEC_IO_I
    INCLUDE	"exec/io.i"
    ENDC

    DEVINIT

    DEVCMD	CBD_POST
    DEVCMD	CBD_CURRENTREADID
    DEVCMD	CBD_CURRENTWRITEID
    DEVCMD	CBD_CHANGEHOOK

CBERR_OBSOLETEID	EQU	1

 STRUCTURE  ClipboardUnitPartial,0
    STRUCT  cu_Node,LN_SIZE	; list of units
    ULONG   cu_UnitNum		; unit number for this unit
    ; the remaining unit data is private to the device

 STRUCTURE  IOClipReq,0
    STRUCT  io_Message,MN_SIZE
    APTR    io_Device		; device node pointer
    APTR    io_Unit		; unit node pointer (ClipboardUnitPartial)
    UWORD   io_Command		; device command
    UBYTE   io_Flags		; including QUICK and SATISFY
    BYTE    io_Error		; error or warning num
    ULONG   io_Actual		; number of bytes transferred
    ULONG   io_Length		; number of bytes requested
    APTR    io_Data		; either clip stream or post port
    ULONG   io_Offset		; offset in clip stream
    LONG    io_ClipID		; ordinal clip identifier
    LABEL   iocr_SIZEOF

PRIMARY_CLIP	EQU	0	; primary clip unit

 STRUCTURE  SatisfyMsg,0
    STRUCT  sm_Msg,MN_SIZE	; the length will be 6
    UWORD   sm_Unit		; which clip unit this is
    LONG    sm_ClipID		; the clip identifier of the post
    LABEL   satisfyMsg_SIZEOF

 STRUCTURE  ClipHookMsg,0
    ULONG   chm_Type		; zero for this structure format
    LONG    chm_ChangeCmd;	; command that caused this hook invocation:
                ;   either CMD_UPDATE or CBD_POST
    LONG    chm_ClipID		; the clip identifier of the new data

    ENDC	; DEVICES_CLIPBOARD_I


Includes/devices/input.i

    IFND	DEVICES_INPUT_I
DEVICES_INPUT_I SET	1
**
**	$Filename: devices/input.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.0 $
**	$Date: 90/05/01 $
**
**	input device command definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

   IFND	    EXEC_IO_I
   INCLUDE     "exec/io.i"
   ENDC

   DEVINIT

   DEVCMD	IND_ADDHANDLER
   DEVCMD	IND_REMHANDLER
   DEVCMD	IND_WRITEEVENT
   DEVCMD	IND_SETTHRESH
   DEVCMD	IND_SETPERIOD
   DEVCMD	IND_SETMPORT
   DEVCMD	IND_SETMTYPE
   DEVCMD	IND_SETMTRIG

    ENDC	; DEVICES_INPUT_I


Includes/devices/parallel.i

    IFND     DEVICES_PARALLEL_I
DEVICES_PARALLEL_I SET 1
**
**	$Filename: devices/parallel.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 34.9 $
**	$Date: 89/05/25 $
**
**	external declarations for the parallel device
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**
    IFND     EXEC_IO_I
    include "exec/io.i"
    ENDC    !EXEC_IO_I

*--------------------------------------------------------------------
*
* Driver error definitions
*
*--------------------------------------------------------------------

ParErr_DevBusy		EQU	1
ParErr_BufTooBig		EQU	2
ParErr_InvParam		EQU	3
ParErr_LineErr		EQU	4
ParErr_NotOpen		EQU	5
ParErr_PortReset	EQU	6
ParErr_InitErr		EQU	7

*--------------------------------------------------------------------
*
* Useful constants
*
*--------------------------------------------------------------------
*
PDCMD_QUERY	   EQU	   CMD_NONSTD
PDCMD_SETPARAMS    EQU	   CMD_NONSTD+1
Par_DEVFINISH	   EQU	   10	     ; number of device comands
*
*--------------------------------------------------------------------
*
* Driver Specific Commands
*
*--------------------------------------------------------------------

PARALLELNAME:	MACRO
        dc.b	'parallel.device',0
        ds.w	0
        ENDM

    BITDEF	PAR,SHARED,5	  ; PARFLAGS non-exclusive access
    BITDEF	PAR,SLOWMODE,4	  ;    "     slow mode selected bit
    BITDEF	PAR,FASTMODE,3    ;    "     fast mode selected bit
    BITDEF	PAR,RAD_BOOGIE,3  ;    "     for backward compatibility
    BITDEF	PAR,ACKMODE,2     ;    "     ACK handshaking selected bit
    BITDEF	PAR,EOFMODE,1	  ;    "     EOF mode enabled bit
        BITDEF  IOPAR,QUEUED,6    ; IO_FLAGS rqst-queued bit
        BITDEF	IOPAR,ABORT,5     ;    "     rqst-aborted bit
    BITDEF	IOPAR,ACTIVE,4	  ;    "     rqst-qued-or-current bit
        BITDEF	IOPT,RWDIR,3      ; IO_STATUS read=0,write=1
        BITDEF	IOPT,PARSEL,2     ;    "     printer selected on the A1000
                  ; printer selected & serial "Ring Indicator" on
                  ; the A500/A2000.  Be careful when making cables.
    BITDEF	IOPT,PAPEROUT,1   ;    "     paper out
        BITDEF	IOPT,PARBUSY,0    ;    "     printer in busy toggle
;Note: Previous versions of this include file had bits 0 and 2 swapped
*
************************************************************************

 STRUCTURE PTERMARRAY,0
    ULONG	 PTERMARRAY_0
    ULONG	 PTERMARRAY_1
    LABEL	 PTERMARRAY_SIZE

*****************************************************************
*  CAUTION !!!	IF YOU ACCESS the parallel.device, you MUST (!!!!) use an
*  IOEXTPAR-sized structure or you may overlay innocent memory, okay ?!
*****************************************************************

 STRUCTURE IOEXTPAR,IOSTD_SIZE

*     STRUCT   MsgNode
*   0	APTR	 Succ
*   4	APTR	 Pred
*   8	UBYTE	 Type
*   9	UBYTE	 Pri
*   A	APTR	 Name
*   E	APTR	 ReplyPort
*  12	UWORD	 MNLength
*     STRUCT   IOExt
*  14	APTR	 IO_DEVICE
*  18	APTR	 IO_UNIT
*  1C	UWORD	 IO_COMMAND
*  1E	UBYTE	 IO_FLAGS
*  1F	UBYTE	 IO_ERROR
*     STRUCT   IOStdExt
*  20	ULONG	 IO_ACTUAL
*  24	ULONG	 IO_LENGTH
*  28	APTR	 IO_DATA
*  2C	ULONG	 IO_OFFSET
*

*
*  30
    ULONG	IO_PEXTFLAGS	; (not used) flag extension area
    UBYTE	IO_PARSTATUS	; device status (see bit defs above)
    UBYTE	IO_PARFLAGS	; see PARFLAGS bit definitions above
    STRUCT	IO_PTERMARRAY,PTERMARRAY_SIZE ; termination char array
    LABEL	IOEXTPar_SIZE

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

    ENDC    !DEVICES_PARALLEL_I


Includes/devices/serial.i

    IFND DEVICES_SERIAL_I
DEVICES_SERIAL_I SET 1
**
**	$Filename: devices/serial.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 33.6 $
**	$Date: 90/11/06 $
**
**	external declarations for the serial device
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**
    IFND     EXEC_IO_I
    include "exec/io.i"
    ENDC    !EXEC_IO_I

*--------------------------------------------------------------------
*
* Useful constants
*
*--------------------------------------------------------------------
*
SER_DEFAULT_CTLCHAR EQU $11130000  ; default chars for xON,xOFF
; You may change these via SETPARAMS.  At this time, parity is not
; calculated for xON/xOFF characters.  You must supply them with the
; desired parity.

*
*--------------------------------------------------------------------
*
* Driver Specific Commands

SDCMD_QUERY	EQU	CMD_NONSTD	;$09
SDCMD_BREAK	EQU	CMD_NONSTD+1	;$0A
SDCMD_SETPARAMS EQU	CMD_NONSTD+2	;$0B

SER_DEVFINISH	EQU	CMD_NONSTD+2 ; number of device comands

*--------------------------------------------------------------------

SERIALNAME:	MACRO
        dc.b	'serial.device',0
        dc.w	0
        ENDM

    BITDEF	SER,XDISABLED,7	  ; SERFLAGS xOn-xOff feature disabled bit
    BITDEF	SER,EOFMODE,6	  ;    "     EOF mode enabled bit
    BITDEF	SER,SHARED,5	  ;    "     non-exclusive access
    BITDEF	SER,RAD_BOOGIE,4  ;    "     high-speed mode active
    BITDEF	SER,QUEUEDBRK,3	  ;    "     queue this Break ioRqst
    BITDEF	SER,7WIRE,2	  ;    "     RS232 7-wire protocol
    BITDEF	SER,PARTY_ODD,1	  ;    "     use-odd-parity bit
    BITDEF	SER,PARTY_ON,0	  ;    "     parity-enabled bit
;
;WARNING: The next series of BITDEFs refer to the HIGH order BYTE of
;IO_STATUS.  Example usage: "BTST.B #IOST_XOFFWRITE,IO_STATUS+1(AX)"
;
    BITDEF	IOST,XOFFREAD,4	  ; IOST_HOB receive currently xOFF'ed
    BITDEF	IOST,XOFFWRITE,3  ;	"    transmit currently xOFF'ed
    BITDEF	IOST,READBREAK,2  ;	"    break was latest input
    BITDEF	IOST,WROTEBREAK,1 ;	"    break was latest output
    BITDEF	IOST,OVERRUN,0	  ;	"    status word RBF overrun
;
;	BITDEF's in a longword field)
;	Example usage: BSET.B #SEXTB_MSPON,IO_EXTFLAGS+3(AX)
                ;IO_EXTFLAGS (extended flag longword)
    BITDEF	SEXT,MSPON,1	;     "	   use mark-space parity,not odd-even
    BITDEF	SEXT,MARK,0	;     "	   if mark-space, use mark
*
******************************************************************************
 STRUCTURE TERMARRAY,0
    ULONG	 TERMARRAY_0
    ULONG	 TERMARRAY_1
    LABEL	 TERMARRAY_SIZE

*****************************************************************
* CAUTION !!  IF YOU ACCESS the serial.device, you MUST (!!!!) use an
* IOEXTSER-sized structure or you may overlay innocent memory, okay ?!
*****************************************************************

 STRUCTURE IOEXTSER,IOSTD_SIZE

*     STRUCT   MsgNode
*   0	APTR	 Succ
*   4	APTR	 Pred
*   8	UBYTE	 Type
*   9	UBYTE	 Pri
*   A	APTR	 Name
*   E	APTR	 ReplyPort
*  12	UWORD	 MNLength
*     STRUCT   IOExt
*  14	APTR	 IO_DEVICE
*  18	APTR	 IO_UNIT
*  1C	UWORD	 IO_COMMAND
*  1E	UBYTE	 IO_FLAGS
*  1F	UBYTE	 IO_ERROR
*     STRUCT   IOStdExt
*  20	ULONG	 IO_ACTUAL
*  24	ULONG	 IO_LENGTH
*  28	APTR	 IO_DATA
*  2C	ULONG	 IO_OFFSET
*
*  30
    ULONG	IO_CTLCHAR	; control char's (order = xON,xOFF,rsvd,rsvd)
    ULONG	IO_RBUFLEN	; length in bytes of serial port's read buffer
    ULONG	IO_EXTFLAGS	; additional serial flags (see bitdefs above)
    ULONG	IO_BAUD		; baud rate requested (true baud)
    ULONG	IO_BRKTIME	; duration of break signal in MICROseconds
    STRUCT	IO_TERMARRAY,TERMARRAY_SIZE ; termination character array
    UBYTE	IO_READLEN	; bits per read char (bit count)
    UBYTE	IO_WRITELEN	; bits per write char (bit count)
    UBYTE	IO_STOPBITS	; stopbits for read (count)
    UBYTE	IO_SERFLAGS	; see SERFLAGS bit definitions above
    UWORD	IO_STATUS	; status of serial port, as follows:
*
*		   BIT	ACTIVE	FUNCTION
*		    0	 ---	reserved
*		    1	 ---	reserved
*		    2	 high	Connected to parallel "select" on the A1000.
*				Connected to both the parallel "select" and
*				serial "ring indicator" pins on the A500
*				& A2000.  Take care when making cables.
*		    3	 low	Data Set Ready
*		    4	 low	Clear To Send
*		    5	 low	Carrier Detect
*		    6	 low	Ready To Send
*		    7	 low	Data Terminal Ready
*		    8	 high	read overrun
*		    9	 high	break sent
*		   10	 high	break received
*		   11	 high	transmit x-OFF'ed
*		   12	 high	receive x-OFF'ed
*		13-15		reserved
*
    LABEL	IOEXTSER_SIZE

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

*--------------------------------------------------------------------
*
* Driver error definitions
*
*--------------------------------------------------------------------

SerErr_DevBusy		EQU	1
SerErr_BaudMismatch	EQU	2	;baud rate not supported by hardware
SerErr_BufErr		EQU	4	;Failed to allocate new read buffer
SerErr_InvParam		EQU	5
SerErr_LineErr		EQU	6
SerErr_ParityErr	EQU	9
SerErr_TimerErr		EQU    11	;(See the serial/OpenDevice autodoc)
SerErr_BufOverflow	EQU    12
SerErr_NoDSR		EQU    13
SerErr_DetectedBreak	EQU    15

 IFD	DEVICES_SERIAL_I_OBSOLETE
SER_DBAUD		EQU	9600	;unused
SerErr_InvBaud		EQU	3	;unused
SerErr_NotOpen		EQU	7	;unused
SerErr_PortReset	EQU	8	;unused
SerErr_InitErr		EQU    10	;unused
SerErr_NoCTS		EQU    14	;unused
    BITDEF	IOSER,QUEUED,6	  ; IO_FLAGS rqst-queued bit
    BITDEF	IOSER,ABORT,5	  ;	"    rqst-aborted bit
    BITDEF	IOSER,ACTIVE,4	  ;	"    rqst-qued-or-current bit
 ENDC

    ENDC    !DEVICES_SERIAL_I


Includes/devices/console.h

#ifndef DEVICES_CONSOLE_H
#define DEVICES_CONSOLE_H
/*
**	$Filename: devices/console.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.11 $
**	$Date: 90/11/07 $
**
**	Console device command definitions
**
**	(C) Copyright 1986-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include	"exec/types.h"
#endif

#ifndef EXEC_IO_H
#include	"exec/io.h"
#endif	/* EXEC_IO_H */

/****** Console commands ******/
#define CD_ASKKEYMAP		(CMD_NONSTD+0)
#define CD_SETKEYMAP		(CMD_NONSTD+1)
#define CD_ASKDEFAULTKEYMAP	(CMD_NONSTD+2)
#define CD_SETDEFAULTKEYMAP	(CMD_NONSTD+3)

/****** SGR parameters ******/

#define SGR_PRIMARY	0
#define SGR_BOLD	1
#define SGR_ITALIC	3
#define SGR_UNDERSCORE	4
#define SGR_NEGATIVE	7

#define	SGR_NORMAL	22	/* default foreground color, not bold */
#define	SGR_NOTITALIC	23
#define	SGR_NOTUNDERSCORE 24
#define	SGR_POSITIVE	27

/* these names refer to the ANSI standard, not the implementation */
#define SGR_BLACK	30
#define SGR_RED		31
#define SGR_GREEN	32
#define SGR_YELLOW	33
#define SGR_BLUE	34
#define SGR_MAGENTA	35
#define SGR_CYAN	36
#define SGR_WHITE	37
#define SGR_DEFAULT	39

#define SGR_BLACKBG	40
#define SGR_REDBG	41
#define SGR_GREENBG	42
#define SGR_YELLOWBG	43
#define SGR_BLUEBG	44
#define SGR_MAGENTABG	45
#define SGR_CYANBG	46
#define SGR_WHITEBG	47
#define SGR_DEFAULTBG	49

/* these names refer to the implementation, they are the preferred */
/* names for use with the Amiga console device. */
#define SGR_CLR0	30
#define SGR_CLR1	31
#define SGR_CLR2	32
#define SGR_CLR3	33
#define SGR_CLR4	34
#define SGR_CLR5	35
#define SGR_CLR6	36
#define SGR_CLR7	37

#define SGR_CLR0BG	40
#define SGR_CLR1BG	41
#define SGR_CLR2BG	42
#define SGR_CLR3BG	43
#define SGR_CLR4BG	44
#define SGR_CLR5BG	45
#define SGR_CLR6BG	46
#define SGR_CLR7BG	47

/****** DSR parameters ******/

#define DSR_CPR		6

/****** CTC parameters ******/
#define CTC_HSETTAB	0
#define CTC_HCLRTAB	2
#define CTC_HCLRTABSALL	5

/******	TBC parameters ******/
#define TBC_HCLRTAB	0
#define TBC_HCLRTABSALL	3

/******	SM and RM parameters ******/
#define M_LNM	20	/* linefeed newline mode */
#define M_ASM	">1"	/* auto scroll mode */
#define M_AWM	"?7"	/* auto wrap mode */

#endif	/* DEVICES_CONSOLE_H */


Includes/devices/inputevent.h

#ifndef DEVICES_INPUTEVENT_H
#define DEVICES_INPUTEVENT_H
/*
**	$Filename: devices/inputevent.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.7 $
**	$Date: 91/01/22 $
**
**	input event definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef DEVICES_TIMER_H
#include "devices/timer.h"
#endif

/*----- constants --------------------------------------------------*/

/*  --- InputEvent.ie_Class --- */
/* A NOP input event */
#define IECLASS_NULL			0x00
/* A raw keycode from the keyboard device */
#define IECLASS_RAWKEY			0x01
/* The raw mouse report from the game port device */
#define IECLASS_RAWMOUSE		0x02
/* A private console event */
#define IECLASS_EVENT			0x03
/* A Pointer Position report */
#define IECLASS_POINTERPOS		0x04
/* A timer event */
#define IECLASS_TIMER			0x06
/* select button pressed down over a Gadget (address in ie_EventAddress) */
#define IECLASS_GADGETDOWN		0x07
/* select button released over the same Gadget (address in ie_EventAddress) */
#define IECLASS_GADGETUP		0x08
/* some Requester activity has taken place.  See Codes REQCLEAR and REQSET */
#define IECLASS_REQUESTER		0x09
/* this is a Menu Number transmission (Menu number is in ie_Code) */
#define IECLASS_MENULIST		0x0A
/* User has selected the active Window's Close Gadget */
#define IECLASS_CLOSEWINDOW		0x0B
/* this Window has a new size */
#define IECLASS_SIZEWINDOW		0x0C
/* the Window pointed to by ie_EventAddress needs to be refreshed */
#define IECLASS_REFRESHWINDOW		0x0D
/* new preferences are available */
#define IECLASS_NEWPREFS		0x0E
/* the disk has been removed */
#define IECLASS_DISKREMOVED		0x0F
/* the disk has been inserted */
#define IECLASS_DISKINSERTED		0x10
/* the window is about to be been made active */
#define IECLASS_ACTIVEWINDOW		0x11
/* the window is about to be made inactive */
#define IECLASS_INACTIVEWINDOW		0x12
/* extended-function pointer position report (V36) */
#define IECLASS_NEWPOINTERPOS		0x13
/* Help key report during Menu session (V36) */
#define IECLASS_MENUHELP		0x14
/* the Window has been modified with move, size, zoom, or change (V36) */
#define	IECLASS_CHANGEWINDOW		0x15

/* the last class */
#define IECLASS_MAX			0x15

/*  --- InputEvent.ie_SubClass --- */
/*  IECLASS_NEWPOINTERPOS */
/*	like IECLASS_POINTERPOS */
#define IESUBCLASS_COMPATIBLE	0x00
/*	ie_EventAddress points to struct IEPointerPixel */
#define IESUBCLASS_PIXEL	0x01
/*	ie_EventAddress points to struct IEPointerTablet */
#define IESUBCLASS_TABLET	0x02

/* pointed to by ie_EventAddress for IECLASS_NEWPOINTERPOS,
 * and IESUBCLASS_PIXEL.
 *
 * You specify a screen and pixel coordinates in that screen
 * at which you'd like the mouse to be positioned.
 * Intuition will try to oblige, but there will be restrictions
 * to positioning the pointer over offscreen pixels.
 *
 * IEQUALIFIER_RELATIVEMOUSE is supported for IESUBCLASS_PIXEL.
 */
struct IEPointerPixel	{
    struct Screen	*iepp_Screen;	/* pointer to an open screen */
    struct {				/* pixel coordinates in iepp_Screen */
    WORD	X;
    WORD	Y;
    }			iepp_Position;
};

/* pointed to by ie_EventAddress for IECLASS_NEWPOINTERPOS,
 * and IESUBCLASS_TABLET.
 *
 * You specify a range of values and a value within the range
 * independently for each of X and Y (the minimum value of
 * the ranges is always normalized to 0).
 *
 * Intuition will position the mouse proportionally within its
 * natural mouse position rectangle limits.
 *
 * IEQUALIFIER_RELATIVEMOUSE is not supported for IESUBCLASS_TABLET.
 */
struct IEPointerTablet	{
    struct {
    UWORD	X;
    UWORD	Y;
    }			iept_Range;	/* 0 is min, these are max	*/
    struct {
    UWORD	X;
    UWORD	Y;
    }			iept_Value;	/* between 0 and iept_Range	*/

    WORD		iept_Pressure;	/* -128 to 127 (unused, set to 0)  */
};

/*  --- InputEvent.ie_Code --- */
/*  IECLASS_RAWKEY */
#define IECODE_UP_PREFIX		0x80
#define IECODE_KEY_CODE_FIRST		0x00
#define IECODE_KEY_CODE_LAST		0x77
#define IECODE_COMM_CODE_FIRST		0x78
#define IECODE_COMM_CODE_LAST		0x7F

/*  IECLASS_ANSI */
#define IECODE_C0_FIRST			0x00
#define IECODE_C0_LAST			0x1F
#define IECODE_ASCII_FIRST		0x20
#define IECODE_ASCII_LAST		0x7E
#define IECODE_ASCII_DEL		0x7F
#define IECODE_C1_FIRST			0x80
#define IECODE_C1_LAST			0x9F
#define IECODE_LATIN1_FIRST		0xA0
#define IECODE_LATIN1_LAST		0xFF

/*  IECLASS_RAWMOUSE */
#define IECODE_LBUTTON			0x68	/* also uses IECODE_UP_PREFIX */
#define IECODE_RBUTTON			0x69
#define IECODE_MBUTTON			0x6A
#define IECODE_NOBUTTON			0xFF

/*  IECLASS_EVENT (V36) */
#define IECODE_NEWACTIVE		0x01	/* new active input window */
#define IECODE_NEWSIZE			0x02	/* resize of window */
#define IECODE_REFRESH			0x03	/* refresh of window */

/*  IECLASS_REQUESTER */
/*	broadcast when the first Requester (not subsequent ones) opens up in */
/*	the Window */
#define IECODE_REQSET			0x01
/*	broadcast when the last Requester clears out of the Window */
#define IECODE_REQCLEAR			0x00

/*  --- InputEvent.ie_Qualifier --- */
#define IEQUALIFIER_LSHIFT		0x0001
#define IEQUALIFIER_RSHIFT		0x0002
#define IEQUALIFIER_CAPSLOCK		0x0004
#define IEQUALIFIER_CONTROL		0x0008
#define IEQUALIFIER_LALT		0x0010
#define IEQUALIFIER_RALT		0x0020
#define IEQUALIFIER_LCOMMAND		0x0040
#define IEQUALIFIER_RCOMMAND		0x0080
#define IEQUALIFIER_NUMERICPAD		0x0100
#define IEQUALIFIER_REPEAT		0x0200
#define IEQUALIFIER_INTERRUPT		0x0400
#define IEQUALIFIER_MULTIBROADCAST	0x0800
#define IEQUALIFIER_MIDBUTTON		0x1000
#define IEQUALIFIER_RBUTTON		0x2000
#define IEQUALIFIER_LEFTBUTTON		0x4000
#define IEQUALIFIER_RELATIVEMOUSE	0x8000

#define IEQUALIFIERB_LSHIFT		0
#define IEQUALIFIERB_RSHIFT		1
#define IEQUALIFIERB_CAPSLOCK		2
#define IEQUALIFIERB_CONTROL		3
#define IEQUALIFIERB_LALT		4
#define IEQUALIFIERB_RALT		5
#define IEQUALIFIERB_LCOMMAND		6
#define IEQUALIFIERB_RCOMMAND		7
#define IEQUALIFIERB_NUMERICPAD		8
#define IEQUALIFIERB_REPEAT		9
#define IEQUALIFIERB_INTERRUPT		10
#define IEQUALIFIERB_MULTIBROADCAST	11
#define IEQUALIFIERB_MIDBUTTON		12
#define IEQUALIFIERB_RBUTTON		13
#define IEQUALIFIERB_LEFTBUTTON		14
#define IEQUALIFIERB_RELATIVEMOUSE	15

/*----- InputEvent -------------------------------------------------*/

struct InputEvent {
    struct  InputEvent *ie_NextEvent;	/* the chronologically next event */
    UBYTE   ie_Class;			/* the input event class */
    UBYTE   ie_SubClass;		/* optional subclass of the class */
    UWORD   ie_Code;			/* the input event code */
    UWORD   ie_Qualifier;		/* qualifiers in effect for the event*/
    union {
    struct {
        WORD    ie_x;		/* the pointer position for the event*/
        WORD    ie_y;
    } ie_xy;
    APTR	ie_addr;		/* the event address */
    struct {
        UBYTE   ie_prev1DownCode;	/* previous down keys for dead */
        UBYTE   ie_prev1DownQual;	/*   key translation: the ie_Code */
        UBYTE   ie_prev2DownCode;	/*   & low byte of ie_Qualifier for */
        UBYTE   ie_prev2DownQual;	/*   last & second last down keys */
    } ie_dead;
    } ie_position;
    struct timeval ie_TimeStamp;	/* the system tick at the event */
};

#define	ie_X			ie_position.ie_xy.ie_x
#define	ie_Y			ie_position.ie_xy.ie_y
#define	ie_EventAddress		ie_position.ie_addr
#define	ie_Prev1DownCode	ie_position.ie_dead.ie_prev1DownCode
#define	ie_Prev1DownQual	ie_position.ie_dead.ie_prev1DownQual
#define	ie_Prev2DownCode	ie_position.ie_dead.ie_prev2DownCode
#define	ie_Prev2DownQual	ie_position.ie_dead.ie_prev2DownQual

#endif	/* DEVICES_INPUTEVENT_H */


Includes/devices/printer.h

#ifndef     DEVICES_PRINTER_H
#define     DEVICES_PRINTER_H
/*
**	$Filename: devices/printer.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.7 $
**	$Date: 90/07/26 $
**
**	printer.device structure definitions
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef  EXEC_TYPES_H
#include "exec/types.h"
#endif

#ifndef  EXEC_NODES_H
#include "exec/nodes.h"
#endif

#ifndef  EXEC_LISTS_H
#include "exec/lists.h"
#endif

#ifndef  EXEC_PORTS_H
#include "exec/ports.h"
#endif

#define  PRD_RAWWRITE	   (CMD_NONSTD+0)
#define  PRD_PRTCOMMAND    (CMD_NONSTD+1)
#define  PRD_DUMPRPORT	   (CMD_NONSTD+2)
#define  PRD_QUERY	   (CMD_NONSTD+3)

/* printer command definitions */

#define aRIS	 0  /* ESCc  reset		      ISO */
#define aRIN	 1  /* ESC#1 initialize	      +++ */
#define aIND	 2  /* ESCD  lf		      ISO */
#define aNEL	 3  /* ESCE  return,lf		      ISO */
#define aRI	 4  /* ESCM  reverse lf	      ISO */

#define aSGR0	 5  /* ESC[0m normal char set	      ISO */
#define aSGR3	 6  /* ESC[3m italics on	      ISO */
#define aSGR23	 7  /* ESC[23m italics off	      ISO */
#define aSGR4	 8  /* ESC[4m underline on	      ISO */
#define aSGR24	 9  /* ESC[24m underline off	      ISO */
#define aSGR1	10  /* ESC[1m boldface on	      ISO */
#define aSGR22	11  /* ESC[22m boldface off	      ISO */
#define aSFC	12  /* SGR30-39  set foreground color ISO */
#define aSBC	13  /* SGR40-49  set background color ISO */

#define aSHORP0 14  /* ESC[0w normal pitch	      DEC */
#define aSHORP2 15  /* ESC[2w elite on		      DEC */
#define aSHORP1 16  /* ESC[1w elite off	      DEC */
#define aSHORP4 17  /* ESC[4w condensed fine on       DEC */
#define aSHORP3 18  /* ESC[3w condensed off	      DEC */
#define aSHORP6 19  /* ESC[6w enlarged on	      DEC */
#define aSHORP5 20  /* ESC[5w enlarged off	      DEC */

#define aDEN6	21  /* ESC[6"z shadow print on	      DEC (sort of) */
#define aDEN5	22  /* ESC[5"z shadow print off       DEC */
#define aDEN4	23  /* ESC[4"z doublestrike on	      DEC */
#define aDEN3	24  /* ESC[3"z doublestrike off       DEC */
#define aDEN2	25  /* ESC[2"z	NLQ on		      DEC */
#define aDEN1	26  /* ESC[1"z	NLQ off	      DEC */

#define aSUS2	27  /* ESC[2v superscript on	      +++ */
#define aSUS1	28  /* ESC[1v superscript off	      +++ */
#define aSUS4	29  /* ESC[4v subscript on	      +++ */
#define aSUS3	30  /* ESC[3v subscript off	      +++ */
#define aSUS0	31  /* ESC[0v normalize the line      +++ */
#define aPLU	32  /* ESCL  partial line up	      ISO */
#define aPLD	33  /* ESCK  partial line down	      ISO */

#define aFNT0	34  /* ESC(B US char set	or Typeface  0 (default) */
#define aFNT1	35  /* ESC(R French char set	or Typeface  1 */
#define aFNT2	36  /* ESC(K German char set	or Typeface  2 */
#define aFNT3	37  /* ESC(A UK char set	or Typeface  3 */
#define aFNT4	38  /* ESC(E Danish I char set	or Typeface  4 */
#define aFNT5	39  /* ESC(H Sweden char set	or Typeface  5 */
#define aFNT6	40  /* ESC(Y Italian char set	or Typeface  6 */
#define aFNT7	41  /* ESC(Z Spanish char set	or Typeface  7 */
#define aFNT8	42  /* ESC(J Japanese char set	or Typeface  8 */
#define aFNT9	43  /* ESC(6 Norweign char set	or Typeface  9 */
#define aFNT10	44  /* ESC(C Danish II char set or Typeface 10 */

/*
    Suggested typefaces are:

     0 - default typeface.
     1 - Line Printer or equiv.
     2 - Pica or equiv.
     3 - Elite or equiv.
     4 - Helvetica or equiv.
     5 - Times Roman or equiv.
     6 - Gothic or equiv.
     7 - Script or equiv.
     8 - Prestige or equiv.
     9 - Caslon or equiv.
    10 - Orator or equiv.
*/

#define aPROP2	45  /* ESC[2p  proportional on	      +++ */
#define aPROP1	46  /* ESC[1p  proportional off       +++ */
#define aPROP0	47  /* ESC[0p  proportional clear     +++ */
#define aTSS	48  /* ESC[n E set proportional offset ISO */
#define aJFY5	49  /* ESC[5 F auto left justify      ISO */
#define aJFY7	50  /* ESC[7 F auto right justify     ISO */
#define aJFY6	51  /* ESC[6 F auto full justify      ISO */
#define aJFY0	52  /* ESC[0 F auto justify off       ISO */
#define aJFY3	53  /* ESC[3 F letter space (justify) ISO (special) */
#define aJFY1	54  /* ESC[1 F word fill(auto center) ISO (special) */

#define aVERP0	55  /* ESC[0z  1/8" line spacing      +++ */
#define aVERP1	56  /* ESC[1z  1/6" line spacing      +++ */
#define aSLPP	57  /* ESC[nt  set form length n      DEC */
#define aPERF	58  /* ESC[nq  perf skip n (n>0)      +++ */
#define aPERF0	59  /* ESC[0q  perf skip off	      +++ */

#define aLMS	60  /* ESC#9   Left margin set	      +++ */
#define aRMS	61  /* ESC#0   Right margin set       +++ */
#define aTMS	62  /* ESC#8   Top margin set	      +++ */
#define aBMS	63  /* ESC#2   Bottom marg set	      +++ */
#define aSTBM	64  /* ESC[Pn1;Pn2r  T&B margins      DEC */
#define aSLRM	65  /* ESC[Pn1;Pn2s  L&R margin       DEC */
#define aCAM	66  /* ESC#3   Clear margins	      +++ */

#define aHTS	67  /* ESCH    Set horiz tab	      ISO */
#define aVTS	68  /* ESCJ    Set vertical tabs      ISO */
#define aTBC0	69  /* ESC[0g  Clr horiz tab	      ISO */
#define aTBC3	70  /* ESC[3g  Clear all h tab	      ISO */
#define aTBC1	71  /* ESC[1g  Clr vertical tabs      ISO */
#define aTBC4	72  /* ESC[4g  Clr all v tabs	      ISO */
#define aTBCALL 73  /* ESC#4   Clr all h & v tabs     +++ */
#define aTBSALL 74  /* ESC#5   Set default tabs       +++ */
#define aEXTEND 75  /* ESC[Pn"x extended commands     +++ */

#define aRAW	76	/* ESC[Pn"r	Next 'Pn' chars are raw +++ */

struct IOPrtCmdReq {
    struct  Message io_Message;
    struct  Device  *io_Device;     /* device node pointer  */
    struct  Unit    *io_Unit;	    /* unit (driver private)*/
    UWORD   io_Command;	    /* device command */
    UBYTE   io_Flags;
    BYTE    io_Error;		    /* error or warning num */
    UWORD   io_PrtCommand;	    /* printer command */
    UBYTE   io_Parm0;		    /* first command parameter */
    UBYTE   io_Parm1;		    /* second command parameter */
    UBYTE   io_Parm2;		    /* third command parameter */
    UBYTE   io_Parm3;		    /* fourth command parameter */
};

struct IODRPReq {
    struct  Message io_Message;
    struct  Device  *io_Device;     /* device node pointer  */
    struct  Unit    *io_Unit;	    /* unit (driver private)*/
    UWORD   io_Command;	    /* device command */
    UBYTE   io_Flags;
    BYTE    io_Error;		    /* error or warning num */
    struct  RastPort *io_RastPort;  /* raster port */
    struct  ColorMap *io_ColorMap;  /* color map */
    ULONG   io_Modes;		    /* graphics viewport modes */
    UWORD   io_SrcX;		    /* source x origin */
    UWORD   io_SrcY;		    /* source y origin */
    UWORD   io_SrcWidth;	    /* source x width */
    UWORD   io_SrcHeight;	    /* source x height */
    LONG    io_DestCols;	    /* destination x width */
    LONG    io_DestRows;	    /* destination y height */
    UWORD   io_Special;	    /* option flags */
};

#define SPECIAL_MILCOLS		0x0001	/* DestCols specified in 1/1000" */
#define SPECIAL_MILROWS		0x0002	/* DestRows specified in 1/1000" */
#define SPECIAL_FULLCOLS	0x0004	/* make DestCols maximum possible */
#define SPECIAL_FULLROWS	0x0008	/* make DestRows maximum possible */
#define SPECIAL_FRACCOLS	0x0010	/* DestCols is fraction of FULLCOLS */
#define SPECIAL_FRACROWS	0x0020	/* DestRows is fraction of FULLROWS */
#define SPECIAL_CENTER		0x0040	/* center image on paper */
#define SPECIAL_ASPECT		0x0080	/* ensure correct aspect ratio */
#define SPECIAL_DENSITY1	0x0100	/* lowest resolution (dpi) */
#define SPECIAL_DENSITY2	0x0200	/* next res */
#define SPECIAL_DENSITY3	0x0300	/* next res */
#define SPECIAL_DENSITY4	0x0400	/* next res */
#define SPECIAL_DENSITY5	0x0500	/* next res */
#define SPECIAL_DENSITY6	0x0600	/* next res */
#define SPECIAL_DENSITY7	0x0700	/* highest res */
#define SPECIAL_NOFORMFEED	0x0800	/* don't eject paper on gfx prints */
#define SPECIAL_TRUSTME		0x1000	/* don't reset on gfx prints */
/*
    Compute print size, set 'io_DestCols' and 'io_DestRows' in the calling
    program's 'IODRPReq' structure and exit, DON'T PRINT.  This allows the
    calling program to see what the final print size would be in printer
    pixels.  Note that it modifies the 'io_DestCols' and 'io_DestRows'
    fields of your 'IODRPReq' structure.  Also, set the print density and
    update the 'MaxXDots', 'MaxYDots', 'XDotsInch', and 'YDotsInch' fields
    of the 'PrinterExtendedData' structure.
*/
#define SPECIAL_NOPRINT		0x2000	/* see above */

#define PDERR_NOERR		0	/* clean exit, no errors */
#define PDERR_CANCEL		1	/* user cancelled print */
#define PDERR_NOTGRAPHICS	2	/* printer cannot output graphics */
#define PDERR_INVERTHAM		3	/* OBSOLETE */
#define PDERR_BADDIMENSION	4	/* print dimensions illegal */
#define PDERR_DIMENSIONOVFLOW	5	/* OBSOLETE */
#define PDERR_INTERNALMEMORY	6	/* no memory for internal variables */
#define PDERR_BUFFERMEMORY	7	/* no memory for print buffer */
/*
    Note : this is an internal error that can be returned from the render
    function to the printer device.  It is NEVER returned to the user.
    If the printer device sees this error it converts it 'PDERR_NOERR'
    and exits gracefully.  Refer to the document on
    'How to Write a Graphics Printer Driver' for more info.
*/
#define PDERR_TOOKCONTROL	8	/* Took control in case 0 of render */

/* internal use */
#define SPECIAL_DENSITYMASK	0x0700	/* masks out density values */
#define SPECIAL_DIMENSIONSMASK \
    (SPECIAL_MILCOLS|SPECIAL_MILROWS|SPECIAL_FULLCOLS|SPECIAL_FULLROWS\
    |SPECIAL_FRACCOLS|SPECIAL_FRACROWS|SPECIAL_ASPECT)
#endif


Includes/devices/timer.h

#ifndef DEVICES_TIMER_H
#define DEVICES_TIMER_H 1
/*
**	$Filename: devices/timer.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.16 $
**	$Date: 91/01/25 $
**
**	Timer device name and useful definitions.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**		All Rights Reserved
*/

#include <exec/types.h>
#include <exec/io.h>

/* unit defintions */
#define UNIT_MICROHZ	0
#define UNIT_VBLANK	1
#define UNIT_ECLOCK	2
#define UNIT_WAITUNTIL	3
#define	UNIT_WAITECLOCK	4

#define TIMERNAME	"timer.device"

struct timeval {
    ULONG tv_secs;
    ULONG tv_micro;
};

struct EClockVal {
    ULONG ev_hi;
    ULONG ev_lo;
};

struct timerequest {
    struct IORequest tr_node;
    struct timeval tr_time;
};

/* IO_COMMAND to use for adding a timer */
#define TR_ADDREQUEST	CMD_NONSTD
#define TR_GETSYSTIME	(CMD_NONSTD+1)
#define TR_SETSYSTIME	(CMD_NONSTD+2)

#endif /* DEVICES_TIMER_H */


Includes/devices/console.i

    IFND	DEVICES_CONSOLE_I
DEVICES_CONSOLE_I	SET	1
**
**	$Filename: devices/console.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.10 $
**	$Date: 90/11/07 $
**
**	Console device command definitions
**
**	(C) Copyright 1986-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND	EXEC_TYPES_I
    INCLUDE	"exec/types.i"
    ENDC

    IFND	EXEC_IO_I
    INCLUDE	"exec/io.i"
    ENDC	; EXEC_IO_I

******* Console commands *******
    DEVINIT

    DEVCMD	CD_ASKKEYMAP
    DEVCMD	CD_SETKEYMAP
    DEVCMD	CD_ASKDEFAULTKEYMAP
    DEVCMD	CD_SETDEFAULTKEYMAP

******* SGR parameters

SGR_PRIMARY	EQU	0
SGR_BOLD	EQU	1
SGR_ITALIC	EQU	3
SGR_UNDERSCORE	EQU	4
SGR_NEGATIVE	EQU	7

SGR_NORMAL	EQU	22	; default foreground color, not bold
SGR_NOTITALIC	EQU	23
SGR_NOTUNDERSCORE EQU	24
SGR_POSITIVE	EQU	27

*  these names refer to the ANSI standard, not the implementation
SGR_BLACK	EQU	30
SGR_RED		EQU	31
SGR_GREEN	EQU	32
SGR_YELLOW	EQU	33
SGR_BLUE	EQU	34
SGR_MAGENTA	EQU	35
SGR_CYAN	EQU	36
SGR_WHITE	EQU	37
SGR_DEFAULT	EQU	39

SGR_BLACKBG	EQU	40
SGR_REDBG	EQU	41
SGR_GREENBG	EQU	42
SGR_YELLOWBG	EQU	43
SGR_BLUEBG	EQU	44
SGR_MAGENTABG	EQU	45
SGR_CYANBG	EQU	46
SGR_WHITEBG	EQU	47
SGR_DEFAULTBG	EQU	49

*  these names refer to the implementation, they are the preferred
*  names for use with the Amiga console device.
SGR_CLR0	EQU	30
SGR_CLR1	EQU	31
SGR_CLR2	EQU	32
SGR_CLR3	EQU	33
SGR_CLR4	EQU	34
SGR_CLR5	EQU	35
SGR_CLR6	EQU	36
SGR_CLR7	EQU	37

SGR_CLR0BG	EQU	40
SGR_CLR1BG	EQU	41
SGR_CLR2BG	EQU	42
SGR_CLR3BG	EQU	43
SGR_CLR4BG	EQU	44
SGR_CLR5BG	EQU	45
SGR_CLR6BG	EQU	46
SGR_CLR7BG	EQU	47

******	 DSR parameters

DSR_CPR		EQU	6

******	 CTC parameters
CTC_HSETTAB	EQU	0
CTC_HCLRTAB	EQU	2
CTC_HCLRTABSALL	EQU	5

******	 TBC parameters
TBC_HCLRTAB	EQU	0
TBC_HCLRTABSALL	EQU	3

******	 SM and RM parameters
M_LNM		EQU	20	; linefeed newline mode
M_ASM	MACRO
        DC.B	'>1'	; auto scroll mode
    ENDM
M_AWM	MACRO
        DC.B	'?7'	; auto wrap mode
    ENDM

    ENDC	; DEVICES_CONSOLE_I


Includes/devices/inputevent.i

    IFND	DEVICES_INPUTEVENT_I
DEVICES_INPUTEVENT_I	SET	1
**
**	$Filename: devices/inputevent.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.6 $
**	$Date: 91/01/22 $
**
**	input event definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND	 DEVICES_TIMER_I
    INCLUDE  "devices/timer.i"
    ENDC

;------ constants ----------------------------------------------------

;   --- InputEvent.ie_Class ---
; A NOP input event
IECLASS_NULL			EQU	$00
; A raw keycode from the keyboard device
IECLASS_RAWKEY			EQU	$01
; A raw mouse report from the game port device
IECLASS_RAWMOUSE		EQU	$02
; A private console event
IECLASS_EVENT			EQU	$03
; A Pointer Position report
IECLASS_POINTERPOS		EQU	$04
; A timer event
IECLASS_TIMER			EQU	$06
; select button pressed down over a Gadget (address in ie_EventAddress)
IECLASS_GADGETDOWN		EQU	$07
; select button released over the same Gadget (address in ie_EventAddress)
IECLASS_GADGETUP		EQU	$08
; some Requester activity has taken place.  See Codes REQCLEAR and REQSET
IECLASS_REQUESTER		EQU	$09
; this is a Menu Number transmission (Menu number is in ie_Code)
IECLASS_MENULIST		EQU	$0A
; User has selected the active Window's Close Gadget
IECLASS_CLOSEWINDOW		EQU	$0B
; this Window has a new size
IECLASS_SIZEWINDOW		EQU	$0C
; the Window pointed to by ie_EventAddress needs to be refreshed
IECLASS_REFRESHWINDOW		EQU	$0D
; new preferences are available
IECLASS_NEWPREFS		EQU	$0E
; the disk has been removed
IECLASS_DISKREMOVED		EQU	$0F
; the disk has been inserted
IECLASS_DISKINSERTED		EQU	$10
; the window is about to be been made active
IECLASS_ACTIVEWINDOW		EQU	$11
; the window is about to be made inactive
IECLASS_INACTIVEWINDOW		EQU	$12
; extended-function pointer position report (V36)
IECLASS_NEWPOINTERPOS		EQU	$13
; Help key report during Menu session (V36)
IECLASS_MENUHELP		EQU	$14
; the Window has been modified with move, size, zoom, or change (V36)
IECLASS_CHANGEWINDOW		EQU	$15

; the last class
IECLASS_MAX			EQU	$15

;   --- InputEvent.ie_SubClass ---
;  IECLASS_NEWPOINTERPOS
;	like IECLASS_POINTERPOS
IESUBCLASS_COMPATIBLE		EQU	$00
;	ie_EventAddress points to struct IEPointerPixel
IESUBCLASS_PIXEL		EQU	$01
;	ie_EventAddress points to struct IEPointerTablet
IESUBCLASS_TABLET		EQU	$02

; pointed to by ie_EventAddress for IECLASS_NEWPOINTERPOS,
; and IESUBCLASS_PIXEL.
;
; You specify a screen and pixel coordinates in that screen
; at which you'd like the mouse to be positioned.
; Intuition will try to oblige, but there will be restrictions
; to positioning the pointer over offscreen pixels.
;
; IEQUALIFIER_RELATIVEMOUSE is supported for IESUBCLASS_PIXEL.

 STRUCTURE	IEPointerPixel,0
    APTR    iepp_Screen		; pointer to an open screen
    LABEL   iepp_Position	; pixel coordinates in iepp_Screen
    WORD    iepp_PositionX
    WORD    iepp_PositionY
    LABEL   IEPointerPixel_SIZEOF

; pointed to by ie_EventAddress for IECLASS_NEWPOINTERPOS,
; and IESUBCLASS_TABLET.
;
; You specify a range of values and a value within the range
; independently for each of X and Y (the minimum value of
; the ranges is always normalized to 0).
;
; Intuition will position the mouse proportionally within its
; natural mouse position rectangle limits.
;
; IEQUALIFIER_RELATIVEMOUSE is not supported for IESUBCLASS_TABLET.

 STRUCTURE	IEPointerTablet,0
    LABEL   iept_Range		; 0 is min, these are max
    UWORD   iept_RangeX
    UWORD   iept_RangeY
    LABEL   iept_Value		; between 0 and iept_Range
    UWORD   iept_ValueX
    UWORD   iept_ValueY
    WORD    iept_Pressure	; -128 to 127 (unused, set to 0)
    LABEL   IEPointerTablet_SIZEOF

;   --- InputEvent.ie_Code ---
;   IECLASS_RAWKEY
IECODE_UP_PREFIX		EQU	$80
IECODEB_UP_PREFIX		EQU	7
IECODE_KEY_CODE_FIRST		EQU	$00
IECODE_KEY_CODE_LAST		EQU	$77
IECODE_COMM_CODE_FIRST		EQU	$78
IECODE_COMM_CODE_LAST		EQU	$7F

;   IECLASS_ANSI
IECODE_C0_FIRST			EQU	$00
IECODE_C0_LAST			EQU	$1F
IECODE_ASCII_FIRST		EQU	$20
IECODE_ASCII_LAST		EQU	$7E
IECODE_ASCII_DEL		EQU	$7F
IECODE_C1_FIRST			EQU	$80
IECODE_C1_LAST			EQU	$9F
IECODE_LATIN1_FIRST		EQU	$A0
IECODE_LATIN1_LAST		EQU	$FF

;   IECLASS_RAWMOUSE
IECODE_LBUTTON			EQU	$68	; also uses IECODE_UP_PREFIX
IECODE_RBUTTON			EQU	$69	;
IECODE_MBUTTON			EQU	$6A	;
IECODE_NOBUTTON			EQU	$FF

;   IECLASS_EVENT (V36)
IECODE_NEWACTIVE		EQU	$01	; new active input window
IECODE_NEWSIZE			EQU	$02	; resize of specified window
IECODE_REFRESH			EQU	$03	; refresh of specified window

;   IECLASS_REQUESTER Codes
;	broadcast when the first Requester (not subsequent ones) opens in
;	the Window
IECODE_REQSET			EQU	$01
;	broadcast when the last Requester clears out of the Window
IECODE_REQCLEAR			EQU	$00

*   --- InputEvent.ie_Qualifier ---
IEQUALIFIER_LSHIFT		EQU	$0001
IEQUALIFIER_RSHIFT		EQU	$0002
IEQUALIFIER_CAPSLOCK		EQU	$0004
IEQUALIFIER_CONTROL		EQU	$0008
IEQUALIFIER_LALT		EQU	$0010
IEQUALIFIER_RALT		EQU	$0020
IEQUALIFIER_LCOMMAND		EQU	$0040
IEQUALIFIER_RCOMMAND		EQU	$0080
IEQUALIFIER_NUMERICPAD		EQU	$0100
IEQUALIFIER_REPEAT		EQU	$0200
IEQUALIFIER_INTERRUPT		EQU	$0400
IEQUALIFIER_MULTIBROADCAST	EQU	$0800
IEQUALIFIER_MIDBUTTON		EQU	$1000
IEQUALIFIER_RBUTTON		EQU	$2000
IEQUALIFIER_LEFTBUTTON		EQU	$4000
IEQUALIFIER_RELATIVEMOUSE	EQU	$8000

IEQUALIFIERB_LSHIFT		EQU	0
IEQUALIFIERB_RSHIFT		EQU	1
IEQUALIFIERB_CAPSLOCK		EQU	2
IEQUALIFIERB_CONTROL		EQU	3
IEQUALIFIERB_LALT		EQU	4
IEQUALIFIERB_RALT		EQU	5
IEQUALIFIERB_LCOMMAND		EQU	6
IEQUALIFIERB_RCOMMAND		EQU	7
IEQUALIFIERB_NUMERICPAD		EQU	8
IEQUALIFIERB_REPEAT		EQU	9
IEQUALIFIERB_INTERRUPT		EQU	10
IEQUALIFIERB_MULTIBROADCAST	EQU	11
IEQUALIFIERB_MIDBUTTON		EQU	12
IEQUALIFIERB_RBUTTON		EQU	13
IEQUALIFIERB_LEFTBUTTON		EQU	14
IEQUALIFIERB_RELATIVEMOUSE	EQU	15

;------ InputEvent ---------------------------------------------------

 STRUCTURE	InputEvent,0
    APTR    ie_NextEvent	; the chronologically next event
    UBYTE   ie_Class		; the input event class
    UBYTE   ie_SubClass		; optional subclass of the class
    UWORD   ie_Code		; the input event code
    UWORD   ie_Qualifier	; qualifiers in effect for the event
    LABEL   ie_EventAddress	; the event address
    LABEL   ie_X		; the pointer position for the event
    UBYTE   ie_Prev1DownCode	; previous down keys for dead key translation
    UBYTE   ie_Prev1DownQual
    LABEL   ie_Y
    UBYTE   ie_Prev2DownCode
    UBYTE   ie_Prev2DownQual
    STRUCT  ie_TimeStamp,TV_SIZE ; the system tick at the event
    LABEL   ie_SIZEOF

    ENDC	; DEVICES_INPUTEVENT_I


Includes/devices/printer.i

   IFND  DEVICES_PRINTER_I
DEVICES_PRINTER_I EQU	1
**
**	$Filename: devices/printer.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.7 $
**	$Date: 90/07/26 $
**
**	printer.device structure definitions
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
**

   IFND  EXEC_TYPES_I
   INCLUDE  "exec/types.i"
   ENDC

   IFND  EXEC_NODES_I
   INCLUDE  "exec/nodes.i"
   ENDC

   IFND  EXEC_LISTS_I
   INCLUDE  "exec/lists.i"
   ENDC

   IFND  EXEC_PORTS_I
   INCLUDE  "exec/ports.i"
   ENDC

   IFND  EXEC_IO_I
   INCLUDE  "exec/io.i"
   ENDC

   DEVINIT

   DEVCMD   PRD_RAWWRITE
   DEVCMD   PRD_PRTCOMMAND
   DEVCMD   PRD_DUMPRPORT
   DEVCMD   PRD_QUERY

;****** printer definitions
aRIS	 EQU	0 ; ESCc  reset		      ISO
aRIN	 EQU	1 ; ESC#1 initialize		      +++
aIND	 EQU	2 ; ESCD  lf			      ISO
aNEL	 EQU	3 ; ESCE  return,lf		      ISO
aRI	 EQU	4 ; ESCM  reverse lf		      ISO

aSGR0	 EQU	5 ; ESC[0m normal char set	      ISO
aSGR3	 EQU	6 ; ESC[3m italics on		      ISO
aSGR23	 EQU	7 ; ESC[23m italics off	      ISO
aSGR4	 EQU	8 ; ESC[4m underline on	      ISO
aSGR24	 EQU	9 ; ESC[24m underline off	      ISO
aSGR1	 EQU   10 ; ESC[1m boldface on		      ISO
aSGR22	 EQU   11 ; ESC[22m boldface off	      ISO
aSFC	 EQU   12 ; SGR30-39  set foreground color    ISO
aSBC	 EQU   13 ; SGR40-49  set background color    ISO

aSHORP0  EQU   14 ; ESC[0w normal pitch	      DEC
aSHORP2  EQU   15 ; ESC[2w elite on		      DEC
aSHORP1  EQU   16 ; ESC[1w elite off		      DEC
aSHORP4  EQU   17 ; ESC[4w condensed fine on	      DEC
aSHORP3  EQU   18 ; ESC[3w condensed off	      DEC
aSHORP6  EQU   19 ; ESC[6w enlarged on		      DEC
aSHORP5  EQU   20 ; ESC[5w enlarged off	      DEC

aDEN6	 EQU   21 ; ESC[6"z shadow print on           DEC (sort of)
aDEN5    EQU   22 ; ESC[5"z shadow print off	      DEC
aDEN4	 EQU   23 ; ESC[4"z doublestrike on           DEC
aDEN3    EQU   24 ; ESC[3"z doublestrike off	      DEC
aDEN2	 EQU   25 ; ESC[2"z  NLQ on                   DEC
aDEN1    EQU   26 ; ESC[1"z  NLQ off		      DEC

aSUS2	 EQU   27 ; ESC[2v superscript on	      +++
aSUS1	 EQU   28 ; ESC[1v superscript off	      +++
aSUS4	 EQU   29 ; ESC[4v subscript on	      +++
aSUS3	 EQU   30 ; ESC[3v subscript off	      +++
aSUS0	 EQU   31 ; ESC[0v normalize the line	      +++
aPLU	 EQU   32 ; ESCL  partial line up	      ISO
aPLD	 EQU   33 ; ESCK  partial line down	      ISO

aFNT0	 EQU   34 ; ESC(B US char set	     or Typeface  0 (default)
aFNT1	 EQU   35 ; ESC(R French char set    or Typeface  1
aFNT2	 EQU   36 ; ESC(K German char set    or Typeface  2
aFNT3	 EQU   37 ; ESC(A UK char set	     or Typeface  3
aFNT4	 EQU   38 ; ESC(E Danish I char set  or Typeface  4
aFNT5	 EQU   39 ; ESC(H Sweden char set    or Typeface  5
aFNT6	 EQU   40 ; ESC(Y Italian char set   or Typeface  6
aFNT7	 EQU   41 ; ESC(Z Spanish char set   or Typeface  7
aFNT8	 EQU   42 ; ESC(J Japanese char set  or Typeface  8
aFNT9	 EQU   43 ; ESC(6 Norweign char set  or Typeface  9
aFNT10	 EQU   44 ; ESC(C Danish II char set or Typeface 10

;	Suggested typefaces are:
;
;	 0 - default typeface.
;	 1 - Line Printer or equiv.
;	 2 - Pica or equiv.
;	 3 - Elite or equiv.
;	 4 - Helvetica or equiv.
;	 5 - Times Roman or equiv.
;	 6 - Gothic or equiv.
;	 7 - Script or equiv.
;	 8 - Prestige or equiv.
;	 9 - Caslon or equiv.
;	10 - Orator or equiv.
;

aPROP2	 EQU   45 ; ESC[2p  proportional on	      +++
aPROP1	 EQU   46 ; ESC[1p  proportional off	      +++
aPROP0	 EQU   47 ; ESC[0p  proportional clear	      +++
aTSS	 EQU   48 ; ESC[n E set proportional offset   ISO
aJFY5	 EQU   49 ; ESC[5 F auto left justify	      ISO
aJFY7	 EQU   50 ; ESC[7 F auto right justiy	      ISO
aJFY6	 EQU   51 ; ESC[6 F auto full justify	      ISO
aJFY0	 EQU   52 ; ESC[0 F auto justify off	      ISO
aJFY2	 EQU   53 ; ESC[2 F  word space(auto center)  ISO (special)
aJFY3	 EQU   54 ; ESC[3 F letter space (justify)    ISO (special)

aVERP0	 EQU   55 ; ESC[0z  1/8" line spacing         +++
aVERP1   EQU   56 ; ESC[1z  1/6" line spacing	      +++
aSLPP	 EQU   57 ; ESC[nt  set form length n	      DEC
aPERF	 EQU   58 ; ESC[nq  perf skip n (n>0)	      +++
aPERF0	 EQU   59 ; ESC[0q  perf skip off	      +++

aLMS	 EQU   60 ; ESC#9  Left margin set	      +++
aRMS	 EQU   61 ; ESC#0  Right margin set	      +++
aTMS	 EQU   62 ; ESC#8  Top margin set	      +++
aBMS	 EQU   63 ; ESC#2  Bottom marg set	      +++
aSTBM	 EQU   64 ; ESC[Pn1;Pn2r  T&B margins	      DEC
aSLRM	 EQU   65 ; ESC[Pn1;Pn2s  L&R margin	      DEC
aCAM	 EQU   66 ; ESC#3  Clear margins	      +++

aHTS	 EQU   67 ; ESCH    Set horiz tab	      ISO
aVTS	 EQU   68 ; ESCJ    Set vertical tabs	      ISO
aTBC0	 EQU   69 ; ESC[0g  Clr horiz tab	      ISO
aTBC3	 EQU   70 ; ESC[3g  Clear all h tab	      ISO
aTBC1	 EQU   71 ; ESC[1g  Clr vertical tabs	      ISO
aTBC4	 EQU   72 ; ESC[4g  Clr all v tabs	      ISO
aTBCALL  EQU   73 ; ESC#4   Clr all h & v tabs	      +++
aTBSALL  EQU   74 ; ESC#5   Set default tabs	      +++
aEXTEND  EQU   75 ; ESC[Pn"x extended commands        +++

aRAW     EQU   76 ; ESC[Pn"r Next 'Pn' chars are raw  +++

 STRUCTURE IOPrtCmdReq,IO_SIZE
    UWORD   io_PrtCommand  ; printer command
    UBYTE   io_Parm0	; first command parameter
    UBYTE   io_Parm1	; second command parameter
    UBYTE   io_Parm2	; third command parameter
    UBYTE   io_Parm3	; fourth command parameter
    LABEL   iopcr_SIZEOF

 STRUCTURE  IODRPReq,IO_SIZE
    APTR    io_RastPort    ; raster port
    APTR    io_ColorMap    ; color map
    ULONG   io_Modes	   ; graphics viewport modes
    UWORD   io_SrcX	   ; source x origin
    UWORD   io_SrcY	   ; source y origin
    UWORD   io_SrcWidth    ; source x width
    UWORD   io_SrcHeight   ; source x height
    LONG    io_DestCols    ; destination x width
    LONG    io_DestRows    ; destination y height
    UWORD   io_Special	   ; option flags
    LABEL   iodrpr_SIZEOF

SPECIAL_MILCOLS		EQU	$0001	; DestCols specified in 1/1000"
SPECIAL_MILROWS		EQU	$0002	; DestRows specified in 1/1000"
SPECIAL_FULLCOLS	EQU	$0004	; make DestCols maximum possible
SPECIAL_FULLROWS	EQU	$0008	; make DestRows maximum possible
SPECIAL_FRACCOLS	EQU	$0010	; DestCols is fraction of FULLCOLS
SPECIAL_FRACROWS	EQU	$0020	; DestRows is fraction of FULLROWS
SPECIAL_CENTER		EQU	$0040	; center image on paper
SPECIAL_ASPECT		EQU	$0080	; ensure correct aspect ratio
SPECIAL_DENSITY1	EQU	$0100	; lowest resolution (dpi)
SPECIAL_DENSITY2	EQU	$0200	; next res
SPECIAL_DENSITY3	EQU	$0300	; next res
SPECIAL_DENSITY4	EQU	$0400	; next res
SPECIAL_DENSITY5	EQU	$0500	; next res
SPECIAL_DENSITY6	EQU	$0600	; next res
SPECIAL_DENSITY7	EQU	$0700	; highest res
SPECIAL_NOFORMFEED	EQU	$0800	; don't eject paper after gfx prints
SPECIAL_TRUSTME		EQU	$1000	; don't reset on gfx prints
;
;	Compute print size, set 'io_DestCols' and 'io_DestRows' in the calling
;	program's 'IODRPReq' structure and exit, don't print.  This allows the
;	calling program to see what the final print size would be in printer
;	pixels.  Note that it modifies the 'io_DestCols' and 'io_DestRows'
;	fields of your 'IODRPReq' structure.  Also, set the print density and
;	update the 'MaxXDots', 'MaxYDots', 'XDotsInch', and 'YDotsInch' fields
;	of the 'PrinterExtendedData' structure.
;
SPECIAL_NOPRINT		EQU	$2000	; see above

PDERR_NOERR		EQU	0	; clean exit, no errors
PDERR_CANCEL		EQU	1	; user cancelled print
PDERR_NOTGRAPHICS	EQU	2	; printer cannot output graphics
PDERR_INVERTHAM		EQU	3	; OBSOLETE
PDERR_BADDIMENSION	EQU	4	; print dimensions illegal
PDERR_DIMENSIONOVFLOW	EQU	5	; OBSOLETE
PDERR_INTERNALMEMORY	EQU	6	; no memory for internal variables
PDERR_BUFFERMEMORY	EQU	7	; no memory for print buffer
;
;	Note : this is an internal error that can be returned from the render
;	function to the printer device.  It is NEVER returned to the user.
;	If the printer device sees this error it converts it 'PDERR_NOERR'
;	and exits gracefully.  Refer to the document on
;	'How to Write a Graphics Printer Driver' for more info.
;
PDERR_TOOKCONTROL	EQU	8	; I took control in case 0 of render

; internal use
SPECIAL_DENSITYMASK	EQU $0700	;  masks out density values
SPECIAL_DIMENSIONSMASK	EQU SPECIAL_MILCOLS!SPECIAL_MILROWS!SPECIAL_FULLCOLS!SPECIAL_FULLROWS!SPECIAL_FRACCOLS!SPECIAL_FRACROWS!SPECIAL_ASPECT

   ENDC


Includes/devices/timer.i

    IFND	DEVICES_TIMER_I
DEVICES_TIMER_I	SET	1
**
**	$Filename: devices/timer.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.10 $
**	$Date: 91/03/05 $
**
**	Timer device name and useful definitions.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**		All Rights Reserved
**

    IFND	EXEC_TYPES_I
    INCLUDE "exec/types.i"
    ENDC

    IFND	EXEC_IO_I
    INCLUDE "exec/io.i"
    ENDC

* unit defintions
UNIT_MICROHZ	EQU	0
UNIT_VBLANK	EQU	1
UNIT_ECLOCK	EQU	2
UNIT_WAITUNTIL	EQU	3
UNIT_WAITECLOCK	EQU	4

TIMERNAME	MACRO
        DC.B	'timer.device',0
        DS.W	0
        ENDM

 STRUCTURE TIMEVAL,0
    ULONG	TV_SECS
    ULONG	TV_MICRO
    LABEL	TV_SIZE

 STRUCTURE ECLOCKVAL,0
    ULONG	EV_HI
    ULONG	EV_LO
    LABEL	EV_SIZE

 STRUCTURE TIMEREQUEST,IO_SIZE
    STRUCT	IOTV_TIME,TV_SIZE
    LABEL	IOTV_SIZE

* IO_COMMAND to use for adding a timer
    DEVINIT
    DEVCMD	TR_ADDREQUEST
    DEVCMD	TR_GETSYSTIME
    DEVCMD	TR_SETSYSTIME

    ENDC	; DEVICES_TIMER_I


Includes/devices/conunit.h

#ifndef DEVICES_CONUNIT_H
#define DEVICES_CONUNIT_H
/*
**	$Filename: devices/conunit.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.15 $
**	$Date: 90/11/20 $
**
**	Console device unit definitions
**
**	(C) Copyright 1986-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef	EXEC_TYPES_H
#include	"exec/types.h"
#endif

#ifndef EXEC_PORTS_H
#include	"exec/ports.h"
#endif

#ifndef DEVICES_CONSOLE_H
#include	"devices/console.h"
#endif

#ifndef DEVICES_KEYMAP_H
#include	"devices/keymap.h"
#endif

#ifndef DEVICES_INPUTEVENT_H
#include	"devices/inputevent.h"
#endif

/* ----	console unit numbers for OpenDevice() */
#define	CONU_LIBRARY	-1	/* no unit, just fill in IO_DEVICE field */
#define	CONU_STANDARD	0	/* standard unmapped console */

/* ---- New unit numbers for OpenDevice() - (V36) */

#define	CONU_CHARMAP	1	/* bind character map to console */
#define	CONU_SNIPMAP	3	/* bind character map w/ snip to console */

/* ---- New flag defines for OpenDevice() - (V37) */

#define CONFLAG_DEFAULT			0
#define CONFLAG_NODRAW_ON_NEWSIZE	1

#define	PMB_ASM		(M_LNM+1)	/* internal storage bit for AS flag */
#define	PMB_AWM		(PMB_ASM+1)	/* internal storage bit for AW flag */
#define	MAXTABS		80

struct	ConUnit {
    struct  MsgPort cu_MP;
    /* ---- read only variables */
    struct  Window *cu_Window;	/* intuition window bound to this unit */
    WORD    cu_XCP;		/* character position */
    WORD    cu_YCP;
    WORD    cu_XMax;		/* max character position */
    WORD    cu_YMax;
    WORD    cu_XRSize;		/* character raster size */
    WORD    cu_YRSize;
    WORD    cu_XROrigin;	/* raster origin */
    WORD    cu_YROrigin;
    WORD    cu_XRExtant;	/* raster maxima */
    WORD    cu_YRExtant;
    WORD    cu_XMinShrink;	/* smallest area intact from resize process */
    WORD    cu_YMinShrink;
    WORD    cu_XCCP;		/* cursor position */
    WORD    cu_YCCP;

    /* ---- read/write variables (writes must must be protected) */
    /* ---- storage for AskKeyMap and SetKeyMap */
    struct  KeyMap cu_KeyMapStruct;
    /* ---- tab stops */
    UWORD   cu_TabStops[MAXTABS]; /* 0 at start, 0xffff at end of list */

    /* ---- console rastport attributes */
    BYTE    cu_Mask;
    BYTE    cu_FgPen;
    BYTE    cu_BgPen;
    BYTE    cu_AOLPen;
    BYTE    cu_DrawMode;
    BYTE    cu_Obsolete1;	/* was cu_AreaPtSz -- not used in V36 */
    APTR    cu_Obsolete2;	/* was cu_AreaPtrn -- not used in V36 */
    UBYTE   cu_Minterms[8];	/* console minterms */
    struct  TextFont *cu_Font;
    UBYTE   cu_AlgoStyle;
    UBYTE   cu_TxFlags;
    UWORD   cu_TxHeight;
    UWORD   cu_TxWidth;
    UWORD   cu_TxBaseline;
    WORD    cu_TxSpacing;

    /* ---- console MODES and RAW EVENTS switches */
    UBYTE   cu_Modes[(PMB_AWM+7)/8];	/* one bit per mode */
    UBYTE   cu_RawEvents[(IECLASS_MAX+8)/8];
};

#endif	/* DEVICES_CONUNIT_H */


Includes/devices/keyboard.h

#ifndef DEVICES_KEYBOARD_H
#define DEVICES_KEYBOARD_H
/*
**	$Filename: devices/keyboard.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.0 $
**	$Date: 90/05/01 $
**
**	Keyboard device command definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef	 EXEC_IO_H
#include "exec/io.h"
#endif

#define	 KBD_READEVENT	      (CMD_NONSTD+0)
#define	 KBD_READMATRIX	      (CMD_NONSTD+1)
#define	 KBD_ADDRESETHANDLER  (CMD_NONSTD+2)
#define	 KBD_REMRESETHANDLER  (CMD_NONSTD+3)
#define	 KBD_RESETHANDLERDONE (CMD_NONSTD+4)

#endif	/* DEVICES_KEYBOARD_H */


Includes/devices/prtbase.h

#ifndef  DEVICES_PRTBASE_H
#define  DEVICES_PRTBASE_H
/*
**	$Filename: devices/prtbase.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.10 $
**	$Date: 90/11/02 $
**
**	printer.device base structure definitions
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef  EXEC_TYPES_H
#include "exec/types.h"
#endif
#ifndef  EXEC_NODES_H
#include "exec/nodes.h"
#endif
#ifndef  EXEC_LISTS_H
#include "exec/lists.h"
#endif
#ifndef  EXEC_PORTS_H
#include "exec/ports.h"
#endif
#ifndef  EXEC_LIBRARIES_H
#include "exec/libraries.h"
#endif
#ifndef  EXEC_TASKS_H
#include "exec/tasks.h"
#endif

#ifndef  DEVICES_PARALLEL_H
#include "devices/parallel.h"
#endif
#ifndef  DEVICES_SERIAL_H
#include "devices/serial.h"
#endif
#ifndef  DEVICES_TIMER_H
#include "devices/timer.h"
#endif
#ifndef  LIBRARIES_DOSEXTENS_H
#include "libraries/dosextens.h"
#endif
#ifndef  INTUITION_INTUITION_H
#include "intuition/intuition.h"
#endif

struct DeviceData {
    struct Library dd_Device; /* standard library node */
    APTR dd_Segment;	      /* A0 when initialized */
    APTR dd_ExecBase;	      /* A6 for exec */
    APTR dd_CmdVectors;       /* command table for device commands */
    APTR dd_CmdBytes;	      /* bytes describing which command queue */
    UWORD   dd_NumCommands;   /* the number of commands supported */
};

#define P_OLDSTKSIZE	0x0800	/* stack size for child task (OBSOLETE) */
#define P_STKSIZE	0x1000	/* stack size for child task */
#define P_BUFSIZE	256	/* size of internal buffers for text i/o */
#define P_SAFESIZE	128	/* safety margin for text output buffer */

struct	 PrinterData {
    struct DeviceData pd_Device;
    struct MsgPort pd_Unit;	/* the one and only unit */
    BPTR pd_PrinterSegment;	/* the printer specific segment */
    UWORD pd_PrinterType;	/* the segment printer type */
                /* the segment data structure */
    struct PrinterSegment *pd_SegmentData;
    UBYTE *pd_PrintBuf;	/* the raster print buffer */
    int (*pd_PWrite)();	/* the write function */
    int (*pd_PBothReady)();	/* write function's done */
    union {			/* port I/O request 0 */
        struct IOExtPar pd_p0;
        struct IOExtSer pd_s0;
    } pd_ior0;

#define  pd_PIOR0 pd_ior0.pd_p0
#define  pd_SIOR0 pd_ior0.pd_s0

    union {			/*   and 1 for double buffering */
        struct IOExtPar pd_p1;
        struct IOExtSer pd_s1;
    } pd_ior1;

#define  pd_PIOR1 pd_ior1.pd_p1
#define  pd_SIOR1 pd_ior1.pd_s1

    struct timerequest pd_TIOR;	/* timer I/O request */
    struct MsgPort pd_IORPort;	/* and message reply port */
    struct Task pd_TC;		/* write task */
    UBYTE pd_OldStk[P_OLDSTKSIZE];	/* and stack space (OBSOLETE) */
    UBYTE pd_Flags;			/* device flags */
    UBYTE pd_pad;			/* padding */
    struct Preferences pd_Preferences;	/* the latest preferences */
    UBYTE pd_PWaitEnabled;		/* wait function switch */
    /* new fields for V2.0 */
    UBYTE pd_Flags1;		/* padding */
    UBYTE pd_Stk[P_STKSIZE];	/* stack space */
};

/* Printer Class */
#define PPCB_GFX	0	/* graphics (bit position) */
#define PPCF_GFX	0x1	/* graphics (and/or flag) */
#define PPCB_COLOR	1	/* color (bit position) */
#define PPCF_COLOR	0x2	/* color (and/or flag) */

#define PPC_BWALPHA	0x00	/* black&white alphanumerics */
#define PPC_BWGFX	0x01	/* black&white graphics */
#define PPC_COLORALPHA	0x02	/* color alphanumerics */
#define PPC_COLORGFX	0x03	/* color graphics */

/* Color Class */
#define	PCC_BW		0x01	/* black&white only */
#define	PCC_YMC		0x02	/* yellow/magenta/cyan only */
#define	PCC_YMC_BW	0x03	/* yellow/magenta/cyan or black&white */
#define	PCC_YMCB	0x04	/* yellow/magenta/cyan/black */
#define	PCC_4COLOR	0x04	/* a flag for YMCB and BGRW */
#define	PCC_ADDITIVE	0x08	/* not ymcb but blue/green/red/white */
#define	PCC_WB		0x09	/* black&white only, 0 == BLACK */
#define	PCC_BGR		0x0A	/* blue/green/red */
#define	PCC_BGR_WB	0x0B	/* blue/green/red or black&white */
#define	PCC_BGRW	0x0C	/* blue/green/red/white */
/*
    The picture must be scanned once for each color component, as the
    printer can only define one color at a time.  ie. If 'PCC_YMC' then
    first pass sends all 'Y' info to printer, second pass sends all 'M'
    info, and third pass sends all C info to printer.  The CalComp
    PlotMaster is an example of this type of printer.
*/
#define PCC_MULTI_PASS	0x10	/* see explanation above */

struct PrinterExtendedData {
    char	*ped_PrinterName;    /* printer name, null terminated */
    VOID	(*ped_Init)();	     /* called after LoadSeg */
    VOID	(*ped_Expunge)();    /* called before UnLoadSeg */
    int	(*ped_Open)();	     /* called at OpenDevice */
    VOID	(*ped_Close)();      /* called at CloseDevice */
    UBYTE	ped_PrinterClass;    /* printer class */
    UBYTE	ped_ColorClass;      /* color class */
    UBYTE	ped_MaxColumns;      /* number of print columns available */
    UBYTE	ped_NumCharSets;     /* number of character sets */
    UWORD	ped_NumRows;	     /* number of 'pins' in print head */
    ULONG	ped_MaxXDots;	     /* number of dots max in a raster dump */
    ULONG	ped_MaxYDots;	     /* number of dots max in a raster dump */
    UWORD	ped_XDotsInch;	     /* horizontal dot density */
    UWORD	ped_YDotsInch;	     /* vertical dot density */
    char	***ped_Commands;     /* printer text command table */
    int	(*ped_DoSpecial)();  /* special command handler */
    int	(*ped_Render)();     /* raster render function */
    LONG	ped_TimeoutSecs;     /* good write timeout */
    /* the following only exists if the segment version is >= 33 */
    char	**ped_8BitChars;     /* conv. strings for the extended font */
    LONG	ped_PrintMode;	     /* set if text printed, otherwise 0 */
    /* the following only exists if the segment version is >= 34 */
    /* ptr to conversion function for all chars */
    int	(*ped_ConvFunc)();
};

struct PrinterSegment {
    ULONG   ps_NextSegment;	 /* (actually a BPTR) */
    ULONG   ps_runAlert;	 /* MOVEQ #0,D0 : RTS */
    UWORD   ps_Version;	 /* segment version */
    UWORD   ps_Revision;	 /* segment revision */
    struct  PrinterExtendedData ps_PED;   /* printer extended data */
};
#endif


Includes/devices/trackdisk.h

#ifndef DEVICES_TRACKDISK_H
#define DEVICES_TRACKDISK_H

/*
**
**	$Filename: devices/trackdisk.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 33.13 $
**	$Date: 90/11/28 $
**
**	trackdisk device structure and value definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**
*/

#ifndef EXEC_IO_H
#include "exec/io.h"
#endif

#ifndef EXEC_DEVICES_H
#include "exec/devices.h"
#endif

/*
 *--------------------------------------------------------------------
 *
 * Physical drive constants
 *
 *--------------------------------------------------------------------
 */

/* OBSOLETE -- use the TD_GETNUMTRACKS command! */
/*#define	NUMCYLS	80*/		/*  normal # of cylinders */
/*#define	MAXCYLS	(NUMCYLS+20)*/	/* max # cyls to look for during cal */
/*#define	NUMHEADS 2*/
/*#define	NUMTRACKS (NUMCYLS*NUMHEADS)*/

#define	NUMSECS	11
#define NUMUNITS 4

/*
 *--------------------------------------------------------------------
 *
 * Useful constants
 *
 *--------------------------------------------------------------------
 */

/*-- sizes before mfm encoding */
#define	TD_SECTOR 512
#define	TD_SECSHIFT 9		/* log TD_SECTOR */

/*
 *--------------------------------------------------------------------
 *
 * Driver Specific Commands
 *
 *--------------------------------------------------------------------
 */

/*
 *-- TD_NAME is a generic macro to get the name of the driver.	This
 *-- way if the name is ever changed you will pick up the change
 *-- automatically.
 *--
 *-- Normal usage would be:
 *--
 *-- char internalName[] = TD_NAME;
 *--
 */

#define	TD_NAME	"trackdisk.device"

#define	TDF_EXTCOM (1<<15)		/* for internal use only! */

#define	TD_MOTOR	(CMD_NONSTD+0)	/* control the disk's motor */
#define	TD_SEEK		(CMD_NONSTD+1)	/* explicit seek (for testing) */
#define	TD_FORMAT	(CMD_NONSTD+2)	/* format disk */
#define	TD_REMOVE	(CMD_NONSTD+3)	/* notify when disk changes */
#define	TD_CHANGENUM	(CMD_NONSTD+4)	/* number of disk changes */
#define	TD_CHANGESTATE	(CMD_NONSTD+5)	/* is there a disk in the drive? */
#define	TD_PROTSTATUS	(CMD_NONSTD+6)	/* is the disk write protected? */
#define	TD_RAWREAD	(CMD_NONSTD+7)	/* read raw bits from the disk */
#define	TD_RAWWRITE	(CMD_NONSTD+8)	/* write raw bits to the disk */
#define	TD_GETDRIVETYPE	(CMD_NONSTD+9)	/* get the type of the disk drive */
#define	TD_GETNUMTRACKS	(CMD_NONSTD+10)	/* # of tracks for this type drive */
#define	TD_ADDCHANGEINT	(CMD_NONSTD+11)	/* TD_REMOVE done right */
#define	TD_REMCHANGEINT	(CMD_NONSTD+12)	/* remove softint set by ADDCHANGEINT */
#define TD_GETGEOMETRY	(CMD_NONSTD+13) /* gets the disk geometry table */
#define TD_EJECT	(CMD_NONSTD+14) /* for those drives that support it */
#define	TD_LASTCOMM	(CMD_NONSTD+15)

/*
 *
 * The disk driver has an "extended command" facility.	These commands
 * take a superset of the normal IO Request block.
 *
 */

#define	ETD_WRITE	(CMD_WRITE|TDF_EXTCOM)
#define	ETD_READ	(CMD_READ|TDF_EXTCOM)
#define	ETD_MOTOR	(TD_MOTOR|TDF_EXTCOM)
#define	ETD_SEEK	(TD_SEEK|TDF_EXTCOM)
#define	ETD_FORMAT	(TD_FORMAT|TDF_EXTCOM)
#define	ETD_UPDATE	(CMD_UPDATE|TDF_EXTCOM)
#define	ETD_CLEAR	(CMD_CLEAR|TDF_EXTCOM)
#define	ETD_RAWREAD	(TD_RAWREAD|TDF_EXTCOM)
#define	ETD_RAWWRITE	(TD_RAWWRITE|TDF_EXTCOM)

/*
 *
 * extended IO has a larger than normal io request block.
 *
 */

struct IOExtTD {
    struct	IOStdReq iotd_Req;
    ULONG	iotd_Count;
    ULONG	iotd_SecLabel;
};

/*
 *  This is the structure returned by TD_DRIVEGEOMETRY
 *  Note that the layout can be defined three ways:
 *
 *  1. TotalSectors
 *  2. Cylinders and CylSectors
 *  3. Cylinders, Heads, and TrackSectors.
 *
 *  #1 is most accurate, #2 is less so, and #3 is least accurate.  All
 *  are usable, though #2 and #3 may waste some portion of the available
 *  space on some drives.
 */
struct DriveGeometry {
    ULONG	dg_SectorSize;		/* in bytes */
    ULONG	dg_TotalSectors;	/* total # of sectors on drive */
    ULONG	dg_Cylinders;		/* number of cylinders */
    ULONG	dg_CylSectors;		/* number of sectors/cylinder */
    ULONG	dg_Heads;		/* number of surfaces */
    ULONG	dg_TrackSectors;	/* number of sectors/track */
    ULONG	dg_BufMemType;		/* preferred buffer memory type */
                    /* (usually MEMF_PUBLIC) */
    UBYTE	dg_DeviceType;		/* codes as defined in the SCSI-2 spec*/
    UBYTE	dg_Flags;		/* flags, including removable */
    UWORD	dg_Reserved;
};

/* device types */
#define DG_DIRECT_ACCESS	0
#define DG_SEQUENTIAL_ACCESS	1
#define DG_PRINTER		2
#define DG_PROCESSOR		3
#define DG_WORM			4
#define DG_CDROM		5
#define DG_SCANNER		6
#define DG_OPTICAL_DISK		7
#define DG_MEDIUM_CHANGER	8
#define DG_COMMUNICATION	9
#define DG_UNKNOWN		31

/* flags */
#define DGB_REMOVABLE		0
#define DGF_REMOVABLE		1

/*
** raw read and write can be synced with the index pulse.  This flag
** in io request's IO_FLAGS field tells the driver that you want this.
*/

#define IOTDB_INDEXSYNC	4
#define IOTDF_INDEXSYNC (1<<4)
/*
** raw read and write can be synced with a $4489 sync pattern.	This flag
** in io request's IO_FLAGS field tells the driver that you want this.
*/
#define IOTDB_WORDSYNC	5
#define IOTDF_WORDSYNC (1<<5)

/* labels are TD_LABELSIZE bytes per sector */

#define	TD_LABELSIZE 16

/*
** This is a bit in the FLAGS field of OpenDevice.  If it is set, then
** the driver will allow you to open all the disks that the trackdisk
** driver understands.	Otherwise only 3.5" disks will succeed.
*/

#define TDB_ALLOW_NON_3_5	0
#define TDF_ALLOW_NON_3_5	(1<<0)

/*
**  If you set the TDB_ALLOW_NON_3_5 bit in OpenDevice, then you don't
**  know what type of disk you really got.  These defines are for the
**  TD_GETDRIVETYPE command.  In addition, you can find out how many
**  tracks are supported via the TD_GETNUMTRACKS command.
*/

#define	DRIVE3_5	1
#define	DRIVE5_25	2
#define	DRIVE3_5_150RPM	3

/*
 *--------------------------------------------------------------------
 *
 * Driver error defines
 *
 *--------------------------------------------------------------------
 */

#define	TDERR_NotSpecified	20	/* general catchall */
#define	TDERR_NoSecHdr		21	/* couldn't even find a sector */
#define	TDERR_BadSecPreamble	22	/* sector looked wrong */
#define	TDERR_BadSecID		23	/* ditto */
#define	TDERR_BadHdrSum		24	/* header had incorrect checksum */
#define	TDERR_BadSecSum		25	/* data had incorrect checksum */
#define	TDERR_TooFewSecs	26	/* couldn't find enough sectors */
#define	TDERR_BadSecHdr		27	/* another "sector looked wrong" */
#define	TDERR_WriteProt		28	/* can't write to a protected disk */
#define	TDERR_DiskChanged	29	/* no disk in the drive */
#define	TDERR_SeekError		30	/* couldn't find track 0 */
#define	TDERR_NoMem		31	/* ran out of memory */
#define	TDERR_BadUnitNum	32	/* asked for a unit > NUMUNITS */
#define	TDERR_BadDriveType	33	/* not a drive that trackdisk groks */
#define	TDERR_DriveInUse	34	/* someone else allocated the drive */
#define	TDERR_PostReset		35	/* user hit reset; awaiting doom */

/*
 *--------------------------------------------------------------------
 *
 * public portion of the unit structure
 *
 *--------------------------------------------------------------------
 */

struct TDU_PublicUnit {
    struct	Unit tdu_Unit;		/* base message port */
    UWORD	tdu_Comp01Track;	/* track for first precomp */
    UWORD	tdu_Comp10Track;	/* track for second precomp */
    UWORD	tdu_Comp11Track;	/* track for third precomp */
    ULONG	tdu_StepDelay;		/* time to wait after stepping */
    ULONG	tdu_SettleDelay;	/* time to wait after seeking */
    UBYTE	tdu_RetryCnt;		/* # of times to retry */
    UBYTE	tdu_PubFlags;		/* public flags, see below */
    UWORD	tdu_CurrTrk;		/* track the heads are over... */
                    /* ONLY ACCESS WHILE UNIT IS STOPPED! */
    ULONG	tdu_CalibrateDelay;	/* time to wait after stepping */
                    /* during a recalibrate */
    ULONG	tdu_Counter;		/* counter for disk changes... */
                    /* ONLY ACCESS WHILE UNIT IS STOPPED! */
};

/* flags for tdu_PubFlags */
#define TDPB_NOCLICK	0
#define TDPF_NOCLICK	(1L << 0)

#endif	/* DEVICES_TRACKDISK_H */


Includes/devices/conunit.i

    IFND	DEVICES_CONUNIT_I
DEVICES_CONUNIT_I	SET	1
**
**	$Filename: devices/conunit.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.16 $
**	$Date: 90/11/20 $
**
**	Console device unit definitions
**
**	(C) Copyright 1986-1999 Amiga, Inc.
**	    All Rights Reserved
**
    IFND	EXEC_TYPES_I
    INCLUDE	"exec/types.i"
    ENDC

    IFND	EXEC_PORTS_I
    INCLUDE	"exec/ports.i"
    ENDC

    IFND	DEVICES_CONSOLE_I
    INCLUDE	"devices/console.i"
    ENDC

    IFND	DEVICES_KEYMAP_I
    INCLUDE	"devices/keymap.i"
    ENDC

    IFND	DEVICES_INPUTEVENT_I
    INCLUDE	"devices/inputevent.i"
    ENDC

;------	console unit numbers for OpenDevice()
CONU_LIBRARY	EQU	-1	; no unit, just fill in IO_DEVICE field
CONU_STANDARD	EQU	0	; standard unmapped console

;------ New unit numbers for OpenDevice() - (V36)

CONU_CHARMAP	EQU	1	; bind character map to console
CONU_SNIPMAP	EQU	3	; bind character map w/ snip to console

;------ New flag defines for OpenDevice() - (V37)

CONFLAG_DEFAULT			EQU	0
CONFLAG_NODRAW_ON_NEWSIZE	EQU	1

PMB_ASM		EQU	M_LNM+1		; internal storage bit for AS flag
PMB_AWM		EQU	PMB_ASM+1	; internal storage bit for AW flag
MAXTABS		EQU	80

 STRUCTURE  ConUnit,MP_SIZE
    ;------ read only variables
    APTR    cu_Window		; intuition window bound to this unit
    WORD    cu_XCP		; character position
    WORD    cu_YCP
    WORD    cu_XMax		; max character position
    WORD    cu_YMax
    WORD    cu_XRSize		; character raster size
    WORD    cu_YRSize
    WORD    cu_XROrigin		; raster origin
    WORD    cu_YROrigin
    WORD    cu_XRExtant		; raster maxima
    WORD    cu_YRExtant
    WORD    cu_XMinShrink	; smallest area intact from resize process
    WORD    cu_YMinShrink
    WORD    cu_XCCP		; cursor position
    WORD    cu_YCCP

    ;------ read/write variables (writes must must be protected)
    ;------ storage for AskKeyMap and SetKeyMap
    STRUCT  cu_KeyMapStruct,km_SIZEOF
    ; ---- tab stops
    STRUCT  cu_TabStops,2*MAXTABS ; 0 at start, 0xffff at end of list

    ;------ console rastport attributes
    BYTE    cu_Mask		; these must appear as in RastPort
    BYTE    cu_FgPen		;   |
    BYTE    cu_BgPen		;   |
    BYTE    cu_AOLPen		;   +
    BYTE    cu_DrawMode		; these must appear as in RastPort
    BYTE    cu_Obsolete1	; was cu_AreaPtSz -- not used in V36
    APTR    cu_Obsolete2	; was cu_AreaPtrn -- not used in V36
    STRUCT  cu_Minterms,8	; console minterms
    APTR    cu_Font		;
    UBYTE   cu_AlgoStyle	; these must appear as in RastPort
    UBYTE   cu_TxFlags		;   +
    UWORD   cu_TxHeight		; these must appear as in RastPort
    UWORD   cu_TxWidth		;   |
    UWORD   cu_TxBaseline	;   |
    WORD    cu_TxSpacing	;   +

    ;------ console MODES and RAW EVENTS switches
    STRUCT  cu_Modes,<(PMB_AWM+7)/8>	; one bit per mode
    STRUCT  cu_RawEvents,<(IECLASS_MAX+8)/8>

    ;------ ensure the ConsUnit structure is even
    ALIGNWORD

    LABEL   ConUnit_SIZEOF

    ENDC	; DEVICES_CONUNIT_I


Includes/devices/keyboard.i

    IFND	DEVICES_KEYBOARD_I
DEVICES_KEYBOARD_I	SET	1
**
**	$Filename: devices/keyboard.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.0 $
**	$Date: 90/05/01 $
**
**	Keyboard device command definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

   IFND	    EXEC_IO_I
   INCLUDE     "exec/io.i"
   ENDC

   DEVINIT

   DEVCMD	KBD_READEVENT
   DEVCMD	KBD_READMATRIX
   DEVCMD	KBD_ADDRESETHANDLER
   DEVCMD	KBD_REMRESETHANDLER
   DEVCMD	KBD_RESETHANDLERDONE

    ENDC	; DEVICES_KEYBOARD_I


Includes/devices/prtbase.i

   IFND  DEVICES_PRTBASE_I
DEVICES_PRTBASE_I EQU	1
**
**	$Filename: devices/prtbase.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.9 $
**	$Date: 90/07/26 $
**
**	printer.device base structure definitions
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
**

   IFND  EXEC_TYPES_I
   INCLUDE  "exec/types.i"
   ENDC
   IFND  EXEC_NODES_I
   INCLUDE  "exec/nodes.i"
   ENDC
   IFND  EXEC_LISTS_I
   INCLUDE  "exec/lists.i"
   ENDC
   IFND  EXEC_PORTS_I
   INCLUDE  "exec/ports.i"
   ENDC
   IFND  EXEC_LIBRARIES_I
   INCLUDE  "exec/libraries.i"
   ENDC
   IFND  EXEC_TASKS_I
   INCLUDE  "exec/tasks.i"
   ENDC

   IFND  DEVICES_PARALLEL_I
   INCLUDE  "devices/parallel.i"
   ENDC
   IFND  DEVICES_SERIAL_I
   INCLUDE  "devices/serial.i"
   ENDC
   IFND  DEVICES_TIMER_I
   INCLUDE  "devices/timer.i"
   ENDC
   IFND  LIBRARIES_DOSEXTENS_I
   INCLUDE  "libraries/dosextens.i"
   ENDC
   IFND  INTUITION_INTUITION_I
   INCLUDE  "intuition/intuition.i"
   ENDC

 STRUCTURE  DeviceData,LIB_SIZE
    APTR dd_Segment	      ; A0 when initialized
    APTR dd_ExecBase	      ; A6 for exec
    APTR dd_CmdVectors	      ; command table for device commands
    APTR dd_CmdBytes	      ; bytes describing which command queue
    UWORD   dd_NumCommands    ; the number of commands supported
    LABEL   dd_SIZEOF

*------
*------ device driver private variables ------------------------------
*------
du_Flags EQU   LN_PRI	      ; various unit flags

;------ IO_FLAGS
    BITDEF  IO,QUEUED,4       ; command is queued to be performed
    BITDEF  IO,CURRENT,5      ; command is being performed
    BITDEF  IO,SERVICING,6    ; command is being actively performed
    BITDEF  IO,DONE,7	      ; command is done

;------ du_Flags
    BITDEF  DU,STOPPED,0      ; commands are not to be performed

*------ Constants ----------------------------------------------------
P_PRIORITY	EQU	0
P_OLDSTKSIZE	EQU	$0800	; stack size for child task (OBSOLETE)
P_STKSIZE	EQU	$1000	; stack size for child task
P_BUFSIZE	EQU	256	; size of internal buffers for text i/o
P_SAFESIZE	EQU	128	; safety margin for text output buffer

*------ pd_Flags ------
   BITDEF   P,IOR0,0	      ; IOR0 is in use
   BITDEF   P,IOR1,1	      ; IOR1 is in use
   BITDEF   P,EXPUNGED,7      ; device to be expunged when all closed

 STRUCTURE  PrinterData,dd_SIZEOF
    STRUCT  pd_Unit,MP_SIZE   ; the one and only unit
    BPTR pd_PrinterSegment    ; the printer specific segment
    UWORD   pd_PrinterType    ; the segment printer type
    APTR pd_SegmentData       ; the segment data structure
    APTR pd_PrintBuf	      ; the raster print buffer
    APTR pd_PWrite	      ; the parallel write function
    APTR pd_PBothReady	      ; the parallel write function's done

    IFGT IOEXTPar_SIZE-IOEXTSER_SIZE
    STRUCT  pd_IOR0,IOEXTPar_SIZE   ; port I/O request 0
    STRUCT  pd_IOR1,IOEXTPar_SIZE   ;   and 1 for double buffering
    ENDC

    IFLE IOEXTPar_SIZE-IOEXTSER_SIZE
    STRUCT  pd_IOR0,IOEXTSER_SIZE   ; port I/O request 0
    STRUCT  pd_IOR1,IOEXTSER_SIZE   ;   and 1 for double buffering
    ENDC

    STRUCT  pd_TIOR,IOTV_SIZE       ; timer I/O request
    STRUCT  pd_IORPort,MP_SIZE      ;   and message reply port
    STRUCT  pd_TC,TC_SIZE           ; write task
    STRUCT  pd_OldStk,P_OLDSTKSIZE  ;   and stack space (OBSOLETE)
    UBYTE   pd_Flags                ; device flags
    UBYTE   pd_pad		    ; padding
    STRUCT  pd_Preferences,pf_SIZEOF ; the latest preferences
    UBYTE   pd_PWaitEnabled         ; wait function switch
;   /* new fields for V2.0 */
    UBYTE   pd_Pad1		    ; padding
    STRUCT  pd_Stk,P_STKSIZE	    ; stack space
    LABEL   pd_SIZEOF               ; warning! this may be odd

    BITDEF  PPC,GFX,0		;graphics (bit position)
    BITDEF  PPC,COLOR,1		;color (bit position)

PPC_BWALPHA	EQU	$00	;black&white alphanumerics
PPC_BWGFX	EQU	$01	;black&white graphics
PPC_COLORALPHA	EQU	$02	;color alphanumerics
PPC_COLORGFX	EQU	$03	;color graphics

PCC_BW		EQU	1	;black&white only
PCC_YMC		EQU	2	;yellow/magenta/cyan only
PCC_YMC_BW	EQU	3	;yellow/magenta/cyan or black&white
PCC_YMCB	EQU	4	;yellow/magenta/cyan/black

PCC_4COLOR	EQU	$4	;a flag for YMCB and BGRW
PCC_ADDITIVE	EQU	$8	;not ymcb but blue/green/red/white
PCC_WB		EQU	$9	;black&white only, 0 == BLACK
PCC_BGR		EQU	$a	;blue/green/red
PCC_BGR_WB	EQU	$b	;blue/green/red or black&white
PCC_BGRW	EQU	$c	;blue/green/red/white
;	The picture must be scanned once for each color component, as the
;	printer can only define one color at a time.  ie. If 'PCC_YMC' then
;	first pass sends all 'Y' info to printer, second pass sends all 'M'
;	info, and third pass sends all C info to printer.  The CalComp
;	PlotMaster is an example of this type of printer.
PCC_MULTI_PASS	EQU	$10	;see explanation above

 STRUCTURE  PrinterExtendedData,0
    APTR    ped_PrinterName   ; printer name, null terminated
    APTR    ped_Init          ; called after LoadSeg
    APTR    ped_Expunge       ; called before UnLoadSeg
    APTR    ped_Open          ; called at OpenDevice
    APTR    ped_Close         ; called at CloseDevice
    UBYTE   ped_PrinterClass  ; printer class
    UBYTE   ped_ColorClass    ; color class
    UBYTE   ped_MaxColumns    ; number of print columns available
    UBYTE   ped_NumCharSets   ; number of character sets
    UWORD   ped_NumRows       ; number of 'pins' in print head
    ULONG   ped_MaxXDots      ; number of dots maximum in a raster dump
    ULONG   ped_MaxYDots      ; number of dots maximum in a raster dump
    UWORD   ped_XDotsInch     ; horizontal dot density
    UWORD   ped_YDotsInch     ; vertical dot density
    APTR    ped_Commands      ; printer text command table
    APTR    ped_DoSpecial     ; special command handler
    APTR    ped_Render        ; raster render function
    LONG    ped_TimeoutSecs   ; good write timeout
;------	the following only exists if the segment version is 33 or greater
    APTR     ped_8BitChars	;conversion strings for the extended font
    LONG     ped_PrintMode	;set if text printed, otherwise 0
;------	the following only exists if the segment version is 34 or greater
    APTR	ped_ConvFunv	; ptr to conversion function for all chars
    LABEL   ped_SIZEOF

 STRUCTURE  PrinterSegment,0
    ULONG   ps_NextSegment    ; (actually a BPTR)
    ULONG   ps_runAlert       ; MOVEQ #0,D0 : RTS
    UWORD   ps_Version        ; segment version
    UWORD   ps_Revision       ; segment revision
    LABEL   ps_PED            ; printer extended data

   ENDC


Includes/devices/trackdisk.i

    IFND	DEVICES_TRACKDISK_I
DEVICES_TRACKDISK_I	SET	1

**
**	$Filename: devices/trackdisk.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 33.12 $
**	$Date: 90/11/28 $
**
**	trackdisk device structure and value definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND	EXEC_IO_I
    INCLUDE	"exec/io.i"
    ENDC	!EXEC_IO_I

    IFND	EXEC_DEVICES_I
    INCLUDE	"exec/devices.i"
    ENDC	!EXEC_DEVICES_I

*--------------------------------------------------------------------
*
* Physical drive constants
*
*--------------------------------------------------------------------

* OBSOLETE -- only valid for 3 1/4" drives.  Use the TD_GETNUMTRACKS command!
*
*NUMCYLS		EQU	80		; normal # of cylinders
*MAXCYLS		EQU	NUMCYLS+20	; max # of cyls to look for
*						;	during a calibrate
*NUMHEADS	EQU	2
*NUMTRACKS	EQU	NUMCYLS*NUMHEADS

NUMSECS		EQU	11
NUMUNITS	EQU	4

*--------------------------------------------------------------------
*
* Useful constants
*
*--------------------------------------------------------------------

*-- sizes before mfm encoding
TD_SECTOR	EQU	512
TD_SECSHIFT	EQU	9			; log TD_SECTOR
*						;    2

*--------------------------------------------------------------------
*
* Driver Specific Commands
*
*--------------------------------------------------------------------

*-- TD_NAME is a generic macro to get the name of the driver.  This
*-- way if the name is ever changed you will pick up the change
*-- automatically.
*--
*-- Normal usage would be:
*--
*-- internalName:	TD_NAME
*--

TD_NAME:	MACRO
        DC.B	'trackdisk.device',0
        DS.W	0
        ENDM

    BITDEF	TD,EXTCOM,15

    DEVINIT
    DEVCMD	TD_MOTOR		; control the disk's motor
    DEVCMD	TD_SEEK			; explicit seek (for testing)
    DEVCMD	TD_FORMAT		; format disk
    DEVCMD	TD_REMOVE		; notify when disk changes
    DEVCMD	TD_CHANGENUM		; number of disk changes
    DEVCMD	TD_CHANGESTATE		; is there a disk in the drive?
    DEVCMD	TD_PROTSTATUS		; is the disk write protected?
    DEVCMD	TD_RAWREAD		; read raw bits from the disk
    DEVCMD	TD_RAWWRITE		; write raw bits to the disk
    DEVCMD	TD_GETDRIVETYPE		; get the type of the disk drive
    DEVCMD	TD_GETNUMTRACKS		; get the # of tracks on this disk
    DEVCMD	TD_ADDCHANGEINT		; TD_REMOVE done right
    DEVCMD	TD_REMCHANGEINT		; removes softint set by ADDCHANGEINT
    DEVCMD	TD_GETGEOMETRY		; gets the disk geometry table
    DEVCMD	TD_EJECT		; for those drives that support it
    DEVCMD	TD_LASTCOMM		; dummy placeholder for end of list

*
*
* The disk driver has an "extended command" facility.  These commands
* take a superset of the normal IO Request block.
*
ETD_WRITE	EQU	(CMD_WRITE!TDF_EXTCOM)
ETD_READ	EQU	(CMD_READ!TDF_EXTCOM)
ETD_MOTOR	EQU	(TD_MOTOR!TDF_EXTCOM)
ETD_SEEK	EQU	(TD_SEEK!TDF_EXTCOM)
ETD_FORMAT	EQU	(TD_FORMAT!TDF_EXTCOM)
ETD_UPDATE	EQU	(CMD_UPDATE!TDF_EXTCOM)
ETD_CLEAR	EQU	(CMD_CLEAR!TDF_EXTCOM)
ETD_RAWREAD	EQU	(TD_RAWREAD!TDF_EXTCOM)
ETD_RAWWRITE	EQU	(TD_RAWWRITE!TDF_EXTCOM)

*
* extended IO has a larger than normal io request block.
*

 STRUCTURE IOEXTTD,IOSTD_SIZE
    ULONG	IOTD_COUNT	; removal/insertion count
    ULONG	IOTD_SECLABEL	; sector label data region
    LABEL	IOTD_SIZE

*
*  This is the structure returned by TD_DRIVEGEOMETRY
*  Note that the layout can be defined three ways:
*
*  1. TotalSectors
*  2. Cylinders and CylSectors
*  3. Cylinders, Heads, and TrackSectors.
*
*  #1 is most accurate, #2 is less so, and #3 is least accurate.  All
*  are usable, though #2 and #3 may waste some portion of the available
*  space on some drives.
*

 STRUCTURE DriveGeometry,0
    ULONG	dg_SectorSize		; in bytes
    ULONG	dg_TotalSectors		; total # of sectors on drive
    ULONG	dg_Cylinders		; number of cylinders
    ULONG	dg_CylSectors		; number of sectors/cylinder
    ULONG	dg_Heads		; number of surfaces
    ULONG	dg_TrackSectors		; number of sectors/track
    ULONG	dg_BufMemType		; preferred buffer memory type
                    ; (usually MEMF_PUBLIC)
    UBYTE	dg_DeviceType		; codes as defined in the SCSI-2 spec
    UBYTE	dg_Flags		; flags, including removable
    UWORD	dg_Reserved
 LABEL dg_SIZEOF

* device types
DG_DIRECT_ACCESS	EQU	0
DG_SEQUENTIAL_ACCESS	EQU	1
DG_PRINTER		EQU	2
DG_PROCESSOR		EQU	3
DG_WORM			EQU	4
DG_CDROM		EQU	5
DG_SCANNER		EQU	6
DG_OPTICAL_DISK		EQU	7
DG_MEDIUM_CHANGER	EQU	8
DG_COMMUNICATION	EQU	9
DG_UNKNOWN		EQU	31

* flags
 BITDEF DG,REMOVABLE,0

*
* raw read and write can be synced with the index pulse.  This flag
* in io request's IO_FLAGS field tells the driver that you want this.
*
    BITDEF	IOTD,INDEXSYNC,4
*
* raw read and write can be synced with a $4489 sync pattern.  This flag
* in io request's IO_FLAGS field tells the driver that you want this.
*
    BITDEF	IOTD,WORDSYNC,5

* labels are TD_LABELSIZE bytes per sector

TD_LABELSIZE	EQU	16

*
* This is a bit in the FLAGS field of OpenDevice.  If it is set, then
* the driver will allow you to open all the disks that the trackdisk
* driver understands.  Otherwise only 3.5" disks will succeed.
*
*
    BITDEF	TD,ALLOW_NON_3_5,0

*
*  If you set the TDB_ALLOW_NON_3_5 bit in OpenDevice, then you don't
*  know what type of disk you really got.  These defines are for the
*  TD_GETDRIVETYPE command.  In addition, you can find out how many
*  tracks are supported via the TD_GETNUMTRACKS command.
*
DRIVE3_5	EQU	1
DRIVE5_25	EQU	2
DRIVE3_5_150RPM	EQU	3

*--------------------------------------------------------------------
*
* Driver error defines
*
*--------------------------------------------------------------------

TDERR_NotSpecified	EQU	20	; general catchall
TDERR_NoSecHdr		EQU	21	; couldn't even find a sector
TDERR_BadSecPreamble	EQU	22	; sector looked wrong
TDERR_BadSecID		EQU	23	; ditto
TDERR_BadHdrSum		EQU	24	; header had incorrect checksum
TDERR_BadSecSum		EQU	25	; data had incorrect checksum
TDERR_TooFewSecs	EQU	26	; couldn't find enough sectors
TDERR_BadSecHdr		EQU	27	; another "sector looked wrong"
TDERR_WriteProt		EQU	28	; can't write to a protected disk
TDERR_DiskChanged	EQU	29	; no disk in the drive
TDERR_SeekError		EQU	30	; couldn't find track 0
TDERR_NoMem		EQU	31	; ran out of memory
TDERR_BadUnitNum	EQU	32	; asked for a unit > NUMUNITS
TDERR_BadDriveType	EQU	33	; not a drive that trackdisk groks
TDERR_DriveInUse	EQU	34	; someone else allocated the drive
TDERR_PostReset		EQU	35	; user hit reset; awaiting doom

*--------------------------------------------------------------------
*
* Public portion of unit structure
*
*--------------------------------------------------------------------

 STRUCTURE TDU_PUBLICUNIT,UNIT_SIZE
    UWORD	TDU_COMP01TRACK		; track for first precomp
    UWORD	TDU_COMP10TRACK		; track for second precomp
    UWORD	TDU_COMP11TRACK		; track for third precomp
    ULONG	TDU_STEPDELAY		; time to wait after stepping
    ULONG	TDU_SETTLEDELAY		; time to wait after seeking
    UBYTE	TDU_RETRYCNT		; # of times to retry
    UBYTE	TDU_PUBFLAGS		; public flags, see below
    UWORD	TDU_CURRTRK		; track heads are over
                    ;  (ONLY ACCESS WHILE UNIT IS STOPPED!)
    ULONG	TDU_CALIBRATEDELAY	; time to wait after stepping
                    ; for recalibrate
    ULONG	TDU_COUNTER		; counter for disk changes
                    ;  (ONLY ACCESS WHILE UNIT IS STOPPED!)
    LABEL	TDU_PUBLICUNITSIZE

*
* Flags for TDU_PUBFLAGS:
*
    BITDEF	TDP,NOCLICK,0		; set to enable noclickstart

    ENDC	; DEVICE_TRACKDISK_I


Includes/dos/datetime.h

#ifndef DOS_DATETIME_H
#define DOS_DATETIME_H

/*
**	$Filename: dos/datetime.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.7 $
**	$Date: 90/07/12 $
**
**	Date and time C header for AmigaDOS
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**
*/

#ifndef DOS_DOS_H
#include "dos/dos.h"
#endif

/*
 *	Data structures and equates used by the V1.4 DOS functions
 * StrtoDate() and DatetoStr()
 */

/*--------- String/Date structures etc */
struct DateTime {
    struct DateStamp dat_Stamp;	/* DOS DateStamp */
    UBYTE	dat_Format;		/* controls appearance of dat_StrDate */
    UBYTE	dat_Flags;		/* see BITDEF's below */
    UBYTE	*dat_StrDay;		/* day of the week string */
    UBYTE	*dat_StrDate;		/* date string */
    UBYTE	*dat_StrTime;		/* time string */
};

/* You need this much room for each of the DateTime strings: */
#define	LEN_DATSTRING	16

/*	flags for dat_Flags */

#define DTB_SUBST	0		/* substitute Today, Tomorrow, etc. */
#define DTF_SUBST	1
#define DTB_FUTURE	1		/* day of the week is in future */
#define DTF_FUTURE	2

/*
 *	date format values
 */

#define FORMAT_DOS	0		/* dd-mmm-yy */
#define FORMAT_INT	1		/* yy-mm-dd  */
#define FORMAT_USA	2		/* mm-dd-yy  */
#define FORMAT_CDN	3		/* dd-mm-yy  */
#define FORMAT_MAX	FORMAT_CDN

#endif /* DOS_DATETIME_H */


Includes/dos/dosextens.i

    IFND	DOS_DOSEXTENS_I
DOS_DOSEXTENS_I	SET	1
**
**	$Filename: dos/dosextens.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.37 $
**	$Date: 91/11/08 $
**
**	DOS structures not needed for the casual AmigaDOS user
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

     IFND  EXEC_TYPES_I
     INCLUDE "exec/types.i"
     ENDC
     IFND  EXEC_TASKS_I
     INCLUDE "exec/tasks.i"
     ENDC
     IFND  EXEC_PORTS_I
     INCLUDE "exec/ports.i"
     ENDC
     IFND  EXEC_LIBRARIES_I
     INCLUDE "exec/libraries.i"
     ENDC
     IFND  EXEC_SEMAPHORES_I
     INCLUDE "exec/semaphores.i"
     ENDC
     IFND  DEVICES_TIMER_I
     INCLUDE "devices/timer.i"
     ENDC

     IFND  DOS_DOS_I
     INCLUDE "dos/dos.i"
     ENDC

* All DOS processes have this STRUCTure
* Create and DeviceProc returns pointer to the MsgPort in this STRUCTure
* Process_addr = DeviceProc(..) - TC_SIZE

 STRUCTURE Process,0
    STRUCT  pr_Task,TC_SIZE
    STRUCT  pr_MsgPort,MP_SIZE	* This is BPTR address from DOS functions
    WORD    pr_Pad		* Remaining variables on 4 byte boundaries
    BPTR    pr_SegList		* Array of seg lists used by this process
    LONG    pr_StackSize	* Size of process stack in bytes
    APTR    pr_GlobVec		* Global vector for this process (BCPL)
    LONG    pr_TaskNum		* CLI task number of zero if not a CLI
    BPTR    pr_StackBase	* Ptr to high memory end of process stack
    LONG    pr_Result2		* Value of secondary result from last call
    BPTR    pr_CurrentDir	* Lock associated with current directory
    BPTR    pr_CIS		* Current CLI Input Stream
    BPTR    pr_COS		* Current CLI Output Stream
    APTR    pr_ConsoleTask	* Console handler process for current window
    APTR    pr_FileSystemTask	* File handler process for current drive
    BPTR    pr_CLI		* pointer to CommandLineInterface
    APTR    pr_ReturnAddr	* pointer to previous stack frame
    APTR    pr_PktWait		* Function to be called when awaiting msg
    APTR    pr_WindowPtr	* Window pointer for errors

* following definitions are new with 2.0
    BPTR    pr_HomeDir		* Home directory of executing program
    LONG    pr_Flags		* flags telling dos about process
    APTR    pr_ExitCode		* code to call on exit of program or NULL
    LONG    pr_ExitData		* Passed as an argument to pr_ExitCode
    APTR    pr_Arguments	* Arguments passed to the process at start
    STRUCT  pr_LocalVars,MLH_SIZE * Local environment variables
    APTR    pr_ShellPrivate	* for the use of the current shell
    BPTR    pr_CES		* Error stream - if NULL, use pr_COS
   LABEL   pr_SIZEOF		* Process

*
* Flags for pr_Flags
*
    BITDEF PR,FREESEGLIST,0
    BITDEF PR,FREECURRDIR,1
    BITDEF PR,FREECLI,2
    BITDEF PR,CLOSEINPUT,3
    BITDEF PR,CLOSEOUTPUT,4
    BITDEF PR,FREEARGS,5

* The long word address (BPTR) of this STRUCTure is returned by
* Open() and other routines that return a file.	 You need only worry
* about this STRUCT to do async io's via PutMsg() instead of
* standard file system calls

 STRUCTURE FileHandle,0
   APTR	  fh_Link		* pointer to EXEC message
   APTR	  fh_Interactive	* Boolean; TRUE if interactive handle
   APTR	  fh_Type		* Port to do PutMsg() to
   LONG	  fh_Buf
   LONG	  fh_Pos
   LONG	  fh_End
   LONG	  fh_Funcs
fh_Func1 EQU fh_Funcs
   LONG	  fh_Func2
   LONG	  fh_Func3
   LONG	  fh_Args
fh_Arg1 EQU fh_Args
   LONG	  fh_Arg2
   LABEL  fh_SIZEOF * FileHandle

* This is the extension to EXEC Messages used by DOS
 STRUCTURE DosPacket,0
   APTR	  dp_Link	  * pointer to EXEC message
   APTR	  dp_Port	  * pointer to Reply port for the packet
*			  * Must be filled in each send.
   LONG	  dp_Type	  * See ACTION_... below and
*			  * 'R' means Read, 'W' means Write to the file system
   LONG	  dp_Res1	  * For file system calls this is the result
*			  * that would have been returned by the
*			  * function, e.g. Write ('W') returns actual
*			  * length written
   LONG	  dp_Res2	  * For file system calls this is what would
*			  * have been returned by IoErr()
   LONG	  dp_Arg1
*  Device packets common equivalents
dp_Action  EQU	dp_Type
dp_Status  EQU	dp_Res1
dp_Status2 EQU	dp_Res2
dp_BufAddr EQU	dp_Arg1
   LONG	  dp_Arg2
   LONG	  dp_Arg3
   LONG	  dp_Arg4
   LONG	  dp_Arg5
   LONG	  dp_Arg6
   LONG	  dp_Arg7
   LABEL  dp_SIZEOF * DosPacket

* A Packet does not require the Message to before it in memory, but
* for convenience it is useful to associate the two.
* Also see the function init_std_pkt for initializing this STRUCTure

 STRUCTURE StandardPacket,0
   STRUCT sp_Msg,MN_SIZE
   STRUCT sp_Pkt,dp_SIZEOF
   LABEL  sp_SIZEOF * StandardPacket

* Packet types
ACTION_NIL		EQU	0
ACTION_STARTUP		EQU	0
ACTION_GET_BLOCK	EQU	2	;OBSOLETE
ACTION_SET_MAP		EQU	4
ACTION_DIE		EQU	5
ACTION_EVENT		EQU	6
ACTION_CURRENT_VOLUME	EQU	7
ACTION_LOCATE_OBJECT	EQU	8
ACTION_RENAME_DISK	EQU	9
ACTION_WRITE		EQU	'W'
ACTION_READ		EQU	'R'
ACTION_FREE_LOCK	EQU	15
ACTION_DELETE_OBJECT	EQU	16
ACTION_RENAME_OBJECT	EQU	17
ACTION_MORE_CACHE	EQU	18
ACTION_COPY_DIR		EQU	19
ACTION_WAIT_CHAR	EQU	20
ACTION_SET_PROTECT	EQU	21
ACTION_CREATE_DIR	EQU	22
ACTION_EXAMINE_OBJECT	EQU	23
ACTION_EXAMINE_NEXT	EQU	24
ACTION_DISK_INFO	EQU	25
ACTION_INFO		EQU	26
ACTION_FLUSH		EQU	27
ACTION_SET_COMMENT	EQU	28
ACTION_PARENT		EQU	29
ACTION_TIMER		EQU	30
ACTION_INHIBIT		EQU	31
ACTION_DISK_TYPE	EQU	32
ACTION_DISK_CHANGE	EQU	33
ACTION_SET_DATE		EQU	34

ACTION_SCREEN_MODE	EQU	994

ACTION_READ_RETURN	EQU	1001
ACTION_WRITE_RETURN	EQU	1002
ACTION_SEEK		EQU	1008
ACTION_FINDUPDATE	EQU	1004
ACTION_FINDINPUT	EQU	1005
ACTION_FINDOUTPUT	EQU	1006
ACTION_END		EQU	1007
ACTION_SET_FILE_SIZE	EQU	1022	; fast file system only
ACTION_WRITE_PROTECT	EQU	1023	; fast file system only

* new 2.0 packets
ACTION_SAME_LOCK	EQU	40
ACTION_CHANGE_SIGNAL	EQU	995
ACTION_FORMAT		EQU	1020
ACTION_MAKE_LINK	EQU	1021
*
*
ACTION_READ_LINK	EQU	1024
ACTION_FH_FROM_LOCK	EQU	1026
ACTION_IS_FILESYSTEM	EQU	1027
ACTION_CHANGE_MODE	EQU	1028
*
ACTION_COPY_DIR_FH	EQU	1030
ACTION_PARENT_FH	EQU	1031
ACTION_EXAMINE_ALL	EQU	1033
ACTION_EXAMINE_FH	EQU	1034

ACTION_LOCK_RECORD	EQU	2008
ACTION_FREE_RECORD	EQU	2009

ACTION_ADD_NOTIFY	EQU	4097
ACTION_REMOVE_NOTIFY	EQU	4098

* Tell a file system to serialize the current volume. This is typically
* done by changing the creation date of the disk. This packet does not take
* any arguments.  NOTE: be prepared to handle failure of this packet for
* V37 ROM filesystems.

ACTION_SERIALIZE_DISK	EQU	4200

* A structure for holding error messages - stored as array with error == 0
* for the last entry.

 STRUCTURE ErrorString,0
    APTR   estr_Nums
    APTR   estr_Strings
        LABEL  ErrorString_SIZEOF

* DOS library node structure.
* This is the data at positive offsets from the library node.
* Negative offsets from the node is the jump table to DOS functions
* node = (STRUCT DosLibrary *) OpenLibrary( "dos.library" .. )

 STRUCTURE DosLibrary,0
    STRUCT  dl_lib,LIB_SIZE
    APTR    dl_Root	     * Pointer to RootNode, described below
    APTR    dl_GV	     * Pointer to BCPL global vector
    LONG    dl_A2	     * BCPL standard register values
    LONG    dl_A5
    LONG    dl_A6
    APTR    dl_Errors	     * PRIVATE pointer to array of error msgs
    APTR    dl_TimeReq	     * PRIVATE pointer to timer request
    APTR    dl_UtilityBase   * PRIVATE pointer to utility library base
    APTR    dl_IntuitionBase * PRIVATE pointer to intuition library base
    LABEL   dl_SIZEOF *	 DosLibrary

*

 STRUCTURE RootNode,0
    BPTR    rn_TaskArray       * [0] is max number of CLI's
*			       * [1] is APTR to process id of CLI 1
*			       * [n] is APTR to process id of CLI n
    BPTR    rn_ConsoleSegment  * SegList for the CLI
    STRUCT  rn_Time,ds_SIZEOF  * Current time
    LONG    rn_RestartSeg      * SegList for the disk validator process
    BPTR    rn_Info	       * Pointer to the Info structure
    BPTR    rn_FileHandlerSegment * code for file handler
    STRUCT  rn_CliList,MLH_SIZE * new list of all CLI processes
*			       * the first cpl_Array is also rn_TaskArray
    APTR    rn_BootProc	       * private! ptr to msgport of boot fs
    BPTR    rn_ShellSegment    * seglist for Shell (for NewShell)
    LONG    rn_Flags	       * dos flags
    LABEL   rn_SIZEOF * RootNode

 BITDEF	RN,WILDSTAR,24
 BITDEF RN,PRIVATE1,1

* ONLY to be allocated by DOS!
 STRUCTURE CliProcList,0
    STRUCT  cpl_Node,MLN_SIZE
    LONG    cpl_First	       * number of first entry in array
    APTR    cpl_Array	       * pointer to array of process msgport pointers
*			       * [0] is max number of CLI's in this entry (n)
*			       * [1] is APTR to process id of CLI cpl_First
*			       * [n] is APTR to process id of CLI cpl_First+n-1
    LABEL   cpl_SIZEOF

 STRUCTURE DosInfo,0
    BPTR    di_McName	       * PRIVATE: system resident module list
di_ResList EQU di_McName
    BPTR    di_DevInfo	       * Device List
    BPTR    di_Devices	       * Currently zero
    BPTR    di_Handlers	       * Currently zero
    APTR    di_NetHand	       * Network handler processid currently zero
    STRUCT  di_DevLock,SS_SIZE    * do NOT access directly!
    STRUCT  di_EntryLock,SS_SIZE  * do NOT access directly!
    STRUCT  di_DeleteLock,SS_SIZE * do NOT access directly!
    LABEL   di_SIZEOF * DosInfo

* structure for the Dos resident list.  Do NOT allocate these, use
* AddSegment(), and heed the warnings in the autodocs!

 STRUCTURE Segment,0
    BPTR seg_Next
    LONG seg_UC
    BPTR seg_Seg
    STRUCT seg_Name,4	; Actually the first 4 chars of BSTR name
    LABEL seg_SIZEOF

CMD_SYSTEM	EQU	-1
CMD_INTERNAL	EQU	-2
CMD_DISABLED	EQU	-999

* DOS Processes started from the CLI via RUN or NEWCLI have this additional
* set to data associated with them

 STRUCTURE CommandLineInterface,0
    LONG   cli_Result2	       * Value of IoErr from last command
    BSTR   cli_SetName	       * Name of current directory
    BPTR   cli_CommandDir      * Head of the path locklist
    LONG   cli_ReturnCode      * Return code from last command
    BSTR   cli_CommandName     * Name of current command
    LONG   cli_FailLevel       * Fail level (set by FAILAT)
    BSTR   cli_Prompt	       * Current prompt (set by PROMPT)
    BPTR   cli_StandardInput   * Default (terminal) CLI input
    BPTR   cli_CurrentInput    * Current CLI input
    BSTR   cli_CommandFile     * Name of EXECUTE command file
    LONG   cli_Interactive     * Boolean True if prompts required
    LONG   cli_Background      * Boolean True if CLI created by RUN
    BPTR   cli_CurrentOutput   * Current CLI output
    LONG   cli_DefaultStack    * Stack size to be obtained in long words
    BPTR   cli_StandardOutput  * Default (terminal) CLI output
    BPTR   cli_Module	       * SegList of currently loaded command
    LABEL  cli_SIZEOF	       * CommandLineInterface

* This structure can take on different values depending on whether it is
* a device, an assigned directory, or a volume.	 Below is the structure
* reflecting volumes only.  Following that is the structure representing
* only devices. Following that is the unioned structure representing all
* the values

* structure representing a volume

 STRUCTURE DevList,0
    BPTR	dl_Next			; bptr to next device list
    LONG	dl_Type			; see DLT below
    APTR	dl_Task			; ptr to handler task
    BPTR	dl_Lock			; not for volumes
    STRUCT	dl_VolumeDate,ds_SIZEOF ; creation date
    BPTR	dl_LockList		; outstanding locks
    LONG	dl_DiskType		; 'DOS', etc
    LONG	dl_unused
    BSTR	dl_Name			; bptr to bcpl name
    LABEL	DevList_SIZEOF

* device structure (same as the DeviceNode structure in filehandler.i

 STRUCTURE	 DevInfo,0
    BPTR    dvi_Next
    LONG    dvi_Type
    APTR    dvi_Task
    BPTR    dvi_Lock
    BSTR    dvi_Handler
    LONG    dvi_Stacksize
    LONG    dvi_Priority
    LONG    dvi_Startup
    BPTR    dvi_SegList
    BPTR    dvi_GlobVec
    BSTR    dvi_Name
    LABEL   dvi_SIZEOF

* combined structure for devices, assigned directories, volumes

 STRUCTURE DosList,0
    BPTR     dol_Next	     ; bptr to next device on lis
    LONG     dol_Type	     ; see DLT below
    APTR     dol_Task	     ; ptr to handler task
    BPTR     dol_Lock

    STRUCT	dol_VolumeDate,0	; creation date (UNION)
    STRUCT	dol_AssignName,0	; name for assign path (UNION)
    BSTR	dol_Handler		; file name to load if seglist is null
    STRUCT	dol_List,0		; List of directories assigned (UNION)
    LONG	dol_StackSize		; stacksize to use when starting process
    LONG	dol_Priority		; task priority when starting process

    STRUCT	dol_LockList,0		; outstanding locks (UNION)
    ULONG	dol_Startup		; startup msg: FileSysStartupMsg
                    ; for disks

    STRUCT	dol_DiskType,0		; 'DOS', etc (UNION)
    BPTR	dol_SegList		; already loaded code for new task

    BPTR	dol_GlobVec		; BCPL global vector

    BSTR	dol_Name		; bptr to bcpl name
    LABEL	DosList_SIZEOF

* definitions for dl_Type
DLT_DEVICE	EQU	0
DLT_DIRECTORY	EQU	1	; assign
DLT_VOLUME	EQU	2
DLT_LATE	EQU	3	; late-binding assign
DLT_NONBINDING	EQU	4	; non-binding assign (AssignPath)
DLT_PRIVATE	EQU	-1	; for internal use only

* structure return by GetDeviceProc()
 STRUCTURE DevProc,0
    APTR	dvp_Port	; struct MsgPort *
    BPTR	dvp_Lock
    ULONG	dvp_Flags
    APTR	dvp_DevNode	; struct DosList * - DON'T TOUCH OR USE!
    LABEL	dvp_SIZEOF

* definitions for dvp_Flags
 BITDEF	DVP,UNLOCK,0
 BITDEF	DVP,ASSIGN,1

* Flags to be passed to LockDosList(), etc
 BITDEF LD,DEVICES,2
 BITDEF LD,VOLUMES,3
 BITDEF LD,ASSIGNS,4
 BITDEF LD,ENTRY,5
 BITDEF LD,DELETE,6

* You MUST specify one of LDF_READ or LDF_WRITE
 BITDEF LD,READ,0
 BITDEF LD,WRITE,1

* actually all but LDF_ENTRY (which is used for internal locking)
LDF_ALL	EQU	(LDF_DEVICES!LDF_VOLUMES!LDF_ASSIGNS)

* a lock structure, as returned by Lock() or DupLock()
 STRUCTURE FileLock,0
    BPTR	fl_Link			; bcpl pointer to next lock
    LONG	fl_Key			; disk block number
    LONG	fl_Access		; exclusive or shared
    APTR	fl_Task			; handler task's port
    BPTR	fl_Volume		; bptr to DLT_VOLUME DosList entry
    LABEL	fl_SIZEOF

* error report types for ErrorReport()
REPORT_STREAM	EQU	0	; a stream
REPORT_TASK	EQU	1	; a process - unused
REPORT_LOCK	EQU	2	; a lock
REPORT_VOLUME	EQU	3	; a volume node
REPORT_INSERT	EQU	4	; please insert volume

* Special error codes for ErrorReport()
ABORT_DISK_ERROR	EQU	296	; Read/write error
ABORT_BUSY		EQU	288	; You MUST replace...

* types for initial packets to shells from run/newcli/execute/system.
* For shell-writers only
RUN_EXECUTE		EQU	-1
RUN_SYSTEM		EQU	-2
RUN_SYSTEM_ASYNCH	EQU	-3

* Types for fib_DirEntryType.  NOTE that both USERDIR and ROOT are
* directories, and that directory/file checks should use <0 and >=0.
* This is not necessarily exhaustive!  Some handlers may use other
* values as needed, though <0 and >=0 should remain as supported as
* possible.
ST_ROOT		EQU	1
ST_USERDIR	EQU	2
ST_SOFTLINK	EQU	3	; looks like dir, but may point to a file!
ST_LINKDIR	EQU	4	; hard link to dir
ST_FILE		EQU	-3	; must be negative for FIB!
ST_LINKFILE	EQU	-4	; hard link to file
ST_PIPEFILE	EQU	-5	; for pipes that support ExamineFH

    ENDC	; DOS_DOSEXTENS_I


Includes/dos/exall.i

    IFND DOS_EXALL_I
DOS_EXALL_I SET 1
**
**	$Filename: dos/exall.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.5 $
**	$Date: 90/07/12 $
**
**	include file for ExAll() data structures
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**

     IFND  EXEC_TYPES_I
     INCLUDE "exec/types.i"
     ENDC

     IFND UTILITY_HOOKS_I
     INCLUDE "utility/hooks.i"
     ENDC

* values that can be passed for what data you want from ExAll()
* each higher value includes those below it (numerically)
* you MUST chose one of these values

ED_NAME		EQU	1
ED_TYPE		EQU	2
ED_SIZE		EQU	3
ED_PROTECTION	EQU	4
ED_DATE		EQU	5
ED_COMMENT	EQU	6

*
*   Structure in which exall results are returned in.  Note that only the
*   fields asked for will exist!
*

 STRUCTURE ExAllData,0
    APTR	ed_Next		; next struct ExAllData
    APTR	ed_Name		; to CSTR
    LONG	ed_Type		; type of file/dir
    ULONG	ed_Size		; size of file (if file) in bytes
    ULONG	ed_Prot		; protection bits
    ULONG	ed_Days		; datestamp - last modification
    ULONG	ed_Mins
    ULONG	ed_Ticks
    APTR	ed_Comment	; strings will be after last used field
    LABEL	ed_Strings	; strings will start after the last USED field
 LABEL ExAllData_SIZEOF

*
*   Control structure passed to ExAll.	Unused fields MUST be initialized to
*   0, expecially eac_LastKey.
*
*   eac_MatchFunc is a hook (see utility.library documentation for usage)
*   It should return true if the entry is to returned, false if it is to be
*   ignored.
*
*   This structure MUST be allocated by AllocDosObject()!
*

 STRUCTURE ExAllControl,0
    ULONG	eac_Entries	 ; number of entries returned in buffer
    ULONG	eac_LastKey	 ; Don't touch inbetween linked ExAll calls!
    APTR	eac_MatchString  ; wildcard CSTR for pattern match or NULL
    APTR	eac_MatchFunc    ; optional private wildcard function hook
 LABEL ExAllControl_SIZEOF

    ENDC	; DOS_EXALL_I


Includes/dos/record.h

#ifndef DOS_RECORD_H
#define DOS_RECORD_H
/*
**
**	$Filename: dos/record.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.5 $
**	$Date: 90/07/12 $
**
**	include file for record locking
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**
*/

#ifndef DOS_DOS_H
#include "dos/dos.h"
#endif

/* Modes for LockRecord/LockRecords() */
#define REC_EXCLUSIVE		0
#define REC_EXCLUSIVE_IMMED	1
#define REC_SHARED		2
#define REC_SHARED_IMMED	3

/* struct to be passed to LockRecords()/UnLockRecords() */

struct RecordLock {
    BPTR	rec_FH;		/* filehandle */
    ULONG	rec_Offset;	/* offset in file */
    ULONG	rec_Length;	/* length of file to be locked */
    ULONG	rec_Mode;	/* Type of lock */
};

#endif /* DOS_RECORD_H */


Includes/dos/datetime.i

    IFND	DOS_DATETIME_I
DOS_DATETIME_I SET 1

**
**	$Filename: dos/datetime.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.7 $
**	$Date: 90/07/12 $
**
**	Date and time assembler header for AmigaDOS
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND DOS_DOS_I
    INCLUDE "dos/dos.i"
    ENDC

*
*	Data structures and equates used by the V1.4 DOS functions
* StrtoDate() and DatetoStr()
*
*

*--------- String/Date structures etc
    STRUCTURE	DateTime,0
    STRUCT	dat_Stamp,ds_SIZEOF	;DOS DateStamp
    UBYTE	dat_Format		;controls appearance of dat_StrDate
    UBYTE	dat_Flags		;see BITDEF's below
    CPTR	dat_StrDay		;day of the week string
    CPTR	dat_StrDate		;date string
    CPTR	dat_StrTime		;time string
    LABEL	dat_SIZEOF
*
* You need this much room for each of the DateTime strings:
LEN_DATSTRING	EQU	16

*	flags for dat_Flags
*
    BITDEF	DT,SUBST,0		;substitute Today, Tomorrow, etc.
    BITDEF	DT,FUTURE,1		;day of the week is in future
*
*	date format values
*
FORMAT_DOS	equ	0		; dd-mmm-yy
FORMAT_INT	equ	1		; yy-mm-dd
FORMAT_USA	equ	2		; mm-dd-yy
FORMAT_CDN	equ	3		; dd-mm-yy
FORMAT_MAX	equ	FORMAT_CDN

    ENDC	; DOS_DATETIME_I


Includes/dos/doshunks.h

#ifndef DOS_DOSHUNKS_H
#define DOS_DOSHUNKS_H
/*
**	$Filename: dos/doshunks.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.5 $
**	$Date: 90/07/12 $
**
**	Hunk definitions for object and load modules.
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
*/

/* hunk types */
#define HUNK_UNIT	999
#define HUNK_NAME	1000
#define HUNK_CODE	1001
#define HUNK_DATA	1002
#define HUNK_BSS	1003
#define HUNK_RELOC32	1004
#define HUNK_RELOC16	1005
#define HUNK_RELOC8	1006
#define HUNK_EXT	1007
#define HUNK_SYMBOL	1008
#define HUNK_DEBUG	1009
#define HUNK_END	1010
#define HUNK_HEADER	1011

#define HUNK_OVERLAY	1013
#define HUNK_BREAK	1014

#define HUNK_DREL32	1015
#define HUNK_DREL16	1016
#define HUNK_DREL8	1017

#define HUNK_LIB	1018
#define HUNK_INDEX	1019

/* hunk_ext sub-types */
#define EXT_SYMB	0	/* symbol table */
#define EXT_DEF		1	/* relocatable definition */
#define EXT_ABS		2	/* Absolute definition */
#define EXT_RES		3	/* no longer supported */
#define EXT_REF32	129	/* 32 bit reference to symbol */
#define EXT_COMMON	130	/* 32 bit reference to COMMON block */
#define EXT_REF16	131	/* 16 bit reference to symbol */
#define EXT_REF8	132	/*  8 bit reference to symbol */
#define EXT_DEXT32	133	/* 32 bit data releative reference */
#define EXT_DEXT16	134	/* 16 bit data releative reference */
#define EXT_DEXT8	135	/*  8 bit data releative reference */

#endif	/* DOS_DOSHUNKS_H */


Includes/dos/filehandler.h

#ifndef DOS_FILEHANDLER_H
#define DOS_FILEHANDLER_H
/*
**	$Filename: dos/filehandler.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.5 $
**	$Date: 90/07/12 $
**
**	device and file handler specific code for AmigaDOS
**
**	(C) Copyright 1986-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef	  EXEC_PORTS_H
#include "exec/ports.h"
#endif

#ifndef	  DOS_DOS_H
#include "dos/dos.h"
#endif

/* The disk "environment" is a longword array that describes the
 * disk geometry.  It is variable sized, with the length at the beginning.
 * Here are the constants for a standard geometry.
 */

struct DosEnvec {
    ULONG de_TableSize;	     /* Size of Environment vector */
    ULONG de_SizeBlock;	     /* in longwords: standard value is 128 */
    ULONG de_SecOrg;	     /* not used; must be 0 */
    ULONG de_Surfaces;	     /* # of heads (surfaces). drive specific */
    ULONG de_SectorPerBlock; /* not used; must be 1 */
    ULONG de_BlocksPerTrack; /* blocks per track. drive specific */
    ULONG de_Reserved;	     /* DOS reserved blocks at start of partition. */
    ULONG de_PreAlloc;	     /* DOS reserved blocks at end of partition */
    ULONG de_Interleave;     /* usually 0 */
    ULONG de_LowCyl;	     /* starting cylinder. typically 0 */
    ULONG de_HighCyl;	     /* max cylinder. drive specific */
    ULONG de_NumBuffers;     /* Initial # DOS of buffers.  */
    ULONG de_BufMemType;     /* type of mem to allocate for buffers */
    ULONG de_MaxTransfer;    /* Max number of bytes to transfer at a time */
    ULONG de_Mask;	     /* Address Mask to block out certain memory */
    LONG  de_BootPri;	     /* Boot priority for autoboot */
    ULONG de_DosType;	     /* ASCII (HEX) string showing filesystem type;
                  * 0X444F5300 is old filesystem,
                  * 0X444F5301 is fast file system */
    ULONG de_Baud;	     /* Baud rate for serial handler */
    ULONG de_Control;	     /* Control word for handler/filesystem */
    ULONG de_BootBlocks;     /* Number of blocks containing boot code */

};

/* these are the offsets into the array */

#define DE_TABLESIZE	0	/* standard value is 11 */
#define DE_SIZEBLOCK	1	/* in longwords: standard value is 128 */
#define DE_SECORG	2	/* not used; must be 0 */
#define DE_NUMHEADS	3	/* # of heads (surfaces). drive specific */
#define DE_SECSPERBLK	4	/* not used; must be 1 */
#define DE_BLKSPERTRACK 5	/* blocks per track. drive specific */
#define DE_RESERVEDBLKS 6	/* unavailable blocks at start.	 usually 2 */
#define DE_PREFAC	7	/* not used; must be 0 */
#define DE_INTERLEAVE	8	/* usually 0 */
#define DE_LOWCYL	9	/* starting cylinder. typically 0 */
#define DE_UPPERCYL	10	/* max cylinder.  drive specific */
#define DE_NUMBUFFERS	11	/* starting # of buffers.  typically 5 */
#define DE_MEMBUFTYPE	12	/* type of mem to allocate for buffers. */
#define DE_BUFMEMTYPE	12	/* same as above, better name
                 * 1 is public, 3 is chip, 5 is fast */
#define DE_MAXTRANSFER	13	/* Max number bytes to transfer at a time */
#define DE_MASK		14	/* Address Mask to block out certain memory */
#define DE_BOOTPRI	15	/* Boot priority for autoboot */
#define DE_DOSTYPE	16	/* ASCII (HEX) string showing filesystem type;
                 * 0X444F5300 is old filesystem,
                 * 0X444F5301 is fast file system */
#define DE_BAUD		17	/* Baud rate for serial handler */
#define DE_CONTROL	18	/* Control word for handler/filesystem */
#define DE_BOOTBLOCKS	19	/* Number of blocks containing boot code */

/* The file system startup message is linked into a device node's startup
** field.  It contains a pointer to the above environment, plus the
** information needed to do an exec OpenDevice().
*/
struct FileSysStartupMsg {
    ULONG	fssm_Unit;	/* exec unit number for this device */
    BSTR	fssm_Device;	/* null terminated bstring to the device name */
    BPTR	fssm_Environ;	/* ptr to environment table (see above) */
    ULONG	fssm_Flags;	/* flags for OpenDevice() */
};

/* The include file "libraries/dosextens.h" has a DeviceList structure.
 * The "device list" can have one of three different things linked onto
 * it.	Dosextens defines the structure for a volume.  DLT_DIRECTORY
 * is for an assigned directory.  The following structure is for
 * a dos "device" (DLT_DEVICE).
*/

struct DeviceNode {
    BPTR	dn_Next;	/* singly linked list */
    ULONG	dn_Type;	/* always 0 for dos "devices" */
    struct MsgPort *dn_Task;	/* standard dos "task" field.  If this is
                 * null when the node is accesses, a task
                 * will be started up */
    BPTR	dn_Lock;	/* not used for devices -- leave null */
    BSTR	dn_Handler;	/* filename to loadseg (if seglist is null) */
    ULONG	dn_StackSize;	/* stacksize to use when starting task */
    LONG	dn_Priority;	/* task priority when starting task */
    BPTR	dn_Startup;	/* startup msg: FileSysStartupMsg for disks */
    BPTR	dn_SegList;	/* code to run to start new task (if necessary).
                 * if null then dn_Handler will be loaded. */
    BPTR	dn_GlobalVec;	/* BCPL global vector to use when starting
                 * a task.  -1 means that dn_SegList is not
                 * for a bcpl program, so the dos won't
                 * try and construct one.  0 tell the
                 * dos that you obey BCPL linkage rules,
                 * and that it should construct a global
                 * vector for you.
                 */
    BSTR	dn_Name;	/* the node name, e.g. '\3','D','F','3' */
};

#endif	/* DOS_FILEHANDLER_H */


Includes/dos/record.i

    IFND DOS_RECORD_I
DOS_RECORD_I SET 1
**
**	$Filename: dos/record.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.5 $
**	$Date: 90/07/12 $
**
**	include file for record locking
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**

     IFND  DOS_DOS_I
     INCLUDE "dos/dos.i"
     ENDC

* Modes for LockRecord/LockRecords()
REC_EXCLUSIVE		EQU	0
REC_EXCLUSIVE_IMMED	EQU	1
REC_SHARED		EQU	2
REC_SHARED_IMMED	EQU	3

* struct to be passed to LockRecords()/UnLockRecords()

 STRUCTURE RecordLock,0
    BPTR	rec_FH		; filehandle
    ULONG	rec_Offset	; offset in file
    ULONG	rec_Length	; length of file to be locked
    ULONG	rec_Mode	; Type of lock
 LABEL RecordLock_SIZEOF

    ENDC	; DOS_RECORD_I


Includes/dos/dos.h

#ifndef DOS_DOS_H
#define DOS_DOS_H
/*
**	$Filename: dos/dos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.24 $
**	$Date: 91/10/29 $
**
**	Standard C header for AmigaDOS
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include "exec/types.h"
#endif

#define	 DOSNAME  "dos.library"

/* Predefined Amiga DOS global constants */

#define DOSTRUE (-1L)
#define DOSFALSE (0L)

/* Mode parameter to Open() */
#define MODE_OLDFILE	     1005   /* Open existing file read/write
                     * positioned at beginning of file. */
#define MODE_NEWFILE	     1006   /* Open freshly created file (delete
                     * old file) read/write, exclusive lock. */
#define MODE_READWRITE	     1004   /* Open old file w/shared lock,
                     * creates file if doesn't exist. */

/* Relative position to Seek() */
#define OFFSET_BEGINNING    -1	    /* relative to Begining Of File */
#define OFFSET_CURRENT	     0	    /* relative to Current file position */
#define OFFSET_END	     1	    /* relative to End Of File	  */

#define OFFSET_BEGINING	    OFFSET_BEGINNING  /* ancient compatibility */

#define BITSPERBYTE	     8
#define BYTESPERLONG	     4
#define BITSPERLONG	     32
#define MAXINT		     0x7FFFFFFF
#define MININT		     0x80000000

/* Passed as type to Lock() */
#define SHARED_LOCK	     -2	    /* File is readable by others */
#define ACCESS_READ	     -2	    /* Synonym */
#define EXCLUSIVE_LOCK	     -1	    /* No other access allowed	  */
#define ACCESS_WRITE	     -1	    /* Synonym */

struct DateStamp {
   LONG	 ds_Days;	      /* Number of days since Jan. 1, 1978 */
   LONG	 ds_Minute;	      /* Number of minutes past midnight */
   LONG	 ds_Tick;	      /* Number of ticks past minute */
}; /* DateStamp */

#define TICKS_PER_SECOND      50   /* Number of ticks in one second */

/* Returned by Examine() and ExNext(), must be on a 4 byte boundary */
struct FileInfoBlock {
   LONG	  fib_DiskKey;
   LONG	  fib_DirEntryType;  /* Type of Directory. If < 0, then a plain file.
                  * If > 0 a directory */
   char	  fib_FileName[108]; /* Null terminated. Max 30 chars used for now */
   LONG	  fib_Protection;    /* bit mask of protection, rwxd are 3-0.	   */
   LONG	  fib_EntryType;
   LONG	  fib_Size;	     /* Number of bytes in file */
   LONG	  fib_NumBlocks;     /* Number of blocks in file */
   struct DateStamp fib_Date;/* Date file last changed */
   char	  fib_Comment[80];  /* Null terminated comment associated with file */
   char	  fib_Reserved[36];
}; /* FileInfoBlock */

/* FIB stands for FileInfoBlock */

/* FIBB are bit definitions, FIBF are field definitions */
#define FIBB_SCRIPT    6	/* program is a script (execute) file */
#define FIBB_PURE      5	/* program is reentrant and rexecutable */
#define FIBB_ARCHIVE   4	/* cleared whenever file is changed */
#define FIBB_READ      3	/* ignored by old filesystem */
#define FIBB_WRITE     2	/* ignored by old filesystem */
#define FIBB_EXECUTE   1	/* ignored by system, used by Shell */
#define FIBB_DELETE    0	/* prevent file from being deleted */
#define FIBF_SCRIPT    (1<<FIBB_SCRIPT)
#define FIBF_PURE      (1<<FIBB_PURE)
#define FIBF_ARCHIVE   (1<<FIBB_ARCHIVE)
#define FIBF_READ      (1<<FIBB_READ)
#define FIBF_WRITE     (1<<FIBB_WRITE)
#define FIBF_EXECUTE   (1<<FIBB_EXECUTE)
#define FIBF_DELETE    (1<<FIBB_DELETE)

/* Standard maximum length for an error string from fault.  However, most */
/* error strings should be kept under 60 characters if possible.  Don't   */
/* forget space for the header you pass in. */
#define FAULT_MAX	82

/* All BCPL data must be long word aligned.  BCPL pointers are the long word
 *  address (i.e byte address divided by 4 (>>2)) */
typedef long  BPTR;		    /* Long word pointer */
typedef long  BSTR;		    /* Long word pointer to BCPL string	 */

/* Convert BPTR to typical C pointer */
#ifdef OBSOLETE_LIBRARIES_DOS_H
#define BADDR( bptr )	(((ULONG)bptr) << 2)
#else
/* This one has no problems with CASTing */
#define BADDR(x)	((APTR)((ULONG)(x) << 2))
#endif
/* Convert address into a BPTR */
#define MKBADDR(x)	(((LONG)(x)) >> 2)

/* BCPL strings have a length in the first byte and then the characters.
 * For example:	 s[0]=3 s[1]=S s[2]=Y s[3]=S				 */

/* returned by Info(), must be on a 4 byte boundary */
struct InfoData {
   LONG	  id_NumSoftErrors;	/* number of soft errors on disk */
   LONG	  id_UnitNumber;	/* Which unit disk is (was) mounted on */
   LONG	  id_DiskState;		/* See defines below */
   LONG	  id_NumBlocks;		/* Number of blocks on disk */
   LONG	  id_NumBlocksUsed;	/* Number of block in use */
   LONG	  id_BytesPerBlock;
   LONG	  id_DiskType;		/* Disk Type code */
   BPTR	  id_VolumeNode;	/* BCPL pointer to volume node */
   LONG	  id_InUse;		/* Flag, zero if not in use */
}; /* InfoData */

/* ID stands for InfoData */
    /* Disk states */
#define ID_WRITE_PROTECTED 80	 /* Disk is write protected */
#define ID_VALIDATING	   81	 /* Disk is currently being validated */
#define ID_VALIDATED	   82	 /* Disk is consistent and writeable */

    /* Disk types */
/* ID_INTER_* use international case comparison routines for hashing */
#define ID_NO_DISK_PRESENT	(-1)
#define ID_UNREADABLE_DISK	(0x42414400L)	/* 'BAD\0' */
#define ID_DOS_DISK		(0x444F5300L)	/* 'DOS\0' */
#define ID_FFS_DISK		(0x444F5301L)	/* 'DOS\1' */
#define ID_INTER_DOS_DISK	(0x444F5302L)	/* 'DOS\2' */
#define ID_INTER_FFS_DISK	(0x444F5303L)	/* 'DOS\3' */
#define ID_NOT_REALLY_DOS	(0x4E444F53L)	/* 'NDOS'  */
#define ID_KICKSTART_DISK	(0x4B49434BL)	/* 'KICK'  */
#define ID_MSDOS_DISK		(0x4d534400L)	/* 'MSD\0' */

/* Errors from IoErr(), etc. */
#define ERROR_NO_FREE_STORE		  103
#define ERROR_TASK_TABLE_FULL		  105
#define ERROR_BAD_TEMPLATE		  114
#define ERROR_BAD_NUMBER		  115
#define ERROR_REQUIRED_ARG_MISSING	  116
#define ERROR_KEY_NEEDS_ARG		  117
#define ERROR_TOO_MANY_ARGS		  118
#define ERROR_UNMATCHED_QUOTES		  119
#define ERROR_LINE_TOO_LONG		  120
#define ERROR_FILE_NOT_OBJECT		  121
#define ERROR_INVALID_RESIDENT_LIBRARY	  122
#define ERROR_NO_DEFAULT_DIR		  201
#define ERROR_OBJECT_IN_USE		  202
#define ERROR_OBJECT_EXISTS		  203
#define ERROR_DIR_NOT_FOUND		  204
#define ERROR_OBJECT_NOT_FOUND		  205
#define ERROR_BAD_STREAM_NAME		  206
#define ERROR_OBJECT_TOO_LARGE		  207
#define ERROR_ACTION_NOT_KNOWN		  209
#define ERROR_INVALID_COMPONENT_NAME	  210
#define ERROR_INVALID_LOCK		  211
#define ERROR_OBJECT_WRONG_TYPE		  212
#define ERROR_DISK_NOT_VALIDATED	  213
#define ERROR_DISK_WRITE_PROTECTED	  214
#define ERROR_RENAME_ACROSS_DEVICES	  215
#define ERROR_DIRECTORY_NOT_EMPTY	  216
#define ERROR_TOO_MANY_LEVELS		  217
#define ERROR_DEVICE_NOT_MOUNTED	  218
#define ERROR_SEEK_ERROR		  219
#define ERROR_COMMENT_TOO_BIG		  220
#define ERROR_DISK_FULL			  221
#define ERROR_DELETE_PROTECTED		  222
#define ERROR_WRITE_PROTECTED		  223
#define ERROR_READ_PROTECTED		  224
#define ERROR_NOT_A_DOS_DISK		  225
#define ERROR_NO_DISK			  226
#define ERROR_NO_MORE_ENTRIES		  232
/* added for 1.4 */
#define ERROR_IS_SOFT_LINK		  233
#define ERROR_OBJECT_LINKED		  234
#define ERROR_BAD_HUNK			  235
#define ERROR_NOT_IMPLEMENTED		  236
#define ERROR_RECORD_NOT_LOCKED		  240
#define ERROR_LOCK_COLLISION		  241
#define ERROR_LOCK_TIMEOUT		  242
#define ERROR_UNLOCK_ERROR		  243

/* error codes 303-305 are defined in dosasl.h */

/* These are the return codes used by convention by AmigaDOS commands */
/* See FAILAT and IF for relvance to EXECUTE files		      */
#define RETURN_OK			    0  /* No problems, success */
#define RETURN_WARN			    5  /* A warning only */
#define RETURN_ERROR			   10  /* Something wrong */
#define RETURN_FAIL			   20  /* Complete or severe failure*/

/* Bit numbers that signal you that a user has issued a break */
#define SIGBREAKB_CTRL_C   12
#define SIGBREAKB_CTRL_D   13
#define SIGBREAKB_CTRL_E   14
#define SIGBREAKB_CTRL_F   15

/* Bit fields that signal you that a user has issued a break */
/* for example:	 if (SetSignal(0,0) & SIGBREAKF_CTRL_C) cleanup_and_exit(); */
#define SIGBREAKF_CTRL_C   (1<<SIGBREAKB_CTRL_C)
#define SIGBREAKF_CTRL_D   (1<<SIGBREAKB_CTRL_D)
#define SIGBREAKF_CTRL_E   (1<<SIGBREAKB_CTRL_E)
#define SIGBREAKF_CTRL_F   ((long)1<<SIGBREAKB_CTRL_F)

/* Values returned by SameLock() */
#define LOCK_DIFFERENT		-1
#define LOCK_SAME		0
#define LOCK_SAME_VOLUME	1	/* locks are on same volume */
#define LOCK_SAME_HANDLER	LOCK_SAME_VOLUME
/* LOCK_SAME_HANDLER was a misleading name, def kept for src compatibility */

/* types for ChangeMode() */
#define CHANGE_LOCK	0
#define CHANGE_FH	1

/* Values for MakeLink() */
#define LINK_HARD	0
#define LINK_SOFT	1	/* softlinks are not fully supported yet */

/* values returned by ReadItem */
#define	ITEM_EQUAL	-2		/* "=" Symbol */
#define ITEM_ERROR	-1		/* error */
#define ITEM_NOTHING	0		/* *N, ;, endstreamch */
#define ITEM_UNQUOTED	1		/* unquoted item */
#define ITEM_QUOTED	2		/* quoted item */

/* types for AllocDosObject/FreeDosObject */
#define DOS_FILEHANDLE		0	/* few people should use this */
#define DOS_EXALLCONTROL	1	/* Must be used to allocate this! */
#define	DOS_FIB			2	/* useful */
#define DOS_STDPKT		3	/* for doing packet-level I/O */
#define DOS_CLI			4	/* for shell-writers, etc */
#define DOS_RDARGS		5	/* for ReadArgs if you pass it in */

#endif	/* DOS_DOS_H */


Includes/dos/doshunks.i

    IFND	DOS_DOSHUNKS_I
DOS_DOSHUNKS_I	SET	1
**
**	$Filename: dos/doshunks.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.6 $
**	$Date: 91/02/10 $
**
**	Hunk definitions for object and load modules.
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**

* hunk types

HUNK_UNIT	EQU	999
HUNK_NAME	EQU	1000
HUNK_CODE	EQU	1001
HUNK_DATA	EQU	1002
HUNK_BSS	EQU	1003
HUNK_RELOC32	EQU	1004
HUNK_RELOC16	EQU	1005
HUNK_RELOC8	EQU	1006
HUNK_EXT	EQU	1007
HUNK_SYMBOL	EQU	1008
HUNK_DEBUG	EQU	1009
HUNK_END	EQU	1010
HUNK_HEADER	EQU	1011

HUNK_OVERLAY	EQU	1013
HUNK_BREAK	EQU	1014

HUNK_DREL32	EQU	1015
HUNK_DREL16	EQU	1016
HUNK_DREL8	EQU	1017

HUNK_LIB	EQU	1018
HUNK_INDEX	EQU	1019

* hunk_ext sub-types

EXT_SYMB	EQU	0	; symbol table
EXT_DEF		EQU	1	; relocatable definition
EXT_ABS		EQU	2	; Absolute definition
EXT_RES		EQU	3	; no longer supported
EXT_REF32	EQU	129	; 32 bit reference to symbol
EXT_COMMON	EQU	130	; 32 bit reference to COMMON block
EXT_REF16	EQU	131	; 16 bit reference to symbol
EXT_REF8	EQU	132	;  8 bit reference to symbol
EXT_DEXT32	EQU	133	; 32 bit data releative reference
EXT_DEXT16	EQU	134	; 16 bit data releative reference
EXT_DEXT8	EQU	135	;  8 bit data releative reference

    ENDC	; DOS_DOSHUNKS_I


Includes/dos/filehandler.i

    IFND	DOS_FILEHANDLER_I
DOS_FILEHANDLER_I SET	1
**
**	$Filename: dos/filehandler.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.4 $
**	$Date: 90/07/12 $
**
**	device and file handler specific code for AmigaDOS
**
**	(C) Copyright 1986-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND	  EXEC_TYPES_I
    INCLUDE "exec/types.i"
    ENDC	; EXEC_TYPES_I

    IFND	  EXEC_PORTS_I
    INCLUDE "exec/ports.i"
    ENDC	; EXEC_PORTS_I

    IFND	  DOS_DOS_I
    INCLUDE "libraries/dos.i"
    ENDC	; DOS_DOS_I

* The disk "environment" is a longword array that describes the
* disk geometry.  It is variable sized, with the length at the beginning.
* Here are the constants for a standard geometry.

 STRUCTURE DosEnvec,0
    ULONG de_TableSize	     ; Size of Environment vector
    ULONG de_SizeBlock	     ; in longwords: standard value is 128
    ULONG de_SecOrg	     ; not used; must be 0
    ULONG de_Surfaces	     ; # of heads (surfaces). drive specific
    ULONG de_SectorPerBlock  ; not used; must be 1
    ULONG de_BlocksPerTrack  ; blocks per track. drive specific
    ULONG de_Reserved	     ; DOS reserved blocks at start of partition.
    ULONG de_PreAlloc	     ; DOS reserved blocks at end of partition
    ULONG de_Interleave	     ; usually 0
    ULONG de_LowCyl	     ; starting cylinder. typically 0
    ULONG de_HighCyl	     ; max cylinder. drive specific
    ULONG de_NumBuffers	     ; Initial # DOS of buffers.
    ULONG de_BufMemType	     ; type of mem to allocate for buffers
    ULONG de_MaxTransfer     ; Max number of bytes to transfer at a time
    ULONG de_Mask	     ; Address Mask to block out certain memory
    LONG  de_BootPri	     ; Boot priority for autoboot
    ULONG de_DosType	     ; ASCII (HEX) string showing filesystem type;
                 ; 0X444F5300 is old filesystem,
                 ; 0X444F5301 is fast file system
    ULONG de_Baud	     ; Baud rate for serial handler
    ULONG de_Control	     ; Control word for handler/filesystem
    ULONG de_BootBlocks      ; Number of blocks containing boot code

    LABEL DosEnvec_SIZEOF

* these are the offsets into the array

DE_TABLESIZE	EQU	0	; standard value is 11
DE_SIZEBLOCK	EQU	1	; in longwords: standard value is 128
DE_SECORG	EQU	2	; not used; must be 0
DE_NUMHEADS	EQU	3	; # of heads (surfaces). drive specific
DE_SECSPERBLK	EQU	4	; not used; must be 1
DE_BLKSPERTRACK EQU	5	; blocks per track. drive specific
DE_RESERVEDBLKS EQU	6	; unavailable blocks at start.	usually 2
DE_PREFAC	EQU	7	; not used; must be 0
DE_INTERLEAVE	EQU	8	; usually 0
DE_LOWCYL	EQU	9	; starting cylinder. typically 0
DE_UPPERCYL	EQU	10	; max cylinder.	 drive specific
DE_NUMBUFFERS	EQU	11	; starting # of buffers.  typically 5
DE_MEMBUFTYPE	EQU	12	; type of mem to allocate for buffers.
DE_BUFMEMTYPE	EQU	12	; same as above, better name
                ; 1 is public, 3 is chip, 5 is fast
DE_MAXTRANSFER	EQU	13	; Maximum number of bytes to transfer at a time
DE_MASK		EQU	14	; Address Mask to block out certain memory
DE_BOOTPRI	EQU	15	; Boot priority for autoboot
DE_DOSTYPE	EQU	16	; ASCII (HEX) string showing filesystem type
                ; 0X444F5300 is old filesystem,
                ; 0X444F5301 is fast file system
DE_BAUD	EQU	17	; Baud rate for serial handler
DE_CONTROL	EQU	18	; Control word for handler/filesystem
DE_BOOTBLOCKS	EQU	19	; Number of blocks containing boot code

*
* The file system startup message is linked into a device node's startup
* field.  It contains a pointer to the above environment, plus the
* information needed to do an exec OpenDevice().
*

 STRUCTURE FileSysStartupMsg,0
    ULONG	fssm_Unit	; exec unit number for this device
    BSTR	fssm_Device	; null terminated bstring to the device name
    BPTR	fssm_Environ	; ptr to environment table (see above)
    ULONG	fssm_Flags	; flags for OpenDevice()
    LABEL	FileSysStartupMsg_SIZEOF

* The include file "libraries/dosextens.h" has a DeviceList structure.
* The "device list" can have one of three different things linked onto
* it.  Dosextens defines the structure for a volume.  DLT_DIRECTORY
* is for an assigned directory.	 The following structure is for
* a dos "device" (DLT_DEVICE).

 STRUCTURE DeviceNode,0
    BPTR	dn_Next		; singly linked list
    ULONG	dn_Type		; always 0 for dos "devices"
    CPTR	dn_Task		; standard dos "task" field.  If this is
                ;     null when the node is accesses, a task
                ;     will be started up
    BPTR	dn_Lock		; not used for devices -- leave null
    BSTR	dn_Handler	; filename to loadseg (if seglist is null)
    ULONG	dn_StackSize	; stacksize to use when starting task
    LONG	dn_Priority	; task priority when starting task
    BPTR	dn_Startup	; startup msg: FileSysStartupMsg for disks
    BPTR	dn_SegList	; code to run to start new task (if necessary).
                ;     if null then dn_Handler will be loaded.
    BPTR	dn_GlobalVec	; BCPL global vector to use when starting
                ;     a task.  -1 means that dn_SegList is not
                ;     for a bcpl program, so the dos won't
                ;     try and construct one.  0 tell the
                ;     dos that you obey BCPL linkage rules,
                ;     and that it should construct a global
                ;     vector for you.
    BSTR	dn_Name		; the node name, e.g. '\3','D','F','3'
    LABEL	DeviceNode_SIZEOF

    ENDC	; DOS_FILEHANDLER_I


Includes/dos/stdio.h

#ifndef DOS_STDIO_H
#define DOS_STDIO_H
/*
**
**	$Filename: dos/stdio.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.6 $
**	$Date: 91/11/01 $
**
**	ANSI-like stdio defines for dos buffered I/O
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**
*/

#define ReadChar()		FGetC(Input())
#define WriteChar(c)		FPutC(Output(),(c))
#define UnReadChar(c)		UnGetC(Input(),(c))
/* next one is inefficient */
#define ReadChars(buf,num)	FRead(Input(),(buf),1,(num))
#define ReadLn(buf,len)		FGets(Input(),(buf),(len))
#define WriteStr(s)		FPuts(Output(),(s))
#define VWritef(format,argv)	VFWritef(Output(),(format),(argv))

/* types for SetVBuf */
#define BUF_LINE	0	/* flush on \n, etc */
#define BUF_FULL	1	/* never flush except when needed */
#define BUF_NONE	2	/* no buffering */

/* EOF return value */
#define ENDSTREAMCH	-1

#endif	/* DOS_STDIO_H */


Includes/dos/dos.i

    IFND	DOS_DOS_I
DOS_DOS_I SET	1
**	$Filename: dos/dos.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.24 $
**	$Date: 91/05/16 $
**
**	Standard asm header for AmigaDOS
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND	EXEC_TYPES_I
    INCLUDE	"exec/types.i"
    ENDC

DOSNAME	    MACRO
      DC.B  'dos.library',0
      ENDM

* Predefined Amiga DOS global constants

DOSTRUE	      EQU     -1
DOSFALSE      EQU      0

* Mode parameter to Open()
MODE_OLDFILE	     EQU   1005	  * Open existing file read/write
*				  * positioned at beginning of file.
MODE_NEWFILE	     EQU   1006	  * Open freshly created file (delete
*				  * old file) read/write
MODE_READWRITE	     EQU   1004	  * Open old file w/shared lock,
*				  * creates file if doesn't exist.

* Relative position to Seek()
OFFSET_BEGINNING     EQU   -1	  * relative to Beginning Of File
OFFSET_CURRENT	     EQU    0	  * relative to Current file position
OFFSET_END	     EQU    1	  * relative to End Of File

OFFSET_BEGINING	    EQU	  OFFSET_BEGINNING     * Ancient compatibility

BITSPERBYTE	     EQU   8
BYTESPERLONG	     EQU   4
BITSPERLONG	     EQU   32
MAXINT		     EQU   $7FFFFFFF
MININT		     EQU   $80000000

* Passed as type to Lock()
SHARED_LOCK	     EQU   -2	; File is readable by others
ACCESS_READ	     EQU   -2	; Synonym
EXCLUSIVE_LOCK	     EQU   -1	; No other access allowed
ACCESS_WRITE	     EQU   -1	; Synonym

 STRUCTURE DateStamp,0
   LONG	 ds_Days		; Number of days since Jan. 1, 1978
   LONG	 ds_Minute		; Number of minutes past midnight
   LONG	 ds_Tick		; Number of ticks past minute
   LABEL ds_SIZEOF		; DateStamp

TICKS_PER_SECOND EQU 50		; Number of ticks in one second

* Returned by Examine() and ExInfo()
 STRUCTURE FileInfoBlock,0
   LONG	  fib_DiskKey
   LONG	  fib_DirEntryType	; Type of Directory. If < 0, then a plain file.
                ; If > 0 a directory
   STRUCT fib_FileName,108	; Null terminated. Max 30 chars used for now
   LONG	  fib_Protection	; bit mask of protection, rwxd are 3-0.
   LONG	  fib_EntryType
   LONG	  fib_Size		; Number of bytes in file
   LONG	  fib_NumBlocks		; Number of blocks in file
   STRUCT fib_DateStamp,ds_SIZEOF ; Date file last changed.
   STRUCT fib_Comment,80	; Null terminated. Comment associated with file
   STRUCT fib_Reserved,36
   LABEL  fib_SIZEOF		; FileInfoBlock

* FIB stands for FileInfoBlock
* FIBB are bit definitions, FIBF are field definitions
   BITDEF   FIB,SCRIPT,6	; program is an execute script
   BITDEF   FIB,PURE,5		; program is reentrant and reexecutable
   BITDEF   FIB,ARCHIVE,4	; cleared whenever file is changed
   BITDEF   FIB,READ,3		; ignored by the system
   BITDEF   FIB,WRITE,2		; ignored by the system
   BITDEF   FIB,EXECUTE,1	; ignored by the system
   BITDEF   FIB,DELETE,0	; prevent file from being deleted

* Standard maximum length for an error string from fault.  However, most
* error strings should be kept under 60 characters if possible.  Don't
* forget space for the header you pass in.
FAULT_MAX	EQU	82

* All BCPL data must be long word aligned.  BCPL pointers are the long word
* address (i.e byte address divided by 4 (>>2))

* Macro to indicate BCPL pointers
BPTR	 MACRO			    * Long word pointer
     LONG	  \1
     ENDM
BSTR	 MACRO			    * Long word pointer to BCPL string.
     LONG	  \1
     ENDM

* #define BADDR( bptr ) (bptr << 2) * Convert BPTR to byte addressed pointer

* BCPL strings have a length in the first byte and then the characters.
* For example:	s[0]=3 s[1]=S s[2]=Y s[3]=S

* returned by Info()
 STRUCTURE InfoData,0
   LONG id_NumSoftErrors	* number of soft errors on disk
   LONG id_UnitNumber		* Which unit disk is (was) mounted on
   LONG id_DiskState		* See defines below
   LONG id_NumBlocks		* Number of blocks on disk
   LONG id_NumBlocksUsed	* Number of block in use
   LONG id_BytesPerBlock
   LONG id_DiskType		* Disk Type code
   BPTR id_VolumeNode		* BCPL pointer to volume node
   LONG id_InUse		* Flag, zero if not in use
   LABEL id_SIZEOF		* InfoData

* ID stands for InfoData
*	     Disk states
ID_WRITE_PROTECTED	EQU	80	* Disk is write protected
ID_VALIDATING		EQU	81	* Disk is currently being validated
ID_VALIDATED		EQU	82	* Disk is consistent and writeable

*	   Disk types
* ID_INTER_* use international case comparison routines for hashing
ID_NO_DISK_PRESENT	EQU -1
ID_UNREADABLE_DISK	EQU  ('B'<<24)!('A'<<16)!('D'<<8)
ID_NOT_REALLY_DOS	EQU  ('N'<<24)!('D'<<16)!('O'<<8)!('S')
ID_DOS_DISK		EQU  ('D'<<24)!('O'<<16)!('S'<<8)
ID_FFS_DISK		EQU  ('D'<<24)!('O'<<16)!('S'<<8)!(1)
ID_INTER_DOS_DISK	EQU  ('D'<<24)!('O'<<16)!('S'<<8)!(2)
ID_INTER_FFS_DISK	EQU  ('D'<<24)!('O'<<16)!('S'<<8)!(3)
ID_KICKSTART_DISK	EQU  ('K'<<24)!('I'<<16)!('C'<<8)!('K')
ID_MSDOS_DISK		EQU  ('M'<<24)!('S'<<16)!('D'<<8)

* Errors from IoErr(), etc.
ERROR_NO_FREE_STORE		  EQU  103
ERROR_TASK_TABLE_FULL		  EQU  105
ERROR_BAD_TEMPLATE		  EQU  114
ERROR_BAD_NUMBER		  EQU  115
ERROR_REQUIRED_ARG_MISSING	  EQU  116
ERROR_KEY_NEEDS_ARG		  EQU  117
ERROR_TOO_MANY_ARGS		  EQU  118
ERROR_UNMATCHED_QUOTES		  EQU  119
ERROR_LINE_TOO_LONG		  EQU  120
ERROR_FILE_NOT_OBJECT		  EQU  121
ERROR_INVALID_RESIDENT_LIBRARY	  EQU  122
ERROR_NO_DEFAULT_DIR		  EQU  201
ERROR_OBJECT_IN_USE		  EQU  202
ERROR_OBJECT_EXISTS		  EQU  203
ERROR_DIR_NOT_FOUND		  EQU  204
ERROR_OBJECT_NOT_FOUND		  EQU  205
ERROR_BAD_STREAM_NAME		  EQU  206
ERROR_OBJECT_TOO_LARGE		  EQU  207
ERROR_ACTION_NOT_KNOWN		  EQU  209
ERROR_INVALID_COMPONENT_NAME	  EQU  210
ERROR_INVALID_LOCK		  EQU  211
ERROR_OBJECT_WRONG_TYPE		  EQU  212
ERROR_DISK_NOT_VALIDATED	  EQU  213
ERROR_DISK_WRITE_PROTECTED	  EQU  214
ERROR_RENAME_ACROSS_DEVICES	  EQU  215
ERROR_DIRECTORY_NOT_EMPTY	  EQU  216
ERROR_TOO_MANY_LEVELS		  EQU  217
ERROR_DEVICE_NOT_MOUNTED	  EQU  218
ERROR_SEEK_ERROR		  EQU  219
ERROR_COMMENT_TOO_BIG		  EQU  220
ERROR_DISK_FULL			  EQU  221
ERROR_DELETE_PROTECTED		  EQU  222
ERROR_WRITE_PROTECTED		  EQU  223
ERROR_READ_PROTECTED		  EQU  224
ERROR_NOT_A_DOS_DISK		  EQU  225
ERROR_NO_DISK			  EQU  226
ERROR_NO_MORE_ENTRIES		  EQU  232
* added for 1.4
ERROR_IS_SOFT_LINK		  EQU  233
ERROR_OBJECT_LINKED		  EQU  234
ERROR_BAD_HUNK			  EQU  235
ERROR_NOT_IMPLEMENTED		  EQU  236
ERROR_RECORD_NOT_LOCKED		  EQU  240
ERROR_LOCK_COLLISION		  EQU  241
ERROR_LOCK_TIMEOUT		  EQU  242
ERROR_UNLOCK_ERROR		  EQU  243

* error codes 303-305 are defined in dosasl.i

* These are the return codes used by convention by AmigaDOS commands
* See FAILAT and IF for relvance to EXECUTE files
RETURN_OK			  EQU	 0  * No problems, success
RETURN_WARN			  EQU	 5  * A warning only
RETURN_ERROR			  EQU	10  * Something wrong
RETURN_FAIL			  EQU	20  * Complete or severe failure

* Bit numbers that signal you that a user has issued a break
* for example: if (SetSignal(0,0) & SIGBREAKF_CTRL_C) cleanup_and_exit();
    BITDEF	SIGBREAK,CTRL_C,12
    BITDEF	SIGBREAK,CTRL_D,13
    BITDEF	SIGBREAK,CTRL_E,14
    BITDEF	SIGBREAK,CTRL_F,15

* Values returned by SameLock()
LOCK_DIFFERENT		EQU	-1
LOCK_SAME		EQU	0
LOCK_SAME_VOLUME	EQU	1	; locks are on same volume
LOCK_SAME_HANDLER	EQU	LOCK_SAME_VOLUME
* LOCK_SAME_HANDLER was a misleading name, def kept for src compatibility

* types for ChangeMode()
CHANGE_LOCK	EQU	0
CHANGE_FH	EQU	1

* Values for MakeLink()
LINK_HARD	EQU	0
LINK_SOFT	EQU	1		; softlinks are not fully supported yet

* values returned by ReadItem
ITEM_EQUAL	EQU	-2		; "=" Symbol
ITEM_ERROR	EQU	-1		; error
ITEM_NOTHING	EQU	0		; *N, ;, endstreamch
ITEM_UNQUOTED	EQU	1		; unquoted item
ITEM_QUOTED	EQU	2		; quoted item

* types for AllocDosObject/FreeDosObject
DOS_FILEHANDLE		EQU	0	; few people should use this
DOS_EXALLCONTROL	EQU	1	; Must be used to allocate this!
DOS_FIB			EQU	2	; useful
DOS_STDPKT		EQU	3	; for doing packet-level I/O
DOS_CLI			EQU	4	; for shell-writers, etc
DOS_RDARGS		EQU	5	; for ReadArgs if you pass it in

    ENDC	; DOS_DOS_I


Includes/dos/dostags.h

#ifndef DOS_DOSTAGS_H
#define DOS_DOSTAGS_H
/*
**
**	$Filename: dos/dostags.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.11 $
**	$Date: 91/04/29 $
**
**	Tag definitions for all Dos routines using tags
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**
*/

#ifndef UTILITY_TAGITEM_H
#include "utility/tagitem.h"
#endif

/*****************************************************************************/
/* definitions for the System() call */

#define SYS_Dummy	(TAG_USER + 32)
#define	SYS_Input	(SYS_Dummy + 1)
                /* specifies the input filehandle  */
#define	SYS_Output	(SYS_Dummy + 2)
                /* specifies the output filehandle */
#define	SYS_Asynch	(SYS_Dummy + 3)
                /* run asynch, close input/output on exit(!) */
#define	SYS_UserShell	(SYS_Dummy + 4)
                /* send to user shell instead of boot shell */
#define	SYS_CustomShell	(SYS_Dummy + 5)
                /* send to a specific shell (data is name) */
/*	SYS_Error, */

/*****************************************************************************/
/* definitions for the CreateNewProc() call */
/* you MUST specify one of NP_Seglist or NP_Entry.  All else is optional. */

#define	NP_Dummy (TAG_USER + 1000)
#define	NP_Seglist	(NP_Dummy + 1)
                /* seglist of code to run for the process  */
#define	NP_FreeSeglist	(NP_Dummy + 2)
                /* free seglist on exit - only valid for   */
                /* for NP_Seglist.  Default is TRUE.	   */
#define	NP_Entry	(NP_Dummy + 3)
                /* entry point to run - mutually exclusive */
                /* with NP_Seglist! */
#define	NP_Input	(NP_Dummy + 4)
                /* filehandle - default is Open("NIL:"...) */
#define	NP_Output	(NP_Dummy + 5)
                /* filehandle - default is Open("NIL:"...) */
#define	NP_CloseInput	(NP_Dummy + 6)
                /* close input filehandle on exit	   */
                /* default TRUE				   */
#define	NP_CloseOutput	(NP_Dummy + 7)
                /* close output filehandle on exit	   */
                /* default TRUE				   */
#define	NP_Error	(NP_Dummy + 8)
                /* filehandle - default is Open("NIL:"...) */
#define	NP_CloseError	(NP_Dummy + 9)
                /* close error filehandle on exit	   */
                /* default TRUE				   */
#define	NP_CurrentDir	(NP_Dummy + 10)
                /* lock - default is parent's current dir  */
#define	NP_StackSize	(NP_Dummy + 11)
                /* stacksize for process - default 4000    */
#define	NP_Name		(NP_Dummy + 12)
                /* name for process - default "New Process"*/
#define	NP_Priority	(NP_Dummy + 13)
                /* priority - default same as parent	   */
#define	NP_ConsoleTask	(NP_Dummy + 14)
                /* consoletask - default same as parent    */
#define	NP_WindowPtr	(NP_Dummy + 15)
                /* window ptr - default is same as parent  */
#define	NP_HomeDir	(NP_Dummy + 16)
                /* home directory - default curr home dir  */
#define	NP_CopyVars	(NP_Dummy + 17)
                /* boolean to copy local vars-default TRUE */
#define	NP_Cli		(NP_Dummy + 18)
                /* create cli structure - default FALSE    */
#define	NP_Path		(NP_Dummy + 19)
                /* path - default is copy of parents path  */
                /* only valid if a cli process!	   */
#define	NP_CommandName	(NP_Dummy + 20)
                /* commandname - valid only for CLI	   */
#define	NP_Arguments	(NP_Dummy + 21)
/* cstring of arguments - passed with str in a0, length in d0.	*/
/* (copied and freed on exit.)	Default is 0-length NULL ptr.	*/
/* NOTE: not operational until V37 - see BIX/TechNotes for	*/
/* more info/workaround.  In V36, the registers were random.	*/
/* You must NEVER use NP_Arguments with a NP_Input of NULL.	*/

/* FIX! should this be only for cli's? */
#define	NP_NotifyOnDeath (NP_Dummy + 22)
                /* notify parent on death - default FALSE  */
                /* Not functional yet. */
#define	NP_Synchronous	(NP_Dummy + 23)
                /* don't return until process finishes -   */
                /* default FALSE.			   */
                /* Not functional yet. */
#define	NP_ExitCode	(NP_Dummy + 24)
                /* code to be called on process exit	   */
#define	NP_ExitData	(NP_Dummy + 25)
                /* optional argument for NP_EndCode rtn -  */
                /* default NULL				   */

/*****************************************************************************/
/* tags for AllocDosObject */

#define ADO_Dummy	(TAG_USER + 2000)
#define	ADO_FH_Mode	(ADO_Dummy + 1)
                /* for type DOS_FILEHANDLE only		   */
                /* sets up FH for mode specified.
                   This can make a big difference for buffered
                   files.				   */
    /* The following are for DOS_CLI */
    /* If you do not specify these, dos will use it's preferred values */
    /* which may change from release to release.  The BPTRs to these   */
    /* will be set up correctly for you.  Everything will be zero,	   */
    /* except cli_FailLevel (10) and cli_Background (DOSTRUE).	   */
    /* NOTE: you may also use these 4 tags with CreateNewProc.	   */

#define	ADO_DirLen	(ADO_Dummy + 2)
                /* size in bytes for current dir buffer    */
#define	ADO_CommNameLen	(ADO_Dummy + 3)
                /* size in bytes for command name buffer   */
#define	ADO_CommFileLen	(ADO_Dummy + 4)
                /* size in bytes for command file buffer   */
#define	ADO_PromptLen	(ADO_Dummy + 5)
                /* size in bytes for the prompt buffer	   */

/*****************************************************************************/
/* tags for NewLoadSeg */
/* no tags are defined yet for NewLoadSeg */

#endif /* DOS_DOSTAGS_H */


Includes/dos/notify.h

#ifndef DOS_NOTIFY_H
#define DOS_NOTIFY_H
/*
**
**	$Filename: dos/notify.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.8 $
**	$Date: 90/08/29 $
**
**	dos notification definitions
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**
*/

#ifndef EXEC_TYPES_H
#include "exec/types.h"
#endif

#ifndef EXEC_PORTS_H
#include "exec/ports.h"
#endif

#ifndef EXEC_TASKS_H
#include "exec/tasks.h"
#endif

/* use of Class and code is discouraged for the time being - we might want to
   change things */
/* --- NotifyMessage Class ------------------------------------------------ */
#define NOTIFY_CLASS	0x40000000

/* --- NotifyMessage Codes ------------------------------------------------ */
#define NOTIFY_CODE	0x1234

/* Sent to the application if SEND_MESSAGE is specified.		    */

struct NotifyMessage {
    struct Message nm_ExecMessage;
    ULONG  nm_Class;
    UWORD  nm_Code;
    struct NotifyRequest *nm_NReq;	/* don't modify the request! */
    ULONG  nm_DoNotTouch;		/* like it says!  For use by handlers */
    ULONG  nm_DoNotTouch2;		/* ditto */
};

/* Do not modify or reuse the notifyrequest while active.		    */
/* note: the first LONG of nr_Data has the length transfered		    */

struct NotifyRequest {
    UBYTE *nr_Name;
    UBYTE *nr_FullName;		/* set by dos - don't touch */
    ULONG nr_UserData;		/* for applications use */
    ULONG nr_Flags;

    union {

        struct {
        struct MsgPort *nr_Port;	/* for SEND_MESSAGE */
        } nr_Msg;

        struct {
        struct Task *nr_Task;		/* for SEND_SIGNAL */
        UBYTE nr_SignalNum;		/* for SEND_SIGNAL */
        UBYTE nr_pad[3];
        } nr_Signal;
    } nr_stuff;

    ULONG nr_Reserved[4];		/* leave 0 for now */

    /* internal use by handlers */
    ULONG nr_MsgCount;		/* # of outstanding msgs */
    struct MsgPort *nr_Handler;	/* handler sent to (for EndNotify) */
};

/* --- NotifyRequest Flags ------------------------------------------------ */
#define NRF_SEND_MESSAGE	1
#define NRF_SEND_SIGNAL		2
#define NRF_WAIT_REPLY		8
#define NRF_NOTIFY_INITIAL	16

/* do NOT set or remove NRF_MAGIC!  Only for use by handlers! */
#define NRF_MAGIC	0x80000000

/* bit numbers */
#define NRB_SEND_MESSAGE	0
#define NRB_SEND_SIGNAL		1
#define NRB_WAIT_REPLY		3
#define NRB_NOTIFY_INITIAL	4

#define NRB_MAGIC		31

/* Flags reserved for private use by the handler: */
#define NR_HANDLER_FLAGS	0xffff0000

#endif /* DOS_NOTIFY_H */


Includes/dos/stdio.i

    IFND DOS_STDIO_I
DOS_STDIO_I	EQU	1
**
**	$Filename: dos/stdio.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.2 $
**	$Date: 91/11/01 $
**
**	ANSI-like stdio defines for dos buffered I/O
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**

* types for SetVBuf()
BUF_LINE	EQU	0	; flush on \n, etc
BUF_FULL	EQU	1	; never flush except when needed
BUF_NONE	EQU	2	; no buffering

* EOF return value
ENDSTREAMCH	EQU	-1

    ENDC	; DOS_STDIO_I


Includes/dos/dosasl.h

#ifndef DOS_DOSASL_H
#define DOS_DOSASL_H
/*
**
**	$Filename: dos/dosasl.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.16 $
**	$Date: 91/05/02 $
**
**	Pattern-matching structure definitions
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**
*/

#ifndef EXEC_LIBRARIES_H
#include <exec/libraries.h>
#endif

#ifndef EXEC_LISTS_H
#include <exec/lists.h>
#endif

#ifndef DOS_DOS_H
#include <dos/dos.h>
#endif

/***********************************************************************
************************ PATTERN MATCHING ******************************
************************************************************************

* structure expected by MatchFirst, MatchNext.
* Allocate this structure and initialize it as follows:
*
* Set ap_BreakBits to the signal bits (CDEF) that you want to take a
* break on, or NULL, if you don't want to convenience the user.
*
* If you want to have the FULL PATH NAME of the files you found,
* allocate a buffer at the END of this structure, and put the size of
* it into ap_Strlen.  If you don't want the full path name, make sure
* you set ap_Strlen to zero.  In this case, the name of the file, and stats
* are available in the ap_Info, as per usual.
*
* Then call MatchFirst() and then afterwards, MatchNext() with this structure.
* You should check the return value each time (see below) and take the
* appropriate action, ultimately calling MatchEnd() when there are
* no more files and you are done.  You can tell when you are done by
* checking for the normal AmigaDOS return code ERROR_NO_MORE_ENTRIES.
*
*/

struct AnchorPath {
    struct AChain	*ap_Base;	/* pointer to first anchor */
#define	ap_First ap_Base
    struct AChain	*ap_Last;	/* pointer to last anchor */
#define ap_Current ap_Last
    LONG	ap_BreakBits;	/* Bits we want to break on */
    LONG	ap_FoundBreak;	/* Bits we broke on. Also returns ERROR_BREAK */
    BYTE	ap_Flags;	/* New use for extra word. */
    BYTE	ap_Reserved;
    WORD	ap_Strlen;	/* This is what ap_Length used to be */
#define	ap_Length ap_Flags	/* Old compatability for LONGWORD ap_Length */
    struct	FileInfoBlock ap_Info;
    UBYTE	ap_Buf[1];	/* Buffer for path name, allocated by user */
    /* FIX! */
};

#define	APB_DOWILD	0	/* User option ALL */
#define APF_DOWILD	1

#define	APB_ITSWILD	1	/* Set by MatchFirst, used by MatchNext	 */
#define APF_ITSWILD	2	/* Application can test APB_ITSWILD, too */
                /* (means that there's a wildcard	 */
                /* in the pattern after calling		 */
                /* MatchFirst).				 */

#define	APB_DODIR	2	/* Bit is SET if a DIR node should be */
#define APF_DODIR	4	/* entered. Application can RESET this */
                /* bit after MatchFirst/MatchNext to AVOID */
                /* entering a dir. */

#define	APB_DIDDIR	3	/* Bit is SET for an "expired" dir node. */
#define APF_DIDDIR	8

#define	APB_NOMEMERR	4	/* Set on memory error */
#define APF_NOMEMERR	16

#define	APB_DODOT	5	/* If set, allow conversion of '.' to */
#define APF_DODOT	32	/* CurrentDir */

#define APB_DirChanged	6	/* ap_Current->an_Lock changed */
#define APF_DirChanged	64	/* since last MatchNext call */

#define APB_FollowHLinks 7	/* follow hardlinks on DODIR - defaults   */
#define APF_FollowHLinks 128	/* to not following hardlinks on a DODIR. */

struct AChain {
    struct AChain *an_Child;
    struct AChain *an_Parent;
    BPTR	an_Lock;
    struct FileInfoBlock an_Info;
    BYTE	an_Flags;
    UBYTE	an_String[1];	/* FIX!! */
};

#define	DDB_PatternBit	0
#define	DDF_PatternBit	1
#define	DDB_ExaminedBit	1
#define	DDF_ExaminedBit	2
#define	DDB_Completed	2
#define	DDF_Completed	4
#define	DDB_AllBit	3
#define	DDF_AllBit	8
#define	DDB_Single	4
#define	DDF_Single	16

/*
 * Constants used by wildcard routines, these are the pre-parsed tokens
 * referred to by pattern match.  It is not necessary for you to do
 * anything about these, MatchFirst() MatchNext() handle all these for you.
 */

#define P_ANY		0x80	/* Token for '*' or '#?  */
#define P_SINGLE	0x81	/* Token for '?' */
#define P_ORSTART	0x82	/* Token for '(' */
#define P_ORNEXT	0x83	/* Token for '|' */
#define P_OREND	0x84	/* Token for ')' */
#define P_NOT		0x85	/* Token for '~' */
#define P_NOTEND	0x86	/* Token for */
#define P_NOTCLASS	0x87	/* Token for '^' */
#define P_CLASS	0x88	/* Token for '[]' */
#define P_REPBEG	0x89	/* Token for '[' */
#define P_REPEND	0x8A	/* Token for ']' */
#define P_STOP		0x8B	/* token to force end of evaluation */

/* Values for an_Status, NOTE: These are the actual bit numbers */

#define COMPLEX_BIT	1	/* Parsing complex pattern */
#define EXAMINE_BIT	2	/* Searching directory */

/*
 * Returns from MatchFirst(), MatchNext()
 * You can also get dos error returns, such as ERROR_NO_MORE_ENTRIES,
 * these are in the dos.h file.
 */

#define ERROR_BUFFER_OVERFLOW	303	/* User or internal buffer overflow */
#define ERROR_BREAK		304	/* A break character was received */
#define ERROR_NOT_EXECUTABLE	305	/* A file has E bit cleared */

#endif /* DOS_DOSASL_H */


Includes/dos/dostags.i

    IFND	DOS_DOSTAGS_I
DOS_DOSTAGS_I SET	1
**
**	$Filename: dos/dostags.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.13 $
**	$Date: 91/04/29 $
**
**	Tag definitions for all Dos routines using tags
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**

     IFND  UTILITY_TAGITEM_I
     INCLUDE "utility/tagitem.i"
     ENDC

*****************************************************************************
* definitions for the System() call

SYS_Dummy	EQU	TAG_USER+32
SYS_Input	EQU	SYS_Dummy+1	; specifies the input filehandle
SYS_Output	EQU	SYS_Dummy+2	; specifies the output filehandle
SYS_Asynch	EQU	SYS_Dummy+3	; run asynch, close input/output(!)
SYS_UserShell	EQU	SYS_Dummy+4   ; send to user shell instead of boot shell
SYS_CustomShell	EQU	SYS_Dummy+5   ; send to a specific shell (data is name)
*SYS_Error	EQU	SYS_Dummy+?

*****************************************************************************
* definitions for the CreateNewProc() call
* you MUST specify one of NP_Seglist or NP_Entry.  All else is optional.

NP_Dummy	EQU TAG_USER+1000
NP_Seglist	EQU NP_Dummy+1	 ; seglist of code to run for the process
NP_FreeSeglist	EQU NP_Dummy+2	 ; free seglist on exit - only valid for
                 ; for NP_Seglist.  Default is TRUE.
NP_Entry	EQU NP_Dummy+3	 ; entry point to run - mutually exclusive
                 ; with NP_Seglist.
NP_Input	EQU NP_Dummy+4	 ; filehandle - default is Open("NIL:"...)
NP_Output	EQU NP_Dummy+5	 ; filehandle - default is Open("NIL:"...)
NP_CloseInput	EQU NP_Dummy+6	 ; close input filehandle on exit
                 ; default TRUE
NP_CloseOutput	EQU NP_Dummy+7	 ; close output filehandle on exit
                 ; default TRUE
NP_Error	EQU NP_Dummy+8	 ; filehandle - default is Open("NIL:"...)
NP_CloseError	EQU NP_Dummy+9	 ; close error filehandle on exit
                 ; default TRUE
NP_CurrentDir	EQU NP_Dummy+10	 ; lock - default is parent's current dir
NP_StackSize	EQU NP_Dummy+11	 ; stacksize for process - default 4000
NP_Name		EQU NP_Dummy+12	 ; name for process - default "New Process"
NP_Priority	EQU NP_Dummy+13	 ; priority - default same as parent
NP_ConsoleTask	EQU NP_Dummy+14	 ; consoletask - default same as parent
NP_WindowPtr	EQU NP_Dummy+15	 ; window ptr - default is same as parent
NP_HomeDir	EQU NP_Dummy+16	 ; home directory - default current home dir
NP_CopyVars	EQU NP_Dummy+17	 ; boolean to copy local vars-default TRUE
NP_Cli		EQU NP_Dummy+18	 ; create cli structure - default FALSE
NP_Path		EQU NP_Dummy+19	 ; path - default is copy of parents path
                 ; only valid if a cli process!
NP_CommandName	EQU NP_Dummy+20  ; commandname - valid only for CLI
NP_Arguments	EQU NP_Dummy+21
; cstring of arguments - passed with str in a0, length in d0.
; (copied and freed on exit.)  Default is 0-length NULL ptr.
; NOTE: not operational until V37 - see BIX/TechNotes for
; more info/workaround.  In V36, the registers were random.
; You must NEVER use NP_Arguments with a NP_Input of NULL.

NP_NotifyOnDeath EQU NP_Dummy+22 ; notify parent on death - default FALSE
                 ; Not functional yet.
NP_Synchronous	EQU NP_Dummy+23	 ; don't return until process finishes -
                 ; default FALSE.
                 ; Not functional yet.
NP_ExitCode	EQU NP_Dummy+24	 ; code to be called on process exit
NP_ExitData	EQU NP_Dummy+25	 ; optional argument for NP_EndCode rtn -
                 ; default NULL

*****************************************************************************
* tags for AllocDosObject
ADO_Dummy	EQU	TAG_USER+2000
ADO_FH_Mode	EQU	ADO_Dummy+1	; for type DOS_FILEHANDLE only
                ; sets up FH for the type of open being done
                ; This can make a big difference for buffered
                ; files.

    ; The following are for DOS_CLI
    ; If you do not specify these, dos will use it's preferred values
    ; which may change from release to release.  The BPTRs to these
    ; will be set up correctly for you.  Everything will be zero,
    ; except cli_FailLevel (10) and cli_Background (DOSTRUE).
    ; NOTE: you may also use these 4 tags with CreateNewProc.

ADO_DirLen	EQU	ADO_Dummy+2	; size in bytes for current dir buffer
ADO_CommNameLen	EQU	ADO_Dummy+3	; size in bytes for command name buffer
ADO_CommFileLen	EQU	ADO_Dummy+4	; size in bytes for command file buffer
ADO_PromptLen	EQU	ADO_Dummy+5	; size in bytes for the prompt buffer

* tags for NewLoadSeg
* no tags are defined yet for NewLoadSeg

    ENDC	; DOS_DOSTAGS_I


Includes/dos/notify.i

    IFND	DOS_NOTIFY_I
DOS_NOTIFY_I	SET	1
**
**	$Filename: dos/notify.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.5 $
**	$Date: 90/08/29 $
**
**	dos notification definitions
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND	EXEC_PORTS_I
    INCLUDE	"exec/ports.i"
    ENDC
    IFND	EXEC_TASKS_I
    INCLUDE	"exec/tasks.i"
    ENDC

* use of Class and code is discouraged for the time being - we might want to
* change things
*------ NotifyMessage Class ------------------------------------------
NOTIFY_CLASS	EQU	$40000000

*------ NotifyMessage Code --------------------------------------------
NOTIFY_CODE	EQU	$1234

* Sent to the application if SEND_MESSAGE is specified.

 STRUCTURE NotifyMessage,0
    STRUCT nm_ExecMessage,MN_SIZE
    ULONG  nm_Class
    UWORD  nm_Code
    APTR   nm_NReq			; don't modify the request!
    ULONG  nm_DoNotTouch		; like it says!  For use by handlers
    ULONG  nm_DoNotTouch2		; ditto
    LABEL  NotifyMessage_SIZEOF

* Do not modify or reuse the notifyrequest while it is active.

 STRUCTURE NotifyRequest,0
    CPTR   nr_Name			; Application sets this
    CPTR   nr_FullName			; fully expanded name created by Dos
                    ; (handlers need nr_FullName)
    ULONG  nr_UserData			; for the application's use
    ULONG  nr_Flags

    ;-- nr_Msg:
    APTR   nr_Port			; struct MsgPort * for SEND_MESSAGE

    ;-- nr_Signal:
nr_Task	EQU nr_Port			; struct Task * for SEND_SIGNAL
    UBYTE  nr_SignalNum			; for SEND_SIGNAL
    STRUCT nr_pad,3

    ;-- Reserved fields:
    STRUCT nr_Reserved,4*4

    ;-- internal for use by handlers/dos:
    ULONG  nr_MsgCount			; # of outstanding msgs
    APTR   nr_Handler			; handler sent to (for EndNotify)
    LABEL  NotifyRequest_SIZEOF

;------ NotifyRequest Flags ------------------------------------------
    BITDEF	NR,SEND_MESSAGE,0
    BITDEF	NR,SEND_SIGNAL,1
    BITDEF	NR,WAIT_REPLY,3
    BITDEF	NR,NOTIFY_INITIAL,4

* do NOT set or remove NRF_MAGIC!  Only for use by handlers!
    BITDEF	NR,MAGIC,31

* Flags reserved for private use by the handler:
NR_HANDLER_FLAGS	EQU	$ffff0000

    ENDC	; DOS_NOTIFY_I


Includes/dos/var.h

#ifndef DOS_VAR_H
#define DOS_VAR_H
/*
**
**	$Filename: dos/var.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.10 $
**	$Date: 91/03/14 $
**
**	include file for dos local and environment variables
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**
*/

#ifndef EXEC_NODES_H
#include "exec/nodes.h"
#endif

/* the structure in the pr_LocalVars list */
/* Do NOT allocate yourself, use SetVar()!!! This structure may grow in */
/* future releases!  The list should be left in alphabetical order, and */
/* may have multiple entries with the same name but different types.	*/

struct LocalVar {
    struct Node lv_Node;
    UWORD	lv_Flags;
    UBYTE	*lv_Value;
    ULONG	lv_Len;
};

/*
 * The lv_Flags bits are available to the application.	The unused
 * lv_Node.ln_Pri bits are reserved for system use.
 */

/* bit definitions for lv_Node.ln_Type: */
#define LV_VAR			0	/* an variable */
#define LV_ALIAS		1	/* an alias */
/* to be or'ed into type: */
#define LVB_IGNORE		7	/* ignore this entry on GetVar, etc */
#define LVF_IGNORE		0x80

/* definitions of flags passed to GetVar()/SetVar()/DeleteVar() */
/* bit defs to be OR'ed with the type: */
/* item will be treated as a single line of text unless BINARY_VAR is used */
#define GVB_GLOBAL_ONLY		8
#define GVF_GLOBAL_ONLY		0x100
#define GVB_LOCAL_ONLY		9
#define GVF_LOCAL_ONLY		0x200
#define GVB_BINARY_VAR		10		/* treat variable as binary */
#define GVF_BINARY_VAR		0x400
#define GVB_DONT_NULL_TERM	11	/* only with GVF_BINARY_VAR */
#define GVF_DONT_NULL_TERM	0x800

#endif /* DOS_VAR_H */


Includes/dos/dosasl.i

    IFND DOS_DOSASL_I
DOS_DOSASL_I	SET	1
**
**	$Filename: dos/dosasl.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.19 $
**	$Date: 91/05/02 $
**
**	pattern-matching structure definitions
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND EXEC_LIBRARIES_I
    INCLUDE "exec/libraries.i"
    ENDC

    IFND EXEC_LISTS_I
    INCLUDE "exec/lists.i"
    ENDC

    IFND DOS_DOS_I
    INCLUDE "dos/dos.i"
    ENDC

************************************************************************
************************ PATTERN MATCHING ******************************
************************************************************************

* structure expected by MatchFirst, MatchNext.
* Allocate this structure and initialize it as follows:
*
* Set ap_BreakBits to the signal bits (CDEF) that you want to take a
* break on, or NULL, if you don't want to convenience the user.
*
* If you want to have the FULL PATH NAME of the files you found,
* allocate a buffer at the END of this structure, and put the size of
* it into ap_Strlen.  If you don't want the full path name, make sure
* you set ap_Strlen to zero.  In this case, the name of the file, and stats
* are available in the ap_Info, as per usual.
*
* Then call MatchFirst() and then afterwards, MatchNext() with this structure.
* You should check the return value each time (see below) and take the
* appropriate action, ultimately calling MatchEnd() when there are
* no more files and you are done.  You can tell when you are done by
* checking for the normal AmigaDOS return code ERROR_NO_MORE_ENTRIES.
*

    STRUCTURE AnchorPath,0
        LABEL	ap_First
        CPTR	ap_Base	; pointer to first anchor
        LABEL	ap_Current
        CPTR	ap_Last	; pointer to last anchor
        LONG	ap_BreakBits	; Bits we want to break on
        LONG	ap_FoundBreak	; Bits we broke on. Also returns ERROR_BREAK
        LABEL	ap_Length	; Old compatability for LONGWORD ap_Length
        BYTE	ap_Flags	; New use for extra word.
        BYTE	ap_Reserved
        WORD	ap_Strlen	; This is what ap_Length used to be
        STRUCT	ap_Info,fib_SIZEOF	; FileInfoBlock
        LABEL	ap_Buf		; Buffer for path name, allocated by user
        LABEL	ap_SIZEOF

    BITDEF	AP,DOWILD,0		; User option ALL
    BITDEF	AP,ITSWILD,1		; Set by MatchFirst, used by MatchNext
                    ; Application can test APB_ITSWILD,
                    ; too (means that there's a wildcard
                    ; in the pattern after calling
                    ; MatchFirst).
    BITDEF	AP,DODIR,2		; Bit is SET if a DIR node should be
                    ; entered. Application can RESET this
                    ; bit after MatchFirst/MatchNext to
                    ; AVOID entering a dir.
    BITDEF	AP,DIDDIR,3		; Bit is SET for an "expired" dir node.
    BITDEF	AP,NOMEMERR,4		; Set on memory error
    BITDEF	AP,DODOT,5		; If set, allow conversion of '.' to
                    ; CurrentDir
    BITDEF	AP,DirChanged,6		; ap_Current->an_Lock changed
                    ; since last MatchNext call

    BITDEF	AP,FollowHLinks,7      ; follow hardlinks on DODIR - defaults
                       ; to not following hardlinks on a DODIR.

    STRUCTURE	AChain,0
        CPTR	an_Child
        CPTR	an_Parent
        LONG	an_Lock
        STRUCT	an_Info,fib_SIZEOF	; FileInfoBlock
        BYTE	an_Flags
        LABEL	an_String
        LABEL	an_SIZEOF

    BITDEF	DD,PatternBit,0
    BITDEF	DD,ExaminedBit,1
    BITDEF	DD,Completed,2
    BITDEF	DD,AllBit,3
    BITDEF	DD,SINGLE,4

* Constants used by wildcard routines, these are the pre-parsed tokens
* referred to by pattern match.  It is not necessary for you to do
* anything about these, MatchFirst() MatchNext() handle all these for you.

P_ANY		EQU	$80	; Token for '*' or '#?
P_SINGLE	EQU	$81	; Token for '?'
P_ORSTART	EQU	$82	; Token for '('
P_ORNEXT	EQU	$83	; Token for '|'
P_OREND	EQU	$84	; Token for ')'
P_NOT		EQU	$85	; Token for '~'
P_NOTEND	EQU	$86	; Token for
P_NOTCLASS	EQU	$87	; Token for '^'
P_CLASS	EQU	$88	; Token for '[]'
P_REPBEG	EQU	$89	; Token for '['
P_REPEND	EQU	$8A	; Token for ']'
P_STOP		EQU	$8B	; token to force end of evaluation

* Values for an_Status, NOTE: These are the actual bit numbers

COMPLEX_BIT	EQU	1	; Parsing complex pattern
EXAMINE_BIT	EQU	2	; Searching directory

* Returns from MatchFirst(), MatchNext()
* You can also get dos error returns, such as ERROR_NO_MORE_ENTRIES,
* these are in the dos.h file.
*
ERROR_BUFFER_OVERFLOW	EQU	303	; User or internal buffer overflow
ERROR_BREAK		EQU	304	; A break character was received
ERROR_NOT_EXECUTABLE	EQU	305	; A file has E bit cleared

    ENDC	; DOS_DOSASL_I


Includes/dos/dos_lib.i

    IFND	DOS_DOS_LIB_I
DOS_DOS_LIB_I	SET	1
**
**	$Filename: dos/dos_lib.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.1 $
**	$Date: 90/11/04 $
**
**	Library interface offsets for DOS library
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

reserve EQU	4
vsize	EQU	6
count	SET	-vsize*(reserve+1)
LIBENT	MACRO
_LVO\1	EQU	count
count	SET	count-vsize
    ENDM
*
*
*
   LIBENT   Open
   LIBENT   Close
   LIBENT   Read
   LIBENT   Write
   LIBENT   Input
   LIBENT   Output
   LIBENT   Seek
   LIBENT   DeleteFile
   LIBENT   Rename
   LIBENT   Lock
   LIBENT   UnLock
   LIBENT   DupLock
   LIBENT   Examine
   LIBENT   ExNext
   LIBENT   Info
   LIBENT   CreateDir
   LIBENT   CurrentDir
   LIBENT   IoErr
   LIBENT   CreateProc
   LIBENT   Exit
   LIBENT   LoadSeg
   LIBENT   UnLoadSeg
   LIBENT   GetPacket
   LIBENT   QueuePacket
   LIBENT   DeviceProc
   LIBENT   SetComment
   LIBENT   SetProtection
   LIBENT   DateStamp
   LIBENT   Delay
   LIBENT   WaitForChar
   LIBENT   ParentDir
   LIBENT   IsInteractive
   LIBENT   Execute

    ENDC	; DOS_DOS_LIB_I


Includes/dos/rdargs.h

#ifndef DOS_RDARGS_H
#define DOS_RDARGS_H
/*
**
**	$Filename: dos/rdargs.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.6 $
**	$Date: 90/07/12 $
**
**	ReadArgs() structure definitions
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**
*/

#ifndef EXEC_TYPES_H
#include "exec/types.h"
#endif

#ifndef EXEC_NODES_H
#include "exec/nodes.h"
#endif

/**********************************************************************
 *
 * The CSource data structure defines the input source for "ReadItem()"
 * as well as the ReadArgs call.  It is a publicly defined structure
 * which may be used by applications which use code that follows the
 * conventions defined for access.
 *
 * When passed to the dos.library functions, the value passed as
 * struct *CSource is defined as follows:
 *	if ( CSource == 0)	Use buffered IO "ReadChar()" as data source
 *	else			Use CSource for input character stream
 *
 * The following two pseudo-code routines define how the CSource structure
 * is used:
 *
 * long CS_ReadChar( struct CSource *CSource )
 * {
 *	if ( CSource == 0 )	return ReadChar();
 *	if ( CSource->CurChr >= CSource->Length )	return ENDSTREAMCHAR;
 *	return CSource->Buffer[ CSource->CurChr++ ];
 * }
 *
 * BOOL CS_UnReadChar( struct CSource *CSource )
 * {
 *	if ( CSource == 0 )	return UnReadChar();
 *	if ( CSource->CurChr <= 0 )	return FALSE;
 *	CSource->CurChr--;
 *	return TRUE;
 * }
 *
 * To initialize a struct CSource, you set CSource->CS_Buffer to
 * a string which is used as the data source, and set CS_Length to
 * the number of characters in the string.  Normally CS_CurChr should
 * be initialized to ZERO, or left as it was from prior use as
 * a CSource.
 *
 **********************************************************************/

struct CSource {
    UBYTE	*CS_Buffer;
    LONG	CS_Length;
    LONG	CS_CurChr;
};

/**********************************************************************
 *
 * The RDArgs data structure is the input parameter passed to the DOS
 * ReadArgs() function call.
 *
 * The RDA_Source structure is a CSource as defined above;
 * if RDA_Source.CS_Buffer is non-null, RDA_Source is used as the input
 * character stream to parse, else the input comes from the buffered STDIN
 * calls ReadChar/UnReadChar.
 *
 * RDA_DAList is a private address which is used internally to track
 * allocations which are freed by FreeArgs().  This MUST be initialized
 * to NULL prior to the first call to ReadArgs().
 *
 * The RDA_Buffer and RDA_BufSiz fields allow the application to supply
 * a fixed-size buffer in which to store the parsed data.  This allows
 * the application to pre-allocate a buffer rather than requiring buffer
 * space to be allocated.  If either RDA_Buffer or RDA_BufSiz is NULL,
 * the application has not supplied a buffer.
 *
 * RDA_ExtHelp is a text string which will be displayed instead of the
 * template string, if the user is prompted for input.
 *
 * RDA_Flags bits control how ReadArgs() works.  The flag bits are
 * defined below.  Defaults are initialized to ZERO.
 *
 **********************************************************************/

struct RDArgs {
    struct	CSource RDA_Source;	/* Select input source */
    LONG	RDA_DAList;		/* PRIVATE. */
    UBYTE	*RDA_Buffer;		/* Optional string parsing space. */
    LONG	RDA_BufSiz;		/* Size of RDA_Buffer (0..n) */
    UBYTE	*RDA_ExtHelp;		/* Optional extended help */
    LONG	RDA_Flags;		/* Flags for any required control */
};

#define RDAB_STDIN	0	/* Use "STDIN" rather than "COMMAND LINE" */
#define RDAF_STDIN	1
#define RDAB_NOALLOC	1	/* If set, do not allocate extra string space.*/
#define RDAF_NOALLOC	2
#define RDAB_NOPROMPT	2	/* Disable reprompting for string input. */
#define RDAF_NOPROMPT	4

/**********************************************************************
 * Maximum number of template keywords which can be in a template passed
 * to ReadArgs(). IMPLEMENTOR NOTE - must be a multiple of 4.
 **********************************************************************/
#define MAX_TEMPLATE_ITEMS	100

/**********************************************************************
 * Maximum number of MULTIARG items returned by ReadArgs(), before
 * an ERROR_LINE_TOO_LONG.  These two limitations are due to stack
 * usage.  Applications should allow "a lot" of stack to use ReadArgs().
 **********************************************************************/
#define MAX_MULTIARGS		128

#endif /* DOS_RDARGS_H */


Includes/dos/var.i

    IFND	DOS_VAR_I
DOS_VAR_I SET	1
**
**	$Filename: dos/var.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.12 $
**	$Date: 91/03/14 $
**
**	include file for dos local and environment variables
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**

     IFND  EXEC_NODES_I
     INCLUDE "exec/nodes.i"
     ENDC

* the structure in the pr_LocalVars list
* Do NOT allocate yourself, use SetVar()!!! This structure may grow in
* future releases!  The list should be left in alphabetical order, and
* may have multiple entries with the same name but different types.

 STRUCTURE LocalVar,0
    STRUCT	lv_Node,LN_SIZE
    UWORD	lv_Flags
    APTR	lv_Value
    ULONG	lv_Len
 LABEL LocalVar_SIZEOF

*
* The lv_Flags bits are available to the application.  The unused
* lv_Node.ln_Pri bits are reserved for system use.
*

* bit definitions for lv_Node.ln_Type:

LV_VAR		EQU	0		; a variable
LV_ALIAS	EQU	1		; an alias
* to be or'ed into type:
LVB_IGNORE	EQU	7		; ignore this entry on GetVar, etc
LVF_IGNORE	EQU	$80

* definitions of flags passed to GetVar()/SetVar()/DeleteVar()
* bit defs to be OR'ed with the type:
* item will be treated as a single line of text unless BINARY_VAR is used

    BITDEF	GV,GLOBAL_ONLY,8
    BITDEF	GV,LOCAL_ONLY,9
    BITDEF	GV,BINARY_VAR,10	; treat as binary variable
    BITDEF	GV,DONT_NULL_TERM,11	; only with GVF_BINARY_VAR

    ENDC	; DOS_VAR_I


Includes/dos/dosextens.h

#ifndef DOS_DOSEXTENS_H
#define DOS_DOSEXTENS_H
/*
**	$Filename: dos/dosextens.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.38 $
**	$Date: 91/11/08 $
**
**	DOS structures not needed for the casual AmigaDOS user
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TASKS_H
#include "exec/tasks.h"
#endif
#ifndef EXEC_PORTS_H
#include "exec/ports.h"
#endif
#ifndef EXEC_LIBRARIES_H
#include "exec/libraries.h"
#endif
#ifndef EXEC_SEMAPHORES_H
#include "exec/semaphores.h"
#endif
#ifndef DEVICES_TIMER_H
#include "devices/timer.h"
#endif

#ifndef DOS_DOS_H
#include "dos/dos.h"
#endif

/* All DOS processes have this structure */
/* Create and Device Proc returns pointer to the MsgPort in this structure */
/* dev_proc = (struct Process *) (DeviceProc(..) - sizeof(struct Task)); */

struct Process {
    struct  Task    pr_Task;
    struct  MsgPort pr_MsgPort; /* This is BPTR address from DOS functions  */
    WORD    pr_Pad;		/* Remaining variables on 4 byte boundaries */
    BPTR    pr_SegList;		/* Array of seg lists used by this process  */
    LONG    pr_StackSize;	/* Size of process stack in bytes	    */
    APTR    pr_GlobVec;		/* Global vector for this process (BCPL)    */
    LONG    pr_TaskNum;		/* CLI task number of zero if not a CLI	    */
    BPTR    pr_StackBase;	/* Ptr to high memory end of process stack  */
    LONG    pr_Result2;		/* Value of secondary result from last call */
    BPTR    pr_CurrentDir;	/* Lock associated with current directory   */
    BPTR    pr_CIS;		/* Current CLI Input Stream		    */
    BPTR    pr_COS;		/* Current CLI Output Stream		    */
    APTR    pr_ConsoleTask;	/* Console handler process for current window*/
    APTR    pr_FileSystemTask;	/* File handler process for current drive   */
    BPTR    pr_CLI;		/* pointer to CommandLineInterface	    */
    APTR    pr_ReturnAddr;	/* pointer to previous stack frame	    */
    APTR    pr_PktWait;		/* Function to be called when awaiting msg  */
    APTR    pr_WindowPtr;	/* Window for error printing		    */

    /* following definitions are new with 2.0 */
    BPTR    pr_HomeDir;		/* Home directory of executing program	    */
    LONG    pr_Flags;		/* flags telling dos about process	    */
    void    (*pr_ExitCode)();	/* code to call on exit of program or NULL  */
    LONG    pr_ExitData;	/* Passed as an argument to pr_ExitCode.    */
    UBYTE   *pr_Arguments;	/* Arguments passed to the process at start */
    struct MinList pr_LocalVars; /* Local environment variables		    */
    ULONG   pr_ShellPrivate;	/* for the use of the current shell	    */
    BPTR    pr_CES;		/* Error stream - if NULL, use pr_COS	    */
};  /* Process */

/*
 * Flags for pr_Flags
 */
#define	PRB_FREESEGLIST		0
#define	PRF_FREESEGLIST		1
#define	PRB_FREECURRDIR		1
#define	PRF_FREECURRDIR		2
#define	PRB_FREECLI		2
#define	PRF_FREECLI		4
#define	PRB_CLOSEINPUT		3
#define	PRF_CLOSEINPUT		8
#define	PRB_CLOSEOUTPUT		4
#define	PRF_CLOSEOUTPUT		16
#define	PRB_FREEARGS		5
#define	PRF_FREEARGS		32

/* The long word address (BPTR) of this structure is returned by
 * Open() and other routines that return a file.  You need only worry
 * about this struct to do async io's via PutMsg() instead of
 * standard file system calls */

struct FileHandle {
   struct Message *fh_Link;	 /* EXEC message	      */
   struct MsgPort *fh_Port;	 /* Reply port for the packet */
   struct MsgPort *fh_Type;	 /* Port to do PutMsg() to
                  * Address is negative if a plain file */
   LONG fh_Buf;
   LONG fh_Pos;
   LONG fh_End;
   LONG fh_Funcs;
#define fh_Func1 fh_Funcs
   LONG fh_Func2;
   LONG fh_Func3;
   LONG fh_Args;
#define fh_Arg1 fh_Args
   LONG fh_Arg2;
}; /* FileHandle */

/* This is the extension to EXEC Messages used by DOS */

struct DosPacket {
   struct Message *dp_Link;	 /* EXEC message	      */
   struct MsgPort *dp_Port;	 /* Reply port for the packet */
                 /* Must be filled in each send. */
   LONG dp_Type;		 /* See ACTION_... below and
                  * 'R' means Read, 'W' means Write to the
                  * file system */
   LONG dp_Res1;		 /* For file system calls this is the result
                  * that would have been returned by the
                  * function, e.g. Write ('W') returns actual
                  * length written */
   LONG dp_Res2;		 /* For file system calls this is what would
                  * have been returned by IoErr() */
/*  Device packets common equivalents */
#define dp_Action  dp_Type
#define dp_Status  dp_Res1
#define dp_Status2 dp_Res2
#define dp_BufAddr dp_Arg1
   LONG dp_Arg1;
   LONG dp_Arg2;
   LONG dp_Arg3;
   LONG dp_Arg4;
   LONG dp_Arg5;
   LONG dp_Arg6;
   LONG dp_Arg7;
}; /* DosPacket */

/* A Packet does not require the Message to be before it in memory, but
 * for convenience it is useful to associate the two.
 * Also see the function init_std_pkt for initializing this structure */

struct StandardPacket {
   struct Message   sp_Msg;
   struct DosPacket sp_Pkt;
}; /* StandardPacket */

/* Packet types */
#define ACTION_NIL		0
#define ACTION_STARTUP		0
#define ACTION_GET_BLOCK	2	/* OBSOLETE */
#define ACTION_SET_MAP		4
#define ACTION_DIE		5
#define ACTION_EVENT		6
#define ACTION_CURRENT_VOLUME	7
#define ACTION_LOCATE_OBJECT	8
#define ACTION_RENAME_DISK	9
#define ACTION_WRITE		'W'
#define ACTION_READ		'R'
#define ACTION_FREE_LOCK	15
#define ACTION_DELETE_OBJECT	16
#define ACTION_RENAME_OBJECT	17
#define ACTION_MORE_CACHE	18
#define ACTION_COPY_DIR		19
#define ACTION_WAIT_CHAR	20
#define ACTION_SET_PROTECT	21
#define ACTION_CREATE_DIR	22
#define ACTION_EXAMINE_OBJECT	23
#define ACTION_EXAMINE_NEXT	24
#define ACTION_DISK_INFO	25
#define ACTION_INFO		26
#define ACTION_FLUSH		27
#define ACTION_SET_COMMENT	28
#define ACTION_PARENT		29
#define ACTION_TIMER		30
#define ACTION_INHIBIT		31
#define ACTION_DISK_TYPE	32
#define ACTION_DISK_CHANGE	33
#define ACTION_SET_DATE		34

#define ACTION_SCREEN_MODE	994

#define ACTION_READ_RETURN	1001
#define ACTION_WRITE_RETURN	1002
#define ACTION_SEEK		1008
#define ACTION_FINDUPDATE	1004
#define ACTION_FINDINPUT	1005
#define ACTION_FINDOUTPUT	1006
#define ACTION_END		1007
#define ACTION_SET_FILE_SIZE	1022	/* fast file system only in 1.3 */
#define ACTION_WRITE_PROTECT	1023	/* fast file system only in 1.3 */

/* new 2.0 packets */
#define ACTION_SAME_LOCK	40
#define ACTION_CHANGE_SIGNAL	995
#define ACTION_FORMAT		1020
#define ACTION_MAKE_LINK	1021
/**/
/**/
#define ACTION_READ_LINK	1024
#define ACTION_FH_FROM_LOCK	1026
#define ACTION_IS_FILESYSTEM	1027
#define ACTION_CHANGE_MODE	1028
/**/
#define ACTION_COPY_DIR_FH	1030
#define ACTION_PARENT_FH	1031
#define ACTION_EXAMINE_ALL	1033
#define ACTION_EXAMINE_FH	1034

#define ACTION_LOCK_RECORD	2008
#define ACTION_FREE_RECORD	2009

#define ACTION_ADD_NOTIFY	4097
#define ACTION_REMOVE_NOTIFY	4098

/* Tell a file system to serialize the current volume. This is typically
 * done by changing the creation date of the disk. This packet does not take
 * any arguments.  NOTE: be prepared to handle failure of this packet for
 * V37 ROM filesystems.
 */
#define	ACTION_SERIALIZE_DISK	4200

/*
 * A structure for holding error messages - stored as array with error == 0
 * for the last entry.
 */
struct ErrorString {
    LONG  *estr_Nums;
    UBYTE *estr_Strings;
};

/* DOS library node structure.
 * This is the data at positive offsets from the library node.
 * Negative offsets from the node is the jump table to DOS functions
 * node = (struct DosLibrary *) OpenLibrary( "dos.library" .. )	     */

struct DosLibrary {
    struct Library dl_lib;
    struct RootNode *dl_Root; /* Pointer to RootNode, described below */
    APTR    dl_GV;	      /* Pointer to BCPL global vector	      */
    LONG    dl_A2;	      /* BCPL standard register values	      */
    LONG    dl_A5;
    LONG    dl_A6;
    struct ErrorString *dl_Errors;	  /* PRIVATE pointer to array of error msgs */
    struct timerequest *dl_TimeReq;	  /* PRIVATE pointer to timer request */
    struct Library     *dl_UtilityBase;   /* PRIVATE ptr to utility library */
    struct Library     *dl_IntuitionBase; /* PRIVATE ptr to intuition library */
};  /*	DosLibrary */

/*			       */

struct RootNode {
    BPTR    rn_TaskArray;	     /* [0] is max number of CLI's
                      * [1] is APTR to process id of CLI 1
                      * [n] is APTR to process id of CLI n */
    BPTR    rn_ConsoleSegment; /* SegList for the CLI			   */
    struct  DateStamp rn_Time; /* Current time				   */
    LONG    rn_RestartSeg;     /* SegList for the disk validator process   */
    BPTR    rn_Info;	       /* Pointer to the Info structure		   */
    BPTR    rn_FileHandlerSegment; /* segment for a file handler	   */
    struct MinList rn_CliList; /* new list of all CLI processes */
                   /* the first cpl_Array is also rn_TaskArray */
    struct MsgPort *rn_BootProc; /* private ptr to msgport of boot fs	   */
    BPTR    rn_ShellSegment;   /* seglist for Shell (for NewShell)	   */
    LONG    rn_Flags;	       /* dos flags */
};  /* RootNode */

#define RNB_WILDSTAR	24
#define RNF_WILDSTAR	(1L<<24)
#define RNB_PRIVATE1	1	/* private for dos */
#define RNF_PRIVATE1	2

/* ONLY to be allocated by DOS! */
struct CliProcList {
    struct MinNode cpl_Node;
    LONG cpl_First;	     /* number of first entry in array */
    struct MsgPort **cpl_Array;
                 /* [0] is max number of CLI's in this entry (n)
                  * [1] is CPTR to process id of CLI cpl_First
                  * [n] is CPTR to process id of CLI cpl_First+n-1
                  */
};

struct DosInfo {
    BPTR    di_McName;	       /* PRIVATE: system resident module list	    */
#define di_ResList di_McName
    BPTR    di_DevInfo;	       /* Device List				    */
    BPTR    di_Devices;	       /* Currently zero			    */
    BPTR    di_Handlers;       /* Currently zero			    */
    APTR    di_NetHand;	       /* Network handler processid; currently zero */
    struct  SignalSemaphore di_DevLock;	   /* do NOT access directly! */
    struct  SignalSemaphore di_EntryLock;  /* do NOT access directly! */
    struct  SignalSemaphore di_DeleteLock; /* do NOT access directly! */
};  /* DosInfo */

/* structure for the Dos resident list.  Do NOT allocate these, use	  */
/* AddSegment(), and heed the warnings in the autodocs!			  */

struct Segment {
    BPTR seg_Next;
    LONG seg_UC;
    BPTR seg_Seg;
    UBYTE seg_Name[4];	/* actually the first 4 chars of BSTR name */
};

#define CMD_SYSTEM	-1
#define CMD_INTERNAL	-2
#define CMD_DISABLED	-999

/* DOS Processes started from the CLI via RUN or NEWCLI have this additional
 * set to data associated with them */

struct CommandLineInterface {
    LONG   cli_Result2;	       /* Value of IoErr from last command	  */
    BSTR   cli_SetName;	       /* Name of current directory		  */
    BPTR   cli_CommandDir;     /* Head of the path locklist		  */
    LONG   cli_ReturnCode;     /* Return code from last command		  */
    BSTR   cli_CommandName;    /* Name of current command		  */
    LONG   cli_FailLevel;      /* Fail level (set by FAILAT)		  */
    BSTR   cli_Prompt;	       /* Current prompt (set by PROMPT)	  */
    BPTR   cli_StandardInput;  /* Default (terminal) CLI input		  */
    BPTR   cli_CurrentInput;   /* Current CLI input			  */
    BSTR   cli_CommandFile;    /* Name of EXECUTE command file		  */
    LONG   cli_Interactive;    /* Boolean; True if prompts required	  */
    LONG   cli_Background;     /* Boolean; True if CLI created by RUN	  */
    BPTR   cli_CurrentOutput;  /* Current CLI output			  */
    LONG   cli_DefaultStack;   /* Stack size to be obtained in long words */
    BPTR   cli_StandardOutput; /* Default (terminal) CLI output		  */
    BPTR   cli_Module;	       /* SegList of currently loaded command	  */
};  /* CommandLineInterface */

/* This structure can take on different values depending on whether it is
 * a device, an assigned directory, or a volume.  Below is the structure
 * reflecting volumes only.  Following that is the structure representing
 * only devices. Following that is the unioned structure representing all
 * the values
 */

/* structure representing a volume */

struct DeviceList {
    BPTR		dl_Next;	/* bptr to next device list */
    LONG		dl_Type;	/* see DLT below */
    struct MsgPort *	dl_Task;	/* ptr to handler task */
    BPTR		dl_Lock;	/* not for volumes */
    struct DateStamp	dl_VolumeDate;	/* creation date */
    BPTR		dl_LockList;	/* outstanding locks */
    LONG		dl_DiskType;	/* 'DOS', etc */
    LONG		dl_unused;
    BSTR		dl_Name;	/* bptr to bcpl name */
};

/* device structure (same as the DeviceNode structure in filehandler.h) */

struct	      DevInfo {
    BPTR  dvi_Next;
    LONG  dvi_Type;
    APTR  dvi_Task;
    BPTR  dvi_Lock;
    BSTR  dvi_Handler;
    LONG  dvi_StackSize;
    LONG  dvi_Priority;
    LONG  dvi_Startup;
    BPTR  dvi_SegList;
    BPTR  dvi_GlobVec;
    BSTR  dvi_Name;
};

/* combined structure for devices, assigned directories, volumes */

struct DosList {
    BPTR		dol_Next;	 /* bptr to next device on list */
    LONG		dol_Type;	 /* see DLT below */
    struct MsgPort     *dol_Task;	 /* ptr to handler task */
    BPTR		dol_Lock;
    union {
    struct {
    BSTR	dol_Handler;	/* file name to load if seglist is null */
    LONG	dol_StackSize;	/* stacksize to use when starting process */
    LONG	dol_Priority;	/* task priority when starting process */
    ULONG	dol_Startup;	/* startup msg: FileSysStartupMsg for disks */
    BPTR	dol_SegList;	/* already loaded code for new task */
    BPTR	dol_GlobVec;	/* BCPL global vector to use when starting
                 * a process. -1 indicates a C/Assembler
                 * program. */
    } dol_handler;

    struct {
    struct DateStamp	dol_VolumeDate;	 /* creation date */
    BPTR			dol_LockList;	 /* outstanding locks */
    LONG			dol_DiskType;	 /* 'DOS', etc */
    } dol_volume;

    struct {
    UBYTE	*dol_AssignName;     /* name for non-or-late-binding assign */
    struct AssignList *dol_List; /* for multi-directory assigns (regular) */
    } dol_assign;

    } dol_misc;

    BSTR		dol_Name;	 /* bptr to bcpl name */
    };

/* structure used for multi-directory assigns. AllocVec()ed. */

struct AssignList {
    struct AssignList *al_Next;
    BPTR		   al_Lock;
};

/* definitions for dl_Type */
#define DLT_DEVICE	0
#define DLT_DIRECTORY	1	/* assign */
#define DLT_VOLUME	2
#define DLT_LATE	3	/* late-binding assign */
#define DLT_NONBINDING	4	/* non-binding assign */
#define DLT_PRIVATE	-1	/* for internal use only */

/* structure return by GetDeviceProc() */
struct DevProc {
    struct MsgPort *dvp_Port;
    BPTR		dvp_Lock;
    ULONG		dvp_Flags;
    struct DosList *dvp_DevNode;	/* DON'T TOUCH OR USE! */
};

/* definitions for dvp_Flags */
#define DVPB_UNLOCK	0
#define DVPF_UNLOCK	(1L << DVPB_UNLOCK)
#define DVPB_ASSIGN	1
#define DVPF_ASSIGN	(1L << DVPB_ASSIGN)

/* Flags to be passed to LockDosList(), etc */
#define LDB_DEVICES	2
#define LDF_DEVICES	(1L << LDB_DEVICES)
#define LDB_VOLUMES	3
#define LDF_VOLUMES	(1L << LDB_VOLUMES)
#define LDB_ASSIGNS	4
#define LDF_ASSIGNS	(1L << LDB_ASSIGNS)
#define LDB_ENTRY	5
#define LDF_ENTRY	(1L << LDB_ENTRY)
#define LDB_DELETE	6
#define LDF_DELETE	(1L << LDB_DELETE)

/* you MUST specify one of LDF_READ or LDF_WRITE */
#define LDB_READ	0
#define LDF_READ	(1L << LDB_READ)
#define LDB_WRITE	1
#define LDF_WRITE	(1L << LDB_WRITE)

/* actually all but LDF_ENTRY (which is used for internal locking) */
#define LDF_ALL		(LDF_DEVICES|LDF_VOLUMES|LDF_ASSIGNS)

/* a lock structure, as returned by Lock() or DupLock() */
struct FileLock {
    BPTR		fl_Link;	/* bcpl pointer to next lock */
    LONG		fl_Key;		/* disk block number */
    LONG		fl_Access;	/* exclusive or shared */
    struct MsgPort *	fl_Task;	/* handler task's port */
    BPTR		fl_Volume;	/* bptr to DLT_VOLUME DosList entry */
};

/* error report types for ErrorReport() */
#define REPORT_STREAM		0	/* a stream */
#define REPORT_TASK		1	/* a process - unused */
#define REPORT_LOCK		2	/* a lock */
#define REPORT_VOLUME		3	/* a volume node */
#define REPORT_INSERT		4	/* please insert volume */

/* Special error codes for ErrorReport() */
#define ABORT_DISK_ERROR	296	/* Read/write error */
#define ABORT_BUSY		288	/* You MUST replace... */

/* types for initial packets to shells from run/newcli/execute/system. */
/* For shell-writers only */
#define RUN_EXECUTE		-1
#define RUN_SYSTEM		-2
#define RUN_SYSTEM_ASYNCH	-3

/* Types for fib_DirEntryType.	NOTE that both USERDIR and ROOT are	 */
/* directories, and that directory/file checks should use <0 and >=0.	 */
/* This is not necessarily exhaustive!	Some handlers may use other	 */
/* values as needed, though <0 and >=0 should remain as supported as	 */
/* possible.								 */
#define ST_ROOT		1
#define ST_USERDIR	2
#define ST_SOFTLINK	3	/* looks like dir, but may point to a file! */
#define ST_LINKDIR	4	/* hard link to dir */
#define ST_FILE		-3	/* must be negative for FIB! */
#define ST_LINKFILE	-4	/* hard link to file */
#define ST_PIPEFILE	-5	/* for pipes that support ExamineFH */

#endif	/* DOS_DOSEXTENS_H */


Includes/dos/exall.h

#ifndef DOS_EXALL_H
#define DOS_EXALL_H
/*
**
**	$Filename: dos/exall.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.5 $
**	$Date: 90/07/12 $
**
**	include file for ExAll() data structures
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**
*/

#ifndef EXEC_TYPES_H
#include "exec/types.h"
#endif

#ifndef UTILITY_HOOKS_H
#include "utility/hooks.h"
#endif

/* values that can be passed for what data you want from ExAll() */
/* each higher value includes those below it (numerically)	 */
/* you MUST chose one of these values */
#define	ED_NAME		1
#define	ED_TYPE		2
#define ED_SIZE		3
#define ED_PROTECTION	4
#define ED_DATE		5
#define ED_COMMENT	6

/*
 *   Structure in which exall results are returned in.	Note that only the
 *   fields asked for will exist!
 */

struct ExAllData {
    struct ExAllData *ed_Next;
    UBYTE  *ed_Name;
    LONG	ed_Type;
    ULONG	ed_Size;
    ULONG	ed_Prot;
    ULONG	ed_Days;
    ULONG	ed_Mins;
    ULONG	ed_Ticks;
    UBYTE  *ed_Comment;	/* strings will be after last used field */
};

/*
 *   Control structure passed to ExAll.  Unused fields MUST be initialized to
 *   0, expecially eac_LastKey.
 *
 *   eac_MatchFunc is a hook (see utility.library documentation for usage)
 *   It should return true if the entry is to returned, false if it is to be
 *   ignored.
 *
 *   This structure MUST be allocated by AllocDosObject()!
 */

struct ExAllControl {
    ULONG	eac_Entries;	 /* number of entries returned in buffer      */
    ULONG	eac_LastKey;	 /* Don't touch inbetween linked ExAll calls! */
    UBYTE  *eac_MatchString; /* wildcard string for pattern match or NULL */
    struct Hook *eac_MatchFunc; /* optional private wildcard function     */
};

#endif /* DOS_EXALL_H */


Includes/dos/rdargs.i

    IFND	DOS_RDARGS_I
DOS_RDARGS_I SET 1
**
**	$Filename: dos/rdargs.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.7 $
**	$Date: 90/07/12 $
**
**	ReadArgs() structure definitions
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND EXEC_NODES_I
    INCLUDE "exec/nodes.i"
    ENDC

**********************************************************************
*
* The CSource data structure defines the input source for "RdItem()"
* as well as the ReadArgs call.  It is a publicly defined structure
* which may be used by applications which use code that follows the
* conventions defined for access.
*
* When passed to the dos.library functions, the value passed as
* struct *CSource is defined as follows:
*	if ( CSource == 0)	Use buffered IO "ReadChar()" as data source
*	else			Use CSource for input character stream
*
* The following two pseudo-code routines define how the CSource structure
* is used:
*
* long CS_ReadChar( struct CSource *CSource )
* {
*	if ( CSource == 0 )	return ReadChar();
*	if ( CSource->CurChr >= CSource->Length )	return ENDSTREAMCHAR;
*	return CSource->Buffer[ CSource->CurChr++ ];
* }
*
* BOOL CS_UnReadChar( struct CSource *CSource )
* {
*	if ( CSource == 0 )	return UnReadChar();
*	if ( CSource->CurChr <= 0 )	return FALSE;
*	CSource->CurChr--;
*	return TRUE;
* }
*
* To initialize a struct CSource, you set CSource->CS_Buffer to
* a string which is used as the data source, and set CS_Length to
* the number of characters in the string.  Normally CS_CurChr should
* be initialized to ZERO, or left as it was from prior use as
* a CSource.
*
**********************************************************************

    STRUCTURE	CSource,0
        APTR	CS_Buffer
        LONG	CS_Length
        LONG	CS_CurChr
        LABEL	CS_SIZEOF

**********************************************************************
*
* The RDArgs data structure is the input parameter passed to the DOS
* ReadArgs() function call.
*
* The RDA_Source structure is a CSource as defined above;
* if RDA_Source.CS_Buffer is non-null, RDA_Source is used as the input
* character stream to parse, else the input comes from the buffered STDIN
* calls ReadChar/UnReadChar.
*
* RDA_DAList is a private address which is used internally to track
* allocations which are freed by FreeArgs().  This MUST be initialized
* to NULL prior to the first call to ReadArgs().
*
* The RDA_Buffer and RDA_BufSiz fields allow the application to supply
* a fixed-size buffer in which to store the parsed data.  This allows
* the application to pre-allocate a buffer rather than requiring buffer
* space to be allocated.  If either RDA_Buffer or RDA_BufSiz is NULL,
* the application has not supplied a buffer.
*
* RDA_ExtHelp is a text string which will be displayed instead of the
* template string, if the user is prompted for input.
*
* RDA_Flags bits control how ReadArgs() works.	The flag bits are
* defined below.  Defaults are initialized to ZERO.
*
**********************************************************************

    STRUCTURE	RDArgs,0
        STRUCT	RDA_Source,CS_SIZEOF	; Select input source
        APTR	RDA_DAList		; PRIVATE.
        LONG	RDA_Buffer		; Optional string parsing space.
        LONG	RDA_BufSiz		; Size of RDA_Buffer (0..n)
        APTR	RDA_ExtHelp		; Optional extended help
        LONG	RDA_Flags		; Flags for any required control
        LABEL	RDA_SIZEOF

    BITDEF	RDA,STDIN,0	; Use "STDIN" rather than "COMMAND LINE"
    BITDEF	RDA,NOALLOC,1	; If set, do not allocate extra string space.
    BITDEF	RDA,NOPROMPT,2	; Disable reprompting for string input.

**********************************************************************
* Maximum number of template keywords which can be in a template passed
* to ReadArgs(). IMPLEMENTOR NOTE - must be a multiple of 4.
**********************************************************************
MAX_TEMPLATE_ITEMS	equ	100

**********************************************************************
* Maximum number of MULTIARG items returned by ReadArgs(), before
* an ERROR_LINE_TOO_LONG.  These two limitations are due to stack
* usage.  Applications should allow "a lot" of stack to use ReadArgs().
**********************************************************************
MAX_MULTIARGS	equ	128

    ENDC	; DOS_RDARGS_I


Includes/exec/ables.i

    IFND	EXEC_ABLES_I
EXEC_ABLES_I	SET	1
**
**	$Filename: exec/ables.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.6 $
**	$Date: 90/05/10 $
**
**	Task switch and interrupt control macros
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND EXEC_TYPES_I
    INCLUDE "exec/types.i"
    ENDC	; EXEC_TYPES_I

    IFND EXEC_EXECBASE_I
    INCLUDE "exec/execbase.i"
    ENDC	; EXEC_EXECBASE_I

*-------------------------------------------------------------------------
*
*   Interrupt Exclusion Macros.  Disable all tasks and interrupts.
*
*-------------------------------------------------------------------------

INT_ABLES   MACRO		; externals used by DISABLE and ENABLE
        XREF    _intena
        ENDM

;Disable interrupts.  Avoid use of DISABLE if at all possible.
;Please realize the danger of this macro!  Don't disable for long periods!
DISABLE     MACRO   ; [scratchReg],[NOFETCH] or have ExecBase in A6.
        IFC     '\1',''             ;Case 1: Assume A6=ExecBase
          MOVE.W  #$04000,_intena	;(NOT IF_SETCLR)+IF_INTEN
          ADDQ.B  #1,IDNestCnt(A6)
          MEXIT
        ENDC
        IFC     '\2','NOFETCH'      ;Case 2: Assume \1=ExecBase
          MOVE.W  #$04000,_intena
          ADDQ.B  #1,IDNestCnt(\1)
          MEXIT
        ENDC
        IFNC    '\1',''             ;Case 3: Use \1 as scratch
          MOVE.L  4,\1		;Get ExecBase
          MOVE.W  #$04000,_intena
          ADDQ.B  #1,IDNestCnt(\1)
          MEXIT
        ENDC
        ENDM

;Enable interrupts.  Please realize the danger of this macro!
ENABLE	    MACRO   ; [scratchReg],[NOFETCH] or have ExecBase in A6.
        IFC     '\1',''             ;Case 1: Assume A6=ExecBase
          SUBQ.B  #1,IDNestCnt(A6)
          BGE.S   ENABLE\@
          MOVE.W  #$0C000,_intena	;IF_SETCLR+IF_INTEN
ENABLE\@:
          MEXIT
        ENDC
        IFC     '\2','NOFETCH'      ;Case 2: Assume \1=ExecBase
          SUBQ.B  #1,IDNestCnt(\1)
          BGE.S   ENABLE\@
          MOVE.W  #$0C000,_intena
ENABLE\@:
          MEXIT
        ENDC
        IFNC    '\1',''             ;Case 3: Use \1 as scratch
          MOVE.L  4,\1		;Get ExecBase
          SUBQ.B  #1,IDNestCnt(\1)
          BGE.S   ENABLE\@
          MOVE.W  #$0C000,_intena
ENABLE\@:
          MEXIT
        ENDC
        ENDM

*-------------------------------------------------------------------------
*
*   Tasking Exclusion Macros.  Forbid all other tasks (but not interrupts)
*
*-------------------------------------------------------------------------

TASK_ABLES  MACRO		; externals used by FORBID and PERMIT
        XREF    _LVOPermit
        ENDM

;Prevent task switching (disables reschedule)
FORBID	    MACRO   ; [scratchReg],[NOFETCH] or ExecBase in A6!
        IFC     '\1',''             ;Case 1: Assume A6=ExecBase
          ADDQ.B  #1,TDNestCnt(A6)
          MEXIT
        ENDC
        IFC     '\2','NOFETCH'      ;Case 2: Assume \1=ExecBase
          ADDQ.B  #1,TDNestCnt(\1)
          MEXIT
        ENDC
        IFNC    '\1',''             ;Case 3: Use \1 as scratch
          MOVE.L  4,\1	;Get ExecBase
          ADDQ.B  #1,TDNestCnt(\1)
          MEXIT
        ENDC
        ENDM

;Enable task switching
PERMIT	    MACRO   ; [saveFlag],[NOFETCH] or ExecBase in A6!
        IFC     '\1',''             ;Case 1: Assume A6=ExecBase
          JSR     _LVOPermit(A6)
          MEXIT
        ENDC
        IFC     '\2','NOFETCH'      ;Case 2: Assume \1=ExecBase
          EXG.L   A6,\1		;put execbase in A6
          JSR     _LVOPermit(A6)    ;no registers touched.  A6=ExecBase
          EXG.L   A6,\1
          MEXIT
        ENDC
        IFNC    '\1',''             ;Case 2: save/restore A6
          MOVE.L  A6,-(SP)
          MOVE.L  4,A6
          JSR     _LVOPermit(A6)
          MOVE.L  (SP)+,A6
          MEXIT
        ENDC
        ENDM

    ENDC	; EXEC_ABLES_I


Includes/exec/execbase.i

    IFND	EXEC_EXECBASE_I
EXEC_EXECBASE_I SET	1
**
**	$Filename: exec/execbase.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.16 $
**	$Date: 91/10/10 $
**
**	Definition of the exec.library base structure.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND EXEC_TYPES_I
    INCLUDE "exec/types.i"
    ENDC	; EXEC_TYPES_I

    IFND EXEC_LISTS_I
    INCLUDE "exec/lists.i"
    ENDC	; EXEC_LISTS_I

    IFND EXEC_INTERRUPTS_I
    INCLUDE "exec/interrupts.i"
    ENDC	; EXEC_INTERRUPTS_I

    IFND EXEC_LIBRARIES_I
    INCLUDE "exec/libraries.i"
    ENDC	; EXEC_LIBRARIES_I

** Definition of the Exec library base structure (pointed to by location 4).
** Most fields are not to be viewed or modified by user programs.  Use
** extreme caution.
**
 STRUCTURE  ExecBase,LIB_SIZE		; Standard library node

******* Static System Variables *********************************************

        UWORD	SoftVer	; kickstart release number (obs.)
        WORD	LowMemChkSum	; checksum of 68000 trap vectors
        ULONG	ChkBase	; system base pointer complement
        APTR	ColdCapture	; coldstart soft capture vector
        APTR	CoolCapture	; coolstart soft capture vector
        APTR	WarmCapture	; warmstart soft capture vector
        APTR	SysStkUpper	; system stack base   (upper bound)
        APTR	SysStkLower	; top of system stack (lower bound)
        ULONG	MaxLocMem	; top of chip memory
        APTR	DebugEntry	; global debugger entry point
        APTR	DebugData	; global debugger data segment
        APTR	AlertData	; alert data segment
        APTR	MaxExtMem	; top of extended mem, or null if none

        WORD	ChkSum		; for all of the above (minus 2)

******* Interrupt Related ********************************************

        LABEL	IntVects
        STRUCT	IVTBE,IV_SIZE
        STRUCT	IVDSKBLK,IV_SIZE
        STRUCT	IVSOFTINT,IV_SIZE
        STRUCT	IVPORTS,IV_SIZE
        STRUCT	IVCOPER,IV_SIZE
        STRUCT	IVVERTB,IV_SIZE
        STRUCT	IVBLIT,IV_SIZE
        STRUCT	IVAUD0,IV_SIZE
        STRUCT	IVAUD1,IV_SIZE
        STRUCT	IVAUD2,IV_SIZE
        STRUCT	IVAUD3,IV_SIZE
        STRUCT	IVRBF,IV_SIZE
        STRUCT	IVDSKSYNC,IV_SIZE
        STRUCT	IVEXTER,IV_SIZE
        STRUCT	IVINTEN,IV_SIZE
        STRUCT	IVNMI,IV_SIZE

******* Dynamic System Variables *************************************

        APTR	ThisTask	; pointer to current task (readable)

        ULONG	IdleCount	; idle counter
        ULONG	DispCount	; dispatch counter
        UWORD	Quantum	; time slice quantum
        UWORD	Elapsed	; current quantum ticks
        UWORD	SysFlags	; misc internal system flags
        BYTE	IDNestCnt	; interrupt disable nesting count
        BYTE	TDNestCnt	; task disable nesting count

        UWORD	AttnFlags	; special attention flags (readable)

        UWORD	AttnResched	; rescheduling attention
        APTR	ResModules	; pointer to resident module array
        APTR	TaskTrapCode	; default task trap routine
        APTR	TaskExceptCode	; default task exception code
        APTR	TaskExitCode	; default task exit code
        ULONG	TaskSigAlloc	; preallocated signal mask
        UWORD	TaskTrapAlloc	; preallocated trap mask

******* System List Headers (private!) ********************************

        STRUCT	MemList,LH_SIZE
        STRUCT	ResourceList,LH_SIZE
        STRUCT	DeviceList,LH_SIZE
        STRUCT	IntrList,LH_SIZE
        STRUCT	LibList,LH_SIZE
        STRUCT	PortList,LH_SIZE
        STRUCT	TaskReady,LH_SIZE
        STRUCT	TaskWait,LH_SIZE

        STRUCT	SoftInts,SH_SIZE*5

******* Other Globals ******************************************************

        STRUCT	LastAlert,4*4

        ;------ these next two variables are provided to allow
        ;------ system developers to have a rough idea of the
        ;------ period of two externally controlled signals --
        ;------ the time between vertical blank interrupts and the
        ;------ external line rate (which is counted by CIA A's
        ;------ "time of day" clock).  In general these values
        ;------ will be 50 or 60, and may or may not track each
        ;------ other.  These values replace the obsolete AFB_PAL
        ;------ and AFB_50HZ flags.
        UBYTE	VBlankFrequency 	;(readable)
        UBYTE	PowerSupplyFrequency	;(readable)

        STRUCT	SemaphoreList,LH_SIZE

        ;------ these next two are to be able to kickstart into user ram.
        ;------ KickMemPtr holds a singly linked list of MemLists which
        ;------ will be removed from the memory list via AllocAbs.	If
        ;------ all the AllocAbs's succeeded, then the KickTagPtr will
        ;------ be added to the rom tag list.
        APTR	KickMemPtr	; ptr to queue of mem lists
        APTR	KickTagPtr	; ptr to rom tag queue
        APTR	KickCheckSum	; checksum for mem and tags

******* V36 Exec additions start here ***************************************

        UWORD	ex_Pad0
        ULONG	ex_LaunchPoint	; Private to Launch/Switch
        APTR	ex_RamLibPrivate
        ;* The next ULONG contains the system "E" clock frequency,
        ;* expressed in Hertz.  The E clock is used as a timebase for
        ;* the Amiga's 8520 I/O chips. (E is connected to "02").
        ;* Typical values are 715909 for NTSC, or 709379 for PAL.
        ;*
        ULONG	ex_EClockFrequency ;(readable)
        ULONG	ex_CacheControl	   ;Private to the CacheControl call
        ULONG	ex_TaskID	   ;Next available task ID

        ULONG	ex_PuddleSize
        ULONG	ex_PoolThreshold
        STRUCT	ex_PublicPool,MLN_SIZE

        APTR	ex_MMULock	   ;Private

        STRUCT	ex_Reserved,12

        LABEL	SYSBASESIZE

******* Bit defines for AttnFlags (see above) *******************************

*  Processors and Co-processors:
    BITDEF	AF,68010,0	; also set for 68020
    BITDEF	AF,68020,1	; also set for 68030
    BITDEF	AF,68030,2	; also set for 68040
    BITDEF	AF,68040,3
    BITDEF	AF,68881,4	; also set for 68882
    BITDEF	AF,68882,5
    BITDEF	AF,FPU40,6	; Set if 68040 FPU
;
; The AFB_FPU40 bit is set when a working 68040 FPU
; is in the system.  If this bit is set and both the
; AFB_68881 and AFB_68882 bits are not set, then the 68040
; math emulation code has not been loaded and only 68040
; FPU instructions are available.  This bit is valid *ONLY*
; if the AFB_68040 bit is set.
;
;	BITDEF	AF,RESERVED8,8
;	BITDEF	AF,RESERVED9,9
    BITDEF	AF,PRIVATE,15	; Just what it says

******* Selected bit definitions for Cache manipulation calls **************

    BITDEF	CACR,EnableI,0		;Enable instruction cache
    BITDEF	CACR,FreezeI,1		;Freeze instruction cache
    BITDEF	CACR,ClearI,3		;Clear instruction cache
    BITDEF	CACR,IBE,4		;Instruction burst enable
    BITDEF	CACR,EnableD,8		;68030 Enable data cache
    BITDEF	CACR,FreezeD,9		;68030 Freeze data cache
    BITDEF	CACR,ClearD,11		;68030 Clear data cache
    BITDEF	CACR,DBE,12		;68030 Data burst enable
    BITDEF	CACR,WriteAllocate,13	;68030 Write-Allocate mode (must
                    ;always be set)
    BITDEF	CACR,CopyBack,31	;Master enable for copyback caches

    BITDEF	DMA,Continue,1		;Continuation flag for CachePreDMA
    BITDEF	DMA,NoModify,2		;Set if DMA does not update memory

    ENDC	; EXEC_EXECBASE_I


Includes/exec/lists.h

#ifndef EXEC_LISTS_H
#define EXEC_LISTS_H
/*
**	$Filename: exec/lists.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.10 $
**	$Date: 91/03/15 $
**
**	Definitions and macros for use with Exec lists
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_NODES_H
#include "exec/nodes.h"
#endif /* EXEC_NODES_H */

/*
 *  Full featured list header.
 */
struct List {
   struct  Node *lh_Head;
   struct  Node *lh_Tail;
   struct  Node *lh_TailPred;
   UBYTE   lh_Type;
   UBYTE   l_pad;
};	/* word aligned */

/*
 * Minimal List Header - no type checking
 */
struct MinList {
   struct  MinNode *mlh_Head;
   struct  MinNode *mlh_Tail;
   struct  MinNode *mlh_TailPred;
};	/* longword aligned */

/*
 *	Check for the presence of any nodes on the given list.	These
 *	macros are even safe to use on lists that are modified by other
 *	tasks.	However; if something is simultaneously changing the
 *	list, the result of the test is unpredictable.
 *
 *	Unless you first arbitrated for ownership of the list, you can't
 *	_depend_ on the contents of the list.  Nodes might have been added
 *	or removed during or after the macro executes.
 *
 *		if( IsListEmpty(list) )		printf("List is empty\n");
 */
#define IsListEmpty(x) \
    ( ((x)->lh_TailPred) == (struct Node *)(x) )

#define IsMsgPortEmpty(x) \
    ( ((x)->mp_MsgList.lh_TailPred) == (struct Node *)(&(x)->mp_MsgList) )

#endif	/* EXEC_LISTS_H */


Includes/exec/resident.i

    IFND	EXEC_RESIDENT_I
EXEC_RESIDENT_I	SET	1
**
**	$Filename: exec/resident.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.8 $
**	$Date: 90/11/01 $
**
**	Resident/ROMTag stuff.	Used to identify and initialize code modules.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND EXEC_TYPES_I
    INCLUDE "exec/types.i"
    ENDC ; EXEC_TYPES_I

*----------------------------------------------------------------
*
*   Resident Module Tag
*
*----------------------------------------------------------------

 STRUCTURE RT,0
    UWORD RT_MATCHWORD			; word to match on (ILLEGAL)
    APTR  RT_MATCHTAG			; pointer to the above (RT_MATCHWORD)
    APTR  RT_ENDSKIP			; address to continue scan
    UBYTE RT_FLAGS			; various tag flags
    UBYTE RT_VERSION			; release version number
    UBYTE RT_TYPE			; type of module (NT_XXXXXX)
    BYTE  RT_PRI			; initialization priority
    APTR  RT_NAME			; pointer to node name
    APTR  RT_IDSTRING			; pointer to identification string
    APTR  RT_INIT			; pointer to init code
    LABEL RT_SIZE

;------ Match word definition:

RTC_MATCHWORD	EQU	$4AFC		; The 68000 "ILLEGAL" instruction

;------ RT_FLAGS bit and field definitions:

    BITDEF RT,COLDSTART,0
    BITDEF RT,SINGLETASK,1
    BITDEF RT,AFTERDOS,2
    BITDEF RT,AUTOINIT,7		; RT_INIT points to data structure

; Compatibility: (obsolete)
;RTM_WHEN	EQU	1		; field position in RT_FLAGS
RTW_NEVER	EQU	0		; never ever init
RTW_COLDSTART	EQU	1		; init at coldstart time

    ENDC	; EXEC_RESIDENT_I


Includes/exec/alerts.h

#ifndef EXEC_ALERTS_H
#define EXEC_ALERTS_H
/*
**	$Filename: exec/alerts.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.18 $
**	$Date: 91/01/12 $
**
**	Alert numbers, as displayed by system crashes.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

/*********************************************************************
*
*  Format of the alert error number:
*
*    +-+-------------+----------------+--------------------------------+
*    |D|  SubSysId   |	General Error |    SubSystem Specific Error    |
*    +-+-------------+----------------+--------------------------------+
*     1    7 bits	   8 bits		   16 bits
*
*		     D:  DeadEnd alert
*	      SubSysId:  indicates ROM subsystem number.
*	 General Error:  roughly indicates what the error was
*	Specific Error:  indicates more detail
**********************************************************************/

/*********************************************************************
*
*  General Alerts
*
*  For example: timer.device cannot open math.library would be 0x05038015
*
*	Alert(AN_TimerDev|AG_OpenLib|AO_MathLib);
*
*********************************************************************/

/*------ alert types */
#define AT_DeadEnd	0x80000000
#define AT_Recovery	0x00000000

/*------ general purpose alert codes */
#define AG_NoMemory	0x00010000
#define AG_MakeLib	0x00020000
#define AG_OpenLib	0x00030000
#define AG_OpenDev	0x00040000
#define AG_OpenRes	0x00050000
#define AG_IOError	0x00060000
#define AG_NoSignal	0x00070000
#define AG_BadParm	0x00080000
#define AG_CloseLib	0x00090000	/* usually too many closes */
#define AG_CloseDev	0x000A0000	/* or a mismatched close */
#define AG_ProcCreate	0x000B0000	/* Process creation failed */

/*------ alert objects: */
#define AO_ExecLib	0x00008001
#define AO_GraphicsLib	0x00008002
#define AO_LayersLib	0x00008003
#define AO_Intuition	0x00008004
#define AO_MathLib	0x00008005
#define AO_DOSLib	0x00008007
#define AO_RAMLib	0x00008008
#define AO_IconLib	0x00008009
#define AO_ExpansionLib 0x0000800A
#define AO_DiskfontLib	0x0000800B
#define AO_UtilityLib	0x0000800C

#define AO_AudioDev	0x00008010
#define AO_ConsoleDev	0x00008011
#define AO_GamePortDev	0x00008012
#define AO_KeyboardDev	0x00008013
#define AO_TrackDiskDev 0x00008014
#define AO_TimerDev	0x00008015

#define AO_CIARsrc	0x00008020
#define AO_DiskRsrc	0x00008021
#define AO_MiscRsrc	0x00008022

#define AO_BootStrap	0x00008030
#define AO_Workbench	0x00008031
#define AO_DiskCopy	0x00008032
#define AO_GadTools	0x00008033
#define AO_Unknown	0x00008035

/*********************************************************************
*
*   Specific Alerts:
*
*********************************************************************/

/*------ exec.library */
#define AN_ExecLib	0x01000000
#define AN_ExcptVect	0x01000001 /* 68000 exception vector checksum (obs.) */
#define AN_BaseChkSum	0x01000002 /* Execbase checksum (obs.) */
#define AN_LibChkSum	0x01000003 /* Library checksum failure */

#define AN_MemCorrupt	0x81000005 /* Corrupt memory list detected in FreeMem */
#define AN_IntrMem	0x81000006 /* No memory for interrupt servers */
#define AN_InitAPtr	0x01000007 /* InitStruct() of an APTR source (obs.) */
#define AN_SemCorrupt	0x01000008 /* A semaphore is in an illegal state
                      at ReleaseSempahore() */
#define AN_FreeTwice	0x01000009 /* Freeing memory already freed */
#define AN_BogusExcpt	0x8100000A /* illegal 68k exception taken (obs.) */
#define AN_IOUsedTwice	0x0100000B /* Attempt to reuse active IORequest */
#define AN_MemoryInsane 0x0100000C /* Sanity check on memory list failed
                      during AvailMem(MEMF_LARGEST) */
#define AN_IOAfterClose 0x0100000D /* IO attempted on closed IORequest */
#define AN_StackProbe	0x0100000E /* Stack appears to extend out of range */
#define AN_BadFreeAddr	0x0100000F /* Memory header not located. [ Usually an
                      invalid address passed to FreeMem() ] */

/*------ graphics.library */
#define AN_GraphicsLib	0x02000000
#define AN_GfxNoMem	0x82010000	/* graphics out of memory */
#define AN_GfxNoMemMspc 0x82010001	/* MonitorSpec alloc, no memory */
#define AN_LongFrame	0x82010006	/* long frame, no memory */
#define AN_ShortFrame	0x82010007	/* short frame, no memory */
#define AN_TextTmpRas	0x02010009	/* text, no memory for TmpRas */
#define AN_BltBitMap	0x8201000A	/* BltBitMap, no memory */
#define AN_RegionMemory 0x8201000B	/* regions, memory not available */
#define AN_MakeVPort	0x82010030	/* MakeVPort, no memory */
#define AN_GfxNewError	0x0200000C
#define AN_GfxFreeError 0x0200000D

#define AN_GfxNoLCM	0x82011234	/* emergency memory not available */

#define AN_ObsoleteFont 0x02000401	/* unsupported font description used */

/*------ layers.library */
#define AN_LayersLib	0x03000000
#define AN_LayersNoMem	0x83010000	/* layers out of memory */

/*------ intuition.library */
#define AN_Intuition	0x04000000
#define AN_GadgetType	0x84000001	/* unknown gadget type */
#define AN_BadGadget	0x04000001	/* Recovery form of AN_GadgetType */
#define AN_CreatePort	0x84010002	/* create port, no memory */
#define AN_ItemAlloc	0x04010003	/* item plane alloc, no memory */
#define AN_SubAlloc	0x04010004	/* sub alloc, no memory */
#define AN_PlaneAlloc	0x84010005	/* plane alloc, no memory */
#define AN_ItemBoxTop	0x84000006	/* item box top < RelZero */
#define AN_OpenScreen	0x84010007	/* open screen, no memory */
#define AN_OpenScrnRast 0x84010008	/* open screen, raster alloc, no memory */
#define AN_SysScrnType	0x84000009	/* open sys screen, unknown type */
#define AN_AddSWGadget	0x8401000A	/* add SW gadgets, no memory */
#define AN_OpenWindow	0x8401000B	/* open window, no memory */
#define AN_BadState	0x8400000C	/* Bad State Return entering Intuition */
#define AN_BadMessage	0x8400000D	/* Bad Message received by IDCMP */
#define AN_WeirdEcho	0x8400000E	/* Weird echo causing incomprehension */
#define AN_NoConsole	0x8400000F	/* couldn't open the Console Device */

/*------ math.library */
#define AN_MathLib	0x05000000

/*------ dos.library */
#define AN_DOSLib	0x07000000
#define AN_StartMem	0x07010001 /* no memory at startup */
#define AN_EndTask	0x07000002 /* EndTask didn't */
#define AN_QPktFail	0x07000003 /* Qpkt failure */
#define AN_AsyncPkt	0x07000004 /* Unexpected packet received */
#define AN_FreeVec	0x07000005 /* Freevec failed */
#define AN_DiskBlkSeq	0x07000006 /* Disk block sequence error */
#define AN_BitMap	0x07000007 /* Bitmap corrupt */
#define AN_KeyFree	0x07000008 /* Key already free */
#define AN_BadChkSum	0x07000009 /* Invalid checksum */
#define AN_DiskError	0x0700000A /* Disk Error */
#define AN_KeyRange	0x0700000B /* Key out of range */
#define AN_BadOverlay	0x0700000C /* Bad overlay */
#define AN_BadInitFunc	0x0700000D /* Invalid init packet for cli/shell */
#define AN_FileReclosed 0x0700000E /* A filehandle was closed more than once */

/*------ ramlib.library */
#define AN_RAMLib	0x08000000
#define AN_BadSegList	0x08000001	/* no overlays in library seglists */

/*------ icon.library */
#define AN_IconLib	0x09000000

/*------ expansion.library */
#define AN_ExpansionLib 0x0A000000
#define AN_BadExpansionFree	0x0A000001 /* freeed free region */

/*------ diskfont.library */
#define AN_DiskfontLib	0x0B000000

/*------ audio.device */
#define AN_AudioDev	0x10000000

/*------ console.device */
#define AN_ConsoleDev	0x11000000
#define AN_NoWindow	0x11000001	/* Console can't open initial window */

/*------ gameport.device */
#define AN_GamePortDev	0x12000000

/*------ keyboard.device */
#define AN_KeyboardDev	0x13000000

/*------ trackdisk.device */
#define AN_TrackDiskDev 0x14000000
#define AN_TDCalibSeek	0x14000001	/* calibrate: seek error */
#define AN_TDDelay	0x14000002	/* delay: error on timer wait */

/*------ timer.device */
#define AN_TimerDev	0x15000000
#define AN_TMBadReq	0x15000001 /* bad request */
#define AN_TMBadSupply	0x15000002 /* power supply -- no 50/60Hz ticks */

/*------ cia.resource */
#define AN_CIARsrc	0x20000000

/*------ disk.resource */
#define AN_DiskRsrc	0x21000000
#define AN_DRHasDisk	0x21000001	/* get unit: already has disk */
#define AN_DRIntNoAct	0x21000002	/* interrupt: no active unit */

/*------ misc.resource */
#define AN_MiscRsrc	0x22000000

/*------ bootstrap */
#define AN_BootStrap	0x30000000
#define AN_BootError	0x30000001	/* boot code returned an error */

/*------ Workbench */
#define AN_Workbench			0x31000000
#define AN_NoFonts			0xB1000001
#define AN_WBBadStartupMsg1		0x31000001
#define AN_WBBadStartupMsg2		0x31000002
#define AN_WBBadIOMsg			0x31000003

#define AN_WBInitPotionAllocDrawer	0xB1010004
#define AN_WBCreateWBMenusCreateMenus1	0xB1010005
#define AN_WBCreateWBMenusCreateMenus2	0xB1010006
#define AN_WBLayoutWBMenusLayoutMenus	0xB1010007
#define AN_WBAddToolMenuItem		0xB1010008
#define AN_WBReLayoutToolMenu		0xB1010009
#define AN_WBinitTimer			0xB101000A
#define AN_WBInitLayerDemon		0xB101000B
#define AN_WBinitWbGels			0xB101000C
#define AN_WBInitScreenAndWindows1	0xB101000D
#define AN_WBInitScreenAndWindows2	0xB101000E
#define AN_WBInitScreenAndWindows3	0xB101000F
#define AN_WBMAlloc			0xB1010010

/*------ DiskCopy */
#define AN_DiskCopy	0x32000000

/*------ toolkit for Intuition */
#define AN_GadTools	0x33000000

/*------ System utility library */
#define AN_UtilityLib	0x34000000

/*------ For use by any application that needs it */
#define AN_Unknown	0x35000000

#endif /* EXEC_ALERTS_H */


Includes/exec/exec_lib.i

    FUNCDEF	Supervisor
    FUNCDEF	ExitIntr
    FUNCDEF	Schedule
    FUNCDEF	Reschedule
    FUNCDEF	Switch
    FUNCDEF	Dispatch
    FUNCDEF	Exception
    FUNCDEF	InitCode
    FUNCDEF	InitStruct
    FUNCDEF	MakeLibrary
    FUNCDEF	MakeFunctions
    FUNCDEF	FindResident
    FUNCDEF	InitResident
    FUNCDEF	Alert
    FUNCDEF	Debug
    FUNCDEF	Disable
    FUNCDEF	Enable
    FUNCDEF	Forbid
    FUNCDEF	Permit
    FUNCDEF	SetSR
    FUNCDEF	SuperState
    FUNCDEF	UserState
    FUNCDEF	SetIntVector
    FUNCDEF	AddIntServer
    FUNCDEF	RemIntServer
    FUNCDEF	Cause
    FUNCDEF	Allocate
    FUNCDEF	Deallocate
    FUNCDEF	AllocMem
    FUNCDEF	AllocAbs
    FUNCDEF	FreeMem
    FUNCDEF	AvailMem
    FUNCDEF	AllocEntry
    FUNCDEF	FreeEntry
    FUNCDEF	Insert
    FUNCDEF	AddHead
    FUNCDEF	AddTail
    FUNCDEF	Remove
    FUNCDEF	RemHead
    FUNCDEF	RemTail
    FUNCDEF	Enqueue
    FUNCDEF	FindName
    FUNCDEF	AddTask
    FUNCDEF	RemTask
    FUNCDEF	FindTask
    FUNCDEF	SetTaskPri
    FUNCDEF	SetSignal
    FUNCDEF	SetExcept
    FUNCDEF	Wait
    FUNCDEF	Signal
    FUNCDEF	AllocSignal
    FUNCDEF	FreeSignal
    FUNCDEF	AllocTrap
    FUNCDEF	FreeTrap
    FUNCDEF	AddPort
    FUNCDEF	RemPort
    FUNCDEF	PutMsg
    FUNCDEF	GetMsg
    FUNCDEF	ReplyMsg
    FUNCDEF	WaitPort
    FUNCDEF	FindPort
    FUNCDEF	AddLibrary
    FUNCDEF	RemLibrary
    FUNCDEF	OldOpenLibrary
    FUNCDEF	CloseLibrary
    FUNCDEF	SetFunction
    FUNCDEF	SumLibrary
    FUNCDEF	AddDevice
    FUNCDEF	RemDevice
    FUNCDEF	OpenDevice
    FUNCDEF	CloseDevice
    FUNCDEF	DoIO
    FUNCDEF	SendIO
    FUNCDEF	CheckIO
    FUNCDEF	WaitIO
    FUNCDEF	AbortIO
    FUNCDEF	AddResource
    FUNCDEF	RemResource
    FUNCDEF	OpenResource
    FUNCDEF	RawIOInit
    FUNCDEF	RawMayGetChar
    FUNCDEF	RawPutChar
    FUNCDEF	RawDoFmt
    FUNCDEF	GetCC
    FUNCDEF	TypeOfMem
    FUNCDEF	Procure
    FUNCDEF	Vacate
    FUNCDEF	OpenLibrary
    FUNCDEF	InitSemaphore
    FUNCDEF	ObtainSemaphore
    FUNCDEF	ReleaseSemaphore
    FUNCDEF	AttemptSemaphore
    FUNCDEF	ObtainSemaphoreList
    FUNCDEF	ReleaseSemaphoreList
    FUNCDEF	FindSemaphore
    FUNCDEF	AddSemaphore
    FUNCDEF	RemSemaphore
    FUNCDEF	SumKickData
    FUNCDEF	AddMemList
    FUNCDEF	CopyMem
    FUNCDEF	CopyMemQuick
    FUNCDEF	CacheClearU
    FUNCDEF	CacheClearE
    FUNCDEF	CacheControl
    FUNCDEF	CreateIORequest
    FUNCDEF	DeleteIORequest
    FUNCDEF	CreateMsgPort
    FUNCDEF	DeleteMsgPort
    FUNCDEF	ObtainSemaphoreShared
    FUNCDEF	AllocVec
    FUNCDEF	FreeVec
    FUNCDEF	CreatePrivatePool
    FUNCDEF	DeletePrivatePool
    FUNCDEF	AllocPooled
    FUNCDEF	FreePooled
    FUNCDEF	AttemptSemaphoreShared
    FUNCDEF	ColdReboot
    FUNCDEF	StackSwap
    FUNCDEF	ChildFree
    FUNCDEF	ChildOrphan
    FUNCDEF	ChildStatus
    FUNCDEF	ChildWait
    FUNCDEF	CachePreDMA
    FUNCDEF	CachePostDMA
    FUNCDEF	ExecReserved01
    FUNCDEF	ExecReserved02
    FUNCDEF	ExecReserved03
    FUNCDEF	ExecReserved04


Includes/exec/lists.i

    IFND	EXEC_LISTS_I
EXEC_LISTS_I	SET	1
**
**	$Filename: exec/lists.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.10 $
**	$Date: 91/02/19 $
**
**	Definitions and macros for use with Exec lists.  Most of the
**	macros require ownership or locking of the list before use.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND EXEC_NODES_I
    INCLUDE "exec/nodes.i"
    ENDC	; EXEC_NODES_I

*---------------------------------------------------------------------

*
* Full featured list header
*
   STRUCTURE	LH,0
    APTR	LH_HEAD
    APTR	LH_TAIL
    APTR	LH_TAILPRED
    UBYTE	LH_TYPE
    UBYTE	LH_pad
    LABEL	LH_SIZE ;word aligned

*
* Minimal List Header - no type checking (best for most applications)
*
   STRUCTURE	MLH,0
    APTR	MLH_HEAD
    APTR	MLH_TAIL
    APTR	MLH_TAILPRED
    LABEL	MLH_SIZE ;longword aligned

*---------------------------------------------------------------------

;Prepare a list header for use
NEWLIST     MACRO   ; list
        MOVE.L  \1,LH_TAILPRED(\1)
        ADDQ.L  #4,\1	;Get address of LH_TAIL
        CLR.L   (\1)	;Clear LH_TAIL
        MOVE.L  \1,-(\1)	;Address of LH_TAIL to LH_HEAD
        ENDM

;Test if list is empty (list address in register)
;This operation is safe at any time - no list arbitration needed.
TSTLIST     MACRO   ; [list]
        IFGT    NARG-1
           FAIL    !!! TSTLIST - Too many arguments !!!
        ENDC
        IFC     '\1',''
        CMP.L   LH_TAIL+LN_PRED(A0),A0
        ENDC
        IFNC    '\1',''
        CMP.L   LH_TAIL+LN_PRED(\1),\1
        ENDC
        ENDM

;Test if list is empty (from effective address of list)
;list arbitration required.
TSTLST2     MACRO    ;EA of list,=node
        MOVE.L   \1,\2
        TST.L    (\2)
        ENDM

;Get next in list
SUCC	    MACRO   ; node,=succ
        MOVE.L  (\1),\2
        ENDM

;Get previous in list
PRED	    MACRO   ; node,=pred
        MOVE.L  LN_PRED(\1),\2
        ENDM

;If empty, branch
IFEMPTY     MACRO   ; list,label
        CMP.L   LH_TAIL+LN_PRED(\1),\1
        BEQ     \2
        ENDM

;If not empty, branch
IFNOTEMPTY  MACRO   ; list,label
        CMP.L   LH_TAIL+LN_PRED(\1),\1
        BNE     \2
        ENDM

;Get next node, test if at end
TSTNODE     MACRO   ; node,=next
        MOVE.L  (\1),\2
        TST.L   (\2)
        ENDM

;Get next, go to exit label if at end
NEXTNODE    MACRO   ; next=next,=current,exit_label ([.s],DX,AX,DISP16)
        MOVE.L  \1,\2
        MOVE.L  (\2),\1
        IFC     '\0',''	;Check extension
        BEQ     \3
        ENDC
        IFNC    '\0',''
        BEQ.S   \3
        ENDC
        ENDM

;Add to head of list
ADDHEAD     MACRO   ; A0-list(destroyed) A1-node D0-(destroyed)
        MOVE.L  (A0),D0
        MOVE.L  A1,(A0)
        MOVEM.L D0/A0,(A1)
        MOVE.L  D0,A0
        MOVE.L  A1,LN_PRED(A0)
        ENDM

;Add to tail of list
ADDTAIL     MACRO   ; A0-list(destroyed) A1-node D0-(destroyed)
        ADDQ.L  #LH_TAIL,A0
        MOVE.L  LN_PRED(A0),D0
        MOVE.L  A1,LN_PRED(A0)
        MOVE.L  A0,(A1)
        MOVE.L  D0,LN_PRED(A1)
        MOVE.L  D0,A0
        MOVE.L  A1,(A0)
        ENDM

;Remove node from whatever list it is in
REMOVE	    MACRO   ; A0-(destroyed)  A1-node(destroyed)
        MOVE.L  (A1),A0
        MOVE.L  LN_PRED(A1),A1
        MOVE.L  A0,(A1)
        MOVE.L  A1,LN_PRED(A0)
        ENDM

;Remove node from head of list
REMHEAD     MACRO   ; A0-list A1-(destroyed) D0=node
        MOVE.L  (A0),A1
        MOVE.L  (A1),D0
        BEQ.S   REMHEAD\@
        MOVE.L  D0,(A0)
        EXG.L   D0,A1
        MOVE.L  A0,LN_PRED(A1)
REMHEAD\@
        ENDM

;Remove head quickly
;	Useful when a scratch register is available, and
;	list is known to contain at least one node.
REMHEADQ    MACRO   ; list,=node,scratchReg-(destroyed)
        MOVE.L  (\1),\2
        MOVE.L  (\2),\3
        MOVE.L  \3,(\1)
        MOVE.L  \1,LN_PRED(\3)
        ENDM

;Remove node from tail of list
REMTAIL     MACRO   ; A0-list A1-(destroyed) D0=node
        MOVE.L  LH_TAIL+LN_PRED(A0),A1
        MOVE.L  LN_PRED(A1),D0
        BEQ.S   REMTAIL\@
        MOVE.L  D0,LH_TAIL+LN_PRED(A0)
        EXG.L   D0,A1
        MOVE.L  A0,(A1)
        ADDQ.L  #4,(A1)
REMTAIL\@
        ENDM

    ENDC	; EXEC_LISTS_I


Includes/exec/semaphores.h

#ifndef	EXEC_SEMAPHORES_H
#define	EXEC_SEMAPHORES_H
/*
**	$Filename: exec/semaphores.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.6 $
**	$Date: 90/05/10 $
**
**	Definitions for locking functions.
**
**	(C) Copyright 1986-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_NODES_H
#include "exec/nodes.h"
#endif /* EXEC_NODES_H */

#ifndef EXEC_LISTS_H
#include "exec/lists.h"
#endif /* EXEC_LISTS_H */

#ifndef EXEC_PORTS_H
#include "exec/ports.h"
#endif /* EXEC_PORTS_H */

#ifndef EXEC_TASKS_H
#include "exec/tasks.h"
#endif /* EXEC_TASKS_H */

/****** SignalSemaphore *********************************************/

/* Private structure used by ObtainSemaphore() */
struct SemaphoreRequest {
    struct  MinNode sr_Link;
    struct  Task *sr_Waiter;
};

/* Signal Semaphore data structure */
struct SignalSemaphore {
    struct  Node ss_Link;
    WORD    ss_NestCount;
    struct  MinList ss_WaitQueue;
    struct  SemaphoreRequest ss_MultipleLink;
    struct  Task *ss_Owner;
    WORD    ss_QueueCount;
};

/****** Semaphore (Procure/Vacate type) *****************************/

struct Semaphore {
    struct MsgPort sm_MsgPort;
    WORD   sm_Bids;
};

#define sm_LockMsg	mp_SigTask

#endif	/* EXEC_SEMAPHORES_H */


Includes/exec/alerts.i

    IFND EXEC_ALERTS_I
EXEC_ALERTS_I SET 1
**
**	$Filename: exec/alerts.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.17 $
**	$Date: 91/01/12 $
**
**	Alert numbers, as displayed by system crashes.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

**********************************************************************
*
*  Format of the alert error number:
*
*    +---------------+----------------+--------------------------------+
*    |D|  SubSysId   |	General Error |    SubSystem Specific Error    |
*    +---------------+----------------+--------------------------------+
*     1    7 bits	   8 bits		   16 bits
*
*		     D:  DeadEnd alert
*	      SubSysId:  indicates ROM subsystem number.
*	 General Error:  roughly indicates what the error was
*	Specific Error:  indicates more detail
***********************************************************************

*
*  Use this macro for causing an alert.  It is very sensitive to memory
*  corruption.... like stepping on location 4!	After the alert, it
*  will return.
*
*	A0/A1 and D0/D1 are destroyed
*
*
ALERT		MACRO	(alertNumber, [paramArray])
        movem.l d7/a5/a6,-(sp)
        move.l	#\1,d7
        IFNC	'\2',''
          lea.l	\2,a5
        ENDC
        move.l	4,a6
        jsr	_LVOAlert(a6)
        movem.l	(sp)+,d7/a5/a6
        ENDM
*
*  Use this macro for dead end alerts that never return
*
DEADALERT	MACRO	(alertNumber, [paramArray])
        move.l	#\1,d7
        IFNC	'\2',''
          lea.l \2,a5
        ENDC
        move.l	4,a6
        jsr	_LVOAlert(a6)	; never returns
        ENDM

**********************************************************************
*
*  General Alerts
*
*  For example:  timer.device cannot open math.library:
*
*	ALERT  (AN_TimerDev!AG_OpenLib!AO_MathLib)	;0x05038015
*
**********************************************************************

;------ alert types
AT_DeadEnd	equ $80000000
AT_Recovery	equ $00000000

;------ general purpose alert codes
AG_NoMemory	equ $00010000
AG_MakeLib	equ $00020000
AG_OpenLib	equ $00030000
AG_OpenDev	equ $00040000
AG_OpenRes	equ $00050000
AG_IOError	equ $00060000
AG_NoSignal	equ $00070000
AG_BadParm	equ $00080000
AG_CloseLib	equ $00090000	;Usually too many closes
AG_CloseDev	equ $000A0000	;or a mismatched close
AG_ProcCreate	equ $000B0000	;Process creation failed

;------ alert objects:
AO_ExecLib	equ $00008001
AO_GraphicsLib	equ $00008002
AO_LayersLib	equ $00008003
AO_Intuition	equ $00008004
AO_MathLib	equ $00008005
AO_DOSLib	equ $00008007
AO_RAMLib	equ $00008008
AO_IconLib	equ $00008009
AO_ExpansionLib	equ $0000800A
AO_DiskfontLib	equ $0000800B
AO_UtilityLib	equ $0000800C

AO_AudioDev	equ $00008010
AO_ConsoleDev	equ $00008011
AO_GamePortDev	equ $00008012
AO_KeyboardDev	equ $00008013
AO_TrackDiskDev equ $00008014
AO_TimerDev	equ $00008015

AO_CIARsrc	equ $00008020
AO_DiskRsrc	equ $00008021
AO_MiscRsrc	equ $00008022

AO_BootStrap	equ $00008030
AO_Workbench	equ $00008031
AO_DiskCopy	equ $00008032
AO_GadTools	equ $00008033
AO_Unknown	equ $00008035

**********************************************************************
*
*   Specific Alerts:
*
*   For example:   exec.library -- corrupted memory list
*
*	    ALERT  AN_MemCorrupt	;8100 0005
*
**********************************************************************

;------ exec.library
AN_ExecLib	equ $01000000
AN_ExcptVect	equ $01000001	; 68000 exception vector checksum (obs.)
AN_BaseChkSum	equ $01000002	; Execbase checksum bad (obs.)
AN_LibChkSum	equ $01000003	; Library checksum failure

AN_MemCorrupt	equ $81000005	; Corrupt memory list detected in FreeMem
AN_IntrMem	equ $81000006	; No memory for interrupt servers
AN_InitAPtr	equ $01000007	; InitStruct() of an APTR source (obs.)
AN_SemCorrupt	equ $01000008	; A semaphore is in an illegal state
                ; at RemSempahore()
AN_FreeTwice	equ $01000009	; Freeing memory that is already free
AN_BogusExcpt	equ $8100000A	; Illegal 68k exception taken (obs.)
AN_IOUsedTwice	equ $0100000B	; Attempt to reuse active IORequest
AN_MemoryInsane	equ $0100000C	; Sanity check on memory list failed
                ; during AvailMem(MEMF_LARGEST)
AN_IOAfterClose	equ $0100000D	; IO attempted on closed IORequest
AN_StackProbe	equ $0100000E	; Stack appears to extend out of range
AN_BadFreeAddr	equ $0100000F	; Memory header not located. [ Usually an
                ; invalid address passed to FreeMem() ]

;------ graphics.library
AN_GraphicsLib	equ $02000000
AN_GfxNoMem	equ $82010000	; graphics out of memory
AN_GfxNoMemMspc equ $82010001	; MonitorSpec alloc, no memory
AN_LongFrame	equ $82010006	; long frame, no memory
AN_ShortFrame	equ $82010007	; short frame, no memory
AN_TextTmpRas	equ $02010009	; text, no memory for TmpRas
AN_BltBitMap	equ $8201000A	; BltBitMap, no memory
AN_RegionMemory	equ $8201000B	; regions, memory not available
AN_MakeVPort	equ $82010030	; MakeVPort, no memory
AN_GfxNewError	equ $0200000C
AN_GfxFreeError equ $0200000D

AN_GfxNoLCM	equ $82011234	; emergency memory not available

AN_ObsoleteFont	equ $02000401	; unsupported font description used

;------ layers.library
AN_LayersLib	equ $03000000
AN_LayersNoMem	equ $83010000	; layers out of memory

;------ intuition.library
AN_Intuition	equ $04000000
AN_GadgetType	equ $84000001	; unknown gadget type
AN_BadGadget	equ $04000001	; Recovery form of AN_GadgetType
AN_CreatePort	equ $84010002	; create port, no memory
AN_ItemAlloc	equ $04010003	; item plane alloc, no memory
AN_SubAlloc	equ $04010004	; sub alloc, no memory
AN_PlaneAlloc	equ $84010005	; plane alloc, no memory
AN_ItemBoxTop	equ $84000006	; item box top < RelZero
AN_OpenScreen	equ $84010007	; open screen, no memory
AN_OpenScrnRast	equ $84010008	; open screen, raster alloc, no memory
AN_SysScrnType	equ $84000009	; open sys screen, unknown type
AN_AddSWGadget	equ $8401000A	; add SW gadgets, no memory
AN_OpenWindow	equ $8401000B	; open window, no memory
AN_BadState	equ $8400000C	; Bad State Return entering Intuition
AN_BadMessage	equ $8400000D	; Bad Message received by IDCMP
AN_WeirdEcho	equ $8400000E	; Weird echo causing incomprehension
AN_NoConsole	equ $8400000F	; couldn't open the Console Device

;------ math.library
AN_MathLib	equ $05000000

;------ dos.library
AN_DOSLib	equ $07000000
AN_StartMem	equ $07010001	; no memory at startup
AN_EndTask	equ $07000002	; EndTask didn't
AN_QPktFail	equ $07000003	; Qpkt failure
AN_AsyncPkt	equ $07000004	; Unexpected packet received
AN_FreeVec	equ $07000005	; Freevec failed
AN_DiskBlkSeq	equ $07000006	; Disk block sequence error
AN_BitMap	equ $07000007	; Bitmap corrupt
AN_KeyFree	equ $07000008	; Key already free
AN_BadChkSum	equ $07000009	; Invalid checksum
AN_DiskError	equ $0700000A	; Disk Error
AN_KeyRange	equ $0700000B	; Key out of range
AN_BadOverlay	equ $0700000C	; Bad overlay
AN_BadInitFunc	equ $0700000D	; Invalid init packet for cli/shell
AN_FileReclosed equ $0700000E	; A filehandle was closed more than once

;------ ramlib.library
AN_RAMLib	equ $08000000
AN_BadSegList	equ $08000001	; overlays are illegal for library segments

;------ icon.library
AN_IconLib	equ $09000000

;------ expansion.library
AN_ExpansionLib	equ $0A000000
AN_BadExpansionFree	equ $0A000001	;Freeed free region

;------ diskfont.library
AN_DiskfontLib	equ $0B000000

;------ audio.device
AN_AudioDev	equ $10000000

;------ console.device
AN_ConsoleDev	equ $11000000
AN_NoWindow	equ $11000001	; Console can't open initial window

;------ gameport.device
AN_GamePortDev	equ $12000000

;------ keyboard.device
AN_KeyboardDev	equ $13000000

;------ trackdisk.device
AN_TrackDiskDev equ $14000000
AN_TDCalibSeek	equ $14000001	; calibrate: seek error
AN_TDDelay	equ $14000002	; delay: error on timer wait

;------	timer.device
AN_TimerDev	equ $15000000
AN_TMBadReq	equ $15000001	; bad request
AN_TMBadSupply	equ $15000002	; power supply -- no 50/60hz ticks

;------ cia.resource
AN_CIARsrc	equ $20000000

;------	disk.resource
AN_DiskRsrc 	equ $21000000
AN_DRHasDisk	equ $21000001	; get unit: already has disk
AN_DRIntNoAct	equ $21000002	; interrupt: no active unit

;------ misc.resource
AN_MiscRsrc	equ $22000000

;------ bootstrap
AN_BootStrap    equ $30000000
AN_BootError	equ $30000001	; boot code returned an error

;------ workbench
AN_Workbench			equ $31000000
AN_NoFonts			equ $B1000001
AN_WBBadStartupMsg1		equ $31000001
AN_WBBadStartupMsg2		equ $31000002
AN_WBBadIOMsg			equ $31000003

AN_WBInitPotionAllocDrawer	equ $B1010004
AN_WBCreateWBMenusCreateMenus1	equ $B1010005
AN_WBCreateWBMenusCreateMenus2	equ $B1010006
AN_WBLayoutWBMenusLayoutMenus	equ $B1010007
AN_WBAddToolMenuItem		equ $B1010008
AN_WBReLayoutToolMenu		equ $B1010009
AN_WBinitTimer			equ $B101000A
AN_WBInitLayerDemon		equ $B101000B
AN_WBinitWbGels			equ $B101000C
AN_WBInitScreenAndWindows1	equ $B101000D
AN_WBInitScreenAndWindows2	equ $B101000E
AN_WBInitScreenAndWindows3	equ $B101000F
AN_WBMAlloc			equ $B1010010

;------ DiskCopy
AN_DiskCopy	equ $32000000

;------ toolkit for Intuition
AN_GadTools	equ $33000000

;------ System utility library
AN_UtilityLib	equ $34000000

;------ For use by any application that needs it
AN_Unknown	equ $35000000

    ENDC ;EXEC_ALERTS_I


Includes/exec/initializers.h

#ifndef	EXEC_INITIALIZERS_H
#define	EXEC_INITIALIZERS_H
/*
**	$Filename: exec/initializers.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.5 $
**	$Date: 90/05/10 $
**
**	Macros for use with the InitStruct() function.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#define	OFFSET(structName, structEntry) \
                (&(((struct structName *) 0)->structEntry))
#define	INITBYTE(offset,value)	0xe000,(UWORD) (offset),(UWORD) ((value)<<8)
#define	INITWORD(offset,value)	0xd000,(UWORD) (offset),(UWORD) (value)
#define	INITLONG(offset,value)	0xc000,(UWORD) (offset), \
                (UWORD) ((value)>>16), \
                (UWORD) ((value) & 0xffff)
#define	INITSTRUCT(size,offset,value,count) \
                (UWORD) (0xc000|(size<<12)|(count<<8)| \
                ((UWORD) ((offset)>>16)), \
                ((UWORD) (offset)) & 0xffff)
#endif /* EXEC_INITIALIZERS_H */


Includes/exec/macros.i

    IFND	EXEC_MACROS_I
EXEC_MACROS_I	 SET	 1
**
**	$Filename: exec/macros.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.8 $
**	$Date: 90/11/01 $
**
**	Handy macros for assembly language programmers.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

        IFND	DEBUG_DETAIL
DEBUG_DETAIL	SET	0	;Detail level of debugging.  Zero for none.
        ENDC

JSRLIB		MACRO	;FunctionName
        XREF	_LVO\1
        jsr	_LVO\1(a6)
        ENDM

JMPLIB		MACRO	;FunctionName
        XREF	_LVO\1
        jmp	_LVO\1(a6)
        ENDM

BSRSELF	MACRO
        XREF	\1
        bsr	\1
        ENDM

BRASELF	MACRO
        XREF	\1
        bra	\1
        ENDM

BLINK		MACRO
        IFNE	DEBUG_DETAIL
          bchg.b #1,$bfe001  ;Toggle the power LED
        ENDC
        ENDM

TRIGGER		MACRO	;<level> Trigger a hardware state analyzer
        IFGE	DEBUG_DETAIL-\1
          move.w #$5555,$2fe
        ENDC
        ENDM

CLEAR		MACRO
        moveq.l #0,\1
        ENDM

CLEARA		MACRO
        suba.l	\1,\1	;Quick way to put zero in an address register
        ENDM

*************************************************************************
        IFND	PRINTF
PRINTF		MACRO	; level,<string>,...
        IFGE	DEBUG_DETAIL-\1
        XREF	kprint_macro
PUSHCOUNT	SET	0

        IFNC	'\9',''
        move.l	\9,-(sp)
PUSHCOUNT	SET	PUSHCOUNT+4
        ENDC

        IFNC	'\8',''
        move.l	\8,-(sp)
PUSHCOUNT	SET	PUSHCOUNT+4
        ENDC

        IFNC	'\7',''
        move.l	\7,-(sp)
PUSHCOUNT	SET	PUSHCOUNT+4
        ENDC

        IFNC	'\6',''
        move.l	\6,-(sp)
PUSHCOUNT	SET	PUSHCOUNT+4
        ENDC

        IFNC	'\5',''
        move.l	\5,-(sp)
PUSHCOUNT	SET	PUSHCOUNT+4
        ENDC

        IFNC	'\4',''
        move.l	\4,-(sp)
PUSHCOUNT	SET	PUSHCOUNT+4
        ENDC

        IFNC	'\3',''
        move.l	\3,-(sp)
PUSHCOUNT	SET	PUSHCOUNT+4
        ENDC

        movem.l a0/a1,-(sp)
        lea.l	PSS\@(pc),A0
        lea.l	4*2(SP),A1
        BSR	kprint_macro
        movem.l (sp)+,a0/a1
        bra.s	PSE\@

PSS\@		dc.b	\2
        IFEQ	(\1&1)	;If even, add CR/LF par...
           dc.b 13,10
        ENDC
        dc.b	0
        ds.w	0
PSE\@
        lea.l	PUSHCOUNT(sp),sp
        ENDC	;IFGE	DEBUG_DETAIL-\1
        ENDM	;PRINTF	MACRO
        ENDC	;IFND	PRINTF

;----------------------------------------------------------------------------
;Push a set of registers onto the stack - undo with POPM.  This prevents
;the need to update or synchronize two MOVEM instructions.  These macros
;assume an optimizing assembler that will convert single register  MOVEM
;to MOVE.  Because the REG assignment can't be reset, these macros do
;not nest.
;
;	    PUSHM   d2/a2/a5
;	    ...code...
;	    POPM
;	    RTS
;
PUSHM_COUNT			SET	0
PUSHM				MACRO
                IFGT	NARG-1
                FAIL	!!!! TOO MANY ARGUMENTS TO PUSHM !!!!
                ENDC
PUSHM_COUNT			SET	PUSHM_COUNT+1
PUSHM_\*VALOF(PUSHM_COUNT)      REG     \1
                movem.l PUSHM_\*VALOF(PUSHM_COUNT),-(sp)
                ENDM

;
;Undo most recent PUSHM.  'POPM NOBUMP' allows multiple exit points.
;
POPM				MACRO
                movem.l (sp)+,PUSHM_\*VALOF(PUSHM_COUNT)
                IFNC	'\1','NOBUMP'
PUSHM_COUNT			SET	PUSHM_COUNT+1	;error if re-used
                ENDC
                ENDM
;----------------------------------------------------------------------------

    ENDC	; EXEC_MACROS_I


Includes/exec/semaphores.i

    IFND	EXEC_SEMAPHORES_I
EXEC_SEMAPHORES_I	SET	1
**
**	$Filename: exec/semaphores.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.6 $
**	$Date: 90/05/10 $
**
**	Definitions for locking functions.
**
**	(C) Copyright 1986-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND EXEC_NODES_I
    INCLUDE "exec/nodes.i"
    ENDC	; EXEC_NODES_I

    IFND EXEC_LISTS_I
    INCLUDE "exec/lists.i"
    ENDC	; EXEC_LISTS_I

    IFND EXEC_PORTS_I
    INCLUDE "exec/ports.i"
    ENDC	; EXEC_PORTS_I

*----------------------------------------------------------------
*
*   Signal Semaphore Structure
*
*----------------------------------------------------------------

** Private structure used by ObtainSemaphore()
 STRUCTURE  SSR,MLN_SIZE
    APTR    SSR_WAITER
    LABEL   SSR_SIZE

** Signal Semaphore data structure
 STRUCTURE  SS,LN_SIZE
    WORD    SS_NESTCOUNT
    STRUCT  SS_WAITQUEUE,MLH_SIZE
    STRUCT  SS_MULTIPLELINK,SSR_SIZE
    APTR    SS_OWNER
    WORD    SS_QUEUECOUNT
    LABEL   SS_SIZE

*----------------------------------------------------------------
*
*   Semaphore Structure (Procure/Vacate type)
*
*----------------------------------------------------------------

 STRUCTURE  SM,MP_SIZE
    WORD    SM_BIDS	      ; number of bids for lock
    LABEL   SM_SIZE

*------ unions:

SM_LOCKMSG    EQU  MP_SIGTASK

    ENDC	; EXEC_SEMAPHORES_I


Includes/exec/devices.h

#ifndef	EXEC_DEVICES_H
#define	EXEC_DEVICES_H
/*
**	$Filename: exec/devices.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.5 $
**	$Date: 90/05/10 $
**
**	Include file for use by Exec device drivers
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_LIBRARIES_H
#include "exec/libraries.h"
#endif /* EXEC_LIBRARIES_H */

#ifndef EXEC_PORTS_H
#include "exec/ports.h"
#endif /* EXEC_PORTS_H */

/****** Device ******************************************************/

struct Device {
    struct  Library dd_Library;
};

/****** Unit ********************************************************/

struct Unit {
    struct  MsgPort unit_MsgPort;	/* queue for unprocessed messages */
                    /* instance of msgport is recommended */
    UBYTE   unit_flags;
    UBYTE   unit_pad;
    UWORD   unit_OpenCnt;		/* number of active opens */
};

#define UNITF_ACTIVE	(1<<0)
#define UNITF_INTASK	(1<<1)

#endif	/* EXEC_DEVICES_H */


Includes/exec/initializers.i

    IFND	EXEC_INITIALIZERS_I
EXEC_INITIALIZERS_I	SET	1
**
**	$Filename: exec/initializers.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.5 $
**	$Date: 90/05/10 $
**
**	Macros for creating InitStruct() tables
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

INITBYTE	MACRO	; &offset,&value
        IFLE	(\1)-255	;If offset <=255
        DC.B	$a0,\1		;use byte offset
        DC.B	\2,0
        MEXIT			;exit early
        ENDC
        DC.B	$e0,0
        DC.W	\1
        DC.B	\2,0
        ENDM

INITWORD	MACRO	; &offset,&value
        IFLE	(\1)-255	;If offset <=255
        DC.B	$90,\1		;use byte offset
        DC.W	\2
        MEXIT			;exit early
        ENDC
        DC.B	$d0,0
        DC.W	\1
        DC.W	\2
        ENDM

INITLONG	MACRO	; &offset,&value
        IFLE	(\1)-255	;If offset <=255
        DC.B	$80,\1		;use byte offset
        DC.L	\2
        MEXIT			;exit early
        ENDC
        DC.B	$c0,0
        DC.W	\1
        DC.L	\2
        ENDM

;size=source size 0=long, 1=word, 2=byte, 3=illegal.
;offset=offset from memory base to put data
;value=unused
;count=number of source items to copy, minus one
;follow this macro with the proper sized data (dc.b,dc.w,dc.l,etc.)
INITSTRUCT	MACRO	; &size,&offset,&value,&count
        DS.W	0
        IFC	'\4',''
COUNT\@	SET	0
        ENDC
        IFNC	'\4',''
COUNT\@	SET	\4
        ENDC
CMD\@		SET	(((\1)<<4)!COUNT\@)
        IFLE	(\2)-255	;byte offset large enough?
        DC.B	(CMD\@)!$80
        DC.B	\2
        MEXIT
        ENDC
        DC.B	CMD\@!$0C0	;byte too small, use 24-bit offset.
        DC.B	(((\2)>>16)&$0FF)
        DC.W	((\2)&$0FFFF)
        ENDM

    ENDC	; EXEC_INITIALIZERS_I


Includes/exec/memory.h

#ifndef	EXEC_MEMORY_H
#define	EXEC_MEMORY_H
/*
**	$Filename: exec/memory.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.12 $
**	$Date: 91/03/15 $
**
**	Definitions and structures used by the memory allocation system
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_NODES_H
#include "exec/nodes.h"
#endif /* EXEC_NODES_H */

/****** MemChunk ****************************************************/

struct	MemChunk {
    struct  MemChunk *mc_Next;	/* pointer to next chunk */
    ULONG   mc_Bytes;		/* chunk byte size	*/
};

/****** MemHeader ***************************************************/

struct	MemHeader {
    struct  Node mh_Node;
    UWORD   mh_Attributes;	/* characteristics of this region */
    struct  MemChunk *mh_First; /* first free region		*/
    APTR    mh_Lower;		/* lower memory bound		*/
    APTR    mh_Upper;		/* upper memory bound+1	*/
    ULONG   mh_Free;		/* total number of free bytes	*/
};

/****** MemEntry ****************************************************/

struct	MemEntry {
union {
    ULONG   meu_Reqs;		/* the AllocMem requirements */
    APTR    meu_Addr;		/* the address of this memory region */
    } me_Un;
    ULONG   me_Length;		/* the length of this memory region */
};

#define me_un	    me_Un	/* compatibility - do not use*/
#define me_Reqs     me_Un.meu_Reqs
#define me_Addr     me_Un.meu_Addr

/****** MemList *****************************************************/

/* Note: sizeof(struct MemList) includes the size of the first MemEntry! */
struct	MemList {
    struct  Node ml_Node;
    UWORD   ml_NumEntries;	/* number of entries in this struct */
    struct  MemEntry ml_ME[1];	/* the first entry	*/
};

#define ml_me	ml_ME		/* compatability - do not use */

/*----- Memory Requirement Types ---------------------------*/
/*----- See the AllocMem() documentation for details--------*/

#define MEMF_ANY    (0L)	/* Any type of memory will do */
#define MEMF_PUBLIC (1L<<0)
#define MEMF_CHIP   (1L<<1)
#define MEMF_FAST   (1L<<2)
#define MEMF_LOCAL  (1L<<8)	/* Memory that does not go away at RESET */
#define MEMF_24BITDMA (1L<<9)	/* DMAable memory within 24 bits of address */

#define MEMF_CLEAR   (1L<<16)	/* AllocMem: NULL out area before return */
#define MEMF_LARGEST (1L<<17)	/* AvailMem: return the largest chunk size */
#define MEMF_REVERSE (1L<<18)	/* AllocMem: allocate from the top down */
#define MEMF_TOTAL   (1L<<19)	/* AvailMem: return total size of memory */

/*----- Current alignment rules for memory blocks (may increase) -----*/
#define MEM_BLOCKSIZE	8L
#define MEM_BLOCKMASK	(MEM_BLOCKSIZE-1)

#endif	/* EXEC_MEMORY_H */


Includes/exec/strings.i

    IFND	EXEC_STRINGS_I
EXEC_STRINGS_I	SET	1
**
**	$Filename: exec/strings.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.5 $
**	$Date: 90/05/10 $
**
**	Macros for defining old style CR/LF terminated string constants
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

*------ Terminal Control:

EOS	EQU 0
BELL	EQU 7
LF	EQU 10
CR	EQU 13
BS	EQU 8
DEL	EQU $7F
NL	EQU LF

*----------------------------------------------------------------
*
*   String Support Macros
*
*----------------------------------------------------------------

STRING	MACRO
    dc.b	\1
    dc.b	0
    CNOP	0,2
    ENDM

STRINGL MACRO
    dc.b	13,10
    dc.b	\1
    dc.b	0
    CNOP	0,2
    ENDM

STRINGR MACRO
    dc.b	\1
    dc.b	13,10,0
    CNOP	0,2
    ENDM

STRINGLR MACRO
    dc.b	13,10
    dc.b	\1
    dc.b	13,10,0
    CNOP	0,2
    ENDM

    ENDC	; EXEC_STRINGS_I


Includes/exec/devices.i

    IFND	EXEC_DEVICES_I
EXEC_DEVICES_I	SET	1
**
**	$Filename: exec/devices.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.4 $
**	$Date: 90/05/10 $
**
**	Include file for use by Exec device drivers
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND EXEC_LIBRARIES_I
    INCLUDE "exec/libraries.i"
    ENDC	; EXEC_LIBRARIES_I

    IFND EXEC_PORTS_I
    INCLUDE "exec/ports.i"
    ENDC	; EXEC_PORTS_I

*----------------------------------------------------------------
*
*   Device Data Structure
*
*----------------------------------------------------------------

 STRUCTURE  DD,LIB_SIZE
    LABEL   DD_SIZE			; identical to library

*----------------------------------------------------------------
*
*   Suggested Unit Structure
*
*----------------------------------------------------------------

 STRUCTURE  UNIT,MP_SIZE		; queue for requests
    UBYTE   UNIT_FLAGS
    UBYTE   UNIT_pad
    UWORD   UNIT_OPENCNT
    LABEL   UNIT_SIZE

*------ UNIT_FLAG definitions:

    BITDEF  UNIT,ACTIVE,0		; driver is active
    BITDEF  UNIT,INTASK,1		; running in driver's task

    ENDC	; EXEC_DEVICES_I


Includes/exec/interrupts.h

#ifndef	EXEC_INTERRUPTS_H
#define	EXEC_INTERRUPTS_H
/*
**	$Filename: exec/interrupts.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.4 $
**	$Date: 90/05/10 $
**
**	Callback structures used by hardware & software interrupts
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_NODES_H
#include "exec/nodes.h"
#endif /* EXEC_NODES_H */

#ifndef EXEC_LISTS_H
#include "exec/lists.h"
#endif /* EXEC_LISTS_H */

struct Interrupt {
    struct  Node is_Node;
    APTR    is_Data;		    /* server data segment  */
    VOID    (*is_Code)();	    /* server code entry    */
};

struct IntVector {		/* For EXEC use ONLY! */
    APTR    iv_Data;
    VOID    (*iv_Code)();
    struct  Node *iv_Node;
};

struct SoftIntList {		/* For EXEC use ONLY! */
    struct List sh_List;
    UWORD  sh_Pad;
};

#define SIH_PRIMASK (0xf0)

/* this is a fake INT definition, used only for AddIntServer and the like */
#define INTB_NMI	15
#define INTF_NMI	(1<<15)

#endif	/* EXEC_INTERRUPTS_H */


Includes/exec/memory.i

    IFND	EXEC_MEMORY_I
EXEC_MEMORY_I	SET	1
**
**	$Filename: exec/memory.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.11 $
**	$Date: 91/03/15 $
**
**	Definitions and structures used by the memory allocation system
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND EXEC_NODES_I
    INCLUDE "exec/nodes.i"
    ENDC	; EXEC_NODES_I

*---------------------------------------------------------------------
*
*   Memory List Structures
*
*---------------------------------------------------------------------
*
*   A memory list appears in two forms:  One is a requirements list
*   the other is a list of already allocated memory.  The format is
*   the same, with the reqirements/address field occupying the same
*   position.
*
*   The format is a linked list of ML structures each of which has
*   an array of ME entries.
*
*---------------------------------------------------------------------

 STRUCTURE ML,LN_SIZE
    UWORD   ML_NUMENTRIES	    ; The number of ME structures that follow
    LABEL   ML_ME		    ; where the ME structures begin
    LABEL   ML_SIZE	;Note: does NOT include any "ME" structures.

 STRUCTURE ME,0
    LABEL   ME_REQS		    ; the AllocMem requirements
    APTR    ME_ADDR		    ; the address of this block (an alias
                    ;	for the same location as ME_REQS)
    ULONG   ME_LENGTH		    ; the length of this region
    LABEL   ME_SIZE

*------ memory options:
*------ see the AllocMem() documentation for details------*

MEMF_ANY	EQU 0		;Any type of memory will do
    BITDEF  MEM,PUBLIC,0
    BITDEF  MEM,CHIP,1
    BITDEF  MEM,FAST,2
    BITDEF  MEM,LOCAL,8		;Memory that does not go away at RESET
    BITDEF  MEM,24BITDMA,9	;DMAable memory within 24 bits of address

    BITDEF  MEM,CLEAR,16	;AllocMem: NULL out area before return
    BITDEF  MEM,LARGEST,17	;AvailMem: return the largest chunk size
    BITDEF  MEM,REVERSE,18	;AllocMem: allocate from the top down
    BITDEF  MEM,TOTAL,19	;AvailMem: return total size of memory

*----- Current alignment rules for memory blocks (may increase) -----
MEM_BLOCKSIZE	EQU 8
MEM_BLOCKMASK	EQU (MEM_BLOCKSIZE-1)

*---------------------------------------------------------------------
*
*   Memory Region Header
*
*---------------------------------------------------------------------

 STRUCTURE  MH,LN_SIZE		    ; (LN_TYPE will be set to NT_MEMORY)
    UWORD   MH_ATTRIBUTES	    ; characteristics of this region
    APTR    MH_FIRST		    ; first free region
    APTR    MH_LOWER		    ; lower memory bound
    APTR    MH_UPPER		    ; upper memory bound+1
    ULONG   MH_FREE		    ; number of free bytes
    LABEL   MH_SIZE

*---------------------------------------------------------------------
*
*   Memory Chunk
*
*---------------------------------------------------------------------

 STRUCTURE  MC,0
    APTR    MC_NEXT		    ; ptr to next chunk
    ULONG   MC_BYTES		    ; chunk byte size
    APTR    MC_SIZE

    ENDC	; EXEC_MEMORY_I


Includes/exec/tasks.h

#ifndef	EXEC_TASKS_H
#define	EXEC_TASKS_H
/*
**	$Filename: exec/tasks.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.9 $
**	$Date: 91/11/06 $
**
**	Task Control Block, Singals, and Task flags.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_NODES_H
#include "exec/nodes.h"
#endif /* EXEC_NODES_H */

#ifndef EXEC_LISTS_H
#include "exec/lists.h"
#endif /* EXEC_LISTS_H */

/* Please use Exec functions to modify task structure fields, where available.
 */
struct Task {
    struct  Node tc_Node;
    UBYTE   tc_Flags;
    UBYTE   tc_State;
    BYTE    tc_IDNestCnt;	    /* intr disabled nesting*/
    BYTE    tc_TDNestCnt;	    /* task disabled nesting*/
    ULONG   tc_SigAlloc;	    /* sigs allocated */
    ULONG   tc_SigWait;	    /* sigs we are waiting for */
    ULONG   tc_SigRecvd;	    /* sigs we have received */
    ULONG   tc_SigExcept;	    /* sigs we will take excepts for */
    UWORD   tc_TrapAlloc;	    /* traps allocated */
    UWORD   tc_TrapAble;	    /* traps enabled */
    APTR    tc_ExceptData;	    /* points to except data */
    APTR    tc_ExceptCode;	    /* points to except code */
    APTR    tc_TrapData;	    /* points to trap code */
    APTR    tc_TrapCode;	    /* points to trap data */
    APTR    tc_SPReg;		    /* stack pointer	    */
    APTR    tc_SPLower;	    /* stack lower bound    */
    APTR    tc_SPUpper;	    /* stack upper bound + 2*/
    VOID    (*tc_Switch)();	    /* task losing CPU	  */
    VOID    (*tc_Launch)();	    /* task getting CPU  */
    struct  List tc_MemEntry;	    /* Allocated memory. Freed by RemTask() */
    APTR    tc_UserData;	    /* For use by the task; no restrictions! */
};

/*
 * Stack swap structure as passed to StackSwap()
 */
struct	StackSwapStruct {
    APTR	stk_Lower;	/* Lowest byte of stack */
    ULONG	stk_Upper;	/* Upper end of stack (size + Lowest) */
    APTR	stk_Pointer;	/* Stack pointer at switch point */
};

/*----- Flag Bits ------------------------------------------*/
#define TB_PROCTIME	0
#define TB_ETASK	3
#define TB_STACKCHK	4
#define TB_EXCEPT	5
#define TB_SWITCH	6
#define TB_LAUNCH	7

#define TF_PROCTIME	(1<<0)
#define TF_ETASK	(1<<3)
#define TF_STACKCHK	(1<<4)
#define TF_EXCEPT	(1<<5)
#define TF_SWITCH	(1<<6)
#define TF_LAUNCH	(1<<7)

/*----- Task States ----------------------------------------*/
#define TS_INVALID	0
#define TS_ADDED	1
#define TS_RUN		2
#define TS_READY	3
#define TS_WAIT	4
#define TS_EXCEPT	5
#define TS_REMOVED	6

/*----- Predefined Signals -------------------------------------*/
#define SIGB_ABORT	0
#define SIGB_CHILD	1
#define SIGB_BLIT	4	/* Note: same as SINGLE */
#define SIGB_SINGLE	4	/* Note: same as BLIT */
#define SIGB_INTUITION	5
#define SIGB_DOS	8

#define SIGF_ABORT	(1L<<0)
#define SIGF_CHILD	(1L<<1)
#define SIGF_BLIT	(1L<<4)
#define SIGF_SINGLE	(1L<<4)
#define SIGF_INTUITION	(1L<<5)
#define SIGF_DOS	(1L<<8)

#endif	/* EXEC_TASKS_H */


Includes/exec/errors.h

#ifndef	EXEC_ERRORS_H
#define	EXEC_ERRORS_H
/*
**	$Filename: exec/errors.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.6 $
**	$Date: 90/05/27 $
**
**	Standard Device IO Errors (returned in io_Error)
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#define IOERR_OPENFAIL	 (-1) /* device/unit failed to open */
#define IOERR_ABORTED	 (-2) /* request terminated early [after AbortIO()] */
#define IOERR_NOCMD	 (-3) /* command not supported by device */
#define IOERR_BADLENGTH	 (-4) /* not a valid length (usually IO_LENGTH) */
#define IOERR_BADADDRESS (-5) /* invalid address (misaligned or bad range) */
#define IOERR_UNITBUSY	 (-6) /* device opens ok, but requested unit is busy */
#define IOERR_SELFTEST	 (-7) /* hardware failed self-test */

#endif	/* EXEC_ERRORS_H */


Includes/exec/interrupts.i

    IFND	EXEC_INTERRUPTS_I
EXEC_INTERRUPTS_I	SET	1
**
**	$Filename: exec/interrupts.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.5 $
**	$Date: 90/05/10 $
**
**	Callback structures used by hardware & software interrupts
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND EXEC_NODES_I
    INCLUDE "exec/nodes.i"
    ENDC	; EXEC_NODES_I

    IFND EXEC_LISTS_I
    INCLUDE "exec/lists.i"
    ENDC	; EXEC_LISTS_I

*----------------------------------------------------------------
*
*   Interrupt Structure
*
*----------------------------------------------------------------

 STRUCTURE  IS,LN_SIZE
    APTR    IS_DATA
    APTR    IS_CODE
    LABEL   IS_SIZE

*---------------------------------------------------------------------
*
*   Exec Internal Interrupt Vectors
*
*---------------------------------------------------------------------

 STRUCTURE  IV,0
    APTR    IV_DATA
    APTR    IV_CODE
    APTR    IV_NODE
    LABEL   IV_SIZE

*------ System Flag bits (in SysBase.SysFlags )

    BITDEF  S,SAR,15	    ; scheduling attention required (TOP BIT)
    BITDEF  S,TQE,14	    ; time quantum expended -- time to resched
    BITDEF  S,SINT,13

*---------------------------------------------------------------------
*
*   Software Interrupt List Headers
*
*---------------------------------------------------------------------

 STRUCTURE  SH,LH_SIZE
    UWORD   SH_PAD
    LABEL   SH_SIZE

SIH_PRIMASK  EQU	$0F0
SIH_QUEUES   EQU	5

** this is a fake INT definition, used only for AddIntServer and the like
    BITDEF	INT,NMI,15

    ENDC	; EXEC_INTERRUPTS_I


Includes/exec/nodes.h

#ifndef	EXEC_NODES_H
#define	EXEC_NODES_H
/*
**	$Filename: exec/nodes.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.11 $
**	$Date: 91/01/09 $
**
**	Nodes & Node type identifiers.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include "exec/types.h"
#endif /* EXEC_TYPES_H */

/*
 *  List Node Structure.  Each member in a list starts with a Node
 */

struct Node {
    struct  Node *ln_Succ;	/* Pointer to next (successor) */
    struct  Node *ln_Pred;	/* Pointer to previous (predecessor) */
    UBYTE   ln_Type;
    BYTE    ln_Pri;		/* Priority, for sorting */
    char    *ln_Name;		/* ID string, null terminated */
};	/* Note: word aligned */

/* minimal node -- no type checking possible */
struct MinNode {
    struct MinNode *mln_Succ;
    struct MinNode *mln_Pred;
};

/*
** Note: Newly initialized IORequests, and software interrupt structures
** used with Cause(), should have type NT_UNKNOWN.  The OS will assign a type
** when they are first used.
*/
/*----- Node Types for LN_TYPE -----*/
#define NT_UNKNOWN	0
#define NT_TASK		1	/* Exec task */
#define NT_INTERRUPT	2
#define NT_DEVICE	3
#define NT_MSGPORT	4
#define NT_MESSAGE	5	/* Indicates message currently pending */
#define NT_FREEMSG	6
#define NT_REPLYMSG	7	/* Message has been replied */
#define NT_RESOURCE	8
#define NT_LIBRARY	9
#define NT_MEMORY	10
#define NT_SOFTINT	11	/* Internal flag used by SoftInits */
#define NT_FONT		12
#define NT_PROCESS	13	/* AmigaDOS Process */
#define NT_SEMAPHORE	14
#define NT_SIGNALSEM	15	/* signal semaphores */
#define NT_BOOTNODE	16
#define NT_KICKMEM	17
#define NT_GRAPHICS	18
#define NT_DEATHMESSAGE	19

#define NT_USER		254	/* User node types work down from here */
#define NT_EXTENDED	255

#endif	/* EXEC_NODES_H */


Includes/exec/tasks.i

    IFND	EXEC_TASKS_I
EXEC_TASKS_I	SET	1
**
**	$Filename: exec/tasks.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.8 $
**	$Date: 90/10/22 $
**
**	Task Control Block, Signals, and Task flags.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND EXEC_NODES_I
    INCLUDE "exec/nodes.i"
    ENDC	; EXEC_NODES_I

    IFND EXEC_LISTS_I
    INCLUDE "exec/lists.i"
    ENDC	; EXEC_LISTS_I

    IFND EXEC_PORTS_I
    INCLUDE "exec/ports.i"
    ENDC	; EXEC_PORTS_I

*----------------------------------------------------------------
*
*	Task Control Structure
*
*	Please use Exec functions to modify task structure fields,
*	where available.
*
*----------------------------------------------------------------

 STRUCTURE  TC_Struct,LN_SIZE	    ; was "TC"
    UBYTE   TC_FLAGS
    UBYTE   TC_STATE
    BYTE    TC_IDNESTCNT	    ; intr disabled nesting
    BYTE    TC_TDNESTCNT	    ; task disabled nesting
    ULONG   TC_SIGALLOC	    ; sigs allocated
    ULONG   TC_SIGWAIT		    ; sigs we are waiting for
    ULONG   TC_SIGRECVD	    ; sigs we have received
    ULONG   TC_SIGEXCEPT	    ; sigs we take as exceptions
    ;* Pointer to an extended task structure.  This structure is allocated
    ;* by V36 Exec if the proper flags in tc_ETaskFlags are set.  This
    ;* field was formerly defined as:
    ;*		UWORD	TC_TRAPALLOC	    ; traps allocated
    ;*		UWORD	TC_TRAPABLE	    ; traps enabled
    ;* Please see the Exec AllocTrap() and FreeTrap() calls.
    ;*
    APTR    tc_ETask		    ; pointer to extended task structure
    APTR    TC_EXCEPTDATA	    ; data for except proc
    APTR    TC_EXCEPTCODE	    ; exception procedure
    APTR    TC_TRAPDATA	    ; data for proc trap proc
    APTR    TC_TRAPCODE	    ; proc trap procedure
    APTR    TC_SPREG		    ; stack pointer
    APTR    TC_SPLOWER		    ; stack lower bound
    APTR    TC_SPUPPER		    ; stack upper bound + 2
    FPTR    TC_SWITCH		    ; task losing CPU (function pointer)
    FPTR    TC_LAUNCH		    ; task getting CPU (function pointer)
    STRUCT  TC_MEMENTRY,LH_SIZE     ; Allocated memory list.  Freed by RemTask()
    APTR    TC_Userdata		    ; For use by the task; no restrictions!
    LABEL   TC_SIZE

;Don't even _think_ about allocating one of these yourself.
 STRUCTURE	ETask,MN_SIZE
        APTR	et_Parent		;Pointer to task (TC)
        ULONG	et_UniqueID		;ID unique to this task
        STRUCT	et_Children,MLH_SIZE	;List of children
        UWORD	et_TRAPALLOC
        UWORD	et_TRAPABLE
        ULONG	et_Result1		;First result
        APTR	et_Result2		;Result data pointer (AllocVec)
        STRUCT	et_TaskMsgPort,MP_SIZE
        LABEL	ETask_SIZEOF	;_never_ depend on this size!

CHILD_NOTNEW	EQU	1	;function not called from a new style task
CHILD_NOTFOUND	EQU	2	;child not found
CHILD_EXITED	EQU	3	;child has exited
CHILD_ACTIVE	EQU	4	;child has exited

;Stack swap structure as passed to StackSwap()
;
 STRUCTURE	StackSwapStruct,0
        APTR	stk_Lower	;Lowest byte of stack
        ULONG	stk_Upper	;Upper end of stack (size + Lowest)
        APTR	stk_Pointer	;Stack pointer at switch point
        LABEL	StackSwapStruct_SIZEOF

;------ TC_FLAGS Bits:

    BITDEF  T,PROCTIME,0
    BITDEF  T,ETASK,3
    BITDEF  T,STACKCHK,4
    BITDEF  T,EXCEPT,5
    BITDEF  T,SWITCH,6		;Enable TC_SWITCH point
    BITDEF  T,LAUNCH,7		;Enable TC_LAUNCH point

;------ Task States:

TS_INVALID  EQU     0
TS_ADDED    EQU     TS_INVALID+1
TS_RUN	    EQU     TS_ADDED+1
TS_READY    EQU     TS_RUN+1
TS_WAIT     EQU     TS_READY+1
TS_EXCEPT   EQU     TS_WAIT+1
TS_REMOVED  EQU     TS_EXCEPT+1

;------ System Task Signals:

    BITDEF	SIG,ABORT,0
    BITDEF	SIG,CHILD,1
    BITDEF	SIG,BLIT,4	; Note: same as SINGLE
    BITDEF	SIG,SINGLE,4	; "single-threaded".  Note: same as BLIT
    BITDEF	SIG,INTUITION,5
    BITDEF	SIG,DOS,8

SYS_SIGALLOC	EQU	$0FFFF		; pre-allocated signals
SYS_TRAPALLOC	EQU	$08000		; pre-allocated traps

    ENDC	; EXEC_TASKS_I


Includes/exec/errors.i

    IFND	EXEC_ERRORS_I
EXEC_ERRORS_I	SET	1
**
**	$Filename: exec/errors.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.5 $
**	$Date: 90/05/27 $
**
**	Standard Device IO Errors (returned in io_Error)
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

IOERR_OPENFAIL		EQU -1	; device/unit failed to open
IOERR_ABORTED		EQU -2	; request terminated early [after AbortIO()]
IOERR_NOCMD		EQU -3	; command not supported by device
IOERR_BADLENGTH		EQU -4	; not a valid length (usually IO_LENGTH)
IOERR_BADADDRESS	EQU -5	; invalid address (misaligned or bad range)
IOERR_UNITBUSY		EQU -6	; device opens ok, but requested unit is busy
IOERR_SELFTEST		EQU -7	; hardware failed self-test

ERR_OPENDEVICE		EQU  IOERR_OPENFAIL	; Obsolete

    ENDC	; EXEC_ERRORS_I


Includes/exec/io.h

#ifndef	EXEC_IO_H
#define	EXEC_IO_H
/*
**	$Filename: exec/io.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.4 $
**	$Date: 90/05/10 $
**
**	Message structures used for device communication
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_PORTS_H
#include "exec/ports.h"
#endif /* EXEC_PORTS_H */

struct IORequest {
    struct  Message io_Message;
    struct  Device  *io_Device;     /* device node pointer  */
    struct  Unit    *io_Unit;	    /* unit (driver private)*/
    UWORD   io_Command;	    /* device command */
    UBYTE   io_Flags;
    BYTE    io_Error;		    /* error or warning num */
};

struct IOStdReq {
    struct  Message io_Message;
    struct  Device  *io_Device;     /* device node pointer  */
    struct  Unit    *io_Unit;	    /* unit (driver private)*/
    UWORD   io_Command;	    /* device command */
    UBYTE   io_Flags;
    BYTE    io_Error;		    /* error or warning num */
    ULONG   io_Actual;		    /* actual number of bytes transferred */
    ULONG   io_Length;		    /* requested number bytes transferred*/
    APTR    io_Data;		    /* points to data area */
    ULONG   io_Offset;		    /* offset for block structured devices */
};

/* library vector offsets for device reserved vectors */
#define DEV_BEGINIO	(-30)
#define DEV_ABORTIO	(-36)

/* io_Flags defined bits */
#define IOB_QUICK	0
#define IOF_QUICK	(1<<0)

#define CMD_INVALID	0
#define CMD_RESET	1
#define CMD_READ	2
#define CMD_WRITE	3
#define CMD_UPDATE	4
#define CMD_CLEAR	5
#define CMD_STOP	6
#define CMD_START	7
#define CMD_FLUSH	8

#define CMD_NONSTD	9

#endif	/* EXEC_IO_H */


Includes/exec/nodes.i

    IFND EXEC_NODES_I
EXEC_NODES_I	SET 1
**
**	$Filename: exec/nodes.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.10 $
**	$Date: 91/01/09 $
**
**	Nodes & Node type identifiers.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND EXEC_TYPES_I
    INCLUDE "exec/types.i"
    ENDC ; EXEC_TYPES_I

*
*   List Node Structure.  Each member in a list starts with a Node
*
   STRUCTURE	LN,0	; List Node
    APTR	LN_SUCC	; Pointer to next (successor)
    APTR	LN_PRED	; Pointer to previous (predecessor)
    UBYTE	LN_TYPE
    BYTE	LN_PRI	; Priority, for sorting
    APTR	LN_NAME	; ID string, null terminated
    LABEL	LN_SIZE	; Note: word aligned

; minimal node -- no type checking possible
   STRUCTURE	MLN,0	; Minimal List Node
    APTR	MLN_SUCC
    APTR	MLN_PRED
    LABEL	MLN_SIZE

**
** Note: Newly initialized IORequests, and software interrupt structures
** used with Cause(), should have type NT_UNKNOWN.  The OS will assign a type
** when they are first used.
**
;------ Node Types for LN_TYPE

NT_UNKNOWN	EQU 0
NT_TASK	EQU 1	; Exec task
NT_INTERRUPT	EQU 2
NT_DEVICE	EQU 3
NT_MSGPORT	EQU 4
NT_MESSAGE	EQU 5	; Indicates message currently pending
NT_FREEMSG	EQU 6
NT_REPLYMSG	EQU 7	; Message has been replied
NT_RESOURCE	EQU 8
NT_LIBRARY	EQU 9
NT_MEMORY	EQU 10
NT_SOFTINT	EQU 11	; Internal flag used by SoftInts
NT_FONT	EQU 12
NT_PROCESS	EQU 13	; AmigaDOS Process
NT_SEMAPHORE	EQU 14
NT_SIGNALSEM	EQU 15	; signal semaphores
NT_BOOTNODE	EQU 16
NT_KICKMEM	EQU 17
NT_GRAPHICS	EQU 18
NT_DEATHMESSAGE	EQU 19

NT_USER		EQU 254	; User node types work down from here
NT_EXTENDED	EQU 255

    ENDC	;EXEC_NODES_I


Includes/exec/types.h

#ifndef	EXEC_TYPES_H
#define	EXEC_TYPES_H
/*
**	$Filename: exec/types.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.14 $
**	$Date: 91/11/08 $
**
**	Data typing.  Must be included before any other Amiga include.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#define INCLUDE_VERSION	36 /* Version of the include files in use. (Do not
                  use this label for OpenLibrary() calls!) */

#define GLOBAL	extern	    /* the declaratory use of an external */
#define IMPORT	extern	    /* reference to an external */
#define STATIC	static	    /* a local static variable */
#define REGISTER register   /* a (hopefully) register variable */

#ifndef VOID
#define VOID		void
#endif

  /*  WARNING: APTR was redefined for the V36 Includes!  APTR is a   */
 /*  32-Bit Absolute Memory Pointer.  C pointer math will not	    */
/*  operate on APTR --	use "ULONG *" instead.			   */
#ifndef APTR_TYPEDEF
#define APTR_TYPEDEF
typedef void	       *APTR;	    /* 32-bit untyped pointer */
#endif
typedef long		LONG;	    /* signed 32-bit quantity */
typedef unsigned long	ULONG;	    /* unsigned 32-bit quantity */
typedef unsigned long	LONGBITS;   /* 32 bits manipulated individually */
typedef short		WORD;	    /* signed 16-bit quantity */
typedef unsigned short	UWORD;	    /* unsigned 16-bit quantity */
typedef unsigned short	WORDBITS;   /* 16 bits manipulated individually */
#if __STDC__
typedef signed char	BYTE;	    /* signed 8-bit quantity */
#else
typedef char		BYTE;	    /* signed 8-bit quantity */
#endif
typedef unsigned char	UBYTE;	    /* unsigned 8-bit quantity */
typedef unsigned char	BYTEBITS;   /* 8 bits manipulated individually */
typedef unsigned short	RPTR;	    /* signed relative pointer */
typedef unsigned char  *STRPTR;     /* string pointer (NULL terminated) */

/* For compatibility only: (don't use in new code) */
typedef short		SHORT;	    /* signed 16-bit quantity (use WORD) */
typedef unsigned short	USHORT;     /* unsigned 16-bit quantity (use UWORD) */
typedef short		COUNT;
typedef unsigned short	UCOUNT;
typedef ULONG		CPTR;

/* Types with specific semantics */
typedef float		FLOAT;
typedef double		DOUBLE;
typedef short		BOOL;
typedef unsigned char	TEXT;

#ifndef TRUE
#define TRUE		1
#endif
#ifndef FALSE
#define FALSE		0
#endif
#ifndef NULL
#define NULL		0L
#endif

#define BYTEMASK	0xFF

 /* #define LIBRARY_VERSION is now obsolete.  Please use LIBRARY_MINIMUM */
/* or code the specific minimum library version you require.		*/
#define LIBRARY_MINIMUM	33 /* Lowest version supported by Amiga, Inc. */

#endif	/* EXEC_TYPES_H */


Includes/exec/exec.h

#ifndef EXEC_EXEC_H
#define EXEC_EXEC_H
/*
**	$Filename: exec/exec.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.5 $
**	$Date: 90/05/10 $
**
**	Include all other Exec include files in a non-overlapping order.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#include "exec/types.h"
#include "exec/nodes.h"
#include "exec/lists.h"
#include "exec/alerts.h"
#include "exec/errors.h"
#include "exec/initializers.h"
#include "exec/resident.h"
#include "exec/memory.h"
#include "exec/tasks.h"
#include "exec/ports.h"
#include "exec/interrupts.h"
#include "exec/semaphores.h"
#include "exec/libraries.h"
#include "exec/io.h"
#include "exec/devices.h"
#include "exec/execbase.h"

#endif	/* EXEC_EXEC_H */


Includes/exec/io.i

    IFND	EXEC_IO_I
EXEC_IO_I	SET	1
**
**	$Filename: exec/io.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.4 $
**	$Date: 90/05/10 $
**
**	Message structures used for device communication
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND EXEC_PORTS_I
    INCLUDE "exec/ports.i"
    ENDC	; EXEC_PORTS_I

    IFND EXEC_LIBRARIES_I
    INCLUDE "exec/libraries.i"
    ENDC	; EXEC_LIBRARIES_I

;----------------------------------------------------------------
;
;   IO Request Structures
;
;----------------------------------------------------------------

;------ Required portion of IO request:

 STRUCTURE  IO,MN_SIZE
    APTR    IO_DEVICE			; device node pointer
    APTR    IO_UNIT			; unit (driver private)
    UWORD   IO_COMMAND			; device command
    UBYTE   IO_FLAGS			; special flags
    BYTE    IO_ERROR			; error or warning code
    LABEL   IO_SIZE

;------ Standard IO request extension:

    ULONG   IO_ACTUAL			; actual # of bytes transfered
    ULONG   IO_LENGTH			; requested # of bytes transfered
    APTR    IO_DATA			; pointer to data area
    ULONG   IO_OFFSET			; offset for seeking devices
    LABEL   IOSTD_SIZE

;------ IO_FLAGS bit definitions:

    BITDEF  IO,QUICK,0			; complete IO quickly

;----------------------------------------------------------------
;
;   Standard Device Library Functions
;
;----------------------------------------------------------------

        LIBINIT

        LIBDEF  DEV_BEGINIO	; process IO request
        LIBDEF  DEV_ABORTIO	; abort IO request

;----------------------------------------------------------------
;
;   IO Function Macros
;
;----------------------------------------------------------------

BEGINIO     MACRO
        LINKLIB DEV_BEGINIO,IO_DEVICE(A1)
        ENDM

ABORTIO     MACRO
        LINKLIB DEV_ABORTIO,IO_DEVICE(A1)
        ENDM

;----------------------------------------------------------------
;
;   Standard Device Command Definitions
;
;----------------------------------------------------------------

;------ Command definition macro:
DEVINIT     MACRO   ; [baseOffset]
        IFC     '\1',''
CMD_COUNT   SET     CMD_NONSTD
        ENDC
        IFNC    '\1',''
CMD_COUNT   SET     \1
        ENDC
        ENDM

DEVCMD	    MACRO   ; cmdname
\1	    EQU     CMD_COUNT
CMD_COUNT   SET     CMD_COUNT+1
        ENDM

;------ Standard device commands:

        DEVINIT 0

        DEVCMD  CMD_INVALID	; invalid command
        DEVCMD  CMD_RESET		; reset as if just inited
        DEVCMD  CMD_READ		; standard read
        DEVCMD  CMD_WRITE		; standard write
        DEVCMD  CMD_UPDATE		; write out all buffers
        DEVCMD  CMD_CLEAR		; clear all buffers
        DEVCMD  CMD_STOP		; hold current and queued
        DEVCMD  CMD_START		; restart after stop
        DEVCMD  CMD_FLUSH		; abort entire queue

;------ First non-standard device command value:

        DEVCMD  CMD_NONSTD

    ENDC	; EXEC_IO_I


Includes/exec/ports.h

#ifndef	EXEC_PORTS_H
#define	EXEC_PORTS_H
/*
**	$Filename: exec/ports.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.5 $
**	$Date: 90/05/10 $
**
**	Message ports and Messages.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_NODES_H
#include "exec/nodes.h"
#endif /* EXEC_NODES_H */

#ifndef EXEC_LISTS_H
#include "exec/lists.h"
#endif /* EXEC_LISTS_H */

#ifndef EXEC_TASKS_H
#include "exec/tasks.h"
#endif /* EXEC_TASKS_H */

/****** MsgPort *****************************************************/

struct MsgPort {
    struct  Node mp_Node;
    UBYTE   mp_Flags;
    UBYTE   mp_SigBit;		/* signal bit number	*/
    void   *mp_SigTask;		/* object to be signalled */
    struct  List mp_MsgList;	/* message linked list	*/
};

#define mp_SoftInt mp_SigTask	/* Alias */

/* mp_Flags: Port arrival actions (PutMsg) */
#define PF_ACTION	3	/* Mask */
#define PA_SIGNAL	0	/* Signal task in mp_SigTask */
#define PA_SOFTINT	1	/* Signal SoftInt in mp_SoftInt/mp_SigTask */
#define PA_IGNORE	2	/* Ignore arrival */

/****** Message *****************************************************/

struct Message {
    struct  Node mn_Node;
    struct  MsgPort *mn_ReplyPort;  /* message reply port */
    UWORD   mn_Length;		    /* total message length, in bytes */
                    /* (include the size of the Message */
                    /* structure in the length) */
};

#endif	/* EXEC_PORTS_H */


Includes/exec/types.i

    IFND	EXEC_TYPES_I
EXEC_TYPES_I	SET	1
**
**	$Filename: exec/types.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.10 $
**	$Date: 91/03/15 $
**
**	Data storage macros.  Must be included before any other Amiga include.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

INCLUDE_VERSION	EQU 36	;Version of the include files in use. (Do not
            ;use this label for OpenLibrary() calls!)

EXTERN_LIB  MACRO
        XREF    _LVO\1
        ENDM

**
** Structure Building Macros
**
STRUCTURE   MACRO		; structure name, initial offset
\1	    EQU     0
SOFFSET     SET     \2
        ENDM

FPTR	    MACRO		; function pointer (32 bits - all bits valid)
\1	    EQU     SOFFSET
SOFFSET     SET     SOFFSET+4
        ENDM

BOOL	    MACRO		; boolean (16 bits)
\1	    EQU     SOFFSET
SOFFSET     SET     SOFFSET+2
        ENDM

BYTE	    MACRO		; byte (8 bits)
\1	    EQU     SOFFSET
SOFFSET     SET     SOFFSET+1
        ENDM

UBYTE	    MACRO		; unsigned byte (8 bits)
\1	    EQU     SOFFSET
SOFFSET     SET     SOFFSET+1
        ENDM

WORD	    MACRO		; word (16 bits)
\1	    EQU     SOFFSET
SOFFSET     SET     SOFFSET+2
        ENDM

UWORD	    MACRO		; unsigned word (16 bits)
\1	    EQU     SOFFSET
SOFFSET     SET     SOFFSET+2
        ENDM

SHORT	    MACRO		; obsolete - use WORD
\1	    EQU     SOFFSET
SOFFSET     SET     SOFFSET+2
        ENDM

USHORT	    MACRO		; obsolete - use UWORD
\1	    EQU     SOFFSET
SOFFSET     SET     SOFFSET+2
        ENDM

LONG	    MACRO		; long (32 bits)
\1	    EQU     SOFFSET
SOFFSET     SET     SOFFSET+4
        ENDM

ULONG	    MACRO		; unsigned long (32 bits)
\1	    EQU     SOFFSET
SOFFSET     SET     SOFFSET+4
        ENDM

FLOAT	    MACRO		; C float (32 bits)
\1	    EQU     SOFFSET
SOFFSET     SET     SOFFSET+4
        ENDM

DOUBLE	    MACRO		; C double (64 bits)
\1	    EQU	    SOFFSET
SOFFSET	    SET	    SOFFSET+8
        ENDM

APTR	    MACRO		; untyped pointer (32 bits - all bits valid)
\1	    EQU     SOFFSET
SOFFSET     SET     SOFFSET+4
        ENDM

CPTR	    MACRO		; obsolete
\1	    EQU     SOFFSET
SOFFSET     SET     SOFFSET+4
        ENDM

RPTR	    MACRO		; unsigned relative pointer (16 bits)
\1	    EQU     SOFFSET
SOFFSET     SET     SOFFSET+2
        ENDM

LABEL	    MACRO		; Define a label without bumping the offset
\1	    EQU     SOFFSET
        ENDM

STRUCT	    MACRO		; Define a sub-structure
\1	    EQU     SOFFSET
SOFFSET     SET     SOFFSET+\2
        ENDM

ALIGNWORD   MACRO		; Align structure offset to nearest word
SOFFSET     SET     (SOFFSET+1)&$fffffffe
        ENDM

ALIGNLONG   MACRO		; Align structure offset to nearest longword
SOFFSET     SET     (SOFFSET+3)&$fffffffc
        ENDM

**
** Enumerated variables.  Use ENUM to set a base number, and EITEM to assign
** incrementing values.  ENUM can be used to set a new base at any time.
**
ENUM	    MACRO   ;[new base]
        IFC     '\1',''
EOFFSET	    SET	    0		; Default to zero
        ENDC
        IFNC    '\1',''
EOFFSET	    SET     \1
        ENDC
        ENDM

EITEM	    MACRO   ;label
\1	    EQU     EOFFSET
EOFFSET     SET     EOFFSET+1
        ENDM

**
**  Bit Definition Macro
**
**  Given:
**	BITDEF	MEM,CLEAR,16
**
**  Yields:
**	MEMB_CLEAR  EQU 16			; Bit number
**	MEMF_CLEAR  EQU 1<<16			; Bit mask
**

BITDEF	    MACRO   ; prefix,&name,&bitnum
        BITDEF0 \1,\2,B_,\3
\@BITDEF    SET     1<<\3
        BITDEF0 \1,\2,F_,\@BITDEF
        ENDM

BITDEF0     MACRO   ; prefix,&name,&type,&value
\1\3\2	    EQU     \4
        ENDM

**
** LIBRARY_VERSION is now obsolete.  Please use LIBRARY_MINIMUM or code
** the specific minimum library version you require.
**		LIBRARY_VERSION EQU	36
**
LIBRARY_MINIMUM	EQU 33	;Lowest version supported by Amiga, Inc.

    ENDC	; EXEC_TYPES_I


Includes/exec/exec.i

    IFND	EXEC_EXEC_I
EXEC_EXEC_I	SET	1
**
**	$Filename: exec/exec.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.7 $
**	$Date: 90/05/10 $
**
**	Include all other Exec include files in non-overlapping order.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND	EXEC_TYPES_I
    INCLUDE "exec/types.i"
    ENDC
    INCLUDE "exec/macros.i"
    INCLUDE "exec/nodes.i"
    INCLUDE "exec/lists.i"
    INCLUDE "exec/alerts.i"
    INCLUDE "exec/errors.i"
    INCLUDE "exec/initializers.i"
    INCLUDE "exec/resident.i"
    INCLUDE "exec/strings.i"
    INCLUDE "exec/memory.i"
    INCLUDE "exec/tasks.i"
    INCLUDE "exec/ports.i"
    INCLUDE "exec/interrupts.i"
    INCLUDE "exec/semaphores.i"
    INCLUDE "exec/libraries.i"
    INCLUDE "exec/io.i"
    INCLUDE "exec/devices.i"
    INCLUDE "exec/execbase.i"
    INCLUDE "exec/ables.i"
;;;;;;;;INCLUDE "exec/exec_lib.i"    ;special information

    ENDC	; EXEC_EXEC_I


Includes/exec/libraries.h

#ifndef	EXEC_LIBRARIES_H
#define	EXEC_LIBRARIES_H
/*
**	$Filename: exec/libraries.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.10 $
**	$Date: 90/05/10 $
**
**	Definitions for use when creating or using Exec libraries
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_NODES_H
#include "exec/nodes.h"
#endif /* EXEC_NODES_H */

/*------ Special Constants ---------------------------------------*/
#define LIB_VECTSIZE	6	/* Each library entry takes 6 bytes */
#define LIB_RESERVED	4	/* Exec reserves the first 4 vectors */
#define LIB_BASE	(-LIB_VECTSIZE)
#define LIB_USERDEF	(LIB_BASE-(LIB_RESERVED*LIB_VECTSIZE))
#define LIB_NONSTD	(LIB_USERDEF)

/*------ Standard Functions --------------------------------------*/
#define LIB_OPEN	(-6)
#define LIB_CLOSE	(-12)
#define LIB_EXPUNGE	(-18)
#define LIB_EXTFUNC	(-24)	/* for future expansion */

/*------ Library Base Structure ----------------------------------*/
/* Also used for Devices and some Resources */
struct Library {
    struct  Node lib_Node;
    UBYTE   lib_Flags;
    UBYTE   lib_pad;
    UWORD   lib_NegSize;	    /* number of bytes before library */
    UWORD   lib_PosSize;	    /* number of bytes after library */
    UWORD   lib_Version;	    /* major */
    UWORD   lib_Revision;	    /* minor */
    APTR    lib_IdString;	    /* ASCII identification */
    ULONG   lib_Sum;		    /* the checksum itself */
    UWORD   lib_OpenCnt;	    /* number of current opens */
};	/* Warning: size is not a longword multiple! */

/* lib_Flags bit definitions (all others are system reserved) */
#define LIBF_SUMMING	(1<<0)	    /* we are currently checksumming */
#define LIBF_CHANGED	(1<<1)	    /* we have just changed the lib */
#define LIBF_SUMUSED	(1<<2)	    /* set if we should bother to sum */
#define LIBF_DELEXP	(1<<3)	    /* delayed expunge */

/* Temporary Compatibility */
#define lh_Node	lib_Node
#define lh_Flags	lib_Flags
#define lh_pad		lib_pad
#define lh_NegSize	lib_NegSize
#define lh_PosSize	lib_PosSize
#define lh_Version	lib_Version
#define lh_Revision	lib_Revision
#define lh_IdString	lib_IdString
#define lh_Sum		lib_Sum
#define lh_OpenCnt	lib_OpenCnt

#endif	/* EXEC_LIBRARIES_H */


Includes/exec/ports.i

    IFND	EXEC_PORTS_I
EXEC_PORTS_I	SET	1
**
**	$Filename: exec/ports.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.5 $
**	$Date: 90/05/10 $
**
**	Message ports and Messages.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND EXEC_NODES_I
    INCLUDE "exec/nodes.i"
    ENDC	; EXEC_NODES_I

    IFND EXEC_LISTS_I
    INCLUDE "exec/lists.i"
    ENDC	; EXEC_LISTS_I

*----------------------------------------------------------------
*
*   Message Port Structure
*
*----------------------------------------------------------------

 STRUCTURE  MP,LN_SIZE
    UBYTE   MP_FLAGS
    UBYTE   MP_SIGBIT		    ; signal bit number
    APTR    MP_SIGTASK		    ; object to be signalled
    STRUCT  MP_MSGLIST,LH_SIZE	    ; message linked list
    LABEL   MP_SIZE

*------ unions:
MP_SOFTINT	EQU  MP_SIGTASK

*------ MP_FLAGS: Port arrival actions (PutMsg)
PF_ACTION	EQU  3	; Mask
PA_SIGNAL	EQU  0	; Signal task in MP_SIGTASK
PA_SOFTINT	EQU  1	; Signal SoftInt in MP_SOFTINT/MP_SIGTASK
PA_IGNORE	EQU  2	; Ignore arrival

*----------------------------------------------------------------
*
*   Message Structure
*
*----------------------------------------------------------------

 STRUCTURE  MN,LN_SIZE
    APTR    MN_REPLYPORT	; message reply port
    UWORD   MN_LENGTH		; total message length in bytes
                ; (include MN_SIZE in the length)
    LABEL   MN_SIZE

    ENDC	; EXEC_PORTS_I


Includes/exec/execbase.h

#ifndef EXEC_EXECBASE_H
#define EXEC_EXECBASE_H
/*
**	$Filename: exec/execbase.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.18 $
**	$Date: 91/10/10 $
**
**	Definition of the exec.library base structure.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_LISTS_H
#include "exec/lists.h"
#endif /* EXEC_LISTS_H */

#ifndef EXEC_INTERRUPTS_H
#include "exec/interrupts.h"
#endif /* EXEC_INTERRUPTS_H */

#ifndef EXEC_LIBRARIES_H
#include "exec/libraries.h"
#endif /* EXEC_LIBRARIES_H */

#ifndef EXEC_TASKS_H
#include "exec/tasks.h"
#endif /* EXEC_TASKS_H */

/* Definition of the Exec library base structure (pointed to by location 4).
** Most fields are not to be viewed or modified by user programs.  Use
** extreme caution.
*/
struct ExecBase {
    struct Library LibNode; /* Standard library node */

/******** Static System Variables ********/

    UWORD	SoftVer;	/* kickstart release number (obs.) */
    WORD	LowMemChkSum;	/* checksum of 68000 trap vectors */
    ULONG	ChkBase;	/* system base pointer complement */
    APTR	ColdCapture;	/* coldstart soft capture vector */
    APTR	CoolCapture;	/* coolstart soft capture vector */
    APTR	WarmCapture;	/* warmstart soft capture vector */
    APTR	SysStkUpper;	/* system stack base   (upper bound) */
    APTR	SysStkLower;	/* top of system stack (lower bound) */
    ULONG	MaxLocMem;	/* top of chip memory */
    APTR	DebugEntry;	/* global debugger entry point */
    APTR	DebugData;	/* global debugger data segment */
    APTR	AlertData;	/* alert data segment */
    APTR	MaxExtMem;	/* top of extended mem, or null if none */

    UWORD	ChkSum;	/* for all of the above (minus 2) */

/****** Interrupt Related ***************************************/

    struct	IntVector IntVects[16];

/****** Dynamic System Variables *************************************/

    struct	Task *ThisTask; /* pointer to current task (readable) */

    ULONG	IdleCount;	/* idle counter */
    ULONG	DispCount;	/* dispatch counter */
    UWORD	Quantum;	/* time slice quantum */
    UWORD	Elapsed;	/* current quantum ticks */
    UWORD	SysFlags;	/* misc internal system flags */
    BYTE	IDNestCnt;	/* interrupt disable nesting count */
    BYTE	TDNestCnt;	/* task disable nesting count */

    UWORD	AttnFlags;	/* special attention flags (readable) */

    UWORD	AttnResched;	/* rescheduling attention */
    APTR	ResModules;	/* resident module array pointer */
    APTR	TaskTrapCode;
    APTR	TaskExceptCode;
    APTR	TaskExitCode;
    ULONG	TaskSigAlloc;
    UWORD	TaskTrapAlloc;

/****** System Lists (private!) ********************************/

    struct	List MemList;
    struct	List ResourceList;
    struct	List DeviceList;
    struct	List IntrList;
    struct	List LibList;
    struct	List PortList;
    struct	List TaskReady;
    struct	List TaskWait;

    struct	SoftIntList SoftInts[5];

/****** Other Globals *******************************************/

    LONG	LastAlert[4];

    /* these next two variables are provided to allow
    ** system developers to have a rough idea of the
    ** period of two externally controlled signals --
    ** the time between vertical blank interrupts and the
    ** external line rate (which is counted by CIA A's
    ** "time of day" clock).  In general these values
    ** will be 50 or 60, and may or may not track each
    ** other.  These values replace the obsolete AFB_PAL
    ** and AFB_50HZ flags.
    */
    UBYTE	VBlankFrequency;	/* (readable) */
    UBYTE	PowerSupplyFrequency;	/* (readable) */

    struct	List SemaphoreList;

    /* these next two are to be able to kickstart into user ram.
    ** KickMemPtr holds a singly linked list of MemLists which
    ** will be removed from the memory list via AllocAbs.  If
    ** all the AllocAbs's succeeded, then the KickTagPtr will
    ** be added to the rom tag list.
    */
    APTR	KickMemPtr;	/* ptr to queue of mem lists */
    APTR	KickTagPtr;	/* ptr to rom tag queue */
    APTR	KickCheckSum;	/* checksum for mem and tags */

/****** V36 Exec additions start here **************************************/

    UWORD	ex_Pad0;
    ULONG	ex_LaunchPoint;		/* Private to Launch/Switch */
    APTR	ex_RamLibPrivate;
    /* The next ULONG contains the system "E" clock frequency,
    ** expressed in Hertz.	The E clock is used as a timebase for
    ** the Amiga's 8520 I/O chips. (E is connected to "02").
    ** Typical values are 715909 for NTSC, or 709379 for PAL.
    */
    ULONG	ex_EClockFrequency;	/* (readable) */
    ULONG	ex_CacheControl;	/* Private to CacheControl calls */
    ULONG	ex_TaskID;		/* Next available task ID */

    ULONG	ex_PuddleSize;
    ULONG	ex_PoolThreshold;
    struct	MinList ex_PublicPool;

    APTR	ex_MMULock;		/* private */

    UBYTE	ex_Reserved[12];
};

/****** Bit defines for AttnFlags (see above) ******************************/

/*  Processors and Co-processors: */
#define AFB_68010	0	/* also set for 68020 */
#define AFB_68020	1	/* also set for 68030 */
#define AFB_68030	2	/* also set for 68040 */
#define AFB_68040	3
#define AFB_68881	4	/* also set for 68882 */
#define AFB_68882	5
#define	AFB_FPU40	6	/* Set if 68040 FPU */
/*
 * The AFB_FPU40 bit is set when a working 68040 FPU
 * is in the system.  If this bit is set and both the
 * AFB_68881 and AFB_68882 bits are not set, then the 68040
 * math emulation code has not been loaded and only 68040
 * FPU instructions are available.  This bit is valid *ONLY*
 * if the AFB_68040 bit is set.
 */

#define AFB_PRIVATE	15	/* Just what it says */

#define AFF_68010	(1L<<0)
#define AFF_68020	(1L<<1)
#define AFF_68030	(1L<<2)
#define AFF_68040	(1L<<3)
#define AFF_68881	(1L<<4)
#define AFF_68882	(1L<<5)
#define	AFF_FPU40	(1L<<6)

#define AFF_PRIVATE	(1L<<15)

/* #define AFB_RESERVED8   8 */
/* #define AFB_RESERVED9   9 */

/****** Selected flag definitions for Cache manipulation calls **********/

#define CACRF_EnableI	    (1L<<0)  /* Enable instruction cache */
#define CACRF_FreezeI	    (1L<<1)  /* Freeze instruction cache */
#define CACRF_ClearI	    (1L<<3)  /* Clear instruction cache  */
#define CACRF_IBE	    (1L<<4)  /* Instruction burst enable */
#define CACRF_EnableD	    (1L<<8)  /* 68030 Enable data cache  */
#define CACRF_FreezeD	    (1L<<9)  /* 68030 Freeze data cache  */
#define CACRF_ClearD	    (1L<<11) /* 68030 Clear data cache	 */
#define CACRF_DBE	    (1L<<12) /* 68030 Data burst enable */
#define CACRF_WriteAllocate (1L<<13) /* 68030 Write-Allocate mode
                    (must always be set!)	 */
#define CACRF_CopyBack	    (1L<<31) /* Master enable for copyback caches */

#define DMA_Continue	    (1L<<1)  /* Continuation flag for CachePreDMA */
#define DMA_NoModify	    (1L<<2)  /* Set if DMA does not update memory */

#endif	/* EXEC_EXECBASE_H */


Includes/exec/libraries.i

    IFND	EXEC_LIBRARIES_I
EXEC_LIBRARIES_I	SET	1
**
**	$Filename: exec/libraries.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.12 $
**	$Date: 91/03/15 $
**
**	Definitions for use when creating or using Exec libraries
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND EXEC_NODES_I
    INCLUDE "exec/nodes.i"
    ENDC	; EXEC_NODES_I

*------ Special Constants ---------------------------------------
LIB_VECTSIZE	EQU	6		;Each library entry takes 6 bytes
LIB_RESERVED	EQU	4		;Exec reserves the first 4 vectors
LIB_BASE	EQU	-LIB_VECTSIZE
LIB_USERDEF	EQU	LIB_BASE-(LIB_RESERVED*LIB_VECTSIZE) ;First user func
LIB_NONSTD	EQU	LIB_USERDEF

*----------------------------------------------------------------
*
*   Library Definition Macros (for creating libraries)
*
*----------------------------------------------------------------

*------ LIBINIT initializes the base offset for using the "LIBDEF" macro:
LIBINIT     MACRO   ; [baseOffset]
        IFC     '\1',''
COUNT_LIB   SET     LIB_USERDEF
        ENDC
        IFNC    '\1',''
COUNT_LIB   SET     \1
        ENDC
        ENDM

*------ LIBDEF is used to define each library function entry:
LIBDEF	    MACRO   ;libraryFunctionSymbol
\1	    EQU     COUNT_LIB
COUNT_LIB   SET     COUNT_LIB-LIB_VECTSIZE
        ENDM

*------ FUNCDEF is used to parse library offset tables.  Many applications
*------ need a special version of FUNCDEF - you provide your own macro
*------ to match your needs.  Here is an example:
*
*	FUNCDEF		 MACRO
*	_LVO\1		 EQU	FUNC_CNT
*	FUNC_CNT	 SET	FUNC_CNT-6	* Standard offset-6 bytes each
*	FUNC_CNT	 EQU	LIB_USERDEF	* Skip 4 standard vectors
*			 ENDM

*----------------------------------------------------------------
*
*   Standard Library Functions
*
*----------------------------------------------------------------

    LIBINIT LIB_BASE

    LIBDEF  LIB_OPEN
    LIBDEF  LIB_CLOSE
    LIBDEF  LIB_EXPUNGE ; must exist in all libraries
    LIBDEF  LIB_EXTFUNC	; for future expansion - must return zero.

*----------------------------------------------------------------
*
*   Library Base Structure Definition
*   Also used for Devices and some Resources
*
*----------------------------------------------------------------

 STRUCTURE LIB,LN_SIZE
    UBYTE   LIB_FLAGS			; see below
    UBYTE   LIB_pad			; must be zero
    UWORD   LIB_NEGSIZE		; number of bytes before LIB
    UWORD   LIB_POSSIZE		; number of bytes after LIB
    UWORD   LIB_VERSION		; major
    UWORD   LIB_REVISION		; minor
    APTR    LIB_IDSTRING		; ASCII identification
    ULONG   LIB_SUM			; the system-calculated checksum
    UWORD   LIB_OPENCNT		; number of current opens
    LABEL   LIB_SIZE	;Warning: Size is not a longword multiple!

*------ LIB_FLAGS bit definitions (all others are system reserved)
    BITDEF  LIB,SUMMING,0  ; system is currently checksumming
    BITDEF  LIB,CHANGED,1  ; something has changed the library since last sum
    BITDEF  LIB,SUMUSED,2  ; indicates if the library allows checksumming
    BITDEF  LIB,DELEXP,3   ; delayed expunge flag (for use by library)
    BITDEF  LIB,EXP0CNT,4  ; special system expunge flag.

*---------------------------------------------------------------------------
*
*	Function Invocation Macros (for calling existing, opened, libraries)
*	Also see exec/macros.i
*
*---------------------------------------------------------------------------

*------ CALLLIB for calling functions where A6 is already correct:

CALLLIB     MACRO   ; functionOffset
    IFGT NARG-1
        FAIL    !!! CALLLIB MACRO - too many arguments !!!
    ENDC
        JSR     \1(A6)
        ENDM

*------ LINKLIB for calling functions where A6 is incorrect:

LINKLIB     MACRO   ; functionOffset,libraryBase
    IFGT NARG-2
        FAIL    !!! LINKLIB MACRO - too many arguments !!!
    ENDC
        MOVE.L  A6,-(SP)
        MOVE.L  \2,A6
        JSR     \1(A6)
        MOVE.L  (SP)+,A6
        ENDM

    ENDC	; EXEC_LIBRARIES_I


Includes/exec/resident.h

#ifndef	EXEC_RESIDENT_H
#define	EXEC_RESIDENT_H
/*
**	$Filename: exec/resident.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.8 $
**	$Date: 90/11/01 $
**
**	Resident/ROMTag stuff.	Used to identify and initialize code modules.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include "exec/types.h"
#endif /* EXEC_TYPES_H */

struct Resident {
    UWORD rt_MatchWord;	/* word to match on (ILLEGAL)	*/
    struct Resident *rt_MatchTag; /* pointer to the above	*/
    APTR  rt_EndSkip;		/* address to continue scan	*/
    UBYTE rt_Flags;		/* various tag flags		*/
    UBYTE rt_Version;		/* release version number	*/
    UBYTE rt_Type;		/* type of module (NT_XXXXXX)	*/
    BYTE  rt_Pri;		/* initialization priority */
    char  *rt_Name;		/* pointer to node name	*/
    char  *rt_IdString;	/* pointer to identification string */
    APTR  rt_Init;		/* pointer to init code	*/
};

#define RTC_MATCHWORD	0x4AFC	/* The 68000 "ILLEGAL" instruction */

#define RTF_AUTOINIT	(1<<7)	/* rt_Init points to data structure */
#define RTF_AFTERDOS	(1<<2)
#define RTF_SINGLETASK	(1<<1)
#define RTF_COLDSTART	(1<<0)

/* Compatibility: (obsolete) */
/* #define RTM_WHEN	   3 */
#define RTW_NEVER	0
#define RTW_COLDSTART	1

#endif	/* EXEC_RESIDENT_H */


Includes/graphics/clip.h

#ifndef	GRAPHICS_CLIP_H
#define	GRAPHICS_CLIP_H
/*
**	$Filename: graphics/clip.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.2 $
**	$Date: 91/10/24 $
**
**
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef GRAPHICS_GFX_H
#include <graphics/gfx.h>
#endif
#ifndef EXEC_SEMAPHORES_H
#include <exec/semaphores.h>
#endif
#ifndef UTILITY_HOOKS_H
#include <utility/hooks.h>
#endif

/* structures used by and constructed by windowlib.a */
/* understood by rom software */

#define NEWLOCKS

struct Layer
{
    struct  Layer *front,*back;
    struct  ClipRect	*ClipRect;  /* read by roms to find first cliprect */
    struct  RastPort	*rp;
    struct  Rectangle	bounds;
    UBYTE   reserved[4];
    UWORD   priority;		    /* system use only */
    UWORD   Flags;		    /* obscured ?, Virtual BitMap? */
    struct  BitMap *SuperBitMap;
    struct  ClipRect *SuperClipRect; /* super bitmap cliprects if VBitMap != 0*/
                  /* else damage cliprect list for refresh */
    APTR    Window;		  /* reserved for user interface use */
    WORD   Scroll_X,Scroll_Y;
    struct  ClipRect *cr,*cr2,*crnew;	/* used by dedice */
    struct  ClipRect *SuperSaveClipRects; /* preallocated cr's */
    struct  ClipRect *_cliprects;	/* system use during refresh */
    struct  Layer_Info	*LayerInfo;	/* points to head of the list */
    struct  SignalSemaphore Lock;
    struct  Hook *BackFill;
    ULONG   reserved1;
    struct  Region *ClipRegion;
    struct  Region *saveClipRects;	/* used to back out when in trouble*/
    WORD    Width,Height;		/* system use */
    UBYTE   reserved2[18];
    /* this must stay here */
    struct  Region  *DamageList;    /* list of rectangles to refresh
                       through */
};

struct ClipRect
{
    struct  ClipRect *Next;	    /* roms used to find next ClipRect */
    struct  ClipRect *prev;	    /* Temp use in layers (private) */
    struct  Layer   *lobs;	    /* Private use for layers */
    struct  BitMap  *BitMap;	    /* Bitmap for layers private use */
    struct  Rectangle	bounds;     /* bounds of cliprect */
    void    *_p1;		    /* Layers private use!!! */
    void    *_p2;		    /* Layers private use!!! */
    LONG    reserved;		    /* system use (Layers private) */
#ifdef NEWCLIPRECTS_1_1
    LONG    Flags;		    /* Layers private field for cliprects */
                    /* that layers allocates... */
#endif				    /* MUST be multiple of 8 bytes to buffer */
};

/* internal cliprect flags */
#define CR_NEEDS_NO_CONCEALED_RASTERS  1
#define CR_NEEDS_NO_LAYERBLIT_DAMAGE   2

/* defines for code values for getcode */
#define ISLESSX 1
#define ISLESSY 2
#define ISGRTRX 4
#define ISGRTRY 8

#endif	/* GRAPHICS_CLIP_H */


Includes/graphics/gels.i

    IFND	GRAPHICS_GELS_I
GRAPHICS_GELS_I	SET	1
**
**	$Filename: graphics/gels.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**	include file for AMIGA GELS (Graphics Elements)
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND    EXEC_TYPES_I
    include 'exec/types.i'
    ENDC

*------ VS_vSflags ---------------------------------------------------

*   ;-- user-set vSprite flags --
SUSERFLAGS  EQU $00FF	      ; mask of all user-settable vSprite-flags
    BITDEF  VS,VSPRITE,0      ; set if vSprite, clear if bob
    BITDEF  VS,SAVEBACK,1     ; set if background is to be saved/restored
    BITDEF  VS,OVERLAY,2      ; set to mask image of bob onto background
    BITDEF  VS,MUSTDRAW,3     ; set if vSprite absolutely must be drawn
*   ;-- system-set vSprite flags --
    BITDEF  VS,BACKSAVED,8    ; this bob's background has been saved
    BITDEF  VS,BOBUPDATE,9    ; temporary flag, useless to outside world
    BITDEF  VS,GELGONE,10     ; set if gel is completely clipped (offscreen)
    BITDEF  VS,VSOVERFLOW,11  ; vSprite overflow (if MUSTDRAW set we draw!)

*------ B_flags ------------------------------------------------------
*   ;-- these are the user flag bits --
BUSERFLAGS  EQU $00FF         ; mask of all user-settable bob-flags
    BITDEF  B,SAVEBOB,0       ; set to not erase bob
    BITDEF  B,BOBISCOMP,1     ; set to identify bob as animComp
*   ;-- these are the system flag bits --
    BITDEF  B,BWAITING,8      ; set while bob is waiting on 'after'
    BITDEF  B,BDRAWN,9        ; set when bob is drawn this DrawG pass
    BITDEF  B,BOBSAWAY,10     ; set to initiate removal of bob
    BITDEF  B,BOBNIX,11       ; set when bob is completely removed
    BITDEF  B,SAVEPRESERVE,12 ; for back-restore during double-buffer
    BITDEF  B,OUTSTEP,13      ; for double-clearing if double-buffer

*------ defines for the animation procedures -------------------------

ANFRACSIZE  EQU 6
ANIMHALF    EQU $0020
RINGTRIGGER EQU $0001

*------ macros --------------------------------------------------------
* these are GEL functions that are currently simple enough to exist as a
* definition.  It should not be assumed that this will always be the case

InitAnimate MACRO   * &animKey
       CLR.L   \1
       ENDM

RemBob      MACRO   * &b
       OR.W    #BF_BOBSAWAY,b_BobFlags+\1
       ENDM

*------ VS : vSprite -------------------------------------------------
 STRUCTURE  VS,0    ; vSprite
*   -- SYSTEM VARIABLES --
*   GEL linked list forward/backward pointers sorted by y,x value
    APTR    vs_NextVSprite    ; struct *vSprite
    APTR    vs_PrevVSprite    ; struct *vSprite
*   GEL draw list constructed in the order the bobs are actually drawn, then
*   list is copied to clear list
*   must be here in vSprite for system boundary detection
    APTR    vs_DrawPath       ; struct *vSprite: pointer of overlay drawing
    APTR    vs_ClearPath      ; struct *vSprite: pointer for overlay clearing
*   the vSprite positions are defined in (y,x) order to make sorting
*   sorting easier, since (y,x) as a long integer
    WORD    vs_Oldy           ; previous position
    WORD    vs_Oldx           ;
*   -- COMMON VARIABLES --
    WORD    vs_VSFlags        ; vSprite flags
*   -- USER VARIABLES --
*    the vSprite positions are defined in (y,x) order to make sorting
*    easier, since (y,x) as a long integer
    WORD    vs_Y              ; screen position
    WORD    vs_X
    WORD    vs_Height
    WORD    vs_Width          ; number of words per row of image data
    WORD    vs_Depth          ; number of planes of data
    WORD    vs_MeMask         ; which types can collide with this vSprite
    WORD    vs_HitMask        ; which types this vSprite can collide with
    APTR    vs_ImageData      ; *WORD pointer to vSprite image
*    borderLine is the one-dimensional logical OR of all
*    the vSprite bits, used for fast collision detection of edge
    APTR    vs_BorderLine     ; *WORD: logical OR of all vSprite bits
    APTR    vs_CollMask       ; *WORD: similar to above except this is a
*    matrix pointer to this vSprite's color definitions (not used by bobs)
    APTR    vs_SprColors      ; *WORD
    APTR    vs_VSBob	      ; struct *bob: points home if this vSprite is
                  ;  part of a bob
*    planePick flag:  set bit selects a plane from image, clear bit selects
*	  use of shadow mask for that plane
*    OnOff flag: if using shadow mask to fill plane, this bit (corresponding
*	  to bit in planePick) describes whether to fill with 0's or 1's
*    There are two uses for these flags:
*	       - if this is the vSprite of a bob, these flags describe how
*		 the bob is to be drawn into memory
*	       - if this is a simple vSprite and the user intends on setting
*		 the MUSTDRAW flag of the vSprite, these flags must be set
*		 too to describe which color registers the user wants for
*		 the image
    BYTE    vs_PlanePick
    BYTE    vs_PlaneOnOff
    LABEL   vs_SUserExt       ; user definable
    LABEL   vs_SIZEOF

*------ BOB : bob ------------------------------------------------------

 STRUCTURE  BOB,0     ; bob: blitter object
*   -- COMMON VARIABLES --
    WORD    bob_BobFlags      ; general purpose flags (see definitions below)
*   -- USER VARIABLES --
    APTR    bob_SaveBuffer    ; *WORD pointer to the buffer for background
*    save used by bobs for "cookie-cutting" and multi-plane masking
    APTR    bob_ImageShadow   ; *WORD
*    pointer to BOBs for sequenced drawing of bobs
*      for correct overlaying of multiple component animations
    APTR    bob_Before	      ; struct *bob: draw this bob before bob pointed
                  ; to by before
    APTR    bob_After	      ; struct *bob: draw this bob after bob pointed
                  ; to by after
    APTR    bob_BobVSprite    ; struct *vSprite: this bob's vSprite definition
    APTR    bob_BobComp       ; struct *animComp: pointer to this bob's
                  ; animComp def
    APTR    bob_DBuffer       ; struct dBufPacket: pointer to this bob's
                              ; dBuf packet
    LABEL   bob_BUserExt      ; bob user extension
    LABEL   bob_SIZEOF

*------ AC : animComp ------------------------------------------------

 STRUCTURE  AC,0    ; animComp
*   -- COMMON VARIABLES --
    WORD    ac_CompFlags      ; animComp flags for system & user
*    timer defines how long to keep this component active:
*      if set non-zero, timer decrements to zero then switches to nextSeq
*      if set to zero, animComp never switches
    WORD    ac_Timer
*   -- USER VARIABLES --
*    initial value for timer when the animComp is activated by the system
    WORD    ac_TimeSet
*    pointer to next and previous components of animation object
    APTR    ac_NextComp       ; struct *animComp
    APTR    ac_PrevComp       ; struct *animComp
*    pointer to component component definition of next image in sequence
    APTR    ac_NextSeq        ; struct *animComp
    APTR    ac_PrevSeq        ; struct *animComp
    APTR    ac_AnimCRoutine   ; address of special animation procedure
    WORD    ac_YTrans         ; initial y translation (if this is a component)
    WORD    ac_XTrans         ; initial x translation (if this is a component)
    APTR    ac_HeadOb         ; struct *animOb
    APTR    ac_AnimBob        ; struct *bob
    LABEL   ac_SIZE

*------ AO : animOb --------------------------------------------------

 STRUCTURE  AO,0    ; animOb
*   -- SYSTEM VARIABLES --
    APTR    ao_NextOb         ; struct *animOb
    APTR    ao_PrevOb         ; struct *animOb
*    number of calls to Animate this animOb has endured
    LONG    ao_Clock
    WORD    ao_AnOldY         ; old y,x coordinates
    WORD    ao_AnOldX         ;
*   -- COMMON VARIABLES --
    WORD    ao_AnY            ; y,x coordinates of the animOb
    WORD    ao_AnX            ;
*   -- USER VARIABLES --
    WORD    ao_YVel           ; velocities of this object
    WORD    ao_XVel           ;
    WORD    ao_XAccel         ; accelerations of this object
    WORD    ao_YAccel         ;   !!! backwards !!!
    WORD    ao_RingYTrans     ; ring translation values
    WORD    ao_RingXTrans     ;
    APTR    ao_AnimORoutine   ; address of special animation procedure
    APTR    ao_HeadComp       ; struct *animComp: pointer to first component
    LABEL   ao_AUserExt       ; animOb user extension
    LABEL   ao_SIZEOF

*------ DBP : dBufPacket ---------------------------------------------
* dBufPacket defines the values needed to be saved across buffer to buffer
*   when in double-buffer mode

 STRUCTURE  DBP,0             ; dBufPacket
    WORD    dbp_BufY          ; save the other buffers screen coordinates
    WORD    dbp_BufX          ;
    APTR    dbp_BufPath       ; struct *vSprite: carry the draw path over
                              ; the gap
*    these pointers must be filled in by the user
*    pointer to other buffer's background save buffer
    APTR    dbp_BufBuffer     ; *WORD
*    pointer to other buffer's background plane pointers
    APTR    dbp_BufPlanes     ; **WORD
    LABEL   dbp_SIZEOF

    ENDC	; GRAPHICS_GELS_I


Includes/graphics/layers.i

    IFND	GRAPHICS_LAYERS_I
GRAPHICS_LAYERS_I	SET	1
**
**	$Filename: graphics/layers.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND    EXEC_SEMAPHORES_I
       include "exec/semaphores.i"
    ENDC

    IFND  EXEC_LISTS_I
       include	"exec/lists.i"
    ENDC

* these should be clip.i/h but you know backwards compatibility etc.
LAYERSIMPLE		equ   1
LAYERSMART		equ   2
LAYERSUPER		equ   4
LAYERUPDATING		equ   $10
LAYERBACKDROP		equ   $40
LAYERREFRESH		equ   $80
LAYER_CLIPRECTS_LOST	equ   $100

LMN_REGION  equ -1

    STRUCTURE  Layer_Info,0
    APTR       li_top_layer
    APTR       li_check_lp
    APTR       li_obs
    STRUCT     li_FreeClipRects,MLH_SIZE
    STRUCT     li_Lock,SS_SIZE
    STRUCT	   li_gs_Head,LH_SIZE
    LONG		li_long_reserved
    WORD	   li_Flags
    BYTE       li_fatten_count
    BYTE	   li_LockLayersCount
    WORD       li_LayerInfo_extra_size
    APTR		li_blitbuff
    APTR       li_LayerInfo_extra
    LABEL      li_SIZEOF

NEWLAYERINFO_CALLED	equ 1
ALERTLAYERSNOMEM	equ $83010000

    ENDC	; GRAPHICS_LAYERS_I


Includes/graphics/sprite.i

    IFND	GRAPHICS_SPRITE_I
GRAPHICS_SPRITE_I	SET	1
**
**	$Filename: graphics/sprite.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND    EXEC_TYPES_I
    include 'exec/types.i'
    ENDC

   STRUCTURE   SimpleSprite,0
   APTR        ss_posctldata
   WORD        ss_height
   WORD        ss_x
   WORD        ss_y
   WORD        ss_num
   LABEL       ss_SIZEOF

    ENDC	; GRAPHICS_SPRITE_I


Includes/graphics/clip.i

    IFND	GRAPHICS_CLIP_I
GRAPHICS_CLIP_I	SET	1
**
**	$Filename: graphics/clip.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.1 $
**	$Date: 91/01/28 $
**
**
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND    EXEC_TYPES_I
    include 'exec/types.i'
    ENDC

    IFND    GRAPHICS_GFX_I
    include "graphics/gfx.i"
    ENDC

    IFND    EXEC_SEMAPHORES_I
    include "exec/semaphores.i"
    ENDC

NEWLOCKS	equ	1

 STRUCTURE  Layer,0
    LONG    lr_front
    LONG    lr_back
    LONG    lr_ClipRect
    LONG    lr_rp
    WORD    lr_MinX
    WORD    lr_MinY
    WORD    lr_MaxX
    WORD    lr_MaxY
    STRUCT	lr_reserved,4
    WORD	lr_priority
    WORD    lr_Flags
    LONG    lr_SuperBitMap
    LONG    lr_SuperClipRect
    APTR    lr_Window
    WORD    lr_Scroll_X
    WORD    lr_Scroll_Y
    APTR    lr_cr
    APTR    lr_cr2
    APTR    lr_crnew
    APTR    lr_SuperSaverClipRects
    APTR    lr__cliprects
    APTR    lr_LayerInfo
*			just by lucky coincidence
*			this is not confused with simplesprites
    STRUCT	lr_Lock,SS_SIZE
    APTR	lr_BackFill
    ULONG	lr_reserved1
    APTR	lr_ClipRegion
    APTR	lr_saveClipRects
    STRUCT	lr_reserved2,22
    APTR    lr_DamageList
    LABEL   lr_SIZEOF

 STRUCTURE  ClipRect,0
    LONG    cr_Next
    LONG    cr_prev
    LONG    cr_lobs
    LONG    cr_BitMap
    WORD    cr_MinX
    WORD    cr_MinY
    WORD    cr_MaxX
    WORD    cr_MaxY
    APTR    cr__p1
    APTR    cr__p2
    LONG    cr_reserved
    LONG    cr_Flags
 LABEL	    cr_SIZEOF

* internal cliprect flags
CR_NEEDS_NO_CONCEALED_RASTERS	equ	1
CR_NEEDS_NO_LAYERBLIT_DAMAGE	equ	2

* defines for clipping
ISLESSX equ 1
ISLESSY equ 2
ISGRTRX equ 4
ISGRTRY equ 8

* for ancient history reasons
    IFND	lr_Front
lr_Front	equ lr_front
lr_Back	equ lr_back
lr_RastPort	equ	lr_rp
cr_Prev	equ cr_prev
cr_LObs	equ	cr_lobs
    ENDC

    ENDC	; GRAPHICS_CLIP_I


Includes/graphics/gfx.h

#ifndef	GRAPHICS_GFX_H
#define	GRAPHICS_GFX_H
/*
**	$Filename: graphics/gfx.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**	general include file for application programs
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#define BITSET	0x8000
#define BITCLR	0

#define AGNUS
#ifdef AGNUS
#define TOBB(a)      ((long)(a))
#else
#define TOBB(a)      ((long)(a)>>1)  /* convert Chip adr to Bread Board Adr */
#endif

struct Rectangle
{
    WORD   MinX,MinY;
    WORD   MaxX,MaxY;
};

struct Rect32
{
    LONG    MinX,MinY;
    LONG    MaxX,MaxY;
};

typedef struct tPoint
{
    WORD x,y;
} Point;

typedef UBYTE *PLANEPTR;

struct BitMap
{
    UWORD   BytesPerRow;
    UWORD   Rows;
    UBYTE   Flags;
    UBYTE   Depth;
    UWORD   pad;
    PLANEPTR Planes[8];
};

#define RASSIZE(w,h)	((h)*( ((w)+15)>>3&0xFFFE))

#endif	/* GRAPHICS_GFX_H */


Includes/graphics/monitor.h

#ifndef	GRAPHICS_MONITOR_H
#define	GRAPHICS_MONITOR_H
/*
**	$Filename: graphics/monitor.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**	graphics monitorspec definintions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef	EXEC_SEMAPHORES_H
#include	<exec/semaphores.h>
#endif

#ifndef	GRAPHICS_GFXNODES_H
#include	<graphics/gfxnodes.h>
#endif

#ifndef	GRAPHICS_GFX_H
#include	<graphics/gfx.h>
#endif

struct	MonitorSpec
{
    struct	ExtendedNode	ms_Node;
    UWORD	ms_Flags;
    LONG	ratioh;
    LONG	ratiov;
    UWORD	total_rows;
    UWORD	total_colorclocks;
    UWORD	DeniseMaxDisplayColumn;
    UWORD	BeamCon0;
    UWORD	min_row;
    struct	SpecialMonitor	*ms_Special;
    UWORD	ms_OpenCount;
    LONG	(*ms_transform)();
    LONG	(*ms_translate)();
    LONG	(*ms_scale)();
    UWORD	ms_xoffset;
    UWORD	ms_yoffset;
    struct	Rectangle	ms_LegalView;
    LONG	(*ms_maxoscan)();	/* maximum legal overscan */
    LONG	(*ms_videoscan)();	/* video display overscan */
    UWORD	DeniseMinDisplayColumn;
    ULONG	DisplayCompatible;
    struct	List DisplayInfoDataBase;
    struct	SignalSemaphore DisplayInfoDataBaseSemaphore;
    ULONG	ms_reserved00;
    ULONG	ms_reserved01;
};

#define	TO_MONITOR	0
#define	FROM_MONITOR	1
#define	STANDARD_XOFFSET	9
#define	STANDARD_YOFFSET	0
#define	REQUEST_NTSC	1
#define	REQUEST_PAL	2
#define	REQUEST_SPECIAL	4
#define	REQUEST_A2024	8

#define	DEFAULT_MONITOR_NAME	"default.monitor"
#define	NTSC_MONITOR_NAME	"ntsc.monitor"
#define	PAL_MONITOR_NAME	"pal.monitor"
#define	STANDARD_MONITOR_MASK	( REQUEST_NTSC | REQUEST_PAL )

#define	STANDARD_NTSC_ROWS	262
#define	STANDARD_PAL_ROWS	312
#define	STANDARD_COLORCLOCKS	226
#define	STANDARD_DENISE_MAX	455
#define	STANDARD_DENISE_MIN	93
#define	STANDARD_NTSC_BEAMCON	( 0x0000 )
#define	STANDARD_PAL_BEAMCON	( DISPLAYPAL )

#define	SPECIAL_BEAMCON	( VARVBLANK | LOLDIS | VARVSYNC | VARBEAM | CSBLANK )

#define	MIN_NTSC_ROW	21
#define	MIN_PAL_ROW	29
#define	STANDARD_VIEW_X	0x81
#define	STANDARD_VIEW_Y	0x2C
#define	STANDARD_HBSTRT	0x06
#define	STANDARD_HSSTRT	0x0B
#define	STANDARD_HSSTOP	0x1C
#define	STANDARD_HBSTOP	0x2C
#define	STANDARD_VBSTRT	0x0122
#define	STANDARD_VSSTRT	0x02A6
#define	STANDARD_VSSTOP	0x03AA
#define	STANDARD_VBSTOP	0x1066

#define	VGA_COLORCLOCKS (STANDARD_COLORCLOCKS/2)
#define	VGA_TOTAL_ROWS	(STANDARD_NTSC_ROWS*2)
#define	VGA_DENISE_MIN	59
#define	MIN_VGA_ROW	29
#define	VGA_HBSTRT	0x08
#define	VGA_HSSTRT	0x0E
#define	VGA_HSSTOP	0x1C
#define	VGA_HBSTOP	0x1E
#define	VGA_VBSTRT	0x0000
#define	VGA_VSSTRT	0x0153
#define	VGA_VSSTOP	0x0235
#define	VGA_VBSTOP	0x0CCD

#define	VGA_MONITOR_NAME	"vga.monitor"

#define	VGA70_COLORCLOCKS (STANDARD_COLORCLOCKS/2)
#define	VGA70_TOTAL_ROWS 449
#define	VGA70_DENISE_MIN 59
#define	MIN_VGA70_ROW	35
#define	VGA70_HBSTRT	0x08
#define	VGA70_HSSTRT	0x0E
#define	VGA70_HSSTOP	0x1C
#define	VGA70_HBSTOP	0x1E
#define	VGA70_VBSTRT	0x0000
#define	VGA70_VSSTRT	0x02A6
#define	VGA70_VSSTOP	0x0388
#define	VGA70_VBSTOP	0x0F73

#define	VGA70_BEAMCON	(SPECIAL_BEAMCON ^ VSYNCTRUE)
#define	VGA70_MONITOR_NAME	"vga70.monitor"

#define	BROADCAST_HBSTRT	0x01
#define	BROADCAST_HSSTRT	0x06
#define	BROADCAST_HSSTOP	0x17
#define	BROADCAST_HBSTOP	0x27
#define	BROADCAST_VBSTRT	0x0000
#define	BROADCAST_VSSTRT	0x02A6
#define	BROADCAST_VSSTOP	0x054C
#define	BROADCAST_VBSTOP	0x1C40
#define	BROADCAST_BEAMCON	( LOLDIS | CSBLANK )
#define	RATIO_FIXEDPART	4
#define	RATIO_UNITY	(1 << RATIO_FIXEDPART)

struct	AnalogSignalInterval
{
    UWORD	asi_Start;
    UWORD	asi_Stop;
};

struct	SpecialMonitor
{
    struct	ExtendedNode	spm_Node;
    UWORD	spm_Flags;
    int	(*do_monitor)();
    int	(*reserved1)();
    int	(*reserved2)();
    int	(*reserved3)();
    struct	AnalogSignalInterval	hblank;
    struct	AnalogSignalInterval	vblank;
    struct	AnalogSignalInterval	hsync;
    struct	AnalogSignalInterval	vsync;
};

#endif	/* GRAPHICS_MONITOR_H */


Includes/graphics/text.h

#ifndef	GRAPHICS_TEXT_H
#define	GRAPHICS_TEXT_H
/*
**	$Filename: graphics/text.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**	graphics library text structures
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef	EXEC_PORTS_H
#include	"exec/ports.h"
#endif	/* EXEC_PORTS_H */

#ifndef	GRAPHICS_GFX_H
#include	"graphics/gfx.h"
#endif	/* GRAPHICS_GFX_H */

#ifndef	UTILITY_TAGITEM_H
#include	"utility/tagitem.h"
#endif	/* UTILITY_TAGITEM_H */

/*------ Font Styles ------------------------------------------------*/
#define	FS_NORMAL	0	/* normal text (no style bits set) */
#define	FSB_UNDERLINED	0	/* underlined (under baseline) */
#define	FSF_UNDERLINED	0x01
#define	FSB_BOLD	1	/* bold face text (ORed w/ shifted) */
#define	FSF_BOLD	0x02
#define	FSB_ITALIC	2	/* italic (slanted 1:2 right) */
#define	FSF_ITALIC	0x04
#define	FSB_EXTENDED	3	/* extended face (wider than normal) */
#define	FSF_EXTENDED	0x08

#define	FSB_COLORFONT	6	/* this uses ColorTextFont structure */
#define	FSF_COLORFONT	0x40
#define	FSB_TAGGED	7	/* the TextAttr is really an TTextAttr, */
#define	FSF_TAGGED	0x80

/*------ Font Flags -------------------------------------------------*/
#define	FPB_ROMFONT	0	/* font is in rom */
#define	FPF_ROMFONT	0x01
#define	FPB_DISKFONT	1	/* font is from diskfont.library */
#define	FPF_DISKFONT	0x02
#define	FPB_REVPATH	2	/* designed path is reversed (e.g. left) */
#define	FPF_REVPATH	0x04
#define	FPB_TALLDOT	3	/* designed for hires non-interlaced */
#define	FPF_TALLDOT	0x08
#define	FPB_WIDEDOT	4	/* designed for lores interlaced */
#define	FPF_WIDEDOT	0x10
#define	FPB_PROPORTIONAL 5	/* character sizes can vary from nominal */
#define	FPF_PROPORTIONAL 0x20
#define	FPB_DESIGNED	6	/* size explicitly designed, not constructed */
                /* note: if you do not set this bit in your */
                /* textattr, then a font may be constructed */
                /* for you by scaling an existing rom or disk */
                /* font (under V36 and above). */
#define	FPF_DESIGNED	0x40
    /* bit 7 is always clear for fonts on the graphics font list */
#define	FPB_REMOVED	7	/* the font has been removed */
#define	FPF_REMOVED	(1<<7)

/****** TextAttr node, matches text attributes in RastPort **********/
struct TextAttr {
    STRPTR  ta_Name;		/* name of the font */
    UWORD   ta_YSize;		/* height of the font */
    UBYTE   ta_Style;		/* intrinsic font style */
    UBYTE   ta_Flags;		/* font preferences and flags */
};

struct TTextAttr {
    STRPTR  tta_Name;		/* name of the font */
    UWORD   tta_YSize;		/* height of the font */
    UBYTE   tta_Style;		/* intrinsic font style */
    UBYTE   tta_Flags;		/* font preferences and flags */
    struct TagItem *tta_Tags;	/* extended attributes */
};

/****** Text Tags ***************************************************/
#define	TA_DeviceDPI	(1|TAG_USER)	/* Tag value is Point union: */
                    /* Hi word XDPI, Lo word YDPI */

#define	MAXFONTMATCHWEIGHT	32767	/* perfect match from WeighTAMatch */

/****** TextFonts node **********************************************/
struct TextFont {
    struct Message tf_Message;	/* reply message for font removal */
                /* font name in LN	  \    used in this */
    UWORD   tf_YSize;		/* font height		  |    order to best */
    UBYTE   tf_Style;		/* font style		  |    match a font */
    UBYTE   tf_Flags;		/* preferences and flags  /    request. */
    UWORD   tf_XSize;		/* nominal font width */
    UWORD   tf_Baseline;	/* distance from the top of char to baseline */
    UWORD   tf_BoldSmear;	/* smear to affect a bold enhancement */

    UWORD   tf_Accessors;	/* access count */

    UBYTE   tf_LoChar;		/* the first character described here */
    UBYTE   tf_HiChar;		/* the last character described here */
    APTR    tf_CharData;	/* the bit character data */

    UWORD   tf_Modulo;		/* the row modulo for the strike font data */
    APTR    tf_CharLoc;		/* ptr to location data for the strike font */
                /*   2 words: bit offset then size */
    APTR    tf_CharSpace;	/* ptr to words of proportional spacing data */
    APTR    tf_CharKern;	/* ptr to words of kerning data */
};

/* unfortunately, this needs to be explicitly typed */
#define	tf_Extension	tf_Message.mn_ReplyPort

/*-----	tfe_Flags0 (partial definition) ----------------------------*/
#define TE0B_NOREMFONT	0	/* disallow RemFont for this font */
#define TE0F_NOREMFONT	0x01

struct TextFontExtension {	/* this structure is read-only */
    UWORD   tfe_MatchWord;		/* a magic cookie for the extension */
    UBYTE   tfe_Flags0;			/* (system private flags) */
    UBYTE   tfe_Flags1;			/* (system private flags) */
    struct TextFont *tfe_BackPtr;	/* validation of compilation */
    struct MsgPort *tfe_OrigReplyPort;	/* original value in tf_Extension */
    struct TagItem *tfe_Tags;		/* Text Tags for the font */
    UWORD  *tfe_OFontPatchS;		/* (system private use) */
    UWORD  *tfe_OFontPatchK;		/* (system private use) */
    /* this space is reserved for future expansion */
};

/******	ColorTextFont node ******************************************/
/*-----	ctf_Flags --------------------------------------------------*/
#define	CT_COLORMASK	0x000F	/* mask to get to following color styles */
#define	CT_COLORFONT	0x0001	/* color map contains designer's colors */
#define	CT_GREYFONT	0x0002	/* color map describes even-stepped */
                /* brightnesses from low to high */
#define	CT_ANTIALIAS	0x0004	/* zero background thru fully saturated char */

#define	CTB_MAPCOLOR	0	/* map ctf_FgColor to the rp_FgPen if it's */
#define	CTF_MAPCOLOR	0x0001	/* is a valid color within ctf_Low..ctf_High */

/*----- ColorFontColors --------------------------------------------*/
struct ColorFontColors {
    UWORD   cfc_Reserved;	/* *must* be zero */
    UWORD   cfc_Count;		/* number of entries in cfc_ColorTable */
    UWORD  *cfc_ColorTable;	/* 4 bit per component color map packed xRGB */
};

/*-----	ColorTextFont ----------------------------------------------*/
struct ColorTextFont {
    struct TextFont ctf_TF;
    UWORD   ctf_Flags;		/* extended flags */
    UBYTE   ctf_Depth;		/* number of bit planes */
    UBYTE   ctf_FgColor;	/* color that is remapped to FgPen */
    UBYTE   ctf_Low;		/* lowest color represented here */
    UBYTE   ctf_High;		/* highest color represented here */
    UBYTE   ctf_PlanePick;	/* PlanePick ala Images */
    UBYTE   ctf_PlaneOnOff;	/* PlaneOnOff ala Images */
    struct ColorFontColors *ctf_ColorFontColors; /* colors for font */
    APTR    ctf_CharData[8];	/*pointers to bit planes ala tf_CharData */
};

/****** TextExtent node *********************************************/
struct TextExtent {
    UWORD   te_Width;		/* same as TextLength */
    UWORD   te_Height;		/* same as tf_YSize */
    struct Rectangle te_Extent;	/* relative to CP */
};

#endif	/* GRAPHICS_TEXT_H */


Includes/graphics/collide.h

#ifndef	GRAPHICS_COLLIDE_H
#define	GRAPHICS_COLLIDE_H
/*
**	$Filename: graphics/collide.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**	include file for collision detection and control
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

/* These bit descriptors are used by the GEL collide routines.
 *  These bits are set in the hitMask and meMask variables of
 *  a GEL to describe whether or not these types of collisions
 *  can affect the GEL.  BNDRY_HIT is described further below;
 *  this bit is permanently assigned as the boundary-hit flag.
 *  The other bit GEL_HIT is meant only as a default to cover
 *  any GEL hitting any other; the user may redefine this bit.
 */
#define BORDERHIT 0

/* These bit descriptors are used by the GEL boundry hit routines.
 *  When the user's boundry-hit routine is called (via the argument
 *  set by a call to SetCollision) the first argument passed to
 *  the user's routine is the address of the GEL involved in the
 *  boundry-hit, and the second argument has the appropriate bit(s)
 *  set to describe which boundry was surpassed
 */
#define TOPHIT	  1
#define BOTTOMHIT 2
#define LEFTHIT   4
#define RIGHTHIT  8

#endif	/* GRAPHICS_COLLIDE_H */


Includes/graphics/gfx.i

    IFND	GRAPHICS_GFX_I
GRAPHICS_GFX_I	SET	1
**
**	$Filename: graphics/gfx.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND    EXEC_TYPES_I
    include 'exec/types.i'
    ENDC

BITSET	    equ $8000
BITCLR	    equ 0
AGNUS	    equ 1
DENISE	    equ 1

    STRUCTURE	BitMap,0
    WORD    bm_BytesPerRow
    WORD    bm_Rows
    BYTE    bm_Flags
    BYTE    bm_Depth
    WORD    bm_Pad
    STRUCT  bm_Planes,8*4
    LABEL   bm_SIZEOF

   STRUCTURE   Rectangle,0
      WORD  ra_MinX
      WORD  ra_MinY
      WORD  ra_MaxX
      WORD  ra_MaxY
   LABEL    ra_SIZEOF

   STRUCTURE   Rect32,0
      LONG  r32_MinX
      LONG  r32_MinY
      LONG  r32_MaxX
      LONG  r32_MaxY
   LABEL    r32_SIZEOF

   STRUCTURE   tPoint,0
      WORD  tpt_x
      WORD  tpt_y
   LABEL    tpt_SIZEOF

    ENDC	; GRAPHICS_GFX_I


Includes/graphics/monitor.i

    IFND    GRAPHICS_MONITOR_I
GRAPHICS_MONITOR_I SET 1
**
**	$Filename: graphics/monitor.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**	graphics monitorspec definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND    EXEC_TYPES_I
    include 'exec/types.i'
    ENDC

    IFND    GRAPHICS_GFX_I
    include 'graphics/gfx.i'
    ENDC

    IFND    GRAPHICS_GFXNODES_I
    include 'graphics/gfxnodes.i'
    ENDC

    IFND    GRAPHICS_VIEW_I
    include 'graphics/view.i'
    ENDC

    IFND    EXEC_SEMAPHORES_I
    include 'exec/semaphores.i'
    ENDC

    STRUCTURE	AnalogSignalInterval,0
    UWORD	asi_Start
    UWORD	asi_Stop
    LABEL	asi_SIZEOF

    STRUCTURE	SpecialMonitor,XLN_SIZE
    UWORD	spm_Flags
    APTR	spm_do_monitor
    APTR	spm_reserved1
    APTR	spm_reserved2
    APTR	spm_reserved3
    STRUCT	spm_hblank,asi_SIZEOF
    STRUCT	spm_vblank,asi_SIZEOF
    STRUCT	spm_hsync,asi_SIZEOF
    STRUCT	spm_vsync,asi_SIZEOF
    LABEL	spm_SIZEOF

    STRUCTURE	MonitorSpec,XLN_SIZE
    UWORD	ms_Flags
    LONG	ms_ratioh
    LONG	ms_ratiov
    UWORD	ms_total_rows
    UWORD	ms_total_colorclocks
    UWORD	ms_DeniseMaxDisplayColumn
    UWORD	ms_BeamCon0
    UWORD	ms_min_row
    APTR	ms_Special
    UWORD	ms_OpenCount
    APTR	ms_transform
    APTR	ms_translate
    APTR	ms_scale
    UWORD	ms_xoffset
    UWORD	ms_yoffset
    STRUCT	ms_LegalView,ra_SIZEOF
    APTR	ms_maxoscan
    APTR	ms_videoscan
    UWORD	ms_DeniseMinDisplayColumn
    UWORD	ms_DisplayCompatible
    STRUCT	ms_DisplayInfoDataBase,LH_SIZE
    STRUCT	ms_DIDBSemaphore,SS_SIZE
    ULONG	ms_reserved00
    ULONG	ms_reserved01
    LABEL	ms_SIZEOF

    BITDEF	MS,REQUEST_NTSC,0
    BITDEF	MS,REQUEST_PAL,1
    BITDEF	MS,REQUEST_SPECIAL,2
    BITDEF	MS,REQUEST_A2024,3

STANDARD_VIEW_X	equ $81
STANDARD_VIEW_Y	equ $2C

    ENDC	; GRAPHICS_MONITOR_I


Includes/graphics/text.i

    IFND	GRAPHICS_TEXT_I
GRAPHICS_TEXT_I	SET	1
**
**	$Filename: graphics/text.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**	graphics library text structures
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND	EXEC_PORTS_I
    INCLUDE	"exec/ports.i"
    ENDC	; EXEC_PORTS_I

    IFND	UTILITY_TAGITEM_I
    INCLUDE	"utility/tagitem.i"
    ENDC	; UTILITY_TAGITEM_I

*------ Font Styles --------------------------------------------------
FS_NORMAL	EQU	0	; normal text (no style attributes set)
    BITDEF  FS,UNDERLINED,0	; underlined (under baseline)
    BITDEF  FS,BOLD,1		; bold face text (ORed w/ shifted right 1)
    BITDEF  FS,ITALIC,2		; italic (slanted 1:2 right)
    BITDEF  FS,EXTENDED,3	; extended face (must be designed)

    BITDEF  FS,COLORFONT,6	; this uses ColorTextFont structure
    BITDEF  FS,TAGGED,7		; the TextAttr is really an TTextAttr,

*------ Font Flags ---------------------------------------------------
    BITDEF  FP,ROMFONT,0	; font is in rom
    BITDEF  FP,DISKFONT,1	; font is from diskfont.library
    BITDEF  FP,REVPATH,2	; designed path is reversed (e.g. left)
    BITDEF  FP,TALLDOT,3	; designed for hires non-interlaced
    BITDEF  FP,WIDEDOT,4	; designed for lores interlaced
    BITDEF  FP,PROPORTIONAL,5	; character sizes vary from tf_XSize
    BITDEF  FP,DESIGNED,6	; size is "designed", not constructed
*				; note: if you do not set this bit in your
*				; textattr, then a font may be constructed
*				; for you by scaling an existing rom or disk
*				; font (under V36 and above).
    ;-- bit 7 is always clear for fonts on the graphics font list
    BITDEF  FP,REMOVED,7	; the font has been removed

******* TextAttr node ************************************************
 STRUCTURE  TextAttr,0
    APTR    ta_Name		; name of the desired font
    UWORD   ta_YSize		; height of the desired font
    UBYTE   ta_Style		; desired font style
    UBYTE   ta_Flags		; font preferences flags
    LABEL   ta_SIZEOF

 STRUCTURE  TTextAttr,0
    APTR    tta_Name		; name of the desired font
    UWORD   tta_YSize		; height of the desired font
    UBYTE   tta_Style		; desired font style
    UBYTE   tta_Flags		; font preferences flags
    APTR    tta_Tags		; extended attributes
    LABEL   tta_SIZEOF

******* Text Tags ****************************************************
TA_DeviceDPI	EQU	1!TAG_USER	; Tag value is Point union:
                    ; Hi word XDPI, Lo word YDPI

MAXFONTMATCHWEIGHT	EQU	32767	; perfect match from WeighTAMatch

******* TextFont node ************************************************
 STRUCTURE	TextFont,MN_SIZE ; reply message for font removal
                ; font name in LN_NAME	\ used in this
    UWORD   tf_YSize		; font height		| order to best
    UBYTE   tf_Style		; font style		| match a font
    UBYTE   tf_Flags		; preference attributes	/ request.
    UWORD   tf_XSize		; nominal font width
    UWORD   tf_Baseline		; distance from the top of char to baseline
    UWORD   tf_BoldSmear	; smear to affect a bold enhancement

    UWORD   tf_Accessors	; access count

    UBYTE   tf_LoChar		; the first character described here
    UBYTE   tf_HiChar		; the last character described here
    APTR    tf_CharData		; the bit character data

    UWORD   tf_Modulo		; the row modulo for the strike font data
    APTR    tf_CharLoc		; ptr to location data for the strike font
                ;   2 words: bit offset then size
    APTR    tf_CharSpace	; ptr to words of proportional spacing data
    APTR    tf_CharKern		; ptr to words of kerning data
    LABEL   tf_SIZEOF

tf_Extension	EQU	MN_REPLYPORT

;------	tfe_Flags0 (partial definition) ------------------------------
    BITDEF  TE0,NOREMFONT,0	; disallow RemFont for this font

 STRUCTURE	TextFontExtension,0	; this structure is read-only
    UWORD   tfe_MatchWord	; a magic cookie for the extension
    UBYTE   tfe_Flags0		; (system private flags)
    UBYTE   tfe_Flags1		; (system private flags)
    APTR    tfe_BackPtr		; validation of compilation
    APTR    tfe_OrigReplyPort	; original value in tf_Extension
    APTR    tfe_Tags		; Text Tags for the font
    APTR    tfe_OFontPatchS	; (system private use)
    APTR    tfe_OFontPatchK	; (system private use)
    ; this space is reserved for future expansion
    LABEL   tfe_SIZEOF		; (but allocated only by the system)

*******	ColorTextFont node *******************************************
;------	ctf_Flags ----------------------------------------------------
CT_COLORFONT	EQU	$0001	; color map contains designer's colors
CT_GREYFONT	EQU	$0002	; color map describes even-stepped brightnesses
                ; from low to high
CT_ANTIALIAS	EQU	$0004	; zero background thru fully saturated char

    BITDEF	CT,MAPCOLOR,0	; map ctf_FgColor to the rp_FgPen if the former
                ; is a valid color within ctf_Low..ctf_High

;------ ColorFontColors ----------------------------------------------
 STRUCTURE	ColorFontColors,0
    UWORD   cfc_Reserved	; must be zero
    UWORD   cfc_Count		; number of entries in cfc_ColorTable
    APTR    cfc_ColorTable	; 4 bit per component color map packed xRGB
    LABEL   cfc_SIZEOF

;------	ColorTextFont ------------------------------------------------
 STRUCTURE	ColorTextFont,tf_SIZEOF
    UWORD   ctf_Flags		; extended flags
    UBYTE   ctf_Depth		; number of bit planes
    UBYTE   ctf_FgColor		; color that is remapped to FgPen
    UBYTE   ctf_Low		; lowest color represented here
    UBYTE   ctf_High		; highest color represented here
    UBYTE   ctf_PlanePick	; PlanePick ala Images
    UBYTE   ctf_PlaneOnOff	; PlaneOnOff ala Images
    APTR    ctf_ColorFontColors	; struct ColorFontColors * for font
    STRUCT  ctf_CharData,8*4	; pointers to bit planes ala tf_CharData
    LABEL   ctf_SIZEOF

******* TextExtent node **********************************************
 STRUCTURE	TextExtent,0
    UWORD   te_Width		; same as TextLength
    UWORD   te_Height		; same as tf_YSize
    STRUCT  te_Extent,8		; WORD MinX, MinY, MaxX, MaxY relative to CP
    LABEL   te_SIZEOF

    ENDC	; GRAPHICS_TEXT_I


Includes/graphics/copper.h

#ifndef GRAPHICS_COPPER_H
#define GRAPHICS_COPPER_H
/*
**	$Filename: graphics/copper.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**	graphics copper list intstruction definintions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#define COPPER_MOVE 0	    /* pseude opcode for move #XXXX,dir */
#define COPPER_WAIT 1	    /* pseudo opcode for wait y,x */
#define CPRNXTBUF   2	    /* continue processing with next buffer */
#define CPR_NT_LOF  0x8000  /* copper instruction only for short frames */
#define CPR_NT_SHT  0x4000  /* copper instruction only for long frames */
#define CPR_NT_SYS  0x2000  /* copper user instruction only */

struct CopIns
{
    WORD   OpCode; /* 0 = move, 1 = wait */
    union
    {
    struct CopList *nxtlist;
    struct
    {
   union
   {
   WORD   VWaitPos;	   /* vertical beam wait */
   WORD   DestAddr;	   /* destination address of copper move */
   } u1;
   union
   {
   WORD   HWaitPos;	   /* horizontal beam wait position */
   WORD   DestData;	   /* destination immediate data to send */
   } u2;
    } u4;
    } u3;
};
/* shorthand for above */
#define NXTLIST     u3.nxtlist
#define VWAITPOS    u3.u4.u1.VWaitPos
#define DESTADDR    u3.u4.u1.DestAddr
#define HWAITPOS    u3.u4.u2.HWaitPos
#define DESTDATA    u3.u4.u2.DestData

/* structure of cprlist that points to list that hardware actually executes */
struct cprlist
{
    struct cprlist *Next;
    UWORD   *start;	    /* start of copper list */
    WORD   MaxCount;	   /* number of long instructions */
};

struct CopList
{
    struct  CopList *Next;  /* next block for this copper list */
    struct  CopList *_CopList;	/* system use */
    struct  ViewPort *_ViewPort;    /* system use */
    struct  CopIns *CopIns; /* start of this block */
    struct  CopIns *CopPtr; /* intermediate ptr */
    UWORD   *CopLStart;     /* mrgcop fills this in for Long Frame*/
    UWORD   *CopSStart;     /* mrgcop fills this in for Short Frame*/
    WORD   Count;	   /* intermediate counter */
    WORD   MaxCount;	   /* max # of copins for this block */
    WORD   DyOffset;	   /* offset this copper list vertical waits */
#ifdef V1_3
    UWORD   *Cop2Start;
    UWORD   *Cop3Start;
    UWORD   *Cop4Start;
    UWORD   *Cop5Start;
#endif
};

struct UCopList
{
    struct UCopList *Next;
    struct CopList  *FirstCopList; /* head node of this copper list */
    struct CopList  *CopList;	   /* node in use */
};

/* private graphics data structure */

struct copinit
{
    UWORD vsync_hblank[2];
    UWORD diwstart[4];
    UWORD diagstrt[4];	    /* copper list for first bitplane */
    UWORD sprstrtup[(2*8*2)];
    UWORD wait14[2];
    UWORD norm_hblank[2];
    UWORD genloc[4];
    UWORD jump[(2*2)];
    UWORD wait_forever[2];
    UWORD   sprstop[4];
};

#endif	/* GRAPHICS_COPPER_H */


Includes/graphics/gfxbase.h

#ifndef GRAPHICS_GFXBASE_H
#define GRAPHICS_GFXBASE_H
/*
**	$Filename: graphics/gfxbase.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.3 $
**	$Date: 91/04/15 $
**
**	graphics base definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_LISTS_H
#include <exec/lists.h>
#endif
#ifndef EXEC_LIBRARIES_H
#include <exec/libraries.h>
#endif
#ifndef EXEC_INTERRUPTS_H
#include <exec/interrupts.h>
#endif

struct GfxBase
{
    struct Library  LibNode;
    struct View *ActiView;
    struct copinit *copinit;	/* ptr to copper start up list */
    long    *cia;		/* for 8520 resource use */
    long    *blitter;		/* for future blitter resource use */
    UWORD   *LOFlist;
    UWORD   *SHFlist;
    struct bltnode *blthd,*blttl;
    struct bltnode *bsblthd,*bsblttl;
    struct Interrupt vbsrv,timsrv,bltsrv;
    struct List     TextFonts;
    struct  TextFont *DefaultFont;
    UWORD  Modes;			/* copy of current first bplcon0 */
    BYTE VBlank;
    BYTE Debug;
    WORD BeamSync;
    WORD system_bplcon0;	/* it is ored into each bplcon0 for display */
    UBYTE   SpriteReserved;
    UBYTE   bytereserved;
    UWORD   Flags;
    WORD   BlitLock;
    WORD	BlitNest;

    struct	List	BlitWaitQ;
    struct	Task	*BlitOwner;
    struct	List	TOF_WaitQ;
    UWORD	DisplayFlags;		/* NTSC PAL GENLOC etc*/
                    /* flags initialized at power on */
    struct SimpleSprite **SimpleSprites;
    UWORD	MaxDisplayRow;		/* hardware stuff, do not use */
    UWORD	MaxDisplayColumn;	/* hardware stuff, do not use */
    UWORD	NormalDisplayRows;
    UWORD	NormalDisplayColumns;
    /* the following are for standard non interlace, 1/2 wb width */
    UWORD	NormalDPMX;		/* Dots per meter on display */
    UWORD	NormalDPMY;		/* Dots per meter on display */
    struct	SignalSemaphore *LastChanceMemory;
    UWORD	*LCMptr;
    UWORD	MicrosPerLine;		/* 256 time usec/line */
    UWORD	MinDisplayColumn;
    UBYTE	ChipRevBits0;
    UBYTE	crb_reserved[5];
    UWORD	monitor_id;		/* normally null */
    ULONG	hedley[8];
    ULONG	hedley_sprites[8] ;	/* sprite ptrs for intuition mouse */
    ULONG	hedley_sprites1[8] ;		/* sprite ptrs for intuition mouse */
    WORD	hedley_count;
    UWORD	hedley_flags;
    WORD	hedley_tmp;
    LONG	*hash_table;
    UWORD	current_tot_rows;
    UWORD	current_tot_cclks;
    UBYTE	hedley_hint;
    UBYTE	hedley_hint2;
    ULONG	nreserved[4];
    LONG	*a2024_sync_raster;
    WORD   control_delta_pal;
    WORD   control_delta_ntsc;
    struct	MonitorSpec *current_monitor;
    struct	List MonitorList;
    struct	MonitorSpec *default_monitor;
    struct	SignalSemaphore *MonitorListSemaphore;
    VOID	*DisplayInfoDataBase;
    WORD	lapad;			/* alignment */
    struct	SignalSemaphore *ActiViewCprSemaphore;
    ULONG	*UtilityBase;		/* for hook and tag utilities	*/
    ULONG	*ExecBase;		/* to link with rom.lib	*/
    };

#define NTSC		1
#define GENLOC		2
#define PAL		4
#define TODA_SAFE	8

#define BLITMSG_FAULT	4

/* bits defs for ChipRevBits */
#define	GFXB_BIG_BLITS	0
#define	GFXB_HR_AGNUS	0
#define GFXB_HR_DENISE	1

#define GFXF_BIG_BLITS	1
#define	GFXF_HR_AGNUS	1
#define GFXF_HR_DENISE	2

#define GRAPHICSNAME	"graphics.library"

#endif	/* GRAPHICS_GFXBASE_H */


Includes/graphics/rastport.h

#ifndef	GRAPHICS_RASTPORT_H
#define	GRAPHICS_RASTPORT_H
/*
**	$Filename: graphics/rastport.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef GRAPHICS_GFX_H
#include <graphics/gfx.h>
#endif

struct AreaInfo
{
    WORD   *VctrTbl;	     /* ptr to start of vector table */
    WORD   *VctrPtr;	     /* ptr to current vertex */
    BYTE    *FlagTbl;	      /* ptr to start of vector flag table */
    BYTE    *FlagPtr;	      /* ptrs to areafill flags */
    WORD   Count;	     /* number of vertices in list */
    WORD   MaxCount;	     /* AreaMove/Draw will not allow Count>MaxCount*/
    WORD   FirstX,FirstY;    /* first point for this polygon */
};

struct TmpRas
{
    BYTE *RasPtr;
    LONG Size;
};

/* unoptimized for 32bit alignment of pointers */
struct GelsInfo
{
    BYTE sprRsrvd;	      /* flag of which sprites to reserve from
                 vsprite system */
    UBYTE Flags;	      /* system use */
    struct VSprite *gelHead, *gelTail; /* dummy vSprites for list management*/
    /* pointer to array of 8 WORDS for sprite available lines */
    WORD *nextLine;
    /* pointer to array of 8 pointers for color-last-assigned to vSprites */
    WORD **lastColor;
    struct collTable *collHandler;     /* addresses of collision routines */
    WORD leftmost, rightmost, topmost, bottommost;
   APTR firstBlissObj,lastBlissObj;    /* system use only */
};

struct RastPort
{
    struct  Layer *Layer;
    struct  BitMap   *BitMap;
    UWORD  *AreaPtrn;	     /* ptr to areafill pattern */
    struct  TmpRas *TmpRas;
    struct  AreaInfo *AreaInfo;
    struct  GelsInfo *GelsInfo;
    UBYTE   Mask;	      /* write mask for this raster */
    BYTE    FgPen;	      /* foreground pen for this raster */
    BYTE    BgPen;	      /* background pen  */
    BYTE    AOlPen;	      /* areafill outline pen */
    BYTE    DrawMode;	      /* drawing mode for fill, lines, and text */
    BYTE    AreaPtSz;	      /* 2^n words for areafill pattern */
    BYTE    linpatcnt;	      /* current line drawing pattern preshift */
    BYTE    dummy;
    UWORD  Flags;	     /* miscellaneous control bits */
    UWORD  LinePtrn;	     /* 16 bits for textured lines */
    WORD   cp_x, cp_y;	     /* current pen position */
    UBYTE   minterms[8];
    WORD   PenWidth;
    WORD   PenHeight;
    struct  TextFont *Font;   /* current font address */
    UBYTE   AlgoStyle;	      /* the algorithmically generated style */
    UBYTE   TxFlags;	      /* text specific flags */
    UWORD   TxHeight;	      /* text height */
    UWORD   TxWidth;	      /* text nominal width */
    UWORD   TxBaseline;       /* text baseline */
    WORD    TxSpacing;	      /* text spacing (per character) */
    APTR    *RP_User;
    ULONG   longreserved[2];
#ifndef GFX_RASTPORT_1_2
    UWORD   wordreserved[7];  /* used to be a node */
    UBYTE   reserved[8];      /* for future use */
#endif
};

/* drawing modes */
#define JAM1	    0	      /* jam 1 color into raster */
#define JAM2	    1	      /* jam 2 colors into raster */
#define COMPLEMENT  2	      /* XOR bits into raster */
#define INVERSVID   4	      /* inverse video for drawing modes */

/* these are the flag bits for RastPort flags */
#define FRST_DOT    0x01      /* draw the first dot of this line ? */
#define ONE_DOT     0x02      /* use one dot mode for drawing lines */
#define DBUFFER     0x04      /* flag set when RastPorts
                 are double-buffered */

         /* only used for bobs */

#define AREAOUTLINE 0x08      /* used by areafiller */
#define NOCROSSFILL 0x20      /* areafills have no crossovers */

/* there is only one style of clipping: raster clipping */
/* this preserves the continuity of jaggies regardless of clip window */
/* When drawing into a RastPort, if the ptr to ClipRect is nil then there */
/* is no clipping done, this is dangerous but useful for speed */

#endif	/* GRAPHICS_RASTPORT_H */


Includes/graphics/videocontrol.h

#ifndef	GRAPHICS_VIDEOCONTROL_H
#define	GRAPHICS_VIDEOCONTROL_H
/*
**	$Filename: graphics/videocontrol.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**	include define file for videocontrol commands
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif /* EXEC_TYPES_H */

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif /* UTILITY_TAGITEM_H */

#define	VTAG_END_CM		0x00000000
#define	VTAG_CHROMAKEY_CLR	0x80000000
#define	VTAG_CHROMAKEY_SET	0x80000001
#define	VTAG_BITPLANEKEY_CLR	0x80000002
#define	VTAG_BITPLANEKEY_SET	0x80000003
#define	VTAG_BORDERBLANK_CLR	0x80000004
#define	VTAG_BORDERBLANK_SET	0x80000005
#define	VTAG_BORDERNOTRANS_CLR	0x80000006
#define	VTAG_BORDERNOTRANS_SET	0x80000007
#define	VTAG_CHROMA_PEN_CLR	0x80000008
#define	VTAG_CHROMA_PEN_SET	0x80000009
#define	VTAG_CHROMA_PLANE_SET	0x8000000A
#define	VTAG_ATTACH_CM_SET	0x8000000B
#define	VTAG_NEXTBUF_CM		0x8000000C
#define	VTAG_BATCH_CM_CLR	0x8000000D
#define	VTAG_BATCH_CM_SET	0x8000000E
#define	VTAG_NORMAL_DISP_GET	0x8000000F
#define	VTAG_NORMAL_DISP_SET	0x80000010
#define	VTAG_COERCE_DISP_GET	0x80000011
#define	VTAG_COERCE_DISP_SET	0x80000012
#define	VTAG_VIEWPORTEXTRA_GET	0x80000013
#define	VTAG_VIEWPORTEXTRA_SET	0x80000014
#define	VTAG_CHROMAKEY_GET	0x80000015
#define	VTAG_BITPLANEKEY_GET	0x80000016
#define	VTAG_BORDERBLANK_GET	0x80000017
#define	VTAG_BORDERNOTRANS_GET	0x80000018
#define	VTAG_CHROMA_PEN_GET	0x80000019
#define	VTAG_CHROMA_PLANE_GET	0x8000001A
#define	VTAG_ATTACH_CM_GET	0x8000001B
#define	VTAG_BATCH_CM_GET	0x8000001C
#define	VTAG_BATCH_ITEMS_GET	0x8000001D
#define	VTAG_BATCH_ITEMS_SET	0x8000001E
#define	VTAG_BATCH_ITEMS_ADD	0x8000001F
#define	VTAG_VPMODEID_GET	0x80000020
#define	VTAG_VPMODEID_SET	0x80000021
#define	VTAG_VPMODEID_CLR	0x80000022
#define	VTAG_USERCLIP_GET	0x80000023
#define	VTAG_USERCLIP_SET	0x80000024
#define	VTAG_USERCLIP_CLR	0x80000025

#endif	/* GRAPHICS_VIDEOCONTROL_H */


Includes/graphics/copper.i

   IFND  GRAPHICS_COPPER_I
GRAPHICS_COPPER_I SET	1
**
**	$Filename: graphics/copper.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.1 $
**	$Date: 91/02/12 $
**
**	graphics copper list intruction definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND    EXEC_TYPES_I
    include 'exec/types.i'
    ENDC

COPPER_MOVE equ 0	* pseude opcode for move #XXXX,dir
COPPER_WAIT equ 1	* pseudo opcode for wait y,x
CPRNXTBUF   equ 2	* continue processing with next buffer
CPR_NT_LOF  equ $8000	* copper instruction only for short frames
CPR_NT_SHT  equ $4000	* copper instruction only for long frames
CPR_NT_SYS  equ $2000	* copper user instruction only

   STRUCTURE   CopIns,0
      WORD  ci_OpCode	      * 0 = move, 1 = wait
      STRUCT   ci_nxtlist,0   * UNION
      STRUCT   ci_VWaitPos,0
      STRUCT   ci_DestAddr,2

      STRUCT   ci_HWaitPos,0
      STRUCT   ci_DestData,2

   LABEL ci_SIZEOF

* structure of cprlist that points to list that hardware actually executes
   STRUCTURE   cprlist,0
      APTR  crl_Next
      APTR  crl_start
      WORD  crl_MaxCount
   LABEL crl_SIZEOF

   STRUCTURE   CopList,0
      APTR  cl_Next	   * next block for this copper list
      APTR  cl__CopList    * system use
      APTR  cl__ViewPort   * system use
      APTR  cl_CopIns	   * start of this block
      APTR  cl_CopPtr	   * intermediate ptr
      APTR  cl_CopLStart   * mrgcop fills this in for Long Frame
      APTR  cl_CopSStart   * mrgcop fills this in for Short Frame
      WORD  cl_Count	   * intermediate counter
      WORD  cl_MaxCount    * max # of copins for this block
      WORD  cl_DyOffset    * offset this copper list vertical waits
   LABEL cl_SIZEOF

   STRUCTURE   UCopList,0
      APTR     ucl_Next
      APTR     ucl_FirstCopList * head node of this copper list
      APTR     ucl_CopList	* node in use
   LABEL ucl_SIZEOF

*  private graphics data structure
   STRUCTURE   copinit,0
    STRUCT	copinit_vsync_hblank,4
    STRUCT	copinit_diwstart,8
    STRUCT	copinit_diagstrt,8
    STRUCT	copinit_sprstrtup,2*(2*8*2)
    STRUCT	copinit_wait14,2*(2+2)
    STRUCT	copinit_genloc,2*(4+(2*2)+2)
    STRUCT	copinit_sprstop,8
   LABEL copinit_SIZEOF

   ENDC	; GRAPHICS_COPPER_I


Includes/graphics/gfxbase.i

    IFND    GRAPHICS_GFXBASE_I
GRAPHICS_GFXBASE_I  SET 1
**
**	$Filename: graphics/gfxbase.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.3 $
**	$Date: 91/04/15 $
**
**	graphics base definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND    EXEC_LISTS_I
    include 'exec/lists.i'
    ENDC
    IFND    EXEC_LIBRARIES_I
    include 'exec/libraries.i'
    ENDC
    IFND    EXEC_INTERRUPTS_I
    include 'exec/interrupts.i'
    ENDC

 STRUCTURE  GfxBase,LIB_SIZE
    APTR    gb_ActiView     ; struct *View
    APTR    gb_copinit	    ; struct *copinit; ptr to copper start up list
    APTR    gb_cia	; for 6526 resource use
    APTR    gb_blitter	    ; for blitter resource use
    APTR    gb_LOFlist	    ; current copper list being run
    APTR    gb_SHFlist	    ; current copper list being run
    APTR    gb_blthd	    ; struct *bltnode
    APTR    gb_blttl	    ;
    APTR    gb_bsblthd	    ;
    APTR    gb_bsblttl	    ;
    STRUCT  gb_vbsrv,IS_SIZE
    STRUCT  gb_timsrv,IS_SIZE
    STRUCT  gb_bltsrv,IS_SIZE
    STRUCT  gb_TextFonts,LH_SIZE
    APTR    gb_DefaultFont
    UWORD   gb_Modes	    ; copy of bltcon0
    BYTE    gb_VBlank
    BYTE    gb_Debug
    UWORD   gb_BeamSync
    WORD    gb_system_bplcon0
    BYTE    gb_SpriteReserved
    BYTE    gb_bytereserved

    WORD    gb_Flags
    WORD    gb_BlitLock
    WORD	gb_BlitNest
    STRUCT	gb_BlitWaitQ,LH_SIZE
    APTR	gb_BlitOwner
    STRUCT	gb_TOF_WaitQ,LH_SIZE

    WORD	gb_DisplayFlags
    APTR	gb_SimpleSprites
    WORD	gb_MaxDisplayRow
    WORD	gb_MaxDisplayColumn
    WORD	gb_NormalDisplayRows
    WORD	gb_NormalDisplayColumns
    WORD	gb_NormalDPMX
    WORD	gb_NormalDPMY

    APTR	gb_LastChanceMemory
    APTR	gb_LCMptr

    WORD	gb_MicrosPerLine	; usecs per line times 256
    WORD	gb_MinDisplayColumn

    UBYTE	gb_ChipRevBits0		; agnus/denise new features
    STRUCT	gb_crb_reserved,5

    STRUCT	gb_monitor_id,2	; normally null
    STRUCT	gb_hedley,4*8
    STRUCT	gb_hedley_sprites,4*8
    STRUCT	gb_hedley_sprites1,4*8
    WORD	gb_hedley_count
    WORD	gb_hedley_flags
    WORD	gb_hedley_tmp
    APTR	gb_hash_table
    UWORD	gb_current_tot_rows
    UWORD	gb_current_tot_cclks
    UBYTE	gb_hedley_hint
    UBYTE	gb_hedley_hint2
    STRUCT	gb_nreserved,4*4
    APTR	gb_a2024_sync_raster
    WORD	gb_control_delta_pal
    WORD	gb_control_delta_ntsc
    APTR	gb_current_monitor
    STRUCT	gb_MonitorList,LH_SIZE
    APTR	gb_default_monitor
    APTR	gb_MonitorListSemaphore
    APTR	gb_DisplayInfoDataBase
    WORD	lapad;					; alignment
    APTR	gb_ActiViewCprSemaphore
    APTR	gb_UtilityBase
    APTR	gb_ExecBase
    LABEL   gb_SIZE

* bits for dalestuff, which may go away when blitter becomes a resource
OWNBLITTERn equ 0   * blitter owned bit
QBOWNERn    equ 1   * blitter owned by blit queuer

* flag bits for ChipRevBits
    BITDEF	GFX,BIG_BLITS,0
    BITDEF	GFX,HR_AGNUS,0
    BITDEF	GFX,HR_DENISE,1

QBOWNER     equ 1<<QBOWNERn

* flag bits for DisplayFlags

NTSCn		equ 0
NTSC		equ 1<<NTSCn

GENLOCn		equ 1
GENLOC		equ 1<<GENLOCn

PALn		equ 2
PAL		equ 1<<PALn

TODA_SAFEn	equ 3
TODA_SAFE	equ 1<<TODA_SAFEn

BLITMSG_FAULTn	equ 2
BLITMSG_FAULT	equ 1<<BLITMSG_FAULTn

* handy name macro

GRAPHICSNAME	MACRO
        DC.B  'graphics.library',0
        ENDM

    ENDC	; GRAPHICS_GFXBASE_I


Includes/graphics/rastport.i

    IFND	GRAPHICS_RASTPORT_I
GRAPHICS_RASTPORT_I	SET	1
**
**	$Filename: graphics/rastport.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND    EXEC_TYPES_I
    include 'exec/types.i'
    ENDC

    IFND    GRAPHICS_GFX_I
       include "graphics/gfx.i"
    ENDC

*------ TR : TmpRas --------------------------------------------------

 STRUCTURE  TmpRas,0
   APTR     tr_RasPtr	      ; *WORD
   LONG     tr_Size
   LABEL    tr_SIZEOF

*------ GelsInfo

   STRUCTURE   GelsInfo,0
   BYTE     gi_sprRsrvd       * flag of which sprites to reserve from
*			      * vsprite system
   BYTE     gi_Flags	      * reserved for system use
   APTR     gi_gelHead
   APTR     gi_gelTail	      * dummy vSprites for list management
* pointer to array of 8 WORDS for sprite available lines
   APTR     gi_nextLine
* pointer to array of 8 pointers for color-last-assigned to vSprites
   APTR     gi_lastColor
   APTR     gi_collHandler    * addresses of collision routines
   WORD    gi_leftmost
   WORD    gi_rightmost
   WORD    gi_topmost
   WORD    gi_bottommost
   APTR     gi_firstBlissObj
   APTR     gi_lastBlissObj   * system use only
   LABEL    gi_SIZEOF

*------ RP_Flags ------
   BITDEF   RP,FRST_DOT,0     ; draw the first dot of this line ?
   BITDEF   RP,ONE_DOT,1      ; use one dot mode for drawing lines
   BITDEF   RP,DBUFFER,2      ; flag set when RastPorts are double-buffered
*			      ;   (only used for bobs)
   BITDEF   RP,AREAOUTLINE,3  ; used by areafiller
   BITDEF   RP,NOCROSSFILL,5  ; used by areafiller

*------ RP_DrawMode ------
RP_JAM1        EQU 0
RP_JAM2        EQU 1
RP_COMPLEMENT  EQU 2
RP_INVERSVID   EQU 4	      ; inverse video for drawing modes

*------ RP_TxFlags ------
   BITDEF  RP,TXSCALE,0

 STRUCTURE  RastPort,0
   LONG     rp_Layer
   LONG     rp_BitMap
   LONG     rp_AreaPtrn
   LONG     rp_TmpRas
   LONG     rp_AreaInfo
   LONG     rp_GelsInfo
   BYTE     rp_Mask
   BYTE     rp_FgPen
   BYTE     rp_BgPen
   BYTE     rp_AOLPen
   BYTE     rp_DrawMode
   BYTE     rp_AreaPtSz
   BYTE     rp_linpatcnt
   BYTE     rp_Dummy
   WORD     rp_Flags
   WORD     rp_LinePtrn
   WORD     rp_cp_x
   WORD     rp_cp_y
   STRUCT   rp_minterms,8
   WORD     rp_PenWidth
   WORD     rp_PenHeight
   LONG     rp_Font
   BYTE     rp_AlgoStyle
   BYTE     rp_TxFlags
   WORD     rp_TxHeight
   WORD     rp_TxWidth
   WORD     rp_TxBaseline
   WORD     rp_TxSpacing
   APTR     rp_RP_User
   STRUCT   rp_longreserved,8
    ifnd	GFX_RASTPORT_1_2
   STRUCT   rp_wordreserved,14
   STRUCT   rp_reserved,8
    endc
   LABEL    rp_SIZEOF

 STRUCTURE  AreaInfo,0
   LONG     ai_VctrTbl
   LONG     ai_VctrPtr
   LONG     ai_FlagTbl
   LONG     ai_FlagPtr
   WORD     ai_Count
   WORD     ai_MaxCount
   WORD     ai_FirstX
   WORD     ai_FirstY
   LABEL    ai_SIZEOF

ONE_DOTn    equ     1
ONE_DOT     equ     $2	    * 1<<ONE_DOTn
FRST_DOTn   equ     0
FRST_DOT    equ     1	    * 1<<FRST_DOTn

    ENDC	; GRAPHICS_RASTPORT_I


Includes/graphics/videocontrol.i

    IFND    GRAPHICS_VIDEOCONTROL_I
GRAPHICS_VIDEOCONTROL_I SET 1
**
**	$Filename: graphics/videocontrol.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**	graphics videocontrol definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND    EXEC_TYPES_I
    include 'exec/types.i'
    ENDC

    IFND    UTILITY_TAGITEM_I
    include 'utility/tagitem.i'
    ENDC

VTAG_END_CM		equ	$00000000
VTAG_CHROMAKEY_CLR	equ	$80000000
VTAG_CHROMAKEY_SET	equ	$80000001
VTAG_BITPLANEKEY_CLR	equ	$80000002
VTAG_BITPLANEKEY_SET	equ	$80000003
VTAG_BORDERBLANK_CLR	equ	$80000004
VTAG_BORDERBLANK_SET	equ	$80000005
VTAG_BORDERNOTRANS_CLR	equ	$80000006
VTAG_BORDERNOTRANS_SET	equ	$80000007
VTAG_CHROMA_PEN_CLR	equ	$80000008
VTAG_CHROMA_PEN_SET	equ	$80000009
VTAG_CHROMA_PLANE_SET	equ	$8000000A
VTAG_ATTACH_CM_SET	equ	$8000000B
VTAG_NEXTBUF_CM		equ	$8000000C
VTAG_BATCH_CM_CLR	equ	$8000000D
VTAG_BATCH_CM_SET	equ	$8000000E
VTAG_NORMAL_DISP_GET	equ	$8000000F
VTAG_NORMAL_DISP_SET	equ	$80000010
VTAG_COERCE_DISP_GET	equ	$80000011
VTAG_COERCE_DISP_SET	equ	$80000012
VTAG_VIEWPORTEXTRA_GET	equ	$80000013
VTAG_VIEWPORTEXTRA_SET	equ	$80000014
VTAG_CHROMAKEY_GET	equ	$80000015
VTAG_BITPLANEKEY_GET	equ	$80000016
VTAG_BORDERBLANK_GET	equ	$80000017
VTAG_BORDERNOTRANS_GET	equ	$80000018
VTAG_CHROMA_PEN_GET	equ	$80000019
VTAG_CHROMA_PLANE_GET	equ	$8000001A
VTAG_ATTACH_CM_GET	equ	$8000001B
VTAG_BATCH_CM_GET	equ	$8000001C
VTAG_BATCH_ITEMS_GET	equ	$8000001D
VTAG_BATCH_ITEMS_SET	equ	$8000001E
VTAG_BATCH_ITEMS_ADD	equ	$8000001F
VTAG_VPMODEID_GET	equ	$80000020
VTAG_VPMODEID_SET	equ	$80000021
VTAG_VPMODEID_CLR	equ	$80000022
VTAG_USERCLIP_GET	equ	$80000023
VTAG_USERCLIP_SET	equ	$80000024
VTAG_USERCLIP_CLR	equ	$80000025

    ENDC	; GRAPHICS_VIDEOCONTROL_I


Includes/graphics/display.h

#ifndef	GRAPHICS_DISPLAY_H
#define	GRAPHICS_DISPLAY_H
/*
**	$Filename: graphics/display.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**	include define file for display control registers
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

/* bplcon0 defines */
#define MODE_640    0x8000
#define PLNCNTMSK   0x7	    /* how many bit planes? */
                    /* 0 = none, 1->6 = 1->6, 7 = reserved */
#define PLNCNTSHFT  12		    /* bits to shift for bplcon0 */
#define PF2PRI	    0x40	    /* bplcon2 bit */
#define COLORON     0x0200	    /* disable color burst */
#define DBLPF	    0x400
#define HOLDNMODIFY 0x800
#define INTERLACE   4		    /* interlace mode for 400 */

/* bplcon1 defines */
#define PFA_FINE_SCROLL       0xF
#define PFB_FINE_SCROLL_SHIFT 4
#define PF_FINE_SCROLL_MASK   0xF

/* display window start and stop defines */
#define DIW_HORIZ_POS	0x7F	   /* horizontal start/stop */
#define DIW_VRTCL_POS	0x1FF	   /* vertical start/stop */
#define DIW_VRTCL_POS_SHIFT 7

/* Data fetch start/stop horizontal position */
#define DFTCH_MASK	0xFF

/* vposr bits */
#define VPOSRLOF	0x8000

#endif	/* GRAPHICS_DISPLAY_H */


Includes/graphics/gfxmacros.h

#ifndef	GRAPHICS_GFXMACROS_H
#define	GRAPHICS_GFXMACROS_H
/*
**	$Filename: graphics/gfxmacros.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef  GRAPHICS_RASTPORT_H
#include <graphics/rastport.h>
#endif

#define ON_DISPLAY	custom.dmacon = BITSET|DMAF_RASTER;
#define OFF_DISPLAY	custom.dmacon = BITCLR|DMAF_RASTER;
#define ON_SPRITE	custom.dmacon = BITSET|DMAF_SPRITE;
#define OFF_SPRITE	custom.dmacon = BITCLR|DMAF_SPRITE;

#define ON_VBLANK	custom.intena = BITSET|INTF_VERTB;
#define OFF_VBLANK	custom.intena = BITCLR|INTF_VERTB;

#define SetOPen(w,c)	{(w)->AOlPen = c;(w)->Flags |= AREAOUTLINE;}
#define SetDrPt(w,p)	{(w)->LinePtrn = p;(w)->Flags |= FRST_DOT;(w)->linpatcnt=15;}
#define SetWrMsk(w,m)	{(w)->Mask = m;}
#define SetAfPt(w,p,n)	{(w)->AreaPtrn = p;(w)->AreaPtSz = n;}

#define BNDRYOFF(w)	{(w)->Flags &= ~AREAOUTLINE;}

#define CINIT(c,n)	  UCopperListInit(c,n);
#define CMOVE(c,a,b)	{ CMove(c,&a,b);CBump(c); }
#define CWAIT(c,a,b)	{ CWait(c,a,b);CBump(c); }
#define CEND(c)	{ CWAIT(c,10000,255); }

#define DrawCircle(rp,cx,cy,r)	DrawEllipse(rp,cx,cy,r,r);
#define AreaCircle(rp,cx,cy,r)	AreaEllipse(rp,cx,cy,r,r);

#endif	/* GRAPHICS_GFXMACROS_H */


Includes/graphics/regions.h

#ifndef	GRAPHICS_REGIONS_H
#define	GRAPHICS_REGIONS_H
/*
**	$Filename: graphics/regions.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef GRAPHICS_GFX_H
#include <graphics/gfx.h>
#endif

struct RegionRectangle
{
    struct RegionRectangle *Next,*Prev;
    struct Rectangle bounds;
};

struct Region
{
    struct Rectangle bounds;
    struct RegionRectangle *RegionRectangle;
};

#endif	/* GRAPHICS_REGIONS_H */


Includes/graphics/view.h

#ifndef GRAPHICS_VIEW_H
#define GRAPHICS_VIEW_H
/*
**	$Filename: graphics/view.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**	graphics view/viewport definintions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#define ECS_SPECIFIC

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef GRAPHICS_GFX_H
#include <graphics/gfx.h>
#endif

#ifndef GRAPHICS_COPPER_H
#include <graphics/copper.h>
#endif

#ifndef GRAPHICS_GFXNODES_H
#include <graphics/gfxnodes.h>
#endif

#ifndef GRAPHICS_MONITOR_H
#include <graphics/monitor.h>
#endif

#ifndef HARDWARE_CUSTOM_H
#include <hardware/custom.h>
#endif

struct ViewPort
{
   struct   ViewPort *Next;
   struct   ColorMap  *ColorMap;    /* table of colors for this viewport */
          /* if this is nil, MakeVPort assumes default values */
   struct   CopList  *DspIns;	    /* user by MakeView() */
   struct   CopList  *SprIns;	    /* used by sprite stuff */
   struct   CopList  *ClrIns;	    /* used by sprite stuff */
   struct   UCopList *UCopIns;	    /* User copper list */
   WORD    DWidth,DHeight;
   WORD    DxOffset,DyOffset;
   UWORD    Modes;
   UBYTE	SpritePriorities;		/* used by makevp */
   UBYTE	ExtendedModes;
   struct   RasInfo *RasInfo;
};

struct View
{
   struct ViewPort *ViewPort;
   struct cprlist *LOFCprList;	 /* used for interlaced and noninterlaced */
   struct cprlist *SHFCprList;	 /* only used during interlace */
   WORD DyOffset,DxOffset;   /* for complete View positioning */
                  /* offsets are +- adjustments to standard #s */
   UWORD   Modes;	      /* such as INTERLACE, GENLOC */
};

/* these structures are obtained via GfxNew */
/* and disposed by GfxFree */
struct ViewExtra
{
    struct ExtendedNode n;
    struct View *View;	 /* backwards link */
    struct MonitorSpec *Monitor; /* monitors for this view */
};

/* this structure is obtained via GfxNew */
/* and disposed by GfxFree */
struct ViewPortExtra
{
    struct ExtendedNode n;
    struct ViewPort *ViewPort;	/* backwards link */
    struct Rectangle DisplayClip;  /* makevp display clipping information */
};

#define EXTEND_VSTRUCT	0x1000	/* unused bit in Modes field of View */

/* defines used for Modes in IVPargs */

#define GENLOCK_VIDEO	0x0002
#define LACE		0x0004
#define SUPERHIRES	0x0020
#define PFBA		0x0040
#define EXTRA_HALFBRITE 0x0080
#define GENLOCK_AUDIO	0x0100
#define DUALPF		0x0400
#define HAM		0x0800
#define EXTENDED_MODE	0x1000
#define VP_HIDE	0x2000
#define SPRITES	0x4000
#define HIRES		0x8000

#define VPF_A2024		0x40
#define VPF_AGNUS		0x20
#define VPF_TENHZ		0x20

struct RasInfo	/* used by callers to and InitDspC() */
{
   struct   RasInfo *Next;	    /* used for dualpf */
   struct   BitMap *BitMap;
   WORD    RxOffset,RyOffset;	   /* scroll offsets in this BitMap */
};

struct ColorMap
{
    UBYTE	Flags;
    UBYTE	Type;
    UWORD	Count;
    APTR	ColorTable;
    struct	ViewPortExtra *cm_vpe;
    UWORD	*TransparencyBits;
    UBYTE	TransparencyPlane;
    UBYTE	reserved1;
    UWORD	reserved2;
    struct	ViewPort *cm_vp;
    APTR	NormalDisplayInfo;
    APTR	CoerceDisplayInfo;
    struct	TagItem *cm_batch_items;
    ULONG	VPModeID;
};

/* if Type == 0 then ColorMap is V1.2/V1.3 compatible */
/* if Type != 0 then ColorMap is V36	   compatible */

#define COLORMAP_TYPE_V1_2	0x00
#define COLORMAP_TYPE_V1_4	0x01
#define COLORMAP_TYPE_V36 COLORMAP_TYPE_V1_4	/* use this definition */

/* Flags variable */
#define COLORMAP_TRANSPARENCY	0x01
#define COLORPLANE_TRANSPARENCY	0x02
#define BORDER_BLANKING		0x04
#define BORDER_NOTRANSPARENCY	0x08
#define VIDEOCONTROL_BATCH	0x10
#define USER_COPPER_CLIP	0x20

#endif	/* GRAPHICS_VIEW_H */


Includes/graphics/display.i

    IFND	GRAPHICS_DISPLAY_I
GRAPHICS_DISPLAY_I	SET	1
**
**	$Filename: graphics/display.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**	include define file for display control registers
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

* bplcon0 defines
MODE_640    equ   $8000
PLNCNTMSK   equ   $7		    * how many bit planes?
*				    * 0 = none, 1->6 = 1->6, 7 = reserved
PLNCNTSHFT  equ   12		    * bits to shift for bplcon0
PF2PRI	    equ   $40		    * bplcon2 bit
COLORON     equ   $0200	    * disable color burst
DBLPF	    equ   $400
HOLDNMODIFY equ   $800
INTERLACE   equ   4		    * interlace mode for 400

* bplcon1 defines
PFA_FINE_SCROLL       equ   $F
PFB_FINE_SCROLL_SHIFT equ   4
PF_FINE_SCROLL_MASK   equ   $F

* display window start and stop defines
DIW_HORIZ_POS	      equ   $7F     * horizontal start/stop
DIW_VRTCL_POS	      equ   $1FF    * vertical start/stop
DIW_VRTCL_POS_SHIFT   equ   7

* Data fetch start/stop horizontal position
DFTCH_MASK	      equ   $FF

* vposr bits
VPOSRLOF	      equ   $8000

    ENDC	; GRAPHICS_DISPLAY_I


Includes/graphics/gfxnodes.h

#ifndef	GRAPHICS_GFXNODES_H
#define	GRAPHICS_GFXNODES_H
/*
**	$Filename: graphics/gfxnodes.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**	graphics extended node definintions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_NODES_H
#include <exec/nodes.h>
#endif

struct	ExtendedNode	{
struct	Node	*xln_Succ;
struct	Node	*xln_Pred;
UBYTE	xln_Type;
BYTE	xln_Pri;
char	*xln_Name;
UBYTE	xln_Subsystem;
UBYTE	xln_Subtype;
LONG	xln_Library;
LONG	(*xln_Init)();
};

#define SS_GRAPHICS	0x02

#define	VIEW_EXTRA_TYPE		1
#define	VIEWPORT_EXTRA_TYPE	2
#define	SPECIAL_MONITOR_TYPE	3
#define	MONITOR_SPEC_TYPE	4

#endif	/* GRAPHICS_GFXNODES_H */


Includes/graphics/regions.i

    IFND	GRAPHICS_REGIONS_I
GRAPHICS_REGIONS_I	SET	1
**
**	$Filename: graphics/regions.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND    EXEC_TYPES_I
    include 'exec/types.i'
    ENDC

   IFND  GRAPHICS_GFX_I
   include  "graphics/gfx.i"
   ENDC

    STRUCTURE	Region,0
      STRUCT   rg_bounds,ra_SIZEOF
      APTR  rg_RegionRectangle
   LABEL    rg_SIZEOF

   STRUCTURE   RegionRectangle,0
      APTR  rr_Next
      APTR  rr_Prev
      STRUCT   rr_bounds,ra_SIZEOF
   LABEL    rr_SIZEOF

    ENDC	; GRAPHICS_REGIONS_I


Includes/graphics/view.i

    IFND    GRAPHICS_VIEW_I
GRAPHICS_VIEW_I SET 1
**
**	$Filename: graphics/view.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**	graphics view/viewport definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND    EXEC_TYPES_I
    include 'exec/types.i'
    ENDC

    IFND    GRAPHICS_GFX_I
    include 'graphics/gfx.i'
    ENDC

    IFND    GRAPHICS_COPPER_I
    include 'graphics/copper.i'
    ENDC

    IFND    GRAPHICS_GFXNODES_I
    include 'graphics/gfxnodes.i'
    ENDC

GENLOCK_VIDEO		EQU	$2
V_LACE			EQU	$4
V_SUPERHIRES		EQU	$20
V_PFBA			EQU	$40
V_EXTRA_HALFBRITE	EQU	$80
GENLOCK_AUDIO		EQU	$100
V_DUALPF		EQU	$400
V_HAM			EQU	$800
V_EXTENDED_MODE	EQU	$1000
V_VP_HIDE		EQU	$2000
V_SPRITES		EQU	$4000
V_HIRES		EQU	$8000

EXTEND_VSTRUCT		EQU	$1000

VPF_DENISE	EQU	$80
VPF_A2024	EQU	$40
VPF_AGNUS	EQU	$20
VPF_TENHZ	EQU	$20
VPF_ILACE	EQU	$10

   STRUCTURE   ColorMap,0
    BYTE	cm_Flags
    BYTE	cm_Type
    WORD	cm_Count
    APTR	cm_ColorTable
    APTR	cm_vpe
    APTR	cm_TransparencyBits
    BYTE	cm_TransparenyPlane
    BYTE	cm_reserved1
    WORD	cm_reserved2
    APTR	cm_vp
    APTR	cm_NormalDisplayInfo
    APTR	cm_CoerceDisplayInfo
    APTR	cm_batch_items
    LONG	cm_VPModeID
   LABEL cm_SIZEOF

COLORMAP_TYPE_V1_2	EQU	$00
COLORMAP_TYPE_V1_4	EQU	$01
COLORMAP_TYPE_V36 EQU COLORMAP_TYPE_V1_4	; use this definition

COLORMAP_TRANSPARENCY	EQU	$01
COLORPLANE_TRANSPARENCY EQU	$02
BORDER_BLANKING		EQU	$04
BORDER_NOTRANSPARENCY	EQU	$08
VIDEOCONTROL_BATCH	EQU	$10
USER_COPPER_CLIP	EQU	$20

   STRUCTURE	  ViewPort,0
   LONG    vp_Next
   LONG    vp_ColorMap
   LONG    vp_DspIns
   LONG    vp_SprIns
   LONG    vp_ClrIns
   LONG    vp_UCopIns
   WORD    vp_DWidth
   WORD    vp_DHeight
   WORD    vp_DxOffset
   WORD    vp_DyOffset
   WORD    vp_Modes
   BYTE    vp_SpritePriorities
   BYTE    vp_ExtendedModes
   APTR    vp_RasInfo
   LABEL   vp_SIZEOF

   STRUCTURE View,0
   LONG    v_ViewPort
   LONG    v_LOFCprList
   LONG    v_SHFCprList
   WORD    v_DyOffset
   WORD    v_DxOffset
   WORD    v_Modes
   LABEL   v_SIZEOF

   STRUCTURE ViewExtra,XLN_SIZE
   APTR    ve_View
   APTR    ve_Monitor
   LABEL   ve_SIZEOF

   STRUCTURE ViewPortExtra,XLN_SIZE
   APTR    vpe_ViewPort
   STRUCT  vpe_DisplayClip,ra_SIZEOF
   LABEL   vpe_SIZEOF

   STRUCTURE  collTable,0
   LONG    cp_collPtrs,16
   LABEL   cp_SIZEOF

   STRUCTURE  RasInfo,0
   APTR    ri_Next
   LONG    ri_BitMap
   WORD    ri_RxOffset
   WORD    ri_RyOffset
   LABEL   ri_SIZEOF

    ENDC	; GRAPHICS_VIEW_I


Includes/graphics/displayinfo.h

#ifndef	GRAPHICS_DISPLAYINFO_H
#define	GRAPHICS_DISPLAYINFO_H
/*
**	$Filename: graphics/displayinfo.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.6 $
**	$Date: 91/11/08 $
**
**	include define file for displayinfo database
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif /* EXEC_TYPES_H */

#ifndef GRAPHICS_GFX_H
#include <graphics/gfx.h>
#endif /* GRAPHICS_GFX_H */

#ifndef GRAPHICS_MONITOR_H
#include <graphics/monitor.h>
#endif /* GRAPHICS_MONITOR_H */

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif /* UTILITY_TAGITEM_H */

/* the "public" handle to a DisplayInfoRecord */

typedef APTR DisplayInfoHandle;

/* datachunk type identifiers */

#define DTAG_DISP		0x80000000
#define DTAG_DIMS		0x80001000
#define DTAG_MNTR		0x80002000
#define DTAG_NAME		0x80003000

struct QueryHeader
{
    ULONG	StructID;	/* datachunk type identifier */
    ULONG	DisplayID;	/* copy of display record key	*/
    ULONG	SkipID;		/* TAG_SKIP -- see tagitems.h */
    ULONG	Length;		/* length of local data in double-longwords */
};

struct DisplayInfo
{
    struct	QueryHeader Header;
    UWORD	NotAvailable;	/* if NULL available, else see defines */
    ULONG	PropertyFlags;	/* Properties of this mode see defines */
    Point	Resolution;	/* ticks-per-pixel X/Y		       */
    UWORD	PixelSpeed;	/* aproximation in nanoseconds	       */
    UWORD	NumStdSprites;	/* number of standard amiga sprites    */
    UWORD	PaletteRange;	/* distinguishable shades available    */
    Point	SpriteResolution; /* std sprite ticks-per-pixel X/Y    */
    UBYTE	pad[4];
    ULONG	reserved[2];	/* terminator */
};

/* availability */

#define DI_AVAIL_NOCHIPS	0x0001
#define DI_AVAIL_NOMONITOR	0x0002
#define DI_AVAIL_NOTWITHGENLOCK 0x0004

/* mode properties */

#define DIPF_IS_LACE		0x00000001
#define DIPF_IS_DUALPF		0x00000002
#define DIPF_IS_PF2PRI		0x00000004
#define DIPF_IS_HAM		0x00000008

#define DIPF_IS_ECS		0x00000010	/*	note: ECS modes (SHIRES, VGA, and **
                                            **	PRODUCTIVITY) do not support	  **
                                            **	attached sprites.		  **
                                            */
#define DIPF_IS_PAL		0x00000020
#define DIPF_IS_SPRITES	0x00000040
#define DIPF_IS_GENLOCK	0x00000080

#define DIPF_IS_WB		0x00000100
#define DIPF_IS_DRAGGABLE	0x00000200
#define DIPF_IS_PANELLED	0x00000400
#define DIPF_IS_BEAMSYNC	0x00000800

#define DIPF_IS_EXTRAHALFBRITE	0x00001000

struct DimensionInfo
{
    struct	QueryHeader Header;
    UWORD	MaxDepth;	      /* log2( max number of colors ) */
    UWORD	MinRasterWidth;       /* minimum width in pixels      */
    UWORD	MinRasterHeight;      /* minimum height in pixels     */
    UWORD	MaxRasterWidth;       /* maximum width in pixels      */
    UWORD	MaxRasterHeight;      /* maximum height in pixels     */
    struct	Rectangle   Nominal;  /* "standard" dimensions	      */
    struct	Rectangle   MaxOScan; /* fixed, hardware dependant    */
    struct	Rectangle VideoOScan; /* fixed, hardware dependant    */
    struct	Rectangle   TxtOScan; /* editable via preferences     */
    struct	Rectangle   StdOScan; /* editable via preferences     */
    UBYTE	pad[14];
    ULONG	reserved[2];	      /* terminator */
};

struct MonitorInfo
{
    struct	QueryHeader Header;
    struct	MonitorSpec  *Mspc;   /* pointer to monitor specification  */
    Point	ViewPosition;	      /* editable via preferences	   */
    Point	ViewResolution;       /* standard monitor ticks-per-pixel  */
    struct	Rectangle ViewPositionRange;  /* fixed, hardware dependant */
    UWORD	TotalRows;	      /* display height in scanlines	   */
    UWORD	TotalColorClocks;     /* scanline width in 280 ns units    */
    UWORD	MinRow;	      /* absolute minimum active scanline  */
    WORD	Compatibility;	      /* how this coexists with others	   */
    UBYTE	pad[36];
        Point	DefaultViewPosition;  /* original, never changes */
        ULONG	PreferredModeID;      /* for Preferences */
    ULONG	reserved[2];	      /* terminator */
};

/* monitor compatibility */

#define MCOMPAT_MIXED	0	/* can share display with other MCOMPAT_MIXED */
#define MCOMPAT_SELF	1	/* can share only within same monitor */
#define MCOMPAT_NOBODY -1	/* only one viewport at a time */

#define DISPLAYNAMELEN 32

struct NameInfo
{
    struct	QueryHeader Header;
    UBYTE	Name[DISPLAYNAMELEN];
    ULONG	reserved[2];	      /* terminator */
};

/* DisplayInfoRecord identifiers */

#define INVALID_ID		~0

/* normal identifiers */

#define MONITOR_ID_MASK		0xFFFF1000

#define DEFAULT_MONITOR_ID		0x00000000
#define NTSC_MONITOR_ID		0x00011000
#define PAL_MONITOR_ID			0x00021000

/* the following 20 composite keys are for Modes on the default Monitor */
/* ntsc & pal "flavors" of these particular keys may be made by or'ing	*/
/* the ntsc or pal MONITOR_ID with the desired MODE_KEY... */

#define LORES_KEY			0x00000000
#define HIRES_KEY			0x00008000
#define SUPER_KEY			0x00008020
#define HAM_KEY			0x00000800
#define LORESLACE_KEY			0x00000004
#define HIRESLACE_KEY			0x00008004
#define SUPERLACE_KEY			0x00008024
#define HAMLACE_KEY			0x00000804
#define LORESDPF_KEY			0x00000400
#define HIRESDPF_KEY			0x00008400
#define SUPERDPF_KEY			0x00008420
#define LORESLACEDPF_KEY		0x00000404
#define HIRESLACEDPF_KEY		0x00008404
#define SUPERLACEDPF_KEY		0x00008424
#define LORESDPF2_KEY			0x00000440
#define HIRESDPF2_KEY			0x00008440
#define SUPERDPF2_KEY			0x00008460
#define LORESLACEDPF2_KEY		0x00000444
#define HIRESLACEDPF2_KEY		0x00008444
#define SUPERLACEDPF2_KEY		0x00008464
#define EXTRAHALFBRITE_KEY		0x00000080
#define EXTRAHALFBRITELACE_KEY		0x00000084

/* vga identifiers */

#define VGA_MONITOR_ID			0x00031000

#define VGAEXTRALORES_KEY		0x00031004
#define VGALORES_KEY			0x00039004
#define VGAPRODUCT_KEY			0x00039024
#define VGAHAM_KEY			0x00031804
#define VGAEXTRALORESLACE_KEY		0x00031005
#define VGALORESLACE_KEY		0x00039005
#define VGAPRODUCTLACE_KEY		0x00039025
#define VGAHAMLACE_KEY			0x00031805
#define VGAEXTRALORESDPF_KEY		0x00031404
#define VGALORESDPF_KEY		0x00039404
#define VGAPRODUCTDPF_KEY		0x00039424
#define VGAEXTRALORESLACEDPF_KEY	0x00031405
#define VGALORESLACEDPF_KEY		0x00039405
#define VGAPRODUCTLACEDPF_KEY		0x00039425
#define VGAEXTRALORESDPF2_KEY		0x00031444
#define VGALORESDPF2_KEY		0x00039444
#define VGAPRODUCTDPF2_KEY		0x00039464
#define VGAEXTRALORESLACEDPF2_KEY	0x00031445
#define VGALORESLACEDPF2_KEY		0x00039445
#define VGAPRODUCTLACEDPF2_KEY		0x00039465
#define VGAEXTRAHALFBRITE_KEY		0x00031084
#define VGAEXTRAHALFBRITELACE_KEY	0x00031085

/* a2024 identifiers */

#define A2024_MONITOR_ID		0x00041000

#define A2024TENHERTZ_KEY		0x00041000
#define A2024FIFTEENHERTZ_KEY		0x00049000

/* prototype identifiers */

#define PROTO_MONITOR_ID		0x00051000

#endif	/* GRAPHICS_DISPLAYINFO_H */


Includes/graphics/gfxnodes.i

    IFND	GRAPHICS_GFXNODES_I
GRAPHICS_GFXNODES_I	EQU	1
**
**	$Filename: graphics/gfxnodes.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**	graphics extended node definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND    EXEC_TYPES_I
    include 'exec/types.i'
    ENDC

    STRUCTURE	XLN,0
    APTR	XLN_SUCC
    APTR	XLN_PRED
    UBYTE	XLN_TYPE
    BYTE	XLN_PRI
    APTR	XLN_NAME
    UBYTE	XLN_SUBSYSTEM
    UBYTE	XLN_SUBTYPE
    LONG	XLN_LIBRARY
    LONG	XLN_INIT
    LABEL	XLN_SIZE

SS_GRAPHICS	EQU	$02

VIEW_EXTRA_TYPE		EQU	1
VIEWPORT_EXTRA_TYPE	EQU	2
SPECIAL_MONITOR_TYPE	EQU	3
MONITOR_SPEC_TYPE	EQU	4

    ENDC	; GRAPHICS_GFXNODES_I


Includes/graphics/scale.h

#ifndef	GRAPHICS_SCALE_H
#define	GRAPHICS_SCALE_H
/*
**	$Filename: graphics/scale.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**	structure argument to BitMapScale()
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

struct BitScaleArgs {
    UWORD   bsa_SrcX, bsa_SrcY;			/* source origin */
    UWORD   bsa_SrcWidth, bsa_SrcHeight;	/* source size */
    UWORD   bsa_XSrcFactor, bsa_YSrcFactor;	/* scale factor denominators */
    UWORD   bsa_DestX, bsa_DestY;		/* destination origin */
    UWORD   bsa_DestWidth, bsa_DestHeight;	/* destination size result */
    UWORD   bsa_XDestFactor, bsa_YDestFactor;	/* scale factor numerators */
    struct BitMap *bsa_SrcBitMap;		/* source BitMap */
    struct BitMap *bsa_DestBitMap;		/* destination BitMap */
    ULONG   bsa_Flags;				/* reserved.  Must be zero! */
    UWORD   bsa_XDDA, bsa_YDDA;			/* reserved */
    LONG    bsa_Reserved1;
    LONG    bsa_Reserved2;
};
#endif	/* GRAPHICS_SCALE_H */


Includes/graphics/displayinfo.i

    IFND	GRAPHICS_DISPLAYINFO_I
GRAPHICS_DISPLAYINFO_I	SET	1
**
**	$Filename: graphics/displayinfo.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.7 $
**	$Date: 91/11/08 $
**
**	include define file for display control registers
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND	EXEC_TYPES_I
    include 'exec/types.i'
    ENDC

    IFND	GRAPHICS_GFX_I
    include 'graphics/gfx.i'
    ENDC

    IFND	GRAPHICS_MONITOR_I
    include 'graphics/monitor.i'
    ENDC

    IFND	UTILITY_TAGITEM_I
    include 'utility/tagitem.i'
    ENDC

* datachunk type identifiers

DTAG_DISP	equ		  $80000000
DTAG_DIMS	equ		  $80001000
DTAG_MNTR	equ		  $80002000
DTAG_NAME	equ		  $80003000

    STRUCTURE	QueryHeader,0
    ULONG	qh_StructID	; datachunk type identifier
    ULONG	qh_DisplayID	; copy of display record key
    ULONG	qh_SkipID	; TAG_SKIP -- see tagitems.h
    ULONG	qh_Length	; length of data in double-longwords
    LABEL qh_SIZEOF

    STRUCTURE	DisplayInfo,qh_SIZEOF
    UWORD	dis_NotAvailable	  ; if NULL available, else see defines
    ULONG	dis_PropertyFlags	  ; Properties of this mode see defines
    STRUCT	dis_Resolution,tpt_SIZEOF ; ticks-per-pixel X/Y
    UWORD	dis_PixelSpeed		  ; aproximation in nanoseconds
    UWORD	dis_NumStdSprites	  ; number of standard amiga sprites
    UWORD	dis_PaletteRange	  ; distinguishable shades available
    STRUCT	dis_SpriteResolution,tpt_SIZEOF ; sprite ticks-per-pixel X/Y
    STRUCT	dis_pad,4
    STRUCT	dis_reserved,8		  ; terminator
    LABEL dis_SIZEOF

* availability

DI_AVAIL_NOCHIPS	equ	$0001
DI_AVAIL_NOMONITOR	equ	$0002
DI_AVAIL_NOTWITHGENLOCK	equ	$0004

* mode properties

DIPF_IS_LACE		equ	$00000001
DIPF_IS_DUALPF		equ	$00000002
DIPF_IS_PF2PRI		equ	$00000004
DIPF_IS_HAM		equ	$00000008

DIPF_IS_ECS		equ	$00000010	;*	note: ECS modes (SHIRES, VGA, and **
*								;*	PRODUCTIVITY) do not support	  **
*								;*	attached sprites.		  **
DIPF_IS_PAL		equ	$00000020
DIPF_IS_SPRITES		equ	$00000040
DIPF_IS_GENLOCK		equ	$00000080

DIPF_IS_WB		equ	$00000100
DIPF_IS_DRAGGABLE	equ	$00000200
DIPF_IS_PANELLED	equ	$00000400
DIPF_IS_BEAMSYNC	equ	$00000800

DIPF_IS_EXTRAHALFBRITE equ	$00001000

    STRUCTURE DimensionInfo,qh_SIZEOF
    UWORD	dim_MaxDepth		; log2( max number of colors
    UWORD	dim_MinRasterWidth	; minimum width in pixels
    UWORD	dim_MinRasterHeight	; minimum height in pixels
    UWORD	dim_MaxRasterWidth	; maximum width in pixels
    UWORD	dim_MaxRasterHeight	; maximum height in pixels
    STRUCT	dim_Nominal,ra_SIZEOF	; "standard" dimensions
    STRUCT	dim_MaxOScan,ra_SIZEOF	; fixed, hardware dependant
    STRUCT	dim_VideoOScan,ra_SIZEOF ; fixed, hardware dependant
    STRUCT	dim_TxtOScan,ra_SIZEOF	; editable via preferences
    STRUCT	dim_StdOScan,ra_SIZEOF	; editable via preferences
    STRUCT	dim_pad,14
    STRUCT	dim_reserved,8		; terminator
    LABEL dim_SIZEOF

    STRUCTURE MonitorInfo,qh_SIZEOF
    APTR	mtr_Mspc		; pointer to monitor specification
    STRUCT	mtr_ViewPosition,tpt_SIZEOF	; editable via preferences
    STRUCT	mtr_ViewResolution,tpt_SIZEOF	; monitor ticks-per-pixel
    STRUCT	mtr_ViewPositionRange,ra_SIZEOF	; fixed, hardware dependant
    UWORD	mtr_TotalRows		; display height in scanlines
    UWORD	mtr_TotalColorClocks	; scanline width in 280 ns units
    UWORD	mtr_MinRow		; absolute minimum active scanline
    WORD	mtr_Compatibility	; how this coexists with others
    STRUCT	mtr_pad,36
    STRUCT	mtr_DefaultViewPosition,tpt_SIZEOF	; original, never changes
    ULONG	mtr_PreferredModeID				; for preferences
    STRUCT	mtr_reserved,8		; terminator
    LABEL mtr_SIZEOF

* monitor compatibility

MCOMPAT_MIXED		equ  0	; can share display with other MCOMPAT_MIXED
MCOMPAT_SELF		equ  1	; can share only within same monitor
MCOMPAT_NOBODY		equ -1	; only one viewport at a time

DISPLAYNAMELEN		equ 32

    STRUCTURE NameInfo,qh_SIZEOF
    STRUCT	nif_Name,DISPLAYNAMELEN
    STRUCT	nif_reserved,8		; terminator
    LABEL nif_SIZEOF

* DisplayInfoRecord identifiers

INVALID_ID		equ	-1

*normal identifiers

MONITOR_ID_MASK		equ	$FFFF1000

DEFAULT_MONITOR_ID	equ	$00000000
NTSC_MONITOR_ID		equ	$00011000
PAL_MONITOR_ID		equ	$00021000

* the following 20 composite keys are for Modes on the default Monitor
* ntsc & pal "flavors" of these particular keys may be made by or'ing
* the ntsc or pal MONITOR_ID with the desired MODE_KEY...

LORES_KEY		equ	$00000000
HIRES_KEY		equ	$00008000
SUPER_KEY		equ	$00008020
HAM_KEY			equ	$00000800
LORESLACE_KEY		equ	$00000004
HIRESLACE_KEY		equ	$00008004
SUPERLACE_KEY		equ	$00008024
HAMLACE_KEY		equ	$00000804
LORESDPF_KEY		equ	$00000400
HIRESDPF_KEY		equ	$00008400
SUPERDPF_KEY		equ	$00008420
LORESLACEDPF_KEY	equ	$00000404
HIRESLACEDPF_KEY	equ	$00008404
SUPERLACEDPF_KEY	equ	$00008424
LORESDPF2_KEY		equ	$00000440
HIRESDPF2_KEY		equ	$00008440
SUPERDPF2_KEY		equ	$00008460
LORESLACEDPF2_KEY	equ	$00000444
HIRESLACEDPF2_KEY	equ	$00008444
SUPERLACEDPF2_KEY	equ	$00008464
EXTRAHALFBRITE_KEY	equ	$00000080
EXTRAHALFBRITELACE_KEY	equ	$00000084

* vga identifiers

VGA_MONITOR_ID		equ	$00031000

VGAEXTRALORES_KEY	equ	$00031004
VGALORES_KEY		equ	$00039004
VGAPRODUCT_KEY 		equ	$00039024
VGAHAM_KEY		equ	$00031804
VGAEXTRALORESLACE_KEY	equ	$00031005
VGALORESLACE_KEY	equ	$00039005
VGAPRODUCTLACE_KEY	equ	$00039025
VGAHAMLACE_KEY		equ	$00031805
VGAEXTRALORESDPF_KEY	equ	$00031404
VGALORESDPF_KEY		equ	$00039404
VGAPRODUCTDPF_KEY	equ	$00039424
VGAEXTRALORESLACEDPF_KEY equ	$00031405
VGALORESLACEDPF_KEY	equ	$00039405
VGAPRODUCTLACEDPF_KEY	equ	$00039425
VGAEXTRALORESDPF2_KEY	equ	$00031444
VGALORESDPF2_KEY	equ	$00039444
VGAPRODUCTDPF2_KEY	equ	$00039464
VGAEXTRALORESLACEDPF2_KEY equ	$00031445
VGALORESLACEDPF2_KEY	equ	$00039445
VGAPRODUCTLACEDPF2_KEY	equ	$00039465
VGAEXTRAHALFBRITE_KEY	equ	$00031084
VGAEXTRAHALFBRITELACE_KEY equ	$00031085

* a2024 identifiers

A2024_MONITOR_ID	equ	$00041000

A2024TENHERTZ_KEY 	equ	$00041000
A2024FIFTEENHERTZ_KEY   equ	$00049000

* prototype identifiers

PROTO_MONITOR_ID	equ	$00051000

    ENDC	; GRAPHICS_DISPLAYINFO_I


Includes/graphics/graphint.h

#ifndef	GRAPHICS_GRAPHINT_H
#define	GRAPHICS_GRAPHINT_H
/*
**	$Filename: graphics/graphint.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_NODES_H
#include <exec/nodes.h>
#endif

/* structure used by AddTOFTask */
struct Isrvstr
{
    struct Node is_Node;
    struct Isrvstr *Iptr;   /* passed to srvr by os */
    int (*code)();
    int (*ccode)();
    int Carg;
};

#endif	/* GRAPHICS_GRAPHINT_H */


Includes/graphics/scale.i

    IFND	GRAPHICS_SCALE_I
GRAPHICS_SCALE_I	SET	1
**
**	$Filename: graphics/scale.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**	structure argument to BitMapScale()
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND    EXEC_TYPES_I
    include 'exec/types.i'
    ENDC

 STRUCTURE	BitScaleArgs,0
    UWORD   bsa_SrcX		; source origin
    UWORD   bsa_SrcY
    UWORD   bsa_SrcWidth	; source size
    UWORD   bsa_SrcHeight
    UWORD   bsa_XSrcFactor	; scale factor denominators
    UWORD   bsa_YSrcFactor
    UWORD   bsa_DestX		; destination origin
    UWORD   bsa_DestY
    UWORD   bsa_DestWidth	; destination size result
    UWORD   bsa_DestHeight
    UWORD   bsa_XDestFactor	; scale factor numerators
    UWORD   bsa_YDestFactor
    APTR    bsa_SrcBitMap	; source BitMap
    APTR    bsa_DestBitMap	; destination BitMap
    ULONG   bsa_Flags		; reserved.  Must be zero!
    UWORD   bsa_XDDA		; reserved
    UWORD   bsa_YDDA
    LONG    bsa_Reserved1
    LONG    bsa_Reserved2
    LABEL   bsa_SIZEOF

    ENDC	; GRAPHICS_SCALE_I


Includes/graphics/gels.h

#ifndef	GRAPHICS_GELS_H
#define	GRAPHICS_GELS_H
/*
**	$Filename: graphics/gels.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**	include file for AMIGA GELS (Graphics Elements)
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

/* VSprite flags */
/* user-set VSprite flags: */
#define SUSERFLAGS  0x00FF    /* mask of all user-settable VSprite-flags */
#define VSPRITE     0x0001    /* set if VSprite, clear if Bob */
#define SAVEBACK    0x0002    /* set if background is to be saved/restored */
#define OVERLAY     0x0004    /* set to mask image of Bob onto background */
#define MUSTDRAW    0x0008    /* set if VSprite absolutely must be drawn */
/* system-set VSprite flags: */
#define BACKSAVED   0x0100    /* this Bob's background has been saved */
#define BOBUPDATE   0x0200    /* temporary flag, useless to outside world */
#define GELGONE     0x0400    /* set if gel is completely clipped (offscreen) */
#define VSOVERFLOW  0x0800    /* VSprite overflow (if MUSTDRAW set we draw!) */

/* Bob flags */
/* these are the user flag bits */
#define BUSERFLAGS  0x00FF    /* mask of all user-settable Bob-flags */
#define SAVEBOB     0x0001    /* set to not erase Bob */
#define BOBISCOMP   0x0002    /* set to identify Bob as AnimComp */
/* these are the system flag bits */
#define BWAITING    0x0100    /* set while Bob is waiting on 'after' */
#define BDRAWN	    0x0200    /* set when Bob is drawn this DrawG pass*/
#define BOBSAWAY    0x0400    /* set to initiate removal of Bob */
#define BOBNIX	    0x0800    /* set when Bob is completely removed */
#define SAVEPRESERVE 0x1000   /* for back-restore during double-buffer*/
#define OUTSTEP     0x2000    /* for double-clearing if double-buffer */

/* defines for the animation procedures */
#define ANFRACSIZE  6
#define ANIMHALF    0x0020
#define RINGTRIGGER 0x0001

/* UserStuff definitions
 *  the user can define these to be a single variable or a sub-structure
 *  if undefined by the user, the system turns these into innocuous variables
 *  see the manual for a thorough definition of the UserStuff definitions
 *
 */
#ifndef VUserStuff	      /* VSprite user stuff */
#define VUserStuff WORD
#endif

#ifndef BUserStuff	      /* Bob user stuff */
#define BUserStuff WORD
#endif

#ifndef AUserStuff	      /* AnimOb user stuff */
#define AUserStuff WORD
#endif

/*********************** GEL STRUCTURES ***********************************/

struct VSprite
{
/* --------------------- SYSTEM VARIABLES ------------------------------- */
/* GEL linked list forward/backward pointers sorted by y,x value */
    struct VSprite   *NextVSprite;
    struct VSprite   *PrevVSprite;

/* GEL draw list constructed in the order the Bobs are actually drawn, then
 *  list is copied to clear list
 *  must be here in VSprite for system boundary detection
 */
    struct VSprite   *DrawPath;     /* pointer of overlay drawing */
    struct VSprite   *ClearPath;    /* pointer for overlay clearing */

/* the VSprite positions are defined in (y,x) order to make sorting
 *  sorting easier, since (y,x) as a long integer
 */
    WORD OldY, OldX;	      /* previous position */

/* --------------------- COMMON VARIABLES --------------------------------- */
    WORD Flags;	      /* VSprite flags */

/* --------------------- USER VARIABLES ----------------------------------- */
/* the VSprite positions are defined in (y,x) order to make sorting
 *  sorting easier, since (y,x) as a long integer
 */
    WORD Y, X;		      /* screen position */

    WORD Height;
    WORD Width;	      /* number of words per row of image data */
    WORD Depth;	      /* number of planes of data */

    WORD MeMask;	      /* which types can collide with this VSprite*/
    WORD HitMask;	      /* which types this VSprite can collide with*/

    WORD *ImageData;	      /* pointer to VSprite image */

/* borderLine is the one-dimensional logical OR of all
 *  the VSprite bits, used for fast collision detection of edge
 */
    WORD *BorderLine;	      /* logical OR of all VSprite bits */
    WORD *CollMask;	      /* similar to above except this is a matrix */

/* pointer to this VSprite's color definitions (not used by Bobs) */
    WORD *SprColors;

    struct Bob *VSBob;	      /* points home if this VSprite is part of
                   a Bob */

/* planePick flag:  set bit selects a plane from image, clear bit selects
 *  use of shadow mask for that plane
 * OnOff flag: if using shadow mask to fill plane, this bit (corresponding
 *  to bit in planePick) describes whether to fill with 0's or 1's
 * There are two uses for these flags:
 *	- if this is the VSprite of a Bob, these flags describe how the Bob
 *	  is to be drawn into memory
 *	- if this is a simple VSprite and the user intends on setting the
 *	  MUSTDRAW flag of the VSprite, these flags must be set too to describe
 *	  which color registers the user wants for the image
 */
    BYTE PlanePick;
    BYTE PlaneOnOff;

    VUserStuff VUserExt;      /* user definable:  see note above */
};

struct Bob
/* blitter-objects */
{
/* --------------------- SYSTEM VARIABLES --------------------------------- */

/* --------------------- COMMON VARIABLES --------------------------------- */
    WORD Flags;	/* general purpose flags (see definitions below) */

/* --------------------- USER VARIABLES ----------------------------------- */
    WORD *SaveBuffer;	/* pointer to the buffer for background save */

/* used by Bobs for "cookie-cutting" and multi-plane masking */
    WORD *ImageShadow;

/* pointer to BOBs for sequenced drawing of Bobs
 *  for correct overlaying of multiple component animations
 */
    struct Bob *Before; /* draw this Bob before Bob pointed to by before */
    struct Bob *After;	/* draw this Bob after Bob pointed to by after */

    struct VSprite   *BobVSprite;   /* this Bob's VSprite definition */

    struct AnimComp  *BobComp;	    /* pointer to this Bob's AnimComp def */

    struct DBufPacket *DBuffer;     /* pointer to this Bob's dBuf packet */

    BUserStuff BUserExt;	    /* Bob user extension */
};

struct AnimComp
{
/* --------------------- SYSTEM VARIABLES --------------------------------- */

/* --------------------- COMMON VARIABLES --------------------------------- */
    WORD Flags;		    /* AnimComp flags for system & user */

/* timer defines how long to keep this component active:
 *  if set non-zero, timer decrements to zero then switches to nextSeq
 *  if set to zero, AnimComp never switches
 */
    WORD Timer;

/* --------------------- USER VARIABLES ----------------------------------- */
/* initial value for timer when the AnimComp is activated by the system */
    WORD TimeSet;

/* pointer to next and previous components of animation object */
    struct AnimComp  *NextComp;
    struct AnimComp  *PrevComp;

/* pointer to component component definition of next image in sequence */
    struct AnimComp  *NextSeq;
    struct AnimComp  *PrevSeq;

    WORD (*AnimCRoutine)(); /* address of special animation procedure */

    WORD YTrans;     /* initial y translation (if this is a component) */
    WORD XTrans;     /* initial x translation (if this is a component) */

    struct AnimOb    *HeadOb;

    struct Bob	     *AnimBob;
};

struct AnimOb
{
/* --------------------- SYSTEM VARIABLES --------------------------------- */
    struct AnimOb    *NextOb, *PrevOb;

/* number of calls to Animate this AnimOb has endured */
    LONG Clock;

    WORD AnOldY, AnOldX;	    /* old y,x coordinates */

/* --------------------- COMMON VARIABLES --------------------------------- */
    WORD AnY, AnX;		    /* y,x coordinates of the AnimOb */

/* --------------------- USER VARIABLES ----------------------------------- */
    WORD YVel, XVel;		    /* velocities of this object */
    WORD YAccel, XAccel;	    /* accelerations of this object */

    WORD RingYTrans, RingXTrans;    /* ring translation values */

    WORD (*AnimORoutine)();	    /* address of special animation
                       procedure */

    struct AnimComp  *HeadComp;     /* pointer to first component */

    AUserStuff AUserExt;	    /* AnimOb user extension */
};

/* dBufPacket defines the values needed to be saved across buffer to buffer
 *  when in double-buffer mode
 */
struct DBufPacket
{
    WORD BufY, BufX;		    /* save the other buffers screen coordinates */
    struct VSprite   *BufPath;	    /* carry the draw path over the gap */

/* these pointers must be filled in by the user */
/* pointer to other buffer's background save buffer */
    WORD *BufBuffer;
};

/* ************************************************************************ */

/* these are GEL functions that are currently simple enough to exist as a
 *  definition.  It should not be assumed that this will always be the case
 */
#define InitAnimate(animKey) {*(animKey) = NULL;}
#define RemBob(b) {(b)->Flags |= BOBSAWAY;}

/* ************************************************************************ */

#define B2NORM	    0
#define B2SWAP	    1
#define B2BOBBER    2

/* ************************************************************************ */

/* a structure to contain the 16 collision procedure addresses */
struct collTable
{
    int (*collPtrs[16])();
};

#endif	/* GRAPHICS_GELS_H */


Includes/graphics/layers.h

#ifndef	GRAPHICS_LAYERS_H
#define	GRAPHICS_LAYERS_H
/*
**	$Filename: graphics/layers.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_LISTS_H
#include <exec/lists.h>
#endif

#ifndef EXEC_SEMAPHORES_H
#include <exec/semaphores.h>
#endif

#define LAYERSIMPLE	1
#define LAYERSMART	2
#define LAYERSUPER	4
#define LAYERUPDATING	0x10
#define LAYERBACKDROP	0x40
#define LAYERREFRESH	0x80
#define LAYER_CLIPRECTS_LOST	0x100	/* during BeginUpdate */
                    /* or during layerop */
                    /* this happens if out of memory */
#define LMN_REGION	-1

struct Layer_Info
{
    struct Layer *top_layer;
    struct Layer *check_lp;	    /* system use */
    struct ClipRect *obs;	    /* system use */
    struct MinList	FreeClipRects;
    struct SignalSemaphore Lock;
    struct List gs_Head;			/* system use */
    LONG	longreserved;
    UWORD	Flags;
    BYTE	fatten_count;
    BYTE	LockLayersCount;
    UWORD  LayerInfo_extra_size;
    WORD	*blitbuff;
    VOID	*LayerInfo_extra;
};

#define NEWLAYERINFO_CALLED 1
#define ALERTLAYERSNOMEM 0x83010000

#endif	/* GRAPHICS_LAYERS_H */


Includes/graphics/sprite.h

#ifndef	GRAPHICS_SPRITE_H
#define	GRAPHICS_SPRITE_H
/*
**	$Filename: graphics/sprite.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.0 $
**	$Date: 91/01/07 $
**
**
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#define SPRITE_ATTACHED 0x80

struct SimpleSprite
{
    UWORD *posctldata;
    UWORD height;
    UWORD   x,y;    /* current position */
    UWORD   num;
};

#endif	/* GRAPHICS_SPRITE_H */


Includes/hardware/adkbits.h

#ifndef	HARDWARE_ADKBITS_H
#define	HARDWARE_ADKBITS_H
/*
**	$Filename: hardware/adkbits.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.2 $
**	$Date: 90/07/10 $
**
**	bit definitions for adkcon register
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#define  ADKB_SETCLR	15 /* standard set/clear bit */
#define  ADKB_PRECOMP1	14 /* two bits of precompensation */
#define  ADKB_PRECOMP0	13
#define  ADKB_MFMPREC	12 /* use mfm style precompensation */
#define  ADKB_UARTBRK	11 /* force uart output to zero */
#define  ADKB_WORDSYNC	10 /* enable DSKSYNC register matching */
#define  ADKB_MSBSYNC	9  /* (Apple GCR Only) sync on MSB for reading */
#define  ADKB_FAST	8  /* 1 -> 2 us/bit (mfm), 2 -> 4 us/bit (gcr) */
#define  ADKB_USE3PN	7  /* use aud chan 3 to modulate period of ?? */
#define  ADKB_USE2P3	6  /* use aud chan 2 to modulate period of 3 */
#define  ADKB_USE1P2	5  /* use aud chan 1 to modulate period of 2 */
#define  ADKB_USE0P1	4  /* use aud chan 0 to modulate period of 1 */
#define  ADKB_USE3VN	3  /* use aud chan 3 to modulate volume of ?? */
#define  ADKB_USE2V3	2  /* use aud chan 2 to modulate volume of 3 */
#define  ADKB_USE1V2	1  /* use aud chan 1 to modulate volume of 2 */
#define  ADKB_USE0V1	0  /* use aud chan 0 to modulate volume of 1 */

#define  ADKF_SETCLR	(1<<15)
#define  ADKF_PRECOMP1	(1<<14)
#define  ADKF_PRECOMP0	(1<<13)
#define  ADKF_MFMPREC	(1<<12)
#define  ADKF_UARTBRK	(1<<11)
#define  ADKF_WORDSYNC	(1<<10)
#define  ADKF_MSBSYNC	(1<<9)
#define  ADKF_FAST	(1<<8)
#define  ADKF_USE3PN	(1<<7)
#define  ADKF_USE2P3	(1<<6)
#define  ADKF_USE1P2	(1<<5)
#define  ADKF_USE0P1	(1<<4)
#define  ADKF_USE3VN	(1<<3)
#define  ADKF_USE2V3	(1<<2)
#define  ADKF_USE1V2	(1<<1)
#define  ADKF_USE0V1	(1<<0)

#define ADKF_PRE000NS	0			/* 000 ns of precomp */
#define ADKF_PRE140NS	(ADKF_PRECOMP0)	/* 140 ns of precomp */
#define ADKF_PRE280NS	(ADKF_PRECOMP1)	/* 280 ns of precomp */
#define ADKF_PRE560NS	(ADKF_PRECOMP0|ADKF_PRECOMP1) /* 560 ns of precomp */

#endif	/* HARDWARE_ADKBITS_H */


Includes/hardware/cia.h

#ifndef	HARDWARE_CIA_H
#define	HARDWARE_CIA_H
/*
**	$Filename: hardware/cia.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.3 $
**	$Date: 90/11/05 $
**
**	registers and bits in the Complex Interface Adapter (CIA) chip
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include "exec/types.h"
#endif /* EXEC_TYPES_H */

/*
 * ciaa is on an ODD address (e.g. the low byte) -- $bfe001
 * ciab is on an EVEN address (e.g. the high byte) -- $bfd000
 *
 * do this to get the definitions:
 *    extern struct CIA ciaa, ciab;
 */

struct CIA {
    UBYTE   ciapra;
    UBYTE   pad0[0xff];
    UBYTE   ciaprb;
    UBYTE   pad1[0xff];
    UBYTE   ciaddra;
    UBYTE   pad2[0xff];
    UBYTE   ciaddrb;
    UBYTE   pad3[0xff];
    UBYTE   ciatalo;
    UBYTE   pad4[0xff];
    UBYTE   ciatahi;
    UBYTE   pad5[0xff];
    UBYTE   ciatblo;
    UBYTE   pad6[0xff];
    UBYTE   ciatbhi;
    UBYTE   pad7[0xff];
    UBYTE   ciatodlow;
    UBYTE   pad8[0xff];
    UBYTE   ciatodmid;
    UBYTE   pad9[0xff];
    UBYTE   ciatodhi;
    UBYTE   pad10[0xff];
    UBYTE   unusedreg;
    UBYTE   pad11[0xff];
    UBYTE   ciasdr;
    UBYTE   pad12[0xff];
    UBYTE   ciaicr;
    UBYTE   pad13[0xff];
    UBYTE   ciacra;
    UBYTE   pad14[0xff];
    UBYTE   ciacrb;
};

/* interrupt control register bit numbers */
#define CIAICRB_TA	0
#define CIAICRB_TB	1
#define CIAICRB_ALRM	2
#define CIAICRB_SP	3
#define CIAICRB_FLG	4
#define CIAICRB_IR	7
#define CIAICRB_SETCLR	7

/* control register A bit numbers */
#define CIACRAB_START	0
#define CIACRAB_PBON	1
#define CIACRAB_OUTMODE 2
#define CIACRAB_RUNMODE 3
#define CIACRAB_LOAD	4
#define CIACRAB_INMODE	5
#define CIACRAB_SPMODE	6
#define CIACRAB_TODIN	7

/* control register B bit numbers */
#define CIACRBB_START	0
#define CIACRBB_PBON	1
#define CIACRBB_OUTMODE 2
#define CIACRBB_RUNMODE 3
#define CIACRBB_LOAD	4
#define CIACRBB_INMODE0 5
#define CIACRBB_INMODE1 6
#define CIACRBB_ALARM	7

/* interrupt control register masks */
#define CIAICRF_TA	(1<<CIAICRB_TA)
#define CIAICRF_TB	(1<<CIAICRB_TB)
#define CIAICRF_ALRM	(1<<CIAICRB_ALRM)
#define CIAICRF_SP	(1<<CIAICRB_SP)
#define CIAICRF_FLG	(1<<CIAICRB_FLG)
#define CIAICRF_IR	(1<<CIAICRB_IR)
#define CIAICRF_SETCLR	(1<<CIAICRB_SETCLR)

/* control register A register masks */
#define CIACRAF_START	(1<<CIACRAB_START)
#define CIACRAF_PBON	(1<<CIACRAB_PBON)
#define CIACRAF_OUTMODE (1<<CIACRAB_OUTMODE)
#define CIACRAF_RUNMODE (1<<CIACRAB_RUNMODE)
#define CIACRAF_LOAD	(1<<CIACRAB_LOAD)
#define CIACRAF_INMODE	(1<<CIACRAB_INMODE)
#define CIACRAF_SPMODE	(1<<CIACRAB_SPMODE)
#define CIACRAF_TODIN	(1<<CIACRAB_TODIN)

/* control register B register masks */
#define CIACRBF_START	(1<<CIACRBB_START)
#define CIACRBF_PBON	(1<<CIACRBB_PBON)
#define CIACRBF_OUTMODE (1<<CIACRBB_OUTMODE)
#define CIACRBF_RUNMODE (1<<CIACRBB_RUNMODE)
#define CIACRBF_LOAD	(1<<CIACRBB_LOAD)
#define CIACRBF_INMODE0 (1<<CIACRBB_INMODE0)
#define CIACRBF_INMODE1 (1<<CIACRBB_INMODE1)
#define CIACRBF_ALARM	(1<<CIACRBB_ALARM)

/* control register B INMODE masks */
#define CIACRBF_IN_PHI2 0
#define CIACRBF_IN_CNT	(CIACRBF_INMODE0)
#define CIACRBF_IN_TA	(CIACRBF_INMODE1)
#define CIACRBF_IN_CNT_TA  (CIACRBF_INMODE0|CIACRBF_INMODE1)

/*
 * Port definitions -- what each bit in a cia peripheral register is tied to
 */

/* ciaa port A (0xbfe001) */
#define CIAB_GAMEPORT1	(7)   /* gameport 1, pin 6 (fire button*) */
#define CIAB_GAMEPORT0	(6)   /* gameport 0, pin 6 (fire button*) */
#define CIAB_DSKRDY	(5)   /* disk ready* */
#define CIAB_DSKTRACK0	(4)   /* disk on track 00* */
#define CIAB_DSKPROT	(3)   /* disk write protect* */
#define CIAB_DSKCHANGE	(2)   /* disk change* */
#define CIAB_LED	(1)   /* led light control (0==>bright) */
#define CIAB_OVERLAY	(0)   /* memory overlay bit */

/* ciaa port B (0xbfe101) -- parallel port */

/* ciab port A (0xbfd000) -- serial and printer control */
#define CIAB_COMDTR	(7)   /* serial Data Terminal Ready* */
#define CIAB_COMRTS	(6)   /* serial Request to Send* */
#define CIAB_COMCD	(5)   /* serial Carrier Detect* */
#define CIAB_COMCTS	(4)   /* serial Clear to Send* */
#define CIAB_COMDSR	(3)   /* serial Data Set Ready* */
#define CIAB_PRTRSEL	(2)   /* printer SELECT */
#define CIAB_PRTRPOUT	(1)   /* printer paper out */
#define CIAB_PRTRBUSY	(0)   /* printer busy */

/* ciab port B (0xbfd100) -- disk control */
#define CIAB_DSKMOTOR	(7)   /* disk motorr* */
#define CIAB_DSKSEL3	(6)   /* disk select unit 3* */
#define CIAB_DSKSEL2	(5)   /* disk select unit 2* */
#define CIAB_DSKSEL1	(4)   /* disk select unit 1* */
#define CIAB_DSKSEL0	(3)   /* disk select unit 0* */
#define CIAB_DSKSIDE	(2)   /* disk side select* */
#define CIAB_DSKDIREC	(1)   /* disk direction of seek* */
#define CIAB_DSKSTEP	(0)   /* disk step heads* */

/* ciaa port A (0xbfe001) */
#define CIAF_GAMEPORT1	(1<<7)
#define CIAF_GAMEPORT0	(1<<6)
#define CIAF_DSKRDY	(1<<5)
#define CIAF_DSKTRACK0	(1<<4)
#define CIAF_DSKPROT	(1<<3)
#define CIAF_DSKCHANGE	(1<<2)
#define CIAF_LED	(1<<1)
#define CIAF_OVERLAY	(1<<0)

/* ciaa port B (0xbfe101) -- parallel port */

/* ciab port A (0xbfd000) -- serial and printer control */
#define CIAF_COMDTR	(1<<7)
#define CIAF_COMRTS	(1<<6)
#define CIAF_COMCD	(1<<5)
#define CIAF_COMCTS	(1<<4)
#define CIAF_COMDSR	(1<<3)
#define CIAF_PRTRSEL	(1<<2)
#define CIAF_PRTRPOUT	(1<<1)
#define CIAF_PRTRBUSY	(1<<0)

/* ciab port B (0xbfd100) -- disk control */
#define CIAF_DSKMOTOR	(1<<7)
#define CIAF_DSKSEL3	(1<<6)
#define CIAF_DSKSEL2	(1<<5)
#define CIAF_DSKSEL1	(1<<4)
#define CIAF_DSKSEL0	(1<<3)
#define CIAF_DSKSIDE	(1<<2)
#define CIAF_DSKDIREC	(1<<1)
#define CIAF_DSKSTEP	(1<<0)

#endif	/* HARDWARE_CIA_H */


Includes/hardware/dmabits.h

#ifndef	HARDWARE_DMABITS_H
#define	HARDWARE_DMABITS_H
/*
**	$Filename: hardware/dmabits.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.2 $
**	$Date: 90/07/10 $
**
**	include file for defining dma control stuff
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

/* write definitions for dmaconw */
#define DMAF_SETCLR  0x8000
#define DMAF_AUDIO   0x000F   /* 4 bit mask */
#define DMAF_AUD0    0x0001
#define DMAF_AUD1    0x0002
#define DMAF_AUD2    0x0004
#define DMAF_AUD3    0x0008
#define DMAF_DISK    0x0010
#define DMAF_SPRITE  0x0020
#define DMAF_BLITTER 0x0040
#define DMAF_COPPER  0x0080
#define DMAF_RASTER  0x0100
#define DMAF_MASTER  0x0200
#define DMAF_BLITHOG 0x0400
#define DMAF_ALL     0x01FF   /* all dma channels */

/* read definitions for dmaconr */
/* bits 0-8 correspnd to dmaconw definitions */
#define DMAF_BLTDONE 0x4000
#define DMAF_BLTNZERO	0x2000

#define DMAB_SETCLR  15
#define DMAB_AUD0    0
#define DMAB_AUD1    1
#define DMAB_AUD2    2
#define DMAB_AUD3    3
#define DMAB_DISK    4
#define DMAB_SPRITE  5
#define DMAB_BLITTER 6
#define DMAB_COPPER  7
#define DMAB_RASTER  8
#define DMAB_MASTER  9
#define DMAB_BLITHOG 10
#define DMAB_BLTDONE 14
#define DMAB_BLTNZERO	13

#endif	/* HARDWARE_DMABITS_H */


Includes/hardware/adkbits.i

    IFND	HARDWARE_ADKBITS_I
HARDWARE_ADKBITS_I	SET	1
**
**	$Filename: hardware/adkbits.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.2 $
**	$Date: 90/07/10 $
**
**	bit definitions for adkcon register
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

ADKB_SETCLR    EQU   15 ; standard set/clear bit
ADKB_PRECOMP1  EQU   14 ; two bits of precompensation
ADKB_PRECOMP0  EQU   13
ADKB_MFMPREC   EQU   12 ; use mfm style precompensation
ADKB_UARTBRK   EQU   11 ; force uart output to zero
ADKB_WORDSYNC  EQU   10 ; enable DSKSYNC register matching
ADKB_MSBSYNC   EQU   9	; (Apple GCR Only) sync on MSB for reading
ADKB_FAST      EQU   8	; 1 -> 2 us/bit (mfm), 2 -> 4 us/bit (gcr)
ADKB_USE3PN    EQU   7	; use aud chan 3 to modulate period of ??
ADKB_USE2P3    EQU   6	; use aud chan 2 to modulate period of 3
ADKB_USE1P2    EQU   5	; use aud chan 1 to modulate period of 2
ADKB_USE0P1    EQU   4	; use aud chan 0 to modulate period of 1
ADKB_USE3VN    EQU   3	; use aud chan 3 to modulate volume of ??
ADKB_USE2V3    EQU   2	; use aud chan 2 to modulate volume of 3
ADKB_USE1V2    EQU   1	; use aud chan 1 to modulate volume of 2
ADKB_USE0V1    EQU   0	; use aud chan 0 to modulate volume of 1

ADKF_SETCLR    EQU   (1<<15)
ADKF_PRECOMP1  EQU   (1<<14)
ADKF_PRECOMP0  EQU   (1<<13)
ADKF_MFMPREC   EQU   (1<<12)
ADKF_UARTBRK   EQU   (1<<11)
ADKF_WORDSYNC  EQU   (1<<10)
ADKF_MSBSYNC   EQU   (1<<9)
ADKF_FAST      EQU   (1<<8)
ADKF_USE3PN    EQU   (1<<7)
ADKF_USE2P3    EQU   (1<<6)
ADKF_USE1P2    EQU   (1<<5)
ADKF_USE0P1    EQU   (1<<4)
ADKF_USE3VN    EQU   (1<<3)
ADKF_USE2V3    EQU   (1<<2)
ADKF_USE1V2    EQU   (1<<1)
ADKF_USE0V1    EQU   (1<<0)

ADKF_PRE000NS  EQU   0			     ; 000 ns of precomp
ADKF_PRE140NS  EQU   (ADKF_PRECOMP0)	     ; 140 ns of precomp
ADKF_PRE280NS  EQU   (ADKF_PRECOMP1)	     ; 280 ns of precomp
ADKF_PRE560NS  EQU   (ADKF_PRECOMP0!ADKF_PRECOMP1) ; 560 ns of precomp

    ENDC	; HARDWARE_ADKBITS_I


Includes/hardware/cia.i

    IFND	HARDWARE_CIA_I
HARDWARE_CIA_I	SET	1
**
**	$Filename: hardware/cia.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.2 $
**	$Date: 90/07/10 $
**
**	registers and bits in the Complex Interface Adapter (CIA) chip
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

*
* _ciaa is on an ODD address (e.g. the low byte) -- $bfe001
* _ciab is on an EVEN address (e.g. the high byte) -- $bfd000
*
* do this to get the definitions:
*    XREF _ciaa
*    XREF _ciab
*

* cia register offsets
ciapra		  EQU	$0000
ciaprb		  EQU	$0100
ciaddra	  EQU	$0200
ciaddrb	  EQU	$0300
ciatalo	  EQU	$0400
ciatahi	  EQU	$0500
ciatblo	  EQU	$0600
ciatbhi	  EQU	$0700
ciatodlow	  EQU	$0800
ciatodmid	  EQU	$0900
ciatodhi	  EQU	$0A00
ciasdr		  EQU	$0C00
ciaicr		  EQU	$0D00
ciacra		  EQU	$0E00
ciacrb		  EQU	$0F00

* interrupt control register bit numbers
CIAICRB_TA	  EQU	0
CIAICRB_TB	  EQU	1
CIAICRB_ALRM	  EQU	2
CIAICRB_SP	  EQU	3
CIAICRB_FLG	  EQU	4
CIAICRB_IR	  EQU	7
CIAICRB_SETCLR	  EQU	7

* control register A bit numbers
CIACRAB_START	  EQU	0
CIACRAB_PBON	  EQU	1
CIACRAB_OUTMODE   EQU	2
CIACRAB_RUNMODE   EQU	3
CIACRAB_LOAD	  EQU	4
CIACRAB_INMODE	  EQU	5
CIACRAB_SPMODE	  EQU	6
CIACRAB_TODIN	  EQU	7

* control register B bit numbers
CIACRBB_START	  EQU	0
CIACRBB_PBON	  EQU	1
CIACRBB_OUTMODE   EQU	2
CIACRBB_RUNMODE   EQU	3
CIACRBB_LOAD	  EQU	4
CIACRBB_INMODE0   EQU	5
CIACRBB_INMODE1   EQU	6
CIACRBB_ALARM	  EQU	7

* interrupt control register bit masks
CIAICRF_TA	  EQU	(1<<0)
CIAICRF_TB	  EQU	(1<<1)
CIAICRF_ALRM	  EQU	(1<<2)
CIAICRF_SP	  EQU	(1<<3)
CIAICRF_FLG	  EQU	(1<<4)
CIAICRF_IR	  EQU	(1<<7)
CIAICRF_SETCLR	  EQU	(1<<7)

* control register A bit masks
CIACRAF_START	  EQU	(1<<0)
CIACRAF_PBON	  EQU	(1<<1)
CIACRAF_OUTMODE   EQU	(1<<2)
CIACRAF_RUNMODE   EQU	(1<<3)
CIACRAF_LOAD	  EQU	(1<<4)
CIACRAF_INMODE	  EQU	(1<<5)
CIACRAF_SPMODE	  EQU	(1<<6)
CIACRAF_TODIN	  EQU	(1<<7)

* control register B bit masks
CIACRBF_START	  EQU	(1<<0)
CIACRBF_PBON	  EQU	(1<<1)
CIACRBF_OUTMODE   EQU	(1<<2)
CIACRBF_RUNMODE   EQU	(1<<3)
CIACRBF_LOAD	  EQU	(1<<4)
CIACRBF_INMODE0   EQU	(1<<5)
CIACRBF_INMODE1   EQU	(1<<6)
CIACRBF_ALARM	  EQU	(1<<7)

* control register B INMODE masks
CIACRBF_IN_PHI2   EQU	0
CIACRBF_IN_CNT	  EQU	(CIACRBF_INMODE0)
CIACRBF_IN_TA	  EQU	(CIACRBF_INMODE1)
CIACRBF_IN_CNT_TA EQU	(CIACRBF_INMODE0!CIACRBF_INMODE1)

*
* Port definitions -- what each bit in a cia peripheral register is tied to
*

* ciaa port A (0xbfe001)
CIAB_GAMEPORT1	  EQU	(7)   * gameport 1, pin 6 (fire button*)
CIAB_GAMEPORT0	  EQU	(6)   * gameport 0, pin 6 (fire button*)
CIAB_DSKRDY	  EQU	(5)   * disk ready*
CIAB_DSKTRACK0	  EQU	(4)   * disk on track 00*
CIAB_DSKPROT	  EQU	(3)   * disk write protect*
CIAB_DSKCHANGE	  EQU	(2)   * disk change*
CIAB_LED	  EQU	(1)   * led light control (0==>bright)
CIAB_OVERLAY	  EQU	(0)   * memory overlay bit

* ciaa port B (0xbfe101) -- parallel port

* ciab port A (0xbfd000) -- serial and printer control
CIAB_COMDTR	  EQU	(7)   * serial Data Terminal Ready*
CIAB_COMRTS	  EQU	(6)   * serial Request to Send*
CIAB_COMCD	  EQU	(5)   * serial Carrier Detect*
CIAB_COMCTS	  EQU	(4)   * serial Clear to Send*
CIAB_COMDSR	  EQU	(3)   * serial Data Set Ready*
CIAB_PRTRSEL	  EQU	(2)   * printer SELECT
CIAB_PRTRPOUT	  EQU	(1)   * printer paper out
CIAB_PRTRBUSY	  EQU	(0)   * printer busy

* ciab port B (0xbfd100) -- disk control
CIAB_DSKMOTOR	  EQU	(7)   * disk motorr*
CIAB_DSKSEL3	  EQU	(6)   * disk select unit 3*
CIAB_DSKSEL2	  EQU	(5)   * disk select unit 2*
CIAB_DSKSEL1	  EQU	(4)   * disk select unit 1*
CIAB_DSKSEL0	  EQU	(3)   * disk select unit 0*
CIAB_DSKSIDE	  EQU	(2)   * disk side select*
CIAB_DSKDIREC	  EQU	(1)   * disk direction of seek*
CIAB_DSKSTEP	  EQU	(0)   * disk step heads*

* ciaa port A (0xbfe001)
CIAF_GAMEPORT1	  EQU	(1<<7)
CIAF_GAMEPORT0	  EQU	(1<<6)
CIAF_DSKRDY	  EQU	(1<<5)
CIAF_DSKTRACK0	  EQU	(1<<4)
CIAF_DSKPROT	  EQU	(1<<3)
CIAF_DSKCHANGE	  EQU	(1<<2)
CIAF_LED	  EQU	(1<<1)
CIAF_OVERLAY	  EQU	(1<<0)

* ciaa port B (0xbfe101) -- parallel port

* ciab port A (0xbfd000) -- serial and printer control
CIAF_COMDTR	  EQU	(1<<7)
CIAF_COMRTS	  EQU	(1<<6)
CIAF_COMCD	  EQU	(1<<5)
CIAF_COMCTS	  EQU	(1<<4)
CIAF_COMDSR	  EQU	(1<<3)
CIAF_PRTRSEL	  EQU	(1<<2)
CIAF_PRTRPOUT	  EQU	(1<<1)
CIAF_PRTRBUSY	  EQU	(1<<0)

* ciab port B (0xbfd100) -- disk control
CIAF_DSKMOTOR	  EQU	(1<<7)
CIAF_DSKSEL3	  EQU	(1<<6)
CIAF_DSKSEL2	  EQU	(1<<5)
CIAF_DSKSEL1	  EQU	(1<<4)
CIAF_DSKSEL0	  EQU	(1<<3)
CIAF_DSKSIDE	  EQU	(1<<2)
CIAF_DSKDIREC	  EQU	(1<<1)
CIAF_DSKSTEP	  EQU	(1<<0)

    ENDC	; HARDWARE_CIA_I


Includes/hardware/dmabits.i

    IFND	HARDWARE_DMABITS_I
HARDWARE_DMABITS_I	SET	1
**
**	$Filename: hardware/dmabits.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.2 $
**	$Date: 90/07/10 $
**
**	include file for defining dma control stuff
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

* write definitions for dmaconw
DMAF_SETCLR    EQU   $8000
DMAF_AUDIO     EQU   $000F  * 4 bit mask
DMAF_AUD0      EQU   $0001
DMAF_AUD1      EQU   $0002
DMAF_AUD2      EQU   $0004
DMAF_AUD3      EQU   $0008
DMAF_DISK      EQU   $0010
DMAF_SPRITE    EQU   $0020
DMAF_BLITTER   EQU   $0040
DMAF_COPPER    EQU   $0080
DMAF_RASTER    EQU   $0100
DMAF_MASTER    EQU   $0200
DMAF_BLITHOG   EQU   $0400
DMAF_ALL       EQU   $01FF  * all dma channels

* read definitions for dmaconr
* bits 0-8 correspnd to dmaconw definitions
DMAF_BLTDONE   EQU   $4000
DMAF_BLTNZERO  EQU   $2000

DMAB_SETCLR    EQU   15
DMAB_AUD0      EQU   0
DMAB_AUD1      EQU   1
DMAB_AUD2      EQU   2
DMAB_AUD3      EQU   3
DMAB_DISK      EQU   4
DMAB_SPRITE    EQU   5
DMAB_BLITTER   EQU   6
DMAB_COPPER    EQU   7
DMAB_RASTER    EQU   8
DMAB_MASTER    EQU   9
DMAB_BLITHOG   EQU   10
DMAB_BLTDONE   EQU   14
DMAB_BLTNZERO  EQU   13

    ENDC	; HARDWARE_DMABITS_I


Includes/hardware/blit.h

#ifndef	HARDWARE_BLIT_H
#define	HARDWARE_BLIT_H
/*
**	$Filename: hardware/blit.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.3 $
**	$Date: 90/11/05 $
**
**	Defines for direct hardware use of the blitter.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#define HSIZEBITS 6
#define VSIZEBITS 16-HSIZEBITS
#define HSIZEMASK 0x3f	      /* 2^6 -- 1 */
#define VSIZEMASK 0x3FF       /* 2^10 - 1 */

/* all agnii support horizontal blit of at least 1024 bits (128 bytes) wide */
/* some agnii support horizontal blit of up to 32768 bits (4096 bytes) wide */

#ifndef	 NO_BIG_BLITS
#define  MINBYTESPERROW 128
#define  MAXBYTESPERROW 4096
#else
#define  MAXBYTESPERROW 128
#endif

/* definitions for blitter control register 0 */

#define ABC    0x80
#define ABNC   0x40
#define ANBC   0x20
#define ANBNC  0x10
#define NABC   0x8
#define NABNC  0x4
#define NANBC  0x2
#define NANBNC 0x1

/* some commonly used operations */
#define A_OR_B	  ABC|ANBC|NABC | ABNC|ANBNC|NABNC
#define A_OR_C	  ABC|NABC|ABNC | ANBC|NANBC|ANBNC
#define A_XOR_C   NABC|ABNC   | NANBC|ANBNC
#define A_TO_D	  ABC|ANBC|ABNC|ANBNC

#define BC0B_DEST 8
#define BC0B_SRCC 9
#define BC0B_SRCB   10
#define BC0B_SRCA 11
#define BC0F_DEST 0x100
#define BC0F_SRCC 0x200
#define BC0F_SRCB 0x400
#define BC0F_SRCA 0x800

#define BC1F_DESC   2	      /* blitter descend direction */

#define DEST 0x100
#define SRCC 0x200
#define SRCB 0x400
#define SRCA 0x800

#define ASHIFTSHIFT  12       /* bits to right align ashift value */
#define BSHIFTSHIFT  12       /* bits to right align bshift value */

/* definations for blitter control register 1 */
#define LINEMODE     0x1
#define FILL_OR      0x8
#define FILL_XOR     0x10
#define FILL_CARRYIN 0x4
#define ONEDOT	     0x2      /* one dot per horizontal line */
#define OVFLAG	     0x20
#define SIGNFLAG     0x40
#define BLITREVERSE  0x2

#define SUD	     0x10
#define SUL	     0x8
#define AUL	     0x4

#define OCTANT8   24
#define OCTANT7   4
#define OCTANT6   12
#define OCTANT5   28
#define OCTANT4   20
#define OCTANT3   8
#define OCTANT2   0
#define OCTANT1   16

/* stuff for blit qeuer */
struct bltnode
{
    struct  bltnode *n;
    int     (*function)();
    char    stat;
    short   blitsize;
    short   beamsync;
    int     (*cleanup)();
};

/* defined bits for bltstat */
#define CLEANUP 0x40
#define CLEANME CLEANUP

#endif	/* HARDWARE_BLIT_H */


Includes/hardware/custom.h

#ifndef	HARDWARE_CUSTOM_H
#define	HARDWARE_CUSTOM_H
/*
**	$Filename: hardware/custom.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.4 $
**	$Date: 90/11/05 $
**
**	Offsets of Amiga custom chip registers
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include "exec/types.h"
#endif /* EXEC_TYPES_H */

/*
 * do this to get base of custom registers:
 * extern struct Custom custom;
 */

struct Custom {
    UWORD   bltddat;
    UWORD   dmaconr;
    UWORD   vposr;
    UWORD   vhposr;
    UWORD   dskdatr;
    UWORD   joy0dat;
    UWORD   joy1dat;
    UWORD   clxdat;
    UWORD   adkconr;
    UWORD   pot0dat;
    UWORD   pot1dat;
    UWORD   potinp;
    UWORD   serdatr;
    UWORD   dskbytr;
    UWORD   intenar;
    UWORD   intreqr;
    APTR    dskpt;
    UWORD   dsklen;
    UWORD   dskdat;
    UWORD   refptr;
    UWORD   vposw;
    UWORD   vhposw;
    UWORD   copcon;
    UWORD   serdat;
    UWORD   serper;
    UWORD   potgo;
    UWORD   joytest;
    UWORD   strequ;
    UWORD   strvbl;
    UWORD   strhor;
    UWORD   strlong;
    UWORD   bltcon0;
    UWORD   bltcon1;
    UWORD   bltafwm;
    UWORD   bltalwm;
    APTR    bltcpt;
    APTR    bltbpt;
    APTR    bltapt;
    APTR    bltdpt;
    UWORD   bltsize;
    UBYTE   pad2d;
    UBYTE   bltcon0l;	/* low 8 bits of bltcon0, write only */
    UWORD   bltsizv;
    UWORD   bltsizh;	/* 5e */
    UWORD   bltcmod;
    UWORD   bltbmod;
    UWORD   bltamod;
    UWORD   bltdmod;
    UWORD   pad34[4];
    UWORD   bltcdat;
    UWORD   bltbdat;
    UWORD   bltadat;
    UWORD   pad3b[3];
    UWORD deniseid;   /* 7c */
    UWORD   dsksync;
    ULONG   cop1lc;
    ULONG   cop2lc;
    UWORD   copjmp1;
    UWORD   copjmp2;
    UWORD   copins;
    UWORD   diwstrt;
    UWORD   diwstop;
    UWORD   ddfstrt;
    UWORD   ddfstop;
    UWORD   dmacon;
    UWORD   clxcon;
    UWORD   intena;
    UWORD   intreq;
    UWORD   adkcon;
    struct  AudChannel {
      UWORD *ac_ptr; /* ptr to start of waveform data */
      UWORD ac_len;	/* length of waveform in words */
      UWORD ac_per;	/* sample period */
      UWORD ac_vol;	/* volume */
      UWORD ac_dat;	/* sample pair */
      UWORD ac_pad[2];	/* unused */
    } aud[4];
    APTR    bplpt[8];
    UWORD   bplcon0;
    UWORD   bplcon1;
    UWORD   bplcon2;
    UWORD   bplcon3;
    UWORD   bpl1mod;
    UWORD   bpl2mod;
    UWORD   bplhmod;
    UWORD   pad86[1];
    UWORD   bpldat[8];
    APTR    sprpt[8];
    struct  SpriteDef {
      UWORD pos;
      UWORD ctl;
      UWORD dataa;
      UWORD datab;
    } spr[8];
    UWORD   color[32];
    UWORD htotal;
    UWORD hsstop;
    UWORD hbstrt;
    UWORD hbstop;
    UWORD vtotal;
    UWORD vsstop;
    UWORD vbstrt;
    UWORD vbstop;
    UWORD sprhstrt;
    UWORD sprhstop;
    UWORD bplhstrt;
    UWORD bplhstop;
    UWORD hhposw;
    UWORD hhposr;
    UWORD beamcon0;
    UWORD hsstrt;
    UWORD vsstrt;
    UWORD hcenter;
    UWORD   diwhigh;	/* 1e4 */
};

#ifdef ECS_SPECIFIC

/* defines for beamcon register */
#define VARVBLANK	0x1000	/* Variable vertical blank enable */
#define LOLDIS		0x0800	/* long line disable */
#define CSCBLANKEN	0x0400	/* redirect composite sync */
#define VARVSYNC	0x0200	/* Variable vertical sync enable */
#define VARHSYNC	0x0100	/* Variable horizontal sync enable */
#define VARBEAM	0x0080	/* variable beam counter enable */
#define DISPLAYDUAL	0x0040	/* use UHRES pointer and standard pointers */
#define DISPLAYPAL	0x0020	/* set decodes to generate PAL display */
#define VARCSYNC	0x0010	/* Variable composite sync enable */
#define CSBLANK	0x0008	/* Composite blank out to CSY* pin */
#define CSYNCTRUE	0x0004	/* composite sync true signal */
#define VSYNCTRUE	0x0002	/* vertical sync true */
#define HSYNCTRUE	0x0001	/* horizontal sync true */

/* new defines for bplcon0 */
#define USE_BPLCON3	1

/* new defines for bplcon2 */
#define BPLCON2_ZDCTEN		(1<<10) /* colormapped genlock bit */
#define BPLCON2_ZDBPEN		(1<<11) /* use bitplane as genlock bits */
#define BPLCON2_ZDBPSEL0	(1<<12) /* three bits to select one */
#define BPLCON2_ZDBPSEL1	(1<<13) /* of 8 bitplanes in */
#define BPLCON2_ZDBPSEL2	(1<<14) /* ZDBPEN genlock mode */

/* defines for bplcon3 register */
#define BPLCON3_EXTBLNKEN	(1<<0)	/* external blank enable */
#define BPLCON3_EXTBLKZD	(1<<1)	/* external blank ored into trnsprncy */
#define BPLCON3_ZDCLKEN	(1<<2)	/* zd pin outputs a 14mhz clock*/
#define BPLCON3_BRDNTRAN	(1<<4)	/* border is opaque */
#define BPLCON3_BRDNBLNK	(1<<5)	/* border is opaque */

#endif	/* ECS_SPECIFIC */

#endif	/* HARDWARE_CUSTOM_H */


Includes/hardware/intbits.h

#ifndef	HARDWARE_INTBITS_H
#define	HARDWARE_INTBITS_H
/*
**	$Filename: hardware/intbits.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.2 $
**	$Date: 90/07/10 $
**
**	bits in the interrupt enable (and interrupt request) register
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#define  INTB_SETCLR	(15)  /* Set/Clear control bit. Determines if bits */
        /* written with a 1 get set or cleared. Bits */
        /* written with a zero are allways unchanged */
#define  INTB_INTEN	(14)  /* Master interrupt (enable only ) */
#define  INTB_EXTER	(13)  /* External interrupt */
#define  INTB_DSKSYNC	(12)  /* Disk re-SYNChronized */
#define  INTB_RBF	(11)  /* serial port Receive Buffer Full */
#define  INTB_AUD3	(10)  /* Audio channel 3 block finished */
#define  INTB_AUD2	(9)   /* Audio channel 2 block finished */
#define  INTB_AUD1	(8)   /* Audio channel 1 block finished */
#define  INTB_AUD0	(7)   /* Audio channel 0 block finished */
#define  INTB_BLIT	(6)   /* Blitter finished */
#define  INTB_VERTB	(5)   /* start of Vertical Blank */
#define  INTB_COPER	(4)   /* Coprocessor */
#define  INTB_PORTS	(3)   /* I/O Ports and timers */
#define  INTB_SOFTINT	(2)   /* software interrupt request */
#define  INTB_DSKBLK	(1)   /* Disk Block done */
#define  INTB_TBE	(0)   /* serial port Transmit Buffer Empty */

#define  INTF_SETCLR	(1<<15)
#define  INTF_INTEN	(1<<14)
#define  INTF_EXTER	(1<<13)
#define  INTF_DSKSYNC	(1<<12)
#define  INTF_RBF	(1<<11)
#define  INTF_AUD3	(1<<10)
#define  INTF_AUD2	(1<<9)
#define  INTF_AUD1	(1<<8)
#define  INTF_AUD0	(1<<7)
#define  INTF_BLIT	(1<<6)
#define  INTF_VERTB	(1<<5)
#define  INTF_COPER	(1<<4)
#define  INTF_PORTS	(1<<3)
#define  INTF_SOFTINT	(1<<2)
#define  INTF_DSKBLK	(1<<1)
#define  INTF_TBE	(1<<0)

#endif	/* HARDWARE_INTBITS_H */


Includes/hardware/blit.i

    IFND	HARDWARE_BLIT_I
HARDWARE_BLIT_I	SET	1
**
**	$Filename: hardware/blit.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.3 $
**	$Date: 90/11/05 $
**
**	Defines for direct hardware use of the blitter.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND	EXEC_TYPES_I
    INCLUDE	"exec/types.i"
    ENDC	;EXEC_TYPES_I

   STRUCTURE bltnode,0
   LONG  bn_n
   LONG  bn_function
   BYTE  bn_stat
   BYTE  bn_dummy
   WORD  bn_blitsize
   WORD  bn_beamsync
   LONG  bn_cleanup
   LABEL bn_SIZEOF

* bit defines used by blit queuer
CLEANMEn    equ 6
CLEANME     equ 1<<CLEANMEn

* include file for blitter */
HSIZEBITS   equ   6
VSIZEBITS   equ   16-HSIZEBITS
HSIZEMASK   equ   $3f	      /* 2^6 -- 1 */
VSIZEMASK   equ   $3FF	      /* 2^10 - 1 */

* all agnii support horizontal blit of at least 1024 bits (128 bytes) wide */
* some agnii support horizontal blit of up to 32768 bits (4096 bytes) wide */

    IFD	NO_BIG_BLITS
MAXBYTESPERROW EQU   128
    ENDC

    IFND	NO_BIG_BLITS
MINBYTESPERROW EQU   128
MAXBYTESPERROW EQU   4096
    ENDC

* definitions for blitter control register 0 */

ABC	    equ   $80
ABNC	    equ   $40
ANBC	    equ   $20
ANBNC	    equ   $10
NABC	    equ   $8
NABNC	    equ   $4
NANBC	    equ   $2
NANBNC	    equ   $1

BC0B_DEST   equ     8
BC0B_SRCC   equ     9
BC0B_SRCB   equ     10
BC0B_SRCA   equ     11
BC0F_DEST   equ   $100
BC0F_SRCC   equ   $200
BC0F_SRCB   equ   $400
BC0F_SRCA   equ   $800

BC1F_DESC   equ 2

DEST	    equ   $100
SRCC	    equ   $200
SRCB	    equ   $400
SRCA	    equ   $800

ASHIFTSHIFT equ   12 /* bits to right align ashift value */
BSHIFTSHIFT equ   12 /* bits to right align bshift value */

* definations for blitter control register 1 */
LINEMODE    equ   $1
FILL_OR     equ   $8
FILL_XOR    equ   $10
FILL_CARRYIN   equ   $4
ONEDOT	    equ   $2
OVFLAG	    equ   $20
SIGNFLAG    equ   $40
BLITREVERSE equ   $2

SUD	    equ   $10
SUL	    equ   $8
AUL	    equ   $4

OCTANT8     equ   24
OCTANT7     equ   4
OCTANT6     equ   12
OCTANT5     equ   28
OCTANT4     equ   20
OCTANT3     equ   8
OCTANT2     equ   0
OCTANT1     equ   16

    ENDC	; HARDWARE_BLIT_I


Includes/hardware/custom.i

    IFND	HARDWARE_CUSTOM_I
HARDWARE_CUSTOM_I	SET	1
**
**	$Filename: hardware/custom.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.6 $
**	$Date: 91/04/30 $
**
**	Offsets of Amiga custom chip registers
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

*
* do this to get base of custom registers:
*  XREF _custom;
*

bltddat     EQU   $000
dmaconr     EQU   $002
vposr	    EQU   $004
vhposr	    EQU   $006
dskdatr     EQU   $008
joy0dat     EQU   $00A
joy1dat     EQU   $00C
clxdat	    EQU   $00E

adkconr     EQU   $010
pot0dat     EQU   $012
pot1dat     EQU   $014
potinp	    EQU   $016
serdatr     EQU   $018
dskbytr     EQU   $01A
intenar     EQU   $01C
intreqr     EQU   $01E

dskpt	    EQU   $020
dsklen	    EQU   $024
dskdat	    EQU   $026
refptr	    EQU   $028
vposw	    EQU   $02A
vhposw	    EQU   $02C
copcon	    EQU   $02E
serdat	    EQU   $030
serper	    EQU   $032
potgo	    EQU   $034
joytest     EQU   $036
strequ	    EQU   $038
strvbl	    EQU   $03A
strhor	    EQU   $03C
strlong     EQU   $03E

bltcon0     EQU   $040
bltcon1     EQU   $042
bltafwm     EQU   $044
bltalwm     EQU   $046
bltcpt	    EQU   $048
bltbpt	    EQU   $04C
bltapt	    EQU   $050
bltdpt	    EQU   $054
bltsize     EQU   $058
bltcon0l    EQU   $05B		; note: byte access only
bltsizv     EQU   $05C
bltsizh     EQU   $05E

bltcmod     EQU   $060
bltbmod     EQU   $062
bltamod     EQU   $064
bltdmod     EQU   $066

bltcdat     EQU   $070
bltbdat     EQU   $072
bltadat     EQU   $074

deniseid    EQU   $07C
dsksync     EQU   $07E

cop1lc	    EQU   $080
cop2lc	    EQU   $084
copjmp1     EQU   $088
copjmp2     EQU   $08A
copins	    EQU   $08C
diwstrt     EQU   $08E
diwstop     EQU   $090
ddfstrt     EQU   $092
ddfstop     EQU   $094
dmacon	    EQU   $096
clxcon	    EQU   $098
intena	    EQU   $09A
intreq	    EQU   $09C
adkcon	    EQU   $09E

aud	    EQU   $0A0
aud0	    EQU   $0A0
aud1	    EQU   $0B0
aud2	    EQU   $0C0
aud3	    EQU   $0D0

* AudChannel
ac_ptr	    EQU   $00	; ptr to start of waveform data
ac_len	    EQU   $04	; length of waveform in words
ac_per	    EQU   $06	; sample period
ac_vol	    EQU   $08	; volume
ac_dat	    EQU   $0A	; sample pair
ac_SIZEOF   EQU   $10

bplpt	    EQU   $0E0

bplcon0     EQU   $100
bplcon1     EQU   $102
bplcon2     EQU   $104
bplcon3     EQU   $106
bpl1mod     EQU   $108
bpl2mod     EQU   $10A
bplhmod     EQU   $10C

bpldat	    EQU   $110

sprpt	    EQU   $120

spr	    EQU   $140

* SpriteDef
sd_pos	    EQU   $00
sd_ctl	    EQU   $02
sd_dataa    EQU   $04
sd_dataB    EQU   $06
sd_SIZEOF   EQU   $08

color	    EQU   $180

htotal	    EQU   $1c0
hsstop	    EQU   $1c2
hbstrt	    EQU   $1c4
hbstop	    EQU   $1c6
vtotal	    EQU   $1c8
vsstop	    EQU   $1ca
vbstrt	    EQU   $1cc
vbstop	    EQU   $1ce
sprhstrt    EQU   $1d0
sprhstop    EQU   $1d2
bplhstrt    EQU   $1d4
bplhstop    EQU   $1d6
hhposw	    EQU   $1d8
hhposr	    EQU   $1da
beamcon0    EQU   $1dc
hsstrt	    EQU   $1de
vsstrt	    EQU   $1e0
hcenter     EQU   $1e2
diwhigh     EQU   $1e4

   ENDC  !HARDWARE_CUSTOM_I


Includes/hardware/intbits.i

    IFND	HARDWARE_INTBITS_I
HARDWARE_INTBITS_I	SET	1
**
**	$Filename: hardware/intbits.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.2 $
**	$Date: 90/07/10 $
**
**	bits in the interrupt enable (and interrupt request) register
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

INTB_SETCLR    EQU   (15)  ;Set/Clear control bit. Determines if bits
               ;written with a 1 get set or cleared. Bits
               ;written with a zero are allways unchanged.
INTB_INTEN     EQU   (14)  ;Master interrupt (enable only )
INTB_EXTER     EQU   (13)  ;External interrupt
INTB_DSKSYNC   EQU   (12)  ;Disk re-SYNChronized
INTB_RBF       EQU   (11)  ;serial port Receive Buffer Full
INTB_AUD3      EQU   (10)  ;Audio channel 3 block finished
INTB_AUD2      EQU   (9)   ;Audio channel 2 block finished
INTB_AUD1      EQU   (8)   ;Audio channel 1 block finished
INTB_AUD0      EQU   (7)   ;Audio channel 0 block finished
INTB_BLIT      EQU   (6)   ;Blitter finished
INTB_VERTB     EQU   (5)   ;start of Vertical Blank
INTB_COPER     EQU   (4)   ;Coprocessor
INTB_PORTS     EQU   (3)   ;I/O Ports and timers
INTB_SOFTINT   EQU   (2)   ;software interrupt request
INTB_DSKBLK    EQU   (1)   ;Disk Block done
INTB_TBE       EQU   (0)   ;serial port Transmit Buffer Empty

INTF_SETCLR    EQU   (1<<15)
INTF_INTEN     EQU   (1<<14)
INTF_EXTER     EQU   (1<<13)
INTF_DSKSYNC   EQU   (1<<12)
INTF_RBF       EQU   (1<<11)
INTF_AUD3      EQU   (1<<10)
INTF_AUD2      EQU   (1<<9)
INTF_AUD1      EQU   (1<<8)
INTF_AUD0      EQU   (1<<7)
INTF_BLIT      EQU   (1<<6)
INTF_VERTB     EQU   (1<<5)
INTF_COPER     EQU   (1<<4)
INTF_PORTS     EQU   (1<<3)
INTF_SOFTINT   EQU   (1<<2)
INTF_DSKBLK    EQU   (1<<1)
INTF_TBE       EQU   (1<<0)

    ENDC	; HARDWARE_INTBITS_I


Includes/intuition/cghooks.h

#ifndef INTUITION_CGHOOKS_H
#define INTUITION_CGHOOKS_H 1
/*
**  $Filename: intuition/cghooks.h $
**  $Release: 2.04 Includes, V37.4 $
**  $Revision: 36.2 $
**  $Date: 91/11/08 $
**
**  Custom Gadget processing
**
**  (C) Copyright 1988-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef INTUITION_INTUITION_H
#include <intuition/intuition.h>
#endif

/*
 * Package of information passed to custom and 'boopsi'
 * gadget "hook" functions.  This structure is READ ONLY.
 */
struct GadgetInfo {

    struct Screen		*gi_Screen;
    struct Window		*gi_Window;	/* null for screen gadgets */
    struct Requester		*gi_Requester;	/* null if not GTYP_REQGADGET */

    /* rendering information:
     * don't use these without cloning/locking.
     * Official way is to call ObtainRPort()
     */
    struct RastPort		*gi_RastPort;
    struct Layer		*gi_Layer;

    /* copy of dimensions of screen/window/g00/req(/group)
     * that gadget resides in.	Left/Top of this box is
     * offset from window mouse coordinates to gadget coordinates
     *		screen gadgets:			0,0 (from screen coords)
     *	window gadgets (no g00):	0,0
     *	GTYP_GZZGADGETs (borderlayer):		0,0
     *	GZZ innerlayer gadget:		borderleft, bordertop
     *	Requester gadgets:		reqleft, reqtop
     */
    struct IBox			gi_Domain;

    /* these are the pens for the window or screen	*/
    struct {
    UBYTE	DetailPen;
    UBYTE	BlockPen;
    }				gi_Pens;

    /* the Detail and Block pens in gi_DrInfo->dri_Pens[] are
     * for the screen.	Use the above for window-sensitive
     * colors.
     */
    struct DrawInfo		*gi_DrInfo;

    /* reserved space: this structure is extensible
     * anyway, but using these saves some recompilation
     */
    ULONG			gi_Reserved[6];
};

/*** system private data structure for now ***/
/* prop gadget extra info	*/
struct PGX	{
    struct IBox	pgx_Container;
    struct IBox	pgx_NewKnob;
};

/* this casts MutualExclude for easy assignment of a hook
 * pointer to the unused MutualExclude field of a custom gadget
 */
#define CUSTOM_HOOK( gadget ) ( (struct Hook *) (gadget)->MutualExclude)

#endif


Includes/intuition/gadgetclass.h

#ifndef INTUITION_GADGETCLASS_H
#define INTUITION_GADGETCLASS_H 1
/*
**  $Filename: intuition/gadgetclass.h $
**  $Release: 2.04 Includes, V37.4 $
**  $Revision: 36.6 $
**  $Date: 91/11/08 $
**
**  Custom and 'boopsi' gadget class interface
**
**  (C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef INTUITION_INTUITION_H
#include <intuition/intuition.h>
#endif

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

/*
 * NOTE:  <intuition/iobsolete.h> is included at the END of this file!
 */

/* Gadget Class attributes	*/

#define	   GA_Dummy		(TAG_USER +0x30000)
#define    GA_Left		(GA_Dummy + 0x0001)
#define    GA_RelRight		(GA_Dummy + 0x0002)
#define    GA_Top		(GA_Dummy + 0x0003)
#define    GA_RelBottom		(GA_Dummy + 0x0004)
#define    GA_Width		(GA_Dummy + 0x0005)
#define    GA_RelWidth		(GA_Dummy + 0x0006)
#define    GA_Height		(GA_Dummy + 0x0007)
#define    GA_RelHeight		(GA_Dummy + 0x0008)
#define    GA_Text		(GA_Dummy + 0x0009) /* ti_Data is (UBYTE *) */
#define    GA_Image		(GA_Dummy + 0x000A)
#define    GA_Border		(GA_Dummy + 0x000B)
#define    GA_SelectRender	(GA_Dummy + 0x000C)
#define    GA_Highlight		(GA_Dummy + 0x000D)
#define    GA_Disabled		(GA_Dummy + 0x000E)
#define    GA_GZZGadget		(GA_Dummy + 0x000F)
#define    GA_ID		(GA_Dummy + 0x0010)
#define    GA_UserData		(GA_Dummy + 0x0011)
#define    GA_SpecialInfo	(GA_Dummy + 0x0012)
#define    GA_Selected		(GA_Dummy + 0x0013)
#define    GA_EndGadget		(GA_Dummy + 0x0014)
#define    GA_Immediate		(GA_Dummy + 0x0015)
#define    GA_RelVerify		(GA_Dummy + 0x0016)
#define    GA_FollowMouse	(GA_Dummy + 0x0017)
#define    GA_RightBorder	(GA_Dummy + 0x0018)
#define    GA_LeftBorder	(GA_Dummy + 0x0019)
#define    GA_TopBorder		(GA_Dummy + 0x001A)
#define    GA_BottomBorder	(GA_Dummy + 0x001B)
#define    GA_ToggleSelect	(GA_Dummy + 0x001C)

    /* internal use only, until further notice, please */
#define    GA_SysGadget		(GA_Dummy + 0x001D)
    /* bool, sets GTYP_SYSGADGET field in type	*/
#define    GA_SysGType		(GA_Dummy + 0x001E)
    /* e.g., GTYP_WUPFRONT, ...	*/

#define    GA_Previous		(GA_Dummy + 0x001F)
    /* previous gadget (or (struct Gadget **)) in linked list
     * NOTE: This attribute CANNOT be used to link new gadgets
     * into the gadget list of an open window or requester.
     * You must use AddGList().
     */

#define    GA_Next		(GA_Dummy + 0x0020)
     /* not implemented */

#define    GA_DrawInfo		(GA_Dummy + 0x0021)
    /* some fancy gadgets need to see a DrawInfo
     * when created or for layout
     */

/* You should use at most ONE of GA_Text, GA_IntuiText, and GA_LabelImage */
#define GA_IntuiText		(GA_Dummy + 0x0022)
    /* ti_Data is (struct IntuiText	*) */

#define GA_LabelImage		(GA_Dummy + 0x0023)
    /* ti_Data is an image (object), used in place of
     * GadgetText
     */

#define GA_TabCycle		(GA_Dummy + 0x0024)
    /* New for V37:
     * Boolean indicates that this gadget is to participate in
     * cycling activation with Tab or Shift-Tab.
     */

/* PROPGCLASS attributes */

#define PGA_Dummy	(TAG_USER + 0x31000)
#define PGA_Freedom	(PGA_Dummy + 0x0001)
    /* only one of FREEVERT or FREEHORIZ */
#define PGA_Borderless	(PGA_Dummy + 0x0002)
#define PGA_HorizPot	(PGA_Dummy + 0x0003)
#define PGA_HorizBody	(PGA_Dummy + 0x0004)
#define PGA_VertPot	(PGA_Dummy + 0x0005)
#define PGA_VertBody	(PGA_Dummy + 0x0006)
#define PGA_Total	(PGA_Dummy + 0x0007)
#define PGA_Visible	(PGA_Dummy + 0x0008)
#define PGA_Top		(PGA_Dummy + 0x0009)
/* New for V37: */
#define PGA_NewLook	(PGA_Dummy + 0x000A)

/* STRGCLASS attributes	*/

#define STRINGA_Dummy			(TAG_USER      +0x32000)
#define STRINGA_MaxChars	(STRINGA_Dummy + 0x0001)
#define STRINGA_Buffer		(STRINGA_Dummy + 0x0002)
#define STRINGA_UndoBuffer	(STRINGA_Dummy + 0x0003)
#define STRINGA_WorkBuffer	(STRINGA_Dummy + 0x0004)
#define STRINGA_BufferPos	(STRINGA_Dummy + 0x0005)
#define STRINGA_DispPos		(STRINGA_Dummy + 0x0006)
#define STRINGA_AltKeyMap	(STRINGA_Dummy + 0x0007)
#define STRINGA_Font		(STRINGA_Dummy + 0x0008)
#define STRINGA_Pens		(STRINGA_Dummy + 0x0009)
#define STRINGA_ActivePens	(STRINGA_Dummy + 0x000A)
#define STRINGA_EditHook	(STRINGA_Dummy + 0x000B)
#define STRINGA_EditModes	(STRINGA_Dummy + 0x000C)

/* booleans */
#define STRINGA_ReplaceMode	(STRINGA_Dummy + 0x000D)
#define STRINGA_FixedFieldMode	(STRINGA_Dummy + 0x000E)
#define STRINGA_NoFilterMode	(STRINGA_Dummy + 0x000F)

#define STRINGA_Justification	(STRINGA_Dummy + 0x0010)
    /* GACT_STRINGCENTER, GACT_STRINGLEFT, GACT_STRINGRIGHT */
#define STRINGA_LongVal		(STRINGA_Dummy + 0x0011)
#define STRINGA_TextVal		(STRINGA_Dummy + 0x0012)

#define STRINGA_ExitHelp	(STRINGA_Dummy + 0x0013)
    /* STRINGA_ExitHelp is new for V37, and ignored by V36.
     * Set this if you want the gadget to exit when Help is
     * pressed.  Look for a code of 0x5F, the rawkey code for Help
     */

#define SG_DEFAULTMAXCHARS	(128)

/* Gadget Layout related attributes	*/

#define	LAYOUTA_Dummy		(TAG_USER  + 0x38000)
#define LAYOUTA_LayoutObj	(LAYOUTA_Dummy + 0x0001)
#define LAYOUTA_Spacing		(LAYOUTA_Dummy + 0x0002)
#define LAYOUTA_Orientation	(LAYOUTA_Dummy + 0x0003)

/* orientation values	*/
#define LORIENT_NONE	0
#define LORIENT_HORIZ	1
#define LORIENT_VERT	2

/* Gadget Method ID's	*/

#define GM_Dummy	(-1)	/* not used for anything		*/
#define GM_HITTEST	(0)	/* return GMR_GADGETHIT if you are clicked on
                 * (whether or not you are disabled).
                 */
#define GM_RENDER	(1)	/* draw yourself, in the appropriate state */
#define GM_GOACTIVE	(2)	/* you are now going to be fed input	*/
#define GM_HANDLEINPUT	(3)	/* handle that input			*/
#define GM_GOINACTIVE	(4)	/* whether or not by choice, you are done  */

/* Parameter "Messages" passed to gadget class methods	*/

/* GM_HITTEST	*/
struct gpHitTest {
    ULONG		MethodID;
    struct GadgetInfo	*gpht_GInfo;
    struct {
    WORD	X;
    WORD	Y;
    }			gpht_Mouse;
};
/* GM_HITTEST return value */
#define GMR_GADGETHIT	(0x00000004)	/* if no hit, return 0 */

/* GM_RENDER	*/
struct gpRender {
    ULONG		MethodID;
    struct GadgetInfo	*gpr_GInfo;	/* gadget context		*/
    struct RastPort	*gpr_RPort;	/* all ready for use		*/
    LONG		gpr_Redraw;	/* might be a "highlight pass"	*/
};

/* values of gpr_Redraw	*/
#define GREDRAW_UPDATE	(2)	/* incremental update, e.g. prop slider	*/
#define GREDRAW_REDRAW	(1)	/* redraw gadget	*/
#define GREDRAW_TOGGLE	(0)	/* toggle highlight, if applicable	*/

/* GM_GOACTIVE, GM_HANDLEINPUT	*/
struct gpInput {
    ULONG		MethodID;
    struct GadgetInfo	*gpi_GInfo;
    struct InputEvent	*gpi_IEvent;
    LONG		*gpi_Termination;
    struct {
    WORD	X;
    WORD	Y;
    }			gpi_Mouse;
};

/* GM_HANDLEINPUT and GM_GOACTIVE  return code flags	*/
/* return GMR_MEACTIVE (0) alone if you want more input.
 * Otherwise, return ONE of GMR_NOREUSE and GMR_REUSE, and optionally
 * GMR_VERIFY.
 */
#define GMR_MEACTIVE	(0)
#define GMR_NOREUSE	(1 << 1)
#define GMR_REUSE	(1 << 2)
#define GMR_VERIFY	(1 << 3)	/* you MUST set cgp_Termination */

/* New for V37:
 * You can end activation with one of GMR_NEXTACTIVE and GMR_PREVACTIVE,
 * which instructs Intuition to activate the next or previous gadget
 * that has GFLG_TABCYCLE set.
 */
#define GMR_NEXTACTIVE	(1 << 4)
#define GMR_PREVACTIVE	(1 << 5)

/* GM_GOINACTIVE */
struct gpGoInactive {
    ULONG		MethodID;
    struct GadgetInfo	*gpgi_GInfo;

    /* V37 field only!	DO NOT attempt to read under V36! */
    ULONG		gpgi_Abort;	/* gpgi_Abort=1 if gadget was aborted
                     * by Intuition and 0 if gadget went
                     * inactive at its own request
                     */
};

/* Include obsolete identifiers: */
#ifndef INTUITION_IOBSOLETE_H
#include <intuition/iobsolete.h>
#endif

#endif


Includes/intuition/intuition.h

#ifndef INTUITION_INTUITION_H
#define INTUITION_INTUITION_H TRUE
/*
**  $Filename: intuition/intuition.h $
**  $Release: 2.04 Includes, V37.4 $
**  $Revision: 36.51 $
**  $Date: 91/03/28 $
**
**  Interface definitions for Intuition applications.
**
**  (C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef GRAPHICS_GFX_H
#include <graphics/gfx.h>
#endif

#ifndef GRAPHICS_CLIP_H
#include <graphics/clip.h>
#endif

#ifndef GRAPHICS_VIEW_H
#include <graphics/view.h>
#endif

#ifndef GRAPHICS_RASTPORT_H
#include <graphics/rastport.h>
#endif

#ifndef GRAPHICS_LAYERS_H
#include <graphics/layers.h>
#endif

#ifndef GRAPHICS_TEXT_H
#include <graphics/text.h>
#endif

#ifndef EXEC_PORTS_H
#include <exec/ports.h>
#endif

#ifndef DEVICES_INPUTEVENT_H
#include <devices/inputevent.h>
#endif

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

/*
 * NOTE:  intuition/iobsolete.h is included at the END of this file!
 */

/* ======================================================================== */
/* === Menu =============================================================== */
/* ======================================================================== */
struct Menu
{
    struct Menu *NextMenu;	/* same level */
    WORD LeftEdge, TopEdge;	/* position of the select box */
    WORD Width, Height;	/* dimensions of the select box */
    UWORD Flags;		/* see flag definitions below */
    BYTE *MenuName;		/* text for this Menu Header */
    struct MenuItem *FirstItem; /* pointer to first in chain */

    /* these mysteriously-named variables are for internal use only */
    WORD JazzX, JazzY, BeatX, BeatY;
};

/* FLAGS SET BY BOTH THE APPLIPROG AND INTUITION */
#define MENUENABLED 0x0001	/* whether or not this menu is enabled */

/* FLAGS SET BY INTUITION */
#define MIDRAWN 0x0100		/* this menu's items are currently drawn */

/* ======================================================================== */
/* === MenuItem =========================================================== */
/* ======================================================================== */
struct MenuItem
{
    struct MenuItem *NextItem;	/* pointer to next in chained list */
    WORD LeftEdge, TopEdge;	/* position of the select box */
    WORD Width, Height;		/* dimensions of the select box */
    UWORD Flags;		/* see the defines below */

    LONG MutualExclude;		/* set bits mean this item excludes that */

    APTR ItemFill;		/* points to Image, IntuiText, or NULL */

    /* when this item is pointed to by the cursor and the items highlight
     *	mode HIGHIMAGE is selected, this alternate image will be displayed
     */
    APTR SelectFill;		/* points to Image, IntuiText, or NULL */

    BYTE Command;		/* only if appliprog sets the COMMSEQ flag */

    struct MenuItem *SubItem;	/* if non-zero, points to MenuItem for submenu */

    /* The NextSelect field represents the menu number of next selected
     *	item (when user has drag-selected several items)
     */
    UWORD NextSelect;
};

/* FLAGS SET BY THE APPLIPROG */
#define CHECKIT		0x0001	/* set to indicate checkmarkable item */
#define ITEMTEXT	0x0002	/* set if textual, clear if graphical item */
#define COMMSEQ		0x0004	/* set if there's an command sequence */
#define MENUTOGGLE	0x0008	/* set for toggling checks (else mut. exclude) */
#define ITEMENABLED	0x0010	/* set if this item is enabled */

/* these are the SPECIAL HIGHLIGHT FLAG state meanings */
#define HIGHFLAGS	0x00C0	/* see definitions below for these bits */
#define HIGHIMAGE	0x0000	/* use the user's "select image" */
#define HIGHCOMP	0x0040	/* highlight by complementing the selectbox */
#define HIGHBOX		0x0080	/* highlight by "boxing" the selectbox */
#define HIGHNONE	0x00C0	/* don't highlight */

/* FLAGS SET BY BOTH APPLIPROG AND INTUITION */
#define CHECKED	0x0100	/* state of the checkmark */

/* FLAGS SET BY INTUITION */
#define ISDRAWN		0x1000	/* this item's subs are currently drawn */
#define HIGHITEM	0x2000	/* this item is currently highlighted */
#define MENUTOGGLED	0x4000	/* this item was already toggled */

/* ======================================================================== */
/* === Requester ========================================================== */
/* ======================================================================== */
struct Requester
{
    struct Requester *OlderRequest;
    WORD LeftEdge, TopEdge;		/* dimensions of the entire box */
    WORD Width, Height;			/* dimensions of the entire box */
    WORD RelLeft, RelTop;		/* for Pointer relativity offsets */

    struct Gadget *ReqGadget;		/* pointer to a list of Gadgets */
    struct Border *ReqBorder;		/* the box's border */
    struct IntuiText *ReqText;		/* the box's text */
    UWORD Flags;			/* see definitions below */

    /* pen number for back-plane fill before draws */
    UBYTE BackFill;
    /* Layer in place of clip rect	*/
    struct Layer *ReqLayer;

    UBYTE ReqPad1[32];

    /* If the BitMap plane pointers are non-zero, this tells the system
     * that the image comes pre-drawn (if the appliprog wants to define
     * its own box, in any shape or size it wants!);  this is OK by
     * Intuition as long as there's a good correspondence between
     * the image and the specified Gadgets
     */
    struct BitMap *ImageBMap;	/* points to the BitMap of PREDRAWN imagery */
    struct Window *RWindow;	/* added.  points back to Window */

    struct Image  *ReqImage;	/* new for V36: drawn if USEREQIMAGE set */

    UBYTE ReqPad2[32];
};

/* FLAGS SET BY THE APPLIPROG */
#define POINTREL	0x0001
              /* if POINTREL set, TopLeft is relative to pointer
               * for DMRequester, relative to window center
               * for Request().
               */
#define PREDRAWN	0x0002
    /* set if Requester.ImageBMap points to predrawn Requester imagery */
#define NOISYREQ	0x0004
    /* if you don't want requester to filter input	   */
#define SIMPLEREQ	0x0010
    /* to use SIMPLEREFRESH layer (recommended)	*/

/* New for V36		*/
#define USEREQIMAGE	0x0020
    /*  render linked list ReqImage after BackFill
     * but before gadgets and text
     */
#define NOREQBACKFILL	0x0040
    /* don't bother filling requester with Requester.BackFill pen	*/

/* FLAGS SET BY INTUITION */
#define REQOFFWINDOW	0x1000	/* part of one of the Gadgets was offwindow */
#define REQACTIVE	0x2000	/* this requester is active */
#define SYSREQUEST	0x4000	/* (unused) this requester caused by system */
#define DEFERREFRESH	0x8000	/* this Requester stops a Refresh broadcast */

/* ======================================================================== */
/* === Gadget ============================================================= */
/* ======================================================================== */
struct Gadget
{
    struct Gadget *NextGadget;	/* next gadget in the list */

    WORD LeftEdge, TopEdge;	/* "hit box" of gadget */
    WORD Width, Height;		/* "hit box" of gadget */

    UWORD Flags;		/* see below for list of defines */

    UWORD Activation;		/* see below for list of defines */

    UWORD GadgetType;		/* see below for defines */

    /* appliprog can specify that the Gadget be rendered as either as Border
     * or an Image.  This variable points to which (or equals NULL if there's
     * nothing to be rendered about this Gadget)
     */
    APTR GadgetRender;

    /* appliprog can specify "highlighted" imagery rather than algorithmic
     * this can point to either Border or Image data
     */
    APTR SelectRender;

    struct IntuiText *GadgetText;   /* text for this gadget */

    /* MutualExclude, never implemented, is now declared obsolete.
     * There are published examples of implementing a more general
     * and practical exclusion in your applications.
     *
     * Starting with V36, this field is used to point to a hook
     * for a custom gadget.
     *
     * Programs using this field for their own processing will
     * continue to work, as long as they don't try the
     * trick with custom gadgets.
     */
    LONG MutualExclude;  /* obsolete */

    /* pointer to a structure of special data required by Proportional,
     * String and Integer Gadgets
     */
    APTR SpecialInfo;

    UWORD GadgetID;	/* user-definable ID field */
    APTR UserData;	/* ptr to general purpose User data (ignored by In) */
};

/* --- Gadget.Flags values	--- */
/* combinations in these bits describe the highlight technique to be used */
#define GFLG_GADGHIGHBITS 0x0003
#define GFLG_GADGHCOMP	  0x0000  /* Complement the select box */
#define GFLG_GADGHBOX	  0x0001  /* Draw a box around the image */
#define GFLG_GADGHIMAGE	  0x0002  /* Blast in this alternate image */
#define GFLG_GADGHNONE	  0x0003  /* don't highlight */

#define GFLG_GADGIMAGE		  0x0004  /* set if GadgetRender and SelectRender
                   * point to an Image structure, clear
                   * if they point to Border structures
                   */

/* combinations in these next two bits specify to which corner the gadget's
 *  Left & Top coordinates are relative.  If relative to Top/Left,
 *  these are "normal" coordinates (everything is relative to something in
 *  this universe).
 *
 * Gadget positions and dimensions are relative to the window or
 * requester which contains the gadget
 */
#define GFLG_RELBOTTOM	  0x0008  /* vert. pos. is relative to bottom edge */
#define GFLG_RELRIGHT	  0x0010  /* horiz. pos. is relative to right edge */
#define GFLG_RELWIDTH	  0x0020  /* width is relative to req/window	*/
#define GFLG_RELHEIGHT	  0x0040  /* height is relative to req/window	*/

#define GFLG_SELECTED	  0x0080  /* you may initialize and look at this	*/

/* the GFLG_DISABLED flag is initialized by you and later set by Intuition
 * according to your calls to On/OffGadget().  It specifies whether or not
 * this Gadget is currently disabled from being selected
 */
#define GFLG_DISABLED	  0x0100

/* These flags specify the type of text field that Gadget.GadgetText
 * points to.  In all normal (pre-V36) gadgets which you initialize
 * this field should always be zero.  Some types of gadget objects
 * created from classes will use these fields to keep track of
 * types of labels/contents that different from IntuiText, but are
 * stashed in GadgetText.
 */

#define GFLG_LABELMASK	  0x3000
#define GFLG_LABELITEXT	  0x0000  /* GadgetText points to IntuiText	*/
#define	GFLG_LABELSTRING  0x1000  /* GadgetText points to (UBYTE *)	*/
#define GFLG_LABELIMAGE	  0x2000  /* GadgetText points to Image (object)	*/

/* New for V37: GFLG_TABCYCLE */
#define GFLG_TABCYCLE	  0x0200  /* (string or custom) gadget participates in
                   * cycling activation with Tab or Shift-Tab
                   */
/* New for V37: GFLG_STRINGEXTEND.  We discovered that V34 doesn't properly
 * ignore the value we had chosen for the Gadget->Activation flag
 * GACT_STRINGEXTEND.  NEVER SET THAT FLAG WHEN RUNNING UNDER V34.
 * The Gadget->Flags bit GFLG_STRINGEXTEND is provided as a synonym which is
 * safe under V34, and equivalent to GACT_STRINGEXTEND under V37.
 * (Note that the two flags are not numerically equal)
 */
#define GFLG_STRINGEXTEND 0x0400  /* this String Gadget has StringExtend	*/

/* ---	Gadget.Activation flag values	--- */
/* Set GACT_RELVERIFY if you want to verify that the pointer was still over
 * the gadget when the select button was released.  Will cause
 * an IDCMP_GADGETUP message to be sent if so.
 */
#define GACT_RELVERIFY	  0x0001

/* the flag GACT_IMMEDIATE, when set, informs the caller that the gadget
 *  was activated when it was activated.  This flag works in conjunction with
 *  the GACT_RELVERIFY flag
 */
#define GACT_IMMEDIATE	  0x0002

/* the flag GACT_ENDGADGET, when set, tells the system that this gadget,
 * when selected, causes the Requester to be ended.  Requesters
 * that are ended are erased and unlinked from the system.
 */
#define GACT_ENDGADGET	  0x0004

/* the GACT_FOLLOWMOUSE flag, when set, specifies that you want to receive
 * reports on mouse movements while this gadget is active.
 * You probably want to set the GACT_IMMEDIATE flag when using
 * GACT_FOLLOWMOUSE, since that's the only reasonable way you have of
 * learning why Intuition is suddenly sending you a stream of mouse
 * movement events.  If you don't set GACT_RELVERIFY, you'll get at
 * least one Mouse Position event.
 * Note: boolean FOLLOWMOUSE gadgets require GACT_RELVERIFY to get
 * _any_ mouse movement events (this unusual behavior is a compatibility
 * hold-over from the old days).
 */
#define GACT_FOLLOWMOUSE  0x0008

/* if any of the BORDER flags are set in a Gadget that's included in the
 * Gadget list when a Window is opened, the corresponding Border will
 * be adjusted to make room for the Gadget
 */
#define GACT_RIGHTBORDER  0x0010
#define GACT_LEFTBORDER	  0x0020
#define GACT_TOPBORDER	  0x0040
#define GACT_BOTTOMBORDER 0x0080
#define GACT_BORDERSNIFF  0x8000  /* neither set nor rely on this bit	*/

#define GACT_TOGGLESELECT 0x0100  /* this bit for toggle-select mode */
#define GACT_BOOLEXTEND	  0x2000  /* this Boolean Gadget has a BoolInfo	*/

/* should properly be in StringInfo, but aren't	*/
#define GACT_STRINGLEFT	  0x0000  /* NOTE WELL: that this has value zero	*/
#define GACT_STRINGCENTER 0x0200
#define GACT_STRINGRIGHT  0x0400
#define GACT_LONGINT	  0x0800  /* this String Gadget is for Long Ints	*/
#define GACT_ALTKEYMAP	  0x1000  /* this String has an alternate keymap	*/
#define GACT_STRINGEXTEND 0x2000  /* this String Gadget has StringExtend	*/
                  /* NOTE: NEVER SET GACT_STRINGEXTEND IF YOU
                   * ARE RUNNING ON LESS THAN V36!  SEE
                   * GFLG_STRINGEXTEND (ABOVE) INSTEAD
                   */

#define GACT_ACTIVEGADGET 0x4000  /* this gadget is "active".  This flag
                   * is maintained by Intuition, and you
                   * cannot count on its value persisting
                   * while you do something on your program's
                   * task.  It can only be trusted by
                   * people implementing custom gadgets
                   */

/* note 0x8000 is used above (GACT_BORDERSNIFF);
 * all Activation flags defined */

/* --- GADGET TYPES ------------------------------------------------------- */
/* These are the Gadget Type definitions for the variable GadgetType
 * gadget number type MUST start from one.  NO TYPES OF ZERO ALLOWED.
 * first comes the mask for Gadget flags reserved for Gadget typing
 */
#define GTYP_GADGETTYPE	0xFC00	/* all Gadget Global Type flags (padded) */
#define GTYP_SYSGADGET	0x8000	/* 1 = Allocated by the system, 0 = by app. */
#define GTYP_SCRGADGET	0x4000	/* 1 = ScreenGadget, 0 = WindowGadget */
#define GTYP_GZZGADGET	0x2000	/* 1 = for WFLG_GIMMEZEROZERO borders */
#define GTYP_REQGADGET	0x1000	/* 1 = this is a Requester Gadget */
/* system gadgets */
#define GTYP_SIZING	0x0010
#define GTYP_WDRAGGING	0x0020
#define GTYP_SDRAGGING	0x0030
#define GTYP_WUPFRONT	0x0040
#define GTYP_SUPFRONT	0x0050
#define GTYP_WDOWNBACK	0x0060
#define GTYP_SDOWNBACK	0x0070
#define GTYP_CLOSE	0x0080
/* application gadgets */
#define GTYP_BOOLGADGET	0x0001
#define GTYP_GADGET0002	0x0002
#define GTYP_PROPGADGET	0x0003
#define GTYP_STRGADGET	0x0004
#define GTYP_CUSTOMGADGET	0x0005
#define GTYP_GTYPEMASK	0x0007	/* masks out to gadget class	*/

/* This bit in GadgetType is reserved for undocumented internal use
 * by the Gadget Toolkit, and cannot be used nor relied on by
 * applications:	0x0100
 */

/* ======================================================================== */
/* === BoolInfo======================================================= */
/* ======================================================================== */
/* This is the special data needed by an Extended Boolean Gadget
 * Typically this structure will be pointed to by the Gadget field SpecialInfo
 */
struct BoolInfo
{
    UWORD  Flags;	/* defined below */
    UWORD  *Mask;	/* bit mask for highlighting and selecting
             * mask must follow the same rules as an Image
             * plane.  Its width and height are determined
             * by the width and height of the gadget's
             * select box. (i.e. Gadget.Width and .Height).
             */
    ULONG  Reserved;	/* set to 0	*/
};

/* set BoolInfo.Flags to this flag bit.
 * in the future, additional bits might mean more stuff hanging
 * off of BoolInfo.Reserved.
 */
#define BOOLMASK	0x0001	/* extension is for masked gadget */

/* ======================================================================== */
/* === PropInfo =========================================================== */
/* ======================================================================== */
/* this is the special data required by the proportional Gadget
 * typically, this data will be pointed to by the Gadget variable SpecialInfo
 */
struct PropInfo
{
    UWORD Flags;	/* general purpose flag bits (see defines below) */

    /* You initialize the Pot variables before the Gadget is added to
     * the system.  Then you can look here for the current settings
     * any time, even while User is playing with this Gadget.  To
     * adjust these after the Gadget is added to the System, use
     * ModifyProp();  The Pots are the actual proportional settings,
     * where a value of zero means zero and a value of MAXPOT means
     * that the Gadget is set to its maximum setting.
     */
    UWORD HorizPot;	/* 16-bit FixedPoint horizontal quantity percentage */
    UWORD VertPot;	/* 16-bit FixedPoint vertical quantity percentage */

    /* the 16-bit FixedPoint Body variables describe what percentage of
     * the entire body of stuff referred to by this Gadget is actually
     * shown at one time.  This is used with the AUTOKNOB routines,
     * to adjust the size of the AUTOKNOB according to how much of
     * the data can be seen.  This is also used to decide how far
     * to advance the Pots when User hits the Container of the Gadget.
     * For instance, if you were controlling the display of a 5-line
     * Window of text with this Gadget, and there was a total of 15
     * lines that could be displayed, you would set the VertBody value to
     *	   (MAXBODY / (TotalLines / DisplayLines)) = MAXBODY / 3.
     * Therefore, the AUTOKNOB would fill 1/3 of the container, and
     * if User hits the Cotainer outside of the knob, the pot would
     * advance 1/3 (plus or minus) If there's no body to show, or
     * the total amount of displayable info is less than the display area,
     * set the Body variables to the MAX.  To adjust these after the
     * Gadget is added to the System, use ModifyProp();
     */
    UWORD HorizBody;		/* horizontal Body */
    UWORD VertBody;		/* vertical Body */

    /* these are the variables that Intuition sets and maintains */
    UWORD CWidth;	/* Container width (with any relativity absoluted) */
    UWORD CHeight;	/* Container height (with any relativity absoluted) */
    UWORD HPotRes, VPotRes;	/* pot increments */
    UWORD LeftBorder;		/* Container borders */
    UWORD TopBorder;		/* Container borders */
};

/* --- FLAG BITS ---------------------------------------------------------- */
#define AUTOKNOB	0x0001	/* this flag sez:  gimme that old auto-knob */
/* NOTE: if you do not use an AUTOKNOB for a proportional gadget,
 * you are currently limited to using a single Image of your own
 * design: Intuition won't handle a linked list of images as
 * a proportional gadget knob.
 */

#define FREEHORIZ	0x0002	/* if set, the knob can move horizontally */
#define FREEVERT	0x0004	/* if set, the knob can move vertically */
#define PROPBORDERLESS	0x0008	/* if set, no border will be rendered */
#define KNOBHIT		0x0100	/* set when this Knob is hit */
#define PROPNEWLOOK	0x0010	/* set this if you want to get the new
                 * V36 look
                 */

#define KNOBHMIN	6	/* minimum horizontal size of the Knob */
#define KNOBVMIN	4	/* minimum vertical size of the Knob */
#define MAXBODY		0xFFFF	/* maximum body value */
#define MAXPOT			0xFFFF	/* maximum pot value */

/* ======================================================================== */
/* === StringInfo ========================================================= */
/* ======================================================================== */
/* this is the special data required by the string Gadget
 * typically, this data will be pointed to by the Gadget variable SpecialInfo
 */
struct StringInfo
{
    /* you initialize these variables, and then Intuition maintains them */
    UBYTE *Buffer;	/* the buffer containing the start and final string */
    UBYTE *UndoBuffer;	/* optional buffer for undoing current entry */
    WORD BufferPos;	/* character position in Buffer */
    WORD MaxChars;	/* max number of chars in Buffer (including NULL) */
    WORD DispPos;	/* Buffer position of first displayed character */

    /* Intuition initializes and maintains these variables for you */
    WORD UndoPos;	/* character position in the undo buffer */
    WORD NumChars;	/* number of characters currently in Buffer */
    WORD DispCount;	/* number of whole characters visible in Container */
    WORD CLeft, CTop;	/* topleft offset of the container */

    /* This unused field is changed to allow extended specification
     * of string gadget parameters.  It is ignored unless the flag
     * GACT_STRINGEXTEND is set in the Gadget's Activation field
     * or the GFLG_STRINGEXTEND flag is set in the Gadget Flags field.
     * (See GFLG_STRINGEXTEND for an important note)
     */
    /* struct Layer *LayerPtr;	--- obsolete --- */
    struct StringExtend *Extension;

    /* you can initialize this variable before the gadget is submitted to
     * Intuition, and then examine it later to discover what integer
     * the user has entered (if the user never plays with the gadget,
     * the value will be unchanged from your initial setting)
     */
    LONG LongInt;

    /* If you want this Gadget to use your own Console keymapping, you
     * set the GACT_ALTKEYMAP bit in the Activation flags of the Gadget,
     * and then set this variable to point to your keymap.  If you don't
     * set the GACT_ALTKEYMAP, you'll get the standard ASCII keymapping.
     */
    struct KeyMap *AltKeyMap;
};

/* ======================================================================== */
/* === IntuiText ========================================================== */
/* ======================================================================== */
/* IntuiText is a series of strings that start with a location
 *  (always relative to the upper-left corner of something) and then the
 *  text of the string.  The text is null-terminated.
 */
struct IntuiText
{
    UBYTE FrontPen, BackPen;	/* the pen numbers for the rendering */
    UBYTE DrawMode;		/* the mode for rendering the text */
    WORD LeftEdge;		/* relative start location for the text */
    WORD TopEdge;		/* relative start location for the text */
    struct TextAttr *ITextFont;	/* if NULL, you accept the default */
    UBYTE *IText;		/* pointer to null-terminated text */
    struct IntuiText *NextText; /* pointer to another IntuiText to render */
};

/* ======================================================================== */
/* === Border ============================================================= */
/* ======================================================================== */
/* Data type Border, used for drawing a series of lines which is intended for
 *  use as a border drawing, but which may, in fact, be used to render any
 *  arbitrary vector shape.
 *  The routine DrawBorder sets up the RastPort with the appropriate
 *  variables, then does a Move to the first coordinate, then does Draws
 *  to the subsequent coordinates.
 *  After all the Draws are done, if NextBorder is non-zero we call DrawBorder
 *  on NextBorder
 */
struct Border
{
    WORD LeftEdge, TopEdge;	/* initial offsets from the origin */
    UBYTE FrontPen, BackPen;	/* pens numbers for rendering */
    UBYTE DrawMode;		/* mode for rendering */
    BYTE Count;			/* number of XY pairs */
    WORD *XY;			/* vector coordinate pairs rel to LeftTop */
    struct Border *NextBorder;	/* pointer to any other Border too */
};

/* ======================================================================== */
/* === Image ============================================================== */
/* ======================================================================== */
/* This is a brief image structure for very simple transfers of
 * image data to a RastPort
 */
struct Image
{
    WORD LeftEdge;		/* starting offset relative to some origin */
    WORD TopEdge;		/* starting offsets relative to some origin */
    WORD Width;			/* pixel size (though data is word-aligned) */
    WORD Height;
    WORD Depth;			/* >= 0, for images you create		*/
    UWORD *ImageData;		/* pointer to the actual word-aligned bits */

    /* the PlanePick and PlaneOnOff variables work much the same way as the
     * equivalent GELS Bob variables.  It's a space-saving
     * mechanism for image data.  Rather than defining the image data
     * for every plane of the RastPort, you need define data only
     * for the planes that are not entirely zero or one.  As you
     * define your Imagery, you will often find that most of the planes
     * ARE just as color selectors.  For instance, if you're designing
     * a two-color Gadget to use colors one and three, and the Gadget
     * will reside in a five-plane display, bit plane zero of your
     * imagery would be all ones, bit plane one would have data that
     * describes the imagery, and bit planes two through four would be
     * all zeroes.  Using these flags avoids wasting all
     * that memory in this way:  first, you specify which planes you
     * want your data to appear in using the PlanePick variable.  For
     * each bit set in the variable, the next "plane" of your image
     * data is blitted to the display.	For each bit clear in this
     * variable, the corresponding bit in PlaneOnOff is examined.
     * If that bit is clear, a "plane" of zeroes will be used.
     * If the bit is set, ones will go out instead.  So, for our example:
     *	 Gadget.PlanePick = 0x02;
     *	 Gadget.PlaneOnOff = 0x01;
     * Note that this also allows for generic Gadgets, like the
     * System Gadgets, which will work in any number of bit planes.
     * Note also that if you want an Image that is only a filled
     * rectangle, you can get this by setting PlanePick to zero
     * (pick no planes of data) and set PlaneOnOff to describe the pen
     * color of the rectangle.
     *
     * NOTE:  Intuition relies on PlanePick to know how many planes
     * of data are found in ImageData.	There should be no more
     * '1'-bits in PlanePick than there are planes in ImageData.
     */
    UBYTE PlanePick, PlaneOnOff;

    /* if the NextImage variable is not NULL, Intuition presumes that
     * it points to another Image structure with another Image to be
     * rendered
     */
    struct Image *NextImage;
};

/* ======================================================================== */
/* === IntuiMessage ======================================================= */
/* ======================================================================== */
struct IntuiMessage
{
    struct Message ExecMessage;

    /* the Class bits correspond directly with the IDCMP Flags, except for the
     * special bit IDCMP_LONELYMESSAGE (defined below)
     */
    ULONG Class;

    /* the Code field is for special values like MENU number */
    UWORD Code;

    /* the Qualifier field is a copy of the current InputEvent's Qualifier */
    UWORD Qualifier;

    /* IAddress contains particular addresses for Intuition functions, like
     * the pointer to the Gadget or the Screen
     */
    APTR IAddress;

    /* when getting mouse movement reports, any event you get will have the
     * the mouse coordinates in these variables.  the coordinates are relative
     * to the upper-left corner of your Window (WFLG_GIMMEZEROZERO
     * notwithstanding).  If IDCMP_DELTAMOVE is set, these values will
     * be deltas from the last reported position.
     */
    WORD MouseX, MouseY;

    /* the time values are copies of the current system clock time.  Micros
     * are in units of microseconds, Seconds in seconds.
     */
    ULONG Seconds, Micros;

    /* the IDCMPWindow variable will always have the address of the Window of
     * this IDCMP
     */
    struct Window *IDCMPWindow;

    /* system-use variable */
    struct IntuiMessage *SpecialLink;
};

/* --- IDCMP Classes ------------------------------------------------------ */
/* Please refer to the Autodoc for OpenWindow() and to the Rom Kernel
 * Manual for full details on the IDCMP classes.
 */
#define IDCMP_SIZEVERIFY	0x00000001
#define IDCMP_NEWSIZE		0x00000002
#define IDCMP_REFRESHWINDOW	0x00000004
#define IDCMP_MOUSEBUTTONS	0x00000008
#define IDCMP_MOUSEMOVE		0x00000010
#define IDCMP_GADGETDOWN	0x00000020
#define IDCMP_GADGETUP		0x00000040
#define IDCMP_REQSET		0x00000080
#define IDCMP_MENUPICK		0x00000100
#define IDCMP_CLOSEWINDOW	0x00000200
#define IDCMP_RAWKEY		0x00000400
#define IDCMP_REQVERIFY		0x00000800
#define IDCMP_REQCLEAR		0x00001000
#define IDCMP_MENUVERIFY	0x00002000
#define IDCMP_NEWPREFS		0x00004000
#define IDCMP_DISKINSERTED	0x00008000
#define IDCMP_DISKREMOVED	0x00010000
#define IDCMP_WBENCHMESSAGE	0x00020000  /*	System use only		*/
#define IDCMP_ACTIVEWINDOW	0x00040000
#define IDCMP_INACTIVEWINDOW	0x00080000
#define IDCMP_DELTAMOVE		0x00100000
#define IDCMP_VANILLAKEY	0x00200000
#define IDCMP_INTUITICKS	0x00400000
/*  for notifications from "boopsi" gadgets	*/
#define IDCMP_IDCMPUPDATE	0x00800000  /* new for V36	*/
/* for getting help key report during menu session	*/
#define IDCMP_MENUHELP		0x01000000  /* new for V36	*/
/* for notification of any move/size/zoom/change window		*/
#define IDCMP_CHANGEWINDOW	0x02000000  /* new for V36	*/

/* NOTEZ-BIEN:				0x80000000 is reserved for internal use   */

/* the IDCMP Flags do not use this special bit, which is cleared when
 * Intuition sends its special message to the Task, and set when Intuition
 * gets its Message back from the Task.  Therefore, I can check here to
 * find out fast whether or not this Message is available for me to send
 */
#define IDCMP_LONELYMESSAGE	0x80000000

/* --- IDCMP Codes -------------------------------------------------------- */
/* This group of codes is for the IDCMP_MENUVERIFY function */
#define MENUHOT		0x0001	/* IntuiWants verification or MENUCANCEL    */
#define MENUCANCEL	0x0002	/* HOT Reply of this cancels Menu operation */
#define MENUWAITING	0x0003	/* Intuition simply wants a ReplyMsg() ASAP */

/* These are internal tokens to represent state of verification attempts
 * shown here as a clue.
 */
#define OKOK		MENUHOT	/* guy didn't care			*/
#define OKABORT		0x0004	/* window rendered question moot	*/
#define OKCANCEL	MENUCANCEL /* window sent cancel reply		*/

/* This group of codes is for the IDCMP_WBENCHMESSAGE messages */
#define WBENCHOPEN	0x0001
#define WBENCHCLOSE	0x0002

/* A data structure common in V36 Intuition processing	*/
struct IBox {
    WORD Left;
    WORD Top;
    WORD Width;
    WORD Height;
    };

/* ======================================================================== */
/* === Window ============================================================= */
/* ======================================================================== */
struct Window
{
    struct Window *NextWindow;		/* for the linked list in a screen */

    WORD LeftEdge, TopEdge;		/* screen dimensions of window */
    WORD Width, Height;			/* screen dimensions of window */

    WORD MouseY, MouseX;		/* relative to upper-left of window */

    WORD MinWidth, MinHeight;		/* minimum sizes */
    UWORD MaxWidth, MaxHeight;		/* maximum sizes */

    ULONG Flags;			/* see below for defines */

    struct Menu *MenuStrip;		/* the strip of Menu headers */

    UBYTE *Title;			/* the title text for this window */

    struct Requester *FirstRequest;	/* all active Requesters */

    struct Requester *DMRequest;	/* double-click Requester */

    WORD ReqCount;			/* count of reqs blocking Window */

    struct Screen *WScreen;		/* this Window's Screen */
    struct RastPort *RPort;		/* this Window's very own RastPort */

    /* the border variables describe the window border.  If you specify
     * WFLG_GIMMEZEROZERO when you open the window, then the upper-left of
     * the ClipRect for this window will be upper-left of the BitMap (with
     * correct offsets when in SuperBitMap mode; you MUST select
     * WFLG_GIMMEZEROZERO when using SuperBitMap).  If you don't specify
     * ZeroZero, then you save memory (no allocation of RastPort, Layer,
     * ClipRect and associated Bitmaps), but you also must offset all your
     * writes by BorderTop, BorderLeft and do your own mini-clipping to
     * prevent writing over the system gadgets
     */
    BYTE BorderLeft, BorderTop, BorderRight, BorderBottom;
    struct RastPort *BorderRPort;

    /* You supply a linked-list of Gadgets for your Window.
     * This list DOES NOT include system gadgets.  You get the standard
     * window system gadgets by setting flag-bits in the variable Flags (see
     * the bit definitions below)
     */
    struct Gadget *FirstGadget;

    /* these are for opening/closing the windows */
    struct Window *Parent, *Descendant;

    /* sprite data information for your own Pointer
     * set these AFTER you Open the Window by calling SetPointer()
     */
    UWORD *Pointer;	/* sprite data */
    BYTE PtrHeight;	/* sprite height (not including sprite padding) */
    BYTE PtrWidth;	/* sprite width (must be less than or equal to 16) */
    BYTE XOffset, YOffset;	/* sprite offsets */

    /* the IDCMP Flags and User's and Intuition's Message Ports */
    ULONG IDCMPFlags;	/* User-selected flags */
    struct MsgPort *UserPort, *WindowPort;
    struct IntuiMessage *MessageKey;

    UBYTE DetailPen, BlockPen;	/* for bar/border/gadget rendering */

    /* the CheckMark is a pointer to the imagery that will be used when
     * rendering MenuItems of this Window that want to be checkmarked
     * if this is equal to NULL, you'll get the default imagery
     */
    struct Image *CheckMark;

    UBYTE *ScreenTitle;	/* if non-null, Screen title when Window is active */

    /* These variables have the mouse coordinates relative to the
     * inner-Window of WFLG_GIMMEZEROZERO Windows.  This is compared with the
     * MouseX and MouseY variables, which contain the mouse coordinates
     * relative to the upper-left corner of the Window, WFLG_GIMMEZEROZERO
     * notwithstanding
     */
    WORD GZZMouseX;
    WORD GZZMouseY;
    /* these variables contain the width and height of the inner-Window of
     * WFLG_GIMMEZEROZERO Windows
     */
    WORD GZZWidth;
    WORD GZZHeight;

    UBYTE *ExtData;

    BYTE *UserData;	/* general-purpose pointer to User data extension */

    /** 11/18/85: this pointer keeps a duplicate of what
     * Window.RPort->Layer is _supposed_ to be pointing at
     */
    struct Layer *WLayer;

    /* NEW 1.2: need to keep track of the font that
     * OpenWindow opened, in case user SetFont's into RastPort
     */
    struct TextFont *IFont;

    /* (V36) another flag word (the Flags field is used up).
     * At present, all flag values are system private.
     * Until further notice, you may not change nor use this field.
     */
    ULONG	MoreFlags;

    /**** Data beyond this point are Intuition Private.  DO NOT USE ****/
};

/* --- Flags requested at OpenWindow() time by the application --------- */
#define WFLG_SIZEGADGET	    0x00000001	/* include sizing system-gadget? */
#define WFLG_DRAGBAR	    0x00000002	/* include dragging system-gadget? */
#define WFLG_DEPTHGADGET    0x00000004	/* include depth arrangement gadget? */
#define WFLG_CLOSEGADGET    0x00000008	/* include close-box system-gadget? */

#define WFLG_SIZEBRIGHT	    0x00000010	/* size gadget uses right border */
#define WFLG_SIZEBBOTTOM    0x00000020	/* size gadget uses bottom border */

/* --- refresh modes ------------------------------------------------------ */
/* combinations of the WFLG_REFRESHBITS select the refresh type */
#define WFLG_REFRESHBITS    0x000000C0
#define WFLG_SMART_REFRESH  0x00000000
#define WFLG_SIMPLE_REFRESH 0x00000040
#define WFLG_SUPER_BITMAP   0x00000080
#define WFLG_OTHER_REFRESH  0x000000C0

#define WFLG_BACKDROP	    0x00000100	/* this is a backdrop window */

#define WFLG_REPORTMOUSE    0x00000200	/* to hear about every mouse move */

#define WFLG_GIMMEZEROZERO  0x00000400	/* a GimmeZeroZero window	*/

#define WFLG_BORDERLESS	    0x00000800	/* to get a Window sans border */

#define WFLG_ACTIVATE	    0x00001000	/* when Window opens, it's Active */

/* FLAGS SET BY INTUITION */
#define WFLG_WINDOWACTIVE   0x00002000	/* this window is the active one */
#define WFLG_INREQUEST	    0x00004000	/* this window is in request mode */
#define WFLG_MENUSTATE	    0x00008000	/* Window is active with Menus on */

/* --- Other User Flags --------------------------------------------------- */
#define WFLG_RMBTRAP	    0x00010000	/* Catch RMB events for your own */
#define WFLG_NOCAREREFRESH  0x00020000	/* not to be bothered with REFRESH */

/* --- Other Intuition Flags ---------------------------------------------- */
#define WFLG_WINDOWREFRESH  0x01000000	/* Window is currently refreshing */
#define WFLG_WBENCHWINDOW   0x02000000	/* WorkBench tool ONLY Window */
#define WFLG_WINDOWTICKED   0x04000000	/* only one timer tick at a time */

/* - V36 new Flags which the programmer may specify in NewWindow.Flags	*/
#define WFLG_NW_EXTENDED    0x00040000	/* extension data provided	*/
                    /* see struct ExtNewWindow	*/

/* --- V36 Flags to be set only by Intuition -------------------------	*/
#define WFLG_VISITOR	    0x08000000	/* visitor window		*/
#define WFLG_ZOOMED	    0x10000000	/* identifies "zoom state"	*/
#define WFLG_HASZOOM	    0x20000000	/* windowhas a zoom gadget	*/

/* --- Other Window Values ---------------------------------------------- */
#define DEFAULTMOUSEQUEUE	(5)	/* no more mouse messages	*/

/* --- see struct IntuiMessage for the IDCMP Flag definitions ------------- */

/* ======================================================================== */
/* === NewWindow ========================================================== */
/* ======================================================================== */
/*
 * Note that the new extension fields have been removed.  Use ExtNewWindow
 * structure below to make use of these fields
 */
struct NewWindow
{
    WORD LeftEdge, TopEdge;		/* screen dimensions of window */
    WORD Width, Height;			/* screen dimensions of window */

    UBYTE DetailPen, BlockPen;		/* for bar/border/gadget rendering */

    ULONG IDCMPFlags;			/* User-selected IDCMP flags */

    ULONG Flags;			/* see Window struct for defines */

    /* You supply a linked-list of Gadgets for your Window.
     *	This list DOES NOT include system Gadgets.  You get the standard
     *	system Window Gadgets by setting flag-bits in the variable Flags (see
     *	the bit definitions under the Window structure definition)
     */
    struct Gadget *FirstGadget;

    /* the CheckMark is a pointer to the imagery that will be used when
     * rendering MenuItems of this Window that want to be checkmarked
     * if this is equal to NULL, you'll get the default imagery
     */
    struct Image *CheckMark;

    UBYTE *Title;			  /* the title text for this window */

    /* the Screen pointer is used only if you've defined a CUSTOMSCREEN and
     * want this Window to open in it.	If so, you pass the address of the
     * Custom Screen structure in this variable.  Otherwise, this variable
     * is ignored and doesn't have to be initialized.
     */
    struct Screen *Screen;

    /* WFLG_SUPER_BITMAP Window?  If so, put the address of your BitMap
     * structure in this variable.  If not, this variable is ignored and
     * doesn't have to be initialized
     */
    struct BitMap *BitMap;

    /* the values describe the minimum and maximum sizes of your Windows.
     * these matter only if you've chosen the WFLG_SIZEGADGET option,
     * which means that you want to let the User to change the size of
     * this Window.  You describe the minimum and maximum sizes that the
     * Window can grow by setting these variables.  You can initialize
     * any one these to zero, which will mean that you want to duplicate
     * the setting for that dimension (if MinWidth == 0, MinWidth will be
     * set to the opening Width of the Window).
     * You can change these settings later using SetWindowLimits().
     * If you haven't asked for a SIZING Gadget, you don't have to
     * initialize any of these variables.
     */
    WORD MinWidth, MinHeight;	    /* minimums */
    UWORD MaxWidth, MaxHeight;	     /* maximums */

    /* the type variable describes the Screen in which you want this Window to
     * open.  The type value can either be CUSTOMSCREEN or one of the
     * system standard Screen Types such as WBENCHSCREEN.  See the
     * type definitions under the Screen structure.
     */
    UWORD Type;

};

/* The following structure is the future NewWindow.  Compatibility
 * issues require that the size of NewWindow not change.
 * Data in the common part (NewWindow) indicates the the extension
 * fields are being used.
 * NOTE WELL: This structure may be subject to future extension.
 * Writing code depending on its size is not allowed.
 */
struct ExtNewWindow
{
    WORD LeftEdge, TopEdge;
    WORD Width, Height;

    UBYTE DetailPen, BlockPen;
    ULONG IDCMPFlags;
    ULONG Flags;
    struct Gadget *FirstGadget;

    struct Image *CheckMark;

    UBYTE *Title;
    struct Screen *Screen;
    struct BitMap *BitMap;

    WORD MinWidth, MinHeight;
    UWORD MaxWidth, MaxHeight;

    /* the type variable describes the Screen in which you want this Window to
     * open.  The type value can either be CUSTOMSCREEN or one of the
     * system standard Screen Types such as WBENCHSCREEN.  See the
     * type definitions under the Screen structure.
     * A new possible value for this field is PUBLICSCREEN, which
     * defines the window as a 'visitor' window.  See below for
     * additional information provided.
     */
    UWORD Type;

    /* ------------------------------------------------------- *
     * extensions for V36
     * if the NewWindow Flag value WFLG_NW_EXTENDED is set, then
     * this field is assumed to point to an array ( or chain of arrays)
     * of TagItem structures.  See also ExtNewScreen for another
     * use of TagItems to pass optional data.
     *
     * see below for tag values and the corresponding data.
     */
    struct TagItem	*Extension;
};

/*
 * The TagItem ID's (ti_Tag values) for OpenWindowTagList() follow.
 * They are values in a TagItem array passed as extension/replacement
 * values for the data in NewWindow.  OpenWindowTagList() can actually
 * work well with a NULL NewWindow pointer.
 */

#define WA_Dummy	(TAG_USER + 99)	/* 0x80000063	*/

/* these tags simply override NewWindow parameters */
#define WA_Left			(WA_Dummy + 0x01)
#define WA_Top			(WA_Dummy + 0x02)
#define WA_Width		(WA_Dummy + 0x03)
#define WA_Height		(WA_Dummy + 0x04)
#define WA_DetailPen		(WA_Dummy + 0x05)
#define WA_BlockPen		(WA_Dummy + 0x06)
#define WA_IDCMP		(WA_Dummy + 0x07)
            /* "bulk" initialization of NewWindow.Flags */
#define WA_Flags		(WA_Dummy + 0x08)
#define WA_Gadgets		(WA_Dummy + 0x09)
#define WA_Checkmark		(WA_Dummy + 0x0A)
#define WA_Title		(WA_Dummy + 0x0B)
            /* means you don't have to call SetWindowTitles
             * after you open your window
             */
#define WA_ScreenTitle		(WA_Dummy + 0x0C)
#define WA_CustomScreen		(WA_Dummy + 0x0D)
#define WA_SuperBitMap		(WA_Dummy + 0x0E)
            /* also implies WFLG_SUPER_BITMAP property	*/
#define WA_MinWidth		(WA_Dummy + 0x0F)
#define WA_MinHeight		(WA_Dummy + 0x10)
#define WA_MaxWidth		(WA_Dummy + 0x11)
#define WA_MaxHeight		(WA_Dummy + 0x12)

/* The following are specifications for new features	*/

#define WA_InnerWidth		(WA_Dummy + 0x13)
#define WA_InnerHeight		(WA_Dummy + 0x14)
            /* You can specify the dimensions of the interior
             * region of your window, independent of what
             * the border widths will be.  You probably want
             * to also specify WA_AutoAdjust to allow
             * Intuition to move your window or even
             * shrink it so that it is completely on screen.
             */

#define WA_PubScreenName	(WA_Dummy + 0x15)
            /* declares that you want the window to open as
             * a visitor on the public screen whose name is
             * pointed to by (UBYTE *) ti_Data
             */
#define WA_PubScreen		(WA_Dummy + 0x16)
            /* open as a visitor window on the public screen
             * whose address is in (struct Screen *) ti_Data.
             * To ensure that this screen remains open, you
             * should either be the screen's owner, have a
             * window open on the screen, or use LockPubScreen().
             */
#define WA_PubScreenFallBack	(WA_Dummy + 0x17)
            /* A Boolean, specifies whether a visitor window
             * should "fall back" to the default public screen
             * (or Workbench) if the named public screen isn't
             * available
             */
#define WA_WindowName		(WA_Dummy + 0x18)
            /* not implemented	*/
#define WA_Colors		(WA_Dummy + 0x19)
            /* a ColorSpec array for colors to be set
             * when this window is active.	This is not
             * implemented, and may not be, since the default
             * values to restore would be hard to track.
             * We'd like to at least support per-window colors
             * for the mouse pointer sprite.
             */
#define WA_Zoom		(WA_Dummy + 0x1A)
            /* ti_Data points to an array of four WORD's,
             * the initial Left/Top/Width/Height values of
             * the "alternate" zoom position/dimensions.
             * It also specifies that you want a Zoom gadget
             * for your window, whether or not you have a
             * sizing gadget.
             */
#define WA_MouseQueue		(WA_Dummy + 0x1B)
            /* ti_Data contains initial value for the mouse
             * message backlog limit for this window.
             */
#define WA_BackFill		(WA_Dummy + 0x1C)
            /* unimplemented at present: provides a "backfill
             * hook" for your window's layer.
             */
#define WA_RptQueue		(WA_Dummy + 0x1D)
            /* initial value of repeat key backlog limit	*/

    /* These Boolean tag items are alternatives to the NewWindow.Flags
     * boolean flags with similar names.
     */
#define WA_SizeGadget		(WA_Dummy + 0x1E)
#define WA_DragBar		(WA_Dummy + 0x1F)
#define WA_DepthGadget		(WA_Dummy + 0x20)
#define WA_CloseGadget		(WA_Dummy + 0x21)
#define WA_Backdrop		(WA_Dummy + 0x22)
#define WA_ReportMouse		(WA_Dummy + 0x23)
#define WA_NoCareRefresh	(WA_Dummy + 0x24)
#define WA_Borderless		(WA_Dummy + 0x25)
#define WA_Activate		(WA_Dummy + 0x26)
#define WA_RMBTrap		(WA_Dummy + 0x27)
#define WA_WBenchWindow		(WA_Dummy + 0x28)	/* PRIVATE!! */
#define WA_SimpleRefresh	(WA_Dummy + 0x29)
            /* only specify if TRUE	*/
#define WA_SmartRefresh		(WA_Dummy + 0x2A)
            /* only specify if TRUE	*/
#define WA_SizeBRight		(WA_Dummy + 0x2B)
#define WA_SizeBBottom		(WA_Dummy + 0x2C)

    /* New Boolean properties	*/
#define WA_AutoAdjust		(WA_Dummy + 0x2D)
            /* shift or squeeze the window's position and
             * dimensions to fit it on screen.
             */

#define WA_GimmeZeroZero	(WA_Dummy + 0x2E)
            /* equiv. to NewWindow.Flags WFLG_GIMMEZEROZERO	*/

/* New for V37: WA_MenuHelp (ignored by V36) */
#define WA_MenuHelp		(WA_Dummy + 0x2F)
            /* Enables IDCMP_MENUHELP:  Pressing HELP during menus
             * will return IDCMP_MENUHELP message.
             */

#ifndef INTUITION_SCREENS_H
#include <intuition/screens.h>
#endif

#ifndef INTUITION_PREFERENCES_H
#include <intuition/preferences.h>
#endif

/* ======================================================================== */
/* === Remember =========================================================== */
/* ======================================================================== */
/* this structure is used for remembering what memory has been allocated to
 * date by a given routine, so that a premature abort or systematic exit
 * can deallocate memory cleanly, easily, and completely
 */
struct Remember
{
    struct Remember *NextRemember;
    ULONG RememberSize;
    UBYTE *Memory;
};

/* === Color Spec ====================================================== */
/* How to tell Intuition about RGB values for a color table entry. */
struct ColorSpec {
    WORD	ColorIndex;	/* -1 terminates an array of ColorSpec	*/
    UWORD	Red;		/* only 6 bits recognized in V36	*/
    UWORD	Green;		/* only 6 bits recognized in V36	*/
    UWORD	Blue;		/* only 6 bits recognized in V36	*/
};

/* === Easy Requester Specification ======================================= */
/* see also autodocs for EasyRequest and BuildEasyRequest	*/
/* NOTE: This structure may grow in size in the future		*/
struct EasyStruct {
    ULONG	es_StructSize;	/* should be sizeof (struct EasyStruct )*/
    ULONG	es_Flags;	/* should be 0 for now			*/
    UBYTE	*es_Title;	/* title of requester window		*/
    UBYTE	*es_TextFormat;	/* 'printf' style formatting string	*/
    UBYTE	*es_GadgetFormat; /* 'printf' style formatting string	*/
};

/* ======================================================================== */
/* === Miscellaneous ====================================================== */
/* ======================================================================== */

/* = MACROS ============================================================== */
#define MENUNUM(n) (n & 0x1F)
#define ITEMNUM(n) ((n >> 5) & 0x003F)
#define SUBNUM(n) ((n >> 11) & 0x001F)

#define SHIFTMENU(n) (n & 0x1F)
#define SHIFTITEM(n) ((n & 0x3F) << 5)
#define SHIFTSUB(n) ((n & 0x1F) << 11)

#define FULLMENUNUM( menu, item, sub )	\
    ( SHIFTSUB(sub) | SHIFTITEM(item) | SHIFTMENU(menu) )

#define SRBNUM(n)    (0x08 - (n >> 4))	/* SerRWBits -> read bits per char */
#define SWBNUM(n)    (0x08 - (n & 0x0F))/* SerRWBits -> write bits per chr */
#define SSBNUM(n)    (0x01 + (n >> 4))	/* SerStopBuf -> stop bits per chr */
#define SPARNUM(n)   (n >> 4)		/* SerParShk -> parity setting	  */
#define SHAKNUM(n)   (n & 0x0F)	/* SerParShk -> handshake mode	  */

/* = MENU STUFF =========================================================== */
#define NOMENU 0x001F
#define NOITEM 0x003F
#define NOSUB  0x001F
#define MENUNULL 0xFFFF

/* = =RJ='s peculiarities ================================================= */
#define FOREVER for(;;)
#define SIGN(x) ( ((x) > 0) - ((x) < 0) )
#define NOT !

/* these defines are for the COMMSEQ and CHECKIT menu stuff.  If CHECKIT,
 * I'll use a generic Width (for all resolutions) for the CheckMark.
 * If COMMSEQ, likewise I'll use this generic stuff
 */
#define CHECKWIDTH	19
#define COMMWIDTH	27
#define LOWCHECKWIDTH	13
#define LOWCOMMWIDTH	16

/* these are the AlertNumber defines.  if you are calling DisplayAlert()
 * the AlertNumber you supply must have the ALERT_TYPE bits set to one
 * of these patterns
 */
#define ALERT_TYPE	0x80000000
#define RECOVERY_ALERT	0x00000000	/* the system can recover from this */
#define DEADEND_ALERT	0x80000000	/* no recovery possible, this is it */

/* When you're defining IntuiText for the Positive and Negative Gadgets
 * created by a call to AutoRequest(), these defines will get you
 * reasonable-looking text.  The only field without a define is the IText
 * field; you decide what text goes with the Gadget
 */
#define AUTOFRONTPEN	0
#define AUTOBACKPEN	1
#define AUTODRAWMODE	JAM2
#define AUTOLEFTEDGE	6
#define AUTOTOPEDGE	3
#define AUTOITEXTFONT	NULL
#define AUTONEXTTEXT	NULL

/* --- RAWMOUSE Codes and Qualifiers (Console OR IDCMP) ------------------- */
#define SELECTUP	(IECODE_LBUTTON | IECODE_UP_PREFIX)
#define SELECTDOWN	(IECODE_LBUTTON)
#define MENUUP		(IECODE_RBUTTON | IECODE_UP_PREFIX)
#define MENUDOWN	(IECODE_RBUTTON)
#define MIDDLEDOWN	(IECODE_MBUTTON)
#define MIDDLEUP	(IECODE_MBUTTON | IECODE_UP_PREFIX)
#define ALTLEFT		(IEQUALIFIER_LALT)
#define ALTRIGHT	(IEQUALIFIER_RALT)
#define AMIGALEFT	(IEQUALIFIER_LCOMMAND)
#define AMIGARIGHT	(IEQUALIFIER_RCOMMAND)
#define AMIGAKEYS	(AMIGALEFT | AMIGARIGHT)

#define CURSORUP	0x4C
#define CURSORLEFT	0x4F
#define CURSORRIGHT	0x4E
#define CURSORDOWN	0x4D
#define KEYCODE_Q	0x10
#define KEYCODE_Z	0x31
#define KEYCODE_X	0x32
#define KEYCODE_V	0x34
#define KEYCODE_B	0x35
#define KEYCODE_N	0x36
#define KEYCODE_M	0x37
#define KEYCODE_LESS	0x38
#define KEYCODE_GREATER 0x39

/* Include obsolete identifiers: */
#ifndef INTUITION_IOBSOLETE_H
#include <intuition/iobsolete.h>
#endif

#endif


Includes/intuition/preferences.h

#ifndef INTUITION_PREFERENCES_H
#define INTUITION_PREFERENCES_H TRUE
/*
**  $Filename: intuition/preferences.h $
**  $Release: 2.04 Includes, V37.4 $
**  $Revision: 36.8 $
**  $Date: 91/05/08 $
**
**  Structure definition for old-style preferences
**
**  (C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef DEVICES_TIMER_H
#include <devices/timer.h>
#endif

/* ======================================================================== */
/* === Preferences ======================================================== */
/* ======================================================================== */

/* these are the definitions for the printer configurations */
#define	FILENAME_SIZE	30			/* Filename size */

#define	POINTERSIZE (1 + 16 + 1) * 2	/* Size of Pointer data buffer */

/* These defines are for the default font size.  These actually describe the
 * height of the defaults fonts.  The default font type is the topaz
 * font, which is a fixed width font that can be used in either
 * eighty-column or sixty-column mode.	The Preferences structure reflects
 * which is currently selected by the value found in the variable FontSize,
 * which may have either of the values defined below.  These values actually
 * are used to select the height of the default font.  By changing the
 * height, the resolution of the font changes as well.
 */
#define TOPAZ_EIGHTY 8
#define TOPAZ_SIXTY 9

struct Preferences
{
    /* the default font height */
    BYTE FontHeight;			/* height for system default font  */

    /* constant describing what's hooked up to the port */
    UBYTE PrinterPort;			/* printer port connection	   */

    /* the baud rate of the port */
    UWORD BaudRate;			/* baud rate for the serial port   */

    /* various timing rates */
    struct timeval KeyRptSpeed;		/* repeat speed for keyboard	   */
    struct timeval KeyRptDelay;		/* Delay before keys repeat	   */
    struct timeval DoubleClick;		/* Interval allowed between clicks */

    /* Intuition Pointer data */
    UWORD PointerMatrix[POINTERSIZE];	/* Definition of pointer sprite    */
    BYTE XOffset;			/* X-Offset for active 'bit'	   */
    BYTE YOffset;			/* Y-Offset for active 'bit'	   */
    UWORD color17;			/***********************************/
    UWORD color18;			/* Colours for sprite pointer	   */
    UWORD color19;			/***********************************/
    UWORD PointerTicks;			/* Sensitivity of the pointer	   */

    /* Workbench Screen colors */
    UWORD color0;			/***********************************/
    UWORD color1;			/*  Standard default colours	   */
    UWORD color2;			/*   Used in the Workbench	   */
    UWORD color3;			/***********************************/

    /* positioning data for the Intuition View */
    BYTE ViewXOffset;			/* Offset for top lefthand corner  */
    BYTE ViewYOffset;			/* X and Y dimensions		   */
    WORD ViewInitX, ViewInitY;		/* View initial offset values	   */

    BOOL EnableCLI;			/* CLI availability switch */

    /* printer configurations */
    UWORD PrinterType;			/* printer type		   */
    UBYTE PrinterFilename[FILENAME_SIZE];/* file for printer	   */

    /* print format and quality configurations */
    UWORD PrintPitch;			/* print pitch			   */
    UWORD PrintQuality;			/* print quality		   */
    UWORD PrintSpacing;			/* number of lines per inch	   */
    UWORD PrintLeftMargin;		/* left margin in characters	   */
    UWORD PrintRightMargin;		/* right margin in characters	   */
    UWORD PrintImage;			/* positive or negative		   */
    UWORD PrintAspect;			/* horizontal or vertical	   */
    UWORD PrintShade;			/* b&w, half-tone, or color	   */
    WORD PrintThreshold;		/* darkness ctrl for b/w dumps	   */

    /* print paper descriptors */
    UWORD PaperSize;			/* paper size			   */
    UWORD PaperLength;			/* paper length in number of lines */
    UWORD PaperType;			/* continuous or single sheet	   */

    /* Serial device settings: These are six nibble-fields in three bytes */
    /* (these look a little strange so the defaults will map out to zero) */
    UBYTE   SerRWBits;	 /* upper nibble = (8-number of read bits)	*/
             /* lower nibble = (8-number of write bits)	*/
    UBYTE   SerStopBuf;  /* upper nibble = (number of stop bits - 1)	*/
             /* lower nibble = (table value for BufSize)	*/
    UBYTE   SerParShk;	 /* upper nibble = (value for Parity setting)	*/
             /* lower nibble = (value for Handshake mode)	*/
    UBYTE   LaceWB;	 /* if workbench is to be interlaced		*/

    UBYTE   WorkName[FILENAME_SIZE];  /* temp file for printer		*/

    BYTE    RowSizeChange;	/* affect NormalDisplayRows/Columns	*/
    BYTE    ColumnSizeChange;

    UWORD    PrintFlags;	/* user preference flags */
    UWORD    PrintMaxWidth;	/* max width of printed picture in 10ths/in */
    UWORD    PrintMaxHeight;	/* max height of printed picture in 10ths/in */
    UBYTE    PrintDensity;	/* print density */
    UBYTE    PrintXOffset;	/* offset of printed picture in 10ths/inch */

    UWORD    wb_Width;		/* override default workbench width  */
    UWORD    wb_Height;		/* override default workbench height */
    UBYTE    wb_Depth;		/* override default workbench depth  */

    UBYTE    ext_size;		/* extension information -- do not touch! */
                /* extension size in blocks of 64 bytes */
};

/* Workbench Interlace (use one bit) */
#define LACEWB			(1<< 0)
#define LW_RESERVED	1		/* internal use only */

/* Enable_CLI	*/
#define SCREEN_DRAG	(1<<14)
#define MOUSE_ACCEL	(1L<<15)

/* PrinterPort */
#define PARALLEL_PRINTER 0x00
#define SERIAL_PRINTER	0x01

/* BaudRate */
#define BAUD_110	0x00
#define BAUD_300	0x01
#define BAUD_1200	0x02
#define BAUD_2400	0x03
#define BAUD_4800	0x04
#define BAUD_9600	0x05
#define BAUD_19200	0x06
#define BAUD_MIDI	0x07

/* PaperType */
#define FANFOLD	0x00
#define SINGLE		0x80

/* PrintPitch */
#define PICA		0x000
#define ELITE		0x400
#define FINE		0x800

/* PrintQuality */
#define DRAFT		0x000
#define LETTER		0x100

/* PrintSpacing */
#define SIX_LPI		0x000
#define EIGHT_LPI	0x200

/* Print Image */
#define IMAGE_POSITIVE	0x00
#define IMAGE_NEGATIVE	0x01

/* PrintAspect */
#define ASPECT_HORIZ	0x00
#define ASPECT_VERT	0x01

/* PrintShade */
#define SHADE_BW	0x00
#define SHADE_GREYSCALE	0x01
#define SHADE_COLOR	0x02

/* PaperSize */
#define US_LETTER	0x00
#define US_LEGAL	0x10
#define N_TRACTOR	0x20
#define W_TRACTOR	0x30
#define CUSTOM		0x40

/* New PaperSizes for V36: */
#define EURO_A0	0x50		/* European size A0: 841 x 1189 */
#define EURO_A1	0x60		/* European size A1: 594 x 841 */
#define EURO_A2	0x70		/* European size A2: 420 x 594 */
#define EURO_A3	0x80		/* European size A3: 297 x 420 */
#define EURO_A4	0x90		/* European size A4: 210 x 297 */
#define EURO_A5	0xA0		/* European size A5: 148 x 210 */
#define EURO_A6	0xB0		/* European size A6: 105 x 148 */
#define EURO_A7	0xC0		/* European size A7: 74 x 105 */
#define EURO_A8	0xD0		/* European size A8: 52 x 74 */

/* PrinterType */
#define CUSTOM_NAME		0x00
#define	ALPHA_P_101		0x01
#define BROTHER_15XL		0x02
#define CBM_MPS1000		0x03
#define DIAB_630		0x04
#define DIAB_ADV_D25		0x05
#define DIAB_C_150		0x06
#define EPSON			0x07
#define EPSON_JX_80		0x08
#define OKIMATE_20		0x09
#define QUME_LP_20		0x0A
/* new printer entries, 3 October 1985 */
#define HP_LASERJET		0x0B
#define HP_LASERJET_PLUS	0x0C

/* Serial Input Buffer Sizes */
#define SBUF_512	0x00
#define SBUF_1024	0x01
#define SBUF_2048	0x02
#define SBUF_4096	0x03
#define SBUF_8000	0x04
#define SBUF_16000	0x05

/* Serial Bit Masks */
#define	SREAD_BITS	0xF0 /* for SerRWBits	*/
#define	SWRITE_BITS	0x0F

#define	SSTOP_BITS	0xF0 /* for SerStopBuf	*/
#define	SBUFSIZE_BITS	0x0F

#define	SPARITY_BITS	0xF0 /* for SerParShk	*/
#define SHSHAKE_BITS	0x0F

/* Serial Parity (upper nibble, after being shifted by
 * macro SPARNUM() )
 */
#define SPARITY_NONE	 0
#define SPARITY_EVEN	 1
#define SPARITY_ODD	 2
/* New parity definitions for V36: */
#define SPARITY_MARK	 3
#define SPARITY_SPACE	 4

/* Serial Handshake Mode (lower nibble, after masking using
 * macro SHANKNUM() )
 */
#define SHSHAKE_XON	 0
#define SHSHAKE_RTS	 1
#define SHSHAKE_NONE	 2

/* new defines for PrintFlags */

#define CORRECT_RED	    0x0001  /* color correct red shades */
#define CORRECT_GREEN	    0x0002  /* color correct green shades */
#define CORRECT_BLUE	    0x0004  /* color correct blue shades */

#define CENTER_IMAGE	    0x0008  /* center image on paper */

#define IGNORE_DIMENSIONS   0x0000 /* ignore max width/height settings */
#define BOUNDED_DIMENSIONS  0x0010  /* use max width/height as boundaries */
#define ABSOLUTE_DIMENSIONS 0x0020  /* use max width/height as absolutes */
#define PIXEL_DIMENSIONS    0x0040  /* use max width/height as prt pixels */
#define MULTIPLY_DIMENSIONS 0x0080 /* use max width/height as multipliers */

#define INTEGER_SCALING     0x0100  /* force integer scaling */

#define ORDERED_DITHERING   0x0000 /* ordered dithering */
#define HALFTONE_DITHERING  0x0200  /* halftone dithering */
#define FLOYD_DITHERING     0x0400 /* Floyd-Steinberg dithering */

#define ANTI_ALIAS	    0x0800 /* anti-alias image */
#define GREY_SCALE2	    0x1000 /* for use with hi-res monitor */

/* masks used for checking bits */

#define CORRECT_RGB_MASK    (CORRECT_RED|CORRECT_GREEN|CORRECT_BLUE)
#define DIMENSIONS_MASK     (BOUNDED_DIMENSIONS|ABSOLUTE_DIMENSIONS|PIXEL_DIMENSIONS|MULTIPLY_DIMENSIONS)
#define DITHERING_MASK	    (HALFTONE_DITHERING|FLOYD_DITHERING)

#endif


Includes/intuition/cghooks.i

    IFND INTUITION_CGHOOKS_I
INTUITION_CGHOOKS_I SET 1
**
** $Filename: intuition/cghooks.i $
** $Release: 2.04 Includes, V37.4 $
** $Revision: 36.4 $
** $Date: 91/11/08 $
**
**  Custom gadget processing
**
**  (C) Copyright 1988-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND EXEC_TYPES_I
    INCLUDE "exec/types.i"
    ENDC

    IFND INTUITION_INTUITION_I
    INCLUDE "intuition/intuition.i"
    ENDC

; ========================================================================
; === Gadget Info =========================================================
; ========================================================================

; Package of information passed to custom and 'boopsi'
; gadget "hook" functions.  This structure is READ ONLY.

 STRUCTURE GadgetInfo,0
;    APTR ggi_Gadget

    APTR ggi_Screen
    APTR ggi_Window	 ; null for screen gadgets
    APTR ggi_Requester	 ; null if not GTYP_REQGADGET

    ; rendering information:
    ; don't use these without cloning/locking.
    ; Official way is to call ObtainRPort()
    APTR ggi_RastPort
    APTR ggi_Layer

    ; copy of dimensions of screen/window/g00/req/group
    ; that gadget resides in.  Left/Top of this box is
    ; offset from window mouse coordinates to gadget coordinates
    ; 	screen gadgets:			0,0 (from screen coords)
    ;	window gadgets (no g00):  	0,0
    ;  GZZGADGETs (borderlayer): 	0,0
    ;  GZZ innerlayer gadget:  	borderleft, bordertop
    ;  Requester gadgets: 		reqleft, reqtop
    STRUCT 	ggi_Domain,ibox_SIZEOF

    ; these are the pens for the window or screen
    STRUCT	ggi_Pens,2	; detail and block pen UBYTE's

    ; the Detail and Block pens in ggi_DrInfo->dri_Pens[] are
    ; for the screen. Use the above for window-sensitive
    ; colors.
    APTR ggi_DrInfo

    ; the size of this struct is not defined, since it is allocated
    ; ONLY by Intuition.
    ;	 LABEL ggi_SIZEOF

    ENDC


Includes/intuition/gadgetclass.i

    IFND INTUITION_GADGETCLASS_I
INTUITION_GADGETCLASS_I SET 1
**
** $Filename: intuition/gadgetclass.i $
** $Release: 2.04 Includes, V37.4 $
** $Revision: 36.10 $
** $Date: 91/11/08 $
**
** Custom and 'boopsi' gadget class interface
**
**  (C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND EXEC_TYPES_I
    INCLUDE "exec/types.i"
    ENDC

    IFND INTUITION_INTUITION_I
    INCLUDE "intuition/intuition.i"
    ENDC

    IFND UTILITY_TAGITEM_I
    INCLUDE "utility/tagitem.i"
    ENDC

*
* NOTE:  intuition/iobsolete.i is included at the END of this file!
*

; Gadget Class attributes

GA_Dummy		EQU	(TAG_USER+$30000)
GA_Left			EQU	(GA_Dummy+$0001)
GA_RelRight		EQU	(GA_Dummy+$0002)
GA_Top			EQU	(GA_Dummy+$0003)
GA_RelBottom		EQU	(GA_Dummy+$0004)
GA_Width		EQU	(GA_Dummy+$0005)
GA_RelWidth		EQU	(GA_Dummy+$0006)
GA_Height		EQU	(GA_Dummy+$0007)
GA_RelHeight		EQU	(GA_Dummy+$0008)
GA_Text			EQU	(GA_Dummy+$0009)  ; ti_Data is (UBYTE *)
GA_Image		EQU	(GA_Dummy+$000A)
GA_Border		EQU	(GA_Dummy+$000B)
GA_SelectRender		EQU	(GA_Dummy+$000C)
GA_Highlight		EQU	(GA_Dummy+$000D)
GA_Disabled		EQU	(GA_Dummy+$000E)
GA_GZZGadget		EQU	(GA_Dummy+$000F)
GA_ID			EQU	(GA_Dummy+$0010)
GA_UserData		EQU	(GA_Dummy+$0011)
GA_SpecialInfo		EQU	(GA_Dummy+$0012)
GA_Selected		EQU	(GA_Dummy+$0013)
GA_EndGadget		EQU	(GA_Dummy+$0014)
GA_Immediate		EQU	(GA_Dummy+$0015)
GA_RelVerify		EQU	(GA_Dummy+$0016)
GA_FollowMouse		EQU	(GA_Dummy+$0017)
GA_RightBorder		EQU	(GA_Dummy+$0018)
GA_LeftBorder		EQU	(GA_Dummy+$0019)
GA_TopBorder		EQU	(GA_Dummy+$001A)
GA_BottomBorder		EQU	(GA_Dummy+$001B)
GA_ToggleSelect		EQU	(GA_Dummy+$001C)

* internal use only, until further notice, please
GA_SysGadget		EQU	(GA_Dummy+$001D)
* bool, sets GTYP_SYSGADGET field in type
GA_SysGType		EQU	(GA_Dummy+$001E)
* e.g., GTYP_WUPFRONT, ...

GA_Previous		EQU	(GA_Dummy+$001F)
* previous gadget (or (struct Gadget **)) in linked list
* NOTE: This attribute CANNOT be used to link new gadgets
* into the gadget list of an open window or requester.
* You must use AddGList().

GA_Next			EQU	(GA_Dummy+$0020)
* not implemented

GA_DrawInfo		EQU	(GA_Dummy+$0021)
* some fancy gadgets need to see a DrawInfo
* when created or for layout

* You should use at most ONE of GA_Text, GA_IntuiText, and GA_LabelImage
GA_IntuiText		EQU	(GA_Dummy+$0022)
* ti_Data is (struct IntuiText	*)

GA_LabelImage		EQU	(GA_Dummy+$0023)
* ti_Data is an image (object), used in place of
* GadgetText

GA_TabCycle		EQU	(GA_Dummy+$0024)
* New for V37:
* Boolean indicates that this gadget is to participate in
* cycling activation with Tab or Shift-Tab.

* PROPGCLASS attributes

PGA_Dummy		EQU	(TAG_USER+$31000)
PGA_Freedom		EQU	(PGA_Dummy+$0001)
* either or both of FREEVERT and FREEHORIZ
PGA_Borderless		EQU	(PGA_Dummy+$0002)
PGA_HorizPot		EQU	(PGA_Dummy+$0003)
PGA_HorizBody		EQU	(PGA_Dummy+$0004)
PGA_VertPot		EQU	(PGA_Dummy+$0005)
PGA_VertBody		EQU	(PGA_Dummy+$0006)
PGA_Total		EQU	(PGA_Dummy+$0007)
PGA_Visible		EQU	(PGA_Dummy+$0008)
PGA_Top			EQU	(PGA_Dummy+$0009)
; New for V37:
PGA_NewLook		EQU	(PGA_Dummy+$000A)

* STRGCLASS attributes

STRINGA_Dummy			EQU	(TAG_USER+$32000)
STRINGA_MaxChars	EQU	(STRINGA_Dummy+$0001)
STRINGA_Buffer		EQU	(STRINGA_Dummy+$0002)
STRINGA_UndoBuffer	EQU	(STRINGA_Dummy+$0003)
STRINGA_WorkBuffer	EQU	(STRINGA_Dummy+$0004)
STRINGA_BufferPos	EQU	(STRINGA_Dummy+$0005)
STRINGA_DispPos		EQU	(STRINGA_Dummy+$0006)
STRINGA_AltKeyMap	EQU	(STRINGA_Dummy+$0007)
STRINGA_Font		EQU	(STRINGA_Dummy+$0008)
STRINGA_Pens		EQU	(STRINGA_Dummy+$0009)
STRINGA_ActivePens	EQU	(STRINGA_Dummy+$000A)
STRINGA_EditHook	EQU	(STRINGA_Dummy+$000B)
STRINGA_EditModes	EQU	(STRINGA_Dummy+$000C)

* booleans
STRINGA_ReplaceMode	EQU	(STRINGA_Dummy+$000D)
STRINGA_FixedFieldMode	EQU	(STRINGA_Dummy+$000E)
STRINGA_NoFilterMode	EQU	(STRINGA_Dummy+$000F)

STRINGA_Justification	EQU	(STRINGA_Dummy+$0010)
* GACT_STRINGCENTER, GACT_STRINGLEFT, GACT_STRINGRIGHT
STRINGA_LongVal		EQU	(STRINGA_Dummy+$0011)
STRINGA_TextVal		EQU	(STRINGA_Dummy+$0012)

STRINGA_ExitHelp	EQU	(STRINGA_Dummy+$0013)
* STRINGA_ExitHelp is new for V37, and ignored by V36.
* Set this if you want the gadget to exit when Help is
* pressed.  Look for a code of 0x5F, the rawkey code for Help

SG_DEFAULTMAXCHARS	EQU	(128)

* Gadget Layout related attributes

LAYOUTA_Dummy		EQU	(TAG_USER+$38000)
LAYOUTA_LayoutObj	EQU	(LAYOUTA_Dummy+$0001)
LAYOUTA_Spacing		EQU	(LAYOUTA_Dummy+$0002)
LAYOUTA_Orientation	EQU	(LAYOUTA_Dummy+$0003)

* orientation values
LORIENT_NONE		EQU	0
LORIENT_HORIZ		EQU	1
LORIENT_VERT		EQU	2

; Custom gadget hook command ID's
; (gadget class method/message ID's)

GM_HITTEST EQU		0	; return GMR_GADGETHIT if you are clicked
                ; (whether or not you are disabled)
GM_RENDER EQU		1	; draw yourself, in the appropriate state
GM_GOACTIVE EQU		2	; you are now going to be fed input
GM_HANDLEINPUT EQU	3	; handle that input
GM_GOINACTIVE EQU	4	; whether or not by choice, you are done

; Parameter "Messages" passed to gadget class methods

; All parameter structure begin with a MethodID field
; This definition of an abstract generic "message" is
; equivalent to a better one in intuition/classusr.i, but
; it's left here for historic reasons
 STRUCTURE MsgHeader,0
    ULONG	MethodID
    LABEL	methodid_SIZEOF

; GM_HITTEST
 STRUCTURE	gpHitTest,methodid_SIZEOF
    APTR	gpht_GInfo
    WORD	gpht_MouseX
    WORD	gpht_MouseY

; GM_HITTEST return value
GMR_GADGETHIT	EQU $00000004	; if no hit, return 0

; GM_RENDER
 STRUCTURE	gpRender,methodid_SIZEOF
    APTR	gpr_GInfo	; gadget context
    APTR	gpr_RPort	; all ready for use
    LONG	gpr_Redraw	; might be a "highlight pass"

; values of gpr_Redraw
GREDRAW_UPDATE	EQU 2	; update for change in attributesvalues
GREDRAW_REDRAW	EQU 1	; redraw gadget
GREDRAW_TOGGLE	EQU 0	; toggle highlight, if applicable

; GM_GOACTIVE, GM_HANDLEINPUT
 STRUCTURE	gpInput,methodid_SIZEOF
    APTR	gpi_GInfo
    APTR	gpi_IEvent
    APTR	gpi_Termination
    WORD	gpi_MouseX
    WORD	gpi_MouseY

; GM_HANDLEINPUT and GM_GOACTIVE  return code flags
; return GMR_MEACTIVE (0) alone if you want more input.
; Otherwise, return ONE of GMR_NOREUSE and GMR_REUSE, and optionally
; GMR_VERIFY.

; here are the original constant "equates"
GMR_MEACTIVE	EQU $0000 	; (bugfix: was $0001 during beta)
GMR_NOREUSE	EQU $0002
GMR_REUSE	EQU $0004
GMR_VERIFY	EQU $0008	; you MUST set cgp_Termination

* New for V37:
* You can end activation with one of GMR_NEXTACTIVE and GMR_PREVACTIVE,
* which instructs Intuition to activate the next or previous gadget
* that has GFLG_TABCYCLE set.
*
GMR_NEXTACTIVE	EQU $0010
GMR_PREVACTIVE	EQU $0020

; here are standard bit/flag pairs
GMRB_NOREUSE	EQU 1
GMRB_REUSE	EQU 2
GMRB_VERIFY	EQU 3
GMRB_NEXTACTIVE	EQU 4
GMRB_PREVACTIVE	EQU 5

GMRF_NOREUSE	EQU $0002
GMRF_REUSE	EQU $0004
GMRF_VERIFY	EQU $0008
GMRF_NEXTACTIVE	EQU $0010
GMRF_PREVACTIVE	EQU $0020

; GM_GOINACTIVE
 STRUCTURE	gpGoInactive,methodid_SIZEOF
    APTR	gpgi_GInfo

* V37 field only!  DO NOT attempt to read under V36!
    ULONG	gpgi_Abort	; gpgi_Abort=1 if gadget was aborted
                ; by Intuition and 0 if gadget went
                ; inactive at its own request

* Include obsolete identifiers:
    IFND	INTUITION_IOBSOLETE_I
    INCLUDE "intuition/iobsolete.i"
    ENDC

    ENDC


Includes/intuition/intuition.i

    IFND	INTUITION_INTUITION_I
INTUITION_INTUITION_I	SET	1
**
**	$Filename: intuition/intuition.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.30 $
**	$Date: 91/03/28 $
**
**	Interface definitions for Intuition applications
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND EXEC_TYPES_I
    INCLUDE "exec/types.i"
    ENDC

    IFND	GRAPHICS_GFX_I
    INCLUDE	"graphics/gfx.i"
    ENDC

    IFND	GRAPHICS_CLIP_I
    INCLUDE	"graphics/clip.i"
    ENDC

    IFND	GRAPHICS_VIEW_I
    INCLUDE	"graphics/view.i"
    ENDC

    IFND	GRAPHICS_RASTPORT_I
    INCLUDE	"graphics/rastport.i"
    ENDC

    IFND	GRAPHICS_LAYERS_I
    INCLUDE	"graphics/layers.i"
    ENDC

    IFND	GRAPHICS_TEXT_I
    INCLUDE "graphics/text.i"
    ENDC

    IFND EXEC_PORTS_I
    INCLUDE "exec/ports.i"
    ENDC

    IFND	DEVICES_TIMER_I
    INCLUDE	"devices/timer.i"
    ENDC

    IFND	DEVICES_INPUTEVENT_I
    INCLUDE "devices/inputevent.i"
    ENDC

    IFND UTILITY_TAGITEM_I
    INCLUDE "utility/tagitem.i"
    ENDC

*
* NOTE:  intuition/iobsolete.i is included at the END of this file!
*

; ========================================================================;
; === Menu ===============================================================;
; ========================================================================;
 STRUCTURE Menu,0

    APTR  mu_NextMenu	; menu pointer, same level
    WORD mu_LeftEdge	; position of the select box
    WORD mu_TopEdge	; position of the select box
    WORD mu_Width	; dimensions of the select box
    WORD mu_Height	; dimensions of the select box
    WORD mu_Flags	; see flag definitions below
    APTR mu_MenuName	; text for this Menu Header
    APTR  mu_FirstItem	; pointer to first in chain

    ; these mysteriously-named variables are for internal use only
    WORD mu_JazzX
    WORD mu_JazzY
    WORD mu_BeatX
    WORD mu_BeatY

    LABEL mu_SIZEOF

;*** FLAGS SET BY BOTH THE APPLIPROG AND INTUITION ***
MENUENABLED EQU $0001	; whether or not this menu is enabled

;*** FLAGS SET BY INTUITION ***
MIDRAWN EQU $0100	; this menu's items are currently drawn

; ========================================================================;
; === MenuItem ===========================================================;
; ========================================================================;
 STRUCTURE MenuItem,0

    APTR mi_NextItem	; pointer to next in chained list
    WORD mi_LeftEdge	; position of the select box
    WORD mi_TopEdge	; position of the select box
    WORD mi_Width	; dimensions of the select box
    WORD mi_Height	; dimensions of the select box
    WORD mi_Flags	; see the defines below

    LONG mi_MutualExclude ; set bits mean this item excludes that item

    APTR mi_ItemFill	; points to Image, IntuiText, or NULL

    ; when this item is pointed to by the cursor and the items highlight
    ; mode HIGHIMAGE is selected, this alternate image will be displayed
    APTR mi_SelectFill	; points to Image, IntuiText, or NULL

    BYTE mi_Command	; only if appliprog sets the COMMSEQ flag

    BYTE mi_KludgeFill00 ; This is strictly for word-alignment

    APTR mi_SubItem	; if non-zero, points to MenuItem for submenu

   ; The NextSelect field represents the menu number of next selected
   ; item (when user has drag-selected several items)
    WORD mi_NextSelect

    LABEL  mi_SIZEOF

; --- FLAGS SET BY THE APPLIPROG --------------------------------------------
CHECKIT		EQU $0001	; set to indicate checkmarkable item
ITEMTEXT	EQU $0002	; set if textual, clear if graphical item
COMMSEQ		EQU $0004	; set if there's an command sequence
MENUTOGGLE	EQU $0008	; set for toggling checks (else mut. exclude)
ITEMENABLED	EQU $0010	; set if this item is enabled

; these are the SPECIAL HIGHLIGHT FLAG state meanings
HIGHFLAGS	EQU $00C0	; see definitions below for these bits
HIGHIMAGE	EQU $0000	; use the user's "select image"
HIGHCOMP	EQU $0040	; highlight by complementing the select box
HIGHBOX		EQU $0080	; highlight by drawing a box around the image
HIGHNONE	EQU $00C0	; don't highlight

; --- FLAGS SET BY BOTH APPLIPROG AND INTUITION -----------------------------
CHECKED	EQU $0100	; state of the checkmark

; --- FLAGS SET BY INTUITION ------------------------------------------------
ISDRAWN		EQU $1000	; this item's subs are currently drawn
HIGHITEM	EQU $2000	; this item is currently highlighted
MENUTOGGLED	EQU $4000	; this item was already toggled

; ========================================================================
; === Requester ==========================================================
; ========================================================================
 STRUCTURE Requester,0

    APTR  rq_OlderRequest
    WORD rq_LeftEdge		; dimensions of the entire box
    WORD rq_TopEdge		; dimensions of the entire box
    WORD rq_Width		; dimensions of the entire box
    WORD rq_Height		; dimensions of the entire box

    WORD rq_RelLeft		; get POINTREL Pointer relativity offsets
    WORD rq_RelTop		; get POINTREL Pointer relativity offsets

    APTR  rq_ReqGadget     	; pointer to the first of a list of gadgets
    APTR  rq_ReqBorder		; the box's border
    APTR  rq_ReqText		; the box's text

    WORD  rq_Flags		; see definitions below

    UBYTE rq_BackFill		; pen number for back-plane fill before draws

    BYTE rq_KludgeFill00	; This is strictly for word-alignment

    APTR rq_ReqLayer		; layer in which requester rendered
    STRUCT rq_ReqPad1,32	; for backwards compatibility (reserved)

    ; If the BitMap plane pointers are non-zero, this tells the system
    ; that the image comes pre-drawn (if the appliprog wants to define
    ; its own box, in any shape or size it wants!); this is OK by
    ; Intuition as long as there's a good correspondence between the image
    ; and the specified Gadgets
    APTR  rq_ImageBMap		; points to the BitMap of PREDRAWN imagery

    APTR  rq_RWindow		; points back to requester's window
    APTR  rq_ReqImage		; new for V36: drawn if USEREQIMAGE set
    STRUCT rq_ReqPad2,32	; for backwards compatibility (reserved)

    LABEL rq_SIZEOF

; FLAGS SET BY THE APPLIPROG
POINTREL	EQU $0001  ; if POINTREL set, TopLeft is relative to pointer
               ; for DMRequester, relative to window center
               ; for Request().
PREDRAWN	EQU $0002  ; if ReqBMap points to predrawn Requester imagery
NOISYREQ 	EQU $0004  ; if you don't want requester to filter input

; New for V36
SIMPLEREQ	EQU $0010  ; to use SIMPLEREFRESH layer (recommended)
USEREQIMAGE	EQU $0020  ; render linked list ReqImage after BackFill
               ; but before gadgets and text
NOREQBACKFILL	EQU $0040  ; don't bother filling with Requester.BackFill

; FLAGS SET BY INTUITION;
REQOFFWINDOW	EQU $1000	; part of one of the Gadgets was offwindow
REQACTIVE	EQU $2000	; this requester is active
SYSREQUEST	EQU $4000	; (unused) this requester caused by system
DEFERREFRESH	EQU $8000	; this Requester stops a Refresh broadcast

; ========================================================================
; === Gadget =============================================================
; ========================================================================
 STRUCTURE Gadget,0

    APTR gg_NextGadget		; next gadget in the list

    WORD gg_LeftEdge		; "hit box" of gadget
    WORD gg_TopEdge		; "hit box" of gadget
    WORD gg_Width		; "hit box" of gadget
    WORD gg_Height		; "hit box" of gadget

    WORD gg_Flags 		; see below for list of defines

    WORD gg_Activation		; see below for list of defines

    WORD gg_GadgetType		; see below for defines

    ; appliprog can specify that the Gadget be rendered as either as Border
    ; or an Image.  This variable points to which (or equals NULL if there's
    ; nothing to be rendered about this Gadget)
    APTR gg_GadgetRender

    ; appliprog can specify "highlighted" imagery rather than algorithmic
    ; this can point to either Border or Image data
    APTR gg_SelectRender

    APTR gg_GadgetText		; text for this gadget;

    ; MutualExclude, never implemented, is now declared obsolete.
    ; There are published examples of implementing a more general
    ; and practical exclusion in your applications.
    ;
    ; Starting V36, this field is used to point to a hook
    ; for a custom gadget.
    ;
    ; Programs using this field for their own processing will
    ; continue to work, as long as they don't try the
    ; trick with custom gadgets
    LONG gg_MutualExclude 	; obsolete

    ; pointer to a structure of special data required by Proportional, String
    ; and Integer Gadgets
    APTR gg_SpecialInfo

    WORD gg_GadgetID	; user-definable ID field
    APTR  gg_UserData	; ptr to general purpose User data (ignored by Intuit)

    LABEL gg_SIZEOF

; --- Gadget.Flags values ---
; combinations in these bits describe the highlight technique to be used
GFLG_GADGHIGHBITS	EQU $0003
GFLG_GADGHCOMP		EQU $0000	; Complement the select box
GFLG_GADGHBOX		EQU $0001	; Draw a box around the image
GFLG_GADGHIMAGE		EQU $0002	; Blast in this alternate image
GFLG_GADGHNONE		EQU $0003	; don't highlight

; set this flag if the GadgetRender and SelectRender point to Image imagery,
; clear if it's a Border
GFLG_GADGIMAGE		EQU $0004

; combinations in these next two bits specify to which corner the gadget's
; Left & Top coordinates are relative.	If relative to Top/Left,
; these are "normal" coordinates (everything is relative to something in
; this universe)
GFLG_RELBOTTOM		EQU $0008	; set if rel to bottom, clear if to top
GFLG_RELRIGHT		EQU $0010	; set if rel to right, clear if to left
; set the GFLG_RELWIDTH bit to spec that Width is relative to width of screen
GFLG_RELWIDTH		EQU $0020
; set the GFLG_RELHEIGHT bit to spec that Height is rel to height of screen
GFLG_RELHEIGHT		EQU $0040

; the GFLG_SELECTED flag is initialized by you and set by Intuition.  It
; specifies whether or not this Gadget is currently selected/highlighted
GFLG_SELECTED		EQU $0080

; the GFLG_DISABLED flag is initialized by you and later set by Intuition
; according to your calls to On/OffGadget().  It specifies whether or not
; this Gadget is currently disabled from being selected
GFLG_DISABLED		EQU $0100

* These flags specify the type of text field that Gadget.GadgetText
* points to.  In all normal (pre-V36) gadgets which you initialize
* this field should always be zero.  Some types of gadget objects
* created from classes will use these fields to keep track of
* types of labels/contents that different from IntuiText, but are
* stashed in GadgetText.

GFLG_LABELMASK		EQU	$3000
GFLG_LABELITEXT		EQU	$0000	; GadgetText points to IntuiText
GFLG_LABELSTRING	EQU	$1000	; GadgetText points to (UBYTE *)
GFLG_LABELIMAGE		EQU	$2000	; GadgetText points to Image (object)
; New for V37: GFLG_TABCYCLE
GFLG_TABCYCLE		EQU	$0200	; (string or custom) gadget
                ; participates in cycling activation with
                ; Tab or Shift-Tab

; New for V37: GFLG_STRINGEXTEND.  We discovered that V34 doesn't properly
; ignore the value we had chosen for the Gadget->Activation flag
; GACT_STRINGEXTEND.  NEVER SET THAT FLAG WHEN RUNNING UNDER V34.
; The Gadget->Flags bit GFLG_STRINGEXTEND is provided as a synonym which is
; safe under V34, and equivalent to GACT_STRINGEXTEND under V37.
; (Note that the two flags are not numerically equal)
GFLG_STRINGEXTEND	EQU	$0400  ; this String Gadget has StringExtend

; --- These are the Activation flag bits ----------------------------------
; GACT_RELVERIFY is set if you want to verify that the pointer was still over
; the gadget when the select button was released.  Will cause
; an IDCMP_GADGETUP message to be sent if so.
GACT_RELVERIFY		EQU $0001

; the flag GACT_IMMEDIATE, when set, informs the caller that the gadget
; was activated when it was activated.  this flag works in conjunction with
; the GACT_RELVERIFY flag
GACT_IMMEDIATE		EQU $0002

; the flag GACT_ENDGADGET, when set, tells the system that this gadget, when
; selected, causes the Requester or AbsMessage to be ended.  Requesters or
; AbsMessages that are ended are erased and unlinked from the system
GACT_ENDGADGET		EQU $0004

; the GACT_FOLLOWMOUSE flag, when set, specifies that you want to receive
; reports on mouse movements while this gadget is active.
; You probably want to set the GACT_IMMEDIATE flag when using
; GACT_FOLLOWMOUSE, since that's the only reasonable way you have of learning
; why Intuition is suddenly sending you a stream of mouse movement events.
; If you don't set GACT_RELVERIFY, you'll get at least one Mouse Position
; event.
; Note: boolean FOLLOWMOUSE gadgets require GACT_RELVERIFY to get
; _any_ mouse movement events (this unusual behavior is a compatibility
; hold-over from the old days).

GACT_FOLLOWMOUSE	EQU $0008

; if any of the BORDER flags are set in a Gadget that's included in the
; Gadget list when a Window is opened, the corresponding Border will
; be adjusted to make room for the Gadget
GACT_RIGHTBORDER	EQU $0010
GACT_LEFTBORDER		EQU $0020
GACT_TOPBORDER		EQU $0040
GACT_BOTTOMBORDER	EQU $0080
GACT_BORDERSNIFF	EQU $8000	; neither set nor rely on this bit

GACT_TOGGLESELECT	EQU $0100	; this bit for toggle-select mode
GACT_BOOLEXTEND		EQU $2000	; This Boolean Gadget has a BoolInfo

; should properly be in StringInfo, but aren't
GACT_STRINGLEFT		EQU $0000	; NOTE WELL: that this has value zero
GACT_STRINGCENTER	EQU $0200	; center the String
GACT_STRINGRIGHT	EQU $0400	; right-justify the String
GACT_LONGINT		EQU $0800	; This String Gadget is a Long Integer
GACT_ALTKEYMAP		EQU $1000	; has an alternate keymapping
GACT_STRINGEXTEND	EQU $2000	; this String Gadget has an extension
                    ; NOTE: NEVER SET GACT_STRINGEXTEND
                    ; IF YOU ARE RUNNING ON LESS THAN V36!
                    ; SEE GFLG_STRINGEXTEND (ABOVE) INSTEAD

GACT_ACTIVEGADGET	EQU $4000	; this gadget is "active".  This flag
                ; is maintained by Intuition, and you
                ; cannot count on its value persisting
                ; while you do something on your program's
                ; task.  It can only be trusted by
                ; people implementing custom gadgets

* note $8000 is used above (GACT_BORDERSNIFF); all Activation flags defined

; --- GADGET TYPES -----------------------------------------------------------
; These are the Gaget Type definitions for the variable GadgetType.
; Gadget number type MUST start from one.  NO TYPES OF ZERO ALLOWED.
; first comes the mask for Gadget flags reserved for Gadget typing
GTYP_GADGETTYPE		EQU $FC00	; all Gadget Global Type flags
                    ; (padded)
GTYP_SYSGADGET		EQU $8000	; 1 = Allocated by the system, 0 = by app.
GTYP_SCRGADGET		EQU $4000	; 1 = ScreenGadget, 0 = WindowGadget
GTYP_GZZGADGET		EQU $2000	; 1 = Gadget for WFLG_GIMMEZEROZERO
                    ;     borders
GTYP_REQGADGET		EQU $1000	; 1 = this is a Requester Gadget
; system gadgets
GTYP_SIZING		EQU $0010
GTYP_WDRAGGING		EQU $0020
GTYP_SDRAGGING		EQU $0030
GTYP_WUPFRONT		EQU $0040
GTYP_SUPFRONT		EQU $0050
GTYP_WDOWNBACK		EQU $0060
GTYP_SDOWNBACK		EQU $0070
GTYP_CLOSE		EQU $0080
; application gadgets
GTYP_BOOLGADGET		EQU $0001
GTYP_GADGET0002		EQU $0002
GTYP_PROPGADGET		EQU $0003
GTYP_STRGADGET		EQU $0004
GTYP_CUSTOMGADGET	EQU $0005
GTYP_GTYPEMASK		EQU $0004	; masks out to gadget class

; ========================================================================
; === BoolInfo============================================================
; ========================================================================
; This is the special data needed by an Extended Boolean Gadget
; Typically this structure will be pointed to by the Gadget field SpecialInfo

 STRUCTURE BoolInfo,0

    WORD    bi_Flags	; defined below
    APTR    bi_Mask	; bit mask for highlighting and selecting
            ; mask must follow the same rules as an Image
            ; plane.  Its width and height are determined
            ; by the width and height of the gadget's
            ; select box. (i.e. Gadget.Width and .Height).
    LONG    bi_Reserved	; set to 0

    LABEL   bi_SIZEOF

; set BoolInfo.Flags to this flag bit.
; in the future, additional bits might mean more stuff hanging
; off of BoolInfo.Reserved.

BOOLMASK	EQU	$0001	; extension is for masked gadget

; ========================================================================
; === PropInfo ===========================================================
; ========================================================================
; this is the special data required by the proportional Gadget
; typically, this data will be pointed to by the Gadget variable SpecialInfo
 STRUCTURE PropInfo,0

    WORD pi_Flags	; general purpose flag bits (see defines below)

    ; You initialize the Pot variables before the Gadget is added to
    ; the system.  Then you can look here for the current settings
    ; any time, even while User is playing with this Gadget.  To
    ; adjust these after the Gadget is added to the System, use
    ; ModifyProp(); The Pots are the actual proportional settings,
    ; where a value of zero means zero and a value of MAXPOT means
    ; that the Gadget is set to its maximum setting.
    WORD pi_HorizPot	; 16-bit FixedPoint horizontal quantity percentage;
    WORD pi_VertPot	; 16-bit FixedPoint vertical quantity percentage;

    ; the 16-bit FixedPoint Body variables describe what percentage
    ; of the entire body of stuff referred to by this Gadget is
    ; actually shown at one time.  This is used with the AUTOKNOB
    ; routines, to adjust the size of the AUTOKNOB according to how
    ; much of the data can be seen.  This is also used to decide how
    ; far to advance the Pots when User hits the Container of the Gadget.
    ; For instance, if you were controlling the display of a 5-line
    ; Window of text with this Gadget, and there was a total of 15
    ; lines that could be displayed, you would set the VertBody value to
    ;	 (MAXBODY / (TotalLines / DisplayLines)) = MAXBODY / 3.
    ; Therefore, the AUTOKNOB would fill 1/3 of the container, and if
    ; User hits the Cotainer outside of the knob, the pot would advance
    ; 1/3 (plus or minus) If there's no body to show, or the total
    ; amount of displayable info is less than the display area, set the
    ; Body variables to the MAX.  To adjust these after the Gadget is
    ; added to the System, use ModifyProp().
    WORD pi_HorizBody	; horizontal Body
    WORD pi_VertBody	; vertical Body

    ; these are the variables that Intuition sets and maintains
    WORD pi_CWidth	; Container width (with any relativity absoluted)
    WORD pi_CHeight	; Container height (with any relativity absoluted)
    WORD pi_HPotRes	; pot increments
    WORD pi_VPotRes	; pot increments
    WORD pi_LeftBorder	; Container borders
    WORD pi_TopBorder	; Container borders
    LABEL  pi_SIZEOF

; --- FLAG BITS --------------------------------------------------------------
AUTOKNOB	EQU $0001	; this flag sez:  gimme that old auto-knob
FREEHORIZ	EQU $0002	; if set, the knob can move horizontally
FREEVERT	EQU $0004	; if set, the knob can move vertically
PROPBORDERLESS	EQU $0008	; if set, no border will be rendered
KNOBHIT		EQU $0100	; set when this Knob is hit
PROPNEWLOOK	EQU $0010	; set this if you want to get the new
                ; V36 look

KNOBHMIN	EQU 6		; minimum horizontal size of the knob
KNOBVMIN 	EQU 4		; minimum vertical size of the knob
MAXBODY		EQU $FFFF	; maximum body value
MAXPOT 		EQU $FFFF	; maximum pot value

; ========================================================================
; === StringInfo =========================================================
; ========================================================================
; this is the special data required by the string Gadget
; typically, this data will be pointed to by the Gadget variable SpecialInfo
 STRUCTURE StringInfo,0

    ; you initialize these variables, and then Intuition maintains them
    APTR  si_Buffer	; the buffer containing the start and final string
    APTR  si_UndoBuffer	; optional buffer for undoing current entry
    WORD si_BufferPos	; character position in Buffer
    WORD si_MaxChars	; max number of chars in Buffer (including NULL)
    WORD si_DispPos	; Buffer position of first displayed character

    ; Intuition initializes and maintains these variables for you
    WORD si_UndoPos	; character position in the undo buffer
    WORD si_NumChars	; number of characters currently in Buffer
    WORD si_DispCount	; number of whole characters visible in Container
    WORD si_CLeft	; topleft offset of the container
    WORD si_CTop	; topleft offset of the container

    ; unused field is changed to allow extended specification
    ; of string gadget parameters.  It is ignored unless the flag
    ; GACT_STRINGEXTEND is set in the Gadget's Activation field
    ; or the GFLG_STRINGEXTEND flag is set in the Gadget Flags field.
    ; (See GFLG_STRINGEXTEND for an important note)
    ;APTR  si_LayerPtr	; --- obsolete ---
    APTR  si_Extension

    ; you can initialize this variable before the gadget is submitted to
    ; Intuition, and then examine it later to discover what integer
    ; the user has entered (if the user never plays with the gadget,
    ; the value will be unchanged from your initial setting)
    LONG  si_LongInt	; the LONG return value of a GACT_LONGINT String Gad.

    ; If you want this Gadget to use your own Console keymapping, you
    ; set the GACT_ALTKEYMAP bit in the Activation flags of the Gadget, and
    ; then set this variable to point to your keymap.  If you don't set the
    ; GACT_ALTKEYMAP, you'll get the standard ASCII keymapping.
    APTR si_AltKeyMap

    LABEL si_SIZEOF

; ========================================================================
; === IntuiText ==========================================================
; ========================================================================
; IntuiText is a series of strings that start with a location
; (always relative to the upper-left corner of something) and then the
; text of the string.  The text is null-terminated.
 STRUCTURE IntuiText,0

    BYTE it_FrontPen		; the pens for rendering the text
    BYTE it_BackPen		; the pens for rendering the text

    BYTE it_DrawMode		; the mode for rendering the text

    BYTE it_KludgeFill00	; This is strictly for word-alignment

    WORD it_LeftEdge		; relative start location for the text
    WORD it_TopEdge		; relative start location for the text

    APTR  it_ITextFont		; if NULL, you accept the defaults

    APTR it_IText		; pointer to null-terminated text

    APTR  it_NextText		; pointer to another IntuiText to render

    LABEL it_SIZEOF

; ========================================================================
; === Border =============================================================
; ========================================================================
; Data type Border, used for drawing a series of lines which is intended for
; use as a border drawing, but which may, in fact, be used to render any
; arbitrary vector shape.
; The routine DrawBorder sets up the RastPort with the appropriate
; variables, then does a Move to the first coordinate, then does Draws
; to the subsequent coordinates.
; After all the Draws are done, if NextBorder is non-zero we call DrawBorder
; on NextBorder
 STRUCTURE Border,0

    WORD  bd_LeftEdge		; initial offsets from the origin
    WORD  bd_TopEdge		; initial offsets from the origin
    BYTE  bd_FrontPen		; pen number for rendering
    BYTE  bd_BackPen		; pen number for rendering
    BYTE  bd_DrawMode		; mode for rendering
    BYTE  bd_Count		; number of XY pairs
    APTR  bd_XY			; vector coordinate pairs rel to LeftTop
    APTR  bd_NextBorder		; pointer to any other Border too

    LABEL bd_SIZEOF

; ========================================================================
; === Image ==============================================================
; ========================================================================
; This is a brief image structure for very simple transfers of
; image data to a RastPort
 STRUCTURE Image,0

    WORD ig_LeftEdge		; starting offset relative to something
    WORD ig_TopEdge		; starting offset relative to something
    WORD ig_Width		; pixel size (though data is word-aligned)
    WORD ig_Height		; pixel size
    WORD ig_Depth		; pixel size
    APTR ig_ImageData		; pointer to the actual image bits

    ; the PlanePick and PlaneOnOff variables work much the same way as the
    ; equivalent GELS Bob variables.  It's a space-saving
    ; mechanism for image data.  Rather than defining the image data
    ; for every plane of the RastPort, you need define data only for planes
    ; that are not entirely zero or one.  As you define your Imagery, you will
    ; often find that most of the planes ARE just as color selectors.  For
    ; instance, if you're designing a two-color Gadget to use colors two and
    ; three, and the Gadget will reside in a five-plane display, plane zero
    ; of your imagery would be all ones, bit plane one would have data that
    ; describes the imagery, and bit planes two through four would be
    ; all zeroes.  Using these flags allows you to avoid wasting all that
    ; memory in this way:
    ; first, you specify which planes you want your data to appear
    ; in using the PlanePick variable.	For each bit set in the variable, the
    ; next "plane" of your image data is blitted to the display.  For each bit
    ; clear in this variable, the corresponding bit in PlaneOnOff is examined.
    ; If that bit is clear, a "plane" of zeroes will be used.  If the bit is
    ; set, ones will go out instead.  So, for our example:
    ;	Gadget.PlanePick = 0x02;
    ;	Gadget.PlaneOnOff = 0x01;
    ; Note that this also allows for generic Gadgets, like the System Gadgets,
    ; which will work in any number of bit planes
    ; Note also that if you want an Image that is only a filled rectangle,
    ; you can get this by setting PlanePick to zero (pick no planes of data)
    ; and set PlaneOnOff to describe the pen color of the rectangle.
    ;
    ; NOTE:  Intuition relies on PlanePick to know how many planes
    ; of data are found in ImageData.  There should be no more
    ; '1'-bits in PlanePick than there are planes in ImageData.
    BYTE ig_PlanePick
    BYTE ig_PlaneOnOff

    ; if the NextImage variable is not NULL, Intuition presumes that
    ; it points to another Image structure with another Image to be
    ; rendered
    APTR ig_NextImage

    LABEL ig_SIZEOF

; ========================================================================
; === IntuiMessage =======================================================
; ========================================================================
 STRUCTURE IntuiMessage,0

    STRUCT im_ExecMessage,MN_SIZE

    ; the Class bits correspond directly with the IDCMP Flags, except for the
    ; special bit IDCMP_LONELYMESSAGE (defined below)
    LONG im_Class

    ; the Code field is for special values like MENU number
    WORD im_Code

    ; the Qualifier field is a copy of the current InputEvent's Qualifier
    WORD im_Qualifier

    ; IAddress contains particular addresses for Intuition functions, like
    ; the pointer to the Gadget or the Screen
    APTR im_IAddress

    ; when getting mouse movement reports, any event you get will have the
    ; the mouse coordinates in these variables.  the coordinates are relative
    ; to the upper-left corner of your Window (WFLG_GIMMEZEROZERO
    ; notwithstanding)
    ; If the DELTAMOVE IDCMP flag is set, these values will be deltas from
    ; the last reported position.
    WORD im_MouseX
    WORD im_MouseY

    ; the time values are copies of the current system clock time.  Micros
    ; are in units of microseconds, Seconds in seconds.
    LONG im_Seconds
    LONG im_Micros

    ; the IDCMPWindow variable will always have the address of the Window of
    ; this IDCMP
    APTR im_IDCMPWindow

    ; system-use variable
    APTR im_SpecialLink

    LABEL  im_SIZEOF

; --- IDCMP Classes ------------------------------------------------------
; Please refer to the Autodoc for OpenWindow() and to the Rom Kernel
; Manual for full details on the IDCMP classes.

IDCMP_SIZEVERIFY	EQU	$00000001
IDCMP_NEWSIZE		EQU	$00000002
IDCMP_REFRESHWINDOW	EQU	$00000004
IDCMP_MOUSEBUTTONS	EQU	$00000008
IDCMP_MOUSEMOVE		EQU	$00000010
IDCMP_GADGETDOWN	EQU	$00000020
IDCMP_GADGETUP		EQU	$00000040
IDCMP_REQSET		EQU	$00000080
IDCMP_MENUPICK		EQU	$00000100
IDCMP_CLOSEWINDOW	EQU	$00000200
IDCMP_RAWKEY		EQU	$00000400
IDCMP_REQVERIFY		EQU	$00000800
IDCMP_REQCLEAR		EQU	$00001000
IDCMP_MENUVERIFY	EQU	$00002000
IDCMP_NEWPREFS		EQU	$00004000
IDCMP_DISKINSERTED	EQU	$00008000
IDCMP_DISKREMOVED	EQU	$00010000
IDCMP_WBENCHMESSAGE	EQU	$00020000	; System use only
IDCMP_ACTIVEWINDOW	EQU	$00040000
IDCMP_INACTIVEWINDOW	EQU	$00080000
IDCMP_DELTAMOVE		EQU	$00100000
IDCMP_VANILLAKEY	EQU	$00200000
IDCMP_INTUITICKS	EQU	$00400000
;  for notifications from "boopsi" gadgets:
IDCMP_IDCMPUPDATE	EQU	$00800000  	; new for V36
; for getting help key report during menu session:
IDCMP_MENUHELP		EQU	$01000000  	; new for V36
; for notification of any move/size/zoom/change window:
IDCMP_CHANGEWINDOW	EQU	$02000000  	; new for V36
; NOTEZ-BIEN:		$80000000 is reserved for internal use by IDCMP

; the IDCMP Flags do not use this special bit, which is cleared when
; Intuition sends its special message to the Task, and set when Intuition
; gets its Message back from the Task.  Therefore, I can check here to
; find out fast whether or not this Message is available for me to send
IDCMP_LONELYMESSAGE	EQU	$80000000

; --- IDCMP Codes --------------------------------------------------------
; This group of codes is for the IDCMP_MENUVERIFY function
MENUHOT		EQU	$0001	; IntuiWants verification or MENUCANCEL
MENUCANCEL	EQU	$0002	; HOT Reply of this cancels Menu operation
MENUWAITING	EQU	$0003	; Intuition simply wants a ReplyMsg() ASAP

; These are internal tokens to represent state of verification attempts
; shown here as a clue.
OKOK		EQU	MENUHOT		; guy didn't care
OKABORT		EQU	$0004		; window rendered question moot
OKCANCEL	EQU	MENUCANCEL	; window sent cancel reply

; This group of codes is for the IDCMP_WBENCHMESSAGE messages
WBENCHOPEN	EQU $0001
WBENCHCLOSE	EQU $0002

; A data structure common in V36 Intuition processing

 STRUCTURE	IBox,0
    WORD	ibox_Left
    WORD	ibox_Top
    WORD	ibox_Width
    WORD	ibox_Height
 LABEL	ibox_SIZEOF

; ========================================================================
; === Window =============================================================
; ========================================================================
 STRUCTURE Window,0

    APTR wd_NextWindow		; for the linked list of a Screen

    WORD wd_LeftEdge		; screen dimensions
    WORD wd_TopEdge		; screen dimensions
    WORD wd_Width		; screen dimensions
    WORD wd_Height		; screen dimensions

    WORD wd_MouseY		; relative top top-left corner
    WORD wd_MouseX		; relative top top-left corner

    WORD wd_MinWidth		; minimum sizes
    WORD wd_MinHeight		; minimum sizes
    WORD wd_MaxWidth		; maximum sizes
    WORD wd_MaxHeight		; maximum sizes

    LONG wd_Flags		; see below for definitions

    APTR wd_MenuStrip		; first in a list of menu headers

    APTR wd_Title		; title text for the Window

    APTR wd_FirstRequest	; first in linked list of active Requesters
    APTR wd_DMRequest		; the double-menu Requester
    WORD wd_ReqCount		; number of Requesters blocking this Window
    APTR wd_WScreen		; this Window's Screen
    APTR wd_RPort		; this Window's very own RastPort

    ; the border variables describe the window border.	If you specify
    ; WFLG_GIMMEZEROZERO when you open the window, then the upper-left of the
    ; ClipRect for this window will be upper-left of the BitMap (with correct
    ; offsets when in SuperBitMap mode; you MUST select WFLG_GIMMEZEROZERO
    ; when using SuperBitMap).	If you don't specify ZeroZero, then you save
    ; memory (no allocation of RastPort, Layer, ClipRect and associated
    ; Bitmaps), but you also must offset all your writes by BorderTop,
    ; BorderLeft and do your own mini-clipping to prevent writing over the
    ; system gadgets
    BYTE wd_BorderLeft
    BYTE wd_BorderTop
    BYTE wd_BorderRight
    BYTE wd_BorderBottom
    APTR wd_BorderRPort

    ; You supply a linked-list of gadget that you want for your Window.
    ; This list DOES NOT include system Gadgets.  You get the standard
    ; window system Gadgets by setting flag-bits in the variable Flags (see
    ; the bit definitions below)
    APTR wd_FirstGadget

    ; these are for opening/closing the windows
    APTR wd_Parent
    APTR wd_Descendant

    ; sprite data information for your own Pointer
    ; set these AFTER you Open the Window by calling SetPointer()
    APTR wd_Pointer
    BYTE wd_PtrHeight
    BYTE wd_PtrWidth
    BYTE wd_XOffset
    BYTE wd_YOffset

    ; the IDCMP Flags and User's and Intuition's Message Ports
    ULONG wd_IDCMPFlags
    APTR wd_UserPort
    APTR wd_WindowPort
    APTR wd_MessageKey

    BYTE wd_DetailPen
    BYTE wd_BlockPen

    ; the CheckMark is a pointer to the imagery that will be used when
    ; rendering MenuItems of this Window that want to be checkmarked
    ; if this is equal to NULL, you'll get the default imagery
    APTR wd_CheckMark

    ; if non-null, Screen title when Window is active
    APTR wd_ScreenTitle

    ; These variables have the mouse coordinates relative to the
    ; inner-Window of WFLG_GIMMEZEROZERO Windows.  This is compared with the
    ; MouseX and MouseY variables, which contain the mouse coordinates
    ; relative to the upper-left corner of the Window, WFLG_GIMMEZEROZERO
    ; notwithstanding
    WORD wd_GZZMouseX
    WORD wd_GZZMouseY
    ; these variables contain the width and height of the inner-Window of
    ; WFLG_GIMMEZEROZERO Windows
    WORD wd_GZZWidth
    WORD wd_GZZHeight

    APTR wd_ExtData

    ; general-purpose pointer to User data extension
    APTR wd_UserData
    APTR wd_WLayer	; stash of Window.RPort->Layer

    ; NEW 1.2: need to keep track of the font that OpenWindow opened,
    ; in case user SetFont's into RastPort
    APTR  wd_IFont

    ; (V36) another flag word (the Flags field is used up).
    ; At present, all flag values are system private.
    ; Until further notice, you may not change nor use this field.
    ULONG wd_MoreFlags

    ; ----- subsequent fields are INTUITION PRIVATE ---

    LABEL wd_Size
    LABEL wd_SIZEOF	; you should never use this: only Intuition allocates

; --- Flags requested at OpenWindow() time by the application -------------
WFLG_SIZEGADGET  	EQU $0001	; include sizing system-gadget?
WFLG_DRAGBAR    	EQU $0002	; include dragging system-gadget?
WFLG_DEPTHGADGET   	EQU $0004	; include depth arrangement gadget?
WFLG_CLOSEGADGET   	EQU $0008	; include close-box system-gadget?

WFLG_SIZEBRIGHT		EQU $0010	; size gadget uses right border
WFLG_SIZEBBOTTOM	EQU $0020	; size gadget uses bottom border

; --- refresh modes ----------------------------------------------------------
; combinations of the WFLG_REFRESHBITS select the refresh type
WFLG_REFRESHBITS	EQU $00C0
WFLG_SMART_REFRESH	EQU $0000
WFLG_SIMPLE_REFRESH	EQU $0040
WFLG_SUPER_BITMAP	EQU $0080
WFLG_OTHER_REFRESH	EQU $00C0

WFLG_BACKDROP		EQU $0100	; this is a backdrop window

WFLG_REPORTMOUSE	EQU $0200	; set this to hear every mouse move

WFLG_GIMMEZEROZERO	EQU $0400	; make extra border stuff

WFLG_BORDERLESS		EQU $0800	; set this to get a Window sans border

WFLG_ACTIVATE		EQU $1000	; when Window opens, it's the Active
                    ; one

; FLAGS SET BY INTUITION
WFLG_WINDOWACTIVE	EQU $2000	; this window is the active one
WFLG_INREQUEST		EQU $4000	; this window is in request mode
WFLG_MENUSTATE		EQU $8000	; this Window is active with its
                    ; Menus on

; --- Other User Flags -------------------------------------------------------
WFLG_RMBTRAP		EQU $00010000	; Catch RMB events for your own
WFLG_NOCAREREFRESH	EQU $00020000	; not to be bothered with REFRESH

; --- Other Intuition Flags ----------------------------------------------
WFLG_WINDOWREFRESH	EQU $01000000	; Window is currently refreshing
WFLG_WBENCHWINDOW	EQU $02000000	; WorkBench Window
WFLG_WINDOWTICKED	EQU $04000000	; only one timer tick at a time

SUPER_UNUSED	EQU $FCFC0000	;bits of Flag unused yet

; - V36 new Flags which the programmer may specify in NewScreen.Flags
WFLG_NW_EXTENDED	EQU $00040000	; extension data provided
                    ; see ExtNewWindow structure

; --- V36 Flags to be set only by Intuition -------------------------
WFLG_VISITOR		EQU $08000000	; visitor window (see autodoc for OpenWindow)
WFLG_ZOOMED		EQU $10000000	; identifies "zoom state"
WFLG_HASZOOM		EQU $20000000	; window has a zoom gadget

; --- Other Window Values ----------------------------------------------
DEFAULTMOUSEQUEUE	EQU 5	 ; no more mouse messages

; --- see struct IntuiMessage for the IDCMP Flag definitions -----------------

; ========================================================================
; === NewWindow ==========================================================
; ========================================================================
; NOTE: to use the new features of V36, you may need to use the
; ExtNewWindow structure, below.
 STRUCTURE NewWindow,0

    WORD nw_LeftEdge		; initial Window dimensions
    WORD nw_TopEdge		; initial Window dimensions
    WORD nw_Width		; initial Window dimensions
    WORD nw_Height		; initial Window dimensions

    BYTE nw_DetailPen		; for rendering the detail bits of the Window
    BYTE nw_BlockPen		; for rendering the block-fill bits

    LONG nw_IDCMPFlags		; initial IDCMP state

    LONG nw_Flags		; see the Flag definition under Window

    ; You supply a linked-list of Gadgets for your Window.
    ; This list DOES NOT include system Gadgets.  You get the standard
    ; system Window Gadgets by setting flag-bits in the variable Flags (see
    ; the bit definitions under the Window structure definition)
    APTR	nw_FirstGadget

    ; the CheckMark is a pointer to the imagery that will be used when
    ; rendering MenuItems of this Window that want to be checkmarked
    ; if this is equal to NULL, you'll get the default imagery
    APTR nw_CheckMark

    APTR nw_Title		; title text for the Window

    ; the Screen pointer is used only if you've defined a CUSTOMSCREEN and
    ; want this Window to open in it.  If so, you pass the address of the
    ; Custom Screen structure in this variable.  Otherwise, this variable
    ; is ignored and doesn't have to be initialized.
    APTR nw_Screen

    ; WFLG_SUPER_BITMAP Window?  If so, put the address of your BitMap
    ; structure in this variable.  If not, this variable is ignored and
    ; doesn't have to be initialized
    APTR nw_BitMap

    ; the values describe the minimum and maximum sizes of your Windows.
    ; these matter only if you've chosen the WFLG_SIZEGADGET Gadget option,
    ; which means that you want to let the User to change the size of
    ; this Window.  You describe the minimum and maximum sizes that the
    ; Window can grow by setting these variables.  You can initialize
    ; any one these to zero, which will mean that you want to duplicate
    ; the setting for that dimension (if MinWidth == 0, MinWidth will be
    ; set to the opening Width of the Window).
    ; You can change these settings later using SetWindowLimits().
    ; If you haven't asked for a GTYP_SIZING Gadget, you don't have to
    ; initialize any of these variables.
    WORD nw_MinWidth
    WORD nw_MinHeight
    WORD nw_MaxWidth
    WORD nw_MaxHeight

    ; the type variable describes the Screen in which you want this Window to
    ; open.  The type value can either be CUSTOMSCREEN or one of the
    ; system standard Screen Types such as WBENCHSCREEN.  See the
    ; type definitions under the Screen structure
    ; A new possible value for this field is PUBLICSCREEN, which
    ; defines the window as a 'visitor' window.  See below for
    ; additional information provided.
    WORD nw_Type

    LABEL nw_SIZE
    LABEL nw_SIZEOF

; ExtNewWindow -- NewWindow plus extension fields.
; This structure may be extended again, so programs depending on its
; size are incorrect.

 STRUCTURE ExtNewWindow,nw_SIZE

    ; extensions for V36
    ; if the NewWindow Flag WFLG_NW_EXTENDED is set, then
    ; this field is assumed to point to an array (or chain of arrays)
    ; of TagItem structures.  See also ExtNewScreen for another
    ; use of TagItems to pass optional data.
    ;
    ; see below for tag values and the corresponding data

    APTR	enw_Extension	; pointer to TagItem array
    LABEL enw_SIZEOF

* The TagItem ID's (ti_Tag values) for OpenWindowTagList() follow.
* They are values in a TagItem array passed as extension/replacement
* values for the data in NewWindow.  OpenWindowTagList() can actually
* work well with a NULL NewWindow pointer.

    ENUM TAG_USER+100

    ; these tags simply override NewWindow parameters
    EITEM WA_Left
    EITEM WA_Top
    EITEM WA_Width
    EITEM WA_Height
    EITEM WA_DetailPen
    EITEM WA_BlockPen
    EITEM WA_IDCMP
    EITEM WA_Flags	; not implemented at present
    EITEM WA_Gadgets
    EITEM WA_Checkmark
    EITEM WA_Title
    EITEM WA_ScreenTitle	; means you don't have to call SetWindowTitles
                 ; after you open your window

    EITEM WA_CustomScreen
    EITEM WA_SuperBitMap	; also implies WFLG_SUPER_BITMAP property
    EITEM WA_MinWidth
    EITEM WA_MinHeight
    EITEM WA_MaxWidth
    EITEM WA_MaxHeight

    ; The following are specifications for new features

    EITEM WA_InnerWidth
    EITEM WA_InnerHeight ; You can specify the dimensions of the interior
             ; region of your window, independent of what
             ; the border widths will be.  You probably want
             ; to also specify WA_AutoAdjust to allow
             ; Intuition to move your window or even
             ; shrink it so that it is completely on screen.

    EITEM WA_PubScreenName	; declares that you want the window to open as
             ; a visitor on the public screen whose name is
             ; pointed to by (UBYTE *) ti_Data

    EITEM WA_PubScreen	; open as a visitor window on the public screen
            ; whose address is in (struct Screen *) ti_Data.
            ; To ensure that this screen remains open, you
            ; should either be the screen's owner, have a
            ; window open on the screen, or use LockPubScreen().

    EITEM WA_PubScreenFallBack	; A Boolean, specifies whether a visitor window
             ; should "fall back" to the default public screen
             ; (or Workbench) if the named public screen isn't
             ; available

    EITEM WA_WindowName	; not implemented
    EITEM WA_Colors	; a ColorSpec array for colors to be set
            ; when this window is active.  This is not
            ; implemented, and may not be, since the default
            ; values to restore would be hard to track.
            ; We'd like to at least support per-window colors
            ; for the mouse pointer sprite.

    EITEM WA_Zoom	; ti_Data points to an array of four WORD's,
            ; the initial Left/Top/Width/Height values of
            ; the "alternate" zoom position/dimensions.
            ; It also specifies that you want a Zoom gadget
            ; for your window, whether or not you have a
            ; sizing gadget.

    EITEM WA_MouseQueue	; ti_Data contains initial value for the mouse
            ; message backlog limit for this window.

    EITEM WA_BackFill	; unimplemented at present: provides a "backfill
            ; hook" for your window's layer.

    EITEM WA_RptQueue	; initial value of repeat key backlog limit

    ; These Boolean tag items are alternatives to the NewWindow.Flags
    ; boolean flags with similar names.

    EITEM WA_SizeGadget
    EITEM WA_DragBar
    EITEM WA_DepthGadget
    EITEM WA_CloseGadget
    EITEM WA_Backdrop
    EITEM WA_ReportMouse
    EITEM WA_NoCareRefresh
    EITEM WA_Borderless
    EITEM WA_Activate
    EITEM WA_RMBTrap
    EITEM WA_WBenchWindow	; PRIVATE!!
    EITEM WA_SimpleRefresh	; only specify if TRUE
    EITEM WA_SmartRefresh	; only specify if TRUE
    EITEM WA_SizeBRight
    EITEM WA_SizeBBottom

    ; New Boolean properties
    EITEM WA_AutoAdjust	; shift or squeeze the window's position and
            ; dimensions to fit it on screen.

    EITEM WA_GimmeZeroZero	; equiv. to NewWindow.Flags WFLG_GIMMEZEROZERO

    ; New for V37: WA_MenuHelp (ignored by V36)
    EITEM WA_MenuHelp	; Enables IDCMP_MENUHELP:  Pressing HELP during menus
            ; will return IDCMP_MENUHELP IDCMP message.

*** End of Window attribute enumeration ***

    IFND INTUITION_SCREENS_I
    INCLUDE "intuition/screens.i"
    ENDC

    IFND INTUITION_PREFERENCES_I
    INCLUDE "intuition/preferences.i"
    ENDC

; ========================================================================
; === Remember ===========================================================
; ========================================================================
; this structure is used for remembering what memory has been allocated to
; date by a given routine, so that a premature abort or systematic exit
; can deallocate memory cleanly, easily, and completely
 STRUCTURE Remember,0

    APTR rm_NextRemember
    LONG rm_RememberSize
    APTR rm_Memory

 LABEL    rm_SIZEOF

 STRUCTURE ColorSpec,0

    WORD cs_ColorIndex	; -1 terminates an array of ColorSpec
    UWORD cs_Red	; only six bits recognized in V36
    UWORD cs_Green	; only six bits recognized in V36
    UWORD cs_Blue	; only six bits recognized in V36
 LABEL	cs_SIZEOF

* === Easy Requester Specification ======================================= *
* see also autodocs for EasyRequest and BuildEasyRequest
* NOTE: This structure may grow in size in the future

 STRUCTURE EasyStruct,0

    ULONG es_StructSize		; should be es_SIZEOF
    ULONG es_Flags		; should be 0 for now
    APTR  es_Title		; title of requester window
    APTR  es_TextFormat		; 'printf' style formatting string
    APTR  es_GadgetFormat	; 'printf' style formatting string
 LABEL	es_SIZEOF

; ========================================================================
; === Miscellaneous ======================================================
; ========================================================================

; = MACROS ==============================================================
;#define MENUNUM(n) (n & 0x1F)
;#define ITEMNUM(n) ((n >> 5) & 0x003F)
;#define SUBNUM(n) ((n >> 11) & 0x001F)
;
;#define SHIFTMENU(n) (n & 0x1F)
;#define SHIFTITEM(n) ((n & 0x3F) << 5)
;#define SHIFTSUB(n) ((n & 0x1F) << 11)
;
;#define SRBNUM(n)  (0x08 - (n >> 4))  /* SerRWBits -> read bits per char */
;#define SWBNUM(n)  (0x08 - (n & 0x0F))/* SerRWBits -> write bits per chr */
;#define SSBNUM(n)  (0x01 + (n >> 4))  /* SerStopBuf -> stop bits per chr */
;#define SPARNUM(n) (n >> 4)           /* SerParShk -> parity setting    */
;#define SHAKNUM(n) (n & 0x0F)         /* SerParShk -> handshake mode    */
;
; = MENU STUFF ===========================================================
NOMENU EQU	$001F
NOITEM EQU	$003F
NOSUB  EQU	$001F
MENUNULL EQU	$FFFF

; = =RJ='s peculiarities =================================================
;#define FOREVER for(;;)
;#define SIGN(x) ( ((x) > 0) - ((x) < 0) )

; these defines are for the COMMSEQ and CHECKIT menu stuff.  If CHECKIT,
; I'll use a generic Width (for all resolutions) for the CheckMark.
; If COMMSEQ, likewise I'll use this generic stuff
CHECKWIDTH	EQU	19
COMMWIDTH	EQU	27
LOWCHECKWIDTH	EQU	13
LOWCOMMWIDTH	EQU	16

; these are the AlertNumber defines.  if you are calling DisplayAlert()
; the AlertNumber you supply must have the ALERT_TYPE bits set to one
; of these patterns
ALERT_TYPE	EQU	$80000000
RECOVERY_ALERT	EQU	$00000000	; the system can recover from this
DEADEND_ALERT	EQU	$80000000	; no recovery possible, this is it

; When you're defining IntuiText for the Positive and Negative Gadgets
; created by a call to AutoRequest(), these defines will get you
; reasonable-looking text.  The only field without a define is the IText
; field; you decide what text goes with the Gadget
AUTOFRONTPEN	EQU	0
AUTOBACKPEN	EQU	1
AUTODRAWMODE	EQU	RP_JAM2
AUTOLEFTEDGE	EQU	6
AUTOTOPEDGE	EQU	3
AUTOITEXTFONT	EQU	0
AUTONEXTTEXT	EQU	0

;* --- RAWMOUSE Codes and Qualifiers (Console OR IDCMP) -------------------
SELECTUP	EQU	(IECODE_LBUTTON+IECODE_UP_PREFIX)
SELECTDOWN	EQU	(IECODE_LBUTTON)
MENUUP		EQU	(IECODE_RBUTTON+IECODE_UP_PREFIX)
MENUDOWN	EQU	(IECODE_RBUTTON)
ALTLEFT		EQU	(IEQUALIFIER_LALT)
ALTRIGHT	EQU	(IEQUALIFIER_RALT)
AMIGALEFT	EQU	(IEQUALIFIER_LCOMMAND)
AMIGARIGHT	EQU	(IEQUALIFIER_RCOMMAND)
AMIGAKEYS	EQU	(AMIGALEFT+AMIGARIGHT)

CURSORUP	EQU	$4C
CURSORLEFT	EQU	$4F
CURSORRIGHT	EQU	$4E
CURSORDOWN	EQU	$4D
KEYCODE_Q	EQU	$10
KEYCODE_X	EQU	$32
KEYCODE_N	EQU	$36
KEYCODE_M	EQU	$37
KEYCODE_V   	EQU	$34
KEYCODE_B   	EQU	$35
KEYCODE_LESS	EQU	$38
KEYCODE_GREATER	EQU	$39

    IFND	INTUITION_INTUITIONBASE_I
    INCLUDE	"intuition/intuitionbase.i"
    ENDC

* Include obsolete identifiers:
    IFND	INTUITION_IOBSOLETE_I
    INCLUDE "intuition/iobsolete.i"
    ENDC

    ENDC


Includes/intuition/preferences.i

    IFND  INTUITION_PREFERENCES_I
INTUITION_PREFERENCES_I	SET  1
**
**	$Filename: intuition/preferences.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.6 $
**	$Date: 91/03/13 $
**
**	Structure definition for old-style preferences
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND EXEC_TYPES_I
    INCLUDE "exec/types.i"
    ENDC

    IFND	DEVICES_TIMER_I
    INCLUDE	"devices/timer.i"
    ENDC

; ========================================================================
; === Preferences ========================================================
; ========================================================================

; these are the definitions for the printer configurations
FILENAME_SIZE EQU	30	; Filename size

POINTERSIZE	EQU	(1+16+1)*2	; Size of Pointer data buffer

; These defines are for the default font size.	These actually describe the
; height of the defaults fonts.  The default font type is the topaz
; font, which is a fixed width font that can be used in either
; eighty-column or sixty-column mode.  The Preferences structure reflects
; which is currently selected by the value found in the variable FontSize,
; which may have either of the values defined below.  These values actually
; are used to select the height of the default font.  By changing the
; height, the resolution of the font changes as well.
TOPAZ_EIGHTY	EQU	8
TOPAZ_SIXTY	EQU	9

; ------------------------------------------------------------------------
 STRUCTURE Preferences,0

    ; the default font height
    BYTE pf_FontHeight		; height for system default font

    ; constant describing what's hooked up to the port
    BYTE pf_PrinterPort	; printer port connection

    ; the baud rate of the port
    WORD pf_BaudRate		; baud rate for the serial port

    ; various timing rates
    STRUCT pf_KeyRptSpeed,TV_SIZE ; repeat speed for keyboard
    STRUCT pf_KeyRptDelay,TV_SIZE ; Delay before keys repeat
    STRUCT pf_DoubleClick,TV_SIZE ; Interval allowed between clicks

    ; Intuition Pointer data
    STRUCT pf_PointerMatrix,POINTERSIZE*2 ; Definition of pointer sprite
    BYTE pf_XOffset		; X-Offset for active 'bit'
    BYTE pf_YOffset		; Y-Offset for active 'bit'
    WORD pf_color17		;********************************
    WORD pf_color18		; Colours for sprite pointer
    WORD pf_color19		;********************************
    WORD pf_PointerTicks	; Sensitivity of the pointer

    ; Workbench Screen colors
    WORD pf_color0		;********************************
    WORD pf_color1		;  Standard default colours
    WORD pf_color2		;   Used in the Workbench
    WORD pf_color3		;********************************

    ; positioning data for the Intuition View
    BYTE pf_ViewXOffset		; Offset for top lefthand corner
    BYTE pf_ViewYOffset		; X and Y dimensions
    WORD pf_ViewInitX		; View initial offsets at startup
    WORD pf_ViewInitY		; View initial offsets at startup

    BOOL EnableCLI		; CLI availability switch

    ; printer configurations
    WORD pf_PrinterType		; printer type
    STRUCT pf_PrinterFilename,FILENAME_SIZE ; file for printer

    ; print format and quality configurations
    WORD pf_PrintPitch 		; print pitch
    WORD pf_PrintQuality	; print quality
    WORD pf_PrintSpacing	; number of lines per inch
    WORD pf_PrintLeftMargin	; left margin in characters
    WORD pf_PrintRightMargin	; right margin in characters
    WORD pf_PrintImage		; positive or negative
    WORD pf_PrintAspect		; horizontal or vertical
    WORD pf_PrintShade		; b&w, half-tone, or color
    WORD pf_PrintThreshold	; darkness ctrl for b/w dumps

    ; print paper description
    WORD pf_PaperSize		; paper size
    WORD pf_PaperLength		; paper length in lines
    WORD pf_PaperType		; continuous or single sheet

    ; Serial device settings: These are six nibble-fields in three bytes
    ; (these look a little strange so the defaults will map out to zero)
    BYTE pf_SerRWBits           ; upper nibble = (8-number of read bits)
                                ; lower nibble = (8-number of write bits)
    BYTE pf_SerStopBuf          ; upper nibble = (number of stop bits - 1)
                                ; lower nibble = (table value for BufSize)
    BYTE pf_SerParShk           ; upper nibble = (value for Parity setting)
                                ; lower nibble = (value for Handshake mode)

    BYTE pf_LaceWB		; if workbench is to be interlaced

    STRUCT pf_WorkName,FILENAME_SIZE ; temp file for printer

    BYTE    pf_RowSizeChange	;
    BYTE    pf_ColumnSizeChange ;

    UWORD   pf_PrintFlags	; user preference flags
    WORD    pf_PrintMaxWidth    ; max width of printed picture in 10ths/inch
    UWORD   pf_PrintMaxHeight   ; max height of printed picture in 10ths/inch
    UBYTE   pf_PrintDensity     ; print density
    UBYTE   pf_PrintXOffset     ; offset of printed picture in 10ths/inch

    UWORD   pf_wb_Width		; override default workbench width
    UWORD   pf_wb_Height	; override default workbench height
    UBYTE   pf_wb_Depth		; override default workbench depth

    UBYTE   pf_ext_size		; extension information -- do not touch!
                ; extension size in blocks of 64 bytes

    LABEL pf_SIZEOF

; === Preferences definitions ===========================================

; Workbench Interlace (use one bit)
LACEWB		EQU	$01

; PrinterPort
PARALLEL_PRINTER EQU	$00
SERIAL_PRINTER	EQU	$01

; BaudRate
BAUD_110	EQU	$00
BAUD_300	EQU	$01
BAUD_1200	EQU	$02
BAUD_2400	EQU	$03
BAUD_4800	EQU	$04
BAUD_9600	EQU	$05
BAUD_19200	EQU	$06
BAUD_MIDI	EQU	$07

; PaperType
FANFOLD 	EQU	$00
SINGLE    	EQU	$80

; PrintPitch
PICA    	EQU	$000
ELITE    	EQU	$400
FINE    	EQU	$800

; PrintQuality
DRAFT    	EQU	$000
LETTER		EQU	$100

; PrintSpacing
SIX_LPI		EQU	$000
EIGHT_LPI	EQU	$200

; Print Image
IMAGE_POSITIVE	EQU	$00
IMAGE_NEGATIVE	EQU	$01

; PrintAspect
ASPECT_HORIZ	EQU	$00
ASPECT_VERT	EQU	$01

; PrintShade
SHADE_BW	EQU	$00
SHADE_GREYSCALE	EQU	$01
SHADE_COLOR	EQU	$02

; PaperSize
US_LETTER	EQU	$00
US_LEGAL	EQU	$10
N_TRACTOR	EQU	$20
W_TRACTOR	EQU	$30
CUSTOM    	EQU	$40

; New PaperSizes for V36:
EURO_A0         EQU	$50            ; European size A0: 841 x 1189
EURO_A1         EQU	$60            ; European size A1: 594 x 841
EURO_A2         EQU	$70            ; European size A2: 420 x 594
EURO_A3         EQU	$80            ; European size A3: 297 x 420
EURO_A4         EQU	$90            ; European size A4: 210 x 297
EURO_A5         EQU	$A0            ; European size A5: 148 x 210
EURO_A6         EQU	$B0            ; European size A6: 105 x 148
EURO_A7         EQU	$C0            ; European size A7: 74 x 105
EURO_A8         EQU	$D0            ; European size A8: 52 x 74

; PrinterType
CUSTOM_NAME	EQU	$00
ALPHA_P_101	EQU	$01
BROTHER_15XL	EQU	$02
CBM_MPS1000	EQU	$03
DIAB_630	EQU	$04
DIAB_ADV_D25	EQU	$05
DIAB_C_150	EQU	$06
EPSON		EQU	$07
EPSON_JX_80	EQU	$08
OKIMATE_20	EQU	$09
QUME_LP_20	EQU	$0A
; new printer entries, 3 October 1985
HP_LASERJET	EQU	$0B
HP_LASERJET_PLUS EQU	$0C

; Serial Input Buffer Sizes
SBUF_512        EQU     $00
SBUF_1024       EQU     $01
SBUF_2048       EQU     $02
SBUF_4096       EQU     $03
SBUF_8000       EQU     $04
SBUF_16000      EQU     $05

; Serial Bit Masks
SREAD_BITS	EQU	$F0	; pf_SerRWBits
SWRITE_BITS	EQU	$0F

SSTOP_BITS	EQU	$F0	; pf_SerStopBuf
SBUFSIZE_BITS	EQU	$0F

SPARITY_BITS	EQU	$F0	; pf_SerParShk
SHSHAKE_BITS	EQU	$0F

; Serial Parity (high nibble, but here shifted right, as by C-macro SPARNUM)
SPARITY_NONE    EQU     $00
SPARITY_EVEN    EQU     $01
SPARITY_ODD     EQU     $02
; New parity definitions for V36:
SPARITY_MARK	EQU	$03
SPARITY_SPACE	EQU	$04

; Serial Handshake Mode (low nibble, mask by SHSHAKE_BITS)
SHSHAKE_XON     EQU     $00
SHSHAKE_RTS     EQU     $01
SHSHAKE_NONE    EQU     $02

; new defines for PrintFlags
CORRECT_RED         EQU $0001    ; color correct red shades
CORRECT_GREEN       EQU $0002    ; color correct green shades
CORRECT_BLUE        EQU $0004    ; color correct blue shades

CENTER_IMAGE        EQU $0008      ; center image on paper

IGNORE_DIMENSIONS   EQU $0000    ; ignore max width/height settings
BOUNDED_DIMENSIONS  EQU $0010    ; use max width/height as boundaries
ABSOLUTE_DIMENSIONS EQU $0020    ; use max width/height as absolutes
PIXEL_DIMENSIONS    EQU $0040    ; use max width/height as prt pixels
MULTIPLY_DIMENSIONS EQU $0080    ; use max width/height as multipliers

INTEGER_SCALING     EQU $0100    ; force integer scaling

ORDERED_DITHERING   EQU $0000    ; ordered dithering
HALFTONE_DITHERING  EQU $0200    ; halftone dithering
FLOYD_DITHERING     EQU $0400    ; floyd-steinberg dithering

ANTI_ALIAS          EQU $0800    ; anti-alias image
GREY_SCALE2         EQU $1000    ; for use with hi-res monitor

CORRECT_RGB_MASK    EQU (CORRECT_RED+CORRECT_GREEN+CORRECT_BLUE)
DIMENSIONS_MASK     EQU (BOUNDED_DIMENSIONS+ABSOLUTE_DIMENSIONS+PIXEL_DIMENSIONS+MULTIPLY_DIMENSIONS)
DITHERING_MASK      EQU (HALFTONE_DITHERING+FLOYD_DITHERING)

    ENDC


Includes/intuition/classes.h

#ifndef	INTUITION_CLASSES_H
#define INTUITION_CLASSES_H	1
/*
**  $Filename: intuition/classes.h $
**  $Release: 2.04 Includes, V37.4 $
**  $Revision: 36.2 $
**  $Date: 91/11/08 $
**
**  Used only by class implementors
**
**  (C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef UTILITY_HOOKS_H
#include <utility/hooks.h>
#endif

#ifndef	INTUITION_CLASSUSR_H
#include <intuition/classusr.h>
#endif

/*******************************************/
/*** "White box" access to struct IClass ***/
/*******************************************/

/* This structure is READ-ONLY, and allocated only by Intuition */
typedef struct IClass {
    struct Hook		cl_Dispatcher;
    ULONG		cl_Reserved;	/* must be 0  */
    struct IClass	*cl_Super;
    ClassID		cl_ID;

    /* where within an object is the instance data for this class? */
    UWORD		cl_InstOffset;
    UWORD		cl_InstSize;

    ULONG		cl_UserData;	/* per-class data of your choice */
    ULONG		cl_SubclassCount;
                    /* how many direct subclasses?	*/
    ULONG		cl_ObjectCount;
                /* how many objects created of this class? */
    ULONG		cl_Flags;
#define	CLF_INLIST	0x00000001	/* class is in public class list */
} Class;

/* add offset for instance data to an object handle */
#define INST_DATA( cl, o )	((VOID *) (((UBYTE *)o)+cl->cl_InstOffset))

/* sizeof the instance data for a given class */
#define SIZEOF_INSTANCE( cl )	((cl)->cl_InstOffset + (cl)->cl_InstSize \
            + sizeof (struct _Object ))

/**************************************************/
/*** "White box" access to struct _Object	***/
/**************************************************/

/*
 * We have this, the instance data of the root class, PRECEDING
 * the "object".  This is so that Gadget objects are Gadget pointers,
 * and so on.  If this structure grows, it will always have o_Class
 * at the end, so the macro OCLASS(o) will always have the same
 * offset back from the pointer returned from NewObject().
 *
 * This data structure is subject to change.  Do not use the o_Node
 * embedded structure.
 */
struct _Object {
    struct MinNode	o_Node;
    struct IClass	*o_Class;
};

/* convenient typecast	*/
#define _OBJ( o )	((struct _Object *)(o))

/* get "public" handle on baseclass instance from real beginning of obj data */
#define BASEOBJECT( _obj )	( (Object *) (_OBJ(_obj)+1) )

/* get back to object data struct from public handle */
#define _OBJECT( o )		(_OBJ(o) - 1)

/* get class pointer from an object handle	*/
#define OCLASS( o )	( (_OBJECT(o))->o_Class )

#endif


Includes/intuition/icclass.h

#ifndef INTUITION_ICCLASS_H
#define INTUITION_ICCLASS_H
/*
**  $Filename: intuition/icclass.h $
**  $Release: 2.04 Includes, V37.4 $
**  $Revision: 36.2 $
**  $Date: 91/11/08 $
**
**  Gadget/object interconnection classes
**
**  (C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

#define ICM_Dummy	(0x0401L)	/* used for nothing		*/
#define ICM_SETLOOP	(0x0402L)	/* set/increment loop counter	*/
#define ICM_CLEARLOOP	(0x0403L)	/* clear/decrement loop counter	*/
#define ICM_CHECKLOOP	(0x0404L)	/* set/increment loop		*/

/* no parameters for ICM_SETLOOP, ICM_CLEARLOOP, ICM_CHECKLOOP	*/

/* interconnection attributes used by icclass, modelclass, and gadgetclass */
#define ICA_Dummy	(TAG_USER+0x40000L)
#define ICA_TARGET	(ICA_Dummy + 1)
    /* interconnection target		*/
#define ICA_MAP		(ICA_Dummy + 2)
    /* interconnection map tagitem list	*/
#define ICSPECIAL_CODE	(ICA_Dummy + 3)
    /* a "pseudo-attribute", see below.	*/

/* Normally, the value for ICA_TARGET is some object pointer,
 * but if you specify the special value ICTARGET_IDCMP, notification
 * will be send as an IDCMP_IDCMPUPDATE message to the appropriate window's
 * IDCMP port.	See the definition of IDCMP_IDCMPUPDATE.
 *
 * When you specify ICTARGET_IDCMP for ICA_TARGET, the map you
 * specify will be applied to derive the attribute list that is
 * sent with the IDCMP_IDCMPUPDATE message.  If you specify a map list
 * which results in the attribute tag id ICSPECIAL_CODE, the
 * lower sixteen bits of the corresponding ti_Data value will
 * be copied into the Code field of the IDCMP_IDCMPUPDATE IntuiMessage.
 */
#define ICTARGET_IDCMP	(~0L)

#endif /* INTUITION_ICCLASS_H */


Includes/intuition/intuitionbase.h

#ifndef INTUITION_INTUITIONBASE_H
#define INTUITION_INTUITIONBASE_H 1
/*
**  $Filename: intuition/intuitionbase.h $
**  $Release: 2.04 Includes, V37.4 $
**  $Revision: 36.19 $
**  $Date: 90/07/12 $
**
**  Public part of IntuitionBase structure and supporting structures
**
**  (C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef EXEC_LIBRARIES_H
#include <exec/libraries.h>
#endif

#ifndef INTUITION_INTUITION_H
#include <intuition/intuition.h>
#endif

#ifndef EXEC_INTERRUPTS_H
#include <exec/interrupts.h>
#endif

/* these are the display modes for which we have corresponding parameter
 *  settings in the config arrays
 */
#define DMODECOUNT	0x0002	/* how many modes there are */
#define HIRESPICK	0x0000
#define LOWRESPICK	0x0001

#define EVENTMAX 10		/* size of event array */

/* these are the system Gadget defines */
#define RESCOUNT	2
#define HIRESGADGET	0
#define LOWRESGADGET	1

#define GADGETCOUNT	8
#define UPFRONTGADGET	0
#define DOWNBACKGADGET	1
#define SIZEGADGET	2
#define CLOSEGADGET	3
#define DRAGGADGET	4
#define SUPFRONTGADGET	5
#define SDOWNBACKGADGET	6
#define SDRAGGADGET	7

/* ======================================================================== */
/* === IntuitionBase ====================================================== */
/* ======================================================================== */
/*
 * Be sure to protect yourself against someone modifying these data as
 * you look at them.  This is done by calling:
 *
 * lock = LockIBase(0), which returns a ULONG.	When done call
 * UnlockIBase(lock) where lock is what LockIBase() returned.
 */

/* This structure is strictly READ ONLY */
struct IntuitionBase
{
    struct Library LibNode;

    struct View ViewLord;

    struct Window *ActiveWindow;
    struct Screen *ActiveScreen;

    /* the FirstScreen variable points to the frontmost Screen.  Screens are
     * then maintained in a front to back order using Screen.NextScreen
     */
    struct Screen *FirstScreen; /* for linked list of all screens */

    ULONG Flags;	/* values are all system private */
    WORD	MouseY, MouseX;
            /* note "backwards" order of these		*/

    ULONG Seconds;	/* timestamp of most current input event */
    ULONG Micros;	/* timestamp of most current input event */

    /* I told you this was private.
     * The data beyond this point has changed, is changing, and
     * will continue to change.
     */
};

#endif


Includes/intuition/screens.h

#ifndef INTUITION_SCREENS_H
#define INTUITION_SCREENS_H TRUE
/*
**  $Filename: intuition/screens.h $
**  $Release: 2.04 Includes, V37.4 $
**  $Revision: 36.36 $
**  $Date: 91/10/07 $
**
**  The Screen and NewScreen structures and attributes
**
**  (C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef GRAPHICS_GFX_H
#include <graphics/gfx.h>
#endif

#ifndef GRAPHICS_CLIP_H
#include <graphics/clip.h>
#endif

#ifndef GRAPHICS_VIEW_H
#include <graphics/view.h>
#endif

#ifndef GRAPHICS_RASTPORT_H
#include <graphics/rastport.h>
#endif

#ifndef GRAPHICS_LAYERS_H
#include <graphics/layers.h>
#endif

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

/*
 * NOTE:  intuition/iobsolete.h is included at the END of this file!
 */

/* ======================================================================== */
/* === DrawInfo ========================================================= */
/* ======================================================================== */

/* This is a packet of information for graphics rendering.  It originates
 * with a Screen, and is gotten using GetScreenDrawInfo( screen );
 */

/* If you find dri_Version >= DRI_VERSION, you know this structure
 * has at least the fields defined in this version of the include file
 */
#define RI_VERSION	(1)	/* obsolete, will be removed		*/
#define DRI_VERSION	(1)

struct DrawInfo
{
    UWORD	dri_Version;	/* will be  DRI_VERSION			*/
    UWORD	dri_NumPens;	/* guaranteed to be >= numDrIPens	*/
    UWORD	*dri_Pens;	/* pointer to pen array			*/

    struct TextFont	*dri_Font;	/* screen default font		*/
    UWORD	dri_Depth;	/* (initial) depth of screen bitmap	*/

    struct {	  /* from DisplayInfo database for initial display mode	*/
    UWORD	X;
    UWORD	Y;
    }		dri_Resolution;

    ULONG	dri_Flags;		/* defined below		*/
    ULONG	dri_Reserved[7];	/* avoid recompilation ;^)	*/
};

#define DRIF_NEWLOOK	0x00000001	/* specified SA_Pens, full treatment */

/* rendering pen number indexes into DrawInfo.dri_Pens[]	*/
#define DETAILPEN	 (0x0000)	/* compatible Intuition rendering pens	*/
#define BLOCKPEN	 (0x0001)	/* compatible Intuition rendering pens	*/
#define TEXTPEN		 (0x0002)	/* text on background			*/
#define SHINEPEN	 (0x0003)	/* bright edge on 3D objects		*/
#define SHADOWPEN	 (0x0004)	/* dark edge on 3D objects		*/
#define FILLPEN		 (0x0005)	/* active-window/selected-gadget fill	*/
#define FILLTEXTPEN	 (0x0006)	/* text over FILLPEN			*/
#define BACKGROUNDPEN	 (0x0007)	/* always color 0			*/
#define HIGHLIGHTTEXTPEN (0x0008)	/* special color text, on background	*/

#define NUMDRIPENS	 (0x0009)

/* ======================================================================== */
/* === Screen ============================================================= */
/* ======================================================================== */
struct Screen
{
    struct Screen *NextScreen;		/* linked list of screens */
    struct Window *FirstWindow;		/* linked list Screen's Windows */

    WORD LeftEdge, TopEdge;		/* parameters of the screen */
    WORD Width, Height;			/* parameters of the screen */

    WORD MouseY, MouseX;		/* position relative to upper-left */

    UWORD Flags;			/* see definitions below */

    UBYTE *Title;			/* null-terminated Title text */
    UBYTE *DefaultTitle;		/* for Windows without ScreenTitle */

    /* Bar sizes for this Screen and all Window's in this Screen */
    /* Note that BarHeight is one less than the actual menu bar
     * height.	We're going to keep this in V36 for compatibility,
     * although V36 artwork might use that extra pixel
     *
     * Also, the title bar height of a window is calculated from the
     * screen's WBorTop field, plus the font height, plus one.
     */
    BYTE BarHeight, BarVBorder, BarHBorder, MenuVBorder, MenuHBorder;
    BYTE WBorTop, WBorLeft, WBorRight, WBorBottom;

    struct TextAttr *Font;		/* this screen's default font	   */

    /* the display data structures for this Screen */
    struct ViewPort ViewPort;		/* describing the Screen's display */
    struct RastPort RastPort;		/* describing Screen rendering	   */
    struct BitMap BitMap;		/* extra copy of RastPort BitMap   */
    struct Layer_Info LayerInfo;	/* each screen gets a LayerInfo    */

    /* Only system gadgets may be attached to a screen.
     *	You get the standard system Screen Gadgets automatically
     */
    struct Gadget *FirstGadget;

    UBYTE DetailPen, BlockPen;		/* for bar/border/gadget rendering */

    /* the following variable(s) are maintained by Intuition to support the
     * DisplayBeep() color flashing technique
     */
    UWORD SaveColor0;

    /* This layer is for the Screen and Menu bars */
    struct Layer *BarLayer;

    UBYTE *ExtData;

    UBYTE *UserData;	/* general-purpose pointer to User data extension */

    /**** Data below this point are SYSTEM PRIVATE ****/
};

/* --- FLAGS SET BY INTUITION --------------------------------------------- */
/* The SCREENTYPE bits are reserved for describing various Screen types
 * available under Intuition.
 */
#define SCREENTYPE	0x000F	/* all the screens types available	*/
/* --- the definitions for the Screen Type ------------------------------- */
#define WBENCHSCREEN	0x0001	/* identifies the Workbench screen	*/
#define PUBLICSCREEN	0x0002	/* public shared (custom) screen	*/
#define CUSTOMSCREEN	0x000F	/* original custom screens		*/

#define SHOWTITLE	0x0010	/* this gets set by a call to ShowTitle() */

#define BEEPING		0x0020	/* set when Screen is beeping (private)	*/

#define CUSTOMBITMAP	0x0040	/* if you are supplying your own BitMap */

#define SCREENBEHIND	0x0080	/* if you want your screen to open behind
                 * already open screens
                 */
#define SCREENQUIET	0x0100	/* if you do not want Intuition to render
                 * into your screen (gadgets, title)
                 */
#define SCREENHIRES	0x0200	/* do not use lowres gadgets  (private)	*/

#define NS_EXTENDED	0x1000		/* ExtNewScreen.Extension is valid	*/
/* V36 applications can use OpenScreenTagList() instead of NS_EXTENDED	*/

#define AUTOSCROLL	0x4000	/* screen is to autoscoll		*/

#define STDSCREENHEIGHT -1	/* supply in NewScreen.Height		*/
#define STDSCREENWIDTH -1	/* supply in NewScreen.Width		*/

/*
 * Screen attribute tag ID's.  These are used in the ti_Tag field of
 * TagItem arrays passed to OpenScreenTagList() (or in the
 * ExtNewScreen.Extension field).
 */

/* Screen attribute tags.  Please use these versions, not those in
 * iobsolete.h.
 */

#define SA_Dummy	(TAG_USER + 32)
/*
 * these items specify items equivalent to fields in NewScreen
 */
#define SA_Left		(SA_Dummy + 0x0001)
#define SA_Top		(SA_Dummy + 0x0002)
#define SA_Width	(SA_Dummy + 0x0003)
#define SA_Height	(SA_Dummy + 0x0004)
            /* traditional screen positions	and dimensions	*/
#define SA_Depth	(SA_Dummy + 0x0005)
            /* screen bitmap depth				*/
#define SA_DetailPen	(SA_Dummy + 0x0006)
            /* serves as default for windows, too		*/
#define SA_BlockPen	(SA_Dummy + 0x0007)
#define SA_Title	(SA_Dummy + 0x0008)
            /* default screen title				*/
#define SA_Colors	(SA_Dummy + 0x0009)
            /* ti_Data is an array of struct ColorSpec,
             * terminated by ColorIndex = -1.  Specifies
             * initial screen palette colors.
             */
#define SA_ErrorCode	(SA_Dummy + 0x000A)
            /* ti_Data points to LONG error code (values below)*/
#define SA_Font		(SA_Dummy + 0x000B)
            /* equiv. to NewScreen.Font			*/
#define SA_SysFont	(SA_Dummy + 0x000C)
            /* Selects one of the preferences system fonts:
             *	0 - old DefaultFont, fixed-width
             *	1 - WB Screen preferred font
             */
#define SA_Type		(SA_Dummy + 0x000D)
            /* equiv. to NewScreen.Type			*/
#define SA_BitMap	(SA_Dummy + 0x000E)
            /* ti_Data is pointer to custom BitMap.  This
             * implies type of CUSTOMBITMAP
             */
#define SA_PubName	(SA_Dummy + 0x000F)
            /* presence of this tag means that the screen
             * is to be a public screen.  Please specify
             * BEFORE the two tags below
             */
#define SA_PubSig	(SA_Dummy + 0x0010)
#define SA_PubTask	(SA_Dummy + 0x0011)
            /* Task ID and signal for being notified that
             * the last window has closed on a public screen.
             */
#define SA_DisplayID	(SA_Dummy + 0x0012)
            /* ti_Data is new extended display ID from
             * <graphics/displayinfo.h>.
             */
#define SA_DClip	(SA_Dummy + 0x0013)
            /* ti_Data points to a rectangle which defines
             * screen display clip region
             */
#define SA_Overscan	(SA_Dummy + 0x0014)
            /* was S_STDDCLIP.  Set to one of the OSCAN_
             * specifiers below to get a system standard
             * overscan region for your display clip,
             * screen dimensions (unless otherwise specified),
             * and automatically centered position (partial
             * support only so far).
             * If you use this, you shouldn't specify
             * SA_DClip.  SA_Overscan is for "standard"
             * overscan dimensions, SA_DClip is for
             * your custom numeric specifications.
             */
#define SA_Obsolete1	(SA_Dummy + 0x0015)
            /* obsolete S_MONITORNAME			*/

/** booleans **/
#define SA_ShowTitle	(SA_Dummy + 0x0016)
            /* boolean equivalent to flag SHOWTITLE		*/
#define SA_Behind	(SA_Dummy + 0x0017)
            /* boolean equivalent to flag SCREENBEHIND	*/
#define SA_Quiet	(SA_Dummy + 0x0018)
            /* boolean equivalent to flag SCREENQUIET	*/
#define SA_AutoScroll	(SA_Dummy + 0x0019)
            /* boolean equivalent to flag AUTOSCROLL	*/
#define SA_Pens		(SA_Dummy + 0x001A)
            /* pointer to ~0 terminated UWORD array, as
             * found in struct DrawInfo
             */
#define SA_FullPalette	(SA_Dummy + 0x001B)
            /* boolean: initialize color table to entire
             *  preferences palette (32 for V36), rather
             * than compatible pens 0-3, 17-19, with
             * remaining palette as returned by GetColorMap()
             */

/* this is an obsolete tag included only for compatibility with V35
 * interim release for the A2024 and Viking monitors
 */
#ifndef NSTAG_EXT_VPMODE
#define NSTAG_EXT_VPMODE (TAG_USER | 1)
#endif

/* OpenScreen error codes, which are returned in the (optional) LONG
 * pointed to by ti_Data for the SA_ErrorCode tag item
 */
#define OSERR_NOMONITOR	(1)	/* named monitor spec not available	*/
#define OSERR_NOCHIPS	(2)	/* you need newer custom chips		*/
#define OSERR_NOMEM	(3)	/* couldn't get normal memory		*/
#define OSERR_NOCHIPMEM	(4)	/* couldn't get chipmem			*/
#define OSERR_PUBNOTUNIQUE (5)	/* public screen name already used	*/
#define OSERR_UNKNOWNMODE (6)	/* don't recognize mode asked for	*/

/* ======================================================================== */
/* === NewScreen ========================================================== */
/* ======================================================================== */
/* note: to use the Extended field, you must use the
 * new ExtNewScreen structure, below
 */
struct NewScreen
{
    WORD LeftEdge, TopEdge, Width, Height, Depth;  /* screen dimensions */

    UBYTE DetailPen, BlockPen;	/* for bar/border/gadget rendering	*/

    UWORD ViewModes;		/* the Modes for the ViewPort (and View) */

    UWORD Type;			/* the Screen type (see defines above)	*/

    struct TextAttr *Font;	/* this Screen's default text attributes */

    UBYTE *DefaultTitle;	/* the default title for this Screen	*/

    struct Gadget *Gadgets;	/* UNUSED:  Leave this NULL		*/

    /* if you are opening a CUSTOMSCREEN and already have a BitMap
     * that you want used for your Screen, you set the flags CUSTOMBITMAP in
     * the Type field and you set this variable to point to your BitMap
     * structure.  The structure will be copied into your Screen structure,
     * after which you may discard your own BitMap if you want
     */
    struct BitMap *CustomBitMap;
};

/*
 * For compatibility reasons, we need a new structure for extending
 * NewScreen.  Use this structure is you need to use the new Extension
 * field.
 *
 * NOTE: V36-specific applications should use the
 * OpenScreenTagList( newscreen, tags ) version of OpenScreen().
 * Applications that want to be V34-compatible as well may safely use the
 * ExtNewScreen structure.  Its tags will be ignored by V34 Intuition.
 *
 */
struct ExtNewScreen
{
    WORD LeftEdge, TopEdge, Width, Height, Depth;
    UBYTE DetailPen, BlockPen;
    UWORD ViewModes;
    UWORD Type;
    struct TextAttr *Font;
    UBYTE *DefaultTitle;
    struct Gadget *Gadgets;
    struct BitMap *CustomBitMap;

    struct TagItem	*Extension;
                /* more specification data, scanned if
                 * NS_EXTENDED is set in NewScreen.Type
                 */
};

/* === Overscan Types ===	*/
#define OSCAN_TEXT	(1)	/* entirely visible	*/
#define OSCAN_STANDARD	(2)	/* just past edges	*/
#define OSCAN_MAX	(3)	/* as much as possible	*/
#define OSCAN_VIDEO	(4)	/* even more than is possible	*/

/* === Public Shared Screen Node ===	*/

/* This is the representative of a public shared screen.
 * This is an internal data structure, but some functions may
 * present a copy of it to the calling application.  In that case,
 * be aware that the screen pointer of the structure can NOT be
 * used safely, since there is no guarantee that the referenced
 * screen will remain open and a valid data structure.
 *
 * Never change one of these.
 */

struct PubScreenNode	{
    struct Node		psn_Node;	/* ln_Name is screen name */
    struct Screen	*psn_Screen;
    UWORD		psn_Flags;	/* below		*/
    WORD		psn_Size;	/* includes name buffer	*/
    WORD		psn_VisitorCount; /* how many visitor windows */
    struct Task		*psn_SigTask;	/* who to signal when visitors gone */
    UBYTE		psn_SigBit;	/* which signal	*/
};

#define PSNF_PRIVATE	(0x0001)

/* NOTE: Due to a bug in NextPubScreen(), make sure your buffer
 * actually has MAXPUBSCREENNAME+1 characters in it!
 */
#define MAXPUBSCREENNAME	(139)	/* names no longer, please	*/

/* pub screen modes	*/
#define SHANGHAI	0x0001	/* put workbench windows on pub screen */
#define POPPUBSCREEN	0x0002	/* pop pub screen to front when visitor opens */

/* Include obsolete identifiers: */
#ifndef INTUITION_IOBSOLETE_H
#include <intuition/iobsolete.h>
#endif

#endif


Includes/intuition/classes.i

    IFND INTUITION_CLASSES_I
INTUITION_CLASSES_I SET 1
**
**  $Filename: intuition/classes.i $
**  $Release: 2.04 Includes, V37.4 $
**  $Revision: 36.3 $
**  $Date: 91/11/08 $
**
**  Only used by class implementors
**
**  (C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND UTILITY_HOOKS_I
    INCLUDE "utility/hooks.i"
    ENDC

    IFND	INTUITION_CLASSUSR_I
    INCLUDE "intuition/classusr.i"
    ENDC

;*******************************************
;*** "White box" access to struct IClass ***
;*******************************************

 STRUCTURE ICLASS,0
    STRUCT cl_Dispatcher,h_SIZEOF
    ULONG  cl_Reserved		; must be 0

    APTR   cl_Super
    APTR   cl_ID		; pointer to null-terminated string

    ; where within an object is the instance data for this class?
    UWORD  cl_InstOffset
    UWORD  cl_InstSize

    ULONG  cl_UserData		; per-class data of your choice
    ULONG  cl_SubclassCount	; how many direct subclasses?
    ULONG  cl_ObjectCount	; how many objects created of this class?
    ULONG  cl_Flags
    ; no iclass_SIZEOF because only Intuition allocates these

; defined values of cl_Flags
CLB_INLIST EQU 0
CLF_INLIST EQU $00000001	; class in in public class list

; see classes.h for common calculations (sorry, no macros yet)

;**************************************************
;*** "White box" access to struct _Object	***
;**************************************************

* We have this, the instance data of the root class, PRECEDING
* the "object".  This is so that Gadget objects are Gadget pointers,
* and so on.  If this structure grows, it will always have o_Class
* at the end, so the you can always get it by subtracting #4 from
* the pointer returned from NewObject().
*
* This data structure is subject to change.  Do not use the o_Node
* embedded structure.

 STRUCTURE _Object,0
    STRUCT o_Node,MLN_SIZE
    APTR   o_Class

    ; this value may change but difference between it and offset of o_Class
    ; will remain constant
    LABEL  _object_SIZEOF

    ENDC


Includes/intuition/icclass.i

    IFND INTUITION_ICCLASS_I
INTUITION_ICCLASS_I SET 1
**
**  $Filename: intuition/icclass.i $
**  $Release: 2.04 Includes, V37.4 $
**  $Revision: 36.4 $
**  $Date: 91/11/08 $
**
**  Gadget/object interconnection classes
**
**  (C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND UTILITY_TAGITEM_I
    INCLUDE "utility/tagitem.i"
    ENDC

ICM_SETLOOP   EQU $402	; set/increment loop counter
ICM_CLEARLOOP EQU $403	; clear/decrement loop counter
ICM_CHECKLOOP EQU $404	; set/increment loop

* no arguments for ICM_SETLOOP, ICM_CLEARLOOP, ICM_CHECKLOOP

* interconnection attributes used by icclass, modelclass, and gadgetclass

ICA_Dummy EQU		$40000
ICA_TARGET EQU		(ICA_Dummy+1)	; interconnection target
ICA_MAP EQU		(ICA_Dummy+2)	; interconnection map tagitem list
ICSPECIAL_CODE EQU	(ICA_Dummy+3)	; a "pseudo-attribute",  see below.

* Normally, the value for ICA_TARGET is some object pointer,
* but if you specify the special value ICTARGET_IDCMP, notification
* will be send as an IDCMP_IDCMPUPDATE message to the appropriate window's
* IDCMP port.  See the definition of IDCMP_IDCMPUPDATE.
*
* When you specify ICTARGET_IDCMP for ICA_TARGET, the map you
* specify will be applied to derive the attribute list that is
* sent with the IDCMP_IDCMPUPDATE message.  If you specify a map list
* which results in the attribute tag id ICSPECIAL_CODE, the
* lower sixteen bits of the corresponding ti_Data value will
* be copied into the Code field of the IDCMP_IDCMPUPDATE IntuiMessage.

ICTARGET_IDCMP	EQU $ffffffff

    ENDC


Includes/intuition/intuitionbase.i

    IFND  INTUITION_INTUITIONBASE_I
INTUITION_INTUITIONBASE_I SET  1
**
** $Filename: intuition/intuitionbase.i $
** $Release: 2.04 Includes, V37.4 $
** $Revision: 36.5 $
** $Date: 90/07/12 $
**
** The public part of  IntuitionBase structure and supporting structures
**
**  (C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND EXEC_TYPES_I
    INCLUDE "exec/types.i"
    ENDC

    IFND EXEC_LIBRARIES_I
    INCLUDE "exec/libraries.i"
    ENDC

    IFND	GRAPHICS_VIEW_I
    INCLUDE	"graphics/view.i"
    ENDC

* Be sure to protect yourself against someone modifying these data as
* you look at them.  This is done by calling:
*
* lock = LockIBase(0), which returns a ULONG.  When done call
*  D0		  D0
* UnlockIBase(lock) where lock is what LockIBase() returned.
*	       A0
* NOTE: these library functions are simply stubs now, but should be called
* to be compatible with future releases.

* ======================================================================== *
* === IntuitionBase ====================================================== *
* ======================================================================== *
 STRUCTURE IntuitionBase,0

    STRUCT	ib_LibNode,LIB_SIZE
    STRUCT	ib_ViewLord,v_SIZEOF
    APTR	ib_ActiveWindow
    APTR	ib_ActiveScreen

* the FirstScreen variable points to the frontmost Screen.  Screens are
* then maintained in a front to back order using Screen.NextScreen

    APTR	ib_FirstScreen
    ULONG	ib_Flags	; private meaning
    WORD	ib_MouseY	; these are supposed to be backwards,
    WORD	ib_MouseX	;  but weren't, recently

    ULONG	ib_Seconds
    ULONG	ib_Micros

* there is not 'sizeof' here because...
*
*
    ENDC


Includes/intuition/screens.i

    IFND  INTUITION_SCREENS_I
INTUITION_SCREENS_I	SET  1
**
**	$Filename: intuition/screens.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.18 $
**	$Date: 91/10/07 $
**
**	The Screen and NewScreen structures and attributes
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**
    IFND EXEC_TYPES_I
    INCLUDE "exec/types.i"
    ENDC

    IFND GRAPHICS_GFX_I
    INCLUDE "graphics/gfx.i"
    ENDC

    IFND GRAPHICS_CLIP_I
    INCLUDE "graphics/clip.i"
    ENDC

    IFND GRAPHICS_VIEW_I
    INCLUDE "graphics/view.i"
    ENDC

    IFND GRAPHICS_RASTPORT_I
    INCLUDE "graphics/rastport.i"
    ENDC

    IFND GRAPHICS_LAYERS_I
    INCLUDE "graphics/layers.i"
    ENDC

    IFND UTILITY_TAGITEM_I
    INCLUDE "utility/tagitem.i"
    ENDC

*
* NOTE:  intuition/iobsolete.i is included at the END of this file!
*

; ========================================================================
; === DrawInfo =========================================================
; ========================================================================

* This is a packet of information for graphics rendering.  It originates
* with a Screen, and is gotten using GetScreenDrawInfo( screen );

* If you find dri_Version >= DRI_VERSION, you know this structure
* has at least the fields defined in this version of the include file

DRI_VERSION	EQU	1

 STRUCTURE DrawInfo,0
    UWORD	dri_Version	 ; will be  DRI_VERSION
    UWORD	dri_NumPens	 ; guaranteed to be >= NUMDRIPENS
    APTR	dri_Pens	 ; pointer to pen array
    APTR	dri_Font	 ; screen default font
    UWORD	dri_Depth	 ; (initial) depth of screen bitmap
    ; from DisplayInfo database for initial display mode
    UWORD	dri_ResolutionX
    UWORD	dri_ResolutionY
    ULONG	dri_Flags
   STRUCT	dri_longreserved,28

DRIF_NEWLOOK	EQU	$00000001 ; specified SA_Pens, full treatment
DRIB_NEWLOOK	EQU	0

    ; rendering pen number indexes into DrawInfo.dri_Pens[]
    ENUM
    EITEM	DETAILPEN	; compatible Intuition rendering pens
    EITEM	BLOCKPEN,
    EITEM	TEXTPEN		; text on background (pen = 0)
    EITEM	SHINEPEN	; bright edge on bas-relief
    EITEM	SHADOWPEN	; dark edge
    EITEM	FILLPEN		; active window fill
    EITEM	FILLTEXTPEN	; text over FILLPEN
    EITEM	BACKGROUNDPEN	; always color 0
    EITEM	HIGHLIGHTTEXTPEN  ; highlighted text, against BACKGROUNDPEN
    EITEM	NUMDRIPENS

; ========================================================================
; === Screen =============================================================
; ========================================================================
 STRUCTURE Screen,0

    APTR sc_NextScreen		; linked list of screens
    APTR sc_FirstWindow		; linked list Screen's Windows

    WORD sc_LeftEdge		; parameters of the screen
    WORD sc_TopEdge		; parameters of the screen

    WORD sc_Width		; null-terminated Title text
    WORD sc_Height		; for Windows without ScreenTitle

    WORD sc_MouseY		; position relative to upper-left
    WORD sc_MouseX		; position relative to upper-left

    WORD sc_Flags		; see definitions below

    APTR sc_Title
    APTR sc_DefaultTitle

    ; Bar sizes for this Screen and all Window's in this Screen
    BYTE sc_BarHeight
    BYTE sc_BarVBorder
    BYTE sc_BarHBorder
    BYTE sc_MenuVBorder
    BYTE sc_MenuHBorder
    BYTE sc_WBorTop
    BYTE sc_WBorLeft
    BYTE sc_WBorRight
    BYTE sc_WBorBottom

    BYTE sc_KludgeFill00	; This is strictly for word-alignment

    ; the display data structures for this Screen
    APTR sc_Font			; this screen's default font
    STRUCT sc_ViewPort,vp_SIZEOF	; describing the Screen's display
    STRUCT sc_RastPort,rp_SIZEOF	; describing Screen rendering
    STRUCT sc_BitMap,bm_SIZEOF		; auxiliary graphexcess baggage
    STRUCT sc_LayerInfo,li_SIZEOF	; each screen gets a LayerInfo

    APTR sc_FirstGadget

    BYTE sc_DetailPen		; for bar/border/gadget rendering
    BYTE sc_BlockPen		; for bar/border/gadget rendering

    ; the following variable(s) are maintained by Intuition to support the
    ; DisplayBeep() color flashing technique
    WORD sc_SaveColor0

    ; This layer is for the Screen and Menu bars
    APTR sc_BarLayer		; was "BarLayer"

    APTR sc_ExtData

    APTR sc_UserData		; general-purpose pointer to User data

    LABEL sc_SIZEOF	; actually, you have no business talking about
            ; or relying on the size of a screen structure

; --- FLAGS SET BY INTUITION -------------------------------------------------
; The SCREENTYPE bits are reserved for describing various Screen types
; available under Intuition.
SCREENTYPE	EQU	$000F	; all the screens types available
; --- the definitions for the Screen Type ------------------------------------
WBENCHSCREEN	EQU	$0001	; identifies the Workbench screen
PUBLICSCREEN	EQU	$0002	; public shared (custom) screen
CUSTOMSCREEN	EQU	$000F	; for that special look

SHOWTITLE	EQU	$0010	; this gets set by a call to ShowTitle()

BEEPING	EQU	$0020	; set when Screen is beeping

CUSTOMBITMAP	EQU	$0040	; if you are supplying your own BitMap

SCREENBEHIND	EQU	$0080	; if you want your screen to open behind
                ; already open screens

SCREENQUIET	EQU	$0100	; if you do not want Intuition to render
                ; into your screen (gadgets, title)

SCREENHIRES	EQU	$0200	; do not use lowres gadgets (set by intuition)

STDSCREENHEIGHT	EQU	-1	; supply in NewScreen.Height
STDSCREENWIDTH	EQU	-1	; supply in NewScreen.Width

NS_EXTENDED	EQU	$1000	; means ns_Extenion is valid
AUTOSCROLL	EQU	$4000	; automatic scrolling of large raster

* Screen attribute tag ID's.  These are used in the ti_Tag field of
* TagItem arrays passed to OpenScreenTagList() (or in the
* ExtNewScreen.Extension field).

* Screen attribute tags.  Please use these versions, not those in
* iobsolete.h.

 ENUM TAG_USER+33
*
*   these items specify items equivalent to fields in NewScreen
    EITEM SA_Left	; traditional screen positions	and dimensions
    EITEM SA_Top
    EITEM SA_Width
    EITEM SA_Height
    EITEM SA_Depth	; screen bitmap depth
    EITEM SA_DetailPen	; serves as default for windows, too
    EITEM SA_BlockPen
    EITEM SA_Title	; default screen title

    EITEM SA_Colors	; ti_Data is an array of struct ColorSpec,
            ; terminated by ColorIndex = -1.  Specifies
            ; initial screen palette colors.

    EITEM SA_ErrorCode	; ti_Data points to LONG error code (values below)
    EITEM SA_Font	; equiv. to NewScreen.Font
    EITEM SA_SysFont	; Selects one of the preferences system fonts:
            ;	0 - old DefaultFont, fixed-width
            ;	1 - WB Screen preferred font

    EITEM SA_Type	; equiv. to NewScreen.Type
    EITEM SA_BitMap	; ti_Data is pointer to custom BitMap.  This
            ; implies type of CUSTOMBITMAP

    EITEM SA_PubName	; presence of this tag means that the screen
            ; is to be a public screen.  Please specify
            ; BEFORE the two tags below

    EITEM SA_PubSig
    EITEM SA_PubTask	; Task ID and signal for being notified that
            ; the last window has closed on a public screen.

    EITEM SA_DisplayID	; ti_Data is new extended display ID from
            ; <graphics/displayinfo.h>.

    EITEM SA_DClip	; ti_Data points to a rectangle which defines
            ; screen display clip region

    EITEM SA_Overscan	; was S_STDDCLIP.  Set to one of the OSCAN_
            ; specifiers below to get a system standard
            ; overscan region for your display clip,
            ; screen dimensions (unless otherwise specified),
            ; and automatically centered position (partial
            ; support only so far).

    EITEM SA_Obsolete1	; obsolete S_MONITORNAME

*   booleans *
    EITEM SA_ShowTitle	; boolean equivalent to flag SHOWTITLE
    EITEM SA_Behind	; boolean equivalent to flag SCREENBEHIND
    EITEM SA_Quiet	; boolean equivalent to flag SCREENQUIET
    EITEM SA_AutoScroll	; boolean equivalent to flag AUTOSCROLL
    EITEM SA_Pens	; array as in DrawInfo, terminated by -1
    EITEM SA_FullPalette ; boolean: initialize color table to entire
                ;  preferences palette (32 for V36), rather
             ; than compatible pens 0-3, 17-19, with
             ; remaining palette as returned by GetColorMap()

* OpenScreen error codes, which are returned in the (optional) LONG
* pointed to by ti_Data for the SA_ErrorCode tag item

OSERR_NOMONITOR	EQU	(1)	; named monitor spec not available
OSERR_NOCHIPS	EQU	(2)	; you need newer custom chips
OSERR_NOMEM	EQU	(3)	; couldn't get normal memory
OSERR_NOCHIPMEM	EQU	(4)	; couldn't get chipmem
OSERR_PUBNOTUNIQUE	EQU (5)	; public screen name already used
OSERR_UNKNOWNMODE	EQU (6)	; don't recognize mode asked for

; ========================================================================
; === NewScreen ==========================================================
; ========================================================================
; NOTE: to use Extension field, you need to use ExtNewScreen, below
 STRUCTURE NewScreen,0

    WORD ns_LeftEdge		; initial Screen dimensions
    WORD ns_TopEdge		; initial Screen dimensions
    WORD ns_Width		; initial Screen dimensions
    WORD ns_Height		; initial Screen dimensions
    WORD ns_Depth		; initial Screen dimensions

    BYTE ns_DetailPen		; default rendering pens (for Windows too)
    BYTE ns_BlockPen		; default rendering pens (for Windows too)

    WORD ns_ViewModes		; display "modes" for this Screen

    WORD ns_Type		; Intuition Screen Type specifier

    APTR ns_Font		; default font for Screen and Windows

    APTR ns_DefaultTitle	; Title when Window doesn't care

    APTR ns_Gadgets		; UNUSED:  Leave this NULL

    ; if you are opening a CUSTOMSCREEN and already have a BitMap
    ; that you want used for your Screen, you set the flags CUSTOMBITMAP in
    ; the Types variable and you set this variable to point to your BitMap
    ; structure.  The structure will be copied into your Screen structure,
    ; after which you may discard your own BitMap if you want
    APTR ns_CustomBitMap
 LABEL    ns_SIZEOF

; For compatibility reasons, we need a new structure for extending
; NewScreen.  Use this structure is you need to use the new Extension
; field.
; NOTE WELL: this structure may be extended again in the future.
;Writing code which depends on its size is not allowed.

 STRUCTURE ExtNewScreen,ns_SIZEOF

    APTR ens_Extension		; struct TagItem *
                ; more specification data, scanned if
                ; NS_EXTENDED is set in ns_Type

 LABEL    ens_SIZEOF

* === Overscan Types ===
OSCAN_TEXT	EQU	1	; entirely visible
OSCAN_STANDARD	EQU	2	; just past edges
OSCAN_MAX	EQU	3	; as much as possible
OSCAN_VIDEO	EQU	4	; even more than is possible

* === Public Shared Screen Node ===

* This is the representative of a public shared screen.
* This is an internal data structure, but some functions may
* present a copy of it to the calling application.  In that case,
* be aware that the screen pointer of the structure can NOT be
* used safely, since there is no guarantee that the referenced
* screen will remain open and a valid data structure.

 STRUCTURE PubScreenNode,LN_SIZE
    APTR	psn_Screen	; pointer to screen itself
    UWORD	psn_Flags	; below
    WORD	psn_Size	; includes name buffer size
    WORD	psn_VisitorCount ; how many visitor windows
    APTR	psn_SigTask	; who to signal when visitors gone
    UBYTE	psn_SigBit	; which signal
    UBYTE	psn_Pad1	; word align
 LABEL		psn_SIZEOF

* psn_Flags values
PSNF_PRIVATE	EQU	$0001

* NOTE: Due to a bug in NextPubScreen(), make sure your buffer
* actually has MAXPUBSCREENNAME+1 characters in it!

MAXPUBSCREENNAME EQU	139	; names no longer, please

; pub screen modes
SHANGHAI	EQU	$0001	; put workbench windows on pub screen
POPPUBSCREEN	EQU	$0002	; pop pub screen to front when visitor opens

* Include obsolete identifiers:
    IFND	INTUITION_IOBSOLETE_I
    INCLUDE "intuition/iobsolete.i"
    ENDC

    ENDC


Includes/intuition/classusr.h

#ifndef	INTUITION_CLASSUSR_H
#define INTUITION_CLASSUSR_H	1
/*
**  $Filename: intuition/classusr.h $
**  $Release: 2.04 Includes, V37.4 $
**  $Revision: 36.2 $
**  $Date: 91/11/08 $
**
**  For application users of Intuition object classes
**
**  (C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef UTILITY_HOOKS_H
#include <utility/hooks.h>
#endif

/*** User visible handles on objects, classes, messages ***/
typedef ULONG	Object;		/* abstract handle */

typedef	UBYTE	*ClassID;

/* you can use this type to point to a "generic" message,
 * in the object-oriented programming parlance.  Based on
 * the value of 'MethodID', you dispatch to processing
 * for the various message types.  The meaningful parameter
 * packet structure definitions are defined below.
 */
typedef struct {
    ULONG MethodID;
    /* method-specific data follows, some examples below */
}		*Msg;

/*
 * Class id strings for Intuition classes.
 * There's no real reason to use the uppercase constants
 * over the lowercase strings, but this makes a good place
 * to list the names of the built-in classes.
 */
#define ROOTCLASS	"rootclass"		/* classusr.h	*/
#define IMAGECLASS	"imageclass"		/* imageclass.h	*/
#define FRAMEICLASS	"frameiclass"
#define SYSICLASS	"sysiclass"
#define FILLRECTCLASS	"fillrectclass"
#define GADGETCLASS	"gadgetclass"		/* gadgetclass.h */
#define PROPGCLASS	"propgclass"
#define STRGCLASS	"strgclass"
#define BUTTONGCLASS	"buttongclass"
#define FRBUTTONCLASS	"frbuttonclass"
#define GROUPGCLASS	"groupgclass"
#define ICCLASS		"icclass"		/* icclass.h	*/
#define MODELCLASS	"modelclass"

/* Dispatched method ID's
 * NOTE: Applications should use Intuition entry points, not direct
 * DoMethod() calls, for NewObject, DisposeObject, SetAttrs,
 * SetGadgetAttrs, and GetAttr.
 */

#define OM_Dummy	(0x100)
#define OM_NEW		(0x101)	/* 'object' parameter is "true class"	*/
#define OM_DISPOSE	(0x102)	/* delete self (no parameters)		*/
#define OM_SET		(0x103)	/* set attributes (in tag list)		*/
#define OM_GET		(0x104)	/* return single attribute value	*/
#define OM_ADDTAIL	(0x105)	/* add self to a List (let root do it)	*/
#define OM_REMOVE	(0x106)	/* remove self from list		*/
#define OM_NOTIFY	(0x107)	/* send to self: notify dependents	*/
#define OM_UPDATE	(0x108)	/* notification message from somebody	*/
#define OM_ADDMEMBER	(0x109)	/* used by various classes with lists	*/
#define OM_REMMEMBER	(0x10A)	/* used by various classes with lists	*/

/* Parameter "Messages" passed to methods	*/

/* OM_NEW and OM_SET	*/
struct opSet {
    ULONG		MethodID;
    struct TagItem	*ops_AttrList;	/* new attributes	*/
    struct GadgetInfo	*ops_GInfo;	/* always there for gadgets,
                     * when SetGadgetAttrs() is used,
                     * but will be NULL for OM_NEW
                     */
};

/* OM_NOTIFY, and OM_UPDATE	*/
struct opUpdate {
    ULONG		MethodID;
    struct TagItem	*opu_AttrList;	/* new attributes	*/
    struct GadgetInfo	*opu_GInfo;	/* non-NULL when SetGadgetAttrs or
                     * notification resulting from gadget
                     * input occurs.
                     */
    ULONG		opu_Flags;	/* defined below	*/
};

/* this flag means that the update message is being issued from
 * something like an active gadget, a la GACT_FOLLOWMOUSE.  When
 * the gadget goes inactive, it will issue a final update
 * message with this bit cleared.  Examples of use are for
 * GACT_FOLLOWMOUSE equivalents for propgadclass, and repeat strobes
 * for buttons.
 */
#define OPUF_INTERIM	(1<<0)

/* OM_GET	*/
struct opGet {
    ULONG		MethodID;
    ULONG		opg_AttrID;
    ULONG		*opg_Storage;	/* may be other types, but "int"
                     * types are all ULONG
                     */
};

/* OM_ADDTAIL	*/
struct opAddTail {
    ULONG		MethodID;
    struct List		*opat_List;
};

/* OM_ADDMEMBER, OM_REMMEMBER	*/
#define  opAddMember opMember
struct opMember {
    ULONG		MethodID;
    Object		*opam_Object;
};

#endif


Includes/intuition/imageclass.h

#ifndef INTUITION_IMAGECLASS_H
#define INTUITION_IMAGECLASS_H TRUE
/*
**  $Filename: intuition/imageclass.h $
**  $Release: 2.04 Includes, V37.4 $
**  $Revision: 36.3 $
**  $Date: 91/11/08 $
**
**  Definitions for the image classes
**
**  (C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

/*
 * NOTE:  <intuition/iobsolete.h> is included at the END of this file!
 */

#define CUSTOMIMAGEDEPTH	(-1)
/* if image.Depth is this, it's a new Image class object */

/* some convenient macros and casts */
#define GADGET_BOX( g )	( (struct IBox *) &((struct Gadget *)(g))->LeftEdge )
#define IM_BOX( im )	( (struct IBox *) &((struct Image *)(im))->LeftEdge )
#define IM_FGPEN( im )	( (im)->PlanePick )
#define IM_BGPEN( im )	( (im)->PlaneOnOff )

/******************************************************/
#define IA_Dummy		(TAG_USER + 0x20000)
#define IA_Left			(IA_Dummy + 0x01)
#define IA_Top			(IA_Dummy + 0x02)
#define IA_Width		(IA_Dummy + 0x03)
#define IA_Height		(IA_Dummy + 0x04)
#define IA_FGPen		(IA_Dummy + 0x05)
            /* IA_FGPen also means "PlanePick"	*/
#define IA_BGPen		(IA_Dummy + 0x06)
            /* IA_BGPen also means "PlaneOnOff"	*/
#define IA_Data			(IA_Dummy + 0x07)
            /* bitplanes, for classic image,
             * other image classes may use it for other things
             */
#define IA_LineWidth		(IA_Dummy + 0x08)
#define IA_Pens			(IA_Dummy + 0x0E)
            /* pointer to UWORD pens[],
             * ala DrawInfo.Pens, MUST be
             * terminated by ~0.  Some classes can
             * choose to have this, or SYSIA_DrawInfo,
             * or both.
             */
#define IA_Resolution		(IA_Dummy + 0x0F)
            /* packed uwords for x/y resolution into a longword
             * ala DrawInfo.Resolution
             */

/**** see class documentation to learn which	*****/
/**** classes recognize these			*****/
#define IA_APattern		(IA_Dummy + 0x10)
#define IA_APatSize		(IA_Dummy + 0x11)
#define IA_Mode			(IA_Dummy + 0x12)
#define IA_Font			(IA_Dummy + 0x13)
#define IA_Outline		(IA_Dummy + 0x14)
#define IA_Recessed		(IA_Dummy + 0x15)
#define IA_DoubleEmboss		(IA_Dummy + 0x16)
#define IA_EdgesOnly		(IA_Dummy + 0x17)

/**** "sysiclass" attributes			*****/
#define SYSIA_Size		(IA_Dummy + 0x0B)
            /* #define's below		*/
#define SYSIA_Depth		(IA_Dummy + 0x0C)
            /* this is unused by Intuition.  SYSIA_DrawInfo
             * is used instead for V36
             */
#define SYSIA_Which		(IA_Dummy + 0x0D)
            /* see #define's below	*/
#define SYSIA_DrawInfo		(IA_Dummy + 0x18)
            /* pass to sysiclass, please */

/*****	obsolete: don't use these, use IA_Pens	*****/
#define SYSIA_Pens		IA_Pens
#define IA_ShadowPen		(IA_Dummy + 0x09)
#define IA_HighlightPen		(IA_Dummy + 0x0A)

/** next attribute: (IA_Dummy + 0x19)	**/
/*************************************************/

/* data values for SYSIA_Size	*/
#define SYSISIZE_MEDRES	(0)
#define SYSISIZE_LOWRES	(1)
#define SYSISIZE_HIRES	(2)

/*
 * SYSIA_Which tag data values:
 * Specifies which system gadget you want an image for.
 * Some numbers correspond to internal Intuition #defines
 */
#define DEPTHIMAGE	(0x00L)
#define ZOOMIMAGE	(0x01L)
#define SIZEIMAGE	(0x02L)
#define CLOSEIMAGE	(0x03L)
#define SDEPTHIMAGE	(0x05L)	/* screen depth gadget */
#define LEFTIMAGE	(0x0AL)
#define UPIMAGE		(0x0BL)
#define RIGHTIMAGE	(0x0CL)
#define DOWNIMAGE	(0x0DL)
#define CHECKIMAGE	(0x0EL)
#define MXIMAGE		(0x0FL)	/* mutual exclude "button" */

/* image message id's	*/
#define    IM_DRAW	0x202L	/* draw yourself, with "state"		*/
#define    IM_HITTEST	0x203L	/* return TRUE if click hits image	*/
#define    IM_ERASE	0x204L	/* erase yourself			*/
#define    IM_MOVE	0x205L	/* draw new and erase old, smoothly	*/

#define    IM_DRAWFRAME	0x206L	/* draw with specified dimensions	*/
#define    IM_FRAMEBOX	0x207L	/* get recommended frame around some box*/
#define    IM_HITFRAME	0x208L	/* hittest with dimensions		*/
#define    IM_ERASEFRAME 0x209L	/* hittest with dimensions		*/

/* image draw states or styles, for IM_DRAW */
#define    IDS_NORMAL		(0L)
#define    IDS_SELECTED		(1L)	/* for selected gadgets	    */
#define    IDS_DISABLED		(2L)	/* for disabled gadgets	    */
#define    IDS_BUSY		(3L)	/* for future functionality */
#define    IDS_INDETERMINATE	(4L)	/* for future functionality */
#define    IDS_INACTIVENORMAL	(5L)	/* normal, in inactive window border */
#define    IDS_INACTIVESELECTED	(6L)	/* selected, in inactive border */
#define    IDS_INACTIVEDISABLED	(7L)	/* disabled, in inactive border */

/* oops, please forgive spelling error by jimm */
#define IDS_INDETERMINANT IDS_INDETERMINATE

/* IM_FRAMEBOX	*/
struct impFrameBox {
    ULONG		MethodID;
    struct IBox	*imp_ContentsBox;	/* input: relative box of contents */
    struct IBox	*imp_FrameBox;		/* output: rel. box of encl frame  */
    struct DrawInfo	*imp_DrInfo;	/* NB: May be NULL */
    ULONG	imp_FrameFlags;
};

#define FRAMEF_SPECIFY	(1<<0)	/* Make do with the dimensions of FrameBox
                 * provided.
                 */

/* IM_DRAW, IM_DRAWFRAME	*/
struct impDraw {
    ULONG		MethodID;
    struct RastPort	*imp_RPort;
    struct {
    WORD	X;
    WORD	Y;
    }			imp_Offset;

    ULONG		imp_State;
    struct DrawInfo	*imp_DrInfo;	/* NB: May be NULL */

    /* these parameters only valid for IM_DRAWFRAME */
    struct {
    WORD	Width;
    WORD	Height;
    }			imp_Dimensions;
};

/* IM_ERASE, IM_ERASEFRAME	*/
/* NOTE: This is a subset of impDraw	*/
struct impErase {
    ULONG		MethodID;
    struct RastPort	*imp_RPort;
    struct {
    WORD	X;
    WORD	Y;
    }			imp_Offset;

    /* these parameters only valid for IM_ERASEFRAME */
    struct {
    WORD	Width;
    WORD	Height;
    }			imp_Dimensions;
};

/* IM_HITTEST, IM_HITFRAME	*/
struct impHitTest {
    ULONG		MethodID;
    struct {
    WORD	X;
    WORD	Y;
    }			imp_Point;

    /* these parameters only valid for IM_HITFRAME */
    struct {
    WORD	Width;
    WORD	Height;
    }			imp_Dimensions;
};

/* Include obsolete identifiers: */
#ifndef INTUITION_IOBSOLETE_H
#include <intuition/iobsolete.h>
#endif

#endif


Includes/intuition/iobsolete.h

#ifndef INTUITION_IOBSOLETE_H
#define INTUITION_IOBSOLETE_H

/*
**  $Filename: intuition/iobsolete.h $
**  $Release: 2.04 Includes, V37.4 $
**  $Revision: 36.2 $
**  $Date: 90/11/02 $
**
**  Obsolete identifiers for Intuition.  Use the new ones instead!
**
**  (C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

/* This file contains:
 *
 * 1.  The traditional identifiers for gadget Flags, Activation, and Type,
 * and for window Flags and IDCMP classes.  They are defined in terms
 * of their new versions, which serve to prevent confusion between
 * similar-sounding but different identifiers (like IDCMP_WINDOWACTIVE
 * and WFLG_ACTIVATE).
 *
 * 2.  Some tag names and constants whose labels were adjusted after V36.
 *
 * 3.  Some tag names that were used only during the V36-beta cycle.
 *
 * By default, 1 and 2 are enabled, while 3 are excluded.
 *
 * #define INTUI_V36_NAMES_ONLY to exclude the traditional identifiers and
 * the original V36 names of some identifiers.
 *
 * #define INTUI_V36_BETA_NAMES to include the beta tag-names.
 */

#ifndef INTUITION_INTUITION_H
#include <intuition/intuition.h>
#endif

/* #define INTUI_V36_NAMES_ONLY to remove these older names */

#ifndef INTUI_V36_NAMES_ONLY

/* V34-style Gadget->Flags names: */

#define GADGHIGHBITS	GFLG_GADGHIGHBITS
#define GADGHCOMP	GFLG_GADGHCOMP
#define GADGHBOX	GFLG_GADGHBOX
#define GADGHIMAGE	GFLG_GADGHIMAGE
#define GADGHNONE	GFLG_GADGHNONE
#define GADGIMAGE	GFLG_GADGIMAGE
#define GRELBOTTOM	GFLG_RELBOTTOM
#define GRELRIGHT	GFLG_RELRIGHT
#define GRELWIDTH	GFLG_RELWIDTH
#define GRELHEIGHT	GFLG_RELHEIGHT
#define SELECTED	GFLG_SELECTED
#define GADGDISABLED	GFLG_DISABLED
#define LABELMASK	GFLG_LABELMASK
#define LABELITEXT	GFLG_LABELITEXT
#define	LABELSTRING	GFLG_LABELSTRING
#define LABELIMAGE	GFLG_LABELIMAGE

/* V34-style Gadget->Activation flag names: */

#define RELVERIFY	GACT_RELVERIFY
#define GADGIMMEDIATE	GACT_IMMEDIATE
#define ENDGADGET	GACT_ENDGADGET
#define FOLLOWMOUSE	GACT_FOLLOWMOUSE
#define RIGHTBORDER	GACT_RIGHTBORDER
#define LEFTBORDER	GACT_LEFTBORDER
#define TOPBORDER	GACT_TOPBORDER
#define BOTTOMBORDER	GACT_BOTTOMBORDER
#define BORDERSNIFF	GACT_BORDERSNIFF
#define TOGGLESELECT	GACT_TOGGLESELECT
#define BOOLEXTEND	GACT_BOOLEXTEND
#define STRINGLEFT	GACT_STRINGLEFT
#define STRINGCENTER	GACT_STRINGCENTER
#define STRINGRIGHT	GACT_STRINGRIGHT
#define LONGINT		GACT_LONGINT
#define ALTKEYMAP	GACT_ALTKEYMAP
#define STRINGEXTEND	GACT_STRINGEXTEND
#define ACTIVEGADGET	GACT_ACTIVEGADGET

/* V34-style Gadget->Type names: */

#define GADGETTYPE	GTYP_GADGETTYPE
#define SYSGADGET	GTYP_SYSGADGET
#define SCRGADGET	GTYP_SCRGADGET
#define GZZGADGET	GTYP_GZZGADGET
#define REQGADGET	GTYP_REQGADGET
#define SIZING		GTYP_SIZING
#define WDRAGGING	GTYP_WDRAGGING
#define SDRAGGING	GTYP_SDRAGGING
#define WUPFRONT	GTYP_WUPFRONT
#define SUPFRONT	GTYP_SUPFRONT
#define WDOWNBACK	GTYP_WDOWNBACK
#define SDOWNBACK	GTYP_SDOWNBACK
#define CLOSE		GTYP_CLOSE
#define BOOLGADGET	GTYP_BOOLGADGET
#define GADGET0002	GTYP_GADGET0002
#define PROPGADGET	GTYP_PROPGADGET
#define STRGADGET	GTYP_STRGADGET
#define CUSTOMGADGET	GTYP_CUSTOMGADGET
#define GTYPEMASK	GTYP_GTYPEMASK

/* V34-style IDCMP class names: */

#define SIZEVERIFY	IDCMP_SIZEVERIFY
#define NEWSIZE		IDCMP_NEWSIZE
#define REFRESHWINDOW	IDCMP_REFRESHWINDOW
#define MOUSEBUTTONS	IDCMP_MOUSEBUTTONS
#define MOUSEMOVE	IDCMP_MOUSEMOVE
#define GADGETDOWN	IDCMP_GADGETDOWN
#define GADGETUP	IDCMP_GADGETUP
#define REQSET		IDCMP_REQSET
#define MENUPICK	IDCMP_MENUPICK
#define CLOSEWINDOW	IDCMP_CLOSEWINDOW
#define RAWKEY		IDCMP_RAWKEY
#define REQVERIFY	IDCMP_REQVERIFY
#define REQCLEAR	IDCMP_REQCLEAR
#define MENUVERIFY	IDCMP_MENUVERIFY
#define NEWPREFS	IDCMP_NEWPREFS
#define DISKINSERTED	IDCMP_DISKINSERTED
#define DISKREMOVED	IDCMP_DISKREMOVED
#define WBENCHMESSAGE	IDCMP_WBENCHMESSAGE
#define ACTIVEWINDOW	IDCMP_ACTIVEWINDOW
#define INACTIVEWINDOW	IDCMP_INACTIVEWINDOW
#define DELTAMOVE	IDCMP_DELTAMOVE
#define VANILLAKEY	IDCMP_VANILLAKEY
#define INTUITICKS	IDCMP_INTUITICKS
#define IDCMPUPDATE	IDCMP_IDCMPUPDATE
#define MENUHELP	IDCMP_MENUHELP
#define CHANGEWINDOW	IDCMP_CHANGEWINDOW
#define LONELYMESSAGE	IDCMP_LONELYMESSAGE

/* V34-style Window->Flags names: */

#define WINDOWSIZING	WFLG_SIZEGADGET
#define WINDOWDRAG	WFLG_DRAGBAR
#define WINDOWDEPTH	WFLG_DEPTHGADGET
#define WINDOWCLOSE	WFLG_CLOSEGADGET
#define SIZEBRIGHT	WFLG_SIZEBRIGHT
#define SIZEBBOTTOM	WFLG_SIZEBBOTTOM
#define REFRESHBITS	WFLG_REFRESHBITS
#define SMART_REFRESH	WFLG_SMART_REFRESH
#define SIMPLE_REFRESH	WFLG_SIMPLE_REFRESH
#define SUPER_BITMAP	WFLG_SUPER_BITMAP
#define OTHER_REFRESH	WFLG_OTHER_REFRESH
#define BACKDROP	WFLG_BACKDROP
#define REPORTMOUSE	WFLG_REPORTMOUSE
#define GIMMEZEROZERO	WFLG_GIMMEZEROZERO
#define BORDERLESS	WFLG_BORDERLESS
#define ACTIVATE	WFLG_ACTIVATE
#define WINDOWACTIVE	WFLG_WINDOWACTIVE
#define INREQUEST	WFLG_INREQUEST
#define MENUSTATE	WFLG_MENUSTATE
#define RMBTRAP		WFLG_RMBTRAP
#define NOCAREREFRESH	WFLG_NOCAREREFRESH
#define WINDOWREFRESH	WFLG_WINDOWREFRESH
#define WBENCHWINDOW	WFLG_WBENCHWINDOW
#define WINDOWTICKED	WFLG_WINDOWTICKED
#define NW_EXTENDED	WFLG_NW_EXTENDED
#define VISITOR		WFLG_VISITOR
#define ZOOMED		WFLG_ZOOMED
#define HASZOOM		WFLG_HASZOOM

/* These are the obsolete tag names for general gadgets, proportional gadgets,
 * and string gadgets.	Use the mixed-case equivalents from gadgetclass.h
 * instead.
 */

#define GA_LEFT			GA_Left
#define GA_RELRIGHT		GA_RelRight
#define GA_TOP			GA_Top
#define GA_RELBOTTOM		GA_RelBottom
#define GA_WIDTH		GA_Width
#define GA_RELWIDTH		GA_RelWidth
#define GA_HEIGHT		GA_Height
#define GA_RELHEIGHT		GA_RelHeight
#define GA_TEXT			GA_Text
#define GA_IMAGE		GA_Image
#define GA_BORDER		GA_Border
#define GA_SELECTRENDER		GA_SelectRender
#define GA_HIGHLIGHT		GA_Highlight
#define GA_DISABLED		GA_Disabled
#define GA_GZZGADGET		GA_GZZGadget
#define GA_USERDATA		GA_UserData
#define GA_SPECIALINFO		GA_SpecialInfo
#define GA_SELECTED		GA_Selected
#define GA_ENDGADGET		GA_EndGadget
#define GA_IMMEDIATE		GA_Immediate
#define GA_RELVERIFY		GA_RelVerify
#define GA_FOLLOWMOUSE		GA_FollowMouse
#define GA_RIGHTBORDER		GA_RightBorder
#define GA_LEFTBORDER		GA_LeftBorder
#define GA_TOPBORDER		GA_TopBorder
#define GA_BOTTOMBORDER		GA_BottomBorder
#define GA_TOGGLESELECT		GA_ToggleSelect
#define GA_SYSGADGET		GA_SysGadget
#define GA_SYSGTYPE		GA_SysGType
#define GA_PREVIOUS		GA_Previous
#define GA_NEXT			GA_Next
#define GA_DRAWINFO		GA_DrawInfo
#define GA_INTUITEXT		GA_IntuiText
#define GA_LABELIMAGE		GA_LabelImage

#define PGA_FREEDOM		PGA_Freedom
#define PGA_BORDERLESS		PGA_Borderless
#define PGA_HORIZPOT		PGA_HorizPot
#define PGA_HORIZBODY		PGA_HorizBody
#define PGA_VERTPOT		PGA_VertPot
#define PGA_VERTBODY		PGA_VertBody
#define PGA_TOTAL		PGA_Total
#define PGA_VISIBLE		PGA_Visible
#define PGA_TOP			PGA_Top

#define LAYOUTA_LAYOUTOBJ	LAYOUTA_LayoutObj
#define LAYOUTA_SPACING		LAYOUTA_Spacing
#define LAYOUTA_ORIENTATION	LAYOUTA_Orientation

/* These are the obsolete tag names for image attributes.
 * Use the mixed-case equivalents from imageclass.h instead.
 */

#define IMAGE_ATTRIBUTES	(IA_Dummy)
#define IA_LEFT			IA_Left
#define IA_TOP			IA_Top
#define IA_WIDTH		IA_Width
#define IA_HEIGHT		IA_Height
#define IA_FGPEN		IA_FGPen
#define IA_BGPEN		IA_BGPen
#define IA_DATA			IA_Data
#define IA_LINEWIDTH		IA_LineWidth
#define IA_PENS			IA_Pens
#define IA_RESOLUTION		IA_Resolution
#define IA_APATTERN		IA_APattern
#define IA_APATSIZE		IA_APatSize
#define IA_MODE			IA_Mode
#define IA_FONT			IA_Font
#define IA_OUTLINE		IA_Outline
#define IA_RECESSED		IA_Recessed
#define IA_DOUBLEEMBOSS		IA_DoubleEmboss
#define IA_EDGESONLY		IA_EdgesOnly
#define IA_SHADOWPEN		IA_ShadowPen
#define IA_HIGHLIGHTPEN		IA_HighlightPen

/* These are the obsolete identifiers for the various DrawInfo pens.
 * Use the uppercase versions in screens.h instead.
 */

#define detailPen	DETAILPEN
#define blockPen	BLOCKPEN
#define textPen		TEXTPEN
#define shinePen	SHINEPEN
#define shadowPen	SHADOWPEN
#define hifillPen	FILLPEN
#define hifilltextPen	FILLTEXTPEN
#define backgroundPen	BACKGROUNDPEN
#define hilighttextPen	HIGHLIGHTTEXTPEN
#define numDrIPens	NUMDRIPENS

#endif /* !INTUI_V36_NAMES_ONLY */

/* #define INTUI_V36_BETA_NAMES to enable these tag names that were used
 * during the V36 beta period only.  New code should use the official
 * tags instead.
 */

#ifdef INTUI_V36_BETA_NAMES

/* These are the obsolete tag-names for the OpenWindowTags().
 * Use the WA_... equivalents from intuition.h instead.
 */

#define W_Dummy			WA_Dummy
#define W_LEFT			WA_Left
#define W_TOP			WA_Top
#define W_WIDTH			WA_Width
#define W_HEIGHT		WA_Height
#define W_DETAILPEN		WA_DetailPen
#define W_BLOCKPEN		WA_BlockPen
#define W_IDCMP			WA_IDCMP
#define W_FLAGS			WA_Flags
#define W_GADGETS		WA_Gadgets
#define W_CHECKMARK		WA_Checkmark
#define W_TITLE			WA_Title
#define W_SCREENTITLE		WA_ScreenTitle
#define W_CUSTOMSCREEN		WA_CustomScreen
#define W_SUPERBITMAP		WA_SuperBitMap
#define W_MINWIDTH		WA_MinWidth
#define W_MINHEIGHT		WA_MinHeight
#define W_MAXWIDTH		WA_MaxWidth
#define W_MAXHEIGHT		WA_MaxHeight
#define W_INNERWIDTH		WA_InnerWidth
#define W_INNERHEIGHT		WA_InnerHeight
#define W_PUBSCNAME		WA_PubScreenName
#define W_PUBSC			WA_PubScreen
#define W_PUBSCFALLBACK		WA_PubScreenFallBack
#define W_WINDOWNAME		WA_WindowName
#define W_COLORS		WA_Colors
#define W_ZOOM			WA_Zoom
#define W_MOUSEQUEUE		WA_MouseQueue
#define W_BACKFILL		WA_BackFill
#define W_RPTQUEUE		WA_RptQueue
#define W_SIZEGADGET		WA_SizeGadget
#define W_DRAGBAR		WA_DragBar
#define W_DEPTHGADGET		WA_DepthGadget
#define W_CLOSEGADGET		WA_CloseGadget
#define W_BACKDROP		WA_Backdrop
#define W_REPORTMOUSE		WA_ReportMouse
#define W_NOCAREREFRESH		WA_NoCareRefresh
#define W_BORDERLESS		WA_Borderless
#define W_ACTIVATE		WA_Activate
#define W_RMBTRAP		WA_RMBTrap
#define W_WBENCHWINDOW		WA_WBenchWindow
#define W_SIMPLE_REFRESH	WA_SimpleRefresh
#define W_SMART_REFRESH		WA_SmartRefresh
#define W_SIZEBRIGHT		WA_SizeBRight
#define W_SIZEBBOTTOM		WA_SizeBBottom
#define W_AUTOADJUST		WA_AutoAdjust
#define W_GIMMEZEROZERO		WA_GimmeZeroZero

/* These are the obsolete tag-names for the OpenScreenTags().
 * Use the SA_... equivalents from screens.h instead.
 */

#define S_DUMMY		SA_Dummy
#define S_LEFT		SA_Left
#define S_TOP		SA_Top
#define S_WIDTH		SA_Width
#define S_HEIGHT	SA_Height
#define S_DEPTH		SA_Depth
#define S_DETAILPEN	SA_DetailPen
#define S_BLOCKPEN	SA_BlockPen
#define S_TITLE		SA_Title
#define S_COLORS	SA_Colors
#define S_ERRORCODE	SA_ErrorCode
#define S_FONT		SA_Font
#define S_SYSFONT	SA_SysFont
#define S_TYPE		SA_Type
#define S_BITMAP	SA_BitMap
#define S_PUBNAME	SA_PubName
#define S_PUBSIG	SA_PubSig
#define S_PUBTASK	SA_PubTask
#define S_DISPLAYID	SA_DisplayID
#define S_DCLIP		SA_DClip
#define S_STDDCLIP	SA_Overscan
#define S_MONITORNAME	SA_Obsolete1
#define S_SHOWTITLE	SA_ShowTitle
#define S_BEHIND	SA_Behind
#define S_QUIET		SA_Quiet
#define S_AUTOSCROLL	SA_AutoScroll

#endif /* INTUI_V36_BETA_NAMES */

#endif /* INTUITION_IOBSOLETE_H */


Includes/intuition/sghooks.h

#ifndef INTUITION_SGHOOKS_H
#define INTUITION_SGHOOKS_H TRUE
/*
**  $Filename: intuition/sghooks.h $
**  $Release: 2.04 Includes, V37.4 $
**  $Revision: 36.5 $
**  $Date: 91/11/08 $
**
**  string gadget extensions and hooks
**
**  (C) Copyright 1988-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

struct StringExtend {
    /* display specifications	*/
    struct TextFont *Font;	/* must be an open Font (not TextAttr)	*/
    UBYTE	Pens[2];	/* color of text/backgroun		*/
    UBYTE	ActivePens[2];	/* colors when gadget is active		*/

    /* edit specifications	*/
    ULONG	InitialModes;	/* initial mode flags, below		*/
    struct Hook *EditHook;	/* if non-NULL, must supply WorkBuffer	*/
    UBYTE	*WorkBuffer;	/* must be as large as StringInfo.Buffer*/

    ULONG	Reserved[4];	/* set to 0				*/
};

struct SGWork	{
    /* set up when gadget is first activated	*/
    struct Gadget	*Gadget;	/* the contestant itself	*/
    struct StringInfo	*StringInfo;	/* easy access to sinfo		*/
    UBYTE		*WorkBuffer;	/* intuition's planned result	*/
    UBYTE		*PrevBuffer;	/* what was there before	*/
    ULONG		Modes;		/* current mode			*/

    /* modified for each input event	*/
    struct InputEvent	*IEvent;	/* actual event: do not change	*/
    UWORD		Code;		/* character code, if one byte	*/
    WORD		BufferPos;	/* cursor position		*/
    WORD		NumChars;
    ULONG		Actions;	/* what Intuition will do	*/
    LONG		LongInt;	/* temp storage for longint	*/

    struct GadgetInfo	*GadgetInfo;	/* see cghooks.h		*/
    UWORD		EditOp;		/* from constants below		*/
};

/* SGWork.EditOp -
 * These values indicate what basic type of operation the global
 * editing hook has performed on the string before your gadget's custom
 * editing hook gets called.  You do not have to be concerned with the
 * value your custom hook leaves in the EditOp field, only if you
 * write a global editing hook.
 *
 * For most of these general edit operations, you'll want to compare
 * the BufferPos and NumChars of the StringInfo (before global editing)
 * and SGWork (after global editing).
 */

#define EO_NOOP		(0x0001)
    /* did nothing							*/
#define EO_DELBACKWARD	(0x0002)
    /* deleted some chars (maybe 0).				*/
#define EO_DELFORWARD	(0x0003)
    /* deleted some characters under and in front of the cursor	*/
#define EO_MOVECURSOR	(0x0004)
    /* moved the cursor						*/
#define EO_ENTER	(0x0005)
    /* "enter" or "return" key, terminate				*/
#define EO_RESET	(0x0006)
    /* current Intuition-style undo					*/
#define EO_REPLACECHAR	(0x0007)
    /* replaced one character and (maybe) advanced cursor		*/
#define EO_INSERTCHAR	(0x0008)
    /* inserted one char into string or added one at end		*/
#define EO_BADFORMAT	(0x0009)
    /* didn't like the text data, e.g., Bad LONGINT			*/
#define EO_BIGCHANGE	(0x000A)	/* unused by Intuition	*/
    /* complete or major change to the text, e.g. new string	*/
#define EO_UNDO		(0x000B)	/* unused by Intuition	*/
    /* some other style of undo					*/
#define EO_CLEAR	(0x000C)
    /* clear the string						*/
#define EO_SPECIAL	(0x000D)	/* unused by Intuition	*/
    /* some operation that doesn't fit into the categories here	*/

/* Mode Flags definitions (ONLY first group allowed as InitialModes)	*/
#define SGM_REPLACE	(1L << 0)	/* replace mode			*/
/* please initialize StringInfo with in-range value of BufferPos
 * if you are using SGM_REPLACE mode.
 */

#define SGM_FIXEDFIELD	(1L << 1)	/* fixed length buffer		*/
                    /* always set SGM_REPLACE, too	*/
#define SGM_NOFILTER	(1L << 2)	/* don't filter control chars	*/

/* SGM_EXITHELP is new for V37, and ignored by V36: */
#define SGM_EXITHELP	(1L << 7)	/* exit with code = 0x5F if HELP hit */

/* These Mode Flags are for internal use only				*/
#define SGM_NOCHANGE	(1L << 3)	/* no edit changes yet		*/
#define SGM_NOWORKB	(1L << 4)	/* Buffer == PrevBuffer		*/
#define SGM_CONTROL	(1L << 5)	/* control char escape mode	*/
#define SGM_LONGINT	(1L << 6)	/* an intuition longint gadget	*/

/* String Gadget Action Flags (put in SGWork.Actions by EditHook)	*/
#define SGA_USE		(0x1L)	/* use contents of SGWork		*/
#define SGA_END		(0x2L)	/* terminate gadget, code in Code field	*/
#define SGA_BEEP	(0x4L)	/* flash the screen for the user	*/
#define SGA_REUSE	(0x8L)	/* reuse input event			*/
#define SGA_REDISPLAY	(0x10L)	/* gadget visuals changed		*/

/* New for V37: */
#define SGA_NEXTACTIVE	(0x20L)	/* Make next possible gadget active.	*/
#define SGA_PREVACTIVE	(0x40L)	/* Make previous possible gadget active.*/

/* function id for only existing custom string gadget edit hook	*/

#define SGH_KEY		(1L)	/* process editing keystroke		*/
#define SGH_CLICK	(2L)	/* process mouse click cursor position	*/

/* Here's a brief summary of how the custom string gadget edit hook works:
 *	You provide a hook in StringInfo.Extension.EditHook.
 *	The hook is called in the standard way with the 'object'
 *	a pointer to SGWork, and the 'message' a pointer to a command
 *	block, starting either with (longword) SGH_KEY, SGH_CLICK,
 *	or something new.
 *
 *	You return 0 if you don't understand the command (SGH_KEY is
 *	required and assumed).	Return non-zero if you implement the
 *	command.
 *
 *   SGH_KEY:
 *	There are no parameters following the command longword.
 *
 *	Intuition will put its idea of proper values in the SGWork
 *	before calling you, and if you leave SGA_USE set in the
 *	SGWork.Actions field, Intuition will use the values
 *	found in SGWork fields WorkBuffer, NumChars, BufferPos,
 *	and LongInt, copying the WorkBuffer back to the StringInfo
 *	Buffer.
 *
 *	NOTE WELL: You may NOT change other SGWork fields.
 *
 *	If you clear SGA_USE, the string gadget will be unchanged.
 *
 *	If you set SGA_END, Intuition will terminate the activation
 *	of the string gadget.  If you also set SGA_REUSE, Intuition
 *	will reuse the input event after it deactivates your gadget.
 *
 *	In this case, Intuition will put the value found in SGWork.Code
 *	into the IntuiMessage.Code field of the IDCMP_GADGETUP message it
 *	sends to the application.
 *
 *	If you set SGA_BEEP, Intuition will call DisplayBeep(); use
 *	this if the user has typed in error, or buffer is full.
 *
 *	Set SGA_REDISPLAY if the changes to the gadget warrant a
 *	gadget redisplay.  Note: cursor movement requires a redisplay.
 *
 *	Starting in V37, you may set SGA_PREVACTIVE or SGA_NEXTACTIVE
 *	when you set SGA_END.  This tells Intuition that you want
 *	the next or previous gadget with GFLG_TABCYCLE to be activated.
 *
 *   SGH_CLICK:
 *	This hook command is called when Intuition wants to position
 *	the cursor in response to a mouse click in the string gadget.
 *
 *	Again, here are no parameters following the command longword.
 *
 *	This time, Intuition has already calculated the mouse position
 *	character cell and put it in SGWork.BufferPos.	The previous
 *	BufferPos value remains in the SGWork.StringInfo.BufferPos.
 *
 *	Intuition will again use the SGWork fields listed above for
 *	SGH_KEY.  One restriction is that you are NOT allowed to set
 *	SGA_END or SGA_REUSE for this command.	Intuition will not
 *	stand for a gadget which goes inactive when you click in it.
 *
 *	You should always leave the SGA_REDISPLAY flag set, since Intuition
 *	uses this processing when activating a string gadget.
 */

#endif


Includes/intuition/classusr.i

    IFND INTUITION_CLASSUSR_I
INTUITION_CLASSUSR_I SET 1
**
** $Filename: intuition/classusr.i $
** $Release: 2.04 Includes, V37.4 $
** $Revision: 36.4 $
** $Date: 91/11/08 $
**
** For application users of Intuition object classes
**
**  (C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND UTILITY_HOOKS_I
    INCLUDE "utility/hooks.i"
    ENDC

* beginning of "method message" passed to class dispatchers
 STRUCTURE Msg,0
    ULONG msg_MethodID
    ; method-specific data follows, some examples below

* For now, see the class id's for Intuition basic classes
* defined in classusr.h.  Sorry there aren't macros for the strings yet.

* dispatched method ID's
* NOTE: Applications should use Intuition entry points, not these,
* for NewObject, DisposeObject, SetAttrs, SetGadgetAttrs, and GetAttr.

    ENUM $101
    EITEM OM_NEW		; 'object' parameter is "true class"
    EITEM OM_DISPOSE		; delete self (no parameters)
    EITEM OM_SET		; set attribute (list)
    EITEM OM_GET		; return single attribute value
    EITEM OM_ADDTAIL		; add self to a List
    EITEM OM_REMOVE		; remove self from list (no parameters)
    EITEM OM_NOTIFY		; send to self: notify dependents
    EITEM OM_UPDATE		; notification message from someone
    EITEM OM_ADDMEMBER		; used by various classes with lists
    EITEM OM_REMMEMBER		; used by various classes with lists

* Parameter "Messages" passed to methods.
* NOTE: All of these parameter packets
* start off by the longword MethodID, but
* we don't redefine it for each structure.

* OM_NEW and OM_SET
 STRUCTURE opSet,4
    ; ULONG		MethodID
    APTR		ops_AttrList	; new attributes
    APTR		ops_GInfo	; always there for gadgets,
                    ; but will be NULL for OM_NEW

* OM_NOTIFY, and OM_UPDATE
 STRUCTURE opUpdate,4
    ; ULONG		MethodID
    APTR		opu_AttrList	; new attributes
    APTR		opu_GInfo	; always there for gadgets,
                    ; but will be NULL for OM_NEW
    ULONG		opu_Flags	; defined below

* this flag means that the update message is being issued from
* something like an active gadget, ala GACT_FOLLOWMOUSE.  When
* the gadget goes inactive, it will issue a final update
* message with this bit cleared.  Examples of use are for
* GACT_FOLLOWMOUSE equivalents for propgadclass, and repeat strobes
* for buttons.

OPUB_INTERIM	EQU	0
OPUF_INTERIM	EQU	1

* OM_GET
 STRUCTURE opGet,4
    ; ULONG		MethodID
    ULONG		opg_AttrID
    APTR		opg_Storage	; may be other types, but "int"
                    ; types are all ULONG

* OM_ADDTAIL
 STRUCTURE opAddTail,4
    ; ULONG		MethodID
    APTR		opat_List

* OM_ADDMEMBER, OM_REMMEMBER

 STRUCTURE opMember,4
    ; ULONG		MethodID
    APTR		opam_Object

 ENDC	; IFND INTUITION_CLASSUSR_I


Includes/intuition/imageclass.i

    IFND INTUITION_IMAGECLASS_I
INTUITION_IMAGECLASS_I SET 1
**
**  $Filename: intuition/imageclass.i $
**  $Release: 2.04 Includes, V37.4 $
**  $Revision: 36.5 $
**  $Date: 91/11/08 $
**
**  Definitions for the image classes
**
**  (C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND UTILITY_TAGITEM_I
    INCLUDE "utility/tagitem.i"
    ENDC

*
* NOTE:  intuition/iobsolete.i is included at the END of this file!
*

CUSTOMIMAGEDEPTH	EQU (-1)
* if image.Depth is this, it's a new Image class object

******************************************************
IMAGE_ATTRIBUTES	EQU (TAG_USER+$20000)

IA_Left		EQU (IMAGE_ATTRIBUTES+$0001)
IA_Top		EQU (IMAGE_ATTRIBUTES+$0002)
IA_Width	EQU (IMAGE_ATTRIBUTES+$0003)
IA_Height	EQU (IMAGE_ATTRIBUTES+$0004)
IA_FGPen	EQU (IMAGE_ATTRIBUTES+$0005)
            ; IA_FGPen also means "PlanePick"
IA_BGPen	EQU (IMAGE_ATTRIBUTES+$0006)
            ; IA_BGPen also means "PlaneOnOff"
IA_Data		EQU (IMAGE_ATTRIBUTES+$0007)
            ; bitplanes, for classic image,
            ; other image classes may use it for other things
IA_LineWidth	EQU (IMAGE_ATTRIBUTES+$0008)
IA_Pens		EQU (IMAGE_ATTRIBUTES+$000E)
            ; pointer to UWORD pens[],
            ; ala DrawInfo.Pens, MUST be
            ; terminated by ~0.  Some classes can
            ; choose to have this, or SYSIA_DrawInfo,
            ; or both.
IA_Resolution	EQU (IMAGE_ATTRIBUTES+$000F)
            ; packed uwords for x/y resolution into a longword
            ; ala DrawInfo.Resolution

* see class documentation to learn which
* classes recognize these
IA_APattern	EQU (IMAGE_ATTRIBUTES+$0010)
IA_APatSize	EQU (IMAGE_ATTRIBUTES+$0011)
IA_Mode		EQU (IMAGE_ATTRIBUTES+$0012)
IA_Font		EQU (IMAGE_ATTRIBUTES+$0013)
IA_Outline	EQU (IMAGE_ATTRIBUTES+$0014)
IA_Recessed	EQU (IMAGE_ATTRIBUTES+$0015)
IA_DoubleEmboss	EQU (IMAGE_ATTRIBUTES+$0016)
IA_EdgesOnly	EQU (IMAGE_ATTRIBUTES+$0017)

* "sysiclass" attributes
SYSIA_Size	EQU (IMAGE_ATTRIBUTES+$000B)
            ; EQU's below
SYSIA_Depth	EQU (IMAGE_ATTRIBUTES+$000C)
            ; this is unused by Intuition.  SYSIA_DrawInfo
            ; is used instead for V36
SYSIA_Which	EQU (IMAGE_ATTRIBUTES+$000D)
            ; see EQU's below
SYSIA_DrawInfo	EQU (IMAGE_ATTRIBUTES+$0018)
            ; pass to sysiclass, please

*  obsolete: don't use these, use IA_Pens
SYSIA_Pens	EQU IA_Pens
IA_ShadowPen	EQU (IMAGE_ATTRIBUTES+$0009)
IA_HighlightPen	EQU (IMAGE_ATTRIBUTES+$000A)

* next attribute: (IMAGE_ATTRIBUTES+$0019)
******************************************************

* data values for SYSIA_Size
SYSISIZE_MEDRES	EQU (0)
SYSISIZE_LOWRES	EQU (1)
SYSISIZE_HIRES	EQU (2)

*
* SYSIA_Which tag data values:
* Specifies which system gadget you want an image for.
* Some numbers correspond to internal Intuition #defines
DEPTHIMAGE	EQU ($00)
ZOOMIMAGE	EQU ($01)
SIZEIMAGE	EQU ($02)
CLOSEIMAGE	EQU ($03)
SDEPTHIMAGE	EQU ($05)		; screen depth gadget
LEFTIMAGE	EQU ($0A)
UPIMAGE		EQU ($0B)
RIGHTIMAGE	EQU ($0C)
DOWNIMAGE	EQU ($0D)
CHECKIMAGE	EQU ($0E)
MXIMAGE		EQU ($0F)	; mutual exclude "button"

* image message id's
IM_DRAW		EQU ($0202)	; draw yourself, with "state"
IM_HITTEST	EQU ($0203)	; return TRUE if click hits image
IM_ERASE	EQU ($0204)	; erase yourself
IM_MOVE		EQU ($0205)	; draw new and erase old, smoothly

IM_DRAWFRAME	EQU ($0206)	; draw with specified dimensions
IM_FRAMEBOX	EQU ($0207)	; get recommended frame around some box
IM_HITFRAME	EQU ($0208)	; hittest with dimensions
IM_ERASEFRAME	EQU ($0209)	; hittest with dimensions

* image draw states or styles, for IM_DRAW
IDS_NORMAL		EQU (0)
IDS_SELECTED		EQU (1)	; for selected gadgets
IDS_DISABLED		EQU (2)	; for disabled gadgets
IDS_BUSY		EQU (3)	; for future functionality
IDS_INDETERMINATE	EQU (4)	; for future functionality
IDS_INACTIVENORMAL	EQU (5)	; normal, in inactive window border
IDS_INACTIVESELECTED	EQU (6)	; selected, in inactive border
IDS_INACTIVEDISABLED	EQU (7)	; disabled, in inactive border

* oops, please forgive spelling error by jimm
IDS_INDETERMINANT EQU IDS_INDETERMINATE

* IM_FRAMEBOX
 STRUCTURE impFrameBox,4		; starts with ULONG MethodID
    APTR	impf_ContentsBox	; input: relative box of contents
    APTR	impf_FrameBox	; output: rel. box of encl frame
    APTR	impf_DrInfo	; NB: May be NULL
    LONG	impf_FrameFlags

; Make do with the dimensions of FrameBox provided.
FRAMEB_SPECIFY	EQU (0)
FRAMEF_SPECIFY	EQU (1)

* IM_DRAW, IM_DRAWFRAME
 STRUCTURE impDraw,4		; starts with ULONG MethodID
    APTR	impd_RPort
    WORD	impd_OffsetX
    WORD	impd_OffsetY
    ULONG	impd_State
    APTR	impd_DrInfo	; NB: May be NULL
    ; these parameters only valid for IM_DRAWFRAME
    WORD	impd_DimensionsWidth
    WORD	impd_DimensionsHeight

* IM_ERASE, IM_ERASEFRAME
* NOTE: This is a subset of impDraw
 STRUCTURE impErase,4		; starts with ULONG MethodID
    APTR	impe_RPort
    WORD	impe_OffsetX
    WORD	impe_OffsetY
    ; these parameters only valid for IM_ERASEFRAME
    WORD	impe_DimensionsWidth
    WORD	impe_DimensionsHeight

* IM_HITTEST, IM_HITFRAME
 STRUCTURE impHitTest,4		; starts with ULONG MethodID
    ; these parameters only valid for IM_ERASEFRAME
    WORD	imph_PointX
    WORD	imph_PointY
    ; these parameters only valid for IM_HITFRAME
    WORD	imph_DimensionsWidth
    WORD	imph_DimensionsHeight

* Include obsolete identifiers:
    IFND	INTUITION_IOBSOLETE_I
    INCLUDE "intuition/iobsolete.i"
    ENDC

    ENDC


Includes/intuition/iobsolete.i

    IFND INTUITION_IOBSOLETE_I
INTUITION_IOBSOLETE_I SET 1
**
**  $Filename: intuition/iobsolete.i $
**  $Release: 2.04 Includes, V37.4 $
**  $Revision: 36.2 $
**  $Date: 91/02/05 $
**
**  Obsolete identifiers for Intuition.  Use the new ones instead!
**
**  (C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

* This file contains:
*
* 1.  The traditional identifiers for gadget Flags, Activation, and Type,
* and for window Flags and IDCMP classes.  They are defined in terms
* of their new versions, which serve to prevent confusion between
* similar-sounding but different identifiers (like IDCMP_WINDOWACTIVE
* and WFLG_ACTIVATE).
*
* 2.  Some tag names and constants whose labels were adjusted after V36.
*
* By default, 1 and 2 are enabled.
*
* Set INTUI_V36_NAMES_ONLY to exclude the traditional identifiers and
* the original V36 names of some identifiers.
*

    IFND INTUITION_INTUITION_I
    INCLUDE "intuition/intuition.i"
    ENDC

    IFND INTUITION_SCREENS_I
    INCLUDE "intuition/screens.i"
    ENDC

    IFND INTUITION_GADGETCLASS_I
    INCLUDE "intuition/gadgetclass.i"
    ENDC

    IFND INTUITION_IMAGECLASS_I
    INCLUDE "intuition/imageclass.i"
    ENDC

* Set INTUI_V36_NAMES_ONLY to remove these older names

    IFND INTUI_V36_NAMES_ONLY

* V34-style Gadget->Flags names:

GADGHIGHBITS	equ	GFLG_GADGHIGHBITS
GADGHCOMP	equ	GFLG_GADGHCOMP
GADGHBOX	equ	GFLG_GADGHBOX
GADGHIMAGE	equ	GFLG_GADGHIMAGE
GADGHNONE	equ	GFLG_GADGHNONE
GADGIMAGE	equ	GFLG_GADGIMAGE
GRELBOTTOM	equ	GFLG_RELBOTTOM
GRELRIGHT	equ	GFLG_RELRIGHT
GRELWIDTH	equ	GFLG_RELWIDTH
GRELHEIGHT	equ	GFLG_RELHEIGHT
SELECTED	equ	GFLG_SELECTED
GADGDISABLED	equ	GFLG_DISABLED
LABELMASK	equ	GFLG_LABELMASK
LABELITEXT	equ	GFLG_LABELITEXT
LABELSTRING	equ	GFLG_LABELSTRING
LABELIMAGE	equ	GFLG_LABELIMAGE

* V34-style Gadget->Activation flag names:

RELVERIFY	equ	GACT_RELVERIFY
GADGIMMEDIATE	equ	GACT_IMMEDIATE
ENDGADGET	equ	GACT_ENDGADGET
FOLLOWMOUSE	equ	GACT_FOLLOWMOUSE
RIGHTBORDER	equ	GACT_RIGHTBORDER
LEFTBORDER	equ	GACT_LEFTBORDER
TOPBORDER	equ	GACT_TOPBORDER
BOTTOMBORDER	equ	GACT_BOTTOMBORDER
BORDERSNIFF	equ	GACT_BORDERSNIFF
TOGGLESELECT	equ	GACT_TOGGLESELECT
BOOLEXTEND	equ	GACT_BOOLEXTEND
STRINGLEFT	equ	GACT_STRINGLEFT
STRINGCENTER	equ	GACT_STRINGCENTER
STRINGRIGHT	equ	GACT_STRINGRIGHT
LONGINT		equ	GACT_LONGINT
ALTKEYMAP	equ	GACT_ALTKEYMAP
STRINGEXTEND	equ	GACT_STRINGEXTEND
ACTIVEGADGET	equ	GACT_ACTIVEGADGET

* V34-style Gadget->Type names:

GADGETTYPE	equ	GTYP_GADGETTYPE
SYSGADGET	equ	GTYP_SYSGADGET
SCRGADGET	equ	GTYP_SCRGADGET
GZZGADGET	equ	GTYP_GZZGADGET
REQGADGET	equ	GTYP_REQGADGET
SIZING		equ	GTYP_SIZING
WDRAGGING	equ	GTYP_WDRAGGING
SDRAGGING	equ	GTYP_SDRAGGING
WUPFRONT	equ	GTYP_WUPFRONT
SUPFRONT	equ	GTYP_SUPFRONT
WDOWNBACK	equ	GTYP_WDOWNBACK
SDOWNBACK	equ	GTYP_SDOWNBACK
CLOSE		equ	GTYP_CLOSE
BOOLGADGET	equ	GTYP_BOOLGADGET
GADGET0002	equ	GTYP_GADGET0002
PROPGADGET	equ	GTYP_PROPGADGET
STRGADGET	equ	GTYP_STRGADGET
CUSTOMGADGET	equ	GTYP_CUSTOMGADGET
GTYPEMASK	equ	GTYP_GTYPEMASK

* V34-style IDCMP class names:

SIZEVERIFY	equ	IDCMP_SIZEVERIFY
NEWSIZE		equ	IDCMP_NEWSIZE
REFRESHWINDOW	equ	IDCMP_REFRESHWINDOW
MOUSEBUTTONS	equ	IDCMP_MOUSEBUTTONS
MOUSEMOVE	equ	IDCMP_MOUSEMOVE
GADGETDOWN	equ	IDCMP_GADGETDOWN
GADGETUP	equ	IDCMP_GADGETUP
REQSET		equ	IDCMP_REQSET
MENUPICK	equ	IDCMP_MENUPICK
CLOSEWINDOW	equ	IDCMP_CLOSEWINDOW
RAWKEY		equ	IDCMP_RAWKEY
REQVERIFY	equ	IDCMP_REQVERIFY
REQCLEAR	equ	IDCMP_REQCLEAR
MENUVERIFY	equ	IDCMP_MENUVERIFY
NEWPREFS	equ	IDCMP_NEWPREFS
DISKINSERTED	equ	IDCMP_DISKINSERTED
DISKREMOVED	equ	IDCMP_DISKREMOVED
WBENCHMESSAGE	equ	IDCMP_WBENCHMESSAGE
ACTIVEWINDOW	equ	IDCMP_ACTIVEWINDOW
INACTIVEWINDOW	equ	IDCMP_INACTIVEWINDOW
DELTAMOVE	equ	IDCMP_DELTAMOVE
VANILLAKEY	equ	IDCMP_VANILLAKEY
INTUITICKS	equ	IDCMP_INTUITICKS
IDCMPUPDATE	equ	IDCMP_IDCMPUPDATE
MENUHELP	equ	IDCMP_MENUHELP
CHANGEWINDOW	equ	IDCMP_CHANGEWINDOW
LONELYMESSAGE	equ	IDCMP_LONELYMESSAGE

* V34-style Window->Flags names:

WINDOWSIZING	equ	WFLG_SIZEGADGET
WINDOWDRAG	equ	WFLG_DRAGBAR
WINDOWDEPTH	equ	WFLG_DEPTHGADGET
WINDOWCLOSE	equ	WFLG_CLOSEGADGET
SIZEBRIGHT	equ	WFLG_SIZEBRIGHT
SIZEBBOTTOM	equ	WFLG_SIZEBBOTTOM
REFRESHBITS	equ	WFLG_REFRESHBITS
SMART_REFRESH	equ	WFLG_SMART_REFRESH
SIMPLE_REFRESH	equ	WFLG_SIMPLE_REFRESH
SUPER_BITMAP	equ	WFLG_SUPER_BITMAP
OTHER_REFRESH	equ	WFLG_OTHER_REFRESH
BACKDROP	equ	WFLG_BACKDROP
REPORTMOUSE	equ	WFLG_REPORTMOUSE
GIMMEZEROZERO	equ	WFLG_GIMMEZEROZERO
BORDERLESS	equ	WFLG_BORDERLESS
ACTIVATE	equ	WFLG_ACTIVATE
WINDOWACTIVE	equ	WFLG_WINDOWACTIVE
INREQUEST	equ	WFLG_INREQUEST
MENUSTATE	equ	WFLG_MENUSTATE
RMBTRAP		equ	WFLG_RMBTRAP
NOCAREREFRESH	equ	WFLG_NOCAREREFRESH
WINDOWREFRESH	equ	WFLG_WINDOWREFRESH
WBENCHWINDOW	equ	WFLG_WBENCHWINDOW
WINDOWTICKED	equ	WFLG_WINDOWTICKED
NW_EXTENDED	equ	WFLG_NW_EXTENDED
VISITOR		equ	WFLG_VISITOR
ZOOMED		equ	WFLG_ZOOMED
HASZOOM		equ	WFLG_HASZOOM

* These are the obsolete tag names for general gadgets, proportional gadgets,
* and string gadgets.  Use the mixed-case equivalents from gadgetclass.h
* instead.
*

GA_LEFT			equ	GA_Left
GA_RELRIGHT		equ	GA_RelRight
GA_TOP			equ	GA_Top
GA_RELBOTTOM		equ	GA_RelBottom
GA_WIDTH		equ	GA_Width
GA_RELWIDTH		equ	GA_RelWidth
GA_HEIGHT		equ	GA_Height
GA_RELHEIGHT		equ	GA_RelHeight
GA_TEXT			equ	GA_Text
GA_IMAGE		equ	GA_Image
GA_BORDER		equ	GA_Border
GA_SELECTRENDER		equ	GA_SelectRender
GA_HIGHLIGHT		equ	GA_Highlight
GA_DISABLED		equ	GA_Disabled
GA_GZZGADGET		equ	GA_GZZGadget
GA_USERDATA		equ	GA_UserData
GA_SPECIALINFO		equ	GA_SpecialInfo
GA_SELECTED		equ	GA_Selected
GA_ENDGADGET		equ	GA_EndGadget
GA_IMMEDIATE		equ	GA_Immediate
GA_RELVERIFY		equ	GA_RelVerify
GA_FOLLOWMOUSE		equ	GA_FollowMouse
GA_RIGHTBORDER		equ	GA_RightBorder
GA_LEFTBORDER		equ	GA_LeftBorder
GA_TOPBORDER		equ	GA_TopBorder
GA_BOTTOMBORDER		equ	GA_BottomBorder
GA_TOGGLESELECT		equ	GA_ToggleSelect
GA_SYSGADGET		equ	GA_SysGadget
GA_SYSGTYPE		equ	GA_SysGType
GA_PREVIOUS		equ	GA_Previous
GA_NEXT			equ	GA_Next
GA_DRAWINFO		equ	GA_DrawInfo
GA_INTUITEXT		equ	GA_IntuiText
GA_LABELIMAGE		equ	GA_LabelImage

PGA_FREEDOM		equ	PGA_Freedom
PGA_BORDERLESS		equ	PGA_Borderless
PGA_HORIZPOT		equ	PGA_HorizPot
PGA_HORIZBODY		equ	PGA_HorizBody
PGA_VERTPOT		equ	PGA_VertPot
PGA_VERTBODY		equ	PGA_VertBody
PGA_TOTAL		equ	PGA_Total
PGA_VISIBLE		equ	PGA_Visible
PGA_TOP			equ	PGA_Top

LAYOUTA_LAYOUTOBJ	equ	LAYOUTA_LayoutObj
LAYOUTA_SPACING		equ	LAYOUTA_Spacing
LAYOUTA_ORIENTATION	equ	LAYOUTA_Orientation

* These are the obsolete tag names for image attributes.
* Use the mixed-case equivalents from imageclass.h instead.
*

IA_LEFT			equ	IA_Left
IA_TOP			equ	IA_Top
IA_WIDTH		equ	IA_Width
IA_HEIGHT		equ	IA_Height
IA_FGPEN		equ	IA_FGPen
IA_BGPEN		equ	IA_BGPen
IA_DATA			equ	IA_Data
IA_LINEWIDTH		equ	IA_LineWidth
IA_PENS			equ	IA_Pens
IA_RESOLUTION		equ	IA_Resolution
IA_APATTERN		equ	IA_APattern
IA_APATSIZE		equ	IA_APatSize
IA_MODE			equ	IA_Mode
IA_FONT			equ	IA_Font
IA_OUTLINE		equ	IA_Outline
IA_RECESSED		equ	IA_Recessed
IA_DOUBLEEMBOSS		equ	IA_DoubleEmboss
IA_EDGESONLY		equ	IA_EdgesOnly
IA_SHADOWPEN		equ	IA_ShadowPen
IA_HIGHLIGHTPEN		equ	IA_HighlightPen

* These are the obsolete identifiers for the various DrawInfo pens.
* Use the uppercase versions in screens.h instead.
*

detailPen	equ	DETAILPEN
blockPen	equ	BLOCKPEN
textPen		equ	TEXTPEN
shinePen	equ	SHINEPEN
shadowPen	equ	SHADOWPEN
hifillPen	equ	FILLPEN
hifilltextPen	equ	FILLTEXTPEN
backgroundPen	equ	BACKGROUNDPEN
hilighttextPen	equ	HIGHLIGHTTEXTPEN
numDrIPens	equ	NUMDRIPENS

    ENDC	* !INTUI_V36_NAMES_ONLY

    ENDC	* INTUITION_IOBSOLETE_I


Includes/intuition/sghooks.i

    IFND INTUITION_SGHOOKS_I
INTUITION_SGHOOKS_I SET 1
**
** $Filename: intuition/sghooks.i $
** $Release: 2.04 Includes, V37.4 $
** $Revision: 36.5 $
** $Date: 91/11/08 $
**
**  String gadget extensions and hooks
**
**  (C) Copyright 1988-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND EXEC_TYPES_I
    INCLUDE "exec/types.i"
    ENDC

 STRUCTURE StringExtend,0
    ; display specifications
    APTR	sex_Font	; must be an open Font (not TextAttr)
    STRUCT	sex_Pens,2	; color of text/background
    STRUCT	sex_ActivePens,2 ; colors when gadget is active

    ; edit specifications
    ULONG	sex_InitialModes ; initial mode flags, below
    APTR	sex_EditHook	; if non-NULL, must supply WorkBuffer
    APTR	sex_WorkBuffer	; must be as large as StringInfo.Buffer

    STRUCT	sex_Reserved,16	; set to 0
 LABEL	sex_SIZEOF

 STRUCTURE SGWork,0
    ; set up when gadget is first activated
    APTR		sgw_Gadget	; the contestant itself
    APTR		sgw_StringInfo	; easy access to sinfo
    APTR		sgw_WorkBuffer	; intuition's planned result
    APTR		sgw_PrevBuffer	; what was there before
    ULONG		sgw_Modes	; current mode

    ; modified for each input event
    APTR		sgw_IEvent	; actual event: do not change
    UWORD		sgw_Code	; character code, if one byte
    WORD		sgw_BufferPos	; cursor position
    WORD		sgw_NumChars
    ULONG		sgw_Actions	; what Intuition will do
    LONG		sgw_LongInt	; temp storage for longint

    APTR		sgw_GadgetInfo	; see cghooks.h
    UWORD		sgw_EditOp	; from constants below
 LABEL	sgw_SIZEOF	; this may change as the structure is extended

* SGWork.EditOp -
* These values indicate what basic type of operation the global
* editing hook has performed on the string before your gadget's custom
* editing hook gets called.  You do not have to be concerned with the
* value your custom hook leaves in the sgw_EditOp field, only if you
* write a global editing hook.
*
* For most of these general edit operations, you'll want to compare
* the BufferPos and NumChars of the StringInfo (before global editing)
* and SGWork (after global editing).

EO_NOOP		EQU ($0001)
    ; did nothing
EO_DELBACKWARD	EQU ($0002)
    ; deleted some chars (maybe 0).
EO_DELFORWARD	EQU ($0003)
    ; deleted some characters under and in front of the cursor
EO_MOVECURSOR	EQU ($0004)
    ; moved the cursor
EO_ENTER	EQU ($0005)
        ; "enter" or "return" key, terminate
EO_RESET	EQU ($0006)
    ; current Intuition-style undo
EO_REPLACECHAR	EQU ($0007)
    ; replaced one character and (maybe) advanced cursor
EO_INSERTCHAR	EQU ($0008)
    ; inserted one char into string or added one at end
EO_BADFORMAT	EQU ($0009)
    ; didn't like the text data, e.g., Bad LONGINT
EO_BIGCHANGE	EQU ($000A)	; unused by Intuition
    ; complete or major change to the text, e.g. new string
EO_UNDO		EQU ($000B)	; unused by Intuition
    ; some other style of undo
EO_CLEAR	EQU ($000C)
    ; clear the string
EO_SPECIAL	EQU ($000D)	; unused by Intuition
    ; some operation that doesn't fit into the categories here

; Mode Flags definitions (ONLY first group allowed as InitialModes)

SGM_REPLACE	EQU	1
SGMB_REPLACE	EQU	0
SGMF_REPLACE	EQU	1
; please initialize StringInfo with in-range value of BufferPos
; if you are using SGM_REPLACE mode.

; fixed length buffer, always set SGM_REPLACE, too.
SGM_FIXEDFIELD	EQU $00000002
SGMB_FIXEDFIELD	EQU 1
SGMF_FIXEDFIELD	EQU 2

; don't filter control chars
SGM_NOFILTER	EQU $00000004
SGMB_NOFILTER	EQU 2
SGMF_NOFILTER	EQU 4

; SGM_EXITHELP is new for V37, and ignored by V36:
; exit with code = 0x5F if HELP hit
SGM_EXITHELP	EQU $00000080
SGMB_EXITHELP	EQU 7
SGMF_EXITHELP	EQU $80

; String Gadget Action Flags (put in SGWork.Actions by EditHook)
SGA_USE		EQU $1		; use contents of SGWork
SGAB_USE	EQU 0
SGAF_USE	EQU $1

SGA_END		EQU $2		; terminate gadget, code in Code field
SGAB_END	EQU 1
SGAF_END	EQU $2

SGA_BEEP	EQU $4		; flash the screen for the user
SGAB_BEEP	EQU 2
SGAF_BEEP	EQU $4

SGA_REUSE	EQU $8		; reuse input event
SGAB_REUSE	EQU 3
SGAF_REUSE	EQU $8

SGA_REDISPLAY	EQU $10		; gadget visuals changed
SGAB_REDISPLAY		EQU 4
SGAF_REDISPLAY		EQU $10

; New for V37:
SGA_NEXTACTIVE	EQU $20		; Make next possible gadget active.
SGAB_NEXTACTIVE	EQU 5
SGAF_NEXTACTIVE	EQU $20

; New for V37:
SGA_PREVACTIVE	EQU $40		; Make previous possible gadget active.
SGAB_PREVACTIVE	EQU 6
SGAF_PREVACTIVE	EQU $40

; function id for only existing custom string gadget edit hook
SGH_KEY		EQU	1	; process editing keystroke
SGH_CLICK	EQU	2	; process mouse click cursor position

* Here's a brief summary of how the custom string gadget edit hook works:
*	You provide a hook in StringInfo.Extension.EditHook.
*	The hook is called in the standard way with the 'object'
*	a pointer to SGWork, and the 'message' a pointer to a command
*	block, starting either with (longword) SGH_KEY, SGH_CLICK,
*	or something new.
*
*	You return 0 if you don't understand the command (SGH_KEY is
*	required and assumed).	Return non-zero if you implement the
*	command.
*
*   SGH_KEY:
*	There are no parameters following the command longword.
*
*	Intuition will put its idea of proper values in the SGWork
*	before calling you, and if you leave SGA_USE set in the
*	SGWork.Actions field, Intuition will use the values
*	found in SGWork fields WorkBuffer, NumChars, BufferPos,
*	and LongInt, copying the WorkBuffer back to the StringInfo
*	Buffer.
*
*	NOTE WELL: You may NOT change other SGWork fields.
*
*	If you clear SGA_USE, the string gadget will be unchanged.
*
*	If you set SGA_END, Intuition will terminate the activation
*	of the string gadget.  If you also set SGA_REUSE, Intuition
*	will reuse the input event after it deactivates your gadget.
*
*	In this case, Intuition will put the value found in SGWork.Code
*	into the IntuiMessage.Code field of the IDCMP_GADGETUP message it
*	sends to the application.
*
*	If you set SGA_BEEP, Intuition will call DisplayBeep(); use
*	this if the user has typed in error, or buffer is full.
*
*	Set SGA_REDISPLAY if the changes to the gadget warrant a
*	gadget redisplay.  Note: cursor movement requires a redisplay.
*
*	Starting in V37, you may set SGA_PREVACTIVE or SGA_NEXTACTIVE
*	when you set SGA_END.  This tells Intuition that you want
*	the next or previous gadget with GFLG_TABCYCLE to be activated.
*
*   SGH_CLICK:
*	This hook command is called when Intuition wants to position
*	the cursor in response to a mouse click in the string gadget.
*
*	Again, here are no parameters following the command longword.
*
*	This time, Intuition has already calculated the mouse position
*	character cell and put it in SGWork.BufferPos.	The previous
*	BufferPos value remains in the SGWork.StringInfo.BufferPos.
*
*	Intuition will again use the SGWork fields listed above for
*	SGH_KEY.  One restriction is that you are NOT allowed to set
*	SGA_END or SGA_REUSE for this command.	Intuition will not
*	stand for a gadget which goes inactive when you click in it.
*
*	You should always leave the SGA_REDISPLAY flag set, since Intuition
*	uses this processing when activating a string gadget.

    ENDC


Includes/libraries/asl.h

#ifndef	LIBRARIES_ASL_H
#define	LIBRARIES_ASL_H	1

/*
**	$Filename: libraries/asl.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.5 $
**	$Date: 91/11/08 $
**
**	ASL library name and useful definitions.
**
**	(C) Copyright 1989,1990 Charlie Heath
**	(C) Copyright 1989-1999 Amiga, Inc.
**		All Rights Reserved
*/

#ifndef	EXEC_TYPES_H
#include	<exec/types.h>
#endif

#ifndef	EXEC_LISTS_H
#include	<exec/lists.h>
#endif

#ifndef	EXEC_LIBRARIES_H
#include	<exec/libraries.h>
#endif

#ifndef UTILITY_HOOKS_H
#include <utility/hooks.h>
#endif

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

#ifndef WBArg
#include <workbench/startup.h>
#endif

#ifndef GRAPHICS_TEXT_H
#include <graphics/text.h>
#endif

/*
 ************************************************************************
 *	Standard definitions for asl library information		*
 ************************************************************************
 */

#define	AslName		"asl.library"

/*
 ************************************************************************
 *									*
 *	The ASL file requester data structure...			*
 *									*
 * The fields described here are for READ ACCESS to the structure	*
 * returned by AllocAslRequest( ASL_FileRequest, ... )			*
 *									*
 * Any modifications MUST be done via TAGS either at the time of	*
 * creation by AllocAslRequest(), or when used, via AslRequest()	*
 *									*
 ************************************************************************
 */
struct FileRequester	{
    APTR	rf_Reserved1;
    BYTE	*rf_File;	/* Filename pointer		*/
    BYTE	*rf_Dir;	/* Directory name pointer	*/
    CPTR	rf_Reserved2;
    UBYTE	rf_Reserved3;
    UBYTE	rf_Reserved4;
    APTR	rf_Reserved5;
    WORD	rf_LeftEdge,rf_TopEdge;	/* Preferred window pos	*/
    WORD	rf_Width,rf_Height;   /* Preferred window size	*/
    WORD	rf_Reserved6;
    LONG	rf_NumArgs;	/* A-la WB Args, for multiselects */
    struct WBArg *rf_ArgList;
    APTR	rf_UserData;	/* Applihandle (you may write!!) */
    APTR	rf_Reserved7;
    APTR	rf_Reserved8;
    BYTE	*rf_Pat;	/* Pattern match pointer */
    };			/* note - more reserved fields follow */

/*
 * The following defined values are the ASL_FuncFlags tag values which
 * are defined for the ASL file request.  These values may be passed
 * as a TagItem to modify the way the requester is presented.  Each
 * flag value defined has a description of the particular action.
 *
 * Also related to the ASL_FuncFlags values is the ASL_HookFunc tagitem,
 * which provides a callback function pointer to allow the application
 * to interact with the requester.  If an ASL_HookFunc TagItem is
 * provided, the hook function will be called like so:
 *
 * ULONG rf_Function(ULONG Mask, CPTR Object, CPTR AslRequester)
 *
 * The Mask value is a copy of the specific ASL_FuncFlags value
 * the callback is for; Object is a pointer to a data object.
 * AslRequester is a pointer to the requester structure.
 *
 * For the ASL file and font requesters, two ASL_FuncFlags values
 * are currently defined; FILF_DOWILDFUNC and FILF_DOMSGFUNC.
 *
 */

#define	FILB_DOWILDFUNC	7L /* Called with an Object=AnchorPath,	*/
               /*		 ZERO return accepts.	*/
#define	FILB_DOMSGFUNC	6L /* Called with Object=IDCMP message	*/
               /*  for other window of shared port. */
               /* You must return pointer to Object,*/
               /* asl will reply the Object for you */
#define	FILB_SAVE	5L /* For a SAVE operation, set this bit */
#define	FILB_NEWIDCMP	4L /* Force a new IDCMP (only if rf_Window != NULL)  */
#define FILB_MULTISELECT 3L /* Request multiple selections returned from FR. */
               /*	MULISELECT is ignored if FILB_SAVE is on     */
#define	FILB_PATGAD	0L /* Ask for pattern gadget			     */

#define	FILF_DOWILDFUNC	(1L << FILB_DOWILDFUNC)
#define	FILF_DOMSGFUNC	(1L << FILB_DOMSGFUNC)

#define	FILF_SAVE	(1L << FILB_SAVE)
#define	FILF_NEWIDCMP	(1L << FILB_NEWIDCMP)
#define	FILF_MULTISELECT (1L << FILB_MULTISELECT)
#define	FILF_PATGAD	(1L << FILB_PATGAD)

/* The following additional flags may be passed with the
 * ASL_ExtFlags1 tag.
 */
#define	FIL1B_NOFILES	0L /* Do not want a file gadget, no files shown      */
#define	FIL1B_MATCHDIRS	1L /* Have Patgad or rf_Pat screen files AND DIRS    */

#define	FIL1F_NOFILES	(1L << FIL1B_NOFILES)
#define	FIL1F_MATCHDIRS	(1L << FIL1B_MATCHDIRS)

/*
 ************************************************************************
 *	The ASL font requester data structure...			*
 *									*
 * As with the FileRequest structure, the fields documented here are	*
 * for READ ACCESS ONLY.  Any modifications must be done via tags.	*
 ************************************************************************
 */
struct FontRequester	{
    APTR	fo_Reserved1[2];
    struct TextAttr fo_Attr;	/* Returned TextAttr		*/
    UBYTE	fo_FrontPen;		/* Returned pens, if selected	*/
    UBYTE	fo_BackPen;
    UBYTE	fo_DrawMode;
    APTR	fo_UserData;
    };

/* Bit defines for ASL_FuncFlags, for FONT requester			*/
/* See descriptive text for FILF_ values above for an overview.		*/
/* Note - old mixed-case defines were nonstandard, now obsolete		*/

#define	FONB_FRONTCOLOR	0	/* Display Front color selector?	*/
#define	FONB_BACKCOLOR	1	/* Display Back color selector?		*/
#define	FONB_STYLES	2	/* Display Styles checkboxes?		*/
#define	FONB_DRAWMODE	3	/* Display DrawMode NWay?		*/
#define	FONB_FIXEDWIDTH	4	/* Only allow fixed-width fonts?	*/
#define	FONB_NEWIDCMP	5	/* Create a new IDCMP port, not shared	*/
#define	FONB_DOMSGFUNC	6	/* Called with Object=IntuiMessage for	*/
                /*	other windows in shared port,	*/
                /*   you must return Object pointer	*/
                /*   and asl will reply Object for you	*/
#define	FONB_DOWILDFUNC	7	/* Called with Object=TextAttr to approve*/
                /*	NON-Zero return accepts		*/

#define	FONF_FRONTCOLOR	(1L << FONB_FRONTCOLOR)
#define	FONF_BACKCOLOR	(1L << FONB_BACKCOLOR)
#define	FONF_STYLES	(1L << FONB_STYLES)
#define	FONF_DRAWMODE	(1L << FONB_DRAWMODE)
#define	FONF_FIXEDWIDTH	(1L << FONB_FIXEDWIDTH)
#define	FONF_NEWIDCMP	(1L << FONB_NEWIDCMP)
#define	FONF_DOMSGFUNC	(1L << FONB_DOMSGFUNC)
#define	FONF_DOWILDFUNC	(1L << FONB_DOWILDFUNC)

/************************************************************************/
/* Arguments to AllocAslRequest()					*/
/* Types of requester structures which may be allocated:		*/
/************************************************************************/
#define	ASL_FileRequest	0
#define	ASL_FontRequest	1

/************************************************************************/
/* Tags for AllocAslRequest() and AslRequest()				*/
/************************************************************************/

#define ASL_Dummy (TAG_USER + 0x80000)

#define ASL_Hail	ASL_Dummy+1	/* Hailing text follows		     */
#define ASL_Window	ASL_Dummy+2	/* Parent window for IDCMP & screen  */
#define	ASL_LeftEdge	ASL_Dummy+3	/* Initialize LeftEdge		     */
#define	ASL_TopEdge	ASL_Dummy+4	/* Initialize TopEdge		     */
#define	ASL_Width	ASL_Dummy+5
#define	ASL_Height	ASL_Dummy+6
#define	ASL_HookFunc	ASL_Dummy+7	/* Hook function pointer	     */

/* Tags specific to file request					     */
#define	ASL_File	ASL_Dummy+8	/* Initial name of file follows	     */
#define	ASL_Dir		ASL_Dummy+9	/* Initial string of filerequest dir */

/* Tags specific to font request					     */
#define	ASL_FontName	ASL_Dummy+10	/* Initial font name		     */
#define	ASL_FontHeight	ASL_Dummy+11	/* Initial font height		     */
#define	ASL_FontStyles	ASL_Dummy+12	/* Initial font styles		     */
#define	ASL_FontFlags	ASL_Dummy+13	/* Initial font flags for textattr   */
#define	ASL_FrontPen	ASL_Dummy+14	/* Initial frontpen color	     */
#define	ASL_BackPen	ASL_Dummy+15	/* Initial backpen color	     */
#define	ASL_MinHeight	ASL_Dummy+16	/* Minimum font height to display    */
#define	ASL_MaxHeight	ASL_Dummy+17	/* Max font height to display	     */

#define	ASL_OKText	ASL_Dummy+18	/* Text displayed in OK gadget	     */
#define	ASL_CancelText	ASL_Dummy+19	/* Text displayed in CANCEL gadget   */
#define	ASL_FuncFlags	ASL_Dummy+20	/* Function flags, depend on request */

#define	ASL_ModeList	ASL_Dummy+21	/* Substitute list for font drawmodes */
#define	ASL_ExtFlags1	ASL_Dummy+22	/* For passing extended FIL1F flags   */

#define	ASL_Pattern	ASL_FontName	/* File requester pattern string     */

/******** END of ASL Tag values	*****************************************/

#endif


Includes/libraries/dosextens.h

#ifndef LIBRARIES_DOSEXTENS_H
#define LIBRARIES_DOSEXTENS_H
/*
**	$Filename: libraries/dosextens.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.2 $
**	$Date: 90/07/12 $
**
**	DOS structures not needed for the casual AmigaDOS user
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef DOS_DOSEXTENS_H
#include "dos/dosextens.h"
#endif

#endif /* LIBRARIES_DOSEXTENS_H */


Includes/libraries/iffparse.i

    IFND	IFF_IFFPARSE_I
IFF_IFFPARSE_I	SET	1
**
**	$Filename: libraries/iffparse.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 33.1 $
**	$Date: 90/11/20 $
**
**	Assembly include file for iffparse.library.
**	Generated by hand from iffparse.h (9006.04)
**
**	(C) Copyright 1989-1999 Amiga, Inc., Stuart Ferguson
**	and Leo L. Schwab
**		All Rights Reserved
**

        IFND	EXEC_TYPES_I
        include "exec/types.i"
        ENDC

        IFND	EXEC_LISTS_I
        include "exec/lists.i"
        ENDC

        IFND	EXEC_PORTS_I
        include "exec/ports.i"
        ENDC

        IFND	DEVICES_CLIPBOARD_I
        include "devices/clipboard.i"
        ENDC

*\
* Struct associated with an active IFF stream.
* "iff_Stream" is a value used by the client's read/write/seek functions -
* it will not be accessed by the library itself and can have any value
* (could even be a pointer or a BPTR).
*/
    STRUCTURE IFFHandle,0
        ULONG	iff_Stream
        ULONG	iff_Flags
        LONG	iff_Depth	; Depth of context stack.
* There are private fields hiding here.
    LABEL	iff_SIZEOF

*\
* Bit masks for "iff_Flags" field.
*/
IFFF_READ	EQU	0			; read mode - default
IFFF_WRITE	EQU	1			; write mode
IFFF_RWBITS	EQU	IFFF_READ!IFFF_WRITE	; read/write bits
IFFF_FSEEK	EQU	1<<1			; forward seek only
IFFF_RSEEK	EQU	1<<2			; random seek
IFFF_RESERVED	EQU	$FFFF0000		; Don't touch these bits.

*\
* When the library calls your stream handler, you'll be passed a pointer
* to this structure as the "message packet".
* NOTE:  ASSEMBLY PREFIX (isc_) DIFFERENT FROM C PREFIX (sc_).
*/
    STRUCTURE IFFStreamCmd,0
        LONG	isc_Command	; Operation to be performed (IFFCMD_)
        APTR	isc_Buf		; Pointer to data buffer
        LONG	isc_NBytes	; Number of bytes to be affected
    LABEL	isc_SIZEOF

*\
* A node associated with a context on the iff_Stack.  Each node
* represents a chunk, the stack representing the current nesting
* of chunks in the open IFF file.  Each context node has associated
* local context items in the (private) LocalItems list.  The ID, type,
* size and scan values describe the chunk associated with this node.
*/
    STRUCTURE ContextNode,MLN_SIZE	; cn_Node
        LONG	cn_ID
        LONG	cn_Type
        LONG	cn_Size		; Size of this chunk
        LONG	cn_Scan		; # of bytes read/written so far
* There are private fields hiding here.
    LABEL	cn_SIZEOF

*\
* Local context items live in the ContextNode's.  Each class is identified
* by its lci_Ident code and has a (private) purge vector for when the
* parent context node is popped.
*/
    STRUCTURE LocalContextItem,MLN_SIZE	; lci_Node
        ULONG	lci_ID
        ULONG	lci_Type
        ULONG	lci_Ident
* There are private fields hiding here.
    LABEL	lci_SIZEOF

*\
* StoredProperty: a local context item containing the data stored
* from a previously encountered property chunk.
* NOTE:  ASSEMBLY PREFIX (spr_) DIFFERENT FROM C PREFIX (sp_).
*/
    STRUCTURE StoredProperty,0
        LONG	spr_Size
        APTR	spr_Data
    LABEL	spr_SIZEOF

*\
* Collection Item: the actual node in the collection list at which
* client will look.  The next pointers cross context boundaries so
* that the complete list is accessable.
* NOTE:  ASSEMBLY PREFIX (cit_) DIFFERENT FROM C PREFIX (ci_).
*/
    STRUCTURE CollectionItem,0
        APTR	cit_Next
        LONG	cit_Size
        APTR	cit_Data
    LABEL	cit_SIZEOF

*\
* Structure returned by OpenClipboard().  You may do CMD_POSTs and such
* using this structure.  However, once you call OpenIFF(), you may not
* do any more of your own I/O to the clipboard until you call CloseIFF().
*/
    STRUCTURE ClipboardHandle,iocr_SIZEOF	; cbh_Reg
        STRUCT	cbh_CBport,MP_SIZE
        STRUCT	cbh_SatisfyPort,MP_SIZE
    LABEL	cbh_SIZEOF

*\
* IFF return codes.  Most functions return either zero for success or
* one of these codes.  The exceptions are the read/write functions which
* return positive values for number of bytes or records read or written,
* or a negative error code.  Some of these codes are not errors per sae,
* but valid conditions such as EOF or EOC (End of Chunk).
*/
IFFERR_EOF		EQU	-1	; Reached logical end of file
IFFERR_EOC		EQU	-2	; About to leave context
IFFERR_NOSCOPE		EQU	-3	; No valid scope for property
IFFERR_NOMEM		EQU	-4	; Internal memory alloc failed
IFFERR_READ		EQU	-5	; Stream read error
IFFERR_WRITE		EQU	-6	; Stream write error
IFFERR_SEEK		EQU	-7	; Stream seek error
IFFERR_MANGLED		EQU	-8	; Data in file is corrupt
IFFERR_SYNTAX		EQU	-9	; IFF syntax error
IFFERR_NOTIFF		EQU	-10	; Not an IFF file
IFFERR_NOHOOK		EQU	-11	; No call-back hook provided
IFF_RETURN2CLIENT	EQU	-12	; Client handler normal return

*\
* Universal IFF identifiers.
*/
ID_FORM			EQU	'FORM'
ID_LIST			EQU	'LIST'
ID_CAT			EQU	'CAT '
ID_PROP			EQU	'PROP'
ID_NULL			EQU	'    '

*\
* Ident codes for universally recognized local context items.
*/
IFFLCI_PROP		EQU	'prop'
IFFLCI_COLLECTION	EQU	'coll'
IFFLCI_ENTRYHANDLER	EQU	'enhd'
IFFLCI_EXITHANDLER	EQU	'exhd'

*\
* Control modes for ParseIFF() function.
*/
IFFPARSE_SCAN		EQU	0
IFFPARSE_STEP		EQU	1
IFFPARSE_RAWSTEP	EQU	2

*\
* Control modes for StoreLocalItem().
*/
IFFSLI_ROOT		EQU	1	; Store in default context
IFFSLI_TOP		EQU	2	; Store in current context
IFFSLI_PROP		EQU	3	; Store in topmost FORM or LIST

*\
* "Flag" for writing functions.  If you pass this value in as a size
* to PushChunk() when writing a file, the parser will figure out the
* size of the chunk for you.  (Chunk sizes >= 2**31 are forbidden by the
* IFF specification, so this works.)
*/
IFFSIZE_UNKNOWN		EQU	-1

*\
* Possible call-back command values.  (Gee, it would be nice if there was an
* ENUM macro.)
*/
IFFCMD_INIT		EQU	0	; Prepare your stream for a session
IFFCMD_CLEANUP		EQU	1	; Terminate stream session
IFFCMD_READ		EQU	2	; Read bytes from stream
IFFCMD_WRITE		EQU	3	; Write bytes to stream
IFFCMD_SEEK		EQU	4	; Seek on stream
IFFCMD_ENTRY		EQU	5	; You just entered a new context
IFFCMD_EXIT		EQU	6	; You're about to leave a context
IFFCMD_PURGELCI		EQU	7	; Purge a LocalContextItem

* Backward compatibility.  Don't use these in new code.
IFFSCC_INIT		EQU	IFFCMD_INIT
IFFSCC_CLEANUP		EQU	IFFCMD_CLEANUP
IFFSCC_READ		EQU	IFFCMD_READ
IFFSCC_WRITE		EQU	IFFCMD_WRITE
IFFSCC_SEEK		EQU	IFFCMD_SEEK

        ENDC	; IFF_IFFPARSE_I


Includes/libraries/asl.i

    IFND LIBRARIES_ASL_I
LIBRARIES_ASL_I	SET	1
**
**	$Filename: libraries/asl.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.5 $
**	$Date: 91/11/08 $
**
**	ASL library name and useful definitions.
**
**	(C) Copyright 1989,1990 Charlie Heath
**	(C) Copyright 1989-1999 Amiga, Inc.
**		All Rights Reserved
**

    IFND EXEC_TYPES_I
    INCLUDE "exec/types.i"
    ENDC

    IFND EXEC_LIBRARIES_I
    INCLUDE "exec/libraries.i"
    ENDC

    IFND EXEC_LISTS_I
    INCLUDE "exec/lists.i"
    ENDC

    IFND	UTILITY_TAGITEM_I
    INCLUDE	"utility/tagitem.i"
    ENDC

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

AslName	MACRO
    dc.b	'asl.library',0
    ds.w	0
    ENDM

************************************************************************
* REQUESTER TYPES, these are passed to AllocAslRequest
************************************************************************

ASL_FileRequest		equ	0
ASL_FontRequest		equ	1

*************************************************************************
*									*
*	The ASL file requester data structure...			*
*									*
* The fields described here are for READ ACCESS to the structure	*
* returned by AllocAslRequest( ASL_FileRequest, ... )			*
*									*
* Any modifications MUST be done via TAGS either at the time of		*
* creation by AllocAslRequest(), or when used, via AslRequest()		*
*									*
*************************************************************************

    STRUCTURE FileRequester,0
    STRUCTURE FileRequestr,0		; obsolete spelling
        CPTR	rf_Reserved1
        CPTR	rf_File		; *Filename array (FCHARS+1)
        CPTR	rf_Dir			; *Directory array (DSIZE+1)
        CPTR	rf_Reserved2
        UBYTE	rf_Reserved3
        UBYTE	rf_Reserved4
        APTR	rf_Reserved5
        WORD	rf_LeftEdge
        WORD	rf_TopEdge
        WORD	rf_Width
        WORD	rf_Height
        WORD	rf_Reserved6
        LONG	rf_NumArgs
        APTR	rf_ArgList
        APTR	rf_UserData
        APTR	rf_Reserved7
        APTR	rf_Reserved8
        CPTR	rf_Pat			; *Pattern array

*****************************************************************************
*
* The following defined values are the ASL_FuncFlags tag values which
* are defined for the ASL file request.  These values may be passed
* as a TagItem to modify the way the requester is presented.  Each
* flag value defined has a description of the particular action.
*
* Also related to the ASL_FuncFlags values is the ASL_HookFunc tagitem,
* which provides a callback function to allow the application to
* interact with the requester.	If an ASL_HookFunc TagItem is
* defined, that function will be called as follows:
*
* ULONG rf_Function(ULONG Mask, CPTR Object, CPTR AslRequester)
*
* The Mask value is a copy of the specific ASL_FuncFlags value
* the callback is for; Object is a pointer to a data object.
* AslRequester is a pointer to the requester structure.
*
* For the ASL file and font requesters, two ASL_FuncFlags values
* are currently defined; FILF_DOWILDFUNC and FILF_DOMSGFUNC.
*
*****************************************************************************

* Pass these flags with the tag ASL_FuncFlags
    BITDEF	FIL,PATGAD,0		; Request a pattern gadget
    BITDEF	FIL,MULTISELECT,3	; Request multiple selection returns -
                    ; MUTUAL EXCLUSIVE WITH SAVE
    BITDEF	FIL,NEWIDCMP,4	; Force a new IDCMP (only if rf_Window != NULL)
    BITDEF	FIL,SAVE,5	; Use this bit for SAVE requesters
    BITDEF	FIL,DOMSGFUNC,6	; Called with Object=IDCMP messages
                ;  for other windows of shered port.
                ;  You must return pointer to Object,
                ;  asl will reply the Object for you.
    BITDEF	FIL,DOWILDFUNC,7 ; Called with an AnchorPath,
                 ;	ZERO return accepts.

* Pass these flags with the tag ASL_ExtFlags
    BITDEF	FIL1,NOFILES,0	  ; Do not want a file gadget, no files shown
    BITDEF	FIL1,MATCHDIRS,1  ; Patgad/rf_Pat should screen files AND DIRS

*****************************************************************************
* Obsolete - Use FIL flag names instead
    BITDEF	RF,DOWILDFUNC,7 ; Called me with an AnchorPath,
                ;	ZERO return accepts.
    BITDEF	RF,DOMSGFUNC,6	; You get all IDCMP message not for FileRequest()
    BITDEF	RF,DOCOLOR,5	; This bit is used for FILE SAVE operations.
    BITDEF	RF,NEWIDCMP,4	; Force a new IDCMP (only if rf_Window != NULL)
    BITDEF	RF,MULTISELECT,3 ; Request multiple selection returns -
                ;	MUTUAL EXCLUSIVE WITH DOCOLOR
    BITDEF	RF,PATGAD,0	; Request a pattern gadget
*********************************************************************************

    STRUCTURE FontRequester,0
        CPTR	fo_Reserved1
        CPTR	fo_Reserved2
        APTR	fo_Name		; Returned name
        USHORT	fo_YSize
        UBYTE	fo_Style
        UBYTE	fo_Flags
        UBYTE	fo_FrontPen
        UBYTE	fo_BackPen
        UBYTE	fo_DrawMode
        UBYTE	fo_Reserved3

        APTR	fo_UserData

        SHORT	fo_LeftEdge
        SHORT	fo_TopEdge

        SHORT	fo_Width
        SHORT	fo_Height

******* BITDEFS for ASL_FuncFlags - FONT requester

    BITDEF	FON,FRONTCOLOR,0	; Display Front Color palette selector?
    BITDEF	FON,BACKCOLOR,1		; Display Back Color palette selector?
    BITDEF	FON,STYLES,2		; Display Styles checkboxes?
    BITDEF	FON,DRAWMODE,3		; Display DrawMode NWAY selector?
    BITDEF	FON,FIXEDWIDTH,4	; Only allow fixed-width (SYS) fonts?
    BITDEF	FON,NEWIDCMP,5		; Request a NEW IDCMP port,
                    ;	rather than shared.
    BITDEF	FON,DOMSGFUNC,6		; Called with Object=IDCMP message
                    ;  for other windows sharing port.
                    ; You must return pointer to Object.
                    ; asl will reply the object for you.
    BITDEF	FON,DOWILDFUNC,7	; Called with Object=TextAttr
                    ;	NON-Zero return accepts

****	Tag values for AslRequest()	*************************************

ASL_Dummy	equ	TAG_USER+$80000

ASL_Hail	equ	ASL_Dummy+1
ASL_Window	equ	ASL_Dummy+2

ASL_LeftEdge	equ	ASL_Dummy+3
ASL_TopEdge	equ	ASL_Dummy+4
ASL_Width	equ	ASL_Dummy+5
ASL_Height	equ	ASL_Dummy+6

ASL_HookFunc	equ	ASL_Dummy+7

ASL_File	equ	ASL_Dummy+8
ASL_Dir		equ	ASL_Dummy+9

* OVERLAP HERE file and font stuffskies!!!
ASL_Pattern	equ	ASL_Dummy+10

* Font specific, some overlap!!!
ASL_FontName	equ	ASL_Dummy+10
ASL_FontHeight	equ	ASL_Dummy+11
ASL_FontStyles	equ	ASL_Dummy+12
ASL_FontFlags	equ	ASL_Dummy+13
ASL_FrontPen	equ	ASL_Dummy+14
ASL_BackPen	equ	ASL_Dummy+15
ASL_MinHeight	equ	ASL_Dummy+16
ASL_MaxHeight	equ	ASL_Dummy+17

ASL_OKText	equ	ASL_Dummy+18
ASL_CancelText	equ	ASL_Dummy+19

ASL_FuncFlags	equ	ASL_Dummy+20

ASL_ModeList	equ	ASL_Dummy+21

*** Pass the FIL1 extended flag bits using this tag
ASL_ExtFlags1	equ	ASL_Dummy+22

    ENDC	!LIBRARIES_ASL_I


Includes/libraries/dosextens.i

    IFND	LIBRARIES_DOSEXTENS_I
LIBRARIES_DOSEXTENS_I SET	1
**
**	$Filename: libraries/dosextens.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.2 $
**	$Date: 90/07/12 $
**
**	DOS structures not needed for the casual AmigaDOS user
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND	DOS_DOSEXTENS_I
    INCLUDE	"dos/dosextens.i"
    ENDC

    ENDC	; LIBRARIES_DOSEXTENS_I


Includes/libraries/mathffp.h

#ifndef	LIBRARIES_MATHFFP_H
#define	LIBRARIES_MATHFFP_H 1
/*
**	$Filename: libraries/mathffp.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.2 $
**	$Date: 90/05/01 $
**
**	general floating point declarations
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef PI
#define PI	  ((float) 3.141592653589793)
#endif
#define TWO_PI	  (((float) 2) * PI)
#define PI2	  (PI / ((float) 2))
#define PI4	  (PI / ((float) 4))
#ifndef E
#define E	  ((float) 2.718281828459045)
#endif
#define LOG10	  ((float) 2.302585092994046)

#define FPTEN	  ((float) 10.0)
#define FPONE	  ((float) 1.0)
#define FPHALF	  ((float) 0.5)
#define FPZERO	  ((float) 0.0)

#define trunc(x)  ((int) (x))
#define round(x)  ((int) ((x) + 0.5))
#define itof(i)   ((float) (i))

#define	fabs	SPAbs
#define floor	SPFloor
#define	ceil	SPCeil

#define	tan	SPTan
#define	atan	SPAtan
#define cos	SPCos
#define acos	SPAcos
#define sin	SPSin
#define asin	SPAsin
#define exp	SPExp
#define pow(a,b)	SPPow((b),(a))
#define log	SPLog
#define log10	SPLog10
#define sqrt	SPSqrt

#define	sinh	SPSinh
#define cosh	SPCosh
#define tanh	SPTanh

int	 SPFix();			  /* Basic math functions */
float	 SPFlt();
int	 SPCmp();
int	 SPTst();
float	 SPAbs();
float	 SPFloor();
float	 SPCeil();
#ifndef abs
float	 abs();
#endif
float	 SPNeg();
float	 SPAdd();
float	 SPSub();
float	 SPMul();
float	 SPDiv();

float	 SPAsin(),  SPAcos(),  SPAtan();  /* Transcendental math functions */
float	 SPSin(),   SPCos(),   SPTan(),   SPSincos();
float	 SPSinh(),  SPCosh(),  SPTanh();
float	 SPExp(),   SPLog(),   SPLog10(), SPPow();
float	 SPSqrt(),  SPFieee();

float	 afp(),    dbf();		  /* Math conversion functions */

#endif	/* LIBRARIES_MATHFFP_H */


Includes/libraries/commodities.h

#ifndef LIBRARIES_COMMODITIES_H
#define LIBRARIES_COMMODITIES_H

/*
**   $Filename: libraries/commodities.h $
**   $Release: 2.04 Includes, V37.4 $
**   $Revision: 37.1 $
**   $Date: 91/04/15 $
**
**   Commodities definitions.
**
**   (C) Copyright 1988-1999 Amiga, Inc.
**	All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

/*************************
 * object creation macros
 *************************/
#define CxFilter(d)	    CreateCxObj((LONG)CX_FILTER, (LONG) d, 0)
#define CxTypeFilter(type)  CreateCxObj((LONG)CX_TYPEFILTER, (LONG) type, 0)
#define CxSender(port,id)   CreateCxObj((LONG)CX_SEND, (LONG) port, (LONG) id)
#define CxSignal(task,sig)  CreateCxObj((LONG)CX_SIGNAL,(LONG) task, (LONG) sig)
#define CxTranslate(ie)     CreateCxObj((LONG)CX_TRANSLATE, (LONG) ie, 0)
#define CxDebug(id)	    CreateCxObj((LONG)CX_DEBUG, (LONG) id, 0)
#define CxCustom(action,id) CreateCxObj((LONG)CX_CUSTOM,(LONG)action,(LONG)id)

/***************
 * Broker stuff
 ***************/

/* buffer sizes   */
#define CBD_NAMELEN	24
#define CBD_TITLELEN	40
#define CBD_DESCRLEN	40

/* CxBroker errors   */
#define CBERR_OK	0	 /* No error			     */
#define CBERR_SYSERR	1	 /* System error , no memory, etc    */
#define CBERR_DUP	2	 /* uniqueness violation	     */
#define CBERR_VERSION	3	 /* didn't understand nb_VERSION     */

#define NB_VERSION	5	 /* Version of NewBroker structure   */

struct NewBroker {
   BYTE     nb_Version;	 /* set to NB_VERSION		     */
   BYTE     *nb_Name;
   BYTE     *nb_Title;
   BYTE     *nb_Descr;
   SHORT    nb_Unique;
   SHORT    nb_Flags;
   BYTE     nb_Pri;
   struct MsgPort   *nb_Port;
   WORD     nb_ReservedChannel;  /* plans for later port sharing     */
};

/* Flags for nb_Unique */
#define NBU_DUPLICATE	0
#define NBU_UNIQUE	1	 /* will not allow duplicates	     */
#define NBU_NOTIFY	2	 /* sends CXM_UNIQUE to existing broker */

/* Flags for nb_Flags */
#define   COF_SHOW_HIDE 4

/********
 * cxusr
 ********/

/** Fake data types for system private objects	 */
#ifndef CX_H
typedef LONG   CxObj;
typedef LONG   CxMsg;
#endif

/* Pointer to Function returning Long	*/
typedef LONG   (*PFL)();

/********************************/
/** Commodities Object Types   **/
/********************************/
#define CX_INVALID	0     /* not a valid object (probably null)  */
#define CX_FILTER	1     /* input event messages only	     */
#define CX_TYPEFILTER	2     /* filter on message type	     */
#define CX_SEND	3     /* sends a message		     */
#define CX_SIGNAL	4     /* sends a signal		     */
#define CX_TRANSLATE	5     /* translates IE into chain	     */
#define CX_BROKER	6     /* application representative	     */
#define CX_DEBUG	7     /* dumps kprintf to serial port	     */
#define CX_CUSTOM	8     /* application provids function	     */
#define CX_ZERO	9     /* system terminator node	     */

/*****************/
/** CxMsg types **/
/*****************/
#define CXM_UNIQUE   (1 << 4) /* sent down broker by CxBroker()      */
/* Obsolete: subsumed by CXM_COMMAND (below)   */

/* Messages of this type rattle around the Commodities input network.
 * They will be sent to you by a Sender object, and passed to you
 * as a synchronous function call by a Custom object.
 *
 * The message port or function entry point is stored in the object,
 * and the ID field of the message will be set to what you arrange
 * issuing object.
 *
 * The Data field will point to the input event triggering the
 * message.
 */
#define CXM_IEVENT   (1 << 5)

/* These messages are sent to a port attached to your Broker.
 * They are sent to you when the controller program wants your
 * program to do something.  The ID field identifies the command.
 *
 * The Data field will be used later.
 */
#define CXM_COMMAND   (1 << 6)

/* ID values   */
#define CXCMD_DISABLE	(15)  /* please disable yourself       */
#define CXCMD_ENABLE	(17)  /* please enable yourself        */
#define CXCMD_APPEAR	(19)  /* open your window, if you can  */
#define CXCMD_DISAPPEAR (21)  /* go dormant		       */
#define CXCMD_KILL	(23)  /* go away for good	       */
#define CXCMD_UNIQUE	(25)  /* someone tried to create a broker
                   * with your name.  Suggest you Appear.
                   */
#define CXCMD_LIST_CHG	(27)  /* Used by Exchange program. Someone */
                  /* has changed the broker list	   */

/* return values for BrokerCommand(): */
#define CMDE_OK	(0)
#define CMDE_NOBROKER	(-1)
#define CMDE_NOPORT	(-2)
#define CMDE_NOMEM	(-3)

/* IMPORTANT NOTE:
 * Only CXM_IEVENT messages are passed through the input network.
 *
 * Other types of messages are sent to an optional port in your broker.
 *
 * This means that you must test the message type in your message handling,
 * if input messages and command messages come to the same port.
 *
 * Older programs have no broker port, so processing loops which
 * make assumptions about type won't encounter the new message types.
 *
 * The TypeFilter CxObject is hereby obsolete.
 *
 * It is less convenient for the application, but eliminates testing
 * for type of input messages.
 */

/**********************************************************/
/** CxObj Error Flags (return values from CxObjError())  **/
/**********************************************************/
#define COERR_ISNULL	   1  /* you called CxError(NULL)	     */
#define COERR_NULLATTACH   2  /* someone attached NULL to my list    */
#define COERR_BADFILTER    4  /* a bad filter description was given  */
#define COERR_BADTYPE	   8  /* unmatched type-specific operation   */

/*****
 * ix
 *****/

#define IX_VERSION   2

struct InputXpression {
   UBYTE   ix_Version;	   /* must be set to IX_VERSION  */
   UBYTE   ix_Class;	   /* class must match exactly	 */

   UWORD   ix_Code;
   UWORD   ix_CodeMask;    /* normally used for UPCODE	 */

   UWORD   ix_Qualifier;
   UWORD   ix_QualMask;
   UWORD   ix_QualSame;    /* synonyms in qualifier	 */
   };
typedef struct InputXpression IX;

/* QualSame identifiers */
#define IXSYM_SHIFT  1	   /* left- and right- shift are equivalent	*/
#define IXSYM_CAPS   2	   /* either shift or caps lock are equivalent	*/
#define IXSYM_ALT    4	   /* left- and right- alt are equivalent	*/

/* corresponding QualSame masks */
#define IXSYM_SHIFTMASK (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)
#define IXSYM_CAPSMASK	(IXSYM_SHIFTMASK    | IEQUALIFIER_CAPSLOCK)
#define IXSYM_ALTMASK	(IEQUALIFIER_LALT   | IEQUALIFIER_RALT)

#define IX_NORMALQUALS	0x7FFF;/* for QualMask field: avoid RELATIVEMOUSE */

/* matches nothing   */
#define NULL_IX(I)   ((I)->ix_Class == IECLASS_NULL)

#endif


Includes/libraries/dos_lib.i

    IFND	LIBRARIES_DOS_LIB_I
LIBRARIES_DOS_LIB_I	SET	1
**
**	$Filename: libraries/dos_lib.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.3 $
**	$Date: 90/11/02 $
**
**	Library interface offsets for DOS library
**	Retained only for compatibility
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND	DOS_DOS_LIB_I
    INCLUDE	"dos/dos_lib.i"
    ENDC

    ENDC	; LIBRARIES_DOS_LIB_I


Includes/libraries/mathieeedp.h

#ifndef	LIBRARIES_MATHIEEEDP_H
#define	LIBRARIES_MATHIEEEDP_H
/*
**	$Filename: libraries/mathieeedp.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.1 $
**	$Date: 90/07/13 $
**	Include file to use for <math.h>
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef PI
#define PI	((double)	3.141592653589793))
#endif

#define TWO_PI	(((double)	2)	* PI)
#define PI2	(PI/((double)2))
#define PI4	(PI/((double)4))

#ifndef	E
#define	E	((double)	2.718281828459045)
#endif

#define LOG10	((double)	2.302585092994046)
#define FPTEN	((double)	10.0)
#define	FPONE	((double)	1.0)
#define FPHALF	((double)	0.5)
#define FPZERO	((double)	0.0)
#define trunc(x)	((int)	(x))
#define round(x)	((int)	((x) + 0.5))
#define itof(i)		((double) (i))

#define	fabs	IEEEDPAbs
#define floor	IEEEDPFloor
#define	ceil	IEEEDPCeil

#define	tan	IEEEDPTan
#define	atan	IEEEDPAtan
#define cos	IEEEDPCos
#define acos	IEEEDPAcos
#define sin	IEEEDPSin
#define asin	IEEEDPAsin
#define exp	IEEEDPExp
#define pow(a,b)	IEEEDPPow((b),(a))
#define log	IEEEDPLog
#define log10	IEEEDPLog10
#define sqrt	IEEEDPSqrt

#define	sinh	IEEEDPSinh
#define cosh	IEEEDPCosh
#define tanh	IEEEDPTanh

double	IEEEDPTan(),IEEEDPAtan();
double	IEEEDPCos(),IEEEDPACos();
double	IEEEDPSin(),IEEEDPASin();
double	IEEEDPExp(),IEEEDPLog();
double	IEEEDPSqrt();
double	IEEEDPLog10(),IEEEDPPow();
double	IEEEDPSincos();
double	IEEEDPSinh(),IEEEDPCosh(),IEEEDPTanh();
float	IEEEDPTieee();
double	IEEEDPFieee();

int	IEEEDPFix();
int	IEEEDPCmp(),IEEEDPTst();
double	IEEEDPFlt();
double	IEEEDPAbs();
double	IEEEDPNeg();
double	IEEEDPAdd();
double	IEEEDPSub();
double	IEEEDPMul();
double	IEEEDPDiv();
double	IEEEDPFloor();
double	IEEEDPCeil();

#endif	/* LIBRARIES_MATHIEEEDP_H */


Includes/libraries/commodities.i

    IFND LIBRARIES_COMMODITIES_I
LIBRARIES_COMMODITIES_I	SET 1
**   $Filename: libraries/commodities.i $
**   $Release: 2.04 Includes, V37.4 $
**   $Revision: 37.0 $
**   $Date: 91/04/15 $
**
**   Commodities definitions
**
**   (C) Copyright 1988-1999 Amiga, Inc.
**	All Rights Reserved
*-----------------------------------------------------------*

    IFND EXEC_TYPES_I
    INCLUDE "exec/types.i"

    ENDC
    IFND DEVICES_INPUTEVENT_I
    INCLUDE "devices/inputevent.i"
    ENDC

***************
* Broker stuff
***************

* buffer sizes
CBD_NAMELEN	EQU	24
CBD_TITLELEN	EQU	40
CBD_DESCRLEN	EQU	40

* CxBroker errors
CBERR_OK	EQU	0	 ; No error
CBERR_SYSERR	EQU	1	 ; System error , no memory, etc
CBERR_DUP	EQU	2	 ; uniqueness violation
CBERR_VERSION	EQU	3	 ; didn't understand nb_VERSION
NB_VERSION 	EQU	5        ; Version of NewBroker structure

    STRUCTURE NewBroker,0
       BYTE     	nb_Version         ; set to NB_VERSION
       BYTE		nb_Reserve1	; for alignment
       APTR     	nb_Name
       APTR     	nb_Title
       APTR     	nb_Descr
       WORD    	nb_Unique
       WORD		nb_Flags
       BYTE 	nb_Pri
       BYTE		nb_Reserve2	; for alignment
       APTR		nb_Port
       WORD     	nb_ReservedChannel 	;plans for later port sharing

***********************
* Flags for nb_Unique
***********************

NBU_DUPLICATE 	EQU	   0
NBU_UNIQUE 	EQU	   1        ; will not allow duplicates
NBU_NOTIFY 	EQU	   2        ; sends CXM_UNIQUE to existing broker

* Flags for nb_Flags
COF_SHOW_HIDE 	EQU	   4

********
* cxusr
********

********************************
** Commodities Object Types   **
********************************
CX_INVALID 	EQU	0     ; not a valid object (probably null)
CX_FILTER 	EQU	1     ; input event messages only
CX_TYPEFILTER 	EQU	2     ; filter on message type
CX_SEND 	EQU	3     ; sends a message
CX_SIGNAL 	EQU	4     ; sends a signal
CX_TRANSLATE 	EQU	5     ; translates IE into chain
CX_BROKER 	EQU	6     ; application representative
CX_DEBUG 	EQU	7     ; dumps kprintf to serial port
CX_CUSTOM 	EQU	8     ; application provids function
CX_ZERO 	EQU	9     ; system terminator node

*****************
** CxMsg types **
*****************
CXM_UNIQUE 	EQU	   $10 ; (1 << 4) sent down broker by CxBroker()
; Obsolete: subsumed by CXM_COMMAND (below)

* Messages of this type rattle around the Commodities input network.
* They will be sent to you by a Sender object, and passed to you
* as a synchronous function call by a Custom object.
*
* The message port or function entry point is stored in the object,
* and the ID field of the message will be set to what you arrange
* issuing object.
*
* The Data field will point to the input event triggering the
* message.

CXM_IEVENT 	EQU	   $20 ;(1 << 5)

* These messages are sent to a port attached to your Broker.
* They are sent to you when the controller program wants your
* program to do something.  The ID field identifies the command.
*
* The Data field will be used later.
*

CXM_COMMAND 	EQU	   $40 ;(1 << 6)

* ID values

CXCMD_DISABLE 	EQU	15  ; please disable yourself
CXCMD_ENABLE 	EQU	17  ; please enable yourself
CXCMD_APPEAR 	EQU	19  ; open your window, if you can
CXCMD_DISAPPEAR EQU	21  ; go dormant
CXCMD_KILL 	EQU	23  ; go away for good
CXCMD_UNIQUE 	EQU	25  ; someone tried to create a brok
                            ; with your name.  Suggest you Appear.
CXCMD_LIST_CHG 	EQU	27  ; Used by Exchange program. Someone
                            ; has changed the broker list

* return values for BrokerCommand()
CMDE_OK 	EQU        0
CMDE_NOBROKER 	EQU	  -1
CMDE_NOPORT 	EQU	  -2
CMDE_NOMEM 	EQU	  -3

* IMPORTANT NOTE:
* Only CXM_IEVENT messages are passed through the input network.
*
* Other types of messages are sent to an optional port in your broker.
*
* This means that you must test the message type in your message handling,
* if input messages and command messages come to the same port.
*
* Older programs have no broker port, so processing loops which
* make assumptions about type won't encounter the new message types.
*
* The TypeFilter CxObject is hereby obsolete.
*
* It is less convenient for the application, but eliminates testing
* for type of input messages.

**********************************************************
** CxObj Error Flags (return values from CxObjError())	**
**********************************************************

COERR_ISNULL		EQU	1  ; you called CxError(NULL)
COERR_NULLATTACH	EQU	2  ; someone attached NULL to my list
COERR_BADFILTER	EQU	4  ; a bad filter description was given
COERR_BADTYPE		EQU	8  ; unmatched type-specific operation

******************************
* Input Expression structure *
******************************

IX_VERSION	EQU	   2

    STRUCTURE InputXpression,0

       UBYTE   ix_Version	   ; must be set to IX_VERSION
       UBYTE   ix_Class	   ; class must match exactly

       UWORD   ix_Code	   ; Bits that we want

       UWORD   ix_CodeMask	   ; Set bits here to indicate
                   ; which bits in ix_Code are
                   ; don't care bits.

       UWORD   ix_Qualifier    ; Bits that we want

       UWORD   ix_QualMask     ; Set bits here to indicate
                               ; which bits in ix_Qualifier
                   ; are don't care bits

       UWORD   ix_QualSame	  ; synonyms in qualifier

    LABEL	ix_SIZEOF

* QualSame identifiers
IXSYM_SHIFT	EQU	  1	; left- and right- shift are equivalent
IXSYM_CAPS	EQU	  2	; either shift or caps lock are equivalent
IXSYM_ALT	EQU	  4	; left- and right- alt are equivalent

* corresponding QualSame masks
IXSYM_SHIFTMASK EQU	 IEQUALIFIER_LSHIFT!IEQUALIFIER_RSHIFT
IXSYM_CAPSMASK		EQU	 IXSYM_SHIFTMASK!IEQUALIFIER_CAPSLOCK
IXSYM_ALTMASK	EQU	 IEQUALIFIER_LALT!IEQUALIFIER_RALT

IX_NORMALQUALS		EQU	  $7FFF  ;for QualMask field: avoid RELATIVEMOUSE

    ENDC	; LIBRARIES_COMMODITIES_I


Includes/libraries/expansion.h

#ifndef LIBRARIES_EXPANSION_H
#define	LIBRARIES_EXPANSION_H
/*
**	$Filename: libraries/expansion.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.7 $
**	$Date: 90/05/28 $
**
**	External definitions for expansion.library
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#define EXPANSIONNAME	"expansion.library"

/* flags for the AddDosNode() call */
#define ADNB_STARTPROC	0
#define ADNF_STARTPROC	(1L<<0)

#endif /* LIBRARIES_EXPANSION_H */


Includes/libraries/mathieeesp.h

#ifndef	LIBRARIES_MATHIEEESP_H
#define	LIBRARIES_MATHIEEESP_H
/*
**	$Filename: libraries/mathieeesp.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.1 $
**	$Date: 90/07/13 $
**
**	Include file to use for <math.h>
**
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef PI
#define PI	((float)	3.141592653589793))
#endif

#define TWO_PI	(((float)	2)	* PI)
#define PI2	(PI/((float)2))
#define PI4	(PI/((float)4))

#ifndef	E
#define	E	((float)	2.718281828459045)
#endif

#define LOG10	((float)	2.302585092994046)
#define FPTEN	((float)	10.0)
#define	FPONE	((float)	1.0)
#define FPHALF	((float)	0.5)
#define FPZERO	((float)	0.0)
#define trunc(x)	((int)	(x))
#define round(x)	((int)	((x) + 0.5))
#define itof(i)		((float) (i))

#define	fabs	IEEESPAbs
#define floor	IEEESPFloor
#define	ceil	IEEESPCeil

#define	tan	IEEESPTan
#define	atan	IEEESPAtan
#define cos	IEEESPCos
#define acos	IEEESPAcos
#define sin	IEEESPSin
#define asin	IEEESPAsin
#define exp	IEEESPExp
#define pow(a,b)	IEEESPPow((b),(a))
#define log	IEEESPLog
#define log10	IEEESPLog10
#define sqrt	IEEESPSqrt

#define	sinh	IEEESPSinh
#define cosh	IEEESPCosh
#define tanh	IEEESPTanh

float	IEEESPTan(),IEEESPAtan();
float	IEEESPCos(),IEEESPACos();
float	IEEESPSin(),IEEESPASin();
float	IEEESPExp(),IEEESPLog();
float	IEEESPSqrt();
float	IEEESPLog10(),IEEESPPow();
float	IEEESPSincos();
float	IEEESPSinh(),IEEESPCosh(),IEEESPTanh();
float	IEEESPTieee();
float	IEEESPFieee();

int	IEEESPFix();
int	IEEESPCmp(),IEEESPTst();
float	IEEESPFlt();
float	IEEESPAbs();
float	IEEESPNeg();
float	IEEESPAdd();
float	IEEESPSub();
float	IEEESPMul();
float	IEEESPDiv();
float	IEEESPFloor();
float	IEEESPCeil();

#endif	/* LIBRARIES_MATHIEEESP_H */


Includes/libraries/configregs.h

#ifndef LIBRARIES_CONFIGREGS_H
#define LIBRARIES_CONFIGREGS_H
/*
**	$Filename: libraries/configregs.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.13 $
**	$Date: 91/02/15 $
**
**	AutoConfig (tm) hardware register and bit definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include "exec/types.h"
#endif	/* EXEC_TYPES_H */

/*
** AutoConfig (tm) boards each contain a 32 byte "ExpansionRom" area that is
** read by the system software at configuration time.  Configuration of each
** board starts when the ConfigIn* signal is passed from the previous board
** (or from the system for the first board).  Each board will present it's
** ExpansionRom structure at location $00E80000 to be read by the system.
** This file defines the appearance of the ExpansionRom area.
**
** Expansion boards are actually organized such that only one nybble per
** 16 bit word contains valid information.  The low nybbles of each
** word are combined to fill the structure below. (This table is structured
** as LOGICAL information.  This means that it never corresponds exactly
** with a physical implementation.)
**
** The ExpansionRom space is further split into two regions:  The first 16
** bytes are read-only.  Except for the er_type field, this area is inverted
** by the system software when read in.  The second 16 bytes contain the
** control portion, where all read/write registers are located.
**
** The system builds one "ConfigDev" structure for each board found.  The
** list of boards can be examined using the expansion.library/FindConfigDev
** function.
**
** A special "hacker" Manufacturer ID number is reserved for test use:
** 2011 ($7DB).  When inverted this will look like $F824.
*/

struct ExpansionRom {		/* -First 16 bytes of the expansion ROM */
    UBYTE	er_Type;	/* Board type, size and flags */
    UBYTE	er_Product;	/* Product number, assigned by manufacturer */
    UBYTE	er_Flags;	/* Flags */
    UBYTE	er_Reserved03;	/* Must be zero ($ff inverted) */
    UWORD	er_Manufacturer; /* Unique ID,ASSIGNED BY AMIGA, INC.! */
    ULONG	er_SerialNumber; /* Available for use by manufacturer */
    UWORD	er_InitDiagVec; /* Offset to optional "DiagArea" structure */
    UBYTE	er_Reserved0c;
    UBYTE	er_Reserved0d;
    UBYTE	er_Reserved0e;
    UBYTE	er_Reserved0f;
};

/*
** Note that use of the ec_BaseAddress register is tricky.  The system
** will actually write twice.  First the low order nybble is written
** to the ec_BaseAddress register+2 (D15-D12).	Then the entire byte is
** written to ec_BaseAddress (D15-D8).	This allows writing of a byte-wide
** address to nybble size registers.
*/

struct ExpansionControl {	/* -Second 16 bytes of the expansion ROM */
    UBYTE	ec_Interrupt;	/* Optional interrupt control register */
    UBYTE	ec_Z3_HighBase; /* Zorro III   : Config address bits 24-31 */
    UBYTE	ec_BaseAddress; /* Zorro II/III: Config address bits 16-23 */
    UBYTE	ec_Shutup;	/* The system writes here to shut up a board */
    UBYTE	ec_Reserved14;
    UBYTE	ec_Reserved15;
    UBYTE	ec_Reserved16;
    UBYTE	ec_Reserved17;
    UBYTE	ec_Reserved18;
    UBYTE	ec_Reserved19;
    UBYTE	ec_Reserved1a;
    UBYTE	ec_Reserved1b;
    UBYTE	ec_Reserved1c;
    UBYTE	ec_Reserved1d;
    UBYTE	ec_Reserved1e;
    UBYTE	ec_Reserved1f;
};

/*
** many of the constants below consist of a triplet of equivalent
** definitions: xxMASK is a bit mask of those bits that matter.
** xxBIT is the starting bit number of the field.  xxSIZE is the
** number of bits that make up the definition.	This method is
** used when the field is larger than one bit.
**
** If the field is only one bit wide then the xxB_xx and xxF_xx convention
** is used (xxB_xx is the bit number, and xxF_xx is mask of the bit).
*/

/* manifest constants */
#define E_SLOTSIZE		0x10000
#define E_SLOTMASK		0xffff
#define E_SLOTSHIFT		16

/* these define the free regions of Zorro memory space.
** THESE MAY WELL CHANGE FOR FUTURE PRODUCTS!
*/
#define E_EXPANSIONBASE	0x00e80000	/* Zorro II  config address */
#define EZ3_EXPANSIONBASE	0xff000000	/* Zorro III config address */

#define E_EXPANSIONSIZE	0x00080000	/* Zorro II  I/O type cards */
#define E_EXPANSIONSLOTS	8

#define E_MEMORYBASE		0x00200000	/* Zorro II  8MB space */
#define E_MEMORYSIZE		0x00800000
#define E_MEMORYSLOTS		128

#define EZ3_CONFIGAREA		0x40000000	/* Zorro III space */
#define EZ3_CONFIGAREAEND	0x7FFFFFFF	/* Zorro III space */
#define EZ3_SIZEGRANULARITY	0x00080000	/* 512K increments */

/**** er_Type definitions (ttldcmmm) ***************************************/

/* er_Type board type bits -- the OS ignores "old style" boards */
#define ERT_TYPEMASK		0xc0	/* Bits 7-6 */
#define ERT_TYPEBIT		6
#define ERT_TYPESIZE		2
#define ERT_NEWBOARD		0xc0
#define ERT_ZORROII		ERT_NEWBOARD
#define ERT_ZORROIII		0x80

/* other bits defined in er_Type */
#define ERTB_MEMLIST		5   /* Link RAM into free memory list */
#define ERTB_DIAGVALID		4   /* ROM vector is valid */
#define ERTB_CHAINEDCONFIG	3   /* Next config is part of the same card */

#define ERTF_MEMLIST		(1<<5)
#define ERTF_DIAGVALID		(1<<4)
#define ERTF_CHAINEDCONFIG	(1<<3)

/* er_Type field memory size bits */
#define ERT_MEMMASK		0x07	/* Bits 2-0 */
#define ERT_MEMBIT		0
#define ERT_MEMSIZE		3

/**** er_Flags byte -- for those things that didn't fit into the type byte ****/
/**** the hardware stores this byte in inverted form			   ****/
#define ERFF_MEMSPACE		(1<<7)	/* Wants to be in 8 meg space. */
#define ERFB_MEMSPACE		7	/* (NOT IMPLEMENTED) */

#define ERFF_NOSHUTUP		(1<<6)	/* Board can't be shut up */
#define ERFB_NOSHUTUP		6

#define ERFF_EXTENDED		(1<<5)	/* Zorro III: Use extended size table */
#define ERFB_EXTENDED		5	/*	      for bits 0-2 of er_Type */
                    /* Zorro II : Must be 0 */

#define ERFF_ZORRO_III		(1<<4)	/* Zorro III: must be 1 */
#define ERFB_ZORRO_III		4	/* Zorro II : must be 0 */

#define ERT_Z3_SSMASK		0x0F	/* Bits 3-0.  Zorro III Sub-Size.  How */
#define ERT_Z3_SSBIT		0	/* much space the card actually uses   */
#define ERT_Z3_SSSIZE		4	/* (regardless of config granularity)  */
                    /* Zorro II : must be 0	       */

/* ec_Interrupt register (unused) ********************************************/
#define ECIB_INTENA		1
#define ECIB_RESET		3
#define ECIB_INT2PEND		4
#define ECIB_INT6PEND		5
#define ECIB_INT7PEND		6
#define ECIB_INTERRUPTING	7

#define ECIF_INTENA		(1<<1)
#define ECIF_RESET		(1<<3)
#define ECIF_INT2PEND		(1<<4)
#define ECIF_INT6PEND		(1<<5)
#define ECIF_INT7PEND		(1<<6)
#define ECIF_INTERRUPTING	(1<<7)

/* figure out amount of memory needed by this box/board */
#define ERT_MEMNEEDED(t)	\
    (((t)&ERT_MEMMASK)? 0x10000 << (((t)&ERT_MEMMASK) -1) : 0x800000 )

/* same as ERT_MEMNEEDED, but return number of slots */
#define ERT_SLOTSNEEDED(t)	\
    (((t)&ERT_MEMMASK)? 1 << (((t)&ERT_MEMMASK)-1) : 0x80 )

/* convert a expansion slot number into a memory address */
#define EC_MEMADDR(slot)		((slot) << (E_SLOTSHIFT) )

/* a kludge to get the byte offset of a structure */
#define EROFFSET(er)	((int)&((struct ExpansionRom *)0)->er)
#define ECOFFSET(ec)	\
 (sizeof(struct ExpansionRom)+((int)&((struct ExpansionControl *)0)->ec))

/***************************************************************************
**
** these are the specifications for the diagnostic area.  If the Diagnostic
** Address Valid bit is set in the Board Type byte (the first byte in
** expansion space) then the Diag Init vector contains a valid offset.
**
** The Diag Init vector is actually a word offset from the base of the
** board.  The resulting address points to the base of the DiagArea
** structure.  The structure may be physically implemented either four,
** eight, or sixteen bits wide.  The code will be copied out into
** ram first before being called.
**
** The da_Size field, and both code offsets (da_DiagPoint and da_BootPoint)
** are offsets from the diag area AFTER it has been copied into ram, and
** "de-nibbleized" (if needed).  (In other words, the size is the size of
** the actual information, not how much address space is required to
** store it.)
**
** All bits are encoded with uninverted logic (e.g. 5 volts on the bus
** is a logic one).
**
** If your board is to make use of the boot facility then it must leave
** its config area available even after it has been configured.  Your
** boot vector will be called AFTER your board's final address has been
** set.
**
****************************************************************************/

struct DiagArea {
    UBYTE	da_Config;	/* see below for definitions */
    UBYTE	da_Flags;	/* see below for definitions */
    UWORD	da_Size;	/* the size (in bytes) of the total diag area */
    UWORD	da_DiagPoint;	/* where to start for diagnostics, or zero */
    UWORD	da_BootPoint;	/* where to start for booting */
    UWORD	da_Name;	/* offset in diag area where a string */
                /*   identifier can be found (or zero if no */
                /*   identifier is present). */

    UWORD	da_Reserved01;	/* two words of reserved data.	must be zero. */
    UWORD	da_Reserved02;
};

/* da_Config definitions */
/*
** DAC_BYTEWIDE can be simulated using DAC_NIBBLEWIDE.
*/
#define DAC_BUSWIDTH	0xC0 /* two bits for bus width */
#define DAC_NIBBLEWIDE	0x00
#define DAC_BYTEWIDE	0x40 /* BUG: Will not work under V34 Kickstart! */
#define DAC_WORDWIDE	0x80

#define DAC_BOOTTIME	0x30	/* two bits for when to boot */
#define DAC_NEVER	0x00	/* obvious */
#define DAC_CONFIGTIME	0x10	/* call da_BootPoint when first configing */
                /*   the device */
#define DAC_BINDTIME	0x20	/* run when binding drivers to boards */

/*
**
** These are the calling conventions for the diagnostic callback
** (from da_DiagPoint):
**
** A7 -- points to at least 2K of stack
** A6 -- ExecBase
** A5 -- ExpansionBase
** A3 -- your board's ConfigDev structure
** A2 -- Base of diag/init area that was copied
** A0 -- Base of your board
**
** Your board must return a value in D0.  If this value is NULL, then
** the diag/init area that was copied in will be returned to the free
** memory pool.
*/

#endif /* LIBRARIES_CONFIGREGS_H */


Includes/libraries/expansion.i

    IFND	LIBRARIES_EXPANSION_I
LIBRARIES_EXPANSION_I	SET	1
**
**	$Filename: libraries/expansion.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.6 $
**	$Date: 90/11/05 $
**
**	External definitions for expansion.library
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND	EXEC_TYPES_I
    INCLUDE	"exec/types.i"
    ENDC	;EXEC_TYPES_I

EXPANSIONNAME	MACRO
        dc.b	'expansion.library',0
        ENDM

;flag for the AddDosNode() call
    BITDEF	ADN,STARTPROC,0

    ENDC	;LIBRARIES_EXPANSION_I


Includes/libraries/mathlibrary.h

#ifndef	LIBRARIES_MATHLIBRARY_H
#define	LIBRARIES_MATHLIBRARY_H
/*
**	$Filename: libraries/mathlibrary.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.6 $
**	$Date: 90/07/13 $
**
**	Data structure returned by OpenLibrary of:
**	mathieeedoubbas.library,mathieeedoubtrans.library
**	mathieeesingbas.library,mathieeesingtrans.library
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_LIBRARIES_H
#include <exec/libraries.h>
#endif

struct MathIEEEBase
{
    struct Library MathIEEEBase_LibNode;
    unsigned char	MathIEEEBase_reserved[18];
    int	(*MathIEEEBase_TaskOpenLib)();
    int	(*MathIEEEBase_TaskCloseLib)();
    /*	This structure may be extended in the future */
};
/*
* Math resources may need to know when a program opens or closes this
* library. The functions TaskOpenLib and TaskCloseLib are called when
* a task opens or closes this library. They are initialized to point to
* local initialization pertaining to 68881 stuff if 68881 resources
* are found. To override the default the vendor must provide appropriate
* hooks in the MathIEEEResource. If specified, these will be called
* when the library initializes.
*/

#endif	/* LIBRARIES_MATHLIBRARY_H */


Includes/libraries/configregs.i

    IFND	LIBRARIES_CONFIGREGS_I
LIBRARIES_CONFIGREGS_I	SET	1
**
**	$Filename: libraries/configregs.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.11 $
**	$Date: 90/11/03 $
**
**	AutoConfig (tm) hardware register and bit definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND	EXEC_TYPES_I
    INCLUDE	"exec/types.i"
    ENDC	;EXEC_TYPES_I

**
** AutoConfig (tm) boards each contain a 32 byte "ExpansionRom" area that is
** read by the system software at configuration time.  Configuration of each
** board starts when the ConfigIn* signal is passed from the previous board
** (or from the system for the first board).  Each board will present it's
** ExpansionRom structure at location $00E80000 to be read by the system.
** This file defines the appearance of the ExpansionRom area.
**
** Expansion boards are actually organized such that only one nybble per
** 16 bit word contains valid information.  The low nybbles of each
** word are combined to fill the structure below. (This table is structured
** as LOGICAL information.  This means that it never corresponds exactly
** with a physical implementation.)
**
** The ExpansionRom space is further split into two regions:  The first 16
** bytes are read-only.  Except for the er_type field, this area is inverted
** by the system software when read in.  The second 16 bytes contain the
** control portion, where all read/write registers are located.
**
** The system builds one "ConfigDev" structure for each board found.  The
** list of boards can be examined using the expansion.library/FindConfigDev
** function.
**
** A special "hacker" Manufacturer ID number is reserved for test use:
** 2011 ($7DB).  When inverted this will look like $F824.
**

 STRUCTURE ExpansionRom,0	;-First 16 bytes of the expansion ROM
    UBYTE	er_Type 	;Board type, size and flags
    UBYTE	er_Product	;Product number, assigned by manufacturer
    UBYTE	er_Flags	;Flags
    UBYTE	er_Reserved03	;Must be zero ($ff inverted)
    UWORD	er_Manufacturer ;Unique ID,ASSIGNED BY AMIGA, INC.!
    ULONG	er_SerialNumber ;Available for use by manufacturer
    UWORD	er_InitDiagVec	;Offset to optional "DiagArea" structure
    UBYTE	er_Reserved0c
    UBYTE	er_Reserved0d
    UBYTE	er_Reserved0e
    UBYTE	er_Reserved0f
    LABEL	ExpansionRom_SIZEOF

**
** Note that use of the ec_BaseAddress register is tricky.  The system
** will actually write twice.  First the low order nybble is written
** to the ec_BaseAddress register+2 (D15-D12).  Then the entire byte is
** written to ec_BaseAddress (D15-D8).  This allows writing of a byte-wide
** address to nybble size registers.
**

 STRUCTURE ExpansionControl,0	;-Second 16 bytes of the expansion ROM
    UBYTE	ec_Interrupt	;Optional interrupt control register
    UBYTE	ec_Z3_HighBase	;Zorro III   : Bits 24-31 of config address
    UBYTE	ec_BaseAddress	;Zorro II/III: Bits 16-23 of config address
    UBYTE	ec_Shutup	;The system writes here to shut up a board
    UBYTE	ec_Reserved14
    UBYTE	ec_Reserved15
    UBYTE	ec_Reserved16
    UBYTE	ec_Reserved17
    UBYTE	ec_Reserved18
    UBYTE	ec_Reserved19
    UBYTE	ec_Reserved1a
    UBYTE	ec_Reserved1b
    UBYTE	ec_Reserved1c
    UBYTE	ec_Reserved1d
    UBYTE	ec_Reserved1e
    UBYTE	ec_Reserved1f
    LABEL	ExpansionControl_SIZEOF

**
** many of the constants below consist of a triplet of equivalent
** definitions: xxMASK is a bit mask of those bits that matter.
** xxBIT is the starting bit number of the field.  xxSIZE is the
** number of bits that make up the definition.	This method is
** used when the field is larger than one bit.
**
** If the field is only one bit wide then the xxB_xx and xxF_xx convention
** is used (xxB_xx is the bit number, and xxF_xx is mask of the bit).
**

** manifest constants **
E_SLOTSIZE		EQU	$10000
E_SLOTMASK		EQU	$ffff
E_SLOTSHIFT		EQU	16

** these define the free regions of Zorro memory space.
** THESE MAY WELL CHANGE FOR FUTURE PRODUCTS!
E_EXPANSIONBASE 	EQU	$00e80000	;Zorro II  config address
EZ3_EXPANSIONBASE	EQU	$ff000000	;Zorro III config address

E_EXPANSIONSIZE 	EQU	$00080000	;Zorro II  I/O type cards
E_EXPANSIONSLOTS	EQU	8

E_MEMORYBASE		EQU	$00200000	;Zorro II  8MB space
E_MEMORYSIZE		EQU	$00800000
E_MEMORYSLOTS		EQU	128

EZ3_CONFIGAREA		EQU	$40000000	;Zorro III space
EZ3_CONFIGAREAEND	EQU	$7FFFFFFF	;Zorro III space
EZ3_SIZEGRANULARITY	EQU	$00080000	;512K increments

***** er_Type definitions (ttldcmmm) ****************************************

** er_Type board type bits -- the OS ignores "old style" boards **
ERT_TYPEMASK		EQU	$c0	;Bits 7-6
ERT_TYPEBIT		EQU	6
ERT_TYPESIZE		EQU	2
ERT_NEWBOARD		EQU	$c0
ERT_ZORROII		EQU	ERT_NEWBOARD
ERT_ZORROIII		EQU	$80

** other bits defined in er_Type **
    BITDEF	ERT,MEMLIST,5		; Link RAM into free memory list
    BITDEF	ERT,DIAGVALID,4 	; ROM vector is valid
    BITDEF	ERT,CHAINEDCONFIG,3	; Next config is part of the same card

** er_Type field memory size bits **
ERT_MEMMASK		EQU	$07	;Bits 2-0
ERT_MEMBIT		EQU	0
ERT_MEMSIZE		EQU	3

***** er_Flags byte -- for those things that didn't fit into the type byte ****
***** the hardware stores this byte in inverted form			   ****
    BITDEF	ERF,MEMSPACE,7		; Wants to be in 8 meg space.
                    ; (NOT IMPLEMENTED)

    BITDEF	ERF,NOSHUTUP,6		; Board can't be shut up.

    BITDEF	ERF,EXTENDED,5		; Zorro III: Use extended size table
                    ;	     for bits 0-2 of er_Type.
                    ; Zorro II : Must be 0

    BITDEF	ERF,ZORRO_III,4 	; Zorro III: must be 1
                    ; Zorro II : must be 0

ERT_Z3_SSMASK		EQU	$0F	; Bits 3-0.  Zorro III Sub-Size.  How
ERT_Z3_SSBIT		EQU	0	; much space the card actually uses
ERT_Z3_SSSIZE		EQU	4	; (regardless of config granularity)
                    ; Zorro II : must be 0

** ec_Interrupt register (unused) *********************************************
    BITDEF	ECI,INTENA,1
    BITDEF	ECI,RESET,3
    BITDEF	ECI,INT2PEND,4
    BITDEF	ECI,INT6PEND,5
    BITDEF	ECI,INT7PEND,6
    BITDEF	ECI,INTERRUPTING,7

**************************************************************************
**
** these are the specifications for the diagnostic area.  If the Diagnostic
** Address Valid bit is set in the Board Type byte (the first byte in
** expansion space) then the Diag Init vector contains a valid offset.
**
** The Diag Init vector is actually a word offset from the base of the
** board.  The resulting address points to the base of the DiagArea
** structure.  The structure may be physically implemented either four,
** eight, or sixteen bits wide.  The code will be copied out into
** ram first before being called.
**
** The da_Size field, and both code offsets (da_DiagPoint and da_BootPoint)
** are offsets from the diag area AFTER it has been copied into ram, and
** "de-nybbleized" (if needed). (In other words, the byte size is the size of
** the actual information, not how much address space is required to
** store it.)
**
** All bits are encoded with uninverted logic (e.g. 5 volts on the bus
** is a logic one).
**
** If your board is to make use of the boot facility then it must leave
** its config area available even after it has been configured.  Your
** boot vector will be called AFTER your board's final address has been
** set.
**
**************************************************************************

 STRUCTURE DiagArea,0
    UBYTE	da_Config	; see below for definitions
    UBYTE	da_Flags	; see below for definitions
    UWORD	da_Size	; the size (in bytes) of the total diag area
    UWORD	da_DiagPoint	; where to start for diagnostics, or zero
    UWORD	da_BootPoint	; where to start for booting
    UWORD	da_Name	; offset in diag area where a string
                ;   identifier can be found (or zero if no
                ;   identifier is present).

    UWORD	da_Reserved01	; two words of reserved data.  must be zero.
    UWORD	da_Reserved02
    LABEL	DiagArea_SIZEOF

; da_Config definitions
**
** DAC_BYTEWIDE can be simulated using DAC_NIBBLEWIDE.
**
DAC_BUSWIDTH	EQU	$C0	; two bits for bus width
DAC_NIBBLEWIDE	EQU	$00	; (indicates information is nybble wide)
DAC_BYTEWIDE	EQU	$40	; BUG: Will not work under V34 Kickstart!
DAC_WORDWIDE	EQU	$80

DAC_BOOTTIME	EQU	$30	; two bits for when to boot
DAC_NEVER	EQU	$00	; obvious
DAC_CONFIGTIME	EQU	$10	; call da_BootPoint when first configing
                ;   the device
DAC_BINDTIME	EQU	$20	; run when binding drivers to boards

**
** These are the calling conventions for the diagnostic callback
** (from da_DiagPoint).
**
** A7 -- points to at least 2K of stack
** A6 -- ExecBase
** A5 -- ExpansionBase
** A3 -- your board's ConfigDev structure
** A2 -- Base of diag/init area that was copied
** A0 -- Base of your board
**
** Your board must return a value in D0.  If this value is NULL, then
** the diag/init area that was copied in will be returned to the free
** memory pool.
**

    ENDC	;LIBRARIES_CONFIGREGS_I


Includes/libraries/expansionbase.h

#ifndef LIBRARIES_EXPANSIONBASE_H
#define LIBRARIES_EXPANSIONBASE_H
/*
**	$Filename: libraries/expansionbase.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.15 $
**	$Date: 91/10/21 $
**
**	Definitions for the expansion library base
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include "exec/types.h"
#endif	/* EXEC_TYPES_H */

#ifndef EXEC_LIBRARIES_H
#include "exec/libraries.h"
#endif	/* EXEC_LIBRARIES_H */

#ifndef EXEC_SEMAPHORES_H
#include "exec/semaphores.h"
#endif	/* EXEC_SEMAPHORES_H */

#ifndef LIBRARIES_CONFIGVARS_H
#include "libraries/configvars.h"
#endif	/* LIBRARIES_CONFIGVARS_H */

/* BootNodes are scanned by dos.library at startup.  Items found on the
   list are started by dos. BootNodes are added with the AddDosNode() or
   the V36 AddBootNode() calls. */
struct BootNode
{
    struct Node bn_Node;
    UWORD	bn_Flags;
    APTR	bn_DeviceNode;
};

/* expansion.library has functions to manipulate most of the information in
   ExpansionBase.  Direct access is not permitted.  Use FindConfigDev()
   to scan the board list. */
struct	ExpansionBase
{
    struct Library	LibNode;
    UBYTE	Flags;				/* read only (see below) */
    UBYTE	eb_Private01;			/* private */
    ULONG	eb_Private02;			/* private */
    ULONG	eb_Private03;			/* private */
    struct	CurrentBinding	eb_Private04;	/* private */
    struct	List	eb_Private05;		/* private */
    struct	List	MountList;	/* contains struct BootNode entries */
    /* private */
};

/* error codes */
#define EE_OK		0
#define EE_LASTBOARD	40  /* could not shut him up */
#define EE_NOEXPANSION	41  /* not enough expansion mem; board shut up */
#define EE_NOMEMORY	42  /* not enough normal memory */
#define EE_NOBOARD	43  /* no board at that address */
#define EE_BADMEM	44  /* tried to add bad memory card */

/* Flags */
#define EBB_CLOGGED	0	/* someone could not be shutup */
#define EBF_CLOGGED	(1<<0)
#define EBB_SHORTMEM	1	/* ran out of expansion mem */
#define EBF_SHORTMEM	(1<<1)
#define EBB_BADMEM	2	/* tried to add bad memory card */
#define EBF_BADMEM	(1<<2)
#define EBB_DOSFLAG	3	/* reserved for use by AmigaDOS */
#define EBF_DOSFLAG	(1<<3)
#define EBB_KICKBACK33	4	/* reserved for use by AmigaDOS */
#define EBF_KICKBACK33	(1<<4)
#define EBB_KICKBACK36	5	/* reserved for use by AmigaDOS */
#define EBF_KICKBACK36	(1<<5)
/* If the following flag is set by a floppy's bootblock code, the initial
   open of the initial shell window will be delayed until the first output
   to that shell.  Otherwise the 1.3 compatible behavior applies. */
#define EBB_SILENTSTART	6
#define EBF_SILENTSTART	(1<<6)

/* Magic kludge for CC0 use */
#define	EBB_START_CC0	7
#define	EBF_START_CC0	(1<<7)

#endif	/* LIBRARIES_EXPANSIONBASE_H */


Includes/libraries/mathlibrary.i

    IFND	LIBRARIES_MATHLIBRARY_I
LIBRARIES_MATHLIBRARY_I	SET	1
**
**	$Filename: libraries/mathlibrary.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.4 $
**	$Date: 90/07/13 $
**
**	Data structure returned by OpenLibrary of:
**	mathieeedoubbas.library,mathieeedoubtrans.library
**	mathieeesingbas.library,mathieeesingtrans.library
**
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
**

    ifnd EXEC_LIBRARIES_I
    include "exec/libraries.i"
    endc

    STRUCTURE MathIEEEBase,0
        STRUCT	MathIEEEBase_LibNode,LIB_SIZE
        STRUCT	MathIEEEBase_reserved,18
        APTR	MathIEEEBase_TaskOpenLib	; hook
        APTR	MathIEEEBase_TaskCloseLib	; hook
*	This structure may be extended in the future */
    LABEL	MathIEEEBase_SIZE

;	Math resources may need to know when a program opens or closes this
;	library. The functions TaskOpenLib and TaskCloseLib are called when
;	a task opens or closes this library. The yare initialized to point
;	local initialization pertaining to 68881 stuff if 68881 resources
;	are found. To override the default the vendor must provide appropriate
;	hooks in the MathIEEEResource. If specified, these will be called
;	when the library initializes.

    ENDC	; LIBRARIES_MATHLIBRARY_I


Includes/libraries/configvars.h

#ifndef LIBRARIES_CONFIGVARS_H
#define LIBRARIES_CONFIGVARS_H
/*
**	$Filename: libraries/configvars.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.14 $
**	$Date: 91/04/22 $
**
**	Software structures used by AutoConfig (tm) boards
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef	EXEC_TYPES_H
#include "exec/types.h"
#endif	/* EXEC_TYPES_H */

#ifndef EXEC_NODES_H
#include "exec/nodes.h"
#endif /* EXEC_NODES_H */

#ifndef LIBRARIES_CONFIGREGS_H
#include "libraries/configregs.h"
#endif /* LIBRARIES_CONFIGREGS_H */

/*
** At early system startup time, one ConfigDev structure is created for
** each board found in the system.  Software may seach for ConfigDev
** structures by vendor & product ID number.  For debugging and diagnostic
** use, the entire list can be accessed.  See the expansion.library document
** for more information.
*/
struct ConfigDev {
    struct Node		cd_Node;
    UBYTE		cd_Flags;	/* (read/write) */
    UBYTE		cd_Pad;		/* reserved */
    struct ExpansionRom	cd_Rom;		/* copy of board's expansion ROM */
    APTR		cd_BoardAddr; /* where in memory the board was placed */
    ULONG		cd_BoardSize;	/* size of board in bytes */
    UWORD		cd_SlotAddr;	/* which slot number (PRIVATE) */
    UWORD		cd_SlotSize;	/* number of slots (PRIVATE) */
    APTR		cd_Driver;	/* pointer to node of driver */
    struct ConfigDev *	cd_NextCD;	/* linked list of drivers to config */
    ULONG		cd_Unused[4];	/* for whatever the driver wants */
};

/* cd_Flags */
#define	CDB_SHUTUP	0	/* this board has been shut up */
#define	CDB_CONFIGME	1	/* this board needs a driver to claim it */
#define	CDB_BADMEMORY	2	/* this board contains bad memory */
#define	CDB_PROCESSED	3	/* private flag */

#define	CDF_SHUTUP	0x01
#define	CDF_CONFIGME	0x02
#define	CDF_BADMEMORY	0x04
#define	CDF_PROCESSED	0x08

/*
** Boards are usually "bound" to software drivers.
** This structure is used by GetCurrentBinding() and SetCurrentBinding()
*/
struct CurrentBinding {
    struct ConfigDev *	cb_ConfigDev;		/* first configdev in chain */
    UBYTE *		cb_FileName;		/* file name of driver */
    UBYTE *		cb_ProductString;	/* product # string */
    UBYTE **		cb_ToolTypes;		/* tooltypes from disk object */
};

#endif /* LIBRARIES_CONFIGVARS_H */


Includes/libraries/expansionbase.i

    IFND	LIBRARIES_EXPANSIONBASE_I
LIBRARIES_EXPANSIONBASE_I	SET	1
**
**	$Filename: libraries/expansionbase.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.18 $
**	$Date: 91/10/21 $
**
**	Definitions for the expansion library base
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
**
    IFND	EXEC_TYPES_I
    INCLUDE "exec/types.i"
    ENDC	; EXEC_TYPES_I

    IFND	EXEC_LIBRARIES_I
    INCLUDE "exec/libraries.i"
    ENDC	; EXEC_LIBRARIES_I

    IFND	EXEC_SEMAPHORES_I
    INCLUDE "exec/semaphores.i"
    ENDC	; EXEC_SEMAPHORES_I

    IFND	LIBRARIES_CONFIGVARS_I
    INCLUDE "libraries/configvars.i"
    ENDC	; LIBRARIES_CONFIGVARS_I

**
** BootNodes are scanned by dos.library at startup.  Items found on the
** list are started by dos. BootNodes are added with the AddDosNode() or
** the V36 AddBootNode() calls.
**
  STRUCTURE	BootNode,LN_SIZE
    UWORD	bn_Flags
    APTR	bn_DeviceNode
    LABEL	BootNode_SIZEOF

**
** expansion.library has functions to manipulate most of the information in
** ExpansionBase.  Direct access is not permitted.  Use FindConfigDev()
** to scan the board list.
**
  STRUCTURE	ExpansionBase,LIB_SIZE
    UBYTE	eb_Flags				;read only (see below)
    UBYTE	eb_Private01				;private
    ULONG	eb_Private02				;private
    ULONG	eb_Private03				;private
    STRUCT	eb_Private04,CurrentBinding_SIZEOF	;private
    STRUCT	eb_Private05,LH_SIZE			;private
    STRUCT	eb_MountList,LH_SIZE	; contains struct BootNode entries
    ;...						;private

; error codes
EE_OK		EQU 0
EE_LASTBOARD	EQU 40	; could not shut him up
EE_NOEXPANSION	EQU 41	; not enough expansion mem; board shut up
EE_NOMEMORY	EQU 42	; not enough normal memory
EE_NOBOARD	EQU 43	; no board at that address
EE_BADMEM	EQU 44	; tried to add a bad memory card

; Flags
    BITDEF	EB,CLOGGED,0	; someone could not be shutup
    BITDEF	EB,SHORTMEM,1	; ran out of expansion mem
    BITDEF	EB,BADMEM,2	; tried to add a bad memory card
    BITDEF	EB,DOSFLAG,3	; reserved for use by AmigaDOS
    BITDEF	EB,KICKBACK33,4	; reserved for use by AmigaDOS
    BITDEF	EB,KICKBACK36,5	; reserved for use by AmigaDOS
** If the following flag is set by a floppy's bootblock code, the initial
** open of the initial shell window will be delayed until the first output
** to that shell.  Otherwise the 1.3 compatible behavior applies.
    BITDEF	EB,SILENTSTART,6

*
* Magic kludge to tell the system if CC0 was started or not...
*
    BITDEF	EB,START_CC0,7

    ENDC	; LIBRARIES_EXPANSIONBASE_I


Includes/libraries/mathresource.h

#ifndef	RESOURCES_MATHRESOURCE_H
#define	RESOURCES_MATHRESOURCE_H
/*
**	$Filename: libraries/mathresource.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.2 $
**	$Date: 90/07/13 $
**
**	Data structure returned by OpenResource of:
**	"MathIEEE.resource"
**
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_NODES_H
#include <exec/nodes.h>
#endif

/*
*	The 'Init' entries are only used if the corresponding
*	bit is set in the Flags field.
*
*	So if you are just a 68881, you do not need the Init stuff
*	just make sure you have cleared the Flags field.
*
*	This should allow us to add Extended Precision later.
*
*	For Init users, if you need to be called whenever a task
*	opens this library for use, you need to change the appropriate
*	entries in MathIEEELibrary.
*/

struct MathIEEEResource
{
    struct	Node	MathIEEEResource_Node;
    unsigned short	MathIEEEResource_Flags;
    unsigned short	*MathIEEEResource_BaseAddr; /* ptr to 881 if exists */
    void	(*MathIEEEResource_DblBasInit)();
    void	(*MathIEEEResource_DblTransInit)();
    void	(*MathIEEEResource_SglBasInit)();
    void	(*MathIEEEResource_SglTransInit)();
    void	(*MathIEEEResource_ExtBasInit)();
    void	(*MathIEEEResource_ExtTransInit)();
};

/* definations for MathIEEEResource_FLAGS */
#define	MATHIEEERESOURCEF_DBLBAS	(1<<0)
#define	MATHIEEERESOURCEF_DBLTRANS	(1<<1)
#define	MATHIEEERESOURCEF_SGLBAS	(1<<2)
#define	MATHIEEERESOURCEF_SGLTRANS	(1<<3)
#define	MATHIEEERESOURCEF_EXTBAS	(1<<4)
#define	MATHIEEERESOURCEF_EXTTRANS	(1<<5)

#endif	/* RESOURCES_MATHRESOURCE_H */


Includes/libraries/configvars.i

    IFND	LIBRARIES_CONFIGVARS_I
LIBRARIES_CONFIGVARS_I	SET	1
**
**	$Filename: libraries/configvars.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.7 $
**	$Date: 91/04/09 $
**
**	Software structures used by AutoConfig (tm) boards
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND	EXEC_NODES_I
    INCLUDE	"exec/nodes.i"
    ENDC	;EXEC_NODES_I

    IFND	LIBRARIES_CONFIGREGS_I
    INCLUDE	"libraries/configregs.i"
    ENDC	;LIBRARIES_CONFIGREGS_I

**
** At early system startup time, one ConfigDev structure is created for
** each board found in the system.  Software may seach for ConfigDev
** structures by vendor & product ID number.  For debugging and diagnostic
** use, the entire list can be accessed.  See the expansion.library document
** for more information.
**
 STRUCTURE ConfigDev,0
    STRUCT	cd_Node,LN_SIZE
    UBYTE	cd_Flags	; (read/write)
    UBYTE	cd_Pad		; reserved
    STRUCT	cd_Rom,ExpansionRom_SIZEOF ; copy of board's expansion ROM
    APTR	cd_BoardAddr	; where in memory the board was placed
    ULONG	cd_BoardSize	; size of board in bytes
    UWORD	cd_SlotAddr	; which slot number (PRIVATE)
    UWORD	cd_SlotSize	; number of slots (PRIVATE)
    APTR	cd_Driver	; pointer to node of driver
    APTR 	cd_NextCD	; linked list of drivers to config
    STRUCT	cd_Unused,4*4	; for whatever the driver wants!
    LABEL	ConfigDev_SIZEOF

; cd_Flags
    BITDEF	CD,SHUTUP,0	; this board has been shut up
    BITDEF	CD,CONFIGME,1	; this board needs a driver to claim it
    BITDEF	CD,BADMEMORY,2	; this board contains bad memory
    BITDEF	CD,PROCESSED,3	; private flag

**
** Boards are usually "bound" to software drivers.
** This structure is used by GetCurrentBinding() and SetCurrentBinding()
**
 STRUCTURE CurrentBinding,0
    APTR	cb_ConfigDev
    APTR	cb_FileName
    APTR 	cb_ProductString
    APTR	cb_ToolTypes
    LABEL	CurrentBinding_SIZEOF

    ENDC	;LIBRARIES_CONFIGVARS_I


Includes/libraries/filehandler.h

#ifndef LIBRARIES_FILEHANDLER_H
#define LIBRARIES_FILEHANDLER_H
/*
**	$Filename: libraries/filehandler.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.2 $
**	$Date: 90/07/12 $
**
**	device and file handler specific code for AmigaDOS
**
**	(C) Copyright 1986-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef DOS_FILEHANDLER_H
#include "dos/filehandler.h"
#endif

#endif /* LIBRARIES_FILEHANDLER_H */


Includes/libraries/mathresource.i

    IFND	RESOURCES_MATHRESOURCE_I
RESOURCES_MATHRESOURCE_I	SET	1
**
**	$Filename: libraries/mathresource.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.3 $
**	$Date: 90/07/13 $
**
**	Data structure returned by OpenResource of:
**	"MathIEEE.resource"
**
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND EXEC_NODES_I
    include "exec/nodes.i"
    ENDC

*
*	The 'Init' entries are only used if the corresponding
*	bit is set in the Flags field.
*
*	So if you are just a 68881, you do not need the Init stuff
*	just make sure you have cleared the Flags field.
*
*	This should allow us to add Extended Precision later.
*
*	For Init users, if you need to be called whenever a task
*	opens this library for use, you need to change the appropriate
*	entries in MathIEEELibrary.
*

    STRUCTURE MathIEEEResourceResource,0
        STRUCT	MathIEEEResource_Node,LN_SIZE
        USHORT	MathIEEEResource_Flags
        APTR	MathIEEEResource_BaseAddr	* ptr to 881 if exists *
        APTR	MathIEEEResource_DblBasInit
        APTR	MathIEEEResource_DblTransInit
        APTR	MathIEEEResource_SglBasInit
        APTR	MathIEEEResource_SglTransInit
        APTR	MathIEEEResource_ExtBasInit
        APTR	MathIEEEResource_ExtTransInit
    LABEL	MathIEEEResourceResource_SIZE

* definations for MathIEEERESOURCE_FLAGS *
    BITDEF	MATHIEEERESOURCE,DBLBAS,0
    BITDEF	MATHIEEERESOURCE,DBLTRANS,1
    BITDEF	MATHIEEERESOURCE,SGLBAS,2
    BITDEF	MATHIEEERESOURCE,SGLTRANS,3
    BITDEF	MATHIEEERESOURCE,EXTBAS,4
    BITDEF	MATHIEEERESOURCE,EXTTRANS,5

    ENDC	; RESOURCES_MATHRESOURCE_I


Includes/libraries/diskfont.h

#ifndef	LIBRARIES_DISKFONT_H
#define	LIBRARIES_DISKFONT_H
/*
**	$Filename: libraries/diskfont.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.6 $
**	$Date: 90/11/26 $
**
**	diskfont library definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef     EXEC_TYPES_H
#include "exec/types.h"
#endif
#ifndef     EXEC_NODES_H
#include "exec/nodes.h"
#endif
#ifndef     EXEC_LISTS_H
#include "exec/lists.h"
#endif
#ifndef     GRAPHICS_TEXT_H
#include "graphics/text.h"
#endif

#define     MAXFONTPATH 256   /* including null terminator */

struct FontContents {
    char    fc_FileName[MAXFONTPATH];
    UWORD   fc_YSize;
    UBYTE   fc_Style;
    UBYTE   fc_Flags;
};

struct TFontContents {
    char    tfc_FileName[MAXFONTPATH-2];
    UWORD   tfc_TagCount;	/* including the TAG_DONE tag */
    /*
     *	if tfc_TagCount is non-zero, tfc_FileName is overlayed with
     *	Text Tags starting at:	(struct TagItem *)
     *	    &tfc_FileName[MAXFONTPATH-(tfc_TagCount*sizeof(struct TagItem))]
     */
    UWORD   tfc_YSize;
    UBYTE   tfc_Style;
    UBYTE   tfc_Flags;
};

#define  FCH_ID		0x0f00	/* FontContentsHeader, then FontContents */
#define  TFCH_ID	0x0f02	/* FontContentsHeader, then TFontContents */

struct FontContentsHeader {
    UWORD   fch_FileID;		/* FCH_ID */
    UWORD   fch_NumEntries;	/* the number of FontContents elements */
    /* struct FontContents fch_FC[], or struct TFontContents fch_TFC[]; */
};

#define  DFH_ID		0x0f80
#define  MAXFONTNAME	32	/* font name including ".font\0" */

struct DiskFontHeader {
    /* the following 8 bytes are not actually considered a part of the	*/
    /* DiskFontHeader, but immediately preceed it. The NextSegment is	*/
    /* supplied by the linker/loader, and the ReturnCode is the code	*/
    /* at the beginning of the font in case someone runs it...		*/
    /*	 ULONG dfh_NextSegment;			\* actually a BPTR	*/
    /*	 ULONG dfh_ReturnCode;			\* MOVEQ #0,D0 : RTS	*/
    /* here then is the official start of the DiskFontHeader...		*/
    struct Node dfh_DF;		/* node to link disk fonts */
    UWORD   dfh_FileID;		/* DFH_ID */
    UWORD   dfh_Revision;	/* the font revision */
    LONG    dfh_Segment;	/* the segment address when loaded */
    char    dfh_Name[MAXFONTNAME]; /* the font name (null terminated) */
    struct TextFont dfh_TF;	/* loaded TextFont structure */
};

/* unfortunately, this needs to be explicitly typed */
/* used only if dfh_TF.tf_Style FSB_TAGGED bit is set */
#define	dfh_TagList	dfh_Segment	/* destroyed during loading */

#define     AFB_MEMORY	0
#define     AFF_MEMORY	0x0001
#define     AFB_DISK	1
#define     AFF_DISK	0x0002
#define     AFB_SCALED	2
#define     AFF_SCALED	0x0004

#define     AFB_TAGGED	16	/* return TAvailFonts */
#define     AFF_TAGGED	0x10000L

struct AvailFonts {
    UWORD   af_Type;		/* MEMORY, DISK, or SCALED */
    struct TextAttr af_Attr;	/* text attributes for font */
};

struct TAvailFonts {
    UWORD   taf_Type;		/* MEMORY, DISK, or SCALED */
    struct TTextAttr taf_Attr;	/* text attributes for font */
};

struct AvailFontsHeader {
    UWORD   afh_NumEntries;	 /* number of AvailFonts elements */
    /* struct AvailFonts afh_AF[], or struct TAvailFonts afh_TAF[]; */
};

#endif	/* LIBRARIES_DISKFONT_H */


Includes/libraries/filehandler.i

    IFND	LIBRARIES_FILEHANDLER_I
LIBRARIES_FILEHANDLER_I SET	1
**
**	$Filename: libraries/filehandler.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.2 $
**	$Date: 90/07/12 $
**
**	device and file handler specific code for AmigaDOS
**
**	(C) Copyright 1986-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND	DOS_FILEHANDLER_I
    INCLUDE	"dos/filehandler.i"
    ENDC

    ENDC	; LIBRARIES_FILEHANDLER_I


Includes/libraries/translator.h

#ifndef LIBRARIES_TRANSLATOR_H
#define LIBRARIES_TRANSLATOR_H

/*
**	$Filename: libraries/translator.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.1 $
**	$Date: 90/12/13 $
**
**	Useful definitions for translator.library
**
**	(C) Copyright 1988-1999 Amiga, Inc. and
**	Joseph Katz/Mark Barton.  All rights reserved.
*/

/*	Translator error return codes	*/

#define	TR_NotUsed	-1	/* This is an oft used system rc	*/
#define	TR_NoMem	-2	/* Can't allocate memory		*/
#define TR_MakeBad	-4	/* Error in MakeLibrary call		*/

#endif	/* LIBRARIES_TRANSLATOR_H */


Includes/libraries/diskfont.i

    IFND	LIBRARIES_DISKFONT_I
LIBRARIES_DISKFONT_I	SET	1
**
**	$Filename: libraries/diskfont.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.3 $
**	$Date: 90/10/22 $
**
**	diskfont library definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND	EXEC_TYPES_I
    INCLUDE "exec/types.i"
    ENDC
    IFND	EXEC_NODES_I
    INCLUDE	"exec/nodes.i"
    ENDC
    IFND	EXEC_LISTS_I
    INCLUDE	"exec/lists.i"
    ENDC
    IFND	GRAPHICS_TEXT_I
    INCLUDE	"graphics/text.i"
    ENDC

MAXFONTPATH	EQU	256	; including null terminator

 STRUCTURE  FC,0		; FontContents
    STRUCT  fc_FileName,MAXFONTPATH
    UWORD   fc_YSize
    UBYTE   fc_Style
    UBYTE   fc_Flags
    LABEL   fc_SIZEOF

 STRUCTURE  TFC,0		; TFontContents
    STRUCT  tfc_FileName,MAXFONTPATH-2
    UWORD   tfc_TagCount	; including the TAG_DONE tag
    ;
    ;	if tfc_TagCount is non-zero, tfc_FileName is overlayed with
    ;	Text Tags starting at:	(struct TagItem *)
    ;	    &tfc_FileName[MAXFONTPATH-(tfc_TagCount*sizeof(struct TagItem))]
    ;
    UWORD   tfc_YSize
    UBYTE   tfc_Style
    UBYTE   tfc_Flags
    LABEL   tfc_SIZEOF

FCH_ID		EQU	$0f00	; FontContentsHeader, then FontContents
TFCH_ID		EQU	$0f02	; FontContentsHeader, then TFontContents

 STRUCTURE  FCH,0		; FontContentsHeader
    UWORD   fch_FileID		; FCH_ID or TFCH_ID
    UWORD   fch_NumEntries	; the number of FontContents elements
    LABEL   fch_FC		; the [T]FontContents elements follow here

DFH_ID		EQU	$0f80
MAXFONTNAME	EQU	32	; font name including ".font\0"

 STRUCTURE  DiskFontHeader,0
    ; the following 8 bytes are not actually considered a part of the
    ; DiskFontHeader, but immediately preceed it.  The NextSegment is supplied
    ; by the linker/loader, and the ReturnCode is the code at the beginning
    ; of the font in case someone runs it...
    ; ULONG dfh_NextSegment	; actually a BPTR
    ; ULONG dfh_ReturnCode	; MOVEQ #0,D0 : RTS
    ; here then is the official start of the DiskFontHeader...
    STRUCT  dfh_DF,LN_SIZE	; node to link disk fonts
    UWORD   dfh_FileID		; DFH_ID
    UWORD   dfh_Revision	; the font revision in this version
    LONG    dfh_Segment		; the segment address when loaded
    STRUCT  dfh_Name,MAXFONTNAME ; the font name (null terminated)
    STRUCT  dfh_TF,tf_SIZEOF	; loaded TextFont structure
    LABEL   dfh_SIZEOF

; used only if dfh_TF.tf_Style FSB_TAGGED bit is set
dfh_TagList	EQU	dfh_Segment	; destroyed during loading

    BITDEF  AF,MEMORY,0
    BITDEF  AF,DISK,1
    BITDEF  AF,SCALED,2

    BITDEF  AF,TTATTR,16	; return TAvailFonts

 STRUCTURE  AF,0		; AvailFonts
    UWORD   af_Type		; MEMORY, DISK, or SCALED
    STRUCT  af_Attr,ta_SIZEOF	; text attributes for font
    LABEL   af_SIZEOF

 STRUCTURE  TAF,0		; TAvailFonts
    UWORD   taf_Type		; MEMORY, DISK, or SCALED
    STRUCT  taf_Attr,tta_SIZEOF	; text attributes for font
    LABEL   taf_SIZEOF

 STRUCTURE  AFH,0		; AvailFontsHeader
    UWORD   afh_NumEntries	; number of AvailFonts elements
    LABEL   afh_AF		; the [T]AvailFonts elements follow here

    ENDC	; LIBRARIES_DISKFONT_I


Includes/libraries/gadtools.h

#ifndef LIBRARIES_GADTOOLS_H
#define LIBRARIES_GADTOOLS_H
/*
**	$Filename: libraries/gadtools.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.18 $
**	$Date: 91/10/09 $
**
**	gadtools.library definitions
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	All Rights Reserved
*/

/*------------------------------------------------------------------------*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

#ifndef INTUITION_INTUITION_H
#include <intuition/intuition.h>
#endif

/*------------------------------------------------------------------------*/

/*  The kinds (almost classes) of gadgets in the toolkit.  Use these
    identifiers when calling CreateGadgetA() */

#define GENERIC_KIND	0
#define BUTTON_KIND	1
#define CHECKBOX_KIND	2
#define INTEGER_KIND	3
#define LISTVIEW_KIND	4
#define MX_KIND		5
#define NUMBER_KIND	6
#define CYCLE_KIND	7
#define PALETTE_KIND	8
#define SCROLLER_KIND	9
/* Kind number 10 is reserved */
#define SLIDER_KIND	11
#define STRING_KIND	12
#define TEXT_KIND	13

#define NUM_KINDS	14

/*------------------------------------------------------------------------*/

/*  These two definitions are obsolete, but are here for backwards
    compatibility.  You never need to worry about these: */
#define GADTOOLBIT	(0x8000)
/*  Use this mask to isolate the user part: */
#define GADTOOLMASK	(~GADTOOLBIT)

/*------------------------------------------------------------------------*/

/*  'Or' the appropriate set together for your Window IDCMPFlags: */

#define ARROWIDCMP	(IDCMP_GADGETUP | IDCMP_GADGETDOWN |\
    IDCMP_INTUITICKS | IDCMP_MOUSEBUTTONS)

#define BUTTONIDCMP	(IDCMP_GADGETUP)
#define CHECKBOXIDCMP	(IDCMP_GADGETUP)
#define INTEGERIDCMP	(IDCMP_GADGETUP)
#define LISTVIEWIDCMP	(IDCMP_GADGETUP | IDCMP_GADGETDOWN |\
    IDCMP_MOUSEMOVE | ARROWIDCMP)

#define MXIDCMP		(IDCMP_GADGETDOWN)
#define NUMBERIDCMP	(NULL)
#define CYCLEIDCMP	(IDCMP_GADGETUP)
#define PALETTEIDCMP	(IDCMP_GADGETUP)

/*  Use ARROWIDCMP|SCROLLERIDCMP if your scrollers have arrows: */
#define SCROLLERIDCMP	(IDCMP_GADGETUP | IDCMP_GADGETDOWN | IDCMP_MOUSEMOVE)
#define SLIDERIDCMP	(IDCMP_GADGETUP | IDCMP_GADGETDOWN | IDCMP_MOUSEMOVE)
#define STRINGIDCMP	(IDCMP_GADGETUP)

#define TEXTIDCMP	(NULL)

/*------------------------------------------------------------------------*/

/*  Typical suggested spacing between "elements": */
#define INTERWIDTH	8
#define INTERHEIGHT	4

/*------------------------------------------------------------------------*/

/*  Generic NewGadget used by several of the gadget classes: */

struct NewGadget
    {
    WORD ng_LeftEdge, ng_TopEdge;	/*  gadget position */
    WORD ng_Width, ng_Height;		/*  gadget size */
    UBYTE *ng_GadgetText;		/*  gadget label */
    struct TextAttr *ng_TextAttr;	/*  desired font for gadget label */
    UWORD ng_GadgetID;			/*  gadget ID */
    ULONG ng_Flags;			/*  see below */
    APTR ng_VisualInfo;			/*  Set to retval of GetVisualInfo() */
    APTR ng_UserData;			/*  gadget UserData */
    };

/*  ng_Flags control certain aspects of the gadget.  The first five control
    the placement of the descriptive text.  All larger groups supply a
    default: */

#define PLACETEXT_LEFT	0x0001	/* Right-align text on left side */
#define PLACETEXT_RIGHT	0x0002	/* Left-align text on right side */
#define PLACETEXT_ABOVE	0x0004	/* Center text above */
#define PLACETEXT_BELOW	0x0008	/* Center text below */
#define PLACETEXT_IN	0x0010	/* Center text on */

#define NG_HIGHLABEL	0x0020	/* Highlight the label */

/*------------------------------------------------------------------------*/

/* Fill out an array of these and pass that to CreateMenus(): */

struct NewMenu
    {
    UBYTE nm_Type;		/*  See below */
    /* Compiler inserts a PAD byte here */
    STRPTR nm_Label;		/*  Menu's label */
    STRPTR nm_CommKey;		/*  MenuItem Command Key Equiv */
    UWORD nm_Flags;		/*  Menu or MenuItem flags (see note) */
    LONG nm_MutualExclude;	/*  MenuItem MutualExclude word */
    APTR nm_UserData;		/*  For your own use, see note */
    };

/*  Each nm_Type should be one of these: */
#define NM_TITLE	1
#define NM_ITEM		2
#define NM_SUB		3
#define NM_END		0

#define MENU_IMAGE	128

/* For an image menu-item or sub-item, use one of these.  Set
 * nm_Label to point at the Image structure you wish to use.
 * NOTE: At present, you may only use conventional images.
 * Custom images created from Intuition image-classes do not work.
 */
#define IM_ITEM		(NM_ITEM | MENU_IMAGE)
#define IM_SUB		(NM_SUB | MENU_IMAGE)

/*  If you set your label to NM_BARLABEL, you'll get a separator bar. */
#define NM_BARLABEL	((STRPTR)-1)

/*  The nm_Flags field is used to fill out either the Menu->Flags or
    MenuItem->Flags field.  Note that the sense of the MENUENABLED or
    ITEMENABLED bit is inverted between this use and Intuition's use,
    in other words, NewMenus are enabled by default.  The following
    labels are provided to disable them: */
#define NM_MENUDISABLED	MENUENABLED
#define NM_ITEMDISABLED	ITEMENABLED

/*  The following are pre-cleared (COMMSEQ, ITEMTEXT, and HIGHxxx are set
    later as appropriate): */
#define NM_FLAGMASK	(~(COMMSEQ | ITEMTEXT | HIGHFLAGS))

/*  You may choose among CHECKIT, MENUTOGGLE, and CHECKED.
    Toggle-select menuitems are of type CHECKIT|MENUTOGGLE, along
    with CHECKED if currently selected.  Mutually exclusive ones
    are of type CHECKIT, and possibly CHECKED too.  The nm_MutualExclude
    is a bit-wise representation of the items excluded by this one,
    so in the simplest case (choose 1 among n), these flags would be
    ~1, ~2, ~4, ~8, ~16, etc.  See the Intuition Menus chapter. */

/*  A UserData pointer can be associated with each Menu and MenuItem structure.
    The CreateMenus() call allocates space for a UserData after each
    Menu or MenuItem (header, item or sub-item).  You should use the
    GTMENU_USERDATA() or GTMENUITEM_USERDATA() macro to extract it. */

#define GTMENU_USERDATA(menu) (* ( (APTR *)(((struct Menu *)menu)+1) ) )
#define GTMENUITEM_USERDATA(menuitem) (* ( (APTR *)(((struct MenuItem *)menuitem)+1) ) )

/*  Here is an old one for compatibility.  Do not use in new code! */
#define MENU_USERDATA(menuitem) (* ( (APTR *)(menuitem+1) ) )

/*  These return codes can be obtained through the GTMN_SecondaryError tag */
#define GTMENU_TRIMMED	0x00000001	/* Too many menus, items, or subitems,
                       menu has been trimmed down */
#define GTMENU_INVALID	0x00000002	/* Invalid NewMenu array */
#define GTMENU_NOMEM	0x00000003	/* Out of memory */

/*------------------------------------------------------------------------*/

/*  Tags for toolkit functions: */

#define GT_TagBase	     TAG_USER + 0x80000

#define GTVI_NewWindow	     GT_TagBase+1  /* Unused */
#define GTVI_NWTags	     GT_TagBase+2  /* Unused */

#define GT_Private0	     GT_TagBase+3  /* (private) */

#define GTCB_Checked	     GT_TagBase+4  /* State of checkbox */

#define GTLV_Top	     GT_TagBase+5  /* Top visible one in listview */
#define GTLV_Labels	     GT_TagBase+6  /* List to display in listview */
#define GTLV_ReadOnly	     GT_TagBase+7  /* TRUE if listview is to be
                          read-only */
#define GTLV_ScrollWidth     GT_TagBase+8  /* Width of scrollbar */

#define GTMX_Labels	     GT_TagBase+9  /* NULL-terminated array of labels */
#define GTMX_Active	     GT_TagBase+10 /* Active one in mx gadget */

#define GTTX_Text	     GT_TagBase+11 /* Text to display */
#define GTTX_CopyText	     GT_TagBase+12 /* Copy text label instead of
                          referencing it */

#define GTNM_Number	     GT_TagBase+13 /* Number to display */

#define GTCY_Labels	     GT_TagBase+14 /* NULL-terminated array of labels */
#define GTCY_Active	     GT_TagBase+15 /* The active one in the cycle gad */

#define GTPA_Depth	     GT_TagBase+16 /* Number of bitplanes in palette */
#define GTPA_Color	     GT_TagBase+17 /* Palette color */
#define GTPA_ColorOffset     GT_TagBase+18 /* First color to use in palette */
#define GTPA_IndicatorWidth  GT_TagBase+19 /* Width of current-color indicator */
#define GTPA_IndicatorHeight GT_TagBase+20 /* Height of current-color indicator */

#define GTSC_Top	     GT_TagBase+21 /* Top visible in scroller */
#define GTSC_Total	     GT_TagBase+22 /* Total in scroller area */
#define GTSC_Visible	     GT_TagBase+23 /* Number visible in scroller */
#define GTSC_Overlap	     GT_TagBase+24 /* Unused */

/*  GT_TagBase+25 through GT_TagBase+37 are reserved */

#define GTSL_Min	     GT_TagBase+38 /* Slider min value */
#define GTSL_Max	     GT_TagBase+39 /* Slider max value */
#define GTSL_Level	     GT_TagBase+40 /* Slider level */
#define GTSL_MaxLevelLen     GT_TagBase+41 /* Max length of printed level */
#define GTSL_LevelFormat     GT_TagBase+42 /* Format string for level */
#define GTSL_LevelPlace      GT_TagBase+43 /* Where level should be placed */
#define GTSL_DispFunc	     GT_TagBase+44 /* Callback for number calculation
                          before display */

#define GTST_String	     GT_TagBase+45 /* String gadget's displayed string */
#define GTST_MaxChars	     GT_TagBase+46 /* Max length of string */

#define GTIN_Number	     GT_TagBase+47 /* Number in integer gadget */
#define GTIN_MaxChars	     GT_TagBase+48 /* Max number of digits */

#define GTMN_TextAttr	     GT_TagBase+49 /* MenuItem font TextAttr */
#define GTMN_FrontPen	     GT_TagBase+50 /* MenuItem text pen color */

#define GTBB_Recessed	     GT_TagBase+51 /* Make BevelBox recessed */

#define GT_VisualInfo	     GT_TagBase+52 /* result of VisualInfo call */

#define GTLV_ShowSelected    GT_TagBase+53 /* show selected entry beneath
        listview, set tag data = NULL for display-only, or pointer
        to a string gadget you've created */
#define GTLV_Selected	     GT_TagBase+54 /* Set ordinal number of selected
                          entry in the list */
#define GT_Reserved1	     GT_TagBase+56 /* Reserved for future use */

#define GTTX_Border	     GT_TagBase+57 /* Put a border around
                          Text-display gadgets */
#define GTNM_Border	     GT_TagBase+58 /* Put a border around
                          Number-display gadgets */

#define GTSC_Arrows	     GT_TagBase+59 /* Specify size of arrows for
                          scroller */

#define GTMN_Menu	     GT_TagBase+60 /* Pointer to Menu for use by
                          LayoutMenuItems() */
#define GTMX_Spacing	     GT_TagBase+61 /* Added to font height to
        figure spacing between mx choices.  Use this instead
        of LAYOUTA_SPACING for mx gadgets. */

/* New to V37 GadTools.  Ignored by GadTools V36 */
#define GTMN_FullMenu	     GT_TagBase+62 /* Asks CreateMenus() to
        validate that this is a complete menu structure */
#define GTMN_SecondaryError  GT_TagBase+63 /* ti_Data is a pointer
        to a ULONG to receive error reports from CreateMenus() */
#define GT_Underscore	     GT_TagBase+64 /* ti_Data points to the symbol
        that preceeds the character you'd like to underline in a
        gadget label */
#define GTST_EditHook	     GT_TagBase+55 /* String EditHook */

/*  GT_TagBase+65 on up reserved for future use */

/* Old definition, now obsolete: */
#define GT_Reserved0	     GTST_EditHook

/*------------------------------------------------------------------------*/

/*  "NWay" is an old synonym for cycle gadgets */
#define NWAY_KIND	CYCLE_KIND
#define NWAYIDCMP	CYCLEIDCMP
#define GTNW_Labels	GTCY_Labels
#define GTNW_Active	GTCY_Active

/*------------------------------------------------------------------------*/

#endif /* LIBRARIES_GADTOOLS_H */


Includes/libraries/translator.i

    IFND	LIBRARIES_TRANSLATOR_I
LIBRARIES_TRANSLATOR_I	SET	1
**
**	$Filename: libraries/translator.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.1 $
**	$Date: 90/12/13 $
**
**	Useful definitions for translator.library
**
**	(C) Copyright 1988-1999 Amiga, Inc. and
**	Joseph Katz/Mark Barton.  All rights reserved.
**

*		;------	Translator error codes
TR_NotUsed	EQU	-1		;This is an often used system rc
TR_NoMem	EQU	-2		;Can't allocate memory
TR_MakeBad	EQU	-4		;Error in MakeLibrary call

    ENDC	; LIBRARIES_TRANSLATOR_I


Includes/libraries/dos.h

#ifndef LIBRARIES_DOS_H
#define LIBRARIES_DOS_H
/*
**	$Filename: libraries/dos.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.2 $
**	$Date: 90/07/12 $
**
**	Standard C header for AmigaDOS
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef DOS_DOS_H
#include "dos/dos.h"
#endif

#endif /* LIBRARIES_DOS_H */


Includes/libraries/gadtools.i

    IFND LIBRARIES_GADTOOLS_I
LIBRARIES_GADTOOLS_I	SET	1
**
**	$Filename: libraries/gadtools.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.13 $
**	$Date: 91/10/09 $
**
**	gadtools.library definitions
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	All Rights Reserved.
**

*------------------------------------------------------------------------*

    IFND EXEC_TYPES_I
    INCLUDE 'exec/types.i'
    ENDC

    IFND UTILITY_TAGITEM_I
    INCLUDE 'utility/tagitem.i'
    ENDC

    IFND INTUITION_INTUITION_I
    INCLUDE 'intuition/intuition.i'
    ENDC

*------------------------------------------------------------------------*

*	The kinds (almost classes) of gadgets in the toolkit.  Use these
*	identifiers when calling CreateGadgetA()

GENERIC_KIND	EQU	0
BUTTON_KIND	EQU	1
CHECKBOX_KIND	EQU	2
INTEGER_KIND	EQU	3
LISTVIEW_KIND	EQU	4
MX_KIND		EQU	5
NUMBER_KIND	EQU	6
CYCLE_KIND	EQU	7
PALETTE_KIND	EQU	8
SCROLLER_KIND	EQU	9
* Kind number 10 is reserved
SLIDER_KIND	EQU	11
STRING_KIND	EQU	12
TEXT_KIND	EQU	13

NUM_KINDS	EQU	14

*------------------------------------------------------------------------*

*  These two definitions are obsolete, but are here for backwards
*  compatibility.  You never need to worry about these:
GADTOOLBIT	EQU	$8000

*  Use this mask to isolate the user part: *
GADTOOLMASK	EQU	~GADTOOLBIT

*------------------------------------------------------------------------*

*  'Or' the appropriate set together for your Window IDCMPFlags: *

ARROWIDCMP	EQU	GADGETUP!GADGETDOWN!INTUITICKS!MOUSEBUTTONS

BUTTONIDCMP	EQU	GADGETUP
CHECKBOXIDCMP	EQU	GADGETUP
INTEGERIDCMP	EQU	GADGETUP
LISTVIEWIDCMP	EQU	GADGETUP!GADGETDOWN!MOUSEMOVE!ARROWIDCMP

MXIDCMP		EQU	GADGETDOWN
NUMBERIDCMP	EQU	0
CYCLEIDCMP	EQU	GADGETUP
PALETTEIDCMP	EQU	GADGETUP

*  Use ARROWIDCMP!SCROLLERIDCMP if your scrollers have arrows: *
SCROLLERIDCMP	EQU	GADGETUP!GADGETDOWN!MOUSEMOVE
SLIDERIDCMP	EQU	GADGETUP!GADGETDOWN!MOUSEMOVE
STRINGIDCMP	EQU	GADGETUP

TEXTIDCMP	EQU	0

*------------------------------------------------------------------------*

*  Typical suggested spacing between "elements": *
INTERWIDTH	EQU	8
INTERHEIGHT	EQU	4

*------------------------------------------------------------------------*

*  Generic NewGadget used by several of the gadget classes: *

    STRUCTURE NewGadget,0

    WORD	gng_LeftEdge
    WORD	gng_TopEdge	; gadget position
    WORD	gng_Width
    WORD	gng_Height	;  gadget size
    APTR	gng_GadgetText	; gadget label
    APTR	gng_TextAttr	; desired font for gadget label
    UWORD	gng_GadgetID	; gadget ID
    ULONG	gng_Flags	; see below
    APTR	gng_VisualInfo	; Set to retval of GetVisualInfo()
    APTR	gng_UserData	; gadget UserData

    LABEL	gng_SIZEOF

*   ng_Flags control certain aspects of the gadget.  The first five control
*   the placement of the descriptive text.  All larger groups supply a
*   default:

PLACETEXT_LEFT	EQU	$0001	* Right-align text on left side
PLACETEXT_RIGHT	EQU	$0002	* Left-align text on right side
PLACETEXT_ABOVE	EQU	$0004	* Center text above
PLACETEXT_BELOW	EQU	$0008	* Center text below
PLACETEXT_IN	EQU	$0010	* Center text on

NG_HIGHLABEL	EQU	$0020	* Highlight the label

*------------------------------------------------------------------------*

* Fill out an array of these and pass that to CreateMenus():

    STRUCTURE NewMenu,0

    UBYTE	gnm_Type		; See below
    UBYTE	gnm_Pad			; alignment padding
    APTR	gnm_Label		; Menu's label
    APTR	gnm_CommKey		; MenuItem Command Key Equiv
    UWORD	gnm_Flags		; Menu or MenuItem flags (see note)
    LONG	gnm_MutualExclude	; MenuItem MutualExclude word
    APTR	gnm_UserData		; For your own use, see note

    LABEL	gnm_SIZEOF

*  Each nm_Type should be one of these:
NM_TITLE	EQU	1
NM_ITEM		EQU	2
NM_SUB		EQU	3
NM_END		EQU	0

MENU_IMAGE	EQU	128

* For an image menu-item or sub-item, use one of these.  Set
* nm_Label to point at the Image structure you wish to use.
* NOTE: At present, you may only use conventional images.
* Custom images created from Intuition image-classes do not work.

IM_ITEM		EQU	NM_ITEM!MENU_IMAGE
IM_SUB		EQU	NM_SUB!MENU_IMAGE

*  If you set your label to NM_BARLABEL, you'll get a separator bar.
NM_BARLABEL	EQU	-1

*   The nm_Flags field is used to fill out either the Menu->Flags or
*   MenuItem->Flags field.  Note that the sense of the MENUENABLED or
*   ITEMENABLED bit is inverted between this use and Intuition's use,
*   in other words, NewMenus are enabled by default.  The following
*   labels are provided to disable them:

NM_MENUDISABLED	EQU	MENUENABLED
NM_ITEMDISABLED	EQU	ITEMENABLED

*   The following are pre-cleared (COMMSEQ, ITEMTEXT, and HIGHxxx are set
*   later as appropriate):

NM_FLAGMASK	EQU	~(COMMSEQ!ITEMTEXT!HIGHFLAGS)

*   You may choose among CHECKIT, MENUTOGGLE, and CHECKED.
*   Toggle-select menuitems are of type CHECKIT!MENUTOGGLE, along
*   with CHECKED if currently selected.  Mutually exclusive ones
*   are of type CHECKIT, and possibly CHECKED too.  The nm_MutualExclude
*   is a bit-wise representation of the items excluded by this one,
*   so in the simplest case (choose 1 among n), these flags would be
*   ~1, ~2, ~4, ~8, ~16, etc.  See the Intuition Menus chapter.

*   A UserData pointer can be associated with each Menu and MenuItem structure.
*   The CreateMenus() call allocates space for a UserData after each
*   Menu or MenuItem (header, item or sub-item).  You should use the
*   GTMENU_USERDATA or GTMENUITEM_USERDATA macro to extract it. */

GTMENU_USERDATA	MACRO
        move.l	mu_SIZEOF(\1),\2
        ENDM

GTMENUITEM_USERDATA	MACRO
        move.l	mi_SIZEOF(\1),\2
        ENDM

*  Here is an old one for compatibility.  Do not use in new code!
MENU_USERDATA	MACRO
        move.l	mi_SIZEOF(\1),\2
        ENDM

*  These return codes can be obtained through the GTMN_SecondaryError tag:
GTMENU_TRIMMED	EQU	$00000001	; Too many menus, items, or subitems,
                    ; menu has been trimmed down
GTMENU_INVALID	EQU	$00000002	; Invalid NewMenu array
GTMENU_NOMEM	EQU	$00000003	; Out of memory

*------------------------------------------------------------------------*

*  Tags for toolkit functions:

GT_TagBase	EQU	TAG_USER+$80000 ; Begin counting tags

GTVI_NewWindow	EQU	GT_TagBase+$01	; NewWindow struct for GetVisualInfo
GTVI_NWTags	EQU	GT_TagBase+$02	; NWTags for GetVisualInfo

GT_Private0	EQU	GT_TagBase+$03	; (private)

GTCB_Checked	EQU	GT_TagBase+$04	; State of checkbox

GTLV_Top	EQU	GT_TagBase+$05	; Top visible one in listview
GTLV_Labels	EQU	GT_TagBase+$06	; List to display in listview
GTLV_ReadOnly	EQU	GT_TagBase+$07	; TRUE if listview is to be read-only
GTLV_ScrollWidth	EQU	GT_TagBase+$08	; Width of scrollbar

GTMX_Labels	EQU	GT_TagBase+$09	; NULL-terminated array of labels
GTMX_Active	EQU	GT_TagBase+$0A	; Active one in mx gadget

GTTX_Text	EQU	GT_TagBase+$0B	; Text to display
GTTX_CopyText	EQU	GT_TagBase+$0C	; Copy text label instead of referencing it

GTNM_Number	EQU	GT_TagBase+$0D	; Number to display

GTCY_Labels	EQU	GT_TagBase+$0E	; NULL-terminated array of labels
GTCY_Active	EQU	GT_TagBase+$0F	; The active one in the cycle gad

GTPA_Depth	EQU	GT_TagBase+$10	; Number of bitplanes in palette
GTPA_Color	EQU	GT_TagBase+$11	; Palette color
GTPA_ColorOffset	EQU	GT_TagBase+$12	; First color to use in palette
GTPA_IndicatorWidth	EQU	GT_TagBase+$13	; Width of current-color indicator
GTPA_IndicatorHeight	EQU	GT_TagBase+$14	; Height of current-color indicator

GTSC_Top	EQU	GT_TagBase+$15	; Top visible in scroller
GTSC_Total	EQU	GT_TagBase+$16	; Total in scroller area
GTSC_Visible	EQU	GT_TagBase+$17	; Number visible in scroller
GTSC_Overlap	EQU	GT_TagBase+$18	; Unused

* GT_TagBase+$19 through GT_TagBase+$25 are reserved

GTSL_Min	EQU	GT_TagBase+$26	; Slider min value
GTSL_Max	EQU	GT_TagBase+$27	; Slider max value
GTSL_Level	EQU	GT_TagBase+$28	; Slider level
GTSL_MaxLevelLen	EQU	GT_TagBase+$29	; Max length of printed level
GTSL_LevelFormat	EQU	GT_TagBase+$2A	; Format string for level
GTSL_LevelPlace	EQU	GT_TagBase+$2B	; Where level should be placed
GTSL_DispFunc	EQU	GT_TagBase+$2C	; Callback for number calculation before display

GTST_String	EQU	GT_TagBase+$2D	; String gadget's displayed string
GTST_MaxChars	EQU	GT_TagBase+$2E	; Max length of string

GTIN_Number	EQU	GT_TagBase+$2F	; Number in integer gadget
GTIN_MaxChars	EQU	GT_TagBase+$30	; Max number of digits

GTMN_TextAttr	EQU	GT_TagBase+$31	; MenuItem font TextAttr
GTMN_FrontPen	EQU	GT_TagBase+$32	; MenuItem text pen color

GTBB_Recessed	EQU	GT_TagBase+$33	; Make BevelBox recessed

GT_VisualInfo	EQU	GT_TagBase+$34	; result of VisualInfo call

GTLV_ShowSelected	EQU	GT_TagBase+$35	; show selected entry beneath listview,
            ; set tag data = NULL for display-only, or pointer
            ; to a string gadget you've created
GTLV_Selected	EQU	GT_TagBase+$36	; Set ordinal number of selected entry in the list
GT_Reserved1	EQU	GT_TagBase+$38	; Reserved for future use

GTTX_Border	EQU	GT_TagBase+$39	; Put a border around Text-display gadgets
GTNM_Border	EQU	GT_TagBase+$3A	; Put a border around Number-display gadgets

GTSC_Arrows	EQU	GT_TagBase+$3B	; Specify size of arrows for scroller
GTMN_Menu	EQU	GT_TagBase+$3C	; Pointer to Menu for use by
            ; LayoutMenuItems()
GTMX_Spacing	EQU	GT_TagBase+$3D	; Added to font height to
            ; figure spacing between mx choices.  Use this
            ; instead of LAYOUTA_SPACING for mx gadgets.

*  New to V37 GadTools.  Ignored by GadTools V36.
GTMN_FullMenu	EQU	GT_TagBase+$3E  ; Asks CreateMenus() to
        ; validate that this is a complete menu structure
GTMN_SecondaryError	EQU	GT_TagBase+$3F  ; ti_Data is a pointer
        ; to a ULONG to receive error reports from CreateMenus()
GT_Underscore	EQU	GT_TagBase+$40	; ti_Data points to the symbol
        ; that preceeds the character you'd like to underline in a
        ; gadget label
GTST_EditHook	EQU	GT_TagBase+$37	; String EditHook

*  Old definition, now obsolete:
GT_Reserved0	EQU	GTST_EditHook

*------------------------------------------------------------------------*

* "NWay" is an old synonym for cycle gadgets

NWAY_KIND	EQU	CYCLE_KIND
NWAYIDCMP	EQU	CYCLEIDCMP

GTNW_Labels	EQU	GTCY_Labels
GTNW_Active	EQU	GTCY_Active

    ENDC


Includes/libraries/dos.i

    IFND	LIBRARIES_DOS_I
LIBRARIES_DOS_I SET	1
**
**	$Filename: libraries/dos.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.2 $
**	$Date: 90/07/12 $
**
**	Standard C header for AmigaDOS
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND	DOS_DOS_I
    INCLUDE	"dos/dos.i"
    ENDC

    ENDC	; LIBRARIES_DOS_I


Includes/libraries/iffparse.h

#ifndef IFF_IFFPARSE_H
#define IFF_IFFPARSE_H
/*
**	$Filename: libraries/iffparse.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 33.1 $
**	$Date: 90/11/20 $
**
**	Structure definitions for the all new good nifty IFF code.
**
**	(C) Copyright 1989-1999 Amiga, Inc., Stuart Ferguson and
**	Leo L. Schwab
**		All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif
#ifndef EXEC_LISTS_H
#include <exec/lists.h>
#endif
#ifndef EXEC_PORTS_H
#include <exec/ports.h>
#endif
#ifndef DEVICES_CLIPBOARD_H
#include <devices/clipboard.h>
#endif

/*
 * Struct associated with an active IFF stream.
 * "iff_Stream" is a value used by the client's read/write/seek functions -
 * it will not be accessed by the library itself and can have any value
 * (could even be a pointer or a BPTR).
 */
struct IFFHandle {
    ULONG	iff_Stream;
    ULONG	iff_Flags;
    LONG	iff_Depth;	/*  Depth of context stack.  */
    /*  There are private fields hiding here.  */
};

/*
 * Bit masks for "iff_Flags" field.
 */
#define IFFF_READ	0L			/* read mode - default */
#define IFFF_WRITE	1L			/* write mode */
#define IFFF_RWBITS	(IFFF_READ | IFFF_WRITE)	/* read/write bits */
#define IFFF_FSEEK	(1L<<1)			/* forward seek only */
#define IFFF_RSEEK	(1L<<2)			/* random seek */
#define	IFFF_RESERVED	0xFFFF0000L		/* Don't touch these bits. */

/*
 * When the library calls your stream handler, you'll be passed a pointer
 * to this structure as the "message packet".
 */
struct IFFStreamCmd {
    LONG	sc_Command;	/*  Operation to be performed (IFFCMD_)	*/
    APTR	sc_Buf;		/*  Pointer to data buffer		*/
    LONG	sc_NBytes;	/*  Number of bytes to be affected	*/
};

/*
 * A node associated with a context on the iff_Stack.  Each node
 * represents a chunk, the stack representing the current nesting
 * of chunks in the open IFF file.  Each context node has associated
 * local context items in the (private) LocalItems list.  The ID, type,
 * size and scan values describe the chunk associated with this node.
 */
struct ContextNode {
    struct MinNode	cn_Node;
    LONG		cn_ID;
    LONG		cn_Type;
    LONG		cn_Size;	/*  Size of this chunk		   */
    LONG		cn_Scan;	/*  # of bytes read/written so far */
    /*  There are private fields hiding here.  */
};

/*
 * Local context items live in the ContextNode's.  Each class is identified
 * by its lci_Ident code and has a (private) purge vector for when the
 * parent context node is popped.
 */
struct LocalContextItem {
    struct MinNode	lci_Node;
    ULONG		lci_ID,
            lci_Type,
            lci_Ident;
    /*  There are private fields hiding here.  */
};

/*
 * StoredProperty: a local context item containing the data stored
 * from a previously encountered property chunk.
 */
struct StoredProperty {
    LONG	sp_Size;
    UBYTE	*sp_Data;
};

/*
 * Collection Item: the actual node in the collection list at which
 * client will look.  The next pointers cross context boundaries so
 * that the complete list is accessable.
 */
struct CollectionItem {
    struct CollectionItem	*ci_Next;
    LONG			ci_Size;
    UBYTE			*ci_Data;
};

/*
 * Structure returned by OpenClipboard().  You may do CMD_POSTs and such
 * using this structure.  However, once you call OpenIFF(), you may not
 * do any more of your own I/O to the clipboard until you call CloseIFF().
 */
struct ClipboardHandle {
    struct IOClipReq	cbh_Req;
    struct MsgPort		cbh_CBport;
    struct MsgPort		cbh_SatisfyPort;
};

/*
 * IFF return codes.  Most functions return either zero for success or
 * one of these codes.	The exceptions are the read/write functions which
 * return positive values for number of bytes or records read or written,
 * or a negative error code.  Some of these codes are not errors per sae,
 * but valid conditions such as EOF or EOC (End of Chunk).
 */
#define	IFFERR_EOF		-1L	/*  Reached logical end of file	*/
#define IFFERR_EOC		-2L	/*  About to leave context	*/
#define	IFFERR_NOSCOPE		-3L	/*  No valid scope for property	*/
#define	IFFERR_NOMEM		-4L	/*  Internal memory alloc failed*/
#define	IFFERR_READ		-5L	/*  Stream read error		*/
#define	IFFERR_WRITE		-6L	/*  Stream write error		*/
#define	IFFERR_SEEK		-7L	/*  Stream seek error		*/
#define	IFFERR_MANGLED		-8L	/*  Data in file is corrupt	*/
#define	IFFERR_SYNTAX		-9L	/*  IFF syntax error		*/
#define	IFFERR_NOTIFF		-10L	/*  Not an IFF file		*/
#define	IFFERR_NOHOOK		-11L	/*  No call-back hook provided	*/
#define IFF_RETURN2CLIENT	-12L	/*  Client handler normal return*/

#define	MAKE_ID(a,b,c,d)	\
    ((ULONG) (a)<<24 | (ULONG) (b)<<16 | (ULONG) (c)<<8 | (ULONG) (d))

/*
 * Universal IFF identifiers.
 */
#define	ID_FORM			MAKE_ID('F','O','R','M')
#define	ID_LIST			MAKE_ID('L','I','S','T')
#define	ID_CAT			MAKE_ID('C','A','T',' ')
#define	ID_PROP			MAKE_ID('P','R','O','P')
#define	ID_NULL			MAKE_ID(' ',' ',' ',' ')

/*
 * Ident codes for universally recognized local context items.
 */
#define IFFLCI_PROP		MAKE_ID('p','r','o','p')
#define IFFLCI_COLLECTION	MAKE_ID('c','o','l','l')
#define IFFLCI_ENTRYHANDLER	MAKE_ID('e','n','h','d')
#define IFFLCI_EXITHANDLER	MAKE_ID('e','x','h','d')

/*
 * Control modes for ParseIFF() function.
 */
#define IFFPARSE_SCAN		0L
#define IFFPARSE_STEP		1L
#define IFFPARSE_RAWSTEP	2L

/*
 * Control modes for StoreLocalItem().
 */
#define IFFSLI_ROOT		1L	/*  Store in default context	   */
#define IFFSLI_TOP		2L	/*  Store in current context	   */
#define IFFSLI_PROP		3L	/*  Store in topmost FORM or LIST  */

/*
 * "Flag" for writing functions.  If you pass this value in as a size
 * to PushChunk() when writing a file, the parser will figure out the
 * size of the chunk for you.  (Chunk sizes >= 2**31 are forbidden by the
 * IFF specification, so this works.)
 */
#define	IFFSIZE_UNKNOWN		-1L

/*
 * Possible call-back command values.  (Using 0 as the value for IFFCMD_INIT
 * was, in retrospect, probably a bad idea.)
 */
#define	IFFCMD_INIT	0	/*  Prepare the stream for a session	*/
#define	IFFCMD_CLEANUP	1	/*  Terminate stream session		*/
#define	IFFCMD_READ	2	/*  Read bytes from stream		*/
#define	IFFCMD_WRITE	3	/*  Write bytes to stream		*/
#define	IFFCMD_SEEK	4	/*  Seek on stream			*/
#define	IFFCMD_ENTRY	5	/*  You just entered a new context	*/
#define	IFFCMD_EXIT	6	/*  You're about to leave a context	*/
#define	IFFCMD_PURGELCI	7	/*  Purge a LocalContextItem		*/

/*  Backward compatibility.  Don't use these in new code.  */
#define	IFFSCC_INIT	IFFCMD_INIT
#define	IFFSCC_CLEANUP	IFFCMD_CLEANUP
#define	IFFSCC_READ	IFFCMD_READ
#define	IFFSCC_WRITE	IFFCMD_WRITE
#define	IFFSCC_SEEK	IFFCMD_SEEK

#endif


Includes/resources/battclock.h

#ifndef RESOURCES_BATTCLOCK_H
#define RESOURCES_BATTCLOCK_H 1
/*
**	$Filename: resources/battclock.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.4 $
**	$Date: 90/05/01 $
**
**	BattClock resource name strings.
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**		All Rights Reserved
*/

#define BATTCLOCKNAME	"battclock.resource"

#endif /* RESOURCES_BATTCLOCK_H */


Includes/resources/cia.h

#ifndef DEVICES_CIA_H
#define DEVICES_CIA_H 1
/*
**	$Filename: resources/cia.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.4 $
**	$Date: 91/01/09 $
**
**	Cia resource name strings.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**		All Rights Reserved
*/

#define	CIAANAME "ciaa.resource"
#define	CIABNAME "ciab.resource"

#endif	/* DEVICES_CIA_H */


Includes/resources/misc.h

#ifndef RESOURCES_MISC_H
#define RESOURCES_MISC_H
/*
**	$Filename: resources/misc.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.13 $
**	$Date: 90/05/06 $
**
**	Unit number definitions for "misc.resource"
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include "exec/types.h"
#endif	/* EXEC_TYPES_H */

#ifndef EXEC_LIBRARIES_H
#include "exec/libraries.h"
#endif	/* EXEC_LIBRARIES_H */

/*
 * Unit number definitions.  Ownership of a resource grants low-level
 * bit access to the hardware registers.  You are still obligated to follow
 * the rules for shared access of the interrupt system (see
 * exec.library/SetIntVector or cia.resource as appropriate).
 */
#define	MR_SERIALPORT	0 /* Amiga custom chip serial port registers
                 (SERDAT,SERDATR,SERPER,ADKCON, and interrupts) */
#define	MR_SERIALBITS	1 /* Serial control bits (DTR,CTS, etc.) */
#define	MR_PARALLELPORT	2 /* The 8 bit parallel data port
                 (CIAAPRA & CIAADDRA only!) */
#define	MR_PARALLELBITS	3 /* All other parallel bits & interrupts
                 (BUSY,ACK,etc.) */

/*
 * Library vector offset definitions
 */
#define	MR_ALLOCMISCRESOURCE	(LIB_BASE)		/* -6 */
#define MR_FREEMISCRESOURCE	(LIB_BASE-LIB_VECTSIZE)	/* -12 */

#define MISCNAME "misc.resource"

#endif	/* RESOURCES_MISC_H */


Includes/resources/battclock.i

    IFND	RESOURCES_BATTCLOCK_I
RESOURCES_BATTCLOCK_I	SET	1
**
**	$Filename: resources/battclock.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.3 $
**	$Date: 90/05/01 $
**
**	BattClock resource name strings.
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**		All Rights Reserved
**

BATTCLOCKNAME	MACRO
        dc.b	'battclock.resource',0
        ds.w	0
        ENDM

    ENDC	; RESOURCES_BATTCLOCK_I


Includes/resources/cia.i

    IFND	DEVICES_CIA_I
DEVICES_CIA_I	SET	1
**
**	$Filename: resources/cia.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.3 $
**	$Date: 90/05/01 $
**
**	Cia resource name strings.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**		All Rights Reserved
**

CIAANAME	MACRO
        DC.B	'ciaa.resource',0
        ENDM

CIABNAME	MACRO
        DC.B	'ciab.resource',0
        ENDM

    ENDC	; DEVICES_CIA_I


Includes/resources/misc.i

    IFND	RESOURCES_MISC_I
RESOURCES_MISC_I	SET	1
**
**	$Filename: resources/misc.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.12 $
**	$Date: 90/05/06 $
**
**	Unit number definitions for "misc.resource"
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND	EXEC_TYPES_I
    INCLUDE "exec/types.i"
    ENDC	!EXEC_TYPES_I

    IFND	EXEC_LIBRARIES_I
    INCLUDE "exec/libraries.i"
    ENDC	!EXEC_LIBRARIES_I

*
* Unit number definitions.  Ownership of a resource grants low-level
* bit access to the hardware registers.  You are still obligated to follow
* the rules for shared access of the interrupt system.	(see
* exec.library/SetIntVector or cia.resource as appropriate).
*
MR_SERIALPORT	EQU 0	;Amiga custom chip serial port registers & interrupts
            ;(SERDAT,SERDATR,SERPER,ADKCON, and interrupts)
MR_SERIALBITS	EQU 1	;Serial control bits (DTR,CTS, etc.)
MR_PARALLELPORT	EQU 2	;The 8 bit parallel data port
            ;(CIAAPRA & CIAADDRA only!)
MR_PARALLELBITS	EQU 3	;All other parallel bits & interrupts (BUSY,ACK,etc.)

*
* Library vector offset definitions
*
    LIBINIT LIB_BASE
    LIBDEF	MR_ALLOCMISCRESOURCE	;-6
    LIBDEF	MR_FREEMISCRESOURCE	;-12

*
* Name of misc.resource
*
MISCNAME	MACRO
        DC.B	'misc.resource',0
        CNOP	0,2
        ENDM

    ENDC	;RESOURCE_MISC_I


Includes/resources/battmem.h

#ifndef RESOURCES_BATTMEM_H
#define RESOURCES_BATTMEM_H 1
/*
**	$Filename: resources/battmem.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.4 $
**	$Date: 90/05/01 $
**
**	BattMem resource name strings.
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**		All Rights Reserved
*/

#define BATTMEMNAME	"battmem.resource"

#endif /* RESOURCES_BATTMEM_H */


Includes/resources/ciabase.h

#ifndef RESOURCES_CIA_H
#define RESOURCES_CIA_H
/*
**	$Filename: resources/ciabase.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.2 $
**	$Date: 90/05/16 $
**
**	cia base definitions
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/

/*
 *	There is no public information in CiaBase
 */

#endif	/* RESOURCES_CIA_H */


Includes/resources/potgo.h

#ifndef RESOURCES_POTGO_H
#define RESOURCES_POTGO_H
/*
**	$Filename: resources/potgo.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.0 $
**	$Date: 90/04/13 $
**
**	potgo resource name
**
**	(C) Copyright 1986-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#define  POTGONAME	"potgo.resource"
#endif	 /* RESOURCES_POTGO_H */


Includes/resources/battmem.i

    IFND	RESOURCES_BATTMEM_I
RESOURCES_BATTMEM_I	SET	1
**
**	$Filename: resources/battmem.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.3 $
**	$Date: 90/05/01 $
**
**	BattMem resource name strings.
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**		All Rights Reserved
**

BATTMEMNAME	MACRO
        dc.b	'battmem.resource',0
        ds.w	0
        ENDM

    ENDC	; RESOURCES_BATTMEM_I


Includes/resources/ciabase.i

    IFND	RESOURCES_CIA_I
RESOURCES_CIA_I	SET	1
**
**	$Filename: resources/ciabase.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.2 $
**	$Date: 90/05/16 $
**
**	cia base definitions
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
**

;	There is no public information in CiaBase

    ENDC	; RESOURCES_CIA_I


Includes/resources/potgo.i

    IFND	RESOURCES_POTGO_I
RESOURCES_POTGO_I	EQU	1
**
**	$Filename: resources/potgo.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.0 $
**	$Date: 90/04/13 $
**
**	potgo resource name
**
**	(C) Copyright 1986-1999 Amiga, Inc.
**	    All Rights Reserved
**
POTGONAME MACRO
        dc.b	'potgo.resource',0
        ds.w	0
    ENDM

    ENDC	; RESOURCES_POTGO_I


Includes/resources/battmembitsamiga.h

#ifndef RESOURCES_BATTMEMBITSAMIGA_H
#define RESOURCES_BATTMEMBITSAMIGA_H 1
/*
**	$Filename: resources/battmembitsamiga.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.1 $
**	$Date: 90/05/25 $
**
**	BattMem Amiga specific bit definitions.
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**		All Rights Reserved
*/

/*
 * Amiga specific bits in the battery-backedup ram.
 *
 *	Bits 0 to 31, inclusive
 */

/*
 * AMIGA_AMNESIA
 *
 *		The battery-backedup memory has had a memory loss.
 *		This bit is used as a flag that the user should be
 *		notified that all battery-backed bit have been
 *		reset and that some attention is required. Zero
 *		indicates that a memory loss has occured.
 */

#define BATTMEM_AMIGA_AMNESIA_ADDR	0
#define BATTMEM_AMIGA_AMNESIA_LEN	1

/*
 * SCSI_TIMEOUT
 *
 *		adjusts the timeout value for SCSI device selection.  A
 *		value of 0 will produce short timeouts (128 ms) while a
 *		value of 1 produces long timeouts (2 sec).  This is used
 *		for SeaCrate drives (and some Maxtors apparently) that
 *		don`t respond to selection until they are fully spun up
 *		and intialised.
 */

#define BATTMEM_SCSI_TIMEOUT_ADDR	1
#define BATTMEM_SCSI_TIMEOUT_LEN	1

/*
 * SCSI_LUNS
 *
 *		Determines if the controller attempts to access logical
 *		units above 0 at any given SCSI address.  This prevents
 *		problems with drives that respond to ALL LUN addresses
 *		(instead of only 0 like they should).  Default value is
 *		0 meaning don't support LUNs.
 */

#define BATTMEM_SCSI_LUNS_ADDR		2
#define BATTMEM_SCSI_LUNS_LEN		1

#endif /* RESOURCES_BATTMEMBITSAMIGA_H */


Includes/resources/disk.h

#ifndef	RESOURCES_DISK_H
#define RESOURCES_DISK_H
/*
**	$Filename: resources/disk.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 27.11 $
**	$Date: 90/11/21 $
**
**	disk.h -- external declarations for the disk resource
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef	EXEC_TYPES_H
#include "exec/types.h"
#endif

#ifndef	EXEC_LISTS_H
#include "exec/lists.h"
#endif

#ifndef	EXEC_PORTS_H
#include "exec/ports.h"
#endif

#ifndef	EXEC_INTERRUPTS_H
#include "exec/interrupts.h"
#endif

#ifndef	EXEC_LIBRARIES_H
#include "exec/libraries.h"
#endif

/********************************************************************
*
* Resource structures
*
********************************************************************/

struct DiscResourceUnit {
    struct Message dru_Message;
    struct Interrupt dru_DiscBlock;
    struct Interrupt dru_DiscSync;
    struct Interrupt dru_Index;
};

struct DiscResource {
    struct Library		dr_Library;
    struct DiscResourceUnit	*dr_Current;
    UBYTE			dr_Flags;
    UBYTE			dr_pad;
    struct Library		*dr_SysLib;
    struct Library		*dr_CiaResource;
    ULONG			dr_UnitID[4];
    struct List		dr_Waiting;
    struct Interrupt		dr_DiscBlock;
    struct Interrupt		dr_DiscSync;
    struct Interrupt		dr_Index;
    struct Task			*dr_CurrTask;
};

/* dr_Flags entries */
#define DRB_ALLOC0	0	/* unit zero is allocated */
#define DRB_ALLOC1	1	/* unit one is allocated */
#define DRB_ALLOC2	2	/* unit two is allocated */
#define DRB_ALLOC3	3	/* unit three is allocated */
#define DRB_ACTIVE	7	/* is the disc currently busy? */

#define DRF_ALLOC0	(1<<0)	/* unit zero is allocated */
#define DRF_ALLOC1	(1<<1)	/* unit one is allocated */
#define DRF_ALLOC2	(1<<2)	/* unit two is allocated */
#define DRF_ALLOC3	(1<<3)	/* unit three is allocated */
#define DRF_ACTIVE	(1<<7)	/* is the disc currently busy? */

/********************************************************************
*
* Hardware Magic
*
********************************************************************/

#define	DSKDMAOFF	0x4000	/* idle command for dsklen register */

/********************************************************************
*
* Resource specific commands
*
********************************************************************/

/*
 * DISKNAME is a generic macro to get the name of the resource.
 * This way if the name is ever changed you will pick up the
 *  change automatically.
 */

#define DISKNAME	"disk.resource"

#define	DR_ALLOCUNIT	(LIB_BASE - 0*LIB_VECTSIZE)
#define	DR_FREEUNIT	(LIB_BASE - 1*LIB_VECTSIZE)
#define	DR_GETUNIT	(LIB_BASE - 2*LIB_VECTSIZE)
#define	DR_GIVEUNIT	(LIB_BASE - 3*LIB_VECTSIZE)
#define	DR_GETUNITID	(LIB_BASE - 4*LIB_VECTSIZE)
#define	DR_READUNITID	(LIB_BASE - 5*LIB_VECTSIZE)

#define	DR_LASTCOMM	(DR_READUNITID)

/********************************************************************
*
* drive types
*
********************************************************************/

#define	DRT_AMIGA	(0x00000000)
#define	DRT_37422D2S	(0x55555555)
#define DRT_EMPTY	(0xFFFFFFFF)
#define DRT_150RPM	(0xAAAAAAAA)

#endif /* RESOURCES_DISK_H */


Includes/resources/battmembitsamiga.i

    IFND	RESOURCES_BATTMEMBITSAMIGA_I
RESOURCES_BATTMEMBITSAMIGA_I	SET	1
**
**	$Filename: resources/battmembitsamiga.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.2 $
**	$Date: 90/05/29 $
**
**	BattMem Amiga specific bit definitions.
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**		All Rights Reserved
**

*
* Amiga specific bits in the battery-backedup ram.
*
*	Bits 0 to 31, inclusive
*

*
* AMIGA_AMNESIA
*
*		The battery-backedup memory has had a memory loss.
*		This bit is used as a flag that the user should be
*		notified that all battery-backed bit have been
*		reset and that some attention is required. Zero
*		indicates that a memory loss has occured.
*

BATTMEM_AMIGA_AMNESIA_ADDR	EQU	0
BATTMEM_AMIGA_AMNESIA_LEN	EQU	1

*
* SCSI_TIMEOUT
*
*		adjusts the timeout value for SCSI device selection.  A
*		value of 0 will produce short timeouts (128 ms) while a
*		value of 1 produces long timeouts (2 sec).  This is used
*		for SeaCrate drives (and some Maxtors apparently) that
*		don`t respond to selection until they are fully spun up
*		and intialised.
*

BATTMEM_SCSI_TIMEOUT_ADDR	EQU	1
BATTMEM_SCSI_TIMEOUT_LEN	EQU	1

*
* SCSI_LUNS
*
*		Determines if the controller attempts to access logical
*		units above 0 at any given SCSI address.  This prevents
*		problems with drives that respond to ALL LUN addresses
*		(instead of only 0 like they should).  Default value is
*		0 meaning don't support LUNs.
*

BATTMEM_SCSI_LUNS_ADDR		EQU	2
BATTMEM_SCSI_LUNS_LEN		EQU	1

    ENDC	; RESOURCES_BATTMEMBITSAMIGA_I


Includes/resources/disk.i

    IFND	RESOURCES_DISK_I
RESOURCES_DISK_I	SET	1
**
**	$Filename: resources/disk.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 27.10 $
**	$Date: 90/11/21 $
**
**	disk.i -- external declarations for the disk resource
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND	EXEC_TYPES_I
    INCLUDE	"exec/types.i"
    ENDC	!EXEC_TYPES_I

    IFND	EXEC_LISTS_I
    INCLUDE	"exec/lists.i"
    ENDC	!EXEC_LISTS_I

    IFND	EXEC_PORTS_I
    INCLUDE	"exec/ports.i"
    ENDC	!EXEC_PORTS_I

    IFND	EXEC_INTERRUPTS_I
    INCLUDE	"exec/interrupts.i"
    ENDC	!EXEC_INTERRUPTS_I

    IFND	EXEC_LIBRARIES_I
    INCLUDE	"exec/libraries.i"
    ENDC	!EXEC_LIBRARIES_I

*********************************************************************
*
* Resource structures
*
*********************************************************************

    STRUCTURE DISCRESOURCEUNIT,MN_SIZE
    STRUCT	DRU_DISCBLOCK,IS_SIZE
    STRUCT	DRU_DISCSYNC,IS_SIZE
    STRUCT	DRU_INDEX,IS_SIZE
    LABEL	DRU_SIZE

    STRUCTURE DISCRESOURCE,LIB_SIZE
    APTR	DR_CURRENT	; pointer to current unit structure
    UBYTE	DR_FLAGS
    UBYTE	DR_pad
    APTR	DR_SYSLIB
    APTR	DR_CIARESOURCE
    STRUCT	DR_UNITID,4*4
    STRUCT	DR_WAITING,LH_SIZE
    STRUCT	DR_DISCBLOCK,IS_SIZE
    STRUCT	DR_DISCSYNC,IS_SIZE
    STRUCT	DR_INDEX,IS_SIZE
    APTR	DR_CURRTASK	; pointer to owning task for GiveUnit
    LABEL	DR_SIZE

    BITDEF	DR,ALLOC0,0	; unit zero is allocated
    BITDEF	DR,ALLOC1,1	; unit one is allocated
    BITDEF	DR,ALLOC2,2	; unit two is allocated
    BITDEF	DR,ALLOC3,3	; unit three is allocated
    BITDEF	DR,ACTIVE,7	; is the disc currently busy?

*********************************************************************
*
* Hardware Magic
*
*********************************************************************

DSKDMAOFF	EQU	$4000	; idle command for dsklen register

*********************************************************************
*
* Resource specific commands
*
*********************************************************************

*-- DR_NAME is a generic macro to get the name of the resource.  This
*-- way if the name is ever changed you will pick up the change
*-- automatically.
*--
*-- Normal usage would be:
*--
*-- internalName:	DISKNAME
*--

DISKNAME:	MACRO
        DC.B	'disk.resource',0
        DS.W	0
        ENDM

    LIBINIT LIB_BASE
    LIBDEF	DR_ALLOCUNIT
    LIBDEF	DR_FREEUNIT
    LIBDEF	DR_GETUNIT
    LIBDEF	DR_GIVEUNIT
    LIBDEF	DR_GETUNITID
    LIBDEF	DR_READUNITID

DR_LASTCOMM	EQU	DR_READUNITID

*********************************************************************
*
* drive types
*
*********************************************************************

DRT_AMIGA	EQU	$00000000
DRT_37422D2S	EQU	$55555555
DRT_EMPTY	EQU	$FFFFFFFF
DRT_150RPM	EQU	$AAAAAAAA

    ENDC	; RESOURCES_DISK_I


Includes/resources/battmembitsamix.h

#ifndef RESOURCES_BATTMEMBITSAMIX_H
#define RESOURCES_BATTMEMBITSAMIX_H 1
/*
**	$Filename: resources/battmembitsamix.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.1 $
**	$Date: 90/05/25 $
**
**	BattMem Amix specific bit definitions.
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**		All Rights Reserved
*/

/*
 *	See Amix documentation for these bit definitions
 *
 *	Bits 32 to 63, inclusive
 */

#endif /* RESOURCES_BATTMEMBITSAMIX_H */


Includes/resources/filesysres.h

#ifndef	RESOURCES_FILESYSRES_H
#define	RESOURCES_FILESYSRES_H
/*
**	$Filename: resources/filesysres.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.4 $
**	$Date: 90/05/03 $
**
**	FileSystem.resource description
**
**	(C) Copyright 1988-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef	EXEC_NODES_H
#include	"exec/nodes.h"
#endif
#ifndef	EXEC_LISTS_H
#include	"exec/lists.h"
#endif
#ifndef	DOS_DOS_H
#include	"dos/dos.h"
#endif

#define	FSRNAME	"FileSystem.resource"

struct FileSysResource {
    struct Node fsr_Node;		/* on resource list */
    char   *fsr_Creator;		/* name of creator of this resource */
    struct List fsr_FileSysEntries;	/* list of FileSysEntry structs */
};

struct FileSysEntry {
    struct Node fse_Node;	/* on fsr_FileSysEntries list */
                /* ln_Name is of creator of this entry */
    ULONG   fse_DosType;	/* DosType of this FileSys */
    ULONG   fse_Version;	/* Version of this FileSys */
    ULONG   fse_PatchFlags;	/* bits set for those of the following that */
                /*   need to be substituted into a standard */
                /*   device node for this file system: e.g. */
                /*   0x180 for substitute SegList & GlobalVec */
    ULONG   fse_Type;		/* device node type: zero */
    CPTR    fse_Task;		/* standard dos "task" field */
    BPTR    fse_Lock;		/* not used for devices: zero */
    BSTR    fse_Handler;	/* filename to loadseg (if SegList is null) */
    ULONG   fse_StackSize;	/* stacksize to use when starting task */
    LONG    fse_Priority;	/* task priority when starting task */
    BPTR    fse_Startup;	/* startup msg: FileSysStartupMsg for disks */
    BPTR    fse_SegList;	/* code to run to start new task */
    BPTR    fse_GlobalVec;	/* BCPL global vector when starting task */
    /* no more entries need exist than those implied by fse_PatchFlags */
};

#endif	/* RESOURCES_FILESYSRES_H */


Includes/resources/battmembitsamix.i

    IFND	RESOURCES_BATTMEMBITSAMIX_I
RESOURCES_BATTMEMBITSAMIX_I	SET	1
**
**	$Filename: resources/battmembitsamix.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.2 $
**	$Date: 90/05/29 $
**
**	BattMem Amix specific bit definitions.
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**		All Rights Reserved
**

*
*	See Amix documentation for these bit definitions
*
*	Bits 32 to 63, inclusive
*

    ENDC	; RESOURCES_BATTMEMBITSAMIX_I


Includes/resources/filesysres.i

    IFND	RESOURCES_FILESYSRES_I
RESOURCES_FILESYSRES_I	SET	1
**
**	$Filename: resources/filesysres.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.4 $
**	$Date: 90/05/03 $
**
**	FileSystem.resource description
**
**	(C) Copyright 1988-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND	EXEC_NODES_I
    INCLUDE	"exec/nodes.i"
    ENDC
    IFND	EXEC_LISTS_I
    INCLUDE	"exec/lists.i"
    ENDC
    IFND	DOS_DOS_I
    INCLUDE	"dos/dos.i"
    ENDC

FSRNAME	MACRO
        dc.b	'FileSystem.resource',0
    ENDM

 STRUCTURE  FileSysResource,LN_SIZE	; on resource list
    CPTR    fsr_Creator			; name of creator of this resource
    STRUCT  fsr_FileSysEntries,LH_SIZE	; list of FileSysEntry structs
    LABEL   FileSysResource_SIZEOF

 STRUCTURE  FileSysEntry,LN_SIZE	; on fsr_FileSysEntries list
                    ; LN_NAME is of creator of this entry
    ULONG   fse_DosType		; DosType of this FileSys
    ULONG   fse_Version		; Version of this FileSys
    ULONG   fse_PatchFlags	; bits set for those of the following that need
                ;   to be substituted into a standard device
                ;   node for this file system: e.g. $180
                ;   for substitute SegList & GlobalVec
    ULONG   fse_Type		; device node type: zero
    CPTR    fse_Task		; standard dos "task" field
    BPTR    fse_Lock		; not used for devices: zero
    BSTR    fse_Handler		; filename to loadseg (if SegList is null)
    ULONG   fse_StackSize	; stacksize to use when starting task
    LONG    fse_Priority	; task priority when starting task
    BPTR    fse_Startup		; startup msg: FileSysStartupMsg for disks
    BPTR    fse_SegList		; code to run to start new task
    BPTR    fse_GlobalVec	; BCPL global vector when starting task
    ; no more entries need exist than those implied by fse_PatchFlags

    ENDC	; RESOURCES_FILESYSRES_I


Includes/resources/battmembitsshared.h

#ifndef RESOURCES_BATTMEMBITSSHARED_H
#define RESOURCES_BATTMEMBITSSHARED_H 1
/*
**	$Filename: resources/battmembitsshared.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.1 $
**	$Date: 90/05/25 $
**
**	BattMem shared specific bit definitions.
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**		All Rights Reserved
*/

/*
 * Shared bits in the battery-backedup ram.
 *
 *	Bits 64 and above
 */

/*
 * SHARED_AMNESIA
 *
 *		The battery-backedup memory has had a memory loss.
 *		This bit is used as a flag that the user should be
 *		notified that all battery-backed bit have been
 *		reset and that some attention is required. Zero
 *		indicates that a memory loss has occured.
 */

#define BATTMEM_SHARED_AMNESIA_ADDR	64
#define BATTMEM_SHARED_AMNESIA_LEN	1

/*
 * SCSI_HOST_ID
 *
 *		a 3 bit field (0-7) that is stored in complemented form
 *		(this is so that default value of 0 really means 7)
 *		It's used to set the A3000 controllers SCSI ID (on reset)
 */

#define BATTMEM_SCSI_HOST_ID_ADDR	65
#define BATTMEM_SCSI_HOST_ID_LEN	3

/*
 * SCSI_SYNC_XFER
 *
 *		determines if the driver should initiate synchronous
 *		transfer requests or leave it to the drive to send the
 *		first request.	This supports drives that crash or
 *		otherwise get confused when presented with a sync xfer
 *		message.  Default=0=sync xfer not initiated.
 */

#define BATTMEM_SCSI_SYNC_XFER_ADDR	68
#define BATTMEM_SCSI_SYNC_XFER_LEN	1

#endif /* RESOURCES_BATTMEMBITSSHARED_H */


Includes/resources/mathresource.h

#ifndef	RESOURCES_MATHRESOURCE_H
#define	RESOURCES_MATHRESOURCE_H
/*
**	$Filename: resources/mathresource.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.2 $
**	$Date: 90/07/13 $
**
**	Data structure returned by OpenResource of:
**	"MathIEEE.resource"
**
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_NODES_H
#include <exec/nodes.h>
#endif

/*
*	The 'Init' entries are only used if the corresponding
*	bit is set in the Flags field.
*
*	So if you are just a 68881, you do not need the Init stuff
*	just make sure you have cleared the Flags field.
*
*	This should allow us to add Extended Precision later.
*
*	For Init users, if you need to be called whenever a task
*	opens this library for use, you need to change the appropriate
*	entries in MathIEEELibrary.
*/

struct MathIEEEResource
{
    struct	Node	MathIEEEResource_Node;
    unsigned short	MathIEEEResource_Flags;
    unsigned short	*MathIEEEResource_BaseAddr; /* ptr to 881 if exists */
    void	(*MathIEEEResource_DblBasInit)();
    void	(*MathIEEEResource_DblTransInit)();
    void	(*MathIEEEResource_SglBasInit)();
    void	(*MathIEEEResource_SglTransInit)();
    void	(*MathIEEEResource_ExtBasInit)();
    void	(*MathIEEEResource_ExtTransInit)();
};

/* definations for MathIEEEResource_FLAGS */
#define	MATHIEEERESOURCEF_DBLBAS	(1<<0)
#define	MATHIEEERESOURCEF_DBLTRANS	(1<<1)
#define	MATHIEEERESOURCEF_SGLBAS	(1<<2)
#define	MATHIEEERESOURCEF_SGLTRANS	(1<<3)
#define	MATHIEEERESOURCEF_EXTBAS	(1<<4)
#define	MATHIEEERESOURCEF_EXTTRANS	(1<<5)

#endif	/* RESOURCES_MATHRESOURCE_H */


Includes/resources/battmembitsshared.i

    IFND	RESOURCES_BATTMEMSHARED_I
RESOURCES_BATTMEMBITSSHARED_I	SET	1
**
**	$Filename: resources/battmembitsshared.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.2 $
**	$Date: 90/05/29 $
**
**	BattMem shared specific bit definitions.
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**		All Rights Reserved
**

*
* Shared bits in the battery-backedup ram.
*
*	Bits 64 and above
*

*
* SHARED_AMNESIA
*
*		The battery-backedup memory has had a memory loss.
*		This bit is used as a flag that the user should be
*		notified that all battery-backed bit have been
*		reset and that some attention is required. Zero
*		indicates that a memory loss has occured.
*

BATTMEM_SHARED_AMNESIA_ADDR	EQU	64
BATTMEM_SHARED_AMNESIA_LEN	EQU	1

*
* SCSI_HOST_ID
*
*		a 3 bit field (0-7) that is stored in complemented form
*		(this is so that default value of 0 really means 7)
*		It's used to set the A3000 controllers SCSI ID (on reset)
*

BATTMEM_SCSI_HOST_ID_ADDR	EQU	65
BATTMEM_SCSI_HOST_ID_LEN	EQU	3

*
* SCSI_SYNC_XFER
*
*		determines if the driver should initiate synchronous
*		transfer requests or leave it to the drive to send the
*		first request.  This supports drives that crash or
*		otherwise get confused when presented with a sync xfer
*		message.  Default=0=sync xfer not initiated.
*

BATTMEM_SCSI_SYNC_XFER_ADDR	EQU	68
BATTMEM_SCSI_SYNC_XFER_LEN	EQU	1

    ENDC	; RESOURCES_BATTMEMSHARED_I


Includes/resources/mathresource.i

    IFND	RESOURCES_MATHRESOURCE_I
RESOURCES_MATHRESOURCE_I	SET	1
**
**	$Filename: resources/mathresource.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.3 $
**	$Date: 90/07/13 $
**
**	Data structure returned by OpenResource of:
**	"MathIEEE.resource"
**
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
**

    IFND EXEC_NODES_I
    include "exec/nodes.i"
    ENDC

*
*	The 'Init' entries are only used if the corresponding
*	bit is set in the Flags field.
*
*	So if you are just a 68881, you do not need the Init stuff
*	just make sure you have cleared the Flags field.
*
*	This should allow us to add Extended Precision later.
*
*	For Init users, if you need to be called whenever a task
*	opens this library for use, you need to change the appropriate
*	entries in MathIEEELibrary.
*

    STRUCTURE MathIEEEResourceResource,0
        STRUCT	MathIEEEResource_Node,LN_SIZE
        USHORT	MathIEEEResource_Flags
        APTR	MathIEEEResource_BaseAddr	* ptr to 881 if exists *
        APTR	MathIEEEResource_DblBasInit
        APTR	MathIEEEResource_DblTransInit
        APTR	MathIEEEResource_SglBasInit
        APTR	MathIEEEResource_SglTransInit
        APTR	MathIEEEResource_ExtBasInit
        APTR	MathIEEEResource_ExtTransInit
    LABEL	MathIEEEResourceResource_SIZE

* definations for MathIEEERESOURCE_FLAGS *
    BITDEF	MATHIEEERESOURCE,DBLBAS,0
    BITDEF	MATHIEEERESOURCE,DBLTRANS,1
    BITDEF	MATHIEEERESOURCE,SGLBAS,2
    BITDEF	MATHIEEERESOURCE,SGLTRANS,3
    BITDEF	MATHIEEERESOURCE,EXTBAS,4
    BITDEF	MATHIEEERESOURCE,EXTTRANS,5

    ENDC	; RESOURCES_MATHRESOURCE_I


Includes/rexx/errors.h

#ifndef REXX_ERRORS_H
#define REXX_ERRORS_H
/*
**	$Filename: rexx/errors.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.4 $
**	$Date: 91/11/08 $
**
**	Definitions for ARexx error codes
**
**	(C) Copyright 1987,1988,1989,1990 William S. Hawes
**	(C) Copyright 1990-1999 Amiga, Inc.
**		All Rights Reserved
*/

#define ERRC_MSG  0		       /*  error code offset	       */
#define ERR10_001 (ERRC_MSG+1)	       /*  program not found	       */
#define ERR10_002 (ERRC_MSG+2)	       /*  execution halted	       */
#define ERR10_003 (ERRC_MSG+3)	       /*  no memory available	       */
#define ERR10_004 (ERRC_MSG+4)	       /*  invalid character in program*/
#define ERR10_005 (ERRC_MSG+5)	       /*  unmatched quote	       */
#define ERR10_006 (ERRC_MSG+6)	       /*  unterminated comment        */
#define ERR10_007 (ERRC_MSG+7)	       /*  clause too long	       */
#define ERR10_008 (ERRC_MSG+8)	       /*  unrecognized token	       */
#define ERR10_009 (ERRC_MSG+9)	       /*  symbol or string too long   */

#define ERR10_010 (ERRC_MSG+10)        /*  invalid message packet      */
#define ERR10_011 (ERRC_MSG+11)        /*  command string error        */
#define ERR10_012 (ERRC_MSG+12)        /*  error return from function  */
#define ERR10_013 (ERRC_MSG+13)        /*  host environment not found  */
#define ERR10_014 (ERRC_MSG+14)        /*  required library not found  */
#define ERR10_015 (ERRC_MSG+15)        /*  function not found	       */
#define ERR10_016 (ERRC_MSG+16)        /*  no return value	       */
#define ERR10_017 (ERRC_MSG+17)        /*  wrong number of arguments   */
#define ERR10_018 (ERRC_MSG+18)        /*  invalid argument to function*/
#define ERR10_019 (ERRC_MSG+19)        /*  invalid PROCEDURE	       */

#define ERR10_020 (ERRC_MSG+20)        /*  unexpected THEN/ELSE        */
#define ERR10_021 (ERRC_MSG+21)        /*  unexpected WHEN/OTHERWISE   */
#define ERR10_022 (ERRC_MSG+22)        /*  unexpected LEAVE or ITERATE */
#define ERR10_023 (ERRC_MSG+23)        /*  invalid statement in SELECT */
#define ERR10_024 (ERRC_MSG+24)        /*  missing THEN clauses        */
#define ERR10_025 (ERRC_MSG+25)        /*  missing OTHERWISE	       */
#define ERR10_026 (ERRC_MSG+26)        /*  missing or unexpected END   */
#define ERR10_027 (ERRC_MSG+27)        /*  symbol mismatch on END      */
#define ERR10_028 (ERRC_MSG+28)        /*  invalid DO syntax	       */
#define ERR10_029 (ERRC_MSG+29)        /*  incomplete DO/IF/SELECT     */

#define ERR10_030 (ERRC_MSG+30)        /*  label not found	       */
#define ERR10_031 (ERRC_MSG+31)        /*  symbol expected	       */
#define ERR10_032 (ERRC_MSG+32)        /*  string or symbol expected   */
#define ERR10_033 (ERRC_MSG+33)        /*  invalid sub-keyword	       */
#define ERR10_034 (ERRC_MSG+34)        /*  required keyword missing    */
#define ERR10_035 (ERRC_MSG+35)        /*  extraneous characters       */
#define ERR10_036 (ERRC_MSG+36)        /*  sub-keyword conflict        */
#define ERR10_037 (ERRC_MSG+37)        /*  invalid template	       */
#define ERR10_038 (ERRC_MSG+38)        /*  invalid TRACE request       */
#define ERR10_039 (ERRC_MSG+39)        /*  uninitialized variable      */

#define ERR10_040 (ERRC_MSG+40)        /*  invalid variable name       */
#define ERR10_041 (ERRC_MSG+41)        /*  invalid expression	       */
#define ERR10_042 (ERRC_MSG+42)        /*  unbalanced parentheses      */
#define ERR10_043 (ERRC_MSG+43)        /*  nesting level exceeded      */
#define ERR10_044 (ERRC_MSG+44)        /*  invalid expression result   */
#define ERR10_045 (ERRC_MSG+45)        /*  expression required	       */
#define ERR10_046 (ERRC_MSG+46)        /*  boolean value not 0 or 1    */
#define ERR10_047 (ERRC_MSG+47)        /*  arithmetic conversion error */
#define ERR10_048 (ERRC_MSG+48)        /*  invalid operand	       */

/*
 * Return Codes for general use
 */
#define RC_OK	  0L		       /*  success		       */
#define RC_WARN   5L		       /*  warning only	       */
#define RC_ERROR  10L		       /*  something's wrong	       */
#define RC_FATAL  20L		       /*  complete or severe failure  */

#endif


Includes/rexx/rexxio.h

#ifndef REXX_REXXIO_H
#define REXX_REXXIO_H
/*
**	$Filename: rexx/rexxio.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.4 $
**	$Date: 91/11/08 $
**
**	Header file for ARexx Input/Output related structures
**
**	(C) Copyright 1986,1987,1988,1989,1990 William S. Hawes
**	(C) Copyright 1990-1999 Amiga, Inc.
**		All Rights Reserved
*/

#ifndef REXX_STORAGE_H
#include "rexx/storage.h"
#endif

#define RXBUFFSZ  204		       /* buffer length		*/

/*
 * The IoBuff is a resource node used to maintain the File List.  Nodes
 * are allocated and linked into the list whenever a file is opened.
 */
struct IoBuff {
   struct RexxRsrc iobNode;	       /* structure for files/strings	*/
   APTR     iobRpt;		       /* read/write pointer		*/
   LONG     iobRct;		       /* character count		*/
   LONG     iobDFH;		       /* DOS filehandle		*/
   APTR     iobLock;		       /* DOS lock			*/
   LONG     iobBct;		       /* buffer length		*/
   BYTE     iobArea[RXBUFFSZ];	       /* buffer area			*/
   };				       /* size: 256 bytes		*/

/* Access mode definitions						*/
#define RXIO_EXIST   -1	       /* an external filehandle	*/
#define RXIO_STRF    0		       /* a "string file"		*/
#define RXIO_READ    1		       /* read-only access		*/
#define RXIO_WRITE   2		       /* write mode			*/
#define RXIO_APPEND  3		       /* append mode (existing file)	*/

/*
 * Offset anchors for SeekF()
 */
#define RXIO_BEGIN   -1L	       /* relative to start		*/
#define RXIO_CURR    0L	       /* relative to current position	*/
#define RXIO_END     1L	       /* relative to end		*/

/* The Library List contains just plain resource nodes.		*/

#define LLOFFSET(rrp) (rrp->rr_Arg1)   /* "Query" offset		*/
#define LLVERS(rrp)   (rrp->rr_Arg2)   /* library version		*/

/*
 * The RexxClipNode structure is used to maintain the Clip List.  The value
 * string is stored as an argstring in the rr_Arg1 field.
 */
#define CLVALUE(rrp) ((STRPTR) rrp->rr_Arg1)

/*
 * A message port structure, maintained as a resource node.  The ReplyList
 * holds packets that have been received but haven't been replied.
 */
struct RexxMsgPort {
   struct RexxRsrc rmp_Node;	       /* linkage node			*/
   struct MsgPort  rmp_Port;	       /* the message port		*/
   struct List	   rmp_ReplyList;      /* messages awaiting reply	*/
   };

/*
 * DOS Device types
 */
#define DT_DEV	  0L		       /* a device			*/
#define DT_DIR	  1L		       /* an ASSIGNed directory	*/
#define DT_VOL	  2L		       /* a volume			*/

/*
 * Private DOS packet types
 */
#define ACTION_STACK 2002L	       /* stack a line			*/
#define ACTION_QUEUE 2003L	       /* queue a line			*/

#endif


Includes/rexx/rxslib.h

#ifndef REXX_RXSLIB_H
#define REXX_RXSLIB_H
/*
**	$Filename: rexx/rxslib.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.6 $
**	$Date: 91/11/08 $
**
**	The header file for the REXX Systems Library
**
**	(C) Copyright 1987,1988,1989,1990 William S. Hawes
**	(C) Copyright 1990-1999 Amiga, Inc.
**		All Rights Reserved
*/

#ifndef REXX_STORAGE_H
#include "rexx/storage.h"
#endif

#define RXSNAME  "rexxsyslib.library"
#define RXSDIR	 "REXX"
#define RXSTNAME "ARexx"

/* The REXX systems library structure.	This should be considered as	*/
/* semi-private and read-only, except for documented exceptions.	*/

struct RxsLib {
   struct Library rl_Node;	       /* EXEC library node		*/
   UBYTE    rl_Flags;		       /* global flags			*/
   UBYTE    rl_Shadow;		       /* shadow flags			*/
   APTR     rl_SysBase;	       /* EXEC library base		*/
   APTR     rl_DOSBase;	       /* DOS library base		*/
   APTR     rl_IeeeDPBase;	       /* IEEE DP math library base	*/
   LONG     rl_SegList;	       /* library seglist		*/
   LONG     rl_NIL;		       /* global NIL: filehandle	*/
   LONG     rl_Chunk;		       /* allocation quantum		*/
   LONG     rl_MaxNest;	       /* maximum expression nesting	*/
   struct NexxStr *rl_NULL;	       /* static string: NULL		*/
   struct NexxStr *rl_FALSE;	       /* static string: FALSE		*/
   struct NexxStr *rl_TRUE;	       /* static string: TRUE		*/
   struct NexxStr *rl_REXX;	       /* static string: REXX		*/
   struct NexxStr *rl_COMMAND;	       /* static string: COMMAND	*/
   struct NexxStr *rl_STDIN;	       /* static string: STDIN		*/
   struct NexxStr *rl_STDOUT;	       /* static string: STDOUT	*/
   struct NexxStr *rl_STDERR;	       /* static string: STDERR	*/
   STRPTR    rl_Version;	       /* version string		*/

   STRPTR    rl_TaskName;	       /* name string for tasks	*/
   LONG      rl_TaskPri;	       /* starting priority		*/
   LONG      rl_TaskSeg;	       /* startup seglist		*/
   LONG      rl_StackSize;	       /* stack size			*/
   STRPTR    rl_RexxDir;	       /* REXX directory		*/
   STRPTR    rl_CTABLE;	       /* character attribute table	*/
   STRPTR    rl_Notice;	       /* copyright notice		*/

   struct MsgPort rl_RexxPort;	       /* REXX public port		*/
   UWORD     rl_ReadLock;	       /* lock count			*/
   LONG      rl_TraceFH;	       /* global trace console		*/
   struct List rl_TaskList;	       /* REXX task list		*/
   WORD      rl_NumTask;	       /* task count			*/
   struct List rl_LibList;	       /* Library List header		*/
   WORD      rl_NumLib;	       /* library count		*/
   struct List rl_ClipList;	       /* ClipList header		*/
   WORD      rl_NumClip;	       /* clip node count		*/
   struct List rl_MsgList;	       /* pending messages		*/
   WORD      rl_NumMsg;	       /* pending count		*/
   struct List rl_PgmList;	       /* cached programs		*/
   WORD      rl_NumPgm;	       /* program count		*/

   UWORD     rl_TraceCnt;	       /* usage count for trace console */
   WORD      rl_avail;
   };

/* Global flag bit definitions for RexxMaster				*/
#define RLFB_TRACE RTFB_TRACE	       /* interactive tracing?		*/
#define RLFB_HALT  RTFB_HALT	       /* halt execution?		*/
#define RLFB_SUSP  RTFB_SUSP	       /* suspend execution?		*/
#define RLFB_STOP  6		       /* deny further invocations	*/
#define RLFB_CLOSE 7		       /* close the master		*/

#define RLFMASK    (1<<RLFB_TRACE) | (1<<RLFB_HALT) | (1<<RLFB_SUSP)

/* Initialization constants						*/
#define RXSCHUNK   1024	       /* allocation quantum		*/
#define RXSNEST    32		       /* expression nesting limit	*/
#define RXSTPRI    0		       /* task priority		*/
#define RXSSTACK   4096	       /* stack size			*/

/* Character attribute flag bits used in REXX.				*/
#define CTB_SPACE   0		       /* white space characters	*/
#define CTB_DIGIT   1		       /* decimal digits 0-9		*/
#define CTB_ALPHA   2		       /* alphabetic characters	*/
#define CTB_REXXSYM 3		       /* REXX symbol characters	*/
#define CTB_REXXOPR 4		       /* REXX operator characters	*/
#define CTB_REXXSPC 5		       /* REXX special symbols		*/
#define CTB_UPPER   6		       /* UPPERCASE alphabetic		*/
#define CTB_LOWER   7		       /* lowercase alphabetic		*/

/* Attribute flags							*/
#define CTF_SPACE   (1 << CTB_SPACE)
#define CTF_DIGIT   (1 << CTB_DIGIT)
#define CTF_ALPHA   (1 << CTB_ALPHA)
#define CTF_REXXSYM (1 << CTB_REXXSYM)
#define CTF_REXXOPR (1 << CTB_REXXOPR)
#define CTF_REXXSPC (1 << CTB_REXXSPC)
#define CTF_UPPER   (1 << CTB_UPPER)
#define CTF_LOWER   (1 << CTB_LOWER)

#endif


Includes/rexx/storage.h

#ifndef REXX_STORAGE_H
#define REXX_STORAGE_H
/*
**	$Filename: rexx/storage.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.4 $
**	$Date: 91/11/08 $
**
**	Header file to define ARexx data structures.
**
**	(C) Copyright 1986,1987,1988,1989,1990 William S. Hawes
**	(C) Copyright 1990-1999 Amiga, Inc.
**		All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include "exec/types.h"
#endif

#ifndef EXEC_NODES_H
#include "exec/nodes.h"
#endif

#ifndef EXEC_LISTS_H
#include "exec/lists.h"
#endif

#ifndef EXEC_PORTS_H
#include "exec/ports.h"
#endif

#ifndef EXEC_LIBRARIES_H
#include "exec/libraries.h"
#endif

/* The NexxStr structure is used to maintain the internal strings in REXX.
 * It includes the buffer area for the string and associated attributes.
 * This is actually a variable-length structure; it is allocated for a
 * specific length string, and the length is never modified thereafter
 * (since it's used for recycling).
 */

struct NexxStr {
   LONG     ns_Ivalue;		       /* integer value		*/
   UWORD    ns_Length;		       /* length in bytes (excl null)	*/
   UBYTE    ns_Flags;		       /* attribute flags		*/
   UBYTE    ns_Hash;		       /* hash code			*/
   BYTE     ns_Buff[8];	       /* buffer area for strings	*/
   };				       /* size: 16 bytes (minimum)	*/

#define NXADDLEN 9		       /* offset plus null byte	*/
#define IVALUE(nsPtr) (nsPtr->ns_Ivalue)

/* String attribute flag bit definitions				*/
#define NSB_KEEP     0		       /* permanent string?		*/
#define NSB_STRING   1		       /* string form valid?		*/
#define NSB_NOTNUM   2		       /* non-numeric?			*/
#define NSB_NUMBER   3		       /* a valid number?		*/
#define NSB_BINARY   4		       /* integer value saved?		*/
#define NSB_FLOAT    5		       /* floating point format?	*/
#define NSB_EXT      6		       /* an external string?		*/
#define NSB_SOURCE   7		       /* part of the program source?	*/

/* The flag form of the string attributes				*/
#define NSF_KEEP     (1 << NSB_KEEP  )
#define NSF_STRING   (1 << NSB_STRING)
#define NSF_NOTNUM   (1 << NSB_NOTNUM)
#define NSF_NUMBER   (1 << NSB_NUMBER)
#define NSF_BINARY   (1 << NSB_BINARY)
#define NSF_FLOAT    (1 << NSB_FLOAT )
#define NSF_EXT      (1 << NSB_EXT   )
#define NSF_SOURCE   (1 << NSB_SOURCE)

/* Combinations of flags						*/
#define NSF_INTNUM   (NSF_NUMBER | NSF_BINARY | NSF_STRING)
#define NSF_DPNUM    (NSF_NUMBER | NSF_FLOAT)
#define NSF_ALPHA    (NSF_NOTNUM | NSF_STRING)
#define NSF_OWNED    (NSF_SOURCE | NSF_EXT    | NSF_KEEP)
#define KEEPSTR      (NSF_STRING | NSF_SOURCE | NSF_NOTNUM)
#define KEEPNUM      (NSF_STRING | NSF_SOURCE | NSF_NUMBER | NSF_BINARY)

/* The RexxArg structure is identical to the NexxStr structure, but
 * is allocated from system memory rather than from internal storage.
 * This structure is used for passing arguments to external programs.
 * It is usually passed as an "argstring", a pointer to the string buffer.
 */

struct RexxArg {
   LONG     ra_Size;		       /* total allocated length	*/
   UWORD    ra_Length;		       /* length of string		*/
   UBYTE    ra_Flags;		       /* attribute flags		*/
   UBYTE    ra_Hash;		       /* hash code			*/
   BYTE     ra_Buff[8];	       /* buffer area			*/
   };				       /* size: 16 bytes (minimum)	*/

/* The RexxMsg structure is used for all communications with REXX
 * programs.  It is an EXEC message with a parameter block appended.
 */

struct RexxMsg {
   struct Message rm_Node;	       /* EXEC message structure	*/
   APTR     rm_TaskBlock;	       /* global structure (private)	*/
   APTR     rm_LibBase;	       /* library base (private)	*/
   LONG     rm_Action;		       /* command (action) code	*/
   LONG     rm_Result1;	       /* primary result (return code)	*/
   LONG     rm_Result2;	       /* secondary result		*/
   STRPTR   rm_Args[16];	       /* argument block (ARG0-ARG15)	*/

   struct MsgPort *rm_PassPort;        /* forwarding port		*/
   STRPTR   rm_CommAddr;	       /* host address (port name)	*/
   STRPTR   rm_FileExt;	       /* file extension		*/
   LONG     rm_Stdin;		       /* input stream (filehandle)	*/
   LONG     rm_Stdout;		       /* output stream (filehandle)	*/
   LONG     rm_avail;		       /* future expansion		*/
   };				       /* size: 128 bytes		*/

/* Field definitions							*/
#define ARG0(rmp) (rmp->rm_Args[0])    /* start of argblock		*/
#define ARG1(rmp) (rmp->rm_Args[1])    /* first argument		*/
#define ARG2(rmp) (rmp->rm_Args[2])    /* second argument		*/

#define MAXRMARG  15		       /* maximum arguments		*/

/* Command (action) codes for message packets				*/
#define RXCOMM	  0x01000000	       /* a command-level invocation	*/
#define RXFUNC	  0x02000000	       /* a function call		*/
#define RXCLOSE   0x03000000	       /* close the REXX server	*/
#define RXQUERY   0x04000000	       /* query for information	*/
#define RXADDFH   0x07000000	       /* add a function host		*/
#define RXADDLIB  0x08000000	       /* add a function library	*/
#define RXREMLIB  0x09000000	       /* remove a function library	*/
#define RXADDCON  0x0A000000	       /* add/update a ClipList string	*/
#define RXREMCON  0x0B000000	       /* remove a ClipList string	*/
#define RXTCOPN   0x0C000000	       /* open the trace console	*/
#define RXTCCLS   0x0D000000	       /* close the trace console	*/

/* Command modifier flag bits						*/
#define RXFB_NOIO    16	       /* suppress I/O inheritance?	*/
#define RXFB_RESULT  17	       /* result string expected?	*/
#define RXFB_STRING  18	       /* program is a "string file"?	*/
#define RXFB_TOKEN   19	       /* tokenize the command line?	*/
#define RXFB_NONRET  20	       /* a "no-return" message?	*/

/* The flag form of the command modifiers				*/
#define RXFF_NOIO    (1L << RXFB_NOIO  )
#define RXFF_RESULT  (1L << RXFB_RESULT)
#define RXFF_STRING  (1L << RXFB_STRING)
#define RXFF_TOKEN   (1L << RXFB_TOKEN )
#define RXFF_NONRET  (1L << RXFB_NONRET)

#define RXCODEMASK   0xFF000000
#define RXARGMASK    0x0000000F

/* The RexxRsrc structure is used to manage global resources.  Each node
 * has a name string created as a RexxArg structure, and the total size
 * of the node is saved in the "rr_Size" field.  The REXX systems library
 * provides functions to allocate and release resource nodes.  If special
 * deletion operations are required, an offset and base can be provided in
 * "rr_Func" and "rr_Base", respectively.  This "autodelete" function will
 * be called with the base in register A6 and the node in A0.
 */

struct RexxRsrc {
   struct Node rr_Node;
   WORD     rr_Func;		       /* "auto-delete" offset		*/
   APTR     rr_Base;		       /* "auto-delete" base		*/
   LONG     rr_Size;		       /* total size of node		*/
   LONG     rr_Arg1;		       /* available ...		*/
   LONG     rr_Arg2;		       /* available ...		*/
   };				       /* size: 32 bytes		*/

/* Resource node types							*/
#define RRT_ANY      0		       /* any node type ...		*/
#define RRT_LIB      1		       /* a function library		*/
#define RRT_PORT     2		       /* a public port		*/
#define RRT_FILE     3		       /* a file IoBuff		*/
#define RRT_HOST     4		       /* a function host		*/
#define RRT_CLIP     5		       /* a Clip List node		*/

/* The RexxTask structure holds the fields used by REXX to communicate with
 * external processes, including the client task.  It includes the global
 * data structure (and the base environment).  The structure is passed to
 * the newly-created task in its "wake-up" message.
 */

#define GLOBALSZ  200		       /* total size of GlobalData	*/

struct RexxTask {
   BYTE     rt_Global[GLOBALSZ];       /* global data structure	*/
   struct MsgPort rt_MsgPort;	       /* global message port		*/
   UBYTE    rt_Flags;		       /* task flag bits		*/
   BYTE     rt_SigBit;		       /* signal bit			*/

   APTR     rt_ClientID;	       /* the client's task ID		*/
   APTR     rt_MsgPkt;		       /* the packet being processed	*/
   APTR     rt_TaskID;		       /* our task ID			*/
   APTR     rt_RexxPort;	       /* the REXX public port		*/

   APTR     rt_ErrTrap;	       /* Error trap address		*/
   APTR     rt_StackPtr;	       /* stack pointer for traps	*/

   struct List rt_Header1;	       /* Environment list		*/
   struct List rt_Header2;	       /* Memory freelist		*/
   struct List rt_Header3;	       /* Memory allocation list	*/
   struct List rt_Header4;	       /* Files list			*/
   struct List rt_Header5;	       /* Message Ports List		*/
   };

/* Definitions for RexxTask flag bits					*/
#define RTFB_TRACE   0		       /* external trace flag		*/
#define RTFB_HALT    1		       /* external halt flag		*/
#define RTFB_SUSP    2		       /* suspend task?		*/
#define RTFB_TCUSE   3		       /* trace console in use?	*/
#define RTFB_WAIT    6		       /* waiting for reply?		*/
#define RTFB_CLOSE   7		       /* task completed?		*/

/* Definitions for memory allocation constants				*/
#define MEMQUANT  16L		       /* quantum of memory space	*/
#define MEMMASK   0xFFFFFFF0	       /* mask for rounding the size	*/

#define MEMQUICK  (1L << 0 )	       /* EXEC flags: MEMF_PUBLIC	*/
#define MEMCLEAR  (1L << 16)	       /* EXEC flags: MEMF_CLEAR	*/

/* The SrcNode is a temporary structure used to hold values destined for
 * a segment array.  It is also used to maintain the memory freelist.
 */

struct SrcNode {
   struct SrcNode *sn_Succ;	       /* next node			*/
   struct SrcNode *sn_Pred;	       /* previous node		*/
   APTR     sn_Ptr;		       /* pointer value		*/
   LONG     sn_Size;		       /* size of object		*/
   };				       /* size: 16 bytes		*/

#endif


Includes/rexx/errors.i

     IFND	  REXX_ERRORS_I
REXX_ERRORS_I SET      1
**
**	$Filename: rexx/errors.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.6 $
**	$Date: 91/11/08 $
**
**	Definitions for ARexx error codes
**
**	(C) Copyright 1986,1987,1988,1989,1990 William S. Hawes.
**	(C) Copyright 1990-1999 Amiga, Inc.
**		All Rights Reserved
**

ERRC_MSG    EQU   0		    ; error code offset
ERR10_001   EQU   (ERRC_MSG+1)	    ; program not found
ERR10_002   EQU   (ERRC_MSG+2)	    ; execution halted
ERR10_003   EQU   (ERRC_MSG+3)	    ; no memory available
                    ; unassigned
ERR10_005   EQU   (ERRC_MSG+5)	    ; unmatched quote
ERR10_006   EQU   (ERRC_MSG+6)	    ; unterminated comment
                    ; unassigned
ERR10_008   EQU   (ERRC_MSG+8)	    ; unrecognized token
ERR10_009   EQU   (ERRC_MSG+9)	    ; symbol or string too long

ERR10_010   EQU   (ERRC_MSG+10)     ; invalid message packet
ERR10_011   EQU   (ERRC_MSG+11)     ; command string error
ERR10_012   EQU   (ERRC_MSG+12)     ; error return from function
ERR10_013   EQU   (ERRC_MSG+13)     ; host environment not found
ERR10_014   EQU   (ERRC_MSG+14)     ; required library not available
ERR10_015   EQU   (ERRC_MSG+15)     ; function not found
ERR10_016   EQU   (ERRC_MSG+16)     ; function did not return value
ERR10_017   EQU   (ERRC_MSG+17)     ; wrong number of arguments
ERR10_018   EQU   (ERRC_MSG+18)     ; invalid argument to function
ERR10_019   EQU   (ERRC_MSG+19)     ; invalid PROCEDURE instruction

ERR10_020   EQU   (ERRC_MSG+20)     ; unexpected THEN/ELSE
ERR10_021   EQU   (ERRC_MSG+21)     ; unexpected WHEN/OTHERWISE
ERR10_022   EQU   (ERRC_MSG+22)     ; unexpected BREAK, LEAVE or ITERATE
ERR10_023   EQU   (ERRC_MSG+23)     ; invalid statement in SELECT
ERR10_024   EQU   (ERRC_MSG+24)     ; missing or multiple THEN clauses
ERR10_025   EQU   (ERRC_MSG+25)     ; missing OTHERWISE
ERR10_026   EQU   (ERRC_MSG+26)     ; missing or unexpected END
ERR10_027   EQU   (ERRC_MSG+27)     ; symbol mismatch on END/LEAVE/ITERATE
ERR10_028   EQU   (ERRC_MSG+28)     ; invalid 'DO' syntax
ERR10_029   EQU   (ERRC_MSG+29)     ; incomplete DO/IF/SELECT

ERR10_030   EQU   (ERRC_MSG+30)     ; label not found
ERR10_031   EQU   (ERRC_MSG+31)     ; symbol expected
ERR10_032   EQU   (ERRC_MSG+32)     ; string or symbol expected
ERR10_033   EQU   (ERRC_MSG+33)     ; invalid sub-keyword
ERR10_034   EQU   (ERRC_MSG+34)     ; required keyword missing
ERR10_035   EQU   (ERRC_MSG+35)     ; extraneous characters in clause
ERR10_036   EQU   (ERRC_MSG+36)     ; sub-keyword conflict
ERR10_037   EQU   (ERRC_MSG+37)     ; invalid template
                    ; unassigned
ERR10_039   EQU   (ERRC_MSG+39)     ; uninitialized variable

ERR10_040   EQU   (ERRC_MSG+40)     ; invalid variable name
ERR10_041   EQU   (ERRC_MSG+41)     ; invalid expression
ERR10_042   EQU   (ERRC_MSG+42)     ; unbalanced parentheses
ERR10_043   EQU   (ERRC_MSG+43)     ; nesting level exceeded
ERR10_044   EQU   (ERRC_MSG+44)     ; invalid expression result
ERR10_045   EQU   (ERRC_MSG+45)     ; expression required
ERR10_046   EQU   (ERRC_MSG+46)     ; boolean value not 0 or 1
ERR10_047   EQU   (ERRC_MSG+47)     ; arithmetic conversion error
ERR10_048   EQU   (ERRC_MSG+48)     ; invalid operand

* Return Codes for general use ...
RC_FAIL     EQU   -1		    ; something's wrong
RC_OK       EQU   0                 ; success
RC_WARN     EQU   5                 ; A warning only
RC_ERROR    EQU   10                ; Something wrong
RC_FATAL    EQU   20                ; Complete or severe failure

         ENDC


Includes/rexx/rexxio.i

     IFND	  REXX_REXXIO_I
REXX_REXXIO_I SET      1
**
**	$Filename: rexx/rexxio.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.8 $
**	$Date: 91/11/08 $
**
**	Include file for Input/Output related structures
**
**	(C) Copyright 1986,1987,1988,1989,1990 William S. Hawes.
**	(C) Copyright 1990-1999 Amiga, Inc.
**		All Rights Reserved
**

     IFND	  REXX_STORAGE_I
     INCLUDE  "rexx/storage.i"
     ENDC

RXBUFFSZ EQU	  204		       ; buffer length

* The IoBuff is a resource node used to maintain the File List.  Nodes are
* allocated and linked into the list whenever a file is opened.

     STRUCTURE IoBuff,RRSIZEOF     ; structure for files/strings
     APTR	  iobRpt	       ; read/write pointer
     LONG	  iobRct	       ; character count
     LONG	  iobDFH	       ; DOS filehandle
     APTR	  iobLock	       ; DOS lock
     LONG	  iobBct	       ; buffer length
     STRUCT   iobArea,RXBUFFSZ     ; buffer area
     LABEL	  iobSIZEOF	       ; size: 256 bytes

IOBNAME  EQU	  LN_NAME	       ; logical name
IOBMODE  EQU	  rr_Arg1	       ; access mode
IOBEOF	 EQU	  rr_Arg1+1	       ; EOF flag
IOBPOS	 EQU	  rr_Arg2	       ; current position

* Access mode definitions
RXIO_EXIST  EQU      -1	       ; an existing filehandle
RXIO_STRF   EQU      0		       ; a "string file"
RXIO_READ   EQU      1		       ; read-only access
RXIO_WRITE  EQU      2		       ; write mode
RXIO_APPEND EQU      3		       ; append mode (existing file)

* Offset anchors for SeekF()
RXIO_BEGIN  EQU      -1	       ; relative to start
RXIO_CURR   EQU      0		       ; relative to current position
RXIO_END    EQU      1		       ; relative to end

* The Library List contains just plain resource nodes.
LLOFFSET EQU	  rr_Arg1	       ; "Query" offset
LLVERS	 EQU	  rr_Arg2	       ; library version

* The RexxClipNode structure is used to maintain the Clip List.  The
* value string is stored as an argstring in the rr_Arg1 field.
CLVALUE  EQU	  rr_Arg1	       ; value string

* A message port structure, maintained as a resource node.
* The ReplyList holds packets that have been received but haven't been
* replied.

         STRUCTURE RexxMsgPort,RRSIZEOF
         STRUCT   rmp_Port,MP_SIZE           ; the message port
         STRUCT   rmp_ReplyList,LH_SIZE      ; messages awaiting reply
         LABEL    rmp_SIZEOF

* Device types
DT_DEV   EQU      0                    ; a device
DT_DIR   EQU      1                    ; an ASSIGNed directory
DT_VOL   EQU      2                    ; a volume

* Private packet types
ACTION_STACK   EQU   2002              ; stack a line
ACTION_QUEUE   EQU   2003              ; queue a line

         ENDC


Includes/rexx/rxslib.i

     IFND	  REXX_RXSLIB_I
REXX_RXSLIB_I  SET   1
**
**	$Filename: rexx/rxslib.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.15 $
**	$Date: 91/11/08 $
**
**	Include file for the REXX Systems Library
**
**	(C) Copyright 1986,1987,1988,1989,1990 William S. Hawes.
**	(C) Copyright 1990-1999 Amiga, Inc.
**		All Rights Reserved
**

     IFND	  REXX_STORAGE_I
     INCLUDE  "rexx/storage.i"
     ENDC

     ; Macro definitions

RXSLIBNAME MACRO
     dc.b	  'rexxsyslib.library',0
     ENDM

RXSDIR	 MACRO			       ; public port name
     dc.b	  'REXX',0
     ENDM

RXSTNAME MACRO			       ; name for tasks
     dc.b	  'ARexx',0
     ENDM

     ; Structure definition for the REXX systems library

     STRUCTURE RxsLib,LIB_SIZE     ; EXEC library node
     UBYTE	  rl_Flags	       ; global flags
     UBYTE	  rl_Shadow	       ; shadow flags
     APTR	  rl_SysBase	       ; EXEC library base
     APTR	  rl_DOSBase	       ; DOS library base
     APTR	  rl_IeeeDPBase        ; IEEE DP math library base
     LONG	  rl_SegList	       ; library seglist
     LONG	  rl_NIL	       ; NIL: stream
     LONG	  rl_Chunk	       ; allocation quantum
     LONG	  rl_MaxNest	       ; maximum expression nesting

     APTR	  rl_NULL	       ; static string: NULL
     APTR	  rl_FALSE	       ; static string: FALSE
     APTR	  rl_TRUE	       ; static string: TRUE
     APTR	  rl_REXX	       ; static string: REXX
     APTR	  rl_COMMAND	       ; static string: COMMAND
     APTR	  rl_STDIN	       ; static string: STDIN
     APTR	  rl_STDOUT	       ; static string: STDOUT
     APTR	  rl_STDERR	       ; static string: STDERR
     APTR	  rl_Version	       ; version string

     APTR	  rl_TaskName	       ; name string for tasks
     LONG	  rl_TaskPri	       ; starting priority
     LONG	  rl_TaskSeg	       ; startup seglist
     LONG	  rl_StackSize	       ; stack size
     APTR	  rl_RexxDir	       ; REXX directory
     APTR	  rl_CTABLE	       ; character attribute table
     APTR	  rl_Notice	       ; copyright notice

     STRUCT   rl_RexxPort,MP_SIZE  ; public port
     UWORD	  rl_ReadLock	       ; lock count
     APTR	  rl_TraceFH	       ; global trace console

     STRUCT   rl_TaskList,LH_SIZE  ; REXX task list
     WORD	  rl_NumTask
     STRUCT   rl_LibList,LH_SIZE   ; Library List header
     WORD	  rl_NumLib
     STRUCT   rl_ClipList,LH_SIZE  ; ClipList header
     WORD	  rl_NumClip
     STRUCT   rl_MsgList,LH_SIZE   ; pending messages
     WORD	  rl_NumMsg
     STRUCT   rl_PgmList,LH_SIZE   ; cached programs
     WORD	  rl_NumPgm	       ; cache count

     UWORD	  rl_TraceCnt	       ; trace console usage count
     WORD	  rl_avail
     LABEL	  rl_SIZEOF

* Global flag bit definitions for RexxMaster
RLFB_TRACE EQU	  RTFB_TRACE	       ; interactive tracing?
RLFB_HALT  EQU	  RTFB_HALT	       ; halt execution?
RLFB_SUSP  EQU	  RTFB_SUSP	       ; suspend execution?
RLFB_STOP  EQU	  6		       ; deny further invocations
RLFB_CLOSE EQU	  7		       ; close the master

* Mask for control flags
RLFMASK  EQU	  1<<RLFB_TRACE!1<<RLFB_HALT!1<<RLFB_SUSP

     ; Initialization constants

RXSCHUNK EQU	  1024		       ; allocation quantum
RXSNEST  EQU	  32		       ; expression nesting limit
RXSTPRI  EQU	  0		       ; task priority
RXSSTACK EQU	  4096		       ; stack size

     ; The library entry point offsets

     LIBINIT
     LIBDEF   _LVORexx	       ; Main entry point
     LIBDEF   _LVOrxParse	       ; (private)
     LIBDEF   _LVOrxInstruct       ; (private)
     LIBDEF   _LVOrxSuspend        ; (private)
     LIBDEF   _LVOEvalOp	       ; (private)

     LIBDEF   _LVOAssignValue      ; (private)
     LIBDEF   _LVOEnterSymbol      ; (private)
     LIBDEF   _LVOFetchValue       ; (private)
     LIBDEF   _LVOLookUpValue      ; (private)
     LIBDEF   _LVOSetValue	       ; (private)
     LIBDEF   _LVOSymExpand        ; (private)

     LIBDEF   _LVOErrorMsg
     LIBDEF   _LVOIsSymbol
     LIBDEF   _LVOCurrentEnv
     LIBDEF   _LVOGetSpace
     LIBDEF   _LVOFreeSpace

     LIBDEF   _LVOCreateArgstring
     LIBDEF   _LVODeleteArgstring
     LIBDEF   _LVOLengthArgstring
     LIBDEF   _LVOCreateRexxMsg
     LIBDEF   _LVODeleteRexxMsg
     LIBDEF   _LVOClearRexxMsg
     LIBDEF   _LVOFillRexxMsg
     LIBDEF   _LVOIsRexxMsg

     LIBDEF   _LVOAddRsrcNode
     LIBDEF   _LVOFindRsrcNode
     LIBDEF   _LVORemRsrcList
     LIBDEF   _LVORemRsrcNode
     LIBDEF   _LVOOpenPublicPort
     LIBDEF   _LVOClosePublicPort
     LIBDEF   _LVOListNames

     LIBDEF   _LVOClearMem
     LIBDEF   _LVOInitList
     LIBDEF   _LVOInitPort
     LIBDEF   _LVOFreePort

     LIBDEF   _LVOCmpString
     LIBDEF   _LVOStcToken
     LIBDEF   _LVOStrcmpN
     LIBDEF   _LVOStrcmpU
     LIBDEF   _LVOStrcpyA	       ; obsolete
     LIBDEF   _LVOStrcpyN
     LIBDEF   _LVOStrcpyU
     LIBDEF   _LVOStrflipN
     LIBDEF   _LVOStrlen
     LIBDEF   _LVOToUpper

     LIBDEF   _LVOCVa2i
     LIBDEF   _LVOCVi2a
     LIBDEF   _LVOCVi2arg
     LIBDEF   _LVOCVi2az
     LIBDEF   _LVOCVc2x
     LIBDEF   _LVOCVx2c

     LIBDEF   _LVOOpenF
     LIBDEF   _LVOCloseF
     LIBDEF   _LVOReadStr
     LIBDEF   _LVOReadF
     LIBDEF   _LVOWriteF
     LIBDEF   _LVOSeekF
     LIBDEF   _LVOQueueF
     LIBDEF   _LVOStackF
     LIBDEF   _LVOExistF

     LIBDEF   _LVODOSCommand
     LIBDEF   _LVODOSRead
     LIBDEF   _LVODOSWrite
     LIBDEF   _LVOCreateDOSPkt     ; obsolete
     LIBDEF   _LVODeleteDOSPkt     ; obsolete
     LIBDEF   _LVOSendDOSPkt       ; (private)
     LIBDEF   _LVOWaitDOSPkt       ; (private)
     LIBDEF   _LVOFindDevice       ; (private)

     LIBDEF   _LVOAddClipNode
     LIBDEF   _LVORemClipNode
     LIBDEF   _LVOLockRexxBase
     LIBDEF   _LVOUnlockRexxBase
     LIBDEF   _LVOCreateCLI        ; (private)
     LIBDEF   _LVODeleteCLI        ; (private)
     LIBDEF   _LVOCVs2i

* Character attribute flag bits used in REXX.
CTB_SPACE   EQU   0		       ; white space characters
CTB_DIGIT   EQU   1		       ; decimal digits 0-9
CTB_ALPHA   EQU   2		       ; alphabetic characters
CTB_REXXSYM EQU   3		       ; REXX symbol characters
CTB_REXXOPR EQU   4		       ; REXX operator characters
CTB_REXXSPC EQU   5		       ; REXX special symbols
CTB_UPPER   EQU   6		       ; UPPERCASE alphabetic
CTB_LOWER   EQU   7		       ; lowercase alphabetic

* The flag form of the character attributes
CTF_SPACE   EQU   1<<CTB_SPACE
CTF_DIGIT   EQU   1<<CTB_DIGIT
CTF_ALPHA   EQU   1<<CTB_ALPHA
CTF_REXXSYM EQU   1<<CTB_REXXSYM
CTF_REXXOPR EQU   1<<CTB_REXXOPR
CTF_REXXSPC EQU   1<<CTB_REXXSPC
CTF_UPPER   EQU   1<<CTB_UPPER
CTF_LOWER   EQU   1<<CTB_LOWER

     ENDC


Includes/rexx/storage.i

     IFND REXX_STORAGE_I
REXX_STORAGE_I SET    1
**
**	$Filename: rexx/storage.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 1.8 $
**	$Date: 91/11/08 $
**
**	Include file for REXX data structures and memory/storage management.
**
**	(C) Copyright 1986,1987,1988,1989,1990 William S. Hawes.
**	(C) Copyright 1990-1999 Amiga, Inc.
**		All Rights Reserved
**

     IFND EXEC_TYPES_I
     INCLUDE "exec/types.i"
     ENDC

     IFND EXEC_NODES_I
     INCLUDE "exec/nodes.i"
     ENDC

     IFND EXEC_LISTS_I
     INCLUDE "exec/lists.i"
     ENDC

     IFND EXEC_PORTS_I
     INCLUDE "exec/ports.i"
     ENDC

     IFND EXEC_LIBRARIES_I
     INCLUDE "exec/libraries.i"
     ENDC

* The NexxStr structure is used to maintain the internal strings in REXX.
* It includes the buffer area for the string and associated attributes.
* This is actually a variable-length structure; it is allocated for a
* specific length string, and the length is never modified thereafter
* (since it's used for recycling).

         STRUCTURE NexxStr,0
         LONG     ns_Ivalue            ; integer value
         UWORD    ns_Length            ; length in bytes (excl null byte)
         UBYTE    ns_Flags             ; attribute flags
         UBYTE    ns_Hash              ; sum-of-characters hash code
         STRUCT   ns_Buff,8            ; buffer area for strings
         LABEL    NSMINSIZE            ; 16 bytes (minimum)

NXADDLEN EQU      ns_Buff+1            ; structure offset plus null byte
IVALUE   EQU      ns_Ivalue            ; integer value

* String attribute flag bit definitions
NSB_KEEP    EQU   0                    ; permanent string? (in Symbol Table)
NSB_STRING  EQU   1                    ; string form valid?
NSB_NOTNUM  EQU   2                    ; non-numeric?
NSB_NUMBER  EQU   3                    ; a valid number?
NSB_BINARY  EQU   4                    ; integer value saved?
NSB_FLOAT   EQU   5                    ; floating point format?
NSB_EXT     EQU   6                    ; an external string?
NSB_SOURCE  EQU   7                    ; part of the program source?

* The flag form of the string attributes
NSF_KEEP    EQU   1<<NSB_KEEP
NSF_STRING  EQU   1<<NSB_STRING
NSF_NOTNUM  EQU   1<<NSB_NOTNUM
NSF_NUMBER  EQU   1<<NSB_NUMBER
NSF_BINARY  EQU   1<<NSB_BINARY
NSF_FLOAT   EQU   1<<NSB_FLOAT
NSF_EXT     EQU   1<<NSB_EXT
NSF_SOURCE  EQU   1<<NSB_SOURCE

* Combinations of flags
NSF_INTNUM  EQU   (NSF_NUMBER!NSF_BINARY!NSF_STRING)
NSF_DPNUM   EQU   (NSF_NUMBER!NSF_FLOAT)
NSF_ALPHA   EQU   (NSF_NOTNUM!NSF_STRING)
NSF_OWNED   EQU   (NSF_SOURCE!NSF_EXT!NSF_KEEP)
KEEPSTR     EQU   (NSF_STRING!NSF_SOURCE!NSF_NOTNUM)
KEEPNUM     EQU   (NSF_STRING!NSF_SOURCE!NSF_NUMBER!NSF_BINARY)

* The RexxArg structure is identical to the NexxStr structure, but
* is allocated from system memory rather than from internal storage.
* This structure is used for passing arguments to external programs.
* It is usually passed as an "argstring", a pointer to the string buffer.

         STRUCTURE RexxArg,0
         LONG     ra_Size              ; total allocated length
         UWORD    ra_Length            ; length of string
         UBYTE    ra_Flags             ; attribute flags
         UBYTE    ra_Hash              ; hash code
         STRUCT   ra_Buff,8            ; buffer area
         LABEL    RexxArg_SIZEOF       ; size: 16 bytes
; Changed to RexxArg_SIZEOF from ra_SIZEOF

* The RexxMsg structure is used for all communications with Rexx programs.
* It is an EXEC message with a parameter block appended.

         STRUCTURE RexxMsg,MN_SIZE
         APTR     rm_TaskBlock         ; pointer to RexxTask structure
         APTR     rm_LibBase           ; library pointer
         LONG     rm_Action            ; command (action) code
         LONG     rm_Result1           ; return code
         LONG     rm_Result2           ; secondary result
         STRUCT   rm_Args,16*4         ; argument block (ARG0-ARG15)
         APTR     rm_PassPort          ; forwarding port
         APTR     rm_CommAddr          ; host address (port name)
         APTR     rm_FileExt           ; file extension
         LONG     rm_Stdin             ; input stream
         LONG     rm_Stdout            ; output stream
         LONG     rm_avail             ; future expansion
         LABEL    RMSIZEOF             ; size: 128 bytes
; Ranamed from rm_SIZEOF

* Field definitions
ACTION   EQU      rm_Action            ; action code
RESULT1  EQU      rm_Result1           ; primary return/error level
RESULT2  EQU      rm_Result2           ; secondary return/result string
ARG0     EQU      rm_Args              ; start of argblock
ARG1     EQU      rm_Args+4            ; first argument
ARG2     EQU      rm_Args+8            ; second argument

MAXRMARG EQU      15                   ; maximum arguments

* Command (action) codes for message packets
RXCOMM   EQU      $01000000            ; a command-level invocation
RXFUNC   EQU      $02000000            ; a function call
RXCLOSE  EQU      $03000000            ; close the port
RXQUERY  EQU      $04000000            ; query for information
RXADDFH  EQU      $07000000            ; add a function host
RXADDLIB EQU      $08000000            ; add a function library
RXREMLIB EQU      $09000000            ; remove a function library
RXADDCON EQU      $0A000000            ; add/update a ClipList string
RXREMCON EQU      $0B000000            ; remove a ClipList string
RXTCOPN  EQU      $0C000000            ; open the trace console
RXTCCLS  EQU      $0D000000            ; close the trace console

* Command modifier flag bits
RXFB_NOIO   EQU   16                   ; suppress I/O inheritance?
RXFB_RESULT EQU   17                   ; result string expected?
RXFB_STRING EQU   18                   ; program is a "string file"?
RXFB_TOKEN  EQU   19                   ; tokenize the command line?
RXFB_NONRET EQU   20                   ; a "no-return" message?

* Modifier flags
RXFF_RESULT EQU   1<<RXFB_RESULT
RXFF_STRING EQU   1<<RXFB_STRING
RXFF_TOKEN  EQU   1<<RXFB_TOKEN
RXFF_NONRET EQU   1<<RXFB_NONRET

RXCODEMASK  EQU   $FF000000
RXARGMASK   EQU   $0000000F

* The RexxRsrc structure is used to manage global resources.
* The name string for each node is created as a RexxArg structure,
* and the total size of the node is saved in the "rr_Size" field.
* Functions are provided to allocate and release resource nodes.
* If special deletion operations are required, an offset and base can
* be provided in "rr_Func" and "rr_Base", respectively.  This function
* will be called with the base in register A6 and the node in A0.

         STRUCTURE RexxRsrc,LN_SIZE
         WORD     rr_Func              ; "auto-delete" offset
         APTR     rr_Base              ; "auto-delete" base
         LONG     rr_Size              ; total size of node
         LONG     rr_Arg1              ; available ...
         LONG     rr_Arg2              ; available ...
         LABEL    RRSIZEOF             ; size: 32 bytes
; Changed from rr_SIZEOF to RRSIZEOF

* Field definitions
RRTYPE   EQU      LN_TYPE              ; node type
RRNAME   EQU      LN_NAME              ; node name (argstring)
RRSIZE   EQU      rr_Size              ; total size of node

* Resource node types
RRT_ANY  EQU      0                    ; any node type ...
RRT_LIB  EQU      1                    ; a function library
RRT_PORT EQU      2                    ; a public port
RRT_FILE EQU      3                    ; a file IoBuff
RRT_HOST EQU      4                    ; a function host
RRT_CLIP EQU      5                    ; a Clip List node

* The RexxTask structure holds the fields used by REXX to communicate with
* external processes, including the client task.  It includes the global
* data structure (and the base environment).  The structure is passed to
* the newly-created task in its "wake-up" message.

GLOBALSZ EQU      200                  ; space for the Global Data structure

         STRUCTURE RexxTask,GLOBALSZ   ; global data structure
         STRUCT   rt_MsgPort,MP_SIZE   ; message port
         UBYTE    rt_Flags             ; task flag bits
         BYTE     rt_SigBit            ; signal bit

         APTR     rt_ClientID          ; the client's task ID
     APTR	  rt_MsgPkt	       ; the packet being processed
     APTR	  rt_TaskID	       ; our task ID
     APTR	  rt_RexxPort	       ; the REXX public port

     APTR	  rt_ErrTrap	       ; Error trap address
     APTR	  rt_StackPtr	       ; stack pointer for traps

     STRUCT   rt_Header1,LH_SIZE
     STRUCT   rt_Header2,LH_SIZE
     STRUCT   rt_Header3,LH_SIZE
     STRUCT   rt_Header4,LH_SIZE
     STRUCT   rt_Header5,LH_SIZE
     LABEL	  rt_SIZEOF

ENVLIST  EQU	  rt_Header1	       ; environment list (internal)
FREELIST EQU	  rt_Header2	       ; freelist (internal)
MEMLIST  EQU	  rt_Header3	       ; allocation list (external)
FILELIST EQU	  rt_Header4	       ; I/O files list (external)
PORTLIST EQU	  rt_Header5	       ; message ports list (external)
NUMLISTS EQU	  5

* Definitions for RexxTask flag bits
RTFB_TRACE  EQU      0		       ; external trace flag
RTFB_HALT   EQU      1		       ; external halt flag
RTFB_SUSP   EQU      2		       ; suspend task?
RTFB_TCUSE  EQU      3		       ; trace console in use?
RTFB_WAIT   EQU      6		       ; waiting for reply?
RTFB_CLOSE  EQU      7		       ; task completed?

* Definitions for memory allocation constants
MEMQUANT EQU	  16		       ; quantum of memory space
MEMMASK  EQU	  $FFFFFFF0	       ; mask for rounding the size

MEMQUICK EQU	  (1<<0)	       ; EXEC flags: MEMF_PUBLIC
MEMCLEAR EQU	  (1<<16)	       ; EXEC flags: MEMF_CLEAR

* The SrcNode is a temporary structure used to hold values destined for a
* segment array.  It is also used to maintain the memory freelist.

     STRUCTURE SrcNode,0	       ; temporary source data structure
     APTR	  sn_Succ
     APTR	  sn_Pred
     APTR	  sn_Ptr	       ; pointer value
     LONG	  sn_Size	       ; size of object
     LABEL	  sn_SIZEOF	       ; size: 16 bytes

     ENDC


Includes/utility/date.h

#ifndef UTILITY_DATE_H
#define UTILITY_DATE_H 1
/*
**	$Filename: utility/date.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.2 $
**	$Date: 91/03/04 $
**
**	Date conversion routines ClockData definition.
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**		All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include "exec/types.h"
#endif

struct ClockData
    {
    UWORD sec;
    UWORD min;
    UWORD hour;
    UWORD mday;
    UWORD month;
    UWORD year;
    UWORD wday;
    };

#endif


Includes/utility/hooks.h

#ifndef UTILITY_HOOKS_H
#define UTILITY_HOOKS_H TRUE
/*
**	$Filename: utility/hooks.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.1 $
**	$Date: 90/07/12 $
**
**	callback hooks
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**		All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include "exec/types.h"
#endif

#ifndef EXEC_NODES_H
#include "exec/nodes.h"
#endif

/* new standard hook structure */
struct Hook	{
    struct MinNode	h_MinNode;
    ULONG		(*h_Entry)();	/* assembler entry point	*/
    ULONG		(*h_SubEntry)();/* often HLL entry point	*/
    VOID		*h_Data;	/* owner specific		*/
};

/*
 * Hook calling conventions:
 *	A0 - pointer to hook data structure itself
 *	A1 - pointer to parameter structure ("message") typically
 *	     beginning with a longword command code, which makes
 *	     sense in the context in which the hook is being used.
 *	A2 - Hook specific address data ("object," e.g, GadgetInfo)
 *
 * Control will be passed to the routine h_Entry.  For many
 * High-Level Languages (HLL), this will be an assembly language
 * stub which pushes registers on the stack, does other setup,
 * and then calls the function at h_SubEntry.
 *
 * The C standard receiving code is:
 * CDispatcher( hook, object, message )
 *     struct Hook	*hook;
 *     APTR		object;
 *     APTR		message;
 *
 * NOTE that register natural order differs from this convention
 * for C parameter order, which is A0,A2,A1.
 *
 * The assembly language stub for "vanilla" C parameter conventions
 * could be:

 _hookEntry:
    move.l	a1,-(sp)		; push message packet pointer
    move.l	a2,-(sp)		; push object pointer
    move.l	a0,-(sp)		; push hook pointer
    move.l	h_SubEntry(a0),a0	; fetch C entry point ...
    jsr	(a0)			; ... and call it
    lea	12(sp),sp		; fix stack
    rts

 * with this function as your interface stub, you can write
 * a Hook setup function as:

 SetupHook( hook, c_function, userdata )
 struct Hook	*hook;
 ULONG		(*c_function)();
 VOID		*userdata;
 {
    ULONG	(*hookEntry)();

    hook->h_Entry =		hookEntry;
    hook->h_SubEntry =	c_function;
    hook->h_Data =			userdata;
 }

 * with Lattice C pragmas, you can put the C function in the
 * h_Entry field directly if you declare the function:

ULONG __saveds __asm
CDispatcher(	register __a0 struct Hook	*hook,
        register __a2 VOID		*object,
        register __a1 ULONG		*message );
 *
 ****/

#endif


Includes/utility/tagitem.h

#ifndef UTILITY_TAGITEM_H
#define UTILITY_TAGITEM_H TRUE
/*
**	$Filename: utility/tagitem.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.1 $
**	$Date: 90/07/12 $
**
**	extended specification mechanism
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**		All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

/* ======================================================================= */
/* ====	TagItem	========================================================== */
/* ======================================================================= */
/* This data type may propagate through the system for more general use.
 * In the meantime, it is used as a general mechanism of extensible data
 * arrays for parameter specification and property inquiry (coming soon
 * to a display controller near you).
 *
 * In practice, an array (or chain of arrays) of TagItems is used.
 */

typedef ULONG	Tag;

struct TagItem	{
    Tag		ti_Tag;
    ULONG	ti_Data;
};

/* ----	system tag values -----------------------------	*/
#define TAG_DONE   (0L)	/* terminates array of TagItems. ti_Data unused	*/
#define TAG_END	TAG_DONE
#define	TAG_IGNORE (1L)	/* ignore this item, not end of array		*/
#define	TAG_MORE   (2L)	/* ti_Data is pointer to another array of TagItems
             * note that this tag terminates the current array
             */
#define	TAG_SKIP   (3L)	/* skip this and the next ti_Data items		*/

/* ----	user tag identification -----------------------	*/
#define TAG_USER  (1L<<31)    /* differentiates user tags from system tags*/

/* until further notice, tag bits 16-30 are RESERVED and should be zero.
 * Also, the value (TAG_USER | 0) should never be used as a tag value.
 */

/* ---- Tag filter logic specifiers ---- */
#define TAGFILTER_AND	0	/* exclude everything but filter hits	*/
#define TAGFILTER_NOT	1	/* exclude only filter hits		*/

#endif


Includes/utility/utility.i

    IFND	UTILITY_UTILITY_I
UTILITY_UTILITY_I SET 1
**
**	$Filename: utility/utility.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.1 $
**	$Date: 90/07/12 $
**
**	utility.library include file
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**

UTILITYNAME MACRO
        DC.B	'utility.library',0
    ENDM

    ENDC	; UTILITY_UTILITY_I


Includes/utility/date.i

    IFND	UTILITY_DATE_I
UTILITY_DATE_I	SET	1
**
**	$Filename: utility/date.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.2 $
**	$Date: 91/03/04 $
**
**	Date conversion routines ClockData definition.
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**		All Rights Reserved
**

    IFND EXEC_TYPES_I
    INCLUDE	"exec/types.i"
    ENDC

 STRUCTURE CLOCKDATA,0
    UWORD	sec
    UWORD	min
    UWORD	hour
    UWORD	mday
    UWORD	month
    UWORD	year
    UWORD	wday
    LABEL	CD_SIZE

    ENDC	; UTILITY_DATE_I


Includes/utility/hooks.i

    IFND UTILITY_HOOKS_I
UTILITY_HOOKS_I SET 1
**
**	$Filename: utility/hooks.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.1 $
**	$Date: 90/07/12 $
**
**	callback hooks
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**		All Rights Reserved
**

    IFND EXEC_TYPES_I
    INCLUDE "exec/types.i"
    ENDC

    IFND EXEC_NODES_I
    INCLUDE "exec/nodes.i"
    ENDC

; New Hook conventions
; A0 - pointer to hook itself
; A1 - pointer to parameter packed ("message")
; A2 - Hook specific address data ("object," e.g, gadget )

 STRUCTURE HOOK,MLN_SIZE
    APTR	h_Entry			; assembler entry point
    APTR	h_SubEntry		; optional HLL entry point
    APTR	h_Data			; owner specific
 LABEL		h_SIZEOF

 ENDC


Includes/utility/tagitem.i

    IFND UTILITY_TAGITEM_I
UTILITY_TAGITEM_I SET	1
**
**	$Filename: utility/tagitem.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.3 $
**	$Date: 91/01/24 $
**
**	extended specification mechanism
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**		All Rights Reserved
**

    IFND EXEC_TYPES_I
    INCLUDE "exec/types.i"
    ENDC

; =======================================================================
; ====	TagItem	==========================================================
; =======================================================================
; This data type may propagate through the system for more general use.
; In the meantime, it is used as a general mechanism of extensible data
; arrays for parameter specification and property inquiry (coming soon
; to a display controller near you).
;
; In practice, an array (or chain of arrays) of TagItems is used.

 STRUCTURE	TagItem,0
    ULONG	ti_Tag		; identifies the type of this item
    ULONG	ti_Data		; type-specific data, can be a pointer
    LABEL	ti_SIZEOF

; ----	system tag values -----------------------------
TAG_DONE	EQU	0  ; terminates array of TagItems. ti_Data unused
TAG_IGNORE	EQU	1  ; ignore this item, not end of array
TAG_MORE	EQU	2  ; ti_Data is pointer to another array of TagItems
               ; note that this tag terminates the current array
TAG_SKIP	EQU	3  ; skip this and the next ti_Data items

; ----	user tag identification -----------------------
TAG_USER	EQU	$80000000  ; differentiates user tags from system tags

; until further notice, tag bits 16-30 are RESERVED and should be zero.
; Also, the value (TAG_USER | 0) should never be used as a tag value.

    ENDC


Includes/workbench/icon.h

#ifndef WORKBENCH_ICON_H
#define WORKBENCH_ICON_H
/*
**	$Filename: workbench/icon.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.1 $
**	$Date: 90/10/26 $
**
**	external declarations for icon.library
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	All Rights Reserved
*/

#define	ICONNAME	"icon.library"

#endif	/* !WORKBENCH_ICON_H */


Includes/workbench/startup.h

#ifndef WORKBENCH_STARTUP_H
#define WORKBENCH_STARTUP_H
/*
**	$Filename: workbench/startup.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.3 $
**	$Date: 90/07/11 $
**
**	workbench startup definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include "exec/types.h"
#endif

#ifndef EXEC_PORTS_H
#include "exec/ports.h"
#endif

#ifndef LIBRARIES_DOS_H
#include "libraries/dos.h"
#endif

struct WBStartup {
    struct Message	sm_Message;	/* a standard message structure */
    struct MsgPort *	sm_Process;	/* the process descriptor for you */
    BPTR		sm_Segment;	/* a descriptor for your code */
    LONG		sm_NumArgs;	/* the number of elements in ArgList */
    char *		sm_ToolWindow;	/* description of window */
    struct WBArg *	sm_ArgList;	/* the arguments themselves */
};

struct WBArg {
    BPTR		wa_Lock;	/* a lock descriptor */
    BYTE *		wa_Name;	/* a string relative to that lock */
};

#endif	/* !WORKBENCH_STARTUP_H */


Includes/workbench/workbench.h

#ifndef WORKBENCH_WORKBENCH_H
#define WORKBENCH_WORKBENCH_H
/*
**	$Filename: workbench/workbench.h $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.25 $
**	$Date: 90/11/02 $
**
**	workbench.library general definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include "exec/types.h"
#endif

#ifndef	EXEC_NODES_H
#include "exec/nodes.h"
#endif

#ifndef	EXEC_LISTS_H
#include "exec/lists.h"
#endif

#ifndef EXEC_TASKS_H
#include "exec/tasks.h"
#endif

#ifndef INTUITION_INTUITION_H
#include "intuition/intuition.h"
#endif

#define	WBDISK		1
#define	WBDRAWER	2
#define	WBTOOL		3
#define	WBPROJECT	4
#define	WBGARBAGE	5
#define	WBDEVICE	6
#define	WBKICK		7
#define WBAPPICON	8

struct OldDrawerData { /* pre V36 definition */
    struct NewWindow	dd_NewWindow;	/* args to open window */
    LONG		dd_CurrentX;	/* current x coordinate of origin */
    LONG		dd_CurrentY;	/* current y coordinate of origin */
};
/* the amount of DrawerData actually written to disk */
#define OLDDRAWERDATAFILESIZE	(sizeof(struct OldDrawerData))

struct DrawerData {
    struct NewWindow	dd_NewWindow;	/* args to open window */
    LONG		dd_CurrentX;	/* current x coordinate of origin */
    LONG		dd_CurrentY;	/* current y coordinate of origin */
    ULONG		dd_Flags;	/* flags for drawer */
    UWORD		dd_ViewModes;	/* view mode for drawer */
};
/* the amount of DrawerData actually written to disk */
#define DRAWERDATAFILESIZE	(sizeof(struct DrawerData))

struct DiskObject {
    UWORD		do_Magic; /* a magic number at the start of the file */
    UWORD		do_Version; /* a version number, so we can change it */
    struct Gadget	do_Gadget;	/* a copy of in core gadget */
    UBYTE		do_Type;
    char *		do_DefaultTool;
    char **		do_ToolTypes;
    LONG		do_CurrentX;
    LONG		do_CurrentY;
    struct DrawerData *	do_DrawerData;
    char *		do_ToolWindow;	/* only applies to tools */
    LONG		do_StackSize;	/* only applies to tools */

};

#define WB_DISKMAGIC	0xe310	/* a magic number, not easily impersonated */
#define WB_DISKVERSION	1	/* our current version number */
#define WB_DISKREVISION	1	/* our current revision number */
/* I only use the lower 8 bits of Gadget.UserData for the revision # */
#define WB_DISKREVISIONMASK	255

struct FreeList {
    WORD		fl_NumFree;
    struct List		fl_MemList;
};

/* each message that comes into the WorkBenchPort must have a type field
** in the preceeding short.  These are the defines for this type
*/

#define MTYPE_PSTD		1	/* a "standard Potion" message */
#define MTYPE_TOOLEXIT		2	/* exit message from our tools */
#define MTYPE_DISKCHANGE	3	/* dos telling us of a disk change */
#define MTYPE_TIMER		4	/* we got a timer tick */
#define MTYPE_CLOSEDOWN		5	/* <unimplemented> */
#define MTYPE_IOPROC		6	/* <unimplemented> */
#define MTYPE_APPWINDOW		7	/* msg from an app window */
#define MTYPE_APPICON		8	/* msg from an app icon */
#define MTYPE_APPMENUITEM	9	/* msg from an app menuitem */
#define MTYPE_COPYEXIT		10	/* exit msg from copy process */
#define MTYPE_ICONPUT		11	/* msg from PutDiskObject in icon.library */

/* workbench does different complement modes for its gadgets.
** It supports separate images, complement mode, and backfill mode.
** The first two are identical to intuitions GADGIMAGE and GADGHCOMP.
** backfill is similar to GADGHCOMP, but the region outside of the
** image (which normally would be color three when complemented)
** is flood-filled to color zero.
*/
#define GADGBACKFILL	0x0001

/* if an icon does not really live anywhere, set its current position
** to here
*/
#define NO_ICON_POSITION	(0x80000000)

/* workbench now is a library.	this is it's name */
#define WORKBENCH_NAME		"workbench.library"

/* If you find am_Version >= AM_VERSION, you know this structure has
 * at least the fields defined in this version of the include file
 */
#define	AM_VERSION	1

struct AppMessage {
    struct Message am_Message;	/* standard message structure */
    UWORD am_Type;		/* message type */
    ULONG am_UserData;		/* application specific */
    ULONG am_ID;		/* application definable ID */
    LONG am_NumArgs;		/* # of elements in arglist */
    struct WBArg *am_ArgList;	/* the arguements themselves */
    UWORD am_Version;		/* will be AM_VERSION */
    UWORD am_Class;		/* message class */
    WORD am_MouseX;		/* mouse x position of event */
    WORD am_MouseY;		/* mouse y position of event */
    ULONG am_Seconds;		/* current system clock time */
    ULONG am_Micros;		/* current system clock time */
    ULONG am_Reserved[8];	/* avoid recompilation */
};

/*
 * The following structures are private.  These are just stub
 * structures for code compatibility...
 */
struct	AppWindow	{ void *aw_PRIVATE;  };
struct	AppIcon		{ void *ai_PRIVATE;  };
struct		AppMenuItem	{ void *ami_PRIVATE; };

#endif	/* !WORKBENCH_WORKBENCH_H */


Includes/workbench/icon.i

    IFND	WORKBENCH_ICON_I
WORKBENCH_ICON_I	SET	1
**
**	$Filename: workbench/icon.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.1 $
**	$Date: 90/10/26 $
**
**	external declarations for icon.library
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	All Rights Reserved
**

ICONNAME	MACRO
        DC.B	'icon.library',0
        ENDM

    ENDC	; WORKBENCH_ICON_I


Includes/workbench/startup.i

    IFND	WORKBENCH_STARTUP_I
WORKBENCH_STARTUP_I	EQU	1
**
**	$Filename: workbench/startup.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 36.4 $
**	$Date: 90/12/02 $
**
**	workbench startup definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	All Rights Reserved
**

    IFND	EXEC_TYPES_I
    INCLUDE	"exec/types.i"
    ENDC

    IFND	EXEC_PORTS_I
    INCLUDE	"exec/ports.i"
    ENDC

    IFND	LIBRARIES_DOS_I
    INCLUDE	"libraries/dos.i"
    ENDC

 STRUCTURE WBStartup,0
    STRUCT	sm_Message,MN_SIZE	; a standard message structure
    APTR	sm_Process		; the process descriptor for you
    BPTR	sm_Segment		; a descriptor for your code
    LONG	sm_NumArgs		; the number of elements in ArgList
    APTR	sm_ToolWindow		; description of window
    APTR	sm_ArgList		; the arguments themselves
    LABEL	sm_SIZEOF

 STRUCTURE WBArg,0
    BPTR	wa_Lock			; a lock descriptor
    APTR	wa_Name			; a string relative to that lock
    LABEL	wa_SIZEOF

    ENDC	; WORKBENCH_STARTUP_I


Includes/workbench/workbench.i

    IFND	WORKBENCH_WORKBENCH_I
WORKBENCH_WORKBENCH_I	EQU	1
**
**	$Filename: workbench/workbench.i $
**	$Release: 2.04 Includes, V37.4 $
**	$Revision: 37.2 $
**	$Date: 91/02/01 $
**
**	workbench.library general definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	All Rights Reserved
**

    IFND	EXEC_TYPES_I
    INCLUDE	"exec/types.i"
    ENDC

    IFND	EXEC_NODES_I
    INCLUDE	"exec/nodes.i"
    ENDC

    IFND	EXEC_LISTS_I
    INCLUDE	"exec/lists.i"
    ENDC

    IFND	EXEC_TASKS_I
    INCLUDE	"exec/tasks.i"
    ENDC

    IFND	INTUITION_INTUITION_I
    INCLUDE	"intuition/intuition.i"
    ENDC

; the Workbench object types
WBDISK		EQU	1
WBDRAWER	EQU	2
WBTOOL		EQU	3
WBPROJECT	EQU	4
WBGARBAGE	EQU	5
WBDEVICE	EQU	6
WBKICK		EQU	7
WBAPPICON	EQU	8

; the main workbench object structure
 STRUCTURE DrawerData,0
    STRUCT	dd_NewWindow,nw_SIZE	; args to open window
    LONG	dd_CurrentX		; current x coordinate of origin
    LONG	dd_CurrentY		; current y coordinate of origin
    LABEL	OldDrawerData_SIZEOF	; pre V36 size
; the amount of OldDrawerData actually written to disk
OLDDRAWERDATAFILESIZE	EQU (OldDrawerData_SIZEOF)
    ULONG	dd_Flags		; flags for drawer
    UWORD	dd_ViewModes		; view mode for drawer
    LABEL	DrawerData_SIZEOF
; the amount of DrawerData actually written to disk
DRAWERDATAFILESIZE	EQU (DrawerData_SIZEOF)

 STRUCTURE DiskObject,0
    UWORD	do_Magic		; a magic num at the start of the file
    UWORD	do_Version		; a version number, so we can change it
    STRUCT	do_Gadget,gg_SIZEOF	; a copy of in core gadget
    UBYTE	do_Type
    UBYTE	do_PAD_BYTE		; Pad it out to the next word boundry
    APTR	do_DefaultTool
    APTR	do_ToolTypes
    LONG	do_CurrentX
    LONG	do_CurrentY
    APTR	do_DrawerData
    APTR	do_ToolWindow		; only applies to tools
    LONG	do_StackSize		; only applies to tools
    LABEL	do_SIZEOF

WB_DISKMAGIC	EQU	$e310	; a magic number, not easily impersonated
WB_DISKVERSION	EQU	1	; our current version number
WB_DISKREVISION	EQU	1	; out current revision number
; I only use the lower 8 bits of Gadget.UserData for the revision #
WB_DISKREVISIONMASK	EQU	$ff

 STRUCTURE FreeList,0
    WORD	fl_NumFree
    STRUCT	fl_MemList,LH_SIZE
    ; weird name to avoid conflicts with FileLocks
    LABEL	FreeList_SIZEOF

* each message that comes into the WorkBenchPort must have a type field
* in the preceeding short.  These are the defines for this type
*

MTYPE_PSTD		EQU	1	; a "standard Potion" message
MTYPE_TOOLEXIT		EQU	2	; exit message from our tools
MTYPE_DISKCHANGE	EQU	3	; dos telling us of a disk change
MTYPE_TIMER		EQU	4	; we got a timer tick
MTYPE_CLOSEDOWN		EQU	5	; <unimplemented>
MTYPE_IOPROC		EQU	6	; <unimplemented>
MTYPE_APPWINDOW		EQU	7	; msg from an app window
MTYPE_APPICON		EQU	8	; msg from an app icon
MTYPE_APPMENUITEM	EQU	9	; msg from an app menuitem
MTYPE_COPYEXIT		EQU	10	; exit message from copy process
MTYPE_ICONPUT		EQU	11	; msg from PutDiskObject in icon.library

* workbench does different complement modes for its gadgets.
* It supports separate images, complement mode, and backfill mode.
* The first two are identical to intuitions GADGIMAGE and GADGHCOMP.
* backfill is similar to GADGHCOMP, but the region outside of the
* image (which normally would be color three when complemented)
* is flood-filled to color zero.
*
GADGBACKFILL		EQU	$0001

* if an icon does not really live anywhere, set its current position
* to here
*
NO_ICON_POSITION	EQU	($80000000)

* workbench now is a library.  this is it's name
WORKBENCH_NAME	MACRO
        dc.b		'workbench.library',0
        ds.w		0
        ENDM

; If you find am_Version >= AM_VERSION, you now this structure has
; at least the fields defined in this version of the include file
AM_VERSION	EQU	1

 STRUCTURE AppMessage,0
    STRUCT am_Message,MN_SIZE	; standard message structure
    UWORD am_Type			; message type
    ULONG am_UserData		; application specific
    ULONG am_ID			; application definable ID
    LONG am_NumArgs			; # of elements in arglist
    APTR am_ArgList			; the arguements themselves
    UWORD am_Version		; will be AM_VERSION
    UWORD am_Class			; message class
    WORD am_MouseX			; mouse x position of event
    WORD am_MouseY			; mount y position of event
    ULONG am_Seconds		; current system clock time
    ULONG am_Micros			; current system clock time
    STRUCT am_Reserved,8		; avoid recompilation
    LABEL AppMessage_SIZEOF

*
* The following structures are private.  These are just stub
* structures for code compatibility...
*
 STRUCTURE AppWindow,0
    STRUCT aw_PRIVATE,0
    LABEL AppWindow_SIZEOF

 STRUCTURE AppIcon,0
     STRUCT ai_PRIVATE,0
    LABEL AppIcon_SIZEOF

 STRUCTURE AppMenuItem,0
    STRUCT ami_PRIVATE,0
    LABEL AppMenuItem_SIZEOF

    ENDC	; WORKBENCH_WORKBENCH_I


amiga_lib.doc

 AddTOF()             CreateTask()          FastRand()
 afp()                CxCustom()            fpa()
 ArgArrayDone()       CxDebug()             FreeIEvents()
 ArgArrayInit()       CxFilter()            GetRexxVar()
 ArgInt()             CxSender()            HookEntry()
 ArgString()          CxSignal()            HotKey()
 arnd()               CxTranslate()         InvertString()
 BeginIO()            dbf()                 NewList()
 CallHook()           DeleteExtIO()         printf()
 CallHookA()          DeletePort()          RangeRand()
 CheckRexxMsg()       DeleteStdIO()         RemTOF()
 CoerceMethod()       DeleteTask()          SetRexxVar()
 CoerceMethodA()      DoMethod()            SetSuperAttrs()
 CreateExtIO()        DoMethodA()           sprintf()
 CreatePort()         DoSuperMethod()       stdio()
 CreateStdIO()        DoSuperMethodA()      TimeDelay()


amiga.lib/AddTOF

NAME
    AddTOF - add a task to the VBlank interrupt server chain.

SYNOPSIS
    AddTOF(i,p,a);

    VOID AddTOF(struct Isrvstr *, APTR, APTR);

FUNCTION
    Adds a task to the vertical-blanking interval interrupt server
    chain. This prevents C programmers from needing to write an
    assembly language stub to do this function.

INPUTS
    i - pointer to an initialized Isrvstr structure
    p - pointer to the C-code routine that this server is to call each
        time TOF happens
    a - pointer to the first longword in an array of longwords that
        is to be used as the arguments passed to your routine
        pointed to by p.

SEE ALSO
    RemTOF(), <graphics/graphint.h>


amiga.lib/afp

NAME
    afp - Convert ASCII string variable into fast floating point

SYNOPSIS
    ffp_value = afp(string);

FUNCTION
    Accepts the address of the ASCII string in C format that is
    converted into an FFP floating point number.

    The string is expected in this Format:
    {S}{digits}{'.'}{digits}{'E'}{S}{digits}
    <*******MANTISSA*******><***EXPONENT***>

    Syntax rules:
    Both signs are optional and are '+' or '-'. The mantissa must be
    present. The exponent need not be present. The mantissa may lead
    with a decimal point. The mantissa need not have a decimal point.
    Examples: All of these values represent the number fourty-two.
                 42            .042e3
                 42.          +.042e+03
                +42.          0.000042e6
            0000042.00       420000e-4
                         420000.00e-0004

    Floating point range:
    Fast floating point supports the value zero and non-zero values
    within the following bounds -
                    18                             20
     9.22337177 x 10   > +number >  5.42101070 x 10
                    18                             -20
    -9.22337177 x 10   > -number > -2.71050535 x 10

    Precision:
    This conversion results in a 24 bit precision with guaranteed
    error less than or equal to one-half least significant bit.

    INPUTS
    string - Pointer to the ASCII string to be converted.

    OUTPUTS
    string - points to the character which terminated the scan
    equ - fast floating point equivalent


amiga.lib/ArgArrayDone

NAME
    ArgArrayDone -- release the memory allocated by a previous call
                    to ArgArrayInit(). (V36)

SYNOPSIS
    ArgArrayDone();

    VOID ArgArrayDone(VOID);

FUNCTION
    This function frees memory and does cleanup required after a
    call to ArgArrayInit(). Don't call this until you are done using
    the ToolTypes argument strings.

SEE ALSO
    ArgArrayInit()


amiga.lib/ArgArrayInit

NAME
    ArgArrayInit -- allocate and initialize a tooltype array. (V36)

SYNOPSIS
    ttypes = ArgArrayInit(argc,argv);

    UBYTE **ArgArrayInit(LONG,UBYTE **);

FUNCTION
    This function returns a null-terminated array of strings
    suitable for sending to icon.library/FindToolType(). This array will
    be the ToolTypes array of the program's icon, if it was started from
    Workbench. It will just be 'argv' if the program was started from
    a shell.

    Pass ArgArrayInit() your startup arguments received by main().

    ArgArrayInit() requires that icon.library be open (even if the caller
    was started from a shell, so that the function FindToolType() can be
    used) and may call GetDiskObject(), so clean up is necessary when
    the strings are no longer needed. The function ArgArrayDone() does
    just that.

INPUTS
    argc - the number of arguments in argv, 0 when started from Workbench
    argv - an array of pointers to the program's arguments, or the
           Workbench startup message when started from WB.

RESULTS
    ttypes - the initialized argument array or NULL if it could not be
             allocated

EXAMPLE
    Use of these routines facilitates the use of ToolTypes or command-
    line arguments to control end-user parameters in Commodities
    applications. For example, a filter used to trap a keystroke for
    popping up a window might be created by something like this:

            char   *ttypes  = ArgArrayInit(argc, argv);
            CxObj   *filter = UserFilter(ttypes, "POPWINDOW", "alt f1");

           ... with ...

           CxObj *UserFilter(char **tt, char *action_name,
                              char *default_descr)
            {
            char *desc;

                desc = FindToolType(tt,action_name);

                return(CxFilter((ULONG)(desc? desc: default_descr)));
            }

    In this way the user can assign "alt f2" to the action by
    entering a tooltype in the program's icon of the form:

            POPWINDOW=alt f2

    or by starting the program from the CLI like so:

            myprogram "POPWINDOW=alt f2"

NOTE
    Your program must open icon.library and set up IconBase before calling
    this routine. In addition IconBase must remain valid until after
    ArgArrayDone() has been called!

SEE ALSO
    ArgArrayDone(), ArgString(), ArgInt(), icon.library/FindToolType()


amiga.lib/ArgInt

NAME
    ArgInt -- return an integer value from a ToolTypes array. (V36)

SYNOPSIS
    value = ArgInt(tt,entry,defaultval)

    LONG ArgInt(UBYTE **,STRPTR,LONG);

FUNCTION
    This function looks in the ToolTypes array 'tt' returned
    by ArgArrayInit() for 'entry' and returns the value associated
    with it. 'tt' is in standard ToolTypes format such as:

            ENTRY=Value

    The Value string is passed to atoi() and the result is returned by
    this function.

    If 'entry' is not found, the integer 'defaultval' is returned.

INPUTS
    tt - a ToolTypes array as returned by ArgArrayInit()
    entry - the entry in the ToolTypes array to search for
    defaultval - the value to return in case 'entry' is not found within
                 the ToolTypes array

RESULTS
    value - the value associated with 'entry', or defaultval if 'entry'
            is not in the ToolTypes array

NOTES
    This function requires that dos.library V36 or higher be opened.

SEE ALSO
    ArgArrayInit()


amiga.lib/ArgString

NAME
    ArgString -- return a string pointer from a ToolTypes array. (V36)

SYNOPSIS
    string = ArgString(tt,entry,defaultstring)

    STRPTR ArgString(UBYTE **,STRPTR,STRPTR);

FUNCTION
    This function looks in the ToolTypes array 'tt' returned
    by ArgArrayInit() for 'entry' and returns the value associated
    with it. 'tt' is in standard ToolTypes format such as:

            ENTRY=Value

    This function returns a pointer to the Value string.

    If 'entry' is not found, 'defaultstring' is returned.

INPUTS
    tt - a ToolTypes array as returned by ArgArrayInit()
    entry - the entry in the ToolTypes array to search for
    defaultstring - the value to return in case 'entry' is not found within
                    the ToolTypes array

RESULTS
    value - the value associated with 'entry', or defaultstring if 'entry'
            is not in the ToolTypes array

SEE ALSO
    ArgArrayInit()


amiga.lib/arnd

NAME
    arnd - ASCII round of the provided floating point string

SYNOPSIS
    arnd(place, exp, &string[0]);

FUNCTION
    Accepts an ASCII string representing an FFP floating point
    number, the binary representation of the exponent of said
    floating point number and the number of places to round to.
    A rounding process is initiated, either to the left or right
    of the decimal place and the result placed back at the
    input address defined by &string[0].

INPUTS
    place - integer representing number of decimal places to round to
    exp - integer representing exponent value of the ASCII string
    &string[0] - address where rounded ASCII string is to be placed
                 (16 bytes)

RESULT
    &string[0] - rounded ASCII string

BUGS
    None


amiga.lib/BeginIO

NAME
    BeginIO -- initiate asynchronous device I/O

SYNOPSIS
    BeginIO(ioReq)

    VOID BeginIO(struct IORequest *);

FUNCTION
    This function takes an IORequest, and passes it directly to the
    "BeginIO" vector of the proper device.  This is equivalent to
    SendIO(), except that io_Flags is not cleared. A good understanding
    of Exec device I/O is required to properly use this function.

    This function does not wait for the I/O to complete.

INPUTS
    ioReq - an initialized and opened IORequest structure with the
            io_Flags field set to a reasonable value (set to 0 if you do
            not require io_Flags).

SEE ALSO
    exec.library/DoIO(), exec.library/SendIO(), exec.library/WaitIO()


amiga.lib/CallHook

NAME
    CallHook -- Invoke a hook given a message on the stack.  (V36)

SYNOPSIS
    result = CallHook( hookPtr, obj, ... )

    ULONG CallHook( struct Hook *, Object *, ... );

FUNCTION
    Like CallHookA(), CallHook() invoke a hook on the supplied
    hook-specific data (an "object") and a parameter packet ("message").
    However, CallHook() allows you to build the message on your stack.

INPUTS
    hookPtr - A system-standard hook
    obj - hook-specific data object
    ... - The hook-specific message you wish to send.  The hook is
        expecting a pointer to the message, so a pointer into your
        stack will be sent.

RESULT
    result - a hook-specific result.

NOTES
    While this function requires V36 or higher intuition.library,
    it first appeared in V37 amiga.lib.

EXAMPLE
    If your hook's message was

        struct myMessage
        {
            ULONG mm_FirstGuy;
            ULONG mm_SecondGuy;
            ULONG mm_ThirdGuy;
        };

    You could write:

        result = CallHook( hook, obj, firstguy, secondguy, thirdguy );

    as a shorthand for:

        struct myMessage msg;

        msg.mm_FirstGuy = firstguy;
        msg.mm_SecondGuy = secondguy;
        msg.mm_ThirdGuy = thirdguy;

        result = CallHookA( hook, obj, &msg );

SEE ALSO
    CallHookA(), utility.library/CallHookPkt(), <utility/hooks.h>


amiga.lib/CallHookA

NAME
    CallHookA -- Invoke a hook given a pointer to a message.  (V36)

SYNOPSIS
    result = CallHookA( hookPtr, obj, message )

    ULONG CallHook( struct Hook *, Object *, APTR );

FUNCTION
    Invoke a hook on the supplied hook-specific data (an "object")
    and a parameter packet ("message").  This function is equivalent
    to utility.library/CallHookPkt().

INPUTS
    hookPtr - A system-standard hook
    obj - hook-specific data object
    message - The hook-specific message you wish to send

RESULT
    result - a hook-specific result.

NOTES
    While this function requires V36 or higher intuition.library,
    it first appeared in V37 amiga.lib.

SEE ALSO
    CallHook(), utility.library/CallHookPkt(), <utility/hooks.h>


amiga.lib/CheckRexxMsg

NAME
    CheckRexxMsg - Check if a RexxMsg is from ARexx

SYNOPSIS
    result = CheckRexxMsg(message)
    D0                    A0

    BOOL CheckRexxMsg(struct RexxMsg *);

FUNCTION
    This function checks to make sure that the message is from ARexx
    directly.  It is required when using the Rexx Variable Interface
    routines (RVI) that the message be from ARexx.

    While this function is new in the V37 amiga.lib, it is safe to
    call it in all versions of the operating system.  It is also
    PURE code, thus usable in resident/pure executables.

NOTE
    This is a stub in amiga.lib.  It is only available via amiga.lib.
    The stub has two labels.  One, _CheckRexxMsg, takes the arguments
    from the stack.  The other, CheckRexxMsg, takes the arguments in
    registers.

EXAMPLE
    if (CheckRexxMsg(rxmsg))
    {
            /* Message is one from ARexx */
    }

INPUTS
    message         A pointer to the RexxMsg in question

RESULTS
    result          A boolean - TRUE if message is from ARexx.

SEE ALSO
    GetRexxVar(), SetRexxVar()


amiga.lib/CoerceMethod

NAME
    CoerceMethod -- Perform method on coerced object.  (V36)

SYNOPSIS
    result = CoerceMethod( cl, obj, MethodID, ... )

    ULONG CoerceMethod( struct IClass *, Object *, ULONG, ... );

FUNCTION
    Boopsi support function that invokes the supplied message
    on the specified object, as though it were the specified
    class.  Equivalent to CoerceMethodA(), but allows you to
    build the message on the stack.

INPUTS
    cl - pointer to boopsi class to receive the message
    obj - pointer to boopsi object
    ... - method-specific message built on the stack

RESULT
    result - class and message-specific result.

NOTES
    While this function requires V36 or higher intuition.library,
    it first appeared in V37 amiga.lib.

SEE ALSO
    CoerceMethodA(), DoMethodA(), DoSuperMethodA(), <intuition/classusr.h>
    ROM Kernel Manual boopsi section


amiga.lib/CoerceMethodA

NAME
    CoerceMethodA -- Perform method on coerced object.  (V36)

SYNOPSIS
    result = CoerceMethodA( cl, obj, msg )

    ULONG CoerceMethodA( struct IClass *, Object *, Msg * );

FUNCTION
    Boopsi support function that invokes the supplied message
    on the specified object, as though it were the specified
    class.

INPUTS
    cl - pointer to boopsi class to receive the message
    obj - pointer to boopsi object
    msg - pointer to method-specific message to send

RESULT
    result - class and message-specific result.

NOTES
    While this function requires V36 or higher intuition.library,
    it first appeared in V37 amiga.lib.
    Some early example code may refer to this function as CM().

SEE ALSO
    CoerceMethod(), DoMethodA(), DoSuperMethodA(), <intuition/classusr.h>
    ROM Kernel Manual boopsi section


amiga.lib/CreateExtIO

NAME
    CreateExtIO -- create an IORequest structure

SYNOPSIS
    ioReq = CreateExtIO(port,ioSize);

    struct IORequest *CreateExtIO(struct MsgPort *, ULONG);

FUNCTION
    Allocates memory for and initializes a new IO request block
    of a user-specified number of bytes. The number of bytes
    MUST be the size of a legal IORequest (or extended IORequest)
    or very nasty things will happen.

INPUTS
    port - an already initialized message port to be used for this IO
           request's reply port. If this is NULL this function fails.
    ioSize - the size of the IO request to be created.

RESULT
    ioReq - a new IO Request block, or NULL if there was not enough memory

EXAMPLE
    if (ioReq = CreateExtIO(CreatePort(NULL,0),sizeof(struct IOExtTD)))

SEE ALSO
    DeleteExtIO(), CreatePort(), exec.library/CreateMsgPort()


amiga.lib/CreatePort

NAME
    CreatePort - Allocate and initialize a new message port

SYNOPSIS
    port = CreatePort(name,pri)

    struct MsgPort *CreatePort(STRPTR,LONG);

FUNCTION
    Allocates and initializes a new message port. The message list
    of the new port will be prepared for use (via NewList).  A signal
    bit will be allocated, and the port will be set to signal your
    task when a message arrives (PA_SIGNAL).

    You *must* use DeletePort() to delete ports created with
    CreatePort()!

INPUTS
    name - public name of the port, or NULL if the port is not named.
           The name string is not copied. Most ports do not need names,
           see notes below on this.
    pri  - Priority used for insertion into the public port list,
           normally 0.

RESULT
    port - a new MsgPort structure ready for use, or NULL if the port
           could not be created due to not enough memory or no available
           signal bit.

NOTE
    In most cases, ports should not be named. Named ports are used for
    rendez-vous between tasks. Everytime a named port needs to be located,
    the list of all named ports must be traversed. The more named
    ports there are, the longer this list traversal takes. Thus, unless
    you really need to, do not name your ports, which will keep them off
    of the named port list and improve system performance.

BUGS
    With versions of amiga.lib prior to V37.14, this function would
    not fail even though it couldn't allocate a signal bit. The port
    would be returned with no signal allocated.

SEE ALSO
    DeletePort(), exec.library/FindPort(), <exec/ports.h>,
    exec.library/CreateMsgPort()


amiga.lib/CreateStdIO

NAME
    CreateStdIO -- create an IOStdReq structure

SYNOPSIS
    ioReq = CreateStdIO(port);

    struct IOStdReq *CreateStdIO(struct MsgPort *)

FUNCTION
    Allocates memory for and initializes a new IOStdReq structure.

INPUTS
    port - an already initialized message port to be used for this IO
           request's reply port. If this is NULL this function fails.

RESULT
    ioReq - a new IOStdReq structure, or NULL if there was not enough
            memory

SEE ALSO
    DeleteStdIO(), CreateExtIO(), exec.library/CreateIORequest()


amiga.lib/CreateTask

NAME
    CreateTask -- Create task with given name, priority, stacksize

SYNOPSIS
    task = CreateTask(name,pri,initPC,stackSize)

    struct Task *CreateTask(STRPTR,LONG,funcEntry,ULONG);

FUNCTION
    This function simplifies program creation of sub-tasks by
    dynamically allocating and initializing required structures
    and stack space, and adding the task to Exec's task list
    with the given name and priority. A tc_MemEntry list is provided
    so that all stack and structure memory allocated by CreateTask()
    is automatically deallocated when the task is removed.

    An Exec task may not call dos.library functions or any function
    which might cause the loading of a disk-resident library, device,
    or file (since such functions are indirectly calls to dos.library).
    Only AmigaDOS Processes may call AmigaDOS; see the
    dos.library/CreateProc() or the dos.library/CreateNewProc()
    functions for more information.

    If other tasks or processes will need to find this task by name,
    provide a complex and unique name to avoid conflicts.

    If your compiler provides automatic insertion of stack-checking
    code, you may need to disable this feature when compiling sub-task
    code since the stack for the subtask is at a dynamically allocated
    location.  If your compiler requires 68000 registers to contain
    particular values for base relative addressing, you may need to
    save these registers from your main process, and restore them
    in your initial subtask code.

    The function entry initPC is generally provided as follows:

    In C:
    extern void functionName();
    char *tname = "unique name";
    task = CreateTask(tname, 0L, functionName, 4000L);

    In assembler:
            PEA     startLabel

INPUTS
    name - a null-terminated name string
    pri - an Exec task priority between -128 and 127, normally 0
    funcEntry - the address of the first executable instruction
                of the subtask code
    stackSize - size in bytes of stack for the subtask. Don't cut it
                too close - system function stack usage may change.

RESULT
    task - a pointer to the newly created task, or NULL if there was not
           enough memory.

BUGS
    Under exec.library V37 or beyond, the AddTask() function used
    internally by CreateTask() can fail whereas it couldn't fail in
    previous versions of Exec. Prior to amiga.lib V37.14, this function
    did not check for failure of AddTask() and thus might return a
    pointer to a task structure even though the task was not actually
    added to the system.

SEE ALSO
    DeleteTask(), exec/FindTask()


amiga.lib/CxCustom

NAME
    CxCustom -- create a custom commodity object. (V36)

SYNOPSIS
    customObj = CxCustom(action,id);

    CxObj *CxCustom(LONG(*)(),LONG);

FUNCTION
    This function creates a custom commodity object. The action
    of this object on receiving a commodity message is to call a
    function of the application programmer's choice.

    The function provided ('action') will be passed a pointer to
    the actual commodities message (in commodities private data
    space), and will actually execute as part of the input handler
    system task. Among other things, the value of 'id' can be
    recovered from the message by using the function CxMsgID().

    The purpose of this function is two-fold. First, it allows
    programmers to create Commodities Exchange objects with
    functionality that was not imagined or chosen for inclusion
    by the designers. Secondly, this is the only way to act
    synchronously with Commodities.

    This function is a C-language macro for CreateCxObj(), defined
    in <libraries/commodities.h>.

INPUTS
    action - a function to call whenever a message reaches the object
    id - a message id to assign to the object

RESULTS
    customObj - a pointer to the new custom object, or NULL if it could
                not be created.

SEE ALSO
    commodities.library/CreateCxObj(), commodities.library/CxMsgID()


amiga.lib/CxDebug

NAME
    CxDebug -- create a commodity debug object. (V36)

SYNOPSIS
    debugObj = CxDebug(id);

    CxObj *CxDebug(LONG);

FUNCTION
    This function creates a Commodities debug object. The action of this
    object on receiving a Commodities message is to print out information
    about the Commodities message through the serial port (using the
    kprintf() routine). The value of 'id' will also be displayed.

    Note that this is a synchronous occurence (the printing is done by
    the input device task). If screen or file output is desired, using a
    sender object instead of a debug object is necessary, since such
    output is best done by your application process.

    This function is a C-language macro for CreateCxObj(), defined
    in <libraries/commodities.h>.

INPUTS
    id - the id to assign to the debug object, this value is output
         whenever the debug object sends data to the serial port.

RESULTS
    debugObj - a pointer to the debug object, or NULL if it could
               not be created.

SEE ALSO
    commodities.library/CreateCxObj(), CxSender(), debug.lib/kprintf()


amiga.lib/CxFilter

NAME
    CxFilter -- create a commodity filter object. (V36)

SYNOPSIS
    filterObj = CxFilter(description);

    CxObj *CxFilter(STRPTR)

FUNCTION
    Creates an input event filter object that matches the
    'description' string. If 'description' is NULL, the filter will not
    match any messages.

    A filter may be modified by the functions SetFilter(), using
    a description string, and SetFilterIX(), which takes a
    binary Input Expression as a parameter.

    This function is a C-language macro for CreateCxObj(), defined
    in <libraries/commodities.h>.

INPUTS
    description - the description string in the same format as strings
                  expected by commodities.library/SetFilter()

RESULTS
    filterObj - a pointer to the filter object, or NULL if there
                was not enough memory. If there is a problem in the
                description string, the internal error code of the filter
                object will be set to so indicate. This error code may be
                interrogated using the function CxObjError().

SEE ALSO
    commodities.library/CreateCxObj(), commodities.library/SetFilter(),
    commodities.library/SetFilterIX(), commodities.library/CxObjError()


amiga.lib/CxSender

NAME
    CxSender -- create a commodity sender object. (V36)

SYNOPSIS
    senderObj = CxSender(port,id)

    CxObj *CxSender(struct MsgPort *,LONG);

FUNCTION
    This function creates a Commodities sender object. The action
    of this object on receiving a Commodities message is to copy the
    Commodities message into a standard Exec Message, to put the value
    'id' in the message as well, and to send the message off to the
    message port 'port'.

    The value 'id' is used so that an application can monitor
    messages from several senders at a single port. It can be retrieved
    from the Exec message by using the function CxMsgID(). The value can
    be a simple integer ID, or a pointer to some application data
    structure.

    Note that Exec messages sent by sender objects arrive
    asynchronously at the destination port. Do not assume anything about
    the status of the Commodities message which was copied into the Exec
    message you received.

    All Exec messages sent to your ports must be replied. Messages may be
    replied after the sender object has been deleted.

    This function is a C-language macro for CreateCxObj(), defined
    in <libraries/commodities.h>.

INPUTS
    port - the port for the sender to send messages to
    id - the id of the messages sent by the sender

RESULTS
    semderObj - a pointer to the sender object, or NULL if it could
                not be created.

SEE ALSO
    commodities.library/CreateCxObj(), commodities.library/CxMsgID(),
    exec.library/PutMsg(), exec.library/ReplyMsg()


amiga.lib/CxSignal

NAME
    CxSignal -- create a commodity signaller object. (V36)

SYNOPSIS
    signalerObj = CxSignal(task,signal);

    CxObj *CxSignal(struct Task *,LONG);

FUNCTION
    This function creates a Commodities signal object. The action
    of this object on receiving a Commodities message is to
    send the 'signal' to the 'task'. The caller is responsible
    for allocating the signal and determining the proper task ID.

    Note that 'signal' is the signal value as returned by AllocSignal(),
    not the mask made from that value.

    This function is a C-language macro for CreateCxObj(), defined
    in <libraries/commodities.h>.

INPUTS
    task - the task for the signaller to signal
    signal - the signal bit number for the signaller to send

RESULTS
    signallerObj - a pointer to the signaller object, or NULL if it could
                   not be created.

SEE ALSO
    commodities.library/CreateCxObj(), exec.library/FindTask()
    exec.library/Signal(), exec.library/AllocSignal(),


amiga.lib/CxTranslate

NAME
    CxTranslate -- create a commodity translator object. (V36)

SYNOPSIS
    translatorObj = CxTranslate(ie);

    CxObj *CxTranslate(struct InputEvent *);

FUNCTION
    This function creates a Commodities 'translator' object.
    The action of this object on receiving a Commodities message is to
    replace that message in the commodities network with a chain of
    Commodities input messages.

    There is one new Commodities input message generated for each input
    event in the linked list starting at 'ie' (and NULL terminated). The
    routing information of the new input messages is copied from the input
    message they replace.

    The linked list of input events associated with a translator object
    can be changed using the SetTranslate() function.

    If 'ie' is NULL, the null translation occurs: that is, the original
    commodities input message is disposed, and no others are created to
    take its place.

    This function is a C-language macro for CreateCxObj(), defined
    in <libraries/commodities.h>.

INPUTS
    ie - the input event list used as replacement by the translator

RESULTS
    translatorObj - a pointer to the translator object, or NULL if it could
                    not be created.

SEE ALSO
    commodities.library/CreateCxObj(), commodities.library/SetTranslate()


amiga.lib/dbf

NAME
    dbf - convert FFP dual-binary number to FFP format

SYNOPSIS
    fnum = dbf(exp, mant);

FUNCTION
    Accepts a dual-binary format (described below) floating point
    number and converts it to an FFP format floating point number.
    The dual-binary format is defined as:

            exp bit  16     = sign (0=>positive, 1=>negative)
            exp bits 15-0   = binary integer representing the base
                                      ten (10) exponent
            man             = binary integer mantissa

INPUTS
    exp - binary integer representing sign and exponent
    mant - binary integer representing the mantissa

RESULT
    fnum - converted FFP floating point format number

BUGS
    None


amiga.lib/DeleteExtIO

NAME
    DeleteExtIO - return memory allocated for extended IO request

SYNOPSIS
    DeleteExtIO(ioReq);

    VOID DeleteExtIO(struct IORequest *);

FUNCTION
    Frees up an IO request as allocated by CreateExtIO().

INPUTS
    ioReq - the IORequest block to be freed, or NULL.

SEE ALSO
    CreateExtIO()


amiga.lib/DeletePort

NAME
    DeletePort - free a message port created by CreatePort()

SYNOPSIS
    DeletePort(port)

    VOID DeletePort(struct MsgPort *);

FUNCTION
    Frees a message port created by CreatePort. All messages that
    may have been attached to this port must have already been
    replied before this function is called.

INPUTS
    port - message port to delete

SEE ALSO
    CreatePort()


amiga.lib/DeleteStdIO

NAME
    DeleteStdIO - return memory allocated for IOStdReq

SYNOPSIS
    DeleteStdIO(ioReq);

    VOID DeleteStdIO(struct IOStdReq *);

FUNCTION
    Frees up an IOStdReq as allocated by CreateStdIO().

INPUTS
    ioReq - the IORequest block to be freed, or NULL.

SEE ALSO
    CreateStdIO(), DeleteExtIO(), exec.library/CreateIORequest()


amiga.lib/DeleteTask

NAME
    DeleteTask -- delete a task created with CreateTask()

SYNOPSIS
    DeleteTask(task)

    VOID DeleteTask(struct Task *);

FUNCTION
    This function simply calls exec.library/RemTask(), deleting a task
    from the Exec task lists and automatically freeing any stack and
    structure memory allocated for it by CreateTask().

    Before deleting a task, you must first make sure that the task is
    not currently executing any system code which might try to signal
    the task after it is gone.

    This can be accomplished by stopping all sources that might reference
    the doomed task, then causing the subtask to execute a Wait(0L).
    Another option is to have the task call DeleteTask()/RemTask() on
    itself.

INPUTS
    task - task to remove from the system

NOTE
    This function simply calls exec.library/RemTask(), so you can call
    RemTask() directly instead of calling this function.

SEE ALSO
    CreateTask(), exec.library/RemTask()


amiga.lib/DoMethod

NAME
    DoMethod -- Perform method on object.  (V36)

SYNOPSIS
    result = DoMethod( obj, MethodID, ... )

    ULONG DoMethod( Object *, ULONG, ... );

FUNCTION
    Boopsi support function that invokes the supplied message
    on the specified object.  The message is invoked on the
    object's true class.  Equivalent to DoMethodA(), but allows
    you to build the message on the stack.

INPUTS
    obj - pointer to boopsi object
    MethodID - which method to send (see <intuition/classusr.h>)
    ... - method-specific message built on the stack

RESULT
    result - specific to the message and the object's class.

NOTES
    While this function requires V36 or higher intuition.library,
    it first appeared in V37 amiga.lib.

SEE ALSO
    DoMethodA(), CoerceMethodA(), DoSuperMethodA(), <intuition/classusr.h>
    ROM Kernel Manual boopsi section


amiga.lib/DoMethodA

NAME
    DoMethodA -- Perform method on object.  (V36)

SYNOPSIS
    result = DoMethodA( obj, msg )

    ULONG DoMethodA( Object *, Msg * );

FUNCTION
    Boopsi support function that invokes the supplied message
    on the specified object.  The message is invoked on the
    object's true class.

INPUTS
    obj - pointer to boopsi object
    msg - pointer to method-specific message to send

RESULT
    result - specific to the message and the object's class.

NOTES
    While this function requires V36 or higher intuition.library,
    it first appeared in V37 amiga.lib.
    Some early example code may refer to this function as DM().

SEE ALSO
    DoMethod(), CoerceMethodA(), DoSuperMethodA(), <intuition/classusr.h>
    ROM Kernel Manual boopsi section


amiga.lib/DoSuperMethod

NAME
    DoSuperMethod -- Perform method on object coerced to superclass. (V36)

SYNOPSIS
    result = DoSuperMethod( cl, obj, MethodID, ... )

    ULONG DoSuperMethod( struct IClass *, Object *, ULONG, ... );

FUNCTION
    Boopsi support function that invokes the supplied message
    on the specified object, as though it were the superclass
    of the specified class.  Equivalent to DoSuperMethodA(),
    but allows you to build the message on the stack.

INPUTS
    cl - pointer to boopsi class whose superclass is to
        receive the message
    obj - pointer to boopsi object
    ... - method-specific message built on the stack

RESULT
    result - class and message-specific result.

NOTES
    While this function requires V36 or higher intuition.library,
    it first appeared in V37 amiga.lib.

SEE ALSO
    CoerceMethodA(), DoMethodA(), DoSuperMethodA(), <intuition/classusr.h>
    ROM Kernel Manual boopsi section


amiga.lib/DoSuperMethodA

NAME
    DoSuperMethodA -- Perform method on object coerced to superclass. (V36)

SYNOPSIS
    result = DoSuperMethodA( cl, obj, msg )

    ULONG DoSuperMethodA( struct IClass *, Object *, Msg * );

FUNCTION
    Boopsi support function that invokes the supplied message
    on the specified object, as though it were the superclass
    of the specified class.

INPUTS
    cl - pointer to boopsi class whose superclass is to
        receive the message
    obj - pointer to boopsi object
    msg - pointer to method-specific message to send

RESULT
    result - class and message-specific result.

NOTES
    While this function requires V36 or higher intuition.library,
    it first appeared in V37 amiga.lib.
    Some early example code may refer to this function as DSM().

SEE ALSO
    CoerceMethodA(), DoMethodA(), DoSuperMethod(), <intuition/classusr.h>
    ROM Kernel Manual boopsi section


amiga.lib/FastRand

NAME
    FastRand - quickly generate a somewhat random integer

SYNOPSIS
    number = FastRand(seed);

    ULONG FastRand(ULONG);

FUNCTION
    Seed value is taken from stack, shifted left one position,
    exclusive-or'ed with hex value $1D872B41 and returned.

INPUTS
    seed - a 32-bit integer

RESULT
    number - new random seed, a 32-bit value

SEE ALSO
    RangeRand()


amiga.lib/fpa

NAME
    fpa - convert fast floating point into ASCII string equivalent

SYNOPSIS
    exp = fpa(fnum, &string[0]);

FUNCTION
    Accepts an FFP number and the address of the ASCII string where it's
    onverted output is to be stored.  The number is converted to a NULL
    terminated ASCII string in and stored at the address provided.
    Additionally, the base ten (10) exponent in binary form is returned.

INPUTS
    fnum       - Motorola Fast Floating Point number
    &string[0] - address for output of converted ASCII character string
                 (16 bytes)

RESULT
    &string[0] - converted ASCII character string
    exp        - integer exponent value in binary form

BUGS
    None


amiga.lib/FreeIEvents

NAME
    FreeIEvents -- free a chain of input events allocated by
                   InvertString(). (V36)

SYNOPSIS
    FreeIEvents(events)

    VOID FreeIEvents(struct InputEvent *);

FUNCTION
    This function frees a linked list of input events as obtained from
    InvertString().

INPUTS
   events - the list of input events to free, may be NULL.

SEE ALSO
    InvertString()


amiga.lib/GetRexxVar

NAME
    GetRexxVar - Gets the value of a variable from a running ARexx program

SYNOPSIS
    error = GetRexxVar(message,varname,bufpointer)
    D0,A1              A0      A1      (C-only)

    LONG GetRexxVar(struct RexxMsg *,char *,char **);

FUNCTION
    This function will attempt to extract the value of the symbol
    varname from the ARexx script that sent the message.  When called
    from C, a pointer to the extracted value will be placed in the
    pointer pointed to by bufpointer.  (*bufpointer will be the pointer
    to the value)

    When called from assembly, the pointer will be returned in A1.

    The value string returned *MUST* *NOT* be modified.

    While this function is new in the V37 amiga.lib, it is safe to
    call it in all versions of the operating system.  It is also
    PURE code, thus usable in resident/pure executables.

NOTE
    This is a stub in amiga.lib.  It is only available via amiga.lib.
    The stub has two labels.  One, _GetRexxVar, takes the arguments
    from the stack.  The other, GetRexxVar, takes the arguments in
    registers.

    This routine does a CheckRexxMsg() on the message.

EXAMPLE

    char    *value;

    /* Message is one from ARexx */
    if (!GetRexxVar(rxmsg,"TheVar",&value))
    {
            /* The value was gotten and now is pointed to by value */
            printf("Value of TheVar is %sn",value);
    }

INPUTS
    message         A message gotten from an ARexx script
    varname         The name of the variable to extract
    bufpointer      (For C only) A pointer to a string pointer.

RESULTS
    error           0 for success, otherwise an error code.
                    (Other codes may exists, these are documented)
                    3  == Insufficient Storage
                    9  == String too long
                    10 == invalid message

    A1              (Assembly only)  Pointer to the string.

SEE ALSO
    SetRexxVar(), CheckRexxMsg()


amiga.lib/HookEntry

NAME
    HookEntry -- Assembler to HLL conversion stub for hook entry.  (V36)

SYNOPSIS
    result = HookEntry( struct Hook *, Object *, APTR )
    D0                  A0             A2        A1

FUNCTION
    By definition, a standard hook entry-point must receive the
    hook in A0, the object in A2, and the message in A1.  If your
    hook entry-point is written in a high-level language and is
    expecting its parameters on the stack, then HookEntry() will
    put the three parameters on the stack and invoke the function
    stored in the hook h_SubEntry field.

    This function is only useful to hook implementers, and is
    never called from C.

INPUTS
    hook - pointer to hook being invoked
    object - pointer to hook-specific data
    msg - pointer to hook-specific message

RESULT
    result - a hook-specific result.

NOTES
    While this function requires V36 or higher intuition.library,
    it first appeared in V37 amiga.lib.

EXAMPLE
    If your hook dispatcher is this:

    dispatch( struct Hook *hookPtr, Object *obj, APTR msg )
    {
        ...
    }

    Then when you initialize your hook, you would say:

    myhook.h_Entry = HookEntry;     /* amiga.lib stub */
    myhook.h_SubEntry = dispatch;   /* HLL entry */

SEE ALSO
    CallHook(), CallHookA(), <utility/hooks.h>


amiga.lib/HotKey

NAME
    HotKey -- create a commodity triad. (V36)

SYNOPSIS
    filterObj = Hotkey(description,port,id);

    CxObj *HotKey(STRPTR,struct MsgPort *,LONG);

FUNCTION
    This function creates a triad of commodity objects to accomplish a
    high-level function.

    The three objects are a filter, which is created to match by the call
    CxFilter(description), a sender created by the call CxSender(port,id),
    and a translator which is created by CxTranslate(NULL), so that it
    swallows any commodity input event messages that are passed down by
    the filter.

    This is the simple way to get a message sent to your program when the
    user performs a particular input action.

    It is strongly recommended that the ToolTypes environment be used to
    allow the user to specify the input descriptions for your application's
    hotkeys.

INPUTS
    description - the description string to use for the filter in the same
                  format as accepted by commodities.library/SetFilter()
    port - port for the sender to send messages to.
    id - id of the messages sent by the sender

RESULTS
    filterObj - a pointer to a filter object, or NULL if it could
                not be created.

SEE ALSO
    CxFilter(), CxSender(), CxTranslate(),
    commodities.library/CxObjError(), commodities.library/SetFilter()


amiga.lib/InvertString

NAME
    InvertString -- produce input events that would generate the
                    given string. (V36)

SYNOPSIS
    events = InvertString(str,km)

    struct InputEvent *InvertString(STRPTR,struct KeyMap *);

FUNCTION
    This function returns a linked list of input events which would
    translate into the string using the supplied keymap (or the system
    default keymap if 'km' is NULL).

    'str' is null-terminated and may contain:
       - ANSI character codes
       - backslash escaped characters:
            n   -   CR
            r   -   CR
            t   -   TAB
            0   -   illegal, do not use!
            \   -   backslash
       - a text description of an input event as used by ParseIX(),
         enclosed in angle brackets.

    An example is:

      abc<alt f1>nhi there.

INPUTS
    str - null-terminated string to convert to input events
    km - keymap to use for the conversion, or NULL to use the default
         keymap.

RESULTS
    events - a chain of input events, or NULL if there was a problem. The
             most likely cause of failure is an illegal description
             enclosed in angled brackets.

             This chain should eventually be freed using FreeIEvents().

SEE ALSO
    commodities.library/ParseIX(), FreeIEvents()


amiga.lib/NewList

NAME
    NewList -- prepare a list structure for use

SYNOPSIS
    NewList(list)

    VOID NewList(struct List *);
    VOID NewList(struct MinList *);

FUNCTION
    Perform the magic needed to prepare a List header structure for
    use; the list will be empty and ready to use.  (If the list is the
    full featured type, you may need to initialize lh_Type afterwards)

    Assembly programmers may want to use the NEWLIST macro instead.

INPUTS
    list - pointer to a List or MinList.

SEE ALSO
    <exec/lists.h>


amiga.lib/printf

NAME
    printf - print a formatted output line to the standard output.

SYNOPSIS
    printf(formatstring [,value [,values] ] );

FUNCTION
    Format the output in accordance with specifications in the format
    string.

INPUTS
    formatString - a C-language-like NULL-terminated format string,
                   with the following supported % options:

      %[flags][width][.limit][length]type

        $     - must follow the arg_pos value, if specified
      flags   - only one allowed. '-' specifies left justification.
      width   - field width. If the first character is a '0', the
                field is padded with leading 0s.
        .     - must precede the field width value, if specified
      limit   - maximum number of characters to output from a string.
                (only valid for %s or %b).
      length  - size of input data defaults to word (16-bit) for types c,
                d, u and x, 'l' changes this to long (32-bit).
      type    - supported types are:
                      b - BSTR, data is 32-bit BPTR to byte count followed
                          by a byte string. A NULL BPTR is treated as an
                          empty string. (V36)
                      d - signed decimal
                      u - unsigned decimal
                      x - hexadecimal with hex digits in uppercase
                      X - hexadecimal with hex digits in lowercase
                      s - string, a 32-bit pointer to a NULL-terminated
                          byte string. A NULL pointer is treated
                          as an empty string.
                      c - character

    value(s) - numeric variables or addresses of null-terminated strings
               to be added to the format information.

NOTE
    The global "_stdout" must be defined, and contain a pointer to
    a legal AmigaDOS file handle. Using the standard Amiga startup
    module sets this up. In other cases you will need to define
    stdout, and assign it to some reasonable value (like what the
    dos.library/Output() call returns). This code would set it up:

            ULONG stdout;
            stdout=Output();

BUGS
    This function will crash if the resulting stream after
    parameter substitution is longer than 140 bytes.


amiga.lib/RangeRand

NAME
    RangeRand - generate a random number within a specific integer range

SYNOPSIS
    number = RangeRand(maxValue);

    UWORD RangeRand(UWORD);

FUNCTION
    RangeRand() accepts a value from 0 to 65535, and returns a value
    within that range.

    maxValue is passed on stack as a 32-bit integer but used as though
    it is only a 16-bit integer. Variable named RangeSeed is available
    beginning with V33 that contains the global seed value passed from
    call to call and thus can be changed in a program by declaring:

      extern ULONG RangeSeed;

INPUTS
    maxValue - the returned random number will be in the range
               [0..maxValue-1]

RESULT
    number - pseudo random number in the range of [0..maxValue-1].

SEE ALSO
    FastRand()


amiga.lib/RemTOF

NAME
    RemTOF - remove a task from the VBlank interrupt server chain.

SYNOPSIS
    RemTOF(i);

    VOID RemTOF(struct Isrvstr *);

FUNCTION
    Removes a task from the vertical-blanking interval interrupt server
    chain.

INPUTS
    i - pointer to an Isrvstr structure

SEE ALSO
    AddTOF(), <graphics/graphint.h>


amiga.lib/SetRexxVar

NAME
    SetRexxVar - Sets the value of a variable of a running ARexx program

SYNOPSIS
    error = SetRexxVar(message,varname,value,length)
    D0                 A0      A1      D0    D1

    LONG SetRexxVar(struct RexxMsg *,char *,char *,ULONG);

FUNCTION
    This function will attempt to the the value of the symbol
    varname in the ARexx script that sent the message.

    While this function is new in the V37 amiga.lib, it is safe to
    call it in all versions of the operating system.  It is also
    PURE code, thus usable in resident/pure executables.

NOTE
    This is a stub in amiga.lib.  It is only available via amiga.lib.
    The stub has two labels.  One, _SetRexxVar, takes the arguments
    from the stack.  The other, SetRexxVar, takes the arguments in
    registers.

    This routine does a CheckRexxMsg() on the message.

EXAMPLE

    char    *value;

    /* Message is one from ARexx */
    if (!SetRexxVar(rxmsg,"TheVar","25 Dollars",10))
    {
            /* The value of TheVar will now be "25 Dollars" */
    }

INPUTS
    message         A message gotten from an ARexx script
    varname         The name of the variable to set
    value           A string that will be the new value of the variable
    length          The length of the value string

RESULTS
    error           0 for success, otherwise an error code.
                    (Other codes may exists, these are documented)
                    3  == Insufficient Storage
                    9  == String too long
                    10 == invalid message

SEE ALSO
    SetRexxVar(), CheckRexxMsg()


amiga.lib/SetSuperAttrs

NAME
    SetSuperAttrs -- Invoke OM_SET method on superclass with varargs. (V36)

SYNOPSIS
    result = SetSuperAttrs( cl, obj, tag, ... )

    ULONG SetSuperAttrs( struct IClass *, Object *, ULONG, ... );

FUNCTION
    Boopsi support function which invokes the OM_SET method on the
    superclass of the supplied class for the supplied object.  Allows
    the ops_AttrList to be supplied on the stack (i.e. in a varargs
    way).  The equivalent non-varargs function would simply be

        DoSuperMethod( cl, obj, OM_SET, taglist, NULL );

INPUTS
    cl - pointer to boopsi class whose superclass is to
        receive the OM_SET message
    obj - pointer to boopsi object
    tag - list of tag-attribute pairs, ending in TAG_DONE

RESULT
    result - class and message-specific result.

NOTES
    While this function requires V36 or higher intuition.library,
    it first appeared in V37 amiga.lib.

SEE ALSO
    CoerceMethodA(), DoMethodA(), DoSuperMethodA(), <intuition/classusr.h>
    ROM Kernel Manual boopsi section


amiga.lib/sprintf

NAME
    sprintf - format a C-like string into a string buffer.

SYNOPSIS
    sprintf(destination formatstring [,value [, values] ] );

FUNCTION
    Performs string formatting identical to printf, but directs the output
    into a specific destination in memory. This uses the ROM version
    of printf (exec.library/RawDoFmt()), so it is very small.

    Assembly programmers can call this by placing values on the
    stack, followed by a pointer to the formatstring, followed
    by a pointer to the destination string.

INPUTS
    destination - the address of an area in memory into which the
                  formatted output is to be placed.
    formatstring - pointer to a null terminated string describing the
                   desired output formatting (see printf() for a
                   description of this string).
    value(s) - numeric information to be formatted into the output
               stream.

SEE ALSO
     printf(), exec.library/RawDoFmt()


amiga.lib/stdio

NAMES
    fclose  - close a file
    fgetc   - get a character from a file
    fprintf - format data to file (see printf())
    fputc   - put character to file
    fputs   - write string to file
    getchar - get a character from stdin
    printf   - put format data to stdout (see exec.library/RawDoFmt)
    putchar - put character to stdout
    puts    - put string to stdout, followed by newline

FUNCTION
    These functions work much like the standard C functions of the same
    names. The file I/O functions all use non-buffered AmigaDOS
    files, and must not be mixed with the file I/O of any C
    compiler. The names of these functions match those found in many
    standard C libraries, when a name conflict occurs, the function is
    generally taken from the FIRST library that was specified on the
    linker's command line.  Thus to use these functions, specify
    the amiga.lib library first.

    To get a suitable AmigaDOS FileHandle, the dos.library/Open() or
    dos.library/Output() functions must be used.

    All of the functions that write to stdout expect an appropriate
    FileHandle to have been set up ahead of time. Depending on
    your C compiler and options, this may have been done by the
    startup code.  Or it can be done manually

    From C:
            extern ULONG stdout;
            /* Remove the extern if startup code did not define stdout */
            stdout=Output();

    From assembly:
            XDEF    _stdout
            DC.L    _stdout ;<- Place result of dos.library/Output() here.


amiga.lib/TimeDelay

NAME
    TimeDelay -- Return after a period of time has elapsed.

SYNOPSIS
    Error = TimeDelay( Unit, Seconds, MicroSeconds )
    D0                 D0    D1       D2

    LONG TimeDelay( LONG, ULONG, ULONG );

FUNCTION
    Waits for the period of time specified before returning to the
    the caller.

INPUTS
    Unit -- timer.device unit to open for this command.
    Seconds -- The seconds field of a timerequest is filled with
        this value. Check the documentation for what a partucular
        timer.device unit expects there.
    MicroSeconds -- The microseconds field of a timerequest is
        filled with this value. Check the documentation for what
        a particular timer.device units expects there.

RESULTS
    Error -- will be zero if all went well; otherwise, non-zero.

NOTES
    Two likely reasons for failures are invalid unit numbers or
    no more free signal bits for this task.

    While this function first appears in V37 amiga.lib, it works
    on Kickstart V33 and higher.

SEE ALSO
    timer.device/TR_ADDREQUEST,
    timer.device/TR_WAITUNTIL,
    timer.device/WaitUnitl()

BUGS


ddebug_lib.doc

 DDoFmt()        DGetNum()          DPutChar()      DPutStr()
 DGetChar()      DMayGetChar()      DPutFmt()       KCmpStr()


DDoFmt

NAME
    DDoFmt -- format data into a character stream.

SYNOPSIS
    DDoFmt(FormatString, DataStream, PutChProc, PutChData);
          A0            A1          A2         A3

FUNCTION
    perform "C"-language-like formatting of a data stream,
    outputting the result a character at a time

INPUTS
    FormatString - a "C"-language-like null terminated format
            string, with the following supported % types:
    DataStream - a stream of data that is interpreted according to
            the format string.
    PutChProc - the procedure to call with each character to be
            output, called as:
        PutChProc(Char,  PutChData);
                  D0-0:8 A3
            the procedure is called with a null Char at the end of
            the format string.
    PutChData - an address register that passes thru to PutChProc.


DGetChar

NAME
    DGetChar - get a character from the parallel port

SYNOPSIS
    char = DGetChar()
    D0

FUNCTION
    get the next character from the parallel port.


DGetNum

NAME
    DGetNum - get a number from the parallel port

SYNOPSIS
    number = DGetNum()
    D0

FUNCTION
    get a signed decimal integer from the parallel port.


DMayGetChar

NAME
    DMayGetChar - return a char iff present, but don't block

SYNOPSIS
    flagChar = DMayGetChar()
    D0

FUNCTION
    return either a -1, saying that there is no char present, or
    the char that was waiting


DPutChar

NAME
    DPutChar - put a character to the parallel port

SYNOPSIS
    char = DPutChar(char)
    D0             D0

FUNCTION
    put a character to the parallel port.


DPutFmt

NAME
    DPutFmt - print formatted data to the parallel port

SYNOPSIS
    DPutFmt(format,values)
           A0     A1

FUNCTION
    print formatted data to the parallel port


DPutStr

NAME
    DPutStr - put a string to the parallel port

SYNOPSIS
    DPutStr(string)
           A0

FUNCTION
    put a null terminated string to the parallel port.


KCmpStr

NAME
    KCmpStr - compare two null terminated strings

SYNOPSIS
    mismatch = KCmpStr(string1, string2)
    D0                A0       A1

FUNCTION
    string1 is compared to string2 using the ASCII coalating
    sequence.


debug_lib.doc

 KCmpStr()       KGetNum()          KPrintF()       KPutStr()
 KGetChar()      KMayGetChar()      KPutChar()


debug.lib/KCmpStr

NAME
    KCmpStr - compare two null terminated strings

SYNOPSIS
    mismatch = KCmpStr(string1, string2)
    D0         A0        A1

FUNCTION
    string1 is compared to string2 using the ASCII coalating
    sequence.  0 indicates the strings are identical.


debug.lib/KGetChar

NAME
    KGetChar - get a character from the console
               (defaults to the serial port at 9600 baud)

SYNOPSIS
    char = KGetChar()
    D0

FUNCTION
    busy wait until a character arrives from the console.
    KGetChar is the assembly interface, _KGetChar and _kgetc
    are the C interfaces.


debug.lib/KGetNum

NAME
    KGetNum - get a number from the console

SYNOPSIS
    number = KGetNum()
    D0

FUNCTION
    get a signed decimal integer from the console.  This will busy
    wait until the number arrives.


debug.lib/KMayGetChar

NAME
    KMayGetChar - return a character if present, but don't wait
                  (defaults to the serial port at 9600 baud)

SYNOPSIS
    flagChar = KMayGetChar()
    D0

FUNCTION
    return either a -1, saying that there is no character present, or
    whatever character was waiting.  KMayGetChar is the assembly
    interface,  _KMayGetChar is the C interface.


debug.lib/KPrintF

NAME
    KPrintF - print formatted data to the console
              (defaults to the serial port at 9600 baud)

SYNOPSIS
    KPrintF("format string",values)
             A0             A1

FUNCTION
    print a formatted C-type string to the console.  See the
    exec RawDoFmt() call for the supported % formatting commands.

INPUTS
    "format string" - A C style string with % commands to indicate
                      where paramters are to be inserted.
    values - A pointer to an array of paramters, to be inserted into
             specified places in the string.

    KPutFmt and KPrintF are identical assembly interfaces that want the
    two pointers in registers.  _KPrintF and _kprintf are C interfaces
    that expect the format string pointer on the stack, and the
    paramters on the stack above that.

SEE ALSO
    exec.library/RawDoFmt, any C compiler's "printf" call.


debug.lib/KPutChar

NAME
    KPutChar - put a character to the console
               (defaults to the serial port at 9600 baud)

SYNOPSIS
    char = KPutChar(char)
    D0              D0

FUNCTION
    Put a character to the console.  This function will not return
    until the character has been completely transmitted.

INPUTS
    KPutChar is the assembly interface, the character must be in D0.
    _KPutChar and _kputc are the C interfaces, the character must be
    a longword on the stack.


debug.lib/KPutStr

NAME
    KPutStr - put a string to the console
               (defaults to the serial port at 9600 baud)

SYNOPSIS
    KPutStr(string)
            A0

FUNCTION
    put a null terminated string to the console.  This function will
    not return until the string has been completely transmitted.

INPUTS
    KPutStr is the assembly interface, a string pointer must be in A0.
    _KPutStr and _kputs are the C interfaces, the string pointer must
    be on the stack.


asl.doc

 AllocAslRequest()       AslRequest()          FreeFileRequest()
 AllocFileRequest()      FreeAslRequest()      RequestFile()


asl.library/AllocAslRequest

NAME
    AllocAslRequest -- alloc an ASL requester, with TagItem modifiers (V36)

SYNOPSIS
    request = AllocAslRequest( type, ptags )
    D0                         D0    A0

    APTR    request;
    ulong   type;
    struct TagItem       *ptags;

FUNCTION
    Allocates an ASL requester data structure of the specified type,
    with optional TagItem modifiers.

INPUTS
    type = type of requester to create.  Currently defined types
        include ASL_FileRequest and ASL_FontRequest.
    ptags = pointer to a tagitem array, which is defined for each
        specified type.  See "asl.h" and example programs for usage
        of various tag types.  See AslRequest() for specifications
        of currently defined tag values and their effects.

    Note that tag values stay in effect for each use of the
    requester until they are cleared or modified by passing the
    same tag with a new value.

    AllocAslRequestTags( type, tags... ) which accepts your tags
    on the stack, is available in amiga.lib.

    Example Usage: AllocAslRequestTags( ASL_FileRequest,
                                        ASL_Hail, "My Title Bar",
                                        TAG_DONE );

RESULT
    Pointer to an initialized requester data structure, or NULL on
    failure.  The data structure returned will match the requested
    type; for type ASL_FileRequest, a struct FileRequester *; for
    ASL_FontRequest, a struct FontRequester *.

    The requester returned may then be passed to AslRequest(), and
    is freed by calling FreeAslRequest().

SEE ALSO
    AslRequest(), FreeAslRequest()


asl.library/AllocFileRequest

NAME
    AllocFileRequest -- allocates a FileRequester structure (V36)

SYNOPSIS
    request = AllocFileRequest()
    D0

    struct FileRequester *request;

FUNCTION
    Creates and initializes the data structure required to pass to the
    RequestFile() function.

INPUTS
    None.  If you wish to get other than default values, you can use
    AllocAslRequest() to set up a file request with tag items.

RESULT
    Pointer to a struct FileRequester, which is to be passed to the
    RequestFile() function.

    The returned FileRequester pointer has public fields which are
    readable by the application as defined in aslbase.h.

CAUTION
    The application MUST use either the AllocFileRequest(), or
    AllocAslRequest(), function to allocate the structure to be passed to
    the FileRequest() or AslRequest() functions; it is not possible to
    create a struct FileRequest except through the library calls.

    Also, any modifications MUST be done through TagItem values, rather
    than directly modifying, unless explicitly documented otherwise.

SEE ALSO
    RequestFile(), FreeAslRequest(), AslRequest()


asl.library/AslRequest

NAME
    AslRequest -- get input from user for an ASL requester (V36)

SYNOPSIS
    BOOL result = AslRequest( request, ptags );
    D0                        A0       A1

    BOOL    result;
    APTR    request;
    struct TagItem       *ptags;

FUNCTION
    Prompts the user for input, based on the specific type of
    requester and modifying tagitems.  The actions and results
    are specific to the type but in general the action is to open
    a requesting window prompting the user for a specific input.
    If the user cancels or the system aborts the request, NULL
    is returned, otherwise the request data structure readable
    data reflects the user input.
    Note that tag values stay in effect for each use of the
    requester until they are cleared or modified by passing the
    same tag with a new value.

INPUTS
    request = requester structure allocated with AllocAslRequest().
    ptags = pointer to an array of TagItems which may be used to
        modify the requester.

    AslRequestTags( type, tags... ) which accepts your tags
    on the stack, is available in amiga.lib.

    Example Usage: AslRequestTags( ASL_FileRequest,
                                   ASL_Hail, "My Title Bar",
                                   TAG_DONE );

TAGS

    ( REMEMBER - ALL DATA STRUCTURES ARE READ-ONLY EXCEPT BY USING
      TAGITEMS !!! )

    ASL_Hail (STRPTR) - Hailing text to prompt user, typically
        displayed in window title bar.
    ASL_Window (struct Window *) - Parent window for the request
        function, which is used to select the screen on which the
        requesting window will be displayed and also is used for
        a shared IDCMP port.

    ASL_LeftEdge (WORD) - Preferred display position for left edge where
        request window should open.
    ASL_TopEdge (WORD) - Preferred top edge of request window.
    ASL_Width (WORD)   - Preferred width of request window.
    ASL_Height (WORD)  - Preferred height of request window.

    ASL_HookFunc (APTR) - Pointer to callback function, specific to
        each AslRequest type.

    ASL_File (STRPTR) - FileRequester initial filename string.
    ASL_Dir (STRPTR) - FileRequester initial directory path string.

    ASL_FontName (STRPTR) - FontRequester initial fontname string.
    ASL_FontHeight (UWORD) - FontRequester initial height (ta_YSize).
    ASL_FontStyles (UBYTE) - FontRequester initial styles (ta_Style).
    ASL_FontFlags (UBYTE) - FontRequester initial flags (ta_Flags).
    ASL_FrontPen (BYTE) - FontRequester front pen color (fo_FrontPen).
    ASL_BackPen (BYTE) - FontRequester back pen color (fo_BackPen).
    ASL_MinHeight (UWORD) - Minimum height for FontRequester display
        of font sizes.  (Application must check return value).
    ASL_MaxHeight (UWORD) - Maximum height for FontRequester display
        of font sizes. (Application must check ta_YSize returned).

    ASL_OKText (STRPTR) - Replacement for default "OK" gadget text.
        ( Limited to approx. six characters ).
    ASL_CancelText (STRPTR) - Replacement for default "CANCEL"
        gadget text. ( Limited to approx. six characters ).

    ASL_FuncFlags (ULONG) - Function flags, depends on requester
        type.  Example: FILF_SAVE for FileRequester.
    ASL_ExtFlags1 (ULONG) - Extended flags (to pass FILF1_ bitdefs)
               Example: FIL1F_NOFILES for file requester

RESULT
    If NULL, typically the user cancelled the requester or a system
    failure prevented the requester from being opened.  If non-zero,
    values will be set depending on the particular type of request,
    in the requesting data structure.  See "libraries/asl.h" for
    information on the READ-ONLY fields in each specific type of
    requester.

NOTES

    Asl provides a way for applications to interact with requester
    operation via a callback (hook) function.  For the ASL file and
    font requesters, there are two ASL_FuncFlags to specify that you
    want a callback:

         for FileRequester: FILF_DOWILDFUNC and FILF_DOMSGFUNC
         for FontRequester: FONF_DOWILDFUNC and FONF_DOMSGFUNC

    The DOWILDFUNC allows you to perform the pattern matching.
    The DOMSGFUNC allows you to handle IDCMP messages received
    for windows that are sharing a UserPort with the requester.

    If you set one or both of these flags via the ASL_FuncFlags
    tagitem, you must provide a pointer to your hook function
    using the ASL_HookFunc tagitem.  Your function will be called
    as follows:

     ULONG rf_Function(ULONG Mask, CPTR Object, CPTR AslRequester)

    The Mask value is a copy of the specific ASL_FuncFlag value
    the callback is for.  Object is a pointer to a data object
    specific to the reason for the callback (defined by Mask).
    AslRequester is a pointer to the requester structure.

    Note that you can only define one HookFunc per requester.
    Your hook function must examine the Mask passed to it to
    determine what the callback is for and what the Object is.

    The following table will explain what is passed to, and
    expected to be returned by a hook functions for various masks:

    FileRequester DOWILDFUNC
    Purpose: to accept or reject individual files for display list
    Inputs: Mask            = FILF_DOWILDFUNC
            Object          = struct AnchorPath *
            AslRequester    = struct FileRequester *
    Result: You return zero to accept file for display in list

    FontRequester DOWILDFUNC
    Purpose: to accept or reject individual fonts for display list
    Inputs: Mask            = FONF_DOWILDFUNC
            Object          = struct TextAttr *
            AslRequester    = struct FontRequester *
    Result: You return non-zero to accept font for display in list

    FileRequester (or FontRequester) DOMSGFUNC
    Purpose: to handle IDCMP msgs for other windows sharing port
    Inputs: Mask            = FILF_DOMSGFUNC (FONF_DOMSGFUNC)
            Object          = struct IntuiMessage *
            AslRequester    = struct FileRequester (FontRequester) *
    Result: You must return the Object pointer (asl will Reply the Object)

SEE ALSO
    AllocAslRequest(), FreeAslRequest()


asl.library/FreeAslRequest

NAME
    FreeAslRequest - frees requester obtained from AllocAslRequest (V36)

SYNOPSIS
    FreeAslRequest( request )
                    A0

    APTR request;

FUNCTION
    FreeAslRequest() is used to free the structure returned by
    AllocAslRequest() or AllocFileRequest(), in order to free
    all resources associated with that requester after the
    application has completed all use of the data structures.

INPUTS
    request - value returned from AllocAslRequest() or
                    AllocFileRequest().

RESULT
    None.  All resources associated with the request will be
    freed.

SEE ALSO
    AllocAslRequest(), AslRequest(), AllocFileRequest()


asl.library/FreeFileRequest

NAME
    FreeFileRequest -- frees requester allocated by AllocFileRequest (V36)

SYNOPSIS
    FreeFileRequest( request )
                     A0

    struct FileRequester *request;

FUNCTION
    This function is identical to the FreeAslRequest() function, but is
    documented for source code compatability and ease of use.
    Applications may use either FreeAslRequest() or FreeFileRequest() to
    free the data structures allocated by AllocFileRequest().

INPUTS
    request = the return value from AllocFileRequest().

SEE ALSO
    FreeAslRequest()


asl.library/RequestFile

NAME
    RequestFile -- request user to select file(s) (V36)

SYNOPSIS
    BOOL result = RequestFile( request )
    D0                         A0

    BOOL    result;
    struct FileRequester *request;

FUNCTION
    RequestFile() displays a file requester and waits for the user to
    select filenames or cancel the request.  This function is identical
    to the AslRequest() function, except that there is no TagList to
    modify the settings for the requester.  See AslRequest() for details.

INPUT
    request = struct FileRequester * returned by AllocFileRequest().

RESULT
    result - See AslRequest() result.  NULL indicates cancelled.

SEE ALSO
    AllocFileRequest(), FreeFileRequest(), AslRequest()


icon.doc

 AddFreeList()           FreeDiskObject()        GetDiskObjectNew()
 BumpRevision()          FreeFreeList()          MatchToolValue()
 DeleteDiskObject()      GetDefDiskObject()      PutDefDiskObject()
 FindToolType()          GetDiskObject()         PutDiskObject()


icon.library/AddFreeList

NAME
    AddFreeList - add memory to a free list.

SYNOPSIS
    status = AddFreeList(free, mem, len)
      D0                  A0    A1   A2

    BOOL AddFreeList(struct FreeList *, APTR, ULONG);

FUNCTION
    This routine adds the specified memory to the free list.
    The free list will be extended (if required).  If there
    is not enough memory to complete the call, a null is returned.

    Note that AddFreeList does NOT allocate the requested memory.
    It only records the memory in the free list.

INPUTS
    free -- a pointer to a FreeList structure
    mem -- the base of the memory to be recorded
    len -- the length of the memory to be recorded

RESULTS
    status -- TRUE if the call succeeded else FALSE;

SEE ALSO
    AllocEntry(), FreeEntry(), FreeFreeList()

BUGS
    None


icon.library/BumpRevision

NAME
    BumpRevision - reformat a name for a second copy.

SYNOPSIS
    result = BumpRevision(newbuf, oldname)
      D0                    A0      A1

    char *BumpRevision(char *, char *);

FUNCTION
    BumpRevision takes a name and turns it into a "copy_of_name".
    It knows how to deal with copies of copies.  The routine
    will truncate the new name to the maximum dos name size
    (currently 30 characters).

INPUTS
    newbuf - the new buffer that will receive the name
             (it must be at least 31 characters long).
    oldname - the original name

RESULTS
    result - a pointer to newbuf

EXAMPLE
    oldname                          newbuf
    -------                          ------
    "foo"                            "copy_of_foo"
    "copy_of_foo"                    "copy_2_of_foo"
    "copy_2_of_foo"                  "copy_3_of_foo"
    "copy_199_of_foo"                "copy_200_of_foo"
    "copy foo"                       "copy_of_copy foo"
    "copy_0_of_foo"                  "copy_1_of_foo"
    "012345678901234567890123456789" "copy_of_0123456789012345678901"

SEE ALSO

BUGS
    None


icon.library/DeleteDiskObject

NAME
    DeleteDiskObject - Delete a Workbench disk object from disk.     (V37)

SYNOPSIS
    result = DeleteDiskObject(name)
      D0                      A0

    BOOL DeleteDiskObject(char *);

FUNCTION
    This routine will try to delete a Workbench disk object from disk.
    The name parameter will have a ".info" postpended to it, and the
    info file of that name will be deleted.  If the call fails,
    it will return zero.  The reason for the failure may be obtained
    via IoErr().

    This call also updates the Workbench screen if needed.

    Using this routine protects you from any future changes to
    the way icons are stored within the system.

INPUTS
    name -- name of the object (char *)

RESULTS
    result -- TRUE if it worked, false if not.

EXAMPLE
    error=NULL;

    *Check if you have the right library version*

    if (((struct Library *)IconBase)->lib_Version > 36)
    {
            if (!DeleteDiskObject(name)) error=IoErr();
    }
    else
    {
            * Delete name plus ".info" *
    }

    if (error)
    {
            * Do error routine...*
    }

SEE ALSO
    PutDiskObject(), GetDiskObject(), FreeDiskObject()

BUGS
    None


icon.library/FindToolType

NAME
    FindToolType - find the value of a ToolType variable.

SYNOPSIS
    value = FindToolType(toolTypeArray, typeName)
      D0                      A0           A1

    char *FindToolType(char **, char *);

FUNCTION
    This function searches a tool type array for a given entry,
    and returns a pointer to that entry.  This is useful for
    finding standard tool type variables.  The returned
    value is not a new copy of the string but is only
    a pointer to the part of the string after typeName.

INPUTS
    toolTypeArray - an array of strings (char **).
    typeName - the name of the tooltype entry (char *).

RESULTS
    value - a pointer to a string that is the value bound to typeName,
            or NULL if typeName is not in the toolTypeArray.

EXAMPLE
    Assume the tool type array has two strings in it:
        "FILETYPE=text"
        "TEMPDIR=:t"

    FindToolType( toolTypeArray, "FILETYPE" ) returns "text"
    FindToolType( toolTypeArray, "filetype" ) returns "text"
    FindToolType( toolTypeArray, "TEMPDIR" )  returns ":t"
    FindToolType( toolTypeArray, "MAXSIZE" )  returns NULL

SEE ALSO
    MatchToolValue()

BUGS
    None


icon.library/FreeDiskObject

NAME
    FreeDiskObject - free all memory in a Workbench disk object.

SYNOPSIS
    FreeDiskObject(diskobj)
                    A0

    void FreeDiskObject(struct DiskObject *);

FUNCTION
    This routine frees all memory in a Workbench disk object, and the
    object itself.  It is implemented via FreeFreeList().

    GetDiskObject() takes care of all the initialization required
    to set up the object's free list.  This procedure may ONLY
    be called on a DiskObject allocated via GetDiskObject().

INPUTS
    diskobj -- a pointer to a DiskObject structure

RESULTS
    None

SEE ALSO
    GetDiskObject(), PutDiskObject(), DeleteDiskObject(), FreeFreeList()

BUGS
    None


icon.library/FreeFreeList

NAME
    FreeFreeList - free all memory in a free list.

SYNOPSIS
    FreeFreeList(free)
                 A0

    void FreeFreeList(struct FreeList *);

FUNCTION
    This routine frees all memory in a free list, and the
    free list itself.  It is useful for easily getting
    rid of all memory in a series of structures.  There is
    a free list in a Workbench object, and this contains
    all the memory associated with that object.

    A FreeList is a list of MemList structures.  See the
    MemList and MemEntry documentation for more information.

    If the FreeList itself is in the free list, it must be
    in the first MemList in the FreeList.

INPUTS
    free -- a pointer to a FreeList structure

RESULTS
    None

SEE ALSO
    AllocEntry(), FreeEntry(), AddFreeList()

BUGS
    None


icon.library/GetDefDiskObject

NAME
    GetDefDiskObject - read default wb disk object from disk.       (V36)

SYNOPSIS
    diskobj = GetDefDiskObject(def_type)
     D0                          D0

    struct DiskObject *GetDefDiskObject(LONG);

FUNCTION
    This routine reads in a default Workbench disk object from disk.
    The valid def_types can be found in workbench/workbench.h and
    currently include WBDISK thru WBGARBAGE.  If the call fails,
    it will return zero.  The reason for the failure may be obtained
    via IoErr().

    Using this routine protects you from any future changes to
    the way default icons are stored within the system.

INPUTS
    def_type - default icon type (WBDISK thru WBKICK).  Note that the
               define 'WBDEVICE' is not currently supported.

RESULTS
    diskobj -- the default Workbench disk object in question

SEE ALSO
    PutDefDiskObject

BUGS
    None


icon.library/GetDiskObject

NAME
    GetDiskObject - read in a Workbench disk object from disk.

SYNOPSIS
    diskobj = GetDiskObject(name)
      D0                      A0

    struct DiskObject *GetDiskObject(char *);

FUNCTION
    This routine reads in a Workbench disk object in from disk.  The
    name parameter will have a ".info" postpended to it, and the
    info file of that name will be read.  If the call fails,
    it will return zero.  The reason for the failure may be obtained
    via IoErr().

    Using this routine protects you from any future changes to
    the way icons are stored within the system.

    A FreeList structure is allocated just after the DiskObject
    structure; FreeDiskObject makes use of this to get rid of the
    memory that was allocated.

INPUTS
    name -- name of the object (char *) or NULL if you just want a
            DiskObject structure allocated for you (useful when
            calling AddAppIcon in workbench.library).

RESULTS
    diskobj -- the Workbench disk object in question

SEE ALSO
    GetDiskObjectNew(), PutDiskObject(), DeleteDiskObject(),
    FreeDiskObject()

BUGS
    None


icon.library/GetDiskObjectNew

NAME
    GetDiskObjectNew - read in a Workbench disk object from disk.    (V36)

SYNOPSIS
    diskobj = GetDiskObjectNew(name)
      D0                      A0

    struct DiskObject *GetDiskObjectNew(char *);

FUNCTION
    This routine reads in a Workbench disk object in from disk.  The
    name parameter will have a ".info" postpended to it, and the
    info file of that name will be read.  If the call fails,
    it will return zero.  The reason for the failure may be obtained
    via IoErr().

    Using this routine protects you from any future changes to
    the way icons are stored within the system.

    A FreeList structure is allocated just after the DiskObject
    structure; FreeDiskObject makes use of this to get rid of the
    memory that was allocated.

    This call is functionally identical to GetDiskObject with one
    exception.  If its call to GetDiskObject fails, this function calls
    GetDefDiskObject.  This is useful when there is no .info file for the
    icon you are trying to get a disk object for.  Applications that use
    workbench application windows MUST use this call if they want to
    handle the user dropping an icon (that doesn't have a .info file) on
    their window.  The V2.0 icon editor program is an example of a
    workbench application window that uses this call.

INPUTS
    name -- name of the object (char *) or NULL if you just want a
            DiskObject structure allocated for you (useful when
            calling AddAppIcon in workbench.library).

RESULTS
    diskobj -- the Workbench disk object in question

SEE ALSO
    FreeDiskObject(), GetDiskObject(), PutDiskObject(), DeleteDiskObject()

BUGS
    None


icon.library/MatchToolValue

NAME
    MatchToolValue - check a tool type variable for a particular value.

SYNOPSIS
    result = MatchToolValue(typeString, value)
      D0                        A0        A1

    BOOL MatchToolValue(char *, char *);

FUNCTION
    MatchToolValue is useful for parsing a tool type value for
    a known value.  It knows how to parse the syntax for a tool
    type value (in particular, it knows that '|' separates
    alternate values).  Note that the parsing is case insensitve.

INPUTS
    typeString - a ToolType value (as returned by FindToolType)
    value - you are interested if value appears in typeString

RESULTS
    result - TRUE if the value was in typeString else FALSE.

EXAMPLE
    Assume there are two type strings:
        type1 = "text"
        type2 = "a|b|c"

    MatchToolValue( type1, "text" ) returns TRUE
    MatchToolValue( type1, "TEXT" ) returns TRUE
    MatchToolValue( type1, "data" ) returns FALSE
    MatchToolValue( type2, "a" ) returns TRUE
    MatchToolValue( type2, "b" ) returns TRUE
    MatchToolValue( type2, "d" ) returns FALSE
    MatchToolValue( type2, "a|b" ) returns FALSE

SEE ALSO
    FindToolType()

BUGS
    None


icon.library/PutDefDiskObject

NAME
    PutDefDiskObject - write disk object as the default for its type.
                       (V36)

SYNOPSIS
    status = PutDefDiskObject(diskobj)
      D0                        A0

    BOOL PutDefDiskObject(struct DiskObject *);

FUNCTION
    This routine writes out a DiskObject structure, and its
    associated information.  If the call fails, a zero will
    be returned.  The reason for the failure may be obtained
    via IoErr().

    Note that this function calls PutDiskObject internally which means
    that this call (if sucessful) notifies workbench than an icon has
    been created/modified.

    Using this routine protects you from any future changes to
    the way default icons are stored within the system.

INPUTS
    diskobj -- a pointer to a DiskObject

RESULTS
    status -- TRUE if the call succeeded else FALSE

SEE ALSO
    GetDefDiskObject

BUGS
    None


icon.library/PutDiskObject

NAME
    PutDiskObject - write out a DiskObject to disk.

SYNOPSIS
    status = PutDiskObject(name, diskobj)
      D0                    A0      A1

    BOOL PutDiskObject(char *, struct DiskObject *);

FUNCTION
    This routine writes out a DiskObject structure, and its
    associated information.  The file name of the info
    file will be the name parameter with a
    ".info" postpended to it.  If the call fails, a zero will
    be returned.  The reason for the failure may be obtained
    via IoErr().

    As of release V2.0, PutDiskObject (if sucessful) notifies workbench
    han an icon has been created/modified.

    Using this routine protects you from any future changes to
    the way icons are stored within the system.

INPUTS
    name -- name of the object (pointer to a character string)
    diskobj -- a pointer to a DiskObject

RESULTS
    status -- TRUE if the call succeeded else FALSE

NOTES
    It is recommended that if you wish to copy an icon from one place
    to another than you use GetDiskObject() and PutDiskObject()
    and do not copy them directly.

SEE ALSO
    GetDiskObject(), FreeDiskObject(), DeleteDiskObject()

BUGS
    None


mathieeesingbas.doc

 IEEESPAbs()       IEEESPCmp()      IEEESPFloor()      IEEESPNeg()
 IEEESPAdd()       IEEESPDiv()      IEEESPFlt()        IEEESPSub()
 IEEESPCeil()      IEEESPFix()      IEEESPMul()        IEEESPTst()


mathieeesingbas.library/IEEESPAbs

NAME
    IEEESPAbs -- compute absolute value of IEEE single precision argument

SYNOPSIS
      x   = IEEESPAbs(  y  );
     d0                 d0

    float   x,y;

FUNCTION
    Take the absolute value of argument y and return it to caller.

INPUTS
    y -- IEEE single precision floating point value

RESULT
    x -- IEEE single precision floating point value

BUGS

SEE ALSO


mathieeesingbas.library/IEEESPAdd

NAME
    IEEESPAdd -- add one single precision IEEE number to another

SYNOPSIS
      x   = IEEESPAdd(  y  ,  z  );
     d0                d0     d1

    float   x,y,z;

FUNCTION
    Compute x = y + z in IEEE single precision.

INPUTS
    y -- IEEE single precision floating point value
    z -- IEEE single precision floating point value

RESULT
    x -- IEEE single precision floating point value

BUGS

SEE ALSO
    IEEESPSub


mathieeesingbas.library/IEEESPCeil

NAME
    IEEESPCeil -- compute Ceil function of IEEE single precision number

SYNOPSIS
      x   = IEEESPCeil(  y  );
     d0                  d0

    float   x,y;

FUNCTION
    Calculate the least integer greater than or equal to x and return it.
    This identity is true.  Ceil(x) = -Floor(-x).

INPUTS
    y -- IEEE single precision floating point value

RESULT
    x -- IEEE single precision floating point value

BUGS

SEE ALSO
    IEEESPFloor


mathieeesingbas.library/IEEESPCmp

NAME
    IEEESPCmp -- compare two single precision floating point numbers

SYNOPSIS
      c   = IEEESPCmp(  y  ,  z  );
      d0                d0   d1

    float   y,z;
    long    c;

FUNCTION
    Compare y with z. Set the condition codes for less, greater, or
    equal. Set return value c to -1 if y<z, or +1 if y>z, or 0 if
    y == z.

INPUTS
    y -- IEEE single precision floating point value
    z -- IEEE single precision floating point value

RESULT
   c = 1   cc = gt         for (y > z)
   c = 0   cc = eq         for (y == z)
   c = -1  cc = lt         for (y < z)

BUGS

SEE ALSO


mathieeesingbas.library/IEEESPDiv

NAME
    IEEESPDiv -- divide one single precision IEEE by another

SYNOPSIS
      x   = IEEESPDiv(  y  ,  z  );
     d0                d0    d1

    float   x,y,z;

FUNCTION
    Compute x = y / z in IEEE single precision.
    Note that the Motorola fast floating point Div routine reverses
    the order of the arguments for the C interface, although the
    dividend is still in d0 and the divisor is in d1.

INPUTS
    y -- IEEE single precision floating point value
    z -- IEEE single precision floating point value

RESULT
    x -- IEEE single precision floating point value

BUGS

SEE ALSO
    IEEESPMul


mathieeesingbas.library/IEEESPFix

NAME
    IEEESPFix -- convert IEEE single float to integer

SYNOPSIS
    x   = IEEESPFix(  y  );
    d0               d0

    long    x;
    float   y;

FUNCTION
    Convert IEEE single precision argument to a 32 bit signed integer
    and return result.

INPUTS
    y -- IEEE single precision floating point value

RESULT
    if no overflow occured then return
            x -- 32 bit signed integer
    if overflow return largest +- integer
            For round to zero

BUGS

SEE ALSO
    IEEESPFlt


mathieeesingbas.library/IEEESPFloor

NAME
    IEEESPFloor -- compute Floor function of IEEE single precision number

SYNOPSIS
      x   = IEEESPFloor(  y  );
      d0                  d0

    float   x,y;

FUNCTION
    Calculate the largest integer less than or equal to x and return it.

INPUTS
    y -- IEEE single precision floating point value

RESULT
    x -- IEEE single precision floating point value

BUGS

SEE ALSO
    IEEESPCeil


mathieeesingbas.library/IEEESPFlt

NAME
    IEEESPFlt -- convert integer to IEEE single precision number

SYNOPSIS
      x   = IEEESPFlt(  y  );
     d0                d0

    float   x;
    long    y;

FUNCTION
    Convert a signed 32 bit value to a single precision IEEE value
    and return it in d0. No exceptions can occur with this
    function.

INPUTS
    y -- 32 bit integer in d0

RESULT
    x is a 32 bit single precision IEEE value

BUGS

SEE ALSO
    IEEESPFix


mathieeesingbas.library/IEEESPMul

NAME
    IEEESPMul -- multiply one double precision IEEE number by another

SYNOPSIS
      x   = IEEESPMul(  y  ,  z  );
     d0                d0    d1

    float   x,y,z;

FUNCTION
    Compute x = y * z in IEEE single precision.

INPUTS
    y -- IEEE single precision floating point value
    z -- IEEE single precision floating point value

RESULT
    x -- IEEE single precision floating point value

BUGS

SEE ALSO
    IEEESPDiv


mathieeesingbas.library/IEEESPNeg

NAME
    IEEESPNeg -- compute negative value of IEEE single precision number

SYNOPSIS
      x   = IEEESPNeg(  y  );
      d0               d0

    float   x,y;

FUNCTION
    Invert the sign of argument y and return it to caller.

INPUTS
    y - IEEE single precision floating point value

RESULT
    x - IEEE single precision floating point value

BUGS

SEE ALSO


mathieeesingbas.library/IEEESPSub

NAME
    IEEESPSub -- subtract one single precision IEEE number from another

SYNOPSIS
      x   = IEEESPSub(  y  ,  z  );
     d0                d0     d1

    float   x,y,z;

FUNCTION
    Compute x = y - z in IEEE single precision.

INPUTS
    y -- IEEE single precision floating point value
    z -- IEEE single precision floating point value

RESULT
    x -- IEEE single precision floating point value

BUGS

SEE ALSO
    IEEESPAdd


mathieeesingbas.library/IEEESPTst

NAME
    IEEESPTst -- compare IEEE single precision value to 0.0

SYNOPSIS
      c   = IEEESPTst(  y  );
      d0                d0

    float   y;
    long    c;

FUNCTION
    Compare y to 0.0, set the condition codes for less than, greater
    than, or equal to 0.0.  Set the return value c to -1 if less than,
    to +1 if greater than, or 0 if equal to 0.0.

INPUTS
    y -- IEEE single precision floating point value

RESULT
    c = 1   cc = gt         for (y > 0.0)
    c = 0   cc = eq         for (y == 0.0)
    c = -1  cc = lt         for (y < 0.0)

BUGS

SEE ALSO


commodities.doc

 ActivateCxObj()        CxObjError()          ParseIX()
 AddIEvents()           CxObjType()           RemoveCxObj()
 AttachCxObj()          DeleteCxObj()         RouteCxMsg()
 ClearCxObjError()      DeleteCxObjAll()      SetCxObjPri()
 CreateCxObj()          DisposeCxMsg()        SetFilter()
 CxBroker()             DivertCxMsg()         SetFilterIX()
 CxMsgData()            EnqueueCxObj()        SetTranslate()
 CxMsgID()              InsertCxObj()
 CxMsgType()            InvertKeyMap()


commodities.library/ActivateCxObj

NAME
    ActivateCxObj -- change the activation state of a commodity object.
                     (V36)

SYNOPSIS
    previous = ActivateCxObj(co,true);
                             A0 D0

    LONG ActivateCxObj(CxObj *,LONG);

FUNCTION
    Commodity objects of all types maintain an "activation state".
    If an object is "active", then it performs its particular action
    whenever a commodity message arrives. If the object is "inactive"
    no action is taken, and the message goes on to its next destination.

    All objects are created in the "active" state except brokers
    which are created "inactive". Thus, after you create your
    broker and hang a tree of objects off of it, you must remember
    to use this function to activate it. This causes it to divert all
    messages to your tree of objects.

    This function activates 'co' if 'true' is different than 0. and
    deactivates it otherwise. The previous activation state is
    returned.

INPUTS
    co - the commodity object to affect
    true - 0 to deactivate the object, anything else to activate it

RESULTS
    previous - the previous activation state: 0 if the object was
               inactive, anything else if the object was active

SEE ALSO
    CxBroker()


commodities.library/AddIEvents

NAME
    AddIEvents -- add input events to commodities' input stream. (V36)

SYNOPSIS
    AddIEvents(events)
               A0

    VOID AddIEvents(struct InputEvent *);

FUNCTION
    This function adds a null-terminated linked list of input events to
    the input stream of commodities. It is a touch easier than using the
    input device directly.

    The contents of the input events are copied into commodity
    messages, so they may be disposed of as soon as this call returns.

    The messages are initially routed to the first broker in the
    Commodities Object List.

INPUTS
    events - the list of input events to add

SEE ALSO
    cx_lib/FreeIEvents()


commodities.library/AttachCxObj

NAME
    AttachCxObj -- attach a commodity object to the end of an existing
                   list of objects. (V36)

SYNOPSIS
    AttachCxObj(headObj,co);
                A0      A1

    VOID AttachCxObj(CxObj *,CxObj *);

FUNCTION
    Adds 'co' to the list of objects pointed to by 'headObj'. The
    new object is added at the end of the list.

INPUTS
    headObj - pointer to a list of objects
    co - the object to add to the list

RESULTS
    If 'co' is NULL, this function will record that fact in the
    internal accumulated error of 'headObj'. This error record
    can be retrieved using CxObjError() and cleared using
    ClearCxObjError().

SEE ALSO
    CxObjError(), ClearCxObjError()


commodities.library/ClearCxObjError

NAME
    ClearCxObjError -- clear the accumulated error value of a commodity
                       object. (V36)

SYNOPSIS
    ClearCxObjError(co);
            A0

    VOID ClearCxObjError(CxObj *);

FUNCTION
    This function clears the accumulated error value of commodity object
    'co'.

    It is unwise to do this to a filter if COERR_BADFILTER is set.
    This will fool commodities into thinking the filter is OK. Set
    another valid filter, or leave the error value alone.

INPUTS
    co - the object to affect

SEE ALSO
    CxObjError()


commodities.library/CreateCxObj

NAME
    CreateCxObj -- create a new commodity object. (V36)

SYNOPSIS
    co = CreateCxObj(type,arg1,arg2);
                     D0   A0   A1

    CxObj *CreateCxObj(ULONG,LONG,LONG);

FUNCTION
    This function creates a commodity object of type 'type'. It is not
    proper to call this function directly. Each object creation routine
    except CxBroker() is defined as a macro in <libraries/commodities.h>
    These are independently documented.

    All functions which operate on a commodity object are made with
    a reference to the thirty-two bit value returned by this function
    (or by CxBroker()).

INPUTS
    type - the type of object to create as defined in
           <libraries/commodities.h>
   arg1 - first argument, meaning depends on 'type'
    arg2 - second argument, meaning depends on 'type'

RESULTS
    co - a pointer to the new object or NULL if it could not be created.
         A NULL return indicates typically a lack of system memory. Minor
         problems in creating an object, such as providing a bad filter
         description to cx_lib/CxFilter(), typically don't cause failure,
         but are recorded in an internal error field in the new object
         which can be accessed via CxObjError().

SEE ALSO
    CxObjError(), cx_lib/CxFilter(), cx_lib/CxSender(),
    cx_lib/CxSignal(), cx_lib/CxTranslate(), cx_lib/CxDebug(),
    cx_lib/CxCustom(), CxBroker()


commodities.library/CxBroker

NAME
    CxBroker -- create a commodity broker. (V36)

SYNOPSIS
    broker = CxBroker(nb,error);
                      A0 D0

    CxObj *CxBroker(struct NewBroker *,LONG *);

FUNCTION
    This function creates a broker from the specification found in the
    NewBroker structure pointed to by 'nb'. The purpose and meaning of the
    fields of the NewBroker structure are described below. Also see
    <libraries/commodities.h> for more info.

    struct NewBroker
    {
       BYTE            nb_Version;
       BYTE           *nb_Name;
       BYTE           *nb_Title;
       BYTE           *nb_Descr;
       SHORT           nb_Unique;
       BYTE            nb_Pri;
        struct MsgPort *nb_Port;
        WORD            nb_ReservedChannel;
    };

    nb_Version
    This is the way that future versions of commodities.library
    can identify which version of the NewBroker structure you are using.
    This should be set to NB_VERSION, defined in <libraries/commodities.h>

    nb_Name
    This is the name of the broker. This name is used to find the broker
    in the Commodities Object List and is the name shown in the list
    gadget of the Exchange program. The name string is copied in the
    broker object upon creation, so this string can be discarded right
    after CxBroker() returns. The maximum length of the name string is
    defined by a constant in <libraries/commodities.h>.

    nb_Title, nb_Descr
    These are two strings which appear to the user in the Exchange
    program and describe the application the broker is representing.
    Note that these strings are copied into the broker object.
    The maximum length of these strings that will be recognized are
    defined by constants in <libraries/commodities.h>.

    nb_Unique
    This field indicates what should happen if a broker of the same name
    (nb_Name) already exists in the Commodities Object List. Constants
    in <libraries/commodities.h> allow the caller to specify whether
    another broker is to be created, and whether any existing broker of
    the same name should be notified that an attempt at creating a
    duplicate has been made.

    nb_Pri
    This specifies with what priority the new broker is to be inserted
    within the Commodities Object List. Higher priority nodes appear
    earlier in a list. See <libraries/commodities.h> for guidelines for
    priorities of different types of applications. It is strongly
    recommended that the ToolTypes environment of an application be used
    to allow the end-user to set the priority of the broker.

INPUTS
    nb - an initialized NewBroker structure
    error - a pointer to a longword where to store a failure code, this
            may be NULL

RESULTS
    broker - a pointer to the broker object or NULL upon failure. If the
             'error' is not NULL, a further diagnostic code is placed at
             that address. Error codes are in <libraries/commodities.h> and
             include:

                    CBERR_OK
                    No problems; broker created OK.

                    CBERR_SYSERR
                    System problems, not your fault. Sign of low memory or
                    big problems.

                    CBERR_DUP
                    The nb_Unique field specified that only one broker of
                    'nb_Name' should be allowed, and one already exists.

                    CBERR_VERSION
                    The version specified in 'nb_Version' is unknown to the
                    library.

SEE ALSO
    SetCxObjPri(), <libraries/commodities.h>


commodities.library/CxMsgData

NAME
    CxMsgData -- obtain a pointer to a commodity message's data area. (V36)

SYNOPSIS
    data = CxMsgData(cxm);
                     A0

    UBYTE *CxMsgData(struct CxMsg *);

FUNCTION
    Most commodity messages contain meaningful data, such as an InputEvent
    structure. This function returns a pointer to this data.

    You may get a commodity message from a synchronous (custom object) or
    asynchronous (sender object) source. In the second case, 'data' is
    not valid after you have replied to the message.

INPUTS
    cxm - the commodity message to get the data pointer from

RESULTS
    data - a pointer to the message's data, or NULL if 'cxm' is NULL.

SEE ALSO
    cx_lib/CxSender(), cx_lib/CxCustom()


commodities.library/CxMsgID

NAME
    CxMsgID -- obtain the ID of a commodity message. (V36)

SYNOPSIS
    id = CxMsgID(cxm);
                 A0

    LONG CxMsgID(struct CxMsg *);

FUNCTION
    This function returns the value associated with the cause or source
    of the commodity message 'cxm'. Values are provided by the application
    when a sender or custom object is created.

INPUTS
    cxm - the commodity message to inquire about

RESULTS
    id - if not specified by the application, the ID value of a
        commodity message will be 0. It is suggested that using
         non-zero values in your program as a rule may identify some
         possible errors.

SEE ALSO
    cx_lib/CxSender(), cx_lib/CxCustom()


commodities.library/CxMsgType

NAME
    CxMsgType -- obtain the type of a commodity message. (V36)

SYNOPSIS
    type = CxMsgType(cxm);
                     A0

    ULONG CxMsgType(struct CxMsg *);

FUNCTION
    This function returns the type of a commodity message. Possible values
    of 'type' are defined in <libraries/commodities.h>. Most commodity
    messages are of type CXM_IEVENT.

INPUTS
    cxm - the commodity message to inquire about

RESULTS
    type - the type of the commodity message, possible values are defined
           in <libraries/commodities.h>


commodities.library/CxObjError

NAME
    CxObjError -- obtain a commodity object's accumulated error. (V36)

SYNOPSIS
    error = CxObjError(co);
                       A0

    LONG CxObjError(CxObj *);

FUNCTION
    When a function acting on an object fails, it records the failure
    in the object. This function returns the accumulated error value.
    The values are represented by flag bits defined in
    <libraries/commodities.h>. Several errors may be recorded by multiple
    bits in 'error'.

    The currently defined errors are:

    COERR_ISNULL
      The value of parameter 'co' was in fact NULL. This error
      means "the problem with the object you inquire about is
      that it failed to be created."

    COERR_NULLATTACH
      Using the commodities' list manipulation functions, an attempt was
      made to add a NULL object to the list belonging to 'co'. This allows
      a line of code as follows to exist in an error-tolerant program:

        AttachCxObj(filter,CxSender(myport,MY_ID));

    COERR_BADFILTER
      The most recent filter specification for a filter object
      was faulty. This happens if no sense can be made out of a
      description string, or if an input expression (IX) has an
      invalid format or version byte. When this bit is set in a
      filter's error field, the filter will match nothing, but this
      is not the proper way to "turn off" a filter, use ActivateCxObj().

    COERR_BADTYPE
      A type specific operation, such as SetFilterIX(), was called
      for object 'co', but 'co' isn't of the proper type.

INPUTS
    co - the commodity object to get the accumulated error from

RESULTS
    error - the accumulated error

SEE ALSO
    SetFilter(), SetFilterIX(), AttachCxObj(), ActivateCxObj(),
    ClearCxObjError()


commodities.library/CxObjType

NAME
    CxObjType -- obtain the type of a commodity object. (V36)

SYNOPSIS
    type = CxObjType(co);
                     A0

    ULONG CxObjType(CxObj *);

FUNCTION
    This function should not really be necessary. It returns
    the type of a commodity object, which you should already
    know, since you created it in the first place.

INPUTS
    co - the commodity object to inquire about

RESULTS
    type - the type of the commodity object, possible values are
           defined in <libraries/commodities.h>

SEE ALSO
    CreateCxObj()


commodities.library/DeleteCxObj

NAME
    DeleteCxObj -- delete a commmodity object. (V36)

SYNOPSIS
    DeleteCxObj(co);
                A0

    VOID DeleteCxObj(CxObj *);

FUNCTION
    Deletes a commodity object of any type. If the object
    is linked into a list, it is first removed. Note that
    the handle 'co' is invalid after this function is called.

    Also note that deleting an object which has other objects attached
    to it may be undesirable. Use the function DeleteCxObjAll()
    to delete an entire sub-tree of objects.

INPUTS
    co - the commodity object to delete

SEE ALSO
    DeleteCxObjAll()


commodities.library/DeleteCxObjAll

NAME
    DeleteCxObjAll -- recursively delete a tree of commodity objects.
                      (V36)

SYNOPSIS
    DeleteCxObjAll(co);
                   A0

    VOID DeleteCxObjAll(CxObj *);

FUNCTION
    This function deletes the commodity object 'co', and
    recursively deletes all objects attached to it, and the
    objects attached to them, etc.

    If 'co' is linked into a list, it is first removed. Note
    that the handle 'co' is invalid after this function is called.

    This function is useful when an application exits: most
    applications can clean up completely by deleting the
    entire sub-tree of objects starting at their broker.

INPUTS
    co - the first commodity object to delete

SEE ALSO
    DeleteCxObj()


commodities.library/DisposeCxMsg

NAME
    DisposeCxMsg -- delete a commodity message. (V36)

SYNOPSIS
    DisposeCxMsg(cxm);
                 A0

    VOID DisposeCxMsg(struct CxMsg *);

FUNCTION
    This function eliminates the commodity message pointed to by 'cxm'.
    Can be used to 'swallow' InputEvents by disposing of every commodity
    message of type CXM_IEVENT.

INPUTS
    cxm - the commodity message to delete


commodities.library/DivertCxMsg

NAME
    DivertCxMsg -- send a commodity message down an object list. (V36)

SYNOPSIS
    DivertCxMsg(cxm,headObj,returnObj);
                A0  A1      A2

    VOID DivertCxMsg(struct CxMsg *,CxObj *,CxObj *);

FUNCTION
    This function sends the commodity message 'cxm' down the list of
    objects attached to 'headObj'. The pointer 'returnObj' is first
    pushed onto the routing stack of 'cxm' so that when the end of the
    list of 'headObj' is reached the SUCCESSOR of 'returnObj' is the
    next destination.

    For example, when a filter finds a match with a message, the
    message is diverted down the filter's list like this:

            DivertCxMsg(cxm,filter,filter);

INPUTS
    cxm - the commodity message to divert
    headObj - the list of objects to divert the message to
    returnObj - the object to use as a place holder

SEE ALSO
    RouteCxMsg()


commodities.library/EnqueueCxObj

NAME
    EnqueueCxObj -- insert a commodity object within a list of objects
                    based on object priority. (V36)

SYNOPSIS
    EnqueueCxObj(headObj,co);
                 A0      A1

    VOID EnqueueCxObj(CxObj *,CxObj *);

FUNCTION
    This function puts object 'co' into the list of object 'headObj'.
    The insertion point is determined by the object's priority. The
    objects are kept in the list from the highest priority to the
    lowest. New nodes are inserted in front of the first node with a
    lower priority. Hence a FIFO queue for nodes of equal priority.

    The priority of the commodity object can be set using SetCxObjPri().

INPUTS
    headObj - pointer to a list of objects
    co - the object to add to the list

RESULTS
    If 'co' is NULL, this function will record that fact in the
    internal accumulated error of 'headObj'. This error record
    can be retrieved using CxObjError() and cleared using
    ClearCxObjError().

SEE ALSO
    SetCxObjPri(), CxObjError(), ClearCxObjError()


commodities.library/InsertCxObj

NAME
    InsertCxObj -- insert a commodity object in a list after a given
                   object. (V36)

SYNOPSIS
    InsertCxObj(headObj,co,pred);
                A0      A1 A2

    VOID InsertCxObj(CxObj *,CxObj *,CxObj *);

FUNCTION
    Adds 'co' to the list of objects pointed to by 'headObj' after
    object 'pred'.

INPUTS
    headObj - pointer to a list of objects
    co - the object to insert in the list
    pred - the object after which 'co' should be inserted. If this is NULL
           then 'co' is added to the head of the list.

RESULTS
    If 'co' is NULL, this function will record that fact in the
    internal accumulated error of 'headObj'. This error record
    can be retrieved using CxObjError() and cleared using
    ClearCxObjError().

SEE ALSO
    CxObjError(), ClearCxObjError()


commodities.library/InvertKeyMap

NAME
    InvertKeyMap -- generate an input event from an ANSI code. (V36)

SYNOPSIS
    success = InvertKeyMap(ansicode,event,km)
                           D0       A0    A1

    BOOL InvertKeyMap(ULONG,struct InputEvent *,struct KeyMap *);

FUNCTION
    This function uses the system call MapANSI() to figure out what
    InputEvent translates to an ANSI character code 'ansicode'. The
    InputEvent pointed to by 'event' is filled in with that information.
    The KeyMap 'km' is used for the translation, unless it is NULL, in
    which case the system default keymap (as defined when
    commodities.library is initialized) is used.

INPUTS
    ansicode - the ANSI code to convert to an input event
    event - the InputEvent to fill-in
    km - the keymap to use for the translation, or NULL to use the
         system default keymap.

RESULTS
    success - TRUE if the translation worked, FALSE otherwise.

BUGS
    This function currently handles one-deep dead keys (such as
    <alt f>o). It does not look up the high key map (keystrokes
    with scan codes greater than 0x40), and misses system changes to
    the default key map.

SEE ALSO
    cx_lib/InvertString()


commodities.library/ParseIX

NAME
    ParseIX -- initialize an input expression given a description string.
               (V36)

SYNOPSIS
    failureCode = ParseIX(description,ix);
                          A0          A1

    LONG ParseIX(STRPTR,IX *);

FUNCTION
    Given an input description string and an allocated input
    expression, sets the fields of the input expression to
    correspond to the description string.

INPUTS
    description - the string to parse
    ix - the input expression to hold the result of the parse

RESULTS
    failureCode -  0 if all went well,
                  -1 if tokens after end (code spec)
                  -2 if 'description' was NULL


commodities.library/RemoveCxObj

NAME
    RemoveCxObj -- remove a commodity object from a list. (V36)

SYNOPSIS
    RemoveCxObj(co);
                A0

    VOID RemoveCxObj(CxObj *);

FUNCTION
    This function remove 'co' from any list it may be a part of.
    Will not crash if 'co' is NULL, or if it has not been inserted
    in a list (and is not corrupted).

    It is not recommended to remove a broker from the master list.

INPUTS
   co - the object to remove, may be NULL

SEE ALSO
    AttachCxObj(), EnqueueCxObj(), InsertCxObj()


commodities.library/RouteCxMsg

NAME
    RouteCxMsg -- set the next destination of a commodity message. (V36)

SYNOPSIS
    RouteCxMsg(cxm,co);
               A0  A1

    VOID RouteCxMsg(struct CxMsg *,CxObj *);

FUNCTION
    Establishes the next destination of a commodity message
    to be 'co', which must be a valid commodity object, and
    must be linked in ultimately to the Commodities Object List.

    Routing of an object is analogous to a 'goto' in a program.
    There is no effect on the message's routing stack.

INPUTS
    cxm - the commodity message to route
    co - the commodity object to route the message to

SEE ALSO
    DivertCxMsg()


commodities.library/SetCxObjPri

NAME
    SetCxObjPri -- set the priority of a commodity object. (V36)

SYNOPSIS
    SetCxObjPri(co,pri)
                A0 D0

    VOID SetCxObjPri(CxObj *,LONG);

FUNCTION
    This function sets the priority of a commodity object for the
    purposes of EnqueueCxObj().

    It is strongly recommended that the ToolTypes environment be
    utilized to provide end-user control over the priority of
    brokers, but application specific ordering of other objects
    within their lists is not dictated.

INPUTS
    co - the commodity object to affect
    pri - the object's new priority in the range -128 to +127. A value
          of 0 is normal.

SEE ALSO
    EnqueueCxObj()


commodities.library/SetFilter

NAME
    SetFilter -- change the matching condition of a commodity filter.
                 (V36)

SYNOPSIS
    SetFilter(filter,text);
              A0     A1

    VOID SetFilter(CxObj *,STRPTR);

FUNCTION
    This function changes the matching condition of a commodity input
    filter to that described by the input description string 'text'.

INPUTS
    filter - the filter object to affect
    text - the new matching conditions for the filter

RESULTS
    The internal error of 'filter' will have the COERR_BADFILTER
    bit set or cleared depending on the failure or success of this
    function.

SEE ALSO
    SetFilterIX(), CxObjError()


commodities.library/SetFilterIX

NAME
    SetFilterIX -- change the matching condition of a commodity filter.
                   (V36)

SYNOPSIS
    SetFilterIX(filter,ix);
                A0     A1

    VOID SetFilterIX(CxObj *,IX *);

FUNCTION
    This function changes the matching condition of a commodity input
    filter to that described by the binary input expression pointed by
    'ix'.

    Input expressions are defined in <libraries/commodities.h>.
    It is important to remember that the first field of the input
    expression structure must indicate which version of the
    input expression structure is being used.

INPUTS
    filter - the filter object to affect
    ix - the new matching conditions for the filter

RESULTS
    The internal error of 'filter' will have the COERR_BADFILTER
    bit set or cleared depending on the failure or success of this
    function.

SEE ALSO
    SetFilter(), CxObjError(), <libraries/commodities.h>


commodities.library/SetTranslate

NAME
    SetTranslate -- replace a translator object's translation list. (V36)

SYNOPSIS
    SetTranslate(translator,events);
                 A0         A1

    VOID SetTranslate(CxObj *,struct InputEvent *);

FUNCTION
    This function replaces the translation list of a commodity
    translator object with the linked list starting at 'events'.

    A NULL value for 'events' indicates that the object 'translator'
    should swallow all commodity messages that are sent its way.

    Note that the input events are not copied into commodities' private
    memory, but the value of 'events' is used -- asynchronously to the
    application program -- to find a chain of InputEvents in the
    application's data space. At the time of translation, each input event
    is copied into its own new commodity message.

    The above means that no other commodities' user, nor
    commodities.library itself will be modifying your list of InputEvents.
    On the other hand, your program must not corrupt the input event
    chain that has been presented to a translator.

INPUTS
    translator - the translator object to affect
    events - the new input event translation list

SEE ALSO
    <devices/inputevent.h>, cx_lib/CxTranslate()


iffparse.doc

 HookEntry()             FreeIFF()            PropChunk()
 AllocIFF()              FreeLocalItem()      PropChunks()
 AllocLocalItem()        GoodID()             PushChunk()
 CloseClipboard()        GoodType()           ReadChunkBytes()
 CloseIFF()              IDtoStr()            ReadChunkRecords()
 CollectionChunk()       InitIFF()            SetLocalItemPurge()
 CollectionChunks()      InitIFFasClip()      StopChunk()
 CurrentChunk()          InitIFFasDOS()       StopChunks()
 EntryHandler()          LocalItemData()      StopOnExit()
 ExitHandler()           OpenClipboard()      StoreItemInContext()
 FindCollection()        OpenIFF()            StoreLocalItem()
 FindLocalItem()         ParentChunk()        WriteChunkBytes()
 FindProp()              ParseIFF()           WriteChunkRecords()
 FindPropContext()       PopChunk()


HookEntry

NAME
    HookEntry -- call-back stub vector (LANGUAGE SPECIFIC LINK ROUTINE)

SYNOPSIS
    This function is never called directly by the client.

FUNCTION
    HookEntry's purpose is to do language-specific setup and conversion
    of parameters passed from a library to a client call-back routine.
    Under Kickstart 2.0, a standard for call-backs has been established.
    The registers will contain the following items:

            A0:     pointer to hook that enabled us to get here.
            A2:     pointer to "object."
            A1:     pointer to "message packet."

    In iffparse, the "object" will vary from routine to routine.  The
    "message packet" is also specific to the operation involved (RTFM!).

    THIS ROUTINE IS NOT PART OF IFFPARSE.  It, or something similar, is
    part of the compiler vendor's link library.  (If it's not there,
    cobbling up your own isn't too hard.)

SEE ALSO
    EntryHandler(), ExitHandler(), InitIFF(), SetLocalItemPurge(),
    utility/hooks.h (A must-read;  LOTS of details in there)


iffparse.library/AllocIFF

NAME
    AllocIFF -- Create a new IFFHandle structure.

SYNOPSIS
    iff = AllocIFF ()
    d0

    struct IFFHandle *iff;

FUNCTION
    Allocates a new IFFHandle structure and initializes the basic values.
    This function is the only supported way to create an IFFHandle
    structure since there are private fields that need to be initialized.

INPUTS

RESULT
    iff     - pointer to IFFHandle structure or NULL if the allocation
              failed.

EXAMPLE

NOTES

BUGS

SEE ALSO
    FreeIFF()


iffparse.library/AllocLocalItem

NAME
    AllocLocalItem -- Create a local context item structure.

SYNOPSIS
    item = AllocLocalItem (type, id, ident, usize)
     d0                     d0   d1   d2     d3

    struct LocalContextItem *item;
    LONG                    type, id, ident, usize;

FUNCTION
    Allocates and initializes a LocalContextItem structure with "usize"
    bytes of associated user data.  This is the only supported way to
    create such an item.  The user data can be accessed with the
    LocalItemData function.  An item created with this function
    automatically has its purge vectors set up correctly to dispose of
    itself and its associated user data area.  Any additional cleanup
    should be done with a user-supplied purge vector.

INPUTS
    type,id - additional longword identification values.
    ident   - longword identifier for class of context item.
    usize   - number of bytes of user data to allocate for this item.

RESULT
    item    - pointer to initialized LocalContextItem or NULL if the
              allocation failed.

EXAMPLE

NOTES

BUGS

SEE ALSO
    FreeLocalItem(), LocalItemData(), StoreLocalItem(),
    StoreItemInContext(), SetLocalItemPurge()


iffparse.library/CloseClipboard

NAME
    CloseClipboard -- Close and free an open ClipboardHandle.

SYNOPSIS
    CloseClipboard (clip)
                     a0

    struct ClipboardHandle *clip;

FUNCTION
    Closes the clipboard.device and frees the ClipboardHandle structure.

INPUTS
    clip    - pointer to ClipboardHandle struct created with
              OpenClipboard.

RESULT

EXAMPLE

NOTES

BUGS

SEE ALSO
    OpenClipboard(), InitIFFasClip()


iffparse.library/CloseIFF

NAME
    CloseIFF -- Close an IFF context.

SYNOPSIS
    CloseIFF (iff)
              a0

    struct IFFHandle *iff;

FUNCTION
    Completes an IFF read or write operation by closing the IFF context
    established for this IFFHandle struct.  The IFFHandle struct itself
    is left ready for re-use and a new context can be opened with
    OpenIFF().  This function can be used for cleanup if a read or write
    fails partway through.

    As part of its cleanup operation, CloseIFF() calls the client-
    supplied stream hook vector.  The IFFStreamCmd packet will be set
    as follows:

            sc_Command:     IFFCMD_CLEANUP
            sc_Buf:         (Not applicable)
            sc_NBytes:      (Not applicable)

    This operation is NOT permitted to fail;  any error code returned
    will be ignored (best to return 0, though).  DO NOT write to this
    structure.

INPUTS
    iff     - pointer to IFFHandle struct previously opened with
              OpenIFF().

RESULT

EXAMPLE

NOTES

BUGS

SEE ALSO
    OpenIFF(), InitIFF()


iffparse.library/CollectionChunk

NAME
    CollectionChunk -- declare a chunk type for collection.

SYNOPSIS
    error = CollectionChunk (iff, type, id)
     d0                      a0    d0   d1

    LONG             error;
    struct IFFHandle *iff;
    LONG             type;
    LONG             id;

FUNCTION
    Installs an entry handler for chunks with the given type and id so
    that the contents of those chunks will be stored as they are
    encountered.  This is like PropChunk() except that more than one
    chunk of this type can be stored in lists which can be returned by
    FindCollection().  The storage of these chunks still follows the
    property chunk scoping rules for IFF files so that at any given
    point, stored collection chunks will be valid in the current context.

INPUTS
    iff     - pointer to IFFHandle struct (does not need to be open).
    type    - type code for the chunk to declare (ex. "ILBM").
    id      - identifier for the chunk to declare (ex. "CRNG").

RESULT
    error   - 0 if successful or an IFFERR_#? error code if not
              successful.

EXAMPLE

NOTES

BUGS

SEE ALSO
    CollectionChunks(), FindCollection(), PropChunk()


iffparse.library/CollectionChunks

NAME
    CollectionChunks -- Declare many collection chunks at once.

SYNOPSIS
    error = CollectionChunks (iff, list, n)
     d0                       a0    a1  d0

    LONG             error;
    struct IFFHandle *iff;
    LONG             *list;
    LONG             n;

FUNCTION
    Declares multiple collection chunks from a list.  The list argument
    is a pointer to an array of long words arranged in pairs.  The format
    for the list is as follows:

            TYPE1, ID1, TYPE2, ID2, ..., TYPEn, IDn

    The argument n is the number of pairs.  CollectionChunks() just calls
    CollectionChunk() n times.

INPUTS
    iff     - pointer to IFFHandle struct.
    list    - pointer to array of longword chunk types and identifiers.
    n       - number of chunks to declare.

RESULT
    error   - 0 if successful or an IFFERR_#? error code if not
              successful.

EXAMPLE

NOTES

BUGS

SEE ALSO
    CollectionChunk()


iffparse.library/CurrentChunk

NAME
    CurrentChunk -- Get context node for current chunk.

SYNOPSIS
    top = CurrentChunk (iff)
    d0                  a0

    struct ContextNode        *top;
    struct IFFHandle  *iff;

FUNCTION
    Returns top context node for the given IFFHandle struct.  The top
    context node corresponds to the chunk most recently pushed on the
    stack, which is the chunk where the stream is currently positioned.
    The ContextNode structure contains information on the type of chunk
    currently being parsed (or written), its size and the current
    position within the chunk.

INPUTS
    iff     - pointer to IFFHandle struct.

RESULT
    top     - pointer to top context node or NULL if none.

EXAMPLE

NOTES

BUGS

SEE ALSO
    PushChunk(), PopChunk(), ParseIFF(), ParentChunk()


iffparse.library/EntryHandler

NAME
    EntryHandler -- Add an entry handler to the IFFHandle context.

SYNOPSIS
    error = EntryHandler (iff, type, id, position, hook, object)
     d0                   a0    d0   d1    d2       a1     a2

    LONG             error;
    struct IFFHandle *iff;
    LONG             type, id, position;
    struct Hook     *hook;
    APTR             object;

FUNCTION
    Installs an entry handler vector for a specific type of chunk into
    the context for the given IFFHandle struct.  Type and id are the
    longword identifiers for the chunk to handle.  The hook is a client-
    supplied standard 2.0 Hook structure, properly initialized.  Position
    tells where to put the handler in the context.  The handler will be
    called whenever the parser enters a chunk of the given type, so the
    IFF stream will be positioned to read the first data byte in the
    chunk.  The handler will execute in the same context as whoever
    called ParseIFF().  The handler will be called (through the hook)
    with the following arguments:

            A0:     the Hook pointer you passed.
            A2:     the 'object' pointer you passed.
            A1:     pointer to a LONG containing the value
                    IFFCMD_ENTRY.

    The error code your call-back routine returns will affect the parser
    in three different ways:

    Return value            Result
    ------------            ------
    0:                      Normal success;  ParseIFF() will continue
                            through the file.
    IFF_RETURN2CLIENT:      ParseIFF() will stop and return the value 0.
                            (StopChunk() is internally implemented using
                            this return value.)
    Any other value:        ParseIFF() will stop and return the value
                            you supplied.  This is how errors should be
                            returned.

INPUTS
    iff     - pointer to IFFHandle struct.
    type    - type code for chunk to handle (ex. "ILBM").
    id      - ID code for chunk to handle (ex. "CMAP").
    position- Local context item position.  One of the IFFSLI_#? codes.
    hook    - pointer to Hook structure.
    object  - a client-defined pointer which is passed in A2 during call-
              back.

RESULT
    error   - 0 if successful or an IFFERR_#? error code if not
              successful.

EXAMPLE

NOTES

BUGS
    Returning the values IFFERR_EOF or IFFERR_EOC from the call-back
    routine *may* confuse the parser.

    There is no way to explicitly remove a handler once installed.
    However, by installing a do-nothing handler using IFFSLI_TOP,
    previous handlers will be overridden until the context expires.

SEE ALSO
    ExitHandler(), StoreLocalItem(), StoreItemInContext(),
    utility/hooks.h


iffparse.library/ExitHandler

NAME
    ExitHandler -- Add an exit handler to the IFFHandle context.

SYNOPSIS
    error = ExitHandler (iff, type, id, position, hook, object)
     d0                  a0    d0   d1    d2       a1     a2

    LONG             error;
    struct IFFHandle *iff;
    LONG             type, id, position;
    struct Hook     *hook;
    APTR             object;

FUNCTION
    Installs an exit handler vector for a specific type of chunk into the
    context for the given IFFHandle struct.  Type and id are the longword
    identifiers for the chunk to handle.  The hook is a client-supplied
    standard 2.0 Hook structure, properly initialized.  Position tells
    where to put the handler in the context.  The handler will be called
    just before the parser exits the given chunk in the "pause" parse
    state.  The IFF stream may not be positioned predictably within the
    chunk.  The handler will execute in the same context as whoever
    called ParseIFF().  The handler will be called (through the hook)
    with the following arguments:

            A0:     the Hook pointer you passed.
            A2:     the 'object' pointer you passed.
            A1:     pointer to a LONG containing the value
                    IFFCMD_EXIT.

    The error code your call-back routine returns will affect the parser
    in three different ways:

    Return value            Result
    ------------            ------
    0:                      Normal success;  ParseIFF() will continue
                            through the file.
    IFF_RETURN2CLIENT:      ParseIFF() will stop and return the value 0.
                            (StopChunk() is internally implemented using
                            this return value.)
    Any other value:        ParseIFF() will stop and return the value
                            you supplied.  This is how errors should be
                            returned.

INPUTS
    iff     - pointer to IFFHandle struct.
    type    - type code for chunk to handle (ex. "ILBM").
    id      - identifier code for chunk to handle (ex. "CMAP").
    position- local context item position.  One of the IFFSLI_#? codes.
    hook    - pointer to Hook structure.
    object  - a client-defined pointer which is passed in A2 during call-
              back.

RESULT
    error   - 0 if successful or an IFFERR_#? error code if not
              successful.

EXAMPLE

NOTES

BUGS
    Returning the values IFFERR_EOF or IFFERR_EOC from the call-back
    routine *may* confuse the parser.

    There is no way to explicitly remove a handler once installed.
    However, by installing a do-nothing handler using IFFSLI_TOP,
    previous handlers will be overridden until the context expires.

SEE ALSO
    EntryHandler(), StoreLocalItem(), StoreItemInContext(),
    utility/hooks.h


iffparse.library/FindCollection

NAME
    FindCollection -- Get a pointer to the current list of collection
                      items.

SYNOPSIS
    ci = FindCollection (iff, type, id)
    d0                   a0    d0   d1

    struct CollectionItem    *ci;
    struct IFFHandle  *iff;
    LONG                    type, id;

FUNCTION
    Returns a pointer to a list of CollectionItem structures for each of
    the collection chunks of the given type encountered so far in the
    course of parsing this IFF file.  The items appearing first in the
    list will be the ones encountered most recently.

INPUTS
    iff     - pointer to IFFHandle struct.
    type    - type code to search for.
    id      - identifier code to search for.

RESULT
    ci      - pointer to last collection chunk encountered with
              links to previous ones.

EXAMPLE

NOTES

BUGS

SEE ALSO
    CollectionChunk(), CollectionChunks()


iffparse.library/FindLocalItem

NAME
    FindLocalItem -- Return a local context item from the context stack.

SYNOPSIS
    lci = FindLocalItem (iff, type, id, ident)
    d0                   a0    d0   d1   d2

    struct LocalContextItem   *lci;
    struct IFFHandle  *iff;
    LONG                    type, id, ident;

FUNCTION
    Searches the context stack of the given IFFHandle struct for a local
    context item which matches the given ident, type and id.  This
    function searches the context stack from the most current context
    backwards, so that the item found (if any) will be the one with
    greatest precedence in the context stack.

INPUTS
    iff     - pointer to IFFHandle struct.
    type    - type code to search for.
    id      - ID code to search for.
    ident   - ident code for the class of context item to search for
              (ex. "exhd" -- exit handler).

RESULT
    lci     - pointer local context item if found, or NULL if nothing
              matched.

EXAMPLE

NOTES

BUGS
    It really should have some sort of wildcarding capability.

SEE ALSO
    StoreLocalItem()


iffparse.library/FindProp

NAME
    FindProp -- Search for a stored property chunk.

SYNOPSIS
    sp = FindProp (iff, type, id)
    d0             a0    d0   d1

    struct StoredProperty     *sp;
    struct IFFHandle  *iff;
    LONG                    type, id;

FUNCTION
    Searches for the stored property which is valid in the given context.
    Property chunks are automatically stored by ParseIFF() when
    pre-declared by PropChunk() or PropChunks().  The StoredProperty
    struct, if found, contains a pointer to a data buffer containing the
    contents of the stored property.

INPUTS
    iff     - pointer to IFFHandle struct.
    type    - type code for chunk to search for (ex. "ILBM").
    id      - identifier code for chunk to search for (ex. "CMAP").

RESULT
    sp      - pointer to stored property, if found, or NULL if none
              found.

EXAMPLE

NOTES

BUGS

SEE ALSO
    PropChunk(), PropChunks()


iffparse.library/FindPropContext

NAME
    FindPropContext -- Get the property context for the current state.

SYNOPSIS
    cn = FindPropContext (iff)
    d0                    a0

    struct ContextNode        *cn;
    struct IFFHandle  *iff;

FUNCTION
    Locates the context node which would be the scoping chunk for
    properties in the current parsing state.  (Huh?)  This is used for
    locating the proper scoping context for property chunks i.e. the
    scope from which a property would apply.  This is usually the FORM
    or LIST with the highest precedence in the context stack.

    If you don't understand this, read the IFF spec a couple more times.

INPUTS
    iff     - pointer to IFFHandle struct.

RESULT
    cn      - ContextNode of property scoping chunk.

EXAMPLE

NOTES

BUGS

SEE ALSO
    CurrentChunk(), ParentChunk(), StoreItemInContext()


iffparse.library/FreeIFF

NAME
    FreeIFF -- Deallocate an IFFHandle struct.

SYNOPSIS
    FreeIFF (iff)
             a0

    struct IFFHandle *iff;

FUNCTION
    Deallocates all resources associated with this IFFHandle struct.  The
    struct MUST have already been closed with CloseIFF().

INPUTS
    iff     - pointer to IFFHandle struct to free.

RESULT

EXAMPLE

NOTES

BUGS

SEE ALSO
    AllocIFF(), CloseIFF()


iffparse.library/FreeLocalItem

NAME
    FreeLocalItem -- Deallocate a local context item structure.

SYNOPSIS
    FreeLocalItem (lci)
                   a0

    struct LocalContextItem *lci;

FUNCTION
    Frees the memory for the local context item and any associated user
    memory as allocated with AllocLocalItem.  User purge vectors should
    call this function after they have freed any other resources
    associated with this item.

    Note that FreeLocalItem() does NOT call the custom purge vector set
    up through SetLocalItemPurge(); all it does is free the local context
    item.  (This implies that your custom purge vector would want to call
    this to ultimately free the LocalContextItem.)  (This description
    still seems muddy; how to clear it up?)

INPUTS
    lci     - pointer to LocalContextItem created with AllocLocalItem.

RESULT

EXAMPLE

NOTES

BUGS

SEE ALSO
    AllocLocalItem()


iffparse.library/GoodID

NAME
    GoodID -- Test if an identifier follows the IFF 85 specification.

SYNOPSIS
    isok = GoodID (id)
     d0            d0

    LONG isok, id;

FUNCTION
    Tests the given longword identifier to see if it meets all the EA IFF
    85 specifications for a chunk ID.  If so, it returns non-zero,
    otherwise 0.

INPUTS
    id      - potential 32 bit identifier.

RESULT
    isok    - non-zero if this is a valid ID, 0 otherwise.

EXAMPLE

NOTES

BUGS

SEE ALSO
    GoodType()


iffparse.library/GoodType

NAME
    GoodType -- Test if a type follows the IFF 85 specification.

SYNOPSIS
    isok = GoodType (type)
     d0               d0

    LONG isok, type;

FUNCTION
    Tests the given longword type identifier to see if it meets all the
    EA IFF 85 specifications for a FORM type (requirements for a FORM
    type are more stringent than those for a simple chunk ID).  If it
    complies, GoodType() returns non-zero, otherwise 0.

INPUTS
    type    - potential 32 bit format type identifier.

RESULT
    isok    - non-zero if this is a valid type id, 0 otherwise.

EXAMPLE

NOTES

BUGS

SEE ALSO
    GoodID()


iffparse.library/IDtoStr

NAME
    IDtoStr -- Convert a longword identifier to a null-terminated string.

SYNOPSIS
    str = IDtoStr (id, buf)
    d0             d0  a0

    STRPTR  str;
    LONG    id;
    STRPTR  buf;

FUNCTION
    Writes the ASCII equivalent of the given longword ID into buf as a
    null-terminated string.

INPUTS
    id      - longword ID.
    buf     - character buffer to accept string (at least 5 chars).

RESULT
    str     - the value of 'buf'.

EXAMPLE

NOTES

BUGS

SEE ALSO


iffparse.library/InitIFF

NAME
    InitIFF -- Initialize an IFFHandle struct as a user stream.

SYNOPSIS
    InitIFF (iff, flags, streamhook)
             a0    d0        a1

    struct IFFHandle *iff;
    LONG             flags;
    struct Hook     *streamhook;

FUNCTION
    Initializes an IFFHandle as a general user-defined stream by
    allowing the user to declare a hook that the library will call to
    accomplish the low-level reading, writing, and seeking of the stream.
    Flags are the stream I/O flags for the specified stream; typically a
    combination of the IFFF_?SEEK flags.

    The stream vector is called with the following arguments:

            A0:     pointer to streamhook.
            A2:     pointer to IFFHandle struct.
            A1:     pointer to IFFStreamCmd struct.

    The IFFStreamCmd packet appears as follows:

            sc_Command:     Contains an IFFCMD_#? value
            sc_Buf:         Pointer to memory buffer
            sc_NBytes:      Number of bytes involved in operation

    The values taken on by sc_Command, and their meaning, are as follows:

    IFFCMD_INIT:
            Prepare your stream for reading.  This is used for certain
            streams that can't be read immediately upon opening, and need
            further preparation.  (The clipboard.device is an example of
            such a stream.)  This operation is allowed to fail;  any
            error code will be returned directly to the client.  sc_Buf
            and sc_NBytes have no meaning here.
    IFFCMD_CLEANUP:
            Terminate the transaction with the associated stream.  This
            is used with streams that can't simply be closed.  (Again,
            the clipboard is an example of such a stream.)  This
            operation is not permitted to fail;  any error returned will
            be ignored (best to return 0, though).  sc_Buf and sc_NBytes
            have no meaning here.
    IFFCMD_READ:
            Read from the stream.  You are to read sc_NBytes from the
            stream and place them in the buffer pointed to by sc_Buf.
            Any (non-zero) error returned will be remapped by the parser
            into IFFERR_READ.
    IFFCMD_WRITE:
            Write to the stream.  You are to write sc_NBytes to the
            stream from the buffer pointed to by sc_Buf.  Any (non-zero)
            error returned will be remapped by the parser into
            IFFERR_WRITE.
    IFFCMD_SEEK:
            Seek on the stream.  You are to perform a seek on the stream
            relative to the current position.  sc_NBytes is signed;
            negative values mean seek backward, positive values mean seek
            forward.  sc_Buf has no meaning here.  Any (non-zero) error
            returned will be remapped by the parser into IFFERR_SEEK.

    All errors are returned in D0.  A return of 0 indicates success.
    UNDER NO CIRCUMSTANCES are you permitted to write to the IFFStreamCmd
    structure.

INPUTS
    iff     - pointer to IFFHandle structure to initialize.
    flags   - stream I/O flags for the IFFHandle.
    hook    - pointer to Hook structure.

RESULT

EXAMPLE

NOTES

BUGS

SEE ALSO
    utility/hooks.h


iffparse.library/InitIFFasClip

NAME
    InitIFFasClip -- Initialize an IFFHandle as a clipboard stream.

SYNOPSIS
    InitIFFasClip (iff)
                   a0

    struct IFFHandle *iff;

FUNCTION
    Initializes the given IFFHandle to be a clipboard stream.  The
    function initializes the stream processing vectors to operate on
    streams of the ClipboardHandle type.  The iff_Stream field will still
    need to be initialized to point to a ClipboardHandle as returned from
    OpenClipboard().

INPUTS
    iff     - pointer to IFFHandle struct.

RESULT

EXAMPLE

NOTES

BUGS

SEE ALSO
    OpenClipboard()


iffparse.library/InitIFFasDOS

NAME
    InitIFFasDOS -- Initialize an IFFHandle as a DOS stream.

SYNOPSIS
    InitIFFasDOS (iff)
                  a0

    struct IFFHandle *iff;

FUNCTION
    The function initializes the given IFFHandle to operate on DOS
    streams.  The iff_Stream field will need to be initialized as a BPTR
    returned from the DOS function Open().

INPUTS
    iff     - pointer to IFFHandle struct.

RESULT

EXAMPLE

NOTES

BUGS

SEE ALSO


iffparse.library/LocalItemData

NAME
    LocalItemData -- Get pointer to user data for local context item.

SYNOPSIS
    data = LocalItemData (lci)
     d0                   a0

    UBYTE                   *data;
    struct LocalContextItem   *lci;

FUNCTION
    Returns pointer to the user data associated with the given local
    context item.  The size of the data area depends on the "usize"
    argument used when allocating this item.  If the pointer to the item
    given (lci) is NULL, the function also returns NULL.

INPUTS
    lci     - pointer to local context item or NULL.

RESULT
    data    - pointer to user data area or NULL if lci is NULL.

EXAMPLE

NOTES

BUGS
    Currently, there is no way to determine the size of the user data
    area; you have to 'know'.

SEE ALSO
    AllocLocalItem(), FreeLocalItem()


iffparse.library/OpenClipboard

NAME
    OpenClipboard -- Create a handle on a clipboard unit.

SYNOPSIS
    ch = OpenClipboard (unit)
    d0                   d0

    struct ClipboardHandle   *ch;
    LONG                    unit;

FUNCTION
    Opens the clipboard.device and opens a stream for the specified unit
    (usually PRIMARY_CLIP).  This handle structure will be used as the
    clipboard stream for IFFHandles initialized as clipboard streams by
    InitIFFasClip().

INPUTS
    unit    - clipboard unit number (usually PRIMARY_CLIP).

RESULT
    ch      - pointer to ClipboardHandle structure or NULL if
              unsuccessful.

EXAMPLE

NOTES

BUGS

SEE ALSO
    InitIFFasClip(), CloseClipboard()


iffparse.library/OpenIFF

NAME
    OpenIFF -- Prepare an IFFHandle to read or write a new IFF stream.

SYNOPSIS
    error = OpenIFF (iff, rwmode)
     d0              a0     d0

    LONG             error;
    struct IFFHandle *iff;
    LONG             rwmode;

FUNCTION
    Initializes an IFFHandle struct for a new read or write.  The
    direction of the I/O is given by the value of rwmode, which can be
    either IFFF_READ or IFFF_WRITE.

    As part of its initialization procedure, OpenIFF() calls the client-
    supplied stream hook vector.  The IFFStreamCmd packet will contain
    the following:

            sc_Command:     IFFCMD_INIT
            sc_Buf:         (Not applicable)
            sc_NBytes:      (Not applicable)

    This operation is permitted to fail.  DO NOT write to this structure.

INPUTS
    iff     - pointer to IFFHandle struct.
    rwmode  - IFFF_READ or IFFF_WRITE

RESULT
    error   - contains an error code or 0 if successful.

EXAMPLE

NOTES

BUGS

SEE ALSO
    CloseIFF(), InitIFF()


iffparse.library/ParentChunk

NAME
    ParentChunk -- Get the nesting context node for the given chunk.

SYNOPSIS
    parent = ParentChunk (cn)
      d0                  a0

    struct ContextNode *parent, *cn;

FUNCTION
    Returns a context node for the chunk containing the chunk for the
    given context node.  This function effectively moves down the context
    stack into previously pushed contexts.  For example, to get a
    ContextNode pointer for the enclosing FORM chunk while reading a data
    chunk, use: ParentChunk (CurrentChunk (iff)) to find this pointer.
    The ContextNode structure contains information on the type of chunk
    and its size.

INPUTS
    cn      - pointer to a context node.

RESULT
    parent  - pointer to the enclosing context node or NULL if none.

EXAMPLE

NOTES

BUGS

SEE ALSO
    CurrentChunk()


iffparse.library/ParseIFF

NAME
    ParseIFF -- Parse an IFF file from an IFFHandle struct stream.

SYNOPSIS
    error = ParseIFF (iff, control)
     d0               a0     d0

    LONG             error;
    struct IFFHandle *iff;
    LONG             control;

FUNCTION
    This is the biggie.

    Traverses a file opened for read by pushing chunks onto the context
    stack and popping them off directed by the generic syntax of IFF
    files.  As it pushes each new chunk, it searches the context stack
    for handlers to apply to chunks of that type.  If it finds an entry
    handler it will invoke it just after entering the chunk.  If it finds
    an exit handler it will invoke it just before leaving the chunk.
    Standard handlers include entry handlers for pre-declared
    property chunks and collection chunks and entry and exit handlers for
    for stop chunks - that is, chunks which will cause the ParseIFF()
    function to return control to the client.  Client programs can also
    provide their own custom handlers.

    The control flag can have three values:

    IFFPARSE_SCAN:
            In this normal mode, ParseIFF() will only return control to
            the caller when either:
                    1) an error is encountered,
                    2) a stop chunk is encountered, or a user handler
                       returns the special IFF_RETURN2CLIENT code, or
                    3) the end of the logical file is reached, in which
                       case IFFERR_EOF is returned.

            ParseIFF() will continue pushing and popping chunks until one
            of these conditions occurs.  If ParseIFF() is called again
            after returning, it will continue to parse the file where it
            left off.

    IFFPARSE_STEP and _RAWSTEP:
            In these two modes, ParseIFF() will return control to the
            caller after every step in the parse, specifically, after
            each push of a context node and just before each pop.  If
            returning just before a pop, ParseIFF() will return
            IFFERR_EOC, which is not an error, per se, but is just an
            indication that the most recent context is ending.  In STEP
            mode, ParseIFF() will invoke the handlers for chunks, if
            any, before returning.  In RAWSTEP mode, ParseIFF() will not
            invoke any handlers and will return right away.  In both
            cases the function can be called multiple times to step
            through the parsing of the IFF file.

INPUTS
    iff     - pointer to IFFHandle struct.
    control - control code (IFFPARSE_SCAN, _STEP or _RAWSTEP).

RESULT
    error   - 0 or IFFERR_#? value or return value from user handler.

EXAMPLE

NOTES

BUGS

SEE ALSO
    PushChunk(), PopChunk(), EntryHandler(), ExitHandler(),
    PropChunk[s](), CollectionChunk[s](), StopChunk(), StopOnExit()


iffparse.library/PopChunk

NAME
    PopChunk -- Pop top context node off context stack.

SYNOPSIS
    error = PopChunk (iff)
     d0               a0

    LONG             error;
    struct IFFHandle *iff;

FUNCTION
    Pops top context chunk and frees all associated local context items.
    The function is normally called only for writing files and signals
    the end of a chunk.

INPUTS
    iff     - pointer to IFFHandle struct.

RESULT
    error   - 0 if successful or an IFFERR_#? error code if not
              successful.

EXAMPLE

NOTES

BUGS

SEE ALSO
    PushChunk()


iffparse.library/PropChunk

NAME
    PropChunk -- Specify a property chunk to store.

SYNOPSIS
    error = PropChunk (iff, type, id)
     d0                a0    d0   d1

    LONG             error;
    struct IFFHandle *iff;
    LONG             type;
    LONG             id;

FUNCTION
    Installs an entry handler for chunks with the given type and ID so
    that the contents of those chunks will be stored as they are
    encountered.  The storage of these chunks follows the property chunk
    scoping rules for IFF files so that at any given point, a stored
    property chunk returned by FindProp() will be the valid property for
    the current context.

INPUTS
    iff     - pointer to IFFHandle struct (does not need to be open).
    type    - type code for the chunk to declare (ex. "ILBM").
    id      - identifier for the chunk to declare (ex. "CMAP").

RESULT
    error   - 0 if successful or an IFFERR_#? error code if not
              successful.

EXAMPLE

NOTES

BUGS

SEE ALSO
    PropChunks(), FindProp(), CollectionChunk()


iffparse.library/PropChunks

NAME
    PropChunks -- Declare many property chunks at once.

SYNOPSIS
    error = PropChunks (iff, list, n)
     d0                 a0    a1  d0

    LONG             error;
    struct IFFHandle *iff;
    LONG             *list;
    LONG             n;

FUNCTION
    Declares multiple property chunks from a list.  The list argument is
    a pointer to an array of long words arranged in pairs, and has the
    following format:

            TYPE1, ID1, TYPE2, ID2, ..., TYPEn, IDn

    The argument n is the number of pairs.  PropChunks() just calls
    PropChunk() n times.

INPUTS
    iff     - pointer to IFFHandle struct.
    list    - pointer to array of longword chunk types and identifiers.
    n       - number of chunks to declare.

RESULT
    error   - 0 if successful or an IFFERR_#? error code if not
              successful.

EXAMPLE

NOTES

BUGS

SEE ALSO
    PropChunk()


iffparse.library/PushChunk

NAME
    PushChunk -- Push a new context node on the context stack.

SYNOPSIS
    error = PushChunk (iff, type, id, size)
     d0                a0    d0   d1   d2

    LONG             error;
    struct IFFHandle *iff;
    LONG             type, id, size;

FUNCTION
    Pushes a new context node on the context stack by reading it from the
    stream if this is a read file, or by creating it from the passed
    parameters if this is a write file.  Normally this function is only
    called in write mode, where the type and id codes specify the new
    chunk to create.  If this is a leaf chunk, i.e. a local chunk inside
    a FORM or PROP chunk, then the type argument is ignored.  If the size
    is specified then the chunk writing functions will enforce this size.
    If the size is given as IFFSIZE_UNKNOWN, the chunk will expand to
    accommodate whatever is written into it.

INPUTS
    iff     - pointer to IFFHandle struct.
    type    - chunk type specifier (ex. ILBM) (ignored for read mode or
              leaf chunks).
    id      - chunk id specifier (ex. CMAP) (ignored for read mode).
    size    - size of the chunk to create or IFFSIZE_UNKNOWN (ignored for
              read mode).

RESULT
    error   - 0 if successful or an IFFERR_#? error code if not
              successful.

EXAMPLE

NOTES

BUGS

SEE ALSO
    PopChunk(), WriteChunkRecords(), WriteChunkBytes()


iffparse.library/ReadChunkBytes

NAME
    ReadChunkBytes -- Read bytes from the current chunk into a buffer.

SYNOPSIS
    actual = ReadChunkBytes (iff, buf, size)
      d0                     a0   a1    d0

    LONG             actual;
    struct IFFHandle *iff;
    UBYTE            *buf;
    LONG             size;

FUNCTION
    Reads the IFFHandle stream into the buffer for the specified number
    of bytes.  Reads are limited to the size of the current chunk and
    attempts to read past the end of the chunk will truncate.  Function
    returns positive number of bytes read or a negative error code.

INPUTS
    iff     - pointer to IFFHandle struct.
    buf     - pointer to buffer area to receive data.
    size    - number of bytes to read.

RESULT
    actual  - (positive) number of bytes read if successful or a
              (negative) IFFERR_#? error code if not successful.

EXAMPLE

NOTES

BUGS

SEE ALSO
    ReadChunkRecords(), ParseIFF(), WriteChunkBytes()


iffparse.library/ReadChunkRecords

NAME
    ReadChunkRecords -- Read record elements from the current chunk into
                        a buffer.

SYNOPSIS
    actual = ReadChunkRecords (iff, buf, recsize, numrec)
      d0                       a0   a1     d0       d1

    LONG             actual;
    struct IFFHandle *iff;
    UBYTE            *buf;
    LONG             recsize, numrec;

FUNCTION
    Reads records from the current chunk into buffer.  Truncates attempts
    to read past end of chunk (only whole records are read; remaining
    bytes that are not of a whole record size are left unread and
    available for ReadChunkBytes()).

INPUTS
    iff     - pointer to IFFHandle struct.
    buf     - pointer to buffer area to receive data.
    recsize - size of data records to read.
    numrec  - number of data records to read.

RESULT
    actual  - (positive) number of whole records read if successful or a
              (negative) IFFERR_#? error code if not successful.

EXAMPLE

NOTES

BUGS

SEE ALSO
    ReadChunkBytes(), ParseIFF(), WriteChunkRecords()


iffparse.library/SetLocalItemPurge

NAME
    SetLocalItemPurge -- Set purge vector for a local context item.

SYNOPSIS
    SetLocalItemPurge (item, purgehook)
                        a0      a1

    struct LocalContextItem   *item;
    struct Hook            *purgehook;

FUNCTION
    Sets a local context item to use a client-supplied cleanup (purge)
    vector for disposal when its context is popped.  The purge vector
    will be called when the ContextNode containing this local item is
    popped off the context stack and is about to be deleted itself.  If
    the purge vector has not been set, the parser will use FreeLocalItem
    to delete the item, but if this function is used to set the purge
    vector, the supplied vector will be called with the following
    arguments:

            A0:     pointer to purgehook.
            A2:     pointer to LocalContextItem to be freed.
            A1:     pointer to a LONG containing the value
                    IFFCMD_PURGELCI.

    The user purge vector is then responsible for calling FreeLocalItem()
    as part of its own cleanup.  Although the purge vector can return a
    value, it will be ignored -- purge vectors must always work (best to
    return 0, though).

INPUTS
    item      - pointer to local context item.
    purgehook - pointer to a Hook structure.

RESULT

EXAMPLE

NOTES

BUGS

SEE ALSO
    AllocLocalItem(), FreeLocalItem(), utility/hooks.h


iffparse.library/StopChunk

NAME
    StopChunk -- Declare a chunk which should cause ParseIFF to return.

SYNOPSIS
    error = StopChunk (iff, type, id)
     d0                a0    d0   d1

    LONG             error;
    struct IFFHandle *iff;
    LONG             type;
    LONG             id;

FUNCTION
    Installs an entry handler for the specified chunk which will cause
    the ParseIFF() function to return control to the caller when this
    chunk is encountered.  This is only of value when ParseIFF() is
    called with the IFFPARSE_SCAN control code.

INPUTS
    iff     - pointer to IFFHandle struct (need not be open).
    type    - type code for chunk to declare (ex. "ILBM").
    id      - identifier for chunk to declare (ex. "BODY").

RESULT
    error   - 0 if successful or an IFFERR_#? error code if not
              successful.

EXAMPLE

NOTES

BUGS

SEE ALSO
    StopChunks(), ParseIFF()


iffparse.library/StopChunks

NAME
    StopChunks -- Declare many stop chunks at once.

SYNOPSIS
    error = StopChunks (iff, list, n)
     d0                 a0    a1  d0

    LONG             error;
    struct IFFHandle *iff;
    LONG             *list;
    LONG             n;

FUNCTION
    (is to StopChunk() as PropChunks() is to PropChunk().)

INPUTS
    iff     - pointer to IFFHandle struct.
    list    - pointer to array of longword chunk types and identifiers.
    n       - number of chunks to declare.

RESULT
    error   - 0 if successful or an IFFERR_#? error code if not
              successful.

EXAMPLE

NOTES

BUGS

SEE ALSO
    StopChunk()


iffparse.library/StopOnExit

NAME
    StopOnExit -- Declare a stop condition for exiting a chunk.

SYNOPSIS
    error = StopOnExit (iff, type, id)
     d0                 a0    d0   d1

    LONG             error;
    struct IFFHandle *iff;
    LONG             type;
    LONG             id;

FUNCTION
    Installs an exit handler for the specified chunk which will cause the
    ParseIFF() function to return control to the caller when this chunk
    is exhausted.  ParseIFF() will return IFFERR_EOC when the declared
    chunk is about to be popped.  This is only of value when ParseIFF()
    is called with the IFFPARSE_SCAN control code.

INPUTS
    iff     - pointer to IFFHandle struct (need not be open).
    type    - type code for chunk to declare (ex. "ILBM").
    id      - identifier for chunk to declare (ex. "BODY").

RESULT
    error   - 0 if successful or an IFFERR_#? error code if not
              successful.

EXAMPLE

NOTES

BUGS

SEE ALSO
    ParseIFF()


iffparse.library/StoreItemInContext

NAME
    StoreItemInContext -- Store local context item in given context node.

SYNOPSIS
    StoreItemInContext (iff, item, cn)
                        a0    a1   a2

    struct IFFHandle  *iff;
    struct LocalContextItem   *item;
    struct ContextNode        *cn;

FUNCTION
    Adds the LocalContextItem to the list of items for the given context
    node.  If an LCI with the same Type, ID, and Ident is already
    present in the ContextNode, it will be purged and replaced with the
    new one.  This is a raw form of StoreLocalItem.

INPUTS
    iff     - pointer to IFFHandle struct for this context.
    item    - pointer to a LocalContextItem to be stored.
    cn      - pointer to context node in which to store item.

RESULT

EXAMPLE

NOTES

BUGS

SEE ALSO
    StoreLocalItem()


iffparse.library/StoreLocalItem

NAME
    StoreLocalItem -- Insert a local context item into the context stack.

SYNOPSIS
    error = StoreLocalItem (iff, item, position)
     d0                     a0    a1      d0

    LONG                    error;
    struct IFFHandle  *iff;
    struct LocalContextItem   *item;
    LONG                    position;

FUNCTION
    Adds the local context item to the list of items for one of the
    context nodes on the context stack and purges any other item in the
    same context with the same ident, type and id.  The position argument
    determines where in the stack to add the item:

    IFFSLI_ROOT:
            Add item to list at root (default) stack position.
    IFFSLI_TOP:
            Add item to the top (current) context node.
    IFFSLI_PROP:
            Add element in top property context.  Top property context is
            either the top FORM chunk, or the top LIST chunk, whichever
            is closer to the top of the stack.

    Items added to the root context, or added to the top context before
    the IFFHandle has been opened or after it has been closed, are put in
    the default context.  That is, they will be the local items found
    only after all other context nodes have been searched.  Items in the
    default context are also immune to being purged until the IFFHandle
    struct itself is deleted with FreeIFF().  This means that handlers
    installed in the root context will still be there after an IFFHandle
    struct has been opened and closed.  (Note that this implies that
    items stored in a higher context will be deleted when that context
    ends.)

INPUTS
    iff     - pointer to IFFHandle struct.
    item    - pointer to LocalContextItem struct to insert.
    position- where to store the item (IFFSLI_ROOT, _TOP or _PROP).

RESULT
    error   - 0 if successful or an IFFERR_#? error code if not
              successful.

EXAMPLE

NOTES

BUGS

SEE ALSO
    FindLocalItem(), StoreItemInContext(), EntryHandler(), ExitHandler()


iffparse.library/WriteChunkBytes

NAME
    WriteChunkBytes -- Write data from a buffer into the current chunk.

SYNOPSIS
    error = WriteChunkBytes (iff, buf, size)
     d0                      a0   a1    d0

    LONG             error;
    struct IFFHandle *iff;
    UBYTE            *buf;
    LONG             size;

FUNCTION
    Writes "size" bytes from the specified buffer into the current chunk.
    If the current chunk was pushed with IFFSIZE_UNKNOWN, the size of the
    chunk gets increased by the size of the buffer written.  If the size
    was specified for this chunk, attempts to write past the end of the
    chunk will be truncated.

INPUTS
    iff     - pointer to IFFHandle struct.
    buf     - pointer to buffer area with bytes to be written.
    size    - number of bytes to write.

RESULT
    error   - (positive) number of bytes written if successful or a
              (negative) IFFERR_#? error code if not successful.

EXAMPLE

NOTES

BUGS

SEE ALSO
    PushChunk(), PopChunk(), WriteChunkRecords()


iffparse.library/WriteChunkRecords

NAME
    WriteChunkRecords -- Write records from a buffer to the current
                         chunk.

SYNOPSIS
    error = WriteChunkRecords (iff, buf, recsize, numrec)
     d0                        a0   a1     d0      d1

    LONG             error;
    struct IFFHandle *iff;
    UBYTE            *buf;
    LONG             recsize, numrec;

FUNCTION
    Writes record elements from the buffer into the top chunk.  This
    function operates much like ReadChunkBytes().

INPUTS
    iff     - pointer to IFFHandle struct.
    buf     - pointer to buffer area containing data.
    recsize - size of data records to write.
    numrec  - number of data records to write.

RESULT
    error   - (positive) number of whole records written if successful
              or a (negative) IFFERR_#? error code if not successful.

EXAMPLE

NOTES

BUGS

SEE ALSO
    WriteChunkBytes()


mathieeesingtrans.doc

 IEEESPAcos()      IEEESPExp()        IEEESPSin()         IEEESPTanh()
 IEEESPAsin()      IEEESPFieee()      IEEESPSincos()      IEEESPTieee()
 IEEESPAtan()      IEEESPLog()        IEEESPSinh()
 IEEESPCos()       IEEESPLog10()      IEEESPSqrt()
 IEEESPCosh()      IEEESPPow()        IEEESPTan()


mathieeesingtrans.library/IEEESPAcos

NAME
    IEEESPAcos -- compute the arc cosine of a number

SYNOPSIS
      x   = IEEESPAcos(  y  );
    d0                 d0

    float   x,y;

FUNCTION
    Compute arc cosine of y in IEEE single precision

INPUTS
    y - IEEE single precision floating point value

RESULT
    x - IEEE single precision floating point value

BUGS

SEE ALSO
    IEEESPCos(), IEEESPAtan(), IEEESPAsin()


mathieeesingtrans.library/IEEESPAsin

NAME
    IEEESPAsin -- compute the arcsine of a number

SYNOPSIS
      x   = IEEESPAsin(  y  );
    d0                 d0

    float   x,y;

FUNCTION
    Compute the arc sine of y in IEEE single precision

INPUTS
    y - IEEE single precision floating point value

RESULT
    x - IEEE single precision floating point value

BUGS

SEE ALSO
    IEEESPSin(), IEEESPAtan(), IEEESPAcos()


mathieeesingtrans.library/IEEESPAtan

NAME
    IEEESPAtan -- compute the arc tangent of number

SYNOPSIS
      x   = IEEESPAtan(  y  );
    d0                 d0

    single  x,y;

FUNCTION
    Compute arctangent of y in IEEE single precision

INPUTS
    y - IEEE single precision floating point value

RESULT
    x - IEEE single precision floating point value

BUGS

SEE ALSO


mathieeesingtrans.library/IEEESPCos

NAME
    IEEESPCos -- compute the cosine of a floating point number

SYNOPSIS
      x   = IEEESPCos(  y  );
    d0                 d0

    float   x,y;

FUNCTION
    Compute cosine of y in IEEE single precision

INPUTS
    y - IEEE single precision floating point value

RESULT
    x - IEEE single precision floating point value

BUGS

SEE ALSO
    IEEESPAcos(), IEEESPSin(), IEEESPTan()


mathieeesingtrans.library/IEEESPCosh

NAME
    IEEESPCosh -- compute the hyperbolic cosine of a floating point number

SYNOPSIS
      x   = IEEESPCosh(  y  );
    d0                 d0

    float   x,y;

FUNCTION
    Compute hyperbolic cosine of y in IEEE single precision

INPUTS
    y - IEEE single precision floating point value

RESULT
    x - IEEE single precision floating point value

BUGS

SEE ALSO
    IEEESPSinh(), IEEESPTanh()


mathieeesingtrans.library/IEEESPExp

NAME
    IEEESPExp -- compute the exponential of e

SYNOPSIS
      x   = IEEESPExp(  y  );
    d0                d0

    float   x,y;

FUNCTION
    Compute e^y in IEEE single precision

INPUTS
    y - IEEE single precision floating point value

RESULT
    x - IEEE single precision floating point value

BUGS

SEE ALSO
    IEEESPLog()


mathieeesingtrans.library/IEEESPFieee

NAME
    IEEESPFieee -- convert IEEE single to IEEE single

SYNOPSIS
      x   = IEEESPFieee(  y  );
    d0                    d0

    float   y;
    float  x;

FUNCTION
    Convert IEEE single precision number to IEEE single precision.
    These are included for completeness although they just
    return the input parameter. A good way to remember how these
    functions work is: They convert to and from the local format
    to Single Precision IEEE. The local format for this library
    happens to also be Single Precision IEEE.

INPUTS
    y - IEEE single precision floating point value

RESULT
    x - IEEE single precision floating point value

BUGS

SEE ALSO
    IEEESPTieee()


mathieeesingtrans.library/IEEESPLog

NAME
    IEEESPLog -- compute the natural logarithm of a floating point number

SYNOPSIS
      x   = IEEESPLog(  y  );
    d0                d0

    float   x,y;

FUNCTION
    Compute ln(y) in IEEE single precision

INPUTS
    y - IEEE single precision floating point value

RESULT
    x - IEEE single precision floating point value

BUGS

SEE ALSO
    IEEESPExp()


mathieeesingtrans.library/IEEESPLog10

NAME
    IEEESPLog10 -- compute logarithm base 10 of a number

SYNOPSIS
      x   = IEEESPLog10(  y  );
    d0                  d0

    float   x,y;

FUNCTION
    Compute the logarithm base 10 of y in IEEE single precision

INPUTS
    y - IEEE single precision floating point value

RESULT
    x - IEEE single precision floating point value

BUGS

SEE ALSO
    IEEESPLog()


mathieeesingtrans.library/IEEESPPow

NAME
    IEEESPPow -- raise a number to another number power

SYNOPSIS
      z   = IEEESPPow(  x  ,  y  );
    d0                d1 d0

    float   x,y,z;

FUNCTION
    Compute y^x in IEEE single precision

INPUTS
    x - IEEE single precision floating point value
    y - IEEE single precision floating point value

RESULT
    z - IEEE single precision floating point value

BUGS

SEE ALSO


mathieeesingtrans.library/IEEESPSin

NAME
    IEEESPSin -- compute the sine of a floating point number

SYNOPSIS
      x   = IEEESPSin(  y  );
    d0                d0

    float   x,y;

FUNCTION
    Compute sine of y in IEEE single precision

INPUTS
    y - IEEE single precision floating point value

RESULT
    x - IEEE single precision floating point value

BUGS

SEE ALSO
    IEEESPAsin(), IEEESPTan(), IEEESPCos()


mathieeesingtrans.library/IEEESPSincos

NAME
    IEEESPSincos -- compute the arc tangent of a floating point number

SYNOPSIS
      x   = IEEESPSincos( z ,  y  );
    d0                   a0  d0

    float   x,y,*z;

FUNCTION
    Compute sin and cosine of y in IEEE single precision.
    Store the cosine in *z. Return the sine of y.

INPUTS
    y - IEEE single precision floating point value
    z - pointer to IEEE single precision floating point number

RESULT
    x - IEEE single precision floating point value

BUGS

SEE ALSO
    IEEESPSin(), IEEESPCos()


mathieeesingtrans.library/IEEESPSinh

NAME
    IEEESPSinh -- compute the hyperbolic sine of a floating point number

SYNOPSIS
      x   = IEEESPSinh(  y  );
    d0                 d0

    float   x,y;

FUNCTION
    Compute hyperbolic sine of y in IEEE single precision

INPUTS
    y - IEEE single precision floating point value

RESULT
    x - IEEE single precision floating point value

BUGS

SEE ALSO
    IEEESPCosh, IEEESPTanh


mathieeesingtrans.library/IEEESPSqrt

NAME
    IEEESPSqrt -- compute the square root of a number

SYNOPSIS
      x   = IEEESPSqrt(  y  );
     d0                  d0

    float   x,y;

FUNCTION
    Compute square root of y in IEEE single precision

INPUTS
    y - IEEE single precision floating point value

RESULT
    x - IEEE single precision floating point value

BUGS

SEE ALSO


mathieeesingtrans.library/IEEESPTan

NAME
    IEEESPTan -- compute the tangent of a floating point number

SYNOPSIS
      x   = IEEESPTan(  y  );
    d0                d0

    float   x,y;

FUNCTION
    Compute tangent of y in IEEE single precision

INPUTS
    y - IEEE single precision floating point value

RESULT
    x - IEEE single precision floating point value

BUGS

SEE ALSO
    IEEESPAtan(), IEEESPSin(), IEEESPCos()


mathieeesingtrans.library/IEEESPTanh

NAME
    IEEESPTanh -- compute the hyperbolic tangent of a floating point number

SYNOPSIS
      x   = IEEESPTanh(  y  );
    d0                 d0

    float   x,y;

FUNCTION
    Compute hyperbolic tangent of y in IEEE single precision

INPUTS
    y - IEEE single precision floating point value

RESULT
    x - IEEE single precision floating point value

BUGS

SEE ALSO
    IEEESPSinh(), IEEESPCosh()


mathieeesingtrans.library/IEEESPTieee

NAME
    IEEESPTieee -- convert IEEE single to IEEE single

SYNOPSIS
      x   = IEEESPTieee(  y  );
     d0                 d0

    float   y;
    float   x;

FUNCTION
    Convert IEEE single precision number to IEEE single precision.
    These are included for completeness although they just
    return the input parameter. A good way to remember how these
    functions work is: They convert to and from the local format
    to Single Precision IEEE. The local format for this library
    happens to also be Single Precision IEEE.

INPUTS
    y - IEEE single precision floating point value

RESULT
    x - IEEE single precision floating point value

BUGS

SEE ALSO
    IEEESPFieee()


diskfont.doc

 AvailFonts()               NewFontContents()        OpenDiskFont()
 DisposeFontContents()      NewScaledDiskFont()


diskfont.library/AvailFonts

NAME
     AvailFonts -- Inquire available memory & disk fonts.

SYNOPSIS
     error = AvailFonts(buffer, bufBytes, flags);
                        A0      D0        D1

     LONG AvailFonts( struct AvailFontsHeader *buffer, LONG bufBytes,
             ULONG flags );

FUNCTION
     AvailFonts fills a user supplied buffer with the structure,
     described below, that contains information about all the
     fonts available in memory and/or on disk.  Those fonts
     available on disk need to be loaded into memory and opened
     via OpenDiskFont, those already in memory are accessed via
     OpenFont.  The TextAttr structure required by the open calls
     is part of the information AvailFonts supplies.

     When AvailFonts fails, it returns the number of extra bytes
     it needed to complete the command.  Add this number to your
     current buffer size, allocate a new buffer, and try again.

INPUTS
     buffer - memory to be filled with struct AvailFontsHeader
             followed by an array of AvailFonts elements, which
             contains entries for the available fonts and their
             names.

     bufBytes - the number of bytes in the buffer
     flags - AFF_MEMORY is set to search memory for fonts to fill
             the structure, AFF_DISK is set to search the disk for
             fonts to fill the structure.  AFF_SCALED is set to
             not filter out memory fonts that are not designed.
             Any combination may be specified.  AFF_TAGGED is set
             to fill the buffer with TAvailFonts elements instead
             of AvailFonts elements.

RESULTS
     buffer - filled with struct AvailFontsHeader followed by the
             [T]AvailFonts elements, There will be duplicate entries
             for fonts found both in memory and on disk, differing
             only by type.  The existence of a disk font in the
             buffer indicates that it exists as an entry in a font
             contents file -- the underlying font file has not been
             checked for validity, thus an OpenDiskFont of it may
             fail.
     error - if non-zero, this indicates the number of bytes needed
             for AvailFonts in addition to those supplied.  Thus
             structure elements were not returned because of
             insufficient bufBytes.

EXAMPLE
     int afShortage, afSize;
     struct AvailFontsHeader *afh;

     ...

     afSize = 400;
     do {
         afh = (struct AvailFontsHeader *) AllocMem(afSize, 0);
         if (afh) {
             afShortage = AvailFonts(afh, afSize, AFF_MEMORY|AFF_DISK);
             if (afShortage) {
                 FreeMem(afh, afSize);
                 afSize += afShortage;
             }
         }
         else {
             fail("AllocMem of AvailFonts buffer afh failedn");
             break;
         }
     }
         while (afShortage);

     /*
      * if (afh) non-zero here, then:
      * 1. it points to a valid AvailFontsHeader
      * 2. it must have FreeMem(afh, afSize) called for it after use
      */


diskfont.library/DisposeFontContents

NAME
     DisposeFontContents -- Free the result from NewFontContents. (V34)

SYNOPSIS
     DisposeFontContents(fontContentsHeader)
                         A1

     VOID DisposeFontContents( struct FontContentsHeader * );

FUNCTION
     This function frees the array of FontContents entries
     returned by NewFontContents.

INPUTS
     fontContentsHeader - a struct FontContentsHeader pointer
         returned by NewFontContents.

EXCEPTIONS
     This command was first made available as of version 34.

     A fontContentsHeader other than one acquired by a call
     NewFontContents will crash.

SEE ALSO
     NewFontContents to get structure freed here.


diskfont.library/NewFontContents

NAME
     NewFontContents -- Create a FontContents image for a font. (V34)

SYNOPSIS
     fontContentsHeader = NewFontContents(fontsLock,fontName)
    D0                                   A0        A1

     struct FontContentsHeader *NewFontContents( BPTR, char * );

FUNCTION
     This function creates a new array of FontContents entries
     that describe all the fonts associated with the fontName,
     specifically, all those in the font directory whose name
     is that of the font sans the ".font" suffix.

INPUTS
     fontsLock - a DOS lock on the FONTS: directory (or other
         directory where the font contents file and associated
         font directory resides).
     fontName - the font name, with the ".font" suffix, which
         is also the name of the font contents file.

RESULT
     fontContentsHeader - a struct FontContentsHeader pointer.

EXCEPTIONS
     This command was first made available as of version 34.

     D0 is zero if the fontName is does not have a ".font" suffix,
     if the fontName is too long, if a DOS error occurred, or if
     memory could not be allocated for the fontContentsHeader.

SEE ALSO
     DisposeFontContents to free the structure acquired here.


diskfont.library/NewScaledDiskFont

NAME
     NewScaledDiskFont -- Create a DiskFont scaled from another. (V36)

SYNOPSIS
     header = NewScaledDiskFont(srcFont, destTextAttr)
     D0                         A0       A1

     struct DiskFontHeader *NewScaledDiskFont( struct TextFont *,
             struct TTextAttr * );

INPUTS
     srcFont - the font from which the scaled font is to be
         constructed.
     destTextAttr - the desired attributes for the new scaled
         font.  This may be a structure of type TextAttr or
         TTextAttr.

RESULT
     header - a pointer to a DiskFontHeader structure.  This is not
             being managed by the diskfont.library, however.

NOTES
     o   This function may use the blitter.
     o   Fonts containing characters that render wholly outside
         the character advance cell are currently not scalable.
     o   The font, and memory allocated for the scaled font can
         can be freed by calling StripFont() on the font,
         and then calling UnLoadSeg() on the segment created
         by this function.

         Both the TextFont structure, and segment pointer are contained
         within the DiskFontHeader struct.  The DiskFontHeader structure
         will also be freed as part of the UnLoadSeg() call.
         StripFont() is a new graphics.library call as of V36.


diskfont.library/OpenDiskFont

NAME
    OpenDiskFont - load and get a pointer to a disk font.

SYNOPSIS
    font = OpenDiskFont(textAttr)
    D0                  A0

FUNCTION
    This function finds the font with the specified textAttr on
    disk, loads it into memory, and returns a pointer to the font
    that can be used in subsequent SetFont and CloseFont calls.
    It is important to match this call with a corresponding
    CloseFont call for effective management of font memory.

    If the font is already in memory, the copy in memory is used.
    The disk copy is not reloaded.

INPUTS
    textAttr - a TextAttr structure that describes the text font
            attributes desired.

RESULTS
    D0 is zero if the desired font cannot be found.

NOTES
    As of V36, OpenDiskFont() will automatically attempt to
    construct a font for you if:

            You have requested a font size which does not exist
            as a designed font, and

            You have not set the DESIGNED bit in the ta_Flags
            field of the TextAttr, or TTextAttr struct.

    Constructed fonts are created by scaling a designed font.
    A designed font is one which typically resides on disk,
    or in ROM (e.g., a font which has been designed by hand
    using a drawing tool).  Designed fonts generally look better
    than fonts constructed by the font scaler, but designed
    fonts also require disk space for each font size.

    Always set the DESIGNED bit if you do not want constructed fonts,
    or use AvailFonts() to find out which font sizes already exist.

BUGS
    This routine will not work well with font names whose file
    name components are longer than the maximum allowed
    (30 characters).


intuition.doc

 ActivateGadget()            NextObject()
 ActivateWindow()            NextPubScreen()
 AddClass()                  ObtainGIRPort()
 AddGadget()                 OffGadget()
 AddGList()                  OffMenu()
 AllocRemember()             OnGadget()
 AutoRequest()               OnMenu()
 BeginRefresh()              OpenScreen()
 BuildEasyRequestArgs()      OpenScreenTagList()
 BuildSysRequest()           OpenWindow()
 ChangeWindowBox()           OpenWindowTagList()
 ClearDMRequest()            OpenWorkBench()
 ClearMenuStrip()            PointInImage()
 ClearPointer()              PrintIText()
 CloseScreen()               PubScreenStatus()
 CloseWindow()               QueryOverscan()
 CloseWorkBench()            RefreshGadgets()
 CurrentTime()               RefreshGList()
 DisplayAlert()              RefreshWindowFrame()
 DisplayBeep()               ReleaseGIRPort()
 DisposeObject()             RemakeDisplay()
 DoubleClick()               RemoveClass()
 DrawBorder()                RemoveGadget()
 DrawImage()                 RemoveGList()
 DrawImageState()            ReportMouse()
 EasyRequestArgs()           Request()
 EndRefresh()                ResetMenuStrip()
 EndRequest()                RethinkDisplay()
 EraseImage()                ScreenToBack()
 FreeClass()                 ScreenToFront()
 FreeRemember()              SetAttrsA()
 FreeScreenDrawInfo()        SetDefaultPubScreen()
 FreeSysRequest()            SetDMRequest()
 GadgetMouse()               SetEditHook()
 GetAttr()                   SetGadgetAttrsA()
 GetDefaultPubScreen()       SetMenuStrip()
 GetDefPrefs()               SetMouseQueue()
 GetPrefs()                  SetPointer()
 GetScreenData()             SetPrefs()
 GetScreenDrawInfo()         SetPubScreenModes()
 InitRequester()             SetWindowTitles()
 IntuiTextLength()           ShowTitle()
 ItemAddress()               SizeWindow()
 LockIBase()                 SysReqHandler()
 LockPubScreen()             UnlockIBase()
 LockPubScreenList()         UnlockPubScreen()
 MakeClass()                 UnlockPubScreenList()
 MakeScreen()                ViewAddress()
 ModifyIDCMP()               ViewPortAddress()
 ModifyProp()                WBenchToBack()
 MoveScreen()                WBenchToFront()
 MoveWindow()                WindowLimits()
 MoveWindowInFrontOf()       WindowToBack()
 NewModifyProp()             WindowToFront()
 NewObject()                 ZipWindow()


intuition.library/ActivateGadget

NAME
    ActivateGadget -- Activate a (string or custom) gadget.

SYNOPSIS
    Success = ActivateGadget( Gadget, Window, Request )
    D0                        A0      A1      A2

    BOOL ActivateGadget( struct Gadget *, struct Window *,
            struct Requester * );

FUNCTION
    Activates a string or custom gadget.  If successful, this means
    that the user does not need to click in the gadget before typing.

    The window parameter must point to the window which contains the
    gadget.  If the gadget is actually in a requester, the window must
    contain the requester, and a pointer to the requester must also be
    passed. The requester parameter must only be valid if the gadget
    has the GTYP_REQGADGET flag set, a requirement for all requester
    gadgets.

    The success of this function depends on a rather complex set
    of conditions.  The intent is that the user is never interrupted from
    what interactions he may have underway.

    The current set of conditions includes:
    -   The window must be active.  If you are opening a new window
        and want an active gadget in it, it is not sufficient to
        assume that the WFLG_ACTIVATE flag has taken effect by the time
        OpenWindow() returns, even if you insert a delay of some
        finite amount of time.  Use the IDCMP_ACTIVEWINDOW IntuiMessage
        to tell when your window really becomes active.  Many
        programs use an event loop that calls ActivateGadget()
        whenever they receive the IDCMP_ACTIVEWINDOW message, and also
        the IDCMP_MOUSEBUTTONS messages, and so on, to keep the
        gadget active until it is used (or the user selects some
        other "Cancel" gadget).

    -   No other gadgets may be in use.  This includes system gadgets,
        such as those for window sizing, dragging, etc.
    -   If the gadget is in a requester, that requester must
        be active. (Use IDCMP_REQSET and IDCMP_REQCLEAR).
    -   The right mouse button cannot be held down (e.g. menus)

    NOTE: Don't try to activate a gadget which is disabled or
    not attached to a window or requester.

INPUTS
    Gadget = pointer to the gadget that you want activated.
    Window = pointer to a window structure containing the gadget.
    Requester = pointer to a requester (may by NULL if this isn't
       a requester gadget (i.e. GTYP_REQGADGET is not set)).

RESULT
    If the conditions above are met, and the gadget is in fact a string
    gadget, then this function will return TRUE, else FALSE.

BUGS
    At present, this function will not return FALSE if a custom
    gadget declines to be activated.

SEE ALSO


intuition.library/ActivateWindow

NAME
    ActivateWindow -- Activate an Intuition window.

SYNOPSIS
    [success =] ActivateWindow( Window )
    [D0]                        A0

    [LONG] ActivateWindow( struct Window * );
    /* returns LONG in V36 and higher */

FUNCTION
    Activates an Intuition window.

    Note that this call may have its action deferred: you cannot assume
    that when this call is made the selected window has become active.
    This action will be postponed while the user plays with gadgets and
    menus, or sizes and drags windows.  You may detect when the window
    actually has become active by the IDCMP_ACTIVEWINDOW IDCMP message.

    This call is intended to provide flexibility but not to confuse the
    user.  Please call this function synchronously with some action
    by the user.

INPUTS
    Window = a pointer to a Window structure

RESULT
    V35 and before: None.
    V36 and later: returns zero if no problem queuing up
        the request for deferred action

BUGS
    Calling this function in a tight loop can blow out Intuition's deferred
    action queue.

SEE ALSO
    OpenWindow(), and the WFLG_ACTIVATE window flag


intuition.library/AddClass

NAME
    AddClass -- Make a public class available (V36)

SYNOPSIS
    AddClass( Class )
              A0

    VOID AddClass( struct IClass * );

FUNCTION
    Adds a public boopsi class to the internal list of classes available
    for public consumption.

    You must call this function after you call MakeClass().

INPUTS
    Class = pointer returned by MakeClass()

RESULT
    Nothing returned.

NOTES

BUGS
    Although there is some protection against creating classes
    with the same name as an existing class, this function
    does not do any checking or other dealings with like-named
    classes.  Until this is rectified, only officially registered
    names can be used for public classes, and there is no
    "class replacement" policy in effect.

SEE ALSO
    MakeClass(), FreeClass(), RemoveClass()
    Document "Basic Object-Oriented Programming System for Intuition"
    and the "boopsi Class Reference" document.


intuition.library/AddGadget

NAME
    AddGadget -- Add a gadget to the gadget list of a window.

SYNOPSIS
    RealPosition = AddGadget( Window, Gadget, Position )
    D0                        A0      A1      D0

    UWORD  AddGadget( struct Window *, struct Gadget *, UWORD );

FUNCTION
    Adds the specified gadget to the gadget list of the given window,
    linked in at the position in the list specified by the position
    argument (that is, if Position == 0, the gadget will be inserted
    at the head of the list, and if Position == 1 then the gadget will
    be inserted after the first gadget and before the second).  If the
    position you specify is greater than the number of gadgets in the
    list, your gadget will be added to the end of the list.

    Calling AddGadget() does not cause your gadget to be redisplayed.
    The benefit of this is that you may add several gadgets without
    having the gadget list redrawn every time.

    This procedure returns the position at which your gadget was added.

    NOTE:  A relatively safe way to add the gadget to the end of the
    list is to specify a position of -1 (i.e., (UWORD) ~0).  That way,
    only the 65536th (and multiples of it) will be inserted at the wrong
    position.  The return value of the procedure will tell you where it
    was actually inserted.

    NOTE:  The system window gadgets are initially added to the
    front of the gadget list.  The reason for this is:  If you position
    your own gadgets in some way that interferes with the graphical
    representation of the system gadgets, the system's ones will be "hit"
    first by user.  If you then start adding gadgets to the front of the
    list, you will disturb this plan, so beware.  On the other hand, if
    you don't violate the design rule of never overlapping your gadgets,
    there's no problem.

    NOTE:  You may not add your own gadgets to a screen.  Gadgets may
    be added to backdrop windows, however, which can be visually similar,
    but also provide an IDCMP channel for gadget input messages.

INPUTS
    Window = pointer to the window to get your gadget
    Gadget = pointer to the new gadget
    Position = integer position in the list for the new gadget (starting
        from zero as the first position in the list)

RESULT
    Returns the position of where the gadget was actually added.

BUGS

SEE ALSO
    AddGList(), RemoveGadget(), RemoveGList()


intuition.library/AddGList

NAME
    AddGList -- Add a linked list of gadgets to a window or requester.

SYNOPSIS
    RealPosition = AddGList( Window, Gadget, Position, Numgad, Requester )
    D0                       A0      A1      D0        D1      A2

    UWORD AddGList( struct Window *, struct Gadget *, UWORD, WORD,
            struct Requester * );

FUNCTION
    Adds the list of gadgets to the gadget list of the given window
    or requester linked in at the position in the list specified by
    the position argument.

    See AddGadget() for more information about gadget list position,
    and more information about gadgets in general.

    The requester parameter will be ignored unless the GTYP_REQGADGET
    bit is set in the GadgetType field of the first gadget in the list.
    In that case, the gadget list is added to the requester gadgets.
    NOTE: be sure that GTYP_REQGADGET is either set or cleared consistently
    for all gadgets in the list.  NOTE ALSO: The window parameter
    should point to the window that the requester (will) appear in.

    Will add 'Numgad' gadgets from gadget list linked by the field
    NextGadget, or until some NextGadget field is found to be NULL.  Does
    not assume that the Numgad'th gadget has NextGadget equal to NULL.

    NOTE WELL: In order to link your gadget list in, the NextGadget
    field of the Numgad'th (or last) gadget will be modified.  Thus, if
    you are adding the first 3 gadgets from a linked list of five gadgets,
    this call will sever the connection between your third and fourth
    gadgets.

INPUTS
    Window = pointer to the window to get your gadget
    Gadget = pointer to the first gadget to be added
    Position = integer position in the list for the new gadget
        (starting from zero as the first position in the list)
    Numgad = the number of gadgets from the linked list to be added
        if Numgad equals -1, the entire null-terminated list of
        gadgets will be added.
    Requester = the requester the gadgets will be added to if the
        GTYP_REQGADGET GadgetType flag is set for the first gadget
        in the list

RESULT
    Returns the position of where the first gadget in the list was actually
    added.

BUGS

SEE ALSO
    AddGadget(), RemoveGadget(), RemoveGList()


intuition.library/AllocRemember

NAME
    AllocRemember -- AllocMem() with tracking to make freeing easy.

SYNOPSIS
    MemBlock = AllocRemember( RememberKey, Size, Flags )
    D0                        A0           D0    D1

    APTR AllocRemember( struct Remember **, ULONG, ULONG );

FUNCTION
    This routine calls the Exec AllocMem() function for you, but also links
    the parameters of the allocation into a master list, so that
    you can simply call the Intuition routine FreeRemember() at a later
    time to deallocate all allocated memory without being required to
    remember the details of the memory you've allocated.

    This routine will have two primary uses:
   -   Let's say that you're doing a long series of allocations in a
       procedure.  If any one of the allocations fails, your program
        may need to abort the procedure.  Abandoning ship correctly
        involves freeing up what memory you've already allocated.  This
        procedure allows you to free up that memory easily, without being
        required to keep track of how many allocations you've already done,
        what the sizes of the allocations were, or where the memory was
        allocated.

   -   Also, in the more general case, you may do all of the allocations
       in your entire program using this routine.  Then, when your
       program is exiting, you can free it all up at once with a
       simple call to FreeRemember().

    You create the "anchor" for the allocation master list by creating
    a variable that's a pointer to struct Remember, and initializing
    that pointer to NULL.  This is called the RememberKey.  Whenever
    you call AllocRemember(), the routine actually does two memory
    allocations, one for the memory you want and the other for a copy
    of a Remember structure.  The Remember structure is filled in
    with data describing your memory allocation, and it's linked
    into the master list pointed to by your RememberKey.  Then, to
    free up any memory that's been allocated, all you have to do is
    call FreeRemember() with your RememberKey.

    Please read the FreeRemember() function description, too.  As you will
    see, you can select either to free just the link nodes and keep all the
    allocated memory for yourself, or to free both the nodes and your
    memory buffers.

INPUTS
    RememberKey = the address of a pointer to struct Remember.  Before the
    very first call to AllocRemember, initialize this pointer to NULL.

    Size = the size in bytes of the memory allocation.  Please refer to the
        exec.library/AllocMem() function for details.
    Flags = the specifications for the memory allocation.  Please refer to
        the exec.library/AllocMem() function for details.

EXAMPLE
    struct Remember *RememberKey;
    RememberKey = NULL;
    buffer = AllocRemember(&RememberKey, BUFSIZE, MEMF_CHIP);
    if (buffer)
    {
        /* Use the buffer */
        ...
    }
    FreeRemember(&RememberKey, TRUE);

RESULT
    If the memory allocation is successful, this routine returns the byte
    address of your requested memory block.  Also, the node to your block
    will be linked into the list pointed to by your RememberKey variable.
    If the allocation fails, this routine returns NULL and the list pointed
    to by RememberKey, if any, will be unchanged.

BUGS
    This function makes two allocations for each memory buffer
    you request.  This is neither fast nor good for memory
    fragmentation.

    This function should use the exec AllocPool() function internally,
    at least for the Remember headers.

SEE ALSO
    FreeRemember(), exec.library/AllocMem()


intuition.library/AutoRequest

NAME
    AutoRequest -- Automatically build and get response from a requester.

SYNOPSIS
    Response = AutoRequest( Window, BodyText, PosText, NegText,
    D0                      A0      A1        A2       A3
                    PosFlags, NegFlags, Width, Height )
                    D0        D1        D2     D3

    BOOL AutoRequest( struct Window *, struct IntuiText *,
            struct IntuiText *, struct IntuiText *,
            ULONG, ULONG, WORD, WORD );

FUNCTION
    This procedure automatically builds a requester for you and then
    waits for a response from the user, or for the system to satisfy your
    request.  If the response is positive, this procedure returns TRUE.
    If the response is negative, this procedure returns FALSE.

    An IDCMPFlag specification is created by bitwise "or'ing" your
    PosFlags, NegFlags, and the IDCMP classes IDCMP_GADGETUP and
    IDCMP_RAWKEY.  You may specify zero flags for either the PosFlags
    or NegFlags arguments.

    The IntuiText arguments, and the width and height values, are
    passed directly to the BuildSysRequest() procedure along with
    your window pointer and the IDCMP flags.  Please refer to
    BuildSysRequest() for a description of the IntuiText that you are
    expected to supply when calling this routine.  It's an important
    but long-winded description that need not be duplicated here.

    If the BuildSysRequest() procedure does not return a pointer
    to a window, it will return TRUE or FALSE (not valid structure
    pointers) instead, and these BOOL values will be returned to
    you immediately.

    On the other hand, if a valid window pointer is returned, that
    window will have had its IDCMP ports and flags initialized according
    to your specifications.  AutoRequest() then waits for IDCMP messages
    on the UserPort, which satisfies one of four requirements:
    -   either the message is of a class that matches
        one of your PosFlags arguments (if you've supplied
        any), in which case this routine returns TRUE.  Or
    -   the message class matches one of your NegFlags
        arguments (if you've supplied any), in which case
        this routine returns FALSE.  Or
    -   the IDCMP message is of class IDCMP_GADGETUP, which means that
        one of the two gadgets, as provided with the PosText and NegText
        arguments, was selected by the user.  If the TRUE gadget
        was selected, TRUE is returned.  If the FALSE gadget was
        selected, FALSE is returned.
    -   Lastly, two IDCMP_RAWKEY messages may satisfy the request: those
        for the V and B keys with the left Amiga key depressed.
        These keys, satisfy the gadgets on the left or right side of
        the requester--TRUE or FALSE--, respectively.

        NOTE: For V36, these two keys left-Amiga-B and V are processed
        through the default keymap.

    When the dust has settled, this routine calls FreeSysRequest() if
    necessary to clean up the requester and any other allocated memory.

    NOTE: For V36, this function now switches the processor stack
    to ensure sufficient stack space for the function to succeed.

INPUTS
    Window = pointer to a Window structure.  See BuildSysRequest()
        for a full discussion.
    BodyText = pointer to an IntuiText structure
    PosText = pointer to an IntuiText structure, may by NULL.
    NegText = pointer to an IntuiText structure, MUST be valid!
    PosFlags = flags for the IDCMP
    NegFlags = flags for the IDCMP
    Width, Height = the sizes to be used for the rendering of the requester

    NOTE for V36: The width and height parameters are ignored, as
    are several other specifications in the IntuiText, to make
    AutoRequest() requesters retroactively conform to the new look
    designed for EasyRequest().

RESULT
    The return value is either TRUE or FALSE.  See the text above for a
    complete description of the chain of events that might lead to either
    of these values being returned.

NOTES
    When DOS brings up AutoRequests() on your process (eg.
    "Please insert volume XXX in any drive", they normally come
    up on the Workbench screen.  If you set your Process pr_WindowPtr
    field to point to one of your windows, then DOS will bring its
    requesters up on the same screen as that window.  A pr_WindowPtr
    of -1 prevents requesters from coming up at all.
    (Some FileSystem requesters cannot be redirected or supressed).

BUGS
    The requester no longer devolves into a call to DisplayAlert()
    if there is not enough memory for the requester.

SEE ALSO
    EasyRequest(), BuildSysRequest(), SysReqHandler()


intuition.library/BeginRefresh

NAME
    BeginRefresh -- Sets up a window for optimized refreshing.

SYNOPSIS
    BeginRefresh( Window )
                  A0

    VOID BeginRefresh( struct Window * );

FUNCTION
    This routine sets up your window for optimized refreshing.

    Its role is to provide Intuition integrated access to the Layers
    library function BeginUpdate().  Its additional contribution is
    to be sure that locking protocols for layers are followed, by
    locking both layers of a WFLG_GIMMEZEROZERO window only after the
    parent Layer_Info has been locked.  Also, the WFLG_WINDOWREFRESH
    flag is set in your window, for your information.

    The purpose of BeginUpdate(), and hence BeginRefresh(), is to
    restrict rendering in a window (layer) to the region that needs
    refreshing after an operation such as window sizing or uncovering.
    This restriction to the "damage region" persists until you call
    EndRefresh().

    For instance, if you have a WFLG_SIMPLE_REFRESH window which is
    partially concealed and the user brings it to the front, you can
    receive an IDCMP_REFRESHWINDOW message asking you to refresh your
    display.  If you call BeginRefresh() before doing any of the
    rendering, then the layer that underlies your window will be arranged
    so that the only rendering that will actually take place will be that
    which goes to the newly-revealed areas.  This is very performance-
    efficient, and visually attractive.

    After you have performed your refresh of the display, you should call
    EndRefresh() to reset the state of the layer and the window.  Then you
    may proceed with rendering to the entire window as usual.

    You learn that your window needs refreshing by receiving either a
    message of class IDCMP_REFRESHWINDOW through the IDCMP, or an input
    event of class IECLASS_REFRESHWINDOW through the Console device.
    Whenever you are told that your window needs refreshing, you should
    call BeginRefresh() and EndRefresh() to clear the refresh-needed
    state, even if you don't plan on doing any rendering.  You may relieve
    yourself of even this burden by setting the WFLG_NOCAREREFRESH flag
    when opening your window.

    WARNING: You should only perform graphics refreshing operations
    during the period between calling BeginRefresh() and EndRefresh().
    In particular, do not call RefreshGadgets() or RefreshGList(), since
    the locking protocol internal to Intuition runs the risk of creating
    a deadlock.  Note that Intuition refreshes the gadgets (through
    the damage region) before it sends the IDCMP_REFRESHWINDOW message.

    ANOTHER WARNING: The concept of multiple refresh passes using
    EndRefresh( w, FALSE ) is not completely sound without further
    protection.  The reason is that between two sessions, more
    damage can occur to your window.  Your final EndRefresh( w, TRUE )
    will dispose of all damage, including the new, and your
    initial refreshing pass will never get the chance to refresh
    the new damage.

    To avoid this, you must protect your session using LockLayerInfo()
    which will prevent Intuition from performing window operations
    or anything else which might cause further damage from occurring.
    Again, while holding the LayerInfo lock make no Intuition
    function calls dealing with gadgets; just render.

    You can, however, call InstallClipRegion() for the different
    refresh passes, if you have two clip regions.

    SIMILAR WARNING: Your program and Intuition "share" your window
    layer's DamageList.  BeginRefresh() helps arbitrate this
    sharing, but the lower-level function layers.library/BeginUpdate()
    does not.  It isn't really supported to use BeginUpdate() on
    a window's layer, but if you do--for whatever reason--it is
    critical that you first acquire the LayerInfo lock as in
    the above example: even if you only have one pass of refresh
    rendering to do.  Otherwise, the refreshing of your window's
    borders and gadgets can be incomplete, and the problem might
    occur only under certain conditions of task priority and
    system load.

EXAMPLE
    Code fragment for "two pass" window refreshing, in response
    to an IDCMP_REFRESHWINDOW message:
    switch ( imsg->Class )
    {
    ...
    case IDCMP_REFRESHWINDOW:
        window = imsg->IDCMPWindow;

        /* this lock only needed for "two-pass" refreshing */
        LockLayerInfo( &window->WScreen->LayerInfo );

        /* refresh pass for region 1 */
        origclip = InstallClipRegion( window->WLayer, region1 );
        BeginRefresh( window );
        myRefreshRegion1( window );
        EndRefresh( window, FALSE );

        /* refresh pass for region 2 */
        InstallClipRegion( window->WLayer, region2 );
        BeginRefresh( window );
        myRefreshRegion2( window );
        EndRefresh( window, TRUE );         /* and dispose damage list */

        /* restore and unlock */
        InstallClipRegion( window->WLayer, origclip );
        UnlockLayerInfo( &window->WScreen->LayerInfo );
        break;
    ...
    }

INPUTS
    Window = pointer to the window structure which needs refreshing

RESULT
    None

BUGS
    This function should check the return code of
    layers.library/BeginUpdate(), and abort if that function fails.

SEE ALSO
   EndRefresh(), layers.library/BeginUpdate(), OpenWindow()
    layer.library/InstallClipRegion(), graphics.library/LockLayerInfo()
    The "Windows" chapter of the Intuition Reference Manual


intuition.library/BuildEasyRequestArgs

NAME
    BuildEasyRequestArgs -- Simple creation of system request. (V36)
    BuildEasyRequest -- Varargs stub for BuildEasyRequestArgs(). (V36)

SYNOPSIS
    ReqWindow = BuildEasyRequestArgs( RefWindow, easyStruct, IDCMP, Args )
    D0                                A0         A1          D0     A3

    struct Window *BuildEasyRequestArgs( struct Window *,
            struct EasyStruct *, ULONG, APTR );

    ReqWindow = BuildEasyRequest( RefWindow, easyStruct, IDCMP, Arg1, ... )

    struct Window *BuildEasyRequest( struct Window *,
            struct EasyStruct *, ULONG, APTR, ... );

FUNCTION
    This function is to EasyRequest() as BuildSysRequest() is to
    AutoRequest(): it returns a pointer to the system requester
    window.  The input from that window can then be processed
    under application control.

    It is recommended that this processing be done with
    SysReqHandler(), so that future enhancement to the
    processing will be enjoyed.

    After you have determined that the requester is satisfied or
    cancelled, you must free this requester using FreeSysRequest().

    Please see the autodoc for EasyRequest().

    NOTE: This function switches the processor stack to ensure
    sufficient stack space for the function to complete.

INPUTS
    Window = reference window for requester: determines the
        requester window title and screen.
    easyStruct = pointer to EasyStruct structure, as described
        in the EasyRequest() autodocs.
    IDCMP = (NOT A POINTER) provided application specific IDCMP
        flags for the system requester window.
    Args = see EasyRequest()

RESULT
    A pointer to the system request window opened.  In the event
    of problems, you may also be returned the value '0' which
    is to be interpreted as the "FALSE, Cancel" choice, or
    (if you have a second gadget defined) the value '1', which
    is to be taken to mean the equivalent of your corresponding
    left-most gadget.

    If there is a problem creating the window, a recoverable alert may
    be substituted for the requester, and the result, either 0 or 1,
    returned.

BUGS
    Does not put up alternative alert.
    See also BUGS listed for EasyRequestArgs().

SEE ALSO
    EasyRequestArgs(), FreeSysRequest(), SysReqHandler(),
    BuildSysRequest(), AutoRequest()


intuition.library/BuildSysRequest

NAME
    BuildSysRequest -- Build and display a system requester.

SYNOPSIS
    ReqWindow = BuildSysRequest( Window, BodyText, PosText, NegText,
    D0                           A0      A1        A2       A3
                       IDCMPFlags, Width, Height )
                       D0          D1     D2

    struct Window *BuildSysRequest( struct Window *, struct IntuiText *,
            struct IntuiText *, struct IntuiText *, ULONG, WORD, WORD );

FUNCTION
    This procedure builds a system requester based on the supplied
    information.  If all goes well and the requester is constructed,
    this procedure returns a pointer to the window in which the requester
    appears.  That window will have its IDCMP initialized to reflect the
    flags found in the IDCMPFlags argument.  You may then wait on those
    ports to detect the user's response to your requester, which response
    may include either selecting one of the gadgets or causing some other
    event to be noticed by Intuition (like IDCMP_DISKINSERTED, for
    instance).  After the requester is satisfied, you should call the
    FreeSysRequest() procedure to remove the requester and free up
    any allocated memory.

    See the autodoc for SysReqHandler() for more information on the
    how to handle the IntuiMessages this window will receive.

    The requester used by this function has the NOISYREQ flag bit set,
    which means that the set of IDCMPFlags that may be used here
    include IDCMP_RAWKEY, IDCMP_MOUSEBUTTONS, and others.

    In release previous to V36, if the requester could not be built,
    this function would try to call DisplayAlert() with the same
    information, with more or less favorable results.  In V36,
    the requesters themselves require less memory (SIMPLEREQ), but
    there is no alert attempt.

    The function may return TRUE (1) or FALSE if it cannot post
    the requester.  (V36 will always return FALSE, but be sure to
    test for TRUE in case somebody reinstates the fallback alert.)

    If the window argument you supply is equal to NULL, a new window will
    be created for you in the Workbench screen, or the default
    public screen, for V36.  If you want the requester
    created by this routine to be bound to a particular window (i.e.,
    to appear in the same screen as the window), you should
    not supply a window argument of NULL.

    New for V36: if you pass a NULL window pointer, the system requester
    will appear on the default public screen, which is not always
    the Workbench.

    The text arguments are used to construct the display.  Each is a
    pointer to an instance of the structure IntuiText.

    The BodyText argument should be used to describe the nature of
    the requester.  As usual with IntuiText data, you may link several
    lines of text together, and the text may be placed in various
    locations in the requester.  This IntuiText pointer will be stored
    in the ReqText variable of the new requester.

    The PosText argument describes the text that you want associated
    with the user choice of "Yes,  TRUE,  Retry,  Good."  If the requester
    is successfully opened, this text will be rendered in a gadget in
    the lower-left of the requester, which gadget will have the
    GadgetID field set to TRUE.  If the requester cannot be opened and
    the DisplayAlert() mechanism is used, this text will be rendered in
    the lower-left corner of the alert display with additional text
    specifying that the left mouse button will select this choice.  This
    pointer can be set to NULL, which specifies that there is no TRUE
    choice that can be made.

    The NegText argument describes the text that you want associated
    with the user choice of "No,  FALSE,  Cancel,  Bad."  If the requester
    is successfully opened, this text will be rendered in a gadget in
    the lower-right of the requester, which gadget will have the
    GadgetID field set to FALSE.  If the requester cannot be opened and
    the DisplayAlert() mechanism is used, this text will be rendered in
    the lower-right corner of the alert display with additional text
    specifying that the right mouse button will select this choice.  This
    pointer cannot be set to NULL.  There must always be a way for the
    user to cancel this requester.

    The Positive and Negative Gadgets created by this routine have
    the following features:
      - GTYP_BOOLGADGET
      - GACT_RELVERIFY
      - GTYP_REQGADGET
      - GACT_TOGGLESELECT

    When defining the text for your gadgets, you may find it convenient
    to use the special constants used by Intuition for the construction
    of the gadgets.  These include defines like AUTODRAWMODE, AUTOLEFTEDGE,
    AUTOTOPEDGE and AUTOFRONTPEN.  You can find these in your local
    intuition.h (or intuition.i) file.

    These hard-coded constants are not very resolution or font
    sensitive, but V36 will override them to provide more modern
    layout.

    New for V36, linked lists of IntuiText are not correctly supported
    for gadget labels.

    The width and height values describe the size of the requester.  All
    of your BodyText must fit within the width and height of your
    requester.  The gadgets will be created to conform to your sizes.

    VERY IMPORTANT NOTE:  for this release of this procedure, a new window
    is opened in the same screen as the one containing your window.
    Future alternatives may be provided as a function distinct from this
    one.

    NOTE: This function will pop the screen the requester and its
    window appears in to the front of all screens.  New for V36,
    if the user doesn't perform any other screen arrangement before
    finishing with the requester, a popped screen will be pushed
    back behind.

INPUTS
    Window = pointer to a Window structure
    BodyText = pointer to an IntuiText structure
    PosText = pointer to an IntuiText structure
    NegText = pointer to an IntuiText structure
    IDCMPFlags = the IDCMP flags you want used for the initialization of
                 the IDCMP of the window containing this requester
    Width, Height = the size required to render your requester

    NOTE for V36: the width and height you pass are ignored, as
    are some of the parameters of your IntuiText, so that Intuition
    can make the Requesters real nice for the new look.

RESULT
    If the requester was successfully created, the value
    returned by this procedure is a pointer to the window in which the
    requester is rendered.  If the requester could not be created,
    this routine might have called DisplayAlert() before returning
    (it depends on the version) and will pass back TRUE if the user
    pressed the left mouse button and FALSE if the user pressed the
    right mouse button.   If the version of Intuition doesn't
    call DisplayAlert(), or if it does, and there's not enough
    memory for the alert, the value of FALSE is returned.

BUGS
    This procedure currently opens a window in the Screen which
    contains the window which is passed as a parameter, or the
    default public screen, if that parameter is NULL.  Although
    not as originally envisioned, this will probably always be the
    behavior of this function.

    DisplayAlert() is not called in version V36.

    It's almost impossible to make complete, correct account
    of different system fonts, window border dimensions, and
    screen resolution to get the layout of a System Requester
    just right using this routine.  For V36, we recommend the
    automatic layout implemented in BuildEasyRequest and EasyRequest.

SEE ALSO
    FreeSysRequest(), DisplayAlert(), ModifyIDCMP(), exec.library/Wait(),
    Request(), AutoRequest(), EasyRequest(), BuildEasyRequestArgs()


intuition.library/ChangeWindowBox

NAME
    ChangeWindowBox -- Change window position and dimensions. (V36)

SYNOPSIS
    ChangeWindowBox( Window, Left, Top, Width, Height )
                     A0      D0    D1   D2     D3

    VOID ChangeWindowBox( struct Window *, WORD, WORD, WORD, WORD );

FUNCTION
    Makes simultaneous changes in window position and dimensions,
    in absolute (not relative) coordinates.

    Like MoveWindow() and SizeWindow(), the effect of this function
    is deferred until the next input comes along.  Unlike these
    functions, ChangeWindowBox() specifies absolute window position
    and dimensions, not relative.  This makes for more reliable
    results considering that the action is deferred, so this
    function is typically preferable to MoveWindow() and SizeWindow()
    paired.

    You can detect that this operation has completed by receiving
    the IDCMP_CHANGEWINDOW IDCMP message

    The dimensions are limited to legal range, but you should still
    take care to specify sensible inputs based on the window's dimension
    limits and the size of its screen.

    This function limits the position and dimensions to legal
    values.

INPUTS
    Window = the window to change position/dimension
    Left, Top, Width, Height = new position and dimensions

RESULT
    Position and dimension are changed to your specification,
    or as close as possible.
    Returns nothing.

BUGS

SEE ALSO
    MoveWindow(), SizeWindow(), ZipWindow(),
    layers.library/MoveSizeLayer()


intuition.library/ClearDMRequest

NAME
    ClearDMRequest -- Clear (detaches) the DMRequest of the window.

SYNOPSIS
    Response = ClearDMRequest( Window )
    D0                         A0

    BOOL ClearDMRequest( struct Window * );

FUNCTION
    Attempts to clear the DMRequest from the specified window,
    that is detaches the special requester that you attach to
    the double-click of the menu button which the user can then
    bring up on demand.  This routine WILL NOT clear the DMRequest
    if it's active (in use by the user). The IDCMP message class
    IDCMP_REQCLEAR can be used to detect that the requester is not in use,
    but that message is sent only when the last of perhaps several
    requesters in use in a window is terminated.

INPUTS
    Window = pointer to the window from which the DMRequest is to be
             cleared.

RESULT
    If the DMRequest was not currently in use, detaches the DMRequest
    from the window and returns TRUE.

    If the DMRequest was currently in use, doesn't change anything
    and returns FALSE.

BUGS

SEE ALSO
    SetDMRequest(), Request()


intuition.library/ClearMenuStrip

NAME
    ClearMenuStrip -- Clear (detach) the menu strip from the window.

SYNOPSIS
    ClearMenuStrip( Window )
                    A0

    VOID ClearMenuStrip( struct Window * );

FUNCTION
    Detaches the current menu strip from the window; menu strips
    are attached to windows using the SetMenuStrip() function
    (or, for V36, ResetMenuStrip() ).

    If the menu is in use (for that matter if any menu is in use)
    this function will block (Wait()) until the user has finished.

    Call this function before you make any changes to the data
    in a Menu or MenuItem structure which is part of a menu
    strip linked into a window.

INPUTS
    Window = pointer to a window structure

RESULT
    None

BUGS

SEE ALSO
    SetMenuStrip(), ResetMenuStrip()


intuition.library/ClearPointer

NAME
    ClearPointer -- Clear the mouse pointer definition from a window.

SYNOPSIS
    ClearPointer( Window )
                  A0

    VOID ClearPointer( struct Window * );

FUNCTION
    Clears the window of its own definition of the Intuition mouse pointer.
    After calling ClearPointer(), every time this window is the active
    one the default Intuition pointer will be the pointer displayed
    to the user.  If your window is the active one when this routine
    is called, the change will take place immediately.

    Custom definitions of the mouse pointer which this function clears
    are installed by a call to SetPointer().

INPUTS
    Window = pointer to the window to be cleared of its pointer definition

RESULT
    None

BUGS

SEE ALSO
    SetPointer()


intuition.library/CloseScreen

NAME
    CloseScreen -- Close an Intuition screen.

SYNOPSIS
    [Success =] CloseScreen( Screen )
    [D0]                     A0

    [BOOL] CloseScreen( struct Screen * );
    /* returns BOOL in V36 and greater */

FUNCTION
    Unlinks the screen, unlinks the viewport, deallocates everything that
    Intuition allocated when the screen was opened (using OpenScreen()).
    Doesn't care whether or not there are still any windows attached to the
    screen.  Doesn't try to close any attached windows; in fact, ignores
    them altogether (but see below for changes in V36).

    If this is the last screen to go, attempts to reopen Workbench.

    New for V36: this function will refuse to close the screen
    if there are windows open on the screen when CloseScreen() is
    called.  This avoids the almost certain crash when a screen
    is closed out from under a window.

INPUTS
    Screen = pointer to the screen to be closed.

RESULT
    New for V36: returns TRUE (1) if screen is closed,
    returns FALSE (0) if screen had open windows when
    called.

BUGS

SEE ALSO
    OpenScreen()


intuition.library/CloseWindow

NAME
    CloseWindow -- Close an Intuition window.

SYNOPSIS
    CloseWindow( Window )
                 A0

    VOID CloseWindow( struct Window * );

FUNCTION
    Closes an Intuition window.  Unlinks it from the system, deallocates
    its memory, and makes it disappear.

    When this function is called, all IDCMP messages which have been sent
    to your window are deallocated.  If the window had shared a message
    Port with other windows, you must be sure that there are no unreplied
    messages for this window in the message queue.  Otherwise, your program
    will try to make use of a linked list (the queue) which contains free
    memory (the old messages).  This will give you big problems.
    See the code fragment CloseWindowSafely(), below.

    NOTE:  If you have added a Menu strip to this Window (via
    a call to SetMenuStrip()) you must be sure to remove that Menu strip
    (via a call to ClearMenuStrip()) before closing your Window.

    NOTE: This function may block until it is safe to de-link and free
    your window.  Your program may thus be suspended while the user
    plays with gadgets, menus, or window sizes and position.

    New for V36: If your window is a "Visitor Window" (see OpenWindow)
    CloseWindow will decrement the "visitor count" in the public screen
    on which the window was open.  When the last visitor window is
    closed, a signal will be sent to the public screen task, if this
    was pre-arranged (see OpenScreen).

INPUTS
    Window = a pointer to a Window structure

RESULT
    None

BUGS

SEE ALSO
    OpenWindow(), OpenScreen(), CloseScreen()

EXAMPLE
/*  CloseWindowSafely */

    /* these functions close an Intuition window
     * that shares a port with other Intuition
     * windows or IPC customers.
     *
     * We are careful to set the UserPort to
     * null before closing, and to free
     * any messages that it might have been
     * sent.
     */
    #include "exec/types.h"
    #include "exec/nodes.h"
    #include "exec/lists.h"
    #include "exec/ports.h"
    #include "intuition/intuition.h"

    CloseWindowSafely( win )
    struct Window *win;
    {
        /* we forbid here to keep out of race conditions with Intuition */
        Forbid();

        /* send back any messages for this window
         * that have not yet been processed
         */
        StripIntuiMessages( win->UserPort, win );

        /* clear UserPort so Intuition will not free it */
        win->UserPort = NULL;

        /* tell Intuition to stop sending more messages */
        ModifyIDCMP( win, 0L );

        /* turn multitasking back on */
        Permit();

        /* and really close the window */
        CloseWindow( win );
    }

    /* remove and reply all IntuiMessages on a port that
     * have been sent to a particular window
     * (note that we don't rely on the ln_Succ pointer
     *  of a message after we have replied it)
     */
    StripIntuiMessages( mp, win )
    struct MsgPort *mp;
    struct Window *win;
    {
        struct IntuiMessage *msg;
        struct Node *succ;

        msg = (struct IntuiMessage *) mp->mp_MsgList.lh_Head;

        while( succ =  msg->ExecMessage.mn_Node.ln_Succ ) {

            if( msg->IDCMPWindow ==  win ) {

                /* Intuition is about to free this message.
                 * Make sure that we have politely sent it back.
                 */
                Remove( msg );

                ReplyMsg( msg );
            }

            msg = (struct IntuiMessage *) succ;
        }
    }


intuition.library/CloseWorkBench

NAME
    CloseWorkBench -- Closes the Workbench screen.

SYNOPSIS
    Success = CloseWorkBench()
    D0

    LONG CloseWorkBench( VOID );

FUNCTION
    This routine attempts to close the Workbench screen:
   -   Test whether or not any applications have opened windows on the
       Workbench, and return FALSE if so.  Otherwise ...
   -   Clean up all special buffers
   -   Close the Workbench screen
   -   Make the Workbench program mostly inactive (it will still
       monitor disk activity)
   -   Return TRUE

INPUTS
    None

RESULT
    TRUE if the Workbench screen closed successfully
    FALSE if the Workbench was not open, or if it has windows
        open which are not Workbench drawers.

NOTES
    This routine has been drastically rewritten for V36.
    It is much more solid, although we haven't eliminated
    all the problem cases yet.

BUGS
    The name of this function is improperly spelled.  It ought
    to have been CloseWorkbench().

    It might be more convenient to have it return TRUE if the
    Workbench wasn't opened when called.  The idea as it is now
    is probably this: if you want to free up the memory of the
    Workbench screen when your program begins, you can call
    CloseWorkBench().  The return value of that call indicates
    whether you should call OpenWorkBench() when your program
    exits: if FALSE, that means either the the Workbench existed
    but you could not close it, or that it wasn't around to
    begin with, and you should not try to re-open it.

    We would prefer that you provide a user selection to attempt
    to open or close the Workbench screen from within your application,
    rather than your making assumptions like these.

SEE ALSO
    OpenWorkBench()


intuition.library/CurrentTime

NAME
    CurrentTime -- Get the current time values.

SYNOPSIS
    CurrentTime( Seconds, Micros )
                 A0       A1

    VOID CurrentTime( ULONG *, ULONG * );

FUNCTION
    Puts copies of the current time into the supplied argument pointers.

    This time value is not extremely accurate, nor is it of a very fine
    resolution.  This time will be updated no more than sixty times a
    a second, and will typically be updated far fewer times a second.

INPUTS
    Seconds = pointer to a LONG variable to receive the current seconds
        value
    Micros = pointer to a LONG variable for the current microseconds value

RESULT
    Puts the time values into the memory locations specified by the
        arguments
    Return value is not defined.

BUGS

SEE ALSO
    timer.device/TR_GETSYSTIME


intuition.library/DisplayAlert

NAME
    DisplayAlert -- Create the display of an alert message.

SYNOPSIS
    Response = DisplayAlert( AlertNumber, String, Height )
    D0                       D0           A0      D1

    BOOL DisplayAlert( ULONG, UBYTE *, WORD );

FUNCTION
    Creates an alert display with the specified message.

    If the system can recover from this alert, it's a RECOVERY_ALERT and
    this routine waits until the user presses one of the mouse buttons,
    after which the display is restored to its original state and a
    BOOL value is returned by this routine to specify whether or not
    the user pressed the LEFT mouse button.

    If the system cannot recover from this alert, it's a DEADEND_ALERT
    and this routine returns immediately upon creating the alert display.
    The return value is FALSE.

    NOTE: Starting with V33, if Intuition can't get enough
    memory for a RECOVERY_ALERT, the value FALSE will be returned.

    AlertNumber is a LONG value, historically related to the value
    sent to the Alert() routine.  But the only bits that are pertinent to
    this routine are the ALERT_TYPE bit(s).  These bits must be set to
    either RECOVERY_ALERT for alerts from which the system may safely
    recover, or DEADEND_ALERT for those fatal alerts.  These states are
    described in the paragraph above.   There is a third type of
    alert, the DAISY_ALERT, which is used only by the Exec.

    The string argument points to an AlertMessage string.  The AlertMessage
    string is comprised of one or more substrings, each of which is
    composed of the following components:
       - first, a 16-bit x-coordinate and an 8-bit y-coordinate,
         describing where on the alert display you want this string
         to appear.  The y-coordinate describes the offset to the
         baseline of the text.
       - then, the bytes of the string itself, which must be
         null-terminated (end with a byte of zero)
       - lastly, the continuation byte, which specifies whether or
         not there's another substring following this one.  If the
         continuation byte is non-zero, there IS another substring
         to be processed in this alert message.  If the continuation
         byte is zero, this is the last substring in the message.

    The last argument, Height, describes how many video lines tall you
    want the alert display to be.

    New for V36: Alerts are always rendered in Topaz 8 (80 column font),
    regardless of the system default font.  Also, RECOVERY_ALERTs are
    displayed in amber, while DEADEND_ALERTs are still red.  Alerts
    no longer push down the application screens to be displayed.  Rather,
    they appear alone in a black display.

    Also new for V36: Alerts block each other out, and input
    during an alert is deprived of the rest of the system.  Internal
    input buffers still cause alert clicks to be processed by
    applications sometimes.

INPUTS
    AlertNumber = the number of this alert message.  The only pertinent
        bits of this number are the ALERT_TYPE bit(s).  The rest of the
       number is ignored by this routine.
    String = pointer to the alert message string, as described above
    Height = minimum display lines required for your message

RESULT
    A BOOL value of TRUE or FALSE.  If this is a DEADEND_ALERT, FALSE
    is always the return value.  If this is a RECOVERY_ALERT. The return
    value will be TRUE if the user presses the left mouse button in
    response to your message, and FALSE if the user presses the right hand
    button is response to your text, or if the alert could not
    be posted.

BUGS
    If the system is worse off than you think, the level of your alert
    may become DEADEND_ALERT without you ever knowing about it.  This
    will NOT happen due simply to low memory.  Rather, the alert
    display will be skipped, and FALSE will be returned.

    The left and right button clicks satisfying the alerts are
    unfortunately passed to the normal applications, because of
    some internal system input buffering.

SEE ALSO


intuition.library/DisplayBeep

NAME
    DisplayBeep -- Flash the video display.

SYNOPSIS
    DisplayBeep( Screen )
                 A0

    VOID DisplayBeep( struct Screen * );

FUNCTION
    "Beeps" the video display by flashing the background color of the
    specified screen.  If the screen argument is NULL, every screen
    in the display will be beeped.  Flashing everyone's screen is not
    a polite thing to do, so this should be reserved for dire
    circumstances.

    The reason such a routine is supported is because the Amiga has
    no internal bell or speaker.  When the user needs to know of
    an event that is not serious enough to require the use of a requester,
    the DisplayBeep() function may be called.

    New for V36:  Intuition now calls DisplayBeep through the
    external library vector.  This means that if you call SetFunction()
    to replace DisplayBeep with an audible beep, for example, then
    your change will affect even Intuition's calls to DisplayBeep.

INPUTS
    Screen = pointer to a screen.  If NULL, every screen in the display
       will be flashed

RESULT
    None

BUGS

SEE ALSO


intuition.library/DisposeObject

NAME
    DisposeObject -- Deletes a 'boopsi' object. (V36)

SYNOPSIS
    DisposeObject( Object )
                   A0

    VOID DisposeObject( APTR );

FUNCTION
    Deletes a boopsi object and all of it auxiliary data.
    These objects are all created by NewObject().  Objects
    of certain classes "own" other objects, which will also
    be deleted when the object is passed to DisposeObject().
    Read the per-class documentation carefully to be aware
    of these instances.

INPUTS
    Object = abstract pointer to a boopsi object returned by NewObject()

NOTES
    This function invokes the OM_DISPOSE method.

RESULT
    None.

BUGS

SEE ALSO
    NewObject(), SetAttrs(), GetAttr(), MakeClass(),
    Document "Basic Object-Oriented Programming System for Intuition"
    and the "boopsi Class Reference" document.


intuition.library/DoubleClick

NAME
    DoubleClick -- Test two time values for double-click timing.

SYNOPSIS
    IsDouble = DoubleClick( StartSecs, StartMicros,
    D0                      D0         D1
            CurrentSecs, CurrentMicros )
            D2           D3

    BOOL DoubleClick( ULONG, ULONG, ULONG, ULONG );

FUNCTION
    Compares the difference in the time values with the double-click
    timeout range that the user has set (using the "Preferences" tool) or
    some other program has configured into the system.  If the
    difference between the specified time values is within the current
    double-click time range, this function returns TRUE, else it
    returns FALSE.

   These time values can be found in input events and IDCMP messages.
   The time values are not perfect; however, they are precise enough for
   nearly all applications.

INPUTS
    StartSeconds, StartMicros = the timestamp value describing the start of
      the double-click time period you are considering
    CurrentSeconds, CurrentMicros = the timestamp value describing
      the end of the double-click time period you are considering

RESULT
    If the difference between the supplied timestamp values is within the
    double-click time range in the current set of Preferences, this
    function returns TRUE, else it returns FALSE

BUGS

SEE ALSO
    CurrentTime()


intuition.library/DrawBorder

NAME
    DrawBorder -- Draw the specified Border structure into a RastPort.

SYNOPSIS
    DrawBorder( RastPort, Border, LeftOffset, TopOffset )
                A0        A1      D0          D1

    VOID DrawBorder( struct RastPort *, struct Border *, WORD, WORD );

FUNCTION
    First, sets up the draw mode and pens in the RastPort according to the
    arguments of the Border structure.  Then, draws the vectors of
    the border argument into the RastPort, offset by the left and top
    offsets.

    As with all graphics rendering routines, the border will be clipped to
    to the boundaries of the RastPort's layer, if it exists.  This is
    the case with window RastPorts.

    This routine will draw all borders in the NULL-terminated list linked
    by the NextBorder field of the border argument.

INPUTS
    RastPort = pointer to the RastPort to receive the border rendering
    Border = pointer to a Border structure
    LeftOffset = the offset to be added to each vector's x coordinate
    TopOffset = the offset to be added to each vector's y coordinate

RESULT
    None

BUGS

SEE ALSO


intuition.library/DrawImage

NAME
    DrawImage -- Draw the specified Image structure into a RastPort.

SYNOPSIS
    DrawImage( RastPort, Image, LeftOffset, TopOffset )
               A0        A1     D0          D1

    VOID DrawImage( struct RastPort *, struct Image    *, WORD, WORD );

FUNCTION
    First, sets up the draw mode and pens in the RastPort according to the
    arguments of the Image structure.  Then, moves the image data of
    the image argument into the RastPort, offset by the left and top
    offsets.

    This routine does window layer clipping if you pass your window's
    (layered) RastPort -- if you draw an image outside of your window,
    your imagery will be clipped at the window's edge.  If you pass
    a (non-layered) screen RastPort, you MUST be sure your image is
    wholly contained within the rastport bounds.

    If the NextImage field of the image argument is non-NULL,
    the next image is rendered as well, and so on until some
    NextImage field is found to be NULL.

INPUTS
    RastPort = pointer to the RastPort to receive image rendering
    Image = pointer to an image structure
    LeftOffset = the offset which will be added to the image's x coordinate
    TopOffset = the offset which will be added to the image's y coordinate

RESULT
    None

NOTES
    Intuition always has and will continue to assume there are
    at least as many planes of data pointed to by ImageData as there
    are '1' bits in the PlanePick field.  Please ensure that
    this is so.  (See the intuition.h include file for full details
    on using PlanePick).

BUGS

SEE ALSO
    DrawImageState(), EraseImage()


intuition.library/DrawImageState

NAME
    DrawImageState -- Draw an (extended) Intuition Image with
            special visual state. (V36)

SYNOPSIS
    DrawImageState( RPort, Image, LeftOffset, TopOffset, State, DrawInfo )
                    A0     A1     D0          D1         D2     A2

    VOID DrawImageState( struct RastPort *, struct Image *,
            WORD, WORD, ULONG, struct DrawInfo * );

FUNCTION
    This function draws an Intuition Image structure in a variety of
    "visual states," which are defined by constants in
    intuition/imageclass.h.  These include:
    IDS_NORMAL              - like DrawImage()
    IDS_SELECTED            - represents the "selected state" of a Gadget
    IDS_DISABLED            - the "ghosted state" of a gadget
    IDS_BUSY                - for future functionality
    IDS_INDETERMINATE       - for future functionality
    IDS_INACTIVENORMAL      - for gadgets in window border
    IDS_INACTIVESELECTED    - for gadgets in window border
    IDS_INACTIVEDISABLED    - for gadgets in window border

    Only IDS_NORMAL will make sense for traditional Image structures,
    this function is more useful when applied to new custom images
    or "object-oriented image classes."

    Each class of custom images is responsible for documenting which
    visual states it supports, and you typically want to use images
    which support the appropriate states with your custom gadgets.

    The DrawInfo parameter provides information invaluable to
    "rendered" images, such as pen color and resolution.  Each
    image class must document whether this parameter is required.

INPUTS
    RPort   - RastPort for rendering
    Image   - pointer to a (preferably custom) image
    LeftOffset,RightOffset - positional offsets in pixels
    State   - visual state selected from above
    DrawInfo - pointer to packed of pen selections and resolution.

RESULT
    None.

EXAMPLE
    Provided separately in the DevCon '90 disk set.

NOTES

BUGS

SEE ALSO
    DrawImage(), GetScreenDrawInfo(), intuition/imageclass.h


intuition.library/EasyRequestArgs

NAME
    EasyRequestArgs -- Easy alternative to AutoRequest(). (V36)
    EasyRequest -- Varargs stub for EasyRequestArgs(). (V36)

SYNOPSIS
    num = EasyRequestArgs( Window, easyStruct, IDCMP_ptr, ArgList )
    D0                     A0      A1          A2         A3

    LONG EasyRequestArgs( struct Window *, struct EasyStruct *,
            ULONG *, APTR );

    num = EasyRequest( Window, easyStruct, IDCMP_ptr, Arg1, Arg2, ... )

    LONG EasyRequest( struct Window *, struct EasyStruct *,
            ULONG *, APTR, ... );

    ( from intuition.h )
    struct EasyStruct {
        ULONG       es_StructSize;
        ULONG       es_Flags;
        UBYTE       *es_Title;
        UBYTE       *es_TextFormat;
        UBYTE       *es_GadgetFormat;
    };

FUNCTION
    This function provides a simpler method of using a 'System
    Requester' than provided by AutoRequest().  It performs layout
    and size calculations sensitive to the current font and screen
    resolution.

    It provides for the descriptive 'body' text and the gadget
    text to be constructed from 'printf' style format strings.

    It also provides a general way for the requester to be
    sensitive to particular IDCMP messages.

    The first function listed is the actual Intuition library
    function.  It is passed the arguments for the formatting
    operations as a pointer to the first argument.

    The second function uses a C-style variable number of argument
    (varargs) calling convention.  It should be implemented as
    a call to the first function, and might be supplied by your
    compiler vendor, in amiga.lib, or using the first example below,
    for most C compilers.

    NOTE: The formatting is done by exec.library/RawDoFmt(), so
    be aware that to display a 32-bit integer argument, for
    example, you must say "%ld", not "%d", since RawDoFmt() is
    "word-oriented."

    NOTE: This function switches the processor stack to ensure
    sufficient stack space for the function to complete.

EXAMPLES
    /* varargs interface works for most C compilers */
    EasyRequest( w, es, ip, arg1 )
    struct Window   *w;
    struct EasyStruct *es;
    ULONG             *ip;
    int               arg1;
    {
        return ( EasyRequestArgs( w, es, ip, &arg1 ) );
    }

    /*********************************************/

    /* typical use */
    struct EasyStruct volumeES = {
        sizeof (struct EasyStruct),
        0,
        "Volume Request",
        "Please insert volume %s in any drive.",
        "Retry|Cancel",
    };
    #define CANCEL  (0)

    Volume  *
    getVolume( volname )
    UBYTE   *volname;
    {
        Volume      *vptr;
        Volume      *findVolume();
        UWORD       reply;
        ULONG       iflags;

        iflags = IDCMP_DISKINSERTED;

    while ( ((vptr = findVolume( volname )) == NULL) &&
     (EasyRequest( w, &volumeES, &iflags, volname ) != CANCEL) )
            /* loop */ ;

        /* note that in some circumstances, you will have to
           re-initialize the value of 'iflags'.  Here, it
           is either unchanged, or returned as the single
           IDCMPFlag value IDCMP_DISKINSERTED.  If you combine
           multiple  IDCMPFlag values in 'iflags,' only
           one will be returned, so you must reinitialize
           'iflags' to be the combination.
          */
        return ( vptr );
    }

INPUTS
    Window = Reference window pointer, determines the screen and
        title of the requester window.  This can be NULL, which
        means the requester is to appear on the Workbench screen,
        or default public screen, if defined.
    IDCMP_ptr = Pointer to IDCMP flags that you want to terminate
            the requester.  This pointer may be NULL.
    easyStruct = Pointer to EasyStruct structure with fields
            interpreted as follows:

    es_StructSize = sizeof (struct EasyStruct), for future extension.
    es_Flags = 0 for now, in the future may specify other options.
    es_Title = Title of system requester window.  If this is NULL,
        the title will be taken to be the same as the title of 'Window',
        if provided, or else "System Request."
    es_TextFormat = Format string, a la RawDoFmt(), for message in
        requester body.  Lines are separated by 'n'.  Formatting
        '%' functions are supported exactly as in RawDoFmt().
    es_GadgetFormat = Format string for gadgets.  Text for separate
        gadgets is separated by '|'.  Format functions are supported.
        You MUST specify at least one gadget.

    Args = Arguments for format commands.   Arguments for
        GadFmt follow arguments for TextFmt.

RESULT
    0, 1, ..., N = Successive GadgetID values, for the gadgets
        you specify for the requester.  NOTE: The numbering
        from left to right is actually: 1, 2, ..., N, 0.
        This is for compatibility with AutoRequests which has
        FALSE for the rightmost gadget.

    -1 = Means that one of the caller-supplied IDCMPFlags occurred.
        The IDCMPFlag value is in the longword pointed to by IDCMP_ptr.

NOTES
    When DOS brings up EasyRequests() on your process (eg.
    "Please insert volume XXX in any drive", they normally come
    up on the default public screen, which is usually the Workbench
    screen.  If you set your Process pr_WindowPtr field to point to
    one of your windows, then DOS will bring its requesters up on the
    same screen as that window.  A pr_WindowPtr of -1 prevents
    requesters from coming up at all.
    (Some FileSystem requesters cannot be redirected or supressed).

BUGS
    Does not fall back to a recoverable alert if the requester
     cannot be created.

    Does not handle case when gadgets don't fit or window title
    is too long, although it does trim trailing spaces from the
    title for calculating dimensions.

PLANS
    Possible enhancements include: centering of text, size-sensitive
    layout,  window-relative requester, vertical gadget layout,
    window placement, more keyboard shortcuts.

    We also reserve the use of the newline character 'n' in
    gadget format strings for future use as a line separator.

SEE ALSO
    exec.library/RawDoFmt(), BuildEasyRequestArgs(), SysReqHandler(),
    AutoRequest(), BuildSysRequest()


intuition.library/EndRefresh

NAME
    EndRefresh -- End the optimized refresh state of the window.

SYNOPSIS
    EndRefresh( Window, Complete )
                A0      D0

    VOID EndRefresh( struct Window *, BOOL );

FUNCTION
    This function gets you out of the special refresh state of your
    window.  It is called following a call to BeginRefresh(), which
    routine puts you into the special refresh state.  While your window
    is in the refresh state, the only rendering that will be wrought in
    your window will be to those areas which were recently revealed and
    need to be refreshed.

    After you've done all the refreshing you want to do for this window,
    you should call this routine to restore the window to its
    non-refreshing state.  Then all rendering will go to the entire
    window, as usual.

    The 'Complete' argument is a boolean TRUE or FALSE value used to
    describe whether or not the refreshing you've done was all the
    refreshing that needs to be done at this time.  Most often, this
    argument will be TRUE.  But if, for instance, you have multiple
    tasks or multiple procedure calls which must run to completely
    refresh the window, then each can call its own Begin/EndRefresh()
    pair with a Complete argument of FALSE, and only the last calls
    with a Complete argument of TRUE.

    WARNING:  Passing this function the value of FALSE has its
    pitfalls.  Please see the several caveats in the autodoc for
    BeginRefresh().

    For your information, this routine calls the Layers library function
    EndUpdate(), unlocks your layers (calls UnlockLayerRom()), clears
    the LAYERREFRESH bit in your Layer Flags, and clears the
    WFLG_WINDOWREFRESH bit in your window Flags.

INPUTS
    Window = pointer to the window currently in optimized-refresh mode
    Complete = Boolean TRUE or FALSE describing whether or not this
       window is completely refreshed

RESULT
    None

BUGS

SEE ALSO
    BeginRefresh(), layers.library/EndUpdate(),
    graphics.library/UnlockLayerRom()


intuition.library/EndRequest

NAME
    EndRequest -- Remove a currently active requester.

SYNOPSIS
    EndRequest( Requester, Window )
                A0         A1

    VOID EndRequest( struct Requester *, struct Window * );

FUNCTION
    Ends the request by erasing the requester and decoupling it from
    the window.

    Note that this doesn't necessarily clear all requesters from the
    window, only the specified one.  If the window labors under other
    requesters, they will remain in the window.

INPUTS
    Requester = pointer to the requester to be removed
    Window = pointer to the Window structure with which this requester
       is associated

RESULT
    None

BUGS

SEE ALSO
    Request()


intuition.library/EraseImage

NAME
    EraseImage -- Erases an Image. (V36)

SYNOPSIS
    EraseImage( RPort, Image, LeftOffset, TopOffset )
                A0     A1     D0          D1

    VOID EraseImage( struct RastPort *, struct Image *, WORD, WORD );

FUNCTION
    Erases an Image.  For a normal Image structure, this will
    call the graphics function EraseRect() (clear using layer
    backfill, if any) for the Image box (LeftEdge/TopEdge/Width/Height).

    For custom image, the exact behavior is determined by the
    custom image class.

INPUTS
    RPort   - RastPort to erase a part of
    Image   - custom or standard image
    LeftOffset,RightOffset - pixel offsets of Image position

RESULT
    None.

EXAMPLE

NOTES

BUGS

SEE ALSO
    graphics.library/EraseRect().


intuition.library/FreeClass

NAME
    FreeClass -- Frees a boopsi class created by MakeClass(). (V36)

SYNOPSIS
    success = FreeClass( ClassPtr )
    D0                   A0

    BOOL FreeClass( struct IClass * );

FUNCTION
    For class implementors only.

    Tries to free a boopsi class created by MakeClass().  This
    won't always succeed: classes with outstanding objects or
    with subclasses cannot be freed.  You cannot allow the code
    which implements the class to be unloaded in this case.

    For public classes, this function will *always* remove
    the class (see RemoveClass() ) making it unavailable, whether
    it succeeds or not.

    If you have a dynamically allocated data for your class (hanging
    off of cl_UserData), try to free the class before you free the
    user data, so you don't get stuck with a half-freed class.

INPUTS
    ClassPtr - pointer to a class created by MakeClass().

RESULT
    Returns FALSE if the class could not be freed.  Reasons include,
    but will not be limited to, having non-zero cl_ObjectCount or
    cl_SubclassCount.

    Returns TRUE if the class could be freed.

    Calls RemoveClass() for the class in either case.

EXAMPLE
    Freeing a private class with dynamically allocated user data:

    freeMyClass( cl )
    struct IClass   *cl;
    {
        struct MyPerClassData       *mpcd;

        mpcd = (struct MyPerClassData *) cl->cl_UserData;
        if ( FreeClass( cl ) )
        {
            FreeMem( mpcd, sizeof mpcd );
            return ( TRUE );
        }
        else
        {
            return ( FALSE );
        }
    }

BUGS

SEE ALSO
    MakeClass(),
    Document "Basic Object-Oriented Programming System for Intuition"
    and the "boopsi Class Reference" document.


intuition.library/FreeRemember

NAME
    FreeRemember -- Free memory allocated by calls to AllocRemember().

SYNOPSIS
    FreeRemember( RememberKey, ReallyForget )
                  A0           D0

    VOID FreeRemember( struct Remember **, BOOL );

FUNCTION
    This function frees up memory allocated by the AllocRemember()
    function.  It will either free up just the Remember structures, which
    supply the link nodes that tie your allocations together, or it will
    deallocate both the link nodes AND your memory buffers too.

    If you want to deallocate just the Remember structure link nodes,
    you should set the ReallyForget argument to FALSE.  However, if you
    want FreeRemember to really deallocate all the memory, including
    both the Remember structure link nodes and the buffers you requested
    via earlier calls to AllocRemember(), then you should set the
    ReallyForget argument to TRUE.

    NOTE WELL: Once you call this function passing it FALSE, the
    linkages between all the memory chunks are lost, and you
    cannot subsequently use FreeRemember() to free them.

INPUTS
    RememberKey = the address of a pointer to struct Remember.  This
       pointer should either be NULL or set to some value (possibly
       NULL) by a call to AllocRemember().
    ReallyForget = a BOOL FALSE or TRUE describing, respectively,
       whether you want to free up only the Remember nodes or
       if you want this procedure to really forget about all of
       the memory, including both the nodes and the memory buffers
       referenced by the nodes.

EXAMPLE
    struct Remember *RememberKey;
    RememberKey = NULL;
    AllocRemember(&RememberKey, BUFSIZE, MEMF_CHIP);
    FreeRemember(&RememberKey, TRUE);

RESULT
    None

BUGS

SEE ALSO
    AllocRemember(), exec.library/FreeMem()


intuition.library/FreeScreenDrawInfo

NAME
    FreeScreenDrawInfo -- Finish using a DrawInfo structure. (V36)

SYNOPSIS
    FreeScreenDrawInfo( Screen, DrInfo )
                        A0      A1

    VOID FreeScreenDrawInfo( struct Screen *, struct DrawInfo * );

FUNCTION
    Declares that you are finished with the DrawInfo structure
    returned by GetScreenDrawInfo().

INPUTS
    Screen           - pointer to screen passed to GetScreenDrawInfo()
    DrInfo      - pointer to DrawInfo returned by GetScreenDrawInfo()

RESULT
    None

NOTES
    This function, and GetScreenDrawInfo(), don't really do much, but
    they provide an upward compatibility path.  That means that
    if you misuse them today, they probably won't cause a problem,
    although they may someday later.  So, please be very careful
    only to use the DrawInfo structure between calls to
    GetScreenDrawInfo() and FreeScreenDrawInfo(), and be sure
    that you don't forget FreeScreenDrawInfo().

BUGS

SEE ALSO
    GetScreenDrawInfo()


intuition.library/FreeSysRequest

NAME
    FreeSysRequest -- Free resources gotten by a call to BuildSysRequest().

SYNOPSIS
    FreeSysRequest( Window )
                    A0

    VOID FreeSysRequest( struct Window * );

FUNCTION
    This routine frees up all memory allocated by a successful call to
    the BuildSysRequest() procedure.  If BuildSysRequest() returned a
    pointer to a window, then you are able to wait on the message port
    of that window to detect an event which satisfies the requester.
    When you want to remove the requester, you call this procedure.  It
    ends the requester and deallocates any memory used in the creation
    of the requester.  It also closes the special window that was opened
    for your system requester.

    For V36: It's OK if you pass a NULL or a TRUE (1) value to
    this function.  Also, this function properly disposes of
    requesters gotten using BuildEasyRequest().

INPUTS
    Window = value of the window pointer returned by a successful call to
       the BuildSysRequest() procedure

RESULT
    None

BUGS

SEE ALSO
    BuildSysRequest(), AutoRequest(), CloseWindow()


intuition.library/GadgetMouse

NAME
    GadgetMouse -- Calculate gadget-relative mouse position. (V36)

SYNOPSIS
    GadgetMouse( Gadget, GInfo, MousePoint )
                 A0      A1     A2

    VOID GadgetMouse( struct GadgetInfo *, WORD * );

FUNCTION
    Determines the current location of the mouse pointer relative
    to the upper-left corner of a custom gadget.  Typically used
    only in the GM_HANDLEINPUT and GM_GOACTIVE custom gadget hook
    routines.

    NEWS FLASH!!: These two hook routines are now passed the mouse
    coordinates, so this function has no known usefulness.

    We recommend that you don't call it.

    Note that this function calculates the mouse position taking
    "gadget relativity" (GFLG_RELRIGHT, GFLG_RELBOTTOM) into
    consideration.  If your custom gadget intends to ignore these
    properties, then you should either enjoin or inhibit your users
    from setting those bits, since Intuition won't ask if you respect
    them.

INPUTS
    GInfo = A pointer to a GadgetInfo structure as passed to the
            custom gadget hook routine.
    MousePoint = address of two WORDS, or a pointer to a structure of
            type Point.

RESULT
    Returns nothing.  Fills in the two words pointed to by
    MousePoint with the gadget-relative mouse position.

BUGS
    Useless, since equivalent information is now passed to every
    function that might have a use for this.

SEE ALSO


intuition.library/GetAttr

NAME
    GetAttr -- Inquire the value of some attribute of an object. (V36)

SYNOPSIS
    attr = GetAttr( AttrID, Object, StoragePtr )
    D0              D0      A0      A1

    ULONG GetAttr( ULONG, APTR, ULONG * );

FUNCTION
    Inquires from the specified object the value of the specified
    attribute.

    You always pass the address of a long variable, which will
    receive the same value that would be passed to SetAttrs() in
    the ti_Data portion of a TagItem element.  See the documentation
    for the class for exceptions to this general rule.

    Not all attributes will respond to this function.  Those that
    will are documented on a class-by-class basis.

INPUTS
    AttrID = the attribute tag ID understood by the object's class
    Object = abstract pointer to the boopsi object you are interested in
    StoragePtr = pointer to appropriate storage for the answer

RESULT
    Returns FALSE (0) if the inquiries of attribute are not provided
    by the object's class.

NOTES
    This function invokes the OM_GET method of the object.

BUGS

SEE ALSO
    NewObject(), DisposeObject(), SetAttrs(), MakeClass(),
    Document "Basic Object-Oriented Programming System for Intuition"
    and the "boopsi Class Reference" document.


intuition.library/GetDefaultPubScreen

NAME
    GetDefaultPubScreen -- Get name of default public screen. (V36)

SYNOPSIS
    GetDefaultPubScreen( Namebuff )
                         A0

    VOID GetDefaultPubScreen( UBYTE * );

FUNCTION
    Provides the name of the current default public screen.
    Only anticipated use is for Public Screen Manager utilities,
    since it is easy to open a visitor window on the default
    public screen without specifying the name.

INPUTS
    Namebuff = a buffer of MAXPUBSCREENNAME.  This can be NULL.

RESULT
    None.  Will provide the string "Workbench" in Namebuff if there
    is no current default public screen.

NOTE
    This function actually "returns" in register D0 a pointer
    to the public screen.  Unfortunately, the lifespan of
    this pointer is not ensured; the screen could be closed
    at any time.  The *ONLY* legitimate use we can see for
    this return value is to compare for identity with the pointer
    to a public screen you either have a window open in, or
    a lock on using LockPubScreen(), to determine if that
    screen is in fact the default screen.

BUGS
    The function prototype does not reflect the return value.

SEE ALSO
    SetDefaultPubScreen(), OpenWindow()


intuition.library/GetDefPrefs

NAME
    GetDefPrefs -- Get a copy of the the Intuition default Preferences.

SYNOPSIS
    Prefs = GetDefPrefs( PrefBuffer, Size )
    D0                   A0          D0

    struct Preferences *GetDefPrefs( struct Preferences *, WORD );

FUNCTION
    Gets a copy of the Intuition default preferences data.  Writes the
    data into the buffer you specify.  The number of bytes you want
    copied is specified by the size argument.

    The default preferences are those that Intuition uses when it
    is first opened.  If no preferences file is found, these are
    the preferences that are used.  These would also be the startup
    preferences in an AmigaDOS-less environment.

    It is legal to take a partial copy of the Preferences structure.
    The more pertinent preferences variables have been grouped near
    the top of the structure to facilitate the memory conservation
    that can be had by taking a copy of only some of the Preferences
    structure.

INPUTS
    PrefBuffer = pointer to the memory buffer to receive your copy of the
            Intuition Preferences structure
    Size = the number of bytes in your PrefBuffer, the number of bytes
      you want copied from the system's internal Preference settings

RESULT
    Returns your parameter PrefBuffer.

BUGS

SEE ALSO
    GetPrefs()


intuition.library/GetPrefs

NAME
    GetPrefs -- Get the current Intuition Preferences structure.

SYNOPSIS
    Prefs = GetPrefs( PrefBuffer, Size )
    D0                A0          D0

    struct Preferences *GetPrefs( struct Preferences *, WORD );

FUNCTION
    Gets a copy of the current Intuition Preferences structure.
    Writes the data into the buffer you specify.  The number of bytes you
    want copied is specified by the size argument.

    It is legal to take a partial copy of the Preferences structure.
    The more pertinent preferences variables have been grouped near
    the top of the structure to facilitate the memory conservation
    that can be had by taking a copy of only some of the Preferences
    structure.

    New for V36:  A new and more extensible method for supplying
    Preferences has been introduced in V36, and relies on file
    system notification.  The Intuition preferences items rely
    also on the IPrefs program.  Certain elements of the
    Preferences structure have been superceded by this new method.
    As much as possible, the Preferences structure returned by
    GetPrefs() reflect the current state of Preferences.  However,
    it is impossible to represent some of the V36-style preferences
    items using the existing Preferences structure.

INPUTS
    PrefBuffer = pointer to the memory buffer to receive your copy of the
       Intuition Preferences
    Size = the number of bytes in your PrefBuffer, the number of bytes
       you want copied from the system's internal Preference settings

RESULT
    Returns your parameter PrefBuffer.

BUGS

SEE ALSO
    GetDefPrefs(), SetPrefs()


intuition.library/GetScreenData

NAME
    GetScreenData -- Get copy of a screen data structure.

SYNOPSIS
    Success = GetScreenData( Buffer, Size, Type, Screen )
    D0                       A0      D0    D1    A1

    BOOL GetScreenData( APTR, UWORD, UWORD, struct Screen * );

FUNCTION
    This function copies into the caller's buffer data from a Screen
    structure.  Typically, this call will be used to find the size, title
    bar height, and other values for a standard screen, such as the
    Workbench screen.

    To get the data for the Workbench screen, one would call:
        GetScreenData(buff, sizeof(struct Screen), WBENCHSCREEN, NULL)

    NOTE: if the requested standard screen is not open, this function
    will have the effect of opening it.

    This function has been useful for two basic types of things:
    1) Determining information about the Workbench screen, in
       preparation for opening a window on it.
    2) Attempts at discerning the user's preferences in a working
       screen, for "cloning" the Workbench modes and dimensions
       when opening a similar custom screen.

    Providing compatibility with both of these goals has proven
    difficult, as we introduce new display modes and screen scrolling
    in V36.  Read carefully the somewhat involved exceptions we
    elected to implement ...

    Changes as of V36:

    For V36 and later, the function LockPubScreen() is an improvement
    over this function, in that it doesn't copy the screen data
    but returns a pointer and a guarantee that the screen will not
    be closed.

    If the global public screen SHANGHAI mode is in effect (see
    SetPubScreenModes() ), this function will actually report on
    the default public screen, where "Workbench" windows will
    actually open.

    For V36 and later, this function does some "compatibility tricks"
    when you inquire about the WBENCHSCREEN.  To keep programs from
    "stumbling" into modes they don't understand, and because an NTSC
    machine may be running a PAL Workbench or PRODUCTIVITY, for example,
    the following "false" information is returned.

    The Screen.ViewPort.Modes field will either be HIRES or HIRES+LACE
    (with the SPRITES flag also set, as usual).  HIRES+LACE is
    used if the display mode selected for the Workbench screen
    is an interlaced screen of any type.

    The dimensions returned will be the *smaller* of the OSCAN_TEXT
    dimensions for the returned mode, and the actual dimensions
    of the Workbench screen.

    EXCEPTION: For specific compatibility considerations, if the
    Workbench is in one of the A2024 modes, the mode returned
    in Screen.ViewPort.Modes will be HIRES+LACE (with perhaps
    some "special" bits also set for future improvement), but
    with dimensions equal to the actual A2024-mode Workbench screen.
    This will favor programs which open windows on the A2024
    Workbench, but will cause some problems for programs which
    try to "clone" the Workbench screen using this function.

    If you want the real information about the modern Workbench
    screen, call LockPubScreen( "Workbench" ) and acquire its
    display mode ID by inquiring of the actual ViewPort (using
    graphics.library/GetVPModeID() ).

    You may then use the information you get to clone as many of
    the properties of the Workbench screen that you wish.

    In the long run, it's probably better to provide your user
    with a screen mode selection option, and skip all this.

INPUTS
    Buffer = pointer to a buffer into which data can be copied
    Size   = the size of the buffer provided, in bytes
    Type   = the screen type, as specified in OpenWindow() (WBENCHSCREEN,
        CUSTOMSCREEN, ...)
    Screen = ignored, unless type is CUSTOMSCREEN, which results only in
        copying 'size' bytes from 'screen' to 'buffer'

RESULT
    TRUE if successful
    FALSE if standard screen of Type 'type' could not be opened.

BUGS
    You cannot support the new V36 display modes using this function.

SEE ALSO
    OpenWindow(), LockPubScreen(), graphics.library/GetVPModeID(),
    SetPubScreenModes(), OpenScreen()


intuition.library/GetScreenDrawInfo

NAME
    GetScreenDrawInfo -- Get pointer to rendering information. (V36)

SYNOPSIS
    DrInfo = GetScreenDrawInfo( Screen )
    D0                          A0

    struct DrawInfo *GetScreenDrawInfo( struct Screen * );

FUNCTION
    Returns a pointer to a DrawInfo structure derived from the
    screen passed.  This data structure is READ ONLY.  The field
    dri_Version identifies which version of struct DrawInfo you
    are given a pointer to.

INPUTS
    Screen        - pointer to a valid, open screen.

RESULT
    DrInfo - pointer to a system-allocated DrawInfo structure,
    as defined in intuition/screens.h.

NOTES
    Some information in the DrawInfo structure may in the future
    be calculated the first time this function is called for a
    particular screen.

    You must call FreeScreenDrawInfo() when you are done using the
    returned pointer.

    This function does not prevent a screen from closing.  Apply it
    only to the screens you opened yourself, or apply a protocol
    such as LockPubScreen().

    WARNING: Until further notice, the pointer returned does not
    remain valid after the screen is closed.

    This function and FreeScreenDrawInfo() don't really do much now,
    but they provide an upward compatibility path.  That means that
    if you misuse them today, they probably won't cause a problem,
    although they may someday later.  So, please be very careful
    only to use the DrawInfo structure between calls to
    GetScreenDrawInfo() and FreeScreenDrawInfo(), and be sure
    that you don't forget FreeScreenDrawInfo().

BUGS
    Does not reflect to changes in screen modes, depth, or pens.

SEE ALSO
    FreeScreenDrawInfo(), LockPubScreen(), intuition/screens.h


intuition.library/InitRequester

NAME
    InitRequester -- Initialize a Requester structure.

SYNOPSIS
    InitRequester( Requester )
                   A0

    VOID InitRequester( struct Requester * );

FUNCTION
    Initializes a requester for general use.  After calling InitRequester,
    you need fill in only those Requester values that fit your needs.
    The other values are set to NULL--or zero--states.

    Note that the example in the early versions of the Intuition
    Reference Manual is flawed because the Requester structure is
    initialized BEFORE InitRequester is called.  Be sure to
    perform your initialization AFTER calling InitRequester.

INPUTS
    Requester = a pointer to a Requester structure

RESULT
    None

BUGS
    Since the publication of the first Intuition Manual to this
    day, most people haven't used this function, and for
    compatibility reasons, we'll never be able to assume that
    they do.  Thus, this function is useless.

SEE ALSO


intuition.library/IntuiTextLength

NAME
    IntuiTextLength -- Return the length (pixel-width) of an IntuiText.

SYNOPSIS
    Length = IntuiTextLength( IText )
    D0                        A0

    LONG IntuiTextLength( struct IntuiText * );

FUNCTION
    This routine accepts a pointer to an instance of an IntuiText
    structure, and returns the length (the pixel-width) of the string
    which that instance of the structure represents.

    NOTE: if the Font pointer of your IntuiText structure is set to NULL,
    you'll get the pixel-width of your text in terms of the current system
    default font.  You may wish to be sure that the field IText->ITextFont
    for 'default font' text is equal to the Font field of the screen it is
    being measured for.

INPUTS
    IText = pointer to an instance of an IntuiText structure

RESULT
    Returns the pixel-width of the text specified by the IntuiText data

BUGS
    Would do better to take a RastPort as argument, so that a NULL in
    the Font pointer would lead automatically to the font for the
    intended target RastPort, rather than the system default font.

SEE ALSO
    OpenScreen()


intuition.library/ItemAddress

NAME
    ItemAddress -- Returns the address of the specified MenuItem.

SYNOPSIS
    Item = ItemAddress( MenuStrip, MenuNumber )
    D0                  A0         D0

    struct MenuItem *ItemAddress( struct Menu *, UWORD );

FUNCTION
    This routine feels through the specified menu strip and returns the
    address of the item specified by the menu number.  Typically,
    you will use this routine to get the address of a menu item from
    a menu number sent to you by Intuition after user has chosen from
    a window's menus.

   This routine requires that the arguments are well-defined.
    MenuNumber may be equal to MENUNULL, in which case this routine returns
    NULL.  If MenuNumber doesn't equal MENUNULL, it's presumed to be a
    valid item number selector for your menu strip, which includes:
       - a valid menu number
       - a valid item number
       - if the item specified by the above two components has a
         sub-item, the menu number may have a sub-item component, too.

    Note that there must be BOTH a menu number and an item number.
    Because a sub-item specifier is optional, the address returned by
    this routine may point to either an item or a sub-item.

INPUTS
    MenuStrip = a pointer to the first menu in your menu strip
    MenuNumber = the value which contains the packed data that selects
       the menu and item (and sub-item).  See the Intuition Reference
        Manual for information on menu numbers.

RESULT
    If MenuNumber == MENUNULL, this routine returns NULL,
    else this routine returns the address of the menu item specified
    by MenuNumber.

BUGS

SEE ALSO
    The "Menus" chapter of the Intuition Reference Manual,
    or the Amiga Rom Kernel Manual


intuition.library/LockIBase

NAME
    LockIBase -- Invoke semaphore arbitration of IntuitionBase.

SYNOPSIS
    Lock = LockIBase( LockNumber )
    D0                D0

    ULONG LockIBase( ULONG );

FUNCTION
    Grabs Intuition internal semaphore so that caller may examine
    IntuitionBase safely.  This function is not a magic "fix all my
    race conditions" panacea.

    The idea here is that you can get the locks Intuition needs before
    such IntuitionBase fields as ActiveWindow and FirstScreen are
    changed, or linked lists of windows and screens are changed.

    Do Not Get Tricky with this entry point, and do not hold these locks
    for long, as all Intuition input processing will wait for you to
    surrender the lock by a call to UnlockIBase().

    NOTE WELL: A call to this function MUST be paired with a subsequent
    call to UnlockIBase(), and soon, please.

    NOTE WELL: Do not call any Intuition functions (nor any graphics,
    layers, dos, or other high-level system function) while
    holding this lock.

INPUTS
    A long unsigned integer, LockNumber, specifies which of Intuition's
    internal locks you want to get.  This parameter should be zero for all
    forseeable uses of this function, which will let you examine active
    fields and linked lists of screens and windows with safety.

RESULT
    Returns another ULONG which should be passed to UnlockIBase() to
    surrender the lock gotten by this call.

BUGS
    This function must not be called while holding any other system locks
    such as layer or LayerInfo locks.

SEE ALSO
    UnlockIBase(), layers.library/LockLayerInfo(),
    exec.library/ObtainSemaphore()


intuition.library/LockPubScreen

NAME
    LockPubScreen -- Prevent a public screen from closing. (V36)

SYNOPSIS
    screen = LockPubScreen( Name )
    D0                      A0

    struct Screen *LockPubScreen( UBYTE * );

FUNCTION
    Prevents a public screen (or the Workbench) from closing
    while you examine it in preparation of opening a visitor window.

    The sequence you use to open a visitor window that needs to
    examine fields in the screen it is about to open on is:
            LockPubScreen()
            ... examine fields ...
            OpenWindow() on public screen
            UnlockPubScreen()
            ... use your window ...
            CloseWindow()

NOTE
    You needn't hold the "pubscreen lock" for the duration that
    your window is opened.  LockPubScreen() basically has the
    same effect as an open visitor window: it prevents the
    screen from being closed.

    If you pass the string "Workbench" or you pass NULL and there
    is no default public screen, the Workbench screen will
    be automatically opened if it is not already present.

INPUTS
    Name = name string for public screen or NULL for default public
    screen.  The string "Workbench" indicates the Workbench
    screen.

RESULT
    Returns pointer to a screen, if successful, else NULL.
    The call can fail for reasons including that the named
    public screen doesn't exist or is in private state.

BUGS

SEE ALSO
    OpenWindow(), UnlockPubScreen(), GetScreenData()


intuition.library/LockPubScreenList

NAME
    LockPubScreenList -- Prevent changes to the system list. (V36)

SYNOPSIS
    List = LockPubScreenList()
    D0

    struct List *LockPubScreenList( VOID );

FUNCTION
    Arbitrates access to public screen list while you quickly
    make a copy of it for display to the user.

    Note that this is intended only for the Public Screen Manager
    program.

NOTES
    The nodes on the list are PubScreenNode structures.
    Act quickly while holding this lock.  The restrictions
    on LockIBase() apply here as well.

INPUTS
    None.

RESULT
    A pointer to the public screen list.

BUGS

SEE ALSO
    OpenScreen(), Intuition V36 update documentation


intuition.library/MakeClass

NAME
    MakeClass -- Create and initialize a boopsi class. (V36)

SYNOPSIS
    iclass = MakeClass( ClassID, SuperClassID, SuperClassPtr,
    D0                  A0       A1            A2
            InstanceSize, Flags )
            D0            D1

    struct IClass *MakeClass( UBYTE *, UBYTE *, struct IClass *,
            UWORD, ULONG );

FUNCTION
    For class implementors only.

    This function creates a new public or private boopsi class.
    The superclass should be defined to be another boopsi class:
    all classes are descendants of the class "rootclass".

    Superclasses can be public or private.  You provide a name/ID
    for your class if it is to be a public class (but you must
    have registered your class name and your attribute ID's with
    Commodore before you do this!).  For a public class, you would
    also call AddClass() to make it available after you have
    finished your initialization.

    Returns pointer to an IClass data structure for your
    class.  You then initialize the Hook cl_Dispatcher for
    your class methods code.  You can also set up special data
    shared by all objects in your class, and point cl_UserData at it.
    The last step for public classes is to call AddClass().

    You dispose of a class created by this function by calling
    FreeClass().

INPUTS
    ClassID = NULL for private classes, the name/ID string for public
            classes
    SuperClassID = name/ID of your new class's superclass.  NULL if
            superclass is a private class
    SuperClassPtr = pointer to private superclass.  Only used if
            SuperClassID is NULL.  You are required never to provide
            a NULL superclass.
    InstanceSize = the size of the instance data that your class's
            objects will require, beyond that data defined for
            your superclass's objects.
    Flags = for future enhancement, including possible additional
            parameters.  Provide zero for now.

RESULT
    Pointer to the resulting class, or NULL if not possible:
    - no memory for class data structure
    - public superclass not found
    - public class of same name/ID as this one already exists

NOTES

EXAMPLE
    Creating a private subclass of a public class:

/* per-object instance data defined by my class     */
struct MyInstanceData {
    ULONG   mid_SomeData;
};

/* some useful table I'll share use for all objects */
UWORD myTable[] = {
    5, 4, 3, 2, 1, 0
};

struct IClass       *
initMyClass()
{
    ULONG __saveds  myDispatcher();
    ULONG   hookEntry();    /* asm-to-C interface glue       */
    struct IClass   *cl;
    struct IClass   *MakeClass();

    if ( cl =  MakeClass( NULL,
                SUPERCLASSID, NULL,  /* superclass is public */
                sizeof (struct MyInstanceData),
                0 ))
    {
        /* initialize the cl_Dispatcher Hook       */
        cl->cl_Dispatcher.h_Entry = hookEntry;
        cl->cl_Dispatcher.h_SubEntry = myDispatcher;
        cl->cl_Dispatcher.h_Data = (VOID *) 0xFACE; /* unused */

        cl-cl_UserData = (ULONG) myTable;
    }
    return ( cl );
}

BUGS
    The typedef 'Class' isn't consistently used.  Class pointers
    used blindly should be APTR, or struct IClass for class implementors.

SEE ALSO
    FreeClass(), AddClass(), RemoveClass(), NewObject(),
    Document "Basic Object-Oriented Programming System for Intuition"
    and the "boopsi Class Reference" document.


intuition.library/MakeScreen

NAME
    MakeScreen -- Do an Intuition-integrated MakeVPort() of a screen.

SYNOPSIS
    MakeScreen( Screen )
                A0

    VOID MakeScreen( struct Screen * );

FUNCTION
    This procedure allows you to do a MakeVPort() for the viewport of your
    custom screen in an Intuition-integrated way.  This way you can
    do your own screen manipulations without worrying about interference
    with Intuition's usage of the same viewport.

    The operation of this function is as follows:
        - Block until the Intuition View structure is not in being changed.
        - Set the view modes correctly to reflect if there is a (visible)
          interlaced screen.
        - call MakeVPort(), passing the Intuition View and your screen's
          ViewPort.
        - Unlocks the Intuition View.

    After calling this routine, you should call RethinkDisplay() to
    incorporate the new viewport of your custom screen into the
    Intuition display.

    NOTE: Intuition may determine that because of a change in global
    interlace needs that all viewports need to be remade, so
    it may effectively call RemakeDisplay().

INPUTS
    Screen = address of the custom screen structure

RESULT
    None

BUGS

SEE ALSO
    RethinkDisplay(), RemakeDisplay(), graphics.library/MakeVPort()


intuition.library/ModifyIDCMP

NAME
    ModifyIDCMP -- Modify the state of a window's IDCMPFlags.

SYNOPSIS
    [Success =] ModifyIDCMP( Window, IDCMPFlags )
    [D0]                     A0      D0

    [BOOL] ModifyIDCMP( struct Window *, ULONG );
    /* returns BOOL in V37 and greater */

FUNCTION
    This routine modifies the state of your window's IDCMP (Intuition
    Direct Communication Message Port).  The state is modified to reflect
    your desires as described by the flag bits in the value IDCMPFlags.

    The four actions that might be taken are:

   - if there is currently no IDCMP in the given window, and IDCMPFlags
     is zero, nothing happens
   - if there is currently no IDCMP in the given window, and any of the
     IDCMPFlags is selected (set), then the IDCMP of the window is
     created, including allocating and initializing the message ports
     and allocating a signal bit for your port.  See the "Input and
     Output Methods" chapter of the Intuition Reference Manual for full
      details
   - if the IDCMP for the given window exists, and the
     IDCMPFlags argument is zero, this says that you want
     Intuition to close the ports, free the buffers and free
     your signal bit.  You MUST be the same task that was active
     when this signal bit was allocated (either by ModifyIDCMP()
      or OpenWindow() ).
   - if the IDCMP for the given window is opened, and the IDCMPFlags
     argument is not zero, this means that you want to change the
     state of which events will be broadcast to you through the IDCMP

    NOTE:  You can set up the Window->UserPort to any port of your own
    before you call ModifyIDCMP().  If IDCMPFlags is non-null but
    your UserPort is already initialized, Intuition will assume that
    it's a valid port with task and signal data preset and Intuition
    won't disturb your set-up at all, Intuition will just allocate
    the Intuition message port half of it.  The converse is true
    as well:  if UserPort is NULL when you call here with
    IDCMPFlags == NULL, Intuition will deallocate only the Intuition
    side of the port.

    This allows you to use a port that you already have allocated:
    - OpenWindow() with IDCMPFlags equal to NULL (open no ports)
    - set the UserPort variable of your window to any valid port of your
      own choosing
    - call ModifyIDCMP with IDCMPFlags set to what you want
    - then, to clean up later, set UserPort equal to NULL before calling
      CloseWindow() (leave IDCMPFlags alone)  BUT FIRST: you must make
      sure that no messages sent your window are queued at the port,
      since they will be returned to the memory free pool.

    For an example of how to close a window with a shared IDCMP,
    see the description for CloseWindow().

INPUTS
    Window = pointer to the Window structure containing the IDCMP ports
    IDCMPFlags = the flag bits describing the new desired state of the
                 IDCMP

RESULT
    Starting in V37, this function returns NULL if it was unable
    to create the necessary message ports.  (The possibility of
    failure exists in earlier releases, but no return code was offered).
    Do not check the return code under V36 or earlier.

BUGS

SEE ALSO
    OpenWindow(), CloseWindow()


intuition.library/ModifyProp

NAME
    ModifyProp -- Modify the current parameters of a proportional gadget.

SYNOPSIS
    ModifyProp( Gadget, Window, Requester,
                A0      A1      A2
                Flags, HorizPot, VertPot, HorizBody, VertBody )
                D0     D1        D2       D3         D4

    VOID ModifyProp( struct Gadget *, struct Window *,
            struct Requester *, UWORD, UWORD, UWORD, UWORD, UWORD );

FUNCTION
    Modifies the parameters of the specified proportional gadget.  The
    gadget's internal state is then recalculated and the imagery
    is redisplayed in the window or requester that contains the gadget.

    The requester variable can point to a requester structure.  If the
    gadget has the GTYP_REQGADGET flag set, the gadget is in a requester
    and the window pointer must point to the window of the requester.
    If this is not the gadget of a requester, the requester argument may
    be NULL.

    NOTE: this function causes all gadgets from the proportional
    gadget to the end of the gadget list to be refreshed, for
    reasons of compatibility.
    For more refined display updating, use NewModifyProp().

    New for V36: ModifyProp() refreshing consists of redrawing gadgets
    completely.  NewModifyProp() has changed this behavior (see
    NewModifyProp()).

INPUTS
    PropGadget = pointer to a proportional gadget
    Window = pointer to the window containing the gadget or the window
        containing the requester containing the gadget.
    Requester = pointer to a requester (may be NULL if this isn't
        a requester gadget)
    Flags = value to be stored in the Flags field of the PropInfo
    HorizPot = value to be stored in the HorizPot field of the PropInfo
    VertPot = value to be stored in the VertPot field of the PropInfo
    HorizBody = value to be stored in the HorizBody field of the PropInfo
    VertBody = value to be stored in the VertBody field of the PropInfo

RESULT
    None

BUGS

SEE ALSO
    NewModifyProp()
    The Intuition Reference Manual and Amiga Rom Kernel Manual contain
    more information on Proportional Gadgets.


intuition.library/MoveScreen

NAME
    MoveScreen -- Attempt to move the screen by the increments provided.

SYNOPSIS
    MoveScreen( Screen, DeltaX, DeltaY )
                A0      D0      D1

    VOID MoveScreen( struct Screen *, WORD, WORD );

FUNCTION
    Moves the screen the specified increment, specified in screen
    pixel resolution coordinates.

    New for V36: Screen movement limits have been greatly relaxed,
    to support screen scrolling.  In particular, negative values
    for screen LeftEdge and TopEdge may now be valid.

   If the DeltaX and DeltaY variables you specify would move the screen
   in a way that violates any restrictions, the screen will be moved
   as far as possible.  You may examine the LeftEdge and TopEdge fields
    of the Screen structure after this function returns to see where
    the screen really ended up.

    In operation, this function determines what the resulting position
    values that are actually to be used, sets these up, and calls
    MakeScreen() and RethinkDisplay().

INPUTS
    Screen = pointer to a Screen structure
    DeltaX = amount to move the screen on the x-axis
            Note that DeltaX no longer (V36) need be set to zero
    DeltaY = amount to move the screen on the y-axis
            Note that these coordinates are in the same resolution
            as the screen (such as HIRES or INTERLACE)

RESULT
    None

BUGS

SEE ALSO
    RethinkDisplay()


intuition.library/MoveWindow

NAME
    MoveWindow -- Ask Intuition to move a window.

SYNOPSIS
    MoveWindow( Window, DeltaX, DeltaY )
                A0      D0      D1

    VOID MoveWindow( struct Window *, WORD, WORD );

FUNCTION
    This routine sends a request to Intuition asking to move the window
    the specified distance.  The delta arguments describe how far to
    move the window along the respective axes.

    Note that the window will not be moved immediately, but rather
    will be moved the next time Intuition receives an input event,
    which happens currently at a minimum rate of ten times per second,
    and a maximum of sixty times a second.

    Interactions with other arbitration of Intuition data structures
    may defer this operation longer.  For V36, you can use the new
    IDCMP class IDCMP_CHANGEWINDOW to detect when this operation has
    completed.

    New for V36: Intuition now will do validity checking on the final
    position.  To send absolute movements, or to move and size a
    window in one step, use ChangeWindowBox().

INPUTS
    Window = pointer to the structure of the Window to be moved
    DeltaX = how far to move the Window on the x-axis
    DeltaY = how far to move the Window on the y-axis

RESULT
    None

BUGS

SEE ALSO
    ChangeWindowBox(), SizeWindow(), WindowToFront(), WindowToBack()


intuition.library/MoveWindowInFrontOf

NAME
    MoveWindowInFrontOf -- Arrange the relative depth of a window. (V36)

SYNOPSIS
    MoveWindowInFrontOf( Window, BehindWindow )
                         A0      A1

    VOID MoveWindowInFrontOf( struct Window *, struct Window * );

FUNCTION
    Depth-arranges a window in front of an another window.
    Brings out the layers.library MoveLayerInFrontOf() to the
    Intuition user.

INPUTS
    Window =  window to re-position in front of another window
    BehindWindow =  window to re-position in front of

RESULT
    Repositions window.

BUGS
    Doesn't respect backdrop windows.

SEE ALSO
    WindowToFront(), WindowToBack(), layers.library/MoveLayerInFrontOf()


intuition.library/NewModifyProp

NAME
    NewModifyProp -- ModifyProp(), but with selective refresh.

SYNOPSIS
    NewModifyProp( Gadget, Window, Requester, Flags,
                   A0      A1      A2         D0
            HorizPot, VertPot, HorizBody, VertBody, NumGad )
            D1        D2       D3         D4        D5

    VOID NewModifyProp( struct Gadget *, struct Window *,
            struct Requester *, UWORD, UWORD, UWORD, UWORD, UWORD, WORD );

FUNCTION
    Performs the function of ModifyProp(), but refreshes
    gadgets in the list as specified by the NumGad parameter.
    With NumGad = -1, this function is identical to ModifyProp().

    New for V36: When NumGad = 1, this function will now perform
    an incremental update of the proportional gadget knob image,
    rather than refreshing the entire gadget.  This means much
    less flashing when programmatically scrolling a proportional
    gadget.

INPUTS
    PropGadget = pointer to a proportional gadget
    Window = pointer to the window containing the gadget or the window
        containing the requester containing the gadget.
    Requester = pointer to a requester (may be NULL if this isn't
        a requester gadget)
    Flags = value to be stored in the Flags field of the PropInfo
    HorizPot = value to be stored in the HorizPot field of the PropInfo
    VertPot = value to be stored in the VertPot field of the PropInfo
    HorizBody = value to be stored in the HorizBody field of the PropInfo
    VertBody = value to be stored in the VertBody field of the PropInfo
    NumGad = number of gadgets to be refreshed after propgadget internals
        have been adjusted.  -1 means "to end of list."

RESULT
    None

BUGS

SEE ALSO
    ModifyProp()
    The Intuition Reference Manual contains more information on
    Proportional Gadgets.


intuition.library/NewObject

NAME
    NewObjectA -- Create an object from a class. (V36)
    NewObject -- Varargs stub for NewObjectA(). (V36)

SYNOPSIS
    object = NewObjectA( class, classID, tagList )
    D0                   A0     A1       A2

    APTR NewObjectA( struct IClass *, UBYTE *, struct TagItem * );

    object = NewObject( class, classID, Tag1, ... )

    APTR NewObject( struct IClass *, UBYTE *, ULONG, ... );

FUNCTION
    This is the general method of creating objects from 'boopsi' classes.
    ('Boopsi' stands for "basic object-oriented programming system for
    Intuition".)

    You specify a class either as a pointer (for a private class) or
    by its ID string (for public classes).  If the class pointer
    is NULL, then the classID is used.

    You further specify initial "create-time" attributes for the
    object via a TagItem list, and they are applied to the resulting
    generic data object that is returned.  The attributes, their meanings,
    attributes applied only at create-time, and required attributes
    are all defined and documented on a class-by-class basis.

INPUTS
    class = abstract pointer to a boopsi class gotten via MakeClass().
    classID = the name/ID string of a public class.  This parameter is
            only used if 'class' is NULL.
    tagList = pointer to array of TagItems containing attribute/value
            pairs to be applied to the object being created

RESULT
    A boopsi object, which may be used in different contexts such
    as a gadget or image, and may be manipulated by generic functions.
    You eventually free the object using DisposeObject().

NOTES
    This function invokes the OM_NEW "method" for the class specified.

BUGS
    Typedef's for 'Object' and 'Class' are defined in the include
    files but not used consistently.  The generic type APTR is
    probably best used for object and class "handles", with the
    type (UBYTE *) used for classID strings.

SEE ALSO
    DisposeObject(), SetAttrs(), GetAttr(), MakeClass(),
    Document "Basic Object-Oriented Programming System for Intuition"
    and the "boopsi Class Reference" document.


intuition.library/NextObject

NAME
    NextObject -- iterate through the object on an Exec list. (V36)

SYNOPSIS
    object = NextObject( objectPtrPtr )
    D0                   A0

    APTR NextObject( APTR );

FUNCTION
    This function is for boopsi class implementors only.

    When you collect a set of boopsi objects on an Exec List
    structure by invoking their OM_ADDMEMBER method, you
    can (only) retrieve them by iterations of this function.

    Works even if you remove and dispose the returned list
    members in turn.

INPUTS
    Initially, you set a pointer variable to equal the
    lh_Head field of the list (or mlh_Head field of a MinList).
    You pass the *address* of that pointer repeatedly
    to NextObject() until it returns NULL.

EXAMPLE

    /* here is the OM_DISPOSE case of some class's dispatcher */
    case OM_DISPOSE:
        /* dispose members  */
        object_state = mydata->md_CollectionList.lh_Head;
        while ( member_object = NextObject( &object_state ) )
        {
            DoMethod( member_object, OM_REMOVE ); /* remove from list */
            DM( member, msg );      /* and pass along dispose       */
        }

RESULT
    Returns pointers to each object in the list in turn, and NULL
    when there are no more.

NOTES

BUGS

SEE ALSO
    DisposeObject(), SetAttrs(), GetAttr(), MakeClass(),
    Document "Basic Object-Oriented Programming System for Intuition"
    and the "boopsi Class Reference" document.


intuition.library/NextPubScreen

NAME
    NextPubScreen -- Identify next public screen in the cycle. (V36)

SYNOPSIS
    Buff = NextPubScreen( Screen, NameBuff )
    D0                    A0      A1

    UBYTE *NextPubScreen( struct Screen *, UBYTE * );

FUNCTION
    Returns name of next public screen in system rotation, to
    allow visitor windows to provide function to "jump" among
    public-screens in a cycle.

INPUTS
    Screen = pointer to the screen your window is currently open in,
      or NULL, if you don't have a pointer to a public screen.
    NameBuff = pointer to a buffer of MAXPUBSCREENNAME+1 characters,
      for Intuition to fill in with the name of the next public
      screen in rotation.

RESULT
    Returns NULL if there are no public screens, otherwise a
    pointer to your NameBuff.

NOTES
    There is no guarantee that the public screen whose name
    was returned by this function will exist or be in "public" state
    by the time you call LockPubScreen(), etc.  You must handle
    cases where LockPubScreen(), etc. will fail.

BUGS
    Due to a bug, your buffer needs to be (MAXPUBSCREENNAME + 1)
    characters big, which is one more than originally documented.

    The starting screen and cycle order of the public screens isn't
    defined, so do not draw conclusions about the order you
    see in the current version of Intuition.  We reserve the
    right to add meaning to the ordering at a future time.

SEE ALSO
    OpenScreen(), Intuition V36 update documentation


intuition.library/ObtainGIRPort

NAME
    ObtainGIRPort -- Set up a RastPort for a custom gadget. (V36)

SYNOPSIS
    RPort = ObtainGIRPort( GInfo )
    D0                     A0

    struct RastPort *ObtainGIRPort( struct GadgetInfo * );

FUNCTION
    Sets up a RastPort for use (only) by custom gadget hook routines.
    This function must be called EACH time a hook routine needing
    to perform gadget rendering is called, and must be accompanied
    by a corresponding call to ReleaseGIRPort().

    Note that if a hook function passes you a RastPort pointer,
    e.g., GM_RENDER, you needn't call ObtainGIRPort() in that case.

INPUTS
    A pointer to a GadgetInfo structure, as passed to each custom
    gadget hook function.

RESULT
    A pointer to a RastPort that may be used for gadget rendering.
    This pointer may be NULL, in which case you should do no rendering.
    You may (optionally) pass a null return value to ReleaseGIRPort().

BUGS

SEE ALSO
    ReleaseGIRPort(), Custom Gadget documentation


intuition.library/OffGadget

NAME
    OffGadget -- Disable the specified gadget.

SYNOPSIS
    OffGadget( Gadget, Window, Requester )
               A0      A1      A2

    VOID OffGadget( struct Gadget *, struct Window *,
            struct Requester * );

FUNCTION
    This command disables the specified gadget.  When a gadget is
    disabled, these things happen:
         - its imagery is displayed ghosted
         - the GFLG_DISABLED flag is set
         - the gadget cannot be selected by User

    The window parameter must point to the window which contains the
    gadget, or which contains the requester that contains the gadget.
    The requester parameter must only be valid if the gadget has the
    GTYP_REQGADGET flag set, a requirement for all requester gadgets.

   NOTE:  it's never safe to tinker with the gadget list yourself.  Don't
   supply some gadget that Intuition hasn't already processed in
   the usual way.

    NOTE: for compatibility reasons, this function will refresh all
    gadgets in a requester, and all gadgets from gadget to the
    end of the gadget list if gadget is in a window.

    If you want to improve on this behavior, you may perform the
    equivalent operation yourself: remove a gadget or gadgets,
    change the state of their GFLG_DISABLED flag, replace the
    gadgets using AddGList(), and selectively call RefreshGList().

INPUTS
    Gadget = pointer to the gadget that you want disabled
    Window = pointer to a window structure containing the gadget or
        containing the requester which contains the gadget
    Requester = pointer to a requester (may by NULL if this isn't
       a requester gadget (i.e. GTYP_REQGADGET is not set)).

RESULT
    None

BUGS

SEE ALSO
    AddGadget(), RefreshGadgets()


intuition.library/OffMenu

NAME
    OffMenu -- Disable the given menu or menu item.

SYNOPSIS
    OffMenu( Window, MenuNumber )
             A0      D0

    VOID OffMenu( struct Window *, UWORD );

FUNCTION
    This command disables a sub-item, an item, or a whole menu.
    This depends on the contents of the data packed into MenuNumber,
    which is described in the Intuition Reference Manual.

INPUTS
    Window = pointer to the window
    MenuNumber = the menu piece to be disabled

RESULT
    None

BUGS

SEE ALSO
    OnMenu(), ResetMenuStrip()


intuition.library/OnGadget

NAME
    OnGadget -- Enable the specified gadget.

SYNOPSIS
    OnGadget( Gadget, Window, Requester )
              A0      A1      A2

    VOID OnGadget( struct Gadget *, struct Window *,
            struct Requester * );

FUNCTION
    This command enables the specified gadget.  When a gadget is
    enabled, these things happen:
    - its imagery is displayed normally (not ghosted)
    - the GFLG_DISABLED flag is cleared
    - the gadget can thereafter be selected by the user

    The window parameter must point to the window which contains the
    gadget, or which contains the requester that contains the gadget
    The requester parameter must only be valid if the gadget has the
    GTYP_REQGADGET flag set, a requirement for all requester gadgets.

   NOTE:  it's never safe to tinker with the gadget list yourself.  Don't
   supply some gadget that Intuition hasn't already processed in
   the usual way.

    NOTE: for compatibility reasons, this function will refresh all
    gadgets in a requester, and all gadgets from gadget to the
    end of the gadget list if gadget is in a window.

    If you want to improve on this behavior, you may perform the
    equivalent operation yourself: remove a gadget or gadgets,
    change the state of their GFLG_DISABLED flag, replace the
    gadgets using AddGList(), and selectively call RefreshGList().

INPUTS
    Gadget = pointer to the gadget that you want disabled
    Window = pointer to a window structure containing the gadget or
        containing the requester which contains the gadget
    Requester = pointer to a requester (may by NULL if this isn't
       a requester gadget (i.e. GTYP_REQGADGET is not set)).

RESULT
    None

BUGS

SEE ALSO


intuition.library/OnMenu

NAME
    OnMenu -- Enable the given menu or menu item.

SYNOPSIS
    OnMenu( Window, MenuNumber )
            A0      D0

    VOID OnMenu( struct Window *, UWORD );

FUNCTION
    This command enables a sub-item, an item, or a whole menu.
    This depends on the contents of the data packed into MenuNumber,
    which is described in the Intuition Reference Manual.

INPUTS
    Window = pointer to the window
    MenuNumber = the menu piece to be enables

RESULT
    None

BUGS

SEE ALSO
    OffMenu(), ResetMenuStrip()


intuition.library/OpenScreen

NAME
    OpenScreen -- Open an Intuition screen.

SYNOPSIS
    Screen = OpenScreen( NewScreen )
    D0                   A0

    struct Screen *OpenScreen( struct NewScreen * );

    or

    struct Screen *OpenScreen( struct ExtNewScreen * );

FUNCTION
    Opens an Intuition screen according to the specified parameters
    found in the NewScreen structure.

    Does all the allocations, sets up the screen structure and all
    substructures completely, and links this screen's viewport into
    Intuition's View structure.

    Before you call OpenScreen(), you must initialize an instance of
    a NewScreen structure.  NewScreen is a structure that contains
    all of the arguments needed to open a screen.  The NewScreen
    structure may be discarded immediately after OpenScreen() returns.

    The SHOWTITLE flag is set to TRUE by default when a screen is opened.
    To change this, you must call the routine ShowTitle().

INPUTS
    NewScreen = pointer to an instance of a NewScreen structure.

    New for V36:
    In addition to the information contained in the NewScreen structure,
    Intuition now recognizes extended data passed in the form
    of an array of TagItem structures (from <utility/tagitem.h>),
    commonly called a "tag list."

    There are two ways to provide this array.  The first is to
    use the new Intuition entry point OpenScreenTagList() and
    pass the tag list as a parameter.  This is the recommended
    method, and has a convenient format variation for C programs
    using a variable number of arguments.

    An older way used for some V36 development uses the OpenScreen()
    entry point, and an extension of the NewScreen structure named
    ExtNewScreen.  See the documentation of the flag NS_EXTENDED,
    below.

    While we recommend that you use OpenScreenTagList() rather than
    OpenScreen() when using the extension tag list, we document
    the tag ID values here, so that all parameters for opening
    a screen can be found in one place.

    NewScreen is initialized with the following information:
    -------------------------------------------------------------
    Left = initial x-position of your screen (should be zero for
    releases prior to V36)

    Top = initial y-position of the opening screen
    (Note: Left and Top are specified relative to the Intuition's view,
    in same resolution as the screen pixels.)

    Width = the width for this screen's RastPort

    Height = the height for his screen's RastPort, or the constant
            STDSCREENHEIGHT to get the current default height (at
            this time guaranteed to be at least 200 rows).  The normal
            width and height for a particular system is stored by
            the graphics.library in GfxBase->NormalDisplayRows and
            GfxBase->NormalDisplayColumns.  These values will be different
            depending on factors such as PAL video and overscan.

            For V36, a new constant STDSCREENWIDTH is introduced.  It
            serves the similar function for screen width.  Both
            STDSCREENWIDTH and STDSCREENHEIGHT indicate that your
            screen RastPort is to be the same dimensions as your
            DisplayClip rectangle.  If you do not specify either a
            standard or custom DisplayClip, the OSCAN_TEXT region
            will be used, which corresponds to the standard dimensions
            of V35 and earlier.

            Furthermore, if you are using OpenScreenTagList(), and you
            specify STDSCREENWIDTH, and you DO NOT provide a NewScreen
            pointer, and you DO NOT provide SA_Left, then Intuition
            will automatically set the LeftEdge of the screen to
            be the left edge of the screen's DisplayClip region.
            Likewise for STDSCREENHEIGHT and the screen's TopEdge.

    Depth = number of bitplanes

    DetailPen = pen number for details (like gadgets or text in title bar)
        The common value for this pen is 0.

    BlockPen = pen number for block fills (like title bar)
        The common value for this pen is 1.

    Type = screen type values
        Set these flags as desired from the set:
        CUSTOMSCREEN -- this is your own screen, not a system screen.
        CUSTOMBITMAP -- this custom screen has bit maps supplied
            in the bitmap field of the NewScreen structure.  Intuition is
            not to allocate any raster bitmaps.
        SCREENBEHIND -- your screen will be created behind all other open
            screens.  This allows a program to prepare imagery in the
            screen, change its colors, and so on, bringing it to the
            front when it is presentable.
        SCREENQUIET -- Intuition will not render system screen gadgets or
            screen title.  In concert with the WFLG_RMBTRAP flag on all
            your screen's windows, this flag will prevent Intuition from
            rendering into your screen's bitplanes.  Without WFLG_RMBTRAP
            (or using the IDCMP_MENUVERIFY facility to cancel menu
            operations), this flag will prevent Intuition from clearing
            your menu bar, which is probably unacceptable.  The menu bar
            layer may still overwrite  a portion of your screen bitmap
            when the screen is opened.  (V36: it won't clobber your bits
            any more.)
        NS_EXTENDED for this screen to use extended attributes pointed
            to by the 'Extended' field, below.

    ViewModes = the appropriate argument for the data type ViewPort.Modes.
       These include:
       HIRES for this screen to be HIRES width.
       INTERLACE for the display to switch to interlace.
       SPRITES for this screen to use sprites (the pointer
            sprite is always displayed)
       DUALPF for dual-playfield mode (not supported yet)
        [For V36: The ViewModes field is superceded by a TagItem with
        tag value SA_DisplayID.]

    Font = pointer to the default TextAttr structure for text in this
        screen and all windows that open in this screen.  Text that uses
        this TextAttr includes title bars of both screen and windows,
        string gadgets, and menu titles.  Of course, IntuiText that
        specifies a NULL TextAttr field will use the screen/window default
        fonts.  NOTE: Intuition will *NOT* call OpenDiskFont(), so
        the TextAttr you supply must be in memory.  The ways to ensure
        that are to either use a ROM font (Topaz 8 or 9) or first
        call OpenDiskFont() to load the font, and don't close it
        until after your screen is successfully opened.
        [For V36: this is superceded by SA_Font and SA_SysFont.]

    DefaultTitle = pointer to a line of text that will be displayed along
        the screen's title bar.  Null terminated, or just a NULL pointer
       to get no text
        [For V36: superceded by SA_Title.]

    Gadgets = This field should be set to NULL, since no user gadgets may
        be attached to a screen with the current versions of Intuition.

    CustomBitMap = if you're not supplying a custom bitmap, this value is
       ignored.  However, if you have your own display memory that you
       want used for this screen, the CustomBitMap field should point to
        the BitMap structure that describes your display memory.  See the
       "Screens" chapter and the "Amiga ROM Kernel Manual" for more
       information about bitmaps.
        [For V36: this is superceded by SA_BitMap.]

    [ All TagItem extensions below are new for V36.]
    Extension = if NS_EXTENDED is set in NewScreen.Type, this pointer
        should point to an array (or chain of arrays) of TagItems,
        as defined in the include file <utility/tagitem.h>.   This
        field is only defined in the structure ExtNewScreen.
        The values to use for TagItem.ti_Tag are defined below.  We
        recommend that V36-specific applications use the new Intuition
        entry point OpenScreenTagList(), rather than using this field.
        The ExtNewScreen structure is a convenient way to give V36
        Intuition some information that V34 and earlier Intuition will
        ignore.

        Each TagItem is an optional tagged data structure which identifies
        an additional parameter to OpenScreen().  The applicable tag ID
        values for TagItem.ti_Tag and their corresponding data follow.

        Several of the tag items are alternative (and overriding) versions
        to familiar fields in NewScreen.  They are:

    SA_Left
    SA_Top
    SA_Width
    SA_Height
    SA_Depth
    SA_DetailPen
    SA_BlockPen
    SA_Title
    SA_Font
    SA_Type
    SA_BitMap (whose existence also implies CUSTOMBITMAP).

        Several tags are Booleans, which means that depending on whether
        their corresponding ti_Data field is zero (FALSE) or non-zero
        (TRUE), they specify Boolean attributes.  The ones corresponding
        to Boolean flags in the NewScreen.Type field are:

    SA_ShowTitle
    SA_Behind (equiv. to SCREENBEHIND)
    SA_Quiet (equiv. to SCREENQUIET)

        The following tags provide extended information to Intuition
        when creating a screen:

    SA_DisplayID: ti_Data is a 32-bit extended display mode ID
        as defined in <graphics/displayinfo.h>

    SA_Overscan: ti_Data contains a defined constant specifying
        one of the system standard overscan dimensions appropriate for
        the display mode of the screen.  Used with the Width and
        Height dimensions STDSCREENWIDTH and STDSCREEN, this makes
        it trivial to open an overscanned or standard dimension
        screen.  You may also hand-pick your various dimensions
        for overscanned or other screens, by specifying screen position
        and dimensions explicitly, and by using SA_DClip to explicitly
        specify an overscanned DisplayClip region.

        The values for ti_Data of this tag are as follows:

        OSCAN_TEXT - Text Overscan region.  A region which is completely
        on screen and readable ("text safe").  A preferences data
        setting, this is backward equivalent with the old MoreRows,
        and specifies the DisplayClip and default dimensions of the
        Workbench screen.  This is the default.

        OSCAN_STANDARD - Also a preferences setting, this specifies
        a rectangle whose edges are "just out of view."  This yields
        the most efficient position and dimensions of on-monitor
        presentations, such as games and artwork.

        OSCAN_MAX - This is the largest rectangular region that the
        graphics library can handle "comfortably" for a given mode.
        Screens can smoothly scroll (hardware pan) within this region,
        and any DisplayClip or Screen region within this rectangle
        is also legal.  It is not a preferences item, but reflects
        the limits of the graphics hardware and software.

        OSCAN_VIDEO - This is the largest region that the graphics
        library can display, comfortable or not.  There is no guarantee
        that all smaller rectangles are valid.  This region is
        typically out of sight on any monitor or TV, but provides our
        best shot at "edge-to-edge" video generation.

        Remember, using overscan drastically effects memory use and
        chip memory bandwidth.  Always use the smallest (standard)
        overscan region that works for your application.

    SA_DClip: ti_Data is a pointer to a rectangle which explicitly
        defines a DisplayClip region for this screen.  See QueryOverscan()
        for the role of the DisplayClip region.

        Except for overscan display screens, this parameter is
        unnecessary, and specifying a standard value using SA_Overscan
        is normally an easier way to get overscan.

    SA_AutoScroll: this is a Boolean tag item, which specifies that
        this screens is to scroll automatically when the mouse pointer
        reaches the edge of the screen.  The operation of this requires
        that the screen dimensions be larger than its DisplayClip
        region.

    SA_PubName: If this field is present (and ti_Data is non-NULL),
        it means that the screen is a public screen, and that
        the public screen name string is pointed to by ti_Data.
        Public screens are opened in "PRIVATE" mode and must
        be made public using PubScreenStatus().

    SA_Pens: The ti_Data field (if non-NULL) points to a UWORD
        array of pen specification, as defined for struct DrawInfo.
        This array will be used to initialize the screen's
        DrawInfo.dri_Pens array.

        SA_Pens is also used to decide that a screen is ready
        to support the full-blown "new look" graphics.  If you
        want the 3D embossed look, you must provide this tag,
        and the ti_Data value cannot be NULL.  If it points
        to a "minimal" array, containing just the terminator ~0,
        you can specify "new look" without providing any values
        for the pen array.

    The following two tag items specify the task and signal to be issued
    to notify when the last "visitor" window closes on a public screen.
    This support is to assist envisioned public screen manager programs.

    SA_PubTask:  Task to be signalled.  If absent (and SA_PubSig is
        valid), use the task which called OpenScreen() or
        OpenScreenTagList()).

    SA_PubSig:  Data is a UBYTE signal number (not flag) used to notify
        a task when the last visitor window closes on a public screen.

    SA_Colors: ti_Data points to an array of ColorSpec structures
        (terminated with ColorIndex = -1) which specify initial
        values of the screen's color palette.

    SA_FullPalette: this is a Boolean attribute.  Prior to V36, there
        were just 7 RGB color values that Intuition maintained
        in its user preferences (playfield colors 0-3, and colors
        17-19 for the sprite).  When opening a screen, the color
        map for the screens viewport is first initialized by
        graphics (graphics.library/GetColorMap()) then these
        seven values are overridden to take the preferences values.

        In V36, Intuition maintains a full set of 32 preferences colors.
        If you specify TRUE for SA_FullPalette, Intuition will
        override ALL color map entries with its full suite of
        preferred colors.

    SA_ErrorCode: ti_Data points to a ULONG in which Intuition will
        stick an extended error code if OpenScreen[TagList]() fails.
        Values are of this include 0, for success, and:
        OSERR_NOMONITOR     - monitor for display mode not available.
        OSERR_NOCHIPS       - you need newer custom chips for display mode.
        OSERR_NOMEM         - couldn't get normal memory
        OSERR_NOCHIPMEM     - couldn't get chip memory
        OSERR_PUBNOTUNIQUE  - public screen name already used
        OSERR_UNKNOWNMODE   - don't recognize display mode requested

        NOTE: These values are not the same as some similar return
        values defined in graphics.library/ModeNotAvailable().

    SA_SysFont: ti_Data selects one of the system standard fonts
        specified in preferences.  This tag item overrides the
        NewScreen.Font field and the SA_Font tag item.

        Values recognized in ti_Data at present are:
            0 - old DefaultFont, fixed-width, the default.
            1 - Workbench screen preferred font.  You have to
                be very font sensitive to handle a proportional or
                larger than traditional screen font.

        NOTE WELL: if you select sysfont 1, windows opened on
        your screen will not inherit the screen font, but rather
        the window RastPort will be initialized to the old-style
        DefaultFont (sysfont 0).

RESULT
    If all is well, returns the pointer to your new screen
    If anything goes wrong, returns NULL, with further error
    specification in the variable pointed to by the SA_ErrorCode
    data field (V36 and later).

NOTE
    By default, AmigaDOS requesters related to your process are put on
    the Workbench screen (these are messages like "Disk Full").  If
    you wish them to show up on custom screens, DOS must be told.
    This fragment shows the procedure.  More information is available
    in the AmigaDOS manuals.  Sample code fragment:

    #include "libraries/dosextens.h"
            ...
    struct Process *process;
    struct Window   *window;
    APTR            temp;
            ...
            process = (struct Process *) FindTask(NULL);
            temp = process->pr_WindowPtr;   (save old value)
            process->pr_WindowPtr = (APTR) window;
            ( use a pointer to any open window on your screen )
                    ...
            your code goes here
                    ...
            process->pr_WindowPtr = temp;
            ( restore value BEFORE CloseWindow() )
            CloseWindow(window);

BUGS

SEE ALSO
    OpenScreenTagList(), OpenWindow(), PrintIText(), CloseScreen(),
    QueryOverscan() PubScreenStatus(), The Intuition Reference Manual,
    utility/tagitem.h, graphics.library/ModeNotAvailable(),
    diskfont.library/OpenDiskFont(), graphics.library/GetColorMap()


intuition.library/OpenScreenTagList

NAME
    OpenScreenTagList -- OpenScreen() with TagItem extension array. (V36)
    OpenScreenTags -- Varargs stub for OpenScreenTagList. (V36)

SYNOPSIS
    Screen = OpenScreenTagList( NewScreen, TagItems )
    D0                          A0         A1

    struct Screen *OpenScreenTagList( struct NewScreen *,
            struct TagItem * );

    Screen = OpenScreenTags( NewScreen, Tag1, ... )

    struct Screen *OpenScreenTags( struct NewScreen *,
            ULONG, ... );

FUNCTION
    Provides an extension to the parameters passed to OpenScreen().
    This extensions is in the form of (a pointer to) an array of
    TagItem structures, which have to fields: ti_Tag, an ID identifying
    the meaning of the other field, ti_Data.  See <utility/tagitem.h>.

    The tag items can supplement or override the values in NewScreen.
    In fact, you can pass a NULL value of the NewScreen pointer.
    For that matter, if you pass NULL in both arguments, you'll get
    a screen with defaults in all fields, including display mode,
    depth, colors, dimension, title, and so on.  We ask that
    you at least supply a title when you open a screen.

    See OpenScreen() documentation for parameter specifications.

INPUTS
    NewScreen     - (optional) pointer to a NewScreen structure.
    TagItems      - (optional) pointer to (an array of) TagItem
                    structures, terminated by the value TAG_END.

RESULT
    Screen     - an open Intuition screen.  See OpenScreen() for
            extended error codes when Screen is returned NULL.

EXAMPLE
    The version using a variable number of arguments must be
    created for each particular compiler, and may not have
    an analogue in all versions.  For vanilla, 32-bit C
    parameter passing conventions, this works (and will
    appear in amiga.lib):

    struct Screen      *
    OpenScreenTags( ns, tag1 )
    struct NewScreen  *ns;
    ULONG                   tag1;
    {
        struct Screen  *OpenScreenTagList();

        return ( OpenScreenTagList( ns, (struct TagItem *) &tag1 ) );
    }

NOTES
    We recommend this extension to OpenScreen() over using the
    field ExtNewScreen.Extension.  However, the ExtNewScreen.Extension
    is a convenient way to supply a few tags to V36 Intuition which
    will be ignored by V34 Intuition.  See OpenScreen() documentation
    for lots of details.

BUGS

SEE ALSO
    OpenScreen()


intuition.library/OpenWindow

NAME
    OpenWindow -- Open an Intuition window.

SYNOPSIS
    Window = OpenWindow( NewWindow )
    D0                   A0

    struct Window *OpenWindow( struct NewWindow * );

FUNCTION
    Opens an Intuition window of the given dimensions and position,
    with the properties specified in the NewWindow structure.
    Allocates everything you need to get going.

    New for V36: there is an extensive discussion of public Screens
    and visitor windows at the end of this section.  Also,
    you can provide extensions to the NewWindow parameters using
    and array of TagItem structures.  See the discussion below,
    and the documentation for the function OpenScreenTagList().

    Before you call OpenWindow(), you must initialize an instance of
    a NewWindow structure.  NewWindow is a structure that contains
    all of the arguments needed to open a window.  The NewWindow
    structure may be discarded immediately after it is used to open
    the window.

    If Type == CUSTOMSCREEN, you must have opened your own screen
    already via a call to OpenScreen().  Then Intuition uses your screen
    argument for the pertinent information needed to get your window
    going.  On the other hand, if type == one of the Intuition's standard
    screens, your screen argument is ignored.  Instead,
    Intuition will check to see whether or not that screen
    already exists:  if it doesn't, it will be opened first before
    Intuition opens your window in the standard screen.

    New for V36: If you specify Type == WBENCHSCREEN, then your
    window will appear on the Workbench screen, unless the global
    public screen mode SHANGHAI is set, in which case your window
    will be "hijacked" to the default public screen.  See also
    SetPubScreenModes().

    New for V36: If the WFLG_NW_EXTENDED flag is set, it means that the
    field 'ExtNewWindow->Extension' points to an array of TagItems, as
    defined in intuition/tagitem.h.  This provides an extensible means
    of providing extra parameters to OpenWindow.  For compatibility
    reasons, we could not add the 'Extension' field to the NewWindow
    structure, so we have define a new structure ExtNewWindow, which
    is identical to NewWindow with the addition of the Extension field.

    We recommend that rather than using ExtNewWindow.Extension, you
    use the new Intuition function OpenWindowTagList() and its
    varargs equivalent OpenWindowTags().  We document the window
    attribute tag ID's (ti_Tag values) here, rather than in
    OpenWindowTagList(), so that you can find all the parameters
    for a new window defined in one place.

    If the WFLG_SUPER_BITMAP flag is set, the bitmap variable must point
    to your own bitmap.

    The DetailPen and the BlockPen are used for system rendering; for
    instance, the title bar is first filled using the BlockPen, and then
    the gadgets and text are rendered using DetailPen.  You can either
    choose to supply special pens for your window, or, by setting either
    of these arguments to -1, the screen's pens will be used instead.

    Note for V36: The DetailPen and BlockPen no longer determine
    what colors will be used for window borders, if your window
    opens on a "full-blown new look screen."

INPUTS
    NewWindow = pointer to an instance of a NewWindow structure.  That
           structure is initialized with the following data:
-------------------------------------------------------------------------
    Left = the initial x-position for your window
    Top = the initial y-position for your window
    Width = the initial width of this window
    Height = the initial height of this window

    DetailPen = pen number (or -1) for the rendering of window details
     (like gadgets or text in title bar)
    BlockPen = pen number (or -1) for window block fills (like title bar)
    [For V36: Title bar colors are determined otherwise.]

    Flags = specifiers for your requirements of this window, including:
         which system gadgets you want attached to your window:

        - WFLG_DRAGBAR allows this window to be dragged
        - WFLG_DEPTHGADGET lets the user depth-arrange this window
        - WFLG_CLOSEGADGET attaches the standard close gadget
        - WFLG_SIZEGADGET allows this window to be sized.

        If you ask for the WFLG_SIZEGADGET gadget, you must specify one or
        both of the flags WFLG_SIZEBRIGHT and WFLG_SIZEBBOTTOM below; if
        you don't, the default is WFLG_SIZEBRIGHT.  See the following items
        WFLG_SIZEBRIGHT and WFLG_SIZEBBOTTOM for more details.

        - WFLG_SIZEBRIGHT is a special system gadget flag that
          you set to specify whether or not you want the
          RIGHT border adjusted to account for the physical size
          of the sizing gadget.  The sizing gadget must, after
          all, take up room in either the right or bottom border
          (or both, if you like) of the window.  Setting either
          this or the WFLG_SIZEBBOTTOM flag selects which edge
          will take up the slack.  This will be particularly
          useful to applications that want to use the extra space
          for other gadgets (like a proportional gadget and two
          Booleans done up to look like scroll bars) or, for
          for instance, applications that want every possible
          horizontal bit and are willing to lose lines vertically.
          NOTE:  if you select WFLG_SIZEGADGET, you must select
          either WFLG_SIZEBRIGHT or WFLG_SIZEBBOTTOM or both.  If
          you select neither, the default is WFLG_SIZEBRIGHT.
        - WFLG_SIZEBBOTTOM is a special system gadget flag that
          you set to specify whether or not you want the
          BOTTOM border adjusted to account for the physical size
          of the sizing gadget.  For details, refer to
          WFLG_SIZEBRIGHT above.

        - WFLG_GIMMEZEROZERO for easy but expensive output

        what type of window layer you want, either:
        - WFLG_SIMPLE_REFRESH
        - WFLG_SMART_REFRESH
        - WFLG_SUPER_BITMAP

        - WFLG_BACKDROP for whether or not you want this window to be one
          of Intuition's special backdrop windows.  See WFLG_BORDERLESS
          as well.

        - WFLG_REPORTMOUSE for whether or not you want to "listen" to
          mouse movement events whenever your window is the active
          one.  After you've opened your window, if you want to change
          you can later change the status of this via a call to
          ReportMouse().  Whether or not your window is listening to
          mouse is affected by gadgets too, since they can cause you
          to start getting reports too if you like.  The mouse move
          reports (either InputEvents or messages on the IDCMP) that
          you get will have the x/y coordinates of the current mouse
          position, relative to the upper-left corner of your window
          (WFLG_GIMMEZEROZERO notwithstanding).  This flag can work in
          conjunction with the IDCMP Flag called IDCMP_MOUSEMOVE, which
          allows you to listen via the IDCMP.

        - WFLG_BORDERLESS should be set if you want a window with no
          border padding.  Your window may have the border variables
          set anyway, depending on what gadgetry you've requested for
          the window, but you won't get the standard border lines and
          spacing that comes with typical windows.

          This is a good way to take over the entire screen, since you
          can have a window cover the entire width of the screen using
          this flag.  This will work particularly well in conjunction
          with the WFLG_BACKDROP flag (see above), since it allows you
          to open a window that fills the ENTIRE screen.  NOTE:  this is
          not a flag that you want to set casually, since it may cause
          visual confusion on the screen.  The window borders are the
          only dependable visual division between various windows and
          the background screen.  Taking away that border takes away
          that visual cue, so make sure that your design doesn't need
          it at all before you proceed.

        - WFLG_ACTIVATE is the flag you set if you want this window to
          automatically become the active window.  The active
          window is the one that receives input from the keyboard and
          mouse.  It's usually a good idea to to have the window you
          open when your application first starts up be an ACTIVATED
          one, but all others opened later not be ACTIVATED (if the
          user is off doing something with another screen, for
          instance, your new window will change where the input is
          going, which would have the effect of yanking the input rug
          from under the user).  Please use this flag thoughtfully and
          carefully.

          Some notes: First, your window may or may not be active
          by the time this function returns.  Use the IDCMP_ACTIVEWINDOW
          IDCMP message to know when your window has become active.
          Also, be very careful not to mistakenly specify the
          obsolete flag names WINDOWACTIVE or ACTIVEWINDOW.  These are
          used in other contexts, and their values unintentionally added
          to your flags can cause most unfortunate results.  To avoid
          confusion, they are now know as WFLG_WINDOWACTIVE and
          IDCMP_ACTIVEWINDOW.

        - WFLG_RMBTRAP, when set, causes the right mouse button events
          to be trapped and broadcast as events.  You can receive
          these events through either the IDCMP or the console.

        - WFLG_NOCAREREFRESH indicates that you do not wish to
          be responsible for calling BeginRefresh() and EndRefresh()
          when your window has exposed regions (i.e., when the
          IDCMP_REFRESHWINDOW message would be generated).  See also
          the descriptions of these two functions.

        - WFLG_NW_EXTENDED (V36) indicates that NewWindow in fact points
          to an ExtNewWindow structure, and that the 'Extension'
          field points to an array of TagItem structures, with
          meaning described below.

    IDCMPFlags = IDCMP is the acronym for Intuition Direct Communications
        Message Port.  (It's Intuition's sole acronym.) If any of the
        IDCMP Flags is selected, Intuition will create a pair of
        message ports and use them for direct communications with the
        task opening this window (as compared with broadcasting
        information via the Console device).  See the "Input and
        Output Methods" chapter of the Intuition Reference Manual for
        complete details.

        You request an IDCMP by setting any of these flags.  Except
        for the special VERIFY flags, every other flag you set tells
        Intuition that if a given event occurs which your program
        wants to know about, it is to broadcast the details of that
        event through the IDCMP rather than via the Console device.
        This allows a program to interface with Intuition directly,
        rather than going through the Console device.

        Many programs have elected to use IDCMP communication
        exclusively, and not to associate a console with their
        windows at all.  Some operations, such as IDCMP_MENUVERIFY,
        can ONLY be achieved using IDCMP.

        The IDCMP flags you can set are:

        - IDCMP_REQVERIFY is the flag which, like IDCMP_SIZEVERIFY and ...

        - IDCMP_MENUVERIFY (see immediately below), specifies that you
          want to make sure that your graphical state is quiescent
          before something extraordinary happens.  In this case, the
          extraordinary event is that a rectangle of graphical data is
          about to be blasted into your Window.  If you're drawing
          directly into its screen, you probably will wish to make sure
          that you've ceased drawing before the user is allowed to bring
          up the DMRequest you've set up, and the same for when system
          has a request for the user.  Set this flag to ask for that
          verification step.

        - IDCMP_REQCLEAR is the flag you set to hear a message whenever
          a requester is cleared from your window.  If you are using
          IDCMP_REQVERIFY to arbitrate access to your screen's bitmap, it
          is safe to start your output once you have heard an
          IDCMP_REQCLEAR for each IDCMP_REQSET.

        - IDCMP_REQSET is a flag that you set to receive a broadcast
          for each requester that is opened in your window.  Compare
          this with IDCMP_REQCLEAR above.  This function is distinct
          from IDCMP_REQVERIFY.  This functions merely tells you that a
          requester has opened, whereas IDCMP_REQVERIFY requires you to
          respond before the requester is opened.

        - IDCMP_MENUVERIFY is the flag you set to have Intuition stop
          and wait for you to finish all graphical output to your
          window before rendering the menus.  Menus are currently
          rendered in the most memory-efficient way, which involves
          interrupting output to all windows in the screen before the
          menus are drawn.  If you need to finish your graphical
          output before this happens, you can set this flag to make
          sure that you do.

        - IDCMP_SIZEVERIFY means that you will be doing output to your
          window which depends on a knowledge of the current size of the
          window.  If the user wants to resize the window,  you may want
          to make sure that any queued output completes before the sizing
          takes place (critical text, for instance).  If this is the
          case, set this flag.   Then, when the user wants to size,
          Intuition will send you the IDCMP_SIZEVERIFY message and Wait()
          until you reply that it's OK to proceed with the sizing. NOTE:
          when we say that Intuition will Wait() until you reply, what
          we're really saying is that user will WAIT until you reply, which
          suffers the great negative potential of User-Unfriendliness.
          So remember:  use this flag sparingly, and, as always with any
          IDCMP Message you receive, reply to it promptly!  Then, after
          user has sized the window, you can find out about it using
          IDCMP_NEWSIZE.

        With all the "VERIFY" functions, it is not save to leave them
        enabled at any time when your task may not be able to respond
        for a long period.

        It is NEVER safe to call AmigaDOS, directly or indirectly, when
        a "VERIFY" function is active.  If AmigaDOS needs to put up a
        disk requester for you, your task might end up waiting for the
        requester to be satisfied, at the same time as Intuition is
        waiting for your response.  The result is a complete machine
        lockup.  USE ModifyIDCMP() TO TURN OFF ANY VERIFY MESSAGES
        BEFORE CALLING dos.library!!

        For V36: If you do not respond to the verification IntuiMessages
        within the user specified timeout duration, Intuition will abort
        the operation.  This eliminates the threat of these easy
        deadlocks, but can result in a confused user.  Please try
        hard to continue to avoid "logical deadlocks".

        - IDCMP_NEWSIZE is the flag that tells Intuition to send an IDCMP
          message to you after the user has resized your window.  At
          this point, you could examine the size variables in your
          window structure to discover the new size of the window.
          See also the IDCMP_CHANGEWINDOW IDCMP flag.

        - IDCMP_REFRESHWINDOW when set will cause a message to be sent
          whenever your window needs refreshing.  This flag makes
          sense only with WFLG_SIMPLE_REFRESH and WFLG_SMART_REFRESH
          windows.

        - IDCMP_MOUSEBUTTONS will get reports about mouse-button up/down
          events broadcast to you (Note:  only the ones that
          don't mean something to Intuition.  If the user clicks the
          select button over a gadget, Intuition deals with it and you
          don't find out about it through here).

        - IDCMP_MOUSEMOVE will work only if you've set the
          WFLG_REPORTMOUSE flag above, or if one of your gadgets has the
          GACT_FOLLOWMOUSE flag set.  Then all mouse movements will be
          reported here, providing your window is active.

        - IDCMP_GADGETDOWN means that when the User "selects" a gadget
          you've created with the GACT_IMMEDIATE flag set, the fact
          will be broadcast through the IDCMP.

        - IDCMP_GADGETUP means that when the user "releases" a gadget that
          you've created with the GACT_RELVERIFY flag set, the fact
          will be broadcast through the IDCMP.  This message is
          only generated if the release is "good", such as releasing
          the select button over a Boolean gadget, or typing ENTER
          in a string gadget.

        - IDCMP_MENUPICK selects that menu number data will be sent via
          the IDCMP.

        - IDCMP_CLOSEWINDOW means broadcast the IDCMP_CLOSEWINDOW event
          through the IDCMP rather than the console.

        - IDCMP_RAWKEY selects that all IDCMP_RAWKEY events are
          transmitted via the IDCMP.  Note that these are absolutely RAW
          keycodes, which you will have to translate before using.
          Setting this and the MOUSE flags effectively eliminates the need
          to open a Console device to get input from the keyboard and
          mouse.  Of course, in exchange you lose all of the console
          features, most notably the "cooking" of input data and
          the systematic output of text to your window.

        - IDCMP_VANILLAKEY is for developers who don't want the hassle
          of IDCMP_RAWKEYS.  This flag will return all the keycodes after
          translation via the current country-dependent keymap.  When
          you set this flag, you will get IntuiMessages where the Code
          field has a decoded ANSI character code representing the key
          struck on the keyboard.  Only codes that map to a single
          character are returned: you can't read such keys as HELP or
          the function keys with IDCMP_VANILLAKEY.

          NOTE FOR V36: If you have both IDCMP_RAWKEY and IDCMP_VANILLAKEY
          set, Intuition will send an IDCMP_RAWKEY event for those
          *downstrokes* which do not map to single-byte characters
          ("non-vanilla" keys).  In this way you can easily detect cursor
          keys, function keys, and the Help key without sacrificing the
          convenience of IDCMP_VANILLAKEY.

        - IDCMP_INTUITICKS gives you simple timer events from Intuition
          when your window is the active one; it may help you avoid
          opening and managing the timer device.  With this flag set,
          you will get only one queued-up INTUITICKS message at a
          time.  If Intuition notices that you've been sent an
          IDCMP_INTUITICKS message and haven't replied to it, another
          message will not be sent.  Intuition receives timer events and
          considers sending you an IDCMP_INTUITICKS message approximately
          ten times a second.

        - IDCMP_DELTAMOVE gives raw (unscaled) input event delta X/Y
          values.  This is so you can detect mouse motion regardless of
          screen/window/display boundaries.  This works a little
          strangely: if you set both IDCMP_MOUSEMOVE and IDCMP_DELTAMOVE.
          IDCMPFlags, you will get IDCMP_MOUSEMOVE messages with delta
          x/y values in the MouseX and MouseY fields of the
          IDCMPMessage.

        - IDCMP_NEWPREFS indicates you wish to be notified when the
          system-wide Preferences changes.  For V36, there is a new
          environment mechanism to replace Preferences, which we
          recommend you consider using instead.

        - Set IDCMP_ACTIVEWINDOW and IDCMP_INACTIVEWINDOW to get messages
          when those events happen to your window.  Take care not to
          confuse this "ACTIVEWINDOW" with the familiar sounding, but
          totally different "WINDOWACTIVE" flag.  These two flags have
          been supplanted by "IDCMP_ACTIVEWINDOW" and "WFLG_WINDOWACTIVE".
          Use the new equivalent terms to avoid confusion.

        - Set IDCMP_DISKINSERTED or IDCMP_DISKREMOVED to learn when
          removable disks are inserted or removed, respectively.

        - IDCMP_IDCMPUPDATE is a new class for V36 which is used as
          a channel of communication from custom and boopsi gadgets
          to your application.

        - IDCMP_CHANGEWINDOW is a new class for V36 that will be sent
          to your window whenever its dimensions or position are changed
          by the user or the functions SizeWindow(), MoveWindow(),
          ChangeWindowBox(), or ZipWindow().

        - IDCMP_MENUHELP is new for V37.  If you specify the WA_MenuHelp
          tag when you open your window, then when the user presses the
          HELP key on the keyboard during a menu session, Intuition will
          terminate the menu session and issue this even in place of an
          IDCMP_MENUPICK message.
            - NEVER follow the NextSelect link for MENUHELP messages.
            - You will be able to hear MENUHELP for ghosted menus.
              (This lets you tell the user why the option is ghosted.)
            - Be aware that you can receive a MENUHELP message whose code
              corresponds to a menu header or an item that has sub-items
              (which does not happen for MENUPICK).  The code may also be
              MENUNULL.
            - LIMITATION:  if the user extend-selects some checkmarked
              items with the mouse, then presses MENUHELP, your
              application will only hear the MENUHELP report.  You
              must re-examine the state of your checkmarks when you
              get a MENUHELP.
            - Availability of MENUHELP in V36 is not directly
              controllable.  We apologize...

    Gadgets = the pointer to the first of a linked list of the your own
          Gadgets which you want attached to this Window.  Can be NULL
          if you have no Gadgets of your own

   CheckMark = a pointer to an instance of the struct Image where can
          be found the imagery you want used when any of your
          menu items is to be checkmarked.  If you don't want to
          supply your own imagery and you want to just use
          Intuition's own checkmark, set this argument to NULL

   Text = a null-terminated line of text to appear on the title bar of
          your window (may be null if you want no text)

   Type = the screen type for this window.  If this equal CUSTOMSCREEN,
          you must have already opened a CUSTOMSCREEN (see text above).
          Types available include:
              - WBENCHSCREEN
              - CUSTOMSCREEN
              - PUBLICSCREEN (new for V36, see text below)

   Screen = if your type is one of Intuition's standard screens, then
          this argument is ignored.  However, if Type == CUSTOMSCREEN,
          this must point to the structure of your own screen

   BitMap = if you have specified WFLG_SUPER_BITMAP as the type of
           refreshing you want for this window, then this value points to a
           instance of the struct bitmap.  However, if the refresh type
           is NOT WFLG_SUPER_BITMAP, this pointer is ignored.

   MinWidth, MinHeight, MaxWidth, MaxHeight = the size limits for this
          window.  These must be reasonable values, which is to say that
          the minimums cannot be greater than the current size, nor can
          the maximums be smaller than the current size.  If they are,
          they're ignored.  Any one of these can be initialized to zero,
          which means that that limit will be set to the current
          dimension of that axis.  The limits can be changed after the
          Window is opened by calling the WindowLimits() routine.

          NOTE: ORIGINALLY, we stated that:

          "If you haven't requested the WFLG_SIZEGADGET option, these
          variables are ignored so you don't have to initialize them."

          It is now clear that a variety of programs take it upon
          themselves to call SizeWindow() (or ChangeWindowBox()) without
          your program's consent or consulting your WFLG_SIZEGADGE
          option.  To protect yourself against the results, we strongly
          urge that if you supply suitable values for these fields even
          if you do not specify WFLG_SIZEGADGET.

          The maximums may be LARGER than the current size, or even
          larger than the current screen.  The maximums should be set to
          the highest value your application can handle.  This allows
          users with larger display devices to take full advantage of
          your software.  If there is no good reason to limit the size,
          then don't.  -1 or ~0 indicates that the maximum size is only
          limited by the size of the window's screen.

          See also the docs on the function WindowLimits() for more
          information.

   Extension (New for V36) = a pointer to an array (or chain of arrays)
        of TagItems to specify additional parameters to OpenWindow().
        TagItems in general are described in utility/tagitem.h,
        and the OpenWindow tags are defined in intuition/intuition.h
        and described here.  For items pertaining to Public Screens
        and visitor windows, please see below.

    Here are the TagItem.ti_Tag values that are defined for OpenWindow
    (and OpenWindowTagList()).

    Certain tags simply override equivalent values in NewWindow,
    and allow you to open a window using OpenWindowTagList() without
    having a NewWindow structure at all.  In each case, cast
    the corresponding data to ULONG and put it in ti_Data.

    The compatible tag items include:

    WA_Left
    WA_Top
    WA_Width
    WA_Height
    WA_DetailPen
    WA_BlockPen
    WA_IDCMP
    WA_Flags        - initial values for Flags before looking at other
                    Boolean component Tag values
    WA_Gadgets
    WA_Checkmark
    WA_Title
    WA_CustomScreen - also implies CUSTOMSCREEN property
    WA_SuperBitMap - also implies WFLG_SUPER_BITMAP refresh mode.
    WA_MinWidth
    WA_MinHeight
    WA_MaxWidth
    WA_MaxHeight

    These Boolean tag items are alternatives to the NewWindow.Flags
    Boolean attributes with similar names.

    WA_SizeGadget           - equivalent to WFLG_SIZEGADGET
    WA_DragBar              - equivalent to WFLG_DRAGBAR
    WA_DepthGadget          - equivalent to WFLG_DEPTHGADGET
    WA_CloseGadget          - equivalent to WFLG_CLOSEGADGET
    WA_Backdrop             - equivalent to WFLG_BACKDROP
    WA_ReportMouse          - equivalent to WFLG_REPORTMOUSE
    WA_NoCareRefresh        - equivalent to WFLG_NOCAREREFRESH
    WA_Borderless           - equivalent to WFLG_BORDERLESS
    WA_Activate             - equivalent to WFLG_ACTIVATE
    WA_RMBTrap              - equivalent to WFLG_RMBTRAP
    WA_WBenchWindow         - equivalent to WFLG_WBENCHWINDOW
                              (system PRIVATE)
    WA_SimpleRefresh        - only specify if TRUE
    WA_SmartRefresh         - only specify if TRUE
    WA_SizeBRight           - equivalent to WFLG_SIZEBRIGHT
    WA_SizeBBottom          - equivalent to WFLG_SIZEBBOTTOM
    WA_GimmeZeroZero        - equivalent to WFLG_GIMMEZEROZERO

    The following tag items specify new attributes of a window.

    WA_ScreenTitle - You can specify the screen title associated
        with your window this way, and avoid a call to SetWindowTitles()
        when your window opens.

    WA_AutoAdjust - a Boolean attribute which says that it's OK
        to move or even shrink the dimensions of this window
        to fit it on the screen, within the dimension
        limits specified by MinWidth and MinHeight.
        Someday, this processing might be sensitive to the
        currently visible portion of the screen the window
        will be opening on, so don't draw too many conclusions
        about the auto-adjust algorithms.
        (Normally, this attribute defaults to FALSE.  However,
        if you call OpenWindowTags() or OpenWindowTagList()
        with a NULL NewWindow pointer, this attribute defaults
        to TRUE).

    WA_InnerWidth
    WA_InnerHeight - You can specify the dimensions of the interior
        region of your window, independent of what the border
        thicknesses will be.  You probably want to specify
        WA_AutoAdjust to allow Intuition to move your window
        or even shrink it so that it is completely on screen.

        Note: using these tags puts some reasonable restrictions
        on the gadgets you can specify as "border" gadgets when
        you open your window.  Since border gadgets determine
        the border dimensions and hence the overall dimensions of
        your window, those dimensions cannot be used calculating
        the position or dimensions of border gadgets.

        Here's the complete list of restrictions:
        - GACT_LEFTBORDER gadgets cannot be GFLG_RELWIDTH if
          WA_InnerWidth is used.
        - GACT_RIGHTBORDER gadgets MUST be GFLG_RELRIGHT if
          WA_InnerWidth is used.
        - GACT_TOPBORDER gadgets cannot be GFLG_RELHEIGHT if
          WA_InnerHeight is used.
        - GACT_BOTTOMBORDER gadgets MUST be GFLG_RELBOTTOM if
          WA_InnerHeight is used.

    WA_PubScreenName - This tag item declares that you want your window
        to open as a visitor window on the public screen whose name
        is pointed to by (UBYTE *) ti_Data.

    WA_PubScreen - Open as a visitor window on the public screen
        whose address if provided as (struct Screen *) ti_Data.
        To ensure that this screen remains open long enough, you
        must either:
            1) Be the screen's owner
            2) have another window already open on the screen
            3) use LockPubScreen()
        Using exec.library/Forbid() is not sufficient.

        You can provide ti_Data to be NULL (zero), without any
        of the above precautions, to specify the default public screen.

    WA_PubScreenFallBack - This Boolean attribute specifies that a
        visitor window should "fall back" to opening on the default
        public screen if the explicitly specify public screen is not
        available.

    WA_WindowName - this visionary specification of a window
        rendezvous name string is not yet implemented.

    WA_Colors - this equally great idea about associating a palette
        specification with the active window may not ever be implemented.

    WA_Zoom - ti_Data points to an array of four WORD's to be used
        as the initial Left/Top/Width/Height of the "alternate
        Zoom position and dimensions."  The presence of this tag
        item implies that you want a Zoom gadget, even though you
        might not have a sizing gadget.

    WA_MouseQueue - This tag specifies a limit for the number
        of outstanding IDCMP_MOUSEMOVE IntuiMessages that Intuition
        will send to your window.  You can change the value of this
        limit after the window is open using SetMouseQueue().

    WA_RptQueue - This tag specifies a limit for the number of
        outstanding repeated-IDCMP_RAWKEY, repeated-IDCMP_VANILLAKEY,
        and repeated-IDCMP_IDCMPUPDATE IntuiMessages that Intuition will
        send to your window.  Currently, there is no function to adjust
        the repeat-key queue.

    WA_BackFill - ti_Data is a pointer to a Hook structure that
        the Layers library will call when your window needs
        "backfilling."  See layers.library/InstallLayerHook().

    WA_MenuHelp - ti_Data is a boolean.  If true, enables the MenuHelp
        feature for this window.  See IDCMP_MENUHELP above.  (Ignored
        in V36 and earlier).

NOTES
    Regarding Public Screens, you can specify a window to be a
    "visitor window" on a public screen in one of several ways.
    In each case, you must be sure not to specify a NewWindow
    type of CUSTOMSCREEN.  You should use the value PUBLICSCREEN.

    There are actually several ways you can specify which screen
    you want a visitor window to be opened on:

        1) Specify the name of the public screen WA_PubScreenName,
        or a NULL pointer, in ti_Data.  The name might have been
        provided by the user.  A NULL pointer means to use the
        default public screen.

        If the named screen cannot be found, the default public screen
        will be used if the Boolean attribute WA_PubScreenFallBack
        is TRUE.

        2) Specify a pointer to a public screen using the
        WA_PubScreen tag item.  The WA_PubScreenFallBack
        attribute has no effect.  You can specify the default
        public screen by providing a NULL pointer.

        You can also specify the pointer by setting NewWindow.Type
        to PUBLICSCREEN, and specifying the public screen pointer
        in NewWindow.Screen.  The WA_PubScreen tag item has precedent
        over this technique.

        Unless NULL, the screen pointer provided MUST be a valid
        public screen.  You may ensure this several ways:

        - Be the owner of the screen.
        - Have a window already open on the screen.
        - Use LockPubScreen() to prevent the screen from closing.
        - specifying the WFLG_VISITOR bit in NewWindow.Flags is not
          supported.

        It is anticipated that the last will be the most common method
        of opening public screens because you often want to examine
        properties of the screen your window will be using in order
        to compensate for differences in dimension, depth, and font.

        The standard sequence for this method is as follows:
        LockPubScreen() - obtain a pointer and a promise
        layout window       - adapt your window to the screen you will use
        OpenWindow()        - using the pointer you specify
        UnlockPubScreen()     - once your window is open, you can let go
                              of the lock on the public screen
        ... normal window even processing ...
        CloseWindow().

    Regarding "service" windows, such as those opened for a system
    requester or file requester associated with a given "client"window.
    These windows should NOT be "visitor" windows.  Open them
    using NewWindow.Type = CUSTOMSCREEN and NewWindow.Screen
    equal to the screen of the client window (window->WScreen).
    You can also use WA_CustomScreen, which has precedence.

    This ensures that the requester service window will be allowed to
    open on the same screen as the client window, even if that
    screen is not a public screen, or has private status.

    This has an implication for service/client protocol: when you
    pass a window pointer to any system requester routine or
    to a routine which creates some other other service window,
    you MUST keep your window open until the client window
    is closed.

    If a requester service will allow a NULL client window, this
    should indicate to open the service window on the default public
    screen (probably Workbench).  The correct way to get a pointer
    to this screen is to call LockPubScreen( NULL ).  In this
    case, you want to open as a visitor window, which means you
    should use either PUBLICSCREEN or WA_PubScreen, described above.
    You should call UnlockPubScreen() after your visitor window is open.

    As of V36, gadgets in the right and bottom border
    (specified with GACT_RIGHTBORDER and GACT_BOTTOMBORDER) only
    contribute to the dimensions of the borders if they are also
    GFLG_RELRIGHT and GFLG_RELBOTTOM, respectively.

RESULT
    If all is well, returns the pointer to your new Window
    If anything goes wrong, returns NULL

BUGS
    When you open a window, Intuition will set the font of
    the window's RastPort to the font of the window's screen.
    This does not work right for GimmeZeroZero windows: the
    BorderRPort RastPort has the font set correctly, but
    Window.RPort is set up with the system default font.
    For compatibility reasons, we won't be fixing this problem.

    Also, there is a compatibility trick going on with the
    default font of your window's RastPort if the screen's
    font is "fancy."  See the SA_SysFont attribute described
    under OpenScreen().

    Unless you arrange otherwise, each window you open will allocate
    a signal for your task from the 16 "user signals."
    If no signal is available, your window will not be able
    to be opened.  In early V36 versions and before, Intuition didn't
    check this condition, but just left you with an unusable port.

SEE ALSO
   OpenWindowTagList(), OpenScreen(), ModifyIDCMP(), SetWindowTitles(),
    LockPubScreen(), SetDefaultPubScreen(), ZipWindow(),
    layers.library/InstallLayerHook(), SetPubScreenModes()


intuition.library/OpenWindowTagList

NAME
    OpenWindowTagList -- OpenWindow() with TagItem extension. (V36)
    OpenWindowTags -- Varargs stub for OpenWindowTagList (V36)

SYNOPSIS
    Window = OpenWindowTagList( NewWindow, TagItems )
    D0                          A0         A1

    struct Window *OpenWindowTagList( struct NewWindow *,
            struct TagItem * );

    Window = OpenWindowTags( NewWindow, Tag1, ... )

    struct Window *OpenWindowTags( struct NewWindow *, ULONG, ... );

FUNCTION
    A variation of OpenWindow() that allow direct specification of
    a TagItem array of extension data.  Recommended over using the
    ExtNewWindow.Extension field.

    If you omit the NewWindow (pass NULL), a set of defaults
    are used, and overridden by the tag items.  Even without
    any tag items at all, a reasonable window opens on the Workbench
    or default public screen.

    See OpenWindow() for all the details.

INPUTS
    NewWindow - (optional) pointer to a NewWindow structure.
    TagItems - (optional) pointer to TagItem array, with tag
            values as described under the description for
            OpenWindow().

RESULT
    Window - newly created window, per your specifications.

EXAMPLE
    See OpenScreenTagList() for an example of how to create
    a "varargs" version of this function for convenient C
    language programming.

NOTES

BUGS

SEE ALSO
    OpenWindow()


intuition.library/OpenWorkBench

NAME
    OpenWorkBench -- Open the Workbench screen.

SYNOPSIS
    WBScreen = OpenWorkBench()
    D0

    ULONG OpenWorkBench( VOID );

FUNCTION
    This routine attempts to reopen the Workbench.  The actions taken are:
        - general good stuff and nice things, and then return a non-null
          pointer to the Workbench screen.
        - find that something has gone wrong, and return NULL

    The return value, if not NULL, is indeed the address of the Workbench
    screen, although you should not use it as such.  This is because the
    Workbench may be closed by other programs, which can invalidate
    the address at any time.  We suggest that you regard the return
    value as a ULONG indication that the routine has succeeded, if
    you pay any attention to it at all.

INPUTS
    None

RESULT
    non-zero if Workbench screen opened successfully, or was already
            opened
    zero if anything went wrong and the Workbench screen isn't out there

BUGS
    The name of this routine is spelled wrong: it ought to have been
    OpenWorkbench().

SEE ALSO


intuition.library/PointInImage

NAME
    PointInImage -- Tests whether an image "contains" a point. (V36)

SYNOPSIS
    DoesContain = PointInImage( Point, Image )
    D0                          D0     A0

    BOOL PointInImage( struct Point, struct Image * );

FUNCTION
    Tests whether a point is properly contained in an image.
    The intention of this is to provide custom gadgets a means
    to delegate "image mask" processing to the Image, where
    it belongs (superceding things like BOOLMASK).  After all,
    a rounded rect image with a drop shadow knows more about
    what points are inside it than anybody else should.

    For traditional Intuition Images, this routine checks if
    the point is in the Image box (LeftEdge/RightEdge/Width/Height).

INPUTS
    Point   - Two words, X/Y packed into a LONG, with high word
            containing 'X'.  This is what you get if you pass
            a Point structure (not a pointer!) using common
            C language parameter conventions.
    Image - a pointer to a standard or custom Image data object.
        NOTE: If 'Image' is NULL, this function returns TRUE.

RESULT
    DoesContain - Boolean result of the test.

EXAMPLE

NOTES

BUGS
    Only applies to the first image, does not follow NextImage
    linked list.  This might be preferred.

SEE ALSO


intuition.library/PrintIText

NAME
    PrintIText -- Print text described by the IntuiText argument.

SYNOPSIS
    PrintIText( RastPort, IText, LeftOffset, TopOffset )
                A0        A1     D0          D1

    VOID PrintIText( struct RastPort *, struct IntuiText *, WORD, WORD );

FUNCTION
    Prints the IntuiText into the specified RastPort.  Sets up the
    RastPort as specified by the IntuiText values, then prints the text
    into the RastPort at the IntuiText x/y coordinates offset by the
    left/top arguments.  Note, though, that the IntuiText structure
    itself may contain further text position coordinates: those
    coordinates and the Left/TopOffsets are added to obtain the true
    position of the text to be rendered.

    This routine does window layer clipping as appropriate -- if you
    print text outside of your window, your characters will be
    clipped at the window's edge, providing you pass your window's
    (layered) RastPort.

    If the NextText field of the IntuiText argument is non-NULL,
    the next IntuiText is rendered as well, and so on until some
    NextText field is NULL.

    IntuiText with the ITextFont field NULL are displayed in the
    font of the RastPort.  If the RastPort font is also NULL, the
    system default font, as set via the Preferences tool, will be used.

INPUTS
    RastPort = the RastPort destination of the text
    IText = pointer to an instance of the structure IntuiText
    LeftOffset = left offset of the IntuiText into the RastPort
    TopOffset = top offset of the IntuiText into the RastPort

RESULT
    None

BUGS

SEE ALSO


intuition.library/PubScreenStatus

NAME
    PubScreenStatus -- Change status flags for a public screen. (V36)

SYNOPSIS
    ResultFlags = PubScreenStatus( Screen, StatusFlags )
    D0                             A0      D0

    UWORD PubScreenStatus( struct Screen *, UWORD );

FUNCTION
    Changes status flags for a given public screen.

    Do not apply this function to a screen if your program
    isn't the screen's "owner", in particular, don't call
    this function for the Workbench screen.

INPUTS
    Screen = pointer to public screen
    StatusFlags = values currently:
      PSNF_PRIVATE: make this screen unavailable to visitor windows

RESULT
    Returns 0 in the lowest order bit of the return value
    if the screen wasn't public, or because it can not be taken
    private because visitors are open in it.

    All other bits in the return code are reserved for future
    enhancement.

BUGS

SEE ALSO
    OpenScreen(), Intuition V36 update documentation


intuition.library/QueryOverscan

NAME
    QueryOverscan -- Inquire about a standard overscan region. (V36)

SYNOPSIS
    success = QueryOverscan( DisplayID, Rect, OScanType )
    D0                       A0         A1    D0

    LONG QueryOverscan( ULONG, struct Rectangle *, WORD );

FUNCTION
    This function fills in a rectangle with one of the system
    overscan dimensions, scaled appropriately for the mode of
    the DisplayID it is passed.

    There are three types of system overscan values:
    OSCAN_TEXT: completely visible, by user preference.  Used
      for Workbench screen and screen dimensions STDSCREENWIDTH
      and STDSCREENHEIGHT.  Left/Top is always 0,0.
    OSCAN_STANDARD: just beyond visible bounds of monitor, by
      user preference.  Left/Top may be negative.
    OSCAN_MAX: The largest region we can display, AND display
      any smaller region (see note below).
    OSCAN_VIDEO: The absolute largest region that the graphics.library
      can display.  This region must be used as-is.

INPUTS
    DisplayID -- A 32-bit identifier for a display mode, as
      defined in graphics/displayinfo.h.

      NOTE: If you only intend to use one of the four standard
      overscan dimensions as is, and open your screen to exactly
      the DisplayClip dimensions, you can specify one of
      the OSCAN_ values in the ExtNewScreen tag SA_StdDClip,
      and specify STDSCREENWIDTH and STDSCREENHEIGHT as the
      dimensions to more easily open up an overscanned screen
      (or use no NewScreen in OpenScreenTagList() and accept
      the default standard screen dimensions).

    Rect -- pointer to a Rectangle structure which this function
      will fill out with its return values.  Note that to convert
      a rectangle to a screen "Height" you do (MaxY - MinY + 1), and
      similarly for "Width."  The rectangle may be passed directly
      to OpenScreen() as a DisplayClip region (SA_DClip).

RESULT
    0 (FALSE) if the MonitorSpec your NewScreen requests
    does not exist.  Non-zero (TRUE) if it does.

BUGS
    Change in parameter V36.A17 might cause problems for some.

SEE ALSO
    OpenScreen(), Intuition V36 update documentation


intuition.library/RefreshGadgets

NAME
    RefreshGadgets -- Refresh (redraw) the gadget display.

SYNOPSIS
    RefreshGadgets( Gadgets, Window, Requester )
                    A0       A1      A2

    VOID RefreshGadgets( struct Gadget *, struct Window *,
            struct Requester * );

FUNCTION
    Refreshes (redraws) all of the gadgets in the gadget list starting
    from the specified gadget.

    The window parameter must point to the window which contains the
    gadget, or which contains the requester that contains the gadget
    The requester parameter must only be valid if the gadget has the
    GTYP_REQGADGET flag set, a requirement for all requester gadgets.

    The Pointer argument points to a Window structure.

    The two main reasons why you might want to use this routine are:
    first, that you've modified the imagery of the gadgets in your
    display and you want the new imagery to be displayed; secondly,
    if you think that some graphic operation you just performed
    trashed the gadgetry of your display, this routine will refresh
    the imagery for you.

    Note that to modify the imagery of a gadget, you must first remove
    that gadget from the window's gadget list, using RemoveGadget() (or
    RemoveGList()).  After changing the image, border, text (including
    text for a string gadget), the gadget is replaced in the gadget list
    (using AddGadget() or AddGList()).  Adding gadgets does not cause
    them to be displayed (refreshed), so this function, or RefreshGList()
    is typically called.

    A common technique is to set or reset the GFLG_SELECTED flag of a
    Boolean gadget and then call RefreshGadgets() to see it displayed
    highlighted if and only if GFLG_SELECTED is set.  If you wish to do
    this and be completely proper, you must RemoveGadget(), change the
    GFLG_SELECTED flag, AddGadget(), and RefreshGadgets(), or the
    equivalent.

    The gadgets argument can be a copy of the FirstGadget variable in
    the Window structure that you want refreshed:
    the effect of this will be that all gadgets will be redrawn.
    However, you can selectively refresh just some of the gadgets
    by starting the refresh part-way into the list:  for instance,
    redrawing your window non-GTYP_GZZGADGET gadgets only, which you've
    conveniently grouped at the end of your gadget list.

    Even more control is available using the RefreshGList() routine which
    enables you to refresh a single gadget, or number of your choice.

    NOTE:  It's never safe to tinker with the gadget list yourself.  Don't
    supply some gadget list that Intuition hasn't already processed in
    the usual way.

INPUTS
    Gadgets = pointer to the first in the list of gadgets wanting
        refreshment
    Window = pointer to the window containing the gadget or its requester
    Requester = pointer to a requester (ignored if gadget is not attached
        to a requester).

RESULT
    None

BUGS

SEE ALSO
    RefreshGList(), RemoveGadget(), RemoveGList(), AddGadget(), AddGList()


intuition.library/RefreshGList

NAME
    RefreshGList -- Refresh (redraw) a chosen number of gadgets.

SYNOPSIS
    RefreshGList( Gadgets, Window, Requester, NumGad )
                  A0       A1      A2         D0

    VOID RefreshGList( struct Gadget *, struct Window *,
            struct Requester *, WORD );

FUNCTION
    Refreshes (redraws) gadgets in the gadget list starting
    from the specified gadget.  At most NumGad gadgets are redrawn.
    If NumGad is -1, all gadgets until a terminating NULL value
    in the NextGadget field is found will be refreshed, making this
    routine a superset of RefreshGadgets().

    The Requester parameter can point to a Requester structure.  If
    the first gadget in the list has the GTYP_REQGADGET flag set, the
    gadget list refers to gadgets in a requester and the pointer
    must necessarily point to a window.  If these are not the gadgets
    of a requester, the requester argument may be NULL.

    Be sure to see the RefreshGadgets() function description, as this
    function is simply an extension of that.

INPUTS
    Gadgets = pointer to the first in the list of gadgets wanting
        refreshment
    Window = pointer to the window containing the gadget or its requester
    Requester = pointer to a requester (ignored if Gadget is not attached
        to a Requester).
    NumGad  = maximum number of gadgets to be refreshed.  A value of -1
      will cause all gadgets to be refreshed from gadget to the
      end of the list.  A value of -2 will also do this, but if 'Gadgets'
      points to a Requester Gadget (GTYP_REQGADGET) ALL gadgets in the
      requester will be refreshed (this is a mode compatible with v1.1
      RefreshGadgets().)

RESULT
    None

BUGS

SEE ALSO
    RefreshGadgets()


intuition.library/RefreshWindowFrame

NAME
    RefreshWindowFrame -- Ask Intuition to redraw your window border.

SYNOPSIS
    RefreshWindowFrame( Window )
                        A0

    VOID RefreshWindowFrame( struct Window * );

FUNCTION
    Refreshes the border of a window, including title region and all
    of the window's gadgets.

    You may use this call if you wish to update the display of your
    borders.  The expected use of this is to correct unavoidable
    corruption.

INPUTS
    Window = a pointer to a Window structure

RESULT
    None

BUGS

SEE ALSO


intuition.library/ReleaseGIRPort

NAME
    ReleaseGIRPort -- Release a custom gadget RastPort. (V36)

SYNOPSIS
    ReleaseGIRPort( RPort )
                    A0

    VOID ReleaseGIRPort( struct RastPort * );

FUNCTION
    The corresponding function to ObtainGIRPort(), it releases
    arbitration used by Intuition for gadget RastPorts.

INPUTS
    Pointer to the RastPort returned by ObtainGIRPort().
    This pointer can be NULL, in which case nothing happens.

RESULT
    None

BUGS

SEE ALSO
    ObtainGIRPort(), Custom Gadget documentation


intuition.library/RemakeDisplay

NAME
    RemakeDisplay -- Remake the entire Intuition display.

SYNOPSIS
    RemakeDisplay()

    VOID RemakeDisplay( VOID );

FUNCTION
    This is the big one.

    This procedure remakes the entire View structure for the
    Intuition display.  It does the equivalent of MakeScreen() for
    every screen in the system, and then it calls the internal
    equivalent of RethinkDisplay().

    WARNING:  This routine can take many milliseconds to run, so
    do not use it lightly.

    Calling MakeScreen() followed by RethinkDisplay() is typically
    a more efficient method for affecting changes to a single
    screen's ViewPort.

INPUTS
    None

RESULT
    None

BUGS

SEE ALSO
    MakeScreen(), RethinkDisplay(), graphics.library/MakeVPort()
    graphics.library/MrgCop(), graphics.library/LoadView()


intuition.library/RemoveClass

NAME
    RemoveClass -- Make a public boopsi class unavailable. (V36)

SYNOPSIS
    RemoveClass( classPtr )
                 A0

    VOID RemoveClass( struct IClass * );

FUNCTION
    Makes a public class unavailable for public consumption.
    It's OK to call this function for a class which is not
    yet in the internal public class list, or has been
    already removed.

INPUTS
    ClassPtr = pointer to *public* class created by MakeClass(),
            may be NULL.

RESULT
    None.

NOTES

BUGS

SEE ALSO
    MakeClass(), FreeClass(), AddClass()
    Document "Basic Object-Oriented Programming System for Intuition"
    and the "boopsi Class Reference" document.


intuition.library/RemoveGadget

NAME
    RemoveGadget -- Remove a gadget from a window.

SYNOPSIS
    Position = RemoveGadget( Window, Gadget )
    D0                       A0      A1

    UWORD RemoveGadget( struct Window *, struct Gadget * );

FUNCTION
    Removes the given gadget from the gadget list of the specified
    window.  Returns the ordinal position of the removed gadget.

    If the gadget is in a requester attached the the window, this
    routine will look for it and remove it if it is found.

    If the gadget pointer points to a gadget that isn't in the
    appropriate list, -1 is returned.  If there aren't any gadgets in the
    list, -1 is returned.  If you remove the 65535th gadget from the list
    -1 is returned.

NOTES
    New with V37: If one of the gadgets you wish to remove
    is the active gadget, this routine will wait for the user
    to release the mouse button before deactivating and removing
    the gadget.

INPUTS
    Window = pointer to the window containing the gadget or the requester
        containing the gadget to be removed.
    Gadget = pointer to the gadget to be removed.  The gadget itself
        describes whether this is a gadget that should be removed from the
        window or some requester.

RESULT
    Returns the ordinal position of the removed gadget.  If the gadget
    wasn't found in the appropriate list, or if there are no gadgets in
    the list, returns -1.

BUGS

SEE ALSO
    AddGadget(), AddGList(), RemoveGList()


intuition.library/RemoveGList

NAME
    RemoveGList -- Remove a sublist of gadgets from a window.

SYNOPSIS
    Position = RemoveGList( Window, Gadget, Numgad )
    D0                      A0      A1      D0

    UWORD RemoveGList( struct Window *, struct Gadget *, WORD );

FUNCTION
    Removes 'Numgad' gadgets from the gadget list of the specified
    window.  Will remove gadgets from a requester if the first
    gadget's GadgetType flag GTYP_REQGADGET is set.

    Otherwise identical to RemoveGadget().

NOTE
    The last gadget in the list does NOT have its link zeroed.
    New with V36: OK, last gadget's NextGadget field is set to NULL.

    New with V37: If one of the gadgets you wish to remove
    is the active gadget, this routine will wait for the user
    to release the mouse button before deactivating and removing
    the gadget.

INPUTS
    Window = pointer to the window containing the gadget or the requester
        containing the gadget to be removed.
    Gadget = pointer to the gadget to be removed.  The gadget itself
       describes whether this is a gadget that should be removed
       from the window or some requester.
    Numgad = number of gadgets to be removed.  If -1, remove all gadgets
        to end of window gadget list

RESULT
    Returns the ordinal position of the removed gadget.  If the gadget
    wasn't found in the appropriate list, or if there are no gadgets in
    the list, returns -1.

BUGS

SEE ALSO
    RemoveGadget(), AddGadget(), AddGList()


intuition.library/ReportMouse

NAME
    ReportMouse -- Tell Intuition whether to report mouse movement.

SYNOPSIS
    ReportMouse( Boolean, Window )
                 D0       A0        <-note

    VOID ReportMouse( BOOL, struct Window * );

SPECIAL NOTE
    Some compilers and link files switch the arguments to this function
    about in unpredictable ways.  We apologize for this confusion
    wrapped around an error enclosing a mistake.
    The call will take one of two forms:

            ReportMouse(Boolean, Window);
                    -or-
            ReportMouse(Window, (ULONG)Boolean);

    The first form is the one that corresponds to the amiga.lib supplied
    by Commodore.  The linker libraries and "pragmas" of some compilers
    supply the alternate form.

    A key point to remember is that the form of the function in ROM
    has always been the same, so there has always been object code
    compatibility.  However some care should be taken when switching
    compilers or switching between stubs and pragmas.

    From assembler the interface has always been:
            Boolean in D0, Window in A0

    Also, it is still endorsed to simply set the WFLG_REPORTMOUSE flag bit
    in Window->Flags, or reset it, on your own.  Make the operation
    an atomic assembly instruction (OR.W #WFLG_REPORTMOUSE,wd_Flags+2(A0)
    where A0 contains your window pointer).  Most compilers will produce
    an atomic operation when faced with:
                    Window->Flags |= WFLG_REPORTMOUSE;
                    Window->Flags &=~WFLG_REPORTMOUSE;
    or else bracket the operation between Forbid()/Permit().

FUNCTION
    Tells Intuition whether or not to broadcast mouse-movement events to
    your window when it's the active one.  The Boolean value specifies
    whether to start or stop broadcasting position information of
    mouse-movement.  If the window is the active one, mouse-movement
    reports start coming immediately afterwards.  This same routine will
    change the current state of the GACT_FOLLOWMOUSE function of a
    currently-selected gadget too.

    Note that calling ReportMouse() when a gadget is selected will only
    temporarily change whether or not mouse movements are reported while
    that gadget remains selected; the next time the gadget is selected, its
    GACT_FOLLOWMOUSE flag is examined anew.

    Note also that calling ReportMouse() when no gadget is currently
    selected will change the state of the window's WFLG_REPORTMOUSE flag,
    but will have no effect on any gadget that may be subsequently
    selected. (This is all fixed in V36.)

    The ReportMouse() function is first performed when OpenWindow()
    is first called; if the flag WFLG_REPORTMOUSE is included among
    the options, then all mouse-movement events are reported
    to the opening task and will continue to be reported
    until ReportMouse() is called with a Boolean value of FALSE.
    If WFLG_REPORTMOUSE is not set, then no mouse-movement reports will
    be broadcast until ReportMouse() is called with a Boolean of TRUE.

    Note that the WFLG_REPORTMOUSE flag, as managed by this routine,
    determines IF mouse messages are to be broadcast.  Determining HOW
    they are to be broadcast is determined by the IDCMP_MOUSEMOVE
    IDCMPFlag.

INPUTS
    Window = pointer to a Window structure associated with this request
    Boolean = TRUE or FALSE value specifying whether to turn this
         function on or off

RESULT
    None

BUGS
    See above

SEE ALSO
    The Input and Output section of the Intuition Reference Manual


intuition.library/Request

NAME
    Request -- Activate a requester.

SYNOPSIS
    Success = Request( Requester, Window )
    D0                 A0         A1

    BOOL Request( struct Requester *, struct Window * );

FUNCTION
    Links in and displays a requester into the specified window.

    This routine ignores the window's IDCMP_REQVERIFY flag.

INPUTS
    Requester = pointer to the requester to be displayed
    Window = pointer to the window into which this requester goes

    New for V36: the POINTREL flag now has meaning if the requester
    is not a DMR (Double-Menu Requester):
    If POINTREL is set this requester should be placed in the center
    of the window, offset by Requester.RelLeft and Requester.RelTop.
    If the requester doesn't fit in the window, its position will be
    adjusted to show the upper-left corner.

RESULT
    If the requester is successfully opened, TRUE is returned.  Otherwise,
    if the requester could not be opened, FALSE is returned.

BUGS
    There is a maximum of 8 requesters that are supported in
    a window that can be changed in size, position, or depth.

SEE ALSO
    The Requesters section of the Intuition Reference Manual


intuition.library/ResetMenuStrip

NAME
    ResetMenuStrip -- Re-attach a menu strip to a window. (V36)

SYNOPSIS
    Success = ResetMenuStrip( Window, Menu )
    D0                        A0      A1

    BOOL ResetMenuStrip( struct Window *, struct Menu * );

FUNCTION
    This function is simply a "fast" version of SetMenuStrip() that
    doesn't perform the precalculations of menu page sizes that
    SetMenuStrip() does.

    You may call this function ONLY IF the menu strip and all items
    and sub-items have not changed since the menu strip was passed to
    SetMenuStrip(), with the following exceptions:

    - You may change the CHECKED flag to turn a checkmark on or off.
    - You may change the ITEMENABLED flag to enable/disable some
      MenuItem or Menu structures.

    In all other ways, this function performs like SetMenuStrip().

    The new sequence of events you can use is:
    - OpenWindow()
    - SetMenuStrip()
    zero or more iterations of:
        - ClearMenuStrip()
        - change CHECKED or ITEMENABLED flags
        - ResetMenuStrip()
    - ClearMenuStrip()
    - CloseWindow()

INPUTS
    Window = pointer to a Window structure
    Menu = pointer to the first menu in the menu strip

RESULT
    TRUE always.

BUGS

SEE ALSO
    SetMenuStrip(), ClearMenuStrip()


intuition.library/RethinkDisplay

NAME
    RethinkDisplay -- Grand manipulation of the entire Intuition display.

SYNOPSIS
    RethinkDisplay()

    VOID RethinkDisplay( VOID );

FUNCTION
    This function performs the Intuition global display reconstruction.
    This includes rethinking about all of the  ViewPorts and their
    relationship to one another and reconstructing the entire display
    based on the results of this rethinking.

    Specifically, and omitting many internal details, the operation
    consists of this:

        Determine which ViewPorts are invisible and set their VP_HIDE
        ViewPort Mode flag. VP_HIDE flags are also set for screens that
        may not be simultaneously displayed with the frontmost (V36).

        If a change to a viewport height, or changing interlace or
        monitor scan rates require, MakeVPort() is called for specific
        screen viewports.  After this phase, the intermediate Copper lists
        for each screen's viewport are correctly set up.

        MrgCop() and LoadView() are then called to get these Copper lists
        in action, thus establishing the new state of the Intuition
        display.

    You may perform a MakeScreen() on your Custom Screen before calling
    this routine.  The results will be incorporated in the new display, but
    changing the INTERLACE ViewPort mode for one screens must be reflected
    in the Intuition View, which is left to Intuition.

    WARNING:  This routine can take several milliseconds to run, so
    do not use it lightly.

    New for V36: This routine is substantially changed to support
    new screen modes.  In particular, if screen rearrangement has
    caused a change in interlace mode or scan rate, this routine
    will remake the copper lists for each screen's viewport.

INPUTS
    None

RESULT
    None

BUGS
    In V35 and earlier, an interlaced screen coming to the front
    may not trigger a complete remake as required when the global
    interlace state is changed.  In some cases, this can be compensated
    for by setting the viewport DHeight field to 0 for hidden screens.

SEE ALSO
    RemakeDisplay(), graphics.library/MakeVPort(),
    graphics.library/MrgCop(), graphics.library/LoadView(), MakeScreen()


intuition.library/ScreenToBack

NAME
    ScreenToBack -- Send the specified screen to the back of the display.

SYNOPSIS
    ScreenToBack( Screen )
                  A0

    VOID ScreenToBack( struct Screen * );

FUNCTION
    Sends the specified screen to the back of the display.

INPUTS
    Screen = pointer to a Screen structure

RESULT
    None

BUGS

SEE ALSO
    ScreenToFront()


intuition.library/ScreenToFront

NAME
    ScreenToFront -- Make the specified screen the frontmost.

SYNOPSIS
    ScreenToFront( Screen )
                   A0

    VOID ScreenToFront( struct Screen * );

FUNCTION
    Brings the specified Screen to the front of the display.

INPUTS
    Screen = a pointer to a Screen structure

RESULT
    None

BUGS

SEE ALSO
    ScreenToBack()


intuition.library/SetAttrsA

NAME
    SetAttrsA -- Specify attribute values for an object. (V36)
    SetAttrs -- Varargs stub for SetAttrsA(). (V36)

SYNOPSIS
    result = SetAttrsA( Object, TagList )
    D0                  A0      A1

    ULONG SetAttrsA( APTR, struct TagItem * );

    result = SetAttrs( Object, Tag1, ... )

    ULONG SetAttrs( APTR, ULONG, ... );

FUNCTION
    Specifies a set of attribute/value pairs with meaning as
    defined by a 'boopsi' object's class.

    This function does not provide enough context information or
    arbitration for boopsi gadgets which are attached to windows
    or requesters.  For those objects, use SetGadgetAttrs().

INPUTS
    Object = abstract pointer to a boopsi object.
    TagList = array of TagItem structures with attribute/value pairs.

RESULT
    The object does whatever it wants with the attributes you provide.
    The return value tends to be non-zero if the changes would require
    refreshing gadget imagery, if the object is a gadget.

NOTES
    This function invokes the OM_SET method with a NULL GadgetInfo
    parameter.

BUGS

SEE ALSO
    NewObject(), DisposeObject(), GetAttr(), MakeClass(),
    Document "Basic Object-Oriented Programming System for Intuition"
    and the "boopsi Class Reference" document.


intuition.library/SetDefaultPubScreen

NAME
    SetDefaultPubScreen -- Choose a new default public screen. (V36)

SYNOPSIS
    SetDefaultPubScreen( Name )
                         A0

    VOID SetDefaultPubScreen( UBYTE * );

FUNCTION
    Establishes a new default public screen for visitor windows.

    This screen is used by windows asking for a named public screen
    that doesn't exist and the FALLBACK option is selected, and for
    windows asking for the default public screen directly.

INPUTS
    Name = name of chosen public screen to be the new default.
    A value of NULL means that the Workbench screen is to
    be the default public screen.

RESULT
    None

BUGS

SEE ALSO
    OpenWindow(), OpenScreen(), Intuition V36 update documentation


intuition.library/SetDMRequest

NAME
    SetDMRequest -- Set the DMRequest of a window.

SYNOPSIS
    success = SetDMRequest( Window, DMRequest )
    D0                      A0      A1

    BOOL SetDMRequest( struct Window *, struct Requester * );

FUNCTION
    Attempts to set the DMRequest into the specified window.
    The DMRequest is the special requester that you attach to
    the double-click of the menu button which the user can then
    bring up on demand.  This routine WILL NOT change the DMRequest
    if it's already set and is currently active (in use by the user).
    After having called SetDMRequest(), if you want to change the
    DMRequest, the correct way to start is by calling ClearDMRequest()
    until it returns a value of TRUE; then you can call SetDMRequest()
    with the new DMRequest.

    If the POINTREL flag is set in the DMRequest, the DMR will open as
    close to the pointer as possible.  The RelLeft/Top fields are
    for fine-tuning the position.

INPUTS
    Window = pointer to the window from which the DMRequest is to be set
    DMRequest = a pointer to a requester

RESULT
    If the current DMRequest was not in use, sets the DMRequest
        pointer into the window and returns TRUE.
    If the DMRequest was currently in use, doesn't change the pointer
        and returns FALSE

BUGS

SEE ALSO
    ClearDMRequest(), Request()


intuition.library/SetEditHook

NAME
    SetEditHook -- Set global processing for string gadgets. (V36)

SYNOPSIS
    OldHook = SetEditHook( Hook )
    D0                     A0

    struct Hook *SetEditHook( struct Hook * );

FUNCTION
    Sets new global editing hook for string gadgets.

    WARNING: This function is wholly untested.  Do *NOT* use
    this in a commercial product until further notice.

INPUTS
    Hook -- A pointer to a struct Hook which determines a function
      in your code to be called every time the user types a key.
      This is done before control is passed to the gadget custom
      editing hook, so effects ALL string gadgets.

RESULT
    Returns previous global edit hook structure.

BUGS
    Unknown, risky.

SEE ALSO


intuition.library/SetGadgetAttrsA

NAME
    SetGadgetAttrsA -- Specify attribute values for a boopsi gadget. (V36)
    SetGadgetAttrs -- Varargs stub for SetGadgetAttrsA(). (V36)

SYNOPSIS
    result = SetGadgetAttrsA( Gadget, Window, Requester, TagList )
    D0                        A0      A1      A2         A3

    ULONG SetGadgetAttrsA( struct Gadget *, struct Window *,
            struct Requester *, struct TagItem * );

    result = SetGadgetAttrs( Gadget, Window, Requester, Tag1, ...)

    ULONG SetGadgetAttrs( struct Gadget *, struct Window *,
            struct Requester *, ULONG, ... );

FUNCTION
    Same as SetAttrs(), but provides context information and
    arbitration for classes which implement custom Intuition gadgets.

    You should use this function for boopsi gadget objects which have
    already been added to a requester or a window, or for "models" which
    propagate information to gadget already added.

    Typically, the gadgets will refresh their visuals to reflect
    changes to visible attributes, such as the value of a slider,
    the text in a string-type gadget, the selected state of a button.

    You can use this as a replacement for SetAttrs(), too, if you
    specify NULL for the 'Window' and 'Requester' parameters.

INPUTS
    Gadget = abstract pointer to a boopsi gadget
    Window = window gadget has been added to using AddGList() or
             AddGadget()
    Requester = for REQGADGETs, requester containing the gadget
    TagList = array of TagItem structures with attribute/value pairs.

RESULT
    The object does whatever it wants with the attributes you provide,
    which might include updating its gadget visuals.

    The return value tends to be non-zero if the changes would require
    refreshing gadget imagery, if the object is a gadget.

NOTES
    This function invokes the OM_SET method with a GadgetInfo
    derived from the 'Window' and 'Requester' pointers.

BUGS
    There should be more arbitration between this function and
    the calls that Intuition's input task will make to the
    gadgets.  In the meantime, this function, input processing,
    and refreshing must be mutually re-entrant.

SEE ALSO
    NewObject(), DisposeObject(), GetAttr(), MakeClass(),
    Document "Basic Object-Oriented Programming System for Intuition"
    and the "boopsi Class Reference" document.


intuition.library/SetMenuStrip

NAME
    SetMenuStrip -- Attach a menu strip to a window.

SYNOPSIS
    Success = SetMenuStrip( Window, Menu )
    D0                      A0      A1

    BOOL SetMenuStrip( struct Window *, struct Menu * );

FUNCTION
    Attaches the menu strip to the window.  After calling this routine,
    if the user presses the menu button, this specified menu strip
    will be displayed and accessible by the user.

    Menus with zero menu items are not allowed.

    NOTE:  You should always design your menu strip changes to be a
    two-way operation, where for every menu strip you add to your
    window you should always plan to clear that strip sometime.  Even
    in the simplest case, where you will have just one menu strip for
    the lifetime of your window, you should always clear the menu strip
    before closing the window.  If you already have a menu strip attached
    to this window, the correct procedure for changing to a new menu
    strip involves calling ClearMenuStrip() to clear the old first.

    The sequence of events should be:
    - OpenWindow()
    - zero or more iterations of:
    - SetMenuStrip()
    - ClearMenuStrip()
    - CloseWindow()

INPUTS
    Window = pointer to a Window structure
    Menu = pointer to the first menu in the menu strip

RESULT
    TRUE if there were no problems.  TRUE always, since this routine
    will wait until it is OK to proceed.

BUGS

SEE ALSO
    ClearMenuStrip(), ResetMenuStrip()


intuition.library/SetMouseQueue

NAME
    SetMouseQueue -- Change limit on pending mouse messages. (V36)

SYNOPSIS
    oldQueueLength = SetMouseQueue( Window, QueueLength )
    D0                              A0      D0

    LONG SetMouseQueue( struct Window *, UWORD );

FUNCTION
    Changes the number of mouse messages that Intuition will allow
    to be outstanding for your window.

INPUTS
    Window = your window
    QueueLength = the new value of outstanding mouse movement messages
      you wish to allow.

RESULT
    -1 if 'Window' is not known
    Otherwise the previous value of the queue limit.
    The corresponding function for changing the repeat key
    queue limit is not yet implemented.

BUGS

SEE ALSO
    OpenWindow()


intuition.library/SetPointer

NAME
    SetPointer -- Specify a pointer sprite image for a window.

SYNOPSIS
    SetPointer( Window, Pointer, Height, Width, XOffset, YOffset )
                A0      A1       D0      D1     D2       D3

    VOID SetPointer( struct Window *, UWORD *, WORD, WORD, WORD, WORD );

FUNCTION
    Sets up the window with the sprite definition for the pointer.
    Then, whenever the window is the active one, the pointer
    image will change to the window's version.  If the window is
    the active one when this routine is called, the change takes
    place immediately.

    The XOffset and YOffset parameters are used to offset the
    upper-left corner of the hardware sprite image from what Intuition
    regards as the current position of the pointer.  Another way of
    describing it is as the offset from the "hot spot" of the pointer
    to the top-left corner of the sprite.  For instance, if you specify
    offsets of zero, zero, then the top-left corner of your sprite
    image will be placed at the mouse position.  On the other hand,
    if you specify an XOffset of -7 (remember, sprites are 16 pixels
    wide) then your sprite will be centered over the mouse position.
    If you specify an XOffset of -15, the right-edge of the sprite
    will be over the mouse position.

INPUTS
    Window = pointer to the window to receive this pointer definition
    Pointer = pointer to the data definition of a sprite
    Height = the height of the pointer
    Width = the width of the sprite (must be less than or equal to sixteen)
    XOffset = the offset for your sprite from the mouse position
    YOffset = the offset for your sprite from the mouse position

RESULT
    None

BUGS

SEE ALSO
    ClearPointer(), Intuition Reference Manual or Amiga Rom
    Kernel Manual


intuition.library/SetPrefs

NAME
    SetPrefs -- Set Intuition preferences data.

SYNOPSIS
    Prefs = SetPrefs( PrefBuffer, Size, Inform )
    D0                A0          D0    D1

    struct Preferences *SetPrefs( struct Preferences *, LONG, BOOL );

FUNCTION
    Sets new preferences values.  Copies the first 'Size' bytes
    from your preferences buffer to the system preferences table,
    and puts them into effect.

    The 'Inform' parameter, if TRUE, indicates that an IDCMP_NEWPREFS
    message is to be sent to all windows that have the IDCMP_NEWPREFS
    IDCMPFlag set.

    It is legal to set a partial copy of the Preferences structure.
    The most frequently changed values are grouped at the beginning
    of the Preferences structure.

    New for V36:  A new and more extensible method for supplying
    Preferences has been introduced in V36, and relies on file
    system notification.  The Intuition preferences items rely
    also on the IPrefs program.  Certain elements of the
    Preferences structure have been superceded by this new method.
    Pointer changes submitted through SetPrefs() are only heeded
    until the first time IPrefs informs Intuition of a V36-style
    pointer.ilbm preferences file.  The Preferences FontHeight and
    LaceWB fields are respected only from the system-configuration
    file, and never thereafter.  As well, the view centering and
    size apply only to the default monitor, and not to such modes
    as Productivity.  Other fields may be superceded in the future.

INPUTS
    PrefBuffer = pointer to the memory buffer which contains your
        desired settings for Intuition preferences
    Size = the number of bytes in your PrefBuffer, the number of bytes
       you want copied to the system's internal preference settings
    Inform = whether you want the information of a new preferences
        setting propagated to all windows.

NOTES
    Unless you are responding to a user's explicit request to
    change Preferences (for example, you are writing a Preferences
    editor), you should probably avoid using this function.
    The user's Preferences should be respected, not overridden.

RESULT
    Returns your parameter PrefBuffer.

BUGS

SEE ALSO
    GetDefPrefs(), GetPrefs()


intuition.library/SetPubScreenModes

NAME
    SetPubScreenModes -- Establish global public screen behavior. (V36)

SYNOPSIS
    OldModes = SetPubScreenModes( Modes )
    D0                            D0

    UWORD SetPubScreenModes( UWORD );

FUNCTION
    Sets GLOBAL Intuition public screen modes.

INPUTS
    Modes = new global modes flags.  Values for flag bits are:
      SHANGHAI: workbench windows are to be opened on the
            default public screen
      POPPUBSCREEN: when a visitor window is opened, the public
            screen it opens on is to be brought to the front.

RESULT
    OldModes = previous global mode settings

BUGS

SEE ALSO
    OpenScreen(), Intuition V36 update documentation


intuition.library/SetWindowTitles

NAME
    SetWindowTitles -- Set the window's titles for both window and screen.

SYNOPSIS
    SetWindowTitles( Window, WindowTitle, ScreenTitle )
                     A0      A1           A2

    VOID SetWindowTitles( struct Window *, UBYTE *, UBYTE * );

FUNCTION
    Allows you to set the text which appears in the Window and/or Screen
    title bars.

    The window title appears at all times along the window title bar.
    The window's screen title appears at the screen title bar whenever
    this window is the active one.

    When this routine is called, your window title will be changed
    immediately.  If your window is the active one when this routine is
    called, the screen title will be changed immediately.

    You can specify a value of -1 (i.e. (UBYTE *) ~0) for either of
    the title pointers.  This designates that you want Intuition to leave
    the current setting of that particular title alone, and modify
    only the other one.  Of course, you could set both to -1.

    Furthermore, you can set a value of 0 (zero) for either of the
    title pointers.  Doing so specifies that you want no title to
    appear (the title bar will be blank).

    Both of the titles are rendered in the default font of the window's
    screen, as set using OpenScreen().

    In setting the window's title, Intuition may do some other rendering
    in the top border of your window.  If your own rendering sometimes
    appears in your window border areas, you may want to restore the entire
    window border frame.  The function SetWindowTitles() does not do this
    in the newer versions.  The function RefreshWindowFrame() is provided
    to do this kind of thing for you.

INPUTS
    Window = pointer to your window structure
    WindowTitle = pointer to a null-terminated text string, or set to
       either the value of -1 (negative one) or 0 (zero)
    ScreenTitle = pointer to a null-terminated text string, or set to
       either the value of -1 (negative one) or 0 (zero)

RESULT
    None

BUGS

SEE ALSO
    OpenWindow(), RefreshWindowFrame(), OpenScreen()


intuition.library/ShowTitle

NAME
    ShowTitle -- Set the screen title bar display mode.

SYNOPSIS
    ShowTitle( Screen, ShowIt )
               A0      D0

    VOID ShowTitle( struct Screen *, BOOL );

FUNCTION
    This routine sets the SHOWTITLE flag of the specified screen, and
    then coordinates the redisplay of the screen and its windows.

    The screen title bar can appear either in front of or behind
    WFLG_BACKDROP windows.  This is contrasted with the fact that
    non-WFLG_BACKDROP windows always appear in front of the screen title
    bar.  You specify whether you want the screen title bar to be in front
    of or behind the screen's WFLG_BACKDROP windows by calling this
    routine.

    The ShowIt argument should be set to either TRUE or FALSE.  If TRUE,
   the screen's title bar will be shown in front of WFLG_BACKDROP windows
.
   If FALSE, the title bar will be rendered behind all windows.

   When a screen is first opened, the default setting of the SHOWTITLE
   flag is TRUE.

INPUTS
   Screen = pointer to a Screen structure
   ShowIt = Boolean TRUE or FALSE describing whether to show or hide the
       screen title bar

RESULT
   None

BUGS

SEE ALSO


intuition.library/SizeWindow

NAME
    SizeWindow -- Ask Intuition to size a window.

SYNOPSIS
    SizeWindow( Window, DeltaX, DeltaY )
                A0      D0      D1

    VOID SizeWindow( struct Window *, WORD, WORD );

FUNCTION
    This routine sends a request to Intuition asking to size the window
    the specified amounts.  The delta arguments describe how much to
    size the window along the respective axes.

    Note that the window will not be sized immediately, but rather
    will be sized the next time Intuition receives an input event,
    which happens currently at a minimum rate of ten times per second,
    and a maximum of sixty times a second.  You can discover when
    you window has finally been sized by setting the IDCMP_NEWSIZE flag
    of the IDCMP of your window.  See the "Input and Output Methods"
    chapter of The Intuition Reference Manual for description of the IDCMP.

    New for V36: Intuition now will do validity checking on the final
    dimensions.  To change to new absolute dimensions, or to move and
    size a window in one step, use ChangeWindowBox().

    However, limit checking against window MinWidth, MinHeight,
    MaxWidth, and MaxHeight was not done prior to V36, and
    these fields are still ignored (as documented) if you have
    no sizing gadget (WFLG_SIZEGADGET is not set).  The *are*
    respected now (V36) if WFLG_SIZEGADGET is set.

    New for V36: you can determine when the change in size has
    taken effect by receiving the IDCMP_CHANGEWINDOW IDCMP message.

INPUTS
    Window = pointer to the structure of the window to be sized
    DeltaX = signed value describing how much to size the window
     on the x-axis
    DeltaY = signed value describing how much to size the window
     on the y-axis

RESULT
    None

BUGS

SEE ALSO
    ChangeWindowBox(), MoveWindow(), WindowToFront(), WindowToBack()


intuition.library/SysReqHandler

NAME
    SysReqHandler -- Handle system requester input. (V36)

SYNOPSIS
    num = SysReqHandler( Window, IDCMPFlagsPtr, WaitInput )
    D0                   A0      A1             D0

    LONG SysReqHandler( struct Window *, ULONG *, BOOL );

FUNCTION
    Handles input for a window returned by either BuildSysRequest()
    or BuildEasyRequest().  These functions with SysReqHandler()
    you can perform an "asynchronous" EasyRequest() or AutoRequest().
    That is to say, you can perform other processing while you
    wait for the requester to be satisfied.

    Each time this function is called, it will process all
    IDCMPMessages that the window has received.  If the parameter
    'WaitInput' is non-zero, SysReqHandler() will wait for input
    (by calling WaitPort()) if there are no IDCMP messages.

    SysReqHandler() returns the same values as EasyRequest(): A gadget
    ID greater than equal to 0, and  -1 if one of the other IDCMP
    events were received.

    An additional value of -2 is returned if the input processed
    does not satisfy the requester.  In this case, you might
    perform some processing and call SysReqHandler() again.

    Note: this function does NOT terminate the system request.
    Not only must you call FreeSysRequest() to eliminate the request,
    but you may also continue processing after an event which would
    normally terminate a normal call to EasyRequest().

EXAMPLE
    Implementation of EasyRequest() input loop:

    window = BuildEasyRequest( ZZZZ )
    while ( (retval = SysReqHandler( window, idcmp_ptr, TRUE )) == -2 )
    {
        /* loop     */;
    }
    FreeSysRequest( window );

EXAMPLE
    Request a volume, but don't remove the requester when the
    user inserts the wrong disk:

    struct EasyStruct volumeES = {
        sizeof (struct EasyStruct),
        0,
        "Volume Request",
        "Please insert volume %s in any drive.",
        "Cancel"
    };

    Volume *
    getVolume( volname )
    UBYTE   *volname;
    {
        struct Window       *window;
        Volume              *volume = NULL;
        Volume              *findVolume();
        int                 retval;

        window = BuildEasyRequest( NULL, &volumeES, IDCMP_DISKINSERTED,
                  volname );

        while ( (retval = SysReqHandler( window, NULL, TRUE )) != 0 )
        {
            /* not cancelled yet    */

            /* when IDCMP_DISKINSERTED, check for volume */
            if (( retval == -1 ) && (volume = findVolume( volname )))
                break;
        }
        FreeSysRequest( window );
        return ( volume );
    }

INPUTS
    Window = Window pointer returned from BuildSysRequest() or
            BuildEasyRequest().  Those functions can also return
            values '0' or '1', and these values may also be
            passed to SysReqHandler(), which will immediately
            return the same value.

    IDCMPFlagsPtr = If you passed application specific IDCMP
            flags to BuildSysRequest() or BuildEasyRequest(),
            SysReqHandler() will return -1 if that IDCMP message
            is received.  If IDCMPFlagsPtr is non-null, it
            points to a ULONG where the IDCMP class received
            will be copied for your examination.

            This pointer can be NULL if you have provided no
            application specific IDCMP flags or if you do
            not need to know which application specific IDCMP
            event occurred.

            If you provide more than on flag in the flags variable
            this pointer points to, you will have to refresh
            the variable whenever -1 is returned, since the
            variable will have been changed to show just the
            single IDCMP Class bit that caused the return.

    WaitInput = Specifies that you want SysReqHandler() to
            to wait for IDCMP input if there is none pending.

RESULT
    0, 1, ..., N = Successive GadgetID values, for the gadgets
        you specify for the requester.  NOTE: The numbering
        from left to right is actually: 1, 2, ..., N, 0.
        This is for compatibility with AutoRequests which has
        FALSE for the rightmost gadget.

    -1 = Means that one of the caller-supplied IDCMPFlags occurred.
        The IDCMPFlag value is in the longword pointed to by UDCMP_ptr.

    -2 = input processed did not satisfy the requester. One example
        is a keystroke that does not satisfy the requester.  Another
        example is if there is no input pending and you specified
        FALSE for WaitInput.

BUGS

SEE ALSO
    exec.library/WaitPort()


intuition.library/UnlockIBase

NAME
    UnlockIBase -- Surrender an Intuition lock gotten by LockIBase().

SYNOPSIS
    UnlockIBase( Lock )
                 A0

    VOID UnlockIBase( ULONG );

FUNCTION

    Surrenders lock gotten by LockIBase().

    Calling this function when you do not own the specified lock will
    immediately crash the system.

INPUTS
    The value returned by LockIBase() should be passed to this function,
    to specify which internal lock is to be freed.

    Note that the parameter is passed in A0, not D0, for historical
    reasons.

RESULT
    None

BUGS

SEE ALSO
    LockIBase()


intuition.library/UnlockPubScreen

NAME
    UnlockPubScreen -- Release lock on a public screen. (V36)

SYNOPSIS
    UnlockPubScreen( Name, [Screen] )
                     A0    A1

    VOID UnlockPubScreen( UBYTE *, struct Screen * );

FUNCTION
    Releases lock gotten by LockPubScreen().
    It is best to identify the locked public screen by
    the pointer returned from LockPubScreen().  To do this,
    supply a NULL 'Name' pointer and the screen pointer.

    In rare circumstances where it would be more convenient to pass
    a non-NULL pointer to the public screen name string, the
    'Screen' parameter is ignored.

INPUTS
    Name = pointer to name of public screen.  If Name is NULL,
        then argument 'Screen' is used as a direct pointer to
        a public screen.
    Screen = pointer to a public screen.  Used only if Name
        is NULL.  This pointer MUST have been returned
        by LockPubScreen().
        It is safe to call UnlockPubScreen() with NULL Name
        and Screen (the function will have no effect).

RESULT

BUGS

SEE ALSO
    LockPubScreen()


intuition.library/UnlockPubScreenList

NAME
    UnlockPubScreenList -- Release public screen list semaphore. (V36)

SYNOPSIS
    UnlockPubScreenList()

    VOID UnlockPubScreenList( VOID );

FUNCTION
    Releases lock gotten by LockPubScreenList().

INPUTS
    None.

RESULT
    None.

BUGS

SEE ALSO
    LockPubScreenList()


intuition.library/ViewAddress

NAME
    ViewAddress -- Return the address of the Intuition View structure.

SYNOPSIS
    view = ViewAddress()
    D0

    struct View *ViewAddress( VOID );

FUNCTION
    Returns the address of the Intuition View structure.  If you
    want to use any of the graphics, text, or animation primitives
    in your window and that primitive requires a pointer to a view,
    this routine will return the address of the view for you.

INPUTS
    None

RESULT
    Returns the address of the Intuition View structure

BUGS

SEE ALSO
    graphics.library


intuition.library/ViewPortAddress

NAME
    ViewPortAddress -- Return the address of a window's viewport.

SYNOPSIS
    ViewPort = ViewPortAddress( Window )
    D0                          A0

    struct ViewPort *ViewPortAddress( struct Window * );

FUNCTION
    Returns the address of the viewport associated with the specified
    window.  The viewport is actually the viewport of the screen within
    which the window is displayed.  If you want to use any of the graphics,
    text, or animation primitives in your window and that primitive
    requires a pointer to a viewport, you can use this call.

    This pointer is only valid as long as your window's screen remains
    open, which is ensured by keeping your window open.

INPUTS
    Window = pointer to the window for which you want the viewport address

RESULT
    Returns the address of the Intuition ViewPort structure for
    your window's screen .

BUGS
    This routine is unnecessary: you can just use the expression
    &Window->WScreen->ViewPort.

SEE ALSO
    graphics.library


intuition.library/WBenchToBack

NAME
    WBenchToBack -- Send the Workbench screen in back of all screens.

SYNOPSIS
    Success = WBenchToBack()
    D0

    BOOL WBenchToBack( VOID );

FUNCTION
    Causes the Workbench screen, if it's currently opened, to go behind
    all other screens.  This does not 'move' the screen up or down,
    instead only affects the depth-arrangement of the screens.

INPUTS
    None

RESULT
    If the Workbench screen was opened, this function returns TRUE,
    otherwise it returns FALSE.

BUGS

SEE ALSO
    WBenchToFront(), ScreenToFront()


intuition.library/WBenchToFront

NAME
    WBenchToFront -- Bring the Workbench screen in front of all screens.

SYNOPSIS
    Success = WBenchToFront()
    D0

    BOOL WBenchToFront( VOID );

FUNCTION
    Causes the Workbench Screen, if it's currently opened, to come to
    the foreground.  This does not 'move' the screen up or down, instead
    only affects the depth-arrangement of the screen.

INPUTS
    None

RESULT
    If the Workbench screen was opened, this function returns TRUE,
    otherwise it returns FALSE.

BUGS

SEE ALSO
    WBenchToBack(), ScreenToBack()


intuition.library/WindowLimits

NAME
    WindowLimits -- Set the minimum and maximum limits of a window.

SYNOPSIS
    Success = WindowLimits( Window, MinWidth, MinHeight, MaxWidth,
    D0                      A0      D0        D1         D2
                            MaxHeight )
                            D3

    BOOL WindowLimits( struct Window *, WORD, WORD, UWORD, UWORD );

FUNCTION
    Sets the minimum and maximum limits of the window's size.  Until this
    routine is called, the window's size limits are equal to the initial
    values established in the OpenWindow() function.

    After a call to this routine, the Window will be able to be sized
    to any dimensions within the specified limits.

    If you don't want to change any one of the dimensions, set the limit
    argument for that dimension to zero.  If any of the limit arguments
    is equal to zero, that argument is ignored and the initial setting
    of that parameter remains undisturbed.

    If any of the arguments is out of range (minimums greater than the
    current size, maximums less than the current size), that limit
    will be ignored, though the others will still take effect if they
    are in range.  If any are out of range, the return value from this
    procedure will be FALSE.  If all arguments are valid, the return
    value will be TRUE.

    If you want your window to be able to become "as large as possible"
    you may put -1 (i.e. ~0) in either or both Max arguments.  But
    please note: screen sizes may vary for several reasons, and you
    must be able to handle any possible size of window you might end
    up with if you use this method.  Note that you can use the function
    GetScreenData() to find out how big the screen your window appears in
    is.  That function is particularly useful if your window is in
    the Workbench screen.  You may also refer to the WScreen field
    in your window structure, providing that your window remains open,
    which will ensure that the screen remains open, and thus the
    pointer remains valid.

    If the user is currently sizing this window, the new limits will
    not take effect until after the sizing is completed.

INPUTS
    Window = pointer to a Window structure
    MinWidth, MinHeight, MaxWidth, MaxHeight = the new limits for the size
        of this window.  If any of these is set to zero, it will
        be ignored and that setting will be unchanged.

RESULT
    Returns TRUE if everything was in order.  If any of the parameters was
    out of range (minimums greater than current size, maximums less than
    current size), FALSE is returned and the errant limit request is
    not fulfilled (though the valid ones will be).

BUGS

SEE ALSO
    GetScreenData()


intuition.library/WindowToBack

NAME
    WindowToBack -- Ask Intuition to send a window behind others.

SYNOPSIS
    WindowToBack( Window )
                  A0

    VOID WindowToBack( struct Window * );

FUNCTION
    This routine sends a request to Intuition asking to send the window
    in back of all other windows in the screen.

    Note that the window will not be depth-arranged immediately, but rather
    will be arranged the next time Intuition receives an input event,
    which happens currently at a minimum rate of ten times per second,
    and a maximum of sixty times a second.

    Remember that WFLG_BACKDROP windows cannot be depth-arranged.

INPUTS
    Window = pointer to the structure of the window to be sent to the back

RESULT
    None

BUGS

SEE ALSO
    MoveWindow(), SizeWindow(), WindowToFront(), MoveWindowInFrontOf()


intuition.library/WindowToFront

NAME
    WindowToFront -- Ask Intuition to bring a window to the front.

SYNOPSIS
    WindowToFront( Window )
                   A0

    VOID WindowToFront( struct Window * );

FUNCTION
    This routine sends a request to Intuition asking to bring the window
    in front of all other windows in the screen.

    Note that the window will not be depth-arranged immediately, but rather
    will be arranged the next time Intuition receives an input event,
    which happens currently at a minimum rate of ten times per second,
    and a maximum of sixty times a second.

    Remember that WFLG_BACKDROP windows cannot be depth-arranged.

INPUTS
    Window = pointer to the structure of the window to be brought to front

RESULT
    None

BUGS

SEE ALSO
    MoveWindow(), SizeWindow(), WindowToBack(), MoveWindowInFrontOf()


intuition.library/ZipWindow

NAME
    ZipWindow -- Change window to "alternate" position and
                 dimensions. (V36)

SYNOPSIS
    ZipWindow( Window )
               A0

    VOID ZipWindow( struct Window * );

FUNCTION
    Changes the position and dimension of a window to the values
    at the last occasion of ZipWindow being called (or invoked
    via the "zoom" gadget).

    Typically this is used to snap between a normal, large, working
    dimension of the window to a smaller, more innocuous position
    and dimension.

    Like MoveWindow(), SizeWindow(), and ChangeWindowBox(), the action of
    this function is deferred to the Intuition input handler.

    More tuning needs to be done to establish initial values for
    the first invocation of this function for a window.  You can
    provide initial values using the OpenWindow() tag item
    WA_Zoom.

    It could also use a new name, but "ZoomWindow" is misleading,
    since "Zoom" normally implies "scale."

    The zoom gadget will appear (in the place of the old "toback"
    gadget) when you open your window if you either specify a
    sizing gadget or use WA_Zoom.

    You can detect that this function has taken effect by receiving
    an IDCMP_CHANGEWINDOW IDCMP message.

INPUTS
    Window -- window to be changed.

RESULT
    None

BUGS
    OpenWindow() assumes that the proper default "other" dimensions
    are "full size."

SEE ALSO
    ChangeWindowBox(), MoveWindow(), SizeWindow()


mathtrans.doc

 SPAcos()      SPExp()        SPSin()         SPTanh()
 SPAsin()      SPFieee()      SPSincos()      SPTieee()
 SPAtan()      SPLog()        SPSinh()
 SPCos()       SPLog10()      SPSqrt()
 SPCosh()      SPPow()        SPTan()


mathtrans.library/SPAcos

NAME
    SPAcos - obtain the arccosine of the floating point number

SYNOPSIS
    fnum2 = SPAcos(fnum1);
                   d0.l
    float fnum2;
    float fnum1;

FUNCTION
    Accepts a floating point number representing the cosine
    of an angle and returns the value of said angle in
    radians

INPUTS
    fnum1 - Motorola fast floating point number

RESULT
    fnum2 - Motorola fast floating point number

BUGS
    None

SEE ALSO
    SPSin


mathtrans.library/SPAsin

NAME
    SPAsin - obtain the arcsine of the floating point number

SYNOPSIS
    fnum2 = SPAsin(fnum1);
                   d0.l
    float fnum2;
    float fnum1;

FUNCTION
    Accepts a floating point number representing the sine
    of an angle and returns the value of said angle in
    radians

INPUTS
    fnum1 - Motorola fast floating point number

RESULT
    fnum2 - Motorola fast floating point number

BUGS
    None

SEE ALSO
    SPCos


mathtrans.library/SPAtan

NAME
    SPAtan - obtain the arctangent of the floating point number

SYNOPSIS
    fnum2 = SPAtan(fnum1);
                   d0.l
    float fnum2;
    float fnum1;

FUNCTION
    Accepts a floating point number representing the tangent
    of an angle and returns the value of said angle in
    radians

INPUTS
    fnum1 - Motorola fast floating point number

RESULT
    fnum2 - Motorola fast floating point number

BUGS
    None

SEE ALSO
    SPTan


mathtrans.library/SPCos

NAME
    SPCos - obtain the cosine of the floating point number

SYNOPSIS
    fnum2 = SPCos(fnum1);
                   d0.l
    float fnum2;
    float fnum1;

FUNCTION
    Accepts a floating point number representing an angle
    in radians and returns the cosine of said angle.

INPUTS
    fnum1 - Motorola fast floating point number

RESULT
    fnum2 - Motorola fast floating point number

BUGS
    None

SEE ALSO
    SPAcos


mathtrans.library/SPCosh

NAME
    SPCosh - obtain the hyperbolic cosine of the floating point number

SYNOPSIS
    fnum2 = SPCosh(fnum1);
                   d0.l
    float fnum2;
    float fnum1;

FUNCTION
    Accepts a floating point number representing an angle
    in radians and returns the hyperbolic cosine of said angle.

INPUTS
    fnum1 - Motorola fast floating point number

RESULT
    fnum2 - Motorola fast floating point number

BUGS
    None

SEE ALSO
    SPSinh


mathtrans.library/SPExp

NAME
    SPExp - obtain the exponential (e**X) of the floating point number

SYNOPSIS
    fnum2 = SPExp(fnum1);
                  d0.l
    float fnum2;
    float fnum1;

FUNCTION
    Accepts a floating point number and returns the value
    of e raised to the fnum1 power

INPUTS
    fnum1 - Motorola fast floating point number

RESULT
    fnum2 - Motorola fast floating point number

BUGS
    None

SEE ALSO
    SPLog


mathtrans.library/SPFieee

NAME
    SPFieee - convert single precision ieee to FFP number

SYNOPSIS
    fnum = SPFieee(ieeenum);
                   d0.l
    float fnum;
    float ieeenum;

FUNCTION
    Accepts a standard single precision format
    returns the same number, converted to Motorola
    fast floating point number

INPUTS
    ieeenum - IEEE Single Precision Floating Point

RESULT
    fnum - Motorola fast floating point number

BUGS
    None

SEE ALSO
    SPTieee


mathtrans.library/SPLog

NAME
    SPLog - obtain the natural logarithm of the floating point number

SYNOPSIS
    fnum2 = SPLog(fnum1);
                  d0.l
    float fnum2;
    float fnum1;

FUNCTION
    Accepts a floating point number and returns the natural
    logarithem (base e) of said number

INPUTS
    fnum1 - Motorola fast floating point number

RESULT
    fnum2 - Motorola fast floating point number

BUGS
    None

SEE ALSO
    SPExp


mathtrans.library/SPLog10

NAME
    SPLog10 - obtain the naperian logarithm(base 10) of the
              floating point number

SYNOPSIS
    fnum2 = SPLog10(fnum1);
                    d0.l
    float fnum2;
    float fnum1;

FUNCTION
    Accepts a floating point number and returns the naperian
    logarithm (base 10) of said number

INPUTS
    fnum1 - Motorola fast floating point number

RESULT
    fnum2 - Motorola fast floating point number

BUGS
    None

SEE ALSO
    SPExp, SpLog


mathtrans.library/SPPow

NAME
    SPPow - raise a number to a power

SYNOPSIS
    result = SPPow(fnum1, fnum2);
                  d1.l    d0.l
    float fnum1, fnum2;
    float result;

FUNCTION
    Accepts two floating point numbers and returns the
    result of fnum2 raised to the fnum1 power

INPUTS
    fnum1 - Motorola fast floating point number
    fnum2 - Motorola fast floating point number

RESULT
    result - Motorola fast floating point number

BUGS
    None

SEE ALSO
    SPExp, SPLog


mathtrans.library/SPSin

NAME
    SPSin - obtain the sine of the floating point number

SYNOPSIS
    fnum2 = SPSin(fnum1);
                   d0.l
    float fnum2;
    float fnum1;

FUNCTION
    Accepts a floating point number representing an angle
    in radians and returns the sine of said angle.

INPUTS
    fnum1 - Motorola fast floating point number

RESULT
    fnum2 - Motorola fast floating point number

BUGS
    None

SEE ALSO
    SPAsin


mathtrans.library/SPSincos

NAME
    SPSincos - obtain the sine and cosine of a number

SYNOPSIS
    fnum3 = SPSincos(pfnum2, fnum1);
                     d1.l,   d0.l
    float *pfnum2;
    float fnum1;
    float fnum3;

FUNCTION
    Accepts a floating point number (fnum1) representing
    an angle in radians and a pointer to another floating
    point number (pfnum2). It computes the cosine and places it in
    *pfnum2. It computes the sine and returns it as a result.

INPUTS
    fnum1 - Motorola fast floating point number
    pfnum2 - pointer to Motorola fast floating point number

RESULT
    *pfnum2 - Motorola fast floating point number (cosine)
    fnum3 - Motorola fast floating point number (sine)

BUGS
    None

SEE ALSO
    SPSin, SPCos


mathtrans.library/SPSinh

NAME
    SPSinh - obtain the hyperbolic sine of the floating point number

SYNOPSIS
    fnum2 = SPSinh(fnum1);
                   d0.l
    float fnum2;
    float fnum1;

FUNCTION
    Accepts a floating point number representing an angle
    in radians and returns the hyperbolic sine of said angle.

INPUTS
    fnum1 - Motorola fast floating point number

RESULT
    fnum2 - Motorola fast floating point number

BUGS
    None

SEE ALSO
    SPCosh


mathtrans.library/SPSqrt

NAME
    SPSqrt - obtain the square root of the floating point number

SYNOPSIS
    fnum2 = SPSqrt(fnum1);
                  d0.l
    float fnum2;
    float fnum1;

FUNCTION
    Accepts a floating point number and returns the square toot
    of said number

INPUTS
    fnum1 - Motorola fast floating point number

RESULT
    fnum2 - Motorola fast floating point number

BUGS
    None

SEE ALSO
    SPPow, SPMul


mathtrans.library/SPTan

NAME
    SPTan - obtain the tangent of the floating point number

SYNOPSIS
    fnum2 = SPTan(fnum1);
                   d0.l
    float fnum2;
    float fnum1;

FUNCTION
    Accepts a floating point number representing an angle
    in radians and returns the tangent of said angle.

INPUTS
    fnum1 - Motorola fast floating point number

RESULT
    fnum2 - Motorola fast floating point number

BUGS
    None

SEE ALSO
    SPAtan


mathtrans.library/SPTanh

NAME
    SPTanh - obtain the hyperbolic tangent of the floating point number

SYNOPSIS
    fnum2 = SPTanh(fnum1);
                   d0.l
    float fnum2;
    float fnum1;

FUNCTION
    Accepts a floating point number representing an angle
    in radians and returns the hyperbolic tangent of said angle.

INPUTS
    fnum1 - Motorola fast floating point number

RESULT
    fnum2 - Motorola fast floating point number

BUGS
    None

SEE ALSO
    SPSinh, SPCosh


mathtrans.library/SPTieee

NAME
    SPTieee - convert FFP number to single precision ieee

SYNOPSIS
    ieeenum = SPTieee(fnum);
                     d0.l
    float ieeenum;
    float fnum;

FUNCTION
    Accepts a Motorola fast floating point number and
    returns the same number, converted into IEEE
    standard single precision format

INPUTS
    fnum - Motorola fast floating point number

RESULT
    ieeenum - IEEE Single Precision Floating Point

BUGS
    None

SEE ALSO
    SPFieee


dos.doc

 AbortPkt()                FPuts()                   Read()
 AddBuffers()              FRead()                   ReadArgs()
 AddDosEntry()             FreeArgs()                ReadItem()
 AddPart()                 FreeDeviceProc()          ReadLink()
 AddSegment()              FreeDosEntry()            Relabel()
 AllocDosObject()          FreeDosObject()           RemAssignList()
 AssignAdd()               FWrite()                  RemDosEntry()
 AssignLate()              GetArgStr()               RemSegment()
 AssignLock()              GetConsoleTask()          Rename()
 AssignPath()              GetCurrentDirName()       ReplyPkt()
 AttemptLockDosList()      GetDeviceProc()           RunCommand()
 ChangeMode()              GetFileSysTask()          SameDevice()
 CheckSignal()             GetProgramDir()           SameLock()
 Cli()                     GetProgramName()          Seek()
 CliInitNewcli()           GetPrompt()               SelectInput()
 CliInitRun()              GetVar()                  SelectOutput()
 Close()                   Info()                    SendPkt()
 CompareDates()            Inhibit()                 SetArgStr()
 CreateDir()               Input()                   SetComment()
 CreateNewProc()           InternalLoadSeg()         SetConsoleTask()
 CreateProc()              InternalUnLoadSeg()       SetCurrentDirName()
 CurrentDir()              IoErr()                   SetFileDate()
 DateStamp()               IsFileSystem()            SetFileSize()
 DateToStr()               IsInteractive()           SetFileSysTask()
 Delay()                   LoadSeg()                 SetIoErr()
 DeleteFile()              Lock()                    SetMode()
 DeleteVar()               LockDosList()             SetProgramDir()
 DeviceProc()              LockRecord()              SetProgramName()
 DoPkt()                   LockRecords()             SetPrompt()
 DupLock()                 MakeDosEntry()            SetProtection()
 DupLockFromFH()           MakeLink()                SetVar()
 EndNotify()               MatchEnd()                SetVBuf()
 ErrorReport()             MatchFirst()              SplitName()
 ExAll()                   MatchNext()               StartNotify()
 Examine()                 MatchPattern()            StrToDate()
 ExamineFH()               MatchPatternNoCase()      StrToLong()
 Execute()                 MaxCli()                  SystemTagList()
 Exit()                    NameFromFH()              UnGetC()
 ExNext()                  NameFromLock()            UnLoadSeg()
 Fault()                   NewLoadSeg()              UnLock()
 FGetC()                   NextDosEntry()            UnLockDosList()
 FGets()                   Open()                    UnLockRecord()
 FilePart()                OpenFromLock()            UnLockRecords()
 FindArg()                 Output()                  VFPrintf()
 FindCliProc()             ParentDir()               VFWritef()
 FindDosEntry()            ParentOfFH()              VPrintf()
 FindSegment()             ParsePattern()            WaitForChar()
 FindVar()                 ParsePatternNoCase()      WaitPkt()
 Flush()                   PathPart()                Write()
 Format()                  PrintFault()              WriteChars()
 FPutC()                   PutStr()


dos.library/AbortPkt

NAME
    AbortPkt -- Aborts an asynchronous packet, if possible. (V36)

SYNOPSIS
    AbortPkt(port, pkt)
              D1    D2

    void AbortPkt(struct MsgPort *, struct DosPacket *)

FUNCTION
    This attempts to abort a packet sent earlier with SendPkt to a
    handler.  There is no guarantee that any given handler will allow
    a packet to be aborted, or if it is aborted whether function
    requested completed first or completely.  After calling AbortPkt(),
    you must wait for the packet to return before reusing it or
    deallocating it.

INPUTS
    port - port the packet was sent to
    pkt  - the packet you wish aborted

BUGS
    As of V37, this function does nothing.

SEE ALSO
    SendPkt(), DoPkt(), WaitPkt()


dos.library/AddBuffers

NAME
    AddBuffers -- Changes the number of buffers for a filesystem (V36)

SYNOPSIS
    success = AddBuffers(filesystem, number)
    D0                     D1          D2

    BOOL AddBuffers(STRPTR, LONG)

FUNCTION
    Adds buffers to a filesystem.  If it succeeds, the number of current
    buffers is returned in IoErr().  Note that "number" may be negative.
    The amount of memory used per buffer, and any limits on the number of
    buffers, are dependant on the filesystem in question.
    If the call succeeds, the number of buffers in use on the filesystem
    will be returned by IoErr().

INPUTS
    filesystem - Name of device to add buffers to (with ':').
    number     - Number of buffers to add.  May be negative.

RESULT
    success    - Success or failure of command.

BUGS
    The V36 ROM filesystem (FFS/OFS) doesn't return the right number of
    buffers unless preceded by an AddBuffers(fs,-1) (in-use buffers aren't
    counted).  This is fixed in V37.

    The V37 and before ROM filesystem doesn't return success, it returns
    the number of buffers.  The best way to test for this is to consider
    0 (FALSE) failure, -1 (DOSTRUE) to mean that IoErr() will have the
    number of buffers, and any other positive value to be the number of
    buffers.  It may be fixed in some future ROM revision.

SEE ALSO
    IoErr()


dos.library/AddDosEntry

NAME
    AddDosEntry -- Add a Dos List entry to the lists (V36)

SYNOPSIS
    success = AddDosEntry(dlist)
    D0                     D1

    LONG AddDosEntry(struct DosList *)

FUNCTION
    Adds a device, volume or assign to the dos devicelist.  Can fail if it
    conflicts with an existing entry (such as another assign to the same
    name or another device of the same name).  Volume nodes with different
    dates and the same name CAN be added, or with names that conflict with
    devices or assigns.  Note: the dos list does NOT have to be locked to
    call this.  Do not access dlist after adding unless you have locked the
    Dos Device list.

    An additional note concerning calling this from within a handler:
    in order to avoid deadlocks, your handler must either be multi-
    threaded, or it must attempt to lock the list before calling this
    function.  The code would look something like this:

    if (AttemptLockDosList(LDF_xxx|LDF_WRITE))
    {
            rc = AddDosEntry(...);
            UnLockDosList(LDF_xxx|LDF_WRITE);
    }

    If AttemptLockDosList() fails (i.e. it's locked already), check for
    messages at your filesystem port (don't wait!) and try the
    AttemptLockDosList() again.

INPUTS
    dlist   - Device list entry to be added.

RESULT
    success - Success/Failure indicator

SEE ALSO
    RemDosEntry(), FindDosEntry(), NextDosEntry(), LockDosList(),
    MakeDosEntry(), FreeDosEntry(), AttemptLockDosList()


dos.library/AddPart

NAME
    AddPart -- Appends a file/dir to the end of a path (V36)

SYNOPSIS
    success = AddPart( dirname, filename, size )
    D0                   D1        D2      D3

    BOOL AddPart( STRPTR, STRPTR, ULONG )

FUNCTION
    This function adds a file, directory, or subpath name to a directory
    path name taking into account any required separator characters.  If
    filename is a fully-qualified path it will totally replace the current
    value of dirname.

INPUTS
    dirname  - the path to add a file/directory name to.
    filename - the filename or directory name to add.  May be a relative
               pathname from the current directory (example: foo/bar).
               Can deal with leading '/'(s), indicating one directory up
               per '/', or with a ':', indicating it's relative to the
               root of the appropriate volume.
    size     - size in bytes of the space allocated for dirname.  Must
               not be 0.

RESULT
    success - non-zero for ok, FALSE if the buffer would have overflowed.
              If an overflow would have occured, dirname will not be
              changed.

BUGS
    Doesn't check if a subpath is legal (i.e. doesn't check for ':'s) and
    doesn't handle leading '/'s in 2.0 through 2.02 (V36).  V37 fixes
    this, allowing filename to be any path, including absolute.

SEE ALSO
    Filepart(), PathPart()


dos.library/AddSegment

NAME
    AddSegment - Adds a resident segment to the resident list (V36)

SYNOPSIS
    success = AddSegment(name, seglist, type)
    D0                    D1     D2      D3

    BOOL AddSegment(STRPTR, BPTR, LONG)

FUNCTION
    Adds a segment to the Dos resident list, with the specified Seglist
    and type (stored in seg_UC - normally 0).  NOTE: currently unused
    types may cause it to interpret other registers (d4-?) as additional
    parameters in the future.

    Do NOT build Segment structures yourself!

INPUTS
    name    - name for the segment
    seglist - Dos seglist of code for segment
    type    - initial usecount, normally 0

RESULT
    success - success or failure

SEE ALSO
    FindSegment(), RemSegment(), LoadSeg()


dos.library/AllocDosObject

NAME
    AllocDosObject -- Creates a dos object (V36)

SYNOPSIS
    ptr = AllocDosObject(type, tags)
    D0                    D1    D2

    void *AllocDosObject(ULONG, struct TagItem *)

    ptr = AllocDosObjectTagList(type, tags)
    D0                           D1    D2

    void *AllocDosObjectTagList(ULONG, struct TagItem *)

    ptr = AllocDosObjectTags(type, Tag1, ...)

    void *AllocDosObjectTags(ULONG, ULONG, ...)

FUNCTION
    Create one of several dos objects, initializes it, and returns it
    to you.  Note the DOS_STDPKT returns a pointer to the sp_Pkt of the
    structure.

INPUTS
    type - type of object requested
    tags - pointer to taglist with additional information

RESULT
    packet - pointer to the object or NULL

SEE ALSO
    FreeDosObject(), <dos/dostags.h>, <dos/dos.h>


dos.library/AssignAdd

NAME
    AssignAdd -- Adds a lock to an assign for multi-directory assigns (V36)

SYNOPSIS
    success = AssignAdd(name,lock)
    D0                   D1   D2

    BOOL AssignAdd(STRPTR,BPTR)

FUNCTION
    Adds a lock to an assign, making or adding to a multi-directory
    assign.  Note that this only will succeed on an assign created with
    AssignLock(), or an assign created with AssignLate() which has been
    resolved (converted into a AssignLock()-assign).

    NOTE: you should not use the lock in any way after making this call
    successfully.  It becomes the part of the assign, and will be unlocked
    by the system when the assign is removed.  If you need to keep the
    lock, pass a lock from DupLock() to AssignLock().

INPUTS
    name - Name of device to assign lock to (without trailing ':')
    lock - Lock associated with the assigned name

RESULT
    success - Success/failure indicator.  On failure, the lock is not
              unlocked.

SEE ALSO
    Lock(), AssignLock(), AssignPath(), AssignLate(), DupLock(),
    RemAssignList()


dos.library/AssignLate

NAME
    AssignLate -- Creates an assignment to a specified path later (V36)

SYNOPSIS
    success = AssignLate(name,path)
    D0                    D1   D2

    BOOL AssignLate(STRPTR,STRPTR)

FUNCTION
    Sets up a assignment that is expanded upon the FIRST reference to the
    name.  The path (a string) would be attached to the node.  When
    the name is referenced (Open("FOO:xyzzy"...), the string will be used
    to determine where to set the assign to, and if the directory can be
    locked, the assign will act from that point on as if it had been
    created by AssignLock().

    A major advantage is assigning things to unmounted volumes, which
    will be requested upon access (useful in startup sequences).

INPUTS
    name - Name of device to be assigned (without trailing ':')
    path - Name of late assignment to be resolved on the first reference.

RESULT
    success - Success/failure indicator of the operation

SEE ALSO
    Lock(), AssignAdd(), AssignPath(), AssignLock(),


dos.library/AssignLock

NAME
    AssignLock -- Creates an assignment to a locked object (V36)

SYNOPSIS
    success = AssignLock(name,lock)
    D0                    D1   D2

    BOOL AssignLock(STRPTR,BPTR)

FUNCTION
    Sets up an assign of a name to a given lock.  Passing NULL for a lock
    cancels any outstanding assign to that name.  If an assign entry of
    that name is already on the list, this routine replaces that entry.  If
    an entry is on the list that conflicts with the new assign, then a
    failure code is returned.

    NOTE: you should not use the lock in any way after making this call
    successfully.  It becomes the assign, and will be unlocked by the
    system when the assign is removed.  If you need to keep the lock,
    pass a lock from DupLock() to AssignLock().

INPUTS
    name - Name of device to assign lock to (without trailing ':')
    lock - Lock associated with the assigned name

RESULT
    success - Success/failure indicator.  On failure, the lock is not
              unlocked.

SEE ALSO
    Lock(), AssignAdd(), AssignPath(), AssignLate(), DupLock(),
    RemAssignList()


dos.library/AssignPath

NAME
    AssignPath -- Creates an assignment to a specified path (V36)

SYNOPSIS
    success = AssignPath(name,path)
    D0                    D1   D2

    BOOL AssignPath(STRPTR,STRPTR)

FUNCTION
    Sets up a assignment that is expanded upon EACH reference to the name.
    This is implemented through a new device list type (DLT_ASSIGNPATH, or
    some such).  The path (a string) would be attached to the node.  When
    the name is referenced (Open("FOO:xyzzy"...), the string will be used
    to determine where to do the open.  No permanent lock will be part of
    it.  For example, you could AssignPath() c2: to df2:c, and references
    to c2: would go to df2:c, even if you change disks.

    The other major advantage is assigning things to unmounted volumes,
    which will be requested upon access (useful in startup sequences).

INPUTS
    name - Name of device to be assigned (without trailing ':')
    path - Name of late assignment to be resolved at each reference

RESULT
    success - Success/failure indicator of the operation

SEE ALSO
    AssignAdd(), AssignLock(), AssignLate(), Open()


dos.library/AttemptLockDosList

NAME
    AttemptLockDosList -- Attempt to lock the Dos Lists for use (V36)

SYNOPSIS
    dlist = AttemptLockDosList(flags)
    D0                          D1

    struct DosList *AttemptLockDosList(ULONG)

FUNCTION
    Locks the dos device list in preparation to walk the list.  If the
    list is 'busy' then this routine will return NULL.  See LockDosList()
    for more information.

INPUTS
    flags - Flags stating which types of nodes you want to lock.

RESULT
    dlist - Pointer to the beginning of the list or NULL.  Not a valid
            node!

SEE ALSO
    LockDosList(), UnLockDosList(), Forbid(), NextDosEntry()


dos.library/ChangeMode

NAME
    ChangeMode - Change the current mode of a lock or filehandle (V36)

SYNOPSIS
    success = ChangeMode(type, object, newmode)
    D0                    D1     D2      D3

    BOOL ChangeMode(ULONG, BPTR, ULONG)

FUNCTION
    This allows you to attempt to change the mode in use by a lock or
    filehandle.  For example, you could attempt to turn a shared lock
    into an exclusive lock.  The handler may well reject this request.
    Warning: if you use the wrong type for the object, the system may
    crash.

INPUTS
    type    - Either CHANGE_FH or CHANGE_LOCK
    object  - A lock or filehandle
    newmode - The new mode you want

RESULT
    success - Boolean

BUGS
    Did not work in 2.02 or before (V36).  Works in V37.  In the
    earlier versions, it can crash the machine.

SEE ALSO
    Lock(), Open()


dos.library/CheckSignal

NAME
    CheckSignal -- Checks for break signals (V36)

SYNOPSIS
    signals = CheckSignal(mask)
    D0                    D1

    ULONG CheckSignals(ULONG)

FUNCTION
    This function checks to see if any signals specified in the mask have
    been set and if so, returns them.  Otherwise it returns FALSE.
    All signals specified in mask will be cleared.

INPUTS
    mask    - Signals to check for.

RESULT
    signals - Signals specified in mask that were set.

SEE ALSO


dos.library/Cli

NAME
    Cli -- Returns a pointer to the CLI structure of the process (V36)

SYNOPSIS
    cli_ptr = Cli()
    D0

    struct CommandLineInterface *Cli(void)

FUNCTION
    Returns a pointer to the CLI structure of the current process, or NULL
    if the process has no CLI structure.

RESULT
    cli_ptr - pointer to the CLI structure, or NULL.

SEE ALSO


dos.library/CliInitNewcli

NAME
    CliInitNewcli -- Set up a process to be a shell from initial packet

SYNOPSIS
    flags = CliInitNewcli( packet )
    D0                       A0

    LONG CliInitNewcli( struct DosPacket * )

FUNCTION
    This function initializes a process and CLI structure for a new
    shell, from parameters in an initial packet passed by the system
    (NewShell or NewCLI, etc).  The format of the data in the packet
    is purposely not defined.  The setup includes all the normal fields
    in the structures that are required for proper operation (current
    directory, paths, input streams, etc).

    It returns a set of flags containing information about what type
    of shell invocation this is.

    Definitions for the values of fn:
            Bit 31     Set to indicate flags are valid
            Bit  3     Set to indicate asynch system call
            Bit  2     Set if this is a System() call
            Bit  1     Set if user provided input stream
            Bit  0     Set if RUN provided output stream

    If Bit 31 is 0, then you must check IoErr() to determine if an error
    occurred.  If IoErr() returns a pointer to your process, there has
    been an error, and you should clean up and exit.  The packet will
    have already been returned by CliInitNewcli().  If it isn't a pointer
    to your process and Bit 31 is 0, reply the packet immediately.
    (Note: this is different from what you do for CliInitRun().)

    This function is very similar to CliInitRun().

INPUTS
    packet - the initial packet sent to your process MsgPort

RESULT
    fn - flags or a pointer

SEE ALSO
    CliInitRun(), ReplyPkt(), WaitPkt(), IoErr()


dos.library/CliInitRun

NAME
    CliInitRun -- Set up a process to be a shell from initial packet

SYNOPSIS
    flags = CliInitRun( packet )
    D0                    A0

    LONG CliInitRun( struct DosPacket * )

FUNCTION
    This function initializes a process and CLI structure for a new
    shell, from parameters in an initial packet passed by the system
    (Run, System(), Execute()).  The format of the data in the packet
    is purposely not defined.  The setup includes all the normal fields
    in the structures that are required for proper operation (current
    directory, paths, input streams, etc).

    It returns a set of flags containing information about what type
    of shell invocation this is.

    Definitions for the values of fn:
            Bit 31     Set to indicate flags are valid
            Bit  3     Set to indicate asynch system call
            Bit  2     Set if this is a System() call
            Bit  1     Set if user provided input stream
            Bit  0     Set if RUN provided output stream

    If Bit 31 is 0, then you must check IoErr() to determine if an error
    occurred.  If IoErr() returns a pointer to your process, there has
    been an error, and you should clean up and exit.  The packet will
    have already been returned by CliInitNewcli().  If it isn't a pointer
    to your process and Bit 31 is 0, you should wait before replying
    the packet until after you've loaded the first command (or when you
    exit).  This helps avoid disk "gronking" with the Run command.
    (Note: this is different from what you do for CliInitNewcli().)

    If Bit 31 is 1, then if Bit 3 is one, ReplyPkt() the packet
    immediately (Asynch System()), otherwise wait until your shell exits
    (Sync System(), Execute()).
    (Note: this is different from what you do for CliInitNewcli().)

    This function is very similar to CliInitNewcli().

INPUTS
    packet - the initial packet sent to your process MsgPort

RESULT
    fn - flags or a pointer

SEE ALSO
    CliInitNewcli(), ReplyPkt(), WaitPkt(), System(), Execute(), IoErr()


dos.library/Close

NAME
    Close -- Close an open file

SYNOPSIS
    success = Close( file )
       D0             D1

    BOOL Close(BPTR)

FUNCTION
    The file specified by the file handle is closed. You must close all
    files you explicitly opened, but you must not close inherited file
    handles that are passed to you (each filehandle must be closed once
    and ONLY once).  If Close() fails, the file handle is still
    deallocated and should not be used.

INPUTS
    file - BCPL pointer to a file handle

RESULTS
    success - returns if Close() succeeded.  Note that it might fail
              depending on buffering and whatever IO must be done to
              close a file being written to.  NOTE: this return value
              did not exist before V36!

SEE ALSO
    Open(), OpenFromLock()


dos.library/CompareDates

NAME
    CompareDates -- Compares two datestamps (V36)

SYNOPSIS
    result = CompareDates(date1,date2)
    D0                     D1     D2

    LONG CompareDates(struct DateStamp *,struct DateStamp *)

FUNCTION
    Compares two times for relative magnitide.  <0 is returned if date1 is
    later than date2, 0 if they are equal, or >0 if date2 is later than
    date1.  NOTE: this is NOT the same ordering as strcmp!

INPUTS
    date1, date2 - DateStamps to compare

RESULT
    result -  <0, 0, or >0 based on comparison of two date stamps

SEE ALSO
    DateStamp(), DateToStr(), StrToDate()


dos.library/CreateDir

NAME
    CreateDir -- Create a new directory

SYNOPSIS
    lock = CreateDir( name )
    D0                D1

    BPTR CreateDir(STRPTR)

FUNCTION
    CreateDir creates a new directory with the specified name. An error
    is returned if it fails.  Directories can only be created on
    devices which support them, e.g. disks.  CreateDir returns an
    exclusive lock on the new directory if it succeeds.

INPUTS
    name - pointer to a null-terminated string

RESULTS
    lock - BCPL pointer to a lock or NULL for failure.

SEE ALSO
    Lock(), UnLock()


dos.library/CreateNewProc

NAME
    CreateNewProc -- Create a new process (V36)

SYNOPSIS
    process = CreateNewProc(tags)
    D0                       D1

    struct Process *CreateNewProc(struct TagItem *)

    process = CreateNewProcTagList(tags)
    D0                              D1

    struct Process *CreateNewProcTagList(struct TagItem *)

    process = CreateNewProcTags(Tag1, ...)

    struct Process *CreateNewProcTags(ULONG, ...)

FUNCTION
    This creates a new process according to the tags passed in.  See
    dos/dostags.h for the tags.

    You must specify one of NP_Seglist or NP_Entry.  NP_Seglist takes a
    seglist (as returned by LoadSeg()).  NP_Entry takes a function
    pointer for the routine to call.

    There are many options, as you can see by examining dos/dostags.h.
    The defaults are for a non-CLI process, with copies of your
    CurrentDir, HomeDir (used for PROGDIR:), priority, consoletask,
    windowptr, and variables.  The input and output filehandles default
    to opens of NIL:, stack to 4000, and others as shown in dostags.h.
    This is a fairly reasonable default setting for creating threads,
    though you may wish to modify it (for example, to give a descriptive
    name to the process.)

    CreateNewProc() is callable from a task, though any actions that
    require doing Dos I/O (DupLock() of currentdir, for example) will not
    occur.

    NOTE: if you call CreateNewProc() with both NP_Arguments, you must
    not specify an NP_Input of NULL.  When NP_Arguments is specified, it
    needs to modify the input filehandle to make ReadArgs() work properly.

INPUTS
    tags - a pointer to a TagItem array.

RESULT
    process - The created process, or NULL.  Note that if it returns
              NULL, you must free any items that were passed in via
              tags, such as if you passed in a new current directory
              with NP_CurrentDir.

BUGS
    In V36, NP_Arguments was broken in a number of ways, and probably
    should be avoided (instead you should start a small piece of your
    own code, which calls RunCommand() to run the actual code you wish
    to run).  In V37, NP_Arguments works, though see the note above.

SEE ALSO
    LoadSeg(), CreateProc(), ReadArgs(), RunCommand(), <dos/dostags.h>


dos.library/CreateProc

NAME

    CreateProc -- Create a new process

SYNOPSIS
    process = CreateProc( name, pri, seglist, stackSize )
    D0                    D1    D2   D3       D4

    struct MsgPort *CreateProc(STRPTR, LONG, BPTR, LONG)

FUNCTION
    CreateProc() creates a new AmigaDOS process of name 'name'.  AmigaDOS
    processes are a superset of exec tasks.

    A seglist, as returned by LoadSeg(), is passed as 'seglist'.
    This represents a section of code which is to be run as a new
    process. The code is entered at the first hunk in the segment list,
    which should contain suitable initialization code or a jump to
    such.  A process control structure is allocated from memory and
    initialized.  If you wish to fake a seglist (that will never
    have DOS UnLoadSeg() called on it), use this code:

                DS.L    0   ;Align to longword
                DC.L    16  ;Segment "length" (faked)
                DC.L    0   ;Pointer to next segment
                ...start of code...

    The size of the root stack upon activation is passed as
    'stackSize'.  'pri' specifies the required priority of the new
    process.  The result will be the process msgport address of the new
    process, or zero if the routine failed.  The argument 'name'
    specifies the new process name.  A zero return code indicates
    error.

    The seglist passed to CreateProc() is not freed when it exits; it
    is up to the parent process to free it, or for the code to unload
    itself.

    Under V36 and later, you probably should use CreateNewProc() instead.

INPUTS
    name      - pointer to a null-terminated string
    pri       - signed long (range -128 to +127)
    seglist   - BCPL pointer to a seglist
    stackSize - integer (must be a multiple of 4 bytes)

RESULTS
    process   - pointer to new process msgport

SEE ALSO
    CreateNewProc(), LoadSeg(), UnLoadSeg()


dos.library/CurrentDir

NAME
    CurrentDir -- Make a directory lock the current directory

SYNOPSIS
    oldLock = CurrentDir( lock )
    D0                    D1

    BPTR CurrentDir(BPTR)

FUNCTION
    CurrentDir() causes a directory associated with a lock to be made
    the current directory.  The old current directory lock is returned.

    A value of zero is a valid result here, this 0 lock represents the
    root of file system that you booted from.

    Any call that has to Open() or Lock() files (etc) requires that
    the current directory be a valid lock or 0.

INPUTS
    lock - BCPL pointer to a lock

RESULTS
    oldLock - BCPL pointer to a lock

SEE ALSO
    Lock(), UnLock(), Open(), DupLock()


dos.library/DateStamp

NAME
    DateStamp -- Obtain the date and time in internal format

SYNOPSIS
    ds = DateStamp( ds );
    D0              D1

    struct DateStamp *DateStamp(struct DateStamp *)

FUNCTION
    DateStamp() takes a structure of three longwords that is set to the
    current time.  The first element in the vector is a count of the
    number of days.  The second element is the number of minutes elapsed
    in the day.  The third is the number of ticks elapsed in the current
    minute.  A tick happens 50 times a second.  DateStamp() ensures that
    the day and minute are consistent.  All three elements are zero if
    the date is unset. DateStamp() currently only returns even
    multiples of 50 ticks.  Therefore the time you get is always an even
    number of ticks.

    Time is measured from Jan 1, 1978.

INPUTS
    ds - pointer a struct DateStamp

RESULTS
    The array is filled as described and returned (for pre-V36
    compabability).

SEE ALSO
    DateToStr(), StrToDate(), SetFileDate(), CompareDates()


dos.library/DateToStr

NAME
    DateToStr -- Converts a DateStamp to a string (V36)

SYNOPSIS
    success = DateToStr( datetime )
    D0                      D1

    BOOL DateToStr(struct DateTime *)

FUNCTION
    StamptoStr converts an AmigaDOS DateStamp to a human
    readable ASCII string as requested by your settings in the
    DateTime structure.

INPUTS
    DateTime - a pointer to an initialized DateTime structure.

    The DateTime structure should be initialized as follows:

    dat_Stamp - a copy of the datestamp you wish to convert to
              ascii.

    dat_Format - a format   byte which specifies the format of the
              dat_StrDate.  This can be any of the following
              (note: If value used is something other than those
              below, the default of FORMAT_DOS is used):

              FORMAT_DOS:     AmigaDOS format (dd-mmm-yy).

              FORMAT_INT:     International format (yy-mmm-dd).

              FORMAT_USA:     American format (mm-dd-yy).

              FORMAT_CDN:     Canadian format (dd-mm-yy).

              FORMAT_DEF:     default format for locale.

    dat_Flags - a   flags byte.  The only flag which affects this
              function is:

              DTF_SUBST:      If set, a string such as Today,
                              Monday, etc., will be used instead
                              of the dat_Format specification if
                              possible.
              DTF_FUTURE:     Ignored by this function.

    dat_StrDay - pointer to a buffer to receive the day of the
              week string.  (Monday, Tuesday, etc.). If null, this
              string will not be generated.

    dat_StrDate -   pointer to a buffer to receive the date
              string, in the format requested by dat_Format,
              subject to possible modifications by DTF_SUBST.  If
              null, this string will not be generated.

    dat_StrTime -   pointer to a buffer to receive the time of day
              string. If NULL, this will not be generated.

RESULT
    success - a zero return indicates that the DateStamp was
              invalid, and could not be converted.  Non-zero
              indicates that the call succeeded.

SEE ALSO
    DateStamp(), StrtoDate(), <dos/datetime.h>


dos.library/Delay

NAME
    Delay -- Delay a process for a specified time

SYNOPSIS
    Delay( ticks )
           D1

    void Delay(ULONG)

FUNCTION
    The argument 'ticks' specifies how many ticks (50 per second) to
    wait before returning control.

INPUTS
    ticks - integer

BUGS
    Due to a bug in the timer.device in V1.2/V1.3, specifying a timeout
    of zero for Delay() can cause the unreliable timer & floppy disk
    operation.  This is fixed in V36 and later.

SEE ALSO


dos.library/DeleteFile

NAME
    DeleteFile -- Delete a file or directory

SYNOPSIS
    success = DeleteFile( name )
    D0                    D1

    BOOL DeleteFile(STRPTR)

FUNCTION
    This attempts to delete the file or directory specified by 'name'.
    An error is returned if the deletion fails. Note that all the files
    within a directory must be deleted before the directory itself can
    be deleted.

INPUTS
    name - pointer to a null-terminated string

RESULTS
    success - boolean

SEE ALSO


dos.library/DeleteVar

NAME
    DeleteVar -- Deletes a local or environment variable (V36)

SYNOPSIS
    success = DeleteVar( name, flags )
    D0                    D1    D2

    BOOL DeleteVar(STRPTR, ULONG )

FUNCTION
    Deletes a local or environment variable.

INPUTS
    name   - pointer to an variable name.  Note variable names follow
             filesystem syntax and semantics.
    flags  - combination of type of var to delete (low 8 bits), and
             flags to control the behavior of this routine.  Currently
             defined flags include:

             GVF_LOCAL_ONLY  - delete a local (to your process) variable.
             GVF_GLOBAL_ONLY - delete a global environment variable.

             The default is to delete a local variable if found, otherwise
             a global environment variable if found (only for LV_VAR).

RESULT
    success - If non-zero, the variable was sucessfully deleted, FALSE
              indicates failure.

BUGS
    LV_VAR is the only type that can be global

SEE ALSO
    GetVar(), SetVar(), FindVar(), DeleteFile(), <dos/var.h>


dos.library/DeviceProc

NAME
    DeviceProc -- Return the process MsgPort of specific I/O handler

SYNOPSIS
    process = DeviceProc( name )
    D0                    D1

    struct MsgPort *DeviceProc (STRPTR)

FUNCTION
    DeviceProc() returns the process identifier of the process which
    handles the device associated with the specified name. If no
    process handler can be found then the result is zero. If the name
    refers to an assign then a directory lock is returned in IoErr().
    This lock should not be UnLock()ed or Examine()ed (if you wish to do
    so, DupLock() it first).

BUGS
    In V36, if you try to DeviceProc() something relative to an assign
    made with AssignPath(), it will fail.  This is because there's no
    way to know when to unlock the lock.  If you're writing code for
    V36 or later, it is highly advised you use GetDeviceProc() instead,
    or make your code conditional on V36 to use GetDeviceProc()/
    FreeDeviceProc().

SEE ALSO
    GetDeviceProc(), FreeDeviceProc(), DupLock(), UnLock(), Examine()


dos.library/DoPkt

NAME
    DoPkt -- Send a dos packet and wait for reply (V36)

SYNOPSIS
    result1 = DoPkt(port,action,arg1,arg2,arg3,arg4,arg5)
    D0               D1    D2    D3   D4   D5   D6   D7

    LONG DoPkt(struct MsgPort *,LONG,LONG,LONG,LONG,LONG,LONG)

FUNCTION
    Sends a packet to a handler and waits for it to return.  Any secondary
    return will be available in D1 AND from IoErr().  DoPkt() will work
    even if the caller is an exec task and not a process; however it will
    be slower, and may fail for some additional reasons, such as being
    unable to allocate a signal.  DoPkt() uses your pr_MsgPort for the
    reply, and will call pr_PktWait.  (See BUGS regarding tasks, though).

    Only allows 5 arguments to be specified.  For more arguments (packets
    support a maximum of 7) create a packet and use SendPkt()/WaitPkt().

INPUTS
    port    - pr_MsgPort of the handler process to send to.
    action  - the action requested of the filesystem/handler
    arg1, arg2, arg3, arg4,arg5 - arguments, depend on the action, may not
               be required.

RESULT
    result1 - the value returned in dp_Res1, or FALSE if there was some
              problem in sending the packet or recieving it.
    result2 - Available from IoErr() AND in register D1.

BUGS
    Using DoPkt() from tasks doesn't work in V36. Use AllocDosObject(),
    PutMsg(), and WaitPort()/GetMsg() for a workaround, or you can call
    CreateNewProc() to start a process to do Dos I/O for you.  In V37,
    DoPkt() will allocate, use, and free the MsgPort required.

NOTES
    Callable from a task (under V37 and above).

SEE ALSO
    AllocDosObject(), FreeDosObject(), SendPkt(), WaitPkt(),
    CreateNewProc(), AbortPkt()


dos.library/DupLock

NAME
    DupLock -- Duplicate a lock

SYNOPSIS
    lock = DupLock( lock )
    D0              D1

    BPTR DupLock(BPTR)

FUNCTION
    DupLock() is passed a shared filing system lock.  This is the ONLY
    way to obtain a duplicate of a lock... simply copying is not
    allowed.

    Another lock to the same object is then returned.  It is not
    possible to create a copy of a exclusive lock.

    A zero return indicates failure.

INPUTS
    lock - BCPL pointer to a lock

RESULTS
    newLock - BCPL pointer to a lock

SEE ALSO
    Lock(), UnLock(), DupLockFromFH(), ParentOfFH()


dos.library/DupLockFromFH

NAME
    DupLockFromFH -- Gets a lock on an open file (V36)

SYNOPSIS
    lock = DupLockFromFH(fh)
    D0                   D1

    BPTR DupLockFromFH(BPTR)

FUNCTION
    Obtain a lock on the object associated with fh.  Only works if the
    file was opened using a non-exclusive mode.  Other restrictions may be
    placed on success by the filesystem.

INPUTS
    fh   - Opened file for which to obtain the lock

RESULT
    lock - Obtained lock or NULL for failure

SEE ALSO
    DupLock(), Lock(), UnLock()


dos.library/EndNotify

NAME
    EndNotify -- Ends a notification request (V36)

SYNOPSIS
    EndNotify(notifystructure)
                    D1

    VOID EndNotify(struct NotifyRequest *)

FUNCTION
    Removes a notification request.  Safe to call even if StartNotify()
    failed.  For NRF_SEND_MESSAGE, it searches your port for any messages
    about the object in question and removes and replies them before
    returning.

INPUTS
    notifystructure - a structure passed to StartNotify()

SEE ALSO
    StartNotify(), <dos/notify.h>


dos.library/ErrorReport

NAME
    ErrorReport -- Displays a Retry/Cancel requester for an error (V36)

SYNOPSIS
    status = ErrorReport(code, type, arg1, device)
    D0                    D1    D2    D3     A0

    BOOL ErrorReport(LONG, LONG, ULONG, struct MsgPort *)

FUNCTION
    Based on the request type, this routine formats the appropriate
    requester to be displayed.  If the code is not understood, it returns
    DOS_TRUE immediately.  Returns DOS_TRUE if the user selects CANCEL or
    if the attempt to put up the requester fails, or if the process
    pr_WindowPtr is -1.  Returns FALSE if the user selects Retry.  The
    routine will retry on DISKINSERTED for appropriate error codes.
    These return values are the opposite of what AutoRequest returns.

    Note: this routine sets IoErr() to code before returning.

INPUTS
    code   - Error code to put a requester up for.
       Current valid error codes are:
            ERROR_DISK_NOT_VALIDATED
            ERROR_DISK_WRITE_PROTECTED
            ERROR_DISK_FULL
            ERROR_DEVICE_NOT_MOUNTED
            ERROR_NOT_A_DOS_DISK
            ERROR_NO_DISK
            ABORT_DISK_ERROR        /* read/write error */
            ABORT_BUSY              /* you MUST replace... */
    type   - Request type:
                   REPORT_LOCK   - arg1 is a lock (BPTR).
                   REPORT_FH     - arg1 is a filehandle (BPTR).
                    REPORT_VOLUME - arg1 is a volumenode (C pointer).
                    REPORT_INSERT - arg1 is the string for the volumename
                                    (will be split on a ':').
                                    With ERROR_DEVICE_NOT_MOUNTED puts
                                    up the "Please insert..." requester.
    arg1   - variable parameter (see type)
    device - (Optional) Address of handler task for which report is to be
            made.  Only required for REPORT_LOCK, and only if arg1==NULL.

RESULT
    status - Cancel/Retry indicator (0 means Retry)

SEE ALSO
    Fault(), IoErr()


dos.library/ExAll

NAME
    ExAll -- Examine an entire directory (V36)

SYNOPSIS
    continue = ExAll(lock, buffer, size, type, control)
    D0               D1     D2     D3    D4     D5

    BOOL ExAll(BPTR,STRPTR,LONG,LONG,struct ExAllControl *)

FUNCTION
    Examines an entire directory.

Lock must be on a directory.  Size is the size of the buffer supplied.
The buffer will be filled with (partial) ExAllData structures, as
specified by the type field.

Type is a value from those shown below that determines which information is
to be stored in the buffer.  Each higher value adds a new thing to the list
as described in the table below:-

    ED_NAME         FileName
    ED_TYPE         Type
    ED_SIZE         Size in bytes
    ED_PROTECTION   Protection bits
    ED_DATE         3 longwords of date
    ED_COMMENT      Comment (will be NULL if no comment)

Thus, ED_NAME gives only filenames, and ED_COMMENT gives everything.

The ead_Next entry gives a pointer to the next entry in the buffer.  The
last entry will have NULL in ead_Next.

The control structure is required so that FFS can keep track if more than
one call to ExAll is required.  This happens when there are more names in
a directory than will fit into the buffer.  The format of the control
structure is as follows:-

NOTE: the control structure MUST be allocated by AllocDosObject!!!

Entries:  This field tells the calling application how many entries are
        in the buffer after calling ExAll.  Note: make sure your code
        handles the 0 entries case, including 0 entries with continue
        non-zero.

LastKey:  This field ABSOLUTELY MUST be initialised to 0 before calling
        ExAll for the first time.  Any other value will cause nasty
        things to happen.  If ExAll returns non-zero, then this field
        should not be touched before making the second and subsequent
        calls to ExAll.  Whenever ExAll returns non-zero, there are more
        calls required before all names have been received.

        As soon as a FALSE return is received then ExAll has completed
        (if IoErr() returns ERROR_NO_MORE_ENTRIES - otherwise it returns
        the error that occured, similar to ExNext.)

MatchString
        If this field is NULL then all filenames will be returned.  If
        this field is non-null then it is interpreted as a pointer to
        a string that is used to pattern match all file names before
        accepting them and putting them into the buffer.  The default
        AmigaDOS caseless pattern match routine is used.  This string
        MUST have been parsed by ParsePatternNoCase()!

MatchFunc:
        Contains a pointer to a hook for a routine to decide if the entry
        will be included in the returned list of entries.  The entry is
        filled out first, and then passed to the hook.  If no MatchFunc is
        to be called then this entry should be NULL.  The hook is
        called with the following parameters (as is standard for hooks):

        BOOL = MatchFunc( hookptr, data, typeptr )
                            a0      a1      a2
        (a0 = ptr to hook, a1 = ptr to filled in ExAllData, a2 = ptr
         to longword of type).

        MatchFunc should return FALSE if the entry is not to be
        accepted, otherwise return TRUE.

    Note that Dos will emulate ExAll() using Examine() and ExNext()
    if the handler in question doesn't support the ExAll() packet.

INPUTS
    lock    - Lock on directory to be examined.
    buffer  - Buffer for data returned (MUST be at least word-aligned,
              preferably long-word aligned).
    size    - Size in bytes of 'buffer'.
    type    - Type of data to be returned.
    control - Control data structure (see notes above).  MUST have been
              allocated by AllocDosObject!

RESULT
    continue - Whether or not ExAll is done.  If FALSE is returned, either
               ExAll has completed (IoErr() == ERROR_NO_MORE_ENTRIES), or
               an error occurred (check IoErr()).  If non-zero is returned,
               you MUST call ExAll again until it returns FALSE.

EXAMPLE

eac = AllocDosObject(DOS_EXALLCONTROL,NULL);
if (!eac) ...
...
eac->eac_LastKey = 0;
do {
   more = ExAll(lock, EAData, sizeof(EAData), ED_FOO, eac);
   if ((!more) && (IoErr() != ERROR_NO_MORE_ENTRIES)) {
       /* ExAll failed abnormally */
       break;
   }
   if (eac->eac_Entries == 0) {
       /* ExAll failed normally with no entries */
       continue;                   /* ("more" is *usually* zero) */
   }
   ead = (struct ExAllData *) EAData;
   do {
       /* use ead here */
       ...
       /* get next ead */
       ead = ead->ed_Next;
   } while (ead);

} while (more);
...
FreeDosObject(DOS_EXALLCONTROL,eac);

BUGS
    In V36, there were problems with ExAll (particularily with
    eac_MatchString, and ed_Next with the ramdisk and the emulation
    of it in Dos for handlers that do not support the packet.  It is
    advised you only use this under V37 and later.

SEE ALSO
    Examine(), ExNext(), ExamineFH(), MatchPatternNoCase(),
    ParsePatternNoCase(), AllocDosObject()


dos.library/Examine

NAME
    Examine -- Examine a directory or file associated with a lock

SYNOPSIS
    success = Examine( lock, FileInfoBlock )
    D0                  D1        D2

    BOOL Examine(BPTR,struct FileInfoBlock *)

FUNCTION
    Examine() fills in information in the FileInfoBlock concerning the
    file or directory associated with the lock. This information
    includes the name, size, creation date and whether it is a file or
    directory.  FileInfoBlock must be longword aligned.  Examine() gives
    a return code of zero if it fails.

    You may make a local copy of the FileInfoBlock, as long as it is
    never passed to ExNext().

INPUTS
    lock      - BCPL pointer to a lock
    infoBlock - pointer to a FileInfoBlock (MUST be longword aligned)

RESULTS
    success - boolean

SPECIAL NOTE
    FileInfoBlock must be longword-aligned.  AllocDosObject() will
    allocate them correctly for you.

SEE ALSO
    Lock(), UnLock(), ExNext(), ExamineFH(), <dos/dos.h>, AllocDosObject(),
    ExAll()


dos.library/ExamineFH

NAME
    ExamineFH -- Gets information on an open file (V36)

SYNOPSIS
    success = ExamineFH(fh, fib)
    D0                  D1  D2

    BOOL ExamineFH(BPTR, struct FileInfoBlock *)

FUNCTION
    Examines a filehandle and returns information about the file in the
    FileInfoBlock.  There are no guarantees as to whether the fib_Size
    field will reflect any changes made to the file size it was opened,
    though filesystems should attempt to provide up-to-date information
    for it.

INPUTS
    fh  - Filehandle you wish to examine
    fib - FileInfoBlock, must be longword aligned.

RESULT
    success - Success/failure indication

SEE ALSO
    Examine(), ExNext(), ExAll(), Open(), AllocDosObject()


dos.library/Execute

NAME
    Execute -- Execute a CLI command

SYNOPSIS
    success = Execute( commandString, input, output )
    D0                 D1             D2     D3

    BOOL Execute(STRPTR, BPTR, BPTR)

FUNCTION
    This function attempts to execute the string commandString as a
    Shell command and arguments. The string can contain any valid input
    that you could type directly in a Shell, including input and output
    redirection using < and >.  Note that Execute() doesn't return until
    the command(s) in commandstring have returned.

    The input file handle will normally be zero, and in this case
    Execute() will perform whatever was requested in the commandString
    and then return. If the input file handle is nonzero then after the
    (possibly empty) commandString is performed subsequent input is read
    from the specified input file handle until end of that file is
    reached.

    In most cases the output file handle must be provided, and is used
    by the Shell commands as their output stream unless output
    redirection was specified. If the output file handle is set to zero
    then the current window, normally specified as *, is used. Note
    that programs running under the Workbench do not normally have a
    current window.

    Execute() may also be used to create a new interactive Shell process
    just like those created with the NewShell command. In order to do
    this you would call Execute() with an empty commandString, and pass
    a file handle relating to a new window as the input file handle.
    The output file handle would be set to zero. The Shell will read
    commands from the new window, and will use the same window for
    output. This new Shell window can only be terminated by using the
    EndCLI command.

    Under V37, if an input filehandle is passed, and it's either
    interactive or a NIL: filehandle, the pr_ConsoleTask of the new
    process will be set to that filehandle's process (the same applies
    to SystemTagList()).

    For this command to work the program Run must be present in C: in
    versions before V36 (except that in 1.3.2 and any later 1.3 versions,
    the system first checks the resident list for Run).

INPUTS
    commandString - pointer to a null-terminated string
    input         - BCPL pointer to a file handle
    output        - BCPL pointer to a file handle

RESULTS
    success - BOOLEAN indicating whether Execute was successful
              in finding and starting the specified program.  Note this
              is NOT the return code of the command(s).
SEE ALSO
    SystemTagList(), NewShell, EndCLI, Run


dos.library/Exit

NAME
    Exit -- Exit from a program

SYNOPSIS
    Exit( returnCode )
          D1

    void Exit(LONG)

FUNCTION
    Exit() is currently for use with programs written as if they
    were BCPL programs.  This function is not normally useful for
    other purposes.

    In general, therefore, please DO NOT CALL THIS FUNCTION!

    In order to exit, C programs should use the C language exit()
    function (note the lower case letter "e").  Assembly programs should
    place a return code in D0, and execute an RTS instruction with
    their original stack ptr.

IMPLEMENTATION
    The action of Exit() depends on whether the program which called it
    is running as a command under a CLI or not. If the program is
    running under the CLI the command finishes and control reverts to
    the CLI. In this case, returnCode is interpreted as the return code
    from the program.

    If the program is running as a distinct process, Exit() deletes the
    process and release the space associated with the stack, segment
    list and process structure.

INPUTS
    returnCode - integer

SEE ALSO
    CreateProc(), CreateNewProc()


dos.library/ExNext

NAME
    ExNext -- Examine the next entry in a directory

SYNOPSIS
    success = ExNext( lock, FileInfoBlock )
    D0                 D1        D2

    BOOL ExNext(BPTR, struct FileInfoBlock *)

FUNCTION
    This routine is passed a directory lock and a FileInfoBlock that
    have been initialized by a previous call to Examine(), or updated
    by a previous call to ExNext().  ExNext() gives a return code of zero
    on failure.  The most common cause of failure is reaching the end
    of the list of files in the owning directory.  In this case, IoErr
    will return ERROR_NO_MORE_ENTRIES and a good exit is appropriate.

    So, follow these steps to examine a directory:
    1) Pass a Lock and a FileInfoBlock to Examine().  The lock must
       be on the directory you wish to examine.
    2) Pass ExNext() the same lock and FileInfoBlock.
    3) Do something with the information returned in the FileInfoBlock.
       Note that the fib_DirEntryType field is positive for directories,
       negative for files.
    4) Keep calling ExNext() until it returns FALSE.  Check IoErr()
       to ensure that the reason for failure was ERROR_NO_MORE_ENTRIES.

    Note: if you wish to recursively scan the file tree and you find
    another directory while ExNext()ing you must Lock that directory and
    Examine() it using a new FileInfoBlock.  Use of the same
    FileInfoBlock to enter a directory would lose important state
    information such that it will be impossible to continue scanning
    the parent directory.  While it is permissible to UnLock() and Lock()
    the parent directory between ExNext() calls, this is NOT recommended.
    Important state information is associated with the parent lock, so
    if it is freed between ExNext() calls this information has to be
    rebuilt on each new ExNext() call, and will significantly slow down
    directory scanning.

    It is NOT legal to Examine() a file, and then to ExNext() from that
    FileInfoBlock.       You may make a local copy of the FileInfoBlock, as
    long as it is never passed back to the operating system.

INPUTS
    lock - BCPL pointer to a lock originally used for the Examine() call
    infoBlock - pointer to a FileInfoBlock used on the previous Examine()
                or ExNext() call.

RESULTS
    success - boolean

SPECIAL NOTE
    FileInfoBlock must be longword-aligned.  AllocDosObject() will
    allocate them correctly for you.

SEE ALSO
    Examine(), Lock(), UnLock(), IoErr(), ExamineFH(), AllocDosObject(),
    ExAll()


dos.library/Fault

NAME
    Fault -- Returns the text associated with a DOS error code (V36)

SYNOPSIS
    success = Fault(code, header, buffer, len)
    D0               D1     D2      D3    D4

    BOOL Fault(LONG, STRPTR, STRPTR, LONG)

FUNCTION
    This routine obtains the error message text for the given error code.
    The header is prepended to the text of the error message, followed
    by a colon.  Puts a null-terminated string for the error message into
    the buffer.  By convention, error messages should be no longer than 80
    characters (+1 for termination), and preferably no more than 60.
    The value returned by IoErr() is set to the code passed in.  If there
    is no message for the error code, the message will be "Error code
    <number>n".

INPUTS
    code   - Error code
    header - header to output before error text
    buffer - Buffer to receive error message.
    len    - Length of the buffer.

RESULT
    success - Success/failure code.

SEE ALSO
    IoErr(), SetIoErr(), PrintFault()


dos.library/FGetC

NAME
    FGetC -- Read a character from the specified input (buffered) (V36)

SYNOPSIS
    char = FGetC(fh)
    D0           D1

    LONG FGetC(BPTR)

FUNCTION
    Reads the next character from the input stream.  A -1 is
    returned when EOF or an error is encountered.  This call is buffered.
    Use Flush() between buffered and unbuffered I/O on a filehandle.

INPUTS
    fh - filehandle to use for buffered I/O

RESULT
    char - character read (0-255) or -1

BUGS
    In V36, after an EOF was read, EOF would always be returned from
    FGetC() from then on.  Starting in V37, it tries to read from the
    handler again each time (unless UnGetC(fh,-1) was called).

SEE ALSO
    FPutC(), UnGetC(), Flush()


dos.library/FGets

NAME
    FGets -- Reads a line from the specified input (buffered) (V36)

SYNOPSIS
    buffer = FGets(fh, buf, len)
    D0             D1  D2   D3

    STRPTR FGets(BPTR, STRPTR, ULONG)

FUNCTION
    This routine reads in a single line from the specified input stopping
    at a NEWLINE character or EOF.  In either event, UP TO the number of
    len specified bytes minus 1 will be copied into the buffer.  Hence if
    a length of 50 is passed and the input line is longer than 49 bytes,
    it will return 49 characters.  It returns the buffer pointer normally,
    or NULL if EOF is the first thing read.

    If terminated by a newline, the newline WILL be the last character in
    the buffer.  This is a buffered read routine.  The string read in IS
    null-terminated.

INPUTS
    fh  - filehandle to use for buffered I/O
    buf - Area to read bytes into.
    len - Number of bytes to read, must be > 0.

RESULT
    buffer - Pointer to buffer passed in, or NULL for immediate EOF or for
             an error.  If NULL is returnd for an EOF, IoErr() will return
             0.

SEE ALSO
    FRead(), FPuts(), FGetC()


dos.library/FilePart

NAME
    FilePart -- Returns the last component of a path (V36)

SYNOPSIS
    fileptr = FilePart( path )
    D0                   D1

    STRPTR FilePart( STRPTR )

FUNCTION
    This function returns a pointer to the last component of a string path
    specification, which will normally be the file name.  If there is only
    one component, it returns a pointer to the beginning of the string.

INPUTS
    path - pointer to an path string.  May be relative to the current
           directory or the current disk.

RESULT
    fileptr - pointer to the last component of the path.

EXAMPLE
    FilePart("xxx:yyy/zzz/qqq") would return a pointer to the first 'q'.
    FilePart("xxx:yyy") would return a pointer to the first 'y').

SEE ALSO
    PathPart(), AddPart()


dos.library/FindArg

NAME
    FindArg - find a keyword in a template (V36)

SYNOPSIS
    index = FindArg(template, keyword)
    D0                D1        D2

    LONG FindArg(STRPTR, STRPTR)

FUNCTION
    Returns the argument number of the keyword, or -1 if it is not a
    keyword for the template.  Abbreviations are handled.

INPUTS
    keyword  - keyword to search for in template
    template - template string to search

RESULT
    index - number of entry in template, or -1 if not found

BUGS
    In earlier published versions of the autodoc, keyword and template
    were backwards.

SEE ALSO
    ReadArgs(), ReadItem(), FreeArgs()


dos.library/FindCliProc

NAME
    FindCliProc -- returns a pointer to the requested CLI process (V36)

SYNOPSIS
    proc = FindCliProc(num)
    D0             D1

    struct Process *FindCliProc(LONG)

FUNCTION
    This routine returns a pointer to the CLI process associated with the
    given CLI number.  If the process isn't an active CLI process, NULL is
    returned.  NOTE: should normally be called inside a Forbid(), if you
    must use this function at all.

INPUTS
    num  - Task number of CLI process

RESULT
    proc - Pointer to given CLI process

SEE ALSO
    Cli(), Forbid(), MaxCli()


dos.library/FindDosEntry

NAME
    FindDosEntry -- Finds a specific Dos List entry (V36)

SYNOPSIS
    newdlist = FindDosEntry(dlist,name,flags)
    D0                       D1    D2   D3

    struct DosList *FindDosEntry(struct DosList *,STRPTR,ULONG)

FUNCTION
    Locates an entry on the device list.  Starts with the entry dlist.
    NOTE: must be called with the device list locked, no references may be
    made to dlist after unlocking.

INPUTS
    dlist    - The device entry to start with.
    name     - Name of device entry (without ':') to locate.
    flags    - Search control flags.  Use the flags you passed to
               LockDosList, or a subset of them.  LDF_READ/LDF_WRITE are
               not required for this call.

RESULT
    newdlist - The device entry or NULL

SEE ALSO
    AddDosEntry(), RemDosEntry(), NextDosEntry(), LockDosList(),
    MakeDosEntry(), FreeDosEntry()


dos.library/FindSegment

NAME
    FindSegment - Finds a segment on the resident list (V36)

SYNOPSIS
    segment = FindSegment(name, start, system)
    D0                     D1     D2     D3

    struct Segment *FindSegment(STRPTR, struct Segment *, LONG)

FUNCTION
    Finds a segment on the Dos resident list by name and type, starting
    at the segment AFTER 'start', or at the beginning if start is NULL.
    If system is zero, it will only return nodes with a seg_UC of 0
    or more.  It does NOT increment the seg_UC, and it does NOT do any
    locking of the list.  You must Forbid() lock the list to use this
    call.

    To use an entry you have found, you must: if the seg_UC is 0 or more,
    increment it, and decrement it (under Forbid()!) when you're done
    the the seglist.

    The other values for seg_UC are:
            -1   - system module, such as a filesystem or shell
            -2   - resident shell command
            -999 - disabled internal command, ignore
    Negative values should never be modified.  All other negative
    values between 0 and -32767 are reserved to AmigaDos and should not
    be used.

INPUTS
    name   - name of segment to find
    start  - segment to start the search after
    system - true for system segment, false for normal segments

RESULT
    segment - the segment found or NULL

SEE ALSO
    AddSegment(), RemSegment(), Forbid()


dos.library/FindVar

NAME
    FindVar -- Finds a local variable (V36)

SYNOPSIS
    var = FindVar( name, type )
    D0              D1    D2

    struct LocalVar * FindVar(STRPTR, ULONG )

FUNCTION
    Finds a local variable structure.

INPUTS
    name - pointer to an variable name.  Note variable names follow
           filesystem syntax and semantics.

    type - type of variable to be found (see <dos/var.h>)

RESULT

    var  - pointer to a LocalVar structure or NULL

SEE ALSO
    GetVar(), SetVar(), DeleteVar(), <dos/var.h>


dos.library/Flush

NAME
    Flush -- Flushes buffers for a buffered filehandle (V36)

SYNOPSIS
    success = Flush(fh)
    D0              D1

    LONG Flush(BPTR)

FUNCTION
    Flushes any pending buffered writes to the filehandle.  All buffered
    writes will also be flushed on Close().  If the filehandle was being
    used for input, it drops the buffer, and tries to Seek() back to the
    last read position  (so subsequent reads or writes will occur at the
    expected position in the file).

INPUTS
    fh      - Filehandle to flush.

RESULT
    success - Success or failure.

BUGS
    Before V37 release, Flush() returned a random value.  As of V37,
    it always returns success (this will be fixed in some future
    release).

SEE ALSO
    FputC(), FGetC(), UnGetC(), Seek(), Close()


dos.library/Format

NAME
    Format -- Causes a filesystem to initialize itself (V36)

SYNOPSIS
    success = Format(filesystem, volumename, dostype)
    D0                   D1          D2         D3

    BOOL Format(STRPTR, STRPTR, ULONG)

FUNCTION
    Interface for initializing new media on a device.  This causes the
    filesystem to write out an empty disk structure to the media, which
    should then be ready for use.  This assumes the media has been low-
    level formatted and verified already.

    The filesystem should be inhibited before calling Format() to make
    sure you don't get an ERROR_OBJECT_IN_USE.

INPUTS
    filesystem - Name of device to be formatted.  ':' must be supplied.
    volumename - Name for volume (if supported).  No ':'.
    dostype    - Type of format, if filesystem supports multiple types.

RESULT
    success - Success/failure indicator.

BUGS
    Existed, but was non-functional in V36 dos.  (The volumename wasn't
    converted to a BSTR.)  Workaround: require V37, or under V36
    convert volumename to a BPTR to a BSTR before calling Format().
    Note: a number of printed packet docs for ACTION_FORMAT are wrong
    as to the arguments.

SEE ALSO


dos.library/FPutC

NAME
    FPutC -- Write a character to the specified output (buffered) (V36)

SYNOPSIS
    char = FPutC(fh, char)
    D0           D1   D2

    LONG FPutC(BPTR, UBYTE)

FUNCTION
    Writes a single character to the output stream.  This call is
    buffered.  Use Flush() between buffered and unbuffered I/O on a
    filehandle.  Interactive filehandles are flushed automatically
    on a newline, return, '0', or line feed.

INPUTS
    fh   - filehandle to use for buffered I/O
    char - character to write

RESULT
    char - either the character written, or EOF for an error.

SEE ALSO
    FGetC(), UnGetC(), Flush()


dos.library/FPuts

NAME
    FPuts -- Writes a string the the specified output (buffered) (V36)

SYNOPSIS
    error = FPuts(fh, str)
    D0            D1  D2

    LONG FPuts(BPTR, STRPTR)

FUNCTION
    This routine writes an unformatted string to the filehandle.  No
    newline is appended to the string and the length actually written is
    returned.  This routine is buffered.

INPUTS
    fh    - filehandle to use for buffered I/O
    str   - Null-terminated string to be written to default output

RESULT
    error - 0 normally, otherwise -1.  Note that this is opposite of
            most other Dos functions, which return success.

SEE ALSO
    FGets(), FPutC(), FWrite(), PutStr()


dos.library/FRead

NAME
    FRead -- Reads a number of blocks from an input (buffered) (V36)

SYNOPSIS
    count = FRead(fh, buf, blocklen, blocks)
    D0            D1  D2     D3        D4

    LONG FRead(BPTR, STRPTR, ULONG, ULONG)

FUNCTION
    Attempts to read a number of blocks, each blocklen long, into the
    specified buffer from the input stream.  May return less than
    the number of blocks requested, either due to EOF or read errors.
    This call is buffered.

INPUTS
    fh       - filehandle to use for buffered I/O
    buf      - Area to read bytes into.
    blocklen - number of bytes per block.  Must be > 0.
    blocks   - number of blocks to read.  Must be > 0.

RESULT
    count - Number of _blocks_ read, or 0 for EOF.  On an error, the
            number of blocks actually read is returned.

BUGS
    Doesn't clear IoErr() before starting.  If you want to find out
    about errors, use SetIoErr(0L) before calling.

SEE ALSO
    FGetC(), FWrite(), FGets()


dos.library/FreeArgs

NAME
    FreeArgs - Free allocated memory after ReadArgs() (V36)

SYNOPSIS
    FreeArgs(rdargs)
               D1

    void FreeArgs(struct RDArgs *)

FUNCTION
    Frees memory allocated to return arguments in from ReadArgs().  If
    ReadArgs allocated the RDArgs structure it will be freed.

INPUTS
    rdargs - structure returned from ReadArgs()

SEE ALSO
    ReadArgs(), ReadItem(), FindArg()


dos.library/FreeDeviceProc

NAME
    FreeDeviceProc -- Releases port returned by GetDeviceProc() (V36)

SYNOPSIS
    FreeDeviceProc(devproc)
                     D1

    void FreeDeviceProc(struct DevProc *)

FUNCTION
    Frees up the structure created by GetDeviceProc(), and any associated
    temporary locks.

    Decrements the counter incremented by GetDeviceProc().  The counter
    is in an extension to the 1.3 process structure.  After calling
    FreeDeviceProc(), do not use the port or lock again!  It is safe to
    call FreeDeviceProc(NULL).

INPUTS
    devproc - A value returned by GetDeviceProc()

BUGS
    Counter not currently active in 2.0.

SEE ALSO
    GetDeviceProc(), DeviceProc(), AssignLock(), AssignLate(),
    AssignPath()


dos.library/FreeDosEntry

NAME
    FreeDosEntry -- Frees an entry created by MakeDosEntry (V36)

SYNOPSIS
    FreeDosEntry(dlist)
                   D1

    void FreeDosEntry(struct DosList *)

FUNCTION
    Frees an entry created by MakeDosEntry().  This routine should be
    eliminated and replaced by a value passed to FreeDosObject()!

INPUTS
    dlist - DosList to free.

SEE ALSO
    AddDosEntry(), RemDosEntry(), FindDosEntry(), LockDosList(),
    NextDosEntry(), MakeDosEntry()


dos.library/FreeDosObject

NAME
    FreeDosObject -- Frees an object allocated by AllocDosObject() (V36)

SYNOPSIS
    FreeDosObject(type, ptr)
                   D1   D2

    void FreeDosObject(ULONG, void *)

FUNCTION
    Frees an object allocated by AllocDosObject().  Do NOT call for
    objects allocated in any other way.

INPUTS
    type - type passed to AllocDosObject()
    ptr  - ptr returned by AllocDosObject()

SEE ALSO
    AllocDosObject(), <dos/dos.h>


dos.library/FWrite

NAME
    FWrite -- Writes a number of blocks to an output (buffered) (V36)

SYNOPSIS
    count = FWrite(fh, buf, blocklen, blocks)
    D0             D1  D2     D3        D4

    LONG FWrite(BPTR, STRPTR, ULONG, ULONG)

FUNCTION
    Attempts to write a number of blocks, each blocklen long, from the
    specified buffer to the output stream.  May return less than the
    number of blocks requested, if there is some error such as a full
    disk or r/w error.  This call is buffered.

INPUTS
    fh       - filehandle to use for buffered I/O
    buf      - Area to write bytes from.
    blocklen - number of bytes per block.  Must be > 0.
    blocks   - number of blocks to read.  Must be > 0.

RESULT
    count - Number of _blocks_ written.  On an error, the number of
            blocks actually written is returned.

BUGS
    Doesn't clear IoErr() before starting.  If you want to find out
    about errors, use SetIoErr(0L) before calling.

SEE ALSO
    FPutC(), FRead(), FPuts()


dos.library/GetArgStr

NAME
    GetArgStr -- Returns the arguments for the process (V36)

SYNOPSIS
    ptr = GetArgStr()
    D0

    STRPTR GetArgStr(void)

FUNCTION
    Returns a pointer to the (null-terminated) arguments for the program
    (process).  This is the same string passed in a0 on startup from CLI.

RESULT
    ptr - pointer to arguments

SEE ALSO
    SetArgStr(), RunCommand()


dos.library/GetConsoleTask

NAME
    GetConsoleTask -- Returns the default console for the process (V36)

SYNOPSIS
    port = GetConsoleTask()
    D0

    struct MsgPort *GetConsoleTask(void)

FUNCTION
    Returns the default console task's port (pr_ConsoleTask) for the
    current process.

RESULT
    port - The pr_MsgPort of the console handler, or NULL.

SEE ALSO
    SetConsoleTask(), Open()


dos.library/GetCurrentDirName

NAME
    GetCurrentDirName -- returns the current directory name (V36)

SYNOPSIS
    success = GetCurrentDirName(buf, len)
    D0                          D1   D2

    BOOL GetCurrentDirName(STRPTR, LONG)

FUNCTION
    Extracts the current directory name from the CLI structure and puts it
    into the buffer.  If the buffer is too small, the name is truncated
    appropriately and a failure code returned.  If no CLI structure is
    present, a null string is returned in the buffer, and failure from
    the call (with IoErr() == ERROR_OBJECT_WRONG_TYPE);

INPUTS
    buf     - Buffer to hold extracted name
    len     - Number of bytes of space in buffer

RESULT
    success - Success/failure indicator

BUGS
    In V36, this routine didn't handle 0-length buffers correctly.

SEE ALSO
    SetCurrentDirName()


dos.library/GetDeviceProc

NAME
    GetDeviceProc -- Finds a handler to send a message to (V36)

SYNOPSIS
    devproc = GetDeviceProc(name, devproc)
      D0                     D1     D2

    struct DevProc *GetDeviceProc(STRPTR, struct DevProc *)

FUNCTION
    Finds the handler/filesystem to send packets regarding 'name' to.
    This may involve getting temporary locks.  It returns a structure
    that includes a lock and msgport to send to to attempt your operation.
    It also includes information on how to handle multiple-directory
    assigns (by passing the DevProc back to GetDeviceProc() until it
    returns NULL).

    The initial call to GetDeviceProc() should pass NULL for devproc.  If
    after using the returned DevProc, you get an ERROR_OBJECT_NOT_FOUND,
    and (devproc->dvp_Flags & DVPF_ASSIGN) is true, you should call
    GetDeviceProc() again, passing it the devproc structure.  It will
    either return a modified devproc structure, or NULL (with
    ERROR_NO_MORE_ENTRIES in IoErr()).  Continue until it returns NULL.

    This call also increments the counter that locks a handler/fs into
    memory.  After calling FreeDeviceProc(), do not use the port or lock
    again!

INPUTS
    name    - name of the object you wish to access.  This can be a
              relative path ("foo/bar"), relative to the current volume
              (":foo/bar"), or relative to a device/volume/assign
              ("foo:bar").
    devproc - A value returned by GetDeviceProc() before, or NULL

RESULT
    devproc - a pointer to a DevProc structure or NULL

BUGS
    Counter not currently active in 2.0.
    In 2.0 and 2.01, you HAD to check DVPF_ASSIGN before calling it again.
    This was fixed for the 2.02 release of V36.

SEE ALSO
    FreeDeviceProc(), DeviceProc(), AssignLock(), AssignLate(),
    AssignPath()


dos.library/GetFileSysTask

NAME
    GetFileSysTask -- Returns the default filesystem for the process (V36)

SYNOPSIS
    port = GetFileSysTask()
    D0

    struct MsgPort *GetFileSysTask(void)

FUNCTION
    Returns the default filesystem task's port (pr_FileSystemTask) for the
    current process.

RESULT
    port - The pr_MsgPort of the filesystem, or NULL.

SEE ALSO
    SetFileSysTask(), Open()


dos.library/GetProgramDir

NAME
    GetProgramDir -- Returns a lock on the directory the program was loaded
                     from (V36)

SYNOPSIS
    lock = GetProgramDir()
    D0

    BPTR GetProgramDir(void)

FUNCTION
    Returns a shared lock on the directory the program was loaded from.
    This can be used for a program to find data files, etc, that are stored
    with the program, or to find the program file itself.  NULL returns are
    valid, and may occur, for example, when running a program from the
    resident list.  You should NOT unlock the lock.

RESULT
    lock - A lock on the directory the current program was loaded from,
           or NULL if loaded from resident list, etc.

BUGS
    Should return a lock for things loaded via resident.  Perhaps should
    return currentdir if NULL.

SEE ALSO
    SetProgramDir(), Open()


dos.library/GetProgramName

NAME
    GetProgramName -- Returns the current program name (V36)

SYNOPSIS
    success = GetProgramName(buf, len)
    D0                       D1   D2

    BOOL GetProgramName(STRPTR, LONG)

FUNCTION
    Extracts the program name from the CLI structure and puts it
    into the buffer.  If the buffer is too small, the name is truncated
    present, a null string is returned in the buffer, and failure from
    the call (with IoErr() == ERROR_OBJECT_WRONG_TYPE);

INPUTS
    buf     - Buffer to hold extracted name
    len     - Number of bytes of space in buffer

RESULT
    success - Success/failure indicator

SEE ALSO
    SetProgramName()


dos.library/GetPrompt

NAME
    GetPrompt -- Returns the prompt for the current process (V36)

SYNOPSIS
    success = GetPrompt(buf, len)
    D0                  D1   D2

    BOOL GetPrompt(STRPTR, LONG)

FUNCTION
    Extracts the prompt string from the CLI structure and puts it
    into the buffer.  If the buffer is too small, the string is truncated
    appropriately and a failure code returned.  If no CLI structure is
    present, a null string is returned in the buffer, and failure from
    the call (with IoErr() == ERROR_OBJECT_WRONG_TYPE);

INPUTS
    buf     - Buffer to hold extracted prompt
    len     - Number of bytes of space in buffer

RESULT
    success - Success/failure indicator

SEE ALSO
    SetPrompt()


dos.library/GetVar

NAME
    GetVar -- Returns the value of a local or global variable (V36)

SYNOPSIS
    len = GetVar( name, buffer, size, flags )
    D0             D1     D2     D3    D4

    LONG GetVar( STRPTR, STRPTR, LONG, ULONG )

FUNCTION
    Gets the value of a local or environment variable.  It is advised to
    only use ASCII strings inside variables, but not required.  This stops
    putting characters into the destination when a n is hit, unless
    GVF_BINARY_VAR is specified.  (The n is not stored in the buffer.)

INPUTS
    name   - pointer to a variable name.
    buffer - a user allocated area which will be used to store
             the value associated with the variable.
    size   - length of the buffer region in bytes.
    flags  - combination of type of var to get value of (low 8 bits), and
             flags to control the behavior of this routine.  Currently
             defined flags include:

                    GVF_GLOBAL_ONLY - tries to get a global env variable.
                    GVF_LOCAL_ONLY  - tries to get a local variable.
                    GVF_BINARY_VAR  - don't stop at n

             The default is to try to get a local variable first, then
             to try to get a global environment variable.

RESULT
    len -   Size of environment variable.  -1 indicates that the
            variable was not defined (if IoErr() returns
            ERROR_OBJECT_NOT_FOUND - it returns ERROR_BAD_NUMBER if
            you specify a size of 0).  If the value would overflow
            the user buffer, the buffer is truncated.  The buffer
            returned is null-terminated (even if GVF_BINARY_VAR is
            used).  The number of characters put in the buffer (not
            including '0') is returned, and IoErr() will return the
            the size of the variable.

BUGS
    LV_VAR is the only type that can be global.
    Under V36, we documented (and it returned) the size of the variable,
    not the number of characters transferred.  For V37 this was changed
    to the number of characters put in the buffer, and the total size
    of the variable is put in IoErr().

SEE ALSO
    SetVar(), DeleteVar(), FindVar(), <dos/var.h>


dos.library/Info

NAME
    Info -- Returns information about the disk

SYNOPSIS
    success = Info( lock, parameterBlock )
    D0              D1    D2

    BOOL Info(BPTR, struct InfoData *)

FUNCTION
    Info() can be used to find information about any disk in use.
    'lock' refers to the disk, or any file on the disk. The parameter
    block is returned with information about the size of the disk,
    number of free blocks and any soft errors.

INPUTS
    lock           - BCPL pointer to a lock
    parameterBlock - pointer to an InfoData structure
                     (longword aligned)

RESULTS
    success - boolean

SPECIAL NOTE:
    Note that InfoData structure must be longword aligned.


dos.library/Inhibit

NAME
    Inhibit -- Inhibits access to a filesystem (V36)

SYNOPSIS
    success = Inhibit(filesystem, flag)
    D0                    D1       D2

    BOOL Inhibit(STRPTR,LONG)

FUNCTION
    Sends an ACTION_INHIBIT packet to the indicated handler.  This stops
    all activity by the handler until uninhibited.  When uninhibited,
    anything may have happened to the disk in the drive, or there may no
    longer be one.

INPUTS
    filesystem - Name of device to inhibit (with ':')
    flag       - New status.  DOSTRUE = inhibited, FALSE = uninhibited

RESULT
    success    - Success/failure indicator

SEE ALSO


dos.library/Input

NAME
    Input -- Identify the program's initial input file handle

SYNOPSIS
    file = Input()
    D0

    BPTR Input(void)

FUNCTION
    Input() is used to identify the initial input stream allocated when
    the program was initiated.  Never close the filehandle returned by
    Input!

RESULTS
    file - BCPL pointer to a file handle

SEE ALSO
    Output(), SelectInput()


dos.library/InternalLoadSeg

NAME
    InternalLoadSeg -- Low-level load routine (V36)

SYNOPSIS
    seglist = InternalLoadSeg(fh,table,functionarray,stack)
    D0                        D0  A0        A1        A2

    BPTR InternalLoadSeg(BPTR,BPTR,LONG *,LONG *)

FUNCTION
    Loads from fh.  Table is used when loading an overlay, otherwise
    should be NULL.  Functionarray is a pointer to an array of functions.
    Note that the current Seek position after loading may be at any point
    after the last hunk loaded.  The filehandle will not be closed.  If a
    stacksize is encoded in the file, the size will be stuffed in the
    LONG pointed to by stack.  This LONG should be initialized to your
    default value: InternalLoadSeg() will not change it if no stacksize
    is found. Clears unused portions of Code and Data hunks (as well as
    BSS hunks).  (This also applies to LoadSeg() and NewLoadSeg()).

    If the file being loaded is an overlaid file, this will return
    -(seglist).  All other results will be positive.

    NOTE to overlay users: InternalLoadSeg() does NOT return seglist in
    both D0 and D1, as LoadSeg does.  The current ovs.asm uses LoadSeg(),
    and assumes returns are in D1.  We will support this for LoadSeg()
    ONLY.

INPUTS
    fh            - Filehandle to load from.
    table         - When loading an overlay, otherwise ignored.
    functionarray - Array of function to be used for read, alloc, and free.
       FuncTable[0] ->  Actual = ReadFunc(readhandle,buffer,length),DOSBase
                        D0                D1         A0     D0      A6
       FuncTable[1] ->  Memory = AllocFunc(size,flags), Execbase
                        D0                 D0   D1      a6
       FuncTable[2] ->  FreeFunc(memory,size), Execbase
                                 A1     D0     a6
    stack         - Pointer to storage (ULONG) for stacksize.

RESULT
    seglist       - Seglist loaded or NULL.  NOT returned in D1!

BUGS
    Really should use tags.

SEE ALSO
    LoadSeg(), UnLoadSeg(), NewLoadSeg(), InternalUnLoadSeg()


dos.library/InternalUnLoadSeg

NAME
    InternalUnLoadSeg -- Unloads a seglist loaded with InternalLoadSeg()
                         (V36)

SYNOPSIS
    success = InternalUnLoadSeg(seglist,FreeFunc)
      D0                          D1       A1

    BOOL InternalUnLoadSeg(BPTR,void (*)(STRPTR,ULONG))

FUNCTION
    Unloads a seglist using freefunc to free segments.  Freefunc is called
    as for InternalLoadSeg.  NOTE: will call Close() for overlaid
    seglists.

INPUTS
    seglist  - Seglist to be unloaded
    FreeFunc - Function called to free memory

RESULT
    success - returns whether everything went OK (since this may close
              files).  Also returns FALSE if seglist was NULL.

BUGS
    Really should use tags

SEE ALSO
    LoadSeg(), UnLoadSeg(), InternalLoadSeg(), NewUnLoadSeg(), Close()


dos.library/IoErr

NAME
    IoErr -- Return extra information from the system

SYNOPSIS
    error = IoErr()
      D0

    LONG IoErr(void)

FUNCTION
    Most I/O routines return zero to indicate an error. When this
    happens (or whatever the defined error return for the routine)
    this routine may be called to determine more information. It is
    also used in some routines to pass back a secondary result.

    Note: there is no guarantee as to the value returned from IoErr()
    after a successful operation, unless to specified by the routine.

RESULTS
    error - integer

SEE ALSO
    Fault(), PrintFault(), SetIoErr()


dos.library/IsFileSystem

NAME
    IsFileSystem -- returns whether a Dos handler is a filesystem (V36)

SYNOPSIS
    result = IsFileSystem(name)
    D0                     D1

    BOOL IsFileSystem(STRPTR)

FUNCTION
    Returns whether the device is a filesystem or not.  A filesystem
    supports seperate files storing information.  It may also support
    sub-directories, but is not required to.  If the filesystem doesn't
    support this new packet, IsFileSystem() will use Lock(":",...) as
    an indicator.

INPUTS
    name   - Name of device in question, with trailing ':'.

RESULT
    result - Flag to indicate if device is a file system

SEE ALSO
    Lock()


dos.library/IsInteractive

NAME
    IsInteractive -- Discover whether a file is "interactive"

SYNOPSIS
    status = IsInteractive( file )
    D0                      D1

    BOOL IsInteractive(BPTR)

FUNCTION
    The return value 'status' indicates whether the file associated
    with the file handle 'file' is connected to a virtual terminal.

INPUTS
    file - BCPL pointer to a file handle

RESULTS
    status - boolean

SEE ALSO


dos.library/LoadSeg

NAME
    LoadSeg -- Scatterload a loadable file into memory

SYNOPSIS
    seglist = LoadSeg( name )
    D0                 D1

    BPTR LoadSeg(STRPTR)

FUNCTION
    The file 'name' should be a load module produced by the linker.
    LoadSeg() scatterloads the CODE, DATA and BSS segments into memory,
    chaining together the segments with BPTR's on their first words.
    The end of the chain is indicated by a zero.  There can be any number
    of segments in a file.  All necessary relocation is handled by
    LoadSeg().

    In the event of an error any blocks loaded will be unloaded and a
    NULL result returned.

    If the module is correctly loaded then the output will be a pointer
    at the beginning of the list of blocks. Loaded code is unloaded via
    a call to UnLoadSeg().

INPUTS
    name - pointer to a null-terminated string

RESULTS
    seglist - BCPL pointer to a seglist

SEE ALSO
    UnLoadSeg(), InternalLoadSeg(), InternalUnLoadSeg(), CreateProc(),
    CreateNewProc(), NewLoadSeg().


dos.library/Lock

NAME
    Lock -- Lock a directory or file

SYNOPSIS
    lock  = Lock( name, accessMode )
    D0            D1        D2

    BPTR Lock(STRPTR, LONG)

FUNCTION
    A filing system lock on the file or directory 'name' is returned if
    possible.

    If the accessMode is ACCESS_READ, the lock is a shared read lock;
    if the accessMode is ACCESS_WRITE then it is an exclusive write
    lock.  Do not use random values for mode.

    If Lock() fails (that is, if it cannot obtain a filing system lock
    on the file or directory) it returns a zero.

    Tricky assumptions about the internal format of a lock are unwise,
    as are any attempts to use the fl_Link or fl_Access fields.

INPUTS
    name       - pointer to a null-terminated string
    accessMode - integer

RESULTS
    lock - BCPL pointer to a lock

SEE ALSO
    UnLock(), DupLock(), ChangeMode(), NameFromLock(), DupLockFromFH()


dos.library/LockDosList

NAME
    LockDosList -- Locks the specified Dos Lists for use (V36)

SYNOPSIS
    dlist = LockDosList(flags)
    D0                   D1

    struct DosList *LockDosList(ULONG)

FUNCTION
    Locks the dos device list in preparation to walk the list.
    If the list is 'busy' then this routine will not return until it is
    available.  This routine "nests": you can call it multiple times, and
    then must unlock it the same number of times.  The dlist
    returned is NOT a valid entry: it is a special value.  Note that
    for 1.3 compatibility, it also does a Forbid() - this will probably
    be removed at some future time.  The 1.3 Forbid() locking of this
    list had some race conditions.  The pointer returned by this is NOT
    an actual DosList pointer - you should use on of the other DosEntry
    calls to get actual pointers to DosList structures (such as
    NextDosEntry()), passing the value returned by LockDosList()
    as the dlist value.

    Note for handler writers: you should never call this function with
    LDF_WRITE, since it can deadlock you (if someone has it read-locked
    and they're trying to send you a packet).  Use AttemptLockDosList()
    instead, and effectively busy-wait with delays for the list to be
    available.  The other option is that you can spawn a process to
    add the entry safely.

    As an example, here's how you can search for all volumes of a specific
    name and do something with them:

    2.0 way:

            dl = LockDosList(LDF_VOLUMES|LDF_READ);
            while (dl = FindDosEntry(dl,name,LDF_VOLUMES))
            {
                    Add to list of volumes to process or break out of
                    the while loop.
                    (You could try using it here, but I advise
                    against it for compatability reasons if you
                    are planning on continuing to examine the list.)
            }

            process list of volumes saved above, or current entry if
            you're only interested in the first one of that name.

            UnLockDosList();  /* must not use dl after this! */

    1.3/2.0 way:

            if (version >= 36)
                    dl = LockDosList(LDF_VOLUMES|LDF_READ);
            else {
                    Forbid();
                    /* tricky! note dol_Next is at offset 0! */
                    dl = &(...->di_DeviceList);
            }

            while (version >= 36 ?
                            dl = FindDosEntry(dl,name,LDF_VOLUMES) :
                            dl = yourfindentry(dl,name,DLT_VOLUME))
            {
                    Add to list of volumes to process, or break out of
                    the while loop.
                    Do NOT lock foo1/foo2 here if you will continue
                    to examine the list - it breaks the forbid
                    and the list may change on you.
            }

            process list of volumes saved above, or current entry if
            you're only interested in the first one of that name.

            if (version >= 36)
                    UnLockDosList();
            else
                    Permit();
            /* must not use dl after this! */
            ...

            struct DosList *
            yourfindentry (struct DosList *dl, STRPTRname, type)
            {
            /* tricky - depends on dol_Next being at offset 0,
               and the initial ptr being a ptr to di_DeviceList! */
                    while (dl = dl->dol_Next)
                    {
                        if (dl->dol_Type == type &&
                            stricmp(name,BADDR(dl->dol_Name)+1) == 0)
                        {
                            break;
                        }
                    }
                    return dl;
            }

INPUTS
    flags - Flags stating which types of nodes you want to lock.

RESULT
    dlist - Pointer to the head of the list.  NOT a valid node!

SEE ALSO
    AttemptLockDosList(), UnLockDosList(), Forbid(), NextDosEntry()


dos.library/LockRecord

NAME
    LockRecord -- Locks a portion of a file (V36)

SYNOPSIS
    success = LockRecord(fh,offset,length,mode,timeout)
    D0                   D1   D2     D3    D4    D5

    ULONG LockRecord(BPTR,ULONG,ULONG,ULONG,ULONG)

FUNCTION
    This locks a portion of a file for exclusive access.  Timeout is how
    long to wait in ticks (1/50 sec) for the record to be available.

    Valid modes are:
            REC_EXCLUSIVE
            REC_EXCLUSIVE_IMMED
            REC_SHARED
            REC_SHARED_IMMED
    For the IMMED modes, the timeout is ignored.

    Record locks are tied to the filehandle used to create them.  The
    same filehandle can get any number of exclusive locks on the same
    record, for example.  These are cooperative locks, they only
    affect other people calling LockRecord().

INPUTS
    fh      - File handle for which to lock the record
    offset  - Record start position
    length  - Length of record in bytes
    mode    - Type of lock requester
    timeout - Timeout interval in ticks.  0 is legal.

RESULT
    success - Success or failure

BUGS
    In 2.0 through 2.02 (V36), LockRecord() only worked in the ramdisk.
    Attempting to lock records on the disk filesystem causes a crash.
    This was fixed for V37.

SEE ALSO
    LockRecords(), UnLockRecord(), UnLockRecords()


dos.library/LockRecords

NAME
    LockRecords -- Lock a series of records (V36)

SYNOPSIS
    success = LockRecords(record_array,timeout)
    D0                       D1           D2

    BOOL LockRecords(struct RecordLock *,ULONG)

FUNCTION
    This locks several records within a file for exclusive access.
    Timeout is how long to wait in ticks for the records to be available.
    The wait is applied to each attempt to lock each record in the list.
    It is recommended that you always lock a set of records in the same
    order to reduce possibilities of deadlock.

    The array of RecordLock structures is terminated by an entry with
    rec_FH of NULL.

INPUTS
    record_array - List of records to be locked
    timeout      - Timeout interval.  0 is legal

RESULT
    success      - Success or failure

BUGS
    See LockRecord()

SEE ALSO
    LockRecord(), UnLockRecord(), UnLockRecords()


dos.library/MakeDosEntry

NAME
    MakeDosEntry -- Creates a DosList structure (V36)

SYNOPSIS
    newdlist = MakeDosEntry(name, type)
    D0                       D1    D2

    struct DosList *MakeDosEntry(STRPTR, LONG)

FUNCTION
    Create a DosList structure, including allocating a name and correctly
    null-terminating the BSTR.  It also sets the dol_Type field, and sets
    all other fields to 0.  This routine should be eliminated and replaced
    by a value passed to AllocDosObject()!

INPUTS
    name - name for the device/volume/assign node.
    type - type of node.

RESULT
    newdlist - The new device entry or NULL.

SEE ALSO
    AddDosEntry(), RemDosEntry(), FindDosEntry(), LockDosList(),
    NextDosEntry(), FreeDosEntry()


dos.library/MakeLink

NAME
    MakeLink -- Creates a filesystem link (V36)

SYNOPSIS
    success = MakeLink( name, dest, soft )
    D0                   D1    D2    D3

    BOOL MakeLink( STRPTR, LONG, LONG )

FUNCTION
    Create a filesystem link from 'name' to dest.  For "soft-links",
    dest is a pointer to a null-terminated path string.  For "hard-
    links", dest is a lock (BPTR).  'soft' is FALSE for hard-links,
    non-zero otherwise.

    Soft-links are resolved at access time by a combination of the
    filesystem (by returning ERROR_IS_SOFT_LINK to dos), and by
    Dos (using ReadLink() to resolve any links that are hit).

    Hard-links are resolved by the filesystem in question.  A series
    of hard-links to a file are all equivalent to the file itself.
    If one of the links (or the original entry for the file) is
    deleted, the data remains until there are no links left.

INPUTS
    name - Name of the link to create
    dest - CPTR to path string, or BPTR lock
    soft - FALSE for hard-links, non-zero for soft-links

RESULT
    Success - boolean

BUGS
    In V36, soft-links didn't work in the ROM filesystem.  This was
    fixed for V37.

SEE ALSO
    ReadLink(), Open(), Lock()


dos.library/MatchEnd

NAME
    MatchEnd -- Free storage allocated for MatchFirst()/MatchNext() (V36)

SYNOPSIS
    MatchEnd(AnchorPath)
                 D1

    VOID MatchEnd(struct AnchorPath *)

FUNCTION
    Return all storage associated with a given search.

INPUTS
    AnchorPath - Anchor used for MatchFirst()/MatchNext()
                 MUST be longword aligned!

SEE ALSO
    MatchFirst(), ParsePattern(), Examine(), CurrentDir(), Examine(),
    MatchNext(), ExNext(), <dos/dosasl.h>


dos.library/MatchFirst

NAME
    MatchFirst -- Finds file that matches pattern (V36)

SYNOPSIS
    error = MatchFirst(pat, AnchorPath)
    D0                 D1       D2

    LONG MatchFirst(STRPTR, struct AnchorPath *)

FUNCTION
    Locates the first file or directory that matches a given pattern.
    MatchFirst() is passed your pattern (you do not pass it through
    ParsePattern() - MatchFirst() does that for you), and the control
    structure.  MatchFirst() normally initializes your AnchorPath
    structure for you, and returns the first file that matched your
    pattern, or an error.  Note that MatchFirst()/MatchNext() are unusual
    for Dos in that they return 0 for success, or the error code (see
    <dos/dos.h>), instead of the application getting the error code
    from IoErr().

    When looking at the result of MatchFirst()/MatchNext(), the ap_Info
    field of your AnchorPath has the results of an Examine() of the object.
    You normally get the name of the object from fib_FileName, and the
    directory it's in from ap_Current->an_Lock.  To access this object,
    normally you would temporarily CurrentDir() to the lock, do an action
    to the file/dir, and then CurrentDir() back to your original directory.
    This makes certain you affect the right object even when two volumes
    of the same name are in the system.  You can use ap_Buf (with
    ap_Strlen) to get a name to report to the user.

    To initialize the AnchorPath structure (particularily when reusing
    it), set ap_BreakBits to the signal bits (CDEF) that you want to take
    a break on, or NULL, if you don't want to convenience the user.
    ap_Flags should be set to any flags you need or all 0's otherwise.
    ap_FoundBreak should be cleared if you'll be using breaks.

    If you want to have the FULL PATH NAME of the files you found,
    allocate a buffer at the END of this structure, and put the size of
    it into ap_Strlen.  If you don't want the full path name, make sure
    you set ap_Strlen to zero.  In this case, the name of the file, and
    stats are available in the ap_Info, as per usual.

    Then call MatchFirst() and then afterwards, MatchNext() with this
    structure.  You should check the return value each time (see below)
    and take the appropriate action, ultimately calling MatchEnd() when
    there are no more files or you are done.  You can tell when you are
    done by checking for the normal AmigaDOS return code
    ERROR_NO_MORE_ENTRIES.

    Note: patterns with trailing slashes may cause MatchFirst()/MatchNext()
    to return with an ap_Current->an_Lock on the object, and a filename
    of the empty string ("").

    See ParsePattern() for more information on the patterns.

INPUTS
    pat        - Pattern to search for
    AnchorPath - Place holder for search.  MUST be longword aligned!

RESULT
    error - 0 for success or error code.  (Opposite of most Dos calls!)

BUGS
    In V36, there were a number of bugs with MatchFirst()/MatchNext().
    One was that if you entered a directory with a name like "df0:l"
    using DODIR, it would re-lock the full string "df0:l", which can
    cause problems if the disk has changed.  It also had problems
    with patterns such as #?/abc/def - the ap_Current->an_Lock would
    not be on the directory def is found in.  ap_Buf would be correct,
    however.  It had similar problems with patterns with trailing
    slashes.  These have been fixed for V37 and later.

    A bug that has not been fixed for V37 concerns a pattern of a
    single directory name (such as "l").  If you enter such a directory
    via DODIR, it re-locks l relative to the current directory.  Thus
    you must not change the current directory before calling MatchNext()
    with DODIR in that situation.  If you aren't using DODIR to enter
    directories you can ignore this.  This may be fixed in some upcoming
    release.

SEE ALSO
    MatchNext(), ParsePattern(), Examine(), CurrentDir(), Examine(),
    MatchEnd(), ExNext(), <dos/dosasl.h>


dos.library/MatchNext

NAME
    MatchNext - Finds the next file or directory that matches pattern (V36)

SYNOPSIS
    error = MatchNext(AnchorPath)
    D0                    D1

    LONG MatchNext(struct AnchorPath *)

FUNCTION
    Locates the next file or directory that matches a given pattern.
    See <dos/dosasl.h> for more information.  Various bits in the flags
    allow the application to control the operation of MatchNext().

    See MatchFirst() for other notes.

INPUTS
    AnchorPath - Place holder for search.  MUST be longword aligned!

RESULT
    error - 0 for success or error code.  (Opposite of most Dos calls)

BUGS
    See MatchFirst().

SEE ALSO
    MatchFirst(), ParsePattern(), Examine(), CurrentDir(), Examine(),
    MatchEnd(), ExNext(), <dos/dosasl.h>


dos.library/MatchPattern

NAME
    MatchPattern --  Checks for a pattern match with a string (V36)

SYNOPSIS
    match = MatchPattern(pat, str)
    D0                   D1   D2

    BOOL MatchPattern(STRPTR, STRPTR)

FUNCTION
    Checks for a pattern match with a string.  The pattern must be a
    tokenized string output by ParsePattern().  This routine is
    case-sensitive.

    NOTE: this routine is highly recursive.  You must have at least
    1500 free bytes of stack to call this (it will cut off it's
    recursion before going any deeper than that and return failure).
    That's _currently_ enough for about 100 levels deep of #, (, ~, etc.

INPUTS
    pat - Special pattern string to match as returned by ParsePattern()
    str - String to match against given pattern

RESULT
    match - success or failure of pattern match.  On failure,
            IoErr() will return 0 or ERROR_TOO_MANY_LEVELS (starting
            with V37 - before that there was no stack checking).

SEE ALSO
    ParsePattern(), MatchPatternNoCase(), MatchFirst(), MatchNext()


dos.library/MatchPatternNoCase

NAME
    MatchPatternNoCase --  Checks for a pattern match with a string (V37)

SYNOPSIS
    match = MatchPatternNoCase(pat, str)
    D0                         D1   D2

    BOOL MatchPatternNoCase(STRPTR, STRPTR)

FUNCTION
    Checks for a pattern match with a string.  The pattern must be a
    tokenized string output by ParsePatternNoCase().  This routine is
    case-insensitive.

    NOTE: this routine is highly recursive.  You must have at least
    1500 free bytes of stack to call this (it will cut off it's
    recursion before going any deeper than that and return failure).
    That's _currently_ enough for about 100 levels deep of #, (, ~, etc.

INPUTS
    pat - Special pattern string to match as returned by
          ParsePatternNoCase()
    str - String to match against given pattern

RESULT
    match - success or failure of pattern match.  On failure,
            IoErr() will return 0 or ERROR_TOO_MANY_LEVELS (starting
            with V37 - before that there was no stack checking).

SEE ALSO
    ParsePatternNoCase(), MatchPattern(), MatchFirst(), MatchNext()


dos.library/MaxCli

NAME
    MaxCli -- returns the highest CLI process number possibly in use (V36)

SYNOPSIS
    number = MaxCli()
    D0

    LONG MaxCli(void)

FUNCTION
    Returns the highest CLI number that may be in use.  CLI numbers are
    reused, and are usually as small as possible.  To find all CLIs, scan
    using FindCliProc() from 1 to MaxCLI().  The number returned by
    MaxCli() may change as processes are created and destroyed.

RESULT
    number - The highest CLI number that _may_ be in use.

SEE ALSO
    FindCliProc(), Cli()


dos.library/NameFromFH

NAME
    NameFromFH -- Get the name of an open filehandle (V36)

SYNOPSIS
    success = NameFromFH(fh, buffer, len)
    D0                   D1    D2    D3

    BOOL NameFromFH(BPTR, STRPTR, LONG)

FUNCTION
    Returns a fully qualified path for the filehandle.  This routine is
    guaranteed not to write more than len characters into the buffer.  The
    name will be null-terminated.  See NameFromLock() for more information.

INPUTS
    fh     - Lock of object to be examined.
    buffer - Buffer to store name.
    len    - Length of buffer.

RESULT
    success - Success/failure indicator.

SEE ALSO
    NameFromLock()


dos.library/NameFromLock

NAME
    NameFromLock -- Returns the name of a locked object (V36)

SYNOPSIS
    success = NameFromLock(lock, buffer, len)
    D0                      D1     D2    D3

    BOOL NameFromLock(BPTR, STRPTR, LONG)

FUNCTION
    Returns a fully qualified path for the lock.  This routine is
    guaranteed not to write more than len characters into the buffer.  The
    name will be null-terminated.  NOTE: if the volume is not mounted,
    the system will request it (unless of course you set pr_WindowPtr to
    -1).  If the volume is not mounted or inserted, it will return an
    error.  If the lock passed in is NULL, "SYS:" will be returned. If
    the buffer is too short, an error will be returned, and IoErr() will
    return ERROR_LINE_TOO_LONG.

INPUTS
    lock   - Lock of object to be examined.
    buffer - Buffer to store name.
    len    - Length of buffer.

RESULT
    success - Success/failure indicator.

BUGS
    Should return the name of the boot volume instead of SYS: for a NULL
    lock.

SEE ALSO
    NameFromFH(), Lock()


dos.library/NewLoadSeg

NAME
    NewLoadSeg -- Improved version of LoadSeg for stacksizes (V36)

SYNOPSIS
    seglist = NewLoadSeg(file, tags)
    D0                    D1    D2

    BPTR NewLoadSeg(STRPTR, struct TagItem *)

    seglist = NewLoadSegTagList(file, tags)
    D0                           D1    D2

    BPTR NewLoadSegTagList(STRPTR, struct TagItem *)

    seglist = NewLoadSegTags(file, ...)

    BPTR NewLoadSegTags(STRPTR, ...)

FUNCTION
    Does a LoadSeg on a file, and takes additional actions based on the
    tags supplied.

    Clears unused portions of Code and Data hunks (as well as BSS hunks).
    (This also applies to InternalLoadSeg() and LoadSeg()).

    NOTE to overlay users: NewLoadSeg() does NOT return seglist in
    both D0 and D1, as LoadSeg does.  The current ovs.asm uses LoadSeg(),
    and assumes returns are in D1.  We will support this for LoadSeg()
    ONLY.

INPUTS
    file - Filename of file to load
    tags - pointer to tagitem array

RESULT
    seglist - Seglist loaded, or NULL

BUGS
    No tags are currently defined.

SEE ALSO
    LoadSeg(), UnLoadSeg(), InternalLoadSeg(), InternalUnLoadSeg()


dos.library/NextDosEntry

NAME
    NextDosEntry -- Get the next Dos List entry (V36)

SYNOPSIS
    newdlist = NextDosEntry(dlist,flags)
    D0                       D1    D2

    struct DosList *NextDosEntry(struct DosList *,ULONG)

FUNCTION
    Find the next Dos List entry of the right type.  You MUST have locked
    the types you're looking for.  Returns NULL if there are no more of
    that type in the list.

INPUTS
    dlist    - The current device entry.
    flags    - What type of entries to look for.

RESULT
    newdlist - The next device entry of the right type or NULL.

SEE ALSO
    AddDosEntry(), RemDosEntry(), FindDosEntry(), LockDosList(),
    MakeDosEntry(), FreeDosEntry()


dos.library/Open

NAME
    Open -- Open a file for input or output

SYNOPSIS
    file = Open( name, accessMode )
    D0           D1    D2

    BPTR Open(STRPTR, LONG)

FUNCTION
    The named file is opened and a file handle returned.  If the
    accessMode is MODE_OLDFILE, an existing file is opened for reading
    or writing. If the value is MODE_NEWFILE, a new file is created for
    writing. MODE_READWRITE opens a file with an shared lock, but
    creates it if it didn't exist.  Open types are documented in the
    <dos/dos.h> or <libraries/dos.h> include file.

    The 'name' can be a filename (optionally prefaced by a device
    name), a simple device such as NIL:, a window specification such as
    CON: or RAW: followed by window parameters, or "*", representing the
    current window.  Note that as of V36, "*" is obsolete, and CONSOLE:
    should be used instead.

    If the file cannot be opened for any reason, the value returned
    will be zero, and a secondary error code will be available by
    calling the routine IoErr().

INPUTS
    name       - pointer to a null-terminated string
    accessMode - integer

RESULTS
    file - BCPL pointer to a file handle

SEE ALSO
    Close(), ChangeMode(), NameFromFH(), ParentOfFH(), ExamineFH()


dos.library/OpenFromLock

NAME
    OpenFromLock -- Opens a file you have a lock on (V36)

SYNOPSIS
    fh = OpenFromLock(lock)
    D0                 D1

    BPTR OpenFromLock(BPTR)

FUNCTION
    Given a lock, this routine performs an open on that lock.  If the open
    succeeds, the lock is (effectively) relinquished, and should not be
    UnLock()ed or used.  If the open fails, the lock is still usable.
    The lock associated with the file internally is of the same access
    mode as the lock you gave up - shared is similar to MODE_OLDFILE,
    exclusive is similar to MODE_NEWFILE.

INPUTS
    lock - Lock on object to be opened.

RESULT
    fh   - Newly opened file handle or NULL for failure

BUGS
    In the original V36 autodocs, this was shown (incorrectly) as
    taking a Mode parameter as well.  The prototypes and pragmas were
    also wrong.

SEE ALSO
    Open(), Close(), Lock(), UnLock()


dos.library/Output

NAME
    Output -- Identify the programs' initial output file handle

SYNOPSIS
    file = Output()
    D0

    BPTR Output(void)

FUNCTION
    Output() is used to identify the initial output stream allocated
    when the program was initiated.  Never close the filehandle returned
    by Output().

RESULTS
    file - BCPL pointer to a file handle

SEE ALSO
    Input()


dos.library/ParentDir

NAME
    ParentDir -- Obtain the parent of a directory or file

SYNOPSIS
    newlock = ParentDir( lock )
    D0                   D1

    BPTR ParentDir(BPTR)

FUNCTION
    The argument 'lock' is associated with a given file or directory.
    ParentDir() returns 'newlock' which is associated the parent
    directory of 'lock'.

    Taking the ParentDir() of the root of the current filing system
    returns a NULL (0) lock.  Note this 0 lock represents the root of
    file system that you booted from (which is, in effect, the parent
    of all other file system roots.)

INPUTS
    lock - BCPL pointer to a lock

RESULTS
    newlock - BCPL pointer to a lock

SEE ALSO
    Lock(), DupLock(), UnLock(), ParentOfFH(), DupLockFromFH()


dos.library/ParentOfFH

NAME
    ParentOfFH -- returns a lock on the parent directory of a file (V36)

SYNOPSIS
    lock = ParentOfFH(fh)
    D0               D1

    BPTR ParentOfFH(BPTR)

FUNCTION
    Returns a shared lock on the parent directory of the filehandle.

INPUTS
    fh   - Filehandle you want the parent of.

RESULT
    lock - Lock on parent directory of the filehandle or NULL for failure.

SEE ALSO
    Parent(), Lock(), UnLock() DupLockFromFH()


dos.library/ParsePattern

NAME
    ParsePattern -- Create a tokenized string for MatchPattern() (V36)

SYNOPSIS
    IsWild = ParsePattern(Source, Dest, DestLength)
    d0                      D1     D2      D3

    LONG ParsePattern(STRPTR, STRPTR, LONG)

FUNCTION
    Tokenizes a pattern, for use by MatchPattern().  Also indicates if
    there are any wildcards in the pattern (i.e. whether it might match
    more than one item).  Note that Dest must be at least 2 times as
    large as Source plus bytes to be (almost) 100% certain of no
    buffer overflow.  This is because each input character can currently
    expand to 2 tokens (with one exception that can expand to 3, but
    only once per string).  Note: this implementation may change in
    the future, so you should handle error returns in all cases, but
    the size above should still be a reasonable upper bound for a buffer
    allocation.

    The patterns are fairly extensive, and approximate some of the ability
    of Unix/grep "regular expression" patterns.  Here are the available
    tokens:

    ?       Matches a single character.
    #       Matches the following expression 0 or more times.
    (ab|cd) Matches any one of the items seperated by '|'.
    ~       Negates the following expression.  It matches all strings
            that do not match the expression (aka ~(foo) matches all
            strings that are not exactly "foo").
    [abc]   Character class: matches any of the characters in the class.
    [~bc]   Character class: matches any of the characters not in the
            class.
    a-z     Character range (only within character classes).
    %       Matches 0 characters always (useful in "(foo|bar|%)").
    *       Synonym for "#?", not available by default in 2.0.  Available
            as an option that can be turned on.

    "Expression" in the above table means either a single character
    (ex: "#?"), or an alternation (ex: "#(ab|cd|ef)"), or a character
    class (ex: "#[a-zA-Z]").

INPUTS
    source     - unparsed wildcard string to search for.
   dest       - output string, gets tokenized version of input.
    DestLength - length available in destination (should be at least as
                 twice as large as source + 2 bytes).

RESULT
    IsWild - 1 means there were wildcards in the pattern,
             0 means there were no wildcards in the pattern,
            -1 means there was a buffer overflow or other error

BUGS
    Should set IoErr() to something useful (not currently set) on an
    error.

SEE ALSO
    ParsePatternNoCase(), MatchPattern(), MatchFirst(), MatchNext()


dos.library/ParsePatternNoCase

NAME
    ParsePatternNoCase -- Create a tokenized string for
                                            MatchPatternNoCase() (V37)

SYNOPSIS
    IsWild = ParsePatternNoCase(Source, Dest, DestLength)
    d0                            D1     D2      D3

    LONG ParsePatternNoCase(STRPTR, STRPTR, LONG)

FUNCTION
    Tokenizes a pattern, for use by MatchPatternNoCase().  Also indicates
    if there are any wildcards in the pattern (i.e. whether it might match
    more than one item).  Note that Dest must be at least 2 times as
    large as Source plus 2 bytes.

    For a description of the wildcards, see ParsePattern().

INPUTS
    source     - unparsed wildcard string to search for.
   dest       - output string, gets tokenized version of input.
    DestLength - length available in destination (should be at least as
                 twice as large as source + 2 bytes).

RESULT
    IsWild - 1 means there were wildcards in the pattern,
             0 means there were no wildcards in the pattern,
            -1 means there was a buffer overflow or other error

BUGS
    Should set IoErr() to something useful (not currently set) on an
    error.

SEE ALSO
    ParsePattern(), MatchPatternNoCase(), MatchFirst(), MatchNext()


dos.library/PathPart

NAME
    PathPart -- Returns a pointer to the end of the next-to-last (V36)
                component of a path.

SYNOPSIS
    fileptr = PathPart( path )
    D0                   D1

    STRPTR PathPart( STRPTR )

FUNCTION
    This function returns a pointer to the character after the next-to-last
    component of a path specification, which will normally be the directory
    name.  If there is only one component, it returns a pointer to the
    beginning of the string.  The only real difference between this and
    FilePart() is the handling of '/'.

INPUTS
    path - pointer to an path string.  May be relative to the current
           directory or the current disk.

RESULT
    fileptr - pointer to the end of the next-to-last component of the path.

EXAMPLE
    PathPart("xxx:yyy/zzz/qqq") would return a pointer to the last '/'.
    PathPart("xxx:yyy") would return a pointer to the first 'y').

SEE ALSO
    FilePart(), AddPart()


dos.library/PrintFault

NAME
    PrintFault -- Returns the text associated with a DOS error code (V36)

SYNOPSIS
    success = PrintFault(code, header)
    D0                    D1     D2

    BOOL PrintFault(LONG, STRPTR)

FUNCTION
    This routine obtains the error message text for the given error code.
    This is similar to the Fault() function, except that the output is
    written to the default output channel with buffered output.
    The value returned by IoErr() is set to the code passed in.

INPUTS
    code   - Error code
    header - header to output before error text

RESULT
    success - Success/failure code.

SEE ALSO
    IoErr(), Fault(), SetIoErr(), Output(), FPuts()


dos.library/PutStr

NAME
    PutStr -- Writes a string the the default output (buffered) (V36)

SYNOPSIS
    error = PutStr(str)
    D0             D1

    LONG PutStr(STRPTR)

FUNCTION
    This routine writes an unformatted string to the default output.  No
    newline is appended to the string and any error is returned.  This
    routine is buffered.

INPUTS
    str   - Null-terminated string to be written to default output

RESULT
    error - 0 for success, -1 for any error.  NOTE: this is opposite
            most Dos function returns!

SEE ALSO
    FPuts(), FPutC(), FWrite(), WriteChars()


dos.library/Read

NAME
    Read -- Read bytes of data from a file

SYNOPSIS
    actualLength = Read( file, buffer, length )
    D0                   D1    D2      D3

    LONG Read(BPTR, void *, LONG)

FUNCTION
    Data can be copied using a combination of Read() and Write().
    Read() reads bytes of information from an opened file (represented
    here by the argument 'file') into the buffer given. The argument
    'length' is the length of the buffer given.

    The value returned is the length of the information actually read.
    So, when 'actualLength' is greater than zero, the value of
    'actualLength' is the the number of characters read. Usually Read
    will try to fill up your buffer before returning. A value of zero
    means that end-of-file has been reached. Errors are indicated by a
    value of -1.

    Note: this is an unbuffered routine (the request is passed directly
    to the filesystem.)  Buffered I/O is more efficient for small
    reads and writes; see FGetC().

INPUTS
    file - BCPL pointer to a file handle
    buffer - pointer to buffer
    length - integer

RESULTS
    actualLength - integer

SEE ALSO
    Open(), Close(), Write(), Seek(), FGetC()


dos.library/ReadArgs

NAME
    ReadArgs - Parse the command line input (V36)

SYNOPSIS
    result = ReadArgs(template, array, rdargs)
    D0                   D1      D2      D3

    struct RDArgs * ReadArgs(STRPTR, LONG *, struct RDArgs *)

FUNCTION
    Parses and argument string according to a template.  Normally gets
    the arguments by reading buffered IO from Input(), but also can be
    made to parse a string.  MUST be matched by a call to FreeArgs().

    ReadArgs() parses the commandline according to a template that is
    passed to it.  This specifies the different command-line options and
    their types.  A template consists of a list of options.  Options are
    named in "full" names where possible (for example, "Quick" instead of
    "Q").  Abbreviations can also be specified by using "abbrev=option"
    (for example, "Q=Quick").

    Options in the template are separated by commas.  To get the results
    of ReadArgs(), you examine the array of longwords you passed to it
    (one entry per option in the template).  This array should be cleared
    (or initialized to your default values) before passing to ReadArgs().
    Exactly what is put in a given entry by ReadArgs() depends on the type
    of option.  The default is a string (a sequence of non-whitespace
    characters, or delimited by quotes, which will be stripped by
    ReadArgs()), in which case the entry will be a pointer.

    Options can be followed by modifiers, which specify things such as
    the type of the option.  Modifiers are specified by following the
    option with a '/' and a single character modifier.  Multiple modifiers
    can be specified by using multiple '/'s.  Valid modifiers are:

    /S - Switch.  This is considered a boolean variable, and will be
         set if the option name appears in the command-line.  The entry
         is the boolean (0 for not set, non-zero for set).

    /K - Keyword.  This means that the option will not be filled unless
         the keyword appears.  For example if the template is "Name/K",
         then unless "Name=<string>" or "Name <string>" appears in the
         command line, Name will not be filled.

    /N - Number.  This parameter is considered a decimal number, and will
         be converted by ReadArgs.  If an invalid number is specified,
         an error will be returned.  The entry will be a pointer to the
         longword number (this is how you know if a number was specified).

    /T - Toggle.  This is similar to a switch, but when specified causes
         the boolean value to "toggle".  Similar to /S.

    /A - Required.  This keyword must be given a value during command-line
         processing, or an error is returned.

    /F - Rest of line.  If this is specified, the entire rest of the line
         is taken as the parameter for the option, even if other option
         keywords appear in it.

    /M - Multiple strings.  This means the argument will take any number
         of strings, returning them as an array of strings.  Any arguments
         not considered to be part of another option will be added to this
         option.  Only one /M should be specified in a template.  Example:
         for a template "Dir/M,All/S" the command-line "foo bar all qwe"
         will set the boolean "all", and return an array consisting of
         "foo", "bar", and "qwe".  The entry in the array will be a pointer
         to an array of string pointers, the last of which will be NULL.

         There is an interaction between /M parameters and /A parameters.
         If there are unfilled /A parameters after parsing, it will grab
         strings from the end of a previous /M parameter list to fill the
         /A's.  This is used for things like Copy ("From/A/M,To/A").

    ReadArgs() returns a struct RDArgs if it succeeds.  This serves as an
    "anchor" to allow FreeArgs() to free the associated memory.  You can
    also pass in a struct RDArgs to control the operation of ReadArgs()
    (normally you pass NULL for the parameter, and ReadArgs() allocates
    one for you).  This allows providing different sources for the
    arguments, providing your own string buffer space for temporary
    storage, and extended help text.  See <dos/rdargs.h> for more
    information on this.  Note: if you pass in a struct RDArgs, you must
    still call FreeArgs() to release storage that gets attached to it,
    but you are responsible for freeing the RDArgs yourself.

    See BUGS regarding passing in strings.

INPUTS
    template - formatting string
    array    - array of longwords for results, 1 per template entry
    rdargs   - optional rdargs structure for options.  AllocDosObject
               should be used for allocating them if you pass one in.

RESULT
    result   - a struct RDArgs or NULL for failure.

BUGS
    In V36, there were a couple of minor bugs with certain argument
    combinations (/M/N returned strings, /T didn't work, and /K and
    /F interacted).  Also, a template with a /K before any non-switch
    parameter will require the argument name to be given in order for
    line to be accepted (i.e. "parm/K,xyzzy/A" would require
    "xyzzy=xxxxx" in order to work - "xxxxx" would not work).  If you
    need to avoid this for V36, put /K parameters after all non-switch
    parameters.  These problems should be fixed for V37.

    Currently (V37 and before) it requires any strings passed in to have
    newlines at the end of the string.  This may or may not be fixed in
    the future.

SEE ALSO
    FindArg(), ReadItem(), FreeArgs(), AllocDosObject()


dos.library/ReadItem

NAME
    ReadItem - reads a single argument/name from command line (V36)

SYNOPSIS
    value = ReadItem(buffer, maxchars, input)
    D0                D1        D2      D3

    LONG ReadItem(STRPTR, LONG, struct CSource *)

FUNCTION
    Reads a "word" from either Input() (buffered), or via CSource, if it
    is non-NULL (see <dos/rdargs.h> for more information).  Handles
    quoting and some '*' substitutions (*e and *n) inside quotes (only).
    See dos/dos.h for a listing of values returned by ReadItem()
    (ITEM_XXXX).  A "word" is delimited by whitespace, quotes, or an EOF.

    ReadItem always unreads the last thing read (UnGetC(fh,-1)) so the
    caller can find out what the terminator was.

INPUTS
    buffer   - buffer to store word in.
    maxchars - size of the buffer
    input    - CSource input or NULL (uses FGetC(Input()))

RESULT
    value - See <dos/dos.h> for return values.

SEE ALSO
    ReadArgs(), FindArg(), UnGetC(), FGetC(), Input(), <dos/dos.h>,
    <dos/rdargs.h>, FreeArgs()


dos.library/ReadLink

NAME
    ReadLink -- Reads the path for a soft filesystem link (V36)

SYNOPSIS
    success = ReadLink( port, lock, path, buffer, size)
    D0                   D1    D2    D3     D4     D5

    BOOL ReadLink( struct MsgPort *, BPTR, STRPTR, STRPTR, ULONG)

FUNCTION
    ReadLink() takes a lock/name pair (usually from a failed attempt
    to use them to access an object with packets), and asks the
    filesystem to find the softlink and fill buffer with the modified
    path string.  You then start the resolution process again by
    calling GetDeviceProc() with the new string from ReadLink().

    Soft-links are resolved at access time by a combination of the
    filesystem (by returning ERROR_IS_SOFT_LINK to dos), and by
    Dos (using ReadLink() to resolve any links that are hit).

INPUTS
    port - msgport of the filesystem
    lock - lock this path is relative to on the filesystem
    path - path that caused the ERROR_IS_SOFT_LINK
    buffer - pointer to buffer for new path from handler.
    size - size of buffer.

RESULT
    Success - boolean

BUGS
    In V36, soft-links didn't work in the ROM filesystem.  This was
    fixed for V37.

SEE ALSO
    MakeLink(), Open(), Lock(), GetDeviceProc()


dos.library/Relabel

NAME
    Relabel -- Change the volume name of a volume (V36)

SYNOPSIS
    success = Relabel(volumename,name)
    D0                    D1      D2

    BOOL Relabel(STRPTR,STRPTR)

FUNCTION
    Changes the volumename of a volume, if supported by the filesystem.

INPUTS
    volumename - Full name of device to rename (with ':')
    newname    - New name to apply to device (without ':')

RESULT
    success    - Success/failure indicator

SEE ALSO


dos.library/RemAssignList

NAME
    RemAssignList -- Remove an entry from a multi-dir assign (V36)

SYNOPSIS
    success = RemAssignList(name,lock)
    D0                       D1   D2

    BOOL RemAssignList(STRPTR,BPTR)

FUNCTION
    Removes an entry from a multi-directory assign.  The entry removed is
    the first one for which SameLock with 'lock' returns that they are on
    the same object.  The lock for the entry in the list is unlocked (not
    the entry passed in).

INPUTS
    name - Name of device to remove lock from (without trailing ':')
    lock - Lock associated with the object to remove from the list

RESULT
    success - Success/failure indicator.

SEE ALSO
    Lock(), AssignLock(), AssignPath(), AssignLate(), DupLock(),
    AssignAdd(), UnLock()


dos.library/RemDosEntry

NAME
    RemDosEntry -- Removes a Dos List entry from it's list (V36)

SYNOPSIS
    success = RemDosEntry(dlist)
    D0                     D1

    BOOL RemDosEntry(struct DosList *)

FUNCTION
    This removes an entry from the Dos Device list.  The memory associated
    with the entry is NOT freed.  NOTE: you must have locked the Dos List
    with the appropriate flags before calling this routine.  Handler
    writers should see the AddDosEntry() caveats about locking and use
    a similar workaround to avoid deadlocks.

INPUTS
    dlist   - Device list entry to be removed.

RESULT
    success - Success/failure indicator

SEE ALSO
    AddDosEntry(), FindDosEntry(), NextDosEntry(), LockDosList(),
    MakeDosEntry(), FreeDosEntry()


dos.library/RemSegment

NAME
    RemSegment - Removes a resident segment from the resident list (V36)

SYNOPSIS
    success = RemSegment(segment)
    D0                      D1

    BOOL RemSegment(struct Segment *)

FUNCTION
    Removes a resident segment from the Dos resident segment list,
    unloads it, and does any other cleanup required.  Will only succeed
    if the seg_UC (usecount) is 0.

INPUTS
    segment - the segment to be removed

RESULT
    success - success or failure.

SEE ALSO
    FindSegment(), AddSegment()


dos.library/Rename

NAME
    Rename -- Rename a directory or file

SYNOPSIS
    success = Rename( oldName, newName )
    D0                D1       D2

    BOOL Rename(STRPTR, STRPTR)

FUNCTION
    Rename() attempts to rename the file or directory specified as
    'oldName' with the name 'newName'. If the file or directory
    'newName' exists, Rename() fails and returns an error. Both
    'oldName' and the 'newName' can contain a directory specification.
    In this case, the file will be moved from one directory to another.

    Note: it is impossible to Rename() a file from one volume to
    another.

INPUTS
    oldName - pointer to a null-terminated string
    newName - pointer to a null-terminated string

RESULTS
    success - boolean

SEE ALSO
    Relabel()


dos.library/ReplyPkt

NAME
    ReplyPkt -- replies a packet to the person who sent it to you (V36)

SYNOPSIS
    ReplyPkt(packet, result1, result2)
               D1      D2       D3

    void ReplyPkt(struct DosPacket *, LONG, LONG)

FUNCTION
    This returns a packet to the process which sent it to you.  In
    addition, puts your pr_MsgPort address in dp_Port, so using ReplyPkt()
    again will send the message to you.  (This is used in "ping-ponging"
    packets between two processes).  It uses result 1 & 2 to set the
    dp_Res1 and dp_Res2 fields of the packet.

INPUTS
    packet  - packet to reply, assumed to set up correctly.
    result1 - first result
    result2 - secondary result

SEE ALSO
    DoPkt(), SendPkt(), WaitPkt(), IoErr()


dos.library/RunCommand

NAME
    RunCommand -- Runs a program using the current process (V36)

SYNOPSIS
    rc = RunCommand(seglist, stacksize, argptr, argsize)
    D0                D1         D2       D3      D4

    LONG RunCommand(BPTR, ULONG, STRPTR, ULONG)

FUNCTION
    Runs a command on your process/cli.  Seglist may be any language,
    including BCPL programs.  Stacksize is in bytes.  argptr is a null-
    terminated string, argsize is its length.  Returns the returncode the
    program exited with in d0. Returns -1 if the stack couldn't be
    allocated.

    NOTE: the argument string MUST be terminated with a newline to work
    properly with ReadArgs() and other argument parsers.

    RunCommand also takes care of setting up the current input filehandle
    in such a way that ReadArgs() can be used in the program, and restores
    the state of the buffering before returning.  It also sets the value
    returned by GetArgStr(), and restores it before returning.  NOTE:
    the setting of the argument string in the filehandle was added in V37.

    It's usually appropriate to set the command name (via
    SetProgramName()) before calling RunCommand().  RunCommand() sets
    the value returned by GetArgStr() while the command is running.

INPUTS
    seglist   - Seglist of command to run.
    stacksize - Number of bytes to allocate for stack space
    argptr    - Pointer to argument command string.
    argsize   - Number of bytes in argument command.

RESULT
    rc        - Return code from executed command. -1 indicates failure

SEE ALSO
    CreateNewProc(), SystemTagList(), Execute(), GetArgStr(),
    SetProgramName(), ReadArgs()


dos.library/SameDevice

NAME
    SameDevice -- Are two locks are on partitions of the device? (V37)

SYNOPSIS
    same = SameDevice(lock1, lock2)
    D0                 D1     D2

    BOOL SameDevice( BPTR, BPTR )

FUNCTION
    SameDevice() returns whether two locks refer to partitions that
    are on the same physical device (if it can figure it out).  This
    may be useful in writing copy routines to take advantage of
    asynchronous multi-device copies.

    Entry existed in V36 and always returned 0.

INPUTS
    lock1,lock2 - locks

RESULT
    same - whether they're on the same device as far as Dos can determine.


dos.library/SameLock

NAME
    SameLock -- returns whether two locks are on the same object (V36)

SYNOPSIS
    value = SameLock(lock1, lock2)
    D0                D1     D2

    LONG SameLock(BPTR, BPTR)

FUNCTION
    Compares two locks.  Returns LOCK_SAME if they are on the same object,
    LOCK_SAME_VOLUME if on different objects on the same volume, and
    LOCK_DIFFERENT if they are on different volumes.  Always compare
    for equality or non-equality with the results, in case new return
    values are added.

INPUTS
    lock1 - 1st lock for comparison
    lock2 - 2nd lock for comparison

RESULT
    value - LOCK_SAME, LOCK_SAME_VOLUME, or LOCK_DIFFERENT

BUGS
    Should do more extensive checks for NULL against a real lock, checking
    to see if the real lock is a lock on the root of the boot volume.

    In V36, it would return LOCK_SAME_VOLUME for different volumes on the
    same handler.  Also, LOCK_SAME_VOLUME was LOCK_SAME_HANDLER (now
    an obsolete define, see <dos/dos.h>).

SEE ALSO
    <dos/dos.h>


dos.library/Seek

NAME
    Seek -- Set the current position for reading and writing

SYNOPSIS
    oldPosition = Seek( file, position, mode )
    D0                  D1    D2        D3

    LONG Seek(BPTR, LONG, LONG)

FUNCTION
    Seek() sets the read/write cursor for the file 'file' to the
    position 'position'. This position is used by both Read() and
    Write() as a place to start reading or writing. The result is the
    current absolute position in the file, or -1 if an error occurs, in
    which case IoErr() can be used to find more information. 'mode' can
    be OFFSET_BEGINNING, OFFSET_CURRENT or OFFSET_END. It is used to
    specify the relative start position. For example, 20 from current
    is a position 20 bytes forward from current, -20 is 20 bytes back
    from current.

    So that to find out where you are, seek zero from current. The end
    of the file is a Seek() positioned by zero from end. You cannot
    Seek() beyond the end of a file.

INPUTS
    file - BCPL pointer to a file handle
    position - integer
    mode - integer

RESULTS
    oldPosition - integer

BUGS
    The V36 and V37 ROM filesystem (and V36/V37 l:fastfilesystem)
    returns the current position instead of -1 on an error.  It sets
    IoErr() to 0 on success, and an error code on an error.

SEE ALSO
    Read(), Write(), SetFileSize()


dos.library/SelectInput

NAME
    SelectInput -- Select a filehandle as the default input channel (V36)

SYNOPSIS
    old_fh = SelectInput(fh)
    D0                   D1

    BPTR SelectInput(BPTR)

FUNCTION
    Set the current input as the default input for the process.
    This changes the value returned by Input().  old_fh should
    be closed or saved as needed.

INPUTS
    fh     - Newly default input handle

RESULT
    old_fh - Previous default input filehandle

SEE ALSO
    Input(), SelectOutput(), Output()


dos.library/SelectOutput

NAME
    SelectOutput -- Select a filehandle as the default input channel (V36)

SYNOPSIS
    old_fh = SelectOutput(fh)
    D0                    D1

    BPTR SelectOutput(BPTR)

FUNCTION
    Set the current output as the default output for the process.
    This changes the value returned by Output().  old_fh should
    be closed or saved as needed.

INPUTS
    fh     - Newly desired output handle

RESULT
    old_fh - Previous current output

SEE ALSO
    Output(), SelectInput(), Input()


dos.library/SendPkt

NAME
    SendPkt -- Sends a packet to a handler (V36)

SYNOPSIS
    SendPkt(packet, port, replyport)
             D1     D2      D3

    void SendPkt(struct DosPacket *,struct MsgPort *,struct MsgPort *)

FUNCTION
    Sends a packet to a handler and does not wait.  All fields in the
    packet must be initialized before calling this routine.  The packet
    will be returned to replyport.  If you wish to use this with
    WaitPkt(), use the address or your pr_MsgPort for replyport.

INPUTS
    packet - packet to send, must be initialized and have a message.
    port   - pr_MsgPort of handler process to send to.
    replyport - MsgPort for the packet to come back to.

NOTES
    Callable from a task.

SEE ALSO
    DoPkt(), WaitPkt(), AllocDosObject(), FreeDosObject(), AbortPkt()


dos.library/SetArgStr

NAME
    SetArgStr -- Sets the arguments for the current process (V36)

SYNOPSIS
    oldptr = SetArgStr(ptr)
    D0                 D1

    STRPTR SetArgStr(STRPTR)

FUNCTION
    Sets the arguments for the current program.  The ptr MUST be reset
    to it's original value before process exit.

INPUTS
    ptr - pointer to new argument string.

RESULT
    oldptr - the previous argument string

SEE ALSO
    GetArgStr(), RunCommand()


dos.library/SetComment

NAME
    SetComment -- Change a files' comment string

SYNOPSIS
    success = SetComment( name, comment )
    D0                    D1    D2

    BOOL SetComment(STRPTR, STRPTR)

FUNCTION
    SetComment() sets a comment on a file or directory. The comment is
    a pointer to a null-terminated string of up to 80 characters in the
    current ROM filesystem (and RAM:).  Note that not all filesystems
    will support comments (for example, NFS usually will not), or the
    size of comment supported may vary.

INPUTS
    name    - pointer to a null-terminated string
    comment - pointer to a null-terminated string

RESULTS
    success - boolean

SEE ALSO
    Examine(), ExNext(), SetProtection()


dos.library/SetConsoleTask

NAME
    SetConsoleTask -- Sets the default console for the process (V36)

SYNOPSIS
    oldport = SetConsoleTask(port)
    D0                        D1

    struct MsgPort *SetConsoleTask(struct MsgPort *)

FUNCTION
    Sets the default console task's port (pr_ConsoleTask) for the
    current process.

INPUTS
    port - The pr_MsgPort of the default console handler for the process

RESULT
    oldport - The previous ConsoleTask value.

SEE ALSO
    GetConsoleTask(), Open()


dos.library/SetCurrentDirName

NAME
    SetCurrentDirName -- Sets the directory name for the process (V36)

SYNOPSIS
    success = SetCurrentDirName(name)
    D0                        D1

    BOOL SetCurrentDirName(STRPTR)

FUNCTION
    Sets the name for the current dir in the cli structure.  If the name
    is too long to fit, a failure is returned, and the old value is left
    intact.  It is advised that you inform the user of this condition.
    This routine is safe to call even if there is no CLI structure.

INPUTS
    name    - Name of directory to be set.

RESULT
    success - Success/failure indicator

BUGS
    This clips to a fixed (1.3 compatible) size.

SEE ALSO
    GetCurrentDirName()


dos.library/SetFileDate

NAME
    SetFileDate -- Sets the modification date for a file or dir (V36)

SYNOPSIS
    success = SetFileDate(name, date)
    D0                     D1    D2

    BOOL SetFileDate(STRPTR, struct DateStamp *)

FUNCTION
    Sets the file date for a file or directory.  Note that for the Old
    File System and the Fast File System, the date of the root directory
    cannot be set.  Other filesystems may not support setting the date
    for all files/directories.

INPUTS
    name - Name of object
    date - New modification date

RESULT
    success - Success/failure indication

SEE ALSO
    DateStamp(), Examine(), ExNext(), ExAll()


dos.library/SetFileSize

NAME
    SetFileSize -- Sets the size of a file (V36)

SYNOPSIS
    newsize = SetFileSize(fh, offset, mode)
    D0                    D1    D2     D3

    LONG SetFileSize(BPTR, LONG, LONG)

FUNCTION
    Changes the file size, truncating or extending as needed.  Not all
    handlers may support this; be careful and check the return code.  If
    the file is extended, no values should be assumed for the new bytes.
    If the new position would be before the filehandle's current position
    in the file, the filehandle will end with a position at the
    end-of-file.  If there are other filehandles open onto the file, the
    new size will not leave any filehandle pointing past the end-of-file.
    You can check for this by looking at the new size.

    Do NOT count on any specific values to be in the extended area.

INPUTS
    fh     - File to be truncated/extended.
    offset - Offset from position determined by mode.
    mode   - One of OFFSET_BEGINNING, OFFSET_CURRENT, or OFFSET_END.

RESULT
    newsize - position of new end-of-file or -1 for error.

SEE ALSO
    Seek()


dos.library/SetFileSysTask

NAME
    SetFileSysTask -- Sets the default filesystem for the process (V36)

SYNOPSIS
    oldport = SetFileSysTask(port)
    D0                        D1

    struct MsgPort *SetFileSysTask(struct MsgPort *)

FUNCTION
    Sets the default filesystem task's port (pr_FileSystemTask) for the
    current process.

INPUTS
    port - The pr_MsgPort of the default filesystem for the process

RESULT
    oldport - The previous FileSysTask value

SEE ALSO
    GetFileSysTask(), Open()


dos.library/SetIoErr

NAME
    SetIoErr -- Sets the value returned by IoErr() (V36)

SYNOPSIS
    oldcode = SetIoErr(code)
    D0                  D1

    LONG SetIoErr(LONG);

FUNCTION
    This routine sets up the secondary result (pr_Result2) return code
    (returned by the IoErr() function).

INPUTS
    code - Code to be returned by a call to IoErr.

RESULT
    oldcode - The previous error code.

SEE ALSO
    IoErr(), Fault(), PrintFault()


dos.library/SetMode

NAME
    SetMode - Set the current behavior of a handler (V36)

SYNOPSIS
    success = SetMode(fh, mode)
    D0                D1  D2

    BOOL SetMode(BPTR, LONG)

FUNCTION
    SetMode() sends an ACTION_SCREEN_MODE packet to the handler in
    question, normally for changing a CON: handler to raw mode or
    vice-versa.  For CON:, use 1 to go to RAW: mode, 0 for CON: mode.

INPUTS
    fh   - filehandle
    mode - The new mode you want

RESULT
    success - Boolean

SEE ALSO


dos.library/SetProgramDir

NAME
    SetProgramDir -- Sets the directory returned by GetProgramDir (V36)

SYNOPSIS
    oldlock = SetProgramDir(lock)
    D0                       D1

    BPTR SetProgramDir(BPTR)

FUNCTION
    Sets a shared lock on the directory the program was loaded from.
    This can be used for a program to find data files, etc, that are
    stored with the program, or to find the program file itself.  NULL
    is a valid input.  This can be accessed via GetProgramDir() or
    by using paths relative to PROGDIR:.

INPUTS
    lock - A lock on the directory the current program was loaded from

RESULT
    oldlock - The previous ProgramDir.

SEE ALSO
    GetProgramDir(), Open()


dos.library/SetProgramName

NAME
    SetProgramName -- Sets the name of the program being run (V36)

SYNOPSIS
    success = SetProgramName(name)
    D0                        D1

    BOOL SetProgramName(STRPTR)

FUNCTION
    Sets the name for the program in the cli structure.  If the name is
    too long to fit, a failure is returned, and the old value is left
    intact.  It is advised that you inform the user if possible of this
    condition, and/or set the program name to an empty string.
    This routine is safe to call even if there is no CLI structure.

INPUTS
    name    - Name of program to use.

RESULT
    success - Success/failure indicator.

BUGS
    This clips to a fixed (1.3 compatible) size.

SEE ALSO
    GetProgramName()


dos.library/SetPrompt

NAME
    SetPrompt -- Sets the CLI/shell prompt for the current process (V36)

SYNOPSIS
    success = SetPrompt(name)
    D0                D1

    BOOL SetPrompt(STRPTR)

FUNCTION
    Sets the text for the prompt in the cli structure.  If the prompt is
    too long to fit, a failure is returned, and the old value is left
    intact.  It is advised that you inform the user of this condition.
    This routine is safe to call even if there is no CLI structure.

INPUTS
    name    - Name of prompt to be set.

RESULT
    success - Success/failure indicator.

BUGS
    This clips to a fixed (1.3 compatible) size.

SEE ALSO
    GetPrompt()


dos.library/SetProtection

NAME
    SetProtection -- Set protection for a file or directory

SYNOPSIS
    success = SetProtection( name, mask )
    D0                       D1    D2:4

    BOOL SetProtection (STRPTR, LONG)

FUNCTION
    SetProtection() sets the protection attributes on a file or
    directory. The lower bits of the mask are as follows:

    bit 4: 1 = file has not changed         0 = file has been changed
    bit 3: 1 = reads not allowed,           0 = reads allowed.
    bit 2: 1 = writes not allowed,          0 = writes allowed.
    bit 1: 1 = execution not allowed,       0 = execution allowed.
    bit 0: 1 = deletion not allowed,        0 = deletion allowed.

    Before V36, the ROM filesystem didn't respect the Read and Write
    bits.  In V36 or later and in the FFS, the Read and Write
    bits are respected.

    The archive bit should be cleared by the filesystem whenever the file
    is changed.  Backup utilities will generally set the bit after
    backing up each file.

    The V36 Shell looks at the execute bit, and will refuse to execute
    a file if it is set.

    Other bits will be defined in the <dos/dos.h> include files.  Rather
    than referring to bits by number you should use the definitions in
    <dos/dos.h>.

INPUTS
    name - pointer to a null-terminated string
    mask - the protection mask required

RESULTS
    success - boolean

SEE ALSO
    SetComment(), Examine(), ExNext(), <dos/dos.h>


dos.library/SetVar

NAME
    SetVar -- Sets a local or environment variable (V36)

SYNOPSIS
    success = SetVar( name, buffer, size, flags )
    D0                 D1     D2     D3    D4

    BOOL SetVar(STRPTR, STRPTR, LONG, ULONG )

FUNCTION
    Sets a local or environment variable.  It is advised to only use
    ASCII strings inside variables, but not required.

INPUTS
    name   - pointer to an variable name.  Note variable names follow
             filesystem syntax and semantics.
    buffer - a user allocated area which contains a string that is the
             value to be associated with this variable.
    size   - length of the buffer region in bytes.  -1 means buffer
             contains a null-terminated string.
    flags  - combination of type of var to set (low 8 bits), and
             flags to control the behavior of this routine.  Currently
             defined flags include:

            GVF_LOCAL_ONLY - set a local (to your process) variable.
            GVF_GLOBAL_ONLY - set a global environment variable.

            The default is to set a local environment variable.

RESULT
    success - If non-zero, the variable was sucessfully set, FALSE
              indicates failure.

BUGS
    LV_VAR is the only type that can be global

SEE ALSO
    GetVar(), DeleteVar(), FindVar(), <dos/var.h>


dos.library/SetVBuf

NAME
    SetVBuf -- set buffering modes and size (V36)

SYNOPSIS
    error = SetVBuf(fh, buff, type, size)
    D0              D1   D2    D3    D4

    LONG SetVBuf(BPTR, STRPTR, LONG, LONG)

FUNCTION
    Changes the buffering modes and buffer size for a filehandle.
    With buff == NULL, the current buffer will be deallocated and a
    new one of (approximately) size will be allocated.  If buffer is
    non-NULL, it will be used for buffering and must be at least
    max(size,208) bytes long.  If buff is NULL and size is -1,
    then only the buffering mode will be changed.

INPUTS
    fh   - Filehandle
    buff - buffer pointer for buffered I/O
    type - buffering mode (see <dos/stdio.h>)
    size - size of buffer for buffered I/O (sizes less than 208 bytes
           will be ignored).

RESULT
    error - 0 if successful.  NOTE: opposite of most dos functions!

BUGS
    Not implemented yet, always returns 0.

SEE ALSO
    FputC(), FGetC(), UnGetC(), Flush(), FRead(), FWrite(), FGets(),
    FPuts().


dos.library/SplitName

NAME
    SplitName -- splits out a component of a pathname into a buffer (V36)

SYNOPSIS
    newpos = SplitName(name, separator, buf, oldpos, size)
    D0                  D1      D2      D3     D4     D5

    WORD SplitName(STRPTR, UBYTE, STRPTR, WORD, LONG)

FUNCTION
    This routine splits out the next piece of a name from a given file
    name.  Each piece is copied into the buffer, truncating at size-1
    characters.  The new position is then returned so that it may be
    passed in to the next call to splitname.  If the separator is not
    found within 'size' characters, then size-1 characters plus a null will
    be put into the buffer, and the position of the next separator will
    be returned.

    If a a separator cannot be found, -1 is returned (but the characters
    from the old position to the end of the string are copied into the
    buffer, up to a maximum of size-1 characters).  Both strings are
    null-terminated.

    This function is mainly intended to support handlers.

INPUTS
    name      - Filename being parsed.
    separator - Separator charactor to split by.
    buf       - Buffer to hold separated name.
    oldpos    - Current position in the file.
    size      - Size of buf in bytes (including null termination);

RESULT
    newpos    - New position for next call to splitname.  -1 for last one.

SEE ALSO
    FilePart(), PathPart(), AddPart()


dos.library/StartNotify

NAME
    StartNotify -- Starts notification on a file or directory (V36)

SYNOPSIS
    success = StartNotify(notifystructure)
    D0                          D1

    BOOL StartNotify(struct NotifyRequest *)

FUNCTION
    Posts a notification request.  Do not modify the notify structure while
    it is active.  You will be notified when the file or directory changes.
    For files, you will be notified after the file is closed.  Not all
    filesystems will support this: applications should NOT require it.  In
    particular, most network filesystems won't support it.

INPUTS
    notifystructure - A filled-in NotifyRequest structure

RESULT
    success - Success/failure of request

BUGS
    The V36 floppy/HD filesystem doesn't actually send notifications.  The
    V36 ram handler (ram:) does.  This has been fixed for V37.

SEE ALSO
    EndNotify(), <dos/notify.h>


dos.library/StrToDate

NAME
    StrToDate -- Converts a string to a DateStamp (V36)

SYNOPSIS
    success = StrToDate( datetime )
    D0                      D1

    BOOL StrToDate( struct DateTime * )

FUNCTION
    Converts a human readable ASCII string into an AmigaDOS
    DateStamp.

INPUTS
    DateTime - a pointer to an initialized DateTime structure.

    The DateTime structure should   be initialized as follows:

    dat_Stamp  - ignored on input.

    dat_Format - a format   byte which specifies the format of the
            dat_StrDat.  This can   be any of the following (note:
            If value used   is something other than those below,
            the default of FORMAT_DOS is used):

            FORMAT_DOS:       AmigaDOS format (dd-mmm-yy).

            FORMAT_INT:       International format (yy-mmm-dd).

            FORMAT_USA:       American format (mm-dd-yy).

            FORMAT_CDN:       Canadian format (dd-mm-yy).

            FORMAT_DEF:       default format for locale.

    dat_Flags - a flags byte.  The only flag which affects this
              function is:

            DTF_SUBST:      ignored by this function
            DTF_FUTURE:       If set, indicates that strings such
                              as (stored in dat_StrDate) "Monday"
                              refer to "next" monday. Otherwise,
                              if clear, strings like "Monday"
                              refer to "last" monday.

    dat_StrDay - ignored bythis function.

    dat_StrDate -   pointer to valid string representing the date.
              This can be a "DTF_SUBST" style string such as
              "Today" "Tomorrow" "Monday", or it may be a string
              as specified by the dat_Format byte.  This will be
              converted to the ds_Days portion of the DateStamp.
              If this pointer is NULL, DateStamp->ds_Days will not
              be affected.

    dat_StrTime -   Pointer to a buffer which contains the time in
              the ASCII format hh:mm:ss.  This will be converted
              to the ds_Minutes and ds_Ticks portions of the
              DateStamp.  If this pointer is NULL, ds_Minutes and
              ds_Ticks will be unchanged.

RESULT
    success - a zero return indicates that a conversion could
            not be performed. A non-zero return indicates that the
            DateTime.dat_Stamp variable contains the converted
            values.

SEE ALSO
    DateStamp(), DateToStr(), <dos/datetime.h>


dos.library/StrToLong

NAME
    StrToLong -- string to long value (decimal) (V36)

SYNOPSIS
    characters = StrToLong(string,value)
    D0                       D1    D2

    LONG StrToLong(STRPTR, LONG *)

FUNCTION
    Converts decimal string into LONG value.  Returns number of characters
    converted.  Skips over leading spaces & tabs (included in count).  If
    no decimal digits are found (after skipping leading spaces & tabs),
    StrToLong returns -1 for characters converted, and puts 0 into value.

INPUTS
    string - Input string.
    value  - Pointer to long value.  Set to 0 if no digits are converted.

RESULT
    result - Number of characters converted or -1.


dos.library/SystemTagList

NAME
    SystemTagList -- Have a shell execute a command line (V36)

SYNOPSIS
    error = SystemTagList(command, tags)
    D0                      D1      D2

    LONG SystemTagList(STRPTR, struct TagItem *)

    error = System(command, tags)
    D0               D1      D2

    LONG System(STRPTR, struct TagItem *)

    error = SystemTags(command, Tag1, ...)

    LONG SystemTags(STRPTR, ULONG, ...)

FUNCTION
    Similar to Execute(), but does not read commands from the input
    filehandle.  Spawns a Shell process to execute the command, and
    returns the returncode the command produced, or -1 if the command
    could not be run for any reason.  The input and output filehandles
    will not be closed by System, you must close them (if needed) after
    System returns, if you specified them via SYS_INPUT or SYS_OUTPUT.

    By default the new process will use your current Input() and Output()
    filehandles.  Normal Shell command-line parsing will be done
    including redirection on 'command'.  The current directory and path
    will be inherited from your process.  Your path will be used to find
    the command (if no path is specified).

    If used with the SYS_Asynch flag, it WILL close both it's input and
    output filehandles after running the command (even if these were
    your Input() and Output()!)

    Normally uses the boot (ROM) shell, but other shells can be specified
    via SYS_UserShell and SYS_CustomShell.  Normally, you should send
    things written by the user to the UserShell.  The UserShell defaults
    to the same shell as the boot shell.

    The tags are passed through to CreateNewProc() (tags that conflict
    with SystemTagList() will be filtered out).  This allows setting
    things like priority, etc for the new process.

INPUTS
    command - Program and arguments
    tags    - see <dos/dostags.h>.  Note that both SystemTagList()-
              specific tags and tags from CreateNewProc() may be passed.

RESULT
    error   - 0 for success, result from command, or -1.  Note that on
              error, the caller is responsible for any filehandles or other
              things passed in via tags.

SEE ALSO
    Execute(), CreateNewProc(), <dos/dostags.h>, Input(), Output()


dos.library/UnGetC

NAME
    UnGetC -- Makes a char available for reading again. (buffered) (V36)

SYNOPSIS
    value = UnGetC(fh, character)
    D0             D1      D2

    LONG UnGetC(BPTR, LONG)

FUNCTION
    Pushes the character specified back into the input buffer.  Every
    time you use a buffered read routine, you can always push back 1
    character.  You may be able to push back more, though it is not
    recommended, since there is no guarantee on how many can be
    pushed back at a given moment.

    Passing -1 for the character will cause the last character read to
    be pushed back.  If the last character read was an EOF, the next
    character read will be an EOF.

    Note: UnGetC can be used to make sure that a filehandle is set up
    as a read filehandle.  This is only of importance if you are writing
    a shell, and must manipulate the filehandle's buffer.

INPUTS
    fh        - filehandle to use for buffered I/O
    character - character to push back or -1

RESULT
    value     - character pushed back, or FALSE if the character cannot
                be pushed back.

BUGS
    In V36, UnGetC(fh,-1) after an EOF would not cause the next character
    read to be an EOF.  This was fixed for V37.

SEE ALSO
    FGetC(), FPutC(), Flush()


dos.library/UnLoadSeg

NAME
    UnLoadSeg -- Unload a seglist previously loaded by LoadSeg()

SYNOPSIS
    success = UnLoadSeg( seglist )
    D0                     D1

    BOOL UnLoadSeg(BPTR)

FUNCTION
    Unload a seglist loaded by LoadSeg().  'seglist' may be zero.
    Overlaid segments will have all needed cleanup done, including
    closing files.

INPUTS
    seglist - BCPL pointer to a segment identifier

RESULTS
    success - returns 0 if a NULL seglist was passed or if it failed
              to close an overlay file.  NOTE: this function returned
              a random value before V36!

SEE ALSO
    LoadSeg(), InternalLoadSeg(), InternalUnLoadSeg()


dos.library/UnLock

NAME
    UnLock -- Unlock a directory or file

SYNOPSIS
    UnLock( lock )
            D1

    void UnLock(BPTR)

FUNCTION
    The filing system lock (obtained from Lock(), DupLock(), or
    CreateDir()) is removed and deallocated.

INPUTS
    lock - BCPL pointer to a lock

NOTE
    passing zero to UnLock() is harmless

SEE ALSO
    Lock(), DupLock(), ParentOfFH(), DupLockFromFH()


dos.library/UnLockDosList

NAME
    UnLockDosList -- Unlocks the Dos List (V36)

SYNOPSIS
    UnLockDosList(flags)
                    D1

    void UnLockDosList(ULONG)

FUNCTION
    Unlocks the access on the Dos Device List.  You MUST pass the same
    flags you used to lock the list.

INPUTS
    flags - MUST be the same flags passed to (Attempt)LockDosList()

SEE ALSO
    AttemptLockDosList(), LockDosList(), Permit()


dos.library/UnLockRecord

NAME
    UnLockRecord -- Unlock a record (V36)

SYNOPSIS
    success = UnLockRecord(fh,offset,length)
    D0                     D1   D2     D3

    BOOL UnLockRecord(BPTR,ULONG,ULONG)

FUNCTION
    This releases the specified lock on a file.  Note that you must use
    the same filehandle you used to lock the record, and offset and length
    must be the same values used to lock it.  Every LockRecord() call must
    be balanced with an UnLockRecord() call.

INPUTS
    fh      - File handle of locked file
    offset  - Record start position
    length  - Length of record in bytes

RESULT
    success - Success or failure.

BUGS
    See LockRecord()

SEE ALSO
    LockRecords(), LockRecord(), UnLockRecords()


dos.library/UnLockRecords

NAME
    UnLockRecords -- Unlock a list of records (V36)

SYNOPSIS
    success = UnLockRecords(record_array)
    D0                           D1

    BOOL UnLockRecords(struct RecordLock *)

FUNCTION
    This releases an array of record locks obtained using LockRecords.
    You should NOT modify the record_array while you have the records
    locked.  Every LockRecords() call must be balanced with an
    UnLockRecords() call.

INPUTS
    record_array - List of records to be unlocked

RESULT
    success      - Success or failure.

BUGS
    See LockRecord()

SEE ALSO
    LockRecords(), LockRecord(), UnLockRecord()


dos.library/VFPrintf

NAME
    VFPrintf -- format and print a string to a file (buffered) (V36)

SYNOPSIS
    count = VFPrintf(fh, fmt, argv)
    D0               D1  D2    D3

    LONG VFPrintf(BPTR, STRPTR, LONG *)

    count = FPrintf(fh, fmt, ...)

    LONG FPrintf(BPTR, STRPTR, ...)

FUNCTION
    Writes the formatted string and values to the given file.  This
    routine is assumed to handle all internal buffering so that the
    formatting string and resultant formatted values can be arbitrarily
    long.  Any secondary error code is returned in IoErr().  This routine
    is buffered.

INPUTS
    fh    - Filehandle to write to
    fmt   - RawDoFmt() style formatting string
    argv  - Pointer to array of formatting values

RESULT
    count - Number of bytes written or -1 (EOF) for an error

BUGS
    The prototype for FPrintf() currently forces you to cast the first
    varargs parameter to LONG due to a deficiency in the program
    that generates fds, prototypes, and amiga.lib stubs.

SEE ALSO
    VPrintf(), VFWritef(), RawDoFmt(), FPutC()


dos.library/VFWritef

NAME
    VFWritef - write a BCPL formatted string to a file (buffered) (V36)

SYNOPSIS
    count = VFWritef(fh, fmt, argv)
    D0               D1  D2    D3

    LONG VFWritef(BPTR, STRPTR, LONG *)

    count = FWritef(fh, fmt, ...)

    LONG FWritef(BPTR, STRPTR, ...)

FUNCTION
    Writes the formatted string and values to the default output.  This
    routine is assumed to handle all internal buffering so that the
    formatting string and resultant formatted values can be arbitrarily
    long.  The formats are in BCPL form.  This routine is buffered.

    Supported formats are:  (Note x is in base 36!)
            %S  - string (CSTR)
            %Tx - writes a left-justified string in a field at least
                  x bytes long.
            %C  - writes a single character
            %Ox - writes a number in octal, maximum x characters wide
            %Xx - writes a number in hex, maximum x characters wide
            %Ix - writes a number in decimal, maximum x characters wide
            %N  - writes a number in decimal, any length
            %Ux - writes an unsigned number, maximum x characters wide
            %$  - ignore parameter

    Note: 'x' above is actually the character value - '0'.

INPUTS
    fmt   - BCPL style formatting string
    argv  - Pointer to array of formatting values

RESULT
    count - Number of bytes written or -1 for error

BUGS
    As of V37, VFWritef() does NOT return a valid return value.  In
    order to reduce possible errors, the prototypes supplied for the
    system as of V37 have it typed as VOID.

SEE ALSO
    VFPrintf(), VFPrintf(), FPutC()


dos.library/VPrintf

NAME
    VPrintf -- format and print string (buffered) (V36)

SYNOPSIS
    count = VPrintf(fmt, argv)
      D0            D1   D2

    LONG VPrintf(STRPTR, LONG *)

    count = Printf(fmt, ...)

    LONG Printf(STRPTR, ...)

FUNCTION
    Writes the formatted string and values to Output().  This routine is
    assumed to handle all internal buffering so that the formatting string
    and resultant formatted values can be arbitrarily long.  Any secondary
    error code is returned in IoErr().  This routine is buffered.

    Note: RawDoFmt assumes 16 bit ints, so you will usually need 'l's in
    your formats (ex: %ld versus %d).

INPUTS
    fmt   - exec.library RawDoFmt() style formatting string
    argv  - Pointer to array of formatting values

RESULT
    count - Number of bytes written or -1 (EOF) for an error

BUGS
    The prototype for Printf() currently forces you to cast the first
    varargs parameter to LONG due to a deficiency in the program
    that generates fds, prototypes, and amiga.lib stubs.

SEE ALSO
    VFPrintf(), VFWritef(), RawDoFmt(), FPutC()


dos.library/WaitForChar

NAME
    WaitForChar -- Determine if chars arrive within a time limit

SYNOPSIS
    status = WaitForChar( file, timeout )
    D0                    D1    D2

    BOOL WaitForChar(BPTR, LONG)

FUNCTION
    If a character is available to be read from 'file' within a the
    time (in microseconds) indicated by 'timeout', WaitForChar()
    returns -1 (TRUE). If a character is available, you can use Read()
    to read it.  Note that WaitForChar() is only valid when the I/O
    stream is connected to a virtual terminal device. If a character is
    not available within 'timeout', a 0 (FALSE) is returned.

BUGS
    Due to a bug in the timer.device in V1.2/V1.3, specifying a timeout
    of zero for WaitForChar() can cause the unreliable timer & floppy
    disk operation.

INPUTS
    file - BCPL pointer to a file handle
    timeout - integer

RESULTS
    status - boolean

SEE ALSO
    Read(), FGetC()


dos.library/WaitPkt

NAME
    WaitPkt -- Waits for a packet to arrive at your pr_MsgPort (V36)

SYNOPSIS
    packet = WaitPkt()
    D0

    struct DosPacket *WaitPkt(void);

FUNCTION
    Waits for a packet to arrive at your pr_MsgPort.  If anyone has
    installed a packet wait function in pr_PktWait, it will be called.
    The message will be automatically GetMsg()ed so that it is no longer
    on the port.  It assumes the message is a dos packet.  It is NOT
    guaranteed to clear the signal for the port.

RESULT
    packet - the packet that arrived at the port (from ln_Name of message).

SEE ALSO
    SendPkt(), DoPkt(), AbortPkt()


dos.library/Write

NAME
    Write -- Write bytes of data to a file

SYNOPSIS
    returnedLength =  Write( file, buffer, length )
    D0                       D1    D2      D3

    LONG Write (BPTR, void *, LONG)

FUNCTION
    Write() writes bytes of data to the opened file 'file'. 'length'
    indicates the length of data to be transferred; 'buffer' is a
    pointer to the buffer. The value returned is the length of
    information actually written. So, when 'length' is greater than
    zero, the value of 'length' is the number of characters written.
    Errors are indicated by a value of -1.

    Note: this is an unbuffered routine (the request is passed directly
    to the filesystem.)  Buffered I/O is more efficient for small
    reads and writes; see FPutC().

INPUTS
    file - BCPL pointer to a file handle
    buffer - pointer to the buffer
    length - integer

RESULTS
    returnedLength - integer

SEE ALSO
    Read(), Seek(), Open(), Close(), FPutC


dos.library/WriteChars

NAME
    WriteChars -- Writes bytes to the the default output (buffered) (V36)

SYNOPSIS
    count = WriteChars(buf, buflen)
    D0                 D1

    LONG WriteChars(STRPTR, LONG)

FUNCTION
    This routine writes a number of bytes to the default output.  The
    length is returned.  This routine is buffered.

INPUTS
    buf    - buffer of characters to write
    buflen - number of characters to write

RESULT
    count - Number of bytes written.  -1 (EOF) indicates an error

SEE ALSO
    FPuts(), FPutC(), FWrite(), PutStr()


keymap.doc

 AskKeyMapDefault()      MapRawKey()
 MapANSI()               SetKeyMapDefault()


keymap.library/AskKeyMapDefault

NAME
    AskKeyMapDefault -- Ask for a pointer to the current default
                        keymap. (V36)

SYNOPSIS
    keyMap = AskKeyMapDefault()

    struct KeyMap *AskKeyMapDefault( VOID );

FUNCTION
    Return a pointer to the keymap used by the keymap library for
    MapRawKey and MapANSI when a keymap is not specified.

RESULTS
    keyMap - a pointer to a keyMap structure.  This key map is
        guaranteed to be permanently allocated: it will remain in
        memory till the machine is reset.

BUGS
    The keymap.h include file should be in the libraries/ or perhaps
    resources/ directory, but is in the devices/ directory for
    compatability reasons.

SEE ALSO
    devices/keymap.h, keymap.library/SetKeyMapDefault(),
    console.device ...KEYMAP functions


keymap.library/MapANSI

NAME
    MapANSI -- Encode an ANSI string into keycodes. (V36)

SYNOPSIS
    actual = MapANSI( string, count, buffer, length, keyMap )
    D0                A0      D0     A1      D1      A2

    LONG MapANSI( STRPTR, LONG, STRPTR, LONG, struct KeyMap * );

FUNCTION
    This console function converts an ANSI byte string to the
    code/qualifier pairs of type IECLASS_RAWKEY that would
    generate the string and places those pairs in a buffer.
    A code/qualifier pair is a pair of bytes suitable for
    putting in the ie_Code and low byte of ie_Qualifier,
    and for subsequent events, shifted to the ie_Prev1DownCode/
    ie_Prev1DownQual then ie_Prev2DownCode/ie_Prev2DownQual
    pairs for any dead or double dead key mapping.

INPUTS
    string - the ANSI string to convert.
    count - the number of characters in the string.
    buffer - a byte buffer large enough to hold all anticipated
        code/qualifier pairs generated by this conversion.
    length - maximum anticipation, i.e. the buffer size in bytes
        divided by two (the size of the code/qualifier pair).
    keyMap - a KeyMap structure pointer, or null if the default
        key map is to be used.

RESULT
    actual - the number of code/qualifier pairs in the buffer,
        or negative to describe an error (see below).

EXAMPLE
    ...
    #include <devices/inputevent.h>

    #define STIMSIZE        3       /* two dead keys, one key */
    unsigned char rBuffer[STIMSIZE*2];
    ...
        KeymapBase = (struct Library *) OpenLibrary("keymap.library", 0);
        ...
        event.ie_NextEvent = 0;
        event.ie_Class = IECLASS_RAWKEY;
        event.ie_SubClass = 0;

        /* prove keymap code completeness and MapANSI reversibility */
        for (code = 0; code < 256; code++) {
            buffer[0] = code;
            actual = MapANSI(buffer, 1, rBuffer, STIMSIZE, 0);
            r = rBuffer;
            event.ie_Prev2DownCode = 0;
            event.ie_Prev2DownQual = 0;
            event.ie_Prev1DownCode = 0;
            event.ie_Prev1DownQual = 0;
            switch (actual) {
                case -2:
                    printf("MapANSI internal error");
                    goto reportChar;
                case -1:
                    printf("MapANSI overflow error");
                    goto reportChar;
                case 0:
                    printf("MapANSI ungeneratable code");
                    goto reportChar;

                case 3:
                    event.ie_Prev2DownCode = *r++;
                    event.ie_Prev2DownQual = *r++;
                case 2:
                    event.ie_Prev1DownCode = *r++;
                    event.ie_Prev1DownQual = *r++;
                case 1:
                    event.ie_Code = *r++;
                    event.ie_Qualifier = *r;

                    actual = MapRawKey(&event, buffer, BUFFERLEN, 0);
                    if ((actual != 1) || (buffer[0] != code)) {
                        printf("MapANSI not reversible");
                        for (i = 0; i < actual; i++)
                            ReportChar(buffer[i]);
                        printf(" from");
    reportChar:
                        ReportChar(code);
                        printf("n");
                    }
            }
        }
    ...

ERRORS
    if actual is 0, a character in the string was not generatable
        from the keyMap.
    if actual is -1, a buffer overflow condition was detected.
    if actual is -2, an internal error occurred (e.g. no memory)

SEE ALSO
    devices/inputevent.h, devices/keymap.h


keymap.library/MapRawKey

NAME
    MapRawKey -- Decode single raw key input event to an ANSI
                 string. (V36)

SYNOPSIS
    actual = MapRawKey(event, buffer, length, keyMap)
    D0                 A0     A1      D1      A2

    WORD MapRawKey( struct InputEvent *, STRPTR, WORD,
        struct Keymap * );

FUNCTION
    This console function converts input events of type
    IECLASS_RAWKEY to ANSI bytes, based on the keyMap, and
    places the result into the buffer.

INPUTS
    event -  an InputEvent structure pointer.  The event list is
        not traversed.
    buffer - a byte buffer large enough to hold all anticipated
        characters generated by this conversion.
    length - maximum anticipation, i.e. the buffer size in bytes.
    keyMap - a KeyMap structure pointer, or null if the default
        key map is to be used.

RESULT
    actual - the number of characters in the buffer, or -1 if
        a buffer overflow was about to occur.

EXAMPLE
    ...
    #define BUFFERLEN       80    /* length of longest expected mapping /*
    char buffer[BUFFERLEN];
    struct InputEvent ie;
    ...
        KeymapBase = OpenLibrary("keymap.library", 0);
        ...
        ie.ie_Class = IECLASS_RAWKEY;
        ie.ie_SubClass = 0;
        for (;;) {
            WaitPort(window->UserPort);
            while (im = (struct IntuiMessage *) GetMsg(window->UserPort)) {
                switch (im->Class) {
                    case RAWKEY:
                        ie.ie_Code = im->Code;
                        ie.ie_Qualifier = im->Qualifier;
                        /* recover dead key codes & qualifiers */
                        ie.ie_EventAddress = (APTR *) *im->IAddress;
                        actual = MapRawKey(&ie, buffer, BUFFERLEN, 0);
                        for (i = 0; i < actual; i++)
                            ReportChar(buffer[i]);
                        break;
                    ...
                }
                ...
            }
        }

ERRORS
    if actual is -1, a buffer overflow condition was detected.
    Not all of the characters in the buffer are valid.

SEE ALSO
    devices/inputevent.h, devices/keymap.h


keymap.library/SetKeyMapDefault

NAME
    SetKeyMapDefault -- Set the current default keymap. (V36)

SYNOPSIS
    SetKeyMapDefault(keyMap)

    void SetKeyMapDefault( struct KeyMap * );

FUNCTION
    A pointer to key map specified is cached by the keymap library
    for use by MapRawKey and MapANSI when a keymap is not specified.

INPUTS
    keyMap - a pointer to a keyMap structure.  This key map must be
        permanently allocated: it must remain in memory till the
        machine is reset.  It is appropriate that this keyMap be a
        node on the keymap.resource list.

BUGS
    The keymap.h include file should be in the libraries/ or perhaps
    resources/ directory, but is in the devices/ directory for
    compatability reasons.

SEE ALSO
    devices/keymap.h, keymap.library/AskKeyMapDefault(),
    console.device ...KEYMAP functions


rexxsyslib.doc

 ClearRexxMsg()         DeleteRexxMsg()        LockRexxBase()
 CreateArgstring()      FillRexxMsg()          UnlockRexxBase()
 CreateRexxMsg()        IsRexxMsg()
 DeleteArgstring()      LengthArgstring()


rexxsyslib.library/ClearRexxMsg

NAME
    ClearRexxMsg - Releases and clears the argument array in a RexxMsg

SYNOPSIS
    ClearRexxMsg(msgptr, count)
                 A0      D0

    VOID ClearRexxMsg(struct RexxMsg *,ULONG);

FUNCTION
    This function will DeleteArgstring() one or more argstrings from
    the RexxMsg and clear the slot.  The count is used to select the
    number of slots to clear.

INPUTS
    msgptr - A pointer to a RexxMsg
    count - The number of slots to be cleared.  The number can be from
            1 to 16.  (There are 16 slots)

RESULTS
    All of the slots in the given count will be cleared and the argstring
    will have been released.

SEE ALSO
    FillRexxMsg(), DeleteRexxMsg(), DeleteArgstring(), CreateArgstring()

BUGS


rexxsyslib.library/CreateArgstring

NAME
    CreateArgstring - Create an argument string structure

SYNOPSIS
    argstr = CreateArgstring(string, length)
    D0,A0                    A0      D0

    UBYTE *CreateArgstring(UBYTE *, ULONG);

FUNCTION
    Allocates a RexxArg structure and copies the supplied string into it.
    The returned pointer points at the string part of the structure
    and can be treated like an ordinary string pointer.  (However, care
    must be taken that you do not change the string)

INPUTS
    string - A pointer at your input string
    length - The number of bytes of your input string you wish copied.
             (NOTE:  You are limited to 65,535 byte strings)

RESULTS
    argstr - A pointer to the argument string.  The results are returned
             in both A0 and D0.  You should always check the result
             as an allocation failure would cause an error.

SEE ALSO
    DeleteArgstring(), LengthArgstring(), ClearRexxMsg(), FillRexxMsg()

BUGS


rexxsyslib.library/CreateRexxMsg

NAME
    CreateRexxMsg - Create an ARexx message structure

SYNOPSIS
    rexxmsg = CreateRexxMsg(port, extension, host)
    D0,A0                   A0    A1         D0

    struct RexxMsg *CreateRexxMsg(struct MsgPort *, UBYTE *, UBYTE *);

FUNCTION
    This functions allocates an ARexx message packet.  The RexxMsg
    consists of a standard EXEC message structure extended to include
    the ARexx specific information.

INPUTS
    port - A pointer to a public or private message port.  This *MUST*
           be a valid port as this is where the message will be replied.

    extension - A pointer to a NULL terminated string that is to be used
                as the default extension for the REXX scripts.  If this
                is NULL, the default is "REXX"

    host - A pointer to a NULL terminated string that is to be used
           as the default host port.  The name must be the same as the
           name of the public message port that is to be the default host.
           If this field is NULL, the default is REXX.

RESULTS
    rexxmsg - A RexxMsg structure

NOTES
    The extension and host strings must remain valid for as long as the
    RexxMsg exists as only the pointer to those strings are stored.

SEE ALSO
    DeleteRexxMsg(), ClearRexxMsg(), FillRexxMsg()

BUGS


rexxsyslib.library/DeleteArgstring

NAME
    DeleteArgstring - Releases an Argstring created by CreateArgstring()

SYNOPSIS
    DeleteArgstring(argstring)
                    A0

    VOID DeleteArgstring(UBYTE *);

FUNCTION
    Releases an argstring.  The argstring must have been created by ARexx

INPUTS
    argstring - A pointer to the string buffer of an argstring.

RESULTS

SEE ALSO
    CreateArgstring(), ClearRexxMsg(), FillRexxMsg()

BUGS


rexxsyslib.library/DeleteRexxMsg

NAME
    DeleteRexxMsg - Releases a RexxMsg structure created by CreateRexxMsg()

SYNOPSIS
    DeleteRexxMsg(packet)
                  A0

    VOID DeleteRexxMsg(struct RexxMsg *);

FUNCTION
    The function releases an ARexx message packet that was allocated
    with CreateRexxMsg().  Any argument fields in the RexxMsg structure
    should be cleared before calling this function as it does
    not release them for you.

INPUTS
    packet - A pointer to a RexxMsg structure allocated by CreateRexxMsg()

EXAMPLE
    if (rmsg=CreateRexxMsg(myport,"myapp","MYAPP_PORT"))
    {
            /* Do my think with rmsg */
            ClearRexxMsg(rmsg,16);  /* We may not want to clear all 16 */
            DeleteRexxMsg(rmsg);
    }

SEE ALSO
    CreateRexxMsg(), ClearRexxMsg()

BUGS


rexxsyslib.library/FillRexxMsg

NAME
    FillRexxMsg - Fill the argument strings as needed

SYNOPSIS
    result = FillRexxMsg(msgptr, count, mask)
    D0                   A0      D0     D1 [0:15]

    BOOL FillRexxMsg(struct RexxMsg *,ULONG,ULONG);

FUNCTION
    This function will convert and install up to 16 argument strings into
    a RexxMsg structure.  The message packet's argument fields must be
    set to either a pointer to a NULL terminated string or an integer value
    The mask, bits 0 to 15, correspond to the type of value is stored
    in the argument slot.  If the bit is cleared, the argument is a
    string pointer; if the bit is set, the argument is an integer.

INPUTS
    msgptr - Pointer to a RexxMsg (allocated via CreateRexxMsg)
    count - The number of argument slots to fill in.  This number should
            be from 1 to 16.

    mask - A bit mask corresponding to the 16 fields that is used to
           determine the type of the field.

RESULTS
    result - A boolean.  If it is TRUE, the call worked.  If it is false,
             some allocation did not work.  All argstrings that were
             created will be released.

SEE ALSO
    ClearRexxMsg(), CreateArgstring(), DeleteArgstring(), CreateRexxMsg()

BUGS


rexxsyslib.library/IsRexxMsg

NAME
    IsRexxMsg - Function to determine if a message came from ARexx

SYNOPSIS
    result = IsRexxMsg(msgptr)
    D0                 A0

    BOOL IsRexxMsg(struct RexxMsg *);

FUNCTION
    This function can be used to determine if a message came from an
    ARexx program.

INPUTS
    msgptr - A pointer to the suspected RexxMsg.

RESULTS
    result - A boolean:  TRUE if it is an ARexx message, FALSE if not.

SEE ALSO
    CreateRexxMsg()

BUGS


rexxsyslib.library/LengthArgstring

NAME
    LengthArgstring - Returns the length value stored in the argstring

SYNOPSIS
    length = LengthArgstring(argstring)
    D0                       A0

    ULONG LengthArgstring(UBYTE *);

FUNCTION
    This function returns the length value stored in the argstring.
    This is *NOT* the same as doing a strlen() type call on the
    argstring.  (Note that argstrings may contain NULLs)

INPUTS
    argstring - A pointer to an argstring that was created by ARexx

RESULTS
    length - The length of the argstring.

EXAMPLE

SEE ALSO
    CreateArgstring()

BUGS


rexxsyslib.library/LockRexxBase

NAME
    LockRexxBase - Obtain a semaphore lock on the RexxBase structure

SYNOPSIS
    LockRexxBase(resource)
                 D0

    VOID LockRexxBase(ULONG);

FUNCTION
    Secures the specified resource in the ARexx library base.

INPUTS
    resource - A manifest constant defining which resource to lock.
               ZERO locks all resources.

NOTES
    Currently, only ZERO resource type is available.  You *MUST* make
    sure that you do not call this function with an undefined value
    as it may become defined at some future date and cause unwanted
    behavior.

SEE ALSO
    UnlockRexxBase()

BUGS


rexxsyslib.library/UnlockRexxBase

NAME
    UnlockRexxBase - Release a semaphore lock on the RexxBase structure

SYNOPSIS
    UnlockRexxBase(resource)
                   D0

    VOID UnlockRexxBase(ULONG);

FUNCTION
    Releases the specified resource in the ARexx library base.

INPUTS
    resource - A manifest constant defining which resource to unlock.
               This value *MUST* match the value used in the matching
               LockRexxBase() call.

NOTES
    Currently, only ZERO resource type is available.  You *MUST* make
    sure that you do not call this function with an undefined value
    as it may become defined at some future date and cause unwanted
    behavior.  You *MUST* make sure that you only call this function
    after a matching call to LockRexxBase() was made.

SEE ALSO
    LockRexxBase()

BUGS


exec.doc

 AbortIO()             Debug()                    PutMsg()
 AddDevice()           DeleteIORequest()          RawDoFmt()
 AddHead()             DeleteMsgPort()            ReleaseSemaphore()
 AddIntServer()        Disable()                  ReleaseSemaphoreList()
 AddLibrary()          DoIO()                     RemDevice()
 AddMemList()          Enable()                   RemHead()
 AddPort()             Enqueue()                  RemIntServer()
 AddResource()         FindName()                 RemLibrary()
 AddSemaphore()        FindPort()                 Remove()
 AddTail()             FindResident()             RemPort()
 AddTask()             FindSemaphore()            RemResource()
 Alert()               FindTask()                 RemSemaphore()
 AllocAbs()            Forbid()                   RemTail()
 Allocate()            FreeEntry()                RemTask()
 AllocEntry()          FreeMem()                  ReplyMsg()
 AllocMem()            FreeSignal()               SendIO()
 AllocSignal()         FreeTrap()                 SetExcept()
 AllocTrap()           FreeVec()                  SetFunction()
 AllocVec()            GetCC()                    SetIntVector()
 AttemptSemaphore()    GetMsg()                   SetSignal()
 AvailMem()            InitCode()                 SetSR()
 CacheClearE()         InitResident()             SetTaskPri()
 CacheClearU()         InitSemaphore()            Signal()
 CacheControl()        InitStruct()               StackSwap()
 CachePostDMA()        Insert()                   SumKickData()
 CachePreDMA()         MakeFunctions()            SumLibrary()
 Cause()               MakeLibrary()              SuperState()
 CheckIO()             ObtainSemaphore()          Supervisor()
 CloseDevice()         ObtainSemaphoreList()      TypeOfMem()
 CloseLibrary()        ObtainSemaphoreShared()    UserState()
 ColdReboot()          OldOpenLibrary()           Vacate()
 CopyMem()             OpenDevice()               Wait()
 CopyMemQuick()        OpenLibrary()              WaitIO()
 CreateIORequest()     OpenResource()             WaitPort()
 CreateMsgPort()       Permit()
 Deallocate()          Procure()


exec.library/AbortIO

NAME
    AbortIO - attempt to abort an in-progress I/O request

SYNOPSIS
    AbortIO(iORequest)
            A1

    VOID AbortIO(struct IORequest *);

FUNCTION
    Ask a device to abort a previously started IORequest.  This is done
    by calling the device's ABORTIO vector, with your given IORequest.

    AbortIO is a command the device that may or may not grant.  If
    successful, the device will stop processing the IORequest, and
    reply to it earlier than it would otherwise have done.

NOTE
    AbortIO() does NOT Remove() the IORequest from your ReplyPort, OR
    wait for it to complete.  After an AbortIO() you must wait normally
    for the reply message before actually reusing the request.

    If a request has already completed when AbortIO() is called, no
    action is taken.

EXAMPLE
        AbortIO(timer_request);
        WaitIO(timer_request);
        /* Message is free to be reused */

INPUTS
    iORequest - pointer to an I/O request block (must have been used
            at least once.  May be active or finished).

SEE ALSO
    WaitIO, DoIO, SendIO, CheckIO


exec.library/AddDevice

NAME
    AddDevice -- add a device to the system

SYNOPSIS
    AddDevice(device)
              A1

    void AddDevice(struct Device *);

FUNCTION
    This function adds a new device to the system device list, making
    it available to other programs.  The device must be ready to be
    opened at this time.

INPUTS
    device - pointer to a properly initialized device node

SEE ALSO
    RemDevice, OpenDevice, CloseDevice, MakeLibrary


exec.library/AddHead

NAME
    AddHead -- insert node at the head of a list

SYNOPSIS
    AddHead(list, node)
            A0    A1

    void AddHead(struct List *, struct Node *)

FUNCTION
    Add a node to the head of a doubly linked list. Assembly
    programmers may prefer to use the ADDHEAD macro from
    "exec/lists.i".

WARNING
    This function does not arbitrate for access to the list.  The
    calling task must be the owner of the involved list.

INPUTS
    list - a pointer to the target list header
    node - the node to insert at head

SEE ALSO
    AddTail, Enqueue, Insert, Remove, RemHead, RemTail


exec.library/AddIntServer

NAME
    AddIntServer -- add an interrupt server to a system server chain

SYNOPSIS
    AddIntServer(intNum, interrupt)
                 D0-0:4  A1

    void AddIntServer(ULONG, struct Interrupt *);

FUNCTION
    This function adds a new interrupt server to a given server chain.
    The node is located on the chain in a priority dependent position.
    If this is the first server on a particular chain, interrupts will
    be enabled for that chain.

    Each link in the chain will be called in priority order until the
    chain ends or one of the servers returns with the 68000's Z condition
    code clear (indicating non-zero).  Servers on the chain should return
    with the Z flag clear if the interrupt was specifically for that
    server, and no one else.  VERTB servers should always return Z set.
    (Take care with High Level Language servers, the language may not
    have a mechanism for reliably setting the Z flag on exit).

    Servers are called with the following register conventions:

        D0 - scratch
        D1 - scratch

        A0 - scratch
        A1 - server is_Data pointer (scratch)

        A5 - jump vector register (scratch)
        A6 - scratch

        all other registers must be preserved

INPUTS
    intNum - the Paula interrupt bit number (0 through 14). Processor
             level seven interrupts (NMI) are encoded as intNum 15.
             The PORTS, COPER, VERTB, EXTER and NMI interrupts are
             set up as server chains.
    interrupt - pointer to an Interrupt structure.
             By convention, the LN_NAME of the interrupt structure must
             point a descriptive string so that other users may
             identify who currently has control of the interrupt.

WARNING
    Some compilers or assemblers may optimize code in unexpected ways,
    affecting the conditions codes returned from the function.  Watch
    out for a "MOVEM" instruction (which does not affect the condition
    codes) turning into "MOVE" (which does).

BUGS
    The graphics library's VBLANK server, and some user code, currently
    assume that address register A0 will contain a pointer to the custom
    chips. If you add a server at a priority of 10 or greater, you must
    compensate for this by providing the expected value ($DFF000).

SEE ALSO
    RemIntServer, SetIntVector, hardware/intbits.i,exec/interrupts.i


exec.library/AddLibrary

NAME
    AddLibrary -- add a library to the system

SYNOPSIS
    AddLibrary(library)
               A1

    void AddLibrary(struct Library *);

FUNCTION
    This function adds a new library to the system, making it available
    to other programs.  The library should be ready to be opened at
    this time.  It will be added to the system library name list, and
    the checksum on the library entries will be calculated.

INPUTS
    library - pointer to a properly initialized library structure

SEE ALSO
    RemLibrary, CloseLibrary, OpenLibrary, MakeLibrary


exec.library/AddMemList

NAME
    AddMemList - add memory to the system free pool

SYNOPSIS
    AddMemList( size, attributes, pri, base, name )
                 D0      D1        D2   A0    A1

    void AddMemList(ULONG, ULONG, LONG, APTR, STRPTR);

FUNCTION
    Add a new region of memory to the system free pool.  The first few
    bytes will be used to hold the MemHeader structure.  The remainder
    will be made available to the rest of the world.

INPUTS
    size - the size (in bytes) of the memory area
    attributes - the attributes word that the memory pool will have
    pri  - the priority for this memory.  CHIP memory has a pri of -10,
           16 bit expansion memory has a priority of 0.  The higher the
           priority, the closer to the head of the memory list it will
           be placed.
    base - the base of the new memory area
    name - the name that will be used in the memory header, or NULL
           if no name is to be provided.  This name is not copied, so it
           must remain valid for as long as the memory header is in the
           system.

SEE ALSO
    AllocMem, exec/memory.h


exec.library/AddPort

NAME
    AddPort -- add a public message port to the system

SYNOPSIS
    AddPort(port)
            A1

    void AddPort(struct MsgPort *);

FUNCTION
    This function attaches a message port structure to the system's
    public message port list, where it can be found by the FindPort()
    function.  The name and priority fields of the port structure must
    be initialized prior to calling this function.  If the user does
    not require the priority field, it should be initialized to zero.

    Only ports that will be searched for with FindPort() need to
    be added to the system list.  In addition, adding ports is often
    useful during debugging.  If the port will be searched for,
    the priority field should be at least 1 (to avoid the large number
    of inactive ports at priority zero).  If the port will be searched
    for often, set the proritiry in the 50-100 range (so it will be
    before other less used ports).

    Once a port has been added to the naming list, you must be careful
    to remove the port from the list (via RemPort) before deallocating
    its memory.

NOTE
    A point of confusion is that clearing a MsgPort structure to all
    zeros is not enough to prepare it for use.  As mentioned in the
    Exec chapter of the ROM Kernel Manual, the List for the MsgPort
    must be initialized.  This is automatically handled by AddPort(),
    and amiga.lib/CreatePort.  This initialization can be done manually
    with amiga.lib/NewList or the assembly NEWLIST macro.

    Do not AddPort an active port.

INPUTS
    port - pointer to a message port

SEE ALSO
    RemPort, FindPort, amiga.lib/CreatePort, amiga.lib/NewList


exec.library/AddResource

NAME
    AddResource -- add a resource to the system

SYNOPSIS
    AddResource(resource)
                A1

    void AddResource(APTR);

FUNCTION
    This function adds a new resource to the system and makes it
    available to other users.  The resource must be ready to be called
    at this time.

    Resources currently have no system-imposed structure, however they
    must start with a standard named node (LN_SIZE), and should with
    a standard Library node (LIB_SIZE).

INPUTS
    resource - pointer an initialized resource node

SEE ALSO
    RemResource, OpenResource, MakeLibrary


exec.library/AddSemaphore

NAME
    AddSemaphore -- initialize then add a signal semaphore to the system

SYNOPSIS
    AddSemaphore(signalSemaphore)
                 A1

    void AddSemaphore(struct SignalSemaphore *);

FUNCTION
    This function attaches a signal semaphore structure to the system's
    public signal semaphore list.  The name and priority fields of the
    semaphore structure must be initialized prior to calling this
    function.  If you do not want to let others rendezvous with this
    semaphore, use InitSemaphore() instead.

    If a semaphore has been added to the naming list, you must be
    careful to remove the semaphore from the list (via RemSemaphore)
    before deallocating its memory.

    Semaphores that are linked together in an allocation list (which
    ObtainSemaphoreList() would use) may not be added to the system
    naming list, because the facilities use the link field of the
    signal semaphore in incompatible ways

INPUTS
   signalSemaphore -- an signal semaphore structure

BUGS
    Does not work in Exec <V36.  Instead use this code:

        #include <exec/execbase.h>
        #include <exec/nodes.h>
        extern struct ExecBase *SysBase;
            ...
        void LocalAddSemaphore(s)
        struct SignalSemaphore *s;
        {
            s->ss_Link.ln_Type=NT_SIGNALSEM;
            InitSemaphore(s);
            Forbid();
            Enqueue(&SysBase->SemaphoreList,s);
            Permit();
        }

SEE ALSO
    RemSemaphore, FindSemaphore, InitSemaphore


exec.library/AddTail

NAME
    AddTail -- append node to tail of a list

SYNOPSIS
    AddTail(list, node)
            A0    A1

    void AddTail(struct List *, struct Node *);

FUNCTION
    Add a node to the tail of a doubly linked list.  Assembly
    programmers may prefer to use the ADDTAIL macro from
    "exec/lists.i".

WARNING
    This function does not arbitrate for access to the list.  The
    calling task must be the owner of the involved list.

INPUTS
    list - a pointer to the target list header
    node - a pointer to the node to insert at tail of the list

SEE ALSO
    AddHead, Enqueue, Insert, Remove, RemHead, RemTail


exec.library/AddTask

NAME
    AddTask -- add a task to the system

SYNOPSIS
    AddTask(task, initialPC, finalPC)
            A1    A2         A3

    APTR AddTask(struct Task *, APTR, APTR);

FUNCTION
    Add a task to the system.  A reschedule will be run; the task with
    the highest priority in the system will start to execute (this may
    or may not be the new task).

    Certain fields of the task control block must be initialized and a
    stack allocated prior to calling this function.  The absolute
    smallest stack that is allowable is something in the range of 100
    bytes, but in general the stack size is dependent on what
    subsystems are called. In general 256 bytes is sufficient if only
    Exec is called, and 4K will do if anything in the system is called.
    DO NOT UNDERESTIMATE.  If you use a stack sniffing utility,
    leave a healthy pad above the minimum value.  The system guarantees
    that its stack operations will leave the stack longword aligned.

    This function will temporarily use space from the new task's stack
    for the task's initial set of registers.  This space is allocated
    starting at the SPREG location specified in the task control block
    (not from SPUPPER).  This means that a task's stack may contain
    static data put there prior to its execution.  This is useful for
    providing initialized global variables or some tasks may want to
    use this space for passing the task its initial arguments.

    A task's initial registers are set to zero (except the PC).

    The TC_MEMENTRY field of the task structure may be extended by
    the user to hold additional MemLists (as returned by AllocEntry()).
    These will be automatically be deallocated at RemTask() time.
    If the code you have used to start the task has already added
    something to the MEMENTRY list, simply use AddHead to add your
    new MemLists in.  If no initialization has been done, a NewList will
    need to be performed.

INPUTS
    task  - pointer to the task control block (TCB).  All unset fields
            must be zero.
    initialPC - the initial entry point's address
    finalPC - the finalization code entry point's address.  If zero,
              the system will use a general finalizer. This pointer is
              placed on the stack as if it were the outermost return
              address.

RESULTS
    For V36, AddTask returns either a NULL or the address of the new
    task.  Old code need not check this.

WARNING
    Tasks are a low-level building block, and are unable to call
    dos.library, or any system function that might call dos.library.
    See the AmigaDOS CreateProc() for information on Processes.

SEE ALSO
    RemTask, FindTask, amiga.lib/CreateTask, dos/CreateProc,
    amiga.lib/NewList


exec.library/Alert

NAME
    Alert -- alert the user of an error

SYNOPSIS
    Alert(alertNum)
          D7

    void Alert(ULONG);

FUNCTION
    Alerts the user of a serious system problem.  This function will
    bring the system to a grinding halt, and do whatever is necessary
    to present the user with a message stating what happened.
    Interrupts are disabled, and an attempt to post the alert is made.
    If that fails, the system is reset.  When the system comes up
    again, Exec notices the cause of the failure and tries again to
    post the alert.

    If the Alert is a recoverable type, this call MAY return.

    This call may be made at any time, including interrupts.

POST-MORTEM DIAGNOSIS
    There are several options for determining the cause of a crash.
    Descriptions of each alert number can be found in the "alerts.h"
    include file.  Low numbers not mentioned in the include file
    represent 68000 exceptions, see a 68000 manual for details.  The
    most common numbers are:
                    $00000003 - Address Error
                    $00000004 - Illegal Instruction

    A remote terminal can be attached to the Amiga's first built-in
    serial port.  Set the communication parameters to 9600 baud, 8 bits,
    no parity.  Before resetting the machine, the Alert function will
    blink the power LED 10 times.  While the power indicator is flashing,
    pressing DELETE on the remote terminal will invoke the ROMWack
    debugger.

    For Alerts caused by a 68000 exception, all registers are copied
    to a magic low memory location (currently 16 longwords at $180).

INPUT
    alertNum   - a number indicating the particular alert.  -1 is
            not a valid input.

NOTE
    Much more needs to be said about this function and its implications.

SEE ALSO
    exec/alerts.h


exec.library/AllocAbs

NAME
    AllocAbs -- allocate at a given location

SYNOPSIS
    memoryBlock = AllocAbs(byteSize, location)
    D0                     D0        A1

    void *AllocAbs(ULONG, APTR);

FUNCTION
    This function attempts to allocate memory at a given absolute
    memory location.  Often this is used by boot-surviving entities
    such as recoverable ram-disks.  If the memory is already being
    used, or if there is not enough memory to satisfy the request,
    AllocAbs will return NULL.

    This block may not be exactly the same as the requested block
    because of rounding, but if the return value is non-zero, the block
    is guaranteed to contain the requested range.

INPUTS
    byteSize - the size of the desired block in bytes
               This number is rounded up to the next larger
               block size for the actual allocation.
    location - the address where the memory MUST be.

RESULT
    memoryBlock - a pointer to the newly allocated memory block, or
                  NULL if failed.

NOTE
    If the free list is corrupt, the system will panic with alert
    AN_MemCorrupt, $01000005.

    The 8 bytes past the end of an AllocAbs will be changed by Exec
    relinking the next block of memory.  Generally you can't trust
    the first 8 bytes of anything you AllocAbs.

SEE ALSO
    AllocMem, FreeMem


exec.library/Allocate

NAME
    Allocate - allocate a block of memory

SYNOPSIS
    memoryBlock=Allocate(memHeader, byteSize)
    D0                   A0         D0

    void *Allocate(struct MemHeader *, ULONG);

FUNCTION
    This function is used to allocate blocks of memory from a given
    private free memory pool (as specified by a MemHeader and its
    memory chunk list).  Allocate will return the first free block that
    is greater than or equal to the requested size.

    All blocks, whether free or allocated, will be block aligned;
    hence, all allocation sizes are rounded up to the next block even
    value (e.g. the minimum allocation resolution is currently 8
    bytes.  A request for 8 bytes will use up exactly 8 bytes.  A
    request for 7 bytes will also use up exactly 8 bytes.).

    This function can be used to manage an application's internal data
    memory.  Note that no arbitration of the MemHeader and associated
    free chunk list is done.  You must be the owner before calling
    Allocate.

INPUTS
    memHeader - points to the local memory list header.
    byteSize - the size of the desired block in bytes.

RESULT
    memoryBlock - a pointer to the just allocated free block.
           If there are no free regions large enough to satisfy the
           request, return zero.

EXAMPLE
    #include <exec/types.h>
    #include <exec/memory.h>
    void *AllocMem();
    #define BLOCKSIZE 4096L /* Or whatever you want */

    void main()
    {
    struct MemHeader *mh;
    struct MemChunk  *mc;
    APTR   block1;
    APTR   block2;

        /* Get the MemHeader needed to keep track of our new block */
        mh = (struct MemHeader *)
             AllocMem((long)sizeof(struct MemHeader), MEMF_CLEAR );
        if( !mh )
            exit(10);

        /* Get the actual block the above MemHeader will manage */
        mc = (struct MemChunk *)AllocMem( BLOCKSIZE, 0L );
        if( !mc )
            {
            FreeMem( mh, (long)sizeof(struct MemHeader) ); exit(10);
            }

        mh->mh_Node.ln_Type = NT_MEMORY;
        mh->mh_Node.ln_Name = "myname";
        mh->mh_First = mc;
        mh->mh_Lower = (APTR) mc;
        mh->mh_Upper = (APTR) ( BLOCKSIZE + (ULONG) mc );
        mh->mh_Free  = BLOCKSIZE;

        /* Set up first chunk in the freelist */
        mc->mc_Next  = NULL;
        mc->mc_Bytes = BLOCKSIZE;

        block1 = (APTR) Allocate( mh, 20L );
        block2 = (APTR) Allocate( mh, 314L );
        printf("mh=$%lx mc=$%lxn",mh,mc);
        printf("Block1=$%lx, Block2=$%lxn",block1,block2);

        FreeMem( mh, (long)sizeof(struct MemHeader) );
        FreeMem( mc, BLOCKSIZE );
    }

NOTE
    If the free list is corrupt, the system will panic with alert
    AN_MemCorrupt, $01000005.

SEE ALSO
    Deallocate, exec/memory.h


exec.library/AllocEntry

NAME
    AllocEntry -- allocate many regions of memory

SYNOPSIS
    memList = AllocEntry(memList)
    D0                   A0

    struct MemList *AllocEntry(struct MemList *);

FUNCTION
    This function takes a memList structure and allocates enough memory
    to hold the required memory as well as a MemList structure to keep
    track of it.

    These MemList structures may be linked together in a task control
    block to keep track of the total memory usage of this task. (See
    the description of TC_MEMENTRY under RemTask).

INPUTS
    memList -- A MemList structure filled in with MemEntry structures.

RESULTS
    memList -- A different MemList filled in with the actual memory
        allocated in the me_Addr field, and their sizes in me_Length.
        If enough memory cannot be obtained, then the requirements of
        the allocation that failed is returned and bit 31 is set.

        WARNING: The result is unusual!  Bit 31 indicates faulure.

EXAMPLES
    The user wants five regions of 2, 4, 8, 16, and 32 bytes in size
    with requirements of MEMF_CLEAR, MEMF_PUBLIC, MEMF_CHIP!MEMF_CLEAR,
    MEMF_CLEAR, and MEMF_PUBLIC!MEMF_CLEAR respectively.  The
    following code fragment would do that:

        MemListDecl:
            DS.B    LN_SIZE             * reserve space for list node
            DC.W    5                   * number of entries
            DC.L    MEMF_CLEAR                  * entry #0
            DC.L    2
            DC.L    MEMF_PUBLIC                 * entry #1
            DC.L    4
            DC.L    MEMF_CHIP!MEMF_CLEAR        * entry #2
            DC.L    8
            DC.L    MEMF_CLEAR                  * entry #3
            DC.L    16
            DC.L    MEMF_PUBLIC!MEMF_CLEAR      * entry #4
            DC.L    32

        start:
            LEA.L   MemListDecl(PC),A0
            JSR     _LVOAllocEntry(a6)
            BCLR.L  #31,D0
            BEQ.S   success

            ------- Type of memory that we failed on is in D0

BUGS
    If any one of the allocations fails, this function fails to back
    out fully.  This is fixed by the "SetPatch" program on V1.3
    Workbench disks.

SEE ALSO
    exec/memory.h


exec.library/AllocMem

NAME
    AllocMem -- allocate memory given certain requirements

SYNOPSIS
    memoryBlock = AllocMem(byteSize, attributes)
    D0                     D0        D1

    void *AllocMem(ULONG, ULONG);

FUNCTION
    This is the memory allocator to be used by system code and
    applications.  It provides a means of specifying that the allocation
    should be made in a memory area accessible to the chips, or
    accessible to shared system code.

    Memory is allocated based on requirements and options.  Any
    "requirement" must be met by a memory allocation, any "option" will
    be applied to the block regardless.  AllocMem will try all memory
    spaces until one is found with the proper requirements and room for
    the memory request.

INPUTS
    byteSize - the size of the desired block in bytes.  (The operating
            system will automatically round this number to a multiple of
            the system memory chunk size)

    attributes -
        requirements

            If no flags are set, the system will return the best
            available memory block.  For expanded systems, the fast
            memory pool is searched first.

            MEMF_CHIP:      If the requested memory will be used by
                            the Amiga custom chips, this flag *must*
                            be set.

                            Only certain parts of memory are reachable
                            by the special chip sets' DMA circuitry.
                            Chip DMA includes screen memory, images that
                            are blitted, audio data, copper lists, sprites
                            and Pre-V36 trackdisk.device buffers.

            MEMF_FAST:      This is non-chip memory.  If no flag is set
                            MEMF_FAST is taken as the default.

                            DO NOT SPECIFY MEMF_FAST unless you know
                            exactly what you are doing!  If MEMF_FAST is
                            set, AllocMem() will fail on machines that
                            only have chip memory!  This flag may not
                            be set when MEMF_CHIP is set.

            MEMF_PUBLIC:    Memory that must not be mapped, swapped,
                            or otherwise made non-addressable. ALL
                            MEMORY THAT IS REFERENCED VIA INTERRUPTS
                            AND/OR BY OTHER TASKS MUST BE EITHER PUBLIC
                            OR LOCKED INTO MEMORY! This includes both
                            code and data.

            MEMF_LOCAL:     This is memory that will not go away
                            after the CPU RESET instruction.  Normally,
                            autoconfig memory boards become unavailable
                            after RESET while motherboard memory
                            may still be available.  This memory type
                            is now automatically set in V36.  Pre-V36
                            systems may not have this memory type
                            and AllocMem() will then fail.

            MEMF_24BITDMA:  This is memory that is within the address
                            range of 24-bit DMA devices.  (Zorro-II)
                            This is required if you run a Zorro-II
                            DMA device on a machine that has memory
                            beyond the 24-bit addressing limit of
                            Zorro-II.  This memory type
                            is now automatically set in V36.  Pre-V36
                            systems may not have this memory type
                            and AllocMem() will then fail.

        options

            MEMF_CLEAR:     The memory will be initialized to all
                            zeros.

            MEMF_REVERSE:   This allocates memory from the top of
                            the memory pool.  It searches the pools
                            in the same order, such that FAST memory
                            will be found first.  However, the
                            memory will be allocated from the highest
                            address available in the pool.  This
                            option is new as of V36.

RESULT
    memoryBlock - a pointer to the newly allocated memory block.
            If there are no free memory regions large enough to satisfy
            the request, zero will be returned.  The pointer must be
            checked for zero before the memory block may be used!

WARNING
    The result of any memory allocation MUST be checked, and a viable
    error handling path taken.  ANY allocation may fail if memory has
    been filled.

EXAMPLES
    AllocMem(64,0L)         - Allocate the best available memory
    AllocMem(25,MEMF_CLEAR) - Allocate the best available memory, and
                              clear it before returning.
    AllocMem(128,MEMF_CHIP) - Allocate chip memory
    AllocMem(128,MEMF_CHIP|MEMF_CLEAR) - Allocate cleared chip memory
    AllocMem(821,MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR) - Allocate cleared,
            public, chip memory.

NOTE
    If the free list is corrupt, the system will panic with alert
    AN_MemCorrupt, $01000005.

    This function may not be called from interrupts.

    A DOS process will have its pr_Result2 field set to
    ERROR_NO_FREE_STORE if the memory allocation fails.

SEE ALSO
    FreeMem


exec.library/AllocSignal

NAME
    AllocSignal -- allocate a signal bit

SYNOPSIS
    signalNum = AllocSignal(signalNum)
    D0                      D0

    BYTE AllocSignal(BYTE);

FUNCTION
    Allocate a signal bit from the current tasks' pool.  Either a
    particular bit, or the next free bit may be allocated.  The signal
    associated with the bit will be properly initialized (cleared).  At
    least 16 user signals are available per task.  Signals should be
    deallocated before the task exits.

    If the signal is already in use (or no free signals are available)
    a -1 is returned.

    Allocated signals are only valid for use with the task that
    allocated them.

WARNING
    Signals may not be allocated or freed from exception handling code.

INPUTS
    signalNum - the desired signal number {of 0..31} or -1 for no
                preference.

RESULTS
    signalNum - the signal bit number allocated {0..31}. If no signals
                are available, this function returns -1.

SEE ALSO
    FreeSignal


exec.library/AllocTrap

NAME
    AllocTrap -- allocate a processor trap vector

SYNOPSIS
    trapNum = AllocTrap(trapNum)
    D0                  D0

    LONG AllocTrap(LONG);

FUNCTION
    Allocate a trap number from the current task's pool.  These trap
    numbers are those associated with the 68000 TRAP type instructions.
    Either a particular number, or the next free number may be
    allocated.

    If the trap is already in use (or no free traps are available) a -1
    is returned.

    This function only affects the currently running task.

    Traps are sent to the trap handler pointed at by tc_TrapCode.
    Unless changed by user code, this points to a standard trap
    handler.  The stack frame of the exception handler will be:

            0(SP) = Exception vector number.  This will be in the
                    range of 32 to 47 (corresponding to the
                    Trap #1...Trap #15 instructions).
            4(SP) = 68000/68010/68020/68030, etc. exception frame

    tc_TrapData is not used.

WARNING
    Traps may not be allocated or freed from exception handling code.
    You are not allowed to write to the exception table yourself.  In
    fact, on some machines you will have trouble finding it - the VBR
    register may be used to remap its location.

INPUTS
    trapNum - the desired trap number {of 0..15} or -1
              for no preference.

RESULTS
    trapNum - the trap number allocated {of 0..15}.  If no traps are
              available, this function returns -1.  Instructions of the
              form "Trap #trapNum" will be sent to the task's trap
              handler.

SEE ALSO
    FreeTrap


exec.library/AllocVec

NAME
    AllocVec -- allocate memory and keep track of the size  (V36)

SYNOPSIS
    memoryBlock = AllocVec(byteSize, attributes)
    D0                     D0        D1

    void *AllocVec(ULONG, ULONG);

FUNCTION
    This function works identically to AllocMem(), but tracks the size
    of the allocation.

    See the AllocMem() documentation for details.

WARNING
    The result of any memory allocation MUST be checked, and a viable
    error handling path taken.  ANY allocation may fail if memory has
    been filled.

SEE ALSO
    FreeVec, AllocMem


exec.library/AttemptSemaphore

NAME
    AttemptSemaphore -- try to obtain without blocking

SYNOPSIS
    success = AttemptSemaphore(signalSemaphore)
    D0                         A0

    LONG AttemptSemaphore(struct SignalSemaphore *);

FUNCTION
    This call is similar to ObtainSemaphore(), except that it will not
    block if the semaphore could not be locked.

INPUT
   signalSemaphore -- an initialized signal semaphore structure

RESULT
    success -- TRUE if the semaphore was locked, false if some
        other task already possessed the semaphore.

NOTE
    This call does NOT preserve registers.

SEE ALSO
    ObtainSemaphore() ObtainSemaphoreShared(), ReleaseSemaphore(),
    exec/semaphores.h


exec.library/AvailMem

NAME
    AvailMem -- memory available given certain requirements

SYNOPSIS
    size = AvailMem(attributes)
    D0              D1

    ULONG AvailMem(ULONG);

FUNCTION
    This function returns the amount of free memory given certain
    attributes.

    To find out what the largest block of a particular type is, add
    MEMF_LARGEST into the requirements argument.  Returning the largest
    block is a slow operation.

WARNING
    Due to the effect of multitasking, the value returned may not
    actually be the amount of free memory available at that instant.

INPUTS
    requirements - a requirements mask as specified in AllocMem.  Any
                   of the AllocMem bits are valid, as is MEMF_LARGEST
                   which returns the size of the largest block matching
                   the requirements.

RESULT
    size - total free space remaining (or the largest free block).

NOTE
    For V36 Exec, AvailMem(MEMF_LARGEST) does a consistency check on
    the memory list.  Alert AN_MemoryInsane will be pulled if any mismatch
    is noted.

EXAMPLE
    AvailMem(MEMF_CHIP|MEMF_LARGEST);
    /* return size of largest available chip memory chunk */

SEE ALSO
    exec/memory.h


exec.library/CacheClearE

NAME
    CacheClearE - Cache clearing with extended control (V37)

SYNOPSIS
    CacheClearE(address,length,caches)
                a0      d0     d1

    void CacheClearE(APTR,ULONG,ULONG);

FUNCTION
    Flush out the contents of the CPU instruction and/or data caches.
    If dirty data cache lines are present, push them to memory first.

    Motorola CPUs have separate instruction and data caches.  A data
    write does not update the instruction cache.  If an instruction is
    written to memory or modified, the old instruction may still exist
    in the cache.  Before attempting to execute the code, a flush of
    the instruction cache is required.

    For most systems, the data cache is not updated by Direct Memory
    Access (DMA), or if some external factor changes shared memory.

    Caches must be cleared after *any* operation that could cause
    invalid or stale data.  The most common cases are DMA and modifying
    instructions using the processor.

    Some examples:
                    Self modifying code
                    Building Jump tables
                    Run-time code patches
                    Relocating code for use at different addresses.
                    Loading code from disk

INPUTS
    address - Address to start the operation.  This may be rounded
              due to hardware granularity.
    length  - Length of area to be cleared, or $FFFFFFFF to indicate all
              addresses should be cleared.
    caches  - Bit flags to indicate what caches to affect.  The current
              supported flags are:
                    CACRF_ClearI    ;Clear instruction cache
                    CACRF_ClearD    ;Clear data cache
              All other bits are reserved for future definition.

NOTES
    On systems with a copyback mode cache, any dirty data is pushed
    to memory as a part of this operation.

    Regardless of the length given, the function will determine the most
    efficient way to implement the operation.  For some cache systems,
    including the 68030, the overhead partially clearing a cache is often
    too great.  The entire cache may be cleared.

    For all current Amiga models, Chip memory is set with Instruction
    caching enabled, data caching disabled.  This prevents coherency
    conflicts with the blitter or other custom chip DMA.  Custom chip
    registers are marked as non-cacheable by the hardware.

    The system takes care of appropriately flushing the caches for normal
    operations.  The instruction cache is cleared by all calls that
    modify instructions, including LoadSeg(), MakeLibrary() and
    SetFunction().

SEE ALSO
    exec/execbase.i, CacheControl, CacheClearU


exec.library/CacheClearU

NAME
    CacheClearU - User callable simple cache clearing (V37)

SYNOPSIS
    CacheClearU()

    void CacheClearU(void);

FUNCTION
    Flush out the contents of any CPU instruction and data caches.
    If dirty data cache lines are present, push them to memory first.

    Caches must be cleared after *any* operation that could cause
    invalid or stale data.  The most common cases are DMA and modifying
    instructions using the processor.  See the CacheClearE() autodoc
    for a more complete description.

    Some examples of when the cache needs clearing:
                    Self modifying code
                    Building Jump tables
                    Run-time code patches
                    Relocating code for use at different addresses.
                    Loading code from disk

SEE ALSO
    exec/execbase.i, CacheControl, CacheClearE


exec.library/CacheControl

NAME
    CacheControl - Instruction & data cache control

SYNOPSIS
    oldBits = CacheControl(cacheBits,cacheMask)
    D0                     D0        D1

    ULONG CacheControl(ULONG,ULONG);

FUNCTION
    This function provides global control of any instruction or data
    caches that may be connected to the system.  All settings are
    global -- per task control is not provided.

    The action taken by this function will depend on the type of
    CPU installed.  This function may be patched to support external
    caches, or different cache architectures.  In all cases the function
    will attempt to best emulate the provided settings.  Use of this
    function may save state specific to the caches involved.

    The list of supported settings is provided in the exec/execbase.i
    include file.  The bits currently defined map directly to the Motorola
    68030 CPU CACR register.  Alternate cache solutions may patch into
    the Exec cache functions.  Where possible, bits will be interpreted to
    have the same meaning on the installed cache.

INPUTS
    cacheBits - new values for the bits specified in cacheMask.

    cacheMask - a mask with ones for all bits to be changed.

RESULT
    oldBits   - the complete prior values for all settings.

NOTE
    As a side effect, this function clears all caches.

SEE ALSO
    exec/execbase.i, CacheClearU, CacheClearE


exec.library/CachePostDMA

NAME
    CachePostDMA - Take actions after to hardware DMA  (V37)

SYNOPSIS
    CachePostDMA(vaddress,&length,flags)
                 a0       a1      d0

    CachePostDMA(APTR,LONG *,ULONG);

FUNCTION
    Take all appropriate steps after Direct Memory Access (DMA).  This
    function is primarily intended for writers of DMA device drivers.  The
    action will depend on the CPU type installed, caching modes, and the
    state of any Memory Management Unit (MMU) activity.

    As implemented
            68000 - Do nothing
            68010 - Do nothing
            68020 - Do nothing
            68030 - Flush the data cache
            68040 - Flush matching areas of the data cache
            ????? - External cache boards, Virtual Memory Systems, or
                    future hardware may patch this vector to best emulate
                    the intended behavior.
                    With a Bus-Snooping CPU, this function my end up
                    doing nothing.

INPUTS
    address - Same as initially passed to CachePreDMA
    length  - Same as initially passed to CachePreDMA
    flags   - Values:
                    DMA_NoModify - If the area was not modified (and
                    thus there is no reason to flush the cache) set
                    this bit.

SEE ALSO
    exec/execbase.i, CachePreDMA, CacheClearU, CacheClearE


exec.library/CachePreDMA

NAME
    CachePreDMA - Take actions prior to hardware DMA  (V37)

SYNOPSIS
    paddress = CachePreDMA(vaddress,&length,flags)
    d0                     a0       a1      d0

    APTR CachePreDMA(APTR,LONG *,ULONG);

FUNCTION
    Take all appropriate steps before Direct Memory Access (DMA).  This
    function is primarily intended for writers of DMA device drivers.  The
    action will depend on the CPU type installed, caching modes, and the
    state of any Memory Management Unit (MMU) activity.

    This function supports advanced cache architectures that have
    "copyback" modes.  With copyback, write data may be cached, but not
    actually flushed out to memory.  If the CPU has unflushed data at the
    time of DMA, data may be lost.

    As implemented
            68000 - Do nothing
            68010 - Do nothing
            68020 - Do nothing
            68030 - Do nothing
            68040 - Write any matching dirty cache lines back to memory.
                    As a side effect of the 68040's design, matching data
                    cache lines are also invalidated -- future CPUs may
                    be different.
            ????? - External cache boards, Virtual Memory Systems, or
                    future hardware may patch this vector to best emulate
                    the intended behavior.
                    With a Bus-Snooping CPU, this function my end up
                    doing nothing.

INPUTS
    address - Base address to start the action.
    length  - Pointer to a longword with a length.
    flags   - Values:
                    DMA_Continue - Indicates this call is to complete
                    a prior request that was broken up.

RESULTS
    paddress- Physical address that coresponds to the input virtual
              address.
    &length - This length value will be updated to reflect the contiguous
              length of physical memory present at paddress.  This may
              be smaller than the requested length.  To get the mapping
              for the next chunk of memory, call the function again with
              a new address, length, and the DMA_Continue flag.

NOTE
    Due to processor granularity, areas outside of the address range
    may be affected by the cache flushing actions.  Care has been taken
    to ensure that no harm is done outside the range, and that activities
    on overlapping cache lines won't harm data.

SEE ALSO
    exec/execbase.i, CachePostDMA, CacheClearU, CacheClearE


exec.library/Cause

NAME
   Cause -- cause a software interrupt

SYNOPSIS
   Cause(interrupt)
         A1

   void Cause(struct Interrupt *);

FUNCTION
    This function causes a software interrupt to occur.  If it is
    called from user mode (and processor level 0), the software
    interrupt will preempt the current task.  This call is often used
    by high-level hardware interrupts to defer medium-length processing
    down to a lower interrupt level.  Note that a software interrupt is
    still a real interrupt, and must obey the same restrictions on what
    system function it may call.

    Currently only 5 software interrupt priorities are implemented:
    -32, -16, 0, +16, and +32.  Priorities in between are truncated,
    values outside the -32/+32 range are not allowed.

NOTE
    When setting up the Interrupt structure, set the node type to
    NT_INTERRUPT, or NT_UNKOWN.

IMPLEMENTATION
    1> Checks if the node type is NT_SOFTINT.  If so does nothing since
       the softint is already pending.  No nest count is maintained.
    2> Sets the node type to NT_SOFTINT.
    3> Links into one of the 5 priority queues.
    4> Pokes the hardware interrupt bit used for softints.

    The node type returns to NT_INTERRUPT after removal from the list.

INPUTS
    interrupt - pointer to a properly initialized interrupt node

BUGS
    Unlike other Interrupts, SoftInts must preserve the value of A6.


exec.library/CheckIO

NAME
    CheckIO -- get the status of an IORequest

SYNOPSIS
    result = CheckIO(iORequest)
    D0               A1

    BOOL CheckIO(struct IORequest *);

FUNCTION
    This function determines the current state of an I/O request and
    returns FALSE if the I/O has not yet completed.  This function
    effectively hides the internals of the I/O completion mechanism.

    CheckIO() will NOT remove the returned IORequest from the reply port.
    This is best performed with WaitIO(). If the request has already
    completed, WaitIO() will return quickly. Use of the Remove()
    function is dangerous, since other tasks may still be adding things
    to your message port; a Disable() would be required.

    This function should NOT be used to busy loop (looping until IO is
    complete).  WaitIO() is provided for that purpose.

INPUTS
    iORequest - pointer to an I/O request block

RESULTS
    result - NULL if I/O is still in progress.  Otherwise
             D0 points to the IORequest block.

NOTE
    CheckIO can hang if called on an IORequest that has never been used.
    This occurs if LN_TYPE of the IORequest is set to "NT_MESSAGE".
    Instead simply set LN_TYPE to 0.

SEE ALSO
    DoIO, SendIO, WaitIO, AbortIO


exec.library/CloseDevice

NAME
    CloseDevice -- conclude access to a device

SYNOPSIS
    CloseDevice(iORequest)
                A1

    void CloseDevice(struct IORequest *);

FUNCTION
    This function informs the device that access to a device/unit
    previously opened has been concluded.  The device may perform
    certain house-cleaning operations.

    The user must ensure that all outstanding IORequests have been
    returned before closing the device.  The AbortIO function can kill
    any stragglers.

    After a close, the I/O request structure is free to be reused.
    Starting with V36 exec it is safe to CloseDevice() with an
    IORequest that is either cleared to zeros, or failed to
    open.

INPUTS
    iORequest - pointer to an I/O request structure

SEE ALSO
    OpenDevice


exec.library/CloseLibrary

NAME
    CloseLibrary -- conclude access to a library

SYNOPSIS
    CloseLibrary(library)
                 A1

    void CloseLibrary(struct Library *);

FUNCTION
    This function informs the system that access to the given library
    has been concluded.  The user must not reference the library or any
    function in the library after this close.

    Starting with V36, it is safe to pass a NULL instead of
    a library pointer.

INPUTS
    library - pointer to a library node

NOTE
    Library writers must pass a SegList pointer or NULL back from their
    open point.  This value is used by the system, and not visible as
    a return code from CloseLibrary.

SEE ALSO
    OpenLibrary


exec.library/ColdReboot

NAME
    ColdReboot - reboot the Amiga (V36)

SYNOPSIS
    ColdReboot()

    void ColdReboot(void);

FUNCTION
    Reboot the machine.  All external memory and periperals will be
    RESET, and the machine will start its power up diagnostics.

    This function never returns.

INPUT
    A chaotic pile of disoriented bits.

RESULTS
    An altogether totally integrated living system.


exec.library/CopyMem

NAME
    CopyMem - general purpose memory copy function

SYNOPSIS
    CopyMem( source, dest, size )
             A0      A1    D0

    void CopyMem(APTR,APTR,ULONG);

FUNCTION
    CopyMem is a general purpose, fast memory copy function.  It can
    deal with arbitrary lengths, with its pointers on arbitrary
    alignments.  It attempts to optimize larger copies with more
    efficient copies, it uses byte copies for small moves, parts of
    larger copies, or the entire copy if the source and destination are
    misaligned with respect to each other.

    Arbitrary overlapping copies are not supported.

    The internal implementation of this function will change from
    system to system, and may be implemented via hardware DMA.

INPUTS
    source - a pointer to the source data region
    dest  - a pointer to the destination data region
    size  - the size (in bytes) of the memory area.  Zero copies
            zero bytes

SEE ALSO
    CopyMemQuick


exec.library/CopyMemQuick

NAME
    CopyMemQuick - optimized memory copy function

SYNOPSIS
    CopyMemQuick( source, dest, size )
                  A0      A1    D0

    void CopyMemQuick(ULONG *,ULONG *,ULONG);

FUNCTION
    CopyMemQuick is a highly optimized memory copy function, with
    restrictions on the size and alignment of its arguments. Both the
    source and destination pointers must be longword aligned.  In
    addition, the size must be an integral number of longwords (e.g.
    the size must be evenly divisible by four).

    Arbitrary overlapping copies are not supported.

    The internal implementation of this function will change from system
    to system, and may be implemented via hardware DMA.

INPUTS
    source - a pointer to the source data region, long aligned
    dest -  a pointer to the destination data region, long aligned
    size -  the size (in bytes) of the memory area.  Zero copies
            zero bytes.

SEE ALSO
    CopyMem


exec.library/CreateIORequest

NAME
    CreateIORequest() -- create an IORequest structure  (V36)

SYNOPSIS
    ioReq = CreateIORequest( ioReplyPort, size );
                             A0           D0

    struct IORequest *CreateIORequest(struct MsgPort *, ULONG);

FUNCTION
    Allocates memory for and initializes a new IO request block
    of a user-specified number of bytes.  The number of bytes
    must be at least as large as a "struct Message".

INPUTS
    ioReplyPort - Pointer to a port for replies (an initialized message
            port, as created by CreateMsgPort() ).  If NULL, this
            function fails.
    size - the size of the IO request to be created.

RESULT
    ioReq - A pointer to the new IORequest block, or NULL.

SEE ALSO
    DeleteIORequest, CreateMsgPort(), amiga.lib/CreateExtIO()


exec.library/CreateMsgPort

NAME
    CreateMsgPort - Allocate and initialize a new message port  (V36)

SYNOPSIS
    CreateMsgPort()

    struct MsgPort * CreateMsgPort(void);

FUNCTION
    Allocates and initializes a new message port.  The message list
    of the new port will be prepared for use (via NewList).  A signal
    bit will be allocated, and the port will be set to signal your
    task when a message arrives (PA_SIGNAL).

    You *must* use DeleteMsgPort() to delete ports created with
    CreateMsgPort()!

RESULT
    MsgPort - A new MsgPort structure ready for use, or NULL if out of
            memory or signals.  If you wish to add this port to the public
            port list, fill in the ln_Name and ln_Pri fields, then call
            AddPort().  Don't forget RemPort()!

SEE ALSO
    DeleteMsgPort(), exec/AddPort(), exec/ports.h, amiga.lib/CreatePort()


exec.library/Deallocate

NAME
    Deallocate -- deallocate a block of memory

SYNOPSIS
    Deallocate(memHeader, memoryBlock, byteSize)
               A0         A1           D0

    void Deallocate(struct MemHeader *,APTR,ULONG);

FUNCTION
    This function deallocates memory by returning it to the appropriate
    private free memory pool.  This function can be used to free an
    entire block allocated with the above function, or it can be used
    to free a sub-block of a previously allocated block.  Sub-blocks
    must be an even multiple of the memory chunk size (currently 8
    bytes).

    This function can even be used to add a new free region to an
    existing MemHeader, however the extent pointers in the MemHeader
    will no longer be valid.

    If memoryBlock is not on a block boundary (MEM_BLOCKSIZE) then it
    will be rounded down in a manner compatible with Allocate().  Note
    that this will work correctly with all the memory allocation
    functions, but may cause surprises if one is freeing only part of a
    region.  The size of the block will be rounded up, so the freed
    block will fill to an even memory block boundary.

INPUTS
    memHeader - points to the memory header this block is part of.
    memoryBlock - address of memory block to free.
    byteSize - the size of the block in bytes. If NULL, nothing
               happens.

SEE ALSO
    Allocate, exec/memory.h


exec.library/Debug

NAME
    Debug -- run the system debugger

SYNOPSIS
    Debug(flags)
          D0

    void Debug(ULONG);

FUNCTION
    This function calls the system debugger.  By default this debugger
    is "ROM-WACK".  Other debuggers are encouraged to take over this
    entry point (via SetFunction()) so that when an application calls
    Debug(), the alternative debugger will get control.  Currently a
    zero is passed to allow future expansion.

NOTE
    The Debug() call may be made when the system is in a questionable
    state; if you have a SetFunction() patch, make few assumptions, be
    prepared for Supervisor mode, and be aware of differences in the
    Motorola stack frames on the 68000,'10,'20, and '30.

SEE ALSO
    SetFunction
    your favorite debugger's manual
    the ROM-WACK chapter of the ROM Kernel Manual


exec.library/DeleteIORequest

NAME
    DeleteIORequest() - Free a request made by CreateIORequest()  (V36)

SYNOPSIS
    DeleteIORequest( ioReq );
                     a0

    void DeleteIORequest(struct IORequest *);

FUNCTION
    Frees up an IO request as allocated by CreateIORequest().

INPUTS
    ioReq - A pointer to the IORequest block to be freed, or NULL.
            This function uses the mn_Length field to determine how
            much memory to free.

SEE ALSO
    CreateIORequest(), amiga.lib/DeleteExtIO()


exec.library/DeleteMsgPort

NAME
    DeleteMsgPort - Free a message port created by CreateMsgPort  (V36)

SYNOPSIS
    DeleteMsgPort(msgPort)
                  a0

    void DeleteMsgPort(struct MsgPort *);

FUNCTION
    Frees a message port created by CreateMsgPort().  All messages that
    may have been attached to this port must have already been
    replied to.

INPUTS
    msgPort - A message port.  NULL for no action.

SEE ALSO
    CreateMsgPort(), amiga.lib/DeletePort()


exec.library/Disable

NAME
    Disable -- disable interrupt processing.

SYNOPSIS
    Disable();

    void Disable(void);

FUNCTION
    Prevents interrupts from being handled by the system, until a
    matching Enable() is executed.  Disable() implies Forbid().

    DO NOT USE THIS CALL WITHOUT GOOD JUSTIFICATION.  THIS CALL IS
    VERY DANGEROUS!

RESULTS
    All interrupt processing is deferred until the task executing makes
    a call to Enable() or is placed in a wait state.  Normal task
    rescheduling does not occur while interrupts are disabled.  In order
    to restore normal interrupt processing, the programmer must execute
    exactly one call to Enable() for every call to Disable().

    IMPORTANT REMINDER:

    It is important to remember that there is a danger in using
    disabled sections.  Disabling interrupts for more than ~250
    microseconds will prevent vital system functions (especially serial
    I/0) from operating in a normal fashion.

    Think twice before using Disable(), then think once more.
    After all that, think again.  With enough thought, the need
    for a Disable() can often be eliminated.  For the user of many
    device drivers, a write to disable *only* the particular interrupt
    of interest can replace a Disable().  For example:
                    MOVE.W  #INTF_PORTS,_intena
    Do not use a macro for Disable(), insist on the real thing.

    This call may be made from interrupts, it will have the effect
    of locking out all higher-level interrupts (lower-level interrupts
    are automatically disabled by the CPU).

    Note: In the event of a task entering a Wait() after disabling
          interrupts, the system "breaks" the disabled state and runs
          normally until the task which called Disable() is rescheduled.

NOTE
    This call is guaranteed to preserve all registers.

SEE ALSO
    Forbid, Permit, Enable


exec.library/DoIO

NAME
    DoIO -- perform an I/O command and wait for completion

SYNOPSIS
    error = DoIO(iORequest)
    D0           A1

    BYTE DoIO(struct IORequest *);

FUNCTION
    This function requests a device driver to perform the I/O command
    specified in the I/O request.  This function will always wait until
    the I/O request is fully complete.

    DoIO() handles all the details, including Quick I/O, waiting for
    the request, and removing the reply message, etc..

IMPLEMENTATION
    This function first tries to complete the IO via the "Quick I/O"
    mechanism.  The io_Flags field is always set to IOF_QUICK (0x01)
    before the internal device call.

    The LN_TYPE field is used internally to flag completion.  Active
    requests have type NT_MESSAGE.  Requests that have been replied
    have type NT_REPLYMSG.  It is illegal to start IO using a
    still active IORequest, or a request with type NT_REPLYMSG.

INPUTS
    iORequest - pointer to an IORequest initialized by OpenDevice()

RESULTS
    error - a sign-extended copy of the io_Error field of the
            IORequest.  Most device commands require that the error
            return be checked.

SEE ALSO
    SendIO, CheckIO, WaitIO, AbortIO, amiga.lib/BeginIO


exec.library/Enable

NAME
    Enable -- permit system interrupts to resume.

SYNOPSIS
    Enable();

    void Enable(void);

FUNCTION
    Allow system interrupts to again occur normally, after a matching
    Disable() has been executed.

RESULTS
    Interrupt processing is restored to normal operation. The
    programmer must execute exactly one call to Enable() for every call
    to Disable().

NOTE
    This call is guaranteed to preserve all registers.

SEE ALSO
    Forbid, Permit, Disable


exec.library/Enqueue

NAME
    Enqueue -- insert or append node to a system queue

SYNOPSIS
    Enqueue(list, node)
            A0    A1

    void Enqueue(struct List *, struct Node *);

FUNCTION
    Insert or append a node into a system queue.  The insert is
    performed based on the node priority -- it will keep the list
    properly sorted.  New nodes will be inserted in front of the first
    node with a lower priority.   Hence a FIFO queue for nodes of equal
    priority

WARNING
    This function does not arbitrate for access to the list.  The
    calling task must be the owner of the involved list.

INPUTS
    list - a pointer to the system queue header
    node - the node to enqueue.  This must be a full featured list
           with type, priority and name fields.

SEE ALSO
    AddHead, AddTail, Insert, Remove, RemHead, RemTail


exec.library/FindName

NAME
    FindName -- find a system list node with a given name

SYNOPSIS
    node = FindName(start, name)
    D0,Z            A0     A1

    struct Node *FindName(struct List *, STRPTR);

FUNCTION
    Traverse a system list until a node with the given name is found.
    To find multiple occurrences of a string, this function may be
    called with a node starting point.

    No arbitration is done for access to the list!  If multiple tasks
    access the same list, an arbitration mechanism such as
    SignalSemaphores must be used.

INPUTS
    start - a list header or a list node to start the search
            (if node, this one is skipped)
    name - a pointer to a name string terminated with NULL

RESULTS
    node - a pointer to the node with the same name else
        zero to indicate that the string was not found.


exec.library/FindPort

NAME
    FindPort -- find a given system message port

SYNOPSIS
    port = FindPort(name)
    D0              A1

    struct MsgPort *FindPort(STRPTR);

FUNCTION
    This function will search the system message port list for a port
    with the given name.  The first port matching this name will be
    returned.  No arbitration of the port list is done.  This function
    MUST be protected with A Forbid()/Permit() pair!

EXAMPLE
    #include <exec/types.h>
    struct MsgPort *FindPort();

    ULONG SafePutToPort(message, portname)
    struct Message *message;
    STRPTR          portname;
    {
    struct MsgPort *port;

        Forbid();
            port = FindPort(portname);
            if (port)
                PutMsg(port,message);
        Permit();
        return((ULONG)port); /* If zero, the port has gone away */
    }

INPUT
    name - name of the port to find

RETURN
    port - a pointer to the message port, or zero if
            not found.


exec.library/FindResident

NAME
    FindResident - find a resident module by name

SYNOPSIS
    resident = FindResident(name)
    D0                      A1

    struct Resident *FindResident(STRPTR);

FUNCTION
    Search the system resident tag list for a resident tag ("ROMTag") with
    the given name.  If found return a pointer to the resident tag
    structure, else return zero.

    Resident modules are used by the system to pull all its parts
    together at startup.  Resident tags are also found in disk based
    devices and libraries.

INPUTS
    name - pointer to name string

RESULT
    resident - pointer to the resident tag structure or
            zero if none found.

SEE ALSO
    exec/resident.h, InitResident


exec.library/FindSemaphore

NAME
    FindSemaphore -- find a given system signal semaphore

SYNOPSIS
    signalSemaphore = FindSemaphore(name)
    D0                              A1

    struct SignalSemaphore *FindSemaphore(STRPTR);

FUNCTION
    This function will search the system signal semaphore list for a
    semaphore with the given name.  The first semaphore matching this
    name will be returned.

    This function does not arbitrate for access to the semaphore list,
    surround the call with a Forbid()/Permit() pair.

INPUT
    name - name of the semaphore to find

RESULT
    semaphore - a pointer to the signal semaphore, or zero if not
                found.


exec.library/FindTask

NAME
    FindTask -- find a task with the given name or find oneself

SYNOPSIS
    task = FindTask(name)
    D0              A1

    struct Task *FindTask(STRPTR);

FUNCTION
    This function will check all task queues for a task with the given
    name, and return a pointer to its task control block.  If a NULL
    name pointer is given a pointer to the current task will be
    returned.

    Finding oneself with a NULL for the name is very quick.  Finding a
    task by name is very system expensive, and will disable interrupts
    for a long time.  Since a task may remove itself at any time,
    a Forbid()/Permit() pair may be needed to ensure the pointer
    returned by FindTask() is still valid when used.

INPUT
    name - pointer to a name string

RESULT
    task - pointer to the task (or Process)


exec.library/Forbid

NAME
    Forbid -- forbid task rescheduling.

SYNOPSIS
    Forbid()

    void Forbid(void);

FUNCTION
    Prevents other tasks from being scheduled to run by the dispatcher,
    until a matching Permit() is executed, or this task is scheduled to
    Wait().  Interrupts are NOT disabled.

    DO NOT USE THIS CALL WITHOUT GOOD JUSTIFICATION.  THIS CALL IS
    DANGEROUS!

RESULTS
    The current task will not be rescheduled as long as it is ready to
    run.  In the event that the current task enters a wait state, other
    tasks may be scheduled.  Upon return from the wait state, the original
    task will continue to run without disturbing the Forbid().

    Calls to Forbid() nest. In order to restore normal task rescheduling,
    the programmer must execute exactly one call to Permit() for every
    call to Forbid().

WARNING
    In the event of a task entering a Wait() after a Forbid(), the system
    "breaks" the forbidden state and runs normally until the task which
    called Forbid() is rescheduled.  If caution is not taken, this can
    cause subtle bugs, since any device or DOS call will (in effect)
    cause your task to wait.

    Forbid() is not useful or safe from within interrupt code
    (All interrupts are always higher priority than tasks, and
    interrupts are allowed to break a Forbid()).

NOTE
    This call is guaranteed to preserve all registers.

SEE ALSO
    Permit, Disable, ObtainSemaphore, ObtainSemaphoreShared


exec.library/FreeEntry

NAME
    FreeEntry -- free many regions of memory

SYNOPSIS
    FreeEntry(memList)
              A0
    void FreeEntry(struct MemList *);

FUNCTION
    This function takes a memList structure (as returned by AllocEntry)
    and frees all the entries.

INPUTS
    memList -- pointer to structure filled in with MemEntry
               structures

SEE ALSO
    AllocEntry


exec.library/FreeMem

NAME
    FreeMem -- deallocate with knowledge

SYNOPSIS
    FreeMem(memoryBlock, byteSize)
            A1           D0

    void FreeMem(void *,ULONG);

FUNCTION
    Free a region of memory, returning it to the system pool from which
    it came.  Freeing partial blocks back into the system pool is
    unwise.

NOTE
    If a block of memory is freed twice, the system will Guru. The
    Alert is AN_FreeTwice ($01000009).   If you pass the wrong pointer,
    you will probably see AN_MemCorrupt $01000005.  Future versions may
    add more sanity checks to the memory lists.

INPUTS
    memoryBlock - pointer to the memory block to free
    byteSize - the size of the desired block in bytes.  (The operating
            system will automatically round this number to a multiple of
            the system memory chunk size)

SEE ALSO
    AllocMem


exec.library/FreeSignal

NAME
    FreeSignal -- free a signal bit

SYNOPSIS
    FreeSignal(signalNum)
               D0

    void FreeSignal(BYTE);

FUNCTION
    This function frees a previously allocated signal bit for reuse.
    This call must be performed while running in the same task in which
    the signal was allocated.

WARNING
    Signals may not be allocated or freed from exception handling code.

NOTE
    Starting with V37, an attempt to free signal -1 is harmless.

INPUTS
    signalNum - the signal number to free {0..31}.


exec.library/FreeTrap

NAME
    FreeTrap -- free a processor trap

SYNOPSIS
    FreeTrap(trapNum)
             D0

    void FreeTrap(ULONG);

FUNCTION
    This function frees a previously allocated trap number for reuse.
    This call must be performed while running in the same task in which
    the trap was allocated.

WARNING
    Traps may not be allocated or freed from exception handling code.

INPUTS
    trapNum - the trap number to free {of 0..15}


exec.library/FreeVec

NAME
    FreeVec -- return AllocVec() memory to the system  (V36)

SYNOPSIS
    FreeVec(memoryBlock)
            A1

    void FreeVec(void *);

FUNCTION
    Free an allocation made by the AllocVec() call.  The memory will
    be returned to the system pool from which it came.

NOTE
    If a block of memory is freed twice, the system will Guru. The
    Alert is AN_FreeTwice ($01000009).   If you pass the wrong pointer,
    you will probably see AN_MemCorrupt $01000005.  Future versions may
    add more sanity checks to the memory lists.

INPUTS
    memoryBlock - pointer to the memory block to free, or NULL.

SEE ALSO
    AllocVec


exec.library/GetCC

NAME
    GetCC -- get condition codes in a 68010 compatible way.

SYNOPSIS
    conditions = GetCC()
      D0

    UWORD GetCC(void);

FUNCTION
    The 68000 processor has a "MOVE SR,<ea>" instruction which gets a
    copy of the processor condition codes.

    On the 68010,20 and 30 CPUs, "MOVE SR,<ea>" is privileged.  User
    code will trap if it is attempted.  These processors need to use
    the "MOVE CCR,<ea>" instruction instead.

    This function provides a means of obtaining the CPU condition codes
    in a manner that will make upgrades transparent.  This function is
    VERY short and quick.

RESULTS
    conditions - the 680XX condition codes

NOTE
    This call is guaranteed to preserve all registers.  This function
    may be implemented as code right in the jump table.


exec.library/GetMsg

NAME
    GetMsg -- get next message from a message port

SYNOPSIS
    message = GetMsg(port)
    D0               A0

    struct Message *GetMsg(struct MsgPort *);

FUNCTION
    This function receives a message from a given message port. It
    provides a fast, non-copying message receiving mechanism. The
    received message is removed from the message port.

    This function will not wait.  If a message is not present this
    function will return zero.  If a program must wait for a message,
    it can Wait() on the signal specified for the port or use the
    WaitPort() function.  There can only be one task waiting for any
    given port.

    Getting a message does not imply to the sender that the message is
    free to be reused by the sender.  When the receiver is finished
    with the message, it may ReplyMsg() it back to the sender.

    Getting a signal does NOT always imply a message is ready.  More
    than one message may arrive per signal, and signals may show up
    without messages.  Typically you must loop to GetMsg() until it
    returns zero, then Wait() or WaitPort().

INPUT
    port - a pointer to the receiver message port

RESULT
    message - a pointer to the first message available.  If
              there are no messages, return zero.
              Callers must be prepared for zero at any time.

SEE ALSO
    PutMsg, ReplyMsg, WaitPort, Wait, exec/ports.h


exec.library/InitCode

NAME
    InitCode - initialize resident code modules (internal function)

SYNOPSIS
    InitCode(startClass, version)
             D0          D1

    void InitCode(ULONG,ULONG);

FUNCTION
    (This function may be ignored by application programmers)

    Call InitResident() for all resident modules in the ResModules array
    with the given startClass and with versions equal or greater than
    that specified.  The segList parameter is passed as zero.

    Resident modules are used by the system to pull all its parts
    together at startup.  Modules are initialized in a prioritized order.

    Modules that do not have a startclass should be of priority -120.
    RTF_AFTERDOS modues should start at -100 (working down).

INPUTS
    startClass - the class of code to be initialized:
            BITDEF RT,COLDSTART,0
            BITDEF RT,SINGLETASK,1  ;ExecBase->ThisTask==0 (V36 only)
            BITDEF RT,AFTERDOS,2    ;(V36 only)
    version - a major version number

SEE ALSO
    ResidentTag (RT) structure definition (resident.h)


exec.library/InitResident

NAME
    InitResident - initialize resident module

SYNOPSIS
    object = InitResident(resident, segList)
    D0                     A1        D1

    APTR InitResident(struct Resident *,ULONG);

FUNCTION
    Initialize a ROMTag.  ROMTags are used to link system modules
    together.  Each disk based device or library must contain a
    ROMTag structure in the first code hunk.

    Once the validity of the ROMTag is verified, the RT_INIT pointer
    is jumped to  with the following registers:
            D0 = 0
            A0 = segList
            A6 = ExecBase

INPUTS
    resident - Pointer to a ROMTag
    segList  - SegList of the loaded object, if loaded from disk.
               Libraries & Devices will cache this value for later
               return at close or expunge time.  Pass NULL for ROM
               modules.

RESULTS
    object  - Return value from the init code, usually the library
              or device base.  NULL for failure.

AUTOINIT FEATURE
    An automatic method of library/device base and vector table
    initialization is also provided by InitResident().  The initial code
    hunk of the library or device should contain "MOVEQ #-1,d0; RTS;".
    Following that must be an initialized Resident structure with
    RTF_AUTOINIT set in rt_Flags, and an rt_Init pointer which points
    to four longwords.  These four longwords will be used in a call
    to MakeLibrary();

        - The size of your library/device base structure including initial
          Library or Device structure.

        - A pointer to a longword table of standard, then library
          specific function offsets, terminated with -1L.
          (short format offsets are also acceptable)

        - Pointer to data table in exec/InitStruct format for
          initialization of Library or Device structure.

        - Pointer to library initialization function, or NULL.
            Calling sequence:
                    D0 = library base
                    A0 = segList
                    A6 = ExecBase
          This function must return in D0 the library/device base to be
          linked into the library/device list.  If the initialization
          function fails, the device memory must be manually deallocated,
          then NULL returned in D0.

SEE ALSO
    exec/resident.i, FindResident


exec.library/InitSemaphore

NAME
    InitSemaphore -- initialize a signal semaphore

SYNOPSIS
    InitSemaphore(signalSemaphore)
                  A0

    void InitSemaphore(struct SignalSemaphore *);

FUNCTION
    This function initializes a signal semaphore and prepares it for
    use.  It does not allocate anything, but does initialize list
    pointers and the semaphore counters.

    Semaphores are often used to protect critical data structures
    or hardware that can only be accessed by one task at a time.
    After initialization, the address of the SignalSemaphore may be
    made available to any number of tasks.  Typically a task will
    try to ObtainSemaphore(), passing this address in.  If no other
    task owns the semaphore, then the call will lock and return
    quickly.  If more tasks try to ObtainSemaphore(), they will
    be put to sleep.  When the owner of the semaphore releases
    it, the next waiter in turn will be woken up.

    Semaphores are often preferable to the old-style Forbid()/Permit()
    type arbitration.  With Forbid()/Permit() *all* other tasks are
    prevented from running.  With semaphores, only those tasks that
    need access to whatever the semaphore protects are subject
    to waiting.

INPUT
    signalSemaphore -- a signal semaphore structure (with all fields
                       set to zero before the call)

SEE ALSO
    ObtainSemaphore(), ObtainSemaphoreShared(), AttemptSemaphore(),
    ReleaseSemaphore(), exec/semaphores.h


exec.library/InitStruct

NAME
    InitStruct - initialize memory from a table

SYNOPSIS
    InitStruct(initTable, memory, size);
               A1         A2      D0

    void InitStruct(struct InitStruct *, APTR, ULONG);

FUNCTION
    Clear a memory area, then set up default values according to
    the data and offset values in the initTable.  Typically only assembly
    programs take advantage of this function, and only with the macros
    defined in "exec/initializers.i".

    The initialization table has byte commands to

         |a    ||byte|      |given||byte|         |once         |
    load |count||word| into |next ||rptr| offset, |repetitively |
                |long|

    Not all combinations are supported.  The offset, when specified, is
    relative to the memory pointer provided (Memory), and is initially
    zero.  The initialization data (InitTable) contains byte commands
    whose 8 bits are interpreted as follows:

    ddssnnnn
        dd  the destination type (and size):
            00  no offset, use next destination, nnnn is count
            01  no offset, use next destination, nnnn is repeat
            10  destination offset is in the next byte, nnnn is count
            11  destination offset is in the next 24-bits, nnnn is count
        ss  the size and location of the source:
            00  long, from the next two aligned words
            01  word, from the next aligned word
            10  byte, from the next byte
            11  ERROR - will cause an ALERT (see below)
      nnnn  the count or repeat:
         count  the (number+1) of source items to copy
        repeat  the source is copied (number+1) times.

    initTable commands are always read from the next even byte. Given
    destination offsets are always relative to the memory pointer (A2).

    The command %00000000 ends the InitTable stream: use %00010001 if you
    really want to copy one longword without a new offset.

    24 bit APTR not supported for 68020 compatibility -- use long.

INPUTS
    initTable - the beginning of the commands and data to init
            Memory with.  Must be on an even boundary unless only
            byte initialization is done.  End table with "dc.b 0"
            or "dc.w 0".
    memory - the beginning of the memory to initialize.  Must be
            on an even boundary if size is specified.
    size - the size of memory, which is used to clear it before
            initializing it via the initTable.  If Size is zero,
            memory is not cleared before initializing.

            size must be an even number.

SEE ALSO
    exec/initializers.i


exec.library/Insert

NAME
    Insert -- insert a node into a list

SYNOPSIS
    Insert(list, node, listNode)
           A0    A1    A2

    void Insert(struct List *, struct Node *, struct Node *);

FUNCTION
    Insert a node into a doubly linked list AFTER a given node
    position.  Insertion at the head of a list is possible by passing a
    zero value for listNode, though the AddHead function is slightly
    faster for that special case.

WARNING
    This function does not arbitrate for access to the list.  The
    calling task must be the owner of the involved list.

INPUTS
    list - a pointer to the target list header
    node - the node to insert
    listNode - the node after which to insert

SEE ALSO
    AddHead, AddTail, Enqueue, RemHead, Remove, RemTail


exec.library/MakeFunctions

NAME
    MakeFunctions -- construct a function jump table

SYNOPSIS
    tableSize = MakeFunctions(target, functionArray, funcDispBase)
    D0                        A0      A1             A2

    ULONG MakeFunctions(APTR,APTR,APTR);

FUNCTION
    A low level function used by MakeLibrary to build jump tables of
    the type used by libraries, devices and resources.  It allows the
    table to be built anywhere in memory, and can be used both for
    initialization and replacement. This function also supports function
    pointer compression by expanding relative displacements into absolute
    pointers.

    The processor instruction cache is cleared after the table building.

INPUT
    destination - the target address for the high memory end of the
            function jump table.  Typically this will be the library
            base pointer.

    functionArray - pointer to an array of function pointers or
            function displacements.  If funcDispBase is zero, the array
            is assumed to contain absolute pointers to functions. If
            funcDispBase is not zero, then the array is assumed to
            contain word displacements to functions.  In both cases,
            the array is terminated by a -1 (of the same size as the
            actual entry.

    funcDispBase - pointer to the base about which all function
            displacements are relative.  If zero, then the function
            array contains absolute pointers.

RESULT
    tableSize - size of the new table in bytes (for LIB_NEGSIZE).

SEE ALSO
    exec/MakeLibrary


exec.library/MakeLibrary

NAME
    MakeLibrary -- construct a library

SYNOPSIS
    library = MakeLibrary(vectors, structure, init, dSize, segList)
    D0                    A0       A1         A2    D0     D1

    struct Library *MakeLibrary
                          (APTR,struct InitStruct *,APTR,ULONG,BPTR);

FUNCTION
    This function is used for constructing a library vector and data
    area.  The same call is used to make devices.  Space for the library
    is allocated from the system's free memory pool.  The data portion of
    the library is initialized.  init may point to a library specific
    entry point.

NOTE
    Starting with V36, the library base is longword adjusted.  The
    lib_PosSize and lib_NegSize fields of the library structure are
    adjusted to match.

INPUTS
    vectors - pointer to an array of function pointers or function
            displacements.  If the first word of the array is -1, then
            the array contains relative word displacements (based off
            of vectors); otherwise, the array contains absolute
            function pointers. The vector list is terminated by a -1
            (of the same size as the pointers).

    structure - points to an "InitStruct" data region.  If NULL,
            then it will not be used.

    init -  If non-NULL, an entry point that will be called before adding
            the library to the system.  Registers are as follows:
                    d0 = libAddr    ;Your Library Address
                    a0 = segList    ;Your AmigaDOS segment list
                    a6 = ExecBase  ;Address of exec.library
            The result of the init function must be the library address,
            or NULL for failure.   If NULL, the init point must manually
            deallocate the library base memory (based on the sizes stored
            in lib_PosSize and lib_NegSize).

    dSize - the size of the library data area, including the
            standard library node data.  This must be at leas
            sizeof(struct Library).

   segList - pointer to an AmigaDOS SegList (segment list).
             This is passed to a library's init code, and is used later
             for removing the library from memory.

RESULT
    library - the reference address of the library.  This is the
              address used in references to the library, not the
              beginning of the memory area allocated.  If the library
              vector table require more system memory than is
              available, this function will return NULL.

SEE ALSO
    InitStruct, InitResident, exec/initializers.i


exec.library/ObtainSemaphore

NAME
    ObtainSemaphore -- gain exclusive access to a semaphore

SYNOPSIS
    ObtainSemaphore(signalSemaphore)
                    A0

    void ObtainSemaphore(struct SignalSemaphore *);

FUNCTION
    Signal semaphores are used to gain exclusive access to an object.
    ObtainSemaphore is the call used to gain this access.  If another
    user currently has the semaphore locked the call will block until
    the object is available.

    If the current task already has locked the semaphore and attempts to
    lock it again the call will still succeed.  A "nesting count" is
    incremented each time the current owning task of the semaphore calls
    ObtainSemaphore().  This counter is decremented each time
    ReleaseSemaphore() is called.  When the counter returns to zero the
    semaphore is actually released, and the next waiting task is called.

    A queue of waiting tasks is maintained on the stacks of the waiting
    tasks.  Each will be called in turn as soon as the current task
    releases the semaphore.

    Signal Semaphores are different than Procure()/Vacate() semaphores.
    The former requires less CPU time, especially if the semaphore is
    not currently locked.  They require very little set up and user
    thought.  The latter flavor of semaphore make no assumptions about
    how they are used -- they are completely general.  Unfortunately
    they are not as efficient as signal semaphores, and require the
    locker to have done some setup before doing the call.

INPUT
   signalSemaphore -- an initialized signal semaphore structure

NOTE
    This function preserves all registers (see BUGS).

BUGS
    Until V37, this function could destroy A0.

SEE ALSO
    ObtainSemaphoreShared(), InitSemaphore(), ReleaseSemaphore(),
    AttemptSemaphore(), ObtainSemaphoreList()


exec.library/ObtainSemaphoreList

NAME
    ObtainSemaphoreList -- get a list of semaphores.

SYNOPSIS
    ObtainSemaphoreList(list)
                        A0

    void ObtainSemaphoreList(struct List *);

FUNCTION
    Signal semaphores may be linked together into a list. This function
    takes a list of these semaphores and attempts to lock all of them at
    once. This call is preferable to applying ObtainSemaphore() to each
    element in the list because it attempts to lock all the elements
    simultaneously, and won't deadlock if someone is attempting to lock
    in some other order.

    This function assumes that only one task at a time will attempt to
    lock the entire list of semaphores.  In other words, there needs to
    be a higher level lock (perhaps another signal semaphore...) that is
    used before someone attempts to lock the semaphore list via
    ObtainSemaphoreList().

    Note that deadlocks may result if this call is used AND someone
    attempts to use ObtainSemaphore() to lock more than one semaphore on
    the list.  If you wish to lock more than semaphore (but not all of
    them) then you should obtain the higher level lock (see above)

INPUT
   list -- a list of signal semaphores

SEE ALSO
    InitSemaphore(), ReleaseSemaphoreList()


exec.library/ObtainSemaphoreShared

NAME
    ObtainSemaphoreShared -- gain shared access to a semaphore (V36)

SYNOPSIS
    ObtainSemaphoreShared(signalSemaphore)
                          a0

    void ObtainSemaphoreShared(struct SignalSemaphore *);

FUNCTION
    A lock on a signal semaphore may either be exclusive, or shared.
    Exclusive locks are granted by the ObtainSemaphore() and
    AttemptSemaphore() functions.  Shared locks are granted by
    ObtainSemaphoreShared().  Calls may be nested.

    Any number of tasks may simultaneously hold a shared lock on a
    semaphore.  Only one task may hold an exclusive lock.  A typical
    application is a list that is often read, but only occasionally
    written to.

    Any exlusive locker will be held off until all shared lockers
    release the semaphore.  Likewise, if an exlusive lock is held,
    all potential shared lockers will block until the exclusive lock
    is released.  All shared lockers are restarted at the same time.

EXAMPLE
            ObtainSemaphoreShared(ss);
            /* read data */
            ReleaseSemaohore(ss);

            ObtainSemaphore(ss);
            /* modify data */
            ReleaseSemaohore(ss);

NOTES
    While this function was added for V36, the feature magically works
    with all older semaphore structures.

    A task owning a shared lock must not attempt to get an exclusive
    lock on the same semaphore.

INPUT
    signalSemaphore -- an initialized signal semaphore structure

NOTE
    This call is guaranteed to preserve all registers, starting with
    V37 exec.

RESULT

SEE ALSO
    InitSemaphore(), ReleaseSemaphore()


exec.library/OldOpenLibrary

NAME
    OldOpenLibrary -- obsolete OpenLibrary

SYNOPSIS
    library = OldOpenLibrary(libName)
    D0                       A1

    struct Library *OldOpenLibrary(APTR);

FUNCTION
    The 1.0 release of the Amiga system had an incorrect version of
    OpenLibrary that did not check the version number during the
    library open.  This obsolete function is provided so that object
    code compiled using a 1.0 system will still run.

    This exactly the same as "OpenLibrary(libName,0L);"

INPUTS
    libName - the name of the library to open

RESULTS
    library - a library pointer for a successful open, else zero

SEE ALSO
    CloseLibrary


exec.library/OpenDevice

NAME
    OpenDevice -- gain access to a device

SYNOPSIS
    error = OpenDevice(devName, unitNumber, iORequest, flags)
    D0                 A0       D0          A1         D1

    BYTE OpenDevice(STRPTR,ULONG,struct IORequest *,ULONG);

FUNCTION
    This function opens the named device/unit and initializes the given
    I/O request block.  Specific documentation on opening procedures
    may come with certain devices.

    The device may exist in memory, or on disk; this is transparent to
    the OpenDevice caller.

    A full path name for the device name is legitimate.  For example
    "test:devs/fred.device".  This allows the use of custom devices
    without requiring the user to copy the device into the system's
    DEVS: directory.

NOTES
    All calls to OpenDevice should have matching calls to CloseDevice!

    Devices on disk cannot be opened until after DOS has been
    started.

    As of V36 tasks can safely call OpenDevice, though DOS may open
    system requesters (e.g., asking the user to insert the Workbench
    disk if DEVS: is not online).  You must call this function from a
    DOS Process if you want to turn off DOS requesters.

INPUTS
    devName - requested device name

    unitNumber - the unit number to open on that device.  The format of
            the unit number is device specific.  If the device does
            not have separate units, send a zero.

    iORequest - the I/O request block to be returned with
            appropriate fields initialized.

    flags - additional driver specific information.  This is sometimes
            used to request opening a device with exclusive access.

RESULTS
    error - Returns a sign-extended copy of the io_Error field
            of the IORequest.  Zero if successful, else an error code
            is returned.

BUGS
    AmigaDOS file names are not case sensitive, but Exec lists are.  If
    the library name is specified in a different case than it exists on
    disk, unexpected results may occur.

    Prior to V36, tasks could not make OpenDevice calls requiring disk
    access (since tasks are not allowed to make dos.library calls).
    Now OpenDevice is protected from tasks.

SEE ALSO
    CloseDevice, DoIO, SendIO, CheckIO, AbortIO, WaitIO


exec.library/OpenLibrary

NAME
    OpenLibrary -- gain access to a library

SYNOPSIS
    library = OpenLibrary(libName, version)
    D0                    A1       D0

    struct Library *OpenLibrary(STRPTR, ULONG);

FUNCTION
    This function returns a pointer to a library that was previously
    installed into the system.  If the requested library is exists, and
    if the library version is greater than or equal to the requested
    version, then the open will succeed.

    The device may exist in memory, or on disk; this is transparent to
    the OpenDevice caller.  Only Processes are allowed to call
    OpenLibrary (since OpenLibrary may in turn call dos.library).

    A full path name for the library name is legitimate.  For example
    "wp:libs/wp.library".  This allows the use of custom libraries
    without requiring the user to copy the library into the system's
    LIBS: directory.

NOTES
    All calls to OpenLibrary should have matching calls to CloseLibrary!

    Libraries on disk cannot be opened until after DOS has been
    started.

    As of V36 tasks can safely call OpenLibrary, though DOS may open
    system requesters (e.g., asking the user to insert the Workbench
    disk if LIBS: is not online).  You must call this function from a
    DOS Process if you want to turn off DOS requesters.

INPUTS
    libName - the name of the library to open

    version - the version of the library required.

RESULTS
    library - a library pointer for a successful open, else zero

BUGS
    AmigaDOS file names are not case sensitive, but Exec lists are. If
    the library name is specified in a different case than it exists on
    disk, unexpected results may occur.

    Prior to V36, tasks could not make OpenLibrary calls requiring disk
    access (since tasks are not allowed to make dos.library calls).
    Now OpenLibrary is protected from tasks.

    The version number of the resident tag in disk based library must
    match the version number of the library, or V36 may fail to load it.

SEE ALSO
    CloseLibrary


exec.library/OpenResource

NAME
    OpenResource -- gain access to a resource

SYNOPSIS
    resource = OpenResource(resName)
    D0                      A1

    APTR OpenResource(STRPTR);

FUNCTION
    This function returns a pointer to a resource that was previously
    installed into the system.

    There is no CloseResource() function.

INPUTS
   resName - the name of the resource requested.

RESULTS
    resource - if successful, a resource pointer, else NULL


exec.library/Permit

NAME
    Permit -- permit task rescheduling.

SYNOPSIS
    Permit()

    void Permit(void);

FUNCTION
    Allow other tasks to be scheduled to run by the dispatcher, after a
    matching Forbid() has been executed.

RESULTS
    Other tasks will be rescheduled as they are ready to run. In order
    to restore normal task rescheduling, the programmer must execute
    exactly one call to Permit() for every call to Forbid().

NOTE
    This call is guaranteed to preserve all registers.

SEE ALSO
    Forbid, Disable, Enable


exec.library/Procure

NAME
    Procure -- bid for a message lock (semaphore)

SYNOPSIS
    result = Procure(semaphore, bidMessage)
    D0               A0         A1

    BYTE Procure(struct Semaphore *, struct Message *);

FUNCTION
    This function is used to obtain a message based semaphore lock.  If
    the lock is immediate, Procure() returns a true result, and the
    bidMessage is not used.   If the semaphore is already locked,
    Procure() returns false, and the task must wait for the bidMessage
    to arrive at its reply port.

    Straight "Semaphores" use the message system.  They are therefore
    queueable, and users may wait on several of them at the same time.
    This makes them more powerful than "Signal Semaphores"

INPUT
    semaphore - a semaphore message port.  This port is used to queue
    all pending lockers.  This port should be initialized with the
    PA_IGNORE option, as the MP_SigTask field is used for a pointer to
    the current locker message (not a task). New semaphore ports must
    also have the SM_BIDS word initialized to -1.  If the semaphore is
    public, it should be named, its priority set, and the added with
    AddPort. Message port priority is often used for anti-deadlock
    locking conventions.

RESULT
    result - true when the semaphore is free.  In such cases no waiting
    needs to be done.  If false, then the task should wait at its
    bidMessage reply port.

BUGS
    Procure() and Vacate() do not have proven reliability.

SEE ALSO
    Vacate()


exec.library/PutMsg

NAME
    PutMsg -- put a message to a message port

SYNOPSIS
    PutMsg(port, message)
           A0    A1

    void PutMsg(struct MsgPort *, struct Message *);

FUNCTION
    This function attaches a message to the end of a given message port.
    It provides a fast, non-copying message sending mechanism.

    Messages can be attached to only one port at a time.  The message
    body can be of any size or form.  Because messages are not copied,
    cooperating tasks share the same message memory.  The sender task
    must not recycle the message until it has been replied by the
    receiver.  Of course this depends on the message handling conventions
    setup by the involved tasks.  If the ReplyPort field is non-zero,
    when the message is replied by the receiver, it will be sent back to
    that port.

    Any one of the following actions can be set to occur when a message
    is put:

            1. no special action
            2. signal a given task (specified by MP_SIGTASK)
            3. cause a software interrupt (specified by MP_SIGTASK)

    The action is selected depending on the value found in the MP_FLAGS
    of the destination port.

IMPLEMENTATION
    1.  Sets the LN_TYPE field to "NT_MESSAGE".
    2.  Attaches the message to the destination port.
    3.  Performs the specified arrival action at the destination.

INPUT
    port - pointer to a message port
    message - pointer to a message

SEE ALSO
    GetMsg, ReplyMsg, exec/ports.h


exec.library/RawDoFmt

NAME
    RawDoFmt -- format data into a character stream.

SYNOPSIS
    NextData = RawDoFmt(FormatString, DataStream, PutChProc, PutChData);
   d0                  a0            a1          a2         a3

    APTR RawDoFmt(STRPTR,APTR,void (*)(),APTR);

FUNCTION
    perform "C"-language-like formatting of a data stream, outputting
    the result a character at a time.  Where % formatting commands are
    found in the FormatString, they will be replaced with the
    corresponding element in the DataStream.  %% must be used in the
    string if a % is desired in the output.

    Under V36, RawDoFmt() returns a pointer to the end of the DataStream
    (The next argument that would have been processed).  This allows
    multiple formatting passes to be made using the same data.

INPUTS
    FormatString - a "C"-language-like NULL terminated format string,
    with the following supported % options:

     %[flags][width.limit][length]type

    flags  - only one allowed. '-' specifies left justification.
    width  - field width.  If the first character is a '0', the
             field will be padded with leading 0's.
      .    - must follow the field width, if specified
    limit  - maximum number of characters to output from a string.
             (only valid for %s).
    length - size of input data defaults to WORD for types d, x,
             and c, 'l' changes this to long (32-bit).
    type   - supported types are:
                    b - BSTR, data is 32-bit BPTR to byte count followed
                        by a byte string, or NULL terminated byte string.
                        A NULL BPTR is treated as an empty string.
                        (Added in V36 exec)
                    d - decimal
                    u - unsigned decimal (Added in V37 exec)
                    x - hexadecimal
                    s - string, a 32-bit pointer to a NULL terminated
                        byte string.  In V36, a NULL pointer is treated
                        as an empty string
                    c - character

    DataStream - a stream of data that is interpreted according to
             the format string.  Often this is a pointer into
             the task's stack.
    PutChProc  - the procedure to call with each character to be
             output, called as:

    PutChProc(Char,  PutChData);
              D0-0:8 A3

            the procedure is called with a NULL Char at the end of
            the format string.

    PutChData - a value that is passed through to the PutChProc
            procedure.  This is untouched by RawDoFmt, and may be
            modified by the PutChProc.

EXAMPLE
    ;
    ; Simple version of the C "sprintf" function.  Assumes C-style
    ; stack-based function conventions.
    ;
    ;   long eyecount;
    ;   eyecount=2;
    ;   sprintf(string,"%s have %ld eyes.","Fish",eyecount);
    ;
    ; would produce "Fish have 2 eyes." in the string buffer.
    ;
            XDEF _sprintf
            XREF _AbsExecBase
            XREF _LVORawDoFmt
    _sprintf:       ; ( ostring, format, {values} )
            movem.l a2/a3/a6,-(sp)

            move.l  4*4(sp),a3       ;Get the output string pointer
            move.l  5*4(sp),a0       ;Get the FormatString pointer
            lea.l   6*4(sp),a1       ;Get the pointer to the DataStream
            lea.l   stuffChar(pc),a2
            move.l  _AbsExecBase,a6
            jsr     _LVORawDoFmt(a6)

            movem.l (sp)+,a2/a3/a6
            rts

    ;------ PutChProc function used by RawDoFmt -----------
    stuffChar:
            move.b  d0,(a3)+        ;Put data to output string
            rts

WARNING
    This Amiga ROM function formats word values in the data stream.  If
    your compiler defaults to longs, you must add an "l" to your
    % specifications.  This can get strange for characters, which might
    look like "%lc".

    The result of RawDoFmt() is *ONLY* valid in V36 and later releases
    of EXEC.  Pre-V36 versions of EXEC have "random" return values.

SEE ALSO
    Documentation on the C language "printf" call in any C language
    reference book.


exec.library/ReleaseSemaphore

NAME
    ReleaseSemaphore -- make signal semaphore available to others

SYNOPSIS
    ReleaseSemaphore(signalSemaphore)
                     A0

    void ReleaseSemaphore(struct SignalSemaphore *);

FUNCTION
    ReleaseSemaphore() is the inverse of ObtainSemaphore(). It makes
    the semaphore lockable to other users.  If tasks are waiting for
    the semaphore and this this task is done with the semaphore then
    the next waiting task is signalled.

    Each ObtainSemaphore() call must be balanced by exactly one
    ReleaseSemaphore() call.  This is because there is a nesting count
    maintained in the semaphore of the number of times that the current
    task has locked the semaphore. The semaphore is not released to
    other tasks until the number of releases matches the number of
    obtains.

    Needless to say, havoc breaks out if the task releases more times
    than it has obtained.

INPUT
   signalSemaphore -- an initialized signal semaphore structure

NOTE
    This call is guaranteed to preserve all registers.

SEE ALSO
    InitSemaphore(), ObtainSemaphore(), ObtainSemaphoreShared()


exec.library/ReleaseSemaphoreList

NAME
    ReleaseSemaphoreList -- make a list of semaphores available

SYNOPSIS
    ReleaseSemaphoreList(list)
                         A0

    void ReleaseSemaphoreList(struct List *);

FUNCTION
    ReleaseSemaphoreList() is the inverse of ObtainSemaphoreList(). It
    releases each element in the semaphore list.

    Needless to say, havoc breaks out if the task releases more times
    than it has obtained.

INPUT
   list -- a list of signal semaphores

SEE ALSO
    ObtainSemaphoreList()


exec.library/RemDevice

NAME
    RemDevice -- remove a device from the system

SYNOPSIS
    RemDevice(device)
              A1

    void RemDevice(struct Device *);

FUNCTION
    This function calls the device's EXPUNGE vector, which requests
    that a device delete itself.  The device may refuse to do this if
    it is busy or currently open. This is not typically called by user
    code.

    There are certain, limited circumstances where it may be
    appropriate to attempt to specifically flush a certain device.
    Example:

     /* Attempts to flush the named device out of memory. */
     #include <exec/types.h>
     #include <exec/execbase.h>

     void FlushDevice(name)
     STRPTR name;
     {
     struct Device *result;

        Forbid();
        if(result=(struct Device *)FindName(&SysBase->DeviceList,name))
            RemDevice(result);
        Permit();
     }

INPUTS
    device - pointer to a device node

SEE ALSO
    AddLibrary


exec.library/RemHead

NAME
    RemHead -- remove the head node from a list

SYNOPSIS
    node = RemHead(list)
    D0             A0

    struct Node *RemHead(struct List *);

FUNCTION
    Get a pointer to the head node and remove it from the list.
    Assembly programmers may prefer to use the REMHEAD macro from
    "exec/lists.i".

WARNING
    This function does not arbitrate for access to the list.  The
    calling task must be the owner of the involved list.

INPUTS
    list - a pointer to the target list header

RESULT
    node - the node removed or zero when empty list

SEE ALSO
    AddHead, AddTail, Enqueue, Insert, Remove, RemTail


exec.library/RemIntServer

NAME
    RemIntServer -- remove an interrupt server from a server chain

SYNOPSIS
    RemIntServer(intNum, interrupt)
                 D0      A1

    void RemIntServer(ULONG,struct Interrupt *);

FUNCTION
    This function removes an interrupt server node from the given
    server chain.

    If this server was the last one on this chain, interrupts for this
    chain are disabled.

INPUTS
    intNum - the Paula interrupt bit (0..14)
    interrupt - pointer to an interrupt server node

BUGS
    Before V36 Kickstart, the feature that disables the interrupt
    would not function.  For most server chains this does not
    cause a problem.

SEE ALSO
    AddIntServer, hardware/intbits.h


exec.library/RemLibrary

NAME
    RemLibrary -- remove a library from the system

SYNOPSIS
    RemLibrary(library)
               A1

    void RemLibrary(struct Library *);

FUNCTION
    This function calls the library's EXPUNGE vector, which requests
    that a library delete itself.  The library may refuse to do this if
    it is busy or currently open. This is not typically called by user
    code.

    There are certain, limited circumstances where it may be
    appropriate to attempt to specifically flush a certain Library.
    Example:

     /* Attempts to flush the named library out of memory. */
     #include <exec/types.h>
     #include <exec/execbase.h>

     void FlushLibrary(name)
     STRPTR name;
     {
     struct Library *result;

        Forbid();
        if(result=(struct Library *)FindName(&SysBase->LibList,name))
            RemLibrary(result);
        Permit();
     }

INPUTS
    library - pointer to a library node structure


exec.library/Remove

NAME
    Remove -- remove a node from a list

SYNOPSIS
    Remove(node)
           A1

    void Remove(struct Node *);

FUNCTION
    Unlink a node from whatever list it is in.  Nodes that are not part
    of a list must not be passed to this funcion!  Assembly programmers
    may prefer to use the REMOVE macro from "exec/lists.i".

WARNING
    This function does not arbitrate for access to the list.  The
    calling task must be the owner of the involved list.

INPUTS
    node - the node to remove

SEE ALSO
    AddHead, AddTail, Enqueue, Insert, RemHead, RemTail


exec.library/RemPort

NAME
    RemPort -- remove a message port from the system

SYNOPSIS
    RemPort(port)
            A1

    void RemPort(struct MsgPort *);

FUNCTION
    This function removes a message port structure from the system's
    message port list.  Subsequent attempts to rendezvous by name with
    this port will fail.

INPUTS
    port - pointer to a message port

SEE ALSO
    AddPort, FindPort


exec.library/RemResource

NAME
    RemResource -- remove a resource from the system

SYNOPSIS
    RemResource(resource)
               A1

    void RemResource(APTR);

FUNCTION
    This function removes an existing resource from the system resource
    list.  There must be no outstanding users of the resource.

INPUTS
    resource - pointer to a resource node

SEE ALSO
    AddResource


exec.library/RemSemaphore

NAME
    RemSemaphore -- remove a signal semaphore from the system

SYNOPSIS
    RemSemaphore(signalSemaphore)
                 A1

    void RemSemaphore(struct SignalSemaphore *);

FUNCTION
    This function removes a signal semaphore structure from the
    system's signal semaphore list.  Subsequent attempts to
    rendezvous by name with this semaphore will fail.

INPUTS
   signalSemaphore -- an initialized signal semaphore structure

SEE ALSO
    AddSemaphore, FindSemaphore


exec.library/RemTail

NAME
    RemTail -- remove the tail node from a list

SYNOPSIS
    node = RemTail(list)
    D0             A0

    struct Node *RemTail(struct List *);

FUNCTION
    Remove the last node from a list, and return a pointer to it. If
    the list is empty, return zero. Assembly programmers may prefer to
    use the REMTAIL macro from "exec/lists.i".

WARNING
    This function does not arbitrate for access to the list.  The
    calling task must be the owner of the involved list.

INPUTS
    list - a pointer to the target list header

RESULT
    node - the node removed or zero when empty list

SEE ALSO
    AddHead, AddTail, Enqueue, Insert, Remove, RemHead, RemTail


exec.library/RemTask

NAME
    RemTask -- remove a task from the system

SYNOPSIS
    RemTask(task)
            A1

    void RemTask(struct Task *);

FUNCTION
    This function removes a task from the system.  Deallocation of
    resources should have been performed prior to calling this
    function.  Removing some other task is very dangerous.  Generally
    is is best to arrange for tasks to call RemTask(0L) on themselves.

    RemTask will automagically free any memory lists attached to the
    task's TC_MEMENTRY list.

INPUTS
    task - pointer to the task node representing the task to be
           removed.  A zero value indicates self removal, and will
           cause the next ready task to begin execution.

BUGS
    Before V36 if RemTask() was called on a task other than the current
    task, and that task was created with amiga.lib/CreateTask, there was
    a slight chance of a crash.  The problem can be hidden by bracketing
    RemTask() with Forbid()/Permit().

SEE ALSO
    AddTask, exec/AllocEntry, amiga.lib/DeleteTask


exec.library/ReplyMsg

NAME
    ReplyMsg -- put a message to its reply port

SYNOPSIS
    ReplyMsg(message)
             A1

    void ReplyMsg(struct Message *);

FUNCTION
    This function sends a message to its reply port.  This is usually
    done when the receiver of a message has finished and wants to
    return it to the sender (so that it can be re-used or deallocated,
    whatever).

    This call may be made from interrupts.

INPUT
    message - a pointer to the message

IMPLEMENTATION
    1> Places "NT_REPLYMSG" into LN_TYPE.
    2> Puts the message to the port specified by MN_REPLYPORT
       If there is no replyport, sets LN_TYPE to "NT_FREEMSG" (use this
       feature only with extreeme care).

SEE ALSO
    GetMsg, PutMsg, exec/ports.h


exec.library/SendIO

NAME
    SendIO -- initiate an I/O command

SYNOPSIS
    SendIO(iORequest)
           A1

    void SendIO(struct IORequest *);

FUNCTION
    This function requests the device driver start processing the given
    I/O request.  The device will return control without waiting for
    the I/O to complete.

    The io_Flags field of the IORequest will be set to zero before the
    request is sent.  See BeginIO() for more details.

INPUTS
    iORequest - pointer to an I/O request, or a device specific
                extended IORequest.

SEE ALSO
    DoIO, CheckIO, WaitIO, AbortIO


exec.library/SetExcept

NAME
    SetExcept -- define certain signals to cause exceptions

SYNOPSIS
    oldSignals = SetExcept(newSignals, signalMask)
    D0                     D0          D1

    ULONG SetExcept(ULONG,ULONG);

FUNCTION
    This function defines which of the task's signals will cause a
    private task exception.  When any of the signals occurs the task's
    exception handler will be dispatched.  If the signal occurred prior
    to calling SetExcept, the exception will happen immediately.

    The user function pointed to by the task's tc_ExceptCode gets
    called as:

        newExcptSet = <exceptCode>(signals, exceptData),SysBase
        D0                         D0       A1          A6

        signals - The set of signals that caused this exception.  These
            Signals have been disabled from the current set of signals
            that can cause an exception.

        exceptData - A copy of the task structure tc_ExceptData field.

        newExcptSet - The set of signals in NewExceptSet will be re-
            enabled for exception generation.  Usually this will be the
            same as the Signals that caused the exception.

INPUTS
    newSignals - the new values for the signals specified in
            signalMask.
    signalMask - the set of signals to be effected

RESULTS
    oldSignals - the prior exception signals

EXAMPLE
    Get the current state of all exception signals:
        SetExcept(0,0)
    Change a few exception signals:
        SetExcept($1374,$1074)

SEE ALSO
    Signal, SetSignal


exec.library/SetFunction

NAME
    SetFunction -- change a function vector in a library

SYNOPSIS
    oldFunc = SetFunction(library, funcOffset, funcEntry)
    D0                    A1       A0.W        D0

    APTR SetFunction(struct Library *,LONG,APTR);

FUNCTION
    SetFunction is a functional way of changing where vectors in a
    library point.  They are changed in such a way that the
    checksumming process will never falsely declare a library to be
    invalid.

WARNING
    If you use SetFunction on a function that can be called from
    interrupts, you are obligated to provide your own arbitration.

NOTE
    SetFunction cannot be used on non-standard libraries like pre-V36
    dos.library.  Here you must manually Forbid(), preserve all 6
    original bytes, set the new vector, SumLibrary(), then Permit().

INPUTS
    library    - a pointer to the library to be changed
    funcOffset - the offset of the function to be replaced
    funcEntry  - pointer to new function

RESULTS
    oldFunc    - pointer to the old function that was just replaced


exec.library/SetIntVector

NAME
    SetIntVector -- set a new handler for a system interrupt vector

SYNOPSIS
    oldInterrupt = SetIntVector(intNumber, interrupt)
    D0                          D0         A1

    struct Interrupt *SetIntVector(ULONG, struct Interrupt *);

FUNCTION
    This function provides a mechanism for setting the system interrupt
    vectors.  These are non-sharable; setting a new interrupt handler
    disconnects the old one.  Installed handlers are responsible for
    processing, enabling and clearing the interrupt.  Note that interrupts
    may have been left in any state by the previous code.

    The IS_CODE and IS_DATA pointers of the Interrupt structure will
    be copied into a private place by Exec.  A pointer to the previously
    installed Interrupt structure is returned.

    When the system calls the specified interrupt code, the registers are
    setup as follows:

        D0 - scratch
        D1 - scratch (on entry: active
                      interrupts -> equals INTENA & INTREQ)

        A0 - scratch (on entry: pointer to base of custom chips
                      for fast indexing)
        A1 - scratch (on entry: Interrupt's IS_DATA pointer)

        A5 - jump vector register (scratch on call)
        A6 - Exec library base pointer (scratch on call)

        all other registers must be preserved

INPUTS
    intNum - the Paula interrupt bit number (0..14).  Only non-chained
             interrupts should be set.  Use AddIntServer() for server
             chains.
    interrupt - a pointer to an Interrupt structure containing the
             handler's entry point and data segment pointer.  A NULL
             interrupt pointer will remove the current interrupt and
             set illegal values for IS_CODE and IS_DATA.

             By convention, the LN_NAME of the interrupt structure must
             point a descriptive string so that other users may
             identify who currently has control of the interrupt.

RESULT
    A pointer to the prior interrupt structure which had control
    of this interrupt.

SEE ALSO
    AddIntServer(),exec/interrupts.i,hardware/intbits.i


exec.library/SetSignal

NAME
    SetSignal -- define the state of this task's signals

SYNOPSIS
    oldSignals = SetSignal(newSignals, signalMask)
    D0                     D0          D1

    ULONG SetSignal(ULONG,ULONG);

FUNCTION
    This function can query or modify the state of the current task's
    received signal mask.  Setting the state of signals is considered
    dangerous.  Reading the state of signals is safe.

INPUTS
    newSignals - the new values for the signals specified in
                 signalSet.
    signalMask - the set of signals to be affected.

RESULTS
    oldSignals - the prior values for all signals

EXAMPLES
    Get the current state of all signals:
        SetSignal(0L,0L);
    Clear the CTRL-C signal:
        SetSignal(0L,SIGBREAKF_CTRL_C);

    Check if the CTRL-C signal was pressed:

        #include <libraries/dos.h>

        /* Check & clear CTRL_C signal */
        if(SetSignal(0L,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
            {
            printf("CTRL-C pressed!n");
            }

SEE ALSO
    Signal, Wait


exec.library/SetSR

NAME
    SetSR -- get and/or set processor status register

SYNOPSIS
    oldSR = SetSR(newSR, mask)
    D0            D0     D1

    ULONG SetSR(ULONG, ULONG);

FUNCTION
    This function provides a means of modifying the CPU status register
    in a "safe" way (well, how safe can a function like this be
    anyway?).  This function will only affect the status register bits
    specified in the mask parameter.  The prior content of the entire
    status register is returned.

INPUTS
    newSR - new values for bits specified in the mask.
        All other bits are not effected.
    mask - bits to be changed

RESULTS
    oldSR - the entire status register before new bits

EXAMPLES
    To get the current SR:
        currentSR = SetSR(0,0);
    To change the processor interrupt level to 3:
        oldSR = SetSR($0300,$0700);
    Set processor interrupts back to prior level:
        SetSR(oldSR,$0700);


exec.library/SetTaskPri

NAME
    SetTaskPri -- get and set the priority of a task

SYNOPSIS
    oldPriority = SetTaskPri(task, priority)
    D0-0:8                   A1    D0-0:8

    BYTE SetTaskPri(struct Task *,LONG);

FUNCTION
    This function changes the priority of a task regardless of its
    state.  The old priority of the task is returned.  A reschedule is
    performed, and a context switch may result.

    To change the priority of the currently running task, pass the
    result of FindTask(0); as the task pointer.

INPUTS
    task - task to be affected
    priority - the new priority for the task

RESULT
    oldPriority - the tasks previous priority


exec.library/Signal

NAME
    Signal -- signal a task

SYNOPSIS
    Signal(task, signals)
           A1    D0

    void Signal(struct Task *,ULONG);

FUNCTION
    This function signals a task with the given signals.  If the task
    is currently waiting for one or more of these signals, it will be
    made ready and a reschedule will occur. If the task is not waiting
    for any of these signals, the signals will be posted to the task
    for possible later use. A signal may be sent to a task regardless
    of whether its running, ready, or waiting.

    This function is considered "low level".  Its main purpose is to
    support multiple higher level functions like PutMsg.

    This function is safe to call from interrupts.

INPUT
    task - the task to be signalled
    signals - the signals to be sent

SEE ALSO
    Wait, SetSignal


exec.library/StackSwap

NAME
    StackSwap - EXEC supported method of replacing task's stack      (V37)

SYNOPSIS
    StackSwap(newStack)
              A0

    VOID StackSwap(struct StackSwapStruct *);

FUNCTION
    This function will, in an EXEC supported manner, swap the
    stack of your task with the given values in StackSwap.
    The StackSwapStruct structure will then contain the values
    of the old stack such that the old stack can be restored.
    This function is new in V37.

NOTE
    If you do a stack swap, only the new stack is set up.
    This function does not copy the stack or do anything else
    other than set up the new stack for the task.  It is
    generally required that you restore your stack before
    exiting.

INPUTS
    newStack - A structure that contains the values for the
            new upper and lower stack bounds and the new stack
            pointer.  This structure will have its values
            replaced by those in you task such that you can
            restore the stack later.

RESULTS
    newStack - The structure will now contain the old stack.
            This means that StackSwap(foo); StackSwap(foo);
            will effectively do nothing.

SEE ALSO
    AddTask, RemTask, exec/tasks.h


exec.library/SumKickData

NAME
    SumKickData -- compute the checksum for the Kickstart delta list

SYNOPSIS
    checksum = SumKickData()
    D0

    ULONG SumKickData(void);

FUNCTION
    The Amiga system has some ROM (or Kickstart) resident code that
    provides the basic functions for the machine.  This code is
    unchangeable by the system software.  This function is part of a
    support system to modify parts of the ROM.

    The ROM code is linked together at run time via ROMTags (also known
    as Resident structures, defined in exec/resident.h).  These tags tell
    Exec's low level boot code what subsystems exist in which regions of
    memory.  The current list of ROMTags is contained in the ResModules
    field of ExecBase.  By default this list contains any ROMTags found
    in the address ranges $F80000-$FFFFFF and $F00000-$F7FFFF.

    There is also a facility to selectively add or replace modules to the
    ROMTag list.  These modules can exist in RAM, and the memory they
    occupy will be deleted from the memory free list during the boot
    process.  SumKickData() plays an important role in this run-time
    modification of the ROMTag array.

    Three variables in ExecBase are used in changing the ROMTag array:
    KickMemPtr, KickTagPtr, and KickCheckSum. KickMemPtr points to a
    linked list of MemEntry structures. The memory that these MemEntry
    structures reference will be allocated (via AllocAbs) at boot time.
    The MemEntry structure itself must also be in the list.

    KickTagPtr points to a long-word array of the same format as the
    ResModules array.  The array has a series of pointers to ROMTag
    structures.  The array is either NULL terminated, or will have an
    entry with the most significant bit (bit 31) set.  The most
    significant bit being set says that this is a link to another
    long-word array of ROMTag entries.  This new array's address can be
    found by clearing bit 31.

    KickCheckSum has the result of SumKickData().  It is the checksum of
    both the KickMemPtr structure and the KickTagPtr arrays.  If the
    checksum does not compute correctly then both KickMemPtr and
    KickTagPtr will be ignored.

    If all the memory referenced by KickMemPtr can't be allocated then
    KickTagPtr will be ignored.

    There is one more important caveat about adding ROMTags. All this
    ROMTag magic is run very early on in the system -- before expansion
    memory is added to the system. Therefore any memory in this
    additional ROMTag area must be addressable at this time. This means
    that your ROMTag code, MemEntry structures, and resident arrays
    cannot be in expansion memory.  There are two regions of memory that
    are acceptable:  one is chip memory, and the other is "Ranger" memory
    (memory in the range between $C00000-$D80000).

    Remember that changing an existing ROMTag entry falls into the
    "heavy magic" category -- be very careful when doing it.  The odd are
    that you will blow yourself out of the water.

NOTE
    SumKickData was introduced in the 1.2 release

RESULT
    Value to be stuffed into ExecBase->KickCheckSum.

WARNING
    After writing to KickCheckSum, you should push the data cache.
    This prevents potential problems with large copyback style caches.
    A call to CacheClearU will do fine.

SEE ALSO
    InitResident, FindResident


exec.library/SumLibrary

NAME
    SumLibrary -- compute and check the checksum on a library

SYNOPSIS
    SumLibrary(library)
               A1

    void SumLibrary(struct Library *);

FUNCTION
    SumLibrary computes a new checksum on a library.  It can also be
    used to check an old checksum.  If an old checksum does not match,
    and the library has not been marked as changed, then the system
    will call Alert().

    This call could also be periodically made by some future
    system-checking task.

INPUTS
    library - a pointer to the library to be changed

NOTE
    An alert will occur if the checksum fails.

SEE ALSO
    SetFunction


exec.library/SuperState

NAME
    SuperState -- enter supervisor state with user stack

SYNOPSIS
    oldSysStack = SuperState()
    D0

    APTR SuperState(void);

FUNCTION
    Enter supervisor mode while running on the user's stack. The user
    still has access to user stack variables.  Be careful though, the
    user stack must be large enough to accommodate space for all
    interrupt data -- this includes all possible nesting of interrupts.
    This function does nothing when called from supervisor state.

RESULTS
    oldSysStack - system stack pointer; save this.  It will come in
                  handy when you return to user state.  If the system
                  is already in supervisor mode, oldSysStack is zero.

SEE ALSO
    UserState/Supervisor


exec.library/Supervisor

NAME
    Supervisor -- trap to a short supervisor mode function

SYNOPSIS
    result = Supervisor(userFunc)
    Rx                   A5

    ULONG Supervisor(void *);

FUNCTION
    Allow a normal user-mode program to execute a short assembly language
    function in the supervisor mode of the processor.  Supervisor() does
    not modify or save registers; the user function has full access to the
    register set.   All rules that apply to interrupt code must be
    followed.  In addition, no system calls are permitted.  The function
    must end with an RTE instruction.

EXAMPLE
            ;Obtain the Exception Vector base.  68010 or greater only!
            MOVECtrap:      movec.l VBR,d0  ;$4e7a,$0801
                            rte

INPUTS
    userFunc - A pointer to a short assembly language function ending
               in RTE.  The function has full access to the register set.

RESULTS
    result   - Whatever values the userFunc left in the registers.

SEE ALSO
    SuperState,UserState


exec.library/TypeOfMem

NAME
    TypeOfMem -- determine attributes of a given memory address

SYNOPSIS
    attributes = TypeOfMem(address)
    D0                     A1

    ULONG TypeOfMem(void *);

FUNCTION
    Given a RAM memory address, search the system memory lists and
    return its memory attributes.  The memory attributes are similar to
    those specified when the memory was first allocated: (eg. MEMF_CHIP
    and MEMF_FAST).

    This function is usually used to determine if a particular block of
    memory is within CHIP space.

    If the address is not in known-space, a zero will be returned.
    (Anything that is not RAM, like the ROM or expansion area, will
    return zero.  Also the first few bytes of a memory area are used up
    by the MemHeader.)

INPUT
    address - a memory address

RESULT
    attributes - a long word of memory attribute flags.
    If the address is not in known RAM, zero is returned.

SEE ALSO
    AllocMem()


exec.library/UserState

NAME
    UserState -- return to user state with user stack

SYNOPSIS
    UserState(sysStack)
              D0

    void UserState(APTR);

FUNCTION
    Return to user state with user stack, from supervisor state with
    user stack.  This function is normally used in conjunction with the
    SuperState function above.

    This function must not be called from the user state.

INPUT
    sysStack - supervisor stack pointer

BUGS
    This function is broken in V33/34 Kickstart.  Fixed in V1.31 setpatch.

SEE ALSO
    SuperState/Supervisor


exec.library/Vacate

NAME
    Vacate -- release a message lock (semaphore)

SYNOPSIS
    Vacate(semaphore)
           A0

    void Vacate(struct Semaphore *);

FUNCTION
    This function releases a previously locked semaphore (see
    the Procure() function).
    If another task is waiting for the semaphore, its bidMessage
    will be sent to its reply port.

INPUT
    semaphore - the semaport message port representing the
    semaphore to be freed.

BUGS
    Procure() and Vacate() do not have proven reliability.

SEE ALSO
    Procure


exec.library/Wait

NAME
    Wait -- wait for one or more signals

SYNOPSIS
    signals = Wait(signalSet)
    D0             D0

    ULONG Wait(ULONG);

FUNCTION
    This function will cause the current task to suspend waiting for
    one or more signals.  When one or more of the specified signals
    occurs, the task will return to the ready state, and those signals
    will be cleared.

    If a signal occurred prior to calling Wait(), the wait condition will
    be immediately satisfied, and the task will continue to run without
    delay.

CAUTION
    This function cannot be called while in supervisor mode or
    interrupts!  This function will break the action of a Forbid() or
    Disable() call.

INPUT
    signalSet - The set of signals for which to wait.
                Each bit represents a particular signal.

RESULTS
    signals - the set of signals that were active


exec.library/WaitIO

NAME
    WaitIO -- wait for completion of an I/O request

SYNOPSIS
    error = WaitIO(iORequest)
    D0             A1

    BYTE WaitIO(struct IORequest *);

FUNCTION
    This function waits for the specified I/O request to complete, then
    removes it from the replyport.  If the I/O has already completed,
    this function will return immediately.

    This function should be used with care, as it does not return until
    the I/O request completes; if the I/O never completes, this
    function will never return, and your task will hang.  If this
    situation is a possibility, it is safer to use the Wait() function.
    Wait() will return return when any of a specified set of signal is
    received.  This is how I/O timeouts can be properly handled.

WARNING
    If this IORequest was "Quick" or otherwise finished BEFORE this
    call, this function drops though immediately, with no call to
    Wait().  A side effect is that the signal bit related the port may
    remain set.  Expect this.

    When removing a known complete IORequest from a port, WaitIO() is the
    preferred method.  A simple Remove() would require a Disable/Enable
    pair!

INPUTS
    iORequest - pointer to an I/O request block

RESULTS
    error - zero if successful, else an error is returned
            (a sign extended copy of io_Error).

SEE ALSO
    DoIO, SendIO, CheckIO, AbortIO


exec.library/WaitPort

NAME
    WaitPort -- wait for a given port to be non-empty

SYNOPSIS
    message = WaitPort(port)
    D0                 A0

    struct Message *WaitPort(struct MsgPort *);

FUNCTION
    This function waits for the given port to become non-empty.  If
    necessary, the Wait() function will be called to wait for the port
    signal.  If a message is already present at the port, this function
    will return immediately.  The return value is always a pointer to
    the first message queued (but it is not removed from the queue).

CAUTION
    More than one message may be at the port when this returns.  It is
    proper to call the GetMsg() function in a loop until all messages
    have been handled, then wait for more to arrive.

    To wait for more than one port, combine the signal bits from each
    port into one call to the Wait() function, then use a GetMsg() loop
    to collect any and all messages.  It is possible to get a signal
    for a port WITHOUT a message showing up.  Plan for this.

INPUT
    port - a pointer to the message port

RETURN
    message - a pointer to the first available message

SEE ALSO
    GetMsg


layers.doc

 BeginUpdate()                 LockLayers()
 BehindLayer()                 MoveLayer()
 CreateBehindHookLayer()       MoveLayerInFrontOf()
 CreateBehindLayer()           MoveSizeLayer()
 CreateUpfrontHookLayer()      NewLayerInfo()
 CreateUpfrontLayer()          ScrollLayer()
 DeleteLayer()                 SizeLayer()
 DisposeLayerInfo()            SwapBitsRastPortClipRect()
 EndUpdate()                   ThinLayerInfo()
 FattenLayerInfo()             UnlockLayer()
 InitLayers()                  UnlockLayerInfo()
 InstallClipRegion()           UnlockLayers()
 InstallLayerHook()            UpfrontLayer()
 LockLayer()                   WhichLayer()
 LockLayerInfo()


layers.library/BeginUpdate

NAME
    BeginUpdate -- Prepare to repair damaged layer.

SYNOPSIS
    result = BeginUpdate( l )
    d0                    a0

    LONG BeginUpdate( struct Layer *);

FUNCTION
    Convert damage list to ClipRect list and swap in for
    programmer to redraw through. This routine simulates
    the ROM library environment. The idea is to only render in the
    "damaged" areas, saving time over redrawing all of the layer.
    The layer is locked against changes made by the layer library.

INPUTS
    l - pointer to a layer

RESULTS
    result - TRUE if damage list converted to ClipRect list sucessfully.
             FALSE if list conversion aborted. (probably out of memory)

BUGS
    If BeginUpdate returns FALSE, programmer must abort the attempt to
    refresh this layer and instead call EndUpdate( l, FALSE ) to restore
    original ClipRect and damage list.

SEE ALSO
    EndUpdate, graphics/layers.h, graphics/clip.h


layers.library/BehindLayer

NAME
    BehindLayer -- Put layer behind other layers.

SYNOPSIS
    result = BehindLayer( dummy, l )
    d0                    a0     a1

    LONG BehindLayer( LONG, struct Layer *);

FUNCTION
    Move this layer to the most behind position swapping bits
    in and out of the display with other layers.
    If other layers are REFRESH then collect their damage lists and
    set the LAYERREFRESH bit in the Flags fields of those layers that
    may be revealed.  If this layer is a backdrop layer then
    put this layer behind all other backdrop layers.
    If this layer is NOT a backdrop layer then put in front of the
    top backdrop layer and behind all other layers.

    Note: this operation may generate refresh events in other layers
       associated with this layer's Layer_Info structure.

INPUTS
    dummy - unused
    l - pointer to a layer

RESULTS
    result - TRUE    if operation successful
             FALSE   if operation unsuccessful (probably out of memory)

BUGS

SEE ALSO
   graphics/layers.h, graphics/clip.h


layers.library/CreateBehindHookLayer

NAME                                                              (V36)
    CreateBehindHookLayer -- Create a new layer behind all existing layers,
                             using supplied callback BackFill hook.

SYNOPSIS
    result = CreateBehindHookLayer(li,bm,x0,y0,x1,y1,flags,hook,[,bm2])
    d0                             a0 a1 d0 d1 d2 d3 d4    a3   [ a2 ]

    struct Layer *CreateBehindHookLayer(struct Layer_Info *,
                  struct BitMap *, LONG, LONG, LONG,
                  LONG, LONG, struct Hook *, ... );

FUNCTION
    Create a new Layer of position and size (x0,y0)->(x1,y1)
    Make this layer of type found in flags.
    Install Layer->BackFill callback Hook.
    If SuperBitMap, use bm2 as pointer to real SuperBitMap,
    and copy contents of Superbitmap into display layer.
    If this layer is a backdrop layer then place it behind all
    other layers including other backdrop layers. If this is
    not a backdrop layer then place it behind all nonbackdrop
    layers.

    Note: when using SUPERBITMAP, you should also set LAYERSMART flag.

INPUTS
    li - pointer to LayerInfo structure
    bm - pointer to common BitMap used by all Layers
    x0,y0 - upper left hand corner of layer
    x1,y1 - lower right hand corner of layer
    flags - various types of layers supported as bit sets.
            (for bit definitions, see graphics/layers.h )
    hook -  Layer->BackFill callback Hook which will be called
            with object == (struct RastPort *) result->RastPort
            and message == [ (Layer *) layer, (struct Rectangle) bounds,
                           (WORD) offsetx, (WORD) offsety ]
    bm2 - pointer to optional Super BitMap

RESULTS
    result - pointer to Layer structure if successful
             NULL if not successful

BUGS

SEE ALSO
    DeleteLayer, graphics/layers.h, graphics/clip.h, graphics/gfx.h
    utility/hooks.h


layers.library/CreateBehindLayer

NAME
    CreateBehindLayer -- Create a new layer behind all existing layers.

SYNOPSIS
    result = CreateBehindLayer(li,bm,x0,y0,x1,y1,flags [,bm2])
    d0                         a0 a1 d0 d1 d2 d3   d4  [ a2 ]

    struct Layer *CreateBehindLayer(struct Layer_Info *, struct BitMap *,
        LONG, LONG, LONG, LONG, LONG, ... );

FUNCTION
    Create a new Layer of position and size (x0,y0)->(x1,y1)
    Make this layer of type found in flags.
    If SuperBitMap, use bm2 as pointer to real SuperBitMap,
    and copy contents of Superbitmap into display layer.
    If this layer is a backdrop layer then place it behind all
    other layers including other backdrop layers. If this is
    not a backdrop layer then place it behind all nonbackdrop
    layers.

    Note: when using SUPERBITMAP, you should also set LAYERSMART flag.

INPUTS
    li - pointer to LayerInfo structure
    bm - pointer to common BitMap used by all Layers
    x0,y0 - upper left hand corner of layer
    x1,y1 - lower right hand corner of layer
    flags - various types of layers supported as bit sets.
            (for bit definitions, see graphics/layers.h )
    bm2 - pointer to optional Super BitMap

RESULTS
    result - pointer to Layer structure if successful
             NULL if not successful

BUGS

SEE ALSO
    DeleteLayer, graphics/layers.h, graphics/clip.h, graphics/gfx.h


layers.library/CreateUpfrontHookLayer

NAME                                                              (V36)
    CreateUpfrontHookLayer -- Create a new layer on top of existing layers,
                              using supplied callback BackFill hook.

SYNOPSIS
    result = CreateUpfrontHookLayer(li,bm,x0,y0,x1,y1,flags,hook,[,bm2])
    d0                              a0 a1 d0 d1 d2 d3   d4  a3   [ a2 ]

    struct Layer *CreateUpfrontHookLayer(struct Layer_Info *,
                  struct BitMap *, LONG, LONG, LONG,
                  LONG, LONG, struct Hook *, ... );

FUNCTION
    Create a new Layer of position and size (x0,y0)->(x1,y1)
    and place it on top of all other layers.
    Make this layer of type found in flags
    Install Layer->BackFill callback hook.
    if SuperBitMap, use bm2 as pointer to real SuperBitMap.
    and copy contents of Superbitmap into display layer.

    Note: when using SUPERBITMAP, you should also set LAYERSMART flag.

INPUTS
    li - pointer to LayerInfo structure
    bm - pointer to common BitMap used by all Layers
    x0,y0 - upper left hand corner of layer
    x1,y1 - lower right hand corner of layer
    flags - various types of layers supported as bit sets.
    hook -  Layer->BackFill callback Hook which will be called
            with object == (struct RastPort *) result->RastPort
            and message == [ (Layer *) layer, (struct Rectangle) bounds,
                           (WORD) offsetx, (WORD) offsety ]
    bm2 - pointer to optional Super BitMap

RESULTS
    result - pointer to Layer structure if successful
             NULL if not successful

BUGS

SEE ALSO
   DeleteLayer, graphics/layers.h, graphics/clip.h, graphics/gfx.h
    utility/hooks.h


layers.library/CreateUpfrontLayer

NAME
    CreateUpfrontLayer -- Create a new layer on top of existing layers.

SYNOPSIS
    result = CreateUpfrontLayer(li,bm,x0,y0,x1,y1,flags [,bm2])
    d0                          a0 a1 d0 d1 d2 d3   d4  [ a2 ]

    struct Layer *CreateUpfrontLayer(struct Layer_Info *, struct BitMap *,
        LONG, LONG, LONG, LONG, LONG, ... );

FUNCTION
    Create a new Layer of position and size (x0,y0)->(x1,y1)
    and place it on top of all other layers.
    Make this layer of type found in flags
    if SuperBitMap, use bm2 as pointer to real SuperBitMap.
    and copy contents of Superbitmap into display layer.

    Note: when using SUPERBITMAP, you should also set LAYERSMART flag.

INPUTS
    li - pointer to LayerInfo structure
    bm - pointer to common BitMap used by all Layers
    x0,y0 - upper left hand corner of layer
    x1,y1 - lower right hand corner of layer
    flags - various types of layers supported as bit sets.
    bm2 - pointer to optional Super BitMap

RESULTS
    result - pointer to Layer structure if successful
             NULL if not successful

BUGS

SEE ALSO
   DeleteLayer, graphics/layers.h, graphics/clip.h, graphics/gfx.h


layers.library/DeleteLayer

NAME
    DeleteLayer -- delete layer from layer list.

SYNOPSIS
    result = DeleteLayer( dummy, l )
    d0                    a0,    a1

    LONG DeleteLayer( LONG, struct Layer *);

FUNCTION
    Remove this layer from the list of layers.  Release memory
    associated with it.  Restore other layers that may have been
    obscured by it.  Trigger refresh in those that may need it.
    If this is a superbitmap layer make sure SuperBitMap is current.
    The SuperBitMap is not removed from the system but is available
    for program use even though the rest of the layer information has
    been deallocated.

INPUTS
    dummy - unused
    l - pointer to a layer

RESULTS
    result - TRUE if this layer successfully deleted from the system
             FALSE if layer not deleted. (probably out of memory )

BUGS

SEE ALSO
    graphics/layers.h, graphics/clip.h


layers.library/DisposeLayerInfo

NAME
    DisposeLayerInfo -- Return all memory for LayerInfo to memory pool

SYNOPSIS
    DisposeLayerInfo( li )
                      a0

    void DisposeLayerInfo( struct Layer_Info *);

FUNCTION
    return LayerInfo and any other memory attached to this LayerInfo
    to memory allocator.

    Note: if you wish to delete the layers associated with this Layer_Info
        structure, remember to call DeleteLayer() for each of the layers
        before calling DisposeLayerInfo().

INPUTS
    li - pointer to LayerInfo structure

EXAMPLE

    --delete the layers associated this Layer_Info structure--

    DeleteLayer(li,simple_layer);
    DeleteLayer(li,smart_layer);

    --see documentation on DeleteLayer about deleting SuperBitMap layers--
    my_super_bitmap_ptr = super_layer->SuperBitMap;
    DeleteLayer(li,super_layer);

    --now dispose of the Layer_Info structure itself--
    DisposeLayerInfo(li);

BUGS

SEE ALSO
    DeleteLayer, graphics/layers.h


layers.library/EndUpdate

NAME
    EndUpdate -- remove damage list and restore state of layer to normal.

SYNOPSIS
    EndUpdate( l, flag )
               a0  d0

    void EndUpdate( struct Layer *, UWORD);

FUNCTION
    After the programmer has redrawn his picture he calls this
    routine to restore the ClipRects to point to his standard
    layer tiling. The layer is then unlocked for access by the
    layer library.

    Note: use flag = FALSE if you are only making a partial update.
        You may use the other region functions (graphics functions such as
        OrRectRegion, AndRectRegion, and XorRectRegion ) to clip adjust
        the DamageList to reflect a partial update.

INPUTS
    l - pointer to a layer
    flag - use TRUE if update was completed. The damage list is cleared.
           use FALSE if update not complete. The damage list is retained.

EXAMPLE

    -- begin update for first part of two-part refresh --
    BeginUpdate(my_layer);

    -- do some refresh, but not all --
    my_partial_refresh_routine(my_layer);

    -- end update, false (not completely done refreshing yet) --
    EndUpdate(my_layer, FALSE);

    -- begin update for last part of refresh --
    BeginUpdate(my_layer);

    -- do rest of refresh --
    my_complete_refresh_routine(my_layer);

    -- end update, true (completely done refreshing now) --
    EndUpdate(my_layer, TRUE);

BUGS

SEE ALSO
    BeginUpdate, graphics/layers.h, graphics/clip.h


layers.library/FattenLayerInfo

NAME
    FattenLayerInfo -- convert 1.0 LayerInfo to 1.1 LayerInfo
    OBSOLETE OBSOLETE OBSOLETE OBSOLETE OBSOLETE

SYNOPSIS
    OBSOLETE OBSOLETE OBSOLETE OBSOLETE OBSOLETE
    FattenLayerInfo( li )
                     a0

    LONG FattenLayerInfo( struct Layer_Info *);
    OBSOLETE OBSOLETE OBSOLETE OBSOLETE OBSOLETE

FUNCTION
    V1.1 software and any later releases need to have more info in the
    Layer_Info structure. To do this in a 1.0 supportable manner requires
    allocation and deallocation of the memory whenever most
    layer library functions are called.  To prevent unnecessary
    allocation/deallocation FattenLayerInfo will preallocate the
    necessary data structures and fake out the layer library into
    thinking it has a LayerInfo gotten from NewLayerInfo.
    NewLayerInfo is the approved method for getting this structure.
    When a program needs to give up the LayerInfo structure it
    must call ThinLayerInfo before freeing the memory. ThinLayerInfo
    is not necessary if New/DisposeLayerInfo are used however.

INPUTS
    li - pointer to LayerInfo structure

BUGS

SEE ALSO

    NewLayerInfo, ThinLayerInfo, DisposeLayerInfo, graphics/layers.h


layers.library/InitLayers

NAME
    InitLayers -- Initialize Layer_Info structure
    OBSOLETE OBSOLETE OBSOLETE OBSOLETE OBSOLETE

SYNOPSIS
    OBSOLETE OBSOLETE OBSOLETE OBSOLETE OBSOLETE
    InitLayers( li )
                a0

    void InitLayers( struct Layer_Info *);
    OBSOLETE OBSOLETE OBSOLETE OBSOLETE OBSOLETE

FUNCTION
    Initialize Layer_Info structure in preparation to use
    other layer operations on this list of layers.
    Make the Layers unlocked (open), available to layer operations.

INPUTS
    li - pointer to LayerInfo structure

BUGS

SEE ALSO
    NewLayerInfo, DisposeLayerInfo, graphics/layers.h


layers.library/InstallClipRegion

NAME
    InstallClipRegion -- Install clip region in layer

SYNOPSIS
    oldclipregion = InstallClipRegion( l,  region )
    d0                                 a0  a1

    struct Region *InstallClipRegion( struct Layer *, struct Region *);

FUNCTION
    Installs a transparent Clip region in the layer. All
    subsequent graphics calls will be clipped to this region.
    You MUST remember to call InstallClipRegion(l,NULL) before
    calling DeleteLayer(l) or the Intuition function CloseWindow()
    if you have installed a non-NULL ClipRegion in l.

INPUTS
    l - pointer to a layer
    region - pointer to a region

RESULTS
    oldclipregion - The pointer to the previous ClipRegion that
        was installed. Returns NULL if no previous ClipRegion installed.

        Note: If the system runs out of memory while computing the
            resulting ClipRects the LAYERS_CLIPRECTS_LOST bit will
            be set in l->Flags.

BUGS
    If the system runs out of memory during normal layer operations,
    the ClipRect list may get swept away and not restored.
    As soon as there is enough memory and the layer library
    gets called again the ClipRect list will be rebuilt.

SEE ALSO
    BeginUpdate EndUpdate,
    graphics/layers.h, graphics/clip.h, graphics/regions.h


layers.library/InstallLayerHook

NAME                                                              (V36)
    InstallLayerHook -- safely install a new Layer->BackFill hook.

SYNOPSIS
    oldhook = InstallLayerHook( layer, hook )
    d0                          a0     a1

    struct Hook *InstallLayerHook( struct Layer *, struct Hook *);

FUNCTION
    Installs a new Layer->Backfill Hook, waiting until it is safe to do
    so. Locks the layer while substituting the new Hook and removing the
    old one. If a new Hook is not provided, will install the default layer
    BackFill Hook.

INPUTS
    layer - pointer to the layer in which to install the Backfill Hook.
    hook -  pointer to layer callback Hook which will be called
            with object == (struct RastPort *) result->RastPort
            and message == [ (Layer *) layer, (struct Rectangle) bounds,
                           (WORD) offsetx, (WORD) offsety ]

            This hook should fill the Rectangle in the RastPort
            with the BackFill pattern appropriate for offset x/y.

            If this hook pointer is NULL, the function installs
            the "default" Layers BackFill Hook into this Layer.

RESULTS
    oldhook - pointer to the Layer->BackFill Hook that was previously
              active.

BUGS

SEE ALSO
    graphics/clip.h utility/hooks.h


layers.library/LockLayer

NAME
    LockLayer -- Lock layer to make changes to ClipRects.

SYNOPSIS
    LockLayer( dummy, l )
               a0     a1

    void LockLayer( LONG, struct Layer *);

FUNCTION
    Make this layer unavailable for other tasks to use.
    If another task is already using this layer then wait for
    it to complete and then reserve the layer for your own use.
    (this function does the same thing as graphics.library/LockLayerRom)

    Note: if you wish to lock MORE THAN ONE layer at a time, you
        must call LockLayerInfo() before locking those layers and
        then call UnlockLayerInfo() when you have finished. This
        is to prevent system "deadlocks".

    Further Note: while you hold the lock on a layer, Intuition will block
        on operations such as windowsizing, dragging, menus, and depth
        arranging windows in this layer's screen.  It is recommended that
        YOU do not make Intuition function calls while the layer is locked.

INPUTS
    dummy - unused
    l - pointer to a layer

BUGS

SEE ALSO
    UnlockLayer, LockLayerInfo, UnlockLayerInfo,
    graphics.library/LockLayerRom, graphics/layers.h, graphics/clip.h


layers.library/LockLayerInfo

NAME
    LockLayerInfo -- Lock the LayerInfo structure.

SYNOPSIS
    LockLayerInfo( li )
                   a0

    void LockLayerInfo( struct Layer_Info *);

FUNCTION
    Before doing an operation that requires the LayerInfo
    structure, make sure that no other task is also using the
    LayerInfo structure.  LockLayerInfo() returns when the
    LayerInfo belongs to this task.  There should be
    an UnlockLayerInfo for every LockLayerInfo.

    Note: All layer routines presently LockLayerInfo() when they
    start up and UnlockLayerInfo() as they exit.  Programmers
    will need to use these Lock/Unlock routines if they wish
    to do something with the LayerStructure that is not
    supported by the layer library.

INPUTS
    li - pointer to Layer_Info structure

BUGS

SEE ALSO
    UnlockLayerInfo, graphics/layers.h


layers.library/LockLayers

NAME
    LockLayers -- lock all layers from graphics output.

SYNOPSIS
    LockLayers( li )
                a0

    void LockLayers( struct Layer_Info *);

FUNCTION
    First calls LockLayerInfo()
    Make all layers in this layer list locked.

INPUTS
    li - pointer to Layer_Info structure

BUGS

SEE ALSO
    LockLayer, LockLayerInfo, graphics/layers.h


layers.library/MoveLayer

NAME
    MoveLayer -- Move layer to new position in BitMap.

SYNOPSIS
    result = MoveLayer( dummy, l, dx, dy )
    d0                  a0     a1 d0  d1

    LONG MoveLayer( LONG, struct Layer *, LONG, LONG);

FUNCTION
    Move this layer to new position in shared BitMap.
    If any refresh layers become revealed, collect damage and
    set REFRESH bit in layer Flags.

INPUTS
    dummy - unused
    l - pointer to a nonbackdrop layer
    dx - delta to add to current x position
    dy - delta to add to current y position

RETURNS
    result - TRUE if operation successful
             FALSE if failed (out of memory)

BUGS
    May not handle (dx,dy) which attempts to move the layer ouside the
    layer's RastPort->BitMap bounds .

SEE ALSO
    graphics/layers.h, graphics/clip.h


layers.library/MoveLayerInFrontOf

NAME
    MoveLayerInFrontOf -- Put layer in front of another layer.

SYNOPSIS
    result = MoveLayerInFrontOf( layertomove, targetlayer )
                                a0           a1

    LONG MoveLayerInFrontOf( struct Layer *, struct Layer *);

FUNCTION
    Move this layer in front of target layer, swapping bits
    in and out of the display with other layers.
    If this is a refresh layer then collect damage list and
    set the LAYERREFRESH bit in layer->Flags if redraw required.

    Note: this operation may generate refresh events in other layers
        associated with this layer's Layer_Info structure.

INPUTS
    layertomove - pointer to layer which should be moved
    targetlayer - pointer to target layer in front of which to move layer

RESULTS
    result = TRUE    if operation successful
             FALSE   if operation unsuccessful (probably out of memory)

BUGS

SEE ALSO
    graphics/layers.h


layers.library/MoveSizeLayer

NAME                                                              (V36)
    MoveSizeLayer -- Position/Size layer

SYNOPSIS
    result = MoveSizeLayer( layer, dx, dy, dw, dh )
    d0                      a0     d0  d1  d2  d3

    LONG MoveSizeLayer( struct Layer *, LONG, LONG, LONG, LONG);

FUNCTION
    Change upperleft and lower right position of Layer.

INPUTS
    dummy - unused
    l - pointer to a nonbackdrop layer
    dx,dy - change upper left corner by (dx,dy)
    dw,dy - change size by (dw,dh)

RETURNS
    result - TRUE if operation successful
             FALSE if failed (due to out of memory)
             FALSE if failed (due to illegal layer->bounds)

BUGS

SEE ALSO
    graphics/layers.h, graphics/clip.h


layers.library/NewLayerInfo

NAME
    NewLayerInfo -- Allocate and Initialize full Layer_Info structure.

SYNOPSIS
    result = NewLayerInfo()
    d0

    struct Layer_Info *NewLayerInfo( void );

FUNCTION
    Allocate memory required for full Layer_Info structure.
    Initialize Layer_Info structure in preparation to use
    other layer operations on this list of layers.
    Make the Layer_Info unlocked (open).

INPUTS
    None

RESULT
    result- pointer to Layer_Info structure if successful
            NULL if not enough memory

BUGS

SEE ALSO
    graphics/layers.h


layers.library/ScrollLayer

NAME
    ScrollLayer -- Scroll around in a superbitmap, translate coordinates
                  in non-superbitmap layer.

SYNOPSIS
    ScrollLayer( dummy, l, dx, dy )
                 a0     a1 d0  d1

    void ScrollLayer( LONG, struct Layer *, LONG, LONG);

FUNCTION
    For a SuperBitMap Layer:
    Update the SuperBitMap from the layer display, then copy bits
    between Layer and SuperBitMap to reposition layer over different
    portion of SuperBitMap.
    For nonSuperBitMap layers, all (x,y) pairs are adjusted by
    the scroll(x,y) value in the layer.  To cause (0,0) to actually
    be drawn at (3,10) use ScrollLayer(-3,-10). This can be useful
    along with InstallClipRegion to simulate Intuition GZZWindows
    without the overhead of an extra layer.

INPUTS
    dummy - unused
    l - pointer to a layer
    dx - delta to add to current x scroll value
    dy - delta to add to current y scroll value

BUGS
    May not handle (dx,dy) which attempts to move the layer ouside the
    layer's SuperBitMap bounds.

SEE ALSO
    graphics/layers.h


layers.library/SizeLayer

NAME
    SizeLayer -- Change the size of this nonbackdrop layer.

SYNOPSIS
    result = SizeLayer( dummy, l, dx, dy )
    d0                  a0     a1 d0  d1

    LONG SizeLayer( LONG, struct Layer *, LONG, LONG);

FUNCTION
    Change the size of this layer by (dx,dy). The lower right hand
    corner is extended to make room for the larger layer.
    If there is SuperBitMap for this layer then copy pixels into
    or out of the layer depending on whether the layer increases or
    decreases in size.  Collect damage list for those layers that may
    need to be refreshed if damage occurred.

INPUTS
    dummy - unused
    l - pointer to a nonbackdrop layer
    dx - delta to add to current x size
    dy - delta to add to current y size

RESULTS
    result - TRUE if operation successful
             FALSE if failed (out of memory)

BUGS

SEE ALSO
    graphics/layers.h, graphics/clip.h


layers.library/SwapBitsRastPortClipRect

NAME
    SwapBitsRastPortClipRect -- Swap bits between common bitmap
                                and obscured ClipRect

SYNOPSIS
    SwapBitsRastPortClipRect( rp, cr )
                              a0  a1

    void SwapBitsRastPortClipRect( struct RastPort *, struct ClipRect *);

FUNCTION
    Support routine useful for those that need to do some
    operations not done by the layer library.  Allows programmer
    to swap the contents of a small BitMap with a subsection of
    the display. This is accomplished without using extra memory.
    The bits in the display RastPort are exchanged with the
    bits in the ClipRect's BitMap.

    Note: the ClipRect structures which the layer library allocates are
    actually a little bigger than those described in the graphics/clip.h
    include file.  So be warned that it is not a good idea to have
    instances of cliprects in your code.

INPUTS
    rp - pointer to rastport
    cr - pointer to cliprect to swap bits with

NOTE
    Because the blit operation started by this function is done
    asynchronously, it is imperative that a WaitBlit() be performed before
    releasing or using the processor to modify any of the associated
    structures.

BUGS

SEE ALSO
    graphics/clip.h, graphics/rastport.h, graphics/clip.h


layers.library/ThinLayerInfo

NAME
    ThinLayerInfo -- convert 1.1 LayerInfo to 1.0 LayerInfo.
    OBSOLETE OBSOLETE OBSOLETE OBSOLETE OBSOLETE

SYNOPSIS
    OBSOLETE OBSOLETE OBSOLETE OBSOLETE OBSOLETE
    ThinLayerInfo( li )
                   a0

    void ThinLayerInfo( struct Layer_Info *);
    OBSOLETE OBSOLETE OBSOLETE OBSOLETE OBSOLETE

FUNCTION
    return the extra memory needed that was allocated with
    FattenLayerInfo. This is must be done prior to freeing
    the Layer_Info structure itself. V1.1 software should be
    using DisposeLayerInfo.

INPUTS
    li - pointer to LayerInfo structure

BUGS

SEE ALSO
    DisposeLayerInfo, FattenLayerInfo, graphics/layers.h


layers.library/UnlockLayer

NAME
    UnlockLayer -- Unlock layer and allow graphics routines to use it.

SYNOPSIS
    UnlockLayer( l )
                 a0

    void UnlockLayer( struct Layer *);

FUNCTION
    When finished changing the ClipRects or whatever you were
    doing with this layer you must call UnlockLayer() to allow
    other tasks to proceed with graphic output to the layer.

INPUTS
    l - pointer to a layer

BUGS

SEE ALSO
    graphics/layers.h, graphics/clip.h


layers.library/UnlockLayerInfo

NAME
    UnlockLayerInfo -- Unlock the LayerInfo structure.

SYNOPSIS
    UnlockLayerInfo( li )
                     a0

    void UnlockLayerInfo( struct Layer_Info *);

FUNCTION
    After the operation is complete that required a LockLayerInfo,
    unlock the LayerInfo structure so that  other tasks may
    affect the layers.

INPUTS
    li - pointer to the Layer_Info structure

 BUGS

 SEE ALSO
    LockLayerInfo, graphics/layers.h


layers.library/UnlockLayers

NAME
    UnlockLayers -- Unlock all layers from graphics output.
                    Restart graphics output to layers that have been
                    waiting

SYNOPSIS
    UnlockLayers( li )
                  a0

    void UnlockLayers( struct Layer_Info *);

FUNCTION
    Make all layers in this layer list unlocked.
    Then call UnlockLayerInfo

INPUTS
    li - pointer to the Layer_Info structure

BUGS

SEE ALSO
    LockLayers, UnlockLayer, graphics/layers.h


layers.library/UpfrontLayer

NAME
    UpfrontLayer -- Put layer in front of all other layers.

SYNOPSIS
    result = UpfrontLayer( dummy, l )
    d0                     a0     a1

    LONG UpfrontLayer( LONG, struct Layer *);

FUNCTION
    Move this layer to the most upfront position swapping bits
    in and out of the display with other layers.
    If this is a refresh layer then collect damage list and
    set the LAYERREFRESH bit in layer->Flags if redraw required.
    By clearing the BACKDROP bit in the layers Flags you may
    bring a Backdrop layer up to the front of all other layers.

    Note: this operation may generate refresh events in other layers
       associated with this layer's Layer_Info structure.

INPUTS
    dummy - unused
    l - pointer to a nonbackdrop layer

RESULTS
    result - TRUE   if operation successful
             FALSE  if operation unsuccessful (probably out of memory)

BUGS

SEE ALSO
    graphics/layers.h


layers.library/WhichLayer

NAME
    WhichLayer -- Which Layer is this point in?

SYNOPSIS
    layer = WhichLayer( li, x, y )
    d0                  a0  d0 d1

    struct Layer *WhichLayer(struct Layer_Info*, WORD, WORD);

FUNCTION
    Starting at the topmost layer check to see if this point (x,y)
        occurs in this layer.  If it does return the pointer to this
        layer. Return NULL if there is no layer at this point.

INPUTS
    li  = pointer to LayerInfo structure
    (x,y) = coordinate in the BitMap

RESULTS
    layer - pointer to the topmost layer that this point is in
            NULL if this point is not in a layer

SEE ALSO
    graphics/layers.h


translator.doc

 Translate()


translator.library/Translate

NAME
    Translate -- Convert an English string into narrator device phonemes.

SYNOPSIS
    rtnCode = Translate(inString, inLength, outBuffer, outLength)
    D0                  A0        D0        A1         D1

    LONG Translate( STRPTR inString, LONG inLength, STRPTR outBuffer,
                    LONG outlen );

FUNCTION
    The translate function converts an English string into
    a string of phonetic codes suitable as input to the
    narrator device.

INPUTS
    inString  - pointer to English string
    inLength  - length of English string
    outBuffer - a char array which will hold the phonetic codes
    outLength - the length of the output array

RESULTS
    rtnCode - zero if no error has occured.
              The only error that can occur is overflowing the outBuffer.
              If Translate() determines that an overflow will occur, it
              will stop the translation at a word boundary before the
              overflow happens.  If this occurs, rtnCode will be a
              negative number whose absolute value indicates where in
              inString Translate() stopped.  The user can then use the
              offset -rtnCode from the beginning of inString in a
              subsequent Translate() call to continue the translation.

SEE ALSO
    narrator.device/CMD_WRITE


expansion.doc

 AddBootNode()           FindConfigDev()           ReadExpansionByte()
 AddConfigDev()          FreeConfigDev()           ReadExpansionRom()
 AddDosNode()            FreeExpansionMem()        ReleaseConfigBinding()
 AllocConfigDev()        GetCurrentBinding()       RemConfigDev()
 AllocExpansionMem()     MakeDosNode()             SetCurrentBinding()
 ConfigBoard()           ObtainConfigBinding()     WriteExpansionByte()


expansion.library/AddBootNode

NAME
    AddBootNode -- Add a BOOTNODE to the system (V36)

SYNOPSIS
    ok = AddBootNode( bootPri, flags, deviceNode, configDev )
    D0                D0       D1     A0          A1

    BOOL AddBootNode( BYTE,ULONG,struct DeviceNode *,struct ConfigDev * );

FUNCTION
    This function will do one of two things:

            1> If dos is running, add a new disk type device immediatly.
            2> If dos is not yet running, save information for later
               use by the system.

FUNCTION
    This routine makes sure that your disk device (or a device
    that wants to be treated as if it was a disk...) will be
    entered into the system.  If the dos is already up and
    running, then it will be entered immediately.  If the dos
    has not yet been run then the data will be recorded, and the
    dos will get it later.

    We try and boot off of each device in turn, based on priority.
    Floppies have a hard-coded priority.

    There is only one additional piece of magic done by AddBootNode.
    If there is no executable code specified in the deviceNode
    structure (e.g. dn_SegList, dn_Handler, and dn_Task are all
    null) then the standard dos file handler is used for your
    device.

    Documentation note: a "task" as used here is a dos-task, not
    an exec-task.  A dos-task, in the strictest sense, is the
    address of an exec-style message port.  In general, it is
    a pointer to a process's pr_MsgPort field (e.g. a constant
    number of bytes after an exec task).

    Autoboot from an expansion card before DOS is running requires
    the card's ConfigDev structure.

    Pass a NULL ConfigDev pointer to create a non-bootable node.

INPUTS
    bootPri -- a BYTE quantity with the boot priority for this disk.
        This priority is only for which disks should be looked at:
        the actual disk booted from will be the first disk with
        a valid boot block.  If no disk is found then the "bootme"
        hand will come up and the bootstrap code will wait for
        a floppy to be inserted.  Recommend priority assignments are:

            +5   -- unit zero for the floppy disk.  The floppy should
                    always be highest priority to allow the user to
                    abort out of a hard disk boot.
             0   -- the run of the mill hard disk
            -5   -- a "network" disk (local disks should take priority).
            -128 -- don't even bother to boot from this device.

    flags -- additional flag bits for the call:
        ADNF_STARTPROC (bit 0) -- start a handler process immediately.
            Normally the process is started only when the device node
            is first referenced.  This bit is meaningless if you
            have already specified a handler process (non-null dn_Task).

    deviceNode -- a legal DOS device node, properly initialized.
            Typically this will be the result of a MakeDosNode().
            Special cases may require a custom-built device node.

    configDev -- a valid board's ConfigDev stucture.  This is required
            for autoboot before DOS is running and if left NULL will
            result in an non-bootable node.

RESULTS
    ok - non-zero everything went ok, zero if we ran out of memory
        or some other weirdness happened.

NOTE
    This function eliminates the need to manually Enqueue a BOOTNODE
    onto an expansion.library list.  Be sure V36 expansion.library is
    available before calling this function!

SEE ALSO
    AddDosNode


expansion.library/AddConfigDev

NAME
    AddConfigDev - add a new ConfigDev structure to the system

SYNOPSIS
    AddConfigDev( configDev )
                  A0

FUNCTION
    (Not typically called by user code)

    This routine adds the specified ConfigDev structure to the
    list of Configuration Devices in the system.

INPUTS
    configDev - a valid ConfigDev structure.

RESULTS

EXCEPTIONS

SEE ALSO
    RemConfigDev

BUGS


expansion.library/AddDosNode

NAME
    AddDosNode -- mount a disk to the system

SYNOPSIS
    ok = AddDosNode( bootPri, flags, deviceNode )
    D0               D0       D1     A0

    BOOL AddDosNode( BYTE,ULONG,struct DeviceNode *);

FUNCTION
    This is the old (pre V36) function that works just like
    AddBootNode().  It should only be used if you *MUST* work
    in a 1.3 system and you don't need to autoboot.

RESULTS
    ok - non-zero everything went ok, zero if we ran out of memory
        or some other weirdness happened.

EXAMPLE
    /* enter a bootable disk into the system.  Start a file handler
    ** process immediately.
    */
    if(  AddDosNode( 0, ADNF_STARTPROC, MakeDosNode( paramPacket ) )  )
            ...AddDosNode ok...

BUGS
    Before V36 Kickstart, no function existed to add BOOTNODES.
    If an older expansion.library is in use, driver code will need
    to manually construct a BootNode and Enqueue() it to eb_Mountlist.
    If you have a V36 or better expansion.library, your code should
    use AddBootNode().

SEE ALSO
    MakeDosNode, AddBootNode


expansion.library/AllocConfigDev

NAME
    AllocConfigDev - allocate a ConfigDev structure

SYNOPSIS
    configDev = AllocConfigDev()
    D0

FUNCTION
    This routine returns the address of a ConfigDev structure.
    It is provided so new fields can be added to the structure
    without breaking old, existing code.  The structure is cleared
    when it is returned to the user.

INPUTS

RESULTS
    configDev - either a valid ConfigDev structure or NULL.

EXCEPTIONS

SEE ALSO
    FreeConfigDev

BUGS


expansion.library/AllocExpansionMem

NAME
    AllocExpansionMem - allocate expansion memory

SYNOPSIS
    startSlot = AllocExpansionMem( numSlots, slotOffset )
    D0                             D0        D1

FUNCTION
    (Not typically called by user code)

    This function allocates numslots of expansion space (each slot
    is E_SLOTSIZE bytes).  It returns the slot number of the
    start of the expansion memory.  The EC_MEMADDR macro may be
    used to convert this to a memory address.

    Boards that fit the expansion architecture have alignment
    rules.  Normally a board must be on a binary boundary of its
    size.  Four and Eight megabyte boards have special rules.
    User defined boards might have other special rules.

    If AllocExpansionMem() succeeds, the startSlot will satisfy
    the following equation:

            (startSlot - slotOffset) MOD slotAlign = 0

INPUTS
    numSlots - the number of slots required.
    slotOffset - an offset from that boundary for startSlot.

RESULTS
    startSlot - the slot number that was allocated, or -1 for error.

EXAMPLES

            AllocExpansionMem( 2, 0 )

    Tries to allocate 2 slots on a two slot boundary.

            AllocExpansionMem( 64, 32 )

    This is the allocation rule for 4 meg boards.  It allocates
    4 megabytes (64 slots) on an odd 2 meg boundary.

EXCEPTIONS

SEE ALSO
    FreeExpansionMem

BUGS


expansion.library/ConfigBoard

NAME
    ConfigBoard - configure a board

SYNOPSIS
    error = ConfigBoard( board, configDev )
    D0                   A0     A1

FUNCTION
    This routine configures an expansion board.  The board
    will generally live at E_EXPANSIONBASE, but the base is
    passed as a parameter to allow future compatibility.
    The configDev parameter must be a valid configDev that
    has already had ReadExpansionRom() called on it.

    ConfigBoard will allocate expansion memory and place
    the board at its new address.  It will update configDev
    accordingly.  If there is not enough expansion memory
    for this board then an error will be returned.

INPUTS
    board - the current address that the expansion board is
            responding.
    configDev - an initialized ConfigDev structure, returned
            by AllocConfigDev.

RESULTS
    error - non-zero if there was a problem configuring this board
            (Can return EE_OK or EE_NOEXPANSION)

SEE ALSO
    FreeConfigDev


expansion.library/FindConfigDev

NAME
    FindConfigDev - find a matching ConfigDev entry

SYNOPSIS
    configDev = FindConfigDev( oldConfigDev, manufacturer, product )
    D0                         A0            D0            D1

FUNCTION
    This routine searches the list of existing ConfigDev
    structures in the system and looks for one that has
    the specified manufacturer and product codes.

    If the oldConfigDev is NULL the the search is from the
    start of the list of configuration devices.  If it is
    not null then it searches from the first configuration
    device entry AFTER oldConfigDev.

    A code of -1 is treated as a wildcard -- e.g. it matches
    any manufacturer (or product)

INPUTS
    oldConfigDev - a valid ConfigDev structure, or NULL to start
            from the start of the list.
    manufacturer - the manufacturer code being searched for, or
            -1 to ignore manufacturer numbers.
    product - the product code being searched for, or -1 to
            ignore product numbers.

RESULTS
    configDev - the next ConfigDev entry that matches the
            manufacturer and product codes, or NULL if there
            are no more matches.

EXCEPTIONS

EXAMPLES
    /* to find all configdevs of the proper type */
    struct ConfigDev *cd = NULL;

    while( cd = FindConfigDev( cd, MANUFACTURER, PRODUCT ) ) {
            /* do something with the returned ConfigDev */
    }

SEE ALSO

BUGS


expansion.library/FreeConfigDev

NAME
    FreeConfigDev - free a ConfigDev structure

SYNOPSIS
    FreeConfigDev( configDev )
                   A0

FUNCTION
    This routine frees a ConfigDev structure as returned by
    AllocConfigDev.

INPUTS
    configDev - a valid ConfigDev structure.

RESULTS

EXCEPTIONS

SEE ALSO
    AllocConfigDev

BUGS


expansion.library/FreeExpansionMem

NAME
    FreeExpansionMem - allocate standard device expansion memory

SYNOPSIS
    FreeExpansionMem( startSlot, numSlots )
                      D0         D1

FUNCTION
    (Not typically called by user code)

    This function allocates numslots of expansion space (each slot
    is E_SLOTSIZE bytes).  It is the inverse function of
    AllocExpansionMem().

INPUTS
    startSlot - the slot number that was allocated, or -1 for error.
    numSlots - the number of slots to be freed.

RESULTS

EXAMPLES

EXCEPTIONS
    If the caller tries to free a slot that is already in the
    free list, FreeExpansionMem will Alert() (e.g. crash the
    system).

SEE ALSO
    AllocExpansionMem

BUGS


expansion.library/GetCurrentBinding

NAME
    GetCurrentBinding - sets static board configuration area

SYNOPSIS
    actual = GetCurrentBinding( currentBinding, size )
                                A0              D0:16

FUNCTION
    This function writes the contents of the "currentBinding"
    structure out of a private place.  It may be set via
    SetCurrentBinding().  This is really a kludge, but it is
    the only way to pass extra arguments to a newly configured
    device.

    A CurrentBinding structure has the name of the currently
    loaded file, the product string that was associated with
    this driver, and a pointer to the head of a singly linked
    list of ConfigDev structures (linked through the cd_NextCD
    field).

    Many devices may not need this information; they have hard
    coded into themselves their manufacture number.  It is
    recommended that you at least check that you can deal with
    the product code in the linked ConfigDev structures.

INPUTS
    currentBinding - a pointer to a CurrentBinding structure

    size - The size of the user's binddriver structure.
        Do not pass in less than sizeof(struct CurrentBinding).

RESULTS
    actual - the true size of a CurrentBinding structure is returned.

SEE ALSO
    GetCurrentBinding


expansion.library/MakeDosNode

NAME
    MakeDosNode -- construct dos data structures that a disk needs

SYNOPSIS
    deviceNode = MakeDosNode( parameterPkt )
    D0                        A0

    struct DeviceNode * MakeDosNode( void * );

FUNCTION
    This routine manufactures the data structures needed to enter
    a dos disk device into the system.  This consists of a DeviceNode,
    a FileSysStartupMsg, a disk environment vector, and up to two
    bcpl strings.  See the libraries/dosextens.h and
    libraries/filehandler.h include files for more information.

    MakeDosNode will allocate all the memory it needs, and then
    link the various structure together.  It will make sure all
    the structures are long-word aligned (as required by the DOS).
    It then returns the information to the user so he can
    change anything else that needs changing.  Typically he will
    then call AddDosNode() to enter the new device into the dos
    tables.

INPUTS
    parameterPkt - a longword array containing all the information
        needed to initialize the data structures.  Normally I
        would have provided a structure for this, but the variable
        length of the packet caused problems.  The two strings are
        null terminated strings, like all other exec strings.

        longword    description
        --------    -----------
        0           string with dos handler name
        1           string with exec device name
        2           unit number (for OpenDevice)
        3           flags (for OpenDevice)
        4           # of longwords in rest of enviroment
        5-n         file handler environment (see libraries/filehandler.h)

RESULTS
    deviceNode - pointer to initialize device node structure, or
        null if there was not enough memory.  You may need to change
        certain fields before passing the DeviceNode to AddDosNode().

EXAMPLES
    /* set up a 3.5" amiga format floppy drive for unit 1 */

    char execName[] = "trackdisk.device";
    char dosName[] = "df1";

    ULONG parmPkt[] = {
        (ULONG) dosName,
        (ULONG) execName,
        1,                  /* unit number */
        0,                  /* OpenDevice flags */

        /* here is the environment block */
        16,                 /* table upper bound */
        512>>2,             /* # longwords in a block */
        0,                  /* sector origin -- unused */
        2,                  /* number of surfaces */
        1,                  /* secs per logical block -- leave as 1 */
        11,                 /* blocks per track */
        2,                  /* reserved blocks -- 2 boot blocks */
        0,                  /* ?? -- unused */
        0,                  /* interleave */
        0,                  /* lower cylinder */
        79,                 /* upper cylinder */
        5,                  /* number of buffers */
        MEMF_CHIP,          /* type of memory for buffers */
        (~0 >> 1),          /* largest transfer size (largest signed #) */
        ~1,                 /* addmask */
        0,                  /* boot priority */
        0x444f5300,         /* dostype: 'DOS0' */
    };

    struct Device Node *node, *MakeDosNode();

    node = MakeDosNode( parmPkt );

SEE ALSO
    AddDosNode, libraries/dosextens.h, libraries/filehandler.h


expansion.library/ObtainConfigBinding

NAME
    ObtainConfigBinding - try to get permission to bind drivers

SYNOPSIS
    ObtainConfigBinding()

FUNCTION
    ObtainConfigBinding gives permission to bind drivers to
    ConfigDev structures.  It exists so two drivers at once
    do not try and own the same ConfigDev structure.  This
    call will block until it is safe proceed.

    It is crucially important that people lock out others
    before loading new drivers.  Much of the data that is used
    to configure things is statically kept, and others need
    to be kept from using it.

    This call is built directly on Exec SignalSemaphore code
    (e.g. ObtainSemaphore).

INPUTS

RESULTS

EXCEPTIONS

SEE ALSO
    ReleaseConfigBinding()

BUGS


expansion.library/ReadExpansionByte

NAME
    ReadExpansionByte - read a byte nybble by nybble.

SYNOPSIS
    byte = ReadExpansionByte( board, offset )
    D0                        A0     D0

FUNCTION
    (Not typically called by user code)

    ReadExpansionByte reads a byte from a new-style expansion
    board.  These boards have their readable data organized
    as a series of nybbles in memory.  This routine reads
    two nybbles and returns the byte value.

    In general, this routine will only be called by ReadExpansionRom.

    The offset is a byte offset, as if into a ExpansionRom structure.
    The actual memory address read will be four times larger.
    The macros EROFFSET and ECOFFSET are provided to help get
    these offsets from C.

INPUTS
    board - a pointer to the base of a new style expansion board.
    offset - a logical offset from the board base

RESULTS
    byte - a byte of data from the expansion board.

EXAMPLES
    byte = ReadExpansionByte( cd->BoardAddr, EROFFSET( er_Type ) );
    ints = ReadExpansionByte( cd->BoardAddr, ECOFFSET( ec_Interrupt ) );

SEE ALSO
    WriteExpansionByte, ReadExpansionRom


expansion.library/ReadExpansionRom

NAME
    ReadExpansionRom - read a boards configuration rom space

SYNOPSIS
    error = ReadExpansionRom( board, configDev )
    D0                        A0     A1

FUNCTION
    (Not typically called by user code)

    ReadExpansionRom reads a the rom portion of an expansion
    device in to cd_Rom portion of a ConfigDev structure.
    This routine knows how to detect whether or not there is
    actually a board there,

    In addition, the Rom portion of a new style expansion board
    is encoded in ones-complement format (except for the first
    two nybbles -- the er_Type field).  ReadExpansionRom knows
    about this and un-complements the appropriate fields.

INPUTS
    board - a pointer to the base of a new style expansion board.
    configDev - the ConfigDev structure that will be read in.
    offset - a logical offset from the configdev base

RESULTS
    error - If the board address does not contain a valid new style
            expansion board, then error will be non-zero.

EXAMPLES

    configDev = AllocConfigDev();
    if( ! configDev ) panic();

    error = ReadExpansionBoard( board, configDev );
    if( ! error ) {
            configDev->cd_BoardAddr = board;
            ConfigBoard( configDev );
    }

SEE ALSO
    ReadExpansionByte, WriteExpansionByte


expansion.library/ReleaseConfigBinding

NAME
    ReleaseConfigBinding - allow others to bind to drivers

SYNOPSIS
    ReleaseConfigBinding()

FUNCTION
    This call should be used when you are done binding drivers
    to ConfigDev entries.  It releases the SignalSemaphore; this
    allows others to bind their drivers to ConfigDev structures.

SEE ALSO
    ObtainConfigBinding()


expansion.library/RemConfigDev

NAME
    RemConfigDev - remove a ConfigDev structure from the system

SYNOPSIS
    RemConfigDev( configDev )
                  A0

FUNCTION
    (Not typically called by user code)

    This routine removes the specified ConfigDev structure from the
    list of Configuration Devices in the system.

INPUTS
    configDev - a valid ConfigDev structure.

RESULTS

EXCEPTIONS

SEE ALSO
    AddConfigDev

BUGS


expansion.library/SetCurrentBinding

NAME
    SetCurrentBinding - sets static board configuration area

SYNOPSIS
    SetCurrentBinding( currentBinding, size )
                       A0              D0:16

FUNCTION
    This function records the contents of the "currentBinding"
    structure in a private place.  It may be read via
    GetCurrentBinding().  This is really a kludge, but it is
    the only way to pass extra arguments to a newly configured
    device.

    A CurrentBinding structure has the name of the currently
    loaded file, the product string that was associated with
    this driver, and a pointer to the head of a singly linked
    list of ConfigDev structures (linked through the cd_NextCD
    field).

    Many devices may not need this information; they have hard
    coded into themselves their manufacture number.  It is
    recommended that you at least check that you can deal with
    the product code in the linked ConfigDev structures.

INPUTS
    currentBinding - a pointer to a CurrentBinding structure

    size - The size of the user's binddriver structure.  No
        more than this much data will be copied.  If size is
        less than the library's idea a CurrentBinding size,
        then the library's structure will be null padded.

SEE ALSO
    GetCurrentBinding


expansion.library/WriteExpansionByte

NAME
    WriteExpansionByte - write a byte nybble by nybble.

SYNOPSIS
    WriteExpansionByte( board, offset, byte )
                        A0     D0      D1

FUNCTION
    (Not typically called by user code)

    WriteExpansionByte writes a byte to a new-style expansion
    board.  These boards have their writeable data organized
    as a series of nybbles in memory.  This routine writes
    two nybbles in a very careful manner to work with all
    types of new expansion boards.

    To make certain types of board less expensive, an expansion
    board's write registers may be organized as either a
    byte-wide or nybble-wide register.  If it is nybble-wide
    then it must latch the less significant nybble until the
    more significant nybble is written.  This allows the
    following algorithm to work with either type of board:

            write the low order nybble to bits D15-D12 of
                    byte (offset*4)+2

            write the entire byte to bits D15-D8 of
                    byte (offset*4)

    The offset is a byte offset into a ExpansionRom structure.
    The actual memory address read will be four times larger.
    The macros EROFFSET and ECOFFSET are provided to help get
    these offsets from C.

INPUTS
    board - a pointer to the base of a new style expansion board.
    offset - a logical offset from the configdev base
    byte - the byte of data to be written to the expansion board.

EXAMPLES
    WriteExpansionByte( cd->BoardAddr, ECOFFSET( ec_Shutup ),  0 );
    WriteExpansionByte( cd->BoardAddr, ECOFFSET( ec_Interrupt ), 1 );

SEE ALSO
    ReadExpansionByte, ReadExpansionRom


mathffp.doc

 SPAbs()       SPCmp()      SPFloor()      SPNeg()
 SPAdd()       SPDiv()      SPFlt()        SPSub()
 SPCeil()      SPFix()      SPMul()        SPTst()


mathffp.library/SPAbs

NAME
    SPAbs -- Obtain the absolute value of the fast floating point number.

SYNOPSIS
    fnum2 = SPAbs(fnum1)
    D0            D0

    float SPAbs(float fnum1);

FUNCTION
    Accepts a floating point number and returns the absolute value of
    said number.

INPUTS
    fnum1   - floating point number.

RESULT
    fnum2   - floating point absolute value of fnum1.

BUGS
    None

SEE ALSO


mathffp.library/SPAdd

NAME
    SPAdd -- Add two floating point numbers.

SYNOPSIS
    fnum3 = SPAdd(fnum1, fnum2)
    D0            D1     D0

    float SPAdd(float fnum1, float fnum2);

FUNCTION
    Accepts two floating point numbers and returns the arithmetic
    sum of said numbers.

INPUTS
    fnum1   - floating point number to add.
    fnum2   - other floating point number to add.

RESULT
    fnum3   - floating point number, sum of fnum1 and fnum2.

BUGS
    None.

SEE ALSO


mathffp.library/SPCeil

NAME
    SPCeil -- Compute Ceil function of a number.

SYNOPSIS
    x = SPCeil(y)
    D0         D0

    float SPCeil(float y);

FUNCTION
    Calculate the least integer greater than or equal to x and return it.
    This identity is true.  Ceil(x) = -Floor(-x).

INPUTS
    y       - Motorola Fast Floating Point Format Number.

RESULT
    x       - Motorola Fast Floating Point Format Number.

BUGS
    None.

SEE ALSO
    SPFloor()


mathffp.library/SPCmp

NAME
    SPCmp -- Compares two floating point numbers.

SYNOPSIS
    result = SPCmp(fnum1, fnum2)
    D0               D0     D1

    int SPCmp(float fnum1, float fnum2);

FUNCTION

    Accepts two floating point numbers and returns the condition
    codes set to indicate the result of said comparison.  Additionally,
    the integer functional result is returned to indicate the result
    of said comparison.

INPUTS
    fnum1   - floating point number.
    fnum2   - floating point number.

RESULT
    Condition codes set to reflect the following branches:

            GT - fnum2 >  fnum1
            GE - fnum2 >= fnum1
            EQ - fnum2 =  fnum1
            NE - fnum2 != fnum1
            LT - fnum2 <  fnum1
            LE - fnum2 <= fnum1

    Integer functional result as:

            +1 => fnum1 > fnum2
            -1 => fnum1 < fnum2
             0 => fnum1 = fnum2

BUGS
    None.

SEE ALSO


mathffp.library/SPDiv

NAME
    SPDiv -- Divide two floating point numbers.

SYNOPSIS
    fnum3 = SPDiv(fnum1, fnum2)
    D0            D1     D0

    float SPDiv(float fnum1, float fnum2);

FUNCTION
    Accepts two floating point numbers and returns the arithmetic
    division of said numbers.

INPUTS
    fnum1   - floating point number.
    fnum2   - floating point number.

RESULT

    fnum3   - floating point number.

BUGS
    None.

SEE ALSO


mathffp.library/SPFix

NAME
    SPFix -- Convert fast floating point number to integer.

SYNOPSIS
    inum = SPFix(fnum)
    D0           D0

    int SPFix(float fnum);

FUNCTION
    Accepts a floating point number and returns the truncated
    integer portion of said number.

INPUTS

    fnum    - floating point number.

RESULT

    inum    - signed integer number.

BUGS
    None.

SEE ALSO


mathffp.library/SPFloor

NAME
    SPFloor -- compute Floor function of a number.

SYNOPSIS
    x = SPFloor(y)
    D0          D0

    float SPFloor(float y);

FUNCTION
    Calculate the largest integer less than or equal to x and return it.

INPUTS
    y       - Motorola Fast Floating Point number.

RESULT
    x       - Motorola Fast Floating Point number.

BUGS
    None.

SEE ALSO
    SPCeil()


mathffp.library/SPFlt

NAME
    SPFlt -- Convert integer number to fast floating point.

SYNOPSIS
    fnum = SPFlt(inum)
    D0           D0

    float SPFlt(int inum);

FUNCTION
    Accepts an integer and returns the converted
    floating point result of said number.

INPUTS
    inum    - signed integer number

RESULT
    fnum    - floating point number

BUGS
    None.

SEE ALSO


mathffp.library/SPMul

NAME
    SPMul -- Multiply two floating point numbers.

SYNOPSIS
    fnum3 = SPMul(fnum1, fnum2)
    D0            D1     D0

    float SPMul(float fnum1, float fnum2);

FUNCTION
    Accepts two floating point numbers and returns the arithmetic
    multiplication of said numbers.

INPUTS
    fnum1   - floating point number
    fnum2   - floating point number

RESULT
    fnum3   - floating point number

BUGS
    None

SEE ALSO


mathffp.library/SPNeg

NAME
    SPNeg -- Negate the supplied floating point number.

SYNOPSIS
    fnum2 = SPNeg(fnum1)
    D0            D0

    float SPNeg(float fnum1);

FUNCTION
    Accepts a floating point number and returns the value
    of said number after having been subtracted from 0.0.

INPUTS
    fnum1   - floating point number.

RESULT
    fnum2   - floating point negation of fnum1.

BUGS
    None

SEE ALSO


mathffp.library/SPSub

NAME
    SPSub -- Subtract two floating point numbers.

SYNOPSIS
    fnum3 = SPSub(fnum1, fnum2)
    D0            D1     D0

    float SPSub(float fnum1, float fnum2);

FUNCTION
    Accepts two floating point numbers and returns the arithmetic
    subtraction of said numbers.

INPUTS
    fnum1   - floating point number.
    fnum2   - floating point number.

RESULT
    fnum3   - floating point number.

BUGS
    None.

SEE ALSO


mathffp.library/SPTst

NAME
    SPTst - Compares a float against zero (0.0).

SYNOPSIS
    result = SPTst(fnum)
    D0             D1

    int SPTst(float fnum);

FUNCTION
    Accepts a floating point number and returns the condition
    codes set to indicate the result of a comparison against
    the value of zero (0.0).  Additionally, the integer functional
    result is returned.

INPUTS
    fnum    - floating point number.

RESULT
    Condition codes set to reflect the following branches:

            EQ - fnum =  0.0
            NE - fnum != 0.0
            PL - fnum >= 0.0
            MI - fnum <  0.0

    Integer functional result as:

            +1 => fnum > 0.0
            -1 => fnum < 0.0
             0 => fnum = 0.0

BUGS
    None.

SEE ALSO


utility.doc

 AllocateTagItems()      FindTagItem()               SMult32()
 Amiga2Date()            FreeTagItems()              Stricmp()
 CallHookPkt()           GetTagData()                Strnicmp()
 CheckDate()             MapTags()                   TagInArray()
 CloneTagItems()         NextTagItem()               ToLower()
 Date2Amiga()            PackBoolTags()              ToUpper()
 FilterTagChanges()      RefreshTagItemClones()      UDivMod32()
 FilterTagItems()        SDivMod32()                 UMult32()


utility.library/AllocateTagItems

NAME
    AllocateTagItems --  Allocate a TagItem array (or chain). (V36)

SYNOPSIS
    tagList = AllocateTagItems( numItems )
    D0                          D0

    struct TagItem *AllocateTagItems( ULONG numItems);

FUNCTION
    Allocates the specified number of usable TagItems slots, and does
    so in a format that the function FreeTagItems can handle.

    Note that to access the TagItems in 'tagList', you should use
    the function NextTagItem().  This will insure you respect any
    chaining (TAG_MORE) that the list uses, and will skip any
    TAG_IGNORE items that AllocateTagItems() might use to stash
    size and other information.

INPUTS
    numItems        - the number of TagItem slots you want to allocate.

RESULT
    tagList         - the allocated chain of TagItem structures.  Will
                      return NULL if unsuccessful.

BUGS

SEE ALSO
    FreeTagItems(), CloneTagItems()


utility.library/Amiga2Date

NAME
    Amiga2Date -- Calculate the date from a timestamp.  (V36)

SYNOPSIS
    Amiga2Date( AmigaTime, Date )
                D0         A0

    void Amiga2Date( ULONG, struct ClockData * );

FUNCTION
    Fills in a ClockData structure with the date and time calculated
    from a ULONG containing the number of seconds from 01-Jan-1978
    to the date.

INPUTS
    AmigaTime       - the number of seconds from 01-Jan-1978.

RESULTS
    Date            - filled in with the date/time specified by
                      AmigaTime.

NOTES

SEE ALSO
    CheckDate(), Date2Amiga()

BUGS


utility.library/CallHookPkt

NAME
    CallHookPkt -- Invoke a Hook function callback. (V36)

SYNOPSIS
    return = CallHookPkt( hook, object, paramPkt )
    D0                    A0    A2      A1

    ULONG CallHookPkt( struct Hook *hook, VOID *object, VOID *paramPkt );

FUNCTION
    Performs the callback standard defined by a Hook structure.
    This function is really very simple; it effectively performs
    a JMP to Hook->h_Entry.

    It is probably just as well to do this operation in an
    assembly language function linked in to your program, possibly
    from a compiler supplied library or a builtin function.

    It is anticipated that C programs will often call a 'varargs'
    variant of this function which will be named CallHook.  This
    function must be provided in a compiler specific library, but
    an example of use would be:

    returnval = CallHook( hook, dataobject, COMMAND_ID, param1, param2 );

    This function CallHook can be implemented in many C compilers
    like this:
    CallHook( hook, object, command, ... )
    struct Hook    *hook;
    VOID            *object;
    ULONG           command;
    {
            return ( CallHookPkt( hook, object, (VOID *) &command ) );
    }

INPUTS
    Hook           - pointer to Hook structure as defined in
                      utility/hooks.h
    Object          - useful data structure in the particular context the
                      hook is being used for.
    ParamPkt        - pointer to a parameter packet (often built on the
                      stack); by convention this packet should start off
                      with a longword command code, and the remaining
                      data in the packet depends on that command.

RESULT
    return          - The meaning of the value returned in D0 depends on
                      the context in which the Hook is being used.

NOTES
    The functions called through this function should follow normal
    register conventions unless EXPLICITLY documented otherwise (and
    they have a good reason too).

BUGS

SEE ALSO
    utility/hooks.h


utility.library/CheckDate

NAME
    CheckDate -- Checks ClockData struct for legal date. (V36)

SYNOPSIS
    AmigaTime = CheckDate( Date )
    D0                     A0

    ULONG CheckDate( struct ClockData * );

FUNCTION
    Determines if the Date is a legal date and returns the number
    of seconds to Date from 01-Jan-1978 if it is.

INPUTS
    Date            - pointer to a ClockData structure.

RESULTS
    AmigaTime       - 0 if Date invalid; otherwise, the number of
                      seconds to Date from 01-Jan-1978.

NOTES

BUGS
    The wday field of the ClockData structure is not checked.

SEE ALSO
    Amiga2Date(), Date2Amiga()


utility.library/CloneTagItems

NAME
    CloneTagItems -- Copies a TagItem list.  (V36)

SYNOPSIS
    newTagList = CloneTagItems( tagList )
    D0                          A0

    struct TagItem *CloneTagItems( struct TagItem *tagList );

FUNCTION
    Copies the essential contents of a tagItem list.  Internally,
    it uses AllocateTagItems() so that you can use FreeTagItems().

INPUTS
    tagList         - TagItem list to clone.

RESULT
    newTagList      - resultant copy.

BUGS

SEE ALSO
    AllocateTagItems(), FreeTagItems(), RefreshTagItemClones()


utility.library/Date2Amiga

NAME
    Date2Amiga -- Calculate seconds from 01-Jan-1978.  (V36)

SYNOPSIS
    AmigaTime = Date2Amiga( Date )
    D0                      A0

    ULONG Date2Amiga( struct ClockData * );

FUNCTION
    Calculates the number of seconds from 01-Jan-1978 to the date
    specified in the ClockData structure.

INPUTS
    Date            - pointer to a ClockData structure containing the
                      date of interest.

RESULTS
    AmigaTime       - the number of seconds from 01-Jan-1978 to the
                      date specified in Date.

NOTES
    This function does no sanity checking of the data in Date.

SEE ALSO
    Amiga2Date(), CheckDate()

BUGS


utility.library/FilterTagChanges

NAME
    FilterTagChanges -- Eliminate TagItems which specify no change. (V36)

SYNOPSIS
    FilterTagChanges( changeList, oldValues, apply)
                      A0          A1         D0

    void FilterTagChanges( struct TagItem *changeList,
                           struct TagItem *oldValues, LONG apply );

FUNCTION
    Eliminate items from a "change list" that specify values already
    in effect in existing list.  Optionally update the existing list
    if the Boolean 'Apply' is true.

    The elimination is done by changing the ti_Tag field to TAG_IGNORE.
    So, this function may change the input tag list(s).

INPUTS
    changeList      - specification of new tag-value pairs.
    oldValues       - a list of existing tag item pairs.
    apply           - Boolean specification as to whether the values in
                      oldValues are to be updated to the values in
                      changeList.

RESULT
    None.

EXAMPLE
    Assume you have an attribute list for an object (oldValues)
    which looks like this:

            ATTR_Size,  "large",
            ATTR_Color, "orange",
            ATTR_Shape, "square",

    If you receive a new TagList containing some changes (changeList),
    which looks like this:

            ATTR_Size,  "large",
            ATTR_Shape, "triangle"

    If you call FilterTagChanges(), changeList will be modified to
    contain only those attributes which are different from the
    oldValues.  All other tagitems will have their tag-values set to
    TAG_IGNORE.  The resulting changeList will become:

            TAG_IGNORE, "large",
            ATTR_Shape, "triangle"

    If apply was set to TRUE, oldValues would be:

            ATTR_Size,  "large"
            ATTR_Color, "orange"
            ATTR_Shape, "triangle"

BUGS

SEE ALSO


utility.library/FilterTagItems

NAME
    FilterTagItems - Remove selected items from a TagItem list. (V36)

SYNOPSIS
    nvalid = FilterTagItems(tagList, tagArray, logic)
    D0                     A0       A1        D0

    ULONG FilterTagItems(struct TagItem *tagList, Tag *tagArray,
                         LONG logic);

FUNCTION
    Removes TagItems from a TagItem list (by changing ti_Tag to
    TAG_IGNORE) depending on whether its ti_Tag value is
    found in an array of TagValues.

    If the 'logic' parameter is TAGFILTER_AND, then all items
    not appearing in the list are excluded.

    If 'logic' is TAGFILTER_NOT, then items not found in the
    array are preserved, and the ones in the array are cast out.

INPUTS
    tagList         - input list of tag items which is to be filtered
                      by having selected items changed to TAG_IGNORE.
    tagArray        - an array of Tag values, terminated by TAG_END,
                      as specified in the notes on TagInArray().
    logic           - specification whether items in TagArray are to
                      be included or excluded in the filtered result.

RESULT
    nvalid          - number of valid items left in resulting filtered
                      list.

BUGS

SEE ALSO
    TagInArray()


utility.library/FindTagItem

NAME
    FindTagItem -- Scans TagItem list for a Tag. (V36)

SYNOPSIS
    tag = FindTagItem( tagVal, tagList)
    D0                 D0      A0

    struct TagItem *FindTagItem( Tag tagVal, struct TagItem *tagList );

FUNCTION
    Scans a TagItem "List", which is in fact a chain of arrays
    of TagItem structures as defined in utility/tagitem.h.
    Returns a pointer to the FIRST item with ti_Tag matching the
    'TagVal' parameter.

INPUTS
    tagVal          - Tag value to search for.
    tagList         - beginning of TagItem list to scan.

RESULT
    Returns a pointer to the item with ti_Tag matching 'TagVal'.
    Returns NULL if there is no match or if TagList is NULL.

BUGS

SEE ALSO
    utility/tagitem.h, GetTagData(), PackBoolTags(), NextTagItem()


utility.library/FreeTagItems

NAME
    FreeTagItems --  Frees allocated TagItem lists. (V36)

SYNOPSIS
    FreeTagItems( tagList )
                    A0

    void FreeTagItems( struct TagItem *tagList );

FUNCTION
    Frees the memory of a TagItem list allocated either by
    AllocateTagItems() or CloneTagItems().

INPUTS
    TagList         - list to free.  Must be created by functions
                      specified. A value of NULL for 'tagList' is safe.

RESULT
    None.

BUGS

SEE ALSO
    AllocateTagItems(), CloneTagItems()


utility.library/GetTagData

NAME
    GetTagData -- Obtain data corresponding to Tag. (V36)

SYNOPSIS
    value = GetTagData(tagVal, default, tagList)
    D0                 D0      D1       A0

    ULONG GetTagData(Tag TagVal, ULONG Default, struct TagItem *TagList)

FUNCTION
    Searches a TagItem list for a matching Tag value, and returns the
    corresponding ti_Data value for the TagItem found.  If none
    found, will return the value passed it as 'default'.

INPUTS
    tagVal          - Tag value to search for.
    default         - value to be returned if tagVal is not found.
    tagList         - the TagItem list to search.

RESULT
    value           - The ti_Data value for first matching TagItem, or
                      'default' if a ti_Tag matching 'Tag' is not found.

BUGS

SEE ALSO
    utility/tagitem.h, FindTagItem(), PackBoolTags(), NextTagItem()


utility.library/MapTags

NAME
    MapTags -- Convert ti_Tag values in a list via map pairing. (V36)

SYNOPSIS
    MapTags(tagList, mapList, includeMiss)
            A0       A1       D0

    void MapTags(struct TagItem *tagList, struct TagItem mapList,
                 LONG includeMiss);

FUNCTION
    Apply a "mapping list" mapList to tagList:

    If the ti_Tag field of an item in tagList appears as ti_Tag in some
    item in mapList, overwrite ti_Tag with the corresponding ti_Data
    from the map list.

    If a tag in tagList does not appear in the mapList, you can choose
    to have it removed by changing it to TAG_IGNORE. Do this by setting
    includeMiss to FALSE.

    If you want to have items which do not appear in the mapList
    survive the mapping as-is, set includeMiss to 1.

    This is central to gadget interconnections where you want
    to convert the tag values from one space (the sender) to
    another (the receiver).

INPUTS
    tagList         - Input list of tag items which is to be mapped
                      to Tag values as specified in mapList.
    mapList         - a "mapping list" tagItem list which pairs Tag
                      values expected to appear in tagList with new
                      values to be substituted in the ti_Tag fields of
                      tagList.  May be NULL, which means that all items
                      in tagList will be eliminated.
    includeMiss     - 0 to remove tags from tagList not in mapList,
                      1 to remove

RESULT
    None.

EXAMPLE
    /* Consider this source list: */
        struct TagItem list[] = {
            { MY_SIZE,      71 },
            { MY_WEIGHT,    200 },
            { TAG_END,      } };

    /* And the mapping list: */
        struct TagItem map[] = {
            { MY_SIZE,      HIS_TALL },
            { TAG_END,      } };

    /* Then after MapTags( list, map, 0 ), 'list' will become: */
            { HIS_TALL, 71 },
            { TAG_IGNORE, },
            { TAG_END, }

    /* Then after MapTags( list, map, 1 ), 'list' will become: */
            { HIS_TALL, 71 },
            { MY_WEIGHT, 200 },
            { TAG_END, }

NOTES
    The procedure will change the values of the input tag list
    tagList (but not mapList).

    You can "filter" a list by passing includeMiss as 0, and having the
    data items in the map list equal the corresponding tags.

    You can perform the inverse filter ("everything but") by passing
    includeMiss equal to 1, and creating a map item for every tag you
    want to filter out, pairing it with a mapped data value of
    TAG_IGNORE.

    For safety and "order independence" of tag item arrays, if you
    attempt to map some tag to the value TAG_END, the value TAG_IGNORE
    will be substituted instead.

BUGS

SEE ALSO


utility.library/NextTagItem

NAME
    NextTagItem -- Iterate TagItem lists. (V36)

SYNOPSIS
    next_tag = NextTagItem( tagItemPtr )
    D0                      A0

    struct TagItem *NextTagItem( struct TagItem **tagItemPtr );

FUNCTION
    Iterates through a (chained) array of TagItem structures,
    skipping and chaining as dictated by system tags.  TAG_SKIP
    will cause it to skip the entry and the next, TAG_IGNORE ignores
    that single entry, and TAG_MORE has a pointer to another array
    of tags (and terminates the current array!)  TAG_DONE also
    terminates the current array.  Each call returns either the next
    tagitem you should examine, or NULL at the end.

INPUTS
    tagItemPtr      - doubly-indirect reference to a TagItem structure.
                      The pointer will be changed to keep track of the
                      iteration.

RESULT
    next_tag        - Each TagItem in the array or chain of arrays that
                      should be processed according to system Tag values
                      (in utility/tagitem.h) is returned in turn with
                      successive calls.

EXAMPLE
    Iterate( struct TagItem *tags );
    {
            struct TagItem *tstate;
            struct TagItem *tag;

            tstate = tags;
            while ( tag = NextTagItem( &tstate ) )
            {
                    switch ( tag->ti_Tag )
                    {
                    case TAG1:
                        ...
                        break;
                    case TAG2:
                        ...
                        break;
                    ...
                    }
            }
    }

NOTES
    Do NOT use the value of *tagItemPtr, but rather use the pointer
    returned by NextTagItem().

BUGS

SEE ALSO
    utility/tagitem.h, GetTagData(), PackBoolTags(), FindTagItem()


utility.library/PackBoolTags

NAME
    PackBoolTags --  Builds a "Flag" word from a TagList. (V36)

SYNOPSIS
    boolflags = PackBoolTags( initialFlags, tagList, boolMap )
    D0                        D0            A0       A1

    ULONG PackBoolTags( ULONG initialFlags, struct TagItem *tagList,
                        struct TagItem *boolMap );

FUNCTION
    Picks out the Boolean TagItems in a TagItem list and converts
    them into bit-flag representations according to a correspondence
    defined by the TagItem list 'BoolMap.'

    A Boolean TagItem is one where only the logical value of
    the ti_Data is relevant.  If this field is 0, the value is
    FALSE, otherwise TRUE.

INPUTS
    initialFlags    - a starting set of bit-flags which will be changed
                      by the processing of TRUE and FALSE Boolean tags
                      in tagList.
    tagList         - a TagItem list which may contain several TagItems
                      defined to be "Boolean" by their presence in
                      boolMap.  The logical value of ti_Data determines
                      whether a TagItem causes the bit-flag value related
                      by boolMap to set or cleared in the returned flag
                      longword.
    boolMap         - a TagItem list defining the Boolean Tags to be
                      recognized, and the bit (or bits) in the returned
                      longword that are to be set or cleared when a
                      Boolean Tag is found to be TRUE or FALSE in
                      tagList.

RESULT
    boolflags       - the accumulated longword of bit-flags, starting
                      with InitialFlags and modified by each Boolean
                      TagItem encountered.

EXAMPLE

    /* define some nice user tag values ... */
    enum mytags { tag1 = TAG_USER+1, tag2, tag3, tag4, tag5 };

    /* this TagItem list defines the correspondence between Boolean tags
     * and bit-flag values.
     */
    struct TagItem       boolmap[] = {
        { tag1,  0x0001 },
        { tag2,  0x0002 },
        { tag3,  0x0004 },
        { tag4,  0x0008 },
        { TAG_DONE }
    };

    /* You are probably passed these by some client, and you want
     * to "collapse" the Boolean content into a single longword.
     */

    struct TagItem       boolexample[] = {
        { tag1,  TRUE },
        { tag2,  FALSE },
        { tag5, Irrelevant },
        { tag3,  TRUE },
        { TAG_DONE }
    };

    /* Perhaps 'boolflags' already has a current value of 0x800002. */
    boolflags = PackBoolTags( boolflags, boolexample, boolmap );

    /* The resulting new value of 'boolflags' will be 0x80005. /*

BUGS
    There are some undefined cases if there is duplication of
    a given Tag in either list.  It is probably safe to say that
    the *last* of identical Tags in TagList will hold sway.

SEE ALSO
    utility/tagitem.h, GetTagData(), FindTagItem(), NextTagItem()


utility.library/RefreshTagItemClones

NAME
    RefreshTagItemClones -- Rejuvenates a clone from the original. (V36)

SYNOPSIS
    RefreshTagItemClones( cloneTagItems, originalTagItems )
                          A0             A1

    void RefreshTagItemClones( struct TagItem *cloneTagItems,
                              struct TagItem *originalTagItems );

FUNCTION
    If (and only if) the tag items 'cloneTagItems' were created
    from 'originalTagItems' by CloneTagItems(), and if originalTagItems
    has not been changed in any way, you can reset the clone list
    to its original state by using this function.

INPUTS
    CloneTagItems    - return value from CloneTagItems(originalTagItems).
    OriginalTagItems - a tag list that hasn't changed.

RESULT
    None.

EXAMPLE

BUGS

SEE ALSO
    CloneTagItems(), AllocateTagItems(), FreeTagItems()


utility.library/SDivMod32

NAME
    SDivMod32 -- Signed 32 by 32 bit division and modulus. (V36)

SYNOPSIS
    Quotient:Remainder = SDivMod32( Dividend, Divisor )
    D0       D1                     D0        D1

    LONG SDivMod32( LONG, LONG );

FUNCTION
    Divides the signed 32 bit dividend by the signed 32 bit divisor
       and returns a signed 32 bit quotient and remainder.

INPUTS
    Dividend        - signed 32 bit dividend.
    Divisor         - signed 32 bit divisor.

RESULTS
    Quotient        - signed 32 quotient of the division.
    Remainder       - signed 32 remainder of the division.

NOTES

SEE ALSO
    SMult32(), UDivMod32(), UMult32()

BUGS


utility.library/SMult32

NAME
    SMult32 -- Signed 32 by 32 bit multiply with 32 bit result. (V36)

SYNOPSIS
    Result = SMult32( Arg1, Arg2 )
    D0                D0    D1

    LONG SMult32( LONG, LONG );

FUNCTION
    Returns the signed 32 bit result of multiplying Arg1 by Arg2.

INPUTS
    Arg1, Arg2      - signed multiplicands.

RESULTS
    Result          - the signed 32 bit result of multiplying
                      Arg1 by Arg2.

NOTES

SEE ALSO
    SDivMod32(), UDivMod32(), UMult32()

BUGS


utility.library/Stricmp

NAME
    Stricmp --  Case-insensitive string compare. (V37)

SYNOPSIS
    res = Stricmp(string1, string2)
    D0              A0       A1

    LONG Stricmp(char *, char *);

FUNCTION
    Stricmp compares two strings, ignoring case.  It handles all
    internationalization issues.  If the strings have different lengths,
    the shorter is treated as if it were extended with zeros.

INPUTS
    string1, string2 - strings to be compared

RESULT
    res - negative if string1 is below string2, 0 if they're the same, and
          positive if string1 is above string2.

NOTES
    Commodore is planning a localization library which will take care
    of most details pertaining to system integration into different
    cultures, locales, and territories.

    This function will automatically be replaced by a localized version
    whenever the locale.library is loaded in memory. As such, the
    collating order may change depending on the locale currently
    defined by the user. Take this fact into consideration when using
    this function, and do not rely on obtaining specific collating
    sequences.

BUGS

SEE ALSO
    Strnicmp()


utility.library/Strnicmp

NAME
    Strnicmp--  Case-insensitive string compare, length-limited. (V37)

SYNOPSIS
    res = Strnicmp(string1, string2, length)
    D0              A0       A1        D0

    LONG Strnicmp(char *, char *, LONG length);

FUNCTION

    Strnicmp compares two strings, ignoring case.  It handles all
    internationalization issues.  If the strings have different lengths,
    the shorter is treated as if it were extended with zeros.  It never
    compares more than <length> characters.

INPUTS
    string1, string2 - strings to be compared
    length           - maximum number of characters to examine

RESULT
    res - negative if string1 is below string2, 0 if they're the same, and
          positive if string1 is above string2.

NOTES
    Commodore is planning a localization library which will take care
    of most details pertaining to system integration into different
    cultures, locales, and territories.

    This function will automatically be replaced by a localized version
    whenever the locale.library is loaded in memory. As such, the
    collating order may change depending on the locale currently
    defined by the user. Take this fact into consideration when using
    this function, and do not rely on obtaining specific collating
    sequences.

BUGS

SEE ALSO
    Stricmp()


utility.library/TagInArray

NAME
    TagInArray  -- Check if a Tag value appears in a Tag array. (V36)

SYNOPSIS
    BOOL TagInArray( tag, tagArray )
    D0               D0   A0

    BOOL TagInArray( Tag tag, Tag *tagArray);

FUNCTION
    Perform a quick scan to see if a tag value appears in
    an array terminated with TAG_END.  Returns TRUE if
    the value is found.

    The 'tagArray' must be terminated by TAG_END.  It should
    NOT contain other system tag values, such as TAG_MORE
    or TAG_IGNORE.  Note that this is an array of Tag values, NOT
    an array of TagItems.

    This is sort of a "one shot" version of FilterTagItems().

INPUTS
    tag             - Tag value to search array for.
    tagArray        - a simple array terminated by TAG_END.

RESULT
    Boolean success of search.

BUGS

SEE ALSO
    FilterTagItems()


utility.library/ToLower

NAME
    ToLower - Convert a character to lowercase. (V37)

SYNOPSIS
    char = ToLower(char)
    D0              D0

    char ToLower(char);

FUNCTION
    Converts a character to lowercase, handling international character
    sets.

INPUTS
    char - character to be converted.

RESULT
    char - lowercase version of input character.

NOTES
    Commodore is planning a localization library which will take care
    of most details pertaining to system integration into different
    cultures, locales, and territories.

    This function will automatically be replaced by a localized version
    whenever the locale.library is loaded in memory. As such, the
    resulting converted character may change depending on the locale
    currently defined by the user. Take this fact into consideration when
    using this function, and do not rely on obtaining specific
    conversions.

BUGS

SEE ALSO


utility.library/ToUpper

NAME
    ToUpper - Convert a character to uppercase. (V37)

SYNOPSIS
    char = ToUpper(char)
    D0              D0

    char ToUpper(char);

FUNCTION
    Converts a character to uppercase, handling international character
    sets.

INPUTS
    char - character to be converted.

RESULT
    char - uppercase version of input character.

NOTES
    Commodore is planning a localization library which will take care
    of most details pertaining to system integration into different
    cultures, locales, and territories.

    This function will automatically be replaced by a localized version
    whenever the locale.library is loaded in memory. As such, the
    resulting converted character may change depending on the locale
    currently defined by the user. Take this fact into consideration when
    using this function, and do not rely on obtaining specific
    conversions.

BUGS

SEE ALSO


utility.library/UDivMod32

NAME
    UDivMod32 -- Unsigned 32 by 32 bit division and modulus. (V36)

SYNOPSIS
    Quotient:Remainder = UDivMod32( Dividend, Divisor )
    D0       D1                     D0        D1

    ULONG UDivMod32( ULONG, ULONG );

FUNCTION
    Divides the unsigned 32 bit dividend by the unsigned 32 bit divisor
    and returns a unsigned 32 bit quotient and remainder.

INPUTS
    Dividend        - unsigned 32 bit dividend.
    Divisor         - unsigned 32 bit divisor.

RESULTS
    Quotient        - unsigned 32 quotient of the division.
    Remainder       - unsigned 32 remainder of the division.

NOTES

SEE ALSO
    SDivMod32(), SMult32(), UMult32()

BUGS


utility.library/UMult32

NAME
    UMult32 -- Unsigned 32 by 32 bit multiply with 32 bit result. (V36)

SYNOPSIS
    Result = UMult32( Arg1, Arg2 )
    D0                D0    D1

    ULONG UMult32( ULONG, ULONG );

FUNCTION
    Returns the unsigned 32 bit result of multiplying Arg1 by Arg2.

INPUTS
    Arg1, Arg2              - unsigned multiplicands.

RESULTS
    Result                  - the unsigned 32 bit result of
                              multiplying Arg1 by Arg2.

NOTES

SEE ALSO
    SDivMod32(), SMult32(), UDivMod32()

BUGS


gadtools.doc

 CreateContext()      FreeVisualInfo()       GT_PostFilterIMsg()
 CreateGadgetA()      GetVisualInfoA()       GT_RefreshWindow()
 CreateMenusA()       GT_BeginRefresh()      GT_ReplyIMsg()
 DrawBevelBoxA()      GT_EndRefresh()        GT_SetGadgetAttrsA()
 FreeGadgets()        GT_FilterIMsg()        LayoutMenuItemsA()
 FreeMenus()          GT_GetIMsg()           LayoutMenusA()


gadtools.library/CreateContext

NAME
    CreateContext -- Create a place for GadTools context data. (V36)

SYNOPSIS
    gad = CreateContext(glistpointer);
    D0                  A0

    struct Gadget *CreateContext(struct Gadget **);

FUNCTION
    Creates a place for GadTools to store any context data it might
    need for your window.  In reality, an unselectable invisible
    gadget is created, with room for the context data.
    This function also establishes the linkage from a glist type
    pointer to the individual gadget pointers.  Call this function
    before any of the other gadget creation calls.

INPUTS
    glistptr - Address of a pointer to a Gadget, which was previously
        set to NULL.  When all the gadget creation is done, you may
        use that pointer as your NewWindow.FirstGadget, or
        in intuition.library/AddGList(), intuition.library/RefreshGList(),
        FreeGadgets(), etc.

RESULT
    gad - Pointer to context gadget, or NULL if failure.

EXAMPLE

    struct Gadget *gad;
    struct Gadget *glist = NULL;
    gad = CreateContext(&glist);
    /*  Other creation calls go here */
    if (gad)
    {
        myNewWindow.FirstGadget = glist;
        if ( myWindow = OpenWindow(&myNewWindow) )
        {
            GT_RefreshWindow(win);
            /* other stuff */
            CloseWindow(myWindow);
        }
    }
    FreeGadgets(glist);

NOTES

BUGS

SEE ALSO


gadtools.library/CreateGadgetA

NAME
    CreateGadgetA -- Allocate and initialize a gadtools gadget. (V36)
    CreateGadget -- Varargs stub for CreateGadgetA(). (V36)

SYNOPSIS
    gad = CreateGadgetA(kind, previous, newgad, taglist)
    D0                  D0    A0        A1      A2

    struct Gadget *CreateGadgetA(ULONG, struct Gadget *,
        struct NewGadget *, struct TagItem *);

    gad = CreateGadget(kind, previous, newgad, firsttag, ...)

    struct Gadget *CreateGadget(ULONG, struct Gadget *,
        struct NewGadget *, Tag, ...);

FUNCTION
    CreateGadgetA() allocates and initializes a new gadget of the
    specified kind, and attaches it to the previous gadget.  The
    gadget is created based on the supplied kind, NewGadget structure,
    and tags.

INPUTS
    kind - to indicate what kind of gadget is to be created.
    previous - pointer to the previous gadget that this new gadget
        is to be attached to.
    newgad - a filled in NewGadget structure describing the desired
        gadget's size, position, label, etc.
    taglist - pointer to a TagItem list.

TAGS
    All kinds:
    GT_Underscore (GadTools V37 and higher only).
        Indicates the symbol that precedes the character in the gadget
        label to be underscored.  This would be to indicate keyboard
        equivalents for gadgets (note that GadTools does not process
        the keys - it just displays the underscore).
        Example: To underscore the "M" in "Mode"...
            ng.ng_GadgetText = "_Mode:";
            gad = CreateGadget(..._KIND, &ng, prev,
                    GT_Underscore, '_',
                    ...
                    );

    BUTTON_KIND (action buttons):
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    CHECKBOX_KIND (on/off items):
    GTCB_Checked (BOOL) - Initial state of checkbox, defaults to FALSE.
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    CYCLE_KIND (multiple state selections):
    GTCY_Labels (STRPTR *) - Pointer to NULL-terminated array of strings
        that are the choices offered by the cycle gadget (required).
    GTCY_Active (UWORD) - The ordinal number (counting from zero) of
        the initially active choice of a cycle gadget (defaults to zero).
    GA_Disabled (BOOL) - (GadTools V37 and higher only)
        Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    INTEGER_KIND (numeric entry):
    GTIN_Number (ULONG) - The initial contents of the integer gadget
        (default zero).
    GTIN_MaxChars (UWORD) - The maximum number of digits that the
        integer gadget is to hold (defaults to 10).
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).
    STRINGA_ExitHelp (BOOL) - (New for V37) Set to TRUE to have the
        help-key cause an exit from the integer gadget.  You will
        then receive a GADGETUP with code = 0x5F (rawkey for help).
    GA_TabCycle (BOOL) - (New for V37) Set to TRUE so that pressing
        <TAB> or <Shift-TAB> will activate the next or previous
        such gadget. (defaults to TRUE, unlike regular Intuition string
        gadgets, which default to FALSE).
    GTST_EditHook (struct Hook *) - (new for V37) Hook to use as a custom
        integer gadget edit hook (StringExtend->EditHook) for this gadget.
        GadTools will allocate the StringExtend->WorkBuffer for you.
        Defaults to NULL.
    STRINGA_Justification - (new for V37) Controls the justification of
        the contents of an integer gadget.  Choose one of STRINGLEFT,
        STRINGRIGHT, or STRINGCENTER.  (Defaults to STRINGLEFT).
    STRINGA_ReplaceMode (BOOL) - (new for V37) If TRUE, this integer gadget
        is in replace-mode.  Defaults to FALSE (insert-mode).

    LISTVIEW_KIND (scrolling list):
    GTLV_Top (WORD) - Top item visible in the listview.  This value
        will be made reasonable if out-of-range (defaults to zero).
    GTLV_Labels (struct List *) - List of labels whose ln_Name fields
        are to be displayed in the listview.
    GTLV_ReadOnly (BOOL) - If TRUE, then listview is read-only.
    GTLV_ScrollWidth (UWORD) - Width of scroll bar for listview.
        Must be greater than zero (defaults to 16).
    GTLV_ShowSelected (struct Gadget *) - NULL to have the currently
        selected item displayed beneath the listview, or pointer to
        an already-created GadTools STRING_KIND gadget to have an
        editable display of the currently selected item.
    GTLV_Selected (UWORD) - Ordinal number of currently selected
        item, or ~0 to have no current selection (defaults to ~0).
    LAYOUTA_Spacing - Extra space to place between lines of listview
        (defaults to zero).

    MX_KIND (mutually exclusive, radio buttons):
    GTMX_Labels (STRPTR *) - Pointer to a NULL-terminated array of
        strings which are to be the labels beside each choice in a
        set of mutually exclusive gadgets.
    GTMX_Active (UWORD) - The ordinal number (counting from zero) of
        the initially active choice of an mx gadget (Defaults to zero).
    GTMX_Spacing (UWORD) - The amount of space between each choice
        of a set of mutually exclusive gadgets.  This amount is added
        to the font height to produce the vertical shift between
        choices. (defaults to one).
    LAYOUTA_Spacing - FOR COMPATIBILITY ONLY.  Use GTMX_Spacing instead.
        The number of extra pixels to insert between
        each choice of a mutually exclusive gadget.  This is added
        to the present gadget image height (9) to produce the
        true spacing between choices.  (defaults to
        FontHeight-8, which is zero for 8-point font users).

    NUMBER_KIND (read-only numeric):
    GTNM_Number - A signed long integer to be displayed as a read-only
         number (default 0).
    GTNM_Border (BOOL) - If TRUE, this flag asks for a recessed
        border to be placed around the gadget.

    PALETTE_KIND (color selection):
    GTPA_Depth (UWORD) - Number of bitplanes in the palette
        (defaults to 1).
    GTPA_Color (UBYTE) - Initially selected color of the palette
        (defaults to 1).
    GTPA_ColorOffset (UBYTE) - First color to use in palette
        (defaults to zero).
    GTPA_IndicatorWidth (UWORD) - The desired width of the current-color
        indicator, if you want one to the left of the palette.
    GTPA_IndicatorHeight (UWORD) - The desired height of the current-color
        indicator, if you want one above the palette.
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    SCROLLER_KIND (for scrolling through areas or lists):
    GTSC_Top (WORD) - Top visible in area scroller represents
        (defaults to zero).
    GTSC_Total (WORD) - Total in area scroller represents
        (defaults to zero).
    GTSC_Visible (WORD) - Number visible in scroller (defaults to 2).
    GTSC_Arrows (UWORD) - Asks for arrows to be attached to the scroller.
        The value supplied will be taken as the width of each arrow button
        for a horizontal scroller, or the height of each button for a
        vertical scroller (the other dimension will match the whole
        scroller).
    PGA_Freedom - Whether scroller is horizontal or vertical.
        Choose LORIENT_VERT or LORIENT_HORIZ (defaults to horiz).
    GA_Immediate (BOOL) - Hear every IDCMP_GADGETDOWN event from scroller
        (defaults to FALSE).
    GA_RelVerify (BOOL) - Hear every IDCMP_GADGETUP event from scroller
        (defaults to FALSE).
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    SLIDER_KIND (to indicate level or intensity):
    GTSL_Min (WORD) - Minimum level for slider (default 0).
    GTSL_Max (WORD) - Maximum level for slider (default 15).
    GTSL_Level (WORD) - Current level of slider (default 0).
    GTSL_MaxLevelLen (UWORD) - Max. length in characters of level string
        when rendered beside slider.
    GTSL_LevelFormat (STRPTR) - C-Style formatting string for slider
        level.  Be sure to use the 'l' (long) modifier.  This string
        is processed using exec/RawDoFmt(), so refer to that function
        for details.
    GTSL_LevelPlace - One of PLACETEXT_LEFT, PLACETEXT_RIGHT,
        PLACETEXT_ABOVE, or PLACETEXT_BELOW, indicating where the level
        indicator is to go relative to slider (default to PLACETEXT_LEFT).
    GTSL_DispFunc ( LONG (*function)(struct Gadget *, WORD) ) - Function
        to calculate level to be displayed.  A number-of-colors slider
        might want to set the slider up to think depth, and have a
        (1 << n) function here.  Defaults to none.  Your function must
        take a pointer to gadget as the first parameter, the level
        (a WORD) as the second, and return the result as a LONG.
    GA_Immediate (BOOL) - If you want to hear each slider IDCMP_GADGETDOWN
        event.
    GA_RelVerify (BOOL) - If you want to hear each slider IDCMP_GADGETUP
        event.
    PGA_Freedom - Set to LORIENT_VERT or LORIENT_HORIZ to have a
        vertical or horizontal slider.
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    STRING_KIND (text-entry):
    GTST_String (STRPTR) - The initial contents of the string gadget,
         or NULL (default) if string is to start empty.
    GTST_MaxChars (UWORD) - The maximum number of characters that the
        string gadget is to hold.
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).
    STRINGA_ExitHelp (BOOL) - (New for V37) Set to TRUE to have the
        help-key cause an exit from the string gadget.  You will
        then receive a GADGETUP with code = 0x5F (rawkey for help).
    GA_TabCycle (BOOL) - (New for V37) Set to TRUE so that pressing
        <TAB> or <Shift-TAB> will activate the next or previous
        such gadget. (defaults to TRUE, unlike regular Intuition string
        gadgets, which default to FALSE).
    GTST_EditHook (struct Hook *) - (new for V37) Hook to use as a custom
        string gadget edit hook (StringExtend->EditHook) for this gadget.
        GadTools will allocate the StringExtend->WorkBuffer for you.
        Defaults to NULL.
    STRINGA_Justification - (new for V37) Controls the justification of
        the contents of a string gadget.  Choose one of STRINGLEFT,
        STRINGRIGHT, or STRINGCENTER.  (Defaults to STRINGLEFT).
    STRINGA_ReplaceMode (BOOL) - (new for V37) If TRUE, this string gadget
        is in replace-mode.  Defaults to FALSE (insert-mode).

    TEXT_KIND (read-only text):
    GTTX_Text - Pointer to a NULL terminated string to be displayed,
        as a read-only text-display gadget, or NULL. defaults to NULL.
    GTTX_CopyText (BOOL) -  This flag instructs the text-display gadget
        to copy the supplied text string, instead of using only
        pointer to the string.  This only works for the initial value
        of GTTX_Text set at CreateGadget() time.  If you subsequently
        change GTTX_Text, the new text will be referenced by pointer,
        not copied.  Do not use this tag with a NULL GTTX_Text.
    GTTX_Border (BOOL) - If TRUE, this flag asks for a recessed
        border to be placed around the gadget.

RESULT
    gad - pointer to the new gadget, or NULL if the allocation failed
        or if previous was NULL.

EXAMPLE

NOTES
    Note that the ng_VisualInfo and ng_TextAttr fields of the
    NewGadget structure must be set to valid VisualInfo and
    TextAttr pointers, or this function will fail.

    Starting with V37, string and integer gadgets have the GFLG_TABCYCLE
    feature automatically.  If the user presses Tab or Shift-Tab while
    in a string or integer gadget, the next or previous one in
    sequence will be activated.  You will hear a GADGETUP with a code
    of 0x09.  Use {GA_TabCycle, FALSE} to supress this.

BUGS

SEE ALSO
    FreeGadgets(), GT_SetGadgetAttrs(), GetVisualInfo().


gadtools.library/CreateMenusA

NAME
    CreateMenusA -- Allocate and fill out a menu structure. (V36)
    CreateMenus -- Varargs stub for CreateMenus(). (V36)

SYNOPSIS
    menu = CreateMenusA(newmenu, taglist)
    D0                  A0       A1

    struct Menu *CreateMenusA(struct NewMenu *, struct TagItem *);

    menu = CreateMenus(newmenu, firsttag, ...)

    struct Menu *CreateMenus(struct NewMenu *, Tag, ...);

FUNCTION
    CreateMenusA() allocates and initializes a complete menu
    structure based on the supplied array of NewMenu structures.
    Optionally, CreateMenusA() can allocate and initialize a complete
    set of menu items and sub-items for a single menu title.  This
    is dictated by the contents of the array of NewMenus.

INPUTS
    newmenu - Pointer to an array of initialized struct NewMenus.
    taglist - Pointer to a TagItem list.

TAGS
    GTMN_FrontPen (UBYTE) - Pen number to be used for menu text.
        (defaults to zero).
    GTMN_FullMenu (BOOL) - (GadTools V37 and higher only)
        Requires that the NewMenu specification describes a complete
        menu strip, not a fragment.  If a fragment is found,
        CreateMenusA() will fail with a secondary error of
        GTMENU_INVALID.  (defaults to FALSE).
    GTMN_SecondaryError (ULONG *) - (GadTools V37 and higher only)
        Supply a pointer to a NULL-initialized ULONG to receive a
        descriptive error code.  Possible values:
        GTMENU_INVALID - NewMenu structure describes an illegal
            menu.  (CreateMenusA() will fail with a NULL result).
        GTMENU_TRIMMED - NewMenu structure has too many menus, items,
            or subitems (CreateMenusA() will succeed, returning a
            trimmed-down menu structure).
        GTMENU_NOMEM - CreateMenusA() ran out of memory.

RESULT
    menu - Pointer to the resulting initialized menu structure (or
        the resulting FirstItem), with all the links for menu items
        and subitems in place.
        The result will be NULL if CreateMenusA() could not allocate
        memory for the menus, or if the NewMenu array had an
        illegal arrangement (eg. NM_SUB following NM_TITLE).
        (see also the GTMN_SecondaryError tag above).

EXAMPLE

NOTES
    The strings you supply for menu text are not copied, and must
    be preserved for the life of the menu.
    The resulting menus have no positional information.  You will
    want to call LayoutMenusA() (or LayoutMenuItemsA()) to supply that.
    CreateMenusA() automatically provides you with a UserData field
    for each menu, menu-item or sub-item.  Use the GTMENU_USERDATA(menu)
    or GTMENUITEM_USERDATA(menuitem) macro to access it.

BUGS
    At present, if you put images into menus using IM_ITEM
    or IM_SUB for a NewMenu->Type, the image you supply must
    be an ordinary struct Image.  You may not use a 'custom
    image' (eg. one obtained from a boopsi image-class).

SEE ALSO
    LayoutMenusA(), FreeMenus(), gadtools.h/GTMENU_USERDATA(),
    gadtools.h/GTMENUITEM_USERDATA()


gadtools.library/DrawBevelBoxA

NAME
    DrawBevelBoxA -- Draws a bevelled box. (V36)
    DrawBevelBox -- Varargs stub for DrawBevelBox(). (V36)

SYNOPSIS
    DrawBevelBoxA(rport, left, top, width, height, taglist)
                  A0     D0    D1   D2     D3      A1

    VOID DrawBevelBoxA(struct RastPort *, WORD, WORD, WORD, WORD,
        struct TagItem *taglist);

    DrawBevelBox(rport, left, top, width, height, firsttag, ...)

    VOID DrawBevelBox(struct RastPort *, WORD, WORD, WORD, WORD,
        Tag, ...);

FUNCTION
    DrawBevelBoxA() renders a bevelled box of specified dimensions
    into the supplied RastPort.

INPUTS
    rport - The RastPort into which the box is to be drawn.
    left - The left edge of the box.
    top - The top edge of the box.
    width - The width of the box.
    height - The height of the box.
    taglist - Pointer to a TagItem list.

TAGS
    GTBB_Recessed (BOOL):  Set to anything for a recessed-looking box.
        If absent, the box defaults, it would be raised.
    GT_VisualInfo (APTR):  You MUST supply the value you obtained
        from an earlier call to GetVisualInfoA().

RESULT
    None.

EXAMPLE

NOTES
    DrawBevelBox() is a rendering operation, not a gadget.  That
    means you must refresh it at the appropriate time, like any
    other rendering operation.

BUGS

SEE ALSO
    GetVisualInfoA()


gadtools.library/FreeGadgets

NAME
    FreeGadgets -- Free a linked list of gadgets. (V36)

SYNOPSIS
    FreeGadgets(glist)
                A0

    VOID FreeGadgets(struct Gadget *glist);
                     A0

FUNCTION
    Frees any GadTools gadgets found on the linked list of gadgets
    beginning with the specified one.  Frees all the memory that was
    allocated by CreateGadgetA().  This function will return safely
    with no action if it receives a NULL parameter.

INPUTS
    glist - pointer to first gadget in list to be freed.

RESULT
    none

EXAMPLE

NOTES

BUGS

SEE ALSO
    CreateGadgetA()


gadtools.library/FreeMenus

NAME
    FreeMenus -- Frees memory allocated by CreateMenusA(). (V36)

SYNOPSIS
    FreeMenus(menu)
              A0

    VOID FreeMenus(struct Menu *);

FUNCTION
    Frees the menus allocated by CreateMenusA().  It is safe to
    call this function with a NULL parameter.

INPUTS
    menu - Pointer to menu structure (or first MenuItem) obtained
    from CreateMenusA().

RESULT
    None.

EXAMPLE

NOTES

BUGS

SEE ALSO
    CreateMenusA()


gadtools.library/FreeVisualInfo

NAME
    FreeVisualInfo -- Return any resources taken by GetVisualInfo. (V36)

SYNOPSIS
    FreeVisualInfo(vi)
                   A0

    VOID FreeVisualInfo(APTR);

FUNCTION
    FreeVisualInfo() returns any memory or other resources that
    were allocated by GetVisualInfoA().  You should only call this function
    once you are done with using the gadgets (i.e. after CloseWindow()),
    but while the screen is still valid (i.e. before CloseScreen() or
    UnlockPubScreen()).

INPUTS
    vi - Pointer that was obtained by calling GetVisualInfoA().

RESULT
    None.

EXAMPLE

NOTES

BUGS

SEE ALSO
    GetVisualInfoA()


gadtools.library/GetVisualInfoA

NAME
    GetVisualInfoA -- Get information GadTools needs for visuals. (V36)
    GetVisualInfo -- Varargs stub for GetVisualInfoA(). (V36)

SYNOPSIS
    vi = GetVisualInfoA(screen, taglist)
    D0                  A0      A1

    APTR vi = GetVisualInfoA(struct Screen *, struct TagItem *);

    vi = GetVisualInfo(screen, firsttag, ...)

    APTR vi = GetVisualInfo(struct Screen *, Tag, ...);

FUNCTION
    Get a pointer to a (private) block of data containing various bits
    of information that GadTools needs to ensure the best quality
    visuals.  Use the result in the NewGadget structure of any gadget
    you create, or as a parameter to the various menu calls.  Once the
    gadgets/menus are no longer needed (after the last CloseWindow),
    call FreeVisualInfo().

INPUTS
    screen - Pointer to the screen you will be opening on.
    taglist - Pointer to list of TagItems.

RESULT
    vi - Pointer to private data.

EXAMPLE

NOTES

BUGS

SEE ALSO
    FreeVisualInfo(), intuition/LockPubScreen(),
    intuition/UnlockPubScreen()


gadtools.library/GT_BeginRefresh

NAME
    GT_BeginRefresh -- Begin refreshing friendly to GadTools. (V36)

SYNOPSIS
    GT_BeginRefresh(win)
                    A0

    VOID GT_BeginRefresh(struct Window *);

FUNCTION
    Invokes the intuition.library/BeginRefresh() function in a manner
    friendly to the Gadget Toolkit.  This function call permits the
    GadTools gadgets to refresh themselves at the correct time.
    Call GT_EndRefresh() function when done.

INPUTS
    win - Pointer to Window structure for which a IDCMP_REFRESHWINDOW
        IDCMP event was received.

RESULT
    None.

EXAMPLE

NOTES
    The nature of GadTools precludes the use of the IDCMP flag
    WFLG_NOCAREREFRESH.  You must handle IDCMP_REFRESHWINDOW events
    in at least the minimal way, namely:

            case IDCMP_REFRESHWINDOW:
                GT_BeginRefresh(win);
                GT_EndRefresh(win, TRUE);
                break;

BUGS

SEE ALSO
    intuition.library/BeginRefresh()


gadtools.library/GT_EndRefresh

NAME
    GT_EndRefresh -- End refreshing friendly to GadTools. (V36)

SYNOPSIS
    GT_EndRefresh(win, complete)
                  A0   D0

    VOID GT_EndRefresh(struct Window *, BOOL complete);

FUNCTION
    Invokes the intuition.library/EndRefresh() function in a manner
    friendly to the Gadget Toolkit.  This function call permits
    GadTools gadgets to refresh themselves at the correct time.
    Call this function to EndRefresh() when you have used
    GT_BeginRefresh().

INPUTS
    win - Pointer to Window structure for which a IDCMP_REFRESHWINDOW
        IDCMP event was received.
    complete - TRUE when done with refreshing.

RESULT
    None.

EXAMPLE

NOTES

BUGS

SEE ALSO
    intuition.library/EndRefresh()


gadtools.library/GT_FilterIMsg

NAME
    GT_FilterIMsg -- Filter an IntuiMessage through GadTools. (V36)

SYNOPSIS
    modimsg = GT_FilterIMsg(imsg)
    D0                      A1

    struct IntuiMessage *GT_FilterIMsg(struct IntuiMessage *);

FUNCTION
    NOTE WELL:  Extremely few programs will actually need this function.
    You almost certainly should be using GT_GetIMsg() and GT_ReplyIMsg()
    only, and not GT_FilterIMsg() and GT_PostFilterIMsg().

    GT_FilterIMsg() takes the supplied IntuiMessage and asks the
    Gadget Toolkit to consider and possibly act on it.  Returns
    NULL if the message was only of significance to a GadTools gadget
    (i.e. not to you), else returns a pointer to a modified IDCMP
    message, which may contain additional information.
    You should examine the Class, Code, and IAddress fields of
    the returned message to learn what happened.  Do not make
    interpretations based on the original imsg.
    You should use GT_PostFilterIMsg() to revert to the original
    IntuiMessage once you are done with the modified one.

INPUTS
    imsg - An IntuiMessage you obtained from a Window's UserPort.

RESULT
    modimsg - A modified IntuiMessage, possibly with extra information
        from GadTools, or NULL.

EXAMPLE

NOTES

BUGS

SEE ALSO
    GT_GetIMsg(), GT_PostFilterIMsg()


gadtools.library/GT_GetIMsg

NAME
    GT_GetIMsg -- Get an IntuiMessage, with GadTools processing. (V36)

SYNOPSIS
    imsg = GT_GetIMsg(intuiport)
    D0                A0

    struct IntuiMessage *GT_GetIMsg(struct MsgPort *);

FUNCTION
    Use GT_GetIMsg() in place of the usual exec.library/GetMsg() when
    reading IntuiMessages from your window's UserPort.  If needed,
    the GadTools dispatcher will be invoked, and suitable processing
    will be done for gadget actions.  This function returns a pointer
    to a modified IntuiMessage (which is a copy of the original,
    possibly with some supplementary information from GadTools).
    If there are no messages (or if the only messages are meaningful
    only to GadTools, NULL will be returned.

INPUTS
    intuiport - The Window->UserPort of a window that is using the
        Gadget Toolkit.

RESULT
    imsg - Pointer to modified IntuiMessage, or NULL if there are
        no applicable messages.

EXAMPLE

NOTES
    Be sure to use GT_ReplyIMsg() and not exec.library/ReplyMsg() on
    messages obtained with GT_GetIMsg().
    If you intend to do more with the resulting message than read
    its fields, act on it, and reply it, you may find GT_FilterIMsg()
    more appropriate.

BUGS

SEE ALSO
    GT_ReplyIMsg(), GT_FilterIMsg()


gadtools.library/GT_PostFilterIMsg

NAME
    GT_PostFilterIMsg -- Return the unfiltered message after
        GT_FilterIMsg() was called, and clean up. (V36)

SYNOPSIS
    imsg = GT_PostFilterIMsg(modimsg)
    D0                       A1

    struct IntuiMessage *GT_PostFilterIMsg(struct IntuiMessage *);

FUNCTION
    NOTE WELL:  Extremely few programs will actually need this function.
    You almost certainly should be using GT_GetIMsg() and GT_ReplyIMsg()
    only, and not GT_FilterIMsg() and GT_PostFilterIMsg().

    Performs any clean-up necessitated by a previous call to
    GT_FilterIMsg().  The original IntuiMessage is now yours to handle.
    Do not interpret the fields of the original IntuiMessage, but
    rather use only the one you got from GT_FilterIMsg().  You
    may only do message related things at this point, such as queueing
    it up or replying it.  Since you got the message with
    exec.library/GetMsg(), your responsibilities do include replying
    it with exec.library/ReplyMsg(). This function may be safely
    called with a NULL parameter.

INPUTS
    modimsg - A modified IntuiMessage obtained with GT_FilterIMsg().

RESULT
    imsg - A pointer to the original IntuiMessage, if GT_FilterIMsg()
        returned non-NULL.

EXAMPLE

NOTES
    Be sure to use exec.library/ReplyMsg() on the original IntuiMessage
    you obtained with GetMsg(), (which is the what you passed to
    GT_FilterIMsg()), and not on the parameter of this function.

BUGS

SEE ALSO
    GT_FilterIMsg()


gadtools.library/GT_RefreshWindow

NAME
    GT_RefreshWindow -- Refresh all the GadTools gadgets. (V36)

SYNOPSIS
    GT_RefreshWindow(win, req)
                     A0   A1

    VOID GT_RefreshWindow(struct Window *, struct Requester *);

FUNCTION
    Perform the initial refresh of all the GadTools gadgets you have
    created.  After you have opened your window, you must call this
    function.  Or, if you have opened your window without gadgets,
    you add the gadgets with intuition.library/AddGList(),
    refresh them using intuition.library/RefreshGList(), then call
    this function.
    You should not need this function at other times.

INPUTS
    win - Pointer to the Window containing GadTools gadgets.
    req - Pointer to requester, or NULL if not a requester (currently
        ignored - use NULL).

RESULT
    None.

EXAMPLE

NOTES
    req must currently be NULL.  GadTools gadgets are not supported
    in requesters.  This field may allow such support at a future date.

BUGS

SEE ALSO
    GT_BeginRefresh()


gadtools.library/GT_ReplyIMsg

NAME
    GT_ReplyIMsg -- Reply a message obtained with GT_GetIMsg(). (V36)

SYNOPSIS
    GT_ReplyIMsg(imsg)
                 A1

    VOID GT_ReplyIMsg(struct IntuiMessage *);

FUNCTION
    Reply a modified IntuiMessage obtained with GT_GetIMsg().
    If you use GT_GetIMsg(), use this function where you would normally
    have used exec.library/ReplyMsg().
    You may safely call this routine with a NULL pointer (nothing
    will be done).

INPUTS
    imsg - A modified IntuiMessage obtained with GT_GetIMsg().

RESULT
    None.

EXAMPLE

NOTES
    When using GadTools, you MUST explicitly GT_ReplyIMsg()
    all messages you receive.  You cannot depend on CloseWindow()
    to handle messages you have not replied.

BUGS

SEE ALSO
    GT_GetIMsg()


gadtools.library/GT_SetGadgetAttrsA

NAME
    GT_SetGadgetAttrsA -- Change the attributes of a GadTools gadget. (V36)
    GT_SetGadgetAttrs -- Varargs stub for GT_SetGadgetAttrsA(). (V36)

SYNOPSIS
    GT_SetGadgetAttrsA(gad, win, req, taglist)
                       A0   A1   A2   A3

    VOID GT_SetGadgetAttrsA(struct Gadget *, struct Window *,
        struct Requester *, struct TagItem *);

    GT_SetGadgetAttrs(gad, win, req, firsttag, ...)

    VOID GT_SetGadgetAttrs(struct Gadget *, struct Window *,
        struct Requester *, Tag, ...);

FUNCTION
    Change the attributes of the specified gadget, according to the
    attributes chosen in the tag list.

INPUTS
    gad - Pointer to the gadget in question.
    win - Pointer to the window containing the gadget.
    req - Pointer to the requester containing the gadget, or NULL if
        not in a requester.  (Not yet implemented, use NULL).
    taglist - Pointer to TagItem list.

TAGS
    BUTTON_KIND:
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    CHECKBOX_KIND:
    GTCB_Checked (BOOL) - Initial state of checkbox, defaults to FALSE.
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    CYCLE_KIND:
    GTCY_Active (UWORD) - The ordinal number (counting from zero) of
        the active choice of a cycle gadget (defaults to zero).
    GTCY_Labels (STRPTR *) - (GadTools V37 and higher only)
        Pointer to NULL-terminated array of strings
        that are the choices offered by the cycle gadget.
    GA_Disabled (BOOL) - (GadTools V37 and higher only)
        Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    INTEGER_KIND:
    GTIN_Number (ULONG) - The initial contents of the integer gadget
        (default zero).
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    LISTVIEW_KIND:
    GTLV_Top (WORD) - Top item visible in the listview.  This value
        will be made reasonable if out-of-range (defaults to zero).
    GTLV_Labels (struct List *) - List of labels whose ln_Name fields
        are to be displayed in the listview.  Use a value of ~0 to
        "detach" your List from the display.  You must detach your list
        before modifying the List structure, since GadTools reserves
        the right to traverse it on another task's schedule.  When you
        are done, attach the list by using the tag pair
        {GTLV_Labels, list}.
    GTLV_Selected (UWORD) - Ordinal number of currently selected
        item (defaults to zero if GTLV_ShowSelected is set).

    MX_KIND:
    GTMX_Active (UWORD) - The ordinal number (counting from zero) of
        the active choice of an mx gadget (Defaults to zero).

    NUMBER_KIND:
    GTNM_Number - A signed long integer to be displayed as a read-only
         number (default 0).

    PALETTE_KIND:
    GTPA_Color (UBYTE) - Initially selected color of the palette
        (defaults to 1).
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    SCROLLER_KIND:
    GTSC_Top (WORD) - Top visible in scroller (defaults to zero).
    GTSC_Total (WORD) - Total in scroller area (defaults to zero).
    GTSC_Visible (WORD) - Number visible in scroller (defaults to 2).
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    SLIDER_KIND:
    GTSL_Min (WORD) - Minimum level for slider (default 0).
    GTSL_Max (WORD) - Maximum level for slider (default 15).
    GTSL_Level (WORD) - Current level of slider (default 0).
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    STRING_KIND:
    GTST_String (STRPTR) - The initial contents of the string gadget,
         or NULL (default) if string is to start empty.
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    TEXT_KIND:
    GTTX_Text - Pointer to a NULL terminated string to be displayed,
        as a read-only text-display gadget, or NULL. defaults to NULL.

RESULT
    None.

EXAMPLE

NOTES
    req must currently be NULL.  GadTools gadgets are not supported
    in requesters.  This field may allow such support at a future date.

    This function may not be called inside of a GT_BeginRefresh() /
    GT_EndRefresh() session.  (As always, restrict yourself to simple
    rendering functions).

BUGS

SEE ALSO


gadtools.library/LayoutMenuItemsA

NAME
    LayoutMenuItemsA -- Position all the menu items. (V36)
    LayoutMenuItems -- Varargs stub for LayoutMenuItemsA(). (V36)

SYNOPSIS
    success = LayoutMenuItemsA(menuitem, vi, taglist)
    D0                         A0        A1  A2

    BOOL LayoutMenuItemsA(struct MenuItem *, APTR, struct TagItem *);

    success = LayoutMenuItems(menuitem, vi, firsttag, ...)

    BOOL LayoutMenuItemsA(struct MenuItem *, APTR, Tag, ...);

FUNCTION
    Lays out all the menu items and sub-items according to
    the supplied visual information and tag parameters.  You would use this
    if you used CreateMenusA() to make a single menu-pane (with sub-items,
    if any), instead of a whole menu strip.
    This routine attempts to columnize and/or shift the MenuItems in
    the event that a menu would be too tall or too wide.

INPUTS
    menuitem - Pointer to first MenuItem in a linked list of
        items.
    vi - Pointer returned by GetVisualInfoA().
    taglist - Pointer to a TagItem list.

TAGS
    GTMN_TextAttr (struct TextAttr *) - Text Attribute to use for
        menu-items and sub-items.  If not supplied, the screen's
        font will be used.  This font must be openable via OpenFont()
        when this function is called.
    GTMN_Menu (struct Menu *) - Pointer to the Menu structure whose
        FirstItem is the MenuItem supplied above.  If the menu items are
        such that they need to be columnized or shifted, the Menu
        structure is needed to perform the complete calculation.
        It is suggested you always provide this information.

RESULT
    success - TRUE if successful, false otherwise (signifies that
        the TextAttr wasn't openable).

EXAMPLE

NOTES

BUGS
    If a menu ends up being wider than the whole screen, it will
    run off the right-hand side.

SEE ALSO
    CreateMenusA(), GetVisualInfoA()


gadtools.library/LayoutMenusA

NAME
    LayoutMenusA -- Position all the menus and menu items. (V36)
    LayoutMenus -- Varargs stub for LayoutMenusA(). (V36)

SYNOPSIS
    success = LayoutMenusA(menu, vi, taglist)
    D0                     A0    A1  A2

    BOOL LayoutMenusA(struct Menu *, APTR, struct TagItem *);

    success = LayoutMenus(menu, vi, firsttag, ...)

    BOOL LayoutMenus(struct Menu *, APTR, Tag, ...);

FUNCTION
    Lays out all the menus, menu items and sub-items in the supplied
    menu according to the supplied visual information and tag parameters.
    This routine attempts to columnize and/or shift the MenuItems in
    the event that a menu would be too tall or too wide.

INPUTS
    menu - Pointer to menu obtained from CreateMenusA().
    vi - Pointer returned by GetVisualInfoA().
    taglist - Pointer to a TagItem list.

TAGS
    GTMN_TextAttr (struct TextAttr *) - Text Attribute to use for
        menu-items and sub-items.  If not supplied, the screen's
        font will be used.  This font must be openable via OpenFont()
        when this function is called.

RESULT
    success - TRUE if successful, false otherwise (signifies that
        the TextAttr wasn't openable).

EXAMPLE

NOTES
    When using this function, there is no need to also call
    LayoutMenuItemsA().

BUGS
    If a menu ends up being wider than the whole screen, it will
    run off the right-hand side.

SEE ALSO
    CreateMenusA(), GetVisualInfoA()


mathieeedoubbas.doc

 IEEEDPAbs()       IEEEDPCmp()      IEEEDPFloor()      IEEEDPNeg()
 IEEEDPAdd()       IEEEDPDiv()      IEEEDPFlt()        IEEEDPSub()
 IEEEDPCeil()      IEEEDPFix()      IEEEDPMul()        IEEEDPTst()


mathieeedoubbas.library/IEEEDPAbs

NAME
    IEEEDPAbs -- compute absolute value of IEEE double precision argument

SYNOPSIS
      x   = IEEEDPAbs(  y  );
    d0/d1             d0/d1

    double  x,y;

FUNCTION
    Take the absolute value of argument y and return it to caller.

INPUTS
    y -- IEEE double precision floating point value

RESULT
    x -- IEEE double precision floating point value

BUGS

SEE ALSO


mathieeedoubbas.library/IEEEDPAdd

NAME
    IEEEDPAdd -- add one double precision IEEE number to another

SYNOPSIS
      x   = IEEEDPAdd(  y  ,  z  );
    d0/d1             d0/d1 d2/d3

    double  x,y,z;

FUNCTION
    Compute x = y + z in IEEE double precision.

INPUTS
    y -- IEEE double precision floating point value
    z -- IEEE double precision floating point value

RESULT
    x -- IEEE double precision floating point value

BUGS

SEE ALSO
    IEEEDPSub


mathieeedoubbas.library/IEEEDPCeil

NAME
    IEEEDPCeil -- compute Ceil function of IEEE double precision number

SYNOPSIS
      x   = IEEEDPCeil(  y  );
    d0/d1              d0/d1

    double  x,y;

FUNCTION
    Calculate the least integer greater than or equal to x and return it.
    This value may have more than 32 bits of significance.
    This identity is true.  Ceil(x) = -Floor(-x).

INPUTS
    y -- IEEE double precision floating point value

RESULT
    x -- IEEE double precision floating point value

BUGS

SEE ALSO
    IEEEDPFloor


mathieeedoubbas.library/IEEEDPCmp

NAME
    IEEEDPCmp -- compare two double precision floating point numbers

SYNOPSIS
      c   = IEEEDPCmp(  y  ,  z  );
      d0              d0/d1 d2/d3

    double  y,z;
    long    c;

FUNCTION
    Compare y with z. Set the condition codes for less, greater, or
    equal. Set return value c to -1 if y<z, or +1 if y>z, or 0 if
    y == z.

INPUTS
    y -- IEEE double precision floating point value
    z -- IEEE double precision floating point value

RESULT
   c = 1   cc = gt         for (y > z)
   c = 0   cc = eq         for (y == z)
   c = -1  cc = lt         for (y < z)

BUGS

SEE ALSO


mathieeedoubbas.library/IEEEDPDiv

NAME
    IEEEDPDiv -- divide one double precision IEEE by another

SYNOPSIS
      x   = IEEEDPDiv(  y  ,  z  );
    d0/d1             d0/d1 d2/d3

    double  x,y,z;

FUNCTION
    Compute x = y / z in IEEE double precision.

INPUTS
    y -- IEEE double precision floating point value
    z -- IEEE double precision floating point value

RESULT
    x -- IEEE double precision floating point value

BUGS

SEE ALSO
    IEEEDPMul


mathieeedoubbas.library/IEEEDPFix

NAME
    IEEEDPFix -- convert IEEE double float to integer

SYNOPSIS
    x   = IEEEDPFix(  y  );
    d0              d0/d1

    long    x;
    double  y;

FUNCTION
    Convert IEEE double precision argument to a 32 bit signed integer
    and return result.

INPUTS
    y -- IEEE double precision floating point value

RESULT
    if no overflow occured then return
            x -- 32 bit signed integer
    if overflow return largest +- integer
            For round to zero

BUGS

SEE ALSO
    IEEEDPFlt


mathieeedoubbas.library/IEEEDPFloor

NAME
    IEEEDPFloor -- compute Floor function of IEEE double precision number

SYNOPSIS
      x   = IEEEDPFloor(  y  );
    d0/d1               d0/d1

    double  x,y;

FUNCTION
    Calculate the largest integer less than or equal to x and return it.
    This value may have more than 32 bits of significance.

INPUTS
    y -- IEEE double precision floating point value

RESULT
    x -- IEEE double precision floating point value

BUGS

SEE ALSO
    IEEEDPCeil


mathieeedoubbas.library/IEEEDPFlt

NAME
    IEEEDPFlt -- convert integer to IEEE double precision number

SYNOPSIS
      x   = IEEEDPFlt(  y  );
    d0/d1              d0

    double  x;
    long    y;

FUNCTION
    Convert a signed 32 bit value to a double precision IEEE value
    and return it in d0/d1. No exceptions can occur with this
    function.

INPUTS
    y -- 32 bit integer in d0

RESULT
    x is a 64 bit double precision IEEE value

BUGS

SEE ALSO
    IEEEDPFix


mathieeedoubbas.library/IEEEDPMul

NAME
    IEEEDPMul -- multiply one double precision IEEE number by another

SYNOPSIS
      x   = IEEEDPMul(  y  ,  z  );
    d0/d1             d0/d1 d2/d3

    double  x,y,z;

FUNCTION
    Compute x = y * z in IEEE double precision.

INPUTS
    y -- IEEE double precision floating point value
    z -- IEEE double precision floating point value

RESULT
    x -- IEEE double precision floating point value

BUGS

SEE ALSO
    IEEEDPDiv


mathieeedoubbas.library/IEEEDPNeg

NAME
    IEEEDPNeg -- compute negative value of IEEE double precision number

SYNOPSIS
      x   = IEEEDPNeg(  y  );
    d0/d1             d0/d1

    double  x,y;

FUNCTION
    Invert the sign of argument y and return it to caller.

INPUTS
    y - IEEE double precision floating point value

RESULT
    x - IEEE double precision floating point value

BUGS

SEE ALSO


mathieeedoubbas.library/IEEEDPSub

NAME
    IEEEDPSub -- subtract one double precision IEEE number from another

SYNOPSIS
      x   = IEEEDPSub(  y  ,  z  );
    d0/d1             d0/d1 d2/d3

    double  x,y,z;

FUNCTION
    Compute x = y - z in IEEE double precision.

INPUTS
    y -- IEEE double precision floating point value
    z -- IEEE double precision floating point value

RESULT
    x -- IEEE double precision floating point value

BUGS

SEE ALSO
    IEEEDPAdd


mathieeedoubbas.library/IEEEDPTst

NAME
    IEEEDPTst -- compare IEEE double precision value to 0.0

SYNOPSIS
      c   = IEEEDPTst(  y  );
      d0              d0/d1

    double  y;
    long    c;

FUNCTION
    Compare y to 0.0, set the condition codes for less than, greater
    than, or equal to 0.0.  Set the return value c to -1 if less than,
    to +1 if greater than, or 0 if equal to 0.0.

INPUTS
    y -- IEEE double precision floating point value

RESULT
    c = 1   cc = gt         for (y > 0.0)
    c = 0   cc = eq         for (y == 0.0)
    c = -1  cc = lt         for (y < 0.0)

BUGS

SEE ALSO


wb.doc

 AddAppIconA()          AddAppWindowA()      RemoveAppMenuItem()
 AddAppMenuItemA()      RemoveAppIcon()      RemoveAppWindow()


workbench.library/AddAppIconA

NAME
    AddAppIcon - add an icon to workbench's list of appicons.        (V36)

SYNOPSIS
    AppIcon = AddAppIconA(id, userdata, text, msgport,
       D0                 D0     D1      A0     A1

                                    lock, diskobj, taglist)
                                     A2      A3      A4

    struct AppIcon *AddAppIconA(ULONG, ULONG, char *,
            struct MsgPort *, struct FileLock *, struct DiskObject *,
            struct TagItem *);

    Alternate, varargs version:
    struct AppIcon *AddAppIcon(ULONG, ULONG, char *,
                    struct MsgPort *, struct FileLock *,
                    struct DiskObject *,
                    tag1, data1,
                    tag2, data2,
                    ...
                    TAG_END );

FUNCTION
    Attempt to add an icon to workbench's list of appicons.  If
    successful, the icon is displayed on the workbench (the same
    place disk icons are displayed).
    This call is provided to allow applications to be notified when
    a graphical object (non neccessarely associated with a file)
    gets 'manipulated'. (explained later).
    The notification consists of an AppMessage (found in workbench.h/i)
    of type 'MTYPE_APPICON' arriving at the message port you specified.
    The types of 'manipulation' that can occur are:
    1. Double-clicking on the icon.  am_NumArgs will be zero and
       am_ArgList will be NULL.
    2. Dropping an icon or icons on your appicon.  am_NumArgs will
      be the number of icons droppped on your app icon plus one.
      am_ArgList will be an array of ptrs to WBArg structures.
      Refer to the 'WBStartup Message' section of the RKM for more info.
    3. Dropping your appicon on another icon.  NOT SUPPORTED.

INPUTS
    id       - this variable is strictly for your own use and is ignored
               by workbench.  Typical uses in C are in switch and case
               statements, and in assembly language table lookup.
    userdata - this variable is strictly for your own use and is ignored
               by workbench.
    text     - name of icon (char *)
    lock     - NULL    (Currently unused)
    msgport  - pointer to message port workbench will use to send you an
               AppMessage message of type 'MTYPE_APPICON' when your icon
               gets 'manipulted' (explained above).
    diskobj  - pointer to a DiskObject structure filled in as follows:
        do_Magic - NULL
        do_Version - NULL
        do_Gadget - a gadget structure filled in as follows:
            NextGadget - NULL
            LeftEdge - NULL
            TopEdge - NULL
            Width - width of icon hit-box
            Height - height of icon hit-box
            Flags - NULL or GADGHIMAGE
            Activation - NULL
            GadgetType - NULL
            GadgetRender - pointer to Image structure filled in as follows:
                LeftEdge - NULL
                TopEdge - NULL
                Width - width of image (must be <= Width of hit box)
                Height - height of image (must be <= Height of hit box)
                Depth - # of bit-planes in image
                ImageData - pointer to actual word aligned bits (CHIP MEM)
                PlanePick - Plane mask ((1 << depth) - 1)
                PlaneOnOff - 0
                NextImage - NULL
            SelectRender - pointer to alternate Image struct or NULL
            GadgetText - NULL
            MutualExclude - NULL
            SpecialInfo - NULL
            GadgetID - NULL
            UserData - NULL
        do_Type - NULL
        do_DefaultTool - NULL
        do_ToolTypes - NULL
        do_CurrentX - NO_ICON_POSITION (recommended)
        do_CurrentY - NO_ICON_POSITION (recommended)
        do_DrawerData - NULL
        do_ToolWindow - NULL
        do_StackSize - NULL

    (an easy way to create one of these (a DiskObject) is to create an icon
    with the V2.0 icon editor and save it out.  Your application can then
    call GetDiskObject on it and pass that to AddAppIcon.)

    taglist  - ptr to a list of tag items.  Must be NULL for V2.0.

RESULTS
    AppIcon  - a pointer to an appicon structure which you pass to
               RemoveAppIcon when you want to remove the icon
               from workbench's list of appicons.  NULL
               if workbench was unable to add your icon; typically
               happens when workbench is not running or under low
               memory conditions.

EXAMPLE
    You could design a print-spooler icon and add it to the workbench.
    Any file dropped on the print spooler would be printed.  If the
    user double-clicked (opended) your printer-spooler icon, you could
    open a window showing the status of the print spool, allow changes
    to print priorities, allow deletions, etc.  If you registered this
    window as an 'appwindow' (explained in workbench.library AddAppWindow)
    files could also be dropped in the window and added to the spool.

SEE ALSO
    RemoveAppIcon()

BUGS
    Currently Info cannot be obtained on appicons.


workbench.library/AddAppMenuItemA

NAME
    AddAppMenuItem - add a menuitem to workbench's list              (V36)
                    of appmenuitems.

SYNOPSIS
    AppMenuItem = AddAppMenuItemA(id, userdata, text, msgport, taglist)
    D0                            D0     D1      A0     A1       A2

    struct AppMenuItem *AddAppMenuItemA(ULONG, ULONG, char *,
                                            struct MsgPort *,
                                            struct TagItem *);

    Alternate, varargs version:
    struct AppMenuItem *AddAppMenuItem(ULONG, ULONG, char *,
                                    struct MsgPort *,
                                    tag1, data1,
                                    tag2, data2,
                                    ...
                                    TAG_END );

FUNCTION
    Attempt to add the text as a menuitem to workbench's list
    of appmenuitems (the 'Tools' menu strip).

INPUTS
    id       - this variable is strictly for your own use and is ignored
               by workbench.  Typical uses in C are in switch and case
               statements, and in assembly language table lookup.
    userdata - this variable is strictly for your own use and is ignored
               by workbench.
    text     - text for the menuitem (char *)
    msgport  - pointer to message port workbench will use to send you an
               AppMessage message of type 'MTYPE_APPMENUITEM' when your
               menuitem gets selected.
    taglist  - ptr to a list of tag items.  Must be NULL for V2.0.

RESULTS
    AppMenuItem - a pointer to an appmenuitem structure which you pass to
                  RemoveAppMenuItem when you want to remove the menuitem
                  from workbench's list of appmenuitems.  NULL if
                  workbench was unable to add your menuitem; typically
                  happens when workbench is not running or under low
                  memory conditions.

SEE ALSO
    RemoveAppMenuItem()

BUGS
    Currently does not limit the system to 63 menu items...
    Any menu items after the 63rd will not be selectable.


workbench.library/AddAppWindowA

NAME
    AddAppWindow - add a window to workbench's list of appwindows.  (V36)

SYNOPSIS
    AppWindow = AddAppWindowA(id, userdata, window, msgport, taglist)
    D0                        D0     D1       A0      A1       A2

    struct AppWindow *AddAppWindowA(ULONG, ULONG, struct Window *,
                                    struct MsgPort *, struct TagItem *);

    Alternate, varargs version:
    struct AppWindow *AddAppWindow(ULONG, ULONG, struct Window *,
                                    struct MsgPort *
                                    tag1, data1,
                                    tag2, data2,
                                    ...
                                    TAG_END );

FUNCTION
    Attempt to add the window to workbench's list of appwindows.
    Normally non-workbench windows (those not opened by workbench)
    cannot have icons dropped in them.  This call is provided to
    allow applications to be notified when an icon or icons get
    dropped inside a window that they have registered with workbench.
    The notification consists of an AppMessage (found in workbench.h/i)
    of type 'MTYPE_APPWINDOW' arriving at the message port you specified.
    What you do with the list of icons (pointed to by am_ArgList) is
    up to you, but generally you would want to call GetDiskObjectNew on
    them.

INPUTS
    id       - this variable is strictly for your own use and is ignored
               by workbench.  Typical uses in C are in switch and case
               statements, and in assembly language table lookup.
    userdata - this variable is strictly for your own use and is ignored
               by workbench.
    window   - pointer to window to add.
    msgport  - pointer to message port workbench will use to send you an
               AppMessage message of type 'MTYPE_APPWINDOW' when your
               window gets an icon or icons dropped in it.
    taglist  - ptr to a list of tag items.  Must be NULL for V2.0.

RESULTS
    AppWindow - a pointer to an appwindow structure which you pass to
                RemoveAppWindow when you want to remove the window
                from workbench's list of appwindows.  NULL
                if workbench was unable to add your window; typically
                happens when workbench is not running or under low
                memory conditions.

SEE ALSO
    RemoveAppWindow()

NOTES
   The V2.0 icon editor is an example of an app window.  Note that app
   window applications generally want to call GetDiskObjectNew
   (as opposed to GetDiskObject) to get the disk object for the icon
   dropped in the window.

BUGS
    None


workbench.library/RemoveAppIcon

NAME
    RemoveAppIcon - remove an icon from workbench's list            (V36)
                     of appicons.

SYNOPSIS
    error = RemoveAppIcon(AppIcon)
     D0                     A0
    BOOL RemoveAppIcon(struct AppIcon *);

FUNCTION
    Attempt to remove an appicon from workbench's list of appicons.

INPUTS
    AppIcon - pointer to an AppIcon structure returned by AddAppIcon.

RESULTS
    error - Currently always TRUE...

NOTES
    As with anything that deals with async operation, you will need to
    do a final check for messages on your App message port for messages
    that may have come in between the last time you checked and the
    call to removed the App.

SEE ALSO
    AddAppIconA()

BUGS
    None


workbench.library/RemoveAppMenuItem

NAME
    RemoveAppMenuItem - remove a menuitem from workbench's list      (V36)
                        of appmenuitems.

SYNOPSIS
    error = RemoveAppMenuItem(AppMenuItem)
     D0                            A0
    BOOL RemoveAppMenuItem(struct AppMenuItem *);

FUNCTION
    Attempt to remove an appmenuitem from workbench's list
    of appmenuitems.

INPUTS
    AppMenuItem - pointer to an AppMenuItem structure returned by
                  AddAppMenuItem.

RESULTS
    error - Currently always TRUE...

NOTES
    As with anything that deals with async operation, you will need to
    do a final check for messages on your App message port for messages
    that may have come in between the last time you checked and the
    call to removed the App.

SEE ALSO
    AddAppMenuItemA()

BUGS
    None


workbench.library/RemoveAppWindow

NAME
    RemoveAppWindow - remove a window from workbench's list         (V36)
                      of appwindows.

SYNOPSIS
    error = RemoveAppWindow(AppWindow)
     D0                       A0
    BOOL RemoveAppWindow(struct AppWindow *);

FUNCTION
    Attempt to remove an appwindow from workbench's list of appwindows.

INPUTS
    AppWindow - pointer to an AppWindow structure returned by
                AddAppWindow.

RESULTS
    error - Currently always TRUE...

NOTES
    As with anything that deals with async operation, you will need to
    do a final check for messages on your App message port for messages
    that may have come in between the last time you checked and the
    call to removed the App.

SEE ALSO
    AddAppWindowA()

BUGS
    None


graphics.doc

 AddAnimOb()                 ExtendFont()             OwnBlitter()
 AddBob()                    FindDisplayInfo()        PolyDraw()
 AddFont()                   Flood()                  QBlit()
 AddVSprite()                FontExtent()             QBSBlit()
 AllocRaster()               FreeColorMap()           ReadPixel()
 AndRectRegion()             FreeCopList()            ReadPixelArray8()
 AndRegionRegion()           FreeCprList()            ReadPixelLine8()
 Animate()                   FreeGBuffers()           RectFill()
 AreaCircle()                FreeRaster()             RemBob()
 AreaDraw()                  FreeSprite()             RemFont()
 AreaEllipse()               FreeVPortCopLists()      RemIBob()
 AreaEnd()                   GetColorMap()            RemVSprite()
 AreaMove()                  GetDisplayInfoData()     ScalerDiv()
 AskFont()                   GetGBuffers()            ScrollRaster()
 AskSoftStyle()              GetRGB4()                ScrollVPort()
 AttemptLockLayerRom()       GetSprite()              SetAPen()
 BitMapScale()               GetVPModeID()            SetBPen()
 BltBitMap()                 GfxAssociate()           SetCollision()
 BltBitMapRastPort()         GfxFree()                SetDrMd()
 BltClear()                  GfxLookUP()              SetFont()
 BltMaskBitMapRastPort()     GfxNew()                 SetOPen()
 BltPattern()                InitArea()               SetRast()
 BltTemplate()               InitBitMap()             SetRGB4()
 CBump()                     InitGels()               SetRGB4CM()
 CEND                        InitGMasks()             SetSoftStyle()
 ChangeSprite()              InitMasks()              SortGList()
 CINIT                       InitRastPort()           StripFont()
 ClearEOL()                  InitTmpRas()             SyncSBitMap()
 ClearRectRegion()           InitView()               Text()
 ClearRegion()               InitVPort()              TextExtent()
 ClearScreen()               LoadRGB4()               TextFit()
 ClipBlit()                  LoadView()               TextLength()
 CloseFont()                 LockLayerRom()           UnlockLayerRom()
 CloseMonitor()              MakeVPort()              VBeamPos()
 CMOVE                       ModeNotAvailable()       VideoControl()
 CopySBitMap()               Move()                   WaitBlit()
 CWAIT                       MoveSprite()             WaitBOVP()
 DisownBlitter()             MrgCop()                 WaitTOF()
 DisposeRegion()             NewRegion()              WeighTAMatch()
 DoCollision()               NextDisplayInfo()        WritePixel()
 Draw()                      OpenFont()               WritePixelArray8()
 DrawEllipse()               OpenMonitor()            WritePixelLine8()
 DrawGList()                 OrRectRegion()           XorRectRegion()
 EraseRect()                 OrRegionRegion()         XorRegionRegion()


graphics.library/AddAnimOb

NAME
    AddAnimOb  --  Add an AnimOb to the linked list of AnimObs.

SYNOPSIS
    AddAnimOb(anOb, anKey, rp)
              A0    A1     A2

    void AddAnimOb(struct AnimOb *,struct AnimOb **, struct RastPort *);

FUNCTION
    Links this AnimOb into the current list pointed to by animKey.
    Initializes all the Timers of the AnimOb's components.
    Calls AddBob with each component's Bob.
    rp->GelsInfo must point to an initialized GelsInfo structure.

INPUTS
    anOb  = pointer to the AnimOb structure to be added to the list
    anKey = address of a pointer to the first AnimOb in the list
            (anKey = NULL if there are no AnimObs in the list so far)
    rp    = pointer to a valid RastPort

RESULT

BUGS

SEE ALSO
    Animate() graphics/rastport.h graphics/gels.h


graphics.library/AddBob

NAME
    AddBob -- Adds a Bob to current gel list.

SYNOPSIS
    AddBob(Bob, rp)
           A0   A1

    void AddBob(struct Bob *, struct RastPort *);

FUNCTION
    Sets up the system Bob flags, then links this gel into the list
    via AddVSprite.

INPUTS
    Bob = pointer to the Bob structure to be added to the gel list
    rp  = pointer to a RastPort structure

RESULT

BUGS

SEE ALSO
    InitGels()  AddVSprite()  graphics/gels.h  graphics/rastport.h


graphics.library/AddFont

NAME
    AddFont -- add a font to the system list

SYNOPSIS
    AddFont(textFont)
            A1

    void AddFont(struct TextFont *);

FUNCTION
    This function adds the text font to the system, making it
    available for use by any application.  The font added must be
    in public memory, and remain until successfully removed.

INPUTS
    textFont - a TextFont structure in public ram.

RESULT

BUGS

SEE ALSO
    SetFont()  RemFont()  graphics/text.h


graphics.library/AddVSprite

NAME
    AddVSprite -- Add a VSprite to the current gel list.

SYNOPSIS
    AddVSprite(vs, rp)
               A0  A1

    void AddVSprite(struct VSprite *, struct RastPort *);

FUNCTION
    Sets up the system VSprite flags
    Links this VSprite into the current gel list using its Y,X

INPUTS
    vs = pointer to the VSprite structure to be added to the gel list
    rp = pointer to a RastPort structure

RESULT

BUGS

SEE ALSO
    InitGels()  graphics/rastport.h  graphics/gels.h


graphics.library/AllocRaster

NAME
    AllocRaster -- Allocate space for a bitplane.

SYNOPSIS
    planeptr = AllocRaster( width, height )
       d0                    d0:16  d1:16

    PLANEPTR AllocRaster(UWORD,UWORD);

FUNCTION
    This function calls the memory allocation routines
    to allocate memory space for a bitplane width bits
    wide and height bits high.

INPUTS
    width   - number of bits wide for bitplane
    height  - number of rows in bitplane

RESULT
    planeptr - pointer to first word in bitplane, or NULL if
               it was not possible to allocate the desired
               amount of memory.
BUGS

SEE ALSO
    FreeRaster() graphics/gfx.h


graphics.library/AndRectRegion

NAME
    AndRectRegion -- Perform 2d AND operation of rectangle
                     with region, leaving result in region.

SYNOPSIS
    AndRectRegion(region,rectangle)
                    a0      a1

    void AndRectRegion( struct Region *, struct Rectangle * );

FUNCTION
    Clip away any portion of the region that exists outside
    of the rectangle. Leave the result in region.

INPUTS
    region - pointer to Region structure
    rectangle - pointer to Rectangle structure

NOTES
    Unlike the other rect-region primitives, AndRectRegion() cannot
    fail.

BUGS

SEE ALSO
    AndRegionRegion() OrRectRegion() graphics/regions.h


graphics.library/AndRegionRegion

NAME
    AndRegionRegion -- Perform 2d AND operation of one region
                      with second region, leaving result in second region.

SYNOPSIS
    status = AndRegionRegion(region1,region2)
      d0                       a0      a1

    BOOL AndRegionRegion(struct Region *, struct Region * );

FUNCTION
    Remove any portion of region2 that is not in region1.

INPUTS
    region1 - pointer to Region structure
    region2 - pointer to Region structure to use and for result

RESULTS
    status - return TRUE if successful operation
             return FALSE if ran out of memory

BUGS

SEE ALSO
    OrRegionRegion() AndRectRegion() graphics/regions.h


graphics.library/Animate

NAME
    Animate  --  Processes every AnimOb in the current animation list.

SYNOPSIS
    Animate(anKey, rp)
            A0     A1

    void Animate(struct AnimOb **, struct RastPort *);

FUNCTION
    For every AnimOb in the list
        - update its location and velocities
        - call the AnimOb's special routine if one is supplied
        - for each component of the AnimOb
            - if this sequence times out, switch to the new one
            - call this component's special routine if one is supplied
            - set the sequence's VSprite's y,x coordinates based
              on whatever these routines cause

INPUTS
    ankey = address of the variable that points to the head AnimOb
    rp    = pointer to the RastPort structure

RESULT

BUGS

SEE ALSO
    AddAnimOb() graphics/gels.h graphics/rastport.h


graphics.library/AreaCircle

NAME
    AreaCircle -- add a circle to areainfo list for areafill.

SYNOPSIS
    error = (int) AreaCircle( rp,  cx,  cy, radius)
    D0                        A1   D0   D1  D2

    ULONG AreaCircle(struct RastPort *, WORD, WORD, UWORD);

FUNCTION
    Add circle to the vector buffer. It will be drawn to the rastport when
    AreaEnd is executed.

INPUTS
    rp       - pointer to a RastPort structure

    cx, cy   - the coordinates of the center of the desired circle.

    radius   - is the radius of the circle to draw around the centerpoint.

RESULTS
    0 if no error
    -1 if no space left in vector list

NOTES
    This function is actually a macro which calls
        AreaEllipse(rp,cx,cy,radius,radius).

SEE ALSO
    AreaMove() AreaDraw() AreaCircle() InitArea() AreaEnd()
    graphics/rastport.h graphics/gfxmacros.h


graphics.library/AreaDraw

NAME
    AreaDraw -- Add a point to a list of end points for areafill.

SYNOPSIS
    error = AreaDraw( rp,  x,     y)
      d0              A1 D0:16 D1:16

    ULONG AreaDraw( struct RastPort *, SHORT, SHORT);

FUNCTION
    Add point to the vector buffer.

INPUTS
    rp      - points to a RastPort structure.
    x,y     - are coordinates of a point in the raster.

RESULT
    error   - zero for success, else -1 if no there was no space
              left in the vector list.

BUGS

SEE ALSO
    AreaMove() InitArea() AreaEnd() graphics/rastport.h


graphics.library/AreaEllipse

NAME
    AreaEllipse -- add a ellipse to areainfo list for areafill.

SYNOPSIS
    error = AreaEllipse( rp, cx,   cy,   a,    b    )
    d0                   a1  d0:16 d1:16 d2:16 d3:16

    LONG AreaEllipse( struct RastPort *, SHORT, SHORT, SHORT, SHORT)

FUNCTION
    Add an ellipse to the vector buffer. It will be draw when AreaEnd() is
    called.

INPUTS
    rp - pointer to a RastPort structure
    cx - x coordinate of the centerpoint relative to the rastport.
    cy - y coordinate of the centerpoint relative to the rastport.
    a  - the horizontal radius of the ellipse (note: a must be > 0)
    b  - the vertical radius of the ellipse (note: b must be > 0)

RESULT
    error - zero for success, or -1 if there is no space left in the
            vector list

SEE ALSO
    AreaMove() AreaDraw() AreaCircle() InitArea() AreaEnd()
    graphics/rastport.h


graphics.library/AreaEnd

NAME
    AreaEnd -- Process table of vectors and ellipses and produce areafill.

SYNOPSIS
    error = AreaEnd(rp)
      d0            A1

    LONG AreaEnd( struct RastPort * );

FUNCTION
    Trigger the filling operation.
    Process the vector buffer and generate required
    fill into the raster planes. After the fill is complete, reinitialize
    for the next AreaMove or AreaEllipse. Use the raster set up by
    InitTmpRas when generating an areafill mask.

RESULT
    error - zero for success, or -1 if an error occured anywhere.

INPUTS
    rp - pointer to a RastPort structure which specifies where the filled
         regions will be rendered to.

BUGS

SEE ALSO
    InitArea() AreaMove() AreaDraw() AreaEllipse()  InitTmpRas()
    graphics/rastport.h


graphics.library/AreaMove

NAME
    AreaMove -- Define a new starting point for a new
                shape in the vector list.

SYNOPSIS
    error =  AreaMove( rp,   x,     y)
     d0                a1  d0:16  d1:16

    LONG AreaMove( struct RastPort *, SHORT, SHORT );

FUNCTION
    Close  the last polygon and start another polygon
    at  (x,y). Add the necessary  points  to  vector
    buffer. Closing a polygon may result in the generation
    of another AreaDraw() to close previous polygon.
    Remember to have an initialized AreaInfo structure attached
    to the RastPort.

INPUTS
    rp  - points to a RastPort structure
    x,y - positions in the raster

RETURNS
    error - zero for success, or -1 if there is no space left in the
    vector list

BUGS

SEE ALSO
    InitArea() AreaDraw() AreaEllipse() AreaEnd() graphics/rastport.h


graphics.library/AskFont

NAME
    AskFont -- get the text attributes of the current font

SYNOPSIS
    AskFont(rp, textAttr)
            A1  A0

    void AskFont(struct RastPort *, struct TextAttr *);

FUNCTION
    This function fills the text attributes structure with the
    attributes of the current font in the RastPort.

INPUTS
    rp       - the RastPort from which the text attributes are
               extracted
    textAttr - the TextAttr structure to be filled.  Note that
               there is no support for a TTextAttr.

RESULT
    The textAttr structure is filled with the RastPort's text
    attributes.

BUGS

SEE ALSO
    graphics/text.h


graphics.library/AskSoftStyle

NAME
    AskSoftStyle -- Get the soft style bits of the current font.

SYNOPSIS
    enable = AskSoftStyle(rp)
    D0                    A1

    ULONG AskSoftStyle(struct RastPort *);

FUNCTION
    This function returns those style bits of the current font
    that are not intrinsic in the font itself, but
    algorithmically generated.  These are the bits that are
    valid to set in the enable mask for SetSoftStyle().

INPUTS
    rp - the RastPort from which the font and style    are extracted.

RESULTS
    enable - those bits in the style algorithmically generated.
             Style bits that are not defined are also set.

BUGS

SEE ALSO
    SetSoftStyle()  graphics/text.h


graphics.library/AttemptLockLayerRom

                       *
NAME
    AttemptLockLayerRom -- Attempt to Lock Layer structure
                                     by rom(gfx lib) code

SYNOPSIS
    gotit = AttemptLockLayerRom( layer )
     d0                           a5

    BOOL AttempLockLayerRom( struct Layer * );

FUNCTION
    Query the current state of the lock on this Layer. If it is
    already locked then return FALSE, could not lock. If the
    Layer was not locked then lock it and return TRUE.
    This call does not destroy any registers.
    This call nests so that callers in this chain will not lock
    themselves out.

INPUTS
    layer - pointer to Layer structure

RESULT
    gotit - TRUE or FALSE depending on whether the Layer was
            successfully locked by the caller.

SEE ALSO
    LockLayerRom() UnlockLayerRom()


graphics.library/BitMapScale

NAME
    BitMapScale -- Perform raster scaling on a bit map. (V36)

SYNOPSIS
    BitMapScale(bitScaleArgs)
                A0

    void BitMapScale(struct BitScaleArgs *);

FUNCTION
    Scale a source bit map to a non-overlapping destination
    bit map.

INPUTS
    bitScaleArgs - structure of parameters describing scale:
        bsa_SrcX, bsa_SrcY - origin of the source bits.
        bsa_SrcWidth, bsa_SrcHeight - number of bits to scale from in x
        and y.
        bsa_DestX, bsa_DestY - origin of the destination.
        bsa_DestWidth, bsa_DestHeight - resulting number of bits in x
        and y.  NOTE: these values are set by this function.
        bsa_XSrcFactor:bsa_XDestFactor - equivalant to the ratio
            srcWidth:destWidth, but not necessarily the same
            numbers.  Each must be in the range 1..16383.
        bsa_YSrcFactor:bsa_YDestFactor - equivalant to the ratio
            srcHeight:destHeight, but not necessarily the same
            numbers.  Each must be in the range 1..16383.
        bsa_SrcBitMap - source of the bits to scale.
        bsa_DestBitMap - destination for the bits to scale.  This had
            better be big enough!
        bsa_Flags - future scaling options.  Set it to zero!
        bsa_XDDA, bsa_YDDA - for future use.  Need not be set by user.
        bsa_Reserved1, bsa_Reserved2 - for future use.  Need not be set.

RESULT
    The destWidth, destHeight fields are set by this function as
    described above.

NOTES
    o   This function may use the blitter.
    o   Overlapping source and destination bit maps are not
        supported.
    o   No check is made to ensure destBitMap is big enough: use
        ScalerDiv to calculate a destination dimension.

BUGS
    o   This function does not use the HighRes Agnus 'Big Blit'
        facility. You should not use XSrcFactor == XDestFactor,
        where SrcWidth or DestWidth > 1024.

    o   Also, the blitter is used when expanding in the Y direction.
        You should not expand in the Y direction if
        ((DestX & 0xf) + DestWidth) >= 1024 pixels. (Up to 1008 pixels
        is always safe).

SEE ALSO
    ScalerDiv()  graphics/scale.h


graphics.library/BltBitMap

NAME
    BltBitMap -- Move a rectangular region of bits in a BitMap.

SYNOPSIS
    planecnt = BltBitMap(SrcBitMap, SrcX, SrcY, DstBitMap,
    D0                   A0         D0:16 D1:16 A1
        DstX, DstY, SizeX, SizeY, Minterm, Mask [, TempA])
        D2:16 D3:16 D4:16  D5:16  D6:8     D7:8   [A2]

    ULONG BltBitMap(struct BitMap *, WORD, WORD, struct BitMap *,
        WORD, WORD, WORD, WORD, UBYTE, UBYTE, UWORD *);

FUNCTION
    Perform non-destructive blits to move a rectangle from one
    area in a BitMap to another area, which can be on a different
    BitMap.
    This blit is assumed to be friendly: no error conditions (e.g.
    a rectangle outside the BitMap bounds) are tested or reported.

INPUTS
    SrcBitMap, DstBitMap - the BitMap(s) containing the
          rectangles
        - the planes copied from the source to the destination are
          only those whose plane numbers are identical and less
          than the minimum Depth of either BitMap and whose Mask
          bit for that plane is non-zero.
        - as a special case, if a plane pointer in the SrcBitMap
          is zero, it acts as a pointer to a plane of all zeros, and
          if the plane pointer is 0xffffffff, it acts as a pointer
          to a plane of all ones.  (Note: new for V36)
        - SrcBitMap and DstBitMap can be identical if they point
          to actual planes.
    SrcX, SrcY - the x and y coordinates of the upper left corner
        of the source rectangle.  Valid range is positive
        signed integer such that the raster word's offset
        0..(32767-Size)
    DstX, DstY - the x and y coordinates of the upper left
        corner of the destination for the rectangle.  Valid
        range is as for Src.
    SizeX, SizeY - the size of the rectangle to be moved.  Valid
        range is (X: 1..976; Y: 1..1023 such that final raster
        word's offset is 0..32767)
    Minterm - the logic function to apply to the rectangle when
        A is non-zero (i.e. within the rectangle).  B is the
        source rectangle and C, D is the destination for the
        rectangle.
        - $0C0 is a vanilla copy
        - $030 inverts the source before the copy
        - $050 ignores the source and inverts the destination
        - see the hardware reference manual for other combinations
    Mask - the write mask to apply to this operation.  Bits set
        indicate the corresponding planes (if not greater than
        the minimum plane count) are to participate in the
        operation.  Typically this is set to 0xff.
    TempA - If the copy overlaps exactly to the left or right
        (i.e. the scan line addresses overlap), and TempA is
        non-zero, it points to enough chip accessable memory
        to hold a line of A source for the blit (ie CHIP RAM).
        BitBitMap will allocate (and free) the needed TempA if
        none is provided and one is needed.  Blit overlap is
        determined from the relation of the first non-masked
        planes in the source and destination bit maps.

RESULTS
    planecnt - the number of planes actually involved in the blit.

NOTES
    o   This function may use the blitter.

SEE ALSO
    ClipBlit()  graphics/gfx.h  hardware/blit.h


graphics.library/BltBitMapRastPort

NAME
    BltBitMapRastPort -- Blit from source bitmap to destination rastport.

SYNOPSIS
    error = BltBitMapRastPort
         (srcbm, srcx, srcy, destrp, destX, destY, sizeX, sizeY, minterm)
         D0     A0     D0    D1    A1      D2     D3     D4     D5     D6

    BOOL BltBitMapRastPort
         (struct BitMap *, WORD, WORD, struct RastPort *, WORD, WORD,
          WORD, WORD, UBYTE);

FUNCTION
    Blits from source bitmap to position specified in destination rastport
    using minterm.

INPUTS
    srcbm   - a pointer to the source bitmap
    srcx    - x offset into source bitmap
    srcy    - y offset into source bitmap
    destrp  - a pointer to the destination rastport
    destX   - x offset into dest rastport
    destY   - y offset into dest rastport
    sizeX   - width of blit in pixels
    sizeY   - height of blit in rows
    minterm - minterm to use for this blit

RESULT
    TRUE

BUGS

SEE ALSO
    BltMaskBitMapRastPort() graphics/gfx.h graphics/rastport.h


graphics.library/BltClear

NAME

    BltClear - Clear a block of memory words to zero.

SYNOPSIS
    BltClear( memBlock, bytecount, flags )
                a1         d0       d1

    void BltClear( void *, ULONG, ULONG );

FUNCTION
    For memory that is local and blitter accessable, the most
    efficient way to clear a range of memory locations is
    to use the system's most efficient data mover, the blitter.
    This command accepts the starting location and count and clears
    that block to zeros.

INPUTS
    memBloc - pointer to local memory to be cleared
              memBlock is assumed to be even.
    flags   - set bit 0 to force function to wait until
              the blit is done.
              set bit 1 to use row/bytesperrow.

    bytecount - if (flags & 2) == 0 then
                            even number of bytes to clear.
                    else
                            low 16 bits is taken as number of bytes
                            per row and upper 16 bits taken as
                            number of rows.

    This function is somewhat hardware dependant. In the rows/bytesperrow
    mode (with the pre-ECS blitter) rows must be <- 1024. In bytecount mode
    multiple runs of the blitter may be used to clear all the memory.

    Set bit 2 to use the upper 16 bits of the Flags as the data to fill
    memory with instead of 0 (V36).

RESULT
    The block of memory is initialized.

BUGS

SEE ALSO


graphics.library/BltMaskBitMapRastPort

NAME
    BltMaskBitMapRastPort -- blit from source bitmap to destination
    rastport with masking of source image.

SYNOPSIS
    BltMaskBitMapRastPort
        (srcbm, srcx, srcy, destrp, destX, destY, sizeX, sizeY,
         A0     D0    D1    A1      D2     D3     D4     D5
         minterm, bltmask)
         D6       A2

    void BltMaskBitMapRastPort
         (struct BitMap *, WORD, WORD, struct RastPort *, WORD, WORD,
          WORD, WORD, UBYTE, APTR);

FUNCTION
    Blits from source bitmap to position specified in destination rastport
    using bltmask to determine where source overlays destination, and
    minterm to determine whether to copy the source image "as is" or
    to "invert" the sense of the source image when copying. In either
    case, blit only occurs where the mask is non-zero.

INPUTS
    srcbm   - a pointer to the source bitmap
    srcx    - x offset into source bitmap
    srcy    - y offset into source bitmap
    destrp  - a pointer to the destination rastport
    destX   - x offset into dest rastport
    destY   - y offset into dest rastport
    sizeX   - width of blit in pixels
    sizeY   - height of blit in rows
    minterm - either (ABC|ABNC|ANBC) if copy source and blit thru mask
              or     (ANBC)          if invert source and blit thru mask
    bltmask - pointer to the single bit-plane mask, which must be the
              same size and dimensions as the planes of the
              source bitmap.

RESULT

BUGS

SEE ALSO
    BltBitMapRastPort() graphics/gfx.h graphics/rastport.h


graphics.library/BltPattern

NAME
    BltPattern --  Using standard drawing rules for areafill,
                                     blit through a mask.

SYNOPSIS
    BltPattern(rp, mask, xl, yl, maxx, maxy, bytecnt)
              a1,  a0   d0  d1   d2   d3     d4

    void BltPattern
       (struct RastPort *, void *, SHORT, SHORT, SHORT, SHORT, SHORT);

FUNCTION
    Blit using drawmode,areafill pattern, and mask
    at position rectangle (xl,yl) (maxx,maxy).

INPUTS
    rp    -  points to the destination RastPort for the blit.
    mask  -  points to 2 dimensional mask if needed
             if mask == NULL then use a rectangle.
    xl,yl -  coordinates of upper left of rectangular region in RastPort
    maxx,maxy - points to lower right of rectangular region in RastPort
    bytecnt - BytesPerRow for mask

RESULT

SEE ALSO
    AreaEnd


graphics.library/BltTemplate

NAME
    BltTemplate -- Cookie cut a shape in a rectangle to the RastPort.

SYNOPSIS
    BltTemplate(SrcTemplate, SrcX, SrcMod, rp,
                A0           D0:16  D1:16  A1
        DstX,  DstY, SizeX, SizeY)
        D2:16  D3:16 D4:16  D5:16

    void BltTemplate(UWORD *, WORD, WORD, struct RastPort *,
         WORD, WORD, WORD, WORD);

FUNCTION
    This function draws the image in the template into the
    RastPort in the current color and drawing mode at the
    specified position.  The template is assumed not to overlap
    the destination.
    If the template falls outside the RastPort boundary, it is
    truncated to that boundary.

    Note: the SrcTemplate pointer should point to the "nearest" word
       (rounded down) of the template mask. Fine alignment of the mask
       is acheived by setting the SrcX bit offseet within the range
       of 0 to 15 decimal.

INPUTS
    SrcTemplate  - pointer to the first (nearest) word of the template
                   mask.
    SrcX         - x bit offset into the template mask (range 0..15).
    SrcMod       - number of bytes per row in template mask.
    rp           - pointer to destination RastPort.
    DstX, DstY   - x and y coordinates of the upper left
                   corner of the destination for the blit.
    SizeX, SizeY - size of the rectangle to be used as the
                   template.

NOTES
    o   This function may use the blitter.

SEE ALSO
    BltBitMap()  graphics/rastport.h


graphics.library/CBump

NAME
    CBump -- increment user copper list pointer (bump to next position
             in list).

SYNOPSIS
    CBump( c )
          a1

    void CBump( struct UCopList * );

FUNCTION
    Increment pointer to space for next instruction in user copper list.

INPUTS
    c - pointer to UCopList structure

RESULTS
    User copper list pointer is incremented to next position.
    Pointer is repositioned to next user copperlist instruction block
    if the current block is full.

        Note: CBump is usually invoked for the programmer as part of the
              macro definitions CWAIT or CMOVE.

BUGS

SEE ALSO
    CINIT CWAIT CMOVE CEND graphics/copper.h


graphics.library/CEND

NAME
    CEND -- Terminate user copper list.

SYNOPSIS
    CEND( c )

    struct UCopList *c;

FUNCTION
    Add instruction to terminate user copper list.

INPUTS
    c - pointer to UCopList structure

RESULTS
    This is actually a macro that calls the macro CWAIT(c,10000,255)
    10000 is a magical number that the graphics.library uses.
    I hope display technology doesn't catch up too fast!

BUGS

SEE ALSO
    CINIT CWAIT CMOVE graphics/copper.h


graphics.library/ChangeSprite

NAME
    ChangeSprite -- Change the sprite image pointer.

SYNOPSIS
    ChangeSprite( vp, s, newdata)
                 a0  a1   a2

    void ChangeSprite(struct ViewPort *, struct SimpleSprite *, void * )

FUNCTION
    The sprite image is changed to use the data starting at newdata

INPUTS
    vp - pointer to ViewPort structure that this sprite is
              relative to,  or 0 if relative only top of View
    s - pointer to SimpleSprite structure
    newdata - pointer to data structure of the following form.
            struct spriteimage
            {
                UWORD    posctl[2]; /* used by simple sprite machine*/
                UWORD    data[height][2];   /* actual sprite image */
                UWORD    reserved[2];       /* initialized to */
                                                 /*  0x0,0x0 */
            };
    The programmer must initialize reserved[2].  Spriteimage must be
    in CHIP memory. The height subfield of the SimpleSprite structure
    must be set to reflect the height of the new spriteimage BEFORE
    calling ChangeSprite(). The programmer may allocate two sprites to
    handle a single attached sprite.  After GetSprite(), ChangeSprite(),
    the programmer can set the SPRITE_ATTACHED bit in posctl[1] of the
    odd numbered sprite.
    If you need more than 8 sprites, look up VSprites in the
    graphics documentation.

RESULTS

BUGS

SEE ALSO
    FreeSprite() ChangeSprite() MoveSprite() AddVSprite() graphics/sprite.h


graphics.library/CINIT

NAME
    CINIT -- Initialize user copperlist to accept intermediate
             user copper instructions.

SYNOPSIS
    cl = CINIT( ucl , n )

    cl = UCopperListInit( ucl , n )
                          a0    d0

    struct CopList *UCopperListInit( struct UCopList *, UWORD );

FUNCTION
    Allocates and/or initialize copperlist structures/buffers
    internal to a UCopList structure.

    This is a macro that calls UCopListInit. You must pass a
    (non-initialized) UCopList to CINIT (CINIT will NOT allocate
    a new UCopList if ucl==0 ). If (ucl != 0) it will initialize the
    intermediate data buffers internal to a UCopList.

    The maximum number of intermediate copper list instructions
    that these internal CopList data buffers contain is specified
    as the parameter n.

INPUTS
    ucl - pointer to UCopList structure
    n - number of instructions buffer must be able to hold

RESULTS
    cl- a pointer to a buffer which will accept n intermediate copper
        instructions.

    NOTE: this is NOT a UCopList pointer, rather a pointer to the
          UCopList's->FirstCopList sub-structure.

BUGS
    CINIT will not actually allocate a new UCopList if ucl==0.
    Instead you must allocate a block MEMF_PUBLIC|MEMF_CLEAR, the
    sizeof(struct UCopList) and pass it to this function.

    The system's FreeVPortCopLists function will take care of
    deallocating it if they are called.

    Prior to release V36 the  CINIT macro had { } braces surrounding
    the definition, preventing the proper return of the result value.
    These braces have been removed for the V36 include definitions.

SEE ALSO
    CINIT CMOVE CEND graphics/copper.h


graphics.library/ClearEOL

NAME
    ClearEOL -- Clear from current position to end of line.

SYNOPSIS
    ClearEOL(rp)
             A1

    void ClearEOL(struct RastPort *);

FUNCTION
    Clear a rectangular swath from the current position to the
    right edge of the rastPort.  The height of the swath is taken
    from that of the current text font, and the vertical
    positioning of the swath is adjusted by the text baseline,
    such that text output at this position would lie wholly on
    this newly cleared area.
    Clearing consists of setting the color of the swath to zero,
    or, if the DrawMode is 2, to the BgPen.

INPUTS
    rp - pointer to RastPort structure

RESULT

NOTES
    o   This function may use the blitter.

SEE ALSO
    Text()  ClearScreen()  SetRast()
    graphics/text.h  graphics/rastport.h


graphics.library/ClearRectRegion

NAME
    ClearRectRegion -- Perform 2d CLEAR operation of rectangle
                    with region, leaving result in region.

SYNOPSIS
    status = ClearRectRegion(region,rectangle)
     d0                       a0      a1

    BOOL ClearRectRegion(struct Region *, struct Rectangle * );

FUNCTION
    Clip away any portion of the region that exists inside
    of the rectangle. Leave the result in region.

INPUTS
    region - pointer to Region structure
    rectangle - pointer to Rectangle structure

RESULTS
    status - return TRUE if successful operation
             return FALSE if ran out of memory

BUGS

SEE ALSO
    AndRectRegion() graphics/regions.h


graphics.library/ClearRegion

NAME
    ClearRegion -- Remove all rectangles from region.

SYNOPSIS
    ClearRegion(region)
                 a0

    void ClearRegion( struct Region * );

FUNCTION
    Clip away all rectangles in the region leaving nothing.

INPUTS
    region - pointer to Region structure

BUGS

SEE ALSO
    NewRegion() graphics/regions.h


graphics.library/ClearScreen

NAME
    ClearScreen -- Clear from current position to end of RastPort.

SYNOPSIS
    ClearScreen(rp)
                A1

    void ClearScreen(struct RastPort *);

FUNCTION
    Clear a rectangular swath from the current position to the
    right edge of the rastPort with ClearEOL, then clear the rest
    of the screen from just beneath the swath to the bottom of
    the rastPort.
    Clearing consists of setting the color of the swath to zero,
    or, if the DrawMode is 2, to the BgPen.

INPUTS
    rp - pointer to RastPort structure

NOTES
    o   This function may use the blitter.

SEE ALSO
    ClearEOL()  Text()  SetRast()
    graphics/text.h  graphics/rastport.h


graphics.library/ClipBlit

NAME
    ClipBlit  --  Calls BltBitMap() after accounting for windows

SYNOPSIS
    ClipBlit(Src, SrcX, SrcY, Dest, DestX, DestY, XSize, YSize, Minterm)
             A0   D0    D1    A1    D2     D3     D4     D5     D6

    void ClipBlit
         (struct RastPort *, WORD, WORD, struct RastPort *, WORD, WORD,
          WORD, WORD, UBYTE);

FUNCTION
    Performs the same function as BltBitMap(), except that it
    takes into account the Layers and ClipRects of the layer library,
    all of which are (and should be) transparent to you.  So, whereas
    BltBitMap() requires pointers to BitMaps, ClipBlit requires pointers to
    the RastPorts that contain the Bitmaps, Layers, etcetera.

    If you are going to blit blocks of data around via the RastPort of your
    Intuition Window, you must call this routine (rather than BltBitMap()).

    Either the Src RastPort, the Dest RastPort, both, or neither, can have
    Layers. This routine takes care of all cases.

    See BltBitMap() for a thorough explanation.

INPUTS
    Src          = pointer to the RastPort of the source for your blit
    SrcX, SrcY   = the topleft offset into Src for your data
    Dest         = pointer to the RastPort to receive the blitted data
    DestX, DestY = the topleft offset into the destination RastPort
    XSize        = the width of the blit
    YSize        = the height of the blit
    Minterm      = the boolean blitter function, where SRCB is
                   associated with the Src RastPort and SRCC goes to the
                   Dest RastPort

RESULT

BUGS

SEE ALSO
    BltBitMap();


graphics.library/CloseFont

NAME
    CloseFont -- Release a pointer to a system font.

SYNOPSIS
    CloseFont(font)
              A1

    void CloseFont(struct TextFont *);

FUNCTION
    This function indicates that the font specified is no longer
    in use.  It is used to close a font opened by OpenFont, so
    that fonts that are no longer in use do not consume system
    resources.

INPUTS
    font -  a font pointer as returned by OpenFont() or OpenDiskFont()

RESULT

BUGS

SEE ALSO
    OpenFont()  diskfont.library/OpenDiskFont  graphics/text.h


graphics.library/CloseMonitor

NAME
    CloseMonitor -- close a MonitorSpec (V36)

SYNOPSIS
    error = CloseMonitor( monitor_spec )
      d0                    a0

   LONG CloseMonitor( struct MonitorSpec * );

FUNCTION
    Relinquish access to a MonitorSpec.

INPUTS
    monitor_spec - a pointer to a MonitorSpec opened via OpenMonitor()

RESULTS
    error - FALSE if MonitorSpec closed uneventfully.
            TRUE if MonitorSpec could not be closed.

BUGS

SEE ALSO
    OpenMonitor()


graphics.library/CMOVE

NAME
    CMOVE -- append copper move instruction to user copper list.

SYNOPSIS
    CMOVE( c , a , v )

    CMove( c , a , v )
          a1  d0  d1
    CBump( c )
          a1

    void CMove( struct UCopList *, void *, WORD );

FUNCTION
    Add instruction to move value v to hardware register a.

INPUTS
    c - pointer to UCopList structure
    a - hardware register
    v - 16 bit value to be written

RESULTS
    This is actually a macro that calls CMove(c,&a,v)
    and then calls CBump(c) to bump the local pointer
    to the next instruction. Watch out for macro side affects.

BUGS

SEE ALSO
    CINIT CWAIT CEND graphics/copper.h


graphics.library/CopySBitMap

NAME
    CopySBitMap --   Syncronize Layer window with contents of
                                            Super BitMap

SYNOPSIS
    CopySBitMap( layer )
                 a0

    void CopySBitMap(struct Layer *);

FUNCTION
    This is the inverse of SyncSBitMap.
    Copy all bits from SuperBitMap to Layer bounds.
    This is used for those functions that do not
    want to deal with the ClipRect structures but do want
    to be able to work with a SuperBitMap Layer.

INPUTS
    layer - pointer to a SuperBitMap Layer
        The Layer must already be locked by the caller.

BUGS

SEE ALSO
    LockLayerRom() SyncSBitMap()


graphics.library/CWAIT

NAME
    CWAIT -- Append copper wait instruction to user copper list.

SYNOPSIS
    CWAIT( c , v , h )

    CWait( c , v , h )
           a1  d0  d1
    CBump( c )
          a1

    void CWait( struct UCopList *, WORD, WORD)

FUNCTION
    Add instruction to wait for vertical beam position v and
    horizontal position h to this intermediate copper list.

INPUTS
    c - pointer to UCopList structure
    v - vertical beam position (relative to top of viewport)
    h - horizontal beam position

RESULTS
    this is actually a macro that calls CWait(c,v,h)
    and then calls CBump(c) to bump the local pointer
    to the next instruction.

BUGS
    User waiting for horizontal values of greater than 222 decimal
    is illegal.

SEE ALSO
    CINIT CMOVE CEND graphics/copper.h


graphics.library/DisownBlitter

NAME
    DisownBlitter - return blitter to free state.

SYNOPSIS
    DisownBlitter()

    void DisownBlitter( void );

FUNCTION
    Free blitter up for use by other blitter users.

INPUTS

RETURNS

SEE ALSO
    OwnBlitter()


graphics.library/DisposeRegion

NAME
    DisposeRegion -- Return all space for this region to free
                     memory pool.

SYNOPSIS
    DisposeRegion(region)
                  a0

    void DisposeRegion( struct Region * );

FUNCTION
    Free all RegionRectangles for this Region then
    free the Region itself.

INPUTS
    region - pointer to Region structure

BUGS

SEE ALSO
    NewRegion() graphics/regions.h


graphics.library/DoCollision

NAME
    DoCollision -- Test every gel in gel list for collisions.

SYNOPSIS
    DoCollision(rp)
                A1

    void DoCollision(struct RastPort *);

FUNCTION
    Tests each gel in gel list for boundary and gel-to-gel collisions.
    On detecting one of these collisions, the appropriate collision-
    handling routine is called. See the documentation for a thorough
    description of which collision routine is called. This routine
    expects to find the gel list correctly sorted in Y,X order.
    The system routine SortGList performs this function for the user.

INPUTS
    rp = pointer to a RastPort

RESULT

BUGS

SEE ALSO
    InitGels()  SortGList()  graphics/gels.h  graphics/gels.h


graphics.library/Draw

NAME
    Draw -- Draw a line between the current pen position
                   and the new x,y position.

SYNOPSIS
    Draw( rp,   x,     y)
         a1  d0:16  d1:16

    void Draw( struct RastPort *, SHORT, SHORT);

FUNCTION
    Draw a line from the current pen position to (x,y).

INPUTS

    rp - pointer to the destination RastPort
    x,y - coordinates of where in the RastPort to end the line.

BUGS

SEE ALSO
    Move() graphics/rastport.h


graphics.library/DrawEllipse

NAME
    DrawEllipse -- Draw an ellipse centered at cx,cy with vertical
       and horizontal radii of a,b respectively.

SYNOPSIS
    DrawEllipse( rp, cx, cy, a, b )
                 a1  d0  d1  d2 d3

    void DrawEllipse( struct RastPort *, SHORT, SHORT, SHORT, SHORT);

FUNCTION
   Creates an elliptical outline within the rectangular region
    specified by the parameters, using the current foreground pen color.

INPUTS
    rp - pointer to the RastPort into which the ellipse will be drawn.
    cx - x coordinate of the centerpoint relative to the rastport.
    cy - y coordinate of the centerpoint relative to the rastport.
    a - the horizontal radius of the ellipse (note: a must be > 0)
    b - the vertical radius of the ellipse (note: b must be > 0)

BUGS

NOTES
    this routine does not clip the ellipse to a non-layered rastport.

SEE ALSO
    DrawCircle(), graphics/rastport.h


graphics.library/DrawGList

NAME
    DrawGList -- Process the gel list, queueing VSprites, drawing Bobs.

SYNOPSIS
    DrawGList(rp, vp)
              A1  A0

    void DrawGList(struct RastPort *, struct ViewPort *);

FUNCTION
    Performs one pass of the current gel list.
       - If nextLine and lastColor are defined, these are
         initialized for each gel.
      - If it's a VSprite, build it into the copper list.
      - If it's a Bob, draw it into the current raster.
      - Copy the save values into the "old" variables,
         double-buffering if required.

INPUTS
    rp = pointer to the RastPort where Bobs will be drawn
    vp = pointer to the ViewPort for which VSprites will be created

RESULT

BUGS
    MUSTDRAW isn't implemented yet.

SEE ALSO
    InitGels()  graphics/gels.h graphics/rastport.h  graphics/view.h


graphics.library/EraseRect

NAME

    EraseRect -- Fill a defined rectangular area using the current
                    BackFill hook. (V36)

SYNOPSIS
    EraseRect( rp, xmin, ymin, xmax, ymax)
              a1  d0:16 d1:16 d2:16 d3:16

    void EraseRect(struct RastPort *, SHORT, SHORT, SHORT, SHORT);

FUNCTION
    Fill the rectangular region specified by the parameters with the
    BackFill hook. If non-layered, the rectangular region specified by
    the parameters is cleared. If layered the Layer->BackFill Hook is used.

INPUTS
    rp      - pointer to a RastPort structure
    xmin    - x coordinate of the upper left corner of the region to fill.
    ymin    - y coordinate of the upper left corner of the region to fill.
    xmax    - x coordinate of the lower right corner of the region to fill.
    ymax    - y coordinate of the lower right corner of the region to fill.

BUGS

NOTES
    The following relation MUST be true:
    (xmax >= xmin) and (ymax >= ymin)

SEE ALSO
    graphics/rastport.h graphics/clip.h


graphics.library/ExtendFont

NAME
    ExtendFont -- ensure tf_Extension has been built for a font (V36)

SYNOPSIS
    success = ExtendFont(font, fontTags)
    D0                   A0    A1

    ULONG ExtendFont(struct TextFont *, struct TagItem *);

SEE ALSO
    graphics/text.h


graphics.library/FindDisplayInfo

NAME
    FindDisplayInfo -- search for a record identified by a specific key
                       (V36)

SYNOPSIS
    handle = FindDisplayInfo(ID)
    D0                       D0

    DisplayInfoHandle FindDisplayInfo(ULONG);

FUNCTION
    Given a 32-bit Mode Key, return a handle to a valid DisplayInfoRecord
    found in the graphics database.  Using this handle, you can obtain
    information about this Mode, including its default dimensions,
    properties, and whether it is currently available for use.

INPUTS
    ID     - unsigned long identifier

RESULT
    handle - handle to a displayinfo Record with that key
             or NULL if no match.

BUGS

SEE ALSO
    graphics/displayinfo.h


graphics.library/Flood

NAME
    Flood -- Flood rastport like areafill.

SYNOPSIS
    error = Flood( rp, mode, x, y)
    d0            a1   d2  d0  d1

    BOOL Flood(struct RastPort *, ULONG, SHORT, SHORT);

FUNCTION
    Search the BitMap starting at (x,y).
    Fill all adjacent pixels if they are:
        Mode 0: not the same color as AOLPen
        Mode 1: the same color as the pixel at (x,y)

    When actually doing the fill use the modes that apply to
    standard areafill routine such as drawmodes and patterns.

INPUTS
    rp - pointer to RastPort
    (x,y) - coordinate in BitMap to start the flood fill at.
    mode -  0 fill all adjacent pixels searching for border.
            1 fill all adjacent pixels that have same pen number
            as the one at (x,y).

NOTES
    In order to use Flood, the destination RastPort must
    have a valid TmpRas raster whose size is as large as
    that of the RastPort.

SEE ALSO
    AreaEnd() InitTmpRas() graphics/rastport.h


graphics.library/FontExtent

NAME
    FontExtent -- get the font attributes of the current font (V36)

SYNOPSIS
    FontExtent(font, fontExtent)
               A0    A1

    void FontExtent(struct TextFont *, struct TextExtent *);

FUNCTION
    This function fills the text extent structure with a bounding
    (i.e. maximum) extent for the characters in the specified font.

INPUTS
    font       - the TextFont from which the font metrics are extracted.
    fontExtent - the TextExtent structure to be filled.

RESULT
    fontExtent is filled.

NOTES
    The TextFont, not the RastPort, is specified -- unlike
    TextExtent(), effect of algorithmic enhancements is not
    included, nor does te_Width include any effect of
    rp_TxSpacing.  The returned te_Width will be negative only
    when FPF_REVPATH is set in the tf_Flags of the font -- the
    effect of left-moving characters is ignored for the width of
    a normal font, and the effect of right-moving characters is
    ignored if a REVPATH font.  These characters will, however,
    be reflected in the bounding extent.

SEE ALSO
    TextExtent()  graphics/text.h


graphics.library/FreeColorMap

NAME
    FreeColorMap -- Free the ColorMap structure and return memory
                                            to free memory pool.

SYNOPSIS
    FreeColorMap( colormap )
                   a0

    void FreeColorMap(struct ColorMap *);

FUNCTION
    Return the memory to the free memory pool that was allocated
    with GetColorMap.

INPUTS
    colormap - pointer to ColorMap allocated with GetColorMap

RESULT
    The space is made available for others to use.

BUGS

SEE ALSO
    SetRGB4() GetColorMap() graphics/view.h


graphics.library/FreeCopList

NAME
    FreeCopList -- deallocate intermediate copper list

SYNOPSIS
    FreeCopList(coplist)
                  a0

    void FreeCopList( struct CopList *);

FUNCTION
    Deallocate all memory associated with this copper list.

INPUTS
    coplist  - pointer to structure CopList

RESULTS
    memory returned to memory manager

BUGS

SEE ALSO
    graphics/copper.h


graphics.library/FreeCprList

NAME
    FreeCprList -- deallocate hardware copper list

SYNOPSIS
    FreeCprList(cprlist)
                  a0

    void FreeCprList(struct cprlist *);

FUNCTION
    return cprlist to free memory pool

INPUTS
    cprlist - pointer to cprlist structure

RESULTS
    memory returned and made available to other tasks

BUGS

SEE ALSO
    graphics/copper.h


graphics.library/FreeGBuffers

NAME
    FreeGBuffers -- Deallocate memory obtained by GetGBufers.

SYNOPSIS
    FreeGBuffers(anOb, rp, db)
                 A0    A1  D0

    void FreeGBuffers(struct AnimOb *, struct RastPort *, BOOL);

FUNCTION
    For each sequence of each component of the AnimOb,
    deallocate memory for:
        SaveBuffer
        BorderLine
        CollMask and ImageShadow (point to same buffer)
        if db is set (user had used double-buffering) deallocate:
            DBufPacket
            BufBuffer

INPUTS
    anOb = pointer to the AnimOb structure
    rp   = pointer to the current RastPort
    db   = double-buffer indicator (set TRUE for double-buffering)

RESULT

BUGS

SEE ALSO
    GetGBuffers()  graphics/gels.h  graphics/rastport.h


graphics.library/FreeRaster

NAME
    FreeRaster -- Release an allocated area to the system free memory pool.

SYNOPSIS
    FreeRaster( p, width, height)
               a0   d0:16  d1:16

    void FreeRaster( PLANEPTR, USHORT, USHORT);

FUNCTION
    Return the memory associated with this PLANEPTR of size
    width and height to the MEMF_CHIP memory pool.

INPUTS
    p  =  a pointer to a memory space  returned  as  a
          result of a call to AllocRaster.

    width - the width in bits of the bitplane.
    height - number of rows in bitplane.

BUGS

NOTES
    Width and height should be the same values with which you
    called AllocRaster in the first place.

SEE ALSO
    AllocRaster() graphics/gfx.h


graphics.library/FreeSprite

NAME
    FreeSprite -- Return sprite for use by others and virtual
                                      sprite machine.

SYNOPSIS
    FreeSprite( pick )
                d0

    void FreeSprite( WORD );

FUNCTION
    Mark sprite as available for others to use.
    These sprite routines are provided to ease sharing of sprite
    hardware and to handle simple cases of sprite usage and
    movement.  It is assumed the programs that use these routines
    do want to be good citizens in their hearts. ie: they will
    not FreeSprite unless they actually own the sprite.
    The Virtual Sprite machine may ignore the simple sprite machine.

INPUTS
    pick - number in range of 0-7

RESULTS
    sprite made available for subsequent callers of GetSprite
    as well as use by Virtual Sprite Machine.

BUGS

SEE ALSO
    GetSprite() ChangeSprite() MoveSprite() graphics/sprite.h


graphics.library/FreeVPortCopLists

NAME
    FreeVPortCopLists -- deallocate all intermediate copper lists and
                         their headers from a viewport

SYNOPSIS
    FreeVPortCopLists(vp)
                     a0

    void FreeVPortCopLists(struct ViewPort *);

FUNCTION
    Search display, color, sprite, and user copper
    lists and call FreeMem() to deallocate them from memory

INPUTS
    vp - pointer to ViewPort structure

RESULTS
    The memory allocated to the various copper lists will be returned
    to the system's free memory pool, and the following fields in
    the viewport structure will be set to NULL:

            DspIns, Sprins, ClrIns, UCopIns

BUGS
    none known

SEE ALSO
    graphics/view.h


graphics.library/GetColorMap

NAME
    GetColorMap -- allocate and initialize Colormap

SYNOPSIS
    cm = GetColorMap( entries )
          d0                   d0

    struct ColorMap *GetColorMap( ULONG);

FUNCTION
    Allocates, initializes and returns a pointer to a ColorMap
    data structure, later enabling calls to SetRGB4
    and LoadRGB4 to load colors for a view port. The ColorTable
    pointer in the ColorMap structure points to a hardware
    specific colormap data structure. You should not count on
    it being anything you can understand. Use GetRGB4() to
    query it or SetRGB4CM to set it directly.

INPUTS
    entries - number of entries for this colormap

RESULT
    The pointer value returned by this routine, if nonzero,
    may be stored into the ViewPort.ColorMap pointer.
    If a value of 0 is returned, the system was unable
    to allocate enough memory space for the required
    data structures.

BUGS

SEE ALSO
    SetRGB4() FreeColorMap()


graphics.library/GetDisplayInfoData

NAME
    GetDisplayInfoData -- query DisplayInfo Record parameters (V36)

SYNOPSIS
    result = GetDisplayInfoData(handle, buf, size, tagID, [ID])
    D0                          A0      A1   D0    D1     [D2]

    ULONG GetDisplayInfoData(DisplayInfoHandle, UBYTE *, ULONG,
                                       ULONG, ULONG);

FUNCTION
    GetDisplayInfoData() fills a buffer with data meaningful to the
    DisplayInfoRecord pointed at by your valid handle. The data type
    that you are interested in is indicated by a tagID for that chunk.
    The types of tagged information that may be available include:

    DTAG_DISP: (DisplayInfo)   - properties and availability information.
    DTAG_DIMS: (DimensionInfo) - default dimensions and overscan info.
    DTAG_MNTR: (MonitorInfo)   - type, position, scanrate, and
                                 compatibility
    DTAG_NAME: (NameInfo)      - a user friendly way to refer to this mode.

INPUTS
    handle - displayinfo handle
    buf    - pointer to destination buffer
    size   - buffer size in bytes
    tagID  - data chunk type
    ID     - displayinfo identifier, optionally used if handle is NULL

RESULT
    result - if positive, number of bytes actually transferred
             if zero, no information for ID was available

BUGS

SEE ALSO
    FindDisplayInfo(), NextDisplayInfo()
    graphics/displayinfo.h


graphics.library/GetGBuffers

NAME
    GetGBuffers -- Attempt to allocate ALL buffers of an entire AnimOb.

SYNOPSIS
    status = GetGBuffers(anOb, rp, db)
    D0                   A0    A1  D0

    BOOL GetGBuffers(struct AnimOb *, struct RastPort *, BOOL);

FUNCTION
    For each sequence of each component of the AnimOb, allocate memory for:
        SaveBuffer
        BorderLine
        CollMask and ImageShadow (point to same buffer)
        if db is set TRUE (user wants double-buffering) allocate:
            DBufPacket
            BufBuffer

INPUTS
    anOb = pointer to the AnimOb structure
    rp   = pointer to the current RastPort
    db   = double-buffer indicator (set TRUE for double-buffering)

RESULT
    status = TRUE if the memory allocations were all successful, else FALSE

BUGS
    If any of the memory allocations fail it does not free the partial
    allocations that did succeed.

SEE ALSO
    FreeGBuffers() graphics/gels.h


graphics.library/GetRGB4

NAME
    GetRGB4 -- Inquire value of entry in ColorMap.

SYNOPSIS
    value = GetRGB4( colormap, entry )
      d0              a0       d0

    ULONG GetRGB4(struct ColorMap *, LONG);

FUNCTION
    Read and format a value from the ColorMap.

INPUTS
    colormap - pointer to ColorMap structure
    entry - index into colormap

RESULT
    returns -1 if no valid entry
    return UWORD RGB value 4 bits per gun right justified

NOTE
    Intuition's DisplayBeep() changes color 0. Reading Color 0 during a
    DisplayBeep() will lead to incorrect results.

BUGS

SEE ALSO
    SetRGB4() LoadRGB4() GetColorMap() FreeColorMap() graphics/view.h


graphics.library/GetSprite

NAME
    GetSprite -- Attempt to get a sprite for the simple sprite
                                     manager.

SYNOPSIS
    Sprite_Number = GetSprite( sprite, pick )
        d0                      a0      d0

    SHORT GetSprite( struct SimpleSprite *, SHORT );

FUNCTION
    Attempt to allocate one of the eight sprites for private use
    with the simple sprite manager. This must be done before using
    further calls to the simple sprite machine. If the programmer
    wants to use 15 color sprites, they must allocate both sprites
    and set the 'SPRITE_ATTACHED' bit in the odd sprite's posctldata
    array.

INPUTS
    sprite - ptr to programmers SimpleSprite structure.
    pick - number in the range of 0-7 or
      -1 if programmer just wants the next one.

RESULTS
    If pick is 0-7 attempt to allocate the sprite. If the sprite
    is already allocated then return -1.
    If pick -1 allocate the next sprite starting search at 0.
    If no sprites are available return -1 and fill -1 in num entry
    of SimpleSprite structure.
    If the sprite is available for allocation, mark it allocated
    and fill in the 'num' entry of the SimpleSprite structure.
    If successful return the sprite number.

BUGS

SEE ALSO
    FreeSprite() ChangeSprite() MoveSprite() GetSprite() graphics/sprite.h


graphics.library/GetVPModeID

NAME
    GetVPModeID -- get the 32 bit DisplayID from a ViewPort. (V36)

SYNOPSIS
    modeID =  GetVPModeID( vp )
    d0                     a0

    ULONG GetVPModeID( struct ViewPort *);

FUNCTION
    returns the normal display modeID, if one is currently  associated
    with this ViewPort.

INPUTS
    vp -- pointer to a ViewPort structure.

RESULT

    modeID -- a 32 bit DisplayInfoRecord identifier associated with
              this ViewPort, or INVALID_ID.

NOTES
    Test the return value of this function against INVALID_ID, not NULL.
    (INVALID_ID is defined in graphics/displayinfo.h).

BUGS

SEE ALSO
    graphics/displayinfo.h, ModeNotAvailable()


graphics.library/GfxAssociate

NAME
    GfxAssociate -- associate a graphics extended node with a given pointer
                    (V36)

SYNOPSIS
   GfxAssociate(pointer, node);
                A0       A1

    void GfxAssociate(VOID *, struct ExtendedNode *);

FUNCTION
    Associate a special graphics extended data structure (each of which
    begins with an ExtendedNode structure)  with another structure via
    the other structure's pointer. Later, when you call GfxLookUp()
    with the other structure's pointer you may retrieve a pointer
    to this special graphics extended data structure, if it is
    available.

INPUTS
    pointer = a pointer to a data structure.
    node = an ExtendedNode structure to associate with the pointer

RESULT
    an association is created between the pointer and the node such
    that given the pointer the node can be retrieved via GfxLookUp().

BUGS

SEE ALSO
    graphics/gfxnodes.h GfxNew() GfxFree() GfxLookUp()


graphics.library/GfxFree

NAME
    GfxFree -- free a graphics extended data structure (V36)

SYNOPSIS
    GfxFree( node );
          a0

    void GfxFree(struct ExtendedNode *);

FUNCTION
    Free a special graphics extended data structure (each of which
    begins with an ExtendedNode structure).

INPUTS
    node = pointer to a graphics extended data structure obtained via
           GfxNew().

RESULT
    the node is deallocated from memory. graphics will dissassociate
    this special graphics extended node from any associated data
    structures, if necessary, before freeing it (see GfxAssociate()).

BUGS
    an Alert() will be called if you attempt to free any structure
    other than a graphics extended data strucure obtained via GfxFree().

SEE ALSO
    graphics/gfxnodes.h GfxNew() GfxAssociate() GfxLookUp()


graphics.library/GfxLookUP

NAME
    GfxLookUp -- find a graphics extended node associated with a
                 given pointer (V36)

SYNOPSIS
    result = GfxLookUp( pointer );
      d0                   a0

    struct ExtendedNode *GfxLookUp( void *);

FUNCTION
    Finds a special graphics extended data structure (if any) associated
    with the pointer to a data structure (eg: ViewExtra associated with
    a View structure).

INPUTS
    pointer = a pointer to a data structure which may have an
              ExtendedNode associated with it (typically a View ).

RESULT
    result = a pointer to the ExtendedNode that has previously been
             associated with the pointer.

BUGS

SEE ALSO
    graphics/gfxnodes.h GfxNew() GfxFree() GfxAssociate()


graphics.library/GfxNew

NAME
    GfxNew -- allocate a graphics extended data structure (V36)

SYNOPSIS
    result = GfxNew( node_type );
    d0               d0

    struct ExtendedNode *GfxNew( ULONG);

FUNCTION
    Allocate a special graphics extended data structure (each of which
    begins with an ExtendedNode structure).  The type of structure to
    be allocated is specified by the node_type identifier.

INPUTS
    node_type = which type of graphics extended data structure to allocate.
                (see gfxnodes.h for identifier definitions.)

RESULT
    result = a pointer to the allocated graphics node or NULL if the
             allocation failed.

BUGS

SEE ALSO
    graphics/gfxnodes.h GfxFree() GfxAssociate() GfxLookUp()


graphics.library/InitArea

NAME

    InitArea -- Initialize vector collection matrix

SYNOPSIS

    InitArea( areainfo, buffer, maxvectors )
                a0          a1      d0

    void InitArea(struct AreaInfo *, void *, SHORT);

FUNCTION
    This function provides initialization for the vector collection
    matrix such that it has a size of (max vectors ).  The size of the
    region pointed to by buffer (short pointer) should be five (5) times as
    large as maxvectors. This size is in bytes.  Areafills done by using
    AreaMove, AreaDraw, and AreaEnd must have enough space allocated in
    this table to store all the points of the largest fill. AreaEllipse
    takes up two vectors for every call. If AreaMove/Draw/Ellipse detect
    too many vectors going into the buffer they will return -1.

INPUTS
    areainfo - pointer to AreaInfo structure
    buffer - pointer to chunk of memory to collect vertices
    maxvectors - max number of vectors this buffer can hold

RESULT
    Pointers are set up to begin storage of vectors done by
    AreaMove, AreaDraw, and AreaEllipse.

BUGS

SEE ALSO
    AreaEnd() AreaMove() AreaDraw() AreaEllipse() graphics/rastport.h


graphics.library/InitBitMap

NAME
    InitBitMap -- Initialize bit map structure with input values.

SYNOPSIS
    InitBitMap( bm, depth, width, height )
                a0   d0     d1      d2

    void InitBitMap( struct BitMap *, BYTE, UWORD, UWORD );

FUNCTION
    Initialize various elements in the BitMap structure to
    correctly reflect depth, width, and height.
    Must be used before use of BitMap in other graphics calls.
    The Planes[8] are not initialized and need to be set up
    by the caller.  The Planes table was put at the end of the
    structure so that it may be truncated to conserve space,
    as well as extended. All routines that use BitMap should
    only depend on existence of depth number of bitplanes.
    The Flagsh and pad fields are reserved for future use and
    should not be used by application programs.

INPUTS
    bm - pointer to a BitMap structure (gfx.h)
    depth - number of bitplanes that this bitmap will have
    width - number of bits (columns) wide for this BitMap
    height- number of bits (rows) tall for this BitMap

BUGS

SEE ALSO
    graphics/gfx.h


graphics.library/InitGels

NAME
    InitGels -- initialize a gel list; must be called before using gels.

SYNOPSIS
    InitGels(head, tail, GInfo)
             A0    A1    A2

    void InitGels(struct VSprite *, struct VSprite *, struct GelsInfo *);

FUNCTION
    Assigns the VSprites as the head and tail of the gel list in GfxBase.
    Links these two gels together as the keystones of the list.
    If the collHandler vector points to some memory array, sets
    the BORDERHIT vector to NULL.

INPUTS
    head  = pointer to the VSprite structure to be used as the
            gel list head
    tail  = pointer to the VSprite structure to be used as the
            gel list tail
    GInfo = pointer to the GelsInfo structure to be initialized

RESULT

BUGS

SEE ALSO
    graphics/gels.h  graphics/rastport.h


graphics.library/InitGMasks

NAME
    InitGMasks -- Initialize all of the masks of an AnimOb.

SYNOPSIS
    InitGMasks(anOb)
               A0

    void InitGMasks(struct AnimOb *);

FUNCTION
    For every sequence of every component call InitMasks.

INPUTS
    anOb = pointer to the AnimOb

BUGS

SEE ALSO
    InitMasks() graphics/gels.h


graphics.library/InitMasks

NAME
    InitMasks -- Initialize the BorderLine and CollMask masks of a VSprite.

SYNOPSIS
    InitMasks(vs)
              A0

    void InitMasks(struct VSprite *);

FUNCTION
    Creates the appropriate BorderLine and CollMask masks of the VSprite.
    Correctly detects if the VSprite is actually a Bob definition, handles
    the image data accordingly.

INPUTS
    vs = pointer to the VSprite structure

RESULT

BUGS

SEE ALSO
    InitGels()  graphics/gels.h


graphics.library/InitRastPort

NAME
    InitRastPort -- Initialize raster port structure

SYNOPSIS
    InitRastPort( rp )
                  a1

    void InitRastPort(struct RastPort *);

FUNCTION
   Initialize a RastPort structure to standard values.

INPUTS
    rp = pointer to a RastPort structure.

RESULT
    all entries in RastPort get zeroed out, with the following exceptions:

        Mask, FgPen, AOLPen, and LinePtrn are set to -1.
        The DrawMode is set to JAM2
        The font is set to the standard system font

NOTES
    The struct Rastport describes a control structure
    for a write-able raster. The RastPort structure
    describes how a complete single playfield display
    will be written into. A RastPort structure is
    referenced whenever any drawing or filling
    operations are to be performed on a section of
    memory.

    The section of memory which is being used in this
    way may or may not be presently a part of the
    current actual onscreen display memory. The name
    of the actual memory section which is linked to
    the RastPort is referred to here as a "raster" or
    as a bitmap.

    NOTE: Calling the routine InitRastPort only
    establishes various defaults. It does NOT
    establish where, in memory, the rasters are
    located. To do graphics with this RastPort the user
    must set up the BitMap pointer in the RastPort.

BUGS

SEE ALSO
    graphics/rastport.h


graphics.library/InitTmpRas

NAME
    InitTmpRas -- Initialize area of local memory for usage by
                    areafill, floodfill, text.

SYNOPSIS
    InitTmpRas(tmpras, buffer, size)
                a0       a1     d0

    void InitTmpRas( struct TmpRas *, void *, ULONG );

FUNCTION
    The area of memory pointed to by buffer is set up to be used
    by RastPort routines that may need to get some memory for
    intermediate operations in preparation to putting the graphics
    into the final BitMap.
    Tmpras is used to control the usage of buffer.

INPUTS
    tmpras - pointer to a TmpRas structure to be linked into
            a RastPort
    buffer - pointer to a contguous piece of chip memory.
    size - size in bytes of buffer

RESULT
    makes buffer available for users of RastPort

BUGS
    Would be nice if RastPorts could share one TmpRas.

SEE ALSO
    AreaEnd() Flood() Text() graphics/rastport.h


graphics.library/InitView

NAME
InitView - Initialize View structure.

SYNOPSIS
    InitView( view )
               a1

    void InitView( struct View * );

FUNCTION
    Initialize View structure to default values.

INPUTS
    view - pointer to a View structure

RESULT
    View structure set to all 0's. (1.0,1.1.1.2)
    Then values are put in DxOffset,DyOffset to properly position
    default display about .5 inches from top and left on monitor.
    InitView pays no attention to previous contents of view.

BUGS

SEE ALSO
    MakeVPort graphics/view.h


graphics.library/InitVPort

NAME
    InitVPort - Initialize ViewPort structure.

SYNOPSIS
    InitVPort( vp )
               a0

    void InitVPort( struct ViewPort * );

FUNCTION
    Initialize ViewPort structure to default values.

INPUTS
    vp - pointer to a ViewPort structure

RESULT
    ViewPort structure set to all 0's. (1.0,1.1)
    New field added SpritePriorities, initialized to 0x24 (1.2)

BUGS

SEE ALSO
    MakeVPort() graphics/view.h


graphics.library/LoadRGB4

NAME
    LoadRGB4 -- Load RGB color values from table.

SYNOPSIS
    LoadRGB4( vp, colors , count )
             a0     a1     d0:16

    void LoadRGB4( struct ViewPort *, UWORD *, WORD);

FUNCTION
    load the count words of the colormap from table starting at
    entry 0.

INPUTS
    vp - pointer to ViewPort, whose colors you wish to change
    colors - pointer to table of RGB values set up as an array
             of USHORTS
                    background--  0x0RGB
                    color1    --  0x0RGB
                    color2    --  0x0RGB
                     etc.         UWORD per value.
            The colors are interpreted as 15 = maximum intensity.
                                          0 = minimum intensity.
    count   = number of UWORDs in the table to load into the
      colormap starting at color 0(background) and proceeding
      to the next higher color number

RESULTS
    The ViewPort should have a pointer to a valid ColorMap to store
    the colors in.
    Updates the hardware copperlist to reflect the new colors.
    Updates the intermediate copperlist with the new colors.

BUGS

    NOTE: With V36 and up, it is not safe to call this function
    from an interrupt, because of the semaphore locking on graphics
    copper lists.

SEE ALSO
    SetRGB4() GetRGB4() GetColorMap() graphics/view.h


graphics.library/LoadView

NAME
    LoadView -- Use a (possibly freshly created) coprocessor instruction
               list to create the current display.

SYNOPSIS
    LoadView( View )
              A1

    void LoadView( struct View * );

FUNCTION
    Install a new view to be displayed during the next display
    refresh pass.
    Coprocessor instruction list has been created by
    InitVPort(), MakeVPort(), and MrgCop().

INPUTS
    View - a pointer to the View structure which contains the
    pointer to the constructed coprocessor instructions list, or NULL.

RESULT
    If the View pointer is non-NULL, the new View is displayed,
    according to your instructions.  The vertical blank routine
    will pick this pointer up and direct the copper to start
    displaying this View.

    If the View pointer is NULL, no View is displayed.

NOTE
    Even though a LoadView(NULL) is performed, display DMA will still be
    active.  Sprites will continue to be displayed after a LoadView(NULL)
    unless an OFF_SPRITE is subsequently performed.

BUGS

SEE ALSO
    InitVPort() MakeVPort() MrgCop() intuition/RethinkDisplay()
    graphics/view.h


graphics.library/LockLayerRom

NAME
    LockLayerRom -- Lock Layer structure by rom(gfx lib) code.

SYNOPSIS
    LockLayerRom( layer )
                   a5

    void LockLayerRom( struct Layer * );

FUNCTION
    Return when the layer is locked and no other task may
    alter the ClipRect structure in the Layer structure.
    This call does not destroy any registers.
    This call nests so that callers in this chain will not lock
    themselves out.
    Do not have the Layer locked during a call to intuition.
    There is a potential deadlock problem here, if intuition
    needs to get other locks as well.
    Having the layer locked prevents other tasks from using the
    layer library functions, most notably intuition itself. So
    be brief.
    layers.library's LockLayer is identical to LockLayerRom.

INPUTS
    layer - pointer to Layer structure

RESULTS
    The layer is locked and the task can render assuming the
    ClipRects will not change out from underneath it until
    an UnlockLayerRom is called.

SEE ALSO
    UnlockLayerRom() layers.library/LockLayer() graphics/clip.h


graphics.library/MakeVPort

NAME
    MakeVPort -- generate display copper list for a viewport.

SYNOPSIS
    MakeVPort( view, viewport )
                a0      a1

    void MakeVPort( struct View *, struct ViewPort * );

FUNCTION
    Uses information in the View, ViewPort, ViewPort->RasInfo to
    construct and intermediate copper list for this ViewPort.

INPUTS
    view - pointer to a View structure
    viewport - pointer to a ViewPort structure
             The viewport must have valid pointer to a RasInfo.

RESULTS
    constructs intermediate copper list and puts pointers in
    viewport.DspIns
    If the ColorMap ptr in ViewPort is NULL then it uses colors
    from the default color table.
    If DUALPF in Modes then there must be a second RasInfo pointed
    to by the first RasInfo

BUGS
    Narrow Viewports (whose righthand edge is less than 3/4 of the
    way across the display) still do not work properly.

SEE ALSO
    InitVPort() MrgCop() graphics/view.h intuition.library/MakeScreen()
    intuition.library/RemakeDisplay() intuition.library/RethinkDisplay()


graphics.library/ModeNotAvailable

NAME
    ModeNotAvailable -- check to see if a DisplayID isn't available. (V36)

SYNOPSIS
    error =  ModeNotAvailable( modeID )
    d0                         d0

    ULONG   ModeNotAvailable( ULONG);

FUNCTION
    returns an error code, indicating why this modeID is not available,
    or NULL if there is no reason known why this mode should not be there.

INPUTS
    modeID -- a 32 bit DisplayInfoRecord identifier.

RESULT
    error -- a general indication of why this modeID is not available,
             or NULL if there is no reason why it shouldn't be available.

NOTE
    ULONG return values from this function are a proper superset of the
    DisplayInfo.NotAvailable field (defined in graphics/displayinfo.h).

BUGS

SEE ALSO
    graphics/displayinfo.h, GetVPModeID()


graphics.library/Move

NAME
    Move -- Move graphics pen position.

SYNOPSIS
    Move( rp,   x,    y)
          a1  d0:16 d1:16

    void Move( struct RastPort *, SHORT, SHORT );

FUNCTION
    Move graphics pen position to (x,y) relative to upper left (0,0)
    of RastPort. This sets the starting point for subsequent Draw()
    and Text() calls.

INPUTS
    rp - pointer to a RastPort structure
    x,y - point in the RastPort

RESULTS

BUGS

SEE ALSO
    Draw graphics/rastport.h


graphics.library/MoveSprite

NAME
    MoveSprite -- Move sprite to a point relative to top of viewport.

SYNOPSIS
    MoveSprite(vp, sprite, x, y)
               A0  A1      D0 D1

    void MoveSprite(struct ViewPort *,struct SimpleSprite *, WORD, WORD);

FUNCTION
    Move sprite image to new place on display.

INPUTS
    vp - pointer to ViewPort structure
         if vp = 0, sprite is positioned relative to View.
    sprite - pointer to SimpleSprite structure
    (x,y)  - new position relative to top of viewport or view.

RESULTS
    Calculate the hardware information for the sprite and
    place it in the posctldata array. During next video display
    the sprite will appear in new position.

BUGS
    Sprites really appear one pixel to the left of the position you
    specify.  This bug affects the apparent display position of the sprite
    on the screen, but does not affect the numeric position relative to
    the viewport or view.

SEE ALSO
    FreeSprite()  ChangeSprite()  GetSprite()  graphics/sprite.h


graphics.library/MrgCop

NAME
    MrgCop -- Merge together coprocessor instructions.

SYNOPSIS
    MrgCop( View )
            A1

    void MrgCop( struct View * );

FUNCTION
    Merge together the display, color, sprite and user coprocessor
    instructions into a single coprocessor instruction stream.  This
    essentially creates a per-display-frame program for the coprocessor.
    This function MrgCop is used, for example, by the graphics animation
    routines which effectively add information into an essentially
    static background display.  This changes some of the user
    or sprite instructions, but not those which have formed the
    basic display in the first place.  When all forms of coprocessor
    instructions are merged together, you will have a complete per-
    frame instruction list for the coprocessor.

    Restrictions:  Each of the coprocessor instruction lists MUST be
    internally sorted in min to max Y-X order.  The merge routines
    depend on this! Each list must be terminated using CEND(copperlist).

INPUTS
    View - a pointer to the view structure whose coprocessor
          instructions are to be merged.

RESULT
    The view structure will now contain a complete, sorted/merged
    list of instructions for the coprocessor, ready to be used by
    the display processor.  The display processor is told to use
    this new instruction stream through the instruction LoadView().

BUGS

SEE ALSO
    InitVPort() MakeVPort() LoadView() graphics/view.h
    intuition.library/RethinkDisplay()


graphics.library/NewRegion

NAME
    NewRegion -- Get an empty region.

SYNOPSIS
    region = NewRegion()
      d0

    struct Region *NewRegion();

FUNCTION
    Create a Region structure, initialize it to empty, and return
    a pointer it.

RESULTS
    region - pointer to initialized region. If it could not allocate
            required memory region = NULL.

INPUTS
    none

BUGS

SEE ALSO
    graphics/regions.h


graphics.library/NextDisplayInfo

NAME
    NextDisplayInfo -- iterate current displayinfo identifiers (V36)

SYNOPSIS
    next_ID = NextDisplayInfo(last_ID)
    D0                        D0

    ULONG NextDisplayInfo(ULONG);

FUNCTION
    The basic iteration function with which to find all records in the
    graphics database.  Using each ID in succession, you can then call
    FindDisplayInfo() to obtain the handle associated with each ID.
    Each ID is a 32-bit Key which uniquely identifies one record.
    The INVALID_ID is special, and indicates the end-of-list.

INPUTS
    last_ID - previous displayinfo identifier
              or INVALID_ID if beginning iteration.

RESULT
    next_ID - subsequent displayinfo identifier
              or INVALID_ID if no more records.

BUGS

SEE ALSO
    FindDisplayInfo(), GetDisplayInfoData()
    graphics/displayinfo.h


graphics.library/OpenFont

NAME
    OpenFont -- Get a pointer to a system font.

SYNOPSIS
    font = OpenFont(textAttr)
    D0              A0

    struct TextFont *OpenFont(struct TextAttr *);

FUNCTION
    This function searches the system font space for the graphics
    text font that best matches the attributes specified.  The
    pointer to the font returned can be used in subsequent
    SetFont and CloseFont calls.  It is important to match this
    call with a corresponding CloseFont call for effective
    management of ram fonts.

INPUTS
    textAttr - a TextAttr or TTextAttr structure that describes the
               text font attributes desired.

RESULT
    font is zero if the desired font cannot be found.  If the named
    font is found, but the size and style specified are not
    available, a font with the nearest attributes is returned.

SEE ALSO
    CloseFont()  SetFont()
    diskfont.library/OpenDiskFont  graphics/text.h


graphics.library/OpenMonitor

NAME
    OpenMonitor -- open a named MonitorSpec (V36)

SYNOPSIS
    mspc = OpenMonitor( monitor_name , display_id)
     d0                  a1              d0

    struct MonitorSpec *OpenMonitor( char *, ULONG );

FUNCTION
    Locate and open a named MonitorSpec.

INPUTS
    monitor_name - a pointer to a null terminated string.
    display_id - an optional 32 bit monitor/mode identifier

RESULTS
    mspc - a pointer to an open MonitorSpec structure.
           NULL if MonitorSpec could not  be opened.

NOTE
    if monitor_name is non-NULL, the monitor will be opened by name.
    if monitor_name is NULL the monitor will be opened by optional ID.
    if both monitor_name and display_id are NULL returns default monitor.

BUGS

SEE ALSO
    CloseMonitor() graphics/monitor.h


graphics.library/OrRectRegion

NAME
    OrRectRegion -- Perform 2d OR operation of rectangle
                   with region, leaving result in region.

SYNOPSIS
    status = OrRectRegion(region,rectangle)
      d0                    a0      a1

    BOOL OrRectRegion( struct Region *, struct Rectangle * );

FUNCTION
    If any portion of rectangle is not in the region then add
    that portion to the region.

INPUTS
    region - pointer to Region structure
    rectangle - pointer to Rectangle structure

RESULTS
    status - return TRUE if successful operation
             return FALSE if ran out of memory

BUGS

SEE ALSO
    AndRectRegion() OrRegionRegion() graphics/regions.h


graphics.library/OrRegionRegion

NAME
    OrRegionRegion -- Perform 2d OR operation of one region
                   with second region, leaving result in second region

SYNOPSIS
    status = OrRegionRegion(region1,region2)
      d0                       a0      a1

    BOOL OrRegionRegion( struct Region *, struct Region * );

FUNCTION
    If any portion of region1  is not in the region then add
    that portion to the region2

INPUTS
    region1 - pointer to Region structure
    region2 - pointer to Region structure

RESULTS
    status - return TRUE if successful operation
             return FALSE if ran out of memory

BUGS

SEE ALSO
    OrRectRegion() graphics/regions.h


graphics.library/OwnBlitter

NAME
    OwnBlitter -- get the blitter for private usage

SYNOPSIS
    OwnBlitter()

    void OwnBlitter( void );

FUNCTION
    If blitter is available return immediately with the blitter
    locked for your exclusive use. If the blitter is not available
    put task to sleep. It will be awakened as soon as the blitter
    is available. When the task first owns the blitter the blitter
    may still be finishing up a blit for the previous owner. You
    must do a WaitBlit before actually using the blitter registers.

    Calls to OwnBlitter() do not nest. If a task that owns the
    blitter calls OwnBlitter() again, a lockup will result.
    (Same situation if the task calls a system function
    that tries to own the blitter).

INPUTS
    NONE

RETURNS
    NONE

SEE ALSO
    DisownBlitter() WaitBlit()


graphics.library/PolyDraw

NAME
    PolyDraw -- Draw lines from table of (x,y) values.

SYNOPSIS
    PolyDraw( rp, count , array )
              a1   d0      a0

    void PolyDraw( struct RastPort *, WORD, WORD * );

FUNCTION
    starting with the first pair in the array, draw connected lines to
    it and every successive pair.

INPUTS
    rp - pointer to RastPort structure
    count -  number of (x,y) pairs in the array
    array - pointer to first (x,y) pair

BUGS

SEE ALSO
    Draw() Move() graphics/rastport.h


graphics.library/QBlit

NAME
    QBlit -- Queue up a request for blitter usage

SYNOPSIS
    QBlit( bp )
           a1

    void QBlit( struct bltnode * );

FUNCTION
    Link a request for the use of the blitter to the end of the
    current blitter queue.  The pointer bp points to a blit structure
    containing, among other things, the link information, and the
    address of your routine which is to be called when the blitter
    queue finally gets around to this specific request.  When your
    routine is called, you are in control of the blitter ... it is
    not busy with anyone else's requests.  This means that you can
    directly specify the register contents and start the blitter.
    See the description of the blit structure and the uses of QBlit
    in the section titled Graphics Support in the OS Kernel Manual.
    Your code must be written to run either in supervisor or user
    mode on the 68000.

INPUTS
    bp - pointer to a blit structure

RESULT
    Your routine is called when the blitter is ready for you.
    In general requests for blitter usage through this channel are
    put in front of those who use the blitter via OwnBlitter and
    DisownBlitter. However for small blits there is more overhead
    using the queuer than Own/Disown Blitter.

BUGS

SEE ALSO
    QBSBlit() hardware/blit.h


graphics.library/QBSBlit

NAME

    QBSBlit -- Synchronize the blitter request with the video beam.

SYNOPSIS

    QBSBlit( bsp )
             a1

    void QBSBlit( struct bltnode * );

FUNCTION
    Call a user routine for use of the blitter, enqueued separately from
    the QBlit queue.  Calls the user routine contained in the blit
    structure when the video beam is located at a specified position
    onscreen.   Useful when you are trying to blit into a visible part
    of the screen and wish to perform the data move while the beam is
    not trying to display that same area.  (prevents showing part of
    an old display and part of a new display simultaneously).  Blitter
    requests on the QBSBlit queue take precedence over those on the
    regular blitter queue. The beam position is specified the blitnode.

INPUTS
    bsp - pointer to a blit structure.  See description in the
         Graphics Support section of the manual for more info.

RESULT
    User routine is called when the QBSBlit queue reaches this
    request AND the video beam is in the specified position.
    If there are lots of blits going on and the video beam
    has wrapped around back to the top it will call all the
    remaining bltnodes as fast as it can to try and catch up.

BUGS
    Not very smart when getting blits from different tasks.
    They all get put in same queue so there are unfortunately
    some interdependencies with the beam syncing.

SEE ALSO
    QBlit() hardware/blit.h


graphics.library/ReadPixel

NAME
    ReadPixel -- read the pen number value of the pixel at a
                 specified x,y location within a certain RastPort.

SYNOPSIS
    penno = ReadPixel( rp,    x,    y )
      d0               a1  d0:16 d1:16

    LONG ReadPixel( struct RastPort *, SHORT, SHORT );

FUNCTION
    Combine the bits from each of the bit-planes used to describe
    a particular RastPort into the pen number selector which that
    bit combination normally forms for the system hardware selection
    of pixel color.

INPUTS
    rp -  pointer to a RastPort structure
    (x,y) a point in the RastPort

RESULT
    penno - the pen number of the pixel at (x,y) is returned.
            -1 is returned if the pixel cannot be read for some reason.

BUGS

SEE ALSO
    WritePixel()    graphics/rastport.h


graphics.library/ReadPixelArray8

NAME
    ReadPixelArray8 -- read the pen number value of a rectangular array
    of pixels starting at a specified x,y location and continuing
    through to another x,y location within a certain RastPort. (V36)

SYNOPSIS
    count = ReadPixelArray8(rp,xstart,ystart,xstop,ystop,array,temprp)
    D0                      A0 D0:16  D1:16  D2:16 D3:16 A2    A1

 LONG ReadPixelArray8(struct  RastPort *, UWORD, UWORD, UWORD, UWORD,
       UBYTE *, struct RastPort *);

FUNCTION
    For each pixel in a rectangular region, combine the bits from each
    of the bit-planes used to describe a particular RastPort into the pen
    number selector which that bit combination normally forms for the
    system hardware selection of pixel color.

INPUTS
    rp    -  pointer to a RastPort structure
    (xstart,ystart) - starting point in the RastPort
    (xstop,ystop)   - stopping point in the RastPort
    array -  pointer to an array of ubytes from which to fetch the pixel
             data allocate at least ((((width+15)>>4)<<4)*(ystop-ystart+1))
             bytes.
    temprp - temporary rastport (copy of rp with Layer set == NULL,
             temporary memory allocated for
             temprp->BitMap with Rows set == 1,
             temprp->BytesPerRow == (((width+15)>>4)<<1),
             and temporary memory allocated for
             temprp->BitMap->Planes[])

RESULT
    For each pixel in the array:
        Pen - (0..255) number at that position is returned
      count - the number of pixels read.

NOTE
    xstop must be >= xstart
    ystop must be >= ystart

BUGS

SEE ALSO
    ReadPixel()  ReadPixelLine8()  graphics/rastport.h


graphics.library/ReadPixelLine8

NAME
    ReadPixelLine8 -- read the pen number value of a horizontal line
    of pixels starting at a specified x,y location and continuing
    right for count pixels. (V36)

SYNOPSIS
    count = ReadPixelLine8(rp,xstart,ystart,width,array,temprp)
    D0                     A0 D0:16  D1:16  D2    A2    A1

    LONG ReadPixelLine8(struct RastPort *, UWORD, UWORD, UWORD,
         UBYTE *, struct RastPort * );

FUNCTION
    For each pixel in a rectangular region, combine the bits from each
    of the bit-planes used to describe a particular RastPort into the pen
    number selector which that bit combination normally forms for the
    system hardware selection of pixel color.

INPUTS
    rp     - pointer to a RastPort structure
    (x,y)  - a point in the RastPort
    width  - count of horizontal pixels to read
    array -  pointer to an array of UBYTEs from which to fetch the pixel
             data allocate at least (((width+15)>>4)<<4) bytes.
    temprp - temporary rastport (copy of rp with Layer set == NULL,
             temporary memory allocated for
             temprp->BitMap with Rows set == 1,
             temprp->BytesPerRow == (((width+15)>>4)<<1),
             and temporary memory allocated for
             temprp->BitMap->Planes[])

RESULT
    For each pixel in the array:
        Pen - (0..255) number at that position is returned
    count   - the number of pixels read.

NOTE
    width must be non negative

BUGS

SEE ALSO
    ReadPixel()  graphics/rastport.h


graphics.library/RectFill

NAME
    RectFill -- Fill a rectangular region in a RastPort.

SYNOPSIS

    RectFill( rp, xmin, ymin, xmax, ymax)
             a1  d0:16 d1:16 d2:16 d3:16

    void RectFill( struct RastPort *, SHORT, SHORT, SHORT, SHORT );

FUNCTION
    Fills  the  rectangular  region  specified  by  the
    parameters  with the chosen pen  colors,  areafill
    pattern, and drawing mode. If no areafill pattern is
    specified, fill the rectangular region with the FgPen
    color, taking into account the drawing mode.

INPUTS
    rp - pointer to a RastPort structure
    (xmin,ymin) (xmax,ymax) are the coordinates of the upper
            left corner and the lower right corner, respectively, of the
            rectangle.
NOTE

    The following relation MUST be true:
            (xmax >= xmin) and (ymax >= ymin)

BUGS
    Complement mode with FgPen complements all bitplanes.

SEE ALSO
    AreaEnd() graphics/rastport.h


graphics.library/RemBob

NAME
    RemBob -- Macro to remove a Bob from the gel list.

SYNOPSIS
    RemBob(bob)

    RemBob(struct Bob *);

FUNCTION
    Marks a Bob as no-longer-required.  The gels internal code then
    removes the Bob from the list of active gels the next time
    DrawGList is executed. This is implemented as a macro.
    If the user is double-buffering the Bob, it could take two
    calls to DrawGList before the Bob actually disappears from
    the RastPort.

INPUTS
    Bob = pointer to the Bob to be removed

RESULT

BUGS

SEE ALSO
    RemIBob()  DrawGList()  graphics/gels.h  graphics/gfxmacros.h


graphics.library/RemFont

NAME
    RemFont -- Remove a font from the system list.

SYNOPSIS
    RemFont(textFont)
            A1

    void RemFont(struct TextFont *);

FUNCTION
    This function removes a font from the system, ensuring that
    access to it is restricted to those applications that
    currently have an active pointer to it: i.e. no new SetFont
    requests to this font are satisfied.

INPUTS
    textFont - the TextFont structure to remove.

RESULT

BUGS

SEE ALSO
    SetFont()  AddFont()  graphics/text.h


graphics.library/RemIBob

NAME
    RemIBob -- Immediately remove a Bob from the gel list and the RastPort.

SYNOPSIS
    RemIBob(bob, rp, vp)
            A0   A1  A2

    void RemIBob(struct Bob *, struct RastPort *, struct ViewPort *);

FUNCTION
    Removes a Bob immediately by uncoupling it from the gel list and
    erases it from the RastPort.

INPUTS
    bob = pointer to the Bob to be removed
    rp  = pointer to the RastPort if the Bob is to be erased
    vp  = pointer to the ViewPort for beam-synchronizing

RESULT

BUGS

SEE ALSO
    InitGels()  RemVSprite()  graphics/gels.h


graphics.library/RemVSprite

NAME
    RemVSprite -- Remove a VSprite from the current gel list.

SYNOPSIS
    RemVSprite(vs)
               A0

    void RemVSprite(struct VSprite *);

FUNCTION
    Unlinks the VSprite from the current gel list.

INPUTS
    vs = pointer to the VSprite structure to be removed from the gel list

RESULT

BUGS

SEE ALSO
    InitGels()  RemIBob()  graphics/gels.h


graphics.library/ScalerDiv

NAME
    ScalerDiv -- Get the scaling result that BitMapScale would. (V36)

SYNOPSIS
    result = ScalerDiv(factor, numerator, denominator)
    D0                 D0      D1         D2

    UWORD ScalerDiv(UWORD, UWORD, UWORD);

FUNCTION
    Calculate the expression (factor*numerator/denominator) such
    that the result is the same as the width of the destination
    result of BitMapScale when the factor here is the width of
    the source, and the numerator and denominator are the
    XDestFactor and XSrcFactor for BitMapScale.

INPUTS
    factor                 - a number in the range 0..16383
    numerator, denominator - numbers in the range 1..16383

RESULT
    this returns factor*numerator/denominator


graphics.library/ScrollRaster

NAME
    ScrollRaster -- Push bits in rectangle in raster around by
                    dx,dy towards 0,0 inside rectangle.
SYNOPSIS
    ScrollRaster(rp, dx, dy, xmin, ymin, xmax, ymax)
                 A1  D0  D1  D2    D3    D4    D5

    void ScrollRaster
         (struct RastPort *, WORD, WORD, WORD, WORD, WORD, WORD);

FUNCTION
    Move the bits in the raster by (dx,dy) towards (0,0)
    The space vacated is RectFilled with BGPen.
    Limit the scroll operation to the rectangle defined
    by (xmin,ymin)(xmax,ymax). Bits outside will not be
    affected. If xmax,ymax is outside the rastport then use
    the lower right corner of the rastport.
    If you are dealing with a SimpleRefresh layered RastPort you
    should check rp->Layer->Flags & LAYER_REFRESH to see if
    there is any damage in the damage list.  If there is you should
    call the appropriate BeginRefresh(Intuition) or BeginUpdate(graphics)
    routine sequence.

INPUTS
    rp - pointer to a RastPort structure
    dx,dy are integers that may be postive, zero, or negative
    xmin,ymin - upper left of bounding rectangle
    xmax,ymax - lower right of bounding rectangle

EXAMPLE
    ScrollRaster(rp,0,1)    /* shift raster up by one row */
    ScrollRaster(rp,-1,-1)  /* shift raster down and to the right */
                            /* by 1 pixel                         */

BUGS
    In 1.2/V1.3 if you ScrollRaster a SUPERBITMAP exactly left or
    right, and there is no TmpRas attached to the RastPort, the system
    will allocate one for you, but will never free it or record its
    location. This bug has been fixed for V1.4.  The workaround for
    1.2/1.3 is to attach a valid TmpRas of size at least
    MAXBYTESPERROW to the RastPort before the call.

    Begining with V1.4 ScrollRaster adds the shifted areas into the
    damage list for SIMPLE_REFRESH windows. Due to unacceptable
    system overhead, the decision was made NOT to propagate this
    shifted area damage for SMART_REFRESH windows.

SEE ALSO
    graphics/rastport.h


graphics.library/ScrollVPort

NAME
    ScrollVPort -- Reinterpret RasInfo information in ViewPort to reflect
                    the current Offset values.

SYNOPSIS
    ScrollVPort( vp )
                 a0

    void ScrollVPort(struct ViewPort *);

FUNCTION
    After the programmer has adjusted the Offset values in
    the RasInfo structures of ViewPort, change the
    the copper lists to reflect the the Scroll positions.
    Changing the BitMap ptr in RasInfo and not changing the
    the Offsets will effect a double buffering affect.

INPUTS
    vp - pointer to a ViewPort structure
         that is currently be displayed.
RESULTS
    modifies hardware and intermediate copperlists to reflect
    new RasInfo

BUGS
   pokes not fast enough to avoid some visible hashing of display

SEE ALSO
    MakeVPort() MrgCop() LoadView()  graphics/view.h


graphics.library/SetAPen

NAME
    SetAPen -- Set the primary pen for a RastPort.

SYNOPSIS
    SetAPen( rp, pen )
             a1  d0

    void SetAPen( struct RastPort *, UBYTE );

FUNCTION
    Set the primary drawing pen for lines, fills, and text.

INPUTS
    rp - pointer to RastPort structure.
    pen - (0-255)

RESULT
    Changes the minterms in the RastPort to reflect new primary pen.
    Sets line drawer to restart pattern.

BUGS

SEE ALSO
    SetBPen() graphics/rastport.h


graphics.library/SetBPen

NAME
    SetBPen -- Set secondary pen for a RastPort

SYNOPSIS
    SetBPen( rp, pen )
             a1  d0

    void SetBPen( struct RastPort *, UBYTE );

FUNCTION
    Set the secondary drawing pen for lines, fills, and text.

INPUTS
    rp - pointer to RastPort structure.
    pen - (0-255)

RESULT
    Changes the minterms in the RastPort to reflect new secondary pen.
    Sets line drawer to restart pattern.

BUGS

SEE ALSO
    SetAPen() graphics/rastport.h


graphics.library/SetCollision

NAME
    SetCollision -- Set a pointer to a user collision routine.

SYNOPSIS
    SetCollision(num, routine, GInfo)
                 D0   A0       A1

    void SetCollision(ULONG, VOID (*)(), struct GelsInfo *);

FUNCTION
    Sets a specified entry (num) in the user's collision vectors table
    equal to the address of the specified collision routine.

INPUTS
    num     = collision vector number
    routine = pointer to the user's collision routine
    GInfo   = pointer to a GelsInfo structure

RESULT

BUGS

SEE ALSO
    InitGels()  graphics/gels.h  graphics/rastport.h


graphics.library/SetDrMd

NAME
    SetDrMd -- Set drawing mode for a RastPort

SYNOPSIS
    SetDrMd( rp, mode )
             a1  d0:8

    void SetDrMd( struct RastPort *, UBYTE );

FUNCTION
    Set the drawing mode for lines, fills and text.
    Get the bit definitions from rastport.h

INPUTS
    rp - pointer to RastPort structure.
    mode - 0-255, some combinations may not make much sense.

RESULT
    The mode set is dependant on the bits selected.
    Changes minterms to reflect new drawing mode.
    Sets line drawer to restart pattern.

BUGS

SEE ALSO
    SetAPen() SetBPen() graphics/rastport.h


graphics.library/SetFont

NAME
    SetFont -- Set the text font and attributes in a RastPort.

SYNOPSIS
    SetFont(rp, font)
            A1   A0

    void SetFont(struct RastPort *, struct TextFont *);

FUNCTION
    This function sets the font in the RastPort to that described
    by font, and updates the text attributes to reflect that
    change.  This function clears the effect of any previous
    soft styles.

INPUTS
    rp   - the RastPort in which the text attributes are to be changed
    font - pointer to a TextFont structure returned from OpenFont()
           or OpenDiskFont()

RESULT

NOTES
    This function had previously been documented that it would
    accept a null font.  This practice is discouraged.
    o   Use of a RastPort with a null font with text routines has
        always been incorrect and risked the guru.
    o   Keeping an obsolete font pointer in the RastPort is no more
        dangerous than keeping a zero one there.
    o   SetFont(rp, 0) causes spurious low memory accesses under
        some system software releases.

    As of V36, the following Amiga font variants are no longer
    directly supported:
        fonts with NULL tf_CharSpace and non-NULL tf_CharKern.
        fonts with non-NULL tf_CharSpace and NULL tf_CharKern.
        fonts with NULL tf_CharSpace and NULL tf_CharKern with
            a tf_CharLoc size component greater than tf_XSize.
    Attempts to SetFont these one of these font variants will
    cause the system to modify your font to make it acceptable.

BUGS
    Calling SetFont() on in-code TextFonts (ie fonts not
    OpenFont()ed) will result in a loss of 24 bytes from
    the system as of V36.
    This can be resolved by calling StripFont().

SEE ALSO
    OpenFont()  StripFont()
    diskfont.library/OpenDiskFont()  graphics/text.h


graphics.library/SetOPen

NAME
    SetOPen -- Change the Area OutLine pen and turn on Outline
                    mode for areafills.

SYNOPSIS
    SetOPen(rp, pen)

    void SetOPen( struct RastPort *, UBYTE );

FUNCTION
    This is implemented as a c-macro.
    Pen is the pen number that will be used to draw a border
    around an areafill during AreaEnd().

INPUTS
    rp = pointer to RastPort structure
    pen = number  between 0-255

BUGS

SEE ALSO
    AreaEnd() graphics/gfxmacros.h graphics/rastport.h


graphics.library/SetRast

NAME
    SetRast - Set an entire drawing area to a specified color.

SYNOPSIS
    SetRast( rp, pen )
             a1  d0

    void SetRast( struct RastPort *, UBYTE );

FUNCTION
    Set the entire contents of the specified RastPort to the
    specified pen.

INPUTS
    rp - pointer to RastPort structure
    pen - the pen number (0-255) to jam into bitmap

RESULT
    All pixels within the drawing area are set to the
    selected pen number.

BUGS

SEE ALSO
    RectFill() graphics/rastport.h


graphics.library/SetRGB4

NAME
    SetRGB4 -- Set one color register for this viewport.

SYNOPSIS
    SetRGB4(  vp, n,   r,    g,    b)
              a0  d0  d1:4  d2:4  d3:4

    void SetRGB4( struct ViewPort *, SHORT, UBYTE, UBYTE, UBYTE );

FUNCTION
    Change the color look up table so that this viewport displays
    the color (r,g,b) for pen number n.

INPUTS
    vp - pointer to  viewport structure
    n - the color number (range from 0 to 31)
    r - red level (0-15)
    g - green level (0-15)
    b - blue level (0-15)

RESULT
    If there is a ColorMap for this viewport, then the value will
    be stored in the ColorMap.
    The selected color register is changed to match your specs.
    If the color value is unused then nothing will happen.

BUGS
    NOTE: Under V36 and up, it is not safe to call this function
    from an interrupt, due to semaphore protection of graphics
    copper lists.

SEE ALSO
    LoadRGB4() GetRGB4() graphics/view.h


graphics.library/SetRGB4CM

NAME
    SetRGB4CM -- Set one color register for this ColorMap.

SYNOPSIS
    SetRGB4CM(  cm,  n,   r,    g,    b)
                a0  d0  d1:4  d2:4  d3:4

    void SetRGB4CM( struct ColorMap *, SHORT, UBYTE, UBYTE, UBYTE );

INPUTS
    cm = colormap
    n = the number of the color register to set. Ranges from 0 to 31
         on current amiga displays.
    r = red level (0-15)
    g = green level (0-15)
    b = blue level (0-15)

RESULT
    Store the (r,g,b) triplet at index n of the ColorMap structure.
    This function can be used to set up a ColorMap before before
    linking it into a viewport.

BUGS

SEE ALSO
    GetColorMap() GetRGB4() SetRGB4() graphics/view.h


graphics.library/SetSoftStyle

NAME
    SetSoftStyle -- Set the soft style of the current font.

SYNOPSIS
    newStyle = SetSoftStyle(rp, style, enable)
    D0                      A1  D0     D1

    ULONG SetSoftStyle(struct RastPort *, ULONG, ULONG);

FUNCTION
    This function alters the soft style of the current font.  Only
    those bits that are also set in enable are affected.  The
    resulting style is returned, since some style request changes
    will not be honored when the implicit style of the font
    precludes changing them.

INPUTS
    rp     - the RastPort from which the font and style
             are extracted.
    style  - the new font style to set, subject to enable.
    enable - those bits in style to be changed.  Any set bits here
             that would not be set as a result of AskSoftStyle will
             be ignored, and the newStyle result will not be as
             expected.

RESULTS
    newStyle - the resulting style, both as a result of previous
               soft style selection, the effect of this function,
               and the style inherent in the set font.

BUGS

SEE ALSO
    AskSoftStyle()  graphics/text.h


graphics.library/SortGList

NAME
    SortGList -- Sort the current gel list, ordering its y,x coordinates.

SYNOPSIS
    SortGList(rp)
              A1

    void SortGList(struct RastPort *);

FUNCTION
    Sorts the current gel list according to the gels' y,x coordinates.
    This sorting is essential before calls to DrawGList or DoCollision.

INPUTS
    rp = pointer to the RastPort structure containing the GelsInfo

RESULT

BUGS

SEE ALSO
    InitGels()  DoCollision()  DrawGList()  graphics/rastport.h


graphics.library/StripFont

NAME
    StripFont -- remove the tf_Extension from a font (V36)

SYNOPSIS
    StripFont(font)
              A0

    VOID StripFont(struct TextFont *);


graphics.library/SyncSBitMap

NAME
    SyncSBitMap --   Syncronize Super BitMap with whatever is
                     in the standard Layer bounds.

SYNOPSIS
    SyncSBitMap( layer )
                  a0

    void SyncSBitMap( struct Layer * );

FUNCTION
    Copy all bits from ClipRects in Layer into Super BitMap
    BitMap.  This is used for those functions that do not
    want to deal with the ClipRect structures but do want
    to be able to work with a SuperBitMap Layer.

INPUTS
    layer - pointer to a Layer that has a SuperBitMap
            The Layer should already be locked by the caller.

RESULT
    After calling this function, the programmer can manipulate
    the bits in the superbitmap associated with the layer.
    Afterwards, the programmer should call CopySBitMap to
    copy the bits back into the onscreen layer.

BUGS

SEE ALSO
    CopySBitMap() graphics/clip.h


graphics.library/Text

NAME
    Text -- Write text characters (no formatting).

SYNOPSIS
    Text(rp, string, length)
         A1  A0      D0-0:16

    void Text(struct RastPort *, STRPTR, WORD);

FUNCTION
    This graphics function writes printable text characters to the
    specified RastPort at the current position.  No control meaning
    is applied to any of the characters, thus only text on the
    current line is output.

    The current position in the RastPort is updated to the next
    character position.
    If the characters displayed run past the RastPort boundary,
    the current position is truncated to the boundary, and
    thus does not equal the old position plus the text length.

INPUTS
    rp     - a pointer to the RastPort which describes where the
             text is to be output
    string - the address of string to output
    length - the number of characters in the string.
             If zero, there are no characters to be output.

NOTES
    o   This function may use the blitter.
    o   Changing the text direction with RastPort->TxSpacing is
        not supported.

BUGS
    For V34 and earlier:
    o   The maximum string length (in pixels) is limited to
        (1024 - 16 = 1008) pixels wide.
    o   A text string whose last character(s) have a
        tf_CharLoc size component that extends to the right of
        the rightmost of the initial and final CP positions
        will be (inappropriately) clipped.

SEE ALSO
    Move()  TextLength()  graphics/text.h  graphics/rastport.h


graphics.library/TextExtent

NAME
    TextExtent -- Determine raster extent of text data. (V36)

SYNOPSIS
    TextExtent(rp, string, count, textExtent)
               A1  A0      D0:16  A2

    void TextExtent(struct RastPort *, STRPTR, WORD,
         struct TextExtent *);

FUNCTION
    This function determines a more complete metric of the space
    that a text string would render into than the TextLength()
    function.

INPUTS
    rp     - a pointer to the RastPort which describes where the
             text attributes reside.
    string - the address of the string to determine the length of.
    count  - the number of characters in the string.
            If zero, there are no characters in the string.
    textExtent - a structure to hold the result.

RESULTS
    textExtent is filled in as follows:
        te_Width  - same as TextLength() result: the rp_cp_x
                    advance that rendering this text would cause.
        te_Height - same as tf_YSize.  The height of the
                    font.
        te_Extent.MinX - the offset to the left side of the
                    rectangle this would render into.  Often zero.
        te_Extent.MinY - same as -tf_Baseline.  The offset
                    from the baseline to the top of the rectangle
                    this would render into.
        te_Extent.MaxX - the offset of the left side of the
                    rectangle this would render into.  Often the
                    same as te_Width-1.
        te_Extent.MaxY - same as tf_YSize-tf_Baseline-1.
                    The offset from the baseline to the bottom of
                    the rectanangle this would render into.

SEE ALSO
    TextLength()  Text()  TextFit()
    graphics/text.h  graphics/rastport.h


graphics.library/TextFit

NAME
    TextFit - count characters that will fit in a given extent (V36)

SYNOPSIS
    chars = TextFit(rastport, string, strLen, textExtent,
    D0              A1        A0      D0      A2
            constrainingExtent, strDirection,
            A3                  D1
            constrainingBitWidth, constrainingBitHeight)
            D2                    D3

    ULONG TextFit(struct RastPort *, STRPTR, UWORD,
        struct TextExtent *, struct TextExtent *, WORD, UWORD, UWORD);

FUNCTION
    This function determines how many of the characters of the
    provided string will fit into the space described by the
    constraining parameters.  It also returns the extent of
    that number of characters.

INPUTS
    rp     - a pointer to the RastPort which describes where the
             text attributes reside.
    string - the address of string to determine the constraint of
    strLen - The number of characters in the string.
             If zero, there are no characters in the string.
    textExtent - a structure to hold the extent result.
    constrainingExtent - the extent that the text must fit in.
        This can be NULL, indicating only the constrainingBit
        dimensions will describe the constraint.
    strDirection - the offset to add to the string pointer to
        get to the next character in the string.  Usually 1.
        Set to -1 and the string to the end of the string to
        perform a TextFit() anchored at the end.  No other value
        is valid.
    constrainingBitWidth - an alternative way to specify the
        rendering box constraint width that is independent of
        the rendering origin.  Range 0..32767.
    constrainingBitHeight - an alternative way to specify the
        rendering box constraint height that is independent of
        the rendering origin.  Range 0..32767.

RESULTS
    chars - the number of characters from the origin of the
            given string that will fit in both the constraining
            extent (which specifies a CP bound and a rendering
            box relative to the origin) and in the rendering width
            and height specified.

NOTES
    The result is zero chars and an empty textExtent when the fit
    cannot be performed.  This occurs not only when no text will
    fit in the provided constraints, but also when:
    -   the RastPort rp's rp_TxSpacing sign and magnitude is so
        great it reverses the path of the text.
    -   the constrainingExtent does not include x = 0.

SEE ALSO
    TextExtent()  TextLength()  Text()
    graphics/text.h  graphics/rastport.h


graphics.library/TextLength

NAME
    TextLength -- Determine raster length of text data.

SYNOPSIS
    length = TextLength(rp, string, count)
    D0                  A1  A0      D0:16

    WORD TextLength(struct RastPort *, STRPTR, WORD);

FUNCTION
    This graphics function determines the length that text data
    would occupy if output to the specified RastPort with the
    current attributes.  The length is specified as the number of
    raster dots: to determine what the current position would be
    after a Write() using this string, add the length to cp_x
    (cp_y is unchanged by Write()).  Use the newer TextExtent() to
    get more information.

INPUTS
    rp     - a pointer to the RastPort which describes where the
             text attributes reside.
    string - the address of string to determine the length of
    count  - the string length.  If zero, there are no characters
             in the string.

RESULTS
    length - the number of pixels in x this text would occupy, not
             including any negative kerning that may take place at
             the beginning of the text string, nor taking into
             account the effects of any clipping that may take
             place.

NOTES
    Prior to V36, the result length occupied only the low word of
    d0 and was not sign extended into the high word.

BUGS
    A length that would overflow single word arithmatic is not
    calculated correctly.

SEE ALSO
    TextExtent()  Text()  TextFit()
    graphics/text.h  graphics/rastport.h


graphics.library/UnlockLayerRom

NAME
    UnlockLayerRom -- Unlock Layer structure by rom(gfx lib) code.

SYNOPSIS
    UnlockLayerRom( layer )
                     a5

    void UnlockLayerRom( struct Layer * );

FUNCTION
    Release the lock on this layer. If the same task has called
    LockLayerRom more than once than the same number of calls to
    UnlockLayerRom must happen before the layer is actually freed
    so that other tasks may use it.
    This call does destroy scratch registers.
    This call is identical to UnlockLayer (layers.library).

INPUTS
    layer - pointer to Layer structure

BUGS

SEE ALSO
    LockLayerRom() layers.library/UnlockLayer() graphics/clip.h


graphics.library/VBeamPos

NAME
    VBeamPos -- Get vertical beam position at this instant.

SYNOPSIS
    pos = VBeamPos()
     d0

    LONG VBeamPos( void );

FUNCTION
    Get the vertical beam position from the hardware.

INPUTS
    none

RESULT
    interrogates hardware for beam position and returns value.
    valid results in are the range of 0-511.
    Because of multitasking, the actual value returned may have
    no use. If you are the highest priority task then the value
    returned should be close, within 1 line.

BUGS

SEE ALSO


graphics.library/VideoControl

NAME
    VideoControl -- Modify the operation of a ViewPort's ColorMap (V36)

SYNOPSIS
    error = VideoControl( cm , tags )
    d0                    a0   a1

    ULONG VideoControl( struct ColorMap *, struct TagItem * );

FUNCTION
   Process the commands in the VideoControl command TagItem buffer
   using cm as the target, with respect to its "attached" ViewPort.

   viewport commands:

   VTAG_ATTACH_CM     [_SET        | _GET] -- setget attached viewport
   VTAG_VIEWPORTEXTRA [_SET        | _GET] -- setget attached vp_extra
   VTAG_NORMAL_DISP   [_SET        | _GET] -- setget DisplayInfoHandle
                                                      (natural mode)
   VTAG_COERCE_DISP   [_SET        | _GET] -- setget DisplayInfoHandle
                                                      (coerced mode)

   genlock commands:

   VTAG_BORDERBLANK   [_SET | _CLR | _GET] -- onoffinquire blanking
   VTAG_BORDERNOTRANS [_SET | _CLR | _GET] -- onoffinquire notransparency
   VTAG_CHROMAKEY     [_SET | _CLR | _GET] -- onoffinquire chroma mode
   VTAG_BITPLANEKEY   [_SET | _CLR | _GET] -- onoffinquire bitplane mode
   VTAG_CHROMA_PEN    [_SET | _CLR | _GET] -- setclrget chromakey pen #
   VTAG_CHROMA_PLANE  [_SET |      | _GET] -- setget bitplanekey plane #

   copper commands

   VTAG_USERCLIP      [_SET | _CLR | _GET] -- onoffinquire clipping of
                                              UserCopperList at bottom
                                              edge of ColorMap->cm_vp
                                              (defaults to off)

   buffer commands:

   VTAG_NEXTBUF_CM                         -- link to more VTAG commands
   VTAG_END_CM                             -- terminate command buffer

   batch mode commands:

   (if you want your videocontol taglist to be processed in "batch"
    mode, that is, at the next MakeVPort() for the ColorMap->cm_vp;
    you may intall a static list of videocontrol TagItems into the
    ColorMap with the BATCH_ITEMS_SET command; and then enable/disable
    batch mode processing of those items via the BATCH_CM control
    command)

   VTAG_BATCH_CM      [_SET | _CLR | _GET] -- onoffinquire batch mode
   VTAG_BATCH_ITEMS   [_SET | _ADD | _GET] -- setaddget batched TagLists

   private commands (used internally by intuition -- do not call):

   VTAG_VPMODEID      [_SET | _CLR | _GET] -- force GetVPModeID() return

INPUTS
    cm   = pointer to struct ColorMap obtained via GetColorMap().
    tags = pointer to a table of videocontrol tagitems.

RESULT
    error = NULL if no error occured in the control operation.
   (non-NULL if bad colormap pointer, no tagitems or bad tag)

    The operating characteristics of the ColorMap and its attached
    ViewPort are modified. The result will be incorporated into the
    ViewPort when its copper lists are reassembled via MakeVPort().

BUGS

SEE ALSO
    graphics/videocontrol.h, GetColorMap(), FreeColorMap()


graphics.library/WaitBlit

NAME
    WaitBlit -- Wait for the blitter to be finished before proceeding
               with anything else.

SYNOPSIS
    WaitBlit()

    void WaitBlit( void );

FUNCTION
    WaitBlit returns when the blitter is idle. This function should
    normally only be used when dealing with the blitter in a
    synchronous manner, such as when using OwnBlitter and DisownBlitter.
    WaitBlit does not wait for all blits queued up using QBlit or
    QBSBlit. You should call WaitBlit if you are just about to modify or
    free some memory that the blitter may be using.

INPUTS
    none

RESULT
    Your program waits until the blitter is finished.
    This routine does not use any the CPU registers.
    do/d1/a0/a1 are preserved by this routine.
    It may change the condition codes though.

BUGS
    When examining bits with the CPU right after a blit, or when freeeing
    temorary memory used by the blitter, a WaitBlit() may be required.

    Note that many graphics calls fire up the blitter, and let it run.
    The CPU does not need to wait for the blitter to finish before
    returning.

    Because of a bug in agnus (prior to all revisions of fat agnus)
    this code may return too soon when the blitter has, in fact, not
    started the blit yet, even though BltSize has been written.

    This most often occurs in a heavily loaded systen with extended memory,
    HIRES, and 4 bitplanes.

    WaitBlit currently tries to avoid this agnus problem by testing
    the BUSY bit multiple times to make sure the blitter has started.
    If the blitter is BUSY at first check, this function busy waits.

    This initial hardware bug was fixed as of the first "Fat Agnus" chip,
    as used in all A500 and A2000 computers.

    Because of a different bug in agnus (currently all revisions thru ECS)
    this code may return too soon when the blitter has, in fact, not
    stopped the blit yet, even though blitter busy has been cleared.

    This most often occurs in a heavily loaded systen with extended memory,
    in PRODUCTIVITY mode, and 2 bitplanes.

    WaitBlit currently tries to avoid this agnus problem by testing
    the BUSY bit multiple times to make sure the blitter has really
    written its final word of desination data.

SEE ALSO
    OwnBlitter() DisownBlitter() hardware/blit.h


graphics.library/WaitBOVP

NAME
    WaitBOVP -- Wait till vertical beam reached bottom of
                this viewport.

SYNOPSIS
    WaitBOVP( vp )
              a0

    void WaitBOVP( struct ViewPort * );

FUNCTION
    Returns when the vertical beam has reached the bottom of this viewport

INPUTS
    vp - pointer to ViewPort structure

RESULT
    This function will return sometime after the beam gets beyond
    the bottom of the viewport.  Depending on the multitasking load
    of the system, the actual beam position may be different than
    what would be expected in a lightly loaded system.

BUGS
    Horrors! This function currently busy waits waiting for the
    beam to get to the right place.  It should use the copper
    interrupt to trigger and send signals like WaitTOF does.

SEE ALSO
    WaitTOF() VBeamPos()


graphics.library/WaitTOF

NAME
    WaitTOF -- Wait for the top of the next video frame.

SYNOPSIS
    WaitTOF()

    void WaitTOF( void );

FUNCTION
    Wait  for vertical blank to occur and all vertical blank
    interrupt routines to complete before returning to caller.

INPUTS
    none

RESULT
    Places this task on the TOF wait queue. When the vertical blank
    interupt comes around, the interrupt service routine will fire off
    signals to all the tasks doing WaitTOF. The highest priority task
    ready will get to run then.

BUGS

SEE ALSO
    exec.library/Wait() exec.library/Signal()


graphics.library/WeighTAMatch

NAME
    WeighTAMatch -- Get a measure of how well two fonts match. (V36)

SYNOPSIS
    weight = WeighTAMatch(reqTextAttr, targetTextAttr, targetTags)
    D0                    A0           A1              A2

    WORD WeighTAMatch(struct TTextAttr *, struct TextAttr *,
         struct TagItem *);

FUNCTION
    This function provides a metric to describe how well two fonts
    match.  This metric ranges from MAXFONTMATCHWEIGHT (perfect match)
    through lower positive numbers to zero (unsuitable match).

INPUTS
    reqTextAttr    - the text attributes requested.
    targetTextAttr - the text attributes of a potential match.
    targetTags     - tags describing the extended target attributes, or
                     zero if not available.

    The [t]ta_Name fields of the [T]TextAttr structures are not used.

    The tags affect the weight only when both a) the reqTextAttr
    has the FSF_TAGGED bit set in ta_Style, and b) targetTags is
    not zero.  To fairly compare two different weights, the inclusion
    or exclusion of tags in the weighing must be the same for both.

RESULTS
    weight -- a positive weight describes suitable matches, in
          increasing desirability.  MAXFONTMATCHWEIGHT is a perfect
          match.  A zero weight is an unsuitable match.

SEE ALSO
    OpenFont()


graphics.library/WritePixel

NAME
    WritePixel -- Change the pen num of one specific pixel in a
                 specified RastPort.

SYNOPSIS
    error = WritePixel(  rp, x,  y)
     d0                 a1 D0  D1

    LONG WritePixel( struct RastPort *, SHORT, SHORT );

FUNCTION
    Changes the pen number of the selected pixel in the specified
    RastPort to that currently specified by PenA, the primary
    drawing pen. Obeys minterms in RastPort.

INPUTS
    rp    - a pointer to the RastPort structure
    (x,y) - point within the RastPort at which the selected
            pixel is located.

RESULT
    error = 0 if pixel succesfully changed
          = -1 if (x,y) is outside the RastPort

BUGS

SEE ALSO
    ReadPixel() graphics/rastport.h


graphics.library/WritePixelArray8

NAME
    WritePixelArray8 -- write the pen number value of a rectangular array
    of pixels starting at a specified x,y location and continuing
    through to another x,y location within a certain RastPort. (V36)

SYNOPSIS
    count = WritePixelArray8(rp,xstart,ystart,xstop,ystop,array,temprp)
    D0                       A0 D0:16  D1:16  D2:16 D3:16  A2   A1

    LONG WritePixelArray8(struct  RastPort *, UWORD, UWORD,
         UWORD, UWORD, UBYTE *, struct  RastPort *);

FUNCTION
    For each pixel in a rectangular region, decode the pen number selector
    from a linear array of pen numbers into the bit-planes used to describe
    a particular rastport.

INPUTS
    rp     -  pointer to a RastPort structure
    (xstart,ystart) -  starting point in the RastPort
    (xstop,ystop)   -  stopping point in the RastPort
    array  - pointer to an array of UBYTEs from which to fetch the
             pixel data. Allocate at least
             ((((width+15)>>4)<<4)*(ystop-ystart+1)) bytes.
    temprp - temporary rastport (copy of rp with Layer set == NULL,
             temporary memory allocated for
             temprp->BitMap with Rows set == 1,
             temprp->BytesPerRow == (((width+15)>>4)<<1),
             and temporary memory allocated for
             temprp->BitMap->Planes[])

RESULT
    For each pixel in the array:
        Pen - (0..255) number at that position is returned

NOTE
    xstop must be >= xstart
    ystop must be >= ystart

BUGS

SEE ALSO
    WritePixel()  graphics/rastport.h


graphics.library/WritePixelLine8

NAME
    WritePixelLine8 -- write the pen number value of a horizontal line
    of pixels starting at a specified x,y location and continuing
    right for count pixels. (V36)

SYNOPSIS
    count = WritePixelLine8(rp,xstart,ystart,width,array,temprp)
    D0                      A0 D0:16  D1:16  D2    A2    A1

    LONG WritePixelLine8(struct RastPort *, UWORD, UWORD,
         UWORD, UBYTE *, struct RastPort *);

FUNCTION
    For each pixel in a horizontal region, decode the pen number selector
    from a linear array of pen numbers into the bit-planes used to describe
    a particular rastport.

INPUTS
    rp     - pointer to a RastPort structure
    (x,y)  - a point in the RastPort
    width  - count of horizontal pixels to write
    array  - pointer to an array of UBYTEs from which to fetch the pixel
             data allocate at least (((width+15)>>4)<<4) bytes.
    temprp - temporary rastport (copy of rp with Layer set == NULL,
             temporary memory allocated for
             temprp->BitMap with Rows set == 1,
             temprp->BytesPerRow == (((width+15)>>4)<<1),
             and temporary memory allocated for
             temprp->BitMap->Planes[])

RESULT
    For each pixel in the array:
        Pen - (0..255) number at that position is returned

NOTE
    width must be non negative

BUGS

SEE ALSO
    WritePixel()  graphics/rastport.h


graphics.library/XorRectRegion

NAME
    XorRectRegion -- Perform 2d XOR operation of rectangle
                     with region, leaving result in region

SYNOPSIS
    status = XorRectRegion(region,rectangle)
    d0                     a0      a1

    BOOL XorRectRegion( struct Region *, struct Rectangle * );

FUNCTION
    Add portions of rectangle to region if they are not in
    the region.
    Remove portions of rectangle from region if they are
    in the region.

INPUTS
    region - pointer to Region structure
    rectangle - pointer to Rectangle structure

RESULTS
    status - return TRUE if successful operation
             return FALSE if ran out of memory

BUGS

SEE ALSO
    OrRegionRegion() AndRegionRegion() graphics/regions.h


graphics.library/XorRegionRegion

NAME
    XorRegionRegion -- Perform 2d XOR operation of one region
                       with second region, leaving result in second region

SYNOPSIS
    status = XorRegionRegion(region1,region2)
    d0                        a0      a1

    BOOL XorRegionRegion( struct Region *, struct Region * );

FUNCTION
    Join the regions together. If any part of region1 overlaps
    region2 then remove that from the new region.

INPUTS
    region1      = pointer to Region structure
    region2      = pointer to Region structure

RESULTS
    status - return TRUE if successful operation
             return FALSE if ran out of memory

BUGS


mathieeedoubtrans.doc

 IEEEDPAcos()      IEEEDPExp()        IEEEDPSin()         IEEEDPTanh()
 IEEEDPAsin()      IEEEDPFieee()      IEEEDPSincos()      IEEEDPTieee()
 IEEEDPAtan()      IEEEDPLog()        IEEEDPSinh()
 IEEEDPCos()       IEEEDPLog10()      IEEEDPSqrt()
 IEEEDPCosh()      IEEEDPPow()        IEEEDPTan()


mathieeedoubtrans.library/IEEEDPAcos

NAME
    IEEEDPAcos -- compute the arc cosine of a number

SYNOPSIS
      x   = IEEEDPAcos(  y  );
    d0/d1              d0/d1

    double  x,y;

FUNCTION
    Compute arc cosine of y in IEEE double precision

INPUTS
    y - IEEE double precision floating point value

RESULT
    x - IEEE double precision floating point value

BUGS

SEE ALSO
    IEEEDPCos(), IEEEDPAtan(), IEEEDPAsin()


mathieeedoubtrans.library/IEEEDPAsin

NAME
    IEEEDPAsin -- compute the arcsine of a number

SYNOPSIS
      x   = IEEEDPAsin(  y  );
    d0/d1              d0/d1

    double  x,y;

FUNCTION
    Compute the arc sine of y in IEEE double precision

INPUTS
    y - IEEE double precision floating point value

RESULT
    x - IEEE double precision floating point value

BUGS

SEE ALSO
    IEEEDPSin(), IEEEDPAtan(), IEEEDPAcos()


mathieeedoubtrans.library/IEEEDPAtan

NAME
    IEEEDPAtan -- compute the arctangent of a floating point number

SYNOPSIS
      x   = IEEEDPAtan(  y  );
    d0/d1              d0/d1

    double  x,y;

FUNCTION
    Compute arctangent of y in IEEE double precision

INPUTS
    y - IEEE double precision floating point value

RESULT
    x - IEEE double precision floating point value

BUGS

SEE ALSO
    IEEEDPTan(), IEEEDPAsin(), IEEEDPACos()


mathieeedoubtrans.library/IEEEDPCos

NAME
    IEEEDPCos -- compute the cosine of a floating point number

SYNOPSIS
      x   = IEEEDPCos(  y  );
    d0/d1              d0/d1

    double  x,y;

FUNCTION
    Compute cosine of y in IEEE double precision

INPUTS
    y - IEEE double precision floating point value

RESULT
    x - IEEE double precision floating point value

BUGS

SEE ALSO
    IEEEDPAcos(), IEEEDPSin(), IEEEDPTan()


mathieeedoubtrans.library/IEEEDPCosh

NAME
    IEEEDPCosh -- compute the hyperbolic cosine of a floating point number

SYNOPSIS
      x   = IEEEDPCosh(  y  );
    d0/d1              d0/d1

    double  x,y;

FUNCTION
    Compute hyperbolic cosine of y in IEEE double precision

INPUTS
    y - IEEE double precision floating point value

RESULT
    x - IEEE double precision floating point value

BUGS

SEE ALSO
    IEEEDPSinh(), IEEEDPTanh()


mathieeedoubtrans.library/IEEEDPExp

NAME
    IEEEDPExp -- compute the exponential of e

SYNOPSIS
      x   = IEEEDPExp(  y  );
    d0/d1             d0/d1

    double  x,y;

FUNCTION
    Compute e^y in IEEE double precision

INPUTS
    y - IEEE double precision floating point value

RESULT
    x - IEEE double precision floating point value

BUGS

SEE ALSO
    IEEEDPLog()


mathieeedoubtrans.library/IEEEDPFieee

NAME
    IEEEDPFieee -- convert IEEE single to IEEE double

SYNOPSIS
      x   = IEEEDPFieee(  y  );
    d0/d1                 d0

    float   y;
    double  x;

FUNCTION
    Convert IEEE single precision number to IEEE double precision.

INPUTS
    y - IEEE single precision floating point value

RESULT
    x - IEEE double precision floating point value

BUGS

SEE ALSO
    IEEEDPTieee()


mathieeedoubtrans.library/IEEEDPLog

NAME
    IEEEDPLog -- compute the natural logarithm of a floating point number

SYNOPSIS
      x   = IEEEDPLog(  y  );
    d0/d1             d0/d1

    double  x,y;

FUNCTION
    Compute ln(y) in IEEE double precision

INPUTS
    y - IEEE double precision floating point value

RESULT
    x - IEEE double precision floating point value

BUGS

SEE ALSO
    IEEEDPExp()


mathieeedoubtrans.library/IEEEDPLog10

NAME
    IEEEDPLog10 -- compute logarithm base 10 of a number

SYNOPSIS
      x   = IEEEDPLog10(  y  );
    d0/d1               d0/d1

    double  x,y;

FUNCTION
    Compute the logarithm base 10 of y in IEEE double precision

INPUTS
    y - IEEE double precision floating point value

RESULT
    x - IEEE double precision floating point value

BUGS

SEE ALSO
    IEEEDPLog()


mathieeedoubtrans.library/IEEEDPPow

NAME
    IEEEDPPow -- raise a number to another number power

SYNOPSIS
      z   = IEEEDPPow(  x  ,  y  );
    d0/d1             d2/d3 d0/d1

    double  x,y,z;

FUNCTION
    Compute y^x in IEEE double precision

INPUTS
    x - IEEE double precision floating point value
    y - IEEE double precision floating point value

RESULT
    z - IEEE double precision floating point value

BUGS

SEE ALSO


mathieeedoubtrans.library/IEEEDPSin

NAME
    IEEEDPSin -- compute the sine of a floating point number

SYNOPSIS
      x   = IEEEDPSin(  y  );
    d0/d1             d0/d1

    double  x,y;

FUNCTION
    Compute sine of y in IEEE double precision

INPUTS
    y - IEEE double precision floating point value

RESULT
    x - IEEE double precision floating point value

BUGS

SEE ALSO
    IEEEDPAsin(), IEEEDPTan(), IEEEDPCos()


mathieeedoubtrans.library/IEEEDPSincos

NAME
    IEEEDPSincos -- compute the arc tangent of a floating point number

SYNOPSIS
      x   = IEEEDPSincos( z ,  y  );
    d0/d1                a0  d0/d1

    double  x,y,*z;

FUNCTION
    Compute sin and cosine of y in IEEE double precision.
    Store the cosine in *z. Return the sine of y.

INPUTS
    y - IEEE double precision floating point value
    z - pointer to IEEE double precision floating point number

RESULT
    x - IEEE double precision floating point value

BUGS

SEE ALSO
    IEEEDPSin(), IEEEDPCos()


mathieeedoubtrans.library/IEEEDPSinh

NAME
    IEEEDPSinh -- compute the hyperbolic sine of a floating point number

SYNOPSIS
      x   = IEEEDPSinh(  y  );
    d0/d1              d0/d1

    double  x,y;

FUNCTION
    Compute hyperbolic sine of y in IEEE double precision

INPUTS
    y - IEEE double precision floating point value

RESULT
    x - IEEE double precision floating point value

BUGS

SEE ALSO
    IEEEDPCosh, IEEEDPTanh


mathieeedoubtrans.library/IEEEDPSqrt

NAME
    IEEEDPSqrt -- compute the square root of a number

SYNOPSIS
      x   = IEEEDPSqrt(  y  );
    d0/d1              d0/d1

    double  x,y;

FUNCTION
    Compute square root of y in IEEE double precision

INPUTS
    y - IEEE double precision floating point value

RESULT
    x - IEEE double precision floating point value

BUGS

SEE ALSO


mathieeedoubtrans.library/IEEEDPTan

NAME
    IEEEDPTan -- compute the tangent of a floating point number

SYNOPSIS
      x   = IEEEDPTan(  y  );
    d0/d1             d0/d1

    double  x,y;

FUNCTION
    Compute tangent of y in IEEE double precision

INPUTS
    y - IEEE double precision floating point value

RESULT
    x - IEEE double precision floating point value

BUGS

SEE ALSO
    IEEEDPAtan(), IEEEDPSin(), IEEEDPCos()


mathieeedoubtrans.library/IEEEDPTanh

NAME
    IEEEDPTanh -- compute the hyperbolic tangent of a floating point number

SYNOPSIS
      x   = IEEEDPTanh(  y  );
    d0/d1              d0/d1

    double  x,y;

FUNCTION
    Compute hyperbolic tangent of y in IEEE double precision

INPUTS
    y - IEEE double precision floating point value

RESULT
    x - IEEE double precision floating point value

BUGS

SEE ALSO
    IEEEDPSinh(), IEEEDPCosh()


mathieeedoubtrans.library/IEEEDPTieee

NAME
    IEEEDPTieee -- convert IEEE double to IEEE single

SYNOPSIS
      x   = IEEEDPTieee(  y  );
     d0                 d0/d1

    double  y;
    float   x;

FUNCTION
    Convert IEEE double precision number to IEEE single precision.

INPUTS
    y - IEEE double precision floating point value

RESULT
    x - IEEE single precision floating point value

BUGS

SEE ALSO
    IEEEDPFieee()


audio.doc

 AbortIO()           ADCMD_PERVOL         CMD_CLEAR      CMD_STOP
 ADCMD_ALLOCATE      ADCMD_SETPREC        CMD_FLUSH      CMD_UPDATE
 ADCMD_FINISH        ADCMD_WAITCYCLE      CMD_READ       CMD_WRITE
 ADCMD_FREE          BeginIO()            CMD_RESET      Expunge()
 ADCMD_LOCK          CloseDevice()        CMD_START      OpenDevice()


audio.device/AbortIO

NAME
    AbortIO - abort a device command

SYNOPSIS
    AbortIO(iORequest);
                A1

FUNCTION
    AbortIO tries to abort a device command.  It is allowed to be
    unsuccessful.  If the Abort is successful, the io_Error field of the
    iORequest contains an indication that IO was aborted.

INPUTS
    iORequest -- pointer to the I/O Request for the command to abort


audio.device/ADCMD_ALLOCATE

    ADCMD_ALLOCATE -- allocate a set of audio channels

FUNCTION
    ADCMD_ALLOCATE is a command that allocates multiple audio channels.
    ADCMD_ALLOCATE takes an array of possible channel combinations
    (ioa_Data) and an allocation precedence (ln_Pri) and tries to allocate
    one of the combinations of channels.

    If the channel combination array is zero length (ioa_Length), the
    allocation succeeds; otherwise, ADCMD_ALLOCATE checks each
    combination, one at a time, in the specified order, to find one
    combination that does not require ADCMD_ALLOCATE to steal allocated
    channels.

    If it must steal allocated channels, it uses the channel combination
    that steals the lowest precedence channels.

    ADCMD_ALLOCATE cannot steal a channel of equal or greater precedence
    than the allocation precedence (ln_Pri).

    If it fails to allocate any channel combination and the no-wait flag
    (ADIOF_NOWAIT) is set ADCMD_ALLOCATE returns a zero in the unit field
    of the I/O request (io_Unit) and an error (IOERR_ALLOCFAILED).  If the
    no-wait flag is clear, it places the I/O request in a list that tries
    to allocate again whenever ADCMD_FREE frees channels or ADCMD_SETPREC
    lowers the channels' precedences.

    If the allocation is successful, ADCMD_ALLOCATE checks if any channels
    are locked (ADCMD_LOCK) and if so, replies (ReplyMsg) the lock I/O
    request with an error (ADIOERR_CHANNELSTOLEN). Then it places the
    allocation I/O request in a list waiting for the locked channels to be
    freed.  When all the allocated channels are un-locked, ADCMD_ALLOCATE:
      . resets (CMD_RESET) the allocated channels,
      . generates a new allocation key (ioa_AllocKey), if it is zero,
      . copies the allocation key into each of the allocated channels
      . copies the allocation precedence into each of the allocated
        channels, and
      . copies the channel bit map into the unit field of the I/O request.

    If channels are allocated with a non-zero allocation key,
    ADCMD_ALLOCATE allocates with that same key; otherwise, it generates a
    new and unique key.

    ADCMD_ALLOCATE is synchronous:
      . if the allocation succeeds and there are no locked channels to be
        stolen, or
      . if the allocation fails and the no-wait flag is set.

    In either case, ADCMD_ALLOCATE only replies (mn_ReplyPort) if the
    quick flag (IOF_QUICK) is clear; otherwise, the allocation is
    asynchronous, so it clears the quick flag and replies the I/O request
    after the allocation is finished.  If channels are stolen, all audio
    device commands return an error (IOERR_NOALLOCATION) when the former
    user tries to use them again.  Do not use ADCMD_ALLOCATE in interrupt
    code.

    If you decide to store directly to the audio hardware registers, you
    must either lock the channels you've allocated, or set the precedence
    to maximum (ADALLOC_MAXPREC) to prevent the channels from being
    stolen.

    Under all circumstances, unless channels are stolen, you must free
    (ADCMD_FREE) all allocated channels when you are finished using them.

INPUTS
    ln_Pri      - allocation precedence (-128 thru 127)
    mn_ReplyPort- pointer to message port that receives I/O request after
                  the allocation completes is asynchronous or quick flag
                  (ADIOF_QUICK) is set
    io_Device   - pointer to device node, must be set by (or copied from
                  I/O block set by) OpenDevice function
    io_Command  - command number for ADCMD_ALLOCATE
    io_Flags    - flags, must be cleared if not used:
                  IOF_QUICK   - (CLEAR) reply I/O request
                                (SET) only reply I/O request only if
                                      asynchronous (see above text)
                  ADIOF_NOWAIT- (CLEAR) if allocation fails, wait till is
                                        succeeds
                                (SET) if allocation fails, return error
                                      (ADIOERR_ALLOCFAILED)
    ioa_AllocKey- allocation key, zero to generate new key; otherwise,
                  it must be set by (or copied from I/O block set by)
                  OpenDevice function or previous ADCMD_ALLOCATE command
    ioa_Data    - pointer to channel combination options (byte array, bits
                  0 thru 3 correspond to channels 0 thru 3)
    ioa_Length  - length of the channel combination option array
                  (0 thru 16, 0 always succeeds)

OUTPUTS
    io_Unit     - bit map of successfully allocated channels (bits 0 thru
                  3 correspond to channels 0 thru 3)
    io_Flags    - IOF_QUICK flag cleared if asynchronous (see above text)
    io_Error    - error number:
                  0                   - no error
                  ADIOERR_ALLOCFAILED - allocation failed
    ioa_AllocKey- allocation key, set to a unique number if passed a zero
                  and command succeeds


audio.device/ADCMD_FINISH

NAME
    ADCMD_FINISH -- abort writes in progress to audio channels

FUNCTION
    ADCMD_FINISH is a command for multiple audio channels.  For each
    selected channel (io_Unit), if the allocation key (ioa_AllocKey) is
    correct and there is a write (CMD_WRITE)in progress, ADCMD_FINISH
    aborts the current write immediately or at the end of the current
    cycle depending on the sync flag (ADIOF_SYNCCYCLE).  If the allocation
    key is incorrect ADCMD_FINISH returns an error (ADIOERR_NOALLOCATION).
    ADCMD_FINISH is synchronous and only replies (mn_ReplyPort) if the
    quick flag (IOF_QUICK) is clear.  Do not use ADCMD_FINISH in interrupt
    code at interrupt level 5 or higher.

INPUTS
    mn_ReplyPort- pointer to message port that receives I/O request
                  if the quick flag (IOF_QUICK) is clear
    io_Device   - pointer to device node, must be set by (or copied from
                  I/O block set by) OpenDevice function
    io_Unit     - bit map of channels to finish (bits 0 thru 3 correspond
                  to channels 0 thru 3)
    io_Command  - command number for ADCMD_FINISH
    io_Flags    - flags, must be cleared if not used:
                  IOF_QUICK      - (CLEAR) reply I/O request
                  ADIOF_SYNCCYCLE- (CLEAR) finish immediately
                                   (SET) finish at the end of current
                                         cycle

    ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                  set by) OpenDevice function or ADCMD_ALLOCATE command

OUTPUTS
    io_Unit     - bit map of channels successfully finished (bits 0 thru 3
                  correspond to channels 0 thru 3)
    io_Error    - error number:
                  0                    - no error
                  ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                         does not match key for channel


audio.device/ADCMD_FREE

NAME
    ADCMD_FREE -- free audio channels for allocation

FUNCTION
    ADCMD_FREE is a command for multiple audio channels.  For each
    selected channel (io_Unit), if the allocation key (ioa_AllocKey) is
    correct, ADCMD_FREE does the following:
      . restores the channel to a known state (CMD_RESET),
      . changes the channels allocation key, and
      . makes the channel available for re-allocation.
      . If the channel is locked (ADCMD_LOCK) ADCMD_FREE unlocks it and
        clears the bit for the channel (io_Unit) in the lock I/O request.
        If the lock I/O request has no channel bits set ADCMD_FREE replies
        the lock I/O request, and
      . checks if there are allocation requests (ADCMD_ALLOCATE) waiting
        for the channel.

    Otherwise, ADCMD_FREE returns an error (ADIOERR_NOALLOCATION).
    ADCMD_FREE is synchronous and only replies (mn_ReplyPort) if the quick
    flag (IOF_QUICK) is clear.  Do not use ADCMD_FREE in interrupt code.

INPUTS
    mn_ReplyPort- pointer to message port that receives I/O request
                  if the quick flag (IOF_QUICK) is clear
    io_Device   - pointer to device node, must be set by (or copied from
                  I/O block set by) OpenDevice function
    io_Unit     - bit map of channels to free (bits 0 thru 3 correspond to
                  channels 0 thru 3)
    io_Command  - command number for ADCMD_FREE
    io_Flags    - flags, must be cleared if not used:
                  IOF_QUICK - (CLEAR) reply I/O request
    ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                  set by) OpenDevice function or ADCMD_ALLOCATE command

OUTPUTS
    io_Unit     - bit map of channels successfully freed (bits 0 thru 3
                  correspond to channels 0 thru 3)
    io_Error    - error number:
                  0                    - no error
                  ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                         does not match key for channel


audio.device/ADCMD_LOCK

NAME
    ADCMD_LOCK -- prevent audio channels from being stolen

FUNCTION
    ADCMD_LOCK is a command for multiple audio channels.  For each
    selected channel (io_Unit), if the allocation key (ioa_AllocKey) is
    correct, ADCMD_LOCK locks the channel, preventing subsequent
    allocations (ADCMD_ALLOCATE or OpenDevice) from stealing the channel.
    Otherwise, ADCMD_LOCK returns an error (ADIOERR_NOALLOCATION) and will
    not lock any channels.

    Unlike setting the precedence (ADCMD_SETPREC, ADCMD_ALLOCATE or
    OpenDevice) to maximum (ADALLOC_MAXPREC) which would cause all
    subsequent allocations to fail, ADCMD_LOCK causes all higher
    precedence allocations, even no-wait (ADIOF_NOWAIT) allocations, to
    wait until the channels are un-locked.

    Locked channels can only be unlocked by freeing them (ADCMD_FREE),
    which clears the channel select bits (io_Unit).  ADCMD_LOCK does not
    reply the I/O request (mn_ReplyPort) until all the channels it locks
    are freed, unless a higher precedence allocation attempts to steal one
    the locked channels. If a steal occurs, ADCMD_LOCK replies and returns
    an error (ADIOERR_CHANNELSTOLEN).  If the lock is replied
    (mn_ReplyPort) with this error, the channels should be freed as soon
    as possible.  To avoid a possible deadlock, never make the freeing of
    stolen channels dependent on another allocations completion.

    ADCMD_LOCK is only asynchronous if the allocation key is correct, in
    which case it clears the quick flag (IOF_QUICK); otherwise, it is
    synchronous and only replies if the quick flag (IOF_QUICK) is clear.
    Do not use ADCMD_LOCK in interrupt code.

INPUTS
    mn_ReplyPort- pointer to message port that receives I/O request
                  if the quick flag (IOF_QUICK) is clear
    io_Device   - pointer to device node, must be set by (or copied from
                  I/O block set by) OpenDevice function
    io_Unit     - bit map of channels to lock (bits 0 thru 3 correspond to
                  channels 0 thru 3)
    io_Command  - command number for ADCMD_LOCK
    io_Flags    - flags, must be cleared
    ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                  set by) OpenDevice function or ADCMD_ALLOCATE command

OUTPUTS
    io_Unit     - bit map of successfully locked channels (bits 0 thru 3
                  correspond to channels 0 thru 3) not freed (ADCMD_FREE)
    io_Flags    - IOF_QUICK flag cleared if the allocation key is correct
                  (no ADIOERR_NOALLOCATION error)
    io_Error    - error number:
                  0                    - no error
                  ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                         does not match key for channel
                  ADIOERR_CHANNELSTOLEN- allocation attempting to steal
                                         locked channel


audio.device/ADCMD_PERVOL

NAME
    ADCMD_PERVOL -- change the period and volume for writes in progress to
                    audio channels

FUNCTION
    ADCMD_PERVOL is a command for multiple audio channels.  For each
    selected channel (io_Unit), if the allocation key (ioa_AllocKey) is
    correct and there is a write (CMD_WRITE) in progress, ADCMD_PERVOL
    loads a new volume and period immediately or at the end of the current
    cycle depending on the sync flag (ADIOF_SYNCCYCLE).  If the allocation
    key in incorrect, ADCMD_PERVOL returns an error
    (ADIOERR_NOALLOCATION).  ADCMD_PERVOL is synchronous and only replies
    (mn_ReplyPort) if the quick flag (IOF_QUICK) is clear.  Do not use
    ADCMD_PERVOL in interrupt code at interrupt level 5 or higher.

INPUTS
    mn_ReplyPort- pointer to message port that receives I/O request
                  if the quick flag (IOF_QUICK) is clear
    io_Device   - pointer to device node, must be set by (or copied from
                  I/O block set by) OpenDevice function
    io_Unit     - bit map of channels to load period and volume (bits 0
                  thru 3 correspond to channels 0 thru 3)
    io_Command  - command number for ADCMD_PERVOL
    io_Flags    - flags, must be cleared if not used:
                  IOF_QUICK      - (CLEAR) reply I/O request
                  ADIOF_SYNCCYCLE- (CLEAR) load period and volume
                                           immediately
                                   (SET) load period and volume at the end
                                         of the current cycle
    ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                  set by) OpenDevice function or ADCMD_ALLOCATE command
    ioa_Period  - new sample period in 279.365 ns increments (124 thru
                  65536, anti-aliasing filter works below 300 to 500
                  depending on waveform)
    ioa_Volume  - new volume (0 thru 64, linear)

OUTPUTS
    io_Unit     - bit map of channels that successfully loaded period and
                  volume (bits 0 thru 3 correspond to channels 0 thru 3)
    io_Error    - error number:
                  0                    - no error
                  ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                         does not match key for channel


audio.device/ADCMD_SETPREC

NAME
    ADCMD_SETPREC -- set the allocation precedence for audio channels

FUNCTION
    ADCMD_SETPREC is a command for multiple audio channels.  For each
    selected channel (io_Unit), if the allocation key (ioa_AllocKey) is
    correct, ADCMD_SETPREC sets the allocation precedence to a new value
    (ln_Pri) and checks if there are allocation requests (ADCMD_ALLOCATE)
    waiting for the channel which now have higher precedence; otherwise,
    ADCMD_SETPREC returns an error (ADIOERR_NOALLOCATION).  ADCMD_SETPREC
    is synchronous and only replies (mn_ReplyPort) if the quick flag
    (IOF_QUICK) is clear.  Do not use ADCMD_SETPREC in interrupt code.

INPUTS
    ln_Pri      - new allocation precedence (-128 thru 127)
    mn_ReplyPort- pointer to message port that receives I/O request
                  if the quick flag (IOF_QUICK) is clear
    io_Device   - pointer to device node, must be set by (or copied from
                  I/O block set by) OpenDevice function
    io_Unit     - bit map of channels to set precedence (bits 0 thru 3
                  correspond to channels 0 thru 3)
    io_Command  - command number for ADCMD_SETPREC
    io_Flags    - flags, must be cleared if not used:
                  IOF_QUICK - (CLEAR) reply I/O request
    ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                  set by) OpenDevice function or ADCMD_ALLOCATE command

OUTPUTS
    io_Unit     - bit map of channels that successfully set precedence
                  (bits 0 thru 3 correspond to channels 0 thru 3)
    io_Error    - error number:
                  0                    - no error
                  ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                         does not match key for channel


audio.device/ADCMD_WAITCYCLE

NAME
    ADCMD_WAITCYCLE -- wait for an audio channel to complete the current
                       cycle of a write

FUNCTION
    ADCMD_WAITCYCLE is a command for a single audio channel (io_Unit).
    If the allocation key (ioa_AllocKey) is correct and there is a write
    (CMD_WRITE) in progress on selected channel, ADCMD_WAITCYCLE does not
    reply (mn_ReplyPort) until the end of the current cycle.  If there is
    no write is progress, ADCMD_WAITCYCLE replies immediately.  If the
    allocation key is incorrect, ADCMD_WAITCYCLE returns an error
    (ADIOERR_NOALLOCATION).  ADCMD_WAITCYCLE returns an error
    (IOERR_ABORTED) if it is canceled (AbortIO) or the channel is stolen
    (ADCMD_ALLOCATE).  ADCMD_WAITCYCLE is only asynchronous if it is
    waiting for a cycle to complete, in which case it clears the quick
    flag (IOF_QUICK); otherwise, it is synchronous and only replies if the
    quick flag (IOF_QUICK) is clear.  Do not use ADCMD_WAITCYCLE in
    interrupt code at interrupt level 5 or higher.

INPUTS
    mn_ReplyPort- pointer to message port that receives I/O request, if
                  the quick flag (IOF_QUICK) is clear, or if a write is in
                  progress on the selected channel and a cycle has
                  completed
    io_Device   - pointer to device node, must be set by (or copied from
                  I/O block set by) OpenDevice function
    io_Unit     - bit map of channel to wait for cycle (bits 0 thru 3
                  correspond to channels 0 thru 3), if more then one bit
                  is set lowest bit number channel is used
    io_Command  - command number for CMD_WAITCYCLE
    io_Flags    - flags, must be cleared if not used:
                  IOF_QUICK - (CLEAR) reply I/O request
                              (SET) only reply I/O request if a write is
                                    in progress on the selected channel
                                    and a cycle has completed
    ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                  set by) OpenDevice function or ADCMD_ALLOCATE command

OUTPUTS
    io_Unit     - bit map of channel that successfully waited for cycle
                  (bits 0 thru 3 correspond to channels 0 thru 3)
    io_Flags    - IOF_QUICK flag cleared if a write is in progress on the
                  selected channel
    io_Error    - error number:
                  0                    - no error
                  IOERR_ABORTED        - canceled (AbortIO) or channel
                                         stolen
                  ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                         does not match key for channel


audio.device/BeginIO

NAME
    BeginIO - dispatch a device command

SYNOPSIS
    BeginIO(iORequest);
                A1

FUNCTION
    BeginIO has the responsibility of dispatching all device commands.
    Immediate commands are always called directly, and all other commands
    are queued to make them single threaded.

INPUTS
    iORequest -- pointer to the I/O Request for this command


audio.device/CloseDevice

NAME
    CloseDevice - terminate access to the audio device

SYNOPSIS
    CloseDevice(iORequest);
                    A1

FUNCTION
    The CloseDevice routine notifies the audio device that it will no
    longer be used.  It takes an I/O audio request block (IOAudio) and
    clears the device pointer (io_Device).  If there are any channels
    allocated with the same allocation key (ioa_AllocKey), CloseDevice
    frees (ADCMD_FREE) them. CloseDevice decrements the open count, and if
    it falls to zero and an expunge (Expunge) is pending, the device is
    expunged.

INPUTS
    iORequest   - pointer to audio request block (struct IOAudio)
            io_Device   - pointer to device node, must be set by (or
                          copied from I/O block set by) open (OpenDevice)
            io_Unit     - bit map of channels to free (ADCMD_FREE) (bits 0
                          thru 3 correspond to channels 0 thru 3)
            ioa_AllocKey- allocation key, used to free channels

OUTPUTS
    iORequest - pointer to audio request block (struct IOAudio)
            io_Device   - set to -1
            io_Unit     - set to zero


audio.device/CMD_CLEAR

NAME
    CMD_CLEAR -- throw away internal caches

FUNCTION
    CMD_CLEAR is a standard command for multiple audio channels.  For each
    selected channel (io_Unit), if the allocation key (ioa_AllocKey) is
    correct, CMD_CLEAR does nothing; otherwise, CMD_CLEAR returns an error
    (ADIOERR_NOALLOCATION).  CMD_CLEAR is synchronous and only replies
    (mn_ReplyPort) if the quick flag (IOF_QUICK) is clear.

INPUTS
    mn_ReplyPort- pointer to message port that receives I/O request after
                  if the quick flag (IOF_QUICK) is clear
    io_Device   - pointer to device node, must be set by (or copied from
                  I/O block set by) OpenDevice function
    io_Unit     - bit map of channels to clear (bits 0 thru 3 correspond
                  to channels 0 thru 3)
    io_Command  - command number for CMD_CLEAR
    io_Flags    - flags, must be cleared if not used:
                  IOF_QUICK - (CLEAR) reply I/O request
    ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                  set by) OpenDevice function or ADCMD_ALLOCATE command

OUTPUTS
    io_Unit     - bit map of channels successfully cleared (bits 0 thru 3
                  correspond to channels 0 thru 3)
    io_Error    - error number:
                  0                    - no error
                  ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                         does not match key for channel


audio.device/CMD_FLUSH

NAME
    CMD_FLUSH -- cancel all pending I/O

FUNCTION
    CMD_FLUSH is a standard command for multiple audio channels.  For each
    selected channel (io_Unit), if the allocation key (ioa_AllocKey) is
    correct, CMD_FLUSH aborts all writes (CMD_WRITE) in progress or queued
    and any I/O requests waiting to synchronize with the end of the cycle
    (ADCMD_WAITCYCLE); otherwise, CMD_FLUSH returns an error
    (ADIOERR_NOALLOCATION).  CMD_FLUSH is synchronous and only replies
    (mn_ReplyPort) if the quick flag (IOF_QUICK) is clear.  Do not use
    CMD_FLUSH in interrupt code at interrupt level 5 or higher.

INPUTS
    mn_ReplyPort- pointer to message port that receives I/O request
                  if the quick flag (IOF_QUICK) is clear
    io_Device   - pointer to device node, must be set by (or copied from
                  I/O block set by) OpenDevice function
    io_Unit     - bit map of channels to flush (bits 0 thru 3 correspond
                  to channels 0 thru 3)
    io_Command  - command number for CMD_FLUSH
    io_Flags    - flags, must be cleared if not used:
                  IOF_QUICK - (CLEAR) reply I/O request
    ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                  set by) OpenDevice function or ADCMD_ALLOCATE command

OUTPUTS
    io_Unit     - bit map of channels successfully flushed (bits 0 thru 3
                  correspond to channels 0 thru 3)
    io_Error    - error number:
                  0                    - no error
                  ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                         does not match key for channel


audio.device/CMD_READ

NAME
    CMD_READ -- normal I/O entry point

FUNCTION
    CMD_READ is a standard command for a single audio channel (io_Unit).
    If the allocation key (ioa_AllocKey) is correct, CMD_READ returns a
    pointer (io_Data) to the I/O block currently writing (CMD_WRITE) on
    the selected channel; otherwise, CMD_READ returns an error
    (ADIOERR_NOALLOCATION).  If there is no write in progress, CMD_READ
    returns zero.  CMD_READ is synchronous and only replies (mn_ReplyPort)
    if the quick bit (IOF_QUICK) is clear.

INPUTS
    mn_ReplyPort- pointer to message port that receives I/O request after
                  if the quick flag (IOF_QUICK) is clear
    io_Device   - pointer to device node, must be set by (or copied from
                  I/O block set by) OpenDevice function
    io_Unit     - bit map of channel to read (bit 0 thru 3 corresponds to
                  channel 0 thru 3), if more then one bit is set lowest
                  bit number channel read
    io_Command  - command number for CMD_READ
    io_Flags    - flags, must be cleared if not used:
                  IOF_QUICK - (CLEAR) reply I/O request
    ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                  set by) OpenDevice function or ADCMD_ALLOCATE command

OUTPUTS
    io_Unit     - bit map of channel successfully read (bit 0 thru 3
                  corresponds to channel 0 thru 3)
    io_Error    - error number:
                  0                    - no error
                  ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                         does not match key for channel
    ioa_Data    - pointer to I/O block for current write, zero if none is
                  progress


audio.device/CMD_RESET

NAME
    CMD_RESET -- restore device to a known state

FUNCTION
    CMD_RESET is a standard command for multiple audio channels.  For each
    selected channel (io_Unit), if the allocation key (ioa_AllocKey) is
    correct, CMD_RESET:
      . clears the hardware audio registers and attach bits,
      . sets the audio interrupt vector,
      . cancels all pending I/O (CMD_FLUSH), and
      . un-stops the channel if it is stopped (CMD_STOP),

    Otherwise, CMD_RESET returns an error (ADIOERR_NOALLOCATION).
    CMD_RESET is synchronous and only replies (mn_ReplyPort) if the quick
    flag (IOF_QUICK) is clear.  Do not use CMD_RESET in interrupt code at
    interrupt level 5 or higher.

INPUTS
    mn_ReplyPort- pointer to message port that receives I/O request
                  if the quick flag (IOF_QUICK) is clear
    io_Device   - pointer to device node, must be set by (or copied from
                  I/O block set by) OpenDevice function
    io_Unit     - bit map of channels to reset (bits 0 thru 3 correspond
                  to channels 0 thru 3)
    io_Command  - command number for CMD_RESET
    io_Flags    - flags, must be cleared if not used:
                  IOF_QUICK - (CLEAR) reply I/O request
    ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                  set by) OpenDevice function or ADCMD_ALLOCATE command

OUTPUTS
    io_Unit     - bit map of channels to successfully reset (bits 0 thru 3
                  correspond to channels 0 thru 3)
    io_Error    - error number:
                  0                    - no error
                  ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                         does not match key for channel


audio.device/CMD_START

NAME
    CMD_START -- start device processing (like ^Q)

FUNCTION
    CMD_START is a standard command for multiple audio channels.  For each
    selected channel (io_Unit), if the allocation key (ioa_AllocKey) is
    correct and the channel was previously stopped (CMD_STOP), CMP_START
    immediately starts all writes (CMD_WRITE) to the channel.  If the
    allocation key is incorrect, CMD_START returns an error
    (ADIOERR_NOALLOCATION).  CMD_START starts multiple channels
    simultaneously to minimize distortion if the channels are playing the
    same waveform and their outputs are mixed. CMD_START is synchronous an
d
    only replies (mn_ReplyPort) if the quick flag (IOF_QUICK) is clear.  D
o
    not use CMD_START in interrupt code at interrupt level 5 or higher.

INPUTS
    mn_ReplyPort- pointer to message port that receives I/O request after
                  if the quick flag (IOF_QUICK) is clear
    io_Device   - pointer to device node, must be set by (or copied from
                  I/O block set by) OpenDevice function
    io_Unit     - bit map of channels to start (bits 0 thru 3 correspond
                  to channels 0 thru 3)
    io_Command  - command number for CMD_START
    io_Flags    - flags, must be cleared if not used:
                  IOF_QUICK - (CLEAR) reply I/O request
    ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                  set by) OpenDevice function or ADCMD_ALLOCATE command

OUTPUTS
    io_Unit     - bit map of channels successfully started (bits 0 thru 3
                  correspond to channels 0 thru 3)
    io_Error    - error number:
                  0                    - no error
                  ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                         does not match key for channel


audio.device/CMD_STOP

NAME
    CMD_STOP -- stop device processing (like ^S)

FUNCTION
    CMD_STOP is a standard command for multiple audio channels.  For each
    selected channel (io_Unit), if the allocation key (ioa_AllocKey) is
    correct, CMD_STOP immediately stops any writes (CMD_WRITE) in
    progress; otherwise, CMD_STOP returns an error (ADIOERR_NOALLOCATION).
    CMD_WRITE queues up writes to a stopped channel until CMD_START starts
    the channel or CMD_RESET resets the channel. CMD_STOP is synchronous
    and only replies (mn_ReplyPort) if the quick flag (IOF_QUICK) is
    clear.  Do not use CMD_STOP in interrupt code at interrupt level 5 or
    higher.

INPUTS
    mn_ReplyPort- pointer to message port that receives I/O request after
                  if the quick flag (IOF_QUICK) is clear
    io_Device   - pointer to device node, must be set by (or copied from
                  I/O block set by) OpenDevice function
    io_Unit     - bit map of channels to stop (bits 0 thru 3 correspond to
                  channels 0 thru 3)
    io_Command  - command number for CMD_STOP
    io_Flags    - flags, must be cleared if not used:
                  IOF_QUICK - (CLEAR) reply I/O request
    ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                  set by) OpenDevice function or ADCMD_ALLOCATE command

OUTPUTS
    io_Unit     - bit map of channels successfully stopped (bits 0 thru 3
                  correspond to channels 0 thru 3)
    io_Error    - error number:
                  0                    - no error
                  ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                         does not match key for channel


audio.device/CMD_UPDATE

NAME
    CMD_UPDATE -- force dirty buffers out

FUNCTION
    CMD_UPDATE is a standard command for multiple audio channels.  For
    each selected channel (io_Unit), if the allocation key (ioa_AllocKey)
    is correct, CMD_UPDATE does nothing; otherwise, CMD_UPDATE returns an
    error (ADIOERR_NOALLOCATION).  CMD_UPDATE is synchronous and only
    replies (mn_ReplyPort) if the quick flag (IOF_QUICK) is clear.

INPUTS
    mn_ReplyPort- pointer to message port that receives I/O request after
                  if the quick flag (IOF_QUICK) is clear
    io_Device   - pointer to device node, must be set by (or copied from
                  I/O block set by) OpenDevice function
    io_Unit     - bit map of channels to update (bits 0 thru 3 correspond
                  to channels 0 thru 3)
    io_Command  - command number for CMD_UPDATE
    io_Flags    - flags, must be cleared if not used:
                  IOF_QUICK - (CLEAR) reply I/O request
    ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                  set by) OpenDevice function or ADCMD_ALLOCATE command

OUTPUTS
    io_Unit     - bit map of channels successfully updated (bits 0 thru 3
                  correspond to channels 0 thru 3)
    io_Error    - error number:
                  0                    - no error
                  ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                         does not match key for channel


audio.device/CMD_WRITE

NAME
    CMD_WRITE -- normal I/O entry point

FUNCTION
    CMD_WRITE is a standard command for a single audio channel (io_Unit).
    If the allocation key (ioa_AllocKey) is correct, CMD_WRITE plays a
    sound using the selected channel; otherwise, it returns an error
    (ADIOERR_NOALLOCATION).  CMD_WRITE queues up requests if there is
    another write in progress or if the channel is stopped (CMD_STOP).
    When the write actually starts; if the ADIOF_PERVOL flag is set,
    CMD_WRITE loads volume (ioa_Volume) and period (ioa_Period), and if
    the ADIOF_WRITEMESSAGE flag is set, CMD_WRITE replies the write
    message (ioa_WriteMsg).  CMD_WRITE returns an error (IOERR_ABORTED) if
    it is canceled (AbortIO) or the channel is stolen (ADCMD_ALLOCATE).
    CMD_WRITE is only asynchronous if there is no error, in which case it
    clears the quick flag (IOF_QUICK) and replies the I/O request
    (mn_ReplyPort) after it finishes writting; otherwise, it is synchronou
s
    and only replies if the quick flag (IOF_QUICK) is clear.  Do not use
    CMD_WRITE in interrupt code at interrupt level 5 or higher.

INPUTS
    mn_ReplyPort- pointer to message port that receives I/O request after
                  the write completes
    io_Device   - pointer to device node, must be set by (or copied from
                  I/O block set by) OpenDevice function
    io_Unit     - bit map of channel to write (bit 0 thru 3 corresponds to
                  channel 0 thru 3), if more then one bit is set lowest
                  bit number channel is written
    io_Command  - command number for CMD_WRITE
    io_Flags    - flags, must be cleared if not used:
                  ADIOF_PERVOL       - (SET) load volume and period
                  ADIOF_WRITEMESSAGE - (SET) reply message at write start
    ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                  set by) OpenDevice function or ADCMD_ALLOCATE command
    ioa_Data    - pointer to waveform array (signed bytes (-128 thru 127)
                  in custom chip addressable ram and word aligned)
    ioa_Length  - length of the wave array in bytes (2 thru 131072, must
                  be even number)
    ioa_Period  - sample period in 279.365 ns increments (124 thru 65536,
                  anti-aliasing filter works below 300 to 500 depending on
                  waveform), if enabled by ADIOF_PERVOL
    ioa_Volume  - volume (0 thru 64, linear), if enabled by ADIOF_PERVOL
    ioa_Cycles  - number of times to repeat array (0 thru 65535, 0 for
                  infinite)
    ioa_WriteMsg- message replied at start of write,  if enabled by
                  ADIOF_WRITEMESSAGE

OUTPUTS
    io_Unit     - bit map of channel successfully written (bit 0 thru 3
                  corresponds to channel 0 thru 3)
    io_Flags    - IOF_QUICK flag cleared if there is no error
    io_Error    - error number:
                  0                    - no error
                  IOERR_ABORTED        - canceled (AbortIO) or channel
                                         stolen
                  ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                         does not match key for channel

BUGS
    If CMD_WRITE starts the write immediately after stopping a previous
    write, you must set the ADIOF_PERVOL flag or else the new data pointer
    (ioa_Data) and length (ioa_Length) may not be loaded.


audio.device/Expunge

NAME
    EXPUNGE - indicate a desire to remove the Audio device

FUNCTION
    The Expunge routine is called when a user issues a RemDevice call.  By
    the time it is called, the device has already been removed from the
    device list, so no new opens will succeed.  The existence of any other
    users of the device, as determined by the device open count being
    non-zero, will cause the Expunge to be deferred.  When the device is
    not in use, or no longer in use, the Expunge is actually performed.


audio.device/OpenDevice

NAME
    OpenDevice - open the audio device

SYNOPSIS
    error = OpenDevice("audio.device", unitNumber, iORequest, flags);

FUNCTION
    The OpenDevice routine grants access to the audio device.  It takes an
    I/O audio request block (iORequest) and if it can successfully open
    the audio device, it loads the device pointer (io_Device) and the
    allocation key (ioa_AllocKey); otherwise, it returns an error
    (IOERR_OPENFAIL).  OpenDevice increments the open count keeping the
    device from being expunged (Expunge).  If the length (ioa_Length) is
    non-zero, OpenDevice tries to allocate (ADCMD_ALLOCATE) audio channels
    from a array of channel combination options (ioa_Data). If the
    allocation succeeds, the allocated channel combination is loaded into
    the unit field (ioa_Unit); otherwise, OpenDevice returns an error
    (ADIOERR_ALLOCFAILED).  OpenDevice does not wait for allocation to
    succeed and closes (CloseDevice) the audio device if it fails.  To
    allocate channels, OpenDevice also requires a properly initialized
    reply port (mn_ReplyPort) with an allocated signal bit.

INPUTS
    unitNumber- not used
    iORequest - pointer to audio request block (struct IOAudio)
            ln_Pri      - allocation precedence (-128 thru 127), only
                          necessary for allocation (non-zero length)
            mn_ReplyPort- pointer to message port for allocation, only
                          necessary for allocation (non-zero length)
            ioa_AllocKey- allocation key; zero to generate new key.
                          Otherwise, it must be set by (or copied from I/O
                          block that is set by) previous OpenDevice
                          function or ADCMD_ALLOCATE command (non-zero
                          length)
            ioa_Data    - pointer to channel combination options (byte
                          array, bits 0 thru 3 correspond to channels 0
                          thru 3), only necessary for allocation (non-zero
                          length)
            ioa_Length  - length of the channel combination option array
                          (0 thru 16), zero for no allocation
    flags     - not used

OUTPUTS
    iORequest - pointer to audio request block (struct IOAudio)
            io_Device   - pointer to device node if OpenDevice succeeds,
                          otherwise -1
            io_Unit     - bit map of successfully allocated channels (bits
                          0 thru 3 correspond to channels 0 thru 3)
            io_Error    - error number:
                          0                   - no error
                          IOERR_OPENFAIL      - open failed
                          ADIOERR_ALLOCFAILED - allocation failed, no open
            ioa_AllocKey- allocation key, set to a unique number if passed
                          a zero and OpenDevice succeeds
    error     - copy of io_Error


gameport.doc

 GPD_ASKCTYPE        GPD_READEVENT      GPD_SETTRIGGER
 GPD_ASKTRIGGER      GPD_SETCTYPE


gameport.device/GPD_ASKCTYPE

NAME
    GPD_ASKCTYPE -- Acquire the current game port controller type

FUNCTION
    This command identifies the type of controller at the game
    port, so that the signals at the port may be properly
    interpreted.  The controller type has been set by a previous
    SetCType.

    This command always executes immediately.

IO REQUEST
    io_Message      mn_ReplyPort set if quick I/O is not possible
    io_Device       preset by the call to OpenDevice
    io_Unit         preset by the call to OpenDevice
    io_Command      GPD_ASKCTYPE
    io_Flags        IOB_QUICK set if quick I/O is possible
    io_Length       at least 1
    io_Data         the address of the byte variable for the
                    result


gameport.device/GPD_ASKTRIGGER

NAME
    GPD_ASKTRIGGER -- Inquire the conditions for a game port report

FUNCTION
    This command inquires what conditions must be met by a game
    port unit before a pending Read request will be satisfied.
    These conditions, called triggers, are independent -- that
    any one occurs is sufficient to queue a game port report to
    the Read queue.  These conditions are set by SetTrigger.

    This command always executes immediately.

IO REQUEST
    io_Message      mn_ReplyPort set if quick I/O is not possible
    io_Device       preset by the call to OpenDevice
    io_Unit         preset by the call to OpenDevice
    io_Command      GPD_ASKTRIGGER
    io_Flags        IOB_QUICK set if quick I/O is possible
    io_Length       sizeof(gamePortTrigger)
    io_Data         a structure of type GamePortTrigger, which
                    has the following elements
        gpt_Keys -
                GPTB_DOWNKEYS set if button down transitions
                trigger a report, and GPTB_UPKEYS set if button up
                transitions trigger a report
        gpt_Timeout -
                a time which, if exceeded, triggers a report;
                measured in vertical blank units (60/sec)
        gpt_XDelta  -
                a distance in x which, if exceeded, triggers a
                report
        gpt_YDelta  -
                a distance in x which, if exceeded, triggers a
                report


gameport.device/GPD_READEVENT

NAME
    GPD_READEVENT -- Return the next game port event.

FUNCTION
    Read game port events from the game port and put them in the
    data area of the iORequest.  If there are no pending game port
    events, this command will not be satisfied, but if there are
    some events, but not as many as can fill IO_LENGTH, the
    request will be satisfied with those currently available.

IO REQUEST
    io_Message      mn_ReplyPort set if quick I/O is not possible
    io_Device       preset by the call to OpenDevice
    io_Unit         preset by the call to OpenDevice
    io_Command      GPD_READEVENT
    io_Flags        IOB_QUICK set if quick I/O is possible
    io_Length       the size of the io_Data area in bytes: there
                    are sizeof(inputEvent) bytes per input event.
    io_Data         a buffer area to fill with input events.  The
                    fields of the input event are:
        ie_NextEvent
                    links the events returned
        ie_Class
                    is IECLASS_RAWMOUSE
        ie_SubClass
                    is 0 for the left, 1 for the right game port
        ie_Code
                    contains any gameport button reports.  No
                    report is indicated by the value 0xff.
        ie_Qualifier
                    only the relative and button bits are set
        ie_X, ie_Y
                    the x and y values for this report, in either
                    relative or absolute device dependent units.
        ie_TimeStamp
                    the delta time since the last report, given
                    not as a standard timestamp, but as the frame
                    count in the TV_SECS field.

RESULTS
    This function sets the error field in the iORequest, and fills
    the iORequest with the next game port events (but not partial
    events).

SEE ALSO
    gameport.device/SetCType, gameport.device/SetTrigger


gameport.device/GPD_SETCTYPE

NAME
    GPD_SETCTYPE -- Set the current game port controller type

FUNCTION
    This command sets the type of device at the game port, so that
    the signals at the port may be properly interpreted.  The port
    can also be turned off, so that no reports are generated.

    This command always executes immediately.

IO REQUEST
    io_Message      mn_ReplyPort set if quick I/O is not possible
    io_Device       preset by the call to OpenDevice
    io_Unit         preset by the call to OpenDevice
    io_Command      GPD_SETCTYPE
    io_Flags        IOB_QUICK set if quick I/O is possible
    io_Length       1
    io_Data         the address of the byte variable describing
                    the controller type, as per the equates in
                    the gameport include file


gameport.device/GPD_SETTRIGGER

NAME
    GPD_SETTRIGGER -- Set the conditions for a game port report

FUNCTION
    This command sets what conditions must be met by a game
    port unit before a pending Read request will be satisfied.
    These conditions, called triggers, are independent -- that
    any one occurs is sufficient to queue a game port report to
    the Read queue.  These conditions are inquired with
    AskTrigger.

    This command always executes immediately.

IO REQUEST
    io_Message      mn_ReplyPort set if quick I/O is not possible
    io_Device       preset by the call to OpenDevice
    io_Unit         preset by the call to OpenDevice
    io_Command      GPD_SETTRIGGER
    io_Flags        IOB_QUICK set if quick I/O is possible
    io_Length       sizeof(gamePortTrigger)
    io_Data         a structure of type GamePortTrigger, which
                    has the following elements
        gpt_Keys -
                GPTB_DOWNKEYS set if button down transitions
                trigger a report, and GPTB_UPKEYS set if button up
                transitions trigger a report
        gpt_Timeout -
                a time which, if exceeded, triggers a report;
                measured in vertical blank units (60/sec)
        gpt_XDelta  -
                a distance in x which, if exceeded, triggers a
                report
        gpt_YDelta  -
                a distance in x which, if exceeded, triggers a
                report


narrator.doc

 AbortIO()         CMD_READ       CMD_STOP
 OpenDevice()      CMD_RESET      CMD_WRITE
 CMD_FLUSH         CMD_START      CloseDevice()


narrator.device/AbortIO

NAME
    AbortIO - Abort an IO request

SYNOPSIS
    AbortIO(IORequest)
               A1

FUNCTION
    Exec library call to abort a specified READ or WRITE request.
    The IORequest may be in the queue or currently active.  If
    currently active, the request is immediately stopped and then
    removed.

INPUTS
    Pointer to the IORequest block to be aborted.

RESULTS
    io_Error field in the IORequest block set to #IOERR_ABORTED.

SEE ALSO


narrator.device/CloseDevice

NAME
    CloseDevice - terminates access to the narrator device

SYNOPSIS
    CloseDevice(IORequest)
                   A1

FUNCTION
    Close invalidates the IO_UNIT and IO_DEVICE fields in the
    IORequest block, preventing subsequent IO until another
    OpenDevice.  CloseDevice also reduces the open count.  If
    the count goes to 0 and the expunge bit is set, the device
    is expunged.  If the open count goes to zero and the delayed
    expunge bit is not set, CloseDevice sets the expunge bit.

INPUTS
    A valid IORequest block with its io_Message structure, and
    io_Device and io_Unit fields properly initialized.  These
    fields are initialized by OpenDevice.

RESULTS
    CloseDevice invalidates the unit and device pointers in the
    IORequest block.

SEE ALSO


narrator.device/CMD_FLUSH

NAME
    CMD_FLUSH - Aborts all inprogress and queued requests

SYNOPSIS
    Standard device command.

FUNCTION
    Aborts all inprogress and queued speech requests.

INPUTS
    Valid IORequest block with the io_Command field set to CMD_FLUSH.
    A valid IORequest block is one with its io_Message structure, and
    io_Device and io_Unit fields properly initialized.  The easiest
    way to insure proper initialization is to make a copy of the
    IORequest block after a successful OpenDevice call.

RESULTS
    io_Error in IORequest block set to 0

SEE ALSO
    Exec input/output documentation.


narrator.device/CMD_Read

NAME
    CMD_READ - Query the narrator device for mouth shape or other
               synchronization events.

SYNOPSIS
    Standard device command.

FUNCTION
    Currently, there are three events which the user can inquire
    about from the narrator device.  These are: mouth shape changes,
    start of word, and start of syllable.  Each read request returns
    information about any or all of these events as determined by
    the bits set in the sync field of the read IORequest block.  In
    the case of mouth shape changes, each shape returned is guaranteed
    to be different from the previously returned shape to allow
    updating to be done only when necessary.  Each read request is
    associated with a write request by information contained in the
    IORequest block used to open the device.  Since the first field
    in the read IORequest block is a write IORequest structure, this
    association is easily made by copying the write IORequest block
    (after the OpenDevice call) into the voice field of the read
    IORequest block.  If there is no write in progress or in the
    device input queue with the same pseudo unit number as the read
    request, the read will be returned to the user with an error.  This
    is also how the user knows that the write request has finished and
    that s/he should not issue any more reads.  Note that in this case
    the mouth shapes may not be different from previously returned values.

INPUTS
    mouth_rb IORequest block with the voice field (a narrator_rb
    structure) copied from the associated write request with the
    following fields modified:

       io_Message - Pointer to message port for read request
       io_Command - CMD_READ
       io_Error   - Clear before issuing first read
       width      - 0
       height     - 0

RESULTS
    As long as the speech is in progress, each read returns the
    following information in the mouth_rb IORequest block.

    If mouth shape changes are requested the following fields are
    modified:
       width  - Contains mouth width value in arbitrary units
       height - Contains mouth height value in arbitrary units
       shape  - Compressed form of mouth shapes (internal use only)

    ******  NEW FOR V37 NARRATOR

    If word synchronization is requested:
       sync   - Bit NDB_WORDSYNC is set

    If syllable synchronization is requested:
       sync   - Bit NDB_SYLSYNC is set

    Note that any or all of the above fields can be set and it is
    the user's responsibility to check for all possibilities.

SEE ALSO
    CMD_WRITE
    Exec input/output documentation.


narrator.device/CMD_RESET

NAME
    CMD_RESET - Reset the device to a known state

SYNOPSIS
    Standard device command.

FUNCTION
    Resets the device as though it has just be initialized.
    Aborts all read/write requests whether active of enqueued.
    Restarts device if it has been stopped.

INPUTS
    Valid IORequest block with the io_Command field set to CMD_RESET.
    A valid IORequest block is one with its io_Message structure, and
    io_Device and io_Unit fields properly initialized.  The easiest
    way to insure proper initialization is to make a copy of the
    IORequest block after a successful OpenDevice call.

RESULTS

SEE ALSO
    Exec input/output documentation.


narrator.device/CMD_START

NAME
    CMD_START - Restarts the device after a CMD_STOP command

SYNOPSIS
    Standard device command.

FUNCTION
    CMD_START restarts the currently active speech (if any) and
    allows queued requests to start.

INPUTS
    Valid IORequest block with the io_Command field set to CMD_START
    A valid IORequest block is one with its io_Message structure, and
    io_Device and io_Unit fields properly initialized.  The easiest
    way to insure proper initialization is to make a copy of the
    IORequest block after a successful OpenDevice call.

RESULTS
    io_Error set to 0.

SEE ALSO
    Exec input/output documentation.


narrator.device/CMD_STOP

NAME
    CMD_STOP  - Stops the device.

SYNOPSIS
    Standard device command.

FUNCTION
    CMD_STOP halts the currently active speech (if any) and prevents
    any queued requests from starting.

INPUTS
    Valid IORequest block with the io_Command field set to CMD_STOP.
    A valid IORequest block is one with its io_Message structure, and
    io_Device and io_Unit fields properly initialized.  The easiest
    way to insure proper initialization is to make a copy of the
    IORequest block after a successful OpenDevice call.

RESULTS
    io_Error set to 0.

SEE ALSO
    Exec input/output documentation.


narrator.device/CMD_WRITE

NAME
    CMD_WRITE - Send speech request to the narrator device

SYNOPSIS
    Standard device command.

FUNCTION
    Sends a phonetic string to the narrator device to be spoken
    and, optionally, is used to direct the narrator device to
    return mouth shape changes, and word and syllable sync events
    in response to read requests from the user.  The phonetic string
    consists of ASCII characters representing the individual phonemes.
    Refer to the narrator device chapter of the libraries and devices
    volume of the ROM Kernel Manual for detailed information.

INPUTS
    User IORequest block (struct narrator_rb as defined in .h file).
    The OpenDevice call will initialize the IORequest block to a
    "standard male" voice.  If you want to change any parms, do so
    after the OpenDevice call and before the DoIO (or SendIO/WaitIO).
    For a complete description of the narrator_rb structure, see the
    narrator.h or .i include file.  Note that the OpenDevice call does
    not initialize all the fields needed by the narrator device.  The
    IORequest fields which must be set by the user before issuing the
    write request are:

       io_Command - Set to CMD_WRITE
       io_Data    - Pointer to phonetic string
       io_Length  - Length of phonetic string
       ch_masks   - Array of audio channel selection masks (see audio
                    device documentation for description of this field)
       nm_masks   - Number of audio channel selection masks

       ****** NEW FOR V37 NARRATOR

       flags - The bit NDB_NEWIORB must be set in the flags field if
               any of the new features of the V37 narrator are used

    In addition to producing synthetic speech, the narrator device
    also provides features for synchronizing the speech to animation
    or other user defined events.  There are three types of events
    that the user can request.  They are mouth shape changes, start of
    new word, and start of new syllable.  Mouth shape changes are
    requested by setting the mouths field of the IORequest block to a
    non-zero value.  Word and syllable sync events are requested by
    setting the NDB_WORDSYNC and/or NDB_SYLSYNC bits in the flags field
    of the IORequest block.  Note that word and syllable sync only work
    in V37 and later versions of the narrator device.

RESULTS
    The narrator device range checks and performs other validity
    checks for all input parms.  If any input is in error, the device
    sets the io_Error field of the IORequest block to an appropriate
    value (see include files for error codes).  If everything is in
    order, the narrator device will produce the speech and clear the
    io_Error field.  The io_Actual field is set to the length of the
    input string that was actually processed.  If the return code
    indicates a phoneme error (ND_PhonErr), io_Actual is the NEGATIVE
    of the position in the input string where the error occured.

SEE ALSO
    Read command.
    Audio device documentation.
    Exec input/output documentation.


narrator.device/OpenDevice

NAME
    OpenDevice - opens the narrator device.

SYNOPSIS
    error = OpenDevice("narrator.device",  unit, IORequest, flags);
     D0                       A0            D0     A1         D1

FUNCTION
    The OpenDevice routine grants access to the narrator device.
    OpenDevice checks the unit number, and if non-zero, returns an
    error (ND_UnitErr).  If this is the first time the driver has
    been opened, OpenDevice will attempt to open the audio device
    and allocate the driver's static buffers.  If either of these
    operations fail, an error is returned.  See the .h and .i
    include files for possible error return codes.  Next, OpenDevice
    (done for all opens, not just the first one) initializes various
    fields in the user's IORequest block (see below).  If users wish
    to use non-default values for these parms, the values must be set
    after the open is done.  OpenDevice also assigns a pseudo unit
    number to the IORB for use in synchronizing read and write requests.
    See the read command for more details.  Finally, OpenDevice stores
    the device node pointer in the IORequest block and clears the
    delayed expunge bit.

    ***** NEW FOR V37 NARRATOR *****

    Several new fields in the IORequest block have been added for V37
    narrator.  These fields are initialized when the device is opened
    if the NDB_NEWIORB bit is set in the flags field of the user's
    IORequest block.  Note that NDB_NEWIORB is set in the IORequest
    block, NOT in the "flags" input parm to the OpenDevice call.

INPUTS
    device     - "narrator.device"
    unit       - 0
    IORequest  - Pointer to the user's IORequest block
    flags      - 0

RESULTS
    The narrator device will initialize the IORequest block as follows
    (assume IORB points to the IOrequest block):

    IORB->rate = 150;               /* Speaking rate in words/minute */
    IORB->pitch = 110;              /* Baseline pitch in Hertz      */
    IORB->mode = NATURALF0;         /* Pitch (F0) mode              */
    IORB->sex = MALE;               /* Sex of voice                 */
    IORB->volume = 64               /* Volume, full on              */
    IORB->sampfreq = 22200          /* Audio sampling freq          */
    IORB->mouths = 0                /* Don't generate sync events   */

    and if the NDB_NEWIORB bit is set:

    IORB->F0enthusiasm = 0          /* F0 excursion factor          */
    IORB->F0perturb = 32            /* F0 perturbation (in 32nds)   */
    IORB->F1adj = 0                 /* F1 adjustment in ±5% steps   */
    IORB->F2adj = 0                 /* F2 adjustment in ±5% steps   */
    IORB->F3adj = 0                 /* F3 adjustment in ±5% steps   */
    IORB->A1adj = 0                 /* A1 adjustment in decibels    */
    IORB->A2adj = 0                 /* A2 adjustment in decibels    */
    IORB->A3adj = 0                 /* A3 adjustment in decibels    */
    IORB->articulate = 100          /* Transition time multiplier   */
    IORB->centralize = 0            /* Degree of vowel centralization */
    IORB->centphon = ""             /* Pointer to central ASCII phon  */
    IORB->AVbias = 0                /* AV bias                      */
    IORB->AFbias = 0                /* AF bias                      */
    IORB->priority = 100            /* Priority while speaking      */

SEE ALSO
    The include files contain the complete IORequest block definition,
        default settings, and error return codes.
    Exec input/output documentation.


serial.doc

 AbortIO()          CMD_FLUSH      CMD_STOP          SDCMD_QUERY
 BeginIO()          CMD_READ       CMD_WRITE         SDCMD_SETPARAMS
 CloseDevice()      CMD_RESET      OpenDevice()
 CMD_CLEAR          CMD_START      SDCMD_BREAK


serial.device/AbortIO

NAME
    AbortIO(ioRequest) -- abort an I/O request
            A1

FUNCTION
    This is an exec.library call.

    This function attempts to aborts a specified read or write request.
    If the request is active, it is stopped immediately. If the request is
    queued, it is painlessly removed.  The request will be returned
    in the same way any completed request it.

    After AbortIO(), you must generally do a WaitIO().

INPUTS
    iORequest  -- pointer to the IORequest Block that is to be aborted.

RESULTS
    io_Error -- if the Abort succeded, then io_Error will be #IOERR_ABORTED
                (-2) and the request will be flagged as aborted (bit 5 of
                io_Flags is set).  If the Abort failed, then the Error will
                be zero.

BUGS
    Previous to version 34, the serial.device would often hang when
    aborting CTS/RTS handshake requests.  This was the cause of the
    incorrect assumption that AbortIO() does not need to be followed
    by a wait for a reply (or a WaitIO()).


serial.device/BeginIO

NAME
    BeginIO(ioRequest),deviceNode -- start up an I/O process
             A1        A6
FUNCTION
    This is a direct function call to the device.  It is intended for
    more advanced programmers.  See exec's DoIO() and SendIO() for
    the normal method of calling devices.

    This function initiates a I/O request made to the serial
    device. Other than read or write, the functions are performed
    synchronously, and do not depend on any interrupt handling
    logic (or it's associated discontinuities), and hence should
    be performed as IO_QUICK.
    With some exceptions, reads and writes are merely initiated by
    BeginIO, and thusly return to the caller as begun, not completed.
    Completion is signalled via the standard ReplyMsg routine.
    Multiple requests are handled via FIFO queueing.
    One exception to this non-QUICK handling of reads and writes
    is for READS when:
      - IO_QUICK bit is set
      - There are no pending read requests
      - There is already enough data in the input buffer to satisfy
        this I/O Request immediately.
    In this case, the IO_QUICK flag is not cleared, and the request
    is completed by the time it returns to the caller. There is no
    ReplyMsg or signal bit activity in this case.

INPUTS
    ioRequest  -- pointer to an I/O Request Block of size
                  io_ExtSerSize (see serial.i for size/definition),
                  containing a valid command in io_Command to process,
                  as well as the command's other required parameters.
    deviceNode -- pointer to the "serial.device", as found in
                  the IO_DEVICE of the ioRequest.

RESULTS
    io_Error   -- if the BeginIO succeded, then Error will be null.
                  If the BeginIO failed, then the Error will be non-zero.
                  I/O errors won't be reported until the io completes.

SEE ALSO
     devices/serial.h


serial.device/CloseDevice

NAME
    CloseDevice -- close the serial port

SYNOPSIS
    CloseDevice(deviceNode)
                 A1
FUNCTION
    This is an exec call that terminates communication with the
    serial device.  Upon closing, the device's input buffer is freed.

    Note that all IORequests MUST be complete before closing.
     If any are pending, your program must AbortIO() then WaitIO()
    to complete them.

INPUTS
    deviceNode - pointer to the device node, set by Open

SEE ALSO
    serial.device/OpenDevice


serial.device/CMD_CLEAR

NAME
    Clear -- clear the serial port buffers

FUNCTION
    This command resets the serial port's read buffer pointers.

IO REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       set by OpenDevice
    io_Unit         set by OpenDevice
    io_Command      CMD_CLEAR

RESULTS
    Error -- If the Clear succeded, then io_Error will be null.
             If the Clear failed, then the io_Error will be non-zero.


serial.device/CMD_FLUSH

NAME
    Flush -- clear all queued I/O requests for the serial port

FUNCTION
    This command purges the read and write request queues for the
    serial device. Flush will not affect active requests.

IO REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       set by OpenDevice
    io_Unit         set by OpenDevice
    io_Command      CMD_FLUSH

RESULTS
    Error -- if the Flush succeded, then io_Error will be null.
             If the Flush failed, then the io_Error will be non-zero.


serial.device/CMD_READ

NAME
    Read -- read input from serial port

FUNCTION
    This command causes a stream of characters to be read in from
    the serial port buffer.  The number of characters is specified
    in io_Length.

    The Query function can be used to check how many characters
    are currently waiting in the serial port buffer.  If more characters
    are requested than are currently available, the ioRequest
    will be queued until it can be satisfied.

    The best way to handle reads is to first Query to get the number
    of characters currently in the buffer.  Then post a read request
    for that number of characters (or the maximum size of your buffer).

    If zero characters are in the buffer, post a request
    for 1 character.  When at least one is ready, the device will return
    it.  Now start over with another Query.

    Before the program exits, it must be sure to AbortIO() then WaitIO()
    any outstanding ioRequests.

IO REQUEST
    io_Message      A mn_ReplyPort is required
    io_Device       set by OpenDevice
    io_Unit         set by OpenDevice
    io_Command      CMD_READ
    io_Flags        If the IOB_QUICK bit is set, read will try
                     to complete the IO quickly
    io_Length       number of characters to receive.
    io_Data         pointer to buffer

RESULTS
    Error -- if the Read succeded, then io_Error will be null.
             If the Read failed, then io_Error will be non-zero.
             io_Error will indicate problems such as parity mismatch,
             break, and buffer overrun.

SEE ALSO
     serial.device/SDCMD_QUERY
     serial.device/SDCMD_SETPARAMS

BUGS
     Having multiple outstanding read IORequests at any one time will
     probably fail.

     Old documentation mentioned a mode where io_Length was set to -1.
     If you want a NULL terminated read, use the io_TermArray instead.


serial.device/CMD_RESET

NAME
    Reset -- reinitializes the serial port

FUNCTION
    This command resets the serial port to its freshly initialized
    condition. It aborts all I/O requests both queued and current,
    relinquishes the current buffer, obtains a new default sized
    buffer, and sets the port's flags and parameters to their
    boot-up time default values. The functions places the reset
    parameter values in the ioRequest block.

IO REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       set by OpenDevice
    io_Unit         set by OpenDevice
    io_Command      CMD_RESET

RESULTS
    Error -- if the Reset succeded, then Error will be null.
             If the Reset failed, then the Error will be non-zero.


serial.device/CMD_START

NAME
    Start -- restart paused I/O over the serial port

FUNCTION
    This function restarts all current I/O on the serial port by
    sending an xON to the "other side", and submitting a "logical
    xON" to "our side", if/when appropriate to current activity.

IO REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       set by OpenDevice
    io_Unit         set by OpenDevice
    io_Command      CMD_START

RESULTS

SEE ALSO
    serial.device/CMD_STOP


serial.device/CMD_STOP

NAME
    Stop -- pause all current I/O over the serial port

FUNCTION
    This command halts all current I/O on the serial port by
    sending an xOFF to the "other side", and submitting a "logical
    xOFF" to "our side", if/when appropriate to current activity.

IO REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       set by OpenDevice
    io_Unit         set by OpenDevice
    io_Command      CMD_STOP

RESULTS

SEE ALSO
    serial.device/CMD_START


serial.device/CMD_WRITE

NAME
    Write -- send output to serial port

FUNCTION
    This command causes a stream of characters to be written out
    the serial port. The number of characters is specified in
    io_Length, unless -1 is used, in which case output is sent until
    a null(0x00) is encountered.

IO REQUEST
    io_Message      must have mn_ReplyPort initialized
    io_Device       set by OpenDevice
    io_Unit         set by OpenDevice
    io_Command      CMD_WRITE
    io_Flags        Set IOF_QUICK to try quick I/O
    io_Length       number of characters to transmit, or if set
                    to -1 transmit until null encountered in buffer
    io_Data         pointer to block of data to transmit

RESULTS
    Error -- if the Write succeded, then io_Error will be null.
        If the Write failed, then the io_Error will be non-zero.

SEE ALSO
    serial.device/SDCMD_SETPARAMS


serial.device/OpenDevice

NAME
    OpenDevice -- Request an opening of the serial device.

SYNOPSIS
    error = OpenDevice("serial.device", unit, ioRequest, flags)
    D0                  A0              D0    A1         D1

      BYTE OpenDevice(STRPTR, ULONG, struct IOExtSer *, ULONG);

FUNCTION
    This is an exec call.  Exec will search for the serial.device, and
    if found, will pass this call on to the device.

    Unless the shared-access bit (bit 5 of io_SerFlags) is set,
    exclusive use is granted and no other access to that unit is
    allowed until the owner closes it.  All the serial-specific fields
    in the ioRequest are initialized to their most recent values (or
    the Preferences default, for the first time open).

    If support of 7-wire handshaking (i.e. RS232-C CTS/RTS protocol)
    is required, use the serial.device/SDCMD_SETPARAMS command.
     This feature should also be specified at inital OpenDevice() time.

INPUTS
    "serial.device" - pointer to literal string "serial.device"
     unit           - Must be zero, or a user setable unit number.
                      (This field is used by multiple port controllers)
                      Zero specifies the default serial port.
    ioRequest       - pointer to an ioRequest block of size io_ExtSerSize
                      to be initialized by the serial.device.
                      (see devices/serial.h for the definition)
                      NOTE: use of io_SerFlags (see FUNCTION above)
                      IMPORTANT: The ioRequest block MUST be of size
                      io_ExtSerSize, and zeroed (with the exeptions as
                      noted)!
    flags           - Must be zero for future compatibility

RESULTS
    D0              - same as io_Error
    io_Error        - If the Open succeded, then io_Error will be null.
                      If the Open failed, then io_Error will be non-zero.
    io_Device       - A pointer to whatever device will handle the calls
                      for this unit.  This pointer may be different
                      depending on what unit is requested.

BUGS
    If 7-wire handshaking is specified, a timeout "feature" is enabled.
    If the device holds off the computer for more than about 30-60
    seconds, the device will return the write request with the error
    SerErr_TimerErr.  Don't depend on this, however.  If you want a
    timeout, set up the timer.device and wait for either timer, or serial
    IO to complete.

    On open, the serial.device allocates the misc.resource for the
    serial port.  It does not return it until the serial.device is
    expunged from memory.  It should return it when no more openers
    exist.   This code can force a specified device to try and
    expunge.  Of course, if the device is in use nothing will happen:

      #include "exec/types.h"
      #include "exec/execbase.h"
      #include "proto/exec.h"

      void FlushDevice(char *);
      extern struct ExecBase *SysBase;

      void main()
      {
              FlushDevice("serial.device");   /* or parallel.device */
      }

      /*
       * Attempts to flush the named device out of memory.
       * If it fails, no status is returned; examination of
       * the problem will reveal that information has no
       * valid use after the Permit().
       */
      void FlushDevice(name)
      char  *name;
      {
      struct Device *result;

          Forbid();
          if( result=(struct Device *)FindName(&SysBase->DeviceList,name) )
              RemDevice(result);
          Permit();
      }

SEE ALSO
    serial.device/CloseDevice
    serial.device/SDCMD_SETPARAMS
    devices/serial.h


serial.device/SDCMD_BREAK

NAME
    Break -- send a break signal over the serial line

FUNCTION
    This command sends a break signal (serial line held low for an
    extended period) out the serial port. For the built-in port,
    This is accomplished by setting the UARTBRK bit of regisrer ADKCON.

    After a duration (user specifiable via setparams, default 250000
    microseconds) the bit is reset and the signal discontinued.
    If the QUEUEDBRK bit of io_SerFlags is set in the io_Request
    block, the request is placed at the back of the write-request
    queue and executed in turn. If the QUEUEDBRK bit is not set,
    the break is started immediately, control returns to the
    caller, and the timer discontinues the signal after the
    duration is completed. Be aware that calling BREAK may
     affect other commands such as ABORT, FLUSH, STOP, START, etc...

IO REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       set by OpenDevice
    io_Unit         set by OpenDevice
    io_Command      SDCMD_BREAK
    io_Flags        set/reset IO_QUICK per above description

RESULTS
    Error -- if the Break succeded, then Error will be null.
        If the Break failed, then the Error will be non-zero.


serial.device/SDCMD_QUERY

NAME
    Query -- query serial port/line status

FUNCTION
    This command return the status of the serial port lines and
    registers. The number of unread bytes in the serial device's
    read buffer is shown in io_Actual.

    The break send & received flags are cleared by a query, and
    whenever a read IORequest is returned with a error
    in io_Error.

IO REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       preset by OpenDevice
    io_Unit         preset by OpenDevice
    io_Command      SDCMD_QUERY

RESULTS
    io_Status        BIT  ACTIVE  FUNCTION

           LSB       0    ---    reserved
                     1    ---    reserved
                     2    high   parallel "sel" on the A1000
                                 On the A500 & A2000, "sel" is also
                                 connected to the serial port's
                                 "Ring Indicator".  Be cautious when
                                 making cables.
                     3    low    Data Set Ready
                     4    low    Clear To Send
                     5    low    Carrier Detect
                     6    low    Ready To Send
                     7    low    Data Terminal Ready
           MSB       8    high   hardware overrun
                     9    high   break sent (most recent output)
                    10    high   break received (as latest input)
                    11    high   transmit x-OFFed
                    12    high   receive x-OFFed
                 13-15    ---    reserved

    io_Actual       set to count of unread input characters

    io_Error -- Query will always succeded.


serial.device/SDCMD_SETPARAMS

NAME
    SetParams -- change parameters for the serial port

FUNCTION
    This command allows the caller to change parameters for the
    serial device. Except for xON-xOFF enable/disable, it will
    reject a setparams call if any reads or writes are active
    or pending.
       Note specifically:

    1. Valid input for io_Baud is between 112 and 292000 baud inclusive;
       asynchronous i/o above 32KB (especially on a busy system) may
       be ambitious.
    2. The EOFMODE and QUEUEDBRK bits of io_SerFlags can be set/reset
       in the io_Rqst block without a call to SetParams. The SHARED
       and 7WIRE bits of io_SerFlags can be used in OpenDevice calls.
       ALL OTHER PARAMETERS CAN ONLY BE CHANGED BY THE SetParams
       COMMAND.
    3. RBufLen must be at least 64.  The buffer may be any multiple of
        64 bytes.
    4. If not used, io_ExtFlags MUST be set to zero.
    5. xON-xOFF is by default enabled. The XDISABLED bit is the only
       parameter that can be changed via a SetParams call while the
       device is active. Note that this will return the value
       SerErr_DevBusy in the io_Error field.

        xON/xOFF handshaking is inappropriate for certain binary transfer
        protocalls, such as Xmodem.  The binary data might contain the
        xON (ASCII 17) and xOFF (ASCII 19) characters.

    6. If trying to run MIDI, you should set the RAD_BOOGIE bit of
       io_SerFlags to eliminate unneeded overhead. Specifically, this skips
       checks for parity, x-OFF handling, character lengths other than
       8 bits, and testing for a break signal. Setting RAD_BOOGIE will
       also set the XDISABLED bit.
       Note that writing data (that's already in MIDI format) at MIDI rates
       is easily accomplished. Using this driver alone for MIDI reads may,
       however, may not be reliable, due to MIDI timestamping requirements,
       and possibility of overruns in a busy multitasking and/or display
       intensive environment.
    7. If you select mark or space parity (see io_ExtFlags in serial.h),
       this will cause the SERB_PARTY_ON bit to be set, and the setting
       of SERB_PARTY_ODD to be ignored.
    8. For best results, set the RAD_BOOGIE flag whenever possible.  See
        #6 for details.
    9. Note that at this time parity is *not* calculated for the xON-xOFF
        characters.  If you have a system that is picky about the parity of
        these, you must set your own xON-xOFF characters in io_CtlChar.
   10. 7WIRE (CTS/RTS) handshake is bi-directional.  The external side
        is expected to drop CTS several character times before the external
        buffer is full.  The Amiga will drop RTS several character times
        before the Amiga's buffer is full.

IO REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       preset by OpenDevice
    io_Unit         preset by OpenDevice
    io_Command      SDCMD_SETPARAMS (0x0B)
                     NOTE that the following fields are filled in by Open
                    to reflect the serial device's current configuration.
    io_CtlChar      a longword containing byte values for the
                    xON,xOFF,INQ,ACK fields (respectively)
                    (INQ/ACK not used at this time)
    io_RBufLen      length in bytes of input buffer
                     NOTE that any change in buffer size causes the
                    current buffer to be deallocated and a new,
                    correctly sized one to be allocated. Thusly,
                    the CONTENTS OF THE OLD BUFFER ARE LOST.
    io_ExtFlags     additional serial flags (bitdefs in devices/serial.h)
                     mark & space parity may be specified here.
    io_Baud         baud rate for reads AND writes. (See 1 above)
    io_BrkTime      duration of break signal in MICROseconds
    io_TermArray    ASCII descending-ordered 8-byte array of
                    termination characters. If less than 8 chars
                    used, fill out array w/lowest valid value.
                    Terminators are checked only if EOFMODE bit of
                    io_Serflags is set. (e.g. x512F040303030303 )
    io_ReadLen      number of bits in read word (1-8) not including parity
    io_WriteLen     number of bits in write word (1-8) "      "       "
    io_StopBits     number of stop bits (0, 1 or 2)
    io_SerFlags     see devices/serial.h for bit equates, NOTE that x00
                    yields exclusive access, xON/OFF-enabled, no
                    parity checking, 3-wire protocol and TermArray
                    inactive.

RESULTS
    Error -- if the SetParams succeded, then Error will be null.
        If the SetParams failed, then the Error will be non-zero.

SEE ALSO
    exec/OpenDevice


clipboard.doc

 CBD_CHANGEHOOK          CBD_POST        CMD_WRITE
 CBD_CURRENTREADID       CMD_READ
 CBD_CURRENTWRITEID      CMD_UPDATE


clipboard.device/CBD_CHANGEHOOK

NAME
    CBD_CHANGEHOOK -- Add or remove a clip change hook

FUNCTION
    CBD_CHANGEHOOK allows specification of a hook to be called
    when the data on the clipboard has changed.

IO REQUEST
    io_Message      mn_ReplyPort set up
    io_Device       preset by OpenDevice
    io_Unit         preset by OpenDevice
    io_Command      CBD_CHANGEHOOK
    io_Length -     0 to remove, 1 to install this hook
    io_Data -       struct Hook *, the clip change hook

HOOK ENVIRONMENT
   hook message - a ClipHookMsg, as defined in devices/clipboard.h
       chm_Type - 0, indicating that the message has the
           following fields:
       chm_ClipID - the clip ID of the clip triggering the change
   hook object - io_Unit


clipboard.device/CBD_CURRENTREADID

NAME
    CBD_CURRENTREADID - Determine the current read identifier.

FUNCTION
    CBD_CURRENTREADID fills the io_ClipID with a clip identifier that
    can be compared with that of a post command: if greater than
    the post identifier then the post data held privately by an
    application is not valid for its own pasting.

IO REQUEST
    io_Message      mn_ReplyPort set up
    io_Device       preset by OpenDevice
    io_Unit         preset by OpenDevice
    io_Command      CBD_CURRENTREADID

RESULTS
    io_ClipID       the ClipID of the current write is set


clipboard.device/CBD_CURRENTWRITEID

NAME
    CBD_CURRENTWRITEID -- Determine the current write identifier.

FUNCTION
    CBD_CURRENTWRITEID fills the io_ClipID with a clip identifier that
    can be compared with that of a post command: if greater than
    the post identifier then the post is obsolete and need never
    be satisfied.

IO REQUEST
    io_Message      mn_ReplyPort set up
    io_Device       preset by OpenDevice
    io_Unit         preset by OpenDevice
    io_Command      CBD_CURRENTWRITEID

RESULTS
    io_ClipID       the ClipID of the current write is set


clipboard.device/CBD_POST

NAME
    CBD_POST -- Post availability of a clip to the clipboard.

FUNCTION
    Indicate to the clipboard device that data is available for
    use by accessors of the clipboard.  This is intended to be
    used when a cut is large, in a private data format, and/or
    changing frequently, and it thus makes sense to avoid
    converting it to an IFF form and writing it to the clipboard
    unless another application wants it.  The post provides a
    message port to which the clipboard device will send a satisfy
    message if the data is required.

    If the satisfy message is received, the write associated with
    the post must be performed.  The act of writing the clip
    indicates that the message has been received: it may then be
    re-used by the clipboard device, and so must actually be
    removed from the satisfy message port so that the port is not
    corrupted.

    If the application wishes to determine if a post it has
    performed is still the current clip, it should check the
    post's io_ClipID with that returned by the CBD_CURRENTREADID
    command.  If the current read io_ClipID is greater, the clip
    is not still current.

    If an application has a pending post and wishes to determine
    if it should satisfy it (e.g. before it exits), it should
    check the post's io_ClipID with that returned by the
    CBD_CURRENTWRITEID command.  If the current write io_ClipID is
    greater, there is no need to satisfy the post.

IO REQUEST
    io_Message      mn_ReplyPort set up
    io_Device       preset by OpenDevice
    io_Unit         preset by OpenDevice
    io_Command      CBD_POST
    io_Data         pointer to satisfy message port
    io_ClipID       zero

RESULTS
    io_Error        non-zero if an error occurred
    io_ClipID       the clip ID assigned to this post, to be used
                    in the write command if this is satisfied


clipboard.device/CMD_READ

NAME
    CMD_READ -- Read from a clip on the clipboard.

FUNCTION
    The read function serves two purposes.

    When io_Offset is within the clip, this acts as a normal read
    request, and io_Data is filled with data from the clipboard.
    The first read request should have a zero io_ClipID, which
    will be filled with the ID assigned for this read.  Normal
    sequential access from the beginning of the clip is achieved
    by setting io_Offset to zero for the first read, then leaving
    it untouched for subsequent reads.  If io_Data is null, then
    io_Offset is incremented by io_Actual as if io_Length bytes
    had been read: this is useful to skip to the end of file
    by using a huge io_Length.

    When io_Offset is beyond the end of the clip, this acts as a
    signal to the clipboard device that the application is
    through reading this clip.  Realize that while an application
    is in the middle of reading a clip, any attempts to write new
    data to the clipboard are held off.  This read past the end
    of file indicates that those operations may now be initiated.

IO REQUEST
    io_Message      mn_ReplyPort set up
    io_Device       preset by OpenDevice
    io_Unit         preset by OpenDevice
    io_Command      CMD_READ
    io_Length       number of bytes to put in data buffer
    io_Data         pointer to buffer of data to fill, or null to
                    skip over data
    io_Offset       byte offset of data to read
    io_ClipID       zero if this is the initial read

RESULTS
    io_Error        non-zero if an error occurred
    io_Actual       filled with the actual number of bytes read
    io_Data         (the buffer now has io_Actual bytes of data)
    io_Offset       updated to next read position, which is
                    beyond EOF if io_Actual != io_Length
    io_ClipID       the clip ID assigned to this read: do not
                    alter for subsequent reads


clipboard.device/CMD_UPDATE

NAME
    CMD_UPDATE -- Terminate the writing of a clip to the clipboard.

FUNCTION
    Indicate to the clipboard that the previous write commands are
    complete and can be used for any pending pastes (reads).  This
    command cannot be issued while any of the write commands are
    pending.

IO REQUEST
    io_Message      mn_ReplyPort set up
    io_Device       preset by OpenDevice
    io_Unit         preset by OpenDevice
    io_Command      CMD_UPDATE
    io_ClipID       the ClipID of the write

RESULTS
    io_Error        non-zero if an error occurred


clipboard.device/CMD_WRITE

NAME
    CMD_WRITE -- Write to a clip on the clipboard.

FUNCTION
    This command writes data to the clipboard.  This data can be
    provided sequentially by clearing io_Offset for the initial
    write, and using the incremented value unaltered for
    subsequent writes.  If io_Offset is ever beyond the current
    clip size, the clip is padded with zeros.

    If this write is in response to a SatisfyMsg for a pending
    post, then the io_ClipID returned by the CBD_POST command must
    be used.  Otherwise, a new ID is obtained by clearing the
    io_ClipID for the first write.  Subsequent writes must not
    alter the io_ClipID.

IO REQUEST
    io_Message      mn_ReplyPort set up
    io_Device       preset by OpenDevice
    io_Unit         preset by OpenDevice
    io_Command      CMD_WRITE
    io_Length       number of bytes from io_Data to write
    io_Data         pointer to block of data to write
    io_Offset       usually zero if this is the initial write
    io_ClipID       zero if this is the initial write, ClipID of
                    the Post if this is to satisfy a post

RESULTS
    io_Error        non-zero if an error occurred
    io_Actual       filled with the actual number of bytes written
    io_Offset       updated to next write position
    io_ClipID       the clip ID assigned to this write: do not
                    alter for subsequent writes


input.doc

 IND_ADDHANDLER      IND_SETMTRIG       IND_SETTHRESH
 IND_REMHANDLER      IND_SETMTYPE       IND_WRITEEVENT
 IND_SETMPORT        IND_SETPERIOD      PeekQualifier()


input.device/IND_ADDHANDLER

NAME
    IND_ADDHANDLER -- Add an input handler to the device

FUNCTION
    Add a function to the list of functions called to handle
    input events generated by this device.  The function is called
    as
        newInputEvents = Handler(inputEvents, handlerData);
        D0                       A0           A1

IO REQUEST
    io_Message      mn_ReplyPort set
    io_Device       preset by OpenDevice
    io_Unit         preset by OpenDevice
    io_Command      IND_ADDHANDLER
    io_Data         a pointer to an interrupt structure.
        is_Data     the handlerData pointer described above
        is_Code     the Handler function address

NOTES
    The interrupt structure is kept by the input device until a
    RemHandler command is satisfied for it.


input.device/IND_REMHANDLER

NAME
    IND_REMHANDLER -- Remove an input handler from the device

FUNCTION
    Remove a function previously added to the list of handler
    functions.

IO REQUEST
    io_Message      mn_ReplyPort set
    io_Device       preset by OpenDevice
    io_Unit         preset by OpenDevice
    io_Command      IND_REMHANDLER
    io_Data         a pointer to the interrupt structure.

NOTES
    This command is not immediate


input.device/IND_SETMPORT

NAME
    IND_SETMPORT -- Set the current mouse port

FUNCTION
    This command sets the gameport port at which the mouse is
    connected.

IO REQUEST
    io_Message      mn_ReplyPort set if quick I/O is not possible
    io_Device       preset by the call to OpenDevice
    io_Unit         preset by the call to OpenDevice
    io_Command      IND_SETMPORT
    io_Flags        IOB_QUICK set if quick I/O is possible
    io_Length       1
    io_Data         a pointer to a byte that is either 0 or 1,
                    indicating that mouse input should be obtained
                    from either the left or right controller port,
                    respectively.


input.device/IND_SETMTRIG

NAME
    IND_SETMTRIG -- Set the conditions for a mouse port report

FUNCTION
    This command sets what conditions must be met by a mouse
    before a pending Read request will be satisfied.  The trigger
    specification is that used by the gameport device.

IO REQUEST
    io_Message      mn_ReplyPort set if quick I/O is not possible
    io_Device       preset by the call to OpenDevice
    io_Unit         preset by the call to OpenDevice
    io_Command      IND_SETMTRIG
    io_Flags        IOB_QUICK set if quick I/O is possible
    io_Length       sizeof(gameportTrigger)
    io_Data         a structure of type GameportTrigger, which
                    has the following elements
        gpt_Keys -
                GPTB_DOWNKEYS set if button down transitions
                trigger a report, and GPTB_UPKEYS set if button up
                transitions trigger a report
        gpt_Timeout -
                a time which, if exceeded, triggers a report;
                measured in vertical blank units (60/sec)
        gpt_XDelta  -
                a distance in x which, if exceeded, triggers a
                report
        gpt_YDelta  -
                a distance in x which, if exceeded, triggers a
                report


input.device/IND_SETMTYPE

NAME
    IND_SETMTYPE -- Set the current mouse port controller type

FUNCTION
    This command sets the type of device at the mouse port, so
    the signals at the port may be properly interpreted.

IO REQUEST
    io_Message      mn_ReplyPort set if quick I/O is not possible
    io_Device       preset by the call to OpenDevice
    io_Unit         preset by the call to OpenDevice
    io_Command      IND_SETMTYPE
    io_Flags        IOB_QUICK set if quick I/O is possible
    io_Length       1
    io_Data         the address of the byte variable describing
                    the controller type, as per the equates in
                    the gameport include file


input.device/IND_SETPERIOD

NAME
    IND_SETPERIOD -- Set the key repeat period

FUNCTION
    This command sets the period at which a repeating key repeats.

    This command always executes immediately.

IO REQUEST - a timerequest
    tr_node.io_Message      mn_ReplyPort set if quick I/O is not possible
    tr_node.io_Device       preset by the call to OpenDevice
    tr_node.io_Unit         preset by the call to OpenDevice
    tr_node.io_Command      IND_SETPERIOD
    tr_node.io_Flags        IOB_QUICK set if quick I/O is possible
    tr_time.tv_secs         the repeat period seconds
    tr_time.tv_micro        the repeat period microseconds


input.device/IND_SETTHRESH

NAME
    IND_SETTHRESH -- Set the key repeat threshold

FUNCTION
    This command sets the time that a key must be held down before
    it can repeat.  The repeatability of a key may be restricted
    (as, for example, are the shift keys).

    This command always executes immediately.

IO REQUEST - a timerequest
    tr_node.io_Message      mn_ReplyPort set if quick I/O is not possible
    tr_node.io_Device       preset by the call to OpenDevice
    tr_node.io_Unit         preset by the call to OpenDevice
    tr_node.io_Command      IND_SETTHRESH
    tr_node.io_Flags        IOB_QUICK set if quick I/O is possible
    tr_time.tv_secs         the threshold seconds
    tr_time.tv_micro        the threshold microseconds


input.device/IND_WRITEEVENT

NAME
    IND_WRITEEVENT -- Propagate an input event to all handlers

FUNCTION

IO REQUEST
    io_Message      mn_ReplyPort set if quick I/O is not possible
    io_Device       preset by the call to OpenDevice
    io_Unit         preset by the call to OpenDevice
    io_Command      IND_WRITEEVENT
    io_Flags        IOB_QUICK set if quick I/O is possible
    io_Length       should be sizeof(struct InputEvent)
    io_Data         a pointer to the struct InputEvent:
        ie_NextEvent
                    will be ignored.
        ie_Class
        ie_SubClass
        ie_Code
        ie_Qualifier
        ie_X, ie_Y
                    as desired
        ie_TimeStamp
                    will be set by this call (V36)

NOTES
    The contents of the input event are destroyed.

    This function was documented in V34 and earlier to allow
    chaining of events via ie_NextEvent.  The implementation
    never allowed that.  The documentation now reflects this.

    ie_TimeStamp is set only in V36 and later.  Software written
    to run on earlier versions should set this field to the
    current time.


input.device/PeekQualifier

NAME
    PeekQualifier -- get the input device's current qualifiers (V36)

SYNOPSIS
    qualifier = PeekQualifier()
    d0

    UWORD PeekQualifier( VOID );

FUNCTION
    This function takes a snapshot of what the input device thinks
    the current qualifiers are.

RESULTS
    qualifier - a word with the following bits set according to
        what the input device knows their state to be:
            IEQUALIFIER_LSHIFT, IEQUALIFIER_RSHIFT,
            IEQUALIFIER_CAPSLOCK, IEQUALIFIER_CONTROL,
            IEQUALIFIER_LALT, IEQUALIFIER_RALT,
            IEQUALIFIER_LCOMMAND, IEQUALIFIER_RCOMMAND,
            IEQUALIFIER_LEFTBUTTON, IEQUALIFIER_RBUTTON,
            IEQUALIFIER_MIDBUTTON

NOTE
    This function is new for V36.

SEE ALSO
    devices/inputevent.h


parallel.doc

 CMD_CLEAR      CMD_RESET      CMD_WRITE         PDCMD_SETPARAMS
 CMD_FLUSH      CMD_START      OpenDevice()
 CMD_READ       CMD_STOP       PDCMD_QUERY


parallel.device/CMD_CLEAR

NAME
    Clear -- clear the parallel port buffer

FUNCTION
    This command just RTS's (no buffer to clear)

IO REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       set by OpenDevice
    io_Unit         set by OpenDevice
    io_Command      CMD_CLEAR (05)


parallel.device/CMD_FLUSH

NAME
    Flush -- clear all queued I/O requests for the parallel port

FUNCTION
    This command purges the read and write request queues for the
    parallel device. The currently active request is not purged.

IO REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       set by OpenDevice
    io_Unit         set by OpenDevice
    io_Command      CMD_FLUSH (08)


parallel.device/CMD_READ

NAME
    Read -- read input from parallel port

FUNCTION
    This command causes a stream of characters to be read from the
    parallel I/O register. The number of characters is specified in
    io_Length. The EOF and EOL modes are supported, but be warned that
    using these modes can result in a buffer overflow if the proper
    EOL or EOF character is not received in time. These modes should
    be used only when the sender and receiver have been designed to
    cooperate. A safety guard can be implemented to EOF by setting
    io_Length to a maximum allowed value. That cannot be done with EOL
    since the EOL mode is identified by io_Length=-1.

    The parallel.device has no internal buffer; if no read request has
    been made, pending input (i.e. handshake request) is not
    acknowledged.

IO REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       set by OpenDevice
    io_Unit         set by OpenDevice
    io_Command      CMD_READ (02)
    io_Flags        If IOF_QUICK is set, driver will attempt Quick IO
    io_Length       number of characters to receive.
    io_Data         pointer where to put the data.

RESULTS
    io_Error -- if the Read succeded, then io_Error will be null.
        If the Read failed, then io_Error will contain an error code.

SEE ALSO
    parallel.device/PDCMD_SETPARAMS


parallel.device/CMD_RESET

NAME
    Reset -- reinitializes the parallel device

FUNCTION
    This command resets the parallel device to its freshly initialized
    condition. It aborts all I/O requests both queued and current and
    sets the devices's flags and parameters to their boot-up time
    default values. At boot-up time the PTermArray is random, and it
    will be so also here.

IO REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       set by OpenDevice
    io_Unit         set by OpenDevice
    io_Command      CMD_RESET (01)

RESULTS
    Error -- if the Reset succeded, then io_Error will be null.
             if the Reset failed, then the io_Error will be non-zero.


parallel.device/CMD_START

NAME
    Start -- restart paused I/O over the parallel port

FUNCTION
    This command restarts the current I/O activity on the parallel
    port by reactivating the handshaking sequence.

IO REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       set by OpenDevice
    io_Unit         set by OpenDevice
    io_Command      CMD_START (07)

SEE ALSO
    parallel.device/CMD_STOP


parallel.device/CMD_STOP

NAME
    Stop -- pause current activity on the parallel device

FUNCTION
    This command halts the current I/O activity on the parallel
    device by discontinuing the handshaking sequence. The stop and
    start commands may not be nested.

IO REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       set by OpenDevice
    io_Unit         set by OpenDevice
    io_Command      CMD_STOP (06)

SEE ALSO
    parallel.device/CMD_START


parallel.device/CMD_WRITE

NAME
    Write -- send output to parallel port

FUNCTION
    This command causes a stream of characters to be written to the
    parallel output register. The number of characters is specified in
    io_Length, unless -1 is used, in which case output is sent until
    a zero byte occurs in the data. This is independent of, and may be
    used simultaneously with setting the EOFMODE in io_ParFlags and using
    the PTermArray to terminate the read or write.

IO REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       set by OpenDevice
    io_Unit         set by OpenDevice
    io_Command      CMD_WRITE (03)
    io_Flags        If IOF_QUICK is set, driver will attempt Quick IO
    io_Length       number of characters to transmit, or if set
                    to -1 send until zero byte encountered
    io_Data         pointer to block of data to transmit

RESULTS
    io_Error -- If the Write succeded, then io_Error will be null.
         If the Write failed, then io_Error will contain an error code.

SEE ALSO
    parallel.device/PDCMD_SETPARAMS


parallel.device/OpenDevice

NAME
    Open -- a request to open the parallel port

SYNOPSIS
    error = OpenDevice("parallel.device", unit, ioExtPar, flags)
    D0                  A0                D0    A1        D1

FUNCTION
    This function allows the requestor software access to the parallel
    device.  Unless the shared-access bit (bit 5 of io_ParFlags) is
    set, exclusive use is granted and no other access is allowed
    until the owner closes the device.

    A FAST_MODE, can be specified (bit 3 of io_Parflags) to speed up
    transfers to high-speed printers. Rather than waiting for the printer
    to acknowledge a character using the *ACK interrupt, this mode will
    send out data as long as the BUSY signal is low. The printer must be
    able to raise the BUSY signal within 3 micro-seconds on A2630s,
    otherwise data will be lost. Should be used only in an exclusive-
    access OpenDevice().

    A SLOWMODE mode can be specified (bit 4 of io_ParFlags) when very
    slow printers are used. If the printer acknowledges data at less
    than 5000 bytes per second, then this mode will actually save CPU
    time, although it consumes much more with high-speed printers.

    The PTermArray of the ioExtPar is initialized only if the EOFMODE
    bit (bit 1 of io_ParFlags) is set. The PTermArray can be further
    modified using the PDCMD_SETPARAMS command.

INPUTS
    "parallel.device" - a pointer to literal string "parallel.device"
    unit - Must be zero for future compatibility
    ioExtPar - pointer to an IO Request block of structure IOExtPar to
               be initialized by the OpenDevice() function. The io_ParFlags
               field must be set as desired.
    flags - Must be zero for future compatibility

RESULTS
    d0 -- same as io_Error
    io_Error -- if the Open succeded, then io_Error will be null.
                If the Open failed, then io_Error will be non-zero.

SEE ALSO
    exec/CloseDevice


parallel.device/PDCMD_QUERY

NAME
    Query -- query parallel port/line status

FUNCTION
    This command return the status of the parallel port lines and
    registers.

IO REQUEST
    io_Message      must have mn_ReplyPort initialized
    io_Device       set by OpenDevice
    io_Unit         set by OpenDevice
    io_Command      PDCMD_QUERY (09)

RESULTS
    io_Status        BIT  ACTIVE  FUNCTION

                     0     high   printer busy toggle (offline)
                     1     high   paper out
                     2     high   printer selected on the A1000
                                  printer selected & serial "Ring
                                  Indicator" on the A500/A2000
                                  Use care when making cables.
                     3      -     read=0,write=1
                   4-7            reserved

BUGS
    In a earlier version of this AutoDoc, BUSY and PSEL were reversed.
    The function has always been correct.


parallel.device/PDCMD_SETPARAMS

NAME
    SetParams -- change parameters for the parallel device

FUNCTION
    This command allows the caller to change the EOFMODE parameter for
    the parallel port device. It will disallow changes if any reads or
    writes are active or queued.

    The PARB_EOFMODE bit of io_ParFlags controlls whether the
    io_PTermArray is to be used as an additional termination criteria
    for reads and writes.  It may be set directly without a call to
    SetParams, setting it here performs the additional service of
    copying the PTermArray into the device default array which is used
    as the initial array for subsequent device opens. The Shared bit
    can be changed here, and overrides the current device access mode
    set at OpenDevice time.

IO REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       preset by OpenDevice
    io_Unit         preset by OpenDevice
    io_Command      PDCMD_SETPARAMS (0A)
                    NOTE that the following fields of your IORequest
                    are filled by Open to reflect the parallel device's
                    current configuration.
    io_PExtFlags    must be set to zero, unless used
    io_ParFlags     see definition in parallel.i or parallel.h
                    NOTE that x00 yields exclusive access, PTermArray
                    inactive.
    io_PTermArray   ASCII descending-ordered 8-byte array of
                    termination characters. If less than 8 chars
                    used, fill out array w/lowest valid value.
                    Terminators are used only if EOFMODE bit of
                    io_Parflags is set. (e.g. x512F040303030303 )
                    This field is filled on OpenDevice only if the
                    EOFMODE bit is set.

RESULTS
    io_Error -- if the SetParams succeded, then io_Error will be null.
                if the SetParams failed, then io_Error will be non-zero.


timer.doc

 --background--      CmpTime()         SubTime()          TR_SETSYSTIME
 AbortIO()           GetSysTime()      TR_ADDREQUEST
 AddTime()           ReadEClock()      TR_GETSYSTIME


timer.device/--background--

TIMER REQUEST
    A time request is a non standard IO Request.  It has an IORequest
    followed by a timeval structure or an eclockval structure.

TIMEVAL
    A timeval structure consists of two longwords.  The first is
    the number of seconds, the latter is the fractional number
    of microseconds.  The microseconds must always be "normalized"
    e.g. the longword must be between 0 and one million.

ECLOCKVAL
    A eclockval structure consists of two longwords.  The first is
    the high order 32 bits of a 64 bit number and the second is the
    the low order 32 bits.  The 64 bit number is a count of "E" clock
    ticks.  The "E" clock frequency is related to the master clock
    frequency of the machine and can be determined by calling the
    ReadEClock() library like call.

UNITS
    The timer contains five units -- two designed to accuratly measure
    short intervals, one that has little system overhead and is very
    stable over time, and two that work like an alarm clock.

UNIT_MICROHZ
    This unit uses the programmable timers in the 8520s to keep track
    of its time.  It has precision down to about 2 microseconds, but
    will drift as system load increases.  The accuracy of this unit
    is the same as that of the master clock of the machine.  This unit
    uses a timeval in its timerequest.

UNIT_VBLANK
    This unit uses a strobe from the power supply to keep track of its
    time or the "E" clock on machines without power supply strobes.
    It is very stable over time, but only has a resolution of that of
    the vertical blank interrupt.  This unit is very cheap to use, and
    should be used by those who are waiting for long periods of time
    (typically 1/2 second or more).  This unit uses a timeval in its
    timerequest.

UNIT_ECLOCK
    This unit is exacly the same as UNIT_MICROHZ except that it uses
    an eclockval instead of a timeval in its timerequest.

UNIT_WAITUNTIL
    This unit waits until the systime is greater than or equal to the
    time in the timeval in the timerequest.  This unit has the same
    resolution and accuracy as that of UNIT_VBLANK.

UNIT_WAITECLOCK
    This unit waits until the E-Clock value as returned by ReadEClock()
    is greater than or equal to the eclockval in the timerequest. This
    unit has the same resolution and accuracy as that of UNIT_ECLOCK.

LIBRARY
    In addition to the normal device calls, the timer also supports
    several direct, library like calls.

BUGS
    In the V1.2/V1.3 release, the timer device has problems with
    very short time requests.  When one of these is made, other
    timer requests may be finished inaccurately.  A side effect
    is that AmigaDOS requests such as "Delay(0);" or
    "WaitForChar(x,0);" are unreliable.


timer.device/AbortIO

NAME
    AbortIO -- Remove an existing timer request.

SYNOPSIS
    error = AbortIO( timerequest )
    D0               A1

    LONG AbortIO( struct timerequest * );

FUNCTION
    This is an exec.library call.

    This routine removes a timerquest from the timer.  It runs in
    the context of the caller.

INPUTS
    timerequest - the timer request to be aborted

RETURNS
    0  if the request was aborted, io_Error will also be set to
        IOERR_ABORTED.
    -1 otherwise

NOTES
    This function may be called from interrupts.

SEE ALSO
    exec.library/AbortIO()

BUGS


timer.device/AddTime

NAME
    AddTime -- Add one time request to another.

SYNOPSIS
    AddTime( Dest, Source )
             A0    A1

    void AddTime( struct timeval *, struct timeval *);

FUNCTION
    This routine adds one timeval structure to another.  The
    results are stored in the destination (Dest + Source -> Dest)

    A0 and A1 will be left unchanged

INPUTS
    Dest, Source -- pointers to timeval structures.

NOTES
    This function may be called from interrupts.

SEE ALSO
    timer.device/CmpTime(),
    timer.device/SubTime()

BUGS


timer.device/CmpTime

NAME
    CmpTime -- Compare two timeval structures.

SYNOPSIS
    result = CmpTime( Dest, Source )
    D0                A0    A1

    LONG CmpTime( struct timeval *, struct timeval *);

FUNCTION
    This routine compares timeval structures

    A0 and A1 will be left unchanged

INPUTS
    Dest, Source -- pointers to timeval structures.

RESULTS
    result will be   0 if Dest has same time as source
                    -1 if Dest has more time than source
                    +1 if Dest has less time than source

NOTES
    This function may be called from interrupts.

SEE ALSO
    timer.device/AddTime(),
    timer.device/SubTime()

BUGS
    Older version of this document had the sense of the return
    codes wrong; the code hasn't changed but the document has.


timer.device/GetSysTime

NAME
    GetSysTime -- Get the system time. (V36)

SYNOPSIS
    GetSysTime( Dest )
                A0

    void GetSysTime( struct timeval * );

FUNCTION
    Ask the system what time it is.  The system time starts off at
    zero at power on, but may be initialized via the TR_SETSYSTIME
    timer.device command.

    System time is monotonocally increasing and guarenteed to be
    unique (except when the system time is set back).

    A0 will be left unchanged.

    This function is less expensive to use than the TR_GETSYSTIME
    IORequest.

INPUTS
    Dest -- pointer to a timeval structure to hold the system time.

RESULTS
    Dest -- the timeval structure will contain the system time.

NOTES
    This function may be called from interrupts.

SEE ALSO
    timer.device/TR_GETSYSTIME,
    timer.device/TR_SETSYSTIME,

BUGS


timer.device/ReadEClock

NAME
    ReadEClock -- Get the current value of the E-Clock. (V36)

SYNOPSIS
    E_Freq = ReadEClock( Dest )
    D0                   A0

    ULONG ReadEClock ( struct EClockVal * );

FUNCTION
    This routine calculates the current 64 bit value of the E-Clock
    and stores it in the destination EClockVal structure. The count
    rate of the E-Clock is also returned.

    A0 will be left unchanged

    This is a low overhead function designed so that very short
    intervals may be timed.

INPUTS
    Dest -- pointer to an EClockVal structure.

RETURNS
    Dest -- the EClockVal structure will contain the E-Clock time
    E_Freq -- The count rate of the E-Clock (tics/sec).

NOTES
    This function may be called from interrupts.

SEE ALSO

BUGS


timer.device/SubTime

NAME
    SubTime -- Subtract one time request from another.

SYNOPSIS
    SubTime( Dest, Source )
             A0    A1

    void SubTime( struct timeval *, struct timeval *);

FUNCTION
    This routine subtracts one timeval structure from another.  The
    results are stored in the destination (Dest - Source -> Dest)

    A0 and A1 will be left unchanged

INPUTS
    Dest, Source -- pointers to timeval structures.

NOTES
    This function may be called from interrupts.

SEE ALSO
    timer.device/AddTime(),
    timer.device/CmpTime()

BUGS


timer.device/TR_ADDREQUEST

NAME
    TR_ADDREQUEST -- Submit a request to wait a period of time.

FUNCTION
    Ask the timer to wait a specified amount of time before
    replying the timerequest.

    The message may be forced to finish early with an
    AbortIO()/WaitIO() pair.

TIMER REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       preset by timer in OpenDevice
    io_Unit         preset by timer in OpenDevice
    io_Command      TR_ADDREQUEST
    io_Flags        IOF_QUICK permitted (but ignored)
    tr_time         a timeval structure specifying how long the
                        device will wait before replying

RESULTS
    tr_time         will be zeroed

NOTES
    This function may be called from interrupts.

    Previous to 2.0, the tr_time field was documented as containing
    junk when the timerequest was returned.

SEE ALSO
    timer.device/AbortIO(),
    timer.device/TimeDelay(),

BUGS


timer.device/TR_GETSYSTIME

NAME
    TR_GETSYSTIME -- get the system time.

FUNCTION
    Ask the system what time it is.  The system time starts off at
    zero at power on, but may be initialized via the TR_SETSYSTIME
    call.

    System time is monotonically increasing, and guaranteed to be
    unique (except when the system time is set backwards).

TIMER REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       preset by timer in OpenDevice
    io_Unit         preset by timer in OpenDevice
    io_Command      TR_GETSYSTIME
    io_Flags        IOF_QUICK permitted

RESULTS
    tr_time         a timeval structure with the current system
                        time

NOTES
    This function may be called from interrupts.

SEE ALSO
    timer.device/TR_SETSYSTIME,
    timer.device/GetSysTime(),

BUGS


timer.device/TR_SETSYSTIME

NAME
    TR_SETSYSTIME -- Set the system time.

FUNCTION
    Set the system idea of what time it is.  The system starts out
    at time "zero" so it is safe to set it forward to the real
    time.  However, care should be taken when setting the time
    backwards.  System time is generally expected to monotonically
    increasing.

TIMER REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       preset by timer in OpenDevice
    io_Unit         preset by timer in OpenDevice
    io_Command      TR_GETSYSTIME
    io_Flags        IOF_QUICK permitted
    tr_time         a timeval structure with the current system
                        time

RESULTS
    tr_time         will contain junk

NOTES
    This function may be called from interrupts.

SEE ALSO
    timer.device/TR_GETSYSTIME,
    timer.device/GetSysTime(),

BUGS


console.doc

 CD_ASKDEFAULTKEYMAP      CDInputHandler()      OpenDevice()
 CD_ASKKEYMAP             CMD_CLEAR             RawKeyConvert()
 CD_SETDEFAULTKEYMAP      CMD_READ
 CD_SETKEYMAP             CMD_WRITE


console.device/CD_ASKDEFAULTKEYMAP

NAME
    CD_ASKDEFAULTKEYMAP -- get the current default keymap

FUNCTION
    Fill the io_Data buffer with the current console device
    default keymap, which is used to initialize console unit
    keymaps when opened, and by RawKeyConvert with a null
    keyMap parameter.

IO REQUEST
    io_Message      mn_ReplyPort set if quick I/O is not possible
    io_Device       preset by the call to OpenDevice
    io_Unit         preset by the call to OpenDevice
    io_Command      CD_ASKDEFAULTKEYMAP
    io_Flags        IOF_QUICK if quick I/O possible, else zero
    io_Length       sizeof(*keyMap)
    io_Data         struct KeyMap *keyMap
                    pointer to a structure that describes
                    the raw keycode to byte stream conversion.

RESULTS
    This function sets the io_Error field in the IOStdReq, and fills
    the structure pointed to by io_Data with the current device
    default key map.

BUGS

SEE ALSO
    exec/io.h, devices/keymap.h, devices/console.h


console.device/CD_ASKKEYMAP

NAME
    CD_ASKKEYMAP -- Get the current key map structure for this console.

FUNCTION
    Fill the io_Data buffer with the current KeyMap structure in
    use by this console unit.

IO REQUEST INPUT
    io_Message      mn_ReplyPort set if quick I/O is not possible
    io_Device       preset by the call to OpenDevice
    io_Unit         preset by the call to OpenDevice
    io_Command      CD_ASKKEYMAP
    io_Flags        IOF_QUICK if quick I/O possible, else zero
    io_Length       sizeof(*keyMap)
    io_Data         struct KeyMap *keyMap
                    pointer to a structure that describes
                    the raw keycode to byte stream conversion.

IO REQUEST RESULT
    This function sets the io_Error field in the IOStdReq, and fills
    the structure the structure pointed to by io_Data with the current
     key map.

SEE ALSO
    exec/io.h, devices/keymap.h, devices/console.h


console.device/CD_SETDEFAULTKEYMAP

NAME
    CD_SETDEFAULTKEYMAP -- set the current default keymap

FUNCTION
    This console command copies/uses the keyMap structure pointed to
    by io_Data to the console device default keymap, which is used
    to initialize console units when opened, and by RawKeyConvert
    with a null keyMap parameter.

IO REQUEST
    io_Message      mn_ReplyPort set if quick I/O is not possible
    io_Device       preset by the call to OpenDevice
    io_Unit         preset by the call to OpenDevice
    io_Command      CD_SETDEFAULTKEYMAP
    io_Flags        IOF_QUICK if quick I/O possible, else zero
    io_Length       sizeof(*keyMap)
    io_Data         struct KeyMap *keyMap
                    pointer to a structure that describes
                    the raw keycode to byte stream conversion.

RESULTS
    This function sets the io_Error field in the IOStdReq, and fills
    the current device default key map from the structure pointed to
    by io_Data.

BUGS
    As of V36, this command no longer copies the keymap structure,
    and the keymap must remain in memory until the default key map
    is changed.  In general there is no reason for applications to
    use this command.  The default key map will generally be set by
    the user using a system provided command/tool.

SEE ALSO
    exec/io.h, devices/keymap.h, devices/console.h


console.device/CD_SETKEYMAP

NAME
    CD_SETKEYMAP -- set the current key map structure for this console

FUNCTION
    Set the current KeyMap structure used by this console unit to
    the structure pointed to by io_Data.

IO REQUEST
    io_Message      mn_ReplyPort set if quick I/O is not possible
    io_Device       preset by the call to OpenDevice
    io_Unit         preset by the call to OpenDevice
    io_Command      CD_SETKEYMAP
    io_Flags        IOF_QUICK if quick I/O possible, else zero
    io_Length       sizeof(*keyMap)
    io_Data         struct KeyMap *keyMap
                    pointer to a structure that describes
                    the raw keycode to byte stream conversion.

RESULTS
    This function sets the io_Error field in the IOStdReq, and fills
    the current key map from the structure pointed to by io_Data.

BUGS

SEE ALSO
    exec/io.h, devices/keymap.h, devices/console.h


console.device/CDInputHandler

NAME
    CDInputHandler -- handle an input event for the console device

SYNOPSIS
    events = CDInputHandler(events, consoleDevice)
                   a0      a1

FUNCTION
    Accept input events from the producer, which is usually the
    rom input.task.

INPUTS
    events - a pointer to a list of input events.
    consoleDevice - a pointer to the library base address of the
        console device.  This has the same value as ConsoleDevice
        described below.

RESULTS
    events - a pointer to a list of input events not used by this
        handler.

NOTES
    This function is available for historical reasons.  It is
    preferred that input events be fed to the system via the
    WriteEvent command of the input.device.

    This function is different from standard device commands in
    that it is a function in the console device library vectors.
    In order to obtain a valid library base pointer for the
    console device (a.k.a. ConsoleDevice) call
    OpenDevice("console.device", -1, IOStdReq, 0),
    and then grab the io_Device pointer field out of the IOStdReq
    and use as ConsoleDevice.

BUGS

SEE ALSO
    input.device


console.device/CMD_CLEAR

NAME
    CMD_CLEAR -- Clear console input buffer.

FUNCTION
    Remove from the console input buffer any reports waiting to
    satisfy read requests.

IO REQUEST INPUT
    io_Message      mn_ReplyPort set if quick I/O is not possible
    io_Device       preset by the call to OpenDevice
    io_Unit         preset by the call to OpenDevice
    io_Command      CMD_CLEAR
    io_Flags        IOB_QUICK set if quick I/O is possible, else 0

SEE ALSO
    exec/io.h, devices/console.h


console.device/CMD_READ

NAME
    CMD_READ -- return the next input from the keyboard

FUNCTION
    Read the next input, generally from the keyboard.  The form of
    this input is as an ANSI byte stream: i.e. either ASCII text
    or control sequences.  Raw input events received by the
    console device can be selectively filtered via the aSRE and aRRE
    control sequences (see the write command).  Keys are converted
    via the keymap associated with the unit, which is modified
    with AskKeyMap and SetKeyMap

    If, for example, raw keycodes had been enabled by writing
    <CSI>1{ to the console (where <CSI> is $9B or Esc[), keys
    would return raw keycode reports with the information from
    the input event itself, in the form:
    <CSI>1;0;<keycode>;<qualifiers>;0;0;<seconds>;<microseconds>q

    If there is no pending input, this command will not be
    satisfied, but if there is some input, but not as much as can
    fill io_Length, the request will be satisfied with the input
    currently available.

IO REQUEST
    io_Message      mn_ReplyPort set if quick I/O is not possible
    io_Device       preset by the call to OpenDevice
    io_Unit         preset by the call to OpenDevice
    io_Command      CMD_READ
    io_Flags        IOF_QUICK if quick I/O possible, else zero
    io_Length       sizeof(*buffer)
    io_Data         char buffer[]
                    a pointer to the destination for the characters to read
                    from the keyboard.

RESULTS
    This function sets the error field in the IOStdReq, and fills
        in the io_Data area with the next input, and io_Actual with
        the number of bytes read.

BUGS

SEE ALSO
    exec/io.h, devices/console.h


console.device/CMD_WRITE

NAME
    CMD_WRITE -- Write ANSI text to the console display.

FUNCTION
    Write a text record to the display.  Interpret the ANSI
    control characters in the data as described below.  Note
    that the RPort of the console window is in use while this
    write command is pending.

IO REQUEST INPUT
    io_Message      mn_ReplyPort set if quick I/O is not possible
    io_Device       preset by the call to OpenDevice
    io_Unit         preset by the call to OpenDevice
    io_Command      CMD_WRITE
    io_Flags        IOF_QUICK if quick I/O possible, else zero
    io_Length       sizeof(*buffer), or -1 if io_Data is null
                    terminated
    io_Data         a pointer to a buffer containing the ANSI text
                    to write to the console device.

IO REQUEST RESULTS
    io_Error        the error result (no errors are reported as of V36)
    io_Actual       the number of bytes written from io_Data
    io_Length       zero
    io_Data         original io_Data plus io_Actual

ANSI CODES SUPPORTED

    Codes are specified in the standard fashion for ANSI documents,
    as the two 4 bit nibbles that comprise the character code,
    high nibble first, separated by a slash.  Thus 01/11 (ESC) is
    a character with the hex value 1B (or the decimal value 27).

    A character on the Amiga falls into one of the following four
    ranges:
    00/ 0-01/15     C0: ASCII control characters.  See below.
    02/ 0-07/15     G0: ASCII graphic characters.  These characters
                    have an image that is displayed.  Note that the
                    DEL character is displayed by the Console Device:
                    it is not treated as control character here.
    08/ 0-09/15     C1: ANSI 3.41 control characters.  See below.
    10/ 0-15/15     G1: ECMA 94 Latin 1 graphic characters.

    Independent Control Functions (no introducer) --
    Code    Name    Definition
    -----   ---     ----------------------------------------------
    00/ 7   BEL     BELL: actually an Intuition DisplayBeep()
    00/ 8   BS      BACKSPACE
    00/ 9   HT      HORIZONTAL TAB
    00/10   LF      LINE FEED
    00/11   VT      VERTICAL TAB
    00/12   FF      FORM FEED
    00/13   CR      CARRIAGE RETURN
    00/14   SO      SHIFT OUT: causes all subsequent G0 (ASCII)
                    characters to be shifted to G1 (ECMA 94/1)
                    characters.
    00/15   SI      SHIFT IN: cancels the effect of SHIFT OUT.
    01/11   ESC     ESCAPE

    Code or Esc Name Definition
    -----   --- ---- ---------------------------------------------
    08/ 4   D   IND  INDEX: move the active position down one line.
    08/ 5   E   NEL  NEXT LINE
    08/ 8   H   HTS  HORIZONTAL TABULATION SET
    08/13   M   RI   REVERSE INDEX
    09/11   [   CSI  CONTROL SEQUENCE INTRODUCER: see next list

    ISO Compatible Escape Sequences (introduced by Esc) --
    Esc   Name Definition
    ----- ---- ---------------------------------------------------
    c     RIS  RESET TO INITIAL STATE: reset the console display.

    Control Sequences, with the number of indicated parameters.
    i.e. <CSI><parameters><control sequence letter(s)>.  Note the
    last entries consist of a space and a letter.  CSI is either
    9B or Esc[.  A minus after the number of parameters (#p)
    indicates less is valid.  Parameters are separated by
    semicolons, e.g. Esc[14;80H sets the cursor position to row
    14, column 80.
    CSI #p  Name Definition
    --- --- ---- -------------------------------------------------
    @   1-  ICH  INSERT CHARACTER
    A   1-  CUU  CURSOR UP
    B   1-  CUD  CURSOR DOWN
    C   1-  CUF  CURSOR FORWARD
    D   1-  CUB  CURSOR BACKWARD
    E   1-  CNL  CURSOR NEXT LINE
    F   1-  CPL  CURSOR PRECEDING LINE
    H   2-  CUP  CURSOR POSITION
    I   1-  CHT  CURSOR HORIZONTAL TABULATION
    J   1-  ED   ERASE IN DISPLAY (only to end of display)
    K   1-  EL   ERASE IN LINE (only to end of line)
    L   1-  IL   INSERT LINE
    M   1-  DL   DELETE LINE
    P   1-  DCH  DELETE CHARACTER
    R   2   CPR  CURSOR POSITION REPORT (in Read stream only)
    S   1-  SU   SCROLL UP
    T   1-  SD   SCROLL DOWN
    W   n   CTC  CURSOR TABULATION CONTROL
    Z   1-  CBT  CURSOR BACKWARD TABULATION
    f   2-  HVP  HORIZONTAL AND VERTICAL POSITION
    g   1-  TBC  TABULATION CLEAR
    h   n   SM   SET MODE: see modes below.
    l   n   RM   RESET MODE: see modes below.
    m   n   SGR  SELECT GRAPHIC RENDITION
    n   1-  DSR  DEVICE STATUS REPORT
    t   1-  aSLPP SET PAGE LENGTH (private Amiga sequence)
    u   1-  aSLL SET LINE LENGTH (private Amiga sequence)
    x   1-  aSLO SET LEFT OFFSET (private Amiga sequence)
    y   1-  aSTO SET TOP OFFSET (private Amiga sequence)
    {   n   aSRE SET RAW EVENTS (private Amiga sequence)
    |   8   aIER INPUT EVENT REPORT (private Amiga Read sequence)
    }   n   aRRE RESET RAW EVENTS (private Amiga sequence)
    ~   1   aSKR SPECIAL KEY REPORT (private Amiga Read sequence)
     p  1-  aSCR SET CURSOR RENDITION (private Amiga sequence)
     q  0   aWSR WINDOW STATUS REQUEST (private Amiga sequence)
     r  4   aWBR WINDOW BOUNDS REPORT (private Amiga Read sequence)
     v  1   aRAV RIGHT AMIGA V PRESS (private Amiga Read sequence-V37)

    Modes, set with <CSI><mode-list>h, and cleared with
    <CSI><mode-list>l, where the mode-list is one or more of the
    following parameters, separated by semicolons --
    Mode    Name Definition
    ------- ---- -------------------------------------------------
    20      LNM  LINEFEED NEWLINE MODE: if a linefeed is a newline
    >1      ASM  AUTO SCROLL MODE: if scroll at bottom of window
    ?7      AWM  AUTO WRAP MODE: if wrap at right edge of window

NOTES
    The console.device recognizes these SGR sequences.
    Note that some of these are new to V36.

    SGR (SELECT GRAPHICS RENDITION)
            Selects colors, and other display characteristics
            for text.

    Syntax:
            <ESC>[graphic-rendition...m

    Example:
            <ESC>[1;7m   (sets bold, and reversed text)

    Parameters:

            0       - Normal colors, and attributes
            1       - Set bold
            2       - Set faint (secondary color)
            3       - Set italic
            4       - Set underscore
            7       - Set reversed character/cell colors
            8       - Set concealed mode.
            22      - Set normal color, not bold    (V36)
            23      - Italic off                    (V36)
            24      - Underscore off                (V36)
            27      - Reversed off                  (V36)
            28      - Concealed off                 (V36)

            30-37   - Set character color
            39      - Reset to default character color

            40-47   - Set character cell color
            49      - Reset to default character cell color

            >0-7    - Set background color          (V36)
                      Used to set the background color before
                      any text is written.  The numeric parameter
                      is prefixed by ">".  This also means that if
                      you issue an SGR command with more than one
                      parameter, you must issue the digit only
                      parameters first, followed by any prefixed
                      parameters.

BUGS
    Does not correctly display cursor in SuperBitMap layers for
    versions prior to V36.

SEE ALSO
    ROM Kernal Manual (Volume 1), exec/io.h


console.device/OpenDevice

NAME
    OpenDevice -- a request to open a Console device

SYNOPSIS
    error = OpenDevice("console.device", unit, IOStdReq, flags )
    d0                  a0               d0    a1        d1

FUNCTION
    The open routine grants access to a device.  There are two
    fields in the IOStdReq block that will be filled in: the
    io_Device field and possibly the io_Unit field.

    As of (V37) the flags field may also be filled in with
    a value described below (see conunit.h or conunit.i).

    This open command differs from most other device open commands
    in that it requires some information to be supplied in the
    io_Data field of the IOStdReq block.  This initialization
    information supplies the window that is used by the console
    device for output.

    The unit number that is a standard parameter for an open call
    is used specially by this device.  See conunit.h, or conunit.i
    for defined valid unit numbers.

    unit number: -1 (CONU_LIBRARY)

            Used to get a pointer to the device library vector
    which is returned in the io_Device field of the IOStdReq
    block.  No actual console is opened.  You must still close
    the device when you are done with it.

    unit number: 0 (CONU_STANDARD)

            A unit number of zero binds the supplied window to
    a unique console.  Sharing a console must be done at a level
    higher than the device.

    unit number: 1 (CONU_CHARMAP) (V36)

            A unit number of one is similar to a unit number of
    zero, but a console map is also created, and maintained by
    the console.device.  The character map is used by the console
    device to restore obscured portions of windows which are
    revealed, and to redraw a window after a resize.  Character
    mapped console.device windows must be opened as SIMPLE REFRESH
    windows.

            The character map is currently for internal use
    only, and is not accessible by the programmer.  The character
    map stores characters, attributes, and style information for
    each character written with the CMD_WRITE command.

    unit number: 3 (CONU_SNIPMAP) (V36)

            A unit number of three is similar to a unit number
    of one, but also gives the user the ability to highlight
    text with the mouse which can be copied by pressing
    RIGHT AMIGA C.  See NOTES below.

    flags: 0 (CONFLAG_DEFAULT)

            The flags field should be set to 0 under V34, or less.

    flags: 1 (CONFLAG_NODRAW_ON_NEWSIZE) (V37)

            The flags field can be set to 0, or 1 as of V37.  The
    flags field is ignored under V36, so can be set, though it
    will have no effect.  When set to 1, it means that you don't
    want the console.device to redraw the window when the window
    size is changed (assuming you have opened the console.device
    with a character map - unit numbers 1, or 3).  This flag is
    ignored if you have opened a console.device with a unit
    number of 0.  Typically you would use this flag when you
    want to perform your own window refresh on a newsize, and
    you want the benefits of a character mapped console.

IO REQUEST
    io_Data         struct Window *window
                    This is the window that will be used for this
                    console.  It must be supplied if the unit in
                    the OpenDevice call is 0 (see above).  The
                    RPort of this window is potentially in use by
                    the console whenever there is an outstanding
                    write command.
INPUTS
    "console.device" - a pointer to the name of the device to be opened.
    unit - the unit number to open on that device.
    IOStdReq - a pointer to a standard request block
    0 - a flag field of zero (CONFLAG_DEFAULT)
    1 - a flag field of one  (CONFLAG_NODRAW_ON_NEWSIZE) (V37)

RESULTS
    error - zero if successful, else an error is returned.

NOTES
    As noted above, opening the console.device with a unit number of 3
    allows the user to drag select text, and copy the selection with
    RIGHT AMIGA C.  The snip is copied to a private buffered managed
    by the console.device (as of V36).  The snip can be copied to
    any console.device window unless you are running a console to
    clipboard utility such as that provided with V37.

    The user pastes text into console.device windows by pressing
    RIGHT AMIGA V.  Both RIGHT AMIGA V, and RIGHT AMIGA C are swallowed
    by the console.device (unless you have asked for key presses as
    RAW INPUT EVENTS).  Text pasted in this way appears in the
    console read stream as if the user had typed all of the characters
    manually.  Additional input (e.g., user input, RAW INPUT EVENTS)
    are queued up after pastes.  Pastes can theoretically be quite
    large, though they are no larger than the amount of text
    which is visible in a console.device window.

    When running the console to clipboard utility, text snips
    are copied to the clipboard.device, and RIGHT AMIGA V key
    presses are broadcast as an escape sequence as part of the
    console.device read stream ("<CSI>0 v" - $9B,$30,$20,$76).

    It is left up to the application to decide what to do when this
    escape sequence is received.  Ideally the application
    will read the contents of the clipboard, and paste the text
    by using successive writes to the console.device.

    Because the contents of the clipboard.device can be quite
    large, your program should limit the size of writes to something
    reasonable (e.g., no more than 1K characters per CMD_WRITE, and
    ideally no more than 256 characters per write).  Your program
    should continue to read events from the console.device looking
    for user input, and possibly RAW INPUT EVENTS.  How you decide
    to deal with these events is left up to the application.

    If you are using a character mapped console you should receive
    Intuition events as RAW INPUT EVENTS from the console.device.
    By doing this you will hear about these events after the console
    device does.  This allows the console.device to deal with events
    such as window resizing, and refresh before your application.

BUGS

SEE ALSO
    exec/io.h, intuition/intuition.h


console.device/RawKeyConvert

NAME
    RawKeyConvert -- decode raw input classes

SYNOPSIS
    actual = RawKeyConvert(event, buffer, length, keyMap)
    D0                     A0     A1      D1      A2

    ConsoleDevice in A6 if called from Assembly Language.

FUNCTION
    This console function converts input events of type
    IECLASS_RAWKEY to ANSI bytes, based on the keyMap, and
    places the result into the buffer.

INPUTS
    event -  an InputEvent structure pointer.
    buffer - a byte buffer large enough to hold all anticipated
        characters generated by this conversion.
    length - maximum anticipation, i.e. the buffer size in bytes.
    keyMap - a KeyMap structure pointer, or null if the default
        console device key map is to be used.

RESULTS
    actual - the number of characters in the buffer, or -1 if
        a buffer overflow was about to occur.

ERRORS
    if actual is -1, a buffer overflow condition was detected.
    Not all of the characters in the buffer are valid.

NOTES
    This function is different from standard device commands in
    that it is a function in the console device library vectors.
    In order to obtain a valid library base pointer for the
    console device (a.k.a. ConsoleDevice) call
    OpenDevice("console.device", -1, IOStdReq, 0),
    and then grab the io_Device pointer field out of the IOStdReq
    and use as ConsoleDevice.

BUGS

SEE ALSO
    exec/io.h, devices/inputevent.h, devices/keymap.h


keyboard.doc

 CMD_CLEAR                KBD_READEVENT       KBD_REMRESETHANDLER
 KBD_ADDRESETHANDLER      KBD_READMATRIX      KBD_RESETHANDLERDONE


keyboard.device/CMD_CLEAR

NAME
    CMD_CLEAR -- Clear the keyboard input buffer.

FUNCTION
    Remove from the input buffer any keys transitions waiting to
    satisfy read requests.

IO REQUEST
    io_Message      mn_ReplyPort set if quick I/O is not possible
    io_Device       preset by the call to OpenDevice
    io_Command      CMD_CLEAR
    io_Flags        IOB_QUICK set if quick I/O is possible


keyboard.device/KBD_ADDRESETHANDLER

NAME
    KBD_ADDRESETHANDLER -- Add a keyboard reset handler.

FUNCTION
    Add a function to the list of functions called to clean up
    before a hard reset generated at the keyboard.  The reset
    handler is called as:
        ResetHandler(handlerData)
                     a1

IO REQUEST
    io_Message      mn_ReplyPort set
    io_Device       preset by OpenDevice
    io_Unit         preset by OpenDevice
    io_Command      KBD_ADDRESETHANDLER
    io_Data         a pointer to an interrupt structure.
        is_Data     the handlerData pointer described above
        is_Code     the Handler function address

NOTES
    Few of the Amiga keyboard models generate the communication codes
    used to implement this reset processing.  Specifically, only the
    Euro a1000 (rare), and the B2000 keyboard generate them.

    The interrupt structure is kept by the keyboard device until a
    RemResetHandler command is satisfied for it, but the
    KBD_ADDRESETHANDLER command itself is replied immediately.


keyboard.device/KBD_READEVENT

NAME
    KBD_READEVENT -- Return the next keyboard event.

FUNCTION
    Read raw keyboard events from the keyboard and put them in the
    data area of the iORequest.  If there are no pending keyboard
    events, this command will not be satisfied, but if there are
    some events, but not as many as can fill IO_LENGTH, the
    request will be satisfied with those currently available.

IO REQUEST
    io_Message      mn_ReplyPort set if quick I/O is not possible
    io_Device       preset by the call to OpenDevice
    io_Command      KBD_READEVENT
    io_Flags        IOB_QUICK set if quick I/O is possible
    io_Length       the size of the io_Data area in bytes: there
                    are sizeof(inputEvent) bytes per input event.
    io_Data         a buffer area to fill with input events.  The
                    fields of the input event are:
        ie_NextEvent
                    links the events returned
        ie_Class
                    is IECLASS_RAWKEY
        ie_Code
                    contains the next key up/down reports
        ie_Qualifier
                    only the shift and numeric pad bits are set
        ie_SubClass, ie_X, ie_Y, ie_TimeStamp
                    are not used, and set to zero

RESULTS
    This function sets the error field in the IORequest, and fills
    the IORequest with the next keyboard events (but not partial
    events).


keyboard.device/KBD_READMATRIX

NAME
    KBD_READMATRIX -- Read the current keyboard key matrix.

FUNCTION
    This function reads the up/down state of every key in the
    key matrix.

IO REQUEST INPUT
    io_Message      mn_ReplyPort set if quick I/O is not possible
    io_Device       preset by the call to OpenDevice
    io_Command      KBD_READMATRIX
    io_Flags        IOB_QUICK set if quick I/O is possible
    io_Length       the size of the io_Data area in bytes: this
                    must be big enough to hold the key matrix.
    io_Data         a buffer area to fill with the key matrix:
                    an array of bytes whose component bits reflect
                    each keys state: the state of the key for
                    keycode n is at bit (n MOD 8) in byte
                    (n DIV 8) of this matrix.

IO REQUEST OUTPUT
    io_Error
         IOERR_BADLENGTH - the io_Length was not exactly 13 bytes.
                    The buffer is unchanged.  This is only returned
                    by V33/V34 kickstart.
    io_Actual       the number of bytes filled in io_Data with key
                    matrix data, i.e. the minimum of the supplied
                    length and the internal key matrix size.

NOTE
    For V33/V34 Kickstart, io_Length must be set to exactly 13 bytes.

RESULTS
    This function sets the error field in the IORequest, and sets
    matrix to the current key matrix.


keyboard.device/KBD_REMRESETHANDLER

NAME
    KBD_REMRESETHANDLER -- Remove a keyboard reset handler.

FUNCTION
    Remove a function previously added to the list of reset
    handler functions with KBD_ADDRESETHANDLER.

IO REQUEST
    io_Message      mn_ReplyPort set
    io_Device       preset by OpenDevice
    io_Unit         preset by OpenDevice
    io_Command      KBD_REMRESETHANDLER
    io_Data         a pointer to the handler interrupt structure.


keyboard.device/KBD_RESETHANDLERDONE

NAME
    KBD_RESETHANDLERDONE -- Indicate that reset handling is done.

FUNCTION
    Indicate that reset cleanup associated with the handler has
    completed.  This command should be issued by all keyboard
    reset handlers so that the reset may proceed.

IO REQUEST
    io_Message      mn_ReplyPort set
    io_Device       preset by OpenDevice
    io_Unit         preset by OpenDevice
    io_Command      KBD_RESETHANDLERDONE
    io_Data         a pointer to the handler interrupt structure.

NOTES
    The keyboard processor itself performs the hardware reset, and
    will time out and perform the reset even if some reset handlers
    have not indicated yet that the reset may proceed.  This
    timeout is several seconds.


printer.doc

 CMD_FLUSH        CMD_START      PRD_DUMPRPORT       PRD_RAWWRITE
 CMD_INVALID      CMD_STOP       PRD_PRTCOMMAND      PWrite()
 CMD_RESET        CMD_WRITE      PRD_QUERY


printer.device/CMD_FLUSH

NAME
    CMD_FLUSH -- abort all I/O requests (immediate)

FUNCTION
    CMD_FLUSH aborts all stopped I/O at the unit.

IO REQUEST
    io_Message      mn_ReplyPort set if quick I/O is not possible
    io_Device       preset by the call to OpenDevice
    io_Command      CMD_FLUSH
    io_Flags        IOB_QUICK set if quick I/O is possible


printer.device/CMD_INVALID

NAME
    CMD_INVALID -- invalid command

FUNCTION
    CMD_INVALID is always an invalid command, and sets the device
    error appropriately.

IO REQUEST
    io_Message      mn_ReplyPort set if quick I/O is not possible
    io_Command      CMD_INVALID
    io_Flags        IOB_QUICK set if quick I/O is possible


printer.device/CMD_RESET

NAME
    CMD_RESET -- reset the printer

FUNCTION
    CMD_RESET resets the printer device without destroying handles
    to the open device.

IO REQUEST
    io_Message      mn_ReplyPort set if quick I/O is not possible
    io_Device       preset by the call to OpenDevice
    io_Command      CMD_RESET
    io_Flags        IOB_QUICK set if quick I/O is possible


printer.device/CMD_START

NAME
    CMD_START -- restart after stop (immediate)

FUNCTION
    CMD_START restarts the unit after a stop command.

IO REQUEST
    io_Message      mn_ReplyPort set if quick I/O is not possible
    io_Device       preset by the call to OpenDevice
    io_Command      CMD_START
    io_Flags        IOB_QUICK set if quick I/O is possible


printer.device/CMD_STOP

NAME
    CMD_STOP -- pause current and queued I/O requests (immediate)

FUNCTION
    CMD_STOP pauses all queued requests for the unit, and tries to
    pause the current I/O request.  The only commands that will
    be subsequently allowed to be performed are immediate I/O
    requests, which include those to start, flush, and finish the
    I/O after the stop command.

IO REQUEST
    io_Message      mn_ReplyPort set if quick I/O is not possible
    io_Device       preset by the call to OpenDevice
    io_Command      CMD_STOP
    io_Flags        IOB_QUICK set if quick I/O is possible


printer.device/CMD_WRITE

NAME
    CMD_WRITE -- send output to the printer

FUNCTION
    This function causes a buffer of characters to be written to the
    current printer port (usually parallel or serial).  The number of
    characters is specified in io_Length, unless -1 is used, in which
    case output is sent until a 0x00 is encountered.

    The Printer device, like the Console device, maps ANSI X3.64 style
    7-bit printer control codes to the control code set of the current
    printer.  The ANSI codes supported can be found below.

NOTES
    Not all printers will support all functions.  In particular you may
    not assume that the MARGINS or TABS can be set.  Close to half the
    supported printers don't fully implement one or the other.  If you
    want the features of margins or tabs you will need to fake it
    internally by sending out spaces.

    Note that the printer device may have already sent out a "set
    margins" command to the printer.  If you are faking your own
    margins, be sure to cancel the old ones first.  (use the "aCAM"
    command)

    Defaults are set up so that if a normal AmigaDOS text file
    is sent to PRT:, it has the greatest chance of working.
    (AmigaDOS text files are defined as follows:)
            tabs            - every 8
            CR (0x0D)       - moves to start of current line
            LF (0x0A)       - moves to start of next line

IO REQUEST
    io_Message      mn_ReplyPort set
    io_Device       preset by OpenDevice
    io_Unit         preset by OpenDevice
    io_Command      CMD_WRITE
    io_Length       number of characters to process, or if -1,
                    process until 0x00 encountered
    io_Data         pointer to block of data to process

RESULTS
    io_Error : if CMD_WRITE succeeded, then io_Error will be zero.
               Otherwise io_Error will be non-zero.

SEE ALSO
    printer.h, parallel.device, serial.device, Preferences

ANSI X3.64 style COMMANDS
    aRIS         ESCc            hard reset
    aRIN         ESC#1           initialize to defaults
    aIND         ESCD            true linefeed (lf)
    aNEL         ESCE            return,lf
    aRI          ESCM            reverse lf              *

    aSGR0        ESC[0m          normal character set
    aSGR3        ESC[3m          italics on
    aSGR23       ESC[23m         italics off
    aSGR4        ESC[4m          underline on
    aSGR24       ESC[24m         underline off
    aSGR1        ESC[1m          boldface on
    aSGR22       ESC[22m         boldface off
    aSFC         SGR30-39        set foreground color
    aSBC         SGR40-49        set background color

    aSHORP0      ESC[0w          normal pitch
    aSHORP2      ESC[2w          elite on
    aSHORP1      ESC[1w          elite off
    aSHORP4      ESC[4w          condensed on
    aSHORP3      ESC[3w          condensed off
    aSHORP6      ESC[6w          enlarged on
    aSHORP5      ESC[5w          enlarged off

    aDEN6        ESC[6"z         shadow print on
    aDEN5        ESC[5"z         shadow print off
    aDEN4        ESC[4"z         doublestrike on
    aDEN3        ESC[3"z         doublestrike off
    aDEN2        ESC[2"z         Near Letter Quality (NLQ) on
    aDEN1        ESC[1"z         NLQ off

    aSUS2        ESC[2v          superscript on
    aSUS1        ESC[1v          superscript off
    aSUS4        ESC[4v          subscript on
    aSUS3        ESC[3v          subscript off
    aSUS0        ESC[0v          normalize the line      *
    aPLU         ESCL            partial line up         *
    aPLD         ESCK            partial line down       *

    aFNT0        ESC(B           US char set (default)   or Font 0
    aFNT1        ESC(R           French char set         or Font 1
    aFNT2        ESC(K           German char set         or Font 2
    aFNT3        ESC(A           UK char set             or Font 3
    aFNT4        ESC(E           Danish I char set       or Font 4
    aFNT5        ESC(H           Sweden char set         or Font 5
    aFNT6        ESC(Y           Italian char set        or Font 6
    aFNT7        ESC(Z           Spanish char set        or Font 7
    aFNT8        ESC(J           Japanese char set       or Font 8
    aFNT9        ESC(6           Norweign char set       or Font 9
    aFNT10       ESC(C           Danish II char set      or Font 10

    aPROP2       ESC[2p          proportional on         *
    aPROP1       ESC[1p          proportional off        *
    aPROP0       ESC[0p          proportional clear      *
    aTSS         ESC[n E         set proportional offset *
    aJFY5        ESC[5 F         auto left justify       *
    aJFY7        ESC[7 F         auto right justify      *
    aJFY6        ESC[6 F         auto full justify       *
    aJFY0        ESC[0 F         auto justify off        *
    aJFY3        ESC[3 F         letter space (justify)  *
    aJFY1        ESC[1 F         word fill(auto center)  *

    aVERP0       ESC[0z          1/8" line spacing
    aVERP1       ESC[1z          1/6" line spacing
    aSLPP        ESC[nt          set form length n
    aPERF        ESC[nq          set perforation skip to n lines (n>0)
    aPERF0       ESC[0q          perforation skip off

    aLMS         ESC#9           Left margin set         *
    aRMS         ESC#0           Right margin set        *
    aTMS         ESC#8           Top margin set          *
    aBMS         ESC#2           Bottom margin set       *
    aSTBM        ESC[Pn1;Pn2r    set T&B margins         *
    aSLRM        ESC[Pn1;Pn2s    set L&R margin          *
    aCAM         ESC#3           Clear margins

    aHTS         ESCH            Set horiz tab           *
    aVTS         ESCJ            Set vertical tabs       *
    aTBC0        ESC[0g          Clr horiz tab           *
    aTBC3        ESC[3g          Clear all h tab         *
    aTBC1        ESC[1g          Clr vertical tabs       *
    aTBC4        ESC[4g          Clr all v tabs          *
    aTBCALL      ESC#4           Clr all h & v tabs      *
    aTBSALL      ESC#5           Set default tabs (every 8)

    aEXTEND      ESC[Pn"x        Extended commands
                                 This is a mechanism for printer drivers
                                 to support extra commands which can be
                                 called by ANSI control sequences
    aRAW         ESC[Pn"r        Next 'Pn' chars are raw (ie. they are not
                                 parsed by the printer device, instead
                                 they are sent directly to the printer.

    (*) indicates that sending this command may cause unexpected results
        on a large number of printers.


printer.device/PRD_DUMPRPORT

NAME
    PRD_DUMPRPORT -- dump the specified RastPort to a graphics printer

FUNCTION
    Print a rendition of the supplied RastPort, using the supplied
    ColorMap, position and scaling information, as specified in
    the printer preferences.

IO REQUEST
    io_Message      mn_ReplyPort set if quick I/O is not possible.
    io_Command      PRD_DUMPRPORT.
    io_Flags        IOB_QUICK set if quick I/O is possible.
    io_RastPort     ptr to a RastPort.
    io_ColorMap     ptr to a ColorMap.
    io_Modes        the 'modes' flag from a ViewPort structure,
                    (the upper word is reserved and should be zero).

                    If you are running under version 36, or greater
                    of graphics.library, it is recommended that
                    you fill in "io_Modes" with the ULONG (32-bit)
                    value returned from calling:

                    ULONG ModeID = GetVPModeID(struct ViewPort *);

                    Doing so provides for upwards compatability with
                    the new display modes available under V36
                    (example: aspect ratio calculations for new
                    display modes).

    io_SrcX         x offset into the RastPort to start printing from.
    io_SrcY         y offset into the RastPort to start printing from.
    io_SrcWidth     width of the RastPort to print (from io_SrcX).
    io_SrcHeight    height of the RastPort to print (from io_SrcY).
    io_DestCols     width of the printout in printer pixels.
    io_DestRows     height of the printout in printer pixels.
    io_Special      flag bits
                    (some of which pertain to DestCols and DestRows).
                    -if SPECIAL_MIL is set, then the associated
                     parameter is specified in thousandths of
                     an inch on the printer.  ie. if DestCols = 8000,
                     DestRows = 10500 and SPECIAL_MILROWS and
                     SPECIAL_MILCOLS is set then the printout would be
                     8.000 x 10.500 inches.
                    -if SPECIAL_FULL is set, then the specific dimension
                     is set to the maximum possible as determined
                     by the printer limits or the configuration
                     limits; whichever is less.
                    -if SPECIAL_FRAC is set, the parameter is
                     taken to be a longword binary fraction
                     of the maximum for that dimension.
                    -if all bits for a dimension are clear,
                     (ie. SPECIAL MIL/FULL/FRAC and ASPECT are NOT set)
                     then the parameter is specified in printer pixels.
                    -if SPECIAL_CENTER is set then the image will be
                     put between the left and right edge of the paper.
                    -if SPECIAL_ASPECT is set, one of the dimensions
                     may be reduced/expanded to preserve the aspect
                     ratio of the print.
                    -SPECIAL_DENSITY(1-7) this allows for a maximum of 7
                     different print densities.  DENSITY1 is the lowest
                     density and the default.
                    -SPECIAL_NOFORMFEED - this allows for the mixing of
                     text and graphics or multiple graphic dumps on page
                     oriented printers (usually laser jet printers).
                     When this flag is set the page will not be ejected
                     after a graphic dump.  If you perform another
                     graphic dump without this flag set OR close the
                     printer after printing text after a graphic dump,
                     the page will be ejected.
                    -if SPECIAL_TRUSTME is set then the printer specific
                     driver is instructed to not issue a reset command
                     before and after the dump.  If this flag is NOT
                     checked by the printer specific driver then setting
                     this flag has no effect.  Since we now recommend
                     that printer driver writers no longer issue a reset
                     command it is probably a safe idea to always set
                     this flag when calling for a dump.
                    -if SPECIAL_NOPRINT is set then the following is done:
                     Compute print size, set 'io_DestCols' and
                     'io_DestRows' in the calling program's 'IODRPReq'
                     structure and exit, DON'T PRINT.  This allows the
                     calling program to see what the final print size
                     would be in printer pixels.  Note that it modifies
                     the 'io_DestCols' and 'io_DestRows' fields of your
                     'IODRPReq' structure.  It also sets the print
                     density and updates the 'MaxXDots', 'MaxYDots',
                     'XDotsInch', and 'YDotsInch' fields of the
                     'PrinterExtendedData' structure.

    The following rules for the interpretation of io_DestRows and
    io_DestCols that may produce unexpected results when they are
    not greater than zero and io_Special is zero.  They have been
    retained for compatability.  The user will not trigger these
    other rules with well formed usage of io_Special.

    When io_Special is equal to 0, the following rules
    (from the V1.1 printer.device, and retained for compatibility
    reasons) take effect.  Remember, these special rules are
    for io_DestRows and io_DestCols and only take effect
    if io_Special is 0).

    a) DestCols>0 & DestRows>0 - use as absolute values.
       ie. DestCols=320 & DestRows=200 means that the picture
       will appear on the printer as 320x200 dots.
    b) DestCols=0 & DestRows>0 - use the printers maximum number
       of columns and print DestRows lines. ie. if DestCols=0
       and DestRows=200 than the picture will appear on the
       printer as wide as it can be and 200 dots high.
    c) DestCols=0 & DestRows=0 - same as above except the driver
       determines the proper number of lines to print based on
       the aspect ratio of the printer. ie. This results in the
       largest picture possible that is not distorted or inverted.
       Note: As of this writing, this is the call made by such
       program as DeluxePaint, GraphicCraft, and AegisImages.
    d) DestCols>0 &DestRows=0 - use the specified width and the
       driver determines the proper number of lines to print based
       on the aspect ratio of the printer. ie. if you desire a
       picture that is 500 pixels wide and aspect ratio correct,
       use DestCols=500 and DestRows=0.
    e) DestCols<0 or DestRows>0 - the final picture is either a
       reduction or expansion based on the fraction
       |DestCols| / DestRows in the proper aspect ratio.
       Some examples:
       1) if DestCols=-2 & DestRows=1 then the printed picture will
          be 2x the AMIGA picture and in the proper aspect ratio.
          (2x is derived from |-2| / 1 which gives 2.0)
       2) if DestCols=-1 & DestRows=2 then the printed picture will
          will be 1/2x the AMIGA picture in the proper aspect ratio.
          (1/2x is derived from |-1| / 2 which gives 0.5)

NOTES
    The printer selected in preferences must have graphics
    capability to use this command.  The error 'PDERR_NOTGRAPHICS'
    is returned if the printer can not print graphics.

    Color printers may not be able to print black and white or
    greyscale pictures -- specifically, the Okimate 20 cannot print
    these with a color ribbon: you must use a black ribbon instead.
    If the printer has an input buffer option, use it.
    If the printer can be uni or bi directional, select
    uni-directional; this produces a much cleaner picture.
    Most printer drivers will attempt to set unidirectional
    printing if it is possible under software control.

    Please note that the width and height of the printable area on
    the printer is in terms of pixels and bounded by the following:
      a) WIDTH = (RIGHT_MARGIN - LEFT_MARGIN + 1) / CHARACTERS_PER_INCH
      b) HEIGHT = LENGTH / LINES_PER_INCH
    Margins are set by preferences.

    For BGR printer support, the YMC values in the printer
    specific render.c functions equate to BGR respectively, ie.
    yellow is blue, magenta is green, and cyan is red.

Data Structures
---------------
The printer specific and non-specific data structures can be read
ONCE you have opened the printer device.  Here is a code fragment
to illustrate how to do just that.

    #include <exec/types.h>
    #include <devices/printer.h>
    #include <devices/prtbase.h>
    #include <devices/prtgfx.h>

    struct IODRPReq PReq;
    struct PrinterData *PD;
    struct PrinterExtendedData *PED;

    open the printer device / if it opened...
    if (OpenDevice("printer.device", 0, &PReq, 0) == NULL) {
       get pointer to printer data
       PD = (struct PrinterData *)PReq.io_Device;
       get pointer to printer extended data
       PED = &PD->pd_SegmentData->ps_PED;
       let's see what's there
       printf("PrinterName = '%s', Version=%u, Revision=%un",
           PED->ped_PrinterName, PD->pd_SegmentData->ps_Version,
           PD->pd_SegmentData->ps_Revision,);
       printf("PrinterClass=%u, ColorClass=%un",
           PED->ped_PrinterClass, PED->ped_ColorClass);
       printf("MaxColumns=%u, NumCharSets=%u, NumRows=%un",
           PED->ped_MaxColumns, PED->ped_NumCharSets, PED->ped_NumRows);
       printf("MaxXDots=%lu, MaxYDots=%lu, XDotsInch=%u, YDotsInch=%un",
           PED->ped_MaxXDots, PED->ped_MaxYDots,
           PED->ped_XDotsInch, PED->ped_YDotsInch);
       CloseDevice(&PReq);
    }

Preferences
-----------
If you want the user to be able to access the printer preferences items
without having to run preferences (like DPAINT II's printer requester),
here is what you do.  You can look at the printer's copy of preferences
by referring to 'PD->pd_Preferences' (the printer device MUST already be
opened at this point).  After you have this you could put up a requester
and allow the user to change whatever parameters they wanted.
BEAR IN MIND THAT YOU ARE RESPONSIBLE FOR RANGE CHECKING THESE SELECTIONS!
Listed below are the printer preferences items and their valid values.

PrintPitch         - PICA, ELITE, FINE.
PrintQuality       - DRAFT, LETTER.
PrintSpacing       - SIX_LPI, EIGHT_LPI.
PrintLeftMargin    - 1 to PrintRightMargin.
PrintRightMargin   - PrintLeftMargin to 999.
PaperLength        - 1 to 999.
PrintImage         - IMAGE_POSITIVE, IMAGE_NEGATIVE.
PrintAspect        - ASPECT_HORIZ, ASPECT_VERT.
PrintShade         - SHADE_BW, SHADE_GREYSCALE, SHADE_COLOR.
PrintThreshold     - 1 to 15.
PrintFlags         - CORRECT_RED, CORRECT_GREEN, CORRECT_BLUE,
                     CENTER_IMAGE, IGNORE_DIMENSIONS,
                     BOUNDED_DIMENSIONS, ABSOLUTE_DIMENSIONS,
                     PIXEL_DIMENSIONS, MULTIPLY_DIMENSIONS,
                     INTEGER_SCALING, ORDERED_DITHERING,
                     HALFTONE_DITHERING. FLOYD_DITHERING, ANTI_ALIAS,
                     GREY_SCALE2
PrintMaxWidth      - 0 to 65535.
PrintMaxHeight     - 0 to 65535.
PrintDensity       - 1 to 7.
PrintXOffset       - 0 to 255.

Asynchronous I/O
----------------
The recommended way to do asynchronous i/o is...

a) To send requests for i/o.

     struct IORequest *ioreq;
     struct MsgPort *port;
     UBYTE signal;

     port = ioreq->io_Message.mn_ReplyPort;
     signal = port->mp_SigBit;

     SendIO(ioreq);  send request
     Wait(signal);  wait for completion (go to sleep)
     while ((Msg = GetMsg(port)) != NULL) {  get ALL messages
     }

b) To abort a previous request for i/o.

     struct IORequest *ioreq;

     AbortIO(ioreq);  abort request
     WaitIO(ioreq);  wait for reply

at this point you can re-use 'ioreq'.

Note that in the above examples 'ioreq' could be any one of...
a) struct IOStdReq    a standard i/o request
b) struct IODRPReq    a dumprport i/o request
c) struct IOPrtCmdReq a printer command i/o request

It is recommend that you do asynchronous i/o in your programs
and give the user a way of aborting all requests.

            V1.3 Printer Driver Notes
            =========================

In general densities which use more than one pass should only be used for
B&W shade dumps.  They can be used for Grey-Scale or Color Shade dumps BUT
the output may tend to look muddy or dark.  Also multiple pass Color dumps
tend to dirty or smear the ribbon (ie. yellow will get contaminated with
the other colors on the ribbon; you have been warned).

Alphacom_AlphaPro_101
---------------------
1. Daisywheel printer (text only).

Brother_HR-15XL
---------------
1. Daisywheel printer (text only).

CalComp_ColorMaster
-------------------
1. Thermal transfer b&w/color printer (text and graphics).
2. Use Black ribbon for non-color dumps; Color ribbon for color dumps.
3. Linefeeds # of vertical dots printed.
4. Densities supported are 203x200(1) dpi.
5. This is a dual printer driver.  Select a PaperSize of 'Narrow Tractor'
   for use with the ColorMaster; 'Wide Tractor' for use with the
   ColorView-5912 (which uses 11 x 17 inch paper).

CalComp_ColorMaster2
-------------------
1. Thermal transfer b&w/color printer (text and graphics).
2. Use Black ribbon for non-color dumps; Color ribbon for color dumps.
3. Linefeeds # of vertical dots printed.
4. Densities supported are 203x200(1) dpi.
5. This is a dual printer driver.  Select a PaperSize of 'Narrow Tractor'
   for use with the ColorMaster; 'Wide Tractor' for use with the
   ColorView-5912 (which uses 11 x 17 inch paper).
6. This driver is the same as the Calcomp_ColorMaster driver EXCEPT it is
   approximately 2 times faster (during color dumps) and requires LOTS of
   memory (up to 1,272,003 bytes for a full 8 x 10 inch (1600 x 2000 dot)
   color dump).  Typically full-size (color) dumps are 1600 x 1149 dots and
   require 730,767 bytes.  Memory requirements for the ColorView-5912
   are up to 2,572,803 bytes for a full 10 x 16 inch (2048 x 3200 dot)
   color dump.  Typically full-size (color) dumps are 2048 x 2155 dots and
   require 1,732,623 bytes.  The memory requirements are 1/3 when doing a
   non-color printout (on both the ColorMaster and ColorView).

Canon_PJ-1080A
--------------
1. Ink jet b&w/color printer (text and graphics).
2. Linefeeds # of vertical dots printed.
3. Densities supported are 83x84(1) dpi.

CBM_MPS1000
-----------
1. Dot matrix b&w printer (text and graphics).
2. Linefeeds # of vertical dots printed
   (-1/3 dot if PaperType = Single). *2
3. Density     XDPI    YDPI    XYDPI   Comments
       1       120      72      8640
       2       120     144     17280   two pass
       3       240      72     17280                   *1
       4       120     216     25920   three pass
       5       240     144     34560   two pass        *1
       6       240     216     51840   three pass      *1
       7       same as 6

Diablo_630
----------
1. Daisywheel printer (text only).

Diablo_Advantage_D25
--------------------
1. Daisywheel printer (text only).

Diablo_C-150
------------
1. Ink jet b&w/color printer (text and graphics).
2. Always linefeeds 4 dots (limitation of printer).
3. A PaperSize of 'Wide Tractor' selects a maximum print width of
   8.5 inches (for wide roll paper).
5. Densities supported are 120x120(1) dpi.

EpsonQ (24-pin Epson compatible)
------
1. Dot matrix b&w/color printer (text and graphics).
2. Drives all EpsonQ (LQ1500, LQ2500, etc.) compatible printers.
3. Linefeeds # of vertical dots printed.
4. Density     XDPI    YDPI    XYDPI   Comments
       1        90     180     16200
       2       120     180     21600
       3       180     180     32400
       4       360     180     64800   *1
       5,6,7   same as 4

5. A PaperSize of 'Wide Tractor' selects a maximum print width of
   13.6 inches (for wide carriage printers).
6. A PaperType of 'Single' uses only 16 of the 24 pins, whereas a PaperType
   of 'Fanfold' uses all 24 pins.  The 'Single' option is useful for those
   printers which have a weak power supply and cannot drive all 24 pins
   continuously.  If during a single pass of the print head you notice that
   the top two thirds of the graphics are darker than the bottom one third
   then you will probably need to drop down to 16 pins.

EpsonX[CBM_MPS-1250] (8/9-pin Epson compatible)
--------------------
1. Dot matrix b&w/color printer (text and graphics).
2. Drives all EpsonX (EX/FX/JX/LX/MX/RX, etc.) compatible printers.
3. Linefeeds # of vertical dots printed
   (-1/3 dot if PaperType = Single). *2
4. Density     XDPI    YDPI    XYDPI   Comments
       1       120      72      8640
       2       120     144     17280   two pass
       3       240      72     17280                   *1
       4       120     216     25920   three pass
       5       240     144     34560   two pass        *1
       6       240     216     51840   three pass      *1
       7       same as 6

5. A PaperSize of 'Wide Tractor' selects a maximum print width of
   13.6 inches (for wide carriage printers).
6. Use this driver if you own a CBM_MPS-1250 (as it is EpsonX compatible).

EpsonXOld (8/9-pin Epson compatible)
---------
1. Dot matrix b&w printer (text and graphics).
2. Drives all very old EpsonX (EX/FX/JX/LX/MX/RX, etc.) compatible
   printers.
3. Linefeeds # of vertical dots printed.
4. Density     XDPI    YDPI    XYDPI   Comments
       1        60     72       4320
       2       120     72       8640   (double speed)                  *1
       3       120     72       8640
       4       240     72      17280                                   *1
       5       120     72       8640   (for use on old Star printers)
       6       240     72      17280   (for use on old Star printers)  *1
       7       240     72      17280   (same as density 4)             *1

5. A PaperSize of 'Wide Tractor' selects a maximum print width of
   13.6 inches (for wide carriage printers).
6. Use this driver if the EpsonX driver does not work properly in graphics
   or text mode on your EpsonX compatible printer.

generic
-------
1. Text only printer.

Howtek_Pixelmaster
------------------
1. Plastic ink jet b&w/color printer (text and graphics).
2. Linefeeds # of vertical dots printed.
3. Density     XDPI    YDPI    XYDPI   Comments
       1        80      80      6400
       2       120     120     14400
       3       160     160     25600
       4       240     240     57600
       5,6,7   same as 4

4. Maximum print area is 8.0 x 10.0 inches.

HP_DeskJet
----------
1. Ink jet non-color printer (text and graphics).
2. Linefeeds # of vertical dots printed.
3. Density     XDPI    YDPI    XYDPI   Comments
       1        75      75      5625
       2       100     100     10000
       3       150     150     22500
       4       300     300     90000
       5,6,7   same as 4

4. Maximum print area is 8.0 x 10.0 inches.

HP_LaserJet (LaserJet+/LaserJetII compatible)
-----------
1. Laser engine non-color printer (text and graphics).
2. Linefeeds # of vertical dots printed.
3. Density     XDPI    YDPI    XYDPI   Comments
       1        75      75      5625
       2       100     100     10000
       3       150     150     22500
       4       300     300     90000
       5,6,7   same as 4

4. Maximum print area is 8.0 x 10.0 inches.

HP_PaintJet
-----------
1. Ink jet b&w/color printer (text and graphics).
2. Linefeeds # of vertical dots printed.
3. Densities supported are 180x180(1) dpi.

HP_ThinkJet
----------
1. Ink jet non-color printer (text and graphics).
2. Linefeeds # of vertical dots printed.
3. Density     XDPI    YDPI    XYDPI   Comments
       1        96     96       9216
       2       192     96      18432
       3,4,5,6,7       same as 4

Imagewriter II (Imagewriter compatible)
--------------
1. Dot matrix b&w/color printer (text and graphics).
2. Linefeeds # of vertical dots printed.
3. Density     XDPI    YDPI    XYDPI   Comments
       1        80      72      5760
       2       120      72      8640
       3       144      72     10368
       4       160      72     11520
       5       120     144     17280   two pass
       6       144     144     20736   two pass
       7       160     144     23040   two pass

Nec_Pinwriter (24-wire Pinwriter compatible (P5/P6/P7/P9/P2200))
-------------
1. Dot matrix b&w/color printer (text and graphics).
2. Drives all Nec 24-wire Pinwriter compatible printers.
3. Linefeeds # of vertical dots printed.
4. Density     XDPI    YDPI    XYDPI   Comments
       1        90     180     16200
       2       120     180     21600
       3       180     180     32400
       4       120     360     43200  two pass
       5       180     360     64800  two pass
       6       360     180     64800
       7       360     360    129600  two pass

5. A PaperSize of 'Wide Tractor' selects a maximum print width of
   13.6 inches (for wide carriage printers).

Okidata_92
----------
1. Dot matrix non-color printer (text and graphics).
2. Always linefeeds 7/72 inch (limitation of printer in graphics mode).
3. Densities supported are 72x72 dpi.

Okidata_293I
------------
1. Dot matrix b&w/color printer (text and graphics).
2. Drives 292 or 293 using the IBM interface module.
3. Linefeeds # of vertical dots printed (-1/2 dot if PaperType = Single) *3
4. Density     XDPI    YDPI    XYDPI   Comments
       1       120     144     17280
       2       240     144     34560
       3       120     288     34560   two pass
       4       240     288     69120   two pass
       5,6,7   same as 4

5. A PaperSize of 'Wide Tractor' selects a maximum print width of
   13.6 inches (for wide carriage printers).

Okimate-20
----------
1. Thermal transfer b&w/color printer (text and graphics).
2. Use Black ribbon for non-color dumps; Color ribbon for color dumps.
3. Linefeeds an even # of dots printed. (ie. if 3 printed, 4 advanced).
4. Densities supported are 120x144(1) dpi.

Quadram_QuadJet
---------------
1. Ink jet b&w/color printer (text and graphics).
2. Linefeeds # of vertical dots printed.
3. Densities supported are 83x84(1) dpi.

Qume_LetterPro_20
-----------------
1. Daisywheel printer (text only).

Seiko_5300
----------
1. Thermal transfer b&w/color printer (graphics only).
2. Use Black ribbon for non-color dumps; Color ribbon for color dumps.
3. Density     XDPI    YDPI    XYDPI   Comments
       1       152     152     23104   drives CH-5301 printer
       2       203     203     41209   drives CH-5312 printer
       3       240     240     57600   drives CH-5303 printer
       4, 5,6,7        same as 3

   You must select the proper density to drive the specific printer
   that you have.
4. This driver is not on the V1.3 Workbench or Extras disk.  It is
   available on BIX and directly from Seiko.

Seiko_5300a
-----------
1. Thermal transfer b&w/color printer (graphics only).
2. Use Black ribbon for non-color dumps; Color ribbon for color dumps.
3. Density     XDPI    YDPI    XYDPI   Comments
       1       152     152     23104   drives CH-5301 printer
       2       203     203     41209   drives CH-5312 printer
       3       240     240     57600   drives CH-5303 printer
       4, 5,6,7        same as 3

   You must select the proper density to drive the specific printer
   that you have.
4. This driver is the same as the Seiko_5300 driver EXCEPT it is
   approximately 2 times faster (during color dumps) and requires LOTS of
   memory (up to 1,564,569 bytes for a full 8 x 10 inch (1927 x 2173 dot)
   color dump).  Typically full-size (color) dumps are 1927 x 1248 dots
   and require 898,569 bytes.  The memory requirements are 1/3 when doing
   a non-color printout.
5. This driver is not on the V1.3 Workbench or Extras disk.  It is
   available on BIX and directly from Seiko.

Tektronix_4693D
---------------
1. Thermal transfer b&w/color printer (graphics only).
2. Densities supported are 300x300(1) dpi
3. Due to the way the printer images a picture none of the printer
   preferences options affect the printout with the following exceptions:
     a)Aspect - Horizontal, Vertical
     b)Shade - B&W, Grey_Scale, Color
   ...as a result of this only full size pictures can be printed.
4. Keypad menu option 3b COLOR ADJUSTMENT may be set from the keypad.
   For normal prints this option should be set to "do not adjust".
5. Keypad menu option 3d VIDEO COLOR CORRECTION may be set from the keypad.
   For normal prints this option should be set to "do not adjust".
6. Keypad menu option 5 BACKGROUND COLOR EXCHANGE may be set from the
   keypad.  For normal prints this option should be set to "print colors
   as received".
7. Once a picture has been printed additional copies may be printed
   without resending by using the printers keypad.
8. This driver is not on the V1.3 Workbench or Extras disk.  It is
   available on BIX and directly from Tektronix.

Tektronix_4696
--------------
1. Ink jet b&w/color printer (text and graphics).
2. Always linefeeds 4 dots (limitation of printer).
3. Densities supported are 121x120(1), 242x120(black)(2) and
   242x120(color)(3).
   Selecting a density of 2 or higher really doesn't give you true 242 dpi
   resolution since the printer only has 121 x dots per inch.
   Instead this mode tells the printer to go into it's double pass mode.
   Here, it outputs a line of dots at 121 dpi; and outputs the line again
   (shifted to the right by 1/242 of an inch).  This produces much more
   vibrate colors and gives the illusion of more resolution.  One drawback
   is that large areas of solid colors (red, green, and blue specifically)
   tend to over-saturate the paper with ink.  Density1 outputs all colors
   in one pass.  Density 2 does a double pass on black.  Density 3 does a
   double pass on all colors.  Density 1 to 3 correspond to the printer's
   graphics printing modes 1 to 3 (respectively).
4. This driver is not on the V1.3 Workbench or Extras disk.  It is
   available on BIX and directly from Tektronix.
5. A PaperSize of 'Wide Tractor' selects a maximum print width of
   9.0 inches (for wide roll paper).

Toshiba_P351C (24-pin Toshiba compatible)
-------------
1. Dot matrix b&w/color printer (text and graphics).
2. Drives all Toshiba_P351C compatible printers.
3. Linefeeds # of vertical dots printed.
4. Density     XDPI    YDPI    XYDPI   Comments
       1       180     180     32400
       2       360     180     64800
       3,4,5,6,7       same as 2

5. A PaperSize of 'Wide Tractor' selects a maximum print width of
   13.5 inches (for wide carriage printers).

Toshiba_P351SX (24-pin Toshiba compatible)
--------------
1. Dot matrix b&w/color printer (text and graphics).
2. Drives all Toshiba_P351SX (321SL, 321SLC, 341SL) compatible printers.
3. Linefeeds # of vertical dots printed.
4. Density     XDPI    YDPI    XYDPI   Comments
       1       180     180     32400
       2       360     180     64800
       3       180     360     64800  two pass
       4       360     360    129600  two pass
       5,6,7   same as 4

5. A PaperSize of 'Wide Tractor' selects a maximum print width of
   13.5 inches (for wide carriage printers).

Xerox_4020
----------
1. Ink jet b&w/color printer (text and graphics).
2. Always linefeeds 4 dots (limitation of printer).
3. This driver is IDENTICAL to the Diablo_C-150 driver EXCEPT it outputs
   all black dots TWICE.  This is a special feature of this printer and
   produces much more solid, darker black shades.  Please note that some
   printing time overhead results from this feature; if you don't want it
   use the Diablo_C-150 driver.
4. Densities supported are 121x120(1) and 242x240(2) dpi.
   Selecting a density of 2 or higher really doesn't give you true 240 dpi
   resolution since the Xerox_4020 only has 121 x dots per inch.
   Instead this mode tells the printer to go into it's pseudo 240 dpi mode.
   Here, it outputs a line of dots at 121 dpi; moves the paper up 1/240 of
   an inch and outputs the line again (shifted to the right by 1/240 of an
   inch).  This produces much more vibrate colors and gives the illusion
   of more resolution.  One drawback is that large areas of solid colors
   (red, green, and blue specifically) tend to over-saturate the paper with
   ink.
5. A PaperSize of 'Wide Tractor' selects a maximum print width of
   9.0 inches (for wide roll paper).

Notes
-----
*0 - on most printers friction fed paper tends to produce better looking
     (ie. less horizontal banding) graphic dumps than tractor fed paper.

*1 - in this mode the printer cannot print two consecutive dots in a row.
     It is recommended that you only use this density for B&W Shade dumps.

*2 - only when 72 YDPI is selected.  This option is useful if you notice
     tiny white horizontal strips in your printout.

*3 - only when 144 YDPI is selected.  This option is useful if you notice
     tiny white horizontal strips in your printout.


printer.device/PRD_PRTCOMMAND

NAME
    PRD_PRTCOMMAND -- send a command to the printer

FUNCTION
    This function sends a command to either the parallel or serial
    device.  The printer device maps this command to the control
    code set of the current printer.  The commands supported can
    be found with the printer.device/Write command.  All printers
    may not support all functions.

IO REQUEST IOPrtCmdReq
    io_Message      mn_ReplyPort set
    io_Device       preset by OpenDevice
    io_Unit         preset by OpenDevice
    io_Command      PRD_PRTCOMMAND
    io_PrtCommand   the actual command number
    io_Parm0        parameter for the command
    io_Parm1        parameter for the command
    io_Parm2        parameter for the command
    io_Parm3        parameter for the command

RESULTS
    Errors: if the PRD_PRTCOMMAND succeeded, then io_Error will be zero.
    Otherwise io_Error will be non-zero.  An error of -1 indicates that
    the command is not supported by the current printer driver.  This
    could be used to check if the connected printer supports a particular
    command (italics for example).

SEE ALSO
    printer.device/Write printer.h, parallel.device, Preferences


printer.device/PRD_QUERY

NAME
    PRD_QUERY -- query printer port/line status

FUNCTION
    This command returns the status of the printer port's lines and
    registers.  Since the printer port uses either the serial or
    parallel port for i/o, the actual status returned is either the
    serial or parallel port's status.

IO REQUEST
    io_Message      mn_ReplyPort set if quick I/O is not possible
    io_Device       preset by the call to OpenDevice
    io_Command      PRD_QUERY
    io_Data         ptr to 2 UBYTES where result will be stored.

RESULTS
    io_Data       BIT  ACTIVE  FUNCTION (SERIAL DEVICE)

         LSB       0    low    reserved
                   1    low    reserved
                   2    low    reserved
                   3    low    Data Set Ready
                   4    low    Clear To Send
                   5    low    Carrier Detect
                   6    low    Ready To Send
                   7    low    Data Terminal Ready
         MSB       8    high   read buffer overflow
                   9    high   break sent (most recent output)
                  10    high   break received (as latest input)
                  11    high   transmit x-OFFed
                  12    high   receive x-OFFed
               13-15           reserved

    io_Data       BIT  ACTIVE  FUNCTION (PARALLEL DEVICE)

                   0     hi     printer busy (offline)
                   1     hi     paper out
                   2     hi     printer selected
                                  (WARNING: the bit 2 line is also
                                   connected to the serial port's ring
                                   indicator pin on the A500 and A2000)
                 3-7            reserved

    io_Actual     1-parallel, 2-serial


printer.device/PRD_RAWWRITE

NAME
    PRD_RAWWRITE -- transparent write command

FUNCTION
    This is a non standard write command that performs no
    processing on the data passed to it.

IO REQUEST
    io_Message      mn_ReplyPort set if quick I/O is not possible
    io_Command      PRD_RAWWRITE
    io_Flags        IOB_QUICK set if quick I/O is possible
    io_Length       the number of bytes in io_Data
    io_Data         the raw bytes to write to the printer


printer.device/PWrite

NAME
    PWrite -- internal write to printer port

SYNOPSIS
    error = (*PrinterData->pd_PWrite)(buffer, length);
    D0                                  A0      D0

FUNCTION
    PWrite writes 'length' bytes directly to the printer.  This
    function is generally called by printer drivers to send
    their buffer(s) to the printer.

    This function is accessed by referencing off the PrinterData (PD)
    structure.  Below is a code fragment to show how to do get access
    to a pointer to the PrinterData (PD) structure.

    #include <exec/types.h>
    #include <devices/printer.h>
    #include <devices/prtbase.h>

    struct IODRPReq PReq;
    struct PrinterData *PD;
    struct PrinterExtendedData *PED;

    /* open the printer device (any version); if it opened... */
    if (OpenDevice("printer.device", 0, &PReq, 0) == NULL) {

        /* get pointer to printer data structure */
        PD = (struct PrinterData *)PReq.io_Device;

        /* write something directly to the printer */
        (*PD->pd_PWrite)("Hello worldn", 12);

        CloseDevice(&PReq); /* close the printer device */
    }


trackdisk.doc

 CMD_CLEAR            TD_CHANGESTATE       TD_MOTOR
 CMD_READ             TD_EJECT             TD_PROTSTATUS
 CMD_UPDATE           TD_FORMAT            TD_RAWREAD
 CMD_WRITE            TD_GETDRIVETYPE      TD_RAWWRITE
 TD_ADDCHANGEINT      TD_GETGEOMETRY       TD_REMCHANGEINT
 TD_CHANGENUM         TD_GETNUMTRACKS      TD_SEEK


trackdisk.device/CMD_CLEAR

NAME
    CMD_CLEAR/ETD_CLEAR -- mark the track buffer as containing invalid
                           data.

FUNCTION
    These commands mark the track buffer as invalid, forcing a
    reread of the disk on the next operation. ETD_UPDATE or CMD_UPDATE
    would be used to force data out to the disk before turning the motor
    off. ETD_CLEAR or CMD_CLEAR are usually used after having locked out
    the trackdisk.device via the use of the disk resource, when you
    wish to prevent the track from being updated, or when you wish to
    force the track to be re-read. ETD_CLEAR or CMD_CLEAR will not do an
    update, nor will an update command do a clear.

IO REQUEST INPUT
    io_Device       preset by the call to OpenDevice()
    io_Unit         preset by the call to OpenDevice()
    io_Command      CMD_CLEAR or ETD_CLEAR
    io_Flags        0 or IOF_QUICK
    iotd_Count      (ETD_CLEAR only) maximum allowable change counter
                    value.

IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>

SEE ALSO
    CMD_WRITE, CMD_UPDATE


trackdisk.device/CMD_READ

NAME
    CMD_READ/ETD_READ -- read sectors of data from a disk.

FUNCTION
    These commands transfer data from the track buffer to a supplied
    buffer. If the desired sector is already in the track buffer, no disk
    activity is initiated. If the desired sector is not in the buffer, the
    track containing that sector is automatically read in. If the data in
    the current track buffer has been modified, it is written out to the
    disk before a new track is read. ETD_READ will read the sector label
    area if the iotd_SecLabel is non-NULL.

IO REQUEST INPUT
    io_Device       preset by the call to OpenDevice()
    io_Unit         preset by the call to OpenDevice()
    io_Command      CMD_READ or ETD_READ
    io_Flags        0 or IOF_QUICK
    io_Data         pointer to the buffer where the data should be put
    io_Length       number of bytes to read, must be a multiple of
                    TD_SECTOR.
    io_Offset       byte offset from the start of the disk describing
                    where to read data from, must be a multiple of
                    TD_SECTOR.
    iotd_Count      (ETD_READ only) maximum allowable change counter
                    value.
    iotd_SecLabel   (ETD_READ only) NULL or sector label buffer pointer.
                    If provided, the buffer must be a multiple of
                    TD_LABELSIZE.

IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>
NOTES
    Under versions of Kickstart earlier than V36, the io_Data had to
    point to a buffer in chip memory. This restriction is no longer
    present as of Kickstart V36 and beyond.

SEE ALSO
    CMD_WRITE


trackdisk.device/CMD_UPDATE

NAME
    CMD_UPDATE/ETD_UPDATE -- write out the track buffer if it is dirty.

FUNCTION
    The trackdisk device does not write data sectors unless it is
    necessary (you request that a different track be used) or until the
    user requests that an update be performed. This improves system speed
    by caching disk operations. These commands ensure that any
    buffered data is flushed out to the disk. If the track buffer has not
    been changed since the track was read in, these commands do nothing.
    ETD_UPDATE command checks for diskchange.

IO REQUEST INPUT
    io_Device       preset by the call to OpenDevice()
    io_Unit         preset by the call to OpenDevice()
    io_Command      CMD_UPDATE or ETD_UPDATE
    io_Flags        0 or IOF_QUICK
    iotd_Count      (ETD_UPDATE only) maximum allowable change counter
                    value.

IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>

SEE ALSO
    CMD_WRITE


trackdisk.device/CMD_WRITE

NAME
    CMD_WRITE/ETD_WRITE -- write sectors of data to a disk.

FUNCTION
    These commands transfer data from a supplied buffer to the track
    buffer. If the track that contains this sector is already in the track
    buffer, no disk activity is initiated. If the desired sector is not in
    the buffer, the track containing that sector is automatically read in.
    If the data in the current track buffer has been modified, it is
    written out to the disk before the new track is read in for
    modification. ETD_WRITE will write the sector label area if
    iotd_SecLabel is non-NULL.

IO REQUEST INPUT
    io_Device       preset by the call to OpenDevice()
    io_Unit         preset by the call to OpenDevice()
    io_Command      CMD_WRITE or ETD_WRITE
    io_Flags        0 or IOF_QUICK
    io_Data         pointer to the buffer where the data should be put
    io_Length       number of bytes to write, must be a multiple of
                    TD_SECTOR.
    io_Offset       byte offset from the start of the disk describing
                    where to write data to, must be a multiple of
                    TD_SECTOR.
    iotd_Count      (ETD_WRITE only) maximum allowable change counter
                    value.
    iotd_SecLabel   (ETD_WRITE only) NULL or sector label buffer pointer.
                    If provided, the buffer must be a multiple of
                    TD_LABELSIZE.

IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>

NOTES
    Under versions of Kickstart earlier than V36, the io_Data had to
    point to a buffer in chip memory. This restriction is no longer
    present as of Kickstart V36 and beyond.

SEE ALSO
    CMD_READ, TD_FORMAT


trackdisk.device/TD_ADDCHANGEINT

NAME
    TD_ADDCHANGEINT -- add a disk change software interrupt handler.

FUNCTION
    This command lets you add a software interrupt handler to the
    disk device that gets invoked whenever a disk insertion or removal
    occurs.

    You must pass in a properly initialized Exec Interrupt structure
    and be prepared to deal with disk insertions/removals
    immediately. From within the interrupt handler, you may only call the
    status commands that can use IOF_QUICK.

    To set up the handler, an Interrupt structure must be initialized.
    This structure is supplied as the io_Data to the TD_ADDCHANGEINT
    command. The handler then gets linked into the handler chain and
    gets invoked whenever a disk change happens. You must eventually
    remove the handler before you exit.

    This command only returns when the handler is removed. That is,
    the device holds onto the IO request until the TD_REMCHANGEINT command
    is executed with that same IO request. Hence, you must use SendIO()
    with this command.

IO REQUEST INPUT
    io_Device       preset by the call to OpenDevice()
    io_Unit         preset by the call to OpenDevice()
    io_Command      TD_ADDCHANGEINT
    io_Flags        0
    io_Length       sizeof(struct Interrupt)
    io_Data         pointer to Interrupt structure

IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>

SEE ALSO
    TD_REMCHANGEINT, <devices/trackdisk.h>, <exec/interrupts.h>,
    exec.library/Cause()


trackdisk.device/TD_CHANGENUM

NAME
    TD_CHANGENUM -- return the current value of the disk-change counter.

FUNCTION
    This command returns the current value of the disk-change counter (as
    used by the enhanced commands). The disk change counter is incremented
    each time a disk is inserted or removed from the trackdisk unit.

IO REQUEST INPUT
    io_Device       preset by the call to OpenDevice()
    io_Unit         preset by the call to OpenDevice()
    io_Command      TD_CHANGENUM
    io_Flags        0 or IOF_QUICK

IO REQUEST RESULT
    io_Error  - 0 for success, or an error code as defined in
                <devices/trackdisk.h>
    io_Actual - if io_Error is 0, this contains the current value of the
                disk-change counter.


trackdisk.device/TD_CHANGESTATE

NAME
    TD_CHANGESTATE -- check if a disk is currently in a drive.

FUNCTION
    This command checks to see if there is currently a disk in a drive.

IO REQUEST INPUT
    io_Device       preset by the call to OpenDevice()
    io_Unit         preset by the call to OpenDevice()
    io_Command      TD_CHANGESTATE
    io_Flags        0 or IOF_QUICK

IO REQUEST RESULT
    io_Error  - 0 for success, or an error code as defined in
                <devices/trackdisk.h>
    io_Actual - if io_Error is 0, this tells you whether a disk is in
                the drive. 0 means there is a disk, while anything else
                indicates there is no disk.


trackdisk.device/TD_EJECT

NAME
   TD_EJECT -- eject the disk in the drive, if possible.

FUNCTION
    This command causes the drive to attempt to eject the disk in
    it, if any.  Note that the current trackdisk.device does not
    implement this command, but it might in the future, and other
    trackdisk-compatible drivers may implement this command.

IO REQUEST INPUT
    io_Device       preset by the call to OpenDevice()
    io_Unit         preset by the call to OpenDevice()
    io_Command      TD_EJECT
    io_Flags        0 or IOF_QUICK

IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>


trackdisk.device/TD_FORMAT

NAME
    TD_FORMAT/ETD_FORMAT -- format a track on a disk.

FUNCTION
    These commands are used to write data to a track that either
    has not yet been formatted or has had a hard error on a standard write
    command. TD_FORMAT completely ignores all data currently on a track and
    does not check for disk change before performing the command. The
    io_Data field must point to at least one track worth of data. The
    io_Offset field must be track aligned, and the io_Length field must be
    in units of track length (that is, NUMSEC*TD_SECTOR).

    The device will format the requested tracks, filling each sector with
    the contents of the buffer pointed to by io_Data. You
    should do a read pass to verify the data.

    If you have a hard write error during a normal write, you may find it
    possible to use the TD_FORMAT command to reformat the track as part of
    your error recovery process. ETD_FORMAT will write the sector label
    area if iotd_SecLabel is non-NULL.

IO REQUEST INPUT
    io_Device       preset by the call to OpenDevice()
    io_Unit         preset by the call to OpenDevice()
    io_Command      TD_FORMAT or ETD_FORMAT
    io_Flags        0 or IOF_QUICK
    io_Data         points to a buffer containing the data to write to the
                    track, must be at least as large as io_Length.
    io_Length       number of bytes to format, must be a multiple of
                    (TD_SECTORS * NUMSEC).
    io_Offset       byte offset from the start of the disk for the track to
                    format, must be a multiple of (TD_SECTORS * NUMSEC).
    iotd_Count      (ETD_FORMAT only) maximum allowable change counter
                    value.
    iotd_SecLabel   (ETD_FORMAT only) NULL or sector label buffer pointer.
                    If provided, the buffer must be a multiple of
                    (TD_LABELSIZE * NUMSEC).

IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>

NOTES
    Under versions of Kickstart earlier than V36, the io_Data had to
    point to a buffer in chip memory. This restriction is no longer
    present as of Kickstart V36 and beyond.

SEE ALSO
    CMD_WRITE, TD_RAWWRITE


trackdisk.device/TD_GETDRIVETYPE

NAME
    TD_GETDRIVETYPE -- return the type of disk drive for the unit that was
                       opened.

FUNCTION
    This command returns the type of the disk drive to the user.
    This number will be a small integer and will come from the set of
    DRIVEXXX constants defined in <devices/trackdisk.h>.

    The only way you can actually use this command is if the trackdisk
    device understands the drive type of the hardware that is plugged in.
    This is because the OpenDevice() call will fail if the trackdisk device
    does not understand the drive type. To find raw drive identifiers see
    the disk.resource's DR_GETUNITID entry point.

IO REQUEST INPUT
    io_Device       preset by the call to OpenDevice()
    io_Unit         preset by the call to OpenDevice()
    io_Command      TD_GETDRIVETYPE
    io_Flags        0 or IOF_QUICK

IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>
    io_Actual - if io_Error is 0 this contains the drive type connected to
                this unit.

SEE ALSO
    TD_GETNUMTRACKS, <devices/trackdisk.h>


trackdisk.device/TD_GETGEOMETRY

NAME
   TD_GETGEOMETRY -- return the geometry of the drive.

FUNCTION
    This command returns a full set of information about the
    layout of the drive. The information is returned in the
    DriveGeometry structure pointed to by io_Data.

IO REQUEST INPUT
    io_Device       preset by the call to OpenDevice()
    io_Unit         preset by the call to OpenDevice()
    io_Command      TD_GETGEOMETRY
    io_Flags        0 or IOF_QUICK
    io_Data         Pointer to a DriveGeometry structure
    io_Length       sizeof(struct DriveGeometry)

IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>

NOTE
    This information may change when a disk in inserted when
    certain hardware is present.

SEE ALSO
    TD_GETDRIVETYPE, TD_GETNUMTRACKS


trackdisk.device/TD_GETNUMTRACKS

NAME
    TD_GETNUMTRACKS -- return the number of tracks for the type of disk
                       drive for the unit that was opened.

FUNCTION
    This command returns the number of tracks that are available
    on the disk unit.

IO REQUEST INPUT
    io_Device       preset by the call to OpenDevice()
    io_Unit         preset by the call to OpenDevice()
    io_Command      TD_GETNUMTRACKS
    io_Flags        0 or IOF_QUICK

IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>
    io_Actual - if io_Error is 0 this contains the drive type connected to
                this unit.

SEE ALSO
    TD_GETDRIVETYPE


trackdisk.device/TD_MOTOR

NAME
    TD_MOTOR/ETD_MOTOR -- control the on/off state of a drive motor.

FUNCTION
    This command gives control over the disk motor. The motor may be
    turned on or off. When it is on, the drive light automatically turns
    on as well.

    If the motor is just being turned on, the device will delay the
    proper amount of time to allow the drive to come up to speed. Normally,
    turning the drive on is not necessary, the device does this
    automatically if it receives a request when the motor is off. However,
    turning the motor off is the programmer's responsibility.

    In addition, the standard instructions to the user are that it is safe
    to remove a disk from a drive if and only if the motor is off (that is,
    if the disk light is off).

IO REQUEST INPUT
    io_Device       preset by the call to OpenDevice()
    io_Unit         preset by the call to OpenDevice()
    io_Command      TD_MOTOR or ETD_MOTOR
    io_Flags        0 or IOF_QUICK
    io_Length       the requested state of the motor, 0 to turn the motor
                    off, and 1 to turn the motor on.
    iotd_Count      (ETD_MOTOR only) maximum allowable change counter
                    value.

IO REQUEST RESULT
    io_Error  - 0 for success, or an error code as defined in
                <devices/trackdisk.h>
    io_Actual - if io_Error is 0 this contains the previous state of the
                drive motor.


trackdisk.device/TD_PROTSTATUS

NAME
    TD_PROTSTATUS -- return whether the current disk is write-protected.

FUNCTION
    This command is used to determine whether the current disk is
    write-protected.

IO REQUEST INPUT
    io_Device       preset by the call to OpenDevice()
    io_Unit         preset by the call to OpenDevice()
    io_Command      TD_PROTSTATUS
    io_Flags        0 or IOF_QUICK

IO REQUEST RESULT
    io_Error  - 0 for success, or an error code as defined in
                <devices/trackdisk.h>
    io_Actual - if io_Error is 0, this tells you whether the disk in the
                drive is write-protected. 0 means the disk is NOT write-
                protected, while any other value indicates it is.


trackdisk.device/TD_RAWREAD

NAME
    TD_RAWREAD/ETD_RAWREAD -- read raw data from the disk.

FUNCTION
    These commands read a track of raw data from disk and deposits it in
    the provided buffer. The data is taken straight from the disk with
    no processing done on it. It will appear exactly as the bits come out
    off the disk, hopefully in some legal MFM format.

    This interface is intended for sophisticated programmers only.
    Commodore-Amiga reserves the right to make enhancements to the disk
    format in the future. We will provide compatibility via the
    CMD_READ and ETD_READ commands, anyone using TD_RAWREAD is
    bypassing this upwards compatibility, and may thus stop working.

IO REQUEST INPUT
    io_Device       preset by the call to OpenDevice()
    io_Unit         preset by the call to OpenDevice()
    io_Command      TD_RAWREAD or ETD_RAWREAD.
    io_Flags        if the IOTDB_INDEXSYNC bit is set then the driver
                    will make a best effort attempt to start reading
                    from the index mark.  Note that there will be at
                    least some delay, and perhaps a great deal of delay
                    (for example if interrupts have been disabled).
    io_Length       Length of buffer in bytes, with a maximum of 32768
                    bytes.
    io_Data         Pointer to CHIP memory buffer where raw track data is
                    to be deposited.
    io_Offset       The number of the track to read in.
    iotd_Count      (ETD_RAWREAD only) maximum allowable change counter
                    value.

IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>

NOTES
    The track buffer provided MUST be in CHIP memory

    There is a delay between the index pulse and the start of bits
    coming in from the drive (e.g. dma started). This delay
    is in the range of 135-200 microseconds. This delay breaks
    down as follows: 55 microsecs is software interrupt overhead
    (this is the time from interrupt to the write of the DSKLEN
    register). 66 microsecs is one horizontal line delay (remember
    that disk IO is synchronized with agnus' display fetches).
    The last variable (0-65 microsecs) is an additional scan line
    since DSKLEN is poked anywhere in the horizontal line. This leaves
    15 microsecs unaccounted for...  Sigh.

    In short, You will almost never get bits within the first 135
    microseconds of the index pulse, and may not get it until 200
    microseconds. At 4 microsecs/bit, this works out to be between
    4 and 7 bytes of user data of delay.

BUGS
    This command does not work reliably under versions of Kickstart
    earlier than V36, especially on systems with 1 floppy drive.

SEE ALSO
    TD_RAWWRITE


trackdisk.device/TD_RAWWRITE

NAME
    TD_RAWWRITE/ETD_RAWWRITE -- write raw data to the disk.

FUNCTION
    This command writes a track of raw data from the provided buffer to
    the specified track on disk. The data is copied straight to the disk
    with no processing done on it. It will appear exactly on the disk as
    it is in the memory buffer, hopefully in a legal MFM format.

    This interface is intended for sophisticated programmers only.
    Commodore-Amiga reserves the right to make enhancements to the disk
    format in the future. We will provide compatibility via the
    CMD_WRITE and ETD_WRITE commands, anyone using TD_RAWWRITE is
    bypassing this upwards compatibility, and may thus stop working.

IO REQUEST INPUT
    io_Device       preset by the call to OpenDevice()
    io_Unit         preset by the call to OpenDevice()
    io_Command      TD_RAWWRITE or ETD_RAWWRITE.
    io_Flags        if the IOTDB_INDEXSYNC bit is set then the driver
                    will make a best effort attempt to start writing
                    from the index mark.  Note that there will be at
                    least some delay, and perhaps a great deal of delay
                    (for example if interrupts have been disabled).
    io_Length       Length of buffer in bytes, with a maximum of 32768
                    bytes.
    io_Data         Pointer to CHIP memory buffer where raw track data is
                    to be taken.
    io_Offset       The number of the track to write to.
    iotd_Count      (ETD_RAWWRITE only) maximum allowable change counter
                    value.

IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>

NOTES
    The track buffer provided MUST be in CHIP memory

    There is a delay between the index pulse and the start of bits
    going out to the driver (e.g. write gate enabled). This delay
    is in the range of 135-200 microseconds. This delay breaks
    down as follows: 55 microsecs is software interrupt overhead
    (this is the time from interrupt to the write of the DSKLEN
    register). 66 microsecs is one horizontal line delay (remember
    that disk IO is synchronized with agnus' display fetches).
    The last variable (0-65 microsecs) is an additional scan line
    since DSKLEN is poked anywhere in the horizontal line. This leaves
    15 microsecs unaccounted for...  Sigh.

    In short, You will almost never get bits within the first 135
    microseconds of the index pulse, and may not get it until 200
    microseconds. At 4 microsecs/bit, this works out to be between
    4 and 7 bytes of user data of delay.

BUGS
    This command does not work reliably under versions of Kickstart
    earlier than V36, especially on systems with 1 floppy drive.

SEE ALSO
    TD_RAWREAD


trackdisk.device/TD_REMCHANGEINT

NAME
    TD_REMCHANGEINT -- remove a disk change software interrupt handler.

FUNCTION
    This command removes a disk change software interrupt added
    by a previous use of TD_ADDCHANGEINT.

IO REQUEST INPUT
    The same IO request used for TD_ADDCHANGEINT.

    io_Device       preset by the call to OpenDevice()
    io_Unit         preset by the call to OpenDevice()
    io_Command      TD_REMCHANGEINT
    io_Flags        0
    io_Length       sizeof(struct Interrupt)
    io_Data         pointer to Interrupt structure

IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>

BUGS
    This command did not function properly under versions of Kickstart
    earlier than V36. A valid workaround under these older versions of
    Kickstart is:

            Forbid();
            Remove(ioRequest);
            Permit();

    Do not use this workaround in versions of Kickstart >= V36, use
    TD_REMCHANGEINT instead (for future compatibility with V38+).

SEE ALSO
    TD_ADDCHANGEINT, <devices/trackdisk.h>


trackdisk.device/TD_SEEK

NAME
    TD_SEEK/ETD_SEEK -- control positioning of the drive heads.

FUNCTION
    These commands are currently provided for internal diagnostics,
    disk repair, and head cleaning only.

    TD_SEEK and ETD_SEEK move the drive heads to the track specified. The
    io_Offset field should be set to the (byte) offset to which the seek is
    to occur. TD_SEEK and ETD_SEEK do not verify their position until the
    next read. That is, they only move the heads; they do not actually read
    any data.

IO REQUEST INPUT
    io_Device       preset by the call to OpenDevice()
    io_Unit         preset by the call to OpenDevice()
    io_Command      TD_SEEK or ETD_SEEK
    io_Flags        0 or IOF_QUICK
    io_Offset       byte offset from the start of the disk describing
                    where to move the head to.
    iotd_Count      (ETD_SEEK only) maximum allowable change counter
                    value.

IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>


battclock.doc

 ReadBattClock()
 ResetBattClock()
 WriteBattClock()


battclock.resource/ReadBattClock

NAME
    ReadBattClock -- Read time from clock chip.  (V36)

SYNOPSIS
    AmigaTime = ReadBattClock( )

    ULONG ReadBattClock( void );
    D0

FUNCTION
    This routine reads the time from the clock chip and returns it
    as the number of seconds from 01-jan-1978.

INPUTS

RESULTS
    AmigaTime       The number of seconds from 01-Jan-1978 that
                        the clock chip thinks it is.

NOTES
    If the clock chip returns an invalid date, the clock chip is
    reset and 0 is returned.

SEE ALSO

BUGS


battclock.resource/ResetBattClock

NAME
    ResetBattClock -- Reset the clock chip.  (V36)

SYNOPSIS
    ResetBattClock( )

    void ResetBattClock( void );

FUNCTION
    This routine does whatever is neeeded to put the clock chip
    into a working and usable state and also sets the date on the
    clock chip to 01-Jan-1978.

INPUTS

RESULTS

NOTES

SEE ALSO

BUGS


battclock.resource/WriteBattClock

NAME
    WriteBattClock -- Set the time on the clock chip.  (V36)

SYNOPSIS
    WriteBattClock( AmigaTime )
                    D0

    void WriteBattClock( ULONG );

FUNCTION
    This routine writes the time given in AmigaTime to the clock
    chip.

INPUTS
    AmigaTime       The number of seconds from 01-Jan-1978 to the
                        time that should be written to the clock
                        chip.

RESULTS

NOTES

SEE ALSO

BUGS


cia.doc

 AbleICR()           RemICRVector()
 AddICRVector()      SetICR()


cia.resource/AbleICR

NAME
    AbleICR -- Enable/disable ICR interrupts.

SYNOPSIS
    oldMask = AbleICR( Resource, mask )
    D0                 A6        D0

    WORD AbleICR( struct Library *, WORD );

FUNCTION
    This function provides a means of enabling and disabling 8520
    CIA interrupt control registers. In addition it returns the
    previous enable mask.

INPUTS
    mask            A bit mask indicating which interrupts to be
                        modified. If bit 7 is clear the mask
                        indicates interrupts to be disabled. If
                        bit 7 is set, the mask indicates
                        interrupts to be enabled. Bit positions
                        are identical to those in 8520 ICR.

RESULTS
    oldMask         The previous enable mask before the requested
                        changes. To get the current mask without
                        making changes, call the function with a
                        null parameter.

EXAMPLES
    Get the current mask:
        mask = AbleICR(0)
    Enable both timer interrupts:
        AbleICR(0x83)
    Disable serial port interrupt:
        AbleICR(0x08)

EXCEPTIONS
    Enabling the mask for a pending interrupt will cause an
    immediate processor interrupt (that is if everything else is
    enabled). You may want to clear the pending interrupts with
    SetICR() prior to enabling them.

NOTE
    The CIA resources are special in that there is more than one
    of them in the system. Because of this, the C language stubs
    in amiga.lib for the CIA resources require an extra parameter
    to specify which CIA resource to use. The synopsys for the
    amiga.lib stubs is as follows:

    oldMask = AbleICR( Resource, mask )
    D0                 A6        D0

    WORD AbleICR( struct Library *, WORD );

SEE ALSO
    cia.resource/SetICR()


cia.resource/AddICRVector

NAME
    AddICRVector -- attach an interrupt handler to a CIA bit.

SYNOPSIS
    interrupt = AddICRVector( Resource, iCRBit, interrupt )
    D0                        A6        D0      A1

    struct Interrupt *AddICRVector( struct Library *, WORD,
            struct Interrupt * );

FUNCTION
    Assign interrupt processing code to a particular interrupt bit
    of the CIA ICR.  If the interrupt bit has already been
    assigned, this function will fail, and return a pointer to the
    owner interrupt.  If it succeeds, a null is returned.

    This function will also enable the CIA interrupt for the given
    ICR bit.

INPUTS
    iCRBit          Bit number to set (0..4).
    interrupt       Pointer to interrupt structure.

RESULT
    interrupt       Zero if successful, otherwise returns a
                        pointer to the current owner interrupt
                        structure.

NOTE
    A processor interrupt may be generated immediatly if this call
    is successful.

    In general, it is probably best to only call this function
    while DISABLED so that the resource to which the interrupt
    handler is being attached may be set to a known state before
    the handler is called. You MUST NOT change the state of the
    resource before attaching your handler to it.

    The CIA resources are special in that there is more than one
    of them in the system. Because of this, the C language stubs
    in amiga.lib for the CIA resources require an extra parameter
    to specify which CIA resource to use. The synopsys for the
    amiga.lib stubs is as follows:

    interrupt = AddICRVector( Resource, iCRBit, interrupt )
    D0                        A6        D0      A1

    struct Interrupt *AddICRVector( struct Library *, WORD,
            struct Interrupt *);

    ***WARNING***

    Never assume that any of the CIA hardware is free for use.
    Always use the AddICRVector() function to obtain ownership
    of the CIA hardware registers your code will use.

    Note that there are two (2) interval timers per CIA.  If
    your application needs one of the interval timers, you
    can try to obtain any one of the four (4) until AddICRVector()
    succeeds.  If all four interval timers are in-use, your
    application should exit cleanly.

    If you just want ownership of a CIA hardware timer, or register,
    but do not want interrupts generated, use the AddICRVector()
    function to obtain ownership, and use the AbleICR() function
    to turn off (or on) interrupts as needed.

    Note that CIA-B generates level 6 interrupts (which can degrade
    system performance by blocking lower priority interrupts).  As
    usual, interrupt handling code should be optimized for speed.

    Always call RemICRVector() when your code exits to release
    ownership of any CIA hardware obtained with AddICRVector().

SEE ALSO
    cia.resource/RemICRVector(), cia.resource/AbleICR()


cia.resource/RemICRVector

NAME
    RemICRVector -- Detach an interrupt handler from a CIA bit.

SYNOPSIS
    RemICRVector( Resource, iCRBit, interrupt )
                  A6        D0      A1

    void RemICRVector( struct Library *, WORD, struct Interrupt *);

FUNCTION
    Disconnect interrupt processing code for a particular
    interrupt bit of the CIA ICR.

    This function will also disable the CIA interrupt for the
    given ICR bit.

INPUTS
    iCRBit          Bit number to set (0..4).
    interrupt       Pointer to interrupt structure.

RESULT

NOTE
    The CIA resources are special in that there is more than one
    of them in the system. Because of this, the C language stubs
    in amiga.lib for the CIA resources require an extra parameter
    to specify which CIA resource to use. The synopsys for the
    amiga.lib stubs is as follows:

    RemICRVector( Resource, iCRBit, interrupt )
                  A6        D0      A1

    void RemICRVector( struct Library *, WORD, struct Interrupt *);

SEE ALSO
    cia.resource/AddICRVector()


cia.resource/SetICR

NAME
    SetICR -- Cause, clear, and sample ICR interrupts.

SYNOPSIS
    oldMask = SetICR( Resource, mask )
    D0                A6        D0

    WORD SetICR( struct Library *, WORD );

FUNCTION
    This function provides a means of reseting, causing, and
    sampling 8520 CIA interrupt control registers.

INPUTS
    mask            A bit mask indicating which interrupts to be
                        effected. If bit 7 is clear the mask
                        indicates interrupts to be reset.  If bit
                        7 is set, the mask indicates interrupts to
                        be caused. Bit positions are identical to
                        those in 8520 ICR.

RESULTS
    oldMask         The previous interrupt register status before
                        making the requested changes.  To sample
                        current status without making changes,
                        call the function with a null parameter.

EXAMPLES
    Get the interrupt mask:
        mask = SetICR(0)
    Clear serial port interrupt:
        SetICR(0x08)

NOTE
    The CIA resources are special in that there is more than one
    of them in the system. Because of this, the C language stubs
    in amiga.lib for the CIA resources require an extra parameter
    to specify which CIA resource to use. The synopsys for the
    amiga.lib stubs is as follows:

    oldMask = SetICR( Resource, mask )
    D0                A6        D0

    WORD SetICR( struct Library *, WORD );

    ***WARNING***

    Never read the contents of the CIA interrupt control registers
    directly.  Reading the contents of one of the CIA interrupt
    control registers clears the register.  This can result in
    interrupts being missed by critical operating system code, and
    other applications.

EXCEPTIONS
    Setting an interrupt bit for an enabled interrupt will cause
    an immediate interrupt.

SEE ALSO
    cia.resource/AbleICR()


filesysres.doc

 --background--


FileSystem.resource/--background--

PURPOSE

    The FileSystem.resource is where boot disk drivers rendezvous
    to share file system code segments for partitions specified by
    dos type.  Prior to V36, it was created by the first driver
    that needed to use it.  For V36, its creation is ensured by the
    rom boot process.

CONTENTS

    The FileSystem.resource is described in the include file
    resources/filesysres.h.  The nodes on it describe how to
    algorithmically convert the result of MakeDosNode (from the
    expansion.library) to a node appropriate for the dos type.

    FileSysEntry
        fse_Node            on fsr_FileSysEntries list
                            ln_Name is of creator of this entry
        fse_DosType         DosType of this FileSys: e.g. 0x444f5301
                            for the fast file system.
        fse_Version         high word is the version, low word is
                            the revision.
        fse_PatchFlags      bits set for those of the following that
                            need to be substituted into a standard
                            device node for this file system: e.g.
                            $180 for substitute SegList & GlobalVec
        fse_Type            device node type: zero
        fse_Task            standard dos "task" field
        fse_Lock            must be zero
        fse_Handler         for V36, if bit 31 is set, this is not
                            an AmigaDOS partition.
        fse_StackSize       stacksize to use when starting task
        fse_Priority        task priority when starting task
        fse_Startup         startup msg: FileSysStartupMsg for disks
        fse_SegList         segment of code to run to start new task
        fse_GlobalVec       BCPL global vector when starting task

    no more entries need exist than those implied by fse_PatchFlags,
    so entries do not have a fixed size.  For V36, for example, the
    entry for the fast file system (fse_DosType 0x444f5301)
    contains a zero fse_PatchFlags, and thus no entries beyond that.


potgo.doc

 AllocPotBits()
 FreePotBits()
 WritePotgo()


potgo.resource/AllocPotBits

NAME
    AllocPotBits -- Allocate bits in the potgo register.

SYNOPSIS
    allocated = AllocPotBits(bits)
    D0                       D0

    UWORD AllocPotBits( UWORD );

FUNCTION
    The AllocPotBits routine allocates bits in the hardware potgo
    register that the application wishes to manipulate via
    WritePotgo.  The request may be for more than one bit.  A
    user trying to allocate bits may find that they are
    unavailable because they are already allocated, or because
    the start bit itself (bit 0) has been allocated, or if
    requesting the start bit, because input bits have been
    allocated.  A user can block itself from allocation: i.e.
    it should FreePotgoBits the bits it has and re-AllocPotBits if
    it is trying to change an allocation involving the start bit.

INPUTS
    bits - a description of the hardware bits that the application
            wishes to manipulate, loosely based on the register
            description itself:
        START (bit 0) - set if you wish to use start (i.e. start
                the proportional controller counters) with the
                input ports you allocate (below).  You must
                allocate all the DATxx ports you want to apply
                START to in this same call, with the OUTxx bit
                clear.
        DATLX (bit 8) - set if you wish to use the port associated
                with the left (0) controller, pin 5.
        OUTLX (bit 9) - set if you promise to use the LX port in
                output mode only.  The port is not set to output
                for you at this time -- this bit set indicates
                that you don't mind if STARTs are initiated at any
                time by others, since ports that are enabled for
                output are unaffected by START.
        DATLY (bit 10) - as DATLX but for the left (0) controller,
                pin 9.
        OUTLY (bit 11) - as OUTLX but for LY.
        DATRX (bit 12) - the right (1) controller, pin 5.
        OUTRX (bit 13) - OUT for RX.
        DATRY (bit 14) - the right (1) controller, pin 9.
        OUTRY (bit 15) - OUT for RY.

RESULTS
    allocated - the START and DATxx bits of those requested that
            were granted.  The OUTxx bits are don't cares.


potgo.resource/FreePotBits

NAME
    FreePotBits -- Free allocated bits in the potgo register.

SYNOPSIS
    FreePotBits(allocated)
                D0

    void FreePotBits( UWORD );

FUNCTION
    The FreePotBits routine frees previously allocated bits in the
    hardware potgo register that the application had allocated via
    AllocPotBits and no longer wishes to use.  It accepts the
    return value from AllocPotBits as its argument.


potgo.resource/WritePotgo

NAME
    WritePotgo -- Write to the hardware potgo register.

SYNOPSIS
    WritePotgo(word, mask)
               D0    D1

    void WritePotgo( UWORD, UWORD );

FUNCTION
    The WritePotgo routine sets and clears bits in the hardware
    potgo register.  Only those bits specified by the mask are
    affected -- it is improper to set bits in the mask that you
    have not successfully allocated.  The bits in the high byte
    are saved to be maintained when other users write to the
    potgo register.  The START bit is not saved, it is written
    only explicitly as the result of a call to this routine with
    the START bit set: other users will not restart it.

INPUTS
    word - the data to write to the hardware potgo register and
        save for further use, except the START bit, which is
        not saved.
    mask - those bits in word that are to be written.  Other
        bits may have been provided by previous calls to
        this routine, and default to zero.


battmem.doc

 ObtainBattSemaphore()      ReleaseBattSemaphore()
 ReadBattMem()              WriteBattMem()


battmem.resource/ObtainBattSemaphore

NAME
    ObtainBattSemaphore -- Obtain access to nonvolatile ram. (V36)

SYNOPSIS
    ObtainBattSemaphore( )

    void ObtainBattSemaphore( void );

FUNCTION
    Aquires exclusive access to the system nonvolatile ram.

INPUTS

RESULTS

NOTES

SEE ALSO

BUGS


battmem.resource/ReadBattMem

NAME
    ReadBattMem -- Read a bitstring from nonvolatile ram.  (V36)

SYNOPSIS
    Error = ReadBattMem( Buffer, Offset, Len )
    D0                   A0      D0      D1

    ULONG ReadBattMem( APTR, ULONG, ULONG );

FUNCTION
    Read a bitstring from nonvolatile ram.

INPUTS
    Buffer          Where to put the bitstring.
    Offset          Bit offset of first bit to read.
    Len             Length of bitstring to read.

RESULTS
    Error           Zero if no error.

NOTES
    The battery-backed memory is checksummed. If a checksum error
    is detected, all bits in the battery-backed memory are
    silently set to zero.

    Bits in the battery-backed memory that do not exist are read
    as zero.

    Partial byte reads (less than 8 bits) result in the bits read
    being put in the low-order bits of the destination byte.

SEE ALSO

BUGS


battmem.resource/ReleaseBattSemaphore

NAME
    ReleaseBattSemaphore -- Allow nonvolatile ram to others.  (V36)

SYNOPSIS
    ReleaseBattSemaphore( )

    void ReleaseBattSemaphore( void );

FUNCTION
    Relinquish exclusive access to the system nonvolatile ram.

INPUTS

RESULTS

NOTES

SEE ALSO

BUGS


battmem.resource/WriteBattMem

NAME
    WriteBattMem -- Write a bitstring to nonvolatile ram.  (V36)

SYNOPSIS
    Error = WriteBattMem( Buffer, Offset, Len )
    D0                    A0      D0      D1

    ULONG WriteBattMem( APTR, ULONG, ULONG );

FUNCTION
    Write a bitstring to the nonvolatile ram.

INPUTS
    Buffer          Where to get the bitstring.
    Offset          Bit offset of first bit to write.
    Len             Length of bitstring to write.

RESULTS
    Error           Zero if no error.

NOTES
    The battery-backed memory is checksummed. If a checksum error
    is detected, all bits in the battery-backed memory are
    silently set to zero.

    Partial byte writes (less than 8 bits) result in the bits
    written being read from the low-order bits of the source byte.

SEE ALSO

BUGS


disk.doc

 AllocUnit()      GetUnit()        GiveUnit()
 FreeUnit()       GetUnitID()      ReadUnitID()


disk.resource/AllocUnit

NAME
   AllocUnit - allocate a unit of the disk

SYNOPSIS
   Success = AllocUnit( unitNum ), DRResource
    D0                   D0         A6

    BOOL AllocUnit(LONG);

FUNCTION
    This routine allocates one of the units of the disk.  It should
    be called before trying to use the disk (via GetUnit).

    In reality, it is perfectly fine to use GetUnit/GiveUnit if AllocUnit
    fails.  Do NOT call FreeUnit if AllocUnit did not succeed.  This
    has been the case for all revisions of disk.resource.

INPUTS
    unitNum -- a legal unit number (zero through three)

RESULTS
    Success -- nonzero if successful.  zero on failure.

EXCEPTIONS

SEE ALSO

BUGS


disk.resource/FreeUnit

NAME
   FreeUnit - deallocate the disk

SYNOPSIS
   FreeUnit( unitNum ), DRResource
              D0         A6

    void FreeUnit(LONG);

FUNCTION
    This routine deallocates one of the units of the disk.  It should
    be called when done with the disk.  Do not call it if you did
    no successfully allocate the disk (there is no protection -- you
    will probably crash the disk system).

INPUTS
    unitNum -- a legal unit number (zero through three)

RESULTS

EXCEPTIONS

SEE ALSO
    FreeUnit

BUGS
    Doesn't check if you own the unit, or even if anyone owns it.


disk.resource/GetUnit

NAME
   GetUnit - allocate the disk for a driver

SYNOPSIS
   lastDriver = GetUnit( unitPointer ), DRResource
   D0                     A1             A6

    struct DiscResourceUnit *GetUnit(struct DiscResourceUnit *);

FUNCTION
    This routine allocates the disk to a driver.  It is either
    immediately available, or the request is saved until the disk
    is available.  When it is available, your unitPointer is
    sent back to you (via ReplyMsg).  You may then reattempt the
    GetUnit.

    Allocating the disk allows you to use the disk's resources.
    Remember however that there are four units to the disk; you are
    only one of them.  Please be polite to the other units (by never
    selecting them, and by not leaving interrupts enabled, etc.).

    When you are done, please leave the disk in the following state:
        dmacon dma bit ON
        dsklen dma bit OFF (write a #DSKDMAOFF to dsklen)
        adkcon disk bits -- any way you want
        entena:disk sync and disk block interrupts -- Both DISABLED
        CIA resource index interrupt -- DISABLED
        8520 outputs -- doesn't matter, because all bits will be
            set to inactive by the resource.
        8520 data direction regs -- restore to original state.

    NOTE: GetUnit() does NOT turn on the interrupts for you.
          You must use AbleICR (for the index interrupt) or intena
          (for the diskbyte and diskblock interrupts) to turn them
          on.  You should turn them off before calling GiveUnit,
          as stated above.

INPUTS
    unitPtr - a pointer you your disk resource unit structure.
            Note that the message filed of the structure MUST
            be a valid message, ready to be replied to.  Make sure
            ln_Name points to a null-terminated string, preferably
            one that identifies your program.

            You need to set up the three interrupt structures,
            in particular the IS_DATA and IS_CODE fields.  Set them
            to NULL if you don't need that interrupt.  Also, set
            the ln_Type of the interrupt structure to NT_INTERRUPT.
            WARNING: don't turn on a disk resource interrupt unless
            the IS_CODE for that interrupt points to executable code!

            IS_CODE will be called with IS_DATA in A1 when the
            interrupt occurs.  Preserve all regs but D0/D1/A0/A1.
            Do not make assumptions about A0.

RESULTS
    lastDriver - if the disk is not busy, then the last unit
            to use the disk is returned.  This may be used to
            see if a driver needs to reset device registers.
            (If you were the last user, then no one has changed
            any of the registers.  If someone else has used it,
            then any allowable changes may have been made).  If the
            disk is busy, then a null is returned.

EXCEPTIONS

SEE ALSO
    GiveUnit

BUGS


disk.resource/GetUnitID

NAME
   GetUnitID - find out what type of disk is out there

SYNOPSIS
   idtype = GetUnitID( unitNum ), DRResource
    D0                  D0         A6

    LONG GetUnitID(LONG);

FUNCTION
    Gets the drive ID for a given unit.  Note that this value may
    change if someone calls ReadUnitID, and the drive id changes.

INPUTS
    unitNum -- a legal unit number (zero through three)

RESULTS
    idtype -- the type of the disk drive.  Standard types are
            defined in the resource include file.

EXCEPTIONS

SEE ALSO
    ReadUnitID

BUGS


disk.resource/GiveUnit

NAME
   GiveUnit - Free the disk back up

SYNOPSIS
   GiveUnit(), DRResource
                A6

    void GiveUnit();

FUNCTION
    This routine frees the disk after a driver is done with it.
    If others are waiting, it will notify them.

INPUTS

RESULTS

EXCEPTIONS

SEE ALSO
    GetUnit

BUGS
    In pre-V36, GiveUnit didn't check if you owned the unit.  A patch
    for this was part of 1.3.1 SetPatch.  Fixed in V36.


disk.resource/ReadUnitID

NAME
   ReadUnitID - reread and return the type of drive (V37)

SYNOPSIS
   idtype = ReadUnitID( unitNum ), DRResource
    D0                     D0         A6

    ULONG ReadUnitID(LONG);

FUNCTION
    Rereads the drive id for a specific unit (for handling drives
    that change ID according to what sort of disk is in them.  You
    MUST have done a GetUnit before calling this function!

INPUTS
    unitNum -- a legal unit number (zero through three)

RESULTS
    idtype -- the type of the disk drive.  Standard types are
            defined in the resource include file.

EXCEPTIONS

SEE ALSO
    GetUnitID

BUGS


misc.doc

 AllocMiscResource()
 FreeMiscResource()


misc.resource/AllocMiscResource

NAME
    AllocMiscResource - allocate one of the miscelaneous resources

SYNOPSIS
    CurrentUser = AllocMiscResource( unitNum, name )
    D0                               D0       A1

    char * AllocMiscResource(ULONG,char *);

FUNCTION
    This routine attempts to allocate one of the miscellaneous resources
    If the resource had already been allocated, an error is returned. If
    you do get it, your name is associated with the resource (so a user
    can see who has it allocated).

    This function may not be called from interrupt code

DESCRIPTION
    There are certain parts of the hardware that a multitasking- friendly
    program may need to take over.  The serial port is a good example. By
    grabbing the misc.resource for the serial port, the caller would
    "own" the hardware registers associated with that function.  Nobody
    else, including the system serial driver, is allowed to interfere.

    Resources are called in exactly the same manner as libraries.
    From assembly language, A6 must equal the resource base.  The
    offsets for the function are listed in the resources/misc.i
    include file (MR_ALLOCMISCRESOURCE for this function).

INPUTS
    unitNum - the number of the resource you want to allocate
              (eg.  MR_SERIALBITS).
    name - a mnenonic name that will help the user figure out
            what piece of software is hogging a resource.
            (havoc breaks out if a name of null is passed in...)

RESULTS
    CurrentUser - if the resource is busy, then the name of
            the current user is returned.  If the resource is
            free, then null is returned.

BUGS

SEE ALSO
    resources/misc.i, FreeMiscResource()


misc.resource/FreeMiscResource

NAME
    FreeMiscResource - make a resource available for reallocation

SYNOPSIS
    FreeMiscResource( unitNum )
                      D0

    void FreeMiscResource(ULONG);

FUNCTION
    This routine frees one of the resources allocated
    by AllocMiscResource.  The resource is made available
    for reuse.

    FreeMiscResource must be called from the same task that
    called AllocMiscResource.  This function may not be called from
    interrupt code.

INPUTS
    unitNum - the number of the miscellaneous resource to be freed.

RESULTS
    Frees the appropriate resource.

BUGS

SEE ALSO
    resources/misc.i, AllocMiscResource()


2.0 Function Index

   --background--                     (filesysres.resource)
   --background--                     (timer.device)

   AbleICR()                          (cia.resource)
   AbortIO()                          (audio.device)
   AbortIO()                          (exec.library)
   AbortIO()                          (narrator.device)
   AbortIO()                          (serial.device)
   AbortIO()                          (timer.device)
   AbortPkt()                         (dos.library)
   ActivateCxObj()                    (commodities.library)
   ActivateGadget()                   (intuition.library)
   ActivateWindow()                   (intuition.library)
   ADCMD_ALLOCATE                     (audio.device)
   ADCMD_FINISH                       (audio.device)
   ADCMD_FREE                         (audio.device)
   ADCMD_LOCK                         (audio.device)
   ADCMD_PERVOL                       (audio.device)
   ADCMD_SETPREC                      (audio.device)
   ADCMD_WAITCYCLE                    (audio.device)
   AddAnimOb()                        (graphics.library)
   AddAppIconA()                      (wb.library)
   AddAppMenuItemA()                  (wb.library)
   AddAppWindowA()                    (wb.library)
   AddBob()                           (graphics.library)
   AddBootNode()                      (expansion.library)
   AddBuffers()                       (dos.library)
   AddClass()                         (intuition.library)
   AddConfigDev()                     (expansion.library)
   AddDevice()                        (exec.library)
   AddDosEntry()                      (dos.library)
   AddDosNode()                       (expansion.library)
   AddFont()                          (graphics.library)
   AddFreeList()                      (icon.library)
   AddGadget()                        (intuition.library)
   AddGList()                         (intuition.library)
   AddHead()                          (exec.library)
   AddICRVector()                     (cia.resource)
   AddIEvents()                       (commodities.library)
   AddIntServer()                     (exec.library)
   AddLibrary()                       (exec.library)
   AddMemList()                       (exec.library)
   AddPart()                          (dos.library)
   AddPort()                          (exec.library)
   AddResource()                      (exec.library)
   AddSegment()                       (dos.library)
   AddSemaphore()                     (exec.library)
   AddTail()                          (exec.library)
   AddTask()                          (exec.library)
   AddTime()                          (timer.device)
   AddTOF()                           (amiga_lib.library)
   AddVSprite()                       (graphics.library)
   afp()                              (amiga_lib.library)
   Alert()                            (exec.library)
   AllocAbs()                         (exec.library)
   AllocAslRequest()                  (asl.library)
   Allocate()                         (exec.library)
   AllocateTagItems()                 (utility.library)
   AllocConfigDev()                   (expansion.library)
   AllocDosObject()                   (dos.library)
   AllocEntry()                       (exec.library)
   AllocExpansionMem()                (expansion.library)
   AllocFileRequest()                 (asl.library)
   AllocIFF()                         (iffparse.library)
   AllocLocalItem()                   (iffparse.library)
   AllocMem()                         (exec.library)
   AllocMiscResource()                (misc.resource)
   AllocPotBits()                     (potgo.resource)
   AllocRaster()                      (graphics.library)
   AllocRemember()                    (intuition.library)
   AllocSignal()                      (exec.library)
   AllocTrap()                        (exec.library)
   AllocUnit()                        (disk.resource)
   AllocVec()                         (exec.library)
   Amiga2Date()                       (utility.library)
   AndRectRegion()                    (graphics.library)
   AndRegionRegion()                  (graphics.library)
   Animate()                          (graphics.library)
   AreaCircle()                       (graphics.library)
   AreaDraw()                         (graphics.library)
   AreaEllipse()                      (graphics.library)
   AreaEnd()                          (graphics.library)
   AreaMove()                         (graphics.library)
   ArgArrayDone()                     (amiga_lib.library)
   ArgArrayInit()                     (amiga_lib.library)
   ArgInt()                           (amiga_lib.library)
   ArgString()                        (amiga_lib.library)
   arnd()                             (amiga_lib.library)
   AskFont()                          (graphics.library)
   AskKeyMapDefault()                 (keymap.library)
   AskSoftStyle()                     (graphics.library)
   AslRequest()                       (asl.library)
   AssignAdd()                        (dos.library)
   AssignLate()                       (dos.library)
   AssignLock()                       (dos.library)
   AssignPath()                       (dos.library)
   AttachCxObj()                      (commodities.library)
   AttemptLockDosList()               (dos.library)
   AttemptLockLayerRom()              (graphics.library)
   AttemptSemaphore()                 (exec.library)
   AutoRequest()                      (intuition.library)
   AvailFonts()                       (diskfont.library)
   AvailMem()                         (exec.library)

   BeginIO()                          (amiga_lib.library)
   BeginIO()                          (audio.device)
   BeginIO()                          (serial.device)
   BeginRefresh()                     (intuition.library)
   BeginUpdate()                      (layers.library)
   BehindLayer()                      (layers.library)
   BitMapScale()                      (graphics.library)
   BltBitMap()                        (graphics.library)
   BltBitMapRastPort()                (graphics.library)
   BltClear()                         (graphics.library)
   BltMaskBitMapRastPort()            (graphics.library)
   BltPattern()                       (graphics.library)
   BltTemplate()                      (graphics.library)
   BuildEasyRequestArgs()             (intuition.library)
   BuildSysRequest()                  (intuition.library)
   BumpRevision()                     (icon.library)

   CacheClearE()                      (exec.library)
   CacheClearU()                      (exec.library)
   CacheControl()                     (exec.library)
   CachePostDMA()                     (exec.library)
   CachePreDMA()                      (exec.library)
   CallHook()                         (amiga_lib.library)
   CallHookA()                        (amiga_lib.library)
   CallHookPkt()                      (utility.library)
   Cause()                            (exec.library)
   CBD_CHANGEHOOK                     (clipboard.device)
   CBD_CURRENTREADID                  (clipboard.device)
   CBD_CURRENTWRITEID                 (clipboard.device)
   CBD_POST                           (clipboard.device)
   CBump()                            (graphics.library)
   CDInputHandler()                   (console.device)
   CD_ASKDEFAULTKEYMAP                (console.device)
   CD_ASKKEYMAP                       (console.device)
   CD_SETDEFAULTKEYMAP                (console.device)
   CD_SETKEYMAP                       (console.device)
   CEND                               (graphics.library)
   ChangeMode()                       (dos.library)
   ChangeSprite()                     (graphics.library)
   ChangeWindowBox()                  (intuition.library)
   CheckDate()                        (utility.library)
   CheckIO()                          (exec.library)
   CheckRexxMsg()                     (amiga_lib.library)
   CheckSignal()                      (dos.library)
   CINIT                              (graphics.library)
   ClearCxObjError()                  (commodities.library)
   ClearDMRequest()                   (intuition.library)
   ClearEOL()                         (graphics.library)
   ClearMenuStrip()                   (intuition.library)
   ClearPointer()                     (intuition.library)
   ClearRectRegion()                  (graphics.library)
   ClearRegion()                      (graphics.library)
   ClearRexxMsg()                     (rexxsyslib.library)
   ClearScreen()                      (graphics.library)
   Cli()                              (dos.library)
   CliInitNewcli()                    (dos.library)
   CliInitRun()                       (dos.library)
   ClipBlit()                         (graphics.library)
   CloneTagItems()                    (utility.library)
   Close()                            (dos.library)
   CloseClipboard()                   (iffparse.library)
   CloseDevice()                      (audio.device)
   CloseDevice()                      (exec.library)
   CloseDevice()                      (narrator.device)
   CloseDevice()                      (serial.device)
   CloseFont()                        (graphics.library)
   CloseIFF()                         (iffparse.library)
   CloseLibrary()                     (exec.library)
   CloseMonitor()                     (graphics.library)
   CloseScreen()                      (intuition.library)
   CloseWindow()                      (intuition.library)
   CloseWorkBench()                   (intuition.library)
   CMD_CLEAR                          (audio.device)
   CMD_CLEAR                          (console.device)
   CMD_CLEAR                          (keyboard.device)
   CMD_CLEAR                          (parallel.device)
   CMD_CLEAR                          (serial.device)
   CMD_CLEAR                          (trackdisk.device)
   CMD_FLUSH                          (audio.device)
   CMD_FLUSH                          (narrator.device)
   CMD_FLUSH                          (parallel.device)
   CMD_FLUSH                          (printer.device)
   CMD_FLUSH                          (serial.device)
   CMD_INVALID                        (printer.device)
   CMD_READ                           (audio.device)
   CMD_READ                           (clipboard.device)
   CMD_READ                           (console.device)
   CMD_READ                           (narrator.device)
   CMD_READ                           (parallel.device)
   CMD_READ                           (serial.device)
   CMD_READ                           (trackdisk.device)
   CMD_RESET                          (audio.device)
   CMD_RESET                          (narrator.device)
   CMD_RESET                          (parallel.device)
   CMD_RESET                          (printer.device)
   CMD_RESET                          (serial.device)
   CMD_START                          (audio.device)
   CMD_START                          (narrator.device)
   CMD_START                          (parallel.device)
   CMD_START                          (printer.device)
   CMD_START                          (serial.device)
   CMD_STOP                           (audio.device)
   CMD_STOP                           (narrator.device)
   CMD_STOP                           (parallel.device)
   CMD_STOP                           (printer.device)
   CMD_STOP                           (serial.device)
   CMD_UPDATE                         (audio.device)
   CMD_UPDATE                         (clipboard.device)
   CMD_UPDATE                         (trackdisk.device)
   CMD_WRITE                          (audio.device)
   CMD_WRITE                          (clipboard.device)
   CMD_WRITE                          (console.device)
   CMD_WRITE                          (narrator.device)
   CMD_WRITE                          (parallel.device)
   CMD_WRITE                          (printer.device)
   CMD_WRITE                          (serial.device)
   CMD_WRITE                          (trackdisk.device)
   CMOVE                              (graphics.library)
   CmpTime()                          (timer.device)
   CoerceMethod()                     (amiga_lib.library)
   CoerceMethodA()                    (amiga_lib.library)
   ColdReboot()                       (exec.library)
   CollectionChunk()                  (iffparse.library)
   CollectionChunks()                 (iffparse.library)
   CompareDates()                     (dos.library)
   ConfigBoard()                      (expansion.library)
   CopyMem()                          (exec.library)
   CopyMemQuick()                     (exec.library)
   CopySBitMap()                      (graphics.library)
   CreateArgstring()                  (rexxsyslib.library)
   CreateBehindHookLayer()            (layers.library)
   CreateBehindLayer()                (layers.library)
   CreateContext()                    (gadtools.library)
   CreateCxObj()                      (commodities.library)
   CreateDir()                        (dos.library)
   CreateExtIO()                      (amiga_lib.library)
   CreateGadgetA()                    (gadtools.library)
   CreateIORequest()                  (exec.library)
   CreateMenusA()                     (gadtools.library)
   CreateMsgPort()                    (exec.library)
   CreateNewProc()                    (dos.library)
   CreatePort()                       (amiga_lib.library)
   CreateProc()                       (dos.library)
   CreateRexxMsg()                    (rexxsyslib.library)
   CreateStdIO()                      (amiga_lib.library)
   CreateTask()                       (amiga_lib.library)
   CreateUpfrontHookLayer()           (layers.library)
   CreateUpfrontLayer()               (layers.library)
   CurrentChunk()                     (iffparse.library)
   CurrentDir()                       (dos.library)
   CurrentTime()                      (intuition.library)
   CWAIT                              (graphics.library)
   CxBroker()                         (commodities.library)
   CxCustom()                         (amiga_lib.library)
   CxDebug()                          (amiga_lib.library)
   CxFilter()                         (amiga_lib.library)
   CxMsgData()                        (commodities.library)
   CxMsgID()                          (commodities.library)
   CxMsgType()                        (commodities.library)
   CxObjError()                       (commodities.library)
   CxObjType()                        (commodities.library)
   CxSender()                         (amiga_lib.library)
   CxSignal()                         (amiga_lib.library)
   CxTranslate()                      (amiga_lib.library)

   Date2Amiga()                       (utility.library)
   DateStamp()                        (dos.library)
   DateToStr()                        (dos.library)
   dbf()                              (amiga_lib.library)
   DDoFmt()                           (ddebug_lib.library)
   Deallocate()                       (exec.library)
   Debug()                            (exec.library)
   Delay()                            (dos.library)
   DeleteArgstring()                  (rexxsyslib.library)
   DeleteCxObj()                      (commodities.library)
   DeleteCxObjAll()                   (commodities.library)
   DeleteDiskObject()                 (icon.library)
   DeleteExtIO()                      (amiga_lib.library)
   DeleteFile()                       (dos.library)
   DeleteIORequest()                  (exec.library)
   DeleteLayer()                      (layers.library)
   DeleteMsgPort()                    (exec.library)
   DeletePort()                       (amiga_lib.library)
   DeleteRexxMsg()                    (rexxsyslib.library)
   DeleteStdIO()                      (amiga_lib.library)
   DeleteTask()                       (amiga_lib.library)
   DeleteVar()                        (dos.library)
   DeviceProc()                       (dos.library)
   DGetChar()                         (ddebug_lib.library)
   DGetNum()                          (ddebug_lib.library)
   Disable()                          (exec.library)
   DisownBlitter()                    (graphics.library)
   DisplayAlert()                     (intuition.library)
   DisplayBeep()                      (intuition.library)
   DisposeCxMsg()                     (commodities.library)
   DisposeFontContents()              (diskfont.library)
   DisposeLayerInfo()                 (layers.library)
   DisposeObject()                    (intuition.library)
   DisposeRegion()                    (graphics.library)
   DivertCxMsg()                      (commodities.library)
   DMayGetChar()                      (ddebug_lib.library)
   DoCollision()                      (graphics.library)
   DoIO()                             (exec.library)
   DoMethod()                         (amiga_lib.library)
   DoMethodA()                        (amiga_lib.library)
   DoPkt()                            (dos.library)
   DoSuperMethod()                    (amiga_lib.library)
   DoSuperMethodA()                   (amiga_lib.library)
   DoubleClick()                      (intuition.library)
   DPutChar()                         (ddebug_lib.library)
   DPutFmt()                          (ddebug_lib.library)
   DPutStr()                          (ddebug_lib.library)
   Draw()                             (graphics.library)
   DrawBevelBoxA()                    (gadtools.library)
   DrawBorder()                       (intuition.library)
   DrawEllipse()                      (graphics.library)
   DrawGList()                        (graphics.library)
   DrawImage()                        (intuition.library)
   DrawImageState()                   (intuition.library)
   DupLock()                          (dos.library)
   DupLockFromFH()                    (dos.library)

   EasyRequestArgs()                  (intuition.library)
   Enable()                           (exec.library)
   EndNotify()                        (dos.library)
   EndRefresh()                       (intuition.library)
   EndRequest()                       (intuition.library)
   EndUpdate()                        (layers.library)
   Enqueue()                          (exec.library)
   EnqueueCxObj()                     (commodities.library)
   EntryHandler()                     (iffparse.library)
   EraseImage()                       (intuition.library)
   EraseRect()                        (graphics.library)
   ErrorReport()                      (dos.library)
   ExAll()                            (dos.library)
   Examine()                          (dos.library)
   ExamineFH()                        (dos.library)
   Execute()                          (dos.library)
   Exit()                             (dos.library)
   ExitHandler()                      (iffparse.library)
   ExNext()                           (dos.library)
   Expunge()                          (audio.device)
   ExtendFont()                       (graphics.library)

   FastRand()                         (amiga_lib.library)
   FattenLayerInfo()                  (layers.library)
   Fault()                            (dos.library)
   FGetC()                            (dos.library)
   FGets()                            (dos.library)
   FilePart()                         (dos.library)
   FillRexxMsg()                      (rexxsyslib.library)
   FilterTagChanges()                 (utility.library)
   FilterTagItems()                   (utility.library)
   FindArg()                          (dos.library)
   FindCliProc()                      (dos.library)
   FindCollection()                   (iffparse.library)
   FindConfigDev()                    (expansion.library)
   FindDisplayInfo()                  (graphics.library)
   FindDosEntry()                     (dos.library)
   FindLocalItem()                    (iffparse.library)
   FindName()                         (exec.library)
   FindPort()                         (exec.library)
   FindProp()                         (iffparse.library)
   FindPropContext()                  (iffparse.library)
   FindResident()                     (exec.library)
   FindSegment()                      (dos.library)
   FindSemaphore()                    (exec.library)
   FindTagItem()                      (utility.library)
   FindTask()                         (exec.library)
   FindToolType()                     (icon.library)
   FindVar()                          (dos.library)
   Flood()                            (graphics.library)
   Flush()                            (dos.library)
   FontExtent()                       (graphics.library)
   Forbid()                           (exec.library)
   Format()                           (dos.library)
   fpa()                              (amiga_lib.library)
   FPutC()                            (dos.library)
   FPuts()                            (dos.library)
   FRead()                            (dos.library)
   FreeArgs()                         (dos.library)
   FreeAslRequest()                   (asl.library)
   FreeClass()                        (intuition.library)
   FreeColorMap()                     (graphics.library)
   FreeConfigDev()                    (expansion.library)
   FreeCopList()                      (graphics.library)
   FreeCprList()                      (graphics.library)
   FreeDeviceProc()                   (dos.library)
   FreeDiskObject()                   (icon.library)
   FreeDosEntry()                     (dos.library)
   FreeDosObject()                    (dos.library)
   FreeEntry()                        (exec.library)
   FreeExpansionMem()                 (expansion.library)
   FreeFileRequest()                  (asl.library)
   FreeFreeList()                     (icon.library)
   FreeGadgets()                      (gadtools.library)
   FreeGBuffers()                     (graphics.library)
   FreeIEvents()                      (amiga_lib.library)
   FreeIFF()                          (iffparse.library)
   FreeLocalItem()                    (iffparse.library)
   FreeMem()                          (exec.library)
   FreeMenus()                        (gadtools.library)
   FreeMiscResource()                 (misc.resource)
   FreePotBits()                      (potgo.resource)
   FreeRaster()                       (graphics.library)
   FreeRemember()                     (intuition.library)
   FreeScreenDrawInfo()               (intuition.library)
   FreeSignal()                       (exec.library)
   FreeSprite()                       (graphics.library)
   FreeSysRequest()                   (intuition.library)
   FreeTagItems()                     (utility.library)
   FreeTrap()                         (exec.library)
   FreeUnit()                         (disk.resource)
   FreeVec()                          (exec.library)
   FreeVisualInfo()                   (gadtools.library)
   FreeVPortCopLists()                (graphics.library)
   FWrite()                           (dos.library)

   GadgetMouse()                      (intuition.library)
   GetArgStr()                        (dos.library)
   GetAttr()                          (intuition.library)
   GetCC()                            (exec.library)
   GetColorMap()                      (graphics.library)
   GetConsoleTask()                   (dos.library)
   GetCurrentBinding()                (expansion.library)
   GetCurrentDirName()                (dos.library)
   GetDefaultPubScreen()              (intuition.library)
   GetDefDiskObject()                 (icon.library)
   GetDefPrefs()                      (intuition.library)
   GetDeviceProc()                    (dos.library)
   GetDiskObject()                    (icon.library)
   GetDiskObjectNew()                 (icon.library)
   GetDisplayInfoData()               (graphics.library)
   GetFileSysTask()                   (dos.library)
   GetGBuffers()                      (graphics.library)
   GetMsg()                           (exec.library)
   GetPrefs()                         (intuition.library)
   GetProgramDir()                    (dos.library)
   GetProgramName()                   (dos.library)
   GetPrompt()                        (dos.library)
   GetRexxVar()                       (amiga_lib.library)
   GetRGB4()                          (graphics.library)
   GetScreenData()                    (intuition.library)
   GetScreenDrawInfo()                (intuition.library)
   GetSprite()                        (graphics.library)
   GetSysTime()                       (timer.device)
   GetTagData()                       (utility.library)
   GetUnit()                          (disk.resource)
   GetUnitID()                        (disk.resource)
   GetVar()                           (dos.library)
   GetVisualInfoA()                   (gadtools.library)
   GetVPModeID()                      (graphics.library)
   GfxAssociate()                     (graphics.library)
   GfxFree()                          (graphics.library)
   GfxLookUP()                        (graphics.library)
   GfxNew()                           (graphics.library)
   GiveUnit()                         (disk.resource)
   GoodID()                           (iffparse.library)
   GoodType()                         (iffparse.library)
   GPD_ASKCTYPE                       (gameport.device)
   GPD_ASKTRIGGER                     (gameport.device)
   GPD_READEVENT                      (gameport.device)
   GPD_SETCTYPE                       (gameport.device)
   GPD_SETTRIGGER                     (gameport.device)
   GT_BeginRefresh()                  (gadtools.library)
   GT_EndRefresh()                    (gadtools.library)
   GT_FilterIMsg()                    (gadtools.library)
   GT_GetIMsg()                       (gadtools.library)
   GT_PostFilterIMsg()                (gadtools.library)
   GT_RefreshWindow()                 (gadtools.library)
   GT_ReplyIMsg()                     (gadtools.library)
   GT_SetGadgetAttrsA()               (gadtools.library)

   HookEntry()                        (amiga_lib.library)
   HookEntry()                        (iffparse.library)
   HotKey()                           (amiga_lib.library)

   IDtoStr()                          (iffparse.library)
   IEEEDPAbs()                        (mathieeedoubbas.library)
   IEEEDPAcos()                       (mathieeedoubtrans.library)
   IEEEDPAdd()                        (mathieeedoubbas.library)
   IEEEDPAsin()                       (mathieeedoubtrans.library)
   IEEEDPAtan()                       (mathieeedoubtrans.library)
   IEEEDPCeil()                       (mathieeedoubbas.library)
   IEEEDPCmp()                        (mathieeedoubbas.library)
   IEEEDPCos()                        (mathieeedoubtrans.library)
   IEEEDPCosh()                       (mathieeedoubtrans.library)
   IEEEDPDiv()                        (mathieeedoubbas.library)
   IEEEDPExp()                        (mathieeedoubtrans.library)
   IEEEDPFieee()                      (mathieeedoubtrans.library)
   IEEEDPFix()                        (mathieeedoubbas.library)
   IEEEDPFloor()                      (mathieeedoubbas.library)
   IEEEDPFlt()                        (mathieeedoubbas.library)
   IEEEDPLog()                        (mathieeedoubtrans.library)
   IEEEDPLog10()                      (mathieeedoubtrans.library)
   IEEEDPMul()                        (mathieeedoubbas.library)
   IEEEDPNeg()                        (mathieeedoubbas.library)
   IEEEDPPow()                        (mathieeedoubtrans.library)
   IEEEDPSin()                        (mathieeedoubtrans.library)
   IEEEDPSincos()                     (mathieeedoubtrans.library)
   IEEEDPSinh()                       (mathieeedoubtrans.library)
   IEEEDPSqrt()                       (mathieeedoubtrans.library)
   IEEEDPSub()                        (mathieeedoubbas.library)
   IEEEDPTan()                        (mathieeedoubtrans.library)
   IEEEDPTanh()                       (mathieeedoubtrans.library)
   IEEEDPTieee()                      (mathieeedoubtrans.library)
   IEEEDPTst()                        (mathieeedoubbas.library)
   IEEESPAbs()                        (mathieeesingbas.library)
   IEEESPAcos()                       (mathieeesingtrans.library)
   IEEESPAdd()                        (mathieeesingbas.library)
   IEEESPAsin()                       (mathieeesingtrans.library)
   IEEESPAtan()                       (mathieeesingtrans.library)
   IEEESPCeil()                       (mathieeesingbas.library)
   IEEESPCmp()                        (mathieeesingbas.library)
   IEEESPCos()                        (mathieeesingtrans.library)
   IEEESPCosh()                       (mathieeesingtrans.library)
   IEEESPDiv()                        (mathieeesingbas.library)
   IEEESPExp()                        (mathieeesingtrans.library)
   IEEESPFieee()                      (mathieeesingtrans.library)
   IEEESPFix()                        (mathieeesingbas.library)
   IEEESPFloor()                      (mathieeesingbas.library)
   IEEESPFlt()                        (mathieeesingbas.library)
   IEEESPLog()                        (mathieeesingtrans.library)
   IEEESPLog10()                      (mathieeesingtrans.library)
   IEEESPMul()                        (mathieeesingbas.library)
   IEEESPNeg()                        (mathieeesingbas.library)
   IEEESPPow()                        (mathieeesingtrans.library)
   IEEESPSin()                        (mathieeesingtrans.library)
   IEEESPSincos()                     (mathieeesingtrans.library)
   IEEESPSinh()                       (mathieeesingtrans.library)
   IEEESPSqrt()                       (mathieeesingtrans.library)
   IEEESPSub()                        (mathieeesingbas.library)
   IEEESPTan()                        (mathieeesingtrans.library)
   IEEESPTanh()                       (mathieeesingtrans.library)
   IEEESPTieee()                      (mathieeesingtrans.library)
   IEEESPTst()                        (mathieeesingbas.library)
   IND_ADDHANDLER                     (input.device)
   IND_REMHANDLER                     (input.device)
   IND_SETMPORT                       (input.device)
   IND_SETMTRIG                       (input.device)
   IND_SETMTYPE                       (input.device)
   IND_SETPERIOD                      (input.device)
   IND_SETTHRESH                      (input.device)
   IND_WRITEEVENT                     (input.device)
   Info()                             (dos.library)
   Inhibit()                          (dos.library)
   InitArea()                         (graphics.library)
   InitBitMap()                       (graphics.library)
   InitCode()                         (exec.library)
   InitGels()                         (graphics.library)
   InitGMasks()                       (graphics.library)
   InitIFF()                          (iffparse.library)
   InitIFFasClip()                    (iffparse.library)
   InitIFFasDOS()                     (iffparse.library)
   InitLayers()                       (layers.library)
   InitMasks()                        (graphics.library)
   InitRastPort()                     (graphics.library)
   InitRequester()                    (intuition.library)
   InitResident()                     (exec.library)
   InitSemaphore()                    (exec.library)
   InitStruct()                       (exec.library)
   InitTmpRas()                       (graphics.library)
   InitView()                         (graphics.library)
   InitVPort()                        (graphics.library)
   Input()                            (dos.library)
   Insert()                           (exec.library)
   InsertCxObj()                      (commodities.library)
   InstallClipRegion()                (layers.library)
   InstallLayerHook()                 (layers.library)
   InternalLoadSeg()                  (dos.library)
   InternalUnLoadSeg()                (dos.library)
   IntuiTextLength()                  (intuition.library)
   InvertKeyMap()                     (commodities.library)
   InvertString()                     (amiga_lib.library)
   IoErr()                            (dos.library)
   IsFileSystem()                     (dos.library)
   IsInteractive()                    (dos.library)
   IsRexxMsg()                        (rexxsyslib.library)
   ItemAddress()                      (intuition.library)

   KBD_ADDRESETHANDLER                (keyboard.device)
   KBD_READEVENT                      (keyboard.device)
   KBD_READMATRIX                     (keyboard.device)
   KBD_REMRESETHANDLER                (keyboard.device)
   KBD_RESETHANDLERDONE               (keyboard.device)
   KCmpStr()                          (ddebug_lib.library)
   KCmpStr()                          (debug_lib.library)
   KGetChar()                         (debug_lib.library)
   KGetNum()                          (debug_lib.library)
   KMayGetChar()                      (debug_lib.library)
   KPrintF()                          (debug_lib.library)
   KPutChar()                         (debug_lib.library)
   KPutStr()                          (debug_lib.library)

   LayoutMenuItemsA()                 (gadtools.library)
   LayoutMenusA()                     (gadtools.library)
   LengthArgstring()                  (rexxsyslib.library)
   LoadRGB4()                         (graphics.library)
   LoadSeg()                          (dos.library)
   LoadView()                         (graphics.library)
   LocalItemData()                    (iffparse.library)
   Lock()                             (dos.library)
   LockDosList()                      (dos.library)
   LockIBase()                        (intuition.library)
   LockLayer()                        (layers.library)
   LockLayerInfo()                    (layers.library)
   LockLayerRom()                     (graphics.library)
   LockLayers()                       (layers.library)
   LockPubScreen()                    (intuition.library)
   LockPubScreenList()                (intuition.library)
   LockRecord()                       (dos.library)
   LockRecords()                      (dos.library)
   LockRexxBase()                     (rexxsyslib.library)

   MakeClass()                        (intuition.library)
   MakeDosEntry()                     (dos.library)
   MakeDosNode()                      (expansion.library)
   MakeFunctions()                    (exec.library)
   MakeLibrary()                      (exec.library)
   MakeLink()                         (dos.library)
   MakeScreen()                       (intuition.library)
   MakeVPort()                        (graphics.library)
   MapANSI()                          (keymap.library)
   MapRawKey()                        (keymap.library)
   MapTags()                          (utility.library)
   MatchEnd()                         (dos.library)
   MatchFirst()                       (dos.library)
   MatchNext()                        (dos.library)
   MatchPattern()                     (dos.library)
   MatchPatternNoCase()               (dos.library)
   MatchToolValue()                   (icon.library)
   MaxCli()                           (dos.library)
   ModeNotAvailable()                 (graphics.library)
   ModifyIDCMP()                      (intuition.library)
   ModifyProp()                       (intuition.library)
   Move()                             (graphics.library)
   MoveLayer()                        (layers.library)
   MoveLayerInFrontOf()               (layers.library)
   MoveScreen()                       (intuition.library)
   MoveSizeLayer()                    (layers.library)
   MoveSprite()                       (graphics.library)
   MoveWindow()                       (intuition.library)
   MoveWindowInFrontOf()              (intuition.library)
   MrgCop()                           (graphics.library)

   NameFromFH()                       (dos.library)
   NameFromLock()                     (dos.library)
   NewFontContents()                  (diskfont.library)
   NewLayerInfo()                     (layers.library)
   NewList()                          (amiga_lib.library)
   NewLoadSeg()                       (dos.library)
   NewModifyProp()                    (intuition.library)
   NewObject()                        (intuition.library)
   NewRegion()                        (graphics.library)
   NewScaledDiskFont()                (diskfont.library)
   NextDisplayInfo()                  (graphics.library)
   NextDosEntry()                     (dos.library)
   NextObject()                       (intuition.library)
   NextPubScreen()                    (intuition.library)
   NextTagItem()                      (utility.library)

   ObtainBattSemaphore()              (battmem.resource)
   ObtainConfigBinding()              (expansion.library)
   ObtainGIRPort()                    (intuition.library)
   ObtainSemaphore()                  (exec.library)
   ObtainSemaphoreList()              (exec.library)
   ObtainSemaphoreShared()            (exec.library)
   OffGadget()                        (intuition.library)
   OffMenu()                          (intuition.library)
   OldOpenLibrary()                   (exec.library)
   OnGadget()                         (intuition.library)
   OnMenu()                           (intuition.library)
   Open()                             (dos.library)
   OpenClipboard()                    (iffparse.library)
   OpenDevice()                       (audio.device)
   OpenDevice()                       (console.device)
   OpenDevice()                       (exec.library)
   OpenDevice()                       (narrator.device)
   OpenDevice()                       (parallel.device)
   OpenDevice()                       (serial.device)
   OpenDiskFont()                     (diskfont.library)
   OpenFont()                         (graphics.library)
   OpenFromLock()                     (dos.library)
   OpenIFF()                          (iffparse.library)
   OpenLibrary()                      (exec.library)
   OpenMonitor()                      (graphics.library)
   OpenResource()                     (exec.library)
   OpenScreen()                       (intuition.library)
   OpenScreenTagList()                (intuition.library)
   OpenWindow()                       (intuition.library)
   OpenWindowTagList()                (intuition.library)
   OpenWorkBench()                    (intuition.library)
   OrRectRegion()                     (graphics.library)
   OrRegionRegion()                   (graphics.library)
   Output()                           (dos.library)
   OwnBlitter()                       (graphics.library)

   PackBoolTags()                     (utility.library)
   ParentChunk()                      (iffparse.library)
   ParentDir()                        (dos.library)
   ParentOfFH()                       (dos.library)
   ParseIFF()                         (iffparse.library)
   ParseIX()                          (commodities.library)
   ParsePattern()                     (dos.library)
   ParsePatternNoCase()               (dos.library)
   PathPart()                         (dos.library)
   PDCMD_QUERY                        (parallel.device)
   PDCMD_SETPARAMS                    (parallel.device)
   PeekQualifier()                    (input.device)
   Permit()                           (exec.library)
   PointInImage()                     (intuition.library)
   PolyDraw()                         (graphics.library)
   PopChunk()                         (iffparse.library)
   PRD_DUMPRPORT                      (printer.device)
   PRD_PRTCOMMAND                     (printer.device)
   PRD_QUERY                          (printer.device)
   PRD_RAWWRITE                       (printer.device)
   printf()                           (amiga_lib.library)
   PrintFault()                       (dos.library)
   PrintIText()                       (intuition.library)
   Procure()                          (exec.library)
   PropChunk()                        (iffparse.library)
   PropChunks()                       (iffparse.library)
   PubScreenStatus()                  (intuition.library)
   PushChunk()                        (iffparse.library)
   PutDefDiskObject()                 (icon.library)
   PutDiskObject()                    (icon.library)
   PutMsg()                           (exec.library)
   PutStr()                           (dos.library)
   PWrite()                           (printer.device)

   QBlit()                            (graphics.library)
   QBSBlit()                          (graphics.library)
   QueryOverscan()                    (intuition.library)

   RangeRand()                        (amiga_lib.library)
   RawDoFmt()                         (exec.library)
   RawKeyConvert()                    (console.device)
   Read()                             (dos.library)
   ReadArgs()                         (dos.library)
   ReadBattClock()                    (battclock.resource)
   ReadBattMem()                      (battmem.resource)
   ReadChunkBytes()                   (iffparse.library)
   ReadChunkRecords()                 (iffparse.library)
   ReadEClock()                       (timer.device)
   ReadExpansionByte()                (expansion.library)
   ReadExpansionRom()                 (expansion.library)
   ReadItem()                         (dos.library)
   ReadLink()                         (dos.library)
   ReadPixel()                        (graphics.library)
   ReadPixelArray8()                  (graphics.library)
   ReadPixelLine8()                   (graphics.library)
   ReadUnitID()                       (disk.resource)
   RectFill()                         (graphics.library)
   RefreshGadgets()                   (intuition.library)
   RefreshGList()                     (intuition.library)
   RefreshTagItemClones()             (utility.library)
   RefreshWindowFrame()               (intuition.library)
   Relabel()                          (dos.library)
   ReleaseBattSemaphore()             (battmem.resource)
   ReleaseConfigBinding()             (expansion.library)
   ReleaseGIRPort()                   (intuition.library)
   ReleaseSemaphore()                 (exec.library)
   ReleaseSemaphoreList()             (exec.library)
   RemakeDisplay()                    (intuition.library)
   RemAssignList()                    (dos.library)
   RemBob()                           (graphics.library)
   RemConfigDev()                     (expansion.library)
   RemDevice()                        (exec.library)
   RemDosEntry()                      (dos.library)
   RemFont()                          (graphics.library)
   RemHead()                          (exec.library)
   RemIBob()                          (graphics.library)
   RemICRVector()                     (cia.resource)
   RemIntServer()                     (exec.library)
   RemLibrary()                       (exec.library)
   Remove()                           (exec.library)
   RemoveAppIcon()                    (wb.library)
   RemoveAppMenuItem()                (wb.library)
   RemoveAppWindow()                  (wb.library)
   RemoveClass()                      (intuition.library)
   RemoveCxObj()                      (commodities.library)
   RemoveGadget()                     (intuition.library)
   RemoveGList()                      (intuition.library)
   RemPort()                          (exec.library)
   RemResource()                      (exec.library)
   RemSegment()                       (dos.library)
   RemSemaphore()                     (exec.library)
   RemTail()                          (exec.library)
   RemTask()                          (exec.library)
   RemTOF()                           (amiga_lib.library)
   RemVSprite()                       (graphics.library)
   Rename()                           (dos.library)
   ReplyMsg()                         (exec.library)
   ReplyPkt()                         (dos.library)
   ReportMouse()                      (intuition.library)
   Request()                          (intuition.library)
   RequestFile()                      (asl.library)
   ResetBattClock()                   (battclock.resource)
   ResetMenuStrip()                   (intuition.library)
   RethinkDisplay()                   (intuition.library)
   RouteCxMsg()                       (commodities.library)
   RunCommand()                       (dos.library)

   SameDevice()                       (dos.library)
   SameLock()                         (dos.library)
   ScalerDiv()                        (graphics.library)
   ScreenToBack()                     (intuition.library)
   ScreenToFront()                    (intuition.library)
   ScrollLayer()                      (layers.library)
   ScrollRaster()                     (graphics.library)
   ScrollVPort()                      (graphics.library)
   SDCMD_BREAK                        (serial.device)
   SDCMD_QUERY                        (serial.device)
   SDCMD_SETPARAMS                    (serial.device)
   SDivMod32()                        (utility.library)
   Seek()                             (dos.library)
   SelectInput()                      (dos.library)
   SelectOutput()                     (dos.library)
   SendIO()                           (exec.library)
   SendPkt()                          (dos.library)
   SetAPen()                          (graphics.library)
   SetArgStr()                        (dos.library)
   SetAttrsA()                        (intuition.library)
   SetBPen()                          (graphics.library)
   SetCollision()                     (graphics.library)
   SetComment()                       (dos.library)
   SetConsoleTask()                   (dos.library)
   SetCurrentBinding()                (expansion.library)
   SetCurrentDirName()                (dos.library)
   SetCxObjPri()                      (commodities.library)
   SetDefaultPubScreen()              (intuition.library)
   SetDMRequest()                     (intuition.library)
   SetDrMd()                          (graphics.library)
   SetEditHook()                      (intuition.library)
   SetExcept()                        (exec.library)
   SetFileDate()                      (dos.library)
   SetFileSize()                      (dos.library)
   SetFileSysTask()                   (dos.library)
   SetFilter()                        (commodities.library)
   SetFilterIX()                      (commodities.library)
   SetFont()                          (graphics.library)
   SetFunction()                      (exec.library)
   SetGadgetAttrsA()                  (intuition.library)
   SetICR()                           (cia.resource)
   SetIntVector()                     (exec.library)
   SetIoErr()                         (dos.library)
   SetKeyMapDefault()                 (keymap.library)
   SetLocalItemPurge()                (iffparse.library)
   SetMenuStrip()                     (intuition.library)
   SetMode()                          (dos.library)
   SetMouseQueue()                    (intuition.library)
   SetOPen()                          (graphics.library)
   SetPointer()                       (intuition.library)
   SetPrefs()                         (intuition.library)
   SetProgramDir()                    (dos.library)
   SetProgramName()                   (dos.library)
   SetPrompt()                        (dos.library)
   SetProtection()                    (dos.library)
   SetPubScreenModes()                (intuition.library)
   SetRast()                          (graphics.library)
   SetRexxVar()                       (amiga_lib.library)
   SetRGB4()                          (graphics.library)
   SetRGB4CM()                        (graphics.library)
   SetSignal()                        (exec.library)
   SetSoftStyle()                     (graphics.library)
   SetSR()                            (exec.library)
   SetSuperAttrs()                    (amiga_lib.library)
   SetTaskPri()                       (exec.library)
   SetTranslate()                     (commodities.library)
   SetVar()                           (dos.library)
   SetVBuf()                          (dos.library)
   SetWindowTitles()                  (intuition.library)
   ShowTitle()                        (intuition.library)
   Signal()                           (exec.library)
   SizeLayer()                        (layers.library)
   SizeWindow()                       (intuition.library)
   SMult32()                          (utility.library)
   SortGList()                        (graphics.library)
   SPAbs()                            (mathffp.library)
   SPAcos()                           (mathtrans.library)
   SPAdd()                            (mathffp.library)
   SPAsin()                           (mathtrans.library)
   SPAtan()                           (mathtrans.library)
   SPCeil()                           (mathffp.library)
   SPCmp()                            (mathffp.library)
   SPCos()                            (mathtrans.library)
   SPCosh()                           (mathtrans.library)
   SPDiv()                            (mathffp.library)
   SPExp()                            (mathtrans.library)
   SPFieee()                          (mathtrans.library)
   SPFix()                            (mathffp.library)
   SPFloor()                          (mathffp.library)
   SPFlt()                            (mathffp.library)
   SplitName()                        (dos.library)
   SPLog()                            (mathtrans.library)
   SPLog10()                          (mathtrans.library)
   SPMul()                            (mathffp.library)
   SPNeg()                            (mathffp.library)
   SPPow()                            (mathtrans.library)
   sprintf()                          (amiga_lib.library)
   SPSin()                            (mathtrans.library)
   SPSincos()                         (mathtrans.library)
   SPSinh()                           (mathtrans.library)
   SPSqrt()                           (mathtrans.library)
   SPSub()                            (mathffp.library)
   SPTan()                            (mathtrans.library)
   SPTanh()                           (mathtrans.library)
   SPTieee()                          (mathtrans.library)
   SPTst()                            (mathffp.library)
   StackSwap()                        (exec.library)
   StartNotify()                      (dos.library)
   stdio()                            (amiga_lib.library)
   StopChunk()                        (iffparse.library)
   StopChunks()                       (iffparse.library)
   StopOnExit()                       (iffparse.library)
   StoreItemInContext()               (iffparse.library)
   StoreLocalItem()                   (iffparse.library)
   Stricmp()                          (utility.library)
   StripFont()                        (graphics.library)
   Strnicmp()                         (utility.library)
   StrToDate()                        (dos.library)
   StrToLong()                        (dos.library)
   SubTime()                          (timer.device)
   SumKickData()                      (exec.library)
   SumLibrary()                       (exec.library)
   SuperState()                       (exec.library)
   Supervisor()                       (exec.library)
   SwapBitsRastPortClipRect()         (layers.library)
   SyncSBitMap()                      (graphics.library)
   SysReqHandler()                    (intuition.library)
   SystemTagList()                    (dos.library)
   TagInArray()                       (utility.library)

   TD_ADDCHANGEINT                    (trackdisk.device)
   TD_CHANGENUM                       (trackdisk.device)
   TD_CHANGESTATE                     (trackdisk.device)
   TD_EJECT                           (trackdisk.device)
   TD_FORMAT                          (trackdisk.device)
   TD_GETDRIVETYPE                    (trackdisk.device)
   TD_GETGEOMETRY                     (trackdisk.device)
   TD_GETNUMTRACKS                    (trackdisk.device)
   TD_MOTOR                           (trackdisk.device)
   TD_PROTSTATUS                      (trackdisk.device)
   TD_RAWREAD                         (trackdisk.device)
   TD_RAWWRITE                        (trackdisk.device)
   TD_REMCHANGEINT                    (trackdisk.device)
   TD_SEEK                            (trackdisk.device)
   Text()                             (graphics.library)
   TextExtent()                       (graphics.library)
   TextFit()                          (graphics.library)
   TextLength()                       (graphics.library)
   ThinLayerInfo()                    (layers.library)
   TimeDelay()                        (amiga_lib.library)
   ToLower()                          (utility.library)
   ToUpper()                          (utility.library)
   Translate()                        (translator.library)
   TR_ADDREQUEST                      (timer.device)
   TR_GETSYSTIME                      (timer.device)
   TR_SETSYSTIME                      (timer.device)
   TypeOfMem()                        (exec.library)

   UDivMod32()                        (utility.library)
   UMult32()                          (utility.library)
   UnGetC()                           (dos.library)
   UnLoadSeg()                        (dos.library)
   UnLock()                           (dos.library)
   UnLockDosList()                    (dos.library)
   UnlockIBase()                      (intuition.library)
   UnlockLayer()                      (layers.library)
   UnlockLayerInfo()                  (layers.library)
   UnlockLayerRom()                   (graphics.library)
   UnlockLayers()                     (layers.library)
   UnlockPubScreen()                  (intuition.library)
   UnlockPubScreenList()              (intuition.library)
   UnLockRecord()                     (dos.library)
   UnLockRecords()                    (dos.library)
   UnlockRexxBase()                   (rexxsyslib.library)
   UpfrontLayer()                     (layers.library)
   UserState()                        (exec.library)

   Vacate()                           (exec.library)
   VBeamPos()                         (graphics.library)
   VFPrintf()                         (dos.library)
   VFWritef()                         (dos.library)
   VideoControl()                     (graphics.library)
   ViewAddress()                      (intuition.library)
   ViewPortAddress()                  (intuition.library)
   VPrintf()                          (dos.library)

   Wait()                             (exec.library)
   WaitBlit()                         (graphics.library)
   WaitBOVP()                         (graphics.library)
   WaitForChar()                      (dos.library)
   WaitIO()                           (exec.library)
   WaitPkt()                          (dos.library)
   WaitPort()                         (exec.library)
   WaitTOF()                          (graphics.library)
   WBenchToBack()                     (intuition.library)
   WBenchToFront()                    (intuition.library)
   WeighTAMatch()                     (graphics.library)
   WhichLayer()                       (layers.library)
   WindowLimits()                     (intuition.library)
   WindowToBack()                     (intuition.library)
   WindowToFront()                    (intuition.library)
   Write()                            (dos.library)
   WriteBattClock()                   (battclock.resource)
   WriteBattMem()                     (battmem.resource)
   WriteChars()                       (dos.library)
   WriteChunkBytes()                  (iffparse.library)
   WriteChunkRecords()                (iffparse.library)
   WriteExpansionByte()               (expansion.library)
   WritePixel()                       (graphics.library)
   WritePixelArray8()                 (graphics.library)
   WritePixelLine8()                  (graphics.library)
   WritePotgo()                       (potgo.resource)

   XorRectRegion()                    (graphics.library)
   XorRegionRegion()                  (graphics.library)

   ZipWindow()                        (intuition.library)


References/Function.offs

***************** asl
* "asl.library"
##base _AslBase
##bias 30
##public
*--- functions in V36 or higher (distributed as Release 2.0) ---
*
 30 $ffe2 -$001e AllocFileRequest()()
 36 $ffdc -$0024 FreeFileRequest(fileReq)(a0)
 42 $ffd6 -$002a RequestFile(fileReq)(a0)
 48 $ffd0 -$0030 AllocAslRequest(type,tagList)(d0/a0)
 54 $ffca -$0036 FreeAslRequest(request)(a0)
 60 $ffc4 -$003c AslRequest(request,tagList)(a0/a1)
##end

***************** battclock
* "battclock.resource"
##base _BattClockBase
##bias 6
##public
  6 $fffa -$0006 ResetBattClock()()
 12 $fff4 -$000c ReadBattClock()()
 18 $ffee -$0012 WriteBattClock(time)(d0)
##private
 24 $ffe8 -$0018 ReadBattClockMem(offset,length)(d1/d2)
 30 $ffe2 -$001e WriteBattClockMem(data,offset,length)(d0/d1/d2)
##end

***************** battmem
* "battmem.resource"
##base _BattMemBase
##bias 6
##public
  6 $fffa -$0006 ObtainBattSemaphore()()
 12 $fff4 -$000c ReleaseBattSemaphore()()
 18 $ffee -$0012 ReadBattMem(buffer,offset,length)(a0,d0/d1)
 24 $ffe8 -$0018 WriteBattMem(buffer,offset,length)(a0,d0/d1)
##end

***************** cia
* "CiaA.Resource" and "CiaB.Resource"
##bias 6
##public
  6 $fffa -$0006 AddICRVector(resource,iCRBit,interrupt)(a6,d0/a1)
 12 $fff4 -$000c RemICRVector(resource,iCRBit,interrupt)(a6,d0/a1)
 18 $ffee -$0012 AbleICR(resource,mask)(a6,d0)
 24 $ffe8 -$0018 SetICR(resource,mask)(a6,d0)
##end

***************** commodities
* "commodities.library"
##base _CxBase
##bias 30
##public
*--- functions in V36 or higher (distributed as Release 2.0) ---
*
*  OBJECT UTILITIES
*
 30 $ffe2 -$001e CreateCxObj(type,arg1,arg2)(d0/a0/a1)
 36 $ffdc -$0024 CxBroker(nb,error)(a0,d0)
 42 $ffd6 -$002a ActivateCxObj(co,true)(a0,d0)
 48 $ffd0 -$0030 DeleteCxObj(co)(a0)
 54 $ffca -$0036 DeleteCxObjAll(co)(a0)
 60 $ffc4 -$003c CxObjType(co)(a0)
 66 $ffbe -$0042 CxObjError(co)(a0)
 72 $ffb8 -$0048 ClearCxObjError(co)(a0)
 78 $ffb2 -$004e SetCxObjPri(co,pri)(a0,d0)
*
*  OBJECT ATTACHMENT
*
 84 $ffac -$0054 AttachCxObj(headobj,co)(a0/a1)
 90 $ffa6 -$005a EnqueueCxObj(headobj,co)(a0/a1)
 96 $ffa0 -$0060 InsertCxObj(headobj,co,pred)(a0/a1/a2)
102 $ff9a -$0066 RemoveCxObj(co)(a0)
*
*  TYPE SPECIFIC
*
##private
108 $ff94 -$006c FindBroker(name)(a0)
##public
114 $ff8e -$0072 SetTranslate(translator,ie)(a0/a1)
120 $ff88 -$0078 SetFilter(filter,text)(a0/a1)
126 $ff82 -$007e SetFilterIX(filter,ix)(a0/a1)
132 $ff7c -$0084 ParseIX(descr,ix)(a0/a1)
*
*  COMMON MESSAGE
*
138 $ff76 -$008a CxMsgType(cxm)(a0)
144 $ff70 -$0090 CxMsgData(cxm)(a0)
150 $ff6a -$0096 CxMsgID(cxm)(a0)
*
*  MESSAGE ROUTING
*
156 $ff64 -$009c DivertCxMsg(cxm,headobj,ret)(a0/a1/a2)
162 $ff5e -$00a2 RouteCxMsg(cxm,co)(a0/a1)
168 $ff58 -$00a8 DisposeCxMsg(cxm)(a0)
*
*  INPUT EVENT HANDLING
*
174 $ff52 -$00ae InvertKeyMap(ansicode,ie,km)(d0/a0/a1)
180 $ff4c -$00b4 AddIEvents(ie)(a0)
*
* FOR USE ONLY BY CONTROLLER PROGRAM
*
##private
186 $ff46 -$00ba CopyBrokerList(blist)(a0)
192 $ff40 -$00c0 FreeBrokerList(list)(a0)
198 $ff3a -$00c6 BrokerCommand(name,id)(a0,d0)
##public
##end

***************** console
* "console.device"
##base _ConsoleDevice
##bias 42
##public
 42 $ffd6 -$002a CDInputHandler(events,consoleDevice)(a0/a1)
 48 $ffd0 -$0030 RawKeyConvert(events,buffer,length,keyMap)(a0/a1,d1/a2)
##private
*--- functions in V36 or higher (distributed as Release 2.0) ---
 54 $ffca -$0036 GetConSnip()()
 60 $ffc4 -$003c SetConSnip(snip)(a0)
 66 $ffbe -$0042 AddConSnipHook(hook)(a0)
 72 $ffb8 -$0048 RemConSnipHook(hook)(a0)
##end

***************** disk
* "disk.resource"
##base _DiskBase
##bias 6
##public
  6 $fffa -$0006 AllocUnit(unitNum)(d0)
 12 $fff4 -$000c FreeUnit(unitNum)(d0)
 18 $ffee -$0012 GetUnit(unitPointer)(a1)
 24 $ffe8 -$0018 GiveUnit()()
 30 $ffe2 -$001e GetUnitID(unitNum)(d0)
*------ new for V37 ------
 36 $ffdc -$0024 ReadUnitID(unitNum)(d0)
##end

***************** diskfont
* "diskfont.library"
##base _DiskfontBase
##bias 30
##public
 30 $ffe2 -$001e OpenDiskFont(textAttr)(a0)
 36 $ffdc -$0024 AvailFonts(buffer,bufBytes,flags)(a0,d0/d1)
*--- functions in V34 or higher (distributed as Release 1.3) ---
 42 $ffd6 -$002a NewFontContents(fontsLock,fontName)(a0/a1)
 48 $ffd0 -$0030 DisposeFontContents(fontContentsHeader)(a1)
*--- functions in V36 or higher (distributed as Release 2.0) ---
 54 $ffca -$0036 NewScaledDiskFont(sourceFont,destTextAttr)(a0/a1)
##end

***************** dos
* "dos.library"
##base _DOSBase
##bias 30
##public
 30 $ffe2 -$001e Open(name,accessMode)(d1/d2)
 36 $ffdc -$0024 Close(file)(d1)
 42 $ffd6 -$002a Read(file,buffer,length)(d1/d2/d3)
 48 $ffd0 -$0030 Write(file,buffer,length)(d1/d2/d3)
 54 $ffca -$0036 Input()()
 60 $ffc4 -$003c Output()()
 66 $ffbe -$0042 Seek(file,position,offset)(d1/d2/d3)
 72 $ffb8 -$0048 DeleteFile(name)(d1)
 78 $ffb2 -$004e Rename(oldName,newName)(d1/d2)
 84 $ffac -$0054 Lock(name,type)(d1/d2)
 90 $ffa6 -$005a UnLock(lock)(d1)
 96 $ffa0 -$0060 DupLock(lock)(d1)
102 $ff9a -$0066 Examine(lock,fileInfoBlock)(d1/d2)
108 $ff94 -$006c ExNext(lock,fileInfoBlock)(d1/d2)
114 $ff8e -$0072 Info(lock,parameterBlock)(d1/d2)
120 $ff88 -$0078 CreateDir(name)(d1)
126 $ff82 -$007e CurrentDir(lock)(d1)
132 $ff7c -$0084 IoErr()()
138 $ff76 -$008a CreateProc(name,pri,segList,stackSize)(d1/d2/d3/d4)
144 $ff70 -$0090 Exit(returnCode)(d1)
150 $ff6a -$0096 LoadSeg(name)(d1)
156 $ff64 -$009c UnLoadSeg(seglist)(d1)
##private
162 $ff5e -$00a2 ClearVec(bVector,upb)(d1/d2)
168 $ff58 -$00a8 NoReqLoadSeg(bFileName)(d1)
##public
174 $ff52 -$00ae DeviceProc(name)(d1)
180 $ff4c -$00b4 SetComment(name,comment)(d1/d2)
186 $ff46 -$00ba SetProtection(name,protect)(d1/d2)
192 $ff40 -$00c0 DateStamp(date)(d1)
198 $ff3a -$00c6 Delay(timeout)(d1)
204 $ff34 -$00cc WaitForChar(file,timeout)(d1/d2)
210 $ff2e -$00d2 ParentDir(lock)(d1)
216 $ff28 -$00d8 IsInteractive(file)(d1)
222 $ff22 -$00de Execute(string,file,file2)(d1/d2/d3)
*--- functions in V36 or higher (distributed as Release 2.0) ---
*	DOS Object creation/deletion
228 $ff1c -$00e4 AllocDosObject(type,tags)(d1/d2)
234 $ff16 -$00ea FreeDosObject(type,ptr)(d1/d2)
*	Packet Level routines
240 $ff10 -$00f0 DoPkt(port,action,arg1,arg2,arg3,arg4,arg5)
                  (d1/d2/d3/d4/d5/d6/d7)
246 $ff0a -$00f6 SendPkt(dp,port,replyport)(d1/d2/d3)
252 $ff04 -$00fc WaitPkt()()
258 $fefe -$0102 ReplyPkt(dp,res1,res2)(d1/d2/d3)
264 $fef8 -$0108 AbortPkt(port,pkt)(d1/d2)
*	Record Locking
270 $fef2 -$010e LockRecord(fh,offset,length,mode,timeout)(d1/d2/d3/d4/d5)
276 $feec -$0114 LockRecords(recArray,timeout)(d1/d2)
282 $fee6 -$011a UnLockRecord(fh,offset,length)(d1/d2/d3)
288 $fee0 -$0120 UnLockRecords(recArray)(d1)
*	Buffered File I/O
294 $feda -$0126 SelectInput(fh)(d1)
300 $fed4 -$012c SelectOutput(fh)(d1)
306 $fece -$0132 FGetC(fh)(d1)
312 $fec8 -$0138 FPutC(fh,ch)(d1/d2)
318 $fec2 -$013e UnGetC(fh,character)(d1/d2)
324 $febc -$0144 FRead(fh,block,blocklen,number)(d1/d2/d3/d4)
330 $feb6 -$014a FWrite(fh,block,blocklen,number)(d1/d2/d3/d4)
336 $feb0 -$0150 FGets(fh,buf,buflen)(d1/d2/d3)
342 $feaa -$0156 FPuts(fh,str)(d1/d2)
348 $fea4 -$015c VFWritef(fh,format,argarray)(d1/d2/d3)
354 $fe9e -$0162 VFPrintf(fh,format,argarray)(d1/d2/d3)
360 $fe98 -$0168 Flush(fh)(d1)
366 $fe92 -$016e SetVBuf(fh,buff,type,size)(d1/d2/d3/d4)
*	DOS Object Management
372 $fe8c -$0174 DupLockFromFH(fh)(d1)
378 $fe86 -$017a OpenFromLock(lock)(d1)
384 $fe80 -$0180 ParentOfFH(fh)(d1)
390 $fe7a -$0186 ExamineFH(fh,fib)(d1/d2)
396 $fe74 -$018c SetFileDate(name,date)(d1/d2)
402 $fe6e -$0192 NameFromLock(lock,buffer,len)(d1/d2/d3)
408 $fe68 -$0198 NameFromFH(fh,buffer,len)(d1/d2/d3)
414 $fe62 -$019e SplitName(name,seperator,buf,oldpos,size)(d1/d2/d3/d4/d5)
420 $fe5c -$01a4 SameLock(lock1,lock2)(d1/d2)
426 $fe56 -$01aa SetMode(fh,mode)(d1/d2)
432 $fe50 -$01b0 ExAll(lock,buffer,size,data,control)(d1/d2/d3/d4/d5)
438 $fe4a -$01b6 ReadLink(port,lock,path,buffer,size)(d1/d2/d3/d4/d5)
444 $fe44 -$01bc MakeLink(name,dest,soft)(d1/d2/d3)
450 $fe3e -$01c2 ChangeMode(type,fh,newmode)(d1/d2/d3)
456 $fe38 -$01c8 SetFileSize(fh,pos,mode)(d1/d2/d3)
*	Error Handling
462 $fe32 -$01ce SetIoErr(result)(d1)
468 $fe2c -$01d4 Fault(code,header,buffer,len)(d1/d2/d3/d4)
474 $fe26 -$01da PrintFault(code,header)(d1/d2)
480 $fe20 -$01e0 ErrorReport(code,type,arg1,device)(d1/d2/d3/d4)
*--- (1 function slot reserved here) ---
##bias 492
*	Process Management
492 $fe14 -$01ec Cli()()
498 $fe0e -$01f2 CreateNewProc(tags)(d1)
504 $fe08 -$01f8 RunCommand(seg,stack,paramptr,paramlen)(d1/d2/d3/d4)
510 $fe02 -$01fe GetConsoleTask()()
516 $fdfc -$0204 SetConsoleTask(task)(d1)
522 $fdf6 -$020a GetFileSysTask()()
528 $fdf0 -$0210 SetFileSysTask(task)(d1)
534 $fdea -$0216 GetArgStr()()
540 $fde4 -$021c SetArgStr(string)(d1)
546 $fdde -$0222 FindCliProc(num)(d1)
552 $fdd8 -$0228 MaxCli()()
558 $fdd2 -$022e SetCurrentDirName(name)(d1)
564 $fdcc -$0234 GetCurrentDirName(buf,len)(d1/d2)
570 $fdc6 -$023a SetProgramName(name)(d1)
576 $fdc0 -$0240 GetProgramName(buf,len)(d1/d2)
582 $fdba -$0246 SetPrompt(name)(d1)
588 $fdb4 -$024c GetPrompt(buf,len)(d1/d2)
594 $fdae -$0252 SetProgramDir(lock)(d1)
600 $fda8 -$0258 GetProgramDir()()
*	Device List Management
606 $fda2 -$025e SystemTagList(command,tags)(d1/d2)
612 $fd9c -$0264 AssignLock(name,lock)(d1/d2)
618 $fd96 -$026a AssignLate(name,path)(d1/d2)
624 $fd90 -$0270 AssignPath(name,path)(d1/d2)
630 $fd8a -$0276 AssignAdd(name,lock)(d1/d2)
636 $fd84 -$027c RemAssignList(name,lock)(d1/d2)
642 $fd7e -$0282 GetDeviceProc(name,dp)(d1/d2)
648 $fd78 -$0288 FreeDeviceProc(dp)(d1)
654 $fd72 -$028e LockDosList(flags)(d1)
660 $fd6c -$0294 UnLockDosList(flags)(d1)
666 $fd66 -$029a AttemptLockDosList(flags)(d1)
672 $fd60 -$02a0 RemDosEntry(dlist)(d1)
678 $fd5a -$02a6 AddDosEntry(dlist)(d1)
684 $fd54 -$02ac FindDosEntry(dlist,name,flags)(d1/d2/d3)
690 $fd4e -$02b2 NextDosEntry(dlist,flags)(d1/d2)
696 $fd48 -$02b8 MakeDosEntry(name,type)(d1/d2)
702 $fd42 -$02be FreeDosEntry(dlist)(d1)
708 $fd3c -$02c4 IsFileSystem(name)(d1)
*	Handler Interface
714 $fd36 -$02ca Format(filesystem,volumename,dostype)(d1/d2/d3)
720 $fd30 -$02d0 Relabel(drive,newname)(d1/d2)
726 $fd2a -$02d6 Inhibit(name,onoff)(d1/d2)
732 $fd24 -$02dc AddBuffers(name,number)(d1/d2)
*	Date, Time Routines
738 $fd1e -$02e2 CompareDates(date1,date2)(d1/d2)
744 $fd18 -$02e8 DateToStr(datetime)(d1)
750 $fd12 -$02ee StrToDate(datetime)(d1)
*	Image Management
756 $fd0c -$02f4 InternalLoadSeg(fh,table,funcarray,stack)(d0/a0/a1/a2)
762 $fd06 -$02fa InternalUnLoadSeg(seglist,freefunc)(d1/a1)
768 $fd00 -$0300 NewLoadSeg(file,tags)(d1/d2)
774 $fcfa -$0306 AddSegment(name,seg,system)(d1/d2/d3)
780 $fcf4 -$030c FindSegment(name,seg,system)(d1/d2/d3)
786 $fcee -$0312 RemSegment(seg)(d1)
*	Command Support
792 $fce8 -$0318 CheckSignal(mask)(d1)
798 $fce2 -$031e ReadArgs(template,array,args)(d1/d2/d3)
804 $fcdc -$0324 FindArg(keyword,template)(d1/d2)
810 $fcd6 -$032a ReadItem(name,maxchars,cSource)(d1/d2/d3)
816 $fcd0 -$0330 StrToLong(string,value)(d1/d2)
822 $fcca -$0336 MatchFirst(pat,anchor)(d1/d2)
828 $fcc4 -$033c MatchNext(anchor)(d1)
834 $fcbe -$0342 MatchEnd(anchor)(d1)
840 $fcb8 -$0348 ParsePattern(pat,buf,buflen)(d1/d2/d3)
846 $fcb2 -$034e MatchPattern(pat,str)(d1/d2)
##private
* Not currently implemented.
852 $fcac -$0354 DosNameFromAnchor(anchor,buffer,len)(d1/d2/d3)
##public
858 $fca6 -$035a FreeArgs(args)(d1)
*--- (1 function slot reserved here) ---
##bias 870
870 $fc9a -$0366 FilePart(path)(d1)
876 $fc94 -$036c PathPart(path)(d1)
882 $fc8e -$0372 AddPart(dirname,filename,size)(d1/d2/d3)
*	Notification
888 $fc88 -$0378 StartNotify(notify)(d1)
894 $fc82 -$037e EndNotify(notify)(d1)
*	Environment Variable functions
900 $fc7c -$0384 SetVar(name,buffer,size,flags)(d1/d2/d3/d4)
906 $fc76 -$038a GetVar(name,buffer,size,flags)(d1/d2/d3/d4)
912 $fc70 -$0390 DeleteVar(name,flags)(d1/d2)
918 $fc6a -$0396 FindVar(name,type)(d1/d2)
924 $fc64 -$039c CliInit(dp)(a0)
930 $fc5e -$03a2 CliInitNewcli(dp)(a0)
936 $fc58 -$03a8 CliInitRun(dp)(a0)
942 $fc52 -$03ae WriteChars(buf,buflen)(d1/d2)
948 $fc4c -$03b4 PutStr(str)(d1)
954 $fc46 -$03ba VPrintf(format,argarray)(d1/d2)
*--- (1 function slot reserved here) ---
##bias 966
* these were unimplemented until dos 36.147
966 $fc3a -$03c6 ParsePatternNoCase(pat,buf,buflen)(d1/d2/d3)
972 $fc34 -$03cc MatchPatternNoCase(pat,str)(d1/d2)
##private
978 $fc2e -$03d2 DosGetString(num)(d1)
##public
* this was added for V37 dos, returned 0 before then.
984 $fc28 -$03d8 SameDevice(lock1,lock2)(d1/d2)
* These were added in dos 36.147
*--- (4 function slots reserved here) ---
##bias 1014
* these were added in dos 37.1
*--- (2 function slots reserved here) ---
##bias 1026
* these were added in dos 37.8
*--- (2 function slots reserved here) ---
##bias 1038
##end

***************** exec
##base _SysBase
##bias 30
##public
*------ misc ---------------------------------------------------------
 30 $ffe2 -$001e Supervisor(userFunction)(a5)
*------ special patchable hooks to internal exec activity ------------
##private
 36 $ffdc -$0024 ExitIntr()()
 42 $ffd6 -$002a Schedule()()
 48 $ffd0 -$0030 Reschedule()()
 54 $ffca -$0036 Switch()()
 60 $ffc4 -$003c Dispatch()()
 66 $ffbe -$0042 Exception()()
##public
*------ module creation ----------------------------------------------
 72 $ffb8 -$0048 InitCode(startClass,version)(d0/d1)
 78 $ffb2 -$004e InitStruct(initTable,memory,size)(a1/a2,d0)
 84 $ffac -$0054 MakeLibrary(funcInit,structInit,libInit,dataSize,segList)
                  (a0/a1/a2,d0/d1)
 90 $ffa6 -$005a MakeFunctions(target,functionArray,funcDispBase)(a0/a1/a2)
 96 $ffa0 -$0060 FindResident(name)(a1)
102 $ff9a -$0066 InitResident(resident,segList)(a1,d1)
*------ diagnostics --------------------------------------------------
108 $ff94 -$006c Alert(alertNum)(d7)
114 $ff8e -$0072 Debug(flags)(d0)
*------ interrupts ---------------------------------------------------
120 $ff88 -$0078 Disable()()
126 $ff82 -$007e Enable()()
132 $ff7c -$0084 Forbid()()
138 $ff76 -$008a Permit()()
144 $ff70 -$0090 SetSR(newSR,mask)(d0/d1)
150 $ff6a -$0096 SuperState()()
156 $ff64 -$009c UserState(sysStack)(d0)
162 $ff5e -$00a2 SetIntVector(intNumber,interrupt)(d0/a1)
168 $ff58 -$00a8 AddIntServer(intNumber,interrupt)(d0/a1)
174 $ff52 -$00ae RemIntServer(intNumber,interrupt)(d0/a1)
180 $ff4c -$00b4 Cause(interrupt)(a1)
*------ memory allocation --------------------------------------------
186 $ff46 -$00ba Allocate(freeList,byteSize)(a0,d0)
192 $ff40 -$00c0 Deallocate(freeList,memoryBlock,byteSize)(a0/a1,d0)
198 $ff3a -$00c6 AllocMem(byteSize,requirements)(d0/d1)
204 $ff34 -$00cc AllocAbs(byteSize,location)(d0/a1)
210 $ff2e -$00d2 FreeMem(memoryBlock,byteSize)(a1,d0)
216 $ff28 -$00d8 AvailMem(requirements)(d1)
222 $ff22 -$00de AllocEntry(entry)(a0)
228 $ff1c -$00e4 FreeEntry(entry)(a0)
*------ lists --------------------------------------------------------
234 $ff16 -$00ea Insert(list,node,pred)(a0/a1/a2)
240 $ff10 -$00f0 AddHead(list,node)(a0/a1)
246 $ff0a -$00f6 AddTail(list,node)(a0/a1)
252 $ff04 -$00fc Remove(node)(a1)
258 $fefe -$0102 RemHead(list)(a0)
264 $fef8 -$0108 RemTail(list)(a0)
270 $fef2 -$010e Enqueue(list,node)(a0/a1)
276 $feec -$0114 FindName(list,name)(a0/a1)
*------ tasks --------------------------------------------------------
282 $fee6 -$011a AddTask(task,initPC,finalPC)(a1/a2/a3)
288 $fee0 -$0120 RemTask(task)(a1)
294 $feda -$0126 FindTask(name)(a1)
300 $fed4 -$012c SetTaskPri(task,priority)(a1,d0)
306 $fece -$0132 SetSignal(newSignals,signalSet)(d0/d1)
312 $fec8 -$0138 SetExcept(newSignals,signalSet)(d0/d1)
318 $fec2 -$013e Wait(signalSet)(d0)
324 $febc -$0144 Signal(task,signalSet)(a1,d0)
330 $feb6 -$014a AllocSignal(signalNum)(d0)
336 $feb0 -$0150 FreeSignal(signalNum)(d0)
342 $feaa -$0156 AllocTrap(trapNum)(d0)
348 $fea4 -$015c FreeTrap(trapNum)(d0)
*------ messages -----------------------------------------------------
354 $fe9e -$0162 AddPort(port)(a1)
360 $fe98 -$0168 RemPort(port)(a1)
366 $fe92 -$016e PutMsg(port,message)(a0/a1)
372 $fe8c -$0174 GetMsg(port)(a0)
378 $fe86 -$017a ReplyMsg(message)(a1)
384 $fe80 -$0180 WaitPort(port)(a0)
390 $fe7a -$0186 FindPort(name)(a1)
*------ libraries ----------------------------------------------------
396 $fe74 -$018c AddLibrary(library)(a1)
402 $fe6e -$0192 RemLibrary(library)(a1)
408 $fe68 -$0198 OldOpenLibrary(libName)(a1)
414 $fe62 -$019e CloseLibrary(library)(a1)
420 $fe5c -$01a4 SetFunction(library,funcOffset,newFunction)(a1,a0,d0)
426 $fe56 -$01aa SumLibrary(library)(a1)
*------ devices ------------------------------------------------------
432 $fe50 -$01b0 AddDevice(device)(a1)
438 $fe4a -$01b6 RemDevice(device)(a1)
444 $fe44 -$01bc OpenDevice(devName,unit,ioRequest,flags)(a0,d0/a1,d1)
450 $fe3e -$01c2 CloseDevice(ioRequest)(a1)
456 $fe38 -$01c8 DoIO(ioRequest)(a1)
462 $fe32 -$01ce SendIO(ioRequest)(a1)
468 $fe2c -$01d4 CheckIO(ioRequest)(a1)
474 $fe26 -$01da WaitIO(ioRequest)(a1)
480 $fe20 -$01e0 AbortIO(ioRequest)(a1)
*------ resources ----------------------------------------------------
486 $fe1a -$01e6 AddResource(resource)(a1)
492 $fe14 -$01ec RemResource(resource)(a1)
498 $fe0e -$01f2 OpenResource(resName)(a1)
*------ private diagnostic support -----------------------------------
##private
504 $fe08 -$01f8 RawIOInit()()
510 $fe02 -$01fe RawMayGetChar()()
516 $fdfc -$0204 RawPutChar()()
##public
*------ misc ---------------------------------------------------------
522 $fdf6 -$020a RawDoFmt(formatString,dataStream,putChProc,putChData)
                  (a0/a1/a2/a3)
528 $fdf0 -$0210 GetCC()()
534 $fdea -$0216 TypeOfMem(address)(a1)
540 $fde4 -$021c Procure(semaport,bidMsg)(a0/a1)
546 $fdde -$0222 Vacate(semaport)(a0)
552 $fdd8 -$0228 OpenLibrary(libName,version)(a1,d0)
*--- functions in V33 or higher (distributed as Release 1.2) ---
*------ signal semaphores (note funny registers)----------------------
558 $fdd2 -$022e InitSemaphore(sigSem)(a0)
564 $fdcc -$0234 ObtainSemaphore(sigSem)(a0)
570 $fdc6 -$023a ReleaseSemaphore(sigSem)(a0)
576 $fdc0 -$0240 AttemptSemaphore(sigSem)(a0)
582 $fdba -$0246 ObtainSemaphoreList(sigSem)(a0)
588 $fdb4 -$024c ReleaseSemaphoreList(sigSem)(a0)
594 $fdae -$0252 FindSemaphore(sigSem)(a1)
600 $fda8 -$0258 AddSemaphore(sigSem)(a1)
606 $fda2 -$025e RemSemaphore(sigSem)(a1)
*------ kickmem support ----------------------------------------------
612 $fd9c -$0264 SumKickData()()
*------ more memory support ------------------------------------------
618 $fd96 -$026a AddMemList(size,attributes,pri,base,name)(d0/d1/d2/a0/a1)
624 $fd90 -$0270 CopyMem(source,dest,size)(a0/a1,d0)
630 $fd8a -$0276 CopyMemQuick(source,dest,size)(a0/a1,d0)
*------ cache --------------------------------------------------------
*--- functions in V36 or higher (distributed as Release 2.0) ---
636 $fd84 -$027c CacheClearU()()
642 $fd7e -$0282 CacheClearE(address,length,caches)(a0,d0/d1)
648 $fd78 -$0288 CacheControl(cacheBits,cacheMask)(d0/d1)
*------ misc ---------------------------------------------------------
654 $fd72 -$028e CreateIORequest(port,size)(a0,d0)
660 $fd6c -$0294 DeleteIORequest(iorequest)(a0)
666 $fd66 -$029a CreateMsgPort()()
672 $fd60 -$02a0 DeleteMsgPort(port)(a0)
678 $fd5a -$02a6 ObtainSemaphoreShared(sigSem)(a0)
*------ even more memory support -------------------------------------
684 $fd54 -$02ac AllocVec(byteSize,requirements)(d0/d1)
690 $fd4e -$02b2 FreeVec(memoryBlock)(a1)
696 $fd48 -$02b8 CreatePrivatePool(requirements,puddleSize,puddleThresh)
                  (d0/d1/d2)
702 $fd42 -$02be DeletePrivatePool(poolHeader)(a0)
708 $fd3c -$02c4 AllocPooled(memSize,poolHeader)(d0/a0)
714 $fd36 -$02ca FreePooled(memory,poolHeader)(a1,a0)
*------ misc ---------------------------------------------------------
##private
720 $fd30 -$02d0 ExecReserved00(nothing)(d0)
##public
726 $fd2a -$02d6 ColdReboot()()
732 $fd24 -$02dc StackSwap(newSize,newSP,newStack)(d0/d1/a0)
*------ task trees ---------------------------------------------------
738 $fd1e -$02e2 ChildFree(tid)(d0)
744 $fd18 -$02e8 ChildOrphan(tid)(d0)
750 $fd12 -$02ee ChildStatus(tid)(d0)
756 $fd0c -$02f4 ChildWait(tid)(d0)
*------ future expansion ---------------------------------------------
##private
762 $fd06 -$02fa ExecReserved01(nothing)(d0)
768 $fd00 -$0300 ExecReserved02(nothing)(d0)
774 $fcfa -$0306 ExecReserved03(nothing)(d0)
780 $fcf4 -$030c ExecReserved04(nothing)(d0)
##public
##end

***************** expansion
##base _ExpansionBase
##bias 30
##public
*--- functions in V33 or higher (distributed as Release 1.2) ---
 30 $ffe2 -$001e AddConfigDev(configDev)(a0)
*--- functions in V36 or higher (distributed as Release 2.0) ---
 36 $ffdc -$0024 AddBootNode(bootPri,flags,deviceNode,configDev)
                  (d0/d1/a0/a1)
*--- functions in V33 or higher (distributed as Release 1.2) ---
 42 $ffd6 -$002a AllocBoardMem(slotSpec)(d0)
 48 $ffd0 -$0030 AllocConfigDev()()
 54 $ffca -$0036 AllocExpansionMem(numSlots,slotAlign)(d0/d1)
 60 $ffc4 -$003c ConfigBoard(board,configDev)(a0/a1)
 66 $ffbe -$0042 ConfigChain(baseAddr)(a0)
 72 $ffb8 -$0048 FindConfigDev(oldConfigDev,manufacturer,product)(a0,d0/d1)
 78 $ffb2 -$004e FreeBoardMem(startSlot,slotSpec)(d0/d1)
 84 $ffac -$0054 FreeConfigDev(configDev)(a0)
 90 $ffa6 -$005a FreeExpansionMem(startSlot,numSlots)(d0/d1)
 96 $ffa0 -$0060 ReadExpansionByte(board,offset)(a0,d0)
102 $ff9a -$0066 ReadExpansionRom(board,configDev)(a0/a1)
108 $ff94 -$006c RemConfigDev(configDev)(a0)
114 $ff8e -$0072 WriteExpansionByte(board,offset,byte)(a0,d0/d1)
120 $ff88 -$0078 ObtainConfigBinding()()
126 $ff82 -$007e ReleaseConfigBinding()()
132 $ff7c -$0084 SetCurrentBinding(currentBinding,bindingSize)(a0,d0)
138 $ff76 -$008a GetCurrentBinding(currentBinding,bindingSize)(a0,d0)
144 $ff70 -$0090 MakeDosNode(parmPacket)(a0)
150 $ff6a -$0096 AddDosNode(bootPri,flags,deviceNode)(d0/d1/a0)
##private
*--- functions in V36 or higher (distributed as Release 2.0) ---
156 $ff64 -$009c ExpansionReserved26()()
162 $ff5e -$00a2 WriteExpansionWord(board,offset,word)(a0,d0/d1)
##end

***************** gadtools
* "gadtools.library"
##base _GadToolsBase
##bias 30
##public
*--- functions in V36 or higher (distributed as Release 2.0) ---
*
* Gadget Functions
*
 30 $ffe2 -$001e CreateGadgetA(kind,gad,ng,taglist)(d0/a0/a1/a2)
 36 $ffdc -$0024 FreeGadgets(gad)(a0)
 42 $ffd6 -$002a GT_SetGadgetAttrsA(gad,win,req,taglist)(a0/a1/a2/a3)
*
* Menu functions
*
 48 $ffd0 -$0030 CreateMenusA(newmenu,taglist)(a0/a1)
 54 $ffca -$0036 FreeMenus(menu)(a0)
 60 $ffc4 -$003c LayoutMenuItemsA(firstitem,vi,taglist)(a0/a1/a2)
 66 $ffbe -$0042 LayoutMenusA(firstmenu,vi,taglist)(a0/a1/a2)
*
* Misc Event-Handling Functions
*
 72 $ffb8 -$0048 GT_GetIMsg(iport)(a0)
 78 $ffb2 -$004e GT_ReplyIMsg(imsg)(a1)
 84 $ffac -$0054 GT_RefreshWindow(win,req)(a0/a1)
 90 $ffa6 -$005a GT_BeginRefresh(win)(a0)
 96 $ffa0 -$0060 GT_EndRefresh(win,complete)(a0,d0)
102 $ff9a -$0066 GT_FilterIMsg(imsg)(a1)
108 $ff94 -$006c GT_PostFilterIMsg(imsg)(a1)
114 $ff8e -$0072 CreateContext(glistptr)(a0)
*
* Rendering Functions
*
120 $ff88 -$0078 DrawBevelBoxA(rport,left,top,width,height,taglist)
                  (a0,d0/d1/d2/d3/a1)
*
* Visuals Functions
*
126 $ff82 -$007e GetVisualInfoA(screen,taglist)(a0/a1)
132 $ff7c -$0084 FreeVisualInfo(vi)(a0)
##private
*
* Reserved entries
*
138 $ff76 -$008a GTReserved0()()
144 $ff70 -$0090 GTReserved1()()
150 $ff6a -$0096 GTReserved2()()
156 $ff64 -$009c GTReserved3()()
162 $ff5e -$00a2 GTReserved4()()
168 $ff58 -$00a8 GTReserved5()()
##end

***************** graphics
* "graphics.library"
##base _GfxBase
##bias 30
##public
*------ BitMap primitives ------
 30 $ffe2 -$001e BltBitMap(srcBitMap,xSrc,ySrc,destBitMap,xDest,yDest,xSize,
                  ySize,minterm,mask,tempA)(a0,d0/d1/a1,d2/d3/d4/d5/d6/d7/a2)
 36 $ffdc -$0024 BltTemplate(source,xSrc,srcMod,destRP,xDest,yDest,xSize,
                  ySize)(a0,d0/d1/a1,d2/d3/d4/d5)
*------ Text routines ------
 42 $ffd6 -$002a ClearEOL(rp)(a1)
 48 $ffd0 -$0030 ClearScreen(rp)(a1)
 54 $ffca -$0036 TextLength(rp,string,count)(a1,a0,d0)
 60 $ffc4 -$003c Text(rp,string,count)(a1,a0,d0)
 66 $ffbe -$0042 SetFont(rp,textFont)(a1,a0)
 72 $ffb8 -$0048 OpenFont(textAttr)(a0)
 78 $ffb2 -$004e CloseFont(textFont)(a1)
 84 $ffac -$0054 AskSoftStyle(rp)(a1)
 90 $ffa6 -$005a SetSoftStyle(rp,style,enable)(a1,d0/d1)
*------	Gels routines ------
 96 $ffa0 -$0060 AddBob(bob,rp)(a0/a1)
102 $ff9a -$0066 AddVSprite(vSprite,rp)(a0/a1)
108 $ff94 -$006c DoCollision(rp)(a1)
114 $ff8e -$0072 DrawGList(rp,vp)(a1,a0)
120 $ff88 -$0078 InitGels(head,tail,gelsInfo)(a0/a1/a2)
126 $ff82 -$007e InitMasks(vSprite)(a0)
132 $ff7c -$0084 RemIBob(bob,rp,vp)(a0/a1/a2)
138 $ff76 -$008a RemVSprite(vSprite)(a0)
144 $ff70 -$0090 SetCollision(num,routine,gelsInfo)(d0/a0/a1)
150 $ff6a -$0096 SortGList(rp)(a1)
156 $ff64 -$009c AddAnimOb(anOb,anKey,rp)(a0/a1/a2)
162 $ff5e -$00a2 Animate(anKey,rp)(a0/a1)
168 $ff58 -$00a8 GetGBuffers(anOb,rp,flag)(a0/a1,d0)
174 $ff52 -$00ae InitGMasks(anOb)(a0)
*------	General graphics routines ------
180 $ff4c -$00b4 DrawEllipse(rp,xCenter,yCenter,a,b)(a1,d0/d1/d2/d3)
186 $ff46 -$00ba AreaEllipse(rp,xCenter,yCenter,a,b)(a1,d0/d1/d2/d3)
192 $ff40 -$00c0 LoadRGB4(vp,colors,count)(a0/a1,d0)
198 $ff3a -$00c6 InitRastPort(rp)(a1)
204 $ff34 -$00cc InitVPort(vp)(a0)
210 $ff2e -$00d2 MrgCop(view)(a1)
216 $ff28 -$00d8 MakeVPort(view,vp)(a0/a1)
222 $ff22 -$00de LoadView(view)(a1)
228 $ff1c -$00e4 WaitBlit()()
234 $ff16 -$00ea SetRast(rp,pen)(a1,d0)
240 $ff10 -$00f0 Move(rp,x,y)(a1,d0/d1)
246 $ff0a -$00f6 Draw(rp,x,y)(a1,d0/d1)
252 $ff04 -$00fc AreaMove(rp,x,y)(a1,d0/d1)
258 $fefe -$0102 AreaDraw(rp,x,y)(a1,d0/d1)
264 $fef8 -$0108 AreaEnd(rp)(a1)
270 $fef2 -$010e WaitTOF()()
276 $feec -$0114 QBlit(blit)(a1)
282 $fee6 -$011a InitArea(areaInfo,vectorBuffer,maxVectors)(a0/a1,d0)
288 $fee0 -$0120 SetRGB4(vp,index,red,green,blue)(a0,d0/d1/d2/d3)
294 $feda -$0126 QBSBlit(blit)(a1)
300 $fed4 -$012c BltClear(memBlock,byteCount,flags)(a1,d0/d1)
306 $fece -$0132 RectFill(rp,xMin,yMin,xMax,yMax)(a1,d0/d1/d2/d3)
312 $fec8 -$0138 BltPattern(rp,mask,xMin,yMin,xMax,yMax,maskBPR)
                  (a1,a0,d0/d1/d2/d3/d4)
318 $fec2 -$013e ReadPixel(rp,x,y)(a1,d0/d1)
324 $febc -$0144 WritePixel(rp,x,y)(a1,d0/d1)
330 $feb6 -$014a Flood(rp,mode,x,y)(a1,d2,d0/d1)
336 $feb0 -$0150 PolyDraw(rp,count,polyTable)(a1,d0/a0)
342 $feaa -$0156 SetAPen(rp,pen)(a1,d0)
348 $fea4 -$015c SetBPen(rp,pen)(a1,d0)
354 $fe9e -$0162 SetDrMd(rp,drawMode)(a1,d0)
360 $fe98 -$0168 InitView(view)(a1)
366 $fe92 -$016e CBump(copList)(a1)
372 $fe8c -$0174 CMove(copList,destination,data)(a1,d0/d1)
378 $fe86 -$017a CWait(copList,v,h)(a1,d0/d1)
384 $fe80 -$0180 VBeamPos()()
390 $fe7a -$0186 InitBitMap(bitMap,depth,width,height)(a0,d0/d1/d2)
396 $fe74 -$018c ScrollRaster(rp,dx,dy,xMin,yMin,xMax,yMax)
                  (a1,d0/d1/d2/d3/d4/d5)
402 $fe6e -$0192 WaitBOVP(vp)(a0)
408 $fe68 -$0198 GetSprite(sprite,num)(a0,d0)
414 $fe62 -$019e FreeSprite(num)(d0)
420 $fe5c -$01a4 ChangeSprite(vp,sprite,newData)(a0/a1/a2)
426 $fe56 -$01aa MoveSprite(vp,sprite,x,y)(a0/a1,d0/d1)
432 $fe50 -$01b0 LockLayerRom(layer)(a5)
438 $fe4a -$01b6 UnlockLayerRom(layer)(a5)
444 $fe44 -$01bc SyncSBitMap(layer)(a0)
450 $fe3e -$01c2 CopySBitMap(layer)(a0)
456 $fe38 -$01c8 OwnBlitter()()
462 $fe32 -$01ce DisownBlitter()()
468 $fe2c -$01d4 InitTmpRas(tmpRas,buffer,size)(a0/a1,d0)
474 $fe26 -$01da AskFont(rp,textAttr)(a1,a0)
480 $fe20 -$01e0 AddFont(textFont)(a1)
486 $fe1a -$01e6 RemFont(textFont)(a1)
492 $fe14 -$01ec AllocRaster(width,height)(d0/d1)
498 $fe0e -$01f2 FreeRaster(p,width,height)(a0,d0/d1)
504 $fe08 -$01f8 AndRectRegion(region,rectangle)(a0/a1)
510 $fe02 -$01fe OrRectRegion(region,rectangle)(a0/a1)
516 $fdfc -$0204 NewRegion()()
522 $fdf6 -$020a ClearRectRegion(region,rectangle)(a0/a1)
528 $fdf0 -$0210 ClearRegion(region)(a0)
534 $fdea -$0216 DisposeRegion(region)(a0)
540 $fde4 -$021c FreeVPortCopLists(vp)(a0)
546 $fdde -$0222 FreeCopList(copList)(a0)
552 $fdd8 -$0228 ClipBlit(srcRP,xSrc,ySrc,destRP,xDest,yDest,xSize,ySize,
                  minterm)(a0,d0/d1/a1,d2/d3/d4/d5/d6)
558 $fdd2 -$022e XorRectRegion(region,rectangle)(a0/a1)
564 $fdcc -$0234 FreeCprList(cprList)(a0)
570 $fdc6 -$023a GetColorMap(entries)(d0)
576 $fdc0 -$0240 FreeColorMap(colorMap)(a0)
582 $fdba -$0246 GetRGB4(colorMap,entry)(a0,d0)
588 $fdb4 -$024c ScrollVPort(vp)(a0)
594 $fdae -$0252 UCopperListInit(uCopList,n)(a0,d0)
600 $fda8 -$0258 FreeGBuffers(anOb,rp,flag)(a0/a1,d0)
606 $fda2 -$025e BltBitMapRastPort(srcBitMap,xSrc,ySrc,destRP,xDest,yDest,
                  xSize,ySize,minterm)(a0,d0/d1/a1,d2/d3/d4/d5/d6)
612 $fd9c -$0264 OrRegionRegion(srcRegion,destRegion)(a0/a1)
618 $fd96 -$026a XorRegionRegion(srcRegion,destRegion)(a0/a1)
624 $fd90 -$0270 AndRegionRegion(srcRegion,destRegion)(a0/a1)
630 $fd8a -$0276 SetRGB4CM(colorMap,index,red,green,blue)(a0,d0/d1/d2/d3)
636 $fd84 -$027c BltMaskBitMapRastPort(srcBitMap,xSrc,ySrc,destRP,xDest,
                  yDest,xSize,ySize,minterm,bltMask)(a0,d0/d1/a1,d2/d3/d4/d5/d6/a2)
*--- (2 function slots reserved here) ---
##bias 654
654 $fd72 -$028e AttemptLockLayerRom(layer)(a5)
*--- functions in V36 or higher (distributed as Release 2.0) ---
660 $fd6c -$0294 GfxNew(gfxNodeType)(d0)
666 $fd66 -$029a GfxFree(gfxNodePtr)(a0)
672 $fd60 -$02a0 GfxAssociate(associateNode,gfxNodePtr)(a0/a1)
678 $fd5a -$02a6 BitMapScale(bitScaleArgs)(a0)
684 $fd54 -$02ac ScalerDiv(factor,numerator,denominator)(d0/d1/d2)
690 $fd4e -$02b2 TextExtent(rp,string,count,textExtent)(a1,a0,d0/a2)
696 $fd48 -$02b8 TextFit(rp,string,strLen,textExtent,constrainingExtent,
                  strDirection,constrainingBitWidth,constrainingBitHeight)(a1,a0,d0/a2/a3,d1/d2/d3)
702 $fd42 -$02be GfxLookUp(associateNode)(a0)
708 $fd3c -$02c4 VideoControl(colorMap,tagarray)(a0/a1)
714 $fd36 -$02ca OpenMonitor(monitorName,displayID)(a1,d0)
720 $fd30 -$02d0 CloseMonitor(monitorSpec)(a0)
726 $fd2a -$02d6 FindDisplayInfo(displayID)(d0)
732 $fd24 -$02dc NextDisplayInfo(displayID)(d0)
##private
738 $fd1e -$02e2 AddDisplayInfo(displayInfoRecord)(a0)
744 $fd18 -$02e8 AddDisplayInfoData(handle,buf,size,tagID,displayID)
                  (a0/a1,d0/d1/d2)
750 $fd12 -$02ee SetDisplayInfoData(handle,buf,size,tagID,displayID)
                  (a0/a1,d0/d1/d2)
##public
756 $fd0c -$02f4 GetDisplayInfoData(handle,buf,size,tagID,displayID)
                  (a0/a1,d0/d1/d2)
762 $fd06 -$02fa FontExtent(font,fontExtent)(a0/a1)
768 $fd00 -$0300 ReadPixelLine8(rp,xstart,ystart,width,array,tempRP)
                  (a0,d0/d1/d2/a2,a1)
774 $fcfa -$0306 WritePixelLine8(rp,xstart,ystart,width,array,tempRP)
                  (a0,d0/d1/d2/a2,a1)
780 $fcf4 -$030c ReadPixelArray8(rp,xstart,ystart,xstop,ystop,array,temprp)
                  (a0,d0/d1/d2/d3/a2,a1)
786 $fcee -$0312 WritePixelArray8(rp,xstart,ystart,xstop,ystop,array,temprp)
                  (a0,d0/d1/d2/d3/a2,a1)
792 $fce8 -$0318 GetVPModeID(vp)(a0)
798 $fce2 -$031e ModeNotAvailable(modeID)(d0)
804 $fcdc -$0324 WeighTAMatch(reqTextAttr,targetTextAttr,targetTags)
                  (a0/a1/a2)
810 $fcd6 -$032a EraseRect(rp,xMin,yMin,xMax,yMax)(a1,d0/d1/d2/d3)
816 $fcd0 -$0330 ExtendFont(font,fontTags)(a0/a1)
822 $fcca -$0336 StripFont(font)(a0)
##end

***************** icon
* "icon.library"
##base _IconBase
##bias 30
*--- functions in V36 or higher (distributed as Release 2.0) ---
*	Use DiskObjects instead of obsolete WBObjects
##private
 30 $ffe2 -$001e OBSOLETEGetWBObject(name)(a0)
 36 $ffdc -$0024 OBSOLETEPutWBObject(name,object)(a0/a1)
##public
 42 $ffd6 -$002a GetIcon(name,icon,freelist)(a0/a1/a2)
 48 $ffd0 -$0030 PutIcon(name,icon)(a0/a1)
 54 $ffca -$0036 FreeFreeList(freelist)(a0)
##private
 60 $ffc4 -$003c OBSOLETEFreeWBObject(object)(a0)
 66 $ffbe -$0042 OBSOLETEAllocWBObject()()
##public
 72 $ffb8 -$0048 AddFreeList(freelist,mem,size)(a0/a1/a2)
 78 $ffb2 -$004e GetDiskObject(name)(a0)
 84 $ffac -$0054 PutDiskObject(name,diskobj)(a0/a1)
 90 $ffa6 -$005a FreeDiskObject(diskobj)(a0)
 96 $ffa0 -$0060 FindToolType(toolTypeArray,typeName)(a0/a1)
102 $ff9a -$0066 MatchToolValue(typeString,value)(a0/a1)
108 $ff94 -$006c BumpRevision(newname,oldname)(a0/a1)
##private
114 $ff8e -$0072 FreeAlloc(free,len,type)(a0/a1/a2)
##public
120 $ff88 -$0078 GetDefDiskObject(type)(d0)
126 $ff82 -$007e PutDefDiskObject(diskObject)(a0)
132 $ff7c -$0084 GetDiskObjectNew(name)(a0)
138 $ff76 -$008a DeleteDiskObject(name)(a0)
*--- (4 function slots reserved here) ---
##bias 168
##end

***************** iffparse
* "iffparse.library"
##base _IFFParseBase
##bias 30
##public
*--- functions in V33 or higher (distributed as Release 1.2) ---
*------ Basic functions ------
 30 $ffe2 -$001e AllocIFF()()
 36 $ffdc -$0024 OpenIFF(iff,rwMode)(a0,d0)
 42 $ffd6 -$002a ParseIFF(iff,control)(a0,d0)
 48 $ffd0 -$0030 CloseIFF(iff)(a0)
 54 $ffca -$0036 FreeIFF(iff)(a0)
*------ Read/Write functions ------
 60 $ffc4 -$003c ReadChunkBytes(iff,buf,size)(a0/a1,d0)
 66 $ffbe -$0042 WriteChunkBytes(iff,buf,size)(a0/a1,d0)
 72 $ffb8 -$0048 ReadChunkRecords(iff,buf,bytesPerRecord,nRecords)
                  (a0/a1,d0/d1)
 78 $ffb2 -$004e WriteChunkRecords(iff,buf,bytesPerRecord,nRecords)
                  (a0/a1,d0/d1)
*------ Context entry/exit ------
 84 $ffac -$0054 PushChunk(iff,type,id,size)(a0,d0/d1/d2)
 90 $ffa6 -$005a PopChunk(iff)(a0)
*--- (1 function slot reserved here) ---
##bias 102
*------ Low-level handler installation ------
102 $ff9a -$0066 EntryHandler(iff,type,id,position,handler,object)
                  (a0,d0/d1/d2/a1/a2)
108 $ff94 -$006c ExitHandler(iff,type,id,position,handler,object)
                  (a0,d0/d1/d2/a1/a2)
*------ Built-in chunk/property handlers ------
114 $ff8e -$0072 PropChunk(iff,type,id)(a0,d0/d1)
120 $ff88 -$0078 PropChunks(iff,propArray,nProps)(a0/a1,d0)
126 $ff82 -$007e StopChunk(iff,type,id)(a0,d0/d1)
132 $ff7c -$0084 StopChunks(iff,propArray,nProps)(a0/a1,d0)
138 $ff76 -$008a CollectionChunk(iff,type,id)(a0,d0/d1)
144 $ff70 -$0090 CollectionChunks(iff,propArray,nProps)(a0/a1,d0)
150 $ff6a -$0096 StopOnExit(iff,type,id)(a0,d0/d1)
*------ Context utilities ------
156 $ff64 -$009c FindProp(iff,type,id)(a0,d0/d1)
162 $ff5e -$00a2 FindCollection(iff,type,id)(a0,d0/d1)
168 $ff58 -$00a8 FindPropContext(iff)(a0)
174 $ff52 -$00ae CurrentChunk(iff)(a0)
180 $ff4c -$00b4 ParentChunk(contextNode)(a0)
*------ LocalContextItem support functions ------
186 $ff46 -$00ba AllocLocalItem(type,id,ident,dataSize)(d0/d1/d2/d3)
192 $ff40 -$00c0 LocalItemData(localItem)(a0)
198 $ff3a -$00c6 SetLocalItemPurge(localItem,purgeHook)(a0/a1)
204 $ff34 -$00cc FreeLocalItem(localItem)(a0)
210 $ff2e -$00d2 FindLocalItem(iff,type,id,ident)(a0,d0/d1/d2)
216 $ff28 -$00d8 StoreLocalItem(iff,localItem,position)(a0/a1,d0)
222 $ff22 -$00de StoreItemInContext(iff,localItem,contextNode)(a0/a1/a2)
*------ IFFHandle initialization ------
228 $ff1c -$00e4 InitIFF(iff,flags,streamHook)(a0,d0/a1)
234 $ff16 -$00ea InitIFFasDOS(iff)(a0)
240 $ff10 -$00f0 InitIFFasClip(iff)(a0)
*------ Internal clipboard support ------
246 $ff0a -$00f6 OpenClipboard(unitNum)(d0)
252 $ff04 -$00fc CloseClipboard(clipboard)(a0)
*------ Miscellaneous ------
258 $fefe -$0102 GoodID(id)(d0)
264 $fef8 -$0108 GoodType(type)(d0)
270 $fef2 -$010e IDtoStr(id,buf)(d0/a0)
##end

***************** input
* "input.device"
##base _InputBase
##bias 42
##public
*--- functions in V36 or higher (distributed as Release 2.0) ---
 42 $ffd6 -$002a PeekQualifier()()
##end

***************** intuition
* "intuition.library"
##base _IntuitionBase
##bias 30
##public
* Public functions OpenIntuition() and Intuition() are intentionally
* not documented.
 30 $ffe2 -$001e OpenIntuition()()
 36 $ffdc -$0024 Intuition(iEvent)(a0)
 42 $ffd6 -$002a AddGadget(window,gadget,position)(a0/a1,d0)
 48 $ffd0 -$0030 ClearDMRequest(window)(a0)
 54 $ffca -$0036 ClearMenuStrip(window)(a0)
 60 $ffc4 -$003c ClearPointer(window)(a0)
 66 $ffbe -$0042 CloseScreen(screen)(a0)
 72 $ffb8 -$0048 CloseWindow(window)(a0)
 78 $ffb2 -$004e CloseWorkBench()()
 84 $ffac -$0054 CurrentTime(seconds,micros)(a0/a1)
 90 $ffa6 -$005a DisplayAlert(alertNumber,string,height)(d0/a0,d1)
 96 $ffa0 -$0060 DisplayBeep(screen)(a0)
102 $ff9a -$0066 DoubleClick(sSeconds,sMicros,cSeconds,cMicros)(d0/d1/d2/d3)
108 $ff94 -$006c DrawBorder(rp,border,leftOffset,topOffset)(a0/a1,d0/d1)
114 $ff8e -$0072 DrawImage(rp,image,leftOffset,topOffset)(a0/a1,d0/d1)
120 $ff88 -$0078 EndRequest(requester,window)(a0/a1)
126 $ff82 -$007e GetDefPrefs(preferences,size)(a0,d0)
132 $ff7c -$0084 GetPrefs(preferences,size)(a0,d0)
138 $ff76 -$008a InitRequester(requester)(a0)
144 $ff70 -$0090 ItemAddress(menuStrip,menuNumber)(a0,d0)
150 $ff6a -$0096 ModifyIDCMP(window,flags)(a0,d0)
156 $ff64 -$009c ModifyProp(gadget,window,requester,flags,horizPot,vertPot,
                  horizBody,vertBody)(a0/a1/a2,d0/d1/d2/d3/d4)
162 $ff5e -$00a2 MoveScreen(screen,dx,dy)(a0,d0/d1)
168 $ff58 -$00a8 MoveWindow(window,dx,dy)(a0,d0/d1)
174 $ff52 -$00ae OffGadget(gadget,window,requester)(a0/a1/a2)
180 $ff4c -$00b4 OffMenu(window,menuNumber)(a0,d0)
186 $ff46 -$00ba OnGadget(gadget,window,requester)(a0/a1/a2)
192 $ff40 -$00c0 OnMenu(window,menuNumber)(a0,d0)
198 $ff3a -$00c6 OpenScreen(newScreen)(a0)
204 $ff34 -$00cc OpenWindow(newWindow)(a0)
210 $ff2e -$00d2 OpenWorkBench()()
216 $ff28 -$00d8 PrintIText(rp,iText,left,top)(a0/a1,d0/d1)
222 $ff22 -$00de RefreshGadgets(gadgets,window,requester)(a0/a1/a2)
228 $ff1c -$00e4 RemoveGadget(window,gadget)(a0/a1)
* The official calling sequence for ReportMouse is given below.
* Note the register order.  For the complete story, read the ReportMouse
* autodoc.
234 $ff16 -$00ea ReportMouse(flag,window)(d0/a0)
240 $ff10 -$00f0 Request(requester,window)(a0/a1)
246 $ff0a -$00f6 ScreenToBack(screen)(a0)
252 $ff04 -$00fc ScreenToFront(screen)(a0)
258 $fefe -$0102 SetDMRequest(window,requester)(a0/a1)
264 $fef8 -$0108 SetMenuStrip(window,menu)(a0/a1)
270 $fef2 -$010e SetPointer(window,pointer,height,width,xOffset,yOffset)
                  (a0/a1,d0/d1/d2/d3)
276 $feec -$0114 SetWindowTitles(window,windowTitle,screenTitle)(a0/a1/a2)
282 $fee6 -$011a ShowTitle(screen,showIt)(a0,d0)
288 $fee0 -$0120 SizeWindow(window,dx,dy)(a0,d0/d1)
294 $feda -$0126 ViewAddress()()
300 $fed4 -$012c ViewPortAddress(window)(a0)
306 $fece -$0132 WindowToBack(window)(a0)
312 $fec8 -$0138 WindowToFront(window)(a0)
318 $fec2 -$013e WindowLimits(window,widthMin,heightMin,widthMax,heightMax)
                  (a0,d0/d1/d2/d3)
*--- start of next generation of names -------------------------------------
324 $febc -$0144 SetPrefs(preferences,size,inform)(a0,d0/d1)
*--- start of next next generation of names --------------------------------
330 $feb6 -$014a IntuiTextLength(iText)(a0)
336 $feb0 -$0150 WBenchToBack()()
342 $feaa -$0156 WBenchToFront()()
*--- start of next next next generation of names ---------------------------
348 $fea4 -$015c AutoRequest(window,body,posText,negText,pFlag,nFlag,width,
                  height)(a0/a1/a2/a3,d0/d1/d2/d3)
354 $fe9e -$0162 BeginRefresh(window)(a0)
360 $fe98 -$0168 BuildSysRequest(window,body,posText,negText,flags,width,
                  height)(a0/a1/a2/a3,d0/d1/d2)
366 $fe92 -$016e EndRefresh(window,complete)(a0,d0)
372 $fe8c -$0174 FreeSysRequest(window)(a0)
378 $fe86 -$017a MakeScreen(screen)(a0)
384 $fe80 -$0180 RemakeDisplay()()
390 $fe7a -$0186 RethinkDisplay()()
*--- start of next next next next generation of names ----------------------
396 $fe74 -$018c AllocRemember(rememberKey,size,flags)(a0,d0/d1)
* Public function AlohaWorkbench() is intentionally not documented
402 $fe6e -$0192 AlohaWorkbench(wbport)(a0)
408 $fe68 -$0198 FreeRemember(rememberKey,reallyForget)(a0,d0)
*--- start of 15 Nov 85 names ------------------------
414 $fe62 -$019e LockIBase(dontknow)(d0)
420 $fe5c -$01a4 UnlockIBase(ibLock)(a0)
*--- functions in V33 or higher (distributed as Release 1.2) ---
426 $fe56 -$01aa GetScreenData(buffer,size,type,screen)(a0,d0/d1/a1)
432 $fe50 -$01b0 RefreshGList(gadgets,window,requester,numGad)(a0/a1/a2,d0)
438 $fe4a -$01b6 AddGList(window,gadget,position,numGad,requester)
                  (a0/a1,d0/d1/a2)
444 $fe44 -$01bc RemoveGList(remPtr,gadget,numGad)(a0/a1,d0)
450 $fe3e -$01c2 ActivateWindow(window)(a0)
456 $fe38 -$01c8 RefreshWindowFrame(window)(a0)
462 $fe32 -$01ce ActivateGadget(gadgets,window,requester)(a0/a1/a2)
468 $fe2c -$01d4 NewModifyProp(gadget,window,requester,flags,horizPot,
                  vertPot,horizBody,vertBody,numGad)(a0/a1/a2,d0/d1/d2/d3/d4/d5)
*--- functions in V36 or higher (distributed as Release 2.0) ---
474 $fe26 -$01da QueryOverscan(displayID,rect,oScanType)(a0/a1,d0)
480 $fe20 -$01e0 MoveWindowInFrontOf(window,behindWindow)(a0/a1)
486 $fe1a -$01e6 ChangeWindowBox(window,left,top,width,height)
                  (a0,d0/d1/d2/d3)
492 $fe14 -$01ec SetEditHook(hook)(a0)
498 $fe0e -$01f2 SetMouseQueue(window,queueLength)(a0,d0)
504 $fe08 -$01f8 ZipWindow(window)(a0)
*--- public screens ---
510 $fe02 -$01fe LockPubScreen(name)(a0)
516 $fdfc -$0204 UnlockPubScreen(name,screen)(a0/a1)
522 $fdf6 -$020a LockPubScreenList()()
528 $fdf0 -$0210 UnlockPubScreenList()()
534 $fdea -$0216 NextPubScreen(screen,namebuf)(a0/a1)
540 $fde4 -$021c SetDefaultPubScreen(name)(a0)
546 $fdde -$0222 SetPubScreenModes(modes)(d0)
552 $fdd8 -$0228 PubScreenStatus(screen,statusFlags)(a0,d0)
*
558 $fdd2 -$022e ObtainGIRPort(gInfo)(a0)
564 $fdcc -$0234 ReleaseGIRPort(rp)(a0)
570 $fdc6 -$023a GadgetMouse(gadget,gInfo,mousePoint)(a0/a1/a2)
* SetIPrefs is system private and not to be used by applications
##private
576 $fdc0 -$0240 SetIPrefs(ptr,size,type)(a0,d0/d1)
##public
582 $fdba -$0246 GetDefaultPubScreen(nameBuffer)(a0)
588 $fdb4 -$024c EasyRequestArgs(window,easyStruct,idcmpPtr,args)
                  (a0/a1/a2/a3)
594 $fdae -$0252 BuildEasyRequestArgs(window,easyStruct,idcmp,args)
                  (a0/a1,d0/a3)
600 $fda8 -$0258 SysReqHandler(window,idcmpPtr,waitInput)(a0/a1,d0)
606 $fda2 -$025e OpenWindowTagList(newWindow,tagList)(a0/a1)
612 $fd9c -$0264 OpenScreenTagList(newScreen,tagList)(a0/a1)
*
*	new Image functions
618 $fd96 -$026a DrawImageState(rp,image,leftOffset,topOffset,state,drawInfo)
                  (a0/a1,d0/d1/d2/a2)
624 $fd90 -$0270 PointInImage(point,image)(d0/a0)
630 $fd8a -$0276 EraseImage(rp,image,leftOffset,topOffset)(a0/a1,d0/d1)
*
636 $fd84 -$027c NewObjectA(class,classID,tagList)(a0/a1/a2)
*
642 $fd7e -$0282 DisposeObject(object)(a0)
648 $fd78 -$0288 SetAttrsA(object,tagList)(a0/a1)
*
654 $fd72 -$028e GetAttr(attrID,object,storagePtr)(d0/a0/a1)
*
* 	special set attribute call for gadgets
660 $fd6c -$0294 SetGadgetAttrsA(gadget,window,requester,tagList)
                  (a0/a1/a2/a3)
*
*	for class implementors only
666 $fd66 -$029a NextObject(objectPtrPtr)(a0)
##private
672 $fd60 -$02a0 FindClass(classID)(a0)
##public
678 $fd5a -$02a6 MakeClass(classID,superClassID,superClassPtr,instanceSize,
                  flags)(a0/a1/a2,d0/d1)
684 $fd54 -$02ac AddClass(class)(a0)
*
*
690 $fd4e -$02b2 GetScreenDrawInfo(screen)(a0)
696 $fd48 -$02b8 FreeScreenDrawInfo(screen,drawInfo)(a0/a1)
*
702 $fd42 -$02be ResetMenuStrip(window,menu)(a0/a1)
708 $fd3c -$02c4 RemoveClass(classPtr)(a0)
714 $fd36 -$02ca FreeClass(classPtr)(a0)
##private
720 $fd30 -$02d0 lockPubClass()()
726 $fd2a -$02d6 unlockPubClass()()
##public
##end

***************** keymap
* "keymap.library"
##base _KeymapBase
##bias 30
##public
*--- functions in V36 or higher (distributed as Release 2.0) ---
 30 $ffe2 -$001e SetKeyMapDefault(keyMap)(a0)
 36 $ffdc -$0024 AskKeyMapDefault()()
 42 $ffd6 -$002a MapRawKey(event,buffer,length,keyMap)(a0/a1,d1/a2)
 48 $ffd0 -$0030 MapANSI(string,count,buffer,length,keyMap)(a0,d0/a1,d1/a2)
##end

***************** layers
* "layers.library"
##base _LayersBase
##bias 30
##public
 30 $ffe2 -$001e InitLayers(li)(a0)
 36 $ffdc -$0024 CreateUpfrontLayer(li,bm,x0,y0,x1,y1,flags,bm2)
                  (a0/a1,d0/d1/d2/d3/d4/a2)
 42 $ffd6 -$002a CreateBehindLayer(li,bm,x0,y0,x1,y1,flags,bm2)
                  (a0/a1,d0/d1/d2/d3/d4/a2)
 48 $ffd0 -$0030 UpfrontLayer(dummy,layer)(a0/a1)
 54 $ffca -$0036 BehindLayer(dummy,layer)(a0/a1)
 60 $ffc4 -$003c MoveLayer(dummy,layer,dx,dy)(a0/a1,d0/d1)
 66 $ffbe -$0042 SizeLayer(dummy,layer,dx,dy)(a0/a1,d0/d1)
 72 $ffb8 -$0048 ScrollLayer(dummy,layer,dx,dy)(a0/a1,d0/d1)
 78 $ffb2 -$004e BeginUpdate(l)(a0)
 84 $ffac -$0054 EndUpdate(layer,flag)(a0,d0)
 90 $ffa6 -$005a DeleteLayer(dummy,layer)(a0/a1)
 96 $ffa0 -$0060 LockLayer(dummy,layer)(a0/a1)
102 $ff9a -$0066 UnlockLayer(layer)(a0)
108 $ff94 -$006c LockLayers(li)(a0)
114 $ff8e -$0072 UnlockLayers(li)(a0)
120 $ff88 -$0078 LockLayerInfo(li)(a0)
126 $ff82 -$007e SwapBitsRastPortClipRect(rp,cr)(a0/a1)
132 $ff7c -$0084 WhichLayer(li,x,y)(a0,d0/d1)
138 $ff76 -$008a UnlockLayerInfo(li)(a0)
144 $ff70 -$0090 NewLayerInfo()()
150 $ff6a -$0096 DisposeLayerInfo(li)(a0)
156 $ff64 -$009c FattenLayerInfo(li)(a0)
162 $ff5e -$00a2 ThinLayerInfo(li)(a0)
168 $ff58 -$00a8 MoveLayerInFrontOf(layer_to_move,other_layer)(a0/a1)
174 $ff52 -$00ae InstallClipRegion(layer,region)(a0/a1)
180 $ff4c -$00b4 MoveSizeLayer(layer,dx,dy,dw,dh)(a0,d0/d1/d2/d3)
186 $ff46 -$00ba CreateUpfrontHookLayer(li,bm,x0,y0,x1,y1,flags,hook,bm2)
                  (a0/a1,d0/d1/d2/d3/d4/a3,a2)
192 $ff40 -$00c0 CreateBehindHookLayer(li,bm,x0,y0,x1,y1,flags,hook,bm2)
                  (a0/a1,d0/d1/d2/d3/d4/a3,a2)
198 $ff3a -$00c6 InstallLayerHook(layer,hook)(a0/a1)
##end

***************** mathffp
* "mathffp.library"
##base _MathBase
##bias 30
##public
 30 $ffe2 -$001e SPFix(parm)(d0)
 36 $ffdc -$0024 SPFlt(integer)(d0)
 42 $ffd6 -$002a SPCmp(leftParm,rightParm)(d1,d0)
 48 $ffd0 -$0030 SPTst(parm)(d1)
 54 $ffca -$0036 SPAbs(parm)(d0)
 60 $ffc4 -$003c SPNeg(parm)(d0)
 66 $ffbe -$0042 SPAdd(leftParm,rightParm)(d1,d0)
 72 $ffb8 -$0048 SPSub(leftParm,rightParm)(d1,d0)
 78 $ffb2 -$004e SPMul(leftParm,rightParm)(d1,d0)
 84 $ffac -$0054 SPDiv(leftParm,rightParm)(d1,d0)
*--- functions in V33 or higher (distributed as Release 1.2) ---
 90 $ffa6 -$005a SPFloor(parm)(d0)
 96 $ffa0 -$0060 SPCeil(parm)(d0)
##end

***************** mathieeedoubbas
* "mathieeedoubbas.library"
##base _MathIeeeDoubBasBase
##bias 30
##public
 30 $ffe2 -$001e IEEEDPFix(parm)(d0/d1)
 36 $ffdc -$0024 IEEEDPFlt(integer)(d0)
 42 $ffd6 -$002a IEEEDPCmp(leftParm,rightParm)(d0/d1/d2/d3)
 48 $ffd0 -$0030 IEEEDPTst(parm)(d0/d1)
 54 $ffca -$0036 IEEEDPAbs(parm)(d0/d1)
 60 $ffc4 -$003c IEEEDPNeg(parm)(d0/d1)
 66 $ffbe -$0042 IEEEDPAdd(leftParm,rightParm)(d0/d1/d2/d3)
 72 $ffb8 -$0048 IEEEDPSub(leftParm,rightParm)(d0/d1/d2/d3)
 78 $ffb2 -$004e IEEEDPMul(factor1,factor2)(d0/d1/d2/d3)
 84 $ffac -$0054 IEEEDPDiv(dividend,divisor)(d0/d1/d2/d3)
*--- functions in V33 or higher (distributed as Release 1.2) ---
 90 $ffa6 -$005a IEEEDPFloor(parm)(d0/d1)
 96 $ffa0 -$0060 IEEEDPCeil(parm)(d0/d1)
##end

***************** mathieeedoubtrans
* "mathieeedoubtrans.library"
##base _MathIeeeDoubTransBase
##bias 30
##public
 30 $ffe2 -$001e IEEEDPAtan(parm)(d0/d1)
 36 $ffdc -$0024 IEEEDPSin(parm)(d0/d1)
 42 $ffd6 -$002a IEEEDPCos(parm)(d0/d1)
 48 $ffd0 -$0030 IEEEDPTan(parm)(d0/d1)
 54 $ffca -$0036 IEEEDPSincos(pf2,parm)(a0,d0/d1)
 60 $ffc4 -$003c IEEEDPSinh(parm)(d0/d1)
 66 $ffbe -$0042 IEEEDPCosh(parm)(d0/d1)
 72 $ffb8 -$0048 IEEEDPTanh(parm)(d0/d1)
 78 $ffb2 -$004e IEEEDPExp(parm)(d0/d1)
 84 $ffac -$0054 IEEEDPLog(parm)(d0/d1)
 90 $ffa6 -$005a IEEEDPPow(exp,arg)(d2/d3,d0/d1)
 96 $ffa0 -$0060 IEEEDPSqrt(parm)(d0/d1)
102 $ff9a -$0066 IEEEDPTieee(parm)(d0/d1)
108 $ff94 -$006c IEEEDPFieee(single)(d0)
114 $ff8e -$0072 IEEEDPAsin(parm)(d0/d1)
120 $ff88 -$0078 IEEEDPAcos(parm)(d0/d1)
126 $ff82 -$007e IEEEDPLog10(parm)(d0/d1)
##end

***************** mathieeesingbas
* "mathieeesingbas.library"
##base _MathIeeeSingBasBase
##bias 30
##public
 30 $ffe2 -$001e IEEESPFix(parm)(d0)
 36 $ffdc -$0024 IEEESPFlt(integer)(d0)
 42 $ffd6 -$002a IEEESPCmp(leftParm,rightParm)(d0/d1)
 48 $ffd0 -$0030 IEEESPTst(parm)(d0)
 54 $ffca -$0036 IEEESPAbs(parm)(d0)
 60 $ffc4 -$003c IEEESPNeg(parm)(d0)
 66 $ffbe -$0042 IEEESPAdd(leftParm,rightParm)(d0/d1)
 72 $ffb8 -$0048 IEEESPSub(leftParm,rightParm)(d0/d1)
 78 $ffb2 -$004e IEEESPMul(leftParm,rightParm)(d0/d1)
 84 $ffac -$0054 IEEESPDiv(dividend,divisor)(d0/d1)
 90 $ffa6 -$005a IEEESPFloor(parm)(d0)
 96 $ffa0 -$0060 IEEESPCeil(parm)(d0)
##end

***************** mathieeesingtrans
* "mathieeesingtrans.library"
##base _MathIeeeSingTransBase
##bias 30
##public
 30 $ffe2 -$001e IEEESPAtan(parm)(d0)
 36 $ffdc -$0024 IEEESPSin(parm)(d0)
 42 $ffd6 -$002a IEEESPCos(parm)(d0)
 48 $ffd0 -$0030 IEEESPTan(parm)(d0)
 54 $ffca -$0036 IEEESPSincos(cosptr,parm)(a0,d0)
 60 $ffc4 -$003c IEEESPSinh(parm)(d0)
 66 $ffbe -$0042 IEEESPCosh(parm)(d0)
 72 $ffb8 -$0048 IEEESPTanh(parm)(d0)
 78 $ffb2 -$004e IEEESPExp(parm)(d0)
 84 $ffac -$0054 IEEESPLog(parm)(d0)
 90 $ffa6 -$005a IEEESPPow(exp,arg)(d1,d0)
 96 $ffa0 -$0060 IEEESPSqrt(parm)(d0)
102 $ff9a -$0066 IEEESPTieee(parm)(d0)
108 $ff94 -$006c IEEESPFieee(parm)(d0)
114 $ff8e -$0072 IEEESPAsin(parm)(d0)
120 $ff88 -$0078 IEEESPAcos(parm)(d0)
126 $ff82 -$007e IEEESPLog10(parm)(d0)
##end

***************** mathtrans
* "mathtrans.library"
##base _MathTransBase
##bias 30
##public
 30 $ffe2 -$001e SPAtan(parm)(d0)
 36 $ffdc -$0024 SPSin(parm)(d0)
 42 $ffd6 -$002a SPCos(parm)(d0)
 48 $ffd0 -$0030 SPTan(parm)(d0)
 54 $ffca -$0036 SPSincos(cosResult,parm)(d1,d0)
 60 $ffc4 -$003c SPSinh(parm)(d0)
 66 $ffbe -$0042 SPCosh(parm)(d0)
 72 $ffb8 -$0048 SPTanh(parm)(d0)
 78 $ffb2 -$004e SPExp(parm)(d0)
 84 $ffac -$0054 SPLog(parm)(d0)
 90 $ffa6 -$005a SPPow(power,arg)(d1,d0)
 96 $ffa0 -$0060 SPSqrt(parm)(d0)
102 $ff9a -$0066 SPTieee(parm)(d0)
108 $ff94 -$006c SPFieee(parm)(d0)
*--- functions in V31 or higher (distributed as Release 1.1) ---
114 $ff8e -$0072 SPAsin(parm)(d0)
120 $ff88 -$0078 SPAcos(parm)(d0)
126 $ff82 -$007e SPLog10(parm)(d0)
##end

***************** misc
##base _MiscBase
##bias 6
##public
  6 $fffa -$0006 AllocMiscResource(unitNum,name)(d0/a1)
 12 $fff4 -$000c FreeMiscResource(unitNum)(d0)
##end

***************** potgo
* "potgo.resource"
##base _PotgoBase
##bias 6
##public
  6 $fffa -$0006 AllocPotBits(bits)(d0)
 12 $fff4 -$000c FreePotBits(bits)(d0)
 18 $ffee -$0012 WritePotgo(word,mask)(d0/d1)
##end

***************** ramdrive
* "ramdrive.device"
##base _RamdriveDevice
##bias 42
##public
*--- functions in V34 or higher (distributed as Release 1.3) ---
 42 $ffd6 -$002a KillRAD0()()
*--- functions in V36 or higher (distributed as Release 2.0) ---
 48 $ffd0 -$0030 KillRAD(unit)(d0)
##end

***************** rexxsyslib
* "rexxsyslib.library"
##base _RexxSysBase
##bias 30
*--- functions in V33 or higher (distributed as Release 1.2) ---
*
##private
*--- (16 function slots reserved here) ---
##bias 126
##public
*
126 $ff82 -$007e CreateArgstring(string,length)(a0,d0)
132 $ff7c -$0084 DeleteArgstring(argstring)(a0)
138 $ff76 -$008a LengthArgstring(argstring)(a0)
144 $ff70 -$0090 CreateRexxMsg(port,extension,host)(a0/a1,d0)
150 $ff6a -$0096 DeleteRexxMsg(packet)(a0)
156 $ff64 -$009c ClearRexxMsg(msgptr,count)(a0,d0)
162 $ff5e -$00a2 FillRexxMsg(msgptr,count,mask)(a0,d0/d1)
168 $ff58 -$00a8 IsRexxMsg(msgptr)(a0)
*
##private
*--- (46 function slots reserved here) ---
##bias 450
##public
*
450 $fe3e -$01c2 LockRexxBase(resource)(d0)
456 $fe38 -$01c8 UnlockRexxBase(resource)(d0)
*
##end

***************** timer
* "Timer.Device"
##base _TimerBase
##bias 42
##public
 42 $ffd6 -$002a AddTime(dest,src)(a0/a1)
 48 $ffd0 -$0030 SubTime(dest,src)(a0/a1)
 54 $ffca -$0036 CmpTime(dest,src)(a0/a1)
 60 $ffc4 -$003c ReadEClock(dest)(a0)
 66 $ffbe -$0042 GetSysTime(dest)(a0)
##end

***************** translator
* "translator.library"
##base _TranslatorBase
##bias 30
##public
 30 $ffe2 -$001e Translate(inputString,inputLength,outputBuffer,bufferSize)
                  (a0,d0/a1,d1)
##end

***************** utility
* "utility.library"
##base _UtilityBase
##bias 30
##public
* *** TagItem FUNCTIONS ***
 30 $ffe2 -$001e FindTagItem(tagVal,tagList)(d0/a0)
 36 $ffdc -$0024 GetTagData(tagVal,defaultVal,tagList)(d0/d1/a0)
 42 $ffd6 -$002a PackBoolTags(initialFlags,tagList,boolMap)(d0/a0/a1)
 48 $ffd0 -$0030 NextTagItem(tagListPtr)(a0)
 54 $ffca -$0036 FilterTagChanges(newTagList,oldTagList,apply)(a0/a1,d0)
 60 $ffc4 -$003c MapTags(tagList,mapList,includeMiss)(a0/a1,d0)
 66 $ffbe -$0042 AllocateTagItems(numItems)(d0)
 72 $ffb8 -$0048 CloneTagItems(tagList)(a0)
 78 $ffb2 -$004e FreeTagItems(tagList)(a0)
 84 $ffac -$0054 RefreshTagItemClones(cloneList,origList)(a0/a1)
 90 $ffa6 -$005a TagInArray(tagVal,tagArray)(d0/a0)
 96 $ffa0 -$0060 FilterTagItems(tagList,filterArray,logic)(a0/a1,d0)
*
* *** HOOK FUNCTIONS *** *
102 $ff9a -$0066 CallHookPkt(hook,object,paramPacket)(a0/a2,a1)
*--- (1 function slot reserved here) ---
##bias 114
*
* *** DATE FUNCTIONS *** *
*--- (1 function slot reserved here) ---
##bias 120
120 $ff88 -$0078 Amiga2Date(amigaTime,date)(d0/a0)
126 $ff82 -$007e Date2Amiga(date)(a0)
132 $ff7c -$0084 CheckDate(date)(a0)
*
* *** 32 BIT MATH FUNCTIONS *** *
138 $ff76 -$008a SMult32(factor1,factor2)(d0/d1)
144 $ff70 -$0090 UMult32(factor1,factor2)(d0/d1)
* NOTE: Quotient:Remainder returned in d0:d1
150 $ff6a -$0096 SDivMod32(dividend,divisor)(d0/d1)
156 $ff64 -$009c UDivMod32(dividend,divisor)(d0/d1)
*
* *** International string routines ***
162 $ff5e -$00a2 Stricmp(string1,string2)(a0/a1)
168 $ff58 -$00a8 Strnicmp(string1,string2,length)(a0/a1,d0)
174 $ff52 -$00ae ToUpper(character)(d0)
180 $ff4c -$00b4 ToLower(character)(d0)
##end

***************** wb
* "workbench.library"
##base _WorkbenchBase
##bias 30
*--- functions in V36 or higher (distributed as Release 2.0) ---
*
##private
*
 30 $ffe2 -$001e UpdateWorkbench(name,lock,flag)(a0/a1,d0)
 36 $ffdc -$0024 QuoteWorkbench(stringNum)(d0)
*
 42 $ffd6 -$002a StartWorkbench(flags,ptr)(d0/d1)
*
##public
*
 48 $ffd0 -$0030 AddAppWindowA(id,userdata,window,msgport,taglist)
                  (d0/d1/a0/a1/a2)
*
 54 $ffca -$0036 RemoveAppWindow(appWindow)(a0)
*
 60 $ffc4 -$003c AddAppIconA(id,userdata,text,msgport,lock,diskobj,taglist)
                  (d0/d1/a0/a1/a2/a3/a4)
*
 66 $ffbe -$0042 RemoveAppIcon(appIcon)(a0)
*
 72 $ffb8 -$0048 AddAppMenuItemA(id,userdata,text,msgport,taglist)
                  (d0/d1/a0/a1/a2)
*
 78 $ffb2 -$004e RemoveAppMenuItem(appMenuItem)(a0)
*
*--- (5 function slots reserved here) ---
##bias 114
*
##end


References/Structure.offs

AChain:
  $0112   274  sizeof(AChain)
  $0000     0  an_Child
  $0004     4  an_Parent
  $0008     8  an_Lock
  $000c    12  an_Info
  $0110   272  an_Flags
  $0111   273  an_String[0]
AnalogSignalInterval:
  $0004     4  sizeof(
    AnalogSignalInterval)
  $0000     0  asi_Start
  $0002     2  asi_Stop
AnchorPath:
  $011a   282  sizeof(AnchorPath)
  $0000     0  ap_Base
  $0004     4  ap_Last
  $0008     8  ap_BreakBits
  $000c    12  ap_FoundBreak
  $0010    16  ap_Flags
  $0011    17  ap_Reserved
  $0012    18  ap_Strlen
  $0014    20  ap_Info
  $0118   280  ap_Buf[0]
AnimComp:
  $0026    38  sizeof(AnimComp)
  $0000     0  Flags
  $0002     2  Timer
  $0004     4  TimeSet
! $0006     6  NextComp
! $000a    10  PrevComp
! $000e    14  NextSeq
! $0012    18  PrevSeq
! $0016    22  AnimCRoutine
  $001a    26  YTrans
  $001c    28  XTrans
! $001e    30  HeadOb
! $0022    34  AnimBob
AnimOb:
  $002a    42  sizeof(AnimOb)
  $0000     0  NextOb
  $0004     4  PrevOb
  $0008     8  Clock
  $000c    12  AnOldY
  $000e    14  AnOldX
  $0010    16  AnY
  $0012    18  AnX
  $0014    20  YVel
  $0016    22  XVel
  $0018    24  YAccel
  $001a    26  XAccel
  $001c    28  RingYTrans
  $001e    30  RingXTrans
  $0020    32  AnimORoutine
  $0024    36  HeadComp
  $0028    40  AUserExt
AppIcon:
  $0020    32  sizeof(AppIcon)
  $0000     0  ai_Node
! $000e    14  ai_Ptr
! $0012    18  ai_MsgPort
! $0016    22  ai_UserData
! $001a    26  ai_ID
  $001e    30  ai_Version
AppMenuItem:
  $0020    32  sizeof(AppMenuItem)
  $0000     0  ami_Node
! $000e    14  ami_Ptr
! $0012    18  ami_MsgPort
! $0016    22  ami_UserData
! $001a    26  ami_ID
  $001e    30  ami_Version
AppMessage:
  $0056    86  sizeof(AppMessage)
  $0000     0  am_Message
  $0014    20  am_Type
! $0016    22  am_UserData
! $001a    26  am_ID
! $001e    30  am_NumArgs
! $0022    34  am_ArgList
  $0026    38  am_Version
  $0028    40  am_Class
  $002a    42  am_MouseX
  $002c    44  am_MouseY
! $002e    46  am_Seconds
! $0032    50  am_Micros
! $0036    54  am_Reserved[0]
AppWindow:
  $0020    32  sizeof(AppWindow)
  $0000     0  aw_Node
! $000e    14  aw_Ptr
! $0012    18  aw_MsgPort
! $0016    22  aw_UserData
! $001a    26  aw_ID
  $001e    30  aw_Version
AreaInfo:
  $0018    24  sizeof(AreaInfo)
  $0000     0  VctrTbl
  $0004     4  VctrPtr
  $0008     8  FlagTbl
  $000c    12  FlagPtr
  $0010    16  Count
  $0012    18  MaxCount
  $0014    20  FirstX
  $0016    22  FirstY
AssignList:
  $0008     8  sizeof(AssignList)
  $0000     0  al_Next
  $0004     4  al_Lock
AudChannel:
  $0010    16  sizeof(AudChannel)
  $0000     0  ac_ptr
  $0004     4  ac_len
  $0006     6  ac_per
  $0008     8  ac_vol
  $000a    10  ac_dat
  $000c    12  ac_pad[0]
AvailFonts:
  $000a    10  sizeof(AvailFonts)
  $0000     0  af_Type
! $0002     2  af_Attr
AvailFontsHeader:
  $0002     2  sizeof(AvailFontsHeader)
  $0000     0  afh_NumEntries
BadBlockBlock:
  $0200   512  sizeof(BadBlockBlock)
  $0000     0  bbb_ID
  $0004     4  bbb_SummedLongs
  $0008     8  bbb_ChkSum
  $000c    12  bbb_HostID
  $0010    16  bbb_Next
  $0014    20  bbb_Reserved
  $0018    24  bbb_BlockPairs[0]
BadBlockEntry:
  $0008     8  sizeof(BadBlockEntry)
  $0000     0  bbe_BadBlock
  $0004     4  bbe_GoodBlock
BitMap:
  $0028    40  sizeof(BitMap)
  $0000     0  BytesPerRow
  $0002     2  Rows
  $0004     4  Flags
  $0005     5  Depth
  $0006     6  pad
  $0008     8  Planes[0]
BitScaleArgs:
  $0030    48  sizeof(BitScaleArgs)
  $0000     0  bsa_SrcX
  $0002     2  bsa_SrcY
  $0004     4  bsa_SrcWidth
  $0006     6  bsa_SrcHeight
  $0008     8  bsa_XSrcFactor
  $000a    10  bsa_YSrcFactor
  $000c    12  bsa_DestX
  $000e    14  bsa_DestY
  $0010    16  bsa_DestWidth
  $0012    18  bsa_DestHeight
  $0014    20  bsa_XDestFactor
  $0016    22  bsa_YDestFactor
  $0018    24  bsa_SrcBitMap
  $001c    28  bsa_DestBitMap
  $0020    32  bsa_Flags
  $0024    36  bsa_XDDA
  $0026    38  bsa_YDDA
  $0028    40  bsa_Reserved1
  $002c    44  bsa_Reserved2
Bob:
  $0020    32  sizeof(Bob)
  $0000     0  Flags
! $0002     2  SaveBuffer
! $0006     6  ImageShadow
! $000a    10  Before
! $000e    14  After
! $0012    18  BobVSprite
! $0016    22  BobComp
! $001a    26  DBuffer
  $001e    30  BUserExt
BoolInfo:
  $000a    10  sizeof(BoolInfo)
  $0000     0  Flags
! $0002     2  Mask
! $0006     6  Reserved
BootBlock:
  $000c    12  sizeof(BootBlock)
  $0000     0  bb_id[0]
  $0004     4  bb_chksum
  $0008     8  bb_dosblock
BootNode:
  $0014    20  sizeof(BootNode)
  $0000     0  bn_Node
  $000e    14  bn_Flags
  $0010    16  bn_DeviceNode
Border:
  $0010    16  sizeof(Border)
  $0000     0  LeftEdge
  $0002     2  TopEdge
  $0004     4  FrontPen
  $0005     5  BackPen
  $0006     6  DrawMode
  $0007     7  Count
  $0008     8  XY
  $000c    12  NextBorder
CIA:
  $0f02  3842  sizeof(CIA)
  $0000     0  ciapra
! $0001     1  pad0[0]
  $0100   256  ciaprb
! $0101   257  pad1[0]
  $0200   512  ciaddra
! $0201   513  pad2[0]
  $0300   768  ciaddrb
! $0301   769  pad3[0]
  $0400  1024  ciatalo
! $0401  1025  pad4[0]
  $0500  1280  ciatahi
! $0501  1281  pad5[0]
  $0600  1536  ciatblo
! $0601  1537  pad6[0]
  $0700  1792  ciatbhi
! $0701  1793  pad7[0]
  $0800  2048  ciatodlow
! $0801  2049  pad8[0]
  $0900  2304  ciatodmid
! $0901  2305  pad9[0]
  $0a00  2560  ciatodhi
! $0a01  2561  pad10[0]
  $0b00  2816  unusedreg
! $0b01  2817  pad11[0]
  $0c00  3072  ciasdr
! $0c01  3073  pad12[0]
  $0d00  3328  ciaicr
! $0d01  3329  pad13[0]
  $0e00  3584  ciacra
! $0e01  3585  pad14[0]
  $0f00  3840  ciacrb
CSource:
  $000c    12  sizeof(CSource)
  $0000     0  CS_Buffer
  $0004     4  CS_Length
  $0008     8  CS_CurChr
CliProcList:
  $0010    16  sizeof(CliProcList)
  $0000     0  cpl_Node
  $0008     8  cpl_First
  $000c    12  cpl_Array
ClipHookMsg:
  $000c    12  sizeof(ClipHookMsg)
  $0000     0  chm_Type
  $0004     4  chm_ChangeCmd
  $0008     8  chm_ClipID
ClipRect:
  $0024    36  sizeof(ClipRect)
  $0000     0  Next
  $0004     4  prev
  $0008     8  lobs
  $000c    12  BitMap
  $0010    16  bounds
  $0018    24  _p1
  $001c    28  _p2
  $0020    32  reserved
ClipboardHandle:
  $0078   120  sizeof(ClipboardHandle)
  $0000     0  cbh_Req
  $0034    52  cbh_CBport
! $0056    86  cbh_SatisfyPort
ClipboardUnitPartial:
  $0012    18  sizeof(
    ClipboardUnitPartial)
  $0000     0  cu_Node
! $000e    14  cu_UnitNum
ClockData:
  $000e    14  sizeof(ClockData)
  $0000     0  sec
  $0002     2  min
  $0004     4  hour
  $0006     6  mday
  $0008     8  month
  $000a    10  year
  $000c    12  wday
CollectionItem:
  $000c    12  sizeof(CollectionItem)
  $0000     0  ci_Next
  $0004     4  ci_Size
  $0008     8  ci_Data
ColorFontColors:
  $0008     8  sizeof(ColorFontColors)
  $0000     0  cfc_Reserved
  $0002     2  cfc_Count
  $0004     4  cfc_ColorTable
ColorMap:
  $0028    40  sizeof(ColorMap)
  $0000     0  Flags
  $0001     1  Type
  $0002     2  Count
  $0004     4  ColorTable
  $0008     8  cm_vpe
  $000c    12  TransparencyBits
  $0010    16  TransparencyPlane
  $0011    17  reserved1
  $0012    18  reserved2
  $0014    20  cm_vp
  $0018    24  NormalDisplayInfo
  $001c    28  CoerceDisplayInfo
  $0020    32  cm_batch_items
  $0024    36  VPModeID
ColorSpec:
  $0008     8  sizeof(ColorSpec)
  $0000     0  ColorIndex
  $0002     2  Red
  $0004     4  Green
  $0006     6  Blue
ColorTextFont:
  $0060    96  sizeof(ColorTextFont)
  $0000     0  ctf_TF
  $0034    52  ctf_Flags
  $0036    54  ctf_Depth
  $0037    55  ctf_FgColor
  $0038    56  ctf_Low
  $0039    57  ctf_High
  $003a    58  ctf_PlanePick
  $003b    59  ctf_PlaneOnOff
  $003c    60  ctf_ColorFontColors
  $0040    64  ctf_CharData[0]
CommandLineInterface:
  $0040    64  sizeof(
    CommandLineInterface)
  $0000     0  cli_Result2
  $0004     4  cli_SetName
  $0008     8  cli_CommandDir
  $000c    12  cli_ReturnCode
  $0010    16  cli_CommandName
  $0014    20  cli_FailLevel
  $0018    24  cli_Prompt
  $001c    28  cli_StandardInput
  $0020    32  cli_CurrentInput
  $0024    36  cli_CommandFile
  $0028    40  cli_Interactive
  $002c    44  cli_Background
  $0030    48  cli_CurrentOutput
  $0034    52  cli_DefaultStack
  $0038    56  cli_StandardOutput
  $003c    60  cli_Module
ConUnit:
  $0128   296  sizeof(ConUnit)
  $0000     0  cu_MP
! $0022    34  cu_Window
  $0026    38  cu_XCP
  $0028    40  cu_YCP
  $002a    42  cu_XMax
  $002c    44  cu_YMax
  $002e    46  cu_XRSize
  $0030    48  cu_YRSize
  $0032    50  cu_XROrigin
  $0034    52  cu_YROrigin
  $0036    54  cu_XRExtant
  $0038    56  cu_YRExtant
  $003a    58  cu_XMinShrink
  $003c    60  cu_YMinShrink
  $003e    62  cu_XCCP
  $0040    64  cu_YCCP
! $0042    66  cu_KeyMapStruct
! $0062    98  cu_TabStops[0]
  $0102   258  cu_Mask
  $0103   259  cu_FgPen
  $0104   260  cu_BgPen
  $0105   261  cu_AOLPen
  $0106   262  cu_DrawMode
  $0107   263  cu_Obsolete1
  $0108   264  cu_Obsolete2
  $010c   268  cu_Minterms[0]
  $0114   276  cu_Font
  $0118   280  cu_AlgoStyle
  $0119   281  cu_TxFlags
  $011a   282  cu_TxHeight
  $011c   284  cu_TxWidth
  $011e   286  cu_TxBaseline
  $0120   288  cu_TxSpacing
  $0122   290  cu_Modes[0]
  $0125   293  cu_RawEvents[0]
ConfigDev:
  $0044    68  sizeof(ConfigDev)
  $0000     0  cd_Node
  $000e    14  cd_Flags
  $000f    15  cd_Pad
  $0010    16  cd_Rom
  $0020    32  cd_BoardAddr
  $0024    36  cd_BoardSize
  $0028    40  cd_SlotAddr
  $002a    42  cd_SlotSize
  $002c    44  cd_Driver
  $0030    48  cd_NextCD
  $0034    52  cd_Unused[0]
ContextNode:
  $0018    24  sizeof(ContextNode)
  $0000     0  cn_Node
  $0008     8  cn_ID
  $000c    12  cn_Type
  $0010    16  cn_Size
  $0014    20  cn_Scan
CopIns:
  $0006     6  sizeof(CopIns)
  $0000     0  OpCode
  $0002     2  u3
  $0002     2  u3.nxtlist
  $0002     2  u3.u4
  $0002     2  u3.u4.u1
  $0002     2  u3.u4.u1.VWaitPos
  $0002     2  u3.u4.u1.DestAddr
  $0004     4  u3.u4.u2
  $0004     4  u3.u4.u2.HWaitPos
  $0004     4  u3.u4.u2.DestData
CopList:
  $0022    34  sizeof(CopList)
  $0000     0  Next
  $0004     4  _CopList
  $0008     8  _ViewPort
  $000c    12  CopIns
  $0010    16  CopPtr
  $0014    20  CopLStart
  $0018    24  CopSStart
  $001c    28  Count
  $001e    30  MaxCount
  $0020    32  DyOffset
CurrentBinding:
  $0010    16  sizeof(CurrentBinding)
  $0000     0  cb_ConfigDev
  $0004     4  cb_FileName
  $0008     8  cb_ProductString
  $000c    12  cb_ToolTypes
Custom:
  $01e6   486  sizeof(Custom)
  $0000     0  bltddat
  $0002     2  dmaconr
  $0004     4  vposr
  $0006     6  vhposr
  $0008     8  dskdatr
  $000a    10  joy0dat
  $000c    12  joy1dat
  $000e    14  clxdat
  $0010    16  adkconr
  $0012    18  pot0dat
  $0014    20  pot1dat
  $0016    22  potinp
  $0018    24  serdatr
  $001a    26  dskbytr
  $001c    28  intenar
  $001e    30  intreqr
  $0020    32  dskpt
  $0024    36  dsklen
  $0026    38  dskdat
  $0028    40  refptr
  $002a    42  vposw
  $002c    44  vhposw
  $002e    46  copcon
  $0030    48  serdat
  $0032    50  serper
  $0034    52  potgo
  $0036    54  joytest
  $0038    56  strequ
  $003a    58  strvbl
  $003c    60  strhor
  $003e    62  strlong
  $0040    64  bltcon0
  $0042    66  bltcon1
  $0044    68  bltafwm
  $0046    70  bltalwm
  $0048    72  bltcpt
  $004c    76  bltbpt
  $0050    80  bltapt
  $0054    84  bltdpt
  $0058    88  bltsize
  $005a    90  pad2d
  $005b    91  bltcon0l
  $005c    92  bltsizv
  $005e    94  bltsizh
  $0060    96  bltcmod
  $0062    98  bltbmod
  $0064   100  bltamod
  $0066   102  bltdmod
  $0068   104  pad34[0]
  $0070   112  bltcdat
  $0072   114  bltbdat
  $0074   116  bltadat
! $0076   118  pad3b[0]
  $007c   124  deniseid
  $007e   126  dsksync
  $0080   128  cop1lc
  $0084   132  cop2lc
  $0088   136  copjmp1
  $008a   138  copjmp2
  $008c   140  copins
  $008e   142  diwstrt
  $0090   144  diwstop
  $0092   146  ddfstrt
  $0094   148  ddfstop
  $0096   150  dmacon
  $0098   152  clxcon
  $009a   154  intena
  $009c   156  intreq
  $009e   158  adkcon
  $0000     0  ac_ptr
  $0004     4  ac_len
  $0006     6  ac_per
  $0008     8  ac_vol
  $000a    10  ac_dat
  $000c    12  ac_pad[0]
  $00a0   160  aud[0]
  $00e0   224  bplpt[0]
  $0100   256  bplcon0
  $0102   258  bplcon1
  $0104   260  bplcon2
  $0106   262  bplcon3
  $0108   264  bpl1mod
  $010a   266  bpl2mod
  $010c   268  bplhmod
  $010e   270  pad86[0]
  $0110   272  bpldat[0]
  $0120   288  sprpt[0]
  $0000     0  pos
  $0002     2  ctl
  $0004     4  dataa
! $0006     6  datab
  $0140   320  spr[0]
  $0180   384  color[0]
  $01c0   448  htotal
  $01c2   450  hsstop
  $01c4   452  hbstrt
  $01c6   454  hbstop
  $01c8   456  vtotal
  $01ca   458  vsstop
  $01cc   460  vbstrt
  $01ce   462  vbstop
  $01d0   464  sprhstrt
  $01d2   466  sprhstop
  $01d4   468  bplhstrt
  $01d6   470  bplhstop
  $01d8   472  hhposw
  $01da   474  hhposr
  $01dc   476  beamcon0
  $01de   478  hsstrt
  $01e0   480  vsstrt
  $01e2   482  hcenter
  $01e4   484  diwhigh
DBufPacket:
  $000c    12  sizeof(DBufPacket)
  $0000     0  BufY
  $0002     2  BufX
  $0004     4  BufPath
  $0008     8  BufBuffer
DateStamp:
  $000c    12  sizeof(DateStamp)
  $0000     0  ds_Days
  $0004     4  ds_Minute
  $0008     8  ds_Tick
DateTime:
  $001a    26  sizeof(DateTime)
  $0000     0  dat_Stamp
  $000c    12  dat_Format
  $000d    13  dat_Flags
! $000e    14  dat_StrDay
! $0012    18  dat_StrDate
! $0016    22  dat_StrTime
DevInfo:
  $002c    44  sizeof(DevInfo)
  $0000     0  dvi_Next
  $0004     4  dvi_Type
  $0008     8  dvi_Task
  $000c    12  dvi_Lock
  $0010    16  dvi_Handler
  $0014    20  dvi_StackSize
  $0018    24  dvi_Priority
  $001c    28  dvi_Startup
  $0020    32  dvi_SegList
  $0024    36  dvi_GlobVec
  $0028    40  dvi_Name
DevProc:
  $0010    16  sizeof(DevProc)
  $0000     0  dvp_Port
  $0004     4  dvp_Lock
  $0008     8  dvp_Flags
  $000c    12  dvp_DevNode
Device:
  $0022    34  sizeof(Device)
  $0000     0  dd_Library
DeviceData:
  $0034    52  sizeof(DeviceData)
  $0000     0  dd_Device
! $0022    34  dd_Segment
! $0026    38  dd_ExecBase
! $002a    42  dd_CmdVectors
! $002e    46  dd_CmdBytes
  $0032    50  dd_NumCommands
DeviceList:
  $002c    44  sizeof(DeviceList)
  $0000     0  dl_Next
  $0004     4  dl_Type
  $0008     8  dl_Task
  $000c    12  dl_Lock
  $0010    16  dl_VolumeDate
  $001c    28  dl_LockList
  $0020    32  dl_DiskType
  $0024    36  dl_unused
  $0028    40  dl_Name
DeviceNode:
  $002c    44  sizeof(DeviceNode)
  $0000     0  dn_Next
  $0004     4  dn_Type
  $0008     8  dn_Task
  $000c    12  dn_Lock
  $0010    16  dn_Handler
  $0014    20  dn_StackSize
  $0018    24  dn_Priority
  $001c    28  dn_Startup
  $0020    32  dn_SegList
  $0024    36  dn_GlobalVec
  $0028    40  dn_Name
DiagArea:
  $000e    14  sizeof(DiagArea)
  $0000     0  da_Config
  $0001     1  da_Flags
  $0002     2  da_Size
  $0004     4  da_DiagPoint
  $0006     6  da_BootPoint
  $0008     8  da_Name
  $000a    10  da_Reserved01
  $000c    12  da_Reserved02
DimensionInfo:
  $0058    88  sizeof(DimensionInfo)
  $0000     0  Header
  $0010    16  MaxDepth
  $0012    18  MinRasterWidth
  $0014    20  MinRasterHeight
  $0016    22  MaxRasterWidth
  $0018    24  MaxRasterHeight
! $001a    26  Nominal
! $0022    34  MaxOScan
! $002a    42  VideoOScan
! $0032    50  TxtOScan
! $003a    58  StdOScan
! $0042    66  pad[0]
  $0050    80  reserved[0]
DiscResource:
  $0094   148  sizeof(DiscResource)
  $0000     0  dr_Library
! $0022    34  dr_Current
  $0026    38  dr_Flags
  $0027    39  dr_pad
  $0028    40  dr_SysLib
  $002c    44  dr_CiaResource
  $0030    48  dr_UnitID[0]
  $0040    64  dr_Waiting
! $004e    78  dr_DiscBlock
  $0064   100  dr_DiscSync
! $007a   122  dr_Index
  $0090   144  dr_CurrTask
DiscResourceUnit:
  $0056    86  sizeof(DiscResourceUnit)
  $0000     0  dru_Message
  $0014    20  dru_DiscBlock
! $002a    42  dru_DiscSync
  $0040    64  dru_Index
DiskFontHeader:
  $006a   106  sizeof(DiskFontHeader)
  $0000     0  dfh_DF
  $000e    14  dfh_FileID
  $0010    16  dfh_Revision
! $0012    18  dfh_Segment
! $0016    22  dfh_Name[0]
! $0036    54  dfh_TF
DiskObject:
  $004e    78  sizeof(DiskObject)
  $0000     0  do_Magic
  $0002     2  do_Version
  $0004     4  do_Gadget
  $0030    48  do_Type
! $0032    50  do_DefaultTool
! $0036    54  do_ToolTypes
! $003a    58  do_CurrentX
! $003e    62  do_CurrentY
! $0042    66  do_DrawerData
! $0046    70  do_ToolWindow
! $004a    74  do_StackSize
DisplayInfo:
  $0030    48  sizeof(DisplayInfo)
  $0000     0  Header
  $0010    16  NotAvailable
! $0012    18  PropertyFlags
! $0016    22  Resolution
  $001a    26  PixelSpeed
  $001c    28  NumStdSprites
  $001e    30  PaletteRange
  $0020    32  SpriteResolution
  $0024    36  pad[0]
  $0028    40  reserved[0]
DosEnvec:
  $0050    80  sizeof(DosEnvec)
  $0000     0  de_TableSize
  $0004     4  de_SizeBlock
  $0008     8  de_SecOrg
  $000c    12  de_Surfaces
  $0010    16  de_SectorPerBlock
  $0014    20  de_BlocksPerTrack
  $0018    24  de_Reserved
  $001c    28  de_PreAlloc
  $0020    32  de_Interleave
  $0024    36  de_LowCyl
  $0028    40  de_HighCyl
  $002c    44  de_NumBuffers
  $0030    48  de_BufMemType
  $0034    52  de_MaxTransfer
  $0038    56  de_Mask
  $003c    60  de_BootPri
  $0040    64  de_DosType
  $0044    68  de_Baud
  $0048    72  de_Control
  $004c    76  de_BootBlocks
DosInfo:
  $0070   112  sizeof(DosInfo)
  $0000     0  di_McName
  $0004     4  di_DevInfo
  $0008     8  di_Devices
  $000c    12  di_Handlers
  $0010    16  di_NetHand
  $0014    20  di_DevLock
! $0042    66  di_EntryLock
DosLibrary:
  $0042    66  sizeof(DosLibrary)
  $0000     0  dl_lib
! $0022    34  dl_Root
! $0026    38  dl_GV
! $002a    42  dl_A2
! $002e    46  dl_A5
! $0032    50  dl_A6
! $0036    54  dl_Errors
! $003a    58  dl_TimeReq
! $003e    62  dl_UtilityBase
DosList:
  $002c    44  sizeof(DosList)
  $0000     0  dol_Next
  $0004     4  dol_Type
  $0008     8  dol_Task
  $000c    12  dol_Lock
  $0010    16  dol_misc
  $0010    16  dol_misc.dol_handler
  $0010    16
      dol_misc.dol_handler.dol_Handler
  $0014    20
      dol_misc.dol_handler.dol_StackSize
  $0018    24
      dol_misc.dol_handler.dol_Priority
  $001c    28
      dol_misc.dol_handler.dol_Startup
  $0020    32
      dol_misc.dol_handler.dol_SegList
  $0024    36
      dol_misc.dol_handler.dol_GlobVec
  $0010    16  dol_misc.dol_volume
  $0010    16
      dol_misc.dol_volume.dol_VolumeDate
  $001c    28
      dol_misc.dol_volume.dol_LockList
  $0020    32
      dol_misc.dol_volume.dol_DiskType
  $0010    16  dol_misc.dol_assign
  $0010    16
      dol_misc.dol_assign.dol_AssignName
  $0014    20
      dol_misc.dol_assign.dol_List
  $0028    40  dol_Name
DosPacket:
  $0030    48  sizeof(DosPacket)
  $0000     0  dp_Link
  $0004     4  dp_Port
  $0008     8  dp_Type
  $000c    12  dp_Res1
  $0010    16  dp_Res2
  $0014    20  dp_Arg1
  $0018    24  dp_Arg2
  $001c    28  dp_Arg3
  $0020    32  dp_Arg4
  $0024    36  dp_Arg5
  $0028    40  dp_Arg6
  $002c    44  dp_Arg7
DrawInfo:
  $0032    50  sizeof(DrawInfo)
  $0000     0  dri_Version
  $0002     2  dri_NumPens
  $0004     4  dri_Pens
  $0008     8  dri_Font
  $000c    12  dri_Depth
  $000e    14  dri_Resolution
  $000e    14  dri_Resolution.X
  $0010    16  dri_Resolution.Y
! $0012    18  dri_Flags
! $0016    22  dri_Reserved[0]
DrawerData:
  $003e    62  sizeof(DrawerData)
  $0000     0  dd_NewWindow
  $0030    48  dd_CurrentX
  $0034    52  dd_CurrentY
  $0038    56  dd_Flags
  $003c    60  dd_ViewModes
DriveGeometry:
  $0020    32  sizeof(DriveGeometry)
  $0000     0  dg_SectorSize
  $0004     4  dg_TotalSectors
  $0008     8  dg_Cylinders
  $000c    12  dg_CylSectors
  $0010    16  dg_Heads
  $0014    20  dg_TrackSectors
  $0018    24  dg_BufMemType
  $001c    28  dg_DeviceType
  $001d    29  dg_Flags
  $001e    30  dg_Reserved
EClockVal:
  $0008     8  sizeof(EClockVal)
  $0000     0  ev_hi
  $0004     4  ev_lo
EasyStruct:
  $0014    20  sizeof(EasyStruct)
  $0000     0  es_StructSize
  $0004     4  es_Flags
  $0008     8  es_Title
  $000c    12  es_TextFormat
  $0010    16  es_GadgetFormat
ErrorString:
  $0008     8  sizeof(ErrorString)
  $0000     0  estr_Nums
  $0004     4  estr_Strings
ExAllControl:
  $0010    16  sizeof(ExAllControl)
  $0000     0  eac_Entries
  $0004     4  eac_LastKey
  $0008     8  eac_MatchString
  $000c    12  eac_MatchFunc
ExAllData:
  $0024    36  sizeof(ExAllData)
  $0000     0  ed_Next
  $0004     4  ed_Name
  $0008     8  ed_Type
  $000c    12  ed_Size
  $0010    16  ed_Prot
  $0014    20  ed_Days
  $0018    24  ed_Mins
  $001c    28  ed_Ticks
  $0020    32  ed_Comment
ExecBase:
  $0268   616  sizeof(ExecBase)
  $0000     0  LibNode
  $0022    34  SoftVer
  $0024    36  LowMemChkSum
! $0026    38  ChkBase
! $002a    42  ColdCapture
! $002e    46  CoolCapture
! $0032    50  WarmCapture
! $0036    54  SysStkUpper
! $003a    58  SysStkLower
! $003e    62  MaxLocMem
! $0042    66  DebugEntry
! $0046    70  DebugData
! $004a    74  AlertData
! $004e    78  MaxExtMem
  $0052    82  ChkSum
  $0054    84  IntVects[0]
  $0114   276  ThisTask
  $0118   280  IdleCount
  $011c   284  DispCount
  $0120   288  Quantum
  $0122   290  Elapsed
  $0124   292  SysFlags
  $0126   294  IDNestCnt
  $0127   295  TDNestCnt
  $0128   296  AttnFlags
  $012a   298  AttnResched
  $012c   300  ResModules
  $0130   304  TaskTrapCode
  $0134   308  TaskExceptCode
  $0138   312  TaskExitCode
  $013c   316  TaskSigAlloc
  $0140   320  TaskTrapAlloc
! $0142   322  MemList
  $0150   336  ResourceList
! $015e   350  DeviceList
  $016c   364  IntrList
! $017a   378  LibList
  $0188   392  PortList
! $0196   406  TaskReady
  $01a4   420  TaskWait
! $01b2   434  SoftInts[0]
! $0202   514  LastAlert[0]
  $0212   530  VBlankFrequency
  $0213   531  PowerSupplyFrequency
  $0214   532  SemaphoreList
! $0222   546  KickMemPtr
! $0226   550  KickTagPtr
! $022a   554  KickCheckSum
  $022e   558  ex_Pad0
  $0230   560  ex_Reserved0
  $0234   564  ex_RamLibPrivate
  $0238   568  ex_EClockFrequency
  $023c   572  ex_CacheControl
  $0240   576  ex_TaskID
  $0244   580  ex_PuddleSize
  $0248   584  ex_PoolThreshold
  $024c   588  ex_PublicPool
  $0258   600  ex_MMULock
  $025c   604  ex_Reserved[0]
ExpansionBase:
  $0058    88  sizeof(ExpansionBase)
  $0000     0  LibNode
  $0022    34  Flags
  $0023    35  eb_Private01
  $0024    36  eb_Private02
  $0028    40  eb_Private03
  $002c    44  eb_Private04
  $003c    60  eb_Private05
! $004a    74  MountList
ExpansionControl:
  $0010    16  sizeof(ExpansionControl)
  $0000     0  ec_Interrupt
  $0001     1  ec_Z3_HighBase
  $0002     2  ec_BaseAddress
  $0003     3  ec_Shutup
  $0004     4  ec_Reserved14
  $0005     5  ec_Reserved15
  $0006     6  ec_Reserved16
  $0007     7  ec_Reserved17
  $0008     8  ec_Reserved18
  $0009     9  ec_Reserved19
  $000a    10  ec_Reserved1a
  $000b    11  ec_Reserved1b
  $000c    12  ec_Reserved1c
  $000d    13  ec_Reserved1d
  $000e    14  ec_Reserved1e
  $000f    15  ec_Reserved1f
ExpansionRom:
  $0010    16  sizeof(ExpansionRom)
  $0000     0  er_Type
  $0001     1  er_Product
  $0002     2  er_Flags
  $0003     3  er_Reserved03
  $0004     4  er_Manufacturer
! $0006     6  er_SerialNumber
  $000a    10  er_InitDiagVec
  $000c    12  er_Reserved0c
  $000d    13  er_Reserved0d
  $000e    14  er_Reserved0e
  $000f    15  er_Reserved0f
ExtNewScreen:
  $0024    36  sizeof(ExtNewScreen)
  $0000     0  LeftEdge
  $0002     2  TopEdge
  $0004     4  Width
  $0006     6  Height
  $0008     8  Depth
  $000a    10  DetailPen
  $000b    11  BlockPen
  $000c    12  ViewModes
  $000e    14  Type
  $0010    16  Font
  $0014    20  DefaultTitle
  $0018    24  Gadgets
  $001c    28  CustomBitMap
  $0020    32  Extension
ExtNewWindow:
  $0034    52  sizeof(ExtNewWindow)
  $0000     0  LeftEdge
  $0002     2  TopEdge
  $0004     4  Width
  $0006     6  Height
  $0008     8  DetailPen
  $0009     9  BlockPen
! $000a    10  IDCMPFlags
! $000e    14  Flags
! $0012    18  FirstGadget
! $0016    22  CheckMark
! $001a    26  Title
! $001e    30  Screen
! $0022    34  BitMap
  $0026    38  MinWidth
  $0028    40  MinHeight
  $002a    42  MaxWidth
  $002c    44  MaxHeight
  $002e    46  Type
  $0030    48  Extension
ExtendedNode:
  $0018    24  sizeof(ExtendedNode)
  $0000     0  xln_Succ
  $0004     4  xln_Pred
  $0008     8  xln_Type
  $0009     9  xln_Pri
! $000a    10  xln_Name
  $000e    14  xln_Subsystem
  $000f    15  xln_Subtype
  $0010    16  xln_Library
  $0014    20  xln_Init
FileHandle:
  $002c    44  sizeof(FileHandle)
  $0000     0  fh_Link
  $0004     4  fh_Port
  $0008     8  fh_Type
  $000c    12  fh_Buf
  $0010    16  fh_Pos
  $0014    20  fh_End
  $0018    24  fh_Funcs
  $001c    28  fh_Func2
  $0020    32  fh_Func3
  $0024    36  fh_Args
  $0028    40  fh_Arg2
FileInfoBlock:
  $0104   260  sizeof(FileInfoBlock)
  $0000     0  fib_DiskKey
  $0004     4  fib_DirEntryType
  $0008     8  fib_FileName[0]
  $0074   116  fib_Protection
  $0078   120  fib_EntryType
  $007c   124  fib_Size
  $0080   128  fib_NumBlocks
  $0084   132  fib_Date
  $0090   144  fib_Comment[0]
  $00e0   224  fib_Reserved[0]
FileLock:
  $0014    20  sizeof(FileLock)
  $0000     0  fl_Link
  $0004     4  fl_Key
  $0008     8  fl_Access
  $000c    12  fl_Task
  $0010    16  fl_Volume
FileRequester:
  $002c    44  sizeof(FileRequester)
  $0000     0  rf_Reserved1
  $0004     4  rf_File
  $0008     8  rf_Dir
  $000c    12  rf_Reserved2[0]
  $0016    22  rf_LeftEdge
  $0018    24  rf_TopEdge
  $001a    26  rf_Width
  $001c    28  rf_Height
  $001e    30  rf_Reserved3
  $0020    32  rf_NumArgs
  $0024    36  rf_ArgList
  $0028    40  rf_UserData
FileSysEntry:
  $003e    62  sizeof(FileSysEntry)
  $0000     0  fse_Node
! $000e    14  fse_DosType
! $0012    18  fse_Version
! $0016    22  fse_PatchFlags
! $001a    26  fse_Type
! $001e    30  fse_Task
! $0022    34  fse_Lock
! $0026    38  fse_Handler
! $002a    42  fse_StackSize
! $002e    46  fse_Priority
! $0032    50  fse_Startup
! $0036    54  fse_SegList
! $003a    58  fse_GlobalVec
FileSysHeaderBlock:
  $0100   256  sizeof(FileSysHeaderBlock)
  $0000     0  fhb_ID
  $0004     4  fhb_SummedLongs
  $0008     8  fhb_ChkSum
  $000c    12  fhb_HostID
  $0010    16  fhb_Next
  $0014    20  fhb_Flags
  $0018    24  fhb_Reserved1[0]
  $0020    32  fhb_DosType
  $0024    36  fhb_Version
  $0028    40  fhb_PatchFlags
  $002c    44  fhb_Type
  $0030    48  fhb_Task
  $0034    52  fhb_Lock
  $0038    56  fhb_Handler
  $003c    60  fhb_StackSize
  $0040    64  fhb_Priority
  $0044    68  fhb_Startup
  $0048    72  fhb_SegListBlocks
  $004c    76  fhb_GlobalVec
  $0050    80  fhb_Reserved2[0]
  $00ac   172  fhb_Reserved3[0]
FileSysResource:
  $0020    32  sizeof(FileSysResource)
  $0000     0  fsr_Node
! $000e    14  fsr_Creator
! $0012    18  fsr_FileSysEntries
FileSysStartupMsg:
  $0010    16  sizeof(FileSysStartupMsg)
  $0000     0  fssm_Unit
  $0004     4  fssm_Device
  $0008     8  fssm_Environ
  $000c    12  fssm_Flags
FontContents:
  $0104   260  sizeof(FontContents)
  $0000     0  fc_FileName[0]
  $0100   256  fc_YSize
  $0102   258  fc_Style
  $0103   259  fc_Flags
FontContentsHeader:
  $0004     4  sizeof(FontContentsHeader)
  $0000     0  fch_FileID
  $0002     2  fch_NumEntries
FontRequester:
  $0018    24  sizeof(FontRequester)
  $0000     0  fo_Reserved1[0]
  $0008     8  fo_Attr
  $0010    16  fo_FrontPen
  $0011    17  fo_BackPen
  $0012    18  fo_DrawMode
  $0014    20  fo_UserData
FreeList:
  $0010    16  sizeof(FreeList)
  $0000     0  fl_NumFree
! $0002     2  fl_MemList
Gadget:
  $002c    44  sizeof(Gadget)
  $0000     0  NextGadget
  $0004     4  LeftEdge
  $0006     6  TopEdge
  $0008     8  Width
  $000a    10  Height
  $000c    12  Flags
  $000e    14  Activation
  $0010    16  GadgetType
! $0012    18  GadgetRender
! $0016    22  SelectRender
! $001a    26  GadgetText
! $001e    30  MutualExclude
! $0022    34  SpecialInfo
  $0026    38  GadgetID
  $0028    40  UserData
GadgetInfo:
  $003a    58  sizeof(GadgetInfo)
  $0000     0  gi_Screen
  $0004     4  gi_Window
  $0008     8  gi_Requester
  $000c    12  gi_RastPort
  $0010    16  gi_Layer
  $0014    20  gi_Domain
  $001c    28  gi_Pens
  $001c    28  gi_Pens.DetailPen
  $001d    29  gi_Pens.BlockPen
! $001e    30  gi_DrInfo
! $0022    34  gi_Reserved[0]
GamePortTrigger:
  $0008     8  sizeof(GamePortTrigger)
  $0000     0  gpt_Keys
  $0002     2  gpt_Timeout
  $0004     4  gpt_XDelta
  $0006     6  gpt_YDelta
GelsInfo:
  $0026    38  sizeof(GelsInfo)
  $0000     0  sprRsrvd
  $0001     1  Flags
! $0002     2  gelHead
! $0006     6  gelTail
! $000a    10  nextLine
! $000e    14  lastColor
! $0012    18  collHandler
  $0016    22  leftmost
  $0018    24  rightmost
  $001a    26  topmost
  $001c    28  bottommost
! $001e    30  firstBlissObj
! $0022    34  lastBlissObj
GfxBase:
  $01a6   422  sizeof(GfxBase)
  $0000     0  LibNode
! $0022    34  ActiView
! $0026    38  copinit
! $002a    42  cia
! $002e    46  blitter
! $0032    50  LOFlist
! $0036    54  SHFlist
! $003a    58  blthd
! $003e    62  blttl
! $0042    66  bsblthd
! $0046    70  bsblttl
! $004a    74  vbsrv
  $0060    96  timsrv
! $0076   118  bltsrv
  $008c   140  TextFonts
! $009a   154  DefaultFont
  $009e   158  Modes
  $00a0   160  VBlank
  $00a1   161  Debug
  $00a2   162  BeamSync
  $00a4   164  system_bplcon0
  $00a6   166  SpriteReserved
  $00a7   167  bytereserved
  $00a8   168  Flags
  $00aa   170  BlitLock
  $00ac   172  BlitNest
! $00ae   174  BlitWaitQ
  $00bc   188  BlitOwner
  $00c0   192  TOF_WaitQ
  $00ce   206  DisplayFlags
  $00d0   208  SimpleSprites
  $00d4   212  MaxDisplayRow
  $00d6   214  MaxDisplayColumn
  $00d8   216  NormalDisplayRows
  $00da   218  NormalDisplayColumns
  $00dc   220  NormalDPMX
  $00de   222  NormalDPMY
  $00e0   224  LastChanceMemory
  $00e4   228  LCMptr
  $00e8   232  MicrosPerLine
  $00ea   234  MinDisplayColumn
  $00ec   236  ChipRevBits0
! $00ed   237  crb_reserved[0]
  $00f2   242  monitor_id
  $00f4   244  hedley[0]
  $0114   276  hedley_sprites[0]
  $0134   308  hedley_sprites1[0]
  $0154   340  hedley_count
  $0156   342  hedley_flags
  $0158   344  hedley_tmp
! $015a   346  hash_table
  $015e   350  current_tot_rows
  $0160   352  current_tot_cclks
  $0162   354  hedley_hint
  $0163   355  hedley_hint2
  $0164   356  nreserved[0]
  $0174   372  a2024_sync_raster
  $0178   376  control_delta_pal
  $017a   378  control_delta_ntsc
  $017c   380  current_monitor
  $0180   384  MonitorList
! $018e   398  default_monitor
! $0192   402  MonitorListSemaphore
! $0196   406  DisplayInfoDataBase
! $019a   410  ActiViewCprSemaphore
! $019e   414  UtilityBase
! $01a2   418  ExecBase
Hook:
  $0014    20  sizeof(Hook)
  $0000     0  h_MinNode
  $0008     8  h_Entry
  $000c    12  h_SubEntry
  $0010    16  h_Data
IBox:
  $0008     8  sizeof(IBox)
  $0000     0  Left
  $0002     2  Top
  $0004     4  Width
  $0006     6  Height
IEPointerPixel:
  $0008     8  sizeof(IEPointerPixel)
  $0000     0  iepp_Screen
  $0004     4  iepp_Position
  $0004     4  iepp_Position.X
  $0006     6  iepp_Position.Y
IEPointerTablet:
  $000a    10  sizeof(IEPointerTablet)
  $0000     0  iept_Range
  $0000     0  iept_Range.X
  $0002     2  iept_Range.Y
  $0004     4  iept_Value
  $0004     4  iept_Value.X
  $0006     6  iept_Value.Y
  $0008     8  iept_Pressure
IFFHandle:
  $000c    12  sizeof(IFFHandle)
  $0000     0  iff_Stream
  $0004     4  iff_Flags
  $0008     8  iff_Depth
IFFStreamCmd:
  $000c    12  sizeof(IFFStreamCmd)
  $0000     0  sc_Command
  $0004     4  sc_Buf
  $0008     8  sc_NBytes
IOAudio:
  $0044    68  sizeof(IOAudio)
  $0000     0  ioa_Request
  $0020    32  ioa_AllocKey
! $0022    34  ioa_Data
! $0026    38  ioa_Length
  $002a    42  ioa_Period
  $002c    44  ioa_Volume
  $002e    46  ioa_Cycles
  $0030    48  ioa_WriteMsg
IOClipReq:
  $0034    52  sizeof(IOClipReq)
  $0000     0  io_Message
  $0014    20  io_Device
  $0018    24  io_Unit
  $001c    28  io_Command
  $001e    30  io_Flags
  $001f    31  io_Error
  $0020    32  io_Actual
  $0024    36  io_Length
  $0028    40  io_Data
  $002c    44  io_Offset
  $0030    48  io_ClipID
IODRPReq:
  $003e    62  sizeof(IODRPReq)
  $0000     0  io_Message
  $0014    20  io_Device
  $0018    24  io_Unit
  $001c    28  io_Command
  $001e    30  io_Flags
  $001f    31  io_Error
  $0020    32  io_RastPort
  $0024    36  io_ColorMap
  $0028    40  io_Modes
  $002c    44  io_SrcX
  $002e    46  io_SrcY
  $0030    48  io_SrcWidth
  $0032    50  io_SrcHeight
  $0034    52  io_DestCols
  $0038    56  io_DestRows
  $003c    60  io_Special
IOExtPar:
  $003e    62  sizeof(IOExtPar)
  $0000     0  IOPar
  $0030    48  io_PExtFlags
  $0034    52  io_Status
  $0035    53  io_ParFlags
! $0036    54  io_PTermArray
IOExtSer:
  $0052    82  sizeof(IOExtSer)
  $0000     0  IOSer
  $0030    48  io_CtlChar
  $0034    52  io_RBufLen
  $0038    56  io_ExtFlags
  $003c    60  io_Baud
  $0040    64  io_BrkTime
  $0044    68  io_TermArray
  $004c    76  io_ReadLen
  $004d    77  io_WriteLen
  $004e    78  io_StopBits
  $004f    79  io_SerFlags
  $0050    80  io_Status
IOExtTD:
  $0038    56  sizeof(IOExtTD)
  $0000     0  iotd_Req
  $0030    48  iotd_Count
  $0034    52  iotd_SecLabel
IOPArray:
  $0008     8  sizeof(IOPArray)
  $0000     0  PTermArray0
  $0004     4  PTermArray1
IOPrtCmdReq:
  $0026    38  sizeof(IOPrtCmdReq)
  $0000     0  io_Message
  $0014    20  io_Device
  $0018    24  io_Unit
  $001c    28  io_Command
  $001e    30  io_Flags
  $001f    31  io_Error
  $0020    32  io_PrtCommand
  $0022    34  io_Parm0
  $0023    35  io_Parm1
  $0024    36  io_Parm2
  $0025    37  io_Parm3
IORequest:
  $0020    32  sizeof(IORequest)
  $0000     0  io_Message
  $0014    20  io_Device
  $0018    24  io_Unit
  $001c    28  io_Command
  $001e    30  io_Flags
  $001f    31  io_Error
IOStdReq:
  $0030    48  sizeof(IOStdReq)
  $0000     0  io_Message
  $0014    20  io_Device
  $0018    24  io_Unit
  $001c    28  io_Command
  $001e    30  io_Flags
  $001f    31  io_Error
  $0020    32  io_Actual
  $0024    36  io_Length
  $0028    40  io_Data
  $002c    44  io_Offset
IOTArray:
  $0008     8  sizeof(IOTArray)
  $0000     0  TermArray0
  $0004     4  TermArray1
Image:
  $0014    20  sizeof(Image)
  $0000     0  LeftEdge
  $0002     2  TopEdge
  $0004     4  Width
  $0006     6  Height
  $0008     8  Depth
! $000a    10  ImageData
  $000e    14  PlanePick
  $000f    15  PlaneOnOff
  $0010    16  NextImage
InfoData:
  $0024    36  sizeof(InfoData)
  $0000     0  id_NumSoftErrors
  $0004     4  id_UnitNumber
  $0008     8  id_DiskState
  $000c    12  id_NumBlocks
  $0010    16  id_NumBlocksUsed
  $0014    20  id_BytesPerBlock
  $0018    24  id_DiskType
  $001c    28  id_VolumeNode
  $0020    32  id_InUse
InputEvent:
  $0016    22  sizeof(InputEvent)
  $0000     0  ie_NextEvent
  $0004     4  ie_Class
  $0005     5  ie_SubClass
  $0006     6  ie_Code
  $0008     8  ie_Qualifier
  $000a    10  ie_position
  $000a    10  ie_position.ie_xy
  $000a    10  ie_position.ie_xy.ie_x
  $000c    12  ie_position.ie_xy.ie_y
  $000a    10  ie_position.ie_addr
  $000a    10  ie_position.ie_dead
  $000a    10
     ie_position.ie_dead.ie_prev1DownCode
  $000b    11
     ie_position.ie_dead.ie_prev1DownQual
  $000c    12
     ie_position.ie_dead.ie_prev2DownCode
  $000d    13
     ie_position.ie_dead.ie_prev2DownQual
! $000e    14  ie_TimeStamp
InputXpression:
  $000c    12  sizeof(InputXpression)
  $0000     0  ix_Version
  $0001     1  ix_Class
  $0002     2  ix_Code
  $0004     4  ix_CodeMask
  $0006     6  ix_Qualifier
  $0008     8  ix_QualMask
  $000a    10  ix_QualSame
IntVector:
  $000c    12  sizeof(IntVector)
  $0000     0  iv_Data
  $0004     4  iv_Code
  $0008     8  iv_Node
Interrupt:
  $0016    22  sizeof(Interrupt)
  $0000     0  is_Node
! $000e    14  is_Data
! $0012    18  is_Code
IntuiMessage:
  $0034    52  sizeof(IntuiMessage)
  $0000     0  ExecMessage
  $0014    20  Class
  $0018    24  Code
  $001a    26  Qualifier
  $001c    28  IAddress
  $0020    32  MouseX
  $0022    34  MouseY
  $0024    36  Seconds
  $0028    40  Micros
  $002c    44  IDCMPWindow
  $0030    48  SpecialLink
IntuiText:
  $0014    20  sizeof(IntuiText)
  $0000     0  FrontPen
  $0001     1  BackPen
  $0002     2  DrawMode
  $0004     4  LeftEdge
  $0006     6  TopEdge
  $0008     8  ITextFont
  $000c    12  IText
  $0010    16  NextText
IntuitionBase:
  $0050    80  sizeof(IntuitionBase)
  $0000     0  LibNode
! $0022    34  ViewLord
  $0034    52  ActiveWindow
  $0038    56  ActiveScreen
  $003c    60  FirstScreen
  $0040    64  Flags
  $0044    68  MouseY
  $0046    70  MouseX
  $0048    72  Seconds
  $004c    76  Micros
IoBuff:
  $0100   256  sizeof(IoBuff)
  $0000     0  iobNode
  $0020    32  iobRpt
  $0024    36  iobRct
  $0028    40  iobDFH
  $002c    44  iobLock
  $0030    48  iobBct
  $0034    52  iobArea[0]
Isrvstr:
  $001e    30  sizeof(Isrvstr)
  $0000     0  is_Node
! $000e    14  Iptr
! $0012    18  code
! $0016    22  ccode
! $001a    26  Carg
KeyMap:
  $0020    32  sizeof(KeyMap)
  $0000     0  km_LoKeyMapTypes
  $0004     4  km_LoKeyMap
  $0008     8  km_LoCapsable
  $000c    12  km_LoRepeatable
  $0010    16  km_HiKeyMapTypes
  $0014    20  km_HiKeyMap
  $0018    24  km_HiCapsable
  $001c    28  km_HiRepeatable
KeyMapNode:
  $002e    46  sizeof(KeyMapNode)
  $0000     0  kn_Node
! $000e    14  kn_KeyMap
KeyMapResource:
  $001c    28  sizeof(KeyMapResource)
  $0000     0  kr_Node
! $000e    14  kr_List
Layer:
  $00a0   160  sizeof(Layer)
  $0000     0  front
  $0004     4  back
  $0008     8  ClipRect
  $000c    12  rp
  $0010    16  bounds
  $0018    24  reserved[0]
  $001c    28  priority
  $001e    30  Flags
  $0020    32  SuperBitMap
  $0024    36  SuperClipRect
  $0028    40  Window
  $002c    44  Scroll_X
  $002e    46  Scroll_Y
  $0030    48  cr
  $0034    52  cr2
  $0038    56  crnew
  $003c    60  SuperSaveClipRects
  $0040    64  _cliprects
  $0044    68  LayerInfo
  $0048    72  Lock
! $0076   118  BackFill
! $007a   122  reserved1
! $007e   126  ClipRegion
! $0082   130  saveClipRects
  $0086   134  Width
  $0088   136  Height
! $008a   138  reserved2[0]
  $009c   156  DamageList
Layer_Info:
  $0066   102  sizeof(Layer_Info)
  $0000     0  top_layer
  $0004     4  check_lp
  $0008     8  obs
  $000c    12  FreeClipRects
  $0018    24  Lock
! $0046    70  gs_Head
  $0054    84  longreserved
  $0058    88  Flags
  $005a    90  fatten_count
  $005b    91  LockLayersCount
  $005c    92  LayerInfo_extra_size
! $005e    94  blitbuff
! $0062    98  LayerInfo_extra
Library:
  $0022    34  sizeof(Library)
  $0000     0  lib_Node
  $000e    14  lib_Flags
  $000f    15  lib_pad
  $0010    16  lib_NegSize
  $0012    18  lib_PosSize
  $0014    20  lib_Version
  $0016    22  lib_Revision
  $0018    24  lib_IdString
  $001c    28  lib_Sum
  $0020    32  lib_OpenCnt
List:
  $000e    14  sizeof(List)
  $0000     0  lh_Head
  $0004     4  lh_Tail
  $0008     8  lh_TailPred
  $000c    12  lh_Type
  $000d    13  l_pad
LoadSegBlock:
  $0200   512  sizeof(LoadSegBlock)
  $0000     0  lsb_ID
  $0004     4  lsb_SummedLongs
  $0008     8  lsb_ChkSum
  $000c    12  lsb_HostID
  $0010    16  lsb_Next
  $0014    20  lsb_LoadData[0]
LocalContextItem:
  $0014    20  sizeof(LocalContextItem)
  $0000     0  lci_Node
  $0008     8  lci_ID
  $000c    12  lci_Type
  $0010    16  lci_Ident
LocalVar:
  $0018    24  sizeof(LocalVar)
  $0000     0  lv_Node
  $000e    14  lv_Flags
  $0010    16  lv_Value
  $0014    20  lv_Len
MathIEEEBase:
  $003c    60  sizeof(MathIEEEBase)
  $0000     0  MathIEEEBase_LibNode
! $0022    34  MathIEEEBase_reserved[0]
  $0034    52  MathIEEEBase_TaskOpenLib
  $0038    56  MathIEEEBase_TaskCloseLib
MathIEEEResource:
  $002c    44  sizeof(MathIEEEResource)
  $0000     0  MathIEEEResource_Node
  $000e    14  MathIEEEResource_Flags
  $0010    16  MathIEEEResource_BaseAddr
  $0014    20
       MathIEEEResource_DblBasInit
  $0018    24
       MathIEEEResource_DblTransInit
  $001c    28
       MathIEEEResource_SglBasInit
  $0020    32
       MathIEEEResource_SglTransInit
  $0024    36
       MathIEEEResource_ExtBasInit
  $0028    40
       MathIEEEResource_ExtTransInit
MemChunk:
  $0008     8  sizeof(MemChunk)
  $0000     0  mc_Next
  $0004     4  mc_Bytes
MemEntry:
  $0008     8  sizeof(MemEntry)
  $0000     0  me_Un
  $0000     0  me_Un.meu_Reqs
  $0000     0  me_Un.meu_Addr
  $0004     4  me_Length
MemHeader:
  $0020    32  sizeof(MemHeader)
  $0000     0  mh_Node
  $000e    14  mh_Attributes
  $0010    16  mh_First
  $0014    20  mh_Lower
  $0018    24  mh_Upper
  $001c    28  mh_Free
MemList:
  $0018    24  sizeof(MemList)
  $0000     0  ml_Node
  $000e    14  ml_NumEntries
  $0010    16  ml_ME[0]
Menu:
  $001e    30  sizeof(Menu)
  $0000     0  NextMenu
  $0004     4  LeftEdge
  $0006     6  TopEdge
  $0008     8  Width
  $000a    10  Height
  $000c    12  Flags
! $000e    14  MenuName
! $0012    18  FirstItem
  $0016    22  JazzX
  $0018    24  JazzY
  $001a    26  BeatX
  $001c    28  BeatY
MenuItem:
  $0022    34  sizeof(MenuItem)
  $0000     0  NextItem
  $0004     4  LeftEdge
  $0006     6  TopEdge
  $0008     8  Width
  $000a    10  Height
  $000c    12  Flags
! $000e    14  MutualExclude
! $0012    18  ItemFill
! $0016    22  SelectFill
  $001a    26  Command
  $001c    28  SubItem
  $0020    32  NextSelect
Message:
  $0014    20  sizeof(Message)
  $0000     0  mn_Node
! $000e    14  mn_ReplyPort
  $0012    18  mn_Length
MinList:
  $000c    12  sizeof(MinList)
  $0000     0  mlh_Head
  $0004     4  mlh_Tail
  $0008     8  mlh_TailPred
MinNode:
  $0008     8  sizeof(MinNode)
  $0000     0  mln_Succ
  $0004     4  mln_Pred
MonitorInfo:
  $0058    88  sizeof(MonitorInfo)
  $0000     0  Header
  $0010    16  Mspc
  $0014    20  ViewPosition
  $0018    24  ViewResolution
  $001c    28  ViewPositionRange
  $0024    36  TotalRows
  $0026    38  TotalColorClocks
  $0028    40  MinRow
  $002a    42  Compatibility
  $002c    44  pad[0]
  $0050    80  reserved[0]
MonitorSpec:
  $009c   156  sizeof(MonitorSpec)
  $0000     0  ms_Node
  $0018    24  ms_Flags
! $001a    26  ratioh
! $001e    30  ratiov
  $0022    34  total_rows
  $0024    36  total_colorclocks
  $0026    38  DeniseMaxDisplayColumn
  $0028    40  BeamCon0
  $002a    42  min_row
  $002c    44  ms_Special
  $0030    48  ms_OpenCount
! $0032    50  ms_transform
! $0036    54  ms_translate
! $003a    58  ms_scale
  $003e    62  ms_xoffset
  $0040    64  ms_yoffset
! $0042    66  ms_LegalView
! $004a    74  ms_maxoscan
! $004e    78  ms_videoscan
  $0052    82  DeniseMinDisplayColumn
  $0054    84  DisplayCompatible
  $0058    88  DisplayInfoDataBase
! $0066   102
      DisplayInfoDataBaseSemaphore
  $0094   148  ms_reserved00
  $0098   152  ms_reserved01
MsgPort:
  $0022    34  sizeof(MsgPort)
  $0000     0  mp_Node
  $000e    14  mp_Flags
  $000f    15  mp_SigBit
  $0010    16  mp_SigTask
  $0014    20  mp_MsgList
NameInfo:
  $0038    56  sizeof(NameInfo)
  $0000     0  Header
  $0010    16  Name[0]
  $0030    48  reserved[0]
NewBroker:
  $001a    26  sizeof(NewBroker)
  $0000     0  nb_Version
! $0002     2  nb_Name
! $0006     6  nb_Title
! $000a    10  nb_Descr
  $000e    14  nb_Unique
  $0010    16  nb_Flags
  $0012    18  nb_Pri
  $0014    20  nb_Port
  $0018    24  nb_ReservedChannel
NewGadget:
  $001e    30  sizeof(NewGadget)
  $0000     0  ng_LeftEdge
  $0002     2  ng_TopEdge
  $0004     4  ng_Width
  $0006     6  ng_Height
  $0008     8  ng_GadgetText
  $000c    12  ng_TextAttr
  $0010    16  ng_GadgetID
! $0012    18  ng_Flags
! $0016    22  ng_VisualInfo
! $001a    26  ng_UserData
NewMenu:
  $0014    20  sizeof(NewMenu)
  $0000     0  nm_Type
! $0002     2  nm_Label
! $0006     6  nm_CommKey
  $000a    10  nm_Flags
  $000c    12  nm_MutualExclude
  $0010    16  nm_UserData
NewScreen:
  $0020    32  sizeof(NewScreen)
  $0000     0  LeftEdge
  $0002     2  TopEdge
  $0004     4  Width
  $0006     6  Height
  $0008     8  Depth
  $000a    10  DetailPen
  $000b    11  BlockPen
  $000c    12  ViewModes
  $000e    14  Type
  $0010    16  Font
  $0014    20  DefaultTitle
  $0018    24  Gadgets
  $001c    28  CustomBitMap
NewWindow:
  $0030    48  sizeof(NewWindow)
  $0000     0  LeftEdge
  $0002     2  TopEdge
  $0004     4  Width
  $0006     6  Height
  $0008     8  DetailPen
  $0009     9  BlockPen
! $000a    10  IDCMPFlags
! $000e    14  Flags
! $0012    18  FirstGadget
! $0016    22  CheckMark
! $001a    26  Title
! $001e    30  Screen
! $0022    34  BitMap
  $0026    38  MinWidth
  $0028    40  MinHeight
  $002a    42  MaxWidth
  $002c    44  MaxHeight
  $002e    46  Type
NexxStr:
  $0010    16  sizeof(NexxStr)
  $0000     0  ns_Ivalue
  $0004     4  ns_Length
  $0006     6  ns_Flags
  $0007     7  ns_Hash
  $0008     8  ns_Buff[0]
Node:
  $000e    14  sizeof(Node)
  $0000     0  ln_Succ
  $0004     4  ln_Pred
  $0008     8  ln_Type
  $0009     9  ln_Pri
! $000a    10  ln_Name
NotifyMessage:
  $0026    38  sizeof(NotifyMessage)
  $0000     0  nm_ExecMessage
  $0014    20  nm_Class
  $0018    24  nm_Code
! $001a    26  nm_NReq
! $001e    30  nm_DoNotTouch
! $0022    34  nm_DoNotTouch2
NotifyRequest:
  $0030    48  sizeof(NotifyRequest)
  $0000     0  nr_Name
  $0004     4  nr_FullName
  $0008     8  nr_UserData
  $000c    12  nr_Flags
  $0010    16  nr_stuff
  $0010    16  nr_stuff.nr_Msg
  $0010    16  nr_stuff.nr_Msg.nr_Port
  $0010    16  nr_stuff.nr_Signal
  $0010    16  nr_stuff.nr_Signal.nr_Task
  $0014    20
      nr_stuff.nr_Signal.nr_SignalNum
  $0015    21
      nr_stuff.nr_Signal.nr_pad[0]
  $0018    24  nr_Reserved[0]
  $0028    40  nr_MsgCount
  $002c    44  nr_Handler
OldDrawerData:
  $0038    56  sizeof(OldDrawerData)
  $0000     0  dd_NewWindow
  $0030    48  dd_CurrentX
  $0034    52  dd_CurrentY
PGX:
  $0010    16  sizeof(PGX)
  $0000     0  pgx_Container
  $0008     8  pgx_NewKnob
PartitionBlock:
  $0100   256  sizeof(PartitionBlock)
  $0000     0  pb_ID
  $0004     4  pb_SummedLongs
  $0008     8  pb_ChkSum
  $000c    12  pb_HostID
  $0010    16  pb_Next
  $0014    20  pb_Flags
  $0018    24  pb_Reserved1[0]
  $0020    32  pb_DevFlags
  $0024    36  pb_DriveName[0]
  $0044    68  pb_Reserved2[0]
  $0080   128  pb_Environment[0]
  $00c4   196  pb_EReserved[0]
Preferences:
  $00e8   232  sizeof(Preferences)
  $0000     0  FontHeight
  $0001     1  PrinterPort
  $0002     2  BaudRate
  $0004     4  KeyRptSpeed
  $000c    12  KeyRptDelay
  $0014    20  DoubleClick
  $001c    28  PointerMatrix[0]
  $0064   100  XOffset
  $0065   101  YOffset
  $0066   102  color17
  $0068   104  color18
  $006a   106  color19
  $006c   108  PointerTicks
  $006e   110  color0
  $0070   112  color1
  $0072   114  color2
  $0074   116  color3
  $0076   118  ViewXOffset
  $0077   119  ViewYOffset
  $0078   120  ViewInitX
  $007a   122  ViewInitY
  $007c   124  EnableCLI
  $007e   126  PrinterType
  $0080   128  PrinterFilename[0]
  $009e   158  PrintPitch
  $00a0   160  PrintQuality
  $00a2   162  PrintSpacing
  $00a4   164  PrintLeftMargin
  $00a6   166  PrintRightMargin
  $00a8   168  PrintImage
  $00aa   170  PrintAspect
  $00ac   172  PrintShade
  $00ae   174  PrintThreshold
  $00b0   176  PaperSize
  $00b2   178  PaperLength
  $00b4   180  PaperType
  $00b6   182  SerRWBits
  $00b7   183  SerStopBuf
  $00b8   184  SerParShk
  $00b9   185  LaceWB
! $00ba   186  WorkName[0]
  $00d8   216  RowSizeChange
  $00d9   217  ColumnSizeChange
  $00da   218  PrintFlags
  $00dc   220  PrintMaxWidth
  $00de   222  PrintMaxHeight
  $00e0   224  PrintDensity
  $00e1   225  PrintXOffset
  $00e2   226  wb_Width
  $00e4   228  wb_Height
  $00e6   230  wb_Depth
  $00e7   231  ext_size
PrinterData:
  $1aa2  6818  sizeof(PrinterData)
  $0000     0  pd_Device
  $0034    52  pd_Unit
! $0056    86  pd_PrinterSegment
  $005a    90  pd_PrinterType
  $005c    92  pd_SegmentData
  $0060    96  pd_PrintBuf
  $0064   100  pd_PWrite
  $0068   104  pd_PBothReady
  $006c   108  pd_ior0
  $006c   108  pd_ior0.pd_p0
  $006c   108  pd_ior0.pd_s0
  $00be   190  pd_ior1
  $00be   190  pd_ior1.pd_p1
! $00be   190  pd_ior1.pd_s1
  $0110   272  pd_TIOR
  $0138   312  pd_IORPort
! $015a   346  pd_TC
! $01b6   438  pd_OldStk[0]
  $09b6  2486  pd_Flags
  $09b7  2487  pd_pad
  $09b8  2488  pd_Preferences
  $0aa0  2720  pd_PWaitEnabled
  $0aa1  2721  pd_Flags1
! $0aa2  2722  pd_Stk[0]
PrinterExtendedData:
  $0042    66  sizeof(
      PrinterExtendedData)
  $0000     0  ped_PrinterName
  $0004     4  ped_Init
  $0008     8  ped_Expunge
  $000c    12  ped_Open
  $0010    16  ped_Close
  $0014    20  ped_PrinterClass
  $0015    21  ped_ColorClass
  $0016    22  ped_MaxColumns
  $0017    23  ped_NumCharSets
  $0018    24  ped_NumRows
! $001a    26  ped_MaxXDots
! $001e    30  ped_MaxYDots
  $0022    34  ped_XDotsInch
  $0024    36  ped_YDotsInch
! $0026    38  ped_Commands
! $002a    42  ped_DoSpecial
! $002e    46  ped_Render
! $0032    50  ped_TimeoutSecs
! $0036    54  ped_8BitChars
! $003a    58  ped_PrintMode
! $003e    62  ped_ConvFunc
PrinterSegment:
  $004e    78  sizeof(PrinterSegment)
  $0000     0  ps_NextSegment
  $0004     4  ps_runAlert
  $0008     8  ps_Version
  $000a    10  ps_Revision
  $000c    12  ps_PED
Process:
  $00e4   228  sizeof(Process)
  $0000     0  pr_Task
  $005c    92  pr_MsgPort
  $007e   126  pr_Pad
  $0080   128  pr_SegList
  $0084   132  pr_StackSize
  $0088   136  pr_GlobVec
  $008c   140  pr_TaskNum
  $0090   144  pr_StackBase
  $0094   148  pr_Result2
  $0098   152  pr_CurrentDir
  $009c   156  pr_CIS
  $00a0   160  pr_COS
  $00a4   164  pr_ConsoleTask
  $00a8   168  pr_FileSystemTask
  $00ac   172  pr_CLI
  $00b0   176  pr_ReturnAddr
  $00b4   180  pr_PktWait
  $00b8   184  pr_WindowPtr
  $00bc   188  pr_HomeDir
  $00c0   192  pr_Flags
  $00c4   196  pr_ExitCode
  $00c8   200  pr_ExitData
  $00cc   204  pr_Arguments
  $00d0   208  pr_LocalVars
  $00dc   220  pr_ShellPrivate
  $00e0   224  pr_CES
PropInfo:
  $0016    22  sizeof(PropInfo)
  $0000     0  Flags
  $0002     2  HorizPot
  $0004     4  VertPot
  $0006     6  HorizBody
  $0008     8  VertBody
  $000a    10  CWidth
  $000c    12  CHeight
  $000e    14  HPotRes
  $0010    16  VPotRes
  $0012    18  LeftBorder
  $0014    20  TopBorder
PrtInfo:
  $0072   114  sizeof(PrtInfo)
  $0000     0  pi_render
  $0004     4  pi_rp
  $0008     8  pi_temprp
  $000c    12  pi_RowBuf
  $0010    16  pi_HamBuf
  $0014    20  pi_ColorMap
  $0018    24  pi_ColorInt
  $001c    28  pi_HamInt
  $0020    32  pi_Dest1Int
  $0024    36  pi_Dest2Int
  $0028    40  pi_ScaleX
  $002c    44  pi_ScaleXAlt
  $0030    48  pi_dmatrix
  $0034    52  pi_TopBuf
  $0038    56  pi_BotBuf
  $003c    60  pi_RowBufSize
  $003e    62  pi_HamBufSize
  $0040    64  pi_ColorMapSize
  $0042    66  pi_ColorIntSize
  $0044    68  pi_HamIntSize
  $0046    70  pi_Dest1IntSize
  $0048    72  pi_Dest2IntSize
  $004a    74  pi_ScaleXSize
  $004c    76  pi_ScaleXAltSize
  $004e    78  pi_PrefsFlags
  $0050    80  pi_special
  $0054    84  pi_xstart
  $0056    86  pi_ystart
  $0058    88  pi_width
  $005a    90  pi_height
  $005c    92  pi_pc
  $0060    96  pi_pr
  $0064   100  pi_ymult
  $0066   102  pi_ymod
  $0068   104  pi_ety
  $006a   106  pi_xpos
  $006c   108  pi_threshold
  $006e   110  pi_tempwidth
  $0070   112  pi_flags
PubScreenNode:
  $001e    30  sizeof(PubScreenNode)
  $0000     0  psn_Node
! $000e    14  psn_Screen
  $0012    18  psn_Flags
  $0014    20  psn_Size
  $0016    22  psn_VisitorCount
  $0018    24  psn_SigTask
  $001c    28  psn_SigBit
QueryHeader:
  $0010    16  sizeof(QueryHeader)
  $0000     0  StructID
  $0004     4  DisplayID
  $0008     8  SkipID
  $000c    12  Length
RDArgs:
  $0020    32  sizeof(RDArgs)
  $0000     0  RDA_Source
  $000c    12  RDA_DAList
  $0010    16  RDA_Buffer
  $0014    20  RDA_BufSiz
  $0018    24  RDA_ExtHelp
  $001c    28  RDA_Flags
RasInfo:
  $000c    12  sizeof(RasInfo)
  $0000     0  Next
  $0004     4  BitMap
  $0008     8  RxOffset
  $000a    10  RyOffset
RastPort:
  $0064   100  sizeof(RastPort)
  $0000     0  Layer
  $0004     4  BitMap
  $0008     8  AreaPtrn
  $000c    12  TmpRas
  $0010    16  AreaInfo
  $0014    20  GelsInfo
  $0018    24  Mask
  $0019    25  FgPen
  $001a    26  BgPen
  $001b    27  AOlPen
  $001c    28  DrawMode
  $001d    29  AreaPtSz
  $001e    30  linpatcnt
  $001f    31  dummy
  $0020    32  Flags
  $0022    34  LinePtrn
  $0024    36  cp_x
  $0026    38  cp_y
  $0028    40  minterms[0]
  $0030    48  PenWidth
  $0032    50  PenHeight
  $0034    52  Font
  $0038    56  AlgoStyle
  $0039    57  TxFlags
  $003a    58  TxHeight
  $003c    60  TxWidth
  $003e    62  TxBaseline
  $0040    64  TxSpacing
! $0042    66  RP_User
! $0046    70  longreserved[0]
! $004e    78  wordreserved[0]
  $005c    92  reserved[0]
RecordLock:
  $0010    16  sizeof(RecordLock)
  $0000     0  rec_FH
  $0004     4  rec_Offset
  $0008     8  rec_Length
  $000c    12  rec_Mode
Rect32:
  $0010    16  sizeof(Rect32)
  $0000     0  MinX
  $0004     4  MinY
  $0008     8  MaxX
  $000c    12  MaxY
Rectangle:
  $0008     8  sizeof(Rectangle)
  $0000     0  MinX
  $0002     2  MinY
  $0004     4  MaxX
  $0006     6  MaxY
Region:
  $000c    12  sizeof(Region)
  $0000     0  bounds
  $0008     8  RegionRectangle
RegionRectangle:
  $0010    16  sizeof(RegionRectangle)
  $0000     0  Next
  $0004     4  Prev
  $0008     8  bounds
Remember:
  $000c    12  sizeof(Remember)
  $0000     0  NextRemember
  $0004     4  RememberSize
  $0008     8  Memory
Requester:
  $0070   112  sizeof(Requester)
  $0000     0  OlderRequest
  $0004     4  LeftEdge
  $0006     6  TopEdge
  $0008     8  Width
  $000a    10  Height
  $000c    12  RelLeft
  $000e    14  RelTop
  $0010    16  ReqGadget
  $0014    20  ReqBorder
  $0018    24  ReqText
  $001c    28  Flags
  $001e    30  BackFill
  $0020    32  ReqLayer
  $0024    36  ReqPad1[0]
  $0044    68  ImageBMap
  $0048    72  RWindow
  $004c    76  ReqImage
  $0050    80  ReqPad2[0]
Resident:
  $001a    26  sizeof(Resident)
  $0000     0  rt_MatchWord
! $0002     2  rt_MatchTag
! $0006     6  rt_EndSkip
  $000a    10  rt_Flags
  $000b    11  rt_Version
  $000c    12  rt_Type
  $000d    13  rt_Pri
! $000e    14  rt_Name
! $0012    18  rt_IdString
! $0016    22  rt_Init
RexxArg:
  $0010    16  sizeof(RexxArg)
  $0000     0  ra_Size
  $0004     4  ra_Length
  $0006     6  ra_Flags
  $0007     7  ra_Hash
  $0008     8  ra_Buff[0]
RexxMsg:
  $0080   128  sizeof(RexxMsg)
  $0000     0  rm_Node
  $0014    20  rm_TaskBlock
  $0018    24  rm_LibBase
  $001c    28  rm_Action
  $0020    32  rm_Result1
  $0024    36  rm_Result2
  $0028    40  rm_Args[0]
  $0068   104  rm_PassPort
  $006c   108  rm_CommAddr
  $0070   112  rm_FileExt
  $0074   116  rm_Stdin
  $0078   120  rm_Stdout
  $007c   124  rm_avail
RexxMsgPort:
  $0050    80  sizeof(RexxMsgPort)
  $0000     0  rmp_Node
  $0020    32  rmp_Port
! $0042    66  rmp_ReplyList
RexxRsrc:
  $0020    32  sizeof(RexxRsrc)
  $0000     0  rr_Node
  $000e    14  rr_Func
  $0010    16  rr_Base
  $0014    20  rr_Size
  $0018    24  rr_Arg1
  $001c    28  rr_Arg2
RexxTask:
  $014a   330  sizeof(RexxTask)
  $0000     0  rt_Global[0]
  $00c8   200  rt_MsgPort
  $00ea   234  rt_Flags
  $00eb   235  rt_SigBit
  $00ec   236  rt_ClientID
  $00f0   240  rt_MsgPkt
  $00f4   244  rt_TaskID
  $00f8   248  rt_RexxPort
  $00fc   252  rt_ErrTrap
  $0100   256  rt_StackPtr
  $0104   260  rt_Header1
! $0112   274  rt_Header2
  $0120   288  rt_Header3
! $012e   302  rt_Header4
  $013c   316  rt_Header5
RigidDiskBlock:
  $0100   256  sizeof(RigidDiskBlock)
  $0000     0  rdb_ID
  $0004     4  rdb_SummedLongs
  $0008     8  rdb_ChkSum
  $000c    12  rdb_HostID
  $0010    16  rdb_BlockBytes
  $0014    20  rdb_Flags
  $0018    24  rdb_BadBlockList
  $001c    28  rdb_PartitionList
  $0020    32  rdb_FileSysHeaderList
  $0024    36  rdb_DriveInit
  $0028    40  rdb_Reserved1[0]
  $0040    64  rdb_Cylinders
  $0044    68  rdb_Sectors
  $0048    72  rdb_Heads
  $004c    76  rdb_Interleave
  $0050    80  rdb_Park
  $0054    84  rdb_Reserved2[0]
  $0060    96  rdb_WritePreComp
  $0064   100  rdb_ReducedWrite
  $0068   104  rdb_StepRate
  $006c   108  rdb_Reserved3[0]
  $0080   128  rdb_RDBBlocksLo
  $0084   132  rdb_RDBBlocksHi
  $0088   136  rdb_LoCylinder
  $008c   140  rdb_HiCylinder
  $0090   144  rdb_CylBlocks
  $0094   148  rdb_AutoParkSeconds
  $0098   152  rdb_Reserved4[0]
  $00a0   160  rdb_DiskVendor[0]
  $00a8   168  rdb_DiskProduct[0]
  $00b8   184  rdb_DiskRevision[0]
  $00bc   188  rdb_ControllerVendor[0]
  $00c4   196  rdb_ControllerProduct[0]
  $00d4   212  rdb_ControllerRevision[0]
  $00d8   216  rdb_Reserved5[0]
RootNode:
  $0038    56  sizeof(RootNode)
  $0000     0  rn_TaskArray
  $0004     4  rn_ConsoleSegment
  $0008     8  rn_Time
  $0014    20  rn_RestartSeg
  $0018    24  rn_Info
  $001c    28  rn_FileHandlerSegment
  $0020    32  rn_CliList
  $002c    44  rn_BootProc
  $0030    48  rn_ShellSegment
  $0034    52  rn_Flags
RxsLib:
  $00fc   252  sizeof(RxsLib)
  $0000     0  rl_Node
  $0022    34  rl_Flags
  $0023    35  rl_Shadow
  $0024    36  rl_SysBase
  $0028    40  rl_DOSBase
  $002c    44  rl_IeeeDPBase
  $0030    48  rl_SegList
  $0034    52  rl_NIL
  $0038    56  rl_Chunk
  $003c    60  rl_MaxNest
  $0040    64  rl_NULL
  $0044    68  rl_FALSE
  $0048    72  rl_TRUE
  $004c    76  rl_REXX
  $0050    80  rl_COMMAND
  $0054    84  rl_STDIN
  $0058    88  rl_STDOUT
  $005c    92  rl_STDERR
  $0060    96  rl_Version
  $0064   100  rl_TaskName
  $0068   104  rl_TaskPri
  $006c   108  rl_TaskSeg
  $0070   112  rl_StackSize
  $0074   116  rl_RexxDir
  $0078   120  rl_CTABLE
  $007c   124  rl_Notice
  $0080   128  rl_RexxPort
  $00a2   162  rl_ReadLock
  $00a4   164  rl_TraceFH
  $00a8   168  rl_TaskList
  $00b6   182  rl_NumTask
  $00b8   184  rl_LibList
  $00c6   198  rl_NumLib
  $00c8   200  rl_ClipList
  $00d6   214  rl_NumClip
  $00d8   216  rl_MsgList
  $00e6   230  rl_NumMsg
  $00e8   232  rl_PgmList
  $00f6   246  rl_NumPgm
  $00f8   248  rl_TraceCnt
  $00fa   250  rl_avail
SCSICmd:
  $001e    30  sizeof(SCSICmd)
  $0000     0  scsi_Data
  $0004     4  scsi_Length
  $0008     8  scsi_Actual
  $000c    12  scsi_Command
  $0010    16  scsi_CmdLength
  $0012    18  scsi_CmdActual
  $0014    20  scsi_Flags
  $0015    21  scsi_Status
! $0016    22  scsi_SenseData
  $001a    26  scsi_SenseLength
  $001c    28  scsi_SenseActual
SGWork:
  $002c    44  sizeof(SGWork)
  $0000     0  Gadget
  $0004     4  StringInfo
  $0008     8  WorkBuffer
  $000c    12  PrevBuffer
  $0010    16  Modes
  $0014    20  IEvent
  $0018    24  Code
  $001a    26  BufferPos
  $001c    28  NumChars
! $001e    30  Actions
! $0022    34  LongInt
! $0026    38  GadgetInfo
  $002a    42  EditOp
SatisfyMsg:
  $001a    26  sizeof(SatisfyMsg)
  $0000     0  sm_Msg
  $0014    20  sm_Unit
! $0016    22  sm_ClipID
Screen:
  $015a   346  sizeof(Screen)
  $0000     0  NextScreen
  $0004     4  FirstWindow
  $0008     8  LeftEdge
  $000a    10  TopEdge
  $000c    12  Width
  $000e    14  Height
  $0010    16  MouseY
  $0012    18  MouseX
  $0014    20  Flags
! $0016    22  Title
! $001a    26  DefaultTitle
  $001e    30  BarHeight
  $001f    31  BarVBorder
  $0020    32  BarHBorder
  $0021    33  MenuVBorder
  $0022    34  MenuHBorder
  $0023    35  WBorTop
  $0024    36  WBorLeft
  $0025    37  WBorRight
  $0026    38  WBorBottom
  $0028    40  Font
  $002c    44  ViewPort
  $0054    84  RastPort
  $00b8   184  BitMap
  $00e0   224  LayerInfo
! $0146   326  FirstGadget
  $014a   330  DetailPen
  $014b   331  BlockPen
  $014c   332  SaveColor0
! $014e   334  BarLayer
! $0152   338  ExtData
! $0156   342  UserData
Semaphore:
  $0024    36  sizeof(Semaphore)
  $0000     0  sm_MsgPort
  $0022    34  sm_Bids
SemaphoreRequest:
  $000c    12  sizeof(SemaphoreRequest)
  $0000     0  sr_Link
  $0008     8  sr_Waiter
SignalSemaphore:
  $002e    46  sizeof(SignalSemaphore)
  $0000     0  ss_Link
  $000e    14  ss_NestCount
  $0010    16  ss_WaitQueue
  $001c    28  ss_MultipleLink
  $0028    40  ss_Owner
  $002c    44  ss_QueueCount
SimpleSprite:
  $000c    12  sizeof(SimpleSprite)
  $0000     0  posctldata
  $0004     4  height
  $0006     6  x
  $0008     8  y
  $000a    10  num
SoftIntList:
  $0010    16  sizeof(SoftIntList)
  $0000     0  sh_List
  $000e    14  sh_Pad
SpecialMonitor:
  $003a    58  sizeof(SpecialMonitor)
  $0000     0  spm_Node
  $0018    24  spm_Flags
! $001a    26  do_monitor
! $001e    30  reserved1
! $0022    34  reserved2
! $0026    38  reserved3
! $002a    42  hblank
! $002e    46  vblank
! $0032    50  hsync
! $0036    54  vsync
SpriteDef:
  $0008     8  sizeof(SpriteDef)
  $0000     0  pos
  $0002     2  ctl
  $0004     4  dataa
  $0006     6  datab
SrcNode:
  $0010    16  sizeof(SrcNode)
  $0000     0  sn_Succ
  $0004     4  sn_Pred
  $0008     8  sn_Ptr
  $000c    12  sn_Size
StandardPacket:
  $0044    68  sizeof(StandardPacket)
  $0000     0  sp_Msg
  $0014    20  sp_Pkt
StoredProperty:
  $0008     8  sizeof(StoredProperty)
  $0000     0  sp_Size
  $0004     4  sp_Data
StringExtend:
  $0024    36  sizeof(StringExtend)
  $0000     0  Font
  $0004     4  Pens[0]
  $0006     6  ActivePens[0]
  $0008     8  InitialModes
  $000c    12  EditHook
  $0010    16  WorkBuffer
  $0014    20  Reserved[0]
StringInfo:
  $0024    36  sizeof(StringInfo)
  $0000     0  Buffer
  $0004     4  UndoBuffer
  $0008     8  BufferPos
  $000a    10  MaxChars
  $000c    12  DispPos
  $000e    14  UndoPos
  $0010    16  NumChars
  $0012    18  DispCount
  $0014    20  CLeft
  $0016    22  CTop
  $0018    24  Extension
  $001c    28  LongInt
  $0020    32  AltKeyMap
TAvailFonts:
  $000e    14  sizeof(TAvailFonts)
  $0000     0  taf_Type
! $0002     2  taf_Attr
TDU_PublicUnit:
  $0040    64  sizeof(TDU_PublicUnit)
  $0000     0  tdu_Unit
  $0026    38  tdu_Comp01Track
  $0028    40  tdu_Comp10Track
  $002a    42  tdu_Comp11Track
  $002c    44  tdu_StepDelay
  $0030    48  tdu_SettleDelay
  $0034    52  tdu_RetryCnt
  $0035    53  tdu_PubFlags
  $0036    54  tdu_CurrTrk
  $0038    56  tdu_CalibrateDelay
  $003c    60  tdu_Counter
TFontContents:
  $0104   260  sizeof(TFontContents)
  $0000     0  tfc_FileName[0]
  $00fe   254  tfc_TagCount
  $0100   256  tfc_YSize
  $0102   258  tfc_Style
  $0103   259  tfc_Flags
TTextAttr:
  $000c    12  sizeof(TTextAttr)
  $0000     0  tta_Name
  $0004     4  tta_YSize
  $0006     6  tta_Style
  $0007     7  tta_Flags
  $0008     8  tta_Tags
TagItem:
  $0008     8  sizeof(TagItem)
  $0000     0  ti_Tag
  $0004     4  ti_Data
Task:
  $005c    92  sizeof(Task)
  $0000     0  tc_Node
  $000e    14  tc_Flags
  $000f    15  tc_State
  $0010    16  tc_IDNestCnt
  $0011    17  tc_TDNestCnt
! $0012    18  tc_SigAlloc
! $0016    22  tc_SigWait
! $001a    26  tc_SigRecvd
! $001e    30  tc_SigExcept
  $0022    34  tc_TrapAlloc
  $0024    36  tc_TrapAble
! $0026    38  tc_ExceptData
! $002a    42  tc_ExceptCode
! $002e    46  tc_TrapData
! $0032    50  tc_TrapCode
! $0036    54  tc_SPReg
! $003a    58  tc_SPLower
! $003e    62  tc_SPUpper
! $0042    66  tc_Switch
! $0046    70  tc_Launch
! $004a    74  tc_MemEntry
  $0058    88  tc_UserData
TextAttr:
  $0008     8  sizeof(TextAttr)
  $0000     0  ta_Name
  $0004     4  ta_YSize
  $0006     6  ta_Style
  $0007     7  ta_Flags
TextExtent:
  $000c    12  sizeof(TextExtent)
  $0000     0  te_Width
  $0002     2  te_Height
  $0004     4  te_Extent
TextFont:
  $0034    52  sizeof(TextFont)
  $0000     0  tf_Message
  $0014    20  tf_YSize
  $0016    22  tf_Style
  $0017    23  tf_Flags
  $0018    24  tf_XSize
  $001a    26  tf_Baseline
  $001c    28  tf_BoldSmear
  $001e    30  tf_Accessors
  $0020    32  tf_LoChar
  $0021    33  tf_HiChar
! $0022    34  tf_CharData
  $0026    38  tf_Modulo
  $0028    40  tf_CharLoc
  $002c    44  tf_CharSpace
  $0030    48  tf_CharKern
TextFontExtension:
  $0018    24  sizeof(TextFontExtension)
  $0000     0  tfe_MatchWord
  $0002     2  tfe_Flags0
  $0003     3  tfe_Flags1
  $0004     4  tfe_BackPtr
  $0008     8  tfe_OrigReplyPort
  $000c    12  tfe_Tags
  $0010    16  tfe_OFontPatchS
  $0014    20  tfe_OFontPatchK
TmpRas:
  $0008     8  sizeof(TmpRas)
  $0000     0  RasPtr
  $0004     4  Size
UCopList:
  $000c    12  sizeof(UCopList)
  $0000     0  Next
  $0004     4  FirstCopList
  $0008     8  CopList
Unit:
  $0026    38  sizeof(Unit)
  $0000     0  unit_MsgPort
  $0022    34  unit_flags
  $0023    35  unit_pad
  $0024    36  unit_OpenCnt
VSprite:
  $003c    60  sizeof(VSprite)
  $0000     0  NextVSprite
  $0004     4  PrevVSprite
  $0008     8  DrawPath
  $000c    12  ClearPath
  $0010    16  OldY
  $0012    18  OldX
  $0014    20  Flags
  $0016    22  Y
  $0018    24  X
  $001a    26  Height
  $001c    28  Width
  $001e    30  Depth
  $0020    32  MeMask
  $0022    34  HitMask
  $0024    36  ImageData
  $0028    40  BorderLine
  $002c    44  CollMask
  $0030    48  SprColors
  $0034    52  VSBob
  $0038    56  PlanePick
  $0039    57  PlaneOnOff
  $003a    58  VUserExt
View:
  $0012    18  sizeof(View)
  $0000     0  ViewPort
  $0004     4  LOFCprList
  $0008     8  SHFCprList
  $000c    12  DyOffset
  $000e    14  DxOffset
  $0010    16  Modes
ViewExtra:
  $0020    32  sizeof(ViewExtra)
  $0000     0  n
  $0018    24  View
  $001c    28  Monitor
ViewPort:
  $0028    40  sizeof(ViewPort)
  $0000     0  Next
  $0004     4  ColorMap
  $0008     8  DspIns
  $000c    12  SprIns
  $0010    16  ClrIns
  $0014    20  UCopIns
  $0018    24  DWidth
  $001a    26  DHeight
  $001c    28  DxOffset
  $001e    30  DyOffset
  $0020    32  Modes
  $0022    34  SpritePriorities
  $0023    35  ExtendedModes
  $0024    36  RasInfo
ViewPortExtra:
  $0024    36  sizeof(ViewPortExtra)
  $0000     0  n
  $0018    24  ViewPort
  $001c    28  DisplayClip
WBArg:
  $0008     8  sizeof(WBArg)
  $0000     0  wa_Lock
  $0004     4  wa_Name
WBStartup:
  $0028    40  sizeof(WBStartup)
  $0000     0  sm_Message
  $0014    20  sm_Process
  $0018    24  sm_Segment
  $001c    28  sm_NumArgs
  $0020    32  sm_ToolWindow
  $0024    36  sm_ArgList
Window:
  $0088   136  sizeof(Window)
  $0000     0  NextWindow
  $0004     4  LeftEdge
  $0006     6  TopEdge
  $0008     8  Width
  $000a    10  Height
  $000c    12  MouseY
  $000e    14  MouseX
  $0010    16  MinWidth
  $0012    18  MinHeight
  $0014    20  MaxWidth
  $0016    22  MaxHeight
  $0018    24  Flags
  $001c    28  MenuStrip
  $0020    32  Title
  $0024    36  FirstRequest
  $0028    40  DMRequest
  $002c    44  ReqCount
! $002e    46  WScreen
! $0032    50  RPort
  $0036    54  BorderLeft
  $0037    55  BorderTop
  $0038    56  BorderRight
  $0039    57  BorderBottom
! $003a    58  BorderRPort
! $003e    62  FirstGadget
! $0042    66  Parent
! $0046    70  Descendant
! $004a    74  Pointer
  $004e    78  PtrHeight
  $004f    79  PtrWidth
  $0050    80  XOffset
  $0051    81  YOffset
! $0052    82  IDCMPFlags
! $0056    86  UserPort
! $005a    90  WindowPort
! $005e    94  MessageKey
  $0062    98  DetailPen
  $0063    99  BlockPen
  $0064   100  CheckMark
  $0068   104  ScreenTitle
  $006c   108  GZZMouseX
  $006e   110  GZZMouseY
  $0070   112  GZZWidth
  $0072   114  GZZHeight
  $0074   116  ExtData
  $0078   120  UserData
  $007c   124  WLayer
  $0080   128  IFont
  $0084   132  MoreFlags
_Object:
  $000c    12  sizeof(_Object)
  $0000     0  o_Node
  $0008     8  o_Class
bltnode:
  $0012    18  sizeof(bltnode)
  $0000     0  n
  $0004     4  function
  $0008     8  stat
  $000a    10  blitsize
  $000c    12  beamsync
! $000e    14  cleanup
collTable:
  $0040    64  sizeof(collTable)
  $0000     0  collPtrs[0]
copinit:
  $0078   120  sizeof(copinit)
  $0000     0  vsync_hblank[0]
  $0004     4  diwstart[0]
  $000c    12  diagstrt[0]
  $0014    20  sprstrtup[0]
  $0054    84  wait14[0]
  $0058    88  norm_hblank[0]
  $005c    92  genloc[0]
  $0064   100  jump[0]
  $006c   108  wait_forever[0]
  $0070   112  sprstop[0]
cprlist:
  $000a    10  sizeof(cprlist)
  $0000     0  Next
  $0004     4  start
  $0008     8  MaxCount
gpGoInactive:
  $0008     8  sizeof(gpGoInactive)
  $0000     0  MethodID
  $0004     4  gpgi_GInfo
gpHitTest:
  $000c    12  sizeof(gpHitTest)
  $0000     0  MethodID
  $0004     4  gpht_GInfo
  $0008     8  gpht_Mouse
  $0008     8  gpht_Mouse.X
  $000a    10  gpht_Mouse.Y
gpInput:
  $0014    20  sizeof(gpInput)
  $0000     0  MethodID
  $0004     4  gpi_GInfo
  $0008     8  gpi_IEvent
  $000c    12  gpi_Termination
  $0010    16  gpi_Mouse
  $0010    16  gpi_Mouse.X
  $0012    18  gpi_Mouse.Y
gpRender:
  $0010    16  sizeof(gpRender)
  $0000     0  MethodID
  $0004     4  gpr_GInfo
  $0008     8  gpr_RPort
  $000c    12  gpr_Redraw
impDraw:
  $0018    24  sizeof(impDraw)
  $0000     0  MethodID
  $0004     4  imp_RPort
  $0008     8  imp_Offset
  $0008     8  imp_Offset.X
  $000a    10  imp_Offset.Y
  $000c    12  imp_State
  $0010    16  imp_DrInfo
  $0014    20  imp_Dimensions
  $0014    20  imp_Dimensions.Width
  $0016    22  imp_Dimensions.Height
impErase:
  $0010    16  sizeof(impErase)
  $0000     0  MethodID
  $0004     4  imp_RPort
  $0008     8  imp_Offset
  $0008     8  imp_Offset.X
  $000a    10  imp_Offset.Y
  $000c    12  imp_Dimensions
  $000c    12  imp_Dimensions.Width
  $000e    14  imp_Dimensions.Height
impFrameBox:
  $0014    20  sizeof(impFrameBox)
  $0000     0  MethodID
  $0004     4  imp_ContentsBox
  $0008     8  imp_FrameBox
  $000c    12  imp_DrInfo
  $0010    16  imp_FrameFlags
impHitTest:
  $000c    12  sizeof(impHitTest)
  $0000     0  MethodID
  $0004     4  imp_Point
  $0004     4  imp_Point.X
  $0006     6  imp_Point.Y
  $0008     8  imp_Dimensions
  $0008     8  imp_Dimensions.Width
  $000a    10  imp_Dimensions.Height
mouth_rb:
  $005c    92  sizeof(mouth_rb)
  $0000     0  voice
  $0058    88  width
  $0059    89  height
  $005a    90  shape
  $005b    91  sync
narrator_rb:
  $0058    88  sizeof(narrator_rb)
  $0000     0  message
  $0030    48  rate
  $0032    50  pitch
  $0034    52  mode
  $0036    54  sex
  $0038    56  ch_masks
  $003c    60  nm_masks
  $003e    62  volume
  $0040    64  sampfreq
  $0042    66  mouths
  $0043    67  chanmask
  $0044    68  numchan
  $0045    69  flags
  $0046    70  F0enthusiasm
  $0047    71  F0perturb
  $0048    72  F1adj
  $0049    73  F2adj
  $004a    74  F3adj
  $004b    75  A1adj
  $004c    76  A2adj
  $004d    77  A3adj
  $004e    78  articulate
  $004f    79  centralize
  $0050    80  centphon
  $0054    84  AVbias
  $0055    85  AFbias
  $0056    86  priority
  $0057    87  pad1
opAddTail:
  $0008     8  sizeof(opAddTail)
  $0000     0  MethodID
  $0004     4  opat_List
opGet:
  $000c    12  sizeof(opGet)
  $0000     0  MethodID
  $0004     4  opg_AttrID
  $0008     8  opg_Storage
opMember:
  $0008     8  sizeof(opMember)
  $0000     0  MethodID
  $0004     4  opam_Object
opSet:
  $000c    12  sizeof(opSet)
  $0000     0  MethodID
  $0004     4  ops_AttrList
  $0008     8  ops_GInfo
opUpdate:
  $0010    16  sizeof(opUpdate)
  $0000     0  MethodID
  $0004     4  opu_AttrList
  $0008     8  opu_GInfo
  $000c    12  opu_Flags
timerequest:
  $0028    40  sizeof(timerequest)
  $0000     0  tr_node
  $0020    32  tr_time
timeval:
  $0008     8  sizeof(timeval)
  $0000     0  tv_secs
  $0004     4  tv_micro
colorEntry:
  $0004     4  sizeof(colorEntry)
  $0000     0  colorLong
  $0000     0  colorByte[0]
  $0000     0  colorSByte[0]


2.0 Structure Index

   AnalogSignalInterval               <graphics/monitor.h>
   AnchorPath                         <dos/dosasl.h>
   AnimComp                           <graphics/gels.h>
   AnimOb                             <graphics/gels.h>
   AppMenuItem                        <workbench/workbench.h>
   AppMessage                         <workbench/workbench.h>
   AppWindow                          <workbench/workbench.h>
   AreaInfo                           <graphics/rastport.h>
   AssignList                         <dos/dosextens.h>
   AvailFonts                         <libraries/diskfont.h>
   AvailFontsHeader                   <libraries/diskfont.h>

   BadBlockBlock                      <devices/hardblocks.h>
   BadBlockEntry                      <devices/hardblocks.h>
   BitMap                             <graphics/gfx.h>
   BitScaleArgs                       <graphics/scale.h>
   bltnode                            <hardware/blit.h>
   Bob                                <graphics/gels.h>
   BoolInfo                           <intuition/intuition.h>
   BootBlock                          <devices/bootblock.h>
   BootNode                           <libraries/expansionbase.h>
   Border                             <intuition/intuition.h>

   CIA                                <hardware/cia.h>
   ClipboardHandle                    <libraries/iffparse.h>
   ClipboardUnitPartial               <devices/clipboard.h>
   ClipHookMsg                        <devices/clipboard.h>
   ClipRect                           <graphics/clip.h>
   CliProcList                        <dos/dosextens.h>
   ClockData                          <utility/date.h>
   CollectionItem                     <libraries/iffparse.h>
   collTable                          <graphics/gels.h>
   ColorFontColors                    <graphics/text.h>
   ColorMap                           <graphics/view.h>
   ColorSpec                          <intuition/intuition.h>
   ColorTextFont                      <graphics/text.h>
   CommandLineInterface               <dos/dosextens.h>
   ConfigDev                          <libraries/configvars.h>
   ContextNode                        <libraries/iffparse.h>
   ConUnit                            <devices/conunit.h>
   copinit                            <graphics/copper.h>
   CopIns                             <graphics/copper.h>
   CopList                            <graphics/copper.h>
   cprlist                            <graphics/copper.h>
   CSource                            <dos/rdargs.h>
   CurrentBinding                     <libraries/configvars.h>
   Custom                             <hardware/custom.h>

   DateStamp                          <dos/dos.h>
   DateTime                           <dos/datetime.h>
   DBufPacket                         <graphics/gels.h>
   Device                             <exec/devices.h>
   DeviceData                         <devices/prtbase.h>
   DeviceList                         <dos/dosextens.h>
   DeviceNode                         <dos/filehandler.h>
   DevInfo                            <dos/dosextens.h>
   DevProc                            <dos/dosextens.h>
   DiagArea                           <libraries/configregs.h>
   DimensionInfo                      <graphics/displayinfo.h>
   DiscResource                       <resources/disk.h>
   DiscResourceUnit                   <resources/disk.h>
   DiskFontHeader                     <libraries/diskfont.h>
   DiskObject                         <workbench/workbench.h>
   DisplayInfo                        <graphics/displayinfo.h>
   DosEnvec                           <dos/filehandler.h>
   DosInfo                            <dos/dosextens.h>
   DosLibrary                         <dos/dosextens.h>
   DosList                            <dos/dosextens.h>
   DosPacket                          <dos/dosextens.h>
   DrawerData                         <workbench/workbench.h>
   DrawInfo                           <intuition/screens.h>
   DriveGeometry                      <devices/trackdisk.h>

   EasyStruct                         <intuition/intuition.h>
   EClockVal                          <devices/timer.h>
   ErrorString                        <dos/dosextens.h>
   ExAllControl                       <dos/exall.h>
   ExAllData                          <dos/exall.h>
   ExecBase                           <exec/execbase.h>
   ExpansionBase                      <libraries/expansionbase.h>
   ExpansionControl                   <libraries/configregs.h>
   ExpansionRom                       <libraries/configregs.h>
   ExtendedNode                       <graphics/gfxnodes.h>
   ExtNewScreen                       <intuition/screens.h>
   ExtNewWindow                       <intuition/intuition.h>

   FileHandle                         <dos/dosextens.h>
   FileInfoBlock                      <dos/dos.h>
   FileLock                           <dos/dosextens.h>
   FileRequester                      <libraries/asl.h>
   FileSysEntry                       <resources/filesysres.h>
   FileSysHeaderBlock                 <devices/hardblocks.h>
   FileSysResource                    <resources/filesysres.h>
   FileSysStartupMsg                  <dos/filehandler.h>
   FontContents                       <libraries/diskfont.h>
   FontContentsHeader                 <libraries/diskfont.h>
   FontRequester                      <libraries/asl.h>
   FreeList                           <workbench/workbench.h>

   Gadget                             <intuition/intuition.h>
   GadgetInfo                         <intuition/cghooks.h>
   GamePortTrigger                    <devices/gameport.h>
   GelsInfo                           <graphics/rastport.h>
   GfxBase                            <graphics/gfxbase.h>
   gpGoInactive                       <intuition/gadgetclass.h>
   gpHitTest                          <intuition/gadgetclass.h>
   gpInput                            <intuition/gadgetclass.h>
   gpRender                           <intuition/gadgetclass.h>

   Hook                               <utility/hooks.h>

   IBox                               <intuition/intuition.h>
   IEPointerPixel                     <devices/inputevent.h>
   IEPointerTablet                    <devices/inputevent.h>
   IFFHandle                          <libraries/iffparse.h>
   IFFStreamCmd                       <libraries/iffparse.h>
   Image                              <intuition/intuition.h>
   impDraw                            <intuition/imageclass.h>
   impErase                           <intuition/imageclass.h>
   impFrameBox                        <intuition/imageclass.h>
   impHitTest                         <intuition/imageclass.h>
   InfoData                           <dos/dos.h>
   InputEvent                         <devices/inputevent.h>
   InputXpression                     <libraries/commodities.h>
   Interrupt                          <exec/interrupts.h>
   IntuiMessage                       <intuition/intuition.h>
   IntuiText                          <intuition/intuition.h>
   IntuitionBase                      <intuition/intuitionbase.h>
   IntVector                          <exec/interrupts.h>
   IOAudio                            <devices/audio.h>
   IoBuff                             <rexx/rexxio.h>
   IOClipReq                          <devices/clipboard.h>
   IODRPReq                           <devices/printer.h>
   IOExtTD                            <devices/trackdisk.h>
   IOPrtCmdReq                        <devices/printer.h>
   IORequest                          <exec/io.h>
   IOStdReq                           <exec/io.h>
   Isrvstr                            <graphics/graphint.h>

   KeyMap                             <devices/keymap.h>
   KeyMapNode                         <devices/keymap.h>
   KeyMapResource                     <devices/keymap.h>

   Layer                              <graphics/clip.h>
   Layer_Info                         <graphics/layers.h>
   Library                            <exec/libraries.h>
   List                               <exec/lists.h>
   LoadSegBlock                       <devices/hardblocks.h>
   LocalContextItem                   <libraries/iffparse.h>
   LocalVar                           <dos/var.h>

   MathIEEEBase                       <libraries/mathlibrary.h>
   MathIEEEResource                   <libraries/mathresource.h>
   MathIEEEResource                   <resources/mathresource.h>
   MemChunk                           <exec/memory.h>
   MemEntry                           <exec/memory.h>
   MemHeader                          <exec/memory.h>
   MemList                            <exec/memory.h>
   Menu                               <intuition/intuition.h>
   MenuItem                           <intuition/intuition.h>
   Message                            <exec/ports.h>
   MinList                            <exec/lists.h>
   MinNode                            <exec/nodes.h>
   MonitorInfo                        <graphics/displayinfo.h>
   MonitorSpec                        <graphics/monitor.h>
   mouth_rb                           <devices/narrator.h>

   MsgPort                            <exec/ports.h>
   NameInfo                           <graphics/displayinfo.h>
   narrator_rb                        <devices/narrator.h>
   NewBroker                          <libraries/commodities.h>
   NewGadget                          <libraries/gadtools.h>
   NewMenu                            <libraries/gadtools.h>
   NewScreen                          <intuition/screens.h>
   NewWindow                          <intuition/intuition.h>
   NexxStr                            <rexx/storage.h>
   Node                               <exec/nodes.h>
   NotifyMessage                      <dos/notify.h>
   NotifyRequest                      <dos/notify.h>

   OldDrawerData                      <workbench/workbench.h>
   opAddTail                          <intuition/classusr.h>
   opGet                              <intuition/classusr.h>
   opMember                           <intuition/classusr.h>
   opSet                              <intuition/classusr.h>
   opUpdate                           <intuition/classusr.h>

   PartitionBlock                     <devices/hardblocks.h>
   PGX                                <intuition/cghooks.h>
   Preferences                        <intuition/preferences.h>
   PrinterData                        <devices/prtbase.h>
   PrinterExtendedData                <devices/prtbase.h>
   PrinterSegment                     <devices/prtbase.h>
   Process                            <dos/dosextens.h>
   PropInfo                           <intuition/intuition.h>
   PrtInfo                            <devices/prtgfx.h>
   PubScreenNode                      <intuition/screens.h>

   QueryHeader                        <graphics/displayinfo.h>

   RastPort                           <graphics/rastport.h>
   RDArgs                             <dos/rdargs.h>
   RecordLock                         <dos/record.h>
   Rect32                             <graphics/gfx.h>
   Rectangle                          <graphics/gfx.h>
   Region                             <graphics/regions.h>
   RegionRectangle                    <graphics/regions.h>
   Remember                           <intuition/intuition.h>
   Requester                          <intuition/intuition.h>
   Resident                           <exec/resident.h>
   RexxArg                            <rexx/storage.h>
   RexxMsg                            <rexx/storage.h>
   RexxMsgPort                        <rexx/rexxio.h>
   RexxRsrc                           <rexx/storage.h>
   RexxTask                           <rexx/storage.h>
   RigidDiskBlock                     <devices/hardblocks.h>
   RootNode                           <dos/dosextens.h>
   RxsLib                             <rexx/rxslib.h>

   SatisfyMsg                         <devices/clipboard.h>
   Screen                             <intuition/screens.h>
   SCSICmd                            <devices/scsidisk.h>
   Segment                            <dos/dosextens.h>
   Semaphore                          <exec/semaphores.h>
   SemaphoreRequest                   <exec/semaphores.h>
   SGWork                             <intuition/sghooks.h>
   SignalSemaphore                    <exec/semaphores.h>
   SimpleSprite                       <graphics/sprite.h>
   SoftIntList                        <exec/interrupts.h>
   SpecialMonitor                     <graphics/monitor.h>
   SrcNode                            <rexx/storage.h>
   StackSwapStruct                    <exec/tasks.h>
   StandardPacket                     <dos/dosextens.h>
   StoredProperty                     <libraries/iffparse.h>
   StringExtend                       <intuition/sghooks.h>
   StringInfo                         <intuition/intuition.h>

   TagItem                            <utility/tagitem.h>
   Task                               <exec/tasks.h>
   TAvailFonts                        <libraries/diskfont.h>
   TDU_PublicUnit                     <devices/trackdisk.h>
   TextAttr                           <graphics/text.h>
   TextExtent                         <graphics/text.h>
   TextFont                           <graphics/text.h>
   TextFontExtension                  <graphics/text.h>
   TFontContents                      <libraries/diskfont.h>
   timerequest                        <devices/timer.h>
   timeval                            <devices/timer.h>
   TmpRas                             <graphics/rastport.h>
   TTextAttr                          <graphics/text.h>

   UCopList                           <graphics/copper.h>
   Unit                               <exec/devices.h>

   View                               <graphics/view.h>
   ViewExtra                          <graphics/view.h>
   ViewPort                           <graphics/view.h>
   ViewPortExtra                      <graphics/view.h>
   VSprite                            <graphics/gels.h>

   WBArg                              <workbench/startup.h>
   WBStartup                          <workbench/startup.h>
   Window                             <intuition/intuition.h>

   _Object                            <intuition/classes.h>


2.0 IncludeXREF: A

a2024_sync_raster pointer to long int in struct GfxBase
         +0x0174 graphics/gfxbase.h: *82
aBMS             #define 63 = 0x0000003f  devices/printer.h: *125
aCAM             #define 66 = 0x00000042  devices/printer.h: *128
aDEN1            #define 26 = 0x0000001a  devices/printer.h: *67
aDEN2            #define 25 = 0x00000019  devices/printer.h: *66
aDEN3            #define 24 = 0x00000018  devices/printer.h: *65
aDEN4            #define 23 = 0x00000017  devices/printer.h: *64
aDEN5            #define 22 = 0x00000016  devices/printer.h: *63
aDEN6            #define 21 = 0x00000015  devices/printer.h: *62
aEXTEND          #define 75 = 0x0000004b  devices/printer.h: *138
aFNT0            #define 34 = 0x00000022  devices/printer.h: *77
aFNT1            #define 35 = 0x00000023  devices/printer.h: *78
aFNT10           #define 44 = 0x0000002c  devices/printer.h: *87
aFNT2            #define 36 = 0x00000024  devices/printer.h: *79
aFNT3            #define 37 = 0x00000025  devices/printer.h: *80
aFNT4            #define 38 = 0x00000026  devices/printer.h: *81
aFNT5            #define 39 = 0x00000027  devices/printer.h: *82
aFNT6            #define 40 = 0x00000028  devices/printer.h: *83
aFNT7            #define 41 = 0x00000029  devices/printer.h: *84
aFNT8            #define 42 = 0x0000002a  devices/printer.h: *85
aFNT9            #define 43 = 0x0000002b  devices/printer.h: *86
aHTS             #define 67 = 0x00000043  devices/printer.h: *130
aIND             #define 2 = 0x00000002  devices/printer.h: *40
aJFY0            #define 52 = 0x00000034  devices/printer.h: *112
aJFY1            #define 54 = 0x00000036  devices/printer.h: *114
aJFY3            #define 53 = 0x00000035  devices/printer.h: *113
aJFY5            #define 49 = 0x00000031  devices/printer.h: *109
aJFY6            #define 51 = 0x00000033  devices/printer.h: *111
aJFY7            #define 50 = 0x00000032  devices/printer.h: *110
aLMS             #define 60 = 0x0000003c  devices/printer.h: *122
aNEL             #define 3 = 0x00000003  devices/printer.h: *41
aPERF            #define 58 = 0x0000003a  devices/printer.h: *119
aPERF0           #define 59 = 0x0000003b  devices/printer.h: *120
aPLD             #define 33 = 0x00000021  devices/printer.h: *75
aPLU             #define 32 = 0x00000020  devices/printer.h: *74
aPROP0           #define 47 = 0x0000002f  devices/printer.h: *107
aPROP1           #define 46 = 0x0000002e  devices/printer.h: *106
aPROP2           #define 45 = 0x0000002d  devices/printer.h: *105
aRAW             #define 76 = 0x0000004c  devices/printer.h: *140
aRI              #define 4 = 0x00000004  devices/printer.h: *42
aRIN             #define 1 = 0x00000001  devices/printer.h: *39
aRIS             #define 0 = 0x00000000  devices/printer.h: *38
aRMS             #define 61 = 0x0000003d  devices/printer.h: *123
aSBC             #define 13 = 0x0000000d  devices/printer.h: *52
aSFC             #define 12 = 0x0000000c  devices/printer.h: *51
aSGR0            #define 5 = 0x00000005  devices/printer.h: *44
aSGR1            #define 10 = 0x0000000a  devices/printer.h: *49
aSGR22           #define 11 = 0x0000000b  devices/printer.h: *50
aSGR23           #define 7 = 0x00000007  devices/printer.h: *46
aSGR24           #define 9 = 0x00000009  devices/printer.h: *48
aSGR3            #define 6 = 0x00000006  devices/printer.h: *45
aSGR4            #define 8 = 0x00000008  devices/printer.h: *47
aSHORP0          #define 14 = 0x0000000e  devices/printer.h: *54
aSHORP1          #define 16 = 0x00000010  devices/printer.h: *56
aSHORP2          #define 15 = 0x0000000f  devices/printer.h: *55
aSHORP3          #define 18 = 0x00000012  devices/printer.h: *58
aSHORP4          #define 17 = 0x00000011  devices/printer.h: *57
aSHORP5          #define 20 = 0x00000014  devices/printer.h: *60
aSHORP6          #define 19 = 0x00000013  devices/printer.h: *59
aSLPP            #define 57 = 0x00000039  devices/printer.h: *118
aSLRM            #define 65 = 0x00000041  devices/printer.h: *127
aSTBM            #define 64 = 0x00000040  devices/printer.h: *126
aSUS0            #define 31 = 0x0000001f  devices/printer.h: *73
aSUS1            #define 28 = 0x0000001c  devices/printer.h: *70
aSUS2            #define 27 = 0x0000001b  devices/printer.h: *69
aSUS3            #define 30 = 0x0000001e  devices/printer.h: *72
aSUS4            #define 29 = 0x0000001d  devices/printer.h: *71
aTBC0            #define 69 = 0x00000045  devices/printer.h: *132
aTBC1            #define 71 = 0x00000047  devices/printer.h: *134
aTBC3            #define 70 = 0x00000046  devices/printer.h: *133
aTBC4            #define 72 = 0x00000048  devices/printer.h: *135
aTBCALL          #define 73 = 0x00000049  devices/printer.h: *136
aTBSALL          #define 74 = 0x0000004a  devices/printer.h: *137
aTMS             #define 62 = 0x0000003e  devices/printer.h: *124
aTSS             #define 48 = 0x00000030  devices/printer.h: *108
aVERP0           #define 55 = 0x00000037  devices/printer.h: *116
aVERP1           #define 56 = 0x00000038  devices/printer.h: *117
aVTS             #define 68 = 0x00000044  devices/printer.h: *131
abs              function returning "LONG"   libraries/mathffp.h: *64
ac_dat           unsigned short int in struct AudChannel
         +0x000a hardware/custom.h: *102
ac_len           unsigned short int in struct AudChannel
         +0x0004 hardware/custom.h: *99
ac_pad           array [2] of unsigned short int in struct AudChannel
         +0x000c hardware/custom.h: *103
ac_per           unsigned short int in struct AudChannel
         +0x0006 hardware/custom.h: *100
ac_ptr           pointer to unsigned short int in struct AudChannel
         +0x0000 hardware/custom.h: *98
ac_vol           unsigned short int in struct AudChannel
         +0x0008 hardware/custom.h: *101
acos             #define IEEEDPAcos  libraries/mathffp.h: *42
                 libraries/mathieeedp.h: *42
adkcon           unsigned short int in struct Custom
         +0x009e hardware/custom.h: *96
adkconr          unsigned short int in struct Custom
         +0x0010 hardware/custom.h: *36
af_Attr          struct TextAttr(size 0x0008 bytes) in struct AvailFonts
         +0x0002 libraries/diskfont.h: *97
af_Type          unsigned short int in struct AvailFonts
         +0x0000 libraries/diskfont.h: *96
afh_NumEntries   unsigned short int in struct AvailFontsHeader
         +0x0000 libraries/diskfont.h: *106
afp              function returning "LONG"   libraries/mathffp.h: *78
ai_PRIVATE       pointer to void in struct AppIcon
         +0x0000 workbench/workbench.h: *147
al_Lock          long int in struct AssignList +0x0004 dos/dosextens.h: *398
al_Next          pointer to struct AssignList in struct AssignList
         +0x0000 dos/dosextens.h: *397
am_ArgList       pointer to struct WBArg in struct AppMessage
         +0x0022 workbench/workbench.h: *132
am_Class         unsigned short int in struct AppMessage
         +0x0028 workbench/workbench.h: *134
am_ID            unsigned long int in struct AppMessage
         +0x001a workbench/workbench.h: *130
am_Message       struct Message(size 0x0014 bytes) in struct AppMessage
         +0x0000 workbench/workbench.h: *127
am_Micros        unsigned long int in struct AppMessage
         +0x0032 workbench/workbench.h: *138
am_MouseX        short int in struct AppMessage
         +0x002a workbench/workbench.h: *135
am_MouseY        short int in struct AppMessage
         +0x002c workbench/workbench.h: *136
am_NumArgs       long int in struct AppMessage
         +0x001e workbench/workbench.h: *131
am_Reserved      array [8] of unsigned long int in struct AppMessage
         +0x0036 workbench/workbench.h: *139
am_Seconds       unsigned long int in struct AppMessage
         +0x002e workbench/workbench.h: *137
am_Type          unsigned short int in struct AppMessage
         +0x0014 workbench/workbench.h: *128
am_UserData      unsigned long int in struct AppMessage
         +0x0016 workbench/workbench.h: *129
am_Version       unsigned short int in struct AppMessage
         +0x0026 workbench/workbench.h: *133
ami_PRIVATE      pointer to void in struct AppMenuItem
         +0x0000 workbench/workbench.h: *148
an_Child         pointer to struct AChain in struct AChain
         +0x0000 dos/dosasl.h: *99
an_Flags         char in struct AChain +0x0110 dos/dosasl.h: *103
an_Info          struct FileInfoBlock(size 0x0104 bytes) in struct AChain
         +0x000c dos/dosasl.h: *102
an_Lock          long int in struct AChain +0x0008 dos/dosasl.h: *101
an_Parent        pointer to struct AChain in struct AChain
         +0x0004 dos/dosasl.h: *100
an_String        array [1] of unsigned char in struct AChain
         +0x0111 dos/dosasl.h: *104
ap_Base          pointer to struct AChain in struct AnchorPath
         +0x0000 dos/dosasl.h: *55
ap_BreakBits     long int in struct AnchorPath +0x0008 dos/dosasl.h: *59
ap_Buf           array [1] of unsigned char in struct AnchorPath
         +0x0118 dos/dosasl.h: *66
ap_Current       #define ap_Last  dos/dosasl.h: *58
ap_First         #define ap_Base  dos/dosasl.h: *56
ap_Flags         char in struct AnchorPath +0x0010 dos/dosasl.h: *61
ap_FoundBreak    long int in struct AnchorPath +0x000c dos/dosasl.h: *60
ap_Info          struct FileInfoBlock(size 0x0104 bytes) in struct AnchorPath
         +0x0014 dos/dosasl.h: *65
ap_Last          pointer to struct AChain in struct AnchorPath
         +0x0004 dos/dosasl.h: *57
ap_Length        #define ap_Flags  dos/dosasl.h: *64
ap_Reserved      char in struct AnchorPath +0x0011 dos/dosasl.h: *62
ap_Strlen        short int in struct AnchorPath +0x0012 dos/dosasl.h: *63
articulate       unsigned char in struct narrator_rb
         +0x004e devices/narrator.h: *115
asi_Start        unsigned short int in struct AnalogSignalInterval
         +0x0000 graphics/monitor.h: *138
asi_Stop         unsigned short int in struct AnalogSignalInterval
         +0x0002 graphics/monitor.h: *139
asin             #define IEEEDPAsin  libraries/mathffp.h: *44
                 libraries/mathieeedp.h: *44
atan             #define IEEEDPAtan  libraries/mathffp.h: *40
                 libraries/mathieeedp.h: *40
aud              array [4] of struct AudChannel(size 0x0010 bytes) in struct
                 Custom
         +0x00a0 hardware/custom.h: *104
aw_PRIVATE       pointer to void in struct AppWindow
         +0x0000 workbench/workbench.h: *146
A1adj            char in struct narrator_rb +0x004b devices/narrator.h: *112
A2024FIFTEENHERTZ_KEY #define 0x00049000 = 0x00049000
                 graphics/displayinfo.h: *210
A2024TENHERTZ_KEY #define 0x00041000 = 0x00041000
                 graphics/displayinfo.h: *209
A2024_MONITOR_ID #define 0x00041000 = 0x00041000  graphics/displayinfo.h: *207
A2adj            char in struct narrator_rb +0x004c devices/narrator.h: *113
A3adj            char in struct narrator_rb +0x004d devices/narrator.h: *114
ABC              #define 0x80 = 0x00000080  hardware/blit.h: *32
ABNC             #define 0x40 = 0x00000040  hardware/blit.h: *33
ABORT_BUSY       #define 288 = 0x00000120  dos/dosextens.h: *460
ABORT_DISK_ERROR #define 296 = 0x00000128  dos/dosextens.h: *459
ABS              macro (1 argument)   clib/macros.h: *17
ABSOLUTE_DIMENSIONS #define 0x0020 = 0x00000020  intuition/preferences.h: *249
ACCESS_READ      #define -2 = 0xfffffffe  dos/dos.h: *50
ACCESS_WRITE     #define -1 = 0xffffffff  dos/dos.h: *52
ACTION_ADD_NOTIFY #define 4097 = 0x00001001  dos/dosextens.h: *211
ACTION_CHANGE_MODE #define 1028 = 0x00000404  dos/dosextens.h: *201
ACTION_CHANGE_SIGNAL #define 995 = 0x000003e3  dos/dosextens.h: *193
ACTION_COPY_DIR  #define 19 = 0x00000013  dos/dosextens.h: *162
ACTION_COPY_DIR_FH #define 1030 = 0x00000406  dos/dosextens.h: *203
ACTION_CREATE_DIR #define 22 = 0x00000016  dos/dosextens.h: *165
ACTION_CURRENT_VOLUME #define 7 = 0x00000007  dos/dosextens.h: *153
ACTION_DELETE_OBJECT #define 16 = 0x00000010  dos/dosextens.h: *159
ACTION_DIE       #define 5 = 0x00000005  dos/dosextens.h: *151
ACTION_DISK_CHANGE #define 33 = 0x00000021  dos/dosextens.h: *176
ACTION_DISK_INFO #define 25 = 0x00000019  dos/dosextens.h: *168
ACTION_DISK_TYPE #define 32 = 0x00000020  dos/dosextens.h: *175
ACTION_END       #define 1007 = 0x000003ef  dos/dosextens.h: *187
ACTION_EVENT     #define 6 = 0x00000006  dos/dosextens.h: *152
ACTION_EXAMINE_ALL #define 1033 = 0x00000409  dos/dosextens.h: *205
ACTION_EXAMINE_FH #define 1034 = 0x0000040a  dos/dosextens.h: *206
ACTION_EXAMINE_NEXT #define 24 = 0x00000018  dos/dosextens.h: *167
ACTION_EXAMINE_OBJECT #define 23 = 0x00000017  dos/dosextens.h: *166
ACTION_FH_FROM_LOCK #define 1026 = 0x00000402  dos/dosextens.h: *199
ACTION_FINDINPUT #define 1005 = 0x000003ed  dos/dosextens.h: *185
ACTION_FINDOUTPUT #define 1006 = 0x000003ee  dos/dosextens.h: *186
ACTION_FINDUPDATE #define 1004 = 0x000003ec  dos/dosextens.h: *184
ACTION_FLUSH     #define 27 = 0x0000001b  dos/dosextens.h: *170
ACTION_FORMAT    #define 1020 = 0x000003fc  dos/dosextens.h: *194
ACTION_FREE_LOCK #define 15 = 0x0000000f  dos/dosextens.h: *158
ACTION_FREE_RECORD #define 2009 = 0x000007d9  dos/dosextens.h: *209
ACTION_GET_BLOCK #define 2 = 0x00000002  dos/dosextens.h: *149
ACTION_INFO      #define 26 = 0x0000001a  dos/dosextens.h: *169
ACTION_INHIBIT   #define 31 = 0x0000001f  dos/dosextens.h: *174
ACTION_IS_FILESYSTEM #define 1027 = 0x00000403  dos/dosextens.h: *200
ACTION_LOCATE_OBJECT #define 8 = 0x00000008  dos/dosextens.h: *154
ACTION_LOCK_RECORD #define 2008 = 0x000007d8  dos/dosextens.h: *208
ACTION_MAKE_LINK #define 1021 = 0x000003fd  dos/dosextens.h: *195
ACTION_MORE_CACHE #define 18 = 0x00000012  dos/dosextens.h: *161
ACTION_NIL       #define 0 = 0x00000000  dos/dosextens.h: *147
ACTION_PARENT    #define 29 = 0x0000001d  dos/dosextens.h: *172
ACTION_PARENT_FH #define 1031 = 0x00000407  dos/dosextens.h: *204
ACTION_QUEUE     #define 2003L = 0x000007d3  rexx/rexxio.h: *81
ACTION_READ      #define 'R' = 0x00000052  dos/dosextens.h: *157
ACTION_READ_LINK #define 1024 = 0x00000400  dos/dosextens.h: *198
ACTION_READ_RETURN #define 1001 = 0x000003e9  dos/dosextens.h: *181
ACTION_REMOVE_NOTIFY #define 4098 = 0x00001002  dos/dosextens.h: *212
ACTION_RENAME_DISK #define 9 = 0x00000009  dos/dosextens.h: *155
ACTION_RENAME_OBJECT #define 17 = 0x00000011  dos/dosextens.h: *160
ACTION_SAME_LOCK #define 40 = 0x00000028  dos/dosextens.h: *192
ACTION_SCREEN_MODE #define 994 = 0x000003e2  dos/dosextens.h: *179
ACTION_SEEK      #define 1008 = 0x000003f0  dos/dosextens.h: *183
ACTION_SET_COMMENT #define 28 = 0x0000001c  dos/dosextens.h: *171
ACTION_SET_DATE  #define 34 = 0x00000022  dos/dosextens.h: *177
ACTION_SET_FILE_SIZE #define 1022 = 0x000003fe  dos/dosextens.h: *188
ACTION_SET_MAP   #define 4 = 0x00000004  dos/dosextens.h: *150
ACTION_SET_PROTECT #define 21 = 0x00000015  dos/dosextens.h: *164
ACTION_STACK     #define 2002L = 0x000007d2  rexx/rexxio.h: *80
ACTION_STARTUP   #define 0 = 0x00000000  dos/dosextens.h: *148
ACTION_TIMER     #define 30 = 0x0000001e  dos/dosextens.h: *173
ACTION_WAIT_CHAR #define 20 = 0x00000014  dos/dosextens.h: *163
ACTION_WRITE     #define 'W' = 0x00000057  dos/dosextens.h: *156
ACTION_WRITE_PROTECT #define 1023 = 0x000003ff  dos/dosextens.h: *189
ACTION_WRITE_RETURN #define 1002 = 0x000003ea  dos/dosextens.h: *182
ACTIVATE         #define WFLG_ACTIVATE = 0x00001000
                 intuition/iobsolete.h: *160
ACTIVEGADGET     #define GACT_ACTIVEGADGET = 0x00004000
                 intuition/iobsolete.h: *86
ACTIVEWINDOW     #define IDCMP_ACTIVEWINDOW = 0x00040000
                 intuition/iobsolete.h: *132
AChain           structure tag size 0x0112 dos/dosasl.h: *55, 57, 98, 99, 100
ADALLOC_MAXPREC  #define 127 = 0x0000007f  devices/audio.h: *24
ADALLOC_MINPREC  #define -128 = 0xffffff80  devices/audio.h: *23
ADCMD_ALLOCATE   #define 32 = 0x00000020  devices/audio.h: *32
ADCMD_FINISH     #define (CMD_NONSTD+2) = 0x0000000b  devices/audio.h: *28
ADCMD_FREE       #define (CMD_NONSTD+0) = 0x00000009  devices/audio.h: *26
ADCMD_LOCK       #define (CMD_NONSTD+4) = 0x0000000d  devices/audio.h: *30
ADCMD_PERVOL     #define (CMD_NONSTD+3) = 0x0000000c  devices/audio.h: *29
ADCMD_SETPREC    #define (CMD_NONSTD+1) = 0x0000000a  devices/audio.h: *27
ADCMD_WAITCYCLE  #define (CMD_NONSTD+5) = 0x0000000e  devices/audio.h: *31
ADHARD_CHANNELS  #define 4 = 0x00000004  devices/audio.h: *21
ADIOB_NOWAIT     #define 6 = 0x00000006  devices/audio.h: *38
ADIOB_PERVOL     #define 4 = 0x00000004  devices/audio.h: *34
ADIOB_SYNCCYCLE  #define 5 = 0x00000005  devices/audio.h: *36
ADIOB_WRITEMESSAGE #define 7 = 0x00000007  devices/audio.h: *40
ADIOERR_ALLOCFAILED #define -11 = 0xfffffff5  devices/audio.h: *44
ADIOERR_CHANNELSTOLEN #define -12 = 0xfffffff4  devices/audio.h: *45
ADIOERR_NOALLOCATION #define -10 = 0xfffffff6  devices/audio.h: *43
ADIOF_NOWAIT     #define (1<<6) = 0x00000040  devices/audio.h: *39
ADIOF_PERVOL     #define (1<<4) = 0x00000010  devices/audio.h: *35
ADIOF_SYNCCYCLE  #define (1<<5) = 0x00000020  devices/audio.h: *37
ADIOF_WRITEMESSAGE #define (1<<7) = 0x00000080  devices/audio.h: *41
ADKB_FAST        #define 8 = 0x00000008  hardware/adkbits.h: *22
ADKB_MFMPREC     #define 12 = 0x0000000c  hardware/adkbits.h: *18
ADKB_MSBSYNC     #define 9 = 0x00000009  hardware/adkbits.h: *21
ADKB_PRECOMP0    #define 13 = 0x0000000d  hardware/adkbits.h: *17
ADKB_PRECOMP1    #define 14 = 0x0000000e  hardware/adkbits.h: *16
ADKB_SETCLR      #define 15 = 0x0000000f  hardware/adkbits.h: *15
ADKB_UARTBRK     #define 11 = 0x0000000b  hardware/adkbits.h: *19
ADKB_USE0P1      #define 4 = 0x00000004  hardware/adkbits.h: *26
ADKB_USE0V1      #define 0 = 0x00000000  hardware/adkbits.h: *30
ADKB_USE1P2      #define 5 = 0x00000005  hardware/adkbits.h: *25
ADKB_USE1V2      #define 1 = 0x00000001  hardware/adkbits.h: *29
ADKB_USE2P3      #define 6 = 0x00000006  hardware/adkbits.h: *24
ADKB_USE2V3      #define 2 = 0x00000002  hardware/adkbits.h: *28
ADKB_USE3PN      #define 7 = 0x00000007  hardware/adkbits.h: *23
ADKB_USE3VN      #define 3 = 0x00000003  hardware/adkbits.h: *27
ADKB_WORDSYNC    #define 10 = 0x0000000a  hardware/adkbits.h: *20
ADKF_FAST        #define (1<<8) = 0x00000100  hardware/adkbits.h: *39
ADKF_MFMPREC     #define (1<<12) = 0x00001000  hardware/adkbits.h: *35
ADKF_MSBSYNC     #define (1<<9) = 0x00000200  hardware/adkbits.h: *38
ADKF_PRE000NS    #define 0 = 0x00000000  hardware/adkbits.h: *49
ADKF_PRE140NS    #define (ADKF_PRECOMP0) = 0x00002000  hardware/adkbits.h: *50
ADKF_PRE280NS    #define (ADKF_PRECOMP1) = 0x00004000  hardware/adkbits.h: *51
ADKF_PRE560NS    #define (ADKF_PRECOMP0|ADKF_PRECOMP1) = 0x00006000
                 hardware/adkbits.h: *52
ADKF_PRECOMP0    #define (1<<13) = 0x00002000  hardware/adkbits.h: *34
ADKF_PRECOMP1    #define (1<<14) = 0x00004000  hardware/adkbits.h: *33
ADKF_SETCLR      #define (1<<15) = 0x00008000  hardware/adkbits.h: *32
ADKF_UARTBRK     #define (1<<11) = 0x00000800  hardware/adkbits.h: *36
ADKF_USE0P1      #define (1<<4) = 0x00000010  hardware/adkbits.h: *43
ADKF_USE0V1      #define (1<<0) = 0x00000001  hardware/adkbits.h: *47
ADKF_USE1P2      #define (1<<5) = 0x00000020  hardware/adkbits.h: *42
ADKF_USE1V2      #define (1<<1) = 0x00000002  hardware/adkbits.h: *46
ADKF_USE2P3      #define (1<<6) = 0x00000040  hardware/adkbits.h: *41
ADKF_USE2V3      #define (1<<2) = 0x00000004  hardware/adkbits.h: *45
ADKF_USE3PN      #define (1<<7) = 0x00000080  hardware/adkbits.h: *40
ADKF_USE3VN      #define (1<<3) = 0x00000008  hardware/adkbits.h: *44
ADKF_WORDSYNC    #define (1<<10) = 0x00000400  hardware/adkbits.h: *37
ADNB_STARTPROC   #define 0 = 0x00000000  libraries/expansion.h: *18
ADNF_STARTPROC   #define (1L<<0) = 0x00000001  libraries/expansion.h: *19
ADO_CommFileLen  #define (ADO_Dummy + 4) = 0x800007d4  dos/dostags.h: *132
ADO_CommNameLen  #define (ADO_Dummy + 3) = 0x800007d3  dos/dostags.h: *130
ADO_DirLen       #define (ADO_Dummy + 2) = 0x800007d2  dos/dostags.h: *128
ADO_Dummy        #define (TAG_USER + 2000) = 0x800007d0  dos/dostags.h: *115
ADO_FH_Mode      #define (ADO_Dummy + 1) = 0x800007d1  dos/dostags.h: *116
ADO_PromptLen    #define (ADO_Dummy + 5) = 0x800007d5  dos/dostags.h: *134
AFB_68010        #define 0 = 0x00000000  exec/execbase.h: *153
AFB_68020        #define 1 = 0x00000001  exec/execbase.h: *154
AFB_68030        #define 2 = 0x00000002  exec/execbase.h: *155
AFB_68040        #define 3 = 0x00000003  exec/execbase.h: *156
AFB_68881        #define 4 = 0x00000004  exec/execbase.h: *157
AFB_68882        #define 5 = 0x00000005  exec/execbase.h: *158
AFB_DISK         #define 1 = 0x00000001  libraries/diskfont.h: *87
AFB_MEMORY       #define 0 = 0x00000000  libraries/diskfont.h: *85
AFB_SCALED       #define 2 = 0x00000002  libraries/diskfont.h: *89
AFB_TAGGED       #define 16 = 0x00000010  libraries/diskfont.h: *92
AFF_68010        #define (1L<<0) = 0x00000001  exec/execbase.h: *160
AFF_68020        #define (1L<<1) = 0x00000002  exec/execbase.h: *161
AFF_68030        #define (1L<<2) = 0x00000004  exec/execbase.h: *162
AFF_68040        #define (1L<<3) = 0x00000008  exec/execbase.h: *163
AFF_68881        #define (1L<<4) = 0x00000010  exec/execbase.h: *164
AFF_68882        #define (1L<<5) = 0x00000020  exec/execbase.h: *165
AFF_DISK         #define 0x0002 = 0x00000002  libraries/diskfont.h: *88
AFF_MEMORY       #define 0x0001 = 0x00000001  libraries/diskfont.h: *86
AFF_SCALED       #define 0x0004 = 0x00000004  libraries/diskfont.h: *90
AFF_TAGGED       #define 0x10000L = 0x00010000  libraries/diskfont.h: *93
AFbias           char in struct narrator_rb +0x0055 devices/narrator.h: *119
AGNUS            #define  graphics/gfx.h: *22, 23
AG_BadParm       #define 0x00080000 = 0x00080000  exec/alerts.h: *53
AG_CloseDev      #define 0x000A0000 = 0x000a0000  exec/alerts.h: *55
AG_CloseLib      #define 0x00090000 = 0x00090000  exec/alerts.h: *54
AG_IOError       #define 0x00060000 = 0x00060000  exec/alerts.h: *51
AG_MakeLib       #define 0x00020000 = 0x00020000  exec/alerts.h: *47
AG_NoMemory      #define 0x00010000 = 0x00010000  exec/alerts.h: *46
AG_NoSignal      #define 0x00070000 = 0x00070000  exec/alerts.h: *52
AG_OpenDev       #define 0x00040000 = 0x00040000  exec/alerts.h: *49
AG_OpenLib       #define 0x00030000 = 0x00030000  exec/alerts.h: *48
AG_OpenRes       #define 0x00050000 = 0x00050000  exec/alerts.h: *50
AG_ProcCreate    #define 0x000B0000 = 0x000b0000  exec/alerts.h: *56
ALERTLAYERSNOMEM #define 0x83010000 = 0x83010000  graphics/layers.h: *52
ALERT_TYPE       #define 0x80000000 = 0x80000000  intuition/intuition.h: *1310
ALPHA_P_101      #define 0x01 = 0x00000001  intuition/preferences.h: *193
ALTKEYMAP        #define GACT_ALTKEYMAP = 0x00001000
                 intuition/iobsolete.h: *84
ALTLEFT          #define (IEQUALIFIER_LALT) = 0x00000010
                 intuition/intuition.h: *1336
ALTRIGHT         #define (IEQUALIFIER_RALT) = 0x00000020
                 intuition/intuition.h: *1337
AMIGAKEYS        #define (AMIGALEFT | AMIGARIGHT) = 0x000000c0
                 intuition/intuition.h: *1340
AMIGALEFT        #define (IEQUALIFIER_LCOMMAND) = 0x00000040
                 intuition/intuition.h: *1338
AMIGARIGHT       #define (IEQUALIFIER_RCOMMAND) = 0x00000080
                 intuition/intuition.h: *1339
AM_VERSION       #define 1 = 0x00000001  workbench/workbench.h: *124
ANBC             #define 0x20 = 0x00000020  hardware/blit.h: *34
ANBNC            #define 0x10 = 0x00000010  hardware/blit.h: *35
ANFRACSIZE       #define 6 = 0x00000006  graphics/gels.h: *46
ANIMHALF         #define 0x0020 = 0x00000020  graphics/gels.h: *47
ANTI_ALIAS       #define 0x0800 = 0x00000800  intuition/preferences.h: *259
AN_AddSWGadget   #define 0x8401000A = 0x8401000a  exec/alerts.h: *151
AN_AsyncPkt      #define 0x07000004 = 0x07000004  exec/alerts.h: *166
AN_AudioDev      #define 0x10000000 = 0x10000000  exec/alerts.h: *193
AN_BadChkSum     #define 0x07000009 = 0x07000009  exec/alerts.h: *171
AN_BadExpansionFree #define 0x0A000001 = 0x0a000001  exec/alerts.h: *187
AN_BadFreeAddr   #define 0x0100000F = 0x0100000f  exec/alerts.h: *116
AN_BadGadget     #define 0x04000001 = 0x04000001  exec/alerts.h: *142
AN_BadInitFunc   #define 0x0700000D = 0x0700000d  exec/alerts.h: *175
AN_BadMessage    #define 0x8400000D = 0x8400000d  exec/alerts.h: *154
AN_BadOverlay    #define 0x0700000C = 0x0700000c  exec/alerts.h: *174
AN_BadSegList    #define 0x08000001 = 0x08000001  exec/alerts.h: *180
AN_BadState      #define 0x8400000C = 0x8400000c  exec/alerts.h: *153
AN_BaseChkSum    #define 0x01000002 = 0x01000002  exec/alerts.h: *100
AN_BitMap        #define 0x07000007 = 0x07000007  exec/alerts.h: *169
AN_BltBitMap     #define 0x8201000A = 0x8201000a  exec/alerts.h: *125
AN_BogusExcpt    #define 0x8100000A = 0x8100000a  exec/alerts.h: *109
AN_BootError     #define 0x30000001 = 0x30000001  exec/alerts.h: *228
AN_BootStrap     #define 0x30000000 = 0x30000000  exec/alerts.h: *227
AN_CIARsrc       #define 0x20000000 = 0x20000000  exec/alerts.h: *216
AN_ConsoleDev    #define 0x11000000 = 0x11000000  exec/alerts.h: *196
AN_CreatePort    #define 0x84010002 = 0x84010002  exec/alerts.h: *143
AN_DOSLib        #define 0x07000000 = 0x07000000  exec/alerts.h: *162
AN_DRHasDisk     #define 0x21000001 = 0x21000001  exec/alerts.h: *220
AN_DRIntNoAct    #define 0x21000002 = 0x21000002  exec/alerts.h: *221
AN_DiskBlkSeq    #define 0x07000006 = 0x07000006  exec/alerts.h: *168
AN_DiskCopy      #define 0x32000000 = 0x32000000  exec/alerts.h: *252
AN_DiskError     #define 0x0700000A = 0x0700000a  exec/alerts.h: *172
AN_DiskRsrc      #define 0x21000000 = 0x21000000  exec/alerts.h: *219
AN_DiskfontLib   #define 0x0B000000 = 0x0b000000  exec/alerts.h: *190
AN_EndTask       #define 0x07000002 = 0x07000002  exec/alerts.h: *164
AN_ExcptVect     #define 0x01000001 = 0x01000001  exec/alerts.h: *99
AN_ExecLib       #define 0x01000000 = 0x01000000  exec/alerts.h: *98
AN_ExpansionLib  #define 0x0A000000 = 0x0a000000  exec/alerts.h: *186
AN_FileReclosed  #define 0x0700000E = 0x0700000e  exec/alerts.h: *176
AN_FreeTwice     #define 0x01000009 = 0x01000009  exec/alerts.h: *108
AN_FreeVec       #define 0x07000005 = 0x07000005  exec/alerts.h: *167
AN_GadTools      #define 0x33000000 = 0x33000000  exec/alerts.h: *255
AN_GadgetType    #define 0x84000001 = 0x84000001  exec/alerts.h: *141
AN_GamePortDev   #define 0x12000000 = 0x12000000  exec/alerts.h: *200
AN_GfxFreeError  #define 0x0200000D = 0x0200000d  exec/alerts.h: *129
AN_GfxNewError   #define 0x0200000C = 0x0200000c  exec/alerts.h: *128
AN_GfxNoLCM      #define 0x82011234 = 0x82011234  exec/alerts.h: *131
AN_GfxNoMem      #define 0x82010000 = 0x82010000  exec/alerts.h: *120
AN_GfxNoMemMspc  #define 0x82010001 = 0x82010001  exec/alerts.h: *121
AN_GraphicsLib   #define 0x02000000 = 0x02000000  exec/alerts.h: *119
AN_IOAfterClose  #define 0x0100000D = 0x0100000d  exec/alerts.h: *113
AN_IOUsedTwice   #define 0x0100000B = 0x0100000b  exec/alerts.h: *110
AN_IconLib       #define 0x09000000 = 0x09000000  exec/alerts.h: *183
AN_InitAPtr      #define 0x01000007 = 0x01000007  exec/alerts.h: *105
AN_IntrMem       #define 0x81000006 = 0x81000006  exec/alerts.h: *104
AN_Intuition     #define 0x04000000 = 0x04000000  exec/alerts.h: *140
AN_ItemAlloc     #define 0x04010003 = 0x04010003  exec/alerts.h: *144
AN_ItemBoxTop    #define 0x84000006 = 0x84000006  exec/alerts.h: *147
AN_KeyFree       #define 0x07000008 = 0x07000008  exec/alerts.h: *170
AN_KeyRange      #define 0x0700000B = 0x0700000b  exec/alerts.h: *173
AN_KeyboardDev   #define 0x13000000 = 0x13000000  exec/alerts.h: *203
AN_LayersLib     #define 0x03000000 = 0x03000000  exec/alerts.h: *136
AN_LayersNoMem   #define 0x83010000 = 0x83010000  exec/alerts.h: *137
AN_LibChkSum     #define 0x01000003 = 0x01000003  exec/alerts.h: *101
AN_LongFrame     #define 0x82010006 = 0x82010006  exec/alerts.h: *122
AN_MakeVPort     #define 0x82010030 = 0x82010030  exec/alerts.h: *127
AN_MathLib       #define 0x05000000 = 0x05000000  exec/alerts.h: *159
AN_MemCorrupt    #define 0x81000005 = 0x81000005  exec/alerts.h: *103
AN_MemoryInsane  #define 0x0100000C = 0x0100000c  exec/alerts.h: *112
AN_MiscRsrc      #define 0x22000000 = 0x22000000  exec/alerts.h: *224
AN_NoConsole     #define 0x8400000F = 0x8400000f  exec/alerts.h: *156
AN_NoFonts       #define 0xB1000001 = 0xb1000001  exec/alerts.h: *232
AN_NoWindow      #define 0x11000001 = 0x11000001  exec/alerts.h: *197
AN_ObsoleteFont  #define 0x02000401 = 0x02000401  exec/alerts.h: *133
AN_OpenScreen    #define 0x84010007 = 0x84010007  exec/alerts.h: *148
AN_OpenScrnRast  #define 0x84010008 = 0x84010008  exec/alerts.h: *149
AN_OpenWindow    #define 0x8401000B = 0x8401000b  exec/alerts.h: *152
AN_PlaneAlloc    #define 0x84010005 = 0x84010005  exec/alerts.h: *146
AN_QPktFail      #define 0x07000003 = 0x07000003  exec/alerts.h: *165
AN_RAMLib        #define 0x08000000 = 0x08000000  exec/alerts.h: *179
AN_RegionMemory  #define 0x8201000B = 0x8201000b  exec/alerts.h: *126
AN_SemCorrupt    #define 0x01000008 = 0x01000008  exec/alerts.h: *107
AN_ShortFrame    #define 0x82010007 = 0x82010007  exec/alerts.h: *123
AN_StackProbe    #define 0x0100000E = 0x0100000e  exec/alerts.h: *114
AN_StartMem      #define 0x07010001 = 0x07010001  exec/alerts.h: *163
AN_SubAlloc      #define 0x04010004 = 0x04010004  exec/alerts.h: *145
AN_SysScrnType   #define 0x84000009 = 0x84000009  exec/alerts.h: *150
AN_TDCalibSeek   #define 0x14000001 = 0x14000001  exec/alerts.h: *207
AN_TDDelay       #define 0x14000002 = 0x14000002  exec/alerts.h: *208
AN_TMBadReq      #define 0x15000001 = 0x15000001  exec/alerts.h: *212
AN_TMBadSupply   #define 0x15000002 = 0x15000002  exec/alerts.h: *213
AN_TextTmpRas    #define 0x02010009 = 0x02010009  exec/alerts.h: *124
AN_TimerDev      #define 0x15000000 = 0x15000000  exec/alerts.h: *211
AN_TrackDiskDev  #define 0x14000000 = 0x14000000  exec/alerts.h: *206
AN_Unknown       #define 0x35000000 = 0x35000000  exec/alerts.h: *261
AN_UtilityLib    #define 0x34000000 = 0x34000000  exec/alerts.h: *258
AN_WBAddToolMenuItem #define 0xB1010008 = 0xb1010008  exec/alerts.h: *241
AN_WBBadIOMsg    #define 0x31000003 = 0x31000003  exec/alerts.h: *235
AN_WBBadStartupMsg1 #define 0x31000001 = 0x31000001  exec/alerts.h: *233
AN_WBBadStartupMsg2 #define 0x31000002 = 0x31000002  exec/alerts.h: *234
AN_WBCreateWBMenusCreateMenus1 #define 0xB1010005 = 0xb1010005
                 exec/alerts.h: *238
AN_WBCreateWBMenusCreateMenus2 #define 0xB1010006 = 0xb1010006
                 exec/alerts.h: *239
AN_WBInitLayerDemon #define 0xB101000B = 0xb101000b  exec/alerts.h: *244
AN_WBInitPotionAllocDrawer #define 0xB1010004 = 0xb1010004
                 exec/alerts.h: *237
AN_WBInitScreenAndWindows1 #define 0xB101000D = 0xb101000d
                 exec/alerts.h: *246
AN_WBInitScreenAndWindows2 #define 0xB101000E = 0xb101000e
                 exec/alerts.h: *247
AN_WBInitScreenAndWindows3 #define 0xB101000F = 0xb101000f
                 exec/alerts.h: *248
AN_WBLayoutWBMenusLayoutMenus #define 0xB1010007 = 0xb1010007
                 exec/alerts.h: *240
AN_WBMAlloc      #define 0xB1010010 = 0xb1010010  exec/alerts.h: *249
AN_WBReLayoutToolMenu #define 0xB1010009 = 0xb1010009  exec/alerts.h: *242
AN_WBinitTimer   #define 0xB101000A = 0xb101000a  exec/alerts.h: *243
AN_WBinitWbGels  #define 0xB101000C = 0xb101000c  exec/alerts.h: *245
AN_WeirdEcho     #define 0x8400000E = 0x8400000e  exec/alerts.h: *155
AN_Workbench     #define 0x31000000 = 0x31000000  exec/alerts.h: *231
AO_AudioDev      #define 0x00008010 = 0x00008010  exec/alerts.h: *72
AO_BootStrap     #define 0x00008030 = 0x00008030  exec/alerts.h: *83
AO_CIARsrc       #define 0x00008020 = 0x00008020  exec/alerts.h: *79
AO_ConsoleDev    #define 0x00008011 = 0x00008011  exec/alerts.h: *73
AO_DOSLib        #define 0x00008007 = 0x00008007  exec/alerts.h: *65
AO_DiskCopy      #define 0x00008032 = 0x00008032  exec/alerts.h: *85
AO_DiskRsrc      #define 0x00008021 = 0x00008021  exec/alerts.h: *80
AO_DiskfontLib   #define 0x0000800B = 0x0000800b  exec/alerts.h: *69
AO_ExecLib       #define 0x00008001 = 0x00008001  exec/alerts.h: *60
AO_ExpansionLib  #define 0x0000800A = 0x0000800a  exec/alerts.h: *68
AO_GadTools      #define 0x00008033 = 0x00008033  exec/alerts.h: *86
AO_GamePortDev   #define 0x00008012 = 0x00008012  exec/alerts.h: *74
AO_GraphicsLib   #define 0x00008002 = 0x00008002  exec/alerts.h: *61
AO_IconLib       #define 0x00008009 = 0x00008009  exec/alerts.h: *67
AO_Intuition     #define 0x00008004 = 0x00008004  exec/alerts.h: *63
AO_KeyboardDev   #define 0x00008013 = 0x00008013  exec/alerts.h: *75
AO_LayersLib     #define 0x00008003 = 0x00008003  exec/alerts.h: *62
AO_MathLib       #define 0x00008005 = 0x00008005  exec/alerts.h: *64
AO_MiscRsrc      #define 0x00008022 = 0x00008022  exec/alerts.h: *81
AO_RAMLib        #define 0x00008008 = 0x00008008  exec/alerts.h: *66
AO_TimerDev      #define 0x00008015 = 0x00008015  exec/alerts.h: *77
AO_TrackDiskDev  #define 0x00008014 = 0x00008014  exec/alerts.h: *76
AO_Unknown       #define 0x00008035 = 0x00008035  exec/alerts.h: *87
AO_UtilityLib    #define 0x0000800C = 0x0000800c  exec/alerts.h: *70
AO_Workbench     #define 0x00008031 = 0x00008031  exec/alerts.h: *84
AOlPen           char in struct RastPort +0x001b graphics/rastport.h: *67
APB_DIDDIR       #define 3 = 0x00000003  dos/dosasl.h: *85
APB_DODIR        #define 2 = 0x00000002  dos/dosasl.h: *80
APB_DODOT        #define 5 = 0x00000005  dos/dosasl.h: *91
APB_DOWILD       #define 0 = 0x00000000  dos/dosasl.h: *71
APB_DirChanged   #define 6 = 0x00000006  dos/dosasl.h: *94
APB_ITSWILD      #define 1 = 0x00000001  dos/dosasl.h: *74
APB_NOMEMERR     #define 4 = 0x00000004  dos/dosasl.h: *88
APF_DIDDIR       #define 8 = 0x00000008  dos/dosasl.h: *86
APF_DODIR        #define 4 = 0x00000004  dos/dosasl.h: *81
APF_DODOT        #define 32 = 0x00000020  dos/dosasl.h: *92
APF_DOWILD       #define 1 = 0x00000001  dos/dosasl.h: *72
APF_DirChanged   #define 64 = 0x00000040  dos/dosasl.h: *95
APF_ITSWILD      #define 2 = 0x00000002  dos/dosasl.h: *75
APF_NOMEMERR     #define 16 = 0x00000010  dos/dosasl.h: *89
APTR             typedef pointer to void  exec/types.h: *36
APTR_TYPEDEF     #define  exec/types.h: *35
AREAOUTLINE      #define 0x08 = 0x00000008  graphics/rastport.h: *107
ARG0             macro (1 argument)   rexx/storage.h: *117
ARG1             macro (1 argument)   rexx/storage.h: *118
ARG2             macro (1 argument)   rexx/storage.h: *119
ARROWIDCMP       #define (IDCMP_GADGETUP | IDCMP_GADGETDOWN | IDCMP_INTUITICKS
                 | IDCMP_MOUSEBUTTONS) = 0x00400068
                 libraries/gadtools.h: *64
ASHIFTSHIFT      #define 12 = 0x0000000c  hardware/blit.h: *63
ASL_BackPen      #define ASL_Dummy+15 = 0x8008000f  libraries/asl.h: *210
ASL_CancelText   #define ASL_Dummy+19 = 0x80080013  libraries/asl.h: *215
ASL_Dir          #define ASL_Dummy+9 = 0x80080009  libraries/asl.h: *202
ASL_Dummy        #define (TAG_USER + 0x80000) = 0x80080000
                 libraries/asl.h: *190
ASL_ExtFlags1    #define ASL_Dummy+22 = 0x80080016  libraries/asl.h: *219
ASL_File         #define ASL_Dummy+8 = 0x80080008  libraries/asl.h: *201
ASL_FileRequest  #define 0 = 0x00000000  libraries/asl.h: *183
ASL_FontFlags    #define ASL_Dummy+13 = 0x8008000d  libraries/asl.h: *208
ASL_FontHeight   #define ASL_Dummy+11 = 0x8008000b  libraries/asl.h: *206
ASL_FontName     #define ASL_Dummy+10 = 0x8008000a  libraries/asl.h: *205
ASL_FontRequest  #define 1 = 0x00000001  libraries/asl.h: *184
ASL_FontStyles   #define ASL_Dummy+12 = 0x8008000c  libraries/asl.h: *207
ASL_FrontPen     #define ASL_Dummy+14 = 0x8008000e  libraries/asl.h: *209
ASL_FuncFlags    #define ASL_Dummy+20 = 0x80080014  libraries/asl.h: *216
ASL_Hail         #define ASL_Dummy+1 = 0x80080001  libraries/asl.h: *192
ASL_Height       #define ASL_Dummy+6 = 0x80080006  libraries/asl.h: *197
ASL_HookFunc     #define ASL_Dummy+7 = 0x80080007  libraries/asl.h: *198
ASL_LeftEdge     #define ASL_Dummy+3 = 0x80080003  libraries/asl.h: *194
ASL_MaxHeight    #define ASL_Dummy+17 = 0x80080011  libraries/asl.h: *212
ASL_MinHeight    #define ASL_Dummy+16 = 0x80080010  libraries/asl.h: *211
ASL_ModeList     #define ASL_Dummy+21 = 0x80080015  libraries/asl.h: *218
ASL_OKText       #define ASL_Dummy+18 = 0x80080012  libraries/asl.h: *214
ASL_Pattern      #define ASL_FontName = 0x8008000a  libraries/asl.h: *221
ASL_TopEdge      #define ASL_Dummy+4 = 0x80080004  libraries/asl.h: *195
ASL_Width        #define ASL_Dummy+5 = 0x80080005  libraries/asl.h: *196
ASL_Window       #define ASL_Dummy+2 = 0x80080002  libraries/asl.h: *193
ASPECT_HORIZ     #define 0x00 = 0x00000000  intuition/preferences.h: *176
ASPECT_VERT      #define 0x01 = 0x00000001  intuition/preferences.h: *177
AT_DeadEnd       #define 0x80000000 = 0x80000000  exec/alerts.h: *41
AT_Recovery      #define 0x00000000 = 0x00000000  exec/alerts.h: *42
AUDIONAME        #define "audio.device"  devices/audio.h: *19
AUL              #define 0x4 = 0x00000004  hardware/blit.h: *78
AUTOBACKPEN      #define 1 = 0x00000001  intuition/intuition.h: *1321
AUTODRAWMODE     #define JAM2 = 0x00000001  intuition/intuition.h: *1322
AUTOFRONTPEN     #define 0 = 0x00000000  intuition/intuition.h: *1320
AUTOITEXTFONT    #define NULL = 0x00000000  intuition/intuition.h: *1325
AUTOKNOB         #define 0x0001 = 0x00000001  intuition/intuition.h: *497
AUTOLEFTEDGE     #define 6 = 0x00000006  intuition/intuition.h: *1323
AUTONEXTTEXT     #define NULL = 0x00000000  intuition/intuition.h: *1326
AUTOSCROLL       #define 0x4000 = 0x00004000  intuition/screens.h: *182
AUTOTOPEDGE      #define 3 = 0x00000003  intuition/intuition.h: *1324
AUserExt         short int in struct AnimOb +0x0028 graphics/gels.h: *225
AUserStuff       #define WORD  graphics/gels.h: *64, 224
AVbias           char in struct narrator_rb +0x0054 devices/narrator.h: *118
A_OR_B           #define ABC|ANBC|NABC | ABNC|ANBNC|NABNC = 0x000000fc
                 hardware/blit.h: *42
A_OR_C           #define ABC|NABC|ABNC | ANBC|NANBC|ANBNC = 0x000000fa
                 hardware/blit.h: *43
A_TO_D           #define ABC|ANBC|ABNC|ANBNC = 0x000000f0
                 hardware/blit.h: *45
A_XOR_C          #define NABC|ABNC | NANBC|ANBNC = 0x0000005a
                 hardware/blit.h: *44
ActiView         pointer to struct View in struct GfxBase
         +0x0022 graphics/gfxbase.h: *28
ActiViewCprSemaphore pointer to struct SignalSemaphore in struct GfxBase
         +0x019a graphics/gfxbase.h: *90
Actions          unsigned long int in struct SGWork
         +0x001e intuition/sghooks.h: *46
Activation       unsigned short int in struct Gadget
         +0x000e intuition/intuition.h: *225
ActivePens       array [2] of unsigned char in struct StringExtend
         +0x0006 intuition/sghooks.h: *23
ActiveScreen     pointer to struct Screen in struct IntuitionBase
         +0x0038 intuition/intuitionbase.h: *75
ActiveWindow     pointer to struct Window in struct IntuitionBase
         +0x0034 intuition/intuitionbase.h: *74
After            pointer to struct Bob in struct Bob
         +0x000e graphics/gels.h: *154
AlertData        pointer to void in struct ExecBase
         +0x004a exec/execbase.h: *52
AlgoStyle        unsigned char in struct RastPort
         +0x0038 graphics/rastport.h: *79
AltKeyMap        pointer to struct KeyMap in struct StringInfo
         +0x0020 intuition/intuition.h: *560
AnOldX           short int in struct AnimOb +0x000e graphics/gels.h: *208
AnOldY           short int in struct AnimOb +0x000c graphics/gels.h: *208
AnX              short int in struct AnimOb +0x0012 graphics/gels.h: *211
AnY              short int in struct AnimOb +0x0010 graphics/gels.h: *211
AnalogSignalInterval structure tag
     size 0x0004 graphics/monitor.h: *136, 150, 151, 152, 153
AnchorPath       structure tag size 0x0119 dos/dosasl.h: *54
AnimBob          pointer to struct Bob in struct AnimComp
         +0x0022 graphics/gels.h: *197
AnimCRoutine     pointer to function returning short int in struct AnimComp
         +0x0016 graphics/gels.h: *190
AnimComp         structure tag
     size 0x0026 graphics/gels.h: *158, 165, 183, 184, 187, 188,
                             222
AnimORoutine     pointer to function returning short int in struct AnimOb
         +0x0020 graphics/gels.h: *219
AnimOb           structure tag size 0x002a graphics/gels.h: *195, 200, 203
AppIcon          structure tag size 0x0004 workbench/workbench.h: *147
AppMenuItem      structure tag size 0x0004 workbench/workbench.h: *148
AppMessage       structure tag size 0x0056 workbench/workbench.h: *126
AppWindow        structure tag size 0x0004 workbench/workbench.h: *146
AreaCircle       macro (4 arguments)   graphics/gfxmacros.h: *44
AreaInfo         structure tag size 0x0018 graphics/rastport.h: *23, 62
AreaInfo         pointer to struct AreaInfo in struct RastPort
         +0x0010 graphics/rastport.h: *62
AreaPtSz         char in struct RastPort +0x001d graphics/rastport.h: *69
AreaPtrn         pointer to unsigned short int in struct RastPort
         +0x0008 graphics/rastport.h: *60
AslName          #define "asl.library"  libraries/asl.h: *50
AssignList       structure tag size 0x0008 dos/dosextens.h: *386, 396, 397
AttnFlags        unsigned short int in struct ExecBase
         +0x0128 exec/execbase.h: *73
AttnResched      unsigned short int in struct ExecBase
         +0x012a exec/execbase.h: *75
AudChannel       structure tag (size 0x0010 bytes)in struct Custom
                 hardware/custom.h: *97
AvailFonts       structure tag size 0x000a libraries/diskfont.h: *95
AvailFontsHeader structure tag size 0x0002 libraries/diskfont.h: *105


2.0 IncludeXREF: B

back             pointer to struct Layer in struct Layer
         +0x0004 graphics/clip.h: *36
backgroundPen    #define BACKGROUNDPEN = 0x00000007
                 intuition/iobsolete.h: *268
bb_chksum        long int in struct BootBlock +0x0004 devices/bootblock.h: *21
bb_dosblock      long int in struct BootBlock +0x0008 devices/bootblock.h: *22
bb_id            array [4] of unsigned char in struct BootBlock
         +0x0000 devices/bootblock.h: *20
bbb_BlockPairs   array [61] of struct BadBlockEntry(size 0x0008 bytes) in
                 struct BadBlockBlock
         +0x0018 devices/hardblocks.h: *121
bbb_ChkSum       long int in struct BadBlockBlock
         +0x0008 devices/hardblocks.h: *117
bbb_HostID       unsigned long int in struct BadBlockBlock
         +0x000c devices/hardblocks.h: *118
bbb_ID           unsigned long int in struct BadBlockBlock
         +0x0000 devices/hardblocks.h: *115
bbb_Next         unsigned long int in struct BadBlockBlock
         +0x0010 devices/hardblocks.h: *119
bbb_Reserved     unsigned long int in struct BadBlockBlock
         +0x0014 devices/hardblocks.h: *120
bbb_SummedLongs unsigned long int in struct BadBlockBlock
         +0x0004 devices/hardblocks.h: *116
bbe_BadBlock     unsigned long int in struct BadBlockEntry
         +0x0000 devices/hardblocks.h: *110
bbe_GoodBlock    unsigned long int in struct BadBlockEntry
         +0x0004 devices/hardblocks.h: *111
beamcon0         unsigned short int in struct Custom
         +0x01dc hardware/custom.h: *137
beamsync         short int in struct bltnode +0x000c hardware/blit.h: *96
blitbuff         pointer to short int in struct Layer_Info
         +0x005e graphics/layers.h: *47
blitsize         short int in struct bltnode +0x000a hardware/blit.h: *95
blitter          pointer to long int in struct GfxBase
         +0x002e graphics/gfxbase.h: *31
blockPen         #define BLOCKPEN = 0x00000001  intuition/iobsolete.h: *262
bltadat          unsigned short int in struct Custom
         +0x0074 hardware/custom.h: *79
bltafwm          unsigned short int in struct Custom
         +0x0044 hardware/custom.h: *61
bltalwm          unsigned short int in struct Custom
         +0x0046 hardware/custom.h: *62
bltamod          unsigned short int in struct Custom
         +0x0064 hardware/custom.h: *74
bltapt           pointer to void in struct Custom
         +0x0050 hardware/custom.h: *65
bltbdat          unsigned short int in struct Custom
         +0x0072 hardware/custom.h: *78
bltbmod          unsigned short int in struct Custom
         +0x0062 hardware/custom.h: *73
bltbpt           pointer to void in struct Custom
         +0x004c hardware/custom.h: *64
bltcdat          unsigned short int in struct Custom
         +0x0070 hardware/custom.h: *77
bltcmod          unsigned short int in struct Custom
         +0x0060 hardware/custom.h: *72
bltcon0          unsigned short int in struct Custom
         +0x0040 hardware/custom.h: *59
bltcon0l         unsigned char in struct Custom +0x005b hardware/custom.h: *69
bltcon1          unsigned short int in struct Custom
         +0x0042 hardware/custom.h: *60
bltcpt           pointer to void in struct Custom
         +0x0048 hardware/custom.h: *63
bltddat          unsigned short int in struct Custom
         +0x0000 hardware/custom.h: *28
bltdmod          unsigned short int in struct Custom
         +0x0066 hardware/custom.h: *75
bltdpt           pointer to void in struct Custom
         +0x0054 hardware/custom.h: *66
blthd            pointer to struct bltnode in struct GfxBase
         +0x003a graphics/gfxbase.h: *34
bltnode          structure tag size 0x0012 graphics/gfxbase.h: *34, 35
                 hardware/blit.h: 90, 92
bltsize          unsigned short int in struct Custom
         +0x0058 hardware/custom.h: *67
bltsizh          unsigned short int in struct Custom
         +0x005e hardware/custom.h: *71
bltsizv          unsigned short int in struct Custom
         +0x005c hardware/custom.h: *70
bltsrv           struct Interrupt(size 0x0016 bytes) in struct GfxBase
         +0x0076 graphics/gfxbase.h: *36
blttl            pointer to struct bltnode in struct GfxBase
         +0x003e graphics/gfxbase.h: *34
bn_DeviceNode    pointer to void in struct BootNode
         +0x0010 libraries/expansionbase.h: *39
bn_Flags         unsigned short int in struct BootNode
         +0x000e libraries/expansionbase.h: *38
bn_Node          struct Node(size 0x000e bytes) in struct BootNode
         +0x0000 libraries/expansionbase.h: *37
bottommost       short int in struct GelsInfo +0x001c graphics/rastport.h: *52
bounds           struct Rectangle(size 0x0008 bytes) in struct Layer
         +0x0010 graphics/clip.h: *39
bounds           struct Rectangle(size 0x0008 bytes) in struct ClipRect
         +0x0010 graphics/clip.h: *70
bounds           struct Rectangle(size 0x0008 bytes) in struct RegionRectangle
         +0x0008 graphics/regions.h: *26
bounds           struct Rectangle(size 0x0008 bytes) in struct Region
         +0x0000 graphics/regions.h: *31
bpl1mod          unsigned short int in struct Custom
         +0x0108 hardware/custom.h: *110
bpl2mod          unsigned short int in struct Custom
         +0x010a hardware/custom.h: *111
bplcon0          unsigned short int in struct Custom
         +0x0100 hardware/custom.h: *106
bplcon1          unsigned short int in struct Custom
         +0x0102 hardware/custom.h: *107
bplcon2          unsigned short int in struct Custom
         +0x0104 hardware/custom.h: *108
bplcon3          unsigned short int in struct Custom
         +0x0106 hardware/custom.h: *109
bpldat           array [8] of unsigned short int in struct Custom
         +0x0110 hardware/custom.h: *114
bplhmod          unsigned short int in struct Custom
         +0x010c hardware/custom.h: *112
bplhstop         unsigned short int in struct Custom
         +0x01d6 hardware/custom.h: *134
bplhstrt         unsigned short int in struct Custom
         +0x01d4 hardware/custom.h: *133
bplpt            array [8] of pointer to void in struct Custom
         +0x00e0 hardware/custom.h: *105
bsa_DestBitMap   pointer to struct BitMap in struct BitScaleArgs
         +0x001c graphics/scale.h: *27
bsa_DestHeight   unsigned short int in struct BitScaleArgs
         +0x0012 graphics/scale.h: *24
bsa_DestWidth    unsigned short int in struct BitScaleArgs
         +0x0010 graphics/scale.h: *24
bsa_DestX        unsigned short int in struct BitScaleArgs
         +0x000c graphics/scale.h: *23
bsa_DestY        unsigned short int in struct BitScaleArgs
         +0x000e graphics/scale.h: *23
bsa_Flags        unsigned long int in struct BitScaleArgs
         +0x0020 graphics/scale.h: *28
bsa_Reserved1    long int in struct BitScaleArgs +0x0028 graphics/scale.h: *30
bsa_Reserved2    long int in struct BitScaleArgs +0x002c graphics/scale.h: *31
bsa_SrcBitMap    pointer to struct BitMap in struct BitScaleArgs
         +0x0018 graphics/scale.h: *26
bsa_SrcHeight    unsigned short int in struct BitScaleArgs
         +0x0006 graphics/scale.h: *21
bsa_SrcWidth     unsigned short int in struct BitScaleArgs
         +0x0004 graphics/scale.h: *21
bsa_SrcX         unsigned short int in struct BitScaleArgs
         +0x0000 graphics/scale.h: *20
bsa_SrcY         unsigned short int in struct BitScaleArgs
         +0x0002 graphics/scale.h: *20
bsa_XDDA         unsigned short int in struct BitScaleArgs
         +0x0024 graphics/scale.h: *29
bsa_XDestFactor unsigned short int in struct BitScaleArgs
         +0x0014 graphics/scale.h: *25
bsa_XSrcFactor   unsigned short int in struct BitScaleArgs
         +0x0008 graphics/scale.h: *22
bsa_YDDA         unsigned short int in struct BitScaleArgs
         +0x0026 graphics/scale.h: *29
bsa_YDestFactor unsigned short int in struct BitScaleArgs
         +0x0016 graphics/scale.h: *25
bsa_YSrcFactor   unsigned short int in struct BitScaleArgs
         +0x000a graphics/scale.h: *22
bsblthd          pointer to struct bltnode in struct GfxBase
         +0x0042 graphics/gfxbase.h: *35
bsblttl          pointer to struct bltnode in struct GfxBase
         +0x0046 graphics/gfxbase.h: *35
bytereserved     unsigned char in struct GfxBase
         +0x00a7 graphics/gfxbase.h: *45
B2BOBBER         #define 2 = 0x00000002  graphics/gels.h: *253
B2NORM           #define 0 = 0x00000000  graphics/gels.h: *251
B2SWAP           #define 1 = 0x00000001  graphics/gels.h: *252
BACKDROP         #define WFLG_BACKDROP = 0x00000100
                 intuition/iobsolete.h: *156
BACKGROUNDPEN    #define (0x0007) = 0x00000007  intuition/screens.h: *89
BACKSAVED        #define 0x0100 = 0x00000100  graphics/gels.h: *27
BADDR            macro (1 argument)   dos/dos.h: *110
BASEOBJECT       macro (1 argument)   intuition/classes.h: *77
BATTCLOCKNAME    #define "battclock.resource"  resources/battclock.h: *15
BATTMEMNAME      #define "battmem.resource"  resources/battmem.h: *15
BATTMEM_AMIGA_AMNESIA_ADDR #define 0 = 0x00000000
                 resources/battmembitsamiga.h: *32
BATTMEM_AMIGA_AMNESIA_LEN #define 1 = 0x00000001
                 resources/battmembitsamiga.h: *33
BATTMEM_SCSI_HOST_ID_ADDR #define 65 = 0x00000041
                 resources/battmembitsshared.h: *44
BATTMEM_SCSI_HOST_ID_LEN #define 3 = 0x00000003
                 resources/battmembitsshared.h: *45
BATTMEM_SCSI_LUNS_ADDR #define 2 = 0x00000002
                 resources/battmembitsamiga.h: *61
BATTMEM_SCSI_LUNS_LEN #define 1 = 0x00000001
                 resources/battmembitsamiga.h: *62
BATTMEM_SCSI_SYNC_XFER_ADDR #define 68 = 0x00000044
                 resources/battmembitsshared.h: *58
BATTMEM_SCSI_SYNC_XFER_LEN #define 1 = 0x00000001
                 resources/battmembitsshared.h: *59
BATTMEM_SCSI_TIMEOUT_ADDR #define 1 = 0x00000001
                 resources/battmembitsamiga.h: *47
BATTMEM_SCSI_TIMEOUT_LEN #define 1 = 0x00000001
                 resources/battmembitsamiga.h: *48
BATTMEM_SHARED_AMNESIA_ADDR #define 64 = 0x00000040
                 resources/battmembitsshared.h: *32
BATTMEM_SHARED_AMNESIA_LEN #define 1 = 0x00000001
                 resources/battmembitsshared.h: *33
BAUD_110         #define 0x00 = 0x00000000  intuition/preferences.h: *145
BAUD_1200        #define 0x02 = 0x00000002  intuition/preferences.h: *147
BAUD_19200       #define 0x06 = 0x00000006  intuition/preferences.h: *151
BAUD_2400        #define 0x03 = 0x00000003  intuition/preferences.h: *148
BAUD_300         #define 0x01 = 0x00000001  intuition/preferences.h: *146
BAUD_4800        #define 0x04 = 0x00000004  intuition/preferences.h: *149
BAUD_9600        #define 0x05 = 0x00000005  intuition/preferences.h: *150
BAUD_MIDI        #define 0x07 = 0x00000007  intuition/preferences.h: *152
BBID_DOS         #define { 'D', 'O', 'S', '0' }  devices/bootblock.h: *27
BBID_KICK        #define { 'K', 'I', 'C', 'K' }  devices/bootblock.h: *28
BBNAME_DOS       #define 0x444F5300 = 0x444f5300  devices/bootblock.h: *30
BBNAME_KICK      #define 0x4B49434B = 0x4b49434b  devices/bootblock.h: *31
BC0B_DEST        #define 8 = 0x00000008  hardware/blit.h: *47
BC0B_SRCA        #define 11 = 0x0000000b  hardware/blit.h: *50
BC0B_SRCB        #define 10 = 0x0000000a  hardware/blit.h: *49
BC0B_SRCC        #define 9 = 0x00000009  hardware/blit.h: *48
BC0F_DEST        #define 0x100 = 0x00000100  hardware/blit.h: *51
BC0F_SRCA        #define 0x800 = 0x00000800  hardware/blit.h: *54
BC0F_SRCB        #define 0x400 = 0x00000400  hardware/blit.h: *53
BC0F_SRCC        #define 0x200 = 0x00000200  hardware/blit.h: *52
BC1F_DESC        #define 2 = 0x00000002  hardware/blit.h: *56
BDRAWN           #define 0x0200 = 0x00000200  graphics/gels.h: *39
BEEPING          #define 0x0020 = 0x00000020  intuition/screens.h: *167
BITCLR           #define 0 = 0x00000000  graphics/gfx.h: *20
BITSET           #define 0x8000 = 0x00008000  graphics/gfx.h: *19
BITSPERBYTE      #define 8 = 0x00000008  dos/dos.h: *42
BITSPERLONG      #define 32 = 0x00000020  dos/dos.h: *44
BLITMSG_FAULT    #define 4 = 0x00000004  graphics/gfxbase.h: *100
BLITREVERSE      #define 0x2 = 0x00000002  hardware/blit.h: *74
BLOCKPEN         #define (0x0001) = 0x00000001  intuition/screens.h: *83
BNDRYOFF         macro (1 argument)   graphics/gfxmacros.h: *36
BOBISCOMP        #define 0x0002 = 0x00000002  graphics/gels.h: *36
BOBNIX           #define 0x0800 = 0x00000800  graphics/gels.h: *41
BOBSAWAY         #define 0x0400 = 0x00000400  graphics/gels.h: *40
BOBUPDATE        #define 0x0200 = 0x00000200  graphics/gels.h: *28
BOOL             typedef short  exec/types.h: *66
BOOLEXTEND       #define GACT_BOOLEXTEND = 0x00002000
                 intuition/iobsolete.h: *79
BOOLGADGET       #define GTYP_BOOLGADGET = 0x00000001
                 intuition/iobsolete.h: *104
BOOLMASK         #define 0x0001 = 0x00000001  intuition/intuition.h: *444
BOOTSECTS        #define 2 = 0x00000002  devices/bootblock.h: *25
BORDERHIT        #define 0 = 0x00000000  graphics/collide.h: *23
BORDERLESS       #define WFLG_BORDERLESS = 0x00000800
                 intuition/iobsolete.h: *159
BORDERSNIFF      #define GACT_BORDERSNIFF = 0x00008000
                 intuition/iobsolete.h: *77
BORDER_BLANKING  #define 0x04 = 0x00000004  graphics/view.h: *142
BORDER_NOTRANSPARENCY #define 0x08 = 0x00000008  graphics/view.h: *143
BOTTOMBORDER     #define GACT_BOTTOMBORDER = 0x00000080
                 intuition/iobsolete.h: *76
BOTTOMHIT        #define 2 = 0x00000002  graphics/collide.h: *33
BOUNDED_DIMENSIONS #define 0x0010 = 0x00000010  intuition/preferences.h: *248
BPLCON2_ZDBPEN   #define (1<<11) = 0x00000800  hardware/custom.h: *166
BPLCON2_ZDBPSEL0 #define (1<<12) = 0x00001000  hardware/custom.h: *167
BPLCON2_ZDBPSEL1 #define (1<<13) = 0x00002000  hardware/custom.h: *168
BPLCON2_ZDBPSEL2 #define (1<<14) = 0x00004000  hardware/custom.h: *169
BPLCON2_ZDCTEN   #define (1<<10) = 0x00000400  hardware/custom.h: *165
BPLCON3_BRDNBLNK #define (1<<5) = 0x00000020  hardware/custom.h: *176
BPLCON3_BRDNTRAN #define (1<<4) = 0x00000010  hardware/custom.h: *175
BPLCON3_EXTBLKZD #define (1<<1) = 0x00000002  hardware/custom.h: *173
BPLCON3_EXTBLNKEN #define (1<<0) = 0x00000001  hardware/custom.h: *172
BPLCON3_ZDCLKEN  #define (1<<2) = 0x00000004  hardware/custom.h: *174
BPTR             typedef long  dos/dos.h: *102
BROADCAST_BEAMCON #define ( LOLDIS | CSBLANK ) = 0x00000808
                 graphics/monitor.h: *132
BROADCAST_HBSTOP #define 0x27 = 0x00000027  graphics/monitor.h: *127
BROADCAST_HBSTRT #define 0x01 = 0x00000001  graphics/monitor.h: *124
BROADCAST_HSSTOP #define 0x17 = 0x00000017  graphics/monitor.h: *126
BROADCAST_HSSTRT #define 0x06 = 0x00000006  graphics/monitor.h: *125
BROADCAST_VBSTOP #define 0x1C40 = 0x00001c40  graphics/monitor.h: *131
BROADCAST_VBSTRT #define 0x0000 = 0x00000000  graphics/monitor.h: *128
BROADCAST_VSSTOP #define 0x054C = 0x0000054c  graphics/monitor.h: *130
BROADCAST_VSSTRT #define 0x02A6 = 0x000002a6  graphics/monitor.h: *129
BROTHER_15XL     #define 0x02 = 0x00000002  intuition/preferences.h: *194
BSHIFTSHIFT      #define 12 = 0x0000000c  hardware/blit.h: *64
BSTR             typedef long  dos/dos.h: *103
BUF_FULL         #define 1 = 0x00000001  dos/stdio.h: *28
BUF_LINE         #define 0 = 0x00000000  dos/stdio.h: *27
BUF_NONE         #define 2 = 0x00000002  dos/stdio.h: *29
BUSERFLAGS       #define 0x00FF = 0x000000ff  graphics/gels.h: *34
BUTTONGCLASS     #define "buttongclass"  intuition/classusr.h: *50
BUTTONIDCMP      #define (IDCMP_GADGETUP) = 0x00000040
                 libraries/gadtools.h: *66
BUTTON_KIND      #define 1 = 0x00000001  libraries/gadtools.h: *35
BUserExt         short int in struct Bob +0x001e graphics/gels.h: *162
BUserStuff       #define WORD  graphics/gels.h: *59, 162
BWAITING         #define 0x0100 = 0x00000100  graphics/gels.h: *38
BYTE             char  exec/types.h: *45
BYTEBITS         unsigned char  exec/types.h: *50
BYTEMASK         #define 0xFF = 0x000000ff  exec/types.h: *80
BYTESPERLONG     #define 4 = 0x00000004  dos/dos.h: *43
BackFill         pointer to struct Hook in struct Layer
         +0x0076 graphics/clip.h: *53
BackFill         unsigned char in struct Requester
         +0x001e intuition/intuition.h: *159
BackPen          unsigned char in struct IntuiText
         +0x0001 intuition/intuition.h: *572
BackPen          unsigned char in struct Border
         +0x0005 intuition/intuition.h: *601
BadBlockBlock    structure tag size 0x0200 devices/hardblocks.h: *114
BadBlockEntry    structure tag size 0x0008 devices/hardblocks.h: *109, 121
BarHBorder       char in struct Screen +0x0020 intuition/screens.h: *121
BarHeight        char in struct Screen +0x001e intuition/screens.h: *121
BarLayer         pointer to struct Layer in struct Screen
         +0x014e intuition/screens.h: *145
BarVBorder       char in struct Screen +0x001f intuition/screens.h: *121
BaudRate         unsigned short int in struct Preferences
         +0x0002 intuition/preferences.h: *53
BeamCon0         unsigned short int in struct MonitorSpec
         +0x0028 graphics/monitor.h: *36
BeamSync         short int in struct GfxBase +0x00a2 graphics/gfxbase.h: *42
BeatX            short int in struct Menu +0x001a intuition/intuition.h: *72
BeatY            short int in struct Menu +0x001c intuition/intuition.h: *72
Before           pointer to struct Bob in struct Bob
         +0x000a graphics/gels.h: *153
BgPen            char in struct RastPort +0x001a graphics/rastport.h: *66
BitMap           structure tag size 0x0028 graphics/gfx.h: *48
                 graphics/clip.h: 43, 69
                 graphics/view.h: 110
                 graphics/rastport.h: 59
                 intuition/intuition.h: 171, 1011, 1058
                 intuition/screens.h: 129, 332, 355
                 graphics/scale.h: 26, 27
BitMap           pointer to struct BitMap in struct ClipRect
         +0x000c graphics/clip.h: *69
BitMap           pointer to struct BitMap in struct RasInfo
         +0x0004 graphics/view.h: *110
BitMap           pointer to struct BitMap in struct RastPort
         +0x0004 graphics/rastport.h: *59
BitMap           pointer to struct BitMap in struct NewWindow
         +0x0022 intuition/intuition.h: *1011
BitMap           pointer to struct BitMap in struct ExtNewWindow
         +0x0022 intuition/intuition.h: *1058
BitMap           struct BitMap(size 0x0028 bytes) in struct Screen
         +0x00b8 intuition/screens.h: *129
BitScaleArgs     structure tag size 0x0030 graphics/scale.h: *19
BlitLock         short int in struct GfxBase +0x00aa graphics/gfxbase.h: *47
BlitNest         short int in struct GfxBase +0x00ac graphics/gfxbase.h: *48
BlitOwner        pointer to struct Task in struct GfxBase
         +0x00bc graphics/gfxbase.h: *51
BlitWaitQ        struct List(size 0x000e bytes) in struct GfxBase
         +0x00ae graphics/gfxbase.h: *50
BlockPen         unsigned char in struct Window
         +0x0063 intuition/intuition.h: *859
BlockPen         unsigned char in struct NewWindow
         +0x0009 intuition/intuition.h: *979
BlockPen         unsigned char in struct ExtNewWindow
         +0x0009 intuition/intuition.h: *1049
BlockPen         unsigned char in struct Screen
         +0x014b intuition/screens.h: *137
BlockPen         unsigned char in struct NewScreen
         +0x000b intuition/screens.h: *314
BlockPen         unsigned char in struct ExtNewScreen
         +0x000b intuition/screens.h: *349
BlockPen         unsigned char in struct (no tag)
         +0x0001 intuition/cghooks.h: *54
Blue             unsigned short int in struct ColorSpec
         +0x0006 intuition/intuition.h: *1245
Bob              structure tag
     size 0x0020 graphics/gels.h: *116, 136, 153, 154, 197
BobComp          pointer to struct AnimComp in struct Bob
         +0x0016 graphics/gels.h: *158
BobVSprite       pointer to struct VSprite in struct Bob
         +0x0012 graphics/gels.h: *156
BoolInfo         structure tag size 0x000a intuition/intuition.h: *428
BootBlock        structure tag size 0x000c devices/bootblock.h: *19
BootNode         structure tag size 0x0014 libraries/expansionbase.h: *35
Border           structure tag
     size 0x0010 intuition/intuition.h: *154, 598, 605
BorderBottom     char in struct Window +0x0039 intuition/intuition.h: *832
BorderLeft       char in struct Window +0x0036 intuition/intuition.h: *832
BorderLine       pointer to short int in struct VSprite
         +0x0028 graphics/gels.h: *110
BorderRPort      pointer to struct RastPort in struct Window
         +0x003a intuition/intuition.h: *833
BorderRight      char in struct Window +0x0038 intuition/intuition.h: *832
BorderTop        char in struct Window +0x0037 intuition/intuition.h: *832
BufBuffer        pointer to short int in struct DBufPacket
         +0x0008 graphics/gels.h: *237
BufPath          pointer to struct VSprite in struct DBufPacket
         +0x0004 graphics/gels.h: *233
BufX             short int in struct DBufPacket +0x0002 graphics/gels.h: *232
BufY             short int in struct DBufPacket +0x0000 graphics/gels.h: *232
Buffer           pointer to unsigned char in struct StringInfo
         +0x0000 intuition/intuition.h: *527
BufferPos        short int in struct StringInfo
         +0x0008 intuition/intuition.h: *529
BufferPos        short int in struct SGWork +0x001a intuition/sghooks.h: *44
BytesPerRow      unsigned short int in struct BitMap
         +0x0000 graphics/gfx.h: *50


2.0 IncludeXREF: C

_cliprects       pointer to struct ClipRect in struct Layer
         +0x0040 graphics/clip.h: *50
_CopList         pointer to struct CopList in struct CopList
         +0x0004 graphics/copper.h: *66
cb_ConfigDev     pointer to struct ConfigDev in struct CurrentBinding
         +0x0000 libraries/configvars.h: *59
cb_FileName      pointer to unsigned char in struct CurrentBinding
         +0x0004 libraries/configvars.h: *60
cb_ProductString pointer to unsigned char in struct CurrentBinding
         +0x0008 libraries/configvars.h: *61
cb_ToolTypes     pointer to pointer to unsigned char in struct CurrentBinding
         +0x000c libraries/configvars.h: *62
cbh_CBport       struct MsgPort(size 0x0022 bytes) in struct ClipboardHandle
         +0x0034 libraries/iffparse.h: *118
cbh_Req          struct IOClipReq(size 0x0034 bytes) in struct ClipboardHandle
         +0x0000 libraries/iffparse.h: *117
cbh_SatisfyPort struct MsgPort(size 0x0022 bytes) in struct ClipboardHandle
         +0x0056 libraries/iffparse.h: *119
ccode            pointer to function returning int in struct Isrvstr
         +0x0016 graphics/graphint.h: *25
cd_BoardAddr     pointer to void in struct ConfigDev
         +0x0020 libraries/configvars.h: *37
cd_BoardSize     unsigned long int in struct ConfigDev
         +0x0024 libraries/configvars.h: *38
cd_Driver        pointer to void in struct ConfigDev
         +0x002c libraries/configvars.h: *41
cd_Flags         unsigned char in struct ConfigDev
         +0x000e libraries/configvars.h: *34
cd_NextCD        pointer to struct ConfigDev in struct ConfigDev
         +0x0030 libraries/configvars.h: *42
cd_Node          struct Node(size 0x000e bytes) in struct ConfigDev
         +0x0000 libraries/configvars.h: *33
cd_Pad           unsigned char in struct ConfigDev
         +0x000f libraries/configvars.h: *35
cd_Rom           struct ExpansionRom(size 0x0010 bytes) in struct ConfigDev
         +0x0010 libraries/configvars.h: *36
cd_SlotAddr      unsigned short int in struct ConfigDev
         +0x0028 libraries/configvars.h: *39
cd_SlotSize      unsigned short int in struct ConfigDev
         +0x002a libraries/configvars.h: *40
cd_Unused        array [4] of unsigned long int in struct ConfigDev
         +0x0034 libraries/configvars.h: *43
ceil             #define IEEEDPCeil  libraries/mathffp.h: *37
                 libraries/mathieeedp.h: *37
centphon         pointer to char in struct narrator_rb
         +0x0050 devices/narrator.h: *117
centralize       unsigned char in struct narrator_rb
         +0x004f devices/narrator.h: *116
cfc_ColorTable   pointer to unsigned short int in struct ColorFontColors
         +0x0004 graphics/text.h: *148
cfc_Count        unsigned short int in struct ColorFontColors
         +0x0002 graphics/text.h: *147
cfc_Reserved     unsigned short int in struct ColorFontColors
         +0x0000 graphics/text.h: *146
ch_masks         pointer to unsigned char in struct narrator_rb
         +0x0038 devices/narrator.h: *99
chanmask         unsigned char in struct narrator_rb
         +0x0043 devices/narrator.h: *104
check_lp         pointer to struct Layer in struct Layer_Info
         +0x0004 graphics/layers.h: *37
chm_ChangeCmd    long int in struct ClipHookMsg
         +0x0004 devices/clipboard.h: *67
chm_ClipID       long int in struct ClipHookMsg
         +0x0008 devices/clipboard.h: *69
chm_Type         unsigned long int in struct ClipHookMsg
         +0x0000 devices/clipboard.h: *66
ci_Data          pointer to unsigned char in struct CollectionItem
         +0x0008 libraries/iffparse.h: *108
ci_Next          pointer to struct CollectionItem in struct CollectionItem
         +0x0000 libraries/iffparse.h: *106
ci_Size          long int in struct CollectionItem
         +0x0004 libraries/iffparse.h: *107
cia              pointer to long int in struct GfxBase
         +0x002a graphics/gfxbase.h: *30
ciacra           unsigned char in struct CIA +0x0e00 hardware/cia.h: *60
ciacrb           unsigned char in struct CIA +0x0f00 hardware/cia.h: *62
ciaddra          unsigned char in struct CIA +0x0200 hardware/cia.h: *36
ciaddrb          unsigned char in struct CIA +0x0300 hardware/cia.h: *38
ciaicr           unsigned char in struct CIA +0x0d00 hardware/cia.h: *58
ciapra           unsigned char in struct CIA +0x0000 hardware/cia.h: *32
ciaprb           unsigned char in struct CIA +0x0100 hardware/cia.h: *34
ciasdr           unsigned char in struct CIA +0x0c00 hardware/cia.h: *56
ciatahi          unsigned char in struct CIA +0x0500 hardware/cia.h: *42
ciatalo          unsigned char in struct CIA +0x0400 hardware/cia.h: *40
ciatbhi          unsigned char in struct CIA +0x0700 hardware/cia.h: *46
ciatblo          unsigned char in struct CIA +0x0600 hardware/cia.h: *44
ciatodhi         unsigned char in struct CIA +0x0a00 hardware/cia.h: *52
ciatodlow        unsigned char in struct CIA +0x0800 hardware/cia.h: *48
ciatodmid        unsigned char in struct CIA +0x0900 hardware/cia.h: *50
cl_Dispatcher    struct Hook(size 0x0014 bytes) in struct IClass
         +0x0000 intuition/classes.h: *29
cl_Flags         unsigned long int in struct IClass
         +0x0030 intuition/classes.h: *43
cl_ID            pointer to unsigned char in struct IClass
         +0x001c intuition/classes.h: *32
cl_InstOffset    unsigned short int in struct IClass
         +0x0020 intuition/classes.h: *35
cl_InstSize      unsigned short int in struct IClass
         +0x0022 intuition/classes.h: *36
cl_ObjectCount   unsigned long int in struct IClass
         +0x002c intuition/classes.h: *41
cl_Reserved      unsigned long int in struct IClass
         +0x0014 intuition/classes.h: *30
cl_SubclassCount unsigned long int in struct IClass
         +0x0028 intuition/classes.h: *39
cl_Super         pointer to struct IClass in struct IClass
         +0x0018 intuition/classes.h: *31
cl_UserData      unsigned long int in struct IClass
         +0x0024 intuition/classes.h: *38
cleanup          pointer to function returning int in struct bltnode
         +0x000e hardware/blit.h: *97
cli_Background   long int in struct CommandLineInterface
         +0x002c dos/dosextens.h: *315
cli_CommandDir   long int in struct CommandLineInterface
         +0x0008 dos/dosextens.h: *306
cli_CommandFile long int in struct CommandLineInterface
         +0x0024 dos/dosextens.h: *313
cli_CommandName long int in struct CommandLineInterface
         +0x0010 dos/dosextens.h: *308
cli_CurrentInput long int in struct CommandLineInterface
         +0x0020 dos/dosextens.h: *312
cli_CurrentOutput long int in struct CommandLineInterface
         +0x0030 dos/dosextens.h: *316
cli_DefaultStack long int in struct CommandLineInterface
         +0x0034 dos/dosextens.h: *317
cli_FailLevel    long int in struct CommandLineInterface
         +0x0014 dos/dosextens.h: *309
cli_Interactive long int in struct CommandLineInterface
         +0x0028 dos/dosextens.h: *314
cli_Module       long int in struct CommandLineInterface
         +0x003c dos/dosextens.h: *319
cli_Prompt       long int in struct CommandLineInterface
         +0x0018 dos/dosextens.h: *310
cli_Result2      long int in struct CommandLineInterface
         +0x0000 dos/dosextens.h: *304
cli_ReturnCode   long int in struct CommandLineInterface
         +0x000c dos/dosextens.h: *307
cli_SetName      long int in struct CommandLineInterface
         +0x0004 dos/dosextens.h: *305
cli_StandardInput long int in struct CommandLineInterface
         +0x001c dos/dosextens.h: *311
cli_StandardOutput long int in struct CommandLineInterface
         +0x0038 dos/dosextens.h: *318
clxcon           unsigned short int in struct Custom
         +0x0098 hardware/custom.h: *93
clxdat           unsigned short int in struct Custom
         +0x000e hardware/custom.h: *35
cm_batch_items   pointer to struct TagItem in struct ColorMap
         +0x0020 graphics/view.h: *128
cm_vp            pointer to struct ViewPort in struct ColorMap
         +0x0014 graphics/view.h: *125
cm_vpe           pointer to struct ViewPortExtra in struct ColorMap
         +0x0008 graphics/view.h: *120
cn_ID            long int in struct ContextNode
         +0x0008 libraries/iffparse.h: *71
cn_Node          struct MinNode(size 0x0008 bytes) in struct ContextNode
         +0x0000 libraries/iffparse.h: *70
cn_Scan          long int in struct ContextNode
         +0x0014 libraries/iffparse.h: *74
cn_Size          long int in struct ContextNode
         +0x0010 libraries/iffparse.h: *73
cn_Type          long int in struct ContextNode
         +0x000c libraries/iffparse.h: *72
code             pointer to function returning int in struct Isrvstr
         +0x0012 graphics/graphint.h: *24
collHandler      pointer to struct collTable in struct GelsInfo
         +0x0012 graphics/rastport.h: *51
collPtrs         array [16] of pointer to function returning int in struct
                 collTable
         +0x0000 graphics/gels.h: *260
collTable        structure tag size 0x0040 graphics/rastport.h: *51
                 graphics/gels.h: 258
color            array [32] of unsigned short int in struct Custom
         +0x0180 hardware/custom.h: *122
color0           unsigned short int in struct Preferences
         +0x006e intuition/preferences.h: *70
color1           unsigned short int in struct Preferences
         +0x0070 intuition/preferences.h: *71
color17          unsigned short int in struct Preferences
         +0x0066 intuition/preferences.h: *64
color18          unsigned short int in struct Preferences
         +0x0068 intuition/preferences.h: *65
color19          unsigned short int in struct Preferences
         +0x006a intuition/preferences.h: *66
color2           unsigned short int in struct Preferences
         +0x0072 intuition/preferences.h: *72
color3           unsigned short int in struct Preferences
         +0x0074 intuition/preferences.h: *73
colorByte        array [4] of unsigned char in union colorEntry
         +0x0000 devices/prtgfx.h: *30
colorEntry       union tag
     size 0x0004 devices/prtgfx.h: *28, 40, 41, 42, 43, 44
colorLong        unsigned long int in union colorEntry
         +0x0000 devices/prtgfx.h: *29
colorSByte       array [4] of char in union colorEntry
         +0x0000 devices/prtgfx.h: *31
control_delta_ntsc short int in struct GfxBase +0x017a graphics/gfxbase.h: *84
control_delta_pal short int in struct GfxBase +0x0178 graphics/gfxbase.h: *83
cop1lc           unsigned long int in struct Custom
         +0x0080 hardware/custom.h: *83
cop2lc           unsigned long int in struct Custom
         +0x0084 hardware/custom.h: *84
copcon           unsigned short int in struct Custom
         +0x002e hardware/custom.h: *50
copinit          structure tag size 0x0078 graphics/copper.h: *92
                 graphics/gfxbase.h: 29
copinit          pointer to struct copinit in struct GfxBase
         +0x0026 graphics/gfxbase.h: *29
copins           unsigned short int in struct Custom
         +0x008c hardware/custom.h: *87
copjmp1          unsigned short int in struct Custom
         +0x0088 hardware/custom.h: *85
copjmp2          unsigned short int in struct Custom
         +0x008a hardware/custom.h: *86
cos              #define IEEEDPCos  libraries/mathffp.h: *41
                 libraries/mathieeedp.h: *41
cosh             #define IEEEDPCosh  libraries/mathffp.h: *52
                 libraries/mathieeedp.h: *52
cp_x             short int in struct RastPort +0x0024 graphics/rastport.h: *74
cp_y             short int in struct RastPort +0x0026 graphics/rastport.h: *74
cpl_Array        pointer to pointer to struct MsgPort in struct CliProcList
         +0x000c dos/dosextens.h: *267
cpl_First        long int in struct CliProcList +0x0008 dos/dosextens.h: *266
cpl_Node         struct MinNode(size 0x0008 bytes) in struct CliProcList
         +0x0000 dos/dosextens.h: *265
cprlist          structure tag size 0x000a graphics/copper.h: *56, 58
                 graphics/view.h: 61, 62
cr               pointer to struct ClipRect in struct Layer
         +0x0030 graphics/clip.h: *48
cr2              pointer to struct ClipRect in struct Layer
         +0x0034 graphics/clip.h: *48
crb_reserved     array [5] of unsigned char in struct GfxBase
         +0x00ed graphics/gfxbase.h: *68
crnew            pointer to struct ClipRect in struct Layer
         +0x0038 graphics/clip.h: *48
ctf_CharData     array [8] of pointer to void in struct ColorTextFont
         +0x0040 graphics/text.h: *162
ctf_ColorFontColors pointer to struct ColorFontColors in struct ColorTextFont
         +0x003c graphics/text.h: *161
ctf_Depth        unsigned char in struct ColorTextFont
         +0x0036 graphics/text.h: *155
ctf_FgColor      unsigned char in struct ColorTextFont
         +0x0037 graphics/text.h: *156
ctf_Flags        unsigned short int in struct ColorTextFont
         +0x0034 graphics/text.h: *154
ctf_High         unsigned char in struct ColorTextFont
         +0x0039 graphics/text.h: *158
ctf_Low          unsigned char in struct ColorTextFont
         +0x0038 graphics/text.h: *157
ctf_PlaneOnOff   unsigned char in struct ColorTextFont
         +0x003b graphics/text.h: *160
ctf_PlanePick    unsigned char in struct ColorTextFont
         +0x003a graphics/text.h: *159
ctf_TF           struct TextFont(size 0x0034 bytes) in struct ColorTextFont
         +0x0000 graphics/text.h: *153
ctl              unsigned short int in struct SpriteDef
         +0x0002 hardware/custom.h: *118
cu_AOLPen        char in struct ConUnit +0x0105 devices/conunit.h: *84
cu_AlgoStyle     unsigned char in struct ConUnit +0x0118 devices/conunit.h: *90
cu_BgPen         char in struct ConUnit +0x0104 devices/conunit.h: *83
cu_DrawMode      char in struct ConUnit +0x0106 devices/conunit.h: *85
cu_FgPen         char in struct ConUnit +0x0103 devices/conunit.h: *82
cu_Font          pointer to struct TextFont in struct ConUnit
         +0x0114 devices/conunit.h: *89
cu_KeyMapStruct struct KeyMap(size 0x0020 bytes) in struct ConUnit
         +0x0042 devices/conunit.h: *76
cu_MP            struct MsgPort(size 0x0022 bytes) in struct ConUnit
         +0x0000 devices/conunit.h: *56
cu_Mask          char in struct ConUnit +0x0102 devices/conunit.h: *81
cu_Minterms      array [8] of unsigned char in struct ConUnit
         +0x010c devices/conunit.h: *88
cu_Modes         array [3] of unsigned char in struct ConUnit
         +0x0122 devices/conunit.h: *98
cu_Node          struct Node(size 0x000e bytes) in struct ClipboardUnitPartial
         +0x0000 devices/clipboard.h: *37
cu_Obsolete1     char in struct ConUnit +0x0107 devices/conunit.h: *86
cu_Obsolete2     pointer to void in struct ConUnit
         +0x0108 devices/conunit.h: *87
cu_RawEvents     array [3] of unsigned char in struct ConUnit
         +0x0125 devices/conunit.h: *99
cu_TabStops      array [80] of unsigned short int in struct ConUnit
         +0x0062 devices/conunit.h: *78
cu_TxBaseline    unsigned short int in struct ConUnit
         +0x011e devices/conunit.h: *94
cu_TxFlags       unsigned char in struct ConUnit +0x0119 devices/conunit.h: *91
cu_TxHeight      unsigned short int in struct ConUnit
         +0x011a devices/conunit.h: *92
cu_TxSpacing     short int in struct ConUnit +0x0120 devices/conunit.h: *95
cu_TxWidth       unsigned short int in struct ConUnit
         +0x011c devices/conunit.h: *93
cu_UnitNum       unsigned long int in struct ClipboardUnitPartial
         +0x000e devices/clipboard.h: *38
cu_Window        pointer to struct Window in struct ConUnit
         +0x0022 devices/conunit.h: *58
cu_XCCP          short int in struct ConUnit +0x003e devices/conunit.h: *71
cu_XCP           short int in struct ConUnit +0x0026 devices/conunit.h: *59
cu_XMax          short int in struct ConUnit +0x002a devices/conunit.h: *61
cu_XMinShrink    short int in struct ConUnit +0x003a devices/conunit.h: *69
cu_XRExtant      short int in struct ConUnit +0x0036 devices/conunit.h: *67
cu_XROrigin      short int in struct ConUnit +0x0032 devices/conunit.h: *65
cu_XRSize        short int in struct ConUnit +0x002e devices/conunit.h: *63
cu_YCCP          short int in struct ConUnit +0x0040 devices/conunit.h: *72
cu_YCP           short int in struct ConUnit +0x0028 devices/conunit.h: *60
cu_YMax          short int in struct ConUnit +0x002c devices/conunit.h: *62
cu_YMinShrink    short int in struct ConUnit +0x003c devices/conunit.h: *70
cu_YRExtant      short int in struct ConUnit +0x0038 devices/conunit.h: *68
cu_YROrigin      short int in struct ConUnit +0x0034 devices/conunit.h: *66
cu_YRSize        short int in struct ConUnit +0x0030 devices/conunit.h: *64
current_monitor pointer to struct MonitorSpec in struct GfxBase
         +0x017c graphics/gfxbase.h: *85
current_tot_cclks unsigned short int in struct GfxBase
         +0x0160 graphics/gfxbase.h: *78
current_tot_rows unsigned short int in struct GfxBase
         +0x015e graphics/gfxbase.h: *77
CACRF_ClearD     #define (1L<<11) = 0x00000800  exec/execbase.h: *179
CACRF_ClearI     #define (1L<<3) = 0x00000008  exec/execbase.h: *175
CACRF_CopyBack   #define (1L<<31) = 0x80000000  exec/execbase.h: *183
CACRF_DBE        #define (1L<<12) = 0x00001000  exec/execbase.h: *180
CACRF_EnableD    #define (1L<<8) = 0x00000100  exec/execbase.h: *177
CACRF_EnableI    #define (1L<<0) = 0x00000001  exec/execbase.h: *173
CACRF_FreezeD    #define (1L<<9) = 0x00000200  exec/execbase.h: *178
CACRF_FreezeI    #define (1L<<1) = 0x00000002  exec/execbase.h: *174
CACRF_IBE        #define (1L<<4) = 0x00000010  exec/execbase.h: *176
CACRF_WriteAllocate #define (1L<<13) = 0x00002000  exec/execbase.h: *182
CBD_CHANGEHOOK   #define (CMD_NONSTD+3) = 0x0000000c  devices/clipboard.h: *31
CBD_CURRENTREADID #define (CMD_NONSTD+1) = 0x0000000a
                 devices/clipboard.h: *29
CBD_CURRENTWRITEID #define (CMD_NONSTD+2) = 0x0000000b
                 devices/clipboard.h: *30
CBD_DESCRLEN     #define 40 = 0x00000028  libraries/commodities.h: *38
CBD_NAMELEN      #define 24 = 0x00000018  libraries/commodities.h: *36
CBD_POST         #define (CMD_NONSTD+0) = 0x00000009  devices/clipboard.h: *28
CBD_TITLELEN     #define 40 = 0x00000028  libraries/commodities.h: *37
CBERR_DUP        #define 2 = 0x00000002  libraries/commodities.h: *43
CBERR_OBSOLETEID #define 1 = 0x00000001  devices/clipboard.h: *33
CBERR_OK         #define 0 = 0x00000000  libraries/commodities.h: *41
CBERR_SYSERR     #define 1 = 0x00000001  libraries/commodities.h: *42
CBERR_VERSION    #define 3 = 0x00000003  libraries/commodities.h: *44
CBM_MPS1000      #define 0x03 = 0x00000003  intuition/preferences.h: *195
CDB_BADMEMORY    #define 2 = 0x00000002  libraries/configvars.h: *49
CDB_CONFIGME     #define 1 = 0x00000001  libraries/configvars.h: *48
CDB_SHUTUP       #define 0 = 0x00000000  libraries/configvars.h: *47
CDF_BADMEMORY    #define 0x04 = 0x00000004  libraries/configvars.h: *53
CDF_CONFIGME     #define 0x02 = 0x00000002  libraries/configvars.h: *52
CDF_SHUTUP       #define 0x01 = 0x00000001  libraries/configvars.h: *51
CD_ASKDEFAULTKEYMAP #define (CMD_NONSTD+2) = 0x0000000b
                 devices/console.h: *26
CD_ASKKEYMAP     #define (CMD_NONSTD+0) = 0x00000009  devices/console.h: *24
CD_SETDEFAULTKEYMAP #define (CMD_NONSTD+3) = 0x0000000c
                 devices/console.h: *27
CD_SETKEYMAP     #define (CMD_NONSTD+1) = 0x0000000a  devices/console.h: *25
CEND             macro (1 argument)   graphics/gfxmacros.h: *41
CENTER_IMAGE     #define 0x0008 = 0x00000008  intuition/preferences.h: *245
CHANGEWINDOW     #define IDCMP_CHANGEWINDOW = 0x02000000
                 intuition/iobsolete.h: *139
CHANGE_FH        #define 1 = 0x00000001  dos/dos.h: *223
CHANGE_LOCK      #define 0 = 0x00000000  dos/dos.h: *222
CHECKBOXIDCMP    #define (IDCMP_GADGETUP) = 0x00000040
                 libraries/gadtools.h: *67
CHECKBOX_KIND    #define 2 = 0x00000002  libraries/gadtools.h: *36
CHECKED          #define 0x0100 = 0x00000100  intuition/intuition.h: *132
CHECKIMAGE       #define (0x0EL) = 0x0000000e  intuition/imageclass.h: *110
CHECKIT          #define 0x0001 = 0x00000001  intuition/intuition.h: *118
CHECKWIDTH       #define 19 = 0x00000013  intuition/intuition.h: *1300
CHeight          unsigned short int in struct PropInfo
         +0x000c intuition/intuition.h: *489
CIA              structure tag size 0x0f01 hardware/cia.h: *31
CIAANAME         #define "ciaa.resource"  resources/cia.h: *15
CIABNAME         #define "ciab.resource"  resources/cia.h: *16
CIAB_COMCD       #define (5) = 0x00000005  hardware/cia.h: *149
CIAB_COMCTS      #define (4) = 0x00000004  hardware/cia.h: *150
CIAB_COMDSR      #define (3) = 0x00000003  hardware/cia.h: *151
CIAB_COMDTR      #define (7) = 0x00000007  hardware/cia.h: *147
CIAB_COMRTS      #define (6) = 0x00000006  hardware/cia.h: *148
CIAB_DSKCHANGE   #define (2) = 0x00000002  hardware/cia.h: *140
CIAB_DSKDIREC    #define (1) = 0x00000001  hardware/cia.h: *163
CIAB_DSKMOTOR    #define (7) = 0x00000007  hardware/cia.h: *157
CIAB_DSKPROT     #define (3) = 0x00000003  hardware/cia.h: *139
CIAB_DSKRDY      #define (5) = 0x00000005  hardware/cia.h: *137
CIAB_DSKSEL0     #define (3) = 0x00000003  hardware/cia.h: *161
CIAB_DSKSEL1     #define (4) = 0x00000004  hardware/cia.h: *160
CIAB_DSKSEL2     #define (5) = 0x00000005  hardware/cia.h: *159
CIAB_DSKSEL3     #define (6) = 0x00000006  hardware/cia.h: *158
CIAB_DSKSIDE     #define (2) = 0x00000002  hardware/cia.h: *162
CIAB_DSKSTEP     #define (0) = 0x00000000  hardware/cia.h: *164
CIAB_DSKTRACK0   #define (4) = 0x00000004  hardware/cia.h: *138
CIAB_GAMEPORT0   #define (6) = 0x00000006  hardware/cia.h: *136
CIAB_GAMEPORT1   #define (7) = 0x00000007  hardware/cia.h: *135
CIAB_LED         #define (1) = 0x00000001  hardware/cia.h: *141
CIAB_OVERLAY     #define (0) = 0x00000000  hardware/cia.h: *142
CIAB_PRTRBUSY    #define (0) = 0x00000000  hardware/cia.h: *154
CIAB_PRTRPOUT    #define (1) = 0x00000001  hardware/cia.h: *153
CIAB_PRTRSEL     #define (2) = 0x00000002  hardware/cia.h: *152
CIACRAB_INMODE   #define 5 = 0x00000005  hardware/cia.h: *81
CIACRAB_LOAD     #define 4 = 0x00000004  hardware/cia.h: *80
CIACRAB_OUTMODE  #define 2 = 0x00000002  hardware/cia.h: *78
CIACRAB_PBON     #define 1 = 0x00000001  hardware/cia.h: *77
CIACRAB_RUNMODE  #define 3 = 0x00000003  hardware/cia.h: *79
CIACRAB_SPMODE   #define 6 = 0x00000006  hardware/cia.h: *82
CIACRAB_START    #define 0 = 0x00000000  hardware/cia.h: *76
CIACRAB_TODIN    #define 7 = 0x00000007  hardware/cia.h: *83
CIACRAF_INMODE   #define (1<<CIACRAB_INMODE) = 0x00000020
                 hardware/cia.h: *110
CIACRAF_LOAD     #define (1<<CIACRAB_LOAD) = 0x00000010  hardware/cia.h: *109
CIACRAF_OUTMODE  #define (1<<CIACRAB_OUTMODE) = 0x00000004
                 hardware/cia.h: *107
CIACRAF_PBON     #define (1<<CIACRAB_PBON) = 0x00000002  hardware/cia.h: *106
CIACRAF_RUNMODE  #define (1<<CIACRAB_RUNMODE) = 0x00000008
                 hardware/cia.h: *108
CIACRAF_SPMODE   #define (1<<CIACRAB_SPMODE) = 0x00000040
                 hardware/cia.h: *111
CIACRAF_START    #define (1<<CIACRAB_START) = 0x00000001  hardware/cia.h: *105
CIACRAF_TODIN    #define (1<<CIACRAB_TODIN) = 0x00000080  hardware/cia.h: *112
CIACRBB_ALARM    #define 7 = 0x00000007  hardware/cia.h: *93
CIACRBB_INMODE0  #define 5 = 0x00000005  hardware/cia.h: *91
CIACRBB_INMODE1  #define 6 = 0x00000006  hardware/cia.h: *92
CIACRBB_LOAD     #define 4 = 0x00000004  hardware/cia.h: *90
CIACRBB_OUTMODE  #define 2 = 0x00000002  hardware/cia.h: *88
CIACRBB_PBON     #define 1 = 0x00000001  hardware/cia.h: *87
CIACRBB_RUNMODE  #define 3 = 0x00000003  hardware/cia.h: *89
CIACRBB_START    #define 0 = 0x00000000  hardware/cia.h: *86
CIACRBF_ALARM    #define (1<<CIACRBB_ALARM) = 0x00000080  hardware/cia.h: *122
CIACRBF_INMODE0  #define (1<<CIACRBB_INMODE0) = 0x00000020
                 hardware/cia.h: *120
CIACRBF_INMODE1  #define (1<<CIACRBB_INMODE1) = 0x00000040
                 hardware/cia.h: *121
CIACRBF_IN_CNT   #define (CIACRBF_INMODE0) = 0x00000020  hardware/cia.h: *126
CIACRBF_IN_CNT_TA #define (CIACRBF_INMODE0|CIACRBF_INMODE1) = 0x00000060
                 hardware/cia.h: *128
CIACRBF_IN_PHI2  #define 0 = 0x00000000  hardware/cia.h: *125
CIACRBF_IN_TA    #define (CIACRBF_INMODE1) = 0x00000040  hardware/cia.h: *127
CIACRBF_LOAD     #define (1<<CIACRBB_LOAD) = 0x00000010  hardware/cia.h: *119
CIACRBF_OUTMODE  #define (1<<CIACRBB_OUTMODE) = 0x00000004
                 hardware/cia.h: *117
CIACRBF_PBON     #define (1<<CIACRBB_PBON) = 0x00000002  hardware/cia.h: *116
CIACRBF_RUNMODE  #define (1<<CIACRBB_RUNMODE) = 0x00000008
                 hardware/cia.h: *118
CIACRBF_START    #define (1<<CIACRBB_START) = 0x00000001  hardware/cia.h: *115
CIAF_COMCD       #define (1<<5) = 0x00000020  hardware/cia.h: *181
CIAF_COMCTS      #define (1<<4) = 0x00000010  hardware/cia.h: *182
CIAF_COMDSR      #define (1<<3) = 0x00000008  hardware/cia.h: *183
CIAF_COMDTR      #define (1<<7) = 0x00000080  hardware/cia.h: *179
CIAF_COMRTS      #define (1<<6) = 0x00000040  hardware/cia.h: *180
CIAF_DSKCHANGE   #define (1<<2) = 0x00000004  hardware/cia.h: *172
CIAF_DSKDIREC    #define (1<<1) = 0x00000002  hardware/cia.h: *195
CIAF_DSKMOTOR    #define (1<<7) = 0x00000080  hardware/cia.h: *189
CIAF_DSKPROT     #define (1<<3) = 0x00000008  hardware/cia.h: *171
CIAF_DSKRDY      #define (1<<5) = 0x00000020  hardware/cia.h: *169
CIAF_DSKSEL0     #define (1<<3) = 0x00000008  hardware/cia.h: *193
CIAF_DSKSEL1     #define (1<<4) = 0x00000010  hardware/cia.h: *192
CIAF_DSKSEL2     #define (1<<5) = 0x00000020  hardware/cia.h: *191
CIAF_DSKSEL3     #define (1<<6) = 0x00000040  hardware/cia.h: *190
CIAF_DSKSIDE     #define (1<<2) = 0x00000004  hardware/cia.h: *194
CIAF_DSKSTEP     #define (1<<0) = 0x00000001  hardware/cia.h: *196
CIAF_DSKTRACK0   #define (1<<4) = 0x00000010  hardware/cia.h: *170
CIAF_GAMEPORT0   #define (1<<6) = 0x00000040  hardware/cia.h: *168
CIAF_GAMEPORT1   #define (1<<7) = 0x00000080  hardware/cia.h: *167
CIAF_LED         #define (1<<1) = 0x00000002  hardware/cia.h: *173
CIAF_OVERLAY     #define (1<<0) = 0x00000001  hardware/cia.h: *174
CIAF_PRTRBUSY    #define (1<<0) = 0x00000001  hardware/cia.h: *186
CIAF_PRTRPOUT    #define (1<<1) = 0x00000002  hardware/cia.h: *185
CIAF_PRTRSEL     #define (1<<2) = 0x00000004  hardware/cia.h: *184
CIAICRB_ALRM     #define 2 = 0x00000002  hardware/cia.h: *69
CIAICRB_FLG      #define 4 = 0x00000004  hardware/cia.h: *71
CIAICRB_IR       #define 7 = 0x00000007  hardware/cia.h: *72
CIAICRB_SETCLR   #define 7 = 0x00000007  hardware/cia.h: *73
CIAICRB_SP       #define 3 = 0x00000003  hardware/cia.h: *70
CIAICRB_TA       #define 0 = 0x00000000  hardware/cia.h: *67
CIAICRB_TB       #define 1 = 0x00000001  hardware/cia.h: *68
CIAICRF_ALRM     #define (1<<CIAICRB_ALRM) = 0x00000004  hardware/cia.h: *98
CIAICRF_FLG      #define (1<<CIAICRB_FLG) = 0x00000010  hardware/cia.h: *100
CIAICRF_IR       #define (1<<CIAICRB_IR) = 0x00000080  hardware/cia.h: *101
CIAICRF_SETCLR   #define (1<<CIAICRB_SETCLR) = 0x00000080
                 hardware/cia.h: *102
CIAICRF_SP       #define (1<<CIAICRB_SP) = 0x00000008  hardware/cia.h: *99
CIAICRF_TA       #define (1<<CIAICRB_TA) = 0x00000001  hardware/cia.h: *96
CIAICRF_TB       #define (1<<CIAICRB_TB) = 0x00000002  hardware/cia.h: *97
CINIT            macro (2 arguments)   graphics/gfxmacros.h: *38
CLEANME          #define CLEANUP = 0x00000040  hardware/blit.h: *102
CLEANUP          #define 0x40 = 0x00000040  hardware/blit.h: *101
CLF_INLIST       #define 0x00000001 = 0x00000001  intuition/classes.h: *44
CLIB_MACROS_H    #define  clib/macros.h: *2
CLOSE            #define GTYP_CLOSE = 0x00000080  intuition/iobsolete.h: *103
CLOSEGADGET      #define 3 = 0x00000003  intuition/intuitionbase.h: *50
CLOSEIMAGE       #define (0x03L) = 0x00000003  intuition/imageclass.h: *104
CLOSEWINDOW      #define IDCMP_CLOSEWINDOW = 0x00000200
                 intuition/iobsolete.h: *123
CLVALUE          macro (1 argument)   rexx/rexxio.h: *58
CLeft            short int in struct StringInfo
         +0x0014 intuition/intuition.h: *537
CMDE_NOBROKER    #define (-1) = 0xffffffff  libraries/commodities.h: *137
CMDE_NOMEM       #define (-3) = 0xfffffffd  libraries/commodities.h: *139
CMDE_NOPORT      #define (-2) = 0xfffffffe  libraries/commodities.h: *138
CMDE_OK          #define (0) = 0x00000000  libraries/commodities.h: *136
CMD_CLEAR        #define 5 = 0x00000005  exec/io.h: *56
CMD_DISABLED     #define -999 = 0xfffffc19  dos/dosextens.h: *297
CMD_FLUSH        #define 8 = 0x00000008  exec/io.h: *59
CMD_INTERNAL     #define -2 = 0xfffffffe  dos/dosextens.h: *296
CMD_INVALID      #define 0 = 0x00000000  exec/io.h: *51
CMD_NONSTD       #define 9 = 0x00000009  exec/io.h: *61
CMD_READ         #define 2 = 0x00000002  exec/io.h: *53
CMD_RESET        #define 1 = 0x00000001  exec/io.h: *52
CMD_START        #define 7 = 0x00000007  exec/io.h: *58
CMD_STOP         #define 6 = 0x00000006  exec/io.h: *57
CMD_SYSTEM       #define -1 = 0xffffffff  dos/dosextens.h: *295
CMD_UPDATE       #define 4 = 0x00000004  exec/io.h: *55
CMD_WRITE        #define 3 = 0x00000003  exec/io.h: *54
CMOVE            macro (3 arguments)   graphics/gfxmacros.h: *39
COERR_BADFILTER  #define 4 = 0x00000004  libraries/commodities.h: *163
COERR_BADTYPE    #define 8 = 0x00000008  libraries/commodities.h: *164
COERR_ISNULL     #define 1 = 0x00000001  libraries/commodities.h: *161
COERR_NULLATTACH #define 2 = 0x00000002  libraries/commodities.h: *162
COF_SHOW_HIDE    #define 4 = 0x00000004  libraries/commodities.h: *67
COLORMAP_TRANSPARENCY #define 0x01 = 0x00000001  graphics/view.h: *140
COLORMAP_TYPE_V1_2 #define 0x00 = 0x00000000  graphics/view.h: *135
COLORMAP_TYPE_V1_4 #define 0x01 = 0x00000001  graphics/view.h: *136
COLORMAP_TYPE_V36 #define COLORMAP_TYPE_V1_4 = 0x00000001
                 graphics/view.h: *137
COLORON          #define 0x0200 = 0x00000200  graphics/display.h: *21
COLORPLANE_TRANSPARENCY #define 0x02 = 0x00000002  graphics/view.h: *141
COMMSEQ          #define 0x0004 = 0x00000004  intuition/intuition.h: *120
COMMWIDTH        #define 27 = 0x0000001b  intuition/intuition.h: *1301
COMPLEMENT       #define 2 = 0x00000002  graphics/rastport.h: *96
COMPLEX_BIT      #define 1 = 0x00000001  dos/dosasl.h: *139
CONFLAG_DEFAULT  #define 0 = 0x00000000  devices/conunit.h: *46
CONFLAG_NODRAW_ON_NEWSIZE #define 1 = 0x00000001  devices/conunit.h: *47
CONU_CHARMAP     #define 1 = 0x00000001  devices/conunit.h: *41
CONU_LIBRARY     #define -1 = 0xffffffff  devices/conunit.h: *36
CONU_SNIPMAP     #define 3 = 0x00000003  devices/conunit.h: *42
CONU_STANDARD    #define 0 = 0x00000000  devices/conunit.h: *37
COPPER_MOVE      #define 0 = 0x00000000  graphics/copper.h: *19
COPPER_WAIT      #define 1 = 0x00000001  graphics/copper.h: *20
CORRECT_BLUE     #define 0x0004 = 0x00000004  intuition/preferences.h: *243
CORRECT_GREEN    #define 0x0002 = 0x00000002  intuition/preferences.h: *242
CORRECT_RED      #define 0x0001 = 0x00000001  intuition/preferences.h: *241
CORRECT_RGB_MASK #define (CORRECT_RED|CORRECT_GREEN|CORRECT_BLUE) = 0x00000007
                 intuition/preferences.h: *264
COUNT            short int  exec/types.h: *58
CPRNXTBUF        #define 2 = 0x00000002  graphics/copper.h: *21
CPR_NT_LOF       #define 0x8000 = 0x00008000  graphics/copper.h: *22
CPR_NT_SHT       #define 0x4000 = 0x00004000  graphics/copper.h: *23
CPR_NT_SYS       #define 0x2000 = 0x00002000  graphics/copper.h: *24
CPTR             typedef ULONG  exec/types.h: *60
CR_NEEDS_NO_CONCEALED_RASTERS #define 1 = 0x00000001  graphics/clip.h: *79
CR_NEEDS_NO_LAYERBLIT_DAMAGE #define 2 = 0x00000002  graphics/clip.h: *80
CSBLANK          #define 0x0008 = 0x00000008  hardware/custom.h: *156
CSCBLANKEN       #define 0x0400 = 0x00000400  hardware/custom.h: *149
CSYNCTRUE        #define 0x0004 = 0x00000004  hardware/custom.h: *157
CS_Buffer        pointer to unsigned char in struct CSource
         +0x0000 dos/rdargs.h: *64
CS_CurChr        long int in struct CSource +0x0008 dos/rdargs.h: *66
CS_Length        long int in struct CSource +0x0004 dos/rdargs.h: *65
CSource          structure tag size 0x000c dos/rdargs.h: *63, 98
CTB_ALPHA        #define 2 = 0x00000002  rexx/rxslib.h: *91
CTB_DIGIT        #define 1 = 0x00000001  rexx/rxslib.h: *90
CTB_LOWER        #define 7 = 0x00000007  rexx/rxslib.h: *96
CTB_MAPCOLOR     #define 0 = 0x00000000  graphics/text.h: *141
CTB_REXXOPR      #define 4 = 0x00000004  rexx/rxslib.h: *93
CTB_REXXSPC      #define 5 = 0x00000005  rexx/rxslib.h: *94
CTB_REXXSYM      #define 3 = 0x00000003  rexx/rxslib.h: *92
CTB_SPACE        #define 0 = 0x00000000  rexx/rxslib.h: *89
CTB_UPPER        #define 6 = 0x00000006  rexx/rxslib.h: *95
CTC_HCLRTAB      #define 2 = 0x00000002  devices/console.h: *90
CTC_HCLRTABSALL  #define 5 = 0x00000005  devices/console.h: *91
CTC_HSETTAB      #define 0 = 0x00000000  devices/console.h: *89
CTF_ALPHA        #define (1 << CTB_ALPHA) = 0x00000004  rexx/rxslib.h: *101
CTF_DIGIT        #define (1 << CTB_DIGIT) = 0x00000002  rexx/rxslib.h: *100
CTF_LOWER        #define (1 << CTB_LOWER) = 0x00000080  rexx/rxslib.h: *106
CTF_MAPCOLOR     #define 0x0001 = 0x00000001  graphics/text.h: *142
CTF_REXXOPR      #define (1 << CTB_REXXOPR) = 0x00000010  rexx/rxslib.h: *103
CTF_REXXSPC      #define (1 << CTB_REXXSPC) = 0x00000020  rexx/rxslib.h: *104
CTF_REXXSYM      #define (1 << CTB_REXXSYM) = 0x00000008  rexx/rxslib.h: *102
CTF_SPACE        #define (1 << CTB_SPACE) = 0x00000001  rexx/rxslib.h: *99
CTF_UPPER        #define (1 << CTB_UPPER) = 0x00000040  rexx/rxslib.h: *105
CT_ANTIALIAS     #define 0x0004 = 0x00000004  graphics/text.h: *139
CT_COLORFONT     #define 0x0001 = 0x00000001  graphics/text.h: *136
CT_COLORMASK     #define 0x000F = 0x0000000f  graphics/text.h: *135
CT_GREYFONT      #define 0x0002 = 0x00000002  graphics/text.h: *137
CTop             short int in struct StringInfo
         +0x0016 intuition/intuition.h: *537
CURSORDOWN       #define 0x4D = 0x0000004d  intuition/intuition.h: *1345
CURSORLEFT       #define 0x4F = 0x0000004f  intuition/intuition.h: *1343
CURSORRIGHT      #define 0x4E = 0x0000004e  intuition/intuition.h: *1344
CURSORUP         #define 0x4C = 0x0000004c  intuition/intuition.h: *1342
CUSTOM           #define 0x40 = 0x00000040  intuition/preferences.h: *189
CUSTOMBITMAP     #define 0x0040 = 0x00000040  intuition/screens.h: *169
CUSTOMGADGET     #define GTYP_CUSTOMGADGET = 0x00000005
                 intuition/iobsolete.h: *108
CUSTOMIMAGEDEPTH #define (-1) = 0xffffffff  intuition/imageclass.h: *24
CUSTOMSCREEN     #define 0x000F = 0x0000000f  intuition/screens.h: *163
CUSTOM_HOOK      macro (1 argument)   intuition/cghooks.h: *79
CUSTOM_NAME      #define 0x00 = 0x00000000  intuition/preferences.h: *192
CWAIT            macro (3 arguments)   graphics/gfxmacros.h: *40
CWidth           unsigned short int in struct PropInfo
         +0x000a intuition/intuition.h: *488
CXCMD_APPEAR     #define (19) = 0x00000013  libraries/commodities.h: *126
CXCMD_DISABLE    #define (15) = 0x0000000f  libraries/commodities.h: *124
CXCMD_DISAPPEAR  #define (21) = 0x00000015  libraries/commodities.h: *127
CXCMD_ENABLE     #define (17) = 0x00000011  libraries/commodities.h: *125
CXCMD_KILL       #define (23) = 0x00000017  libraries/commodities.h: *128
CXCMD_LIST_CHG   #define (27) = 0x0000001b  libraries/commodities.h: *132
CXCMD_UNIQUE     #define (25) = 0x00000019  libraries/commodities.h: *131
CXM_COMMAND      #define (1 << 6) = 0x00000040  libraries/commodities.h: *121
CXM_IEVENT       #define (1 << 5) = 0x00000020  libraries/commodities.h: *113
CXM_UNIQUE       #define (1 << 4) = 0x00000010  libraries/commodities.h: *99
CX_BROKER        #define 6 = 0x00000006  libraries/commodities.h: *91
CX_CUSTOM        #define 8 = 0x00000008  libraries/commodities.h: *93
CX_DEBUG         #define 7 = 0x00000007  libraries/commodities.h: *92
CX_FILTER        #define 1 = 0x00000001  libraries/commodities.h: *86
CX_INVALID       #define 0 = 0x00000000  libraries/commodities.h: *85
CX_SEND          #define 3 = 0x00000003  libraries/commodities.h: *88
CX_SIGNAL        #define 4 = 0x00000004  libraries/commodities.h: *89
CX_TRANSLATE     #define 5 = 0x00000005  libraries/commodities.h: *90
CX_TYPEFILTER    #define 2 = 0x00000002  libraries/commodities.h: *87
CX_ZERO          #define 9 = 0x00000009  libraries/commodities.h: *94
CYCLEIDCMP       #define (IDCMP_GADGETUP) = 0x00000040
                 libraries/gadtools.h: *74
CYCLE_KIND       #define 7 = 0x00000007  libraries/gadtools.h: *41
Carg             int in struct Isrvstr +0x001a graphics/graphint.h: *26
CheckMark        pointer to struct Image in struct Window
         +0x0064 intuition/intuition.h: *865
CheckMark        pointer to struct Image in struct NewWindow
         +0x0016 intuition/intuition.h: *996
CheckMark        pointer to struct Image in struct ExtNewWindow
         +0x0016 intuition/intuition.h: *1054
ChipRevBits0     unsigned char in struct GfxBase
         +0x00ec graphics/gfxbase.h: *67
ChkBase          unsigned long int in struct ExecBase
         +0x0026 exec/execbase.h: *43
ChkSum           unsigned short int in struct ExecBase
         +0x0052 exec/execbase.h: *55
Class            unsigned long int in struct IntuiMessage
         +0x0014 intuition/intuition.h: *684
Class            "UBYTE"  intuition/classes.h: *45
ClassID          pointer to "UBYTE"  intuition/classusr.h: *23
                 intuition/classes.h: 32
ClearPath        pointer to struct VSprite in struct VSprite
         +0x000c graphics/gels.h: *82
CliProcList      structure tag size 0x0010 dos/dosextens.h: *264
ClipHookMsg      structure tag size 0x000c devices/clipboard.h: *65
ClipRect         structure tag
     size 0x0024 graphics/clip.h: *37, 44, 48, 49, 50, 64, 66, 67,
                             71
                 graphics/layers.h: 38
ClipRect         pointer to struct ClipRect in struct Layer
         +0x0008 graphics/clip.h: *37
ClipRegion       pointer to struct Region in struct Layer
         +0x007e graphics/clip.h: *55
ClipboardHandle structure tag size 0x0078 libraries/iffparse.h: *116
ClipboardUnitPartial structure tag size 0x0012 devices/clipboard.h: *36, 46
Clock            long int in struct AnimOb +0x0008 graphics/gels.h: *206
ClockData        structure tag size 0x000e utility/date.h: *18
ClrIns           pointer to struct CopList in struct ViewPort
         +0x0010 graphics/view.h: *48
Code             unsigned short int in struct IntuiMessage
         +0x0018 intuition/intuition.h: *687
Code             unsigned short int in struct SGWork
         +0x0018 intuition/sghooks.h: *43
CoerceDisplayInfo pointer to void in struct ColorMap
         +0x001c graphics/view.h: *127
ColdCapture      pointer to void in struct ExecBase
         +0x002a exec/execbase.h: *44
CollMask         pointer to short int in struct VSprite
         +0x002c graphics/gels.h: *111
CollectionItem   structure tag size 0x000c libraries/iffparse.h: *105, 106
ColorFontColors structure tag size 0x0008 graphics/text.h: *145, 161
ColorIndex       short int in struct ColorSpec
         +0x0000 intuition/intuition.h: *1242
ColorMap         structure tag size 0x0028 devices/printer.h: *164
                 graphics/view.h: 44, 114
ColorMap         pointer to struct ColorMap in struct ViewPort
         +0x0004 graphics/view.h: *44
ColorSpec        structure tag size 0x0008 intuition/intuition.h: *1241
ColorTable       pointer to void in struct ColorMap
         +0x0004 graphics/view.h: *119
ColorTextFont    structure tag size 0x0060 graphics/text.h: *152
ColumnSizeChange char in struct Preferences
         +0x00d9 intuition/preferences.h: *115
Command          char in struct MenuItem +0x001a intuition/intuition.h: *106
CommandLineInterface structure tag size 0x0040 dos/dosextens.h: *303
Compatibility    short int in struct MonitorInfo
         +0x002a graphics/displayinfo.h: *119
ConUnit          structure tag size 0x0128 devices/conunit.h: *55
ConfigDev        structure tag size 0x0044 libraries/configvars.h: *32, 42, 59
ContextNode      structure tag size 0x0018 libraries/iffparse.h: *69
CoolCapture      pointer to void in struct ExecBase
         +0x002e exec/execbase.h: *45
CopIns           structure tag size 0x0006 graphics/copper.h: *26, 68, 69
CopIns           pointer to struct CopIns in struct CopList
         +0x000c graphics/copper.h: *68
CopLStart        pointer to unsigned short int in struct CopList
         +0x0014 graphics/copper.h: *70
CopList          structure tag
     size 0x0022 graphics/copper.h: *31, 63, 65, 66, 86, 87
                 graphics/view.h: 46, 47, 48
CopList          pointer to struct CopList in struct UCopList
         +0x0008 graphics/copper.h: *87
CopPtr           pointer to struct CopIns in struct CopList
         +0x0010 graphics/copper.h: *69
CopSStart        pointer to unsigned short int in struct CopList
         +0x0018 graphics/copper.h: *71
Count            short int in struct CopList +0x001c graphics/copper.h: *72
Count            unsigned short int in struct ColorMap
         +0x0002 graphics/view.h: *118
Count            short int in struct AreaInfo +0x0010 graphics/rastport.h: *29
Count            char in struct Border +0x0007 intuition/intuition.h: *603
CurrentBinding   structure tag size 0x0010 libraries/configvars.h: *58
                 libraries/expansionbase.h: 53
Custom           structure tag size 0x01e6 hardware/custom.h: *27
CustomBitMap     pointer to struct BitMap in struct NewScreen
         +0x001c intuition/screens.h: *332
CustomBitMap     pointer to struct BitMap in struct ExtNewScreen
         +0x001c intuition/screens.h: *355
CxCustom         macro (2 arguments)   libraries/commodities.h: *29
CxDebug          macro (1 argument)   libraries/commodities.h: *28
CxFilter         macro (1 argument)   libraries/commodities.h: *23
CxMsg            "LONG"  libraries/commodities.h: *76
CxObj            "LONG"  libraries/commodities.h: *75
CxSender         macro (2 arguments)   libraries/commodities.h: *25
CxSignal         macro (2 arguments)   libraries/commodities.h: *26
CxTranslate      macro (1 argument)   libraries/commodities.h: *27
CxTypeFilter     macro (1 argument)   libraries/commodities.h: *24


2.0 IncludeXREF: D

da_BootPoint     unsigned short int in struct DiagArea
         +0x0006 libraries/configregs.h: *242
da_Config        unsigned char in struct DiagArea
         +0x0000 libraries/configregs.h: *238
da_DiagPoint     unsigned short int in struct DiagArea
         +0x0004 libraries/configregs.h: *241
da_Flags         unsigned char in struct DiagArea
         +0x0001 libraries/configregs.h: *239
da_Name          unsigned short int in struct DiagArea
         +0x0008 libraries/configregs.h: *243
da_Reserved01    unsigned short int in struct DiagArea
         +0x000a libraries/configregs.h: *247
da_Reserved02    unsigned short int in struct DiagArea
         +0x000c libraries/configregs.h: *248
da_Size          unsigned short int in struct DiagArea
         +0x0002 libraries/configregs.h: *240
dat_Flags        unsigned char in struct DateTime +0x000d dos/datetime.h: *30
dat_Format       unsigned char in struct DateTime +0x000c dos/datetime.h: *29
dat_Stamp        struct DateStamp(size 0x000c bytes) in struct DateTime
         +0x0000 dos/datetime.h: *28
dat_StrDate      pointer to unsigned char in struct DateTime
         +0x0012 dos/datetime.h: *32
dat_StrDay       pointer to unsigned char in struct DateTime
         +0x000e dos/datetime.h: *31
dat_StrTime      pointer to unsigned char in struct DateTime
         +0x0016 dos/datetime.h: *33
dataa            unsigned short int in struct SpriteDef
         +0x0004 hardware/custom.h: *119
datab            unsigned short int in struct SpriteDef
         +0x0006 hardware/custom.h: *120
dbf              function returning "LONG"   libraries/mathffp.h: *78
dd_CmdBytes      pointer to void in struct DeviceData
         +0x002e devices/prtbase.h: *56
dd_CmdVectors    pointer to void in struct DeviceData
         +0x002a devices/prtbase.h: *55
dd_CurrentX      long int in struct OldDrawerData
         +0x0030 workbench/workbench.h: *46
dd_CurrentX      long int in struct DrawerData
         +0x0030 workbench/workbench.h: *54
dd_CurrentY      long int in struct OldDrawerData
         +0x0034 workbench/workbench.h: *47
dd_CurrentY      long int in struct DrawerData
         +0x0034 workbench/workbench.h: *55
dd_Device        struct Library(size 0x0022 bytes) in struct DeviceData
         +0x0000 devices/prtbase.h: *52
dd_ExecBase      pointer to void in struct DeviceData
         +0x0026 devices/prtbase.h: *54
dd_Flags         unsigned long int in struct DrawerData
         +0x0038 workbench/workbench.h: *56
dd_Library       struct Library(size 0x0022 bytes) in struct Device
         +0x0000 exec/devices.h: *27
dd_NewWindow     struct NewWindow(size 0x0030 bytes) in struct OldDrawerData
         +0x0000 workbench/workbench.h: *45
dd_NewWindow     struct NewWindow(size 0x0030 bytes) in struct DrawerData
         +0x0000 workbench/workbench.h: *53
dd_NumCommands   unsigned short int in struct DeviceData
         +0x0032 devices/prtbase.h: *57
dd_Segment       pointer to void in struct DeviceData
         +0x0022 devices/prtbase.h: *53
dd_ViewModes     unsigned short int in struct DrawerData
         +0x003c workbench/workbench.h: *57
ddfstop          unsigned short int in struct Custom
         +0x0094 hardware/custom.h: *91
ddfstrt          unsigned short int in struct Custom
         +0x0092 hardware/custom.h: *90
de_Baud          unsigned long int in struct DosEnvec
         +0x0044 dos/filehandler.h: *49
de_BlocksPerTrack unsigned long int in struct DosEnvec
         +0x0014 dos/filehandler.h: *35
de_BootBlocks    unsigned long int in struct DosEnvec
         +0x004c dos/filehandler.h: *51
de_BootPri       long int in struct DosEnvec +0x003c dos/filehandler.h: *45
de_BufMemType    unsigned long int in struct DosEnvec
         +0x0030 dos/filehandler.h: *42
de_Control       unsigned long int in struct DosEnvec
         +0x0048 dos/filehandler.h: *50
de_DosType       unsigned long int in struct DosEnvec
         +0x0040 dos/filehandler.h: *46
de_HighCyl       unsigned long int in struct DosEnvec
         +0x0028 dos/filehandler.h: *40
de_Interleave    unsigned long int in struct DosEnvec
         +0x0020 dos/filehandler.h: *38
de_LowCyl        unsigned long int in struct DosEnvec
         +0x0024 dos/filehandler.h: *39
de_Mask          unsigned long int in struct DosEnvec
         +0x0038 dos/filehandler.h: *44
de_MaxTransfer   unsigned long int in struct DosEnvec
         +0x0034 dos/filehandler.h: *43
de_NumBuffers    unsigned long int in struct DosEnvec
         +0x002c dos/filehandler.h: *41
de_PreAlloc      unsigned long int in struct DosEnvec
         +0x001c dos/filehandler.h: *37
de_Reserved      unsigned long int in struct DosEnvec
         +0x0018 dos/filehandler.h: *36
de_SecOrg        unsigned long int in struct DosEnvec
         +0x0008 dos/filehandler.h: *32
de_SectorPerBlock unsigned long int in struct DosEnvec
         +0x0010 dos/filehandler.h: *34
de_SizeBlock     unsigned long int in struct DosEnvec
         +0x0004 dos/filehandler.h: *31
de_Surfaces      unsigned long int in struct DosEnvec
         +0x000c dos/filehandler.h: *33
de_TableSize     unsigned long int in struct DosEnvec
         +0x0000 dos/filehandler.h: *30
default_monitor pointer to struct MonitorSpec in struct GfxBase
         +0x018e graphics/gfxbase.h: *87
deniseid         unsigned short int in struct Custom
         +0x007c hardware/custom.h: *81
detailPen        #define DETAILPEN = 0x00000000  intuition/iobsolete.h: *261
dfh_DF           struct Node(size 0x000e bytes) in struct DiskFontHeader
         +0x0000 libraries/diskfont.h: *72
dfh_FileID       unsigned short int in struct DiskFontHeader
         +0x000e libraries/diskfont.h: *73
dfh_Name         array [32] of char in struct DiskFontHeader
         +0x0016 libraries/diskfont.h: *76
dfh_Revision     unsigned short int in struct DiskFontHeader
         +0x0010 libraries/diskfont.h: *74
dfh_Segment      long int in struct DiskFontHeader
         +0x0012 libraries/diskfont.h: *75
dfh_TF           struct TextFont(size 0x0034 bytes) in struct DiskFontHeader
         +0x0036 libraries/diskfont.h: *77
dfh_TagList      #define dfh_Segment  libraries/diskfont.h: *82
dg_BufMemType    unsigned long int in struct DriveGeometry
         +0x0018 devices/trackdisk.h: *144
dg_CylSectors    unsigned long int in struct DriveGeometry
         +0x000c devices/trackdisk.h: *141
dg_Cylinders     unsigned long int in struct DriveGeometry
         +0x0008 devices/trackdisk.h: *140
dg_DeviceType    unsigned char in struct DriveGeometry
         +0x001c devices/trackdisk.h: *146
dg_Flags         unsigned char in struct DriveGeometry
         +0x001d devices/trackdisk.h: *147
dg_Heads         unsigned long int in struct DriveGeometry
         +0x0010 devices/trackdisk.h: *142
dg_Reserved      unsigned short int in struct DriveGeometry
         +0x001e devices/trackdisk.h: *148
dg_SectorSize    unsigned long int in struct DriveGeometry
         +0x0000 devices/trackdisk.h: *138
dg_TotalSectors unsigned long int in struct DriveGeometry
         +0x0004 devices/trackdisk.h: *139
dg_TrackSectors unsigned long int in struct DriveGeometry
         +0x0014 devices/trackdisk.h: *143
di_DevInfo       long int in struct DosInfo +0x0004 dos/dosextens.h: *277
di_DevLock       struct SignalSemaphore(size 0x002e bytes) in struct DosInfo
         +0x0014 dos/dosextens.h: *281
di_Devices       long int in struct DosInfo +0x0008 dos/dosextens.h: *278
di_EntryLock     struct SignalSemaphore(size 0x002e bytes) in struct DosInfo
         +0x0042 dos/dosextens.h: *282
di_Handlers      long int in struct DosInfo +0x000c dos/dosextens.h: *279
di_McName        long int in struct DosInfo +0x0000 dos/dosextens.h: *275
di_NetHand       pointer to void in struct DosInfo
         +0x0010 dos/dosextens.h: *280
di_ResList       #define di_McName  dos/dosextens.h: *276
diagstrt         array [4] of unsigned short int in struct copinit
         +0x000c graphics/copper.h: *96
diwhigh          unsigned short int in struct Custom
         +0x01e4 hardware/custom.h: *141
diwstart         array [4] of unsigned short int in struct copinit
         +0x0004 graphics/copper.h: *95
diwstop          unsigned short int in struct Custom
         +0x0090 hardware/custom.h: *89
diwstrt          unsigned short int in struct Custom
         +0x008e hardware/custom.h: *88
dl_A2            long int in struct DosLibrary +0x002a dos/dosextens.h: *232
dl_A5            long int in struct DosLibrary +0x002e dos/dosextens.h: *233
dl_A6            long int in struct DosLibrary +0x0032 dos/dosextens.h: *234
dl_DiskType      long int in struct DeviceList +0x0020 dos/dosextens.h: *338
dl_Errors        pointer to struct ErrorString in struct DosLibrary
         +0x0036 dos/dosextens.h: *235
dl_GV            pointer to void in struct DosLibrary
         +0x0026 dos/dosextens.h: *231
dl_Lock          long int in struct DeviceList +0x000c dos/dosextens.h: *335
dl_LockList      long int in struct DeviceList +0x001c dos/dosextens.h: *337
dl_Name          long int in struct DeviceList +0x0028 dos/dosextens.h: *340
dl_Next          long int in struct DeviceList +0x0000 dos/dosextens.h: *332
dl_Root          pointer to struct RootNode in struct DosLibrary
         +0x0022 dos/dosextens.h: *230
dl_Task          pointer to struct MsgPort in struct DeviceList
         +0x0008 dos/dosextens.h: *334
dl_TimeReq       pointer to struct timerequest in struct DosLibrary
         +0x003a dos/dosextens.h: *236
dl_Type          long int in struct DeviceList +0x0004 dos/dosextens.h: *333
dl_UtilityBase   pointer to struct Library in struct DosLibrary
         +0x003e dos/dosextens.h: *237
dl_VolumeDate    struct DateStamp(size 0x000c bytes) in struct DeviceList
         +0x0010 dos/dosextens.h: *336
dl_lib           struct Library(size 0x0022 bytes) in struct DosLibrary
         +0x0000 dos/dosextens.h: *229
dl_unused        long int in struct DeviceList +0x0024 dos/dosextens.h: *339
dmacon           unsigned short int in struct Custom
         +0x0096 hardware/custom.h: *92
dmaconr          unsigned short int in struct Custom
         +0x0002 hardware/custom.h: *29
dn_GlobalVec     long int in struct DeviceNode +0x0024 dos/filehandler.h: *114
dn_Handler       long int in struct DeviceNode +0x0010 dos/filehandler.h: *108
dn_Lock          long int in struct DeviceNode +0x000c dos/filehandler.h: *107
dn_Name          long int in struct DeviceNode +0x0028 dos/filehandler.h: *122
dn_Next          long int in struct DeviceNode +0x0000 dos/filehandler.h: *102
dn_Priority      long int in struct DeviceNode +0x0018 dos/filehandler.h: *110
dn_SegList       long int in struct DeviceNode +0x0020 dos/filehandler.h: *112
dn_StackSize     unsigned long int in struct DeviceNode
         +0x0014 dos/filehandler.h: *109
dn_Startup       long int in struct DeviceNode +0x001c dos/filehandler.h: *111
dn_Task          pointer to struct MsgPort in struct DeviceNode
         +0x0008 dos/filehandler.h: *104
dn_Type          unsigned long int in struct DeviceNode
         +0x0004 dos/filehandler.h: *103
do_CurrentX      long int in struct DiskObject
         +0x003a workbench/workbench.h: *69
do_CurrentY      long int in struct DiskObject
         +0x003e workbench/workbench.h: *70
do_DefaultTool   pointer to char in struct DiskObject
         +0x0032 workbench/workbench.h: *67
do_DrawerData    pointer to struct DrawerData in struct DiskObject
         +0x0042 workbench/workbench.h: *71
do_Gadget        struct Gadget(size 0x002c bytes) in struct DiskObject
         +0x0004 workbench/workbench.h: *65
do_Magic         unsigned short int in struct DiskObject
         +0x0000 workbench/workbench.h: *63
do_StackSize     long int in struct DiskObject
         +0x004a workbench/workbench.h: *73
do_ToolTypes     pointer to pointer to char in struct DiskObject
         +0x0036 workbench/workbench.h: *68
do_ToolWindow    pointer to char in struct DiskObject
         +0x0046 workbench/workbench.h: *72
do_Type          unsigned char in struct DiskObject
         +0x0030 workbench/workbench.h: *66
do_Version       unsigned short int in struct DiskObject
         +0x0002 workbench/workbench.h: *64
do_monitor       pointer to function returning int in struct SpecialMonitor
         +0x001a graphics/monitor.h: *146
dol_AssignName   pointer to unsigned char in struct (no tag)
         +0x0000 dos/dosextens.h: *385
dol_DiskType     long int in struct (no tag)  +0x0010 dos/dosextens.h: *381
dol_GlobVec      long int in struct (no tag)  +0x0014 dos/dosextens.h: *373
dol_Handler      long int in struct (no tag)  +0x0000 dos/dosextens.h: *368
dol_List         pointer to struct AssignList in struct (no tag)
         +0x0004 dos/dosextens.h: *386
dol_Lock         long int in struct DosList +0x000c dos/dosextens.h: *365
dol_LockList     long int in struct (no tag)  +0x000c dos/dosextens.h: *380
dol_Name         long int in struct DosList +0x0028 dos/dosextens.h: *391
dol_Next         long int in struct DosList +0x0000 dos/dosextens.h: *362
dol_Priority     long int in struct (no tag)  +0x0008 dos/dosextens.h: *370
dol_SegList      long int in struct (no tag)  +0x0010 dos/dosextens.h: *372
dol_StackSize    long int in struct (no tag)  +0x0004 dos/dosextens.h: *369
dol_Startup      unsigned long int in struct (no tag)
         +0x000c dos/dosextens.h: *371
dol_Task         pointer to struct MsgPort in struct DosList
         +0x0008 dos/dosextens.h: *364
dol_Type         long int in struct DosList +0x0004 dos/dosextens.h: *363
dol_VolumeDate   struct DateStamp(size 0x000c bytes) in struct (no tag)
         +0x0000 dos/dosextens.h: *379
dol_assign       struct (no tag) (size 0x0008 bytes) in union (no tag)
         +0x0000 dos/dosextens.h: *387
dol_handler      struct (no tag) (size 0x0018 bytes) in union (no tag)
         +0x0000 dos/dosextens.h: *376
dol_misc         union (no tag) (size 0x0018 bytes) in struct DosList
         +0x0010 dos/dosextens.h: *389
dol_volume       struct (no tag) (size 0x0014 bytes) in union (no tag)
         +0x0000 dos/dosextens.h: *382
dp_Action        #define dp_Type  dos/dosextens.h: *124
dp_Arg1          long int in struct DosPacket +0x0014 dos/dosextens.h: *128
dp_Arg2          long int in struct DosPacket +0x0018 dos/dosextens.h: *129
dp_Arg3          long int in struct DosPacket +0x001c dos/dosextens.h: *130
dp_Arg4          long int in struct DosPacket +0x0020 dos/dosextens.h: *131
dp_Arg5          long int in struct DosPacket +0x0024 dos/dosextens.h: *132
dp_Arg6          long int in struct DosPacket +0x0028 dos/dosextens.h: *133
dp_Arg7          long int in struct DosPacket +0x002c dos/dosextens.h: *134
dp_BufAddr       #define dp_Arg1  dos/dosextens.h: *127
dp_Link          pointer to struct Message in struct DosPacket
         +0x0000 dos/dosextens.h: *111
dp_Port          pointer to struct MsgPort in struct DosPacket
         +0x0004 dos/dosextens.h: *112
dp_Res1          long int in struct DosPacket +0x000c dos/dosextens.h: *117
dp_Res2          long int in struct DosPacket +0x0010 dos/dosextens.h: *121
dp_Status        #define dp_Res1  dos/dosextens.h: *125
dp_Status2       #define dp_Res2  dos/dosextens.h: *126
dp_Type          long int in struct DosPacket +0x0008 dos/dosextens.h: *114
dr_CiaResource   pointer to struct Library in struct DiscResource
         +0x002c resources/disk.h: *56
dr_CurrTask      pointer to struct Task in struct DiscResource
         +0x0090 resources/disk.h: *62
dr_Current       pointer to struct DiscResourceUnit in struct DiscResource
         +0x0022 resources/disk.h: *52
dr_DiscBlock     struct Interrupt(size 0x0016 bytes) in struct DiscResource
         +0x004e resources/disk.h: *59
dr_DiscSync      struct Interrupt(size 0x0016 bytes) in struct DiscResource
         +0x0064 resources/disk.h: *60
dr_Flags         unsigned char in struct DiscResource
         +0x0026 resources/disk.h: *53
dr_Index         struct Interrupt(size 0x0016 bytes) in struct DiscResource
         +0x007a resources/disk.h: *61
dr_Library       struct Library(size 0x0022 bytes) in struct DiscResource
         +0x0000 resources/disk.h: *51
dr_SysLib        pointer to struct Library in struct DiscResource
         +0x0028 resources/disk.h: *55
dr_UnitID        array [4] of unsigned long int in struct DiscResource
         +0x0030 resources/disk.h: *57
dr_Waiting       struct List(size 0x000e bytes) in struct DiscResource
         +0x0040 resources/disk.h: *58
dr_pad           unsigned char in struct DiscResource
         +0x0027 resources/disk.h: *54
dri_Depth        unsigned short int in struct DrawInfo
         +0x000c intuition/screens.h: *68
dri_Flags        unsigned long int in struct DrawInfo
         +0x0012 intuition/screens.h: *75
dri_Font         pointer to struct TextFont in struct DrawInfo
         +0x0008 intuition/screens.h: *67
dri_NumPens      unsigned short int in struct DrawInfo
         +0x0002 intuition/screens.h: *64
dri_Pens         pointer to unsigned short int in struct DrawInfo
         +0x0004 intuition/screens.h: *65
dri_Reserved     array [7] of unsigned long int in struct DrawInfo
         +0x0016 intuition/screens.h: *76
dri_Resolution   struct (no tag) (size 0x0004 bytes) in struct DrawInfo
         +0x000e intuition/screens.h: *73
dri_Version      unsigned short int in struct DrawInfo
         +0x0000 intuition/screens.h: *63
dru_DiscBlock    struct Interrupt(size 0x0016 bytes) in struct
                 DiscResourceUnit
         +0x0014 resources/disk.h: *45
dru_DiscSync     struct Interrupt(size 0x0016 bytes) in struct
                 DiscResourceUnit
         +0x002a resources/disk.h: *46
dru_Index        struct Interrupt(size 0x0016 bytes) in struct
                 DiscResourceUnit
         +0x0040 resources/disk.h: *47
dru_Message      struct Message(size 0x0014 bytes) in struct DiscResourceUnit
         +0x0000 resources/disk.h: *44
ds_Days          long int in struct DateStamp +0x0000 dos/dos.h: *55
ds_Minute        long int in struct DateStamp +0x0004 dos/dos.h: *56
ds_Tick          long int in struct DateStamp +0x0008 dos/dos.h: *57
dskbytr          unsigned short int in struct Custom
         +0x001a hardware/custom.h: *41
dskdat           unsigned short int in struct Custom
         +0x0026 hardware/custom.h: *46
dskdatr          unsigned short int in struct Custom
         +0x0008 hardware/custom.h: *32
dsklen           unsigned short int in struct Custom
         +0x0024 hardware/custom.h: *45
dskpt            pointer to void in struct Custom
         +0x0020 hardware/custom.h: *44
dsksync          unsigned short int in struct Custom
         +0x007e hardware/custom.h: *82
dummy            char in struct RastPort +0x001f graphics/rastport.h: *71
dvi_GlobVec      long int in struct DevInfo +0x0024 dos/dosextens.h: *355
dvi_Handler      long int in struct DevInfo +0x0010 dos/dosextens.h: *350
dvi_Lock         long int in struct DevInfo +0x000c dos/dosextens.h: *349
dvi_Name         long int in struct DevInfo +0x0028 dos/dosextens.h: *356
dvi_Next         long int in struct DevInfo +0x0000 dos/dosextens.h: *346
dvi_Priority     long int in struct DevInfo +0x0018 dos/dosextens.h: *352
dvi_SegList      long int in struct DevInfo +0x0020 dos/dosextens.h: *354
dvi_StackSize    long int in struct DevInfo +0x0014 dos/dosextens.h: *351
dvi_Startup      long int in struct DevInfo +0x001c dos/dosextens.h: *353
dvi_Task         pointer to void in struct DevInfo
         +0x0008 dos/dosextens.h: *348
dvi_Type         long int in struct DevInfo +0x0004 dos/dosextens.h: *347
dvp_DevNode      pointer to struct DosList in struct DevProc
         +0x000c dos/dosextens.h: *414
dvp_Flags        unsigned long int in struct DevProc
         +0x0008 dos/dosextens.h: *413
dvp_Lock         long int in struct DevProc +0x0004 dos/dosextens.h: *412
dvp_Port         pointer to struct MsgPort in struct DevProc
         +0x0000 dos/dosextens.h: *411
DAC_BINDTIME     #define 0x20 = 0x00000020  libraries/configregs.h: *264
DAC_BOOTTIME     #define 0x30 = 0x00000030  libraries/configregs.h: *260
DAC_BUSWIDTH     #define 0xC0 = 0x000000c0  libraries/configregs.h: *255
DAC_BYTEWIDE     #define 0x40 = 0x00000040  libraries/configregs.h: *257
DAC_CONFIGTIME   #define 0x10 = 0x00000010  libraries/configregs.h: *262
DAC_NEVER        #define 0x00 = 0x00000000  libraries/configregs.h: *261
DAC_NIBBLEWIDE   #define 0x00 = 0x00000000  libraries/configregs.h: *256
DAC_WORDWIDE     #define 0x80 = 0x00000080  libraries/configregs.h: *258
DBLPF            #define 0x400 = 0x00000400  graphics/display.h: *22
DBUFFER          #define 0x04 = 0x00000004  graphics/rastport.h: *103
DBufPacket       structure tag size 0x000c graphics/gels.h: *160, 230
DBuffer          pointer to struct DBufPacket in struct Bob
         +0x001a graphics/gels.h: *160
DDB_AllBit       #define 3 = 0x00000003  dos/dosasl.h: *113
DDB_Completed    #define 2 = 0x00000002  dos/dosasl.h: *111
DDB_ExaminedBit  #define 1 = 0x00000001  dos/dosasl.h: *109
DDB_PatternBit   #define 0 = 0x00000000  dos/dosasl.h: *107
DDB_Single       #define 4 = 0x00000004  dos/dosasl.h: *115
DDF_AllBit       #define 8 = 0x00000008  dos/dosasl.h: *114
DDF_Completed    #define 4 = 0x00000004  dos/dosasl.h: *112
DDF_ExaminedBit  #define 2 = 0x00000002  dos/dosasl.h: *110
DDF_PatternBit   #define 1 = 0x00000001  dos/dosasl.h: *108
DDF_Single       #define 16 = 0x00000010  dos/dosasl.h: *116
DEADEND_ALERT    #define 0x80000000 = 0x80000000  intuition/intuition.h: *1312
DEFARTIC         #define 100 = 0x00000064  devices/narrator.h: *70
DEFAULTMOUSEQUEUE #define (5) = 0x00000005  intuition/intuition.h: *960
DEFAULT_MONITOR_ID #define 0x00000000 = 0x00000000
                 graphics/displayinfo.h: *147
DEFAULT_MONITOR_NAME #define "default.monitor"  graphics/monitor.h: *65
DEFCENTRAL       #define 0 = 0x00000000  devices/narrator.h: *71
DEFERREFRESH     #define 0x8000 = 0x00008000  intuition/intuition.h: *206
DEFF0ENTHUS      #define 32 = 0x00000020  devices/narrator.h: *73
DEFF0PERT        #define 0 = 0x00000000  devices/narrator.h: *72
DEFFREQ          #define 22200 = 0x000056b8  devices/narrator.h: *62
DEFMODE          #define NATURALF0 = 0x00000000  devices/narrator.h: *69
DEFPITCH         #define 110 = 0x0000006e  devices/narrator.h: *59
DEFPRIORITY      #define 100 = 0x00000064  devices/narrator.h: *74
DEFRATE          #define 150 = 0x00000096  devices/narrator.h: *60
DEFSEX           #define MALE = 0x00000000  devices/narrator.h: *68
DEFVOL           #define 64 = 0x00000040  devices/narrator.h: *61
DELTAMOVE        #define IDCMP_DELTAMOVE = 0x00100000
                 intuition/iobsolete.h: *134
DEPTHIMAGE       #define (0x00L) = 0x00000000  intuition/imageclass.h: *101
DEST             #define 0x100 = 0x00000100  hardware/blit.h: *58
DESTADDR         #define u3.u4.u1.DestAddr  graphics/copper.h: *50
DESTDATA         #define u3.u4.u2.DestData  graphics/copper.h: *52
DETAILPEN        #define (0x0000) = 0x00000000  intuition/screens.h: *82
DEVICES_AUDIO_H  #define  devices/audio.h: *2
DEVICES_BOOTBLOCK_H #define  devices/bootblock.h: *2
DEVICES_CIA_H    #define 1 = 0x00000001  resources/cia.h: *2
DEVICES_CLIPBOARD_H #define  devices/clipboard.h: *2
                 libraries/iffparse.h: 25
DEVICES_CONSOLE_H #define  devices/console.h: *2
                 devices/conunit.h: 23
DEVICES_CONUNIT_H #define  devices/conunit.h: *2
DEVICES_GAMEPORT_H #define  devices/gameport.h: *2
DEVICES_HARDBLOCKS_H #define  devices/hardblocks.h: *2
DEVICES_INPUTEVENT_H #define  devices/inputevent.h: *2, 1
                 intuition/intuition.h: 47
DEVICES_INPUT_H  #define  devices/input.h: *2
DEVICES_KEYBOARD_H #define  devices/keyboard.h: *2
DEVICES_KEYMAP_H #define  devices/keymap.h: *2, 1
DEVICES_NARRATOR_H #define  devices/narrator.h: *2
DEVICES_PARALLEL_H #define  devices/parallel.h: *2
                 devices/prtbase.h: 34
DEVICES_PRINTER_H #define  devices/printer.h: *2
DEVICES_PRTBASE_H #define  devices/prtbase.h: *2
DEVICES_PRTGFX_H #define  devices/prtgfx.h: *2
DEVICES_SCSIDISK_H #define  devices/scsidisk.h: *2
DEVICES_SERIAL_H #define  devices/serial.h: *2, 1
DEVICES_TIMER_H  #define 1 = 0x00000001  devices/timer.h: *2, 1
                 devices/prtbase.h: 40
                 dos/dosextens.h: 27
                 intuition/preferences.h: 19
DEVICES_TRACKDISK_H #define  devices/trackdisk.h: *2
DEV_ABORTIO      #define (-36) = 0xffffffdc  exec/io.h: *44
DEV_BEGINIO      #define (-30) = 0xffffffe2  exec/io.h: *43
DE_BAUD          #define 17 = 0x00000011  dos/filehandler.h: *78
DE_BLKSPERTRACK  #define 5 = 0x00000005  dos/filehandler.h: *62
DE_BOOTBLOCKS    #define 19 = 0x00000013  dos/filehandler.h: *80
DE_BOOTPRI       #define 15 = 0x0000000f  dos/filehandler.h: *74
DE_BUFMEMTYPE    #define 12 = 0x0000000c  dos/filehandler.h: *71
DE_CONTROL       #define 18 = 0x00000012  dos/filehandler.h: *79
DE_DOSTYPE       #define 16 = 0x00000010  dos/filehandler.h: *77
DE_INTERLEAVE    #define 8 = 0x00000008  dos/filehandler.h: *65
DE_LOWCYL        #define 9 = 0x00000009  dos/filehandler.h: *66
DE_MASK          #define 14 = 0x0000000e  dos/filehandler.h: *73
DE_MAXTRANSFER   #define 13 = 0x0000000d  dos/filehandler.h: *72
DE_MEMBUFTYPE    #define 12 = 0x0000000c  dos/filehandler.h: *69
DE_NUMBUFFERS    #define 11 = 0x0000000b  dos/filehandler.h: *68
DE_NUMHEADS      #define 3 = 0x00000003  dos/filehandler.h: *60
DE_PREFAC        #define 7 = 0x00000007  dos/filehandler.h: *64
DE_RESERVEDBLKS  #define 6 = 0x00000006  dos/filehandler.h: *63
DE_SECORG        #define 2 = 0x00000002  dos/filehandler.h: *59
DE_SECSPERBLK    #define 4 = 0x00000004  dos/filehandler.h: *61
DE_SIZEBLOCK     #define 1 = 0x00000001  dos/filehandler.h: *58
DE_TABLESIZE     #define 0 = 0x00000000  dos/filehandler.h: *57
DE_UPPERCYL      #define 10 = 0x0000000a  dos/filehandler.h: *67
DFH_ID           #define 0x0f80 = 0x00000f80  libraries/diskfont.h: *61
DFTCH_MASK       #define 0xFF = 0x000000ff  graphics/display.h: *37
DGB_REMOVABLE    #define 0 = 0x00000000  devices/trackdisk.h: *165
DGF_REMOVABLE    #define 1 = 0x00000001  devices/trackdisk.h: *166
DG_CDROM         #define 5 = 0x00000005  devices/trackdisk.h: *157
DG_COMMUNICATION #define 9 = 0x00000009  devices/trackdisk.h: *161
DG_DIRECT_ACCESS #define 0 = 0x00000000  devices/trackdisk.h: *152
DG_MEDIUM_CHANGER #define 8 = 0x00000008  devices/trackdisk.h: *160
DG_OPTICAL_DISK  #define 7 = 0x00000007  devices/trackdisk.h: *159
DG_PRINTER       #define 2 = 0x00000002  devices/trackdisk.h: *154
DG_PROCESSOR     #define 3 = 0x00000003  devices/trackdisk.h: *155
DG_SCANNER       #define 6 = 0x00000006  devices/trackdisk.h: *158
DG_SEQUENTIAL_ACCESS #define 1 = 0x00000001  devices/trackdisk.h: *153
DG_UNKNOWN       #define 31 = 0x0000001f  devices/trackdisk.h: *162
DG_WORM          #define 4 = 0x00000004  devices/trackdisk.h: *156
DHeight          short int in struct ViewPort +0x001a graphics/view.h: *50
DIAB_630         #define 0x04 = 0x00000004  intuition/preferences.h: *196
DIAB_ADV_D25     #define 0x05 = 0x00000005  intuition/preferences.h: *197
DIAB_C_150       #define 0x06 = 0x00000006  intuition/preferences.h: *198
DIMENSIONS_MASK  #define (BOUNDED_DIMENSIONS|ABSOLUTE_DIMENSIONS|
                         PIXEL_DIMENSIONS|MULTIPLY_DIMENSIONS) = 0x000000f0
                 intuition/preferences.h: *265
DIPF_IS_BEAMSYNC #define 0x00000800 = 0x00000800  graphics/displayinfo.h: *88
DIPF_IS_DRAGGABLE #define 0x00000200 = 0x00000200  graphics/displayinfo.h: *86
DIPF_IS_DUALPF   #define 0x00000002 = 0x00000002  graphics/displayinfo.h: *73
DIPF_IS_ECS      #define 0x00000010 = 0x00000010  graphics/displayinfo.h: *80
DIPF_IS_EXTRAHALFBRITE #define 0x00001000 = 0x00001000
                 graphics/displayinfo.h: *90
DIPF_IS_GENLOCK  #define 0x00000080 = 0x00000080  graphics/displayinfo.h: *83
DIPF_IS_HAM      #define 0x00000008 = 0x00000008  graphics/displayinfo.h: *75
DIPF_IS_LACE     #define 0x00000001 = 0x00000001  graphics/displayinfo.h: *72
DIPF_IS_PAL      #define 0x00000020 = 0x00000020  graphics/displayinfo.h: *81
DIPF_IS_PANELLED #define 0x00000400 = 0x00000400  graphics/displayinfo.h: *87
DIPF_IS_PF2PRI   #define 0x00000004 = 0x00000004  graphics/displayinfo.h: *74
DIPF_IS_SPRITES  #define 0x00000040 = 0x00000040  graphics/displayinfo.h: *82
DIPF_IS_WB       #define 0x00000100 = 0x00000100  graphics/displayinfo.h: *85
DISKINSERTED     #define IDCMP_DISKINSERTED = 0x00008000
                 intuition/iobsolete.h: *129
DISKNAME         #define "disk.resource"  resources/disk.h: *102
DISKREMOVED      #define IDCMP_DISKREMOVED = 0x00010000
                 intuition/iobsolete.h: *130
DISPLAYDUAL      #define 0x0040 = 0x00000040  hardware/custom.h: *153
DISPLAYNAMELEN   #define 32 = 0x00000020  graphics/displayinfo.h: *130, 135
DISPLAYPAL       #define 0x0020 = 0x00000020  hardware/custom.h: *154
DITHERING_MASK   #define (HALFTONE_DITHERING|FLOYD_DITHERING) = 0x00000600
                 intuition/preferences.h: *266
DIW_HORIZ_POS    #define 0x7F = 0x0000007f  graphics/display.h: *32
DIW_VRTCL_POS    #define 0x1FF = 0x000001ff  graphics/display.h: *33
DIW_VRTCL_POS_SHIFT #define 7 = 0x00000007  graphics/display.h: *34
DI_AVAIL_NOCHIPS #define 0x0001 = 0x00000001  graphics/displayinfo.h: *66
DI_AVAIL_NOMONITOR #define 0x0002 = 0x00000002  graphics/displayinfo.h: *67
DI_AVAIL_NOTWITHGENLOCK #define 0x0004 = 0x00000004
                 graphics/displayinfo.h: *68
DLT_DEVICE       #define 0 = 0x00000000  dos/dosextens.h: *402
DLT_DIRECTORY    #define 1 = 0x00000001  dos/dosextens.h: *403
DLT_LATE         #define 3 = 0x00000003  dos/dosextens.h: *405
DLT_NONBINDING   #define 4 = 0x00000004  dos/dosextens.h: *406
DLT_PRIVATE      #define -1 = 0xffffffff  dos/dosextens.h: *407
DLT_VOLUME       #define 2 = 0x00000002  dos/dosextens.h: *404
DMAB_AUD0        #define 0 = 0x00000000  hardware/dmabits.h: *37
DMAB_AUD1        #define 1 = 0x00000001  hardware/dmabits.h: *38
DMAB_AUD2        #define 2 = 0x00000002  hardware/dmabits.h: *39
DMAB_AUD3        #define 3 = 0x00000003  hardware/dmabits.h: *40
DMAB_BLITHOG     #define 10 = 0x0000000a  hardware/dmabits.h: *47
DMAB_BLITTER     #define 6 = 0x00000006  hardware/dmabits.h: *43
DMAB_BLTDONE     #define 14 = 0x0000000e  hardware/dmabits.h: *48
DMAB_BLTNZERO    #define 13 = 0x0000000d  hardware/dmabits.h: *49
DMAB_COPPER      #define 7 = 0x00000007  hardware/dmabits.h: *44
DMAB_DISK        #define 4 = 0x00000004  hardware/dmabits.h: *41
DMAB_MASTER      #define 9 = 0x00000009  hardware/dmabits.h: *46
DMAB_RASTER      #define 8 = 0x00000008  hardware/dmabits.h: *45
DMAB_SETCLR      #define 15 = 0x0000000f  hardware/dmabits.h: *36
DMAB_SPRITE      #define 5 = 0x00000005  hardware/dmabits.h: *42
DMAF_ALL         #define 0x01FF = 0x000001ff  hardware/dmabits.h: *29
DMAF_AUD0        #define 0x0001 = 0x00000001  hardware/dmabits.h: *18
DMAF_AUD1        #define 0x0002 = 0x00000002  hardware/dmabits.h: *19
DMAF_AUD2        #define 0x0004 = 0x00000004  hardware/dmabits.h: *20
DMAF_AUD3        #define 0x0008 = 0x00000008  hardware/dmabits.h: *21
DMAF_AUDIO       #define 0x000F = 0x0000000f  hardware/dmabits.h: *17
DMAF_BLITHOG     #define 0x0400 = 0x00000400  hardware/dmabits.h: *28
DMAF_BLITTER     #define 0x0040 = 0x00000040  hardware/dmabits.h: *24
DMAF_BLTDONE     #define 0x4000 = 0x00004000  hardware/dmabits.h: *33
DMAF_BLTNZERO    #define 0x2000 = 0x00002000  hardware/dmabits.h: *34
DMAF_COPPER      #define 0x0080 = 0x00000080  hardware/dmabits.h: *25
DMAF_DISK        #define 0x0010 = 0x00000010  hardware/dmabits.h: *22
DMAF_MASTER      #define 0x0200 = 0x00000200  hardware/dmabits.h: *27
DMAF_RASTER      #define 0x0100 = 0x00000100  hardware/dmabits.h: *26
DMAF_SETCLR      #define 0x8000 = 0x00008000  hardware/dmabits.h: *16
DMAF_SPRITE      #define 0x0020 = 0x00000020  hardware/dmabits.h: *23
DMODECOUNT       #define 0x0002 = 0x00000002  intuition/intuitionbase.h: *35
DMRequest        pointer to struct Requester in struct Window
         +0x0028 intuition/intuition.h: *815
DOSFALSE         #define (0L) = 0x00000000  dos/dos.h: *25
DOSNAME          #define "dos.library"  dos/dos.h: *20
DOSTRUE          #define (-1L) = 0xffffffff  dos/dos.h: *24
DOS_CLI          #define 4 = 0x00000004  dos/dos.h: *241
DOS_DATETIME_H   #define  dos/datetime.h: *2
DOS_DOSASL_H     #define  dos/dosasl.h: *2
DOS_DOSEXTENS_H  #define  dos/dosextens.h: *2, 1
DOS_DOSHUNKS_H   #define  dos/doshunks.h: *2
DOS_DOSTAGS_H    #define  dos/dostags.h: *2
DOS_DOS_H        #define  dos/dos.h: *2, 1
                 dos/filehandler.h: 19
                 dos/record.h: 17
                 dos/datetime.h: 17
                 dos/dosasl.h: 25
                 libraries/dos.h: 15
                 resources/filesysres.h: 21
DOS_EXALLCONTROL #define 1 = 0x00000001  dos/dos.h: *238
DOS_EXALL_H      #define  dos/exall.h: *2
DOS_FIB          #define 2 = 0x00000002  dos/dos.h: *239
DOS_FILEHANDLE   #define 0 = 0x00000000  dos/dos.h: *237
DOS_FILEHANDLER_H #define  dos/filehandler.h: *2
                 libraries/filehandler.h: 15
DOS_NOTIFY_H     #define  dos/notify.h: *2
DOS_RDARGS       #define 5 = 0x00000005  dos/dos.h: *242
DOS_RDARGS_H     #define  dos/rdargs.h: *2
DOS_RECORD_H     #define  dos/record.h: *2
DOS_STDIO_H      #define  dos/stdio.h: *2
DOS_STDPKT       #define 3 = 0x00000003  dos/dos.h: *240
DOS_VAR_H        #define  dos/var.h: *2
DOUBLE           typedef double  exec/types.h: *65
DOWNBACKGADGET   #define 1 = 0x00000001  intuition/intuitionbase.h: *48
DOWNIMAGE        #define (0x0DL) = 0x0000000d  intuition/imageclass.h: *109
DPB_DEAD         #define 3 = 0x00000003  devices/keymap.h: *70
DPB_MOD          #define 0 = 0x00000000  devices/keymap.h: *68
DPF_DEAD         #define 0x08 = 0x00000008  devices/keymap.h: *71
DPF_MOD          #define 0x01 = 0x00000001  devices/keymap.h: *69
DP_2DFACSHIFT    #define 4 = 0x00000004  devices/keymap.h: *74
DP_2DINDEXMASK   #define 0x0f = 0x0000000f  devices/keymap.h: *73
DRAFT            #define 0x000 = 0x00000000  intuition/preferences.h: *164
DRAGGADGET       #define 4 = 0x00000004  intuition/intuitionbase.h: *51
DRAWERDATAFILESIZE #define (sizeof(struct DrawerData)) = 0x0000003e
                 workbench/workbench.h: *60
DRB_ACTIVE       #define 7 = 0x00000007  resources/disk.h: *70
DRB_ALLOC0       #define 0 = 0x00000000  resources/disk.h: *66
DRB_ALLOC1       #define 1 = 0x00000001  resources/disk.h: *67
DRB_ALLOC2       #define 2 = 0x00000002  resources/disk.h: *68
DRB_ALLOC3       #define 3 = 0x00000003  resources/disk.h: *69
DRF_ACTIVE       #define (1<<7) = 0x00000080  resources/disk.h: *76
DRF_ALLOC0       #define (1<<0) = 0x00000001  resources/disk.h: *72
DRF_ALLOC1       #define (1<<1) = 0x00000002  resources/disk.h: *73
DRF_ALLOC2       #define (1<<2) = 0x00000004  resources/disk.h: *74
DRF_ALLOC3       #define (1<<3) = 0x00000008  resources/disk.h: *75
DRIF_NEWLOOK     #define 0x00000001 = 0x00000001  intuition/screens.h: *79
DRIVE3_5         #define 1 = 0x00000001  devices/trackdisk.h: *203
DRIVE3_5_150RPM  #define 3 = 0x00000003  devices/trackdisk.h: *205
DRIVE5_25        #define 2 = 0x00000002  devices/trackdisk.h: *204
DRI_VERSION      #define (1) = 0x00000001  intuition/screens.h: *59
DRT_150RPM       #define (0xAAAAAAAA) = 0xaaaaaaaa  resources/disk.h: *123
DRT_37422D2S     #define (0x55555555) = 0x55555555  resources/disk.h: *121
DRT_AMIGA        #define (0x00000000) = 0x00000000  resources/disk.h: *120
DRT_EMPTY        #define (0xFFFFFFFF) = 0xffffffff  resources/disk.h: *122
DR_ALLOCUNIT     #define (LIB_BASE - 0*LIB_VECTSIZE) = 0xfffffffa
                 resources/disk.h: *105
DR_FREEUNIT      #define (LIB_BASE - 1*LIB_VECTSIZE) = 0xfffffff4
                 resources/disk.h: *106
DR_GETUNIT       #define (LIB_BASE - 2*LIB_VECTSIZE) = 0xffffffee
                 resources/disk.h: *107
DR_GETUNITID     #define (LIB_BASE - 4*LIB_VECTSIZE) = 0xffffffe2
                 resources/disk.h: *109
DR_GIVEUNIT      #define (LIB_BASE - 3*LIB_VECTSIZE) = 0xffffffe8
                 resources/disk.h: *108
DR_LASTCOMM      #define (DR_READUNITID) = 0xffffffdc  resources/disk.h: *112
DR_READUNITID    #define (LIB_BASE - 5*LIB_VECTSIZE) = 0xffffffdc
                 resources/disk.h: *110
DSKDMAOFF        #define 0x4000 = 0x00004000  resources/disk.h: *87
DSR_CPR          #define 6 = 0x00000006  devices/console.h: *86
DTAG_DIMS        #define 0x80001000 = 0x80001000  graphics/displayinfo.h: *38
DTAG_DISP        #define 0x80000000 = 0x80000000  graphics/displayinfo.h: *37
DTAG_MNTR        #define 0x80002000 = 0x80002000  graphics/displayinfo.h: *39
DTAG_NAME        #define 0x80003000 = 0x80003000  graphics/displayinfo.h: *40
DTB_FUTURE       #define 1 = 0x00000001  dos/datetime.h: *43
DTB_SUBST        #define 0 = 0x00000000  dos/datetime.h: *41
DTF_FUTURE       #define 2 = 0x00000002  dos/datetime.h: *44
DTF_SUBST        #define 1 = 0x00000001  dos/datetime.h: *42
DT_DEV           #define 0L = 0x00000000  rexx/rexxio.h: *73
DT_DIR           #define 1L = 0x00000001  rexx/rexxio.h: *74
DT_VOL           #define 2L = 0x00000002  rexx/rexxio.h: *75
DUALPF           #define 0x0400 = 0x00000400  graphics/view.h: *96
DVPB_ASSIGN      #define 1 = 0x00000001  dos/dosextens.h: *420
DVPB_UNLOCK      #define 0 = 0x00000000  dos/dosextens.h: *418
DVPF_ASSIGN      #define (1L << DVPB_ASSIGN) = 0x00000002
                 dos/dosextens.h: *421
DVPF_UNLOCK      #define (1L << DVPB_UNLOCK) = 0x00000001
                 dos/dosextens.h: *419
DWidth           short int in struct ViewPort +0x0018 graphics/view.h: *50
DamageList       pointer to struct Region in struct Layer
         +0x009c graphics/clip.h: *60
DateStamp        structure tag size 0x000c dos/dos.h: *54, 72
                 dos/dosextens.h: 247, 336, 379
                 dos/datetime.h: 28
DateTime         structure tag size 0x001a dos/datetime.h: *27
Debug            char in struct GfxBase +0x00a1 graphics/gfxbase.h: *41
DebugData        pointer to void in struct ExecBase
         +0x0046 exec/execbase.h: *51
DebugEntry       pointer to void in struct ExecBase
         +0x0042 exec/execbase.h: *50
DefaultFont      pointer to struct TextFont in struct GfxBase
         +0x009a graphics/gfxbase.h: *38
DefaultTitle     pointer to unsigned char in struct Screen
         +0x001a intuition/screens.h: *111
DefaultTitle     pointer to unsigned char in struct NewScreen
         +0x0014 intuition/screens.h: *322
DefaultTitle     pointer to unsigned char in struct ExtNewScreen
         +0x0014 intuition/screens.h: *353
DeniseMaxDisplayColumn unsigned short int in struct MonitorSpec
         +0x0026 graphics/monitor.h: *35
DeniseMinDisplayColumn unsigned short int in struct MonitorSpec
         +0x0052 graphics/monitor.h: *48
Depth            unsigned char in struct BitMap +0x0005 graphics/gfx.h: *53
Depth            short int in struct Image +0x0008 intuition/intuition.h: *625
Depth            short int in struct NewScreen
         +0x0008 intuition/screens.h: *312
Depth            short int in struct ExtNewScreen
         +0x0008 intuition/screens.h: *348
Depth            short int in struct VSprite +0x001e graphics/gels.h: *100
Descendant       pointer to struct Window in struct Window
         +0x0046 intuition/intuition.h: *844
DestAddr         short int in union (no tag)  +0x0000 graphics/copper.h: *37
DestData         short int in union (no tag)  +0x0000 graphics/copper.h: *42
DetailPen        unsigned char in struct Window
         +0x0062 intuition/intuition.h: *859
DetailPen        unsigned char in struct NewWindow
         +0x0008 intuition/intuition.h: *979
DetailPen        unsigned char in struct ExtNewWindow
         +0x0008 intuition/intuition.h: *1049
DetailPen        unsigned char in struct Screen
         +0x014a intuition/screens.h: *137
DetailPen        unsigned char in struct NewScreen
         +0x000a intuition/screens.h: *314
DetailPen        unsigned char in struct ExtNewScreen
         +0x000a intuition/screens.h: *349
DetailPen        unsigned char in struct (no tag)
         +0x0000 intuition/cghooks.h: *53
DevInfo          structure tag size 0x002c dos/dosextens.h: *345
DevProc          structure tag size 0x0010 dos/dosextens.h: *410
Device           structure tag size 0x0022 exec/devices.h: *26
                 exec/io.h: 22, 31
                 devices/clipboard.h: 45
                 devices/printer.h: 144, 158
DeviceData       structure tag size 0x0034 devices/prtbase.h: *51, 66
DeviceList       struct List(size 0x000e bytes) in struct ExecBase
         +0x015e exec/execbase.h: *88
DeviceList       structure tag size 0x002c dos/dosextens.h: *331
DeviceNode       structure tag size 0x002c dos/filehandler.h: *101
DiagArea         structure tag size 0x000e libraries/configregs.h: *237
DimensionInfo    structure tag size 0x0058 graphics/displayinfo.h: *92
DiscResource     structure tag size 0x0094 resources/disk.h: *50
DiscResourceUnit structure tag size 0x0056 resources/disk.h: *43, 52
DiskFontHeader   structure tag size 0x006a libraries/diskfont.h: *64
DiskObject       structure tag size 0x004e workbench/workbench.h: *62
DispCount        unsigned long int in struct ExecBase
         +0x011c exec/execbase.h: *66
DispCount        short int in struct StringInfo
         +0x0012 intuition/intuition.h: *536
DispPos          short int in struct StringInfo
         +0x000c intuition/intuition.h: *531
DisplayClip      struct Rectangle(size 0x0008 bytes) in struct ViewPortExtra
         +0x001c graphics/view.h: *83
DisplayCompatible unsigned long int in struct MonitorSpec
         +0x0054 graphics/monitor.h: *49
DisplayFlags     unsigned short int in struct GfxBase
         +0x00ce graphics/gfxbase.h: *53
DisplayID        unsigned long int in struct QueryHeader
         +0x0004 graphics/displayinfo.h: *45
DisplayInfo      structure tag size 0x0030 graphics/displayinfo.h: *50
DisplayInfoDataBase struct List(size 0x000e bytes) in struct MonitorSpec
         +0x0058 graphics/monitor.h: *50
DisplayInfoDataBase pointer to void in struct GfxBase
         +0x0196 graphics/gfxbase.h: *89
DisplayInfoDataBaseSemaphore struct SignalSemaphore(size 0x002e bytes) in
                 struct MonitorSpec
         +0x0066 graphics/monitor.h: *51
DisplayInfoHandle "APTR"  graphics/displayinfo.h: *33
DosEnvec         structure tag size 0x0050 dos/filehandler.h: *29
DosInfo          structure tag size 0x0070 dos/dosextens.h: *274
DosLibrary       structure tag size 0x0042 dos/dosextens.h: *228
DosList          structure tag size 0x002c dos/dosextens.h: *361, 414
DosPacket        structure tag size 0x0030 dos/dosextens.h: *110, 143
DoubleClick      struct timeval(size 0x0008 bytes) in struct Preferences
         +0x0014 intuition/preferences.h: *58
DrawCircle       macro (4 arguments)   graphics/gfxmacros.h: *43
DrawInfo         structure tag (size 0x0032 bytes)in struct impDraw
                 intuition/screens.h: *61
                 intuition/cghooks.h: 61
                 intuition/imageclass.h: 143, 161
DrawMode         char in struct RastPort +0x001c graphics/rastport.h: *68
DrawMode         unsigned char in struct IntuiText
         +0x0002 intuition/intuition.h: *573
DrawMode         unsigned char in struct Border
         +0x0006 intuition/intuition.h: *602
DrawPath         pointer to struct VSprite in struct VSprite
         +0x0008 graphics/gels.h: *81
DrawerData       structure tag size 0x003e workbench/workbench.h: *52, 71
DriveGeometry    structure tag size 0x0020 devices/trackdisk.h: *137
DspIns           pointer to struct CopList in struct ViewPort
         +0x0008 graphics/view.h: *46
DxOffset         short int in struct ViewPort +0x001c graphics/view.h: *51
DxOffset         short int in struct View +0x000e graphics/view.h: *63
DyOffset         short int in struct CopList +0x0020 graphics/copper.h: *74
DyOffset         short int in struct ViewPort +0x001e graphics/view.h: *51
DyOffset         short int in struct View +0x000c graphics/view.h: *63


2.0 IncludeXREF: E

eac_Entries      unsigned long int in struct ExAllControl
         +0x0000 dos/exall.h: *60
eac_LastKey      unsigned long int in struct ExAllControl
         +0x0004 dos/exall.h: *61
eac_MatchFunc    pointer to struct Hook in struct ExAllControl
         +0x000c dos/exall.h: *63
eac_MatchString pointer to unsigned char in struct ExAllControl
         +0x0008 dos/exall.h: *62
eb_Private01     unsigned char in struct ExpansionBase
         +0x0023 libraries/expansionbase.h: *50
eb_Private02     unsigned long int in struct ExpansionBase
         +0x0024 libraries/expansionbase.h: *51
eb_Private03     unsigned long int in struct ExpansionBase
         +0x0028 libraries/expansionbase.h: *52
eb_Private04     struct CurrentBinding(size 0x0010 bytes) in struct
                 ExpansionBase
         +0x002c libraries/expansionbase.h: *53
eb_Private05     struct List(size 0x000e bytes) in struct ExpansionBase
         +0x003c libraries/expansionbase.h: *54
ec_BaseAddress   unsigned char in struct ExpansionControl
         +0x0002 libraries/configregs.h: *74
ec_Interrupt     unsigned char in struct ExpansionControl
         +0x0000 libraries/configregs.h: *72
ec_Reserved14    unsigned char in struct ExpansionControl
         +0x0004 libraries/configregs.h: *76
ec_Reserved15    unsigned char in struct ExpansionControl
         +0x0005 libraries/configregs.h: *77
ec_Reserved16    unsigned char in struct ExpansionControl
         +0x0006 libraries/configregs.h: *78
ec_Reserved17    unsigned char in struct ExpansionControl
         +0x0007 libraries/configregs.h: *79
ec_Reserved18    unsigned char in struct ExpansionControl
         +0x0008 libraries/configregs.h: *80
ec_Reserved19    unsigned char in struct ExpansionControl
         +0x0009 libraries/configregs.h: *81
ec_Reserved1a    unsigned char in struct ExpansionControl
         +0x000a libraries/configregs.h: *82
ec_Reserved1b    unsigned char in struct ExpansionControl
         +0x000b libraries/configregs.h: *83
ec_Reserved1c    unsigned char in struct ExpansionControl
         +0x000c libraries/configregs.h: *84
ec_Reserved1d    unsigned char in struct ExpansionControl
         +0x000d libraries/configregs.h: *85
ec_Reserved1e    unsigned char in struct ExpansionControl
         +0x000e libraries/configregs.h: *86
ec_Reserved1f    unsigned char in struct ExpansionControl
         +0x000f libraries/configregs.h: *87
ec_Shutup        unsigned char in struct ExpansionControl
         +0x0003 libraries/configregs.h: *75
ec_Z3_HighBase   unsigned char in struct ExpansionControl
         +0x0001 libraries/configregs.h: *73
ed_Comment       pointer to unsigned char in struct ExAllData
         +0x0020 dos/exall.h: *46
ed_Days          unsigned long int in struct ExAllData +0x0014 dos/exall.h: *43
ed_Mins          unsigned long int in struct ExAllData +0x0018 dos/exall.h: *44
ed_Name          pointer to unsigned char in struct ExAllData
         +0x0004 dos/exall.h: *39
ed_Next          pointer to struct ExAllData in struct ExAllData
         +0x0000 dos/exall.h: *38
ed_Prot          unsigned long int in struct ExAllData +0x0010 dos/exall.h: *42
ed_Size          unsigned long int in struct ExAllData +0x000c dos/exall.h: *41
ed_Ticks         unsigned long int in struct ExAllData +0x001c dos/exall.h: *45
ed_Type          long int in struct ExAllData +0x0008 dos/exall.h: *40
er_Flags         unsigned char in struct ExpansionRom
         +0x0002 libraries/configregs.h: *51
er_InitDiagVec   unsigned short int in struct ExpansionRom
         +0x000a libraries/configregs.h: *55
er_Manufacturer unsigned short int in struct ExpansionRom
         +0x0004 libraries/configregs.h: *53
er_Product       unsigned char in struct ExpansionRom
         +0x0001 libraries/configregs.h: *50
er_Reserved03    unsigned char in struct ExpansionRom
         +0x0003 libraries/configregs.h: *52
er_Reserved0c    unsigned char in struct ExpansionRom
         +0x000c libraries/configregs.h: *56
er_Reserved0d    unsigned char in struct ExpansionRom
         +0x000d libraries/configregs.h: *57
er_Reserved0e    unsigned char in struct ExpansionRom
         +0x000e libraries/configregs.h: *58
er_Reserved0f    unsigned char in struct ExpansionRom
         +0x000f libraries/configregs.h: *59
er_SerialNumber unsigned long int in struct ExpansionRom
         +0x0006 libraries/configregs.h: *54
er_Type          unsigned char in struct ExpansionRom
         +0x0000 libraries/configregs.h: *49
es_Flags         unsigned long int in struct EasyStruct
         +0x0004 intuition/intuition.h: *1253
es_GadgetFormat pointer to unsigned char in struct EasyStruct
         +0x0010 intuition/intuition.h: *1256
es_StructSize    unsigned long int in struct EasyStruct
         +0x0000 intuition/intuition.h: *1252
es_TextFormat    pointer to unsigned char in struct EasyStruct
         +0x000c intuition/intuition.h: *1255
es_Title         pointer to unsigned char in struct EasyStruct
         +0x0008 intuition/intuition.h: *1254
estr_Nums        pointer to long int in struct ErrorString
         +0x0000 dos/dosextens.h: *219
estr_Strings     pointer to unsigned char in struct ErrorString
         +0x0004 dos/dosextens.h: *220
ev_hi            unsigned long int in struct EClockVal
         +0x0000 devices/timer.h: *33
ev_lo            unsigned long int in struct EClockVal
         +0x0004 devices/timer.h: *34
ex_CacheControl unsigned long int in struct ExecBase
         +0x023c exec/execbase.h: *137
ex_EClockFrequency unsigned long int in struct ExecBase
         +0x0238 exec/execbase.h: *136
ex_MMULock       pointer to void in struct ExecBase
         +0x0258 exec/execbase.h: *144
ex_Pad0          unsigned short int in struct ExecBase
         +0x022e exec/execbase.h: *128
ex_PoolThreshold unsigned long int in struct ExecBase
         +0x0248 exec/execbase.h: *141
ex_PublicPool    struct MinList(size 0x000c bytes) in struct ExecBase
         +0x024c exec/execbase.h: *142
ex_PuddleSize    unsigned long int in struct ExecBase
         +0x0244 exec/execbase.h: *140
ex_RamLibPrivate pointer to void in struct ExecBase
         +0x0234 exec/execbase.h: *130
ex_Reserved      array [12] of unsigned char in struct ExecBase
         +0x025c exec/execbase.h: *146
ex_Reserved0     unsigned long int in struct ExecBase
         +0x0230 exec/execbase.h: *129
ex_TaskID        unsigned long int in struct ExecBase
         +0x0240 exec/execbase.h: *138
exp              #define IEEEDPExp  libraries/mathffp.h: *45
                 libraries/mathieeedp.h: *45
ext_size         unsigned char in struct Preferences
         +0x00e7 intuition/preferences.h: *127
E                #define ((float) 2.718281828459045)  libraries/mathffp.h: *22
                 libraries/mathieeedp.h: 22
EBB_BADMEM       #define 2 = 0x00000002  libraries/expansionbase.h: *72
EBB_CLOGGED      #define 0 = 0x00000000  libraries/expansionbase.h: *68
EBB_DOSFLAG      #define 3 = 0x00000003  libraries/expansionbase.h: *74
EBB_KICKBACK33   #define 4 = 0x00000004  libraries/expansionbase.h: *76
EBB_KICKBACK36   #define 5 = 0x00000005  libraries/expansionbase.h: *78
EBB_SHORTMEM     #define 1 = 0x00000001  libraries/expansionbase.h: *70
EBB_SILENTSTART  #define 6 = 0x00000006  libraries/expansionbase.h: *83
EBF_BADMEM       #define (1<<2) = 0x00000004  libraries/expansionbase.h: *73
EBF_CLOGGED      #define (1<<0) = 0x00000001  libraries/expansionbase.h: *69
EBF_DOSFLAG      #define (1<<3) = 0x00000008  libraries/expansionbase.h: *75
EBF_KICKBACK33   #define (1<<4) = 0x00000010  libraries/expansionbase.h: *77
EBF_KICKBACK36   #define (1<<5) = 0x00000020  libraries/expansionbase.h: *79
EBF_SHORTMEM     #define (1<<1) = 0x00000002  libraries/expansionbase.h: *71
EBF_SILENTSTART  #define (1<<6) = 0x00000040  libraries/expansionbase.h: *84
ECIB_INT2PEND    #define 4 = 0x00000004  libraries/configregs.h: *175
ECIB_INT6PEND    #define 5 = 0x00000005  libraries/configregs.h: *176
ECIB_INT7PEND    #define 6 = 0x00000006  libraries/configregs.h: *177
ECIB_INTENA      #define 1 = 0x00000001  libraries/configregs.h: *173
ECIB_INTERRUPTING #define 7 = 0x00000007  libraries/configregs.h: *178
ECIB_RESET       #define 3 = 0x00000003  libraries/configregs.h: *174
ECIF_INT2PEND    #define (1<<4) = 0x00000010  libraries/configregs.h: *182
ECIF_INT6PEND    #define (1<<5) = 0x00000020  libraries/configregs.h: *183
ECIF_INT7PEND    #define (1<<6) = 0x00000040  libraries/configregs.h: *184
ECIF_INTENA      #define (1<<1) = 0x00000002  libraries/configregs.h: *180
ECIF_INTERRUPTING #define (1<<7) = 0x00000080  libraries/configregs.h: *185
ECIF_RESET       #define (1<<3) = 0x00000008  libraries/configregs.h: *181
ECOFFSET         macro (1 argument)   libraries/configregs.h: *205
ECS_SPECIFIC     #define  graphics/view.h: *15
                 hardware/custom.h: 144
EC_MEMADDR       macro (1 argument)   libraries/configregs.h: *200
EClockVal        structure tag size 0x0008 devices/timer.h: *32
ED_COMMENT       #define 6 = 0x00000006  dos/exall.h: *31
ED_DATE          #define 5 = 0x00000005  dos/exall.h: *30
ED_NAME          #define 1 = 0x00000001  dos/exall.h: *26
ED_PROTECTION    #define 4 = 0x00000004  dos/exall.h: *29
ED_SIZE          #define 3 = 0x00000003  dos/exall.h: *28
ED_TYPE          #define 2 = 0x00000002  dos/exall.h: *27
EE_BADMEM        #define 44 = 0x0000002c  libraries/expansionbase.h: *65
EE_LASTBOARD     #define 40 = 0x00000028  libraries/expansionbase.h: *61
EE_NOBOARD       #define 43 = 0x0000002b  libraries/expansionbase.h: *64
EE_NOEXPANSION   #define 41 = 0x00000029  libraries/expansionbase.h: *62
EE_NOMEMORY      #define 42 = 0x0000002a  libraries/expansionbase.h: *63
EE_OK            #define 0 = 0x00000000  libraries/expansionbase.h: *60
EIGHT_LPI        #define 0x200 = 0x00000200  intuition/preferences.h: *169
ELITE            #define 0x400 = 0x00000400  intuition/preferences.h: *160
ENDGADGET        #define GACT_ENDGADGET = 0x00000004
                 intuition/iobsolete.h: *71
EO_BADFORMAT     #define (0x0009) = 0x00000009  intuition/sghooks.h: *81
EO_BIGCHANGE     #define (0x000A) = 0x0000000a  intuition/sghooks.h: *83
EO_CLEAR         #define (0x000C) = 0x0000000c  intuition/sghooks.h: *87
EO_DELBACKWARD   #define (0x0002) = 0x00000002  intuition/sghooks.h: *67
EO_DELFORWARD    #define (0x0003) = 0x00000003  intuition/sghooks.h: *69
EO_ENTER         #define (0x0005) = 0x00000005  intuition/sghooks.h: *73
EO_INSERTCHAR    #define (0x0008) = 0x00000008  intuition/sghooks.h: *79
EO_MOVECURSOR    #define (0x0004) = 0x00000004  intuition/sghooks.h: *71
EO_NOOP          #define (0x0001) = 0x00000001  intuition/sghooks.h: *65
EO_REPLACECHAR   #define (0x0007) = 0x00000007  intuition/sghooks.h: *77
EO_RESET         #define (0x0006) = 0x00000006  intuition/sghooks.h: *75
EO_SPECIAL       #define (0x000D) = 0x0000000d  intuition/sghooks.h: *89
EO_UNDO          #define (0x000B) = 0x0000000b  intuition/sghooks.h: *85
EPSON            #define 0x07 = 0x00000007  intuition/preferences.h: *199
EPSON_JX_80      #define 0x08 = 0x00000008  intuition/preferences.h: *200
ERFB_EXTENDED    #define 5 = 0x00000005  libraries/configregs.h: *160
ERFB_MEMSPACE    #define 7 = 0x00000007  libraries/configregs.h: *154
ERFB_NOSHUTUP    #define 6 = 0x00000006  libraries/configregs.h: *157
ERFB_ZORRO_III   #define 4 = 0x00000004  libraries/configregs.h: *164
ERFF_EXTENDED    #define (1<<5) = 0x00000020  libraries/configregs.h: *159
ERFF_MEMSPACE    #define (1<<7) = 0x00000080  libraries/configregs.h: *153
ERFF_NOSHUTUP    #define (1<<6) = 0x00000040  libraries/configregs.h: *156
ERFF_ZORRO_III   #define (1<<4) = 0x00000010  libraries/configregs.h: *163
EROFFSET         macro (1 argument)   libraries/configregs.h: *203
ERR10_001        #define (ERRC_MSG+1) = 0x00000001  rexx/errors.h: *16
ERR10_002        #define (ERRC_MSG+2) = 0x00000002  rexx/errors.h: *17
ERR10_003        #define (ERRC_MSG+3) = 0x00000003  rexx/errors.h: *18
ERR10_004        #define (ERRC_MSG+4) = 0x00000004  rexx/errors.h: *19
ERR10_005        #define (ERRC_MSG+5) = 0x00000005  rexx/errors.h: *20
ERR10_006        #define (ERRC_MSG+6) = 0x00000006  rexx/errors.h: *21
ERR10_007        #define (ERRC_MSG+7) = 0x00000007  rexx/errors.h: *22
ERR10_008        #define (ERRC_MSG+8) = 0x00000008  rexx/errors.h: *23
ERR10_009        #define (ERRC_MSG+9) = 0x00000009  rexx/errors.h: *24
ERR10_010        #define (ERRC_MSG+10) = 0x0000000a  rexx/errors.h: *26
ERR10_011        #define (ERRC_MSG+11) = 0x0000000b  rexx/errors.h: *27
ERR10_012        #define (ERRC_MSG+12) = 0x0000000c  rexx/errors.h: *28
ERR10_013        #define (ERRC_MSG+13) = 0x0000000d  rexx/errors.h: *29
ERR10_014        #define (ERRC_MSG+14) = 0x0000000e  rexx/errors.h: *30
ERR10_015        #define (ERRC_MSG+15) = 0x0000000f  rexx/errors.h: *31
ERR10_016        #define (ERRC_MSG+16) = 0x00000010  rexx/errors.h: *32
ERR10_017        #define (ERRC_MSG+17) = 0x00000011  rexx/errors.h: *33
ERR10_018        #define (ERRC_MSG+18) = 0x00000012  rexx/errors.h: *34
ERR10_019        #define (ERRC_MSG+19) = 0x00000013  rexx/errors.h: *35
ERR10_020        #define (ERRC_MSG+20) = 0x00000014  rexx/errors.h: *37
ERR10_021        #define (ERRC_MSG+21) = 0x00000015  rexx/errors.h: *38
ERR10_022        #define (ERRC_MSG+22) = 0x00000016  rexx/errors.h: *39
ERR10_023        #define (ERRC_MSG+23) = 0x00000017  rexx/errors.h: *40
ERR10_024        #define (ERRC_MSG+24) = 0x00000018  rexx/errors.h: *41
ERR10_025        #define (ERRC_MSG+25) = 0x00000019  rexx/errors.h: *42
ERR10_026        #define (ERRC_MSG+26) = 0x0000001a  rexx/errors.h: *43
ERR10_027        #define (ERRC_MSG+27) = 0x0000001b  rexx/errors.h: *44
ERR10_028        #define (ERRC_MSG+28) = 0x0000001c  rexx/errors.h: *45
ERR10_029        #define (ERRC_MSG+29) = 0x0000001d  rexx/errors.h: *46
ERR10_030        #define (ERRC_MSG+30) = 0x0000001e  rexx/errors.h: *48
ERR10_031        #define (ERRC_MSG+31) = 0x0000001f  rexx/errors.h: *49
ERR10_032        #define (ERRC_MSG+32) = 0x00000020  rexx/errors.h: *50
ERR10_033        #define (ERRC_MSG+33) = 0x00000021  rexx/errors.h: *51
ERR10_034        #define (ERRC_MSG+34) = 0x00000022  rexx/errors.h: *52
ERR10_035        #define (ERRC_MSG+35) = 0x00000023  rexx/errors.h: *53
ERR10_036        #define (ERRC_MSG+36) = 0x00000024  rexx/errors.h: *54
ERR10_037        #define (ERRC_MSG+37) = 0x00000025  rexx/errors.h: *55
ERR10_038        #define (ERRC_MSG+38) = 0x00000026  rexx/errors.h: *56
ERR10_039        #define (ERRC_MSG+39) = 0x00000027  rexx/errors.h: *57
ERR10_040        #define (ERRC_MSG+40) = 0x00000028  rexx/errors.h: *59
ERR10_041        #define (ERRC_MSG+41) = 0x00000029  rexx/errors.h: *60
ERR10_042        #define (ERRC_MSG+42) = 0x0000002a  rexx/errors.h: *61
ERR10_043        #define (ERRC_MSG+43) = 0x0000002b  rexx/errors.h: *62
ERR10_044        #define (ERRC_MSG+44) = 0x0000002c  rexx/errors.h: *63
ERR10_045        #define (ERRC_MSG+45) = 0x0000002d  rexx/errors.h: *64
ERR10_046        #define (ERRC_MSG+46) = 0x0000002e  rexx/errors.h: *65
ERR10_047        #define (ERRC_MSG+47) = 0x0000002f  rexx/errors.h: *66
ERR10_048        #define (ERRC_MSG+48) = 0x00000030  rexx/errors.h: *67
ERRC_MSG         #define 0 = 0x00000000  rexx/errors.h: *15
ERROR_ACTION_NOT_KNOWN #define 209 = 0x000000d1  dos/dos.h: *165
ERROR_BAD_HUNK   #define 235 = 0x000000eb  dos/dos.h: *187
ERROR_BAD_NUMBER #define 115 = 0x00000073  dos/dos.h: *150
ERROR_BAD_STREAM_NAME #define 206 = 0x000000ce  dos/dos.h: *163
ERROR_BAD_TEMPLATE #define 114 = 0x00000072  dos/dos.h: *149
ERROR_BREAK      #define 304 = 0x00000130  dos/dosasl.h: *149
ERROR_BUFFER_OVERFLOW #define 303 = 0x0000012f  dos/dosasl.h: *148
ERROR_COMMENT_TOO_BIG #define 220 = 0x000000dc  dos/dos.h: *176
ERROR_DELETE_PROTECTED #define 222 = 0x000000de  dos/dos.h: *178
ERROR_DEVICE_NOT_MOUNTED #define 218 = 0x000000da  dos/dos.h: *174
ERROR_DIRECTORY_NOT_EMPTY #define 216 = 0x000000d8  dos/dos.h: *172
ERROR_DIR_NOT_FOUND #define 204 = 0x000000cc  dos/dos.h: *161
ERROR_DISK_FULL  #define 221 = 0x000000dd  dos/dos.h: *177
ERROR_DISK_NOT_VALIDATED #define 213 = 0x000000d5  dos/dos.h: *169
ERROR_DISK_WRITE_PROTECTED #define 214 = 0x000000d6  dos/dos.h: *170
ERROR_FILE_NOT_OBJECT #define 121 = 0x00000079  dos/dos.h: *156
ERROR_INVALID_COMPONENT_NAME #define 210 = 0x000000d2  dos/dos.h: *166
ERROR_INVALID_LOCK #define 211 = 0x000000d3  dos/dos.h: *167
ERROR_INVALID_RESIDENT_LIBRARY #define 122 = 0x0000007a  dos/dos.h: *157
ERROR_IS_SOFT_LINK #define 233 = 0x000000e9  dos/dos.h: *185
ERROR_KEY_NEEDS_ARG #define 117 = 0x00000075  dos/dos.h: *152
ERROR_LINE_TOO_LONG #define 120 = 0x00000078  dos/dos.h: *155
ERROR_LOCK_COLLISION #define 241 = 0x000000f1  dos/dos.h: *190
ERROR_LOCK_TIMEOUT #define 242 = 0x000000f2  dos/dos.h: *191
ERROR_NOT_A_DOS_DISK #define 225 = 0x000000e1  dos/dos.h: *181
ERROR_NOT_EXECUTABLE #define 305 = 0x00000131  dos/dosasl.h: *150
ERROR_NOT_IMPLEMENTED #define 236 = 0x000000ec  dos/dos.h: *188
ERROR_NO_DEFAULT_DIR #define 201 = 0x000000c9  dos/dos.h: *158
ERROR_NO_DISK    #define 226 = 0x000000e2  dos/dos.h: *182
ERROR_NO_FREE_STORE #define 103 = 0x00000067  dos/dos.h: *147
ERROR_NO_MORE_ENTRIES #define 232 = 0x000000e8  dos/dos.h: *183
ERROR_OBJECT_EXISTS #define 203 = 0x000000cb  dos/dos.h: *160
ERROR_OBJECT_IN_USE #define 202 = 0x000000ca  dos/dos.h: *159
ERROR_OBJECT_LINKED #define 234 = 0x000000ea  dos/dos.h: *186
ERROR_OBJECT_NOT_FOUND #define 205 = 0x000000cd  dos/dos.h: *162
ERROR_OBJECT_TOO_LARGE #define 207 = 0x000000cf  dos/dos.h: *164
ERROR_OBJECT_WRONG_TYPE #define 212 = 0x000000d4  dos/dos.h: *168
ERROR_READ_PROTECTED #define 224 = 0x000000e0  dos/dos.h: *180
ERROR_RECORD_NOT_LOCKED #define 240 = 0x000000f0  dos/dos.h: *189
ERROR_RENAME_ACROSS_DEVICES #define 215 = 0x000000d7  dos/dos.h: *171
ERROR_REQUIRED_ARG_MISSING #define 116 = 0x00000074  dos/dos.h: *151
ERROR_SEEK_ERROR #define 219 = 0x000000db  dos/dos.h: *175
ERROR_TASK_TABLE_FULL #define 105 = 0x00000069  dos/dos.h: *148
ERROR_TOO_MANY_ARGS #define 118 = 0x00000076  dos/dos.h: *153
ERROR_TOO_MANY_LEVELS #define 217 = 0x000000d9  dos/dos.h: *173
ERROR_UNLOCK_ERROR #define 243 = 0x000000f3  dos/dos.h: *192
ERROR_UNMATCHED_QUOTES #define 119 = 0x00000077  dos/dos.h: *154
ERROR_WRITE_PROTECTED #define 223 = 0x000000df  dos/dos.h: *179
ERTB_CHAINEDCONFIG #define 3 = 0x00000003  libraries/configregs.h: *138
ERTB_DIAGVALID   #define 4 = 0x00000004  libraries/configregs.h: *137
ERTB_MEMLIST     #define 5 = 0x00000005  libraries/configregs.h: *136
ERTF_CHAINEDCONFIG #define (1<<3) = 0x00000008  libraries/configregs.h: *142
ERTF_DIAGVALID   #define (1<<4) = 0x00000010  libraries/configregs.h: *141
ERTF_MEMLIST     #define (1<<5) = 0x00000020  libraries/configregs.h: *140
ERT_MEMBIT       #define 0 = 0x00000000  libraries/configregs.h: *146
ERT_MEMMASK      #define 0x07 ;Bits 2-0  libraries/configregs.h: *145
ERT_MEMNEEDED    macro (1 argument)   libraries/configregs.h: *191
ERT_MEMSIZE      #define 3 = 0x00000003  libraries/configregs.h: *147
ERT_NEWBOARD     #define 0xc0 = 0x000000c0  libraries/configregs.h: *131
ERT_SLOTSNEEDED macro (1 argument)   libraries/configregs.h: *195
ERT_TYPEBIT      #define 6 = 0x00000006  libraries/configregs.h: *129
ERT_TYPEMASK     #define 0xc0 ;Bits 7-6  libraries/configregs.h: *128
ERT_TYPESIZE     #define 2 = 0x00000002  libraries/configregs.h: *130
ERT_Z3_SSBIT     #define 0 = 0x00000000  libraries/configregs.h: *167
ERT_Z3_SSMASK    #define 0x0F = 0x0000000f  libraries/configregs.h: *166
ERT_Z3_SSSIZE    #define 4 = 0x00000004  libraries/configregs.h: *168
ERT_ZORROII      #define ERT_NEWBOARD = 0x000000c0
                 libraries/configregs.h: *132
ERT_ZORROIII     #define 0x80 = 0x00000080  libraries/configregs.h: *133
ETD_CLEAR        #define (CMD_CLEAR|TDF_EXTCOM) = 0x00008005
                 devices/trackdisk.h: *109
ETD_FORMAT       #define (TD_FORMAT|TDF_EXTCOM) = 0x0000800b
                 devices/trackdisk.h: *107
ETD_MOTOR        #define (TD_MOTOR|TDF_EXTCOM) = 0x00008009
                 devices/trackdisk.h: *105
ETD_RAWREAD      #define (TD_RAWREAD|TDF_EXTCOM) = 0x00008010
                 devices/trackdisk.h: *110
ETD_RAWWRITE     #define (TD_RAWWRITE|TDF_EXTCOM) = 0x00008011
                 devices/trackdisk.h: *111
ETD_READ         #define (CMD_READ|TDF_EXTCOM) = 0x00008002
                 devices/trackdisk.h: *104
ETD_SEEK         #define (TD_SEEK|TDF_EXTCOM) = 0x0000800a
                 devices/trackdisk.h: *106
ETD_UPDATE       #define (CMD_UPDATE|TDF_EXTCOM) = 0x00008004
                 devices/trackdisk.h: *108
ETD_WRITE        #define (CMD_WRITE|TDF_EXTCOM) = 0x00008003
                 devices/trackdisk.h: *103
EVENTMAX         #define 10 = 0x0000000a  intuition/intuitionbase.h: *39
EXAMINE_BIT      #define 2 = 0x00000002  dos/dosasl.h: *140
EXCLUSIVE_LOCK   #define -1 = 0xffffffff  dos/dos.h: *51
EXEC_ALERTS_H    #define  exec/alerts.h: *2, 1
EXEC_DEVICES_H   #define  exec/devices.h: *2, 1
                 devices/trackdisk.h: 22
EXEC_ERRORS_H    #define  exec/errors.h: *2, 1
EXEC_EXECBASE_H  #define  exec/execbase.h: *2, 1
EXEC_EXEC_H      #define  exec/exec.h: *2
EXEC_INITIALIZERS_H #define  exec/initializers.h: *2, 1
EXEC_INTERRUPTS_H #define  exec/interrupts.h: *2, 1
                 exec/execbase.h: 19
                 graphics/gfxbase.h: 21
                 intuition/intuitionbase.h: 28
                 resources/disk.h: 27
EXEC_IO_H        #define  exec/io.h: *2, 1(2)
                 devices/audio.h: 15
                 devices/console.h: 19
                 devices/gameport.h: 19
                 devices/input.h: 15
                 devices/keyboard.h: 15
                 devices/narrator.h: 17
                 devices/parallel.h: 15
                 devices/serial.h: 15
                 devices/trackdisk.h: 18
EXEC_LIBRARIES_H #define  exec/libraries.h: *2, 1(2)
                 exec/execbase.h: 23
                 devices/prtbase.h: 27
                 dos/dosextens.h: 21
                 dos/dosasl.h: 17
                 graphics/gfxbase.h: 18
                 intuition/intuitionbase.h: 19
                 libraries/asl.h: 24
                 libraries/expansionbase.h: 19
                 libraries/mathlibrary.h: 17
                 resources/disk.h: 31
                 resources/misc.h: 19
                 rexx/storage.h: 31
EXEC_LISTS_H     #define  exec/lists.h: *2, 1(2)
                 exec/tasks.h: 19
                 exec/interrupts.h: 19
                 exec/semaphores.h: 19
                 exec/execbase.h: 15
                 devices/clipboard.h: 21
                 devices/keymap.h: 19
                 devices/printer.h: 23
                 devices/prtbase.h: 21
                 graphics/layers.h: 15
                 dos/dosasl.h: 21
                 graphics/gfxbase.h: 15
                 libraries/asl.h: 20
                 libraries/diskfont.h: 21
                 libraries/iffparse.h: 19
                 resources/disk.h: 19
                 resources/filesysres.h: 18
                 rexx/storage.h: 23
                 workbench/workbench.h: 23
EXEC_MEMORY_H    #define  exec/memory.h: *2, 1
EXEC_NODES_H     #define  exec/nodes.h: *2, 1(2)
                 exec/ports.h: 15
                 exec/lists.h: 15
                 exec/tasks.h: 15
                 exec/memory.h: 15
                 exec/interrupts.h: 15
                 exec/semaphores.h: 15
                 devices/clipboard.h: 18
                 devices/keymap.h: 16
                 devices/printer.h: 19
                 devices/prtbase.h: 18
                 utility/hooks.h: 19
                 graphics/gfxnodes.h: 15
                 dos/rdargs.h: 21
                 dos/var.h: 18
                 graphics/graphint.h: 15
                 libraries/configvars.h: 18
                 libraries/diskfont.h: 18
                 libraries/mathresource.h: 17
                 resources/filesysres.h: 15
                 rexx/storage.h: 19
                 workbench/workbench.h: 19
EXEC_PORTS_H     #define  exec/ports.h: *2, 1(2)
                 exec/semaphores.h: 23
                 exec/io.h: 15
                 devices/clipboard.h: 24
                 devices/conunit.h: 19
                 devices/printer.h: 27
                 devices/prtbase.h: 24
                 dos/dosextens.h: 18
                 graphics/text.h: 15
                 intuition/intuition.h: 43
                 dos/filehandler.h: 15
                 dos/notify.h: 21
                 workbench/startup.h: 19
                 libraries/iffparse.h: 22
                 resources/disk.h: 23
                 rexx/storage.h: 27
EXEC_RESIDENT_H  #define  exec/resident.h: *2, 1
EXEC_SEMAPHORES_H #define  exec/semaphores.h: *2, 1
                 dos/dosextens.h: 24
                 graphics/clip.h: 22
                 graphics/monitor.h: 15
                 graphics/layers.h: 19
                 libraries/expansionbase.h: 23
EXEC_TASKS_H     #define  exec/tasks.h: *2, 1(2)
                 exec/semaphores.h: 27
                 exec/execbase.h: 27
                 devices/prtbase.h: 30
                 dos/dosextens.h: 15
                 dos/notify.h: 25
                 workbench/workbench.h: 27
EXEC_TYPES_H     #define  exec/types.h: *2
                 exec/resident.h: 15
                 devices/prtgfx.h: 15
                 devices/scsidisk.h: 16
                 devices/bootblock.h: 15
                 devices/clipboard.h: 15
                 devices/console.h: 15
                 devices/conunit.h: 15
                 devices/gameport.h: 15
                 devices/hardblocks.h: 15
                 devices/printer.h: 15
                 devices/prtbase.h: 15
                 dos/dos.h: 15
                 intuition/intuition.h: 15
                 graphics/gfx.h: 15
                 graphics/clip.h: 15
                 utility/hooks.h: 15
                 graphics/view.h: 17
                 graphics/copper.h: 15
                 hardware/custom.h: 15
                 graphics/rastport.h: 15
                 utility/tagitem.h: 15
                 intuition/screens.h: 15
                 intuition/preferences.h: 15
                 dos/exall.h: 17
                 dos/notify.h: 17
                 dos/rdargs.h: 17
                 graphics/displayinfo.h: 15
                 graphics/gels.h: 15
                 graphics/gfxmacros.h: 15
                 graphics/regions.h: 15
                 graphics/scale.h: 15
                 graphics/sprite.h: 15
                 graphics/videocontrol.h: 15
                 hardware/cia.h: 16
                 intuition/cghooks.h: 15
                 intuition/gadgetclass.h: 15
                 intuition/intuitionbase.h: 15
                 intuition/sghooks.h: 15
                 libraries/asl.h: 16
                 workbench/startup.h: 15
                 libraries/commodities.h: 16
                 libraries/configregs.h: 16
                 libraries/configvars.h: 14
                 libraries/diskfont.h: 15
                 libraries/expansionbase.h: 15
                 libraries/gadtools.h: 17
                 libraries/iffparse.h: 16
                 resources/disk.h: 15
                 resources/misc.h: 15
                 rexx/storage.h: 15
                 workbench/workbench.h: 15
EXPANSIONNAME    #define "expansion.library"  libraries/expansion.h: *15
EXTENDED_MODE    #define 0x1000 = 0x00001000  graphics/view.h: *98
EXTEND_VSTRUCT   #define 0x1000 = 0x00001000  graphics/view.h: *86
EXTRAHALFBRITELACE_KEY #define 0x00000084 = 0x00000084
                 graphics/displayinfo.h: *176
EXTRAHALFBRITE_KEY #define 0x00000080 = 0x00000080
                 graphics/displayinfo.h: *175
EXTRA_HALFBRITE  #define 0x0080 = 0x00000080  graphics/view.h: *94
EXT_ABS          #define 2 = 0x00000002  dos/doshunks.h: *43
EXT_COMMON       #define 130 = 0x00000082  dos/doshunks.h: *46
EXT_DEF          #define 1 = 0x00000001  dos/doshunks.h: *42
EXT_DEXT16       #define 134 = 0x00000086  dos/doshunks.h: *50
EXT_DEXT32       #define 133 = 0x00000085  dos/doshunks.h: *49
EXT_DEXT8        #define 135 = 0x00000087  dos/doshunks.h: *51
EXT_REF16        #define 131 = 0x00000083  dos/doshunks.h: *47
EXT_REF32        #define 129 = 0x00000081  dos/doshunks.h: *45
EXT_REF8         #define 132 = 0x00000084  dos/doshunks.h: *48
EXT_RES          #define 3 = 0x00000003  dos/doshunks.h: *44
EXT_SYMB         #define 0 = 0x00000000  dos/doshunks.h: *41
EZ3_CONFIGAREA   #define 0x40000000 = 0x40000000  libraries/configregs.h: *119
EZ3_CONFIGAREAEND #define 0x7FFFFFFF = 0x7fffffff
                 libraries/configregs.h: *120
EZ3_EXPANSIONBASE #define 0xff000000 = 0xff000000
                 libraries/configregs.h: *110
EZ3_SIZEGRANULARITY #define 0x00080000 = 0x00080000
                 libraries/configregs.h: *121
E_EXPANSIONBASE  #define 0x00e80000 = 0x00e80000  libraries/configregs.h: *109
E_EXPANSIONSIZE  #define 0x00080000 = 0x00080000  libraries/configregs.h: *112
E_EXPANSIONSLOTS #define 8 = 0x00000008  libraries/configregs.h: *113
E_MEMORYBASE     #define 0x00200000 = 0x00200000  libraries/configregs.h: *115
E_MEMORYSIZE     #define 0x00800000 = 0x00800000  libraries/configregs.h: *116
E_MEMORYSLOTS    #define 128 = 0x00000080  libraries/configregs.h: *117
E_SLOTMASK       #define 0xffff = 0x0000ffff  libraries/configregs.h: *103
E_SLOTSHIFT      #define 16 = 0x00000010  libraries/configregs.h: *104
E_SLOTSIZE       #define 0x10000 = 0x00010000  libraries/configregs.h: *102
EasyStruct       structure tag size 0x0014 intuition/intuition.h: *1251
EditHook         pointer to struct Hook in struct StringExtend
         +0x000c intuition/sghooks.h: *27
EditOp           unsigned short int in struct SGWork
         +0x002a intuition/sghooks.h: *50
Elapsed          unsigned short int in struct ExecBase
         +0x0122 exec/execbase.h: *68
EnableCLI        short int in struct Preferences
         +0x007c intuition/preferences.h: *80
ErrorString      structure tag size 0x0008 dos/dosextens.h: *218, 235
ExAllControl     structure tag size 0x0010 dos/exall.h: *59
ExAllData        structure tag size 0x0024 dos/exall.h: *37, 38
ExecBase         structure tag size 0x0268 exec/execbase.h: *36
ExecBase         pointer to unsigned long int in struct GfxBase
         +0x01a2 graphics/gfxbase.h: *92
ExecMessage      struct Message(size 0x0014 bytes) in struct IntuiMessage
         +0x0000 intuition/intuition.h: *679
ExpansionBase    structure tag size 0x0058 libraries/expansionbase.h: *46
ExpansionControl structure tag size 0x0010 libraries/configregs.h: *71
ExpansionRom     structure tag size 0x0010 libraries/configregs.h: *48
                 libraries/configvars.h: 36
ExtData          pointer to unsigned char in struct Window
         +0x0074 intuition/intuition.h: *883
ExtData          pointer to unsigned char in struct Screen
         +0x0152 intuition/screens.h: *147
ExtNewScreen     structure tag size 0x0024 intuition/screens.h: *346
ExtNewWindow     structure tag size 0x0034 intuition/intuition.h: *1044
ExtendedModes    unsigned char in struct ViewPort +0x0023 graphics/view.h: *54
ExtendedNode     structure tag size 0x0018 graphics/gfxnodes.h: *19
                 graphics/monitor.h: 29, 144
                 graphics/view.h: 72, 81
Extension        pointer to struct StringExtend in struct StringInfo
         +0x0018 intuition/intuition.h: *546
Extension        pointer to struct TagItem in struct ExtNewWindow
         +0x0030 intuition/intuition.h: *1082
Extension        pointer to struct TagItem in struct ExtNewScreen
         +0x0020 intuition/screens.h: *357


2.0 IncludeXREF: F

fabs             #define IEEEDPAbs  libraries/mathffp.h: *35
                 libraries/mathieeedp.h: *35
fatten_count     char in struct Layer_Info +0x005a graphics/layers.h: *44
fc_FileName      array [256] of char in struct FontContents
         +0x0000 libraries/diskfont.h: *31
fc_Flags         unsigned char in struct FontContents
         +0x0103 libraries/diskfont.h: *34
fc_Style         unsigned char in struct FontContents
         +0x0102 libraries/diskfont.h: *33
fc_YSize         unsigned short int in struct FontContents
         +0x0100 libraries/diskfont.h: *32
fch_FileID       unsigned short int in struct FontContentsHeader
         +0x0000 libraries/diskfont.h: *55
fch_NumEntries   unsigned short int in struct FontContentsHeader
         +0x0002 libraries/diskfont.h: *56
fh_Arg1          #define fh_Args  dos/dosextens.h: *104
fh_Arg2          long int in struct FileHandle +0x0028 dos/dosextens.h: *105
fh_Args          long int in struct FileHandle +0x0024 dos/dosextens.h: *103
fh_Buf           long int in struct FileHandle +0x000c dos/dosextens.h: *96
fh_End           long int in struct FileHandle +0x0014 dos/dosextens.h: *98
fh_Func1         #define fh_Funcs  dos/dosextens.h: *100
fh_Func2         long int in struct FileHandle +0x001c dos/dosextens.h: *101
fh_Func3         long int in struct FileHandle +0x0020 dos/dosextens.h: *102
fh_Funcs         long int in struct FileHandle +0x0018 dos/dosextens.h: *99
fh_Link          pointer to struct Message in struct FileHandle
         +0x0000 dos/dosextens.h: *92
fh_Port          pointer to struct MsgPort in struct FileHandle
         +0x0004 dos/dosextens.h: *93
fh_Pos           long int in struct FileHandle +0x0010 dos/dosextens.h: *97
fh_Type          pointer to struct MsgPort in struct FileHandle
         +0x0008 dos/dosextens.h: *94
fhb_ChkSum       long int in struct FileSysHeaderBlock
         +0x0008 devices/hardblocks.h: *155
fhb_DosType      unsigned long int in struct FileSysHeaderBlock
         +0x0020 devices/hardblocks.h: *160
fhb_Flags        unsigned long int in struct FileSysHeaderBlock
         +0x0014 devices/hardblocks.h: *158
fhb_GlobalVec    long int in struct FileSysHeaderBlock
         +0x004c devices/hardblocks.h: *177
fhb_Handler      unsigned long int in struct FileSysHeaderBlock
         +0x0038 devices/hardblocks.h: *170
fhb_HostID       unsigned long int in struct FileSysHeaderBlock
         +0x000c devices/hardblocks.h: *156
fhb_ID           unsigned long int in struct FileSysHeaderBlock
         +0x0000 devices/hardblocks.h: *153
fhb_Lock         unsigned long int in struct FileSysHeaderBlock
         +0x0034 devices/hardblocks.h: *169
fhb_Next         unsigned long int in struct FileSysHeaderBlock
         +0x0010 devices/hardblocks.h: *157
fhb_PatchFlags   unsigned long int in struct FileSysHeaderBlock
         +0x0028 devices/hardblocks.h: *163
fhb_Priority     long int in struct FileSysHeaderBlock
         +0x0040 devices/hardblocks.h: *172
fhb_Reserved1    array [2] of unsigned long int in struct FileSysHeaderBlock
         +0x0018 devices/hardblocks.h: *159
fhb_Reserved2    array [23] of unsigned long int in struct FileSysHeaderBlock
         +0x0050 devices/hardblocks.h: *178
fhb_Reserved3    array [21] of unsigned long int in struct FileSysHeaderBlock
         +0x00ac devices/hardblocks.h: *179
fhb_SegListBlocks long int in struct FileSysHeaderBlock
         +0x0048 devices/hardblocks.h: *174
fhb_StackSize    unsigned long int in struct FileSysHeaderBlock
         +0x003c devices/hardblocks.h: *171
fhb_Startup      long int in struct FileSysHeaderBlock
         +0x0044 devices/hardblocks.h: *173
fhb_SummedLongs unsigned long int in struct FileSysHeaderBlock
         +0x0004 devices/hardblocks.h: *154
fhb_Task         unsigned long int in struct FileSysHeaderBlock
         +0x0030 devices/hardblocks.h: *168
fhb_Type         unsigned long int in struct FileSysHeaderBlock
         +0x002c devices/hardblocks.h: *167
fhb_Version      unsigned long int in struct FileSysHeaderBlock
         +0x0024 devices/hardblocks.h: *162
fib_Comment      array [80] of char in struct FileInfoBlock
         +0x0090 dos/dos.h: *73
fib_Date         struct DateStamp(size 0x000c bytes) in struct FileInfoBlock
         +0x0084 dos/dos.h: *72
fib_DirEntryType long int in struct FileInfoBlock +0x0004 dos/dos.h: *65
fib_DiskKey      long int in struct FileInfoBlock +0x0000 dos/dos.h: *64
fib_EntryType    long int in struct FileInfoBlock +0x0078 dos/dos.h: *69
fib_FileName     array [108] of char in struct FileInfoBlock
         +0x0008 dos/dos.h: *67
fib_NumBlocks    long int in struct FileInfoBlock +0x0080 dos/dos.h: *71
fib_Protection   long int in struct FileInfoBlock +0x0074 dos/dos.h: *68
fib_Reserved     array [36] of char in struct FileInfoBlock
         +0x00e0 dos/dos.h: *74
fib_Size         long int in struct FileInfoBlock +0x007c dos/dos.h: *70
firstBlissObj    pointer to void in struct GelsInfo
         +0x001e graphics/rastport.h: *53
fl_Access        long int in struct FileLock +0x0008 dos/dosextens.h: *446
fl_Key           long int in struct FileLock +0x0004 dos/dosextens.h: *445
fl_Link          long int in struct FileLock +0x0000 dos/dosextens.h: *444
fl_MemList       struct List(size 0x000e bytes) in struct FreeList
         +0x0002 workbench/workbench.h: *85
fl_NumFree       short int in struct FreeList
         +0x0000 workbench/workbench.h: *84
fl_Task          pointer to struct MsgPort in struct FileLock
         +0x000c dos/dosextens.h: *447
fl_Volume        long int in struct FileLock +0x0010 dos/dosextens.h: *448
flags            unsigned char in struct narrator_rb
         +0x0045 devices/narrator.h: *106
floor            #define IEEEDPFloor  libraries/mathffp.h: *36
                 libraries/mathieeedp.h: *36
fo_Attr          struct TextAttr(size 0x0008 bytes) in struct FontRequester
         +0x0008 libraries/asl.h: *148
fo_BackPen       unsigned char in struct FontRequester
         +0x0011 libraries/asl.h: *150
fo_DrawMode      unsigned char in struct FontRequester
         +0x0012 libraries/asl.h: *151
fo_FrontPen      unsigned char in struct FontRequester
         +0x0010 libraries/asl.h: *149
fo_Reserved1     array [2] of pointer to void in struct FontRequester
         +0x0000 libraries/asl.h: *147
fo_UserData      pointer to void in struct FontRequester
         +0x0014 libraries/asl.h: *152
front            pointer to struct Layer in struct Layer
         +0x0000 graphics/clip.h: *36
fse_DosType      unsigned long int in struct FileSysEntry
         +0x000e resources/filesysres.h: *36
fse_GlobalVec    long int in struct FileSysEntry
         +0x003a resources/filesysres.h: *50
fse_Handler      long int in struct FileSysEntry
         +0x0026 resources/filesysres.h: *45
fse_Lock         long int in struct FileSysEntry
         +0x0022 resources/filesysres.h: *44
fse_Node         struct Node(size 0x000e bytes) in struct FileSysEntry
         +0x0000 resources/filesysres.h: *34
fse_PatchFlags   unsigned long int in struct FileSysEntry
         +0x0016 resources/filesysres.h: *38
fse_Priority     long int in struct FileSysEntry
         +0x002e resources/filesysres.h: *47
fse_SegList      long int in struct FileSysEntry
         +0x0036 resources/filesysres.h: *49
fse_StackSize    unsigned long int in struct FileSysEntry
         +0x002a resources/filesysres.h: *46
fse_Startup      long int in struct FileSysEntry
         +0x0032 resources/filesysres.h: *48
fse_Task         unsigned long int in struct FileSysEntry
         +0x001e resources/filesysres.h: *43
fse_Type         unsigned long int in struct FileSysEntry
         +0x001a resources/filesysres.h: *42
fse_Version      unsigned long int in struct FileSysEntry
         +0x0012 resources/filesysres.h: *37
fsr_Creator      pointer to char in struct FileSysResource
         +0x000e resources/filesysres.h: *29
fsr_FileSysEntries struct List(size 0x000e bytes) in struct FileSysResource
         +0x0012 resources/filesysres.h: *30
fsr_Node         struct Node(size 0x000e bytes) in struct FileSysResource
         +0x0000 resources/filesysres.h: *28
fssm_Device      long int in struct FileSysStartupMsg
         +0x0004 dos/filehandler.h: *88
fssm_Environ     long int in struct FileSysStartupMsg
         +0x0008 dos/filehandler.h: *89
fssm_Flags       unsigned long int in struct FileSysStartupMsg
         +0x000c dos/filehandler.h: *90
fssm_Unit        unsigned long int in struct FileSysStartupMsg
         +0x0000 dos/filehandler.h: *87
function         pointer to function returning int in struct bltnode
         +0x0004 hardware/blit.h: *93
F0enthusiasm     unsigned char in struct narrator_rb
         +0x0046 devices/narrator.h: *107
F0perturb        unsigned char in struct narrator_rb
         +0x0047 devices/narrator.h: *108
F1adj            char in struct narrator_rb +0x0048 devices/narrator.h: *109
F2adj            char in struct narrator_rb +0x0049 devices/narrator.h: *110
F3adj            char in struct narrator_rb +0x004a devices/narrator.h: *111
FALSE            #define 0 = 0x00000000  exec/types.h: *73
FANFOLD          #define 0x00 = 0x00000000  intuition/preferences.h: *155
FAULT_MAX        #define 82 = 0x00000052  dos/dos.h: *98
FCH_ID           #define 0x0f00 = 0x00000f00  libraries/diskfont.h: *51
FEMALE           #define 1 = 0x00000001  devices/narrator.h: *64
FIBB_ARCHIVE     #define 4 = 0x00000004  dos/dos.h: *82
FIBB_DELETE      #define 0 = 0x00000000  dos/dos.h: *86
FIBB_EXECUTE     #define 1 = 0x00000001  dos/dos.h: *85
FIBB_PURE        #define 5 = 0x00000005  dos/dos.h: *81
FIBB_READ        #define 3 = 0x00000003  dos/dos.h: *83
FIBB_SCRIPT      #define 6 = 0x00000006  dos/dos.h: *80
FIBB_WRITE       #define 2 = 0x00000002  dos/dos.h: *84
FIBF_ARCHIVE     #define (1<<FIBB_ARCHIVE) = 0x00000010  dos/dos.h: *89
FIBF_DELETE      #define (1<<FIBB_DELETE) = 0x00000001  dos/dos.h: *93
FIBF_EXECUTE     #define (1<<FIBB_EXECUTE) = 0x00000002  dos/dos.h: *92
FIBF_PURE        #define (1<<FIBB_PURE) = 0x00000020  dos/dos.h: *88
FIBF_READ        #define (1<<FIBB_READ) = 0x00000008  dos/dos.h: *90
FIBF_SCRIPT      #define (1<<FIBB_SCRIPT) = 0x00000040  dos/dos.h: *87
FIBF_WRITE       #define (1<<FIBB_WRITE) = 0x00000004  dos/dos.h: *91
FIL1B_MATCHDIRS  #define 1L = 0x00000001  libraries/asl.h: *132
FIL1B_NOFILES    #define 0L = 0x00000000  libraries/asl.h: *131
FIL1F_MATCHDIRS  #define (1L << FIL1B_MATCHDIRS) = 0x00000002
                 libraries/asl.h: *135
FIL1F_NOFILES    #define (1L << FIL1B_NOFILES) = 0x00000001
                 libraries/asl.h: *134
FILB_DOMSGFUNC   #define 6L = 0x00000006  libraries/asl.h: *110
FILB_DOWILDFUNC  #define 7L = 0x00000007  libraries/asl.h: *108
FILB_MULTISELECT #define 3L = 0x00000003  libraries/asl.h: *114
FILB_NEWIDCMP    #define 4L = 0x00000004  libraries/asl.h: *113
FILB_PATGAD      #define 0L = 0x00000000  libraries/asl.h: *116
FILB_SAVE        #define 5L = 0x00000005  libraries/asl.h: *112
FILENAME_SIZE    #define 30 = 0x0000001e
                 intuition/preferences.h: *28, 84, 112
FILF_DOMSGFUNC   #define (1L << FILB_DOMSGFUNC) = 0x00000040
                 libraries/asl.h: *120
FILF_DOWILDFUNC  #define (1L << FILB_DOWILDFUNC) = 0x00000080
                 libraries/asl.h: *119
FILF_MULTISELECT #define (1L << FILB_MULTISELECT) = 0x00000008
                 libraries/asl.h: *124
FILF_NEWIDCMP    #define (1L << FILB_NEWIDCMP) = 0x00000010
                 libraries/asl.h: *123
FILF_PATGAD      #define (1L << FILB_PATGAD) = 0x00000001
                 libraries/asl.h: *125
FILF_SAVE        #define (1L << FILB_SAVE) = 0x00000020  libraries/asl.h: *122
FILLPEN          #define (0x0005) = 0x00000005  intuition/screens.h: *87
FILLRECTCLASS    #define "fillrectclass"  intuition/classusr.h: *46
FILLTEXTPEN      #define (0x0006) = 0x00000006  intuition/screens.h: *88
FILL_CARRYIN     #define 0x4 = 0x00000004  hardware/blit.h: *70
FILL_OR          #define 0x8 = 0x00000008  hardware/blit.h: *68
FILL_XOR         #define 0x10 = 0x00000010  hardware/blit.h: *69
FINE             #define 0x800 = 0x00000800  intuition/preferences.h: *161
FLOAT            typedef float  exec/types.h: *64
FLOYD_DITHERING  #define 0x0400 = 0x00000400  intuition/preferences.h: *257
FOLLOWMOUSE      #define GACT_FOLLOWMOUSE = 0x00000008
                 intuition/iobsolete.h: *72
FONB_BACKCOLOR   #define 1 = 0x00000001  libraries/asl.h: *160
FONB_DOMSGFUNC   #define 6 = 0x00000006  libraries/asl.h: *165
FONB_DOWILDFUNC  #define 7 = 0x00000007  libraries/asl.h: *167
FONB_DRAWMODE    #define 3 = 0x00000003  libraries/asl.h: *162
FONB_FIXEDWIDTH  #define 4 = 0x00000004  libraries/asl.h: *163
FONB_FRONTCOLOR  #define 0 = 0x00000000  libraries/asl.h: *159
FONB_NEWIDCMP    #define 5 = 0x00000005  libraries/asl.h: *164
FONB_STYLES      #define 2 = 0x00000002  libraries/asl.h: *161
FONF_BACKCOLOR   #define (1L << FONB_BACKCOLOR) = 0x00000002
                 libraries/asl.h: *170
FONF_DOMSGFUNC   #define (1L << FONB_DOMSGFUNC) = 0x00000040
                 libraries/asl.h: *175
FONF_DOWILDFUNC  #define (1L << FONB_DOWILDFUNC) = 0x00000080
                 libraries/asl.h: *176
FONF_DRAWMODE    #define (1L << FONB_DRAWMODE) = 0x00000008
                 libraries/asl.h: *172
FONF_FIXEDWIDTH  #define (1L << FONB_FIXEDWIDTH) = 0x00000010
                 libraries/asl.h: *173
FONF_FRONTCOLOR  #define (1L << FONB_FRONTCOLOR) = 0x00000001
                 libraries/asl.h: *169
FONF_NEWIDCMP    #define (1L << FONB_NEWIDCMP) = 0x00000020
                 libraries/asl.h: *174
FONF_STYLES      #define (1L << FONB_STYLES) = 0x00000004
                 libraries/asl.h: *171
FOREVER          #define for(;;)  intuition/intuition.h: *1292
FORMAT_CDN       #define 3 = 0x00000003  dos/datetime.h: *53
FORMAT_DOS       #define 0 = 0x00000000  dos/datetime.h: *50
FORMAT_INT       #define 1 = 0x00000001  dos/datetime.h: *51
FORMAT_MAX       #define FORMAT_CDN = 0x00000003  dos/datetime.h: *54
FORMAT_USA       #define 2 = 0x00000002  dos/datetime.h: *52
FPB_DESIGNED     #define 6 = 0x00000006  graphics/text.h: *56
FPB_DISKFONT     #define 1 = 0x00000001  graphics/text.h: *46
FPB_PROPORTIONAL #define 5 = 0x00000005  graphics/text.h: *54
FPB_REMOVED      #define 7 = 0x00000007  graphics/text.h: *63
FPB_REVPATH      #define 2 = 0x00000002  graphics/text.h: *48
FPB_ROMFONT      #define 0 = 0x00000000  graphics/text.h: *44
FPB_TALLDOT      #define 3 = 0x00000003  graphics/text.h: *50
FPB_WIDEDOT      #define 4 = 0x00000004  graphics/text.h: *52
FPF_DESIGNED     #define 0x40 = 0x00000040  graphics/text.h: *61
FPF_DISKFONT     #define 0x02 = 0x00000002  graphics/text.h: *47
FPF_PROPORTIONAL #define 0x20 = 0x00000020  graphics/text.h: *55
FPF_REMOVED      #define (1<<7) = 0x00000080  graphics/text.h: *64
FPF_REVPATH      #define 0x04 = 0x00000004  graphics/text.h: *49
FPF_ROMFONT      #define 0x01 = 0x00000001  graphics/text.h: *45
FPF_TALLDOT      #define 0x08 = 0x00000008  graphics/text.h: *51
FPF_WIDEDOT      #define 0x10 = 0x00000010  graphics/text.h: *53
FPHALF           #define ((double) 0.5)  libraries/mathffp.h: *28
                 libraries/mathieeedp.h: *29
FPONE            #define ((double) 1.0)  libraries/mathffp.h: *27
                 libraries/mathieeedp.h: *28
FPTEN            #define ((double) 10.0)  libraries/mathffp.h: *26
                 libraries/mathieeedp.h: *27
FPZERO           #define ((double) 0.0)  libraries/mathffp.h: *29
                 libraries/mathieeedp.h: *30
FRAMEF_SPECIFY   #define (1<<0) = 0x00000001  intuition/imageclass.h: *149
FRAMEICLASS      #define "frameiclass"  intuition/classusr.h: *44
FRBUTTONCLASS    #define "frbuttonclass"  intuition/classusr.h: *51
FREEHORIZ        #define 0x0002 = 0x00000002  intuition/intuition.h: *504
FREEVERT         #define 0x0004 = 0x00000004  intuition/intuition.h: *505
FROM_MONITOR     #define 1 = 0x00000001  graphics/monitor.h: *57
FRST_DOT         #define 0x01 = 0x00000001  graphics/rastport.h: *100
FSB_BOLD         #define 1 = 0x00000001  graphics/text.h: *31
FSB_COLORFONT    #define 6 = 0x00000006  graphics/text.h: *38
FSB_EXTENDED     #define 3 = 0x00000003  graphics/text.h: *35
FSB_ITALIC       #define 2 = 0x00000002  graphics/text.h: *33
FSB_TAGGED       #define 7 = 0x00000007  graphics/text.h: *40
FSB_UNDERLINED   #define 0 = 0x00000000  graphics/text.h: *29
FSF_BOLD         #define 0x02 = 0x00000002  graphics/text.h: *32
FSF_COLORFONT    #define 0x40 = 0x00000040  graphics/text.h: *39
FSF_EXTENDED     #define 0x08 = 0x00000008  graphics/text.h: *36
FSF_ITALIC       #define 0x04 = 0x00000004  graphics/text.h: *34
FSF_TAGGED       #define 0x80 = 0x00000080  graphics/text.h: *41
FSF_UNDERLINED   #define 0x01 = 0x00000001  graphics/text.h: *30
FSRNAME          #define "FileSystem.resource"  resources/filesysres.h: *25
FS_NORMAL        #define 0 = 0x00000000  graphics/text.h: *28
FULLMENUNUM      macro (3 arguments)   intuition/intuition.h: *1275
FgPen            char in struct RastPort +0x0019 graphics/rastport.h: *65
FileHandle       structure tag size 0x002c dos/dosextens.h: *91
FileInfoBlock    structure tag size 0x0104 dos/dos.h: *63
                 dos/dosasl.h: 65, 102
FileLock         structure tag size 0x0014 dos/dosextens.h: *443
FileRequester    structure tag size 0x0038 libraries/asl.h: *65
FileSysEntry     structure tag size 0x003e resources/filesysres.h: *33
FileSysHeaderBlock structure tag size 0x0100 devices/hardblocks.h: *152
FileSysResource structure tag size 0x0020 resources/filesysres.h: *27
FileSysStartupMsg structure tag size 0x0010 dos/filehandler.h: *86
FirstCopList     pointer to struct CopList in struct UCopList
         +0x0004 graphics/copper.h: *86
FirstGadget      pointer to struct Gadget in struct Window
         +0x003e intuition/intuition.h: *841
FirstGadget      pointer to struct Gadget in struct NewWindow
         +0x0012 intuition/intuition.h: *990
FirstGadget      pointer to struct Gadget in struct ExtNewWindow
         +0x0012 intuition/intuition.h: *1052
FirstGadget      pointer to struct Gadget in struct Screen
         +0x0146 intuition/screens.h: *135
FirstItem        pointer to struct MenuItem in struct Menu
         +0x0012 intuition/intuition.h: *69
FirstRequest     pointer to struct Requester in struct Window
         +0x0024 intuition/intuition.h: *813
FirstScreen      pointer to struct Screen in struct IntuitionBase
         +0x003c intuition/intuitionbase.h: *80
FirstWindow      pointer to struct Window in struct Screen
         +0x0004 intuition/screens.h: *101
FirstX           short int in struct AreaInfo +0x0014 graphics/rastport.h: *31
FirstY           short int in struct AreaInfo +0x0016 graphics/rastport.h: *31
FlagPtr          pointer to char in struct AreaInfo
         +0x000c graphics/rastport.h: *28
FlagTbl          pointer to char in struct AreaInfo
         +0x0008 graphics/rastport.h: *27
Flags            unsigned char in struct BitMap +0x0004 graphics/gfx.h: *52
Flags            unsigned short int in struct Layer
         +0x001e graphics/clip.h: *42
Flags            unsigned char in struct ColorMap +0x0000 graphics/view.h: *116
Flags            unsigned char in struct GelsInfo
         +0x0001 graphics/rastport.h: *45
Flags            unsigned short int in struct RastPort
         +0x0020 graphics/rastport.h: *72
Flags            unsigned short int in struct Layer_Info
         +0x0058 graphics/layers.h: *43
Flags            unsigned short int in struct Menu
         +0x000c intuition/intuition.h: *67
Flags            unsigned short int in struct MenuItem
         +0x000c intuition/intuition.h: *95
Flags            unsigned short int in struct Requester
         +0x001c intuition/intuition.h: *156
Flags            unsigned short int in struct Gadget
         +0x000c intuition/intuition.h: *223
Flags            unsigned short int in struct BoolInfo
         +0x0000 intuition/intuition.h: *430
Flags            unsigned short int in struct PropInfo
         +0x0000 intuition/intuition.h: *454
Flags            unsigned long int in struct Window
         +0x0018 intuition/intuition.h: *807
Flags            unsigned long int in struct NewWindow
         +0x000e intuition/intuition.h: *983
Flags            unsigned long int in struct ExtNewWindow
         +0x000e intuition/intuition.h: *1051
Flags            unsigned short int in struct Screen
         +0x0014 intuition/screens.h: *108
Flags            short int in struct VSprite +0x0014 graphics/gels.h: *90
Flags            short int in struct Bob +0x0000 graphics/gels.h: *142
Flags            short int in struct AnimComp +0x0000 graphics/gels.h: *170
Flags            unsigned short int in struct GfxBase
         +0x00a8 graphics/gfxbase.h: *46
Flags            unsigned long int in struct IntuitionBase
         +0x0040 intuition/intuitionbase.h: *82
Flags            unsigned char in struct ExpansionBase
         +0x0022 libraries/expansionbase.h: *49
Font             pointer to struct TextFont in struct RastPort
         +0x0034 graphics/rastport.h: *78
Font             pointer to struct TextAttr in struct Screen
         +0x0028 intuition/screens.h: *124
Font             pointer to struct TextAttr in struct NewScreen
         +0x0010 intuition/screens.h: *320
Font             pointer to struct TextAttr in struct ExtNewScreen
         +0x0010 intuition/screens.h: *352
Font             pointer to struct TextFont in struct StringExtend
         +0x0000 intuition/sghooks.h: *21
FontContents     structure tag size 0x0104 libraries/diskfont.h: *30
FontContentsHeader structure tag size 0x0004 libraries/diskfont.h: *54
FontHeight       char in struct Preferences
         +0x0000 intuition/preferences.h: *47
FontRequester    structure tag size 0x0018 libraries/asl.h: *146
FreeClipRects    struct MinList(size 0x000c bytes) in struct Layer_Info
         +0x000c graphics/layers.h: *39
FreeList         structure tag size 0x0010 workbench/workbench.h: *83
FrontPen         unsigned char in struct IntuiText
         +0x0000 intuition/intuition.h: *572
FrontPen         unsigned char in struct Border
         +0x0004 intuition/intuition.h: *601


2.0 IncludeXREF: G

gelHead          pointer to struct VSprite in struct GelsInfo
         +0x0002 graphics/rastport.h: *46
gelTail          pointer to struct VSprite in struct GelsInfo
         +0x0006 graphics/rastport.h: *46
genloc           array [4] of unsigned short int in struct copinit
         +0x005c graphics/copper.h: *100
gi_Domain        struct IBox(size 0x0008 bytes) in struct GadgetInfo
         +0x0014 intuition/cghooks.h: *49
gi_DrInfo        pointer to struct DrawInfo in struct GadgetInfo
         +0x001e intuition/cghooks.h: *61
gi_Layer         pointer to struct Layer in struct GadgetInfo
         +0x0010 intuition/cghooks.h: *38
gi_Pens          struct (no tag) (size 0x0002 bytes) in struct GadgetInfo
         +0x001c intuition/cghooks.h: *55
gi_RastPort      pointer to struct RastPort in struct GadgetInfo
         +0x000c intuition/cghooks.h: *37
gi_Requester     pointer to struct Requester in struct GadgetInfo
         +0x0008 intuition/cghooks.h: *31
gi_Reserved      array [6] of unsigned long int in struct GadgetInfo
         +0x0022 intuition/cghooks.h: *66
gi_Screen        pointer to struct Screen in struct GadgetInfo
         +0x0000 intuition/cghooks.h: *29
gi_Window        pointer to struct Window in struct GadgetInfo
         +0x0004 intuition/cghooks.h: *30
gpGoInactive     structure tag size 0x000c intuition/gadgetclass.h: *231
gpHitTest        structure tag size 0x000c intuition/gadgetclass.h: *176
gpInput          structure tag size 0x0014 intuition/gadgetclass.h: *201
gpRender         structure tag size 0x0010 intuition/gadgetclass.h: *188
gpgi_Abort       unsigned long int in struct gpGoInactive
         +0x0008 intuition/gadgetclass.h: *236
gpgi_GInfo       pointer to struct GadgetInfo in struct gpGoInactive
         +0x0004 intuition/gadgetclass.h: *233
gpht_GInfo       pointer to struct GadgetInfo in struct gpHitTest
         +0x0004 intuition/gadgetclass.h: *178
gpht_Mouse       struct (no tag) (size 0x0004 bytes) in struct gpHitTest
         +0x0008 intuition/gadgetclass.h: *182
gpi_GInfo        pointer to struct GadgetInfo in struct gpInput
         +0x0004 intuition/gadgetclass.h: *203
gpi_IEvent       pointer to struct InputEvent in struct gpInput
         +0x0008 intuition/gadgetclass.h: *204
gpi_Mouse        struct (no tag) (size 0x0004 bytes) in struct gpInput
         +0x0010 intuition/gadgetclass.h: *209
gpi_Termination pointer to long int in struct gpInput
         +0x000c intuition/gadgetclass.h: *205
gpr_GInfo        pointer to struct GadgetInfo in struct gpRender
         +0x0004 intuition/gadgetclass.h: *190
gpr_RPort        pointer to struct RastPort in struct gpRender
         +0x0008 intuition/gadgetclass.h: *191
gpr_Redraw       long int in struct gpRender
         +0x000c intuition/gadgetclass.h: *192
gpt_Keys         unsigned short int in struct GamePortTrigger
         +0x0000 devices/gameport.h: *39
gpt_Timeout      unsigned short int in struct GamePortTrigger
         +0x0002 devices/gameport.h: *40
gpt_XDelta       unsigned short int in struct GamePortTrigger
         +0x0004 devices/gameport.h: *41
gpt_YDelta       unsigned short int in struct GamePortTrigger
         +0x0006 devices/gameport.h: *42
gs_Head          struct List(size 0x000e bytes) in struct Layer_Info
         +0x0046 graphics/layers.h: *41
GACT_ACTIVEGADGET #define 0x4000 = 0x00004000  intuition/intuition.h: *385
GACT_ALTKEYMAP   #define 0x1000 = 0x00001000  intuition/intuition.h: *372
GACT_BOOLEXTEND  #define 0x2000 = 0x00002000  intuition/intuition.h: *365
GACT_BORDERSNIFF #define 0x8000 = 0x00008000  intuition/intuition.h: *362
GACT_BOTTOMBORDER #define 0x0080 = 0x00000080  intuition/intuition.h: *361
GACT_ENDGADGET   #define 0x0004 = 0x00000004  intuition/intuition.h: *342
GACT_FOLLOWMOUSE #define 0x0008 = 0x00000008  intuition/intuition.h: *352
GACT_IMMEDIATE   #define 0x0002 = 0x00000002  intuition/intuition.h: *336
GACT_LEFTBORDER  #define 0x0020 = 0x00000020  intuition/intuition.h: *359
GACT_LONGINT     #define 0x0800 = 0x00000800  intuition/intuition.h: *371
GACT_RELVERIFY   #define 0x0001 = 0x00000001  intuition/intuition.h: *330
GACT_RIGHTBORDER #define 0x0010 = 0x00000010  intuition/intuition.h: *358
GACT_STRINGCENTER #define 0x0200 = 0x00000200  intuition/intuition.h: *369
GACT_STRINGEXTEND #define 0x2000 = 0x00002000  intuition/intuition.h: *373
GACT_STRINGLEFT  #define 0x0000 = 0x00000000  intuition/intuition.h: *368
GACT_STRINGRIGHT #define 0x0400 = 0x00000400  intuition/intuition.h: *370
GACT_TOGGLESELECT #define 0x0100 = 0x00000100  intuition/intuition.h: *364
GACT_TOPBORDER   #define 0x0040 = 0x00000040  intuition/intuition.h: *360
GADGBACKFILL     #define 0x0001 = 0x00000001  workbench/workbench.h: *111
GADGDISABLED     #define GFLG_DISABLED = 0x00000100
                 intuition/iobsolete.h: *60
GADGET0002       #define GTYP_GADGET0002 = 0x00000002
                 intuition/iobsolete.h: *105
GADGETCLASS      #define "gadgetclass"  intuition/classusr.h: *47
GADGETCOUNT      #define 8 = 0x00000008  intuition/intuitionbase.h: *46
GADGETDOWN       #define IDCMP_GADGETDOWN = 0x00000020
                 intuition/iobsolete.h: *119
GADGETTYPE       #define GTYP_GADGETTYPE = 0x0000fc00
                 intuition/iobsolete.h: *91
GADGETUP         #define IDCMP_GADGETUP = 0x00000040
                 intuition/iobsolete.h: *120
GADGET_BOX       macro (1 argument)   intuition/imageclass.h: *28
GADGHBOX         #define GFLG_GADGHBOX = 0x00000001
                 intuition/iobsolete.h: *51
GADGHCOMP        #define GFLG_GADGHCOMP = 0x00000000
                 intuition/iobsolete.h: *50
GADGHIGHBITS     #define GFLG_GADGHIGHBITS = 0x00000003
                 intuition/iobsolete.h: *49
GADGHIMAGE       #define GFLG_GADGHIMAGE = 0x00000002
                 intuition/iobsolete.h: *52
GADGHNONE        #define GFLG_GADGHNONE = 0x00000003
                 intuition/iobsolete.h: *53
GADGIMAGE        #define GFLG_GADGIMAGE = 0x00000004
                 intuition/iobsolete.h: *54
GADGIMMEDIATE    #define GACT_IMMEDIATE = 0x00000002
                 intuition/iobsolete.h: *70
GADTOOLBIT       #define (0x8000) = 0x00008000  libraries/gadtools.h: *55
GADTOOLMASK      #define (~GADTOOLBIT) = 0xffff7fff  libraries/gadtools.h: *57
GA_BORDER        #define GA_Border = 0x8003000b  intuition/iobsolete.h: *190
GA_BOTTOMBORDER  #define GA_BottomBorder = 0x8003001b
                 intuition/iobsolete.h: *205
GA_Border        #define (GA_Dummy + 0x000B) = 0x8003000b
                 intuition/gadgetclass.h: *44
GA_BottomBorder  #define (GA_Dummy + 0x001B) = 0x8003001b
                 intuition/gadgetclass.h: *60
GA_DISABLED      #define GA_Disabled = 0x8003000e  intuition/iobsolete.h: *193
GA_DRAWINFO      #define GA_DrawInfo = 0x80030021  intuition/iobsolete.h: *211
GA_Disabled      #define (GA_Dummy + 0x000E) = 0x8003000e
                 intuition/gadgetclass.h: *47
GA_DrawInfo      #define (GA_Dummy + 0x0021) = 0x80030021
                 intuition/gadgetclass.h: *79
GA_Dummy         #define (TAG_USER +0x30000) = 0x80030000
                 intuition/gadgetclass.h: *33
GA_ENDGADGET     #define GA_EndGadget = 0x80030014
                 intuition/iobsolete.h: *198
GA_EndGadget     #define (GA_Dummy + 0x0014) = 0x80030014
                 intuition/gadgetclass.h: *53
GA_FOLLOWMOUSE   #define GA_FollowMouse = 0x80030017
                 intuition/iobsolete.h: *201
GA_FollowMouse   #define (GA_Dummy + 0x0017) = 0x80030017
                 intuition/gadgetclass.h: *56
GA_GZZGADGET     #define GA_GZZGadget = 0x8003000f
                 intuition/iobsolete.h: *194
GA_GZZGadget     #define (GA_Dummy + 0x000F) = 0x8003000f
                 intuition/gadgetclass.h: *48
GA_HEIGHT        #define GA_Height = 0x80030007  intuition/iobsolete.h: *186
GA_HIGHLIGHT     #define GA_Highlight = 0x8003000d
                 intuition/iobsolete.h: *192
GA_Height        #define (GA_Dummy + 0x0007) = 0x80030007
                 intuition/gadgetclass.h: *40
GA_Highlight     #define (GA_Dummy + 0x000D) = 0x8003000d
                 intuition/gadgetclass.h: *46
GA_ID            #define (GA_Dummy + 0x0010) = 0x80030010
                 intuition/gadgetclass.h: *49
GA_IMAGE         #define GA_Image = 0x8003000a  intuition/iobsolete.h: *189
GA_IMMEDIATE     #define GA_Immediate = 0x80030015
                 intuition/iobsolete.h: *199
GA_INTUITEXT     #define GA_IntuiText = 0x80030022
                 intuition/iobsolete.h: *212
GA_Image         #define (GA_Dummy + 0x000A) = 0x8003000a
                 intuition/gadgetclass.h: *43
GA_Immediate     #define (GA_Dummy + 0x0015) = 0x80030015
                 intuition/gadgetclass.h: *54
GA_IntuiText     #define (GA_Dummy + 0x0022) = 0x80030022
                 intuition/gadgetclass.h: *85
GA_LABELIMAGE    #define GA_LabelImage = 0x80030023
                 intuition/iobsolete.h: *213
GA_LEFT          #define GA_Left = 0x80030001  intuition/iobsolete.h: *180
GA_LEFTBORDER    #define GA_LeftBorder = 0x80030019
                 intuition/iobsolete.h: *203
GA_LabelImage    #define (GA_Dummy + 0x0023) = 0x80030023
                 intuition/gadgetclass.h: *88
GA_Left          #define (GA_Dummy + 0x0001) = 0x80030001
                 intuition/gadgetclass.h: *34
GA_LeftBorder    #define (GA_Dummy + 0x0019) = 0x80030019
                 intuition/gadgetclass.h: *58
GA_NEXT          #define GA_Next = 0x80030020  intuition/iobsolete.h: *210
GA_Next          #define (GA_Dummy + 0x0020) = 0x80030020
                 intuition/gadgetclass.h: *76
GA_PREVIOUS      #define GA_Previous = 0x8003001f  intuition/iobsolete.h: *209
GA_Previous      #define (GA_Dummy + 0x001F) = 0x8003001f
                 intuition/gadgetclass.h: *69
GA_RELBOTTOM     #define GA_RelBottom = 0x80030004
                 intuition/iobsolete.h: *183
GA_RELHEIGHT     #define GA_RelHeight = 0x80030008
                 intuition/iobsolete.h: *187
GA_RELRIGHT      #define GA_RelRight = 0x80030002  intuition/iobsolete.h: *181
GA_RELVERIFY     #define GA_RelVerify = 0x80030016
                 intuition/iobsolete.h: *200
GA_RELWIDTH      #define GA_RelWidth = 0x80030006  intuition/iobsolete.h: *185
GA_RIGHTBORDER   #define GA_RightBorder = 0x80030018
                 intuition/iobsolete.h: *202
GA_RelBottom     #define (GA_Dummy + 0x0004) = 0x80030004
                 intuition/gadgetclass.h: *37
GA_RelHeight     #define (GA_Dummy + 0x0008) = 0x80030008
                 intuition/gadgetclass.h: *41
GA_RelRight      #define (GA_Dummy + 0x0002) = 0x80030002
                 intuition/gadgetclass.h: *35
GA_RelVerify     #define (GA_Dummy + 0x0016) = 0x80030016
                 intuition/gadgetclass.h: *55
GA_RelWidth      #define (GA_Dummy + 0x0006) = 0x80030006
                 intuition/gadgetclass.h: *39
GA_RightBorder   #define (GA_Dummy + 0x0018) = 0x80030018
                 intuition/gadgetclass.h: *57
GA_SELECTED      #define GA_Selected = 0x80030013  intuition/iobsolete.h: *197
GA_SELECTRENDER  #define GA_SelectRender = 0x8003000c
                 intuition/iobsolete.h: *191
GA_SPECIALINFO   #define GA_SpecialInfo = 0x80030012
                 intuition/iobsolete.h: *196
GA_SYSGADGET     #define GA_SysGadget = 0x8003001d
                 intuition/iobsolete.h: *207
GA_SYSGTYPE      #define GA_SysGType = 0x8003001e  intuition/iobsolete.h: *208
GA_SelectRender  #define (GA_Dummy + 0x000C) = 0x8003000c
                 intuition/gadgetclass.h: *45
GA_Selected      #define (GA_Dummy + 0x0013) = 0x80030013
                 intuition/gadgetclass.h: *52
GA_SpecialInfo   #define (GA_Dummy + 0x0012) = 0x80030012
                 intuition/gadgetclass.h: *51
GA_SysGType      #define (GA_Dummy + 0x001E) = 0x8003001e
                 intuition/gadgetclass.h: *66
GA_SysGadget     #define (GA_Dummy + 0x001D) = 0x8003001d
                 intuition/gadgetclass.h: *64
GA_TEXT          #define GA_Text = 0x80030009  intuition/iobsolete.h: *188
GA_TOGGLESELECT  #define GA_ToggleSelect = 0x8003001c
                 intuition/iobsolete.h: *206
GA_TOP           #define GA_Top = 0x80030003  intuition/iobsolete.h: *182
GA_TOPBORDER     #define GA_TopBorder = 0x8003001a
                 intuition/iobsolete.h: *204
GA_TabCycle      #define (GA_Dummy + 0x0024) = 0x80030024
                 intuition/gadgetclass.h: *93
GA_Text          #define (GA_Dummy + 0x0009) = 0x80030009
                 intuition/gadgetclass.h: *42
GA_ToggleSelect  #define (GA_Dummy + 0x001C) = 0x8003001c
                 intuition/gadgetclass.h: *61
GA_Top           #define (GA_Dummy + 0x0003) = 0x80030003
                 intuition/gadgetclass.h: *36
GA_TopBorder     #define (GA_Dummy + 0x001A) = 0x8003001a
                 intuition/gadgetclass.h: *59
GA_USERDATA      #define GA_UserData = 0x80030011  intuition/iobsolete.h: *195
GA_UserData      #define (GA_Dummy + 0x0011) = 0x80030011
                 intuition/gadgetclass.h: *50
GA_WIDTH         #define GA_Width = 0x80030005  intuition/iobsolete.h: *184
GA_Width         #define (GA_Dummy + 0x0005) = 0x80030005
                 intuition/gadgetclass.h: *38
GELGONE          #define 0x0400 = 0x00000400  graphics/gels.h: *29
GENERIC_KIND     #define 0 = 0x00000000  libraries/gadtools.h: *34
GENLOC           #define 2 = 0x00000002  graphics/gfxbase.h: *96
GENLOCK_AUDIO    #define 0x0100 = 0x00000100  graphics/view.h: *95
GENLOCK_VIDEO    #define 0x0002 = 0x00000002  graphics/view.h: *90
GFLG_DISABLED    #define 0x0100 = 0x00000100  intuition/intuition.h: *297
GFLG_GADGHBOX    #define 0x0001 = 0x00000001  intuition/intuition.h: *269
GFLG_GADGHCOMP   #define 0x0000 = 0x00000000  intuition/intuition.h: *268
GFLG_GADGHIGHBITS #define 0x0003 = 0x00000003  intuition/intuition.h: *267
GFLG_GADGHIMAGE  #define 0x0002 = 0x00000002  intuition/intuition.h: *270
GFLG_GADGHNONE   #define 0x0003 = 0x00000003  intuition/intuition.h: *271
GFLG_GADGIMAGE   #define 0x0004 = 0x00000004  intuition/intuition.h: *276
GFLG_LABELIMAGE  #define 0x2000 = 0x00002000  intuition/intuition.h: *310
GFLG_LABELITEXT  #define 0x0000 = 0x00000000  intuition/intuition.h: *308
GFLG_LABELMASK   #define 0x3000 = 0x00003000  intuition/intuition.h: *307
GFLG_LABELSTRING #define 0x1000 = 0x00001000  intuition/intuition.h: *309
GFLG_RELBOTTOM   #define 0x0008 = 0x00000008  intuition/intuition.h: *286
GFLG_RELHEIGHT   #define 0x0040 = 0x00000040  intuition/intuition.h: *289
GFLG_RELRIGHT    #define 0x0010 = 0x00000010  intuition/intuition.h: *287
GFLG_RELWIDTH    #define 0x0020 = 0x00000020  intuition/intuition.h: *288
GFLG_SELECTED    #define 0x0080 = 0x00000080  intuition/intuition.h: *291
GFLG_STRINGEXTEND #define 0x0400 = 0x00000400  intuition/intuition.h: *323
GFLG_TABCYCLE    #define 0x0200 = 0x00000200  intuition/intuition.h: *315
GFXB_BIG_BLITS   #define 0 = 0x00000000  graphics/gfxbase.h: *103
GFXB_HR_AGNUS    #define 0 = 0x00000000  graphics/gfxbase.h: *104
GFXB_HR_DENISE   #define 1 = 0x00000001  graphics/gfxbase.h: *105
GFXF_BIG_BLITS   #define 1 = 0x00000001  graphics/gfxbase.h: *107
GFXF_HR_AGNUS    #define 1 = 0x00000001  graphics/gfxbase.h: *108
GFXF_HR_DENISE   #define 2 = 0x00000002  graphics/gfxbase.h: *109
GIMMEZEROZERO    #define WFLG_GIMMEZEROZERO = 0x00000400
                 intuition/iobsolete.h: *158
GLOBAL           #define extern  exec/types.h: *20
GLOBALSZ         #define 200 = 0x000000c8  rexx/storage.h: *185, 188
GMR_GADGETHIT    #define (0x00000004) = 0x00000004
                 intuition/gadgetclass.h: *185
GMR_MEACTIVE     #define (0) = 0x00000000  intuition/gadgetclass.h: *217
GMR_NEXTACTIVE   #define (1 << 4) = 0x00000010  intuition/gadgetclass.h: *227
GMR_NOREUSE      #define (1 << 1) = 0x00000002  intuition/gadgetclass.h: *218
GMR_PREVACTIVE   #define (1 << 5) = 0x00000020  intuition/gadgetclass.h: *228
GMR_REUSE        #define (1 << 2) = 0x00000004  intuition/gadgetclass.h: *219
GMR_VERIFY       #define (1 << 3) = 0x00000008  intuition/gadgetclass.h: *220
GM_Dummy         #define (-1) = 0xffffffff  intuition/gadgetclass.h: *164
GM_GOACTIVE      #define (2) = 0x00000002  intuition/gadgetclass.h: *169
GM_GOINACTIVE    #define (4) = 0x00000004  intuition/gadgetclass.h: *171
GM_HANDLEINPUT   #define (3) = 0x00000003  intuition/gadgetclass.h: *170
GM_HITTEST       #define (0) = 0x00000000  intuition/gadgetclass.h: *167
GM_RENDER        #define (1) = 0x00000001  intuition/gadgetclass.h: *168
GPCT_ABSJOYSTICK #define 3 = 0x00000003  devices/gameport.h: *51
GPCT_ALLOCATED   #define -1 = 0xffffffff  devices/gameport.h: *46
GPCT_MOUSE       #define 1 = 0x00000001  devices/gameport.h: *49
GPCT_NOCONTROLLER #define 0 = 0x00000000  devices/gameport.h: *47
GPCT_RELJOYSTICK #define 2 = 0x00000002  devices/gameport.h: *50
GPDERR_SETCTYPE  #define 1 = 0x00000001  devices/gameport.h: *55
GPD_ASKCTYPE     #define (CMD_NONSTD+1) = 0x0000000a  devices/gameport.h: *25
GPD_ASKTRIGGER   #define (CMD_NONSTD+3) = 0x0000000c  devices/gameport.h: *27
GPD_READEVENT    #define (CMD_NONSTD+0) = 0x00000009  devices/gameport.h: *24
GPD_SETCTYPE     #define (CMD_NONSTD+2) = 0x0000000b  devices/gameport.h: *26
GPD_SETTRIGGER   #define (CMD_NONSTD+4) = 0x0000000d  devices/gameport.h: *28
GPTB_DOWNKEYS    #define 0 = 0x00000000  devices/gameport.h: *33
GPTB_UPKEYS      #define 1 = 0x00000001  devices/gameport.h: *35
GPTF_DOWNKEYS    #define (1<<0) = 0x00000001  devices/gameport.h: *34
GPTF_UPKEYS      #define (1<<1) = 0x00000002  devices/gameport.h: *36
GRAPHICSNAME     #define "graphics.library"  graphics/gfxbase.h: *111
GRAPHICS_CLIP_H  #define  graphics/clip.h: *2, 1
                 intuition/screens.h: 23
GRAPHICS_COLLIDE_H #define  graphics/collide.h: *2
GRAPHICS_COPPER_H #define  graphics/copper.h: *2, 1
GRAPHICS_DISPLAYINFO_H #define  graphics/displayinfo.h: *2
GRAPHICS_DISPLAY_H #define  graphics/display.h: *2
GRAPHICS_GELS_H  #define  graphics/gels.h: *2
GRAPHICS_GFXBASE_H #define  graphics/gfxbase.h: *2
GRAPHICS_GFXMACROS_H #define  graphics/gfxmacros.h: *2
GRAPHICS_GFXNODES_H #define  graphics/gfxnodes.h: *2, 1
                 graphics/monitor.h: 19
GRAPHICS_GFX_H   #define  graphics/gfx.h: *2, 1
                 graphics/clip.h: 19
                 graphics/view.h: 21
                 graphics/monitor.h: 23
                 graphics/rastport.h: 19
                 graphics/text.h: 19
                 intuition/screens.h: 19
                 graphics/displayinfo.h: 19
                 graphics/regions.h: 19
GRAPHICS_GRAPHINT_H #define  graphics/graphint.h: *2
GRAPHICS_LAYERS_H #define  graphics/layers.h: *2, 1
                 intuition/screens.h: 35
GRAPHICS_MONITOR_H #define  graphics/monitor.h: *2, 1
                 graphics/displayinfo.h: 23
GRAPHICS_RASTPORT_H #define  graphics/rastport.h: *2, 1
                 intuition/screens.h: 31
                 graphics/gfxmacros.h: 19
GRAPHICS_REGIONS_H #define  graphics/regions.h: *2
GRAPHICS_SCALE_H #define  graphics/scale.h: *2
GRAPHICS_SPRITE_H #define  graphics/sprite.h: *2
GRAPHICS_TEXT_H  #define  graphics/text.h: *2, 1
                 libraries/asl.h: 40
                 libraries/diskfont.h: 24
GRAPHICS_VIDEOCONTROL_H #define  graphics/videocontrol.h: *2
GRAPHICS_VIEW_H  #define  graphics/view.h: *2, 1
                 intuition/screens.h: 27
GREDRAW_REDRAW   #define (1) = 0x00000001  intuition/gadgetclass.h: *197
GREDRAW_TOGGLE   #define (0) = 0x00000000  intuition/gadgetclass.h: *198
GREDRAW_UPDATE   #define (2) = 0x00000002  intuition/gadgetclass.h: *196
GRELBOTTOM       #define GFLG_RELBOTTOM = 0x00000008
                 intuition/iobsolete.h: *55
GRELHEIGHT       #define GFLG_RELHEIGHT = 0x00000040
                 intuition/iobsolete.h: *58
GRELRIGHT        #define GFLG_RELRIGHT = 0x00000010
                 intuition/iobsolete.h: *56
GRELWIDTH        #define GFLG_RELWIDTH = 0x00000020
                 intuition/iobsolete.h: *57
GREY_SCALE2      #define 0x1000 = 0x00001000  intuition/preferences.h: *260
GROUPGCLASS      #define "groupgclass"  intuition/classusr.h: *52
GTBB_Recessed    #define GT_TagBase+51 = 0x80080033
                 libraries/gadtools.h: *246
GTCB_Checked     #define GT_TagBase+4 = 0x80080004  libraries/gadtools.h: *195
GTCY_Active      #define GT_TagBase+15 = 0x8008000f
                 libraries/gadtools.h: *213
GTCY_Labels      #define GT_TagBase+14 = 0x8008000e
                 libraries/gadtools.h: *212
GTIN_MaxChars    #define GT_TagBase+48 = 0x80080030
                 libraries/gadtools.h: *241
GTIN_Number      #define GT_TagBase+47 = 0x8008002f
                 libraries/gadtools.h: *240
GTLV_Labels      #define GT_TagBase+6 = 0x80080006  libraries/gadtools.h: *198
GTLV_ReadOnly    #define GT_TagBase+7 = 0x80080007  libraries/gadtools.h: *200
GTLV_ScrollWidth #define GT_TagBase+8 = 0x80080008  libraries/gadtools.h: *201
GTLV_Selected    #define GT_TagBase+54 = 0x80080036
                 libraries/gadtools.h: *254
GTLV_ShowSelected #define GT_TagBase+53 = 0x80080035
                 libraries/gadtools.h: *252
GTLV_Top         #define GT_TagBase+5 = 0x80080005  libraries/gadtools.h: *197
GTMENUITEM_USERDATA macro (1 argument)   libraries/gadtools.h: *173
GTMENU_INVALID   #define 0x00000002 = 0x00000002  libraries/gadtools.h: *181
GTMENU_NOMEM     #define 0x00000003 = 0x00000003  libraries/gadtools.h: *182
GTMENU_TRIMMED   #define 0x00000001 = 0x00000001  libraries/gadtools.h: *180
GTMENU_USERDATA macro (1 argument)   libraries/gadtools.h: *172
GTMN_FrontPen    #define GT_TagBase+50 = 0x80080032
                 libraries/gadtools.h: *244
GTMN_FullMenu    #define GT_TagBase+62 = 0x8008003e
                 libraries/gadtools.h: *274
GTMN_Menu        #define GT_TagBase+60 = 0x8008003c
                 libraries/gadtools.h: *267
GTMN_SecondaryError #define GT_TagBase+63 = 0x8008003f
                 libraries/gadtools.h: *276
GTMN_TextAttr    #define GT_TagBase+49 = 0x80080031
                 libraries/gadtools.h: *243
GTMX_Active      #define GT_TagBase+10 = 0x8008000a
                 libraries/gadtools.h: *204
GTMX_Labels      #define GT_TagBase+9 = 0x80080009  libraries/gadtools.h: *203
GTMX_Spacing     #define GT_TagBase+61 = 0x8008003d
                 libraries/gadtools.h: *270
GTNM_Border      #define GT_TagBase+58 = 0x8008003a
                 libraries/gadtools.h: *261
GTNM_Number      #define GT_TagBase+13 = 0x8008000d
                 libraries/gadtools.h: *210
GTNW_Active      #define GTCY_Active = 0x8008000f  libraries/gadtools.h: *289
GTNW_Labels      #define GTCY_Labels = 0x8008000e  libraries/gadtools.h: *288
GTPA_Color       #define GT_TagBase+17 = 0x80080011
                 libraries/gadtools.h: *216
GTPA_ColorOffset #define GT_TagBase+18 = 0x80080012
                 libraries/gadtools.h: *217
GTPA_Depth       #define GT_TagBase+16 = 0x80080010
                 libraries/gadtools.h: *215
GTPA_IndicatorHeight #define GT_TagBase+20 = 0x80080014
                 libraries/gadtools.h: *219
GTPA_IndicatorWidth #define GT_TagBase+19 = 0x80080013
                 libraries/gadtools.h: *218
GTSC_Arrows      #define GT_TagBase+59 = 0x8008003b
                 libraries/gadtools.h: *264
GTSC_Overlap     #define GT_TagBase+24 = 0x80080018
                 libraries/gadtools.h: *224
GTSC_Top         #define GT_TagBase+21 = 0x80080015
                 libraries/gadtools.h: *221
GTSC_Total       #define GT_TagBase+22 = 0x80080016
                 libraries/gadtools.h: *222
GTSC_Visible     #define GT_TagBase+23 = 0x80080017
                 libraries/gadtools.h: *223
GTSL_DispFunc    #define GT_TagBase+44 = 0x8008002c
                 libraries/gadtools.h: *235
GTSL_Level       #define GT_TagBase+40 = 0x80080028
                 libraries/gadtools.h: *230
GTSL_LevelFormat #define GT_TagBase+42 = 0x8008002a
                 libraries/gadtools.h: *232
GTSL_LevelPlace  #define GT_TagBase+43 = 0x8008002b
                 libraries/gadtools.h: *233
GTSL_Max         #define GT_TagBase+39 = 0x80080027
                 libraries/gadtools.h: *229
GTSL_MaxLevelLen #define GT_TagBase+41 = 0x80080029
                 libraries/gadtools.h: *231
GTSL_Min         #define GT_TagBase+38 = 0x80080026
                 libraries/gadtools.h: *228
GTST_MaxChars    #define GT_TagBase+46 = 0x8008002e
                 libraries/gadtools.h: *238
GTST_String      #define GT_TagBase+45 = 0x8008002d
                 libraries/gadtools.h: *237
GTTX_Border      #define GT_TagBase+57 = 0x80080039
                 libraries/gadtools.h: *259
GTTX_CopyText    #define GT_TagBase+12 = 0x8008000c
                 libraries/gadtools.h: *208
GTTX_Text        #define GT_TagBase+11 = 0x8008000b
                 libraries/gadtools.h: *206
GTVI_NWTags      #define GT_TagBase+2 = 0x80080002  libraries/gadtools.h: *191
GTVI_NewWindow   #define GT_TagBase+1 = 0x80080001  libraries/gadtools.h: *190
GTYPEMASK        #define GTYP_GTYPEMASK = 0x00000007
                 intuition/iobsolete.h: *109
GTYP_BOOLGADGET  #define 0x0001 = 0x00000001  intuition/intuition.h: *410
GTYP_CLOSE       #define 0x0080 = 0x00000080  intuition/intuition.h: *408
GTYP_CUSTOMGADGET #define 0x0005 = 0x00000005  intuition/intuition.h: *414
GTYP_GADGET0002  #define 0x0002 = 0x00000002  intuition/intuition.h: *411
GTYP_GADGETTYPE  #define 0xFC00 = 0x0000fc00  intuition/intuition.h: *395
GTYP_GTYPEMASK   #define 0x0007 = 0x00000007  intuition/intuition.h: *415
GTYP_GZZGADGET   #define 0x2000 = 0x00002000  intuition/intuition.h: *398
GTYP_PROPGADGET  #define 0x0003 = 0x00000003  intuition/intuition.h: *412
GTYP_REQGADGET   #define 0x1000 = 0x00001000  intuition/intuition.h: *399
GTYP_SCRGADGET   #define 0x4000 = 0x00004000  intuition/intuition.h: *397
GTYP_SDOWNBACK   #define 0x0070 = 0x00000070  intuition/intuition.h: *407
GTYP_SDRAGGING   #define 0x0030 = 0x00000030  intuition/intuition.h: *403
GTYP_SIZING      #define 0x0010 = 0x00000010  intuition/intuition.h: *401
GTYP_STRGADGET   #define 0x0004 = 0x00000004  intuition/intuition.h: *413
GTYP_SUPFRONT    #define 0x0050 = 0x00000050  intuition/intuition.h: *405
GTYP_SYSGADGET   #define 0x8000 = 0x00008000  intuition/intuition.h: *396
GTYP_WDOWNBACK   #define 0x0060 = 0x00000060  intuition/intuition.h: *406
GTYP_WDRAGGING   #define 0x0020 = 0x00000020  intuition/intuition.h: *402
GTYP_WUPFRONT    #define 0x0040 = 0x00000040  intuition/intuition.h: *404
GT_Private0      #define GT_TagBase+3 = 0x80080003  libraries/gadtools.h: *193
GT_Reserved0     #define GT_TagBase+55 = 0x80080037
                 libraries/gadtools.h: *255
GT_Reserved1     #define GT_TagBase+56 = 0x80080038
                 libraries/gadtools.h: *256
GT_TagBase       #define TAG_USER + 0x80000 = 0x80080000
                 libraries/gadtools.h: *188
GT_Underscore    #define GT_TagBase+64 = 0x80080040
                 libraries/gadtools.h: *279
GT_VisualInfo    #define GT_TagBase+52 = 0x80080034
                 libraries/gadtools.h: *248
GVB_BINARY_VAR   #define 10 = 0x0000000a  dos/var.h: *53
GVB_GLOBAL_ONLY  #define 8 = 0x00000008  dos/var.h: *49
GVB_LOCAL_ONLY   #define 9 = 0x00000009  dos/var.h: *51
GVF_BINARY_VAR   #define 0x400 = 0x00000400  dos/var.h: *54
GVF_GLOBAL_ONLY  #define 0x100 = 0x00000100  dos/var.h: *50
GVF_LOCAL_ONLY   #define 0x200 = 0x00000200  dos/var.h: *52
GZZGADGET        #define GTYP_GZZGADGET = 0x00002000
                 intuition/iobsolete.h: *94
GZZHeight        short int in struct Window +0x0072 intuition/intuition.h: *881
GZZMouseX        short int in struct Window +0x006c intuition/intuition.h: *875
GZZMouseY        short int in struct Window +0x006e intuition/intuition.h: *876
GZZWidth         short int in struct Window +0x0070 intuition/intuition.h: *880
Gadget           structure tag
     size 0x002c intuition/intuition.h: *153, 216, 218, 841, 990,
                             1052
                 intuition/screens.h: 135, 324, 354
                 intuition/sghooks.h: 35
                 workbench/workbench.h: 65
Gadget           pointer to struct Gadget in struct SGWork
         +0x0000 intuition/sghooks.h: *35
GadgetID         unsigned short int in struct Gadget
         +0x0026 intuition/intuition.h: *260
GadgetInfo       structure tag size 0x003a intuition/cghooks.h: *27
                 intuition/classusr.h: 81, 91
                 intuition/gadgetclass.h: 178, 190, 203, 233
                 intuition/sghooks.h: 49
GadgetInfo       pointer to struct GadgetInfo in struct SGWork
         +0x0026 intuition/sghooks.h: *49
GadgetRender     pointer to void in struct Gadget
         +0x0012 intuition/intuition.h: *233
GadgetText       pointer to struct IntuiText in struct Gadget
         +0x001a intuition/intuition.h: *240
GadgetType       unsigned short int in struct Gadget
         +0x0010 intuition/intuition.h: *227
Gadgets          pointer to struct Gadget in struct NewScreen
         +0x0018 intuition/screens.h: *324
Gadgets          pointer to struct Gadget in struct ExtNewScreen
         +0x0018 intuition/screens.h: *354
GamePortTrigger structure tag size 0x0008 devices/gameport.h: *38
GelsInfo         structure tag size 0x0026 graphics/rastport.h: *41, 63
GelsInfo         pointer to struct GelsInfo in struct RastPort
         +0x0014 graphics/rastport.h: *63
GfxBase          structure tag size 0x01a6 graphics/gfxbase.h: *25
Green            unsigned short int in struct ColorSpec
         +0x0004 intuition/intuition.h: *1244


2.0 IncludeXREF: H

h_Data           pointer to void in struct Hook +0x0010 utility/hooks.h: *28
h_Entry          pointer to function returning unsigned long int in struct
                 Hook
         +0x0008 utility/hooks.h: *26
h_MinNode        struct MinNode(size 0x0008 bytes) in struct Hook
         +0x0000 utility/hooks.h: *25
h_SubEntry       pointer to function returning unsigned long int in struct
                 Hook
         +0x000c utility/hooks.h: *27
hash_table       pointer to long int in struct GfxBase
         +0x015a graphics/gfxbase.h: *76
hblank           struct AnalogSignalInterval(size 0x0004 bytes) in struct
                 SpecialMonitor
         +0x002a graphics/monitor.h: *150
hbstop           unsigned short int in struct Custom
         +0x01c6 hardware/custom.h: *126
hbstrt           unsigned short int in struct Custom
         +0x01c4 hardware/custom.h: *125
hcenter          unsigned short int in struct Custom
         +0x01e2 hardware/custom.h: *140
hedley           array [8] of unsigned long int in struct GfxBase
         +0x00f4 graphics/gfxbase.h: *70
hedley_count     short int in struct GfxBase +0x0154 graphics/gfxbase.h: *73
hedley_flags     unsigned short int in struct GfxBase
         +0x0156 graphics/gfxbase.h: *74
hedley_hint      unsigned char in struct GfxBase
         +0x0162 graphics/gfxbase.h: *79
hedley_hint2     unsigned char in struct GfxBase
         +0x0163 graphics/gfxbase.h: *80
hedley_sprites   array [8] of unsigned long int in struct GfxBase
         +0x0114 graphics/gfxbase.h: *71
hedley_sprites1 array [8] of unsigned long int in struct GfxBase
         +0x0134 graphics/gfxbase.h: *72
hedley_tmp       short int in struct GfxBase +0x0158 graphics/gfxbase.h: *75
height           unsigned char in struct mouth_rb
         +0x0059 devices/narrator.h: *131
height           unsigned short int in struct SimpleSprite
         +0x0004 graphics/sprite.h: *24
hhposr           unsigned short int in struct Custom
         +0x01da hardware/custom.h: *136
hhposw           unsigned short int in struct Custom
         +0x01d8 hardware/custom.h: *135
hifillPen        #define FILLPEN = 0x00000005  intuition/iobsolete.h: *266
hifilltextPen    #define FILLTEXTPEN = 0x00000006  intuition/iobsolete.h: *267
hilighttextPen   #define HIGHLIGHTTEXTPEN = 0x00000008
                 intuition/iobsolete.h: *269
hour             unsigned short int in struct ClockData
         +0x0004 utility/date.h: *22
hsstop           unsigned short int in struct Custom
         +0x01c2 hardware/custom.h: *124
hsstrt           unsigned short int in struct Custom
         +0x01de hardware/custom.h: *138
hsync            struct AnalogSignalInterval(size 0x0004 bytes) in struct
                 SpecialMonitor
         +0x0032 graphics/monitor.h: *152
htotal           unsigned short int in struct Custom
         +0x01c0 hardware/custom.h: *123
HALFTONE_DITHERING #define 0x0200 = 0x00000200  intuition/preferences.h: *256
HAM              #define 0x0800 = 0x00000800  graphics/view.h: *97
HAMLACE_KEY      #define 0x00000804 = 0x00000804  graphics/displayinfo.h: *162
HAM_KEY          #define 0x00000800 = 0x00000800  graphics/displayinfo.h: *158
HARDWARE_ADKBITS_H #define  hardware/adkbits.h: *2
HARDWARE_BLIT_H  #define  hardware/blit.h: *2
HARDWARE_CIA_H   #define  hardware/cia.h: *2
HARDWARE_CUSTOM_H #define  hardware/custom.h: *2, 1
HARDWARE_DMABITS_H #define  hardware/dmabits.h: *2
HARDWARE_INTBITS_H #define  hardware/intbits.h: *2
HASZOOM          #define WFLG_HASZOOM = 0x20000000
                 intuition/iobsolete.h: *172
HD_SCSICMD       #define 28 = 0x0000001c  devices/scsidisk.h: *68
HFERR_BadStatus  #define 45 = 0x0000002d  devices/scsidisk.h: *114
HFERR_DMA        #define 41 = 0x00000029  devices/scsidisk.h: *110
HFERR_NoBoard    #define 50 = 0x00000032  devices/scsidisk.h: *117
HFERR_Parity     #define 43 = 0x0000002b  devices/scsidisk.h: *112
HFERR_Phase      #define 42 = 0x0000002a  devices/scsidisk.h: *111
HFERR_SelTimeout #define 44 = 0x0000002c  devices/scsidisk.h: *113
HFERR_SelfUnit   #define 40 = 0x00000028  devices/scsidisk.h: *109
HIGHBOX          #define 0x0080 = 0x00000080  intuition/intuition.h: *128
HIGHCOMP         #define 0x0040 = 0x00000040  intuition/intuition.h: *127
HIGHFLAGS        #define 0x00C0 = 0x000000c0  intuition/intuition.h: *125
HIGHIMAGE        #define 0x0000 = 0x00000000  intuition/intuition.h: *126
HIGHITEM         #define 0x2000 = 0x00002000  intuition/intuition.h: *136
HIGHLIGHTTEXTPEN #define (0x0008) = 0x00000008  intuition/screens.h: *90
HIGHNONE         #define 0x00C0 = 0x000000c0  intuition/intuition.h: *129
HIRES            #define 0x8000 = 0x00008000  graphics/view.h: *101
HIRESDPF2_KEY    #define 0x00008440 = 0x00008440  graphics/displayinfo.h: *170
HIRESDPF_KEY     #define 0x00008400 = 0x00008400  graphics/displayinfo.h: *164
HIRESGADGET      #define 0 = 0x00000000  intuition/intuitionbase.h: *43
HIRESLACEDPF2_KEY #define 0x00008444 = 0x00008444
                 graphics/displayinfo.h: *173
HIRESLACEDPF_KEY #define 0x00008404 = 0x00008404  graphics/displayinfo.h: *167
HIRESLACE_KEY    #define 0x00008004 = 0x00008004  graphics/displayinfo.h: *160
HIRESPICK        #define 0x0000 = 0x00000000  intuition/intuitionbase.h: *36
HIRES_KEY        #define 0x00008000 = 0x00008000  graphics/displayinfo.h: *156
HOLDNMODIFY      #define 0x800 = 0x00000800  graphics/display.h: *23
HP_LASERJET      #define 0x0B = 0x0000000b  intuition/preferences.h: *204
HP_LASERJET_PLUS #define 0x0C = 0x0000000c  intuition/preferences.h: *205
HPotRes          unsigned short int in struct PropInfo
         +0x000e intuition/intuition.h: *490
HSIZEBITS        #define 6 = 0x00000006  hardware/blit.h: *15
HSIZEMASK        #define 0x3f = 0x0000003f  hardware/blit.h: *17
HSYNCTRUE        #define 0x0001 = 0x00000001  hardware/custom.h: *159
HUNK_BREAK       #define 1014 = 0x000003f6  dos/doshunks.h: *31
HUNK_BSS         #define 1003 = 0x000003eb  dos/doshunks.h: *20
HUNK_CODE        #define 1001 = 0x000003e9  dos/doshunks.h: *18
HUNK_DATA        #define 1002 = 0x000003ea  dos/doshunks.h: *19
HUNK_DEBUG       #define 1009 = 0x000003f1  dos/doshunks.h: *26
HUNK_DREL16      #define 1016 = 0x000003f8  dos/doshunks.h: *34
HUNK_DREL32      #define 1015 = 0x000003f7  dos/doshunks.h: *33
HUNK_DREL8       #define 1017 = 0x000003f9  dos/doshunks.h: *35
HUNK_END         #define 1010 = 0x000003f2  dos/doshunks.h: *27
HUNK_EXT         #define 1007 = 0x000003ef  dos/doshunks.h: *24
HUNK_HEADER      #define 1011 = 0x000003f3  dos/doshunks.h: *28
HUNK_INDEX       #define 1019 = 0x000003fb  dos/doshunks.h: *38
HUNK_LIB         #define 1018 = 0x000003fa  dos/doshunks.h: *37
HUNK_NAME        #define 1000 = 0x000003e8  dos/doshunks.h: *17
HUNK_OVERLAY     #define 1013 = 0x000003f5  dos/doshunks.h: *30
HUNK_RELOC16     #define 1005 = 0x000003ed  dos/doshunks.h: *22
HUNK_RELOC32     #define 1004 = 0x000003ec  dos/doshunks.h: *21
HUNK_RELOC8      #define 1006 = 0x000003ee  dos/doshunks.h: *23
HUNK_SYMBOL      #define 1008 = 0x000003f0  dos/doshunks.h: *25
HUNK_UNIT        #define 999 = 0x000003e7  dos/doshunks.h: *16
HWAITPOS         #define u3.u4.u2.HWaitPos  graphics/copper.h: *51
HWaitPos         short int in union (no tag)  +0x0000 graphics/copper.h: *41
HeadComp         pointer to struct AnimComp in struct AnimOb
         +0x0024 graphics/gels.h: *222
HeadOb           pointer to struct AnimOb in struct AnimComp
         +0x001e graphics/gels.h: *195
Header           struct QueryHeader(size 0x0010 bytes) in struct DisplayInfo
         +0x0000 graphics/displayinfo.h: *52
Header           struct QueryHeader(size 0x0010 bytes) in struct DimensionInfo
         +0x0000 graphics/displayinfo.h: *94
Header           struct QueryHeader(size 0x0010 bytes) in struct MonitorInfo
         +0x0000 graphics/displayinfo.h: *111
Header           struct QueryHeader(size 0x0010 bytes) in struct NameInfo
         +0x0000 graphics/displayinfo.h: *134
Height           short int in struct Layer +0x0088 graphics/clip.h: *57
Height           short int in struct Menu +0x000a intuition/intuition.h: *66
Height           short int in struct MenuItem
         +0x000a intuition/intuition.h: *94
Height           short int in struct Requester
         +0x000a intuition/intuition.h: *150
Height           short int in struct Gadget +0x000a intuition/intuition.h: *221
Height           short int in struct Image +0x0006 intuition/intuition.h: *624
Height           short int in struct IBox +0x0006 intuition/intuition.h: *787
Height           short int in struct Window +0x000a intuition/intuition.h: *800
Height           short int in struct NewWindow
         +0x0006 intuition/intuition.h: *977
Height           short int in struct ExtNewWindow
         +0x0006 intuition/intuition.h: *1047
Height           short int in struct Screen +0x000e intuition/screens.h: *104
Height           short int in struct NewScreen
         +0x0006 intuition/screens.h: *312
Height           short int in struct ExtNewScreen
         +0x0006 intuition/screens.h: *348
Height           short int in struct VSprite +0x001a graphics/gels.h: *98
Height           short int in struct (no tag)
         +0x0002 intuition/imageclass.h: *166
Height           short int in struct (no tag)
         +0x0002 intuition/imageclass.h: *183
Height           short int in struct (no tag)
         +0x0002 intuition/imageclass.h: *198
HitMask          short int in struct VSprite +0x0022 graphics/gels.h: *103
Hook             structure tag size 0x0014 utility/hooks.h: *24
                 graphics/clip.h: 53
                 dos/exall.h: 63
                 intuition/classes.h: 29
                 intuition/sghooks.h: 27
HorizBody        unsigned short int in struct PropInfo
         +0x0006 intuition/intuition.h: *484
HorizPot         unsigned short int in struct PropInfo
         +0x0002 intuition/intuition.h: *464


2.0 IncludeXREF: I

id_BytesPerBlock long int in struct InfoData +0x0014 dos/dos.h: *125
id_DiskState     long int in struct InfoData +0x0008 dos/dos.h: *122
id_DiskType      long int in struct InfoData +0x0018 dos/dos.h: *126
id_InUse         long int in struct InfoData +0x0020 dos/dos.h: *128
id_NumBlocks     long int in struct InfoData +0x000c dos/dos.h: *123
id_NumBlocksUsed long int in struct InfoData +0x0010 dos/dos.h: *124
id_NumSoftErrors long int in struct InfoData +0x0000 dos/dos.h: *120
id_UnitNumber    long int in struct InfoData +0x0004 dos/dos.h: *121
id_VolumeNode    long int in struct InfoData +0x001c dos/dos.h: *127
ie_Class         unsigned char in struct InputEvent
         +0x0004 devices/inputevent.h: *201
ie_Code          unsigned short int in struct InputEvent
         +0x0006 devices/inputevent.h: *203
ie_EventAddress  #define ie_position.ie_addr  devices/inputevent.h: *223
ie_NextEvent     pointer to struct InputEvent in struct InputEvent
         +0x0000 devices/inputevent.h: *200
ie_Prev1DownCode #define ie_position.ie_dead.ie_prev1DownCode
                 devices/inputevent.h: *224
ie_Prev1DownQual #define ie_position.ie_dead.ie_prev1DownQual
                 devices/inputevent.h: *225
ie_Prev2DownCode #define ie_position.ie_dead.ie_prev2DownCode
                 devices/inputevent.h: *226
ie_Prev2DownQual #define ie_position.ie_dead.ie_prev2DownQual
                 devices/inputevent.h: *227
ie_Qualifier     unsigned short int in struct InputEvent
         +0x0008 devices/inputevent.h: *204
ie_SubClass      unsigned char in struct InputEvent
         +0x0005 devices/inputevent.h: *202
ie_TimeStamp     struct timeval(size 0x0008 bytes) in struct InputEvent
         +0x000e devices/inputevent.h: *218
ie_X             #define ie_position.ie_xy.ie_x  devices/inputevent.h: *221
ie_Y             #define ie_position.ie_xy.ie_y  devices/inputevent.h: *222
ie_addr          pointer to void in union (no tag)
         +0x0000 devices/inputevent.h: *210
ie_dead          struct (no tag) (size 0x0004 bytes) in union (no tag)
         +0x0000 devices/inputevent.h: *216
ie_position      union (no tag) (size 0x0004 bytes) in struct InputEvent
         +0x000a devices/inputevent.h: *217
ie_prev1DownCode unsigned char in struct (no tag)
         +0x0000 devices/inputevent.h: *212
ie_prev1DownQual unsigned char in struct (no tag)
         +0x0001 devices/inputevent.h: *213
ie_prev2DownCode unsigned char in struct (no tag)
         +0x0002 devices/inputevent.h: *214
ie_prev2DownQual unsigned char in struct (no tag)
         +0x0003 devices/inputevent.h: *215
ie_x             short int in struct (no tag)
         +0x0000 devices/inputevent.h: *207
ie_xy            struct (no tag) (size 0x0004 bytes) in union (no tag)
         +0x0000 devices/inputevent.h: *209
ie_y             short int in struct (no tag)
         +0x0002 devices/inputevent.h: *208
iepp_Position    struct (no tag) (size 0x0004 bytes) in struct IEPointerPixel
         +0x0004 devices/inputevent.h: *93
iepp_Screen      pointer to struct Screen in struct IEPointerPixel
         +0x0000 devices/inputevent.h: *89
iept_Pressure    short int in struct IEPointerTablet
         +0x0008 devices/inputevent.h: *118
iept_Range       struct (no tag) (size 0x0004 bytes) in struct IEPointerTablet
         +0x0000 devices/inputevent.h: *112
iept_Value       struct (no tag) (size 0x0004 bytes) in struct IEPointerTablet
         +0x0004 devices/inputevent.h: *116
iff_Depth        long int in struct IFFHandle +0x0008 libraries/iffparse.h: *38
iff_Flags        unsigned long int in struct IFFHandle
         +0x0004 libraries/iffparse.h: *37
iff_Stream       unsigned long int in struct IFFHandle
         +0x0000 libraries/iffparse.h: *36
impDraw          structure tag size 0x0018 intuition/imageclass.h: *152
impErase         structure tag (size 0x0010 bytes)in struct impErase
                 intuition/imageclass.h: *172
impFrameBox      structure tag size 0x0014 intuition/imageclass.h: *139
impHitTest       structure tag (size 0x000c bytes)in struct impHitTest
                 intuition/imageclass.h: *188
imp_ContentsBox pointer to struct IBox in struct impFrameBox
         +0x0004 intuition/imageclass.h: *141
imp_Dimensions   struct (no tag) (size 0x0004 bytes) in struct impDraw
         +0x0014 intuition/imageclass.h: *167
imp_Dimensions   struct (no tag) (size 0x0004 bytes) in struct impErase
         +0x000c intuition/imageclass.h: *184
imp_Dimensions   struct (no tag) (size 0x0004 bytes) in struct impHitTest
         +0x0008 intuition/imageclass.h: *199
imp_DrInfo       pointer to struct DrawInfo in struct impFrameBox
         +0x000c intuition/imageclass.h: *143
imp_DrInfo       pointer to struct DrawInfo in struct impDraw
         +0x0010 intuition/imageclass.h: *161
imp_FrameBox     pointer to struct IBox in struct impFrameBox
         +0x0008 intuition/imageclass.h: *142
imp_FrameFlags   unsigned long int in struct impFrameBox
         +0x0010 intuition/imageclass.h: *144
imp_Offset       struct (no tag) (size 0x0004 bytes) in struct impDraw
         +0x0008 intuition/imageclass.h: *158
imp_Offset       struct (no tag) (size 0x0004 bytes) in struct impErase
         +0x0008 intuition/imageclass.h: *178
imp_Point        struct (no tag) (size 0x0004 bytes) in struct impHitTest
         +0x0004 intuition/imageclass.h: *193
imp_RPort        pointer to struct RastPort in struct impDraw
         +0x0004 intuition/imageclass.h: *154
imp_RPort        pointer to struct RastPort in struct impErase
         +0x0004 intuition/imageclass.h: *174
imp_State        unsigned long int in struct impDraw
         +0x000c intuition/imageclass.h: *160
intena           unsigned short int in struct Custom
         +0x009a hardware/custom.h: *94
intenar          unsigned short int in struct Custom
         +0x001c hardware/custom.h: *42
intreq           unsigned short int in struct Custom
         +0x009c hardware/custom.h: *95
intreqr          unsigned short int in struct Custom
         +0x001e hardware/custom.h: *43
io_Actual        unsigned long int in struct IOStdReq +0x0020 exec/io.h: *36
io_Actual        unsigned long int in struct IOClipReq
         +0x0020 devices/clipboard.h: *50
io_Baud          unsigned long int in struct IOExtSer
         +0x003c devices/serial.h: *65
io_BrkTime       unsigned long int in struct IOExtSer
         +0x0040 devices/serial.h: *66
io_ClipID        long int in struct IOClipReq +0x0030 devices/clipboard.h: *54
io_ColorMap      pointer to struct ColorMap in struct IODRPReq
         +0x0024 devices/printer.h: *164
io_Command       unsigned short int in struct IORequest +0x001c exec/io.h: *24
io_Command       unsigned short int in struct IOStdReq +0x001c exec/io.h: *33
io_Command       unsigned short int in struct IOClipReq
         +0x001c devices/clipboard.h: *47
io_Command       unsigned short int in struct IOPrtCmdReq
         +0x001c devices/printer.h: *146
io_Command       unsigned short int in struct IODRPReq
         +0x001c devices/printer.h: *160
io_CtlChar       unsigned long int in struct IOExtSer
         +0x0030 devices/serial.h: *62
io_Data          pointer to void in struct IOStdReq +0x0028 exec/io.h: *38
io_Data          pointer to unsigned char in struct IOClipReq
         +0x0028 devices/clipboard.h: *52
io_DestCols      long int in struct IODRPReq +0x0034 devices/printer.h: *170
io_DestRows      long int in struct IODRPReq +0x0038 devices/printer.h: *171
io_Device        pointer to struct Device in struct IORequest
         +0x0014 exec/io.h: *22
io_Device        pointer to struct Device in struct IOStdReq
         +0x0014 exec/io.h: *31
io_Device        pointer to struct Device in struct IOClipReq
         +0x0014 devices/clipboard.h: *45
io_Device        pointer to struct Device in struct IOPrtCmdReq
         +0x0014 devices/printer.h: *144
io_Device        pointer to struct Device in struct IODRPReq
         +0x0014 devices/printer.h: *158
io_Error         char in struct IORequest +0x001f exec/io.h: *26
io_Error         char in struct IOStdReq +0x001f exec/io.h: *35
io_Error         char in struct IOClipReq +0x001f devices/clipboard.h: *49
io_Error         char in struct IOPrtCmdReq +0x001f devices/printer.h: *148
io_Error         char in struct IODRPReq +0x001f devices/printer.h: *162
io_ExtFlags      unsigned long int in struct IOExtSer
         +0x0038 devices/serial.h: *64
io_Flags         unsigned char in struct IORequest +0x001e exec/io.h: *25
io_Flags         unsigned char in struct IOStdReq +0x001e exec/io.h: *34
io_Flags         unsigned char in struct IOClipReq
         +0x001e devices/clipboard.h: *48
io_Flags         unsigned char in struct IOPrtCmdReq
         +0x001e devices/printer.h: *147
io_Flags         unsigned char in struct IODRPReq
         +0x001e devices/printer.h: *161
io_Length        unsigned long int in struct IOStdReq +0x0024 exec/io.h: *37
io_Length        unsigned long int in struct IOClipReq
         +0x0024 devices/clipboard.h: *51
io_Message       struct Message(size 0x0014 bytes) in struct IORequest
         +0x0000 exec/io.h: *21
io_Message       struct Message(size 0x0014 bytes) in struct IOStdReq
         +0x0000 exec/io.h: *30
io_Message       struct Message(size 0x0014 bytes) in struct IOClipReq
         +0x0000 devices/clipboard.h: *44
io_Message       struct Message(size 0x0014 bytes) in struct IOPrtCmdReq
         +0x0000 devices/printer.h: *143
io_Message       struct Message(size 0x0014 bytes) in struct IODRPReq
         +0x0000 devices/printer.h: *157
io_Modes         unsigned long int in struct IODRPReq
         +0x0028 devices/printer.h: *165
io_Offset        unsigned long int in struct IOStdReq +0x002c exec/io.h: *39
io_Offset        unsigned long int in struct IOClipReq
         +0x002c devices/clipboard.h: *53
io_PExtFlags     unsigned long int in struct IOExtPar
         +0x0030 devices/parallel.h: *52
io_PTermArray    struct IOPArray(size 0x0008 bytes) in struct IOExtPar
         +0x0036 devices/parallel.h: *55
io_ParFlags      unsigned char in struct IOExtPar
         +0x0035 devices/parallel.h: *54
io_Parm0         unsigned char in struct IOPrtCmdReq
         +0x0022 devices/printer.h: *150
io_Parm1         unsigned char in struct IOPrtCmdReq
         +0x0023 devices/printer.h: *151
io_Parm2         unsigned char in struct IOPrtCmdReq
         +0x0024 devices/printer.h: *152
io_Parm3         unsigned char in struct IOPrtCmdReq
         +0x0025 devices/printer.h: *153
io_PrtCommand    unsigned short int in struct IOPrtCmdReq
         +0x0020 devices/printer.h: *149
io_RBufLen       unsigned long int in struct IOExtSer
         +0x0034 devices/serial.h: *63
io_RastPort      pointer to struct RastPort in struct IODRPReq
         +0x0020 devices/printer.h: *163
io_ReadLen       unsigned char in struct IOExtSer +0x004c devices/serial.h: *68
io_SerFlags      unsigned char in struct IOExtSer +0x004f devices/serial.h: *71
io_Special       unsigned short int in struct IODRPReq
         +0x003c devices/printer.h: *172
io_SrcHeight     unsigned short int in struct IODRPReq
         +0x0032 devices/printer.h: *169
io_SrcWidth      unsigned short int in struct IODRPReq
         +0x0030 devices/printer.h: *168
io_SrcX          unsigned short int in struct IODRPReq
         +0x002c devices/printer.h: *166
io_SrcY          unsigned short int in struct IODRPReq
         +0x002e devices/printer.h: *167
io_Status        unsigned char in struct IOExtPar
         +0x0034 devices/parallel.h: *53
io_Status        unsigned short int in struct IOExtSer
         +0x0050 devices/serial.h: *72
io_StopBits      unsigned char in struct IOExtSer +0x004e devices/serial.h: *70
io_TermArray     struct IOTArray(size 0x0008 bytes) in struct IOExtSer
         +0x0044 devices/serial.h: *67
io_Unit          pointer to struct Unit in struct IORequest
         +0x0018 exec/io.h: *23
io_Unit          pointer to struct Unit in struct IOStdReq
         +0x0018 exec/io.h: *32
io_Unit          pointer to struct ClipboardUnitPartial in struct IOClipReq
         +0x0018 devices/clipboard.h: *46
io_Unit          pointer to struct Unit in struct IOPrtCmdReq
         +0x0018 devices/printer.h: *145
io_Unit          pointer to struct Unit in struct IODRPReq
         +0x0018 devices/printer.h: *159
io_WriteLen      unsigned char in struct IOExtSer +0x004d devices/serial.h: *69
ioa_AllocKey     short int in struct IOAudio +0x0020 devices/audio.h: *49
ioa_Cycles       unsigned short int in struct IOAudio
         +0x002e devices/audio.h: *54
ioa_Data         pointer to unsigned char in struct IOAudio
         +0x0022 devices/audio.h: *50
ioa_Length       unsigned long int in struct IOAudio
         +0x0026 devices/audio.h: *51
ioa_Period       unsigned short int in struct IOAudio
         +0x002a devices/audio.h: *52
ioa_Request      struct IORequest(size 0x0020 bytes) in struct IOAudio
         +0x0000 devices/audio.h: *48
ioa_Volume       unsigned short int in struct IOAudio
         +0x002c devices/audio.h: *53
ioa_WriteMsg     struct Message(size 0x0014 bytes) in struct IOAudio
         +0x0030 devices/audio.h: *55
iobArea          array [204] of char in struct IoBuff
         +0x0034 rexx/rexxio.h: *32
iobBct           long int in struct IoBuff +0x0030 rexx/rexxio.h: *31
iobDFH           long int in struct IoBuff +0x0028 rexx/rexxio.h: *29
iobLock          pointer to void in struct IoBuff +0x002c rexx/rexxio.h: *30
iobNode          struct RexxRsrc(size 0x0020 bytes) in struct IoBuff
         +0x0000 rexx/rexxio.h: *26
iobRct           long int in struct IoBuff +0x0024 rexx/rexxio.h: *28
iobRpt           pointer to void in struct IoBuff +0x0020 rexx/rexxio.h: *27
iotd_Count       unsigned long int in struct IOExtTD
         +0x0030 devices/trackdisk.h: *121
iotd_Req         struct IOStdReq(size 0x0030 bytes) in struct IOExtTD
         +0x0000 devices/trackdisk.h: *120
iotd_SecLabel    unsigned long int in struct IOExtTD
         +0x0034 devices/trackdisk.h: *122
is_Code          pointer to function returning void in struct Interrupt
         +0x0012 exec/interrupts.h: *27
is_Data          pointer to void in struct Interrupt
         +0x000e exec/interrupts.h: *26
is_Node          struct Node(size 0x000e bytes) in struct Interrupt
         +0x0000 exec/interrupts.h: *25
is_Node          struct Node(size 0x000e bytes) in struct Isrvstr
         +0x0000 graphics/graphint.h: *22
itof             macro (1 argument)   libraries/mathffp.h: *33
                 libraries/mathieeedp.h: *33
iv_Code          pointer to function returning void in struct IntVector
         +0x0004 exec/interrupts.h: *33
iv_Data          pointer to void in struct IntVector
         +0x0000 exec/interrupts.h: *32
iv_Node          pointer to struct Node in struct IntVector
         +0x0008 exec/interrupts.h: *34
ix_Class         unsigned char in struct InputXpression
         +0x0001 libraries/commodities.h: *175
ix_Code          unsigned short int in struct InputXpression
         +0x0002 libraries/commodities.h: *177
ix_CodeMask      unsigned short int in struct InputXpression
         +0x0004 libraries/commodities.h: *179
ix_QualMask      unsigned short int in struct InputXpression
         +0x0008 libraries/commodities.h: *185
ix_QualSame      unsigned short int in struct InputXpression
         +0x000a libraries/commodities.h: *189
ix_Qualifier     unsigned short int in struct InputXpression
         +0x0006 libraries/commodities.h: *183
ix_Version       unsigned char in struct InputXpression
         +0x0000 libraries/commodities.h: *174
IA_APATSIZE      #define IA_APatSize = 0x80020011  intuition/iobsolete.h: *246
IA_APATTERN      #define IA_APattern = 0x80020010  intuition/iobsolete.h: *245
IA_APatSize      #define (IA_Dummy + 0x11) = 0x80020011
                 intuition/imageclass.h: *63
IA_APattern      #define (IA_Dummy + 0x10) = 0x80020010
                 intuition/imageclass.h: *62
IA_BGPEN         #define IA_BGPen = 0x80020006  intuition/iobsolete.h: *240
IA_BGPen         #define (IA_Dummy + 0x06) = 0x80020006
                 intuition/imageclass.h: *41
IA_DATA          #define IA_Data = 0x80020007  intuition/iobsolete.h: *241
IA_DOUBLEEMBOSS  #define IA_DoubleEmboss = 0x80020016
                 intuition/iobsolete.h: *251
IA_Data          #define (IA_Dummy + 0x07) = 0x80020007
                 intuition/imageclass.h: *43
IA_DoubleEmboss  #define (IA_Dummy + 0x16) = 0x80020016
                 intuition/imageclass.h: *68
IA_Dummy         #define (TAG_USER + 0x20000) = 0x80020000
                 intuition/imageclass.h: *34
IA_EDGESONLY     #define IA_EdgesOnly = 0x80020017
                 intuition/iobsolete.h: *252
IA_EdgesOnly     #define (IA_Dummy + 0x17) = 0x80020017
                 intuition/imageclass.h: *69
IA_FGPEN         #define IA_FGPen = 0x80020005  intuition/iobsolete.h: *239
IA_FGPen         #define (IA_Dummy + 0x05) = 0x80020005
                 intuition/imageclass.h: *39
IA_FONT          #define IA_Font = 0x80020013  intuition/iobsolete.h: *248
IA_Font          #define (IA_Dummy + 0x13) = 0x80020013
                 intuition/imageclass.h: *65
IA_HEIGHT        #define IA_Height = 0x80020004  intuition/iobsolete.h: *238
IA_HIGHLIGHTPEN  #define IA_HighlightPen = 0x8002000a
                 intuition/iobsolete.h: *254
IA_Height        #define (IA_Dummy + 0x04) = 0x80020004
                 intuition/imageclass.h: *38
IA_HighlightPen  #define (IA_Dummy + 0x0A) = 0x8002000a
                 intuition/imageclass.h: *86
IA_LEFT          #define IA_Left = 0x80020001  intuition/iobsolete.h: *235
IA_LINEWIDTH     #define IA_LineWidth = 0x80020008
                 intuition/iobsolete.h: *242
IA_Left          #define (IA_Dummy + 0x01) = 0x80020001
                 intuition/imageclass.h: *35
IA_LineWidth     #define (IA_Dummy + 0x08) = 0x80020008
                 intuition/imageclass.h: *47
IA_MODE          #define IA_Mode = 0x80020012  intuition/iobsolete.h: *247
IA_Mode          #define (IA_Dummy + 0x12) = 0x80020012
                 intuition/imageclass.h: *64
IA_OUTLINE       #define IA_Outline = 0x80020014  intuition/iobsolete.h: *249
IA_Outline       #define (IA_Dummy + 0x14) = 0x80020014
                 intuition/imageclass.h: *66
IA_PENS          #define IA_Pens = 0x8002000e  intuition/iobsolete.h: *243
IA_Pens          #define (IA_Dummy + 0x0E) = 0x8002000e
                 intuition/imageclass.h: *48
IA_RECESSED      #define IA_Recessed = 0x80020015  intuition/iobsolete.h: *250
IA_RESOLUTION    #define IA_Resolution = 0x8002000f
                 intuition/iobsolete.h: *244
IA_Recessed      #define (IA_Dummy + 0x15) = 0x80020015
                 intuition/imageclass.h: *67
IA_Resolution    #define (IA_Dummy + 0x0F) = 0x8002000f
                 intuition/imageclass.h: *55
IA_SHADOWPEN     #define IA_ShadowPen = 0x80020009
                 intuition/iobsolete.h: *253
IA_ShadowPen     #define (IA_Dummy + 0x09) = 0x80020009
                 intuition/imageclass.h: *85
IA_TOP           #define IA_Top = 0x80020002  intuition/iobsolete.h: *236
IA_Top           #define (IA_Dummy + 0x02) = 0x80020002
                 intuition/imageclass.h: *36
IA_WIDTH         #define IA_Width = 0x80020003  intuition/iobsolete.h: *237
IA_Width         #define (IA_Dummy + 0x03) = 0x80020003
                 intuition/imageclass.h: *37
IAddress         pointer to void in struct IntuiMessage
         +0x001c intuition/intuition.h: *695
IBox             structure tag size 0x0008 intuition/intuition.h: *783
                 intuition/cghooks.h: 49, 72, 73
                 intuition/imageclass.h: 141, 142
ICA_Dummy        #define (TAG_USER+0x40000L) = 0x80040000
                 intuition/icclass.h: *28
ICA_MAP          #define (ICA_Dummy + 2) = 0x80040002
                 intuition/icclass.h: *31
ICA_TARGET       #define (ICA_Dummy + 1) = 0x80040001
                 intuition/icclass.h: *29
ICCLASS          #define "icclass"  intuition/classusr.h: *53
ICM_CHECKLOOP    #define (0x0404L) = 0x00000404  intuition/icclass.h: *23
ICM_CLEARLOOP    #define (0x0403L) = 0x00000403  intuition/icclass.h: *22
ICM_Dummy        #define (0x0401L) = 0x00000401  intuition/icclass.h: *20
ICM_SETLOOP      #define (0x0402L) = 0x00000402  intuition/icclass.h: *21
ICONNAME         #define "icon.library"  workbench/icon.h: *15
ICSPECIAL_CODE   #define (ICA_Dummy + 3) = 0x80040003
                 intuition/icclass.h: *33
ICTARGET_IDCMP   #define (~0L) = 0xffffffff  intuition/icclass.h: *48
IClass           structure tag size 0x0034 intuition/classes.h: *28, 31, 70
IDCMPFlags       unsigned long int in struct Window
         +0x0052 intuition/intuition.h: *855
IDCMPFlags       unsigned long int in struct NewWindow
         +0x000a intuition/intuition.h: *981
IDCMPFlags       unsigned long int in struct ExtNewWindow
         +0x000a intuition/intuition.h: *1050
IDCMPUPDATE      #define IDCMP_IDCMPUPDATE = 0x00800000
                 intuition/iobsolete.h: *137
IDCMPWindow      pointer to struct Window in struct IntuiMessage
         +0x002c intuition/intuition.h: *713
IDCMP_ACTIVEWINDOW #define 0x00040000 = 0x00040000
                 intuition/intuition.h: *742
IDCMP_CHANGEWINDOW #define 0x02000000 = 0x02000000
                 intuition/intuition.h: *752
IDCMP_CLOSEWINDOW #define 0x00000200 = 0x00000200  intuition/intuition.h: *733
IDCMP_DELTAMOVE  #define 0x00100000 = 0x00100000  intuition/intuition.h: *744
IDCMP_DISKINSERTED #define 0x00008000 = 0x00008000
                 intuition/intuition.h: *739
IDCMP_DISKREMOVED #define 0x00010000 = 0x00010000  intuition/intuition.h: *740
IDCMP_GADGETDOWN #define 0x00000020 = 0x00000020  intuition/intuition.h: *729
IDCMP_GADGETUP   #define 0x00000040 = 0x00000040  intuition/intuition.h: *730
IDCMP_IDCMPUPDATE #define 0x00800000 = 0x00800000  intuition/intuition.h: *748
IDCMP_INACTIVEWINDOW #define 0x00080000 = 0x00080000
                 intuition/intuition.h: *743
IDCMP_INTUITICKS #define 0x00400000 = 0x00400000  intuition/intuition.h: *746
IDCMP_LONELYMESSAGE #define 0x80000000 = 0x80000000
                 intuition/intuition.h: *761
IDCMP_MENUHELP   #define 0x01000000 = 0x01000000  intuition/intuition.h: *750
IDCMP_MENUPICK   #define 0x00000100 = 0x00000100  intuition/intuition.h: *732
IDCMP_MENUVERIFY #define 0x00002000 = 0x00002000  intuition/intuition.h: *737
IDCMP_MOUSEBUTTONS #define 0x00000008 = 0x00000008
                 intuition/intuition.h: *727
IDCMP_MOUSEMOVE  #define 0x00000010 = 0x00000010  intuition/intuition.h: *728
IDCMP_NEWPREFS   #define 0x00004000 = 0x00004000  intuition/intuition.h: *738
IDCMP_NEWSIZE    #define 0x00000002 = 0x00000002  intuition/intuition.h: *725
IDCMP_RAWKEY     #define 0x00000400 = 0x00000400  intuition/intuition.h: *734
IDCMP_REFRESHWINDOW #define 0x00000004 = 0x00000004
                 intuition/intuition.h: *726
IDCMP_REQCLEAR   #define 0x00001000 = 0x00001000  intuition/intuition.h: *736
IDCMP_REQSET     #define 0x00000080 = 0x00000080  intuition/intuition.h: *731
IDCMP_REQVERIFY  #define 0x00000800 = 0x00000800  intuition/intuition.h: *735
IDCMP_SIZEVERIFY #define 0x00000001 = 0x00000001  intuition/intuition.h: *724
IDCMP_VANILLAKEY #define 0x00200000 = 0x00200000  intuition/intuition.h: *745
IDCMP_WBENCHMESSAGE #define 0x00020000 = 0x00020000
                 intuition/intuition.h: *741
IDNAME_BADBLOCK  #define 0x42414442 = 0x42414442  devices/hardblocks.h: *125
IDNAME_FILESYSHEADER #define 0x46534844 = 0x46534844
                 devices/hardblocks.h: *182
IDNAME_LOADSEG   #define 0x4C534547 = 0x4c534547  devices/hardblocks.h: *195
IDNAME_PARTITION #define 0x50415254 = 0x50415254  devices/hardblocks.h: *144
IDNAME_RIGIDDISK #define 0x5244534B = 0x5244534b  devices/hardblocks.h: *92
IDNestCnt        char in struct ExecBase +0x0126 exec/execbase.h: *70
IDS_BUSY         #define (3L) = 0x00000003  intuition/imageclass.h: *129
IDS_DISABLED     #define (2L) = 0x00000002  intuition/imageclass.h: *128
IDS_INACTIVEDISABLED #define (7L) = 0x00000007  intuition/imageclass.h: *133
IDS_INACTIVENORMAL #define (5L) = 0x00000005  intuition/imageclass.h: *131
IDS_INACTIVESELECTED #define (6L) = 0x00000006  intuition/imageclass.h: *132
IDS_INDETERMINANT #define IDS_INDETERMINATE = 0x00000004
                 intuition/imageclass.h: *136
IDS_INDETERMINATE #define (4L) = 0x00000004  intuition/imageclass.h: *130
IDS_NORMAL       #define (0L) = 0x00000000  intuition/imageclass.h: *126
IDS_SELECTED     #define (1L) = 0x00000001  intuition/imageclass.h: *127
ID_CAT           #define MAKE_ID('C','A','T',' ') = 0x43415420
                 libraries/iffparse.h: *150
ID_DOS_DISK      #define (0x444F5300L) = 0x444f5300  dos/dos.h: *140
ID_FFS_DISK      #define (0x444F5301L) = 0x444f5301  dos/dos.h: *141
ID_FORM          #define MAKE_ID('F','O','R','M') = 0x464f524d
                 libraries/iffparse.h: *148
ID_KICKSTART_DISK #define (0x4B49434BL) = 0x4b49434b  dos/dos.h: *143
ID_LIST          #define MAKE_ID('L','I','S','T') = 0x4c495354
                 libraries/iffparse.h: *149
ID_MSDOS_DISK    #define (0x4d534400L) = 0x4d534400  dos/dos.h: *144
ID_NOT_REALLY_DOS #define (0x4E444F53L) = 0x4e444f53  dos/dos.h: *142
ID_NO_DISK_PRESENT #define (-1) = 0xffffffff  dos/dos.h: *138
ID_NULL          #define MAKE_ID(' ',' ',' ',' ') = 0x20202020
                 libraries/iffparse.h: *152
ID_PROP          #define MAKE_ID('P','R','O','P') = 0x50524f50
                 libraries/iffparse.h: *151
ID_UNREADABLE_DISK #define (0x42414400L) = 0x42414400  dos/dos.h: *139
ID_VALIDATED     #define 82 = 0x00000052  dos/dos.h: *135
ID_VALIDATING    #define 81 = 0x00000051  dos/dos.h: *134
ID_WRITE_PROTECTED #define 80 = 0x00000050  dos/dos.h: *133
IECLASS_ACTIVEWINDOW #define 0x11 = 0x00000011  devices/inputevent.h: *55
IECLASS_CHANGEWINDOW #define 0x15 = 0x00000015  devices/inputevent.h: *63
IECLASS_CLOSEWINDOW #define 0x0B = 0x0000000b  devices/inputevent.h: *43
IECLASS_DISKINSERTED #define 0x10 = 0x00000010  devices/inputevent.h: *53
IECLASS_DISKREMOVED #define 0x0F = 0x0000000f  devices/inputevent.h: *51
IECLASS_EVENT    #define 0x03 = 0x00000003  devices/inputevent.h: *29
IECLASS_GADGETDOWN #define 0x07 = 0x00000007  devices/inputevent.h: *35
IECLASS_GADGETUP #define 0x08 = 0x00000008  devices/inputevent.h: *37
IECLASS_INACTIVEWINDOW #define 0x12 = 0x00000012  devices/inputevent.h: *57
IECLASS_MAX      #define 0x15 = 0x00000015  devices/inputevent.h: *66
                 devices/conunit.h: 99
IECLASS_MENUHELP #define 0x14 = 0x00000014  devices/inputevent.h: *61
IECLASS_MENULIST #define 0x0A = 0x0000000a  devices/inputevent.h: *41
IECLASS_NEWPOINTERPOS #define 0x13 = 0x00000013  devices/inputevent.h: *59
IECLASS_NEWPREFS #define 0x0E = 0x0000000e  devices/inputevent.h: *49
IECLASS_NULL     #define 0x00 = 0x00000000  devices/inputevent.h: *23
IECLASS_POINTERPOS #define 0x04 = 0x00000004  devices/inputevent.h: *31
IECLASS_RAWKEY   #define 0x01 = 0x00000001  devices/inputevent.h: *25
IECLASS_RAWMOUSE #define 0x02 = 0x00000002  devices/inputevent.h: *27
IECLASS_REFRESHWINDOW #define 0x0D = 0x0000000d  devices/inputevent.h: *47
IECLASS_REQUESTER #define 0x09 = 0x00000009  devices/inputevent.h: *39
IECLASS_SIZEWINDOW #define 0x0C = 0x0000000c  devices/inputevent.h: *45
IECLASS_TIMER    #define 0x06 = 0x00000006  devices/inputevent.h: *33
IECODE_ASCII_DEL #define 0x7F = 0x0000007f  devices/inputevent.h: *136
IECODE_ASCII_FIRST #define 0x20 = 0x00000020  devices/inputevent.h: *134
IECODE_ASCII_LAST #define 0x7E = 0x0000007e  devices/inputevent.h: *135
IECODE_C0_FIRST  #define 0x00 = 0x00000000  devices/inputevent.h: *132
IECODE_C0_LAST   #define 0x1F = 0x0000001f  devices/inputevent.h: *133
IECODE_C1_FIRST  #define 0x80 = 0x00000080  devices/inputevent.h: *137
IECODE_C1_LAST   #define 0x9F = 0x0000009f  devices/inputevent.h: *138
IECODE_COMM_CODE_FIRST #define 0x78 = 0x00000078  devices/inputevent.h: *128
IECODE_COMM_CODE_LAST #define 0x7F = 0x0000007f  devices/inputevent.h: *129
IECODE_KEY_CODE_FIRST #define 0x00 = 0x00000000  devices/inputevent.h: *126
IECODE_KEY_CODE_LAST #define 0x77 = 0x00000077  devices/inputevent.h: *127
IECODE_LATIN1_FIRST #define 0xA0 = 0x000000a0  devices/inputevent.h: *139
IECODE_LATIN1_LAST #define 0xFF = 0x000000ff  devices/inputevent.h: *140
IECODE_LBUTTON   #define 0x68 = 0x00000068  devices/inputevent.h: *143
IECODE_MBUTTON   #define 0x6A = 0x0000006a  devices/inputevent.h: *145
IECODE_NEWACTIVE #define 0x01 = 0x00000001  devices/inputevent.h: *149
IECODE_NEWSIZE   #define 0x02 = 0x00000002  devices/inputevent.h: *150
IECODE_NOBUTTON  #define 0xFF = 0x000000ff  devices/inputevent.h: *146
IECODE_RBUTTON   #define 0x69 = 0x00000069  devices/inputevent.h: *144
IECODE_REFRESH   #define 0x03 = 0x00000003  devices/inputevent.h: *151
IECODE_REQCLEAR  #define 0x00 = 0x00000000  devices/inputevent.h: *158
IECODE_REQSET    #define 0x01 = 0x00000001  devices/inputevent.h: *156
IECODE_UP_PREFIX #define 0x80 = 0x00000080  devices/inputevent.h: *125
IEEEDPACos       function returning "LONG"   libraries/mathieeedp.h: *57
IEEEDPASin       function returning "LONG"   libraries/mathieeedp.h: *58
IEEEDPAbs        function returning "LONG"   libraries/mathieeedp.h: *70
IEEEDPAdd        function returning "LONG"   libraries/mathieeedp.h: *72
IEEEDPAtan       function returning "LONG"   libraries/mathieeedp.h: *56
IEEEDPCeil       function returning "LONG"   libraries/mathieeedp.h: *77
IEEEDPCos        function returning "LONG"   libraries/mathieeedp.h: *57
IEEEDPCosh       function returning "LONG"   libraries/mathieeedp.h: *63
IEEEDPDiv        function returning "LONG"   libraries/mathieeedp.h: *75
IEEEDPExp        function returning "LONG"   libraries/mathieeedp.h: *59
IEEEDPFieee      function returning "LONG"   libraries/mathieeedp.h: *65
IEEEDPFloor      function returning "LONG"   libraries/mathieeedp.h: *76
IEEEDPFlt        function returning "LONG"   libraries/mathieeedp.h: *69
IEEEDPLog        function returning "LONG"   libraries/mathieeedp.h: *59
IEEEDPLog10      function returning "LONG"   libraries/mathieeedp.h: *61
IEEEDPMul        function returning "LONG"   libraries/mathieeedp.h: *74
IEEEDPNeg        function returning "LONG"   libraries/mathieeedp.h: *71
IEEEDPPow        function returning "LONG"   libraries/mathieeedp.h: *61
IEEEDPSin        function returning "LONG"   libraries/mathieeedp.h: *58
IEEEDPSincos     function returning "LONG"   libraries/mathieeedp.h: *62
IEEEDPSinh       function returning "LONG"   libraries/mathieeedp.h: *63
IEEEDPSqrt       function returning "LONG"   libraries/mathieeedp.h: *60
IEEEDPSub        function returning "LONG"   libraries/mathieeedp.h: *73
IEEEDPTan        function returning "LONG"   libraries/mathieeedp.h: *56
IEEEDPTanh       function returning "LONG"   libraries/mathieeedp.h: *63
IEEEDPTieee      function returning "LONG"   libraries/mathieeedp.h: *64
IEPointerPixel   structure tag size 0x0008 devices/inputevent.h: *88
IEPointerTablet structure tag (size 0x000a bytes)in struct IEPointerTablet
                 devices/inputevent.h: *108
IEQUALIFIERB_CAPSLOCK #define 2 = 0x00000002  devices/inputevent.h: *182
IEQUALIFIERB_CONTROL #define 3 = 0x00000003  devices/inputevent.h: *183
IEQUALIFIERB_INTERRUPT #define 10 = 0x0000000a  devices/inputevent.h: *190
IEQUALIFIERB_LALT #define 4 = 0x00000004  devices/inputevent.h: *184
IEQUALIFIERB_LCOMMAND #define 6 = 0x00000006  devices/inputevent.h: *186
IEQUALIFIERB_LEFTBUTTON #define 14 = 0x0000000e  devices/inputevent.h: *194
IEQUALIFIERB_LSHIFT #define 0 = 0x00000000  devices/inputevent.h: *180
IEQUALIFIERB_MIDBUTTON #define 12 = 0x0000000c  devices/inputevent.h: *192
IEQUALIFIERB_MULTIBROADCAST #define 11 = 0x0000000b
                 devices/inputevent.h: *191
IEQUALIFIERB_NUMERICPAD #define 8 = 0x00000008  devices/inputevent.h: *188
IEQUALIFIERB_RALT #define 5 = 0x00000005  devices/inputevent.h: *185
IEQUALIFIERB_RBUTTON #define 13 = 0x0000000d  devices/inputevent.h: *193
IEQUALIFIERB_RCOMMAND #define 7 = 0x00000007  devices/inputevent.h: *187
IEQUALIFIERB_RELATIVEMOUSE #define 15 = 0x0000000f  devices/inputevent.h: *195
IEQUALIFIERB_REPEAT #define 9 = 0x00000009  devices/inputevent.h: *189
IEQUALIFIERB_RSHIFT #define 1 = 0x00000001  devices/inputevent.h: *181
IEQUALIFIER_CAPSLOCK #define 0x0004 = 0x00000004  devices/inputevent.h: *165
IEQUALIFIER_CONTROL #define 0x0008 = 0x00000008  devices/inputevent.h: *166
IEQUALIFIER_INTERRUPT #define 0x0400 = 0x00000400  devices/inputevent.h: *173
IEQUALIFIER_LALT #define 0x0010 = 0x00000010  devices/inputevent.h: *167
IEQUALIFIER_LCOMMAND #define 0x0040 = 0x00000040  devices/inputevent.h: *169
IEQUALIFIER_LEFTBUTTON #define 0x4000 = 0x00004000  devices/inputevent.h: *177
IEQUALIFIER_LSHIFT #define 0x0001 = 0x00000001  devices/inputevent.h: *163
IEQUALIFIER_MIDBUTTON #define 0x1000 = 0x00001000  devices/inputevent.h: *175
IEQUALIFIER_MULTIBROADCAST #define 0x0800 = 0x00000800
                 devices/inputevent.h: *174
IEQUALIFIER_NUMERICPAD #define 0x0100 = 0x00000100  devices/inputevent.h: *171
IEQUALIFIER_RALT #define 0x0020 = 0x00000020  devices/inputevent.h: *168
IEQUALIFIER_RBUTTON #define 0x2000 = 0x00002000  devices/inputevent.h: *176
IEQUALIFIER_RCOMMAND #define 0x0080 = 0x00000080  devices/inputevent.h: *170
IEQUALIFIER_RELATIVEMOUSE #define 0x8000 = 0x00008000
                 devices/inputevent.h: *178
IEQUALIFIER_REPEAT #define 0x0200 = 0x00000200  devices/inputevent.h: *172
IEQUALIFIER_RSHIFT #define 0x0002 = 0x00000002  devices/inputevent.h: *164
IESUBCLASS_COMPATIBLE #define 0x00 = 0x00000000  devices/inputevent.h: *72
IESUBCLASS_PIXEL #define 0x01 = 0x00000001  devices/inputevent.h: *74
IESUBCLASS_TABLET #define 0x02 = 0x00000002  devices/inputevent.h: *76
IEvent           pointer to struct InputEvent in struct SGWork
         +0x0014 intuition/sghooks.h: *42
IFFCMD_CLEANUP   #define 1 = 0x00000001  libraries/iffparse.h: *189
IFFCMD_ENTRY     #define 5 = 0x00000005  libraries/iffparse.h: *193
IFFCMD_EXIT      #define 6 = 0x00000006  libraries/iffparse.h: *194
IFFCMD_INIT      #define 0 = 0x00000000  libraries/iffparse.h: *188
IFFCMD_PURGELCI  #define 7 = 0x00000007  libraries/iffparse.h: *195
IFFCMD_READ      #define 2 = 0x00000002  libraries/iffparse.h: *190
IFFCMD_SEEK      #define 4 = 0x00000004  libraries/iffparse.h: *192
IFFCMD_WRITE     #define 3 = 0x00000003  libraries/iffparse.h: *191
IFFERR_EOC       #define -2L = 0xfffffffe  libraries/iffparse.h: *130
IFFERR_EOF       #define -1L = 0xffffffff  libraries/iffparse.h: *129
IFFERR_MANGLED   #define -8L = 0xfffffff8  libraries/iffparse.h: *136
IFFERR_NOHOOK    #define -11L = 0xfffffff5  libraries/iffparse.h: *139
IFFERR_NOMEM     #define -4L = 0xfffffffc  libraries/iffparse.h: *132
IFFERR_NOSCOPE   #define -3L = 0xfffffffd  libraries/iffparse.h: *131
IFFERR_NOTIFF    #define -10L = 0xfffffff6  libraries/iffparse.h: *138
IFFERR_READ      #define -5L = 0xfffffffb  libraries/iffparse.h: *133
IFFERR_SEEK      #define -7L = 0xfffffff9  libraries/iffparse.h: *135
IFFERR_SYNTAX    #define -9L = 0xfffffff7  libraries/iffparse.h: *137
IFFERR_WRITE     #define -6L = 0xfffffffa  libraries/iffparse.h: *134
IFFF_FSEEK       #define (1L<<1) = 0x00000002  libraries/iffparse.h: *48
IFFF_READ        #define 0L = 0x00000000  libraries/iffparse.h: *45
IFFF_RESERVED    #define 0xFFFF0000L = 0xffff0000  libraries/iffparse.h: *50
IFFF_RSEEK       #define (1L<<2) = 0x00000004  libraries/iffparse.h: *49
IFFF_RWBITS      #define (IFFF_READ | IFFF_WRITE) = 0x00000001
                 libraries/iffparse.h: *47
IFFF_WRITE       #define 1L = 0x00000001  libraries/iffparse.h: *46
IFFHandle        structure tag size 0x000c libraries/iffparse.h: *35
IFFLCI_COLLECTION #define MAKE_ID('c','o','l','l') = 0x636f6c6c
                 libraries/iffparse.h: *158
IFFLCI_ENTRYHANDLER #define MAKE_ID('e','n','h','d') = 0x656e6864
                 libraries/iffparse.h: *159
IFFLCI_EXITHANDLER #define MAKE_ID('e','x','h','d') = 0x65786864
                 libraries/iffparse.h: *160
IFFLCI_PROP      #define MAKE_ID('p','r','o','p') = 0x70726f70
                 libraries/iffparse.h: *157
IFFPARSE_RAWSTEP #define 2L = 0x00000002  libraries/iffparse.h: *167
IFFPARSE_SCAN    #define 0L = 0x00000000  libraries/iffparse.h: *165
IFFPARSE_STEP    #define 1L = 0x00000001  libraries/iffparse.h: *166
IFFSCC_CLEANUP   #define IFFCMD_CLEANUP = 0x00000001
                 libraries/iffparse.h: *199
IFFSCC_INIT      #define IFFCMD_INIT = 0x00000000  libraries/iffparse.h: *198
IFFSCC_READ      #define IFFCMD_READ = 0x00000002  libraries/iffparse.h: *200
IFFSCC_SEEK      #define IFFCMD_SEEK = 0x00000004  libraries/iffparse.h: *202
IFFSCC_WRITE     #define IFFCMD_WRITE = 0x00000003  libraries/iffparse.h: *201
IFFSIZE_UNKNOWN  #define -1L = 0xffffffff  libraries/iffparse.h: *182
IFFSLI_PROP      #define 3L = 0x00000003  libraries/iffparse.h: *174
IFFSLI_ROOT      #define 1L = 0x00000001  libraries/iffparse.h: *172
IFFSLI_TOP       #define 2L = 0x00000002  libraries/iffparse.h: *173
IFFStreamCmd     structure tag size 0x000c libraries/iffparse.h: *56
IFF_IFFPARSE_H   #define  libraries/iffparse.h: *2
IFF_RETURN2CLIENT #define -12L = 0xfffffff4  libraries/iffparse.h: *140
IFont            pointer to struct TextFont in struct Window
         +0x0080 intuition/intuition.h: *895
IGNORE_DIMENSIONS #define 0x0000 = 0x00000000  intuition/preferences.h: *247
IMAGECLASS       #define "imageclass"  intuition/classusr.h: *43
IMAGE_ATTRIBUTES #define (IA_Dummy) = 0x80020000  intuition/iobsolete.h: *234
IMAGE_NEGATIVE   #define 0x01 = 0x00000001  intuition/preferences.h: *173
IMAGE_POSITIVE   #define 0x00 = 0x00000000  intuition/preferences.h: *172
IMPORT           #define extern  exec/types.h: *21
IM_BGPEN         macro (1 argument)   intuition/imageclass.h: *31
IM_BOX           macro (1 argument)   intuition/imageclass.h: *29
IM_DRAW          #define 0x202L = 0x00000202  intuition/imageclass.h: *115
IM_DRAWFRAME     #define 0x206L = 0x00000206  intuition/imageclass.h: *120
IM_ERASE         #define 0x204L = 0x00000204  intuition/imageclass.h: *117
IM_ERASEFRAME    #define 0x209L = 0x00000209  intuition/imageclass.h: *123
IM_FGPEN         macro (1 argument)   intuition/imageclass.h: *30
IM_FRAMEBOX      #define 0x207L = 0x00000207  intuition/imageclass.h: *121
IM_HITFRAME      #define 0x208L = 0x00000208  intuition/imageclass.h: *122
IM_HITTEST       #define 0x203L = 0x00000203  intuition/imageclass.h: *116
IM_ITEM          #define (NM_ITEM | MENU_IMAGE) = 0x00000082
                 libraries/gadtools.h: *140
IM_MOVE          #define 0x205L = 0x00000205  intuition/imageclass.h: *118
IM_SUB           #define (NM_SUB | MENU_IMAGE) = 0x00000083
                 libraries/gadtools.h: *141
INACTIVEWINDOW   #define IDCMP_INACTIVEWINDOW = 0x00080000
                 intuition/iobsolete.h: *133
INCLUDE_VERSION  #define 36 = 0x00000024  exec/types.h: *17
IND_ADDHANDLER   #define (CMD_NONSTD+0) = 0x00000009  devices/input.h: *19
IND_REMHANDLER   #define (CMD_NONSTD+1) = 0x0000000a  devices/input.h: *20
IND_SETMPORT     #define (CMD_NONSTD+5) = 0x0000000e  devices/input.h: *24
IND_SETMTRIG     #define (CMD_NONSTD+7) = 0x00000010  devices/input.h: *26
IND_SETMTYPE     #define (CMD_NONSTD+6) = 0x0000000f  devices/input.h: *25
IND_SETPERIOD    #define (CMD_NONSTD+4) = 0x0000000d  devices/input.h: *23
IND_SETTHRESH    #define (CMD_NONSTD+3) = 0x0000000c  devices/input.h: *22
IND_WRITEEVENT   #define (CMD_NONSTD+2) = 0x0000000b  devices/input.h: *21
INITBYTE         macro (2 arguments)   exec/initializers.h: *17
INITLONG         macro (2 arguments)   exec/initializers.h: *21
INITSTRUCT       macro (4 arguments)   exec/initializers.h: *25
INITWORD         macro (2 arguments)   exec/initializers.h: *18
INREQUEST        #define WFLG_INREQUEST = 0x00004000
                 intuition/iobsolete.h: *162
INST_DATA        macro (2 arguments)   intuition/classes.h: *48
INTB_AUD0        #define (7) = 0x00000007  hardware/intbits.h: *25
INTB_AUD1        #define (8) = 0x00000008  hardware/intbits.h: *24
INTB_AUD2        #define (9) = 0x00000009  hardware/intbits.h: *23
INTB_AUD3        #define (10) = 0x0000000a  hardware/intbits.h: *22
INTB_BLIT        #define (6) = 0x00000006  hardware/intbits.h: *26
INTB_COPER       #define (4) = 0x00000004  hardware/intbits.h: *28
INTB_DSKBLK      #define (1) = 0x00000001  hardware/intbits.h: *31
INTB_DSKSYNC     #define (12) = 0x0000000c  hardware/intbits.h: *20
INTB_EXTER       #define (13) = 0x0000000d  hardware/intbits.h: *19
INTB_INTEN       #define (14) = 0x0000000e  hardware/intbits.h: *18
INTB_NMI         #define 15 = 0x0000000f  exec/interrupts.h: *46
INTB_PORTS       #define (3) = 0x00000003  hardware/intbits.h: *29
INTB_RBF         #define (11) = 0x0000000b  hardware/intbits.h: *21
INTB_SETCLR      #define (15) = 0x0000000f  hardware/intbits.h: *15
INTB_SOFTINT     #define (2) = 0x00000002  hardware/intbits.h: *30
INTB_TBE         #define (0) = 0x00000000  hardware/intbits.h: *32
INTB_VERTB       #define (5) = 0x00000005  hardware/intbits.h: *27
INTEGERIDCMP     #define (IDCMP_GADGETUP) = 0x00000040
                 libraries/gadtools.h: *68
INTEGER_KIND     #define 3 = 0x00000003  libraries/gadtools.h: *37
INTEGER_SCALING  #define 0x0100 = 0x00000100  intuition/preferences.h: *253
INTERHEIGHT      #define 4 = 0x00000004  libraries/gadtools.h: *88
INTERLACE        #define 4 = 0x00000004  graphics/display.h: *24
INTERWIDTH       #define 8 = 0x00000008  libraries/gadtools.h: *87
INTF_AUD0        #define (1<<7) = 0x00000080  hardware/intbits.h: *44
INTF_AUD1        #define (1<<8) = 0x00000100  hardware/intbits.h: *43
INTF_AUD2        #define (1<<9) = 0x00000200  hardware/intbits.h: *42
INTF_AUD3        #define (1<<10) = 0x00000400  hardware/intbits.h: *41
INTF_BLIT        #define (1<<6) = 0x00000040  hardware/intbits.h: *45
INTF_COPER       #define (1<<4) = 0x00000010  hardware/intbits.h: *47
INTF_DSKBLK      #define (1<<1) = 0x00000002  hardware/intbits.h: *50
INTF_DSKSYNC     #define (1<<12) = 0x00001000  hardware/intbits.h: *39
INTF_EXTER       #define (1<<13) = 0x00002000  hardware/intbits.h: *38
INTF_INTEN       #define (1<<14) = 0x00004000  hardware/intbits.h: *37
INTF_NMI         #define (1<<15) = 0x00008000  exec/interrupts.h: *47
INTF_PORTS       #define (1<<3) = 0x00000008  hardware/intbits.h: *48
INTF_RBF         #define (1<<11) = 0x00000800  hardware/intbits.h: *40
INTF_SETCLR      #define (1<<15) = 0x00008000  hardware/intbits.h: *36
INTF_SOFTINT     #define (1<<2) = 0x00000004  hardware/intbits.h: *49
INTF_TBE         #define (1<<0) = 0x00000001  hardware/intbits.h: *51
INTF_VERTB       #define (1<<5) = 0x00000020  hardware/intbits.h: *46
INTUITICKS       #define IDCMP_INTUITICKS = 0x00400000
                 intuition/iobsolete.h: *136
INTUITION_CGHOOKS_H #define 1 = 0x00000001  intuition/cghooks.h: *2
INTUITION_CLASSES_H #define 1 = 0x00000001  intuition/classes.h: *2
INTUITION_CLASSUSR_H #define 1 = 0x00000001  intuition/classusr.h: *2, 1
INTUITION_GADGETCLASS_H #define 1 = 0x00000001  intuition/gadgetclass.h: *2
INTUITION_ICCLASS_H #define  intuition/icclass.h: *2
INTUITION_IMAGECLASS_H #define TRUE = 0x00000001  intuition/imageclass.h: *2
INTUITION_INTUITIONBASE_H #define 1 = 0x00000001
                 intuition/intuitionbase.h: *2
INTUITION_INTUITION_H #define TRUE = 0x00000001  intuition/intuition.h: *2, 1
                 intuition/iobsolete.h: 38
                 intuition/cghooks.h: 19
                 intuition/gadgetclass.h: 19
                 intuition/intuitionbase.h: 23
                 libraries/gadtools.h: 25
                 workbench/workbench.h: 31
INTUITION_IOBSOLETE_H #define  intuition/iobsolete.h: *2, 1
                 intuition/intuition.h: 1357
                 intuition/gadgetclass.h: 244
                 intuition/imageclass.h: 203
INTUITION_PREFERENCES_H #define TRUE = 0x00000001
                 intuition/preferences.h: *2, 1
INTUITION_SCREENS_H #define TRUE = 0x00000001  intuition/screens.h: *2, 1
INTUITION_SGHOOKS_H #define TRUE = 0x00000001  intuition/sghooks.h: *2
INVALID_ID       #define ~0 = 0xffffffff  graphics/displayinfo.h: *141
INVERSVID        #define 4 = 0x00000004  graphics/rastport.h: *97
IOAudio          structure tag size 0x0044 devices/audio.h: *47
IOB_QUICK        #define 0 = 0x00000000  exec/io.h: *47
IOClipReq        structure tag size 0x0034 devices/clipboard.h: *43
                 libraries/iffparse.h: 117
IODRPReq         structure tag size 0x003e devices/printer.h: *156
IOERR_ABORTED    #define (-2) = 0xfffffffe  exec/errors.h: *16
IOERR_BADADDRESS #define (-5) = 0xfffffffb  exec/errors.h: *19
IOERR_BADLENGTH  #define (-4) = 0xfffffffc  exec/errors.h: *18
IOERR_NOCMD      #define (-3) = 0xfffffffd  exec/errors.h: *17
IOERR_OPENFAIL   #define (-1) = 0xffffffff  exec/errors.h: *15
IOERR_SELFTEST   #define (-7) = 0xfffffff9  exec/errors.h: *21
IOERR_UNITBUSY   #define (-6) = 0xfffffffa  exec/errors.h: *20
IOExtPar         structure tag size 0x003e devices/parallel.h: *29
                 devices/prtbase.h: 76, 84
IOExtSer         structure tag size 0x0052 devices/serial.h: *38
                 devices/prtbase.h: 77, 85
IOExtTD          structure tag size 0x0038 devices/trackdisk.h: *119
IOF_QUICK        #define (1<<0) = 0x00000001  exec/io.h: *48
IOPARB_ABORT     #define 5 = 0x00000005  devices/parallel.h: *75
IOPARB_ACTIVE    #define 4 = 0x00000004  devices/parallel.h: *77
IOPARB_QUEUED    #define 6 = 0x00000006  devices/parallel.h: *73
IOPARF_ABORT     #define (1<<5) = 0x00000020  devices/parallel.h: *76
IOPARF_ACTIVE    #define (1<<4) = 0x00000010  devices/parallel.h: *78
IOPARF_QUEUED    #define (1<<6) = 0x00000040  devices/parallel.h: *74
IOPArray         structure tag size 0x0008 devices/parallel.h: *19, 55
IOPTB_PAPEROUT   #define 1 = 0x00000001  devices/parallel.h: *85
IOPTB_PARBUSY    #define 0 = 0x00000000  devices/parallel.h: *87
IOPTB_PARSEL     #define 2 = 0x00000002  devices/parallel.h: *81
IOPTB_RWDIR      #define 3 = 0x00000003  devices/parallel.h: *79
IOPTF_PAPEROUT   #define (1<<1) = 0x00000002  devices/parallel.h: *86
IOPTF_PARBUSY    #define (1<<0) = 0x00000001  devices/parallel.h: *88
IOPTF_PARSEL     #define (1<<2) = 0x00000004  devices/parallel.h: *84
IOPTF_RWDIR      #define (1<<3) = 0x00000008  devices/parallel.h: *80
IOPar            struct IOStdReq(size 0x0030 bytes) in struct IOExtPar
         +0x0000 devices/parallel.h: *30
IOPrtCmdReq      structure tag size 0x0026 devices/printer.h: *142
IORequest        structure tag size 0x0020 exec/io.h: *20
                 devices/audio.h: 48
                 devices/timer.h: 38
IOSer            struct IOStdReq(size 0x0030 bytes) in struct IOExtSer
         +0x0000 devices/serial.h: *39
IOStdReq         structure tag size 0x0030 exec/io.h: *29
                 devices/narrator.h: 94
                 devices/parallel.h: 30
                 devices/serial.h: 39
                 devices/trackdisk.h: 120
IOTArray         structure tag size 0x0008 devices/serial.h: *22, 67
IOTDB_INDEXSYNC  #define 4 = 0x00000004  devices/trackdisk.h: *173
IOTDB_WORDSYNC   #define 5 = 0x00000005  devices/trackdisk.h: *179
IOTDF_INDEXSYNC  #define (1<<4) = 0x00000010  devices/trackdisk.h: *174
IOTDF_WORDSYNC   #define (1<<5) = 0x00000020  devices/trackdisk.h: *180
IO_STATB_OVERRUN #define 8 = 0x00000008  devices/serial.h: *126
IO_STATB_READBREAK #define 10 = 0x0000000a  devices/serial.h: *122
IO_STATB_WROTEBREAK #define 9 = 0x00000009  devices/serial.h: *124
IO_STATB_XOFFREAD #define 12 = 0x0000000c  devices/serial.h: *118
IO_STATB_XOFFWRITE #define 11 = 0x0000000b  devices/serial.h: *120
IO_STATF_OVERRUN #define (1<<8) = 0x00000100  devices/serial.h: *127
IO_STATF_READBREAK #define (1<<10) = 0x00000400  devices/serial.h: *123
IO_STATF_WROTEBREAK #define (1<<9) = 0x00000200  devices/serial.h: *125
IO_STATF_XOFFREAD #define (1<<12) = 0x00001000  devices/serial.h: *119
IO_STATF_XOFFWRITE #define (1<<11) = 0x00000800  devices/serial.h: *121
ISDRAWN          #define 0x1000 = 0x00001000  intuition/intuition.h: *135
ISGRTRX          #define 4 = 0x00000004  graphics/clip.h: *85
ISGRTRY          #define 8 = 0x00000008  graphics/clip.h: *86
ISLESSX          #define 1 = 0x00000001  graphics/clip.h: *83
ISLESSY          #define 2 = 0x00000002  graphics/clip.h: *84
ITEMENABLED      #define 0x0010 = 0x00000010  intuition/intuition.h: *122
ITEMNUM          macro (1 argument)   intuition/intuition.h: *1267
ITEMTEXT         #define 0x0002 = 0x00000002  intuition/intuition.h: *119
ITEM_EQUAL       #define -2 = 0xfffffffe  dos/dos.h: *230
ITEM_ERROR       #define -1 = 0xffffffff  dos/dos.h: *231
ITEM_NOTHING     #define 0 = 0x00000000  dos/dos.h: *232
ITEM_QUOTED      #define 2 = 0x00000002  dos/dos.h: *234
ITEM_UNQUOTED    #define 1 = 0x00000001  dos/dos.h: *233
IText            pointer to unsigned char in struct IntuiText
         +0x000c intuition/intuition.h: *577
ITextFont        pointer to struct TextAttr in struct IntuiText
         +0x0008 intuition/intuition.h: *576
IVALUE           macro (1 argument)   rexx/storage.h: *51
IX               "LONG"  libraries/commodities.h: *192
IXSYM_ALT        #define 4 = 0x00000004  libraries/commodities.h: *197
IXSYM_ALTMASK    #define (IEQUALIFIER_LALT | IEQUALIFIER_RALT) = 0x00000030
                 libraries/commodities.h: *202
IXSYM_CAPS       #define 2 = 0x00000002  libraries/commodities.h: *196
IXSYM_CAPSMASK   #define (IXSYM_SHIFTMASK | IEQUALIFIER_CAPSLOCK) = 0x00000007
                 libraries/commodities.h: *201
IXSYM_SHIFT      #define 1 = 0x00000001  libraries/commodities.h: *195
IXSYM_SHIFTMASK  #define (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT) = 0x00000003
                 libraries/commodities.h: *200
IX_NORMALQUALS   #define 0x7FFF;  libraries/commodities.h: *204
IX_VERSION       #define 2 = 0x00000002  libraries/commodities.h: *171
IdleCount        unsigned long int in struct ExecBase
         +0x0118 exec/execbase.h: *65
Image            structure tag
     size 0x0014 intuition/intuition.h: *174, 619, 666, 865, 996,
                             1054
ImageBMap        pointer to struct BitMap in struct Requester
         +0x0044 intuition/intuition.h: *171
ImageData        pointer to unsigned short int in struct Image
         +0x000a intuition/intuition.h: *626
ImageData        pointer to short int in struct VSprite
         +0x0024 graphics/gels.h: *105
ImageShadow      pointer to short int in struct Bob
         +0x0006 graphics/gels.h: *148
InfoData         structure tag size 0x0024 dos/dos.h: *119
InitAnimate      macro (1 argument)   graphics/gels.h: *246
InitialModes     unsigned long int in struct StringExtend
         +0x0008 intuition/sghooks.h: *26
InputEvent       structure tag size 0x0016 devices/inputevent.h: *199, 200
                 intuition/gadgetclass.h: 204
                 intuition/sghooks.h: 42
InputXpression   structure tag size 0x000c libraries/commodities.h: *173, 192
IntVector        structure tag size 0x000c exec/interrupts.h: *31
                 exec/execbase.h: 59
IntVects         array [16] of struct IntVector(size 0x000c bytes) in struct
                 ExecBase
         +0x0054 exec/execbase.h: *59
Interrupt        structure tag size 0x0016 exec/interrupts.h: *24
                 graphics/gfxbase.h: 36
                 resources/disk.h: 45, 46, 47, 59, 60, 61
IntrList         struct List(size 0x000e bytes) in struct ExecBase
         +0x016c exec/execbase.h: *89
IntuiMessage     structure tag
     size 0x0034 intuition/intuition.h: *677, 716, 857
IntuiText        structure tag
     size 0x0014 intuition/intuition.h: *155, 240, 570, 578
IntuitionBase    structure tag size 0x0050 intuition/intuitionbase.h: *68
IoBuff           structure tag size 0x0100 rexx/rexxio.h: *25
Iptr             pointer to struct Isrvstr in struct Isrvstr
         +0x000e graphics/graphint.h: *23
IsListEmpty      macro (1 argument)   exec/lists.h: *53
IsMsgPortEmpty   macro (1 argument)   exec/lists.h: *56
Isrvstr          structure tag size 0x001e graphics/graphint.h: *20, 23
ItemFill         pointer to void in struct MenuItem
         +0x0012 intuition/intuition.h: *99


2.0 IncludeXREF: J

joy0dat          unsigned short int in struct Custom
         +0x000a hardware/custom.h: *33
joy1dat          unsigned short int in struct Custom
         +0x000c hardware/custom.h: *34
joytest          unsigned short int in struct Custom
         +0x0036 hardware/custom.h: *54
jump             array [4] of unsigned short int in struct copinit
         +0x0064 graphics/copper.h: *101
JAM1             #define 0 = 0x00000000  graphics/rastport.h: *94
JAM2             #define 1 = 0x00000001  graphics/rastport.h: *95
JazzX            short int in struct Menu +0x0016 intuition/intuition.h: *72
JazzY            short int in struct Menu +0x0018 intuition/intuition.h: *72


2.0 IncludeXREF: K

km_HiCapsable    pointer to unsigned char in struct KeyMap
         +0x0018 devices/keymap.h: *30
km_HiKeyMap      pointer to unsigned long int in struct KeyMap
         +0x0014 devices/keymap.h: *29
km_HiKeyMapTypes pointer to unsigned char in struct KeyMap
         +0x0010 devices/keymap.h: *28
km_HiRepeatable pointer to unsigned char in struct KeyMap
         +0x001c devices/keymap.h: *31
km_LoCapsable    pointer to unsigned char in struct KeyMap
         +0x0008 devices/keymap.h: *26
km_LoKeyMap      pointer to unsigned long int in struct KeyMap
         +0x0004 devices/keymap.h: *25
km_LoKeyMapTypes pointer to unsigned char in struct KeyMap
         +0x0000 devices/keymap.h: *24
km_LoRepeatable pointer to unsigned char in struct KeyMap
         +0x000c devices/keymap.h: *27
kn_KeyMap        struct KeyMap(size 0x0020 bytes) in struct KeyMapNode
         +0x000e devices/keymap.h: *36
kn_Node          struct Node(size 0x000e bytes) in struct KeyMapNode
         +0x0000 devices/keymap.h: *35
kr_List          struct List(size 0x000e bytes) in struct KeyMapResource
         +0x000e devices/keymap.h: *42
kr_Node          struct Node(size 0x000e bytes) in struct KeyMapResource
         +0x0000 devices/keymap.h: *41
KBD_ADDRESETHANDLER #define (CMD_NONSTD+2) = 0x0000000b
                 devices/keyboard.h: *21
KBD_READEVENT    #define (CMD_NONSTD+0) = 0x00000009  devices/keyboard.h: *19
KBD_READMATRIX   #define (CMD_NONSTD+1) = 0x0000000a  devices/keyboard.h: *20
KBD_REMRESETHANDLER #define (CMD_NONSTD+3) = 0x0000000c
                 devices/keyboard.h: *22
KBD_RESETHANDLERDONE #define (CMD_NONSTD+4) = 0x0000000d
                 devices/keyboard.h: *23
KCB_ALT          #define 1 = 0x00000001  devices/keymap.h: *50
KCB_CONTROL      #define 2 = 0x00000002  devices/keymap.h: *52
KCB_DEAD         #define 5 = 0x00000005  devices/keymap.h: *57
KCB_DOWNUP       #define 3 = 0x00000003  devices/keymap.h: *54
KCB_NOP          #define 7 = 0x00000007  devices/keymap.h: *63
KCB_SHIFT        #define 0 = 0x00000000  devices/keymap.h: *48
KCB_STRING       #define 6 = 0x00000006  devices/keymap.h: *60
KCF_ALT          #define 0x02 = 0x00000002  devices/keymap.h: *51
KCF_CONTROL      #define 0x04 = 0x00000004  devices/keymap.h: *53
KCF_DEAD         #define 0x20 = 0x00000020  devices/keymap.h: *58
KCF_DOWNUP       #define 0x08 = 0x00000008  devices/keymap.h: *55
KCF_NOP          #define 0x80 = 0x00000080  devices/keymap.h: *64
KCF_SHIFT        #define 0x01 = 0x00000001  devices/keymap.h: *49
KCF_STRING       #define 0x40 = 0x00000040  devices/keymap.h: *61
KC_NOQUAL        #define 0 = 0x00000000  devices/keymap.h: *46
KC_VANILLA       #define 7 = 0x00000007  devices/keymap.h: *47
KEEPNUM          #define (NSF_STRING | NSF_SOURCE | NSF_NUMBER | NSF_BINARY) =
                 0x0000009a
                 rexx/storage.h: *79
KEEPSTR          #define (NSF_STRING | NSF_SOURCE | NSF_NOTNUM) = 0x00000086
                 rexx/storage.h: *78
KEYCODE_B        #define 0x35 = 0x00000035  intuition/intuition.h: *1350
KEYCODE_GREATER  #define 0x39 = 0x00000039  intuition/intuition.h: *1354
KEYCODE_LESS     #define 0x38 = 0x00000038  intuition/intuition.h: *1353
KEYCODE_M        #define 0x37 = 0x00000037  intuition/intuition.h: *1352
KEYCODE_N        #define 0x36 = 0x00000036  intuition/intuition.h: *1351
KEYCODE_Q        #define 0x10 = 0x00000010  intuition/intuition.h: *1346
KEYCODE_V        #define 0x34 = 0x00000034  intuition/intuition.h: *1349
KEYCODE_X        #define 0x32 = 0x00000032  intuition/intuition.h: *1348
KEYCODE_Z        #define 0x31 = 0x00000031  intuition/intuition.h: *1347
KNOBHIT          #define 0x0100 = 0x00000100  intuition/intuition.h: *507
KNOBHMIN         #define 6 = 0x00000006  intuition/intuition.h: *512
KNOBVMIN         #define 4 = 0x00000004  intuition/intuition.h: *513
KeyMap           structure tag size 0x0020 devices/keymap.h: *23, 36
                 devices/conunit.h: 76
                 intuition/intuition.h: 560
KeyMapNode       structure tag size 0x002e devices/keymap.h: *34
KeyMapResource   structure tag size 0x001c devices/keymap.h: *40
KeyRptDelay      struct timeval(size 0x0008 bytes) in struct Preferences
         +0x000c intuition/preferences.h: *57
KeyRptSpeed      struct timeval(size 0x0008 bytes) in struct Preferences
         +0x0004 intuition/preferences.h: *56
KickCheckSum     pointer to void in struct ExecBase
         +0x022a exec/execbase.h: *124
KickMemPtr       pointer to void in struct ExecBase
         +0x0222 exec/execbase.h: *122
KickTagPtr       pointer to void in struct ExecBase
         +0x0226 exec/execbase.h: *123


2.0 IncludeXREF: L

l_pad            unsigned char in struct List +0x000d exec/lists.h: *27
lastBlissObj     pointer to void in struct GelsInfo
         +0x0022 graphics/rastport.h: *53
lastColor        pointer to pointer to short int in struct GelsInfo
         +0x000e graphics/rastport.h: *50
lci_ID           unsigned long int in struct LocalContextItem
         +0x0008 libraries/iffparse.h: *85
lci_Ident        unsigned long int in struct LocalContextItem
         +0x0010 libraries/iffparse.h: *87
lci_Node         struct MinNode(size 0x0008 bytes) in struct LocalContextItem
         +0x0000 libraries/iffparse.h: *84
lci_Type         unsigned long int in struct LocalContextItem
         +0x000c libraries/iffparse.h: *86
leftmost         short int in struct GelsInfo +0x0016 graphics/rastport.h: *52
lh_Flags         #define lib_Flags  exec/libraries.h: *55
lh_Head          pointer to struct Node in struct List
         +0x0000 exec/lists.h: *23
lh_IdString      #define lib_IdString  exec/libraries.h: *61
lh_NegSize       #define lib_NegSize  exec/libraries.h: *57
lh_Node          #define lib_Node  exec/libraries.h: *54
lh_OpenCnt       #define lib_OpenCnt  exec/libraries.h: *63
lh_PosSize       #define lib_PosSize  exec/libraries.h: *60
lh_Revision      #define lib_Revision  exec/libraries.h: *60
lh_Sum           #define lib_Sum  exec/libraries.h: *62
lh_Tail          pointer to struct Node in struct List
         +0x0004 exec/lists.h: *24
lh_TailPred      pointer to struct Node in struct List
         +0x0008 exec/lists.h: *25
lh_Type          unsigned char in struct List +0x000c exec/lists.h: *26
lh_Version       #define lib_Version  exec/libraries.h: *59
lh_pad           #define lib_pad  exec/libraries.h: *56
lib_Flags        unsigned char in struct Library +0x000e exec/libraries.h: *36
lib_IdString     pointer to void in struct Library
         +0x0018 exec/libraries.h: *42
lib_NegSize      unsigned short int in struct Library
         +0x0010 exec/libraries.h: *38
lib_Node         struct Node(size 0x000e bytes) in struct Library
         +0x0000 exec/libraries.h: *35
lib_OpenCnt      unsigned short int in struct Library
         +0x0020 exec/libraries.h: *44
lib_PosSize      unsigned short int in struct Library
         +0x0012 exec/libraries.h: *39
lib_Revision     unsigned short int in struct Library
         +0x0016 exec/libraries.h: *41
lib_Sum          unsigned long int in struct Library
         +0x001c exec/libraries.h: *43
lib_Version      unsigned short int in struct Library
         +0x0014 exec/libraries.h: *40
lib_pad          unsigned char in struct Library +0x000f exec/libraries.h: *37
linpatcnt        char in struct RastPort +0x001e graphics/rastport.h: *70
ln_Name          pointer to char in struct Node +0x000a exec/nodes.h: *29
ln_Pred          pointer to struct Node in struct Node
         +0x0004 exec/nodes.h: *26
ln_Pri           char in struct Node +0x0009 exec/nodes.h: *28
ln_Succ          pointer to struct Node in struct Node
         +0x0000 exec/nodes.h: *25
ln_Type          unsigned char in struct Node +0x0008 exec/nodes.h: *27
lobs             pointer to struct Layer in struct ClipRect
         +0x0008 graphics/clip.h: *68
log              #define IEEEDPLog  libraries/mathffp.h: *47
                 libraries/mathieeedp.h: *47
log10            #define IEEEDPLog10  libraries/mathffp.h: *48
                 libraries/mathieeedp.h: *48
longreserved     array [2] of unsigned long int in struct RastPort
         +0x0046 graphics/rastport.h: *86
longreserved     long int in struct Layer_Info +0x0054 graphics/layers.h: *42
lsb_ChkSum       long int in struct LoadSegBlock
         +0x0008 devices/hardblocks.h: *188
lsb_HostID       unsigned long int in struct LoadSegBlock
         +0x000c devices/hardblocks.h: *189
lsb_ID           unsigned long int in struct LoadSegBlock
         +0x0000 devices/hardblocks.h: *186
lsb_LoadData     array [123] of unsigned long int in struct LoadSegBlock
         +0x0014 devices/hardblocks.h: *191
lsb_Next         unsigned long int in struct LoadSegBlock
         +0x0010 devices/hardblocks.h: *190
lsb_SummedLongs unsigned long int in struct LoadSegBlock
         +0x0004 devices/hardblocks.h: *187
lv_Flags         unsigned short int in struct LocalVar +0x000e dos/var.h: *29
lv_Len           unsigned long int in struct LocalVar +0x0014 dos/var.h: *31
lv_Node          struct Node(size 0x000e bytes) in struct LocalVar
         +0x0000 dos/var.h: *28
lv_Value         pointer to unsigned char in struct LocalVar
         +0x0010 dos/var.h: *30
LABELIMAGE       #define GFLG_LABELIMAGE = 0x00002000
                 intuition/iobsolete.h: *64
LABELITEXT       #define GFLG_LABELITEXT = 0x00000000
                 intuition/iobsolete.h: *62
LABELMASK        #define GFLG_LABELMASK = 0x00003000
                 intuition/iobsolete.h: *61
LABELSTRING      #define GFLG_LABELSTRING = 0x00001000
                 intuition/iobsolete.h: *63
LACE             #define 0x0004 = 0x00000004  graphics/view.h: *91
LACEWB           #define (1<< 0) = 0x00000001  intuition/preferences.h: *133
LAYERBACKDROP    #define 0x40 = 0x00000040  graphics/layers.h: *27
LAYERREFRESH     #define 0x80 = 0x00000080  graphics/layers.h: *28
LAYERSIMPLE      #define 1 = 0x00000001  graphics/layers.h: *23
LAYERSMART       #define 2 = 0x00000002  graphics/layers.h: *24
LAYERSUPER       #define 4 = 0x00000004  graphics/layers.h: *25
LAYERUPDATING    #define 0x10 = 0x00000010  graphics/layers.h: *26
LAYER_CLIPRECTS_LOST #define 0x100 = 0x00000100  graphics/layers.h: *29
LAYOUTA_Dummy    #define (TAG_USER + 0x38000) = 0x80038000
                 intuition/gadgetclass.h: *151
LAYOUTA_LAYOUTOBJ #define LAYOUTA_LayoutObj = 0x80038001
                 intuition/iobsolete.h: *225
LAYOUTA_LayoutObj #define (LAYOUTA_Dummy + 0x0001) = 0x80038001
                 intuition/gadgetclass.h: *152
LAYOUTA_ORIENTATION #define LAYOUTA_Orientation = 0x80038003
                 intuition/iobsolete.h: *227
LAYOUTA_Orientation #define (LAYOUTA_Dummy + 0x0003) = 0x80038003
                 intuition/gadgetclass.h: *154
LAYOUTA_SPACING  #define LAYOUTA_Spacing = 0x80038002
                 intuition/iobsolete.h: *226
LAYOUTA_Spacing  #define (LAYOUTA_Dummy + 0x0002) = 0x80038002
                 intuition/gadgetclass.h: *153
LCMptr           pointer to unsigned short int in struct GfxBase
         +0x00e4 graphics/gfxbase.h: *64
LDB_ASSIGNS      #define 4 = 0x00000004  dos/dosextens.h: *428
LDB_DEVICES      #define 2 = 0x00000002  dos/dosextens.h: *424
LDB_ENTRY        #define 5 = 0x00000005  dos/dosextens.h: *430
LDB_READ         #define 0 = 0x00000000  dos/dosextens.h: *434
LDB_VOLUMES      #define 3 = 0x00000003  dos/dosextens.h: *426
LDB_WRITE        #define 1 = 0x00000001  dos/dosextens.h: *436
LDF_ALL          #define (LDF_DEVICES|LDF_VOLUMES|LDF_ASSIGNS) = 0x0000001c
                 dos/dosextens.h: *440
LDF_ASSIGNS      #define (1L << LDB_ASSIGNS) = 0x00000010
                 dos/dosextens.h: *429
LDF_DEVICES      #define (1L << LDB_DEVICES) = 0x00000004
                 dos/dosextens.h: *425
LDF_ENTRY        #define (1L << LDB_ENTRY) = 0x00000020  dos/dosextens.h: *431
LDF_READ         #define (1L << LDB_READ) = 0x00000001  dos/dosextens.h: *435
LDF_VOLUMES      #define (1L << LDB_VOLUMES) = 0x00000008
                 dos/dosextens.h: *427
LDF_WRITE        #define (1L << LDB_WRITE) = 0x00000002  dos/dosextens.h: *437
LEFTBORDER       #define GACT_LEFTBORDER = 0x00000020
                 intuition/iobsolete.h: *74
LEFTHIT          #define 4 = 0x00000004  graphics/collide.h: *34
LEFTIMAGE        #define (0x0AL) = 0x0000000a  intuition/imageclass.h: *106
LEN_DATSTRING    #define 16 = 0x00000010  dos/datetime.h: *37
LETTER           #define 0x100 = 0x00000100  intuition/preferences.h: *165
LIBF_CHANGED     #define (1<<1) = 0x00000002  exec/libraries.h: *49
LIBF_DELEXP      #define (1<<3) = 0x00000008  exec/libraries.h: *51
LIBF_SUMMING     #define (1<<0) = 0x00000001  exec/libraries.h: *48
LIBF_SUMUSED     #define (1<<2) = 0x00000004  exec/libraries.h: *50
LIBRARIES_ASL_H  #define 1 = 0x00000001  libraries/asl.h: *2
LIBRARIES_COMMODITIES_H #define  libraries/commodities.h: *2
LIBRARIES_CONFIGREGS_H #define  libraries/configregs.h: *2
                 libraries/configvars.h: 22
LIBRARIES_CONFIGVARS_H #define  libraries/configvars.h: *2
                 libraries/expansionbase.h: 27
LIBRARIES_DISKFONT_H #define  libraries/diskfont.h: *2
LIBRARIES_DOSEXTENS_H #define  libraries/dosextens.h: *2, 1
LIBRARIES_DOS_H  #define  libraries/dos.h: *2, 1
LIBRARIES_EXPANSIONBASE_H #define  libraries/expansionbase.h: *2
LIBRARIES_EXPANSION_H #define  libraries/expansion.h: *2
LIBRARIES_FILEHANDLER_H #define  libraries/filehandler.h: *2
LIBRARIES_GADTOOLS_H #define  libraries/gadtools.h: *2
LIBRARIES_MATHFFP_H #define 1 = 0x00000001  libraries/mathffp.h: *2
LIBRARIES_MATHIEEEDP_H #define  libraries/mathieeedp.h: *2
LIBRARIES_MATHLIBRARY_H #define  libraries/mathlibrary.h: *2
LIBRARIES_TRANSLATOR_H #define  libraries/translator.h: *2
LIBRARY_MINIMUM  #define 33 = 0x00000021  exec/types.h: *85
LIB_BASE         #define (-LIB_VECTSIZE) = 0xfffffffa  exec/libraries.h: *22
LIB_CLOSE        #define (-12) = 0xfffffff4  exec/libraries.h: *28
LIB_EXPUNGE      #define (-18) = 0xffffffee  exec/libraries.h: *29
LIB_EXTFUNC      #define (-24) = 0xffffffe8  exec/libraries.h: *30
LIB_NONSTD       #define (LIB_USERDEF) = 0xffffffe2  exec/libraries.h: *24
LIB_OPEN         #define (-6) = 0xfffffffa  exec/libraries.h: *27
LIB_RESERVED     #define 4 = 0x00000004  exec/libraries.h: *21
LIB_USERDEF      #define (LIB_BASE-(LIB_RESERVED*LIB_VECTSIZE)) = 0xffffffe2
                 exec/libraries.h: *23
LIB_VECTSIZE     #define 6 = 0x00000006  exec/libraries.h: *20
LINEMODE         #define 0x1 = 0x00000001  hardware/blit.h: *67
LINK_HARD        #define 0 = 0x00000000  dos/dos.h: *226
LINK_SOFT        #define 1 = 0x00000001  dos/dos.h: *227
LISTVIEWIDCMP    #define (IDCMP_GADGETUP | IDCMP_GADGETDOWN | IDCMP_MOUSEMOVE
                 | ARROWIDCMP) = 0x00400078
                 libraries/gadtools.h: *70
LISTVIEW_KIND    #define 4 = 0x00000004  libraries/gadtools.h: *38
LLOFFSET         macro (1 argument)   rexx/rexxio.h: *51
LLVERS           macro (1 argument)   rexx/rexxio.h: *52
LMN_REGION       #define -1 = 0xffffffff  graphics/layers.h: *32
LOCK_DIFFERENT   #define -1 = 0xffffffff  dos/dos.h: *219
LOCK_SAME        #define 0 = 0x00000000  dos/dos.h: *217
LOCK_SAME_HANDLER #define 1 = 0x00000001  dos/dos.h: *218
LOFCprList       pointer to struct cprlist in struct View
         +0x0004 graphics/view.h: *61
LOFlist          pointer to unsigned short int in struct GfxBase
         +0x0032 graphics/gfxbase.h: *32
LOG10            #define ((double) 2.302585092994046)
                 libraries/mathffp.h: *24
                 libraries/mathieeedp.h: *26
LOLDIS           #define 0x0800 = 0x00000800  hardware/custom.h: *148
LONELYMESSAGE    #define IDCMP_LONELYMESSAGE = 0x80000000
                 intuition/iobsolete.h: *140
LONG             long int  exec/types.h: *38
LONGBITS         unsigned long int  exec/types.h: *40
LONGINT          #define GACT_LONGINT = 0x00000800  intuition/iobsolete.h: *83
LORESDPF2_KEY    #define 0x00000440 = 0x00000440  graphics/displayinfo.h: *169
LORESDPF_KEY     #define 0x00000400 = 0x00000400  graphics/displayinfo.h: *163
LORESLACEDPF2_KEY #define 0x00000444 = 0x00000444
                 graphics/displayinfo.h: *172
LORESLACEDPF_KEY #define 0x00000404 = 0x00000404  graphics/displayinfo.h: *166
LORESLACE_KEY    #define 0x00000004 = 0x00000004  graphics/displayinfo.h: *159
LORES_KEY        #define 0x00000000 = 0x00000000  graphics/displayinfo.h: *155
LORIENT_HORIZ    #define 1 = 0x00000001  intuition/gadgetclass.h: *158
LORIENT_NONE     #define 0 = 0x00000000  intuition/gadgetclass.h: *157
LORIENT_VERT     #define 2 = 0x00000002  intuition/gadgetclass.h: *159
LOWCHECKWIDTH    #define 13 = 0x0000000d  intuition/intuition.h: *1302
LOWCOMMWIDTH     #define 16 = 0x00000010  intuition/intuition.h: *1303
LOWRESGADGET     #define 1 = 0x00000001  intuition/intuitionbase.h: *44
LOWRESPICK       #define 0x0001 = 0x00000001  intuition/intuitionbase.h: *37
LVB_IGNORE       #define 7 = 0x00000007  dos/var.h: *43
LVF_IGNORE       #define 0x80 = 0x00000080  dos/var.h: *44
LV_ALIAS         #define 1 = 0x00000001  dos/var.h: *41
LV_VAR           #define 0 = 0x00000000  dos/var.h: *40
LW_RESERVED      #define 1 = 0x00000001  intuition/preferences.h: *134
LaceWB           unsigned char in struct Preferences
         +0x00b9 intuition/preferences.h: *110
LastAlert        array [4] of long int in struct ExecBase
         +0x0202 exec/execbase.h: *99
LastChanceMemory pointer to struct SignalSemaphore in struct GfxBase
         +0x00e0 graphics/gfxbase.h: *63
Layer            structure tag size 0x00a0 graphics/clip.h: *34, 36, 68
                 graphics/rastport.h: 58
                 graphics/layers.h: 36, 37
                 intuition/intuition.h: 161, 890
                 intuition/screens.h: 145
                 intuition/cghooks.h: 38
Layer            pointer to struct Layer in struct RastPort
         +0x0000 graphics/rastport.h: *58
LayerInfo        pointer to struct Layer_Info in struct Layer
         +0x0044 graphics/clip.h: *51
LayerInfo        struct Layer_Info(size 0x0066 bytes) in struct Screen
         +0x00e0 intuition/screens.h: *130
LayerInfo_extra pointer to void in struct Layer_Info
         +0x0062 graphics/layers.h: *48
LayerInfo_extra_size unsigned short int in struct Layer_Info
         +0x005c graphics/layers.h: *46
Layer_Info       structure tag size 0x0066 graphics/clip.h: *51
                 graphics/layers.h: 34
                 intuition/screens.h: 130
Left             short int in struct IBox +0x0000 intuition/intuition.h: *784
LeftBorder       unsigned short int in struct PropInfo
         +0x0012 intuition/intuition.h: *491
LeftEdge         short int in struct Menu +0x0004 intuition/intuition.h: *65
LeftEdge         short int in struct MenuItem
         +0x0004 intuition/intuition.h: *93
LeftEdge         short int in struct Requester
         +0x0004 intuition/intuition.h: *149
LeftEdge         short int in struct Gadget +0x0004 intuition/intuition.h: *220
LeftEdge         short int in struct IntuiText
         +0x0004 intuition/intuition.h: *574
LeftEdge         short int in struct Border +0x0000 intuition/intuition.h: *600
LeftEdge         short int in struct Image +0x0000 intuition/intuition.h: *621
LeftEdge         short int in struct Window +0x0004 intuition/intuition.h: *799
LeftEdge         short int in struct NewWindow
         +0x0000 intuition/intuition.h: *976
LeftEdge         short int in struct ExtNewWindow
         +0x0000 intuition/intuition.h: *1046
LeftEdge         short int in struct Screen +0x0008 intuition/screens.h: *103
LeftEdge         short int in struct NewScreen
         +0x0000 intuition/screens.h: *312
LeftEdge         short int in struct ExtNewScreen
         +0x0000 intuition/screens.h: *348
Length           unsigned long int in struct QueryHeader
         +0x000c graphics/displayinfo.h: *47
LibList          struct List(size 0x000e bytes) in struct ExecBase
         +0x017a exec/execbase.h: *90
LibNode          struct Library(size 0x0022 bytes) in struct ExecBase
         +0x0000 exec/execbase.h: *37
LibNode          struct Library(size 0x0022 bytes) in struct GfxBase
         +0x0000 graphics/gfxbase.h: *27
LibNode          struct Library(size 0x0022 bytes) in struct IntuitionBase
         +0x0000 intuition/intuitionbase.h: *70
LibNode          struct Library(size 0x0022 bytes) in struct ExpansionBase
         +0x0000 libraries/expansionbase.h: *48
Library          structure tag size 0x0022 exec/libraries.h: *34
                 exec/devices.h: 27
                 exec/execbase.h: 37
                 dos/dosextens.h: 229, 237
                 devices/prtbase.h: 52
                 graphics/gfxbase.h: 27
                 intuition/intuitionbase.h: 70
                 libraries/expansionbase.h: 48
                 libraries/mathlibrary.h: 23
                 resources/disk.h: 51, 55, 56
                 rexx/rxslib.h: 27
LinePtrn         unsigned short int in struct RastPort
         +0x0022 graphics/rastport.h: *73
List             structure tag size 0x000e exec/lists.h: *22
                 exec/tasks.h: 47
                 exec/ports.h: 35
                 exec/interrupts.h: 39
                 exec/execbase.h: 86, 87, 88, 89, 90, 91, 92, 93,
                             114
                 devices/keymap.h: 42
                 graphics/monitor.h: 50
                 graphics/layers.h: 41
                 graphics/gfxbase.h: 37, 50, 52, 86
                 intuition/classusr.h: 119
                 libraries/expansionbase.h: 54, 55
                 resources/disk.h: 58
                 resources/filesysres.h: 30
                 rexx/storage.h: 201, 202, 203, 204, 205
                 rexx/rexxio.h: 67
                 rexx/rxslib.h: 58, 60, 62, 64, 66
                 workbench/workbench.h: 85
LoadSegBlock     structure tag size 0x0200 devices/hardblocks.h: *185
LocalContextItem structure tag size 0x0014 libraries/iffparse.h: *83
LocalVar         structure tag size 0x0018 dos/var.h: *27
Lock             struct SignalSemaphore(size 0x002e bytes) in struct Layer
         +0x0048 graphics/clip.h: *52
Lock             struct SignalSemaphore(size 0x002e bytes) in struct
                 Layer_Info
         +0x0018 graphics/layers.h: *40
LockLayersCount char in struct Layer_Info +0x005b graphics/layers.h: *45
LongInt          long int in struct StringInfo
         +0x001c intuition/intuition.h: *553
LongInt          long int in struct SGWork +0x0022 intuition/sghooks.h: *47
LowMemChkSum     short int in struct ExecBase +0x0024 exec/execbase.h: *42


2.0 IncludeXREF: M

mc_Bytes         unsigned long int in struct MemChunk
         +0x0004 exec/memory.h: *24
mc_Next          pointer to struct MemChunk in struct MemChunk
         +0x0000 exec/memory.h: *23
mday             unsigned short int in struct ClockData
         +0x0006 utility/date.h: *23
me_Addr          #define me_Un.meu_Addr  exec/memory.h: *52
me_Length        unsigned long int in struct MemEntry
         +0x0004 exec/memory.h: *47
me_Reqs          #define me_Un.meu_Reqs  exec/memory.h: *51
me_Un            union (no tag) (size 0x0004 bytes) in struct MemEntry
         +0x0000 exec/memory.h: *46
me_un            #define me_Un  exec/memory.h: *50
message          struct IOStdReq(size 0x0030 bytes) in struct narrator_rb
         +0x0000 devices/narrator.h: *94
meu_Addr         pointer to void in union (no tag)  +0x0000 exec/memory.h: *45
meu_Reqs         unsigned long int in union (no tag)
         +0x0000 exec/memory.h: *44
mh_Attributes    unsigned short int in struct MemHeader
         +0x000e exec/memory.h: *32
mh_First         pointer to struct MemChunk in struct MemHeader
         +0x0010 exec/memory.h: *33
mh_Free          unsigned long int in struct MemHeader
         +0x001c exec/memory.h: *36
mh_Lower         pointer to void in struct MemHeader +0x0014 exec/memory.h: *34
mh_Node          struct Node(size 0x000e bytes) in struct MemHeader
         +0x0000 exec/memory.h: *31
mh_Upper         pointer to void in struct MemHeader +0x0018 exec/memory.h: *35
min              unsigned short int in struct ClockData
         +0x0002 utility/date.h: *21
min_row          unsigned short int in struct MonitorSpec
         +0x002a graphics/monitor.h: *37
minterms         array [8] of unsigned char in struct RastPort
         +0x0028 graphics/rastport.h: *75
ml_ME            array [1] of struct MemEntry(size 0x0008 bytes) in struct
                 MemList
         +0x0010 exec/memory.h: *61
ml_Node          struct Node(size 0x000e bytes) in struct MemList
         +0x0000 exec/memory.h: *59
ml_NumEntries    unsigned short int in struct MemList
         +0x000e exec/memory.h: *60
ml_me            #define ml_ME  exec/memory.h: *64
mlh_Head         pointer to struct MinNode in struct MinList
         +0x0000 exec/lists.h: *34
mlh_Tail         pointer to struct MinNode in struct MinList
         +0x0004 exec/lists.h: *35
mlh_TailPred     pointer to struct MinNode in struct MinList
         +0x0008 exec/lists.h: *36
mln_Pred         pointer to struct MinNode in struct MinNode
         +0x0004 exec/nodes.h: *35
mln_Succ         pointer to struct MinNode in struct MinNode
         +0x0000 exec/nodes.h: *34
mn_Length        unsigned short int in struct Message +0x0012 exec/ports.h: *52
mn_Node          struct Node(size 0x000e bytes) in struct Message
         +0x0000 exec/ports.h: *50
mn_ReplyPort     pointer to struct MsgPort in struct Message
         +0x000e exec/ports.h: *51
mode             unsigned short int in struct narrator_rb
         +0x0034 devices/narrator.h: *97
monitor_id       unsigned short int in struct GfxBase
         +0x00f2 graphics/gfxbase.h: *69
month            unsigned short int in struct ClockData
         +0x0008 utility/date.h: *24
mouth_rb         structure tag size 0x005c devices/narrator.h: *128
mouths           unsigned char in struct narrator_rb
         +0x0042 devices/narrator.h: *103
mp_Flags         unsigned char in struct MsgPort +0x000e exec/ports.h: *32
mp_MsgList       struct List(size 0x000e bytes) in struct MsgPort
         +0x0014 exec/ports.h: *35
mp_Node          struct Node(size 0x000e bytes) in struct MsgPort
         +0x0000 exec/ports.h: *31
mp_SigBit        unsigned char in struct MsgPort +0x000f exec/ports.h: *33
mp_SigTask       pointer to void in struct MsgPort +0x0010 exec/ports.h: *34
mp_SoftInt       #define mp_SigTask  exec/ports.h: *38
ms_Flags         unsigned short int in struct MonitorSpec
         +0x0018 graphics/monitor.h: *30
ms_LegalView     struct Rectangle(size 0x0008 bytes) in struct MonitorSpec
         +0x0042 graphics/monitor.h: *45
ms_Node          struct ExtendedNode(size 0x0018 bytes) in struct MonitorSpec
         +0x0000 graphics/monitor.h: *29
ms_OpenCount     unsigned short int in struct MonitorSpec
         +0x0030 graphics/monitor.h: *39
ms_Special       pointer to struct SpecialMonitor in struct MonitorSpec
         +0x002c graphics/monitor.h: *38
ms_maxoscan      pointer to function returning long int in struct MonitorSpec
         +0x004a graphics/monitor.h: *46
ms_reserved00    unsigned long int in struct MonitorSpec
         +0x0094 graphics/monitor.h: *52
ms_reserved01    unsigned long int in struct MonitorSpec
         +0x0098 graphics/monitor.h: *53
ms_scale         pointer to function returning long int in struct MonitorSpec
         +0x003a graphics/monitor.h: *42
ms_transform     pointer to function returning long int in struct MonitorSpec
         +0x0032 graphics/monitor.h: *40
ms_translate     pointer to function returning long int in struct MonitorSpec
         +0x0036 graphics/monitor.h: *41
ms_videoscan     pointer to function returning long int in struct MonitorSpec
         +0x004e graphics/monitor.h: *47
ms_xoffset       unsigned short int in struct MonitorSpec
         +0x003e graphics/monitor.h: *43
ms_yoffset       unsigned short int in struct MonitorSpec
         +0x0040 graphics/monitor.h: *44
MAKE_ID          macro (4 arguments)   libraries/iffparse.h: *143
MALE             #define 0 = 0x00000000  devices/narrator.h: *63
MANUALF0         #define 2 = 0x00000002  devices/narrator.h: *67
MATHIEEERESOURCEF_DBLBAS #define (1<<0) = 0x00000001
                 libraries/mathresource.h: *49
MATHIEEERESOURCEF_DBLTRANS #define (1<<1) = 0x00000002
                 libraries/mathresource.h: *50
MATHIEEERESOURCEF_EXTBAS #define (1<<4) = 0x00000010
                 libraries/mathresource.h: *53
MATHIEEERESOURCEF_EXTTRANS #define (1<<5) = 0x00000020
                 libraries/mathresource.h: *54
MATHIEEERESOURCEF_SGLBAS #define (1<<2) = 0x00000004
                 libraries/mathresource.h: *51
MATHIEEERESOURCEF_SGLTRANS #define (1<<3) = 0x00000008
                 libraries/mathresource.h: *52
MAX              macro (2 arguments)   clib/macros.h: *15
MAXBODY          #define 0xFFFF = 0x0000ffff  intuition/intuition.h: *514
MAXBYTESPERROW   #define 4096 = 0x00001000  hardware/blit.h: *25
MAXCENT          #define 100 = 0x00000064  devices/narrator.h: *88
MAXFONTMATCHWEIGHT #define 32767 = 0x00007fff  graphics/text.h: *87
MAXFONTNAME      #define 32 = 0x00000020  libraries/diskfont.h: *62, 76
MAXFONTPATH      #define 256 = 0x00000100  libraries/diskfont.h: *28, 31, 38
MAXFREQ          #define 28000 = 0x00006d60  devices/narrator.h: *84
MAXINT           #define 0x7FFFFFFF = 0x7fffffff  dos/dos.h: *45
MAXPITCH         #define 320 = 0x00000140  devices/narrator.h: *82
MAXPOT           #define 0xFFFF = 0x0000ffff  intuition/intuition.h: *515
MAXPUBSCREENNAME #define (139) = 0x0000008b  intuition/screens.h: *394
MAXRATE          #define 400 = 0x00000190  devices/narrator.h: *80
MAXRMARG         #define 15 = 0x0000000f  rexx/storage.h: *121
MAXTABS          #define 80 = 0x00000050  devices/conunit.h: *52, 78
MAXVOL           #define 64 = 0x00000040  devices/narrator.h: *86
MAX_MULTIARGS    #define 128 = 0x00000080  dos/rdargs.h: *124
MAX_TEMPLATE_ITEMS #define 100 = 0x00000064  dos/rdargs.h: *117
MCOMPAT_MIXED    #define 0 = 0x00000000  graphics/displayinfo.h: *126
MCOMPAT_NOBODY   #define -1 = 0xffffffff  graphics/displayinfo.h: *128
MCOMPAT_SELF     #define 1 = 0x00000001  graphics/displayinfo.h: *127
MEMCLEAR         #define (1L << 16) = 0x00010000  rexx/storage.h: *221
MEMF_24BITDMA    #define (1L<<9) = 0x00000200  exec/memory.h: *75
MEMF_ANY         #define (0L) = 0x00000000  exec/memory.h: *70
MEMF_CHIP        #define (1L<<1) = 0x00000002  exec/memory.h: *72
MEMF_CLEAR       #define (1L<<16) = 0x00010000  exec/memory.h: *77
MEMF_FAST        #define (1L<<2) = 0x00000004  exec/memory.h: *73
MEMF_LARGEST     #define (1L<<17) = 0x00020000  exec/memory.h: *78
MEMF_LOCAL       #define (1L<<8) = 0x00000100  exec/memory.h: *74
MEMF_PUBLIC      #define (1L<<0) = 0x00000001  exec/memory.h: *71
MEMF_REVERSE     #define (1L<<18) = 0x00040000  exec/memory.h: *79
MEMF_TOTAL       #define (1L<<19) = 0x00080000  exec/memory.h: *80
MEMMASK          #define 0xFFFFFFF0 = 0xfffffff0  rexx/storage.h: *218
MEMQUANT         #define 16L = 0x00000010  rexx/storage.h: *217
MEMQUICK         #define (1L << 0 ) = 0x00000001  rexx/storage.h: *220
MEM_BLOCKMASK    #define (MEM_BLOCKSIZE-1) = 0x00000007  exec/memory.h: *83
MEM_BLOCKSIZE    #define 8L = 0x00000008  exec/memory.h: *82
MENUCANCEL       #define 0x0002 = 0x00000002  intuition/intuition.h: *767
MENUDOWN         #define (IECODE_RBUTTON) = 0x00000069
                 intuition/intuition.h: *1333
MENUENABLED      #define 0x0001 = 0x00000001  intuition/intuition.h: *77
MENUHELP         #define IDCMP_MENUHELP = 0x01000000
                 intuition/iobsolete.h: *138
MENUHOT          #define 0x0001 = 0x00000001  intuition/intuition.h: *766
MENUNULL         #define 0xFFFF = 0x0000ffff  intuition/intuition.h: *1288
MENUNUM          macro (1 argument)   intuition/intuition.h: *1266
MENUPICK         #define IDCMP_MENUPICK = 0x00000100
                 intuition/iobsolete.h: *122
MENUSTATE        #define WFLG_MENUSTATE = 0x00008000
                 intuition/iobsolete.h: *163
MENUTOGGLE       #define 0x0008 = 0x00000008  intuition/intuition.h: *121
MENUTOGGLED      #define 0x4000 = 0x00004000  intuition/intuition.h: *137
MENUUP           #define (IECODE_RBUTTON | IECODE_UP_PREFIX) = 0x000000e9
                 intuition/intuition.h: *1332
MENUVERIFY       #define IDCMP_MENUVERIFY = 0x00002000
                 intuition/iobsolete.h: *127
MENUWAITING      #define 0x0003 = 0x00000003  intuition/intuition.h: *768
MENU_IMAGE       #define 128 = 0x00000080  libraries/gadtools.h: *139
MENU_USERDATA    macro (1 argument)   libraries/gadtools.h: *176
MIDDLEDOWN       #define (IECODE_MBUTTON) = 0x0000006a
                 intuition/intuition.h: *1334
MIDDLEUP         #define (IECODE_MBUTTON | IECODE_UP_PREFIX) = 0x000000ea
                 intuition/intuition.h: *1335
MIDRAWN          #define 0x0100 = 0x00000100  intuition/intuition.h: *80
MIN              macro (2 arguments)   clib/macros.h: *16
MINBYTESPERROW   #define 128 = 0x00000080  hardware/blit.h: *24
MINCENT          #define 0 = 0x00000000  devices/narrator.h: *87
MINFREQ          #define 5000 = 0x00001388  devices/narrator.h: *83
MININT           #define 0x80000000 = 0x80000000  dos/dos.h: *46
MINPITCH         #define 65 = 0x00000041  devices/narrator.h: *81
MINRATE          #define 40 = 0x00000028  devices/narrator.h: *79
MINVOL           #define 0 = 0x00000000  devices/narrator.h: *85
MIN_NTSC_ROW     #define 21 = 0x00000015  graphics/monitor.h: *80
MIN_PAL_ROW      #define 29 = 0x0000001d  graphics/monitor.h: *81
MIN_VGA70_ROW    #define 35 = 0x00000023  graphics/monitor.h: *111
MIN_VGA_ROW      #define 29 = 0x0000001d  graphics/monitor.h: *96
MISCNAME         #define "misc.resource"  resources/misc.h: *43
MKBADDR          macro (1 argument)   dos/dos.h: *113
MODELCLASS       #define "modelclass"  intuition/classusr.h: *54
MODE_640         #define 0x8000 = 0x00008000  graphics/display.h: *16
MODE_NEWFILE     #define 1006 = 0x000003ee  dos/dos.h: *31
MODE_OLDFILE     #define 1005 = 0x000003ed  dos/dos.h: *29
MODE_READWRITE   #define 1004 = 0x000003ec  dos/dos.h: *33
MONITOR_ID_MASK  #define 0xFFFF1000 = 0xffff1000  graphics/displayinfo.h: *145
MONITOR_SPEC_TYPE #define 4 = 0x00000004  graphics/gfxnodes.h: *36
MOUSEBUTTONS     #define IDCMP_MOUSEBUTTONS = 0x00000008
                 intuition/iobsolete.h: *117
MOUSEMOVE        #define IDCMP_MOUSEMOVE = 0x00000010
                 intuition/iobsolete.h: *118
MOUSE_ACCEL      #define (1<<15) = 0x00008000  intuition/preferences.h: *138
MR_ALLOCMISCRESOURCE #define (LIB_BASE) = 0xfffffffa  resources/misc.h: *40
MR_FREEMISCRESOURCE #define (LIB_BASE-LIB_VECTSIZE) = 0xfffffff4
                 resources/misc.h: *41
MR_PARALLELBITS  #define 3 = 0x00000003  resources/misc.h: *35
MR_PARALLELPORT  #define 2 = 0x00000002  resources/misc.h: *33
MR_SERIALBITS    #define 1 = 0x00000001  resources/misc.h: *31
MR_SERIALPORT    #define 0 = 0x00000000  resources/misc.h: *30
MTYPE_APPICON    #define 8 = 0x00000008  workbench/workbench.h: *99
MTYPE_APPMENUITEM #define 9 = 0x00000009  workbench/workbench.h: *100
MTYPE_APPWINDOW  #define 7 = 0x00000007  workbench/workbench.h: *98
MTYPE_CLOSEDOWN  #define 5 = 0x00000005  workbench/workbench.h: *96
MTYPE_COPYEXIT   #define 10 = 0x0000000a  workbench/workbench.h: *101
MTYPE_DISKCHANGE #define 3 = 0x00000003  workbench/workbench.h: *94
MTYPE_ICONPUT    #define 11 = 0x0000000b  workbench/workbench.h: *102
MTYPE_IOPROC     #define 6 = 0x00000006  workbench/workbench.h: *97
MTYPE_PSTD       #define 1 = 0x00000001  workbench/workbench.h: *92
MTYPE_TIMER      #define 4 = 0x00000004  workbench/workbench.h: *95
MTYPE_TOOLEXIT   #define 2 = 0x00000002  workbench/workbench.h: *93
MULTIPLY_DIMENSIONS #define 0x0080 = 0x00000080  intuition/preferences.h: *251
MUSTDRAW         #define 0x0008 = 0x00000008  graphics/gels.h: *25
MXIDCMP          #define (IDCMP_GADGETDOWN) = 0x00000020
                 libraries/gadtools.h: *72
MXIMAGE          #define (0x0FL) = 0x0000000f  intuition/imageclass.h: *111
MX_KIND          #define 5 = 0x00000005  libraries/gadtools.h: *39
M_ASM            #define ">1"  devices/console.h: *99
M_AWM            #define "?7"  devices/console.h: *100
M_LNM            #define 20 = 0x00000014  devices/console.h: *98
                 devices/conunit.h: 98
Mask             unsigned char in struct RastPort
         +0x0018 graphics/rastport.h: *64
Mask             pointer to unsigned short int in struct BoolInfo
         +0x0002 intuition/intuition.h: *431
MathIEEEBase     structure tag size 0x003c libraries/mathlibrary.h: *21
MathIEEEBase_LibNode struct Library(size 0x0022 bytes) in struct MathIEEEBase
         +0x0000 libraries/mathlibrary.h: *23
MathIEEEBase_TaskCloseLib pointer to function returning int in struct
                 MathIEEEBase
         +0x0038 libraries/mathlibrary.h: *26
MathIEEEBase_TaskOpenLib pointer to function returning int in struct
                 MathIEEEBase
         +0x0034 libraries/mathlibrary.h: *25
MathIEEEBase_reserved array [18] of unsigned char in struct MathIEEEBase
         +0x0022 libraries/mathlibrary.h: *24
MathIEEEResource structure tag size 0x002c libraries/mathresource.h: *35
MathIEEEResource_BaseAddr pointer to unsigned short int in struct
                 MathIEEEResource
         +0x0010 libraries/mathresource.h: *39
MathIEEEResource_DblBasInit pointer to function returning void in struct
                 MathIEEEResource
         +0x0014 libraries/mathresource.h: *40
MathIEEEResource_DblTransInit pointer to function returning void in struct
                 MathIEEEResource
         +0x0018 libraries/mathresource.h: *41
MathIEEEResource_ExtBasInit pointer to function returning void in struct
                 MathIEEEResource
         +0x0024 libraries/mathresource.h: *44
MathIEEEResource_ExtTransInit pointer to function returning void in struct
                 MathIEEEResource
         +0x0028 libraries/mathresource.h: *45
MathIEEEResource_Flags unsigned short int in struct MathIEEEResource
         +0x000e libraries/mathresource.h: *38
MathIEEEResource_Node struct Node(size 0x000e bytes) in struct
                 MathIEEEResource
         +0x0000 libraries/mathresource.h: *37
MathIEEEResource_SglBasInit pointer to function returning void in struct
                 MathIEEEResource
         +0x001c libraries/mathresource.h: *42
MathIEEEResource_SglTransInit pointer to function returning void in struct
                 MathIEEEResource
         +0x0020 libraries/mathresource.h: *43
MaxChars         short int in struct StringInfo
         +0x000a intuition/intuition.h: *530
MaxCount         short int in struct cprlist +0x0008 graphics/copper.h: *60
MaxCount         short int in struct CopList +0x001e graphics/copper.h: *73
MaxCount         short int in struct AreaInfo +0x0012 graphics/rastport.h: *30
MaxDepth         unsigned short int in struct DimensionInfo
         +0x0010 graphics/displayinfo.h: *95
MaxDisplayColumn unsigned short int in struct GfxBase
         +0x00d6 graphics/gfxbase.h: *57
MaxDisplayRow    unsigned short int in struct GfxBase
         +0x00d4 graphics/gfxbase.h: *56
MaxExtMem        pointer to void in struct ExecBase
         +0x004e exec/execbase.h: *53
MaxHeight        unsigned short int in struct Window
         +0x0016 intuition/intuition.h: *805
MaxHeight        unsigned short int in struct NewWindow
         +0x002c intuition/intuition.h: *1026
MaxHeight        unsigned short int in struct ExtNewWindow
         +0x002c intuition/intuition.h: *1061
MaxLocMem        unsigned long int in struct ExecBase
         +0x003e exec/execbase.h: *49
MaxOScan         struct Rectangle(size 0x0008 bytes) in struct DimensionInfo
         +0x0022 graphics/displayinfo.h: *101
MaxRasterHeight unsigned short int in struct DimensionInfo
         +0x0018 graphics/displayinfo.h: *99
MaxRasterWidth   unsigned short int in struct DimensionInfo
         +0x0016 graphics/displayinfo.h: *98
MaxWidth         unsigned short int in struct Window
         +0x0014 intuition/intuition.h: *805
MaxWidth         unsigned short int in struct NewWindow
         +0x002a intuition/intuition.h: *1026
MaxWidth         unsigned short int in struct ExtNewWindow
         +0x002a intuition/intuition.h: *1061
MaxX             short int in struct Rectangle +0x0004 graphics/gfx.h: *32
MaxX             long int in struct Rect32 +0x0008 graphics/gfx.h: *38
MaxY             short int in struct Rectangle +0x0006 graphics/gfx.h: *32
MaxY             long int in struct Rect32 +0x000c graphics/gfx.h: *38
MeMask           short int in struct VSprite +0x0020 graphics/gels.h: *102
MemChunk         structure tag size 0x0008 exec/memory.h: *22, 23, 33
MemEntry         structure tag size 0x0008 exec/memory.h: *42, 61
MemHeader        structure tag size 0x0020 exec/memory.h: *30
MemList          structure tag size 0x0018 exec/memory.h: *58
MemList          struct List(size 0x000e bytes) in struct ExecBase
         +0x0142 exec/execbase.h: *86
Memory           pointer to unsigned char in struct Remember
         +0x0008 intuition/intuition.h: *1235
Menu             structure tag size 0x001e intuition/intuition.h: *62, 64, 809
MenuHBorder      char in struct Screen +0x0022 intuition/screens.h: *121
MenuItem         structure tag
     size 0x0022 intuition/intuition.h: *69, 90, 92, 108
MenuName         pointer to char in struct Menu
         +0x000e intuition/intuition.h: *68
MenuStrip        pointer to struct Menu in struct Window
         +0x001c intuition/intuition.h: *809
MenuVBorder      char in struct Screen +0x0021 intuition/screens.h: *121
Message          structure tag size 0x0014 exec/ports.h: *49
                 exec/io.h: 21, 30
                 devices/audio.h: 55
                 devices/clipboard.h: 44, 60
                 devices/printer.h: 143, 157
                 dos/dosextens.h: 92, 111, 142
                 graphics/text.h: 92
                 intuition/intuition.h: 679
                 dos/notify.h: 42
                 workbench/startup.h: 28
                 resources/disk.h: 44
                 rexx/storage.h: 100
                 workbench/workbench.h: 127
MessageKey       pointer to struct IntuiMessage in struct Window
         +0x005e intuition/intuition.h: *857
MethodID         unsigned long int in struct (no tag)
         +0x0000 intuition/classusr.h: *32
MethodID         unsigned long int in struct opSet
         +0x0000 intuition/classusr.h: *79
MethodID         unsigned long int in struct opUpdate
         +0x0000 intuition/classusr.h: *89
MethodID         unsigned long int in struct opGet
         +0x0000 intuition/classusr.h: *109
MethodID         unsigned long int in struct opAddTail
         +0x0000 intuition/classusr.h: *118
MethodID         unsigned long int in struct opMember
         +0x0000 intuition/classusr.h: *125
MethodID         unsigned long int in struct gpHitTest
         +0x0000 intuition/gadgetclass.h: *177
MethodID         unsigned long int in struct gpRender
         +0x0000 intuition/gadgetclass.h: *189
MethodID         unsigned long int in struct gpInput
         +0x0000 intuition/gadgetclass.h: *202
MethodID         unsigned long int in struct gpGoInactive
         +0x0000 intuition/gadgetclass.h: *232
MethodID         unsigned long int in struct impFrameBox
         +0x0000 intuition/imageclass.h: *140
MethodID         unsigned long int in struct impDraw
         +0x0000 intuition/imageclass.h: *153
MethodID         unsigned long int in struct impErase
         +0x0000 intuition/imageclass.h: *173
MethodID         unsigned long int in struct impHitTest
         +0x0000 intuition/imageclass.h: *189
Micros           unsigned long int in struct IntuiMessage
         +0x0028 intuition/intuition.h: *708
Micros           unsigned long int in struct IntuitionBase
         +0x004c intuition/intuitionbase.h: *87
MicrosPerLine    unsigned short int in struct GfxBase
         +0x00e8 graphics/gfxbase.h: *65
MinDisplayColumn unsigned short int in struct GfxBase
         +0x00ea graphics/gfxbase.h: *66
MinHeight        short int in struct Window +0x0012 intuition/intuition.h: *804
MinHeight        short int in struct NewWindow
         +0x0028 intuition/intuition.h: *1025
MinHeight        short int in struct ExtNewWindow
         +0x0028 intuition/intuition.h: *1060
MinList          structure tag size 0x000c exec/lists.h: *33
                 exec/semaphores.h: 44
                 exec/execbase.h: 142
                 dos/dosextens.h: 65, 251
                 graphics/layers.h: 39
MinNode          structure tag size 0x0008 exec/nodes.h: *33, 34, 35
                 exec/lists.h: 34, 35, 36
                 exec/semaphores.h: 36
                 dos/dosextens.h: 265
                 utility/hooks.h: 25
                 intuition/classes.h: 69
                 libraries/iffparse.h: 70, 84
MinRasterHeight unsigned short int in struct DimensionInfo
         +0x0014 graphics/displayinfo.h: *97
MinRasterWidth   unsigned short int in struct DimensionInfo
         +0x0012 graphics/displayinfo.h: *96
MinRow           unsigned short int in struct MonitorInfo
         +0x0028 graphics/displayinfo.h: *118
MinWidth         short int in struct Window +0x0010 intuition/intuition.h: *804
MinWidth         short int in struct NewWindow
         +0x0026 intuition/intuition.h: *1025
MinWidth         short int in struct ExtNewWindow
         +0x0026 intuition/intuition.h: *1060
MinX             short int in struct Rectangle +0x0000 graphics/gfx.h: *31
MinX             long int in struct Rect32 +0x0000 graphics/gfx.h: *37
MinY             short int in struct Rectangle +0x0002 graphics/gfx.h: *31
MinY             long int in struct Rect32 +0x0004 graphics/gfx.h: *37
Modes            unsigned short int in struct ViewPort
         +0x0020 graphics/view.h: *52
Modes            unsigned short int in struct View +0x0010 graphics/view.h: *65
Modes            unsigned short int in struct GfxBase
         +0x009e graphics/gfxbase.h: *39
Modes            unsigned long int in struct SGWork
         +0x0010 intuition/sghooks.h: *39
Monitor          pointer to struct MonitorSpec in struct ViewExtra
         +0x001c graphics/view.h: *74
MonitorInfo      structure tag size 0x0058 graphics/displayinfo.h: *109
MonitorList      struct List(size 0x000e bytes) in struct GfxBase
         +0x0180 graphics/gfxbase.h: *86
MonitorListSemaphore pointer to struct SignalSemaphore in struct GfxBase
         +0x0192 graphics/gfxbase.h: *88
MonitorSpec      structure tag size 0x009c graphics/monitor.h: *27
                 graphics/view.h: 74
                 graphics/displayinfo.h: 112
                 graphics/gfxbase.h: 85, 87
MoreFlags        unsigned long int in struct Window
         +0x0084 intuition/intuition.h: *901
MountList        struct List(size 0x000e bytes) in struct ExpansionBase
         +0x004a libraries/expansionbase.h: *55
MouseX           short int in struct IntuiMessage
         +0x0020 intuition/intuition.h: *703
MouseX           short int in struct Window +0x000e intuition/intuition.h: *802
MouseX           short int in struct Screen +0x0012 intuition/screens.h: *106
MouseX           short int in struct IntuitionBase
         +0x0046 intuition/intuitionbase.h: *83
MouseY           short int in struct IntuiMessage
         +0x0022 intuition/intuition.h: *703
MouseY           short int in struct Window +0x000c intuition/intuition.h: *802
MouseY           short int in struct Screen +0x0010 intuition/screens.h: *106
MouseY           short int in struct IntuitionBase
         +0x0044 intuition/intuitionbase.h: *83
Msg              pointer to "UBYTE"  intuition/classusr.h: *34
MsgPort          structure tag size 0x0022 exec/ports.h: *30, 51
                 exec/devices.h: 34
                 exec/semaphores.h: 55
                 devices/conunit.h: 56
                 dos/dosextens.h: 41, 93, 94, 112, 253, 267, 334,
                             364, 411, 447
                 graphics/text.h: 126
                 intuition/intuition.h: 856
                 devices/prtbase.h: 67, 92
                 dos/filehandler.h: 104
                 dos/notify.h: 62, 76
                 workbench/startup.h: 29
                 libraries/commodities.h: 57
                 libraries/iffparse.h: 118, 119
                 rexx/storage.h: 108, 189
                 rexx/rexxio.h: 66
                 rexx/rxslib.h: 55
Mspc             pointer to struct MonitorSpec in struct MonitorInfo
         +0x0010 graphics/displayinfo.h: *112
MutualExclude    long int in struct MenuItem +0x000e intuition/intuition.h: *97
MutualExclude    long int in struct Gadget +0x001e intuition/intuition.h: *253


2.0 IncludeXREF: N

n                struct ExtendedNode(size 0x0018 bytes) in struct ViewExtra
         +0x0000 graphics/view.h: *72
n                struct ExtendedNode(size 0x0018 bytes) in struct
                 ViewPortExtra
         +0x0000 graphics/view.h: *81
n                pointer to struct bltnode in struct bltnode
         +0x0000 hardware/blit.h: *92
narrator_rb      structure tag size 0x0058 devices/narrator.h: *93, 129
nb_Descr         pointer to char in struct NewBroker
         +0x000a libraries/commodities.h: *52
nb_Flags         short int in struct NewBroker
         +0x0010 libraries/commodities.h: *54
nb_Name          pointer to char in struct NewBroker
         +0x0002 libraries/commodities.h: *50
nb_Port          pointer to struct MsgPort in struct NewBroker
         +0x0014 libraries/commodities.h: *57
nb_Pri           char in struct NewBroker +0x0012 libraries/commodities.h: *55
nb_ReservedChannel short int in struct NewBroker
         +0x0018 libraries/commodities.h: *58
nb_Title         pointer to char in struct NewBroker
         +0x0006 libraries/commodities.h: *51
nb_Unique        short int in struct NewBroker
         +0x000e libraries/commodities.h: *53
nb_Version       char in struct NewBroker +0x0000 libraries/commodities.h: *49
nextLine         pointer to short int in struct GelsInfo
         +0x000a graphics/rastport.h: *48
ng_Flags         unsigned long int in struct NewGadget
         +0x0012 libraries/gadtools.h: *101
ng_GadgetID      unsigned short int in struct NewGadget
         +0x0010 libraries/gadtools.h: *100
ng_GadgetText    pointer to unsigned char in struct NewGadget
         +0x0008 libraries/gadtools.h: *98
ng_Height        short int in struct NewGadget
         +0x0006 libraries/gadtools.h: *97
ng_LeftEdge      short int in struct NewGadget
         +0x0000 libraries/gadtools.h: *96
ng_TextAttr      pointer to struct TextAttr in struct NewGadget
         +0x000c libraries/gadtools.h: *99
ng_TopEdge       short int in struct NewGadget
         +0x0002 libraries/gadtools.h: *96
ng_UserData      pointer to void in struct NewGadget
         +0x001a libraries/gadtools.h: *103
ng_VisualInfo    pointer to void in struct NewGadget
         +0x0016 libraries/gadtools.h: *102
ng_Width         short int in struct NewGadget
         +0x0004 libraries/gadtools.h: *97
nm_Class         unsigned long int in struct NotifyMessage
         +0x0014 dos/notify.h: *43
nm_Code          unsigned short int in struct NotifyMessage
         +0x0018 dos/notify.h: *44
nm_CommKey       pointer to unsigned char in struct NewMenu
         +0x0006 libraries/gadtools.h: *127
nm_DoNotTouch    unsigned long int in struct NotifyMessage
         +0x001e dos/notify.h: *46
nm_DoNotTouch2   unsigned long int in struct NotifyMessage
         +0x0022 dos/notify.h: *47
nm_ExecMessage   struct Message(size 0x0014 bytes) in struct NotifyMessage
         +0x0000 dos/notify.h: *42
nm_Flags         unsigned short int in struct NewMenu
         +0x000a libraries/gadtools.h: *128
nm_Label         pointer to unsigned char in struct NewMenu
         +0x0002 libraries/gadtools.h: *126
nm_MutualExclude long int in struct NewMenu +0x000c libraries/gadtools.h: *129
nm_NReq          pointer to struct NotifyRequest in struct NotifyMessage
         +0x001a dos/notify.h: *45
nm_Type          unsigned char in struct NewMenu
         +0x0000 libraries/gadtools.h: *125
nm_UserData      pointer to void in struct NewMenu
         +0x0010 libraries/gadtools.h: *130
nm_masks         unsigned short int in struct narrator_rb
         +0x003c devices/narrator.h: *100
norm_hblank      array [2] of unsigned short int in struct copinit
         +0x0058 graphics/copper.h: *99
nr_Flags         unsigned long int in struct NotifyRequest
         +0x000c dos/notify.h: *57
nr_FullName      pointer to unsigned char in struct NotifyRequest
         +0x0004 dos/notify.h: *55
nr_Handler       pointer to struct MsgPort in struct NotifyRequest
         +0x002c dos/notify.h: *76
nr_Msg           struct (no tag) (size 0x0004 bytes) in union (no tag)
         +0x0000 dos/notify.h: *63
nr_MsgCount      unsigned long int in struct NotifyRequest
         +0x0028 dos/notify.h: *75
nr_Name          pointer to unsigned char in struct NotifyRequest
         +0x0000 dos/notify.h: *54
nr_Port          pointer to struct MsgPort in struct (no tag)
         +0x0000 dos/notify.h: *62
nr_Reserved      array [4] of unsigned long int in struct NotifyRequest
         +0x0018 dos/notify.h: *72
nr_Signal        struct (no tag) (size 0x0008 bytes) in union (no tag)
         +0x0000 dos/notify.h: *69
nr_SignalNum     unsigned char in struct (no tag)  +0x0004 dos/notify.h: *67
nr_Task          pointer to struct Task in struct (no tag)
         +0x0000 dos/notify.h: *66
nr_UserData      unsigned long int in struct NotifyRequest
         +0x0008 dos/notify.h: *56
nr_pad           array [3] of unsigned char in struct (no tag)
         +0x0005 dos/notify.h: *68
nr_stuff         union (no tag) (size 0x0008 bytes) in struct NotifyRequest
         +0x0010 dos/notify.h: *70
nreserved        array [4] of unsigned long int in struct GfxBase
         +0x0164 graphics/gfxbase.h: *81
ns_Buff          array [8] of char in struct NexxStr
         +0x0008 rexx/storage.h: *47
ns_Flags         unsigned char in struct NexxStr +0x0006 rexx/storage.h: *45
ns_Hash          unsigned char in struct NexxStr +0x0007 rexx/storage.h: *46
ns_Ivalue        long int in struct NexxStr +0x0000 rexx/storage.h: *43
ns_Length        unsigned short int in struct NexxStr
         +0x0004 rexx/storage.h: *44
num              unsigned short int in struct SimpleSprite
         +0x000a graphics/sprite.h: *26
numDrIPens       #define NUMDRIPENS = 0x00000009  intuition/iobsolete.h: *270
numchan          unsigned char in struct narrator_rb
         +0x0044 devices/narrator.h: *105
nxtlist          pointer to struct CopListin union (no tag)
         +0x0000 graphics/copper.h: *31
NABC             #define 0x8 = 0x00000008  hardware/blit.h: *36
NABNC            #define 0x4 = 0x00000004  hardware/blit.h: *37
NANBC            #define 0x2 = 0x00000002  hardware/blit.h: *38
NANBNC           #define 0x1 = 0x00000001  hardware/blit.h: *39
NATURALF0        #define 0 = 0x00000000  devices/narrator.h: *65
NBU_DUPLICATE    #define 0 = 0x00000000  libraries/commodities.h: *62
NBU_NOTIFY       #define 2 = 0x00000002  libraries/commodities.h: *64
NBU_UNIQUE       #define 1 = 0x00000001  libraries/commodities.h: *63
NB_VERSION       #define 5 = 0x00000005  libraries/commodities.h: *46
NDB_NEWIORB      #define 0 = 0x00000000  devices/narrator.h: *24
NDB_SYLSYNC      #define 2 = 0x00000002  devices/narrator.h: *26
NDB_WORDSYNC     #define 1 = 0x00000001  devices/narrator.h: *25
NDF_NEWIORB      #define (1 << NDB_NEWIORB) = 0x00000001
                 devices/narrator.h: *29
NDF_SYLSYNC      #define (1 << NDB_SYLSYNC) = 0x00000004
                 devices/narrator.h: *31
NDF_WORDSYNC     #define (1 << NDB_WORDSYNC) = 0x00000002
                 devices/narrator.h: *30
ND_CantAlloc     #define -6 = 0xfffffffa  devices/narrator.h: *41
ND_CentPhonErr   #define -28 = 0xffffffe4  devices/narrator.h: *53
ND_DCentErr      #define -27 = 0xffffffe5  devices/narrator.h: *52
ND_Expunged      #define -9 = 0xfffffff7  devices/narrator.h: *44
ND_FreqErr       #define -25 = 0xffffffe7  devices/narrator.h: *50
ND_MakeBad       #define -4 = 0xfffffffc  devices/narrator.h: *39
ND_ModeErr       #define -24 = 0xffffffe8  devices/narrator.h: *49
ND_NoAudLib      #define -3 = 0xfffffffd  devices/narrator.h: *38
ND_NoMem         #define -2 = 0xfffffffe  devices/narrator.h: *37
ND_NoWrite       #define -8 = 0xfffffff8  devices/narrator.h: *43
ND_PhonErr       #define -20 = 0xffffffec  devices/narrator.h: *45
ND_PitchErr      #define -22 = 0xffffffea  devices/narrator.h: *47
ND_RateErr       #define -21 = 0xffffffeb  devices/narrator.h: *46
ND_SexErr        #define -23 = 0xffffffe9  devices/narrator.h: *48
ND_Unimpl        #define -7 = 0xfffffff9  devices/narrator.h: *42
ND_UnitErr       #define -5 = 0xfffffffb  devices/narrator.h: *40
ND_VolErr        #define -26 = 0xffffffe6  devices/narrator.h: *51
NEWLAYERINFO_CALLED #define 1 = 0x00000001  graphics/layers.h: *51
NEWLOCKS         #define  graphics/clip.h: *32
NEWPREFS         #define IDCMP_NEWPREFS = 0x00004000
                 intuition/iobsolete.h: *128
NEWSIZE          #define IDCMP_NEWSIZE = 0x00000002
                 intuition/iobsolete.h: *115
NG_HIGHLABEL     #define 0x0020 = 0x00000020  libraries/gadtools.h: *117
NM_BARLABEL      #define ((STRPTR)-1)  libraries/gadtools.h: *144
NM_END           #define 0 = 0x00000000  libraries/gadtools.h: *137
NM_FLAGMASK      #define (~(COMMSEQ | ITEMTEXT | HIGHFLAGS)) = 0xffffff39
                 libraries/gadtools.h: *157
NM_ITEM          #define 2 = 0x00000002  libraries/gadtools.h: *135
NM_ITEMDISABLED  #define ITEMENABLED = 0x00000010  libraries/gadtools.h: *153
NM_MENUDISABLED  #define MENUENABLED = 0x00000001  libraries/gadtools.h: *152
NM_SUB           #define 3 = 0x00000003  libraries/gadtools.h: *136
NM_TITLE         #define 1 = 0x00000001  libraries/gadtools.h: *134
NOCAREREFRESH    #define WFLG_NOCAREREFRESH = 0x00020000
                 intuition/iobsolete.h: *165
NOCROSSFILL      #define 0x20 = 0x00000020  graphics/rastport.h: *108
NOISYREQ         #define 0x0004 = 0x00000004  intuition/intuition.h: *188
NOITEM           #define 0x003F = 0x0000003f  intuition/intuition.h: *1286
NOMENU           #define 0x001F = 0x0000001f  intuition/intuition.h: *1285
NOREQBACKFILL    #define 0x0040 = 0x00000040  intuition/intuition.h: *198
NOSUB            #define 0x001F = 0x0000001f  intuition/intuition.h: *1287
NOT              #define !  intuition/intuition.h: *1294
NOTIFY_CLASS     #define 0x40000000 = 0x40000000  dos/notify.h: *33
NOTIFY_CODE      #define 0x1234 = 0x00001234  dos/notify.h: *36
NO_ICON_POSITION #define (0x80000000) = 0x80000000
                 workbench/workbench.h: *116
NP_Arguments     #define (NP_Dummy + 21) = 0x800003fd  dos/dostags.h: *89
NP_Cli           #define (NP_Dummy + 18) = 0x800003fa  dos/dostags.h: *82
NP_CloseError    #define (NP_Dummy + 9) = 0x800003f1  dos/dostags.h: *63
NP_CloseInput    #define (NP_Dummy + 6) = 0x800003ee  dos/dostags.h: *55
NP_CloseOutput   #define (NP_Dummy + 7) = 0x800003ef  dos/dostags.h: *58
NP_CommandName   #define (NP_Dummy + 20) = 0x800003fc  dos/dostags.h: *87
NP_ConsoleTask   #define (NP_Dummy + 14) = 0x800003f6  dos/dostags.h: *74
NP_CopyVars      #define (NP_Dummy + 17) = 0x800003f9  dos/dostags.h: *80
NP_CurrentDir    #define (NP_Dummy + 10) = 0x800003f2  dos/dostags.h: *66
NP_Dummy         #define (TAG_USER + 1000) = 0x800003e8  dos/dostags.h: *42
NP_Entry         #define (NP_Dummy + 3) = 0x800003eb  dos/dostags.h: *48
NP_Error         #define (NP_Dummy + 8) = 0x800003f0  dos/dostags.h: *61
NP_ExitCode      #define (NP_Dummy + 24) = 0x80000400  dos/dostags.h: *105
NP_ExitData      #define (NP_Dummy + 25) = 0x80000401  dos/dostags.h: *107
NP_FreeSeglist   #define (NP_Dummy + 2) = 0x800003ea  dos/dostags.h: *45
NP_HomeDir       #define (NP_Dummy + 16) = 0x800003f8  dos/dostags.h: *78
NP_Input         #define (NP_Dummy + 4) = 0x800003ec  dos/dostags.h: *51
NP_Name          #define (NP_Dummy + 12) = 0x800003f4  dos/dostags.h: *70
NP_NotifyOnDeath #define (NP_Dummy + 22) = 0x800003fe  dos/dostags.h: *98
NP_Output        #define (NP_Dummy + 5) = 0x800003ed  dos/dostags.h: *53
NP_Path          #define (NP_Dummy + 19) = 0x800003fb  dos/dostags.h: *84
NP_Priority      #define (NP_Dummy + 13) = 0x800003f5  dos/dostags.h: *72
NP_Seglist       #define (NP_Dummy + 1) = 0x800003e9  dos/dostags.h: *43
NP_StackSize     #define (NP_Dummy + 11) = 0x800003f3  dos/dostags.h: *68
NP_Synchronous   #define (NP_Dummy + 23) = 0x800003ff  dos/dostags.h: *101
NP_WindowPtr     #define (NP_Dummy + 15) = 0x800003f7  dos/dostags.h: *76
NRB_MAGIC        #define 31 = 0x0000001f  dos/notify.h: *94
NRB_NOTIFY_INITIAL #define 4 = 0x00000004  dos/notify.h: *92
NRB_SEND_MESSAGE #define 0 = 0x00000000  dos/notify.h: *89
NRB_SEND_SIGNAL  #define 1 = 0x00000001  dos/notify.h: *90
NRB_WAIT_REPLY   #define 3 = 0x00000003  dos/notify.h: *91
NRF_MAGIC        #define 0x80000000 = 0x80000000  dos/notify.h: *86
NRF_NOTIFY_INITIAL #define 16 = 0x00000010  dos/notify.h: *83
NRF_SEND_MESSAGE #define 1 = 0x00000001  dos/notify.h: *80
NRF_SEND_SIGNAL  #define 2 = 0x00000002  dos/notify.h: *81
NRF_WAIT_REPLY   #define 8 = 0x00000008  dos/notify.h: *82
NR_HANDLER_FLAGS #define 0xffff0000 = 0xffff0000  dos/notify.h: *97
NSB_BINARY       #define 4 = 0x00000004  rexx/storage.h: *58
NSB_EXT          #define 6 = 0x00000006  rexx/storage.h: *60
NSB_FLOAT        #define 5 = 0x00000005  rexx/storage.h: *59
NSB_KEEP         #define 0 = 0x00000000  rexx/storage.h: *54
NSB_NOTNUM       #define 2 = 0x00000002  rexx/storage.h: *56
NSB_NUMBER       #define 3 = 0x00000003  rexx/storage.h: *57
NSB_SOURCE       #define 7 = 0x00000007  rexx/storage.h: *61
NSB_STRING       #define 1 = 0x00000001  rexx/storage.h: *55
NSF_ALPHA        #define (NSF_NOTNUM | NSF_STRING) = 0x00000006
                 rexx/storage.h: *76
NSF_BINARY       #define (1 << NSB_BINARY) = 0x00000010  rexx/storage.h: *68
NSF_DPNUM        #define (NSF_NUMBER | NSF_FLOAT) = 0x00000028
                 rexx/storage.h: *75
NSF_EXT          #define (1 << NSB_EXT ) = 0x00000040  rexx/storage.h: *70
NSF_FLOAT        #define (1 << NSB_FLOAT ) = 0x00000020  rexx/storage.h: *69
NSF_INTNUM       #define (NSF_NUMBER | NSF_BINARY | NSF_STRING) = 0x0000001a
                 rexx/storage.h: *74
NSF_KEEP         #define (1 << NSB_KEEP ) = 0x00000001  rexx/storage.h: *64
NSF_NOTNUM       #define (1 << NSB_NOTNUM) = 0x00000004  rexx/storage.h: *66
NSF_NUMBER       #define (1 << NSB_NUMBER) = 0x00000008  rexx/storage.h: *67
NSF_OWNED        #define (NSF_SOURCE | NSF_EXT | NSF_KEEP) = 0x000000c1
                 rexx/storage.h: *77
NSF_SOURCE       #define (1 << NSB_SOURCE) = 0x00000080  rexx/storage.h: *71
NSF_STRING       #define (1 << NSB_STRING) = 0x00000002  rexx/storage.h: *65
NSTAG_EXT_VPMODE #define (TAG_USER | 1) = 0x80000001
                 intuition/screens.h: *290
NS_EXTENDED      #define 0x1000 = 0x00001000  intuition/screens.h: *179
NTSC             #define 1 = 0x00000001  graphics/gfxbase.h: *95
NTSC_MONITOR_ID  #define 0x00011000 = 0x00011000  graphics/displayinfo.h: *148
NTSC_MONITOR_NAME #define "ntsc.monitor"  graphics/monitor.h: *66
NT_BOOTNODE      #define 16 = 0x00000010  exec/nodes.h: *61
NT_DEATHMESSAGE  #define 19 = 0x00000013  exec/nodes.h: *64
NT_DEVICE        #define 3 = 0x00000003  exec/nodes.h: *48
NT_EXTENDED      #define 255 = 0x000000ff  exec/nodes.h: *67
NT_FONT          #define 12 = 0x0000000c  exec/nodes.h: *57
NT_FREEMSG       #define 6 = 0x00000006  exec/nodes.h: *51
NT_GRAPHICS      #define 18 = 0x00000012  exec/nodes.h: *63
NT_INTERRUPT     #define 2 = 0x00000002  exec/nodes.h: *47
NT_KICKMEM       #define 17 = 0x00000011  exec/nodes.h: *62
NT_LIBRARY       #define 9 = 0x00000009  exec/nodes.h: *54
NT_MEMORY        #define 10 = 0x0000000a  exec/nodes.h: *55
NT_MESSAGE       #define 5 = 0x00000005  exec/nodes.h: *50
NT_MSGPORT       #define 4 = 0x00000004  exec/nodes.h: *49
NT_PROCESS       #define 13 = 0x0000000d  exec/nodes.h: *58
NT_REPLYMSG      #define 7 = 0x00000007  exec/nodes.h: *52
NT_RESOURCE      #define 8 = 0x00000008  exec/nodes.h: *53
NT_SEMAPHORE     #define 14 = 0x0000000e  exec/nodes.h: *59
NT_SIGNALSEM     #define 15 = 0x0000000f  exec/nodes.h: *60
NT_SOFTINT       #define 11 = 0x0000000b  exec/nodes.h: *56
NT_TASK          #define 1 = 0x00000001  exec/nodes.h: *46
NT_UNKNOWN       #define 0 = 0x00000000  exec/nodes.h: *45
NT_USER          #define 254 = 0x000000fe  exec/nodes.h: *66
NULL             #define 0L = 0x00000000  exec/types.h: *76
NULL_IX          macro (1 argument)   libraries/commodities.h: *207
NUMBERIDCMP      #define (NULL) = 0x00000000  libraries/gadtools.h: *73
NUMBER_KIND      #define 6 = 0x00000006  libraries/gadtools.h: *40
NUMDRIPENS       #define (0x0009) = 0x00000009  intuition/screens.h: *92
NUMSECS          #define 11 = 0x0000000b  devices/trackdisk.h: *40
NUMUNITS         #define 4 = 0x00000004  devices/trackdisk.h: *41
NUM_KINDS        #define 14 = 0x0000000e  libraries/gadtools.h: *49
NWAYIDCMP        #define CYCLEIDCMP = 0x00000040  libraries/gadtools.h: *287
NWAY_KIND        #define CYCLE_KIND = 0x00000007  libraries/gadtools.h: *286
NW_EXTENDED      #define WFLG_NW_EXTENDED = 0x00040000
                 intuition/iobsolete.h: *169
NXADDLEN         #define 9 = 0x00000009  rexx/storage.h: *50
NXTLIST          #define u3.nxtlist  graphics/copper.h: *48
N_TRACTOR        #define 0x20 = 0x00000020  intuition/preferences.h: *187
Name             array [32] of unsigned char in struct NameInfo
         +0x0010 graphics/displayinfo.h: *135
NameInfo         structure tag size 0x0038 graphics/displayinfo.h: *132
NewBroker        structure tag size 0x001a libraries/commodities.h: *48
NewGadget        structure tag size 0x001e libraries/gadtools.h: *94
NewMenu          structure tag size 0x0014 libraries/gadtools.h: *123
NewScreen        structure tag size 0x0020 intuition/screens.h: *310
NewWindow        structure tag size 0x0030 intuition/intuition.h: *974
                 workbench/workbench.h: 45, 53
Next             pointer to struct ClipRect in struct ClipRect
         +0x0000 graphics/clip.h: *66
Next             pointer to struct cprlist in struct cprlist
         +0x0000 graphics/copper.h: *58
Next             pointer to struct CopList in struct CopList
         +0x0000 graphics/copper.h: *65
Next             pointer to struct UCopList in struct UCopList
         +0x0000 graphics/copper.h: *85
Next             pointer to struct ViewPort in struct ViewPort
         +0x0000 graphics/view.h: *43
Next             pointer to struct RasInfo in struct RasInfo
         +0x0000 graphics/view.h: *109
Next             pointer to struct RegionRectangle in struct RegionRectangle
         +0x0000 graphics/regions.h: *25
NextBorder       pointer to struct Border in struct Border
         +0x000c intuition/intuition.h: *605
NextComp         pointer to struct AnimComp in struct AnimComp
         +0x0006 graphics/gels.h: *183
NextGadget       pointer to struct Gadget in struct Gadget
         +0x0000 intuition/intuition.h: *218
NextImage        pointer to struct Image in struct Image
         +0x0010 intuition/intuition.h: *666
NextItem         pointer to struct MenuItem in struct MenuItem
         +0x0000 intuition/intuition.h: *92
NextMenu         pointer to struct Menu in struct Menu
         +0x0000 intuition/intuition.h: *64
NextOb           pointer to struct AnimOb in struct AnimOb
         +0x0000 graphics/gels.h: *203
NextRemember     pointer to struct Remember in struct Remember
         +0x0000 intuition/intuition.h: *1233
NextScreen       pointer to struct Screen in struct Screen
         +0x0000 intuition/screens.h: *100
NextSelect       unsigned short int in struct MenuItem
         +0x0020 intuition/intuition.h: *113
NextSeq          pointer to struct AnimComp in struct AnimComp
         +0x000e graphics/gels.h: *187
NextText         pointer to struct IntuiText in struct IntuiText
         +0x0010 intuition/intuition.h: *578
NextVSprite      pointer to struct VSprite in struct VSprite
         +0x0000 graphics/gels.h: *74
NextWindow       pointer to struct Window in struct Window
         +0x0000 intuition/intuition.h: *797
NexxStr          structure tag size 0x0010 rexx/storage.h: *42
                 rexx/rxslib.h: 37, 38, 39, 40, 41, 42, 43, 44
Node             structure tag size 0x000e exec/nodes.h: *24, 25, 26
                 exec/libraries.h: 35
                 exec/lists.h: 23, 24, 25
                 exec/tasks.h: 27
                 exec/ports.h: 31, 50
                 exec/memory.h: 31, 59
                 exec/interrupts.h: 25, 34
                 exec/semaphores.h: 42
                 devices/clipboard.h: 37
                 devices/keymap.h: 35, 41
                 graphics/gfxnodes.h: 20, 21
                 intuition/screens.h: 383
                 dos/var.h: 28
                 graphics/graphint.h: 22
                 libraries/configvars.h: 33
                 libraries/diskfont.h: 72
                 libraries/expansionbase.h: 37
                 libraries/mathresource.h: 37
                 resources/filesysres.h: 28, 34
                 rexx/storage.h: 163
Nominal          struct Rectangle(size 0x0008 bytes) in struct DimensionInfo
         +0x001a graphics/displayinfo.h: *100
NormalDPMX       unsigned short int in struct GfxBase
         +0x00dc graphics/gfxbase.h: *61
NormalDPMY       unsigned short int in struct GfxBase
         +0x00de graphics/gfxbase.h: *62
NormalDisplayColumns unsigned short int in struct GfxBase
         +0x00da graphics/gfxbase.h: *59
NormalDisplayInfo pointer to void in struct ColorMap
         +0x0018 graphics/view.h: *126
NormalDisplayRows unsigned short int in struct GfxBase
         +0x00d8 graphics/gfxbase.h: *58
NotAvailable     unsigned short int in struct DisplayInfo
         +0x0010 graphics/displayinfo.h: *53
NotifyMessage    structure tag size 0x0026 dos/notify.h: *41
NotifyRequest    structure tag size 0x0030 dos/notify.h: *45, 53
NumChars         short int in struct StringInfo
         +0x0010 intuition/intuition.h: *535
NumChars         short int in struct SGWork +0x001c intuition/sghooks.h: *45
NumStdSprites    unsigned short int in struct DisplayInfo
         +0x001c graphics/displayinfo.h: *57


2.0 IncludeXREF: O

_OBJ             macro (1 argument)   intuition/classes.h: *74
_OBJECT          macro (1 argument)   intuition/classes.h: *80
_Object          structure tag size 0x000c intuition/classes.h: *68
o_Class          pointer to struct IClass in struct _Object
         +0x0008 intuition/classes.h: *70
o_Node           struct MinNode(size 0x0008 bytes) in struct _Object
         +0x0000 intuition/classes.h: *69
obs              pointer to struct ClipRect in struct Layer_Info
         +0x0008 graphics/layers.h: *38
opAddMember      #define opMember  intuition/classusr.h: *123
opAddTail        structure tag size 0x0008 intuition/classusr.h: *117
opGet            structure tag size 0x000c intuition/classusr.h: *108
opMember         structure tag size 0x0008 intuition/classusr.h: *124
opSet            structure tag size 0x000c intuition/classusr.h: *78
opUpdate         structure tag size 0x0010 intuition/classusr.h: *88
opam_Object      pointer to unsigned long int in struct opMember
         +0x0004 intuition/classusr.h: *126
opat_List        pointer to struct List in struct opAddTail
         +0x0004 intuition/classusr.h: *119
opg_AttrID       unsigned long int in struct opGet
         +0x0004 intuition/classusr.h: *110
opg_Storage      pointer to unsigned long int in struct opGet
         +0x0008 intuition/classusr.h: *111
ops_AttrList     pointer to struct TagItem in struct opSet
         +0x0004 intuition/classusr.h: *80
ops_GInfo        pointer to struct GadgetInfo in struct opSet
         +0x0008 intuition/classusr.h: *81
opu_AttrList     pointer to struct TagItem in struct opUpdate
         +0x0004 intuition/classusr.h: *90
opu_Flags        unsigned long int in struct opUpdate
         +0x000c intuition/classusr.h: *95
opu_GInfo        pointer to struct GadgetInfo in struct opUpdate
         +0x0008 intuition/classusr.h: *91
OCLASS           macro (1 argument)   intuition/classes.h: *83
OCTANT1          #define 16 = 0x00000010  hardware/blit.h: *87
OCTANT2          #define 0 = 0x00000000  hardware/blit.h: *86
OCTANT3          #define 8 = 0x00000008  hardware/blit.h: *85
OCTANT4          #define 20 = 0x00000014  hardware/blit.h: *84
OCTANT5          #define 28 = 0x0000001c  hardware/blit.h: *83
OCTANT6          #define 12 = 0x0000000c  hardware/blit.h: *82
OCTANT7          #define 4 = 0x00000004  hardware/blit.h: *81
OCTANT8          #define 24 = 0x00000018  hardware/blit.h: *80
OFFSET           macro (2 arguments)   exec/initializers.h: *16
OFFSET_BEGINING  #define OFFSET_BEGINNING = 0xffffffff  dos/dos.h: *40
OFFSET_BEGINNING #define -1 = 0xffffffff  dos/dos.h: *36
OFFSET_CURRENT   #define 0 = 0x00000000  dos/dos.h: *37
OFFSET_END       #define 1 = 0x00000001  dos/dos.h: *38
OFF_DISPLAY      #define custom.dmacon = BITCLR|DMAF_RASTER;
                 graphics/gfxmacros.h: *24
OFF_SPRITE       #define custom.dmacon = BITCLR|DMAF_SPRITE;
                 graphics/gfxmacros.h: *26
OFF_VBLANK       #define custom.intena = BITCLR|INTF_VERTB;
                 graphics/gfxmacros.h: *29
OKABORT          #define 0x0004 = 0x00000004  intuition/intuition.h: *774
OKCANCEL         #define MENUCANCEL = 0x00000002  intuition/intuition.h: *775
OKIMATE_20       #define 0x09 = 0x00000009  intuition/preferences.h: *201
OKOK             #define MENUHOT = 0x00000001  intuition/intuition.h: *773
OLDDRAWERDATAFILESIZE #define (sizeof(struct OldDrawerData)) = 0x00000038
                 workbench/workbench.h: *50
OM_ADDMEMBER     #define (0x109) = 0x00000109  intuition/classusr.h: *72
OM_ADDTAIL       #define (0x105) = 0x00000105  intuition/classusr.h: *68
OM_DISPOSE       #define (0x102) = 0x00000102  intuition/classusr.h: *65
OM_Dummy         #define (0x100) = 0x00000100  intuition/classusr.h: *63
OM_GET           #define (0x104) = 0x00000104  intuition/classusr.h: *67
OM_NEW           #define (0x101) = 0x00000101  intuition/classusr.h: *64
OM_NOTIFY        #define (0x107) = 0x00000107  intuition/classusr.h: *70
OM_REMMEMBER     #define (0x10A) = 0x0000010a  intuition/classusr.h: *73
OM_REMOVE        #define (0x106) = 0x00000106  intuition/classusr.h: *69
OM_SET           #define (0x103) = 0x00000103  intuition/classusr.h: *66
OM_UPDATE        #define (0x108) = 0x00000108  intuition/classusr.h: *71
ONEDOT           #define 0x2 = 0x00000002  hardware/blit.h: *71
ONE_DOT          #define 0x02 = 0x00000002  graphics/rastport.h: *101
ON_DISPLAY       #define custom.dmacon = BITSET|DMAF_RASTER;
                 graphics/gfxmacros.h: *23
ON_SPRITE        #define custom.dmacon = BITSET|DMAF_SPRITE;
                 graphics/gfxmacros.h: *25
ON_VBLANK        #define custom.intena = BITSET|INTF_VERTB;
                 graphics/gfxmacros.h: *28
OPUF_INTERIM     #define (1<<0) = 0x00000001  intuition/classusr.h: *105
ORDERED_DITHERING #define 0x0000 = 0x00000000  intuition/preferences.h: *255
OSCAN_MAX        #define (3) = 0x00000003  intuition/screens.h: *366
OSCAN_STANDARD   #define (2) = 0x00000002  intuition/screens.h: *365
OSCAN_TEXT       #define (1) = 0x00000001  intuition/screens.h: *364
OSCAN_VIDEO      #define (4) = 0x00000004  intuition/screens.h: *367
OSERR_NOCHIPMEM  #define (4) = 0x00000004  intuition/screens.h: *300
OSERR_NOCHIPS    #define (2) = 0x00000002  intuition/screens.h: *298
OSERR_NOMEM      #define (3) = 0x00000003  intuition/screens.h: *299
OSERR_NOMONITOR  #define (1) = 0x00000001  intuition/screens.h: *297
OSERR_PUBNOTUNIQUE #define (5) = 0x00000005  intuition/screens.h: *301
OSERR_UNKNOWNMODE #define (6) = 0x00000006  intuition/screens.h: *302
OTHER_REFRESH    #define WFLG_OTHER_REFRESH = 0x000000c0
                 intuition/iobsolete.h: *155
OUTSTEP          #define 0x2000 = 0x00002000  graphics/gels.h: *43
OVERLAY          #define 0x0004 = 0x00000004  graphics/gels.h: *24
OVFLAG           #define 0x20 = 0x00000020  hardware/blit.h: *72
Object           typedef ULONG  intuition/classusr.h: *21, 126
OldDrawerData    structure tag size 0x0038 workbench/workbench.h: *44
OldX             short int in struct VSprite +0x0012 graphics/gels.h: *87
OldY             short int in struct VSprite +0x0010 graphics/gels.h: *87
OlderRequest     pointer to struct Requester in struct Requester
         +0x0000 intuition/intuition.h: *148
OpCode           short int in struct CopIns +0x0000 graphics/copper.h: *28


2.0 IncludeXREF: P

_p1              pointer to struct ClipRect in struct ClipRect
         +0x0018 graphics/clip.h: *71
_p2              pointer to struct ClipRect in struct ClipRect
         +0x001c graphics/clip.h: *71
pad              unsigned short int in struct BitMap
         +0x0006 graphics/gfx.h: *54
pad              array [4] of unsigned char in struct DisplayInfo
         +0x0024 graphics/displayinfo.h: *60
pad              array [14] of unsigned char in struct DimensionInfo
         +0x0042 graphics/displayinfo.h: *105
pad              array [36] of unsigned char in struct MonitorInfo
         +0x002c graphics/displayinfo.h: *120
pad0             array [255] of unsigned char in struct CIA
         +0x0001 hardware/cia.h: *33
pad1             char in struct narrator_rb +0x0057 devices/narrator.h: *121
pad1             array [255] of unsigned char in struct CIA
         +0x0101 hardware/cia.h: *35
pad10            array [255] of unsigned char in struct CIA
         +0x0a01 hardware/cia.h: *53
pad11            array [255] of unsigned char in struct CIA
         +0x0b01 hardware/cia.h: *55
pad12            array [255] of unsigned char in struct CIA
         +0x0c01 hardware/cia.h: *57
pad13            array [255] of unsigned char in struct CIA
         +0x0d01 hardware/cia.h: *59
pad14            array [255] of unsigned char in struct CIA
         +0x0e01 hardware/cia.h: *61
pad2             array [255] of unsigned char in struct CIA
         +0x0201 hardware/cia.h: *37
pad2d            unsigned char in struct Custom +0x005a hardware/custom.h: *68
pad3             array [255] of unsigned char in struct CIA
         +0x0301 hardware/cia.h: *39
pad34            array [4] of unsigned short int in struct Custom
         +0x0068 hardware/custom.h: *76
pad3b            array [3] of unsigned short int in struct Custom
         +0x0076 hardware/custom.h: *80
pad4             array [255] of unsigned char in struct CIA
         +0x0401 hardware/cia.h: *41
pad5             array [255] of unsigned char in struct CIA
         +0x0501 hardware/cia.h: *43
pad6             array [255] of unsigned char in struct CIA
         +0x0601 hardware/cia.h: *45
pad7             array [255] of unsigned char in struct CIA
         +0x0701 hardware/cia.h: *47
pad8             array [255] of unsigned char in struct CIA
         +0x0801 hardware/cia.h: *49
pad86            array [1] of unsigned short int in struct Custom
         +0x010e hardware/custom.h: *113
pad9             array [255] of unsigned char in struct CIA
         +0x0901 hardware/cia.h: *51
pb_ChkSum        long int in struct PartitionBlock
         +0x0008 devices/hardblocks.h: *131
pb_DevFlags      unsigned long int in struct PartitionBlock
         +0x0020 devices/hardblocks.h: *136
pb_DriveName     array [32] of unsigned char in struct PartitionBlock
         +0x0024 devices/hardblocks.h: *137
pb_EReserved     array [15] of unsigned long int in struct PartitionBlock
         +0x00c4 devices/hardblocks.h: *141
pb_Environment   array [17] of unsigned long int in struct PartitionBlock
         +0x0080 devices/hardblocks.h: *140
pb_Flags         unsigned long int in struct PartitionBlock
         +0x0014 devices/hardblocks.h: *134
pb_HostID        unsigned long int in struct PartitionBlock
         +0x000c devices/hardblocks.h: *132
pb_ID            unsigned long int in struct PartitionBlock
         +0x0000 devices/hardblocks.h: *129
pb_Next          unsigned long int in struct PartitionBlock
         +0x0010 devices/hardblocks.h: *133
pb_Reserved1     array [2] of unsigned long int in struct PartitionBlock
         +0x0018 devices/hardblocks.h: *135
pb_Reserved2     array [15] of unsigned long int in struct PartitionBlock
         +0x0044 devices/hardblocks.h: *139
pb_SummedLongs   unsigned long int in struct PartitionBlock
         +0x0004 devices/hardblocks.h: *130
pd_Device        struct DeviceData(size 0x0034 bytes) in struct PrinterData
         +0x0000 devices/prtbase.h: *66
pd_Flags         unsigned char in struct PrinterData
         +0x09b6 devices/prtbase.h: *95
pd_Flags1        unsigned char in struct PrinterData
         +0x0aa1 devices/prtbase.h: *100
pd_IORPort       struct MsgPort(size 0x0022 bytes) in struct PrinterData
         +0x0138 devices/prtbase.h: *92
pd_OldStk        array [2048] of unsigned char in struct PrinterData
         +0x01b6 devices/prtbase.h: *94
pd_PBothReady    pointer to function returning int in struct PrinterData
         +0x0068 devices/prtbase.h: *74
pd_PIOR0         #define pd_ior0.pd_p0  devices/prtbase.h: *80
pd_PIOR1         #define pd_ior1.pd_p1  devices/prtbase.h: *88
pd_PWaitEnabled unsigned char in struct PrinterData
         +0x0aa0 devices/prtbase.h: *98
pd_PWrite        pointer to function returning int in struct PrinterData
         +0x0064 devices/prtbase.h: *73
pd_Preferences   struct Preferences(size 0x00e8 bytes) in struct PrinterData
         +0x09b8 devices/prtbase.h: *97
pd_PrintBuf      pointer to unsigned char in struct PrinterData
         +0x0060 devices/prtbase.h: *72
pd_PrinterSegment long int in struct PrinterData +0x0056 devices/prtbase.h: *68
pd_PrinterType   unsigned short int in struct PrinterData
         +0x005a devices/prtbase.h: *69
pd_SIOR0         #define pd_ior0.pd_s0  devices/prtbase.h: *81
pd_SIOR1         #define pd_ior1.pd_s1  devices/prtbase.h: *89
pd_SegmentData   pointer to struct PrinterSegment in struct PrinterData
         +0x005c devices/prtbase.h: *71
pd_Stk           array [4096] of unsigned char in struct PrinterData
         +0x0aa2 devices/prtbase.h: *101
pd_TC            struct Task(size 0x005c bytes) in struct PrinterData
         +0x015a devices/prtbase.h: *93
pd_TIOR          struct timerequest(size 0x0028 bytes) in struct PrinterData
         +0x0110 devices/prtbase.h: *91
pd_Unit          struct MsgPort(size 0x0022 bytes) in struct PrinterData
         +0x0034 devices/prtbase.h: *67
pd_ior0          union (no tag) (size 0x0052 bytes) in struct PrinterData
         +0x006c devices/prtbase.h: *78
pd_ior1          union (no tag) (size 0x0052 bytes) in struct PrinterData
         +0x00be devices/prtbase.h: *86
pd_p0            struct IOExtPar(size 0x003e bytes) in union (no tag)
         +0x0000 devices/prtbase.h: *76
pd_p1            struct IOExtPar(size 0x003e bytes) in union (no tag)
         +0x0000 devices/prtbase.h: *84
pd_pad           unsigned char in struct PrinterData
         +0x09b7 devices/prtbase.h: *96
pd_s0            struct IOExtSer(size 0x0052 bytes) in union (no tag)
         +0x0000 devices/prtbase.h: *77
pd_s1            struct IOExtSer(size 0x0052 bytes) in union (no tag)
         +0x0000 devices/prtbase.h: *85
ped_8BitChars    pointer to pointer to char in struct PrinterExtendedData
         +0x0036 devices/prtbase.h: *155
ped_Close        pointer to function returning void in struct
                 PrinterExtendedData
         +0x0010 devices/prtbase.h: *140
ped_ColorClass   unsigned char in struct PrinterExtendedData
         +0x0015 devices/prtbase.h: *142
ped_Commands     pointer to pointer to pointer to char in struct
                 PrinterExtendedData
         +0x0026 devices/prtbase.h: *150
ped_ConvFunc     pointer to function returning int in struct
                 PrinterExtendedData
         +0x003e devices/prtbase.h: *159
ped_DoSpecial    pointer to function returning int in struct
                 PrinterExtendedData
         +0x002a devices/prtbase.h: *151
ped_Expunge      pointer to function returning void in struct
                 PrinterExtendedData
         +0x0008 devices/prtbase.h: *138
ped_Init         pointer to function returning void in struct
                 PrinterExtendedData
         +0x0004 devices/prtbase.h: *137
ped_MaxColumns   unsigned char in struct PrinterExtendedData
         +0x0016 devices/prtbase.h: *143
ped_MaxXDots     unsigned long int in struct PrinterExtendedData
         +0x001a devices/prtbase.h: *146
ped_MaxYDots     unsigned long int in struct PrinterExtendedData
         +0x001e devices/prtbase.h: *147
ped_NumCharSets unsigned char in struct PrinterExtendedData
         +0x0017 devices/prtbase.h: *144
ped_NumRows      unsigned short int in struct PrinterExtendedData
         +0x0018 devices/prtbase.h: *145
ped_Open         pointer to function returning int in struct
                 PrinterExtendedData
         +0x000c devices/prtbase.h: *139
ped_PrintMode    long int in struct PrinterExtendedData
         +0x003a devices/prtbase.h: *156
ped_PrinterClass unsigned char in struct PrinterExtendedData
         +0x0014 devices/prtbase.h: *141
ped_PrinterName pointer to char in struct PrinterExtendedData
         +0x0000 devices/prtbase.h: *136
ped_Render       pointer to function returning int in struct
                 PrinterExtendedData
         +0x002e devices/prtbase.h: *152
ped_TimeoutSecs long int in struct PrinterExtendedData
         +0x0032 devices/prtbase.h: *153
ped_XDotsInch    unsigned short int in struct PrinterExtendedData
         +0x0022 devices/prtbase.h: *148
ped_YDotsInch    unsigned short int in struct PrinterExtendedData
         +0x0024 devices/prtbase.h: *149
pgx_Container    struct IBox(size 0x0008 bytes) in struct PGX
         +0x0000 intuition/cghooks.h: *72
pgx_NewKnob      struct IBox(size 0x0008 bytes) in struct PGX
         +0x0008 intuition/cghooks.h: *73
pi_BotBuf        pointer to unsigned short int in struct PrtInfo
         +0x0038 devices/prtgfx.h: *49
pi_ColorInt      pointer to union colorEntryin struct PrtInfo
         +0x0018 devices/prtgfx.h: *41
pi_ColorIntSize unsigned short int in struct PrtInfo
         +0x0042 devices/prtgfx.h: *54
pi_ColorMap      pointer to union colorEntryin struct PrtInfo
         +0x0014 devices/prtgfx.h: *40
pi_ColorMapSize unsigned short int in struct PrtInfo
         +0x0040 devices/prtgfx.h: *53
pi_Dest1Int      pointer to union colorEntryin struct PrtInfo
         +0x0020 devices/prtgfx.h: *43
pi_Dest1IntSize unsigned short int in struct PrtInfo
         +0x0046 devices/prtgfx.h: *56
pi_Dest2Int      pointer to union colorEntryin struct PrtInfo
         +0x0024 devices/prtgfx.h: *44
pi_Dest2IntSize unsigned short int in struct PrtInfo
         +0x0048 devices/prtgfx.h: *57
pi_HamBuf        pointer to unsigned short int in struct PrtInfo
         +0x0010 devices/prtgfx.h: *39
pi_HamBufSize    unsigned short int in struct PrtInfo
         +0x003e devices/prtgfx.h: *52
pi_HamInt        pointer to union colorEntryin struct PrtInfo
         +0x001c devices/prtgfx.h: *42
pi_HamIntSize    unsigned short int in struct PrtInfo
         +0x0044 devices/prtgfx.h: *55
pi_PrefsFlags    unsigned short int in struct PrtInfo
         +0x004e devices/prtgfx.h: *61
pi_RowBuf        pointer to unsigned short int in struct PrtInfo
         +0x000c devices/prtgfx.h: *38
pi_RowBufSize    unsigned short int in struct PrtInfo
         +0x003c devices/prtgfx.h: *51
pi_ScaleX        pointer to unsigned short int in struct PrtInfo
         +0x0028 devices/prtgfx.h: *45
pi_ScaleXAlt     pointer to unsigned short int in struct PrtInfo
         +0x002c devices/prtgfx.h: *46
pi_ScaleXAltSize unsigned short int in struct PrtInfo
         +0x004c devices/prtgfx.h: *59
pi_ScaleXSize    unsigned short int in struct PrtInfo
         +0x004a devices/prtgfx.h: *58
pi_TopBuf        pointer to unsigned short int in struct PrtInfo
         +0x0034 devices/prtgfx.h: *48
pi_dmatrix       pointer to unsigned char in struct PrtInfo
         +0x0030 devices/prtgfx.h: *47
pi_ety           short int in struct PrtInfo +0x0068 devices/prtgfx.h: *71
pi_flags         unsigned short int in struct PrtInfo
         +0x0070 devices/prtgfx.h: *75
pi_height        unsigned short int in struct PrtInfo
         +0x005a devices/prtgfx.h: *66
pi_pc            unsigned long int in struct PrtInfo
         +0x005c devices/prtgfx.h: *67
pi_pr            unsigned long int in struct PrtInfo
         +0x0060 devices/prtgfx.h: *68
pi_render        pointer to function returning int in struct PrtInfo
         +0x0000 devices/prtgfx.h: *35
pi_rp            pointer to struct RastPort in struct PrtInfo
         +0x0004 devices/prtgfx.h: *36
pi_special       unsigned long int in struct PrtInfo
         +0x0050 devices/prtgfx.h: *62
pi_temprp        pointer to struct RastPort in struct PrtInfo
         +0x0008 devices/prtgfx.h: *37
pi_tempwidth     unsigned short int in struct PrtInfo
         +0x006e devices/prtgfx.h: *74
pi_threshold     unsigned short int in struct PrtInfo
         +0x006c devices/prtgfx.h: *73
pi_width         unsigned short int in struct PrtInfo
         +0x0058 devices/prtgfx.h: *65
pi_xpos          unsigned short int in struct PrtInfo
         +0x006a devices/prtgfx.h: *72
pi_xstart        unsigned short int in struct PrtInfo
         +0x0054 devices/prtgfx.h: *63
pi_ymod          unsigned short int in struct PrtInfo
         +0x0066 devices/prtgfx.h: *70
pi_ymult         unsigned short int in struct PrtInfo
         +0x0064 devices/prtgfx.h: *69
pi_ystart        unsigned short int in struct PrtInfo
         +0x0056 devices/prtgfx.h: *64
pitch            unsigned short int in struct narrator_rb
         +0x0032 devices/narrator.h: *96
pos              unsigned short int in struct SpriteDef
         +0x0000 hardware/custom.h: *117
posctldata       pointer to unsigned short int in struct SimpleSprite
         +0x0000 graphics/sprite.h: *23
pot0dat          unsigned short int in struct Custom
         +0x0012 hardware/custom.h: *37
pot1dat          unsigned short int in struct Custom
         +0x0014 hardware/custom.h: *38
potgo            unsigned short int in struct Custom
         +0x0034 hardware/custom.h: *53
potinp           unsigned short int in struct Custom
         +0x0016 hardware/custom.h: *39
pow              macro (2 arguments)   libraries/mathffp.h: *46
                 libraries/mathieeedp.h: *46
pr_Arguments     pointer to unsigned char in struct Process
         +0x00cc dos/dosextens.h: *64
pr_CES           long int in struct Process +0x00e0 dos/dosextens.h: *67
pr_CIS           long int in struct Process +0x009c dos/dosextens.h: *50
pr_CLI           long int in struct Process +0x00ac dos/dosextens.h: *54
pr_COS           long int in struct Process +0x00a0 dos/dosextens.h: *51
pr_ConsoleTask   pointer to void in struct Process +0x00a4 dos/dosextens.h: *52
pr_CurrentDir    long int in struct Process +0x0098 dos/dosextens.h: *49
pr_ExitCode      pointer to function returning void in struct Process
         +0x00c4 dos/dosextens.h: *62
pr_ExitData      long int in struct Process +0x00c8 dos/dosextens.h: *63
pr_FileSystemTask pointer to void in struct Process
         +0x00a8 dos/dosextens.h: *53
pr_Flags         long int in struct Process +0x00c0 dos/dosextens.h: *61
pr_GlobVec       pointer to void in struct Process +0x0088 dos/dosextens.h: *45
pr_HomeDir       long int in struct Process +0x00bc dos/dosextens.h: *60
pr_LocalVars     struct MinList(size 0x000c bytes) in struct Process
         +0x00d0 dos/dosextens.h: *65
pr_MsgPort       struct MsgPort(size 0x0022 bytes) in struct Process
         +0x005c dos/dosextens.h: *41
pr_Pad           short int in struct Process +0x007e dos/dosextens.h: *42
pr_PktWait       pointer to void in struct Process +0x00b4 dos/dosextens.h: *56
pr_Result2       long int in struct Process +0x0094 dos/dosextens.h: *48
pr_ReturnAddr    pointer to void in struct Process +0x00b0 dos/dosextens.h: *55
pr_SegList       long int in struct Process +0x0080 dos/dosextens.h: *43
pr_ShellPrivate unsigned long int in struct Process
         +0x00dc dos/dosextens.h: *66
pr_StackBase     long int in struct Process +0x0090 dos/dosextens.h: *47
pr_StackSize     long int in struct Process +0x0084 dos/dosextens.h: *44
pr_Task          struct Task(size 0x005c bytes) in struct Process
         +0x0000 dos/dosextens.h: *40
pr_TaskNum       long int in struct Process +0x008c dos/dosextens.h: *46
pr_WindowPtr     pointer to void in struct Process +0x00b8 dos/dosextens.h: *57
prev             pointer to struct ClipRect in struct ClipRect
         +0x0004 graphics/clip.h: *67
priority         char in struct narrator_rb +0x0056 devices/narrator.h: *120
priority         unsigned short int in struct Layer
         +0x001c graphics/clip.h: *41
ps_NextSegment   unsigned long int in struct PrinterSegment
         +0x0000 devices/prtbase.h: *163
ps_PED           struct PrinterExtendedData(size 0x0042 bytes) in struct
                 PrinterSegment
         +0x000c devices/prtbase.h: *167
ps_Revision      unsigned short int in struct PrinterSegment
         +0x000a devices/prtbase.h: *166
ps_Version       unsigned short int in struct PrinterSegment
         +0x0008 devices/prtbase.h: *165
ps_runAlert      unsigned long int in struct PrinterSegment
         +0x0004 devices/prtbase.h: *164
psn_Flags        unsigned short int in struct PubScreenNode
         +0x0012 intuition/screens.h: *385
psn_Node         struct Node(size 0x000e bytes) in struct PubScreenNode
         +0x0000 intuition/screens.h: *383
psn_Screen       pointer to struct Screen in struct PubScreenNode
         +0x000e intuition/screens.h: *384
psn_SigBit       unsigned char in struct PubScreenNode
         +0x001c intuition/screens.h: *389
psn_SigTask      pointer to struct Task in struct PubScreenNode
         +0x0018 intuition/screens.h: *388
psn_Size         short int in struct PubScreenNode
         +0x0014 intuition/screens.h: *386
psn_VisitorCount short int in struct PubScreenNode
         +0x0016 intuition/screens.h: *387
PAL              #define 4 = 0x00000004  graphics/gfxbase.h: *97
PALETTEIDCMP     #define (IDCMP_GADGETUP) = 0x00000040
                 libraries/gadtools.h: *75
PALETTE_KIND     #define 8 = 0x00000008  libraries/gadtools.h: *42
PAL_MONITOR_ID   #define 0x00021000 = 0x00021000  graphics/displayinfo.h: *149
PAL_MONITOR_NAME #define "pal.monitor"  graphics/monitor.h: *67
PARALLELNAME     #define "parallel.device"  devices/parallel.h: *91
PARALLEL_PRINTER #define 0x00 = 0x00000000  intuition/preferences.h: *141
PARB_ACKMODE     #define 2 = 0x00000002  devices/parallel.h: *67
PARB_EOFMODE     #define 1 = 0x00000001  devices/parallel.h: *70
PARB_FASTMODE    #define 3 = 0x00000003  devices/parallel.h: *62
PARB_RAD_BOOGIE  #define 3 = 0x00000003  devices/parallel.h: *64
PARB_SHARED      #define 5 = 0x00000005  devices/parallel.h: *58
PARB_SLOWMODE    #define 4 = 0x00000004  devices/parallel.h: *60
PARF_ACKMODE     #define (1<<2) = 0x00000004  devices/parallel.h: *68
PARF_EOFMODE     #define (1<<1) = 0x00000002  devices/parallel.h: *71
PARF_FASTMODE    #define (1<<3) = 0x00000008  devices/parallel.h: *63
PARF_RAD_BOOGIE  #define (1<<3) = 0x00000008  devices/parallel.h: *65
PARF_SHARED      #define (1<<5) = 0x00000020  devices/parallel.h: *59
PARF_SLOWMODE    #define (1<<4) = 0x00000010  devices/parallel.h: *61
PA_IGNORE        #define 2 = 0x00000002  exec/ports.h: *44
PA_SIGNAL        #define 0 = 0x00000000  exec/ports.h: *42
PA_SOFTINT       #define 1 = 0x00000001  exec/ports.h: *43
PBFB_BOOTABLE    #define 0 = 0x00000000  devices/hardblocks.h: *146
PBFB_NOMOUNT     #define 1 = 0x00000001  devices/hardblocks.h: *148
PBFF_BOOTABLE    #define 1L = 0x00000001  devices/hardblocks.h: *147
PBFF_NOMOUNT     #define 2L = 0x00000002  devices/hardblocks.h: *149
PCC_4COLOR       #define 0x04 = 0x00000004  devices/prtbase.h: *120
PCC_ADDITIVE     #define 0x08 = 0x00000008  devices/prtbase.h: *121
PCC_BGR          #define 0x0A = 0x0000000a  devices/prtbase.h: *123
PCC_BGRW         #define 0x0C = 0x0000000c  devices/prtbase.h: *125
PCC_BGR_WB       #define 0x0B = 0x0000000b  devices/prtbase.h: *124
PCC_BW           #define 0x01 = 0x00000001  devices/prtbase.h: *116
PCC_MULTI_PASS   #define 0x10 = 0x00000010  devices/prtbase.h: *133
PCC_WB           #define 0x09 = 0x00000009  devices/prtbase.h: *122
PCC_YMC          #define 0x02 = 0x00000002  devices/prtbase.h: *117
PCC_YMCB         #define 0x04 = 0x00000004  devices/prtbase.h: *119
PCC_YMC_BW       #define 0x03 = 0x00000003  devices/prtbase.h: *118
PCMBLACK         #define 3 = 0x00000003  devices/prtgfx.h: *22
PCMBLUE          #define PCMYELLOW = 0x00000000  devices/prtgfx.h: *23
PCMCYAN          #define 2 = 0x00000002  devices/prtgfx.h: *21
PCMGREEN         #define PCMMAGENTA = 0x00000001  devices/prtgfx.h: *24
PCMMAGENTA       #define 1 = 0x00000001  devices/prtgfx.h: *20
PCMRED           #define PCMCYAN = 0x00000002  devices/prtgfx.h: *25
PCMWHITE         #define PCMBLACK = 0x00000003  devices/prtgfx.h: *26
PCMYELLOW        #define 0 = 0x00000000  devices/prtgfx.h: *19
PDCMD_QUERY      #define (CMD_NONSTD) = 0x00000009  devices/parallel.h: *93
PDCMD_SETPARAMS  #define (CMD_NONSTD+1) = 0x0000000a  devices/parallel.h: *94
PDERR_BADDIMENSION #define 4 = 0x00000004  devices/printer.h: *207
PDERR_BUFFERMEMORY #define 7 = 0x00000007  devices/printer.h: *210
PDERR_CANCEL     #define 1 = 0x00000001  devices/printer.h: *204
PDERR_DIMENSIONOVFLOW #define 5 = 0x00000005  devices/printer.h: *208
PDERR_INTERNALMEMORY #define 6 = 0x00000006  devices/printer.h: *209
PDERR_INVERTHAM  #define 3 = 0x00000003  devices/printer.h: *206
PDERR_NOERR      #define 0 = 0x00000000  devices/printer.h: *203
PDERR_NOTGRAPHICS #define 2 = 0x00000002  devices/printer.h: *205
PDERR_TOOKCONTROL #define 8 = 0x00000008  devices/printer.h: *218
PF2PRI           #define 0x40 = 0x00000040  graphics/display.h: *20
PFA_FINE_SCROLL  #define 0xF = 0x0000000f  graphics/display.h: *27
PFBA             #define 0x0040 = 0x00000040  graphics/view.h: *93
PFB_FINE_SCROLL_SHIFT #define 4 = 0x00000004  graphics/display.h: *28
PFL              pointer to function returning "LONG"   libraries/commodities.h: *80
PF_ACTION        #define 3 = 0x00000003  exec/ports.h: *41
PF_FINE_SCROLL_MASK #define 0xF = 0x0000000f  graphics/display.h: *29
PGA_BORDERLESS   #define PGA_Borderless = 0x80031002
                 intuition/iobsolete.h: *216
PGA_Borderless   #define (PGA_Dummy + 0x0002) = 0x80031002
                 intuition/gadgetclass.h: *104
PGA_Dummy        #define (TAG_USER + 0x31000) = 0x80031000
                 intuition/gadgetclass.h: *101
PGA_FREEDOM      #define PGA_Freedom = 0x80031001  intuition/iobsolete.h: *215
PGA_Freedom      #define (PGA_Dummy + 0x0001) = 0x80031001
                 intuition/gadgetclass.h: *102
PGA_HORIZBODY    #define PGA_HorizBody = 0x80031004
                 intuition/iobsolete.h: *218
PGA_HORIZPOT     #define PGA_HorizPot = 0x80031003
                 intuition/iobsolete.h: *217
PGA_HorizBody    #define (PGA_Dummy + 0x0004) = 0x80031004
                 intuition/gadgetclass.h: *106
PGA_HorizPot     #define (PGA_Dummy + 0x0003) = 0x80031003
                 intuition/gadgetclass.h: *105
PGA_NewLook      #define (PGA_Dummy + 0x000A) = 0x8003100a
                 intuition/gadgetclass.h: *113
PGA_TOP          #define PGA_Top = 0x80031009  intuition/iobsolete.h: *223
PGA_TOTAL        #define PGA_Total = 0x80031007  intuition/iobsolete.h: *221
PGA_Top          #define (PGA_Dummy + 0x0009) = 0x80031009
                 intuition/gadgetclass.h: *111
PGA_Total        #define (PGA_Dummy + 0x0007) = 0x80031007
                 intuition/gadgetclass.h: *109
PGA_VERTBODY     #define PGA_VertBody = 0x80031006
                 intuition/iobsolete.h: *220
PGA_VERTPOT      #define PGA_VertPot = 0x80031005  intuition/iobsolete.h: *219
PGA_VISIBLE      #define PGA_Visible = 0x80031008  intuition/iobsolete.h: *222
PGA_VertBody     #define (PGA_Dummy + 0x0006) = 0x80031006
                 intuition/gadgetclass.h: *108
PGA_VertPot      #define (PGA_Dummy + 0x0005) = 0x80031005
                 intuition/gadgetclass.h: *107
PGA_Visible      #define (PGA_Dummy + 0x0008) = 0x80031008
                 intuition/gadgetclass.h: *110
PGX              structure tag size 0x0010 intuition/cghooks.h: *71
PI               #define ((float) 3.141592653589793)  libraries/mathffp.h: *16
                 libraries/mathieeedp.h: 14
PI2              #define (PI/((double)2))  libraries/mathffp.h: *19
                 libraries/mathieeedp.h: *19
PI4              #define (PI/((double)4))  libraries/mathffp.h: *20
                 libraries/mathieeedp.h: *20
PICA             #define 0x000 = 0x00000000  intuition/preferences.h: *159
PIXEL_DIMENSIONS #define 0x0040 = 0x00000040  intuition/preferences.h: *250
PLACETEXT_ABOVE  #define 0x0004 = 0x00000004  libraries/gadtools.h: *113
PLACETEXT_BELOW  #define 0x0008 = 0x00000008  libraries/gadtools.h: *114
PLACETEXT_IN     #define 0x0010 = 0x00000010  libraries/gadtools.h: *115
PLACETEXT_LEFT   #define 0x0001 = 0x00000001  libraries/gadtools.h: *111
PLACETEXT_RIGHT  #define 0x0002 = 0x00000002  libraries/gadtools.h: *112
PLANEPTR         pointer to "UBYTE"  graphics/gfx.h: *46, 55
PLNCNTMSK        #define 0x7 = 0x00000007  graphics/display.h: *17
PLNCNTSHFT       #define 12 = 0x0000000c  graphics/display.h: *19
PMB_ASM          #define (M_LNM+1) = 0x00000015  devices/conunit.h: *50, 98
PMB_AWM          #define (PMB_ASM+1) = 0x00000016  devices/conunit.h: *51, 98
POINTERSIZE      #define (1 + 16 + 1) * 2 = 0x00000024
                 intuition/preferences.h: *30, 61
POINTREL         #define 0x0001 = 0x00000001  intuition/intuition.h: *181
POPPUBSCREEN     #define 0x0002 = 0x00000002  intuition/screens.h: *398
POTGONAME        #define "potgo.resource"  resources/potgo.h: *14
PPCB_COLOR       #define 1 = 0x00000001  devices/prtbase.h: *107
PPCB_GFX         #define 0 = 0x00000000  devices/prtbase.h: *105
PPCF_COLOR       #define 0x2 = 0x00000002  devices/prtbase.h: *108
PPCF_GFX         #define 0x1 = 0x00000001  devices/prtbase.h: *106
PPC_BWALPHA      #define 0x00 = 0x00000000  devices/prtbase.h: *110
PPC_BWGFX        #define 0x01 = 0x00000001  devices/prtbase.h: *111
PPC_COLORALPHA   #define 0x02 = 0x00000002  devices/prtbase.h: *112
PPC_COLORGFX     #define 0x03 = 0x00000003  devices/prtbase.h: *113
PRB_CLOSEINPUT   #define 3 = 0x00000003  dos/dosextens.h: *79
PRB_CLOSEOUTPUT  #define 4 = 0x00000004  dos/dosextens.h: *81
PRB_FREEARGS     #define 5 = 0x00000005  dos/dosextens.h: *83
PRB_FREECLI      #define 2 = 0x00000002  dos/dosextens.h: *77
PRB_FREECURRDIR  #define 1 = 0x00000001  dos/dosextens.h: *75
PRB_FREESEGLIST  #define 0 = 0x00000000  dos/dosextens.h: *73
PRD_DUMPRPORT    #define (CMD_NONSTD+2) = 0x0000000b  devices/printer.h: *33
PRD_PRTCOMMAND   #define (CMD_NONSTD+1) = 0x0000000a  devices/printer.h: *32
PRD_QUERY        #define (CMD_NONSTD+3) = 0x0000000c  devices/printer.h: *34
PRD_RAWWRITE     #define (CMD_NONSTD+0) = 0x00000009  devices/printer.h: *31
PREDRAWN         #define 0x0002 = 0x00000002  intuition/intuition.h: *186
PRF_CLOSEINPUT   #define 8 = 0x00000008  dos/dosextens.h: *80
PRF_CLOSEOUTPUT  #define 16 = 0x00000010  dos/dosextens.h: *82
PRF_FREEARGS     #define 32 = 0x00000020  dos/dosextens.h: *84
PRF_FREECLI      #define 4 = 0x00000004  dos/dosextens.h: *78
PRF_FREECURRDIR  #define 2 = 0x00000002  dos/dosextens.h: *76
PRF_FREESEGLIST  #define 1 = 0x00000001  dos/dosextens.h: *74
PRIMARY_CLIP     #define 0 = 0x00000000  devices/clipboard.h: *57
PROPBORDERLESS   #define 0x0008 = 0x00000008  intuition/intuition.h: *506
PROPGADGET       #define GTYP_PROPGADGET = 0x00000003
                 intuition/iobsolete.h: *106
PROPGCLASS       #define "propgclass"  intuition/classusr.h: *48
PROPNEWLOOK      #define 0x0010 = 0x00000010  intuition/intuition.h: *510
PROTO_MONITOR_ID #define 0x00051000 = 0x00051000  graphics/displayinfo.h: *214
PSNF_PRIVATE     #define (0x0001) = 0x00000001  intuition/screens.h: *392
PTermArray0      unsigned long int in struct IOPArray
         +0x0000 devices/parallel.h: *20
PTermArray1      unsigned long int in struct IOPArray
         +0x0004 devices/parallel.h: *21
PUBLICSCREEN     #define 0x0002 = 0x00000002  intuition/screens.h: *162
P_ANY            #define 0x80 = 0x00000080  dos/dosasl.h: *124
P_BUFSIZE        #define 256 = 0x00000100  devices/prtbase.h: *62
P_CLASS          #define 0x88 = 0x00000088  dos/dosasl.h: *132
P_NOT            #define 0x85 = 0x00000085  dos/dosasl.h: *129
P_NOTCLASS       #define 0x87 = 0x00000087  dos/dosasl.h: *131
P_NOTEND         #define 0x86 = 0x00000086  dos/dosasl.h: *130
P_OLDSTKSIZE     #define 0x0800 = 0x00000800  devices/prtbase.h: *60, 94
P_OREND          #define 0x84 = 0x00000084  dos/dosasl.h: *128
P_ORNEXT         #define 0x83 = 0x00000083  dos/dosasl.h: *127
P_ORSTART        #define 0x82 = 0x00000082  dos/dosasl.h: *126
P_REPBEG         #define 0x89 = 0x00000089  dos/dosasl.h: *133
P_REPEND         #define 0x8A = 0x0000008a  dos/dosasl.h: *134
P_SAFESIZE       #define 128 = 0x00000080  devices/prtbase.h: *63
P_SINGLE         #define 0x81 = 0x00000081  dos/dosasl.h: *125
P_STKSIZE        #define 0x1000 = 0x00001000  devices/prtbase.h: *61, 101
P_STOP           #define 0x8B = 0x0000008b  dos/dosasl.h: *135
PaletteRange     unsigned short int in struct DisplayInfo
         +0x001e graphics/displayinfo.h: *58
PaperLength      unsigned short int in struct Preferences
         +0x00b2 intuition/preferences.h: *99
PaperSize        unsigned short int in struct Preferences
         +0x00b0 intuition/preferences.h: *98
PaperType        unsigned short int in struct Preferences
         +0x00b4 intuition/preferences.h: *100
ParErr_BufTooBig #define 2 = 0x00000002  devices/parallel.h: *97
ParErr_DevBusy   #define 1 = 0x00000001  devices/parallel.h: *96
ParErr_InitErr   #define 7 = 0x00000007  devices/parallel.h: *102
ParErr_InvParam  #define 3 = 0x00000003  devices/parallel.h: *98
ParErr_LineErr   #define 4 = 0x00000004  devices/parallel.h: *99
ParErr_NotOpen   #define 5 = 0x00000005  devices/parallel.h: *100
ParErr_PortReset #define 6 = 0x00000006  devices/parallel.h: *101
Parent           pointer to struct Window in struct Window
         +0x0042 intuition/intuition.h: *844
PartitionBlock   structure tag size 0x0100 devices/hardblocks.h: *128
PenHeight        short int in struct RastPort +0x0032 graphics/rastport.h: *77
PenWidth         short int in struct RastPort +0x0030 graphics/rastport.h: *76
Pens             array [2] of unsigned char in struct StringExtend
         +0x0004 intuition/sghooks.h: *22
PixelSpeed       unsigned short int in struct DisplayInfo
         +0x001a graphics/displayinfo.h: *56
PlaneOnOff       unsigned char in struct Image
         +0x000f intuition/intuition.h: *660
PlaneOnOff       char in struct VSprite +0x0039 graphics/gels.h: *131
PlanePick        unsigned char in struct Image
         +0x000e intuition/intuition.h: *660
PlanePick        char in struct VSprite +0x0038 graphics/gels.h: *130
Planes           array [8] of pointer to unsigned char in struct BitMap
         +0x0008 graphics/gfx.h: *55
Point            typedef struct tPoint  graphics/gfx.h: *44
                 graphics/displayinfo.h: 55, 59, 113, 114
Pointer          pointer to unsigned short int in struct Window
         +0x004a intuition/intuition.h: *849
PointerMatrix    array [36] of unsigned short int in struct Preferences
         +0x001c intuition/preferences.h: *61
PointerTicks     unsigned short int in struct Preferences
         +0x006c intuition/preferences.h: *67
PortList         struct List(size 0x000e bytes) in struct ExecBase
         +0x0188 exec/execbase.h: *91
PowerSupplyFrequency unsigned char in struct ExecBase
         +0x0213 exec/execbase.h: *112
Preferences      structure tag size 0x00e8 intuition/preferences.h: *44
                 devices/prtbase.h: 97
Prev             pointer to struct RegionRectangle in struct RegionRectangle
         +0x0004 graphics/regions.h: *25
PrevBuffer       pointer to unsigned char in struct SGWork
         +0x000c intuition/sghooks.h: *38
PrevComp         pointer to struct AnimComp in struct AnimComp
         +0x000a graphics/gels.h: *184
PrevOb           pointer to struct AnimOb in struct AnimOb
         +0x0004 graphics/gels.h: *203
PrevSeq          pointer to struct AnimComp in struct AnimComp
         +0x0012 graphics/gels.h: *188
PrevVSprite      pointer to struct VSprite in struct VSprite
         +0x0004 graphics/gels.h: *75
PrintAspect      unsigned short int in struct Preferences
         +0x00aa intuition/preferences.h: *93
PrintDensity     unsigned char in struct Preferences
         +0x00e0 intuition/preferences.h: *120
PrintFlags       unsigned short int in struct Preferences
         +0x00da intuition/preferences.h: *117
PrintImage       unsigned short int in struct Preferences
         +0x00a8 intuition/preferences.h: *92
PrintLeftMargin unsigned short int in struct Preferences
         +0x00a4 intuition/preferences.h: *90
PrintMaxHeight   unsigned short int in struct Preferences
         +0x00de intuition/preferences.h: *119
PrintMaxWidth    unsigned short int in struct Preferences
         +0x00dc intuition/preferences.h: *118
PrintPitch       unsigned short int in struct Preferences
         +0x009e intuition/preferences.h: *87
PrintQuality     unsigned short int in struct Preferences
         +0x00a0 intuition/preferences.h: *88
PrintRightMargin unsigned short int in struct Preferences
         +0x00a6 intuition/preferences.h: *91
PrintShade       unsigned short int in struct Preferences
         +0x00ac intuition/preferences.h: *94
PrintSpacing     unsigned short int in struct Preferences
         +0x00a2 intuition/preferences.h: *89
PrintThreshold   short int in struct Preferences
         +0x00ae intuition/preferences.h: *95
PrintXOffset     unsigned char in struct Preferences
         +0x00e1 intuition/preferences.h: *121
PrinterData      structure tag (size 0x1aa2 bytes)in struct PrinterData
                 devices/prtbase.h: *65
PrinterExtendedData structure tag size 0x0042 devices/prtbase.h: *135, 167
PrinterFilename array [30] of unsigned char in struct Preferences
         +0x0080 intuition/preferences.h: *84
PrinterPort      unsigned char in struct Preferences
         +0x0001 intuition/preferences.h: *50
PrinterSegment   structure tag size 0x004e devices/prtbase.h: *71, 162
PrinterType      unsigned short int in struct Preferences
         +0x007e intuition/preferences.h: *83
Process          structure tag size 0x00e4 dos/dosextens.h: *39
PropInfo         structure tag size 0x0016 intuition/intuition.h: *452
PropertyFlags    unsigned long int in struct DisplayInfo
         +0x0012 graphics/displayinfo.h: *54
PrtInfo          structure tag size 0x0072 devices/prtgfx.h: *34
PtrHeight        char in struct Window +0x004e intuition/intuition.h: *850
PtrWidth         char in struct Window +0x004f intuition/intuition.h: *851
PubScreenNode    structure tag size 0x001d intuition/screens.h: *382


2.0 IncludeXREF: Q

QUME_LP_20       #define 0x0A = 0x0000000a  intuition/preferences.h: *202
Qualifier        unsigned short int in struct IntuiMessage
         +0x001a intuition/intuition.h: *690
Quantum          unsigned short int in struct ExecBase
         +0x0120 exec/execbase.h: *67
QueryHeader      structure tag
     size 0x0010 graphics/displayinfo.h: *42, 52, 94, 111, 134


2.0 IncludeXREF: R

ra_Buff          array [8] of char in struct RexxArg
         +0x0008 rexx/storage.h: *92
ra_Flags         unsigned char in struct RexxArg +0x0006 rexx/storage.h: *90
ra_Hash          unsigned char in struct RexxArg +0x0007 rexx/storage.h: *91
ra_Length        unsigned short int in struct RexxArg
         +0x0004 rexx/storage.h: *89
ra_Size          long int in struct RexxArg +0x0000 rexx/storage.h: *88
rate             unsigned short int in struct narrator_rb
         +0x0030 devices/narrator.h: *95
ratioh           long int in struct MonitorSpec +0x001a graphics/monitor.h: *31
ratiov           long int in struct MonitorSpec +0x001e graphics/monitor.h: *32
rdb_AutoParkSeconds unsigned long int in struct RigidDiskBlock
         +0x0094 devices/hardblocks.h: *80
rdb_BadBlockList unsigned long int in struct RigidDiskBlock
         +0x0018 devices/hardblocks.h: *57
rdb_BlockBytes   unsigned long int in struct RigidDiskBlock
         +0x0010 devices/hardblocks.h: *54
rdb_ChkSum       long int in struct RigidDiskBlock
         +0x0008 devices/hardblocks.h: *52
rdb_ControllerProduct array [16] of char in struct RigidDiskBlock
         +0x00c4 devices/hardblocks.h: *87
rdb_ControllerRevision array [4] of char in struct RigidDiskBlock
         +0x00d4 devices/hardblocks.h: *88
rdb_ControllerVendor array [8] of char in struct RigidDiskBlock
         +0x00bc devices/hardblocks.h: *86
rdb_CylBlocks    unsigned long int in struct RigidDiskBlock
         +0x0090 devices/hardblocks.h: *79
rdb_Cylinders    unsigned long int in struct RigidDiskBlock
         +0x0040 devices/hardblocks.h: *64
rdb_DiskProduct array [16] of char in struct RigidDiskBlock
         +0x00a8 devices/hardblocks.h: *83
rdb_DiskRevision array [4] of char in struct RigidDiskBlock
         +0x00b8 devices/hardblocks.h: *85
rdb_DiskVendor   array [8] of char in struct RigidDiskBlock
         +0x00a0 devices/hardblocks.h: *83
rdb_DriveInit    unsigned long int in struct RigidDiskBlock
         +0x0024 devices/hardblocks.h: *60
rdb_FileSysHeaderList unsigned long int in struct RigidDiskBlock
         +0x0020 devices/hardblocks.h: *59
rdb_Flags        unsigned long int in struct RigidDiskBlock
         +0x0014 devices/hardblocks.h: *55
rdb_Heads        unsigned long int in struct RigidDiskBlock
         +0x0048 devices/hardblocks.h: *66
rdb_HiCylinder   unsigned long int in struct RigidDiskBlock
         +0x008c devices/hardblocks.h: *78
rdb_HostID       unsigned long int in struct RigidDiskBlock
         +0x000c devices/hardblocks.h: *53
rdb_ID           unsigned long int in struct RigidDiskBlock
         +0x0000 devices/hardblocks.h: *50
rdb_Interleave   unsigned long int in struct RigidDiskBlock
         +0x004c devices/hardblocks.h: *67
rdb_LoCylinder   unsigned long int in struct RigidDiskBlock
         +0x0088 devices/hardblocks.h: *77
rdb_Park         unsigned long int in struct RigidDiskBlock
         +0x0050 devices/hardblocks.h: *68
rdb_PartitionList unsigned long int in struct RigidDiskBlock
         +0x001c devices/hardblocks.h: *58
rdb_RDBBlocksHi unsigned long int in struct RigidDiskBlock
         +0x0084 devices/hardblocks.h: *76
rdb_RDBBlocksLo unsigned long int in struct RigidDiskBlock
         +0x0080 devices/hardblocks.h: *75
rdb_ReducedWrite unsigned long int in struct RigidDiskBlock
         +0x0064 devices/hardblocks.h: *71
rdb_Reserved1    array [6] of unsigned long int in struct RigidDiskBlock
         +0x0028 devices/hardblocks.h: *62
rdb_Reserved2    array [3] of unsigned long int in struct RigidDiskBlock
         +0x0054 devices/hardblocks.h: *69
rdb_Reserved3    array [5] of unsigned long int in struct RigidDiskBlock
         +0x006c devices/hardblocks.h: *73
rdb_Reserved4    array [2] of unsigned long int in struct RigidDiskBlock
         +0x0098 devices/hardblocks.h: *81
rdb_Reserved5    array [10] of unsigned long int in struct RigidDiskBlock
         +0x00d8 devices/hardblocks.h: *89
rdb_Sectors      unsigned long int in struct RigidDiskBlock
         +0x0044 devices/hardblocks.h: *65
rdb_StepRate     unsigned long int in struct RigidDiskBlock
         +0x0068 devices/hardblocks.h: *72
rdb_SummedLongs unsigned long int in struct RigidDiskBlock
         +0x0004 devices/hardblocks.h: *51
rdb_WritePreComp unsigned long int in struct RigidDiskBlock
         +0x0060 devices/hardblocks.h: *70
rec_FH           long int in struct RecordLock +0x0000 dos/record.h: *30
rec_Length       unsigned long int in struct RecordLock
         +0x0008 dos/record.h: *32
rec_Mode         unsigned long int in struct RecordLock
         +0x000c dos/record.h: *33
rec_Offset       unsigned long int in struct RecordLock
         +0x0004 dos/record.h: *31
refptr           unsigned short int in struct Custom
         +0x0028 hardware/custom.h: *47
reserved         array [4] of unsigned char in struct Layer
         +0x0018 graphics/clip.h: *40
reserved         long int in struct ClipRect +0x0020 graphics/clip.h: *72
reserved         array [8] of unsigned char in struct RastPort
         +0x005c graphics/rastport.h: *89
reserved         array [2] of unsigned long int in struct DisplayInfo
         +0x0028 graphics/displayinfo.h: *61
reserved         array [2] of unsigned long int in struct DimensionInfo
         +0x0050 graphics/displayinfo.h: *106
reserved         array [2] of unsigned long int in struct MonitorInfo
         +0x0050 graphics/displayinfo.h: *121
reserved         array [2] of unsigned long int in struct NameInfo
         +0x0030 graphics/displayinfo.h: *136
reserved1        unsigned long int in struct Layer +0x007a graphics/clip.h: *54
reserved1        pointer to function returning int in struct SpecialMonitor
         +0x001e graphics/monitor.h: *147
reserved1        unsigned char in struct ColorMap +0x0011 graphics/view.h: *123
reserved2        array [18] of unsigned char in struct Layer
         +0x008a graphics/clip.h: *58
reserved2        pointer to function returning int in struct SpecialMonitor
         +0x0022 graphics/monitor.h: *148
reserved2        unsigned short int in struct ColorMap
         +0x0012 graphics/view.h: *124
reserved3        pointer to function returning int in struct SpecialMonitor
         +0x0026 graphics/monitor.h: *149
rf_ArgList       pointer to struct WBArg in struct FileRequester
         +0x0024 libraries/asl.h: *77
rf_Dir           pointer to char in struct FileRequester
         +0x0008 libraries/asl.h: *68
rf_File          pointer to char in struct FileRequester
         +0x0004 libraries/asl.h: *67
rf_Height        short int in struct FileRequester +0x001c libraries/asl.h: *74
rf_LeftEdge      short int in struct FileRequester +0x0016 libraries/asl.h: *73
rf_NumArgs       long int in struct FileRequester +0x0020 libraries/asl.h: *76
rf_Pat           pointer to char in struct FileRequester
         +0x0034 libraries/asl.h: *81
rf_Reserved1     pointer to void in struct FileRequester
         +0x0000 libraries/asl.h: *66
rf_Reserved2     unsigned long int in struct FileRequester
         +0x000c libraries/asl.h: *69
rf_Reserved3     unsigned char in struct FileRequester
         +0x0010 libraries/asl.h: *70
rf_Reserved4     unsigned char in struct FileRequester
         +0x0011 libraries/asl.h: *71
rf_Reserved5     pointer to void in struct FileRequester
         +0x0012 libraries/asl.h: *72
rf_Reserved6     short int in struct FileRequester +0x001e libraries/asl.h: *75
rf_Reserved7     pointer to void in struct FileRequester
         +0x002c libraries/asl.h: *79
rf_Reserved8     pointer to void in struct FileRequester
         +0x0030 libraries/asl.h: *80
rf_TopEdge       short int in struct FileRequester +0x0018 libraries/asl.h: *73
rf_UserData      pointer to void in struct FileRequester
         +0x0028 libraries/asl.h: *78
rf_Width         short int in struct FileRequester +0x001a libraries/asl.h: *74
rightmost        short int in struct GelsInfo +0x0018 graphics/rastport.h: *52
rl_COMMAND       pointer to struct NexxStr in struct RxsLib
         +0x0050 rexx/rxslib.h: *41
rl_CTABLE        pointer to unsigned char in struct RxsLib
         +0x0078 rexx/rxslib.h: *52
rl_Chunk         long int in struct RxsLib +0x0038 rexx/rxslib.h: *35
rl_ClipList      struct List(size 0x000e bytes) in struct RxsLib
         +0x00c8 rexx/rxslib.h: *62
rl_DOSBase       pointer to void in struct RxsLib +0x0028 rexx/rxslib.h: *31
rl_FALSE         pointer to struct NexxStr in struct RxsLib
         +0x0044 rexx/rxslib.h: *38
rl_Flags         unsigned char in struct RxsLib +0x0022 rexx/rxslib.h: *28
rl_IeeeDPBase    pointer to void in struct RxsLib +0x002c rexx/rxslib.h: *32
rl_LibList       struct List(size 0x000e bytes) in struct RxsLib
         +0x00b8 rexx/rxslib.h: *60
rl_MaxNest       long int in struct RxsLib +0x003c rexx/rxslib.h: *36
rl_MsgList       struct List(size 0x000e bytes) in struct RxsLib
         +0x00d8 rexx/rxslib.h: *64
rl_NIL           long int in struct RxsLib +0x0034 rexx/rxslib.h: *34
rl_NULL          pointer to struct NexxStr in struct RxsLib
         +0x0040 rexx/rxslib.h: *37
rl_Node          struct Library(size 0x0022 bytes) in struct RxsLib
         +0x0000 rexx/rxslib.h: *27
rl_Notice        pointer to unsigned char in struct RxsLib
         +0x007c rexx/rxslib.h: *53
rl_NumClip       short int in struct RxsLib +0x00d6 rexx/rxslib.h: *63
rl_NumLib        short int in struct RxsLib +0x00c6 rexx/rxslib.h: *61
rl_NumMsg        short int in struct RxsLib +0x00e6 rexx/rxslib.h: *65
rl_NumPgm        short int in struct RxsLib +0x00f6 rexx/rxslib.h: *67
rl_NumTask       short int in struct RxsLib +0x00b6 rexx/rxslib.h: *59
rl_PgmList       struct List(size 0x000e bytes) in struct RxsLib
         +0x00e8 rexx/rxslib.h: *66
rl_REXX          pointer to struct NexxStr in struct RxsLib
         +0x004c rexx/rxslib.h: *40
rl_ReadLock      unsigned short int in struct RxsLib +0x00a2 rexx/rxslib.h: *56
rl_RexxDir       pointer to unsigned char in struct RxsLib
         +0x0074 rexx/rxslib.h: *51
rl_RexxPort      struct MsgPort(size 0x0022 bytes) in struct RxsLib
         +0x0080 rexx/rxslib.h: *55
rl_STDERR        pointer to struct NexxStr in struct RxsLib
         +0x005c rexx/rxslib.h: *44
rl_STDIN         pointer to struct NexxStr in struct RxsLib
         +0x0054 rexx/rxslib.h: *42
rl_STDOUT        pointer to struct NexxStr in struct RxsLib
         +0x0058 rexx/rxslib.h: *43
rl_SegList       long int in struct RxsLib +0x0030 rexx/rxslib.h: *33
rl_Shadow        unsigned char in struct RxsLib +0x0023 rexx/rxslib.h: *29
rl_StackSize     long int in struct RxsLib +0x0070 rexx/rxslib.h: *50
rl_SysBase       pointer to void in struct RxsLib +0x0024 rexx/rxslib.h: *30
rl_TRUE          pointer to struct NexxStr in struct RxsLib
         +0x0048 rexx/rxslib.h: *39
rl_TaskList      struct List(size 0x000e bytes) in struct RxsLib
         +0x00a8 rexx/rxslib.h: *58
rl_TaskName      pointer to unsigned char in struct RxsLib
         +0x0064 rexx/rxslib.h: *47
rl_TaskPri       long int in struct RxsLib +0x0068 rexx/rxslib.h: *48
rl_TaskSeg       long int in struct RxsLib +0x006c rexx/rxslib.h: *49
rl_TraceCnt      unsigned short int in struct RxsLib +0x00f8 rexx/rxslib.h: *69
rl_TraceFH       long int in struct RxsLib +0x00a4 rexx/rxslib.h: *57
rl_Version       pointer to unsigned char in struct RxsLib
         +0x0060 rexx/rxslib.h: *45
rl_avail         short int in struct RxsLib +0x00fa rexx/rxslib.h: *70
rm_Action        long int in struct RexxMsg +0x001c rexx/storage.h: *103
rm_Args          array [16] of pointer to unsigned char in struct RexxMsg
         +0x0028 rexx/storage.h: *106
rm_CommAddr      pointer to unsigned char in struct RexxMsg
         +0x006c rexx/storage.h: *109
rm_FileExt       pointer to unsigned char in struct RexxMsg
         +0x0070 rexx/storage.h: *110
rm_LibBase       pointer to void in struct RexxMsg +0x0018 rexx/storage.h: *102
rm_Node          struct Message(size 0x0014 bytes) in struct RexxMsg
         +0x0000 rexx/storage.h: *100
rm_PassPort      pointer to struct MsgPort in struct RexxMsg
         +0x0068 rexx/storage.h: *108
rm_Result1       long int in struct RexxMsg +0x0020 rexx/storage.h: *104
rm_Result2       long int in struct RexxMsg +0x0024 rexx/storage.h: *105
rm_Stdin         long int in struct RexxMsg +0x0074 rexx/storage.h: *111
rm_Stdout        long int in struct RexxMsg +0x0078 rexx/storage.h: *112
rm_TaskBlock     pointer to void in struct RexxMsg +0x0014 rexx/storage.h: *101
rm_avail         long int in struct RexxMsg +0x007c rexx/storage.h: *113
rmp_Node         struct RexxRsrc(size 0x0020 bytes) in struct RexxMsgPort
         +0x0000 rexx/rexxio.h: *65
rmp_Port         struct MsgPort(size 0x0022 bytes) in struct RexxMsgPort
         +0x0020 rexx/rexxio.h: *66
rmp_ReplyList    struct List(size 0x000e bytes) in struct RexxMsgPort
         +0x0042 rexx/rexxio.h: *67
rn_BootProc      pointer to struct MsgPort in struct RootNode
         +0x002c dos/dosextens.h: *253
rn_CliList       struct MinList(size 0x000c bytes) in struct RootNode
         +0x0020 dos/dosextens.h: *251
rn_ConsoleSegment long int in struct RootNode +0x0004 dos/dosextens.h: *246
rn_FileHandlerSegment long int in struct RootNode +0x001c dos/dosextens.h: *250
rn_Flags         long int in struct RootNode +0x0034 dos/dosextens.h: *255
rn_Info          long int in struct RootNode +0x0018 dos/dosextens.h: *249
rn_RestartSeg    long int in struct RootNode +0x0014 dos/dosextens.h: *248
rn_ShellSegment long int in struct RootNode +0x0030 dos/dosextens.h: *254
rn_TaskArray     long int in struct RootNode +0x0000 dos/dosextens.h: *243
rn_Time          struct DateStamp(size 0x000c bytes) in struct RootNode
         +0x0008 dos/dosextens.h: *247
round            macro (1 argument)   libraries/mathffp.h: *32
                 libraries/mathieeedp.h: *32
rp               pointer to struct RastPort in struct Layer
         +0x000c graphics/clip.h: *38
rr_Arg1          long int in struct RexxRsrc +0x0018 rexx/storage.h: *167
rr_Arg2          long int in struct RexxRsrc +0x001c rexx/storage.h: *168
rr_Base          pointer to void in struct RexxRsrc
         +0x0010 rexx/storage.h: *165
rr_Func          short int in struct RexxRsrc +0x000e rexx/storage.h: *164
rr_Node          struct Node(size 0x000e bytes) in struct RexxRsrc
         +0x0000 rexx/storage.h: *163
rr_Size          long int in struct RexxRsrc +0x0014 rexx/storage.h: *166
rt_ClientID      pointer to void in struct RexxTask
         +0x00ec rexx/storage.h: *193
rt_EndSkip       pointer to void in struct Resident
         +0x0006 exec/resident.h: *23
rt_ErrTrap       pointer to void in struct RexxTask
         +0x00fc rexx/storage.h: *198
rt_Flags         unsigned char in struct Resident +0x000a exec/resident.h: *24
rt_Flags         unsigned char in struct RexxTask +0x00ea rexx/storage.h: *190
rt_Global        array [200] of char in struct RexxTask
         +0x0000 rexx/storage.h: *188
rt_Header1       struct List(size 0x000e bytes) in struct RexxTask
         +0x0104 rexx/storage.h: *201
rt_Header2       struct List(size 0x000e bytes) in struct RexxTask
         +0x0112 rexx/storage.h: *202
rt_Header3       struct List(size 0x000e bytes) in struct RexxTask
         +0x0120 rexx/storage.h: *203
rt_Header4       struct List(size 0x000e bytes) in struct RexxTask
         +0x012e rexx/storage.h: *204
rt_Header5       struct List(size 0x000e bytes) in struct RexxTask
         +0x013c rexx/storage.h: *205
rt_IdString      pointer to char in struct Resident
         +0x0012 exec/resident.h: *29
rt_Init          pointer to void in struct Resident
         +0x0016 exec/resident.h: *30
rt_MatchTag      pointer to struct Resident in struct Resident
         +0x0002 exec/resident.h: *22
rt_MatchWord     unsigned short int in struct Resident
         +0x0000 exec/resident.h: *21
rt_MsgPkt        pointer to void in struct RexxTask
         +0x00f0 rexx/storage.h: *194
rt_MsgPort       struct MsgPort(size 0x0022 bytes) in struct RexxTask
         +0x00c8 rexx/storage.h: *189
rt_Name          pointer to char in struct Resident
         +0x000e exec/resident.h: *28
rt_Pri           char in struct Resident +0x000d exec/resident.h: *27
rt_RexxPort      pointer to void in struct RexxTask
         +0x00f8 rexx/storage.h: *196
rt_SigBit        char in struct RexxTask +0x00eb rexx/storage.h: *191
rt_StackPtr      pointer to void in struct RexxTask
         +0x0100 rexx/storage.h: *199
rt_TaskID        pointer to void in struct RexxTask
         +0x00f4 rexx/storage.h: *195
rt_Type          unsigned char in struct Resident +0x000c exec/resident.h: *26
rt_Version       unsigned char in struct Resident +0x000b exec/resident.h: *25
RASSIZE          macro (2 arguments)   graphics/gfx.h: *58
RATIO_FIXEDPART  #define 4 = 0x00000004  graphics/monitor.h: *133
RATIO_UNITY      #define (1 << RATIO_FIXEDPART) = 0x00000010
                 graphics/monitor.h: *134
RAWKEY           #define IDCMP_RAWKEY = 0x00000400
                 intuition/iobsolete.h: *124
RC_ERROR         #define 10L = 0x0000000a  rexx/errors.h: *74
RC_FATAL         #define 20L = 0x00000014  rexx/errors.h: *75
RC_OK            #define 0L = 0x00000000  rexx/errors.h: *72
RC_WARN          #define 5L = 0x00000005  rexx/errors.h: *73
RDAB_NOALLOC     #define 1 = 0x00000001  dos/rdargs.h: *108
RDAB_NOPROMPT    #define 2 = 0x00000002  dos/rdargs.h: *110
RDAB_STDIN       #define 0 = 0x00000000  dos/rdargs.h: *106
RDAF_NOALLOC     #define 2 = 0x00000002  dos/rdargs.h: *109
RDAF_NOPROMPT    #define 4 = 0x00000004  dos/rdargs.h: *111
RDAF_STDIN       #define 1 = 0x00000001  dos/rdargs.h: *107
RDA_BufSiz       long int in struct RDArgs +0x0014 dos/rdargs.h: *101
RDA_Buffer       pointer to unsigned char in struct RDArgs
         +0x0010 dos/rdargs.h: *100
RDA_DAList       long int in struct RDArgs +0x000c dos/rdargs.h: *99
RDA_ExtHelp      pointer to unsigned char in struct RDArgs
         +0x0018 dos/rdargs.h: *102
RDA_Flags        long int in struct RDArgs +0x001c dos/rdargs.h: *103
RDA_Source       struct CSource(size 0x000c bytes) in struct RDArgs
         +0x0000 dos/rdargs.h: *98
RDArgs           structure tag size 0x0020 dos/rdargs.h: *97
RDBFB_CTRLRID    #define 5 = 0x00000005  devices/hardblocks.h: *106
RDBFB_DISKID     #define 4 = 0x00000004  devices/hardblocks.h: *104
RDBFB_LAST       #define 0 = 0x00000000  devices/hardblocks.h: *96
RDBFB_LASTLUN    #define 1 = 0x00000001  devices/hardblocks.h: *98
RDBFB_LASTTID    #define 2 = 0x00000002  devices/hardblocks.h: *100
RDBFB_NORESELECT #define 3 = 0x00000003  devices/hardblocks.h: *102
RDBFF_CTRLRID    #define 0x20L = 0x00000020  devices/hardblocks.h: *106
RDBFF_DISKID     #define 0x10L = 0x00000010  devices/hardblocks.h: *104
RDBFF_LAST       #define 0x01L = 0x00000001  devices/hardblocks.h: *96
RDBFF_LASTLUN    #define 0x02L = 0x00000002  devices/hardblocks.h: *98
RDBFF_LASTTID    #define 0x04L = 0x00000004  devices/hardblocks.h: *99
RDBFF_NORESELECT #define 0x08L = 0x00000008  devices/hardblocks.h: *106
RDB_LOCATION_LIMIT #define 16 = 0x00000010  devices/hardblocks.h: *93
RECOVERY_ALERT   #define 0x00000000 = 0x00000000  intuition/intuition.h: *1311
REC_EXCLUSIVE    #define 0 = 0x00000000  dos/record.h: *22
REC_EXCLUSIVE_IMMED #define 1 = 0x00000001  dos/record.h: *23
REC_SHARED       #define 2 = 0x00000002  dos/record.h: *24
REC_SHARED_IMMED #define 3 = 0x00000003  dos/record.h: *25
REFRESHBITS      #define WFLG_REFRESHBITS = 0x000000c0
                 intuition/iobsolete.h: *151
REFRESHWINDOW    #define IDCMP_REFRESHWINDOW = 0x00000004
                 intuition/iobsolete.h: *116
REGISTER         #define register  exec/types.h: *23
RELVERIFY        #define GACT_RELVERIFY = 0x00000001
                 intuition/iobsolete.h: *69
REPORTMOUSE      #define WFLG_REPORTMOUSE = 0x00000200
                 intuition/iobsolete.h: *157
REPORT_INSERT    #define 4 = 0x00000004  dos/dosextens.h: *456
REPORT_LOCK      #define 2 = 0x00000002  dos/dosextens.h: *454
REPORT_STREAM    #define 0 = 0x00000000  dos/dosextens.h: *452
REPORT_TASK      #define 1 = 0x00000001  dos/dosextens.h: *453
REPORT_VOLUME    #define 3 = 0x00000003  dos/dosextens.h: *455
REQACTIVE        #define 0x2000 = 0x00002000  intuition/intuition.h: *204
REQCLEAR         #define IDCMP_REQCLEAR = 0x00001000
                 intuition/iobsolete.h: *126
REQGADGET        #define GTYP_REQGADGET = 0x00001000
                 intuition/iobsolete.h: *95
REQOFFWINDOW     #define 0x1000 = 0x00001000  intuition/intuition.h: *203
REQSET           #define IDCMP_REQSET = 0x00000080
                 intuition/iobsolete.h: *121
REQUEST_A2024    #define 8 = 0x00000008  graphics/monitor.h: *63
REQUEST_NTSC     #define 1 = 0x00000001  graphics/monitor.h: *60
REQUEST_PAL      #define 2 = 0x00000002  graphics/monitor.h: *61
REQUEST_SPECIAL  #define 4 = 0x00000004  graphics/monitor.h: *62
REQVERIFY        #define IDCMP_REQVERIFY = 0x00000800
                 intuition/iobsolete.h: *125
RESCOUNT         #define 2 = 0x00000002  intuition/intuitionbase.h: *42
RESOURCES_BATTCLOCK_H #define 1 = 0x00000001  resources/battclock.h: *2
RESOURCES_BATTMEMBITSAMIGA_H #define 1 = 0x00000001
                 resources/battmembitsamiga.h: *2
RESOURCES_BATTMEMBITSAMIX_H #define 1 = 0x00000001
                 resources/battmembitsamix.h: *2
RESOURCES_BATTMEMBITSSHARED_H #define 1 = 0x00000001
                 resources/battmembitsshared.h: *2
RESOURCES_BATTMEM_H #define 1 = 0x00000001  resources/battmem.h: *2
RESOURCES_CIA_H  #define  resources/ciabase.h: *2
RESOURCES_DISK_H #define  resources/disk.h: *2
RESOURCES_FILESYSRES_H #define  resources/filesysres.h: *2
RESOURCES_MATHRESOURCE_H #define  libraries/mathresource.h: *2
                 resources/mathresource.h: 1
RESOURCES_MISC_H #define  resources/misc.h: *2
RESOURCES_POTGO_H #define  resources/potgo.h: *2
RETURN_ERROR     #define 10 = 0x0000000a  dos/dos.h: *200
RETURN_FAIL      #define 20 = 0x00000014  dos/dos.h: *201
RETURN_OK        #define 0 = 0x00000000  dos/dos.h: *198
RETURN_WARN      #define 5 = 0x00000005  dos/dos.h: *199
REXX_ERRORS_H    #define  rexx/errors.h: *2
REXX_REXXIO_H    #define  rexx/rexxio.h: *2
REXX_RXSLIB_H    #define  rexx/rxslib.h: *2
REXX_STORAGE_H   #define  rexx/storage.h: *2, 1
                 rexx/rxslib.h: 15
RIGHTBORDER      #define GACT_RIGHTBORDER = 0x00000010
                 intuition/iobsolete.h: *73
RIGHTHIT         #define 8 = 0x00000008  graphics/collide.h: *35
RIGHTIMAGE       #define (0x0CL) = 0x0000000c  intuition/imageclass.h: *108
RINGTRIGGER      #define 0x0001 = 0x00000001  graphics/gels.h: *48
RI_VERSION       #define (1) = 0x00000001  intuition/screens.h: *58
RLFB_CLOSE       #define 7 = 0x00000007  rexx/rxslib.h: *78
RLFB_HALT        #define RTFB_HALT = 0x00000001  rexx/rxslib.h: *75
RLFB_STOP        #define 6 = 0x00000006  rexx/rxslib.h: *77
RLFB_SUSP        #define RTFB_SUSP = 0x00000002  rexx/rxslib.h: *76
RLFB_TRACE       #define RTFB_TRACE = 0x00000000  rexx/rxslib.h: *74
RLFMASK          #define (1<<RLFB_TRACE) | (1<<RLFB_HALT) | (1<<RLFB_SUSP) =
                 0x00000007
                 rexx/rxslib.h: *80
RMBTRAP          #define WFLG_RMBTRAP = 0x00010000
                 intuition/iobsolete.h: *164
RNB_PRIVATE1     #define 1 = 0x00000001  dos/dosextens.h: *260
RNB_WILDSTAR     #define 24 = 0x00000018  dos/dosextens.h: *258
RNF_PRIVATE1     #define 2 = 0x00000002  dos/dosextens.h: *261
RNF_WILDSTAR     #define (1L<<24) = 0x01000000  dos/dosextens.h: *259
ROBOTICF0        #define 1 = 0x00000001  devices/narrator.h: *66
ROOTCLASS        #define "rootclass"  intuition/classusr.h: *42
RPTR             short int  exec/types.h: *51
RP_User          pointer to pointer to void in struct RastPort
         +0x0042 graphics/rastport.h: *85
RPort            pointer to struct RastPort in struct Window
         +0x0032 intuition/intuition.h: *820
RRT_ANY          #define 0 = 0x00000000  rexx/storage.h: *172
RRT_CLIP         #define 5 = 0x00000005  rexx/storage.h: *177
RRT_FILE         #define 3 = 0x00000003  rexx/storage.h: *175
RRT_HOST         #define 4 = 0x00000004  rexx/storage.h: *176
RRT_LIB          #define 1 = 0x00000001  rexx/storage.h: *173
RRT_PORT         #define 2 = 0x00000002  rexx/storage.h: *174
RTC_MATCHWORD    #define 0x4AFC = 0x00004afc  exec/resident.h: *33
RTFB_CLOSE       #define 7 = 0x00000007  rexx/storage.h: *214
RTFB_HALT        #define 1 = 0x00000001  rexx/storage.h: *210
RTFB_SUSP        #define 2 = 0x00000002  rexx/storage.h: *211
RTFB_TCUSE       #define 3 = 0x00000003  rexx/storage.h: *212
RTFB_TRACE       #define 0 = 0x00000000  rexx/storage.h: *209
RTFB_WAIT        #define 6 = 0x00000006  rexx/storage.h: *213
RTF_AFTERDOS     #define (1<<2) = 0x00000004  exec/resident.h: *36
RTF_AUTOINIT     #define (1<<7) = 0x00000080  exec/resident.h: *35
RTF_COLDSTART    #define (1<<0) = 0x00000001  exec/resident.h: *38
RTF_SINGLETASK   #define (1<<1) = 0x00000002  exec/resident.h: *37
RTW_COLDSTART    #define 1 = 0x00000001  exec/resident.h: *43
RTW_NEVER        #define 0 = 0x00000000  exec/resident.h: *42
RUN_EXECUTE      #define -1 = 0xffffffff  dos/dosextens.h: *464
RUN_SYSTEM       #define -2 = 0xfffffffe  dos/dosextens.h: *465
RUN_SYSTEM_ASYNCH #define -3 = 0xfffffffd  dos/dosextens.h: *466
RWindow          pointer to struct Window in struct Requester
         +0x0048 intuition/intuition.h: *172
RXADDCON         #define 0x0A000000 = 0x0a000000  rexx/storage.h: *131
RXADDFH          #define 0x07000000 = 0x07000000  rexx/storage.h: *128
RXADDLIB         #define 0x08000000 = 0x08000000  rexx/storage.h: *129
RXARGMASK        #define 0x0000000F = 0x0000000f  rexx/storage.h: *151
RXBUFFSZ         #define 204 = 0x000000cc  rexx/rexxio.h: *19, 32
RXCLOSE          #define 0x03000000 = 0x03000000  rexx/storage.h: *126
RXCODEMASK       #define 0xFF000000 = 0xff000000  rexx/storage.h: *150
RXCOMM           #define 0x01000000 = 0x01000000  rexx/storage.h: *124
RXFB_NOIO        #define 16 = 0x00000010  rexx/storage.h: *137
RXFB_NONRET      #define 20 = 0x00000014  rexx/storage.h: *141
RXFB_RESULT      #define 17 = 0x00000011  rexx/storage.h: *138
RXFB_STRING      #define 18 = 0x00000012  rexx/storage.h: *139
RXFB_TOKEN       #define 19 = 0x00000013  rexx/storage.h: *140
RXFF_NOIO        #define (1L << RXFB_NOIO ) = 0x00010000  rexx/storage.h: *144
RXFF_NONRET      #define (1L << RXFB_NONRET) = 0x00100000
                 rexx/storage.h: *148
RXFF_RESULT      #define (1L << RXFB_RESULT) = 0x00020000
                 rexx/storage.h: *145
RXFF_STRING      #define (1L << RXFB_STRING) = 0x00040000
                 rexx/storage.h: *146
RXFF_TOKEN       #define (1L << RXFB_TOKEN ) = 0x00080000
                 rexx/storage.h: *147
RXFUNC           #define 0x02000000 = 0x02000000  rexx/storage.h: *125
RXIO_APPEND      #define 3 = 0x00000003  rexx/rexxio.h: *40
RXIO_BEGIN       #define -1L = 0xffffffff  rexx/rexxio.h: *45
RXIO_CURR        #define 0L = 0x00000000  rexx/rexxio.h: *46
RXIO_END         #define 1L = 0x00000001  rexx/rexxio.h: *47
RXIO_EXIST       #define -1 = 0xffffffff  rexx/rexxio.h: *36
RXIO_READ        #define 1 = 0x00000001  rexx/rexxio.h: *38
RXIO_STRF        #define 0 = 0x00000000  rexx/rexxio.h: *37
RXIO_WRITE       #define 2 = 0x00000002  rexx/rexxio.h: *39
RXQUERY          #define 0x04000000 = 0x04000000  rexx/storage.h: *127
RXREMCON         #define 0x0B000000 = 0x0b000000  rexx/storage.h: *132
RXREMLIB         #define 0x09000000 = 0x09000000  rexx/storage.h: *130
RXSCHUNK         #define 1024 = 0x00000400  rexx/rxslib.h: *83
RXSDIR           #define "REXX"  rexx/rxslib.h: *20
RXSNAME          #define "rexxsyslib.library"  rexx/rxslib.h: *19
RXSNEST          #define 32 = 0x00000020  rexx/rxslib.h: *84
RXSSTACK         #define 4096 = 0x00001000  rexx/rxslib.h: *86
RXSTNAME         #define "ARexx"  rexx/rxslib.h: *21
RXSTPRI          #define 0 = 0x00000000  rexx/rxslib.h: *85
RXTCCLS          #define 0x0D000000 = 0x0d000000  rexx/storage.h: *134
RXTCOPN          #define 0x0C000000 = 0x0c000000  rexx/storage.h: *133
RasInfo          structure tag size 0x000c graphics/view.h: *55, 107, 109
RasInfo          pointer to struct RasInfo in struct ViewPort
         +0x0024 graphics/view.h: *55
RasPtr           pointer to char in struct TmpRas
         +0x0000 graphics/rastport.h: *36
RastPort         structure tag (size 0x0064 bytes)in struct impErase
                 devices/prtgfx.h: *36, 37
                 devices/printer.h: 163
                 graphics/clip.h: 38
                 graphics/rastport.h: 56
                 intuition/intuition.h: 820, 833
                 intuition/screens.h: 128
                 intuition/cghooks.h: 37
                 intuition/gadgetclass.h: 191
                 intuition/imageclass.h: 154, 174
RastPort         struct RastPort(size 0x0064 bytes) in struct Screen
         +0x0054 intuition/screens.h: *128
ReadChar         #define FGetC(Input())  dos/stdio.h: *17
ReadChars        macro (2 arguments)   dos/stdio.h: *21
ReadLn           macro (2 arguments)   dos/stdio.h: *22
RecordLock       structure tag size 0x0010 dos/record.h: *29
Rect32           structure tag size 0x0010 graphics/gfx.h: *35
Rectangle        structure tag size 0x0008 graphics/gfx.h: *29
                 graphics/clip.h: 39, 70
                 graphics/monitor.h: 45
                 graphics/view.h: 83
                 graphics/text.h: 169
                 graphics/displayinfo.h: 100, 101, 102, 103, 104,
                             115
                 graphics/regions.h: 26, 31
Red              unsigned short int in struct ColorSpec
         +0x0002 intuition/intuition.h: *1243
Region           structure tag size 0x000c graphics/clip.h: *55, 56, 60
                 graphics/regions.h: 29
RegionRectangle structure tag size 0x0010 graphics/regions.h: *23, 25, 32
RegionRectangle pointer to struct RegionRectangle in struct Region
         +0x0008 graphics/regions.h: *32
RelLeft          short int in struct Requester
         +0x000c intuition/intuition.h: *151
RelTop           short int in struct Requester
         +0x000e intuition/intuition.h: *151
RemBob           macro (1 argument)   graphics/gels.h: *247
Remember         structure tag size 0x000c intuition/intuition.h: *1231, 1233
RememberSize     unsigned long int in struct Remember
         +0x0004 intuition/intuition.h: *1234
ReqBorder        pointer to struct Border in struct Requester
         +0x0014 intuition/intuition.h: *154
ReqCount         short int in struct Window +0x002c intuition/intuition.h: *817
ReqGadget        pointer to struct Gadget in struct Requester
         +0x0010 intuition/intuition.h: *153
ReqImage         pointer to struct Image in struct Requester
         +0x004c intuition/intuition.h: *174
ReqLayer         pointer to struct Layer in struct Requester
         +0x0020 intuition/intuition.h: *161
ReqPad1          array [32] of unsigned char in struct Requester
         +0x0024 intuition/intuition.h: *163
ReqPad2          array [32] of unsigned char in struct Requester
         +0x0050 intuition/intuition.h: *176
ReqText          pointer to struct IntuiText in struct Requester
         +0x0018 intuition/intuition.h: *155
Requester        structure tag
     size 0x0070 intuition/intuition.h: *146, 148, 813, 815
                 intuition/cghooks.h: 31
ResModules       pointer to void in struct ExecBase
         +0x012c exec/execbase.h: *76
Reserved         unsigned long int in struct BoolInfo
         +0x0006 intuition/intuition.h: *437
Reserved         array [4] of unsigned long int in struct StringExtend
         +0x0014 intuition/sghooks.h: *30
Resident         structure tag size 0x001a exec/resident.h: *20, 22
Resolution       struct tPoint(size 0x0004 bytes) in struct DisplayInfo
         +0x0016 graphics/displayinfo.h: *55
ResourceList     struct List(size 0x000e bytes) in struct ExecBase
         +0x0150 exec/execbase.h: *87
RexxArg          structure tag size 0x0010 rexx/storage.h: *87
RexxMsg          structure tag size 0x0080 rexx/storage.h: *99
RexxMsgPort      structure tag size 0x0050 rexx/rexxio.h: *64
RexxRsrc         structure tag size 0x0020 rexx/storage.h: *162
                 rexx/rexxio.h: 26, 65
RexxTask         structure tag size 0x014a rexx/storage.h: *187
RigidDiskBlock   structure tag size 0x0100 devices/hardblocks.h: *49
RingXTrans       short int in struct AnimOb +0x001e graphics/gels.h: *217
RingYTrans       short int in struct AnimOb +0x001c graphics/gels.h: *217
RootNode         structure tag size 0x0038 dos/dosextens.h: *230, 242
RowSizeChange    char in struct Preferences
         +0x00d8 intuition/preferences.h: *114
Rows             unsigned short int in struct BitMap
         +0x0002 graphics/gfx.h: *51
RxOffset         short int in struct RasInfo +0x0008 graphics/view.h: *111
RxsLib           structure tag size 0x00fc rexx/rxslib.h: *26
RyOffset         short int in struct RasInfo +0x000a graphics/view.h: *111


2.0 IncludeXREF: S

__STDC__         #define 1 = 0x00000001  exec/types.h: 44
sampfreq         unsigned short int in struct narrator_rb
         +0x0040 devices/narrator.h: *102
saveClipRects    pointer to struct Region in struct Layer
         +0x0082 graphics/clip.h: *56
sc_Buf           pointer to void in struct IFFStreamCmd
         +0x0004 libraries/iffparse.h: *58
sc_Command       long int in struct IFFStreamCmd
         +0x0000 libraries/iffparse.h: *57
sc_NBytes        long int in struct IFFStreamCmd
         +0x0008 libraries/iffparse.h: *59
scsi_Actual      unsigned long int in struct SCSICmd
         +0x0008 devices/scsidisk.h: *80
scsi_CmdActual   unsigned short int in struct SCSICmd
         +0x0012 devices/scsidisk.h: *83
scsi_CmdLength   unsigned short int in struct SCSICmd
         +0x0010 devices/scsidisk.h: *82
scsi_Command     pointer to unsigned char in struct SCSICmd
         +0x000c devices/scsidisk.h: *81
scsi_Data        pointer to unsigned short int in struct SCSICmd
         +0x0000 devices/scsidisk.h: *74
scsi_Flags       unsigned char in struct SCSICmd
         +0x0014 devices/scsidisk.h: *84
scsi_Length      unsigned long int in struct SCSICmd
         +0x0004 devices/scsidisk.h: *77
scsi_SenseActual unsigned short int in struct SCSICmd
         +0x001c devices/scsidisk.h: *91
scsi_SenseData   pointer to unsigned char in struct SCSICmd
         +0x0016 devices/scsidisk.h: *86
scsi_SenseLength unsigned short int in struct SCSICmd
         +0x001a devices/scsidisk.h: *89
scsi_Status      unsigned char in struct SCSICmd
         +0x0015 devices/scsidisk.h: *85
sec              unsigned short int in struct ClockData
         +0x0000 utility/date.h: *20
seg_Name         array [4] of unsigned char in struct Segment
         +0x000c dos/dosextens.h: *292
seg_Next         long int in struct Segment +0x0000 dos/dosextens.h: *289
seg_Seg          long int in struct Segment +0x0008 dos/dosextens.h: *291
seg_UC           long int in struct Segment +0x0004 dos/dosextens.h: *290
serdat           unsigned short int in struct Custom
         +0x0030 hardware/custom.h: *51
serdatr          unsigned short int in struct Custom
         +0x0018 hardware/custom.h: *40
serper           unsigned short int in struct Custom
         +0x0032 hardware/custom.h: *52
sex              unsigned short int in struct narrator_rb
         +0x0036 devices/narrator.h: *98
sh_List          struct List(size 0x000e bytes) in struct SoftIntList
         +0x0000 exec/interrupts.h: *39
sh_Pad           unsigned short int in struct SoftIntList
         +0x000e exec/interrupts.h: *40
shadowPen        #define SHADOWPEN = 0x00000004  intuition/iobsolete.h: *265
shape            unsigned char in struct mouth_rb
         +0x005a devices/narrator.h: *132
shinePen         #define SHINEPEN = 0x00000003  intuition/iobsolete.h: *264
sin              #define IEEEDPSin  libraries/mathffp.h: *43
                 libraries/mathieeedp.h: *43
sinh             #define IEEEDPSinh  libraries/mathffp.h: *51
                 libraries/mathieeedp.h: *51
sm_ArgList       pointer to struct WBArg in struct WBStartup
         +0x0024 workbench/startup.h: *33
sm_Bids          short int in struct Semaphore +0x0022 exec/semaphores.h: *56
sm_ClipID        long int in struct SatisfyMsg +0x0016 devices/clipboard.h: *62
sm_LockMsg       #define mp_SigTask  exec/semaphores.h: *59
sm_Message       struct Message(size 0x0014 bytes) in struct WBStartup
         +0x0000 workbench/startup.h: *28
sm_Msg           struct Message(size 0x0014 bytes) in struct SatisfyMsg
         +0x0000 devices/clipboard.h: *60
sm_MsgPort       struct MsgPort(size 0x0022 bytes) in struct Semaphore
         +0x0000 exec/semaphores.h: *55
sm_NumArgs       long int in struct WBStartup +0x001c workbench/startup.h: *31
sm_Process       pointer to struct MsgPort in struct WBStartup
         +0x0014 workbench/startup.h: *29
sm_Segment       long int in struct WBStartup +0x0018 workbench/startup.h: *30
sm_ToolWindow    pointer to char in struct WBStartup
         +0x0020 workbench/startup.h: *32
sm_Unit          unsigned short int in struct SatisfyMsg
         +0x0014 devices/clipboard.h: *61
sn_Pred          pointer to struct SrcNode in struct SrcNode
         +0x0004 rexx/storage.h: *229
sn_Ptr           pointer to void in struct SrcNode +0x0008 rexx/storage.h: *230
sn_Size          long int in struct SrcNode +0x000c rexx/storage.h: *231
sn_Succ          pointer to struct SrcNode in struct SrcNode
         +0x0000 rexx/storage.h: *228
sp_Data          pointer to unsigned char in struct StoredProperty
         +0x0004 libraries/iffparse.h: *97
sp_Msg           struct Message(size 0x0014 bytes) in struct StandardPacket
         +0x0000 dos/dosextens.h: *142
sp_Pkt           struct DosPacket(size 0x0030 bytes) in struct StandardPacket
         +0x0014 dos/dosextens.h: *143
sp_Size          long int in struct StoredProperty
         +0x0000 libraries/iffparse.h: *96
spm_Flags        unsigned short int in struct SpecialMonitor
         +0x0018 graphics/monitor.h: *145
spm_Node         struct ExtendedNode(size 0x0018 bytes) in struct
                 SpecialMonitor
         +0x0000 graphics/monitor.h: *144
spr              array [8] of struct SpriteDef(size 0x0008 bytes) in struct
                 Custom
         +0x0140 hardware/custom.h: *121
sprRsrvd         char in struct GelsInfo +0x0000 graphics/rastport.h: *43
sprhstop         unsigned short int in struct Custom
         +0x01d2 hardware/custom.h: *132
sprhstrt         unsigned short int in struct Custom
         +0x01d0 hardware/custom.h: *131
sprpt            array [8] of pointer to void in struct Custom
         +0x0120 hardware/custom.h: *115
sprstop          array [4] of unsigned short int in struct copinit
         +0x0070 graphics/copper.h: *103
sprstrtup        array [32] of unsigned short int in struct copinit
         +0x0014 graphics/copper.h: *97
sqrt             #define IEEEDPSqrt  libraries/mathffp.h: *49
                 libraries/mathieeedp.h: *49
sr_Link          struct MinNode(size 0x0008 bytes) in struct SemaphoreRequest
         +0x0000 exec/semaphores.h: *36
sr_Waiter        pointer to struct Task in struct SemaphoreRequest
         +0x0008 exec/semaphores.h: *37
ss_Link          struct Node(size 0x000e bytes) in struct SignalSemaphore
         +0x0000 exec/semaphores.h: *42
ss_MultipleLink struct SemaphoreRequest(size 0x000c bytes) in struct
                 SignalSemaphore
         +0x001c exec/semaphores.h: *45
ss_NestCount     short int in struct SignalSemaphore
         +0x000e exec/semaphores.h: *43
ss_Owner         pointer to struct Task in struct SignalSemaphore
         +0x0028 exec/semaphores.h: *46
ss_QueueCount    short int in struct SignalSemaphore
         +0x002c exec/semaphores.h: *47
ss_WaitQueue     struct MinList(size 0x000c bytes) in struct SignalSemaphore
         +0x0010 exec/semaphores.h: *44
start            pointer to unsigned short int in struct cprlist
         +0x0004 graphics/copper.h: *59
stat             char in struct bltnode +0x0008 hardware/blit.h: *94
strequ           unsigned short int in struct Custom
         +0x0038 hardware/custom.h: *55
strhor           unsigned short int in struct Custom
         +0x003c hardware/custom.h: *57
strlong          unsigned short int in struct Custom
         +0x003e hardware/custom.h: *58
strvbl           unsigned short int in struct Custom
         +0x003a hardware/custom.h: *56
sync             unsigned char in struct mouth_rb
         +0x005b devices/narrator.h: *133
system_bplcon0   short int in struct GfxBase +0x00a4 graphics/gfxbase.h: *43
SAVEBACK         #define 0x0002 = 0x00000002  graphics/gels.h: *23
SAVEBOB          #define 0x0001 = 0x00000001  graphics/gels.h: *35
SAVEPRESERVE     #define 0x1000 = 0x00001000  graphics/gels.h: *42
SA_AutoScroll    #define (SA_Dummy + 0x0019) = 0x80000039
                 intuition/screens.h: *273
SA_Behind        #define (SA_Dummy + 0x0017) = 0x80000037
                 intuition/screens.h: *269
SA_BitMap        #define (SA_Dummy + 0x000E) = 0x8000002e
                 intuition/screens.h: *229
SA_BlockPen      #define (SA_Dummy + 0x0007) = 0x80000027
                 intuition/screens.h: *210
SA_Colors        #define (SA_Dummy + 0x0009) = 0x80000029
                 intuition/screens.h: *213
SA_DClip         #define (SA_Dummy + 0x0013) = 0x80000033
                 intuition/screens.h: *247
SA_Depth         #define (SA_Dummy + 0x0005) = 0x80000025
                 intuition/screens.h: *206
SA_DetailPen     #define (SA_Dummy + 0x0006) = 0x80000026
                 intuition/screens.h: *208
SA_DisplayID     #define (SA_Dummy + 0x0012) = 0x80000032
                 intuition/screens.h: *243
SA_Dummy         #define (TAG_USER + 32) = 0x80000020
                 intuition/screens.h: *197
SA_ErrorCode     #define (SA_Dummy + 0x000A) = 0x8000002a
                 intuition/screens.h: *218
SA_Font          #define (SA_Dummy + 0x000B) = 0x8000002b
                 intuition/screens.h: *220
SA_FullPalette   #define (SA_Dummy + 0x001B) = 0x8000003b
                 intuition/screens.h: *279
SA_Height        #define (SA_Dummy + 0x0004) = 0x80000024
                 intuition/screens.h: *204
SA_Left          #define (SA_Dummy + 0x0001) = 0x80000021
                 intuition/screens.h: *201
SA_Obsolete1     #define (SA_Dummy + 0x0015) = 0x80000035
                 intuition/screens.h: *263
SA_Overscan      #define (SA_Dummy + 0x0014) = 0x80000034
                 intuition/screens.h: *251
SA_Pens          #define (SA_Dummy + 0x001A) = 0x8000003a
                 intuition/screens.h: *275
SA_PubName       #define (SA_Dummy + 0x000F) = 0x8000002f
                 intuition/screens.h: *233
SA_PubSig        #define (SA_Dummy + 0x0010) = 0x80000030
                 intuition/screens.h: *238
SA_PubTask       #define (SA_Dummy + 0x0011) = 0x80000031
                 intuition/screens.h: *239
SA_Quiet         #define (SA_Dummy + 0x0018) = 0x80000038
                 intuition/screens.h: *271
SA_ShowTitle     #define (SA_Dummy + 0x0016) = 0x80000036
                 intuition/screens.h: *267
SA_SysFont       #define (SA_Dummy + 0x000C) = 0x8000002c
                 intuition/screens.h: *222
SA_Title         #define (SA_Dummy + 0x0008) = 0x80000028
                 intuition/screens.h: *211
SA_Top           #define (SA_Dummy + 0x0002) = 0x80000022
                 intuition/screens.h: *202
SA_Type          #define (SA_Dummy + 0x000D) = 0x8000002d
                 intuition/screens.h: *227
SA_Width         #define (SA_Dummy + 0x0003) = 0x80000023
                 intuition/screens.h: *203
SBUFSIZE_BITS    #define 0x0F = 0x0000000f  intuition/preferences.h: *220
SBUF_1024        #define 0x01 = 0x00000001  intuition/preferences.h: *209
SBUF_16000       #define 0x05 = 0x00000005  intuition/preferences.h: *213
SBUF_2048        #define 0x02 = 0x00000002  intuition/preferences.h: *210
SBUF_4096        #define 0x03 = 0x00000003  intuition/preferences.h: *211
SBUF_512         #define 0x00 = 0x00000000  intuition/preferences.h: *208
SBUF_8000        #define 0x04 = 0x00000004  intuition/preferences.h: *212
SCREENBEHIND     #define 0x0080 = 0x00000080  intuition/screens.h: *173
SCREENHIRES      #define 0x0200 = 0x00000200  intuition/screens.h: *177
SCREENQUIET      #define 0x0100 = 0x00000100  intuition/screens.h: *176
SCREENTYPE       #define 0x000F = 0x0000000f  intuition/screens.h: *159
SCREEN_DRAG      #define (1<<14) = 0x00004000  intuition/preferences.h: *137
SCRGADGET        #define GTYP_SCRGADGET = 0x00004000
                 intuition/iobsolete.h: *93
SCROLLERIDCMP    #define (IDCMP_GADGETUP | IDCMP_GADGETDOWN | IDCMP_MOUSEMOVE)
                 = 0x00000070
                 libraries/gadtools.h: *78
SCROLLER_KIND    #define 9 = 0x00000009  libraries/gadtools.h: *43
SCSIB_AUTOSENSE  #define 1 = 0x00000001  devices/scsidisk.h: *105
SCSIB_OLDAUTOSENSE #define 2 = 0x00000002  devices/scsidisk.h: *106
SCSIB_READ_WRITE #define 0 = 0x00000000  devices/scsidisk.h: *98
SCSICmd          structure tag size 0x001e devices/scsidisk.h: *73
SCSIF_AUTOSENSE  #define 2 = 0x00000002  devices/scsidisk.h: *101
SCSIF_NOSENSE    #define 0 = 0x00000000  devices/scsidisk.h: *100
SCSIF_OLDAUTOSENSE #define 6 = 0x00000006  devices/scsidisk.h: *103
SCSIF_READ       #define 1 = 0x00000001  devices/scsidisk.h: *97
SCSIF_WRITE      #define 0 = 0x00000000  devices/scsidisk.h: *96
SDCMD_BREAK      #define (CMD_NONSTD+1) = 0x0000000a  devices/serial.h: *96
SDCMD_QUERY      #define CMD_NONSTD = 0x00000009  devices/serial.h: *95
SDCMD_SETPARAMS  #define (CMD_NONSTD+2) = 0x0000000b  devices/serial.h: *97
SDEPTHIMAGE      #define (0x05L) = 0x00000005  intuition/imageclass.h: *105
SDOWNBACK        #define GTYP_SDOWNBACK = 0x00000070
                 intuition/iobsolete.h: *102
SDOWNBACKGADGET  #define 6 = 0x00000006  intuition/intuitionbase.h: *53
SDRAGGADGET      #define 7 = 0x00000007  intuition/intuitionbase.h: *54
SDRAGGING        #define GTYP_SDRAGGING = 0x00000030
                 intuition/iobsolete.h: *98
SELECTDOWN       #define (IECODE_LBUTTON) = 0x00000068
                 intuition/intuition.h: *1331
SELECTED         #define GFLG_SELECTED = 0x00000080
                 intuition/iobsolete.h: *59
SELECTUP         #define (IECODE_LBUTTON | IECODE_UP_PREFIX) = 0x000000e8
                 intuition/intuition.h: *1330
SERB_7WIRE       #define 2 = 0x00000002  devices/serial.h: *110
SERB_EOFMODE     #define 6 = 0x00000006  devices/serial.h: *102
SERB_PARTY_ODD   #define 1 = 0x00000001  devices/serial.h: *112
SERB_PARTY_ON    #define 0 = 0x00000000  devices/serial.h: *114
SERB_QUEUEDBRK   #define 3 = 0x00000003  devices/serial.h: *108
SERB_RAD_BOOGIE  #define 4 = 0x00000004  devices/serial.h: *106
SERB_SHARED      #define 5 = 0x00000005  devices/serial.h: *104
SERB_XDISABLED   #define 7 = 0x00000007  devices/serial.h: *100
SERF_7WIRE       #define (1<<2) = 0x00000004  devices/serial.h: *111
SERF_EOFMODE     #define (1<<6) = 0x00000040  devices/serial.h: *103
SERF_PARTY_ODD   #define (1<<1) = 0x00000002  devices/serial.h: *113
SERF_PARTY_ON    #define (1<<0) = 0x00000001  devices/serial.h: *115
SERF_QUEUEDBRK   #define (1<<3) = 0x00000008  devices/serial.h: *109
SERF_RAD_BOOGIE  #define (1<<4) = 0x00000010  devices/serial.h: *107
SERF_SHARED      #define (1<<5) = 0x00000020  devices/serial.h: *105
SERF_XDISABLED   #define (1<<7) = 0x00000080  devices/serial.h: *101
SERIALNAME       #define "serial.device"  devices/serial.h: *180
SERIAL_PRINTER   #define 0x01 = 0x00000001  intuition/preferences.h: *142
SER_DEFAULT_CTLCHAR #define 0x11130000 = 0x11130000  devices/serial.h: *28
SEXTB_MARK       #define 0 = 0x00000000  devices/serial.h: *133
SEXTB_MSPON      #define 1 = 0x00000001  devices/serial.h: *130
SEXTF_MARK       #define (1<<0) = 0x00000001  devices/serial.h: *134
SEXTF_MSPON      #define (1<<1) = 0x00000002  devices/serial.h: *132
SGA_BEEP         #define (0x4L) = 0x00000004  intuition/sghooks.h: *116
SGA_END          #define (0x2L) = 0x00000002  intuition/sghooks.h: *115
SGA_NEXTACTIVE   #define (0x20L) = 0x00000020  intuition/sghooks.h: *121
SGA_PREVACTIVE   #define (0x40L) = 0x00000040  intuition/sghooks.h: *122
SGA_REDISPLAY    #define (0x10L) = 0x00000010  intuition/sghooks.h: *118
SGA_REUSE        #define (0x8L) = 0x00000008  intuition/sghooks.h: *117
SGA_USE          #define (0x1L) = 0x00000001  intuition/sghooks.h: *114
SGH_CLICK        #define (2L) = 0x00000002  intuition/sghooks.h: *127
SGH_KEY          #define (1L) = 0x00000001  intuition/sghooks.h: *126
SGM_CONTROL      #define (1L << 5) = 0x00000020  intuition/sghooks.h: *110
SGM_EXITHELP     #define (1L << 7) = 0x00000080  intuition/sghooks.h: *104
SGM_FIXEDFIELD   #define (1L << 1) = 0x00000002  intuition/sghooks.h: *99
SGM_LONGINT      #define (1L << 6) = 0x00000040  intuition/sghooks.h: *111
SGM_NOCHANGE     #define (1L << 3) = 0x00000008  intuition/sghooks.h: *108
SGM_NOFILTER     #define (1L << 2) = 0x00000004  intuition/sghooks.h: *101
SGM_NOWORKB      #define (1L << 4) = 0x00000010  intuition/sghooks.h: *109
SGM_REPLACE      #define (1L << 0) = 0x00000001  intuition/sghooks.h: *94
SGR_BLACK        #define 30 = 0x0000001e  devices/console.h: *43
SGR_BLACKBG      #define 40 = 0x00000028  devices/console.h: *53
SGR_BLUE         #define 34 = 0x00000022  devices/console.h: *47
SGR_BLUEBG       #define 44 = 0x0000002c  devices/console.h: *57
SGR_BOLD         #define 1 = 0x00000001  devices/console.h: *32
SGR_CLR0         #define 30 = 0x0000001e  devices/console.h: *65
SGR_CLR0BG       #define 40 = 0x00000028  devices/console.h: *74
SGR_CLR1         #define 31 = 0x0000001f  devices/console.h: *66
SGR_CLR1BG       #define 41 = 0x00000029  devices/console.h: *75
SGR_CLR2         #define 32 = 0x00000020  devices/console.h: *67
SGR_CLR2BG       #define 42 = 0x0000002a  devices/console.h: *76
SGR_CLR3         #define 33 = 0x00000021  devices/console.h: *68
SGR_CLR3BG       #define 43 = 0x0000002b  devices/console.h: *77
SGR_CLR4         #define 34 = 0x00000022  devices/console.h: *69
SGR_CLR4BG       #define 44 = 0x0000002c  devices/console.h: *78
SGR_CLR5         #define 35 = 0x00000023  devices/console.h: *70
SGR_CLR5BG       #define 45 = 0x0000002d  devices/console.h: *79
SGR_CLR6         #define 36 = 0x00000024  devices/console.h: *71
SGR_CLR6BG       #define 46 = 0x0000002e  devices/console.h: *80
SGR_CLR7         #define 37 = 0x00000025  devices/console.h: *72
SGR_CLR7BG       #define 47 = 0x0000002f  devices/console.h: *81
SGR_CYAN         #define 36 = 0x00000024  devices/console.h: *49
SGR_CYANBG       #define 46 = 0x0000002e  devices/console.h: *59
SGR_DEFAULT      #define 39 = 0x00000027  devices/console.h: *51
SGR_DEFAULTBG    #define 49 = 0x00000031  devices/console.h: *61
SGR_GREEN        #define 32 = 0x00000020  devices/console.h: *45
SGR_GREENBG      #define 42 = 0x0000002a  devices/console.h: *55
SGR_ITALIC       #define 3 = 0x00000003  devices/console.h: *33
SGR_MAGENTA      #define 35 = 0x00000023  devices/console.h: *48
SGR_MAGENTABG    #define 45 = 0x0000002d  devices/console.h: *58
SGR_NEGATIVE     #define 7 = 0x00000007  devices/console.h: *35
SGR_NORMAL       #define 22 = 0x00000016  devices/console.h: *37
SGR_NOTITALIC    #define 23 = 0x00000017  devices/console.h: *38
SGR_NOTUNDERSCORE #define 24 = 0x00000018  devices/console.h: *39
SGR_POSITIVE     #define 27 = 0x0000001b  devices/console.h: *40
SGR_PRIMARY      #define 0 = 0x00000000  devices/console.h: *31
SGR_RED          #define 31 = 0x0000001f  devices/console.h: *44
SGR_REDBG        #define 41 = 0x00000029  devices/console.h: *54
SGR_UNDERSCORE   #define 4 = 0x00000004  devices/console.h: *34
SGR_WHITE        #define 37 = 0x00000025  devices/console.h: *50
SGR_WHITEBG      #define 47 = 0x0000002f  devices/console.h: *60
SGR_YELLOW       #define 33 = 0x00000021  devices/console.h: *46
SGR_YELLOWBG     #define 43 = 0x0000002b  devices/console.h: *56
SGWork           structure tag size 0x002c intuition/sghooks.h: *33
SG_DEFAULTMAXCHARS #define (128) = 0x00000080  intuition/gadgetclass.h: *147
SHADE_BW         #define 0x00 = 0x00000000  intuition/preferences.h: *180
SHADE_COLOR      #define 0x02 = 0x00000002  intuition/preferences.h: *182
SHADE_GREYSCALE  #define 0x01 = 0x00000001  intuition/preferences.h: *181
SHADOWPEN        #define (0x0004) = 0x00000004  intuition/screens.h: *86
SHAKNUM          macro (1 argument)   intuition/intuition.h: *1281
SHANGHAI         #define 0x0001 = 0x00000001  intuition/screens.h: *397
SHARED_LOCK      #define -2 = 0xfffffffe  dos/dos.h: *49
SHFCprList       pointer to struct cprlist in struct View
         +0x0008 graphics/view.h: *62
SHFlist          pointer to unsigned short int in struct GfxBase
         +0x0036 graphics/gfxbase.h: *33
SHIFTITEM        macro (1 argument)   intuition/intuition.h: *1271
SHIFTMENU        macro (1 argument)   intuition/intuition.h: *1270
SHIFTSUB         macro (1 argument)   intuition/intuition.h: *1272
SHINEPEN         #define (0x0003) = 0x00000003  intuition/screens.h: *85
SHORT            short int  exec/types.h: *56
SHOWTITLE        #define 0x0010 = 0x00000010  intuition/screens.h: *165
SHSHAKE_BITS     #define 0x0F = 0x0000000f  intuition/preferences.h: *223
SHSHAKE_NONE     #define 2 = 0x00000002  intuition/preferences.h: *237
SHSHAKE_RTS      #define 1 = 0x00000001  intuition/preferences.h: *236
SHSHAKE_XON      #define 0 = 0x00000000  intuition/preferences.h: *235
SIGBREAKB_CTRL_C #define 12 = 0x0000000c  dos/dos.h: *204
SIGBREAKB_CTRL_D #define 13 = 0x0000000d  dos/dos.h: *205
SIGBREAKB_CTRL_E #define 14 = 0x0000000e  dos/dos.h: *206
SIGBREAKB_CTRL_F #define 15 = 0x0000000f  dos/dos.h: *207
SIGBREAKF_CTRL_C #define (1<<SIGBREAKB_CTRL_C) = 0x00001000  dos/dos.h: *211
SIGBREAKF_CTRL_D #define (1<<SIGBREAKB_CTRL_D) = 0x00002000  dos/dos.h: *212
SIGBREAKF_CTRL_E #define (1<<SIGBREAKB_CTRL_E) = 0x00004000  dos/dos.h: *213
SIGBREAKF_CTRL_F #define ((long)1<<SIGBREAKB_CTRL_F) = 0x00008000
                 dos/dos.h: *214
SIGB_ABORT       #define 0 = 0x00000000  exec/tasks.h: *76
SIGB_BLIT        #define 4 = 0x00000004  exec/tasks.h: *78
SIGB_CHILD       #define 1 = 0x00000001  exec/tasks.h: *77
SIGB_DOS         #define 8 = 0x00000008  exec/tasks.h: *81
SIGB_INTUITION   #define 5 = 0x00000005  exec/tasks.h: *80
SIGB_SINGLE      #define 4 = 0x00000004  exec/tasks.h: *79
SIGF_ABORT       #define (1L<<0) = 0x00000001  exec/tasks.h: *83
SIGF_BLIT        #define (1L<<4) = 0x00000010  exec/tasks.h: *85
SIGF_CHILD       #define (1L<<1) = 0x00000002  exec/tasks.h: *84
SIGF_DOS         #define (1L<<8) = 0x00000100  exec/tasks.h: *88
SIGF_INTUITION   #define (1L<<5) = 0x00000020  exec/tasks.h: *87
SIGF_SINGLE      #define (1L<<4) = 0x00000010  exec/tasks.h: *86
SIGN             macro (1 argument)   intuition/intuition.h: *1293
SIGNFLAG         #define 0x40 = 0x00000040  hardware/blit.h: *73
SIH_PRIMASK      #define (0xf0) = 0x000000f0  exec/interrupts.h: *43
SIMPLEREQ        #define 0x0010 = 0x00000010  intuition/intuition.h: *190
SIMPLE_REFRESH   #define WFLG_SIMPLE_REFRESH = 0x00000040
                 intuition/iobsolete.h: *153
SINGLE           #define 0x80 = 0x00000080  intuition/preferences.h: *156
SIX_LPI          #define 0x000 = 0x00000000  intuition/preferences.h: *168
SIZEBBOTTOM      #define WFLG_SIZEBBOTTOM = 0x00000020
                 intuition/iobsolete.h: *150
SIZEBRIGHT       #define WFLG_SIZEBRIGHT = 0x00000010
                 intuition/iobsolete.h: *149
SIZEGADGET       #define 2 = 0x00000002  intuition/intuitionbase.h: *49
SIZEIMAGE        #define (0x02L) = 0x00000002  intuition/imageclass.h: *103
SIZEOF_INSTANCE macro (1 argument)   intuition/classes.h: *52
SIZEVERIFY       #define IDCMP_SIZEVERIFY = 0x00000001
                 intuition/iobsolete.h: *114
SIZING           #define GTYP_SIZING = 0x00000010  intuition/iobsolete.h: *96
SLIDERIDCMP      #define (IDCMP_GADGETUP | IDCMP_GADGETDOWN | IDCMP_MOUSEMOVE)
                 = 0x00000070
                 libraries/gadtools.h: *79
SLIDER_KIND      #define 11 = 0x0000000b  libraries/gadtools.h: *45
SMART_REFRESH    #define WFLG_SMART_REFRESH = 0x00000000
                 intuition/iobsolete.h: *152
SPARITY_BITS     #define 0xF0 = 0x000000f0  intuition/preferences.h: *222
SPARITY_EVEN     #define 1 = 0x00000001  intuition/preferences.h: *229
SPARITY_NONE     #define 0 = 0x00000000  intuition/preferences.h: *228
SPARITY_ODD      #define 2 = 0x00000002  intuition/preferences.h: *230
SPARNUM          macro (1 argument)   intuition/intuition.h: *1280
SPAbs            function returning "LONG"   libraries/mathffp.h: *60
SPAcos           function returning "LONG"   libraries/mathffp.h: *72
SPAdd            function returning "LONG"   libraries/mathffp.h: *67
SPAsin           function returning "LONG"   libraries/mathffp.h: *72
SPAtan           function returning "LONG"   libraries/mathffp.h: *72
SPCeil           function returning "LONG"   libraries/mathffp.h: *62
SPCos            function returning "LONG"   libraries/mathffp.h: *73
SPCosh           function returning "LONG"   libraries/mathffp.h: *74
SPDiv            function returning "LONG"   libraries/mathffp.h: *70
SPECIAL_ASPECT   #define 0x0080 = 0x00000080  devices/printer.h: *182
SPECIAL_BEAMCON  #define ( VARVBLANK | LOLDIS | VARVSYNC | VARBEAM | CSBLANK )
                 = 0x00001a88
                 graphics/monitor.h: *78
SPECIAL_CENTER   #define 0x0040 = 0x00000040  devices/printer.h: *181
SPECIAL_DENSITY1 #define 0x0100 = 0x00000100  devices/printer.h: *183
SPECIAL_DENSITY2 #define 0x0200 = 0x00000200  devices/printer.h: *184
SPECIAL_DENSITY3 #define 0x0300 = 0x00000300  devices/printer.h: *185
SPECIAL_DENSITY4 #define 0x0400 = 0x00000400  devices/printer.h: *186
SPECIAL_DENSITY5 #define 0x0500 = 0x00000500  devices/printer.h: *187
SPECIAL_DENSITY6 #define 0x0600 = 0x00000600  devices/printer.h: *188
SPECIAL_DENSITY7 #define 0x0700 = 0x00000700  devices/printer.h: *189
SPECIAL_DENSITYMASK #define 0x0700 = 0x00000700  devices/printer.h: *221
SPECIAL_DIMENSIONSMASK #define (SPECIAL_MILCOLS|SPECIAL_MILROWS|
                                SPECIAL_FULLCOLS|SPECIAL_FULLROWS |
                                SPECIAL_FRACCOLS|SPECIAL_FRACROWS|
                                SPECIAL_ASPECT) = 0x000000bf
                 devices/printer.h: *224
SPECIAL_FRACCOLS #define 0x0010 = 0x00000010  devices/printer.h: *179
SPECIAL_FRACROWS #define 0x0020 = 0x00000020  devices/printer.h: *180
SPECIAL_FULLCOLS #define 0x0004 = 0x00000004  devices/printer.h: *177
SPECIAL_FULLROWS #define 0x0008 = 0x00000008  devices/printer.h: *178
SPECIAL_MILCOLS  #define 0x0001 = 0x00000001  devices/printer.h: *175
SPECIAL_MILROWS  #define 0x0002 = 0x00000002  devices/printer.h: *176
SPECIAL_MONITOR_TYPE #define 3 = 0x00000003  graphics/gfxnodes.h: *35
SPECIAL_NOFORMFEED #define 0x0800 = 0x00000800  devices/printer.h: *190
SPECIAL_NOPRINT  #define 0x2000 = 0x00002000  devices/printer.h: *201
SPECIAL_TRUSTME  #define 0x1000 = 0x00001000  devices/printer.h: *191
SPExp            function returning "LONG"   libraries/mathffp.h: *75
SPFieee          function returning "LONG"   libraries/mathffp.h: *76
SPFloor          function returning "LONG"   libraries/mathffp.h: *61
SPFlt            function returning "LONG"   libraries/mathffp.h: *57
SPLog            function returning "LONG"   libraries/mathffp.h: *75
SPLog10          function returning "LONG"   libraries/mathffp.h: *75
SPMul            function returning "LONG"   libraries/mathffp.h: *69
SPNeg            function returning "LONG"   libraries/mathffp.h: *66
SPPow            function returning "LONG"   libraries/mathffp.h: *75
SPRITES          #define 0x4000 = 0x00004000  graphics/view.h: *100
SPRITE_ATTACHED  #define 0x80 = 0x00000080  graphics/sprite.h: *19
SPSin            function returning "LONG"   libraries/mathffp.h: *73
SPSincos         function returning "LONG"   libraries/mathffp.h: *73
SPSinh           function returning "LONG"   libraries/mathffp.h: *74
SPSqrt           function returning "LONG"   libraries/mathffp.h: *76
SPSub            function returning "LONG"   libraries/mathffp.h: *68
SPTan            function returning "LONG"   libraries/mathffp.h: *73
SPTanh           function returning "LONG"   libraries/mathffp.h: *74
SRBNUM           macro (1 argument)   intuition/intuition.h: *1277
SRCA             #define 0x800 = 0x00000800  hardware/blit.h: *61
SRCB             #define 0x400 = 0x00000400  hardware/blit.h: *60
SRCC             #define 0x200 = 0x00000200  hardware/blit.h: *59
SREAD_BITS       #define 0xF0 = 0x000000f0  intuition/preferences.h: *216
SSBNUM           macro (1 argument)   intuition/intuition.h: *1279
SSTOP_BITS       #define 0xF0 = 0x000000f0  intuition/preferences.h: *219
SS_GRAPHICS      #define 0x02 = 0x00000002  graphics/gfxnodes.h: *31
STANDARD_COLORCLOCKS #define 226 = 0x000000e2  graphics/monitor.h: *72
STANDARD_DENISE_MAX #define 455 = 0x000001c7  graphics/monitor.h: *73
STANDARD_DENISE_MIN #define 93 = 0x0000005d  graphics/monitor.h: *74
STANDARD_HBSTOP  #define 0x2C = 0x0000002c  graphics/monitor.h: *87
STANDARD_HBSTRT  #define 0x06 = 0x00000006  graphics/monitor.h: *84
STANDARD_HSSTOP  #define 0x1C = 0x0000001c  graphics/monitor.h: *86
STANDARD_HSSTRT  #define 0x0B = 0x0000000b  graphics/monitor.h: *85
STANDARD_MONITOR_MASK #define ( REQUEST_NTSC | REQUEST_PAL ) = 0x00000003
                 graphics/monitor.h: *68
STANDARD_NTSC_BEAMCON #define ( 0x0000 ) = 0x00000000  graphics/monitor.h: *75
STANDARD_NTSC_ROWS #define 262 = 0x00000106  graphics/monitor.h: *70
STANDARD_PAL_BEAMCON #define ( DISPLAYPAL ) = 0x00000020
                 graphics/monitor.h: *76
STANDARD_PAL_ROWS #define 312 = 0x00000138  graphics/monitor.h: *71
STANDARD_VBSTOP  #define 0x1066 = 0x00001066  graphics/monitor.h: *91
STANDARD_VBSTRT  #define 0x0122 = 0x00000122  graphics/monitor.h: *88
STANDARD_VIEW_X  #define 0x81 = 0x00000081  graphics/monitor.h: *82
STANDARD_VIEW_Y  #define 0x2C = 0x0000002c  graphics/monitor.h: *83
STANDARD_VSSTOP  #define 0x03AA = 0x000003aa  graphics/monitor.h: *90
STANDARD_VSSTRT  #define 0x02A6 = 0x000002a6  graphics/monitor.h: *89
STANDARD_XOFFSET #define 9 = 0x00000009  graphics/monitor.h: *58
STANDARD_YOFFSET #define 0 = 0x00000000  graphics/monitor.h: *59
STATIC           #define static  exec/types.h: *22
STDSCREENHEIGHT  #define -1 = 0xffffffff  intuition/screens.h: *184
STDSCREENWIDTH   #define -1 = 0xffffffff  intuition/screens.h: *185
STRGADGET        #define GTYP_STRGADGET = 0x00000004
                 intuition/iobsolete.h: *107
STRGCLASS        #define "strgclass"  intuition/classusr.h: *49
STRINGA_ActivePens #define (STRINGA_Dummy + 0x000A) = 0x8003200a
                 intuition/gadgetclass.h: *127
STRINGA_AltKeyMap #define (STRINGA_Dummy + 0x0007) = 0x80032007
                 intuition/gadgetclass.h: *124
STRINGA_Buffer   #define (STRINGA_Dummy + 0x0002) = 0x80032002
                 intuition/gadgetclass.h: *119
STRINGA_BufferPos #define (STRINGA_Dummy + 0x0005) = 0x80032005
                 intuition/gadgetclass.h: *122
STRINGA_DispPos  #define (STRINGA_Dummy + 0x0006) = 0x80032006
                 intuition/gadgetclass.h: *123
STRINGA_Dummy    #define (TAG_USER +0x32000) = 0x80032000
                 intuition/gadgetclass.h: *117
STRINGA_EditHook #define (STRINGA_Dummy + 0x000B) = 0x8003200b
                 intuition/gadgetclass.h: *128
STRINGA_EditModes #define (STRINGA_Dummy + 0x000C) = 0x8003200c
                 intuition/gadgetclass.h: *129
STRINGA_ExitHelp #define (STRINGA_Dummy + 0x0013) = 0x80032013
                 intuition/gadgetclass.h: *141
STRINGA_FixedFieldMode #define (STRINGA_Dummy + 0x000E) = 0x8003200e
                 intuition/gadgetclass.h: *133
STRINGA_Font     #define (STRINGA_Dummy + 0x0008) = 0x80032008
                 intuition/gadgetclass.h: *125
STRINGA_Justification #define (STRINGA_Dummy + 0x0010) = 0x80032010
                 intuition/gadgetclass.h: *136
STRINGA_LongVal  #define (STRINGA_Dummy + 0x0011) = 0x80032011
                 intuition/gadgetclass.h: *138
STRINGA_MaxChars #define (STRINGA_Dummy + 0x0001) = 0x80032001
                 intuition/gadgetclass.h: *118
STRINGA_NoFilterMode #define (STRINGA_Dummy + 0x000F) = 0x8003200f
                 intuition/gadgetclass.h: *134
STRINGA_Pens     #define (STRINGA_Dummy + 0x0009) = 0x80032009
                 intuition/gadgetclass.h: *126
STRINGA_ReplaceMode #define (STRINGA_Dummy + 0x000D) = 0x8003200d
                 intuition/gadgetclass.h: *132
STRINGA_TextVal  #define (STRINGA_Dummy + 0x0012) = 0x80032012
                 intuition/gadgetclass.h: *139
STRINGA_UndoBuffer #define (STRINGA_Dummy + 0x0003) = 0x80032003
                 intuition/gadgetclass.h: *120
STRINGA_WorkBuffer #define (STRINGA_Dummy + 0x0004) = 0x80032004
                 intuition/gadgetclass.h: *121
STRINGCENTER     #define GACT_STRINGCENTER = 0x00000200
                 intuition/iobsolete.h: *81
STRINGEXTEND     #define GACT_STRINGEXTEND = 0x00002000
                 intuition/iobsolete.h: *85
STRINGIDCMP      #define (IDCMP_GADGETUP) = 0x00000040
                 libraries/gadtools.h: *80
STRINGLEFT       #define GACT_STRINGLEFT = 0x00000000
                 intuition/iobsolete.h: *80
STRINGRIGHT      #define GACT_STRINGRIGHT = 0x00000400
                 intuition/iobsolete.h: *82
STRING_KIND      #define 12 = 0x0000000c  libraries/gadtools.h: *46
STRPTR           pointer to unsigned char  exec/types.h: *52
ST_FILE          #define -3 = 0xfffffffd  dos/dosextens.h: *477
ST_LINKDIR       #define 4 = 0x00000004  dos/dosextens.h: *476
ST_LINKFILE      #define -4 = 0xfffffffc  dos/dosextens.h: *478
ST_ROOT          #define 1 = 0x00000001  dos/dosextens.h: *473
ST_SOFTLINK      #define 3 = 0x00000003  dos/dosextens.h: *475
ST_USERDIR       #define 2 = 0x00000002  dos/dosextens.h: *474
SUBNUM           macro (1 argument)   intuition/intuition.h: *1268
SUD              #define 0x10 = 0x00000010  hardware/blit.h: *76
SUL              #define 0x8 = 0x00000008  hardware/blit.h: *77
SUPERDPF2_KEY    #define 0x00008460 = 0x00008460  graphics/displayinfo.h: *171
SUPERDPF_KEY     #define 0x00008420 = 0x00008420  graphics/displayinfo.h: *165
SUPERHIRES       #define 0x0020 = 0x00000020  graphics/view.h: *92
SUPERLACEDPF2_KEY #define 0x00008464 = 0x00008464
                 graphics/displayinfo.h: *174
SUPERLACEDPF_KEY #define 0x00008424 = 0x00008424  graphics/displayinfo.h: *168
SUPERLACE_KEY    #define 0x00008024 = 0x00008024  graphics/displayinfo.h: *161
SUPER_BITMAP     #define WFLG_SUPER_BITMAP = 0x00000080
                 intuition/iobsolete.h: *154
SUPER_KEY        #define 0x00008020 = 0x00008020  graphics/displayinfo.h: *157
SUPFRONT         #define GTYP_SUPFRONT = 0x00000050
                 intuition/iobsolete.h: *100
SUPFRONTGADGET   #define 5 = 0x00000005  intuition/intuitionbase.h: *52
SUSERFLAGS       #define 0x00FF = 0x000000ff  graphics/gels.h: *21
SWBNUM           macro (1 argument)   intuition/intuition.h: *1278
SWRITE_BITS      #define 0x0F = 0x0000000f  intuition/preferences.h: *217
SYSGADGET        #define GTYP_SYSGADGET = 0x00008000
                 intuition/iobsolete.h: *92
SYSIA_Depth      #define (IA_Dummy + 0x0C) = 0x8002000c
                 intuition/imageclass.h: *74
SYSIA_DrawInfo   #define (IA_Dummy + 0x18) = 0x80020018
                 intuition/imageclass.h: *80
SYSIA_Pens       #define IA_Pens = 0x8002000e  intuition/imageclass.h: *84
SYSIA_Size       #define (IA_Dummy + 0x0B) = 0x8002000b
                 intuition/imageclass.h: *72
SYSIA_Which      #define (IA_Dummy + 0x0D) = 0x8002000d
                 intuition/imageclass.h: *78
SYSICLASS        #define "sysiclass"  intuition/classusr.h: *45
SYSISIZE_HIRES   #define (2) = 0x00000002  intuition/imageclass.h: *94
SYSISIZE_LOWRES  #define (1) = 0x00000001  intuition/imageclass.h: *93
SYSISIZE_MEDRES  #define (0) = 0x00000000  intuition/imageclass.h: *92
SYSREQUEST       #define 0x4000 = 0x00004000  intuition/intuition.h: *205
SYS_Asynch       #define (SYS_Dummy + 3) = 0x80000023  dos/dostags.h: *29
SYS_CustomShell  #define (SYS_Dummy + 5) = 0x80000025  dos/dostags.h: *33
SYS_Dummy        #define (TAG_USER + 32) = 0x80000020  dos/dostags.h: *24
SYS_Input        #define (SYS_Dummy + 1) = 0x80000021  dos/dostags.h: *25
SYS_Output       #define (SYS_Dummy + 2) = 0x80000022  dos/dostags.h: *27
SYS_UserShell    #define (SYS_Dummy + 4) = 0x80000024  dos/dostags.h: *31
SatisfyMsg       structure tag size 0x001a devices/clipboard.h: *59
SaveBuffer       pointer to short int in struct Bob
         +0x0002 graphics/gels.h: *145
SaveColor0       unsigned short int in struct Screen
         +0x014c intuition/screens.h: *142
Screen           structure tag size 0x015a devices/inputevent.h: *89
                 intuition/intuition.h: 819, 1005, 1057
                 intuition/screens.h: 98, 100, 384
                 intuition/cghooks.h: 29
                 intuition/intuitionbase.h: 75, 80
Screen           pointer to struct Screen in struct NewWindow
         +0x001e intuition/intuition.h: *1005
Screen           pointer to struct Screen in struct ExtNewWindow
         +0x001e intuition/intuition.h: *1057
ScreenTitle      pointer to unsigned char in struct Window
         +0x0068 intuition/intuition.h: *867
Scroll_X         short int in struct Layer +0x002c graphics/clip.h: *47
Scroll_Y         short int in struct Layer +0x002e graphics/clip.h: *47
Seconds          unsigned long int in struct IntuiMessage
         +0x0024 intuition/intuition.h: *708
Seconds          unsigned long int in struct IntuitionBase
         +0x0048 intuition/intuitionbase.h: *86
Segment          structure tag size 0x0010 dos/dosextens.h: *288
SelectFill       pointer to void in struct MenuItem
         +0x0016 intuition/intuition.h: *104
SelectRender     pointer to void in struct Gadget
         +0x0016 intuition/intuition.h: *238
Semaphore        structure tag size 0x0024 exec/semaphores.h: *54
SemaphoreList    struct List(size 0x000e bytes) in struct ExecBase
         +0x0214 exec/execbase.h: *114
SemaphoreRequest structure tag size 0x000c exec/semaphores.h: *35, 45
SerErr_BaudMismatch #define 2 = 0x00000002  devices/serial.h: *138
SerErr_BufErr    #define 4 = 0x00000004  devices/serial.h: *139
SerErr_BufOverflow #define 12 = 0x0000000c  devices/serial.h: *144
SerErr_DetectedBreak #define 15 = 0x0000000f  devices/serial.h: *146
SerErr_DevBusy   #define 1 = 0x00000001  devices/serial.h: *137
SerErr_InvParam  #define 5 = 0x00000005  devices/serial.h: *140
SerErr_LineErr   #define 6 = 0x00000006  devices/serial.h: *141
SerErr_NoDSR     #define 13 = 0x0000000d  devices/serial.h: *145
SerErr_ParityErr #define 9 = 0x00000009  devices/serial.h: *142
SerErr_TimerErr  #define 11 = 0x0000000b  devices/serial.h: *143
SerParShk        unsigned char in struct Preferences
         +0x00b8 intuition/preferences.h: *108
SerRWBits        unsigned char in struct Preferences
         +0x00b6 intuition/preferences.h: *104
SerStopBuf       unsigned char in struct Preferences
         +0x00b7 intuition/preferences.h: *106
SetAfPt          macro (3 arguments)   graphics/gfxmacros.h: *34
SetDrPt          macro (2 arguments)   graphics/gfxmacros.h: *32
SetOPen          macro (2 arguments)   graphics/gfxmacros.h: *31
SetWrMsk         macro (2 arguments)   graphics/gfxmacros.h: *33
SignalSemaphore structure tag size 0x002e exec/semaphores.h: *41
                 dos/dosextens.h: 281, 282
                 graphics/clip.h: 52
                 graphics/monitor.h: 51
                 graphics/layers.h: 40
                 graphics/gfxbase.h: 63, 88, 90
SimpleSprite     structure tag size 0x000c graphics/gfxbase.h: *55
                 graphics/sprite.h: 21
SimpleSprites    pointer to pointer to struct SimpleSprite in struct GfxBase
         +0x00d0 graphics/gfxbase.h: *55
Size             long int in struct TmpRas +0x0004 graphics/rastport.h: *37
SkipID           unsigned long int in struct QueryHeader
         +0x0008 graphics/displayinfo.h: *46
SoftIntList      structure tag size 0x0010 exec/interrupts.h: *38
                 exec/execbase.h: 95
SoftInts         array [5] of struct SoftIntList(size 0x0010 bytes) in struct
                 ExecBase
         +0x01b2 exec/execbase.h: *95
SoftVer          unsigned short int in struct ExecBase
         +0x0022 exec/execbase.h: *41
SpecialInfo      pointer to void in struct Gadget
         +0x0022 intuition/intuition.h: *258
SpecialLink      pointer to struct IntuiMessage in struct IntuiMessage
         +0x0030 intuition/intuition.h: *716
SpecialMonitor   structure tag size 0x003a graphics/monitor.h: *38, 142
SprColors        pointer to short int in struct VSprite
         +0x0030 graphics/gels.h: *114
SprIns           pointer to struct CopList in struct ViewPort
         +0x000c graphics/view.h: *47
SpriteDef        structure tag (size 0x0008 bytes)in struct Custom
                 hardware/custom.h: *116
SpritePriorities unsigned char in struct ViewPort +0x0022 graphics/view.h: *53
SpriteReserved   unsigned char in struct GfxBase
         +0x00a6 graphics/gfxbase.h: *44
SpriteResolution struct tPoint(size 0x0004 bytes) in struct DisplayInfo
         +0x0020 graphics/displayinfo.h: *59
SrcNode          structure tag size 0x0010 rexx/storage.h: *227, 228, 229
StandardPacket   structure tag size 0x0044 dos/dosextens.h: *141
StdOScan         struct Rectangle(size 0x0008 bytes) in struct DimensionInfo
         +0x003a graphics/displayinfo.h: *104
StoredProperty   structure tag size 0x0008 libraries/iffparse.h: *95
StringExtend     structure tag size 0x0024 intuition/intuition.h: *546
                 intuition/sghooks.h: 19
StringInfo       structure tag size 0x0024 intuition/intuition.h: *524
                 intuition/sghooks.h: 36
StringInfo       pointer to struct StringInfo in struct SGWork
         +0x0004 intuition/sghooks.h: *36
StructID         unsigned long int in struct QueryHeader
         +0x0000 graphics/displayinfo.h: *44
SubItem          pointer to struct MenuItem in struct MenuItem
         +0x001c intuition/intuition.h: *108
SuperBitMap      pointer to struct BitMap in struct Layer
         +0x0020 graphics/clip.h: *43
SuperClipRect    pointer to struct ClipRect in struct Layer
         +0x0024 graphics/clip.h: *44
SuperSaveClipRects pointer to struct ClipRect in struct Layer
         +0x003c graphics/clip.h: *49
SysFlags         unsigned short int in struct ExecBase
         +0x0124 exec/execbase.h: *69
SysStkLower      pointer to void in struct ExecBase
         +0x003a exec/execbase.h: *48
SysStkUpper      pointer to void in struct ExecBase
         +0x0036 exec/execbase.h: *47


2.0 IncludeXREF: T

tPoint           structure tag size 0x0004 graphics/gfx.h: *41
ta_Flags         unsigned char in struct TextAttr +0x0007 graphics/text.h: *71
ta_Name          pointer to unsigned char in struct TextAttr
         +0x0000 graphics/text.h: *68
ta_Style         unsigned char in struct TextAttr +0x0006 graphics/text.h: *70
ta_YSize         unsigned short int in struct TextAttr
         +0x0004 graphics/text.h: *69
taf_Attr         struct TTextAttr(size 0x000c bytes) in struct TAvailFonts
         +0x0002 libraries/diskfont.h: *102
taf_Type         unsigned short int in struct TAvailFonts
         +0x0000 libraries/diskfont.h: *101
tan              #define IEEEDPTan  libraries/mathffp.h: *39
                 libraries/mathieeedp.h: *39
tanh             #define IEEEDPTanh  libraries/mathffp.h: *53
                 libraries/mathieeedp.h: *53
tc_ExceptCode    pointer to void in struct Task +0x002a exec/tasks.h: *39
tc_ExceptData    pointer to void in struct Task +0x0026 exec/tasks.h: *38
tc_Flags         unsigned char in struct Task +0x000e exec/tasks.h: *28
tc_IDNestCnt     char in struct Task +0x0010 exec/tasks.h: *30
tc_Launch        pointer to function returning void in struct Task
         +0x0046 exec/tasks.h: *46
tc_MemEntry      struct List(size 0x000e bytes) in struct Task
         +0x004a exec/tasks.h: *47
tc_Node          struct Node(size 0x000e bytes) in struct Task
         +0x0000 exec/tasks.h: *27
tc_SPLower       pointer to void in struct Task +0x003a exec/tasks.h: *43
tc_SPReg         pointer to void in struct Task +0x0036 exec/tasks.h: *42
tc_SPUpper       pointer to void in struct Task +0x003e exec/tasks.h: *44
tc_SigAlloc      unsigned long int in struct Task +0x0012 exec/tasks.h: *32
tc_SigExcept     unsigned long int in struct Task +0x001e exec/tasks.h: *35
tc_SigRecvd      unsigned long int in struct Task +0x001a exec/tasks.h: *34
tc_SigWait       unsigned long int in struct Task +0x0016 exec/tasks.h: *33
tc_State         unsigned char in struct Task +0x000f exec/tasks.h: *29
tc_Switch        pointer to function returning void in struct Task
         +0x0042 exec/tasks.h: *45
tc_TDNestCnt     char in struct Task +0x0011 exec/tasks.h: *31
tc_TrapAble      unsigned short int in struct Task +0x0024 exec/tasks.h: *37
tc_TrapAlloc     unsigned short int in struct Task +0x0022 exec/tasks.h: *36
tc_TrapCode      pointer to void in struct Task +0x0032 exec/tasks.h: *41
tc_TrapData      pointer to void in struct Task +0x002e exec/tasks.h: *40
tc_UserData      pointer to void in struct Task +0x0058 exec/tasks.h: *48
tdu_CalibrateDelay unsigned long int in struct TDU_PublicUnit
         +0x0038 devices/trackdisk.h: *251
tdu_Comp01Track unsigned short int in struct TDU_PublicUnit
         +0x0026 devices/trackdisk.h: *242
tdu_Comp10Track unsigned short int in struct TDU_PublicUnit
         +0x0028 devices/trackdisk.h: *243
tdu_Comp11Track unsigned short int in struct TDU_PublicUnit
         +0x002a devices/trackdisk.h: *244
tdu_Counter      unsigned long int in struct TDU_PublicUnit
         +0x003c devices/trackdisk.h: *253
tdu_CurrTrk      unsigned short int in struct TDU_PublicUnit
         +0x0036 devices/trackdisk.h: *249
tdu_PubFlags     unsigned char in struct TDU_PublicUnit
         +0x0035 devices/trackdisk.h: *248
tdu_RetryCnt     unsigned char in struct TDU_PublicUnit
         +0x0034 devices/trackdisk.h: *247
tdu_SettleDelay unsigned long int in struct TDU_PublicUnit
         +0x0030 devices/trackdisk.h: *246
tdu_StepDelay    unsigned long int in struct TDU_PublicUnit
         +0x002c devices/trackdisk.h: *245
tdu_Unit         struct Unit(size 0x0026 bytes) in struct TDU_PublicUnit
         +0x0000 devices/trackdisk.h: *241
te_Extent        struct Rectangle(size 0x0008 bytes) in struct TextExtent
         +0x0004 graphics/text.h: *169
te_Height        unsigned short int in struct TextExtent
         +0x0002 graphics/text.h: *168
te_Width         unsigned short int in struct TextExtent
         +0x0000 graphics/text.h: *167
textPen          #define TEXTPEN = 0x00000002  intuition/iobsolete.h: *263
tf_Accessors     unsigned short int in struct TextFont
         +0x001e graphics/text.h: *101
tf_Baseline      unsigned short int in struct TextFont
         +0x001a graphics/text.h: *98
tf_BoldSmear     unsigned short int in struct TextFont
         +0x001c graphics/text.h: *99
tf_CharData      pointer to void in struct TextFont
         +0x0022 graphics/text.h: *105
tf_CharKern      pointer to void in struct TextFont
         +0x0030 graphics/text.h: *111
tf_CharLoc       pointer to void in struct TextFont
         +0x0028 graphics/text.h: *108
tf_CharSpace     pointer to void in struct TextFont
         +0x002c graphics/text.h: *110
tf_Extension     #define tf_Message.mn_ReplyPort  graphics/text.h: *115
tf_Flags         unsigned char in struct TextFont +0x0017 graphics/text.h: *96
tf_HiChar        unsigned char in struct TextFont +0x0021 graphics/text.h: *104
tf_LoChar        unsigned char in struct TextFont +0x0020 graphics/text.h: *103
tf_Message       struct Message(size 0x0014 bytes) in struct TextFont
         +0x0000 graphics/text.h: *92
tf_Modulo        unsigned short int in struct TextFont
         +0x0026 graphics/text.h: *107
tf_Style         unsigned char in struct TextFont +0x0016 graphics/text.h: *95
tf_XSize         unsigned short int in struct TextFont
         +0x0018 graphics/text.h: *97
tf_YSize         unsigned short int in struct TextFont
         +0x0014 graphics/text.h: *94
tfc_FileName     array [254] of char in struct TFontContents
         +0x0000 libraries/diskfont.h: *38
tfc_Flags        unsigned char in struct TFontContents
         +0x0103 libraries/diskfont.h: *47
tfc_Style        unsigned char in struct TFontContents
         +0x0102 libraries/diskfont.h: *46
tfc_TagCount     unsigned short int in struct TFontContents
         +0x00fe libraries/diskfont.h: *39
tfc_YSize        unsigned short int in struct TFontContents
         +0x0100 libraries/diskfont.h: *45
tfe_BackPtr      pointer to struct TextFont in struct TextFontExtension
         +0x0004 graphics/text.h: *125
tfe_Flags0       unsigned char in struct TextFontExtension
         +0x0002 graphics/text.h: *123
tfe_Flags1       unsigned char in struct TextFontExtension
         +0x0003 graphics/text.h: *124
tfe_MatchWord    unsigned short int in struct TextFontExtension
         +0x0000 graphics/text.h: *122
tfe_OFontPatchK pointer to unsigned short int in struct TextFontExtension
         +0x0014 graphics/text.h: *129
tfe_OFontPatchS pointer to unsigned short int in struct TextFontExtension
         +0x0010 graphics/text.h: *128
tfe_OrigReplyPort pointer to struct MsgPort in struct TextFontExtension
         +0x0008 graphics/text.h: *126
tfe_Tags         pointer to struct TagItem in struct TextFontExtension
         +0x000c graphics/text.h: *127
ti_Data          unsigned long int in struct TagItem
         +0x0004 utility/tagitem.h: *34
ti_Tag           unsigned long int in struct TagItem
         +0x0000 utility/tagitem.h: *33
timerequest      structure tag size 0x0028 devices/timer.h: *37
                 dos/dosextens.h: 236
                 devices/prtbase.h: 91
timeval          structure tag size 0x0008 devices/timer.h: *27, 39
                 devices/inputevent.h: 218
                 intuition/preferences.h: 56, 57, 58
timsrv           struct Interrupt(size 0x0016 bytes) in struct GfxBase
         +0x0060 graphics/gfxbase.h: *36
top_layer        pointer to struct Layer in struct Layer_Info
         +0x0000 graphics/layers.h: *36
topmost          short int in struct GelsInfo +0x001a graphics/rastport.h: *52
total_colorclocks unsigned short int in struct MonitorSpec
         +0x0024 graphics/monitor.h: *34
total_rows       unsigned short int in struct MonitorSpec
         +0x0022 graphics/monitor.h: *33
tr_node          struct IORequest(size 0x0020 bytes) in struct timerequest
         +0x0000 devices/timer.h: *38
tr_time          struct timeval(size 0x0008 bytes) in struct timerequest
         +0x0020 devices/timer.h: *39
trunc            macro (1 argument)   libraries/mathffp.h: *31
                 libraries/mathieeedp.h: *31
tta_Flags        unsigned char in struct TTextAttr +0x0007 graphics/text.h: *78
tta_Name         pointer to unsigned char in struct TTextAttr
         +0x0000 graphics/text.h: *75
tta_Style        unsigned char in struct TTextAttr +0x0006 graphics/text.h: *77
tta_Tags         pointer to struct TagItem in struct TTextAttr
         +0x0008 graphics/text.h: *79
tta_YSize        unsigned short int in struct TTextAttr
         +0x0004 graphics/text.h: *76
tv_micro         unsigned long int in struct timeval
         +0x0004 devices/timer.h: *29
tv_secs          unsigned long int in struct timeval
         +0x0000 devices/timer.h: *28
TAGFILTER_AND    #define 0 = 0x00000000  utility/tagitem.h: *54
TAGFILTER_NOT    #define 1 = 0x00000001  utility/tagitem.h: *55
TAG_DONE         #define (0L) = 0x00000000  utility/tagitem.h: *38
TAG_END          #define TAG_DONE = 0x00000000  utility/tagitem.h: *39
TAG_IGNORE       #define (1L) = 0x00000001  utility/tagitem.h: *40
TAG_MORE         #define (2L) = 0x00000002  utility/tagitem.h: *43
TAG_SKIP         #define (3L) = 0x00000003  utility/tagitem.h: *44
TAG_USER         #define (1L<<31) = 0x80000000  utility/tagitem.h: *47
TA_DeviceDPI     #define (1|TAG_USER) = 0x80000001  graphics/text.h: *84
TAvailFonts      structure tag size 0x000e libraries/diskfont.h: *100
TBC_HCLRTAB      #define 0 = 0x00000000  devices/console.h: *94
TBC_HCLRTABSALL  #define 3 = 0x00000003  devices/console.h: *95
TB_ETASK         #define 3 = 0x00000003  exec/tasks.h: *53
TB_EXCEPT        #define 5 = 0x00000005  exec/tasks.h: *55
TB_LAUNCH        #define 7 = 0x00000007  exec/tasks.h: *57
TB_PROCTIME      #define 0 = 0x00000000  exec/tasks.h: *52
TB_STACKCHK      #define 4 = 0x00000004  exec/tasks.h: *54
TB_SWITCH        #define 6 = 0x00000006  exec/tasks.h: *56
TDB_ALLOW_NON_3_5 #define 0 = 0x00000000  devices/trackdisk.h: *193
TDERR_BadDriveType #define 33 = 0x00000021  devices/trackdisk.h: *228
TDERR_BadHdrSum  #define 24 = 0x00000018  devices/trackdisk.h: *219
TDERR_BadSecHdr  #define 27 = 0x0000001b  devices/trackdisk.h: *222
TDERR_BadSecID   #define 23 = 0x00000017  devices/trackdisk.h: *218
TDERR_BadSecPreamble #define 22 = 0x00000016  devices/trackdisk.h: *217
TDERR_BadSecSum  #define 25 = 0x00000019  devices/trackdisk.h: *220
TDERR_BadUnitNum #define 32 = 0x00000020  devices/trackdisk.h: *227
TDERR_DiskChanged #define 29 = 0x0000001d  devices/trackdisk.h: *224
TDERR_DriveInUse #define 34 = 0x00000022  devices/trackdisk.h: *229
TDERR_NoMem      #define 31 = 0x0000001f  devices/trackdisk.h: *226
TDERR_NoSecHdr   #define 21 = 0x00000015  devices/trackdisk.h: *216
TDERR_NotSpecified #define 20 = 0x00000014  devices/trackdisk.h: *215
TDERR_PostReset  #define 35 = 0x00000023  devices/trackdisk.h: *230
TDERR_SeekError  #define 30 = 0x0000001e  devices/trackdisk.h: *225
TDERR_TooFewSecs #define 26 = 0x0000001a  devices/trackdisk.h: *221
TDERR_WriteProt  #define 28 = 0x0000001c  devices/trackdisk.h: *223
TDF_ALLOW_NON_3_5 #define (1<<0) = 0x00000001  devices/trackdisk.h: *194
TDF_EXTCOM       #define (1<<15) = 0x00008000  devices/trackdisk.h: *76
TDNestCnt        char in struct ExecBase +0x0127 exec/execbase.h: *71
TDPB_NOCLICK     #define 0 = 0x00000000  devices/trackdisk.h: *258
TDPF_NOCLICK     #define (1L << 0) = 0x00000001  devices/trackdisk.h: *259
TDU_PublicUnit   structure tag size 0x0040 devices/trackdisk.h: *240
TD_ADDCHANGEINT  #define (CMD_NONSTD+11) = 0x00000014
                 devices/trackdisk.h: *90
TD_CHANGENUM     #define (CMD_NONSTD+4) = 0x0000000d  devices/trackdisk.h: *83
TD_CHANGESTATE   #define (CMD_NONSTD+5) = 0x0000000e  devices/trackdisk.h: *84
TD_EJECT         #define (CMD_NONSTD+14) = 0x00000017
                 devices/trackdisk.h: *93
TD_FORMAT        #define (CMD_NONSTD+2) = 0x0000000b  devices/trackdisk.h: *81
TD_GETDRIVETYPE  #define (CMD_NONSTD+9) = 0x00000012  devices/trackdisk.h: *88
TD_GETGEOMETRY   #define (CMD_NONSTD+13) = 0x00000016
                 devices/trackdisk.h: *92
TD_GETNUMTRACKS  #define (CMD_NONSTD+10) = 0x00000013
                 devices/trackdisk.h: *89
TD_LABELSIZE     #define 16 = 0x00000010  devices/trackdisk.h: *185
TD_LASTCOMM      #define (CMD_NONSTD+15) = 0x00000018
                 devices/trackdisk.h: *94
TD_MOTOR         #define (CMD_NONSTD+0) = 0x00000009  devices/trackdisk.h: *79
TD_NAME          #define "trackdisk.device"  devices/trackdisk.h: *74
TD_PROTSTATUS    #define (CMD_NONSTD+6) = 0x0000000f  devices/trackdisk.h: *85
TD_RAWREAD       #define (CMD_NONSTD+7) = 0x00000010  devices/trackdisk.h: *86
TD_RAWWRITE      #define (CMD_NONSTD+8) = 0x00000011  devices/trackdisk.h: *87
TD_REMCHANGEINT  #define (CMD_NONSTD+12) = 0x00000015
                 devices/trackdisk.h: *91
TD_REMOVE        #define (CMD_NONSTD+3) = 0x0000000c  devices/trackdisk.h: *82
TD_SECSHIFT      #define 9 = 0x00000009  devices/trackdisk.h: *53
TD_SECTOR        #define 512 = 0x00000200  devices/trackdisk.h: *52
TD_SEEK          #define (CMD_NONSTD+1) = 0x0000000a  devices/trackdisk.h: *80
TE0B_NOREMFONT   #define 0 = 0x00000000  graphics/text.h: *118
TE0F_NOREMFONT   #define 0x01 = 0x00000001  graphics/text.h: *119
TEXT             typedef unsigned char  exec/types.h: *67
TEXTIDCMP        #define (NULL) = 0x00000000  libraries/gadtools.h: *82
TEXTPEN          #define (0x0002) = 0x00000002  intuition/screens.h: *84
TEXT_KIND        #define 13 = 0x0000000d  libraries/gadtools.h: *47
TFCH_ID          #define 0x0f02 = 0x00000f02  libraries/diskfont.h: *52
TF_ETASK         #define (1<<3) = 0x00000008  exec/tasks.h: *60
TF_EXCEPT        #define (1<<5) = 0x00000020  exec/tasks.h: *62
TF_LAUNCH        #define (1<<7) = 0x00000080  exec/tasks.h: *64
TF_PROCTIME      #define (1<<0) = 0x00000001  exec/tasks.h: *59
TF_STACKCHK      #define (1<<4) = 0x00000010  exec/tasks.h: *61
TF_SWITCH        #define (1<<6) = 0x00000040  exec/tasks.h: *63
TFontContents    structure tag size 0x0104 libraries/diskfont.h: *37
TICKS_PER_SECOND #define 50 = 0x00000032  dos/dos.h: *60
TIMERNAME        #define "timer.device"  devices/timer.h: *25
TOBB             macro (1 argument)   graphics/gfx.h: *24
TODA_SAFE        #define 8 = 0x00000008  graphics/gfxbase.h: *98
TOF_WaitQ        struct List(size 0x000e bytes) in struct GfxBase
         +0x00c0 graphics/gfxbase.h: *52
TOGGLESELECT     #define GACT_TOGGLESELECT = 0x00000100
                 intuition/iobsolete.h: *78
TOPAZ_EIGHTY     #define 8 = 0x00000008  intuition/preferences.h: *41
TOPAZ_SIXTY      #define 9 = 0x00000009  intuition/preferences.h: *42
TOPBORDER        #define GACT_TOPBORDER = 0x00000040
                 intuition/iobsolete.h: *75
TOPHIT           #define 1 = 0x00000001  graphics/collide.h: *32
TO_MONITOR       #define 0 = 0x00000000  graphics/monitor.h: *56
TRUE             #define 1 = 0x00000001  exec/types.h: *70
TR_ADDREQUEST    #define CMD_NONSTD = 0x00000009  devices/timer.h: *43
TR_GETSYSTIME    #define (CMD_NONSTD+1) = 0x0000000a  devices/timer.h: *44
TR_MakeBad       #define -4 = 0xfffffffc  libraries/translator.h: *20
TR_NoMem         #define -2 = 0xfffffffe  libraries/translator.h: *19
TR_NotUsed       #define -1 = 0xffffffff  libraries/translator.h: *18
TR_SETSYSTIME    #define (CMD_NONSTD+2) = 0x0000000b  devices/timer.h: *45
TS_ADDED         #define 1 = 0x00000001  exec/tasks.h: *68
TS_EXCEPT        #define 5 = 0x00000005  exec/tasks.h: *72
TS_INVALID       #define 0 = 0x00000000  exec/tasks.h: *67
TS_READY         #define 3 = 0x00000003  exec/tasks.h: *70
TS_REMOVED       #define 6 = 0x00000006  exec/tasks.h: *73
TS_RUN           #define 2 = 0x00000002  exec/tasks.h: *69
TS_WAIT          #define 4 = 0x00000004  exec/tasks.h: *71
TTextAttr        structure tag size 0x000c graphics/text.h: *74
                 libraries/diskfont.h: 102
TWO_PI           #define (((double) 2) * PI)  libraries/mathffp.h: *18
                 libraries/mathieeedp.h: *18
Tag              typedef ULONG  utility/tagitem.h: *30, 33
TagItem          structure tag size 0x0008 graphics/view.h: *128
                 utility/tagitem.h: 32
                 graphics/text.h: 79, 127
                 intuition/intuition.h: 1082
                 intuition/screens.h: 357
                 intuition/classusr.h: 80, 90
Task             structure tag size 0x005c exec/tasks.h: *26
                 exec/semaphores.h: 37, 46
                 exec/execbase.h: 63
                 dos/dosextens.h: 40
                 intuition/screens.h: 388
                 devices/prtbase.h: 93
                 dos/notify.h: 66
                 graphics/gfxbase.h: 51
                 resources/disk.h: 62
TaskExceptCode   pointer to void in struct ExecBase
         +0x0134 exec/execbase.h: *78
TaskExitCode     pointer to void in struct ExecBase
         +0x0138 exec/execbase.h: *79
TaskReady        struct List(size 0x000e bytes) in struct ExecBase
         +0x0196 exec/execbase.h: *92
TaskSigAlloc     unsigned long int in struct ExecBase
         +0x013c exec/execbase.h: *80
TaskTrapAlloc    unsigned short int in struct ExecBase
         +0x0140 exec/execbase.h: *81
TaskTrapCode     pointer to void in struct ExecBase
         +0x0130 exec/execbase.h: *77
TaskWait         struct List(size 0x000e bytes) in struct ExecBase
         +0x01a4 exec/execbase.h: *93
TermArray0       unsigned long int in struct IOTArray
         +0x0000 devices/serial.h: *23
TermArray1       unsigned long int in struct IOTArray
         +0x0004 devices/serial.h: *24
TextAttr         structure tag size 0x0008 graphics/text.h: *67
                 intuition/intuition.h: 576
                 intuition/screens.h: 124, 320, 352
                 libraries/asl.h: 148
                 libraries/diskfont.h: 97
                 libraries/gadtools.h: 99
TextExtent       structure tag size 0x000c graphics/text.h: *166
TextFont         structure tag size 0x0034 devices/conunit.h: *89
                 graphics/rastport.h: 78
                 graphics/text.h: 91, 125, 153
                 intuition/intuition.h: 895
                 intuition/screens.h: 67
                 graphics/gfxbase.h: 38
                 intuition/sghooks.h: 21
                 libraries/diskfont.h: 77
TextFontExtension structure tag size 0x0018 graphics/text.h: *121
TextFonts        struct List(size 0x000e bytes) in struct GfxBase
         +0x008c graphics/gfxbase.h: *37
ThisTask         pointer to struct Task in struct ExecBase
         +0x0114 exec/execbase.h: *63
TimeSet          short int in struct AnimComp +0x0004 graphics/gels.h: *180
Timer            short int in struct AnimComp +0x0002 graphics/gels.h: *176
Title            pointer to unsigned char in struct Window
         +0x0020 intuition/intuition.h: *811
Title            pointer to unsigned char in struct NewWindow
         +0x001a intuition/intuition.h: *998
Title            pointer to unsigned char in struct ExtNewWindow
         +0x001a intuition/intuition.h: *1056
Title            pointer to unsigned char in struct Screen
         +0x0016 intuition/screens.h: *110
TmpRas           structure tag size 0x0008 graphics/rastport.h: *34, 61
TmpRas           pointer to struct TmpRas in struct RastPort
         +0x000c graphics/rastport.h: *61
Top              short int in struct IBox +0x0002 intuition/intuition.h: *785
TopBorder        unsigned short int in struct PropInfo
         +0x0014 intuition/intuition.h: *492
TopEdge          short int in struct Menu +0x0006 intuition/intuition.h: *65
TopEdge          short int in struct MenuItem
         +0x0006 intuition/intuition.h: *93
TopEdge          short int in struct Requester
         +0x0006 intuition/intuition.h: *149
TopEdge          short int in struct Gadget +0x0006 intuition/intuition.h: *220
TopEdge          short int in struct IntuiText
         +0x0006 intuition/intuition.h: *575
TopEdge          short int in struct Border +0x0002 intuition/intuition.h: *600
TopEdge          short int in struct Image +0x0002 intuition/intuition.h: *622
TopEdge          short int in struct Window +0x0006 intuition/intuition.h: *799
TopEdge          short int in struct NewWindow
         +0x0002 intuition/intuition.h: *976
TopEdge          short int in struct ExtNewWindow
         +0x0002 intuition/intuition.h: *1046
TopEdge          short int in struct Screen +0x000a intuition/screens.h: *103
TopEdge          short int in struct NewScreen
         +0x0002 intuition/screens.h: *312
TopEdge          short int in struct ExtNewScreen
         +0x0002 intuition/screens.h: *348
TotalColorClocks unsigned short int in struct MonitorInfo
         +0x0026 graphics/displayinfo.h: *117
TotalRows        unsigned short int in struct MonitorInfo
         +0x0024 graphics/displayinfo.h: *116
TransparencyBits pointer to unsigned short int in struct ColorMap
         +0x000c graphics/view.h: *121
TransparencyPlane unsigned char in struct ColorMap
         +0x0010 graphics/view.h: *122
TxBaseline       unsigned short int in struct RastPort
         +0x003e graphics/rastport.h: *83
TxFlags          unsigned char in struct RastPort
         +0x0039 graphics/rastport.h: *80
TxHeight         unsigned short int in struct RastPort
         +0x003a graphics/rastport.h: *81
TxSpacing        short int in struct RastPort +0x0040 graphics/rastport.h: *84
TxWidth          unsigned short int in struct RastPort
         +0x003c graphics/rastport.h: *82
TxtOScan         struct Rectangle(size 0x0008 bytes) in struct DimensionInfo
         +0x0032 graphics/displayinfo.h: *103
Type             unsigned char in struct ColorMap +0x0001 graphics/view.h: *117
Type             unsigned short int in struct NewWindow
         +0x002e intuition/intuition.h: *1033
Type             unsigned short int in struct ExtNewWindow
         +0x002e intuition/intuition.h: *1071
Type             unsigned short int in struct NewScreen
         +0x000e intuition/screens.h: *318
Type             unsigned short int in struct ExtNewScreen
         +0x000e intuition/screens.h: *351


2.0 IncludeXREF: U

u1               union (no tag) (size 0x0002 bytes) in struct (no tag)
         +0x0000 graphics/copper.h: *38
u2               union (no tag) (size 0x0002 bytes) in struct (no tag)
         +0x0002 graphics/copper.h: *43
u3               union (no tag) (size 0x0004 bytes) in struct CopIns
         +0x0002 graphics/copper.h: *45
u4               struct (no tag) (size 0x0004 bytes) in union (no tag)
         +0x0000 graphics/copper.h: *44
unit_MsgPort     struct MsgPort(size 0x0022 bytes) in struct Unit
         +0x0000 exec/devices.h: *34
unit_OpenCnt     unsigned short int in struct Unit +0x0024 exec/devices.h: *38
unit_flags       unsigned char in struct Unit +0x0022 exec/devices.h: *36
unit_pad         unsigned char in struct Unit +0x0023 exec/devices.h: *37
unusedreg        unsigned char in struct CIA +0x0b00 hardware/cia.h: *54
UBYTE            unsigned char  exec/types.h: *49
UCOUNT           unsigned short int  exec/types.h: *59
UCopIns          pointer to struct UCopList in struct ViewPort
         +0x0014 graphics/view.h: *49
UCopList         structure tag size 0x000c graphics/copper.h: *83, 85
                 graphics/view.h: 49
ULONG            unsigned long int  exec/types.h: *39
UNITF_ACTIVE     #define (1<<0) = 0x00000001  exec/devices.h: *42
UNITF_INTASK     #define (1<<1) = 0x00000002  exec/devices.h: *43
UNIT_ECLOCK      #define 2 = 0x00000002  devices/timer.h: *21
UNIT_MICROHZ     #define 0 = 0x00000000  devices/timer.h: *19
UNIT_VBLANK      #define 1 = 0x00000001  devices/timer.h: *20
UNIT_WAITECLOCK  #define 4 = 0x00000004  devices/timer.h: *23
UNIT_WAITUNTIL   #define 3 = 0x00000003  devices/timer.h: *22
UPFRONTGADGET    #define 0 = 0x00000000  intuition/intuitionbase.h: *47
UPIMAGE          #define (0x0BL) = 0x0000000b  intuition/imageclass.h: *107
USEREQIMAGE      #define 0x0020 = 0x00000020  intuition/intuition.h: *194
USER_COPPER_CLIP #define 0x20 = 0x00000020  graphics/view.h: *145
USE_BPLCON3      #define 1 = 0x00000001  hardware/custom.h: *162
USHORT           unsigned short int  exec/types.h: *57
US_LEGAL         #define 0x10 = 0x00000010  intuition/preferences.h: *186
US_LETTER        #define 0x00 = 0x00000000  intuition/preferences.h: *185
UTILITY_DATE_H   #define 1 = 0x00000001  utility/date.h: *2
UTILITY_HOOKS_H  #define TRUE = 0x00000001  utility/hooks.h: *2, 1
                 dos/exall.h: 19
                 intuition/classes.h: 15
                 intuition/classusr.h: 16
                 libraries/asl.h: 28
UTILITY_TAGITEM_H #define TRUE = 0x00000001  utility/tagitem.h: *2, 1
                 intuition/intuition.h: 51
                 intuition/screens.h: 39
                 dos/dostags.h: 17
                 graphics/displayinfo.h: 27
                 graphics/videocontrol.h: 19
                 intuition/gadgetclass.h: 23
                 intuition/icclass.h: 16
                 intuition/imageclass.h: 16
                 libraries/asl.h: 32
                 libraries/gadtools.h: 21
UWORD            unsigned short int  exec/types.h: *42
UnReadChar       macro (1 argument)   dos/stdio.h: *19
UndoBuffer       pointer to unsigned char in struct StringInfo
         +0x0004 intuition/intuition.h: *528
UndoPos          short int in struct StringInfo
         +0x000e intuition/intuition.h: *534
Unit             structure tag size 0x0026 exec/devices.h: *33
                 exec/io.h: 23, 32
                 devices/printer.h: 145, 159
                 devices/trackdisk.h: 241
UserData         pointer to void in struct Gadget
         +0x0028 intuition/intuition.h: *261
UserData         pointer to char in struct Window
         +0x0078 intuition/intuition.h: *885
UserData         pointer to unsigned char in struct Screen
         +0x0156 intuition/screens.h: *149
UserPort         pointer to struct MsgPort in struct Window
         +0x0056 intuition/intuition.h: *856
UtilityBase      pointer to unsigned long int in struct GfxBase
         +0x019e graphics/gfxbase.h: *91


2.0 IncludeXREF: V

_ViewPort        pointer to struct ViewPort in struct CopList
         +0x0008 graphics/copper.h: *67
vblank           struct AnalogSignalInterval(size 0x0004 bytes) in struct
                 SpecialMonitor
         +0x002e graphics/monitor.h: *151
vbsrv            struct Interrupt(size 0x0016 bytes) in struct GfxBase
         +0x004a graphics/gfxbase.h: *36
vbstop           unsigned short int in struct Custom
         +0x01ce hardware/custom.h: *130
vbstrt           unsigned short int in struct Custom
         +0x01cc hardware/custom.h: *129
vhposr           unsigned short int in struct Custom
         +0x0006 hardware/custom.h: *31
vhposw           unsigned short int in struct Custom
         +0x002c hardware/custom.h: *49
voice            struct narrator_rb(size 0x0058 bytes) in struct mouth_rb
         +0x0000 devices/narrator.h: *129
volume           unsigned short int in struct narrator_rb
         +0x003e devices/narrator.h: *101
vposr            unsigned short int in struct Custom
         +0x0004 hardware/custom.h: *30
vposw            unsigned short int in struct Custom
         +0x002a hardware/custom.h: *48
vsstop           unsigned short int in struct Custom
         +0x01ca hardware/custom.h: *128
vsstrt           unsigned short int in struct Custom
         +0x01e0 hardware/custom.h: *139
vsync            struct AnalogSignalInterval(size 0x0004 bytes) in struct
                 SpecialMonitor
         +0x0036 graphics/monitor.h: *153
vsync_hblank     array [2] of unsigned short int in struct copinit
         +0x0000 graphics/copper.h: *94
vtotal           unsigned short int in struct Custom
         +0x01c8 hardware/custom.h: *127
VANILLAKEY       #define IDCMP_VANILLAKEY = 0x00200000
                 intuition/iobsolete.h: *135
VARBEAM          #define 0x0080 = 0x00000080  hardware/custom.h: *152
VARCSYNC         #define 0x0010 = 0x00000010  hardware/custom.h: *155
VARHSYNC         #define 0x0100 = 0x00000100  hardware/custom.h: *151
VARVBLANK        #define 0x1000 = 0x00001000  hardware/custom.h: *147
VARVSYNC         #define 0x0200 = 0x00000200  hardware/custom.h: *150
VBlank           char in struct GfxBase +0x00a0 graphics/gfxbase.h: *40
VBlankFrequency unsigned char in struct ExecBase +0x0212 exec/execbase.h: *111
VGA70_BEAMCON    #define (SPECIAL_BEAMCON ^ VSYNCTRUE) = 0x00001a8a
                 graphics/monitor.h: *121
VGA70_COLORCLOCKS #define (STANDARD_COLORCLOCKS/2) = 0x00000071
                 graphics/monitor.h: *108
VGA70_DENISE_MIN #define 59 = 0x0000003b  graphics/monitor.h: *110
VGA70_HBSTOP     #define 0x1E = 0x0000001e  graphics/monitor.h: *115
VGA70_HBSTRT     #define 0x08 = 0x00000008  graphics/monitor.h: *112
VGA70_HSSTOP     #define 0x1C = 0x0000001c  graphics/monitor.h: *114
VGA70_HSSTRT     #define 0x0E = 0x0000000e  graphics/monitor.h: *113
VGA70_MONITOR_NAME #define "vga70.monitor"  graphics/monitor.h: *122
VGA70_TOTAL_ROWS #define 449 = 0x000001c1  graphics/monitor.h: *109
VGA70_VBSTOP     #define 0x0F73 = 0x00000f73  graphics/monitor.h: *119
VGA70_VBSTRT     #define 0x0000 = 0x00000000  graphics/monitor.h: *116
VGA70_VSSTOP     #define 0x0388 = 0x00000388  graphics/monitor.h: *118
VGA70_VSSTRT     #define 0x02A6 = 0x000002a6  graphics/monitor.h: *117
VGAEXTRAHALFBRITELACE_KEY #define 0x00031085 = 0x00031085
                 graphics/displayinfo.h: *203
VGAEXTRAHALFBRITE_KEY #define 0x00031084 = 0x00031084
                 graphics/displayinfo.h: *202
VGAEXTRALORESDPF2_KEY #define 0x00031444 = 0x00031444
                 graphics/displayinfo.h: *196
VGAEXTRALORESDPF_KEY #define 0x00031404 = 0x00031404
                 graphics/displayinfo.h: *190
VGAEXTRALORESLACEDPF2_KEY #define 0x00031445 = 0x00031445
                 graphics/displayinfo.h: *199
VGAEXTRALORESLACEDPF_KEY #define 0x00031405 = 0x00031405
                 graphics/displayinfo.h: *193
VGAEXTRALORESLACE_KEY #define 0x00031005 = 0x00031005
                 graphics/displayinfo.h: *186
VGAEXTRALORES_KEY #define 0x00031004 = 0x00031004
                 graphics/displayinfo.h: *182
VGAHAMLACE_KEY   #define 0x00031805 = 0x00031805  graphics/displayinfo.h: *189
VGAHAM_KEY       #define 0x00031804 = 0x00031804  graphics/displayinfo.h: *185
VGALORESDPF2_KEY #define 0x00039444 = 0x00039444  graphics/displayinfo.h: *197
VGALORESDPF_KEY  #define 0x00039404 = 0x00039404  graphics/displayinfo.h: *191
VGALORESLACEDPF2_KEY #define 0x00039445 = 0x00039445
                 graphics/displayinfo.h: *200
VGALORESLACEDPF_KEY #define 0x00039405 = 0x00039405
                 graphics/displayinfo.h: *194
VGALORESLACE_KEY #define 0x00039005 = 0x00039005  graphics/displayinfo.h: *187
VGALORES_KEY     #define 0x00039004 = 0x00039004  graphics/displayinfo.h: *183
VGAPRODUCTDPF2_KEY #define 0x00039464 = 0x00039464
                 graphics/displayinfo.h: *198
VGAPRODUCTDPF_KEY #define 0x00039424 = 0x00039424
                 graphics/displayinfo.h: *192
VGAPRODUCTLACEDPF2_KEY #define 0x00039465 = 0x00039465
                 graphics/displayinfo.h: *201
VGAPRODUCTLACEDPF_KEY #define 0x00039425 = 0x00039425
                 graphics/displayinfo.h: *195
VGAPRODUCTLACE_KEY #define 0x00039025 = 0x00039025
                 graphics/displayinfo.h: *188
VGAPRODUCT_KEY   #define 0x00039024 = 0x00039024  graphics/displayinfo.h: *184
VGA_COLORCLOCKS  #define (STANDARD_COLORCLOCKS/2) = 0x00000071
                 graphics/monitor.h: *93
VGA_DENISE_MIN   #define 59 = 0x0000003b  graphics/monitor.h: *95
VGA_HBSTOP       #define 0x1E = 0x0000001e  graphics/monitor.h: *100
VGA_HBSTRT       #define 0x08 = 0x00000008  graphics/monitor.h: *97
VGA_HSSTOP       #define 0x1C = 0x0000001c  graphics/monitor.h: *99
VGA_HSSTRT       #define 0x0E = 0x0000000e  graphics/monitor.h: *98
VGA_MONITOR_ID   #define 0x00031000 = 0x00031000  graphics/displayinfo.h: *180
VGA_MONITOR_NAME #define "vga.monitor"  graphics/monitor.h: *106
VGA_TOTAL_ROWS   #define (STANDARD_NTSC_ROWS*2) = 0x0000020c
                 graphics/monitor.h: *94
VGA_VBSTOP       #define 0x0CCD = 0x00000ccd  graphics/monitor.h: *104
VGA_VBSTRT       #define 0x0000 = 0x00000000  graphics/monitor.h: *101
VGA_VSSTOP       #define 0x0235 = 0x00000235  graphics/monitor.h: *103
VGA_VSSTRT       #define 0x0153 = 0x00000153  graphics/monitor.h: *102
VIDEOCONTROL_BATCH #define 0x10 = 0x00000010  graphics/view.h: *144
VIEWPORT_EXTRA_TYPE #define 2 = 0x00000002  graphics/gfxnodes.h: *34
VIEW_EXTRA_TYPE  #define 1 = 0x00000001  graphics/gfxnodes.h: *33
VISITOR          #define WFLG_VISITOR = 0x08000000
                 intuition/iobsolete.h: *170
VOID             #define void  exec/types.h: *27
VPF_A2024        #define 0x40 = 0x00000040  graphics/view.h: *103
VPF_AGNUS        #define 0x20 = 0x00000020  graphics/view.h: *104
VPF_TENHZ        #define 0x20 = 0x00000020  graphics/view.h: *105
VPModeID         unsigned long int in struct ColorMap
         +0x0024 graphics/view.h: *129
VPOSRLOF         #define 0x8000 = 0x00008000  graphics/display.h: *40
VP_HIDE          #define 0x2000 = 0x00002000  graphics/view.h: *99
VPotRes          unsigned short int in struct PropInfo
         +0x0010 intuition/intuition.h: *490
VSBob            pointer to struct Bob in struct VSprite
         +0x0034 graphics/gels.h: *116
VSIZEBITS        #define 16-HSIZEBITS = 0x0000000a  hardware/blit.h: *16
VSIZEMASK        #define 0x3FF = 0x000003ff  hardware/blit.h: *18
VSOVERFLOW       #define 0x0800 = 0x00000800  graphics/gels.h: *30
VSPRITE          #define 0x0001 = 0x00000001  graphics/gels.h: *22
VSYNCTRUE        #define 0x0002 = 0x00000002  hardware/custom.h: *158
VSprite          structure tag size 0x003c graphics/rastport.h: *46
                 graphics/gels.h: 70, 74, 75, 81, 82, 156, 233
VTAG_ATTACH_CM_GET #define 0x8000001B = 0x8000001b
                 graphics/videocontrol.h: *51
VTAG_ATTACH_CM_SET #define 0x8000000B = 0x8000000b
                 graphics/videocontrol.h: *35
VTAG_BATCH_CM_CLR #define 0x8000000D = 0x8000000d
                 graphics/videocontrol.h: *37
VTAG_BATCH_CM_GET #define 0x8000001C = 0x8000001c
                 graphics/videocontrol.h: *52
VTAG_BATCH_CM_SET #define 0x8000000E = 0x8000000e
                 graphics/videocontrol.h: *38
VTAG_BATCH_ITEMS_ADD #define 0x8000001F = 0x8000001f
                 graphics/videocontrol.h: *55
VTAG_BATCH_ITEMS_GET #define 0x8000001D = 0x8000001d
                 graphics/videocontrol.h: *53
VTAG_BATCH_ITEMS_SET #define 0x8000001E = 0x8000001e
                 graphics/videocontrol.h: *54
VTAG_BITPLANEKEY_CLR #define 0x80000002 = 0x80000002
                 graphics/videocontrol.h: *26
VTAG_BITPLANEKEY_GET #define 0x80000016 = 0x80000016
                 graphics/videocontrol.h: *46
VTAG_BITPLANEKEY_SET #define 0x80000003 = 0x80000003
                 graphics/videocontrol.h: *27
VTAG_BORDERBLANK_CLR #define 0x80000004 = 0x80000004
                 graphics/videocontrol.h: *28
VTAG_BORDERBLANK_GET #define 0x80000017 = 0x80000017
                 graphics/videocontrol.h: *47
VTAG_BORDERBLANK_SET #define 0x80000005 = 0x80000005
                 graphics/videocontrol.h: *29
VTAG_BORDERNOTRANS_CLR #define 0x80000006 = 0x80000006
                 graphics/videocontrol.h: *30
VTAG_BORDERNOTRANS_GET #define 0x80000018 = 0x80000018
                 graphics/videocontrol.h: *48
VTAG_BORDERNOTRANS_SET #define 0x80000007 = 0x80000007
                 graphics/videocontrol.h: *31
VTAG_CHROMAKEY_CLR #define 0x80000000 = 0x80000000
                 graphics/videocontrol.h: *24
VTAG_CHROMAKEY_GET #define 0x80000015 = 0x80000015
                 graphics/videocontrol.h: *45
VTAG_CHROMAKEY_SET #define 0x80000001 = 0x80000001
                 graphics/videocontrol.h: *25
VTAG_CHROMA_PEN_CLR #define 0x80000008 = 0x80000008
                 graphics/videocontrol.h: *32
VTAG_CHROMA_PEN_GET #define 0x80000019 = 0x80000019
                 graphics/videocontrol.h: *49
VTAG_CHROMA_PEN_SET #define 0x80000009 = 0x80000009
                 graphics/videocontrol.h: *33
VTAG_CHROMA_PLANE_GET #define 0x8000001A = 0x8000001a
                 graphics/videocontrol.h: *50
VTAG_CHROMA_PLANE_SET #define 0x8000000A = 0x8000000a
                 graphics/videocontrol.h: *34
VTAG_COERCE_DISP_GET #define 0x80000011 = 0x80000011
                 graphics/videocontrol.h: *41
VTAG_COERCE_DISP_SET #define 0x80000012 = 0x80000012
                 graphics/videocontrol.h: *42
VTAG_END_CM      #define 0x00000000 = 0x00000000  graphics/videocontrol.h: *23
VTAG_NEXTBUF_CM  #define 0x8000000C = 0x8000000c  graphics/videocontrol.h: *36
VTAG_NORMAL_DISP_GET #define 0x8000000F = 0x8000000f
                 graphics/videocontrol.h: *39
VTAG_NORMAL_DISP_SET #define 0x80000010 = 0x80000010
                 graphics/videocontrol.h: *40
VTAG_USERCLIP_CLR #define 0x80000025 = 0x80000025
                 graphics/videocontrol.h: *61
VTAG_USERCLIP_GET #define 0x80000023 = 0x80000023
                 graphics/videocontrol.h: *59
VTAG_USERCLIP_SET #define 0x80000024 = 0x80000024
                 graphics/videocontrol.h: *60
VTAG_VIEWPORTEXTRA_GET #define 0x80000013 = 0x80000013
                 graphics/videocontrol.h: *43
VTAG_VIEWPORTEXTRA_SET #define 0x80000014 = 0x80000014
                 graphics/videocontrol.h: *44
VTAG_VPMODEID_CLR #define 0x80000022 = 0x80000022
                 graphics/videocontrol.h: *58
VTAG_VPMODEID_GET #define 0x80000020 = 0x80000020
                 graphics/videocontrol.h: *56
VTAG_VPMODEID_SET #define 0x80000021 = 0x80000021
                 graphics/videocontrol.h: *57
VUserExt         short int in struct VSprite +0x003a graphics/gels.h: *133
VUserStuff       #define WORD  graphics/gels.h: *56, 133
VWAITPOS         #define u3.u4.u1.VWaitPos  graphics/copper.h: *49
VWaitPos         short int in union (no tag)  +0x0000 graphics/copper.h: *36
VWritef          macro (2 arguments)   dos/stdio.h: *24
VctrPtr          pointer to short int in struct AreaInfo
         +0x0004 graphics/rastport.h: *26
VctrTbl          pointer to short int in struct AreaInfo
         +0x0000 graphics/rastport.h: *25
VertBody         unsigned short int in struct PropInfo
         +0x0008 intuition/intuition.h: *485
VertPot          unsigned short int in struct PropInfo
         +0x0004 intuition/intuition.h: *465
VideoOScan       struct Rectangle(size 0x0008 bytes) in struct DimensionInfo
         +0x002a graphics/displayinfo.h: *102
View             structure tag size 0x0012 graphics/view.h: *58, 73
                 graphics/gfxbase.h: 28
                 intuition/intuitionbase.h: 72
View             pointer to struct View in struct ViewExtra
         +0x0018 graphics/view.h: *73
ViewExtra        structure tag size 0x0020 graphics/view.h: *70
ViewInitX        short int in struct Preferences
         +0x0078 intuition/preferences.h: *78
ViewInitY        short int in struct Preferences
         +0x007a intuition/preferences.h: *78
ViewLord         struct View(size 0x0012 bytes) in struct IntuitionBase
         +0x0022 intuition/intuitionbase.h: *72
ViewModes        unsigned short int in struct NewScreen
         +0x000c intuition/screens.h: *316
ViewModes        unsigned short int in struct ExtNewScreen
         +0x000c intuition/screens.h: *350
ViewPort         structure tag size 0x0028 graphics/copper.h: *67
                 graphics/view.h: 41, 43, 60, 82, 125
                 intuition/screens.h: 127
ViewPort         pointer to struct ViewPort in struct View
         +0x0000 graphics/view.h: *60
ViewPort         pointer to struct ViewPort in struct ViewPortExtra
         +0x0018 graphics/view.h: *82
ViewPort         struct ViewPort(size 0x0028 bytes) in struct Screen
         +0x002c intuition/screens.h: *127
ViewPortExtra    structure tag size 0x0024 graphics/view.h: *79, 120
ViewPosition     struct tPoint(size 0x0004 bytes) in struct MonitorInfo
         +0x0014 graphics/displayinfo.h: *113
ViewPositionRange struct Rectangle(size 0x0008 bytes) in struct MonitorInfo
         +0x001c graphics/displayinfo.h: *115
ViewResolution   struct tPoint(size 0x0004 bytes) in struct MonitorInfo
         +0x0018 graphics/displayinfo.h: *114
ViewXOffset      char in struct Preferences
         +0x0076 intuition/preferences.h: *76
ViewYOffset      char in struct Preferences
         +0x0077 intuition/preferences.h: *77


2.0 IncludeXREF: W

wa_Lock          long int in struct WBArg +0x0000 workbench/startup.h: *37
wa_Name          pointer to char in struct WBArg
         +0x0004 workbench/startup.h: *38
wait14           array [2] of unsigned short int in struct copinit
         +0x0054 graphics/copper.h: *98
wait_forever     array [2] of unsigned short int in struct copinit
         +0x006c graphics/copper.h: *102
wb_Depth         unsigned char in struct Preferences
         +0x00e6 intuition/preferences.h: *125
wb_Height        unsigned short int in struct Preferences
         +0x00e4 intuition/preferences.h: *124
wb_Width         unsigned short int in struct Preferences
         +0x00e2 intuition/preferences.h: *123
wday             unsigned short int in struct ClockData
         +0x000c utility/date.h: *26
width            unsigned char in struct mouth_rb
         +0x0058 devices/narrator.h: *130
wordreserved     array [7] of unsigned short int in struct RastPort
         +0x004e graphics/rastport.h: *88
WA_Activate      #define (WA_Dummy + 0x26) = 0x80000089
                 intuition/intuition.h: *1189
WA_AutoAdjust    #define (WA_Dummy + 0x2D) = 0x80000090
                 intuition/intuition.h: *1200
WA_BackFill      #define (WA_Dummy + 0x1C) = 0x8000007f
                 intuition/intuition.h: *1171
WA_Backdrop      #define (WA_Dummy + 0x22) = 0x80000085
                 intuition/intuition.h: *1185
WA_BlockPen      #define (WA_Dummy + 0x06) = 0x80000069
                 intuition/intuition.h: *1100
WA_Borderless    #define (WA_Dummy + 0x25) = 0x80000088
                 intuition/intuition.h: *1188
WA_Checkmark     #define (WA_Dummy + 0x0A) = 0x8000006d
                 intuition/intuition.h: *1105
WA_CloseGadget   #define (WA_Dummy + 0x21) = 0x80000084
                 intuition/intuition.h: *1184
WA_Colors        #define (WA_Dummy + 0x19) = 0x8000007c
                 intuition/intuition.h: *1151
WA_CustomScreen  #define (WA_Dummy + 0x0D) = 0x80000070
                 intuition/intuition.h: *1111
WA_DepthGadget   #define (WA_Dummy + 0x20) = 0x80000083
                 intuition/intuition.h: *1183
WA_DetailPen     #define (WA_Dummy + 0x05) = 0x80000068
                 intuition/intuition.h: *1099
WA_DragBar       #define (WA_Dummy + 0x1F) = 0x80000082
                 intuition/intuition.h: *1182
WA_Dummy         #define (TAG_USER + 99) = 0x80000063
                 intuition/intuition.h: *1092
WA_Flags         #define (WA_Dummy + 0x08) = 0x8000006b
                 intuition/intuition.h: *1103
WA_Gadgets       #define (WA_Dummy + 0x09) = 0x8000006c
                 intuition/intuition.h: *1104
WA_GimmeZeroZero #define (WA_Dummy + 0x2E) = 0x80000091
                 intuition/intuition.h: *1205
WA_Height        #define (WA_Dummy + 0x04) = 0x80000067
                 intuition/intuition.h: *1098
WA_IDCMP         #define (WA_Dummy + 0x07) = 0x8000006a
                 intuition/intuition.h: *1101
WA_InnerHeight   #define (WA_Dummy + 0x14) = 0x80000077
                 intuition/intuition.h: *1122
WA_InnerWidth    #define (WA_Dummy + 0x13) = 0x80000076
                 intuition/intuition.h: *1121
WA_Left          #define (WA_Dummy + 0x01) = 0x80000064
                 intuition/intuition.h: *1095
WA_MaxHeight     #define (WA_Dummy + 0x12) = 0x80000075
                 intuition/intuition.h: *1117
WA_MaxWidth      #define (WA_Dummy + 0x11) = 0x80000074
                 intuition/intuition.h: *1116
WA_MenuHelp      #define (WA_Dummy + 0x2F) = 0x80000092
                 intuition/intuition.h: *1209
WA_MinHeight     #define (WA_Dummy + 0x10) = 0x80000073
                 intuition/intuition.h: *1115
WA_MinWidth      #define (WA_Dummy + 0x0F) = 0x80000072
                 intuition/intuition.h: *1114
WA_MouseQueue    #define (WA_Dummy + 0x1B) = 0x8000007e
                 intuition/intuition.h: *1167
WA_NoCareRefresh #define (WA_Dummy + 0x24) = 0x80000087
                 intuition/intuition.h: *1187
WA_PubScreen     #define (WA_Dummy + 0x16) = 0x80000079
                 intuition/intuition.h: *1136
WA_PubScreenFallBack #define (WA_Dummy + 0x17) = 0x8000007a
                 intuition/intuition.h: *1143
WA_PubScreenName #define (WA_Dummy + 0x15) = 0x80000078
                 intuition/intuition.h: *1131
WA_RMBTrap       #define (WA_Dummy + 0x27) = 0x8000008a
                 intuition/intuition.h: *1190
WA_ReportMouse   #define (WA_Dummy + 0x23) = 0x80000086
                 intuition/intuition.h: *1186
WA_RptQueue      #define (WA_Dummy + 0x1D) = 0x80000080
                 intuition/intuition.h: *1175
WA_ScreenTitle   #define (WA_Dummy + 0x0C) = 0x8000006f
                 intuition/intuition.h: *1110
WA_SimpleRefresh #define (WA_Dummy + 0x29) = 0x8000008c
                 intuition/intuition.h: *1192
WA_SizeBBottom   #define (WA_Dummy + 0x2C) = 0x8000008f
                 intuition/intuition.h: *1197
WA_SizeBRight    #define (WA_Dummy + 0x2B) = 0x8000008e
                 intuition/intuition.h: *1196
WA_SizeGadget    #define (WA_Dummy + 0x1E) = 0x80000081
                 intuition/intuition.h: *1181
WA_SmartRefresh  #define (WA_Dummy + 0x2A) = 0x8000008d
                 intuition/intuition.h: *1194
WA_SuperBitMap   #define (WA_Dummy + 0x0E) = 0x80000071
                 intuition/intuition.h: *1112
WA_Title         #define (WA_Dummy + 0x0B) = 0x8000006e
                 intuition/intuition.h: *1106
WA_Top           #define (WA_Dummy + 0x02) = 0x80000065
                 intuition/intuition.h: *1096
WA_WBenchWindow  #define (WA_Dummy + 0x28) = 0x8000008b
                 intuition/intuition.h: *1191
WA_Width         #define (WA_Dummy + 0x03) = 0x80000066
                 intuition/intuition.h: *1097
WA_WindowName    #define (WA_Dummy + 0x18) = 0x8000007b
                 intuition/intuition.h: *1149
WA_Zoom          #define (WA_Dummy + 0x1A) = 0x8000007d
                 intuition/intuition.h: *1159
WBAPPICON        #define 8 = 0x00000008  workbench/workbench.h: *42
WBArg            structure tag size 0x0008 workbench/startup.h: *33, 36
                 libraries/asl.h: 77
                 workbench/workbench.h: 132
WBDEVICE         #define 6 = 0x00000006  workbench/workbench.h: *40
WBDISK           #define 1 = 0x00000001  workbench/workbench.h: *35
WBDRAWER         #define 2 = 0x00000002  workbench/workbench.h: *36
WBENCHCLOSE      #define 0x0002 = 0x00000002  intuition/intuition.h: *779
WBENCHMESSAGE    #define IDCMP_WBENCHMESSAGE = 0x00020000
                 intuition/iobsolete.h: *131
WBENCHOPEN       #define 0x0001 = 0x00000001  intuition/intuition.h: *778
WBENCHSCREEN     #define 0x0001 = 0x00000001  intuition/screens.h: *161
WBENCHWINDOW     #define WFLG_WBENCHWINDOW = 0x02000000
                 intuition/iobsolete.h: *167
WBGARBAGE        #define 5 = 0x00000005  workbench/workbench.h: *39
WBKICK           #define 7 = 0x00000007  workbench/workbench.h: *41
WBPROJECT        #define 4 = 0x00000004  workbench/workbench.h: *38
WBStartup        structure tag size 0x0028 workbench/startup.h: *27
WBTOOL           #define 3 = 0x00000003  workbench/workbench.h: *37
WB_DISKMAGIC     #define 0xe310 = 0x0000e310  workbench/workbench.h: *77
WB_DISKREVISION  #define 1 = 0x00000001  workbench/workbench.h: *79
WB_DISKREVISIONMASK #define 255 = 0x000000ff  workbench/workbench.h: *81
WB_DISKVERSION   #define 1 = 0x00000001  workbench/workbench.h: *78
WBorBottom       char in struct Screen +0x0026 intuition/screens.h: *122
WBorLeft         char in struct Screen +0x0024 intuition/screens.h: *122
WBorRight        char in struct Screen +0x0025 intuition/screens.h: *122
WBorTop          char in struct Screen +0x0023 intuition/screens.h: *122
WDOWNBACK        #define GTYP_WDOWNBACK = 0x00000060
                 intuition/iobsolete.h: *101
WDRAGGING        #define GTYP_WDRAGGING = 0x00000020
                 intuition/iobsolete.h: *97
WFLG_ACTIVATE    #define 0x00001000 = 0x00001000  intuition/intuition.h: *932
WFLG_BACKDROP    #define 0x00000100 = 0x00000100  intuition/intuition.h: *924
WFLG_BORDERLESS  #define 0x00000800 = 0x00000800  intuition/intuition.h: *930
WFLG_CLOSEGADGET #define 0x00000008 = 0x00000008  intuition/intuition.h: *911
WFLG_DEPTHGADGET #define 0x00000004 = 0x00000004  intuition/intuition.h: *910
WFLG_DRAGBAR     #define 0x00000002 = 0x00000002  intuition/intuition.h: *909
WFLG_GIMMEZEROZERO #define 0x00000400 = 0x00000400
                 intuition/intuition.h: *928
WFLG_HASZOOM     #define 0x20000000 = 0x20000000  intuition/intuition.h: *957
WFLG_INREQUEST   #define 0x00004000 = 0x00004000  intuition/intuition.h: *937
WFLG_MENUSTATE   #define 0x00008000 = 0x00008000  intuition/intuition.h: *938
WFLG_NOCAREREFRESH #define 0x00020000 = 0x00020000
                 intuition/intuition.h: *942
WFLG_NW_EXTENDED #define 0x00040000 = 0x00040000  intuition/intuition.h: *951
WFLG_OTHER_REFRESH #define 0x000000C0 = 0x000000c0
                 intuition/intuition.h: *922
WFLG_REFRESHBITS #define 0x000000C0 = 0x000000c0  intuition/intuition.h: *918
WFLG_REPORTMOUSE #define 0x00000200 = 0x00000200  intuition/intuition.h: *926
WFLG_RMBTRAP     #define 0x00010000 = 0x00010000  intuition/intuition.h: *941
WFLG_SIMPLE_REFRESH #define 0x00000040 = 0x00000040
                 intuition/intuition.h: *920
WFLG_SIZEBBOTTOM #define 0x00000020 = 0x00000020  intuition/intuition.h: *914
WFLG_SIZEBRIGHT  #define 0x00000010 = 0x00000010  intuition/intuition.h: *913
WFLG_SIZEGADGET  #define 0x00000001 = 0x00000001  intuition/intuition.h: *908
WFLG_SMART_REFRESH #define 0x00000000 = 0x00000000
                 intuition/intuition.h: *919
WFLG_SUPER_BITMAP #define 0x00000080 = 0x00000080  intuition/intuition.h: *921
WFLG_VISITOR     #define 0x08000000 = 0x08000000  intuition/intuition.h: *955
WFLG_WBENCHWINDOW #define 0x02000000 = 0x02000000  intuition/intuition.h: *946
WFLG_WINDOWACTIVE #define 0x00002000 = 0x00002000  intuition/intuition.h: *936
WFLG_WINDOWREFRESH #define 0x01000000 = 0x01000000
                 intuition/intuition.h: *945
WFLG_WINDOWTICKED #define 0x04000000 = 0x04000000  intuition/intuition.h: *947
WFLG_ZOOMED      #define 0x10000000 = 0x10000000  intuition/intuition.h: *956
WINDOWACTIVE     #define WFLG_WINDOWACTIVE = 0x00002000
                 intuition/iobsolete.h: *161
WINDOWCLOSE      #define WFLG_CLOSEGADGET = 0x00000008
                 intuition/iobsolete.h: *148
WINDOWDEPTH      #define WFLG_DEPTHGADGET = 0x00000004
                 intuition/iobsolete.h: *147
WINDOWDRAG       #define WFLG_DRAGBAR = 0x00000002
                 intuition/iobsolete.h: *146
WINDOWREFRESH    #define WFLG_WINDOWREFRESH = 0x01000000
                 intuition/iobsolete.h: *166
WINDOWSIZING     #define WFLG_SIZEGADGET = 0x00000001
                 intuition/iobsolete.h: *145
WINDOWTICKED     #define WFLG_WINDOWTICKED = 0x04000000
                 intuition/iobsolete.h: *168
WLayer           pointer to struct Layer in struct Window
         +0x007c intuition/intuition.h: *890
WORD             short int  exec/types.h: *41
WORDBITS         unsigned short int  exec/types.h: *43
WORKBENCH_ICON_H #define  workbench/icon.h: *2
WORKBENCH_NAME   #define "workbench.library"  workbench/workbench.h: *119
WORKBENCH_STARTUP_H #define  workbench/startup.h: *2, 1
WORKBENCH_WORKBENCH_H #define  workbench/workbench.h: *2
WScreen          pointer to struct Screen in struct Window
         +0x002e intuition/intuition.h: *819
WUPFRONT         #define GTYP_WUPFRONT = 0x00000040
                 intuition/iobsolete.h: *99
W_TRACTOR        #define 0x30 = 0x00000030  intuition/preferences.h: *188
WarmCapture      pointer to void in struct ExecBase
         +0x0032 exec/execbase.h: *46
Width            short int in struct Layer +0x0086 graphics/clip.h: *57
Width            short int in struct Menu +0x0008 intuition/intuition.h: *66
Width            short int in struct MenuItem
         +0x0008 intuition/intuition.h: *94
Width            short int in struct Requester
         +0x0008 intuition/intuition.h: *150
Width            short int in struct Gadget +0x0008 intuition/intuition.h: *221
Width            short int in struct Image +0x0004 intuition/intuition.h: *623
Width            short int in struct IBox +0x0004 intuition/intuition.h: *786
Width            short int in struct Window +0x0008 intuition/intuition.h: *800
Width            short int in struct NewWindow
         +0x0004 intuition/intuition.h: *977
Width            short int in struct ExtNewWindow
         +0x0004 intuition/intuition.h: *1047
Width            short int in struct Screen +0x000c intuition/screens.h: *104
Width            short int in struct NewScreen
         +0x0004 intuition/screens.h: *312
Width            short int in struct ExtNewScreen
         +0x0004 intuition/screens.h: *348
Width            short int in struct VSprite +0x001c graphics/gels.h: *99
Width            short int in struct (no tag)
         +0x0000 intuition/imageclass.h: *165
Width            short int in struct (no tag)
         +0x0000 intuition/imageclass.h: *182
Width            short int in struct (no tag)
         +0x0000 intuition/imageclass.h: *197
Window           structure tag size 0x0088 devices/conunit.h: *58
                 intuition/intuition.h: 172, 713, 795, 797, 844
                 intuition/screens.h: 101
                 intuition/cghooks.h: 30
                 intuition/intuitionbase.h: 74
Window           pointer to void in struct Layer +0x0028 graphics/clip.h: *46
WindowPort       pointer to struct MsgPort in struct Window
         +0x005a intuition/intuition.h: *856
WorkBuffer       pointer to unsigned char in struct StringExtend
         +0x0010 intuition/sghooks.h: *28
WorkBuffer       pointer to unsigned char in struct SGWork
         +0x0008 intuition/sghooks.h: *37
WorkName         array [30] of unsigned char in struct Preferences
         +0x00ba intuition/preferences.h: *112
WriteChar        macro (1 argument)   dos/stdio.h: *18
WriteStr         macro (1 argument)   dos/stdio.h: *23


2.0 IncludeXREF: X

x                short int in struct tPoint +0x0000 graphics/gfx.h: *43
x                unsigned short int in struct SimpleSprite
         +0x0006 graphics/sprite.h: *25
xln_Init         pointer to function returning long int in struct ExtendedNode
         +0x0014 graphics/gfxnodes.h: *28
xln_Library      long int in struct ExtendedNode
         +0x0010 graphics/gfxnodes.h: *27
xln_Name         pointer to char in struct ExtendedNode
         +0x000a graphics/gfxnodes.h: *24
xln_Pred         pointer to struct Node in struct ExtendedNode
         +0x0004 graphics/gfxnodes.h: *21
xln_Pri          char in struct ExtendedNode +0x0009 graphics/gfxnodes.h: *23
xln_Subsystem    unsigned char in struct ExtendedNode
         +0x000e graphics/gfxnodes.h: *25
xln_Subtype      unsigned char in struct ExtendedNode
         +0x000f graphics/gfxnodes.h: *26
xln_Succ         pointer to struct Node in struct ExtendedNode
         +0x0000 graphics/gfxnodes.h: *20
xln_Type         unsigned char in struct ExtendedNode
         +0x0008 graphics/gfxnodes.h: *22
X                short int in struct (no tag)
         +0x0000 devices/inputevent.h: *91
X                unsigned short int in struct (no tag)
         +0x0000 devices/inputevent.h: *110
X                unsigned short int in struct (no tag)
         +0x0000 devices/inputevent.h: *114
X                unsigned short int in struct (no tag)
         +0x0000 intuition/screens.h: *71
X                short int in struct VSprite +0x0018 graphics/gels.h: *96
X                short int in struct (no tag)
         +0x0000 intuition/gadgetclass.h: *180
X                short int in struct (no tag)
         +0x0000 intuition/gadgetclass.h: *207
X                short int in struct (no tag)
         +0x0000 intuition/imageclass.h: *156
X                short int in struct (no tag)
         +0x0000 intuition/imageclass.h: *176
X                short int in struct (no tag)
         +0x0000 intuition/imageclass.h: *191
XAccel           short int in struct AnimOb +0x001a graphics/gels.h: *215
XOffset          char in struct Window +0x0050 intuition/intuition.h: *852
XOffset          char in struct Preferences
         +0x0064 intuition/preferences.h: *62
XTrans           short int in struct AnimComp +0x001c graphics/gels.h: *193
XVel             short int in struct AnimOb +0x0016 graphics/gels.h: *214
XY               pointer to short int in struct Border
         +0x0008 intuition/intuition.h: *604


2.0 IncludeXREF: Y

y                short int in struct tPoint +0x0002 graphics/gfx.h: *43
y                unsigned short int in struct SimpleSprite
         +0x0008 graphics/sprite.h: *25
year             unsigned short int in struct ClockData
         +0x000a utility/date.h: *25
Y                short int in struct (no tag)
         +0x0002 devices/inputevent.h: *92
Y                unsigned short int in struct (no tag)
         +0x0002 devices/inputevent.h: *111
Y                unsigned short int in struct (no tag)
         +0x0002 devices/inputevent.h: *115
Y                unsigned short int in struct (no tag)
         +0x0002 intuition/screens.h: *72
Y                short int in struct VSprite +0x0016 graphics/gels.h: *96
Y                short int in struct (no tag)
         +0x0002 intuition/gadgetclass.h: *181
Y                short int in struct (no tag)
         +0x0002 intuition/gadgetclass.h: *208
Y                short int in struct (no tag)
         +0x0002 intuition/imageclass.h: *157
Y                short int in struct (no tag)
         +0x0002 intuition/imageclass.h: *177
Y                short int in struct (no tag)
         +0x0002 intuition/imageclass.h: *192
YAccel           short int in struct AnimOb +0x0018 graphics/gels.h: *215
YOffset          char in struct Window +0x0051 intuition/intuition.h: *852
YOffset          char in struct Preferences
         +0x0065 intuition/preferences.h: *63
YTrans           short int in struct AnimComp +0x001a graphics/gels.h: *192
YVel             short int in struct AnimOb +0x0014 graphics/gels.h: *214


2.0 IncludeXREF: Z

ZOOMED           #define WFLG_ZOOMED = 0x10000000  intuition/iobsolete.h: *171
ZOOMIMAGE        #define (0x01L) = 0x00000001  intuition/imageclass.h: *102


FD/asl_lib.fd

* "asl.library"
##base _AslBase
##bias 30
##public
*--- functions in V36 or higher (distributed as Release 2.0) ---
*
AllocFileRequest()()
FreeFileRequest(fileReq)(a0)
RequestFile(fileReq)(a0)
AllocAslRequest(type,tagList)(d0/a0)
FreeAslRequest(request)(a0)
AslRequest(request,tagList)(a0/a1)
##end


FD/icon_lib.fd

* "icon.library"
##base _IconBase
##bias 30
*--- functions in V36 or higher (distributed as Release 2.0) ---
*	Use DiskObjects instead of obsolete WBObjects
##private
iconPrivate1()()
iconPrivate2()()
##public
GetIcon(name,icon,freelist)(a0/a1/a2)
PutIcon(name,icon)(a0/a1)
FreeFreeList(freelist)(a0)
##private
iconPrivate3()()
iconPrivate4()()
##public
AddFreeList(freelist,mem,size)(a0/a1/a2)
GetDiskObject(name)(a0)
PutDiskObject(name,diskobj)(a0/a1)
FreeDiskObject(diskobj)(a0)
FindToolType(toolTypeArray,typeName)(a0/a1)
MatchToolValue(typeString,value)(a0/a1)
BumpRevision(newname,oldname)(a0/a1)
##private
iconPrivate5()()
##public
GetDefDiskObject(type)(d0)
PutDefDiskObject(diskObject)(a0)
GetDiskObjectNew(name)(a0)
DeleteDiskObject(name)(a0)
*--- (4 function slots reserved here) ---
##bias 168
##end


FD/potgo_lib.fd

* "potgo.resource"
##base _PotgoBase
##bias 6
##public
AllocPotBits(bits)(d0)
FreePotBits(bits)(d0)
WritePotgo(word,mask)(d0/d1)
##end


FD/battclock_lib.fd

* "battclock.resource"
##base _BattClockBase
##bias 6
##public
ResetBattClock()()
ReadBattClock()()
WriteBattClock(time)(d0)
##private
battclockPrivate1()()
battclockPrivate2()()
##end


FD/iffparse_lib.fd

* "iffparse.library"
##base _IFFParseBase
##bias 30
##public
*--- functions in V33 or higher (distributed as Release 1.2) ---
*------ Basic functions ------
AllocIFF()()
OpenIFF(iff,rwMode)(a0,d0)
ParseIFF(iff,control)(a0,d0)
CloseIFF(iff)(a0)
FreeIFF(iff)(a0)
*------ Read/Write functions ------
ReadChunkBytes(iff,buf,size)(a0/a1,d0)
WriteChunkBytes(iff,buf,size)(a0/a1,d0)
ReadChunkRecords(iff,buf,bytesPerRecord,nRecords)(a0/a1,d0/d1)
WriteChunkRecords(iff,buf,bytesPerRecord,nRecords)(a0/a1,d0/d1)
*------ Context entry/exit ------
PushChunk(iff,type,id,size)(a0,d0/d1/d2)
PopChunk(iff)(a0)
*--- (1 function slot reserved here) ---
##bias 102
*------ Low-level handler installation ------
EntryHandler(iff,type,id,position,handler,object)(a0,d0/d1/d2/a1/a2)
ExitHandler(iff,type,id,position,handler,object)(a0,d0/d1/d2/a1/a2)
*------ Built-in chunk/property handlers ------
PropChunk(iff,type,id)(a0,d0/d1)
PropChunks(iff,propArray,nProps)(a0/a1,d0)
StopChunk(iff,type,id)(a0,d0/d1)
StopChunks(iff,propArray,nProps)(a0/a1,d0)
CollectionChunk(iff,type,id)(a0,d0/d1)
CollectionChunks(iff,propArray,nProps)(a0/a1,d0)
StopOnExit(iff,type,id)(a0,d0/d1)
*------ Context utilities ------
FindProp(iff,type,id)(a0,d0/d1)
FindCollection(iff,type,id)(a0,d0/d1)
FindPropContext(iff)(a0)
CurrentChunk(iff)(a0)
ParentChunk(contextNode)(a0)
*------ LocalContextItem support functions ------
AllocLocalItem(type,id,ident,dataSize)(d0/d1/d2/d3)
LocalItemData(localItem)(a0)
SetLocalItemPurge(localItem,purgeHook)(a0/a1)
FreeLocalItem(localItem)(a0)
FindLocalItem(iff,type,id,ident)(a0,d0/d1/d2)
StoreLocalItem(iff,localItem,position)(a0/a1,d0)
StoreItemInContext(iff,localItem,contextNode)(a0/a1/a2)
*------ IFFHandle initialization ------
InitIFF(iff,flags,streamHook)(a0,d0/a1)
InitIFFasDOS(iff)(a0)
InitIFFasClip(iff)(a0)
*------ Internal clipboard support ------
OpenClipboard(unitNum)(d0)
CloseClipboard(clipboard)(a0)
*------ Miscellaneous ------
GoodID(id)(d0)
GoodType(type)(d0)
IDtoStr(id,buf)(d0/a0)
##end


FD/ramdrive_lib.fd

* "ramdrive.device"
##base _RamdriveDevice
##bias 42
##public
*--- functions in V34 or higher (distributed as Release 1.3) ---
KillRAD0()()
*--- functions in V36 or higher (distributed as Release 2.0) ---
KillRAD(unit)(d0)
##end


FD/battmem_lib.fd

* "battmem.resource"
##base _BattMemBase
##bias 6
##public
ObtainBattSemaphore()()
ReleaseBattSemaphore()()
ReadBattMem(buffer,offset,length)(a0,d0/d1)
WriteBattMem(buffer,offset,length)(a0,d0/d1)
##end


FD/input_lib.fd

* "input.device"
##base _InputBase
##bias 42
##public
*--- functions in V36 or higher (distributed as Release 2.0) ---
PeekQualifier()()
##end


FD/rexxsyslib_lib.fd

* "rexxsyslib.library"
##base _RexxSysBase
##bias 30
*--- functions in V33 or higher (distributed as Release 1.2) ---
*
##private
*--- (16 function slots reserved here) ---
##bias 126
##public
*
CreateArgstring(string,length)(a0,d0)
DeleteArgstring(argstring)(a0)
LengthArgstring(argstring)(a0)
CreateRexxMsg(port,extension,host)(a0/a1,d0)
DeleteRexxMsg(packet)(a0)
ClearRexxMsg(msgptr,count)(a0,d0)
FillRexxMsg(msgptr,count,mask)(a0,d0/d1)
IsRexxMsg(msgptr)(a0)
*
##private
*--- (46 function slots reserved here) ---
##bias 450
##public
*
LockRexxBase(resource)(d0)
UnlockRexxBase(resource)(d0)
*
##end


FD/cia_lib.fd

* "CiaA.Resource" and "CiaB.Resource"
##bias 6
##public
AddICRVector(resource,iCRBit,interrupt)(a6,d0/a1)
RemICRVector(resource,iCRBit,interrupt)(a6,d0/a1)
AbleICR(resource,mask)(a6,d0)
SetICR(resource,mask)(a6,d0)
##end


FD/intuition_lib.fd

* "intuition.library"
##base _IntuitionBase
##bias 30
##public
* Public functions OpenIntuition() and Intuition() are intentionally
* not documented.
OpenIntuition()()
Intuition(iEvent)(a0)
AddGadget(window,gadget,position)(a0/a1,d0)
ClearDMRequest(window)(a0)
ClearMenuStrip(window)(a0)
ClearPointer(window)(a0)
CloseScreen(screen)(a0)
CloseWindow(window)(a0)
CloseWorkBench()()
CurrentTime(seconds,micros)(a0/a1)
DisplayAlert(alertNumber,string,height)(d0/a0,d1)
DisplayBeep(screen)(a0)
DoubleClick(sSeconds,sMicros,cSeconds,cMicros)(d0/d1/d2/d3)
DrawBorder(rp,border,leftOffset,topOffset)(a0/a1,d0/d1)
DrawImage(rp,image,leftOffset,topOffset)(a0/a1,d0/d1)
EndRequest(requester,window)(a0/a1)
GetDefPrefs(preferences,size)(a0,d0)
GetPrefs(preferences,size)(a0,d0)
InitRequester(requester)(a0)
ItemAddress(menuStrip,menuNumber)(a0,d0)
ModifyIDCMP(window,flags)(a0,d0)
ModifyProp(gadget,window,requester,flags,horizPot,vertPot,horizBody,vertBody)(a0/a1/a2,d0/d1/d2/d3/d4)
MoveScreen(screen,dx,dy)(a0,d0/d1)
MoveWindow(window,dx,dy)(a0,d0/d1)
OffGadget(gadget,window,requester)(a0/a1/a2)
OffMenu(window,menuNumber)(a0,d0)
OnGadget(gadget,window,requester)(a0/a1/a2)
OnMenu(window,menuNumber)(a0,d0)
OpenScreen(newScreen)(a0)
OpenWindow(newWindow)(a0)
OpenWorkBench()()
PrintIText(rp,iText,left,top)(a0/a1,d0/d1)
RefreshGadgets(gadgets,window,requester)(a0/a1/a2)
RemoveGadget(window,gadget)(a0/a1)
* The official calling sequence for ReportMouse is given below.
* Note the register order.  For the complete story, read the ReportMouse
* autodoc.
ReportMouse(flag,window)(d0/a0)
Request(requester,window)(a0/a1)
ScreenToBack(screen)(a0)
ScreenToFront(screen)(a0)
SetDMRequest(window,requester)(a0/a1)
SetMenuStrip(window,menu)(a0/a1)
SetPointer(window,pointer,height,width,xOffset,yOffset)(a0/a1,d0/d1/d2/d3)
SetWindowTitles(window,windowTitle,screenTitle)(a0/a1/a2)
ShowTitle(screen,showIt)(a0,d0)
SizeWindow(window,dx,dy)(a0,d0/d1)
ViewAddress()()
ViewPortAddress(window)(a0)
WindowToBack(window)(a0)
WindowToFront(window)(a0)
WindowLimits(window,widthMin,heightMin,widthMax,heightMax)(a0,d0/d1/d2/d3)
*--- start of next generation of names -------------------------------------
SetPrefs(preferences,size,inform)(a0,d0/d1)
*--- start of next next generation of names --------------------------------
IntuiTextLength(iText)(a0)
WBenchToBack()()
WBenchToFront()()
*--- start of next next next generation of names ---------------------------
AutoRequest(window,body,posText,negText,pFlag,nFlag,width,height)(a0/a1/a2/a3,d0/d1/d2/d3)
BeginRefresh(window)(a0)
BuildSysRequest(window,body,posText,negText,flags,width,height)(a0/a1/a2/a3,d0/d1/d2)
EndRefresh(window,complete)(a0,d0)
FreeSysRequest(window)(a0)
MakeScreen(screen)(a0)
RemakeDisplay()()
RethinkDisplay()()
*--- start of next next next next generation of names ----------------------
AllocRemember(rememberKey,size,flags)(a0,d0/d1)
* Public function AlohaWorkbench() is intentionally not documented
AlohaWorkbench(wbport)(a0)
FreeRemember(rememberKey,reallyForget)(a0,d0)
*--- start of 15 Nov 85 names ------------------------
LockIBase(dontknow)(d0)
UnlockIBase(ibLock)(a0)
*--- functions in V33 or higher (distributed as Release 1.2) ---
GetScreenData(buffer,size,type,screen)(a0,d0/d1/a1)
RefreshGList(gadgets,window,requester,numGad)(a0/a1/a2,d0)
AddGList(window,gadget,position,numGad,requester)(a0/a1,d0/d1/a2)
RemoveGList(remPtr,gadget,numGad)(a0/a1,d0)
ActivateWindow(window)(a0)
RefreshWindowFrame(window)(a0)
ActivateGadget(gadgets,window,requester)(a0/a1/a2)
NewModifyProp(gadget,window,requester,flags,horizPot,vertPot,horizBody,vertBody,numGad)(a0/a1/a2,d0/d1/d2/d3/d4/d5)
*--- functions in V36 or higher (distributed as Release 2.0) ---
QueryOverscan(displayID,rect,oScanType)(a0/a1,d0)
MoveWindowInFrontOf(window,behindWindow)(a0/a1)
ChangeWindowBox(window,left,top,width,height)(a0,d0/d1/d2/d3)
SetEditHook(hook)(a0)
SetMouseQueue(window,queueLength)(a0,d0)
ZipWindow(window)(a0)
*--- public screens ---
LockPubScreen(name)(a0)
UnlockPubScreen(name,screen)(a0/a1)
LockPubScreenList()()
UnlockPubScreenList()()
NextPubScreen(screen,namebuf)(a0/a1)
SetDefaultPubScreen(name)(a0)
SetPubScreenModes(modes)(d0)
PubScreenStatus(screen,statusFlags)(a0,d0)
*
ObtainGIRPort(gInfo)(a0)
ReleaseGIRPort(rp)(a0)
GadgetMouse(gadget,gInfo,mousePoint)(a0/a1/a2)
##private
* system private and not to be used by applications:
intuitionPrivate1()()
##public
GetDefaultPubScreen(nameBuffer)(a0)
EasyRequestArgs(window,easyStruct,idcmpPtr,args)(a0/a1/a2/a3)
BuildEasyRequestArgs(window,easyStruct,idcmp,args)(a0/a1,d0/a3)
SysReqHandler(window,idcmpPtr,waitInput)(a0/a1,d0)
OpenWindowTagList(newWindow,tagList)(a0/a1)
OpenScreenTagList(newScreen,tagList)(a0/a1)
*
*	new Image functions
DrawImageState(rp,image,leftOffset,topOffset,state,drawInfo)(a0/a1,d0/d1/d2/a2)
PointInImage(point,image)(d0/a0)
EraseImage(rp,image,leftOffset,topOffset)(a0/a1,d0/d1)
*
NewObjectA(classPtr,classID,tagList)(a0/a1/a2)
*
DisposeObject(object)(a0)
SetAttrsA(object,tagList)(a0/a1)
*
GetAttr(attrID,object,storagePtr)(d0/a0/a1)
*
* 	special set attribute call for gadgets
SetGadgetAttrsA(gadget,window,requester,tagList)(a0/a1/a2/a3)
*
*	for class implementors only
NextObject(objectPtrPtr)(a0)
##private
intuitionPrivate2()()
##public
MakeClass(classID,superClassID,superClassPtr,instanceSize,flags)(a0/a1/a2,d0/d1)
AddClass(classPtr)(a0)
*
*
GetScreenDrawInfo(screen)(a0)
FreeScreenDrawInfo(screen,drawInfo)(a0/a1)
*
ResetMenuStrip(window,menu)(a0/a1)
RemoveClass(classPtr)(a0)
FreeClass(classPtr)(a0)
##private
intuitionPrivate3()()
intuitionPrivate4()()
##public
##end


FD/timer_lib.fd

* "Timer.Device"
##base _TimerBase
##bias 42
##public
AddTime(dest,src)(a0/a1)
SubTime(dest,src)(a0/a1)
CmpTime(dest,src)(a0/a1)
ReadEClock(dest)(a0)
GetSysTime(dest)(a0)
##end


FD/commodities_lib.fd

* "commodities.library"
##base _CxBase
##bias 30
##public
*--- functions in V36 or higher (distributed as Release 2.0) ---
*
*  OBJECT UTILITIES
*
CreateCxObj(type,arg1,arg2)(d0/a0/a1)
CxBroker(nb,error)(a0,d0)
ActivateCxObj(co,true)(a0,d0)
DeleteCxObj(co)(a0)
DeleteCxObjAll(co)(a0)
CxObjType(co)(a0)
CxObjError(co)(a0)
ClearCxObjError(co)(a0)
SetCxObjPri(co,pri)(a0,d0)
*
*  OBJECT ATTACHMENT
*
AttachCxObj(headObj,co)(a0/a1)
EnqueueCxObj(headObj,co)(a0/a1)
InsertCxObj(headObj,co,pred)(a0/a1/a2)
RemoveCxObj(co)(a0)
*
*  TYPE SPECIFIC
*
##private
commoditiesPrivate1()()
##public
SetTranslate(translator,events)(a0/a1)
SetFilter(filter,text)(a0/a1)
SetFilterIX(filter,ix)(a0/a1)
ParseIX(description,ix)(a0/a1)
*
*  COMMON MESSAGE
*
CxMsgType(cxm)(a0)
CxMsgData(cxm)(a0)
CxMsgID(cxm)(a0)
*
*  MESSAGE ROUTING
*
DivertCxMsg(cxm,headobj,ret)(a0/a1/a2)
RouteCxMsg(cxm,co)(a0/a1)
DisposeCxMsg(cxm)(a0)
*
*  INPUT EVENT HANDLING
*
InvertKeyMap(ansicode,event,km)(d0/a0/a1)
AddIEvents(events)(a0)
##private
*
* FOR USE ONLY BY CONTROLLER PROGRAM
*
commoditiesPrivate2()()
commoditiesPrivate3()()
commoditiesPrivate4()()
##public
##end


FD/keymap_lib.fd

* "keymap.library"
##base _KeymapBase
##bias 30
##public
*--- functions in V36 or higher (distributed as Release 2.0) ---
SetKeyMapDefault(keyMap)(a0)
AskKeyMapDefault()()
MapRawKey(event,buffer,length,keyMap)(a0/a1,d1/a2)
MapANSI(string,count,buffer,length,keyMap)(a0,d0/a1,d1/a2)
##end


FD/translator_lib.fd

* "translator.library"
##base _TranslatorBase
##bias 30
##public
Translate(inputString,inputLength,outputBuffer,bufferSize)(a0,d0/a1,d1)
##end


FD/console_lib.fd

* "console.device"
##base _ConsoleDevice
##bias 42
##public
CDInputHandler(events,consoleDevice)(a0/a1)
RawKeyConvert(events,buffer,length,keyMap)(a0/a1,d1/a2)
##private
*--- functions in V36 or higher (distributed as Release 2.0) ---
consolePrivate1()()
consolePrivate2()()
consolePrivate3()()
consolePrivate4()()
##end


FD/layers_lib.fd

* "layers.library"
##base _LayersBase
##bias 30
##public
InitLayers(li)(a0)
CreateUpfrontLayer(li,bm,x0,y0,x1,y1,flags,bm2)(a0/a1,d0/d1/d2/d3/d4/a2)
CreateBehindLayer(li,bm,x0,y0,x1,y1,flags,bm2)(a0/a1,d0/d1/d2/d3/d4/a2)
UpfrontLayer(dummy,layer)(a0/a1)
BehindLayer(dummy,layer)(a0/a1)
MoveLayer(dummy,layer,dx,dy)(a0/a1,d0/d1)
SizeLayer(dummy,layer,dx,dy)(a0/a1,d0/d1)
ScrollLayer(dummy,layer,dx,dy)(a0/a1,d0/d1)
BeginUpdate(l)(a0)
EndUpdate(layer,flag)(a0,d0)
DeleteLayer(dummy,layer)(a0/a1)
LockLayer(dummy,layer)(a0/a1)
UnlockLayer(layer)(a0)
LockLayers(li)(a0)
UnlockLayers(li)(a0)
LockLayerInfo(li)(a0)
SwapBitsRastPortClipRect(rp,cr)(a0/a1)
WhichLayer(li,x,y)(a0,d0/d1)
UnlockLayerInfo(li)(a0)
NewLayerInfo()()
DisposeLayerInfo(li)(a0)
FattenLayerInfo(li)(a0)
ThinLayerInfo(li)(a0)
MoveLayerInFrontOf(layer_to_move,other_layer)(a0/a1)
InstallClipRegion(layer,region)(a0/a1)
MoveSizeLayer(layer,dx,dy,dw,dh)(a0,d0/d1/d2/d3)
CreateUpfrontHookLayer(li,bm,x0,y0,x1,y1,flags,hook,bm2)(a0/a1,d0/d1/d2/d3/d4/a3,a2)
CreateBehindHookLayer(li,bm,x0,y0,x1,y1,flags,hook,bm2)(a0/a1,d0/d1/d2/d3/d4/a3,a2)
InstallLayerHook(layer,hook)(a0/a1)
##end


FD/utility_lib.fd

* "utility.library"
##base _UtilityBase
##bias 30
##public
* *** TagItem FUNCTIONS ***
FindTagItem(tagVal,tagList)(d0/a0)
GetTagData(tagVal,defaultVal,tagList)(d0/d1/a0)
PackBoolTags(initialFlags,tagList,boolMap)(d0/a0/a1)
NextTagItem(tagListPtr)(a0)
FilterTagChanges(newTagList,oldTagList,apply)(a0/a1,d0)
MapTags(tagList,mapList,includeMiss)(a0/a1,d0)
AllocateTagItems(numItems)(d0)
CloneTagItems(tagList)(a0)
FreeTagItems(tagList)(a0)
RefreshTagItemClones(cloneList,origList)(a0/a1)
TagInArray(tagVal,tagArray)(d0/a0)
FilterTagItems(tagList,filterArray,logic)(a0/a1,d0)
*
* *** HOOK FUNCTIONS *** *
CallHookPkt(hook,object,paramPacket)(a0/a2,a1)
*--- (1 function slot reserved here) ---
##bias 114
*
* *** DATE FUNCTIONS *** *
*--- (1 function slot reserved here) ---
##bias 120
Amiga2Date(amigaTime,date)(d0/a0)
Date2Amiga(date)(a0)
CheckDate(date)(a0)
*
* *** 32 BIT MATH FUNCTIONS *** *
SMult32(factor1,factor2)(d0/d1)
UMult32(factor1,factor2)(d0/d1)
* NOTE: Quotient:Remainder returned in d0:d1
SDivMod32(dividend,divisor)(d0/d1)
UDivMod32(dividend,divisor)(d0/d1)
*
* *** International string routines ***
Stricmp(string1,string2)(a0/a1)
Strnicmp(string1,string2,length)(a0/a1,d0)
ToUpper(character)(d0)
ToLower(character)(d0)
##end


FD/disk_lib.fd

* "disk.resource"
##base _DiskBase
##bias 6
##public
AllocUnit(unitNum)(d0)
FreeUnit(unitNum)(d0)
GetUnit(unitPointer)(a1)
GiveUnit()()
GetUnitID(unitNum)(d0)
*------ new for V37 ------
ReadUnitID(unitNum)(d0)
##end


FD/mathffp_lib.fd

* "mathffp.library"
##base _MathBase
##bias 30
##public
SPFix(parm)(d0)
SPFlt(integer)(d0)
SPCmp(leftParm,rightParm)(d1,d0)
SPTst(parm)(d1)
SPAbs(parm)(d0)
SPNeg(parm)(d0)
SPAdd(leftParm,rightParm)(d1,d0)
SPSub(leftParm,rightParm)(d1,d0)
SPMul(leftParm,rightParm)(d1,d0)
SPDiv(leftParm,rightParm)(d1,d0)
*--- functions in V33 or higher (distributed as Release 1.2) ---
SPFloor(parm)(d0)
SPCeil(parm)(d0)
##end


FD/wb_lib.fd

* "workbench.library"
##base _WorkbenchBase
##bias 30
*--- functions in V36 or higher (distributed as Release 2.0) ---
*
##private
*
wbPrivate1()()
wbPrivate2()()
*
wbPrivate3()()
*
##public
*
AddAppWindowA(id,userdata,window,msgport,taglist)(d0/d1/a0/a1/a2)
*
RemoveAppWindow(appWindow)(a0)
*
AddAppIconA(id,userdata,text,msgport,lock,diskobj,taglist)(d0/d1/a0/a1/a2/a3/a4)
*
RemoveAppIcon(appIcon)(a0)
*
AddAppMenuItemA(id,userdata,text,msgport,taglist)(d0/d1/a0/a1/a2)
*
RemoveAppMenuItem(appMenuItem)(a0)
*
*--- (5 function slots reserved here) ---
##bias 114
*
##end


FD/diskfont_lib.fd

* "diskfont.library"
##base _DiskfontBase
##bias 30
##public
OpenDiskFont(textAttr)(a0)
AvailFonts(buffer,bufBytes,flags)(a0,d0/d1)
*--- functions in V34 or higher (distributed as Release 1.3) ---
NewFontContents(fontsLock,fontName)(a0/a1)
DisposeFontContents(fontContentsHeader)(a1)
*--- functions in V36 or higher (distributed as Release 2.0) ---
NewScaledDiskFont(sourceFont,destTextAttr)(a0/a1)
##end


FD/mathieeedoubbas_lib.fd

* "mathieeedoubbas.library"
##base _MathIeeeDoubBasBase
##bias 30
##public
IEEEDPFix(parm)(d0/d1)
IEEEDPFlt(integer)(d0)
IEEEDPCmp(leftParm,rightParm)(d0/d1/d2/d3)
IEEEDPTst(parm)(d0/d1)
IEEEDPAbs(parm)(d0/d1)
IEEEDPNeg(parm)(d0/d1)
IEEEDPAdd(leftParm,rightParm)(d0/d1/d2/d3)
IEEEDPSub(leftParm,rightParm)(d0/d1/d2/d3)
IEEEDPMul(factor1,factor2)(d0/d1/d2/d3)
IEEEDPDiv(dividend,divisor)(d0/d1/d2/d3)
*--- functions in V33 or higher (distributed as Release 1.2) ---
IEEEDPFloor(parm)(d0/d1)
IEEEDPCeil(parm)(d0/d1)
##end


FD/dos_lib.fd

* "dos.library"
##base _DOSBase
##bias 30
##public
Open(name,accessMode)(d1/d2)
Close(file)(d1)
Read(file,buffer,length)(d1/d2/d3)
Write(file,buffer,length)(d1/d2/d3)
Input()()
Output()()
Seek(file,position,offset)(d1/d2/d3)
DeleteFile(name)(d1)
Rename(oldName,newName)(d1/d2)
Lock(name,type)(d1/d2)
UnLock(lock)(d1)
DupLock(lock)(d1)
Examine(lock,fileInfoBlock)(d1/d2)
ExNext(lock,fileInfoBlock)(d1/d2)
Info(lock,parameterBlock)(d1/d2)
CreateDir(name)(d1)
CurrentDir(lock)(d1)
IoErr()()
CreateProc(name,pri,segList,stackSize)(d1/d2/d3/d4)
Exit(returnCode)(d1)
LoadSeg(name)(d1)
UnLoadSeg(seglist)(d1)
##private
dosPrivate1()()
dosPrivate2()()
##public
DeviceProc(name)(d1)
SetComment(name,comment)(d1/d2)
SetProtection(name,protect)(d1/d2)
DateStamp(date)(d1)
Delay(timeout)(d1)
WaitForChar(file,timeout)(d1/d2)
ParentDir(lock)(d1)
IsInteractive(file)(d1)
Execute(string,file,file2)(d1/d2/d3)
*--- functions in V36 or higher (distributed as Release 2.0) ---
*	DOS Object creation/deletion
AllocDosObject(type,tags)(d1/d2)
FreeDosObject(type,ptr)(d1/d2)
*	Packet Level routines
DoPkt(port,action,arg1,arg2,arg3,arg4,arg5)(d1/d2/d3/d4/d5/d6/d7)
SendPkt(dp,port,replyport)(d1/d2/d3)
WaitPkt()()
ReplyPkt(dp,res1,res2)(d1/d2/d3)
AbortPkt(port,pkt)(d1/d2)
*	Record Locking
LockRecord(fh,offset,length,mode,timeout)(d1/d2/d3/d4/d5)
LockRecords(recArray,timeout)(d1/d2)
UnLockRecord(fh,offset,length)(d1/d2/d3)
UnLockRecords(recArray)(d1)
*	Buffered File I/O
SelectInput(fh)(d1)
SelectOutput(fh)(d1)
FGetC(fh)(d1)
FPutC(fh,ch)(d1/d2)
UnGetC(fh,character)(d1/d2)
FRead(fh,block,blocklen,number)(d1/d2/d3/d4)
FWrite(fh,block,blocklen,number)(d1/d2/d3/d4)
FGets(fh,buf,buflen)(d1/d2/d3)
FPuts(fh,str)(d1/d2)
VFWritef(fh,format,argarray)(d1/d2/d3)
VFPrintf(fh,format,argarray)(d1/d2/d3)
Flush(fh)(d1)
SetVBuf(fh,buff,type,size)(d1/d2/d3/d4)
*	DOS Object Management
DupLockFromFH(fh)(d1)
OpenFromLock(lock)(d1)
ParentOfFH(fh)(d1)
ExamineFH(fh,fib)(d1/d2)
SetFileDate(name,date)(d1/d2)
NameFromLock(lock,buffer,len)(d1/d2/d3)
NameFromFH(fh,buffer,len)(d1/d2/d3)
SplitName(name,seperator,buf,oldpos,size)(d1/d2/d3/d4/d5)
SameLock(lock1,lock2)(d1/d2)
SetMode(fh,mode)(d1/d2)
ExAll(lock,buffer,size,data,control)(d1/d2/d3/d4/d5)
ReadLink(port,lock,path,buffer,size)(d1/d2/d3/d4/d5)
MakeLink(name,dest,soft)(d1/d2/d3)
ChangeMode(type,fh,newmode)(d1/d2/d3)
SetFileSize(fh,pos,mode)(d1/d2/d3)
*	Error Handling
SetIoErr(result)(d1)
Fault(code,header,buffer,len)(d1/d2/d3/d4)
PrintFault(code,header)(d1/d2)
ErrorReport(code,type,arg1,device)(d1/d2/d3/d4)
*--- (1 function slot reserved here) ---
##bias 492
*	Process Management
Cli()()
CreateNewProc(tags)(d1)
RunCommand(seg,stack,paramptr,paramlen)(d1/d2/d3/d4)
GetConsoleTask()()
SetConsoleTask(task)(d1)
GetFileSysTask()()
SetFileSysTask(task)(d1)
GetArgStr()()
SetArgStr(string)(d1)
FindCliProc(num)(d1)
MaxCli()()
SetCurrentDirName(name)(d1)
GetCurrentDirName(buf,len)(d1/d2)
SetProgramName(name)(d1)
GetProgramName(buf,len)(d1/d2)
SetPrompt(name)(d1)
GetPrompt(buf,len)(d1/d2)
SetProgramDir(lock)(d1)
GetProgramDir()()
*	Device List Management
SystemTagList(command,tags)(d1/d2)
AssignLock(name,lock)(d1/d2)
AssignLate(name,path)(d1/d2)
AssignPath(name,path)(d1/d2)
AssignAdd(name,lock)(d1/d2)
RemAssignList(name,lock)(d1/d2)
GetDeviceProc(name,dp)(d1/d2)
FreeDeviceProc(dp)(d1)
LockDosList(flags)(d1)
UnLockDosList(flags)(d1)
AttemptLockDosList(flags)(d1)
RemDosEntry(dlist)(d1)
AddDosEntry(dlist)(d1)
FindDosEntry(dlist,name,flags)(d1/d2/d3)
NextDosEntry(dlist,flags)(d1/d2)
MakeDosEntry(name,type)(d1/d2)
FreeDosEntry(dlist)(d1)
IsFileSystem(name)(d1)
*	Handler Interface
Format(filesystem,volumename,dostype)(d1/d2/d3)
Relabel(drive,newname)(d1/d2)
Inhibit(name,onoff)(d1/d2)
AddBuffers(name,number)(d1/d2)
*	Date, Time Routines
CompareDates(date1,date2)(d1/d2)
DateToStr(datetime)(d1)
StrToDate(datetime)(d1)
*	Image Management
InternalLoadSeg(fh,table,funcarray,stack)(d0/a0/a1/a2)
InternalUnLoadSeg(seglist,freefunc)(d1/a1)
NewLoadSeg(file,tags)(d1/d2)
AddSegment(name,seg,system)(d1/d2/d3)
FindSegment(name,seg,system)(d1/d2/d3)
RemSegment(seg)(d1)
*	Command Support
CheckSignal(mask)(d1)
ReadArgs(template,array,args)(d1/d2/d3)
FindArg(keyword,template)(d1/d2)
ReadItem(name,maxchars,cSource)(d1/d2/d3)
StrToLong(string,value)(d1/d2)
MatchFirst(pat,anchor)(d1/d2)
MatchNext(anchor)(d1)
MatchEnd(anchor)(d1)
ParsePattern(pat,buf,buflen)(d1/d2/d3)
MatchPattern(pat,str)(d1/d2)
##private
* Not currently implemented.
dosPrivate3()()
##public
FreeArgs(args)(d1)
*--- (1 function slot reserved here) ---
##bias 870
FilePart(path)(d1)
PathPart(path)(d1)
AddPart(dirname,filename,size)(d1/d2/d3)
*	Notification
StartNotify(notify)(d1)
EndNotify(notify)(d1)
*	Environment Variable functions
SetVar(name,buffer,size,flags)(d1/d2/d3/d4)
GetVar(name,buffer,size,flags)(d1/d2/d3/d4)
DeleteVar(name,flags)(d1/d2)
FindVar(name,type)(d1/d2)
##private
dosPrivate4()()
##public
CliInitNewcli(dp)(a0)
CliInitRun(dp)(a0)
WriteChars(buf,buflen)(d1/d2)
PutStr(str)(d1)
VPrintf(format,argarray)(d1/d2)
*--- (1 function slot reserved here) ---
##bias 966
* these were unimplemented until dos 36.147
ParsePatternNoCase(pat,buf,buflen)(d1/d2/d3)
MatchPatternNoCase(pat,str)(d1/d2)
##private
dosPrivate5()()
##public
* this was added for V37 dos, returned 0 before then.
SameDevice(lock1,lock2)(d1/d2)
##private
* These were added in dos 36.147
*--- (4 function slots reserved here) ---
##bias 1014
* these were added in dos 37.1
*--- (2 function slots reserved here) ---
##bias 1026
* these were added in dos 37.8
*--- (2 function slots reserved here) ---
##bias 1038
##end


FD/mathieeedoubtrans_lib.fd

* "mathieeedoubtrans.library"
##base _MathIeeeDoubTransBase
##bias 30
##public
IEEEDPAtan(parm)(d0/d1)
IEEEDPSin(parm)(d0/d1)
IEEEDPCos(parm)(d0/d1)
IEEEDPTan(parm)(d0/d1)
IEEEDPSincos(pf2,parm)(a0,d0/d1)
IEEEDPSinh(parm)(d0/d1)
IEEEDPCosh(parm)(d0/d1)
IEEEDPTanh(parm)(d0/d1)
IEEEDPExp(parm)(d0/d1)
IEEEDPLog(parm)(d0/d1)
IEEEDPPow(exp,arg)(d2/d3,d0/d1)
IEEEDPSqrt(parm)(d0/d1)
IEEEDPTieee(parm)(d0/d1)
IEEEDPFieee(single)(d0)
IEEEDPAsin(parm)(d0/d1)
IEEEDPAcos(parm)(d0/d1)
IEEEDPLog10(parm)(d0/d1)
##end


FD/exec_lib.fd

* "exec.library"
##base _SysBase
##bias 30
##public
*------ misc ---------------------------------------------------------
Supervisor(userFunction)(a5)
*------ special patchable hooks to internal exec activity ------------
##private
execPrivate1()()
execPrivate2()()
execPrivate3()()
execPrivate4()()
execPrivate5()()
execPrivate6()()
##public
*------ module creation ----------------------------------------------
InitCode(startClass,version)(d0/d1)
InitStruct(initTable,memory,size)(a1/a2,d0)
MakeLibrary(funcInit,structInit,libInit,dataSize,segList)(a0/a1/a2,d0/d1)
MakeFunctions(target,functionArray,funcDispBase)(a0/a1/a2)
FindResident(name)(a1)
InitResident(resident,segList)(a1,d1)
*------ diagnostics --------------------------------------------------
Alert(alertNum)(d7)
Debug(flags)(d0)
*------ interrupts ---------------------------------------------------
Disable()()
Enable()()
Forbid()()
Permit()()
SetSR(newSR,mask)(d0/d1)
SuperState()()
UserState(sysStack)(d0)
SetIntVector(intNumber,interrupt)(d0/a1)
AddIntServer(intNumber,interrupt)(d0/a1)
RemIntServer(intNumber,interrupt)(d0/a1)
Cause(interrupt)(a1)
*------ memory allocation --------------------------------------------
Allocate(freeList,byteSize)(a0,d0)
Deallocate(freeList,memoryBlock,byteSize)(a0/a1,d0)
AllocMem(byteSize,requirements)(d0/d1)
AllocAbs(byteSize,location)(d0/a1)
FreeMem(memoryBlock,byteSize)(a1,d0)
AvailMem(requirements)(d1)
AllocEntry(entry)(a0)
FreeEntry(entry)(a0)
*------ lists --------------------------------------------------------
Insert(list,node,pred)(a0/a1/a2)
AddHead(list,node)(a0/a1)
AddTail(list,node)(a0/a1)
Remove(node)(a1)
RemHead(list)(a0)
RemTail(list)(a0)
Enqueue(list,node)(a0/a1)
FindName(list,name)(a0/a1)
*------ tasks --------------------------------------------------------
AddTask(task,initPC,finalPC)(a1/a2/a3)
RemTask(task)(a1)
FindTask(name)(a1)
SetTaskPri(task,priority)(a1,d0)
SetSignal(newSignals,signalSet)(d0/d1)
SetExcept(newSignals,signalSet)(d0/d1)
Wait(signalSet)(d0)
Signal(task,signalSet)(a1,d0)
AllocSignal(signalNum)(d0)
FreeSignal(signalNum)(d0)
AllocTrap(trapNum)(d0)
FreeTrap(trapNum)(d0)
*------ messages -----------------------------------------------------
AddPort(port)(a1)
RemPort(port)(a1)
PutMsg(port,message)(a0/a1)
GetMsg(port)(a0)
ReplyMsg(message)(a1)
WaitPort(port)(a0)
FindPort(name)(a1)
*------ libraries ----------------------------------------------------
AddLibrary(library)(a1)
RemLibrary(library)(a1)
OldOpenLibrary(libName)(a1)
CloseLibrary(library)(a1)
SetFunction(library,funcOffset,newFunction)(a1,a0,d0)
SumLibrary(library)(a1)
*------ devices ------------------------------------------------------
AddDevice(device)(a1)
RemDevice(device)(a1)
OpenDevice(devName,unit,ioRequest,flags)(a0,d0/a1,d1)
CloseDevice(ioRequest)(a1)
DoIO(ioRequest)(a1)
SendIO(ioRequest)(a1)
CheckIO(ioRequest)(a1)
WaitIO(ioRequest)(a1)
AbortIO(ioRequest)(a1)
*------ resources ----------------------------------------------------
AddResource(resource)(a1)
RemResource(resource)(a1)
OpenResource(resName)(a1)
*------ private diagnostic support -----------------------------------
##private
execPrivate7()()
execPrivate8()()
execPrivate9()()
##public
*------ misc ---------------------------------------------------------
RawDoFmt(formatString,dataStream,putChProc,putChData)(a0/a1/a2/a3)
GetCC()()
TypeOfMem(address)(a1)
Procure(semaport,bidMsg)(a0/a1)
Vacate(semaport)(a0)
OpenLibrary(libName,version)(a1,d0)
*--- functions in V33 or higher (distributed as Release 1.2) ---
*------ signal semaphores (note funny registers)----------------------
InitSemaphore(sigSem)(a0)
ObtainSemaphore(sigSem)(a0)
ReleaseSemaphore(sigSem)(a0)
AttemptSemaphore(sigSem)(a0)
ObtainSemaphoreList(sigSem)(a0)
ReleaseSemaphoreList(sigSem)(a0)
FindSemaphore(sigSem)(a1)
AddSemaphore(sigSem)(a1)
RemSemaphore(sigSem)(a1)
*------ kickmem support ----------------------------------------------
SumKickData()()
*------ more memory support ------------------------------------------
AddMemList(size,attributes,pri,base,name)(d0/d1/d2/a0/a1)
CopyMem(source,dest,size)(a0/a1,d0)
CopyMemQuick(source,dest,size)(a0/a1,d0)
*------ cache --------------------------------------------------------
*--- functions in V36 or higher (distributed as Release 2.0) ---
CacheClearU()()
CacheClearE(address,length,caches)(a0,d0/d1)
CacheControl(cacheBits,cacheMask)(d0/d1)
*------ misc ---------------------------------------------------------
CreateIORequest(port,size)(a0,d0)
DeleteIORequest(iorequest)(a0)
CreateMsgPort()()
DeleteMsgPort(port)(a0)
ObtainSemaphoreShared(sigSem)(a0)
*------ even more memory support -------------------------------------
AllocVec(byteSize,requirements)(d0/d1)
FreeVec(memoryBlock)(a1)
CreatePrivatePool(requirements,puddleSize,puddleThresh)(d0/d1/d2)
DeletePrivatePool(poolHeader)(a0)
AllocPooled(memSize,poolHeader)(d0/a0)
FreePooled(memory,poolHeader)(a1,a0)
*------ misc ---------------------------------------------------------
AttemptSemaphoreShared(sigSem)(a0)
ColdReboot()()
StackSwap(newStack)(a0)
*------ task trees ---------------------------------------------------
ChildFree(tid)(d0)
ChildOrphan(tid)(d0)
ChildStatus(tid)(d0)
ChildWait(tid)(d0)
*------ future expansion ---------------------------------------------
CachePreDMA(address,length,flags)(a0/a1,d1)
CachePostDMA(address,length,flags)(a0/a1,d1)
##private
execPrivate10()()
execPrivate11()()
execPrivate12()()
execPrivate13()()
##public
##end


FD/mathieeesingbas_lib.fd

* "mathieeesingbas.library"
##base _MathIeeeSingBasBase
##bias 30
##public
IEEESPFix(parm)(d0)
IEEESPFlt(integer)(d0)
IEEESPCmp(leftParm,rightParm)(d0/d1)
IEEESPTst(parm)(d0)
IEEESPAbs(parm)(d0)
IEEESPNeg(parm)(d0)
IEEESPAdd(leftParm,rightParm)(d0/d1)
IEEESPSub(leftParm,rightParm)(d0/d1)
IEEESPMul(leftParm,rightParm)(d0/d1)
IEEESPDiv(dividend,divisor)(d0/d1)
IEEESPFloor(parm)(d0)
IEEESPCeil(parm)(d0)
##end


FD/expansion_lib.fd

* "expansion.library"
##base _ExpansionBase
##bias 30
##public
*--- functions in V33 or higher (distributed as Release 1.2) ---
AddConfigDev(configDev)(a0)
*--- functions in V36 or higher (distributed as Release 2.0) ---
AddBootNode(bootPri,flags,deviceNode,configDev)(d0/d1/a0/a1)
*--- functions in V33 or higher (distributed as Release 1.2) ---
AllocBoardMem(slotSpec)(d0)
AllocConfigDev()()
AllocExpansionMem(numSlots,slotAlign)(d0/d1)
ConfigBoard(board,configDev)(a0/a1)
ConfigChain(baseAddr)(a0)
FindConfigDev(oldConfigDev,manufacturer,product)(a0,d0/d1)
FreeBoardMem(startSlot,slotSpec)(d0/d1)
FreeConfigDev(configDev)(a0)
FreeExpansionMem(startSlot,numSlots)(d0/d1)
ReadExpansionByte(board,offset)(a0,d0)
ReadExpansionRom(board,configDev)(a0/a1)
RemConfigDev(configDev)(a0)
WriteExpansionByte(board,offset,byte)(a0,d0/d1)
ObtainConfigBinding()()
ReleaseConfigBinding()()
SetCurrentBinding(currentBinding,bindingSize)(a0,d0)
GetCurrentBinding(currentBinding,bindingSize)(a0,d0)
MakeDosNode(parmPacket)(a0)
AddDosNode(bootPri,flags,deviceNode)(d0/d1/a0)
##private
*--- functions in V36 or higher (distributed as Release 2.0) ---
expansionPrivate1()()
expansionPrivate2()()
##end


FD/mathieeesingtrans_lib.fd

* "mathieeesingtrans.library"
##base _MathIeeeSingTransBase
##bias 30
##public
IEEESPAtan(parm)(d0)
IEEESPSin(parm)(d0)
IEEESPCos(parm)(d0)
IEEESPTan(parm)(d0)
IEEESPSincos(cosptr,parm)(a0,d0)
IEEESPSinh(parm)(d0)
IEEESPCosh(parm)(d0)
IEEESPTanh(parm)(d0)
IEEESPExp(parm)(d0)
IEEESPLog(parm)(d0)
IEEESPPow(exp,arg)(d1,d0)
IEEESPSqrt(parm)(d0)
IEEESPTieee(parm)(d0)
IEEESPFieee(parm)(d0)
IEEESPAsin(parm)(d0)
IEEESPAcos(parm)(d0)
IEEESPLog10(parm)(d0)
##end


FD/gadtools_lib.fd

* "gadtools.library"
##base _GadToolsBase
##bias 30
##public
*--- functions in V36 or higher (distributed as Release 2.0) ---
*
* Gadget Functions
*
CreateGadgetA(kind,gad,ng,taglist)(d0/a0/a1/a2)
FreeGadgets(gad)(a0)
GT_SetGadgetAttrsA(gad,win,req,taglist)(a0/a1/a2/a3)
*
* Menu functions
*
CreateMenusA(newmenu,taglist)(a0/a1)
FreeMenus(menu)(a0)
LayoutMenuItemsA(firstitem,vi,taglist)(a0/a1/a2)
LayoutMenusA(firstmenu,vi,taglist)(a0/a1/a2)
*
* Misc Event-Handling Functions
*
GT_GetIMsg(iport)(a0)
GT_ReplyIMsg(imsg)(a1)
GT_RefreshWindow(win,req)(a0/a1)
GT_BeginRefresh(win)(a0)
GT_EndRefresh(win,complete)(a0,d0)
GT_FilterIMsg(imsg)(a1)
GT_PostFilterIMsg(imsg)(a1)
CreateContext(glistptr)(a0)
*
* Rendering Functions
*
DrawBevelBoxA(rport,left,top,width,height,taglist)(a0,d0/d1/d2/d3/a1)
*
* Visuals Functions
*
GetVisualInfoA(screen,taglist)(a0/a1)
FreeVisualInfo(vi)(a0)
##private
*
* Reserved entries
*
gadtoolsPrivate1()()
gadtoolsPrivate2()()
gadtoolsPrivate3()()
gadtoolsPrivate4()()
gadtoolsPrivate5()()
gadtoolsPrivate6()()
##end


FD/mathtrans_lib.fd

* "mathtrans.library"
##base _MathTransBase
##bias 30
##public
SPAtan(parm)(d0)
SPSin(parm)(d0)
SPCos(parm)(d0)
SPTan(parm)(d0)
SPSincos(cosResult,parm)(d1,d0)
SPSinh(parm)(d0)
SPCosh(parm)(d0)
SPTanh(parm)(d0)
SPExp(parm)(d0)
SPLog(parm)(d0)
SPPow(power,arg)(d1,d0)
SPSqrt(parm)(d0)
SPTieee(parm)(d0)
SPFieee(parm)(d0)
*--- functions in V31 or higher (distributed as Release 1.1) ---
SPAsin(parm)(d0)
SPAcos(parm)(d0)
SPLog10(parm)(d0)
##end


FD/graphics_lib.fd

* "graphics.library"
##base _GfxBase
##bias 30
##public
*------ BitMap primitives ------
BltBitMap(srcBitMap,xSrc,ySrc,destBitMap,xDest,yDest,xSize,ySize,minterm,mask,tempA)(a0,d0/d1/a1,d2/d3/d4/d5/d6/d7/a2)
BltTemplate(source,xSrc,srcMod,destRP,xDest,yDest,xSize,ySize)(a0,d0/d1/a1,d2/d3/d4/d5)
*------ Text routines ------
ClearEOL(rp)(a1)
ClearScreen(rp)(a1)
TextLength(rp,string,count)(a1,a0,d0)
Text(rp,string,count)(a1,a0,d0)
SetFont(rp,textFont)(a1,a0)
OpenFont(textAttr)(a0)
CloseFont(textFont)(a1)
AskSoftStyle(rp)(a1)
SetSoftStyle(rp,style,enable)(a1,d0/d1)
*------	Gels routines ------
AddBob(bob,rp)(a0/a1)
AddVSprite(vSprite,rp)(a0/a1)
DoCollision(rp)(a1)
DrawGList(rp,vp)(a1,a0)
InitGels(head,tail,gelsInfo)(a0/a1/a2)
InitMasks(vSprite)(a0)
RemIBob(bob,rp,vp)(a0/a1/a2)
RemVSprite(vSprite)(a0)
SetCollision(num,routine,gelsInfo)(d0/a0/a1)
SortGList(rp)(a1)
AddAnimOb(anOb,anKey,rp)(a0/a1/a2)
Animate(anKey,rp)(a0/a1)
GetGBuffers(anOb,rp,flag)(a0/a1,d0)
InitGMasks(anOb)(a0)
*------	General graphics routines ------
DrawEllipse(rp,xCenter,yCenter,a,b)(a1,d0/d1/d2/d3)
AreaEllipse(rp,xCenter,yCenter,a,b)(a1,d0/d1/d2/d3)
LoadRGB4(vp,colors,count)(a0/a1,d0)
InitRastPort(rp)(a1)
InitVPort(vp)(a0)
MrgCop(view)(a1)
MakeVPort(view,vp)(a0/a1)
LoadView(view)(a1)
WaitBlit()()
SetRast(rp,pen)(a1,d0)
Move(rp,x,y)(a1,d0/d1)
Draw(rp,x,y)(a1,d0/d1)
AreaMove(rp,x,y)(a1,d0/d1)
AreaDraw(rp,x,y)(a1,d0/d1)
AreaEnd(rp)(a1)
WaitTOF()()
QBlit(blit)(a1)
InitArea(areaInfo,vectorBuffer,maxVectors)(a0/a1,d0)
SetRGB4(vp,index,red,green,blue)(a0,d0/d1/d2/d3)
QBSBlit(blit)(a1)
BltClear(memBlock,byteCount,flags)(a1,d0/d1)
RectFill(rp,xMin,yMin,xMax,yMax)(a1,d0/d1/d2/d3)
BltPattern(rp,mask,xMin,yMin,xMax,yMax,maskBPR)(a1,a0,d0/d1/d2/d3/d4)
ReadPixel(rp,x,y)(a1,d0/d1)
WritePixel(rp,x,y)(a1,d0/d1)
Flood(rp,mode,x,y)(a1,d2,d0/d1)
PolyDraw(rp,count,polyTable)(a1,d0/a0)
SetAPen(rp,pen)(a1,d0)
SetBPen(rp,pen)(a1,d0)
SetDrMd(rp,drawMode)(a1,d0)
InitView(view)(a1)
CBump(copList)(a1)
CMove(copList,destination,data)(a1,d0/d1)
CWait(copList,v,h)(a1,d0/d1)
VBeamPos()()
InitBitMap(bitMap,depth,width,height)(a0,d0/d1/d2)
ScrollRaster(rp,dx,dy,xMin,yMin,xMax,yMax)(a1,d0/d1/d2/d3/d4/d5)
WaitBOVP(vp)(a0)
GetSprite(sprite,num)(a0,d0)
FreeSprite(num)(d0)
ChangeSprite(vp,sprite,newData)(a0/a1/a2)
MoveSprite(vp,sprite,x,y)(a0/a1,d0/d1)
LockLayerRom(layer)(a5)
UnlockLayerRom(layer)(a5)
SyncSBitMap(layer)(a0)
CopySBitMap(layer)(a0)
OwnBlitter()()
DisownBlitter()()
InitTmpRas(tmpRas,buffer,size)(a0/a1,d0)
AskFont(rp,textAttr)(a1,a0)
AddFont(textFont)(a1)
RemFont(textFont)(a1)
AllocRaster(width,height)(d0/d1)
FreeRaster(p,width,height)(a0,d0/d1)
AndRectRegion(region,rectangle)(a0/a1)
OrRectRegion(region,rectangle)(a0/a1)
NewRegion()()
ClearRectRegion(region,rectangle)(a0/a1)
ClearRegion(region)(a0)
DisposeRegion(region)(a0)
FreeVPortCopLists(vp)(a0)
FreeCopList(copList)(a0)
ClipBlit(srcRP,xSrc,ySrc,destRP,xDest,yDest,xSize,ySize,minterm)(a0,d0/d1/a1,d2/d3/d4/d5/d6)
XorRectRegion(region,rectangle)(a0/a1)
FreeCprList(cprList)(a0)
GetColorMap(entries)(d0)
FreeColorMap(colorMap)(a0)
GetRGB4(colorMap,entry)(a0,d0)
ScrollVPort(vp)(a0)
UCopperListInit(uCopList,n)(a0,d0)
FreeGBuffers(anOb,rp,flag)(a0/a1,d0)
BltBitMapRastPort(srcBitMap,xSrc,ySrc,destRP,xDest,yDest,xSize,ySize,minterm)(a0,d0/d1/a1,d2/d3/d4/d5/d6)
OrRegionRegion(srcRegion,destRegion)(a0/a1)
XorRegionRegion(srcRegion,destRegion)(a0/a1)
AndRegionRegion(srcRegion,destRegion)(a0/a1)
SetRGB4CM(colorMap,index,red,green,blue)(a0,d0/d1/d2/d3)
BltMaskBitMapRastPort(srcBitMap,xSrc,ySrc,destRP,xDest,yDest,xSize,ySize,minterm,bltMask)(a0,d0/d1/a1,d2/d3/d4/d5/d6/a2)
*--- (2 function slots reserved here) ---
##bias 654
AttemptLockLayerRom(layer)(a5)
*--- functions in V36 or higher (distributed as Release 2.0) ---
GfxNew(gfxNodeType)(d0)
GfxFree(gfxNodePtr)(a0)
GfxAssociate(associateNode,gfxNodePtr)(a0/a1)
BitMapScale(bitScaleArgs)(a0)
ScalerDiv(factor,numerator,denominator)(d0/d1/d2)
TextExtent(rp,string,count,textExtent)(a1,a0,d0/a2)
TextFit(rp,string,strLen,textExtent,constrainingExtent,strDirection,constrainingBitWidth,constrainingBitHeight)(a1,a0,d0/a2/a3,d1/d2/d3)
GfxLookUp(associateNode)(a0)
VideoControl(colorMap,tagarray)(a0/a1)
OpenMonitor(monitorName,displayID)(a1,d0)
CloseMonitor(monitorSpec)(a0)
FindDisplayInfo(displayID)(d0)
NextDisplayInfo(displayID)(d0)
##private
graphicsPrivate1()()
graphicsPrivate2()()
graphicsPrivate3()()
##public
GetDisplayInfoData(handle,buf,size,tagID,displayID)(a0/a1,d0/d1/d2)
FontExtent(font,fontExtent)(a0/a1)
ReadPixelLine8(rp,xstart,ystart,width,array,tempRP)(a0,d0/d1/d2/a2,a1)
WritePixelLine8(rp,xstart,ystart,width,array,tempRP)(a0,d0/d1/d2/a2,a1)
ReadPixelArray8(rp,xstart,ystart,xstop,ystop,array,temprp)(a0,d0/d1/d2/d3/a2,a1)
WritePixelArray8(rp,xstart,ystart,xstop,ystop,array,temprp)(a0,d0/d1/d2/d3/a2,a1)
GetVPModeID(vp)(a0)
ModeNotAvailable(modeID)(d0)
WeighTAMatch(reqTextAttr,targetTextAttr,targetTags)(a0/a1/a2)
EraseRect(rp,xMin,yMin,xMax,yMax)(a1,d0/d1/d2/d3)
ExtendFont(font,fontTags)(a0/a1)
StripFont(font)(a0)
##end


FD/misc_lib.fd

##base _MiscBase
##bias 6
##public
AllocMiscResource(unitNum,name)(d0/a1)
FreeMiscResource(unitNum)(d0)
##end


Text_Autodocs/amiga_lib.doc

TABLE OF CONTENTS

amiga.lib/AddTOF
amiga.lib/afp
amiga.lib/ArgArrayDone
amiga.lib/ArgArrayInit
amiga.lib/ArgInt
amiga.lib/ArgString
amiga.lib/arnd
amiga.lib/BeginIO
amiga.lib/CallHook
amiga.lib/CallHookA
amiga.lib/CheckRexxMsg
amiga.lib/CoerceMethod
amiga.lib/CoerceMethodA
amiga.lib/CreateExtIO
amiga.lib/CreatePort
amiga.lib/CreateStdIO
amiga.lib/CreateTask
amiga.lib/CxCustom
amiga.lib/CxDebug
amiga.lib/CxFilter
amiga.lib/CxSender
amiga.lib/CxSignal
amiga.lib/CxTranslate
amiga.lib/dbf
amiga.lib/DeleteExtIO
amiga.lib/DeletePort
amiga.lib/DeleteStdIO
amiga.lib/DeleteTask
amiga.lib/DoMethod
amiga.lib/DoMethodA
amiga.lib/DoSuperMethod
amiga.lib/DoSuperMethodA
amiga.lib/FastRand
amiga.lib/fpa
amiga.lib/FreeIEvents
amiga.lib/GetRexxVar
amiga.lib/HookEntry
amiga.lib/HotKey
amiga.lib/InvertString
amiga.lib/NewList
amiga.lib/printf
amiga.lib/RangeRand
amiga.lib/RemTOF
amiga.lib/SetRexxVar
amiga.lib/SetSuperAttrs
amiga.lib/sprintf
amiga.lib/stdio
amiga.lib/TimeDelay
 amiga.lib/AddTOF                                             amiga.lib/AddTOF

   NAME
    AddTOF - add a task to the VBlank interrupt server chain.

   SYNOPSIS
    AddTOF(i,p,a);

    VOID AddTOF(struct Isrvstr *, APTR, APTR);

   FUNCTION
    Adds a task to the vertical-blanking interval interrupt server
    chain. This prevents C programmers from needing to write an
    assembly language stub to do this function.

   INPUTS
    i - pointer to an initialized Isrvstr structure
    p - pointer to the C-code routine that this server is to call each
        time TOF happens
    a - pointer to the first longword in an array of longwords that
        is to be used as the arguments passed to your routine
        pointed to by p.

   SEE ALSO
    RemTOF(), <graphics/graphint.h>

 amiga.lib/afp                                                   amiga.lib/afp

   NAME
    afp - Convert ASCII string variable into fast floating point

   SYNOPSIS
    ffp_value = afp(string);

    FUNCTION
    Accepts the address of the ASCII string in C format that is
    converted into an FFP floating point number.

    The string is expected in this Format:
    {S}{digits}{'.'}{digits}{'E'}{S}{digits}
    <*******MANTISSA*******><***EXPONENT***>

    Syntax rules:
    Both signs are optional and are '+' or '-'. The mantissa must be
    present. The exponent need not be present. The mantissa may lead
    with a decimal point. The mantissa need not have a decimal point.
    Examples: All of these values represent the number fourty-two.
             42 	   .042e3
             42.	  +.042e+03
            +42.	  0.000042e6
        0000042.00	 420000e-4
                 420000.00e-0004

    Floating point range:
    Fast floating point supports the value zero and non-zero values
    within the following bounds -
            18			       20
     9.22337177 x 10   > +number >	5.42101070 x 10
            18			       -20
    -9.22337177 x 10   > -number > -2.71050535 x 10

    Precision:
    This conversion results in a 24 bit precision with guaranteed
    error less than or equal to one-half least significant bit.

    INPUTS
    string - Pointer to the ASCII string to be converted.

    OUTPUTS
    string - points to the character which terminated the scan
    equ - fast floating point equivalent
 amiga.lib/ArgArrayDone                                 amiga.lib/ArgArrayDone

   NAME
    ArgArrayDone -- release the memory allocated by a previous call
            to ArgArrayInit(). (V36)

   SYNOPSIS
    ArgArrayDone();

    VOID ArgArrayDone(VOID);

   FUNCTION
    This function frees memory and does cleanup required after a
    call to ArgArrayInit(). Don't call this until you are done using
    the ToolTypes argument strings.

   SEE ALSO
    ArgArrayInit()

 amiga.lib/ArgArrayInit                                 amiga.lib/ArgArrayInit

   NAME
    ArgArrayInit -- allocate and initialize a tooltype array. (V36)

   SYNOPSIS
    ttypes = ArgArrayInit(argc,argv);

    UBYTE **ArgArrayInit(LONG,UBYTE **);

   FUNCTION
    This function returns a null-terminated array of strings
    suitable for sending to icon.library/FindToolType(). This array will
    be the ToolTypes array of the program's icon, if it was started from
    Workbench. It will just be 'argv' if the program was started from
    a shell.

    Pass ArgArrayInit() your startup arguments received by main().

    ArgArrayInit() requires that icon.library be open (even if the caller
    was started from a shell, so that the function FindToolType() can be
    used) and may call GetDiskObject(), so clean up is necessary when
    the strings are no longer needed. The function ArgArrayDone() does
    just that.

   INPUTS
    argc - the number of arguments in argv, 0 when started from Workbench
    argv - an array of pointers to the program's arguments, or the
           Workbench startup message when started from WB.

   RESULTS
    ttypes - the initialized argument array or NULL if it could not be
             allocated

   EXAMPLE
    Use of these routines facilitates the use of ToolTypes or command-
    line arguments to control end-user parameters in Commodities
    applications. For example, a filter used to trap a keystroke for
    popping up a window might be created by something like this:

            char   *ttypes  = ArgArrayInit(argc, argv);
            CxObj   *filter = UserFilter(ttypes, "POPWINDOW", "alt f1");

               ... with ...

               CxObj *UserFilter(char **tt, char *action_name,
                  char *default_descr)
        {
        char *desc;

            desc = FindToolType(tt,action_name);

            return(CxFilter((ULONG)(desc? desc: default_descr)));
        }

    In this way the user can assign "alt f2" to the action by
    entering a tooltype in the program's icon of the form:

        POPWINDOW=alt f2

    or by starting the program from the CLI like so:

        myprogram "POPWINDOW=alt f2"

   NOTE
    Your program must open icon.library and set up IconBase before calling
    this routine. In addition IconBase must remain valid until after
    ArgArrayDone() has been called!

   SEE ALSO
    ArgArrayDone(), ArgString(), ArgInt(), icon.library/FindToolType()

 amiga.lib/ArgInt                                             amiga.lib/ArgInt

   NAME
    ArgInt -- return an integer value from a ToolTypes array. (V36)

   SYNOPSIS
    value = ArgInt(tt,entry,defaultval)

    LONG ArgInt(UBYTE **,STRPTR,LONG);

   FUNCTION
    This function looks in the ToolTypes array 'tt' returned
    by ArgArrayInit() for 'entry' and returns the value associated
    with it. 'tt' is in standard ToolTypes format such as:

        ENTRY=Value

    The Value string is passed to atoi() and the result is returned by
    this function.

    If 'entry' is not found, the integer 'defaultval' is returned.

   INPUTS
    tt - a ToolTypes array as returned by ArgArrayInit()
    entry - the entry in the ToolTypes array to search for
    defaultval - the value to return in case 'entry' is not found within
             the ToolTypes array

   RESULTS
    value - the value associated with 'entry', or defaultval if 'entry'
        is not in the ToolTypes array

   NOTES
    This function requires that dos.library V36 or higher be opened.

   SEE ALSO
    ArgArrayInit()

 amiga.lib/ArgString                                       amiga.lib/ArgString

   NAME
    ArgString -- return a string pointer from a ToolTypes array. (V36)

   SYNOPSIS
    string = ArgString(tt,entry,defaultstring)

    STRPTR ArgString(UBYTE **,STRPTR,STRPTR);

   FUNCTION
    This function looks in the ToolTypes array 'tt' returned
    by ArgArrayInit() for 'entry' and returns the value associated
    with it. 'tt' is in standard ToolTypes format such as:

        ENTRY=Value

    This function returns a pointer to the Value string.

    If 'entry' is not found, 'defaultstring' is returned.

   INPUTS
    tt - a ToolTypes array as returned by ArgArrayInit()
    entry - the entry in the ToolTypes array to search for
    defaultstring - the value to return in case 'entry' is not found within
                the ToolTypes array

   RESULTS
    value - the value associated with 'entry', or defaultstring if 'entry'
        is not in the ToolTypes array

   SEE ALSO
    ArgArrayInit()

 amiga.lib/arnd                                                 amiga.lib/arnd

  NAME
    arnd - ASCII round of the provided floating point string

   SYNOPSIS
    arnd(place, exp, &string[0]);

   FUNCTION
    Accepts an ASCII string representing an FFP floating point
    number, the binary representation of the exponent of said
    floating point number and the number of places to round to.
    A rounding process is initiated, either to the left or right
    of the decimal place and the result placed back at the
    input address defined by &string[0].

   INPUTS
    place - integer representing number of decimal places to round to
    exp - integer representing exponent value of the ASCII string
    &string[0] - address where rounded ASCII string is to be placed
             (16 bytes)

   RESULT
    &string[0] - rounded ASCII string

   BUGS
    None
 amiga.lib/BeginIO                                           amiga.lib/BeginIO

   NAME
    BeginIO -- initiate asynchronous device I/O

   SYNOPSIS
    BeginIO(ioReq)

    VOID BeginIO(struct IORequest *);

   FUNCTION
    This function takes an IORequest, and passes it directly to the
    "BeginIO" vector of the proper device.  This is equivalent to
    SendIO(), except that io_Flags is not cleared. A good understanding
    of Exec device I/O is required to properly use this function.

    This function does not wait for the I/O to complete.

   INPUTS
    ioReq - an initialized and opened IORequest structure with the
            io_Flags field set to a reasonable value (set to 0 if you do
        not require io_Flags).

   SEE ALSO
    exec.library/DoIO(), exec.library/SendIO(), exec.library/WaitIO()

 amiga.lib/CallHook                                         amiga.lib/CallHook

   NAME
    CallHook -- Invoke a hook given a message on the stack.  (V36)

   SYNOPSIS
    result = CallHook( hookPtr, obj, ... )

    ULONG CallHook( struct Hook *, Object *, ... );

   FUNCTION
    Like CallHookA(), CallHook() invoke a hook on the supplied
    hook-specific data (an "object") and a parameter packet ("message").
    However, CallHook() allows you to build the message on your stack.

   INPUTS
    hookPtr - A system-standard hook
    obj - hook-specific data object
    ... - The hook-specific message you wish to send.  The hook is
        expecting a pointer to the message, so a pointer into your
        stack will be sent.

   RESULT
    result - a hook-specific result.

   NOTES
    While this function requires V36 or higher intuition.library,
    it first appeared in V37 amiga.lib.

   EXAMPLE
    If your hook's message was

        struct myMessage
        {
        ULONG mm_FirstGuy;
        ULONG mm_SecondGuy;
        ULONG mm_ThirdGuy;
        };

    You could write:

        result = CallHook( hook, obj, firstguy, secondguy, thirdguy );

    as a shorthand for:

        struct myMessage msg;

        msg.mm_FirstGuy = firstguy;
        msg.mm_SecondGuy = secondguy;
        msg.mm_ThirdGuy = thirdguy;

        result = CallHookA( hook, obj, &msg );

   SEE ALSO
    CallHookA(), utility.library/CallHookPkt(), <utility/hooks.h>

 amiga.lib/CallHookA                                       amiga.lib/CallHookA

   NAME
    CallHookA -- Invoke a hook given a pointer to a message.  (V36)

   SYNOPSIS
    result = CallHookA( hookPtr, obj, message )

    ULONG CallHook( struct Hook *, Object *, APTR );

   FUNCTION
    Invoke a hook on the supplied hook-specific data (an "object")
    and a parameter packet ("message").  This function is equivalent
    to utility.library/CallHookPkt().

   INPUTS
    hookPtr - A system-standard hook
    obj - hook-specific data object
    message - The hook-specific message you wish to send

   RESULT
    result - a hook-specific result.

   NOTES
    While this function requires V36 or higher intuition.library,
    it first appeared in V37 amiga.lib.

   SEE ALSO
    CallHook(), utility.library/CallHookPkt(), <utility/hooks.h>

 amiga.lib/CheckRexxMsg                                 amiga.lib/CheckRexxMsg

   NAME
    CheckRexxMsg - Check if a RexxMsg is from ARexx

   SYNOPSIS
    result = CheckRexxMsg(message)
    D0                    A0

    BOOL CheckRexxMsg(struct RexxMsg *);

   FUNCTION
    This function checks to make sure that the message is from ARexx
    directly.  It is required when using the Rexx Variable Interface
    routines (RVI) that the message be from ARexx.

    While this function is new in the V37 amiga.lib, it is safe to
    call it in all versions of the operating system.  It is also
    PURE code, thus usable in resident/pure executables.

   NOTE
    This is a stub in amiga.lib.  It is only available via amiga.lib.
    The stub has two labels.  One, _CheckRexxMsg, takes the arguments
    from the stack.  The other, CheckRexxMsg, takes the arguments in
    registers.

   EXAMPLE
    if (CheckRexxMsg(rxmsg))
    {
        /* Message is one from ARexx */
    }

   INPUTS
    message		A pointer to the RexxMsg in question

   RESULTS
    result		A boolean - TRUE if message is from ARexx.

   SEE ALSO
    GetRexxVar(), SetRexxVar()

 amiga.lib/CoerceMethod                                 amiga.lib/CoerceMethod

   NAME
    CoerceMethod -- Perform method on coerced object.  (V36)

   SYNOPSIS
    result = CoerceMethod( cl, obj, MethodID, ... )

    ULONG CoerceMethod( struct IClass *, Object *, ULONG, ... );

   FUNCTION
    Boopsi support function that invokes the supplied message
    on the specified object, as though it were the specified
    class.  Equivalent to CoerceMethodA(), but allows you to
    build the message on the stack.

   INPUTS
    cl - pointer to boopsi class to receive the message
    obj - pointer to boopsi object
    ... - method-specific message built on the stack

   RESULT
    result - class and message-specific result.

   NOTES
    While this function requires V36 or higher intuition.library,
    it first appeared in V37 amiga.lib.

   SEE ALSO
    CoerceMethodA(), DoMethodA(), DoSuperMethodA(), <intuition/classusr.h>
    ROM Kernel Manual boopsi section

 amiga.lib/CoerceMethodA                               amiga.lib/CoerceMethodA

   NAME
    CoerceMethodA -- Perform method on coerced object.  (V36)

   SYNOPSIS
    result = CoerceMethodA( cl, obj, msg )

    ULONG CoerceMethodA( struct IClass *, Object *, Msg * );

   FUNCTION
    Boopsi support function that invokes the supplied message
    on the specified object, as though it were the specified
    class.

   INPUTS
    cl - pointer to boopsi class to receive the message
    obj - pointer to boopsi object
    msg - pointer to method-specific message to send

   RESULT
    result - class and message-specific result.

   NOTES
    While this function requires V36 or higher intuition.library,
    it first appeared in V37 amiga.lib.
    Some early example code may refer to this function as CM().

   SEE ALSO
    CoerceMethod(), DoMethodA(), DoSuperMethodA(), <intuition/classusr.h>
    ROM Kernel Manual boopsi section

 amiga.lib/CreateExtIO                                   amiga.lib/CreateExtIO

   NAME
    CreateExtIO -- create an IORequest structure

   SYNOPSIS
    ioReq = CreateExtIO(port,ioSize);

    struct IORequest *CreateExtIO(struct MsgPort *, ULONG);

   FUNCTION
    Allocates memory for and initializes a new IO request block
    of a user-specified number of bytes. The number of bytes
    MUST be the size of a legal IORequest (or extended IORequest)
    or very nasty things will happen.

   INPUTS
    port - an already initialized message port to be used for this IO
           request's reply port. If this is NULL this function fails.
    ioSize - the size of the IO request to be created.

   RESULT
    ioReq - a new IO Request block, or NULL if there was not enough memory

   EXAMPLE
    if (ioReq = CreateExtIO(CreatePort(NULL,0),sizeof(struct IOExtTD)))

   SEE ALSO
    DeleteExtIO(), CreatePort(), exec.library/CreateMsgPort()

 amiga.lib/CreatePort                                     amiga.lib/CreatePort

   NAME
    CreatePort - Allocate and initialize a new message port

   SYNOPSIS
    port = CreatePort(name,pri)

    struct MsgPort *CreatePort(STRPTR,LONG);

   FUNCTION
    Allocates and initializes a new message port. The message list
    of the new port will be prepared for use (via NewList).  A signal
    bit will be allocated, and the port will be set to signal your
    task when a message arrives (PA_SIGNAL).

    You *must* use DeletePort() to delete ports created with
    CreatePort()!

   INPUTS
    name - public name of the port, or NULL if the port is not named.
           The name string is not copied. Most ports do not need names,
           see notes below on this.
    pri  - Priority used for insertion into the public port list,
           normally 0.

   RESULT
    port - a new MsgPort structure ready for use, or NULL if the port
           could not be created due to not enough memory or no available
           signal bit.

   NOTE
    In most cases, ports should not be named. Named ports are used for
    rendez-vous between tasks. Everytime a named port needs to be located,
    the list of all named ports must be traversed. The more named
    ports there are, the longer this list traversal takes. Thus, unless
    you really need to, do not name your ports, which will keep them off
    of the named port list and improve system performance.

   BUGS
    With versions of amiga.lib prior to V37.14, this function would
    not fail even though it couldn't allocate a signal bit. The port
    would be returned with no signal allocated.

   SEE ALSO
    DeletePort(), exec.library/FindPort(), <exec/ports.h>,
    exec.library/CreateMsgPort()

 amiga.lib/CreateStdIO                                   amiga.lib/CreateStdIO

   NAME
    CreateStdIO -- create an IOStdReq structure

   SYNOPSIS
    ioReq = CreateStdIO(port);

    struct IOStdReq *CreateStdIO(struct MsgPort *)

   FUNCTION
    Allocates memory for and initializes a new IOStdReq structure.

   INPUTS
    port - an already initialized message port to be used for this IO
           request's reply port. If this is NULL this function fails.

   RESULT
    ioReq - a new IOStdReq structure, or NULL if there was not enough
        memory

   SEE ALSO
    DeleteStdIO(), CreateExtIO(), exec.library/CreateIORequest()

 amiga.lib/CreateTask                                     amiga.lib/CreateTask

   NAME
    CreateTask -- Create task with given name, priority, stacksize

   SYNOPSIS
    task = CreateTask(name,pri,initPC,stackSize)

    struct Task *CreateTask(STRPTR,LONG,funcEntry,ULONG);

   FUNCTION
    This function simplifies program creation of sub-tasks by
    dynamically allocating and initializing required structures
    and stack space, and adding the task to Exec's task list
    with the given name and priority. A tc_MemEntry list is provided
    so that all stack and structure memory allocated by CreateTask()
    is automatically deallocated when the task is removed.

    An Exec task may not call dos.library functions or any function
    which might cause the loading of a disk-resident library, device,
    or file (since such functions are indirectly calls to dos.library).
    Only AmigaDOS Processes may call AmigaDOS; see the
    dos.library/CreateProc() or the dos.library/CreateNewProc()
    functions for more information.

    If other tasks or processes will need to find this task by name,
    provide a complex and unique name to avoid conflicts.

    If your compiler provides automatic insertion of stack-checking
    code, you may need to disable this feature when compiling sub-task
    code since the stack for the subtask is at a dynamically allocated
    location.  If your compiler requires 68000 registers to contain
    particular values for base relative addressing, you may need to
    save these registers from your main process, and restore them
    in your initial subtask code.

    The function entry initPC is generally provided as follows:

    In C:
    extern void functionName();
    char *tname = "unique name";
    task = CreateTask(tname, 0L, functionName, 4000L);

    In assembler:
        PEA	startLabel

   INPUTS
    name - a null-terminated name string
    pri - an Exec task priority between -128 and 127, normally 0
    funcEntry - the address of the first executable instruction
            of the subtask code
    stackSize - size in bytes of stack for the subtask. Don't cut it
            too close - system function stack usage may change.

   RESULT
    task - a pointer to the newly created task, or NULL if there was not
           enough memory.

   BUGS
    Under exec.library V37 or beyond, the AddTask() function used
    internally by CreateTask() can fail whereas it couldn't fail in
    previous versions of Exec. Prior to amiga.lib V37.14, this function
    did not check for failure of AddTask() and thus might return a
    pointer to a task structure even though the task was not actually
    added to the system.

   SEE ALSO
    DeleteTask(), exec/FindTask()

 amiga.lib/CxCustom                                         amiga.lib/CxCustom

   NAME
    CxCustom -- create a custom commodity object. (V36)

   SYNOPSIS
    customObj = CxCustom(action,id);

    CxObj *CxCustom(LONG(*)(),LONG);

   FUNCTION
    This function creates a custom commodity object. The action
    of this object on receiving a commodity message is to call a
    function of the application programmer's choice.

    The function provided ('action') will be passed a pointer to
    the actual commodities message (in commodities private data
    space), and will actually execute as part of the input handler
    system task. Among other things, the value of 'id' can be
    recovered from the message by using the function CxMsgID().

    The purpose of this function is two-fold. First, it allows
    programmers to create Commodities Exchange objects with
    functionality that was not imagined or chosen for inclusion
    by the designers. Secondly, this is the only way to act
    synchronously with Commodities.

    This function is a C-language macro for CreateCxObj(), defined
    in <libraries/commodities.h>.

   INPUTS
    action - a function to call whenever a message reaches the object
    id - a message id to assign to the object

   RESULTS
    customObj - a pointer to the new custom object, or NULL if it could
            not be created.

  SEE ALSO
    commodities.library/CreateCxObj(), commodities.library/CxMsgID()

 amiga.lib/CxDebug                                           amiga.lib/CxDebug

   NAME
    CxDebug -- create a commodity debug object. (V36)

   SYNOPSIS
    debugObj = CxDebug(id);

    CxObj *CxDebug(LONG);

   FUNCTION
    This function creates a Commodities debug object. The action of this
    object on receiving a Commodities message is to print out information
    about the Commodities message through the serial port (using the
    kprintf() routine). The value of 'id' will also be displayed.

    Note that this is a synchronous occurence (the printing is done by
    the input device task). If screen or file output is desired, using a
    sender object instead of a debug object is necessary, since such
    output is best done by your application process.

    This function is a C-language macro for CreateCxObj(), defined
    in <libraries/commodities.h>.

   INPUTS
    id - the id to assign to the debug object, this value is output
         whenever the debug object sends data to the serial port.

   RESULTS
    debugObj - a pointer to the debug object, or NULL if it could
           not be created.

   SEE ALSO
    commodities.library/CreateCxObj(), CxSender(), debug.lib/kprintf()

 amiga.lib/CxFilter                                         amiga.lib/CxFilter

   NAME
    CxFilter -- create a commodity filter object. (V36)

   SYNOPSIS
    filterObj = CxFilter(description);

    CxObj *CxFilter(STRPTR)

   FUNCTION
    Creates an input event filter object that matches the
    'description' string. If 'description' is NULL, the filter will not
    match any messages.

    A filter may be modified by the functions SetFilter(), using
    a description string, and SetFilterIX(), which takes a
    binary Input Expression as a parameter.

    This function is a C-language macro for CreateCxObj(), defined
    in <libraries/commodities.h>.

   INPUTS
    description - the description string in the same format as strings
              expected by commodities.library/SetFilter()

   RESULTS
    filterObj - a pointer to the filter object, or NULL if there
            was not enough memory. If there is a problem in the
            description string, the internal error code of the filter
            object will be set to so indicate. This error code may be
            interrogated using the function CxObjError().

   SEE ALSO
    commodities.library/CreateCxObj(), commodities.library/SetFilter(),
    commodities.library/SetFilterIX(), commodities.library/CxObjError()

 amiga.lib/CxSender                                         amiga.lib/CxSender

   NAME
    CxSender -- create a commodity sender object. (V36)

   SYNOPSIS
    senderObj = CxSender(port,id)

    CxObj *CxSender(struct MsgPort *,LONG);

   FUNCTION
    This function creates a Commodities sender object. The action
    of this object on receiving a Commodities message is to copy the
    Commodities message into a standard Exec Message, to put the value
    'id' in the message as well, and to send the message off to the
    message port 'port'.

    The value 'id' is used so that an application can monitor
    messages from several senders at a single port. It can be retrieved
    from the Exec message by using the function CxMsgID(). The value can
    be a simple integer ID, or a pointer to some application data
    structure.

    Note that Exec messages sent by sender objects arrive
    asynchronously at the destination port. Do not assume anything about
    the status of the Commodities message which was copied into the Exec
    message you received.

    All Exec messages sent to your ports must be replied. Messages may be
    replied after the sender object has been deleted.

    This function is a C-language macro for CreateCxObj(), defined
    in <libraries/commodities.h>.

   INPUTS
    port - the port for the sender to send messages to
    id - the id of the messages sent by the sender

   RESULTS
    semderObj - a pointer to the sender object, or NULL if it could
            not be created.

   SEE ALSO
    commodities.library/CreateCxObj(), commodities.library/CxMsgID(),
    exec.library/PutMsg(), exec.library/ReplyMsg()

 amiga.lib/CxSignal                                         amiga.lib/CxSignal

   NAME
    CxSignal -- create a commodity signaller object. (V36)

   SYNOPSIS
    signalerObj = CxSignal(task,signal);

    CxObj *CxSignal(struct Task *,LONG);

   FUNCTION
    This function creates a Commodities signal object. The action
    of this object on receiving a Commodities message is to
    send the 'signal' to the 'task'. The caller is responsible
    for allocating the signal and determining the proper task ID.

    Note that 'signal' is the signal value as returned by AllocSignal(),
    not the mask made from that value.

    This function is a C-language macro for CreateCxObj(), defined
    in <libraries/commodities.h>.

   INPUTS
    task - the task for the signaller to signal
    signal - the signal bit number for the signaller to send

   RESULTS
    signallerObj - a pointer to the signaller object, or NULL if it could
               not be created.

   SEE ALSO
    commodities.library/CreateCxObj(), exec.library/FindTask()
    exec.library/Signal(), exec.library/AllocSignal(),

 amiga.lib/CxTranslate                                   amiga.lib/CxTranslate

   NAME
    CxTranslate -- create a commodity translator object. (V36)

   SYNOPSIS
    translatorObj = CxTranslate(ie);

    CxObj *CxTranslate(struct InputEvent *);

   FUNCTION
    This function creates a Commodities 'translator' object.
    The action of this object on receiving a Commodities message is to
    replace that message in the commodities network with a chain of
    Commodities input messages.

    There is one new Commodities input message generated for each input
    event in the linked list starting at 'ie' (and NULL terminated). The
    routing information of the new input messages is copied from the input
    message they replace.

    The linked list of input events associated with a translator object
    can be changed using the SetTranslate() function.

    If 'ie' is NULL, the null translation occurs: that is, the original
    commodities input message is disposed, and no others are created to
    take its place.

    This function is a C-language macro for CreateCxObj(), defined
    in <libraries/commodities.h>.

   INPUTS
    ie - the input event list used as replacement by the translator

   RESULTS
    translatorObj - a pointer to the translator object, or NULL if it could
                not be created.

   SEE ALSO
    commodities.library/CreateCxObj(), commodities.library/SetTranslate()

 amiga.lib/dbf                                                   amiga.lib/dbf

   NAME
    dbf - convert FFP dual-binary number to FFP format

   SYNOPSIS
    fnum = dbf(exp, mant);

   FUNCTION
    Accepts a dual-binary format (described below) floating point
    number and converts it to an FFP format floating point number.
    The dual-binary format is defined as:

        exp bit  16	= sign (0=>positive, 1=>negative)
        exp bits 15-0	= binary integer representing the base
                      ten (10) exponent
        man		= binary integer mantissa

   INPUTS
    exp - binary integer representing sign and exponent
    mant - binary integer representing the mantissa

   RESULT
    fnum - converted FFP floating point format number

   BUGS
    None
 amiga.lib/DeleteExtIO                                   amiga.lib/DeleteExtIO

   NAME
    DeleteExtIO - return memory allocated for extended IO request

   SYNOPSIS
    DeleteExtIO(ioReq);

    VOID DeleteExtIO(struct IORequest *);

   FUNCTION
    Frees up an IO request as allocated by CreateExtIO().

   INPUTS
    ioReq - the IORequest block to be freed, or NULL.

   SEE ALSO
    CreateExtIO()

 amiga.lib/DeletePort                                     amiga.lib/DeletePort

   NAME
    DeletePort - free a message port created by CreatePort()

   SYNOPSIS
    DeletePort(port)

    VOID DeletePort(struct MsgPort *);

   FUNCTION
    Frees a message port created by CreatePort. All messages that
    may have been attached to this port must have already been
    replied before this function is called.

   INPUTS
    port - message port to delete

   SEE ALSO
    CreatePort()

 amiga.lib/DeleteStdIO                                   amiga.lib/DeleteStdIO

   NAME
    DeleteStdIO - return memory allocated for IOStdReq

   SYNOPSIS
    DeleteStdIO(ioReq);

    VOID DeleteStdIO(struct IOStdReq *);

   FUNCTION
    Frees up an IOStdReq as allocated by CreateStdIO().

   INPUTS
    ioReq - the IORequest block to be freed, or NULL.

   SEE ALSO
    CreateStdIO(), DeleteExtIO(), exec.library/CreateIORequest()

 amiga.lib/DeleteTask                                     amiga.lib/DeleteTask

   NAME
    DeleteTask -- delete a task created with CreateTask()

   SYNOPSIS
    DeleteTask(task)

    VOID DeleteTask(struct Task *);

   FUNCTION
    This function simply calls exec.library/RemTask(), deleting a task
    from the Exec task lists and automatically freeing any stack and
    structure memory allocated for it by CreateTask().

    Before deleting a task, you must first make sure that the task is
    not currently executing any system code which might try to signal
    the task after it is gone.

    This can be accomplished by stopping all sources that might reference
    the doomed task, then causing the subtask to execute a Wait(0L).
    Another option is to have the task call DeleteTask()/RemTask() on
    itself.

   INPUTS
    task - task to remove from the system

   NOTE
    This function simply calls exec.library/RemTask(), so you can call
    RemTask() directly instead of calling this function.

   SEE ALSO
    CreateTask(), exec.library/RemTask()

 amiga.lib/DoMethod                                         amiga.lib/DoMethod

   NAME
    DoMethod -- Perform method on object.  (V36)

   SYNOPSIS
    result = DoMethod( obj, MethodID, ... )

    ULONG DoMethod( Object *, ULONG, ... );

   FUNCTION
    Boopsi support function that invokes the supplied message
    on the specified object.  The message is invoked on the
    object's true class.  Equivalent to DoMethodA(), but allows
    you to build the message on the stack.

   INPUTS
    obj - pointer to boopsi object
    MethodID - which method to send (see <intuition/classusr.h>)
    ... - method-specific message built on the stack

   RESULT
    result - specific to the message and the object's class.

   NOTES
    While this function requires V36 or higher intuition.library,
    it first appeared in V37 amiga.lib.

   SEE ALSO
    DoMethodA(), CoerceMethodA(), DoSuperMethodA(), <intuition/classusr.h>
    ROM Kernel Manual boopsi section

 amiga.lib/DoMethodA                                       amiga.lib/DoMethodA

   NAME
    DoMethodA -- Perform method on object.  (V36)

   SYNOPSIS
    result = DoMethodA( obj, msg )

    ULONG DoMethodA( Object *, Msg * );

   FUNCTION
    Boopsi support function that invokes the supplied message
    on the specified object.  The message is invoked on the
    object's true class.

   INPUTS
    obj - pointer to boopsi object
    msg - pointer to method-specific message to send

   RESULT
    result - specific to the message and the object's class.

   NOTES
    While this function requires V36 or higher intuition.library,
    it first appeared in V37 amiga.lib.
    Some early example code may refer to this function as DM().

   SEE ALSO
    DoMethod(), CoerceMethodA(), DoSuperMethodA(), <intuition/classusr.h>
    ROM Kernel Manual boopsi section

 amiga.lib/DoSuperMethod                               amiga.lib/DoSuperMethod

   NAME
    DoSuperMethod -- Perform method on object coerced to superclass. (V36)

   SYNOPSIS
    result = DoSuperMethod( cl, obj, MethodID, ... )

    ULONG DoSuperMethod( struct IClass *, Object *, ULONG, ... );

   FUNCTION
    Boopsi support function that invokes the supplied message
    on the specified object, as though it were the superclass
    of the specified class.  Equivalent to DoSuperMethodA(),
    but allows you to build the message on the stack.

   INPUTS
    cl - pointer to boopsi class whose superclass is to
        receive the message
    obj - pointer to boopsi object
    ... - method-specific message built on the stack

   RESULT
    result - class and message-specific result.

   NOTES
    While this function requires V36 or higher intuition.library,
    it first appeared in V37 amiga.lib.

   SEE ALSO
    CoerceMethodA(), DoMethodA(), DoSuperMethodA(), <intuition/classusr.h>
    ROM Kernel Manual boopsi section

 amiga.lib/DoSuperMethodA                             amiga.lib/DoSuperMethodA

   NAME
    DoSuperMethodA -- Perform method on object coerced to superclass. (V36)

   SYNOPSIS
    result = DoSuperMethodA( cl, obj, msg )

    ULONG DoSuperMethodA( struct IClass *, Object *, Msg * );

   FUNCTION
    Boopsi support function that invokes the supplied message
    on the specified object, as though it were the superclass
    of the specified class.

   INPUTS
    cl - pointer to boopsi class whose superclass is to
        receive the message
    obj - pointer to boopsi object
    msg - pointer to method-specific message to send

   RESULT
    result - class and message-specific result.

   NOTES
    While this function requires V36 or higher intuition.library,
    it first appeared in V37 amiga.lib.
    Some early example code may refer to this function as DSM().

   SEE ALSO
    CoerceMethodA(), DoMethodA(), DoSuperMethod(), <intuition/classusr.h>
    ROM Kernel Manual boopsi section

 amiga.lib/FastRand                                         amiga.lib/FastRand

   NAME
    FastRand - quickly generate a somewhat random integer

   SYNOPSIS
    number = FastRand(seed);

    ULONG FastRand(ULONG);

   FUNCTION
    Seed value is taken from stack, shifted left one position,
    exclusive-or'ed with hex value $1D872B41 and returned.

   INPUTS
    seed - a 32-bit integer

   RESULT
    number - new random seed, a 32-bit value

   SEE ALSO
    RangeRand()

 amiga.lib/fpa                                                   amiga.lib/fpa

   NAME
    fpa - convert fast floating point into ASCII string equivalent

   SYNOPSIS
    exp = fpa(fnum, &string[0]);

   FUNCTION
    Accepts an FFP number and the address of the ASCII string where it's
    onverted output is to be stored.  The number is converted to a NULL
    terminated ASCII string in and stored at the address provided.
    Additionally, the base ten (10) exponent in binary form is returned.

   INPUTS
    fnum	   - Motorola Fast Floating Point number
    &string[0] - address for output of converted ASCII character string
             (16 bytes)

   RESULT
    &string[0] - converted ASCII character string
    exp	   - integer exponent value in binary form

   BUGS
    None
 amiga.lib/FreeIEvents                                   amiga.lib/FreeIEvents

   NAME
    FreeIEvents -- free a chain of input events allocated by
               InvertString(). (V36)

   SYNOPSIS
    FreeIEvents(events)

    VOID FreeIEvents(struct InputEvent *);

   FUNCTION
    This function frees a linked list of input events as obtained from
    InvertString().

   INPUTS
       events - the list of input events to free, may be NULL.

   SEE ALSO
    InvertString()

 amiga.lib/GetRexxVar                                     amiga.lib/GetRexxVar

   NAME
    GetRexxVar - Gets the value of a variable from a running ARexx program

   SYNOPSIS
    error = GetRexxVar(message,varname,bufpointer)
    D0,A1              A0      A1      (C-only)

    LONG GetRexxVar(struct RexxMsg *,char *,char **);

   FUNCTION
    This function will attempt to extract the value of the symbol
    varname from the ARexx script that sent the message.  When called
    from C, a pointer to the extracted value will be placed in the
    pointer pointed to by bufpointer.  (*bufpointer will be the pointer
    to the value)

    When called from assembly, the pointer will be returned in A1.

    The value string returned *MUST* *NOT* be modified.

    While this function is new in the V37 amiga.lib, it is safe to
    call it in all versions of the operating system.  It is also
    PURE code, thus usable in resident/pure executables.

   NOTE
    This is a stub in amiga.lib.  It is only available via amiga.lib.
    The stub has two labels.  One, _GetRexxVar, takes the arguments
    from the stack.  The other, GetRexxVar, takes the arguments in
    registers.

    This routine does a CheckRexxMsg() on the message.

   EXAMPLE

    char	*value;

    /* Message is one from ARexx */
    if (!GetRexxVar(rxmsg,"TheVar",&value))
    {
        /* The value was gotten and now is pointed to by value */
        printf("Value of TheVar is %s\n",value);
    }

   INPUTS
    message		A message gotten from an ARexx script
    varname		The name of the variable to extract
    bufpointer	(For C only) A pointer to a string pointer.

   RESULTS
    error		0 for success, otherwise an error code.
            (Other codes may exists, these are documented)
            3  == Insufficient Storage
            9  == String too long
            10 == invalid message

    A1		(Assembly only)  Pointer to the string.

   SEE ALSO
    SetRexxVar(), CheckRexxMsg()

 amiga.lib/HookEntry                                       amiga.lib/HookEntry

   NAME
    HookEntry -- Assembler to HLL conversion stub for hook entry.  (V36)

   SYNOPSIS
    result = HookEntry( struct Hook *, Object *, APTR )
    D0                  A0             A2        A1

   FUNCTION
    By definition, a standard hook entry-point must receive the
    hook in A0, the object in A2, and the message in A1.  If your
    hook entry-point is written in a high-level language and is
    expecting its parameters on the stack, then HookEntry() will
    put the three parameters on the stack and invoke the function
    stored in the hook h_SubEntry field.

    This function is only useful to hook implementers, and is
    never called from C.

   INPUTS
    hook - pointer to hook being invoked
    object - pointer to hook-specific data
    msg - pointer to hook-specific message

   RESULT
    result - a hook-specific result.

   NOTES
    While this function requires V36 or higher intuition.library,
    it first appeared in V37 amiga.lib.

   EXAMPLE
    If your hook dispatcher is this:

    dispatch( struct Hook *hookPtr, Object *obj, APTR msg )
    {
        ...
    }

    Then when you initialize your hook, you would say:

    myhook.h_Entry = HookEntry;	/* amiga.lib stub */
    myhook.h_SubEntry = dispatch;	/* HLL entry */

   SEE ALSO
    CallHook(), CallHookA(), <utility/hooks.h>

 amiga.lib/HotKey                                             amiga.lib/HotKey

   NAME
    HotKey -- create a commodity triad. (V36)

   SYNOPSIS
    filterObj = Hotkey(description,port,id);

    CxObj *HotKey(STRPTR,struct MsgPort *,LONG);

   FUNCTION
    This function creates a triad of commodity objects to accomplish a
    high-level function.

    The three objects are a filter, which is created to match by the call
    CxFilter(description), a sender created by the call CxSender(port,id),
    and a translator which is created by CxTranslate(NULL), so that it
    swallows any commodity input event messages that are passed down by
    the filter.

    This is the simple way to get a message sent to your program when the
    user performs a particular input action.

    It is strongly recommended that the ToolTypes environment be used to
    allow the user to specify the input descriptions for your application's
    hotkeys.

   INPUTS
    description - the description string to use for the filter in the same
              format as accepted by commodities.library/SetFilter()
    port - port for the sender to send messages to.
    id - id of the messages sent by the sender

   RESULTS
    filterObj - a pointer to a filter object, or NULL if it could
            not be created.

   SEE ALSO
    CxFilter(), CxSender(), CxTranslate(),
    commodities.library/CxObjError(), commodities.library/SetFilter()

 amiga.lib/InvertString                                 amiga.lib/InvertString

   NAME
    InvertString -- produce input events that would generate the
            given string. (V36)

   SYNOPSIS
    events = InvertString(str,km)

    struct InputEvent *InvertString(STRPTR,struct KeyMap *);

   FUNCTION
    This function returns a linked list of input events which would
    translate into the string using the supplied keymap (or the system
    default keymap if 'km' is NULL).

    'str' is null-terminated and may contain:
       - ANSI character codes
       - backslash escaped characters:
        \n   -   CR
        \r   -   CR
        \t   -   TAB
        \0   -   illegal, do not use!
        \\   -   backslash
       - a text description of an input event as used by ParseIX(),
         enclosed in angle brackets.

    An example is:
          abc<alt f1>\nhi there.

   INPUTS
    str - null-terminated string to convert to input events
    km - keymap to use for the conversion, or NULL to use the default
         keymap.

   RESULTS
    events - a chain of input events, or NULL if there was a problem. The
         most likely cause of failure is an illegal description
         enclosed in angled brackets.

         This chain should eventually be freed using FreeIEvents().

   SEE ALSO
    commodities.library/ParseIX(), FreeIEvents()

 amiga.lib/NewList                                           amiga.lib/NewList

   NAME
    NewList -- prepare a list structure for use

   SYNOPSIS
    NewList(list)

    VOID NewList(struct List *);
    VOID NewList(struct MinList *);

   FUNCTION
    Perform the magic needed to prepare a List header structure for
    use; the list will be empty and ready to use.  (If the list is the
    full featured type, you may need to initialize lh_Type afterwards)

    Assembly programmers may want to use the NEWLIST macro instead.

   INPUTS
    list - pointer to a List or MinList.

   SEE ALSO
    <exec/lists.h>

 amiga.lib/printf                                             amiga.lib/printf

   NAME
    printf - print a formatted output line to the standard output.

   SYNOPSIS
    printf(formatstring [,value [,values] ] );

   FUNCTION
    Format the output in accordance with specifications in the format
    string.

   INPUTS
    formatString - a C-language-like NULL-terminated format string,
               with the following supported % options:

      %[flags][width][.limit][length]type

        $     - must follow the arg_pos value, if specified
      flags   - only one allowed. '-' specifies left justification.
      width   - field width. If the first character is a '0', the
                field is padded with leading 0s.
        .     - must precede the field width value, if specified
      limit   - maximum number of characters to output from a string.
                (only valid for %s or %b).
      length  - size of input data defaults to word (16-bit) for types c,
            d, u and x, 'l' changes this to long (32-bit).
      type    - supported types are:
                      b - BSTR, data is 32-bit BPTR to byte count followed
                          by a byte string. A NULL BPTR is treated as an
                  empty string. (V36)
                      d - signed decimal
              u - unsigned decimal
                      x - hexadecimal with hex digits in uppercase
              X - hexadecimal with hex digits in lowercase
                      s - string, a 32-bit pointer to a NULL-terminated
                          byte string. A NULL pointer is treated
                          as an empty string.
                      c - character

    value(s) - numeric variables or addresses of null-terminated strings
               to be added to the format information.

   NOTE
    The global "_stdout" must be defined, and contain a pointer to
    a legal AmigaDOS file handle. Using the standard Amiga startup
    module sets this up. In other cases you will need to define
    stdout, and assign it to some reasonable value (like what the
    dos.library/Output() call returns). This code would set it up:

        ULONG stdout;
        stdout=Output();

   BUGS
    This function will crash if the resulting stream after
    parameter substitution is longer than 140 bytes.

 amiga.lib/RangeRand                                       amiga.lib/RangeRand

   NAME
    RangeRand - generate a random number within a specific integer range

   SYNOPSIS
    number = RangeRand(maxValue);

    UWORD RangeRand(UWORD);

   FUNCTION
    RangeRand() accepts a value from 0 to 65535, and returns a value
    within that range.

    maxValue is passed on stack as a 32-bit integer but used as though
    it is only a 16-bit integer. Variable named RangeSeed is available
    beginning with V33 that contains the global seed value passed from
    call to call and thus can be changed in a program by declaring:

      extern ULONG RangeSeed;

   INPUTS
    maxValue - the returned random number will be in the range
               [0..maxValue-1]

   RESULT
    number - pseudo random number in the range of [0..maxValue-1].

   SEE ALSO
    FastRand()

 amiga.lib/RemTOF                                             amiga.lib/RemTOF

   NAME
    RemTOF - remove a task from the VBlank interrupt server chain.

   SYNOPSIS
    RemTOF(i);

    VOID RemTOF(struct Isrvstr *);

   FUNCTION
    Removes a task from the vertical-blanking interval interrupt server
    chain.

   INPUTS
    i - pointer to an Isrvstr structure

   SEE ALSO
    AddTOF(), <graphics/graphint.h>

 amiga.lib/SetRexxVar                                     amiga.lib/SetRexxVar

   NAME
    SetRexxVar - Sets the value of a variable of a running ARexx program

   SYNOPSIS
    error = SetRexxVar(message,varname,value,length)
    D0                 A0      A1      D0    D1

    LONG SetRexxVar(struct RexxMsg *,char *,char *,ULONG);

   FUNCTION
    This function will attempt to the the value of the symbol
    varname in the ARexx script that sent the message.

    While this function is new in the V37 amiga.lib, it is safe to
    call it in all versions of the operating system.  It is also
    PURE code, thus usable in resident/pure executables.

   NOTE
    This is a stub in amiga.lib.  It is only available via amiga.lib.
    The stub has two labels.  One, _SetRexxVar, takes the arguments
    from the stack.  The other, SetRexxVar, takes the arguments in
    registers.

    This routine does a CheckRexxMsg() on the message.

   EXAMPLE

    char	*value;

    /* Message is one from ARexx */
    if (!SetRexxVar(rxmsg,"TheVar","25 Dollars",10))
    {
        /* The value of TheVar will now be "25 Dollars" */
    }

   INPUTS
    message		A message gotten from an ARexx script
    varname		The name of the variable to set
    value		A string that will be the new value of the variable
    length		The length of the value string

   RESULTS
    error		0 for success, otherwise an error code.
            (Other codes may exists, these are documented)
            3  == Insufficient Storage
            9  == String too long
            10 == invalid message

   SEE ALSO
    SetRexxVar(), CheckRexxMsg()

 amiga.lib/SetSuperAttrs                               amiga.lib/SetSuperAttrs

   NAME
    SetSuperAttrs -- Invoke OM_SET method on superclass with varargs. (V36)

   SYNOPSIS
    result = SetSuperAttrs( cl, obj, tag, ... )

    ULONG SetSuperAttrs( struct IClass *, Object *, ULONG, ... );

   FUNCTION
    Boopsi support function which invokes the OM_SET method on the
    superclass of the supplied class for the supplied object.  Allows
    the ops_AttrList to be supplied on the stack (i.e. in a varargs
    way).  The equivalent non-varargs function would simply be

        DoSuperMethod( cl, obj, OM_SET, taglist, NULL );

   INPUTS
    cl - pointer to boopsi class whose superclass is to
        receive the OM_SET message
    obj - pointer to boopsi object
    tag - list of tag-attribute pairs, ending in TAG_DONE

   RESULT
    result - class and message-specific result.

   NOTES
    While this function requires V36 or higher intuition.library,
    it first appeared in V37 amiga.lib.

   SEE ALSO
    CoerceMethodA(), DoMethodA(), DoSuperMethodA(), <intuition/classusr.h>
    ROM Kernel Manual boopsi section

 amiga.lib/sprintf                                           amiga.lib/sprintf

   NAME
    sprintf - format a C-like string into a string buffer.

   SYNOPSIS
    sprintf(destination formatstring [,value [, values] ] );

   FUNCTION
    Performs string formatting identical to printf, but directs the output
    into a specific destination in memory. This uses the ROM version
    of printf (exec.library/RawDoFmt()), so it is very small.

    Assembly programmers can call this by placing values on the
    stack, followed by a pointer to the formatstring, followed
    by a pointer to the destination string.

   INPUTS
    destination - the address of an area in memory into which the
              formatted output is to be placed.
    formatstring - pointer to a null terminated string describing the
                   desired output formatting (see printf() for a
               description of this string).
    value(s) - numeric information to be formatted into the output
           stream.

   SEE ALSO
     printf(), exec.library/RawDoFmt()

 amiga.lib/stdio                                               amiga.lib/stdio

   NAMES
    fclose	- close a file
    fgetc	- get a character from a file
    fprintf	- format data to file (see printf())
    fputc	- put character to file
    fputs	- write string to file
    getchar	- get a character from stdin
    printf	- put format data to stdout (see exec.library/RawDoFmt)
    putchar	- put character to stdout
    puts	- put string to stdout, followed by newline

   FUNCTION
    These functions work much like the standard C functions of the same
    names. The file I/O functions all use non-buffered AmigaDOS
    files, and must not be mixed with the file I/O of any C
    compiler. The names of these functions match those found in many
    standard C libraries, when a name conflict occurs, the function is
    generally taken from the FIRST library that was specified on the
    linker's command line.  Thus to use these functions, specify
    the amiga.lib library first.

    To get a suitable AmigaDOS FileHandle, the dos.library/Open() or
    dos.library/Output() functions must be used.

    All of the functions that write to stdout expect an appropriate
    FileHandle to have been set up ahead of time. Depending on
    your C compiler and options, this may have been done by the
    startup code.  Or it can be done manually

    From C:
        extern ULONG stdout;
        /* Remove the extern if startup code did not define stdout */
        stdout=Output();

    From assembly:
        XDEF	_stdout
        DC.L	_stdout	;<- Place result of dos.library/Output() here.

 amiga.lib/TimeDelay                                       amiga.lib/TimeDelay

   NAME
    TimeDelay -- Return after a period of time has elapsed.

   SYNOPSIS
    Error = TimeDelay( Unit, Seconds, MicroSeconds )
    D0                 D0    D1       D2

    LONG TimeDelay( LONG, ULONG, ULONG );

   FUNCTION
    Waits for the period of time specified before returning to the
    the caller.

   INPUTS
    Unit -- timer.device unit to open for this command.
    Seconds -- The seconds field of a timerequest is filled with
        this value. Check the documentation for what a partucular
        timer.device unit expects there.
    MicroSeconds -- The microseconds field of a timerequest is
        filled with this value. Check the documentation for what
        a particular timer.device units expects there.

   RESULTS
    Error -- will be zero if all went well; otherwise, non-zero.

   NOTES
    Two likely reasons for failures are invalid unit numbers or
    no more free signal bits for this task.

    While this function first appears in V37 amiga.lib, it works
    on Kickstart V33 and higher.

   SEE ALSO
    timer.device/TR_ADDREQUEST,
    timer.device/TR_WAITUNTIL,
    timer.device/WaitUnitl()

   BUGS


Text_Autodocs/ddebug_lib.doc

TABLE OF CONTENTS

DDoFmt
DGetChar
DGetNum
DMayGetChar
DPutChar
DPutFmt
DPutStr
KCmpStr
 DDoFmt                                                                 DDoFmt

   NAME
    DDoFmt -- format data into a character stream.

   SYNOPSIS
    DDoFmt(FormatString, DataStream, PutChProc, PutChData);
          A0	    A1		A2	   A3

   FUNCTION
    perform "C"-language-like formatting of a data stream,
    outputting the result a character at a time

   INPUTS
    FormatString - a "C"-language-like null terminated format
        string, with the following supported % types:
    DataStream - a stream of data that is interpreted according to
        the format string.
    PutChProc - the procedure to call with each character to be
        output, called as:
        PutChProc(Char,  PutChData);
              D0-0:8 A3
        the procedure is called with a null Char at the end of
        the format string.
    PutChData - an address register that passes thru to PutChProc.

 DGetChar                                                             DGetChar

   NAME
    DGetChar - get a character from the parallel port

   SYNOPSIS
    char = DGetChar()
    D0

   FUNCTION
    get the next character from the parallel port.

 DGetNum                                                               DGetNum

   NAME
    DGetNum - get a number from the parallel port

   SYNOPSIS
    number = DGetNum()
    D0

   FUNCTION
    get a signed decimal integer from the parallel port.

 DMayGetChar                                                       DMayGetChar

   NAME
    DMayGetChar - return a char iff present, but don't block

   SYNOPSIS
    flagChar = DMayGetChar()
    D0

   FUNCTION
    return either a -1, saying that there is no char present, or
    the char that was waiting

 DPutChar                                                             DPutChar

   NAME
    DPutChar - put a character to the parallel port

   SYNOPSIS
    char = DPutChar(char)
    D0	       D0

   FUNCTION
    put a character to the parallel port.

 DPutFmt                                                               DPutFmt

   NAME
    DPutFmt - print formatted data to the parallel port

   SYNOPSIS
    DPutFmt(format,values)
           A0     A1

   FUNCTION
    print formatted data to the parallel port

 DPutStr                                                               DPutStr

   NAME
    DPutStr - put a string to the parallel port

   SYNOPSIS
    DPutStr(string)
           A0

   FUNCTION
    put a null terminated string to the parallel port.

 KCmpStr                                                               KCmpStr

   NAME
    KCmpStr - compare two null terminated strings

   SYNOPSIS
    mismatch = KCmpStr(string1, string2)
    D0		  A0	   A1

   FUNCTION
    string1 is compared to string2 using the ASCII coalating
    sequence.


Text_Autodocs/debug_lib.doc

TABLE OF CONTENTS

debug.lib/KCmpStr
debug.lib/KGetChar
debug.lib/KGetNum
debug.lib/KMayGetChar
debug.lib/KPrintF
debug.lib/KPutChar
debug.lib/KPutStr
 debug.lib/KCmpStr                                           debug.lib/KCmpStr

   NAME
    KCmpStr - compare two null terminated strings

   SYNOPSIS
    mismatch = KCmpStr(string1, string2)
    D0         A0        A1

   FUNCTION
    string1 is compared to string2 using the ASCII coalating
    sequence.  0 indicates the strings are identical.
 debug.lib/KGetChar                                         debug.lib/KGetChar

   NAME
    KGetChar - get a character from the console
           (defaults to the serial port at 9600 baud)

   SYNOPSIS
    char = KGetChar()
    D0

   FUNCTION
    busy wait until a character arrives from the console.
    KGetChar is the assembly interface, _KGetChar and _kgetc
    are the C interfaces.
 debug.lib/KGetNum                                           debug.lib/KGetNum

   NAME
    KGetNum - get a number from the console

   SYNOPSIS
    number = KGetNum()
    D0

   FUNCTION
    get a signed decimal integer from the console.  This will busy
    wait until the number arrives.

 debug.lib/KMayGetChar                                   debug.lib/KMayGetChar

   NAME
    KMayGetChar - return a character if present, but don't wait
              (defaults to the serial port at 9600 baud)

   SYNOPSIS
    flagChar = KMayGetChar()
    D0

   FUNCTION
    return either a -1, saying that there is no character present, or
    whatever character was waiting.  KMayGetChar is the assembly
    interface,  _KMayGetChar is the C interface.
 debug.lib/KPrintF                                           debug.lib/KPrintF

   NAME
    KPrintF - print formatted data to the console
              (defaults to the serial port at 9600 baud)

   SYNOPSIS
    KPrintF("format string",values)
             A0             A1

   FUNCTION
    print a formatted C-type string to the console.  See the
    exec RawDoFmt() call for the supported % formatting commands.

   INPUTS
    "format string" - A C style string with % commands to indicate
                      where paramters are to be inserted.
    values - A pointer to an array of paramters, to be inserted into
             specified places in the string.

    KPutFmt and KPrintF are identical assembly interfaces that want the
    two pointers in registers.  _KPrintF and _kprintf are C interfaces
    that expect the format string pointer on the stack, and the
    paramters on the stack above that.

   SEE ALSO
    exec.library/RawDoFmt, any C compiler's "printf" call.
 debug.lib/KPutChar                                         debug.lib/KPutChar

   NAME
    KPutChar - put a character to the console
           (defaults to the serial port at 9600 baud)

   SYNOPSIS
    char = KPutChar(char)
    D0	        D0

   FUNCTION
    Put a character to the console.  This function will not return
    until the character has been completely transmitted.

   INPUTS
    KPutChar is the assembly interface, the character must be in D0.
    _KPutChar and _kputc are the C interfaces, the character must be
    a longword on the stack.

 debug.lib/KPutStr                                           debug.lib/KPutStr

   NAME
    KPutStr - put a string to the console
           (defaults to the serial port at 9600 baud)

   SYNOPSIS
    KPutStr(string)
            A0

   FUNCTION
    put a null terminated string to the console.  This function will
    not return until the string has been completely transmitted.

   INPUTS
    KPutStr is the assembly interface, a string pointer must be in A0.
    _KPutStr and _kputs are the C interfaces, the string pointer must
    be on the stack.


Text_Autodocs/asl.doc

TABLE OF CONTENTS

asl.library/AllocAslRequest
asl.library/AllocFileRequest
asl.library/AslRequest
asl.library/FreeAslRequest
asl.library/FreeFileRequest
asl.library/RequestFile

asl.library/AllocAslRequest			   asl.library/AllocAslRequest

  NAME
    AllocAslRequest -- alloc an ASL requester, with TagItem modifiers (V36)

  SYNOPSIS
    request = AllocAslRequest( type, ptags )
    D0			   D0	 A0

    APTR	request;
    ulong	type;
    struct TagItem	*ptags;

  FUNCTION
    Allocates an ASL requester data structure of the specified type,
    with optional TagItem modifiers.

  INPUTS
    type = type of requester to create.  Currently defined types
        include ASL_FileRequest and ASL_FontRequest.
    ptags = pointer to a tagitem array, which is defined for each
        specified type.  See "asl.h" and example programs for usage
        of various tag types.  See AslRequest() for specifications
        of currently defined tag values and their effects.

    Note that tag values stay in effect for each use of the
    requester until they are cleared or modified by passing the
    same tag with a new value.

    AllocAslRequestTags( type, tags... ) which accepts your tags
    on the stack, is available in amiga.lib.

    Example Usage: AllocAslRequestTags( ASL_FileRequest,
                            ASL_Hail, "My Title Bar",
                            TAG_DONE );

  RESULT
    Pointer to an initialized requester data structure, or NULL on
    failure.  The data structure returned will match the requested
    type; for type ASL_FileRequest, a struct FileRequester *; for
    ASL_FontRequest, a struct FontRequester *.

    The requester returned may then be passed to AslRequest(), and
    is freed by calling FreeAslRequest().

  SEE ALSO
    AslRequest(), FreeAslRequest()

asl.library/AllocFileRequest			   asl.library/AllocFileRequest

  NAME
    AllocFileRequest -- allocates a FileRequester structure (V36)

  SYNOPSIS
    request = AllocFileRequest()
    D0

    struct FileRequester *request;

  FUNCTION
    Creates and initializes the data structure required to pass to the
    RequestFile() function.

  INPUTS
    None.  If you wish to get other than default values, you can use
    AllocAslRequest() to set up a file request with tag items.

  RESULT
    Pointer to a struct FileRequester, which is to be passed to the
    RequestFile() function.

    The returned FileRequester pointer has public fields which are
    readable by the application as defined in aslbase.h.

  CAUTION
    The application MUST use either the AllocFileRequest(), or
    AllocAslRequest(), function to allocate the structure to be passed to
    the FileRequest() or AslRequest() functions; it is not possible to
    create a struct FileRequest except through the library calls.

    Also, any modifications MUST be done through TagItem values, rather
    than directly modifying, unless explicitly documented otherwise.

  SEE ALSO
    RequestFile(), FreeAslRequest(), AslRequest()

asl.library/AslRequest					 asl.library/AslRequest

  NAME
    AslRequest -- get input from user for an ASL requester (V36)

  SYNOPSIS
    BOOL result = AslRequest( request, ptags );
    D0                        A0       A1

    BOOL	result;
    APTR	request;
    struct TagItem	*ptags;

  FUNCTION
    Prompts the user for input, based on the specific type of
    requester and modifying tagitems.  The actions and results
    are specific to the type but in general the action is to open
    a requesting window prompting the user for a specific input.
    If the user cancels or the system aborts the request, NULL
    is returned, otherwise the request data structure readable
    data reflects the user input.
    Note that tag values stay in effect for each use of the
    requester until they are cleared or modified by passing the
    same tag with a new value.

  INPUTS
    request = requester structure allocated with AllocAslRequest().
    ptags = pointer to an array of TagItems which may be used to
        modify the requester.

    AslRequestTags( type, tags... ) which accepts your tags
    on the stack, is available in amiga.lib.

    Example Usage: AslRequestTags( ASL_FileRequest,
                       ASL_Hail, "My Title Bar",
                       TAG_DONE );

  TAGS

    ( REMEMBER - ALL DATA STRUCTURES ARE READ-ONLY EXCEPT BY USING
      TAGITEMS !!! )

    ASL_Hail (STRPTR) - Hailing text to prompt user, typically
        displayed in window title bar.
    ASL_Window (struct Window *) - Parent window for the request
        function, which is used to select the screen on which the
        requesting window will be displayed and also is used for
        a shared IDCMP port.

    ASL_LeftEdge (WORD) - Preferred display position for left edge where
        request window should open.
    ASL_TopEdge (WORD) - Preferred top edge of request window.
    ASL_Width (WORD)   - Preferred width of request window.
    ASL_Height (WORD)  - Preferred height of request window.

    ASL_HookFunc (APTR) - Pointer to callback function, specific to
        each AslRequest type.

    ASL_File (STRPTR) - FileRequester initial filename string.
    ASL_Dir (STRPTR) - FileRequester initial directory path string.

    ASL_FontName (STRPTR) - FontRequester initial fontname string.
    ASL_FontHeight (UWORD) - FontRequester initial height (ta_YSize).
    ASL_FontStyles (UBYTE) - FontRequester initial styles (ta_Style).
    ASL_FontFlags (UBYTE) - FontRequester initial flags (ta_Flags).
    ASL_FrontPen (BYTE) - FontRequester front pen color (fo_FrontPen).
    ASL_BackPen (BYTE) - FontRequester back pen color (fo_BackPen).
    ASL_MinHeight (UWORD) - Minimum height for FontRequester display
        of font sizes.  (Application must check return value).
    ASL_MaxHeight (UWORD) - Maximum height for FontRequester display
        of font sizes. (Application must check ta_YSize returned).

    ASL_OKText (STRPTR) - Replacement for default "OK" gadget text.
        ( Limited to approx. six characters ).
    ASL_CancelText (STRPTR) - Replacement for default "CANCEL"
        gadget text. ( Limited to approx. six characters ).

    ASL_FuncFlags (ULONG) - Function flags, depends on requester
        type.  Example: FILF_SAVE for FileRequester.
    ASL_ExtFlags1 (ULONG) - Extended flags (to pass FILF1_ bitdefs)
           Example: FIL1F_NOFILES for file requester

  RESULT
    If NULL, typically the user cancelled the requester or a system
    failure prevented the requester from being opened.  If non-zero,
    values will be set depending on the particular type of request,
    in the requesting data structure.  See "libraries/asl.h" for
    information on the READ-ONLY fields in each specific type of
    requester.

  NOTES

    Asl provides a way for applications to interact with requester
    operation via a callback (hook) function.  For the ASL file and
    font requesters, there are two ASL_FuncFlags to specify that you
    want a callback:

         for FileRequester: FILF_DOWILDFUNC and FILF_DOMSGFUNC
         for FontRequester: FONF_DOWILDFUNC and FONF_DOMSGFUNC

    The DOWILDFUNC allows you to perform the pattern matching.
    The DOMSGFUNC allows you to handle IDCMP messages received
    for windows that are sharing a UserPort with the requester.

    If you set one or both of these flags via the ASL_FuncFlags
    tagitem, you must provide a pointer to your hook function
    using the ASL_HookFunc tagitem.  Your function will be called
    as follows:

     ULONG rf_Function(ULONG Mask, CPTR Object, CPTR AslRequester)

    The Mask value is a copy of the specific ASL_FuncFlag value
    the callback is for.  Object is a pointer to a data object
    specific to the reason for the callback (defined by Mask).
    AslRequester is a pointer to the requester structure.

    Note that you can only define one HookFunc per requester.
    Your hook function must examine the Mask passed to it to
    determine what the callback is for and what the Object is.

    The following table will explain what is passed to, and
    expected to be returned by a hook functions for various masks:

    FileRequester DOWILDFUNC
    Purpose: to accept or reject individual files for display list
    Inputs:	Mask		= FILF_DOWILDFUNC
        Object		= struct AnchorPath *
        AslRequester	= struct FileRequester *
    Result: You return zero to accept file for display in list

    FontRequester DOWILDFUNC
    Purpose: to accept or reject individual fonts for display list
    Inputs:	Mask		= FONF_DOWILDFUNC
        Object		= struct TextAttr *
        AslRequester	= struct FontRequester *
    Result: You return non-zero to accept font for display in list

    FileRequester (or FontRequester) DOMSGFUNC
    Purpose: to handle IDCMP msgs for other windows sharing port
    Inputs:	Mask		= FILF_DOMSGFUNC (FONF_DOMSGFUNC)
        Object		= struct IntuiMessage *
        AslRequester	= struct FileRequester (FontRequester) *
    Result: You must return the Object pointer (asl will Reply the Object)

  SEE ALSO
    AllocAslRequest(), FreeAslRequest()

asl.library/FreeAslRequest			     asl.library/FreeAslRequest

  NAME
    FreeAslRequest - frees requester obtained from AllocAslRequest (V36)

  SYNOPSIS
    FreeAslRequest( request )
            A0

    APTR request;

  FUNCTION
    FreeAslRequest() is used to free the structure returned by
    AllocAslRequest() or AllocFileRequest(), in order to free
    all resources associated with that requester after the
    application has completed all use of the data structures.

  INPUTS
    request - value returned from AllocAslRequest() or
            AllocFileRequest().

  RESULT
    None.  All resources associated with the request will be
    freed.

  SEE ALSO
    AllocAslRequest(), AslRequest(), AllocFileRequest()

asl.library/FreeFileRequest			    asl.library/FreeFileRequest

  NAME
    FreeFileRequest -- frees requester allocated by AllocFileRequest (V36)

  SYNOPSIS
    FreeFileRequest( request )
             A0

    struct FileRequester *request;

  FUNCTION
    This function is identical to the FreeAslRequest() function, but is
    documented for source code compatability and ease of use.
    Applications may use either FreeAslRequest() or FreeFileRequest() to
    free the data structures allocated by AllocFileRequest().

  INPUTS
    request = the return value from AllocFileRequest().

  SEE ALSO
    FreeAslRequest()

 asl.library/RequestFile					asl.library/RequestFile

  NAME
    RequestFile -- request user to select file(s) (V36)

  SYNOPSIS
    BOOL result = RequestFile( request )
    D0                         A0

    BOOL	result;
    struct FileRequester *request;

  FUNCTION
    RequestFile() displays a file requester and waits for the user to
    select filenames or cancel the request.  This function is identical
    to the AslRequest() function, except that there is no TagList to
    modify the settings for the requester.  See AslRequest() for details.

  INPUT
    request = struct FileRequester * returned by AllocFileRequest().

  RESULT
    result - See AslRequest() result.  NULL indicates cancelled.

  SEE ALSO
    AllocFileRequest(), FreeFileRequest(), AslRequest()


Text_Autodocs/icon.doc

TABLE OF CONTENTS

icon.library/AddFreeList
icon.library/BumpRevision
icon.library/DeleteDiskObject
icon.library/FindToolType
icon.library/FreeDiskObject
icon.library/FreeFreeList
icon.library/GetDefDiskObject
icon.library/GetDiskObject
icon.library/GetDiskObjectNew
icon.library/MatchToolValue
icon.library/PutDefDiskObject
icon.library/PutDiskObject
 icon.library/AddFreeList                             icon.library/AddFreeList

   NAME
       AddFreeList - add memory to a free list.

   SYNOPSIS
       status = AddFreeList(free, mem, len)
         D0                  A0    A1   A2

    BOOL AddFreeList(struct FreeList *, APTR, ULONG);

   FUNCTION
    This routine adds the specified memory to the free list.
    The free list will be extended (if required).  If there
    is not enough memory to complete the call, a null is returned.

    Note that AddFreeList does NOT allocate the requested memory.
    It only records the memory in the free list.

   INPUTS
    free -- a pointer to a FreeList structure
    mem -- the base of the memory to be recorded
    len -- the length of the memory to be recorded

   RESULTS
    status -- TRUE if the call succeeded else FALSE;

   SEE ALSO
    AllocEntry(), FreeEntry(), FreeFreeList()

   BUGS
    None

 icon.library/BumpRevision                           icon.library/BumpRevision

   NAME
       BumpRevision - reformat a name for a second copy.

   SYNOPSIS
       result = BumpRevision(newbuf, oldname)
         D0                    A0      A1

    char *BumpRevision(char *, char *);

   FUNCTION
    BumpRevision takes a name and turns it into a "copy_of_name".
    It knows how to deal with copies of copies.  The routine
    will truncate the new name to the maximum dos name size
    (currently 30 characters).

   INPUTS
    newbuf - the new buffer that will receive the name
         (it must be at least 31 characters long).
    oldname - the original name

   RESULTS
    result - a pointer to newbuf

   EXAMPLE
    oldname				 newbuf
    -------				 ------
    "foo"				 "copy_of_foo"
    "copy_of_foo"			 "copy_2_of_foo"
    "copy_2_of_foo"			 "copy_3_of_foo"
    "copy_199_of_foo"		 "copy_200_of_foo"
    "copy foo"			 "copy_of_copy foo"
    "copy_0_of_foo"			 "copy_1_of_foo"
    "012345678901234567890123456789" "copy_of_0123456789012345678901"

   SEE ALSO

   BUGS
    None

 icon.library/DeleteDiskObject                   icon.library/DeleteDiskObject

   NAME
       DeleteDiskObject - Delete a Workbench disk object from disk.     (V37)

   SYNOPSIS
       result = DeleteDiskObject(name)
         D0                      A0

    BOOL DeleteDiskObject(char *);

   FUNCTION
    This routine will try to delete a Workbench disk object from disk.
    The name parameter will have a ".info" postpended to it, and the
    info file of that name will be deleted.  If the call fails,
    it will return zero.  The reason for the failure may be obtained
    via IoErr().

    This call also updates the Workbench screen if needed.

    Using this routine protects you from any future changes to
    the way icons are stored within the system.

   INPUTS
    name -- name of the object (char *)

   RESULTS
    result -- TRUE if it worked, false if not.

   EXAMPLE

    error=NULL;

    *Check if you have the right library version*

    if (((struct Library *)IconBase)->lib_Version > 36)
    {
        if (!DeleteDiskObject(name)) error=IoErr();
    }
    else
    {
        * Delete name plus ".info" *
    }

    if (error)
    {
        * Do error routine...*
    }

   SEE ALSO
    PutDiskObject(), GetDiskObject(), FreeDiskObject()

   BUGS
    None

 icon.library/FindToolType                           icon.library/FindToolType

   NAME
       FindToolType - find the value of a ToolType variable.

   SYNOPSIS
       value = FindToolType(toolTypeArray, typeName)
         D0                      A0           A1

    char *FindToolType(char **, char *);

   FUNCTION
    This function searches a tool type array for a given entry,
    and returns a pointer to that entry.  This is useful for
    finding standard tool type variables.  The returned
    value is not a new copy of the string but is only
    a pointer to the part of the string after typeName.

   INPUTS
    toolTypeArray - an array of strings (char **).
    typeName - the name of the tooltype entry (char *).

   RESULTS
    value - a pointer to a string that is the value bound to typeName,
        or NULL if typeName is not in the toolTypeArray.

   EXAMPLE
    Assume the tool type array has two strings in it:
        "FILETYPE=text"
        "TEMPDIR=:t"

    FindToolType( toolTypeArray, "FILETYPE" ) returns "text"
    FindToolType( toolTypeArray, "filetype" ) returns "text"
    FindToolType( toolTypeArray, "TEMPDIR" )  returns ":t"
    FindToolType( toolTypeArray, "MAXSIZE" )  returns NULL

   SEE ALSO
    MatchToolValue()

   BUGS
    None

 icon.library/FreeDiskObject                       icon.library/FreeDiskObject

   NAME
       FreeDiskObject - free all memory in a Workbench disk object.

   SYNOPSIS
       FreeDiskObject(diskobj)
                        A0

    void FreeDiskObject(struct DiskObject *);

   FUNCTION
    This routine frees all memory in a Workbench disk object, and the
    object itself.  It is implemented via FreeFreeList().

    GetDiskObject() takes care of all the initialization required
    to set up the object's free list.  This procedure may ONLY
    be called on a DiskObject allocated via GetDiskObject().

   INPUTS
    diskobj -- a pointer to a DiskObject structure

   RESULTS
    None

   SEE ALSO
    GetDiskObject(), PutDiskObject(), DeleteDiskObject(), FreeFreeList()

   BUGS
    None

 icon.library/FreeFreeList                           icon.library/FreeFreeList

   NAME
       FreeFreeList - free all memory in a free list.

   SYNOPSIS
       FreeFreeList(free)
                     A0

    void FreeFreeList(struct FreeList *);

   FUNCTION
    This routine frees all memory in a free list, and the
    free list itself.  It is useful for easily getting
    rid of all memory in a series of structures.  There is
    a free list in a Workbench object, and this contains
    all the memory associated with that object.

    A FreeList is a list of MemList structures.  See the
    MemList and MemEntry documentation for more information.

    If the FreeList itself is in the free list, it must be
    in the first MemList in the FreeList.

   INPUTS
    free -- a pointer to a FreeList structure

   RESULTS
    None

   SEE ALSO
    AllocEntry(), FreeEntry(), AddFreeList()

   BUGS
    None

 icon.library/GetDefDiskObject                   icon.library/GetDefDiskObject

   NAME
    GetDefDiskObject - read default wb disk object from disk.       (V36)

   SYNOPSIS
    diskobj = GetDefDiskObject(def_type)
         D0                          D0

    struct DiskObject *GetDefDiskObject(LONG);

   FUNCTION
    This routine reads in a default Workbench disk object from disk.
    The valid def_types can be found in workbench/workbench.h and
    currently include WBDISK thru WBGARBAGE.  If the call fails,
    it will return zero.  The reason for the failure may be obtained
    via IoErr().

    Using this routine protects you from any future changes to
    the way default icons are stored within the system.

   INPUTS
    def_type - default icon type (WBDISK thru WBKICK).  Note that the
           define 'WBDEVICE' is not currently supported.

   RESULTS
    diskobj -- the default Workbench disk object in question

   SEE ALSO
    PutDefDiskObject

   BUGS
    None

 icon.library/GetDiskObject                         icon.library/GetDiskObject

   NAME
       GetDiskObject - read in a Workbench disk object from disk.

   SYNOPSIS
       diskobj = GetDiskObject(name)
         D0                      A0

    struct DiskObject *GetDiskObject(char *);

   FUNCTION
    This routine reads in a Workbench disk object in from disk.  The
    name parameter will have a ".info" postpended to it, and the
    info file of that name will be read.  If the call fails,
    it will return zero.  The reason for the failure may be obtained
    via IoErr().

    Using this routine protects you from any future changes to
    the way icons are stored within the system.

    A FreeList structure is allocated just after the DiskObject
    structure; FreeDiskObject makes use of this to get rid of the
    memory that was allocated.

   INPUTS
    name -- name of the object (char *) or NULL if you just want a
        DiskObject structure allocated for you (useful when
        calling AddAppIcon in workbench.library).

   RESULTS
    diskobj -- the Workbench disk object in question

   SEE ALSO
    GetDiskObjectNew(), PutDiskObject(), DeleteDiskObject(),
    FreeDiskObject()

   BUGS
    None

 icon.library/GetDiskObjectNew                   icon.library/GetDiskObjectNew

   NAME
       GetDiskObjectNew - read in a Workbench disk object from disk.    (V36)

   SYNOPSIS
       diskobj = GetDiskObjectNew(name)
         D0                      A0

    struct DiskObject *GetDiskObjectNew(char *);

   FUNCTION
    This routine reads in a Workbench disk object in from disk.  The
    name parameter will have a ".info" postpended to it, and the
    info file of that name will be read.  If the call fails,
    it will return zero.  The reason for the failure may be obtained
    via IoErr().

    Using this routine protects you from any future changes to
    the way icons are stored within the system.

    A FreeList structure is allocated just after the DiskObject
    structure; FreeDiskObject makes use of this to get rid of the
    memory that was allocated.

    This call is functionally identical to GetDiskObject with one exception.
    If its call to GetDiskObject fails, this function calls GetDefDiskObject.
    This is useful when there is no .info file for the icon you are trying
    to get a disk object for.  Applications that use workbench application
    windows MUST use this call if they want to handle the user dropping an
    icon (that doesn't have a .info file) on their window.  The V2.0
    icon editor program is an example of a workbench application window
    that uses this call.

   INPUTS
    name -- name of the object (char *) or NULL if you just want a
        DiskObject structure allocated for you (useful when
        calling AddAppIcon in workbench.library).

   RESULTS
    diskobj -- the Workbench disk object in question

   SEE ALSO
    FreeDiskObject(), GetDiskObject(), PutDiskObject(), DeleteDiskObject()

   BUGS
    None

 icon.library/MatchToolValue                       icon.library/MatchToolValue

   NAME
       MatchToolValue - check a tool type variable for a particular value.

   SYNOPSIS
       result = MatchToolValue(typeString, value)
         D0                        A0        A1

    BOOL MatchToolValue(char *, char *);

   FUNCTION
    MatchToolValue is useful for parsing a tool type value for
    a known value.  It knows how to parse the syntax for a tool
    type value (in particular, it knows that '|' separates
    alternate values).  Note that the parsing is case insensitve.

   INPUTS
    typeString - a ToolType value (as returned by FindToolType)
    value - you are interested if value appears in typeString

   RESULTS
    result - TRUE if the value was in typeString else FALSE.

   EXAMPLE
    Assume there are two type strings:
        type1 = "text"
        type2 = "a|b|c"

    MatchToolValue( type1, "text" ) returns TRUE
    MatchToolValue( type1, "TEXT" ) returns TRUE
    MatchToolValue( type1, "data" ) returns FALSE
    MatchToolValue( type2, "a" ) returns TRUE
    MatchToolValue( type2, "b" ) returns TRUE
    MatchToolValue( type2, "d" ) returns FALSE
    MatchToolValue( type2, "a|b" ) returns FALSE

   SEE ALSO
    FindToolType()

   BUGS
    None

 icon.library/PutDefDiskObject                   icon.library/PutDefDiskObject

   NAME
    PutDefDiskObject - write disk object as the default for its type.  (V36)

   SYNOPSIS
       status = PutDefDiskObject(diskobj)
         D0                        A0

    BOOL PutDefDiskObject(struct DiskObject *);

   FUNCTION
    This routine writes out a DiskObject structure, and its
    associated information.  If the call fails, a zero will
    be returned.  The reason for the failure may be obtained
    via IoErr().

    Note that this function calls PutDiskObject internally which means
    that this call (if sucessful) notifies workbench than an icon has
    been created/modified.

    Using this routine protects you from any future changes to
    the way default icons are stored within the system.

   INPUTS
    diskobj -- a pointer to a DiskObject

   RESULTS
    status -- TRUE if the call succeeded else FALSE

   SEE ALSO
    GetDefDiskObject

   BUGS
    None

 icon.library/PutDiskObject                         icon.library/PutDiskObject

   NAME
       PutDiskObject - write out a DiskObject to disk.

   SYNOPSIS
       status = PutDiskObject(name, diskobj)
         D0                    A0      A1

    BOOL PutDiskObject(char *, struct DiskObject *);

   FUNCTION
    This routine writes out a DiskObject structure, and its
    associated information.  The file name of the info
    file will be the name parameter with a
    ".info" postpended to it.  If the call fails, a zero will
    be returned.  The reason for the failure may be obtained
    via IoErr().

    As of release V2.0, PutDiskObject (if sucessful) notifies workbench
    han an icon has been created/modified.

    Using this routine protects you from any future changes to
    the way icons are stored within the system.

   INPUTS
    name -- name of the object (pointer to a character string)
    diskobj -- a pointer to a DiskObject

   RESULTS
    status -- TRUE if the call succeeded else FALSE

   NOTES
    It is recommended that if you wish to copy an icon from one place
    to another than you use GetDiskObject() and PutDiskObject()
    and do not copy them directly.

   SEE ALSO
    GetDiskObject(), FreeDiskObject(), DeleteDiskObject()

   BUGS
    None


Text_Autodocs/mathieeesingbas.doc

TABLE OF CONTENTS

mathieeesingbas.library/IEEESPAbs
mathieeesingbas.library/IEEESPAdd
mathieeesingbas.library/IEEESPCeil
mathieeesingbas.library/IEEESPCmp
mathieeesingbas.library/IEEESPDiv
mathieeesingbas.library/IEEESPFix
mathieeesingbas.library/IEEESPFloor
mathieeesingbas.library/IEEESPFlt
mathieeesingbas.library/IEEESPMul
mathieeesingbas.library/IEEESPNeg
mathieeesingbas.library/IEEESPSub
mathieeesingbas.library/IEEESPTst
 mathieeesingbas.library/IEEESPAbs           mathieeesingbas.library/IEEESPAbs

   NAME
    IEEESPAbs -- compute absolute value of IEEE single precision argument

   SYNOPSIS
      x   = IEEESPAbs(  y  );
     d0		    d0

    float	x,y;

   FUNCTION
    Take the absolute value of argument y and return it to caller.

   INPUTS
    y -- IEEE single precision floating point value

   RESULT
    x -- IEEE single precision floating point value

   BUGS

   SEE ALSO
 mathieeesingbas.library/IEEESPAdd           mathieeesingbas.library/IEEESPAdd

   NAME
    IEEESPAdd -- add one single precision IEEE number to another

   SYNOPSIS
      x   = IEEESPAdd(  y  ,  z  );
     d0		   d0     d1

    float	x,y,z;

   FUNCTION
    Compute x = y + z in IEEE single precision.

   INPUTS
    y -- IEEE single precision floating point value
    z -- IEEE single precision floating point value

   RESULT
    x -- IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEESPSub
 mathieeesingbas.library/IEEESPCeil         mathieeesingbas.library/IEEESPCeil

   NAME
    IEEESPCeil -- compute Ceil function of IEEE single precision number

   SYNOPSIS
      x   = IEEESPCeil(  y  );
     d0		     d0

    float	x,y;

   FUNCTION
    Calculate the least integer greater than or equal to x and return it.
    This identity is true.  Ceil(x) = -Floor(-x).

   INPUTS
    y -- IEEE single precision floating point value

   RESULT
    x -- IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEESPFloor
 mathieeesingbas.library/IEEESPCmp           mathieeesingbas.library/IEEESPCmp

   NAME
    IEEESPCmp -- compare two single precision floating point numbers

   SYNOPSIS
      c   = IEEESPCmp(  y  ,  z  );
      d0		    d0   d1

    float	y,z;
    long	c;

   FUNCTION
    Compare y with z. Set the condition codes for less, greater, or
    equal. Set return value c to -1 if y<z, or +1 if y>z, or 0 if
    y == z.

   INPUTS
    y -- IEEE single precision floating point value
    z -- IEEE single precision floating point value

   RESULT
       c = 1   cc = gt         for (y > z)
       c = 0   cc = eq         for (y == z)
       c = -1  cc = lt         for (y < z)

   BUGS

   SEE ALSO
 mathieeesingbas.library/IEEESPDiv           mathieeesingbas.library/IEEESPDiv

   NAME
    IEEESPDiv -- divide one single precision IEEE by another

   SYNOPSIS
      x   = IEEESPDiv(  y  ,  z  );
     d0		   d0    d1

    float	x,y,z;

   FUNCTION
    Compute x = y / z in IEEE single precision.
    Note that the Motorola fast floating point Div routine reverses
    the order of the arguments for the C interface, although the
    dividend is still in d0 and the divisor is in d1.

   INPUTS
    y -- IEEE single precision floating point value
    z -- IEEE single precision floating point value

   RESULT
    x -- IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEESPMul
 mathieeesingbas.library/IEEESPFix           mathieeesingbas.library/IEEESPFix

   NAME
    IEEESPFix -- convert IEEE single float to integer

   SYNOPSIS
    x   = IEEESPFix(  y  );
    d0		 d0

    long	x;
    float	y;

   FUNCTION
    Convert IEEE single precision argument to a 32 bit signed integer
    and return result.

   INPUTS
    y -- IEEE single precision floating point value

   RESULT
    if no overflow occured then return
        x -- 32 bit signed integer
    if overflow return largest +- integer
        For round to zero

   BUGS

   SEE ALSO
    IEEESPFlt
 mathieeesingbas.library/IEEESPFloor       mathieeesingbas.library/IEEESPFloor

   NAME
    IEEESPFloor -- compute Floor function of IEEE single precision number

   SYNOPSIS
      x   = IEEESPFloor(  y  );
      d0		      d0

    float	x,y;

   FUNCTION
    Calculate the largest integer less than or equal to x and return it.

   INPUTS
    y -- IEEE single precision floating point value

   RESULT
    x -- IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEESPCeil
 mathieeesingbas.library/IEEESPFlt           mathieeesingbas.library/IEEESPFlt

   NAME
    IEEESPFlt -- convert integer to IEEE single precision number

   SYNOPSIS
      x   = IEEESPFlt(  y  );
     d0		   d0

    float	x;
    long	y;

   FUNCTION
    Convert a signed 32 bit value to a single precision IEEE value
    and return it in d0. No exceptions can occur with this
    function.

   INPUTS
    y -- 32 bit integer in d0

   RESULT
    x is a 32 bit single precision IEEE value

   BUGS

   SEE ALSO
    IEEESPFix
 mathieeesingbas.library/IEEESPMul           mathieeesingbas.library/IEEESPMul

   NAME
    IEEESPMul -- multiply one double precision IEEE number by another

   SYNOPSIS
      x   = IEEESPMul(  y  ,  z  );
     d0		   d0    d1

    float	x,y,z;

   FUNCTION
    Compute x = y * z in IEEE single precision.

   INPUTS
    y -- IEEE single precision floating point value
    z -- IEEE single precision floating point value

   RESULT
    x -- IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEESPDiv
 mathieeesingbas.library/IEEESPNeg           mathieeesingbas.library/IEEESPNeg

   NAME
    IEEESPNeg -- compute negative value of IEEE single precision number

   SYNOPSIS
      x   = IEEESPNeg(  y  );
      d0		   d0

    float	x,y;

   FUNCTION
    Invert the sign of argument y and return it to caller.

   INPUTS
    y - IEEE single precision floating point value

   RESULT
    x - IEEE single precision floating point value

   BUGS

   SEE ALSO
 mathieeesingbas.library/IEEESPSub           mathieeesingbas.library/IEEESPSub

   NAME
    IEEESPSub -- subtract one single precision IEEE number from another

   SYNOPSIS
      x   = IEEESPSub(  y  ,  z  );
     d0		   d0     d1

    float	x,y,z;

   FUNCTION
    Compute x = y - z in IEEE single precision.

   INPUTS
    y -- IEEE single precision floating point value
    z -- IEEE single precision floating point value

   RESULT
    x -- IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEESPAdd
 mathieeesingbas.library/IEEESPTst           mathieeesingbas.library/IEEESPTst

   NAME
    IEEESPTst -- compare IEEE single precision value to 0.0

   SYNOPSIS
      c   = IEEESPTst(  y  );
      d0		    d0

    float	y;
    long	c;

   FUNCTION
    Compare y to 0.0, set the condition codes for less than, greater
    than, or equal to 0.0.  Set the return value c to -1 if less than,
    to +1 if greater than, or 0 if equal to 0.0.

   INPUTS
    y -- IEEE single precision floating point value

   RESULT
    c = 1	cc = gt		for (y > 0.0)
    c = 0	cc = eq		for (y == 0.0)
    c = -1  cc = lt		for (y < 0.0)

   BUGS

   SEE ALSO


Text_Autodocs/commodities.doc

TABLE OF CONTENTS

commodities.library/ActivateCxObj
commodities.library/AddIEvents
commodities.library/AttachCxObj
commodities.library/ClearCxObjError
commodities.library/CreateCxObj
commodities.library/CxBroker
commodities.library/CxMsgData
commodities.library/CxMsgID
commodities.library/CxMsgType
commodities.library/CxObjError
commodities.library/CxObjType
commodities.library/DeleteCxObj
commodities.library/DeleteCxObjAll
commodities.library/DisposeCxMsg
commodities.library/DivertCxMsg
commodities.library/EnqueueCxObj
commodities.library/InsertCxObj
commodities.library/InvertKeyMap
commodities.library/ParseIX
commodities.library/RemoveCxObj
commodities.library/RouteCxMsg
commodities.library/SetCxObjPri
commodities.library/SetFilter
commodities.library/SetFilterIX
commodities.library/SetTranslate
 commodities.library/ActivateCxObj           commodities.library/ActivateCxObj

   NAME
    ActivateCxObj -- change the activation state of a commodity object.
             (V36)

   SYNOPSIS
    previous = ActivateCxObj(co,true);
                 A0 D0

    LONG ActivateCxObj(CxObj *,LONG);

   FUNCTION
    Commodity objects of all types maintain an "activation state".
    If an object is "active", then it performs its particular action
    whenever a commodity message arrives. If the object is "inactive"
    no action is taken, and the message goes on to its next destination.

    All objects are created in the "active" state except brokers
    which are created "inactive". Thus, after you create your
    broker and hang a tree of objects off of it, you must remember
    to use this function to activate it. This causes it to divert all
    messages to your tree of objects.

    This function activates 'co' if 'true' is different than 0. and
    deactivates it otherwise. The previous activation state is
    returned.

   INPUTS
    co - the commodity object to affect
    true - 0 to deactivate the object, anything else to activate it

   RESULTS
    previous - the previous activation state: 0 if the object was
           inactive, anything else if the object was active

   SEE ALSO
    CxBroker()

 commodities.library/AddIEvents                 commodities.library/AddIEvents

   NAME
    AddIEvents -- add input events to commodities' input stream. (V36)

   SYNOPSIS
    AddIEvents(events)
           A0

    VOID AddIEvents(struct InputEvent *);

   FUNCTION
    This function adds a null-terminated linked list of input events to
    the input stream of commodities. It is a touch easier than using the
    input device directly.

    The contents of the input events are copied into commodity
    messages, so they may be disposed of as soon as this call returns.

    The messages are initially routed to the first broker in the
    Commodities Object List.

   INPUTS
    events - the list of input events to add

   SEE ALSO
    cx_lib/FreeIEvents()

 commodities.library/AttachCxObj               commodities.library/AttachCxObj

   NAME
    AttachCxObj -- attach a commodity object to the end of an existing
               list of objects. (V36)

   SYNOPSIS
    AttachCxObj(headObj,co);
            A0      A1

    VOID AttachCxObj(CxObj *,CxObj *);

   FUNCTION
    Adds 'co' to the list of objects pointed to by 'headObj'. The
    new object is added at the end of the list.

   INPUTS
    headObj - pointer to a list of objects
    co - the object to add to the list

   RESULTS
    If 'co' is NULL, this function will record that fact in the
    internal accumulated error of 'headObj'. This error record
    can be retrieved using CxObjError() and cleared using
    ClearCxObjError().

   SEE ALSO
    CxObjError(), ClearCxObjError()

 commodities.library/ClearCxObjError       commodities.library/ClearCxObjError

   NAME
    ClearCxObjError -- clear the accumulated error value of a commodity
               object. (V36)

   SYNOPSIS
    ClearCxObjError(co);
               A0

    VOID ClearCxObjError(CxObj *);

   FUNCTION
    This function clears the accumulated error value of commodity object
    'co'.

    It is unwise to do this to a filter if COERR_BADFILTER is set.
    This will fool commodities into thinking the filter is OK. Set
    another valid filter, or leave the error value alone.

   INPUTS
    co - the object to affect

   SEE ALSO
    CxObjError()

 commodities.library/CreateCxObj               commodities.library/CreateCxObj

   NAME
    CreateCxObj -- create a new commodity object. (V36)

   SYNOPSIS
    co = CreateCxObj(type,arg1,arg2);
             D0   A0   A1

    CxObj *CreateCxObj(ULONG,LONG,LONG);

   FUNCTION
    This function creates a commodity object of type 'type'. It is not
    proper to call this function directly. Each object creation routine
    except CxBroker() is defined as a macro in <libraries/commodities.h>
    These are independently documented.

    All functions which operate on a commodity object are made with
    a reference to the thirty-two bit value returned by this function
    (or by CxBroker()).

   INPUTS
    type - the type of object to create as defined in
           <libraries/commodities.h>
       arg1 - first argument, meaning depends on 'type'
    arg2 - second argument, meaning depends on 'type'

   RESULTS
    co - a pointer to the new object or NULL if it could not be created.
         A NULL return indicates typically a lack of system memory. Minor
         problems in creating an object, such as providing a bad filter
         description to cx_lib/CxFilter(), typically don't cause failure,
         but are recorded in an internal error field in the new object
         which can be accessed via CxObjError().

   SEE ALSO
    CxObjError(), cx_lib/CxFilter(), cx_lib/CxSender(),
    cx_lib/CxSignal(), cx_lib/CxTranslate(), cx_lib/CxDebug(),
    cx_lib/CxCustom(), CxBroker()

 commodities.library/CxBroker                     commodities.library/CxBroker

   NAME
    CxBroker -- create a commodity broker. (V36)

   SYNOPSIS
    broker = CxBroker(nb,error);
              A0 D0

    CxObj *CxBroker(struct NewBroker *,LONG *);

   FUNCTION
    This function creates a broker from the specification found in the
    NewBroker structure pointed to by 'nb'. The purpose and meaning of the
    fields of the NewBroker structure are described below. Also see
    <libraries/commodities.h> for more info.

    struct NewBroker
    {
           BYTE            nb_Version;
           BYTE           *nb_Name;
           BYTE           *nb_Title;
           BYTE           *nb_Descr;
           SHORT           nb_Unique;
           BYTE            nb_Pri;
        struct MsgPort *nb_Port;
        WORD            nb_ReservedChannel;
    };

    nb_Version
    This is the way that future versions of commodities.library
    can identify which version of the NewBroker structure you are using.
    This should be set to NB_VERSION, defined in <libraries/commodities.h>

    nb_Name
    This is the name of the broker. This name is used to find the broker
    in the Commodities Object List and is the name shown in the list
    gadget of the Exchange program. The name string is copied in the
    broker object upon creation, so this string can be discarded right
    after CxBroker() returns. The maximum length of the name string is
    defined by a constant in <libraries/commodities.h>.

    nb_Title, nb_Descr
    These are two strings which appear to the user in the Exchange
    program and describe the application the broker is representing.
    Note that these strings are copied into the broker object.
    The maximum length of these strings that will be recognized are
    defined by constants in <libraries/commodities.h>.

    nb_Unique
    This field indicates what should happen if a broker of the same name
    (nb_Name) already exists in the Commodities Object List. Constants
    in <libraries/commodities.h> allow the caller to specify whether
    another broker is to be created, and whether any existing broker of
    the same name should be notified that an attempt at creating a
    duplicate has been made.

    nb_Pri
    This specifies with what priority the new broker is to be inserted
    within the Commodities Object List. Higher priority nodes appear
    earlier in a list. See <libraries/commodities.h> for guidelines for
    priorities of different types of applications. It is strongly
    recommended that the ToolTypes environment of an application be used
    to allow the end-user to set the priority of the broker.

   INPUTS
    nb - an initialized NewBroker structure
    error - a pointer to a longword where to store a failure code, this
        may be NULL

   RESULTS
    broker - a pointer to the broker object or NULL upon failure. If the
         'error' is not NULL, a further diagnostic code is placed at
         that address. Error codes are in <libraries/commodities.h> and
         include:

            CBERR_OK
                No problems; broker created OK.

             CBERR_SYSERR
                System problems, not your fault. Sign of low memory or
            big problems.

            CBERR_DUP
            The nb_Unique field specified that only one broker of
            'nb_Name' should be allowed, and one already exists.

            CBERR_VERSION
            The version specified in 'nb_Version' is unknown to the
            library.

   SEE ALSO
    SetCxObjPri(), <libraries/commodities.h>

 commodities.library/CxMsgData                   commodities.library/CxMsgData

   NAME
    CxMsgData -- obtain a pointer to a commodity message's data area. (V36)

   SYNOPSIS
    data = CxMsgData(cxm);
             A0

    UBYTE *CxMsgData(struct CxMsg *);

   FUNCTION
    Most commodity messages contain meaningful data, such as an InputEvent
    structure. This function returns a pointer to this data.

    You may get a commodity message from a synchronous (custom object) or
    asynchronous (sender object) source. In the second case, 'data' is
    not valid after you have replied to the message.

   INPUTS
    cxm - the commodity message to get the data pointer from

   RESULTS
    data - a pointer to the message's data, or NULL if 'cxm' is NULL.

   SEE ALSO
    cx_lib/CxSender(), cx_lib/CxCustom()

 commodities.library/CxMsgID                       commodities.library/CxMsgID

   NAME
    CxMsgID -- obtain the ID of a commodity message. (V36)

   SYNOPSIS
    id = CxMsgID(cxm);
             A0

    LONG CxMsgID(struct CxMsg *);

   FUNCTION
    This function returns the value associated with the cause or source
    of the commodity message 'cxm'. Values are provided by the application
    when a sender or custom object is created.

   INPUTS
    cxm - the commodity message to inquire about

   RESULTS
    id - if not specified by the application, the ID value of a
            commodity message will be 0. It is suggested that using
         non-zero values in your program as a rule may identify some
         possible errors.

   SEE ALSO
    cx_lib/CxSender(), cx_lib/CxCustom()

 commodities.library/CxMsgType                   commodities.library/CxMsgType

   NAME
    CxMsgType -- obtain the type of a commodity message. (V36)

   SYNOPSIS
    type = CxMsgType(cxm);
             A0

    ULONG CxMsgType(struct CxMsg *);

   FUNCTION
    This function returns the type of a commodity message. Possible values
    of 'type' are defined in <libraries/commodities.h>. Most commodity
    messages are of type CXM_IEVENT.

   INPUTS
    cxm - the commodity message to inquire about

   RESULTS
       type - the type of the commodity message, possible values are defined
           in <libraries/commodities.h>

 commodities.library/CxObjError                 commodities.library/CxObjError

   NAME
    CxObjError -- obtain a commodity object's accumulated error. (V36)

   SYNOPSIS
    error = CxObjError(co);
               A0

    LONG CxObjError(CxObj *);

   FUNCTION
    When a function acting on an object fails, it records the failure
    in the object. This function returns the accumulated error value.
    The values are represented by flag bits defined in
    <libraries/commodities.h>. Several errors may be recorded by multiple
    bits in 'error'.

    The currently defined errors are:

    COERR_ISNULL
      The value of parameter 'co' was in fact NULL. This error
      means "the problem with the object you inquire about is
      that it failed to be created."

      COERR_NULLATTACH
      Using the commodities' list manipulation functions, an attempt was
      made to add a NULL object to the list belonging to 'co'. This allows
      a line of code as follows to exist in an error-tolerant program:

        AttachCxObj(filter,CxSender(myport,MY_ID));

      COERR_BADFILTER
      The most recent filter specification for a filter object
      was faulty. This happens if no sense can be made out of a
      description string, or if an input expression (IX) has an
      invalid format or version byte. When this bit is set in a
      filter's error field, the filter will match nothing, but this
      is not the proper way to "turn off" a filter, use ActivateCxObj().

      COERR_BADTYPE
      A type specific operation, such as SetFilterIX(), was called
      for object 'co', but 'co' isn't of the proper type.

   INPUTS
    co - the commodity object to get the accumulated error from

   RESULTS
    error - the accumulated error

   SEE ALSO
    SetFilter(), SetFilterIX(), AttachCxObj(), ActivateCxObj(),
    ClearCxObjError()

 commodities.library/CxObjType                   commodities.library/CxObjType

   NAME
    CxObjType -- obtain the type of a commodity object. (V36)

   SYNOPSIS
    type = CxObjType(co);
             A0

    ULONG CxObjType(CxObj *);

   FUNCTION
    This function should not really be necessary. It returns
    the type of a commodity object, which you should already
    know, since you created it in the first place.

   INPUTS
    co - the commodity object to inquire about

   RESULTS
    type - the type of the commodity object, possible values are
           defined in <libraries/commodities.h>

   SEE ALSO
    CreateCxObj()

 commodities.library/DeleteCxObj               commodities.library/DeleteCxObj

   NAME
    DeleteCxObj -- delete a commmodity object. (V36)

   SYNOPSIS
    DeleteCxObj(co);
                A0

    VOID DeleteCxObj(CxObj *);

   FUNCTION
    Deletes a commodity object of any type. If the object
    is linked into a list, it is first removed. Note that
    the handle 'co' is invalid after this function is called.

    Also note that deleting an object which has other objects attached
    to it may be undesirable. Use the function DeleteCxObjAll()
    to delete an entire sub-tree of objects.

   INPUTS
    co - the commodity object to delete

   SEE ALSO
    DeleteCxObjAll()

 commodities.library/DeleteCxObjAll         commodities.library/DeleteCxObjAll

   NAME
    DeleteCxObjAll -- recursively delete a tree of commodity objects.
              (V36)

   SYNOPSIS
    DeleteCxObjAll(co);
               A0

    VOID DeleteCxObjAll(CxObj *);

   FUNCTION
    This function deletes the commodity object 'co', and
    recursively deletes all objects attached to it, and the
    objects attached to them, etc.

    If 'co' is linked into a list, it is first removed. Note
    that the handle 'co' is invalid after this function is called.

    This function is useful when an application exits: most
    applications can clean up completely by deleting the
    entire sub-tree of objects starting at their broker.

   INPUTS
    co - the first commodity object to delete

   SEE ALSO
    DeleteCxObj()

 commodities.library/DisposeCxMsg             commodities.library/DisposeCxMsg

   NAME
    DisposeCxMsg -- delete a commodity message. (V36)

   SYNOPSIS
    DisposeCxMsg(cxm);
             A0

    VOID DisposeCxMsg(struct CxMsg *);

   FUNCTION
    This function eliminates the commodity message pointed to by 'cxm'.
    Can be used to 'swallow' InputEvents by disposing of every commodity
    message of type CXM_IEVENT.

   INPUTS
    cxm - the commodity message to delete

 commodities.library/DivertCxMsg               commodities.library/DivertCxMsg

   NAME
    DivertCxMsg -- send a commodity message down an object list. (V36)

   SYNOPSIS
    DivertCxMsg(cxm,headObj,returnObj);
            A0  A1      A2

    VOID DivertCxMsg(struct CxMsg *,CxObj *,CxObj *);

   FUNCTION
    This function sends the commodity message 'cxm' down the list of
    objects attached to 'headObj'. The pointer 'returnObj' is first
    pushed onto the routing stack of 'cxm' so that when the end of the
    list of 'headObj' is reached the SUCCESSOR of 'returnObj' is the
    next destination.

    For example, when a filter finds a match with a message, the
    message is diverted down the filter's list like this:

        DivertCxMsg(cxm,filter,filter);

   INPUTS
    cxm - the commodity message to divert
    headObj - the list of objects to divert the message to
    returnObj - the object to use as a place holder

   SEE ALSO
    RouteCxMsg()

 commodities.library/EnqueueCxObj             commodities.library/EnqueueCxObj

   NAME
    EnqueueCxObj -- insert a commodity object within a list of objects
                based on object priority. (V36)

   SYNOPSIS
    EnqueueCxObj(headObj,co);
             A0      A1

    VOID EnqueueCxObj(CxObj *,CxObj *);

   FUNCTION
    This function puts object 'co' into the list of object 'headObj'.
    The insertion point is determined by the object's priority. The
    objects are kept in the list from the highest priority to the
    lowest. New nodes are inserted in front of the first node with a
    lower priority. Hence a FIFO queue for nodes of equal priority.

    The priority of the commodity object can be set using SetCxObjPri().

   INPUTS
    headObj - pointer to a list of objects
    co - the object to add to the list

   RESULTS
    If 'co' is NULL, this function will record that fact in the
    internal accumulated error of 'headObj'. This error record
    can be retrieved using CxObjError() and cleared using
    ClearCxObjError().

   SEE ALSO
    SetCxObjPri(), CxObjError(), ClearCxObjError()

 commodities.library/InsertCxObj               commodities.library/InsertCxObj

   NAME
    InsertCxObj -- insert a commodity object in a list after a given
               object. (V36)

   SYNOPSIS
    InsertCxObj(headObj,co,pred);
            A0      A1 A2

    VOID InsertCxObj(CxObj *,CxObj *,CxObj *);

   FUNCTION
    Adds 'co' to the list of objects pointed to by 'headObj' after
    object 'pred'.

   INPUTS
    headObj - pointer to a list of objects
    co - the object to insert in the list
    pred - the object after which 'co' should be inserted. If this is NULL
           then 'co' is added to the head of the list.

   RESULTS
    If 'co' is NULL, this function will record that fact in the
    internal accumulated error of 'headObj'. This error record
    can be retrieved using CxObjError() and cleared using
    ClearCxObjError().

   SEE ALSO
    CxObjError(), ClearCxObjError()

 commodities.library/InvertKeyMap             commodities.library/InvertKeyMap

   NAME
    InvertKeyMap -- generate an input event from an ANSI code. (V36)

   SYNOPSIS
    success = InvertKeyMap(ansicode,event,km)
                    D0       A0    A1

    BOOL InvertKeyMap(ULONG,struct InputEvent *,struct KeyMap *);

   FUNCTION
    This function uses the system call MapANSI() to figure out what
    InputEvent translates to an ANSI character code 'ansicode'. The
    InputEvent pointed to by 'event' is filled in with that information.
    The KeyMap 'km' is used for the translation, unless it is NULL, in
    which case the system default keymap (as defined when
    commodities.library is initialized) is used.

   INPUTS
    ansicode - the ANSI code to convert to an input event
    event - the InputEvent to fill-in
    km - the keymap to use for the translation, or NULL to use the
         system default keymap.

   RESULTS
    success - TRUE if the translation worked, FALSE otherwise.

   BUGS
    This function currently handles one-deep dead keys (such as
    <alt f>o). It does not look up the high key map (keystrokes
    with scan codes greater than 0x40), and misses system changes to
    the default key map.

   SEE ALSO
    cx_lib/InvertString()

 commodities.library/ParseIX                       commodities.library/ParseIX

   NAME
    ParseIX -- initialize an input expression given a description string.
           (V36)

   SYNOPSIS
    failureCode = ParseIX(description,ix);
                  A0          A1

    LONG ParseIX(STRPTR,IX *);

   FUNCTION
    Given an input description string and an allocated input
    expression, sets the fields of the input expression to
    correspond to the description string.

   INPUTS
    description - the string to parse
    ix - the input expression to hold the result of the parse

   RESULTS
    failureCode -  0 if all went well,
              -1 if tokens after end (code spec)
                  -2 if 'description' was NULL

 commodities.library/RemoveCxObj               commodities.library/RemoveCxObj

   NAME
    RemoveCxObj -- remove a commodity object from a list. (V36)

   SYNOPSIS
    RemoveCxObj(co);
            A0

    VOID RemoveCxObj(CxObj *);

   FUNCTION
    This function remove 'co' from any list it may be a part of.
    Will not crash if 'co' is NULL, or if it has not been inserted
    in a list (and is not corrupted).

    It is not recommended to remove a broker from the master list.

   INPUTS
       co - the object to remove, may be NULL

   SEE ALSO
    AttachCxObj(), EnqueueCxObj(), InsertCxObj()

 commodities.library/RouteCxMsg                 commodities.library/RouteCxMsg

   NAME
    RouteCxMsg -- set the next destination of a commodity message. (V36)

   SYNOPSIS
    RouteCxMsg(cxm,co);
           A0  A1

    VOID RouteCxMsg(struct CxMsg *,CxObj *);

   FUNCTION
    Establishes the next destination of a commodity message
    to be 'co', which must be a valid commodity object, and
    must be linked in ultimately to the Commodities Object List.

    Routing of an object is analogous to a 'goto' in a program.
    There is no effect on the message's routing stack.

   INPUTS
    cxm - the commodity message to route
    co - the commodity object to route the message to

   SEE ALSO
    DivertCxMsg()

 commodities.library/SetCxObjPri               commodities.library/SetCxObjPri

   NAME
    SetCxObjPri -- set the priority of a commodity object. (V36)

   SYNOPSIS
    SetCxObjPri(co,pri)
            A0 D0

    VOID SetCxObjPri(CxObj *,LONG);

   FUNCTION
    This function sets the priority of a commodity object for the
    purposes of EnqueueCxObj().

    It is strongly recommended that the ToolTypes environment be
    utilized to provide end-user control over the priority of
     brokers, but application specific ordering of other objects
    within their lists is not dictated.

   INPUTS
    co - the commodity object to affect
    pri - the object's new priority in the range -128 to +127. A value
          of 0 is normal.

   SEE ALSO
    EnqueueCxObj()

 commodities.library/SetFilter                   commodities.library/SetFilter

   NAME
    SetFilter -- change the matching condition of a commodity filter.
             (V36)

   SYNOPSIS
    SetFilter(filter,text);
          A0     A1

    VOID SetFilter(CxObj *,STRPTR);

   FUNCTION
    This function changes the matching condition of a commodity input
    filter to that described by the input description string 'text'.

   INPUTS
    filter - the filter object to affect
    text - the new matching conditions for the filter

   RESULTS
    The internal error of 'filter' will have the COERR_BADFILTER
    bit set or cleared depending on the failure or success of this
    function.

   SEE ALSO
    SetFilterIX(), CxObjError()

 commodities.library/SetFilterIX               commodities.library/SetFilterIX

   NAME
    SetFilterIX -- change the matching condition of a commodity filter.
               (V36)

   SYNOPSIS
    SetFilterIX(filter,ix);
            A0     A1

    VOID SetFilterIX(CxObj *,IX *);

   FUNCTION
    This function changes the matching condition of a commodity input
    filter to that described by the binary input expression pointed by
    'ix'.

    Input expressions are defined in <libraries/commodities.h>.
    It is important to remember that the first field of the input
    expression structure must indicate which version of the
    input expression structure is being used.

   INPUTS
    filter - the filter object to affect
    ix - the new matching conditions for the filter

   RESULTS
    The internal error of 'filter' will have the COERR_BADFILTER
    bit set or cleared depending on the failure or success of this
    function.

   SEE ALSO
    SetFilter(), CxObjError(), <libraries/commodities.h>

 commodities.library/SetTranslate             commodities.library/SetTranslate

   NAME
    SetTranslate -- replace a translator object's translation list. (V36)

   SYNOPSIS
    SetTranslate(translator,events);
             A0         A1

    VOID SetTranslate(CxObj *,struct InputEvent *);

   FUNCTION
    This function replaces the translation list of a commodity
    translator object with the linked list starting at 'events'.

    A NULL value for 'events' indicates that the object 'translator'
    should swallow all commodity messages that are sent its way.

    Note that the input events are not copied into commodities' private
    memory, but the value of 'events' is used -- asynchronously to the
    application program -- to find a chain of InputEvents in the
    application's data space. At the time of translation, each input event
    is copied into its own new commodity message.

    The above means that no other commodities' user, nor
    commodities.library itself will be modifying your list of InputEvents.
    On the other hand, your program must not corrupt the input event
    chain that has been presented to a translator.

   INPUTS
    translator - the translator object to affect
    events - the new input event translation list

   SEE ALSO
    <devices/inputevent.h>, cx_lib/CxTranslate()


Text_Autodocs/iffparse.doc

TABLE OF CONTENTS

HookEntry
iffparse.library/AllocIFF
iffparse.library/AllocLocalItem
iffparse.library/CloseClipboard
iffparse.library/CloseIFF
iffparse.library/CollectionChunk
iffparse.library/CollectionChunks
iffparse.library/CurrentChunk
iffparse.library/EntryHandler
iffparse.library/ExitHandler
iffparse.library/FindCollection
iffparse.library/FindLocalItem
iffparse.library/FindProp
iffparse.library/FindPropContext
iffparse.library/FreeIFF
iffparse.library/FreeLocalItem
iffparse.library/GoodID
iffparse.library/GoodType
iffparse.library/IDtoStr
iffparse.library/InitIFF
iffparse.library/InitIFFasClip
iffparse.library/InitIFFasDOS
iffparse.library/LocalItemData
iffparse.library/OpenClipboard
iffparse.library/OpenIFF
iffparse.library/ParentChunk
iffparse.library/ParseIFF
iffparse.library/PopChunk
iffparse.library/PropChunk
iffparse.library/PropChunks
iffparse.library/PushChunk
iffparse.library/ReadChunkBytes
iffparse.library/ReadChunkRecords
iffparse.library/SetLocalItemPurge
iffparse.library/StopChunk
iffparse.library/StopChunks
iffparse.library/StopOnExit
iffparse.library/StoreItemInContext
iffparse.library/StoreLocalItem
iffparse.library/WriteChunkBytes
iffparse.library/WriteChunkRecords
 HookEntry                                                           HookEntry

   NAME
    HookEntry -- call-back stub vector (LANGUAGE SPECIFIC LINK ROUTINE)

   SYNOPSIS
    This function is never called directly by the client.

   FUNCTION
    HookEntry's purpose is to do language-specific setup and conversion
    of parameters passed from a library to a client call-back routine.
    Under Kickstart 2.0, a standard for call-backs has been established.
    The registers will contain the following items:

        A0:	pointer to hook that enabled us to get here.
        A2:	pointer to "object."
        A1:	pointer to "message packet."

    In iffparse, the "object" will vary from routine to routine.  The
    "message packet" is also specific to the operation involved (RTFM!).

    THIS ROUTINE IS NOT PART OF IFFPARSE.  It, or something similar, is
    part of the compiler vendor's link library.  (If it's not there,
    cobbling up your own isn't too hard.)

   SEE ALSO
    EntryHandler(), ExitHandler(), InitIFF(), SetLocalItemPurge(),
    utility/hooks.h	(A must-read;  LOTS of details in there)

 iffparse.library/AllocIFF                           iffparse.library/AllocIFF

   NAME
    AllocIFF -- Create a new IFFHandle structure.

   SYNOPSIS
    iff = AllocIFF ()
    d0

    struct IFFHandle *iff;

   FUNCTION
    Allocates a new IFFHandle structure and initializes the basic values.
    This function is the only supported way to create an IFFHandle
    structure since there are private fields that need to be initialized.

   INPUTS

   RESULT
    iff	- pointer to IFFHandle structure or NULL if the allocation
          failed.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    FreeIFF()

 iffparse.library/AllocLocalItem               iffparse.library/AllocLocalItem

   NAME
    AllocLocalItem -- Create a local context item structure.

   SYNOPSIS
    item = AllocLocalItem (type, id, ident, usize)
     d0                     d0   d1   d2     d3

    struct LocalContextItem *item;
    LONG			type, id, ident, usize;

   FUNCTION
    Allocates and initializes a LocalContextItem structure with "usize"
    bytes of associated user data.  This is the only supported way to
    create such an item.  The user data can be accessed with the
    LocalItemData function.  An item created with this function
    automatically has its purge vectors set up correctly to dispose of
    itself and its associated user data area.  Any additional cleanup
    should be done with a user-supplied purge vector.

   INPUTS
    type,id	- additional longword identification values.
    ident	- longword identifier for class of context item.
    usize	- number of bytes of user data to allocate for this item.

   RESULT
    item	- pointer to initialized LocalContextItem or NULL if the
          allocation failed.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    FreeLocalItem(), LocalItemData(), StoreLocalItem(),
    StoreItemInContext(), SetLocalItemPurge()

 iffparse.library/CloseClipboard               iffparse.library/CloseClipboard

   NAME
    CloseClipboard -- Close and free an open ClipboardHandle.

   SYNOPSIS
    CloseClipboard (clip)
                     a0

    struct ClipboardHandle *clip;

   FUNCTION
    Closes the clipboard.device and frees the ClipboardHandle structure.

   INPUTS
    clip	- pointer to ClipboardHandle struct created with
          OpenClipboard.

   RESULT

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    OpenClipboard(), InitIFFasClip()

 iffparse.library/CloseIFF                           iffparse.library/CloseIFF

   NAME
    CloseIFF -- Close an IFF context.

   SYNOPSIS
    CloseIFF (iff)
              a0

    struct IFFHandle *iff;

   FUNCTION
    Completes an IFF read or write operation by closing the IFF context
    established for this IFFHandle struct.  The IFFHandle struct itself
    is left ready for re-use and a new context can be opened with
    OpenIFF().  This function can be used for cleanup if a read or write
    fails partway through.

    As part of its cleanup operation, CloseIFF() calls the client-
    supplied stream hook vector.  The IFFStreamCmd packet will be set
    as follows:

        sc_Command:	IFFCMD_CLEANUP
        sc_Buf:		(Not applicable)
        sc_NBytes:	(Not applicable)

    This operation is NOT permitted to fail;  any error code returned
    will be ignored (best to return 0, though).  DO NOT write to this
    structure.

   INPUTS
    iff	- pointer to IFFHandle struct previously opened with
          OpenIFF().

   RESULT

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    OpenIFF(), InitIFF()

 iffparse.library/CollectionChunk             iffparse.library/CollectionChunk

   NAME
    CollectionChunk -- declare a chunk type for collection.

   SYNOPSIS
    error = CollectionChunk (iff, type, id)
     d0                      a0    d0   d1

    LONG		 error;
    struct IFFHandle *iff;
    LONG		 type;
    LONG		 id;

   FUNCTION
    Installs an entry handler for chunks with the given type and id so
    that the contents of those chunks will be stored as they are
    encountered.  This is like PropChunk() except that more than one
    chunk of this type can be stored in lists which can be returned by
    FindCollection().  The storage of these chunks still follows the
    property chunk scoping rules for IFF files so that at any given
    point, stored collection chunks will be valid in the current context.

   INPUTS
    iff	- pointer to IFFHandle struct (does not need to be open).
    type	- type code for the chunk to declare (ex. "ILBM").
    id	- identifier for the chunk to declare (ex. "CRNG").

   RESULT
    error	- 0 if successful or an IFFERR_#? error code if not
          successful.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    CollectionChunks(), FindCollection(), PropChunk()

 iffparse.library/CollectionChunks           iffparse.library/CollectionChunks

   NAME
    CollectionChunks -- Declare many collection chunks at once.

   SYNOPSIS
    error = CollectionChunks (iff, list, n)
     d0                       a0    a1  d0

    LONG		 error;
    struct IFFHandle *iff;
    LONG		 *list;
    LONG		 n;

   FUNCTION
    Declares multiple collection chunks from a list.  The list argument
    is a pointer to an array of long words arranged in pairs.  The format
    for the list is as follows:

        TYPE1, ID1, TYPE2, ID2, ..., TYPEn, IDn

    The argument n is the number of pairs.  CollectionChunks() just calls
    CollectionChunk() n times.

   INPUTS
    iff	- pointer to IFFHandle struct.
    list	- pointer to array of longword chunk types and identifiers.
    n	- number of chunks to declare.

   RESULT
    error	- 0 if successful or an IFFERR_#? error code if not
          successful.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    CollectionChunk()

 iffparse.library/CurrentChunk                   iffparse.library/CurrentChunk

   NAME
    CurrentChunk -- Get context node for current chunk.

   SYNOPSIS
    top = CurrentChunk (iff)
    d0                  a0

    struct ContextNode	*top;
    struct IFFHandle	*iff;

   FUNCTION
    Returns top context node for the given IFFHandle struct.  The top
    context node corresponds to the chunk most recently pushed on the
    stack, which is the chunk where the stream is currently positioned.
    The ContextNode structure contains information on the type of chunk
    currently being parsed (or written), its size and the current
    position within the chunk.

   INPUTS
    iff	- pointer to IFFHandle struct.

   RESULT
    top	- pointer to top context node or NULL if none.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    PushChunk(), PopChunk(), ParseIFF(), ParentChunk()

 iffparse.library/EntryHandler                   iffparse.library/EntryHandler

   NAME
    EntryHandler -- Add an entry handler to the IFFHandle context.

   SYNOPSIS
    error = EntryHandler (iff, type, id, position, hook, object)
     d0                   a0    d0   d1    d2       a1     a2

    LONG		 error;
    struct IFFHandle *iff;
    LONG		 type, id, position;
    struct Hook	 *hook;
    APTR		 object;

   FUNCTION
    Installs an entry handler vector for a specific type of chunk into
    the context for the given IFFHandle struct.  Type and id are the
    longword identifiers for the chunk to handle.  The hook is a client-
    supplied standard 2.0 Hook structure, properly initialized.  Position
    tells where to put the handler in the context.  The handler will be
    called whenever the parser enters a chunk of the given type, so the
    IFF stream will be positioned to read the first data byte in the
    chunk.  The handler will execute in the same context as whoever
    called ParseIFF().  The handler will be called (through the hook)
    with the following arguments:

        A0:	the Hook pointer you passed.
        A2:	the 'object' pointer you passed.
        A1:	pointer to a LONG containing the value
            IFFCMD_ENTRY.

    The error code your call-back routine returns will affect the parser
    in three different ways:

    Return value		Result
    ------------		------
    0:			Normal success;  ParseIFF() will continue
                through the file.
    IFF_RETURN2CLIENT:	ParseIFF() will stop and return the value 0.
                (StopChunk() is internally implemented using
                this return value.)
    Any other value:	ParseIFF() will stop and return the value
                you supplied.  This is how errors should be
                returned.

   INPUTS
    iff	- pointer to IFFHandle struct.
    type	- type code for chunk to handle (ex. "ILBM").
    id	- ID code for chunk to handle (ex. "CMAP").
    position- Local context item position.  One of the IFFSLI_#? codes.
    hook	- pointer to Hook structure.
    object	- a client-defined pointer which is passed in A2 during call-
          back.

   RESULT
    error	- 0 if successful or an IFFERR_#? error code if not
          successful.

   EXAMPLE

   NOTES

   BUGS
    Returning the values IFFERR_EOF or IFFERR_EOC from the call-back
    routine *may* confuse the parser.

    There is no way to explicitly remove a handler once installed.
    However, by installing a do-nothing handler using IFFSLI_TOP,
    previous handlers will be overridden until the context expires.

   SEE ALSO
    ExitHandler(), StoreLocalItem(), StoreItemInContext(),
    utility/hooks.h

 iffparse.library/ExitHandler                     iffparse.library/ExitHandler

   NAME
    ExitHandler -- Add an exit handler to the IFFHandle context.

   SYNOPSIS
    error = ExitHandler (iff, type, id, position, hook, object)
     d0                  a0    d0   d1    d2       a1     a2

    LONG		 error;
    struct IFFHandle *iff;
    LONG		 type, id, position;
    struct Hook	 *hook;
    APTR		 object;

   FUNCTION
    Installs an exit handler vector for a specific type of chunk into the
    context for the given IFFHandle struct.  Type and id are the longword
    identifiers for the chunk to handle.  The hook is a client-supplied
    standard 2.0 Hook structure, properly initialized.  Position tells
    where to put the handler in the context.  The handler will be called
    just before the parser exits the given chunk in the "pause" parse
    state.  The IFF stream may not be positioned predictably within the
    chunk.  The handler will execute in the same context as whoever
    called ParseIFF().  The handler will be called (through the hook)
    with the following arguments:

        A0:	the Hook pointer you passed.
        A2:	the 'object' pointer you passed.
        A1:	pointer to a LONG containing the value
            IFFCMD_EXIT.

    The error code your call-back routine returns will affect the parser
    in three different ways:

    Return value		Result
    ------------		------
    0:			Normal success;  ParseIFF() will continue
                through the file.
    IFF_RETURN2CLIENT:	ParseIFF() will stop and return the value 0.
                (StopChunk() is internally implemented using
                this return value.)
    Any other value:	ParseIFF() will stop and return the value
                you supplied.  This is how errors should be
                returned.

   INPUTS
    iff	- pointer to IFFHandle struct.
    type	- type code for chunk to handle (ex. "ILBM").
    id	- identifier code for chunk to handle (ex. "CMAP").
    position- local context item position.  One of the IFFSLI_#? codes.
    hook	- pointer to Hook structure.
    object	- a client-defined pointer which is passed in A2 during call-
          back.

   RESULT
    error	- 0 if successful or an IFFERR_#? error code if not
          successful.

   EXAMPLE

   NOTES

   BUGS
    Returning the values IFFERR_EOF or IFFERR_EOC from the call-back
    routine *may* confuse the parser.

    There is no way to explicitly remove a handler once installed.
    However, by installing a do-nothing handler using IFFSLI_TOP,
    previous handlers will be overridden until the context expires.

   SEE ALSO
    EntryHandler(), StoreLocalItem(), StoreItemInContext(),
    utility/hooks.h

 iffparse.library/FindCollection               iffparse.library/FindCollection

   NAME
    FindCollection -- Get a pointer to the current list of collection
              items.

   SYNOPSIS
    ci = FindCollection (iff, type, id)
    d0                   a0    d0   d1

    struct CollectionItem	*ci;
    struct IFFHandle	*iff;
    LONG			type, id;

   FUNCTION
    Returns a pointer to a list of CollectionItem structures for each of
    the collection chunks of the given type encountered so far in the
    course of parsing this IFF file.  The items appearing first in the
    list will be the ones encountered most recently.

   INPUTS
    iff	- pointer to IFFHandle struct.
    type	- type code to search for.
    id	- identifier code to search for.

   RESULT
    ci	- pointer to last collection chunk encountered with
          links to previous ones.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    CollectionChunk(), CollectionChunks()

 iffparse.library/FindLocalItem                 iffparse.library/FindLocalItem

   NAME
    FindLocalItem -- Return a local context item from the context stack.

   SYNOPSIS
    lci = FindLocalItem (iff, type, id, ident)
    d0                   a0    d0   d1   d2

    struct LocalContextItem	*lci;
    struct IFFHandle	*iff;
    LONG			type, id, ident;

   FUNCTION
    Searches the context stack of the given IFFHandle struct for a local
    context item which matches the given ident, type and id.  This
    function searches the context stack from the most current context
    backwards, so that the item found (if any) will be the one with
    greatest precedence in the context stack.

   INPUTS
    iff	- pointer to IFFHandle struct.
    type	- type code to search for.
    id	- ID code to search for.
    ident	- ident code for the class of context item to search for
          (ex. "exhd" -- exit handler).

   RESULT
    lci	- pointer local context item if found, or NULL if nothing
          matched.

   EXAMPLE

   NOTES

   BUGS
    It really should have some sort of wildcarding capability.

   SEE ALSO
    StoreLocalItem()

 iffparse.library/FindProp                           iffparse.library/FindProp

   NAME
    FindProp -- Search for a stored property chunk.

   SYNOPSIS
    sp = FindProp (iff, type, id)
    d0             a0    d0   d1

    struct StoredProperty	*sp;
    struct IFFHandle	*iff;
    LONG			type, id;

   FUNCTION
    Searches for the stored property which is valid in the given context.
    Property chunks are automatically stored by ParseIFF() when
    pre-declared by PropChunk() or PropChunks().  The StoredProperty
    struct, if found, contains a pointer to a data buffer containing the
    contents of the stored property.

   INPUTS
    iff	- pointer to IFFHandle struct.
    type	- type code for chunk to search for (ex. "ILBM").
    id	- identifier code for chunk to search for (ex. "CMAP").

   RESULT
    sp	- pointer to stored property, if found, or NULL if none
          found.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    PropChunk(), PropChunks()

 iffparse.library/FindPropContext             iffparse.library/FindPropContext

   NAME
    FindPropContext -- Get the property context for the current state.

   SYNOPSIS
    cn = FindPropContext (iff)
    d0                    a0

    struct ContextNode	*cn;
    struct IFFHandle	*iff;

   FUNCTION
    Locates the context node which would be the scoping chunk for
    properties in the current parsing state.  (Huh?)  This is used for
    locating the proper scoping context for property chunks i.e. the
    scope from which a property would apply.  This is usually the FORM
    or LIST with the highest precedence in the context stack.

    If you don't understand this, read the IFF spec a couple more times.

   INPUTS
    iff	- pointer to IFFHandle struct.

   RESULT
    cn	- ContextNode of property scoping chunk.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    CurrentChunk(), ParentChunk(), StoreItemInContext()

 iffparse.library/FreeIFF                             iffparse.library/FreeIFF

   NAME
    FreeIFF -- Deallocate an IFFHandle struct.

   SYNOPSIS
    FreeIFF (iff)
             a0

    struct IFFHandle *iff;

   FUNCTION
    Deallocates all resources associated with this IFFHandle struct.  The
    struct MUST have already been closed with CloseIFF().

   INPUTS
    iff	- pointer to IFFHandle struct to free.

   RESULT

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    AllocIFF(), CloseIFF()

 iffparse.library/FreeLocalItem                 iffparse.library/FreeLocalItem

   NAME
    FreeLocalItem -- Deallocate a local context item structure.

   SYNOPSIS
    FreeLocalItem (lci)
                   a0

    struct LocalContextItem *lci;

   FUNCTION
    Frees the memory for the local context item and any associated user
    memory as allocated with AllocLocalItem.  User purge vectors should
    call this function after they have freed any other resources
    associated with this item.

    Note that FreeLocalItem() does NOT call the custom purge vector set
    up through SetLocalItemPurge(); all it does is free the local context
    item.  (This implies that your custom purge vector would want to call
    this to ultimately free the LocalContextItem.)  (This description
    still seems muddy; how to clear it up?)

   INPUTS
    lci	- pointer to LocalContextItem created with AllocLocalItem.

   RESULT

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    AllocLocalItem()

 iffparse.library/GoodID                               iffparse.library/GoodID

   NAME
    GoodID -- Test if an identifier follows the IFF 85 specification.

   SYNOPSIS
    isok = GoodID (id)
     d0            d0

    LONG isok, id;

   FUNCTION
    Tests the given longword identifier to see if it meets all the EA IFF
    85 specifications for a chunk ID.  If so, it returns non-zero,
    otherwise 0.

   INPUTS
    id	- potential 32 bit identifier.

   RESULT
    isok	- non-zero if this is a valid ID, 0 otherwise.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    GoodType()

 iffparse.library/GoodType                           iffparse.library/GoodType

   NAME
    GoodType -- Test if a type follows the IFF 85 specification.

   SYNOPSIS
    isok = GoodType (type)
     d0               d0

    LONG isok, type;

   FUNCTION
    Tests the given longword type identifier to see if it meets all the
    EA IFF 85 specifications for a FORM type (requirements for a FORM
    type are more stringent than those for a simple chunk ID).  If it
    complies, GoodType() returns non-zero, otherwise 0.

   INPUTS
    type	- potential 32 bit format type identifier.

   RESULT
    isok	- non-zero if this is a valid type id, 0 otherwise.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    GoodID()

 iffparse.library/IDtoStr                             iffparse.library/IDtoStr

   NAME
    IDtoStr -- Convert a longword identifier to a null-terminated string.

   SYNOPSIS
    str = IDtoStr (id, buf)
    d0             d0  a0

    STRPTR	str;
    LONG	id;
    STRPTR	buf;

   FUNCTION
    Writes the ASCII equivalent of the given longword ID into buf as a
    null-terminated string.

   INPUTS
    id	- longword ID.
    buf	- character buffer to accept string (at least 5 chars).

   RESULT
    str	- the value of 'buf'.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO

 iffparse.library/InitIFF                             iffparse.library/InitIFF

   NAME
    InitIFF -- Initialize an IFFHandle struct as a user stream.

   SYNOPSIS
    InitIFF (iff, flags, streamhook)
             a0    d0        a1

    struct IFFHandle *iff;
    LONG		 flags;
    struct Hook	 *streamhook;

   FUNCTION
    Initializes an IFFHandle as a general user-defined stream by
    allowing the user to declare a hook that the library will call to
    accomplish the low-level reading, writing, and seeking of the stream.
    Flags are the stream I/O flags for the specified stream; typically a
    combination of the IFFF_?SEEK flags.

    The stream vector is called with the following arguments:

        A0:	pointer to streamhook.
        A2:	pointer to IFFHandle struct.
        A1:	pointer to IFFStreamCmd struct.

    The IFFStreamCmd packet appears as follows:

        sc_Command:	Contains an IFFCMD_#? value
        sc_Buf:		Pointer to memory buffer
        sc_NBytes:	Number of bytes involved in operation

    The values taken on by sc_Command, and their meaning, are as follows:

    IFFCMD_INIT:
        Prepare your stream for reading.  This is used for certain
        streams that can't be read immediately upon opening, and need
        further preparation.  (The clipboard.device is an example of
        such a stream.)  This operation is allowed to fail;  any
        error code will be returned directly to the client.  sc_Buf
        and sc_NBytes have no meaning here.
    IFFCMD_CLEANUP:
        Terminate the transaction with the associated stream.  This
        is used with streams that can't simply be closed.  (Again,
        the clipboard is an example of such a stream.)  This
        operation is not permitted to fail;  any error returned will
        be ignored (best to return 0, though).  sc_Buf and sc_NBytes
        have no meaning here.
    IFFCMD_READ:
        Read from the stream.  You are to read sc_NBytes from the
        stream and place them in the buffer pointed to by sc_Buf.
        Any (non-zero) error returned will be remapped by the parser
        into IFFERR_READ.
    IFFCMD_WRITE:
        Write to the stream.  You are to write sc_NBytes to the
        stream from the buffer pointed to by sc_Buf.  Any (non-zero)
        error returned will be remapped by the parser into
        IFFERR_WRITE.
    IFFCMD_SEEK:
        Seek on the stream.  You are to perform a seek on the stream
        relative to the current position.  sc_NBytes is signed;
        negative values mean seek backward, positive values mean seek
        forward.  sc_Buf has no meaning here.  Any (non-zero) error
        returned will be remapped by the parser into IFFERR_SEEK.

    All errors are returned in D0.  A return of 0 indicates success.
    UNDER NO CIRCUMSTANCES are you permitted to write to the IFFStreamCmd
    structure.

   INPUTS
    iff	- pointer to IFFHandle structure to initialize.
    flags	- stream I/O flags for the IFFHandle.
    hook	- pointer to Hook structure.

   RESULT

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    utility/hooks.h

 iffparse.library/InitIFFasClip                 iffparse.library/InitIFFasClip

   NAME
    InitIFFasClip -- Initialize an IFFHandle as a clipboard stream.

   SYNOPSIS
    InitIFFasClip (iff)
                   a0

    struct IFFHandle *iff;

   FUNCTION
    Initializes the given IFFHandle to be a clipboard stream.  The
    function initializes the stream processing vectors to operate on
    streams of the ClipboardHandle type.  The iff_Stream field will still
    need to be initialized to point to a ClipboardHandle as returned from
    OpenClipboard().

   INPUTS
    iff	- pointer to IFFHandle struct.

   RESULT

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    OpenClipboard()

 iffparse.library/InitIFFasDOS                   iffparse.library/InitIFFasDOS

   NAME
    InitIFFasDOS -- Initialize an IFFHandle as a DOS stream.

   SYNOPSIS
    InitIFFasDOS (iff)
                  a0

    struct IFFHandle *iff;

   FUNCTION
    The function initializes the given IFFHandle to operate on DOS
    streams.  The iff_Stream field will need to be initialized as a BPTR
    returned from the DOS function Open().

   INPUTS
    iff	- pointer to IFFHandle struct.

   RESULT

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO

 iffparse.library/LocalItemData                 iffparse.library/LocalItemData

   NAME
    LocalItemData -- Get pointer to user data for local context item.

   SYNOPSIS
    data = LocalItemData (lci)
     d0                   a0

    UBYTE			*data;
    struct LocalContextItem	*lci;

   FUNCTION
    Returns pointer to the user data associated with the given local
    context item.  The size of the data area depends on the "usize"
    argument used when allocating this item.  If the pointer to the item
    given (lci) is NULL, the function also returns NULL.

   INPUTS
    lci	- pointer to local context item or NULL.

   RESULT
    data	- pointer to user data area or NULL if lci is NULL.

   EXAMPLE

   NOTES

   BUGS
    Currently, there is no way to determine the size of the user data
    area; you have to 'know'.

   SEE ALSO
    AllocLocalItem(), FreeLocalItem()

 iffparse.library/OpenClipboard                 iffparse.library/OpenClipboard

   NAME
    OpenClipboard -- Create a handle on a clipboard unit.

   SYNOPSIS
    ch = OpenClipboard (unit)
    d0                   d0

    struct ClipboardHandle	*ch;
    LONG			unit;

   FUNCTION
    Opens the clipboard.device and opens a stream for the specified unit
    (usually PRIMARY_CLIP).  This handle structure will be used as the
    clipboard stream for IFFHandles initialized as clipboard streams by
    InitIFFasClip().

   INPUTS
    unit	- clipboard unit number (usually PRIMARY_CLIP).

   RESULT
    ch	- pointer to ClipboardHandle structure or NULL if
          unsuccessful.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    InitIFFasClip(), CloseClipboard()

 iffparse.library/OpenIFF                             iffparse.library/OpenIFF

   NAME
    OpenIFF -- Prepare an IFFHandle to read or write a new IFF stream.

   SYNOPSIS
    error = OpenIFF (iff, rwmode)
     d0              a0     d0

    LONG		 error;
    struct IFFHandle *iff;
    LONG		 rwmode;

   FUNCTION
    Initializes an IFFHandle struct for a new read or write.  The
    direction of the I/O is given by the value of rwmode, which can be
    either IFFF_READ or IFFF_WRITE.

    As part of its initialization procedure, OpenIFF() calls the client-
    supplied stream hook vector.  The IFFStreamCmd packet will contain
    the following:

        sc_Command:	IFFCMD_INIT
        sc_Buf:		(Not applicable)
        sc_NBytes:	(Not applicable)

    This operation is permitted to fail.  DO NOT write to this structure.

   INPUTS
    iff	- pointer to IFFHandle struct.
    rwmode	- IFFF_READ or IFFF_WRITE

   RESULT
    error	- contains an error code or 0 if successful.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    CloseIFF(), InitIFF()

 iffparse.library/ParentChunk                     iffparse.library/ParentChunk

   NAME
    ParentChunk -- Get the nesting context node for the given chunk.

   SYNOPSIS
    parent = ParentChunk (cn)
      d0                  a0

    struct ContextNode *parent, *cn;

   FUNCTION
    Returns a context node for the chunk containing the chunk for the
    given context node.  This function effectively moves down the context
    stack into previously pushed contexts.  For example, to get a
    ContextNode pointer for the enclosing FORM chunk while reading a data
    chunk, use: ParentChunk (CurrentChunk (iff)) to find this pointer.
    The ContextNode structure contains information on the type of chunk
    and its size.

   INPUTS
    cn	- pointer to a context node.

   RESULT
    parent	- pointer to the enclosing context node or NULL if none.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    CurrentChunk()

 iffparse.library/ParseIFF                           iffparse.library/ParseIFF

   NAME
    ParseIFF -- Parse an IFF file from an IFFHandle struct stream.

   SYNOPSIS
    error = ParseIFF (iff, control)
     d0               a0     d0

    LONG		 error;
    struct IFFHandle *iff;
    LONG		 control;

   FUNCTION
    This is the biggie.

    Traverses a file opened for read by pushing chunks onto the context
    stack and popping them off directed by the generic syntax of IFF
    files.  As it pushes each new chunk, it searches the context stack
    for handlers to apply to chunks of that type.  If it finds an entry
    handler it will invoke it just after entering the chunk.  If it finds
    an exit handler it will invoke it just before leaving the chunk.
    Standard handlers include entry handlers for pre-declared
    property chunks and collection chunks and entry and exit handlers for
    for stop chunks - that is, chunks which will cause the ParseIFF()
    function to return control to the client.  Client programs can also
    provide their own custom handlers.

    The control flag can have three values:

    IFFPARSE_SCAN:
        In this normal mode, ParseIFF() will only return control to
        the caller when either:
            1) an error is encountered,
            2) a stop chunk is encountered, or a user handler
               returns the special IFF_RETURN2CLIENT code, or
            3) the end of the logical file is reached, in which
               case IFFERR_EOF is returned.

        ParseIFF() will continue pushing and popping chunks until one
        of these conditions occurs.  If ParseIFF() is called again
        after returning, it will continue to parse the file where it
        left off.

    IFFPARSE_STEP and _RAWSTEP:
        In these two modes, ParseIFF() will return control to the
        caller after every step in the parse, specifically, after
        each push of a context node and just before each pop.  If
        returning just before a pop, ParseIFF() will return
        IFFERR_EOC, which is not an error, per se, but is just an
        indication that the most recent context is ending.  In STEP
        mode, ParseIFF() will invoke the handlers for chunks, if
        any, before returning.  In RAWSTEP mode, ParseIFF() will not
        invoke any handlers and will return right away.  In both
        cases the function can be called multiple times to step
        through the parsing of the IFF file.

   INPUTS
    iff	- pointer to IFFHandle struct.
    control	- control code (IFFPARSE_SCAN, _STEP or _RAWSTEP).

   RESULT
    error	- 0 or IFFERR_#? value or return value from user handler.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    PushChunk(), PopChunk(), EntryHandler(), ExitHandler(),
    PropChunk[s](), CollectionChunk[s](), StopChunk(), StopOnExit()

 iffparse.library/PopChunk                           iffparse.library/PopChunk

   NAME
    PopChunk -- Pop top context node off context stack.

   SYNOPSIS
    error = PopChunk (iff)
     d0               a0

    LONG		 error;
    struct IFFHandle *iff;

   FUNCTION
    Pops top context chunk and frees all associated local context items.
    The function is normally called only for writing files and signals
    the end of a chunk.

   INPUTS
    iff	- pointer to IFFHandle struct.

   RESULT
    error	- 0 if successful or an IFFERR_#? error code if not
          successful.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    PushChunk()

 iffparse.library/PropChunk                         iffparse.library/PropChunk

   NAME
    PropChunk -- Specify a property chunk to store.

   SYNOPSIS
    error = PropChunk (iff, type, id)
     d0                a0    d0   d1

    LONG		 error;
    struct IFFHandle *iff;
    LONG		 type;
    LONG		 id;

   FUNCTION
    Installs an entry handler for chunks with the given type and ID so
    that the contents of those chunks will be stored as they are
    encountered.  The storage of these chunks follows the property chunk
    scoping rules for IFF files so that at any given point, a stored
    property chunk returned by FindProp() will be the valid property for
    the current context.

   INPUTS
    iff	- pointer to IFFHandle struct (does not need to be open).
    type	- type code for the chunk to declare (ex. "ILBM").
    id	- identifier for the chunk to declare (ex. "CMAP").

   RESULT
    error	- 0 if successful or an IFFERR_#? error code if not
          successful.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    PropChunks(), FindProp(), CollectionChunk()

 iffparse.library/PropChunks                       iffparse.library/PropChunks

   NAME
    PropChunks -- Declare many property chunks at once.

   SYNOPSIS
    error = PropChunks (iff, list, n)
     d0                 a0    a1  d0

    LONG		 error;
    struct IFFHandle *iff;
    LONG		 *list;
    LONG		 n;

   FUNCTION
    Declares multiple property chunks from a list.  The list argument is
    a pointer to an array of long words arranged in pairs, and has the
    following format:

        TYPE1, ID1, TYPE2, ID2, ..., TYPEn, IDn

    The argument n is the number of pairs.  PropChunks() just calls
    PropChunk() n times.

   INPUTS
    iff	- pointer to IFFHandle struct.
    list	- pointer to array of longword chunk types and identifiers.
    n	- number of chunks to declare.

   RESULT
    error	- 0 if successful or an IFFERR_#? error code if not
          successful.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    PropChunk()

 iffparse.library/PushChunk                         iffparse.library/PushChunk

   NAME
    PushChunk -- Push a new context node on the context stack.

   SYNOPSIS
    error = PushChunk (iff, type, id, size)
     d0                a0    d0   d1   d2

    LONG		 error;
    struct IFFHandle *iff;
    LONG		 type, id, size;

   FUNCTION
    Pushes a new context node on the context stack by reading it from the
    stream if this is a read file, or by creating it from the passed
    parameters if this is a write file.  Normally this function is only
    called in write mode, where the type and id codes specify the new
    chunk to create.  If this is a leaf chunk, i.e. a local chunk inside
    a FORM or PROP chunk, then the type argument is ignored.  If the size
    is specified then the chunk writing functions will enforce this size.
    If the size is given as IFFSIZE_UNKNOWN, the chunk will expand to
    accommodate whatever is written into it.

   INPUTS
    iff	- pointer to IFFHandle struct.
    type	- chunk type specifier (ex. ILBM) (ignored for read mode or
          leaf chunks).
    id	- chunk id specifier (ex. CMAP) (ignored for read mode).
    size	- size of the chunk to create or IFFSIZE_UNKNOWN (ignored for
          read mode).

   RESULT
    error	- 0 if successful or an IFFERR_#? error code if not
          successful.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    PopChunk(), WriteChunkRecords(), WriteChunkBytes()

 iffparse.library/ReadChunkBytes               iffparse.library/ReadChunkBytes

   NAME
    ReadChunkBytes -- Read bytes from the current chunk into a buffer.

   SYNOPSIS
    actual = ReadChunkBytes (iff, buf, size)
      d0                     a0   a1    d0

    LONG		 actual;
    struct IFFHandle *iff;
    UBYTE		 *buf;
    LONG		 size;

   FUNCTION
    Reads the IFFHandle stream into the buffer for the specified number
    of bytes.  Reads are limited to the size of the current chunk and
    attempts to read past the end of the chunk will truncate.  Function
    returns positive number of bytes read or a negative error code.

   INPUTS
    iff	- pointer to IFFHandle struct.
    buf	- pointer to buffer area to receive data.
    size	- number of bytes to read.

   RESULT
    actual	- (positive) number of bytes read if successful or a
          (negative) IFFERR_#? error code if not successful.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    ReadChunkRecords(), ParseIFF(), WriteChunkBytes()

 iffparse.library/ReadChunkRecords           iffparse.library/ReadChunkRecords

   NAME
    ReadChunkRecords -- Read record elements from the current chunk into
                a buffer.

   SYNOPSIS
    actual = ReadChunkRecords (iff, buf, recsize, numrec)
      d0                       a0   a1     d0       d1

    LONG		 actual;
    struct IFFHandle *iff;
    UBYTE		 *buf;
    LONG		 recsize, numrec;

   FUNCTION
    Reads records from the current chunk into buffer.  Truncates attempts
    to read past end of chunk (only whole records are read; remaining
    bytes that are not of a whole record size are left unread and
    available for ReadChunkBytes()).

   INPUTS
    iff	- pointer to IFFHandle struct.
    buf	- pointer to buffer area to receive data.
    recsize	- size of data records to read.
    numrec	- number of data records to read.

   RESULT
    actual	- (positive) number of whole records read if successful or a
          (negative) IFFERR_#? error code if not successful.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    ReadChunkBytes(), ParseIFF(), WriteChunkRecords()

 iffparse.library/SetLocalItemPurge         iffparse.library/SetLocalItemPurge

   NAME
    SetLocalItemPurge -- Set purge vector for a local context item.

   SYNOPSIS
    SetLocalItemPurge (item, purgehook)
                        a0      a1

    struct LocalContextItem	*item;
    struct Hook		*purgehook;

   FUNCTION
    Sets a local context item to use a client-supplied cleanup (purge)
    vector for disposal when its context is popped.  The purge vector
    will be called when the ContextNode containing this local item is
    popped off the context stack and is about to be deleted itself.  If
    the purge vector has not been set, the parser will use FreeLocalItem
    to delete the item, but if this function is used to set the purge
    vector, the supplied vector will be called with the following
    arguments:

        A0:	pointer to purgehook.
        A2:	pointer to LocalContextItem to be freed.
        A1:	pointer to a LONG containing the value
            IFFCMD_PURGELCI.

    The user purge vector is then responsible for calling FreeLocalItem()
    as part of its own cleanup.  Although the purge vector can return a
    value, it will be ignored -- purge vectors must always work (best to
    return 0, though).

   INPUTS
    item	  - pointer to local context item.
    purgehook - pointer to a Hook structure.

   RESULT

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    AllocLocalItem(), FreeLocalItem(), utility/hooks.h

 iffparse.library/StopChunk                         iffparse.library/StopChunk

   NAME
    StopChunk -- Declare a chunk which should cause ParseIFF to return.

   SYNOPSIS
    error = StopChunk (iff, type, id)
     d0                a0    d0   d1

    LONG		 error;
    struct IFFHandle *iff;
    LONG		 type;
    LONG		 id;

   FUNCTION
    Installs an entry handler for the specified chunk which will cause
    the ParseIFF() function to return control to the caller when this
    chunk is encountered.  This is only of value when ParseIFF() is
    called with the IFFPARSE_SCAN control code.

   INPUTS
    iff	- pointer to IFFHandle struct (need not be open).
    type	- type code for chunk to declare (ex. "ILBM").
    id	- identifier for chunk to declare (ex. "BODY").

   RESULT
    error	- 0 if successful or an IFFERR_#? error code if not
          successful.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    StopChunks(), ParseIFF()

 iffparse.library/StopChunks                       iffparse.library/StopChunks

   NAME
    StopChunks -- Declare many stop chunks at once.

   SYNOPSIS
    error = StopChunks (iff, list, n)
     d0                 a0    a1  d0

    LONG		 error;
    struct IFFHandle *iff;
    LONG		 *list;
    LONG		 n;

   FUNCTION
    (is to StopChunk() as PropChunks() is to PropChunk().)

   INPUTS
    iff	- pointer to IFFHandle struct.
    list	- pointer to array of longword chunk types and identifiers.
    n	- number of chunks to declare.

   RESULT
    error	- 0 if successful or an IFFERR_#? error code if not
          successful.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    StopChunk()

 iffparse.library/StopOnExit                       iffparse.library/StopOnExit

   NAME
    StopOnExit -- Declare a stop condition for exiting a chunk.

   SYNOPSIS
    error = StopOnExit (iff, type, id)
     d0                 a0    d0   d1

    LONG		 error;
    struct IFFHandle *iff;
    LONG		 type;
    LONG		 id;

   FUNCTION
    Installs an exit handler for the specified chunk which will cause the
    ParseIFF() function to return control to the caller when this chunk
    is exhausted.  ParseIFF() will return IFFERR_EOC when the declared
    chunk is about to be popped.  This is only of value when ParseIFF()
    is called with the IFFPARSE_SCAN control code.

   INPUTS
    iff	- pointer to IFFHandle struct (need not be open).
    type	- type code for chunk to declare (ex. "ILBM").
    id	- identifier for chunk to declare (ex. "BODY").

   RESULT
    error	- 0 if successful or an IFFERR_#? error code if not
          successful.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    ParseIFF()

 iffparse.library/StoreItemInContext       iffparse.library/StoreItemInContext

   NAME
    StoreItemInContext -- Store local context item in given context node.

   SYNOPSIS
    StoreItemInContext (iff, item, cn)
                        a0    a1   a2

    struct IFFHandle	*iff;
    struct LocalContextItem	*item;
    struct ContextNode	*cn;

   FUNCTION
    Adds the LocalContextItem to the list of items for the given context
    node.  If an LCI with the same Type, ID, and Ident is already
    present in the ContextNode, it will be purged and replaced with the
    new one.  This is a raw form of StoreLocalItem.

   INPUTS
    iff	- pointer to IFFHandle struct for this context.
    item	- pointer to a LocalContextItem to be stored.
    cn	- pointer to context node in which to store item.

   RESULT

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    StoreLocalItem()

 iffparse.library/StoreLocalItem               iffparse.library/StoreLocalItem

   NAME
    StoreLocalItem -- Insert a local context item into the context stack.

   SYNOPSIS
    error = StoreLocalItem (iff, item, position)
     d0                     a0    a1      d0

    LONG			error;
    struct IFFHandle	*iff;
    struct LocalContextItem	*item;
    LONG			position;

   FUNCTION
    Adds the local context item to the list of items for one of the
    context nodes on the context stack and purges any other item in the
    same context with the same ident, type and id.  The position argument
    determines where in the stack to add the item:

    IFFSLI_ROOT:
        Add item to list at root (default) stack position.
    IFFSLI_TOP:
        Add item to the top (current) context node.
    IFFSLI_PROP:
        Add element in top property context.  Top property context is
        either the top FORM chunk, or the top LIST chunk, whichever
        is closer to the top of the stack.

    Items added to the root context, or added to the top context before
    the IFFHandle has been opened or after it has been closed, are put in
    the default context.  That is, they will be the local items found
    only after all other context nodes have been searched.  Items in the
    default context are also immune to being purged until the IFFHandle
    struct itself is deleted with FreeIFF().  This means that handlers
    installed in the root context will still be there after an IFFHandle
    struct has been opened and closed.  (Note that this implies that
    items stored in a higher context will be deleted when that context
    ends.)

   INPUTS
    iff	- pointer to IFFHandle struct.
    item	- pointer to LocalContextItem struct to insert.
    position- where to store the item (IFFSLI_ROOT, _TOP or _PROP).

   RESULT
    error	- 0 if successful or an IFFERR_#? error code if not
          successful.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    FindLocalItem(), StoreItemInContext(), EntryHandler(), ExitHandler()

 iffparse.library/WriteChunkBytes             iffparse.library/WriteChunkBytes

   NAME
    WriteChunkBytes -- Write data from a buffer into the current chunk.

   SYNOPSIS
    error = WriteChunkBytes (iff, buf, size)
     d0                      a0   a1    d0

    LONG		 error;
    struct IFFHandle *iff;
    UBYTE		 *buf;
    LONG		 size;

   FUNCTION
    Writes "size" bytes from the specified buffer into the current chunk.
    If the current chunk was pushed with IFFSIZE_UNKNOWN, the size of the
    chunk gets increased by the size of the buffer written.  If the size
    was specified for this chunk, attempts to write past the end of the
    chunk will be truncated.

   INPUTS
    iff	- pointer to IFFHandle struct.
    buf	- pointer to buffer area with bytes to be written.
    size	- number of bytes to write.

   RESULT
    error	- (positive) number of bytes written if successful or a
          (negative) IFFERR_#? error code if not successful.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    PushChunk(), PopChunk(), WriteChunkRecords()

 iffparse.library/WriteChunkRecords         iffparse.library/WriteChunkRecords

   NAME
    WriteChunkRecords -- Write records from a buffer to the current
                 chunk.

   SYNOPSIS
    error = WriteChunkRecords (iff, buf, recsize, numrec)
     d0                        a0   a1     d0      d1

    LONG		 error;
    struct IFFHandle *iff;
    UBYTE		 *buf;
    LONG		 recsize, numrec;

   FUNCTION
    Writes record elements from the buffer into the top chunk.  This
    function operates much like ReadChunkBytes().

   INPUTS
    iff	- pointer to IFFHandle struct.
    buf	- pointer to buffer area containing data.
    recsize	- size of data records to write.
    numrec	- number of data records to write.

   RESULT
    error	- (positive) number of whole records written if successful
          or a (negative) IFFERR_#? error code if not successful.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    WriteChunkBytes()


Text_Autodocs/mathieeesingtrans.doc

TABLE OF CONTENTS

mathieeesingtrans.library/IEEESPAcos
mathieeesingtrans.library/IEEESPAsin
mathieeesingtrans.library/IEEESPAtan
mathieeesingtrans.library/IEEESPCos
mathieeesingtrans.library/IEEESPCosh
mathieeesingtrans.library/IEEESPExp
mathieeesingtrans.library/IEEESPFieee
mathieeesingtrans.library/IEEESPLog
mathieeesingtrans.library/IEEESPLog10
mathieeesingtrans.library/IEEESPPow
mathieeesingtrans.library/IEEESPSin
mathieeesingtrans.library/IEEESPSincos
mathieeesingtrans.library/IEEESPSinh
mathieeesingtrans.library/IEEESPSqrt
mathieeesingtrans.library/IEEESPTan
mathieeesingtrans.library/IEEESPTanh
mathieeesingtrans.library/IEEESPTieee
 mathieeesingtrans.library/IEEESPAcos     mathieeesingtrans.library/IEEESPAcos

   NAME
    IEEESPAcos -- compute the arc cosine of a number

   SYNOPSIS
      x   = IEEESPAcos(  y  );
    d0	           d0

    float	x,y;

   FUNCTION
    Compute arc cosine of y in IEEE single precision

   INPUTS
    y - IEEE single precision floating point value

   RESULT
    x - IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEESPCos(), IEEESPAtan(), IEEESPAsin()
 mathieeesingtrans.library/IEEESPAsin     mathieeesingtrans.library/IEEESPAsin

   NAME
    IEEESPAsin -- compute the arcsine of a number

   SYNOPSIS
      x   = IEEESPAsin(  y  );
    d0	           d0

    float	x,y;

   FUNCTION
    Compute the arc sine of y in IEEE single precision

   INPUTS
    y - IEEE single precision floating point value

   RESULT
    x - IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEESPSin(), IEEESPAtan(), IEEESPAcos()
 mathieeesingtrans.library/IEEESPAtan     mathieeesingtrans.library/IEEESPAtan

   NAME
    IEEESPAtan -- compute the arc tangent of number

   SYNOPSIS
      x   = IEEESPAtan(  y  );
    d0		   d0

    single	x,y;

   FUNCTION
    Compute arctangent of y in IEEE single precision

   INPUTS
    y - IEEE single precision floating point value

   RESULT
    x - IEEE single precision floating point value

   BUGS

   SEE ALSO
 mathieeesingtrans.library/IEEESPCos       mathieeesingtrans.library/IEEESPCos

   NAME
    IEEESPCos -- compute the cosine of a floating point number

   SYNOPSIS
      x   = IEEESPCos(  y  );
    d0		   d0

    float	x,y;

   FUNCTION
    Compute cosine of y in IEEE single precision

   INPUTS
    y - IEEE single precision floating point value

   RESULT
    x - IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEESPAcos(), IEEESPSin(), IEEESPTan()
 mathieeesingtrans.library/IEEESPCosh     mathieeesingtrans.library/IEEESPCosh

   NAME
    IEEESPCosh -- compute the hyperbolic cosine of a floating point number

   SYNOPSIS
      x   = IEEESPCosh(  y  );
    d0		   d0

    float	x,y;

   FUNCTION
    Compute hyperbolic cosine of y in IEEE single precision

   INPUTS
    y - IEEE single precision floating point value

   RESULT
    x - IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEESPSinh(), IEEESPTanh()
 mathieeesingtrans.library/IEEESPExp       mathieeesingtrans.library/IEEESPExp

   NAME
    IEEESPExp -- compute the exponential of e

   SYNOPSIS
      x   = IEEESPExp(  y  );
    d0	          d0

    float	x,y;

   FUNCTION
    Compute e^y in IEEE single precision

   INPUTS
    y - IEEE single precision floating point value

   RESULT
    x - IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEESPLog()
 mathieeesingtrans.library/IEEESPFieee   mathieeesingtrans.library/IEEESPFieee

   NAME
    IEEESPFieee -- convert IEEE single to IEEE single

   SYNOPSIS
      x   = IEEESPFieee(  y  );
    d0	              d0

    float	y;
    float  x;

   FUNCTION
    Convert IEEE single precision number to IEEE single precision.
    These are included for completeness although they just
    return the input parameter. A good way to remember how these
    functions work is: They convert to and from the local format
    to Single Precision IEEE. The local format for this library
    happens to also be Single Precision IEEE.

   INPUTS
    y - IEEE single precision floating point value

   RESULT
    x - IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEESPTieee()
 mathieeesingtrans.library/IEEESPLog       mathieeesingtrans.library/IEEESPLog

   NAME
    IEEESPLog -- compute the natural logarithm of a floating point number

   SYNOPSIS
      x   = IEEESPLog(  y  );
    d0	          d0

    float	x,y;

   FUNCTION
    Compute ln(y) in IEEE single precision

   INPUTS
    y - IEEE single precision floating point value

   RESULT
    x - IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEESPExp()
 mathieeesingtrans.library/IEEESPLog10   mathieeesingtrans.library/IEEESPLog10

   NAME
    IEEESPLog10 -- compute logarithm base 10 of a number

   SYNOPSIS
      x   = IEEESPLog10(  y  );
    d0	            d0

    float	x,y;

   FUNCTION
    Compute the logarithm base 10 of y in IEEE single precision

   INPUTS
    y - IEEE single precision floating point value

   RESULT
    x - IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEESPLog()
 mathieeesingtrans.library/IEEESPPow       mathieeesingtrans.library/IEEESPPow

   NAME
    IEEESPPow -- raise a number to another number power

   SYNOPSIS
      z   = IEEESPPow(  x  ,  y  );
    d0	          d1 d0

    float	x,y,z;

   FUNCTION
    Compute y^x in IEEE single precision

   INPUTS
    x - IEEE single precision floating point value
    y - IEEE single precision floating point value

   RESULT
    z - IEEE single precision floating point value

   BUGS

   SEE ALSO
 mathieeesingtrans.library/IEEESPSin       mathieeesingtrans.library/IEEESPSin

   NAME
    IEEESPSin -- compute the sine of a floating point number

   SYNOPSIS
      x   = IEEESPSin(  y  );
    d0		  d0

    float	x,y;

   FUNCTION
    Compute sine of y in IEEE single precision

   INPUTS
    y - IEEE single precision floating point value

   RESULT
    x - IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEESPAsin(), IEEESPTan(), IEEESPCos()
 mathieeesingtrans.library/IEEESPSincos mathieeesingtrans.library/IEEESPSincos

   NAME
    IEEESPSincos -- compute the arc tangent of a floating point number

   SYNOPSIS
      x   = IEEESPSincos( z ,  y  );
    d0		     a0  d0

    float	x,y,*z;

   FUNCTION
    Compute sin and cosine of y in IEEE single precision.
    Store the cosine in *z. Return the sine of y.

   INPUTS
    y - IEEE single precision floating point value
    z - pointer to IEEE single precision floating point number

   RESULT
    x - IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEESPSin(), IEEESPCos()
 mathieeesingtrans.library/IEEESPSinh     mathieeesingtrans.library/IEEESPSinh

   NAME
    IEEESPSinh -- compute the hyperbolic sine of a floating point number

   SYNOPSIS
      x   = IEEESPSinh(  y  );
    d0		   d0

    float	x,y;

   FUNCTION
    Compute hyperbolic sine of y in IEEE single precision

   INPUTS
    y - IEEE single precision floating point value

   RESULT
    x - IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEESPCosh, IEEESPTanh
 mathieeesingtrans.library/IEEESPSqrt     mathieeesingtrans.library/IEEESPSqrt

   NAME
    IEEESPSqrt -- compute the square root of a number

   SYNOPSIS
      x   = IEEESPSqrt(  y  );
     d0 	             d0

    float	x,y;

   FUNCTION
    Compute square root of y in IEEE single precision

   INPUTS
    y - IEEE single precision floating point value

   RESULT
    x - IEEE single precision floating point value

   BUGS

   SEE ALSO
 mathieeesingtrans.library/IEEESPTan       mathieeesingtrans.library/IEEESPTan

   NAME
    IEEESPTan -- compute the tangent of a floating point number

   SYNOPSIS
      x   = IEEESPTan(  y  );
    d0		  d0

    float	x,y;

   FUNCTION
    Compute tangent of y in IEEE single precision

   INPUTS
    y - IEEE single precision floating point value

   RESULT
    x - IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEESPAtan(), IEEESPSin(), IEEESPCos()
 mathieeesingtrans.library/IEEESPTanh     mathieeesingtrans.library/IEEESPTanh

   NAME
    IEEESPTanh -- compute the hyperbolic tangent of a floating point number

   SYNOPSIS
      x   = IEEESPTanh(  y  );
    d0		   d0

    float	x,y;

   FUNCTION
    Compute hyperbolic tangent of y in IEEE single precision

   INPUTS
    y - IEEE single precision floating point value

   RESULT
    x - IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEESPSinh(), IEEESPCosh()
 mathieeesingtrans.library/IEEESPTieee   mathieeesingtrans.library/IEEESPTieee

   NAME
    IEEESPTieee -- convert IEEE single to IEEE single

   SYNOPSIS
      x   = IEEESPTieee(  y  );
     d0	            d0

    float 	y;
    float   x;

   FUNCTION
    Convert IEEE single precision number to IEEE single precision.
    These are included for completeness although they just
    return the input parameter. A good way to remember how these
    functions work is: They convert to and from the local format
    to Single Precision IEEE. The local format for this library
    happens to also be Single Precision IEEE.

   INPUTS
    y - IEEE single precision floating point value

   RESULT
    x - IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEESPFieee()


Text_Autodocs/diskfont.doc

TABLE OF CONTENTS

diskfont.library/AvailFonts
diskfont.library/DisposeFontContents
diskfont.library/NewFontContents
diskfont.library/NewScaledDiskFont
diskfont.library/OpenDiskFont
 diskfont.library/AvailFonts                       diskfont.library/AvailFonts

   NAME
    AvailFonts -- Inquire available memory & disk fonts.

   SYNOPSIS
    error = AvailFonts(buffer, bufBytes, flags);
                       A0      D0        D1

    LONG AvailFonts( struct AvailFontsHeader *buffer, LONG bufBytes,
        ULONG flags );

   FUNCTION
    AvailFonts fills a user supplied buffer with the structure,
    described below, that contains information about all the
    fonts available in memory and/or on disk.  Those fonts
    available on disk need to be loaded into memory and opened
    via OpenDiskFont, those already in memory are accessed via
    OpenFont.  The TextAttr structure required by the open calls
    is part of the information AvailFonts supplies.

    When AvailFonts fails, it returns the number of extra bytes
    it needed to complete the command.  Add this number to your
    current buffer size, allocate a new buffer, and try again.

   INPUTS
    buffer - memory to be filled with struct AvailFontsHeader
        followed by an array of AvailFonts elements, which
        contains entries for the available fonts and their
        names.

    bufBytes - the number of bytes in the buffer
    flags - AFF_MEMORY is set to search memory for fonts to fill
        the structure, AFF_DISK is set to search the disk for
        fonts to fill the structure.  AFF_SCALED is set to
        not filter out memory fonts that are not designed.
        Any combination may be specified.  AFF_TAGGED is set
        to fill the buffer with TAvailFonts elements instead
        of AvailFonts elements.

   RESULTS
    buffer - filled with struct AvailFontsHeader followed by the
        [T]AvailFonts elements, There will be duplicate entries
        for fonts found both in memory and on disk, differing
        only by type.  The existence of a disk font in the
        buffer indicates that it exists as an entry in a font
        contents file -- the underlying font file has not been
        checked for validity, thus an OpenDiskFont of it may
        fail.
    error - if non-zero, this indicates the number of bytes needed
        for AvailFonts in addition to those supplied.  Thus
        structure elements were not returned because of
        insufficient bufBytes.

   EXAMPLE
    int afShortage, afSize;
    struct AvailFontsHeader *afh;

    ...

    afSize = 400;
    do {
        afh = (struct AvailFontsHeader *) AllocMem(afSize, 0);
        if (afh) {
            afShortage = AvailFonts(afh, afSize, AFF_MEMORY|AFF_DISK);
            if (afShortage) {
                FreeMem(afh, afSize);
                afSize += afShortage;
            }
        }
        else {
            fail("AllocMem of AvailFonts buffer afh failed\n");
            break;
        }
    }
        while (afShortage);

    /*
     * if (afh) non-zero here, then:
     * 1. it points to a valid AvailFontsHeader
     * 2. it must have FreeMem(afh, afSize) called for it after use
     */

 diskfont.library/DisposeFontContents     diskfont.library/DisposeFontContents

   NAME
    DisposeFontContents -- Free the result from NewFontContents. (V34)

   SYNOPSIS
    DisposeFontContents(fontContentsHeader)
                A1

    VOID DisposeFontContents( struct FontContentsHeader * );

   FUNCTION
    This function frees the array of FontContents entries
    returned by NewFontContents.

   INPUTS
    fontContentsHeader - a struct FontContentsHeader pointer
        returned by NewFontContents.

   EXCEPTIONS
     This command was first made available as of version 34.

    A fontContentsHeader other than one acquired by a call
    NewFontContents will crash.

   SEE ALSO
    NewFontContents to get structure freed here.

 diskfont.library/NewFontContents             diskfont.library/NewFontContents

   NAME
    NewFontContents -- Create a FontContents image for a font. (V34)

   SYNOPSIS
    fontContentsHeader = NewFontContents(fontsLock,fontName)
       D0                                   A0        A1

    struct FontContentsHeader *NewFontContents( BPTR, char * );

   FUNCTION
    This function creates a new array of FontContents entries
    that describe all the fonts associated with the fontName,
    specifically, all those in the font directory whose name
    is that of the font sans the ".font" suffix.

   INPUTS
    fontsLock - a DOS lock on the FONTS: directory (or other
        directory where the font contents file and associated
        font directory resides).
    fontName - the font name, with the ".font" suffix, which
        is also the name of the font contents file.

   RESULT
    fontContentsHeader - a struct FontContentsHeader pointer.

   EXCEPTIONS
    This command was first made available as of version 34.

    D0 is zero if the fontName is does not have a ".font" suffix,
    if the fontName is too long, if a DOS error occurred, or if
    memory could not be allocated for the fontContentsHeader.

   SEE ALSO
    DisposeFontContents to free the structure acquired here.

 diskfont.library/NewScaledDiskFont         diskfont.library/NewScaledDiskFont

   NAME
    NewScaledDiskFont -- Create a DiskFont scaled from another. (V36)

   SYNOPSIS
    header = NewScaledDiskFont(srcFont, destTextAttr)
    D0                         A0       A1

    struct DiskFontHeader *NewScaledDiskFont( struct TextFont *,
        struct TTextAttr * );

   INPUTS
    srcFont - the font from which the scaled font is to be
        constructed.
    destTextAttr - the desired attributes for the new scaled
        font.  This may be a structure of type TextAttr or
        TTextAttr.

   RESULT
    header - a pointer to a DiskFontHeader structure.  This is not
        being managed by the diskfont.library, however.

   NOTES
    o   This function may use the blitter.
    o   Fonts containing characters that render wholly outside
        the character advance cell are currently not scalable.
    o   The font, and memory allocated for the scaled font can
        can be freed by calling StripFont() on the font,
        and then calling UnLoadSeg() on the segment created
        by this function.

        Both the TextFont structure, and segment pointer are contained
        within the DiskFontHeader struct.  The DiskFontHeader structure
        will also be freed as part of the UnLoadSeg() call.
        StripFont() is a new graphics.library call as of V36.

 diskfont.library/OpenDiskFont                   diskfont.library/OpenDiskFont

   NAME
       OpenDiskFont - load and get a pointer to a disk font.

   SYNOPSIS
       font = OpenDiskFont(textAttr)
       D0                  A0

   FUNCTION
       This function finds the font with the specified textAttr on
       disk, loads it into memory, and returns a pointer to the font
       that can be used in subsequent SetFont and CloseFont calls.
       It is important to match this call with a corresponding
       CloseFont call for effective management of font memory.

       If the font is already in memory, the copy in memory is used.
       The disk copy is not reloaded.

   INPUTS
       textAttr - a TextAttr structure that describes the text font
               attributes desired.

   RESULTS
       D0 is zero if the desired font cannot be found.

   NOTES
       As of V36, OpenDiskFont() will automatically attempt to
       construct a font for you if:

               You have requested a font size which does not exist
               as a designed font, and

               You have not set the DESIGNED bit in the ta_Flags
               field of the TextAttr, or TTextAttr struct.

       Constructed fonts are created by scaling a designed font.
       A designed font is one which typically resides on disk,
       or in ROM (e.g., a font which has been designed by hand
       using a drawing tool).  Designed fonts generally look better
       than fonts constructed by the font scaler, but designed
       fonts also require disk space for each font size.

       Always set the DESIGNED bit if you do not want constructed fonts,
       or use AvailFonts() to find out which font sizes already exist.

   BUGS
       This routine will not work well with font names whose file
       name components are longer than the maximum allowed
       (30 characters).


Text_Autodocs/intuition.doc

TABLE OF CONTENTS

intuition.library/ActivateGadget
intuition.library/ActivateWindow
intuition.library/AddClass
intuition.library/AddGadget
intuition.library/AddGList
intuition.library/AllocRemember
intuition.library/AutoRequest
intuition.library/BeginRefresh
intuition.library/BuildEasyRequestArgs
intuition.library/BuildSysRequest
intuition.library/ChangeWindowBox
intuition.library/ClearDMRequest
intuition.library/ClearMenuStrip
intuition.library/ClearPointer
intuition.library/CloseScreen
intuition.library/CloseWindow
intuition.library/CloseWorkBench
intuition.library/CurrentTime
intuition.library/DisplayAlert
intuition.library/DisplayBeep
intuition.library/DisposeObject
intuition.library/DoubleClick
intuition.library/DrawBorder
intuition.library/DrawImage
intuition.library/DrawImageState
intuition.library/EasyRequestArgs
intuition.library/EndRefresh
intuition.library/EndRequest
intuition.library/EraseImage
intuition.library/FreeClass
intuition.library/FreeRemember
intuition.library/FreeScreenDrawInfo
intuition.library/FreeSysRequest
intuition.library/GadgetMouse
intuition.library/GetAttr
intuition.library/GetDefaultPubScreen
intuition.library/GetDefPrefs
intuition.library/GetPrefs
intuition.library/GetScreenData
intuition.library/GetScreenDrawInfo
intuition.library/InitRequester
intuition.library/IntuiTextLength
intuition.library/ItemAddress
intuition.library/LockIBase
intuition.library/LockPubScreen
intuition.library/LockPubScreenList
intuition.library/MakeClass
intuition.library/MakeScreen
intuition.library/ModifyIDCMP
intuition.library/ModifyProp
intuition.library/MoveScreen
intuition.library/MoveWindow
intuition.library/MoveWindowInFrontOf
intuition.library/NewModifyProp
intuition.library/NewObject
intuition.library/NextObject
intuition.library/NextPubScreen
intuition.library/ObtainGIRPort
intuition.library/OffGadget
intuition.library/OffMenu
intuition.library/OnGadget
intuition.library/OnMenu
intuition.library/OpenScreen
intuition.library/OpenScreenTagList
intuition.library/OpenWindow
intuition.library/OpenWindowTagList
intuition.library/OpenWorkBench
intuition.library/PointInImage
intuition.library/PrintIText
intuition.library/PubScreenStatus
intuition.library/QueryOverscan
intuition.library/RefreshGadgets
intuition.library/RefreshGList
intuition.library/RefreshWindowFrame
intuition.library/ReleaseGIRPort
intuition.library/RemakeDisplay
intuition.library/RemoveClass
intuition.library/RemoveGadget
intuition.library/RemoveGList
intuition.library/ReportMouse
intuition.library/Request
intuition.library/ResetMenuStrip
intuition.library/RethinkDisplay
intuition.library/ScreenToBack
intuition.library/ScreenToFront
intuition.library/SetAttrsA
intuition.library/SetDefaultPubScreen
intuition.library/SetDMRequest
intuition.library/SetEditHook
intuition.library/SetGadgetAttrsA
intuition.library/SetMenuStrip
intuition.library/SetMouseQueue
intuition.library/SetPointer
intuition.library/SetPrefs
intuition.library/SetPubScreenModes
intuition.library/SetWindowTitles
intuition.library/ShowTitle
intuition.library/SizeWindow
intuition.library/SysReqHandler
intuition.library/UnlockIBase
intuition.library/UnlockPubScreen
intuition.library/UnlockPubScreenList
intuition.library/ViewAddress
intuition.library/ViewPortAddress
intuition.library/WBenchToBack
intuition.library/WBenchToFront
intuition.library/WindowLimits
intuition.library/WindowToBack
intuition.library/WindowToFront
intuition.library/ZipWindow
 intuition.library/ActivateGadget             intuition.library/ActivateGadget

    NAME
    ActivateGadget -- Activate a (string or custom) gadget.

    SYNOPSIS
    Success = ActivateGadget( Gadget, Window, Request )
    D0			  A0      A1      A2

    BOOL ActivateGadget( struct Gadget *, struct Window *,
        struct Requester * );

    FUNCTION
    Activates a string or custom gadget.  If successful, this means
    that the user does not need to click in the gadget before typing.

    The window parameter must point to the window which contains the gadget.
    If the gadget is actually in a requester, the window must contain
    the requester, and a pointer to the requester must also be
    passed.	The requester parameter must only be valid if the gadget
    has the	GTYP_REQGADGET flag set, a requirement for all requester
    gadgets.

    The success of this function depends on a rather complex set
    of conditions.  The intent is that the user is never interrupted from
    what interactions he may have underway.

    The current set of conditions includes:
    -   The window must be active.  If you are opening a new window
        and want an active gadget in it, it is not sufficient to
        assume that the WFLG_ACTIVATE flag has taken effect by the time
        OpenWindow() returns, even if you insert a delay of some
        finite amount of time.  Use the IDCMP_ACTIVEWINDOW IntuiMessage
        to tell when your window really becomes active.  Many
        programs use an event loop that calls ActivateGadget()
        whenever they receive the IDCMP_ACTIVEWINDOW message, and also
        the IDCMP_MOUSEBUTTONS messages, and so on, to keep the
        gadget active until it is used (or the user selects some
        other "Cancel" gadget).

    -   No other gadgets may be in use.  This includes system gadgets,
        such as those for window sizing, dragging, etc.
    -   If the gadget is in a requester, that requester must
        be active. (Use IDCMP_REQSET and IDCMP_REQCLEAR).
    -   The right mouse button cannot be held down (e.g. menus)

    NOTE: Don't try to activate a gadget which is disabled or
    not attached to a window or requester.

    INPUTS
    Gadget = pointer to the gadget that you want activated.
    Window = pointer to a window structure containing the gadget.
    Requester = pointer to a requester (may by NULL if this isn't
           a requester gadget (i.e. GTYP_REQGADGET is not set)).

    RESULT
    If the conditions above are met, and the gadget is in fact a string
    gadget, then this function will return TRUE, else FALSE.

    BUGS
    At present, this function will not return FALSE if a custom
    gadget declines to be activated.

    SEE ALSO

 intuition.library/ActivateWindow             intuition.library/ActivateWindow

    NAME
    ActivateWindow -- Activate an Intuition window.

    SYNOPSIS
    [success =] ActivateWindow( Window )
    [D0]                        A0

    [LONG] ActivateWindow( struct Window * );
    /* returns LONG in V36 and higher */

    FUNCTION
    Activates an Intuition window.

    Note that this call may have its action deferred: you cannot assume
    that when this call is made the selected window has become active.
    This action will be postponed while the user plays with gadgets and
    menus, or sizes and drags windows.  You may detect when the window
    actually has become active by the IDCMP_ACTIVEWINDOW IDCMP message.

    This call is intended to provide flexibility but not to confuse the
    user.  Please call this function synchronously with some action
    by the user.

    INPUTS
    Window = a pointer to a Window structure

    RESULT
    V35 and before: None.
    V36 and later: returns zero if no problem queuing up
        the request for deferred action

    BUGS
    Calling this function in a tight loop can blow out Intuition's deferred
    action queue.

    SEE ALSO
    OpenWindow(), and the WFLG_ACTIVATE window flag
 intuition.library/AddClass                         intuition.library/AddClass

    NAME
    AddClass -- Make a public class available (V36)

    SYNOPSIS
    AddClass( Class )
              A0

    VOID AddClass( struct IClass * );

    FUNCTION
    Adds a public boopsi class to the internal list of classes available
    for public consumption.

    You must call this function after you call MakeClass().

    INPUTS
    Class = pointer returned by MakeClass()

    RESULT
    Nothing returned.

    NOTES

    BUGS
    Although there is some protection against creating classes
    with the same name as an existing class, this function
    does not do any checking or other dealings with like-named
    classes.  Until this is rectified, only officially registered
    names can be used for public classes, and there is no
    "class replacement" policy in effect.

    SEE ALSO
    MakeClass(), FreeClass(), RemoveClass()
    Document "Basic Object-Oriented Programming System for Intuition"
    and the "boopsi Class Reference" document.
 intuition.library/AddGadget                       intuition.library/AddGadget

    NAME
    AddGadget -- Add a gadget to the gadget list of a window.

    SYNOPSIS
    RealPosition = AddGadget( Window, Gadget, Position )
    D0			  A0      A1      D0

    UWORD  AddGadget( struct Window *, struct Gadget *, UWORD );

    FUNCTION
    Adds the specified gadget to the gadget list of the given window,
    linked in at the position in the list specified by the position
    argument (that is, if Position == 0, the gadget will be inserted
    at the head of the list, and if Position == 1 then the gadget will
    be inserted after the first gadget and before the second).  If the
    position you specify is greater than the number of gadgets in the
    list, your gadget will be added to the end of the list.

    Calling AddGadget() does not cause your gadget to be redisplayed.
    The benefit of this is that you may add several gadgets without
    having the gadget list redrawn every time.

    This procedure returns the position at which your gadget was added.

    NOTE:  A relatively safe way to add the gadget to the end of the
    list is to specify a position of -1 (i.e., (UWORD) ~0).  That way,
    only the 65536th (and multiples of it) will be inserted at the wrong
    position.  The return value of the procedure will tell you where it was
    actually inserted.

    NOTE:  The system window gadgets are initially added to the
    front of the gadget list.  The reason for this is:  If you position
    your own gadgets in some way that interferes with the graphical
    representation of the system gadgets, the system's ones will be "hit"
    first by user.  If you then start adding gadgets to the front of the
    list, you will disturb this plan, so beware.  On the other hand, if
    you don't violate the design rule of never overlapping your gadgets,
    there's no problem.

    NOTE:  You may not add your own gadgets to a screen.  Gadgets may
    be added to backdrop windows, however, which can be visually similar,
    but also provide an IDCMP channel for gadget input messages.

    INPUTS
    Window = pointer to the window to get your gadget
    Gadget = pointer to the new gadget
    Position = integer position in the list for the new gadget (starting
        from zero as the first position in the list)

    RESULT
    Returns the position of where the gadget was actually added.

    BUGS

    SEE ALSO
    AddGList(), RemoveGadget(), RemoveGList()
 intuition.library/AddGList                         intuition.library/AddGList

    NAME
    AddGList -- Add a linked list of gadgets to a window or requester.

    SYNOPSIS
    RealPosition = AddGList( Window, Gadget, Position, Numgad, Requester )
    D0                       A0      A1      D0        D1      A2

    UWORD AddGList( struct Window *, struct Gadget *, UWORD, WORD,
        struct Requester * );

    FUNCTION
    Adds the list of gadgets to the gadget list of the given window
    or requester linked in at the position in the list specified by
    the position argument.

    See AddGadget() for more information about gadget list position,
    and more information about gadgets in general.

    The requester parameter will be ignored unless the GTYP_REQGADGET
    bit is set in the GadgetType field of the first gadget in the list.
    In that case, the gadget list is added to the requester gadgets.
    NOTE: be sure that GTYP_REQGADGET is either set or cleared consistently
    for all gadgets in the list.  NOTE ALSO: The window parameter
    should point to the window that the requester (will) appear in.

    Will add 'Numgad' gadgets from gadget list linked by the field
    NextGadget, or until some NextGadget field is found to be NULL.  Does
    not assume that the Numgad'th gadget has NextGadget equal to NULL.

    NOTE WELL: In order to link your gadget list in, the NextGadget
    field of the Numgad'th (or last) gadget will be modified.  Thus, if
    you are adding the first 3 gadgets from a linked list of five gadgets,
    this call will sever the connection between your third and fourth
    gadgets.

    INPUTS
    Window = pointer to the window to get your gadget
    Gadget = pointer to the first gadget to be added
    Position = integer position in the list for the new gadget
        (starting from zero as the first position in the list)
    Numgad = the number of gadgets from the linked list to be added
        if Numgad equals -1, the entire null-terminated list of
        gadgets will be added.
    Requester = the requester the gadgets will be added to if the
        GTYP_REQGADGET GadgetType flag is set for the first gadget
        in the list

    RESULT
    Returns the position of where the first gadget in the list was actually
    added.

    BUGS

    SEE ALSO
    AddGadget(), RemoveGadget(), RemoveGList()
 intuition.library/AllocRemember               intuition.library/AllocRemember

    NAME
    AllocRemember -- AllocMem() with tracking to make freeing easy.

    SYNOPSIS
    MemBlock = AllocRemember( RememberKey, Size, Flags )
    D0			  A0	       D0    D1

    APTR AllocRemember( struct Remember **, ULONG, ULONG );

    FUNCTION
    This routine calls the Exec AllocMem() function for you, but also links
    the parameters of the allocation into a master list, so that
    you can simply call the Intuition routine FreeRemember() at a later
    time to deallocate all allocated memory without being required to
    remember the details of the memory you've allocated.

    This routine will have two primary uses:
       -   Let's say that you're doing a long series of allocations in a
           procedure.  If any one of the allocations fails, your program
        may need to abort the procedure.  Abandoning ship correctly
        involves freeing up what memory you've already allocated.  This
        procedure allows you to free up that memory easily, without being
        required to keep track of how many allocations you've already done,
        what the sizes of the allocations were, or where the memory was
        allocated.

       -   Also, in the more general case, you may do all of the allocations
           in your entire program using this routine.  Then, when your
           program is exiting, you can free it all up at once with a
           simple call to FreeRemember().

    You create the "anchor" for the allocation master list by creating
    a variable that's a pointer to struct Remember, and initializing
    that pointer to NULL.  This is called the RememberKey.  Whenever
    you call AllocRemember(), the routine actually does two memory
    allocations, one for the memory you want and the other for a copy
    of a Remember structure.  The Remember structure is filled in
    with data describing your memory allocation, and it's linked
    into the master list pointed to by your RememberKey.  Then, to
    free up any memory that's been allocated, all you have to do is
    call FreeRemember() with your RememberKey.

    Please read the FreeRemember() function description, too.  As you will
    see, you can select either to free just the link nodes and keep all the
    allocated memory for yourself, or to free both the nodes and your memory
    buffers.

    INPUTS
    RememberKey = the address of a pointer to struct Remember.  Before the
    very first call to AllocRemember, initialize this pointer to NULL.

    Size = the size in bytes of the memory allocation.  Please refer to the
        exec.library/AllocMem() function for details.
    Flags = the specifications for the memory allocation.  Please refer to
        the exec.library/AllocMem() function for details.

    EXAMPLE
    struct Remember *RememberKey;
    RememberKey = NULL;
    buffer = AllocRemember(&RememberKey, BUFSIZE, MEMF_CHIP);
    if (buffer)
    {
        /* Use the buffer */
        ...
    }
    FreeRemember(&RememberKey, TRUE);

    RESULT
    If the memory allocation is successful, this routine returns the byte
    address of your requested memory block.  Also, the node to your block
    will be linked into the list pointed to by your RememberKey variable.
    If the allocation fails, this routine returns NULL and the list pointed
    to by RememberKey, if any, will be unchanged.

    BUGS
    This function makes two allocations for each memory buffer
    you request.  This is neither fast nor good for memory
    fragmentation.

    This function should use the exec AllocPool() function internally,
    at least for the Remember headers.

    SEE ALSO
    FreeRemember(), exec.library/AllocMem()
 intuition.library/AutoRequest                   intuition.library/AutoRequest

    NAME
    AutoRequest -- Automatically build and get response from a requester.

    SYNOPSIS
    Response = AutoRequest( Window, BodyText, PosText, NegText,
    D0                      A0      A1        A2       A3
            PosFlags, NegFlags, Width, Height )
            D0        D1        D2     D3

    BOOL AutoRequest( struct Window *, struct IntuiText *,
        struct IntuiText *, struct IntuiText *,
        ULONG, ULONG, WORD, WORD );

    FUNCTION
    This procedure automatically builds a requester for you and then
    waits for a response from the user, or for the system to satisfy your
    request.  If the response is positive, this procedure returns TRUE.
    If the response is negative, this procedure returns FALSE.

    An IDCMPFlag specification is created by bitwise "or'ing" your
    PosFlags, NegFlags, and the IDCMP classes IDCMP_GADGETUP and
    IDCMP_RAWKEY.  You may specify zero flags for either the PosFlags
    or NegFlags arguments.

    The IntuiText arguments, and the width and height values, are
    passed directly to the BuildSysRequest() procedure along with
    your window pointer and the IDCMP flags.  Please refer to
    BuildSysRequest() for a description of the IntuiText that you are
    expected to supply when calling this routine.  It's an important
    but long-winded description that need not be duplicated here.

    If the BuildSysRequest() procedure does not return a pointer
    to a window, it will return TRUE or FALSE (not valid structure
    pointers) instead, and these BOOL values will be returned to
    you immediately.

    On the other hand, if a valid window pointer is returned, that
    window will have had its IDCMP ports and flags initialized according
    to your specifications.  AutoRequest() then waits for IDCMP messages
    on the UserPort, which satisfies one of four requirements:
    -   either the message is of a class that matches
        one of your PosFlags arguments (if you've supplied
        any), in which case this routine returns TRUE.  Or
    -   the message class matches one of your NegFlags
        arguments (if you've supplied any), in which case
        this routine returns FALSE.  Or
    -   the IDCMP message is of class IDCMP_GADGETUP, which means that
        one of the two gadgets, as provided with the PosText and NegText
        arguments, was selected by the user.  If the TRUE gadget
        was selected, TRUE is returned.  If the FALSE gadget was
        selected, FALSE is returned.
    -   Lastly, two IDCMP_RAWKEY messages may satisfy the request: those
        for the V and B keys with the left Amiga key depressed.
        These keys, satisfy the gadgets on the left or right side of
        the requester--TRUE or FALSE--, respectively.

        NOTE: For V36, these two keys left-Amiga-B and V are processed
        through the default keymap.

    When the dust has settled, this routine calls FreeSysRequest() if
    necessary to clean up the requester and any other allocated memory.

    NOTE: For V36, this function now switches the processor stack
    to ensure sufficient stack space for the function to succeed.

    INPUTS
    Window = pointer to a Window structure.  See BuildSysRequest()
        for a full discussion.
    BodyText = pointer to an IntuiText structure
    PosText = pointer to an IntuiText structure, may by NULL.
    NegText = pointer to an IntuiText structure, MUST be valid!
    PosFlags = flags for the IDCMP
    NegFlags = flags for the IDCMP
    Width, Height = the sizes to be used for the rendering of the requester

    NOTE for V36: The width and height parameters are ignored, as
    are several other specifications in the IntuiText, to make
    AutoRequest() requesters retroactively conform to the new look
    designed for EasyRequest().

    RESULT
    The return value is either TRUE or FALSE.  See the text above for a
    complete description of the chain of events that might lead to either
    of these values being returned.

    NOTES
    When DOS brings up AutoRequests() on your process (eg.
    "Please insert volume XXX in any drive", they normally come
    up on the Workbench screen.  If you set your Process pr_WindowPtr
    field to point to one of your windows, then DOS will bring its
    requesters up on the same screen as that window.  A pr_WindowPtr
    of -1 prevents requesters from coming up at all.
    (Some FileSystem requesters cannot be redirected or supressed).

    BUGS
    The requester no longer devolves into a call to DisplayAlert()
    if there is not enough memory for the requester.

    SEE ALSO
    EasyRequest(), BuildSysRequest(), SysReqHandler()
 intuition.library/BeginRefresh                 intuition.library/BeginRefresh

    NAME
    BeginRefresh -- Sets up a window for optimized refreshing.

    SYNOPSIS
    BeginRefresh( Window )
              A0

    VOID BeginRefresh( struct Window * );

    FUNCTION
    This routine sets up your window for optimized refreshing.

    Its role is to provide Intuition integrated access to the Layers
    library function BeginUpdate().  Its additional contribution is
    to be sure that locking protocols for layers are followed, by
    locking both layers of a WFLG_GIMMEZEROZERO window only after the
    parent Layer_Info has been locked.  Also, the WFLG_WINDOWREFRESH
    flag is set in your window, for your information.

    The purpose of BeginUpdate(), and hence BeginRefresh(), is to
    restrict rendering in a window (layer) to the region that needs
    refreshing after an operation such as window sizing or uncovering.
    This restriction to the "damage region" persists until you call
    EndRefresh().

    For instance, if you have a WFLG_SIMPLE_REFRESH window which is
    partially concealed and the user brings it to the front, you can
    receive an IDCMP_REFRESHWINDOW message asking you to refresh your
    display.  If you call BeginRefresh() before doing any of the
    rendering, then the layer that underlies your window will be arranged
    so that the only rendering that will actually take place will be that
    which goes to the newly-revealed areas.  This is very performance-
    efficient, and visually attractive.

    After you have performed your refresh of the display, you should call
    EndRefresh() to reset the state of the layer and the window.  Then you
    may proceed with rendering to the entire window as usual.

    You learn that your window needs refreshing by receiving either a
    message of class IDCMP_REFRESHWINDOW through the IDCMP, or an input
    event of class IECLASS_REFRESHWINDOW through the Console device.
    Whenever you are told that your window needs refreshing, you should
    call BeginRefresh() and EndRefresh() to clear the refresh-needed
    state, even if you don't plan on doing any rendering.  You may relieve
    yourself of even this burden by setting the WFLG_NOCAREREFRESH flag
    when opening your window.

    WARNING: You should only perform graphics refreshing operations
    during the period between calling BeginRefresh() and EndRefresh().
    In particular, do not call RefreshGadgets() or RefreshGList(), since
    the locking protocol internal to Intuition runs the risk of creating
    a deadlock.  Note that Intuition refreshes the gadgets (through
    the damage region) before it sends the IDCMP_REFRESHWINDOW message.

    ANOTHER WARNING: The concept of multiple refresh passes using
    EndRefresh( w, FALSE ) is not completely sound without further
    protection.  The reason is that between two sessions, more
    damage can occur to your window.  Your final EndRefresh( w, TRUE )
    will dispose of all damage, including the new, and your
    initial refreshing pass will never get the chance to refresh
    the new damage.

    To avoid this, you must protect your session using LockLayerInfo()
    which will prevent Intuition from performing window operations
    or anything else which might cause further damage from occurring.
    Again, while holding the LayerInfo lock make no Intuition
    function calls dealing with gadgets; just render.

    You can, however, call InstallClipRegion() for the different
    refresh passes, if you have two clip regions.

    SIMILAR WARNING: Your program and Intuition "share" your window
    layer's DamageList.  BeginRefresh() helps arbitrate this
    sharing, but the lower-level function layers.library/BeginUpdate()
    does not.  It isn't really supported to use BeginUpdate() on
    a window's layer, but if you do--for whatever reason--it is
    critical that you first acquire the LayerInfo lock as in
    the above example: even if you only have one pass of refresh
    rendering to do.  Otherwise, the refreshing of your window's
    borders and gadgets can be incomplete, and the problem might
    occur only under certain conditions of task priority and
    system load.

    EXAMPLE
    Code fragment for "two pass" window refreshing, in response
    to an IDCMP_REFRESHWINDOW message:
    switch ( imsg->Class )
    {
    ...
    case IDCMP_REFRESHWINDOW:
        window = imsg->IDCMPWindow;

        /* this lock only needed for "two-pass" refreshing */
        LockLayerInfo( &window->WScreen->LayerInfo );

        /* refresh pass for region 1 */
        origclip = InstallClipRegion( window->WLayer, region1 );
        BeginRefresh( window );
        myRefreshRegion1( window );
        EndRefresh( window, FALSE );

        /* refresh pass for region 2 */
        InstallClipRegion( window->WLayer, region2 );
        BeginRefresh( window );
        myRefreshRegion2( window );
        EndRefresh( window, TRUE );		/* and dispose damage list */

        /* restore and unlock */
        InstallClipRegion( window->WLayer, origclip );
        UnlockLayerInfo( &window->WScreen->LayerInfo );
        break;
    ...
    }

    INPUTS
    Window = pointer to the window structure which needs refreshing

    RESULT
    None

    BUGS
    This function should check the return code of
    layers.library/BeginUpdate(), and abort if that function fails.

    SEE ALSO
       EndRefresh(), layers.library/BeginUpdate(), OpenWindow()
    layer.library/InstallClipRegion(), graphics.library/LockLayerInfo()
    The "Windows" chapter of the Intuition Reference Manual
 intuition.library/BuildEasyRequestArgs intuition.library/BuildEasyRequestArgs

    NAME
    BuildEasyRequestArgs -- Simple creation of system request. (V36)
    BuildEasyRequest -- Varargs stub for BuildEasyRequestArgs(). (V36)

    SYNOPSIS
    ReqWindow = BuildEasyRequestArgs( RefWindow, easyStruct, IDCMP, Args )
    D0                                A0         A1          D0     A3

    struct Window *BuildEasyRequestArgs( struct Window *,
        struct EasyStruct *, ULONG, APTR );

    ReqWindow = BuildEasyRequest( RefWindow, easyStruct, IDCMP, Arg1, ... )

    struct Window *BuildEasyRequest( struct Window *,
        struct EasyStruct *, ULONG, APTR, ... );

    FUNCTION
    This function is to EasyRequest() as BuildSysRequest() is to
    AutoRequest(): it returns a pointer to the system requester
    window.  The input from that window can then be processed
    under application control.

    It is recommended that this processing be done with
    SysReqHandler(), so that future enhancement to the
    processing will be enjoyed.

    After you have determined that the requester is satisfied or
    cancelled, you must free this requester using FreeSysRequest().

    Please see the autodoc for EasyRequest().

    NOTE: This function switches the processor stack to ensure
    sufficient stack space for the function to complete.

    INPUTS
    Window = reference window for requester: determines the
        requester window title and screen.
    easyStruct = pointer to EasyStruct structure, as described
        in the EasyRequest() autodocs.
    IDCMP = (NOT A POINTER) provided application specific IDCMP
        flags for the system requester window.
    Args = see EasyRequest()

    RESULT
    A pointer to the system request window opened.  In the event
    of problems, you may also be returned the value '0' which
    is to be interpreted as the "FALSE, Cancel" choice, or
    (if you have a second gadget defined) the value '1', which
    is to be taken to mean the equivalent of your corresponding
    left-most gadget.

    If there is a problem creating the window, a recoverable alert may
    be substituted for the requester, and the result, either 0 or 1,
    returned.

    BUGS
    Does not put up alternative alert.
    See also BUGS listed for EasyRequestArgs().

    SEE ALSO
    EasyRequestArgs(), FreeSysRequest(), SysReqHandler(),
    BuildSysRequest(), AutoRequest()
 intuition.library/BuildSysRequest           intuition.library/BuildSysRequest

    NAME
    BuildSysRequest -- Build and display a system requester.

    SYNOPSIS
    ReqWindow = BuildSysRequest( Window, BodyText, PosText, NegText,
    D0                           A0      A1        A2       A3
                   IDCMPFlags, Width, Height )
               D0          D1     D2

    struct Window *BuildSysRequest( struct Window *, struct IntuiText *,
        struct IntuiText *, struct IntuiText *, ULONG, WORD, WORD );

    FUNCTION
    This procedure builds a system requester based on the supplied
    information.  If all goes well and the requester is constructed,
    this procedure returns a pointer to the window in which the requester
    appears.  That window will have its IDCMP initialized to reflect the
    flags found in the IDCMPFlags argument.  You may then wait on those
    ports to detect the user's response to your requester, which response
    may include either selecting one of the gadgets or causing some other
    event to be noticed by Intuition (like IDCMP_DISKINSERTED, for
    instance).  After the requester is satisfied, you should call the
    FreeSysRequest() procedure to remove the requester and free up
    any allocated memory.

    See the autodoc for SysReqHandler() for more information on the
    how to handle the IntuiMessages this window will receive.

    The requester used by this function has the NOISYREQ flag bit set,
    which means that the set of IDCMPFlags that may be used here
    include IDCMP_RAWKEY, IDCMP_MOUSEBUTTONS, and others.

    In release previous to V36, if the requester could not be built,
    this function would try to call DisplayAlert() with the same
    information, with more or less favorable results.  In V36,
    the requesters themselves require less memory (SIMPLEREQ), but
    there is no alert attempt.

    The function may return TRUE (1) or FALSE if it cannot post
    the requester.  (V36 will always return FALSE, but be sure to
    test for TRUE in case somebody reinstates the fallback alert.)

    If the window argument you supply is equal to NULL, a new window will
    be created for you in the Workbench screen, or the default
    public screen, for V36.  If you want the requester
    created by this routine to be bound to a particular window (i.e.,
    to appear in the same screen as the window), you should
    not supply a window argument of NULL.

    New for V36: if you pass a NULL window pointer, the system requester
    will appear on the default public screen, which is not always
    the Workbench.

    The text arguments are used to construct the display.  Each is a
    pointer to an instance of the structure IntuiText.

    The BodyText argument should be used to describe the nature of
    the requester.  As usual with IntuiText data, you may link several
    lines of text together, and the text may be placed in various
    locations in the requester.  This IntuiText pointer will be stored
    in the ReqText variable of the new requester.

    The PosText argument describes the text that you want associated
    with the user choice of "Yes,  TRUE,  Retry,  Good."  If the requester
    is successfully opened, this text will be rendered in a gadget in
    the lower-left of the requester, which gadget will have the
    GadgetID field set to TRUE.  If the requester cannot be opened and
    the DisplayAlert() mechanism is used, this text will be rendered in
    the lower-left corner of the alert display with additional text
    specifying that the left mouse button will select this choice.  This
    pointer can be set to NULL, which specifies that there is no TRUE
    choice that can be made.

    The NegText argument describes the text that you want associated
    with the user choice of "No,  FALSE,  Cancel,  Bad."  If the requester
    is successfully opened, this text will be rendered in a gadget in
    the lower-right of the requester, which gadget will have the
    GadgetID field set to FALSE.  If the requester cannot be opened and
    the DisplayAlert() mechanism is used, this text will be rendered in
    the lower-right corner of the alert display with additional text
    specifying that the right mouse button will select this choice.  This
    pointer cannot be set to NULL.  There must always be a way for the
    user to cancel this requester.

    The Positive and Negative Gadgets created by this routine have
    the following features:
          - GTYP_BOOLGADGET
          - GACT_RELVERIFY
          - GTYP_REQGADGET
          - GACT_TOGGLESELECT

    When defining the text for your gadgets, you may find it convenient
    to use the special constants used by Intuition for the construction
    of the gadgets.  These include defines like AUTODRAWMODE, AUTOLEFTEDGE,
    AUTOTOPEDGE and AUTOFRONTPEN.  You can find these in your local
    intuition.h (or intuition.i) file.

    These hard-coded constants are not very resolution or font
    sensitive, but V36 will override them to provide more modern
    layout.

    New for V36, linked lists of IntuiText are not correctly supported
    for gadget labels.

    The width and height values describe the size of the requester.  All
    of your BodyText must fit within the width and height of your
    requester.  The gadgets will be created to conform to your sizes.

    VERY IMPORTANT NOTE:  for this release of this procedure, a new window
    is opened in the same screen as the one containing your window.
    Future alternatives may be provided as a function distinct from this
    one.

    NOTE: This function will pop the screen the requester and its
    window appears in to the front of all screens.  New for V36,
    if the user doesn't perform any other screen arrangement before
    finishing with the requester, a popped screen will be pushed
    back behind.

    INPUTS
    Window = pointer to a Window structure
    BodyText = pointer to an IntuiText structure
    PosText = pointer to an IntuiText structure
    NegText = pointer to an IntuiText structure
    IDCMPFlags = the IDCMP flags you want used for the initialization of the
           IDCMP of the window containing this requester
    Width, Height = the size required to render your requester

    NOTE for V36: the width and height you pass are ignored, as
    are some of the parameters of your IntuiText, so that Intuition
    can make the Requesters real nice for the new look.

    RESULT
    If the requester was successfully created, the value
    returned by this procedure is a pointer to the window in which the
    requester is rendered.  If the requester could not be created,
    this routine might have called DisplayAlert() before returning
    (it depends on the version) and will pass back TRUE if the user
    pressed the left mouse button and FALSE if the user pressed the
    right mouse button.   If the version of Intuition doesn't
    call DisplayAlert(), or if it does, and there's not enough
    memory for the alert, the value of FALSE is returned.

    BUGS
    This procedure currently opens a window in the Screen which
    contains the window which is passed as a parameter, or the
    default public screen, if that parameter is NULL.  Although
    not as originally envisioned, this will probably always be the
    behavior of this function.

    DisplayAlert() is not called in version V36.

    It's almost impossible to make complete, correct account
    of different system fonts, window border dimensions, and
    screen resolution to get the layout of a System Requester
    just right using this routine.  For V36, we recommend the
    automatic layout implemented in BuildEasyRequest and EasyRequest.

    SEE ALSO
    FreeSysRequest(), DisplayAlert(), ModifyIDCMP(), exec.library/Wait(),
    Request(), AutoRequest(), EasyRequest(), BuildEasyRequestArgs()
 intuition.library/ChangeWindowBox           intuition.library/ChangeWindowBox

    NAME
    ChangeWindowBox -- Change window position and dimensions. (V36)

    SYNOPSIS
    ChangeWindowBox( Window, Left, Top, Width, Height )
             A0	 D0    D1   D2     D3

    VOID ChangeWindowBox( struct Window *, WORD, WORD, WORD, WORD );

    FUNCTION
    Makes simultaneous changes in window position and dimensions,
    in absolute (not relative) coordinates.

    Like MoveWindow() and SizeWindow(), the effect of this function
    is deferred until the next input comes along.  Unlike these
    functions, ChangeWindowBox() specifies absolute window position
    and dimensions, not relative.  This makes for more reliable
    results considering that the action is deferred, so this
    function is typically preferable to MoveWindow() and SizeWindow()
    paired.

    You can detect that this operation has completed by receiving
    the IDCMP_CHANGEWINDOW IDCMP message

    The dimensions are limited to legal range, but you should still
    take care to specify sensible inputs based on the window's dimension
    limits and the size of its screen.

    This function limits the position and dimensions to legal
    values.

    INPUTS
    Window = the window to change position/dimension
    Left, Top, Width, Height = new position and dimensions

    RESULT
    Position and dimension are changed to your specification,
    or as close as possible.
    Returns nothing.

    BUGS

    SEE ALSO
    MoveWindow(), SizeWindow(), ZipWindow(),
    layers.library/MoveSizeLayer()
 intuition.library/ClearDMRequest             intuition.library/ClearDMRequest

    NAME
    ClearDMRequest -- Clear (detaches) the DMRequest of the window.

    SYNOPSIS
    Response = ClearDMRequest( Window )
    D0			   A0

    BOOL ClearDMRequest( struct Window * );

    FUNCTION
    Attempts to clear the DMRequest from the specified window,
    that is detaches the special requester that you attach to
    the double-click of the menu button which the user can then
    bring up on demand.  This routine WILL NOT clear the DMRequest
    if it's active (in use by the user). The IDCMP message class
    IDCMP_REQCLEAR can be used to detect that the requester is not in use,
    but that message is sent only when the last of perhaps several
    requesters in use in a window is terminated.

    INPUTS
    Window = pointer to the window from which the DMRequest is to be cleared.

    RESULT
    If the DMRequest was not currently in use, detaches the DMRequest
    from the window and returns TRUE.

    If the DMRequest was currently in use, doesn't change anything
    and returns FALSE.

    BUGS

    SEE ALSO
    SetDMRequest(), Request()
 intuition.library/ClearMenuStrip             intuition.library/ClearMenuStrip

    NAME
    ClearMenuStrip -- Clear (detach) the menu strip from the window.

    SYNOPSIS
    ClearMenuStrip( Window )
                A0

    VOID ClearMenuStrip( struct Window * );

    FUNCTION
    Detaches the current menu strip from the window; menu strips
    are attached to windows using the SetMenuStrip() function
    (or, for V36, ResetMenuStrip() ).

    If the menu is in use (for that matter if any menu is in use)
    this function will block (Wait()) until the user has finished.

    Call this function before you make any changes to the data
    in a Menu or MenuItem structure which is part of a menu
    strip linked into a window.

    INPUTS
    Window = pointer to a window structure

    RESULT
    None

    BUGS

    SEE ALSO
    SetMenuStrip(), ResetMenuStrip()
 intuition.library/ClearPointer                 intuition.library/ClearPointer

    NAME
    ClearPointer -- Clear the mouse pointer definition from a window.

    SYNOPSIS
    ClearPointer( Window )
              A0

    VOID ClearPointer( struct Window * );

    FUNCTION
    Clears the window of its own definition of the Intuition mouse pointer.
    After calling ClearPointer(), every time this window is the active
    one the default Intuition pointer will be the pointer displayed
    to the user.  If your window is the active one when this routine
    is called, the change will take place immediately.

    Custom definitions of the mouse pointer which this function clears
    are installed by a call to SetPointer().

    INPUTS
    Window = pointer to the window to be cleared of its pointer definition

    RESULT
    None

    BUGS

    SEE ALSO
    SetPointer()
 intuition.library/CloseScreen                   intuition.library/CloseScreen

    NAME
    CloseScreen -- Close an Intuition screen.

    SYNOPSIS
    [Success =] CloseScreen( Screen )
    [D0]	    		 A0

    [BOOL] CloseScreen( struct Screen * );
    /* returns BOOL in V36 and greater */

    FUNCTION
    Unlinks the screen, unlinks the viewport, deallocates everything that
    Intuition allocated when the screen was opened (using OpenScreen()).
    Doesn't care whether or not there are still any windows attached to the
    screen.  Doesn't try to close any attached windows; in fact, ignores
    them altogether (but see below for changes in V36).

    If this is the last screen to go, attempts to reopen Workbench.

    New for V36: this function will refuse to close the screen
    if there are windows open on the screen when CloseScreen() is
    called.  This avoids the almost certain crash when a screen
    is closed out from under a window.

    INPUTS
    Screen = pointer to the screen to be closed.

    RESULT
    New for V36: returns TRUE (1) if screen is closed,
    returns FALSE (0) if screen had open windows when
    called.

    BUGS

    SEE ALSO
    OpenScreen()
 intuition.library/CloseWindow                   intuition.library/CloseWindow

    NAME
    CloseWindow -- Close an Intuition window.

    SYNOPSIS
    CloseWindow( Window )
             A0

    VOID CloseWindow( struct Window * );

    FUNCTION
    Closes an Intuition window.  Unlinks it from the system, deallocates
    its memory, and makes it disappear.

    When this function is called, all IDCMP messages which have been sent
    to your window are deallocated.  If the window had shared a message
    Port with other windows, you must be sure that there are no unreplied
    messages for this window in the message queue.  Otherwise, your program
    will try to make use of a linked list (the queue) which contains free
    memory (the old messages).  This will give you big problems.
    See the code fragment CloseWindowSafely(), below.

    NOTE:  If you have added a Menu strip to this Window (via
    a call to SetMenuStrip()) you must be sure to remove that Menu strip
    (via a call to ClearMenuStrip()) before closing your Window.

    NOTE: This function may block until it is safe to de-link and free
    your window.  Your program may thus be suspended while the user
    plays with gadgets, menus, or window sizes and position.

    New for V36: If your window is a "Visitor Window" (see OpenWindow)
    CloseWindow will decrement the "visitor count" in the public screen
    on which the window was open.  When the last visitor window is
    closed, a signal will be sent to the public screen task, if this
    was pre-arranged (see OpenScreen).

    INPUTS
    Window = a pointer to a Window structure

    RESULT
    None

    BUGS

    SEE ALSO
    OpenWindow(), OpenScreen(), CloseScreen()

    EXAMPLE
    /*	CloseWindowSafely */

    /* these functions close an Intuition window
     * that shares a port with other Intuition
     * windows or IPC customers.
     *
     * We are careful to set the UserPort to
     * null before closing, and to free
     * any messages that it might have been
     * sent.
     */
    #include "exec/types.h"
    #include "exec/nodes.h"
    #include "exec/lists.h"
    #include "exec/ports.h"
    #include "intuition/intuition.h"

    CloseWindowSafely( win )
    struct Window *win;
    {
        /* we forbid here to keep out of race conditions with Intuition */
        Forbid();

        /* send back any messages for this window
         * that have not yet been processed
         */
        StripIntuiMessages( win->UserPort, win );

        /* clear UserPort so Intuition will not free it */
        win->UserPort = NULL;

        /* tell Intuition to stop sending more messages */
        ModifyIDCMP( win, 0L );

        /* turn multitasking back on */
        Permit();

        /* and really close the window */
        CloseWindow( win );
    }

    /* remove and reply all IntuiMessages on a port that
     * have been sent to a particular window
     * (note that we don't rely on the ln_Succ pointer
     *  of a message after we have replied it)
     */
    StripIntuiMessages( mp, win )
    struct MsgPort *mp;
    struct Window *win;
    {
        struct IntuiMessage *msg;
        struct Node *succ;

        msg = (struct IntuiMessage *) mp->mp_MsgList.lh_Head;

        while( succ =  msg->ExecMessage.mn_Node.ln_Succ ) {

        if( msg->IDCMPWindow ==  win ) {

            /* Intuition is about to free this message.
             * Make sure that we have politely sent it back.
             */
            Remove( msg );

            ReplyMsg( msg );
        }

        msg = (struct IntuiMessage *) succ;
        }
    }
 intuition.library/CloseWorkBench             intuition.library/CloseWorkBench

    NAME
    CloseWorkBench -- Closes the Workbench screen.

    SYNOPSIS
    Success = CloseWorkBench()
    D0

    LONG CloseWorkBench( VOID );

    FUNCTION
    This routine attempts to close the Workbench screen:
       -   Test whether or not any applications have opened windows on the
           Workbench, and return FALSE if so.  Otherwise ...
       -   Clean up all special buffers
       -   Close the Workbench screen
       -   Make the Workbench program mostly inactive (it will still
           monitor disk activity)
       -   Return TRUE

    INPUTS
    None

    RESULT
    TRUE if the Workbench screen closed successfully
    FALSE if the Workbench was not open, or if it has windows
        open which are not Workbench drawers.

   NOTES
    This routine has been drastically rewritten for V36.
    It is much more solid, although we haven't eliminated
    all the problem cases yet.

    BUGS
    The name of this function is improperly spelled.  It ought
    to have been CloseWorkbench().

    It might be more convenient to have it return TRUE if the
    Workbench wasn't opened when called.  The idea as it is now
    is probably this: if you want to free up the memory of the
    Workbench screen when your program begins, you can call
    CloseWorkBench().  The return value of that call indicates
    whether you should call OpenWorkBench() when your program
    exits: if FALSE, that means either the the Workbench existed
    but you could not close it, or that it wasn't around to
    begin with, and you should not try to re-open it.

    We would prefer that you provide a user selection to attempt
    to open or close the Workbench screen from within your application,
    rather than your making assumptions like these.

    SEE ALSO
    OpenWorkBench()
 intuition.library/CurrentTime                   intuition.library/CurrentTime

    NAME
    CurrentTime -- Get the current time values.

    SYNOPSIS
    CurrentTime( Seconds, Micros )
             A0       A1

    VOID CurrentTime( ULONG *, ULONG * );

    FUNCTION
    Puts copies of the current time into the supplied argument pointers.

    This time value is not extremely accurate, nor is it of a very fine
    resolution.  This time will be updated no more than sixty times a
    a second, and will typically be updated far fewer times a second.

    INPUTS
    Seconds = pointer to a LONG variable to receive the current seconds
        value
    Micros = pointer to a LONG variable for the current microseconds value

    RESULT
    Puts the time values into the memory locations specified by the
        arguments
    Return value is not defined.

    BUGS

    SEE ALSO
    timer.device/TR_GETSYSTIME
 intuition.library/DisplayAlert                 intuition.library/DisplayAlert

    NAME
    DisplayAlert -- Create the display of an alert message.

    SYNOPSIS
    Response = DisplayAlert( AlertNumber, String, Height )
    D0			 D0           A0      D1

    BOOL DisplayAlert( ULONG, UBYTE *, WORD );

    FUNCTION
    Creates an alert display with the specified message.

    If the system can recover from this alert, it's a RECOVERY_ALERT and
    this routine waits until the user presses one of the mouse buttons,
    after which the display is restored to its original state and a
    BOOL value is returned by this routine to specify whether or not
    the user pressed the LEFT mouse button.

    If the system cannot recover from this alert, it's a DEADEND_ALERT
    and this routine returns immediately upon creating the alert display.
    The return value is FALSE.

    NOTE: Starting with V33, if Intuition can't get enough
    memory for a RECOVERY_ALERT, the value FALSE will be returned.

    AlertNumber is a LONG value, historically related to the value
    sent to the Alert() routine.  But the only bits that are pertinent to
    this routine are the ALERT_TYPE bit(s).  These bits must be set to
    either RECOVERY_ALERT for alerts from which the system may safely
    recover, or DEADEND_ALERT for those fatal alerts.  These states are
    described in the paragraph above.   There is a third type of
    alert, the DAISY_ALERT, which is used only by the Exec.

    The string argument points to an AlertMessage string.  The AlertMessage
    string is comprised of one or more substrings, each of which is
    composed of the following components:
           - first, a 16-bit x-coordinate and an 8-bit y-coordinate,
             describing where on the alert display you want this string
             to appear.  The y-coordinate describes the offset to the
             baseline of the text.
           - then, the bytes of the string itself, which must be
             null-terminated (end with a byte of zero)
           - lastly, the continuation byte, which specifies whether or
             not there's another substring following this one.  If the
             continuation byte is non-zero, there IS another substring
             to be processed in this alert message.  If the continuation
             byte is zero, this is the last substring in the message.

    The last argument, Height, describes how many video lines tall you
    want the alert display to be.

    New for V36: Alerts are always rendered in Topaz 8 (80 column font),
    regardless of the system default font.  Also, RECOVERY_ALERTs are
    displayed in amber, while DEADEND_ALERTs are still red.  Alerts
    no longer push down the application screens to be displayed.  Rather,
    they appear alone in a black display.

    Also new for V36: Alerts block each other out, and input
    during an alert is deprived of the rest of the system.  Internal
    input buffers still cause alert clicks to be processed by
    applications sometimes.

    INPUTS
    AlertNumber = the number of this alert message.  The only pertinent
        bits of this number are the ALERT_TYPE bit(s).  The rest of the
           number is ignored by this routine.
    String = pointer to the alert message string, as described above
    Height = minimum display lines required for your message

    RESULT
    A BOOL value of TRUE or FALSE.  If this is a DEADEND_ALERT, FALSE
    is always the return value.  If this is a RECOVERY_ALERT. The return
    value will be TRUE if the user presses the left mouse button in
    response to your message, and FALSE if the user presses the right hand
    button is response to your text, or if the alert could not
    be posted.

    BUGS
    If the system is worse off than you think, the level of your alert
    may become DEADEND_ALERT without you ever knowing about it.  This
    will NOT happen due simply to low memory.  Rather, the alert
    display will be skipped, and FALSE will be returned.

    The left and right button clicks satisfying the alerts are
    unfortunately passed to	the normal applications, because of
    some internal system input buffering.

    SEE ALSO

 intuition.library/DisplayBeep                   intuition.library/DisplayBeep

    NAME
    DisplayBeep -- Flash the video display.

    SYNOPSIS
    DisplayBeep( Screen )
             A0

    VOID DisplayBeep( struct Screen * );

    FUNCTION
    "Beeps" the video display by flashing the background color of the
    specified screen.  If the screen argument is NULL, every screen
    in the display will be beeped.  Flashing everyone's screen is not
    a polite thing to do, so this should be reserved for dire
    circumstances.

    The reason such a routine is supported is because the Amiga has
    no internal bell or speaker.  When the user needs to know of
    an event that is not serious enough to require the use of a requester,
    the DisplayBeep() function may be called.

    New for V36:  Intuition now calls DisplayBeep through the
    external library vector.  This means that if you call SetFunction()
    to replace DisplayBeep with an audible beep, for example, then
    your change will affect even Intuition's calls to DisplayBeep.

    INPUTS
    Screen = pointer to a screen.  If NULL, every screen in the display
           will be flashed

    RESULT
    None

    BUGS

    SEE ALSO

 intuition.library/DisposeObject               intuition.library/DisposeObject

    NAME
    DisposeObject -- Deletes a 'boopsi' object. (V36)

    SYNOPSIS
    DisposeObject( Object )
                   A0

    VOID DisposeObject( APTR );

    FUNCTION
    Deletes a boopsi object and all of it auxiliary data.
    These objects are all created by NewObject().  Objects
    of certain classes "own" other objects, which will also
    be deleted when the object is passed to DisposeObject().
    Read the per-class documentation carefully to be aware
    of these instances.

    INPUTS
    Object = abstract pointer to a boopsi object returned by NewObject()

    NOTES
    This function invokes the OM_DISPOSE method.

    RESULT
    None.

    BUGS

    SEE ALSO
    NewObject(), SetAttrs(), GetAttr(), MakeClass(),
    Document "Basic Object-Oriented Programming System for Intuition"
    and the "boopsi Class Reference" document.
 intuition.library/DoubleClick                   intuition.library/DoubleClick

    NAME
    DoubleClick -- Test two time values for double-click timing.

    SYNOPSIS
    IsDouble = DoubleClick( StartSecs, StartMicros,
    D0                      D0         D1
        CurrentSecs, CurrentMicros )
        D2           D3

    BOOL DoubleClick( ULONG, ULONG, ULONG, ULONG );

    FUNCTION
    Compares the difference in the time values with the double-click
    timeout range that the user has set (using the "Preferences" tool) or
    some other program has configured into the system.  If the
    difference between the specified time values is within the current
    double-click time range, this function returns TRUE, else it
    returns FALSE.

       These time values can be found in input events and IDCMP messages.
       The time values are not perfect; however, they are precise enough for
       nearly all applications.

    INPUTS
    StartSeconds, StartMicros = the timestamp value describing the start of
          the double-click time period you are considering
    CurrentSeconds, CurrentMicros = the timestamp value describing
          the end of the double-click time period you are considering

    RESULT
    If the difference between the supplied timestamp values is within the
    double-click time range in the current set of Preferences, this
    function returns TRUE, else it returns FALSE

    BUGS

    SEE ALSO
    CurrentTime()
 intuition.library/DrawBorder                     intuition.library/DrawBorder

    NAME
    DrawBorder -- Draw the specified Border structure into a RastPort.

    SYNOPSIS
    DrawBorder( RastPort, Border, LeftOffset, TopOffset )
            A0        A1      D0          D1

    VOID DrawBorder( struct RastPort *, struct Border *, WORD, WORD );

    FUNCTION
    First, sets up the draw mode and pens in the RastPort according to the
    arguments of the Border structure.  Then, draws the vectors of
    the border argument into the RastPort, offset by the left and top
    offsets.

    As with all graphics rendering routines, the border will be clipped to
    to the boundaries of the RastPort's layer, if it exists.  This is
    the case with window RastPorts.

    This routine will draw all borders in the NULL-terminated list linked
    by the NextBorder field of the border argument.

    INPUTS
    RastPort = pointer to the RastPort to receive the border rendering
    Border = pointer to a Border structure
    LeftOffset = the offset to be added to each vector's x coordinate
    TopOffset = the offset to be added to each vector's y coordinate

    RESULT
    None

    BUGS

    SEE ALSO

 intuition.library/DrawImage                       intuition.library/DrawImage

    NAME
    DrawImage -- Draw the specified Image structure into a RastPort.

    SYNOPSIS
    DrawImage( RastPort, Image, LeftOffset, TopOffset )
           A0        A1     D0          D1

    VOID DrawImage( struct RastPort *, struct Image	*, WORD, WORD );

    FUNCTION
    First, sets up the draw mode and pens in the RastPort according to the
    arguments of the Image structure.  Then, moves the image data of
    the image argument into the RastPort, offset by the left and top
    offsets.

    This routine does window layer clipping if you pass your window's
    (layered) RastPort -- if you draw an image outside of your window,
    your imagery will be clipped at the window's edge.  If you pass
    a (non-layered) screen RastPort, you MUST be sure your image is
    wholly contained within the rastport bounds.

    If the NextImage field of the image argument is non-NULL,
    the next image is rendered as well, and so on until some
    NextImage field is found to be NULL.

    INPUTS
    RastPort = pointer to the RastPort to receive image rendering
    Image = pointer to an image structure
    LeftOffset = the offset which will be added to the image's x coordinate
    TopOffset = the offset which will be added to the image's y coordinate

    RESULT
    None

    NOTES
    Intuition always has and will continue to assume there are
    at least as many planes of data pointed to by ImageData as there
    are '1' bits in the PlanePick field.  Please ensure that
    this is so.  (See the intuition.h include file for full details
    on using PlanePick).

    BUGS

    SEE ALSO
    DrawImageState(), EraseImage()
 intuition.library/DrawImageState             intuition.library/DrawImageState

   NAME
    DrawImageState -- Draw an (extended) Intuition Image with
        special visual state. (V36)

   SYNOPSIS
    DrawImageState( RPort, Image, LeftOffset, TopOffset, State, DrawInfo )
            A0     A1     D0          D1         D2     A2

    VOID DrawImageState( struct RastPort *, struct Image *,
        WORD, WORD, ULONG, struct DrawInfo * );

   FUNCTION
    This function draws an Intuition Image structure in a variety of
    "visual states," which are defined by constants in
    intuition/imageclass.h.  These include:
    IDS_NORMAL		- like DrawImage()
    IDS_SELECTED		- represents the "selected state" of a Gadget
    IDS_DISABLED		- the "ghosted state" of a gadget
    IDS_BUSY		- for future functionality
    IDS_INDETERMINATE	- for future functionality
    IDS_INACTIVENORMAL	- for gadgets in window border
    IDS_INACTIVESELECTED	- for gadgets in window border
    IDS_INACTIVEDISABLED	- for gadgets in window border

    Only IDS_NORMAL will make sense for traditional Image structures,
    this function is more useful when applied to new custom images
    or "object-oriented image classes."

    Each class of custom images is responsible for documenting which
    visual states it supports, and you typically want to use images
    which support the appropriate states with your custom gadgets.

    The DrawInfo parameter provides information invaluable to
    "rendered" images, such as pen color and resolution.  Each
    image class must document whether this parameter is required.

   INPUTS
     RPort	- RastPort for rendering
    Image	- pointer to a (preferably custom) image
    LeftOffset,RightOffset - positional offsets in pixels
    State	- visual state selected from above
    DrawInfo - pointer to packed of pen selections and resolution.

   RESULT
     None.

   EXAMPLE
    Provided separately in the DevCon '90 disk set.

   NOTES

   BUGS

   SEE ALSO
    DrawImage(), GetScreenDrawInfo(), intuition/imageclass.h

 intuition.library/EasyRequestArgs           intuition.library/EasyRequestArgs

    NAME
    EasyRequestArgs -- Easy alternative to AutoRequest(). (V36)
    EasyRequest -- Varargs stub for EasyRequestArgs(). (V36)

    SYNOPSIS
    num = EasyRequestArgs( Window, easyStruct, IDCMP_ptr, ArgList )
    D0                     A0      A1          A2         A3

    LONG EasyRequestArgs( struct Window *, struct EasyStruct *,
        ULONG *, APTR );

    num = EasyRequest( Window, easyStruct, IDCMP_ptr, Arg1, Arg2, ... )

    LONG EasyRequest( struct Window *, struct EasyStruct *,
        ULONG *, APTR, ... );

    ( from intuition.h )
    struct EasyStruct {
        ULONG	es_StructSize;
        ULONG	es_Flags;
        UBYTE	*es_Title;
        UBYTE	*es_TextFormat;
        UBYTE	*es_GadgetFormat;
    };

    FUNCTION
    This function provides a simpler method of using a 'System
    Requester' than provided by AutoRequest().  It performs layout
    and size calculations sensitive to the current font and screen
    resolution.

    It provides for the descriptive 'body' text and the gadget
    text to be constructed from 'printf' style format strings.

    It also provides a general way for the requester to be
    sensitive to particular IDCMP messages.

    The first function listed is the actual Intuition library
    function.  It is passed the arguments for the formatting
    operations as a pointer to the first argument.

    The second function uses a C-style variable number of argument
    (varargs) calling convention.  It should be implemented as
    a call to the first function, and might be supplied by your
    compiler vendor, in amiga.lib, or using the first example below,
    for most C compilers.

    NOTE: The formatting is done by exec.library/RawDoFmt(), so
    be aware that to display a 32-bit integer argument, for
    example, you must say "%ld", not "%d", since RawDoFmt() is
    "word-oriented."

    NOTE: This function switches the processor stack to ensure
    sufficient stack space for the function to complete.

    EXAMPLES
    /* varargs interface works for most C compilers */
    EasyRequest( w, es, ip, arg1 )
    struct Window	*w;
    struct EasyStruct *es;
    ULONG		  *ip;
    int		  arg1;
    {
        return ( EasyRequestArgs( w, es, ip, &arg1 ) );
    }

    /*********************************************/

    /* typical use */
    struct EasyStruct volumeES = {
        sizeof (struct EasyStruct),
        0,
        "Volume Request",
        "Please insert volume %s in any drive.",
        "Retry|Cancel",
    };
    #define CANCEL	(0)

    Volume	*
    getVolume( volname )
    UBYTE	*volname;
    {
        Volume	*vptr;
        Volume	*findVolume();
        UWORD	reply;
        ULONG	iflags;

        iflags = IDCMP_DISKINSERTED;

    while ( ((vptr = findVolume( volname )) == NULL) &&
     (EasyRequest( w, &volumeES, &iflags, volname ) != CANCEL) )
        /* loop */ ;

        /* note that in some circumstances, you will have to
           re-initialize the value of 'iflags'.  Here, it
           is either unchanged, or returned as the single
           IDCMPFlag value IDCMP_DISKINSERTED.  If you combine
           multiple  IDCMPFlag values in 'iflags,' only
           one will be returned, so you must reinitialize
           'iflags' to be the combination.
          */
        return ( vptr );
    }

    INPUTS
    Window = Reference window pointer, determines the screen and
        title of the requester window.  This can be NULL, which
        means the requester is to appear on the Workbench screen,
        or default public screen, if defined.
    IDCMP_ptr = Pointer to IDCMP flags that you want to terminate
        the requester.  This pointer may be NULL.
    easyStruct = Pointer to EasyStruct structure with fields
        interpreted as follows:

    es_StructSize = sizeof (struct EasyStruct), for future extension.
    es_Flags = 0 for now, in the future may specify other options.
    es_Title = Title of system requester window.  If this is NULL,
        the title will be taken to be the same as the title of 'Window',
        if provided, or else "System Request."
    es_TextFormat = Format string, a la RawDoFmt(), for message in
        requester body.  Lines are separated by '\n'.  Formatting
        '%' functions are supported exactly as in RawDoFmt().
    es_GadgetFormat = Format string for gadgets.  Text for separate
        gadgets is separated by '|'.  Format functions are supported.
        You MUST specify at least one gadget.

    Args = Arguments for format commands.   Arguments for
        GadFmt follow arguments for TextFmt.

    RESULT
    0, 1, ..., N = Successive GadgetID values, for the gadgets
        you specify for the requester.  NOTE: The numbering
        from left to right is actually: 1, 2, ..., N, 0.
        This is for compatibility with AutoRequests which has
        FALSE for the rightmost gadget.

    -1 = Means that one of the caller-supplied IDCMPFlags occurred.
        The IDCMPFlag value is in the longword pointed to by IDCMP_ptr.

    NOTES
    When DOS brings up EasyRequests() on your process (eg.
    "Please insert volume XXX in any drive", they normally come
    up on the default public screen, which is usually the Workbench
    screen.  If you set your Process pr_WindowPtr field to point to
    one of your windows, then DOS will bring its requesters up on the
    same screen as that window.  A pr_WindowPtr of -1 prevents
    requesters from coming up at all.
    (Some FileSystem requesters cannot be redirected or supressed).

    BUGS
    Does not fall back to a recoverable alert if the requester
     cannot be created.

    Does not handle case when gadgets don't fit or window title
    is too long, although it does trim trailing spaces from the
    title for calculating dimensions.

    PLANS
    Possible enhancements include: centering of text, size-sensitive
    layout,  window-relative requester, vertical gadget layout,
    window placement, more keyboard shortcuts.

    We also reserve the use of the newline character '\n' in
    gadget format strings for future use as a line separator.

    SEE ALSO
    exec.library/RawDoFmt(), BuildEasyRequestArgs(), SysReqHandler(),
    AutoRequest(), BuildSysRequest()
 intuition.library/EndRefresh                     intuition.library/EndRefresh

    NAME
    EndRefresh -- End the optimized refresh state of the window.

    SYNOPSIS
    EndRefresh( Window, Complete )
            A0      D0

    VOID EndRefresh( struct Window *, BOOL );

    FUNCTION
    This function gets you out of the special refresh state of your
    window.  It is called following a call to BeginRefresh(), which
    routine puts you into the special refresh state.  While your window
    is in the refresh state, the only rendering that will be wrought in
    your window will be to those areas which were recently revealed and
    need to be refreshed.

    After you've done all the refreshing you want to do for this window,
    you should call this routine to restore the window to its
    non-refreshing state.  Then all rendering will go to the entire
    window, as usual.

    The 'Complete' argument is a boolean TRUE or FALSE value used to
    describe whether or not the refreshing you've done was all the
    refreshing that needs to be done at this time.  Most often, this
    argument will be TRUE.  But if, for instance, you have multiple
    tasks or multiple procedure calls which must run to completely
    refresh the window, then each can call its own Begin/EndRefresh()
    pair with a Complete argument of FALSE, and only the last calls
    with a Complete argument of TRUE.

    WARNING:  Passing this function the value of FALSE has its
    pitfalls.  Please see the several caveats in the autodoc for
    BeginRefresh().

    For your information, this routine calls the Layers library function
    EndUpdate(), unlocks your layers (calls UnlockLayerRom()), clears
    the LAYERREFRESH bit in your Layer Flags, and clears the
    WFLG_WINDOWREFRESH bit in your window Flags.

    INPUTS
    Window = pointer to the window currently in optimized-refresh mode
    Complete = Boolean TRUE or FALSE describing whether or not this
           window is completely refreshed

    RESULT
    None

    BUGS

    SEE ALSO
    BeginRefresh(), layers.library/EndUpdate(),
    graphics.library/UnlockLayerRom()
 intuition.library/EndRequest                     intuition.library/EndRequest

    NAME
    EndRequest -- Remove a currently active requester.

   SYNOPSIS
    EndRequest( Requester, Window )
            A0         A1

    VOID EndRequest( struct Requester *, struct Window * );

    FUNCTION
    Ends the request by erasing the requester and decoupling it from
    the window.

    Note that this doesn't necessarily clear all requesters from the window,
    only the specified one.  If the window labors under other requesters,
    they will remain in the window.

    INPUTS
    Requester = pointer to the requester to be removed
    Window = pointer to the Window structure with which this requester
           is associated

    RESULT
    None

    BUGS

    SEE ALSO
    Request()
 intuition.library/EraseImage                     intuition.library/EraseImage

   NAME
    EraseImage -- Erases an Image. (V36)

   SYNOPSIS
    EraseImage( RPort, Image, LeftOffset, TopOffset )
                A0     A1     D0          D1

    VOID EraseImage( struct RastPort *, struct Image *, WORD, WORD );

   FUNCTION
    Erases an Image.  For a normal Image structure, this will
    call the graphics function EraseRect() (clear using layer
    backfill, if any) for the Image box (LeftEdge/TopEdge/Width/Height).

    For custom image, the exact behavior is determined by the
    custom image class.

   INPUTS
     RPort	- RastPort to erase a part of
    Image	- custom or standard image
    LeftOffset,RightOffset - pixel offsets of Image position

   RESULT
     None.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    graphics.library/EraseRect().

 intuition.library/FreeClass                       intuition.library/FreeClass

    NAME
    FreeClass -- Frees a boopsi class created by MakeClass(). (V36)

    SYNOPSIS
    success = FreeClass( ClassPtr )
    D0                   A0

    BOOL FreeClass( struct IClass * );

    FUNCTION
    For class implementors only.

    Tries to free a boopsi class created by MakeClass().  This
    won't always succeed: classes with outstanding objects or
    with subclasses cannot be freed.  You cannot allow the code
    which implements the class to be unloaded in this case.

    For public classes, this function will *always* remove
    the class (see RemoveClass() ) making it unavailable, whether
    it succeeds or not.

    If you have a dynamically allocated data for your class (hanging
    off of cl_UserData), try to free the class before you free the
    user data, so you don't get stuck with a half-freed class.

    INPUTS
    ClassPtr - pointer to a class created by MakeClass().

    RESULT
    Returns FALSE if the class could not be freed.  Reasons include,
    but will not be limited to, having non-zero cl_ObjectCount or
    cl_SubclassCount.

    Returns TRUE if the class could be freed.

    Calls RemoveClass() for the class in either case.

    EXAMPLE
    Freeing a private class with dynamically allocated user data:

    freeMyClass( cl )
    struct IClass	*cl;
    {
        struct MyPerClassData	*mpcd;

        mpcd = (struct MyPerClassData *) cl->cl_UserData;
        if ( FreeClass( cl ) )
        {
        FreeMem( mpcd, sizeof mpcd );
        return ( TRUE );
        }
        else
        {
        return ( FALSE );
        }
    }

    BUGS

    SEE ALSO
    MakeClass(),
    Document "Basic Object-Oriented Programming System for Intuition"
    and the "boopsi Class Reference" document.

 intuition.library/FreeRemember                 intuition.library/FreeRemember

    NAME
    FreeRemember -- Free memory allocated by calls to AllocRemember().

    SYNOPSIS
    FreeRemember( RememberKey, ReallyForget )
              A0           D0

    VOID FreeRemember( struct Remember **, BOOL );

    FUNCTION
    This function frees up memory allocated by the AllocRemember() function.
    It will either free up just the Remember structures, which supply the
    link nodes that tie your allocations together, or it will deallocate
    both the link nodes AND your memory buffers too.

    If you want to deallocate just the Remember structure link nodes,
    you should set the ReallyForget argument to FALSE.  However, if you
    want FreeRemember to really deallocate all the memory, including
    both the Remember structure link nodes and the buffers you requested
    via earlier calls to AllocRemember(), then you should set the
    ReallyForget argument to TRUE.

    NOTE WELL: Once you call this function passing it FALSE, the
    linkages between all the memory chunks are lost, and you
    cannot subsequently use FreeRemember() to free them.

    INPUTS
    RememberKey = the address of a pointer to struct Remember.  This
           pointer should either be NULL or set to some value (possibly
           NULL) by a call to AllocRemember().
    ReallyForget = a BOOL FALSE or TRUE describing, respectively,
           whether you want to free up only the Remember nodes or
           if you want this procedure to really forget about all of
           the memory, including both the nodes and the memory buffers
           referenced by the nodes.

    EXAMPLE
    struct Remember *RememberKey;
    RememberKey = NULL;
    AllocRemember(&RememberKey, BUFSIZE, MEMF_CHIP);
    FreeRemember(&RememberKey, TRUE);

    RESULT
    None

    BUGS

    SEE ALSO
    AllocRemember(), exec.library/FreeMem()
 intuition.library/FreeScreenDrawInfo     intuition.library/FreeScreenDrawInfo

   NAME
     FreeScreenDrawInfo -- Finish using a DrawInfo structure. (V36)

   SYNOPSIS
    FreeScreenDrawInfo( Screen, DrInfo )
                A0      A1

    VOID FreeScreenDrawInfo( struct Screen *, struct DrawInfo * );

   FUNCTION
    Declares that you are finished with the DrawInfo structure
    returned by GetScreenDrawInfo().

   INPUTS
     Screen	      - pointer to screen passed to GetScreenDrawInfo()
    DrInfo      - pointer to DrawInfo returned by GetScreenDrawInfo()

   RESULT
     None

   NOTES
    This function, and GetScreenDrawInfo(), don't really do much, but
    they provide an upward compatibility path.  That means that
    if you misuse them today, they probably won't cause a problem,
    although they may someday later.  So, please be very careful
    only to use the DrawInfo structure between calls to
    GetScreenDrawInfo() and FreeScreenDrawInfo(), and be sure
    that you don't forget FreeScreenDrawInfo().

   BUGS

   SEE ALSO
    GetScreenDrawInfo()

 intuition.library/FreeSysRequest             intuition.library/FreeSysRequest

    NAME
    FreeSysRequest -- Free resources gotten by a call to BuildSysRequest().

    SYNOPSIS
    FreeSysRequest( Window )
                A0

    VOID FreeSysRequest( struct Window * );

    FUNCTION
    This routine frees up all memory allocated by a successful call to
    the BuildSysRequest() procedure.  If BuildSysRequest() returned a
    pointer to a window, then you are able to wait on the message port
    of that window to detect an event which satisfies the requester.
    When you want to remove the requester, you call this procedure.  It
    ends the requester and deallocates any memory used in the creation
    of the requester.  It also closes the special window that was opened
    for your system requester.

    For V36: It's OK if you pass a NULL or a TRUE (1) value to
    this function.  Also, this function properly disposes of
    requesters gotten using BuildEasyRequest().

    INPUTS
    Window = value of the window pointer returned by a successful call to
           the BuildSysRequest() procedure

    RESULT
    None

    BUGS

    SEE ALSO
    BuildSysRequest(), AutoRequest(), CloseWindow()
 intuition.library/GadgetMouse                   intuition.library/GadgetMouse

    NAME
    GadgetMouse -- Calculate gadget-relative mouse position. (V36)

    SYNOPSIS
    GadgetMouse( Gadget, GInfo, MousePoint )
             A0      A1     A2

    VOID GadgetMouse( struct GadgetInfo *, WORD * );

    FUNCTION
    Determines the current location of the mouse pointer relative
    to the upper-left corner of a custom gadget.  Typically used
    only in the GM_HANDLEINPUT and GM_GOACTIVE custom gadget hook
    routines.

    NEWS FLASH!!: These two hook routines are now passed the mouse
    coordinates, so this function has no known usefulness.

    We recommend that you don't call it.

    Note that this function calculates the mouse position taking
    "gadget relativity" (GFLG_RELRIGHT, GFLG_RELBOTTOM) into
    consideration.  If your custom gadget intends to ignore these
    properties, then you should either enjoin or inhibit your users
    from setting those bits, since Intuition won't ask if you respect
    them.

    INPUTS
    GInfo = A pointer to a GadgetInfo structure as passed to the
        custom gadget hook routine.
    MousePoint = address of two WORDS, or a pointer to a structure of
        type Point.

    RESULT
    Returns nothing.  Fills in the two words pointed to by
    MousePoint with the gadget-relative mouse position.

    BUGS
    Useless, since equivalent information is now passed to every
    function that might have a use for this.

    SEE ALSO

 intuition.library/GetAttr                           intuition.library/GetAttr

    NAME
    GetAttr -- Inquire the value of some attribute of an object. (V36)

    SYNOPSIS
    attr = GetAttr( AttrID, Object, StoragePtr )
    D0		D0	A0	A1

    ULONG GetAttr( ULONG, APTR, ULONG * );

    FUNCTION
    Inquires from the specified object the value of the specified attribute.

    You always pass the address of a long variable, which will
    receive the same value that would be passed to SetAttrs() in
    the ti_Data portion of a TagItem element.  See the documentation
    for the class for exceptions to this general rule.

    Not all attributes will respond to this function.  Those that
    will are documented on a class-by-class basis.

    INPUTS
    AttrID = the attribute tag ID understood by the object's class
    Object = abstract pointer to the boopsi object you are interested in
    StoragePtr = pointer to appropriate storage for the answer

    RESULT
    Returns FALSE (0) if the inquiries of attribute are not provided
    by the object's class.

    NOTES
    This function invokes the OM_GET method of the object.

    BUGS

    SEE ALSO
    NewObject(), DisposeObject(), SetAttrs(), MakeClass(),
    Document "Basic Object-Oriented Programming System for Intuition"
    and the "boopsi Class Reference" document.

 intuition.library/GetDefaultPubScreen   intuition.library/GetDefaultPubScreen

    NAME
    GetDefaultPubScreen -- Get name of default public screen. (V36)

    SYNOPSIS
    GetDefaultPubScreen( Namebuff )
                 A0

    VOID GetDefaultPubScreen( UBYTE * );

    FUNCTION
    Provides the name of the current default public screen.
    Only anticipated use is for Public Screen Manager utilities,
    since it is easy to open a visitor window on the default
    public screen without specifying the name.

    INPUTS
    Namebuff = a buffer of MAXPUBSCREENNAME.  This can be NULL.

    RESULT
    None.  Will provide the string "Workbench" in Namebuff if there
    is no current default public screen.

    NOTE
    This function actually "returns" in register D0 a pointer
    to the public screen.  Unfortunately, the lifespan of
    this pointer is not ensured; the screen could be closed
    at any time.  The *ONLY* legitimate use we can see for
    this return value is to compare for identity with the pointer
    to a public screen you either have a window open in, or
    a lock on using LockPubScreen(), to determine if that
    screen is in fact the default screen.

    BUGS
    The function prototype does not reflect the return value.

    SEE ALSO
    SetDefaultPubScreen(), OpenWindow()
 intuition.library/GetDefPrefs                   intuition.library/GetDefPrefs

    NAME
    GetDefPrefs -- Get a copy of the the Intuition default Preferences.

    SYNOPSIS
    Prefs = GetDefPrefs( PrefBuffer, Size )
    D0		     A0          D0

    struct Preferences *GetDefPrefs( struct Preferences *, WORD );

    FUNCTION
    Gets a copy of the Intuition default preferences data.  Writes the
    data into the buffer you specify.  The number of bytes you want
    copied is specified by the size argument.

    The default preferences are those that Intuition uses when it
    is first opened.  If no preferences file is found, these are
    the preferences that are used.  These would also be the startup
    preferences in an AmigaDOS-less environment.

    It is legal to take a partial copy of the Preferences structure.
    The more pertinent preferences variables have been grouped near
    the top of the structure to facilitate the memory conservation
    that can be had by taking a copy of only some of the Preferences
    structure.

    INPUTS
    PrefBuffer = pointer to the memory buffer to receive your copy of the
                Intuition Preferences structure
    Size = the number of bytes in your PrefBuffer, the number of bytes
          you want copied from the system's internal Preference settings

    RESULT
    Returns your parameter PrefBuffer.

    BUGS

    SEE ALSO
    GetPrefs()
 intuition.library/GetPrefs                         intuition.library/GetPrefs

    NAME
    GetPrefs -- Get the current Intuition Preferences structure.

    SYNOPSIS
    Prefs = GetPrefs( PrefBuffer, Size )
    D0		  A0          D0

    struct Preferences *GetPrefs( struct Preferences *, WORD );

    FUNCTION
    Gets a copy of the current Intuition Preferences structure.
    Writes the data into the buffer you specify.  The number of bytes you
    want copied is specified by the size argument.

    It is legal to take a partial copy of the Preferences structure.
    The more pertinent preferences variables have been grouped near
    the top of the structure to facilitate the memory conservation
    that can be had by taking a copy of only some of the Preferences
    structure.

    New for V36:  A new and more extensible method for supplying
    Preferences has been introduced in V36, and relies on file
    system notification.  The Intuition preferences items rely
    also on the IPrefs program.  Certain elements of the
    Preferences structure have been superceded by this new method.
    As much as possible, the Preferences structure returned by
    GetPrefs() reflect the current state of Preferences.  However,
    it is impossible to represent some of the V36-style preferences
    items using the existing Preferences structure.

    INPUTS
    PrefBuffer = pointer to the memory buffer to receive your copy of the
           Intuition Preferences
    Size = the number of bytes in your PrefBuffer, the number of bytes
           you want copied from the system's internal Preference settings

    RESULT
    Returns your parameter PrefBuffer.

    BUGS

    SEE ALSO
    GetDefPrefs(), SetPrefs()
 intuition.library/GetScreenData               intuition.library/GetScreenData

    NAME
    GetScreenData -- Get copy of a screen data structure.

    SYNOPSIS
    Success = GetScreenData( Buffer, Size, Type, Screen )
    D0                       A0      D0    D1    A1

    BOOL GetScreenData( APTR, UWORD, UWORD, struct Screen * );

    FUNCTION
    This function copies into the caller's buffer data from a Screen
    structure.  Typically, this call will be used to find the size, title
    bar height, and other values for a standard screen, such as the
    Workbench screen.

    To get the data for the Workbench screen, one would call:
        GetScreenData(buff, sizeof(struct Screen), WBENCHSCREEN, NULL)

    NOTE: if the requested standard screen is not open, this function
    will have the effect of opening it.

    This function has been useful for two basic types of things:
    1) Determining information about the Workbench screen, in
       preparation for opening a window on it.
    2) Attempts at discerning the user's preferences in a working
       screen, for "cloning" the Workbench modes and dimensions
       when opening a similar custom screen.

    Providing compatibility with both of these goals has proven
    difficult, as we introduce new display modes and screen scrolling
    in V36.  Read carefully the somewhat involved exceptions we
    elected to implement ...

    Changes as of V36:

    For V36 and later, the function LockPubScreen() is an improvement
    over this function, in that it doesn't copy the screen data
    but returns a pointer and a guarantee that the screen will not
    be closed.

    If the global public screen SHANGHAI mode is in effect (see
    SetPubScreenModes() ), this function will actually report on
    the default public screen, where "Workbench" windows will
    actually open.

    For V36 and later, this function does some "compatibility tricks"
    when you inquire about the WBENCHSCREEN.  To keep programs from
    "stumbling" into modes they don't understand, and because an NTSC
    machine may be running a PAL Workbench or PRODUCTIVITY, for example,
    the following "false" information is returned.

    The Screen.ViewPort.Modes field will either be HIRES or HIRES+LACE
    (with the SPRITES flag also set, as usual).  HIRES+LACE is
    used if the display mode selected for the Workbench screen
    is an interlaced screen of any type.

    The dimensions returned will be the *smaller* of the OSCAN_TEXT
    dimensions for the returned mode, and the actual dimensions
    of the Workbench screen.

    EXCEPTION: For specific compatibility considerations, if the
    Workbench is in one of the A2024 modes, the mode returned
    in Screen.ViewPort.Modes will be HIRES+LACE (with perhaps
    some "special" bits also set for future improvement), but
    with dimensions equal to the actual A2024-mode Workbench screen.
    This will favor programs which open windows on the A2024
    Workbench, but will cause some problems for programs which
    try to "clone" the Workbench screen using this function.

    If you want the real information about the modern Workbench
    screen, call LockPubScreen( "Workbench" ) and acquire its
    display mode ID by inquiring of the actual ViewPort (using
    graphics.library/GetVPModeID() ).

    You may then use the information you get to clone as many of
    the properties of the Workbench screen that you wish.

    In the long run, it's probably better to provide your user
    with a screen mode selection option, and skip all this.

    INPUTS
    Buffer = pointer to a buffer into which data can be copied
    Size   = the size of the buffer provided, in bytes
    Type   = the screen type, as specified in OpenWindow() (WBENCHSCREEN,
        CUSTOMSCREEN, ...)
    Screen = ignored, unless type is CUSTOMSCREEN, which results only in
        copying 'size' bytes from 'screen' to 'buffer'

    RESULT
    TRUE if successful
    FALSE if standard screen of Type 'type' could not be opened.

    BUGS
    You cannot support the new V36 display modes using this function.

    SEE ALSO
    OpenWindow(), LockPubScreen(), graphics.library/GetVPModeID(),
    SetPubScreenModes(), OpenScreen()
 intuition.library/GetScreenDrawInfo       intuition.library/GetScreenDrawInfo

   NAME
    GetScreenDrawInfo -- Get pointer to rendering information. (V36)

   SYNOPSIS
    DrInfo = GetScreenDrawInfo( Screen )
    D0	  		    A0

    struct DrawInfo *GetScreenDrawInfo( struct Screen * );

   FUNCTION
    Returns a pointer to a DrawInfo structure derived from the
    screen passed.  This data structure is READ ONLY.  The field
    dri_Version identifies which version of struct DrawInfo you
    are given a pointer to.

   INPUTS
     Screen        - pointer to a valid, open screen.

   RESULT
     DrInfo - pointer to a system-allocated DrawInfo structure,
    as defined in intuition/screens.h.

   NOTES
    Some information in the DrawInfo structure may in the future
    be calculated the first time this function is called for a
    particular screen.

    You must call FreeScreenDrawInfo() when you are done using the
    returned pointer.

    This function does not prevent a screen from closing.  Apply it
    only to the screens you opened yourself, or apply a protocol
    such as LockPubScreen().

    WARNING: Until further notice, the pointer returned does not
    remain valid after the screen is closed.

    This function and FreeScreenDrawInfo() don't really do much now,
    but they provide an upward compatibility path.  That means that
    if you misuse them today, they probably won't cause a problem,
    although they may someday later.  So, please be very careful
    only to use the DrawInfo structure between calls to
    GetScreenDrawInfo() and FreeScreenDrawInfo(), and be sure
    that you don't forget FreeScreenDrawInfo().

   BUGS
    Does not reflect to changes in screen modes, depth, or pens.

   SEE ALSO
    FreeScreenDrawInfo(), LockPubScreen(), intuition/screens.h

 intuition.library/InitRequester               intuition.library/InitRequester

    NAME
    InitRequester -- Initialize a Requester structure.

    SYNOPSIS
    InitRequester( Requester )
               A0

    VOID InitRequester( struct Requester * );

    FUNCTION
    Initializes a requester for general use.  After calling InitRequester,
    you need fill in only those Requester values that fit your needs.
    The other values are set to NULL--or zero--states.

    Note that the example in the early versions of the Intuition
    Reference Manual is flawed because the Requester structure is
    initialized BEFORE InitRequester is called.  Be sure to
    perform your initialization AFTER calling InitRequester.

    INPUTS
    Requester = a pointer to a Requester structure

    RESULT
    None

    BUGS
    Since the publication of the first Intuition Manual to this
    day, most people haven't used this function, and for
    compatibility reasons, we'll never be able to assume that
    they do.  Thus, this function is useless.

    SEE ALSO

 intuition.library/IntuiTextLength           intuition.library/IntuiTextLength

    NAME
    IntuiTextLength -- Return the length (pixel-width) of an IntuiText.

    SYNOPSIS
    Length = IntuiTextLength( IText )
    D0                        A0

    LONG IntuiTextLength( struct IntuiText * );

    FUNCTION
    This routine accepts a pointer to an instance of an IntuiText structure,
    and returns the length (the pixel-width) of the string which that
    instance of the structure represents.

    NOTE: if the Font pointer of your IntuiText structure is set to NULL,
    you'll get the pixel-width of your text in terms of the current system
    default font.  You may wish to be sure that the field IText->ITextFont
    for 'default font' text is equal to the Font field of the screen it is
    being measured for.

    INPUTS
    IText = pointer to an instance of an IntuiText structure

    RESULT
    Returns the pixel-width of the text specified by the IntuiText data

    BUGS
    Would do better to take a RastPort as argument, so that a NULL in
    the Font pointer would lead automatically to the font for the
    intended target RastPort, rather than the system default font.

    SEE ALSO
    OpenScreen()
 intuition.library/ItemAddress                   intuition.library/ItemAddress

    NAME
    ItemAddress -- Returns the address of the specified MenuItem.

    SYNOPSIS
    Item = ItemAddress( MenuStrip, MenuNumber )
    D0		    A0         D0

    struct MenuItem *ItemAddress( struct Menu *, UWORD );

    FUNCTION
    This routine feels through the specified menu strip and returns the
    address of the item specified by the menu number.  Typically,
    you will use this routine to get the address of a menu item from
    a menu number sent to you by Intuition after user has chosen from
    a window's menus.

       This routine requires that the arguments are well-defined.
    MenuNumber may be equal to MENUNULL, in which case this routine returns
    NULL.  If MenuNumber doesn't equal MENUNULL, it's presumed to be a
    valid item number selector for your menu strip, which includes:
           - a valid menu number
           - a valid item number
           - if the item specified by the above two components has a
             sub-item, the menu number may have a sub-item component, too.

    Note that there must be BOTH a menu number and an item number.
    Because a sub-item specifier is optional, the address returned by
    this routine may point to either an item or a sub-item.

    INPUTS
    MenuStrip = a pointer to the first menu in your menu strip
    MenuNumber = the value which contains the packed data that selects
           the menu and item (and sub-item).  See the Intuition Reference
        Manual for information on menu numbers.

    RESULT
    If MenuNumber == MENUNULL, this routine returns NULL,
    else this routine returns the address of the menu item specified
    by MenuNumber.

    BUGS

    SEE ALSO
    The "Menus" chapter of the Intuition Reference Manual,
    or the Amiga Rom Kernel Manual
 intuition.library/LockIBase                       intuition.library/LockIBase

    NAME
    LockIBase -- Invoke semaphore arbitration of IntuitionBase.

    SYNOPSIS
    Lock = LockIBase( LockNumber )
    D0                D0

    ULONG LockIBase( ULONG );

    FUNCTION
    Grabs Intuition internal semaphore so that caller may examine
    IntuitionBase safely.  This function is not a magic "fix all my
    race conditions" panacea.

    The idea here is that you can get the locks Intuition needs before
    such IntuitionBase fields as ActiveWindow and FirstScreen are
    changed, or linked lists of windows and screens are changed.

    Do Not Get Tricky with this entry point, and do not hold these locks
    for long, as all Intuition input processing will wait for you to
    surrender the lock by a call to UnlockIBase().

    NOTE WELL: A call to this function MUST be paired with a subsequent
    call to UnlockIBase(), and soon, please.

    NOTE WELL: Do not call any Intuition functions (nor any graphics,
    layers, dos, or other high-level system function) while
    holding this lock.

    INPUTS
    A long unsigned integer, LockNumber, specifies which of Intuition's
    internal locks you want to get.  This parameter should be zero for all
    forseeable uses of this function, which will let you examine active
    fields and linked lists of screens and windows with safety.

    RESULT
    Returns another ULONG which should be passed to UnlockIBase() to
    surrender the lock gotten by this call.

    BUGS
    This function must not be called while holding any other system locks
    such as layer or LayerInfo locks.

    SEE ALSO
    UnlockIBase(), layers.library/LockLayerInfo(),
    exec.library/ObtainSemaphore()
 intuition.library/LockPubScreen               intuition.library/LockPubScreen

    NAME
    LockPubScreen -- Prevent a public screen from closing. (V36)

    SYNOPSIS
    screen = LockPubScreen( Name )
    D0                      A0

    struct Screen *LockPubScreen( UBYTE * );

    FUNCTION
    Prevents a public screen (or the Workbench) from closing
    while you examine it in preparation of opening a visitor window.

    The sequence you use to open a visitor window that needs to
    examine fields in the screen it is about to open on is:
        LockPubScreen()
        ... examine fields ...
        OpenWindow() on public screen
        UnlockPubScreen()
        ... use your window ...
        CloseWindow()

    NOTE
    You needn't hold the "pubscreen lock" for the duration that
    your window is opened.  LockPubScreen() basically has the
    same effect as an open visitor window: it prevents the
    screen from being closed.

    If you pass the string "Workbench" or you pass NULL and there
    is no default public screen, the Workbench screen will
    be automatically opened if it is not already present.

    INPUTS
    Name = name string for public screen or NULL for default public
    screen.  The string "Workbench" indicates the Workbench
    screen.

    RESULT
    Returns pointer to a screen, if successful, else NULL.
    The call can fail for reasons including that the named
    public screen doesn't exist or is in private state.

    BUGS

    SEE ALSO
    OpenWindow(), UnlockPubScreen(), GetScreenData()
 intuition.library/LockPubScreenList       intuition.library/LockPubScreenList

    NAME
    LockPubScreenList -- Prevent changes to the system list. (V36)

    SYNOPSIS
    List = LockPubScreenList()
    D0

    struct List *LockPubScreenList( VOID );

    FUNCTION
    Arbitrates access to public screen list	while you quickly
    make a copy of it for display to the user.

    Note that this is intended only for the Public Screen Manager
    program.

    NOTES
    The nodes on the list are PubScreenNode structures.
    Act quickly while holding this lock.  The restrictions
    on LockIBase() apply here as well.

    INPUTS
    None.

    RESULT
    A pointer to the public screen list.

    BUGS

    SEE ALSO
    OpenScreen(), Intuition V36 update documentation
 intuition.library/MakeClass                       intuition.library/MakeClass

    NAME
    MakeClass -- Create and initialize a boopsi class. (V36)

    SYNOPSIS
    iclass = MakeClass( ClassID, SuperClassID, SuperClassPtr,
    D0                  A0       A1            A2
        InstanceSize, Flags )
            D0            D1

    struct IClass *MakeClass( UBYTE *, UBYTE *, struct IClass *,
        UWORD, ULONG );

    FUNCTION
    For class implementors only.

    This function creates a new public or private boopsi class.
    The superclass should be defined to be another boopsi class:
    all classes are descendants of the class "rootclass".

    Superclasses can be public or private.  You provide a name/ID
    for your class if it is to be a public class (but you must
    have registered your class name and your attribute ID's with
    Amiga, Inc. before you do this!).  For a public class, you would
    also call AddClass() to make it available after you have
    finished your initialization.

    Returns pointer to an IClass data structure for your
    class.  You then initialize the Hook cl_Dispatcher for
    your class methods code.  You can also set up special data
    shared by all objects in your class, and point cl_UserData at it.
    The last step for public classes is to call AddClass().

    You dispose of a class created by this function by calling
    FreeClass().

    INPUTS
    ClassID = NULL for private classes, the name/ID string for public
        classes
    SuperClassID = name/ID of your new class's superclass.  NULL if
        superclass is a private class
    SuperClassPtr = pointer to private superclass.  Only used if
        SuperClassID is NULL.  You are required never to provide
        a NULL superclass.
    InstanceSize = the size of the instance data that your class's
        objects will require, beyond that data defined for
        your superclass's objects.
    Flags = for future enhancement, including possible additional
        parameters.  Provide zero for now.

    RESULT
    Pointer to the resulting class, or NULL if not possible:
    - no memory for class data structure
    - public superclass not found
    - public class of same name/ID as this one already exists

    NOTES

    EXAMPLE
    Creating a private subclass of a public class:

    /* per-object instance data defined by my class	*/
    struct MyInstanceData {
    ULONG	mid_SomeData;
    };

    /* some useful table I'll share use for all objects */
    UWORD myTable[] = {
    5, 4, 3, 2, 1, 0
    };

    struct IClass	*
    initMyClass()
    {
    ULONG __saveds	myDispatcher();
    ULONG	hookEntry();	/* asm-to-C interface glue	*/
    struct IClass	*cl;
    struct IClass	*MakeClass();

    if ( cl =  MakeClass( NULL,
            SUPERCLASSID, NULL,		/* superclass is public      */
            sizeof (struct MyInstanceData),
            0 ))
    {
        /* initialize the cl_Dispatcher Hook	*/
        cl->cl_Dispatcher.h_Entry = hookEntry;
        cl->cl_Dispatcher.h_SubEntry = myDispatcher;
        cl->cl_Dispatcher.h_Data = (VOID *) 0xFACE;	/* unused */

        cl-cl_UserData = (ULONG) myTable;
    }
    return ( cl );
    }

    BUGS
    The typedef 'Class' isn't consistently used.  Class pointers
    used blindly should be APTR, or struct IClass for class implementors.

    SEE ALSO
    FreeClass(), AddClass(), RemoveClass(), NewObject(),
    Document "Basic Object-Oriented Programming System for Intuition"
    and the "boopsi Class Reference" document.
 intuition.library/MakeScreen                     intuition.library/MakeScreen

    NAME
    MakeScreen -- Do an Intuition-integrated MakeVPort() of a screen.

    SYNOPSIS
    MakeScreen( Screen )
            A0

    VOID MakeScreen( struct Screen * );

    FUNCTION
    This procedure allows you to do a MakeVPort() for the viewport of your
    custom screen in an Intuition-integrated way.  This way you can
    do your own screen manipulations without worrying about interference
    with Intuition's usage of the same viewport.

    The operation of this function is as follows:
        - Block until the Intuition View structure is not in being changed.
        - Set the view modes correctly to reflect if there is a (visible)
          interlaced screen.
        - call MakeVPort(), passing the Intuition View and your screen's
          ViewPort.
        - Unlocks the Intuition View.

    After calling this routine, you should call RethinkDisplay() to
    incorporate the new viewport of your custom screen into the
    Intuition display.

    NOTE: Intuition may determine that because of a change in global
    interlace needs that all viewports need to be remade, so
    it may effectively call RemakeDisplay().

    INPUTS
    Screen = address of the custom screen structure

    RESULT
    None

    BUGS

    SEE ALSO
    RethinkDisplay(), RemakeDisplay(), graphics.library/MakeVPort()
 intuition.library/ModifyIDCMP                   intuition.library/ModifyIDCMP

    NAME
    ModifyIDCMP -- Modify the state of a window's IDCMPFlags.

    SYNOPSIS
    [Success =] ModifyIDCMP( Window, IDCMPFlags )
    [D0]                     A0      D0

    [BOOL] ModifyIDCMP( struct Window *, ULONG );
    /* returns BOOL in V37 and greater */

    FUNCTION
    This routine modifies the state of your window's IDCMP (Intuition
    Direct Communication Message Port).  The state is modified to reflect
    your desires as described by the flag bits in the value IDCMPFlags.

    The four actions that might be taken are:

       - if there is currently no IDCMP in the given window, and IDCMPFlags
         is zero, nothing happens
       - if there is currently no IDCMP in the given window, and any of the
         IDCMPFlags is selected (set), then the IDCMP of the window is
         created, including allocating and initializing the message ports
         and allocating a signal bit for your port.  See the "Input and
         Output Methods" chapter of the Intuition Reference Manual for full
      details
       - if the IDCMP for the given window exists, and the
         IDCMPFlags argument is zero, this says that you want
         Intuition to close the ports, free the buffers and free
         your signal bit.  You MUST be the same task that was active
         when this signal bit was allocated (either by ModifyIDCMP()
      or OpenWindow() ).
       - if the IDCMP for the given window is opened, and the IDCMPFlags
         argument is not zero, this means that you want to change the
         state of which events will be broadcast to you through the IDCMP

    NOTE:  You can set up the Window->UserPort to any port of your own
    before you call ModifyIDCMP().  If IDCMPFlags is non-null but
    your UserPort is already initialized, Intuition will assume that
    it's a valid port with task and signal data preset and Intuition
    won't disturb your set-up at all, Intuition will just allocate
    the Intuition message port half of it.  The converse is true
    as well:  if UserPort is NULL when you call here with
    IDCMPFlags == NULL, Intuition will deallocate only the Intuition
    side of the port.

    This allows you to use a port that you already have allocated:
       - OpenWindow() with IDCMPFlags equal to NULL (open no ports)
       - set the UserPort variable of your window to any valid port of your
         own choosing
       - call ModifyIDCMP with IDCMPFlags set to what you want
       - then, to clean up later, set UserPort equal to NULL before calling
         CloseWindow() (leave IDCMPFlags alone)  BUT FIRST: you must make
      sure that no messages sent your window are queued at the port,
      since they will be returned to the memory free pool.

    For an example of how to close a window with a shared IDCMP,
    see the description for CloseWindow().

    INPUTS
    Window = pointer to the Window structure containing the IDCMP ports
    IDCMPFlags = the flag bits describing the new desired state of the IDCMP

    RESULT
    Starting in V37, this function returns NULL if it was unable
    to create the necessary message ports.  (The possibility of
    failure exists in earlier releases, but no return code was offered).
    Do not check the return code under V36 or earlier.

    BUGS

    SEE ALSO
    OpenWindow(), CloseWindow()
 intuition.library/ModifyProp                     intuition.library/ModifyProp

    NAME
    ModifyProp -- Modify the current parameters of a proportional gadget.

    SYNOPSIS
    ModifyProp( Gadget, Window, Requester,
            A0	    A1	    A2
                   Flags, HorizPot, VertPot, HorizBody, VertBody )
            D0	   D1	     D2	      D3	 D4

    VOID ModifyProp( struct Gadget *, struct Window *,
        struct Requester *, UWORD, UWORD, UWORD, UWORD, UWORD );

    FUNCTION
    Modifies the parameters of the specified proportional gadget.  The
    gadget's internal state is then recalculated and the imagery
    is redisplayed in the window or requester that contains the gadget.

    The requester variable can point to a requester structure.  If the
    gadget has the GTYP_REQGADGET flag set, the gadget is in a requester
    and the window pointer must point to the window of the requester.
    If this is not the gadget of a requester, the requester argument may
    be NULL.

    NOTE: this function causes all gadgets from the proportional
    gadget to the end of the gadget list to be refreshed, for
    reasons of compatibility.
    For more refined display updating, use NewModifyProp().

    New for V36: ModifyProp() refreshing consists of redrawing gadgets
    completely.  NewModifyProp() has changed this behavior (see
    NewModifyProp()).

    INPUTS
    PropGadget = pointer to a proportional gadget
    Window = pointer to the window containing the gadget or the window
        containing the requester containing the gadget.
    Requester = pointer to a requester (may be NULL if this isn't
        a requester gadget)
    Flags = value to be stored in the Flags field of the PropInfo
    HorizPot = value to be stored in the HorizPot field of the PropInfo
    VertPot = value to be stored in the VertPot field of the PropInfo
    HorizBody = value to be stored in the HorizBody field of the PropInfo
    VertBody = value to be stored in the VertBody field of the PropInfo

    RESULT
    None

    BUGS

    SEE ALSO
    NewModifyProp()
    The Intuition Reference Manual and Amiga Rom Kernel Manual contain
    more information on Proportional Gadgets.
 intuition.library/MoveScreen                     intuition.library/MoveScreen

    NAME
    MoveScreen -- Attempt to move the screen by the increments provided.

    SYNOPSIS
    MoveScreen( Screen, DeltaX, DeltaY )
            A0      D0      D1

    VOID MoveScreen( struct Screen *, WORD, WORD );

    FUNCTION
    Moves the screen the specified increment, specified in screen
    pixel resolution coordinates.

    New for V36: Screen movement limits have been greatly relaxed,
    to support screen scrolling.  In particular, negative values
    for screen LeftEdge and TopEdge may now be valid.

       If the DeltaX and DeltaY variables you specify would move the screen
       in a way that violates any restrictions, the screen will be moved
       as far as possible.  You may examine the LeftEdge and TopEdge fields
    of the Screen structure after this function returns to see where
    the screen really ended up.

    In operation, this function determines what the resulting position
    values that are actually to be used, sets these up, and calls
    MakeScreen() and RethinkDisplay().

    INPUTS
    Screen = pointer to a Screen structure
    DeltaX = amount to move the screen on the x-axis
        Note that DeltaX no longer (V36) need be set to zero
    DeltaY = amount to move the screen on the y-axis
        Note that these coordinates are in the same resolution
        as the screen (such as HIRES or INTERLACE)

    RESULT
    None

    BUGS

    SEE ALSO
    RethinkDisplay()
 intuition.library/MoveWindow                     intuition.library/MoveWindow

    NAME
    MoveWindow -- Ask Intuition to move a window.

    SYNOPSIS
    MoveWindow( Window, DeltaX, DeltaY )
            A0      D0      D1

    VOID MoveWindow( struct Window *, WORD, WORD );

    FUNCTION
    This routine sends a request to Intuition asking to move the window
    the specified distance.  The delta arguments describe how far to
    move the window along the respective axes.

    Note that the window will not be moved immediately, but rather
    will be moved the next time Intuition receives an input event,
    which happens currently at a minimum rate of ten times per second,
    and a maximum of sixty times a second.

    Interactions with other arbitration of Intuition data structures
    may defer this operation longer.  For V36, you can use the new
    IDCMP class IDCMP_CHANGEWINDOW to detect when this operation has
    completed.

    New for V36: Intuition now will do validity checking on the final
    position.  To send absolute movements, or to move and size a
    window in one step, use ChangeWindowBox().

    INPUTS
    Window = pointer to the structure of the Window to be moved
    DeltaX = how far to move the Window on the x-axis
    DeltaY = how far to move the Window on the y-axis

    RESULT
    None

    BUGS

    SEE ALSO
    ChangeWindowBox(), SizeWindow(), WindowToFront(), WindowToBack()
 intuition.library/MoveWindowInFrontOf   intuition.library/MoveWindowInFrontOf

    NAME
    MoveWindowInFrontOf -- Arrange the relative depth of a window. (V36)

    SYNOPSIS
    MoveWindowInFrontOf( Window, BehindWindow )
                 A0      A1

    VOID MoveWindowInFrontOf( struct Window *, struct Window * );

    FUNCTION
    Depth-arranges a window in front of an another window.
    Brings out the layers.library MoveLayerInFrontOf() to the
    Intuition user.

    INPUTS
    Window =  window to re-position in front of another window
    BehindWindow =  window to re-position in front of

    RESULT
    Repositions window.

    BUGS
    Doesn't respect backdrop windows.

    SEE ALSO
    WindowToFront(), WindowToBack(), layers.library/MoveLayerInFrontOf()
 intuition.library/NewModifyProp               intuition.library/NewModifyProp

    NAME
    NewModifyProp -- ModifyProp(), but with selective refresh.

    SYNOPSIS
    NewModifyProp( Gadget, Window, Requester, Flags,
               A0      A1      A2         D0
        HorizPot, VertPot, HorizBody, VertBody, NumGad )
        D1        D2       D3         D4        D5

    VOID NewModifyProp( struct Gadget *, struct Window *,
        struct Requester *, UWORD, UWORD, UWORD, UWORD, UWORD, WORD );

    FUNCTION
    Performs the function of ModifyProp(), but refreshes
    gadgets in the list as specified by the NumGad parameter.
    With NumGad = -1, this function is identical to ModifyProp().

    New for V36: When NumGad = 1, this function will now perform
    an incremental update of the proportional gadget knob image,
    rather than refreshing the entire gadget.  This means much
    less flashing when programmatically scrolling a proportional
    gadget.

    INPUTS
    PropGadget = pointer to a proportional gadget
    Window = pointer to the window containing the gadget or the window
        containing the requester containing the gadget.
    Requester = pointer to a requester (may be NULL if this isn't
        a requester gadget)
    Flags = value to be stored in the Flags field of the PropInfo
    HorizPot = value to be stored in the HorizPot field of the PropInfo
    VertPot = value to be stored in the VertPot field of the PropInfo
    HorizBody = value to be stored in the HorizBody field of the PropInfo
    VertBody = value to be stored in the VertBody field of the PropInfo
    NumGad = number of gadgets to be refreshed after propgadget internals
        have been adjusted.  -1 means "to end of list."

    RESULT
    None

    BUGS

    SEE ALSO
    ModifyProp()
    The Intuition Reference Manual contains more information on
    Proportional Gadgets.
 intuition.library/NewObject                       intuition.library/NewObject

    NAME
    NewObjectA -- Create an object from a class. (V36)
    NewObject -- Varargs stub for NewObjectA(). (V36)

    SYNOPSIS
    object = NewObjectA( class, classID, tagList )
    D0                   A0     A1       A2

    APTR NewObjectA( struct IClass *, UBYTE *, struct TagItem * );

    object = NewObject( class, classID, Tag1, ... )

    APTR NewObject( struct IClass *, UBYTE *, ULONG, ... );

    FUNCTION
    This is the general method of creating objects from 'boopsi' classes.
    ('Boopsi' stands for "basic object-oriented programming system for
    Intuition".)

    You specify a class either as a pointer (for a private class) or
    by its ID string (for public classes).  If the class pointer
    is NULL, then the classID is used.

    You further specify initial "create-time" attributes for the
    object via a TagItem list, and they are applied to the resulting
    generic data object that is returned.  The attributes, their meanings,
    attributes applied only at create-time, and required attributes
    are all defined and documented on a class-by-class basis.

    INPUTS
    class = abstract pointer to a boopsi class gotten via MakeClass().
    classID = the name/ID string of a public class.  This parameter is
        only used if 'class' is NULL.
    tagList = pointer to array of TagItems containing attribute/value
        pairs to be applied to the object being created

    RESULT
    A boopsi object, which may be used in different contexts such
    as a gadget or image, and may be manipulated by generic functions.
    You eventually free the object using DisposeObject().

    NOTES
    This function invokes the OM_NEW "method" for the class specified.

    BUGS
    Typedef's for 'Object' and 'Class' are defined in the include
    files but not used consistently.  The generic type APTR is
    probably best used for object and class "handles", with the
    type (UBYTE *) used for classID strings.

    SEE ALSO
    DisposeObject(), SetAttrs(), GetAttr(), MakeClass(),
    Document "Basic Object-Oriented Programming System for Intuition"
    and the "boopsi Class Reference" document.

 intuition.library/NextObject                     intuition.library/NextObject

    NAME
    NextObject -- iterate through the object on an Exec list. (V36)

    SYNOPSIS
    object = NextObject( objectPtrPtr )
    D0                   A0

    APTR NextObject( APTR );

    FUNCTION
    This function is for boopsi class implementors only.

    When you collect a set of boopsi objects on an Exec List
    structure by invoking their OM_ADDMEMBER method, you
    can (only) retrieve them by iterations of this function.

    Works even if you remove and dispose the returned list
    members in turn.

    INPUTS
    Initially, you set a pointer variable to equal the
    lh_Head field of the list (or mlh_Head field of a MinList).
    You pass the *address* of that pointer repeatedly
    to NextObject() until it returns NULL.

    EXAMPLE

    /* here is the OM_DISPOSE case of some class's dispatcher */
    case OM_DISPOSE:
        /* dispose members	*/
        object_state = mydata->md_CollectionList.lh_Head;
        while ( member_object = NextObject( &object_state ) )
        {
        DoMethod( member_object, OM_REMOVE ); /* remove from list */
        DM( member, msg );	/* and pass along dispose	*/
        }

    RESULT
    Returns pointers to each object in the list in turn, and NULL
    when there are no more.

    NOTES

    BUGS

    SEE ALSO
    DisposeObject(), SetAttrs(), GetAttr(), MakeClass(),
    Document "Basic Object-Oriented Programming System for Intuition"
    and the "boopsi Class Reference" document.
 intuition.library/NextPubScreen               intuition.library/NextPubScreen

    NAME
    NextPubScreen -- Identify next public screen in the cycle. (V36)

    SYNOPSIS
    Buff = NextPubScreen( Screen, NameBuff )
    D0                    A0      A1

    UBYTE *NextPubScreen( struct Screen *, UBYTE * );

    FUNCTION
    Returns name of next public screen in system rotation, to
    allow visitor windows to provide function to "jump" among
    public-screens in a cycle.

    INPUTS
    Screen = pointer to the screen your window is currently open in,
      or NULL, if you don't have a pointer to a public screen.
    NameBuff = pointer to a buffer of MAXPUBSCREENNAME+1 characters,
      for Intuition to fill in with the name of the next public
      screen in rotation.

    RESULT
    Returns NULL if there are no public screens, otherwise a
    pointer to your NameBuff.

    NOTES
    There is no guarantee that the public screen whose name
    was returned by this function will exist or be in "public" state
    by the time you call LockPubScreen(), etc.  You must handle
    cases where LockPubScreen(), etc. will fail.

    BUGS
    Due to a bug, your buffer needs to be (MAXPUBSCREENNAME + 1)
    characters big, which is one more than originally documented.

    The starting screen and cycle order of the public screens isn't
    defined, so do not draw conclusions about the order you
    see in the current version of Intuition.  We reserve the
    right to add meaning to the ordering at a future time.

    SEE ALSO
    OpenScreen(), Intuition V36 update documentation
 intuition.library/ObtainGIRPort               intuition.library/ObtainGIRPort

    NAME
    ObtainGIRPort -- Set up a RastPort for a custom gadget. (V36)

    SYNOPSIS
    RPort = ObtainGIRPort( GInfo )
    D0		       A0

    struct RastPort *ObtainGIRPort( struct GadgetInfo * );

    FUNCTION
    Sets up a RastPort for use (only) by custom gadget hook routines.
    This function must be called EACH time a hook routine needing
    to perform gadget rendering is called, and must be accompanied
    by a corresponding call to ReleaseGIRPort().

    Note that if a hook function passes you a RastPort pointer,
    e.g., GM_RENDER, you needn't call ObtainGIRPort() in that case.

    INPUTS
    A pointer to a GadgetInfo structure, as passed to each custom
    gadget hook function.

    RESULT
    A pointer to a RastPort that may be used for gadget rendering.
    This pointer may be NULL, in which case you should do no rendering.
    You may (optionally) pass a null return value to ReleaseGIRPort().

    BUGS

    SEE ALSO
    ReleaseGIRPort(), Custom Gadget documentation

 intuition.library/OffGadget                       intuition.library/OffGadget

    NAME
    OffGadget -- Disable the specified gadget.

    SYNOPSIS
    OffGadget( Gadget, Window, Requester )
           A0      A1      A2

    VOID OffGadget( struct Gadget *, struct Window *,
        struct Requester * );

    FUNCTION
    This command disables the specified gadget.  When a gadget is
    disabled, these things happen:
         - its imagery is displayed ghosted
         - the GFLG_DISABLED flag is set
         - the gadget cannot be selected by User

    The window parameter must point to the window which contains the
    gadget, or which contains the requester that contains the gadget.
    The requester parameter must only be valid if the gadget has the
    GTYP_REQGADGET flag set, a requirement for all requester gadgets.

       NOTE:  it's never safe to tinker with the gadget list yourself.  Don't
       supply some gadget that Intuition hasn't already processed in
       the usual way.

        NOTE: for compatibility reasons, this function will refresh all
    gadgets in a requester, and all gadgets from gadget to the
    end of the gadget list if gadget is in a window.

    If you want to improve on this behavior, you may perform the
    equivalent operation yourself: remove a gadget or gadgets,
    change the state of their GFLG_DISABLED flag, replace the
    gadgets using AddGList(), and selectively call RefreshGList().

    INPUTS
    Gadget = pointer to the gadget that you want disabled
    Window = pointer to a window structure containing the gadget or
        containing the requester which contains the gadget
    Requester = pointer to a requester (may by NULL if this isn't
           a requester gadget (i.e. GTYP_REQGADGET is not set)).

    RESULT
    None

    BUGS

    SEE ALSO
    AddGadget(), RefreshGadgets()
 intuition.library/OffMenu                           intuition.library/OffMenu

    NAME
    OffMenu -- Disable the given menu or menu item.

    SYNOPSIS
    OffMenu( Window, MenuNumber )
         A0      D0

    VOID OffMenu( struct Window *, UWORD );

    FUNCTION
    This command disables a sub-item, an item, or a whole menu.
    This depends on the contents of the data packed into MenuNumber,
    which is described in the Intuition Reference Manual.

    INPUTS
    Window = pointer to the window
    MenuNumber = the menu piece to be disabled

    RESULT
    None

    BUGS

    SEE ALSO
    OnMenu(), ResetMenuStrip()
 intuition.library/OnGadget                         intuition.library/OnGadget

    NAME
    OnGadget -- Enable the specified gadget.

    SYNOPSIS
    OnGadget( Gadget, Window, Requester )
          A0      A1      A2

    VOID OnGadget( struct Gadget *, struct Window *,
        struct Requester * );

    FUNCTION
    This command enables the specified gadget.  When a gadget is
    enabled, these things happen:
        - its imagery is displayed normally (not ghosted)
        - the GFLG_DISABLED flag is cleared
        - the gadget can thereafter be selected by the user

    The window parameter must point to the window which contains the
    gadget, or which contains the requester that contains the gadget
    The requester parameter must only be valid if the gadget has the
    GTYP_REQGADGET flag set, a requirement for all requester gadgets.

       NOTE:  it's never safe to tinker with the gadget list yourself.  Don't
       supply some gadget that Intuition hasn't already processed in
       the usual way.

        NOTE: for compatibility reasons, this function will refresh all
    gadgets in a requester, and all gadgets from gadget to the
    end of the gadget list if gadget is in a window.

    If you want to improve on this behavior, you may perform the
    equivalent operation yourself: remove a gadget or gadgets,
    change the state of their GFLG_DISABLED flag, replace the
    gadgets using AddGList(), and selectively call RefreshGList().

    INPUTS
    Gadget = pointer to the gadget that you want disabled
    Window = pointer to a window structure containing the gadget or
        containing the requester which contains the gadget
    Requester = pointer to a requester (may by NULL if this isn't
           a requester gadget (i.e. GTYP_REQGADGET is not set)).

    RESULT
    None

    BUGS

    SEE ALSO

 intuition.library/OnMenu                             intuition.library/OnMenu

    NAME
    OnMenu -- Enable the given menu or menu item.

    SYNOPSIS
    OnMenu( Window, MenuNumber )
            A0      D0

    VOID OnMenu( struct Window *, UWORD );

    FUNCTION
    This command enables a sub-item, an item, or a whole menu.
    This depends on the contents of the data packed into MenuNumber,
    which is described in the Intuition Reference Manual.

    INPUTS
    Window = pointer to the window
    MenuNumber = the menu piece to be enables

    RESULT
    None

    BUGS

    SEE ALSO
    OffMenu(), ResetMenuStrip()
 intuition.library/OpenScreen                     intuition.library/OpenScreen

    NAME
    OpenScreen -- Open an Intuition screen.

    SYNOPSIS
    Screen = OpenScreen( NewScreen )
    D0		     A0

    struct Screen *OpenScreen( struct NewScreen * );

    or

    struct Screen *OpenScreen( struct ExtNewScreen * );

    FUNCTION
    Opens an Intuition screen according to the specified parameters
    found in the NewScreen structure.

    Does all the allocations, sets up the screen structure and all
    substructures completely, and links this screen's viewport into
    Intuition's View structure.

    Before you call OpenScreen(), you must initialize an instance of
    a NewScreen structure.  NewScreen is a structure that contains
    all of the arguments needed to open a screen.  The NewScreen
    structure may be discarded immediately after OpenScreen() returns.

    The SHOWTITLE flag is set to TRUE by default when a screen is opened.
    To change this, you must call the routine ShowTitle().

    INPUTS
    NewScreen = pointer to an instance of a NewScreen structure.

    New for V36:
    In addition to the information contained in the NewScreen structure,
    Intuition now recognizes extended data passed in the form
    of an array of TagItem structures (from <utility/tagitem.h>),
    commonly called a "tag list."

    There are two ways to provide this array.  The first is to
    use the new Intuition entry point OpenScreenTagList() and
    pass the tag list as a parameter.  This is the recommended
    method, and has a convenient format variation for C programs
    using a variable number of arguments.

    An older way used for some V36 development uses the OpenScreen()
    entry point, and an extension of the NewScreen structure named
    ExtNewScreen.  See the documentation of the flag NS_EXTENDED,
    below.

    While we recommend that you use OpenScreenTagList() rather than
    OpenScreen() when using the extension tag list, we document
    the tag ID values here, so that all parameters for opening
    a screen can be found in one place.

    NewScreen is initialized with the following information:
    -------------------------------------------------------------
    Left = initial x-position of your screen (should be zero for
    releases prior to V36)

    Top = initial y-position of the opening screen
    (Note: Left and Top are specified relative to the Intuition's view,
    in same resolution as the screen pixels.)

    Width = the width for this screen's RastPort

    Height = the height for his screen's RastPort, or the constant
        STDSCREENHEIGHT to get the current default height (at
        this time guaranteed to be at least 200 rows).  The normal
        width and height for a particular system is stored by
        the graphics.library in GfxBase->NormalDisplayRows and
        GfxBase->NormalDisplayColumns.  These values will be different
        depending on factors such as PAL video and overscan.

        For V36, a new constant STDSCREENWIDTH is introduced.  It
        serves the similar function for screen width.  Both
        STDSCREENWIDTH and STDSCREENHEIGHT indicate that your
        screen RastPort is to be the same dimensions as your
        DisplayClip rectangle.  If you do not specify either a
        standard or custom DisplayClip, the OSCAN_TEXT region
        will be used, which corresponds to the standard dimensions
        of V35 and earlier.

        Furthermore, if you are using OpenScreenTagList(), and you
        specify STDSCREENWIDTH, and you DO NOT provide a NewScreen
        pointer, and you DO NOT provide SA_Left, then Intuition
        will automatically set the LeftEdge of the screen to
        be the left edge of the screen's DisplayClip region.
        Likewise for STDSCREENHEIGHT and the screen's TopEdge.

    Depth = number of bitplanes

    DetailPen = pen number for details (like gadgets or text in title bar)
        The common value for this pen is 0.

    BlockPen = pen number for block fills (like title bar)
        The common value for this pen is 1.

    Type = screen type values
        Set these flags as desired from the set:
        CUSTOMSCREEN -- this is your own screen, not a system screen.
        CUSTOMBITMAP -- this custom screen has bit maps supplied
        in the bitmap field of the NewScreen structure.  Intuition is
        not to allocate any raster bitmaps.
        SCREENBEHIND -- your screen will be created behind all other open
        screens.  This allows a program to prepare imagery in the
        screen, change its colors, and so on, bringing it to the
        front when it is presentable.
        SCREENQUIET -- Intuition will not render system screen gadgets or
        screen title.  In concert with the WFLG_RMBTRAP flag on all
        your screen's windows, this flag will prevent Intuition from
        rendering into your screen's bitplanes.  Without WFLG_RMBTRAP
        (or using the IDCMP_MENUVERIFY facility to cancel menu
        operations), this flag will prevent Intuition from clearing
        your menu bar, which is probably unacceptable.  The menu bar
        layer may still overwrite  a portion of your screen bitmap
        when the screen is opened.  (V36: it won't clobber your bits
        any more.)
        NS_EXTENDED for this screen to use extended attributes pointed
        to by the 'Extended' field, below.

    ViewModes = the appropriate argument for the data type ViewPort.Modes.
           These include:
           HIRES for this screen to be HIRES width.
           INTERLACE for the display to switch to interlace.
           SPRITES for this screen to use sprites (the pointer
        sprite is always displayed)
           DUALPF for dual-playfield mode (not supported yet)
        [For V36: The ViewModes field is superceded by a TagItem with
        tag value SA_DisplayID.]

    Font = pointer to the default TextAttr structure for text in this
        screen and all windows that open in this screen.  Text that uses
        this TextAttr includes title bars of both screen and windows,
        string gadgets, and menu titles.  Of course, IntuiText that
        specifies a NULL TextAttr field will use the screen/window default
        fonts.  NOTE: Intuition will *NOT* call OpenDiskFont(), so
        the TextAttr you supply must be in memory.  The ways to ensure
        that are to either use a ROM font (Topaz 8 or 9) or first
        call OpenDiskFont() to load the font, and don't close it
        until after your screen is successfully opened.
        [For V36: this is superceded by SA_Font and SA_SysFont.]

    DefaultTitle = pointer to a line of text that will be displayed along
        the screen's title bar.  Null terminated, or just a NULL pointer
           to get no text
        [For V36: superceded by SA_Title.]

    Gadgets = This field should be set to NULL, since no user gadgets may
        be attached to a screen with the current versions of Intuition.

    CustomBitMap = if you're not supplying a custom bitmap, this value is
           ignored.  However, if you have your own display memory that you
           want used for this screen, the CustomBitMap field should point to
        the BitMap structure that describes your display memory.  See the
           "Screens" chapter and the "Amiga ROM Kernel Manual" for more
           information about bitmaps.
        [For V36: this is superceded by SA_BitMap.]

    [ All TagItem extensions below are new for V36.]
    Extension = if NS_EXTENDED is set in NewScreen.Type, this pointer
        should point to an array (or chain of arrays) of TagItems,
        as defined in the include file <utility/tagitem.h>.   This
        field is only defined in the structure ExtNewScreen.
        The values to use for TagItem.ti_Tag are defined below.  We
        recommend that V36-specific applications use the new Intuition
        entry point OpenScreenTagList(), rather than using this field.
        The ExtNewScreen structure is a convenient way to give V36
        Intuition some information that V34 and earlier Intuition will
        ignore.

        Each TagItem is an optional tagged data structure which identifies
        an additional parameter to OpenScreen().  The applicable tag ID
        values for TagItem.ti_Tag and their corresponding data follow.

        Several of the tag items are alternative (and overriding) versions
        to familiar fields in NewScreen.  They are:

    SA_Left
    SA_Top
    SA_Width
    SA_Height
    SA_Depth
    SA_DetailPen
    SA_BlockPen
    SA_Title
    SA_Font
    SA_Type
    SA_BitMap (whose existence also implies CUSTOMBITMAP).

        Several tags are Booleans, which means that depending on whether
        their corresponding ti_Data field is zero (FALSE) or non-zero
        (TRUE), they specify Boolean attributes.  The ones corresponding
        to Boolean flags in the NewScreen.Type field are:

    SA_ShowTitle
    SA_Behind (equiv. to SCREENBEHIND)
    SA_Quiet (equiv. to SCREENQUIET)

        The following tags provide extended information to Intuition
        when creating a screen:

    SA_DisplayID: ti_Data is a 32-bit extended display mode ID
        as defined in <graphics/displayinfo.h>

    SA_Overscan: ti_Data contains a defined constant specifying
        one of the system standard overscan dimensions appropriate for
        the display mode of the screen.  Used with the Width and
        Height dimensions STDSCREENWIDTH and STDSCREEN, this makes
        it trivial to open an overscanned or standard dimension
        screen.  You may also hand-pick your various dimensions
        for overscanned or other screens, by specifying screen position
        and dimensions explicitly, and by using SA_DClip to explicitly
        specify an overscanned DisplayClip region.

        The values for ti_Data of this tag are as follows:

        OSCAN_TEXT - Text Overscan region.  A region which is completely
        on screen and readable ("text safe").  A preferences data
        setting, this is backward equivalent with the old MoreRows,
        and specifies the DisplayClip and default dimensions of the
        Workbench screen.  This is the default.

        OSCAN_STANDARD - Also a preferences setting, this specifies
        a rectangle whose edges are "just out of view."  This yields
        the most efficient position and dimensions of on-monitor
        presentations, such as games and artwork.

        OSCAN_MAX - This is the largest rectangular region that the
        graphics library can handle "comfortably" for a given mode.
        Screens can smoothly scroll (hardware pan) within this region,
        and any DisplayClip or Screen region within this rectangle
        is also legal.  It is not a preferences item, but reflects
        the limits of the graphics hardware and software.

        OSCAN_VIDEO - This is the largest region that the graphics
        library can display, comfortable or not.  There is no guarantee
        that all smaller rectangles are valid.  This region is
        typically out of sight on any monitor or TV, but provides our
        best shot at "edge-to-edge" video generation.

        Remember, using overscan drastically effects memory use and
        chip memory bandwidth.  Always use the smallest (standard)
        overscan region that works for your application.

    SA_DClip: ti_Data is a pointer to a rectangle which explicitly
        defines a DisplayClip region for this screen.  See QueryOverscan()
        for the role of the DisplayClip region.

        Except for overscan display screens, this parameter is
        unnecessary, and specifying a standard value using SA_Overscan
        is normally an easier way to get overscan.

    SA_AutoScroll: this is a Boolean tag item, which specifies that
        this screens is to scroll automatically when the mouse pointer
        reaches the edge of the screen.  The operation of this requires
        that the screen dimensions be larger than its DisplayClip
        region.

    SA_PubName: If this field is present (and ti_Data is non-NULL),
        it means that the screen is a public screen, and that
        the public screen name string is pointed to by ti_Data.
        Public screens are opened in "PRIVATE" mode and must
        be made public using PubScreenStatus().

    SA_Pens: The ti_Data field (if non-NULL) points to a UWORD
        array of pen specification, as defined for struct DrawInfo.
        This array will be used to initialize the screen's
        DrawInfo.dri_Pens array.

        SA_Pens is also used to decide that a screen is ready
        to support the full-blown "new look" graphics.  If you
        want the 3D embossed look, you must provide this tag,
        and the ti_Data value cannot be NULL.  If it points
        to a "minimal" array, containing just the terminator ~0,
        you can specify "new look" without providing any values
        for the pen array.

    The following two tag items specify the task and signal to be issued
    to notify when the last "visitor" window closes on a public screen.
    This support is to assist envisioned public screen manager programs.

    SA_PubTask:  Task to be signalled.  If absent (and SA_PubSig is
        valid), use the task which called OpenScreen() or
        OpenScreenTagList()).

    SA_PubSig:  Data is a UBYTE signal number (not flag) used to notify
        a task when the last visitor window closes on a public screen.

    SA_Colors: ti_Data points to an array of ColorSpec structures
        (terminated with ColorIndex = -1) which specify initial
        values of the screen's color palette.

    SA_FullPalette: this is a Boolean attribute.  Prior to V36, there
        were just 7 RGB color values that Intuition maintained
        in its user preferences (playfield colors 0-3, and colors
        17-19 for the sprite).  When opening a screen, the color
        map for the screens viewport is first initialized by
        graphics (graphics.library/GetColorMap()) then these
        seven values are overridden to take the preferences values.

        In V36, Intuition maintains a full set of 32 preferences colors.
        If you specify TRUE for SA_FullPalette, Intuition will
        override ALL color map entries with its full suite of
        preferred colors.

    SA_ErrorCode: ti_Data points to a ULONG in which Intuition will
        stick an extended error code if OpenScreen[TagList]() fails.
        Values are of this include 0, for success, and:
        OSERR_NOMONITOR	- monitor for display mode not available.
        OSERR_NOCHIPS	- you need newer custom chips for display mode.
        OSERR_NOMEM		- couldn't get normal memory
        OSERR_NOCHIPMEM	- couldn't get chip memory
        OSERR_PUBNOTUNIQUE	- public screen name already used
        OSERR_UNKNOWNMODE	- don't recognize display mode requested

        NOTE: These values are not the same as some similar return
        values defined in graphics.library/ModeNotAvailable().

    SA_SysFont: ti_Data selects one of the system standard fonts
        specified in preferences.  This tag item overrides the
        NewScreen.Font field and the SA_Font tag item.

        Values recognized in ti_Data at present are:
        0 - old DefaultFont, fixed-width, the default.
        1 - Workbench screen preferred font.  You have to
            be very font sensitive to handle a proportional or
            larger than traditional screen font.

        NOTE WELL: if you select sysfont 1, windows opened on
        your screen will not inherit the screen font, but rather
        the window RastPort will be initialized to the old-style
        DefaultFont (sysfont 0).

    RESULT
    If all is well, returns the pointer to your new screen
    If anything goes wrong, returns NULL, with further error
    specification in the variable pointed to by the SA_ErrorCode
    data field (V36 and later).

    NOTE
    By default, AmigaDOS requesters related to your process are put on
    the Workbench screen (these are messages like "Disk Full").  If
    you wish them to show up on custom screens, DOS must be told.
    This fragment shows the procedure.  More information is available
    in the AmigaDOS manuals.  Sample code fragment:

    #include "libraries/dosextens.h"
        ...
    struct Process	*process;
    struct Window	*window;
    APTR		temp;
        ...
        process = (struct Process *) FindTask(NULL);
        temp = process->pr_WindowPtr;	(save old value)
        process->pr_WindowPtr = (APTR) window;
        ( use a pointer to any open window on your screen )
            ...
        your code goes here
            ...
        process->pr_WindowPtr = temp;
        ( restore value BEFORE CloseWindow() )
        CloseWindow(window);

    BUGS

    SEE ALSO
    OpenScreenTagList(), OpenWindow(), PrintIText(), CloseScreen(),
    QueryOverscan() PubScreenStatus(), The Intuition Reference Manual,
    utility/tagitem.h, graphics.library/ModeNotAvailable(),
    diskfont.library/OpenDiskFont(), graphics.library/GetColorMap()
 intuition.library/OpenScreenTagList       intuition.library/OpenScreenTagList

   NAME
    OpenScreenTagList -- OpenScreen() with TagItem extension array. (V36)
    OpenScreenTags -- Varargs stub for OpenScreenTagList. (V36)

   SYNOPSIS
    Screen = OpenScreenTagList( NewScreen, TagItems )
    D0	  		    A0         A1

    struct Screen *OpenScreenTagList( struct NewScreen *,
        struct TagItem * );

    Screen = OpenScreenTags( NewScreen, Tag1, ... )

    struct Screen *OpenScreenTags( struct NewScreen *,
        ULONG, ... );

   FUNCTION
    Provides an extension to the parameters passed to OpenScreen().
    This extensions is in the form of (a pointer to) an array of
    TagItem structures, which have to fields: ti_Tag, an ID identifying
    the meaning of the other field, ti_Data.  See <utility/tagitem.h>.

    The tag items can supplement or override the values in NewScreen.
    In fact, you can pass a NULL value of the NewScreen pointer.
    For that matter, if you pass NULL in both arguments, you'll get
    a screen with defaults in all fields, including display mode,
    depth, colors, dimension, title, and so on.  We ask that
    you at least supply a title when you open a screen.

    See OpenScreen() documentation for parameter specifications.

   INPUTS
     NewScreen     - (optional) pointer to a NewScreen structure.
     TagItems      - (optional) pointer to (an array of) TagItem
            structures, terminated by the value TAG_END.

   RESULT
     Screen	- an open Intuition screen.  See OpenScreen() for
        extended error codes when Screen is returned NULL.

   EXAMPLE
    The version using a variable number of arguments must be
    created for each particular compiler, and may not have
    an analogue in all versions.  For vanilla, 32-bit C
    parameter passing conventions, this works (and will
    appear in amiga.lib):

    struct Screen	*
    OpenScreenTags( ns, tag1 )
    struct NewScreen	*ns;
    ULONG			tag1;
    {
        struct Screen	*OpenScreenTagList();

        return ( OpenScreenTagList( ns, (struct TagItem *) &tag1 ) );
    }

   NOTES
    We recommend this extension to OpenScreen() over using the
    field ExtNewScreen.Extension.  However, the ExtNewScreen.Extension
    is a convenient way to supply a few tags to V36 Intuition which
    will be ignored by V34 Intuition.  See OpenScreen() documentation
    for lots of details.

   BUGS

   SEE ALSO
    OpenScreen()

 intuition.library/OpenWindow                     intuition.library/OpenWindow

    NAME
    OpenWindow -- Open an Intuition window.

    SYNOPSIS
       Window = OpenWindow( NewWindow )
    D0                   A0

    struct Window *OpenWindow( struct NewWindow * );

    FUNCTION
    Opens an Intuition window of the given dimensions and position,
    with the properties specified in the NewWindow structure.
    Allocates everything you need to get going.

    New for V36: there is an extensive discussion of public Screens
    and visitor windows at the end of this section.  Also,
    you can provide extensions to the NewWindow parameters using
    and array of TagItem structures.  See the discussion below,
    and the documentation for the function OpenScreenTagList().

    Before you call OpenWindow(), you must initialize an instance of
    a NewWindow structure.  NewWindow is a structure that contains
    all of the arguments needed to open a window.  The NewWindow
    structure may be discarded immediately after it is used to open
    the window.

    If Type == CUSTOMSCREEN, you must have opened your own screen
    already via a call to OpenScreen().  Then Intuition uses your screen
    argument for the pertinent information needed to get your window
    going.  On the other hand, if type == one of the Intuition's standard
    screens, your screen argument is ignored.  Instead,
    Intuition will check to see whether or not that screen
    already exists:  if it doesn't, it will be opened first before
    Intuition opens your window in the standard screen.

    New for V36: If you specify Type == WBENCHSCREEN, then your
    window will appear on the Workbench screen, unless the global
    public screen mode SHANGHAI is set, in which case your window
    will be "hijacked" to the default public screen.  See also
    SetPubScreenModes().

    New for V36: If the WFLG_NW_EXTENDED flag is set, it means that the
    field 'ExtNewWindow->Extension' points to an array of TagItems, as
    defined in intuition/tagitem.h.  This provides an extensible means
    of providing extra parameters to OpenWindow.  For compatibility
    reasons, we could not add the 'Extension' field to the NewWindow
    structure, so we have define a new structure ExtNewWindow, which
    is identical to NewWindow with the addition of the Extension field.

    We recommend that rather than using ExtNewWindow.Extension, you
    use the new Intuition function OpenWindowTagList() and its
    varargs equivalent OpenWindowTags().  We document the window
    attribute tag ID's (ti_Tag values) here, rather than in
    OpenWindowTagList(), so that you can find all the parameters
    for a new window defined in one place.

    If the WFLG_SUPER_BITMAP flag is set, the bitmap variable must point
    to your own bitmap.

    The DetailPen and the BlockPen are used for system rendering; for
    instance, the title bar is first filled using the BlockPen, and then
    the gadgets and text are rendered using DetailPen.  You can either
    choose to supply special pens for your window, or, by setting either
    of these arguments to -1, the screen's pens will be used instead.

    Note for V36: The DetailPen and BlockPen no longer determine
    what colors will be used for window borders, if your window
    opens on a "full-blown new look screen."

    INPUTS
    NewWindow = pointer to an instance of a NewWindow structure.  That
               structure is initialized with the following data:
   -------------------------------------------------------------------------
    Left = the initial x-position for your window
    Top = the initial y-position for your window
    Width = the initial width of this window
    Height = the initial height of this window

    DetailPen = pen number (or -1) for the rendering of window details
         (like gadgets or text in title bar)
    BlockPen = pen number (or -1) for window block fills (like title bar)
    [For V36: Title bar colors are determined otherwise.]

    Flags = specifiers for your requirements of this window, including:
         which system gadgets you want attached to your window:

        - WFLG_DRAGBAR allows this window to be dragged
        - WFLG_DEPTHGADGET lets the user depth-arrange this window
        - WFLG_CLOSEGADGET attaches the standard close gadget
        - WFLG_SIZEGADGET allows this window to be sized.

        If you ask for the WFLG_SIZEGADGET gadget, you must specify one or
        both of the flags WFLG_SIZEBRIGHT and WFLG_SIZEBBOTTOM below; if
        you don't, the default is WFLG_SIZEBRIGHT.  See the following items
        WFLG_SIZEBRIGHT and WFLG_SIZEBBOTTOM for more details.

        - WFLG_SIZEBRIGHT is a special system gadget flag that
          you set to specify whether or not you want the
          RIGHT border adjusted to account for the physical size
          of the sizing gadget.  The sizing gadget must, after
          all, take up room in either the right or bottom border
          (or both, if you like) of the window.  Setting either
          this or the WFLG_SIZEBBOTTOM flag selects which edge
          will take up the slack.  This will be particularly
          useful to applications that want to use the extra space
          for other gadgets (like a proportional gadget and two
          Booleans done up to look like scroll bars) or, for
          for instance, applications that want every possible
          horizontal bit and are willing to lose lines vertically.
          NOTE:  if you select WFLG_SIZEGADGET, you must select
          either WFLG_SIZEBRIGHT or WFLG_SIZEBBOTTOM or both.  If
          you select neither, the default is WFLG_SIZEBRIGHT.
        - WFLG_SIZEBBOTTOM is a special system gadget flag that
          you set to specify whether or not you want the
          BOTTOM border adjusted to account for the physical size
          of the sizing gadget.  For details, refer to
          WFLG_SIZEBRIGHT above.

        - WFLG_GIMMEZEROZERO for easy but expensive output

        what type of window layer you want, either:
        - WFLG_SIMPLE_REFRESH
        - WFLG_SMART_REFRESH
        - WFLG_SUPER_BITMAP

        - WFLG_BACKDROP for whether or not you want this window to be one
          of Intuition's special backdrop windows.  See WFLG_BORDERLESS
          as well.

        - WFLG_REPORTMOUSE for whether or not you want to "listen" to
          mouse movement events whenever your window is the active
          one.  After you've opened your window, if you want to change
          you can later change the status of this via a call to
          ReportMouse().  Whether or not your window is listening to
          mouse is affected by gadgets too, since they can cause you
          to start getting reports too if you like.  The mouse move
          reports (either InputEvents or messages on the IDCMP) that
          you get will have the x/y coordinates of the current mouse
          position, relative to the upper-left corner of your window
          (WFLG_GIMMEZEROZERO notwithstanding).  This flag can work in
          conjunction with the IDCMP Flag called IDCMP_MOUSEMOVE, which
          allows you to listen via the IDCMP.

        - WFLG_BORDERLESS should be set if you want a window with no
          border padding.  Your window may have the border variables
          set anyway, depending on what gadgetry you've requested for
          the window, but you won't get the standard border lines and
          spacing that comes with typical windows.

          This is a good way to take over the entire screen, since you
          can have a window cover the entire width of the screen using
          this flag.  This will work particularly well in conjunction
          with the WFLG_BACKDROP flag (see above), since it allows you
          to open a window that fills the ENTIRE screen.  NOTE:  this is
          not a flag that you want to set casually, since it may cause
          visual confusion on the screen.  The window borders are the
          only dependable visual division between various windows and
          the background screen.  Taking away that border takes away
          that visual cue, so make sure that your design doesn't need
          it at all before you proceed.

        - WFLG_ACTIVATE is the flag you set if you want this window to
          automatically become the active window.  The active
          window is the one that receives input from the keyboard and
          mouse.  It's usually a good idea to to have the window you
          open when your application first starts up be an ACTIVATED
          one, but all others opened later not be ACTIVATED (if the
          user is off doing something with another screen, for
          instance, your new window will change where the input is
          going, which would have the effect of yanking the input rug
          from under the user).  Please use this flag thoughtfully and
          carefully.

          Some notes: First, your window may or may not be active
          by the time this function returns.  Use the IDCMP_ACTIVEWINDOW
          IDCMP message to know when your window has become active.
          Also, be very careful not to mistakenly specify the
          obsolete flag names WINDOWACTIVE or ACTIVEWINDOW.  These are
          used in other contexts, and their values unintentionally added
          to your flags can cause most unfortunate results.  To avoid
          confusion, they are now know as WFLG_WINDOWACTIVE and
          IDCMP_ACTIVEWINDOW.

        - WFLG_RMBTRAP, when set, causes the right mouse button events
          to be trapped and broadcast as events.  You can receive
          these events through either the IDCMP or the console.

        - WFLG_NOCAREREFRESH indicates that you do not wish to
          be responsible for calling BeginRefresh() and EndRefresh()
          when your window has exposed regions (i.e., when the
          IDCMP_REFRESHWINDOW message would be generated).  See also
          the descriptions of these two functions.

        - WFLG_NW_EXTENDED (V36) indicates that NewWindow in fact points
          to an ExtNewWindow structure, and that the 'Extension'
          field points to an array of TagItem structures, with
          meaning described below.

    IDCMPFlags = IDCMP is the acronym for Intuition Direct Communications
        Message Port.  (It's Intuition's sole acronym.) If any of the
        IDCMP Flags is selected, Intuition will create a pair of
        message ports and use them for direct communications with the
        task opening this window (as compared with broadcasting
        information via the Console device).  See the "Input and
        Output Methods" chapter of the Intuition Reference Manual for
        complete details.

        You request an IDCMP by setting any of these flags.  Except
        for the special VERIFY flags, every other flag you set tells
        Intuition that if a given event occurs which your program
        wants to know about, it is to broadcast the details of that
        event through the IDCMP rather than via the Console device.
        This allows a program to interface with Intuition directly,
        rather than going through the Console device.

        Many programs have elected to use IDCMP communication
        exclusively, and not to associate a console with their
        windows at all.  Some operations, such as IDCMP_MENUVERIFY,
        can ONLY be achieved using IDCMP.

            The IDCMP flags you can set are:

        - IDCMP_REQVERIFY is the flag which, like IDCMP_SIZEVERIFY and ...

        - IDCMP_MENUVERIFY (see immediately below), specifies that you
          want to make sure that your graphical state is quiescent
          before something extraordinary happens.  In this case, the
          extraordinary event is that a rectangle of graphical data is
          about to be blasted into your Window.  If you're drawing
          directly into its screen, you probably will wish to make sure
          that you've ceased drawing before the user is allowed to bring
          up the DMRequest you've set up, and the same for when system
          has a request for the user.  Set this flag to ask for that
          verification step.

        - IDCMP_REQCLEAR is the flag you set to hear a message whenever
          a requester is cleared from your window.  If you are using
          IDCMP_REQVERIFY to arbitrate access to your screen's bitmap, it
          is safe to start your output once you have heard an
          IDCMP_REQCLEAR for each IDCMP_REQSET.

        - IDCMP_REQSET is a flag that you set to receive a broadcast
          for each requester that is opened in your window.  Compare
          this with IDCMP_REQCLEAR above.  This function is distinct
          from IDCMP_REQVERIFY.  This functions merely tells you that a
          requester has opened, whereas IDCMP_REQVERIFY requires you to
          respond before the requester is opened.

        - IDCMP_MENUVERIFY is the flag you set to have Intuition stop
          and wait for you to finish all graphical output to your
          window before rendering the menus.  Menus are currently
          rendered in the most memory-efficient way, which involves
          interrupting output to all windows in the screen before the
          menus are drawn.  If you need to finish your graphical
          output before this happens, you can set this flag to make
          sure that you do.

        - IDCMP_SIZEVERIFY means that you will be doing output to your
          window which depends on a knowledge of the current size of the
          window.  If the user wants to resize the window,  you may want
          to make sure that any queued output completes before the sizing
          takes place (critical text, for instance).  If this is the
          case, set this flag.   Then, when the user wants to size,
          Intuition will send you the IDCMP_SIZEVERIFY message and Wait()
          until you reply that it's OK to proceed with the sizing. NOTE:
          when we say that Intuition will Wait() until you reply, what
          we're really saying is that user will WAIT until you reply, which
          suffers the great negative potential of User-Unfriendliness.
          So remember:  use this flag sparingly, and, as always with any
          IDCMP Message you receive, reply to it promptly!  Then, after
          user has sized the window, you can find out about it using
          IDCMP_NEWSIZE.

        With all the "VERIFY" functions, it is not save to leave them
        enabled at any time when your task may not be able to respond
        for a long period.

        It is NEVER safe to call AmigaDOS, directly or indirectly, when
        a "VERIFY" function is active.  If AmigaDOS needs to put up a
        disk requester for you, your task might end up waiting for the
        requester to be satisfied, at the same time as Intuition is
        waiting for your response.  The result is a complete machine
        lockup.  USE ModifyIDCMP() TO TURN OFF ANY VERIFY MESSAGES
        BEFORE CALLING dos.library!!

        For V36: If you do not respond to the verification IntuiMessages
        within the user specified timeout duration, Intuition will abort
        the operation.  This eliminates the threat of these easy
        deadlocks, but can result in a confused user.  Please try
        hard to continue to avoid "logical deadlocks".

        - IDCMP_NEWSIZE is the flag that tells Intuition to send an IDCMP
          message to you after the user has resized your window.  At
          this point, you could examine the size variables in your
          window structure to discover the new size of the window.
          See also the IDCMP_CHANGEWINDOW IDCMP flag.

        - IDCMP_REFRESHWINDOW when set will cause a message to be sent
          whenever your window needs refreshing.  This flag makes
          sense only with WFLG_SIMPLE_REFRESH and WFLG_SMART_REFRESH
          windows.

        - IDCMP_MOUSEBUTTONS will get reports about mouse-button up/down
          events broadcast to you (Note:  only the ones that
          don't mean something to Intuition.  If the user clicks the
          select button over a gadget, Intuition deals with it and you
          don't find out about it through here).

        - IDCMP_MOUSEMOVE will work only if you've set the
          WFLG_REPORTMOUSE flag above, or if one of your gadgets has the
          GACT_FOLLOWMOUSE flag set.  Then all mouse movements will be
          reported here, providing your window is active.

        - IDCMP_GADGETDOWN means that when the User "selects" a gadget
          you've created with the GACT_IMMEDIATE flag set, the fact
          will be broadcast through the IDCMP.

        - IDCMP_GADGETUP means that when the user "releases" a gadget that
          you've created with the GACT_RELVERIFY flag set, the fact
          will be broadcast through the IDCMP.  This message is
          only generated if the release is "good", such as releasing
          the select button over a Boolean gadget, or typing ENTER
          in a string gadget.

        - IDCMP_MENUPICK selects that menu number data will be sent via
          the IDCMP.

        - IDCMP_CLOSEWINDOW means broadcast the IDCMP_CLOSEWINDOW event
          through the IDCMP rather than the console.

        - IDCMP_RAWKEY selects that all IDCMP_RAWKEY events are
          transmitted via the IDCMP.  Note that these are absolutely RAW
          keycodes, which you will have to translate before using.
          Setting this and the MOUSE flags effectively eliminates the need
          to open a Console device to get input from the keyboard and
          mouse.  Of course, in exchange you lose all of the console
          features, most notably the "cooking" of input data and
          the systematic output of text to your window.

        - IDCMP_VANILLAKEY is for developers who don't want the hassle
          of IDCMP_RAWKEYS.  This flag will return all the keycodes after
          translation via the current country-dependent keymap.  When
          you set this flag, you will get IntuiMessages where the Code
          field has a decoded ANSI character code representing the key
          struck on the keyboard.  Only codes that map to a single
          character are returned: you can't read such keys as HELP or
          the function keys with IDCMP_VANILLAKEY.

          NOTE FOR V36: If you have both IDCMP_RAWKEY and IDCMP_VANILLAKEY
          set, Intuition will send an IDCMP_RAWKEY event for those
          *downstrokes* which do not map to single-byte characters
          ("non-vanilla" keys).  In this way you can easily detect cursor
          keys, function keys, and the Help key without sacrificing the
          convenience of IDCMP_VANILLAKEY.

        - IDCMP_INTUITICKS gives you simple timer events from Intuition
          when your window is the active one; it may help you avoid
          opening and managing the timer device.  With this flag set,
          you will get only one queued-up INTUITICKS message at a
          time.  If Intuition notices that you've been sent an
          IDCMP_INTUITICKS message and haven't replied to it, another
          message will not be sent.  Intuition receives timer events and
          considers sending you an IDCMP_INTUITICKS message approximately
          ten times a second.

        - IDCMP_DELTAMOVE gives raw (unscaled) input event delta X/Y
          values.  This is so you can detect mouse motion regardless of
          screen/window/display boundaries.  This works a little
          strangely: if you set both IDCMP_MOUSEMOVE and IDCMP_DELTAMOVE.
          IDCMPFlags, you will get IDCMP_MOUSEMOVE messages with delta
          x/y values in the MouseX and MouseY fields of the
          IDCMPMessage.

        - IDCMP_NEWPREFS indicates you wish to be notified when the
          system-wide Preferences changes.  For V36, there is a new
          environment mechanism to replace Preferences, which we
          recommend you consider using instead.

        - Set IDCMP_ACTIVEWINDOW and IDCMP_INACTIVEWINDOW to get messages
          when those events happen to your window.  Take care not to
          confuse this "ACTIVEWINDOW" with the familiar sounding, but
          totally different "WINDOWACTIVE" flag.  These two flags have
          been supplanted by "IDCMP_ACTIVEWINDOW" and "WFLG_WINDOWACTIVE".
          Use the new equivalent terms to avoid confusion.

        - Set IDCMP_DISKINSERTED or IDCMP_DISKREMOVED to learn when
          removable disks are inserted or removed, respectively.

        - IDCMP_IDCMPUPDATE is a new class for V36 which is used as
          a channel of communication from custom and boopsi gadgets
          to your application.

        - IDCMP_CHANGEWINDOW is a new class for V36 that will be sent
          to your window whenever its dimensions or position are changed
          by the user or the functions SizeWindow(), MoveWindow(),
          ChangeWindowBox(), or ZipWindow().

        - IDCMP_MENUHELP is new for V37.  If you specify the WA_MenuHelp
          tag when you open your window, then when the user presses the
          HELP key on the keyboard during a menu session, Intuition will
          terminate the menu session and issue this even in place of an
          IDCMP_MENUPICK message.
        - NEVER follow the NextSelect link for MENUHELP messages.
        - You will be able to hear MENUHELP for ghosted menus.
          (This lets you tell the user why the option is ghosted.)
        - Be aware that you can receive a MENUHELP message whose code
          corresponds to a menu header or an item that has sub-items
          (which does not happen for MENUPICK).  The code may also be
          MENUNULL.
        - LIMITATION:  if the user extend-selects some checkmarked
          items with the mouse, then presses MENUHELP, your
          application will only hear the MENUHELP report.  You
          must re-examine the state of your checkmarks when you
          get a MENUHELP.
        - Availability of MENUHELP in V36 is not directly
          controllable.  We apologize...

    Gadgets = the pointer to the first of a linked list of the your own
          Gadgets which you want attached to this Window.  Can be NULL
          if you have no Gadgets of your own

       CheckMark = a pointer to an instance of the struct Image where can
          be found the imagery you want used when any of your
          menu items is to be checkmarked.  If you don't want to
          supply your own imagery and you want to just use
          Intuition's own checkmark, set this argument to NULL

       Text = a null-terminated line of text to appear on the title bar of
          your window (may be null if you want no text)

       Type = the screen type for this window.  If this equal CUSTOMSCREEN,
          you must have already opened a CUSTOMSCREEN (see text above).
          Types available include:
          - WBENCHSCREEN
          - CUSTOMSCREEN
          - PUBLICSCREEN (new for V36, see text below)

       Screen = if your type is one of Intuition's standard screens, then
          this argument is ignored.  However, if Type == CUSTOMSCREEN,
          this must point to the structure of your own screen

       BitMap = if you have specified WFLG_SUPER_BITMAP as the type of
           refreshing you want for this window, then this value points to a
           instance of the struct bitmap.  However, if the refresh type
           is NOT WFLG_SUPER_BITMAP, this pointer is ignored.

       MinWidth, MinHeight, MaxWidth, MaxHeight = the size limits for this
          window.  These must be reasonable values, which is to say that
          the minimums cannot be greater than the current size, nor can
          the maximums be smaller than the current size.  If they are,
          they're ignored.  Any one of these can be initialized to zero,
          which means that that limit will be set to the current
          dimension of that axis.  The limits can be changed after the
          Window is opened by calling the WindowLimits() routine.

          NOTE: ORIGINALLY, we stated that:

          "If you haven't requested the WFLG_SIZEGADGET option, these
          variables are ignored so you don't have to initialize them."

          It is now clear that a variety of programs take it upon
          themselves to call SizeWindow() (or ChangeWindowBox()) without
          your program's consent or consulting your WFLG_SIZEGADGE
          option.  To protect yourself against the results, we strongly
          urge that if you supply suitable values for these fields even
          if you do not specify WFLG_SIZEGADGET.

          The maximums may be LARGER than the current size, or even
          larger than the current screen.  The maximums should be set to
          the highest value your application can handle.  This allows
          users with larger display devices to take full advantage of
          your software.  If there is no good reason to limit the size,
          then don't.  -1 or ~0 indicates that the maximum size is only
          limited by the size of the window's screen.

          See also the docs on the function WindowLimits() for more
          information.

       Extension (New for V36) = a pointer to an array (or chain of arrays)
        of TagItems to specify additional parameters to OpenWindow().
        TagItems in general are described in utility/tagitem.h,
        and the OpenWindow tags are defined in intuition/intuition.h
        and described here.  For items pertaining to Public Screens
        and visitor windows, please see below.

    Here are the TagItem.ti_Tag values that are defined for OpenWindow
    (and OpenWindowTagList()).

    Certain tags simply override equivalent values in NewWindow,
    and allow you to open a window using OpenWindowTagList() without
    having a NewWindow structure at all.  In each case, cast
    the corresponding data to ULONG and put it in ti_Data.

    The compatible tag items include:

    WA_Left
    WA_Top
    WA_Width
    WA_Height
    WA_DetailPen
    WA_BlockPen
    WA_IDCMP
    WA_Flags	- initial values for Flags before looking at other
            Boolean component Tag values
    WA_Gadgets
    WA_Checkmark
    WA_Title
    WA_CustomScreen - also implies CUSTOMSCREEN property
    WA_SuperBitMap - also implies WFLG_SUPER_BITMAP refresh mode.
    WA_MinWidth
    WA_MinHeight
    WA_MaxWidth
    WA_MaxHeight

    These Boolean tag items are alternatives to the NewWindow.Flags
    Boolean attributes with similar names.

    WA_SizeGadget		- equivalent to WFLG_SIZEGADGET
    WA_DragBar		- equivalent to WFLG_DRAGBAR
    WA_DepthGadget		- equivalent to WFLG_DEPTHGADGET
    WA_CloseGadget		- equivalent to WFLG_CLOSEGADGET
    WA_Backdrop		- equivalent to WFLG_BACKDROP
    WA_ReportMouse		- equivalent to WFLG_REPORTMOUSE
    WA_NoCareRefresh 	- equivalent to WFLG_NOCAREREFRESH
    WA_Borderless		- equivalent to WFLG_BORDERLESS
    WA_Activate		- equivalent to WFLG_ACTIVATE
    WA_RMBTrap		- equivalent to WFLG_RMBTRAP
    WA_WBenchWindow		- equivalent to WFLG_WBENCHWINDOW
                  (system PRIVATE)
    WA_SimpleRefresh 	- only specify if TRUE
    WA_SmartRefresh 	- only specify if TRUE
    WA_SizeBRight		- equivalent to WFLG_SIZEBRIGHT
    WA_SizeBBottom		- equivalent to WFLG_SIZEBBOTTOM
    WA_GimmeZeroZero 	- equivalent to WFLG_GIMMEZEROZERO

    The following tag items specify new attributes of a window.

    WA_ScreenTitle - You can specify the screen title associated
        with your window this way, and avoid a call to SetWindowTitles()
        when your window opens.

    WA_AutoAdjust - a Boolean attribute which says that it's OK
        to move or even shrink the dimensions of this window
        to fit it on the screen, within the dimension
        limits specified by MinWidth and MinHeight.
        Someday, this processing might be sensitive to the
        currently visible portion of the screen the window
        will be opening on, so don't draw too many conclusions
        about the auto-adjust algorithms.
        (Normally, this attribute defaults to FALSE.  However,
        if you call OpenWindowTags() or OpenWindowTagList()
        with a NULL NewWindow pointer, this attribute defaults
        to TRUE).

    WA_InnerWidth
    WA_InnerHeight - You can specify the dimensions of the interior
        region of your window, independent of what the border
        thicknesses will be.  You probably want to specify
        WA_AutoAdjust to allow Intuition to move your window
        or even shrink it so that it is completely on screen.

        Note: using these tags puts some reasonable restrictions
        on the gadgets you can specify as "border" gadgets when
        you open your window.  Since border gadgets determine
        the border dimensions and hence the overall dimensions of
        your window, those dimensions cannot be used calculating
        the position or dimensions of border gadgets.

        Here's the complete list of restrictions:
        - GACT_LEFTBORDER gadgets cannot be GFLG_RELWIDTH if
          WA_InnerWidth is used.
        - GACT_RIGHTBORDER gadgets MUST be GFLG_RELRIGHT if
          WA_InnerWidth is used.
        - GACT_TOPBORDER gadgets cannot be GFLG_RELHEIGHT if
          WA_InnerHeight is used.
        - GACT_BOTTOMBORDER gadgets MUST be GFLG_RELBOTTOM if
          WA_InnerHeight is used.

    WA_PubScreenName - This tag item declares that you want your window
        to open as a visitor window on the public screen whose name
        is pointed to by (UBYTE *) ti_Data.

    WA_PubScreen - Open as a visitor window on the public screen
        whose address if provided as (struct Screen *) ti_Data.
        To ensure that this screen remains open long enough, you
        must either:
        1) Be the screen's owner
        2) have another window already open on the screen
        3) use LockPubScreen()
        Using exec.library/Forbid() is not sufficient.

        You can provide ti_Data to be NULL (zero), without any
        of the above precautions, to specify the default public screen.

    WA_PubScreenFallBack - This Boolean attribute specifies that a
        visitor window should "fall back" to opening on the default
        public screen if the explicitly specify public screen is not
        available.

    WA_WindowName - this visionary specification of a window
        rendezvous name string is not yet implemented.

    WA_Colors - this equally great idea about associating a palette
        specification with the active window may not ever be implemented.

    WA_Zoom - ti_Data points to an array of four WORD's to be used
        as the initial Left/Top/Width/Height of the "alternate
        Zoom position and dimensions."  The presence of this tag
        item implies that you want a Zoom gadget, even though you
        might not have a sizing gadget.

    WA_MouseQueue - This tag specifies a limit for the number
        of outstanding IDCMP_MOUSEMOVE IntuiMessages that Intuition
        will send to your window.  You can change the value of this
        limit after the window is open using SetMouseQueue().

    WA_RptQueue - This tag specifies a limit for the number of
        outstanding repeated-IDCMP_RAWKEY, repeated-IDCMP_VANILLAKEY,
        and repeated-IDCMP_IDCMPUPDATE IntuiMessages that Intuition will
        send to your window.  Currently, there is no function to adjust
        the repeat-key queue.

    WA_BackFill - ti_Data is a pointer to a Hook structure that
        the Layers library will call when your window needs
        "backfilling."  See layers.library/InstallLayerHook().

     WA_MenuHelp - ti_Data is a boolean.  If true, enables the MenuHelp
        feature for this window.  See IDCMP_MENUHELP above.  (Ignored
        in V36 and earlier).

   NOTES
    Regarding Public Screens, you can specify a window to be a
    "visitor window" on a public screen in one of several ways.
    In each case, you must be sure not to specify a NewWindow
    type of CUSTOMSCREEN.  You should use the value PUBLICSCREEN.

    There are actually several ways you can specify which screen
    you want a visitor window to be opened on:

        1) Specify the name of the public screen WA_PubScreenName,
        or a NULL pointer, in ti_Data.  The name might have been
        provided by the user.  A NULL pointer means to use the
        default public screen.

        If the named screen cannot be found, the default public screen
        will be used if the Boolean attribute WA_PubScreenFallBack
        is TRUE.

        2) Specify a pointer to a public screen using the
        WA_PubScreen tag item.  The WA_PubScreenFallBack
        attribute has no effect.  You can specify the default
        public screen by providing a NULL pointer.

        You can also specify the pointer by setting NewWindow.Type
        to PUBLICSCREEN, and specifying the public screen pointer
        in NewWindow.Screen.  The WA_PubScreen tag item has precedent
        over this technique.

        Unless NULL, the screen pointer provided MUST be a valid
        public screen.  You may ensure this several ways:

        - Be the owner of the screen.
        - Have a window already open on the screen.
        - Use LockPubScreen() to prevent the screen from closing.
        - specifying the WFLG_VISITOR bit in NewWindow.Flags is not
          supported.

        It is anticipated that the last will be the most common method
        of opening public screens because you often want to examine
        properties of the screen your window will be using in order
        to compensate for differences in dimension, depth, and font.

        The standard sequence for this method is as follows:
        LockPubScreen()	- obtain a pointer and a promise
        layout window	- adapt your window to the screen you will use
        OpenWindow()	- using the pointer you specify
        UnlockPubScreen()	- once your window is open, you can let go
                  of the lock on the public screen
        ... normal window even processing ...
        CloseWindow().

    Regarding "service" windows, such as those opened for a system
    requester or file requester associated with a given "client"window.
    These windows should NOT be "visitor" windows.  Open them
    using NewWindow.Type = CUSTOMSCREEN and NewWindow.Screen
    equal to the screen of the client window (window->WScreen).
    You can also use WA_CustomScreen, which has precedence.

    This ensures that the requester service window will be allowed to
    open on the same screen as the client window, even if that
    screen is not a public screen, or has private status.

    This has an implication for service/client protocol: when you
    pass a window pointer to any system requester routine or
    to a routine which creates some other other service window,
    you MUST keep your window open until the client window
    is closed.

    If a requester service will allow a NULL client window, this
    should indicate to open the service window on the default public
    screen (probably Workbench).  The correct way to get a pointer
    to this screen is to call LockPubScreen( NULL ).  In this
    case, you want to open as a visitor window, which means you
    should use either PUBLICSCREEN or WA_PubScreen, described above.
    You should call UnlockPubScreen() after your visitor window is open.

    As of V36, gadgets in the right and bottom border
    (specified with GACT_RIGHTBORDER and GACT_BOTTOMBORDER) only
    contribute to the dimensions of the borders if they are also
    GFLG_RELRIGHT and GFLG_RELBOTTOM, respectively.

    RESULT
    If all is well, returns the pointer to your new Window
    If anything goes wrong, returns NULL

    BUGS
    When you open a window, Intuition will set the font of
    the window's RastPort to the font of the window's screen.
    This does not work right for GimmeZeroZero windows: the
    BorderRPort RastPort has the font set correctly, but
    Window.RPort is set up with the system default font.
    For compatibility reasons, we won't be fixing this problem.

    Also, there is a compatibility trick going on with the
    default font of your window's RastPort if the screen's
    font is "fancy."  See the SA_SysFont attribute described
    under OpenScreen().

    Unless you arrange otherwise, each window you open will allocate
    a signal for your task from the 16 "user signals."
    If no signal is available, your window will not be able
    to be opened.  In early V36 versions and before, Intuition didn't
    check this condition, but just left you with an unusable port.

    SEE ALSO
       OpenWindowTagList(), OpenScreen(), ModifyIDCMP(), SetWindowTitles(),
    LockPubScreen(), SetDefaultPubScreen(), ZipWindow(),
    layers.library/InstallLayerHook(), SetPubScreenModes()
 intuition.library/OpenWindowTagList       intuition.library/OpenWindowTagList

   NAME
    OpenWindowTagList -- OpenWindow() with TagItem extension. (V36)
    OpenWindowTags -- Varargs stub for OpenWindowTagList (V36)

   SYNOPSIS
    Window = OpenWindowTagList( NewWindow, TagItems )
    D0	  		    A0         A1

    struct Window *OpenWindowTagList( struct NewWindow *,
        struct TagItem * );

    Window = OpenWindowTags( NewWindow, Tag1, ... )

    struct Window *OpenWindowTags( struct NewWindow *, ULONG, ... );

   FUNCTION
    A variation of OpenWindow() that allow direct specification of
    a TagItem array of extension data.  Recommended over using the
    ExtNewWindow.Extension field.

    If you omit the NewWindow (pass NULL), a set of defaults
    are used, and overridden by the tag items.  Even without
    any tag items at all, a reasonable window opens on the Workbench
    or default public screen.

    See OpenWindow() for all the details.

   INPUTS
     NewWindow - (optional) pointer to a NewWindow structure.
    TagItems - (optional) pointer to TagItem array, with tag
        values as described under the description for
        OpenWindow().

   RESULT
     Window - newly created window, per your specifications.

   EXAMPLE
    See OpenScreenTagList() for an example of how to create
    a "varargs" version of this function for convenient C
    language programming.

   NOTES

   BUGS

   SEE ALSO
    OpenWindow()

 intuition.library/OpenWorkBench               intuition.library/OpenWorkBench

    NAME
    OpenWorkBench -- Open the Workbench screen.

    SYNOPSIS
    WBScreen = OpenWorkBench()
    D0

    ULONG OpenWorkBench( VOID );

    FUNCTION
    This routine attempts to reopen the Workbench.  The actions taken are:
        - general good stuff and nice things, and then return a non-null
          pointer to the Workbench screen.
        - find that something has gone wrong, and return NULL

    The return value, if not NULL, is indeed the address of the Workbench
    screen, although you should not use it as such.  This is because the
    Workbench may be closed by other programs, which can invalidate
    the address at any time.  We suggest that you regard the return
    value as a ULONG indication that the routine has succeeded, if
    you pay any attention to it at all.

    INPUTS
    None

    RESULT
    non-zero if Workbench screen opened successfully, or was already
        opened
    zero if anything went wrong and the Workbench screen isn't out there

    BUGS
    The name of this routine is spelled wrong: it ought to have been
    OpenWorkbench().

    SEE ALSO

 intuition.library/PointInImage                 intuition.library/PointInImage

   NAME
    PointInImage -- Tests whether an image "contains" a point. (V36)

   SYNOPSIS
    DoesContain = PointInImage( Point, Image )
    D0	  		    D0     A0

    BOOL PointInImage( struct Point, struct Image * );

   FUNCTION
    Tests whether a point is properly contained in an image.
    The intention of this is to provide custom gadgets a means
    to delegate "image mask" processing to the Image, where
    it belongs (superceding things like BOOLMASK).  After all,
    a rounded rect image with a drop shadow knows more about
    what points are inside it than anybody else should.

    For traditional Intuition Images, this routine checks if
    the point is in the Image box (LeftEdge/RightEdge/Width/Height).

   INPUTS
     Point	- Two words, X/Y packed into a LONG, with high word
        containing 'X'.  This is what you get if you pass
        a Point structure (not a pointer!) using common
        C language parameter conventions.
    Image - a pointer to a standard or custom Image data object.
        NOTE: If 'Image' is NULL, this function returns TRUE.

   RESULT
     DoesContain - Boolean result of the test.

   EXAMPLE

   NOTES

   BUGS
    Only applies to the first image, does not follow NextImage
    linked list.  This might be preferred.

   SEE ALSO

 intuition.library/PrintIText                     intuition.library/PrintIText

    NAME
    PrintIText -- Print text described by the IntuiText argument.

    SYNOPSIS
    PrintIText( RastPort, IText, LeftOffset, TopOffset )
            A0        A1     D0          D1

    VOID PrintIText( struct RastPort *, struct IntuiText *, WORD, WORD );

    FUNCTION
    Prints the IntuiText into the specified RastPort.  Sets up the RastPort
    as specified by the IntuiText values, then prints the text into the
    RastPort at the IntuiText x/y coordinates offset by the left/top
    arguments.  Note, though, that the IntuiText structure itself
    may contain further text position coordinates: those coordinates
    and the Left/TopOffsets are added to obtain the true position of
    the text to be rendered.

    This routine does window layer clipping as appropriate -- if you
    print text outside of your window, your characters will be
    clipped at the window's edge, providing you pass your window's
    (layered) RastPort.

    If the NextText field of the IntuiText argument is non-NULL,
    the next IntuiText is rendered as well, and so on until some
    NextText field is NULL.

    IntuiText with the ITextFont field NULL are displayed in the
    font of the RastPort.  If the RastPort font is also NULL, the
    system default font, as set via the Preferences tool, will be used.

    INPUTS
    RastPort = the RastPort destination of the text
    IText = pointer to an instance of the structure IntuiText
    LeftOffset = left offset of the IntuiText into the RastPort
    TopOffset = top offset of the IntuiText into the RastPort

    RESULT
    None

    BUGS

    SEE ALSO

 intuition.library/PubScreenStatus           intuition.library/PubScreenStatus

    NAME
    PubScreenStatus -- Change status flags for a public screen. (V36)

    SYNOPSIS
    ResultFlags = PubScreenStatus( Screen, StatusFlags )
    D0		   	       A0      D0

    UWORD PubScreenStatus( struct Screen *, UWORD );

    FUNCTION
    Changes status flags for a given public screen.

    Do not apply this function to a screen if your program
    isn't the screen's "owner", in particular, don't call
    this function for the Workbench screen.

    INPUTS
    Screen = pointer to public screen
    StatusFlags = values currently:
      PSNF_PRIVATE: make this screen unavailable to visitor windows

    RESULT
    Returns 0 in the lowest order bit of the return value
    if the screen wasn't public, or because it can not be taken
    private because visitors are open in it.

    All other bits in the return code are reserved for future
    enhancement.

    BUGS

    SEE ALSO
    OpenScreen(), Intuition V36 update documentation
 intuition.library/QueryOverscan               intuition.library/QueryOverscan

    NAME
    QueryOverscan -- Inquire about a standard overscan region. (V36)

    SYNOPSIS
    success = QueryOverscan( DisplayID, Rect, OScanType )
    D0                       A0         A1    D0

    LONG QueryOverscan( ULONG, struct Rectangle *, WORD );

    FUNCTION
    This function fills in a rectangle with one of the system
    overscan dimensions, scaled appropriately for the mode of
    the DisplayID it is passed.

    There are three types of system overscan values:
    OSCAN_TEXT: completely visible, by user preference.  Used
      for Workbench screen and screen dimensions STDSCREENWIDTH
      and STDSCREENHEIGHT.  Left/Top is always 0,0.
    OSCAN_STANDARD: just beyond visible bounds of monitor, by
      user preference.  Left/Top may be negative.
    OSCAN_MAX: The largest region we can display, AND display
      any smaller region (see note below).
    OSCAN_VIDEO: The absolute largest region that the graphics.library
      can display.  This region must be used as-is.

    INPUTS
    DisplayID -- A 32-bit identifier for a display mode, as
      defined in graphics/displayinfo.h.

      NOTE: If you only intend to use one of the four standard
      overscan dimensions as is, and open your screen to exactly
      the DisplayClip dimensions, you can specify one of
      the OSCAN_ values in the ExtNewScreen tag SA_StdDClip,
      and specify STDSCREENWIDTH and STDSCREENHEIGHT as the
      dimensions to more easily open up an overscanned screen
      (or use no NewScreen in OpenScreenTagList() and accept
      the default standard screen dimensions).

    Rect -- pointer to a Rectangle structure which this function
      will fill out with its return values.  Note that to convert
      a rectangle to a screen "Height" you do (MaxY - MinY + 1), and
      similarly for "Width."  The rectangle may be passed directly
      to OpenScreen() as a DisplayClip region (SA_DClip).

    RESULT
    0 (FALSE) if the MonitorSpec your NewScreen requests
    does not exist.  Non-zero (TRUE) if it does.

    BUGS
    Change in parameter V36.A17 might cause problems for some.

    SEE ALSO
    OpenScreen(), Intuition V36 update documentation
 intuition.library/RefreshGadgets             intuition.library/RefreshGadgets

    NAME
    RefreshGadgets -- Refresh (redraw) the gadget display.

    SYNOPSIS
    RefreshGadgets( Gadgets, Window, Requester )
                A0       A1      A2

    VOID RefreshGadgets( struct Gadget *, struct Window *,
        struct Requester * );

    FUNCTION
    Refreshes (redraws) all of the gadgets in the gadget list starting
    from the specified gadget.

    The window parameter must point to the window which contains the
    gadget, or which contains the requester that contains the gadget
    The requester parameter must only be valid if the gadget has the
    GTYP_REQGADGET flag set, a requirement for all requester gadgets.

    The Pointer argument points to a Window structure.

    The two main reasons why you might want to use this routine are:
    first, that you've modified the imagery of the gadgets in your
    display and you want the new imagery to be displayed; secondly,
    if you think that some graphic operation you just performed
    trashed the gadgetry of your display, this routine will refresh
    the imagery for you.

    Note that to modify the imagery of a gadget, you must first remove
    that gadget from the window's gadget list, using RemoveGadget() (or
    RemoveGList()).  After changing the image, border, text (including
    text for a string gadget), the gadget is replaced in the gadget list
    (using AddGadget() or AddGList()).  Adding gadgets does not cause
    them to be displayed (refreshed), so this function, or RefreshGList()
    is typically called.

    A common technique is to set or reset the GFLG_SELECTED flag of a
    Boolean gadget and then call RefreshGadgets() to see it displayed
    highlighted if and only if GFLG_SELECTED is set.  If you wish to do
    this and be completely proper, you must RemoveGadget(), change the
    GFLG_SELECTED flag, AddGadget(), and RefreshGadgets(), or the
    equivalent.

    The gadgets argument can be a copy of the FirstGadget variable in
    the Window structure that you want refreshed:
    the effect of this will be that all gadgets will be redrawn.
    However, you can selectively refresh just some of the gadgets
    by starting the refresh part-way into the list:  for instance,
    redrawing your window non-GTYP_GZZGADGET gadgets only, which you've
    conveniently grouped at the end of your gadget list.

    Even more control is available using the RefreshGList() routine which
    enables you to refresh a single gadget, or number of your choice.

    NOTE:  It's never safe to tinker with the gadget list yourself.  Don't
    supply some gadget list that Intuition hasn't already processed in
    the usual way.

    INPUTS
    Gadgets = pointer to the first in the list of gadgets wanting
        refreshment
    Window = pointer to the window containing the gadget or its requester
    Requester = pointer to a requester (ignored if gadget is not attached
        to a requester).

    RESULT
    None

    BUGS

    SEE ALSO
    RefreshGList(), RemoveGadget(), RemoveGList(), AddGadget(), AddGList()
 intuition.library/RefreshGList                 intuition.library/RefreshGList

    NAME
    RefreshGList -- Refresh (redraw) a chosen number of gadgets.

    SYNOPSIS
    RefreshGList( Gadgets, Window, Requester, NumGad )
              A0       A1      A2         D0

    VOID RefreshGList( struct Gadget *, struct Window *,
        struct Requester *, WORD );

    FUNCTION
    Refreshes (redraws) gadgets in the gadget list starting
    from the specified gadget.  At most NumGad gadgets are redrawn.
    If NumGad is -1, all gadgets until a terminating NULL value
    in the NextGadget field is found will be refreshed, making this
    routine a superset of RefreshGadgets().

    The Requester parameter can point to a Requester structure.  If
    the first gadget in the list has the GTYP_REQGADGET flag set, the
    gadget list refers to gadgets in a requester and the pointer
    must necessarily point to a window.  If these are not the gadgets
    of a requester, the requester argument may be NULL.

    Be sure to see the RefreshGadgets() function description, as this
    function is simply an extension of that.

    INPUTS
    Gadgets = pointer to the first in the list of gadgets wanting
        refreshment
    Window = pointer to the window containing the gadget or its requester
    Requester = pointer to a requester (ignored if Gadget is not attached
        to a Requester).
    NumGad  = maximum number of gadgets to be refreshed.  A value of -1
      will cause all gadgets to be refreshed from gadget to the
      end of the list.  A value of -2 will also do this, but if 'Gadgets'
      points to a Requester Gadget (GTYP_REQGADGET) ALL gadgets in the
      requester will be refreshed (this is a mode compatible with v1.1
      RefreshGadgets().)

    RESULT
    None

    BUGS

    SEE ALSO
    RefreshGadgets()
 intuition.library/RefreshWindowFrame     intuition.library/RefreshWindowFrame

    NAME
    RefreshWindowFrame -- Ask Intuition to redraw your window border.

    SYNOPSIS
    RefreshWindowFrame( Window )
                A0

    VOID RefreshWindowFrame( struct Window * );

    FUNCTION
    Refreshes the border of a window, including title region and all
    of the window's gadgets.

    You may use this call if you wish to update the display of your borders.
    The expected use of this is to correct unavoidable corruption.

    INPUTS
    Window = a pointer to a Window structure

    RESULT
    None

    BUGS

    SEE ALSO

 intuition.library/ReleaseGIRPort             intuition.library/ReleaseGIRPort

    NAME
    ReleaseGIRPort -- Release a custom gadget RastPort. (V36)

    SYNOPSIS
    ReleaseGIRPort( RPort )
            A0

    VOID ReleaseGIRPort( struct RastPort * );

    FUNCTION
    The corresponding function to ObtainGIRPort(), it releases
    arbitration used by Intuition for gadget RastPorts.

    INPUTS
    Pointer to the RastPort returned by ObtainGIRPort().
    This pointer can be NULL, in which case nothing happens.

    RESULT
    None

    BUGS

    SEE ALSO
    ObtainGIRPort(), Custom Gadget documentation
 intuition.library/RemakeDisplay               intuition.library/RemakeDisplay

    NAME
    RemakeDisplay -- Remake the entire Intuition display.

    SYNOPSIS
    RemakeDisplay()

    VOID RemakeDisplay( VOID );

    FUNCTION
    This is the big one.

    This procedure remakes the entire View structure for the
    Intuition display.  It does the equivalent of MakeScreen() for
    every screen in the system, and then it calls the internal
    equivalent of RethinkDisplay().

    WARNING:  This routine can take many milliseconds to run, so
    do not use it lightly.

    Calling MakeScreen() followed by RethinkDisplay() is typically
    a more efficient method for affecting changes to a single
    screen's ViewPort.

    INPUTS
    None

    RESULT
    None

    BUGS

    SEE ALSO
    MakeScreen(), RethinkDisplay(), graphics.library/MakeVPort()
    graphics.library/MrgCop(), graphics.library/LoadView()
 intuition.library/RemoveClass                   intuition.library/RemoveClass

    NAME
    RemoveClass -- Make a public boopsi class unavailable. (V36)

    SYNOPSIS
    RemoveClass( classPtr )
             A0

    VOID RemoveClass( struct IClass * );

    FUNCTION
    Makes a public class unavailable for public consumption.
    It's OK to call this function for a class which is not
    yet in the internal public class list, or has been
    already removed.

    INPUTS
    ClassPtr = pointer to *public* class created by MakeClass(),
        may be NULL.

    RESULT
    None.

    NOTES

    BUGS

    SEE ALSO
    MakeClass(), FreeClass(), AddClass()
    Document "Basic Object-Oriented Programming System for Intuition"
    and the "boopsi Class Reference" document.

 intuition.library/RemoveGadget                 intuition.library/RemoveGadget

    NAME
    RemoveGadget -- Remove a gadget from a window.

    SYNOPSIS
    Position = RemoveGadget( Window, Gadget )
    D0			 A0      A1

    UWORD RemoveGadget( struct Window *, struct Gadget * );

    FUNCTION
    Removes the given gadget from the gadget list of the specified
    window.  Returns the ordinal position of the removed gadget.

    If the gadget is in a requester attached the the window, this
    routine will look for it and remove it if it is found.

    If the gadget pointer points to a gadget that isn't in the
    appropriate list, -1 is returned.  If there aren't any gadgets in the
    list, -1 is returned.  If you remove the 65535th gadget from the list
    -1 is returned.

    NOTES
    New with V37: If one of the gadgets you wish to remove
    is the active gadget, this routine will wait for the user
    to release the mouse button before deactivating and removing
    the gadget.

    INPUTS
    Window = pointer to the window containing the gadget or the requester
        containing the gadget to be removed.
    Gadget = pointer to the gadget to be removed.  The gadget itself
        describes whether this is a gadget that should be removed from the
        window or some requester.

    RESULT
    Returns the ordinal position of the removed gadget.  If the gadget
    wasn't found in the appropriate list, or if there are no gadgets in
    the list, returns -1.

    BUGS

    SEE ALSO
    AddGadget(), AddGList(), RemoveGList()
 intuition.library/RemoveGList                   intuition.library/RemoveGList

    NAME
    RemoveGList -- Remove a sublist of gadgets from a window.

    SYNOPSIS
    Position = RemoveGList( Window, Gadget, Numgad )
    D0			A0	A1	D0

    UWORD RemoveGList( struct Window *, struct Gadget *, WORD );

    FUNCTION
    Removes 'Numgad' gadgets from the gadget list of the specified
    window.  Will remove gadgets from a requester if the first
    gadget's GadgetType flag GTYP_REQGADGET is set.

    Otherwise identical to RemoveGadget().

    NOTE
    The last gadget in the list does NOT have its link zeroed.
    New with V36: OK, last gadget's NextGadget field is set to NULL.

    New with V37: If one of the gadgets you wish to remove
    is the active gadget, this routine will wait for the user
    to release the mouse button before deactivating and removing
    the gadget.

    INPUTS
    Window = pointer to the window containing the gadget or the requester
        containing the gadget to be removed.
    Gadget = pointer to the gadget to be removed.  The gadget itself
           describes whether this is a gadget that should be removed
           from the window or some requester.
    Numgad = number of gadgets to be removed.  If -1, remove all gadgets
        to end of window gadget list

    RESULT
    Returns the ordinal position of the removed gadget.  If the gadget
    wasn't found in the appropriate list, or if there are no gadgets in
    the list, returns -1.

    BUGS

    SEE ALSO
    RemoveGadget(), AddGadget(), AddGList()
 intuition.library/ReportMouse                   intuition.library/ReportMouse
    NAME
    ReportMouse -- Tell Intuition whether to report mouse movement.

    SYNOPSIS
    ReportMouse( Boolean, Window )
             D0       A0	<-note

    VOID ReportMouse( BOOL, struct Window * );

    SPECIAL NOTE
    Some compilers and link files switch the arguments to this function
    about in unpredictable ways.  We apologize for this confusion
    wrapped around an error enclosing a mistake.
    The call will take one of two forms:

        ReportMouse(Boolean, Window);
            -or-
        ReportMouse(Window, (ULONG)Boolean);

    The first form is the one that corresponds to the amiga.lib supplied
    by Amiga, Inc.  The linker libraries and "pragmas" of some compilers
    supply the alternate form.

    A key point to remember is that the form of the function in ROM
    has always been the same, so there has always been object code
    compatibility.  However some care should be taken when switching
    compilers or switching between stubs and pragmas.

    From assembler the interface has always been:
        Boolean in D0, Window in A0

    Also, it is still endorsed to simply set the WFLG_REPORTMOUSE flag bit
    in Window->Flags, or reset it, on your own.  Make the operation
    an atomic assembly instruction (OR.W #WFLG_REPORTMOUSE,wd_Flags+2(A0)
    where A0 contains your window pointer).  Most compilers will produce
    an atomic operation when faced with:
            Window->Flags |= WFLG_REPORTMOUSE;
            Window->Flags &=~WFLG_REPORTMOUSE;
    or else bracket the operation between Forbid()/Permit().

    FUNCTION
    Tells Intuition whether or not to broadcast mouse-movement events to
    your window when it's the active one.  The Boolean value specifies
    whether to start or stop broadcasting position information of
    mouse-movement.  If the window is the active one, mouse-movement reports
    start coming immediately afterwards.  This same routine will change
    the current state of the GACT_FOLLOWMOUSE function of a
    currently-selected gadget too.

    Note that calling ReportMouse() when a gadget is selected will only
    temporarily change whether or not mouse	movements are reported while
    that gadget remains selected; the next time the gadget is selected, its
    GACT_FOLLOWMOUSE flag is examined anew.

    Note also that calling ReportMouse() when no gadget is currently
    selected will change the state of the window's WFLG_REPORTMOUSE flag,
    but will have no effect on any gadget that may be subsequently
    selected. (This is all fixed in V36.)

    The ReportMouse() function is first performed when OpenWindow()
    is first called; if the flag WFLG_REPORTMOUSE is included among
    the options, then all mouse-movement events are reported
    to the opening task and will continue to be reported
    until ReportMouse() is called with a Boolean value of FALSE.
    If WFLG_REPORTMOUSE is not set, then no mouse-movement reports will
    be broadcast until ReportMouse() is called with a Boolean of TRUE.

    Note that the WFLG_REPORTMOUSE flag, as managed by this routine,
    determines IF mouse messages are to be broadcast.  Determining HOW
    they are to be broadcast is determined by the IDCMP_MOUSEMOVE
    IDCMPFlag.

    INPUTS
    Window = pointer to a Window structure associated with this request
    Boolean = TRUE or FALSE value specifying whether to turn this
             function on or off

    RESULT
    None

    BUGS
    See above

    SEE ALSO
    The Input and Output section of the Intuition Reference Manual
 intuition.library/Request                           intuition.library/Request

    NAME
    Request -- Activate a requester.

    SYNOPSIS
    Success = Request( Requester, Window )
    D0		   A0         A1

    BOOL Request( struct Requester *, struct Window * );

    FUNCTION
    Links in and displays a requester into the specified window.

    This routine ignores the window's IDCMP_REQVERIFY flag.

    INPUTS
    Requester = pointer to the requester to be displayed
    Window = pointer to the window into which this requester goes

    New for V36: the POINTREL flag now has meaning if the requester
    is not a DMR (Double-Menu Requester):
    If POINTREL is set this requester should be placed in the center
    of the window, offset by Requester.RelLeft and Requester.RelTop.
    If the requester doesn't fit in the window, its position will be
    adjusted to show the upper-left corner.

    RESULT
    If the requester is successfully opened, TRUE is returned.  Otherwise,
    if the requester could not be opened, FALSE is returned.

    BUGS
    There is a maximum of 8 requesters that are supported in
    a window that can be changed in size, position, or depth.

    SEE ALSO
    The Requesters section of the Intuition Reference Manual
 intuition.library/ResetMenuStrip             intuition.library/ResetMenuStrip

    NAME
    ResetMenuStrip -- Re-attach a menu strip to a window. (V36)

    SYNOPSIS
    Success = ResetMenuStrip( Window, Menu )
    D0		          A0      A1

    BOOL ResetMenuStrip( struct Window *, struct Menu * );

    FUNCTION
    This function is simply a "fast" version of SetMenuStrip() that
    doesn't perform the precalculations of menu page sizes that
    SetMenuStrip() does.

    You may call this function ONLY IF the menu strip and all items
    and sub-items have not changed since the menu strip was passed to
    SetMenuStrip(), with the following exceptions:

    - You may change the CHECKED flag to turn a checkmark on or off.
    - You may change the ITEMENABLED flag to enable/disable some
      MenuItem or Menu structures.

    In all other ways, this function performs like SetMenuStrip().

    The new sequence of events you can use is:
    - OpenWindow()
    - SetMenuStrip()
    zero or more iterations of:
        - ClearMenuStrip()
        - change CHECKED or ITEMENABLED flags
        - ResetMenuStrip()
    - ClearMenuStrip()
    - CloseWindow()

    INPUTS
    Window = pointer to a Window structure
    Menu = pointer to the first menu in the menu strip

    RESULT
    TRUE always.

    BUGS

    SEE ALSO
    SetMenuStrip(), ClearMenuStrip()
 intuition.library/RethinkDisplay             intuition.library/RethinkDisplay

    NAME
    RethinkDisplay -- Grand manipulation of the entire Intuition display.

    SYNOPSIS
    RethinkDisplay()

    VOID RethinkDisplay( VOID );

    FUNCTION
    This function performs the Intuition global display reconstruction.
    This includes rethinking about all of the  ViewPorts and their
    relationship to one another and reconstructing the entire display
    based on the results of this rethinking.

    Specifically, and omitting many internal details, the operation
    consists of this:

        Determine which ViewPorts are invisible and set their VP_HIDE
        ViewPort Mode flag. VP_HIDE flags are also set for screens that
        may not be simultaneously displayed with the frontmost (V36).

        If a change to a viewport height, or changing interlace or
        monitor scan rates require, MakeVPort() is called for specific
        screen viewports.  After this phase, the intermediate Copper lists
        for each screen's viewport are correctly set up.

        MrgCop() and LoadView() are then called to get these Copper lists
        in action, thus establishing the new state of the Intuition
        display.

    You may perform a MakeScreen() on your Custom Screen before calling
    this routine.  The results will be incorporated in the new display, but
    changing the INTERLACE ViewPort mode for one screens must be reflected
    in the Intuition View, which is left to Intuition.

    WARNING:  This routine can take several milliseconds to run, so
    do not use it lightly.

    New for V36: This routine is substantially changed to support
    new screen modes.  In particular, if screen rearrangement has
    caused a change in interlace mode or scan rate, this routine
    will remake the copper lists for each screen's viewport.

    INPUTS
    None

    RESULT
    None

    BUGS
    In V35 and earlier, an interlaced screen coming to the front
    may not trigger a complete remake as required when the global
    interlace state is changed.  In some cases, this can be compensated
    for by setting the viewport DHeight field to 0 for hidden screens.

    SEE ALSO
    RemakeDisplay(), graphics.library/MakeVPort(), graphics.library/MrgCop(),
    graphics.library/LoadView(), MakeScreen()
 intuition.library/ScreenToBack                 intuition.library/ScreenToBack

    NAME
    ScreenToBack -- Send the specified screen to the back of the display.

    SYNOPSIS
    ScreenToBack( Screen )
              A0

    VOID ScreenToBack( struct Screen * );

    FUNCTION
    Sends the specified screen to the back of the display.

    INPUTS
    Screen = pointer to a Screen structure

    RESULT
    None

    BUGS

    SEE ALSO
    ScreenToFront()
 intuition.library/ScreenToFront               intuition.library/ScreenToFront

    NAME
    ScreenToFront -- Make the specified screen the frontmost.

    SYNOPSIS
    ScreenToFront( Screen )
               A0

    VOID ScreenToFront( struct Screen * );

    FUNCTION
    Brings the specified Screen to the front of the display.

    INPUTS
    Screen = a pointer to a Screen structure

    RESULT
    None

    BUGS

    SEE ALSO
    ScreenToBack()
 intuition.library/SetAttrsA                       intuition.library/SetAttrsA

    NAME
    SetAttrsA -- Specify attribute values for an object. (V36)
    SetAttrs -- Varargs stub for SetAttrsA(). (V36)

    SYNOPSIS
    result = SetAttrsA( Object, TagList )
    D0                  A0      A1

    ULONG SetAttrsA( APTR, struct TagItem * );

    result = SetAttrs( Object, Tag1, ... )

    ULONG SetAttrs( APTR, ULONG, ... );

    FUNCTION
    Specifies a set of attribute/value pairs with meaning as
    defined by a 'boopsi' object's class.

    This function does not provide enough context information or
    arbitration for boopsi gadgets which are attached to windows
    or requesters.  For those objects, use SetGadgetAttrs().

    INPUTS
    Object = abstract pointer to a boopsi object.
    TagList = array of TagItem structures with attribute/value pairs.

    RESULT
    The object does whatever it wants with the attributes you provide.
    The return value tends to be non-zero if the changes would require
    refreshing gadget imagery, if the object is a gadget.

    NOTES
    This function invokes the OM_SET method with a NULL GadgetInfo
    parameter.

    BUGS

    SEE ALSO
    NewObject(), DisposeObject(), GetAttr(), MakeClass(),
    Document "Basic Object-Oriented Programming System for Intuition"
    and the "boopsi Class Reference" document.
 intuition.library/SetDefaultPubScreen   intuition.library/SetDefaultPubScreen

    NAME
    SetDefaultPubScreen -- Choose a new default public screen. (V36)

    SYNOPSIS
    SetDefaultPubScreen( Name )
                 A0

    VOID SetDefaultPubScreen( UBYTE * );

    FUNCTION
    Establishes a new default public screen for visitor windows.

    This screen is used by windows asking for a named public screen
    that doesn't exist and the FALLBACK option is selected, and for
    windows asking for the default public screen directly.

    INPUTS
    Name = name of chosen public screen to be the new default.
    A value of NULL means that the Workbench screen is to
    be the default public screen.

    RESULT
    None

    BUGS

    SEE ALSO
    OpenWindow(), OpenScreen(), Intuition V36 update documentation
 intuition.library/SetDMRequest                 intuition.library/SetDMRequest

    NAME
    SetDMRequest -- Set the DMRequest of a window.

    SYNOPSIS
    success = SetDMRequest( Window, DMRequest )
    D0                      A0      A1

    BOOL SetDMRequest( struct Window *, struct Requester * );

    FUNCTION
    Attempts to set the DMRequest into the specified window.
    The DMRequest is the special requester that you attach to
    the double-click of the menu button which the user can then
    bring up on demand.  This routine WILL NOT change the DMRequest
    if it's already set and is currently active (in use by the user).
    After having called SetDMRequest(), if you want to change the
    DMRequest, the correct way to start is by calling ClearDMRequest()
    until it returns a value of TRUE; then you can call SetDMRequest()
    with the new DMRequest.

    If the POINTREL flag is set in the DMRequest, the DMR will open as
    close to the pointer as possible.  The RelLeft/Top fields are
    for fine-tuning the position.

    INPUTS
    Window = pointer to the window from which the DMRequest is to be set
    DMRequest = a pointer to a requester

    RESULT
    If the current DMRequest was not in use, sets the DMRequest
        pointer into the window and returns TRUE.
    If the DMRequest was currently in use, doesn't change the pointer
        and returns FALSE

    BUGS

    SEE ALSO
    ClearDMRequest(), Request()
 intuition.library/SetEditHook                   intuition.library/SetEditHook

    NAME
    SetEditHook -- Set global processing for string gadgets. (V36)

    SYNOPSIS
    OldHook = SetEditHook( Hook )
    D0                     A0

    struct Hook *SetEditHook( struct Hook * );

    FUNCTION
    Sets new global editing hook for string gadgets.

    WARNING: This function is wholly untested.  Do *NOT* use
    this in a commercial product until further notice.

    INPUTS
    Hook -- A pointer to a struct Hook which determines a function
      in your code to be called every time the user types a key.
      This is done before control is passed to the gadget custom
      editing hook, so effects ALL string gadgets.

    RESULT
    Returns previous global edit hook structure.

    BUGS
    Unknown, risky.

    SEE ALSO

 intuition.library/SetGadgetAttrsA           intuition.library/SetGadgetAttrsA

    NAME
    SetGadgetAttrsA -- Specify attribute values for a boopsi gadget. (V36)
    SetGadgetAttrs -- Varargs stub for SetGadgetAttrsA(). (V36)

    SYNOPSIS
    result = SetGadgetAttrsA( Gadget, Window, Requester, TagList )
    D0		          A0      A1      A2         A3

    ULONG SetGadgetAttrsA( struct Gadget *, struct Window *,
        struct Requester *, struct TagItem * );

    result = SetGadgetAttrs( Gadget, Window, Requester, Tag1, ...)

    ULONG SetGadgetAttrs( struct Gadget *, struct Window *,
        struct Requester *, ULONG, ... );

    FUNCTION
    Same as SetAttrs(), but provides context information and
    arbitration for classes which implement custom Intuition gadgets.

    You should use this function for boopsi gadget objects which have
    already been added to a requester or a window, or for "models" which
    propagate information to gadget already added.

    Typically, the gadgets will refresh their visuals to reflect
    changes to visible attributes, such as the value of a slider,
    the text in a string-type gadget, the selected state of a button.

    You can use this as a replacement for SetAttrs(), too, if you
    specify NULL for the 'Window' and 'Requester' parameters.

    INPUTS
    Gadget = abstract pointer to a boopsi gadget
    Window = window gadget has been added to using AddGList() or AddGadget()
    Requester = for REQGADGETs, requester containing the gadget
    TagList = array of TagItem structures with attribute/value pairs.

    RESULT
    The object does whatever it wants with the attributes you provide,
    which might include updating its gadget visuals.

    The return value tends to be non-zero if the changes would require
    refreshing gadget imagery, if the object is a gadget.

    NOTES
    This function invokes the OM_SET method with a GadgetInfo
    derived from the 'Window' and 'Requester' pointers.

    BUGS
    There should be more arbitration between this function and
    the calls that Intuition's input task will make to the
    gadgets.  In the meantime, this function, input processing,
    and refreshing must be mutually re-entrant.

    SEE ALSO
    NewObject(), DisposeObject(), GetAttr(), MakeClass(),
    Document "Basic Object-Oriented Programming System for Intuition"
    and the "boopsi Class Reference" document.
 intuition.library/SetMenuStrip                 intuition.library/SetMenuStrip

    NAME
    SetMenuStrip -- Attach a menu strip to a window.

    SYNOPSIS
    Success = SetMenuStrip( Window, Menu )
    D0		        A0      A1

    BOOL SetMenuStrip( struct Window *, struct Menu * );

    FUNCTION
    Attaches the menu strip to the window.  After calling this routine,
    if the user presses the menu button, this specified menu strip
    will be displayed and accessible by the user.

    Menus with zero menu items are not allowed.

    NOTE:  You should always design your menu strip changes to be a
    two-way operation, where for every menu strip you add to your
    window you should always plan to clear that strip sometime.  Even
    in the simplest case, where you will have just one menu strip for
    the lifetime of your window, you should always clear the menu strip
    before closing the window.  If you already have a menu strip attached
    to this window, the correct procedure for changing to a new menu
    strip involves calling ClearMenuStrip() to clear the old first.

    The sequence of events should be:
    - OpenWindow()
    - zero or more iterations of:
          - SetMenuStrip()
          - ClearMenuStrip()
    - CloseWindow()

    INPUTS
    Window = pointer to a Window structure
    Menu = pointer to the first menu in the menu strip

    RESULT
    TRUE if there were no problems.  TRUE always, since this routine
    will wait until it is OK to proceed.

    BUGS

    SEE ALSO
    ClearMenuStrip(), ResetMenuStrip()
 intuition.library/SetMouseQueue               intuition.library/SetMouseQueue

    NAME
    SetMouseQueue -- Change limit on pending mouse messages. (V36)

    SYNOPSIS
    oldQueueLength = SetMouseQueue( Window, QueueLength )
    D0                              A0      D0

    LONG SetMouseQueue( struct Window *, UWORD );

    FUNCTION
    Changes the number of mouse messages that Intuition will allow
    to be outstanding for your window.

    INPUTS
    Window = your window
    QueueLength = the new value of outstanding mouse movement messages
      you wish to allow.

    RESULT
    -1 if 'Window' is not known
    Otherwise the previous value of the queue limit.
    The corresponding function for changing the repeat key
    queue limit is not yet implemented.

    BUGS

    SEE ALSO
    OpenWindow()
 intuition.library/SetPointer                     intuition.library/SetPointer

    NAME
    SetPointer -- Specify a pointer sprite image for a window.

    SYNOPSIS
    SetPointer( Window, Pointer, Height, Width, XOffset, YOffset )
            A0      A1       D0      D1     D2       D3

    VOID SetPointer( struct Window *, UWORD *, WORD, WORD, WORD, WORD );

    FUNCTION
    Sets up the window with the sprite definition for the pointer.
    Then, whenever the window is the active one, the pointer
    image will change to the window's version.  If the window is
    the active one when this routine is called, the change takes
    place immediately.

    The XOffset and YOffset parameters are used to offset the
    upper-left corner of the hardware sprite image from what Intuition
    regards as the current position of the pointer.  Another way of
    describing it is as the offset from the "hot spot" of the pointer
    to the top-left corner of the sprite.  For instance, if you specify
    offsets of zero, zero, then the top-left corner of your sprite
    image will be placed at the mouse position.  On the other hand,
    if you specify an XOffset of -7 (remember, sprites are 16 pixels
    wide) then your sprite will be centered over the mouse position.
    If you specify an XOffset of -15, the right-edge of the sprite
    will be over the mouse position.

    INPUTS
    Window = pointer to the window to receive this pointer definition
    Pointer = pointer to the data definition of a sprite
    Height = the height of the pointer
    Width = the width of the sprite (must be less than or equal to sixteen)
    XOffset = the offset for your sprite from the mouse position
    YOffset = the offset for your sprite from the mouse position

    RESULT
    None

    BUGS

    SEE ALSO
    ClearPointer(), Intuition Reference Manual or Amiga Rom
    Kernel Manual
 intuition.library/SetPrefs                         intuition.library/SetPrefs

    NAME
    SetPrefs -- Set Intuition preferences data.

    SYNOPSIS
    Prefs = SetPrefs( PrefBuffer, Size, Inform )
    D0		  A0          D0    D1

    struct Preferences *SetPrefs( struct Preferences *, LONG, BOOL );

    FUNCTION
    Sets new preferences values.  Copies the first 'Size' bytes
    from your preferences buffer to the system preferences table,
    and puts them into effect.

    The 'Inform' parameter, if TRUE, indicates that an IDCMP_NEWPREFS
    message is to be sent to all windows that have the IDCMP_NEWPREFS
    IDCMPFlag set.

    It is legal to set a partial copy of the Preferences structure.
    The most frequently changed values are grouped at the beginning
    of the Preferences structure.

    New for V36:  A new and more extensible method for supplying
    Preferences has been introduced in V36, and relies on file
    system notification.  The Intuition preferences items rely
    also on the IPrefs program.  Certain elements of the
    Preferences structure have been superceded by this new method.
    Pointer changes submitted through SetPrefs() are only heeded
    until the first time IPrefs informs Intuition of a V36-style
    pointer.ilbm preferences file.  The Preferences FontHeight and
    LaceWB fields are respected only from the system-configuration
    file, and never thereafter.  As well, the view centering and
    size apply only to the default monitor, and not to such modes
    as Productivity.  Other fields may be superceded in the future.

    INPUTS
    PrefBuffer = pointer to the memory buffer which contains your
        desired settings for Intuition preferences
    Size = the number of bytes in your PrefBuffer, the number of bytes
           you want copied to the system's internal preference settings
    Inform = whether you want the information of a new preferences
        setting propagated to all windows.

    NOTES
    Unless you are responding to a user's explicit request to
    change Preferences (for example, you are writing a Preferences
    editor), you should probably avoid using this function.
    The user's Preferences should be respected, not overridden.

    RESULT
    Returns your parameter PrefBuffer.

    BUGS

    SEE ALSO
    GetDefPrefs(), GetPrefs()
 intuition.library/SetPubScreenModes       intuition.library/SetPubScreenModes

    NAME
    SetPubScreenModes -- Establish global public screen behavior. (V36)

    SYNOPSIS
    OldModes = SetPubScreenModes( Modes )
    D0                            D0

    UWORD SetPubScreenModes( UWORD );

    FUNCTION
        Sets GLOBAL Intuition public screen modes.

    INPUTS
    Modes = new global modes flags.  Values for flag bits are:
      SHANGHAI: workbench windows are to be opened on the
        default public screen
      POPPUBSCREEN: when a visitor window is opened, the public
        screen it opens on is to be brought to the front.

    RESULT
    OldModes = previous global mode settings

    BUGS

    SEE ALSO
    OpenScreen(), Intuition V36 update documentation
 intuition.library/SetWindowTitles           intuition.library/SetWindowTitles

    NAME
    SetWindowTitles -- Set the window's titles for both window and screen.

    SYNOPSIS
    SetWindowTitles( Window, WindowTitle, ScreenTitle )
             A0      A1           A2

    VOID SetWindowTitles( struct Window *, UBYTE *, UBYTE * );

    FUNCTION
    Allows you to set the text which appears in the Window and/or Screen
    title bars.

    The window title appears at all times along the window title bar.
    The window's screen title appears at the screen title bar whenever
    this window is the active one.

    When this routine is called, your window title will be changed
    immediately.  If your window is the active one when this routine is
    called, the screen title will be changed immediately.

    You can specify a value of -1 (i.e. (UBYTE *) ~0) for either of
    the title pointers.  This designates that you want Intuition to leave
    the current setting of that particular title alone, and modify
    only the other one.  Of course, you could set both to -1.

    Furthermore, you can set a value of 0 (zero) for either of the
    title pointers.  Doing so specifies that you want no title to
    appear (the title bar will be blank).

    Both of the titles are rendered in the default font of the window's
    screen, as set using OpenScreen().

    In setting the window's title, Intuition may do some other rendering
    in the top border of your window.  If your own rendering sometimes
    appears in your window border areas, you may want to restore the entire
    window border frame.  The function SetWindowTitles() does not do this
    in the newer versions.  The function RefreshWindowFrame() is provided
    to do this kind of thing for you.

    INPUTS
    Window = pointer to your window structure
    WindowTitle = pointer to a null-terminated text string, or set to
           either the value of -1 (negative one) or 0 (zero)
    ScreenTitle = pointer to a null-terminated text string, or set to
           either the value of -1 (negative one) or 0 (zero)

    RESULT
    None

    BUGS

    SEE ALSO
    OpenWindow(), RefreshWindowFrame(), OpenScreen()
 intuition.library/ShowTitle                       intuition.library/ShowTitle

    NAME
    ShowTitle -- Set the screen title bar display mode.

    SYNOPSIS
    ShowTitle( Screen, ShowIt )
           A0      D0

    VOID ShowTitle( struct Screen *, BOOL );

    FUNCTION
    This routine sets the SHOWTITLE flag of the specified screen, and
    then coordinates the redisplay of the screen and its windows.

    The screen title bar can appear either in front of or behind
    WFLG_BACKDROP windows.  This is contrasted with the fact that
    non-WFLG_BACKDROP windows always appear in front of the screen title
    bar.  You specify whether you want the screen title bar to be in front
    of or behind the screen's WFLG_BACKDROP windows by calling this
    routine.

    The ShowIt argument should be set to either TRUE or FALSE.  If TRUE,
       the screen's title bar will be shown in front of WFLG_BACKDROP windows
.
       If FALSE, the title bar will be rendered behind all windows.

       When a screen is first opened, the default setting of the SHOWTITLE
       flag is TRUE.

    INPUTS
       Screen = pointer to a Screen structure
       ShowIt = Boolean TRUE or FALSE describing whether to show or hide the
           screen title bar

    RESULT
       None

    BUGS

    SEE ALSO

 intuition.library/SizeWindow                     intuition.library/SizeWindow

    NAME
    SizeWindow -- Ask Intuition to size a window.

    SYNOPSIS
    SizeWindow( Window, DeltaX, DeltaY )
            A0      D0      D1

    VOID SizeWindow( struct Window *, WORD, WORD );

    FUNCTION
    This routine sends a request to Intuition asking to size the window
    the specified amounts.  The delta arguments describe how much to
    size the window along the respective axes.

    Note that the window will not be sized immediately, but rather
    will be sized the next time Intuition receives an input event,
    which happens currently at a minimum rate of ten times per second,
    and a maximum of sixty times a second.  You can discover when
    you window has finally been sized by setting the IDCMP_NEWSIZE flag
    of the IDCMP of your window.  See the "Input and Output Methods"
    chapter of The Intuition Reference Manual for description of the IDCMP.

    New for V36: Intuition now will do validity checking on the final
    dimensions.  To change to new absolute dimensions, or to move and
    size a window in one step, use ChangeWindowBox().

    However, limit checking against window MinWidth, MinHeight,
    MaxWidth, and MaxHeight was not done prior to V36, and
    these fields are still ignored (as documented) if you have
    no sizing gadget (WFLG_SIZEGADGET is not set).  The *are*
    respected now (V36) if WFLG_SIZEGADGET is set.

    New for V36: you can determine when the change in size has
    taken effect by receiving the IDCMP_CHANGEWINDOW IDCMP message.

    INPUTS
    Window = pointer to the structure of the window to be sized
    DeltaX = signed value describing how much to size the window
     on the x-axis
    DeltaY = signed value describing how much to size the window
     on the y-axis

    RESULT
    None

    BUGS

    SEE ALSO
    ChangeWindowBox(), MoveWindow(), WindowToFront(), WindowToBack()
 intuition.library/SysReqHandler               intuition.library/SysReqHandler

    NAME
    SysReqHandler -- Handle system requester input. (V36)

    SYNOPSIS
    num = SysReqHandler( Window, IDCMPFlagsPtr, WaitInput )
    D0                   A0      A1             D0

    LONG SysReqHandler( struct Window *, ULONG *, BOOL );

    FUNCTION
    Handles input for a window returned by either BuildSysRequest()
    or BuildEasyRequest().  These functions with SysReqHandler()
    you can perform an "asynchronous" EasyRequest() or AutoRequest().
    That is to say, you can perform other processing while you
    wait for the requester to be satisfied.

    Each time this function is called, it will process all
    IDCMPMessages that the window has received.  If the parameter
    'WaitInput' is non-zero, SysReqHandler() will wait for input
    (by calling WaitPort()) if there are no IDCMP messages.

    SysReqHandler() returns the same values as EasyRequest(): A gadget
    ID greater than equal to 0, and  -1 if one of the other IDCMP
    events were received.

    An additional value of -2 is returned if the input processed
    does not satisfy the requester.  In this case, you might
    perform some processing and call SysReqHandler() again.

    Note: this function does NOT terminate the system request.
    Not only must you call FreeSysRequest() to eliminate the request,
    but you may also continue processing after an event which would
    normally terminate a normal call to EasyRequest().

    EXAMPLE
    Implementation of EasyRequest() input loop:

    window = BuildEasyRequest( ZZZZ )
    while ( (retval = SysReqHandler( window, idcmp_ptr, TRUE )) == -2 )
    {
        /* loop	*/;
    }
    FreeSysRequest( window );

    EXAMPLE
    Request a volume, but don't remove the requester when the
    user inserts the wrong disk:

    struct EasyStruct volumeES = {
        sizeof (struct EasyStruct),
        0,
        "Volume Request",
        "Please insert volume %s in any drive.",
        "Cancel"
    };

    Volume *
    getVolume( volname )
    UBYTE	*volname;
    {
        struct Window	*window;
        Volume		*volume = NULL;
        Volume		*findVolume();
        int			retval;

        window = BuildEasyRequest( NULL, &volumeES, IDCMP_DISKINSERTED,
                  volname );

        while ( (retval = SysReqHandler( window, NULL, TRUE )) != 0 )
        {
            /* not cancelled yet	*/

            /* when IDCMP_DISKINSERTED, check for volume */
            if (( retval == -1 ) && (volume = findVolume( volname )))
            break;
        }
        FreeSysRequest( window );
        return ( volume );
    }

    INPUTS
    Window = Window pointer returned from BuildSysRequest() or
        BuildEasyRequest().  Those functions can also return
        values '0' or '1', and these values may also be
        passed to SysReqHandler(), which will immediately
        return the same value.

    IDCMPFlagsPtr = If you passed application specific IDCMP
        flags to BuildSysRequest() or BuildEasyRequest(),
        SysReqHandler() will return -1 if that IDCMP message
        is received.  If IDCMPFlagsPtr is non-null, it
        points to a ULONG where the IDCMP class received
        will be copied for your examination.

        This pointer can be NULL if you have provided no
        application specific IDCMP flags or if you do
        not need to know which application specific IDCMP
        event occurred.

        If you provide more than on flag in the flags variable
        this pointer points to, you will have to refresh
        the variable whenever -1 is returned, since the
        variable will have been changed to show just the
        single IDCMP Class bit that caused the return.

    WaitInput = Specifies that you want SysReqHandler() to
            to wait for IDCMP input if there is none pending.

    RESULT
    0, 1, ..., N = Successive GadgetID values, for the gadgets
        you specify for the requester.  NOTE: The numbering
        from left to right is actually: 1, 2, ..., N, 0.
        This is for compatibility with AutoRequests which has
        FALSE for the rightmost gadget.

    -1 = Means that one of the caller-supplied IDCMPFlags occurred.
        The IDCMPFlag value is in the longword pointed to by UDCMP_ptr.

    -2 = input processed did not satisfy the requester. One example
        is a keystroke that does not satisfy the requester.  Another
        example is if there is no input pending and you specified
        FALSE for WaitInput.

    BUGS

    SEE ALSO
    exec.library/WaitPort()
 intuition.library/UnlockIBase                   intuition.library/UnlockIBase

    NAME
    UnlockIBase -- Surrender an Intuition lock gotten by LockIBase().

    SYNOPSIS
    UnlockIBase( Lock )
             A0

    VOID UnlockIBase( ULONG );

    FUNCTION

    Surrenders lock gotten by LockIBase().

    Calling this function when you do not own the specified lock will
    immediately crash the system.

    INPUTS
    The value returned by LockIBase() should be passed to this function,
    to specify which internal lock is to be freed.

    Note that the parameter is passed in A0, not D0, for historical reasons.

    RESULT
    None

    BUGS

    SEE ALSO
    LockIBase()
 intuition.library/UnlockPubScreen           intuition.library/UnlockPubScreen

    NAME
    UnlockPubScreen -- Release lock on a public screen. (V36)

    SYNOPSIS
    UnlockPubScreen( Name, [Screen] )
             A0    A1

    VOID UnlockPubScreen( UBYTE *, struct Screen * );

    FUNCTION
    Releases lock gotten by LockPubScreen().
    It is best to identify the locked public screen by
    the pointer returned from LockPubScreen().  To do this,
    supply a NULL 'Name' pointer and the screen pointer.

    In rare circumstances where it would be more convenient to pass
    a non-NULL pointer to the public screen name string, the
    'Screen' parameter is ignored.

    INPUTS
    Name = pointer to name of public screen.  If Name is NULL,
        then argument 'Screen' is used as a direct pointer to
        a public screen.
    Screen = pointer to a public screen.  Used only if Name
        is NULL.  This pointer MUST have been returned
        by LockPubScreen().
        It is safe to call UnlockPubScreen() with NULL Name
        and Screen (the function will have no effect).

    RESULT

    BUGS

    SEE ALSO
    LockPubScreen()
 intuition.library/UnlockPubScreenList   intuition.library/UnlockPubScreenList

    NAME
    UnlockPubScreenList -- Release public screen list semaphore. (V36)

    SYNOPSIS
    UnlockPubScreenList()

    VOID UnlockPubScreenList( VOID );

    FUNCTION
    Releases lock gotten by LockPubScreenList().

    INPUTS
    None.

    RESULT
    None.

    BUGS

    SEE ALSO
    LockPubScreenList()
 intuition.library/ViewAddress                   intuition.library/ViewAddress

    NAME
    ViewAddress -- Return the address of the Intuition View structure.

    SYNOPSIS
    view = ViewAddress()
    D0

    struct View *ViewAddress( VOID );

    FUNCTION
    Returns the address of the Intuition View structure.  If you
    want to use any of the graphics, text, or animation primitives
    in your window and that primitive requires a pointer to a view,
    this routine will return the address of the view for you.

    INPUTS
    None

    RESULT
    Returns the address of the Intuition View structure

    BUGS

    SEE ALSO
    graphics.library
 intuition.library/ViewPortAddress           intuition.library/ViewPortAddress

    NAME
    ViewPortAddress -- Return the address of a window's viewport.

    SYNOPSIS
    ViewPort = ViewPortAddress( Window )
    D0                          A0

    struct ViewPort *ViewPortAddress( struct Window * );

    FUNCTION
    Returns the address of the viewport associated with the specified
    window.  The viewport is actually the viewport of the screen within
    which the window is displayed.  If you want to use any of the graphics,
    text, or animation primitives in your window and that primitive
    requires a pointer to a viewport, you can use this call.

    This pointer is only valid as long as your window's screen remains
    open, which is ensured by keeping your window open.

    INPUTS
    Window = pointer to the window for which you want the viewport address

    RESULT
    Returns the address of the Intuition ViewPort structure for
    your window's screen .

    BUGS
    This routine is unnecessary: you can just use the expression
    &Window->WScreen->ViewPort.

    SEE ALSO
    graphics.library
 intuition.library/WBenchToBack                 intuition.library/WBenchToBack

    NAME
    WBenchToBack -- Send the Workbench screen in back of all screens.

    SYNOPSIS
    Success = WBenchToBack()
    D0

    BOOL WBenchToBack( VOID );

    FUNCTION
    Causes the Workbench screen, if it's currently opened, to go behind
    all other screens.  This does not 'move' the screen up or down,
    instead only affects the depth-arrangement of the screens.

    INPUTS
    None

    RESULT
    If the Workbench screen was opened, this function returns TRUE,
    otherwise it returns FALSE.

    BUGS

    SEE ALSO
    WBenchToFront(), ScreenToFront()
 intuition.library/WBenchToFront               intuition.library/WBenchToFront

    NAME
    WBenchToFront -- Bring the Workbench screen in front of all screens.

    SYNOPSIS
    Success = WBenchToFront()
    D0

    BOOL WBenchToFront( VOID );

    FUNCTION
    Causes the Workbench Screen, if it's currently opened, to come to
    the foreground.  This does not 'move' the screen up or down, instead
    only affects the depth-arrangement of the screen.

    INPUTS
    None

    RESULT
    If the Workbench screen was opened, this function returns TRUE,
    otherwise it returns FALSE.

    BUGS

    SEE ALSO
    WBenchToBack(), ScreenToBack()
 intuition.library/WindowLimits                 intuition.library/WindowLimits

    NAME
    WindowLimits -- Set the minimum and maximum limits of a window.

    SYNOPSIS
    Success = WindowLimits( Window, MinWidth, MinHeight, MaxWidth,
    D0		        A0      D0        D1         D2
                            MaxHeight )
                            D3

    BOOL WindowLimits( struct Window *, WORD, WORD, UWORD, UWORD );

    FUNCTION
    Sets the minimum and maximum limits of the window's size.  Until this
    routine is called, the window's size limits are equal to the initial
    values established in the OpenWindow() function.

    After a call to this routine, the Window will be able to be sized
    to any dimensions within the specified limits.

    If you don't want to change any one of the dimensions, set the limit
    argument for that dimension to zero.  If any of the limit arguments
    is equal to zero, that argument is ignored and the initial setting
    of that parameter remains undisturbed.

    If any of the arguments is out of range (minimums greater than the
    current size, maximums less than the current size), that limit
    will be ignored, though the others will still take effect if they
    are in range.  If any are out of range, the return value from this
    procedure will be FALSE.  If all arguments are valid, the return
    value will be TRUE.

    If you want your window to be able to become "as large as possible"
    you may put -1 (i.e. ~0) in either or both Max arguments.  But
    please note: screen sizes may vary for several reasons, and you
    must be able to handle any possible size of window you might end
    up with if you use this method.  Note that you can use the function
    GetScreenData() to find out how big the screen your window appears in
    is.  That function is particularly useful if your window is in
    the Workbench screen.  You may also refer to the WScreen field
    in your window structure, providing that your window remains open,
    which will ensure that the screen remains open, and thus the
    pointer remains valid.

    If the user is currently sizing this window, the new limits will
    not take effect until after the sizing is completed.

    INPUTS
    Window = pointer to a Window structure
    MinWidth, MinHeight, MaxWidth, MaxHeight = the new limits for the size
            of this window.  If any of these is set to zero, it will
            be ignored and that setting will be unchanged.

    RESULT
    Returns TRUE if everything was in order.  If any of the parameters was
    out of range (minimums greater than current size, maximums less than
    current size), FALSE is returned and the errant limit request is
    not fulfilled (though the valid ones will be).

    BUGS

    SEE ALSO
    GetScreenData()
 intuition.library/WindowToBack                 intuition.library/WindowToBack

    NAME
    WindowToBack -- Ask Intuition to send a window behind others.

    SYNOPSIS
    WindowToBack( Window )
              A0

    VOID WindowToBack( struct Window * );

    FUNCTION
    This routine sends a request to Intuition asking to send the window
    in back of all other windows in the screen.

    Note that the window will not be depth-arranged immediately, but rather
    will be arranged the next time Intuition receives an input event,
    which happens currently at a minimum rate of ten times per second,
    and a maximum of sixty times a second.

    Remember that WFLG_BACKDROP windows cannot be depth-arranged.

    INPUTS
    Window = pointer to the structure of the window to be sent to the back

    RESULT
    None

    BUGS

    SEE ALSO
    MoveWindow(), SizeWindow(), WindowToFront(), MoveWindowInFrontOf()
 intuition.library/WindowToFront               intuition.library/WindowToFront

    NAME
    WindowToFront -- Ask Intuition to bring a window to the front.

    SYNOPSIS
    WindowToFront( Window )
                   A0

    VOID WindowToFront( struct Window * );

    FUNCTION
    This routine sends a request to Intuition asking to bring the window
    in front of all other windows in the screen.

    Note that the window will not be depth-arranged immediately, but rather
    will be arranged the next time Intuition receives an input event,
    which happens currently at a minimum rate of ten times per second,
    and a maximum of sixty times a second.

    Remember that WFLG_BACKDROP windows cannot be depth-arranged.

    INPUTS
    Window = pointer to the structure of the window to be brought to front

    RESULT
    None

    BUGS

    SEE ALSO
    MoveWindow(), SizeWindow(), WindowToBack(), MoveWindowInFrontOf()
 intuition.library/ZipWindow                       intuition.library/ZipWindow

    NAME
    ZipWindow -- Change window to "alternate" position and
                 dimensions. (V36)

    SYNOPSIS
    ZipWindow( Window )
           A0

    VOID ZipWindow( struct Window * );

    FUNCTION
    Changes the position and dimension of a window to the values
    at the last occasion of ZipWindow being called (or invoked
    via the "zoom" gadget).

    Typically this is used to snap between a normal, large, working
    dimension of the window to a smaller, more innocuous position
    and dimension.

    Like MoveWindow(), SizeWindow(), and ChangeWindowBox(), the action of
    this function is deferred to the Intuition input handler.

    More tuning needs to be done to establish initial values for
    the first invocation of this function for a window.  You can
    provide initial values using the OpenWindow() tag item
    WA_Zoom.

    It could also use a new name, but "ZoomWindow" is misleading,
    since "Zoom" normally implies "scale."

    The zoom gadget will appear (in the place of the old "toback"
    gadget) when you open your window if you either specify a
    sizing gadget or use WA_Zoom.

    You can detect that this function has taken effect by receiving
    an IDCMP_CHANGEWINDOW IDCMP message.

    INPUTS
    Window -- window to be changed.

    RESULT
    None

    BUGS
    OpenWindow() assumes that the proper default "other" dimensions
    are "full size."

    SEE ALSO
    ChangeWindowBox(), MoveWindow(), SizeWindow()


Text_Autodocs/mathtrans.doc

TABLE OF CONTENTS

mathtrans.library/SPAcos
mathtrans.library/SPAsin
mathtrans.library/SPAtan
mathtrans.library/SPCos
mathtrans.library/SPCosh
mathtrans.library/SPExp
mathtrans.library/SPFieee
mathtrans.library/SPLog
mathtrans.library/SPLog10
mathtrans.library/SPPow
mathtrans.library/SPSin
mathtrans.library/SPSincos
mathtrans.library/SPSinh
mathtrans.library/SPSqrt
mathtrans.library/SPTan
mathtrans.library/SPTanh
mathtrans.library/SPTieee
 mathtrans.library/SPAcos                             mathtrans.library/SPAcos

NAME

    SPAcos - obtain the arccosine of the floating point number

SYNOPSIS

    fnum2 = SPAcos(fnum1);
                       d0.l
    float fnum2;
    float fnum1;

FUNCTION

    Accepts a floating point number representing the cosine
    of an angle and returns the value of said angle in
    radians

INPUTS

    fnum1 - Motorola fast floating point number

RESULT

    fnum2 - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPSin
 mathtrans.library/SPAsin                             mathtrans.library/SPAsin

NAME

    SPAsin - obtain the arcsine of the floating point number

SYNOPSIS

    fnum2 = SPAsin(fnum1);
                       d0.l
    float fnum2;
    float fnum1;

FUNCTION

    Accepts a floating point number representing the sine
    of an angle and returns the value of said angle in
    radians

INPUTS

    fnum1 - Motorola fast floating point number

RESULT

    fnum2 - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPCos
 mathtrans.library/SPAtan                             mathtrans.library/SPAtan

NAME

    SPAtan - obtain the arctangent of the floating point number

SYNOPSIS

    fnum2 = SPAtan(fnum1);
                       d0.l
    float fnum2;
    float fnum1;

FUNCTION

    Accepts a floating point number representing the tangent
    of an angle and returns the value of said angle in
    radians

INPUTS

    fnum1 - Motorola fast floating point number

RESULT

    fnum2 - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPTan
 mathtrans.library/SPCos                               mathtrans.library/SPCos

NAME

    SPCos - obtain the cosine of the floating point number

SYNOPSIS

    fnum2 = SPCos(fnum1);
                       d0.l
    float fnum2;
    float fnum1;

FUNCTION

    Accepts a floating point number representing an angle
    in radians and returns the cosine of said angle.

INPUTS

    fnum1 - Motorola fast floating point number

RESULT

    fnum2 - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPAcos
 mathtrans.library/SPCosh                             mathtrans.library/SPCosh

NAME

    SPCosh - obtain the hyperbolic cosine of the floating point number

SYNOPSIS

    fnum2 = SPCosh(fnum1);
                       d0.l
    float fnum2;
    float fnum1;

FUNCTION

    Accepts a floating point number representing an angle
    in radians and returns the hyperbolic cosine of said angle.

INPUTS

    fnum1 - Motorola fast floating point number

RESULT

    fnum2 - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPSinh
 mathtrans.library/SPExp                               mathtrans.library/SPExp

NAME

    SPExp - obtain the exponential (e**X) of the floating point number

SYNOPSIS

    fnum2 = SPExp(fnum1);
                      d0.l
    float fnum2;
    float fnum1;

FUNCTION

    Accepts a floating point number and returns the value
    of e raised to the fnum1 power

INPUTS

    fnum1 - Motorola fast floating point number

RESULT

    fnum2 - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPLog
 mathtrans.library/SPFieee                           mathtrans.library/SPFieee

NAME

    SPFieee - convert single precision ieee to FFP number

SYNOPSIS

    fnum = SPFieee(ieeenum);
                       d0.l
    float fnum;
    float ieeenum;

FUNCTION

    Accepts a standard single precision format
    returns the same number, converted to Motorola
    fast floating point number

INPUTS

    ieeenum - IEEE Single Precision Floating Point

RESULT

    fnum - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPTieee
 mathtrans.library/SPLog                               mathtrans.library/SPLog

NAME

    SPLog - obtain the natural logarithm of the floating point number

SYNOPSIS

    fnum2 = SPLog(fnum1);
                      d0.l
    float fnum2;
    float fnum1;

FUNCTION

    Accepts a floating point number and returns the natural
    logarithem (base e) of said number

INPUTS

    fnum1 - Motorola fast floating point number

RESULT

    fnum2 - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPExp
 mathtrans.library/SPLog10                           mathtrans.library/SPLog10

NAME

    SPLog10 - obtain the naperian logarithm(base 10) of the
          floating point number

SYNOPSIS

    fnum2 = SPLog10(fnum1);
                        d0.l
    float fnum2;
    float fnum1;

FUNCTION

    Accepts a floating point number and returns the naperian
    logarithm (base 10) of said number

INPUTS

    fnum1 - Motorola fast floating point number

RESULT

    fnum2 - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPExp, SpLog
 mathtrans.library/SPPow                               mathtrans.library/SPPow

NAME

    SPPow - raise a number to a power

SYNOPSIS

    result = SPPow(fnum1, fnum2);
                      d1.l    d0.l
    float fnum1, fnum2;
    float result;

FUNCTION

    Accepts two floating point numbers and returns the
    result of fnum2 raised to the fnum1 power

INPUTS

    fnum1 - Motorola fast floating point number
    fnum2 - Motorola fast floating point number

RESULT

    result - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPExp, SPLog
 mathtrans.library/SPSin                               mathtrans.library/SPSin

NAME

    SPSin - obtain the sine of the floating point number

SYNOPSIS

    fnum2 = SPSin(fnum1);
                       d0.l
    float fnum2;
    float fnum1;

FUNCTION

    Accepts a floating point number representing an angle
    in radians and returns the sine of said angle.

INPUTS

    fnum1 - Motorola fast floating point number

RESULT

    fnum2 - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPAsin
 mathtrans.library/SPSincos                         mathtrans.library/SPSincos

NAME

    SPSincos - obtain the sine and cosine of a number

SYNOPSIS

    fnum3 = SPSincos(pfnum2, fnum1);
                         d1.l,   d0.l
    float *pfnum2;
    float fnum1;
    float fnum3;

FUNCTION

    Accepts a floating point number (fnum1) representing
    an angle in radians and a pointer to another floating
    point number (pfnum2). It computes the cosine and places it in
    *pfnum2. It computes the sine and returns it as a result.

INPUTS

    fnum1 - Motorola fast floating point number
    pfnum2 - pointer to Motorola fast floating point number

RESULT

    *pfnum2 - Motorola fast floating point number (cosine)
    fnum3 - Motorola fast floating point number (sine)

BUGS

    None

SEE ALSO

    SPSin, SPCos
 mathtrans.library/SPSinh                             mathtrans.library/SPSinh

NAME

    SPSinh - obtain the hyperbolic sine of the floating point number

SYNOPSIS

    fnum2 = SPSinh(fnum1);
                       d0.l
    float fnum2;
    float fnum1;

FUNCTION

    Accepts a floating point number representing an angle
    in radians and returns the hyperbolic sine of said angle.

INPUTS

    fnum1 - Motorola fast floating point number

RESULT

    fnum2 - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPCosh
 mathtrans.library/SPSqrt                             mathtrans.library/SPSqrt

NAME

    SPSqrt - obtain the square root of the floating point number

SYNOPSIS

    fnum2 = SPSqrt(fnum1);
                      d0.l
    float fnum2;
    float fnum1;

FUNCTION

    Accepts a floating point number and returns the square toot
    of said number

INPUTS

    fnum1 - Motorola fast floating point number

RESULT

    fnum2 - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPPow, SPMul
 mathtrans.library/SPTan                               mathtrans.library/SPTan

NAME

    SPTan - obtain the tangent of the floating point number

SYNOPSIS

    fnum2 = SPTan(fnum1);
                       d0.l
    float fnum2;
    float fnum1;

FUNCTION

    Accepts a floating point number representing an angle
    in radians and returns the tangent of said angle.

INPUTS

    fnum1 - Motorola fast floating point number

RESULT

    fnum2 - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPAtan
 mathtrans.library/SPTanh                             mathtrans.library/SPTanh

NAME

    SPTanh - obtain the hyperbolic tangent of the floating point number

SYNOPSIS

    fnum2 = SPTanh(fnum1);
                       d0.l
    float fnum2;
    float fnum1;

FUNCTION

    Accepts a floating point number representing an angle
    in radians and returns the hyperbolic tangent of said angle.

INPUTS

    fnum1 - Motorola fast floating point number

RESULT

    fnum2 - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPSinh, SPCosh
 mathtrans.library/SPTieee                           mathtrans.library/SPTieee

NAME

    SPTieee - convert FFP number to single precision ieee

SYNOPSIS

    ieeenum = SPTieee(fnum);
                         d0.l
    float ieeenum;
    float fnum;

FUNCTION

       Accepts a Motorola fast floating point number and
       returns the same number, converted into IEEE
       standard single precision format

INPUTS

    fnum - Motorola fast floating point number

RESULT

    ieeenum - IEEE Single Precision Floating Point

BUGS

    None

SEE ALSO

    SPFieee


Text_Autodocs/dos.doc

TABLE OF CONTENTS

dos.library/AbortPkt
dos.library/AddBuffers
dos.library/AddDosEntry
dos.library/AddPart
dos.library/AddSegment
dos.library/AllocDosObject
dos.library/AssignAdd
dos.library/AssignLate
dos.library/AssignLock
dos.library/AssignPath
dos.library/AttemptLockDosList
dos.library/ChangeMode
dos.library/CheckSignal
dos.library/Cli
dos.library/CliInitNewcli
dos.library/CliInitRun
dos.library/Close
dos.library/CompareDates
dos.library/CreateDir
dos.library/CreateNewProc
dos.library/CreateProc
dos.library/CurrentDir
dos.library/DateStamp
dos.library/DateToStr
dos.library/Delay
dos.library/DeleteFile
dos.library/DeleteVar
dos.library/DeviceProc
dos.library/DoPkt
dos.library/DupLock
dos.library/DupLockFromFH
dos.library/EndNotify
dos.library/ErrorReport
dos.library/ExAll
dos.library/Examine
dos.library/ExamineFH
dos.library/Execute
dos.library/Exit
dos.library/ExNext
dos.library/Fault
dos.library/FGetC
dos.library/FGets
dos.library/FilePart
dos.library/FindArg
dos.library/FindCliProc
dos.library/FindDosEntry
dos.library/FindSegment
dos.library/FindVar
dos.library/Flush
dos.library/Format
dos.library/FPutC
dos.library/FPuts
dos.library/FRead
dos.library/FreeArgs
dos.library/FreeDeviceProc
dos.library/FreeDosEntry
dos.library/FreeDosObject
dos.library/FWrite
dos.library/GetArgStr
dos.library/GetConsoleTask
dos.library/GetCurrentDirName
dos.library/GetDeviceProc
dos.library/GetFileSysTask
dos.library/GetProgramDir
dos.library/GetProgramName
dos.library/GetPrompt
dos.library/GetVar
dos.library/Info
dos.library/Inhibit
dos.library/Input
dos.library/InternalLoadSeg
dos.library/InternalUnLoadSeg
dos.library/IoErr
dos.library/IsFileSystem
dos.library/IsInteractive
dos.library/LoadSeg
dos.library/Lock
dos.library/LockDosList
dos.library/LockRecord
dos.library/LockRecords
dos.library/MakeDosEntry
dos.library/MakeLink
dos.library/MatchEnd
dos.library/MatchFirst
dos.library/MatchNext
dos.library/MatchPattern
dos.library/MatchPatternNoCase
dos.library/MaxCli
dos.library/NameFromFH
dos.library/NameFromLock
dos.library/NewLoadSeg
dos.library/NextDosEntry
dos.library/Open
dos.library/OpenFromLock
dos.library/Output
dos.library/ParentDir
dos.library/ParentOfFH
dos.library/ParsePattern
dos.library/ParsePatternNoCase
dos.library/PathPart
dos.library/PrintFault
dos.library/PutStr
dos.library/Read
dos.library/ReadArgs
dos.library/ReadItem
dos.library/ReadLink
dos.library/Relabel
dos.library/RemAssignList
dos.library/RemDosEntry
dos.library/RemSegment
dos.library/Rename
dos.library/ReplyPkt
dos.library/RunCommand
dos.library/SameDevice
dos.library/SameLock
dos.library/Seek
dos.library/SelectInput
dos.library/SelectOutput
dos.library/SendPkt
dos.library/SetArgStr
dos.library/SetComment
dos.library/SetConsoleTask
dos.library/SetCurrentDirName
dos.library/SetFileDate
dos.library/SetFileSize
dos.library/SetFileSysTask
dos.library/SetIoErr
dos.library/SetMode
dos.library/SetProgramDir
dos.library/SetProgramName
dos.library/SetPrompt
dos.library/SetProtection
dos.library/SetVar
dos.library/SetVBuf
dos.library/SplitName
dos.library/StartNotify
dos.library/StrToDate
dos.library/StrToLong
dos.library/SystemTagList
dos.library/UnGetC
dos.library/UnLoadSeg
dos.library/UnLock
dos.library/UnLockDosList
dos.library/UnLockRecord
dos.library/UnLockRecords
dos.library/VFPrintf
dos.library/VFWritef
dos.library/VPrintf
dos.library/WaitForChar
dos.library/WaitPkt
dos.library/Write
dos.library/WriteChars
 dos.library/AbortPkt                                     dos.library/AbortPkt

   NAME
    AbortPkt -- Aborts an asynchronous packet, if possible. (V36)

   SYNOPSIS
    AbortPkt(port, pkt)
          D1    D2

    void AbortPkt(struct MsgPort *, struct DosPacket *)

   FUNCTION
    This attempts to abort a packet sent earlier with SendPkt to a
    handler.  There is no guarantee that any given handler will allow
    a packet to be aborted, or if it is aborted whether function
    requested completed first or completely.  After calling AbortPkt(),
    you must wait for the packet to return before reusing it or
    deallocating it.

   INPUTS
    port - port the packet was sent to
    pkt  - the packet you wish aborted

   BUGS
    As of V37, this function does nothing.

   SEE ALSO
    SendPkt(), DoPkt(), WaitPkt()

 dos.library/AddBuffers                                 dos.library/AddBuffers

   NAME
    AddBuffers -- Changes the number of buffers for a filesystem (V36)

   SYNOPSIS
    success = AddBuffers(filesystem, number)
    D0		       D1          D2

    BOOL AddBuffers(STRPTR, LONG)

   FUNCTION
    Adds buffers to a filesystem.  If it succeeds, the number of current
    buffers is returned in IoErr().  Note that "number" may be negative.
    The amount of memory used per buffer, and any limits on the number of
    buffers, are dependant on the filesystem in question.
    If the call succeeds, the number of buffers in use on the filesystem
    will be returned by IoErr().

   INPUTS
    filesystem - Name of device to add buffers to (with ':').
    number     - Number of buffers to add.  May be negative.

   RESULT
    success    - Success or failure of command.

   BUGS
    The V36 ROM filesystem (FFS/OFS) doesn't return the right number of
    buffers unless preceded by an AddBuffers(fs,-1) (in-use buffers aren't
    counted).  This is fixed in V37.

    The V37 and before ROM filesystem doesn't return success, it returns
    the number of buffers.  The best way to test for this is to consider
    0 (FALSE) failure, -1 (DOSTRUE) to mean that IoErr() will have the
    number of buffers, and any other positive value to be the number of
    buffers.  It may be fixed in some future ROM revision.

   SEE ALSO
    IoErr()

 dos.library/AddDosEntry                               dos.library/AddDosEntry

   NAME
    AddDosEntry -- Add a Dos List entry to the lists (V36)

   SYNOPSIS
    success = AddDosEntry(dlist)
    D0                     D1

    LONG AddDosEntry(struct DosList *)

   FUNCTION
    Adds a device, volume or assign to the dos devicelist.  Can fail if it
    conflicts with an existing entry (such as another assign to the same
    name or another device of the same name).  Volume nodes with different
    dates and the same name CAN be added, or with names that conflict with
    devices or assigns.  Note: the dos list does NOT have to be locked to
    call this.  Do not access dlist after adding unless you have locked the
    Dos Device list.

    An additional note concerning calling this from within a handler:
    in order to avoid deadlocks, your handler must either be multi-
    threaded, or it must attempt to lock the list before calling this
    function.  The code would look something like this:

    if (AttemptLockDosList(LDF_xxx|LDF_WRITE))
    {
        rc = AddDosEntry(...);
        UnLockDosList(LDF_xxx|LDF_WRITE);
    }

    If AttemptLockDosList() fails (i.e. it's locked already), check for
    messages at your filesystem port (don't wait!) and try the
    AttemptLockDosList() again.

   INPUTS
    dlist   - Device list entry to be added.

   RESULT
    success - Success/Failure indicator

   SEE ALSO
    RemDosEntry(), FindDosEntry(), NextDosEntry(), LockDosList(),
    MakeDosEntry(), FreeDosEntry(), AttemptLockDosList()

 dos.library/AddPart                                       dos.library/AddPart

   NAME
    AddPart -- Appends a file/dir to the end of a path (V36)

   SYNOPSIS
    success = AddPart( dirname, filename, size )
    D0                   D1        D2      D3

    BOOL AddPart( STRPTR, STRPTR, ULONG )

   FUNCTION
    This function adds a file, directory, or subpath name to a directory
    path name taking into account any required separator characters.  If
    filename is a fully-qualified path it will totally replace the current
    value of dirname.

   INPUTS
    dirname  - the path to add a file/directory name to.
    filename - the filename or directory name to add.  May be a relative
           pathname from the current directory (example: foo/bar).
           Can deal with leading '/'(s), indicating one directory up
           per '/', or with a ':', indicating it's relative to the
           root of the appropriate volume.
    size     - size in bytes of the space allocated for dirname.  Must
           not be 0.

   RESULT
    success - non-zero for ok, FALSE if the buffer would have overflowed.
          If an overflow would have occured, dirname will not be
          changed.

   BUGS
    Doesn't check if a subpath is legal (i.e. doesn't check for ':'s) and
    doesn't handle leading '/'s in 2.0 through 2.02 (V36).  V37 fixes
    this, allowing filename to be any path, including absolute.

   SEE ALSO
    Filepart(), PathPart()

 dos.library/AddSegment                                 dos.library/AddSegment

   NAME
    AddSegment - Adds a resident segment to the resident list (V36)

   SYNOPSIS
    success = AddSegment(name, seglist, type)
    D0		      D1     D2      D3

    BOOL AddSegment(STRPTR, BPTR, LONG)

   FUNCTION
    Adds a segment to the Dos resident list, with the specified Seglist
    and type (stored in seg_UC - normally 0).  NOTE: currently unused
    types may cause it to interpret other registers (d4-?) as additional
    parameters in the future.

    Do NOT build Segment structures yourself!

   INPUTS
    name    - name for the segment
    seglist - Dos seglist of code for segment
    type    - initial usecount, normally 0

   RESULT
    success - success or failure

   SEE ALSO
    FindSegment(), RemSegment(), LoadSeg()

 dos.library/AllocDosObject                         dos.library/AllocDosObject

   NAME
    AllocDosObject -- Creates a dos object (V36)

   SYNOPSIS
    ptr = AllocDosObject(type, tags)
    D0                    D1    D2

    void *AllocDosObject(ULONG, struct TagItem *)

    ptr = AllocDosObjectTagList(type, tags)
    D0                 	     D1    D2

    void *AllocDosObjectTagList(ULONG, struct TagItem *)

    ptr = AllocDosObjectTags(type, Tag1, ...)

    void *AllocDosObjectTags(ULONG, ULONG, ...)

   FUNCTION
    Create one of several dos objects, initializes it, and returns it
    to you.  Note the DOS_STDPKT returns a pointer to the sp_Pkt of the
    structure.

   INPUTS
    type - type of object requested
    tags - pointer to taglist with additional information

   RESULT
    packet - pointer to the object or NULL

   SEE ALSO
    FreeDosObject(), <dos/dostags.h>, <dos/dos.h>

 dos.library/AssignAdd                                   dos.library/AssignAdd

   NAME
    AssignAdd -- Adds a lock to an assign for multi-directory assigns (V36)

   SYNOPSIS
    success = AssignAdd(name,lock)
    D0                   D1   D2

    BOOL AssignAdd(STRPTR,BPTR)

   FUNCTION
    Adds a lock to an assign, making or adding to a multi-directory
    assign.  Note that this only will succeed on an assign created with
    AssignLock(), or an assign created with AssignLate() which has been
    resolved (converted into a AssignLock()-assign).

    NOTE: you should not use the lock in any way after making this call
    successfully.  It becomes the part of the assign, and will be unlocked
    by the system when the assign is removed.  If you need to keep the
    lock, pass a lock from DupLock() to AssignLock().

   INPUTS
    name - Name of device to assign lock to (without trailing ':')
    lock - Lock associated with the assigned name

   RESULT
    success - Success/failure indicator.  On failure, the lock is not
          unlocked.

   SEE ALSO
    Lock(), AssignLock(), AssignPath(), AssignLate(), DupLock(),
    RemAssignList()

 dos.library/AssignLate                                 dos.library/AssignLate

   NAME
    AssignLate -- Creates an assignment to a specified path later (V36)

   SYNOPSIS
    success = AssignLate(name,path)
    D0                    D1   D2

    BOOL AssignLate(STRPTR,STRPTR)

   FUNCTION
    Sets up a assignment that is expanded upon the FIRST reference to the
    name.  The path (a string) would be attached to the node.  When
    the name is referenced (Open("FOO:xyzzy"...), the string will be used
    to determine where to set the assign to, and if the directory can be
    locked, the assign will act from that point on as if it had been
    created by AssignLock().

    A major advantage is assigning things to unmounted volumes, which
    will be requested upon access (useful in startup sequences).

   INPUTS
    name - Name of device to be assigned (without trailing ':')
    path - Name of late assignment to be resolved on the first reference.

   RESULT
    success - Success/failure indicator of the operation

   SEE ALSO
    Lock(), AssignAdd(), AssignPath(), AssignLock(),

 dos.library/AssignLock                                 dos.library/AssignLock

   NAME
    AssignLock -- Creates an assignment to a locked object (V36)

   SYNOPSIS
    success = AssignLock(name,lock)
    D0                    D1   D2

    BOOL AssignLock(STRPTR,BPTR)

   FUNCTION
    Sets up an assign of a name to a given lock.  Passing NULL for a lock
    cancels any outstanding assign to that name.  If an assign entry of
    that name is already on the list, this routine replaces that entry.  If
    an entry is on the list that conflicts with the new assign, then a
    failure code is returned.

    NOTE: you should not use the lock in any way after making this call
    successfully.  It becomes the assign, and will be unlocked by the
    system when the assign is removed.  If you need to keep the lock,
    pass a lock from DupLock() to AssignLock().

   INPUTS
    name - Name of device to assign lock to (without trailing ':')
    lock - Lock associated with the assigned name

   RESULT
    success - Success/failure indicator.  On failure, the lock is not
          unlocked.

   SEE ALSO
    Lock(), AssignAdd(), AssignPath(), AssignLate(), DupLock(),
    RemAssignList()

 dos.library/AssignPath                                 dos.library/AssignPath

   NAME
    AssignPath -- Creates an assignment to a specified path (V36)

   SYNOPSIS
    success = AssignPath(name,path)
    D0                    D1   D2

    BOOL AssignPath(STRPTR,STRPTR)

   FUNCTION
    Sets up a assignment that is expanded upon EACH reference to the name.
    This is implemented through a new device list type (DLT_ASSIGNPATH, or
    some such).  The path (a string) would be attached to the node.  When
    the name is referenced (Open("FOO:xyzzy"...), the string will be used
    to determine where to do the open.  No permanent lock will be part of
    it.  For example, you could AssignPath() c2: to df2:c, and references
    to c2: would go to df2:c, even if you change disks.

    The other major advantage is assigning things to unmounted volumes,
    which will be requested upon access (useful in startup sequences).

   INPUTS
    name - Name of device to be assigned (without trailing ':')
    path - Name of late assignment to be resolved at each reference

   RESULT
    success - Success/failure indicator of the operation

   SEE ALSO
    AssignAdd(), AssignLock(), AssignLate(), Open()

 dos.library/AttemptLockDosList                 dos.library/AttemptLockDosList

   NAME
    AttemptLockDosList -- Attempt to lock the Dos Lists for use (V36)

   SYNOPSIS
    dlist = AttemptLockDosList(flags)
    D0			    D1

    struct DosList *AttemptLockDosList(ULONG)

   FUNCTION
    Locks the dos device list in preparation to walk the list.  If the
    list is 'busy' then this routine will return NULL.  See LockDosList()
    for more information.

   INPUTS
    flags - Flags stating which types of nodes you want to lock.

   RESULT
    dlist - Pointer to the beginning of the list or NULL.  Not a valid
        node!

   SEE ALSO
    LockDosList(), UnLockDosList(), Forbid(), NextDosEntry()

 dos.library/ChangeMode                                 dos.library/ChangeMode

   NAME
    ChangeMode - Change the current mode of a lock or filehandle (V36)

   SYNOPSIS
    success = ChangeMode(type, object, newmode)
    D0                    D1     D2      D3

    BOOL ChangeMode(ULONG, BPTR, ULONG)

   FUNCTION
    This allows you to attempt to change the mode in use by a lock or
    filehandle.  For example, you could attempt to turn a shared lock
    into an exclusive lock.  The handler may well reject this request.
    Warning: if you use the wrong type for the object, the system may
    crash.

   INPUTS
    type    - Either CHANGE_FH or CHANGE_LOCK
    object  - A lock or filehandle
    newmode - The new mode you want

   RESULT
    success - Boolean

   BUGS
    Did not work in 2.02 or before (V36).  Works in V37.  In the
    earlier versions, it can crash the machine.

   SEE ALSO
    Lock(), Open()

 dos.library/CheckSignal                               dos.library/CheckSignal

   NAME
    CheckSignal -- Checks for break signals (V36)

   SYNOPSIS
    signals = CheckSignal(mask)
    D0		      D1

    ULONG CheckSignals(ULONG)

   FUNCTION
    This function checks to see if any signals specified in the mask have
    been set and if so, returns them.  Otherwise it returns FALSE.
    All signals specified in mask will be cleared.

   INPUTS
    mask    - Signals to check for.

   RESULT
    signals - Signals specified in mask that were set.

   SEE ALSO

 dos.library/Cli                                               dos.library/Cli

   NAME
    Cli -- Returns a pointer to the CLI structure of the process (V36)

   SYNOPSIS
    cli_ptr = Cli()
    D0

    struct CommandLineInterface *Cli(void)

   FUNCTION
    Returns a pointer to the CLI structure of the current process, or NULL
    if the process has no CLI structure.

   RESULT
    cli_ptr - pointer to the CLI structure, or NULL.

   SEE ALSO

 dos.library/CliInitNewcli                           dos.library/CliInitNewcli

   NAME
    CliInitNewcli -- Set up a process to be a shell from initial packet

   SYNOPSIS
    flags = CliInitNewcli( packet )
    D0		         A0

    LONG CliInitNewcli( struct DosPacket * )

   FUNCTION
    This function initializes a process and CLI structure for a new
    shell, from parameters in an initial packet passed by the system
    (NewShell or NewCLI, etc).  The format of the data in the packet
    is purposely not defined.  The setup includes all the normal fields
    in the structures that are required for proper operation (current
    directory, paths, input streams, etc).

    It returns a set of flags containing information about what type
    of shell invocation this is.

    Definitions for the values of fn:
        Bit 31     Set to indicate flags are valid
        Bit  3     Set to indicate asynch system call
        Bit  2     Set if this is a System() call
        Bit  1     Set if user provided input stream
        Bit  0     Set if RUN provided output stream

    If Bit 31 is 0, then you must check IoErr() to determine if an error
    occurred.  If IoErr() returns a pointer to your process, there has
    been an error, and you should clean up and exit.  The packet will
    have already been returned by CliInitNewcli().  If it isn't a pointer
    to your process and Bit 31 is 0, reply the packet immediately.
    (Note: this is different from what you do for CliInitRun().)

    This function is very similar to CliInitRun().

   INPUTS
    packet - the initial packet sent to your process MsgPort

   RESULT
    fn - flags or a pointer

   SEE ALSO
    CliInitRun(), ReplyPkt(), WaitPkt(), IoErr()

 dos.library/CliInitRun                                 dos.library/CliInitRun

   NAME
    CliInitRun -- Set up a process to be a shell from initial packet

   SYNOPSIS
    flags = CliInitRun( packet )
    D0		      A0

    LONG CliInitRun( struct DosPacket * )

   FUNCTION
    This function initializes a process and CLI structure for a new
    shell, from parameters in an initial packet passed by the system
    (Run, System(), Execute()).  The format of the data in the packet
    is purposely not defined.  The setup includes all the normal fields
    in the structures that are required for proper operation (current
    directory, paths, input streams, etc).

    It returns a set of flags containing information about what type
    of shell invocation this is.

    Definitions for the values of fn:
        Bit 31     Set to indicate flags are valid
        Bit  3     Set to indicate asynch system call
        Bit  2     Set if this is a System() call
        Bit  1     Set if user provided input stream
        Bit  0     Set if RUN provided output stream

    If Bit 31 is 0, then you must check IoErr() to determine if an error
    occurred.  If IoErr() returns a pointer to your process, there has
    been an error, and you should clean up and exit.  The packet will
    have already been returned by CliInitNewcli().  If it isn't a pointer
    to your process and Bit 31 is 0, you should wait before replying
    the packet until after you've loaded the first command (or when you
    exit).  This helps avoid disk "gronking" with the Run command.
    (Note: this is different from what you do for CliInitNewcli().)

    If Bit 31 is 1, then if Bit 3 is one, ReplyPkt() the packet
    immediately (Asynch System()), otherwise wait until your shell exits
    (Sync System(), Execute()).
    (Note: this is different from what you do for CliInitNewcli().)

    This function is very similar to CliInitNewcli().

   INPUTS
    packet - the initial packet sent to your process MsgPort

   RESULT
    fn - flags or a pointer

   SEE ALSO
    CliInitNewcli(), ReplyPkt(), WaitPkt(), System(), Execute(), IoErr()

 dos.library/Close                                           dos.library/Close

    NAME
    Close -- Close an open file

    SYNOPSIS
    success = Close( file )
       D0             D1

    BOOL Close(BPTR)

    FUNCTION
    The file specified by the file handle is closed. You must close all
    files you explicitly opened, but you must not close inherited file
    handles that are passed to you (each filehandle must be closed once
    and ONLY once).  If Close() fails, the file handle is still
    deallocated and should not be used.

    INPUTS
    file - BCPL pointer to a file handle

    RESULTS
    success - returns if Close() succeeded.  Note that it might fail
          depending on buffering and whatever IO must be done to
          close a file being written to.  NOTE: this return value
          did not exist before V36!

    SEE ALSO
    Open(), OpenFromLock()

 dos.library/CompareDates                             dos.library/CompareDates

   NAME
    CompareDates -- Compares two datestamps (V36)

   SYNOPSIS
    result = CompareDates(date1,date2)
    D0                     D1     D2

    LONG CompareDates(struct DateStamp *,struct DateStamp *)

   FUNCTION
    Compares two times for relative magnitide.  <0 is returned if date1 is
    later than date2, 0 if they are equal, or >0 if date2 is later than
    date1.  NOTE: this is NOT the same ordering as strcmp!

   INPUTS
    date1, date2 - DateStamps to compare

   RESULT
    result -  <0, 0, or >0 based on comparison of two date stamps

   SEE ALSO
    DateStamp(), DateToStr(), StrToDate()

 dos.library/CreateDir                                   dos.library/CreateDir

    NAME
    CreateDir -- Create a new directory

    SYNOPSIS
    lock = CreateDir( name )
    D0		  D1

    BPTR CreateDir(STRPTR)

    FUNCTION
    CreateDir creates a new directory with the specified name. An error
    is returned if it fails.  Directories can only be created on
    devices which support them, e.g. disks.  CreateDir returns an
    exclusive lock on the new directory if it succeeds.

    INPUTS
    name - pointer to a null-terminated string

    RESULTS
    lock - BCPL pointer to a lock or NULL for failure.

    SEE ALSO
    Lock(), UnLock()

 dos.library/CreateNewProc                           dos.library/CreateNewProc

   NAME
    CreateNewProc -- Create a new process (V36)

   SYNOPSIS
    process = CreateNewProc(tags)
    D0                       D1

    struct Process *CreateNewProc(struct TagItem *)

    process = CreateNewProcTagList(tags)
    D0                       	D1

    struct Process *CreateNewProcTagList(struct TagItem *)

    process = CreateNewProcTags(Tag1, ...)

    struct Process *CreateNewProcTags(ULONG, ...)

   FUNCTION
    This creates a new process according to the tags passed in.  See
    dos/dostags.h for the tags.

    You must specify one of NP_Seglist or NP_Entry.  NP_Seglist takes a
    seglist (as returned by LoadSeg()).  NP_Entry takes a function
    pointer for the routine to call.

    There are many options, as you can see by examining dos/dostags.h.
    The defaults are for a non-CLI process, with copies of your
    CurrentDir, HomeDir (used for PROGDIR:), priority, consoletask,
    windowptr, and variables.  The input and output filehandles default
    to opens of NIL:, stack to 4000, and others as shown in dostags.h.
    This is a fairly reasonable default setting for creating threads,
    though you may wish to modify it (for example, to give a descriptive
    name to the process.)

    CreateNewProc() is callable from a task, though any actions that
    require doing Dos I/O (DupLock() of currentdir, for example) will not
    occur.

    NOTE: if you call CreateNewProc() with both NP_Arguments, you must
    not specify an NP_Input of NULL.  When NP_Arguments is specified, it
    needs to modify the input filehandle to make ReadArgs() work properly.

   INPUTS
    tags - a pointer to a TagItem array.

   RESULT
    process - The created process, or NULL.  Note that if it returns
          NULL, you must free any items that were passed in via
          tags, such as if you passed in a new current directory
          with NP_CurrentDir.

   BUGS
    In V36, NP_Arguments was broken in a number of ways, and probably
    should be avoided (instead you should start a small piece of your
    own code, which calls RunCommand() to run the actual code you wish
    to run).  In V37, NP_Arguments works, though see the note above.

   SEE ALSO
    LoadSeg(), CreateProc(), ReadArgs(), RunCommand(), <dos/dostags.h>

 dos.library/CreateProc                                 dos.library/CreateProc

    NAME

    CreateProc -- Create a new process

    SYNOPSIS
    process = CreateProc( name, pri, seglist, stackSize )
    D0		      D1    D2	 D3	  D4

    struct MsgPort *CreateProc(STRPTR, LONG, BPTR, LONG)

    FUNCTION
    CreateProc() creates a new AmigaDOS process of name 'name'.  AmigaDOS
    processes are a superset of exec tasks.

    A seglist, as returned by LoadSeg(), is passed as 'seglist'.
    This represents a section of code which is to be run as a new
    process. The code is entered at the first hunk in the segment list,
    which should contain suitable initialization code or a jump to
    such.  A process control structure is allocated from memory and
    initialized.  If you wish to fake a seglist (that will never
    have DOS UnLoadSeg() called on it), use this code:

            DS.L    0	;Align to longword
            DC.L    16	;Segment "length" (faked)
            DC.L    0	;Pointer to next segment
            ...start of code...

    The size of the root stack upon activation is passed as
    'stackSize'.  'pri' specifies the required priority of the new
    process.  The result will be the process msgport address of the new
    process, or zero if the routine failed.  The argument 'name'
    specifies the new process name.  A zero return code indicates
    error.

    The seglist passed to CreateProc() is not freed when it exits; it
    is up to the parent process to free it, or for the code to unload
    itself.

    Under V36 and later, you probably should use CreateNewProc() instead.

    INPUTS
    name      - pointer to a null-terminated string
    pri       - signed long (range -128 to +127)
    seglist   - BCPL pointer to a seglist
    stackSize - integer (must be a multiple of 4 bytes)

    RESULTS
    process   - pointer to new process msgport

    SEE ALSO
    CreateNewProc(), LoadSeg(), UnLoadSeg()

 dos.library/CurrentDir                                 dos.library/CurrentDir

    NAME
    CurrentDir -- Make a directory lock the current directory

    SYNOPSIS
    oldLock = CurrentDir( lock )
    D0		      D1

    BPTR CurrentDir(BPTR)

    FUNCTION
    CurrentDir() causes a directory associated with a lock to be made
    the current directory.	The old current directory lock is returned.

    A value of zero is a valid result here, this 0 lock represents the
    root of file system that you booted from.

    Any call that has to Open() or Lock() files (etc) requires that
    the current directory be a valid lock or 0.

    INPUTS
    lock - BCPL pointer to a lock

    RESULTS
    oldLock - BCPL pointer to a lock

    SEE ALSO
    Lock(), UnLock(), Open(), DupLock()

 dos.library/DateStamp                                   dos.library/DateStamp

    NAME
    DateStamp -- Obtain the date and time in internal format

    SYNOPSIS
    ds = DateStamp( ds );
    D0		D1

    struct DateStamp *DateStamp(struct DateStamp *)

    FUNCTION
    DateStamp() takes a structure of three longwords that is set to the
    current time.  The first element in the vector is a count of the
    number of days.  The second element is the number of minutes elapsed
    in the day.  The third is the number of ticks elapsed in the current
    minute.  A tick happens 50 times a second.  DateStamp() ensures that
    the day and minute are consistent.  All three elements are zero if
    the date is unset. DateStamp() currently only returns even
    multiples of 50 ticks.  Therefore the time you get is always an even
    number of ticks.

    Time is measured from Jan 1, 1978.

    INPUTS
    ds - pointer a struct DateStamp

    RESULTS
    The array is filled as described and returned (for pre-V36
    compabability).

    SEE ALSO
    DateToStr(), StrToDate(), SetFileDate(), CompareDates()

 dos.library/DateToStr                                   dos.library/DateToStr

   NAME
    DateToStr -- Converts a DateStamp to a string (V36)

   SYNOPSIS
    success = DateToStr( datetime )
    D0                      D1

    BOOL DateToStr(struct DateTime *)

   FUNCTION
    StamptoStr converts an AmigaDOS DateStamp to a human
    readable ASCII string as requested by your settings in the
    DateTime structure.

   INPUTS
    DateTime - a pointer to an initialized DateTime structure.

    The DateTime structure should be initialized as follows:

    dat_Stamp - a copy of the datestamp you wish to convert to
          ascii.

    dat_Format - a format	byte which specifies the format	of the
          dat_StrDate.	This can be any	of the following
          (note: If value used is something other than those
          below, the default of	FORMAT_DOS is used):

          FORMAT_DOS:	  AmigaDOS format (dd-mmm-yy).

          FORMAT_INT:	  International	format (yy-mmm-dd).

          FORMAT_USA:	  American format (mm-dd-yy).

          FORMAT_CDN:	  Canadian format (dd-mm-yy).

          FORMAT_DEF:	  default format for locale.

    dat_Flags - a	flags byte.  The only flag which affects this
          function is:

          DTF_SUBST:	  If set, a string such	as Today,
                  Monday, etc.,	will be	used instead
                  of the dat_Format specification if
                  possible.
          DTF_FUTURE:	  Ignored by this function.

    dat_StrDay - pointer to a buffer to receive the day of the
          week string.	(Monday, Tuesday, etc.). If null, this
          string will not be generated.

    dat_StrDate -	pointer	to a buffer to receive the date
          string, in the format	requested by dat_Format,
          subject to possible modifications by DTF_SUBST.  If
          null,	this string will not be	generated.

    dat_StrTime -	pointer	to a buffer to receive the time	of day
          string. If NULL, this	will not be generated.

   RESULT
    success	- a zero return indicates that the DateStamp was
          invalid, and could not be converted.	Non-zero
          indicates that the call succeeded.

   SEE ALSO
    DateStamp(), StrtoDate(), <dos/datetime.h>

 dos.library/Delay                                           dos.library/Delay

    NAME
    Delay -- Delay a process for a specified time

    SYNOPSIS
    Delay( ticks )
           D1

    void Delay(ULONG)

    FUNCTION
    The argument 'ticks' specifies how many ticks (50 per second) to
    wait before returning control.

    INPUTS
    ticks - integer

    BUGS
    Due to a bug in the timer.device in V1.2/V1.3, specifying a timeout
    of zero for Delay() can cause the unreliable timer & floppy disk
    operation.  This is fixed in V36 and later.

    SEE ALSO

 dos.library/DeleteFile                                 dos.library/DeleteFile

    NAME
    DeleteFile -- Delete a file or directory

    SYNOPSIS
    success = DeleteFile( name )
    D0		      D1

    BOOL DeleteFile(STRPTR)

    FUNCTION
    This attempts to delete the file or directory specified by 'name'.
    An error is returned if the deletion fails. Note that all the files
    within a directory must be deleted before the directory itself can
    be deleted.

    INPUTS
    name - pointer to a null-terminated string

    RESULTS
    success - boolean

    SEE ALSO

 dos.library/DeleteVar                                   dos.library/DeleteVar

   NAME
    DeleteVar -- Deletes a local or environment variable (V36)

   SYNOPSIS
    success = DeleteVar( name, flags )
    D0		      D1    D2

    BOOL DeleteVar(STRPTR, ULONG )

   FUNCTION
    Deletes a local or environment variable.

   INPUTS
    name   - pointer to an variable name.  Note variable names follow
         filesystem syntax and semantics.
    flags  - combination of type of var to delete (low 8 bits), and
         flags to control the behavior of this routine.  Currently
         defined flags include:

         GVF_LOCAL_ONLY  - delete a local (to your process) variable.
         GVF_GLOBAL_ONLY - delete a global environment variable.

         The default is to delete a local variable if found, otherwise
         a global environment variable if found (only for LV_VAR).

   RESULT
    success - If non-zero, the variable was sucessfully deleted, FALSE
          indicates failure.

   BUGS
    LV_VAR is the only type that can be global

   SEE ALSO
    GetVar(), SetVar(), FindVar(), DeleteFile(), <dos/var.h>

 dos.library/DeviceProc                                 dos.library/DeviceProc

    NAME
    DeviceProc -- Return the process MsgPort of specific I/O handler

    SYNOPSIS
    process = DeviceProc( name )
    D0		      D1

    struct MsgPort *DeviceProc (STRPTR)

    FUNCTION
    DeviceProc() returns the process identifier of the process which
    handles the device associated with the specified name. If no
    process handler can be found then the result is zero. If the name
    refers to an assign then a directory lock is returned in IoErr().
    This lock should not be UnLock()ed or Examine()ed (if you wish to do
    so, DupLock() it first).

    BUGS
    In V36, if you try to DeviceProc() something relative to an assign
    made with AssignPath(), it will fail.  This is because there's no
    way to know when to unlock the lock.  If you're writing code for
    V36 or later, it is highly advised you use GetDeviceProc() instead,
    or make your code conditional on V36 to use GetDeviceProc()/
    FreeDeviceProc().

    SEE ALSO
    GetDeviceProc(), FreeDeviceProc(), DupLock(), UnLock(), Examine()

 dos.library/DoPkt                                           dos.library/DoPkt

   NAME
    DoPkt -- Send a dos packet and wait for reply (V36)

   SYNOPSIS
    result1 = DoPkt(port,action,arg1,arg2,arg3,arg4,arg5)
    D0               D1    D2    D3   D4   D5   D6   D7

    LONG DoPkt(struct MsgPort *,LONG,LONG,LONG,LONG,LONG,LONG)

   FUNCTION
    Sends a packet to a handler and waits for it to return.  Any secondary
    return will be available in D1 AND from IoErr().  DoPkt() will work
    even if the caller is an exec task and not a process; however it will
    be slower, and may fail for some additional reasons, such as being
    unable to allocate a signal.  DoPkt() uses your pr_MsgPort for the
    reply, and will call pr_PktWait.  (See BUGS regarding tasks, though).

    Only allows 5 arguments to be specified.  For more arguments (packets
    support a maximum of 7) create a packet and use SendPkt()/WaitPkt().

   INPUTS
    port    - pr_MsgPort of the handler process to send to.
    action  - the action requested of the filesystem/handler
    arg1, arg2, arg3, arg4,arg5 - arguments, depend on the action, may not
           be required.

   RESULT
    result1 - the value returned in dp_Res1, or FALSE if there was some
          problem in sending the packet or recieving it.
    result2 - Available from IoErr() AND in register D1.

   BUGS
    Using DoPkt() from tasks doesn't work in V36. Use AllocDosObject(),
    PutMsg(), and WaitPort()/GetMsg() for a workaround, or you can call
    CreateNewProc() to start a process to do Dos I/O for you.  In V37,
    DoPkt() will allocate, use, and free the MsgPort required.

   NOTES
    Callable from a task (under V37 and above).

   SEE ALSO
    AllocDosObject(), FreeDosObject(), SendPkt(), WaitPkt(),
    CreateNewProc(), AbortPkt()

 dos.library/DupLock                                       dos.library/DupLock

    NAME
    DupLock -- Duplicate a lock

    SYNOPSIS
    lock = DupLock( lock )
    D0		D1

    BPTR DupLock(BPTR)

    FUNCTION
    DupLock() is passed a shared filing system lock.  This is the ONLY
    way to obtain a duplicate of a lock... simply copying is not
    allowed.

    Another lock to the same object is then returned.  It is not
    possible to create a copy of a exclusive lock.

    A zero return indicates failure.

    INPUTS
    lock - BCPL pointer to a lock

    RESULTS
    newLock - BCPL pointer to a lock

    SEE ALSO
    Lock(), UnLock(), DupLockFromFH(), ParentOfFH()

 dos.library/DupLockFromFH                           dos.library/DupLockFromFH

   NAME
    DupLockFromFH -- Gets a lock on an open file (V36)

   SYNOPSIS
    lock = DupLockFromFH(fh)
    D0                   D1

    BPTR DupLockFromFH(BPTR)

   FUNCTION
    Obtain a lock on the object associated with fh.  Only works if the
    file was opened using a non-exclusive mode.  Other restrictions may be
    placed on success by the filesystem.

   INPUTS
    fh   - Opened file for which to obtain the lock

   RESULT
    lock - Obtained lock or NULL for failure

   SEE ALSO
    DupLock(), Lock(), UnLock()

 dos.library/EndNotify                                   dos.library/EndNotify

   NAME
    EndNotify -- Ends a notification request (V36)

   SYNOPSIS
    EndNotify(notifystructure)
            D1

    VOID EndNotify(struct NotifyRequest *)

   FUNCTION
    Removes a notification request.  Safe to call even if StartNotify()
    failed.  For NRF_SEND_MESSAGE, it searches your port for any messages
    about the object in question and removes and replies them before
    returning.

   INPUTS
    notifystructure - a structure passed to StartNotify()

   SEE ALSO
    StartNotify(), <dos/notify.h>

 dos.library/ErrorReport                               dos.library/ErrorReport

   NAME
    ErrorReport -- Displays a Retry/Cancel requester for an error (V36)

   SYNOPSIS
    status = ErrorReport(code, type, arg1, device)
    D0                    D1    D2    D3     A0

    BOOL ErrorReport(LONG, LONG, ULONG, struct MsgPort *)

   FUNCTION
    Based on the request type, this routine formats the appropriate
    requester to be displayed.  If the code is not understood, it returns
    DOS_TRUE immediately.  Returns DOS_TRUE if the user selects CANCEL or
    if the attempt to put up the requester fails, or if the process
    pr_WindowPtr is -1.  Returns FALSE if the user selects Retry.  The
    routine will retry on DISKINSERTED for appropriate error codes.
    These return values are the opposite of what AutoRequest returns.

    Note: this routine sets IoErr() to code before returning.

   INPUTS
    code   - Error code to put a requester up for.
       Current valid error codes are:
        ERROR_DISK_NOT_VALIDATED
        ERROR_DISK_WRITE_PROTECTED
        ERROR_DISK_FULL
        ERROR_DEVICE_NOT_MOUNTED
        ERROR_NOT_A_DOS_DISK
        ERROR_NO_DISK
        ABORT_DISK_ERROR	/* read/write error */
        ABORT_BUSY		/* you MUST replace... */
    type   - Request type:
                       REPORT_LOCK   - arg1 is a lock (BPTR).
                       REPORT_FH     - arg1 is a filehandle (BPTR).
            REPORT_VOLUME - arg1 is a volumenode (C pointer).
            REPORT_INSERT - arg1 is the string for the volumename
                    (will be split on a ':').
                    With ERROR_DEVICE_NOT_MOUNTED puts
                    up the "Please insert..." requester.
    arg1   - variable parameter (see type)
    device - (Optional) Address of handler task for which report is to be
                made.  Only required for REPORT_LOCK, and only if arg1==NULL.

   RESULT
    status - Cancel/Retry indicator (0 means Retry)

   SEE ALSO
    Fault(), IoErr()

 dos.library/ExAll                                           dos.library/ExAll

   NAME
    ExAll -- Examine an entire directory (V36)

   SYNOPSIS
    continue = ExAll(lock, buffer, size, type, control)
    D0               D1     D2     D3    D4     D5

    BOOL ExAll(BPTR,STRPTR,LONG,LONG,struct ExAllControl *)

   FUNCTION
    Examines an entire directory.

 Lock must be on a directory.  Size is the size of the buffer supplied.
 The buffer will be filled with (partial) ExAllData structures, as
 specified by the type field.

 Type is a value from those shown below that determines which information is
 to be stored in the buffer.  Each higher value adds a new thing to the list
 as described in the table below:-

    ED_NAME		FileName
    ED_TYPE		Type
    ED_SIZE		Size in bytes
    ED_PROTECTION	Protection bits
    ED_DATE		3 longwords of date
    ED_COMMENT	Comment (will be NULL if no comment)

 Thus, ED_NAME gives only filenames, and ED_COMMENT gives everything.

 The ead_Next entry gives a pointer to the next entry in the buffer.  The
 last entry will have NULL in ead_Next.

 The control structure is required so that FFS can keep track if more than
 one call to ExAll is required.  This happens when there are more names in
 a directory than will fit into the buffer.  The format of the control
 structure is as follows:-

 NOTE: the control structure MUST be allocated by AllocDosObject!!!

 Entries:  This field tells the calling application how many entries are
        in the buffer after calling ExAll.  Note: make sure your code
        handles the 0 entries case, including 0 entries with continue
        non-zero.

 LastKey:  This field ABSOLUTELY MUST be initialised to 0 before calling
        ExAll for the first time.  Any other value will cause nasty
        things to happen.  If ExAll returns non-zero, then this field
        should not be touched before making the second and subsequent
        calls to ExAll.  Whenever ExAll returns non-zero, there are more
        calls required before all names have been received.

        As soon as a FALSE return is received then ExAll has completed
        (if IoErr() returns ERROR_NO_MORE_ENTRIES - otherwise it returns
        the error that occured, similar to ExNext.)

 MatchString
        If this field is NULL then all filenames will be returned.  If
        this field is non-null then it is interpreted as a pointer to
        a string that is used to pattern match all file names before
        accepting them and putting them into the buffer.  The default
        AmigaDOS caseless pattern match routine is used.  This string
        MUST have been parsed by ParsePatternNoCase()!

 MatchFunc:
        Contains a pointer to a hook for a routine to decide if the entry
        will be included in the returned list of entries.  The entry is
        filled out first, and then passed to the hook.  If no MatchFunc is
        to be called then this entry should be NULL.  The hook is
        called with the following parameters (as is standard for hooks):

        BOOL = MatchFunc( hookptr, data, typeptr )
                a0	a1	a2
        (a0 = ptr to hook, a1 = ptr to filled in ExAllData, a2 = ptr
         to longword of type).

        MatchFunc should return FALSE if the entry is not to be
        accepted, otherwise return TRUE.

    Note that Dos will emulate ExAll() using Examine() and ExNext()
    if the handler in question doesn't support the ExAll() packet.

   INPUTS
    lock    - Lock on directory to be examined.
    buffer  - Buffer for data returned (MUST be at least word-aligned,
          preferably long-word aligned).
    size    - Size in bytes of 'buffer'.
    type    - Type of data to be returned.
    control - Control data structure (see notes above).  MUST have been
          allocated by AllocDosObject!

   RESULT
    continue - Whether or not ExAll is done.  If FALSE is returned, either
           ExAll has completed (IoErr() == ERROR_NO_MORE_ENTRIES), or
           an error occurred (check IoErr()).  If non-zero is returned,
           you MUST call ExAll again until it returns FALSE.

   EXAMPLE

   eac = AllocDosObject(DOS_EXALLCONTROL,NULL);
   if (!eac) ...
   ...
   eac->eac_LastKey = 0;
   do {
       more = ExAll(lock, EAData, sizeof(EAData), ED_FOO, eac);
       if ((!more) && (IoErr() != ERROR_NO_MORE_ENTRIES)) {
           /* ExAll failed abnormally */
           break;
       }
       if (eac->eac_Entries == 0) {
           /* ExAll failed normally with no entries */
           continue;                   /* ("more" is *usually* zero) */
       }
       ead = (struct ExAllData *) EAData;
       do {
           /* use ead here */
           ...
           /* get next ead */
           ead = ead->ed_Next;
       } while (ead);

   } while (more);
   ...
   FreeDosObject(DOS_EXALLCONTROL,eac);

   BUGS
    In V36, there were problems with ExAll (particularily with
    eac_MatchString, and ed_Next with the ramdisk and the emulation
    of it in Dos for handlers that do not support the packet.  It is
    advised you only use this under V37 and later.

   SEE ALSO
    Examine(), ExNext(), ExamineFH(), MatchPatternNoCase(),
    ParsePatternNoCase(), AllocDosObject()

 dos.library/Examine                                       dos.library/Examine

    NAME
    Examine -- Examine a directory or file associated with a lock

    SYNOPSIS
    success = Examine( lock, FileInfoBlock )
    D0		    D1	      D2

    BOOL Examine(BPTR,struct FileInfoBlock *)

    FUNCTION
    Examine() fills in information in the FileInfoBlock concerning the
    file or directory associated with the lock. This information
    includes the name, size, creation date and whether it is a file or
    directory.  FileInfoBlock must be longword aligned.  Examine() gives
    a return code of zero if it fails.

    You may make a local copy of the FileInfoBlock, as long as it is
    never passed to ExNext().

    INPUTS
    lock	  - BCPL pointer to a lock
    infoBlock - pointer to a FileInfoBlock (MUST be longword aligned)

    RESULTS
    success - boolean

    SPECIAL NOTE
    FileInfoBlock must be longword-aligned.  AllocDosObject() will
    allocate them correctly for you.

    SEE ALSO
    Lock(), UnLock(), ExNext(), ExamineFH(), <dos/dos.h>, AllocDosObject(),
    ExAll()

 dos.library/ExamineFH                                   dos.library/ExamineFH

   NAME
    ExamineFH -- Gets information on an open file (V36)

   SYNOPSIS
    success = ExamineFH(fh, fib)
    D0                  D1  D2

    BOOL ExamineFH(BPTR, struct FileInfoBlock *)

   FUNCTION
    Examines a filehandle and returns information about the file in the
    FileInfoBlock.  There are no guarantees as to whether the fib_Size
    field will reflect any changes made to the file size it was opened,
    though filesystems should attempt to provide up-to-date information
    for it.

   INPUTS
    fh  - Filehandle you wish to examine
    fib - FileInfoBlock, must be longword aligned.

   RESULT
    success - Success/failure indication

   SEE ALSO
    Examine(), ExNext(), ExAll(), Open(), AllocDosObject()

 dos.library/Execute                                       dos.library/Execute

    NAME
    Execute -- Execute a CLI command

    SYNOPSIS
    success = Execute( commandString, input, output )
    D0		   D1		  D2	 D3

    BOOL Execute(STRPTR, BPTR, BPTR)

    FUNCTION
    This function attempts to execute the string commandString as a
    Shell command and arguments. The string can contain any valid input
    that you could type directly in a Shell, including input and output
    redirection using < and >.  Note that Execute() doesn't return until
    the command(s) in commandstring have returned.

    The input file handle will normally be zero, and in this case
    Execute() will perform whatever was requested in the commandString
    and then return. If the input file handle is nonzero then after the
    (possibly empty) commandString is performed subsequent input is read
    from the specified input file handle until end of that file is
    reached.

    In most cases the output file handle must be provided, and is used
    by the Shell commands as their output stream unless output
    redirection was specified. If the output file handle is set to zero
    then the current window, normally specified as *, is used. Note
    that programs running under the Workbench do not normally have a
    current window.

    Execute() may also be used to create a new interactive Shell process
    just like those created with the NewShell command. In order to do
    this you would call Execute() with an empty commandString, and pass
    a file handle relating to a new window as the input file handle.
    The output file handle would be set to zero. The Shell will read
    commands from the new window, and will use the same window for
    output. This new Shell window can only be terminated by using the
    EndCLI command.

    Under V37, if an input filehandle is passed, and it's either
    interactive or a NIL: filehandle, the pr_ConsoleTask of the new
    process will be set to that filehandle's process (the same applies
    to SystemTagList()).

    For this command to work the program Run must be present in C: in
    versions before V36 (except that in 1.3.2 and any later 1.3 versions,
    the system first checks the resident list for Run).

    INPUTS
    commandString - pointer to a null-terminated string
    input	      - BCPL pointer to a file handle
    output	      - BCPL pointer to a file handle

    RESULTS
    success - BOOLEAN indicating whether Execute was successful
          in finding and starting the specified program.  Note this
          is NOT the return code of the command(s).
    SEE ALSO
    SystemTagList(), NewShell, EndCLI, Run

 dos.library/Exit                                             dos.library/Exit

    NAME
    Exit -- Exit from a program

    SYNOPSIS
    Exit( returnCode )
          D1

    void Exit(LONG)

    FUNCTION
    Exit() is currently for use with programs written as if they
    were BCPL programs.  This function is not normally useful for
    other purposes.

    In general, therefore, please DO NOT CALL THIS FUNCTION!

    In order to exit, C programs should use the C language exit()
    function (note the lower case letter "e").  Assembly programs should
    place a return code in D0, and execute an RTS instruction with
    their original stack ptr.

    IMPLEMENTATION
    The action of Exit() depends on whether the program which called it
    is running as a command under a CLI or not. If the program is
    running under the CLI the command finishes and control reverts to
    the CLI. In this case, returnCode is interpreted as the return code
    from the program.

    If the program is running as a distinct process, Exit() deletes the
    process and release the space associated with the stack, segment
    list and process structure.

    INPUTS
    returnCode - integer

    SEE ALSO
    CreateProc(), CreateNewProc()

 dos.library/ExNext                                         dos.library/ExNext

    NAME
    ExNext -- Examine the next entry in a directory

    SYNOPSIS
    success = ExNext( lock, FileInfoBlock )
    D0		   D1	     D2

    BOOL ExNext(BPTR, struct FileInfoBlock *)

    FUNCTION
    This routine is passed a directory lock and a FileInfoBlock that
    have been initialized by a previous call to Examine(), or updated
    by a previous call to ExNext().  ExNext() gives a return code of zero
    on failure.  The most common cause of failure is reaching the end
    of the list of files in the owning directory.  In this case, IoErr
    will return ERROR_NO_MORE_ENTRIES and a good exit is appropriate.

    So, follow these steps to examine a directory:
    1) Pass a Lock and a FileInfoBlock to Examine().  The lock must
       be on the directory you wish to examine.
    2) Pass ExNext() the same lock and FileInfoBlock.
    3) Do something with the information returned in the FileInfoBlock.
       Note that the fib_DirEntryType field is positive for directories,
       negative for files.
    4) Keep calling ExNext() until it returns FALSE.  Check IoErr()
       to ensure that the reason for failure was ERROR_NO_MORE_ENTRIES.

    Note: if you wish to recursively scan the file tree and you find
    another directory while ExNext()ing you must Lock that directory and
    Examine() it using a new FileInfoBlock.  Use of the same
    FileInfoBlock to enter a directory would lose important state
    information such that it will be impossible to continue scanning
    the parent directory.  While it is permissible to UnLock() and Lock()
    the parent directory between ExNext() calls, this is NOT recommended.
    Important state information is associated with the parent lock, so
    if it is freed between ExNext() calls this information has to be
    rebuilt on each new ExNext() call, and will significantly slow down
    directory scanning.

    It is NOT legal to Examine() a file, and then to ExNext() from that
    FileInfoBlock.	You may make a local copy of the FileInfoBlock, as
    long as it is never passed back to the operating system.

    INPUTS
    lock - BCPL pointer to a lock originally used for the Examine() call
    infoBlock - pointer to a FileInfoBlock used on the previous Examine()
            or ExNext() call.

    RESULTS
    success - boolean

    SPECIAL NOTE
    FileInfoBlock must be longword-aligned.  AllocDosObject() will
    allocate them correctly for you.

    SEE ALSO
    Examine(), Lock(), UnLock(), IoErr(), ExamineFH(), AllocDosObject(),
    ExAll()

 dos.library/Fault                                           dos.library/Fault

   NAME
    Fault -- Returns the text associated with a DOS error code (V36)

   SYNOPSIS
    success = Fault(code, header, buffer, len)
    D0               D1     D2      D3    D4

    BOOL Fault(LONG, STRPTR, STRPTR, LONG)

   FUNCTION
    This routine obtains the error message text for the given error code.
    The header is prepended to the text of the error message, followed
    by a colon.  Puts a null-terminated string for the error message into
    the buffer.  By convention, error messages should be no longer than 80
    characters (+1 for termination), and preferably no more than 60.
    The value returned by IoErr() is set to the code passed in.  If there
    is no message for the error code, the message will be "Error code
    <number>\n".

   INPUTS
    code   - Error code
    header - header to output before error text
    buffer - Buffer to receive error message.
    len    - Length of the buffer.

   RESULT
    success - Success/failure code.

   SEE ALSO
    IoErr(), SetIoErr(), PrintFault()

 dos.library/FGetC                                           dos.library/FGetC

   NAME
    FGetC -- Read a character from the specified input (buffered) (V36)

   SYNOPSIS
    char = FGetC(fh)
    D0	     D1

    LONG FGetC(BPTR)

   FUNCTION
    Reads the next character from the input stream.  A -1 is
    returned when EOF or an error is encountered.  This call is buffered.
    Use Flush() between buffered and unbuffered I/O on a filehandle.

   INPUTS
    fh - filehandle to use for buffered I/O

   RESULT
    char - character read (0-255) or -1

   BUGS
    In V36, after an EOF was read, EOF would always be returned from
    FGetC() from then on.  Starting in V37, it tries to read from the
    handler again each time (unless UnGetC(fh,-1) was called).

   SEE ALSO
    FPutC(), UnGetC(), Flush()

 dos.library/FGets                                           dos.library/FGets

   NAME
    FGets -- Reads a line from the specified input (buffered) (V36)

   SYNOPSIS
    buffer = FGets(fh, buf, len)
    D0             D1  D2   D3

    STRPTR FGets(BPTR, STRPTR, ULONG)

   FUNCTION
    This routine reads in a single line from the specified input stopping
    at a NEWLINE character or EOF.  In either event, UP TO the number of
    len specified bytes minus 1 will be copied into the buffer.  Hence if
    a length of 50 is passed and the input line is longer than 49 bytes,
    it will return 49 characters.  It returns the buffer pointer normally,
    or NULL if EOF is the first thing read.

    If terminated by a newline, the newline WILL be the last character in
    the buffer.  This is a buffered read routine.  The string read in IS
    null-terminated.

   INPUTS
    fh  - filehandle to use for buffered I/O
    buf - Area to read bytes into.
    len - Number of bytes to read, must be > 0.

   RESULT
    buffer - Pointer to buffer passed in, or NULL for immediate EOF or for
         an error.  If NULL is returnd for an EOF, IoErr() will return
         0.

   SEE ALSO
    FRead(), FPuts(), FGetC()

 dos.library/FilePart                                     dos.library/FilePart

   NAME
    FilePart -- Returns the last component of a path (V36)

   SYNOPSIS
    fileptr = FilePart( path )
    D0		     D1

    STRPTR FilePart( STRPTR )

   FUNCTION
    This function returns a pointer to the last component of a string path
    specification, which will normally be the file name.  If there is only
    one component, it returns a pointer to the beginning of the string.

   INPUTS
    path - pointer to an path string.  May be relative to the current
           directory or the current disk.

   RESULT
    fileptr - pointer to the last component of the path.

   EXAMPLE
    FilePart("xxx:yyy/zzz/qqq") would return a pointer to the first 'q'.
    FilePart("xxx:yyy") would return a pointer to the first 'y').

   SEE ALSO
    PathPart(), AddPart()

 dos.library/FindArg                                       dos.library/FindArg

   NAME
    FindArg - find a keyword in a template (V36)

   SYNOPSIS
    index = FindArg(template, keyword)
    D0                D1        D2

    LONG FindArg(STRPTR, STRPTR)

   FUNCTION
    Returns the argument number of the keyword, or -1 if it is not a
    keyword for the template.  Abbreviations are handled.

   INPUTS
    keyword  - keyword to search for in template
    template - template string to search

   RESULT
    index - number of entry in template, or -1 if not found

   BUGS
    In earlier published versions of the autodoc, keyword and template
    were backwards.

   SEE ALSO
    ReadArgs(), ReadItem(), FreeArgs()

 dos.library/FindCliProc                               dos.library/FindCliProc

   NAME
    FindCliProc -- returns a pointer to the requested CLI process (V36)

   SYNOPSIS
    proc = FindCliProc(num)
    D0             D1

    struct Process *FindCliProc(LONG)

   FUNCTION
    This routine returns a pointer to the CLI process associated with the
    given CLI number.  If the process isn't an active CLI process, NULL is
    returned.  NOTE: should normally be called inside a Forbid(), if you
    must use this function at all.

   INPUTS
    num  - Task number of CLI process

   RESULT
    proc - Pointer to given CLI process

   SEE ALSO
    Cli(), Forbid(), MaxCli()

 dos.library/FindDosEntry                             dos.library/FindDosEntry

   NAME
    FindDosEntry -- Finds a specific Dos List entry (V36)

   SYNOPSIS
    newdlist = FindDosEntry(dlist,name,flags)
    D0                       D1    D2   D3

    struct DosList *FindDosEntry(struct DosList *,STRPTR,ULONG)

   FUNCTION
    Locates an entry on the device list.  Starts with the entry dlist.
    NOTE: must be called with the device list locked, no references may be
    made to dlist after unlocking.

   INPUTS
    dlist    - The device entry to start with.
    name     - Name of device entry (without ':') to locate.
    flags    - Search control flags.  Use the flags you passed to
           LockDosList, or a subset of them.  LDF_READ/LDF_WRITE are
           not required for this call.

   RESULT
    newdlist - The device entry or NULL

   SEE ALSO
    AddDosEntry(), RemDosEntry(), NextDosEntry(), LockDosList(),
    MakeDosEntry(), FreeDosEntry()

 dos.library/FindSegment                               dos.library/FindSegment

   NAME
    FindSegment - Finds a segment on the resident list (V36)

   SYNOPSIS
    segment = FindSegment(name, start, system)
    D0		       D1     D2     D3

    struct Segment *FindSegment(STRPTR, struct Segment *, LONG)

   FUNCTION
    Finds a segment on the Dos resident list by name and type, starting
    at the segment AFTER 'start', or at the beginning if start is NULL.
    If system is zero, it will only return nodes with a seg_UC of 0
    or more.  It does NOT increment the seg_UC, and it does NOT do any
    locking of the list.  You must Forbid() lock the list to use this
    call.

    To use an entry you have found, you must: if the seg_UC is 0 or more,
    increment it, and decrement it (under Forbid()!) when you're done
    the the seglist.

    The other values for seg_UC are:
        -1   - system module, such as a filesystem or shell
        -2   - resident shell command
        -999 - disabled internal command, ignore
    Negative values should never be modified.  All other negative
    values between 0 and -32767 are reserved to AmigaDos and should not
    be used.

   INPUTS
    name   - name of segment to find
    start  - segment to start the search after
    system - true for system segment, false for normal segments

   RESULT
    segment - the segment found or NULL

   SEE ALSO
    AddSegment(), RemSegment(), Forbid()

 dos.library/FindVar                                       dos.library/FindVar

   NAME
    FindVar -- Finds a local variable (V36)

   SYNOPSIS
    var = FindVar( name, type )
    D0		D1    D2

    struct LocalVar * FindVar(STRPTR, ULONG )

   FUNCTION
    Finds a local variable structure.

   INPUTS
    name - pointer to an variable name.  Note variable names follow
           filesystem syntax and semantics.

    type - type of variable to be found (see <dos/var.h>)

   RESULT

    var  - pointer to a LocalVar structure or NULL

   SEE ALSO
    GetVar(), SetVar(), DeleteVar(), <dos/var.h>

 dos.library/Flush                                           dos.library/Flush

   NAME
    Flush -- Flushes buffers for a buffered filehandle (V36)

   SYNOPSIS
    success = Flush(fh)
    D0		D1

    LONG Flush(BPTR)

   FUNCTION
    Flushes any pending buffered writes to the filehandle.  All buffered
    writes will also be flushed on Close().  If the filehandle was being
    used for input, it drops the buffer, and tries to Seek() back to the
    last read position  (so subsequent reads or writes will occur at the
    expected position in the file).

   INPUTS
    fh	- Filehandle to flush.

   RESULT
    success - Success or failure.

   BUGS
    Before V37 release, Flush() returned a random value.  As of V37,
    it always returns success (this will be fixed in some future
    release).

   SEE ALSO
    FputC(), FGetC(), UnGetC(), Seek(), Close()

 dos.library/Format                                         dos.library/Format

   NAME
    Format -- Causes a filesystem to initialize itself (V36)

   SYNOPSIS
    success = Format(filesystem, volumename, dostype)
    D0                   D1          D2         D3

    BOOL Format(STRPTR, STRPTR, ULONG)

   FUNCTION
    Interface for initializing new media on a device.  This causes the
    filesystem to write out an empty disk structure to the media, which
    should then be ready for use.  This assumes the media has been low-
    level formatted and verified already.

    The filesystem should be inhibited before calling Format() to make
    sure you don't get an ERROR_OBJECT_IN_USE.

   INPUTS
    filesystem - Name of device to be formatted.  ':' must be supplied.
    volumename - Name for volume (if supported).  No ':'.
    dostype    - Type of format, if filesystem supports multiple types.

   RESULT
    success - Success/failure indicator.

   BUGS
    Existed, but was non-functional in V36 dos.  (The volumename wasn't
    converted to a BSTR.)  Workaround: require V37, or under V36
    convert volumename to a BPTR to a BSTR before calling Format().
    Note: a number of printed packet docs for ACTION_FORMAT are wrong
    as to the arguments.

   SEE ALSO

 dos.library/FPutC                                           dos.library/FPutC

   NAME
    FPutC -- Write a character to the specified output (buffered) (V36)

   SYNOPSIS
    char = FPutC(fh, char)
    D0           D1   D2

    LONG FPutC(BPTR, UBYTE)

   FUNCTION
    Writes a single character to the output stream.  This call is
    buffered.  Use Flush() between buffered and unbuffered I/O on a
    filehandle.  Interactive filehandles are flushed automatically
    on a newline, return, '\0', or line feed.

   INPUTS
    fh   - filehandle to use for buffered I/O
    char - character to write

   RESULT
    char - either the character written, or EOF for an error.

   SEE ALSO
    FGetC(), UnGetC(), Flush()

 dos.library/FPuts                                           dos.library/FPuts

   NAME
    FPuts -- Writes a string the the specified output (buffered) (V36)

   SYNOPSIS
    error = FPuts(fh, str)
    D0            D1  D2

    LONG FPuts(BPTR, STRPTR)

   FUNCTION
    This routine writes an unformatted string to the filehandle.  No
    newline is appended to the string and the length actually written is
    returned.  This routine is buffered.

   INPUTS
    fh    - filehandle to use for buffered I/O
    str   - Null-terminated string to be written to default output

   RESULT
    error - 0 normally, otherwise -1.  Note that this is opposite of
        most other Dos functions, which return success.

   SEE ALSO
    FGets(), FPutC(), FWrite(), PutStr()

 dos.library/FRead                                           dos.library/FRead

   NAME
    FRead -- Reads a number of blocks from an input (buffered) (V36)

   SYNOPSIS
    count = FRead(fh, buf, blocklen, blocks)
    D0	      D1  D2     D3        D4

    LONG FRead(BPTR, STRPTR, ULONG, ULONG)

   FUNCTION
    Attempts to read a number of blocks, each blocklen long, into the
    specified buffer from the input stream.  May return less than
    the number of blocks requested, either due to EOF or read errors.
    This call is buffered.

   INPUTS
    fh	 - filehandle to use for buffered I/O
    buf      - Area to read bytes into.
    blocklen - number of bytes per block.  Must be > 0.
    blocks	 - number of blocks to read.  Must be > 0.

   RESULT
    count - Number of _blocks_ read, or 0 for EOF.  On an error, the
        number of blocks actually read is returned.

   BUGS
    Doesn't clear IoErr() before starting.  If you want to find out
    about errors, use SetIoErr(0L) before calling.

   SEE ALSO
    FGetC(), FWrite(), FGets()

 dos.library/FreeArgs                                     dos.library/FreeArgs

   NAME
    FreeArgs - Free allocated memory after ReadArgs() (V36)

   SYNOPSIS
    FreeArgs(rdargs)
               D1

    void FreeArgs(struct RDArgs *)

   FUNCTION
    Frees memory allocated to return arguments in from ReadArgs().  If
    ReadArgs allocated the RDArgs structure it will be freed.

   INPUTS
    rdargs - structure returned from ReadArgs()

   SEE ALSO
    ReadArgs(), ReadItem(), FindArg()

 dos.library/FreeDeviceProc                         dos.library/FreeDeviceProc

   NAME
    FreeDeviceProc -- Releases port returned by GetDeviceProc() (V36)

   SYNOPSIS
    FreeDeviceProc(devproc)
             D1

    void FreeDeviceProc(struct DevProc *)

   FUNCTION
    Frees up the structure created by GetDeviceProc(), and any associated
    temporary locks.

    Decrements the counter incremented by GetDeviceProc().  The counter
    is in an extension to the 1.3 process structure.  After calling
    FreeDeviceProc(), do not use the port or lock again!  It is safe to
    call FreeDeviceProc(NULL).

   INPUTS
    devproc - A value returned by GetDeviceProc()

   BUGS
    Counter not currently active in 2.0.

   SEE ALSO
    GetDeviceProc(), DeviceProc(), AssignLock(), AssignLate(),
    AssignPath()

 dos.library/FreeDosEntry                             dos.library/FreeDosEntry

   NAME
    FreeDosEntry -- Frees an entry created by MakeDosEntry (V36)

   SYNOPSIS
    FreeDosEntry(dlist)
                   D1

    void FreeDosEntry(struct DosList *)

   FUNCTION
    Frees an entry created by MakeDosEntry().  This routine should be
    eliminated and replaced by a value passed to FreeDosObject()!

   INPUTS
    dlist - DosList to free.

   SEE ALSO
    AddDosEntry(), RemDosEntry(), FindDosEntry(), LockDosList(),
    NextDosEntry(), MakeDosEntry()

 dos.library/FreeDosObject                           dos.library/FreeDosObject

   NAME
    FreeDosObject -- Frees an object allocated by AllocDosObject() (V36)

   SYNOPSIS
    FreeDosObject(type, ptr)
               D1   D2

    void FreeDosObject(ULONG, void *)

   FUNCTION
    Frees an object allocated by AllocDosObject().  Do NOT call for
    objects allocated in any other way.

   INPUTS
    type - type passed to AllocDosObject()
    ptr  - ptr returned by AllocDosObject()

   SEE ALSO
    AllocDosObject(), <dos/dos.h>

 dos.library/FWrite                                         dos.library/FWrite

   NAME
    FWrite -- Writes a number of blocks to an output (buffered) (V36)

   SYNOPSIS
    count = FWrite(fh, buf, blocklen, blocks)
    D0	       D1  D2     D3        D4

    LONG FWrite(BPTR, STRPTR, ULONG, ULONG)

   FUNCTION
    Attempts to write a number of blocks, each blocklen long, from the
    specified buffer to the output stream.  May return less than the
    number of blocks requested, if there is some error such as a full
    disk or r/w error.  This call is buffered.

   INPUTS
    fh	 - filehandle to use for buffered I/O
    buf      - Area to write bytes from.
    blocklen - number of bytes per block.  Must be > 0.
    blocks	 - number of blocks to read.  Must be > 0.

   RESULT
    count - Number of _blocks_ written.  On an error, the number of
        blocks actually written is returned.

   BUGS
    Doesn't clear IoErr() before starting.  If you want to find out
    about errors, use SetIoErr(0L) before calling.

   SEE ALSO
    FPutC(), FRead(), FPuts()

 dos.library/GetArgStr                                   dos.library/GetArgStr

   NAME
    GetArgStr -- Returns the arguments for the process (V36)

   SYNOPSIS
    ptr = GetArgStr()
    D0

    STRPTR GetArgStr(void)

   FUNCTION
    Returns a pointer to the (null-terminated) arguments for the program
    (process).  This is the same string passed in a0 on startup from CLI.

   RESULT
    ptr - pointer to arguments

   SEE ALSO
    SetArgStr(), RunCommand()

 dos.library/GetConsoleTask                         dos.library/GetConsoleTask

   NAME
    GetConsoleTask -- Returns the default console for the process (V36)

   SYNOPSIS
    port = GetConsoleTask()
    D0

    struct MsgPort *GetConsoleTask(void)

   FUNCTION
    Returns the default console task's port (pr_ConsoleTask) for the
    current process.

   RESULT
    port - The pr_MsgPort of the console handler, or NULL.

   SEE ALSO
    SetConsoleTask(), Open()

 dos.library/GetCurrentDirName                   dos.library/GetCurrentDirName

   NAME
    GetCurrentDirName -- returns the current directory name (V36)

   SYNOPSIS
    success = GetCurrentDirName(buf, len)
    D0                          D1   D2

    BOOL GetCurrentDirName(STRPTR, LONG)

   FUNCTION
    Extracts the current directory name from the CLI structure and puts it
    into the buffer.  If the buffer is too small, the name is truncated
    appropriately and a failure code returned.  If no CLI structure is
    present, a null string is returned in the buffer, and failure from
    the call (with IoErr() == ERROR_OBJECT_WRONG_TYPE);

   INPUTS
    buf     - Buffer to hold extracted name
    len     - Number of bytes of space in buffer

   RESULT
    success - Success/failure indicator

   BUGS
    In V36, this routine didn't handle 0-length buffers correctly.

   SEE ALSO
    SetCurrentDirName()

 dos.library/GetDeviceProc                           dos.library/GetDeviceProc

   NAME
    GetDeviceProc -- Finds a handler to send a message to (V36)

   SYNOPSIS
    devproc = GetDeviceProc(name, devproc)
      D0			 D1     D2

    struct DevProc *GetDeviceProc(STRPTR, struct DevProc *)

   FUNCTION
    Finds the handler/filesystem to send packets regarding 'name' to.
    This may involve getting temporary locks.  It returns a structure
    that includes a lock and msgport to send to to attempt your operation.
    It also includes information on how to handle multiple-directory
    assigns (by passing the DevProc back to GetDeviceProc() until it
    returns NULL).

    The initial call to GetDeviceProc() should pass NULL for devproc.  If
    after using the returned DevProc, you get an ERROR_OBJECT_NOT_FOUND,
    and (devproc->dvp_Flags & DVPF_ASSIGN) is true, you should call
    GetDeviceProc() again, passing it the devproc structure.  It will
    either return a modified devproc structure, or NULL (with
    ERROR_NO_MORE_ENTRIES in IoErr()).  Continue until it returns NULL.

    This call also increments the counter that locks a handler/fs into
    memory.  After calling FreeDeviceProc(), do not use the port or lock
    again!

   INPUTS
    name    - name of the object you wish to access.  This can be a
          relative path ("foo/bar"), relative to the current volume
          (":foo/bar"), or relative to a device/volume/assign
          ("foo:bar").
    devproc - A value returned by GetDeviceProc() before, or NULL

   RESULT
    devproc - a pointer to a DevProc structure or NULL

   BUGS
    Counter not currently active in 2.0.
    In 2.0 and 2.01, you HAD to check DVPF_ASSIGN before calling it again.
    This was fixed for the 2.02 release of V36.

   SEE ALSO
    FreeDeviceProc(), DeviceProc(), AssignLock(), AssignLate(),
    AssignPath()

 dos.library/GetFileSysTask                         dos.library/GetFileSysTask

   NAME
    GetFileSysTask -- Returns the default filesystem for the process (V36)

   SYNOPSIS
    port = GetFileSysTask()
    D0

    struct MsgPort *GetFileSysTask(void)

   FUNCTION
    Returns the default filesystem task's port (pr_FileSystemTask) for the
    current process.

   RESULT
    port - The pr_MsgPort of the filesystem, or NULL.

   SEE ALSO
    SetFileSysTask(), Open()

 dos.library/GetProgramDir                           dos.library/GetProgramDir

   NAME
    GetProgramDir -- Returns a lock on the directory the program was loaded
             from (V36)

   SYNOPSIS
    lock = GetProgramDir()
    D0

    BPTR GetProgramDir(void)

   FUNCTION
    Returns a shared lock on the directory the program was loaded from.
    This can be used for a program to find data files, etc, that are stored
    with the program, or to find the program file itself.  NULL returns are
    valid, and may occur, for example, when running a program from the
    resident list.  You should NOT unlock the lock.

   RESULT
    lock - A lock on the directory the current program was loaded from,
           or NULL if loaded from resident list, etc.

   BUGS
    Should return a lock for things loaded via resident.  Perhaps should
    return currentdir if NULL.

   SEE ALSO
    SetProgramDir(), Open()

 dos.library/GetProgramName                         dos.library/GetProgramName

   NAME
    GetProgramName -- Returns the current program name (V36)

   SYNOPSIS
    success = GetProgramName(buf, len)
    D0                       D1   D2

    BOOL GetProgramName(STRPTR, LONG)

   FUNCTION
    Extracts the program name from the CLI structure and puts it
    into the buffer.  If the buffer is too small, the name is truncated
    present, a null string is returned in the buffer, and failure from
    the call (with IoErr() == ERROR_OBJECT_WRONG_TYPE);

   INPUTS
    buf     - Buffer to hold extracted name
    len     - Number of bytes of space in buffer

   RESULT
    success - Success/failure indicator

   SEE ALSO
    SetProgramName()

 dos.library/GetPrompt                                   dos.library/GetPrompt

   NAME
    GetPrompt -- Returns the prompt for the current process (V36)

   SYNOPSIS
    success = GetPrompt(buf, len)
    D0                  D1   D2

    BOOL GetPrompt(STRPTR, LONG)

   FUNCTION
    Extracts the prompt string from the CLI structure and puts it
    into the buffer.  If the buffer is too small, the string is truncated
    appropriately and a failure code returned.  If no CLI structure is
    present, a null string is returned in the buffer, and failure from
    the call (with IoErr() == ERROR_OBJECT_WRONG_TYPE);

   INPUTS
    buf     - Buffer to hold extracted prompt
    len     - Number of bytes of space in buffer

   RESULT
    success - Success/failure indicator

   SEE ALSO
    SetPrompt()

 dos.library/GetVar                                         dos.library/GetVar

   NAME
    GetVar -- Returns the value of a local or global variable (V36)

   SYNOPSIS
    len = GetVar( name, buffer, size, flags )
    D0	       D1     D2     D3    D4

    LONG GetVar( STRPTR, STRPTR, LONG, ULONG )

   FUNCTION
    Gets the value of a local or environment variable.  It is advised to
     only use ASCII strings inside variables, but not required.  This stops
    putting characters into the destination when a \n is hit, unless
    GVF_BINARY_VAR is specified.  (The \n is not stored in the buffer.)

   INPUTS
    name   - pointer to a variable name.
    buffer - a user allocated area which will be used to store
         the value associated with the variable.
    size   - length of the buffer region in bytes.
    flags  - combination of type of var to get value of (low 8 bits), and
         flags to control the behavior of this routine.  Currently
         defined flags include:

            GVF_GLOBAL_ONLY - tries to get a global env variable.
            GVF_LOCAL_ONLY  - tries to get a local variable.
            GVF_BINARY_VAR  - don't stop at \n

         The default is to try to get a local variable first, then
         to try to get a global environment variable.

   RESULT
    len -   Size of environment variable.  -1 indicates that the
        variable was not defined (if IoErr() returns
        ERROR_OBJECT_NOT_FOUND - it returns ERROR_BAD_NUMBER if
        you specify a size of 0).  If the value would overflow
        the user buffer, the buffer is truncated.  The buffer
        returned is null-terminated (even if GVF_BINARY_VAR is
        used).  The number of characters put in the buffer (not
        including '\0') is returned, and IoErr() will return the
        the size of the variable.

   BUGS
    LV_VAR is the only type that can be global.
    Under V36, we documented (and it returned) the size of the variable,
    not the number of characters transferred.  For V37 this was changed
    to the number of characters put in the buffer, and the total size
    of the variable is put in IoErr().

   SEE ALSO
    SetVar(), DeleteVar(), FindVar(), <dos/var.h>

 dos.library/Info                                             dos.library/Info

    NAME
    Info -- Returns information about the disk

    SYNOPSIS
    success = Info( lock, parameterBlock )
    D0		D1    D2

    BOOL Info(BPTR, struct InfoData *)

    FUNCTION
    Info() can be used to find information about any disk in use.
    'lock' refers to the disk, or any file on the disk. The parameter
    block is returned with information about the size of the disk,
    number of free blocks and any soft errors.

    INPUTS
    lock	       - BCPL pointer to a lock
    parameterBlock - pointer to an InfoData structure
             (longword aligned)

    RESULTS
    success - boolean

    SPECIAL NOTE:
    Note that InfoData structure must be longword aligned.

 dos.library/Inhibit                                       dos.library/Inhibit

   NAME
    Inhibit -- Inhibits access to a filesystem (V36)

   SYNOPSIS
    success = Inhibit(filesystem, flag)
    D0                    D1       D2

    BOOL Inhibit(STRPTR,LONG)

   FUNCTION
    Sends an ACTION_INHIBIT packet to the indicated handler.  This stops
    all activity by the handler until uninhibited.  When uninhibited,
    anything may have happened to the disk in the drive, or there may no
    longer be one.

   INPUTS
    filesystem - Name of device to inhibit (with ':')
    flag	   - New status.  DOSTRUE = inhibited, FALSE = uninhibited

   RESULT
    success    - Success/failure indicator

   SEE ALSO

 dos.library/Input                                           dos.library/Input

    NAME
    Input -- Identify the program's initial input file handle

    SYNOPSIS
    file = Input()
    D0

    BPTR Input(void)

    FUNCTION
    Input() is used to identify the initial input stream allocated when
    the program was initiated.  Never close the filehandle returned by
    Input!

    RESULTS
    file - BCPL pointer to a file handle

    SEE ALSO
    Output(), SelectInput()

 dos.library/InternalLoadSeg                       dos.library/InternalLoadSeg

   NAME
    InternalLoadSeg -- Low-level load routine (V36)

   SYNOPSIS
    seglist = InternalLoadSeg(fh,table,functionarray,stack)
    D0			  D0  A0        A1	  A2

    BPTR InternalLoadSeg(BPTR,BPTR,LONG *,LONG *)

   FUNCTION
    Loads from fh.  Table is used when loading an overlay, otherwise
    should be NULL.  Functionarray is a pointer to an array of functions.
    Note that the current Seek position after loading may be at any point
    after the last hunk loaded.  The filehandle will not be closed.  If a
    stacksize is encoded in the file, the size will be stuffed in the
    LONG pointed to by stack.  This LONG should be initialized to your
    default value: InternalLoadSeg() will not change it if no stacksize
    is found. Clears unused portions of Code and Data hunks (as well as
    BSS hunks).  (This also applies to LoadSeg() and NewLoadSeg()).

    If the file being loaded is an overlaid file, this will return
    -(seglist).  All other results will be positive.

    NOTE to overlay users: InternalLoadSeg() does NOT return seglist in
    both D0 and D1, as LoadSeg does.  The current ovs.asm uses LoadSeg(),
    and assumes returns are in D1.  We will support this for LoadSeg()
    ONLY.

   INPUTS
    fh	      - Filehandle to load from.
    table	      - When loading an overlay, otherwise ignored.
    functionarray - Array of function to be used for read, alloc, and free.
       FuncTable[0] ->  Actual = ReadFunc(readhandle,buffer,length),DOSBase
                    D0                D1         A0     D0      A6
       FuncTable[1] ->  Memory = AllocFunc(size,flags), Execbase
                    D0                 D0   D1      a6
       FuncTable[2] ->  FreeFunc(memory,size), Execbase
                             A1     D0     a6
    stack         - Pointer to storage (ULONG) for stacksize.

   RESULT
    seglist	      - Seglist loaded or NULL.  NOT returned in D1!

   BUGS
    Really should use tags.

   SEE ALSO
    LoadSeg(), UnLoadSeg(), NewLoadSeg(), InternalUnLoadSeg()

 dos.library/InternalUnLoadSeg                   dos.library/InternalUnLoadSeg

   NAME
    InternalUnLoadSeg -- Unloads a seglist loaded with InternalLoadSeg() (V36)

   SYNOPSIS
    success = InternalUnLoadSeg(seglist,FreeFunc)
      D0			      D1       A1

    BOOL InternalUnLoadSeg(BPTR,void (*)(STRPTR,ULONG))

   FUNCTION
    Unloads a seglist using freefunc to free segments.  Freefunc is called
    as for InternalLoadSeg.  NOTE: will call Close() for overlaid
    seglists.

   INPUTS
    seglist  - Seglist to be unloaded
    FreeFunc - Function called to free memory

   RESULT
    success - returns whether everything went OK (since this may close
          files).  Also returns FALSE if seglist was NULL.

   BUGS
    Really should use tags

   SEE ALSO
    LoadSeg(), UnLoadSeg(), InternalLoadSeg(), NewUnLoadSeg(), Close()

 dos.library/IoErr                                           dos.library/IoErr

    NAME
    IoErr -- Return extra information from the system

    SYNOPSIS
    error = IoErr()
      D0

    LONG IoErr(void)

    FUNCTION
    Most I/O routines return zero to indicate an error. When this
    happens (or whatever the defined error return for the routine)
    this routine may be called to determine more information. It is
    also used in some routines to pass back a secondary result.

    Note: there is no guarantee as to the value returned from IoErr()
    after a successful operation, unless to specified by the routine.

    RESULTS
    error - integer

    SEE ALSO
    Fault(), PrintFault(), SetIoErr()

 dos.library/IsFileSystem                             dos.library/IsFileSystem

   NAME
    IsFileSystem -- returns whether a Dos handler is a filesystem (V36)

   SYNOPSIS
    result = IsFileSystem(name)
    D0                     D1

    BOOL IsFileSystem(STRPTR)

   FUNCTION
    Returns whether the device is a filesystem or not.  A filesystem
    supports seperate files storing information.  It may also support
    sub-directories, but is not required to.  If the filesystem doesn't
    support this new packet, IsFileSystem() will use Lock(":",...) as
    an indicator.

   INPUTS
    name   - Name of device in question, with trailing ':'.

   RESULT
    result - Flag to indicate if device is a file system

   SEE ALSO
    Lock()

 dos.library/IsInteractive                           dos.library/IsInteractive

    NAME
    IsInteractive -- Discover whether a file is "interactive"

    SYNOPSIS
    status = IsInteractive( file )
    D0			D1

    BOOL IsInteractive(BPTR)

    FUNCTION
    The return value 'status' indicates whether the file associated
    with the file handle 'file' is connected to a virtual terminal.

    INPUTS
    file - BCPL pointer to a file handle

    RESULTS
    status - boolean

    SEE ALSO

 dos.library/LoadSeg                                       dos.library/LoadSeg

    NAME
    LoadSeg -- Scatterload a loadable file into memory

    SYNOPSIS
    seglist = LoadSeg( name )
    D0		   D1

    BPTR LoadSeg(STRPTR)

    FUNCTION
    The file 'name' should be a load module produced by the linker.
    LoadSeg() scatterloads the CODE, DATA and BSS segments into memory,
    chaining together the segments with BPTR's on their first words.
    The end of the chain is indicated by a zero.  There can be any number
    of segments in a file.  All necessary relocation is handled by
    LoadSeg().

    In the event of an error any blocks loaded will be unloaded and a
    NULL result returned.

    If the module is correctly loaded then the output will be a pointer
    at the beginning of the list of blocks. Loaded code is unloaded via
    a call to UnLoadSeg().

    INPUTS
    name - pointer to a null-terminated string

    RESULTS
    seglist - BCPL pointer to a seglist

    SEE ALSO
    UnLoadSeg(), InternalLoadSeg(), InternalUnLoadSeg(), CreateProc(),
    CreateNewProc(), NewLoadSeg().

 dos.library/Lock                                             dos.library/Lock

    NAME
    Lock -- Lock a directory or file

    SYNOPSIS
    lock  = Lock( name, accessMode )
    D0	      D1	D2

    BPTR Lock(STRPTR, LONG)

    FUNCTION
    A filing system lock on the file or directory 'name' is returned if
    possible.

    If the accessMode is ACCESS_READ, the lock is a shared read lock;
    if the accessMode is ACCESS_WRITE then it is an exclusive write
    lock.  Do not use random values for mode.

    If Lock() fails (that is, if it cannot obtain a filing system lock
    on the file or directory) it returns a zero.

    Tricky assumptions about the internal format of a lock are unwise,
    as are any attempts to use the fl_Link or fl_Access fields.

    INPUTS
    name	   - pointer to a null-terminated string
    accessMode - integer

    RESULTS
    lock - BCPL pointer to a lock

    SEE ALSO
    UnLock(), DupLock(), ChangeMode(), NameFromLock(), DupLockFromFH()

 dos.library/LockDosList                               dos.library/LockDosList

   NAME
    LockDosList -- Locks the specified Dos Lists for use (V36)

   SYNOPSIS
    dlist = LockDosList(flags)
    D0		     D1

    struct DosList *LockDosList(ULONG)

   FUNCTION
    Locks the dos device list in preparation to walk the list.
    If the list is 'busy' then this routine will not return until it is
    available.  This routine "nests": you can call it multiple times, and
    then must unlock it the same number of times.  The dlist
    returned is NOT a valid entry: it is a special value.  Note that
    for 1.3 compatibility, it also does a Forbid() - this will probably
    be removed at some future time.  The 1.3 Forbid() locking of this
    list had some race conditions.  The pointer returned by this is NOT
    an actual DosList pointer - you should use on of the other DosEntry
    calls to get actual pointers to DosList structures (such as
    NextDosEntry()), passing the value returned by LockDosList()
    as the dlist value.

    Note for handler writers: you should never call this function with
    LDF_WRITE, since it can deadlock you (if someone has it read-locked
    and they're trying to send you a packet).  Use AttemptLockDosList()
    instead, and effectively busy-wait with delays for the list to be
    available.  The other option is that you can spawn a process to
    add the entry safely.

    As an example, here's how you can search for all volumes of a specific
    name and do something with them:

    2.0 way:

        dl = LockDosList(LDF_VOLUMES|LDF_READ);
        while (dl = FindDosEntry(dl,name,LDF_VOLUMES))
        {
            Add to list of volumes to process or break out of
            the while loop.
            (You could try using it here, but I advise
            against it for compatability reasons if you
            are planning on continuing to examine the list.)
        }

        process list of volumes saved above, or current entry if
        you're only interested in the first one of that name.

        UnLockDosList();  /* must not use dl after this! */

    1.3/2.0 way:

        if (version >= 36)
            dl = LockDosList(LDF_VOLUMES|LDF_READ);
        else {
            Forbid();
            /* tricky! note dol_Next is at offset 0! */
            dl = &(...->di_DeviceList);
        }

        while (version >= 36 ?
                dl = FindDosEntry(dl,name,LDF_VOLUMES) :
                    dl = yourfindentry(dl,name,DLT_VOLUME))
        {
            Add to list of volumes to process, or break out of
            the while loop.
            Do NOT lock foo1/foo2 here if you will continue
            to examine the list - it breaks the forbid
            and the list may change on you.
        }

        process list of volumes saved above, or current entry if
        you're only interested in the first one of that name.

        if (version >= 36)
            UnLockDosList();
        else
            Permit();
        /* must not use dl after this! */
        ...

        struct DosList *
        yourfindentry (struct DosList *dl, STRPTRname, type)
        {
        /* tricky - depends on dol_Next being at offset 0,
           and the initial ptr being a ptr to di_DeviceList! */
            while (dl = dl->dol_Next)
            {
                if (dl->dol_Type == type &&
                stricmp(name,BADDR(dl->dol_Name)+1) == 0)
                {
                break;
                }
            }
            return dl;
        }

   INPUTS
    flags - Flags stating which types of nodes you want to lock.

   RESULT
    dlist - Pointer to the head of the list.  NOT a valid node!

   SEE ALSO
    AttemptLockDosList(), UnLockDosList(), Forbid(), NextDosEntry()

 dos.library/LockRecord                                 dos.library/LockRecord

   NAME
    LockRecord -- Locks a portion of a file (V36)

   SYNOPSIS
    success = LockRecord(fh,offset,length,mode,timeout)
    D0                   D1   D2     D3    D4    D5

    ULONG LockRecord(BPTR,ULONG,ULONG,ULONG,ULONG)

   FUNCTION
    This locks a portion of a file for exclusive access.  Timeout is how
    long to wait in ticks (1/50 sec) for the record to be available.

    Valid modes are:
        REC_EXCLUSIVE
        REC_EXCLUSIVE_IMMED
        REC_SHARED
        REC_SHARED_IMMED
    For the IMMED modes, the timeout is ignored.

    Record locks are tied to the filehandle used to create them.  The
    same filehandle can get any number of exclusive locks on the same
    record, for example.  These are cooperative locks, they only
    affect other people calling LockRecord().

   INPUTS
    fh      - File handle for which to lock the record
    offset  - Record start position
    length  - Length of record in bytes
    mode    - Type of lock requester
    timeout - Timeout interval in ticks.  0 is legal.

   RESULT
    success - Success or failure

   BUGS
    In 2.0 through 2.02 (V36), LockRecord() only worked in the ramdisk.
    Attempting to lock records on the disk filesystem causes a crash.
    This was fixed for V37.

   SEE ALSO
    LockRecords(), UnLockRecord(), UnLockRecords()

 dos.library/LockRecords                               dos.library/LockRecords

   NAME
    LockRecords -- Lock a series of records (V36)

   SYNOPSIS
    success = LockRecords(record_array,timeout)
    D0                       D1           D2

    BOOL LockRecords(struct RecordLock *,ULONG)

   FUNCTION
    This locks several records within a file for exclusive access.
    Timeout is how long to wait in ticks for the records to be available.
    The wait is applied to each attempt to lock each record in the list.
    It is recommended that you always lock a set of records in the same
    order to reduce possibilities of deadlock.

    The array of RecordLock structures is terminated by an entry with
    rec_FH of NULL.

   INPUTS
    record_array - List of records to be locked
    timeout      - Timeout interval.  0 is legal

   RESULT
    success      - Success or failure

   BUGS
    See LockRecord()

   SEE ALSO
    LockRecord(), UnLockRecord(), UnLockRecords()

 dos.library/MakeDosEntry                             dos.library/MakeDosEntry

   NAME
    MakeDosEntry -- Creates a DosList structure (V36)

   SYNOPSIS
    newdlist = MakeDosEntry(name, type)
    D0                       D1    D2

    struct DosList *MakeDosEntry(STRPTR, LONG)

   FUNCTION
    Create a DosList structure, including allocating a name and correctly
    null-terminating the BSTR.  It also sets the dol_Type field, and sets
    all other fields to 0.  This routine should be eliminated and replaced
    by a value passed to AllocDosObject()!

   INPUTS
    name - name for the device/volume/assign node.
    type - type of node.

   RESULT
    newdlist - The new device entry or NULL.

   SEE ALSO
    AddDosEntry(), RemDosEntry(), FindDosEntry(), LockDosList(),
    NextDosEntry(), FreeDosEntry()

 dos.library/MakeLink                                     dos.library/MakeLink

   NAME
    MakeLink -- Creates a filesystem link (V36)

   SYNOPSIS
    success = MakeLink( name, dest, soft )
    D0		     D1    D2    D3

    BOOL MakeLink( STRPTR, LONG, LONG )

   FUNCTION
    Create a filesystem link from 'name' to dest.  For "soft-links",
    dest is a pointer to a null-terminated path string.  For "hard-
    links", dest is a lock (BPTR).  'soft' is FALSE for hard-links,
    non-zero otherwise.

    Soft-links are resolved at access time by a combination of the
    filesystem (by returning ERROR_IS_SOFT_LINK to dos), and by
    Dos (using ReadLink() to resolve any links that are hit).

    Hard-links are resolved by the filesystem in question.  A series
    of hard-links to a file are all equivalent to the file itself.
    If one of the links (or the original entry for the file) is
    deleted, the data remains until there are no links left.

   INPUTS
    name - Name of the link to create
    dest - CPTR to path string, or BPTR lock
    soft - FALSE for hard-links, non-zero for soft-links

   RESULT
    Success - boolean

   BUGS
    In V36, soft-links didn't work in the ROM filesystem.  This was
    fixed for V37.

   SEE ALSO
    ReadLink(), Open(), Lock()

 dos.library/MatchEnd                                     dos.library/MatchEnd

   NAME
    MatchEnd -- Free storage allocated for MatchFirst()/MatchNext() (V36)

   SYNOPSIS
    MatchEnd(AnchorPath)
                 D1

    VOID MatchEnd(struct AnchorPath *)

   FUNCTION
    Return all storage associated with a given search.

   INPUTS
    AnchorPath - Anchor used for MatchFirst()/MatchNext()
             MUST be longword aligned!

   SEE ALSO
    MatchFirst(), ParsePattern(), Examine(), CurrentDir(), Examine(),
    MatchNext(), ExNext(), <dos/dosasl.h>

 dos.library/MatchFirst                                 dos.library/MatchFirst

   NAME
    MatchFirst -- Finds file that matches pattern (V36)

   SYNOPSIS
    error = MatchFirst(pat, AnchorPath)
    D0                 D1       D2

    LONG MatchFirst(STRPTR, struct AnchorPath *)

   FUNCTION
    Locates the first file or directory that matches a given pattern.
    MatchFirst() is passed your pattern (you do not pass it through
    ParsePattern() - MatchFirst() does that for you), and the control
    structure.  MatchFirst() normally initializes your AnchorPath
    structure for you, and returns the first file that matched your
    pattern, or an error.  Note that MatchFirst()/MatchNext() are unusual
    for Dos in that they return 0 for success, or the error code (see
    <dos/dos.h>), instead of the application getting the error code
    from IoErr().

    When looking at the result of MatchFirst()/MatchNext(), the ap_Info
    field of your AnchorPath has the results of an Examine() of the object.
    You normally get the name of the object from fib_FileName, and the
    directory it's in from ap_Current->an_Lock.  To access this object,
    normally you would temporarily CurrentDir() to the lock, do an action
    to the file/dir, and then CurrentDir() back to your original directory.
    This makes certain you affect the right object even when two volumes
    of the same name are in the system.  You can use ap_Buf (with
    ap_Strlen) to get a name to report to the user.

    To initialize the AnchorPath structure (particularily when reusing
    it), set ap_BreakBits to the signal bits (CDEF) that you want to take
    a break on, or NULL, if you don't want to convenience the user.
    ap_Flags should be set to any flags you need or all 0's otherwise.
    ap_FoundBreak should be cleared if you'll be using breaks.

    If you want to have the FULL PATH NAME of the files you found,
    allocate a buffer at the END of this structure, and put the size of
    it into ap_Strlen.  If you don't want the full path name, make sure
    you set ap_Strlen to zero.  In this case, the name of the file, and
    stats are available in the ap_Info, as per usual.

    Then call MatchFirst() and then afterwards, MatchNext() with this
    structure.  You should check the return value each time (see below)
    and take the appropriate action, ultimately calling MatchEnd() when
    there are no more files or you are done.  You can tell when you are
    done by checking for the normal AmigaDOS return code
    ERROR_NO_MORE_ENTRIES.

    Note: patterns with trailing slashes may cause MatchFirst()/MatchNext()
    to return with an ap_Current->an_Lock on the object, and a filename
    of the empty string ("").

    See ParsePattern() for more information on the patterns.

   INPUTS
    pat        - Pattern to search for
    AnchorPath - Place holder for search.  MUST be longword aligned!

   RESULT
    error - 0 for success or error code.  (Opposite of most Dos calls!)

   BUGS
    In V36, there were a number of bugs with MatchFirst()/MatchNext().
    One was that if you entered a directory with a name like "df0:l"
    using DODIR, it would re-lock the full string "df0:l", which can
    cause problems if the disk has changed.  It also had problems
    with patterns such as #?/abc/def - the ap_Current->an_Lock would
    not be on the directory def is found in.  ap_Buf would be correct,
    however.  It had similar problems with patterns with trailing
    slashes.  These have been fixed for V37 and later.

    A bug that has not been fixed for V37 concerns a pattern of a
    single directory name (such as "l").  If you enter such a directory
    via DODIR, it re-locks l relative to the current directory.  Thus
    you must not change the current directory before calling MatchNext()
    with DODIR in that situation.  If you aren't using DODIR to enter
    directories you can ignore this.  This may be fixed in some upcoming
    release.

   SEE ALSO
    MatchNext(), ParsePattern(), Examine(), CurrentDir(), Examine(),
    MatchEnd(), ExNext(), <dos/dosasl.h>

 dos.library/MatchNext                                   dos.library/MatchNext

   NAME
    MatchNext - Finds the next file or directory that matches pattern (V36)

   SYNOPSIS
    error = MatchNext(AnchorPath)
    D0                    D1

    LONG MatchNext(struct AnchorPath *)

   FUNCTION
    Locates the next file or directory that matches a given pattern.
    See <dos/dosasl.h> for more information.  Various bits in the flags
    allow the application to control the operation of MatchNext().

    See MatchFirst() for other notes.

   INPUTS
    AnchorPath - Place holder for search.  MUST be longword aligned!

   RESULT
    error - 0 for success or error code.  (Opposite of most Dos calls)

   BUGS
    See MatchFirst().

   SEE ALSO
    MatchFirst(), ParsePattern(), Examine(), CurrentDir(), Examine(),
    MatchEnd(), ExNext(), <dos/dosasl.h>

 dos.library/MatchPattern                             dos.library/MatchPattern

   NAME
    MatchPattern --  Checks for a pattern match with a string (V36)

   SYNOPSIS
    match = MatchPattern(pat, str)
    D0                   D1   D2

    BOOL MatchPattern(STRPTR, STRPTR)

   FUNCTION
    Checks for a pattern match with a string.  The pattern must be a
    tokenized string output by ParsePattern().  This routine is
    case-sensitive.

    NOTE: this routine is highly recursive.  You must have at least
    1500 free bytes of stack to call this (it will cut off it's
    recursion before going any deeper than that and return failure).
    That's _currently_ enough for about 100 levels deep of #, (, ~, etc.

   INPUTS
    pat - Special pattern string to match as returned by ParsePattern()
    str - String to match against given pattern

   RESULT
    match - success or failure of pattern match.  On failure,
        IoErr() will return 0 or ERROR_TOO_MANY_LEVELS (starting
        with V37 - before that there was no stack checking).

   SEE ALSO
    ParsePattern(), MatchPatternNoCase(), MatchFirst(), MatchNext()

 dos.library/MatchPatternNoCase                 dos.library/MatchPatternNoCase

   NAME
    MatchPatternNoCase --  Checks for a pattern match with a string (V37)

   SYNOPSIS
    match = MatchPatternNoCase(pat, str)
    D0                         D1   D2

    BOOL MatchPatternNoCase(STRPTR, STRPTR)

   FUNCTION
    Checks for a pattern match with a string.  The pattern must be a
    tokenized string output by ParsePatternNoCase().  This routine is
    case-insensitive.

    NOTE: this routine is highly recursive.  You must have at least
    1500 free bytes of stack to call this (it will cut off it's
    recursion before going any deeper than that and return failure).
    That's _currently_ enough for about 100 levels deep of #, (, ~, etc.

   INPUTS
    pat - Special pattern string to match as returned by ParsePatternNoCase()
    str - String to match against given pattern

   RESULT
    match - success or failure of pattern match.  On failure,
        IoErr() will return 0 or ERROR_TOO_MANY_LEVELS (starting
        with V37 - before that there was no stack checking).

   SEE ALSO
    ParsePatternNoCase(), MatchPattern(), MatchFirst(), MatchNext()

 dos.library/MaxCli                                         dos.library/MaxCli

   NAME
    MaxCli -- returns the highest CLI process number possibly in use (V36)

   SYNOPSIS
    number = MaxCli()
    D0

    LONG MaxCli(void)

   FUNCTION
    Returns the highest CLI number that may be in use.  CLI numbers are
    reused, and are usually as small as possible.  To find all CLIs, scan
    using FindCliProc() from 1 to MaxCLI().  The number returned by
    MaxCli() may change as processes are created and destroyed.

   RESULT
    number - The highest CLI number that _may_ be in use.

   SEE ALSO
    FindCliProc(), Cli()

 dos.library/NameFromFH                                 dos.library/NameFromFH

   NAME
    NameFromFH -- Get the name of an open filehandle (V36)

   SYNOPSIS
    success = NameFromFH(fh, buffer, len)
    D0                   D1    D2    D3

    BOOL NameFromFH(BPTR, STRPTR, LONG)

   FUNCTION
    Returns a fully qualified path for the filehandle.  This routine is
    guaranteed not to write more than len characters into the buffer.  The
    name will be null-terminated.  See NameFromLock() for more information.

   INPUTS
    fh     - Lock of object to be examined.
    buffer - Buffer to store name.
    len    - Length of buffer.

   RESULT
    success - Success/failure indicator.

   SEE ALSO
    NameFromLock()

 dos.library/NameFromLock                             dos.library/NameFromLock

   NAME
    NameFromLock -- Returns the name of a locked object (V36)

   SYNOPSIS
    success = NameFromLock(lock, buffer, len)
    D0                      D1     D2    D3

    BOOL NameFromLock(BPTR, STRPTR, LONG)

   FUNCTION
    Returns a fully qualified path for the lock.  This routine is
    guaranteed not to write more than len characters into the buffer.  The
    name will be null-terminated.  NOTE: if the volume is not mounted,
    the system will request it (unless of course you set pr_WindowPtr to
    -1).  If the volume is not mounted or inserted, it will return an
    error.  If the lock passed in is NULL, "SYS:" will be returned. If
    the buffer is too short, an error will be returned, and IoErr() will
    return ERROR_LINE_TOO_LONG.

   INPUTS
    lock   - Lock of object to be examined.
    buffer - Buffer to store name.
    len    - Length of buffer.

   RESULT
    success - Success/failure indicator.

   BUGS
    Should return the name of the boot volume instead of SYS: for a NULL
    lock.

   SEE ALSO
    NameFromFH(), Lock()

 dos.library/NewLoadSeg                                 dos.library/NewLoadSeg

   NAME
    NewLoadSeg -- Improved version of LoadSeg for stacksizes (V36)

   SYNOPSIS
    seglist = NewLoadSeg(file, tags)
    D0		      D1    D2

    BPTR NewLoadSeg(STRPTR, struct TagItem *)

    seglist = NewLoadSegTagList(file, tags)
    D0			     D1    D2

    BPTR NewLoadSegTagList(STRPTR, struct TagItem *)

    seglist = NewLoadSegTags(file, ...)

    BPTR NewLoadSegTags(STRPTR, ...)

   FUNCTION
    Does a LoadSeg on a file, and takes additional actions based on the
    tags supplied.

    Clears unused portions of Code and Data hunks (as well as BSS hunks).
    (This also applies to InternalLoadSeg() and LoadSeg()).

    NOTE to overlay users: NewLoadSeg() does NOT return seglist in
    both D0 and D1, as LoadSeg does.  The current ovs.asm uses LoadSeg(),
    and assumes returns are in D1.  We will support this for LoadSeg()
    ONLY.

   INPUTS
    file - Filename of file to load
    tags - pointer to tagitem array

   RESULT
    seglist - Seglist loaded, or NULL

   BUGS
    No tags are currently defined.

   SEE ALSO
    LoadSeg(), UnLoadSeg(), InternalLoadSeg(), InternalUnLoadSeg()

 dos.library/NextDosEntry                             dos.library/NextDosEntry

   NAME
    NextDosEntry -- Get the next Dos List entry (V36)

   SYNOPSIS
    newdlist = NextDosEntry(dlist,flags)
    D0                       D1    D2

    struct DosList *NextDosEntry(struct DosList *,ULONG)

   FUNCTION
    Find the next Dos List entry of the right type.  You MUST have locked
    the types you're looking for.  Returns NULL if there are no more of
    that type in the list.

   INPUTS
    dlist    - The current device entry.
    flags	 - What type of entries to look for.

   RESULT
    newdlist - The next device entry of the right type or NULL.

   SEE ALSO
    AddDosEntry(), RemDosEntry(), FindDosEntry(), LockDosList(),
    MakeDosEntry(), FreeDosEntry()

 dos.library/Open                                             dos.library/Open

    NAME
    Open -- Open a file for input or output

    SYNOPSIS
    file = Open( name, accessMode )
    D0	     D1    D2

    BPTR Open(STRPTR, LONG)

    FUNCTION
    The named file is opened and a file handle returned.  If the
    accessMode is MODE_OLDFILE, an existing file is opened for reading
    or writing. If the value is MODE_NEWFILE, a new file is created for
    writing. MODE_READWRITE opens a file with an shared lock, but
    creates it if it didn't exist.  Open types are documented in the
    <dos/dos.h> or <libraries/dos.h> include file.

    The 'name' can be a filename (optionally prefaced by a device
    name), a simple device such as NIL:, a window specification such as
    CON: or RAW: followed by window parameters, or "*", representing the
    current window.  Note that as of V36, "*" is obsolete, and CONSOLE:
    should be used instead.

    If the file cannot be opened for any reason, the value returned
    will be zero, and a secondary error code will be available by
    calling the routine IoErr().

    INPUTS
    name	   - pointer to a null-terminated string
    accessMode - integer

    RESULTS
    file - BCPL pointer to a file handle

    SEE ALSO
    Close(), ChangeMode(), NameFromFH(), ParentOfFH(), ExamineFH()

 dos.library/OpenFromLock                             dos.library/OpenFromLock

   NAME
    OpenFromLock -- Opens a file you have a lock on (V36)

   SYNOPSIS
    fh = OpenFromLock(lock)
    D0                 D1

    BPTR OpenFromLock(BPTR)

   FUNCTION
    Given a lock, this routine performs an open on that lock.  If the open
    succeeds, the lock is (effectively) relinquished, and should not be
    UnLock()ed or used.  If the open fails, the lock is still usable.
    The lock associated with the file internally is of the same access
    mode as the lock you gave up - shared is similar to MODE_OLDFILE,
    exclusive is similar to MODE_NEWFILE.

   INPUTS
    lock - Lock on object to be opened.

   RESULT
    fh   - Newly opened file handle or NULL for failure

   BUGS
    In the original V36 autodocs, this was shown (incorrectly) as
    taking a Mode parameter as well.  The prototypes and pragmas were
    also wrong.

   SEE ALSO
    Open(), Close(), Lock(), UnLock()

 dos.library/Output                                         dos.library/Output

    NAME
    Output -- Identify the programs' initial output file handle

    SYNOPSIS
    file = Output()
    D0

    BPTR Output(void)

    FUNCTION
    Output() is used to identify the initial output stream allocated
    when the program was initiated.  Never close the filehandle returned
    by Output().

    RESULTS
    file - BCPL pointer to a file handle

    SEE ALSO
    Input()

 dos.library/ParentDir                                   dos.library/ParentDir

    NAME
    ParentDir -- Obtain the parent of a directory or file

    SYNOPSIS
    newlock = ParentDir( lock )
    D0		     D1

    BPTR ParentDir(BPTR)

    FUNCTION
    The argument 'lock' is associated with a given file or directory.
    ParentDir() returns 'newlock' which is associated the parent
    directory of 'lock'.

    Taking the ParentDir() of the root of the current filing system
    returns a NULL (0) lock.  Note this 0 lock represents the root of
    file system that you booted from (which is, in effect, the parent
    of all other file system roots.)

    INPUTS
    lock - BCPL pointer to a lock

    RESULTS
    newlock - BCPL pointer to a lock

    SEE ALSO
    Lock(), DupLock(), UnLock(), ParentOfFH(), DupLockFromFH()

 dos.library/ParentOfFH                                 dos.library/ParentOfFH

   NAME
    ParentOfFH -- returns a lock on the parent directory of a file (V36)

   SYNOPSIS
    lock = ParentOfFH(fh)
    D0               D1

    BPTR ParentOfFH(BPTR)

   FUNCTION
    Returns a shared lock on the parent directory of the filehandle.

   INPUTS
    fh   - Filehandle you want the parent of.

   RESULT
    lock - Lock on parent directory of the filehandle or NULL for failure.

   SEE ALSO
    Parent(), Lock(), UnLock() DupLockFromFH()

 dos.library/ParsePattern                             dos.library/ParsePattern

   NAME
    ParsePattern -- Create a tokenized string for MatchPattern() (V36)

   SYNOPSIS
    IsWild = ParsePattern(Source, Dest, DestLength)
    d0                      D1     D2      D3

    LONG ParsePattern(STRPTR, STRPTR, LONG)

   FUNCTION
    Tokenizes a pattern, for use by MatchPattern().  Also indicates if
    there are any wildcards in the pattern (i.e. whether it might match
    more than one item).  Note that Dest must be at least 2 times as
    large as Source plus bytes to be (almost) 100% certain of no
    buffer overflow.  This is because each input character can currently
    expand to 2 tokens (with one exception that can expand to 3, but
    only once per string).  Note: this implementation may change in
    the future, so you should handle error returns in all cases, but
    the size above should still be a reasonable upper bound for a buffer
    allocation.

    The patterns are fairly extensive, and approximate some of the ability
    of Unix/grep "regular expression" patterns.  Here are the available
    tokens:

    ?	Matches a single character.
    #	Matches the following expression 0 or more times.
    (ab|cd)	Matches any one of the items seperated by '|'.
    ~	Negates the following expression.  It matches all strings
        that do not match the expression (aka ~(foo) matches all
        strings that are not exactly "foo").
    [abc]	Character class: matches any of the characters in the class.
    [~bc]	Character class: matches any of the characters not in the
        class.
    a-z	Character range (only within character classes).
    %	Matches 0 characters always (useful in "(foo|bar|%)").
    *	Synonym for "#?", not available by default in 2.0.  Available
        as an option that can be turned on.

    "Expression" in the above table means either a single character
    (ex: "#?"), or an alternation (ex: "#(ab|cd|ef)"), or a character
    class (ex: "#[a-zA-Z]").

   INPUTS
    source     - unparsed wildcard string to search for.
       dest       - output string, gets tokenized version of input.
    DestLength - length available in destination (should be at least as
             twice as large as source + 2 bytes).

   RESULT
    IsWild - 1 means there were wildcards in the pattern,
         0 means there were no wildcards in the pattern,
        -1 means there was a buffer overflow or other error

   BUGS
    Should set IoErr() to something useful (not currently set) on an
    error.

   SEE ALSO
    ParsePatternNoCase(), MatchPattern(), MatchFirst(), MatchNext()

 dos.library/ParsePatternNoCase                 dos.library/ParsePatternNoCase

   NAME
    ParsePatternNoCase -- Create a tokenized string for
                        MatchPatternNoCase() (V37)

   SYNOPSIS
    IsWild = ParsePatternNoCase(Source, Dest, DestLength)
    d0                            D1     D2      D3

    LONG ParsePatternNoCase(STRPTR, STRPTR, LONG)

   FUNCTION
    Tokenizes a pattern, for use by MatchPatternNoCase().  Also indicates
    if there are any wildcards in the pattern (i.e. whether it might match
    more than one item).  Note that Dest must be at least 2 times as
    large as Source plus 2 bytes.

    For a description of the wildcards, see ParsePattern().

   INPUTS
    source     - unparsed wildcard string to search for.
       dest       - output string, gets tokenized version of input.
    DestLength - length available in destination (should be at least as
             twice as large as source + 2 bytes).

   RESULT
    IsWild - 1 means there were wildcards in the pattern,
         0 means there were no wildcards in the pattern,
        -1 means there was a buffer overflow or other error

   BUGS
    Should set IoErr() to something useful (not currently set) on an
    error.

   SEE ALSO
    ParsePattern(), MatchPatternNoCase(), MatchFirst(), MatchNext()

 dos.library/PathPart                                     dos.library/PathPart

   NAME
    PathPart -- Returns a pointer to the end of the next-to-last (V36)
            component of a path.

   SYNOPSIS
    fileptr = PathPart( path )
    D0		     D1

    STRPTR PathPart( STRPTR )

   FUNCTION
    This function returns a pointer to the character after the next-to-last
    component of a path specification, which will normally be the directory
    name.  If there is only one component, it returns a pointer to the
    beginning of the string.  The only real difference between this and
    FilePart() is the handling of '/'.

   INPUTS
    path - pointer to an path string.  May be relative to the current
           directory or the current disk.

   RESULT
    fileptr - pointer to the end of the next-to-last component of the path.

   EXAMPLE
    PathPart("xxx:yyy/zzz/qqq") would return a pointer to the last '/'.
    PathPart("xxx:yyy") would return a pointer to the first 'y').

   SEE ALSO
    FilePart(), AddPart()

 dos.library/PrintFault                                 dos.library/PrintFault

   NAME
    PrintFault -- Returns the text associated with a DOS error code (V36)

   SYNOPSIS
    success = PrintFault(code, header)
    D0                    D1     D2

    BOOL PrintFault(LONG, STRPTR)

   FUNCTION
    This routine obtains the error message text for the given error code.
    This is similar to the Fault() function, except that the output is
    written to the default output channel with buffered output.
    The value returned by IoErr() is set to the code passed in.

   INPUTS
    code   - Error code
    header - header to output before error text

   RESULT
    success - Success/failure code.

   SEE ALSO
    IoErr(), Fault(), SetIoErr(), Output(), FPuts()

 dos.library/PutStr                                         dos.library/PutStr

   NAME
    PutStr -- Writes a string the the default output (buffered) (V36)

   SYNOPSIS
    error = PutStr(str)
    D0             D1

    LONG PutStr(STRPTR)

   FUNCTION
    This routine writes an unformatted string to the default output.  No
    newline is appended to the string and any error is returned.  This
    routine is buffered.

   INPUTS
    str   - Null-terminated string to be written to default output

   RESULT
    error - 0 for success, -1 for any error.  NOTE: this is opposite
        most Dos function returns!

   SEE ALSO
    FPuts(), FPutC(), FWrite(), WriteChars()

 dos.library/Read                                             dos.library/Read

    NAME
    Read -- Read bytes of data from a file

    SYNOPSIS
    actualLength = Read( file, buffer, length )
    D0		     D1    D2	   D3

    LONG Read(BPTR, void *, LONG)

    FUNCTION
    Data can be copied using a combination of Read() and Write().
    Read() reads bytes of information from an opened file (represented
    here by the argument 'file') into the buffer given. The argument
    'length' is the length of the buffer given.

    The value returned is the length of the information actually read.
    So, when 'actualLength' is greater than zero, the value of
    'actualLength' is the the number of characters read. Usually Read
    will try to fill up your buffer before returning. A value of zero
    means that end-of-file has been reached. Errors are indicated by a
    value of -1.

    Note: this is an unbuffered routine (the request is passed directly
    to the filesystem.)  Buffered I/O is more efficient for small
    reads and writes; see FGetC().

    INPUTS
    file - BCPL pointer to a file handle
    buffer - pointer to buffer
    length - integer

    RESULTS
    actualLength - integer

    SEE ALSO
    Open(), Close(), Write(), Seek(), FGetC()

 dos.library/ReadArgs                                     dos.library/ReadArgs

   NAME
    ReadArgs - Parse the command line input (V36)

   SYNOPSIS
    result = ReadArgs(template, array, rdargs)
    D0                   D1      D2      D3

    struct RDArgs * ReadArgs(STRPTR, LONG *, struct RDArgs *)

   FUNCTION
    Parses and argument string according to a template.  Normally gets
    the arguments by reading buffered IO from Input(), but also can be
    made to parse a string.  MUST be matched by a call to FreeArgs().

    ReadArgs() parses the commandline according to a template that is
    passed to it.  This specifies the different command-line options and
    their types.  A template consists of a list of options.  Options are
    named in "full" names where possible (for example, "Quick" instead of
    "Q").  Abbreviations can also be specified by using "abbrev=option"
    (for example, "Q=Quick").

    Options in the template are separated by commas.  To get the results
    of ReadArgs(), you examine the array of longwords you passed to it
    (one entry per option in the template).  This array should be cleared
    (or initialized to your default values) before passing to ReadArgs().
    Exactly what is put in a given entry by ReadArgs() depends on the type
    of option.  The default is a string (a sequence of non-whitespace
    characters, or delimited by quotes, which will be stripped by
    ReadArgs()), in which case the entry will be a pointer.

    Options can be followed by modifiers, which specify things such as
    the type of the option.  Modifiers are specified by following the
    option with a '/' and a single character modifier.  Multiple modifiers
    can be specified by using multiple '/'s.  Valid modifiers are:

    /S - Switch.  This is considered a boolean variable, and will be
         set if the option name appears in the command-line.  The entry
         is the boolean (0 for not set, non-zero for set).

    /K - Keyword.  This means that the option will not be filled unless
         the keyword appears.  For example if the template is "Name/K",
         then unless "Name=<string>" or "Name <string>" appears in the
         command line, Name will not be filled.

    /N - Number.  This parameter is considered a decimal number, and will
         be converted by ReadArgs.  If an invalid number is specified,
         an error will be returned.  The entry will be a pointer to the
         longword number (this is how you know if a number was specified).

    /T - Toggle.  This is similar to a switch, but when specified causes
         the boolean value to "toggle".  Similar to /S.

    /A - Required.  This keyword must be given a value during command-line
         processing, or an error is returned.

    /F - Rest of line.  If this is specified, the entire rest of the line
         is taken as the parameter for the option, even if other option
         keywords appear in it.

    /M - Multiple strings.  This means the argument will take any number
         of strings, returning them as an array of strings.  Any arguments
         not considered to be part of another option will be added to this
         option.  Only one /M should be specified in a template.  Example:
         for a template "Dir/M,All/S" the command-line "foo bar all qwe"
         will set the boolean "all", and return an array consisting of
         "foo", "bar", and "qwe".  The entry in the array will be a pointer
         to an array of string pointers, the last of which will be NULL.

         There is an interaction between /M parameters and /A parameters.
         If there are unfilled /A parameters after parsing, it will grab
         strings from the end of a previous /M parameter list to fill the
         /A's.  This is used for things like Copy ("From/A/M,To/A").

    ReadArgs() returns a struct RDArgs if it succeeds.  This serves as an
    "anchor" to allow FreeArgs() to free the associated memory.  You can
    also pass in a struct RDArgs to control the operation of ReadArgs()
    (normally you pass NULL for the parameter, and ReadArgs() allocates
    one for you).  This allows providing different sources for the
    arguments, providing your own string buffer space for temporary
    storage, and extended help text.  See <dos/rdargs.h> for more
    information on this.  Note: if you pass in a struct RDArgs, you must
    still call FreeArgs() to release storage that gets attached to it,
    but you are responsible for freeing the RDArgs yourself.

    See BUGS regarding passing in strings.

   INPUTS
    template - formatting string
    array    - array of longwords for results, 1 per template entry
    rdargs   - optional rdargs structure for options.  AllocDosObject
           should be used for allocating them if you pass one in.

   RESULT
    result   - a struct RDArgs or NULL for failure.

   BUGS
    In V36, there were a couple of minor bugs with certain argument
    combinations (/M/N returned strings, /T didn't work, and /K and
    /F interacted).  Also, a template with a /K before any non-switch
    parameter will require the argument name to be given in order for
    line to be accepted (i.e. "parm/K,xyzzy/A" would require
    "xyzzy=xxxxx" in order to work - "xxxxx" would not work).  If you
    need to avoid this for V36, put /K parameters after all non-switch
    parameters.  These problems should be fixed for V37.

    Currently (V37 and before) it requires any strings passed in to have
    newlines at the end of the string.  This may or may not be fixed in
    the future.

   SEE ALSO
    FindArg(), ReadItem(), FreeArgs(), AllocDosObject()

 dos.library/ReadItem                                     dos.library/ReadItem

   NAME
    ReadItem - reads a single argument/name from command line (V36)

   SYNOPSIS
    value = ReadItem(buffer, maxchars, input)
    D0                D1        D2      D3

    LONG ReadItem(STRPTR, LONG, struct CSource *)

   FUNCTION
    Reads a "word" from either Input() (buffered), or via CSource, if it
    is non-NULL (see <dos/rdargs.h> for more information).  Handles
    quoting and some '*' substitutions (*e and *n) inside quotes (only).
    See dos/dos.h for a listing of values returned by ReadItem()
    (ITEM_XXXX).  A "word" is delimited by whitespace, quotes, or an EOF.

    ReadItem always unreads the last thing read (UnGetC(fh,-1)) so the
    caller can find out what the terminator was.

   INPUTS
    buffer   - buffer to store word in.
    maxchars - size of the buffer
    input    - CSource input or NULL (uses FGetC(Input()))

   RESULT
    value - See <dos/dos.h> for return values.

   SEE ALSO
    ReadArgs(), FindArg(), UnGetC(), FGetC(), Input(), <dos/dos.h>,
    <dos/rdargs.h>, FreeArgs()

 dos.library/ReadLink                                     dos.library/ReadLink

   NAME
    ReadLink -- Reads the path for a soft filesystem link (V36)

   SYNOPSIS
    success = ReadLink( port, lock, path, buffer, size)
    D0		     D1    D2    D3     D4     D5

    BOOL ReadLink( struct MsgPort *, BPTR, STRPTR, STRPTR, ULONG)

   FUNCTION
    ReadLink() takes a lock/name pair (usually from a failed attempt
    to use them to access an object with packets), and asks the
    filesystem to find the softlink and fill buffer with the modified
    path string.  You then start the resolution process again by
    calling GetDeviceProc() with the new string from ReadLink().

    Soft-links are resolved at access time by a combination of the
    filesystem (by returning ERROR_IS_SOFT_LINK to dos), and by
    Dos (using ReadLink() to resolve any links that are hit).

   INPUTS
    port - msgport of the filesystem
    lock - lock this path is relative to on the filesystem
    path - path that caused the ERROR_IS_SOFT_LINK
    buffer - pointer to buffer for new path from handler.
    size - size of buffer.

   RESULT
    Success - boolean

   BUGS
    In V36, soft-links didn't work in the ROM filesystem.  This was
    fixed for V37.

   SEE ALSO
    MakeLink(), Open(), Lock(), GetDeviceProc()

 dos.library/Relabel                                       dos.library/Relabel

   NAME
    Relabel -- Change the volume name of a volume (V36)

   SYNOPSIS
    success = Relabel(volumename,name)
    D0                    D1      D2

    BOOL Relabel(STRPTR,STRPTR)

   FUNCTION
    Changes the volumename of a volume, if supported by the filesystem.

   INPUTS
    volumename - Full name of device to rename (with ':')
    newname    - New name to apply to device (without ':')

   RESULT
    success    - Success/failure indicator

   SEE ALSO

 dos.library/RemAssignList                           dos.library/RemAssignList

   NAME
    RemAssignList -- Remove an entry from a multi-dir assign (V36)

   SYNOPSIS
    success = RemAssignList(name,lock)
    D0                  	 D1   D2

    BOOL RemAssignList(STRPTR,BPTR)

   FUNCTION
    Removes an entry from a multi-directory assign.  The entry removed is
    the first one for which SameLock with 'lock' returns that they are on
    the same object.  The lock for the entry in the list is unlocked (not
    the entry passed in).

   INPUTS
    name - Name of device to remove lock from (without trailing ':')
    lock - Lock associated with the object to remove from the list

   RESULT
    success - Success/failure indicator.

   SEE ALSO
    Lock(), AssignLock(), AssignPath(), AssignLate(), DupLock(),
    AssignAdd(), UnLock()

 dos.library/RemDosEntry                               dos.library/RemDosEntry

   NAME
    RemDosEntry -- Removes a Dos List entry from it's list (V36)

   SYNOPSIS
    success = RemDosEntry(dlist)
    D0                     D1

    BOOL RemDosEntry(struct DosList *)

   FUNCTION
    This removes an entry from the Dos Device list.  The memory associated
    with the entry is NOT freed.  NOTE: you must have locked the Dos List
    with the appropriate flags before calling this routine.  Handler
    writers should see the AddDosEntry() caveats about locking and use
    a similar workaround to avoid deadlocks.

   INPUTS
    dlist   - Device list entry to be removed.

   RESULT
    success - Success/failure indicator

   SEE ALSO
    AddDosEntry(), FindDosEntry(), NextDosEntry(), LockDosList(),
    MakeDosEntry(), FreeDosEntry()

 dos.library/RemSegment                                 dos.library/RemSegment

   NAME
    RemSegment - Removes a resident segment from the resident list (V36)

   SYNOPSIS
    success = RemSegment(segment)
    D0		        D1

    BOOL RemSegment(struct Segment *)

   FUNCTION
    Removes a resident segment from the Dos resident segment list,
    unloads it, and does any other cleanup required.  Will only succeed
    if the seg_UC (usecount) is 0.

   INPUTS
    segment - the segment to be removed

   RESULT
    success - success or failure.

   SEE ALSO
    FindSegment(), AddSegment()

 dos.library/Rename                                         dos.library/Rename

    NAME
    Rename -- Rename a directory or file

    SYNOPSIS
    success = Rename( oldName, newName )
    D0		  D1	   D2

    BOOL Rename(STRPTR, STRPTR)

    FUNCTION
    Rename() attempts to rename the file or directory specified as
    'oldName' with the name 'newName'. If the file or directory
    'newName' exists, Rename() fails and returns an error. Both
    'oldName' and the 'newName' can contain a directory specification.
    In this case, the file will be moved from one directory to another.

    Note: it is impossible to Rename() a file from one volume to
    another.

    INPUTS
    oldName - pointer to a null-terminated string
    newName - pointer to a null-terminated string

    RESULTS
    success - boolean

    SEE ALSO
    Relabel()

 dos.library/ReplyPkt                                     dos.library/ReplyPkt

   NAME
    ReplyPkt -- replies a packet to the person who sent it to you (V36)

   SYNOPSIS
    ReplyPkt(packet, result1, result2)
           D1      D2       D3

    void ReplyPkt(struct DosPacket *, LONG, LONG)

   FUNCTION
    This returns a packet to the process which sent it to you.  In
    addition, puts your pr_MsgPort address in dp_Port, so using ReplyPkt()
    again will send the message to you.  (This is used in "ping-ponging"
    packets between two processes).  It uses result 1 & 2 to set the
    dp_Res1 and dp_Res2 fields of the packet.

   INPUTS
    packet  - packet to reply, assumed to set up correctly.
    result1 - first result
    result2 - secondary result

   SEE ALSO
    DoPkt(), SendPkt(), WaitPkt(), IoErr()

 dos.library/RunCommand                                 dos.library/RunCommand

   NAME
    RunCommand -- Runs a program using the current process (V36)

   SYNOPSIS
    rc = RunCommand(seglist, stacksize, argptr, argsize)
    D0                D1         D2       D3      D4

    LONG RunCommand(BPTR, ULONG, STRPTR, ULONG)

   FUNCTION
    Runs a command on your process/cli.  Seglist may be any language,
    including BCPL programs.  Stacksize is in bytes.  argptr is a null-
    terminated string, argsize is its length.  Returns the returncode the
    program exited with in d0. Returns -1 if the stack couldn't be
    allocated.

    NOTE: the argument string MUST be terminated with a newline to work
    properly with ReadArgs() and other argument parsers.

    RunCommand also takes care of setting up the current input filehandle
    in such a way that ReadArgs() can be used in the program, and restores
    the state of the buffering before returning.  It also sets the value
    returned by GetArgStr(), and restores it before returning.  NOTE:
    the setting of the argument string in the filehandle was added in V37.

    It's usually appropriate to set the command name (via
    SetProgramName()) before calling RunCommand().  RunCommand() sets
    the value returned by GetArgStr() while the command is running.

   INPUTS
    seglist   - Seglist of command to run.
    stacksize - Number of bytes to allocate for stack space
    argptr    - Pointer to argument command string.
    argsize   - Number of bytes in argument command.

   RESULT
    rc        - Return code from executed command. -1 indicates failure

   SEE ALSO
    CreateNewProc(), SystemTagList(), Execute(), GetArgStr(),
    SetProgramName(), ReadArgs()

 dos.library/SameDevice                                 dos.library/SameDevice

   NAME
    SameDevice -- Are two locks are on partitions of the device? (V37)

   SYNOPSIS
    same = SameDevice(lock1, lock2)
    D0		   D1     D2

    BOOL SameDevice( BPTR, BPTR )

   FUNCTION
    SameDevice() returns whether two locks refer to partitions that
    are on the same physical device (if it can figure it out).  This
    may be useful in writing copy routines to take advantage of
    asynchronous multi-device copies.

    Entry existed in V36 and always returned 0.

   INPUTS
    lock1,lock2 - locks

   RESULT
    same - whether they're on the same device as far as Dos can determine.

 dos.library/SameLock                                     dos.library/SameLock

   NAME
    SameLock -- returns whether two locks are on the same object (V36)

   SYNOPSIS
    value = SameLock(lock1, lock2)
    D0		  D1     D2

    LONG SameLock(BPTR, BPTR)

   FUNCTION
    Compares two locks.  Returns LOCK_SAME if they are on the same object,
    LOCK_SAME_VOLUME if on different objects on the same volume, and
    LOCK_DIFFERENT if they are on different volumes.  Always compare
    for equality or non-equality with the results, in case new return
    values are added.

   INPUTS
    lock1 - 1st lock for comparison
    lock2 - 2nd lock for comparison

   RESULT
    value -	LOCK_SAME, LOCK_SAME_VOLUME, or LOCK_DIFFERENT

   BUGS
    Should do more extensive checks for NULL against a real lock, checking
    to see if the real lock is a lock on the root of the boot volume.

    In V36, it would return LOCK_SAME_VOLUME for different volumes on the
    same handler.  Also, LOCK_SAME_VOLUME was LOCK_SAME_HANDLER (now
    an obsolete define, see <dos/dos.h>).

   SEE ALSO
    <dos/dos.h>

 dos.library/Seek                                             dos.library/Seek

    NAME
    Seek -- Set the current position for reading and writing

    SYNOPSIS
    oldPosition = Seek( file, position, mode )
    D0		    D1	  D2	    D3

    LONG Seek(BPTR, LONG, LONG)

    FUNCTION
    Seek() sets the read/write cursor for the file 'file' to the
    position 'position'. This position is used by both Read() and
    Write() as a place to start reading or writing. The result is the
    current absolute position in the file, or -1 if an error occurs, in
    which case IoErr() can be used to find more information. 'mode' can
    be OFFSET_BEGINNING, OFFSET_CURRENT or OFFSET_END. It is used to
    specify the relative start position. For example, 20 from current
    is a position 20 bytes forward from current, -20 is 20 bytes back
    from current.

    So that to find out where you are, seek zero from current. The end
    of the file is a Seek() positioned by zero from end. You cannot
    Seek() beyond the end of a file.

    INPUTS
    file - BCPL pointer to a file handle
    position - integer
    mode - integer

    RESULTS
    oldPosition - integer

    BUGS
    The V36 and V37 ROM filesystem (and V36/V37 l:fastfilesystem)
    returns the current position instead of -1 on an error.  It sets
    IoErr() to 0 on success, and an error code on an error.

    SEE ALSO
    Read(), Write(), SetFileSize()

 dos.library/SelectInput                               dos.library/SelectInput

   NAME
    SelectInput -- Select a filehandle as the default input channel (V36)

   SYNOPSIS
    old_fh = SelectInput(fh)
    D0                   D1

    BPTR SelectInput(BPTR)

   FUNCTION
    Set the current input as the default input for the process.
    This changes the value returned by Input().  old_fh should
    be closed or saved as needed.

   INPUTS
    fh     - Newly default input handle

   RESULT
    old_fh - Previous default input filehandle

   SEE ALSO
    Input(), SelectOutput(), Output()

 dos.library/SelectOutput                             dos.library/SelectOutput

   NAME
    SelectOutput -- Select a filehandle as the default input channel (V36)

   SYNOPSIS
    old_fh = SelectOutput(fh)
    D0                    D1

    BPTR SelectOutput(BPTR)

   FUNCTION
    Set the current output as the default output for the process.
    This changes the value returned by Output().  old_fh should
    be closed or saved as needed.

   INPUTS
    fh     - Newly desired output handle

   RESULT
    old_fh - Previous current output

   SEE ALSO
    Output(), SelectInput(), Input()

 dos.library/SendPkt                                       dos.library/SendPkt

   NAME
    SendPkt -- Sends a packet to a handler (V36)

   SYNOPSIS
    SendPkt(packet, port, replyport)
         D1     D2	D3

    void SendPkt(struct DosPacket *,struct MsgPort *,struct MsgPort *)

   FUNCTION
    Sends a packet to a handler and does not wait.  All fields in the
    packet must be initialized before calling this routine.  The packet
    will be returned to replyport.  If you wish to use this with
    WaitPkt(), use the address or your pr_MsgPort for replyport.

   INPUTS
    packet - packet to send, must be initialized and have a message.
    port   - pr_MsgPort of handler process to send to.
    replyport - MsgPort for the packet to come back to.

   NOTES
    Callable from a task.

   SEE ALSO
    DoPkt(), WaitPkt(), AllocDosObject(), FreeDosObject(), AbortPkt()

 dos.library/SetArgStr                                   dos.library/SetArgStr

   NAME
    SetArgStr -- Sets the arguments for the current process (V36)

   SYNOPSIS
    oldptr = SetArgStr(ptr)
    D0		   D1

    STRPTR SetArgStr(STRPTR)

   FUNCTION
    Sets the arguments for the current program.  The ptr MUST be reset
    to it's original value before process exit.

   INPUTS
    ptr - pointer to new argument string.

   RESULT
    oldptr - the previous argument string

   SEE ALSO
    GetArgStr(), RunCommand()

 dos.library/SetComment                                 dos.library/SetComment

    NAME
    SetComment -- Change a files' comment string

    SYNOPSIS
    success = SetComment( name, comment )
    D0		      D1    D2

    BOOL SetComment(STRPTR, STRPTR)

    FUNCTION
    SetComment() sets a comment on a file or directory. The comment is
    a pointer to a null-terminated string of up to 80 characters in the
    current ROM filesystem (and RAM:).  Note that not all filesystems
    will support comments (for example, NFS usually will not), or the
    size of comment supported may vary.

    INPUTS
    name    - pointer to a null-terminated string
    comment - pointer to a null-terminated string

    RESULTS
    success - boolean

    SEE ALSO
    Examine(), ExNext(), SetProtection()

 dos.library/SetConsoleTask                         dos.library/SetConsoleTask

   NAME
    SetConsoleTask -- Sets the default console for the process (V36)

   SYNOPSIS
    oldport = SetConsoleTask(port)
    D0			  D1

    struct MsgPort *SetConsoleTask(struct MsgPort *)

   FUNCTION
    Sets the default console task's port (pr_ConsoleTask) for the
    current process.

   INPUTS
    port - The pr_MsgPort of the default console handler for the process

   RESULT
    oldport - The previous ConsoleTask value.

   SEE ALSO
    GetConsoleTask(), Open()

 dos.library/SetCurrentDirName                   dos.library/SetCurrentDirName

   NAME
    SetCurrentDirName -- Sets the directory name for the process (V36)

   SYNOPSIS
    success = SetCurrentDirName(name)
    D0                        D1

    BOOL SetCurrentDirName(STRPTR)

   FUNCTION
    Sets the name for the current dir in the cli structure.  If the name
    is too long to fit, a failure is returned, and the old value is left
    intact.  It is advised that you inform the user of this condition.
    This routine is safe to call even if there is no CLI structure.

   INPUTS
    name    - Name of directory to be set.

   RESULT
    success - Success/failure indicator

   BUGS
    This clips to a fixed (1.3 compatible) size.

   SEE ALSO
    GetCurrentDirName()

 dos.library/SetFileDate                               dos.library/SetFileDate

   NAME
    SetFileDate -- Sets the modification date for a file or dir (V36)

   SYNOPSIS
    success = SetFileDate(name, date)
    D0                     D1    D2

    BOOL SetFileDate(STRPTR, struct DateStamp *)

   FUNCTION
    Sets the file date for a file or directory.  Note that for the Old
    File System and the Fast File System, the date of the root directory
    cannot be set.  Other filesystems may not support setting the date
    for all files/directories.

   INPUTS
    name - Name of object
    date - New modification date

   RESULT
    success - Success/failure indication

   SEE ALSO
    DateStamp(), Examine(), ExNext(), ExAll()

 dos.library/SetFileSize                               dos.library/SetFileSize

   NAME
    SetFileSize -- Sets the size of a file (V36)

   SYNOPSIS
    newsize = SetFileSize(fh, offset, mode)
    D0                    D1    D2     D3

    LONG SetFileSize(BPTR, LONG, LONG)

   FUNCTION
    Changes the file size, truncating or extending as needed.  Not all
    handlers may support this; be careful and check the return code.  If
    the file is extended, no values should be assumed for the new bytes.
    If the new position would be before the filehandle's current position
    in the file, the filehandle will end with a position at the
    end-of-file.  If there are other filehandles open onto the file, the
    new size will not leave any filehandle pointing past the end-of-file.
    You can check for this by looking at the new size.

    Do NOT count on any specific values to be in the extended area.

   INPUTS
    fh     - File to be truncated/extended.
    offset - Offset from position determined by mode.
    mode   - One of OFFSET_BEGINNING, OFFSET_CURRENT, or OFFSET_END.

   RESULT
    newsize - position of new end-of-file or -1 for error.

   SEE ALSO
    Seek()

 dos.library/SetFileSysTask                         dos.library/SetFileSysTask

   NAME
    SetFileSysTask -- Sets the default filesystem for the process (V36)

   SYNOPSIS
    oldport = SetFileSysTask(port)
    D0			  D1

    struct MsgPort *SetFileSysTask(struct MsgPort *)

   FUNCTION
    Sets the default filesystem task's port (pr_FileSystemTask) for the
    current process.

   INPUTS
    port - The pr_MsgPort of the default filesystem for the process

   RESULT
    oldport - The previous FileSysTask value

   SEE ALSO
    GetFileSysTask(), Open()

 dos.library/SetIoErr                                     dos.library/SetIoErr

   NAME
    SetIoErr -- Sets the value returned by IoErr() (V36)

   SYNOPSIS
    oldcode = SetIoErr(code)
    D0		    D1

    LONG SetIoErr(LONG);

   FUNCTION
    This routine sets up the secondary result (pr_Result2) return code
    (returned by the IoErr() function).

   INPUTS
    code - Code to be returned by a call to IoErr.

   RESULT
    oldcode - The previous error code.

   SEE ALSO
    IoErr(), Fault(), PrintFault()

 dos.library/SetMode                                       dos.library/SetMode

   NAME
    SetMode - Set the current behavior of a handler (V36)

   SYNOPSIS
    success = SetMode(fh, mode)
    D0                D1  D2

    BOOL SetMode(BPTR, LONG)

   FUNCTION
    SetMode() sends an ACTION_SCREEN_MODE packet to the handler in
    question, normally for changing a CON: handler to raw mode or
    vice-versa.  For CON:, use 1 to go to RAW: mode, 0 for CON: mode.

   INPUTS
    fh   - filehandle
    mode - The new mode you want

   RESULT
    success - Boolean

   SEE ALSO

 dos.library/SetProgramDir                           dos.library/SetProgramDir

   NAME
    SetProgramDir -- Sets the directory returned by GetProgramDir (V36)

   SYNOPSIS
    oldlock = SetProgramDir(lock)
    D0		         D1

    BPTR SetProgramDir(BPTR)

   FUNCTION
    Sets a shared lock on the directory the program was loaded from.
    This can be used for a program to find data files, etc, that are
    stored with the program, or to find the program file itself.  NULL
    is a valid input.  This can be accessed via GetProgramDir() or
    by using paths relative to PROGDIR:.

   INPUTS
    lock - A lock on the directory the current program was loaded from

   RESULT
    oldlock - The previous ProgramDir.

   SEE ALSO
    GetProgramDir(), Open()

 dos.library/SetProgramName                         dos.library/SetProgramName

   NAME
    SetProgramName -- Sets the name of the program being run (V36)

   SYNOPSIS
    success = SetProgramName(name)
    D0                        D1

    BOOL SetProgramName(STRPTR)

   FUNCTION
    Sets the name for the program in the cli structure.  If the name is
    too long to fit, a failure is returned, and the old value is left
    intact.  It is advised that you inform the user if possible of this
    condition, and/or set the program name to an empty string.
    This routine is safe to call even if there is no CLI structure.

   INPUTS
    name    - Name of program to use.

   RESULT
    success - Success/failure indicator.

   BUGS
    This clips to a fixed (1.3 compatible) size.

   SEE ALSO
    GetProgramName()

 dos.library/SetPrompt                                   dos.library/SetPrompt

   NAME
    SetPrompt -- Sets the CLI/shell prompt for the current process (V36)

   SYNOPSIS
    success = SetPrompt(name)
    D0                D1

    BOOL SetPrompt(STRPTR)

   FUNCTION
    Sets the text for the prompt in the cli structure.  If the prompt is
    too long to fit, a failure is returned, and the old value is left
    intact.  It is advised that you inform the user of this condition.
    This routine is safe to call even if there is no CLI structure.

   INPUTS
    name    - Name of prompt to be set.

   RESULT
    success - Success/failure indicator.

   BUGS
    This clips to a fixed (1.3 compatible) size.

   SEE ALSO
    GetPrompt()

 dos.library/SetProtection                           dos.library/SetProtection

    NAME
    SetProtection -- Set protection for a file or directory

    SYNOPSIS
    success = SetProtection( name, mask )
    D0			 D1    D2:4

    BOOL SetProtection (STRPTR, LONG)

    FUNCTION
    SetProtection() sets the protection attributes on a file or
    directory. The lower bits of the mask are as follows:

    bit 4: 1 = file has not changed 	0 = file has been changed
    bit 3: 1 = reads not allowed,		0 = reads allowed.
    bit 2: 1 = writes not allowed,		0 = writes allowed.
    bit 1: 1 = execution not allowed,	0 = execution allowed.
    bit 0: 1 = deletion not allowed,	0 = deletion allowed.

    Before V36, the ROM filesystem didn't respect the Read and Write
    bits.  In V36 or later and in the FFS, the Read and Write
    bits are respected.

    The archive bit should be cleared by the filesystem whenever the file
    is changed.  Backup utilities will generally set the bit after
    backing up each file.

    The V36 Shell looks at the execute bit, and will refuse to execute
    a file if it is set.

    Other bits will be defined in the <dos/dos.h> include files.  Rather
    than referring to bits by number you should use the definitions in
    <dos/dos.h>.

    INPUTS
    name - pointer to a null-terminated string
    mask - the protection mask required

    RESULTS
    success - boolean

    SEE ALSO
    SetComment(), Examine(), ExNext(), <dos/dos.h>

 dos.library/SetVar                                         dos.library/SetVar

   NAME
    SetVar -- Sets a local or environment variable (V36)

   SYNOPSIS
    success = SetVar( name, buffer, size, flags )
    D0	           D1     D2     D3    D4

    BOOL SetVar(STRPTR, STRPTR, LONG, ULONG )

   FUNCTION
    Sets a local or environment variable.  It is advised to only use
    ASCII strings inside variables, but not required.

   INPUTS
    name   - pointer to an variable name.  Note variable names follow
         filesystem syntax and semantics.
    buffer - a user allocated area which contains a string that is the
         value to be associated with this variable.
    size   - length of the buffer region in bytes.  -1 means buffer
         contains a null-terminated string.
    flags  - combination of type of var to set (low 8 bits), and
         flags to control the behavior of this routine.  Currently
         defined flags include:

        GVF_LOCAL_ONLY - set a local (to your process) variable.
        GVF_GLOBAL_ONLY - set a global environment variable.

        The default is to set a local environment variable.

   RESULT
    success - If non-zero, the variable was sucessfully set, FALSE
           indicates failure.

   BUGS
    LV_VAR is the only type that can be global

   SEE ALSO
    GetVar(), DeleteVar(), FindVar(), <dos/var.h>

 dos.library/SetVBuf                                       dos.library/SetVBuf

   NAME
    SetVBuf -- set buffering modes and size (V36)

   SYNOPSIS
    error = SetVBuf(fh, buff, type, size)
    D0		D1   D2    D3    D4

    LONG SetVBuf(BPTR, STRPTR, LONG, LONG)

   FUNCTION
    Changes the buffering modes and buffer size for a filehandle.
    With buff == NULL, the current buffer will be deallocated and a
    new one of (approximately) size will be allocated.  If buffer is
    non-NULL, it will be used for buffering and must be at least
    max(size,208) bytes long.  If buff is NULL and size is -1,
    then only the buffering mode will be changed.

   INPUTS
    fh   - Filehandle
    buff - buffer pointer for buffered I/O
    type - buffering mode (see <dos/stdio.h>)
    size - size of buffer for buffered I/O (sizes less than 208 bytes
           will be ignored).

   RESULT
    error - 0 if successful.  NOTE: opposite of most dos functions!

   BUGS
    Not implemented yet, always returns 0.

   SEE ALSO
    FputC(), FGetC(), UnGetC(), Flush(), FRead(), FWrite(), FGets(),
    FPuts().

 dos.library/SplitName                                   dos.library/SplitName

   NAME
    SplitName -- splits out a component of a pathname into a buffer (V36)

   SYNOPSIS
    newpos = SplitName(name, separator, buf, oldpos, size)
    D0                  D1      D2      D3     D4     D5

    WORD SplitName(STRPTR, UBYTE, STRPTR, WORD, LONG)

   FUNCTION
    This routine splits out the next piece of a name from a given file
    name.  Each piece is copied into the buffer, truncating at size-1
    characters.  The new position is then returned so that it may be
    passed in to the next call to splitname.  If the separator is not
    found within 'size' characters, then size-1 characters plus a null will
    be put into the buffer, and the position of the next separator will
    be returned.

    If a a separator cannot be found, -1 is returned (but the characters
    from the old position to the end of the string are copied into the
    buffer, up to a maximum of size-1 characters).  Both strings are
    null-terminated.

    This function is mainly intended to support handlers.

   INPUTS
    name      - Filename being parsed.
    separator - Separator charactor to split by.
    buf       - Buffer to hold separated name.
    oldpos    - Current position in the file.
    size 	  - Size of buf in bytes (including null termination);

   RESULT
    newpos    - New position for next call to splitname.  -1 for last one.

   SEE ALSO
    FilePart(), PathPart(), AddPart()

 dos.library/StartNotify                               dos.library/StartNotify

   NAME
    StartNotify -- Starts notification on a file or directory (V36)

   SYNOPSIS
    success = StartNotify(notifystructure)
    D0                          D1

    BOOL StartNotify(struct NotifyRequest *)

   FUNCTION
    Posts a notification request.  Do not modify the notify structure while
    it is active.  You will be notified when the file or directory changes.
    For files, you will be notified after the file is closed.  Not all
    filesystems will support this: applications should NOT require it.  In
    particular, most network filesystems won't support it.

   INPUTS
    notifystructure - A filled-in NotifyRequest structure

   RESULT
    success - Success/failure of request

   BUGS
    The V36 floppy/HD filesystem doesn't actually send notifications.  The
    V36 ram handler (ram:) does.  This has been fixed for V37.

   SEE ALSO
    EndNotify(), <dos/notify.h>

 dos.library/StrToDate                                   dos.library/StrToDate

   NAME
    StrToDate -- Converts a string to a DateStamp (V36)

   SYNOPSIS
    success = StrToDate( datetime )
    D0                      D1

    BOOL StrToDate( struct DateTime * )

   FUNCTION
    Converts a human readable ASCII string into an AmigaDOS
    DateStamp.

   INPUTS
    DateTime - a pointer to an initialized DateTime structure.

    The DateTime structure should	be initialized as follows:

    dat_Stamp  - ignored on input.

    dat_Format - a format	byte which specifies the format	of the
        dat_StrDat.  This can	be any of the following	(note:
        If value used	is something other than	those below,
        the default of FORMAT_DOS is used):

        FORMAT_DOS:	  AmigaDOS format (dd-mmm-yy).

        FORMAT_INT:	  International	format (yy-mmm-dd).

        FORMAT_USA:	  American format (mm-dd-yy).

        FORMAT_CDN:	  Canadian format (dd-mm-yy).

        FORMAT_DEF:	  default format for locale.

    dat_Flags - a flags byte.  The only flag which affects this
          function is:

        DTF_SUBST:	ignored by this function
        DTF_FUTURE:	  If set, indicates that strings such
                  as (stored in	dat_StrDate) "Monday"
                  refer	to "next" monday. Otherwise,
                  if clear, strings like "Monday"
                  refer	to "last" monday.

    dat_StrDay - ignored bythis function.

    dat_StrDate -	pointer	to valid string	representing the date.
          This can be a	"DTF_SUBST" style string such as
          "Today" "Tomorrow" "Monday", or it may be a string
          as specified by the dat_Format byte.	This will be
          converted to the ds_Days portion of the DateStamp.
          If this pointer is NULL, DateStamp->ds_Days will not
          be affected.

    dat_StrTime -	Pointer	to a buffer which contains the time in
          the ASCII format hh:mm:ss.  This will	be converted
          to the ds_Minutes and	ds_Ticks portions of the
          DateStamp.  If this pointer is NULL, ds_Minutes and
          ds_Ticks will	be unchanged.

   RESULT
    success	- a zero return indicates that a conversion could
        not be performed. A non-zero return indicates that the
        DateTime.dat_Stamp variable contains the converted
        values.

   SEE ALSO
    DateStamp(), DateToStr(), <dos/datetime.h>

 dos.library/StrToLong                                   dos.library/StrToLong

   NAME
    StrToLong -- string to long value (decimal) (V36)

   SYNOPSIS
    characters = StrToLong(string,value)
    D0                       D1    D2

    LONG StrToLong(STRPTR, LONG *)

   FUNCTION
    Converts decimal string into LONG value.  Returns number of characters
    converted.  Skips over leading spaces & tabs (included in count).  If
    no decimal digits are found (after skipping leading spaces & tabs),
    StrToLong returns -1 for characters converted, and puts 0 into value.

   INPUTS
    string - Input string.
    value  - Pointer to long value.  Set to 0 if no digits are converted.

   RESULT
    result - Number of characters converted or -1.

 dos.library/SystemTagList                           dos.library/SystemTagList

   NAME
    SystemTagList -- Have a shell execute a command line (V36)

   SYNOPSIS
    error = SystemTagList(command, tags)
    D0		        D1      D2

    LONG SystemTagList(STRPTR, struct TagItem *)

    error = System(command, tags)
    D0		 D1      D2

    LONG System(STRPTR, struct TagItem *)

    error = SystemTags(command, Tag1, ...)

    LONG SystemTags(STRPTR, ULONG, ...)

   FUNCTION
    Similar to Execute(), but does not read commands from the input
    filehandle.  Spawns a Shell process to execute the command, and
    returns the returncode the command produced, or -1 if the command
    could not be run for any reason.  The input and output filehandles
    will not be closed by System, you must close them (if needed) after
    System returns, if you specified them via SYS_INPUT or SYS_OUTPUT.

    By default the new process will use your current Input() and Output()
    filehandles.  Normal Shell command-line parsing will be done
    including redirection on 'command'.  The current directory and path
    will be inherited from your process.  Your path will be used to find
    the command (if no path is specified).

    If used with the SYS_Asynch flag, it WILL close both it's input and
    output filehandles after running the command (even if these were
    your Input() and Output()!)

    Normally uses the boot (ROM) shell, but other shells can be specified
    via SYS_UserShell and SYS_CustomShell.  Normally, you should send
    things written by the user to the UserShell.  The UserShell defaults
    to the same shell as the boot shell.

    The tags are passed through to CreateNewProc() (tags that conflict
    with SystemTagList() will be filtered out).  This allows setting
    things like priority, etc for the new process.

   INPUTS
    command - Program and arguments
    tags    - see <dos/dostags.h>.  Note that both SystemTagList()-
          specific tags and tags from CreateNewProc() may be passed.

   RESULT
    error	- 0 for success, result from command, or -1.  Note that on
          error, the caller is responsible for any filehandles or other
          things passed in via tags.

   SEE ALSO
    Execute(), CreateNewProc(), <dos/dostags.h>, Input(), Output()

 dos.library/UnGetC                                         dos.library/UnGetC

   NAME
    UnGetC -- Makes a char available for reading again. (buffered) (V36)

   SYNOPSIS
    value = UnGetC(fh, character)
    D0	       D1      D2

    LONG UnGetC(BPTR, LONG)

   FUNCTION
    Pushes the character specified back into the input buffer.  Every
    time you use a buffered read routine, you can always push back 1
    character.  You may be able to push back more, though it is not
    recommended, since there is no guarantee on how many can be
    pushed back at a given moment.

    Passing -1 for the character will cause the last character read to
    be pushed back.  If the last character read was an EOF, the next
    character read will be an EOF.

    Note: UnGetC can be used to make sure that a filehandle is set up
    as a read filehandle.  This is only of importance if you are writing
    a shell, and must manipulate the filehandle's buffer.

   INPUTS
    fh	  - filehandle to use for buffered I/O
    character - character to push back or -1

   RESULT
    value     - character pushed back, or FALSE if the character cannot
            be pushed back.

   BUGS
    In V36, UnGetC(fh,-1) after an EOF would not cause the next character
    read to be an EOF.  This was fixed for V37.

   SEE ALSO
    FGetC(), FPutC(), Flush()

 dos.library/UnLoadSeg                                   dos.library/UnLoadSeg

    NAME
    UnLoadSeg -- Unload a seglist previously loaded by LoadSeg()

    SYNOPSIS
    success = UnLoadSeg( seglist )
    D0		       D1

    BOOL UnLoadSeg(BPTR)

    FUNCTION
    Unload a seglist loaded by LoadSeg().  'seglist' may be zero.
    Overlaid segments will have all needed cleanup done, including
    closing files.

    INPUTS
    seglist - BCPL pointer to a segment identifier

    RESULTS
    success - returns 0 if a NULL seglist was passed or if it failed
          to close an overlay file.  NOTE: this function returned
          a random value before V36!

    SEE ALSO
    LoadSeg(), InternalLoadSeg(), InternalUnLoadSeg()

 dos.library/UnLock                                         dos.library/UnLock

    NAME
    UnLock -- Unlock a directory or file

    SYNOPSIS
    UnLock( lock )
        D1

    void UnLock(BPTR)

    FUNCTION
    The filing system lock (obtained from Lock(), DupLock(), or
    CreateDir()) is removed and deallocated.

    INPUTS
    lock - BCPL pointer to a lock

    NOTE
    passing zero to UnLock() is harmless

    SEE ALSO
    Lock(), DupLock(), ParentOfFH(), DupLockFromFH()

 dos.library/UnLockDosList                           dos.library/UnLockDosList

   NAME
    UnLockDosList -- Unlocks the Dos List (V36)

   SYNOPSIS
    UnLockDosList(flags)
            D1

    void UnLockDosList(ULONG)

   FUNCTION
    Unlocks the access on the Dos Device List.  You MUST pass the same
    flags you used to lock the list.

   INPUTS
    flags - MUST be the same flags passed to (Attempt)LockDosList()

   SEE ALSO
    AttemptLockDosList(), LockDosList(), Permit()

 dos.library/UnLockRecord                             dos.library/UnLockRecord

   NAME
    UnLockRecord -- Unlock a record (V36)

   SYNOPSIS
    success = UnLockRecord(fh,offset,length)
    D0		       D1   D2     D3

    BOOL UnLockRecord(BPTR,ULONG,ULONG)

   FUNCTION
    This releases the specified lock on a file.  Note that you must use
    the same filehandle you used to lock the record, and offset and length
    must be the same values used to lock it.  Every LockRecord() call must
    be balanced with an UnLockRecord() call.

   INPUTS
    fh      - File handle of locked file
    offset  - Record start position
    length  - Length of record in bytes

   RESULT
    success - Success or failure.

   BUGS
    See LockRecord()

   SEE ALSO
    LockRecords(), LockRecord(), UnLockRecords()

 dos.library/UnLockRecords                           dos.library/UnLockRecords

   NAME
    UnLockRecords -- Unlock a list of records (V36)

   SYNOPSIS
    success = UnLockRecords(record_array)
    D0		             D1

    BOOL UnLockRecords(struct RecordLock *)

   FUNCTION
    This releases an array of record locks obtained using LockRecords.
    You should NOT modify the record_array while you have the records
    locked.  Every LockRecords() call must be balanced with an
    UnLockRecords() call.

   INPUTS
    record_array - List of records to be unlocked

   RESULT
    success      - Success or failure.

   BUGS
    See LockRecord()

   SEE ALSO
    LockRecords(), LockRecord(), UnLockRecord()

 dos.library/VFPrintf                                     dos.library/VFPrintf

   NAME
    VFPrintf -- format and print a string to a file (buffered) (V36)

   SYNOPSIS
    count = VFPrintf(fh, fmt, argv)
    D0               D1  D2    D3

    LONG VFPrintf(BPTR, STRPTR, LONG *)

    count = FPrintf(fh, fmt, ...)

    LONG FPrintf(BPTR, STRPTR, ...)

   FUNCTION
    Writes the formatted string and values to the given file.  This
    routine is assumed to handle all internal buffering so that the
    formatting string and resultant formatted values can be arbitrarily
    long.  Any secondary error code is returned in IoErr().  This routine
    is buffered.

   INPUTS
    fh    - Filehandle to write to
    fmt   - RawDoFmt() style formatting string
    argv  - Pointer to array of formatting values

   RESULT
    count - Number of bytes written or -1 (EOF) for an error

   BUGS
    The prototype for FPrintf() currently forces you to cast the first
    varargs parameter to LONG due to a deficiency in the program
    that generates fds, prototypes, and amiga.lib stubs.

   SEE ALSO
    VPrintf(), VFWritef(), RawDoFmt(), FPutC()

 dos.library/VFWritef                                     dos.library/VFWritef

   NAME
    VFWritef - write a BCPL formatted string to a file (buffered) (V36)

   SYNOPSIS
    count = VFWritef(fh, fmt, argv)
    D0               D1  D2    D3

    LONG VFWritef(BPTR, STRPTR, LONG *)

    count = FWritef(fh, fmt, ...)

    LONG FWritef(BPTR, STRPTR, ...)

   FUNCTION
    Writes the formatted string and values to the default output.  This
    routine is assumed to handle all internal buffering so that the
    formatting string and resultant formatted values can be arbitrarily
    long.  The formats are in BCPL form.  This routine is buffered.

    Supported formats are:  (Note x is in base 36!)
        %S  - string (CSTR)
        %Tx - writes a left-justified string in a field at least
              x bytes long.
        %C  - writes a single character
        %Ox - writes a number in octal, maximum x characters wide
        %Xx - writes a number in hex, maximum x characters wide
        %Ix - writes a number in decimal, maximum x characters wide
        %N  - writes a number in decimal, any length
        %Ux - writes an unsigned number, maximum x characters wide
        %$  - ignore parameter

    Note: 'x' above is actually the character value - '0'.

   INPUTS
    fmt   - BCPL style formatting string
    argv  - Pointer to array of formatting values

   RESULT
    count - Number of bytes written or -1 for error

   BUGS
    As of V37, VFWritef() does NOT return a valid return value.  In
    order to reduce possible errors, the prototypes supplied for the
    system as of V37 have it typed as VOID.

   SEE ALSO
    VFPrintf(), VFPrintf(), FPutC()

 dos.library/VPrintf                                       dos.library/VPrintf

   NAME
    VPrintf -- format and print string (buffered) (V36)

   SYNOPSIS
    count = VPrintf(fmt, argv)
      D0            D1   D2

    LONG VPrintf(STRPTR, LONG *)

    count = Printf(fmt, ...)

    LONG Printf(STRPTR, ...)

   FUNCTION
    Writes the formatted string and values to Output().  This routine is
    assumed to handle all internal buffering so that the formatting string
    and resultant formatted values can be arbitrarily long.  Any secondary
    error code is returned in IoErr().  This routine is buffered.

    Note: RawDoFmt assumes 16 bit ints, so you will usually need 'l's in
    your formats (ex: %ld versus %d).

   INPUTS
    fmt   - exec.library RawDoFmt() style formatting string
    argv  - Pointer to array of formatting values

   RESULT
    count - Number of bytes written or -1 (EOF) for an error

   BUGS
    The prototype for Printf() currently forces you to cast the first
    varargs parameter to LONG due to a deficiency in the program
    that generates fds, prototypes, and amiga.lib stubs.

   SEE ALSO
    VFPrintf(), VFWritef(), RawDoFmt(), FPutC()

 dos.library/WaitForChar                               dos.library/WaitForChar

    NAME
    WaitForChar -- Determine if chars arrive within a time limit

    SYNOPSIS
    status = WaitForChar( file, timeout )
    D0		      D1    D2

    BOOL WaitForChar(BPTR, LONG)

    FUNCTION
    If a character is available to be read from 'file' within a the
    time (in microseconds) indicated by 'timeout', WaitForChar()
    returns -1 (TRUE). If a character is available, you can use Read()
    to read it.  Note that WaitForChar() is only valid when the I/O
    stream is connected to a virtual terminal device. If a character is
    not available within 'timeout', a 0 (FALSE) is returned.

    BUGS
    Due to a bug in the timer.device in V1.2/V1.3, specifying a timeout
    of zero for WaitForChar() can cause the unreliable timer & floppy
    disk operation.

    INPUTS
    file - BCPL pointer to a file handle
    timeout - integer

    RESULTS
    status - boolean

    SEE ALSO
    Read(), FGetC()

 dos.library/WaitPkt                                       dos.library/WaitPkt

   NAME
    WaitPkt -- Waits for a packet to arrive at your pr_MsgPort (V36)

   SYNOPSIS
    packet = WaitPkt()
    D0

    struct DosPacket *WaitPkt(void);

   FUNCTION
    Waits for a packet to arrive at your pr_MsgPort.  If anyone has
    installed a packet wait function in pr_PktWait, it will be called.
    The message will be automatically GetMsg()ed so that it is no longer
    on the port.  It assumes the message is a dos packet.  It is NOT
    guaranteed to clear the signal for the port.

   RESULT
    packet - the packet that arrived at the port (from ln_Name of message).

   SEE ALSO
    SendPkt(), DoPkt(), AbortPkt()

 dos.library/Write                                           dos.library/Write

    NAME
    Write -- Write bytes of data to a file

    SYNOPSIS
    returnedLength =  Write( file, buffer, length )
    D0			 D1    D2      D3

    LONG Write (BPTR, void *, LONG)

    FUNCTION
    Write() writes bytes of data to the opened file 'file'. 'length'
    indicates the length of data to be transferred; 'buffer' is a
    pointer to the buffer. The value returned is the length of
    information actually written. So, when 'length' is greater than
    zero, the value of 'length' is the number of characters written.
    Errors are indicated by a value of -1.

    Note: this is an unbuffered routine (the request is passed directly
    to the filesystem.)  Buffered I/O is more efficient for small
    reads and writes; see FPutC().

    INPUTS
    file - BCPL pointer to a file handle
    buffer - pointer to the buffer
    length - integer

    RESULTS
    returnedLength - integer

    SEE ALSO
    Read(), Seek(), Open(), Close(), FPutC

 dos.library/WriteChars                                 dos.library/WriteChars

   NAME
    WriteChars -- Writes bytes to the the default output (buffered) (V36)

   SYNOPSIS
    count = WriteChars(buf, buflen)
    D0                 D1

    LONG WriteChars(STRPTR, LONG)

   FUNCTION
    This routine writes a number of bytes to the default output.  The
    length is returned.  This routine is buffered.

   INPUTS
    buf    - buffer of characters to write
    buflen - number of characters to write

   RESULT
    count - Number of bytes written.  -1 (EOF) indicates an error

   SEE ALSO
    FPuts(), FPutC(), FWrite(), PutStr()


Text_Autodocs/keymap.doc

TABLE OF CONTENTS

keymap.library/AskKeyMapDefault
keymap.library/MapANSI
keymap.library/MapRawKey
keymap.library/SetKeyMapDefault
 keymap.library/AskKeyMapDefault               keymap.library/AskKeyMapDefault

   NAME
    AskKeyMapDefault -- Ask for a pointer to the current default
                        keymap. (V36)

   SYNOPSIS
    keyMap = AskKeyMapDefault()

    struct KeyMap *AskKeyMapDefault( VOID );

   FUNCTION
    Return a pointer to the keymap used by the keymap library for
    MapRawKey and MapANSI when a keymap is not specified.

   RESULTS
    keyMap - a pointer to a keyMap structure.  This key map is
        guaranteed to be permanently allocated: it will remain in
        memory till the machine is reset.

   BUGS
    The keymap.h include file should be in the libraries/ or perhaps
    resources/ directory, but is in the devices/ directory for
    compatability reasons.

   SEE ALSO
    devices/keymap.h, keymap.library/SetKeyMapDefault(),
    console.device ...KEYMAP functions

 keymap.library/MapANSI                                 keymap.library/MapANSI

   NAME
    MapANSI -- Encode an ANSI string into keycodes. (V36)

   SYNOPSIS
    actual = MapANSI( string, count, buffer, length, keyMap )
    D0                A0      D0     A1      D1      A2

    LONG MapANSI( STRPTR, LONG, STRPTR, LONG, struct KeyMap * );

   FUNCTION
    This console function converts an ANSI byte string to the
    code/qualifier pairs of type IECLASS_RAWKEY that would
    generate the string and places those pairs in a buffer.
    A code/qualifier pair is a pair of bytes suitable for
    putting in the ie_Code and low byte of ie_Qualifier,
    and for subsequent events, shifted to the ie_Prev1DownCode/
    ie_Prev1DownQual then ie_Prev2DownCode/ie_Prev2DownQual
    pairs for any dead or double dead key mapping.

   INPUTS
    string - the ANSI string to convert.
    count - the number of characters in the string.
    buffer - a byte buffer large enough to hold all anticipated
        code/qualifier pairs generated by this conversion.
    length - maximum anticipation, i.e. the buffer size in bytes
        divided by two (the size of the code/qualifier pair).
    keyMap - a KeyMap structure pointer, or null if the default
        key map is to be used.

   RESULT
    actual - the number of code/qualifier pairs in the buffer,
        or negative to describe an error (see below).

   EXAMPLE
    ...
    #include <devices/inputevent.h>

    #define	STIMSIZE	3	/* two dead keys, one key */
    unsigned char rBuffer[STIMSIZE*2];
    ...
        KeymapBase = (struct Library *) OpenLibrary("keymap.library", 0);
        ...
        event.ie_NextEvent = 0;
        event.ie_Class = IECLASS_RAWKEY;
        event.ie_SubClass = 0;

        /* prove keymap code completeness and MapANSI reversibility */
        for (code = 0; code < 256; code++) {
        buffer[0] = code;
        actual = MapANSI(buffer, 1, rBuffer, STIMSIZE, 0);
        r = rBuffer;
        event.ie_Prev2DownCode = 0;
        event.ie_Prev2DownQual = 0;
        event.ie_Prev1DownCode = 0;
        event.ie_Prev1DownQual = 0;
        switch (actual) {
            case -2:
            printf("MapANSI internal error");
            goto reportChar;
            case -1:
            printf("MapANSI overflow error");
            goto reportChar;
            case 0:
            printf("MapANSI ungeneratable code");
            goto reportChar;

            case 3:
            event.ie_Prev2DownCode = *r++;
            event.ie_Prev2DownQual = *r++;
            case 2:
            event.ie_Prev1DownCode = *r++;
            event.ie_Prev1DownQual = *r++;
            case 1:
            event.ie_Code = *r++;
            event.ie_Qualifier = *r;

            actual = MapRawKey(&event, buffer, BUFFERLEN, 0);
            if ((actual != 1) || (buffer[0] != code)) {
                printf("MapANSI not reversible");
                for (i = 0; i < actual; i++)
                ReportChar(buffer[i]);
                printf(" from");
    reportChar:
                ReportChar(code);
                printf("\n");
            }
        }
        }
    ...

   ERRORS
    if actual is 0, a character in the string was not generatable
        from the keyMap.
    if actual is -1, a buffer overflow condition was detected.
    if actual is -2, an internal error occurred (e.g. no memory)

   SEE ALSO
    devices/inputevent.h, devices/keymap.h

 keymap.library/MapRawKey                             keymap.library/MapRawKey

   NAME
    MapRawKey -- Decode single raw key input event to an ANSI
                 string. (V36)

   SYNOPSIS
    actual = MapRawKey(event, buffer, length, keyMap)
    D0                 A0     A1      D1      A2

    WORD MapRawKey( struct InputEvent *, STRPTR, WORD,
        struct Keymap * );

   FUNCTION
    This console function converts input events of type
    IECLASS_RAWKEY to ANSI bytes, based on the keyMap, and
    places the result into the buffer.

   INPUTS
    event -  an InputEvent structure pointer.  The event list is
        not traversed.
    buffer - a byte buffer large enough to hold all anticipated
        characters generated by this conversion.
    length - maximum anticipation, i.e. the buffer size in bytes.
    keyMap - a KeyMap structure pointer, or null if the default
        key map is to be used.

   RESULT
    actual - the number of characters in the buffer, or -1 if
        a buffer overflow was about to occur.

   EXAMPLE
    ...
    #define	BUFFERLEN	80	/* length of longest expected mapping /*
    char buffer[BUFFERLEN];
    struct InputEvent ie;
    ...
        KeymapBase = OpenLibrary("keymap.library", 0);
        ...
        ie.ie_Class = IECLASS_RAWKEY;
        ie.ie_SubClass = 0;
        for (;;) {
        WaitPort(window->UserPort);
        while (im = (struct IntuiMessage *) GetMsg(window->UserPort)) {
            switch (im->Class) {
            case RAWKEY:
                ie.ie_Code = im->Code;
                ie.ie_Qualifier = im->Qualifier;
                /* recover dead key codes & qualifiers */
                ie.ie_EventAddress = (APTR *) *im->IAddress;
                actual = MapRawKey(&ie, buffer, BUFFERLEN, 0);
                for (i = 0; i < actual; i++)
                ReportChar(buffer[i]);
                break;
            ...
            }
            ...
        }
        }

   ERRORS
    if actual is -1, a buffer overflow condition was detected.
    Not all of the characters in the buffer are valid.

   SEE ALSO
    devices/inputevent.h, devices/keymap.h

 keymap.library/SetKeyMapDefault               keymap.library/SetKeyMapDefault

   NAME
    SetKeyMapDefault -- Set the current default keymap. (V36)

   SYNOPSIS
    SetKeyMapDefault(keyMap)

    void SetKeyMapDefault( struct KeyMap * );

   FUNCTION
    A pointer to key map specified is cached by the keymap library
    for use by MapRawKey and MapANSI when a keymap is not specified.

   INPUTS
    keyMap - a pointer to a keyMap structure.  This key map must be
        permanently allocated: it must remain in memory till the
        machine is reset.  It is appropriate that this keyMap be a
        node on the keymap.resource list.

   BUGS
    The keymap.h include file should be in the libraries/ or perhaps
    resources/ directory, but is in the devices/ directory for
    compatability reasons.

   SEE ALSO
    devices/keymap.h, keymap.library/AskKeyMapDefault(),
    console.device ...KEYMAP functions


Text_Autodocs/rexxsyslib.doc

TABLE OF CONTENTS

rexxsyslib.library/ClearRexxMsg
rexxsyslib.library/CreateArgstring
rexxsyslib.library/CreateRexxMsg
rexxsyslib.library/DeleteArgstring
rexxsyslib.library/DeleteRexxMsg
rexxsyslib.library/FillRexxMsg
rexxsyslib.library/IsRexxMsg
rexxsyslib.library/LengthArgstring
rexxsyslib.library/LockRexxBase
rexxsyslib.library/UnlockRexxBase
 rexxsyslib.library/ClearRexxMsg               rexxsyslib.library/ClearRexxMsg

    NAME
    ClearRexxMsg - Releases and clears the argument array in a RexxMsg

    SYNOPSIS
    ClearRexxMsg(msgptr, count)
                 A0      D0

    VOID ClearRexxMsg(struct RexxMsg *,ULONG);

    FUNCTION
    This function will DeleteArgstring() one or more argstrings from
    the RexxMsg and clear the slot.  The count is used to select the
    number of slots to clear.

    INPUTS
    msgptr - A pointer to a RexxMsg
    count - The number of slots to be cleared.  The number can be from
            1 to 16.  (There are 16 slots)

    RESULTS
    All of the slots in the given count will be cleared and the argstring
    will have been released.

    SEE ALSO
    FillRexxMsg(), DeleteRexxMsg(), DeleteArgstring(), CreateArgstring()

    BUGS
 rexxsyslib.library/CreateArgstring         rexxsyslib.library/CreateArgstring

    NAME
    CreateArgstring - Create an argument string structure

    SYNOPSIS
    argstr = CreateArgstring(string, length)
    D0,A0                    A0      D0

    UBYTE *CreateArgstring(UBYTE *, ULONG);

    FUNCTION
    Allocates a RexxArg structure and copies the supplied string into it.
    The returned pointer points at the string part of the structure
    and can be treated like an ordinary string pointer.  (However, care
    must be taken that you do not change the string)

    INPUTS
    string - A pointer at your input string
    length - The number of bytes of your input string you wish copied.
             (NOTE:  You are limited to 65,535 byte strings)

    RESULTS
    argstr - A pointer to the argument string.  The results are returned
             in both A0 and D0.  You should always check the result
             as an allocation failure would cause an error.

    SEE ALSO
    DeleteArgstring(), LengthArgstring(), ClearRexxMsg(), FillRexxMsg()

    BUGS
 rexxsyslib.library/CreateRexxMsg             rexxsyslib.library/CreateRexxMsg

    NAME
    CreateRexxMsg - Create an ARexx message structure

    SYNOPSIS
    rexxmsg = CreateRexxMsg(port, extension, host)
    D0,A0                   A0    A1         D0

    struct RexxMsg *CreateRexxMsg(struct MsgPort *, UBYTE *, UBYTE *);

    FUNCTION
    This functions allocates an ARexx message packet.  The RexxMsg
    consists of a standard EXEC message structure extended to include
    the ARexx specific information.

    INPUTS
    port - A pointer to a public or private message port.  This *MUST*
           be a valid port as this is where the message will be replied.

    extension - A pointer to a NULL terminated string that is to be used
                as the default extension for the REXX scripts.  If this
                is NULL, the default is "REXX"

    host - A pointer to a NULL terminated string that is to be used
           as the default host port.  The name must be the same as the
           name of the public message port that is to be the default host.
           If this field is NULL, the default is REXX.

    RESULTS
    rexxmsg - A RexxMsg structure

    NOTES
    The extension and host strings must remain valid for as long as the
    RexxMsg exists as only the pointer to those strings are stored.

    SEE ALSO
    DeleteRexxMsg(), ClearRexxMsg(), FillRexxMsg()

    BUGS
 rexxsyslib.library/DeleteArgstring         rexxsyslib.library/DeleteArgstring

    NAME
    DeleteArgstring - Releases an Argstring created by CreateArgstring()

    SYNOPSIS
    DeleteArgstring(argstring)
                    A0

    VOID DeleteArgstring(UBYTE *);

    FUNCTION
    Releases an argstring.  The argstring must have been created by ARexx

    INPUTS
    argstring - A pointer to the string buffer of an argstring.

    RESULTS

    SEE ALSO
    CreateArgstring(), ClearRexxMsg(), FillRexxMsg()

    BUGS
 rexxsyslib.library/DeleteRexxMsg             rexxsyslib.library/DeleteRexxMsg

    NAME
    DeleteRexxMsg - Releases a RexxMsg structure created by CreateRexxMsg()

    SYNOPSIS
    DeleteRexxMsg(packet)
                  A0

    VOID DeleteRexxMsg(struct RexxMsg *);

    FUNCTION
    The function releases an ARexx message packet that was allocated
    with CreateRexxMsg().  Any argument fields in the RexxMsg structure
    should be cleared before calling this function as it does
    not release them for you.

    INPUTS
    packet - A pointer to a RexxMsg structure allocated by CreateRexxMsg()

    EXAMPLE
    if (rmsg=CreateRexxMsg(myport,"myapp","MYAPP_PORT"))
    {
        /* Do my think with rmsg */
        ClearRexxMsg(rmsg,16);	/* We may not want to clear all 16 */
        DeleteRexxMsg(rmsg);
    }

    SEE ALSO
    CreateRexxMsg(), ClearRexxMsg()

    BUGS
 rexxsyslib.library/FillRexxMsg                 rexxsyslib.library/FillRexxMsg

    NAME
    FillRexxMsg - Fill the argument strings as needed

    SYNOPSIS
    result = FillRexxMsg(msgptr, count, mask)
    D0                   A0      D0     D1 [0:15]

    BOOL FillRexxMsg(struct RexxMsg *,ULONG,ULONG);

    FUNCTION
    This function will convert and install up to 16 argument strings into
    a RexxMsg structure.  The message packet's argument fields must be
    set to either a pointer to a NULL terminated string or an integer value
    The mask, bits 0 to 15, correspond to the type of value is stored
    in the argument slot.  If the bit is cleared, the argument is a
    string pointer; if the bit is set, the argument is an integer.

    INPUTS
    msgptr - Pointer to a RexxMsg (allocated via CreateRexxMsg)
    count - The number of argument slots to fill in.  This number should
            be from 1 to 16.

    mask - A bit mask corresponding to the 16 fields that is used to
           determine the type of the field.

    RESULTS
    result - A boolean.  If it is TRUE, the call worked.  If it is false,
             some allocation did not work.  All argstrings that were
             created will be released.

    SEE ALSO
    ClearRexxMsg(), CreateArgstring(), DeleteArgstring(), CreateRexxMsg()

    BUGS
 rexxsyslib.library/IsRexxMsg                     rexxsyslib.library/IsRexxMsg

    NAME
    IsRexxMsg - Function to determine if a message came from ARexx

    SYNOPSIS
    result = IsRexxMsg(msgptr)
    D0                 A0

    BOOL IsRexxMsg(struct RexxMsg *);

    FUNCTION
    This function can be used to determine if a message came from an
    ARexx program.

    INPUTS
    msgptr - A pointer to the suspected RexxMsg.

    RESULTS
    result - A boolean:  TRUE if it is an ARexx message, FALSE if not.

    SEE ALSO
    CreateRexxMsg()

    BUGS
 rexxsyslib.library/LengthArgstring         rexxsyslib.library/LengthArgstring

    NAME
    LengthArgstring - Returns the length value stored in the argstring

    SYNOPSIS
    length = LengthArgstring(argstring)
    D0                       A0

    ULONG LengthArgstring(UBYTE *);

    FUNCTION
    This function returns the length value stored in the argstring.
    This is *NOT* the same as doing a strlen() type call on the
    argstring.  (Note that argstrings may contain NULLs)

    INPUTS
    argstring - A pointer to an argstring that was created by ARexx

    RESULTS
    length - The length of the argstring.

    EXAMPLE

    SEE ALSO
    CreateArgstring()

    BUGS
 rexxsyslib.library/LockRexxBase               rexxsyslib.library/LockRexxBase

    NAME
    LockRexxBase - Obtain a semaphore lock on the RexxBase structure

    SYNOPSIS
    LockRexxBase(resource)
                 D0

    VOID LockRexxBase(ULONG);

    FUNCTION
    Secures the specified resource in the ARexx library base.

    INPUTS
    resource - A manifest constant defining which resource to lock.
               ZERO locks all resources.

    NOTES
    Currently, only ZERO resource type is available.  You *MUST* make
    sure that you do not call this function with an undefined value
    as it may become defined at some future date and cause unwanted
    behavior.

    SEE ALSO
    UnlockRexxBase()

    BUGS
 rexxsyslib.library/UnlockRexxBase           rexxsyslib.library/UnlockRexxBase

    NAME
    UnlockRexxBase - Release a semaphore lock on the RexxBase structure

    SYNOPSIS
    UnlockRexxBase(resource)
                   D0

    VOID UnlockRexxBase(ULONG);

    FUNCTION
    Releases the specified resource in the ARexx library base.

    INPUTS
    resource - A manifest constant defining which resource to unlock.
               This value *MUST* match the value used in the matching
               LockRexxBase() call.

    NOTES
    Currently, only ZERO resource type is available.  You *MUST* make
    sure that you do not call this function with an undefined value
    as it may become defined at some future date and cause unwanted
    behavior.  You *MUST* make sure that you only call this function
    after a matching call to LockRexxBase() was made.

    SEE ALSO
    LockRexxBase()

    BUGS


Text_Autodocs/exec.doc

TABLE OF CONTENTS

exec.library/AbortIO
exec.library/AddDevice
exec.library/AddHead
exec.library/AddIntServer
exec.library/AddLibrary
exec.library/AddMemList
exec.library/AddPort
exec.library/AddResource
exec.library/AddSemaphore
exec.library/AddTail
exec.library/AddTask
exec.library/Alert
exec.library/AllocAbs
exec.library/Allocate
exec.library/AllocEntry
exec.library/AllocMem
exec.library/AllocSignal
exec.library/AllocTrap
exec.library/AllocVec
exec.library/AttemptSemaphore
exec.library/AvailMem
exec.library/CacheClearE
exec.library/CacheClearU
exec.library/CacheControl
exec.library/CachePostDMA
exec.library/CachePreDMA
exec.library/Cause
exec.library/CheckIO
exec.library/CloseDevice
exec.library/CloseLibrary
exec.library/ColdReboot
exec.library/CopyMem
exec.library/CopyMemQuick
exec.library/CreateIORequest
exec.library/CreateMsgPort
exec.library/Deallocate
exec.library/Debug
exec.library/DeleteIORequest
exec.library/DeleteMsgPort
exec.library/Disable
exec.library/DoIO
exec.library/Enable
exec.library/Enqueue
exec.library/FindName
exec.library/FindPort
exec.library/FindResident
exec.library/FindSemaphore
exec.library/FindTask
exec.library/Forbid
exec.library/FreeEntry
exec.library/FreeMem
exec.library/FreeSignal
exec.library/FreeTrap
exec.library/FreeVec
exec.library/GetCC
exec.library/GetMsg
exec.library/InitCode
exec.library/InitResident
exec.library/InitSemaphore
exec.library/InitStruct
exec.library/Insert
exec.library/MakeFunctions
exec.library/MakeLibrary
exec.library/ObtainSemaphore
exec.library/ObtainSemaphoreList
exec.library/ObtainSemaphoreShared
exec.library/OldOpenLibrary
exec.library/OpenDevice
exec.library/OpenLibrary
exec.library/OpenResource
exec.library/Permit
exec.library/Procure
exec.library/PutMsg
exec.library/RawDoFmt
exec.library/ReleaseSemaphore
exec.library/ReleaseSemaphoreList
exec.library/RemDevice
exec.library/RemHead
exec.library/RemIntServer
exec.library/RemLibrary
exec.library/Remove
exec.library/RemPort
exec.library/RemResource
exec.library/RemSemaphore
exec.library/RemTail
exec.library/RemTask
exec.library/ReplyMsg
exec.library/SendIO
exec.library/SetExcept
exec.library/SetFunction
exec.library/SetIntVector
exec.library/SetSignal
exec.library/SetSR
exec.library/SetTaskPri
exec.library/Signal
exec.library/StackSwap
exec.library/SumKickData
exec.library/SumLibrary
exec.library/SuperState
exec.library/Supervisor
exec.library/TypeOfMem
exec.library/UserState
exec.library/Vacate
exec.library/Wait
exec.library/WaitIO
exec.library/WaitPort
 exec.library/AbortIO                                     exec.library/AbortIO

   NAME
    AbortIO - attempt to abort an in-progress I/O request

   SYNOPSIS
    AbortIO(iORequest)
            A1

    VOID AbortIO(struct IORequest *);

   FUNCTION
    Ask a device to abort a previously started IORequest.  This is done
    by calling the device's ABORTIO vector, with your given IORequest.

    AbortIO is a command the device that may or may not grant.  If
    successful, the device will stop processing the IORequest, and
    reply to it earlier than it would otherwise have done.

   NOTE
    AbortIO() does NOT Remove() the IORequest from your ReplyPort, OR
    wait for it to complete.  After an AbortIO() you must wait normally
    for the reply message before actually reusing the request.

    If a request has already completed when AbortIO() is called, no
    action is taken.

   EXAMPLE
        AbortIO(timer_request);
        WaitIO(timer_request);
        /* Message is free to be reused */

   INPUTS
    iORequest - pointer to an I/O request block (must have been used
        at least once.  May be active or finished).

   SEE ALSO
    WaitIO, DoIO, SendIO, CheckIO

 exec.library/AddDevice                                 exec.library/AddDevice

   NAME
    AddDevice -- add a device to the system

   SYNOPSIS
    AddDevice(device)
          A1

    void AddDevice(struct Device *);

   FUNCTION
    This function adds a new device to the system device list, making
    it available to other programs.  The device must be ready to be
    opened at this time.

   INPUTS
    device - pointer to a properly initialized device node

   SEE ALSO
    RemDevice, OpenDevice, CloseDevice, MakeLibrary

 exec.library/AddHead                                     exec.library/AddHead

   NAME
    AddHead -- insert node at the head of a list

   SYNOPSIS
    AddHead(list, node)
        A0    A1

    void AddHead(struct List *, struct Node *)

   FUNCTION
    Add a node to the head of a doubly linked list. Assembly
    programmers may prefer to use the ADDHEAD macro from
    "exec/lists.i".

   WARNING
    This function does not arbitrate for access to the list.  The
    calling task must be the owner of the involved list.

   INPUTS
    list - a pointer to the target list header
    node - the node to insert at head

   SEE ALSO
    AddTail, Enqueue, Insert, Remove, RemHead, RemTail

 exec.library/AddIntServer                           exec.library/AddIntServer

   NAME
    AddIntServer -- add an interrupt server to a system server chain

   SYNOPSIS
    AddIntServer(intNum, interrupt)
             D0-0:4  A1

    void AddIntServer(ULONG, struct Interrupt *);

   FUNCTION
    This function adds a new interrupt server to a given server chain.
    The node is located on the chain in a priority dependent position.
    If this is the first server on a particular chain, interrupts will
    be enabled for that chain.

    Each link in the chain will be called in priority order until the
    chain ends or one of the servers returns with the 68000's Z condition
    code clear (indicating non-zero).  Servers on the chain should return
    with the Z flag clear if the interrupt was specifically for that
    server, and no one else.  VERTB servers should always return Z set.
    (Take care with High Level Language servers, the language may not
    have a mechanism for reliably setting the Z flag on exit).

    Servers are called with the following register conventions:

        D0 - scratch
        D1 - scratch

        A0 - scratch
        A1 - server is_Data pointer (scratch)

        A5 - jump vector register (scratch)
        A6 - scratch

        all other registers must be preserved

   INPUTS
    intNum - the Paula interrupt bit number (0 through 14). Processor
         level seven interrupts (NMI) are encoded as intNum 15.
         The PORTS, COPER, VERTB, EXTER and NMI interrupts are
         set up as server chains.
    interrupt - pointer to an Interrupt structure.
         By convention, the LN_NAME of the interrupt structure must
         point a descriptive string so that other users may
         identify who currently has control of the interrupt.

   WARNING
    Some compilers or assemblers may optimize code in unexpected ways,
    affecting the conditions codes returned from the function.  Watch
    out for a "MOVEM" instruction (which does not affect the condition
    codes) turning into "MOVE" (which does).

   BUGS
    The graphics library's VBLANK server, and some user code, currently
    assume that address register A0 will contain a pointer to the custom
    chips. If you add a server at a priority of 10 or greater, you must
    compensate for this by providing the expected value ($DFF000).

   SEE ALSO
    RemIntServer, SetIntVector, hardware/intbits.i,exec/interrupts.i

 exec.library/AddLibrary                               exec.library/AddLibrary

   NAME
    AddLibrary -- add a library to the system

   SYNOPSIS
    AddLibrary(library)
           A1

    void AddLibrary(struct Library *);

   FUNCTION
    This function adds a new library to the system, making it available
    to other programs.  The library should be ready to be opened at
    this time.  It will be added to the system library name list, and
    the checksum on the library entries will be calculated.

   INPUTS
    library - pointer to a properly initialized library structure

   SEE ALSO
    RemLibrary, CloseLibrary, OpenLibrary, MakeLibrary

 exec.library/AddMemList                               exec.library/AddMemList

   NAME
    AddMemList - add memory to the system free pool

   SYNOPSIS
    AddMemList( size, attributes, pri, base, name )
                     D0      D1        D2   A0    A1

    void AddMemList(ULONG, ULONG, LONG, APTR, STRPTR);

   FUNCTION
    Add a new region of memory to the system free pool.  The first few
    bytes will be used to hold the MemHeader structure.  The remainder
    will be made available to the rest of the world.

   INPUTS
    size - the size (in bytes) of the memory area
    attributes - the attributes word that the memory pool will have
    pri  - the priority for this memory.  CHIP memory has a pri of -10,
           16 bit expansion memory has a priority of 0.  The higher the
           priority, the closer to the head of the memory list it will
           be placed.
    base - the base of the new memory area
    name - the name that will be used in the memory header, or NULL
           if no name is to be provided.  This name is not copied, so it
           must remain valid for as long as the memory header is in the
           system.

   SEE ALSO
    AllocMem, exec/memory.h

 exec.library/AddPort                                     exec.library/AddPort

   NAME
    AddPort -- add a public message port to the system

   SYNOPSIS
    AddPort(port)
        A1

    void AddPort(struct MsgPort *);

   FUNCTION
    This function attaches a message port structure to the system's
    public message port list, where it can be found by the FindPort()
    function.  The name and priority fields of the port structure must
    be initialized prior to calling this function.	If the user does
    not require the priority field, it should be initialized to zero.

    Only ports that will be searched for with FindPort() need to
    be added to the system list.  In addition, adding ports is often
    useful during debugging.  If the port will be searched for,
    the priority field should be at least 1 (to avoid the large number
    of inactive ports at priority zero).  If the port will be searched
    for often, set the proritiry in the 50-100 range (so it will be
    before other less used ports).

    Once a port has been added to the naming list, you must be careful
    to remove the port from the list (via RemPort) before deallocating
    its memory.

   NOTE
    A point of confusion is that clearing a MsgPort structure to all
    zeros is not enough to prepare it for use.  As mentioned in the
    Exec chapter of the ROM Kernel Manual, the List for the MsgPort
    must be initialized.  This is automatically handled by AddPort(),
    and amiga.lib/CreatePort.  This initialization can be done manually
    with amiga.lib/NewList or the assembly NEWLIST macro.

    Do not AddPort an active port.

   INPUTS
    port - pointer to a message port

   SEE ALSO
    RemPort, FindPort, amiga.lib/CreatePort, amiga.lib/NewList

 exec.library/AddResource                             exec.library/AddResource

   NAME
    AddResource -- add a resource to the system

   SYNOPSIS
    AddResource(resource)
            A1

    void AddResource(APTR);

   FUNCTION
    This function adds a new resource to the system and makes it
    available to other users.  The resource must be ready to be called
    at this time.

    Resources currently have no system-imposed structure, however they
    must start with a standard named node (LN_SIZE), and should with
    a standard Library node (LIB_SIZE).

   INPUTS
    resource - pointer an initialized resource node

   SEE ALSO
    RemResource, OpenResource, MakeLibrary

 exec.library/AddSemaphore                           exec.library/AddSemaphore

   NAME
    AddSemaphore -- initialize then add a signal semaphore to the system

   SYNOPSIS
    AddSemaphore(signalSemaphore)
             A1

    void AddSemaphore(struct SignalSemaphore *);

   FUNCTION
    This function attaches a signal semaphore structure to the system's
    public signal semaphore list.  The name and priority fields of the
    semaphore structure must be initialized prior to calling this
    function.  If you do not want to let others rendezvous with this
    semaphore, use InitSemaphore() instead.

    If a semaphore has been added to the naming list, you must be
    careful to remove the semaphore from the list (via RemSemaphore)
    before deallocating its memory.

    Semaphores that are linked together in an allocation list (which
    ObtainSemaphoreList() would use) may not be added to the system
    naming list, because the facilities use the link field of the
    signal semaphore in incompatible ways

   INPUTS
       signalSemaphore -- an signal semaphore structure

   BUGS
    Does not work in Exec <V36.  Instead use this code:

        #include <exec/execbase.h>
        #include <exec/nodes.h>
        extern struct ExecBase *SysBase;
        ...
        void LocalAddSemaphore(s)
        struct SignalSemaphore *s;
        {
        s->ss_Link.ln_Type=NT_SIGNALSEM;
        InitSemaphore(s);
        Forbid();
        Enqueue(&SysBase->SemaphoreList,s);
        Permit();
        }

   SEE ALSO
    RemSemaphore, FindSemaphore, InitSemaphore

 exec.library/AddTail                                     exec.library/AddTail

   NAME
    AddTail -- append node to tail of a list

   SYNOPSIS
    AddTail(list, node)
                A0    A1

    void AddTail(struct List *, struct Node *);

   FUNCTION
    Add a node to the tail of a doubly linked list.  Assembly
    programmers may prefer to use the ADDTAIL macro from
    "exec/lists.i".

   WARNING
    This function does not arbitrate for access to the list.  The
    calling task must be the owner of the involved list.

   INPUTS
    list - a pointer to the target list header
    node - a pointer to the node to insert at tail of the list

   SEE ALSO
    AddHead, Enqueue, Insert, Remove, RemHead, RemTail

 exec.library/AddTask                                     exec.library/AddTask

   NAME
    AddTask -- add a task to the system

   SYNOPSIS
    AddTask(task, initialPC, finalPC)
        A1    A2	 A3

    APTR AddTask(struct Task *, APTR, APTR);

   FUNCTION
    Add a task to the system.  A reschedule will be run; the task with
    the highest priority in the system will start to execute (this may
    or may not be the new task).

    Certain fields of the task control block must be initialized and a
    stack allocated prior to calling this function.  The absolute
    smallest stack that is allowable is something in the range of 100
    bytes, but in general the stack size is dependent on what
    subsystems are called. In general 256 bytes is sufficient if only
    Exec is called, and 4K will do if anything in the system is called.
    DO NOT UNDERESTIMATE.  If you use a stack sniffing utility,
    leave a healthy pad above the minimum value.  The system guarantees
    that its stack operations will leave the stack longword aligned.

    This function will temporarily use space from the new task's stack
    for the task's initial set of registers.  This space is allocated
    starting at the SPREG location specified in the task control block
    (not from SPUPPER).  This means that a task's stack may contain
    static data put there prior to its execution.  This is useful for
    providing initialized global variables or some tasks may want to
    use this space for passing the task its initial arguments.

    A task's initial registers are set to zero (except the PC).

    The TC_MEMENTRY field of the task structure may be extended by
    the user to hold additional MemLists (as returned by AllocEntry()).
    These will be automatically be deallocated at RemTask() time.
    If the code you have used to start the task has already added
    something to the MEMENTRY list, simply use AddHead to add your
    new MemLists in.  If no initialization has been done, a NewList will
    need to be performed.

   INPUTS
    task  - pointer to the task control block (TCB).  All unset fields
        must be zero.
    initialPC - the initial entry point's address
    finalPC - the finalization code entry point's address.  If zero,
          the system will use a general finalizer. This pointer is
          placed on the stack as if it were the outermost return
          address.

   RESULTS
    For V36, AddTask returns either a NULL or the address of the new
    task.  Old code need not check this.

   WARNING
    Tasks are a low-level building block, and are unable to call
    dos.library, or any system function that might call dos.library.
    See the AmigaDOS CreateProc() for information on Processes.

   SEE ALSO
    RemTask, FindTask, amiga.lib/CreateTask, dos/CreateProc,
    amiga.lib/NewList

 exec.library/Alert                                         exec.library/Alert

   NAME
    Alert -- alert the user of an error

   SYNOPSIS
    Alert(alertNum)
          D7

    void Alert(ULONG);

   FUNCTION
    Alerts the user of a serious system problem.  This function will
    bring the system to a grinding halt, and do whatever is necessary
    to present the user with a message stating what happened.
    Interrupts are disabled, and an attempt to post the alert is made.
    If that fails, the system is reset.  When the system comes up
    again, Exec notices the cause of the failure and tries again to
    post the alert.

    If the Alert is a recoverable type, this call MAY return.

    This call may be made at any time, including interrupts.

   POST-MORTEM DIAGNOSIS
    There are several options for determining the cause of a crash.
    Descriptions of each alert number can be found in the "alerts.h"
    include file.  Low numbers not mentioned in the include file
    represent 68000 exceptions, see a 68000 manual for details.  The
    most common numbers are:
            $00000003 - Address Error
            $00000004 - Illegal Instruction

    A remote terminal can be attached to the Amiga's first built-in
    serial port.  Set the communication parameters to 9600 baud, 8 bits,
    no parity.  Before resetting the machine, the Alert function will
    blink the power LED 10 times.  While the power indicator is flashing,
    pressing DELETE on the remote terminal will invoke the ROMWack
    debugger.

    For Alerts caused by a 68000 exception, all registers are copied
    to a magic low memory location (currently 16 longwords at $180).

   INPUT
    alertNum   - a number indicating the particular alert.  -1 is
        not a valid input.

   NOTE
    Much more needs to be said about this function and its implications.

   SEE ALSO
    exec/alerts.h

 exec.library/AllocAbs                                   exec.library/AllocAbs

   NAME
    AllocAbs -- allocate at a given location

   SYNOPSIS
    memoryBlock = AllocAbs(byteSize, location)
    D0		       D0	 A1

    void *AllocAbs(ULONG, APTR);

   FUNCTION
    This function attempts to allocate memory at a given absolute
    memory location.  Often this is used by boot-surviving entities
    such as recoverable ram-disks.	If the memory is already being
    used, or if there is not enough memory to satisfy the request,
    AllocAbs will return NULL.

    This block may not be exactly the same as the requested block
    because of rounding, but if the return value is non-zero, the block
    is guaranteed to contain the requested range.

   INPUTS
    byteSize - the size of the desired block in bytes
           This number is rounded up to the next larger
           block size for the actual allocation.
    location - the address where the memory MUST be.

   RESULT
    memoryBlock - a pointer to the newly allocated memory block, or
              NULL if failed.

   NOTE
    If the free list is corrupt, the system will panic with alert
    AN_MemCorrupt, $01000005.

    The 8 bytes past the end of an AllocAbs will be changed by Exec
    relinking the next block of memory.  Generally you can't trust
    the first 8 bytes of anything you AllocAbs.

   SEE ALSO
    AllocMem, FreeMem

 exec.library/Allocate                                   exec.library/Allocate

   NAME
    Allocate - allocate a block of memory

   SYNOPSIS
    memoryBlock=Allocate(memHeader, byteSize)
    D0		     A0 	D0

    void *Allocate(struct MemHeader *, ULONG);

   FUNCTION
    This function is used to allocate blocks of memory from a given
    private free memory pool (as specified by a MemHeader and its
    memory chunk list).  Allocate will return the first free block that
    is greater than or equal to the requested size.

    All blocks, whether free or allocated, will be block aligned;
    hence, all allocation sizes are rounded up to the next block even
    value (e.g. the minimum allocation resolution is currently 8
    bytes.  A request for 8 bytes will use up exactly 8 bytes.  A
    request for 7 bytes will also use up exactly 8 bytes.).

    This function can be used to manage an application's internal data
    memory.  Note that no arbitration of the MemHeader and associated
    free chunk list is done.  You must be the owner before calling
    Allocate.

   INPUTS
    memHeader - points to the local memory list header.
    byteSize - the size of the desired block in bytes.

   RESULT
    memoryBlock - a pointer to the just allocated free block.
           If there are no free regions large enough to satisfy the
           request, return zero.

   EXAMPLE
    #include <exec/types.h>
    #include <exec/memory.h>
    void *AllocMem();
    #define BLOCKSIZE 4096L /* Or whatever you want */

    void main()
    {
    struct MemHeader *mh;
    struct MemChunk  *mc;
    APTR   block1;
    APTR   block2;

        /* Get the MemHeader needed to keep track of our new block */
        mh = (struct MemHeader *)
         AllocMem((long)sizeof(struct MemHeader), MEMF_CLEAR );
        if( !mh )
        exit(10);

        /* Get the actual block the above MemHeader will manage */
        mc = (struct MemChunk *)AllocMem( BLOCKSIZE, 0L );
        if( !mc )
        {
        FreeMem( mh, (long)sizeof(struct MemHeader) ); exit(10);
        }

        mh->mh_Node.ln_Type = NT_MEMORY;
        mh->mh_Node.ln_Name = "myname";
        mh->mh_First = mc;
        mh->mh_Lower = (APTR) mc;
        mh->mh_Upper = (APTR) ( BLOCKSIZE + (ULONG) mc );
        mh->mh_Free  = BLOCKSIZE;

        /* Set up first chunk in the freelist */
        mc->mc_Next  = NULL;
        mc->mc_Bytes = BLOCKSIZE;

        block1 = (APTR) Allocate( mh, 20L );
        block2 = (APTR) Allocate( mh, 314L );
        printf("mh=$%lx mc=$%lx\n",mh,mc);
        printf("Block1=$%lx, Block2=$%lx\n",block1,block2);

        FreeMem( mh, (long)sizeof(struct MemHeader) );
        FreeMem( mc, BLOCKSIZE );
    }

   NOTE
    If the free list is corrupt, the system will panic with alert
    AN_MemCorrupt, $01000005.

   SEE ALSO
    Deallocate, exec/memory.h

 exec.library/AllocEntry                               exec.library/AllocEntry

   NAME
    AllocEntry -- allocate many regions of memory

   SYNOPSIS
    memList = AllocEntry(memList)
    D0		     A0

    struct MemList *AllocEntry(struct MemList *);

   FUNCTION
    This function takes a memList structure and allocates enough memory
    to hold the required memory as well as a MemList structure to keep
    track of it.

    These MemList structures may be linked together in a task control
    block to keep track of the total memory usage of this task. (See
    the description of TC_MEMENTRY under RemTask).

   INPUTS
    memList -- A MemList structure filled in with MemEntry structures.

   RESULTS
    memList -- A different MemList filled in with the actual memory
        allocated in the me_Addr field, and their sizes in me_Length.
        If enough memory cannot be obtained, then the requirements of
        the allocation that failed is returned and bit 31 is set.

        WARNING: The result is unusual!  Bit 31 indicates faulure.

   EXAMPLES
    The user wants five regions of 2, 4, 8, 16, and 32 bytes in size
    with requirements of MEMF_CLEAR, MEMF_PUBLIC, MEMF_CHIP!MEMF_CLEAR,
    MEMF_CLEAR, and MEMF_PUBLIC!MEMF_CLEAR respectively.  The
    following code fragment would do that:

        MemListDecl:
        DS.B	LN_SIZE 	    * reserve space for list node
        DC.W	5		    * number of entries
        DC.L	MEMF_CLEAR		    * entry #0
        DC.L	2
        DC.L	MEMF_PUBLIC		    * entry #1
        DC.L	4
        DC.L	MEMF_CHIP!MEMF_CLEAR	    * entry #2
        DC.L	8
        DC.L	MEMF_CLEAR	   	    * entry #3
        DC.L	16
        DC.L	MEMF_PUBLIC!MEMF_CLEAR	    * entry #4
        DC.L	32

        start:
        LEA.L	MemListDecl(PC),A0
        JSR	_LVOAllocEntry(a6)
        BCLR.L	#31,D0
        BEQ.S	success

        ------- Type of memory that we failed on is in D0

   BUGS
    If any one of the allocations fails, this function fails to back
    out fully.  This is fixed by the "SetPatch" program on V1.3
    Workbench disks.

   SEE ALSO
    exec/memory.h

 exec.library/AllocMem                                   exec.library/AllocMem

   NAME
    AllocMem -- allocate memory given certain requirements

   SYNOPSIS
    memoryBlock = AllocMem(byteSize, attributes)
    D0		       D0	 D1

    void *AllocMem(ULONG, ULONG);

   FUNCTION
    This is the memory allocator to be used by system code and
    applications.  It provides a means of specifying that the allocation
    should be made in a memory area accessible to the chips, or
    accessible to shared system code.

    Memory is allocated based on requirements and options.	Any
    "requirement" must be met by a memory allocation, any "option" will
    be applied to the block regardless.  AllocMem will try all memory
    spaces until one is found with the proper requirements and room for
    the memory request.

   INPUTS
    byteSize - the size of the desired block in bytes.  (The operating
        system will automatically round this number to a multiple of
        the system memory chunk size)

    attributes -
        requirements

        If no flags are set, the system will return the best
        available memory block.  For expanded systems, the fast
        memory pool is searched first.

        MEMF_CHIP:	If the requested memory will be used by
                the Amiga custom chips, this flag *must*
                be set.

                Only certain parts of memory are reachable
                by the special chip sets' DMA circuitry.
                Chip DMA includes screen memory, images that
                are blitted, audio data, copper lists, sprites
                and Pre-V36 trackdisk.device buffers.

        MEMF_FAST:	This is non-chip memory.  If no flag is set
                MEMF_FAST is taken as the default.

                DO NOT SPECIFY MEMF_FAST unless you know
                exactly what you are doing!  If MEMF_FAST is
                set, AllocMem() will fail on machines that
                only have chip memory!  This flag may not
                be set when MEMF_CHIP is set.

        MEMF_PUBLIC:	Memory that must not be mapped, swapped,
                or otherwise made non-addressable. ALL
                MEMORY THAT IS REFERENCED VIA INTERRUPTS
                AND/OR BY OTHER TASKS MUST BE EITHER PUBLIC
                OR LOCKED INTO MEMORY! This includes both
                code and data.

        MEMF_LOCAL:	This is memory that will not go away
                after the CPU RESET instruction.  Normally,
                autoconfig memory boards become unavailable
                after RESET while motherboard memory
                may still be available.  This memory type
                is now automatically set in V36.  Pre-V36
                systems may not have this memory type
                and AllocMem() will then fail.

        MEMF_24BITDMA:	This is memory that is within the address
                range of 24-bit DMA devices.  (Zorro-II)
                This is required if you run a Zorro-II
                DMA device on a machine that has memory
                beyond the 24-bit addressing limit of
                Zorro-II.  This memory type
                is now automatically set in V36.  Pre-V36
                systems may not have this memory type
                and AllocMem() will then fail.

        options

        MEMF_CLEAR:	The memory will be initialized to all
                zeros.

        MEMF_REVERSE:	This allocates memory from the top of
                the memory pool.  It searches the pools
                in the same order, such that FAST memory
                will be found first.  However, the
                memory will be allocated from the highest
                address available in the pool.  This
                option is new as of V36.

   RESULT
    memoryBlock - a pointer to the newly allocated memory block.
        If there are no free memory regions large enough to satisfy
        the request, zero will be returned.  The pointer must be
        checked for zero before the memory block may be used!

   WARNING
    The result of any memory allocation MUST be checked, and a viable
    error handling path taken.  ANY allocation may fail if memory has
    been filled.

   EXAMPLES
    AllocMem(64,0L)		- Allocate the best available memory
    AllocMem(25,MEMF_CLEAR) - Allocate the best available memory, and
                  clear it before returning.
    AllocMem(128,MEMF_CHIP) - Allocate chip memory
    AllocMem(128,MEMF_CHIP|MEMF_CLEAR) - Allocate cleared chip memory
    AllocMem(821,MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR) - Allocate cleared,
        public, chip memory.

   NOTE
    If the free list is corrupt, the system will panic with alert
    AN_MemCorrupt, $01000005.

    This function may not be called from interrupts.

    A DOS process will have its pr_Result2 field set to
    ERROR_NO_FREE_STORE if the memory allocation fails.

   SEE ALSO
    FreeMem

 exec.library/AllocSignal                             exec.library/AllocSignal

   NAME
    AllocSignal -- allocate a signal bit

   SYNOPSIS
    signalNum = AllocSignal(signalNum)
    D0			D0

    BYTE AllocSignal(BYTE);

   FUNCTION
    Allocate a signal bit from the current tasks' pool.  Either a
    particular bit, or the next free bit may be allocated.	The signal
    associated with the bit will be properly initialized (cleared).  At
    least 16 user signals are available per task.  Signals should be
    deallocated before the task exits.

    If the signal is already in use (or no free signals are available)
    a -1 is returned.

    Allocated signals are only valid for use with the task that
    allocated them.

   WARNING
    Signals may not be allocated or freed from exception handling code.

   INPUTS
    signalNum - the desired signal number {of 0..31} or -1 for no
            preference.

   RESULTS
    signalNum - the signal bit number allocated {0..31}. If no signals
            are available, this function returns -1.

   SEE ALSO
    FreeSignal

 exec.library/AllocTrap                                 exec.library/AllocTrap

   NAME
    AllocTrap -- allocate a processor trap vector

   SYNOPSIS
    trapNum = AllocTrap(trapNum)
    D0		    D0

    LONG AllocTrap(LONG);

   FUNCTION
    Allocate a trap number from the current task's pool.  These trap
    numbers are those associated with the 68000 TRAP type instructions.
    Either a particular number, or the next free number may be
    allocated.

    If the trap is already in use (or no free traps are available) a -1
    is returned.

    This function only affects the currently running task.

    Traps are sent to the trap handler pointed at by tc_TrapCode.
    Unless changed by user code, this points to a standard trap
    handler.  The stack frame of the exception handler will be:

        0(SP) = Exception vector number.  This will be in the
            range of 32 to 47 (corresponding to the
            Trap #1...Trap #15 instructions).
        4(SP) = 68000/68010/68020/68030, etc. exception frame

    tc_TrapData is not used.

   WARNING
    Traps may not be allocated or freed from exception handling code.
    You are not allowed to write to the exception table yourself.  In
    fact, on some machines you will have trouble finding it - the VBR
    register may be used to remap its location.

   INPUTS
    trapNum - the desired trap number {of 0..15} or -1
          for no preference.

   RESULTS
    trapNum - the trap number allocated {of 0..15}.  If no traps are
          available, this function returns -1.	Instructions of the
          form "Trap #trapNum" will be sent to the task's trap
          handler.

   SEE ALSO
    FreeTrap

 exec.library/AllocVec                                   exec.library/AllocVec

   NAME
    AllocVec -- allocate memory and keep track of the size  (V36)

   SYNOPSIS
    memoryBlock = AllocVec(byteSize, attributes)
    D0		       D0	 D1

    void *AllocVec(ULONG, ULONG);

   FUNCTION
    This function works identically to AllocMem(), but tracks the size
    of the allocation.

    See the AllocMem() documentation for details.

   WARNING
    The result of any memory allocation MUST be checked, and a viable
    error handling path taken.  ANY allocation may fail if memory has
    been filled.

   SEE ALSO
    FreeVec, AllocMem

 exec.library/AttemptSemaphore                   exec.library/AttemptSemaphore

   NAME
    AttemptSemaphore -- try to obtain without blocking

   SYNOPSIS
    success = AttemptSemaphore(signalSemaphore)
    D0			   A0

    LONG AttemptSemaphore(struct SignalSemaphore *);

   FUNCTION
    This call is similar to ObtainSemaphore(), except that it will not
    block if the semaphore could not be locked.

   INPUT
       signalSemaphore -- an initialized signal semaphore structure

   RESULT
    success -- TRUE if the semaphore was locked, false if some
        other task already possessed the semaphore.

    NOTE
    This call does NOT preserve registers.

   SEE ALSO
    ObtainSemaphore() ObtainSemaphoreShared(), ReleaseSemaphore(),
    exec/semaphores.h

 exec.library/AvailMem                                   exec.library/AvailMem

   NAME
    AvailMem -- memory available given certain requirements

   SYNOPSIS
    size = AvailMem(attributes)
    D0		D1

    ULONG AvailMem(ULONG);

   FUNCTION
    This function returns the amount of free memory given certain
    attributes.

    To find out what the largest block of a particular type is, add
    MEMF_LARGEST into the requirements argument.  Returning the largest
    block is a slow operation.

   WARNING
    Due to the effect of multitasking, the value returned may not
    actually be the amount of free memory available at that instant.

   INPUTS
    requirements - a requirements mask as specified in AllocMem.  Any
               of the AllocMem bits are valid, as is MEMF_LARGEST
               which returns the size of the largest block matching
               the requirements.

   RESULT
    size - total free space remaining (or the largest free block).

   NOTE
    For V36 Exec, AvailMem(MEMF_LARGEST) does a consistency check on
    the memory list.  Alert AN_MemoryInsane will be pulled if any mismatch
    is noted.

   EXAMPLE
    AvailMem(MEMF_CHIP|MEMF_LARGEST);
    /* return size of largest available chip memory chunk */

   SEE ALSO
    exec/memory.h

 exec.library/CacheClearE                             exec.library/CacheClearE

   NAME
    CacheClearE - Cache clearing with extended control (V37)

   SYNOPSIS
    CacheClearE(address,length,caches)
                a0      d0     d1

    void CacheClearE(APTR,ULONG,ULONG);

   FUNCTION
    Flush out the contents of the CPU instruction and/or data caches.
    If dirty data cache lines are present, push them to memory first.

    Motorola CPUs have separate instruction and data caches.  A data
    write does not update the instruction cache.  If an instruction is
    written to memory or modified, the old instruction may still exist
    in the cache.  Before attempting to execute the code, a flush of
    the instruction cache is required.

    For most systems, the data cache is not updated by Direct Memory
    Access (DMA), or if some external factor changes shared memory.

    Caches must be cleared after *any* operation that could cause
    invalid or stale data.  The most common cases are DMA and modifying
    instructions using the processor.

    Some examples:
            Self modifying code
            Building Jump tables
            Run-time code patches
            Relocating code for use at different addresses.
            Loading code from disk

   INPUTS
    address - Address to start the operation.  This may be rounded
          due to hardware granularity.
    length	- Length of area to be cleared, or $FFFFFFFF to indicate all
          addresses should be cleared.
    caches  - Bit flags to indicate what caches to affect.  The current
          supported flags are:
            CACRF_ClearI	;Clear instruction cache
            CACRF_ClearD	;Clear data cache
          All other bits are reserved for future definition.

   NOTES
    On systems with a copyback mode cache, any dirty data is pushed
    to memory as a part of this operation.

    Regardless of the length given, the function will determine the most
    efficient way to implement the operation.  For some cache systems,
    including the 68030, the overhead partially clearing a cache is often
    too great.  The entire cache may be cleared.

    For all current Amiga models, Chip memory is set with Instruction
    caching enabled, data caching disabled.  This prevents coherency
    conflicts with the blitter or other custom chip DMA.  Custom chip
    registers are marked as non-cacheable by the hardware.

    The system takes care of appropriately flushing the caches for normal
    operations.  The instruction cache is cleared by all calls that
    modify instructions, including LoadSeg(), MakeLibrary() and
    SetFunction().

   SEE ALSO
    exec/execbase.i, CacheControl, CacheClearU

 exec.library/CacheClearU                             exec.library/CacheClearU

   NAME
    CacheClearU - User callable simple cache clearing (V37)

   SYNOPSIS
    CacheClearU()

    void CacheClearU(void);

   FUNCTION
    Flush out the contents of any CPU instruction and data caches.
    If dirty data cache lines are present, push them to memory first.

    Caches must be cleared after *any* operation that could cause
    invalid or stale data.  The most common cases are DMA and modifying
    instructions using the processor.  See the CacheClearE() autodoc
    for a more complete description.

    Some examples of when the cache needs clearing:
            Self modifying code
            Building Jump tables
            Run-time code patches
            Relocating code for use at different addresses.
            Loading code from disk

   SEE ALSO
    exec/execbase.i, CacheControl, CacheClearE

 exec.library/CacheControl                           exec.library/CacheControl

   NAME
    CacheControl - Instruction & data cache control

   SYNOPSIS
    oldBits = CacheControl(cacheBits,cacheMask)
    D0                     D0        D1

    ULONG CacheControl(ULONG,ULONG);

   FUNCTION
    This function provides global control of any instruction or data
    caches that may be connected to the system.  All settings are
    global -- per task control is not provided.

    The action taken by this function will depend on the type of
    CPU installed.  This function may be patched to support external
    caches, or different cache architectures.  In all cases the function
    will attempt to best emulate the provided settings.  Use of this
    function may save state specific to the caches involved.

    The list of supported settings is provided in the exec/execbase.i
    include file.  The bits currently defined map directly to the Motorola
    68030 CPU CACR register.  Alternate cache solutions may patch into
    the Exec cache functions.  Where possible, bits will be interpreted to
    have the same meaning on the installed cache.

   INPUTS
    cacheBits - new values for the bits specified in cacheMask.

    cacheMask - a mask with ones for all bits to be changed.

   RESULT
    oldBits   - the complete prior values for all settings.

   NOTE
    As a side effect, this function clears all caches.

   SEE ALSO
    exec/execbase.i, CacheClearU, CacheClearE

 exec.library/CachePostDMA                           exec.library/CachePostDMA

   NAME
    CachePostDMA - Take actions after to hardware DMA  (V37)

   SYNOPSIS
    CachePostDMA(vaddress,&length,flags)
                 a0       a1      d0

    CachePostDMA(APTR,LONG *,ULONG);

   FUNCTION
    Take all appropriate steps after Direct Memory Access (DMA).  This
    function is primarily intended for writers of DMA device drivers.  The
    action will depend on the CPU type installed, caching modes, and the
    state of any Memory Management Unit (MMU) activity.

    As implemented
        68000 - Do nothing
        68010 - Do nothing
        68020 - Do nothing
        68030 - Flush the data cache
        68040 - Flush matching areas of the data cache
        ????? - External cache boards, Virtual Memory Systems, or
            future hardware may patch this vector to best emulate
            the intended behavior.
            With a Bus-Snooping CPU, this function my end up
            doing nothing.

   INPUTS
    address	- Same as initially passed to CachePreDMA
    length	- Same as initially passed to CachePreDMA
    flags	- Values:
            DMA_NoModify - If the area was not modified (and
            thus there is no reason to flush the cache) set
            this bit.

   SEE ALSO
    exec/execbase.i, CachePreDMA, CacheClearU, CacheClearE

 exec.library/CachePreDMA                             exec.library/CachePreDMA

   NAME
    CachePreDMA - Take actions prior to hardware DMA  (V37)

   SYNOPSIS
    paddress = CachePreDMA(vaddress,&length,flags)
    d0                     a0       a1      d0

    APTR CachePreDMA(APTR,LONG *,ULONG);

   FUNCTION
    Take all appropriate steps before Direct Memory Access (DMA).  This
    function is primarily intended for writers of DMA device drivers.  The
    action will depend on the CPU type installed, caching modes, and the
    state of any Memory Management Unit (MMU) activity.

    This function supports advanced cache architectures that have
    "copyback" modes.  With copyback, write data may be cached, but not
    actually flushed out to memory.  If the CPU has unflushed data at the
    time of DMA, data may be lost.

    As implemented
        68000 - Do nothing
        68010 - Do nothing
        68020 - Do nothing
        68030 - Do nothing
        68040 - Write any matching dirty cache lines back to memory.
            As a side effect of the 68040's design, matching data
            cache lines are also invalidated -- future CPUs may
            be different.
        ????? - External cache boards, Virtual Memory Systems, or
            future hardware may patch this vector to best emulate
            the intended behavior.
            With a Bus-Snooping CPU, this function my end up
            doing nothing.

   INPUTS
    address	- Base address to start the action.
    length	- Pointer to a longword with a length.
    flags	- Values:
            DMA_Continue - Indicates this call is to complete
            a prior request that was broken up.

   RESULTS
    paddress- Physical address that coresponds to the input virtual
          address.
    &length	- This length value will be updated to reflect the contiguous
          length of physical memory present at paddress.  This may
          be smaller than the requested length.  To get the mapping
          for the next chunk of memory, call the function again with
          a new address, length, and the DMA_Continue flag.

   NOTE
    Due to processor granularity, areas outside of the address range
    may be affected by the cache flushing actions.  Care has been taken
    to ensure that no harm is done outside the range, and that activities
    on overlapping cache lines won't harm data.

   SEE ALSO
    exec/execbase.i, CachePostDMA, CacheClearU, CacheClearE

 exec.library/Cause                                         exec.library/Cause

   NAME
       Cause -- cause a software interrupt

   SYNOPSIS
       Cause(interrupt)
         A1

       void Cause(struct Interrupt *);

   FUNCTION
    This function causes a software interrupt to occur.  If it is
    called from user mode (and processor level 0), the software
    interrupt will preempt the current task.  This call is often used
    by high-level hardware interrupts to defer medium-length processing
    down to a lower interrupt level.  Note that a software interrupt is
    still a real interrupt, and must obey the same restrictions on what
    system function it may call.

    Currently only 5 software interrupt priorities are implemented:
    -32, -16, 0, +16, and +32.  Priorities in between are truncated,
    values outside the -32/+32 range are not allowed.

   NOTE
    When setting up the Interrupt structure, set the node type to
    NT_INTERRUPT, or NT_UNKOWN.

   IMPLEMENTATION
    1> Checks if the node type is NT_SOFTINT.  If so does nothing since
       the softint is already pending.  No nest count is maintained.
    2> Sets the node type to NT_SOFTINT.
    3> Links into one of the 5 priority queues.
    4> Pokes the hardware interrupt bit used for softints.

    The node type returns to NT_INTERRUPT after removal from the list.

   INPUTS
    interrupt - pointer to a properly initialized interrupt node

   BUGS
    Unlike other Interrupts, SoftInts must preserve the value of A6.

 exec.library/CheckIO                                     exec.library/CheckIO

   NAME
    CheckIO -- get the status of an IORequest

   SYNOPSIS
    result = CheckIO(iORequest)
    D0		 A1

    BOOL CheckIO(struct IORequest *);

   FUNCTION
    This function determines the current state of an I/O request and
    returns FALSE if the I/O has not yet completed.  This function
    effectively hides the internals of the I/O completion mechanism.

    CheckIO() will NOT remove the returned IORequest from the reply port.
    This is best performed with WaitIO(). If the request has already
    completed, WaitIO() will return quickly. Use of the Remove()
    function is dangerous, since other tasks may still be adding things
    to your message port; a Disable() would be required.

    This function should NOT be used to busy loop (looping until IO is
    complete).  WaitIO() is provided for that purpose.

   INPUTS
    iORequest - pointer to an I/O request block

   RESULTS
    result - NULL if I/O is still in progress.  Otherwise
         D0 points to the IORequest block.

   NOTE
    CheckIO can hang if called on an IORequest that has never been used.
    This occurs if LN_TYPE of the IORequest is set to "NT_MESSAGE".
    Instead simply set LN_TYPE to 0.

   SEE ALSO
    DoIO, SendIO, WaitIO, AbortIO

 exec.library/CloseDevice                             exec.library/CloseDevice

   NAME
    CloseDevice -- conclude access to a device

   SYNOPSIS
    CloseDevice(iORequest)
            A1

    void CloseDevice(struct IORequest *);

   FUNCTION
    This function informs the device that access to a device/unit
    previously opened has been concluded.  The device may perform
    certain house-cleaning operations.

    The user must ensure that all outstanding IORequests have been
    returned before closing the device.  The AbortIO function can kill
    any stragglers.

    After a close, the I/O request structure is free to be reused.
    Starting with V36 exec it is safe to CloseDevice() with an
    IORequest that is either cleared to zeros, or failed to
    open.

   INPUTS
    iORequest - pointer to an I/O request structure

   SEE ALSO
    OpenDevice

 exec.library/CloseLibrary                           exec.library/CloseLibrary

   NAME
    CloseLibrary -- conclude access to a library

   SYNOPSIS
    CloseLibrary(library)
             A1

    void CloseLibrary(struct Library *);

   FUNCTION
    This function informs the system that access to the given library
    has been concluded.  The user must not reference the library or any
    function in the library after this close.

    Starting with V36, it is safe to pass a NULL instead of
    a library pointer.

   INPUTS
    library - pointer to a library node

   NOTE
    Library writers must pass a SegList pointer or NULL back from their
    open point.  This value is used by the system, and not visible as
    a return code from CloseLibrary.

   SEE ALSO
    OpenLibrary

 exec.library/ColdReboot                               exec.library/ColdReboot

    NAME
    ColdReboot - reboot the Amiga (V36)

    SYNOPSIS
    ColdReboot()

    void ColdReboot(void);

    FUNCTION
    Reboot the machine.  All external memory and periperals will be
    RESET, and the machine will start its power up diagnostics.

    This function never returns.

    INPUT
    A chaotic pile of disoriented bits.

    RESULTS
    An altogether totally integrated living system.

 exec.library/CopyMem                                     exec.library/CopyMem

   NAME
    CopyMem - general purpose memory copy function

   SYNOPSIS
    CopyMem( source, dest, size )
         A0	 A1    D0

    void CopyMem(APTR,APTR,ULONG);

   FUNCTION
    CopyMem is a general purpose, fast memory copy function.  It can
    deal with arbitrary lengths, with its pointers on arbitrary
    alignments.  It attempts to optimize larger copies with more
    efficient copies, it uses byte copies for small moves, parts of
    larger copies, or the entire copy if the source and destination are
    misaligned with respect to each other.

    Arbitrary overlapping copies are not supported.

    The internal implementation of this function will change from
    system to system, and may be implemented via hardware DMA.

   INPUTS
    source - a pointer to the source data region
    dest  - a pointer to the destination data region
    size  - the size (in bytes) of the memory area.  Zero copies
        zero bytes

   SEE ALSO
    CopyMemQuick

 exec.library/CopyMemQuick                           exec.library/CopyMemQuick

   NAME
    CopyMemQuick - optimized memory copy function

   SYNOPSIS
    CopyMemQuick( source, dest, size )
              A0      A1    D0

    void CopyMemQuick(ULONG *,ULONG *,ULONG);

   FUNCTION
    CopyMemQuick is a highly optimized memory copy function, with
    restrictions on the size and alignment of its arguments. Both the
    source and destination pointers must be longword aligned.  In
    addition, the size must be an integral number of longwords (e.g.
    the size must be evenly divisible by four).

    Arbitrary overlapping copies are not supported.

    The internal implementation of this function will change from system
    to system, and may be implemented via hardware DMA.

   INPUTS
    source - a pointer to the source data region, long aligned
    dest -  a pointer to the destination data region, long aligned
    size -  the size (in bytes) of the memory area.  Zero copies
        zero bytes.

   SEE ALSO
    CopyMem

 exec.library/CreateIORequest                     exec.library/CreateIORequest

   NAME
    CreateIORequest() -- create an IORequest structure  (V36)

   SYNOPSIS
    ioReq = CreateIORequest( ioReplyPort, size );
                             A0           D0

    struct IORequest *CreateIORequest(struct MsgPort *, ULONG);

   FUNCTION
    Allocates memory for and initializes a new IO request block
    of a user-specified number of bytes.  The number of bytes
    must be at least as large as a "struct Message".

   INPUTS
    ioReplyPort - Pointer to a port for replies (an initialized message
        port, as created by CreateMsgPort() ).  If NULL, this
        function fails.
    size - the size of the IO request to be created.

   RESULT
    ioReq - A pointer to the new IORequest block, or NULL.

   SEE ALSO
    DeleteIORequest, CreateMsgPort(), amiga.lib/CreateExtIO()

 exec.library/CreateMsgPort                         exec.library/CreateMsgPort

   NAME
    CreateMsgPort - Allocate and initialize a new message port  (V36)

   SYNOPSIS
    CreateMsgPort()

    struct MsgPort * CreateMsgPort(void);

   FUNCTION
    Allocates and initializes a new message port.  The message list
    of the new port will be prepared for use (via NewList).  A signal
    bit will be allocated, and the port will be set to signal your
    task when a message arrives (PA_SIGNAL).

    You *must* use DeleteMsgPort() to delete ports created with
    CreateMsgPort()!

   RESULT
    MsgPort - A new MsgPort structure ready for use, or NULL if out of
        memory or signals.  If you wish to add this port to the public
        port list, fill in the ln_Name and ln_Pri fields, then call
        AddPort().  Don't forget RemPort()!

   SEE ALSO
    DeleteMsgPort(), exec/AddPort(), exec/ports.h, amiga.lib/CreatePort()

 exec.library/Deallocate                               exec.library/Deallocate

   NAME
    Deallocate -- deallocate a block of memory

   SYNOPSIS
    Deallocate(memHeader, memoryBlock, byteSize)
           A0	      A1	   D0

    void Deallocate(struct MemHeader *,APTR,ULONG);

   FUNCTION
    This function deallocates memory by returning it to the appropriate
    private free memory pool.  This function can be used to free an
    entire block allocated with the above function, or it can be used
    to free a sub-block of a previously allocated block.  Sub-blocks
    must be an even multiple of the memory chunk size (currently 8
    bytes).

    This function can even be used to add a new free region to an
    existing MemHeader, however the extent pointers in the MemHeader
    will no longer be valid.

    If memoryBlock is not on a block boundary (MEM_BLOCKSIZE) then it
    will be rounded down in a manner compatible with Allocate().  Note
    that this will work correctly with all the memory allocation
    functions, but may cause surprises if one is freeing only part of a
    region.  The size of the block will be rounded up, so the freed
    block will fill to an even memory block boundary.

   INPUTS
    memHeader - points to the memory header this block is part of.
    memoryBlock - address of memory block to free.
    byteSize - the size of the block in bytes. If NULL, nothing
           happens.

   SEE ALSO
    Allocate, exec/memory.h

 exec.library/Debug                                         exec.library/Debug

   NAME
    Debug -- run the system debugger

   SYNOPSIS
    Debug(flags)
          D0

    void Debug(ULONG);

   FUNCTION
    This function calls the system debugger.  By default this debugger
    is "ROM-WACK".  Other debuggers are encouraged to take over this
    entry point (via SetFunction()) so that when an application calls
    Debug(), the alternative debugger will get control.  Currently a
    zero is passed to allow future expansion.

   NOTE
    The Debug() call may be made when the system is in a questionable
    state; if you have a SetFunction() patch, make few assumptions, be
    prepared for Supervisor mode, and be aware of differences in the
    Motorola stack frames on the 68000,'10,'20, and '30.

   SEE ALSO
    SetFunction
    your favorite debugger's manual
    the ROM-WACK chapter of the ROM Kernel Manual

 exec.library/DeleteIORequest                     exec.library/DeleteIORequest

   NAME
    DeleteIORequest() - Free a request made by CreateIORequest()  (V36)

   SYNOPSIS
    DeleteIORequest( ioReq );
                     a0

    void DeleteIORequest(struct IORequest *);

   FUNCTION
    Frees up an IO request as allocated by CreateIORequest().

   INPUTS
    ioReq - A pointer to the IORequest block to be freed, or NULL.
        This function uses the mn_Length field to determine how
        much memory to free.

   SEE ALSO
    CreateIORequest(), amiga.lib/DeleteExtIO()

 exec.library/DeleteMsgPort                         exec.library/DeleteMsgPort

   NAME
    DeleteMsgPort - Free a message port created by CreateMsgPort  (V36)

   SYNOPSIS
    DeleteMsgPort(msgPort)
              a0

    void DeleteMsgPort(struct MsgPort *);

   FUNCTION
    Frees a message port created by CreateMsgPort().  All messages that
    may have been attached to this port must have already been
    replied to.

   INPUTS
    msgPort - A message port.  NULL for no action.

   SEE ALSO
    CreateMsgPort(), amiga.lib/DeletePort()

 exec.library/Disable                                     exec.library/Disable

    NAME
    Disable -- disable interrupt processing.

    SYNOPSIS
    Disable();

    void Disable(void);

    FUNCTION
    Prevents interrupts from being handled by the system, until a
    matching Enable() is executed.  Disable() implies Forbid().

    DO NOT USE THIS CALL WITHOUT GOOD JUSTIFICATION.  THIS CALL IS
    VERY DANGEROUS!

    RESULTS
    All interrupt processing is deferred until the task executing makes
    a call to Enable() or is placed in a wait state.  Normal task
    rescheduling does not occur while interrupts are disabled.  In order
    to restore normal interrupt processing, the programmer must execute
    exactly one call to Enable() for every call to Disable().

    IMPORTANT REMINDER:

    It is important to remember that there is a danger in using
    disabled sections.  Disabling interrupts for more than ~250
    microseconds will prevent vital system functions (especially serial
    I/0) from operating in a normal fashion.

    Think twice before using Disable(), then think once more.
    After all that, think again.  With enough thought, the need
    for a Disable() can often be eliminated.  For the user of many
    device drivers, a write to disable *only* the particular interrupt
    of interest can replace a Disable().  For example:
            MOVE.W	#INTF_PORTS,_intena
    Do not use a macro for Disable(), insist on the real thing.

    This call may be made from interrupts, it will have the effect
    of locking out all higher-level interrupts (lower-level interrupts
    are automatically disabled by the CPU).

        Note: In the event of a task entering a Wait() after disabling
              interrupts, the system "breaks" the disabled state and runs
              normally until the task which called Disable() is rescheduled.

    NOTE
    This call is guaranteed to preserve all registers.

    SEE ALSO
    Forbid, Permit, Enable

 exec.library/DoIO                                           exec.library/DoIO

   NAME
    DoIO -- perform an I/O command and wait for completion

   SYNOPSIS
    error = DoIO(iORequest)
    D0	     A1

    BYTE DoIO(struct IORequest *);

   FUNCTION
    This function requests a device driver to perform the I/O command
    specified in the I/O request.  This function will always wait until
    the I/O request is fully complete.

    DoIO() handles all the details, including Quick I/O, waiting for
    the request, and removing the reply message, etc..

   IMPLEMENTATION
    This function first tries to complete the IO via the "Quick I/O"
    mechanism.  The io_Flags field is always set to IOF_QUICK (0x01)
    before the internal device call.

    The LN_TYPE field is used internally to flag completion.  Active
    requests have type NT_MESSAGE.  Requests that have been replied
    have type NT_REPLYMSG.  It is illegal to start IO using a
    still active IORequest, or a request with type NT_REPLYMSG.

   INPUTS
    iORequest - pointer to an IORequest initialized by OpenDevice()

   RESULTS
    error - a sign-extended copy of the io_Error field of the
        IORequest.  Most device commands require that the error
        return be checked.

   SEE ALSO
    SendIO, CheckIO, WaitIO, AbortIO, amiga.lib/BeginIO

 exec.library/Enable                                       exec.library/Enable

   NAME
    Enable -- permit system interrupts to resume.

   SYNOPSIS
    Enable();

    void Enable(void);

   FUNCTION
    Allow system interrupts to again occur normally, after a matching
    Disable() has been executed.

   RESULTS
    Interrupt processing is restored to normal operation. The
    programmer must execute exactly one call to Enable() for every call
    to Disable().

    NOTE
    This call is guaranteed to preserve all registers.

   SEE ALSO
    Forbid, Permit, Disable

 exec.library/Enqueue                                     exec.library/Enqueue

   NAME
    Enqueue -- insert or append node to a system queue

   SYNOPSIS
    Enqueue(list, node)
        A0    A1

    void Enqueue(struct List *, struct Node *);

   FUNCTION
    Insert or append a node into a system queue.  The insert is
    performed based on the node priority -- it will keep the list
    properly sorted.  New nodes will be inserted in front of the first
    node with a lower priority.   Hence a FIFO queue for nodes of equal
    priority

   WARNING
    This function does not arbitrate for access to the list.  The
    calling task must be the owner of the involved list.

   INPUTS
    list - a pointer to the system queue header
    node - the node to enqueue.  This must be a full featured list
           with type, priority and name fields.

   SEE ALSO
    AddHead, AddTail, Insert, Remove, RemHead, RemTail

 exec.library/FindName                                   exec.library/FindName

   NAME
    FindName -- find a system list node with a given name

   SYNOPSIS
    node = FindName(start, name)
    D0,Z		A0     A1

    struct Node *FindName(struct List *, STRPTR);

   FUNCTION
    Traverse a system list until a node with the given name is found.
    To find multiple occurrences of a string, this function may be
    called with a node starting point.

    No arbitration is done for access to the list!	If multiple tasks
    access the same list, an arbitration mechanism such as
    SignalSemaphores must be used.

   INPUTS
    start - a list header or a list node to start the search
        (if node, this one is skipped)
    name - a pointer to a name string terminated with NULL

   RESULTS
    node - a pointer to the node with the same name else
        zero to indicate that the string was not found.

 exec.library/FindPort                                   exec.library/FindPort

   NAME
    FindPort -- find a given system message port

   SYNOPSIS
    port = FindPort(name)
    D0		A1

    struct MsgPort *FindPort(STRPTR);

   FUNCTION
    This function will search the system message port list for a port
    with the given name.  The first port matching this name will be
    returned.  No arbitration of the port list is done.  This function
    MUST be protected with A Forbid()/Permit() pair!

   EXAMPLE
    #include <exec/types.h>
    struct MsgPort *FindPort();

    ULONG SafePutToPort(message, portname)
    struct Message *message;
    STRPTR          portname;
    {
    struct MsgPort *port;

        Forbid();
        port = FindPort(portname);
        if (port)
            PutMsg(port,message);
        Permit();
        return((ULONG)port); /* If zero, the port has gone away */
    }

   INPUT
    name - name of the port to find

   RETURN
    port - a pointer to the message port, or zero if
        not found.

 exec.library/FindResident                           exec.library/FindResident

   NAME
    FindResident - find a resident module by name

   SYNOPSIS
    resident = FindResident(name)
    D0			A1

    struct Resident *FindResident(STRPTR);

   FUNCTION
    Search the system resident tag list for a resident tag ("ROMTag") with
    the given name.  If found return a pointer to the resident tag
    structure, else return zero.

    Resident modules are used by the system to pull all its parts
    together at startup.  Resident tags are also found in disk based
    devices and libraries.

   INPUTS
    name - pointer to name string

   RESULT
    resident - pointer to the resident tag structure or
        zero if none found.

    SEE ALSO
    exec/resident.h, InitResident

 exec.library/FindSemaphore                         exec.library/FindSemaphore

   NAME
    FindSemaphore -- find a given system signal semaphore

   SYNOPSIS
    signalSemaphore = FindSemaphore(name)
    D0		                A1

    struct SignalSemaphore *FindSemaphore(STRPTR);

   FUNCTION
    This function will search the system signal semaphore list for a
    semaphore with the given name.	The first semaphore matching this
    name will be returned.

    This function does not arbitrate for access to the semaphore list,
    surround the call with a Forbid()/Permit() pair.

   INPUT
    name - name of the semaphore to find

   RESULT
    semaphore - a pointer to the signal semaphore, or zero if not
            found.

 exec.library/FindTask                                   exec.library/FindTask

   NAME
    FindTask -- find a task with the given name or find oneself

   SYNOPSIS
    task = FindTask(name)
    D0		A1

    struct Task *FindTask(STRPTR);

   FUNCTION
    This function will check all task queues for a task with the given
    name, and return a pointer to its task control block.  If a NULL
    name pointer is given a pointer to the current task will be
    returned.

    Finding oneself with a NULL for the name is very quick.  Finding a
    task by name is very system expensive, and will disable interrupts
    for a long time.  Since a task may remove itself at any time,
    a Forbid()/Permit() pair may be needed to ensure the pointer
    returned by FindTask() is still valid when used.

   INPUT
    name - pointer to a name string

   RESULT
    task - pointer to the task (or Process)

 exec.library/Forbid                                       exec.library/Forbid

    NAME
    Forbid -- forbid task rescheduling.

    SYNOPSIS
    Forbid()

    void Forbid(void);

    FUNCTION
    Prevents other tasks from being scheduled to run by the dispatcher,
    until a matching Permit() is executed, or this task is scheduled to
    Wait().  Interrupts are NOT disabled.

    DO NOT USE THIS CALL WITHOUT GOOD JUSTIFICATION.  THIS CALL IS
    DANGEROUS!

    RESULTS
    The current task will not be rescheduled as long as it is ready to
    run.  In the event that the current task enters a wait state, other
    tasks may be scheduled.  Upon return from the wait state, the original
    task will continue to run without disturbing the Forbid().

    Calls to Forbid() nest. In order to restore normal task rescheduling,
    the programmer must execute exactly one call to Permit() for every
    call to Forbid().

    WARNING
    In the event of a task entering a Wait() after a Forbid(), the system
    "breaks" the forbidden state and runs normally until the task which
    called Forbid() is rescheduled.  If caution is not taken, this can
    cause subtle bugs, since any device or DOS call will (in effect)
    cause your task to wait.

    Forbid() is not useful or safe from within interrupt code
    (All interrupts are always higher priority than tasks, and
    interrupts are allowed to break a Forbid()).

    NOTE
    This call is guaranteed to preserve all registers.

    SEE ALSO
    Permit, Disable, ObtainSemaphore, ObtainSemaphoreShared

 exec.library/FreeEntry                                 exec.library/FreeEntry

   NAME
    FreeEntry -- free many regions of memory

   SYNOPSIS
    FreeEntry(memList)
          A0
    void FreeEntry(struct MemList *);

   FUNCTION
    This function takes a memList structure (as returned by AllocEntry)
    and frees all the entries.

   INPUTS
    memList -- pointer to structure filled in with MemEntry
           structures

   SEE ALSO
    AllocEntry

 exec.library/FreeMem                                     exec.library/FreeMem

   NAME
    FreeMem -- deallocate with knowledge

   SYNOPSIS
    FreeMem(memoryBlock, byteSize)
        A1	     D0

    void FreeMem(void *,ULONG);

   FUNCTION
    Free a region of memory, returning it to the system pool from which
    it came.  Freeing partial blocks back into the system pool is
    unwise.

   NOTE
    If a block of memory is freed twice, the system will Guru. The
    Alert is AN_FreeTwice ($01000009).   If you pass the wrong pointer,
    you will probably see AN_MemCorrupt $01000005.  Future versions may
    add more sanity checks to the memory lists.

   INPUTS
    memoryBlock - pointer to the memory block to free
    byteSize - the size of the desired block in bytes.  (The operating
        system will automatically round this number to a multiple of
        the system memory chunk size)

   SEE ALSO
    AllocMem

 exec.library/FreeSignal                               exec.library/FreeSignal

   NAME
    FreeSignal -- free a signal bit

   SYNOPSIS
    FreeSignal(signalNum)
           D0

    void FreeSignal(BYTE);

   FUNCTION
    This function frees a previously allocated signal bit for reuse.
    This call must be performed while running in the same task in which
    the signal was allocated.

   WARNING
    Signals may not be allocated or freed from exception handling code.

   NOTE
    Starting with V37, an attempt to free signal -1 is harmless.

   INPUTS
    signalNum - the signal number to free {0..31}.

 exec.library/FreeTrap                                   exec.library/FreeTrap

   NAME
    FreeTrap -- free a processor trap

   SYNOPSIS
    FreeTrap(trapNum)
         D0

    void FreeTrap(ULONG);

   FUNCTION
    This function frees a previously allocated trap number for reuse.
    This call must be performed while running in the same task in which
    the trap was allocated.

   WARNING
    Traps may not be allocated or freed from exception handling code.

   INPUTS
    trapNum - the trap number to free {of 0..15}

 exec.library/FreeVec                                     exec.library/FreeVec

   NAME
    FreeVec -- return AllocVec() memory to the system  (V36)

   SYNOPSIS
    FreeVec(memoryBlock)
        A1

    void FreeVec(void *);

   FUNCTION
    Free an allocation made by the AllocVec() call.  The memory will
    be returned to the system pool from which it came.

   NOTE
    If a block of memory is freed twice, the system will Guru. The
    Alert is AN_FreeTwice ($01000009).   If you pass the wrong pointer,
    you will probably see AN_MemCorrupt $01000005.  Future versions may
    add more sanity checks to the memory lists.

   INPUTS
    memoryBlock - pointer to the memory block to free, or NULL.

   SEE ALSO
    AllocVec

 exec.library/GetCC                                         exec.library/GetCC

   NAME
    GetCC -- get condition codes in a 68010 compatible way.

   SYNOPSIS
    conditions = GetCC()
      D0

    UWORD GetCC(void);

   FUNCTION
    The 68000 processor has a "MOVE SR,<ea>" instruction which gets a
    copy of the processor condition codes.

    On the 68010,20 and 30 CPUs, "MOVE SR,<ea>" is privileged.  User
    code will trap if it is attempted.  These processors need to use
    the "MOVE CCR,<ea>" instruction instead.

    This function provides a means of obtaining the CPU condition codes
    in a manner that will make upgrades transparent.  This function is
    VERY short and quick.

   RESULTS
    conditions - the 680XX condition codes

    NOTE
    This call is guaranteed to preserve all registers.  This function
    may be implemented as code right in the jump table.

 exec.library/GetMsg                                       exec.library/GetMsg

   NAME
    GetMsg -- get next message from a message port

   SYNOPSIS
    message = GetMsg(port)
    D0		 A0

    struct Message *GetMsg(struct MsgPort *);

   FUNCTION
    This function receives a message from a given message port. It
    provides a fast, non-copying message receiving mechanism. The
    received message is removed from the message port.

    This function will not wait.  If a message is not present this
    function will return zero.  If a program must wait for a message,
    it can Wait() on the signal specified for the port or use the
    WaitPort() function.  There can only be one task waiting for any
    given port.

    Getting a message does not imply to the sender that the message is
    free to be reused by the sender.  When the receiver is finished
    with the message, it may ReplyMsg() it back to the sender.

    Getting a signal does NOT always imply a message is ready.  More
    than one message may arrive per signal, and signals may show up
    without messages.  Typically you must loop to GetMsg() until it
    returns zero, then Wait() or WaitPort().

   INPUT
    port - a pointer to the receiver message port

   RESULT
    message - a pointer to the first message available.  If
          there are no messages, return zero.
          Callers must be prepared for zero at any time.

   SEE ALSO
    PutMsg, ReplyMsg, WaitPort, Wait, exec/ports.h

 exec.library/InitCode                                   exec.library/InitCode

   NAME
    InitCode - initialize resident code modules (internal function)

   SYNOPSIS
    InitCode(startClass, version)
         D0          D1

    void InitCode(ULONG,ULONG);

   FUNCTION
    (This function may be ignored by application programmers)

    Call InitResident() for all resident modules in the ResModules array
    with the given startClass and with versions equal or greater than
    that specified.  The segList parameter is passed as zero.

    Resident modules are used by the system to pull all its parts
    together at startup.  Modules are initialized in a prioritized order.

    Modules that do not have a startclass should be of priority -120.
    RTF_AFTERDOS modues should start at -100 (working down).

   INPUTS
    startClass - the class of code to be initialized:
        BITDEF RT,COLDSTART,0
        BITDEF RT,SINGLETASK,1	;ExecBase->ThisTask==0 (V36 only)
        BITDEF RT,AFTERDOS,2	;(V36 only)
    version - a major version number

    SEE ALSO
    ResidentTag (RT) structure definition (resident.h)

 exec.library/InitResident                           exec.library/InitResident

   NAME
    InitResident - initialize resident module

   SYNOPSIS
    object = InitResident(resident, segList)
    D0	               A1        D1

    APTR InitResident(struct Resident *,ULONG);

   FUNCTION
    Initialize a ROMTag.  ROMTags are used to link system modules
    together.  Each disk based device or library must contain a
    ROMTag structure in the first code hunk.

    Once the validity of the ROMTag is verified, the RT_INIT pointer
    is jumped to  with the following registers:
        D0 = 0
        A0 = segList
         A6 = ExecBase

   INPUTS
    resident - Pointer to a ROMTag
    segList  - SegList of the loaded object, if loaded from disk.
           Libraries & Devices will cache this value for later
           return at close or expunge time.  Pass NULL for ROM
           modules.

   RESULTS
    object	- Return value from the init code, usually the library
          or device base.  NULL for failure.

   AUTOINIT FEATURE
    An automatic method of library/device base and vector table
    initialization is also provided by InitResident().  The initial code
    hunk of the library or device should contain "MOVEQ #-1,d0; RTS;".
    Following that must be an initialized Resident structure with
    RTF_AUTOINIT set in rt_Flags, and an rt_Init pointer which points
    to four longwords.  These four longwords will be used in a call
    to MakeLibrary();

        - The size of your library/device base structure including initial
          Library or Device structure.

        - A pointer to a longword table of standard, then library
          specific function offsets, terminated with -1L.
          (short format offsets are also acceptable)

        - Pointer to data table in exec/InitStruct format for
          initialization of Library or Device structure.

        - Pointer to library initialization function, or NULL.
        Calling sequence:
            D0 = library base
            A0 = segList
            A6 = ExecBase
          This function must return in D0 the library/device base to be
          linked into the library/device list.  If the initialization
          function fails, the device memory must be manually deallocated,
          then NULL returned in D0.

   SEE ALSO
    exec/resident.i, FindResident

 exec.library/InitSemaphore                         exec.library/InitSemaphore

   NAME
    InitSemaphore -- initialize a signal semaphore

   SYNOPSIS
    InitSemaphore(signalSemaphore)
              A0

    void InitSemaphore(struct SignalSemaphore *);

   FUNCTION
    This function initializes a signal semaphore and prepares it for
    use.  It does not allocate anything, but does initialize list
    pointers and the semaphore counters.

    Semaphores are often used to protect critical data structures
    or hardware that can only be accessed by one task at a time.
    After initialization, the address of the SignalSemaphore may be
    made available to any number of tasks.  Typically a task will
    try to ObtainSemaphore(), passing this address in.  If no other
    task owns the semaphore, then the call will lock and return
    quickly.  If more tasks try to ObtainSemaphore(), they will
    be put to sleep.  When the owner of the semaphore releases
    it, the next waiter in turn will be woken up.

    Semaphores are often preferable to the old-style Forbid()/Permit()
    type arbitration.  With Forbid()/Permit() *all* other tasks are
    prevented from running.  With semaphores, only those tasks that
    need access to whatever the semaphore protects are subject
    to waiting.

   INPUT
    signalSemaphore -- a signal semaphore structure (with all fields
               set to zero before the call)

   SEE ALSO
    ObtainSemaphore(), ObtainSemaphoreShared(), AttemptSemaphore(),
    ReleaseSemaphore(), exec/semaphores.h

 exec.library/InitStruct                               exec.library/InitStruct

   NAME
    InitStruct - initialize memory from a table

   SYNOPSIS
    InitStruct(initTable, memory, size);
           A1	      A2      D0

    void InitStruct(struct InitStruct *, APTR, ULONG);

   FUNCTION
    Clear a memory area, then set up default values according to
    the data and offset values in the initTable.  Typically only assembly
    programs take advantage of this function, and only with the macros
    defined in "exec/initializers.i".

    The initialization table has byte commands to

         |a    ||byte|	|given||byte|	      |once	    |
    load |count||word| into |next ||rptr| offset, |repetitively |
            |long|

    Not all combinations are supported.  The offset, when specified, is
    relative to the memory pointer provided (Memory), and is initially
    zero.  The initialization data (InitTable) contains byte commands
    whose 8 bits are interpreted as follows:

    ddssnnnn
        dd	the destination type (and size):
        00  no offset, use next destination, nnnn is count
        01  no offset, use next destination, nnnn is repeat
        10  destination offset is in the next byte, nnnn is count
        11  destination offset is in the next 24-bits, nnnn is count
        ss	the size and location of the source:
        00  long, from the next two aligned words
        01  word, from the next aligned word
        10  byte, from the next byte
        11  ERROR - will cause an ALERT (see below)
      nnnn	the count or repeat:
         count  the (number+1) of source items to copy
        repeat  the source is copied (number+1) times.

    initTable commands are always read from the next even byte. Given
    destination offsets are always relative to the memory pointer (A2).

    The command %00000000 ends the InitTable stream: use %00010001 if you
    really want to copy one longword without a new offset.

    24 bit APTR not supported for 68020 compatibility -- use long.

   INPUTS
    initTable - the beginning of the commands and data to init
        Memory with.  Must be on an even boundary unless only
        byte initialization is done.  End table with "dc.b 0"
        or "dc.w 0".
    memory - the beginning of the memory to initialize.  Must be
        on an even boundary if size is specified.
    size - the size of memory, which is used to clear it before
        initializing it via the initTable.  If Size is zero,
        memory is not cleared before initializing.

        size must be an even number.

    SEE ALSO
    exec/initializers.i

 exec.library/Insert                                       exec.library/Insert

   NAME
    Insert -- insert a node into a list

   SYNOPSIS
    Insert(list, node, listNode)
           A0    A1    A2

    void Insert(struct List *, struct Node *, struct Node *);

   FUNCTION
    Insert a node into a doubly linked list AFTER a given node
    position.  Insertion at the head of a list is possible by passing a
    zero value for listNode, though the AddHead function is slightly
    faster for that special case.

   WARNING
    This function does not arbitrate for access to the list.  The
    calling task must be the owner of the involved list.

   INPUTS
    list - a pointer to the target list header
    node - the node to insert
    listNode - the node after which to insert

    SEE ALSO
    AddHead, AddTail, Enqueue, RemHead, Remove, RemTail

 exec.library/MakeFunctions                         exec.library/MakeFunctions

   NAME
    MakeFunctions -- construct a function jump table

   SYNOPSIS
    tableSize = MakeFunctions(target, functionArray, funcDispBase)
    D0			  A0	  A1		 A2

    ULONG MakeFunctions(APTR,APTR,APTR);

   FUNCTION
    A low level function used by MakeLibrary to build jump tables of
    the type used by libraries, devices and resources.  It allows the
    table to be built anywhere in memory, and can be used both for
    initialization and replacement. This function also supports function
    pointer compression by expanding relative displacements into absolute
    pointers.

    The processor instruction cache is cleared after the table building.

   INPUT
    destination - the target address for the high memory end of the
        function jump table.  Typically this will be the library
        base pointer.

    functionArray - pointer to an array of function pointers or
        function displacements.  If funcDispBase is zero, the array
        is assumed to contain absolute pointers to functions. If
        funcDispBase is not zero, then the array is assumed to
        contain word displacements to functions.  In both cases,
        the array is terminated by a -1 (of the same size as the
        actual entry.

    funcDispBase - pointer to the base about which all function
        displacements are relative.  If zero, then the function
        array contains absolute pointers.

   RESULT
    tableSize - size of the new table in bytes (for LIB_NEGSIZE).

   SEE ALSO
    exec/MakeLibrary

 exec.library/MakeLibrary                             exec.library/MakeLibrary

   NAME
    MakeLibrary -- construct a library

   SYNOPSIS
    library = MakeLibrary(vectors, structure, init, dSize, segList)
    D0		      A0       A1	  A2	D0     D1

    struct Library *MakeLibrary
                  (APTR,struct InitStruct *,APTR,ULONG,BPTR);

   FUNCTION
    This function is used for constructing a library vector and data
    area.  The same call is used to make devices.  Space for the library
    is allocated from the system's free memory pool.  The data portion of
    the library is initialized.  init may point to a library specific
    entry point.

   NOTE
    Starting with V36, the library base is longword adjusted.  The
    lib_PosSize and lib_NegSize fields of the library structure are
    adjusted to match.

   INPUTS
    vectors - pointer to an array of function pointers or function
        displacements.	If the first word of the array is -1, then
        the array contains relative word displacements (based off
        of vectors); otherwise, the array contains absolute
        function pointers. The vector list is terminated by a -1
        (of the same size as the pointers).

    structure - points to an "InitStruct" data region.  If NULL,
        then it will not be used.

    init -	If non-NULL, an entry point that will be called before adding
        the library to the system.  Registers are as follows:
            d0 = libAddr 	;Your Library Address
            a0 = segList	;Your AmigaDOS segment list
            a6 = ExecBase	;Address of exec.library
        The result of the init function must be the library address,
        or NULL for failure.   If NULL, the init point must manually
        deallocate the library base memory (based on the sizes stored
        in lib_PosSize and lib_NegSize).

    dSize - the size of the library data area, including the
        standard library node data.  This must be at leas
        sizeof(struct Library).

       segList - pointer to an AmigaDOS SegList (segment list).
         This is passed to a library's init code, and is used later
         for removing the library from memory.

   RESULT
    library - the reference address of the library.  This is the
          address used in references to the library, not the
          beginning of the memory area allocated.  If the library
          vector table require more system memory than is
          available, this function will return NULL.

   SEE ALSO
    InitStruct, InitResident, exec/initializers.i

 exec.library/ObtainSemaphore                     exec.library/ObtainSemaphore

   NAME
    ObtainSemaphore -- gain exclusive access to a semaphore

   SYNOPSIS
    ObtainSemaphore(signalSemaphore)
            A0

    void ObtainSemaphore(struct SignalSemaphore *);

   FUNCTION
    Signal semaphores are used to gain exclusive access to an object.
    ObtainSemaphore is the call used to gain this access.  If another
    user currently has the semaphore locked the call will block until
    the object is available.

    If the current task already has locked the semaphore and attempts to
    lock it again the call will still succeed.  A "nesting count" is
    incremented each time the current owning task of the semaphore calls
    ObtainSemaphore().  This counter is decremented each time
    ReleaseSemaphore() is called.  When the counter returns to zero the
    semaphore is actually released, and the next waiting task is called.

    A queue of waiting tasks is maintained on the stacks of the waiting
    tasks.	Each will be called in turn as soon as the current task
    releases the semaphore.

    Signal Semaphores are different than Procure()/Vacate() semaphores.
    The former requires less CPU time, especially if the semaphore is
    not currently locked.  They require very little set up and user
    thought.  The latter flavor of semaphore make no assumptions about
    how they are used -- they are completely general.  Unfortunately
    they are not as efficient as signal semaphores, and require the
    locker to have done some setup before doing the call.

   INPUT
       signalSemaphore -- an initialized signal semaphore structure

   NOTE
    This function preserves all registers (see BUGS).

   BUGS
    Until V37, this function could destroy A0.

   SEE ALSO
    ObtainSemaphoreShared(), InitSemaphore(), ReleaseSemaphore(),
    AttemptSemaphore(), ObtainSemaphoreList()

 exec.library/ObtainSemaphoreList             exec.library/ObtainSemaphoreList

   NAME
    ObtainSemaphoreList -- get a list of semaphores.

   SYNOPSIS
    ObtainSemaphoreList(list)
                A0

    void ObtainSemaphoreList(struct List *);

   FUNCTION
    Signal semaphores may be linked together into a list. This function
    takes a list of these semaphores and attempts to lock all of them at
    once. This call is preferable to applying ObtainSemaphore() to each
    element in the list because it attempts to lock all the elements
    simultaneously, and won't deadlock if someone is attempting to lock
    in some other order.

    This function assumes that only one task at a time will attempt to
    lock the entire list of semaphores.  In other words, there needs to
    be a higher level lock (perhaps another signal semaphore...) that is
    used before someone attempts to lock the semaphore list via
    ObtainSemaphoreList().

    Note that deadlocks may result if this call is used AND someone
    attempts to use ObtainSemaphore() to lock more than one semaphore on
    the list.  If you wish to lock more than semaphore (but not all of
    them) then you should obtain the higher level lock (see above)

   INPUT
       list -- a list of signal semaphores

   SEE ALSO
    InitSemaphore(), ReleaseSemaphoreList()

 exec.library/ObtainSemaphoreShared         exec.library/ObtainSemaphoreShared

    NAME
    ObtainSemaphoreShared -- gain shared access to a semaphore (V36)

    SYNOPSIS
    ObtainSemaphoreShared(signalSemaphore)
                          a0

    void ObtainSemaphoreShared(struct SignalSemaphore *);

    FUNCTION
    A lock on a signal semaphore may either be exclusive, or shared.
    Exclusive locks are granted by the ObtainSemaphore() and
    AttemptSemaphore() functions.  Shared locks are granted by
    ObtainSemaphoreShared().  Calls may be nested.

    Any number of tasks may simultaneously hold a shared lock on a
    semaphore.  Only one task may hold an exclusive lock.  A typical
    application is a list that is often read, but only occasionally
    written to.

    Any exlusive locker will be held off until all shared lockers
    release the semaphore.  Likewise, if an exlusive lock is held,
    all potential shared lockers will block until the exclusive lock
    is released.  All shared lockers are restarted at the same time.

    EXAMPLE
        ObtainSemaphoreShared(ss);
        /* read data */
        ReleaseSemaohore(ss);

        ObtainSemaphore(ss);
        /* modify data */
        ReleaseSemaohore(ss);

    NOTES
    While this function was added for V36, the feature magically works
    with all older semaphore structures.

    A task owning a shared lock must not attempt to get an exclusive
    lock on the same semaphore.

    INPUT
    signalSemaphore -- an initialized signal semaphore structure

    NOTE
    This call is guaranteed to preserve all registers, starting with
    V37 exec.

    RESULT

    SEE ALSO
    InitSemaphore(), ReleaseSemaphore()

 exec.library/OldOpenLibrary                       exec.library/OldOpenLibrary

   NAME
    OldOpenLibrary -- obsolete OpenLibrary

   SYNOPSIS
    library = OldOpenLibrary(libName)
    D0			 A1

    struct Library *OldOpenLibrary(APTR);

   FUNCTION
    The 1.0 release of the Amiga system had an incorrect version of
    OpenLibrary that did not check the version number during the
    library open.  This obsolete function is provided so that object
    code compiled using a 1.0 system will still run.

    This exactly the same as "OpenLibrary(libName,0L);"

   INPUTS
    libName - the name of the library to open

   RESULTS
    library - a library pointer for a successful open, else zero

   SEE ALSO
    CloseLibrary

 exec.library/OpenDevice                               exec.library/OpenDevice

   NAME
    OpenDevice -- gain access to a device

   SYNOPSIS
    error = OpenDevice(devName, unitNumber, iORequest, flags)
    D0		   A0	    D0		A1	   D1

    BYTE OpenDevice(STRPTR,ULONG,struct IORequest *,ULONG);

   FUNCTION
    This function opens the named device/unit and initializes the given
    I/O request block.  Specific documentation on opening procedures
    may come with certain devices.

    The device may exist in memory, or on disk; this is transparent to
    the OpenDevice caller.

    A full path name for the device name is legitimate.  For example
    "test:devs/fred.device".  This allows the use of custom devices
    without requiring the user to copy the device into the system's
    DEVS: directory.

   NOTES
    All calls to OpenDevice should have matching calls to CloseDevice!

    Devices on disk cannot be opened until after DOS has been
    started.

    As of V36 tasks can safely call OpenDevice, though DOS may open
    system requesters (e.g., asking the user to insert the Workbench
    disk if DEVS: is not online).  You must call this function from a
    DOS Process if you want to turn off DOS requesters.

   INPUTS
    devName - requested device name

    unitNumber - the unit number to open on that device.  The format of
        the unit number is device specific.  If the device does
        not have separate units, send a zero.

    iORequest - the I/O request block to be returned with
        appropriate fields initialized.

    flags - additional driver specific information.  This is sometimes
        used to request opening a device with exclusive access.

   RESULTS
    error - Returns a sign-extended copy of the io_Error field
        of the IORequest.  Zero if successful, else an error code
        is returned.

   BUGS
    AmigaDOS file names are not case sensitive, but Exec lists are.  If
    the library name is specified in a different case than it exists on
    disk, unexpected results may occur.

    Prior to V36, tasks could not make OpenDevice calls requiring disk
    access (since tasks are not allowed to make dos.library calls).
    Now OpenDevice is protected from tasks.

   SEE ALSO
    CloseDevice, DoIO, SendIO, CheckIO, AbortIO, WaitIO

 exec.library/OpenLibrary                             exec.library/OpenLibrary

   NAME
    OpenLibrary -- gain access to a library

   SYNOPSIS
    library = OpenLibrary(libName, version)
    D0		      A1       D0

    struct Library *OpenLibrary(STRPTR, ULONG);

   FUNCTION
    This function returns a pointer to a library that was previously
    installed into the system.  If the requested library is exists, and
    if the library version is greater than or equal to the requested
    version, then the open will succeed.

    The device may exist in memory, or on disk; this is transparent to
    the OpenDevice caller.  Only Processes are allowed to call
    OpenLibrary (since OpenLibrary may in turn call dos.library).

    A full path name for the library name is legitimate.  For example
    "wp:libs/wp.library".  This allows the use of custom libraries
    without requiring the user to copy the library into the system's
    LIBS: directory.

   NOTES
    All calls to OpenLibrary should have matching calls to CloseLibrary!

    Libraries on disk cannot be opened until after DOS has been
    started.

    As of V36 tasks can safely call OpenLibrary, though DOS may open
    system requesters (e.g., asking the user to insert the Workbench
    disk if LIBS: is not online).  You must call this function from a
    DOS Process if you want to turn off DOS requesters.

   INPUTS
    libName - the name of the library to open

    version - the version of the library required.

   RESULTS
    library - a library pointer for a successful open, else zero

   BUGS
    AmigaDOS file names are not case sensitive, but Exec lists are. If
    the library name is specified in a different case than it exists on
    disk, unexpected results may occur.

    Prior to V36, tasks could not make OpenLibrary calls requiring disk
    access (since tasks are not allowed to make dos.library calls).
    Now OpenLibrary is protected from tasks.

    The version number of the resident tag in disk based library must
    match the version number of the library, or V36 may fail to load it.

   SEE ALSO
    CloseLibrary

 exec.library/OpenResource                           exec.library/OpenResource

   NAME
    OpenResource -- gain access to a resource

   SYNOPSIS
    resource = OpenResource(resName)
    D0			A1

    APTR OpenResource(STRPTR);

   FUNCTION
    This function returns a pointer to a resource that was previously
    installed into the system.

    There is no CloseResource() function.

   INPUTS
       resName - the name of the resource requested.

   RESULTS
    resource - if successful, a resource pointer, else NULL

 exec.library/Permit                                       exec.library/Permit

    NAME
    Permit -- permit task rescheduling.

    SYNOPSIS
    Permit()

    void Permit(void);

    FUNCTION
    Allow other tasks to be scheduled to run by the dispatcher, after a
    matching Forbid() has been executed.

    RESULTS
    Other tasks will be rescheduled as they are ready to run. In order
    to restore normal task rescheduling, the programmer must execute
    exactly one call to Permit() for every call to Forbid().

    NOTE
    This call is guaranteed to preserve all registers.

    SEE ALSO
    Forbid, Disable, Enable

 exec.library/Procure                                     exec.library/Procure

   NAME
    Procure -- bid for a message lock (semaphore)

   SYNOPSIS
    result = Procure(semaphore, bidMessage)
    D0		 A0	    A1

    BYTE Procure(struct Semaphore *, struct Message *);

   FUNCTION
    This function is used to obtain a message based semaphore lock.  If
    the lock is immediate, Procure() returns a true result, and the
    bidMessage is not used.   If the semaphore is already locked,
    Procure() returns false, and the task must wait for the bidMessage
    to arrive at its reply port.

    Straight "Semaphores" use the message system.  They are therefore
    queueable, and users may wait on several of them at the same time.
    This makes them more powerful than "Signal Semaphores"

   INPUT
    semaphore - a semaphore message port.  This port is used to queue
    all pending lockers.  This port should be initialized with the
    PA_IGNORE option, as the MP_SigTask field is used for a pointer to
    the current locker message (not a task). New semaphore ports must
    also have the SM_BIDS word initialized to -1.  If the semaphore is
    public, it should be named, its priority set, and the added with
    AddPort. Message port priority is often used for anti-deadlock
    locking conventions.

   RESULT
    result - true when the semaphore is free.  In such cases no waiting
    needs to be done.  If false, then the task should wait at its
    bidMessage reply port.

   BUGS
    Procure() and Vacate() do not have proven reliability.

   SEE ALSO
    Vacate()

 exec.library/PutMsg                                       exec.library/PutMsg

   NAME
    PutMsg -- put a message to a message port

   SYNOPSIS
    PutMsg(port, message)
           A0    A1

    void PutMsg(struct MsgPort *, struct Message *);

   FUNCTION
    This function attaches a message to the end of a given message port.
    It provides a fast, non-copying message sending mechanism.

    Messages can be attached to only one port at a time.  The message
    body can be of any size or form.  Because messages are not copied,
    cooperating tasks share the same message memory.  The sender task
    must not recycle the message until it has been replied by the
    receiver.  Of course this depends on the message handling conventions
    setup by the involved tasks.  If the ReplyPort field is non-zero,
    when the message is replied by the receiver, it will be sent back to
    that port.

    Any one of the following actions can be set to occur when a message
    is put:

        1. no special action
        2. signal a given task (specified by MP_SIGTASK)
        3. cause a software interrupt (specified by MP_SIGTASK)

    The action is selected depending on the value found in the MP_FLAGS
    of the destination port.

   IMPLEMENTATION
    1.  Sets the LN_TYPE field to "NT_MESSAGE".
    2.  Attaches the message to the destination port.
    3.  Performs the specified arrival action at the destination.

   INPUT
    port - pointer to a message port
    message - pointer to a message

   SEE ALSO
    GetMsg, ReplyMsg, exec/ports.h

 exec.library/RawDoFmt                                   exec.library/RawDoFmt

   NAME
    RawDoFmt -- format data into a character stream.

   SYNOPSIS
    NextData = RawDoFmt(FormatString, DataStream, PutChProc, PutChData);
       d0                  a0            a1          a2         a3

    APTR RawDoFmt(STRPTR,APTR,void (*)(),APTR);

   FUNCTION
    perform "C"-language-like formatting of a data stream, outputting
    the result a character at a time.  Where % formatting commands are
    found in the FormatString, they will be replaced with the
    corresponding element in the DataStream.  %% must be used in the
    string if a % is desired in the output.

    Under V36, RawDoFmt() returns a pointer to the end of the DataStream
    (The next argument that would have been processed).  This allows
    multiple formatting passes to be made using the same data.

   INPUTS
    FormatString - a "C"-language-like NULL terminated format string,
    with the following supported % options:

     %[flags][width.limit][length]type

    flags  - only one allowed. '-' specifies left justification.
    width  - field width.  If the first character is a '0', the
         field will be padded with leading 0's.
      .    - must follow the field width, if specified
    limit  - maximum number of characters to output from a string.
         (only valid for %s).
    length - size of input data defaults to WORD for types d, x,
         and c, 'l' changes this to long (32-bit).
    type   - supported types are:
            b - BSTR, data is 32-bit BPTR to byte count followed
                by a byte string, or NULL terminated byte string.
                A NULL BPTR is treated as an empty string.
                (Added in V36 exec)
            d - decimal
            u - unsigned decimal (Added in V37 exec)
            x - hexadecimal
            s - string, a 32-bit pointer to a NULL terminated
                byte string.  In V36, a NULL pointer is treated
                as an empty string
            c - character

    DataStream - a stream of data that is interpreted according to
         the format string.  Often this is a pointer into
         the task's stack.
    PutChProc  - the procedure to call with each character to be
         output, called as:

    PutChProc(Char,  PutChData);
          D0-0:8 A3

        the procedure is called with a NULL Char at the end of
        the format string.

    PutChData - a value that is passed through to the PutChProc
        procedure.  This is untouched by RawDoFmt, and may be
        modified by the PutChProc.

   EXAMPLE
    ;
    ; Simple version of the C "sprintf" function.  Assumes C-style
    ; stack-based function conventions.
    ;
    ;   long eyecount;
    ;   eyecount=2;
    ;   sprintf(string,"%s have %ld eyes.","Fish",eyecount);
    ;
    ; would produce "Fish have 2 eyes." in the string buffer.
    ;
        XDEF _sprintf
        XREF _AbsExecBase
        XREF _LVORawDoFmt
    _sprintf:	; ( ostring, format, {values} )
        movem.l a2/a3/a6,-(sp)

        move.l	4*4(sp),a3       ;Get the output string pointer
        move.l	5*4(sp),a0       ;Get the FormatString pointer
        lea.l	6*4(sp),a1       ;Get the pointer to the DataStream
        lea.l	stuffChar(pc),a2
        move.l	_AbsExecBase,a6
        jsr	_LVORawDoFmt(a6)

        movem.l (sp)+,a2/a3/a6
        rts

    ;------ PutChProc function used by RawDoFmt -----------
    stuffChar:
        move.b	d0,(a3)+        ;Put data to output string
        rts

   WARNING
    This Amiga ROM function formats word values in the data stream.  If
    your compiler defaults to longs, you must add an "l" to your
    % specifications.  This can get strange for characters, which might
    look like "%lc".

    The result of RawDoFmt() is *ONLY* valid in V36 and later releases
    of EXEC.  Pre-V36 versions of EXEC have "random" return values.

   SEE ALSO
    Documentation on the C language "printf" call in any C language
    reference book.

 exec.library/ReleaseSemaphore                   exec.library/ReleaseSemaphore

   NAME
    ReleaseSemaphore -- make signal semaphore available to others

   SYNOPSIS
    ReleaseSemaphore(signalSemaphore)
             A0

    void ReleaseSemaphore(struct SignalSemaphore *);

   FUNCTION
    ReleaseSemaphore() is the inverse of ObtainSemaphore(). It makes
    the semaphore lockable to other users.	If tasks are waiting for
    the semaphore and this this task is done with the semaphore then
    the next waiting task is signalled.

    Each ObtainSemaphore() call must be balanced by exactly one
    ReleaseSemaphore() call.  This is because there is a nesting count
    maintained in the semaphore of the number of times that the current
    task has locked the semaphore. The semaphore is not released to
    other tasks until the number of releases matches the number of
    obtains.

    Needless to say, havoc breaks out if the task releases more times
    than it has obtained.

   INPUT
       signalSemaphore -- an initialized signal semaphore structure

   NOTE
    This call is guaranteed to preserve all registers.

   SEE ALSO
    InitSemaphore(), ObtainSemaphore(), ObtainSemaphoreShared()

 exec.library/ReleaseSemaphoreList           exec.library/ReleaseSemaphoreList

   NAME
    ReleaseSemaphoreList -- make a list of semaphores available

   SYNOPSIS
    ReleaseSemaphoreList(list)
                 A0

    void ReleaseSemaphoreList(struct List *);

   FUNCTION
    ReleaseSemaphoreList() is the inverse of ObtainSemaphoreList(). It
    releases each element in the semaphore list.

    Needless to say, havoc breaks out if the task releases more times
    than it has obtained.

   INPUT
       list -- a list of signal semaphores

   SEE ALSO
    ObtainSemaphoreList()

 exec.library/RemDevice                                 exec.library/RemDevice

   NAME
    RemDevice -- remove a device from the system

   SYNOPSIS
    RemDevice(device)
              A1

    void RemDevice(struct Device *);

   FUNCTION
    This function calls the device's EXPUNGE vector, which requests
    that a device delete itself.  The device may refuse to do this if
    it is busy or currently open. This is not typically called by user
    code.

    There are certain, limited circumstances where it may be
    appropriate to attempt to specifically flush a certain device.
    Example:

     /* Attempts to flush the named device out of memory. */
     #include <exec/types.h>
     #include <exec/execbase.h>

     void FlushDevice(name)
     STRPTR name;
     {
     struct Device *result;

        Forbid();
        if(result=(struct Device *)FindName(&SysBase->DeviceList,name))
        RemDevice(result);
        Permit();
     }

   INPUTS
    device - pointer to a device node

   SEE ALSO
    AddLibrary

 exec.library/RemHead                                     exec.library/RemHead

   NAME
    RemHead -- remove the head node from a list

   SYNOPSIS
    node = RemHead(list)
    D0	       A0

    struct Node *RemHead(struct List *);

   FUNCTION
    Get a pointer to the head node and remove it from the list.
    Assembly programmers may prefer to use the REMHEAD macro from
    "exec/lists.i".

   WARNING
    This function does not arbitrate for access to the list.  The
    calling task must be the owner of the involved list.

   INPUTS
    list - a pointer to the target list header

   RESULT
    node - the node removed or zero when empty list

   SEE ALSO
    AddHead, AddTail, Enqueue, Insert, Remove, RemTail

 exec.library/RemIntServer                           exec.library/RemIntServer

   NAME
    RemIntServer -- remove an interrupt server from a server chain

   SYNOPSIS
    RemIntServer(intNum, interrupt)
             D0      A1

    void RemIntServer(ULONG,struct Interrupt *);

   FUNCTION
    This function removes an interrupt server node from the given
    server chain.

    If this server was the last one on this chain, interrupts for this
    chain are disabled.

   INPUTS
    intNum - the Paula interrupt bit (0..14)
    interrupt - pointer to an interrupt server node

   BUGS
    Before V36 Kickstart, the feature that disables the interrupt
    would not function.  For most server chains this does not
    cause a problem.

   SEE ALSO
    AddIntServer, hardware/intbits.h

 exec.library/RemLibrary                               exec.library/RemLibrary

   NAME
    RemLibrary -- remove a library from the system

   SYNOPSIS
    RemLibrary(library)
               A1

    void RemLibrary(struct Library *);

   FUNCTION
    This function calls the library's EXPUNGE vector, which requests
    that a library delete itself.  The library may refuse to do this if
    it is busy or currently open. This is not typically called by user
    code.

    There are certain, limited circumstances where it may be
    appropriate to attempt to specifically flush a certain Library.
    Example:

     /* Attempts to flush the named library out of memory. */
     #include <exec/types.h>
     #include <exec/execbase.h>

     void FlushLibrary(name)
     STRPTR name;
     {
     struct Library *result;

        Forbid();
        if(result=(struct Library *)FindName(&SysBase->LibList,name))
        RemLibrary(result);
        Permit();
     }

   INPUTS
    library - pointer to a library node structure

 exec.library/Remove                                       exec.library/Remove

   NAME
    Remove -- remove a node from a list

   SYNOPSIS
    Remove(node)
           A1

    void Remove(struct Node *);

   FUNCTION
    Unlink a node from whatever list it is in.  Nodes that are not part
    of a list must not be passed to this funcion!  Assembly programmers
    may prefer to use the REMOVE macro from "exec/lists.i".

   WARNING
    This function does not arbitrate for access to the list.  The
    calling task must be the owner of the involved list.

   INPUTS
    node - the node to remove

   SEE ALSO
    AddHead, AddTail, Enqueue, Insert, RemHead, RemTail

 exec.library/RemPort                                     exec.library/RemPort

   NAME
    RemPort -- remove a message port from the system

   SYNOPSIS
    RemPort(port)
        A1

    void RemPort(struct MsgPort *);

   FUNCTION
    This function removes a message port structure from the system's
    message port list.  Subsequent attempts to rendezvous by name with
    this port will fail.

   INPUTS
    port - pointer to a message port

   SEE ALSO
    AddPort, FindPort

 exec.library/RemResource                             exec.library/RemResource

   NAME
    RemResource -- remove a resource from the system

   SYNOPSIS
    RemResource(resource)
           A1

    void RemResource(APTR);

   FUNCTION
    This function removes an existing resource from the system resource
    list.  There must be no outstanding users of the resource.

   INPUTS
    resource - pointer to a resource node

   SEE ALSO
    AddResource

 exec.library/RemSemaphore                           exec.library/RemSemaphore

   NAME
    RemSemaphore -- remove a signal semaphore from the system

   SYNOPSIS
    RemSemaphore(signalSemaphore)
             A1

    void RemSemaphore(struct SignalSemaphore *);

   FUNCTION
    This function removes a signal semaphore structure from the
    system's signal semaphore list.  Subsequent attempts to
    rendezvous by name with this semaphore will fail.

   INPUTS
       signalSemaphore -- an initialized signal semaphore structure

   SEE ALSO
    AddSemaphore, FindSemaphore

 exec.library/RemTail                                     exec.library/RemTail

   NAME
    RemTail -- remove the tail node from a list

   SYNOPSIS
    node = RemTail(list)
    D0	       A0

    struct Node *RemTail(struct List *);

   FUNCTION
    Remove the last node from a list, and return a pointer to it. If
    the list is empty, return zero. Assembly programmers may prefer to
    use the REMTAIL macro from "exec/lists.i".

   WARNING
    This function does not arbitrate for access to the list.  The
    calling task must be the owner of the involved list.

   INPUTS
    list - a pointer to the target list header

   RESULT
    node - the node removed or zero when empty list

   SEE ALSO
    AddHead, AddTail, Enqueue, Insert, Remove, RemHead, RemTail

 exec.library/RemTask                                     exec.library/RemTask

   NAME
    RemTask -- remove a task from the system

   SYNOPSIS
    RemTask(task)
        A1

    void RemTask(struct Task *);

   FUNCTION
    This function removes a task from the system.  Deallocation of
    resources should have been performed prior to calling this
    function.  Removing some other task is very dangerous.	Generally
    is is best to arrange for tasks to call RemTask(0L) on themselves.

    RemTask will automagically free any memory lists attached to the
    task's TC_MEMENTRY list.

   INPUTS
    task - pointer to the task node representing the task to be
           removed.  A zero value indicates self removal, and will
           cause the next ready task to begin execution.

   BUGS
    Before V36 if RemTask() was called on a task other than the current
    task, and that task was created with amiga.lib/CreateTask, there was
    a slight chance of a crash.  The problem can be hidden by bracketing
    RemTask() with Forbid()/Permit().

   SEE ALSO
    AddTask, exec/AllocEntry, amiga.lib/DeleteTask

 exec.library/ReplyMsg                                   exec.library/ReplyMsg

   NAME
    ReplyMsg -- put a message to its reply port

   SYNOPSIS
    ReplyMsg(message)
         A1

    void ReplyMsg(struct Message *);

   FUNCTION
    This function sends a message to its reply port.  This is usually
    done when the receiver of a message has finished and wants to
    return it to the sender (so that it can be re-used or deallocated,
    whatever).

    This call may be made from interrupts.

   INPUT
    message - a pointer to the message

   IMPLEMENTATION
    1> Places "NT_REPLYMSG" into LN_TYPE.
    2> Puts the message to the port specified by MN_REPLYPORT
       If there is no replyport, sets LN_TYPE to "NT_FREEMSG" (use this
       feature only with extreeme care).

   SEE ALSO
    GetMsg, PutMsg, exec/ports.h

 exec.library/SendIO                                       exec.library/SendIO

   NAME
    SendIO -- initiate an I/O command

   SYNOPSIS
    SendIO(iORequest)
           A1

    void SendIO(struct IORequest *);

   FUNCTION
    This function requests the device driver start processing the given
    I/O request.  The device will return control without waiting for
    the I/O to complete.

    The io_Flags field of the IORequest will be set to zero before the
    request is sent.  See BeginIO() for more details.

   INPUTS
    iORequest - pointer to an I/O request, or a device specific
            extended IORequest.

   SEE ALSO
    DoIO, CheckIO, WaitIO, AbortIO

 exec.library/SetExcept                                 exec.library/SetExcept

   NAME
    SetExcept -- define certain signals to cause exceptions

   SYNOPSIS
    oldSignals = SetExcept(newSignals, signalMask)
    D0		       D0	   D1

    ULONG SetExcept(ULONG,ULONG);

   FUNCTION
    This function defines which of the task's signals will cause a
    private task exception.  When any of the signals occurs the task's
    exception handler will be dispatched.  If the signal occurred prior
    to calling SetExcept, the exception will happen immediately.

    The user function pointed to by the task's tc_ExceptCode gets
    called as:

        newExcptSet = <exceptCode>(signals, exceptData),SysBase
        D0			       D0	A1	    A6

        signals - The set of signals that caused this exception.  These
        Signals have been disabled from the current set of signals
        that can cause an exception.

        exceptData - A copy of the task structure tc_ExceptData field.

        newExcptSet - The set of signals in NewExceptSet will be re-
        enabled for exception generation.  Usually this will be the
        same as the Signals that caused the exception.

   INPUTS
    newSignals - the new values for the signals specified in
        signalMask.
    signalMask - the set of signals to be effected

   RESULTS
    oldSignals - the prior exception signals

   EXAMPLE
    Get the current state of all exception signals:
        SetExcept(0,0)
    Change a few exception signals:
        SetExcept($1374,$1074)

   SEE ALSO
    Signal, SetSignal

 exec.library/SetFunction                             exec.library/SetFunction

   NAME
    SetFunction -- change a function vector in a library

   SYNOPSIS
    oldFunc = SetFunction(library, funcOffset, funcEntry)
    D0		      A1       A0.W	   D0

    APTR SetFunction(struct Library *,LONG,APTR);

   FUNCTION
    SetFunction is a functional way of changing where vectors in a
    library point.	They are changed in such a way that the
    checksumming process will never falsely declare a library to be
    invalid.

   WARNING
    If you use SetFunction on a function that can be called from
    interrupts, you are obligated to provide your own arbitration.

   NOTE
    SetFunction cannot be used on non-standard libraries like pre-V36
    dos.library.  Here you must manually Forbid(), preserve all 6
    original bytes, set the new vector, SumLibrary(), then Permit().

   INPUTS
    library    - a pointer to the library to be changed
    funcOffset - the offset of the function to be replaced
    funcEntry  - pointer to new function

   RESULTS
    oldFunc    - pointer to the old function that was just replaced

 exec.library/SetIntVector                           exec.library/SetIntVector

   NAME
    SetIntVector -- set a new handler for a system interrupt vector

   SYNOPSIS
    oldInterrupt = SetIntVector(intNumber, interrupt)
    D0			    D0         A1

    struct Interrupt *SetIntVector(ULONG, struct Interrupt *);

   FUNCTION
    This function provides a mechanism for setting the system interrupt
    vectors.  These are non-sharable; setting a new interrupt handler
    disconnects the old one.  Installed handlers are responsible for
    processing, enabling and clearing the interrupt.  Note that interrupts
    may have been left in any state by the previous code.

    The IS_CODE and IS_DATA pointers of the Interrupt structure will
    be copied into a private place by Exec.  A pointer to the previously
    installed Interrupt structure is returned.

    When the system calls the specified interrupt code, the registers are
    setup as follows:

        D0 - scratch
        D1 - scratch (on entry: active
              interrupts -> equals INTENA & INTREQ)

        A0 - scratch (on entry: pointer to base of custom chips
              for fast indexing)
        A1 - scratch (on entry: Interrupt's IS_DATA pointer)

        A5 - jump vector register (scratch on call)
        A6 - Exec library base pointer (scratch on call)

        all other registers must be preserved

   INPUTS
    intNum - the Paula interrupt bit number (0..14).  Only non-chained
         interrupts should be set.  Use AddIntServer() for server
         chains.
    interrupt - a pointer to an Interrupt structure containing the
         handler's entry point and data segment pointer.  A NULL
         interrupt pointer will remove the current interrupt and
         set illegal values for IS_CODE and IS_DATA.

         By convention, the LN_NAME of the interrupt structure must
         point a descriptive string so that other users may
         identify who currently has control of the interrupt.

   RESULT
    A pointer to the prior interrupt structure which had control
    of this interrupt.

   SEE ALSO
    AddIntServer(),exec/interrupts.i,hardware/intbits.i

 exec.library/SetSignal                                 exec.library/SetSignal

   NAME
    SetSignal -- define the state of this task's signals

   SYNOPSIS
    oldSignals = SetSignal(newSignals, signalMask)
    D0		       D0	   D1

    ULONG SetSignal(ULONG,ULONG);

   FUNCTION
    This function can query or modify the state of the current task's
    received signal mask.  Setting the state of signals is considered
    dangerous.  Reading the state of signals is safe.

   INPUTS
    newSignals - the new values for the signals specified in
             signalSet.
    signalMask - the set of signals to be affected.

   RESULTS
    oldSignals - the prior values for all signals

   EXAMPLES
    Get the current state of all signals:
        SetSignal(0L,0L);
    Clear the CTRL-C signal:
        SetSignal(0L,SIGBREAKF_CTRL_C);

    Check if the CTRL-C signal was pressed:

        #include <libraries/dos.h>

        /* Check & clear CTRL_C signal */
        if(SetSignal(0L,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
        {
        printf("CTRL-C pressed!\n");
        }

   SEE ALSO
    Signal, Wait

 exec.library/SetSR                                         exec.library/SetSR

   NAME
    SetSR -- get and/or set processor status register

   SYNOPSIS
    oldSR = SetSR(newSR, mask)
    D0	      D0     D1

    ULONG SetSR(ULONG, ULONG);

   FUNCTION
    This function provides a means of modifying the CPU status register
    in a "safe" way (well, how safe can a function like this be
    anyway?).  This function will only affect the status register bits
    specified in the mask parameter.  The prior content of the entire
    status register is returned.

   INPUTS
    newSR - new values for bits specified in the mask.
        All other bits are not effected.
    mask - bits to be changed

   RESULTS
    oldSR - the entire status register before new bits

   EXAMPLES
    To get the current SR:
        currentSR = SetSR(0,0);
    To change the processor interrupt level to 3:
        oldSR = SetSR($0300,$0700);
    Set processor interrupts back to prior level:
        SetSR(oldSR,$0700);

 exec.library/SetTaskPri                               exec.library/SetTaskPri

   NAME
    SetTaskPri -- get and set the priority of a task

   SYNOPSIS
    oldPriority = SetTaskPri(task, priority)
    D0-0:8			 A1    D0-0:8

    BYTE SetTaskPri(struct Task *,LONG);

   FUNCTION
    This function changes the priority of a task regardless of its
    state.	The old priority of the task is returned.  A reschedule is
    performed, and a context switch may result.

    To change the priority of the currently running task, pass the
    result of FindTask(0); as the task pointer.

   INPUTS
    task - task to be affected
    priority - the new priority for the task

   RESULT
    oldPriority - the tasks previous priority

 exec.library/Signal                                       exec.library/Signal

   NAME
    Signal -- signal a task

   SYNOPSIS
    Signal(task, signals)
           A1    D0

    void Signal(struct Task *,ULONG);

   FUNCTION
    This function signals a task with the given signals.  If the task
    is currently waiting for one or more of these signals, it will be
    made ready and a reschedule will occur. If the task is not waiting
    for any of these signals, the signals will be posted to the task
    for possible later use. A signal may be sent to a task regardless
    of whether its running, ready, or waiting.

    This function is considered "low level".  Its main purpose is to
    support multiple higher level functions like PutMsg.

    This function is safe to call from interrupts.

   INPUT
    task - the task to be signalled
    signals - the signals to be sent

   SEE ALSO
    Wait, SetSignal

 exec.library/StackSwap                                 exec.library/StackSwap

   NAME
    StackSwap - EXEC supported method of replacing task's stack      (V37)

   SYNOPSIS
    StackSwap(newStack)
              A0

    VOID StackSwap(struct StackSwapStruct *);

   FUNCTION
    This function will, in an EXEC supported manner, swap the
    stack of your task with the given values in StackSwap.
    The StackSwapStruct structure will then contain the values
    of the old stack such that the old stack can be restored.
    This function is new in V37.

   NOTE
    If you do a stack swap, only the new stack is set up.
    This function does not copy the stack or do anything else
    other than set up the new stack for the task.  It is
    generally required that you restore your stack before
    exiting.

   INPUTS
    newStack - A structure that contains the values for the
        new upper and lower stack bounds and the new stack
        pointer.  This structure will have its values
        replaced by those in you task such that you can
        restore the stack later.

   RESULTS
    newStack - The structure will now contain the old stack.
        This means that StackSwap(foo); StackSwap(foo);
        will effectively do nothing.

   SEE ALSO
    AddTask, RemTask, exec/tasks.h

 exec.library/SumKickData                             exec.library/SumKickData

   NAME
    SumKickData -- compute the checksum for the Kickstart delta list

   SYNOPSIS
    checksum = SumKickData()
    D0

    ULONG SumKickData(void);

   FUNCTION
    The Amiga system has some ROM (or Kickstart) resident code that
    provides the basic functions for the machine.  This code is
    unchangeable by the system software.  This function is part of a
    support system to modify parts of the ROM.

    The ROM code is linked together at run time via ROMTags (also known
    as Resident structures, defined in exec/resident.h).  These tags tell
    Exec's low level boot code what subsystems exist in which regions of
    memory.  The current list of ROMTags is contained in the ResModules
    field of ExecBase.  By default this list contains any ROMTags found
    in the address ranges $F80000-$FFFFFF and $F00000-$F7FFFF.

    There is also a facility to selectively add or replace modules to the
    ROMTag list.  These modules can exist in RAM, and the memory they
    occupy will be deleted from the memory free list during the boot
    process.  SumKickData() plays an important role in this run-time
    modification of the ROMTag array.

    Three variables in ExecBase are used in changing the ROMTag array:
    KickMemPtr, KickTagPtr, and KickCheckSum. KickMemPtr points to a
    linked list of MemEntry structures. The memory that these MemEntry
    structures reference will be allocated (via AllocAbs) at boot time.
    The MemEntry structure itself must also be in the list.

    KickTagPtr points to a long-word array of the same format as the
    ResModules array.  The array has a series of pointers to ROMTag
    structures.  The array is either NULL terminated, or will have an
    entry with the most significant bit (bit 31) set.  The most
    significant bit being set says that this is a link to another
    long-word array of ROMTag entries.  This new array's address can be
    found by clearing bit 31.

    KickCheckSum has the result of SumKickData().  It is the checksum of
    both the KickMemPtr structure and the KickTagPtr arrays.  If the
    checksum does not compute correctly then both KickMemPtr and
    KickTagPtr will be ignored.

    If all the memory referenced by KickMemPtr can't be allocated then
    KickTagPtr will be ignored.

    There is one more important caveat about adding ROMTags. All this
    ROMTag magic is run very early on in the system -- before expansion
    memory is added to the system. Therefore any memory in this
    additional ROMTag area must be addressable at this time. This means
    that your ROMTag code, MemEntry structures, and resident arrays
    cannot be in expansion memory.  There are two regions of memory that
    are acceptable:  one is chip memory, and the other is "Ranger" memory
    (memory in the range between $C00000-$D80000).

    Remember that changing an existing ROMTag entry falls into the
    "heavy magic" category -- be very careful when doing it.  The odd are
    that you will blow yourself out of the water.

   NOTE
    SumKickData was introduced in the 1.2 release

   RESULT
    Value to be stuffed into ExecBase->KickCheckSum.

   WARNING
    After writing to KickCheckSum, you should push the data cache.
    This prevents potential problems with large copyback style caches.
    A call to CacheClearU will do fine.

   SEE ALSO
    InitResident, FindResident

 exec.library/SumLibrary                               exec.library/SumLibrary

   NAME
    SumLibrary -- compute and check the checksum on a library

   SYNOPSIS
    SumLibrary(library)
           A1

    void SumLibrary(struct Library *);

   FUNCTION
    SumLibrary computes a new checksum on a library.  It can also be
    used to check an old checksum.	If an old checksum does not match,
    and the library has not been marked as changed, then the system
    will call Alert().

    This call could also be periodically made by some future
    system-checking task.

   INPUTS
    library - a pointer to the library to be changed

   NOTE
    An alert will occur if the checksum fails.

   SEE ALSO
    SetFunction

 exec.library/SuperState                               exec.library/SuperState

   NAME
    SuperState -- enter supervisor state with user stack

   SYNOPSIS
    oldSysStack = SuperState()
    D0

    APTR SuperState(void);

   FUNCTION
    Enter supervisor mode while running on the user's stack. The user
    still has access to user stack variables.  Be careful though, the
    user stack must be large enough to accommodate space for all
    interrupt data -- this includes all possible nesting of interrupts.
    This function does nothing when called from supervisor state.

   RESULTS
    oldSysStack - system stack pointer; save this.	It will come in
              handy when you return to user state.  If the system
              is already in supervisor mode, oldSysStack is zero.

   SEE ALSO
    UserState/Supervisor

 exec.library/Supervisor                               exec.library/Supervisor

   NAME
    Supervisor -- trap to a short supervisor mode function

   SYNOPSIS
    result = Supervisor(userFunc)
    Rx                   A5

    ULONG Supervisor(void *);

   FUNCTION
    Allow a normal user-mode program to execute a short assembly language
    function in the supervisor mode of the processor.  Supervisor() does
    not modify or save registers; the user function has full access to the
    register set.   All rules that apply to interrupt code must be
    followed.  In addition, no system calls are permitted.  The function
    must end with an RTE instruction.

   EXAMPLE
        ;Obtain the Exception Vector base.  68010 or greater only!
        MOVECtrap:	movec.l	VBR,d0	;$4e7a,$0801
                rte

   INPUTS
    userFunc - A pointer to a short assembly language function ending
           in RTE.  The function has full access to the register set.

   RESULTS
    result   - Whatever values the userFunc left in the registers.

   SEE ALSO
    SuperState,UserState

 exec.library/TypeOfMem                                 exec.library/TypeOfMem

   NAME
    TypeOfMem -- determine attributes of a given memory address

   SYNOPSIS
    attributes = TypeOfMem(address)
    D0		       A1

    ULONG TypeOfMem(void *);

   FUNCTION
    Given a RAM memory address, search the system memory lists and
    return its memory attributes.  The memory attributes are similar to
    those specified when the memory was first allocated: (eg. MEMF_CHIP
    and MEMF_FAST).

    This function is usually used to determine if a particular block of
    memory is within CHIP space.

    If the address is not in known-space, a zero will be returned.
    (Anything that is not RAM, like the ROM or expansion area, will
    return zero.  Also the first few bytes of a memory area are used up
    by the MemHeader.)

   INPUT
    address - a memory address

   RESULT
    attributes - a long word of memory attribute flags.
    If the address is not in known RAM, zero is returned.

   SEE ALSO
    AllocMem()

 exec.library/UserState                                 exec.library/UserState

   NAME
    UserState -- return to user state with user stack

   SYNOPSIS
    UserState(sysStack)
          D0

    void UserState(APTR);

   FUNCTION
    Return to user state with user stack, from supervisor state with
    user stack.  This function is normally used in conjunction with the
    SuperState function above.

    This function must not be called from the user state.

   INPUT
    sysStack - supervisor stack pointer

   BUGS
    This function is broken in V33/34 Kickstart.  Fixed in V1.31 setpatch.

   SEE ALSO
    SuperState/Supervisor

 exec.library/Vacate                                       exec.library/Vacate

   NAME
    Vacate -- release a message lock (semaphore)

   SYNOPSIS
    Vacate(semaphore)
           A0

    void Vacate(struct Semaphore *);

   FUNCTION
    This function releases a previously locked semaphore (see
    the Procure() function).
    If another task is waiting for the semaphore, its bidMessage
    will be sent to its reply port.

   INPUT
    semaphore - the semaport message port representing the
    semaphore to be freed.

   BUGS
    Procure() and Vacate() do not have proven reliability.

   SEE ALSO
    Procure

 exec.library/Wait                                           exec.library/Wait

   NAME
    Wait -- wait for one or more signals

   SYNOPSIS
    signals = Wait(signalSet)
    D0	       D0

    ULONG Wait(ULONG);

   FUNCTION
    This function will cause the current task to suspend waiting for
    one or more signals.  When one or more of the specified signals
    occurs, the task will return to the ready state, and those signals
    will be cleared.

    If a signal occurred prior to calling Wait(), the wait condition will
    be immediately satisfied, and the task will continue to run without
    delay.

   CAUTION
    This function cannot be called while in supervisor mode or
    interrupts!  This function will break the action of a Forbid() or
    Disable() call.

   INPUT
    signalSet - The set of signals for which to wait.
            Each bit represents a particular signal.

   RESULTS
    signals - the set of signals that were active

 exec.library/WaitIO                                       exec.library/WaitIO

   NAME
    WaitIO -- wait for completion of an I/O request

   SYNOPSIS
    error = WaitIO(iORequest)
    D0	       A1

    BYTE WaitIO(struct IORequest *);

   FUNCTION
    This function waits for the specified I/O request to complete, then
    removes it from the replyport.	If the I/O has already completed,
    this function will return immediately.

    This function should be used with care, as it does not return until
    the I/O request completes; if the I/O never completes, this
    function will never return, and your task will hang.  If this
    situation is a possibility, it is safer to use the Wait() function.
    Wait() will return return when any of a specified set of signal is
    received.  This is how I/O timeouts can be properly handled.

   WARNING
    If this IORequest was "Quick" or otherwise finished BEFORE this
    call, this function drops though immediately, with no call to
    Wait().  A side effect is that the signal bit related the port may
    remain set.  Expect this.

    When removing a known complete IORequest from a port, WaitIO() is the
    preferred method.  A simple Remove() would require a Disable/Enable
    pair!

   INPUTS
    iORequest - pointer to an I/O request block

   RESULTS
    error - zero if successful, else an error is returned
        (a sign extended copy of io_Error).

   SEE ALSO
    DoIO, SendIO, CheckIO, AbortIO

 exec.library/WaitPort                                   exec.library/WaitPort

   NAME
    WaitPort -- wait for a given port to be non-empty

   SYNOPSIS
    message = WaitPort(port)
    D0		   A0

    struct Message *WaitPort(struct MsgPort *);

   FUNCTION
    This function waits for the given port to become non-empty.  If
    necessary, the Wait() function will be called to wait for the port
    signal.  If a message is already present at the port, this function
    will return immediately.  The return value is always a pointer to
    the first message queued (but it is not removed from the queue).

   CAUTION
    More than one message may be at the port when this returns.  It is
    proper to call the GetMsg() function in a loop until all messages
    have been handled, then wait for more to arrive.

    To wait for more than one port, combine the signal bits from each
    port into one call to the Wait() function, then use a GetMsg() loop
    to collect any and all messages.  It is possible to get a signal
    for a port WITHOUT a message showing up.  Plan for this.

   INPUT
    port - a pointer to the message port

   RETURN
    message - a pointer to the first available message

   SEE ALSO
    GetMsg


Text_Autodocs/layers.doc

TABLE OF CONTENTS

layers.library/BeginUpdate
layers.library/BehindLayer
layers.library/CreateBehindHookLayer
layers.library/CreateBehindLayer
layers.library/CreateUpfrontHookLayer
layers.library/CreateUpfrontLayer
layers.library/DeleteLayer
layers.library/DisposeLayerInfo
layers.library/EndUpdate
layers.library/FattenLayerInfo
layers.library/InitLayers
layers.library/InstallClipRegion
layers.library/InstallLayerHook
layers.library/LockLayer
layers.library/LockLayerInfo
layers.library/LockLayers
layers.library/MoveLayer
layers.library/MoveLayerInFrontOf
layers.library/MoveSizeLayer
layers.library/NewLayerInfo
layers.library/ScrollLayer
layers.library/SizeLayer
layers.library/SwapBitsRastPortClipRect
layers.library/ThinLayerInfo
layers.library/UnlockLayer
layers.library/UnlockLayerInfo
layers.library/UnlockLayers
layers.library/UpfrontLayer
layers.library/WhichLayer
 layers.library/BeginUpdate                         layers.library/BeginUpdate

    NAME
    BeginUpdate -- Prepare to repair damaged layer.

    SYNOPSIS
    result = BeginUpdate( l )
    d0                    a0

    LONG BeginUpdate( struct Layer *);

    FUNCTION
    Convert damage list to ClipRect list and swap in for
    programmer to redraw through. This routine simulates
    the ROM library environment. The idea is to only render in the
    "damaged" areas, saving time over redrawing all of the layer.
    The layer is locked against changes made by the layer library.

    INPUTS
    l - pointer to a layer

    RESULTS
    result - TRUE if damage list converted to ClipRect list sucessfully.
             FALSE if list conversion aborted. (probably out of memory)

    BUGS
    If BeginUpdate returns FALSE, programmer must abort the attempt to
    refresh this layer and instead call EndUpdate( l, FALSE ) to restore
    original ClipRect and damage list.

    SEE ALSO
    EndUpdate, graphics/layers.h, graphics/clip.h

 layers.library/BehindLayer                         layers.library/BehindLayer

    NAME
    BehindLayer -- Put layer behind other layers.

    SYNOPSIS
    result = BehindLayer( dummy, l )
    d0                    a0     a1

    LONG BehindLayer( LONG, struct Layer *);

    FUNCTION
    Move this layer to the most behind position swapping bits
    in and out of the display with other layers.
    If other layers are REFRESH then collect their damage lists and
    set the LAYERREFRESH bit in the Flags fields of those layers that
    may be revealed.  If this layer is a backdrop layer then
    put this layer behind all other backdrop layers.
    If this layer is NOT a backdrop layer then put in front of the
    top backdrop layer and behind all other layers.

    Note: this operation may generate refresh events in other layers
       associated with this layer's Layer_Info structure.

    INPUTS
    dummy - unused
    l - pointer to a layer

    RESULTS
    result - TRUE    if operation successful
             FALSE   if operation unsuccessful (probably out of memory)

    BUGS

    SEE ALSO
       graphics/layers.h, graphics/clip.h

 layers.library/CreateBehindHookLayer     layers.library/CreateBehindHookLayer

    NAME                                                              (V36)
    CreateBehindHookLayer -- Create a new layer behind all existing layers,
                             using supplied callback BackFill hook.

    SYNOPSIS
    result = CreateBehindHookLayer(li,bm,x0,y0,x1,y1,flags,hook,[,bm2])
    d0                             a0 a1 d0 d1 d2 d3 d4    a3   [ a2 ]

    struct Layer *CreateBehindHookLayer(struct Layer_Info *, struct BitMap *,
        LONG, LONG, LONG, LONG, LONG, struct Hook *, ... );

    FUNCTION
    Create a new Layer of position and size (x0,y0)->(x1,y1)
    Make this layer of type found in flags.
    Install Layer->BackFill callback Hook.
    If SuperBitMap, use bm2 as pointer to real SuperBitMap,
    and copy contents of Superbitmap into display layer.
    If this layer is a backdrop layer then place it behind all
    other layers including other backdrop layers. If this is
    not a backdrop layer then place it behind all nonbackdrop
    layers.

    Note: when using SUPERBITMAP, you should also set LAYERSMART flag.

    INPUTS
    li - pointer to LayerInfo structure
    bm - pointer to common BitMap used by all Layers
    x0,y0 - upper left hand corner of layer
    x1,y1 - lower right hand corner of layer
    flags - various types of layers supported as bit sets.
            (for bit definitions, see graphics/layers.h )
    hook -  Layer->BackFill callback Hook which will be called
            with object == (struct RastPort *) result->RastPort
            and message == [ (Layer *) layer, (struct Rectangle) bounds,
                           (WORD) offsetx, (WORD) offsety ]
    bm2 - pointer to optional Super BitMap

    RESULTS
    result - pointer to Layer structure if successful
             NULL if not successful

    BUGS

    SEE ALSO
    DeleteLayer, graphics/layers.h, graphics/clip.h, graphics/gfx.h
    utility/hooks.h

 layers.library/CreateBehindLayer             layers.library/CreateBehindLayer

    NAME
    CreateBehindLayer -- Create a new layer behind all existing layers.

    SYNOPSIS
    result = CreateBehindLayer(li,bm,x0,y0,x1,y1,flags [,bm2])
    d0                         a0 a1 d0 d1 d2 d3   d4  [ a2 ]

    struct Layer *CreateBehindLayer(struct Layer_Info *, struct BitMap *,
        LONG, LONG, LONG, LONG, LONG, ... );

    FUNCTION
    Create a new Layer of position and size (x0,y0)->(x1,y1)
    Make this layer of type found in flags.
    If SuperBitMap, use bm2 as pointer to real SuperBitMap,
    and copy contents of Superbitmap into display layer.
    If this layer is a backdrop layer then place it behind all
    other layers including other backdrop layers. If this is
    not a backdrop layer then place it behind all nonbackdrop
    layers.

    Note: when using SUPERBITMAP, you should also set LAYERSMART flag.

    INPUTS
    li - pointer to LayerInfo structure
    bm - pointer to common BitMap used by all Layers
    x0,y0 - upper left hand corner of layer
    x1,y1 - lower right hand corner of layer
    flags - various types of layers supported as bit sets.
            (for bit definitions, see graphics/layers.h )
    bm2 - pointer to optional Super BitMap

    RESULTS
    result - pointer to Layer structure if successful
             NULL if not successful

    BUGS

    SEE ALSO
    DeleteLayer, graphics/layers.h, graphics/clip.h, graphics/gfx.h

 layers.library/CreateUpfrontHookLayer   layers.library/CreateUpfrontHookLayer

    NAME                                                              (V36)
    CreateUpfrontHookLayer -- Create a new layer on top of existing layers,
                              using supplied callback BackFill hook.

    SYNOPSIS
    result = CreateUpfrontHookLayer(li,bm,x0,y0,x1,y1,flags,hook,[,bm2])
    d0                              a0 a1 d0 d1 d2 d3   d4  a3   [ a2 ]

    struct Layer *CreateUpfrontHookLayer(struct Layer_Info *, struct BitMap *,
        LONG, LONG, LONG, LONG, LONG, struct Hook *, ... );

    FUNCTION
    Create a new Layer of position and size (x0,y0)->(x1,y1)
    and place it on top of all other layers.
    Make this layer of type found in flags
    Install Layer->BackFill callback hook.
    if SuperBitMap, use bm2 as pointer to real SuperBitMap.
    and copy contents of Superbitmap into display layer.

    Note: when using SUPERBITMAP, you should also set LAYERSMART flag.

    INPUTS
    li - pointer to LayerInfo structure
    bm - pointer to common BitMap used by all Layers
    x0,y0 - upper left hand corner of layer
    x1,y1 - lower right hand corner of layer
    flags - various types of layers supported as bit sets.
    hook -  Layer->BackFill callback Hook which will be called
            with object == (struct RastPort *) result->RastPort
            and message == [ (Layer *) layer, (struct Rectangle) bounds,
                           (WORD) offsetx, (WORD) offsety ]
    bm2 - pointer to optional Super BitMap

    RESULTS
    result - pointer to Layer structure if successful
             NULL if not successful

    BUGS

    SEE ALSO
       DeleteLayer, graphics/layers.h, graphics/clip.h, graphics/gfx.h
    utility/hooks.h

 layers.library/CreateUpfrontLayer           layers.library/CreateUpfrontLayer

    NAME
    CreateUpfrontLayer -- Create a new layer on top of existing layers.

    SYNOPSIS
    result = CreateUpfrontLayer(li,bm,x0,y0,x1,y1,flags [,bm2])
    d0                          a0 a1 d0 d1 d2 d3   d4  [ a2 ]

    struct Layer *CreateUpfrontLayer(struct Layer_Info *, struct BitMap *,
        LONG, LONG, LONG, LONG, LONG, ... );

    FUNCTION
    Create a new Layer of position and size (x0,y0)->(x1,y1)
    and place it on top of all other layers.
    Make this layer of type found in flags
    if SuperBitMap, use bm2 as pointer to real SuperBitMap.
    and copy contents of Superbitmap into display layer.

    Note: when using SUPERBITMAP, you should also set LAYERSMART flag.

    INPUTS
    li - pointer to LayerInfo structure
    bm - pointer to common BitMap used by all Layers
    x0,y0 - upper left hand corner of layer
    x1,y1 - lower right hand corner of layer
    flags - various types of layers supported as bit sets.
    bm2 - pointer to optional Super BitMap

    RESULTS
    result - pointer to Layer structure if successful
             NULL if not successful

    BUGS

    SEE ALSO
       DeleteLayer, graphics/layers.h, graphics/clip.h, graphics/gfx.h

 layers.library/DeleteLayer                         layers.library/DeleteLayer

    NAME
    DeleteLayer -- delete layer from layer list.

    SYNOPSIS
    result = DeleteLayer( dummy, l )
    d0                    a0,    a1

    LONG DeleteLayer( LONG, struct Layer *);

    FUNCTION
    Remove this layer from the list of layers.  Release memory
    associated with it.  Restore other layers that may have been
    obscured by it.  Trigger refresh in those that may need it.
    If this is a superbitmap layer make sure SuperBitMap is current.
    The SuperBitMap is not removed from the system but is available
    for program use even though the rest of the layer information has
    been deallocated.

    INPUTS
    dummy - unused
    l - pointer to a layer

    RESULTS
    result - TRUE if this layer successfully deleted from the system
             FALSE if layer not deleted. (probably out of memory )

    BUGS

    SEE ALSO
    graphics/layers.h, graphics/clip.h

 layers.library/DisposeLayerInfo               layers.library/DisposeLayerInfo

    NAME
    DisposeLayerInfo -- Return all memory for LayerInfo to memory pool

    SYNOPSIS
    DisposeLayerInfo( li )
                      a0

    void DisposeLayerInfo( struct Layer_Info *);

    FUNCTION
    return LayerInfo and any other memory attached to this LayerInfo
    to memory allocator.

    Note: if you wish to delete the layers associated with this Layer_Info
        structure, remember to call DeleteLayer() for each of the layers
        before calling DisposeLayerInfo().

    INPUTS
    li - pointer to LayerInfo structure

    EXAMPLE

    -- delete the layers associated this Layer_Info structure --

    DeleteLayer(li,simple_layer);
    DeleteLayer(li,smart_layer);

    -- see documentation on DeleteLayer about deleting SuperBitMap layers --
    my_super_bitmap_ptr = super_layer->SuperBitMap;
    DeleteLayer(li,super_layer);

    -- now dispose of the Layer_Info structure itself --
    DisposeLayerInfo(li);

    BUGS

    SEE ALSO
    DeleteLayer, graphics/layers.h

 layers.library/EndUpdate                             layers.library/EndUpdate

    NAME
    EndUpdate -- remove damage list and restore state of layer to normal.

    SYNOPSIS
    EndUpdate( l, flag )
               a0  d0

    void EndUpdate( struct Layer *, UWORD);

    FUNCTION
    After the programmer has redrawn his picture he calls this
    routine to restore the ClipRects to point to his standard
    layer tiling. The layer is then unlocked for access by the
    layer library.

    Note: use flag = FALSE if you are only making a partial update.
        You may use the other region functions (graphics functions such as
        OrRectRegion, AndRectRegion, and XorRectRegion ) to clip adjust
        the DamageList to reflect a partial update.

    INPUTS
    l - pointer to a layer
    flag - use TRUE if update was completed. The damage list is cleared.
           use FALSE if update not complete. The damage list is retained.

    EXAMPLE

    -- begin update for first part of two-part refresh --
    BeginUpdate(my_layer);

    -- do some refresh, but not all --
    my_partial_refresh_routine(my_layer);

    -- end update, false (not completely done refreshing yet) --
    EndUpdate(my_layer, FALSE);

    -- begin update for last part of refresh --
    BeginUpdate(my_layer);

    -- do rest of refresh --
    my_complete_refresh_routine(my_layer);

    -- end update, true (completely done refreshing now) --
    EndUpdate(my_layer, TRUE);

    BUGS

    SEE ALSO
    BeginUpdate, graphics/layers.h, graphics/clip.h

 layers.library/FattenLayerInfo                 layers.library/FattenLayerInfo

    NAME
    FattenLayerInfo -- convert 1.0 LayerInfo to 1.1 LayerInfo
    OBSOLETE OBSOLETE OBSOLETE OBSOLETE OBSOLETE

    SYNOPSIS
    OBSOLETE OBSOLETE OBSOLETE OBSOLETE OBSOLETE
    FattenLayerInfo( li )
                     a0

    LONG FattenLayerInfo( struct Layer_Info *);
    OBSOLETE OBSOLETE OBSOLETE OBSOLETE OBSOLETE

    FUNCTION
    V1.1 software and any later releases need to have more info in the
    Layer_Info structure. To do this in a 1.0 supportable manner requires
    allocation and deallocation of the memory whenever most
    layer library functions are called.  To prevent unnecessary
    allocation/deallocation FattenLayerInfo will preallocate the
    necessary data structures and fake out the layer library into
    thinking it has a LayerInfo gotten from NewLayerInfo.
    NewLayerInfo is the approved method for getting this structure.
    When a program needs to give up the LayerInfo structure it
    must call ThinLayerInfo before freeing the memory. ThinLayerInfo
    is not necessary if New/DisposeLayerInfo are used however.

    INPUTS
    li - pointer to LayerInfo structure

    BUGS

    SEE ALSO

    NewLayerInfo, ThinLayerInfo, DisposeLayerInfo, graphics/layers.h

 layers.library/InitLayers                           layers.library/InitLayers

    NAME
    InitLayers -- Initialize Layer_Info structure
    OBSOLETE OBSOLETE OBSOLETE OBSOLETE OBSOLETE

    SYNOPSIS
    OBSOLETE OBSOLETE OBSOLETE OBSOLETE OBSOLETE
    InitLayers( li )
                a0

    void InitLayers( struct Layer_Info *);
    OBSOLETE OBSOLETE OBSOLETE OBSOLETE OBSOLETE

    FUNCTION
    Initialize Layer_Info structure in preparation to use
    other layer operations on this list of layers.
    Make the Layers unlocked (open), available to layer operations.

    INPUTS
    li - pointer to LayerInfo structure

    BUGS

    SEE ALSO
    NewLayerInfo, DisposeLayerInfo, graphics/layers.h

 layers.library/InstallClipRegion             layers.library/InstallClipRegion

    NAME
    InstallClipRegion -- Install clip region in layer

    SYNOPSIS
    oldclipregion = InstallClipRegion( l,  region )
    d0                                 a0  a1

    struct Region *InstallClipRegion( struct Layer *, struct Region *);

    FUNCTION
    Installs a transparent Clip region in the layer. All
    subsequent graphics calls will be clipped to this region.
    You MUST remember to call InstallClipRegion(l,NULL) before
    calling DeleteLayer(l) or the Intuition function CloseWindow()
     if you have installed a non-NULL ClipRegion in l.

    INPUTS
    l - pointer to a layer
    region - pointer to a region

    RESULTS
    oldclipregion - The pointer to the previous ClipRegion that
        was installed. Returns NULL if no previous ClipRegion installed.

        Note: If the system runs out of memory while computing the
            resulting ClipRects the LAYERS_CLIPRECTS_LOST bit will
            be set in l->Flags.

    BUGS
    If the system runs out of memory during normal layer operations,
    the ClipRect list may get swept away and not restored.
    As soon as there is enough memory and the layer library
    gets called again the ClipRect list will be rebuilt.

    SEE ALSO
    BeginUpdate EndUpdate,
    graphics/layers.h, graphics/clip.h, graphics/regions.h

 layers.library/InstallLayerHook               layers.library/InstallLayerHook

    NAME                                                              (V36)
    InstallLayerHook -- safely install a new Layer->BackFill hook.

    SYNOPSIS
    oldhook = InstallLayerHook( layer, hook )
    d0                          a0     a1

    struct Hook *InstallLayerHook( struct Layer *, struct Hook *);

    FUNCTION
    Installs a new Layer->Backfill Hook, waiting until it is safe to do
    so. Locks the layer while substituting the new Hook and removing the
    old one. If a new Hook is not provided, will install the default layer
    BackFill Hook.

    INPUTS
    layer - pointer to the layer in which to install the Backfill Hook.
    hook -  pointer to layer callback Hook which will be called
            with object == (struct RastPort *) result->RastPort
            and message == [ (Layer *) layer, (struct Rectangle) bounds,
                           (WORD) offsetx, (WORD) offsety ]

            This hook should fill the Rectangle in the RastPort
            with the BackFill pattern appropriate for offset x/y.

            If this hook pointer is NULL, the function installs
            the "default" Layers BackFill Hook into this Layer.

    RESULTS
    oldhook - pointer to the Layer->BackFill Hook that was previously
              active.

    BUGS

    SEE ALSO
    graphics/clip.h utility/hooks.h

 layers.library/LockLayer                             layers.library/LockLayer

    NAME
    LockLayer -- Lock layer to make changes to ClipRects.

    SYNOPSIS
    LockLayer( dummy, l )
               a0     a1

    void LockLayer( LONG, struct Layer *);

    FUNCTION
    Make this layer unavailable for other tasks to use.
    If another task is already using this layer then wait for
    it to complete and then reserve the layer for your own use.
    (this function does the same thing as graphics.library/LockLayerRom)

    Note: if you wish to lock MORE THAN ONE layer at a time, you
        must call LockLayerInfo() before locking those layers and
        then call UnlockLayerInfo() when you have finished. This
        is to prevent system "deadlocks".

    Further Note: while you hold the lock on a layer, Intuition will block
        on operations such as windowsizing, dragging, menus, and depth
        arranging windows in this layer's screen.  It is recommended that
        YOU do not make Intuition function calls while the layer is locked.

    INPUTS
    dummy - unused
    l - pointer to a layer

    BUGS

    SEE ALSO
    UnlockLayer, LockLayerInfo, UnlockLayerInfo,
    graphics.library/LockLayerRom, graphics/layers.h, graphics/clip.h

 layers.library/LockLayerInfo                     layers.library/LockLayerInfo

    NAME
    LockLayerInfo -- Lock the LayerInfo structure.

    SYNOPSIS
    LockLayerInfo( li )
                   a0

    void LockLayerInfo( struct Layer_Info *);

    FUNCTION
    Before doing an operation that requires the LayerInfo
    structure, make sure that no other task is also using the
    LayerInfo structure.  LockLayerInfo() returns when the
    LayerInfo belongs to this task.  There should be
    an UnlockLayerInfo for every LockLayerInfo.

    Note: All layer routines presently LockLayerInfo() when they
    start up and UnlockLayerInfo() as they exit.  Programmers
    will need to use these Lock/Unlock routines if they wish
    to do something with the LayerStructure that is not
    supported by the layer library.

    INPUTS
    li - pointer to Layer_Info structure

    BUGS

    SEE ALSO
    UnlockLayerInfo, graphics/layers.h

 layers.library/LockLayers                           layers.library/LockLayers

    NAME
    LockLayers -- lock all layers from graphics output.

    SYNOPSIS
    LockLayers( li )
                a0

    void LockLayers( struct Layer_Info *);

    FUNCTION
    First calls LockLayerInfo()
    Make all layers in this layer list locked.

    INPUTS
    li - pointer to Layer_Info structure

    BUGS

    SEE ALSO
    LockLayer, LockLayerInfo, graphics/layers.h

 layers.library/MoveLayer                             layers.library/MoveLayer

    NAME
    MoveLayer -- Move layer to new position in BitMap.

    SYNOPSIS
    result = MoveLayer( dummy, l, dx, dy )
    d0                  a0     a1 d0  d1

    LONG MoveLayer( LONG, struct Layer *, LONG, LONG);

    FUNCTION
    Move this layer to new position in shared BitMap.
    If any refresh layers become revealed, collect damage and
    set REFRESH bit in layer Flags.

    INPUTS
    dummy - unused
    l - pointer to a nonbackdrop layer
    dx - delta to add to current x position
    dy - delta to add to current y position

    RETURNS
    result - TRUE if operation successful
             FALSE if failed (out of memory)

    BUGS
    May not handle (dx,dy) which attempts to move the layer ouside the
    layer's RastPort->BitMap bounds .

    SEE ALSO
    graphics/layers.h, graphics/clip.h

 layers.library/MoveLayerInFrontOf           layers.library/MoveLayerInFrontOf

    NAME
    MoveLayerInFrontOf -- Put layer in front of another layer.

    SYNOPSIS
    result = MoveLayerInFrontOf( layertomove, targetlayer )
                                    a0           a1

    LONG MoveLayerInFrontOf( struct Layer *, struct Layer *);

    FUNCTION
    Move this layer in front of target layer, swapping bits
    in and out of the display with other layers.
    If this is a refresh layer then collect damage list and
    set the LAYERREFRESH bit in layer->Flags if redraw required.

    Note: this operation may generate refresh events in other layers
        associated with this layer's Layer_Info structure.

    INPUTS
    layertomove - pointer to layer which should be moved
    targetlayer - pointer to target layer in front of which to move layer

    RESULTS
    result = TRUE    if operation successful
             FALSE   if operation unsuccessful (probably out of memory)

    BUGS

    SEE ALSO
    graphics/layers.h

 layers.library/MoveSizeLayer                     layers.library/MoveSizeLayer

    NAME                                                              (V36)
    MoveSizeLayer -- Position/Size layer

    SYNOPSIS
    result = MoveSizeLayer( layer, dx, dy, dw, dh )
    d0                      a0     d0  d1  d2  d3

    LONG MoveSizeLayer( struct Layer *, LONG, LONG, LONG, LONG);

    FUNCTION
    Change upperleft and lower right position of Layer.

    INPUTS
    dummy - unused
    l - pointer to a nonbackdrop layer
    dx,dy - change upper left corner by (dx,dy)
    dw,dy - change size by (dw,dh)

    RETURNS
    result - TRUE if operation successful
             FALSE if failed (due to out of memory)
             FALSE if failed (due to illegal layer->bounds)

    BUGS

    SEE ALSO
    graphics/layers.h, graphics/clip.h

 layers.library/NewLayerInfo                       layers.library/NewLayerInfo

    NAME
    NewLayerInfo -- Allocate and Initialize full Layer_Info structure.

    SYNOPSIS
    result = NewLayerInfo()
    d0

    struct Layer_Info *NewLayerInfo( void );

    FUNCTION
    Allocate memory required for full Layer_Info structure.
    Initialize Layer_Info structure in preparation to use
    other layer operations on this list of layers.
    Make the Layer_Info unlocked (open).

    INPUTS
    None

    RESULT
    result- pointer to Layer_Info structure if successful
            NULL if not enough memory

    BUGS

    SEE ALSO
    graphics/layers.h

 layers.library/ScrollLayer                         layers.library/ScrollLayer

    NAME
    ScrollLayer -- Scroll around in a superbitmap, translate coordinates
                      in non-superbitmap layer.

    SYNOPSIS
    ScrollLayer( dummy, l, dx, dy )
                 a0     a1 d0  d1

    void ScrollLayer( LONG, struct Layer *, LONG, LONG);

    FUNCTION
    For a SuperBitMap Layer:
    Update the SuperBitMap from the layer display, then copy bits
    between Layer and SuperBitMap to reposition layer over different
    portion of SuperBitMap.
    For nonSuperBitMap layers, all (x,y) pairs are adjusted by
    the scroll(x,y) value in the layer.  To cause (0,0) to actually
    be drawn at (3,10) use ScrollLayer(-3,-10). This can be useful
    along with InstallClipRegion to simulate Intuition GZZWindows
    without the overhead of an extra layer.

    INPUTS
    dummy - unused
    l - pointer to a layer
    dx - delta to add to current x scroll value
    dy - delta to add to current y scroll value

    BUGS
    May not handle (dx,dy) which attempts to move the layer ouside the
    layer's SuperBitMap bounds.

    SEE ALSO
    graphics/layers.h

 layers.library/SizeLayer                             layers.library/SizeLayer

    NAME
    SizeLayer -- Change the size of this nonbackdrop layer.

    SYNOPSIS
    result = SizeLayer( dummy, l, dx, dy )
    d0                  a0     a1 d0  d1

    LONG SizeLayer( LONG, struct Layer *, LONG, LONG);

    FUNCTION
    Change the size of this layer by (dx,dy). The lower right hand
    corner is extended to make room for the larger layer.
    If there is SuperBitMap for this layer then copy pixels into
    or out of the layer depending on whether the layer increases or
    decreases in size.  Collect damage list for those layers that may
    need to be refreshed if damage occurred.

    INPUTS
    dummy - unused
    l - pointer to a nonbackdrop layer
    dx - delta to add to current x size
    dy - delta to add to current y size

    RESULTS
    result - TRUE if operation successful
             FALSE if failed (out of memory)

    BUGS

    SEE ALSO
    graphics/layers.h, graphics/clip.h

 layers.library/SwapBitsRastPortClipRectayers.library/SwapBitsRastPortClipRect

    NAME
    SwapBitsRastPortClipRect -- Swap bits between common bitmap
                                and obscured ClipRect

    SYNOPSIS
    SwapBitsRastPortClipRect( rp, cr )
                              a0  a1

    void SwapBitsRastPortClipRect( struct RastPort *, struct ClipRect *);

    FUNCTION
    Support routine useful for those that need to do some
    operations not done by the layer library.  Allows programmer
    to swap the contents of a small BitMap with a subsection of
    the display. This is accomplished without using extra memory.
    The bits in the display RastPort are exchanged with the
    bits in the ClipRect's BitMap.

    Note: the ClipRect structures which the layer library allocates are
    actually a little bigger than those described in the graphics/clip.h
    include file.  So be warned that it is not a good idea to have
    instances of cliprects in your code.

    INPUTS
    rp - pointer to rastport
    cr - pointer to cliprect to swap bits with

    NOTE
    Because the blit operation started by this function is done asynchronously,
    it is imperative that a WaitBlit() be performed before releasing or using
    the processor to modify any of the associated structures.

    BUGS

    SEE ALSO
    graphics/clip.h, graphics/rastport.h, graphics/clip.h

 layers.library/ThinLayerInfo                     layers.library/ThinLayerInfo

    NAME
    ThinLayerInfo -- convert 1.1 LayerInfo to 1.0 LayerInfo.
    OBSOLETE OBSOLETE OBSOLETE OBSOLETE OBSOLETE

    SYNOPSIS
    OBSOLETE OBSOLETE OBSOLETE OBSOLETE OBSOLETE
    ThinLayerInfo( li )
                   a0

    void ThinLayerInfo( struct Layer_Info *);
    OBSOLETE OBSOLETE OBSOLETE OBSOLETE OBSOLETE

    FUNCTION
    return the extra memory needed that was allocated with
    FattenLayerInfo. This is must be done prior to freeing
    the Layer_Info structure itself. V1.1 software should be
    using DisposeLayerInfo.

    INPUTS
    li - pointer to LayerInfo structure

    BUGS

    SEE ALSO
    DisposeLayerInfo, FattenLayerInfo, graphics/layers.h

 layers.library/UnlockLayer                         layers.library/UnlockLayer

    NAME
    UnlockLayer -- Unlock layer and allow graphics routines to use it.

    SYNOPSIS
    UnlockLayer( l )
                 a0

    void UnlockLayer( struct Layer *);

    FUNCTION
    When finished changing the ClipRects or whatever you were
    doing with this layer you must call UnlockLayer() to allow
    other tasks to proceed with graphic output to the layer.

    INPUTS
    l - pointer to a layer

    BUGS

    SEE ALSO
    graphics/layers.h, graphics/clip.h

 layers.library/UnlockLayerInfo                 layers.library/UnlockLayerInfo

    NAME
    UnlockLayerInfo -- Unlock the LayerInfo structure.

    SYNOPSIS
    UnlockLayerInfo( li )
                     a0

    void UnlockLayerInfo( struct Layer_Info *);

    FUNCTION
    After the operation is complete that required a LockLayerInfo,
    unlock the LayerInfo structure so that  other tasks may
    affect the layers.

    INPUTS
    li - pointer to the Layer_Info structure

     BUGS

     SEE ALSO
    LockLayerInfo, graphics/layers.h

 layers.library/UnlockLayers                       layers.library/UnlockLayers

    NAME
    UnlockLayers -- Unlock all layers from graphics output.
                    Restart graphics output to layers that have been waiting

    SYNOPSIS
    UnlockLayers( li )
                  a0

    void UnlockLayers( struct Layer_Info *);

    FUNCTION
    Make all layers in this layer list unlocked.
    Then call UnlockLayerInfo

    INPUTS
    li - pointer to the Layer_Info structure

    BUGS

    SEE ALSO
    LockLayers, UnlockLayer, graphics/layers.h

 layers.library/UpfrontLayer                       layers.library/UpfrontLayer

    NAME
    UpfrontLayer -- Put layer in front of all other layers.

    SYNOPSIS
    result = UpfrontLayer( dummy, l )
    d0                     a0     a1

    LONG UpfrontLayer( LONG, struct Layer *);

    FUNCTION
    Move this layer to the most upfront position swapping bits
    in and out of the display with other layers.
    If this is a refresh layer then collect damage list and
    set the LAYERREFRESH bit in layer->Flags if redraw required.
    By clearing the BACKDROP bit in the layers Flags you may
    bring a Backdrop layer up to the front of all other layers.

    Note: this operation may generate refresh events in other layers
       associated with this layer's Layer_Info structure.

    INPUTS
    dummy - unused
    l - pointer to a nonbackdrop layer

    RESULTS
    result - TRUE   if operation successful
             FALSE  if operation unsuccessful (probably out of memory)

    BUGS

    SEE ALSO
    graphics/layers.h

 layers.library/WhichLayer                           layers.library/WhichLayer

    NAME
    WhichLayer -- Which Layer is this point in?

    SYNOPSIS
    layer = WhichLayer( li, x, y )
    d0                  a0  d0 d1

    struct Layer *WhichLayer(struct Layer_Info*, WORD, WORD);

    FUNCTION
    Starting at the topmost layer check to see if this point (x,y)
        occurs in this layer.  If it does return the pointer to this
        layer. Return NULL if there is no layer at this point.

    INPUTS
    li  = pointer to LayerInfo structure
    (x,y) = coordinate in the BitMap

    RESULTS
    layer - pointer to the topmost layer that this point is in
            NULL if this point is not in a layer

    SEE ALSO
    graphics/layers.h


Text_Autodocs/translator.doc

TABLE OF CONTENTS

translator.library/Translate

translator.library/Translate                       translator.library/Translate

    NAME
    Translate -- Convert an English string into narrator device phonemes.

    SYNOPSIS
    rtnCode = Translate(inString, inLength, outBuffer, outLength)
    D0                  A0        D0        A1         D1

    LONG Translate( STRPTR inString, LONG inLength, STRPTR outBuffer,
        LONG outlen );

    FUNCTION
    The translate function converts an English string into
    a string of phonetic codes suitable as input to the
    narrator device.

    INPUTS
    inString - pointer to English string
    inLength - length of English string
    outBuffer - a char array which will hold the phonetic codes
    outLength - the length of the output array

    RESULTS
    rtnCode - zero if no error has occured.
        The only error that can occur is overflowing the outBuffer.
        If Translate() determines that an overflow will occur, it
        will stop the translation at a word boundary before the
        overflow happens.  If this occurs, rtnCode will be a
        negative number whose absolute value indicates where in
        inString Translate() stopped.  The user can then use the
        offset -rtnCode from the beginning of inString in a
        subsequent Translate() call to continue the translation.

    SEE ALSO
    narrator.device/CMD_WRITE


Text_Autodocs/expansion.doc

TABLE OF CONTENTS

expansion.library/AddBootNode
expansion.library/AddConfigDev
expansion.library/AddDosNode
expansion.library/AllocConfigDev
expansion.library/AllocExpansionMem
expansion.library/ConfigBoard
expansion.library/FindConfigDev
expansion.library/FreeConfigDev
expansion.library/FreeExpansionMem
expansion.library/GetCurrentBinding
expansion.library/MakeDosNode
expansion.library/ObtainConfigBinding
expansion.library/ReadExpansionByte
expansion.library/ReadExpansionRom
expansion.library/ReleaseConfigBinding
expansion.library/RemConfigDev
expansion.library/SetCurrentBinding
expansion.library/WriteExpansionByte
 expansion.library/AddBootNode                   expansion.library/AddBootNode

   NAME
    AddBootNode -- Add a BOOTNODE to the system (V36)

   SYNOPSIS
    ok = AddBootNode( bootPri, flags, deviceNode, configDev )
    D0		  D0	   D1	  A0	      A1

    BOOL AddBootNode( BYTE,ULONG,struct DeviceNode *,struct ConfigDev * );

   FUNCTION
    This function will do one of two things:

        1> If dos is running, add a new disk type device immediatly.
        2> If dos is not yet running, save information for later
           use by the system.

   FUNCTION
    This routine makes sure that your disk device (or a device
    that wants to be treated as if it was a disk...) will be
    entered into the system.  If the dos is already up and
    running, then it will be entered immediately.  If the dos
    has not yet been run then the data will be recorded, and the
    dos will get it later.

    We try and boot off of each device in turn, based on priority.
    Floppies have a hard-coded priority.

    There is only one additional piece of magic done by AddBootNode.
    If there is no executable code specified in the deviceNode
    structure (e.g. dn_SegList, dn_Handler, and dn_Task are all
    null) then the standard dos file handler is used for your
    device.

    Documentation note: a "task" as used here is a dos-task, not
    an exec-task.  A dos-task, in the strictest sense, is the
    address of an exec-style message port.	In general, it is
    a pointer to a process's pr_MsgPort field (e.g. a constant
    number of bytes after an exec task).

    Autoboot from an expansion card before DOS is running requires
    the card's ConfigDev structure.

    Pass a NULL ConfigDev pointer to create a non-bootable node.

   INPUTS
    bootPri -- a BYTE quantity with the boot priority for this disk.
        This priority is only for which disks should be looked at:
        the actual disk booted from will be the first disk with
        a valid boot block.  If no disk is found then the "bootme"
        hand will come up and the bootstrap code will wait for
        a floppy to be inserted.  Recommend priority assignments are:

        +5   -- unit zero for the floppy disk.	The floppy should
            always be highest priority to allow the user to
            abort out of a hard disk boot.
         0   -- the run of the mill hard disk
        -5   -- a "network" disk (local disks should take priority).
        -128 -- don't even bother to boot from this device.

    flags -- additional flag bits for the call:
        ADNF_STARTPROC (bit 0) -- start a handler process immediately.
        Normally the process is started only when the device node
        is first referenced.  This bit is meaningless if you
        have already specified a handler process (non-null dn_Task).

    deviceNode -- a legal DOS device node, properly initialized.
        Typically this will be the result of a MakeDosNode().
        Special cases may require a custom-built device node.

    configDev -- a valid board's ConfigDev stucture.  This is required
        for autoboot before DOS is running and if left NULL will
        result in an non-bootable node.

   RESULTS
    ok - non-zero everything went ok, zero if we ran out of memory
        or some other weirdness happened.

   NOTE
    This function eliminates the need to manually Enqueue a BOOTNODE
    onto an expansion.library list.  Be sure V36 expansion.library is
    available before calling this function!

   SEE ALSO
    AddDosNode

 expansion.library/AddConfigDev                 expansion.library/AddConfigDev

   NAME
    AddConfigDev - add a new ConfigDev structure to the system

   SYNOPSIS
    AddConfigDev( configDev )
                  A0

   FUNCTION
    (Not typically called by user code)

    This routine adds the specified ConfigDev structure to the
    list of Configuration Devices in the system.

   INPUTS
    configDev - a valid ConfigDev structure.

   RESULTS

   EXCEPTIONS

   SEE ALSO
    RemConfigDev

   BUGS

 expansion.library/AddDosNode                     expansion.library/AddDosNode

   NAME
    AddDosNode -- mount a disk to the system

   SYNOPSIS
    ok = AddDosNode( bootPri, flags, deviceNode )
    D0		 D0	  D1	 A0

    BOOL AddDosNode( BYTE,ULONG,struct DeviceNode *);

   FUNCTION
    This is the old (pre V36) function that works just like
    AddBootNode().  It should only be used if you *MUST* work
    in a 1.3 system and you don't need to autoboot.

   RESULTS
    ok - non-zero everything went ok, zero if we ran out of memory
        or some other weirdness happened.

   EXAMPLE
    /* enter a bootable disk into the system.  Start a file handler
    ** process immediately.
    */
    if(  AddDosNode( 0, ADNF_STARTPROC, MakeDosNode( paramPacket ) )  )
        ...AddDosNode ok...

   BUGS
    Before V36 Kickstart, no function existed to add BOOTNODES.
    If an older expansion.library is in use, driver code will need
    to manually construct a BootNode and Enqueue() it to eb_Mountlist.
    If you have a V36 or better expansion.library, your code should
    use AddBootNode().

   SEE ALSO
    MakeDosNode, AddBootNode

 expansion.library/AllocConfigDev             expansion.library/AllocConfigDev

   NAME
    AllocConfigDev - allocate a ConfigDev structure

   SYNOPSIS
    configDev = AllocConfigDev()
    D0

   FUNCTION
    This routine returns the address of a ConfigDev structure.
    It is provided so new fields can be added to the structure
    without breaking old, existing code.  The structure is cleared
    when it is returned to the user.

   INPUTS

   RESULTS
    configDev - either a valid ConfigDev structure or NULL.

   EXCEPTIONS

   SEE ALSO
    FreeConfigDev

   BUGS

 expansion.library/AllocExpansionMem       expansion.library/AllocExpansionMem

   NAME
    AllocExpansionMem - allocate expansion memory

   SYNOPSIS
    startSlot = AllocExpansionMem( numSlots, slotOffset )
    D0                             D0        D1

   FUNCTION
    (Not typically called by user code)

    This function allocates numslots of expansion space (each slot
    is E_SLOTSIZE bytes).  It returns the slot number of the
    start of the expansion memory.  The EC_MEMADDR macro may be
    used to convert this to a memory address.

    Boards that fit the expansion architecture have alignment
    rules.  Normally a board must be on a binary boundary of its
    size.  Four and Eight megabyte boards have special rules.
    User defined boards might have other special rules.

    If AllocExpansionMem() succeeds, the startSlot will satisfy
    the following equation:

        (startSlot - slotOffset) MOD slotAlign = 0

   INPUTS
    numSlots - the number of slots required.
    slotOffset - an offset from that boundary for startSlot.

   RESULTS
    startSlot - the slot number that was allocated, or -1 for error.

   EXAMPLES

        AllocExpansionMem( 2, 0 )

    Tries to allocate 2 slots on a two slot boundary.

        AllocExpansionMem( 64, 32 )

    This is the allocation rule for 4 meg boards.  It allocates
    4 megabytes (64 slots) on an odd 2 meg boundary.

   EXCEPTIONS

   SEE ALSO
    FreeExpansionMem

   BUGS

 expansion.library/ConfigBoard                   expansion.library/ConfigBoard

   NAME
    ConfigBoard - configure a board

   SYNOPSIS
    error = ConfigBoard( board, configDev )
    D0                   A0     A1

   FUNCTION
    This routine configures an expansion board.  The board
    will generally live at E_EXPANSIONBASE, but the base is
    passed as a parameter to allow future compatibility.
    The configDev parameter must be a valid configDev that
    has already had ReadExpansionRom() called on it.

    ConfigBoard will allocate expansion memory and place
    the board at its new address.  It will update configDev
    accordingly.  If there is not enough expansion memory
    for this board then an error will be returned.

   INPUTS
    board - the current address that the expansion board is
        responding.
    configDev - an initialized ConfigDev structure, returned
        by AllocConfigDev.

   RESULTS
    error - non-zero if there was a problem configuring this board
        (Can return EE_OK or EE_NOEXPANSION)

   SEE ALSO
    FreeConfigDev

 expansion.library/FindConfigDev               expansion.library/FindConfigDev

   NAME
    FindConfigDev - find a matching ConfigDev entry

   SYNOPSIS
    configDev = FindConfigDev( oldConfigDev, manufacturer, product )
    D0                         A0            D0            D1

   FUNCTION
    This routine searches the list of existing ConfigDev
    structures in the system and looks for one that has
    the specified manufacturer and product codes.

    If the oldConfigDev is NULL the the search is from the
    start of the list of configuration devices.  If it is
    not null then it searches from the first configuration
    device entry AFTER oldConfigDev.

    A code of -1 is treated as a wildcard -- e.g. it matches
    any manufacturer (or product)

   INPUTS
    oldConfigDev - a valid ConfigDev structure, or NULL to start
        from the start of the list.
    manufacturer - the manufacturer code being searched for, or
        -1 to ignore manufacturer numbers.
    product - the product code being searched for, or -1 to
        ignore product numbers.

   RESULTS
    configDev - the next ConfigDev entry that matches the
        manufacturer and product codes, or NULL if there
        are no more matches.

   EXCEPTIONS

   EXAMPLES
    /* to find all configdevs of the proper type */
    struct ConfigDev *cd = NULL;

    while( cd = FindConfigDev( cd, MANUFACTURER, PRODUCT ) ) {
        /* do something with the returned ConfigDev */
    }

   SEE ALSO

   BUGS

 expansion.library/FreeConfigDev               expansion.library/FreeConfigDev

   NAME
    FreeConfigDev - free a ConfigDev structure

   SYNOPSIS
    FreeConfigDev( configDev )
                   A0

   FUNCTION
    This routine frees a ConfigDev structure as returned by
    AllocConfigDev.

   INPUTS
    configDev - a valid ConfigDev structure.

   RESULTS

   EXCEPTIONS

   SEE ALSO
    AllocConfigDev

   BUGS

 expansion.library/FreeExpansionMem         expansion.library/FreeExpansionMem

   NAME
    FreeExpansionMem - allocate standard device expansion memory

   SYNOPSIS
    FreeExpansionMem( startSlot, numSlots )
                      D0         D1

   FUNCTION
    (Not typically called by user code)

    This function allocates numslots of expansion space (each slot
    is E_SLOTSIZE bytes).  It is the inverse function of
    AllocExpansionMem().

   INPUTS
    startSlot - the slot number that was allocated, or -1 for error.
    numSlots - the number of slots to be freed.

   RESULTS

   EXAMPLES

   EXCEPTIONS
    If the caller tries to free a slot that is already in the
    free list, FreeExpansionMem will Alert() (e.g. crash the
    system).

   SEE ALSO
    AllocExpansionMem

   BUGS

 expansion.library/GetCurrentBinding       expansion.library/GetCurrentBinding

   NAME
    GetCurrentBinding - sets static board configuration area

   SYNOPSIS
    actual = GetCurrentBinding( currentBinding, size )
                                A0              D0:16

   FUNCTION
    This function writes the contents of the "currentBinding"
    structure out of a private place.  It may be set via
    SetCurrentBinding().  This is really a kludge, but it is
    the only way to pass extra arguments to a newly configured
    device.

    A CurrentBinding structure has the name of the currently
    loaded file, the product string that was associated with
    this driver, and a pointer to the head of a singly linked
    list of ConfigDev structures (linked through the cd_NextCD
    field).

    Many devices may not need this information; they have hard
    coded into themselves their manufacture number.  It is
    recommended that you at least check that you can deal with
    the product code in the linked ConfigDev structures.

   INPUTS
    currentBinding - a pointer to a CurrentBinding structure

    size - The size of the user's binddriver structure.
        Do not pass in less than sizeof(struct CurrentBinding).

   RESULTS
    actual - the true size of a CurrentBinding structure is returned.

   SEE ALSO
    GetCurrentBinding

 expansion.library/MakeDosNode                   expansion.library/MakeDosNode

   NAME
    MakeDosNode -- construct dos data structures that a disk needs

   SYNOPSIS
    deviceNode = MakeDosNode( parameterPkt )
    D0			  A0

    struct DeviceNode * MakeDosNode( void * );

   FUNCTION
    This routine manufactures the data structures needed to enter
    a dos disk device into the system.  This consists of a DeviceNode,
    a FileSysStartupMsg, a disk environment vector, and up to two
    bcpl strings.  See the libraries/dosextens.h and
    libraries/filehandler.h include files for more information.

    MakeDosNode will allocate all the memory it needs, and then
    link the various structure together.  It will make sure all
    the structures are long-word aligned (as required by the DOS).
    It then returns the information to the user so he can
    change anything else that needs changing.  Typically he will
    then call AddDosNode() to enter the new device into the dos
    tables.

   INPUTS
    parameterPkt - a longword array containing all the information
        needed to initialize the data structures.  Normally I
        would have provided a structure for this, but the variable
        length of the packet caused problems.  The two strings are
        null terminated strings, like all other exec strings.

        longword	description
        --------	-----------
        0		string with dos handler name
        1		string with exec device name
        2		unit number (for OpenDevice)
        3		flags (for OpenDevice)
        4		# of longwords in rest of enviroment
        5-n 	file handler environment (see libraries/filehandler.h)

   RESULTS
    deviceNode - pointer to initialize device node structure, or
        null if there was not enough memory.  You may need to change
        certain fields before passing the DeviceNode to AddDosNode().

   EXAMPLES
    /* set up a 3.5" amiga format floppy drive for unit 1 */

    char execName[] = "trackdisk.device";
    char dosName[] = "df1";

    ULONG parmPkt[] = {
        (ULONG) dosName,
        (ULONG) execName,
        1,			/* unit number */
        0,			/* OpenDevice flags */

        /* here is the environment block */
        16, 		/* table upper bound */
        512>>2,		/* # longwords in a block */
        0,			/* sector origin -- unused */
        2,			/* number of surfaces */
        1,			/* secs per logical block -- leave as 1 */
        11, 		/* blocks per track */
        2,			/* reserved blocks -- 2 boot blocks */
        0,			/* ?? -- unused */
        0,			/* interleave */
        0,			/* lower cylinder */
        79, 		/* upper cylinder */
        5,			/* number of buffers */
        MEMF_CHIP,		/* type of memory for buffers */
        (~0 >> 1),          /* largest transfer size (largest signed #) */
        ~1, 		/* addmask */
        0,			/* boot priority */
        0x444f5300, 	/* dostype: 'DOS\0' */
    };

    struct Device Node *node, *MakeDosNode();

    node = MakeDosNode( parmPkt );

   SEE ALSO
    AddDosNode, libraries/dosextens.h, libraries/filehandler.h

 expansion.library/ObtainConfigBinding   expansion.library/ObtainConfigBinding

   NAME
    ObtainConfigBinding - try to get permission to bind drivers

   SYNOPSIS
    ObtainConfigBinding()

   FUNCTION
    ObtainConfigBinding gives permission to bind drivers to
    ConfigDev structures.  It exists so two drivers at once
    do not try and own the same ConfigDev structure.  This
    call will block until it is safe proceed.

    It is crucially important that people lock out others
    before loading new drivers.  Much of the data that is used
    to configure things is statically kept, and others need
    to be kept from using it.

    This call is built directly on Exec SignalSemaphore code
    (e.g. ObtainSemaphore).

   INPUTS

   RESULTS

   EXCEPTIONS

   SEE ALSO
    ReleaseConfigBinding()

   BUGS

 expansion.library/ReadExpansionByte       expansion.library/ReadExpansionByte

   NAME
    ReadExpansionByte - read a byte nybble by nybble.

   SYNOPSIS
    byte = ReadExpansionByte( board, offset )
    D0                        A0     D0

   FUNCTION
    (Not typically called by user code)

     ReadExpansionByte reads a byte from a new-style expansion
    board.  These boards have their readable data organized
    as a series of nybbles in memory.  This routine reads
    two nybbles and returns the byte value.

    In general, this routine will only be called by ReadExpansionRom.

    The offset is a byte offset, as if into a ExpansionRom structure.
    The actual memory address read will be four times larger.
    The macros EROFFSET and ECOFFSET are provided to help get
    these offsets from C.

   INPUTS
    board - a pointer to the base of a new style expansion board.
    offset - a logical offset from the board base

   RESULTS
    byte - a byte of data from the expansion board.

   EXAMPLES
    byte = ReadExpansionByte( cd->BoardAddr, EROFFSET( er_Type ) );
    ints = ReadExpansionByte( cd->BoardAddr, ECOFFSET( ec_Interrupt ) );

   SEE ALSO
    WriteExpansionByte, ReadExpansionRom

 expansion.library/ReadExpansionRom         expansion.library/ReadExpansionRom

   NAME
    ReadExpansionRom - read a boards configuration rom space

   SYNOPSIS
    error = ReadExpansionRom( board, configDev )
    D0                        A0     A1

   FUNCTION
    (Not typically called by user code)

    ReadExpansionRom reads a the rom portion of an expansion
    device in to cd_Rom portion of a ConfigDev structure.
    This routine knows how to detect whether or not there is
    actually a board there,

    In addition, the Rom portion of a new style expansion board
    is encoded in ones-complement format (except for the first
    two nybbles -- the er_Type field).  ReadExpansionRom knows
    about this and un-complements the appropriate fields.

   INPUTS
    board - a pointer to the base of a new style expansion board.
    configDev - the ConfigDev structure that will be read in.
    offset - a logical offset from the configdev base

   RESULTS
    error - If the board address does not contain a valid new style
        expansion board, then error will be non-zero.

   EXAMPLES

    configDev = AllocConfigDev();
    if( ! configDev ) panic();

    error = ReadExpansionBoard( board, configDev );
    if( ! error ) {
        configDev->cd_BoardAddr = board;
        ConfigBoard( configDev );
    }

   SEE ALSO
    ReadExpansionByte, WriteExpansionByte

 expansion.library/ReleaseConfigBinding expansion.library/ReleaseConfigBinding

   NAME
    ReleaseConfigBinding - allow others to bind to drivers

   SYNOPSIS
    ReleaseConfigBinding()

   FUNCTION
    This call should be used when you are done binding drivers
    to ConfigDev entries.  It releases the SignalSemaphore; this
    allows others to bind their drivers to ConfigDev structures.

   SEE ALSO
    ObtainConfigBinding()

 expansion.library/RemConfigDev                 expansion.library/RemConfigDev

   NAME
    RemConfigDev - remove a ConfigDev structure from the system

   SYNOPSIS
    RemConfigDev( configDev )
                  A0

   FUNCTION
    (Not typically called by user code)

    This routine removes the specified ConfigDev structure from the
    list of Configuration Devices in the system.

   INPUTS
    configDev - a valid ConfigDev structure.

   RESULTS

   EXCEPTIONS

   SEE ALSO
    AddConfigDev

   BUGS

 expansion.library/SetCurrentBinding       expansion.library/SetCurrentBinding

   NAME
    SetCurrentBinding - sets static board configuration area

   SYNOPSIS
    SetCurrentBinding( currentBinding, size )
                       A0		   D0:16

   FUNCTION
    This function records the contents of the "currentBinding"
    structure in a private place.  It may be read via
    GetCurrentBinding().  This is really a kludge, but it is
    the only way to pass extra arguments to a newly configured
    device.

    A CurrentBinding structure has the name of the currently
    loaded file, the product string that was associated with
    this driver, and a pointer to the head of a singly linked
    list of ConfigDev structures (linked through the cd_NextCD
    field).

    Many devices may not need this information; they have hard
    coded into themselves their manufacture number.  It is
    recommended that you at least check that you can deal with
    the product code in the linked ConfigDev structures.

   INPUTS
    currentBinding - a pointer to a CurrentBinding structure

    size - The size of the user's binddriver structure.  No
        more than this much data will be copied.  If size is
        less than the library's idea a CurrentBinding size,
        then the library's structure will be null padded.

   SEE ALSO
    GetCurrentBinding

 expansion.library/WriteExpansionByte     expansion.library/WriteExpansionByte

   NAME
    WriteExpansionByte - write a byte nybble by nybble.

   SYNOPSIS
    WriteExpansionByte( board, offset, byte )
                A0     D0      D1

   FUNCTION
    (Not typically called by user code)

    WriteExpansionByte writes a byte to a new-style expansion
    board.  These boards have their writeable data organized
    as a series of nybbles in memory.  This routine writes
    two nybbles in a very careful manner to work with all
    types of new expansion boards.

    To make certain types of board less expensive, an expansion
    board's write registers may be organized as either a
    byte-wide or nybble-wide register.  If it is nybble-wide
    then it must latch the less significant nybble until the
    more significant nybble is written.  This allows the
    following algorithm to work with either type of board:

        write the low order nybble to bits D15-D12 of
            byte (offset*4)+2

        write the entire byte to bits D15-D8 of
            byte (offset*4)

    The offset is a byte offset into a ExpansionRom structure.
    The actual memory address read will be four times larger.
    The macros EROFFSET and ECOFFSET are provided to help get
    these offsets from C.

   INPUTS
    board - a pointer to the base of a new style expansion board.
    offset - a logical offset from the configdev base
    byte - the byte of data to be written to the expansion board.

   EXAMPLES
    WriteExpansionByte( cd->BoardAddr, ECOFFSET( ec_Shutup ),  0 );
    WriteExpansionByte( cd->BoardAddr, ECOFFSET( ec_Interrupt ), 1 );

   SEE ALSO
    ReadExpansionByte, ReadExpansionRom


Text_Autodocs/mathffp.doc

TABLE OF CONTENTS

mathffp.library/SPAbs
mathffp.library/SPAdd
mathffp.library/SPCeil
mathffp.library/SPCmp
mathffp.library/SPDiv
mathffp.library/SPFix
mathffp.library/SPFloor
mathffp.library/SPFlt
mathffp.library/SPMul
mathffp.library/SPNeg
mathffp.library/SPSub
mathffp.library/SPTst
 mathffp.library/SPAbs                                   mathffp.library/SPAbs

NAME
    SPAbs -- Obtain the absolute value of the fast floating point number.

SYNOPSIS
    fnum2 = SPAbs(fnum1)
    D0	      D0

    float SPAbs(float fnum1);

FUNCTION
    Accepts a floating point number and returns the absolute value of
    said number.

INPUTS
    fnum1 	- floating point number.

RESULT
    fnum2 	- floating point absolute value of fnum1.

BUGS
    None

SEE ALSO

 mathffp.library/SPAdd                                   mathffp.library/SPAdd

NAME
    SPAdd -- Add two floating point numbers.

SYNOPSIS
    fnum3 = SPAdd(fnum1, fnum2)
    D0	      D1     D0

    float SPAdd(float fnum1, float fnum2);

FUNCTION
    Accepts two floating point numbers and returns the arithmetic
    sum of said numbers.

INPUTS
    fnum1 	- floating point number to add.
    fnum2 	- other floating point number to add.

RESULT
    fnum3 	- floating point number, sum of fnum1 and fnum2.

BUGS
    None.

SEE ALSO

 mathffp.library/SPCeil                                 mathffp.library/SPCeil

   NAME
    SPCeil -- Compute Ceil function of a number.

   SYNOPSIS
    x = SPCeil(y)
    D0         D0

    float SPCeil(float y);

   FUNCTION
    Calculate the least integer greater than or equal to x and return it.
    This identity is true.  Ceil(x) = -Floor(-x).

   INPUTS
    y 	- Motorola Fast Floating Point Format Number.

   RESULT
    x 	- Motorola Fast Floating Point Format Number.

   BUGS
    None.

   SEE ALSO
    SPFloor()

 mathffp.library/SPCmp                                   mathffp.library/SPCmp

NAME
    SPCmp -- Compares two floating point numbers.

SYNOPSIS
    result = SPCmp(fnum1, fnum2)
    D0               D0     D1

    int SPCmp(float fnum1, float fnum2);

FUNCTION

    Accepts two floating point numbers and returns the condition
    codes set to indicate the result of said comparison.  Additionally,
    the integer functional result is returned to indicate the result
    of said comparison.

INPUTS
    fnum1 	- floating point number.
    fnum2 	- floating point number.

RESULT
    Condition codes set to reflect the following branches:

        GT - fnum2 >  fnum1
        GE - fnum2 >= fnum1
        EQ - fnum2 =  fnum1
        NE - fnum2 != fnum1
        LT - fnum2 <  fnum1
        LE - fnum2 <= fnum1

    Integer functional result as:

        +1 => fnum1 > fnum2
        -1 => fnum1 < fnum2
         0 => fnum1 = fnum2

BUGS
    None.

SEE ALSO

 mathffp.library/SPDiv                                   mathffp.library/SPDiv

NAME
    SPDiv -- Divide two floating point numbers.

SYNOPSIS
    fnum3 = SPDiv(fnum1, fnum2)
    D0	      D1     D0

    float SPDiv(float fnum1, float fnum2);

FUNCTION
    Accepts two floating point numbers and returns the arithmetic
    division of said numbers.

INPUTS
    fnum1 	- floating point number.
    fnum2	- floating point number.

RESULT

    fnum3 	- floating point number.

BUGS
    None.

SEE ALSO

 mathffp.library/SPFix                                   mathffp.library/SPFix

NAME
    SPFix -- Convert fast floating point number to integer.

SYNOPSIS
    inum = SPFix(fnum)
    D0	     D0

    int SPFix(float fnum);

FUNCTION
    Accepts a floating point number and returns the truncated
    integer portion of said number.

INPUTS

    fnum 	- floating point number.

RESULT

    inum 	- signed integer number.

BUGS
    None.

SEE ALSO

 mathffp.library/SPFloor                               mathffp.library/SPFloor

   NAME
    SPFloor -- compute Floor function of a number.

   SYNOPSIS
    x = SPFloor(y)
    D0 	    D0

    float SPFloor(float y);

   FUNCTION
    Calculate the largest integer less than or equal to x and return it.

   INPUTS
    y 	- Motorola Fast Floating Point number.

   RESULT
    x 	- Motorola Fast Floating Point number.

   BUGS
    None.

   SEE ALSO
    SPCeil()

 mathffp.library/SPFlt                                   mathffp.library/SPFlt

NAME
    SPFlt -- Convert integer number to fast floating point.

SYNOPSIS
    fnum = SPFlt(inum)
    D0	     D0

    float SPFlt(int inum);

FUNCTION
    Accepts an integer and returns the converted
    floating point result of said number.

INPUTS
    inum 	- signed integer number

RESULT
    fnum 	- floating point number

BUGS
    None.

SEE ALSO

 mathffp.library/SPMul                                   mathffp.library/SPMul

NAME
    SPMul -- Multiply two floating point numbers.

SYNOPSIS
    fnum3 = SPMul(fnum1, fnum2)
    D0	      D1     D0

    float SPMul(float fnum1, float fnum2);

FUNCTION
    Accepts two floating point numbers and returns the arithmetic
    multiplication of said numbers.

INPUTS
    fnum1 	- floating point number
    fnum2 	- floating point number

RESULT
    fnum3 	- floating point number

BUGS
    None

SEE ALSO

 mathffp.library/SPNeg                                   mathffp.library/SPNeg

NAME
    SPNeg -- Negate the supplied floating point number.

SYNOPSIS
    fnum2 = SPNeg(fnum1)
    D0	      D0

    float SPNeg(float fnum1);

FUNCTION
    Accepts a floating point number and returns the value
    of said number after having been subtracted from 0.0.

INPUTS
    fnum1 	- floating point number.

RESULT
    fnum2 	- floating point negation of fnum1.

BUGS
    None

SEE ALSO

 mathffp.library/SPSub                                   mathffp.library/SPSub

NAME
    SPSub -- Subtract two floating point numbers.

SYNOPSIS
    fnum3 = SPSub(fnum1, fnum2)
    D0	      D1     D0

    float SPSub(float fnum1, float fnum2);

FUNCTION
    Accepts two floating point numbers and returns the arithmetic
    subtraction of said numbers.

INPUTS
    fnum1 	- floating point number.
    fnum2 	- floating point number.

RESULT
    fnum3 	- floating point number.

BUGS
    None.

SEE ALSO

 mathffp.library/SPTst                                   mathffp.library/SPTst

NAME
    SPTst - Compares a float against zero (0.0).

SYNOPSIS
    result = SPTst(fnum)
    D0	       D1

    int SPTst(float fnum);

FUNCTION
    Accepts a floating point number and returns the condition
    codes set to indicate the result of a comparison against
    the value of zero (0.0).  Additionally, the integer functional
    result is returned.

INPUTS
    fnum 	- floating point number.

RESULT
    Condition codes set to reflect the following branches:

        EQ - fnum =  0.0
        NE - fnum != 0.0
        PL - fnum >= 0.0
        MI - fnum <  0.0

    Integer functional result as:

        +1 => fnum > 0.0
        -1 => fnum < 0.0
         0 => fnum = 0.0

BUGS
    None.

SEE ALSO


Text_Autodocs/utility.doc

TABLE OF CONTENTS

utility.library/AllocateTagItems
utility.library/Amiga2Date
utility.library/CallHookPkt
utility.library/CheckDate
utility.library/CloneTagItems
utility.library/Date2Amiga
utility.library/FilterTagChanges
utility.library/FilterTagItems
utility.library/FindTagItem
utility.library/FreeTagItems
utility.library/GetTagData
utility.library/MapTags
utility.library/NextTagItem
utility.library/PackBoolTags
utility.library/RefreshTagItemClones
utility.library/SDivMod32
utility.library/SMult32
utility.library/Stricmp
utility.library/Strnicmp
utility.library/TagInArray
utility.library/ToLower
utility.library/ToUpper
utility.library/UDivMod32
utility.library/UMult32
 utility.library/AllocateTagItems             utility.library/AllocateTagItems

    NAME
    AllocateTagItems --  Allocate a TagItem array (or chain). (V36)

    SYNOPSIS
    tagList = AllocateTagItems( numItems )
    D0		            D0

    struct TagItem *AllocateTagItems( ULONG numItems);

    FUNCTION
    Allocates the specified number of usable TagItems slots, and does
    so in a format that the function FreeTagItems can handle.

    Note that to access the TagItems in 'tagList', you should use
    the function NextTagItem().  This will insure you respect any
    chaining (TAG_MORE) that the list uses, and will skip any
    TAG_IGNORE items that AllocateTagItems() might use to stash
    size and other information.

    INPUTS
    numItems	- the number of TagItem slots you want to allocate.

    RESULT
    tagList		- the allocated chain of TagItem structures.  Will
                  return NULL if unsuccessful.

    BUGS

    SEE ALSO
    FreeTagItems(), CloneTagItems()

 utility.library/Amiga2Date                         utility.library/Amiga2Date

   NAME
    Amiga2Date -- Calculate the date from a timestamp.  (V36)

   SYNOPSIS
    Amiga2Date( AmigaTime, Date )
                D0         A0

    void Amiga2Date( ULONG, struct ClockData * );

   FUNCTION
    Fills in a ClockData structure with the date and time calculated
    from a ULONG containing the number of seconds from 01-Jan-1978
    to the date.

   INPUTS
    AmigaTime 	- the number of seconds from 01-Jan-1978.

   RESULTS
    Date		- filled in with the date/time specified by
              AmigaTime.

   NOTES

   SEE ALSO
    CheckDate(), Date2Amiga()

   BUGS

 utility.library/CallHookPkt                       utility.library/CallHookPkt

    NAME
    CallHookPkt -- Invoke a Hook function callback. (V36)

    SYNOPSIS
    return = CallHookPkt( hook, object, paramPkt )
    D0		      A0    A2	    A1

    ULONG CallHookPkt( struct Hook *hook, VOID *object, VOID *paramPkt );

    FUNCTION
    Performs the callback standard defined by a Hook structure.
    This function is really very simple; it effectively performs
    a JMP to Hook->h_Entry.

    It is probably just as well to do this operation in an
    assembly language function linked in to your program, possibly
    from a compiler supplied library or a builtin function.

    It is anticipated that C programs will often call a 'varargs'
    variant of this function which will be named CallHook.  This
    function must be provided in a compiler specific library, but
    an example of use would be:

    returnval = CallHook( hook, dataobject, COMMAND_ID, param1, param2 );

    This function CallHook can be implemented in many C compilers
    like this:
    CallHook( hook, object, command, ... )
    struct Hook	*hook;
    VOID		*object;
    ULONG		command;
    {
        return ( CallHookPkt( hook, object, (VOID *) &command ) );
    }

    INPUTS
    Hook		- pointer to Hook structure as defined in
              utility/hooks.h
    Object		- useful data structure in the particular context the
              hook is being used for.
    ParamPkt	- pointer to a parameter packet (often built on the
              stack); by convention this packet should start off
              with a longword command code, and the remaining
              data in the packet depends on that command.

    RESULT
    return		- The meaning of the value returned in D0 depends on
              the context in which the Hook is being used.

    NOTES
    The functions called through this function should follow normal
    register conventions unless EXPLICITLY documented otherwise (and
    they have a good reason too).

    BUGS

    SEE ALSO
    utility/hooks.h

 utility.library/CheckDate                           utility.library/CheckDate

   NAME
    CheckDate -- Checks ClockData struct for legal date. (V36)

   SYNOPSIS
    AmigaTime = CheckDate( Date )
    D0                     A0

    ULONG CheckDate( struct ClockData * );

   FUNCTION
    Determines if the Date is a legal date and returns the number
    of seconds to Date from 01-Jan-1978 if it is.

   INPUTS
    Date 		- pointer to a ClockData structure.

   RESULTS
    AmigaTime 	- 0 if Date invalid; otherwise, the number of
              seconds to Date from 01-Jan-1978.

   NOTES

   BUGS
    The wday field of the ClockData structure is not checked.

   SEE ALSO
    Amiga2Date(), Date2Amiga()

 utility.library/CloneTagItems                   utility.library/CloneTagItems

    NAME
    CloneTagItems -- Copies a TagItem list.  (V36)

    SYNOPSIS
    newTagList = CloneTagItems( tagList )
    D0			    A0

    struct TagItem *CloneTagItems( struct TagItem *tagList );

    FUNCTION
    Copies the essential contents of a tagItem list.  Internally,
    it uses AllocateTagItems() so that you can use FreeTagItems().

    INPUTS
    tagList		- TagItem list to clone.

    RESULT
    newTagList	- resultant copy.

    BUGS

    SEE ALSO
    AllocateTagItems(), FreeTagItems(), RefreshTagItemClones()

 utility.library/Date2Amiga                         utility.library/Date2Amiga

   NAME
    Date2Amiga -- Calculate seconds from 01-Jan-1978.  (V36)

   SYNOPSIS
    AmigaTime = Date2Amiga( Date )
    D0                      A0

    ULONG Date2Amiga( struct ClockData * );

   FUNCTION
    Calculates the number of seconds from 01-Jan-1978 to the date
    specified in the ClockData structure.

   INPUTS
    Date 		- pointer to a ClockData structure containing the
              date of interest.

   RESULTS
    AmigaTime 	- the number of seconds from 01-Jan-1978 to the
              date specified in Date.

   NOTES
    This function does no sanity checking of the data in Date.

   SEE ALSO
    Amiga2Date(), CheckDate()

   BUGS

 utility.library/FilterTagChanges             utility.library/FilterTagChanges

    NAME
    FilterTagChanges -- Eliminate TagItems which specify no change. (V36)

    SYNOPSIS
    FilterTagChanges( changeList, oldValues, apply)
              A0	      A1	 D0

    void FilterTagChanges( struct TagItem *changeList,
                   struct TagItem *oldValues, LONG apply );

    FUNCTION
    Eliminate items from a "change list" that specify values already
    in effect in existing list.  Optionally update the existing list
    if the Boolean 'Apply' is true.

    The elimination is done by changing the ti_Tag field to TAG_IGNORE.
    So, this function may change the input tag list(s).

    INPUTS
    changeList 	- specification of new tag-value pairs.
    oldValues	- a list of existing tag item pairs.
    apply		- Boolean specification as to whether the values in
              oldValues are to be updated to the values in
              changeList.

    RESULT
    None.

    EXAMPLE
    Assume you have an attribute list for an object (oldValues)
    which looks like this:

        ATTR_Size,  "large",
        ATTR_Color, "orange",
        ATTR_Shape, "square",

    If you receive a new TagList containing some changes (changeList),
    which looks like this:

        ATTR_Size,  "large",
        ATTR_Shape, "triangle"

    If you call FilterTagChanges(), changeList will be modified to
    contain only those attributes which are different from the
    oldValues.  All other tagitems will have their tag-values set to
    TAG_IGNORE.  The resulting changeList will become:

        TAG_IGNORE, "large",
        ATTR_Shape, "triangle"

    If apply was set to TRUE, oldValues would be:

        ATTR_Size,  "large"
        ATTR_Color, "orange"
        ATTR_Shape, "triangle"

    BUGS

    SEE ALSO

 utility.library/FilterTagItems                 utility.library/FilterTagItems

    NAME
    FilterTagItems - Remove selected items from a TagItem list. (V36)

    SYNOPSIS
    nvalid = FilterTagItems(tagList, tagArray, logic)
    D0		       A0	A1	  D0

    ULONG FilterTagItems(struct TagItem *tagList, Tag *tagArray,
                 LONG logic);

    FUNCTION
    Removes TagItems from a TagItem list (by changing ti_Tag to
    TAG_IGNORE) depending on whether its ti_Tag value is
    found in an array of TagValues.

    If the 'logic' parameter is TAGFILTER_AND, then all items
    not appearing in the list are excluded.

    If 'logic' is TAGFILTER_NOT, then items not found in the
    array are preserved, and the ones in the array are cast out.

    INPUTS
    tagList		- input list of tag items which is to be filtered
              by having selected items changed to TAG_IGNORE.
    tagArray	- an array of Tag values, terminated by TAG_END,
              as specified in the notes on TagInArray().
    logic		- specification whether items in TagArray are to
              be included or excluded in the filtered result.

    RESULT
    nvalid		- number of valid items left in resulting filtered
              list.

    BUGS

    SEE ALSO
    TagInArray()

 utility.library/FindTagItem                       utility.library/FindTagItem

    NAME
    FindTagItem -- Scans TagItem list for a Tag. (V36)

    SYNOPSIS
    tag = FindTagItem( tagVal, tagList)
    D0		   D0	   A0

    struct TagItem *FindTagItem( Tag tagVal, struct TagItem *tagList );

    FUNCTION
    Scans a TagItem "List", which is in fact a chain of arrays
    of TagItem structures as defined in utility/tagitem.h.
    Returns a pointer to the FIRST item with ti_Tag matching the
    'TagVal' parameter.

    INPUTS
    tagVal 		- Tag value to search for.
    tagList		- beginning of TagItem list to scan.

    RESULT
    Returns a pointer to the item with ti_Tag matching 'TagVal'.
    Returns NULL if there is no match or if TagList is NULL.

    BUGS

    SEE ALSO
    utility/tagitem.h, GetTagData(), PackBoolTags(), NextTagItem()

 utility.library/FreeTagItems                     utility.library/FreeTagItems

    NAME
    FreeTagItems --  Frees allocated TagItem lists. (V36)

    SYNOPSIS
    FreeTagItems( tagList )
            A0

    void FreeTagItems( struct TagItem *tagList );

    FUNCTION
    Frees the memory of a TagItem list allocated either by
    AllocateTagItems() or CloneTagItems().

    INPUTS
    TagList		- list to free.  Must be created by functions
              specified. A value of NULL for 'tagList' is safe.

    RESULT
    None.

    BUGS

    SEE ALSO
    AllocateTagItems(), CloneTagItems()

 utility.library/GetTagData                         utility.library/GetTagData

    NAME
    GetTagData -- Obtain data corresponding to Tag. (V36)

    SYNOPSIS
    value = GetTagData(tagVal, default, tagList)
    D0		   D0	   D1	    A0

    ULONG GetTagData(Tag TagVal, ULONG Default, struct TagItem *TagList)

    FUNCTION
    Searches a TagItem list for a matching Tag value, and returns the
    corresponding ti_Data value for the TagItem found.  If none
    found, will return the value passed it as 'default'.

    INPUTS
    tagVal 		- Tag value to search for.
    default		- value to be returned if tagVal is not found.
    tagList 	- the TagItem list to search.

    RESULT
    value		- The ti_Data value for first matching TagItem, or
              'default' if a ti_Tag matching 'Tag' is not found.

    BUGS

    SEE ALSO
    utility/tagitem.h, FindTagItem(), PackBoolTags(), NextTagItem()

 utility.library/MapTags                               utility.library/MapTags

    NAME
    MapTags	-- Convert ti_Tag values in a list via map pairing. (V36)

    SYNOPSIS
    MapTags(tagList, mapList, includeMiss)
        A0	 A1       D0

    void MapTags(struct TagItem *tagList, struct TagItem mapList,
             LONG includeMiss);

    FUNCTION
    Apply a "mapping list" mapList to tagList:

    If the ti_Tag field of an item in tagList appears as ti_Tag in some
    item in mapList, overwrite ti_Tag with the corresponding ti_Data
    from the map list.

    If a tag in tagList does not appear in the mapList, you can choose
    to have it removed by changing it to TAG_IGNORE. Do this by setting
    includeMiss to FALSE.

    If you want to have items which do not appear in the mapList
    survive the mapping as-is, set includeMiss to 1.

    This is central to gadget interconnections where you want
    to convert the tag values from one space (the sender) to
    another (the receiver).

    INPUTS
    tagList		- Input list of tag items which is to be mapped
              to Tag values as specified in mapList.
    mapList 	- a "mapping list" tagItem list which pairs Tag
              values expected to appear in tagList with new
              values to be substituted in the ti_Tag fields of
              tagList.  May be NULL, which means that all items
              in tagList will be eliminated.
    includeMiss	- 0 to remove tags from tagList not in mapList,
              1 to remove

    RESULT
    None.

    EXAMPLE
    /* Consider this source list: */
        struct TagItem list[] = {
        { MY_SIZE, 	71 },
        { MY_WEIGHT, 	200 },
        { TAG_END,	} };

    /* And the mapping list: */
        struct TagItem map[] = {
        { MY_SIZE, 	HIS_TALL },
        { TAG_END,	} };

    /* Then after MapTags( list, map, 0 ), 'list' will become: */
        { HIS_TALL, 71 },
        { TAG_IGNORE, },
        { TAG_END, }

    /* Then after MapTags( list, map, 1 ), 'list' will become: */
        { HIS_TALL, 71 },
        { MY_WEIGHT, 200 },
        { TAG_END, }

    NOTES
    The procedure will change the values of the input tag list
    tagList (but not mapList).

    You can "filter" a list by passing includeMiss as 0, and having the
    data items in the map list equal the corresponding tags.

    You can perform the inverse filter ("everything but") by passing
    includeMiss equal to 1, and creating a map item for every tag you
    want to filter out, pairing it with a mapped data value of
    TAG_IGNORE.

    For safety and "order independence" of tag item arrays, if you
    attempt to map some tag to the value TAG_END, the value TAG_IGNORE
    will be substituted instead.

    BUGS

    SEE ALSO

 utility.library/NextTagItem                       utility.library/NextTagItem

    NAME
    NextTagItem -- Iterate TagItem lists. (V36)

    SYNOPSIS
    next_tag = NextTagItem( tagItemPtr )
    D0			A0

    struct TagItem *NextTagItem( struct TagItem **tagItemPtr );

    FUNCTION
    Iterates through a (chained) array of TagItem structures,
    skipping and chaining as dictated by system tags.  TAG_SKIP
    will cause it to skip the entry and the next, TAG_IGNORE ignores
    that single entry, and TAG_MORE has a pointer to another array
    of tags (and terminates the current array!)  TAG_DONE also
    terminates the current array.  Each call returns either the next
    tagitem you should examine, or NULL at the end.

    INPUTS
    tagItemPtr 	- doubly-indirect reference to a TagItem structure.
              The pointer will be changed to keep track of the
              iteration.

    RESULT
    next_tag	- Each TagItem in the array or chain of arrays that
              should be processed according to system Tag values
              (in utility/tagitem.h) is returned in turn with
              successive calls.

    EXAMPLE
    Iterate( struct TagItem *tags );
    {
        struct TagItem *tstate;
        struct TagItem *tag;

        tstate = tags;
        while ( tag = NextTagItem( &tstate ) )
        {
            switch ( tag->ti_Tag )
            {
             case TAG1:
                ...
                break;
             case TAG2:
                ...
                break;
            ...
            }
        }
       }

    NOTES
    Do NOT use the value of *tagItemPtr, but rather use the pointer
    returned by NextTagItem().

    BUGS

    SEE ALSO
    utility/tagitem.h, GetTagData(), PackBoolTags(), FindTagItem()

 utility.library/PackBoolTags                     utility.library/PackBoolTags

    NAME
    PackBoolTags --  Builds a "Flag" word from a TagList. (V36)

    SYNOPSIS
    boolflags = PackBoolTags( initialFlags, tagList, boolMap )
    D0			  D0	        A0       A1

    ULONG PackBoolTags( ULONG initialFlags, struct TagItem *tagList,
                struct TagItem *boolMap );

    FUNCTION
    Picks out the Boolean TagItems in a TagItem list and converts
    them into bit-flag representations according to a correspondence
    defined by the TagItem list 'BoolMap.'

    A Boolean TagItem is one where only the logical value of
    the ti_Data is relevant.  If this field is 0, the value is
    FALSE, otherwise TRUE.

    INPUTS
    initialFlags 	- a starting set of bit-flags which will be changed
              by the processing of TRUE and FALSE Boolean tags
              in tagList.
    tagList		- a TagItem list which may contain several TagItems
              defined to be "Boolean" by their presence in
              boolMap.  The logical value of ti_Data determines
              whether a TagItem causes the bit-flag value related
              by boolMap to set or cleared in the returned flag
              longword.
    boolMap		- a TagItem list defining the Boolean Tags to be
              recognized, and the bit (or bits) in the returned
              longword that are to be set or cleared when a
              Boolean Tag is found to be TRUE or FALSE in
              tagList.

    RESULT
    boolflags	- the accumulated longword of bit-flags, starting
              with InitialFlags and modified by each Boolean
              TagItem encountered.

    EXAMPLE

    /* define some nice user tag values ... */
    enum mytags { tag1 = TAG_USER+1, tag2, tag3, tag4, tag5 };

    /* this TagItem list defines the correspondence between Boolean tags
     * and bit-flag values.
     */
    struct TagItem	boolmap[] = {
        { tag1,  0x0001 },
        { tag2,  0x0002 },
        { tag3,  0x0004 },
        { tag4,  0x0008 },
        { TAG_DONE }
    };

    /* You are probably passed these by some client, and you want
     * to "collapse" the Boolean content into a single longword.
     */

    struct TagItem	boolexample[] = {
        { tag1,  TRUE },
        { tag2,  FALSE },
        { tag5, Irrelevant },
        { tag3,  TRUE },
        { TAG_DONE }
    };

    /* Perhaps 'boolflags' already has a current value of 0x800002. */
    boolflags = PackBoolTags( boolflags, boolexample, boolmap );

    /* The resulting new value of 'boolflags' will be 0x80005. /*

    BUGS
    There are some undefined cases if there is duplication of
    a given Tag in either list.  It is probably safe to say that
    the *last* of identical Tags in TagList will hold sway.

    SEE ALSO
    utility/tagitem.h, GetTagData(), FindTagItem(), NextTagItem()

 utility.library/RefreshTagItemClones     utility.library/RefreshTagItemClones

    NAME
    RefreshTagItemClones -- Rejuvenates a clone from the original. (V36)

    SYNOPSIS
    RefreshTagItemClones( cloneTagItems, originalTagItems )
                  A0	     A1

    void RefreshTagItemClones( struct TagItem *cloneTagItems,
                  struct TagItem *originalTagItems );

    FUNCTION
    If (and only if) the tag items 'cloneTagItems' were created
    from 'originalTagItems' by CloneTagItems(), and if originalTagItems
    has not been changed in any way, you can reset the clone list
    to its original state by using this function.

    INPUTS
    CloneTagItems	- return value from CloneTagItems(originalTagItems).
    OriginalTagItems- a tag list that hasn't changed.

    RESULT
    None.

    EXAMPLE

    BUGS

    SEE ALSO
    CloneTagItems(), AllocateTagItems(), FreeTagItems()

 utility.library/SDivMod32                           utility.library/SDivMod32

   NAME
    SDivMod32 -- Signed 32 by 32 bit division and modulus. (V36)

   SYNOPSIS
    Quotient:Remainder = SDivMod32( Dividend, Divisor )
    D0       D1                     D0        D1

    LONG SDivMod32( LONG, LONG );

   FUNCTION
    Divides the signed 32 bit dividend by the signed 32 bit divisor
       and returns a signed 32 bit quotient and remainder.

   INPUTS
    Dividend 	- signed 32 bit dividend.
    Divisor 	- signed 32 bit divisor.

   RESULTS
    Quotient 	- signed 32 quotient of the division.
    Remainder 	- signed 32 remainder of the division.

   NOTES

   SEE ALSO
    SMult32(), UDivMod32(), UMult32()

   BUGS

 utility.library/SMult32                               utility.library/SMult32

   NAME
    SMult32 -- Signed 32 by 32 bit multiply with 32 bit result. (V36)

   SYNOPSIS
    Result = SMult32( Arg1, Arg2 )
    D0                D0    D1

    LONG SMult32( LONG, LONG );

   FUNCTION
    Returns the signed 32 bit result of multiplying Arg1 by Arg2.

   INPUTS
    Arg1, Arg2	- signed multiplicands.

   RESULTS
    Result		- the signed 32 bit result of multiplying
              Arg1 by Arg2.

   NOTES

   SEE ALSO
    SDivMod32(), UDivMod32(), UMult32()

   BUGS

 utility.library/Stricmp                               utility.library/Stricmp

    NAME
    Stricmp	--  Case-insensitive string compare. (V37)

    SYNOPSIS
    res = Stricmp(string1, string2)
    D0		A0       A1

    LONG Stricmp(char *, char *);

    FUNCTION
    Stricmp compares two strings, ignoring case.  It handles all
    internationalization issues.  If the strings have different lengths,
    the shorter is treated as if it were extended with zeros.

    INPUTS
    string1, string2 - strings to be compared

    RESULT
    res - negative if string1 is below string2, 0 if they're the same, and
          positive if string1 is above string2.

    NOTES
    Commodore is planning a localization library which will take care
    of most details pertaining to system integration into different
    cultures, locales, and territories.

    This function will automatically be replaced by a localized version
    whenever the locale.library is loaded in memory. As such, the
    collating order may change depending on the locale currently
    defined by the user. Take this fact into consideration when using
    this function, and do not rely on obtaining specific collating
    sequences.

    BUGS

    SEE ALSO
    Strnicmp()

 utility.library/Strnicmp                             utility.library/Strnicmp

    NAME
    Strnicmp--  Case-insensitive string compare, length-limited. (V37)

    SYNOPSIS
    res = Strnicmp(string1, string2, length)
    D0		A0       A1	   D0

    LONG Strnicmp(char *, char *, LONG length);

    FUNCTION

    Strnicmp compares two strings, ignoring case.  It handles all
    internationalization issues.  If the strings have different lengths,
    the shorter is treated as if it were extended with zeros.  It never
    compares more than <length> characters.

    INPUTS
    string1, string2 - strings to be compared
    length		 - maximum number of characters to examine

    RESULT
    res - negative if string1 is below string2, 0 if they're the same, and
          positive if string1 is above string2.

    NOTES
    Commodore is planning a localization library which will take care
    of most details pertaining to system integration into different
    cultures, locales, and territories.

    This function will automatically be replaced by a localized version
    whenever the locale.library is loaded in memory. As such, the
    collating order may change depending on the locale currently
    defined by the user. Take this fact into consideration when using
    this function, and do not rely on obtaining specific collating
    sequences.

    BUGS

    SEE ALSO
    Stricmp()

 utility.library/TagInArray                         utility.library/TagInArray

    NAME
    TagInArray  -- Check if a Tag value appears in a Tag array. (V36)

    SYNOPSIS
    BOOL TagInArray( tag, tagArray )
    D0	         D0   A0

    BOOL TagInArray( Tag tag, Tag *tagArray);

    FUNCTION
    Perform a quick scan to see if a tag value appears in
    an array terminated with TAG_END.  Returns TRUE if
    the value is found.

    The 'tagArray' must be terminated by TAG_END.  It should
    NOT contain other system tag values, such as TAG_MORE
    or TAG_IGNORE.  Note that this is an array of Tag values, NOT
    an array of TagItems.

    This is sort of a "one shot" version of FilterTagItems().

    INPUTS
    tag 		- Tag value to search array for.
    tagArray	- a simple array terminated by TAG_END.

    RESULT
    Boolean success of search.

    BUGS

    SEE ALSO
    FilterTagItems()

 utility.library/ToLower                               utility.library/ToLower

    NAME
    ToLower - Convert a character to lowercase. (V37)

    SYNOPSIS
    char = ToLower(char)
    D0		D0

    char ToLower(char);

    FUNCTION
    Converts a character to lowercase, handling international character
    sets.

    INPUTS
    char - character to be converted.

    RESULT
    char - lowercase version of input character.

    NOTES
    Commodore is planning a localization library which will take care
    of most details pertaining to system integration into different
    cultures, locales, and territories.

    This function will automatically be replaced by a localized version
    whenever the locale.library is loaded in memory. As such, the
    resulting converted character may change depending on the locale
    currently defined by the user. Take this fact into consideration when
    using this function, and do not rely on obtaining specific
    conversions.

    BUGS

    SEE ALSO

 utility.library/ToUpper                               utility.library/ToUpper

    NAME
    ToUpper - Convert a character to uppercase. (V37)

    SYNOPSIS
    char = ToUpper(char)
    D0		D0

    char ToUpper(char);

    FUNCTION
    Converts a character to uppercase, handling international character
    sets.

    INPUTS
    char - character to be converted.

    RESULT
    char - uppercase version of input character.

    NOTES
    Commodore is planning a localization library which will take care
    of most details pertaining to system integration into different
    cultures, locales, and territories.

    This function will automatically be replaced by a localized version
    whenever the locale.library is loaded in memory. As such, the
    resulting converted character may change depending on the locale
    currently defined by the user. Take this fact into consideration when
    using this function, and do not rely on obtaining specific
    conversions.

    BUGS

    SEE ALSO

 utility.library/UDivMod32                           utility.library/UDivMod32

   NAME
    UDivMod32 -- Unsigned 32 by 32 bit division and modulus. (V36)

   SYNOPSIS
    Quotient:Remainder = UDivMod32( Dividend, Divisor )
    D0       D1                     D0        D1

    ULONG UDivMod32( ULONG, ULONG );

   FUNCTION
    Divides the unsigned 32 bit dividend by the unsigned 32 bit divisor
    and returns a unsigned 32 bit quotient and remainder.

   INPUTS
    Dividend 	- unsigned 32 bit dividend.
    Divisor 	- unsigned 32 bit divisor.

   RESULTS
    Quotient 	- unsigned 32 quotient of the division.
    Remainder 	- unsigned 32 remainder of the division.

   NOTES

   SEE ALSO
    SDivMod32(), SMult32(), UMult32()

   BUGS

 utility.library/UMult32                               utility.library/UMult32

   NAME
    UMult32 -- Unsigned 32 by 32 bit multiply with 32 bit result. (V36)

   SYNOPSIS
    Result = UMult32( Arg1, Arg2 )
    D0                D0    D1

    ULONG UMult32( ULONG, ULONG );

   FUNCTION
    Returns the unsigned 32 bit result of multiplying Arg1 by Arg2.

   INPUTS
    Arg1, Arg2		- unsigned multiplicands.

   RESULTS
    Result			- the unsigned 32 bit result of
                  multiplying Arg1 by Arg2.

   NOTES

   SEE ALSO
    SDivMod32(), SMult32(), UDivMod32()

   BUGS


Text_Autodocs/gadtools.doc

TABLE OF CONTENTS

gadtools.library/CreateContext
gadtools.library/CreateGadgetA
gadtools.library/CreateMenusA
gadtools.library/DrawBevelBoxA
gadtools.library/FreeGadgets
gadtools.library/FreeMenus
gadtools.library/FreeVisualInfo
gadtools.library/GetVisualInfoA
gadtools.library/GT_BeginRefresh
gadtools.library/GT_EndRefresh
gadtools.library/GT_FilterIMsg
gadtools.library/GT_GetIMsg
gadtools.library/GT_PostFilterIMsg
gadtools.library/GT_RefreshWindow
gadtools.library/GT_ReplyIMsg
gadtools.library/GT_SetGadgetAttrsA
gadtools.library/LayoutMenuItemsA
gadtools.library/LayoutMenusA
 gadtools.library/CreateContext                 gadtools.library/CreateContext

   NAME
    CreateContext -- Create a place for GadTools context data. (V36)

   SYNOPSIS
    gad = CreateContext(glistpointer);
    D0                  A0

    struct Gadget *CreateContext(struct Gadget **);

   FUNCTION
    Creates a place for GadTools to store any context data it might
    need for your window.  In reality, an unselectable invisible
    gadget is created, with room for the context data.
    This function also establishes the linkage from a glist type
    pointer to the individual gadget pointers.  Call this function
    before any of the other gadget creation calls.

   INPUTS
    glistptr - Address of a pointer to a Gadget, which was previously
        set to NULL.  When all the gadget creation is done, you may
        use that pointer as your NewWindow.FirstGadget, or
        in intuition.library/AddGList(), intuition.library/RefreshGList(),
        FreeGadgets(), etc.

   RESULT
    gad - Pointer to context gadget, or NULL if failure.

   EXAMPLE

    struct Gadget *gad;
    struct Gadget *glist = NULL;
    gad = CreateContext(&glist);
    /*  Other creation calls go here */
    if (gad)
    {
        myNewWindow.FirstGadget = glist;
        if ( myWindow = OpenWindow(&myNewWindow) )
        {
        GT_RefreshWindow(win);
        /* other stuff */
        CloseWindow(myWindow);
        }
    }
    FreeGadgets(glist);

   NOTES

   BUGS

   SEE ALSO

 gadtools.library/CreateGadgetA                 gadtools.library/CreateGadgetA

   NAME
    CreateGadgetA -- Allocate and initialize a gadtools gadget. (V36)
    CreateGadget -- Varargs stub for CreateGadgetA(). (V36)

   SYNOPSIS
    gad = CreateGadgetA(kind, previous, newgad, taglist)
    D0                  D0    A0        A1      A2

    struct Gadget *CreateGadgetA(ULONG, struct Gadget *,
        struct NewGadget *, struct TagItem *);

    gad = CreateGadget(kind, previous, newgad, firsttag, ...)

    struct Gadget *CreateGadget(ULONG, struct Gadget *,
        struct NewGadget *, Tag, ...);

   FUNCTION
    CreateGadgetA() allocates and initializes a new gadget of the
    specified kind, and attaches it to the previous gadget.  The
    gadget is created based on the supplied kind, NewGadget structure,
    and tags.

   INPUTS
    kind - to indicate what kind of gadget is to be created.
    previous - pointer to the previous gadget that this new gadget
        is to be attached to.
    newgad - a filled in NewGadget structure describing the desired
        gadget's size, position, label, etc.
    taglist - pointer to a TagItem list.

   TAGS
    All kinds:
    GT_Underscore (GadTools V37 and higher only).
        Indicates the symbol that precedes the character in the gadget
        label to be underscored.  This would be to indicate keyboard
        equivalents for gadgets (note that GadTools does not process
        the keys - it just displays the underscore).
        Example: To underscore the "M" in "Mode"...
        ng.ng_GadgetText = "_Mode:";
        gad = CreateGadget(..._KIND, &ng, prev,
            GT_Underscore, '_',
            ...
            );

    BUTTON_KIND (action buttons):
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    CHECKBOX_KIND (on/off items):
    GTCB_Checked (BOOL) - Initial state of checkbox, defaults to FALSE.
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    CYCLE_KIND (multiple state selections):
    GTCY_Labels (STRPTR *) - Pointer to NULL-terminated array of strings
        that are the choices offered by the cycle gadget (required).
    GTCY_Active (UWORD) - The ordinal number (counting from zero) of
        the initially active choice of a cycle gadget (defaults to zero).
    GA_Disabled (BOOL) - (GadTools V37 and higher only)
        Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    INTEGER_KIND (numeric entry):
    GTIN_Number (ULONG) - The initial contents of the integer gadget
        (default zero).
    GTIN_MaxChars (UWORD) - The maximum number of digits that the
        integer gadget is to hold (defaults to 10).
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).
    STRINGA_ExitHelp (BOOL) - (New for V37) Set to TRUE to have the
        help-key cause an exit from the integer gadget.  You will
        then receive a GADGETUP with code = 0x5F (rawkey for help).
    GA_TabCycle (BOOL) - (New for V37) Set to TRUE so that pressing
        <TAB> or <Shift-TAB> will activate the next or previous
        such gadget. (defaults to TRUE, unlike regular Intuition string
        gadgets, which default to FALSE).
    GTST_EditHook (struct Hook *) - (new for V37) Hook to use as a custom
        integer gadget edit hook (StringExtend->EditHook) for this gadget.
        GadTools will allocate the StringExtend->WorkBuffer for you.
        Defaults to NULL.
    STRINGA_Justification - (new for V37) Controls the justification of
        the contents of an integer gadget.  Choose one of STRINGLEFT,
        STRINGRIGHT, or STRINGCENTER.  (Defaults to STRINGLEFT).
    STRINGA_ReplaceMode (BOOL) - (new for V37) If TRUE, this integer gadget
        is in replace-mode.  Defaults to FALSE (insert-mode).

    LISTVIEW_KIND (scrolling list):
    GTLV_Top (WORD) - Top item visible in the listview.  This value
        will be made reasonable if out-of-range (defaults to zero).
    GTLV_Labels (struct List *) - List of labels whose ln_Name fields
        are to be displayed in the listview.
    GTLV_ReadOnly (BOOL) - If TRUE, then listview is read-only.
    GTLV_ScrollWidth (UWORD) - Width of scroll bar for listview.
        Must be greater than zero (defaults to 16).
    GTLV_ShowSelected (struct Gadget *) - NULL to have the currently
        selected item displayed beneath the listview, or pointer to
        an already-created GadTools STRING_KIND gadget to have an
        editable display of the currently selected item.
    GTLV_Selected (UWORD) - Ordinal number of currently selected
        item, or ~0 to have no current selection (defaults to ~0).
    LAYOUTA_Spacing - Extra space to place between lines of listview
        (defaults to zero).

    MX_KIND (mutually exclusive, radio buttons):
    GTMX_Labels (STRPTR *) - Pointer to a NULL-terminated array of
        strings which are to be the labels beside each choice in a
        set of mutually exclusive gadgets.
    GTMX_Active (UWORD) - The ordinal number (counting from zero) of
        the initially active choice of an mx gadget (Defaults to zero).
    GTMX_Spacing (UWORD) - The amount of space between each choice
        of a set of mutually exclusive gadgets.  This amount is added
        to the font height to produce the vertical shift between
        choices. (defaults to one).
    LAYOUTA_Spacing - FOR COMPATIBILITY ONLY.  Use GTMX_Spacing instead.
        The number of extra pixels to insert between
        each choice of a mutually exclusive gadget.  This is added
        to the present gadget image height (9) to produce the
        true spacing between choices.  (defaults to
        FontHeight-8, which is zero for 8-point font users).

    NUMBER_KIND (read-only numeric):
    GTNM_Number - A signed long integer to be displayed as a read-only
         number (default 0).
    GTNM_Border (BOOL) - If TRUE, this flag asks for a recessed
        border to be placed around the gadget.

    PALETTE_KIND (color selection):
    GTPA_Depth (UWORD) - Number of bitplanes in the palette
        (defaults to 1).
    GTPA_Color (UBYTE) - Initially selected color of the palette
        (defaults to 1).
    GTPA_ColorOffset (UBYTE) - First color to use in palette
        (defaults to zero).
    GTPA_IndicatorWidth (UWORD) - The desired width of the current-color
        indicator, if you want one to the left of the palette.
    GTPA_IndicatorHeight (UWORD) - The desired height of the current-color
        indicator, if you want one above the palette.
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    SCROLLER_KIND (for scrolling through areas or lists):
    GTSC_Top (WORD) - Top visible in area scroller represents
        (defaults to zero).
    GTSC_Total (WORD) - Total in area scroller represents
        (defaults to zero).
    GTSC_Visible (WORD) - Number visible in scroller (defaults to 2).
    GTSC_Arrows (UWORD) - Asks for arrows to be attached to the scroller.
        The value supplied will be taken as the width of each arrow button
        for a horizontal scroller, or the height of each button for a
        vertical scroller (the other dimension will match the whole
        scroller).
    PGA_Freedom - Whether scroller is horizontal or vertical.
        Choose LORIENT_VERT or LORIENT_HORIZ (defaults to horiz).
    GA_Immediate (BOOL) - Hear every IDCMP_GADGETDOWN event from scroller
        (defaults to FALSE).
    GA_RelVerify (BOOL) - Hear every IDCMP_GADGETUP event from scroller
        (defaults to FALSE).
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    SLIDER_KIND (to indicate level or intensity):
    GTSL_Min (WORD) - Minimum level for slider (default 0).
    GTSL_Max (WORD) - Maximum level for slider (default 15).
    GTSL_Level (WORD) - Current level of slider (default 0).
    GTSL_MaxLevelLen (UWORD) - Max. length in characters of level string
        when rendered beside slider.
    GTSL_LevelFormat (STRPTR) - C-Style formatting string for slider
        level.  Be sure to use the 'l' (long) modifier.  This string
        is processed using exec/RawDoFmt(), so refer to that function
        for details.
    GTSL_LevelPlace - One of PLACETEXT_LEFT, PLACETEXT_RIGHT,
        PLACETEXT_ABOVE, or PLACETEXT_BELOW, indicating where the level
        indicator is to go relative to slider (default to PLACETEXT_LEFT).
    GTSL_DispFunc ( LONG (*function)(struct Gadget *, WORD) ) - Function
        to calculate level to be displayed.  A number-of-colors slider
        might want to set the slider up to think depth, and have a
        (1 << n) function here.  Defaults to none.  Your function must
        take a pointer to gadget as the first parameter, the level
        (a WORD) as the second, and return the result as a LONG.
    GA_Immediate (BOOL) - If you want to hear each slider IDCMP_GADGETDOWN
        event.
    GA_RelVerify (BOOL) - If you want to hear each slider IDCMP_GADGETUP
        event.
    PGA_Freedom - Set to LORIENT_VERT or LORIENT_HORIZ to have a
        vertical or horizontal slider.
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    STRING_KIND (text-entry):
    GTST_String (STRPTR) - The initial contents of the string gadget,
         or NULL (default) if string is to start empty.
    GTST_MaxChars (UWORD) - The maximum number of characters that the
        string gadget is to hold.
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).
    STRINGA_ExitHelp (BOOL) - (New for V37) Set to TRUE to have the
        help-key cause an exit from the string gadget.  You will
        then receive a GADGETUP with code = 0x5F (rawkey for help).
    GA_TabCycle (BOOL) - (New for V37) Set to TRUE so that pressing
        <TAB> or <Shift-TAB> will activate the next or previous
        such gadget. (defaults to TRUE, unlike regular Intuition string
        gadgets, which default to FALSE).
    GTST_EditHook (struct Hook *) - (new for V37) Hook to use as a custom
        string gadget edit hook (StringExtend->EditHook) for this gadget.
        GadTools will allocate the StringExtend->WorkBuffer for you.
        Defaults to NULL.
    STRINGA_Justification - (new for V37) Controls the justification of
        the contents of a string gadget.  Choose one of STRINGLEFT,
        STRINGRIGHT, or STRINGCENTER.  (Defaults to STRINGLEFT).
    STRINGA_ReplaceMode (BOOL) - (new for V37) If TRUE, this string gadget
        is in replace-mode.  Defaults to FALSE (insert-mode).

    TEXT_KIND (read-only text):
    GTTX_Text - Pointer to a NULL terminated string to be displayed,
        as a read-only text-display gadget, or NULL. defaults to NULL.
    GTTX_CopyText (BOOL) -	This flag instructs the text-display gadget
        to copy the supplied text string, instead of using only
        pointer to the string.  This only works for the initial value
        of GTTX_Text set at CreateGadget() time.  If you subsequently
        change GTTX_Text, the new text will be referenced by pointer,
        not copied.  Do not use this tag with a NULL GTTX_Text.
    GTTX_Border (BOOL) - If TRUE, this flag asks for a recessed
        border to be placed around the gadget.

   RESULT
    gad - pointer to the new gadget, or NULL if the allocation failed
        or if previous was NULL.

   EXAMPLE

   NOTES
    Note that the ng_VisualInfo and ng_TextAttr fields of the
    NewGadget structure must be set to valid VisualInfo and
    TextAttr pointers, or this function will fail.

    Starting with V37, string and integer gadgets have the GFLG_TABCYCLE
    feature automatically.  If the user presses Tab or Shift-Tab while
    in a string or integer gadget, the next or previous one in
    sequence will be activated.  You will hear a GADGETUP with a code
    of 0x09.  Use {GA_TabCycle, FALSE} to supress this.

   BUGS

   SEE ALSO
    FreeGadgets(), GT_SetGadgetAttrs(), GetVisualInfo().

 gadtools.library/CreateMenusA                   gadtools.library/CreateMenusA

   NAME
    CreateMenusA -- Allocate and fill out a menu structure. (V36)
    CreateMenus -- Varargs stub for CreateMenus(). (V36)

   SYNOPSIS
    menu = CreateMenusA(newmenu, taglist)
    D0                  A0       A1

    struct Menu *CreateMenusA(struct NewMenu *, struct TagItem *);

    menu = CreateMenus(newmenu, firsttag, ...)

    struct Menu *CreateMenus(struct NewMenu *, Tag, ...);

   FUNCTION
    CreateMenusA() allocates and initializes a complete menu
    structure based on the supplied array of NewMenu structures.
    Optionally, CreateMenusA() can allocate and initialize a complete
    set of menu items and sub-items for a single menu title.  This
    is dictated by the contents of the array of NewMenus.

   INPUTS
    newmenu - Pointer to an array of initialized struct NewMenus.
    taglist - Pointer to a TagItem list.

   TAGS
    GTMN_FrontPen (UBYTE) - Pen number to be used for menu text.
        (defaults to zero).
    GTMN_FullMenu (BOOL) - (GadTools V37 and higher only)
        Requires that the NewMenu specification describes a complete
        menu strip, not a fragment.  If a fragment is found,
        CreateMenusA() will fail with a secondary error of
        GTMENU_INVALID.  (defaults to FALSE).
    GTMN_SecondaryError (ULONG *) - (GadTools V37 and higher only)
        Supply a pointer to a NULL-initialized ULONG to receive a
        descriptive error code.  Possible values:
        GTMENU_INVALID - NewMenu structure describes an illegal
            menu.  (CreateMenusA() will fail with a NULL result).
        GTMENU_TRIMMED - NewMenu structure has too many menus, items,
            or subitems (CreateMenusA() will succeed, returning a
            trimmed-down menu structure).
        GTMENU_NOMEM - CreateMenusA() ran out of memory.

   RESULT
    menu - Pointer to the resulting initialized menu structure (or
        the resulting FirstItem), with all the links for menu items
        and subitems in place.
        The result will be NULL if CreateMenusA() could not allocate
        memory for the menus, or if the NewMenu array had an
        illegal arrangement (eg. NM_SUB following NM_TITLE).
        (see also the GTMN_SecondaryError tag above).

   EXAMPLE

   NOTES
    The strings you supply for menu text are not copied, and must
    be preserved for the life of the menu.
    The resulting menus have no positional information.  You will
    want to call LayoutMenusA() (or LayoutMenuItemsA()) to supply that.
    CreateMenusA() automatically provides you with a UserData field
    for each menu, menu-item or sub-item.  Use the GTMENU_USERDATA(menu)
    or GTMENUITEM_USERDATA(menuitem) macro to access it.

   BUGS
    At present, if you put images into menus using IM_ITEM
    or IM_SUB for a NewMenu->Type, the image you supply must
    be an ordinary struct Image.  You may not use a 'custom
    image' (eg. one obtained from a boopsi image-class).

   SEE ALSO
    LayoutMenusA(), FreeMenus(), gadtools.h/GTMENU_USERDATA(),
    gadtools.h/GTMENUITEM_USERDATA()

 gadtools.library/DrawBevelBoxA                 gadtools.library/DrawBevelBoxA

   NAME
    DrawBevelBoxA -- Draws a bevelled box. (V36)
    DrawBevelBox -- Varargs stub for DrawBevelBox(). (V36)

   SYNOPSIS
    DrawBevelBoxA(rport, left, top, width, height, taglist)
                  A0     D0    D1   D2     D3      A1

    VOID DrawBevelBoxA(struct RastPort *, WORD, WORD, WORD, WORD,
        struct TagItem *taglist);

    DrawBevelBox(rport, left, top, width, height, firsttag, ...)

    VOID DrawBevelBox(struct RastPort *, WORD, WORD, WORD, WORD,
        Tag, ...);

   FUNCTION
    DrawBevelBoxA() renders a bevelled box of specified dimensions
    into the supplied RastPort.

   INPUTS
    rport - The RastPort into which the box is to be drawn.
    left - The left edge of the box.
    top - The top edge of the box.
    width - The width of the box.
    height - The height of the box.
    taglist - Pointer to a TagItem list.

   TAGS
    GTBB_Recessed (BOOL):  Set to anything for a recessed-looking box.
        If absent, the box defaults, it would be raised.
    GT_VisualInfo (APTR):  You MUST supply the value you obtained
        from an earlier call to GetVisualInfoA().

   RESULT
    None.

   EXAMPLE

   NOTES
    DrawBevelBox() is a rendering operation, not a gadget.  That
    means you must refresh it at the appropriate time, like any
    other rendering operation.

   BUGS

   SEE ALSO
    GetVisualInfoA()

 gadtools.library/FreeGadgets                     gadtools.library/FreeGadgets

   NAME
    FreeGadgets -- Free a linked list of gadgets. (V36)

   SYNOPSIS
    FreeGadgets(glist)
                A0

    VOID FreeGadgets(struct Gadget *glist);
                     A0

   FUNCTION
    Frees any GadTools gadgets found on the linked list of gadgets
    beginning with the specified one.  Frees all the memory that was
    allocated by CreateGadgetA().  This function will return safely
    with no action if it receives a NULL parameter.

   INPUTS
    glist - pointer to first gadget in list to be freed.

   RESULT
    none

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    CreateGadgetA()

 gadtools.library/FreeMenus                         gadtools.library/FreeMenus

   NAME
    FreeMenus -- Frees memory allocated by CreateMenusA(). (V36)

   SYNOPSIS
    FreeMenus(menu)
              A0

    VOID FreeMenus(struct Menu *);

   FUNCTION
    Frees the menus allocated by CreateMenusA().  It is safe to
    call this function with a NULL parameter.

   INPUTS
    menu - Pointer to menu structure (or first MenuItem) obtained
    from CreateMenusA().

   RESULT
    None.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    CreateMenusA()

 gadtools.library/FreeVisualInfo               gadtools.library/FreeVisualInfo

   NAME
    FreeVisualInfo -- Return any resources taken by GetVisualInfo. (V36)

   SYNOPSIS
    FreeVisualInfo(vi)
                   A0

    VOID FreeVisualInfo(APTR);

   FUNCTION
    FreeVisualInfo() returns any memory or other resources that
    were allocated by GetVisualInfoA().  You should only call this function
    once you are done with using the gadgets (i.e. after CloseWindow()),
    but while the screen is still valid (i.e. before CloseScreen() or
    UnlockPubScreen()).

   INPUTS
    vi - Pointer that was obtained by calling GetVisualInfoA().

   RESULT
    None.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    GetVisualInfoA()

 gadtools.library/GetVisualInfoA               gadtools.library/GetVisualInfoA

   NAME
    GetVisualInfoA -- Get information GadTools needs for visuals. (V36)
    GetVisualInfo -- Varargs stub for GetVisualInfoA(). (V36)

   SYNOPSIS
    vi = GetVisualInfoA(screen, taglist)
    D0                  A0      A1

    APTR vi = GetVisualInfoA(struct Screen *, struct TagItem *);

    vi = GetVisualInfo(screen, firsttag, ...)

    APTR vi = GetVisualInfo(struct Screen *, Tag, ...);

   FUNCTION
    Get a pointer to a (private) block of data containing various bits
    of information that GadTools needs to ensure the best quality
    visuals.  Use the result in the NewGadget structure of any gadget
    you create, or as a parameter to the various menu calls.  Once the
    gadgets/menus are no longer needed (after the last CloseWindow),
    call FreeVisualInfo().

   INPUTS
    screen - Pointer to the screen you will be opening on.
    taglist - Pointer to list of TagItems.

   RESULT
    vi - Pointer to private data.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    FreeVisualInfo(), intuition/LockPubScreen(),
    intuition/UnlockPubScreen()

 gadtools.library/GT_BeginRefresh             gadtools.library/GT_BeginRefresh

   NAME
    GT_BeginRefresh -- Begin refreshing friendly to GadTools. (V36)

   SYNOPSIS
    GT_BeginRefresh(win)
                    A0

    VOID GT_BeginRefresh(struct Window *);

   FUNCTION
    Invokes the intuition.library/BeginRefresh() function in a manner
    friendly to the Gadget Toolkit.  This function call permits the
    GadTools gadgets to refresh themselves at the correct time.
    Call GT_EndRefresh() function when done.

   INPUTS
    win - Pointer to Window structure for which a IDCMP_REFRESHWINDOW
        IDCMP event was received.

   RESULT
    None.

   EXAMPLE

   NOTES
    The nature of GadTools precludes the use of the IDCMP flag
    WFLG_NOCAREREFRESH.  You must handle IDCMP_REFRESHWINDOW events
    in at least the minimal way, namely:

        case IDCMP_REFRESHWINDOW:
            GT_BeginRefresh(win);
            GT_EndRefresh(win, TRUE);
            break;

   BUGS

   SEE ALSO
    intuition.library/BeginRefresh()

 gadtools.library/GT_EndRefresh                 gadtools.library/GT_EndRefresh

   NAME
    GT_EndRefresh -- End refreshing friendly to GadTools. (V36)

   SYNOPSIS
    GT_EndRefresh(win, complete)
                  A0   D0

    VOID GT_EndRefresh(struct Window *, BOOL complete);

   FUNCTION
    Invokes the intuition.library/EndRefresh() function in a manner
    friendly to the Gadget Toolkit.  This function call permits
    GadTools gadgets to refresh themselves at the correct time.
    Call this function to EndRefresh() when you have used
    GT_BeginRefresh().

   INPUTS
    win - Pointer to Window structure for which a IDCMP_REFRESHWINDOW
        IDCMP event was received.
    complete - TRUE when done with refreshing.

   RESULT
    None.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    intuition.library/EndRefresh()

 gadtools.library/GT_FilterIMsg                 gadtools.library/GT_FilterIMsg

   NAME
    GT_FilterIMsg -- Filter an IntuiMessage through GadTools. (V36)

   SYNOPSIS
    modimsg = GT_FilterIMsg(imsg)
    D0                      A1

    struct IntuiMessage *GT_FilterIMsg(struct IntuiMessage *);

   FUNCTION
    NOTE WELL:  Extremely few programs will actually need this function.
    You almost certainly should be using GT_GetIMsg() and GT_ReplyIMsg()
    only, and not GT_FilterIMsg() and GT_PostFilterIMsg().

    GT_FilterIMsg() takes the supplied IntuiMessage and asks the
    Gadget Toolkit to consider and possibly act on it.  Returns
    NULL if the message was only of significance to a GadTools gadget
    (i.e. not to you), else returns a pointer to a modified IDCMP
    message, which may contain additional information.
    You should examine the Class, Code, and IAddress fields of
    the returned message to learn what happened.  Do not make
    interpretations based on the original imsg.
    You should use GT_PostFilterIMsg() to revert to the original
    IntuiMessage once you are done with the modified one.

   INPUTS
    imsg - An IntuiMessage you obtained from a Window's UserPort.

   RESULT
    modimsg - A modified IntuiMessage, possibly with extra information
        from GadTools, or NULL.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO
    GT_GetIMsg(), GT_PostFilterIMsg()

 gadtools.library/GT_GetIMsg                       gadtools.library/GT_GetIMsg

   NAME
    GT_GetIMsg -- Get an IntuiMessage, with GadTools processing. (V36)

   SYNOPSIS
    imsg = GT_GetIMsg(intuiport)
    D0                A0

    struct IntuiMessage *GT_GetIMsg(struct MsgPort *);

   FUNCTION
    Use GT_GetIMsg() in place of the usual exec.library/GetMsg() when
    reading IntuiMessages from your window's UserPort.  If needed,
    the GadTools dispatcher will be invoked, and suitable processing
    will be done for gadget actions.  This function returns a pointer
    to a modified IntuiMessage (which is a copy of the original,
    possibly with some supplementary information from GadTools).
    If there are no messages (or if the only messages are meaningful
    only to GadTools, NULL will be returned.

   INPUTS
    intuiport - The Window->UserPort of a window that is using the
        Gadget Toolkit.

   RESULT
    imsg - Pointer to modified IntuiMessage, or NULL if there are
        no applicable messages.

   EXAMPLE

   NOTES
    Be sure to use GT_ReplyIMsg() and not exec.library/ReplyMsg() on
    messages obtained with GT_GetIMsg().
    If you intend to do more with the resulting message than read
    its fields, act on it, and reply it, you may find GT_FilterIMsg()
    more appropriate.

   BUGS

   SEE ALSO
    GT_ReplyIMsg(), GT_FilterIMsg()

 gadtools.library/GT_PostFilterIMsg         gadtools.library/GT_PostFilterIMsg

   NAME
    GT_PostFilterIMsg -- Return the unfiltered message after
        GT_FilterIMsg() was called, and clean up. (V36)

   SYNOPSIS
    imsg = GT_PostFilterIMsg(modimsg)
    D0                       A1

    struct IntuiMessage *GT_PostFilterIMsg(struct IntuiMessage *);

   FUNCTION
    NOTE WELL:  Extremely few programs will actually need this function.
    You almost certainly should be using GT_GetIMsg() and GT_ReplyIMsg()
    only, and not GT_FilterIMsg() and GT_PostFilterIMsg().

    Performs any clean-up necessitated by a previous call to
    GT_FilterIMsg().  The original IntuiMessage is now yours to handle.
    Do not interpret the fields of the original IntuiMessage, but
    rather use only the one you got from GT_FilterIMsg().  You
    may only do message related things at this point, such as queueing
    it up or replying it.  Since you got the message with
    exec.library/GetMsg(), your responsibilities do include replying
    it with exec.library/ReplyMsg(). This function may be safely
    called with a NULL parameter.

   INPUTS
    modimsg - A modified IntuiMessage obtained with GT_FilterIMsg().

   RESULT
    imsg - A pointer to the original IntuiMessage, if GT_FilterIMsg()
        returned non-NULL.

   EXAMPLE

   NOTES
    Be sure to use exec.library/ReplyMsg() on the original IntuiMessage
    you obtained with GetMsg(), (which is the what you passed to
    GT_FilterIMsg()), and not on the parameter of this function.

   BUGS

   SEE ALSO
    GT_FilterIMsg()

 gadtools.library/GT_RefreshWindow           gadtools.library/GT_RefreshWindow

   NAME
    GT_RefreshWindow -- Refresh all the GadTools gadgets. (V36)

   SYNOPSIS
    GT_RefreshWindow(win, req)
                     A0   A1

    VOID GT_RefreshWindow(struct Window *, struct Requester *);

   FUNCTION
    Perform the initial refresh of all the GadTools gadgets you have
    created.  After you have opened your window, you must call this
    function.  Or, if you have opened your window without gadgets,
    you add the gadgets with intuition.library/AddGList(),
    refresh them using intuition.library/RefreshGList(), then call
    this function.
    You should not need this function at other times.

   INPUTS
    win - Pointer to the Window containing GadTools gadgets.
    req - Pointer to requester, or NULL if not a requester (currently
        ignored - use NULL).

   RESULT
    None.

   EXAMPLE

   NOTES
    req must currently be NULL.  GadTools gadgets are not supported
    in requesters.  This field may allow such support at a future date.

   BUGS

   SEE ALSO
    GT_BeginRefresh()

 gadtools.library/GT_ReplyIMsg                   gadtools.library/GT_ReplyIMsg

   NAME
    GT_ReplyIMsg -- Reply a message obtained with GT_GetIMsg(). (V36)

   SYNOPSIS
    GT_ReplyIMsg(imsg)
                 A1

    VOID GT_ReplyIMsg(struct IntuiMessage *);

   FUNCTION
    Reply a modified IntuiMessage obtained with GT_GetIMsg().
    If you use GT_GetIMsg(), use this function where you would normally
    have used exec.library/ReplyMsg().
    You may safely call this routine with a NULL pointer (nothing
    will be done).

   INPUTS
    imsg - A modified IntuiMessage obtained with GT_GetIMsg().

   RESULT
    None.

   EXAMPLE

   NOTES
    When using GadTools, you MUST explicitly GT_ReplyIMsg()
    all messages you receive.  You cannot depend on CloseWindow()
    to handle messages you have not replied.

   BUGS

   SEE ALSO
    GT_GetIMsg()

 gadtools.library/GT_SetGadgetAttrsA       gadtools.library/GT_SetGadgetAttrsA

   NAME
    GT_SetGadgetAttrsA -- Change the attributes of a GadTools gadget. (V36)
    GT_SetGadgetAttrs -- Varargs stub for GT_SetGadgetAttrsA(). (V36)

   SYNOPSIS
    GT_SetGadgetAttrsA(gad, win, req, taglist)
                       A0   A1   A2   A3

    VOID GT_SetGadgetAttrsA(struct Gadget *, struct Window *,
        struct Requester *, struct TagItem *);

    GT_SetGadgetAttrs(gad, win, req, firsttag, ...)

    VOID GT_SetGadgetAttrs(struct Gadget *, struct Window *,
        struct Requester *, Tag, ...);

   FUNCTION
    Change the attributes of the specified gadget, according to the
    attributes chosen in the tag list.

   INPUTS
    gad - Pointer to the gadget in question.
    win - Pointer to the window containing the gadget.
    req - Pointer to the requester containing the gadget, or NULL if
        not in a requester.  (Not yet implemented, use NULL).
    taglist - Pointer to TagItem list.

   TAGS
    BUTTON_KIND:
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    CHECKBOX_KIND:
    GTCB_Checked (BOOL) - Initial state of checkbox, defaults to FALSE.
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    CYCLE_KIND:
    GTCY_Active (UWORD) - The ordinal number (counting from zero) of
        the active choice of a cycle gadget (defaults to zero).
    GTCY_Labels (STRPTR *) - (GadTools V37 and higher only)
        Pointer to NULL-terminated array of strings
        that are the choices offered by the cycle gadget.
    GA_Disabled (BOOL) - (GadTools V37 and higher only)
        Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    INTEGER_KIND:
    GTIN_Number (ULONG) - The initial contents of the integer gadget
        (default zero).
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    LISTVIEW_KIND:
    GTLV_Top (WORD) - Top item visible in the listview.  This value
        will be made reasonable if out-of-range (defaults to zero).
    GTLV_Labels (struct List *) - List of labels whose ln_Name fields
        are to be displayed in the listview.  Use a value of ~0 to
        "detach" your List from the display.  You must detach your list
        before modifying the List structure, since GadTools reserves
        the right to traverse it on another task's schedule.  When you
        are done, attach the list by using the tag pair
        {GTLV_Labels, list}.
    GTLV_Selected (UWORD) - Ordinal number of currently selected
        item (defaults to zero if GTLV_ShowSelected is set).

    MX_KIND:
    GTMX_Active (UWORD) - The ordinal number (counting from zero) of
        the active choice of an mx gadget (Defaults to zero).

    NUMBER_KIND:
    GTNM_Number - A signed long integer to be displayed as a read-only
         number (default 0).

    PALETTE_KIND:
    GTPA_Color (UBYTE) - Initially selected color of the palette
        (defaults to 1).
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    SCROLLER_KIND:
    GTSC_Top (WORD) - Top visible in scroller (defaults to zero).
    GTSC_Total (WORD) - Total in scroller area (defaults to zero).
    GTSC_Visible (WORD) - Number visible in scroller (defaults to 2).
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    SLIDER_KIND:
    GTSL_Min (WORD) - Minimum level for slider (default 0).
    GTSL_Max (WORD) - Maximum level for slider (default 15).
    GTSL_Level (WORD) - Current level of slider (default 0).
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    STRING_KIND:
    GTST_String (STRPTR) - The initial contents of the string gadget,
         or NULL (default) if string is to start empty.
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).

    TEXT_KIND:
    GTTX_Text - Pointer to a NULL terminated string to be displayed,
        as a read-only text-display gadget, or NULL. defaults to NULL.

   RESULT
    None.

   EXAMPLE

   NOTES
    req must currently be NULL.  GadTools gadgets are not supported
    in requesters.  This field may allow such support at a future date.

    This function may not be called inside of a GT_BeginRefresh() /
    GT_EndRefresh() session.  (As always, restrict yourself to simple
    rendering functions).

   BUGS

   SEE ALSO

 gadtools.library/LayoutMenuItemsA           gadtools.library/LayoutMenuItemsA

   NAME
    LayoutMenuItemsA -- Position all the menu items. (V36)
    LayoutMenuItems -- Varargs stub for LayoutMenuItemsA(). (V36)

   SYNOPSIS
    success = LayoutMenuItemsA(menuitem, vi, taglist)
    D0                         A0        A1  A2

    BOOL LayoutMenuItemsA(struct MenuItem *, APTR, struct TagItem *);

    success = LayoutMenuItems(menuitem, vi, firsttag, ...)

    BOOL LayoutMenuItemsA(struct MenuItem *, APTR, Tag, ...);

   FUNCTION
    Lays out all the menu items and sub-items according to
    the supplied visual information and tag parameters.  You would use this
    if you used CreateMenusA() to make a single menu-pane (with sub-items,
    if any), instead of a whole menu strip.
    This routine attempts to columnize and/or shift the MenuItems in
    the event that a menu would be too tall or too wide.

   INPUTS
    menuitem - Pointer to first MenuItem in a linked list of
        items.
    vi - Pointer returned by GetVisualInfoA().
    taglist - Pointer to a TagItem list.

   TAGS
    GTMN_TextAttr (struct TextAttr *) - Text Attribute to use for
        menu-items and sub-items.  If not supplied, the screen's
        font will be used.  This font must be openable via OpenFont()
        when this function is called.
    GTMN_Menu (struct Menu *) - Pointer to the Menu structure whose
        FirstItem is the MenuItem supplied above.  If the menu items are
        such that they need to be columnized or shifted, the Menu
        structure is needed to perform the complete calculation.
        It is suggested you always provide this information.

   RESULT
    success - TRUE if successful, false otherwise (signifies that
        the TextAttr wasn't openable).

   EXAMPLE

   NOTES

   BUGS
    If a menu ends up being wider than the whole screen, it will
    run off the right-hand side.

   SEE ALSO
    CreateMenusA(), GetVisualInfoA()

 gadtools.library/LayoutMenusA                   gadtools.library/LayoutMenusA

   NAME
    LayoutMenusA -- Position all the menus and menu items. (V36)
    LayoutMenus -- Varargs stub for LayoutMenusA(). (V36)

   SYNOPSIS
    success = LayoutMenusA(menu, vi, taglist)
    D0                     A0    A1  A2

    BOOL LayoutMenusA(struct Menu *, APTR, struct TagItem *);

    success = LayoutMenus(menu, vi, firsttag, ...)

    BOOL LayoutMenus(struct Menu *, APTR, Tag, ...);

   FUNCTION
    Lays out all the menus, menu items and sub-items in the supplied
    menu according to the supplied visual information and tag parameters.
    This routine attempts to columnize and/or shift the MenuItems in
    the event that a menu would be too tall or too wide.

   INPUTS
    menu - Pointer to menu obtained from CreateMenusA().
    vi - Pointer returned by GetVisualInfoA().
    taglist - Pointer to a TagItem list.

   TAGS
    GTMN_TextAttr (struct TextAttr *) - Text Attribute to use for
        menu-items and sub-items.  If not supplied, the screen's
        font will be used.  This font must be openable via OpenFont()
        when this function is called.

   RESULT
    success - TRUE if successful, false otherwise (signifies that
        the TextAttr wasn't openable).

   EXAMPLE

   NOTES
    When using this function, there is no need to also call
    LayoutMenuItemsA().

   BUGS
    If a menu ends up being wider than the whole screen, it will
    run off the right-hand side.

   SEE ALSO
    CreateMenusA(), GetVisualInfoA()


Text_Autodocs/mathieeedoubbas.doc

TABLE OF CONTENTS

mathieeedoubbas.library/IEEEDPAbs
mathieeedoubbas.library/IEEEDPAdd
mathieeedoubbas.library/IEEEDPCeil
mathieeedoubbas.library/IEEEDPCmp
mathieeedoubbas.library/IEEEDPDiv
mathieeedoubbas.library/IEEEDPFix
mathieeedoubbas.library/IEEEDPFloor
mathieeedoubbas.library/IEEEDPFlt
mathieeedoubbas.library/IEEEDPMul
mathieeedoubbas.library/IEEEDPNeg
mathieeedoubbas.library/IEEEDPSub
mathieeedoubbas.library/IEEEDPTst
 mathieeedoubbas.library/IEEEDPAbs           mathieeedoubbas.library/IEEEDPAbs

   NAME
    IEEEDPAbs -- compute absolute value of IEEE double precision argument

   SYNOPSIS
      x   = IEEEDPAbs(  y  );
    d0/d1		  d0/d1

    double	x,y;

   FUNCTION
    Take the absolute value of argument y and return it to caller.

   INPUTS
    y -- IEEE double precision floating point value

   RESULT
    x -- IEEE double precision floating point value

   BUGS

   SEE ALSO
 mathieeedoubbas.library/IEEEDPAdd           mathieeedoubbas.library/IEEEDPAdd

   NAME
    IEEEDPAdd -- add one double precision IEEE number to another

   SYNOPSIS
      x   = IEEEDPAdd(  y  ,  z  );
    d0/d1		  d0/d1 d2/d3

    double	x,y,z;

   FUNCTION
    Compute x = y + z in IEEE double precision.

   INPUTS
    y -- IEEE double precision floating point value
    z -- IEEE double precision floating point value

   RESULT
    x -- IEEE double precision floating point value

   BUGS

   SEE ALSO
    IEEEDPSub
 mathieeedoubbas.library/IEEEDPCeil         mathieeedoubbas.library/IEEEDPCeil

   NAME
    IEEEDPCeil -- compute Ceil function of IEEE double precision number

   SYNOPSIS
      x   = IEEEDPCeil(  y  );
    d0/d1		   d0/d1

    double	x,y;

   FUNCTION
    Calculate the least integer greater than or equal to x and return it.
    This value may have more than 32 bits of significance.
    This identity is true.  Ceil(x) = -Floor(-x).

   INPUTS
    y -- IEEE double precision floating point value

   RESULT
    x -- IEEE double precision floating point value

   BUGS

   SEE ALSO
    IEEEDPFloor
 mathieeedoubbas.library/IEEEDPCmp           mathieeedoubbas.library/IEEEDPCmp

   NAME
    IEEEDPCmp -- compare two double precision floating point numbers

   SYNOPSIS
      c   = IEEEDPCmp(  y  ,  z  );
      d0		  d0/d1 d2/d3

    double	y,z;
    long	c;

   FUNCTION
    Compare y with z. Set the condition codes for less, greater, or
    equal. Set return value c to -1 if y<z, or +1 if y>z, or 0 if
    y == z.

   INPUTS
    y -- IEEE double precision floating point value
    z -- IEEE double precision floating point value

   RESULT
       c = 1   cc = gt         for (y > z)
       c = 0   cc = eq         for (y == z)
       c = -1  cc = lt         for (y < z)

   BUGS

   SEE ALSO
 mathieeedoubbas.library/IEEEDPDiv           mathieeedoubbas.library/IEEEDPDiv

   NAME
    IEEEDPDiv -- divide one double precision IEEE by another

   SYNOPSIS
      x   = IEEEDPDiv(  y  ,  z  );
    d0/d1		  d0/d1 d2/d3

    double	x,y,z;

   FUNCTION
    Compute x = y / z in IEEE double precision.

   INPUTS
    y -- IEEE double precision floating point value
    z -- IEEE double precision floating point value

   RESULT
    x -- IEEE double precision floating point value

   BUGS

   SEE ALSO
    IEEEDPMul
 mathieeedoubbas.library/IEEEDPFix           mathieeedoubbas.library/IEEEDPFix

   NAME
    IEEEDPFix -- convert IEEE double float to integer

   SYNOPSIS
    x   = IEEEDPFix(  y  );
    d0		d0/d1

    long	x;
    double	y;

   FUNCTION
    Convert IEEE double precision argument to a 32 bit signed integer
    and return result.

   INPUTS
    y -- IEEE double precision floating point value

   RESULT
    if no overflow occured then return
        x -- 32 bit signed integer
    if overflow return largest +- integer
        For round to zero

   BUGS

   SEE ALSO
    IEEEDPFlt
 mathieeedoubbas.library/IEEEDPFloor       mathieeedoubbas.library/IEEEDPFloor

   NAME
    IEEEDPFloor -- compute Floor function of IEEE double precision number

   SYNOPSIS
      x   = IEEEDPFloor(  y  );
    d0/d1		    d0/d1

    double	x,y;

   FUNCTION
    Calculate the largest integer less than or equal to x and return it.
    This value may have more than 32 bits of significance.

   INPUTS
    y -- IEEE double precision floating point value

   RESULT
    x -- IEEE double precision floating point value

   BUGS

   SEE ALSO
    IEEEDPCeil
 mathieeedoubbas.library/IEEEDPFlt           mathieeedoubbas.library/IEEEDPFlt

   NAME
    IEEEDPFlt -- convert integer to IEEE double precision number

   SYNOPSIS
      x   = IEEEDPFlt(  y  );
    d0/d1		   d0

    double	x;
    long	y;

   FUNCTION
    Convert a signed 32 bit value to a double precision IEEE value
    and return it in d0/d1. No exceptions can occur with this
    function.

   INPUTS
    y -- 32 bit integer in d0

   RESULT
    x is a 64 bit double precision IEEE value

   BUGS

   SEE ALSO
    IEEEDPFix
 mathieeedoubbas.library/IEEEDPMul           mathieeedoubbas.library/IEEEDPMul

   NAME
    IEEEDPMul -- multiply one double precision IEEE number by another

   SYNOPSIS
      x   = IEEEDPMul(  y  ,  z  );
    d0/d1		  d0/d1 d2/d3

    double	x,y,z;

   FUNCTION
    Compute x = y * z in IEEE double precision.

   INPUTS
    y -- IEEE double precision floating point value
    z -- IEEE double precision floating point value

   RESULT
    x -- IEEE double precision floating point value

   BUGS

   SEE ALSO
    IEEEDPDiv
 mathieeedoubbas.library/IEEEDPNeg           mathieeedoubbas.library/IEEEDPNeg

   NAME
    IEEEDPNeg -- compute negative value of IEEE double precision number

   SYNOPSIS
      x   = IEEEDPNeg(  y  );
    d0/d1		  d0/d1

    double	x,y;

   FUNCTION
    Invert the sign of argument y and return it to caller.

   INPUTS
    y - IEEE double precision floating point value

   RESULT
    x - IEEE double precision floating point value

   BUGS

   SEE ALSO
 mathieeedoubbas.library/IEEEDPSub           mathieeedoubbas.library/IEEEDPSub

   NAME
    IEEEDPSub -- subtract one double precision IEEE number from another

   SYNOPSIS
      x   = IEEEDPSub(  y  ,  z  );
    d0/d1		  d0/d1 d2/d3

    double	x,y,z;

   FUNCTION
    Compute x = y - z in IEEE double precision.

   INPUTS
    y -- IEEE double precision floating point value
    z -- IEEE double precision floating point value

   RESULT
    x -- IEEE double precision floating point value

   BUGS

   SEE ALSO
    IEEEDPAdd
 mathieeedoubbas.library/IEEEDPTst           mathieeedoubbas.library/IEEEDPTst

   NAME
    IEEEDPTst -- compare IEEE double precision value to 0.0

   SYNOPSIS
      c   = IEEEDPTst(  y  );
      d0		  d0/d1

    double	y;
    long	c;

   FUNCTION
    Compare y to 0.0, set the condition codes for less than, greater
    than, or equal to 0.0.  Set the return value c to -1 if less than,
    to +1 if greater than, or 0 if equal to 0.0.

   INPUTS
    y -- IEEE double precision floating point value

   RESULT
    c = 1	cc = gt		for (y > 0.0)
    c = 0	cc = eq		for (y == 0.0)
    c = -1  cc = lt		for (y < 0.0)

   BUGS

   SEE ALSO


Text_Autodocs/wb.doc

TABLE OF CONTENTS

workbench.library/AddAppIconA
workbench.library/AddAppMenuItemA
workbench.library/AddAppWindowA
workbench.library/RemoveAppIcon
workbench.library/RemoveAppMenuItem
workbench.library/RemoveAppWindow
 workbench.library/AddAppIconA                   workbench.library/AddAppIconA

   NAME
    AddAppIcon - add an icon to workbench's list of appicons.        (V36)

   SYNOPSIS
    AppIcon = AddAppIconA(id, userdata, text, msgport,
       D0		      D0     D1      A0     A1

                    lock, diskobj, taglist)
                     A2      A3      A4

    struct AppIcon *AddAppIconA(ULONG, ULONG, char *,
        struct MsgPort *, struct FileLock *, struct DiskObject *,
        struct TagItem *);

    Alternate, varargs version:
    struct AppIcon *AddAppIcon(ULONG, ULONG, char *,
            struct MsgPort *, struct FileLock *,
            struct DiskObject *,
            tag1, data1,
            tag2, data2,
            ...
            TAG_END );

   FUNCTION
    Attempt to add an icon to workbench's list of appicons.  If
    successful, the icon is displayed on the workbench (the same
    place disk icons are displayed).
    This call is provided to allow applications to be notified when
    a graphical object (non neccessarely associated with a file)
    gets 'manipulated'. (explained later).
    The notification consists of an AppMessage (found in workbench.h/i)
    of type 'MTYPE_APPICON' arriving at the message port you specified.
    The types of 'manipulation' that can occur are:
    1. Double-clicking on the icon.  am_NumArgs will be zero and
       am_ArgList will be NULL.
    2. Dropping an icon or icons on your appicon.  am_NumArgs will
          be the number of icons droppped on your app icon plus one.
          am_ArgList will be an array of ptrs to WBArg structures.
          Refer to the 'WBStartup Message' section of the RKM for more info.
    3. Dropping your appicon on another icon.  NOT SUPPORTED.

   INPUTS
    id - this variable is strictly for your own use and is ignored by
         workbench.  Typical uses in C are in switch and case statements,
         and in assembly language table lookup.
    userdata - this variable is strictly for your own use and is ignored
           by workbench.
    text - name of icon (char *)
    lock - NULL    (Currently unused)
    msgport - pointer to message port workbench will use to send you an
          AppMessage message of type 'MTYPE_APPICON' when your icon
          gets 'manipulted' (explained above).
    diskobj - pointer to a DiskObject structure filled in as follows:
        do_Magic - NULL
        do_Version - NULL
        do_Gadget - a gadget structure filled in as follows:
        NextGadget - NULL
        LeftEdge - NULL
        TopEdge - NULL
        Width - width of icon hit-box
        Height - height of icon hit-box
        Flags - NULL or GADGHIMAGE
        Activation - NULL
        GadgetType - NULL
        GadgetRender - pointer to Image structure filled in as follows:
            LeftEdge - NULL
            TopEdge - NULL
            Width - width of image (must be <= Width of hit box)
            Height - height of image (must be <= Height of hit box)
            Depth - # of bit-planes in image
            ImageData - pointer to actual word aligned bits (CHIP MEM)
            PlanePick - Plane mask ((1 << depth) - 1)
            PlaneOnOff - 0
            NextImage - NULL
        SelectRender - pointer to alternate Image struct or NULL
        GadgetText - NULL
        MutualExclude - NULL
        SpecialInfo - NULL
        GadgetID - NULL
        UserData - NULL
        do_Type - NULL
        do_DefaultTool - NULL
        do_ToolTypes - NULL
        do_CurrentX - NO_ICON_POSITION (recommended)
        do_CurrentY - NO_ICON_POSITION (recommended)
        do_DrawerData - NULL
        do_ToolWindow - NULL
        do_StackSize - NULL

    (an easy way to create one of these (a DiskObject) is to create an icon
        with the V2.0 icon editor and save it out.  Your application can then
        call GetDiskObject on it and pass that to AddAppIcon.)

    taglist - ptr to a list of tag items.  Must be NULL for V2.0.

   RESULTS
    AppIcon - a pointer to an appicon structure which you pass to
          RemoveAppIcon when you want to remove the icon
          from workbench's list of appicons.  NULL
          if workbench was unable to add your icon; typically
          happens when workbench is not running or under low
          memory conditions.

   EXAMPLE
    You could design a print-spooler icon and add it to the workbench.
    Any file dropped on the print spooler would be printed.  If the
    user double-clicked (opended) your printer-spooler icon, you could
    open a window showing the status of the print spool, allow changes
    to print priorities, allow deletions, etc.  If you registered this
    window as an 'appwindow' (explained in workbench.library AddAppWindow)
    files could also be dropped in the window and added to the spool.

   SEE ALSO
    RemoveAppIcon()

   BUGS
    Currently Info cannot be obtained on appicons.

 workbench.library/AddAppMenuItemA           workbench.library/AddAppMenuItemA

   NAME
    AddAppMenuItem - add a menuitem to workbench's list              (V36)
                        of appmenuitems.

   SYNOPSIS
    AppMenuItem = AddAppMenuItemA(id, userdata, text, msgport, taglist)
    D0			      D0     D1      A0     A1       A2

    struct AppMenuItem *AddAppMenuItemA(ULONG, ULONG, char *,
                        struct MsgPort *,
                        struct TagItem *);

    Alternate, varargs version:
    struct AppMenuItem *AddAppMenuItem(ULONG, ULONG, char *,
                    struct MsgPort *,
                    tag1, data1,
                    tag2, data2,
                    ...
                    TAG_END );

   FUNCTION
    Attempt to add the text as a menuitem to workbench's list
    of appmenuitems (the 'Tools' menu strip).

   INPUTS
    id - this variable is strictly for your own use and is ignored by
         workbench.  Typical uses in C are in switch and case statements,
         and in assembly language table lookup.
    userdata - this variable is strictly for your own use and is ignored
           by workbench.
    text - text for the menuitem (char *)
    msgport - pointer to message port workbench will use to send you an
          AppMessage message of type 'MTYPE_APPMENUITEM' when your
          menuitem gets selected.
    taglist - ptr to a list of tag items.  Must be NULL for V2.0.

   RESULTS
    AppMenuItem - a pointer to an appmenuitem structure which you pass to
              RemoveAppMenuItem when you want to remove the menuitem
              from workbench's list of appmenuitems.  NULL if
              workbench was unable to add your menuitem; typically
              happens when workbench is not running or under low
              memory conditions.

   SEE ALSO
    RemoveAppMenuItem()

   BUGS
    Currently does not limit the system to 63 menu items...
    Any menu items after the 63rd will not be selectable.

 workbench.library/AddAppWindowA               workbench.library/AddAppWindowA

   NAME
    AddAppWindow - add a window to workbench's list of appwindows.  (V36)

   SYNOPSIS
    AppWindow = AddAppWindowA(id, userdata, window, msgport, taglist)
    D0			  D0     D1       A0      A1       A2

    struct AppWindow *AddAppWindowA(ULONG, ULONG, struct Window *,
                    struct MsgPort *, struct TagItem *);

    Alternate, varargs version:
    struct AppWindow *AddAppWindow(ULONG, ULONG, struct Window *,
                    struct MsgPort *
                    tag1, data1,
                    tag2, data2,
                    ...
                    TAG_END );

   FUNCTION
    Attempt to add the window to workbench's list of appwindows.
    Normally non-workbench windows (those not opened by workbench)
    cannot have icons dropped in them.  This call is provided to
    allow applications to be notified when an icon or icons get
    dropped inside a window that they have registered with workbench.
    The notification consists of an AppMessage (found in workbench.h/i)
    of type 'MTYPE_APPWINDOW' arriving at the message port you specified.
    What you do with the list of icons (pointed to by am_ArgList) is
    up to you, but generally you would want to call GetDiskObjectNew on
    them.

   INPUTS
    id - this variable is strictly for your own use and is ignored by
         workbench.  Typical uses in C are in switch and case statements,
         and in assembly language table lookup.
    userdata - this variable is strictly for your own use and is ignored
           by workbench.
    window - pointer to window to add.
    msgport - pointer to message port workbench will use to send you an
          AppMessage message of type 'MTYPE_APPWINDOW' when your
          window gets an icon or icons dropped in it.
    taglist - ptr to a list of tag items.  Must be NULL for V2.0.

   RESULTS
    AppWindow - a pointer to an appwindow structure which you pass to
            RemoveAppWindow when you want to remove the window
            from workbench's list of appwindows.  NULL
            if workbench was unable to add your window; typically
            happens when workbench is not running or under low
            memory conditions.

   SEE ALSO
    RemoveAppWindow()

   NOTES
       The V2.0 icon editor is an example of an app window.  Note that app
       window applications generally want to call GetDiskObjectNew
       (as opposed to GetDiskObject) to get the disk object for the icon
       dropped in the window.

   BUGS
    None

 workbench.library/RemoveAppIcon               workbench.library/RemoveAppIcon

   NAME
    RemoveAppIcon - remove an icon from workbench's list            (V36)
                         of appicons.

   SYNOPSIS
    error = RemoveAppIcon(AppIcon)
         D0                     A0
    BOOL RemoveAppIcon(struct AppIcon *);

   FUNCTION
    Attempt to remove an appicon from workbench's list of appicons.

   INPUTS
    AppIcon - pointer to an AppIcon structure returned by AddAppIcon.

   RESULTS
    error - Currently always TRUE...

   NOTES
    As with anything that deals with async operation, you will need to
    do a final check for messages on your App message port for messages
    that may have come in between the last time you checked and the
    call to removed the App.

   SEE ALSO
    AddAppIconA()

   BUGS
    None

 workbench.library/RemoveAppMenuItem       workbench.library/RemoveAppMenuItem

   NAME
    RemoveAppMenuItem - remove a menuitem from workbench's list      (V36)
                of appmenuitems.

   SYNOPSIS
    error = RemoveAppMenuItem(AppMenuItem)
         D0                            A0
    BOOL RemoveAppMenuItem(struct AppMenuItem *);

   FUNCTION
    Attempt to remove an appmenuitem from workbench's list
    of appmenuitems.

   INPUTS
    AppMenuItem - pointer to an AppMenuItem structure returned by
              AddAppMenuItem.

   RESULTS
    error - Currently always TRUE...

   NOTES
    As with anything that deals with async operation, you will need to
    do a final check for messages on your App message port for messages
    that may have come in between the last time you checked and the
    call to removed the App.

   SEE ALSO
    AddAppMenuItemA()

   BUGS
    None

 workbench.library/RemoveAppWindow           workbench.library/RemoveAppWindow

   NAME
    RemoveAppWindow - remove a window from workbench's list         (V36)
                          of appwindows.

   SYNOPSIS
    error = RemoveAppWindow(AppWindow)
         D0                       A0
    BOOL RemoveAppWindow(struct AppWindow *);

   FUNCTION
    Attempt to remove an appwindow from workbench's list of appwindows.

   INPUTS
    AppWindow - pointer to an AppWindow structure returned by
            AddAppWindow.

   RESULTS
    error - Currently always TRUE...

   NOTES
    As with anything that deals with async operation, you will need to
    do a final check for messages on your App message port for messages
    that may have come in between the last time you checked and the
    call to removed the App.

   SEE ALSO
    AddAppWindowA()

   BUGS
    None


Text_Autodocs/graphics.doc

TABLE OF CONTENTS

graphics.library/AddAnimOb
graphics.library/AddBob
graphics.library/AddFont
graphics.library/AddVSprite
graphics.library/AllocRaster
graphics.library/AndRectRegion
graphics.library/AndRegionRegion
graphics.library/Animate
graphics.library/AreaCircle
graphics.library/AreaDraw
graphics.library/AreaEllipse
graphics.library/AreaEnd
graphics.library/AreaMove
graphics.library/AskFont
graphics.library/AskSoftStyle
graphics.library/AttemptLockLayerRom
graphics.library/BitMapScale
graphics.library/BltBitMap
graphics.library/BltBitMapRastPort
graphics.library/BltClear
graphics.library/BltMaskBitMapRastPort
graphics.library/BltPattern
graphics.library/BltTemplate
graphics.library/CBump
graphics.library/CEND
graphics.library/ChangeSprite
graphics.library/CINIT
graphics.library/ClearEOL
graphics.library/ClearRectRegion
graphics.library/ClearRegion
graphics.library/ClearScreen
graphics.library/ClipBlit
graphics.library/CloseFont
graphics.library/CloseMonitor
graphics.library/CMOVE
graphics.library/CopySBitMap
graphics.library/CWAIT
graphics.library/DisownBlitter
graphics.library/DisposeRegion
graphics.library/DoCollision
graphics.library/Draw
graphics.library/DrawEllipse
graphics.library/DrawGList
graphics.library/EraseRect
graphics.library/ExtendFont
graphics.library/FindDisplayInfo
graphics.library/Flood
graphics.library/FontExtent
graphics.library/FreeColorMap
graphics.library/FreeCopList
graphics.library/FreeCprList
graphics.library/FreeGBuffers
graphics.library/FreeRaster
graphics.library/FreeSprite
graphics.library/FreeVPortCopLists
graphics.library/GetColorMap
graphics.library/GetDisplayInfoData
graphics.library/GetGBuffers
graphics.library/GetRGB4
graphics.library/GetSprite
graphics.library/GetVPModeID
graphics.library/GfxAssociate
graphics.library/GfxFree
graphics.library/GfxLookUP
graphics.library/GfxNew
graphics.library/InitArea
graphics.library/InitBitMap
graphics.library/InitGels
graphics.library/InitGMasks
graphics.library/InitMasks
graphics.library/InitRastPort
graphics.library/InitTmpRas
graphics.library/InitView
graphics.library/InitVPort
graphics.library/LoadRGB4
graphics.library/LoadView
graphics.library/LockLayerRom
graphics.library/MakeVPort
graphics.library/ModeNotAvailable
graphics.library/Move
graphics.library/MoveSprite
graphics.library/MrgCop
graphics.library/NewRegion
graphics.library/NextDisplayInfo
graphics.library/OpenFont
graphics.library/OpenMonitor
graphics.library/OrRectRegion
graphics.library/OrRegionRegion
graphics.library/OwnBlitter
graphics.library/PolyDraw
graphics.library/QBlit
graphics.library/QBSBlit
graphics.library/ReadPixel
graphics.library/ReadPixelArray8
graphics.library/ReadPixelLine8
graphics.library/RectFill
graphics.library/RemBob
graphics.library/RemFont
graphics.library/RemIBob
graphics.library/RemVSprite
graphics.library/ScalerDiv
graphics.library/ScrollRaster
graphics.library/ScrollVPort
graphics.library/SetAPen
graphics.library/SetBPen
graphics.library/SetCollision
graphics.library/SetDrMd
graphics.library/SetFont
graphics.library/SetOPen
graphics.library/SetRast
graphics.library/SetRGB4
graphics.library/SetRGB4CM
graphics.library/SetSoftStyle
graphics.library/SortGList
graphics.library/StripFont
graphics.library/SyncSBitMap
graphics.library/Text
graphics.library/TextExtent
graphics.library/TextFit
graphics.library/TextLength
graphics.library/UnlockLayerRom
graphics.library/VBeamPos
graphics.library/VideoControl
graphics.library/WaitBlit
graphics.library/WaitBOVP
graphics.library/WaitTOF
graphics.library/WeighTAMatch
graphics.library/WritePixel
graphics.library/WritePixelArray8
graphics.library/WritePixelLine8
graphics.library/XorRectRegion
graphics.library/XorRegionRegion
 graphics.library/AddAnimOb                         graphics.library/AddAnimOb

   NAME
    AddAnimOb  --  Add an AnimOb to the linked list of AnimObs.

   SYNOPSIS
    AddAnimOb(anOb, anKey, rp)
              A0    A1     A2

    void AddAnimOb(struct AnimOb *,struct AnimOb **, struct RastPort *);

   FUNCTION
    Links this AnimOb into the current list pointed to by animKey.
    Initializes all the Timers of the AnimOb's components.
    Calls AddBob with each component's Bob.
    rp->GelsInfo must point to an initialized GelsInfo structure.

   INPUTS
    anOb  = pointer to the AnimOb structure to be added to the list
    anKey = address of a pointer to the first AnimOb in the list
            (anKey = NULL if there are no AnimObs in the list so far)
    rp    = pointer to a valid RastPort

   RESULT

   BUGS

   SEE ALSO
    Animate() graphics/rastport.h graphics/gels.h
 graphics.library/AddBob                               graphics.library/AddBob

   NAME
    AddBob -- Adds a Bob to current gel list.

   SYNOPSIS
    AddBob(Bob, rp)
           A0   A1

    void AddBob(struct Bob *, struct RastPort *);

   FUNCTION
    Sets up the system Bob flags, then links this gel into the list
    via AddVSprite.

   INPUTS
    Bob = pointer to the Bob structure to be added to the gel list
    rp  = pointer to a RastPort structure

   RESULT

   BUGS

   SEE ALSO
    InitGels()  AddVSprite()  graphics/gels.h  graphics/rastport.h

 graphics.library/AddFont                             graphics.library/AddFont

   NAME
    AddFont -- add a font to the system list

   SYNOPSIS
    AddFont(textFont)
            A1

    void AddFont(struct TextFont *);

   FUNCTION
    This function adds the text font to the system, making it
    available for use by any application.  The font added must be
    in public memory, and remain until successfully removed.

   INPUTS
    textFont - a TextFont structure in public ram.

   RESULT

   BUGS

   SEE ALSO
    SetFont()  RemFont()  graphics/text.h

 graphics.library/AddVSprite                       graphics.library/AddVSprite

   NAME
    AddVSprite -- Add a VSprite to the current gel list.

   SYNOPSIS
    AddVSprite(vs, rp)
               A0  A1

    void AddVSprite(struct VSprite *, struct RastPort *);

   FUNCTION
    Sets up the system VSprite flags
    Links this VSprite into the current gel list using its Y,X

   INPUTS
    vs = pointer to the VSprite structure to be added to the gel list
    rp = pointer to a RastPort structure

   RESULT

   BUGS

   SEE ALSO
    InitGels()  graphics/rastport.h  graphics/gels.h

 graphics.library/AllocRaster                     graphics.library/AllocRaster

   NAME
    AllocRaster -- Allocate space for a bitplane.

   SYNOPSIS
    planeptr = AllocRaster( width, height )
       d0                    d0:16  d1:16

    PLANEPTR AllocRaster(UWORD,UWORD);

   FUNCTION
    This function calls the memory allocation routines
    to allocate memory space for a bitplane width bits
    wide and height bits high.

   INPUTS
    width	- number of bits wide for bitplane
    height	- number of rows in bitplane

   RESULT
    planeptr - pointer to first word in bitplane, or NULL if
           it was not possible to allocate the desired
           amount of memory.
   BUGS

   SEE ALSO
    FreeRaster() graphics/gfx.h

 graphics.library/AndRectRegion                 graphics.library/AndRectRegion

   NAME
    AndRectRegion -- Perform 2d AND operation of rectangle
             with region, leaving result in region.

   SYNOPSIS
    AndRectRegion(region,rectangle)
             a0	a1

    void AndRectRegion( struct Region *, struct Rectangle * );

   FUNCTION
    Clip away any portion of the region that exists outside
    of the rectangle. Leave the result in region.

   INPUTS
    region - pointer to Region structure
    rectangle - pointer to Rectangle structure

   NOTES
    Unlike the other rect-region primitives, AndRectRegion() cannot
    fail.

   BUGS

   SEE ALSO
    AndRegionRegion() OrRectRegion() graphics/regions.h

 graphics.library/AndRegionRegion             graphics.library/AndRegionRegion

   NAME
       AndRegionRegion -- Perform 2d AND operation of one region
                       with second region, leaving result in second region.

   SYNOPSIS
       status = AndRegionRegion(region1,region2)
          d0                       a0      a1

    BOOL AndRegionRegion(struct Region *, struct Region * );

   FUNCTION
       Remove any portion of region2 that is not in region1.

   INPUTS
       region1 - pointer to Region structure
       region2 - pointer to Region structure to use and for result

   RESULTS
    status - return TRUE if successful operation
         return FALSE if ran out of memory

   BUGS

   SEE ALSO
    OrRegionRegion() AndRectRegion() graphics/regions.h

 graphics.library/Animate                             graphics.library/Animate

   NAME
    Animate  --  Processes every AnimOb in the current animation list.

   SYNOPSIS
    Animate(anKey, rp)
            A0     A1

    void Animate(struct AnimOb **, struct RastPort *);

   FUNCTION
    For every AnimOb in the list
        - update its location and velocities
        - call the AnimOb's special routine if one is supplied
        - for each component of the AnimOb
            - if this sequence times out, switch to the new one
            - call this component's special routine if one is supplied
            - set the sequence's VSprite's y,x coordinates based
              on whatever these routines cause

   INPUTS
    ankey = address of the variable that points to the head AnimOb
    rp    = pointer to the RastPort structure

   RESULT

   BUGS

   SEE ALSO
    AddAnimOb() graphics/gels.h graphics/rastport.h

 graphics.library/AreaCircle                       graphics.library/AreaCircle

    NAME
    AreaCircle -- add a circle to areainfo list for areafill.

    SYNOPSIS
    error = (int) AreaCircle( rp,  cx,  cy, radius)
    D0			  A1   D0   D1	D2

    ULONG AreaCircle(struct RastPort *, WORD, WORD, UWORD);

    FUNCTION
    Add circle to the vector buffer. It will be drawn to the rastport when
    AreaEnd is executed.

    INPUTS
    rp	 - pointer to a RastPort structure

    cx, cy   - the coordinates of the center of the desired circle.

    radius	 - is the radius of the circle to draw around the centerpoint.

    RESULTS
    0 if no error
    -1 if no space left in vector list

    NOTES
    This function is actually a macro which calls
        AreaEllipse(rp,cx,cy,radius,radius).

    SEE ALSO
    AreaMove() AreaDraw() AreaCircle() InitArea() AreaEnd()
    graphics/rastport.h graphics/gfxmacros.h

 graphics.library/AreaDraw                           graphics.library/AreaDraw

   NAME
    AreaDraw -- Add a point to a list of end points for areafill.

   SYNOPSIS
    error = AreaDraw( rp,  x,     y)
      d0	          A1 D0:16 D1:16

    ULONG AreaDraw( struct RastPort *, SHORT, SHORT);

   FUNCTION
    Add point to the vector buffer.

   INPUTS
    rp	- points to a RastPort structure.
    x,y	- are coordinates of a point in the raster.

   RESULT
    error	- zero for success, else -1 if no there was no space
          left in the vector list.

   BUGS

   SEE ALSO
    AreaMove() InitArea() AreaEnd() graphics/rastport.h

 graphics.library/AreaEllipse                     graphics.library/AreaEllipse

    NAME
    AreaEllipse -- add a ellipse to areainfo list for areafill.

    SYNOPSIS
    error = AreaEllipse( rp, cx,   cy,   a,    b    )
    d0		     a1  d0:16 d1:16 d2:16 d3:16

    LONG AreaEllipse( struct RastPort *, SHORT, SHORT, SHORT, SHORT)

    FUNCTION
    Add an ellipse to the vector buffer. It will be draw when AreaEnd() is
    called.

    INPUTS
    rp - pointer to a RastPort structure
    cx - x coordinate of the centerpoint relative to the rastport.
    cy - y coordinate of the centerpoint relative to the rastport.
    a  - the horizontal radius of the ellipse (note: a must be > 0)
    b  - the vertical radius of the ellipse (note: b must be > 0)

    RESULT
    error - zero for success, or -1 if there is no space left in the
        vector list

    SEE ALSO
    AreaMove() AreaDraw() AreaCircle() InitArea() AreaEnd()
    graphics/rastport.h

 graphics.library/AreaEnd                             graphics.library/AreaEnd

   NAME
    AreaEnd -- Process table of vectors and ellipses and produce areafill.

   SYNOPSIS
    error = AreaEnd(rp)
      d0  	        A1

    LONG AreaEnd( struct RastPort * );

   FUNCTION
    Trigger the filling operation.
    Process the vector buffer and generate required
    fill into the raster planes. After the fill is complete, reinitialize
    for the next AreaMove or AreaEllipse. Use the raster set up by
    InitTmpRas when generating an areafill mask.

   RESULT
    error - zero for success, or -1 if an error occured anywhere.

   INPUTS
    rp - pointer to a RastPort structure which specifies where the filled
         regions will be rendered to.

   BUGS

   SEE ALSO
    InitArea() AreaMove() AreaDraw() AreaEllipse()  InitTmpRas()
    graphics/rastport.h

 graphics.library/AreaMove                           graphics.library/AreaMove

   NAME
    AreaMove -- Define a new starting point for a new
                shape in the vector list.

   SYNOPSIS
    error =  AreaMove( rp,   x,     y)
     d0                a1  d0:16  d1:16

    LONG AreaMove( struct RastPort *, SHORT, SHORT );

   FUNCTION
    Close  the last polygon and start another polygon
    at  (x,y). Add the necessary  points  to  vector
    buffer. Closing a polygon may result in the generation
    of another AreaDraw() to close previous polygon.
    Remember to have an initialized AreaInfo structure attached
    to the RastPort.

   INPUTS
    rp  - points to a RastPort structure
    x,y - positions in the raster

   RETURNS
    error - zero for success, or -1 if there is no space left in the
    vector list

   BUGS

   SEE ALSO
    InitArea() AreaDraw() AreaEllipse() AreaEnd() graphics/rastport.h

 graphics.library/AskFont                             graphics.library/AskFont

   NAME
    AskFont -- get the text attributes of the current font

   SYNOPSIS
    AskFont(rp, textAttr)
            A1  A0

    void AskFont(struct RastPort *, struct TextAttr *);

   FUNCTION
    This function fills the text attributes structure with the
    attributes of the current font in the RastPort.

   INPUTS
    rp       - the RastPort from which the text attributes are
               extracted
    textAttr - the TextAttr structure to be filled.  Note that
               there is no support for a TTextAttr.

   RESULT
    The textAttr structure is filled with the RastPort's text
    attributes.

   BUGS

   SEE ALSO
    graphics/text.h

 graphics.library/AskSoftStyle                   graphics.library/AskSoftStyle

   NAME
    AskSoftStyle -- Get the soft style bits of the current font.

   SYNOPSIS
    enable = AskSoftStyle(rp)
    D0                    A1

    ULONG AskSoftStyle(struct RastPort *);

   FUNCTION
    This function returns those style bits of the current font
    that are not intrinsic in the font itself, but
    algorithmically generated.  These are the bits that are
    valid to set in the enable mask for SetSoftStyle().

   INPUTS
    rp - the RastPort from which the font and style	are extracted.

   RESULTS
    enable - those bits in the style algorithmically generated.
             Style bits that are not defined are also set.

   BUGS

   SEE ALSO
    SetSoftStyle()  graphics/text.h

 graphics.library/AttemptLockLayerRom     graphics.library/AttemptLockLayerRom
                           *
   NAME
    AttemptLockLayerRom -- Attempt to Lock Layer structure
                     by rom(gfx lib) code

   SYNOPSIS
    gotit = AttemptLockLayerRom( layer )
     d0			      a5

    BOOL AttempLockLayerRom( struct Layer * );

   FUNCTION
    Query the current state of the lock on this Layer. If it is
    already locked then return FALSE, could not lock. If the
    Layer was not locked then lock it and return TRUE.
    This call does not destroy any registers.
    This call nests so that callers in this chain will not lock
    themselves out.

   INPUTS
    layer - pointer to Layer structure

   RESULT
    gotit - TRUE or FALSE depending on whether the Layer was
        successfully locked by the caller.

   SEE ALSO
    LockLayerRom() UnlockLayerRom()

 graphics.library/BitMapScale                     graphics.library/BitMapScale

   NAME
    BitMapScale -- Perform raster scaling on a bit map. (V36)

   SYNOPSIS
    BitMapScale(bitScaleArgs)
                A0

    void BitMapScale(struct BitScaleArgs *);

   FUNCTION
    Scale a source bit map to a non-overlapping destination
    bit map.

   INPUTS
    bitScaleArgs - structure of parameters describing scale:
        bsa_SrcX, bsa_SrcY - origin of the source bits.
        bsa_SrcWidth, bsa_SrcHeight - number of bits to scale from in x
        and y.
        bsa_DestX, bsa_DestY - origin of the destination.
        bsa_DestWidth, bsa_DestHeight - resulting number of bits in x
        and y.  NOTE: these values are set by this function.
        bsa_XSrcFactor:bsa_XDestFactor - equivalant to the ratio
            srcWidth:destWidth, but not necessarily the same
            numbers.  Each must be in the range 1..16383.
        bsa_YSrcFactor:bsa_YDestFactor - equivalant to the ratio
            srcHeight:destHeight, but not necessarily the same
            numbers.  Each must be in the range 1..16383.
        bsa_SrcBitMap - source of the bits to scale.
        bsa_DestBitMap - destination for the bits to scale.  This had
            better be big enough!
        bsa_Flags - future scaling options.  Set it to zero!
        bsa_XDDA, bsa_YDDA - for future use.  Need not be set by user.
        bsa_Reserved1, bsa_Reserved2 - for future use.  Need not be set.

   RESULT
    The destWidth, destHeight fields are set by this function as
    described above.

   NOTES
    o   This function may use the blitter.
    o   Overlapping source and destination bit maps are not
        supported.
    o   No check is made to ensure destBitMap is big enough: use
        ScalerDiv to calculate a destination dimension.

   BUGS
    o   This function does not use the HighRes Agnus 'Big Blit'
        facility. You should not use XSrcFactor == XDestFactor,
        where SrcWidth or DestWidth > 1024.

    o   Also, the blitter is used when expanding in the Y direction.
        You should not expand in the Y direction if
        ((DestX & 0xf) + DestWidth) >= 1024 pixels. (Up to 1008 pixels
        is always safe).

   SEE ALSO
    ScalerDiv()  graphics/scale.h

 graphics.library/BltBitMap                         graphics.library/BltBitMap

   NAME
    BltBitMap -- Move a rectangular region of bits in a BitMap.

   SYNOPSIS
    planecnt = BltBitMap(SrcBitMap, SrcX, SrcY, DstBitMap,
    D0                   A0         D0:16 D1:16 A1
        DstX, DstY, SizeX, SizeY, Minterm, Mask [, TempA])
        D2:16 D3:16 D4:16  D5:16  D6:8     D7:8   [A2]

    ULONG BltBitMap(struct BitMap *, WORD, WORD, struct BitMap *,
        WORD, WORD, WORD, WORD, UBYTE, UBYTE, UWORD *);

   FUNCTION
    Perform non-destructive blits to move a rectangle from one
    area in a BitMap to another area, which can be on a different
    BitMap.
    This blit is assumed to be friendly: no error conditions (e.g.
    a rectangle outside the BitMap bounds) are tested or reported.

   INPUTS
    SrcBitMap, DstBitMap - the BitMap(s) containing the
          rectangles
        - the planes copied from the source to the destination are
          only those whose plane numbers are identical and less
          than the minimum Depth of either BitMap and whose Mask
          bit for that plane is non-zero.
        - as a special case, if a plane pointer in the SrcBitMap
          is zero, it acts as a pointer to a plane of all zeros, and
          if the plane pointer is 0xffffffff, it acts as a pointer
          to a plane of all ones.  (Note: new for V36)
        - SrcBitMap and DstBitMap can be identical if they point
          to actual planes.
    SrcX, SrcY - the x and y coordinates of the upper left corner
        of the source rectangle.  Valid range is positive
        signed integer such that the raster word's offset
        0..(32767-Size)
    DstX, DstY - the x and y coordinates of the upper left
        corner of the destination for the rectangle.  Valid
        range is as for Src.
    SizeX, SizeY - the size of the rectangle to be moved.  Valid
        range is (X: 1..976; Y: 1..1023 such that final raster
        word's offset is 0..32767)
    Minterm - the logic function to apply to the rectangle when
        A is non-zero (i.e. within the rectangle).  B is the
        source rectangle and C, D is the destination for the
        rectangle.
        - $0C0 is a vanilla copy
        - $030 inverts the source before the copy
        - $050 ignores the source and inverts the destination
        - see the hardware reference manual for other combinations
    Mask - the write mask to apply to this operation.  Bits set
        indicate the corresponding planes (if not greater than
        the minimum plane count) are to participate in the
        operation.  Typically this is set to 0xff.
    TempA - If the copy overlaps exactly to the left or right
        (i.e. the scan line addresses overlap), and TempA is
        non-zero, it points to enough chip accessable memory
        to hold a line of A source for the blit (ie CHIP RAM).
        BitBitMap will allocate (and free) the needed TempA if
        none is provided and one is needed.  Blit overlap is
        determined from the relation of the first non-masked
        planes in the source and destination bit maps.

   RESULTS
    planecnt - the number of planes actually involved in the blit.

   NOTES
    o   This function may use the blitter.

   SEE ALSO
    ClipBlit()  graphics/gfx.h  hardware/blit.h

 graphics.library/BltBitMapRastPort         graphics.library/BltBitMapRastPort

   NAME
    BltBitMapRastPort -- Blit from source bitmap to destination rastport.

   SYNOPSIS
    error = BltBitMapRastPort
            (srcbm, srcx, srcy, destrp, destX, destY, sizeX, sizeY, minterm)
     D0      A0     D0    D1    A1      D2     D3     D4     D5     D6

    BOOL BltBitMapRastPort
         (struct BitMap *, WORD, WORD, struct RastPort *, WORD, WORD,
          WORD, WORD, UBYTE);

   FUNCTION
    Blits from source bitmap to position specified in destination rastport
    using minterm.

   INPUTS
    srcbm   - a pointer to the source bitmap
    srcx    - x offset into source bitmap
    srcy    - y offset into source bitmap
    destrp  - a pointer to the destination rastport
    destX   - x offset into dest rastport
    destY   - y offset into dest rastport
    sizeX   - width of blit in pixels
    sizeY   - height of blit in rows
    minterm - minterm to use for this blit

   RESULT
    TRUE

   BUGS

   SEE ALSO
    BltMaskBitMapRastPort() graphics/gfx.h graphics/rastport.h

 graphics.library/BltClear                           graphics.library/BltClear

   NAME

    BltClear - Clear a block of memory words to zero.

   SYNOPSIS
    BltClear( memBlock, bytecount, flags )
            a1         d0       d1

    void BltClear( void *, ULONG, ULONG );

   FUNCTION
    For memory that is local and blitter accessable, the most
    efficient way to clear a range of memory locations is
       to use the system's most efficient data mover, the blitter.
       This command accepts the starting location and count and clears
       that block to zeros.

   INPUTS
    memBloc	- pointer to local memory to be cleared
          memBlock is assumed to be even.
    flags	- set bit 0 to force function to wait until
          the blit is done.
          set bit 1 to use row/bytesperrow.

    bytecount - if (flags & 2) == 0 then
                even number of bytes to clear.
            else
                low 16 bits is taken as number of bytes
                per row and upper 16 bits taken as
                number of rows.

    This function is somewhat hardware dependant. In the rows/bytesperrow
    mode (with the pre-ECS blitter) rows must be <- 1024. In bytecount mode
    multiple runs of the blitter may be used to clear all the memory.

    Set bit 2 to use the upper 16 bits of the Flags as the data to fill
    memory with instead of 0 (V36).

   RESULT
    The block of memory is initialized.

   BUGS

   SEE ALSO

 graphics.library/BltMaskBitMapRastPort graphics.library/BltMaskBitMapRastPort

   NAME
    BltMaskBitMapRastPort -- blit from source bitmap to destination rastport
    with masking of source image.

   SYNOPSIS
    BltMaskBitMapRastPort
        (srcbm, srcx, srcy, destrp, destX, destY, sizeX, sizeY,
         A0     D0    D1    A1      D2     D3     D4     D5
         minterm, bltmask)
         D6       A2

    void BltMaskBitMapRastPort
         (struct BitMap *, WORD, WORD, struct RastPort *, WORD, WORD,
          WORD, WORD, UBYTE, APTR);

   FUNCTION
    Blits from source bitmap to position specified in destination rastport
    using bltmask to determine where source overlays destination, and
    minterm to determine whether to copy the source image "as is" or
    to "invert" the sense of the source image when copying. In either
    case, blit only occurs where the mask is non-zero.

   INPUTS
    srcbm   - a pointer to the source bitmap
    srcx    - x offset into source bitmap
    srcy    - y offset into source bitmap
    destrp  - a pointer to the destination rastport
    destX   - x offset into dest rastport
    destY   - y offset into dest rastport
    sizeX   - width of blit in pixels
    sizeY   - height of blit in rows
    minterm - either (ABC|ABNC|ANBC) if copy source and blit thru mask
              or     (ANBC)          if invert source and blit thru mask
    bltmask - pointer to the single bit-plane mask, which must be the
              same size and dimensions as the planes of the
              source bitmap.

   RESULT

   BUGS

   SEE ALSO
    BltBitMapRastPort() graphics/gfx.h graphics/rastport.h

 graphics.library/BltPattern                       graphics.library/BltPattern

   NAME
    BltPattern --  Using standard drawing rules for areafill,
                     blit through a mask.

   SYNOPSIS
       BltPattern(rp, mask, xl, yl, maxx, maxy, bytecnt)
                  a1,  a0   d0  d1   d2   d3     d4

    void BltPattern
       (struct RastPort *, void *, SHORT, SHORT, SHORT, SHORT, SHORT);

   FUNCTION
       Blit using drawmode,areafill pattern, and mask
       at position rectangle (xl,yl) (maxx,maxy).

   INPUTS
       rp    -  points to the destination RastPort for the blit.
       mask  -  points to 2 dimensional mask if needed
                if mask == NULL then use a rectangle.
       xl,yl -  coordinates of upper left of rectangular region in RastPort
       maxx,maxy - points to lower right of rectangular region in RastPort
       bytecnt - BytesPerRow for mask

   RESULT

   SEE ALSO
    AreaEnd

 graphics.library/BltTemplate                     graphics.library/BltTemplate

   NAME
    BltTemplate -- Cookie cut a shape in a rectangle to the RastPort.

   SYNOPSIS
    BltTemplate(SrcTemplate, SrcX, SrcMod, rp,
                A0           D0:16  D1:16  A1
        DstX,  DstY, SizeX, SizeY)
        D2:16  D3:16 D4:16  D5:16

    void BltTemplate(UWORD *, WORD, WORD, struct RastPort *,
         WORD, WORD, WORD, WORD);

   FUNCTION
    This function draws the image in the template into the
    RastPort in the current color and drawing mode at the
    specified position.  The template is assumed not to overlap
    the destination.
    If the template falls outside the RastPort boundary, it is
    truncated to that boundary.

    Note: the SrcTemplate pointer should point to the "nearest" word
       (rounded down) of the template mask. Fine alignment of the mask
       is acheived by setting the SrcX bit offseet within the range
       of 0 to 15 decimal.

   INPUTS
    SrcTemplate  - pointer to the first (nearest) word of the template mask.
    SrcX         - x bit offset into the template mask (range 0..15).
    SrcMod       - number of bytes per row in template mask.
    rp           - pointer to destination RastPort.
    DstX, DstY   - x and y coordinates of the upper left
                   corner of the destination for the blit.
    SizeX, SizeY - size of the rectangle to be used as the
                   template.

   NOTES
    o   This function may use the blitter.

   SEE ALSO
    BltBitMap()  graphics/rastport.h

 graphics.library/CBump                                 graphics.library/CBump
   NAME
    CBump -  increment user copper list pointer (bump to next position in list).

   SYNOPSIS
    CBump( c )
          a1

    void CBump( struct UCopList * );

   FUNCTION
    Increment pointer to space for next instruction in user copper list.

   INPUTS
    c - pointer to UCopList structure

   RESULTS
    User copper list pointer is incremented to next position.
    Pointer is repositioned to next user copperlist instruction block
    if the current block is full.

        Note: CBump is usually invoked for the programmer as part of the
              macro definitions CWAIT or CMOVE.

   BUGS

   SEE ALSO
    CINIT CWAIT CMOVE CEND graphics/copper.h
 graphics.library/CEND                                   graphics.library/CEND
   NAME
    CEND -- Terminate user copper list.

   SYNOPSIS
    CEND( c )

    struct UCopList *c;

   FUNCTION
    Add instruction to terminate user copper list.

   INPUTS
    c - pointer to UCopList structure

   RESULTS
    This is actually a macro that calls the macro CWAIT(c,10000,255)
    10000 is a magical number that the graphics.library uses.
    I hope display technology doesn't catch up too fast!

   BUGS

   SEE ALSO
    CINIT CWAIT CMOVE graphics/copper.h
 graphics.library/ChangeSprite                   graphics.library/ChangeSprite

   NAME
       ChangeSprite -- Change the sprite image pointer.

   SYNOPSIS
       ChangeSprite( vp, s, newdata)
                     a0  a1   a2

    void ChangeSprite(struct ViewPort *, struct SimpleSprite *, void * )

   FUNCTION
    The sprite image is changed to use the data starting at newdata

   INPUTS
       vp - pointer to ViewPort structure that this sprite is
          relative to,  or 0 if relative only top of View
    s - pointer to SimpleSprite structure
    newdata	- pointer to data structure of the following form.
        struct spriteimage
        {
            UWORD    posctl[2];	/* used by simple sprite machine*/
            UWORD    data[height][2];   /* actual sprite image */
            UWORD    reserved[2];	/* initialized to */
                                         /*  0x0,0x0 */
        };
    The programmer must initialize reserved[2].  Spriteimage must be
    in CHIP memory. The height subfield of the SimpleSprite structure
    must be set to reflect the height of the new spriteimage BEFORE
    calling ChangeSprite(). The programmer may allocate two sprites to
    handle a single attached sprite.  After GetSprite(), ChangeSprite(),
    the programmer can set the SPRITE_ATTACHED bit in posctl[1] of the
    odd numbered sprite.
    If you need more than 8 sprites, look up VSprites in the
    graphics documentation.

   RESULTS

   BUGS

   SEE ALSO
    FreeSprite() ChangeSprite() MoveSprite() AddVSprite() graphics/sprite.h

 graphics.library/CINIT                                 graphics.library/CINIT

   NAME
    CINIT -- Initialize user copperlist to accept intermediate
         user copper instructions.

   SYNOPSIS
     cl = CINIT( ucl , n )

    cl = UCopperListInit( ucl , n )
                  a0    d0

    struct CopList *UCopperListInit( struct UCopList *, UWORD );

   FUNCTION
    Allocates and/or initialize copperlist structures/buffers
    internal to a UCopList structure.

    This is a macro that calls UCopListInit. You must pass a
    (non-initialized) UCopList to CINIT (CINIT will NOT allocate
    a new UCopList if ucl==0 ). If (ucl != 0) it will initialize the
    intermediate data buffers internal to a UCopList.

    The maximum number of intermediate copper list instructions
    that these internal CopList data buffers contain is specified
    as the parameter n.

   INPUTS
    ucl - pointer to UCopList structure
    n - number of instructions buffer must be able to hold

   RESULTS
    cl- a pointer to a buffer which will accept n intermediate copper
        instructions.

    NOTE: this is NOT a UCopList pointer, rather a pointer to the
          UCopList's->FirstCopList sub-structure.

   BUGS
    CINIT will not actually allocate a new UCopList if ucl==0.
    Instead you must allocate a block MEMF_PUBLIC|MEMF_CLEAR, the
    sizeof(struct UCopList) and pass it to this function.

    The system's FreeVPortCopLists function will take care of
    deallocating it if they are called.

    Prior to release V36 the  CINIT macro had { } braces surrounding
    the definition, preventing the proper return of the result value.
    These braces have been removed for the V36 include definitions.

   SEE ALSO
     CINIT CMOVE CEND graphics/copper.h

 graphics.library/ClearEOL                           graphics.library/ClearEOL

   NAME
    ClearEOL -- Clear from current position to end of line.

   SYNOPSIS
    ClearEOL(rp)
             A1

    void ClearEOL(struct RastPort *);

   FUNCTION
    Clear a rectangular swath from the current position to the
    right edge of the rastPort.  The height of the swath is taken
    from that of the current text font, and the vertical
    positioning of the swath is adjusted by the text baseline,
    such that text output at this position would lie wholly on
    this newly cleared area.
    Clearing consists of setting the color of the swath to zero,
    or, if the DrawMode is 2, to the BgPen.

   INPUTS
    rp - pointer to RastPort structure

   RESULT

   NOTES
    o   This function may use the blitter.

   SEE ALSO
    Text()  ClearScreen()  SetRast()
    graphics/text.h  graphics/rastport.h

 graphics.library/ClearRectRegion             graphics.library/ClearRectRegion

   NAME
    ClearRectRegion -- Perform 2d CLEAR operation of rectangle
            with region, leaving result in region.

   SYNOPSIS
    status = ClearRectRegion(region,rectangle)
     d0	 	 	  a0 	  a1

    BOOL ClearRectRegion(struct Region *, struct Rectangle * );

   FUNCTION
    Clip away any portion of the region that exists inside
    of the rectangle. Leave the result in region.

   INPUTS
    region - pointer to Region structure
    rectangle - pointer to Rectangle structure

   RESULTS
    status - return TRUE if successful operation
         return FALSE if ran out of memory

   BUGS

   SEE ALSO
    AndRectRegion() graphics/regions.h

 graphics.library/ClearRegion                     graphics.library/ClearRegion

   NAME
       ClearRegion -- Remove all rectangles from region.

   SYNOPSIS
       ClearRegion(region)
                     a0

    void ClearRegion( struct Region * );

   FUNCTION
       Clip away all rectangles in the region leaving nothing.

   INPUTS
       region - pointer to Region structure

   BUGS

   SEE ALSO
    NewRegion() graphics/regions.h

 graphics.library/ClearScreen                     graphics.library/ClearScreen

   NAME
    ClearScreen -- Clear from current position to end of RastPort.

   SYNOPSIS
    ClearScreen(rp)
                A1

    void ClearScreen(struct RastPort *);

   FUNCTION
    Clear a rectangular swath from the current position to the
    right edge of the rastPort with ClearEOL, then clear the rest
    of the screen from just beneath the swath to the bottom of
    the rastPort.
    Clearing consists of setting the color of the swath to zero,
    or, if the DrawMode is 2, to the BgPen.

   INPUTS
    rp - pointer to RastPort structure

   NOTES
    o   This function may use the blitter.

   SEE ALSO
    ClearEOL()  Text()  SetRast()
    graphics/text.h  graphics/rastport.h

 graphics.library/ClipBlit                           graphics.library/ClipBlit

   NAME
    ClipBlit  --  Calls BltBitMap() after accounting for windows

   SYNOPSIS
    ClipBlit(Src, SrcX, SrcY, Dest, DestX, DestY, XSize, YSize, Minterm)
             A0   D0    D1    A1    D2     D3     D4     D5     D6

    void ClipBlit
         (struct RastPort *, WORD, WORD, struct RastPort *, WORD, WORD,
          WORD, WORD, UBYTE);

   FUNCTION
    Performs the same function as BltBitMap(), except that it
    takes into account the Layers and ClipRects of the layer library,
    all of which are (and should be) transparent to you.  So, whereas
    BltBitMap() requires pointers to BitMaps, ClipBlit requires pointers to
    the RastPorts that contain the Bitmaps, Layers, etcetera.

    If you are going to blit blocks of data around via the RastPort of your
    Intuition Window, you must call this routine (rather than BltBitMap()).

    Either the Src RastPort, the Dest RastPort, both, or neither, can have
    Layers. This routine takes care of all cases.

    See BltBitMap() for a thorough explanation.

   INPUTS
    Src          = pointer to the RastPort of the source for your blit
    SrcX, SrcY   = the topleft offset into Src for your data
    Dest         = pointer to the RastPort to receive the blitted data
    DestX, DestY = the topleft offset into the destination RastPort
    XSize        = the width of the blit
    YSize        = the height of the blit
    Minterm      = the boolean blitter function, where SRCB is associated
                   with the Src RastPort and SRCC goes to the Dest RastPort

   RESULT

   BUGS

   SEE ALSO
    BltBitMap();

 graphics.library/CloseFont                         graphics.library/CloseFont

   NAME
    CloseFont -- Release a pointer to a system font.

   SYNOPSIS
    CloseFont(font)
              A1

    void CloseFont(struct TextFont *);

   FUNCTION
    This function indicates that the font specified is no longer
    in use.  It is used to close a font opened by OpenFont, so
    that fonts that are no longer in use do not consume system
    resources.

   INPUTS
    font -	a font pointer as returned by OpenFont() or OpenDiskFont()

   RESULT

   BUGS

   SEE ALSO
    OpenFont()  diskfont.library/OpenDiskFont  graphics/text.h

 graphics.library/CloseMonitor                   graphics.library/CloseMonitor

   NAME
       CloseMonitor -- close a MonitorSpec (V36)

   SYNOPSIS
       error = CloseMonitor( monitor_spec )
       d0                    a0

       LONG CloseMonitor( struct MonitorSpec * );

   FUNCTION
       Relinquish access to a MonitorSpec.

   INPUTS
       monitor_spec - a pointer to a MonitorSpec opened via OpenMonitor()

   RESULTS
       error - FALSE if MonitorSpec closed uneventfully.
               TRUE if MonitorSpec could not be closed.

   BUGS

   SEE ALSO
       OpenMonitor()

 graphics.library/CMOVE                                 graphics.library/CMOVE

   NAME
    CMOVE -- append copper move instruction to user copper list.

   SYNOPSIS
    CMOVE( c , a , v )

    CMove( c , a , v )
          a1  d0  d1
    CBump( c )
          a1

    void CMove( struct UCopList *, void *, WORD );

   FUNCTION
    Add instruction to move value v to hardware register a.

   INPUTS
    c - pointer to UCopList structure
    a - hardware register
    v - 16 bit value to be written

   RESULTS
    This is actually a macro that calls CMove(c,&a,v)
    and then calls CBump(c) to bump the local pointer
    to the next instruction. Watch out for macro side affects.

   BUGS

   SEE ALSO
    CINIT CWAIT CEND graphics/copper.h

 graphics.library/CopySBitMap                     graphics.library/CopySBitMap

   NAME
       CopySBitMap --	Syncronize Layer window with contents of
                        Super BitMap

   SYNOPSIS
       CopySBitMap( layer )
                     a0

    void CopySBitMap(struct Layer *);

   FUNCTION
    This is the inverse of SyncSBitMap.
       Copy all bits from SuperBitMap to Layer bounds.
    This is used for those functions that do not
    want to deal with the ClipRect structures but do want
    to be able to work with a SuperBitMap Layer.

   INPUTS
    layer - pointer to a SuperBitMap Layer
        The Layer must already be locked by the caller.

   BUGS

   SEE ALSO
    LockLayerRom() SyncSBitMap()

 graphics.library/CWAIT                                 graphics.library/CWAIT

   NAME
    CWAIT -- Append copper wait instruction to user copper list.

   SYNOPSIS
    CWAIT( c , v , h )

    CWait( c , v , h )
           a1  d0  d1
    CBump( c )
          a1

    void CWait( struct UCopList *, WORD, WORD)

   FUNCTION
    Add instruction to wait for vertical beam position v and
    horizontal position h to this intermediate copper list.

   INPUTS
    c - pointer to UCopList structure
    v - vertical beam position (relative to top of viewport)
    h - horizontal beam position

   RESULTS
    this is actually a macro that calls CWait(c,v,h)
    and then calls CBump(c) to bump the local pointer
    to the next instruction.

   BUGS
    User waiting for horizontal values of greater than 222 decimal
    is illegal.

   SEE ALSO
     CINIT CMOVE CEND graphics/copper.h

 graphics.library/DisownBlitter                 graphics.library/DisownBlitter

   NAME
       DisownBlitter - return blitter to free state.

   SYNOPSIS
       DisownBlitter()

    void DisownBlitter( void );

   FUNCTION
    Free blitter up for use by other blitter users.

   INPUTS

   RETURNS

   SEE ALSO
       OwnBlitter()

 graphics.library/DisposeRegion                 graphics.library/DisposeRegion

   NAME
       DisposeRegion -- Return all space for this region to free
             memory pool.

   SYNOPSIS
       DisposeRegion(region)
                      a0

    void DisposeRegion( struct Region * );

   FUNCTION
       Free all RegionRectangles for this Region then
    free the Region itself.

   INPUTS
       region - pointer to Region structure

   BUGS

   SEE ALSO
    NewRegion() graphics/regions.h

 graphics.library/DoCollision                     graphics.library/DoCollision

   NAME
    DoCollision -- Test every gel in gel list for collisions.

   SYNOPSIS
    DoCollision(rp)
                A1

    void DoCollision(struct RastPort *);

   FUNCTION
    Tests each gel in gel list for boundary and gel-to-gel collisions.
    On detecting one of these collisions, the appropriate collision-
    handling routine is called. See the documentation for a thorough
    description of which collision routine is called. This routine
    expects to find the gel list correctly sorted in Y,X order.
    The system routine SortGList performs this function for the user.

   INPUTS
    rp = pointer to a RastPort

   RESULT

   BUGS

   SEE ALSO
    InitGels()  SortGList()  graphics/gels.h  graphics/gels.h

 graphics.library/Draw                                   graphics.library/Draw

   NAME
       Draw -- Draw a line between the current pen position
                       and the new x,y position.

   SYNOPSIS
       Draw( rp,   x,     y)
             a1  d0:16  d1:16

    void Draw( struct RastPort *, SHORT, SHORT);

   FUNCTION
       Draw a line from the current pen position to (x,y).

   INPUTS

    rp - pointer to the destination RastPort
    x,y - coordinates of where in the RastPort to end the line.

   BUGS

   SEE ALSO
    Move() graphics/rastport.h

 graphics.library/DrawEllipse                     graphics.library/DrawEllipse

    NAME
    DrawEllipse -- Draw an ellipse centered at cx,cy with vertical
       and horizontal radii of a,b respectively.

    SYNOPSIS
    DrawEllipse( rp, cx, cy, a, b )
             a1  d0  d1  d2 d3

    void DrawEllipse( struct RastPort *, SHORT, SHORT, SHORT, SHORT);

    FUNCTION
       Creates an elliptical outline within the rectangular region
    specified by the parameters, using the current foreground pen color.

    INPUTS
    rp - pointer to the RastPort into which the ellipse will be drawn.
    cx - x coordinate of the centerpoint relative to the rastport.
    cy - y coordinate of the centerpoint relative to the rastport.
    a - the horizontal radius of the ellipse (note: a must be > 0)
    b - the vertical radius of the ellipse (note: b must be > 0)

    BUGS

    NOTES
    this routine does not clip the ellipse to a non-layered rastport.

    SEE ALSO
    DrawCircle(), graphics/rastport.h

 graphics.library/DrawGList                         graphics.library/DrawGList

   NAME
    DrawGList -- Process the gel list, queueing VSprites, drawing Bobs.

   SYNOPSIS
    DrawGList(rp, vp)
              A1  A0

    void DrawGList(struct RastPort *, struct ViewPort *);

   FUNCTION
    Performs one pass of the current gel list.
       - If nextLine and lastColor are defined, these are
         initialized for each gel.
          - If it's a VSprite, build it into the copper list.
          - If it's a Bob, draw it into the current raster.
          - Copy the save values into the "old" variables,
         double-buffering if required.

   INPUTS
    rp = pointer to the RastPort where Bobs will be drawn
    vp = pointer to the ViewPort for which VSprites will be created

   RESULT

   BUGS
    MUSTDRAW isn't implemented yet.

   SEE ALSO
    InitGels()  graphics/gels.h graphics/rastport.h  graphics/view.h

 graphics.library/EraseRect                         graphics.library/EraseRect

   NAME

       EraseRect -- Fill a defined rectangular area using the current
                 BackFill hook. (V36)

   SYNOPSIS
    EraseRect( rp, xmin, ymin, xmax, ymax)
                  a1  d0:16 d1:16 d2:16 d3:16

    void EraseRect(struct RastPort *, SHORT, SHORT, SHORT, SHORT);

   FUNCTION
    Fill the rectangular region specified by the parameters with the
    BackFill hook. If non-layered, the rectangular region specified by
    the parameters is cleared. If layered the Layer->BackFill Hook is used.

   INPUTS
    rp	- pointer to a RastPort structure
    xmin	- x coordinate of the upper left corner of the region to fill.
    ymin	- y coordinate of the upper left corner of the region to fill.
    xmax	- x coordinate of the lower right corner of the region to fill.
    ymax	- y coordinate of the lower right corner of the region to fill.

   BUGS

   NOTES
    The following relation MUST be true:
    (xmax >= xmin) and (ymax >= ymin)

   SEE ALSO
    graphics/rastport.h graphics/clip.h

 graphics.library/ExtendFont                       graphics.library/ExtendFont

   NAME
    ExtendFont -- ensure tf_Extension has been built for a font (V36)

   SYNOPSIS
    success = ExtendFont(font, fontTags)
    D0                   A0    A1

    ULONG ExtendFont(struct TextFont *, struct TagItem *);

   SEE ALSO
    graphics/text.h

 graphics.library/FindDisplayInfo             graphics.library/FindDisplayInfo

   NAME
    FindDisplayInfo -- search for a record identified by a specific key (V36)

   SYNOPSIS
    handle = FindDisplayInfo(ID)
    D0                       D0

    DisplayInfoHandle FindDisplayInfo(ULONG);

   FUNCTION
    Given a 32-bit Mode Key, return a handle to a valid DisplayInfoRecord
    found in the graphics database.  Using this handle, you can obtain
    information about this Mode, including its default dimensions,
    properties, and whether it is currently available for use.

   INPUTS
    ID     - unsigned long identifier

   RESULT
    handle - handle to a displayinfo Record with that key
             or NULL if no match.

   BUGS

   SEE ALSO
    graphics/displayinfo.h

 graphics.library/Flood                                 graphics.library/Flood

   NAME
    Flood -- Flood rastport like areafill.

   SYNOPSIS
    error = Flood( rp, mode, x, y)
        d0            a1   d2  d0  d1

    BOOL Flood(struct RastPort *, ULONG, SHORT, SHORT);

   FUNCTION
    Search the BitMap starting at (x,y).
    Fill all adjacent pixels if they are:
        Mode 0: not the same color as AOLPen
        Mode 1: the same color as the pixel at (x,y)

    When actually doing the fill use the modes that apply to
    standard areafill routine such as drawmodes and patterns.

   INPUTS
    rp - pointer to RastPort
    (x,y) - coordinate in BitMap to start the flood fill at.
    mode -  0 fill all adjacent pixels searching for border.
        1 fill all adjacent pixels that have same pen number
        as the one at (x,y).

   NOTES
    In order to use Flood, the destination RastPort must
    have a valid TmpRas raster whose size is as large as
    that of the RastPort.

   SEE ALSO
    AreaEnd() InitTmpRas() graphics/rastport.h

 graphics.library/FontExtent                       graphics.library/FontExtent

   NAME
    FontExtent -- get the font attributes of the current font (V36)

   SYNOPSIS
    FontExtent(font, fontExtent)
               A0    A1

    void FontExtent(struct TextFont *, struct TextExtent *);

   FUNCTION
    This function fills the text extent structure with a bounding
    (i.e. maximum) extent for the characters in the specified font.

   INPUTS
    font       - the TextFont from which the font metrics are extracted.
    fontExtent - the TextExtent structure to be filled.

   RESULT
    fontExtent is filled.

   NOTES
    The TextFont, not the RastPort, is specified -- unlike
    TextExtent(), effect of algorithmic enhancements is not
    included, nor does te_Width include any effect of
    rp_TxSpacing.  The returned te_Width will be negative only
    when FPF_REVPATH is set in the tf_Flags of the font -- the
    effect of left-moving characters is ignored for the width of
    a normal font, and the effect of right-moving characters is
    ignored if a REVPATH font.  These characters will, however,
    be reflected in the bounding extent.

   SEE ALSO
    TextExtent()  graphics/text.h

 graphics.library/FreeColorMap                   graphics.library/FreeColorMap

   NAME
       FreeColorMap -- Free the ColorMap structure and return memory
                        to free memory pool.

   SYNOPSIS
       FreeColorMap( colormap )
                       a0

    void FreeColorMap(struct ColorMap *);

   FUNCTION
    Return the memory to the free memory pool that was allocated
    with GetColorMap.

   INPUTS
    colormap - pointer to ColorMap allocated with GetColorMap

   RESULT
    The space is made available for others to use.

   BUGS

   SEE ALSO
       SetRGB4() GetColorMap() graphics/view.h
 graphics.library/FreeCopList                     graphics.library/FreeCopList

   NAME
    FreeCopList -- deallocate intermediate copper list

   SYNOPSIS
       FreeCopList(coplist)
              a0

    void FreeCopList( struct CopList *);

   FUNCTION
    Deallocate all memory associated with this copper list.

   INPUTS
       coplist	- pointer to structure CopList

   RESULTS
    memory returned to memory manager

   BUGS

   SEE ALSO
    graphics/copper.h

 graphics.library/FreeCprList                     graphics.library/FreeCprList

   NAME
       FreeCprList -- deallocate hardware copper list

   SYNOPSIS
       FreeCprList(cprlist)
              a0

    void FreeCprList(struct cprlist *);

   FUNCTION
       return cprlist to free memory pool

   INPUTS
       cprlist - pointer to cprlist structure

   RESULTS
    memory returned and made available to other tasks

   BUGS

   SEE ALSO
    graphics/copper.h

 graphics.library/FreeGBuffers                   graphics.library/FreeGBuffers

   NAME
    FreeGBuffers -- Deallocate memory obtained by GetGBufers.

   SYNOPSIS
    FreeGBuffers(anOb, rp, db)
                 A0    A1  D0

    void FreeGBuffers(struct AnimOb *, struct RastPort *, BOOL);

   FUNCTION
    For each sequence of each component of the AnimOb,
    deallocate memory for:
        SaveBuffer
        BorderLine
        CollMask and ImageShadow (point to same buffer)
        if db is set (user had used double-buffering) deallocate:
            DBufPacket
            BufBuffer

   INPUTS
    anOb = pointer to the AnimOb structure
    rp   = pointer to the current RastPort
    db   = double-buffer indicator (set TRUE for double-buffering)

   RESULT

   BUGS

   SEE ALSO
    GetGBuffers()  graphics/gels.h  graphics/rastport.h

 graphics.library/FreeRaster                       graphics.library/FreeRaster

   NAME
       FreeRaster -- Release an allocated area to the system free memory pool
.

   SYNOPSIS
       FreeRaster( p, width, height)
           a0   d0:16  d1:16

    void FreeRaster( PLANEPTR, USHORT, USHORT);

   FUNCTION
    Return the memory associated with this PLANEPTR of size
    width and height to the MEMF_CHIP memory pool.

   INPUTS
       p  =  a pointer to a memory space  returned  as  a
             result of a call to AllocRaster.

    width - the width in bits of the bitplane.
    height - number of rows in bitplane.

   BUGS

   NOTES
       Width and height should be the same values with which you
       called AllocRaster in the first place.

   SEE ALSO
    AllocRaster() graphics/gfx.h

 graphics.library/FreeSprite                       graphics.library/FreeSprite

   NAME
       FreeSprite -- Return sprite for use by others and virtual
                      sprite machine.

   SYNOPSIS
       FreeSprite( pick )
                    d0

    void FreeSprite( WORD );

   FUNCTION
    Mark sprite as available for others to use.
       These sprite routines are provided to ease sharing of sprite
    hardware and to handle simple cases of sprite usage and
    movement.  It is assumed the programs that use these routines
    do want to be good citizens in their hearts. ie: they will
    not FreeSprite unless they actually own the sprite.
    The Virtual Sprite machine may ignore the simple sprite machine.

   INPUTS
       pick - number in range of 0-7

   RESULTS
    sprite made available for subsequent callers of GetSprite
    as well as use by Virtual Sprite Machine.

   BUGS

   SEE ALSO
       GetSprite() ChangeSprite() MoveSprite() graphics/sprite.h

 graphics.library/FreeVPortCopLists         graphics.library/FreeVPortCopLists

   NAME
       FreeVPortCopLists -- deallocate all intermediate copper lists and
       their headers from a viewport

   SYNOPSIS
       FreeVPortCopLists(vp)
                         a0

    void FreeVPortCopLists(struct ViewPort *);

   FUNCTION
       Search display, color, sprite, and user copper
       lists and call FreeMem() to deallocate them from memory

   INPUTS
       vp - pointer to ViewPort structure

   RESULTS
       The memory allocated to the various copper lists will be returned
    to the system's free memory pool, and the following fields in
    the viewport structure will be set to NULL:

        DspIns, Sprins, ClrIns, UCopIns

   BUGS
       none known

   SEE ALSO
    graphics/view.h

 graphics.library/GetColorMap                     graphics.library/GetColorMap

   NAME
       GetColorMap -- allocate and initialize Colormap

   SYNOPSIS
       cm = GetColorMap( entries )
       d0		    d0

    struct ColorMap *GetColorMap( ULONG);

   FUNCTION
       Allocates, initializes and returns a pointer to a ColorMap
       data structure, later enabling calls to SetRGB4
       and LoadRGB4 to load colors for a view port. The ColorTable
    pointer in the ColorMap structure points to a hardware
    specific colormap data structure. You should not count on
    it being anything you can understand. Use GetRGB4() to
    query it or SetRGB4CM to set it directly.

   INPUTS
    entries - number of entries for this colormap

    RESULT
    The pointer value returned by this routine, if nonzero,
       may be stored into the ViewPort.ColorMap pointer.
       If a value of 0 is returned, the system was unable
       to allocate enough memory space for the required
       data structures.

   BUGS

   SEE ALSO
       SetRGB4() FreeColorMap()
 graphics.library/GetDisplayInfoData       graphics.library/GetDisplayInfoData

   NAME
    GetDisplayInfoData -- query DisplayInfo Record parameters (V36)

   SYNOPSIS
    result = GetDisplayInfoData(handle, buf, size, tagID, [ID])
    D0                          A0      A1   D0    D1     [D2]

    ULONG GetDisplayInfoData(DisplayInfoHandle, UBYTE *, ULONG, ULONG, ULONG);

   FUNCTION
    GetDisplayInfoData() fills a buffer with data meaningful to the
    DisplayInfoRecord pointed at by your valid handle. The data type
    that you are interested in is indicated by a tagID for that chunk.
    The types of tagged information that may be available include:

    DTAG_DISP: (DisplayInfo)   - properties and availability information.
    DTAG_DIMS: (DimensionInfo) - default dimensions and overscan info.
    DTAG_MNTR: (MonitorInfo)   - type, position, scanrate, and compatibility
    DTAG_NAME: (NameInfo)      - a user friendly way to refer to this mode.

   INPUTS
    handle - displayinfo handle
    buf    - pointer to destination buffer
    size   - buffer size in bytes
    tagID  - data chunk type
    ID     - displayinfo identifier, optionally used if handle is NULL

   RESULT
    result - if positive, number of bytes actually transferred
             if zero, no information for ID was available

   BUGS

   SEE ALSO
    FindDisplayInfo(), NextDisplayInfo()
    graphics/displayinfo.h

 graphics.library/GetGBuffers                     graphics.library/GetGBuffers

   NAME
    GetGBuffers -- Attempt to allocate ALL buffers of an entire AnimOb.

   SYNOPSIS
    status = GetGBuffers(anOb, rp, db)
    D0                   A0    A1  D0

    BOOL GetGBuffers(struct AnimOb *, struct RastPort *, BOOL);

   FUNCTION
    For each sequence of each component of the AnimOb, allocate memory for:
        SaveBuffer
        BorderLine
        CollMask and ImageShadow (point to same buffer)
        if db is set TRUE (user wants double-buffering) allocate:
            DBufPacket
            BufBuffer

   INPUTS
    anOb = pointer to the AnimOb structure
    rp   = pointer to the current RastPort
    db   = double-buffer indicator (set TRUE for double-buffering)

   RESULT
    status = TRUE if the memory allocations were all successful, else FALSE

   BUGS
    If any of the memory allocations fail it does not free the partial
    allocations that did succeed.

   SEE ALSO
    FreeGBuffers() graphics/gels.h

 graphics.library/GetRGB4                             graphics.library/GetRGB4

   NAME
       GetRGB4 -- Inquire value of entry in ColorMap.

   SYNOPSIS
       value = GetRGB4( colormap, entry )
          d0              a0       d0

    ULONG GetRGB4(struct ColorMap *, LONG);

   FUNCTION
    Read and format a value from the ColorMap.

   INPUTS
    colormap - pointer to ColorMap structure
    entry - index into colormap

   RESULT
    returns -1 if no valid entry
    return UWORD RGB value 4 bits per gun right justified

   NOTE
    Intuition's DisplayBeep() changes color 0. Reading Color 0 during a
    DisplayBeep() will lead to incorrect results.

   BUGS

   SEE ALSO
       SetRGB4() LoadRGB4() GetColorMap() FreeColorMap() graphics/view.h
 graphics.library/GetSprite                         graphics.library/GetSprite

   NAME
    GetSprite -- Attempt to get a sprite for the simple sprite
                     manager.

   SYNOPSIS
    Sprite_Number = GetSprite( sprite, pick )
        d0			    a0      d0

    SHORT GetSprite( struct SimpleSprite *, SHORT );

   FUNCTION
    Attempt to allocate one of the eight sprites for private use
    with the simple sprite manager. This must be done before using
    further calls to the simple sprite machine. If the programmer
    wants to use 15 color sprites, they must allocate both sprites
    and set the 'SPRITE_ATTACHED' bit in the odd sprite's posctldata
    array.

   INPUTS
    sprite - ptr to programmers SimpleSprite structure.
    pick - number in the range of 0-7 or
      -1 if programmer just wants the next one.

   RESULTS
    If pick is 0-7 attempt to allocate the sprite. If the sprite
    is already allocated then return -1.
    If pick -1 allocate the next sprite starting search at 0.
    If no sprites are available return -1 and fill -1 in num entry
    of SimpleSprite structure.
    If the sprite is available for allocation, mark it allocated
    and fill in the 'num' entry of the SimpleSprite structure.
    If successful return the sprite number.

   BUGS

   SEE ALSO
    FreeSprite() ChangeSprite() MoveSprite() GetSprite() graphics/sprite.h

 graphics.library/GetVPModeID                     graphics.library/GetVPModeID

   NAME
    GetVPModeID -- get the 32 bit DisplayID from a ViewPort. (V36)

   SYNOPSIS
    modeID =  GetVPModeID( vp )
    d0		       a0

    ULONG GetVPModeID( struct ViewPort *);

   FUNCTION
    returns the normal display modeID, if one is currently  associated
    with this ViewPort.

   INPUTS
    vp -- pointer to a ViewPort structure.

   RESULT

    modeID -- a 32 bit DisplayInfoRecord identifier associated with
          this ViewPort, or INVALID_ID.

   NOTES
    Test the return value of this function against INVALID_ID, not NULL.
    (INVALID_ID is defined in graphics/displayinfo.h).

   BUGS

   SEE ALSO
    graphics/displayinfo.h, ModeNotAvailable()

 graphics.library/GfxAssociate                   graphics.library/GfxAssociate

   NAME
    GfxAssociate -- associate a graphics extended node with a given pointer
                    (V36)

   SYNOPSIS
       GfxAssociate(pointer, node);
                    A0       A1

    void GfxAssociate(VOID *, struct ExtendedNode *);

   FUNCTION
    Associate a special graphics extended data structure (each of which
    begins with an ExtendedNode structure)  with another structure via
    the other structure's pointer. Later, when you call GfxLookUp()
    with the other structure's pointer you may retrieve a pointer
    to this special graphics extended data structure, if it is
    available.

   INPUTS
    pointer = a pointer to a data structure.
    node = an ExtendedNode structure to associate with the pointer

   RESULT
    an association is created between the pointer and the node such
    that given the pointer the node can be retrieved via GfxLookUp().

   BUGS

   SEE ALSO
    graphics/gfxnodes.h GfxNew() GfxFree() GfxLookUp()

 graphics.library/GfxFree                             graphics.library/GfxFree

   NAME
       GfxFree -- free a graphics extended data structure (V36)

   SYNOPSIS
       GfxFree( node );
                 a0

    void GfxFree(struct ExtendedNode *);

   FUNCTION
    Free a special graphics extended data structure (each of which
    begins with an ExtendedNode structure).

   INPUTS
    node = pointer to a graphics extended data structure obtained via
           GfxNew().

   RESULT
    the node is deallocated from memory. graphics will dissassociate
    this special graphics extended node from any associated data
    structures, if necessary, before freeing it (see GfxAssociate()).

   BUGS
    an Alert() will be called if you attempt to free any structure
    other than a graphics extended data strucure obtained via GfxFree().

   SEE ALSO
    graphics/gfxnodes.h GfxNew() GfxAssociate() GfxLookUp()

 graphics.library/GfxLookUP                         graphics.library/GfxLookUP

   NAME
        GfxLookUp -- find a graphics extended node associated with a
             given pointer (V36)

   SYNOPSIS
       result = GfxLookUp( pointer );
       d0		    a0

    struct ExtendedNode *GfxLookUp( void *);

   FUNCTION
    Finds a special graphics extended data structure (if any) associated
    with the pointer to a data structure (eg: ViewExtra associated with
    a View structure).

   INPUTS
    pointer = a pointer to a data structure which may have an
          ExtendedNode associated with it (typically a View ).

   RESULT
    result = a pointer to the ExtendedNode that has previously been
         associated with the pointer.

   BUGS

   SEE ALSO
    graphics/gfxnodes.h GfxNew() GfxFree() GfxAssociate()

 graphics.library/GfxNew                               graphics.library/GfxNew

   NAME
       GfxNew -- allocate a graphics extended data structure (V36)

   SYNOPSIS
     result = GfxNew( node_type );
    d0		 d0

    struct ExtendedNode *GfxNew( ULONG);

   FUNCTION
    Allocate a special graphics extended data structure (each of which
    begins with an ExtendedNode structure).  The type of structure to
    be allocated is specified by the node_type identifier.

   INPUTS
    node_type = which type of graphics extended data structure to allocate.
            (see gfxnodes.h for identifier definitions.)

   RESULT
    result = a pointer to the allocated graphics node or NULL if the
         allocation failed.

   BUGS

   SEE ALSO
    graphics/gfxnodes.h GfxFree() GfxAssociate() GfxLookUp()

 graphics.library/InitArea                           graphics.library/InitArea

   NAME

    InitArea -- Initialize vector collection matrix

   SYNOPSIS

       InitArea( areainfo, buffer, maxvectors )
            a0          a1      d0

    void InitArea(struct AreaInfo *, void *, SHORT);

   FUNCTION
    This function provides initialization for the vector collection matrix
    such that it has a size of (max vectors ).  The size of the region
    pointed to by buffer (short pointer) should be five (5) times as large
    as maxvectors. This size is in bytes.  Areafills done by using AreaMove,
    AreaDraw, and AreaEnd must have enough space allocated in this table to
    store all the points of the largest fill. AreaEllipse takes up two
    vectors for every call. If AreaMove/Draw/Ellipse detect too many
    vectors going into the buffer they will return -1.

   INPUTS
    areainfo - pointer to AreaInfo structure
    buffer - pointer to chunk of memory to collect vertices
    maxvectors - max number of vectors this buffer can hold

   RESULT
    Pointers are set up to begin storage of vectors done by
    AreaMove, AreaDraw, and AreaEllipse.

   BUGS

   SEE ALSO
    AreaEnd() AreaMove() AreaDraw() AreaEllipse() graphics/rastport.h

 graphics.library/InitBitMap                       graphics.library/InitBitMap

   NAME

       InitBitMap -- Initialize bit map structure with input values.

   SYNOPSIS
    InitBitMap( bm, depth, width, height )
            a0   d0     d1      d2

    void InitBitMap( struct BitMap *, BYTE, UWORD, UWORD );

   FUNCTION
    Initialize various elements in the BitMap structure to
    correctly reflect depth, width, and height.
    Must be used before use of BitMap in other graphics calls.
    The Planes[8] are not initialized and need to be set up
    by the caller.  The Planes table was put at the end of the
    structure so that it may be truncated to conserve space,
    as well as extended. All routines that use BitMap should
    only depend on existence of depth number of bitplanes.
    The Flagsh and pad fields are reserved for future use and
    should not be used by application programs.

   INPUTS
    bm - pointer to a BitMap structure (gfx.h)
    depth - number of bitplanes that this bitmap will have
    width - number of bits (columns) wide for this BitMap
    height- number of bits (rows) tall for this BitMap

   BUGS

   SEE ALSO
    graphics/gfx.h

 graphics.library/InitGels                           graphics.library/InitGels

   NAME
    InitGels -- initialize a gel list; must be called before using gels.

   SYNOPSIS
    InitGels(head, tail, GInfo)
             A0    A1    A2

    void InitGels(struct VSprite *, struct VSprite *, struct GelsInfo *);

   FUNCTION
    Assigns the VSprites as the head and tail of the gel list in GfxBase.
    Links these two gels together as the keystones of the list.
    If the collHandler vector points to some memory array, sets
    the BORDERHIT vector to NULL.

   INPUTS
    head  = pointer to the VSprite structure to be used as the gel list head
    tail  = pointer to the VSprite structure to be used as the gel list tail
    GInfo = pointer to the GelsInfo structure to be initialized

   RESULT

   BUGS

   SEE ALSO
    graphics/gels.h  graphics/rastport.h

 graphics.library/InitGMasks                       graphics.library/InitGMasks

   NAME
    InitGMasks -- Initialize all of the masks of an AnimOb.

   SYNOPSIS
    InitGMasks(anOb)
               A0

    void InitGMasks(struct AnimOb *);

   FUNCTION
    For every sequence of every component call InitMasks.

   INPUTS
    anOb = pointer to the AnimOb

   BUGS

   SEE ALSO
    InitMasks() graphics/gels.h

 graphics.library/InitMasks                         graphics.library/InitMasks

   NAME
    InitMasks -- Initialize the BorderLine and CollMask masks of a VSprite.

   SYNOPSIS
    InitMasks(vs)
              A0

    void InitMasks(struct VSprite *);

   FUNCTION
    Creates the appropriate BorderLine and CollMask masks of the VSprite.
    Correctly detects if the VSprite is actually a Bob definition, handles
    the image data accordingly.

   INPUTS
    vs = pointer to the VSprite structure

   RESULT

   BUGS

   SEE ALSO
    InitGels()  graphics/gels.h

 graphics.library/InitRastPort                   graphics.library/InitRastPort

   NAME
    InitRastPort -- Initialize raster port structure

   SYNOPSIS
       InitRastPort( rp )
              a1

    void InitRastPort(struct RastPort *);

   FUNCTION
       Initialize a RastPort structure to standard values.

   INPUTS
    rp	= pointer to a RastPort structure.

   RESULT
    all entries in RastPort get zeroed out, with the following exceptions:

        Mask, FgPen, AOLPen, and LinePtrn are set to -1.
        The DrawMode is set to JAM2
        The font is set to the standard system font

   NOTES
    The struct Rastport describes a control structure
       for a write-able raster. The RastPort structure
       describes how a complete single playfield display
       will be written into. A RastPort structure is
       referenced whenever any drawing or filling
       operations are to be performed on a section of
       memory.

       The section of memory which is being used in this
       way may or may not be presently a part of the
       current actual onscreen display memory. The name
       of the actual memory section which is linked to
       the RastPort is referred to here as a "raster" or
       as a bitmap.

       NOTE: Calling the routine InitRastPort only
       establishes various defaults. It does NOT
       establish where, in memory, the rasters are
       located. To do graphics with this RastPort the user
    must set up the BitMap pointer in the RastPort.

   BUGS

   SEE ALSO
       graphics/rastport.h

 graphics.library/InitTmpRas                       graphics.library/InitTmpRas

   NAME
    InitTmpRas -- Initialize area of local memory for usage by
            areafill, floodfill, text.

   SYNOPSIS
       InitTmpRas(tmpras, buffer, size)
                      a0	     a1     d0

    void InitTmpRas( struct TmpRas *, void *, ULONG );

   FUNCTION
    The area of memory pointed to by buffer is set up to be used
    by RastPort routines that may need to get some memory for
    intermediate operations in preparation to putting the graphics
    into the final BitMap.
    Tmpras is used to control the usage of buffer.

   INPUTS
    tmpras - pointer to a TmpRas structure to be linked into
        a RastPort
    buffer - pointer to a contguous piece of chip memory.
    size - size in bytes of buffer

   RESULT
    makes buffer available for users of RastPort

   BUGS
    Would be nice if RastPorts could share one TmpRas.

   SEE ALSO
    AreaEnd() Flood() Text() graphics/rastport.h

 graphics.library/InitView                           graphics.library/InitView

   NAME
   InitView - Initialize View structure.

   SYNOPSIS
    InitView( view )
           a1

    void InitView( struct View * );

   FUNCTION
    Initialize View structure to default values.

   INPUTS
    view - pointer to a View structure

   RESULT
    View structure set to all 0's. (1.0,1.1.1.2)
    Then values are put in DxOffset,DyOffset to properly position
    default display about .5 inches from top and left on monitor.
    InitView pays no attention to previous contents of view.

   BUGS

   SEE ALSO
     MakeVPort graphics/view.h

 graphics.library/InitVPort                         graphics.library/InitVPort

   NAME
    InitVPort - Initialize ViewPort structure.

   SYNOPSIS
    InitVPort( vp )
           a0

    void InitVPort( struct ViewPort * );

   FUNCTION
    Initialize ViewPort structure to default values.

   INPUTS
    vp - pointer to a ViewPort structure

   RESULT
    ViewPort structure set to all 0's. (1.0,1.1)
       New field added SpritePriorities, initialized to 0x24 (1.2)

   BUGS

   SEE ALSO
    MakeVPort() graphics/view.h

 graphics.library/LoadRGB4                           graphics.library/LoadRGB4

   NAME
    LoadRGB4 -- Load RGB color values from table.

   SYNOPSIS
    LoadRGB4( vp, colors , count )
                 a0  	a1     d0:16

    void LoadRGB4( struct ViewPort *, UWORD *, WORD);

   FUNCTION
       load the count words of the colormap from table starting at
    entry 0.

   INPUTS
    vp - pointer to ViewPort, whose colors you wish to change
    colors - pointer to table of RGB values set up as an array
             of USHORTS
             background--  0x0RGB
            color1	  --  0x0RGB
            color2    --  0x0RGB
             etc.         UWORD per value.
        The colors are interpreted as 15 = maximum intensity.
                                      0 = minimum intensity.
    count	= number of UWORDs in the table to load into the
      colormap starting at color 0(background) and proceeding
      to the next higher color number

   RESULTS
    The ViewPort should have a pointer to a valid ColorMap to store
    the colors in.
    Updates the hardware copperlist to reflect the new colors.
    Updates the intermediate copperlist with the new colors.

   BUGS

    NOTE: With V36 and up, it is not safe to call this function
    from an interrupt, because of the semaphore locking on graphics
    copper lists.

   SEE ALSO
    SetRGB4() GetRGB4() GetColorMap() graphics/view.h

 graphics.library/LoadView                           graphics.library/LoadView

   NAME
       LoadView -- Use a (possibly freshly created) coprocessor instruction
                   list to create the current display.

   SYNOPSIS
       LoadView( View )
                  A1

    void LoadView( struct View * );

   FUNCTION
    Install a new view to be displayed during the next display
    refresh pass.
       Coprocessor instruction list has been created by
       InitVPort(), MakeVPort(), and MrgCop().

   INPUTS
       View - a pointer to the View structure which contains the
       pointer to the constructed coprocessor instructions list, or NULL.

   RESULT
    If the View pointer is non-NULL, the new View is displayed,
    according to your instructions.  The vertical blank routine
    will pick this pointer up and direct the copper to start
    displaying this View.

    If the View pointer is NULL, no View is displayed.

   NOTE
    Even though a LoadView(NULL) is performed, display DMA will still be
    active.  Sprites will continue to be displayed after a LoadView(NULL)
    unless an OFF_SPRITE is subsequently performed.

   BUGS

   SEE ALSO
       InitVPort() MakeVPort() MrgCop() intuition/RethinkDisplay()
    graphics/view.h

 graphics.library/LockLayerRom                   graphics.library/LockLayerRom

   NAME
    LockLayerRom -- Lock Layer structure by rom(gfx lib) code.

   SYNOPSIS
    LockLayerRom( layer )
               a5

    void LockLayerRom( struct Layer * );

   FUNCTION
    Return when the layer is locked and no other task may
    alter the ClipRect structure in the Layer structure.
    This call does not destroy any registers.
    This call nests so that callers in this chain will not lock
    themselves out.
    Do not have the Layer locked during a call to intuition.
    There is a potential deadlock problem here, if intuition
    needs to get other locks as well.
    Having the layer locked prevents other tasks from using the
    layer library functions, most notably intuition itself. So
    be brief.
    layers.library's LockLayer is identical to LockLayerRom.

   INPUTS
    layer - pointer to Layer structure

   RESULTS
    The layer is locked and the task can render assuming the
    ClipRects will not change out from underneath it until
    an UnlockLayerRom is called.

   SEE ALSO
    UnlockLayerRom() layers.library/LockLayer() graphics/clip.h

 graphics.library/MakeVPort                         graphics.library/MakeVPort

   NAME
    MakeVPort -- generate display copper list for a viewport.

   SYNOPSIS
    MakeVPort( view, viewport )
                      a0 	    a1

    void MakeVPort( struct View *, struct ViewPort * );

   FUNCTION
    Uses information in the View, ViewPort, ViewPort->RasInfo to
    construct and intermediate copper list for this ViewPort.

   INPUTS
    view - pointer to a View structure
    viewport - pointer to a ViewPort structure
         The viewport must have valid pointer to a RasInfo.

   RESULTS
    constructs intermediate copper list and puts pointers in
    viewport.DspIns
    If the ColorMap ptr in ViewPort is NULL then it uses colors
    from the default color table.
    If DUALPF in Modes then there must be a second RasInfo pointed
    to by the first RasInfo

   BUGS
    Narrow Viewports (whose righthand edge is less than 3/4 of the
    way across the display) still do not work properly.

   SEE ALSO
    InitVPort() MrgCop() graphics/view.h intuition.library/MakeScreen()
    intuition.library/RemakeDisplay() intuition.library/RethinkDisplay()

 graphics.library/ModeNotAvailable           graphics.library/ModeNotAvailable

   NAME
    ModeNotAvailable -- check to see if a DisplayID isn't available. (V36)

   SYNOPSIS
    error =  ModeNotAvailable( modeID )
    d0		           d0

    ULONG	ModeNotAvailable( ULONG);

   FUNCTION
    returns an error code, indicating why this modeID is not available,
    or NULL if there is no reason known why this mode should not be there.

   INPUTS
    modeID -- a 32 bit DisplayInfoRecord identifier.

   RESULT
    error -- a general indication of why this modeID is not available,
         or NULL if there is no reason why it shouldn't be available.

   NOTE
    ULONG return values from this function are a proper superset of the
    DisplayInfo.NotAvailable field (defined in graphics/displayinfo.h).

   BUGS

   SEE ALSO
    graphics/displayinfo.h, GetVPModeID()

 graphics.library/Move                                   graphics.library/Move

   NAME
    Move -- Move graphics pen position.

   SYNOPSIS
    Move( rp,   x,    y)
          a1  d0:16 d1:16

    void Move( struct RastPort *, SHORT, SHORT );

   FUNCTION
    Move graphics pen position to (x,y) relative to upper left (0,0)
    of RastPort. This sets the starting point for subsequent Draw()
    and Text() calls.

   INPUTS
    rp - pointer to a RastPort structure
    x,y - point in the RastPort

   RESULTS

   BUGS

   SEE ALSO
    Draw graphics/rastport.h

 graphics.library/MoveSprite                       graphics.library/MoveSprite

   NAME
    MoveSprite -- Move sprite to a point relative to top of viewport.

   SYNOPSIS
    MoveSprite(vp, sprite, x, y)
               A0  A1      D0 D1

    void MoveSprite(struct ViewPort *,struct SimpleSprite *, WORD, WORD);

   FUNCTION
    Move sprite image to new place on display.

   INPUTS
    vp - pointer to ViewPort structure
         if vp = 0, sprite is positioned relative to View.
    sprite - pointer to SimpleSprite structure
    (x,y)  - new position relative to top of viewport or view.

   RESULTS
    Calculate the hardware information for the sprite and
    place it in the posctldata array. During next video display
    the sprite will appear in new position.

   BUGS
    Sprites really appear one pixel to the left of the position you specify.
    This bug affects the apparent display position of the sprite on the
    screen,	but does not affect the numeric position relative to the
    viewport or view.

   SEE ALSO
    FreeSprite()  ChangeSprite()  GetSprite()  graphics/sprite.h

 graphics.library/MrgCop                               graphics.library/MrgCop

   NAME
       MrgCop -- Merge together coprocessor instructions.

   SYNOPSIS
       MrgCop( View )
                A1

    void MrgCop( struct View * );

   FUNCTION
       Merge together the display, color, sprite and user coprocessor
       instructions into a single coprocessor instruction stream.  This
       essentially creates a per-display-frame program for the coprocessor.
       This function MrgCop is used, for example, by the graphics animation
       routines which effectively add information into an essentially
       static background display.  This changes some of the user
       or sprite instructions, but not those which have formed the
       basic display in the first place.  When all forms of coprocessor
       instructions are merged together, you will have a complete per-
       frame instruction list for the coprocessor.

       Restrictions:  Each of the coprocessor instruction lists MUST be
       internally sorted in min to max Y-X order.  The merge routines
       depend on this! Each list must be terminated using CEND(copperlist).

   INPUTS
       View - a pointer to the view structure whose coprocessor
              instructions are to be merged.

   RESULT

       The view structure will now contain a complete, sorted/merged
       list of instructions for the coprocessor, ready to be used by
       the display processor.  The display processor is told to use
       this new instruction stream through the instruction LoadView().

   BUGS

   SEE ALSO
       InitVPort() MakeVPort() LoadView() graphics/view.h
    intuition.library/RethinkDisplay()

 graphics.library/NewRegion                         graphics.library/NewRegion

   NAME
       NewRegion -- Get an empty region.

   SYNOPSIS
       region = NewRegion()
    d0

    struct Region *NewRegion();

   FUNCTION
    Create a Region structure, initialize it to empty, and return
    a pointer it.

   RESULTS
    region - pointer to initialized region. If it could not allocate
        required memory region = NULL.

   INPUTS
    none

   BUGS

   SEE ALSO
    graphics/regions.h

 graphics.library/NextDisplayInfo             graphics.library/NextDisplayInfo

   NAME
    NextDisplayInfo -- iterate current displayinfo identifiers (V36)

   SYNOPSIS
    next_ID = NextDisplayInfo(last_ID)
    D0                        D0

    ULONG NextDisplayInfo(ULONG);

   FUNCTION
    The basic iteration function with which to find all records in the
    graphics database.  Using each ID in succession, you can then call
    FindDisplayInfo() to obtain the handle associated with each ID.
    Each ID is a 32-bit Key which uniquely identifies one record.
    The INVALID_ID is special, and indicates the end-of-list.

   INPUTS
    last_ID - previous displayinfo identifier
              or INVALID_ID if beginning iteration.

   RESULT
    next_ID - subsequent displayinfo identifier
              or INVALID_ID if no more records.

   BUGS

   SEE ALSO
    FindDisplayInfo(), GetDisplayInfoData()
    graphics/displayinfo.h

 graphics.library/OpenFont                           graphics.library/OpenFont

   NAME
    OpenFont -- Get a pointer to a system font.

   SYNOPSIS
    font = OpenFont(textAttr)
    D0              A0

    struct TextFont *OpenFont(struct TextAttr *);

   FUNCTION
    This function searches the system font space for the graphics
    text font that best matches the attributes specified.  The
    pointer to the font returned can be used in subsequent
    SetFont and CloseFont calls.  It is important to match this
    call with a corresponding CloseFont call for effective
    management of ram fonts.

   INPUTS
    textAttr - a TextAttr or TTextAttr structure that describes the
               text font attributes desired.

   RESULT
    font is zero if the desired font cannot be found.  If the named
    font is found, but the size and style specified are not
    available, a font with the nearest attributes is returned.

   SEE ALSO
    CloseFont()  SetFont()
    diskfont.library/OpenDiskFont  graphics/text.h

 graphics.library/OpenMonitor                     graphics.library/OpenMonitor

   NAME
       OpenMonitor -- open a named MonitorSpec (V36)

   SYNOPSIS
       mspc = OpenMonitor( monitor_name , display_id)
       d0                  a1		   d0

       struct MonitorSpec *OpenMonitor( char *, ULONG );

   FUNCTION
       Locate and open a named MonitorSpec.

   INPUTS
       monitor_name - a pointer to a null terminated string.
       display_id - an optional 32 bit monitor/mode identifier

   RESULTS
       mspc - a pointer to an open MonitorSpec structure.
              NULL if MonitorSpec could not  be opened.

   NOTE
    if monitor_name is non-NULL, the monitor will be opened by name.
    if monitor_name is NULL the monitor will be opened by optional ID.
    if both monitor_name and display_id are NULL returns default monitor.

   BUGS

   SEE ALSO
       CloseMonitor() graphics/monitor.h

 graphics.library/OrRectRegion                   graphics.library/OrRectRegion

   NAME
       OrRectRegion -- Perform 2d OR operation of rectangle
                       with region, leaving result in region.

   SYNOPSIS
       status = OrRectRegion(region,rectangle)
         d0                    a0      a1

    BOOL OrRectRegion( struct Region *, struct Rectangle * );

   FUNCTION
       If any portion of rectangle is not in the region then add
       that portion to the region.

   INPUTS
       region - pointer to Region structure
       rectangle - pointer to Rectangle structure

   RESULTS
    status - return TRUE if successful operation
         return FALSE if ran out of memory

   BUGS

   SEE ALSO
    AndRectRegion() OrRegionRegion() graphics/regions.h

 graphics.library/OrRegionRegion               graphics.library/OrRegionRegion

   NAME
       OrRegionRegion -- Perform 2d OR operation of one region
                       with second region, leaving result in second region

   SYNOPSIS
       status = OrRegionRegion(region1,region2)
         d0                       a0      a1

    BOOL OrRegionRegion( struct Region *, struct Region * );

   FUNCTION
       If any portion of region1  is not in the region then add
       that portion to the region2

   INPUTS
       region1 - pointer to Region structure
       region2 - pointer to Region structure

   RESULTS
    status - return TRUE if successful operation
         return FALSE if ran out of memory

   BUGS

   SEE ALSO
     OrRectRegion() graphics/regions.h

 graphics.library/OwnBlitter                       graphics.library/OwnBlitter

   NAME
       OwnBlitter -- get the blitter for private usage

   SYNOPSIS
       OwnBlitter()

    void OwnBlitter( void );

   FUNCTION
    If blitter is available return immediately with the blitter
    locked for your exclusive use. If the blitter is not available
    put task to sleep. It will be awakened as soon as the blitter
    is available. When the task first owns the blitter the blitter
    may still be finishing up a blit for the previous owner. You
    must do a WaitBlit before actually using the blitter registers.

    Calls to OwnBlitter() do not nest. If a task that owns the
    blitter calls OwnBlitter() again, a lockup will result.
    (Same situation if the task calls a system function
    that tries to own the blitter).

   INPUTS
    NONE

   RETURNS
    NONE

   SEE ALSO
    DisownBlitter() WaitBlit()
 graphics.library/PolyDraw                           graphics.library/PolyDraw

   NAME
    PolyDraw -- Draw lines from table of (x,y) values.

   SYNOPSIS
    PolyDraw( rp, count , array )
          a1   d0      a0

    void PolyDraw( struct RastPort *, WORD, WORD * );

   FUNCTION
    starting with the first pair in the array, draw connected lines to
    it and every successive pair.

   INPUTS
    rp - pointer to RastPort structure
    count -  number of (x,y) pairs in the array
    array - pointer to first (x,y) pair

   BUGS

   SEE ALSO
    Draw() Move() graphics/rastport.h

 graphics.library/QBlit                                 graphics.library/QBlit

   NAME

    QBlit -- Queue up a request for blitter usage

   SYNOPSIS
    QBlit( bp )
           a1

    void QBlit( struct bltnode * );

   FUNCTION
    Link a request for the use of the blitter to the end of the
       current blitter queue.  The pointer bp points to a blit structure
       containing, among other things, the link information, and the
       address of your routine which is to be called when the blitter
       queue finally gets around to this specific request.  When your
       routine is called, you are in control of the blitter ... it is
       not busy with anyone else's requests.  This means that you can
       directly specify the register contents and start the blitter.
       See the description of the blit structure and the uses of QBlit
       in the section titled Graphics Support in the OS Kernel Manual.
    Your code must be written to run either in supervisor or user
    mode on the 68000.

   INPUTS
    bp - pointer to a blit structure

   RESULT
    Your routine is called when the blitter is ready for you.
    In general requests for blitter usage through this channel are
    put in front of those who use the blitter via OwnBlitter and
    DisownBlitter. However for small blits there is more overhead
    using the queuer than Own/Disown Blitter.

   BUGS

   SEE ALSO
    QBSBlit() hardware/blit.h

 graphics.library/QBSBlit                             graphics.library/QBSBlit

   NAME

    QBSBlit -- Synchronize the blitter request with the video beam.

   SYNOPSIS

    QBSBlit( bsp )
         a1

    void QBSBlit( struct bltnode * );

   FUNCTION
    Call a user routine for use of the blitter, enqueued separately from
       the QBlit queue.  Calls the user routine contained in the blit
       structure when the video beam is located at a specified position
       onscreen.   Useful when you are trying to blit into a visible part
       of the screen and wish to perform the data move while the beam is
       not trying to display that same area.  (prevents showing part of
       an old display and part of a new display simultaneously).  Blitter
       requests on the QBSBlit queue take precedence over those on the
       regular blitter queue. The beam position is specified the blitnode.

   INPUTS
    bsp - pointer to a blit structure.  See description in the
             Graphics Support section of the manual for more info.

   RESULT
       User routine is called when the QBSBlit queue reaches this
       request AND the video beam is in the specified position.
    If there are lots of blits going on and the video beam
    has wrapped around back to the top it will call all the
    remaining bltnodes as fast as it can to try and catch up.

   BUGS
    Not very smart when getting blits from different tasks.
    They all get put in same queue so there are unfortunately
    some interdependencies with the beam syncing.

   SEE ALSO
    QBlit() hardware/blit.h

 graphics.library/ReadPixel                         graphics.library/ReadPixel

   NAME
       ReadPixel -- read the pen number value of the pixel at a
                    specified x,y location within a certain RastPort.

   SYNOPSIS
       penno = ReadPixel( rp,    x,    y )
         d0               a1  d0:16 d1:16

    LONG ReadPixel( struct RastPort *, SHORT, SHORT );

   FUNCTION
       Combine the bits from each of the bit-planes used to describe
       a particular RastPort into the pen number selector which that
       bit combination normally forms for the system hardware selection
       of pixel color.

   INPUTS
       rp -  pointer to a RastPort structure
       (x,y) a point in the RastPort

   RESULT
       penno - the pen number of the pixel at (x,y) is returned.
        -1 is returned if the pixel cannot be read for some reason.

   BUGS

   SEE ALSO
       WritePixel()	graphics/rastport.h

 graphics.library/ReadPixelArray8             graphics.library/ReadPixelArray8

   NAME
    ReadPixelArray8 -- read the pen number value of a rectangular array
    of pixels starting at a specified x,y location and continuing
    through to another x,y location within a certain RastPort. (V36)

   SYNOPSIS
    count = ReadPixelArray8(rp,xstart,ystart,xstop,ystop,array,temprp)
    D0                      A0 D0:16  D1:16  D2:16 D3:16 A2    A1

     LONG ReadPixelArray8(struct  RastPort *, UWORD, UWORD, UWORD, UWORD,
       UBYTE *, struct RastPort *);

   FUNCTION
    For each pixel in a rectangular region, combine the bits from each
    of the bit-planes used to describe a particular RastPort into the pen
    number selector which that bit combination normally forms for the
    system hardware selection of pixel color.

   INPUTS
    rp    -  pointer to a RastPort structure
    (xstart,ystart) - starting point in the RastPort
    (xstop,ystop)   - stopping point in the RastPort
    array - pointer to an array of ubytes from which to fetch the pixel data
            allocate at least ((((width+15)>>4)<<4)*(ystop-ystart+1)) bytes.
    temprp - temporary rastport (copy of rp with Layer set == NULL,
             temporary memory allocated for
             temprp->BitMap with Rows set == 1,
             temprp->BytesPerRow == (((width+15)>>4)<<1),
             and temporary memory allocated for
             temprp->BitMap->Planes[])

   RESULT
    For each pixel in the array:
        Pen - (0..255) number at that position is returned
    count   - the number of pixels read.

   NOTE
    xstop must be >= xstart
    ystop must be >= ystart

   BUGS

   SEE ALSO
    ReadPixel()  ReadPixelLine8()  graphics/rastport.h

 graphics.library/ReadPixelLine8               graphics.library/ReadPixelLine8

   NAME
    ReadPixelLine8 -- read the pen number value of a horizontal line
    of pixels starting at a specified x,y location and continuing
    right for count pixels. (V36)

   SYNOPSIS
    count = ReadPixelLine8(rp,xstart,ystart,width,array,temprp)
    D0                     A0 D0:16  D1:16  D2    A2    A1

    LONG ReadPixelLine8(struct RastPort *, UWORD, UWORD, UWORD,
         UBYTE *, struct RastPort * );

   FUNCTION
    For each pixel in a rectangular region, combine the bits from each
    of the bit-planes used to describe a particular RastPort into the pen
    number selector which that bit combination normally forms for the
    system hardware selection of pixel color.

   INPUTS
    rp    - pointer to a RastPort structure
    (x,y) - a point in the RastPort
    width - count of horizontal pixels to read
    array - pointer to an array of UBYTEs from which to fetch the pixel data
            allocate at least (((width+15)>>4)<<4) bytes.
    temprp - temporary rastport (copy of rp with Layer set == NULL,
             temporary memory allocated for
             temprp->BitMap with Rows set == 1,
             temprp->BytesPerRow == (((width+15)>>4)<<1),
             and temporary memory allocated for
             temprp->BitMap->Planes[])

   RESULT
    For each pixel in the array:
        Pen - (0..255) number at that position is returned
    count   - the number of pixels read.

   NOTE
    width must be non negative

   BUGS

   SEE ALSO
    ReadPixel()  graphics/rastport.h

 graphics.library/RectFill                           graphics.library/RectFill

   NAME
       RectFill -- Fill a rectangular region in a RastPort.

   SYNOPSIS

    RectFill( rp, xmin, ymin, xmax, ymax)
                 a1  d0:16 d1:16 d2:16 d3:16

    void RectFill( struct RastPort *, SHORT, SHORT, SHORT, SHORT );

   FUNCTION
    Fills  the  rectangular  region  specified  by  the
    parameters  with the chosen pen  colors,  areafill
    pattern, and drawing mode. If no areafill pattern is
    specified, fill the rectangular region with the FgPen
    color, taking into account the drawing mode.

   INPUTS
    rp - pointer to a RastPort structure
    (xmin,ymin) (xmax,ymax) are the coordinates of the upper
        left corner and the lower right corner, respectively, of the
            rectangle.
   NOTE

    The following relation MUST be true:
        (xmax >= xmin) and (ymax >= ymin)

   BUGS
    Complement mode with FgPen complements all bitplanes.

   SEE ALSO
    AreaEnd() graphics/rastport.h

 graphics.library/RemBob                               graphics.library/RemBob

   NAME
    RemBob -- Macro to remove a Bob from the gel list.

   SYNOPSIS
    RemBob(bob)

    RemBob(struct Bob *);

   FUNCTION
    Marks a Bob as no-longer-required.  The gels internal code then
    removes the Bob from the list of active gels the next time
    DrawGList is executed. This is implemented as a macro.
    If the user is double-buffering the Bob, it could take two
    calls to DrawGList before the Bob actually disappears from
    the RastPort.

   INPUTS
    Bob = pointer to the Bob to be removed

   RESULT

   BUGS

   SEE ALSO
    RemIBob()  DrawGList()  graphics/gels.h  graphics/gfxmacros.h

 graphics.library/RemFont                             graphics.library/RemFont

   NAME
    RemFont -- Remove a font from the system list.

   SYNOPSIS
    RemFont(textFont)
            A1

    void RemFont(struct TextFont *);

   FUNCTION
    This function removes a font from the system, ensuring that
    access to it is restricted to those applications that
    currently have an active pointer to it: i.e. no new SetFont
    requests to this font are satisfied.

   INPUTS
    textFont - the TextFont structure to remove.

   RESULT

   BUGS

   SEE ALSO
    SetFont()  AddFont()  graphics/text.h

 graphics.library/RemIBob                             graphics.library/RemIBob

   NAME
    RemIBob -- Immediately remove a Bob from the gel list and the RastPort.

   SYNOPSIS
    RemIBob(bob, rp, vp)
            A0   A1  A2

    void RemIBob(struct Bob *, struct RastPort *, struct ViewPort *);

   FUNCTION
    Removes a Bob immediately by uncoupling it from the gel list and
    erases it from the RastPort.

   INPUTS
    bob = pointer to the Bob to be removed
    rp  = pointer to the RastPort if the Bob is to be erased
    vp  = pointer to the ViewPort for beam-synchronizing

   RESULT

   BUGS

   SEE ALSO
    InitGels()  RemVSprite()  graphics/gels.h

 graphics.library/RemVSprite                       graphics.library/RemVSprite

   NAME
    RemVSprite -- Remove a VSprite from the current gel list.

   SYNOPSIS
    RemVSprite(vs)
               A0

    void RemVSprite(struct VSprite *);

   FUNCTION
    Unlinks the VSprite from the current gel list.

   INPUTS
    vs = pointer to the VSprite structure to be removed from the gel list

   RESULT

   BUGS

   SEE ALSO
    InitGels()  RemIBob()  graphics/gels.h

 graphics.library/ScalerDiv                         graphics.library/ScalerDiv

   NAME
    ScalerDiv -- Get the scaling result that BitMapScale would. (V36)

   SYNOPSIS
    result = ScalerDiv(factor, numerator, denominator)
    D0                 D0      D1         D2

    UWORD ScalerDiv(UWORD, UWORD, UWORD);

   FUNCTION
    Calculate the expression (factor*numerator/denominator) such
    that the result is the same as the width of the destination
    result of BitMapScale when the factor here is the width of
    the source, and the numerator and denominator are the
    XDestFactor and XSrcFactor for BitMapScale.

   INPUTS
    factor                 - a number in the range 0..16383
    numerator, denominator - numbers in the range 1..16383

   RESULT
    this returns factor*numerator/denominator

 graphics.library/ScrollRaster                   graphics.library/ScrollRaster

   NAME
    ScrollRaster -- Push bits in rectangle in raster around by
                    dx,dy towards 0,0 inside rectangle.
   SYNOPSIS
    ScrollRaster(rp, dx, dy, xmin, ymin, xmax, ymax)
                 A1  D0  D1  D2    D3    D4    D5

    void ScrollRaster
         (struct RastPort *, WORD, WORD, WORD, WORD, WORD, WORD);

   FUNCTION
    Move the bits in the raster by (dx,dy) towards (0,0)
    The space vacated is RectFilled with BGPen.
    Limit the scroll operation to the rectangle defined
    by (xmin,ymin)(xmax,ymax). Bits outside will not be
    affected. If xmax,ymax is outside the rastport then use
    the lower right corner of the rastport.
    If you are dealing with a SimpleRefresh layered RastPort you
    should check rp->Layer->Flags & LAYER_REFRESH to see if
    there is any damage in the damage list.  If there is you should
    call the appropriate BeginRefresh(Intuition) or BeginUpdate(graphics)
    routine sequence.

   INPUTS
    rp - pointer to a RastPort structure
    dx,dy are integers that may be postive, zero, or negative
    xmin,ymin - upper left of bounding rectangle
    xmax,ymax - lower right of bounding rectangle

   EXAMPLE
    ScrollRaster(rp,0,1)    /* shift raster up by one row */
    ScrollRaster(rp,-1,-1)  /* shift raster down and to the right by 1 pixel

   BUGS
    In 1.2/V1.3 if you ScrollRaster a SUPERBITMAP exactly left or
    right, and there is no TmpRas attached to the RastPort, the system
    will allocate one for you, but will never free it or record its
    location. This bug has been fixed for V1.4.  The workaround for
    1.2/1.3 is to attach a valid TmpRas of size at least
    MAXBYTESPERROW to the RastPort before the call.

    Begining with V1.4 ScrollRaster adds the shifted areas into the
    damage list for SIMPLE_REFRESH windows. Due to unacceptable
    system overhead, the decision was made NOT to propagate this
    shifted area damage for SMART_REFRESH windows.

   SEE ALSO
    graphics/rastport.h

 graphics.library/ScrollVPort                     graphics.library/ScrollVPort

   NAME
    ScrollVPort -- Reinterpret RasInfo information in ViewPort to reflect
            the current Offset values.

   SYNOPSIS
    ScrollVPort( vp )
             a0

    void ScrollVPort(struct ViewPort *);

   FUNCTION
    After the programmer has adjusted the Offset values in
    the RasInfo structures of ViewPort, change the
    the copper lists to reflect the the Scroll positions.
    Changing the BitMap ptr in RasInfo and not changing the
    the Offsets will effect a double buffering affect.

   INPUTS
       vp - pointer to a ViewPort structure
         that is currently be displayed.
   RESULTS
    modifies hardware and intermediate copperlists to reflect
    new RasInfo

   BUGS
       pokes not fast enough to avoid some visible hashing of display

   SEE ALSO
    MakeVPort() MrgCop() LoadView()  graphics/view.h

 graphics.library/SetAPen                             graphics.library/SetAPen

   NAME
    SetAPen -- Set the primary pen for a RastPort.

   SYNOPSIS
    SetAPen( rp, pen )
         a1  d0

    void SetAPen( struct RastPort *, UBYTE );

   FUNCTION
    Set the primary drawing pen for lines, fills, and text.

   INPUTS
    rp - pointer to RastPort structure.
    pen - (0-255)

   RESULT
    Changes the minterms in the RastPort to reflect new primary pen.
    Sets line drawer to restart pattern.

   BUGS

   SEE ALSO
    SetBPen() graphics/rastport.h

 graphics.library/SetBPen                             graphics.library/SetBPen

   NAME
    SetBPen -- Set secondary pen for a RastPort

   SYNOPSIS
    SetBPen( rp, pen )
         a1  d0

    void SetBPen( struct RastPort *, UBYTE );

   FUNCTION
    Set the secondary drawing pen for lines, fills, and text.

   INPUTS
    rp - pointer to RastPort structure.
    pen - (0-255)

   RESULT
    Changes the minterms in the RastPort to reflect new secondary pen.
    Sets line drawer to restart pattern.

   BUGS

    SEE ALSO
    SetAPen() graphics/rastport.h

 graphics.library/SetCollision                   graphics.library/SetCollision

   NAME
    SetCollision -- Set a pointer to a user collision routine.

   SYNOPSIS
    SetCollision(num, routine, GInfo)
                 D0   A0       A1

    void SetCollision(ULONG, VOID (*)(), struct GelsInfo *);

   FUNCTION
    Sets a specified entry (num) in the user's collision vectors table
    equal to the address of the specified collision routine.

   INPUTS
    num     = collision vector number
    routine = pointer to the user's collision routine
    GInfo   = pointer to a GelsInfo structure

   RESULT

   BUGS

   SEE ALSO
    InitGels()  graphics/gels.h  graphics/rastport.h

 graphics.library/SetDrMd                             graphics.library/SetDrMd

   NAME
     SetDrMd -- Set drawing mode for a RastPort

   SYNOPSIS
    SetDrMd( rp, mode )
         a1  d0:8

    void SetDrMd( struct RastPort *, UBYTE );

   FUNCTION
    Set the drawing mode for lines, fills and text.
    Get the bit definitions from rastport.h

   INPUTS
    rp - pointer to RastPort structure.
    mode - 0-255, some combinations may not make much sense.

   RESULT
    The mode set is dependant on the bits selected.
    Changes minterms to reflect new drawing mode.
    Sets line drawer to restart pattern.

   BUGS

   SEE ALSO
    SetAPen() SetBPen() graphics/rastport.h

 graphics.library/SetFont                             graphics.library/SetFont

   NAME
    SetFont -- Set the text font and attributes in a RastPort.

   SYNOPSIS
    SetFont(rp, font)
            A1   A0

    void SetFont(struct RastPort *, struct TextFont *);

   FUNCTION
    This function sets the font in the RastPort to that described
    by font, and updates the text attributes to reflect that
    change.  This function clears the effect of any previous
    soft styles.

   INPUTS
    rp   - the RastPort in which the text attributes are to be changed
    font - pointer to a TextFont structure returned from OpenFont()
           or OpenDiskFont()

   RESULT

   NOTES
    This function had previously been documented that it would
    accept a null font.  This practice is discouraged.
    o   Use of a RastPort with a null font with text routines has
        always been incorrect and risked the guru.
    o   Keeping an obsolete font pointer in the RastPort is no more
        dangerous than keeping a zero one there.
    o   SetFont(rp, 0) causes spurious low memory accesses under
        some system software releases.

    As of V36, the following Amiga font variants are no longer
    directly supported:
        fonts with NULL tf_CharSpace and non-NULL tf_CharKern.
        fonts with non-NULL tf_CharSpace and NULL tf_CharKern.
        fonts with NULL tf_CharSpace and NULL tf_CharKern with
        a tf_CharLoc size component greater than tf_XSize.
    Attempts to SetFont these one of these font variants will
    cause the system to modify your font to make it acceptable.

   BUGS
    Calling SetFont() on in-code TextFonts (ie fonts not
    OpenFont()ed) will result in a loss of 24 bytes from
    the system as of V36.
    This can be resolved by calling StripFont().

   SEE ALSO
    OpenFont()  StripFont()
    diskfont.library/OpenDiskFont()  graphics/text.h

 graphics.library/SetOPen                             graphics.library/SetOPen

   NAME
    SetOPen -- Change the Area OutLine pen and turn on Outline
            mode for areafills.

   SYNOPSIS
    SetOPen(rp, pen)

    void SetOPen( struct RastPort *, UBYTE );

   FUNCTION
    This is implemented as a c-macro.
    Pen is the pen number that will be used to draw a border
    around an areafill during AreaEnd().

   INPUTS
    rp = pointer to RastPort structure
    pen = number  between 0-255

   BUGS

   SEE ALSO
    AreaEnd() graphics/gfxmacros.h graphics/rastport.h

 graphics.library/SetRast                             graphics.library/SetRast

   NAME
       SetRast - Set an entire drawing area to a specified color.

   SYNOPSIS
       SetRast( rp, pen )
                a1  d0

    void SetRast( struct RastPort *, UBYTE );

   FUNCTION
       Set the entire contents of the specified RastPort to the
       specified pen.

   INPUTS
       rp - pointer to RastPort structure
       pen - the pen number (0-255) to jam into bitmap

   RESULT
       All pixels within the drawing area are set to the
    selected pen number.

   BUGS

   SEE ALSO
    RectFill() graphics/rastport.h

 graphics.library/SetRGB4                             graphics.library/SetRGB4

    NAME
       SetRGB4 -- Set one color register for this viewport.

    SYNOPSIS
       SetRGB4(  vp, n,   r,    g,    b)
                 a0  d0  d1:4  d2:4  d3:4

    void SetRGB4( struct ViewPort *, SHORT, UBYTE, UBYTE, UBYTE );

    FUNCTION
    Change the color look up table so that this viewport displays
    the color (r,g,b) for pen number n.

    INPUTS
    vp - pointer to  viewport structure
       n - the color number (range from 0 to 31)
       r - red level (0-15)
       g - green level (0-15)
       b - blue level (0-15)

    RESULT
    If there is a ColorMap for this viewport, then the value will
    be stored in the ColorMap.
       The selected color register is changed to match your specs.
    If the color value is unused then nothing will happen.

    BUGS
    NOTE: Under V36 and up, it is not safe to call this function
    from an interrupt, due to semaphore protection of graphics
    copper lists.

    SEE ALSO
       LoadRGB4() GetRGB4() graphics/view.h
 graphics.library/SetRGB4CM                         graphics.library/SetRGB4CM

   NAME
       SetRGB4CM -- Set one color register for this ColorMap.

   SYNOPSIS
       SetRGB4CM(  cm,  n,   r,    g,    b)
                   a0  d0  d1:4  d2:4  d3:4

       void SetRGB4CM( struct ColorMap *, SHORT, UBYTE, UBYTE, UBYTE );

   INPUTS
    cm = colormap
       n = the number of the color register to set. Ranges from 0 to 31
        on current amiga displays.
       r = red level (0-15)
       g = green level (0-15)
       b = blue level (0-15)

   RESULT
    Store the (r,g,b) triplet at index n of the ColorMap structure.
       This function can be used to set up a ColorMap before before
    linking it into a viewport.

   BUGS

   SEE ALSO
       GetColorMap() GetRGB4() SetRGB4() graphics/view.h
 graphics.library/SetSoftStyle                   graphics.library/SetSoftStyle

   NAME
    SetSoftStyle -- Set the soft style of the current font.

   SYNOPSIS
    newStyle = SetSoftStyle(rp, style, enable)
    D0                      A1  D0     D1

    ULONG SetSoftStyle(struct RastPort *, ULONG, ULONG);

   FUNCTION
    This function alters the soft style of the current font.  Only
    those bits that are also set in enable are affected.  The
    resulting style is returned, since some style request changes
    will not be honored when the implicit style of the font
    precludes changing them.

   INPUTS
    rp     - the RastPort from which the font and style
             are extracted.
    style  - the new font style to set, subject to enable.
    enable - those bits in style to be changed.  Any set bits here
             that would not be set as a result of AskSoftStyle will
             be ignored, and the newStyle result will not be as
             expected.

   RESULTS
    newStyle - the resulting style, both as a result of previous
               soft style selection, the effect of this function,
               and the style inherent in the set font.

   BUGS

   SEE ALSO
    AskSoftStyle()  graphics/text.h

 graphics.library/SortGList                         graphics.library/SortGList

   NAME
    SortGList -- Sort the current gel list, ordering its y,x coordinates.

   SYNOPSIS
    SortGList(rp)
              A1

    void SortGList(struct RastPort *);

   FUNCTION
    Sorts the current gel list according to the gels' y,x coordinates.
    This sorting is essential before calls to DrawGList or DoCollision.

   INPUTS
    rp = pointer to the RastPort structure containing the GelsInfo

   RESULT

   BUGS

   SEE ALSO
    InitGels()  DoCollision()  DrawGList()  graphics/rastport.h

 graphics.library/StripFont                         graphics.library/StripFont

   NAME
    StripFont -- remove the tf_Extension from a font (V36)

   SYNOPSIS
    StripFont(font)
              A0

    VOID StripFont(struct TextFont *);

 graphics.library/SyncSBitMap                     graphics.library/SyncSBitMap

   NAME
       SyncSBitMap --	Syncronize Super BitMap with whatever is
            in the standard Layer bounds.

   SYNOPSIS
       SyncSBitMap( layer )
                      a0

    void SyncSBitMap( struct Layer * );

   FUNCTION
       Copy all bits from ClipRects in Layer into Super BitMap
    BitMap.  This is used for those functions that do not
    want to deal with the ClipRect structures but do want
    to be able to work with a SuperBitMap Layer.

   INPUTS
    layer - pointer to a Layer that has a SuperBitMap
        The Layer should already be locked by the caller.

   RESULT
    After calling this function, the programmer can manipulate
    the bits in the superbitmap associated with the layer.
    Afterwards, the programmer should call CopySBitMap to
    copy the bits back into the onscreen layer.

   BUGS

   SEE ALSO
    CopySBitMap() graphics/clip.h

 graphics.library/Text                                   graphics.library/Text

   NAME
    Text -- Write text characters (no formatting).

   SYNOPSIS
    Text(rp, string, length)
         A1  A0      D0-0:16

    void Text(struct RastPort *, STRPTR, WORD);

   FUNCTION
    This graphics function writes printable text characters to the
    specified RastPort at the current position.  No control meaning
    is applied to any of the characters, thus only text on the
    current line is output.

    The current position in the RastPort is updated to the next
    character position.
    If the characters displayed run past the RastPort boundary,
    the current position is truncated to the boundary, and
    thus does not equal the old position plus the text length.

   INPUTS
    rp     - a pointer to the RastPort which describes where the
             text is to be output
    string - the address of string to output
    length - the number of characters in the string.
             If zero, there are no characters to be output.

   NOTES
    o   This function may use the blitter.
    o   Changing the text direction with RastPort->TxSpacing is
        not supported.

   BUGS
    For V34 and earlier:
    o   The maximum string length (in pixels) is limited to
        (1024 - 16 = 1008) pixels wide.
    o   A text string whose last character(s) have a
        tf_CharLoc size component that extends to the right of
        the rightmost of the initial and final CP positions
        will be (inappropriately) clipped.

   SEE ALSO
    Move()  TextLength()  graphics/text.h  graphics/rastport.h

 graphics.library/TextExtent                       graphics.library/TextExtent

   NAME
    TextExtent -- Determine raster extent of text data. (V36)

   SYNOPSIS
    TextExtent(rp, string, count, textExtent)
               A1  A0      D0:16  A2

    void TextExtent(struct RastPort *, STRPTR, WORD,
         struct TextExtent *);

   FUNCTION
    This function determines a more complete metric of the space
    that a text string would render into than the TextLength()
    function.

   INPUTS
    rp     - a pointer to the RastPort which describes where the
             text attributes reside.
    string - the address of the string to determine the length of.
    count  - the number of characters in the string.
                If zero, there are no characters in the string.
    textExtent - a structure to hold the result.

   RESULTS
    textExtent is filled in as follows:
        te_Width  - same as TextLength() result: the rp_cp_x
                    advance that rendering this text would cause.
        te_Height - same as tf_YSize.  The height of the
                    font.
        te_Extent.MinX - the offset to the left side of the
                    rectangle this would render into.  Often zero.
        te_Extent.MinY - same as -tf_Baseline.  The offset
                    from the baseline to the top of the rectangle
                    this would render into.
        te_Extent.MaxX - the offset of the left side of the
                    rectangle this would render into.  Often the
                    same as te_Width-1.
        te_Extent.MaxY - same as tf_YSize-tf_Baseline-1.
                    The offset from the baseline to the bottom of
                    the rectanangle this would render into.

   SEE ALSO
    TextLength()  Text()  TextFit()
    graphics/text.h  graphics/rastport.h

 graphics.library/TextFit                             graphics.library/TextFit

   NAME
    TextFit - count characters that will fit in a given extent (V36)

   SYNOPSIS
    chars = TextFit(rastport, string, strLen, textExtent,
    D0              A1        A0      D0      A2
            constrainingExtent, strDirection,
            A3                  D1
            constrainingBitWidth, constrainingBitHeight)
            D2                    D3

    ULONG TextFit(struct RastPort *, STRPTR, UWORD,
        struct TextExtent *, struct TextExtent *, WORD, UWORD, UWORD);

   FUNCTION
    This function determines how many of the characters of the
    provided string will fit into the space described by the
    constraining parameters.  It also returns the extent of
    that number of characters.

   INPUTS
    rp     - a pointer to the RastPort which describes where the
             text attributes reside.
    string - the address of string to determine the constraint of
    strLen - The number of characters in the string.
             If zero, there are no characters in the string.
    textExtent - a structure to hold the extent result.
    constrainingExtent - the extent that the text must fit in.
        This can be NULL, indicating only the constrainingBit
        dimensions will describe the constraint.
    strDirection - the offset to add to the string pointer to
        get to the next character in the string.  Usually 1.
        Set to -1 and the string to the end of the string to
        perform a TextFit() anchored at the end.  No other value
        is valid.
    constrainingBitWidth - an alternative way to specify the
        rendering box constraint width that is independent of
        the rendering origin.  Range 0..32767.
    constrainingBitHeight - an alternative way to specify the
        rendering box constraint height that is independent of
        the rendering origin.  Range 0..32767.

   RESULTS
    chars - the number of characters from the origin of the
            given string that will fit in both the constraining
            extent (which specifies a CP bound and a rendering
            box relative to the origin) and in the rendering width
            and height specified.

   NOTES
    The result is zero chars and an empty textExtent when the fit
    cannot be performed.  This occurs not only when no text will
    fit in the provided constraints, but also when:
    -   the RastPort rp's rp_TxSpacing sign and magnitude is so
        great it reverses the path of the text.
    -   the constrainingExtent does not include x = 0.

   SEE ALSO
    TextExtent()  TextLength()  Text()
    graphics/text.h  graphics/rastport.h

 graphics.library/TextLength                       graphics.library/TextLength

   NAME
    TextLength -- Determine raster length of text data.

   SYNOPSIS
    length = TextLength(rp, string, count)
    D0                  A1  A0      D0:16

    WORD TextLength(struct RastPort *, STRPTR, WORD);

   FUNCTION
    This graphics function determines the length that text data
    would occupy if output to the specified RastPort with the
    current attributes.  The length is specified as the number of
    raster dots: to determine what the current position would be
    after a Write() using this string, add the length to cp_x
    (cp_y is unchanged by Write()).  Use the newer TextExtent() to
    get more information.

   INPUTS
    rp     - a pointer to the RastPort which describes where the
             text attributes reside.
    string - the address of string to determine the length of
    count  - the string length.  If zero, there are no characters
             in the string.

   RESULTS
    length - the number of pixels in x this text would occupy, not
             including any negative kerning that may take place at
             the beginning of the text string, nor taking into
             account the effects of any clipping that may take
             place.

   NOTES
    Prior to V36, the result length occupied only the low word of
    d0 and was not sign extended into the high word.

   BUGS
    A length that would overflow single word arithmatic is not
    calculated correctly.

   SEE ALSO
    TextExtent()  Text()  TextFit()
    graphics/text.h  graphics/rastport.h

 graphics.library/UnlockLayerRom               graphics.library/UnlockLayerRom

   NAME
    UnlockLayerRom -- Unlock Layer structure by rom(gfx lib) code.

   SYNOPSIS
    UnlockLayerRom( layer )
             a5

    void UnlockLayerRom( struct Layer * );

   FUNCTION
    Release the lock on this layer. If the same task has called
    LockLayerRom more than once than the same number of calls to
    UnlockLayerRom must happen before the layer is actually freed
    so that other tasks may use it.
    This call does destroy scratch registers.
    This call is identical to UnlockLayer (layers.library).

   INPUTS
    layer - pointer to Layer structure

   BUGS

   SEE ALSO
    LockLayerRom() layers.library/UnlockLayer() graphics/clip.h

 graphics.library/VBeamPos                           graphics.library/VBeamPos

   NAME
    VBeamPos -- Get vertical beam position at this instant.

   SYNOPSIS
    pos = VBeamPos()
     d0

    LONG VBeamPos( void );

   FUNCTION
    Get the vertical beam position from the hardware.

   INPUTS
    none

   RESULT
    interrogates hardware for beam position and returns value.
    valid results in are the range of 0-511.
    Because of multitasking, the actual value returned may have
    no use. If you are the highest priority task then the value
    returned should be close, within 1 line.

   BUGS

   SEE ALSO

 graphics.library/VideoControl                   graphics.library/VideoControl

   NAME
       VideoControl -- Modify the operation of a ViewPort's ColorMap (V36)

   SYNOPSIS
       error = VideoControl( cm , tags )
       d0                    a0   a1

    ULONG VideoControl( struct ColorMap *, struct TagItem * );

   FUNCTION
    Process the commands in the VideoControl command TagItem buffer
    using cm as the target, with respect to its "attached" ViewPort.

    viewport commands:

    VTAG_ATTACH_CM     [_SET        | _GET] -- set\get attached viewport
    VTAG_VIEWPORTEXTRA [_SET        | _GET] -- set\get attached vp_extra
    VTAG_NORMAL_DISP   [_SET        | _GET] -- set\get DisplayInfoHandle
                               (natural mode)
    VTAG_COERCE_DISP   [_SET        | _GET] -- set\get DisplayInfoHandle
                               (coerced mode)

    genlock commands:

    VTAG_BORDERBLANK   [_SET | _CLR | _GET] -- on\off\inquire blanking
    VTAG_BORDERNOTRANS [_SET | _CLR | _GET] -- on\off\inquire notransparency
    VTAG_CHROMAKEY     [_SET | _CLR | _GET] -- on\off\inquire chroma mode
    VTAG_BITPLANEKEY   [_SET | _CLR | _GET] -- on\off\inquire bitplane mode
    VTAG_CHROMA_PEN    [_SET | _CLR | _GET] -- set\clr\get chromakey pen #
    VTAG_CHROMA_PLANE  [_SET |      | _GET] -- set\get bitplanekey plane #

    copper commands

    VTAG_USERCLIP      [_SET | _CLR | _GET] -- on\off\inquire clipping of
                           UserCopperList at bottom
                           edge of ColorMap->cm_vp
                           (defaults to off)

    buffer commands:

    VTAG_NEXTBUF_CM    		        -- link to more VTAG commands
    VTAG_END_CM    		    	        -- terminate command buffer

    batch mode commands:

    (if you want your videocontol taglist to be processed in "batch"
     mode, that is, at the next MakeVPort() for the ColorMap->cm_vp;
     you may intall a static list of videocontrol TagItems into the
     ColorMap with the BATCH_ITEMS_SET command; and then enable/disable
     batch mode processing of those items via the BATCH_CM control
     command)

    VTAG_BATCH_CM      [_SET | _CLR | _GET] -- on\off\inquire batch mode
    VTAG_BATCH_ITEMS   [_SET | _ADD | _GET] -- set\add\get batched TagLists

    private commands (used internally by intuition -- do not call):

    VTAG_VPMODEID      [_SET | _CLR | _GET] -- force GetVPModeID() return

   INPUTS
    cm   = pointer to struct ColorMap obtained via GetColorMap().
    tags = pointer to a table of videocontrol tagitems.

   RESULT
    error = NULL if no error occured in the control operation.
       (non-NULL if bad colormap pointer, no tagitems or bad tag)

    The operating characteristics of the ColorMap and its attached
    ViewPort are modified. The result will be incorporated into the
    ViewPort when its copper lists are reassembled via MakeVPort().

   BUGS

   SEE ALSO
    graphics/videocontrol.h, GetColorMap(), FreeColorMap()

 graphics.library/WaitBlit                           graphics.library/WaitBlit

   NAME
       WaitBlit -- Wait for the blitter to be finished before proceeding
                   with anything else.

   SYNOPSIS
       WaitBlit()

    void WaitBlit( void );

   FUNCTION
    WaitBlit returns when the blitter is idle. This function should
    normally only be used when dealing with the blitter in a
    synchronous manner, such as when using OwnBlitter and DisownBlitter.
    WaitBlit does not wait for all blits queued up using QBlit or
    QBSBlit. You should call WaitBlit if you are just about to modify or
    free some memory that the blitter may be using.

   INPUTS
       none

   RESULT
       Your program waits until the blitter is finished.
    This routine does not use any the CPU registers.
    do/d1/a0/a1 are preserved by this routine.
    It may change the condition codes though.

   BUGS
    When examining bits with the CPU right after a blit, or when freeeing
    temorary memory used by the blitter, a WaitBlit() may be required.

    Note that many graphics calls fire up the blitter, and let it run.
    The CPU does not need to wait for the blitter to finish before
    returning.

    Because of a bug in agnus (prior to all revisions of fat agnus)
     this code may return too soon when the blitter has, in fact, not
    started the blit yet, even though BltSize has been written.

    This most often occurs in a heavily loaded systen with extended memory,
    HIRES, and 4 bitplanes.

    WaitBlit currently tries to avoid this agnus problem by testing
    the BUSY bit multiple times to make sure the blitter has started.
    If the blitter is BUSY at first check, this function busy waits.

    This initial hardware bug was fixed as of the first "Fat Agnus" chip,
    as used in all A500 and A2000 computers.

    Because of a different bug in agnus (currently all revisions thru ECS)
     this code may return too soon when the blitter has, in fact, not
    stopped the blit yet, even though blitter busy has been cleared.

    This most often occurs in a heavily loaded systen with extended memory,
    in PRODUCTIVITY mode, and 2 bitplanes.

    WaitBlit currently tries to avoid this agnus problem by testing
    the BUSY bit multiple times to make sure the blitter has really
    written its final word of desination data.

   SEE ALSO
    OwnBlitter() DisownBlitter() hardware/blit.h

 graphics.library/WaitBOVP                           graphics.library/WaitBOVP

   NAME
    WaitBOVP -- Wait till vertical beam reached bottom of
            this viewport.

   SYNOPSIS
    WaitBOVP( vp )
          a0

    void WaitBOVP( struct ViewPort * );

   FUNCTION
    Returns when the vertical beam has reached the bottom of this viewport

   INPUTS
    vp - pointer to ViewPort structure

   RESULT
    This function will return sometime after the beam gets beyond
    the bottom of the viewport.  Depending on the multitasking load
    of the system, the actual beam position may be different than
    what would be expected in a lightly loaded system.

   BUGS
    Horrors! This function currently busy waits waiting for the
    beam to get to the right place.  It should use the copper
    interrupt to trigger and send signals like WaitTOF does.

   SEE ALSO
    WaitTOF() VBeamPos()

 graphics.library/WaitTOF                             graphics.library/WaitTOF

   NAME
       WaitTOF -- Wait for the top of the next video frame.

   SYNOPSIS
       WaitTOF()

    void WaitTOF( void );

   FUNCTION
       Wait  for vertical blank to occur and all vertical blank
       interrupt routines to complete before returning to caller.

   INPUTS
       none

   RESULT
    Places this task on the TOF wait queue. When the vertical blank
    interupt comes around, the interrupt service routine will fire off
    signals to all the tasks doing WaitTOF. The highest priority task
    ready will get to run then.

   BUGS

   SEE ALSO
    exec.library/Wait() exec.library/Signal()

 graphics.library/WeighTAMatch                   graphics.library/WeighTAMatch

   NAME
    WeighTAMatch -- Get a measure of how well two fonts match. (V36)

   SYNOPSIS
    weight = WeighTAMatch(reqTextAttr, targetTextAttr, targetTags)
    D0                    A0           A1              A2

    WORD WeighTAMatch(struct TTextAttr *, struct TextAttr *,
         struct TagItem *);

   FUNCTION
    This function provides a metric to describe how well two fonts
    match.  This metric ranges from MAXFONTMATCHWEIGHT (perfect match)
    through lower positive numbers to zero (unsuitable match).

   INPUTS
    reqTextAttr    - the text attributes requested.
    targetTextAttr - the text attributes of a potential match.
    targetTags     - tags describing the extended target attributes, or
                     zero if not available.

    The [t]ta_Name fields of the [T]TextAttr structures are not used.

    The tags affect the weight only when both a) the reqTextAttr
    has the FSF_TAGGED bit set in ta_Style, and b) targetTags is
    not zero.  To fairly compare two different weights, the inclusion
    or exclusion of tags in the weighing must be the same for both.

   RESULTS
    weight -- a positive weight describes suitable matches, in
          increasing desirability.  MAXFONTMATCHWEIGHT is a perfect
          match.  A zero weight is an unsuitable match.

   SEE ALSO
    OpenFont()

 graphics.library/WritePixel                       graphics.library/WritePixel

   NAME
       WritePixel -- Change the pen num of one specific pixel in a
                     specified RastPort.

   SYNOPSIS
       error = WritePixel(  rp, x,  y)
         d0                 a1 D0  D1

    LONG WritePixel( struct RastPort *, SHORT, SHORT );

   FUNCTION
       Changes the pen number of the selected pixel in the specified
       RastPort to that currently specified by PenA, the primary
       drawing pen. Obeys minterms in RastPort.

   INPUTS
       rp - a pointer to the RastPort structure
       (x,y) - point within the RastPort at which the selected
           pixel is located.

   RESULT
       error = 0 if pixel succesfully changed
          = -1 if (x,y) is outside the RastPort

   BUGS

   SEE ALSO
       ReadPixel() graphics/rastport.h

 graphics.library/WritePixelArray8           graphics.library/WritePixelArray8

   NAME
    WritePixelArray8 -- write the pen number value of a rectangular array
    of pixels starting at a specified x,y location and continuing
    through to another x,y location within a certain RastPort. (V36)

   SYNOPSIS
    count = WritePixelArray8(rp,xstart,ystart,xstop,ystop,array,temprp)
    D0                       A0 D0:16  D1:16  D2:16 D3:16  A2   A1

    LONG WritePixelArray8(struct  RastPort *, UWORD, UWORD,
         UWORD, UWORD, UBYTE *, struct  RastPort *);

   FUNCTION
    For each pixel in a rectangular region, decode the pen number selector
    from a linear array of pen numbers into the bit-planes used to describe
    a particular rastport.

   INPUTS
    rp     -  pointer to a RastPort structure
    (xstart,ystart) -  starting point in the RastPort
    (xstop,ystop)   -  stopping point in the RastPort
    array  - pointer to an array of UBYTEs from which to fetch the
             pixel data. Allocate at least
             ((((width+15)>>4)<<4)*(ystop-ystart+1)) bytes.
    temprp - temporary rastport (copy of rp with Layer set == NULL,
             temporary memory allocated for
             temprp->BitMap with Rows set == 1,
             temprp->BytesPerRow == (((width+15)>>4)<<1),
             and temporary memory allocated for
             temprp->BitMap->Planes[])

   RESULT
    For each pixel in the array:
        Pen - (0..255) number at that position is returned

   NOTE
    xstop must be >= xstart
    ystop must be >= ystart

   BUGS

   SEE ALSO
    WritePixel()  graphics/rastport.h

 graphics.library/WritePixelLine8             graphics.library/WritePixelLine8

   NAME
    WritePixelLine8 -- write the pen number value of a horizontal line
    of pixels starting at a specified x,y location and continuing
    right for count pixels. (V36)

   SYNOPSIS
    count = WritePixelLine8(rp,xstart,ystart,width,array,temprp)
    D0                      A0 D0:16  D1:16  D2    A2    A1

    LONG WritePixelLine8(struct RastPort *, UWORD, UWORD,
         UWORD, UBYTE *, struct RastPort *);

   FUNCTION
    For each pixel in a horizontal region, decode the pen number selector
    from a linear array of pen numbers into the bit-planes used to describe
    a particular rastport.

   INPUTS
    rp    -  pointer to a RastPort structure
    (x,y) - a point in the RastPort
    width - count of horizontal pixels to write
    array - pointer to an array of UBYTEs from which to fetch the pixel data
            allocate at least (((width+15)>>4)<<4) bytes.
    temprp - temporary rastport (copy of rp with Layer set == NULL,
             temporary memory allocated for
             temprp->BitMap with Rows set == 1,
             temprp->BytesPerRow == (((width+15)>>4)<<1),
             and temporary memory allocated for
             temprp->BitMap->Planes[])

   RESULT
    For each pixel in the array:
        Pen - (0..255) number at that position is returned

   NOTE
    width must be non negative

   BUGS

   SEE ALSO
    WritePixel()  graphics/rastport.h

 graphics.library/XorRectRegion                 graphics.library/XorRectRegion

   NAME
       XorRectRegion -- Perform 2d XOR operation of rectangle
                       with region, leaving result in region

   SYNOPSIS
       status = XorRectRegion(region,rectangle)
         d0                     a0      a1

    BOOL XorRectRegion( struct Region *, struct Rectangle * );

   FUNCTION
    Add portions of rectangle to region if they are not in
    the region.
    Remove portions of rectangle from region if they are
    in the region.

   INPUTS
       region - pointer to Region structure
       rectangle - pointer to Rectangle structure

   RESULTS
    status - return TRUE if successful operation
         return FALSE if ran out of memory

   BUGS

   SEE ALSO
    OrRegionRegion() AndRegionRegion() graphics/regions.h

 graphics.library/XorRegionRegion             graphics.library/XorRegionRegion

   NAME
       XorRegionRegion -- Perform 2d XOR operation of one region
                       with second region, leaving result in second region

   SYNOPSIS
       status = XorRegionRegion(region1,region2)
         d0                        a0      a1

    BOOL XorRegionRegion( struct Region *, struct Region * );

   FUNCTION
    Join the regions together. If any part of region1 overlaps
    region2 then remove that from the new region.

   INPUTS
       region1      = pointer to Region structure
       region2      = pointer to Region structure

   RESULTS
    status - return TRUE if successful operation
         return FALSE if ran out of memory

   BUGS


Text_Autodocs/mathieeedoubtrans.doc

TABLE OF CONTENTS

mathieeedoubtrans.library/IEEEDPAcos
mathieeedoubtrans.library/IEEEDPAsin
mathieeedoubtrans.library/IEEEDPAtan
mathieeedoubtrans.library/IEEEDPCos
mathieeedoubtrans.library/IEEEDPCosh
mathieeedoubtrans.library/IEEEDPExp
mathieeedoubtrans.library/IEEEDPFieee
mathieeedoubtrans.library/IEEEDPLog
mathieeedoubtrans.library/IEEEDPLog10
mathieeedoubtrans.library/IEEEDPPow
mathieeedoubtrans.library/IEEEDPSin
mathieeedoubtrans.library/IEEEDPSincos
mathieeedoubtrans.library/IEEEDPSinh
mathieeedoubtrans.library/IEEEDPSqrt
mathieeedoubtrans.library/IEEEDPTan
mathieeedoubtrans.library/IEEEDPTanh
mathieeedoubtrans.library/IEEEDPTieee
 mathieeedoubtrans.library/IEEEDPAcos     mathieeedoubtrans.library/IEEEDPAcos

   NAME
    IEEEDPAcos -- compute the arc cosine of a number

   SYNOPSIS
      x   = IEEEDPAcos(  y  );
    d0/d1	           d0/d1

    double	x,y;

   FUNCTION
    Compute arc cosine of y in IEEE double precision

   INPUTS
    y - IEEE double precision floating point value

   RESULT
    x - IEEE double precision floating point value

   BUGS

   SEE ALSO
    IEEEDPCos(), IEEEDPAtan(), IEEEDPAsin()
 mathieeedoubtrans.library/IEEEDPAsin     mathieeedoubtrans.library/IEEEDPAsin

   NAME
    IEEEDPAsin -- compute the arcsine of a number

   SYNOPSIS
      x   = IEEEDPAsin(  y  );
    d0/d1	           d0/d1

    double	x,y;

   FUNCTION
    Compute the arc sine of y in IEEE double precision

   INPUTS
    y - IEEE double precision floating point value

   RESULT
    x - IEEE double precision floating point value

   BUGS

   SEE ALSO
    IEEEDPSin(), IEEEDPAtan(), IEEEDPAcos()
 mathieeedoubtrans.library/IEEEDPAtan     mathieeedoubtrans.library/IEEEDPAtan

   NAME
    IEEEDPAtan -- compute the arctangent of a floating point number

   SYNOPSIS
      x   = IEEEDPAtan(  y  );
    d0/d1		   d0/d1

    double	x,y;

   FUNCTION
    Compute arctangent of y in IEEE double precision

   INPUTS
    y - IEEE double precision floating point value

   RESULT
    x - IEEE double precision floating point value

   BUGS

   SEE ALSO
    IEEEDPTan(), IEEEDPAsin(), IEEEDPACos()
 mathieeedoubtrans.library/IEEEDPCos       mathieeedoubtrans.library/IEEEDPCos

   NAME
    IEEEDPCos -- compute the cosine of a floating point number

   SYNOPSIS
      x   = IEEEDPCos(  y  );
    d0/d1		   d0/d1

    double	x,y;

   FUNCTION
    Compute cosine of y in IEEE double precision

   INPUTS
    y - IEEE double precision floating point value

   RESULT
    x - IEEE double precision floating point value

   BUGS

   SEE ALSO
    IEEEDPAcos(), IEEEDPSin(), IEEEDPTan()
 mathieeedoubtrans.library/IEEEDPCosh     mathieeedoubtrans.library/IEEEDPCosh

   NAME
    IEEEDPCosh -- compute the hyperbolic cosine of a floating point number

   SYNOPSIS
      x   = IEEEDPCosh(  y  );
    d0/d1		   d0/d1

    double	x,y;

   FUNCTION
    Compute hyperbolic cosine of y in IEEE double precision

   INPUTS
    y - IEEE double precision floating point value

   RESULT
    x - IEEE double precision floating point value

   BUGS

   SEE ALSO
    IEEEDPSinh(), IEEEDPTanh()
 mathieeedoubtrans.library/IEEEDPExp       mathieeedoubtrans.library/IEEEDPExp

   NAME
    IEEEDPExp -- compute the exponential of e

   SYNOPSIS
      x   = IEEEDPExp(  y  );
    d0/d1	          d0/d1

    double	x,y;

   FUNCTION
    Compute e^y in IEEE double precision

   INPUTS
    y - IEEE double precision floating point value

   RESULT
    x - IEEE double precision floating point value

   BUGS

   SEE ALSO
    IEEEDPLog()
 mathieeedoubtrans.library/IEEEDPFieee   mathieeedoubtrans.library/IEEEDPFieee

   NAME
    IEEEDPFieee -- convert IEEE single to IEEE double

   SYNOPSIS
      x   = IEEEDPFieee(  y  );
    d0/d1	              d0

    float	y;
    double  x;

   FUNCTION
    Convert IEEE single precision number to IEEE double precision.

   INPUTS
    y - IEEE single precision floating point value

   RESULT
    x - IEEE double precision floating point value

   BUGS

   SEE ALSO
    IEEEDPTieee()
 mathieeedoubtrans.library/IEEEDPLog       mathieeedoubtrans.library/IEEEDPLog

   NAME
    IEEEDPLog -- compute the natural logarithm of a floating point number

   SYNOPSIS
      x   = IEEEDPLog(  y  );
    d0/d1	          d0/d1

    double	x,y;

   FUNCTION
    Compute ln(y) in IEEE double precision

   INPUTS
    y - IEEE double precision floating point value

   RESULT
    x - IEEE double precision floating point value

   BUGS

   SEE ALSO
    IEEEDPExp()
 mathieeedoubtrans.library/IEEEDPLog10   mathieeedoubtrans.library/IEEEDPLog10

   NAME
    IEEEDPLog10 -- compute logarithm base 10 of a number

   SYNOPSIS
      x   = IEEEDPLog10(  y  );
    d0/d1	            d0/d1

    double	x,y;

   FUNCTION
    Compute the logarithm base 10 of y in IEEE double precision

   INPUTS
    y - IEEE double precision floating point value

   RESULT
    x - IEEE double precision floating point value

   BUGS

   SEE ALSO
    IEEEDPLog()
 mathieeedoubtrans.library/IEEEDPPow       mathieeedoubtrans.library/IEEEDPPow

   NAME
    IEEEDPPow -- raise a number to another number power

   SYNOPSIS
      z   = IEEEDPPow(  x  ,  y  );
    d0/d1	          d2/d3 d0/d1

    double	x,y,z;

   FUNCTION
    Compute y^x in IEEE double precision

   INPUTS
    x - IEEE double precision floating point value
    y - IEEE double precision floating point value

   RESULT
    z - IEEE double precision floating point value

   BUGS

   SEE ALSO
 mathieeedoubtrans.library/IEEEDPSin       mathieeedoubtrans.library/IEEEDPSin

   NAME
    IEEEDPSin -- compute the sine of a floating point number

   SYNOPSIS
      x   = IEEEDPSin(  y  );
    d0/d1		  d0/d1

    double	x,y;

   FUNCTION
    Compute sine of y in IEEE double precision

   INPUTS
    y - IEEE double precision floating point value

   RESULT
    x - IEEE double precision floating point value

   BUGS

   SEE ALSO
    IEEEDPAsin(), IEEEDPTan(), IEEEDPCos()
 mathieeedoubtrans.library/IEEEDPSincos mathieeedoubtrans.library/IEEEDPSincos

   NAME
    IEEEDPSincos -- compute the arc tangent of a floating point number

   SYNOPSIS
      x   = IEEEDPSincos( z ,  y  );
    d0/d1		     a0  d0/d1

    double	x,y,*z;

   FUNCTION
    Compute sin and cosine of y in IEEE double precision.
    Store the cosine in *z. Return the sine of y.

   INPUTS
    y - IEEE double precision floating point value
    z - pointer to IEEE double precision floating point number

   RESULT
    x - IEEE double precision floating point value

   BUGS

   SEE ALSO
    IEEEDPSin(), IEEEDPCos()
 mathieeedoubtrans.library/IEEEDPSinh     mathieeedoubtrans.library/IEEEDPSinh

   NAME
    IEEEDPSinh -- compute the hyperbolic sine of a floating point number

   SYNOPSIS
      x   = IEEEDPSinh(  y  );
    d0/d1		   d0/d1

    double	x,y;

   FUNCTION
    Compute hyperbolic sine of y in IEEE double precision

   INPUTS
    y - IEEE double precision floating point value

   RESULT
    x - IEEE double precision floating point value

   BUGS

   SEE ALSO
    IEEEDPCosh, IEEEDPTanh
 mathieeedoubtrans.library/IEEEDPSqrt     mathieeedoubtrans.library/IEEEDPSqrt

   NAME
    IEEEDPSqrt -- compute the square root of a number

   SYNOPSIS
      x   = IEEEDPSqrt(  y  );
    d0/d1 	           d0/d1

    double	x,y;

   FUNCTION
    Compute square root of y in IEEE double precision

   INPUTS
    y - IEEE double precision floating point value

   RESULT
    x - IEEE double precision floating point value

   BUGS

   SEE ALSO
 mathieeedoubtrans.library/IEEEDPTan       mathieeedoubtrans.library/IEEEDPTan

   NAME
    IEEEDPTan -- compute the tangent of a floating point number

   SYNOPSIS
      x   = IEEEDPTan(  y  );
    d0/d1		  d0/d1

    double	x,y;

   FUNCTION
    Compute tangent of y in IEEE double precision

   INPUTS
    y - IEEE double precision floating point value

   RESULT
    x - IEEE double precision floating point value

   BUGS

   SEE ALSO
    IEEEDPAtan(), IEEEDPSin(), IEEEDPCos()
 mathieeedoubtrans.library/IEEEDPTanh     mathieeedoubtrans.library/IEEEDPTanh

   NAME
    IEEEDPTanh -- compute the hyperbolic tangent of a floating point number

   SYNOPSIS
      x   = IEEEDPTanh(  y  );
    d0/d1		   d0/d1

    double	x,y;

   FUNCTION
    Compute hyperbolic tangent of y in IEEE double precision

   INPUTS
    y - IEEE double precision floating point value

   RESULT
    x - IEEE double precision floating point value

   BUGS

   SEE ALSO
    IEEEDPSinh(), IEEEDPCosh()
 mathieeedoubtrans.library/IEEEDPTieee   mathieeedoubtrans.library/IEEEDPTieee

   NAME
    IEEEDPTieee -- convert IEEE double to IEEE single

   SYNOPSIS
      x   = IEEEDPTieee(  y  );
     d0	            d0/d1

    double	y;
    float   x;

   FUNCTION
    Convert IEEE double precision number to IEEE single precision.

   INPUTS
    y - IEEE double precision floating point value

   RESULT
    x - IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEEDPFieee()


Text_Autodocs/audio.doc

TABLE OF CONTENTS

audio.device/AbortIO
audio.device/ADCMD_ALLOCATE
audio.device/ADCMD_FINISH
audio.device/ADCMD_FREE
audio.device/ADCMD_LOCK
audio.device/ADCMD_PERVOL
audio.device/ADCMD_SETPREC
audio.device/ADCMD_WAITCYCLE
audio.device/BeginIO
audio.device/CloseDevice
audio.device/CMD_CLEAR
audio.device/CMD_FLUSH
audio.device/CMD_READ
audio.device/CMD_RESET
audio.device/CMD_START
audio.device/CMD_STOP
audio.device/CMD_UPDATE
audio.device/CMD_WRITE
audio.device/Expunge
audio.device/OpenDevice
 audio.device/AbortIO                                     audio.device/AbortIO

   NAME
       AbortIO - abort a device command

   SYNOPSIS
       AbortIO(iORequest);
                   A1

   FUNCTION
       AbortIO tries to abort a device command.  It is allowed to be
       unsuccessful.  If the Abort is successful, the io_Error field of the
       iORequest contains an indication that IO was aborted.

   INPUTS
       iORequest -- pointer to the I/O Request for the command to abort

 audio.device/ADCMD_ALLOCATE                       audio.device/ADCMD_ALLOCATE
       ADCMD_ALLOCATE -- allocate a set of audio channels

   FUNCTION
       ADCMD_ALLOCATE is a command that allocates multiple audio channels.
       ADCMD_ALLOCATE takes an array of possible channel combinations
       (ioa_Data) and an allocation precedence (ln_Pri) and tries to allocate
       one of the combinations of channels.

       If the channel combination array is zero length (ioa_Length), the
       allocation succeeds; otherwise, ADCMD_ALLOCATE checks each
       combination, one at a time, in the specified order, to find one
       combination that does not require ADCMD_ALLOCATE to steal allocated
       channels.

       If it must steal allocated channels, it uses the channel combination
       that steals the lowest precedence channels.

       ADCMD_ALLOCATE cannot steal a channel of equal or greater precedence
       than the allocation precedence (ln_Pri).

       If it fails to allocate any channel combination and the no-wait flag
       (ADIOF_NOWAIT) is set ADCMD_ALLOCATE returns a zero in the unit field
       of the I/O request (io_Unit) and an error (IOERR_ALLOCFAILED).  If the
       no-wait flag is clear, it places the I/O request in a list that tries
       to allocate again whenever ADCMD_FREE frees channels or ADCMD_SETPREC
       lowers the channels' precedences.

       If the allocation is successful, ADCMD_ALLOCATE checks if any channels
       are locked (ADCMD_LOCK) and if so, replies (ReplyMsg) the lock I/O
       request with an error (ADIOERR_CHANNELSTOLEN). Then it places the
       allocation I/O request in a list waiting for the locked channels to be
       freed.  When all the allocated channels are un-locked, ADCMD_ALLOCATE:
         . resets (CMD_RESET) the allocated channels,
         . generates a new allocation key (ioa_AllocKey), if it is zero,
         . copies the allocation key into each of the allocated channels
         . copies the allocation precedence into each of the allocated
           channels, and
         . copies the channel bit map into the unit field of the I/O request.

       If channels are allocated with a non-zero allocation key,
       ADCMD_ALLOCATE allocates with that same key; otherwise, it generates a
       new and unique key.

       ADCMD_ALLOCATE is synchronous:
         . if the allocation succeeds and there are no locked channels to be
           stolen, or
         . if the allocation fails and the no-wait flag is set.

       In either case, ADCMD_ALLOCATE only replies (mn_ReplyPort) if the
       quick flag (IOF_QUICK) is clear; otherwise, the allocation is
       asynchronous, so it clears the quick flag and replies the I/O request
       after the allocation is finished.  If channels are stolen, all audio
       device commands return an error (IOERR_NOALLOCATION) when the former
       user tries to use them again.  Do not use ADCMD_ALLOCATE in interrupt
       code.

       If you decide to store directly to the audio hardware registers, you
       must either lock the channels you've allocated, or set the precedence
       to maximum (ADALLOC_MAXPREC) to prevent the channels from being
       stolen.

       Under all circumstances, unless channels are stolen, you must free
       (ADCMD_FREE) all allocated channels when you are finished using them.

   INPUTS
       ln_Pri      - allocation precedence (-128 thru 127)
       mn_ReplyPort- pointer to message port that receives I/O request after
                     the allocation completes is asynchronous or quick flag
                     (ADIOF_QUICK) is set
       io_Device   - pointer to device node, must be set by (or copied from
                     I/O block set by) OpenDevice function
       io_Command  - command number for ADCMD_ALLOCATE
       io_Flags    - flags, must be cleared if not used:
                     IOF_QUICK   - (CLEAR) reply I/O request
                                   (SET) only reply I/O request only if
                                         asynchronous (see above text)
                     ADIOF_NOWAIT- (CLEAR) if allocation fails, wait till is
                                           succeeds
                                   (SET) if allocation fails, return error
                                         (ADIOERR_ALLOCFAILED)
       ioa_AllocKey- allocation key, zero to generate new key; otherwise,
                     it must be set by (or copied from I/O block set by)
                     OpenDevice function or previous ADCMD_ALLOCATE command
       ioa_Data    - pointer to channel combination options (byte array, bits
                     0 thru 3 correspond to channels 0 thru 3)
       ioa_Length  - length of the channel combination option array
                     (0 thru 16, 0 always succeeds)

   OUTPUTS
       io_Unit     - bit map of successfully allocated channels (bits 0 thru
                     3 correspond to channels 0 thru 3)
       io_Flags    - IOF_QUICK flag cleared if asynchronous (see above text)
       io_Error    - error number:
                     0                   - no error
                     ADIOERR_ALLOCFAILED - allocation failed
       ioa_AllocKey- allocation key, set to a unique number if passed a zero
                     and command succeeds

 audio.device/ADCMD_FINISH                           audio.device/ADCMD_FINISH

   NAME
       ADCMD_FINISH -- abort writes in progress to audio channels

   FUNCTION
       ADCMD_FINISH is a command for multiple audio channels.  For each
       selected channel (io_Unit), if the allocation key (ioa_AllocKey) is
       correct and there is a write (CMD_WRITE)in progress, ADCMD_FINISH
       aborts the current write immediately or at the end of the current
       cycle depending on the sync flag (ADIOF_SYNCCYCLE).  If the allocation
       key is incorrect ADCMD_FINISH returns an error (ADIOERR_NOALLOCATION).
       ADCMD_FINISH is synchronous and only replies (mn_ReplyPort) if the
       quick flag (IOF_QUICK) is clear.  Do not use ADCMD_FINISH in interrupt
       code at interrupt level 5 or higher.

   INPUTS
       mn_ReplyPort- pointer to message port that receives I/O request
                     if the quick flag (IOF_QUICK) is clear
       io_Device   - pointer to device node, must be set by (or copied from
                     I/O block set by) OpenDevice function
       io_Unit     - bit map of channels to finish (bits 0 thru 3 correspond
                     to channels 0 thru 3)
       io_Command  - command number for ADCMD_FINISH
       io_Flags    - flags, must be cleared if not used:
                     IOF_QUICK      - (CLEAR) reply I/O request
                     ADIOF_SYNCCYCLE- (CLEAR) finish immediately
                                      (SET) finish at the end of current
                                            cycle

       ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                     set by) OpenDevice function or ADCMD_ALLOCATE command

   OUTPUTS
       io_Unit     - bit map of channels successfully finished (bits 0 thru 3
                     correspond to channels 0 thru 3)
       io_Error    - error number:
                     0                    - no error
                     ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                            does not match key for channel

 audio.device/ADCMD_FREE                               audio.device/ADCMD_FREE

   NAME
       ADCMD_FREE -- free audio channels for allocation

   FUNCTION
       ADCMD_FREE is a command for multiple audio channels.  For each
       selected channel (io_Unit), if the allocation key (ioa_AllocKey) is
       correct, ADCMD_FREE does the following:
         . restores the channel to a known state (CMD_RESET),
         . changes the channels allocation key, and
         . makes the channel available for re-allocation.
         . If the channel is locked (ADCMD_LOCK) ADCMD_FREE unlocks it and
           clears the bit for the channel (io_Unit) in the lock I/O request.
           If the lock I/O request has no channel bits set ADCMD_FREE replies
           the lock I/O request, and
         . checks if there are allocation requests (ADCMD_ALLOCATE) waiting
           for the channel.

       Otherwise, ADCMD_FREE returns an error (ADIOERR_NOALLOCATION).
       ADCMD_FREE is synchronous and only replies (mn_ReplyPort) if the quick
       flag (IOF_QUICK) is clear.  Do not use ADCMD_FREE in interrupt code.

   INPUTS
       mn_ReplyPort- pointer to message port that receives I/O request
                     if the quick flag (IOF_QUICK) is clear
       io_Device   - pointer to device node, must be set by (or copied from
                     I/O block set by) OpenDevice function
       io_Unit     - bit map of channels to free (bits 0 thru 3 correspond to
                     channels 0 thru 3)
       io_Command  - command number for ADCMD_FREE
       io_Flags    - flags, must be cleared if not used:
                     IOF_QUICK - (CLEAR) reply I/O request
       ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                     set by) OpenDevice function or ADCMD_ALLOCATE command

   OUTPUTS
       io_Unit     - bit map of channels successfully freed (bits 0 thru 3
                     correspond to channels 0 thru 3)
       io_Error    - error number:
                     0                    - no error
                     ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                            does not match key for channel

 audio.device/ADCMD_LOCK                               audio.device/ADCMD_LOCK

   NAME
       ADCMD_LOCK -- prevent audio channels from being stolen

   FUNCTION
       ADCMD_LOCK is a command for multiple audio channels.  For each
       selected channel (io_Unit), if the allocation key (ioa_AllocKey) is
       correct, ADCMD_LOCK locks the channel, preventing subsequent
       allocations (ADCMD_ALLOCATE or OpenDevice) from stealing the channel.
       Otherwise, ADCMD_LOCK returns an error (ADIOERR_NOALLOCATION) and will
       not lock any channels.

       Unlike setting the precedence (ADCMD_SETPREC, ADCMD_ALLOCATE or
       OpenDevice) to maximum (ADALLOC_MAXPREC) which would cause all
       subsequent allocations to fail, ADCMD_LOCK causes all higher
       precedence allocations, even no-wait (ADIOF_NOWAIT) allocations, to
       wait until the channels are un-locked.

       Locked channels can only be unlocked by freeing them (ADCMD_FREE),
       which clears the channel select bits (io_Unit).  ADCMD_LOCK does not
       reply the I/O request (mn_ReplyPort) until all the channels it locks
       are freed, unless a higher precedence allocation attempts to steal one
       the locked channels. If a steal occurs, ADCMD_LOCK replies and returns
       an error (ADIOERR_CHANNELSTOLEN).  If the lock is replied
       (mn_ReplyPort) with this error, the channels should be freed as soon
       as possible.  To avoid a possible deadlock, never make the freeing of
       stolen channels dependent on another allocations completion.

       ADCMD_LOCK is only asynchronous if the allocation key is correct, in
       which case it clears the quick flag (IOF_QUICK); otherwise, it is
       synchronous and only replies if the quick flag (IOF_QUICK) is clear.
       Do not use ADCMD_LOCK in interrupt code.

   INPUTS
       mn_ReplyPort- pointer to message port that receives I/O request
                     if the quick flag (IOF_QUICK) is clear
       io_Device   - pointer to device node, must be set by (or copied from
                     I/O block set by) OpenDevice function
       io_Unit     - bit map of channels to lock (bits 0 thru 3 correspond to
                     channels 0 thru 3)
       io_Command  - command number for ADCMD_LOCK
       io_Flags    - flags, must be cleared
       ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                     set by) OpenDevice function or ADCMD_ALLOCATE command

   OUTPUTS
       io_Unit     - bit map of successfully locked channels (bits 0 thru 3
                     correspond to channels 0 thru 3) not freed (ADCMD_FREE)
       io_Flags    - IOF_QUICK flag cleared if the allocation key is correct
                     (no ADIOERR_NOALLOCATION error)
       io_Error    - error number:
                     0                    - no error
                     ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                            does not match key for channel
                     ADIOERR_CHANNELSTOLEN- allocation attempting to steal
                                            locked channel

 audio.device/ADCMD_PERVOL                           audio.device/ADCMD_PERVOL

   NAME
       ADCMD_PERVOL -- change the period and volume for writes in progress to
                       audio channels

   FUNCTION
       ADCMD_PERVOL is a command for multiple audio channels.  For each
       selected channel (io_Unit), if the allocation key (ioa_AllocKey) is
       correct and there is a write (CMD_WRITE) in progress, ADCMD_PERVOL
       loads a new volume and period immediately or at the end of the current
       cycle depending on the sync flag (ADIOF_SYNCCYCLE).  If the allocation
       key in incorrect, ADCMD_PERVOL returns an error
       (ADIOERR_NOALLOCATION).  ADCMD_PERVOL is synchronous and only replies
       (mn_ReplyPort) if the quick flag (IOF_QUICK) is clear.  Do not use
       ADCMD_PERVOL in interrupt code at interrupt level 5 or higher.

   INPUTS
       mn_ReplyPort- pointer to message port that receives I/O request
                     if the quick flag (IOF_QUICK) is clear
       io_Device   - pointer to device node, must be set by (or copied from
                     I/O block set by) OpenDevice function
       io_Unit     - bit map of channels to load period and volume (bits 0
                     thru 3 correspond to channels 0 thru 3)
       io_Command  - command number for ADCMD_PERVOL
       io_Flags    - flags, must be cleared if not used:
                     IOF_QUICK      - (CLEAR) reply I/O request
                     ADIOF_SYNCCYCLE- (CLEAR) load period and volume
                                              immediately
                                      (SET) load period and volume at the end
                                            of the current cycle
       ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                     set by) OpenDevice function or ADCMD_ALLOCATE command
       ioa_Period  - new sample period in 279.365 ns increments (124 thru
                     65536, anti-aliasing filter works below 300 to 500
                     depending on waveform)
       ioa_Volume  - new volume (0 thru 64, linear)

   OUTPUTS
       io_Unit     - bit map of channels that successfully loaded period and
                     volume (bits 0 thru 3 correspond to channels 0 thru 3)
       io_Error    - error number:
                     0                    - no error
                     ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                            does not match key for channel

 audio.device/ADCMD_SETPREC                         audio.device/ADCMD_SETPREC

   NAME
       ADCMD_SETPREC -- set the allocation precedence for audio channels

   FUNCTION
       ADCMD_SETPREC is a command for multiple audio channels.  For each
       selected channel (io_Unit), if the allocation key (ioa_AllocKey) is
       correct, ADCMD_SETPREC sets the allocation precedence to a new value
       (ln_Pri) and checks if there are allocation requests (ADCMD_ALLOCATE)
       waiting for the channel which now have higher precedence; otherwise,
       ADCMD_SETPREC returns an error (ADIOERR_NOALLOCATION).  ADCMD_SETPREC
       is synchronous and only replies (mn_ReplyPort) if the quick flag
       (IOF_QUICK) is clear.  Do not use ADCMD_SETPREC in interrupt code.

   INPUTS
       ln_Pri      - new allocation precedence (-128 thru 127)
       mn_ReplyPort- pointer to message port that receives I/O request
                     if the quick flag (IOF_QUICK) is clear
       io_Device   - pointer to device node, must be set by (or copied from
                     I/O block set by) OpenDevice function
       io_Unit     - bit map of channels to set precedence (bits 0 thru 3
                     correspond to channels 0 thru 3)
       io_Command  - command number for ADCMD_SETPREC
       io_Flags    - flags, must be cleared if not used:
                     IOF_QUICK - (CLEAR) reply I/O request
       ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                     set by) OpenDevice function or ADCMD_ALLOCATE command

   OUTPUTS
       io_Unit     - bit map of channels that successfully set precedence
                     (bits 0 thru 3 correspond to channels 0 thru 3)
       io_Error    - error number:
                     0                    - no error
                     ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                            does not match key for channel

 audio.device/ADCMD_WAITCYCLE                     audio.device/ADCMD_WAITCYCLE

   NAME
       ADCMD_WAITCYCLE -- wait for an audio channel to complete the current
                          cycle of a write

   FUNCTION
       ADCMD_WAITCYCLE is a command for a single audio channel (io_Unit).
       If the allocation key (ioa_AllocKey) is correct and there is a write
       (CMD_WRITE) in progress on selected channel, ADCMD_WAITCYCLE does not
       reply (mn_ReplyPort) until the end of the current cycle.  If there is
       no write is progress, ADCMD_WAITCYCLE replies immediately.  If the
       allocation key is incorrect, ADCMD_WAITCYCLE returns an error
       (ADIOERR_NOALLOCATION).  ADCMD_WAITCYCLE returns an error
       (IOERR_ABORTED) if it is canceled (AbortIO) or the channel is stolen
       (ADCMD_ALLOCATE).  ADCMD_WAITCYCLE is only asynchronous if it is
       waiting for a cycle to complete, in which case it clears the quick
       flag (IOF_QUICK); otherwise, it is synchronous and only replies if the
       quick flag (IOF_QUICK) is clear.  Do not use ADCMD_WAITCYCLE in
       interrupt code at interrupt level 5 or higher.

   INPUTS
       mn_ReplyPort- pointer to message port that receives I/O request, if
                     the quick flag (IOF_QUICK) is clear, or if a write is in
                     progress on the selected channel and a cycle has
                     completed
       io_Device   - pointer to device node, must be set by (or copied from
                     I/O block set by) OpenDevice function
       io_Unit     - bit map of channel to wait for cycle (bits 0 thru 3
                     correspond to channels 0 thru 3), if more then one bit
                     is set lowest bit number channel is used
       io_Command  - command number for CMD_WAITCYCLE
       io_Flags    - flags, must be cleared if not used:
                     IOF_QUICK - (CLEAR) reply I/O request
                                 (SET) only reply I/O request if a write is
                                       in progress on the selected channel
                                       and a cycle has completed
       ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                     set by) OpenDevice function or ADCMD_ALLOCATE command

   OUTPUTS
       io_Unit     - bit map of channel that successfully waited for cycle
                     (bits 0 thru 3 correspond to channels 0 thru 3)
       io_Flags    - IOF_QUICK flag cleared if a write is in progress on the
                     selected channel
       io_Error    - error number:
                     0                    - no error
                     IOERR_ABORTED        - canceled (AbortIO) or channel
                                            stolen
                     ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                            does not match key for channel

 audio.device/BeginIO                                     audio.device/BeginIO

   NAME
       BeginIO - dispatch a device command

   SYNOPSIS
       BeginIO(iORequest);
                   A1

   FUNCTION
       BeginIO has the responsibility of dispatching all device commands.
       Immediate commands are always called directly, and all other commands
       are queued to make them single threaded.

   INPUTS
       iORequest -- pointer to the I/O Request for this command

 audio.device/CloseDevice                             audio.device/CloseDevice

   NAME
       CloseDevice - terminate access to the audio device

   SYNOPSIS
       CloseDevice(iORequest);
                       A1

   FUNCTION
       The CloseDevice routine notifies the audio device that it will no
       longer be used.  It takes an I/O audio request block (IOAudio) and
       clears the device pointer (io_Device).  If there are any channels
       allocated with the same allocation key (ioa_AllocKey), CloseDevice
       frees (ADCMD_FREE) them. CloseDevice decrements the open count, and if
       it falls to zero and an expunge (Expunge) is pending, the device is
       expunged.

   INPUTS
       iORequest   - pointer to audio request block (struct IOAudio)
               io_Device   - pointer to device node, must be set by (or
                             copied from I/O block set by) open (OpenDevice)
               io_Unit     - bit map of channels to free (ADCMD_FREE) (bits 0
                             thru 3 correspond to channels 0 thru 3)
               ioa_AllocKey- allocation key, used to free channels

   OUTPUTS
       iORequest - pointer to audio request block (struct IOAudio)
               io_Device   - set to -1
               io_Unit     - set to zero

 audio.device/CMD_CLEAR                                 audio.device/CMD_CLEAR

   NAME
       CMD_CLEAR -- throw away internal caches

   FUNCTION
       CMD_CLEAR is a standard command for multiple audio channels.  For each
       selected channel (io_Unit), if the allocation key (ioa_AllocKey) is
       correct, CMD_CLEAR does nothing; otherwise, CMD_CLEAR returns an error
       (ADIOERR_NOALLOCATION).  CMD_CLEAR is synchronous and only replies
       (mn_ReplyPort) if the quick flag (IOF_QUICK) is clear.

   INPUTS
       mn_ReplyPort- pointer to message port that receives I/O request after
                     if the quick flag (IOF_QUICK) is clear
       io_Device   - pointer to device node, must be set by (or copied from
                     I/O block set by) OpenDevice function
       io_Unit     - bit map of channels to clear (bits 0 thru 3 correspond
                     to channels 0 thru 3)
       io_Command  - command number for CMD_CLEAR
       io_Flags    - flags, must be cleared if not used:
                     IOF_QUICK - (CLEAR) reply I/O request
       ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                     set by) OpenDevice function or ADCMD_ALLOCATE command

   OUTPUTS
       io_Unit     - bit map of channels successfully cleared (bits 0 thru 3
                     correspond to channels 0 thru 3)
       io_Error    - error number:
                     0                    - no error
                     ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                            does not match key for channel

 audio.device/CMD_FLUSH                                 audio.device/CMD_FLUSH

   NAME
       CMD_FLUSH -- cancel all pending I/O

   FUNCTION
       CMD_FLUSH is a standard command for multiple audio channels.  For each
       selected channel (io_Unit), if the allocation key (ioa_AllocKey) is
       correct, CMD_FLUSH aborts all writes (CMD_WRITE) in progress or queued
       and any I/O requests waiting to synchronize with the end of the cycle
       (ADCMD_WAITCYCLE); otherwise, CMD_FLUSH returns an error
       (ADIOERR_NOALLOCATION).  CMD_FLUSH is synchronous and only replies
       (mn_ReplyPort) if the quick flag (IOF_QUICK) is clear.  Do not use
       CMD_FLUSH in interrupt code at interrupt level 5 or higher.

   INPUTS
       mn_ReplyPort- pointer to message port that receives I/O request
                     if the quick flag (IOF_QUICK) is clear
       io_Device   - pointer to device node, must be set by (or copied from
                     I/O block set by) OpenDevice function
       io_Unit     - bit map of channels to flush (bits 0 thru 3 correspond
                     to channels 0 thru 3)
       io_Command  - command number for CMD_FLUSH
       io_Flags    - flags, must be cleared if not used:
                     IOF_QUICK - (CLEAR) reply I/O request
       ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                     set by) OpenDevice function or ADCMD_ALLOCATE command

   OUTPUTS
       io_Unit     - bit map of channels successfully flushed (bits 0 thru 3
                     correspond to channels 0 thru 3)
       io_Error    - error number:
                     0                    - no error
                     ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                            does not match key for channel

 audio.device/CMD_READ                                   audio.device/CMD_READ

   NAME
       CMD_READ -- normal I/O entry point

   FUNCTION
       CMD_READ is a standard command for a single audio channel (io_Unit).
       If the allocation key (ioa_AllocKey) is correct, CMD_READ returns a
       pointer (io_Data) to the I/O block currently writing (CMD_WRITE) on
       the selected channel; otherwise, CMD_READ returns an error
       (ADIOERR_NOALLOCATION).  If there is no write in progress, CMD_READ
       returns zero.  CMD_READ is synchronous and only replies (mn_ReplyPort)
       if the quick bit (IOF_QUICK) is clear.

   INPUTS
       mn_ReplyPort- pointer to message port that receives I/O request after
                     if the quick flag (IOF_QUICK) is clear
       io_Device   - pointer to device node, must be set by (or copied from
                     I/O block set by) OpenDevice function
       io_Unit     - bit map of channel to read (bit 0 thru 3 corresponds to
                     channel 0 thru 3), if more then one bit is set lowest
                     bit number channel read
       io_Command  - command number for CMD_READ
       io_Flags    - flags, must be cleared if not used:
                     IOF_QUICK - (CLEAR) reply I/O request
       ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                     set by) OpenDevice function or ADCMD_ALLOCATE command

   OUTPUTS
       io_Unit     - bit map of channel successfully read (bit 0 thru 3
                     corresponds to channel 0 thru 3)
       io_Error    - error number:
                     0                    - no error
                     ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                            does not match key for channel
       ioa_Data    - pointer to I/O block for current write, zero if none is
                     progress

 audio.device/CMD_RESET                                 audio.device/CMD_RESET

   NAME
       CMD_RESET -- restore device to a known state

   FUNCTION
       CMD_RESET is a standard command for multiple audio channels.  For each
       selected channel (io_Unit), if the allocation key (ioa_AllocKey) is
       correct, CMD_RESET:
         . clears the hardware audio registers and attach bits,
         . sets the audio interrupt vector,
         . cancels all pending I/O (CMD_FLUSH), and
         . un-stops the channel if it is stopped (CMD_STOP),

       Otherwise, CMD_RESET returns an error (ADIOERR_NOALLOCATION).
       CMD_RESET is synchronous and only replies (mn_ReplyPort) if the quick
       flag (IOF_QUICK) is clear.  Do not use CMD_RESET in interrupt code at
       interrupt level 5 or higher.

   INPUTS
       mn_ReplyPort- pointer to message port that receives I/O request
                     if the quick flag (IOF_QUICK) is clear
       io_Device   - pointer to device node, must be set by (or copied from
                     I/O block set by) OpenDevice function
       io_Unit     - bit map of channels to reset (bits 0 thru 3 correspond
                     to channels 0 thru 3)
       io_Command  - command number for CMD_RESET
       io_Flags    - flags, must be cleared if not used:
                     IOF_QUICK - (CLEAR) reply I/O request
       ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                     set by) OpenDevice function or ADCMD_ALLOCATE command

   OUTPUTS
       io_Unit     - bit map of channels to successfully reset (bits 0 thru 3
                     correspond to channels 0 thru 3)
       io_Error    - error number:
                     0                    - no error
                     ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                            does not match key for channel

 audio.device/CMD_START                                 audio.device/CMD_START

   NAME
       CMD_START -- start device processing (like ^Q)

   FUNCTION
       CMD_START is a standard command for multiple audio channels.  For each
       selected channel (io_Unit), if the allocation key (ioa_AllocKey) is
       correct and the channel was previously stopped (CMD_STOP), CMP_START
       immediately starts all writes (CMD_WRITE) to the channel.  If the
       allocation key is incorrect, CMD_START returns an error
       (ADIOERR_NOALLOCATION).  CMD_START starts multiple channels
       simultaneously to minimize distortion if the channels are playing the
       same waveform and their outputs are mixed. CMD_START is synchronous an
d
       only replies (mn_ReplyPort) if the quick flag (IOF_QUICK) is clear.  D
o
       not use CMD_START in interrupt code at interrupt level 5 or higher.

   INPUTS
       mn_ReplyPort- pointer to message port that receives I/O request after
                     if the quick flag (IOF_QUICK) is clear
       io_Device   - pointer to device node, must be set by (or copied from
                     I/O block set by) OpenDevice function
       io_Unit     - bit map of channels to start (bits 0 thru 3 correspond
                     to channels 0 thru 3)
       io_Command  - command number for CMD_START
       io_Flags    - flags, must be cleared if not used:
                     IOF_QUICK - (CLEAR) reply I/O request
       ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                     set by) OpenDevice function or ADCMD_ALLOCATE command

   OUTPUTS
       io_Unit     - bit map of channels successfully started (bits 0 thru 3
                     correspond to channels 0 thru 3)
       io_Error    - error number:
                     0                    - no error
                     ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                            does not match key for channel

 audio.device/CMD_STOP                                   audio.device/CMD_STOP

   NAME
       CMD_STOP -- stop device processing (like ^S)

   FUNCTION
       CMD_STOP is a standard command for multiple audio channels.  For each
       selected channel (io_Unit), if the allocation key (ioa_AllocKey) is
       correct, CMD_STOP immediately stops any writes (CMD_WRITE) in
       progress; otherwise, CMD_STOP returns an error (ADIOERR_NOALLOCATION).
       CMD_WRITE queues up writes to a stopped channel until CMD_START starts
       the channel or CMD_RESET resets the channel. CMD_STOP is synchronous
       and only replies (mn_ReplyPort) if the quick flag (IOF_QUICK) is
       clear.  Do not use CMD_STOP in interrupt code at interrupt level 5 or
       higher.

   INPUTS
       mn_ReplyPort- pointer to message port that receives I/O request after
                     if the quick flag (IOF_QUICK) is clear
       io_Device   - pointer to device node, must be set by (or copied from
                     I/O block set by) OpenDevice function
       io_Unit     - bit map of channels to stop (bits 0 thru 3 correspond to
                     channels 0 thru 3)
       io_Command  - command number for CMD_STOP
       io_Flags    - flags, must be cleared if not used:
                     IOF_QUICK - (CLEAR) reply I/O request
       ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                     set by) OpenDevice function or ADCMD_ALLOCATE command

   OUTPUTS
       io_Unit     - bit map of channels successfully stopped (bits 0 thru 3
                     correspond to channels 0 thru 3)
       io_Error    - error number:
                     0                    - no error
                     ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                            does not match key for channel

 audio.device/CMD_UPDATE                               audio.device/CMD_UPDATE

   NAME
       CMD_UPDATE -- force dirty buffers out

   FUNCTION
       CMD_UPDATE is a standard command for multiple audio channels.  For
       each selected channel (io_Unit), if the allocation key (ioa_AllocKey)
       is correct, CMD_UPDATE does nothing; otherwise, CMD_UPDATE returns an
       error (ADIOERR_NOALLOCATION).  CMD_UPDATE is synchronous and only
       replies (mn_ReplyPort) if the quick flag (IOF_QUICK) is clear.

   INPUTS
       mn_ReplyPort- pointer to message port that receives I/O request after
                     if the quick flag (IOF_QUICK) is clear
       io_Device   - pointer to device node, must be set by (or copied from
                     I/O block set by) OpenDevice function
       io_Unit     - bit map of channels to update (bits 0 thru 3 correspond
                     to channels 0 thru 3)
       io_Command  - command number for CMD_UPDATE
       io_Flags    - flags, must be cleared if not used:
                     IOF_QUICK - (CLEAR) reply I/O request
       ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                     set by) OpenDevice function or ADCMD_ALLOCATE command

   OUTPUTS
       io_Unit     - bit map of channels successfully updated (bits 0 thru 3
                     correspond to channels 0 thru 3)
       io_Error    - error number:
                     0                    - no error
                     ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                            does not match key for channel

 audio.device/CMD_WRITE                                 audio.device/CMD_WRITE

   NAME
       CMD_WRITE -- normal I/O entry point

   FUNCTION
       CMD_WRITE is a standard command for a single audio channel (io_Unit).
       If the allocation key (ioa_AllocKey) is correct, CMD_WRITE plays a
       sound using the selected channel; otherwise, it returns an error
       (ADIOERR_NOALLOCATION).  CMD_WRITE queues up requests if there is
       another write in progress or if the channel is stopped (CMD_STOP).
       When the write actually starts; if the ADIOF_PERVOL flag is set,
       CMD_WRITE loads volume (ioa_Volume) and period (ioa_Period), and if
       the ADIOF_WRITEMESSAGE flag is set, CMD_WRITE replies the write
       message (ioa_WriteMsg).  CMD_WRITE returns an error (IOERR_ABORTED) if
       it is canceled (AbortIO) or the channel is stolen (ADCMD_ALLOCATE).
       CMD_WRITE is only asynchronous if there is no error, in which case it
       clears the quick flag (IOF_QUICK) and replies the I/O request
       (mn_ReplyPort) after it finishes writting; otherwise, it is synchronou
s
       and only replies if the quick flag (IOF_QUICK) is clear.  Do not use
       CMD_WRITE in interrupt code at interrupt level 5 or higher.

   INPUTS
       mn_ReplyPort- pointer to message port that receives I/O request after
                     the write completes
       io_Device   - pointer to device node, must be set by (or copied from
                     I/O block set by) OpenDevice function
       io_Unit     - bit map of channel to write (bit 0 thru 3 corresponds to
                     channel 0 thru 3), if more then one bit is set lowest
                     bit number channel is written
       io_Command  - command number for CMD_WRITE
       io_Flags    - flags, must be cleared if not used:
                     ADIOF_PERVOL       - (SET) load volume and period
                     ADIOF_WRITEMESSAGE - (SET) reply message at write start
       ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                     set by) OpenDevice function or ADCMD_ALLOCATE command
       ioa_Data    - pointer to waveform array (signed bytes (-128 thru 127)
                     in custom chip addressable ram and word aligned)
       ioa_Length  - length of the wave array in bytes (2 thru 131072, must
                     be even number)
       ioa_Period  - sample period in 279.365 ns increments (124 thru 65536,
                     anti-aliasing filter works below 300 to 500 depending on
                     waveform), if enabled by ADIOF_PERVOL
       ioa_Volume  - volume (0 thru 64, linear), if enabled by ADIOF_PERVOL
       ioa_Cycles  - number of times to repeat array (0 thru 65535, 0 for
                     infinite)
       ioa_WriteMsg- message replied at start of write,  if enabled by
                     ADIOF_WRITEMESSAGE

   OUTPUTS
       io_Unit     - bit map of channel successfully written (bit 0 thru 3
                     corresponds to channel 0 thru 3)
       io_Flags    - IOF_QUICK flag cleared if there is no error
       io_Error    - error number:
                     0                    - no error
                     IOERR_ABORTED        - canceled (AbortIO) or channel
                                            stolen
                     ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                            does not match key for channel

   BUGS
       If CMD_WRITE starts the write immediately after stopping a previous
       write, you must set the ADIOF_PERVOL flag or else the new data pointer
       (ioa_Data) and length (ioa_Length) may not be loaded.

 audio.device/Expunge                                     audio.device/Expunge

   NAME
       EXPUNGE - indicate a desire to remove the Audio device

   FUNCTION
       The Expunge routine is called when a user issues a RemDevice call.  By
       the time it is called, the device has already been removed from the
       device list, so no new opens will succeed.  The existence of any other
       users of the device, as determined by the device open count being
       non-zero, will cause the Expunge to be deferred.  When the device is
       not in use, or no longer in use, the Expunge is actually performed.

 audio.device/OpenDevice                               audio.device/OpenDevice

   NAME
       OpenDevice - open the audio device

   SYNOPSIS
       error = OpenDevice("audio.device", unitNumber, iORequest, flags);

   FUNCTION
       The OpenDevice routine grants access to the audio device.  It takes an
       I/O audio request block (iORequest) and if it can successfully open
       the audio device, it loads the device pointer (io_Device) and the
       allocation key (ioa_AllocKey); otherwise, it returns an error
       (IOERR_OPENFAIL).  OpenDevice increments the open count keeping the
       device from being expunged (Expunge).  If the length (ioa_Length) is
       non-zero, OpenDevice tries to allocate (ADCMD_ALLOCATE) audio channels
       from a array of channel combination options (ioa_Data). If the
       allocation succeeds, the allocated channel combination is loaded into
       the unit field (ioa_Unit); otherwise, OpenDevice returns an error
       (ADIOERR_ALLOCFAILED).  OpenDevice does not wait for allocation to
       succeed and closes (CloseDevice) the audio device if it fails.  To
       allocate channels, OpenDevice also requires a properly initialized
       reply port (mn_ReplyPort) with an allocated signal bit.

   INPUTS
       unitNumber- not used
       iORequest - pointer to audio request block (struct IOAudio)
               ln_Pri      - allocation precedence (-128 thru 127), only
                             necessary for allocation (non-zero length)
               mn_ReplyPort- pointer to message port for allocation, only
                             necessary for allocation (non-zero length)
               ioa_AllocKey- allocation key; zero to generate new key.
                             Otherwise, it must be set by (or copied from I/O
                             block that is set by) previous OpenDevice
                             function or ADCMD_ALLOCATE command (non-zero
                             length)
               ioa_Data    - pointer to channel combination options (byte
                             array, bits 0 thru 3 correspond to channels 0
                             thru 3), only necessary for allocation (non-zero
                             length)
               ioa_Length  - length of the channel combination option array
                             (0 thru 16), zero for no allocation
       flags     - not used

   OUTPUTS
       iORequest - pointer to audio request block (struct IOAudio)
               io_Device   - pointer to device node if OpenDevice succeeds,
                             otherwise -1
               io_Unit     - bit map of successfully allocated channels (bits
                             0 thru 3 correspond to channels 0 thru 3)
               io_Error    - error number:
                             0                   - no error
                             IOERR_OPENFAIL      - open failed
                             ADIOERR_ALLOCFAILED - allocation failed, no open
               ioa_AllocKey- allocation key, set to a unique number if passed
                             a zero and OpenDevice succeeds
       error     - copy of io_Error


Text_Autodocs/gameport.doc

TABLE OF CONTENTS

gameport.device/GPD_ASKCTYPE
gameport.device/GPD_ASKTRIGGER
gameport.device/GPD_READEVENT
gameport.device/GPD_SETCTYPE
gameport.device/GPD_SETTRIGGER
 gameport.device/GPD_ASKCTYPE                     gameport.device/GPD_ASKCTYPE

   NAME
    GPD_ASKCTYPE -- Acquire the current game port controller type

   FUNCTION
    This command identifies the type of controller at the game
    port, so that the signals at the port may be properly
    interpreted.  The controller type has been set by a previous
    SetCType.

    This command always executes immediately.

   IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Device	preset by the call to OpenDevice
    io_Unit		preset by the call to OpenDevice
    io_Command	GPD_ASKCTYPE
    io_Flags	IOB_QUICK set if quick I/O is possible
    io_Length	at least 1
    io_Data		the address of the byte variable for the
            result

 gameport.device/GPD_ASKTRIGGER                 gameport.device/GPD_ASKTRIGGER

   NAME
    GPD_ASKTRIGGER -- Inquire the conditions for a game port report

   FUNCTION
    This command inquires what conditions must be met by a game
    port unit before a pending Read request will be satisfied.
    These conditions, called triggers, are independent -- that
    any one occurs is sufficient to queue a game port report to
    the Read queue.	 These conditions are set by SetTrigger.

    This command always executes immediately.

   IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Device	preset by the call to OpenDevice
    io_Unit		preset by the call to OpenDevice
    io_Command	GPD_ASKTRIGGER
    io_Flags	IOB_QUICK set if quick I/O is possible
    io_Length	sizeof(gamePortTrigger)
    io_Data		a structure of type GamePortTrigger, which
            has the following elements
        gpt_Keys -
            GPTB_DOWNKEYS set if button down transitions
            trigger a report, and GPTB_UPKEYS set if button up
            transitions trigger a report
        gpt_Timeout	-
            a time which, if exceeded, triggers a report;
            measured in vertical blank units (60/sec)
        gpt_XDelta	-
            a distance in x which, if exceeded, triggers a
            report
        gpt_YDelta	-
            a distance in x which, if exceeded, triggers a
            report

 gameport.device/GPD_READEVENT                   gameport.device/GPD_READEVENT

   NAME
    GPD_READEVENT -- Return the next game port event.

   FUNCTION
    Read game port events from the game port and put them in the
    data area of the iORequest.  If there are no pending game port
    events, this command will not be satisfied, but if there are
    some events, but not as many as can fill IO_LENGTH, the
    request will be satisfied with those currently available.

   IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Device	preset by the call to OpenDevice
    io_Unit		preset by the call to OpenDevice
    io_Command	GPD_READEVENT
    io_Flags	IOB_QUICK set if quick I/O is possible
    io_Length	the size of the io_Data area in bytes: there
            are sizeof(inputEvent) bytes per input event.
    io_Data		a buffer area to fill with input events.  The
            fields of the input event are:
        ie_NextEvent
            links the events returned
        ie_Class
            is IECLASS_RAWMOUSE
        ie_SubClass
            is 0 for the left, 1 for the right game port
        ie_Code
            contains any gameport button reports.  No
            report is indicated by the value 0xff.
        ie_Qualifier
            only the relative and button bits are set
        ie_X, ie_Y
            the x and y values for this report, in either
            relative or absolute device dependent units.
        ie_TimeStamp
            the delta time since the last report, given
            not as a standard timestamp, but as the frame
            count in the TV_SECS field.

   RESULTS
    This function sets the error field in the iORequest, and fills
    the iORequest with the next game port events (but not partial
    events).

   SEE ALSO
    gameport.device/SetCType, gameport.device/SetTrigger

 gameport.device/GPD_SETCTYPE                     gameport.device/GPD_SETCTYPE

   NAME
    GPD_SETCTYPE -- Set the current game port controller type

   FUNCTION
    This command sets the type of device at the game port, so that
    the signals at the port may be properly interpreted.  The port
    can also be turned off, so that no reports are generated.

    This command always executes immediately.

   IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Device	preset by the call to OpenDevice
    io_Unit		preset by the call to OpenDevice
    io_Command	GPD_SETCTYPE
    io_Flags	IOB_QUICK set if quick I/O is possible
    io_Length	1
    io_Data		the address of the byte variable describing
            the controller type, as per the equates in
            the gameport include file

 gameport.device/GPD_SETTRIGGER                 gameport.device/GPD_SETTRIGGER

   NAME
    GPD_SETTRIGGER -- Set the conditions for a game port report

   FUNCTION
    This command sets what conditions must be met by a game
    port unit before a pending Read request will be satisfied.
    These conditions, called triggers, are independent -- that
    any one occurs is sufficient to queue a game port report to
    the Read queue.	 These conditions are inquired with
    AskTrigger.

    This command always executes immediately.

   IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Device	preset by the call to OpenDevice
    io_Unit		preset by the call to OpenDevice
    io_Command	GPD_SETTRIGGER
    io_Flags	IOB_QUICK set if quick I/O is possible
    io_Length	sizeof(gamePortTrigger)
    io_Data		a structure of type GamePortTrigger, which
            has the following elements
        gpt_Keys -
            GPTB_DOWNKEYS set if button down transitions
            trigger a report, and GPTB_UPKEYS set if button up
            transitions trigger a report
        gpt_Timeout	-
            a time which, if exceeded, triggers a report;
            measured in vertical blank units (60/sec)
        gpt_XDelta	-
            a distance in x which, if exceeded, triggers a
            report
        gpt_YDelta	-
            a distance in x which, if exceeded, triggers a
            report


Text_Autodocs/narrator.doc

TABLE OF CONTENTS

narrator.device/AbortIO
narrator.device/OpenDevice
narrator.device/CMD_FLUSH
narrator.device/CMD_READ
narrator.device/CMD_RESET
narrator.device/CMD_START
narrator.device/CMD_STOP
narrator.device/CMD_WRITE
narrator.device/CloseDevice

narrator.device/AbortIO				    narrator.device/AbortIO

   NAME
    AbortIO - Abort an IO request

   SYNOPSIS
    AbortIO(IORequest)
           A1

   FUNCTION
    Exec library call to abort a specified READ or WRITE request.
    The IORequest may be in the queue or currently active.  If
    currently active, the request is immediately stopped and then
    removed.

   INPUTS
    Pointer to the IORequest block to be aborted.

   RESULTS
    io_Error field in the IORequest block set to #IOERR_ABORTED.

   SEE ALSO

narrator.device/CloseDevice			  narrator.device/CloseDevice

   NAME
    CloseDevice - terminates access to the narrator device

   SYNOPSIS
    CloseDevice(IORequest)
               A1

   FUNCTION
    Close invalidates the IO_UNIT and IO_DEVICE fields in the
    IORequest block, preventing subsequent IO until another
    OpenDevice.  CloseDevice also reduces the open count.  If
    the count goes to 0 and the expunge bit is set, the device
    is expunged.  If the open count goes to zero and the delayed
    expunge bit is not set, CloseDevice sets the expunge bit.

   INPUTS
    A valid IORequest block with its io_Message structure, and
    io_Device and io_Unit fields properly initialized.  These
    fields are initialized by OpenDevice.

   RESULTS
    CloseDevice invalidates the unit and device pointers in the
    IORequest block.

   SEE ALSO

narrator.device/CMD_FLUSH			narrator.device/CMD_FLUSH

   NAME
    CMD_FLUSH - Aborts all inprogress and queued requests

   SYNOPSIS
    Standard device command.

   FUNCTION
    Aborts all inprogress and queued speech requests.

   INPUTS
    Valid IORequest block with the io_Command field set to CMD_FLUSH.
    A valid IORequest block is one with its io_Message structure, and
    io_Device and io_Unit fields properly initialized.  The easiest
    way to insure proper initialization is to make a copy of the
    IORequest block after a successful OpenDevice call.

   RESULTS
    io_Error in IORequest block set to 0

   SEE ALSO
      Exec input/output documentation.

narrator.device/CMD_Read			narrator.device/CMD_Read

   NAME
    CMD_READ - Query the narrator device for mouth shape or other
           synchronization events.

   SYNOPSIS
    Standard device command.

   FUNCTION
    Currently, there are three events which the user can inquire
    about from the narrator device.  These are: mouth shape changes,
    start of word, and start of syllable.  Each read request returns
    information about any or all of these events as determined by
    the bits set in the sync field of the read IORequest block.  In
    the case of mouth shape changes, each shape returned is guaranteed
    to be different from the previously returned shape to allow
    updating to be done only when necessary.  Each read request is
    associated with a write request	by information contained in the
    IORequest block used to open the device.  Since the first field
    in the read IORequest block is a write IORequest structure, this
    association is easily made by copying the write IORequest block
    (after the OpenDevice call) into the voice field of the read
    IORequest block.  If there is no write in progress or in the
    device input queue with the same pseudo unit number as the read
    request, the read will be returned to the user with an error.  This
    is also how the user knows that the write request has finished and
    that s/he should not issue any more reads.  Note that in this case
    the mouth shapes may not be different from previously returned values.

   INPUTS
    mouth_rb IORequest block with the voice field (a narrator_rb
    structure) copied from the associated write request with the
    following fields modified:

       io_Message - Pointer to message port for read request
       io_Command - CMD_READ
       io_Error   - Clear before issuing first read
       width      - 0
       height     - 0

   RESULTS
    As long as the speech is in progress, each read returns the
    following information in the mouth_rb IORequest block.

    If mouth shape changes are requested the following fields are
    modified:
       width  - Contains mouth width value in arbitrary units
       height - Contains mouth height value in arbitrary units
       shape  - Compressed form of mouth shapes (internal use only)

    ******	NEW FOR V37 NARRATOR

    If word synchronization is requested:
       sync   - Bit NDB_WORDSYNC is set

    If syllable synchronization is requested:
       sync   - Bit NDB_SYLSYNC is set

    Note that any or all of the above fields can be set and it is
    the user's responsibility to check for all possibilities.

   SEE ALSO
    CMD_WRITE
    Exec input/output documentation.

narrator.device/CMD_RESET			    narrator.device/CMD_RESET

   NAME
    CMD_RESET - Reset the device to a known state

   SYNOPSIS
    Standard device command.

   FUNCTION
    Resets the device as though it has just be initialized.
    Aborts all read/write requests whether active of enqueued.
    Restarts device if it has been stopped.

   INPUTS
    Valid IORequest block with the io_Command field set to CMD_RESET.
    A valid IORequest block is one with its io_Message structure, and
    io_Device and io_Unit fields properly initialized.  The easiest
    way to insure proper initialization is to make a copy of the
    IORequest block after a successful OpenDevice call.

   RESULTS

   SEE ALSO
    Exec input/output documentation.

narrator.device/CMD_START			    narrator.device/CMD_START

   NAME
    CMD_START - Restarts the device after a CMD_STOP command

   SYNOPSIS
    Standard device command.

   FUNCTION
    CMD_START restarts the currently active speech (if any)	and
    allows queued requests to start.

   INPUTS
    Valid IORequest block with the io_Command field set to CMD_START
    A valid IORequest block is one with its io_Message structure, and
    io_Device and io_Unit fields properly initialized.  The easiest
    way to insure proper initialization is to make a copy of the
    IORequest block after a successful OpenDevice call.

   RESULTS
    io_Error set to 0.

   SEE ALSO
    Exec input/output documentation.

narrator.device/CMD_STOP			    narrator.device/CMD_STOP

   NAME
    CMD_STOP  - Stops the device.

   SYNOPSIS
    Standard device command.

   FUNCTION
    CMD_STOP halts the currently active speech (if any) and	prevents
    any queued requests from starting.

   INPUTS
    Valid IORequest block with the io_Command field set to CMD_STOP.
    A valid IORequest block is one with its io_Message structure, and
    io_Device and io_Unit fields properly initialized.  The easiest
    way to insure proper initialization is to make a copy of the
    IORequest block after a successful OpenDevice call.

   RESULTS
    io_Error set to 0.

   SEE ALSO
    Exec input/output documentation.

narrator.device/CMD_WRITE			    narrator.device/CMD_WRITE

   NAME
    CMD_WRITE - Send speech request to the narrator device

   SYNOPSIS
    Standard device command.

   FUNCTION
    Sends a phonetic string to the narrator device to be spoken
    and, optionally, is used to direct the narrator device to
    return mouth shape changes, and word and syllable sync events
    in response to read requests from the user.  The phonetic string
    consists of ASCII characters representing the individual phonemes.
    Refer to the narrator device chapter of the libraries and devices
    volume of the ROM Kernel Manual for detailed information.

   INPUTS
    User IORequest block (struct narrator_rb as defined in .h file).
    The OpenDevice call will initialize the IORequest block to a
    "standard male" voice.  If you want to change any parms, do so
    after the OpenDevice call and before the DoIO (or SendIO/WaitIO).
    For a complete description of the narrator_rb structure, see the
    narrator.h or .i include file.  Note that the OpenDevice call does
    not initialize all the fields needed by the narrator device.  The
    IORequest fields which must be set by the user before issuing the
    write request are:

       io_Command - Set to CMD_WRITE
       io_Data    - Pointer to phonetic string
       io_Length  - Length of phonetic string
       ch_masks   - Array of audio channel selection masks (see audio
            device documentation for description of this field)
       nm_masks   - Number of audio channel selection masks

       ****** NEW FOR V37 NARRATOR

       flags - The bit NDB_NEWIORB must be set in the flags field if
           any of the new features of the V37 narrator are used

    In addition to producing synthetic speech, the narrator device
    also provides features for synchronizing the speech to animation
    or other user defined events.  There are three types of events
    that the user can request.  They are mouth shape changes, start of
    new word, and start of new syllable.  Mouth shape changes are
    requested by setting the mouths field of the IORequest block to a
    non-zero value.  Word and syllable sync events are requested by
    setting the NDB_WORDSYNC and/or NDB_SYLSYNC bits in the flags field
    of the IORequest block.  Note that word and syllable sync only work
    in V37 and later versions of the narrator device.

   RESULTS
    The narrator device range checks and performs other validity
    checks for all input parms.  If any input is in error, the device
    sets the io_Error field of the IORequest block to an appropriate
    value (see include files for error codes).  If everything is in
    order, the narrator device will produce the speech and clear the
    io_Error field.  The io_Actual field is set to the length of the
    input string that was actually processed.  If the return code
    indicates a phoneme error (ND_PhonErr), io_Actual is the NEGATIVE
    of the position in the input string where the error occured.

   SEE ALSO
    Read command.
    Audio device documentation.
    Exec input/output documentation.

narrator.device/OpenDevice			    narrator.device/OpenDevice

   NAME
    OpenDevice - opens the narrator device.

   SYNOPSIS
    error = OpenDevice("narrator.device",  unit, IORequest, flags);
     D0                       A0            D0     A1         D1

   FUNCTION
    The OpenDevice routine grants access to the narrator device.
    OpenDevice checks the unit number, and if non-zero, returns an
    error (ND_UnitErr).  If this is the first time the driver has
    been opened, OpenDevice will attempt to open the audio device
    and allocate the driver's static buffers.  If either of these
    operations fail, an error is returned.  See the .h and .i
    include files for possible error return codes.  Next, OpenDevice
    (done for all opens, not just the first one) initializes various
    fields in the user's IORequest block (see below).  If users wish
    to use non-default values for these parms, the values must be set
    after the open is done.  OpenDevice also assigns a pseudo unit
    number to the IORB for use in synchronizing read and write requests.
    See the read command for more details.	Finally, OpenDevice stores
    the device node pointer in the IORequest block and clears the
    delayed expunge bit.

    ***** NEW FOR V37 NARRATOR *****

    Several new fields in the IORequest block have been added for V37
    narrator.  These fields are initialized when the device is opened
    if the NDB_NEWIORB bit is set in the flags field of the user's
    IORequest block.  Note that NDB_NEWIORB is set in the IORequest
    block, NOT in the "flags" input parm to the OpenDevice call.

   INPUTS
    device     - "narrator.device"
    unit       - 0
    IORequest  - Pointer to the user's IORequest block
    flags	   - 0

   RESULTS
    The narrator device will initialize the IORequest block as follows
    (assume IORB points to the IOrequest block):

    IORB->rate = 150;		/* Speaking rate in words/minute */
    IORB->pitch = 110;		/* Baseline pitch in Hertz     	*/
    IORB->mode = NATURALF0;		/* Pitch (F0) mode		*/
    IORB->sex = MALE;		/* Sex of voice			*/
    IORB->volume = 64		/* Volume, full on		*/
    IORB->sampfreq = 22200		/* Audio sampling freq 		*/
    IORB->mouths = 0		/* Don't generate sync events	*/

    and if the NDB_NEWIORB bit is set:

    IORB->F0enthusiasm = 0		/* F0 excursion factor		*/
    IORB->F0perturb = 32		/* F0 perturbation (in 32nds)	*/
    IORB->F1adj = 0			/* F1 adjustment in ±5% steps	*/
    IORB->F2adj = 0 		/* F2 adjustment in ±5% steps	*/
    IORB->F3adj = 0			/* F3 adjustment in ±5% steps	*/
    IORB->A1adj = 0			/* A1 adjustment in decibels	*/
    IORB->A2adj = 0			/* A2 adjustment in decibels	*/
    IORB->A3adj = 0		 	/* A3 adjustment in decibels	*/
    IORB->articulate = 100		/* Transition time multiplier	*/
    IORB->centralize = 0		/* Degree of vowel centralization */
    IORB->centphon = ""		/* Pointer to central ASCII phon  */
    IORB->AVbias = 0		/* AV bias			*/
    IORB->AFbias = 0		/* AF bias			*/
    IORB->priority = 100		/* Priority while speaking	*/

   SEE ALSO
    The include files contain the complete IORequest block definition,
        default settings, and error return codes.
    Exec input/output documentation.


Text_Autodocs/serial.doc

TABLE OF CONTENTS

serial.device/AbortIO
serial.device/BeginIO
serial.device/CloseDevice
serial.device/CMD_CLEAR
serial.device/CMD_FLUSH
serial.device/CMD_READ
serial.device/CMD_RESET
serial.device/CMD_START
serial.device/CMD_STOP
serial.device/CMD_WRITE
serial.device/OpenDevice
serial.device/SDCMD_BREAK
serial.device/SDCMD_QUERY
serial.device/SDCMD_SETPARAMS

serial.device/AbortIO                                     serial.device/AbortIO

   NAME
       AbortIO(ioRequest) -- abort an I/O request
               A1

   FUNCTION
      This is an exec.library call.

      This function attempts to aborts a specified read or write request.
      If the request is active, it is stopped immediately. If the request is
      queued, it is painlessly removed.  The request will be returned
      in the same way any completed request it.

      After AbortIO(), you must generally do a WaitIO().

   INPUTS
      iORequest  -- pointer to the IORequest Block that is to be aborted.

   RESULTS
       io_Error -- if the Abort succeded, then io_Error will be #IOERR_ABORTED

           (-2) and the request will be flagged as aborted (bit 5 of
           io_Flags is set).  If the Abort failed, then the Error will be zero.

   BUGS
       Previous to version 34, the serial.device would often hang when
       aborting CTS/RTS handshake requests.  This was the cause of the
       incorrect assumption that AbortIO() does not need to be followed
       by a wait for a reply (or a WaitIO()).

serial.device/BeginIO                                     serial.device/BeginIO

   NAME
       BeginIO(ioRequest),deviceNode -- start up an I/O process
                A1        A6
   FUNCTION
       This is a direct function call to the device.  It is intended for
       more advanced programmers.  See exec's DoIO() and SendIO() for
       the normal method of calling devices.

       This function initiates a I/O request made to the serial
       device. Other than read or write, the functions are performed
       synchronously, and do not depend on any interrupt handling
       logic (or it's associated discontinuities), and hence should
       be performed as IO_QUICK.
       With some exceptions, reads and writes are merely initiated by
       BeginIO, and thusly return to the caller as begun, not completed.
       Completion is signalled via the standard ReplyMsg routine.
       Multiple requests are handled via FIFO queueing.
       One exception to this non-QUICK handling of reads and writes
       is for READS when:
         - IO_QUICK bit is set
         - There are no pending read requests
         - There is already enough data in the input buffer to satisfy
           this I/O Request immediately.
       In this case, the IO_QUICK flag is not cleared, and the request
       is completed by the time it returns to the caller. There is no
       ReplyMsg or signal bit activity in this case.

   INPUTS
       ioRequest  -- pointer to an I/O Request Block of size
           io_ExtSerSize (see serial.i for size/definition),
           containing a valid command in io_Command to process,
           as well as the command's other required parameters.
       deviceNode -- pointer to the "serial.device", as found in
           the IO_DEVICE of the ioRequest.

   RESULTS
       io_Error -- if the BeginIO succeded, then Error will be null.
           If the BeginIO failed, then the Error will be non-zero.
           I/O errors won't be reported until the io completes.

   SEE ALSO
    devices/serial.h

serial.device/CloseDevice                             serial.device/CloseDevice

   NAME
       CloseDevice -- close the serial port

   SYNOPSIS
       CloseDevice(deviceNode)
                    A1
   FUNCTION
       This is an exec call that terminates communication with the
       serial device.  Upon closing, the device's input buffer is freed.

       Note that all IORequests MUST be complete before closing.
    If any are pending, your program must AbortIO() then WaitIO()
       to complete them.

   INPUTS
       deviceNode - pointer to the device node, set by Open

   SEE ALSO
       serial.device/OpenDevice

serial.device/CMD_CLEAR                                 serial.device/CMD_CLEAR

   NAME
       Clear -- clear the serial port buffers

   FUNCTION
       This command resets the serial port's read buffer pointers.

   IO REQUEST
       io_Message      mn_ReplyPort initialized
       io_Device       set by OpenDevice
       io_Unit         set by OpenDevice
       io_Command      CMD_CLEAR

   RESULTS
       Error -- If the Clear succeded, then io_Error will be null.
                If the Clear failed, then the io_Error will be non-zero.

serial.device/CMD_FLUSH                                 serial.device/CMD_FLUSH

   NAME
       Flush -- clear all queued I/O requests for the serial port

   FUNCTION
       This command purges the read and write request queues for the
       serial device. Flush will not affect active requests.

   IO REQUEST
       io_Message      mn_ReplyPort initialized
       io_Device       set by OpenDevice
       io_Unit         set by OpenDevice
       io_Command      CMD_FLUSH

   RESULTS
       Error -- if the Flush succeded, then io_Error will be null.
                If the Flush failed, then the io_Error will be non-zero.

serial.device/CMD_READ                                   serial.device/CMD_READ

   NAME
       Read -- read input from serial port

   FUNCTION
    This command causes a stream of characters to be read in from
    the serial port buffer.  The number of characters is specified
    in io_Length.

    The Query function can be used to check how many characters
    are currently waiting in the serial port buffer.  If more characters
    are requested than are currently available, the ioRequest
    will be queued until it can be satisfied.

    The best way to handle reads is to first Query to get the number
    of characters currently in the buffer.  Then post a read request
    for that number of characters (or the maximum size of your buffer).

    If zero characters are in the buffer, post a request
    for 1 character.  When at least one is ready, the device will return
    it.  Now start over with another Query.

    Before the program exits, it must be sure to AbortIO() then WaitIO()
    any outstanding ioRequests.

   IO REQUEST
       io_Message      A mn_ReplyPort is required
       io_Device       set by OpenDevice
       io_Unit         set by OpenDevice
       io_Command      CMD_READ
       io_Flags        If the IOB_QUICK bit is set, read will try
            to complete the IO quickly
       io_Length       number of characters to receive.
       io_Data         pointer to buffer

   RESULTS
       Error -- if the Read succeded, then io_Error will be null.
           If the Read failed, then io_Error will be non-zero.
         io_Error will indicate problems such as parity mismatch,
         break, and buffer overrun.

   SEE ALSO
    serial.device/SDCMD_QUERY
    serial.device/SDCMD_SETPARAMS

   BUGS
    Having multiple outstanding read IORequests at any one time will
    probably fail.

    Old documentation mentioned a mode where io_Length was set to -1.
    If you want a NULL terminated read, use the io_TermArray instead.

serial.device/CMD_RESET                                 serial.device/CMD_RESET

   NAME
       Reset -- reinitializes the serial port

   FUNCTION
       This command resets the serial port to its freshly initialized
       condition. It aborts all I/O requests both queued and current,
       relinquishes the current buffer, obtains a new default sized
       buffer, and sets the port's flags and parameters to their
       boot-up time default values. The functions places the reset
       parameter values in the ioRequest block.

   IO REQUEST
       io_Message      mn_ReplyPort initialized
       io_Device       set by OpenDevice
       io_Unit         set by OpenDevice
       io_Command      CMD_RESET

   RESULTS
       Error -- if the Reset succeded, then Error will be null.
           If the Reset failed, then the Error will be non-zero.

serial.device/CMD_START                                 serial.device/CMD_START

   NAME
       Start -- restart paused I/O over the serial port

   FUNCTION
       This function restarts all current I/O on the serial port by
       sending an xON to the "other side", and submitting a "logical
       xON" to "our side", if/when appropriate to current activity.

   IO REQUEST
       io_Message      mn_ReplyPort initialized
       io_Device       set by OpenDevice
       io_Unit         set by OpenDevice
       io_Command      CMD_START

   RESULTS

   SEE ALSO
       serial.device/CMD_STOP

serial.device/CMD_STOP                                   serial.device/CMD_STOP

   NAME
       Stop -- pause all current I/O over the serial port

   FUNCTION
       This command halts all current I/O on the serial port by
       sending an xOFF to the "other side", and submitting a "logical
       xOFF" to "our side", if/when appropriate to current activity.

   IO REQUEST
       io_Message      mn_ReplyPort initialized
       io_Device       set by OpenDevice
       io_Unit         set by OpenDevice
       io_Command      CMD_STOP

   RESULTS

   SEE ALSO
       serial.device/CMD_START

serial.device/CMD_WRITE                                 serial.device/CMD_WRITE

   NAME
       Write -- send output to serial port

   FUNCTION
       This command causes a stream of characters to be written out
       the serial port. The number of characters is specified in
       io_Length, unless -1 is used, in which case output is sent until
       a null(0x00) is encountered.

   IO REQUEST
       io_Message      must have mn_ReplyPort initialized
       io_Device       set by OpenDevice
       io_Unit         set by OpenDevice
       io_Command      CMD_WRITE
       io_Flags        Set IOF_QUICK to try quick I/O
       io_Length       number of characters to transmit, or if set
                       to -1 transmit until null encountered in buffer
       io_Data         pointer to block of data to transmit

   RESULTS
       Error -- if the Write succeded, then io_Error will be null.
           If the Write failed, then the io_Error will be non-zero.

   SEE ALSO
    serial.device/SDCMD_SETPARAMS

serial.device/OpenDevice                               serial.device/OpenDevice

   NAME
       OpenDevice -- Request an opening of the serial device.

   SYNOPSIS
       error = OpenDevice("serial.device", unit, ioRequest, flags)
       D0                  A0              D0    A1         D1

    BYTE OpenDevice(STRPTR, ULONG, struct IOExtSer *, ULONG);

   FUNCTION
       This is an exec call.  Exec will search for the serial.device, and
       if found, will pass this call on to the device.

       Unless the shared-access bit (bit 5 of io_SerFlags) is set,
       exclusive use is granted and no other access to that unit is
       allowed until the owner closes it.  All the serial-specific fields
       in the ioRequest are initialized to their most recent values (or
       the Preferences default, for the first time open).

       If support of 7-wire handshaking (i.e. RS232-C CTS/RTS protocol)
       is required, use the serial.device/SDCMD_SETPARAMS command.
    This feature should also be specified at inital OpenDevice() time.

   INPUTS
       "serial.device"	- pointer to literal string "serial.device"
       unit      	- Must be zero, or a user setable unit number.
              (This field is used by multiple port controllers)
                         Zero specifies the default serial port.
       ioRequest 	- pointer to an ioRequest block of size io_ExtSerSize
                         to be initialized by the serial.device.
                         (see devices/serial.h for the definition)
                           NOTE use of io_SerFlags (see FUNCTION above)
        IMPORTANT: The ioRequest block MUST be of size io_ExtSerSize,
               and zeroed (with the exeptions as noted)!
       flags     	- Must be zero for future compatibility

   RESULTS
       D0 	  - same as io_Error
       io_Error  - If the Open succeded, then io_Error will be null.
                   If the Open failed, then io_Error will be non-zero.
       io_Device - A pointer to whatever device will handle the calls
                   for this unit.  This pointer may be different depending
                   on what unit is requested.

   BUGS
    If 7-wire handshaking is specified, a timeout "feature" is enabled.
    If the device holds off the computer for more than about 30-60
    seconds, the device will return the write request with the error
    SerErr_TimerErr.  Don't depend on this, however.  If you want a timeout,
    set up the timer.device and wait for either timer, or serial IO to
    complete.

    On open, the serial.device allocates the misc.resource for the
    serial port.  It does not return it until the serial.device is
    expunged from memory.  It should return it when no more openers
    exist.   This code can force a specified device to try and
    expunge.  Of course, if the device is in use nothing will happen:

    #include "exec/types.h"
    #include "exec/execbase.h"
    #include "proto/exec.h"

    void FlushDevice(char *);
    extern struct ExecBase *SysBase;

    void main()
    {
        FlushDevice("serial.device");	/* or parallel.device */
    }

    /*
     * Attempts to flush the named device out of memory.
     * If it fails, no status is returned; examination of
     * the problem will reveal that information has no
     * valid use after the Permit().
     */
    void FlushDevice(name)
    char  *name;
    {
    struct Device *result;

        Forbid();
        if( result=(struct Device *)FindName(&SysBase->DeviceList,name) )
        RemDevice(result);
        Permit();
    }

   SEE ALSO
    serial.device/CloseDevice
    serial.device/SDCMD_SETPARAMS
    devices/serial.h

serial.device/SDCMD_BREAK                             serial.device/SDCMD_BREAK

   NAME
       Break -- send a break signal over the serial line

   FUNCTION
       This command sends a break signal (serial line held low for an
       extended period) out the serial port. For the built-in port,
       This is accomplished by setting the UARTBRK bit of regisrer ADKCON.

       After a duration (user specifiable via setparams, default 250000
       microseconds) the bit is reset and the signal discontinued.
       If the QUEUEDBRK bit of io_SerFlags is set in the io_Request
       block, the request is placed at the back of the write-request
       queue and executed in turn. If the QUEUEDBRK bit is not set,
       the break is started immediately, control returns to the
       caller, and the timer discontinues the signal after the
       duration is completed. Be aware that calling BREAK may
    affect other commands such as ABORT, FLUSH, STOP, START, etc...

   IO REQUEST
       io_Message      mn_ReplyPort initialized
       io_Device       set by OpenDevice
       io_Unit         set by OpenDevice
       io_Command      SDCMD_BREAK
       io_Flags        set/reset IO_QUICK per above description

   RESULTS
       Error -- if the Break succeded, then Error will be null.
           If the Break failed, then the Error will be non-zero.

serial.device/SDCMD_QUERY                             serial.device/SDCMD_QUERY

   NAME
       Query -- query serial port/line status

   FUNCTION
       This command return the status of the serial port lines and
       registers. The number of unread bytes in the serial device's
       read buffer is shown in io_Actual.

    The break send & received flags are cleared by a query, and
    whenever a read IORequest is returned with a error
    in io_Error.

   IO REQUEST
       io_Message      mn_ReplyPort initialized
       io_Device       preset by OpenDevice
       io_Unit         preset by OpenDevice
       io_Command      SDCMD_QUERY

   RESULTS
       io_Status        BIT  ACTIVE  FUNCTION

              LSB       0    ---    reserved
                        1    ---    reserved
                        2    high   parallel "sel" on the A1000
                                    On the A500 & A2000, "sel" is also
                                    connected to the serial port's
                                    "Ring Indicator".  Be cautious when
                                    making cables.
                        3    low    Data Set Ready
                        4    low    Clear To Send
                        5    low    Carrier Detect
                        6    low    Ready To Send
                        7    low    Data Terminal Ready
              MSB       8    high   hardware overrun
                        9    high   break sent (most recent output)
                       10    high   break received (as latest input)
                       11    high   transmit x-OFFed
                       12    high   receive x-OFFed
                    13-15    ---    reserved

       io_Actual       set to count of unread input characters

       io_Error -- Query will always succeded.

serial.device/SDCMD_SETPARAMS                     serial.device/SDCMD_SETPARAMS

   NAME
       SetParams -- change parameters for the serial port

   FUNCTION
       This command allows the caller to change parameters for the
       serial device. Except for xON-xOFF enable/disable, it will
       reject a setparams call if any reads or writes are active
       or pending.
          Note specifically:

    1. Valid input for io_Baud is between 112 and 292000 baud inclusive;
       asynchronous i/o above 32KB (especially on a busy system) may
       be ambitious.
    2. The EOFMODE and QUEUEDBRK bits of io_SerFlags can be set/reset
       in the io_Rqst block without a call to SetParams. The SHARED
       and 7WIRE bits of io_SerFlags can be used in OpenDevice calls.
       ALL OTHER PARAMETERS CAN ONLY BE CHANGED BY THE SetParams
       COMMAND.
    3. RBufLen must be at least 64.  The buffer may be any multiple of
    64 bytes.
    4. If not used, io_ExtFlags MUST be set to zero.
    5. xON-xOFF is by default enabled. The XDISABLED bit is the only
       parameter that can be changed via a SetParams call while the
       device is active. Note that this will return the value
       SerErr_DevBusy in the io_Error field.

    xON/xOFF handshaking is inappropriate for certain binary transfer
    protocalls, such as Xmodem.  The binary data might contain the
    xON (ASCII 17) and xOFF (ASCII 19) characters.

    6. If trying to run MIDI, you should set the RAD_BOOGIE bit of
       io_SerFlags to eliminate unneeded overhead. Specifically, this skips
       checks for parity, x-OFF handling, character lengths other than
       8 bits, and testing for a break signal. Setting RAD_BOOGIE will
       also set the XDISABLED bit.
       Note that writing data (that's already in MIDI format) at MIDI rates
       is easily accomplished. Using this driver alone for MIDI reads may,
       however, may not be reliable, due to MIDI timestamping requirements,
       and possibility of overruns in a busy multitasking and/or display
       intensive environment.
    7. If you select mark or space parity (see io_ExtFlags in serial.h),
       this will cause the SERB_PARTY_ON bit to be set, and the setting
       of SERB_PARTY_ODD to be ignored.
    8. For best results, set the RAD_BOOGIE flag whenever possible.  See
    #6 for details.
    9. Note that at this time parity is *not* calculated for the xON-xOFF
    characters.  If you have a system that is picky about the parity of
    these, you must set your own xON-xOFF characters in io_CtlChar.
   10. 7WIRE (CTS/RTS) handshake is bi-directional.  The external side
    is expected to drop CTS several character times before the external
    buffer is full.  The Amiga will drop RTS several character times
    before the Amiga's buffer is full.

   IO REQUEST
       io_Message      mn_ReplyPort initialized
       io_Device       preset by OpenDevice
       io_Unit         preset by OpenDevice
       io_Command      SDCMD_SETPARAMS (0x0B)
              NOTE that the following fields are filled in by Open
                       to reflect the serial device's current configuration.
       io_CtlChar      a longword containing byte values for the
                       xON,xOFF,INQ,ACK fields (respectively)
                       (INQ/ACK not used at this time)
       io_RBufLen      length in bytes of input buffer
              NOTE that any change in buffer size causes the
                       current buffer to be deallocated and a new,
                       correctly sized one to be allocated. Thusly,
                       the CONTENTS OF THE OLD BUFFER ARE LOST.
       io_ExtFlags     additional serial flags (bitdefs in devices/serial.h)
            mark & space parity may be specified here.
       io_Baud         baud rate for reads AND writes. (See 1 above)
       io_BrkTime      duration of break signal in MICROseconds
       io_TermArray    ASCII descending-ordered 8-byte array of
                       termination characters. If less than 8 chars
                       used, fill out array w/lowest valid value.
                       Terminators are checked only if EOFMODE bit of
                       io_Serflags is set. (e.g. x512F040303030303 )
       io_ReadLen      number of bits in read word (1-8) not including parity
       io_WriteLen     number of bits in write word (1-8) "      "       "
       io_StopBits     number of stop bits (0, 1 or 2)
       io_SerFlags     see devices/serial.h for bit equates, NOTE that x00
                       yields exclusive access, xON/OFF-enabled, no
                       parity checking, 3-wire protocol and TermArray
                       inactive.

   RESULTS
       Error -- if the SetParams succeded, then Error will be null.
           If the SetParams failed, then the Error will be non-zero.

   SEE ALSO
    exec/OpenDevice


Text_Autodocs/clipboard.doc

TABLE OF CONTENTS

clipboard.device/CBD_CHANGEHOOK
clipboard.device/CBD_CURRENTREADID
clipboard.device/CBD_CURRENTWRITEID
clipboard.device/CBD_POST
clipboard.device/CMD_READ
clipboard.device/CMD_UPDATE
clipboard.device/CMD_WRITE
 clipboard.device/CBD_CHANGEHOOK               clipboard.device/CBD_CHANGEHOOK

   NAME
    CBD_CHANGEHOOK -- Add or remove a clip change hook

   FUNCTION
    CBD_CHANGEHOOK allows specification of a hook to be called
    when the data on the clipboard has changed.

   IO REQUEST
    io_Message	mn_ReplyPort set up
    io_Device	preset by OpenDevice
    io_Unit		preset by OpenDevice
    io_Command	CBD_CHANGEHOOK
    io_Length -     0 to remove, 1 to install this hook
    io_Data -       struct Hook *, the clip change hook

   HOOK ENVIRONMENT
       hook message - a ClipHookMsg, as defined in devices/clipboard.h
           chm_Type - 0, indicating that the message has the
               following fields:
           chm_ClipID - the clip ID of the clip triggering the change
       hook object - io_Unit

 clipboard.device/CBD_CURRENTREADID         clipboard.device/CBD_CURRENTREADID

   NAME
    CBD_CURRENTREADID - Determine the current read identifier.

   FUNCTION
    CBD_CURRENTREADID fills the io_ClipID with a clip identifier that
    can be compared with that of a post command: if greater than
    the post identifier then the post data held privately by an
    application is not valid for its own pasting.

   IO REQUEST
    io_Message	mn_ReplyPort set up
    io_Device	preset by OpenDevice
    io_Unit		preset by OpenDevice
    io_Command	CBD_CURRENTREADID

   RESULTS
    io_ClipID	the ClipID of the current write is set

 clipboard.device/CBD_CURRENTWRITEID       clipboard.device/CBD_CURRENTWRITEID

   NAME
    CBD_CURRENTWRITEID -- Determine the current write identifier.

   FUNCTION
    CBD_CURRENTWRITEID fills the io_ClipID with a clip identifier that
    can be compared with that of a post command: if greater than
    the post identifier then the post is obsolete and need never
    be satisfied.

   IO REQUEST
    io_Message	mn_ReplyPort set up
    io_Device	preset by OpenDevice
    io_Unit		preset by OpenDevice
    io_Command	CBD_CURRENTWRITEID

   RESULTS
    io_ClipID	the ClipID of the current write is set

 clipboard.device/CBD_POST                           clipboard.device/CBD_POST

   NAME
    CBD_POST -- Post availability of a clip to the clipboard.

   FUNCTION
    Indicate to the clipboard device that data is available for
    use by accessors of the clipboard.  This is intended to be
    used when a cut is large, in a private data format, and/or
    changing frequently, and it thus makes sense to avoid
    converting it to an IFF form and writing it to the clipboard
    unless another application wants it.  The post provides a
    message port to which the clipboard device will send a satisfy
    message if the data is required.

    If the satisfy message is received, the write associated with
    the post must be performed.  The act of writing the clip
    indicates that the message has been received: it may then be
    re-used by the clipboard device, and so must actually be
    removed from the satisfy message port so that the port is not
    corrupted.

    If the application wishes to determine if a post it has
    performed is still the current clip, it should check the
    post's io_ClipID with that returned by the CBD_CURRENTREADID
    command.  If the current read io_ClipID is greater, the clip
    is not still current.

    If an application has a pending post and wishes to determine
    if it should satisfy it (e.g. before it exits), it should
    check the post's io_ClipID with that returned by the
    CBD_CURRENTWRITEID command.  If the current write io_ClipID is
    greater, there is no need to satisfy the post.

   IO REQUEST
    io_Message	mn_ReplyPort set up
    io_Device	preset by OpenDevice
    io_Unit		preset by OpenDevice
    io_Command	CBD_POST
    io_Data		pointer to satisfy message port
    io_ClipID	zero

   RESULTS
    io_Error	non-zero if an error occurred
    io_ClipID	the clip ID assigned to this post, to be used
            in the write command if this is satisfied

 clipboard.device/CMD_READ                           clipboard.device/CMD_READ

   NAME
    CMD_READ -- Read from a clip on the clipboard.

   FUNCTION
    The read function serves two purposes.

    When io_Offset is within the clip, this acts as a normal read
    request, and io_Data is filled with data from the clipboard.
    The first read request should have a zero io_ClipID, which
    will be filled with the ID assigned for this read.  Normal
    sequential access from the beginning of the clip is achieved
    by setting io_Offset to zero for the first read, then leaving
    it untouched for subsequent reads.  If io_Data is null, then
    io_Offset is incremented by io_Actual as if io_Length bytes
    had been read: this is useful to skip to the end of file
    by using a huge io_Length.

    When io_Offset is beyond the end of the clip, this acts as a
    signal to the clipboard device that the application is
    through reading this clip.  Realize that while an application
    is in the middle of reading a clip, any attempts to write new
    data to the clipboard are held off.  This read past the end
    of file indicates that those operations may now be initiated.

   IO REQUEST
    io_Message	mn_ReplyPort set up
    io_Device	preset by OpenDevice
    io_Unit		preset by OpenDevice
    io_Command	CMD_READ
    io_Length	number of bytes to put in data buffer
    io_Data		pointer to buffer of data to fill, or null to
            skip over data
    io_Offset	byte offset of data to read
    io_ClipID	zero if this is the initial read

   RESULTS
    io_Error	non-zero if an error occurred
    io_Actual	filled with the actual number of bytes read
    io_Data		(the buffer now has io_Actual bytes of data)
    io_Offset	updated to next read position, which is
            beyond EOF if io_Actual != io_Length
    io_ClipID	the clip ID assigned to this read: do not
            alter for subsequent reads

 clipboard.device/CMD_UPDATE                       clipboard.device/CMD_UPDATE

   NAME
    CMD_UPDATE -- Terminate the writing of a clip to the clipboard.

   FUNCTION
    Indicate to the clipboard that the previous write commands are
    complete and can be used for any pending pastes (reads).  This
    command cannot be issued while any of the write commands are
    pending.

   IO REQUEST
    io_Message	mn_ReplyPort set up
    io_Device	preset by OpenDevice
    io_Unit		preset by OpenDevice
    io_Command	CMD_UPDATE
    io_ClipID	the ClipID of the write

   RESULTS
    io_Error	non-zero if an error occurred

 clipboard.device/CMD_WRITE                         clipboard.device/CMD_WRITE

   NAME
    CMD_WRITE -- Write to a clip on the clipboard.

   FUNCTION
    This command writes data to the clipboard.  This data can be
    provided sequentially by clearing io_Offset for the initial
    write, and using the incremented value unaltered for
    subsequent writes.  If io_Offset is ever beyond the current
    clip size, the clip is padded with zeros.

    If this write is in response to a SatisfyMsg for a pending
    post, then the io_ClipID returned by the CBD_POST command must
    be used.  Otherwise, a new ID is obtained by clearing the
    io_ClipID for the first write.  Subsequent writes must not
    alter the io_ClipID.

   IO REQUEST
    io_Message	mn_ReplyPort set up
    io_Device	preset by OpenDevice
    io_Unit		preset by OpenDevice
    io_Command	CMD_WRITE
    io_Length	number of bytes from io_Data to write
    io_Data		pointer to block of data to write
    io_Offset	usually zero if this is the initial write
    io_ClipID	zero if this is the initial write, ClipID of
            the Post if this is to satisfy a post

   RESULTS
    io_Error	non-zero if an error occurred
    io_Actual	filled with the actual number of bytes written
    io_Offset	updated to next write position
    io_ClipID	the clip ID assigned to this write: do not
            alter for subsequent writes


Text_Autodocs/input.doc

TABLE OF CONTENTS

input.device/IND_ADDHANDLER
input.device/IND_REMHANDLER
input.device/IND_SETMPORT
input.device/IND_SETMTRIG
input.device/IND_SETMTYPE
input.device/IND_SETPERIOD
input.device/IND_SETTHRESH
input.device/IND_WRITEEVENT
input.device/PeekQualifier
 input.device/IND_ADDHANDLER                       input.device/IND_ADDHANDLER

   NAME
    IND_ADDHANDLER -- Add an input handler to the device

   FUNCTION
    Add a function to the list of functions called to handle
    input events generated by this device.  The function is called
    as
        newInputEvents = Handler(inputEvents, handlerData);
        D0			     A0		  A1

   IO REQUEST
    io_Message	mn_ReplyPort set
    io_Device	preset by OpenDevice
    io_Unit		preset by OpenDevice
    io_Command	IND_ADDHANDLER
    io_Data		a pointer to an interrupt structure.
        is_Data 	the handlerData pointer described above
        is_Code	the Handler function address

   NOTES
    The interrupt structure is kept by the input device until a
    RemHandler command is satisfied for it.

 input.device/IND_REMHANDLER                       input.device/IND_REMHANDLER

   NAME
    IND_REMHANDLER -- Remove an input handler from the device

   FUNCTION
    Remove a function previously added to the list of handler
    functions.

   IO REQUEST
    io_Message	mn_ReplyPort set
    io_Device	preset by OpenDevice
    io_Unit		preset by OpenDevice
    io_Command	IND_REMHANDLER
    io_Data		a pointer to the interrupt structure.

   NOTES
    This command is not immediate

 input.device/IND_SETMPORT                           input.device/IND_SETMPORT

   NAME
    IND_SETMPORT -- Set the current mouse port

   FUNCTION
    This command sets the gameport port at which the mouse is
    connected.

   IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Device	preset by the call to OpenDevice
    io_Unit		preset by the call to OpenDevice
    io_Command	IND_SETMPORT
    io_Flags	IOB_QUICK set if quick I/O is possible
    io_Length	1
    io_Data		a pointer to a byte that is either 0 or 1,
            indicating that mouse input should be obtained
            from either the left or right controller port,
            respectively.

 input.device/IND_SETMTRIG                           input.device/IND_SETMTRIG

   NAME
    IND_SETMTRIG -- Set the conditions for a mouse port report

   FUNCTION
    This command sets what conditions must be met by a mouse
    before a pending Read request will be satisfied.  The trigger
    specification is that used by the gameport device.

   IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Device	preset by the call to OpenDevice
    io_Unit		preset by the call to OpenDevice
    io_Command	IND_SETMTRIG
    io_Flags	IOB_QUICK set if quick I/O is possible
    io_Length	sizeof(gameportTrigger)
    io_Data		a structure of type GameportTrigger, which
            has the following elements
        gpt_Keys -
            GPTB_DOWNKEYS set if button down transitions
            trigger a report, and GPTB_UPKEYS set if button up
            transitions trigger a report
        gpt_Timeout	-
            a time which, if exceeded, triggers a report;
            measured in vertical blank units (60/sec)
        gpt_XDelta	-
            a distance in x which, if exceeded, triggers a
            report
        gpt_YDelta	-
            a distance in x which, if exceeded, triggers a
            report

 input.device/IND_SETMTYPE                           input.device/IND_SETMTYPE

   NAME
    IND_SETMTYPE -- Set the current mouse port controller type

   FUNCTION
    This command sets the type of device at the mouse port, so
    the signals at the port may be properly interpreted.

   IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Device	preset by the call to OpenDevice
    io_Unit		preset by the call to OpenDevice
    io_Command	IND_SETMTYPE
    io_Flags	IOB_QUICK set if quick I/O is possible
    io_Length	1
    io_Data		the address of the byte variable describing
            the controller type, as per the equates in
            the gameport include file

 input.device/IND_SETPERIOD                         input.device/IND_SETPERIOD

   NAME
    IND_SETPERIOD -- Set the key repeat period

   FUNCTION
    This command sets the period at which a repeating key repeats.

    This command always executes immediately.

   IO REQUEST - a timerequest
    tr_node.io_Message	mn_ReplyPort set if quick I/O is not possible
    tr_node.io_Device	preset by the call to OpenDevice
    tr_node.io_Unit		preset by the call to OpenDevice
    tr_node.io_Command	IND_SETPERIOD
    tr_node.io_Flags	IOB_QUICK set if quick I/O is possible
    tr_time.tv_secs		the repeat period seconds
    tr_time.tv_micro	the repeat period microseconds

 input.device/IND_SETTHRESH                         input.device/IND_SETTHRESH

   NAME
    IND_SETTHRESH -- Set the key repeat threshold

   FUNCTION
    This command sets the time that a key must be held down before
    it can repeat.  The repeatability of a key may be restricted
    (as, for example, are the shift keys).

    This command always executes immediately.

   IO REQUEST - a timerequest
    tr_node.io_Message	mn_ReplyPort set if quick I/O is not possible
    tr_node.io_Device	preset by the call to OpenDevice
    tr_node.io_Unit		preset by the call to OpenDevice
    tr_node.io_Command	IND_SETTHRESH
    tr_node.io_Flags	IOB_QUICK set if quick I/O is possible
    tr_time.tv_secs		the threshold seconds
    tr_time.tv_micro	the threshold microseconds

 input.device/IND_WRITEEVENT                       input.device/IND_WRITEEVENT

   NAME
    IND_WRITEEVENT -- Propagate an input event to all handlers

   FUNCTION

   IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Device	preset by the call to OpenDevice
    io_Unit		preset by the call to OpenDevice
    io_Command	IND_WRITEEVENT
    io_Flags	IOB_QUICK set if quick I/O is possible
    io_Length	should be sizeof(struct InputEvent)
    io_Data		a pointer to the struct InputEvent:
        ie_NextEvent
            will be ignored.
        ie_Class
        ie_SubClass
        ie_Code
        ie_Qualifier
        ie_X, ie_Y
            as desired
        ie_TimeStamp
            will be set by this call (V36)

   NOTES
    The contents of the input event are destroyed.

    This function was documented in V34 and earlier to allow
    chaining of events via ie_NextEvent.  The implementation
    never allowed that.  The documentation now reflects this.

    ie_TimeStamp is set only in V36 and later.  Software written
    to run on earlier versions should set this field to the
    current time.

 input.device/PeekQualifier                         input.device/PeekQualifier

   NAME
    PeekQualifier -- get the input device's current qualifiers (V36)

   SYNOPSIS
    qualifier = PeekQualifier()
    d0

    UWORD PeekQualifier( VOID );

   FUNCTION
    This function takes a snapshot of what the input device thinks
    the current qualifiers are.

   RESULTS
    qualifier - a word with the following bits set according to
        what the input device knows their state to be:
        IEQUALIFIER_LSHIFT, IEQUALIFIER_RSHIFT,
        IEQUALIFIER_CAPSLOCK, IEQUALIFIER_CONTROL,
        IEQUALIFIER_LALT, IEQUALIFIER_RALT,
        IEQUALIFIER_LCOMMAND, IEQUALIFIER_RCOMMAND,
        IEQUALIFIER_LEFTBUTTON, IEQUALIFIER_RBUTTON,
        IEQUALIFIER_MIDBUTTON

   NOTE
    This function is new for V36.

   SEE ALSO
    devices/inputevent.h


Text_Autodocs/parallel.doc

TABLE OF CONTENTS

parallel.device/CMD_CLEAR
parallel.device/CMD_FLUSH
parallel.device/CMD_READ
parallel.device/CMD_RESET
parallel.device/CMD_START
parallel.device/CMD_STOP
parallel.device/CMD_WRITE
parallel.device/OpenDevice
parallel.device/PDCMD_QUERY
parallel.device/PDCMD_SETPARAMS
 parallel.device/CMD_CLEAR                           parallel.device/CMD_CLEAR

   NAME
    Clear -- clear the parallel port buffer

   FUNCTION
    This command just RTS's (no buffer to clear)

   IO REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       set by OpenDevice
    io_Unit         set by OpenDevice
    io_Command      CMD_CLEAR (05)

 parallel.device/CMD_FLUSH                           parallel.device/CMD_FLUSH

   NAME
    Flush -- clear all queued I/O requests for the parallel port

   FUNCTION
    This command purges the read and write request queues for the
    parallel device. The currently active request is not purged.

   IO REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       set by OpenDevice
    io_Unit         set by OpenDevice
    io_Command      CMD_FLUSH (08)

 parallel.device/CMD_READ                             parallel.device/CMD_READ

   NAME
    Read -- read input from parallel port

   FUNCTION
    This command causes a stream of characters to be read from the
    parallel I/O register. The number of characters is specified in
    io_Length. The EOF and EOL modes are supported, but be warned that
    using these modes can result in a buffer overflow if the proper
    EOL or EOF character is not received in time. These modes should
    be used only when the sender and receiver have been designed to
    cooperate. A safety guard can be implemented to EOF by setting
    io_Length to a maximum allowed value. That cannot be done with EOL
    since the EOL mode is identified by io_Length=-1.

    The parallel.device has no internal buffer; if no read request has
    been made, pending input (i.e. handshake request) is not
    acknowledged.

   IO REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       set by OpenDevice
    io_Unit         set by OpenDevice
    io_Command      CMD_READ (02)
    io_Flags        If IOF_QUICK is set, driver will attempt Quick IO
    io_Length       number of characters to receive.
    io_Data         pointer where to put the data.

   RESULTS
    io_Error -- if the Read succeded, then io_Error will be null.
        If the Read failed, then io_Error will contain an error code.

   SEE ALSO
    parallel.device/PDCMD_SETPARAMS

 parallel.device/CMD_RESET                           parallel.device/CMD_RESET

   NAME
    Reset -- reinitializes the parallel device

   FUNCTION
    This command resets the parallel device to its freshly initialized
    condition. It aborts all I/O requests both queued and current and
    sets the devices's flags and parameters to their boot-up time
    default values. At boot-up time the PTermArray is random, and it
    will be so also here.

   IO REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       set by OpenDevice
    io_Unit         set by OpenDevice
    io_Command      CMD_RESET (01)

   RESULTS
    Error -- if the Reset succeded, then io_Error will be null.
             if the Reset failed, then the io_Error will be non-zero.

 parallel.device/CMD_START                           parallel.device/CMD_START

   NAME
    Start -- restart paused I/O over the parallel port

   FUNCTION
    This command restarts the current I/O activity on the parallel
    port by reactivating the handshaking sequence.

   IO REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       set by OpenDevice
    io_Unit         set by OpenDevice
    io_Command      CMD_START (07)

   SEE ALSO
    parallel.device/CMD_STOP

 parallel.device/CMD_STOP                             parallel.device/CMD_STOP

   NAME
    Stop -- pause current activity on the parallel device

   FUNCTION
    This command halts the current I/O activity on the parallel
    device by discontinuing the handshaking sequence. The stop and
    start commands may not be nested.

   IO REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       set by OpenDevice
    io_Unit         set by OpenDevice
    io_Command      CMD_STOP (06)

   SEE ALSO
    parallel.device/CMD_START

 parallel.device/CMD_WRITE                           parallel.device/CMD_WRITE

   NAME
    Write -- send output to parallel port

   FUNCTION
    This command causes a stream of characters to be written to the
    parallel output register. The number of characters is specified in
    io_Length, unless -1 is used, in which case output is sent until
    a zero byte occurs in the data. This is independent of, and may be
    used simultaneously with setting the EOFMODE in io_ParFlags and using
    the PTermArray to terminate the read or write.

   IO REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       set by OpenDevice
    io_Unit         set by OpenDevice
    io_Command      CMD_WRITE (03)
    io_Flags        If IOF_QUICK is set, driver will attempt Quick IO
    io_Length       number of characters to transmit, or if set
                    to -1 send until zero byte encountered
    io_Data         pointer to block of data to transmit

   RESULTS
    io_Error -- If the Write succeded, then io_Error will be null.
         If the Write failed, then io_Error will contain an error code.

   SEE ALSO
    parallel.device/PDCMD_SETPARAMS

 parallel.device/OpenDevice                         parallel.device/OpenDevice

   NAME
    Open -- a request to open the parallel port

   SYNOPSIS
    error = OpenDevice("parallel.device", unit, ioExtPar, flags)
    D0                  A0                D0    A1        D1

   FUNCTION
    This function allows the requestor software access to the parallel
    device.  Unless the shared-access bit (bit 5 of io_ParFlags) is
    set, exclusive use is granted and no other access is allowed
    until the owner closes the device.

    A FAST_MODE, can be specified (bit 3 of io_Parflags) to speed up
    transfers to high-speed printers. Rather than waiting for the printer
    to acknowledge a character using the *ACK interrupt, this mode will
    send out data as long as the BUSY signal is low. The printer must be
    able to raise the BUSY signal within 3 micro-seconds on A2630s,
    otherwise data will be lost. Should be used only in an exclusive-
    access Open().

    A SLOWMODE mode can be specified (bit 4 of io_ParFlags) when very
    slow printers are used. If the printer acknowledges data at less
    than 5000 bytes per second, then this mode will actually save CPU
    time, although it consumes much more with high-speed printers.

    The PTermArray of the ioExtPar is initialized only if the EOFMODE
    bit (bit 1 of io_ParFlags) is set. The PTermArray can be further
    modified using the PDCMD_SETPARAMS command.

   INPUTS
    "parallel.device" - a pointer to literal string "parallel.device"
    unit - Must be zero for future compatibility
    ioExtPar - pointer to an IO Request block of structure IOExtPar to
           be initialized by the Open() function. The io_ParFlags
           field must be set as desired.
    flags - Must be zero for future compatibility

   RESULTS
    d0 -- same as io_Error
    io_Error -- if the Open succeded, then io_Error will be null.
            If the Open failed, then io_Error will be non-zero.

   SEE ALSO
    exec/CloseDevice

 parallel.device/PDCMD_QUERY                       parallel.device/PDCMD_QUERY

   NAME
    Query -- query parallel port/line status

   FUNCTION
    This command return the status of the parallel port lines and
    registers.

   IO REQUEST
    io_Message      must have mn_ReplyPort initialized
    io_Device       set by OpenDevice
    io_Unit         set by OpenDevice
    io_Command      PDCMD_QUERY (09)

   RESULTS
    io_Status        BIT  ACTIVE  FUNCTION

                     0     high   printer busy toggle (offline)
                     1     high   paper out
                     2     high   printer selected on the A1000
                                  printer selected & serial "Ring
                                  Indicator" on the A500/A2000
                                  Use care when making cables.
                     3      -     read=0,write=1
                   4-7            reserved

   BUGS
    In a earlier version of this AutoDoc, BUSY and PSEL were reversed.
    The function has always been correct.

 parallel.device/PDCMD_SETPARAMS               parallel.device/PDCMD_SETPARAMS

   NAME
    SetParams -- change parameters for the parallel device

   FUNCTION
    This command allows the caller to change the EOFMODE parameter for
    the parallel port device. It will disallow changes if any reads or
    writes are active or queued.

    The PARB_EOFMODE bit of io_ParFlags controlls whether the
    io_PTermArray is to be used as an additional termination criteria
    for reads and writes.  It may be set directly without a call to
    SetParams, setting it here performs the additional service of
    copying the PTermArray into the device default array which is used
    as the initial array for subsequent device opens. The Shared bit
    can be changed here, and overrides the current device access mode
    set at OpenDevice time.

   IO REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       preset by OpenDevice
    io_Unit         preset by OpenDevice
    io_Command      PDCMD_SETPARAMS (0A)
              NOTE that the following fields of your IORequest
                    are filled by Open to reflect the parallel device's
                    current configuration.
    io_PExtFlags    must be set to zero, unless used
    io_ParFlags     see definition in parallel.i or parallel.h
                    NOTE that x00 yields exclusive access, PTermArray
                    inactive.
    io_PTermArray   ASCII descending-ordered 8-byte array of
                    termination characters. If less than 8 chars
                    used, fill out array w/lowest valid value.
                    Terminators are used only if EOFMODE bit of
                    io_Parflags is set. (e.g. x512F040303030303 )
                    This field is filled on OpenDevice only if the
                    EOFMODE bit is set.

   RESULTS
    io_Error -- if the SetParams succeded, then io_Error will be null.
                if the SetParams failed, then io_Error will be non-zero.


Text_Autodocs/timer.doc

TABLE OF CONTENTS

timer.device/--background--
timer.device/AbortIO
timer.device/AddTime
timer.device/CmpTime
timer.device/GetSysTime
timer.device/ReadEClock
timer.device/SubTime
timer.device/TR_ADDREQUEST
timer.device/TR_GETSYSTIME
timer.device/TR_SETSYSTIME
 timer.device/--background--                       timer.device/--background--

   TIMER REQUEST
    A time request is a non standard IO Request.  It has an IORequest
    followed by a timeval structure or an eclockval structure.

   TIMEVAL
    A timeval structure consists of two longwords.  The first is
    the number of seconds, the latter is the fractional number
    of microseconds.  The microseconds must always be "normalized"
    e.g. the longword must be between 0 and one million.

   ECLOCKVAL
    A eclockval structure consists of two longwords.  The first is
    the high order 32 bits of a 64 bit number and the second is the
    the low order 32 bits.  The 64 bit number is a count of "E" clock
    ticks.  The "E" clock frequency is related to the master clock
    frequency of the machine and can be determined by calling the
    ReadEClock() library like call.

   UNITS
    The timer contains five units -- two designed to accuratly measure
    short intervals, one that has little system overhead and is very
    stable over time, and two that work like an alarm clock.

   UNIT_MICROHZ
    This unit uses the programmable timers in the 8520s to keep track
    of its time.  It has precision down to about 2 microseconds, but
    will drift as system load increases.  The accuracy of this unit
    is the same as that of the master clock of the machine.  This unit
    uses a timeval in its timerequest.

   UNIT_VBLANK
    This unit uses a strobe from the power supply to keep track of its
    time or the "E" clock on machines without power supply strobes.
    It is very stable over time, but only has a resolution of that of
    the vertical blank interrupt.  This unit is very cheap to use, and
    should be used by those who are waiting for long periods of time
    (typically 1/2 second or more).  This unit uses a timeval in its
    timerequest.

   UNIT_ECLOCK
    This unit is exacly the same as UNIT_MICROHZ except that it uses
    an eclockval instead of a timeval in its timerequest.

   UNIT_WAITUNTIL
    This unit waits until the systime is greater than or equal to the
    time in the timeval in the timerequest.  This unit has the same
    resolution and accuracy as that of UNIT_VBLANK.

   UNIT_WAITECLOCK
    This unit waits until the E-Clock value as returned by ReadEClock()
    is greater than or equal to the eclockval in the timerequest. This
    unit has the same resolution and accuracy as that of UNIT_ECLOCK.

   LIBRARY
    In addition to the normal device calls, the timer also supports
    several direct, library like calls.

   BUGS
    In the V1.2/V1.3 release, the timer device has problems with
    very short time requests.  When one of these is made, other
    timer requests may be finished inaccurately.  A side effect
    is that AmigaDOS requests such as "Delay(0);" or
    "WaitForChar(x,0);" are unreliable.

 timer.device/AbortIO                                     timer.device/AbortIO

   NAME
    AbortIO -- Remove an existing timer request.

   SYNOPSIS
    error = AbortIO( timerequest )
    D0               A1

    LONG AbortIO( struct timerequest * );

   FUNCTION
    This is an exec.library call.

    This routine removes a timerquest from the timer.  It runs in
    the context of the caller.

   INPUTS
    timerequest - the timer request to be aborted

   RETURNS
    0  if the request was aborted, io_Error will also be set to
        IOERR_ABORTED.
    -1 otherwise

   NOTES
    This function may be called from interrupts.

   SEE ALSO
    exec.library/AbortIO()

   BUGS

 timer.device/AddTime                                     timer.device/AddTime

   NAME
    AddTime -- Add one time request to another.

   SYNOPSIS
    AddTime( Dest, Source )
             A0    A1

    void AddTime( struct timeval *, struct timeval *);

   FUNCTION
    This routine adds one timeval structure to another.  The
    results are stored in the destination (Dest + Source -> Dest)

    A0 and A1 will be left unchanged

   INPUTS
    Dest, Source -- pointers to timeval structures.

   NOTES
    This function may be called from interrupts.

   SEE ALSO
    timer.device/CmpTime(),
    timer.device/SubTime()

   BUGS

 timer.device/CmpTime                                     timer.device/CmpTime

   NAME
    CmpTime -- Compare two timeval structures.

   SYNOPSIS
    result = CmpTime( Dest, Source )
    D0                A0    A1

    LONG CmpTime( struct timeval *, struct timeval *);

   FUNCTION
    This routine compares timeval structures

    A0 and A1 will be left unchanged

   INPUTS
    Dest, Source -- pointers to timeval structures.

   RESULTS
    result will be   0 if Dest has same time as source
                    -1 if Dest has more time than source
                    +1 if Dest has less time than source

   NOTES
    This function may be called from interrupts.

   SEE ALSO
    timer.device/AddTime(),
    timer.device/SubTime()

   BUGS
    Older version of this document had the sense of the return
    codes wrong; the code hasn't changed but the document has.

 timer.device/GetSysTime                               timer.device/GetSysTime

   NAME
    GetSysTime -- Get the system time. (V36)

   SYNOPSIS
    GetSysTime( Dest )
                A0

    void GetSysTime( struct timeval * );

   FUNCTION
    Ask the system what time it is.  The system time starts off at
    zero at power on, but may be initialized via the TR_SETSYSTIME
    timer.device command.

    System time is monotonocally increasing and guarenteed to be
    unique (except when the system time is set back).

    A0 will be left unchanged.

    This function is less expensive to use than the TR_GETSYSTIME
    IORequest.

   INPUTS
    Dest -- pointer to a timeval structure to hold the system time.

   RESULTS
    Dest -- the timeval structure will contain the system time.

   NOTES
    This function may be called from interrupts.

   SEE ALSO
    timer.device/TR_GETSYSTIME,
    timer.device/TR_SETSYSTIME,

   BUGS

 timer.device/ReadEClock                               timer.device/ReadEClock

   NAME
    ReadEClock -- Get the current value of the E-Clock. (V36)

   SYNOPSIS
    E_Freq = ReadEClock( Dest )
    D0                   A0

    ULONG ReadEClock ( struct EClockVal * );

   FUNCTION
    This routine calculates the current 64 bit value of the E-Clock
    and stores it in the destination EClockVal structure. The count
    rate of the E-Clock is also returned.

    A0 will be left unchanged

    This is a low overhead function designed so that very short
    intervals may be timed.

   INPUTS
    Dest -- pointer to an EClockVal structure.

   RETURNS
    Dest -- the EClockVal structure will contain the E-Clock time
    E_Freq -- The count rate of the E-Clock (tics/sec).

   NOTES
    This function may be called from interrupts.

   SEE ALSO

   BUGS

 timer.device/SubTime                                     timer.device/SubTime

   NAME
    SubTime -- Subtract one time request from another.

   SYNOPSIS
    SubTime( Dest, Source )
             A0    A1

    void SubTime( struct timeval *, struct timeval *);

   FUNCTION
    This routine subtracts one timeval structure from another.  The
    results are stored in the destination (Dest - Source -> Dest)

    A0 and A1 will be left unchanged

   INPUTS
    Dest, Source -- pointers to timeval structures.

   NOTES
    This function may be called from interrupts.

   SEE ALSO
    timer.device/AddTime(),
    timer.device/CmpTime()

   BUGS

 timer.device/TR_ADDREQUEST                         timer.device/TR_ADDREQUEST

   NAME
    TR_ADDREQUEST -- Submit a request to wait a period of time.

   FUNCTION
    Ask the timer to wait a specified amount of time before
    replying the timerequest.

    The message may be forced to finish early with an
    AbortIO()/WaitIO() pair.

   TIMER REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       preset by timer in OpenDevice
    io_Unit         preset by timer in OpenDevice
    io_Command      TR_ADDREQUEST
    io_Flags        IOF_QUICK permitted (but ignored)
    tr_time         a timeval structure specifying how long the
                        device will wait before replying

   RESULTS
    tr_time         will be zeroed

   NOTES
    This function may be called from interrupts.

    Previous to 2.0, the tr_time field was documented as containing
    junk when the timerequest was returned.

   SEE ALSO
    timer.device/AbortIO(),
    timer.device/TimeDelay(),

   BUGS

 timer.device/TR_GETSYSTIME                         timer.device/TR_GETSYSTIME

   NAME
    TR_GETSYSTIME -- get the system time.

   FUNCTION
    Ask the system what time it is.  The system time starts off at
    zero at power on, but may be initialized via the TR_SETSYSTIME
    call.

    System time is monotonically increasing, and guaranteed to be
    unique (except when the system time is set backwards).

   TIMER REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       preset by timer in OpenDevice
    io_Unit         preset by timer in OpenDevice
    io_Command      TR_GETSYSTIME
    io_Flags        IOF_QUICK permitted

   RESULTS
    tr_time         a timeval structure with the current system
                        time

   NOTES
    This function may be called from interrupts.

   SEE ALSO
    timer.device/TR_SETSYSTIME,
    timer.device/GetSysTime(),

   BUGS

 timer.device/TR_SETSYSTIME                         timer.device/TR_SETSYSTIME

   NAME
    TR_SETSYSTIME -- Set the system time.

   FUNCTION
    Set the system idea of what time it is.  The system starts out
    at time "zero" so it is safe to set it forward to the real
    time.  However, care should be taken when setting the time
    backwards.  System time is generally expected to monotonically
    increasing.

   TIMER REQUEST
    io_Message      mn_ReplyPort initialized
    io_Device       preset by timer in OpenDevice
    io_Unit         preset by timer in OpenDevice
    io_Command      TR_GETSYSTIME
    io_Flags        IOF_QUICK permitted
    tr_time         a timeval structure with the current system
                        time

   RESULTS
    tr_time         will contain junk

   NOTES
    This function may be called from interrupts.

   SEE ALSO
    timer.device/TR_GETSYSTIME,
    timer.device/GetSysTime(),

   BUGS


Text_Autodocs/console.doc

TABLE OF CONTENTS

console.device/CD_ASKDEFAULTKEYMAP
console.device/CD_ASKKEYMAP
console.device/CD_SETDEFAULTKEYMAP
console.device/CD_SETKEYMAP
console.device/CDInputHandler
console.device/CMD_CLEAR
console.device/CMD_READ
console.device/CMD_WRITE
console.device/OpenDevice
console.device/RawKeyConvert
 console.device/CD_ASKDEFAULTKEYMAP         console.device/CD_ASKDEFAULTKEYMAP

    NAME
    CD_ASKDEFAULTKEYMAP -- get the current default keymap

    FUNCTION
    Fill the io_Data buffer with the current console device
    default keymap, which is used to initialize console unit
    keymaps when opened, and by RawKeyConvert with a null
    keyMap parameter.

   IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Device	preset by the call to OpenDevice
    io_Unit		preset by the call to OpenDevice
    io_Command	CD_ASKDEFAULTKEYMAP
    io_Flags	IOF_QUICK if quick I/O possible, else zero
    io_Length	sizeof(*keyMap)
    io_Data		struct KeyMap *keyMap
            pointer to a structure that describes
            the raw keycode to byte stream conversion.

    RESULTS
    This function sets the io_Error field in the IOStdReq, and fills
    the structure pointed to by io_Data with the current device
    default key map.

    BUGS

    SEE ALSO
    exec/io.h, devices/keymap.h, devices/console.h

 console.device/CD_ASKKEYMAP                       console.device/CD_ASKKEYMAP

   NAME
    CD_ASKKEYMAP -- Get the current key map structure for this console.

    FUNCTION
    Fill the io_Data buffer with the current KeyMap structure in
    use by this console unit.

    IO REQUEST INPUT
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Device	preset by the call to OpenDevice
    io_Unit		preset by the call to OpenDevice
    io_Command	CD_ASKKEYMAP
    io_Flags	IOF_QUICK if quick I/O possible, else zero
    io_Length	sizeof(*keyMap)
    io_Data		struct KeyMap *keyMap
            pointer to a structure that describes
            the raw keycode to byte stream conversion.

    IO REQUEST RESULT
    This function sets the io_Error field in the IOStdReq, and fills
    the structure the structure pointed to by io_Data with the current
     key map.

    SEE ALSO
    exec/io.h, devices/keymap.h, devices/console.h

 console.device/CD_SETDEFAULTKEYMAP         console.device/CD_SETDEFAULTKEYMAP

    NAME
    CD_SETDEFAULTKEYMAP -- set the current default keymap

    FUNCTION
    This console command copies/uses the keyMap structure pointed to
    by io_Data to the console device default keymap, which is used
    to initialize console units when opened, and by RawKeyConvert
    with a null keyMap parameter.

    IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Device	preset by the call to OpenDevice
    io_Unit		preset by the call to OpenDevice
    io_Command	CD_SETDEFAULTKEYMAP
    io_Flags	IOF_QUICK if quick I/O possible, else zero
    io_Length	sizeof(*keyMap)
    io_Data		struct KeyMap *keyMap
            pointer to a structure that describes
            the raw keycode to byte stream conversion.

    RESULTS
    This function sets the io_Error field in the IOStdReq, and fills
    the current device default key map from the structure pointed to
    by io_Data.

    BUGS
    As of V36, this command no longer copies the keymap structure,
    and the keymap must remain in memory until the default key map
    is changed.  In general there is no reason for applications to
    use this command.  The default key map will generally be set by
    the user using a system provided command/tool.

    SEE ALSO
    exec/io.h, devices/keymap.h, devices/console.h

 console.device/CD_SETKEYMAP                       console.device/CD_SETKEYMAP

    NAME
    CD_SETKEYMAP -- set the current key map structure for this console

    FUNCTION
    Set the current KeyMap structure used by this console unit to
    the structure pointed to by io_Data.

    IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Device	preset by the call to OpenDevice
    io_Unit		preset by the call to OpenDevice
    io_Command	CD_SETKEYMAP
    io_Flags	IOF_QUICK if quick I/O possible, else zero
    io_Length	sizeof(*keyMap)
    io_Data		struct KeyMap *keyMap
            pointer to a structure that describes
            the raw keycode to byte stream conversion.

    RESULTS
    This function sets the io_Error field in the IOStdReq, and fills
    the current key map from the structure pointed to by io_Data.

    BUGS

    SEE ALSO
    exec/io.h, devices/keymap.h, devices/console.h

 console.device/CDInputHandler                   console.device/CDInputHandler

    NAME
    CDInputHandler -- handle an input event for the console device

    SYNOPSIS
    events = CDInputHandler(events, consoleDevice)
               a0      a1

    FUNCTION
    Accept input events from the producer, which is usually the
    rom input.task.

    INPUTS
    events - a pointer to a list of input events.
    consoleDevice - a pointer to the library base address of the
        console device.  This has the same value as ConsoleDevice
        described below.

    RESULTS
    events - a pointer to a list of input events not used by this
        handler.

    NOTES
    This function is available for historical reasons.  It is
    preferred that input events be fed to the system via the
    WriteEvent command of the input.device.

    This function is different from standard device commands in
    that it is a function in the console device library vectors.
    In order to obtain a valid library base pointer for the
    console device (a.k.a. ConsoleDevice) call
    OpenDevice("console.device", -1, IOStdReq, 0),
    and then grab the io_Device pointer field out of the IOStdReq
    and use as ConsoleDevice.

    BUGS

    SEE ALSO
    input.device

 console.device/CMD_CLEAR                             console.device/CMD_CLEAR

    NAME
    CMD_CLEAR -- Clear console input buffer.

    FUNCTION
    Remove from the console input buffer any reports waiting to
    satisfy read requests.

    IO REQUEST INPUT
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Device	preset by the call to OpenDevice
    io_Unit		preset by the call to OpenDevice
    io_Command	CMD_CLEAR
    io_Flags	IOB_QUICK set if quick I/O is possible, else 0

    SEE ALSO
    exec/io.h, devices/console.h

 console.device/CMD_READ                               console.device/CMD_READ

   NAME
    CMD_READ -- return the next input from the keyboard

   FUNCTION
    Read the next input, generally from the keyboard.  The form of
    this input is as an ANSI byte stream: i.e. either ASCII text
    or control sequences.  Raw input events received by the
    console device can be selectively filtered via the aSRE and aRRE
    control sequences (see the write command).  Keys are converted
    via the keymap associated with the unit, which is modified
    with AskKeyMap and SetKeyMap

    If, for example, raw keycodes had been enabled by writing
    <CSI>1{ to the console (where <CSI> is $9B or Esc[), keys
    would return raw keycode reports with the information from
    the input event itself, in the form:
    <CSI>1;0;<keycode>;<qualifiers>;0;0;<seconds>;<microseconds>q

    If there is no pending input, this command will not be
    satisfied, but if there is some input, but not as much as can
    fill io_Length, the request will be satisfied with the input
    currently available.

    IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Device	preset by the call to OpenDevice
    io_Unit		preset by the call to OpenDevice
    io_Command	CMD_READ
    io_Flags	IOF_QUICK if quick I/O possible, else zero
    io_Length	sizeof(*buffer)
    io_Data		char buffer[]
            a pointer to the destination for the characters to read
            from the keyboard.

   RESULTS
    This function sets the error field in the IOStdReq, and fills
        in the io_Data area with the next input, and io_Actual with
        the number of bytes read.

    BUGS

    SEE ALSO
    exec/io.h, devices/console.h

 console.device/CMD_WRITE                             console.device/CMD_WRITE

   NAME
    CMD_WRITE -- Write ANSI text to the console display.

   FUNCTION
    Write a text record to the display.  Interpret the ANSI
    control characters in the data as described below.  Note
    that the RPort of the console window is in use while this
    write command is pending.

   IO REQUEST INPUT
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Device	preset by the call to OpenDevice
    io_Unit		preset by the call to OpenDevice
    io_Command	CMD_WRITE
    io_Flags	IOF_QUICK if quick I/O possible, else zero
    io_Length	sizeof(*buffer), or -1 if io_Data is null
            terminated
    io_Data		a pointer to a buffer containing the ANSI text
            to write to the console device.

   IO REQUEST RESULTS
    io_Error	the error result (no errors are reported as of V36)
    io_Actual	the number of bytes written from io_Data
    io_Length	zero
    io_Data		original io_Data plus io_Actual

   ANSI CODES SUPPORTED

    Codes are specified in the standard fashion for ANSI documents,
    as the two 4 bit nibbles that comprise the character code,
    high nibble first, separated by a slash.  Thus 01/11 (ESC) is
    a character with the hex value 1B (or the decimal value 27).

    A character on the Amiga falls into one of the following four
    ranges:
    00/ 0-01/15	C0: ASCII control characters.  See below.
    02/ 0-07/15	G0: ASCII graphic characters.  These characters
            have an image that is displayed.  Note that the
            DEL character is displayed by the Console Device:
            it is not treated as control character here.
    08/ 0-09/15	C1: ANSI 3.41 control characters.  See below.
    10/ 0-15/15	G1: ECMA 94 Latin 1 graphic characters.

    Independent Control Functions (no introducer) --
    Code	Name	Definition
    -----	---	----------------------------------------------
    00/ 7	BEL	BELL: actually an Intuition DisplayBeep()
    00/ 8	BS	BACKSPACE
    00/ 9	HT	HORIZONTAL TAB
    00/10	LF	LINE FEED
    00/11	VT	VERTICAL TAB
    00/12	FF	FORM FEED
    00/13	CR	CARRIAGE RETURN
    00/14	SO	SHIFT OUT: causes all subsequent G0 (ASCII)
            characters to be shifted to G1 (ECMA 94/1)
            characters.
    00/15	SI	SHIFT IN: cancels the effect of SHIFT OUT.
    01/11	ESC	ESCAPE

    Code or Esc Name Definition
    -----	--- ---- ---------------------------------------------
    08/ 4	D   IND	 INDEX: move the active position down one line.
    08/ 5	E   NEL	 NEXT LINE
    08/ 8	H   HTS  HORIZONTAL TABULATION SET
    08/13	M   RI	 REVERSE INDEX
    09/11	[   CSI	 CONTROL SEQUENCE INTRODUCER: see next list

    ISO Compatible Escape Sequences (introduced by Esc) --
    Esc   Name Definition
    ----- ---- ---------------------------------------------------
    c     RIS  RESET TO INITIAL STATE: reset the console display.

    Control Sequences, with the number of indicated parameters.
    i.e. <CSI><parameters><control sequence letter(s)>.  Note the
    last entries consist of a space and a letter.  CSI is either
    9B or Esc[.  A minus after the number of parameters (#p)
    indicates less is valid.  Parameters are separated by
    semicolons, e.g. Esc[14;80H sets the cursor position to row
    14, column 80.
    CSI #p	Name Definition
    --- --- ---- -------------------------------------------------
    @   1-	ICH  INSERT CHARACTER
    A   1-	CUU  CURSOR UP
    B   1-	CUD  CURSOR DOWN
    C   1-	CUF  CURSOR FORWARD
    D   1-	CUB  CURSOR BACKWARD
    E   1-	CNL  CURSOR NEXT LINE
    F   1-	CPL  CURSOR PRECEDING LINE
    H   2-	CUP  CURSOR POSITION
    I   1-	CHT  CURSOR HORIZONTAL TABULATION
    J   1-	ED   ERASE IN DISPLAY (only to end of display)
    K   1-	EL   ERASE IN LINE (only to end of line)
    L   1-	IL   INSERT LINE
    M   1-	DL   DELETE LINE
    P   1-	DCH  DELETE CHARACTER
    R   2	CPR  CURSOR POSITION REPORT (in Read stream only)
    S   1-	SU   SCROLL UP
    T   1-	SD   SCROLL DOWN
    W   n	CTC  CURSOR TABULATION CONTROL
    Z   1-	CBT  CURSOR BACKWARD TABULATION
    f   2-	HVP  HORIZONTAL AND VERTICAL POSITION
    g   1-	TBC  TABULATION CLEAR
    h   n	SM   SET MODE: see modes below.
    l   n	RM   RESET MODE: see modes below.
    m   n	SGR  SELECT GRAPHIC RENDITION
    n   1-	DSR  DEVICE STATUS REPORT
    t   1-	aSLPP SET PAGE LENGTH (private Amiga sequence)
    u   1-	aSLL SET LINE LENGTH (private Amiga sequence)
    x   1-	aSLO SET LEFT OFFSET (private Amiga sequence)
    y   1-	aSTO SET TOP OFFSET (private Amiga sequence)
    {   n	aSRE SET RAW EVENTS (private Amiga sequence)
    |   8	aIER INPUT EVENT REPORT (private Amiga Read sequence)
    }   n	aRRE RESET RAW EVENTS (private Amiga sequence)
    ~   1	aSKR SPECIAL KEY REPORT (private Amiga Read sequence)
     p  1-	aSCR SET CURSOR RENDITION (private Amiga sequence)
     q  0	aWSR WINDOW STATUS REQUEST (private Amiga sequence)
     r  4	aWBR WINDOW BOUNDS REPORT (private Amiga Read sequence)
     v  1	aRAV RIGHT AMIGA V PRESS (private Amiga Read sequence-V37)

    Modes, set with <CSI><mode-list>h, and cleared with
    <CSI><mode-list>l, where the mode-list is one or more of the
    following parameters, separated by semicolons --
    Mode	Name Definition
    ------- ---- -------------------------------------------------
    20	LNM  LINEFEED NEWLINE MODE: if a linefeed is a newline
    >1	ASM  AUTO SCROLL MODE: if scroll at bottom of window
    ?7	AWM  AUTO WRAP MODE: if wrap at right edge of window

    NOTES
    The console.device recognizes these SGR sequences.
    Note that some of these are new to V36.

    SGR (SELECT GRAPHICS RENDITION)
        Selects colors, and other display characteristics
        for text.

    Syntax:
        <ESC>[graphic-rendition...m

    Example:
        <ESC>[1;7m   (sets bold, and reversed text)

    Parameters:

        0	- Normal colors, and attributes
        1	- Set bold
        2	- Set faint (secondary color)
        3	- Set italic
        4	- Set underscore
        7	- Set reversed character/cell colors
        8	- Set concealed mode.
        22	- Set normal color, not bold	(V36)
        23	- Italic off			(V36)
        24	- Underscore off		(V36)
        27	- Reversed off			(V36)
        28	- Concealed off			(V36)

        30-37	- Set character color
        39	- Reset to default character color

        40-47	- Set character cell color
        49	- Reset to default character cell color

        >0-7	- Set background color		(V36)
              Used to set the background color before
              any text is written.  The numeric parameter
              is prefixed by ">".  This also means that if
              you issue an SGR command with more than one
              parameter, you must issue the digit only
              parameters first, followed by any prefixed
              parameters.

    BUGS
    Does not correctly display cursor in SuperBitMap layers for
    versions prior to V36.

    SEE ALSO
    ROM Kernal Manual (Volume 1), exec/io.h

 console.device/OpenDevice                           console.device/OpenDevice

    NAME
    OpenDevice -- a request to open a Console device

    SYNOPSIS
    error = OpenDevice("console.device", unit, IOStdReq, flags )
    d0		    a0               d0    a1        d1

    FUNCTION
    The open routine grants access to a device.  There are two
    fields in the IOStdReq block that will be filled in: the
    io_Device field and possibly the io_Unit field.

    As of (V37) the flags field may also be filled in with
    a value described below (see conunit.h or conunit.i).

    This open command differs from most other device open commands
    in that it requires some information to be supplied in the
    io_Data field of the IOStdReq block.  This initialization
    information supplies the window that is used by the console
    device for output.

    The unit number that is a standard parameter for an open call
    is used specially by this device.  See conunit.h, or conunit.i
    for defined valid unit numbers.

    unit number: -1 (CONU_LIBRARY)

        Used to get a pointer to the device library vector
    which is returned in the io_Device field of the IOStdReq
    block.  No actual console is opened.  You must still close
    the device when you are done with it.

    unit number: 0 (CONU_STANDARD)

        A unit number of zero binds the supplied window to
    a unique console.  Sharing a console must be done at a level
    higher than the device.

    unit number: 1 (CONU_CHARMAP) (V36)

        A unit number of one is similar to a unit number of
    zero, but a console map is also created, and maintained by
    the console.device.  The character map is used by the console
    device to restore obscured portions of windows which are
    revealed, and to redraw a window after a resize.  Character
    mapped console.device windows must be opened as SIMPLE REFRESH
    windows.

        The character map is currently for internal use
    only, and is not accessible by the programmer.  The character
    map stores characters, attributes, and style information for
    each character written with the CMD_WRITE command.

    unit number: 3 (CONU_SNIPMAP) (V36)

        A unit number of three is similar to a unit number
    of one, but also gives the user the ability to highlight
    text with the mouse which can be copied by pressing
    RIGHT AMIGA C.  See NOTES below.

    flags: 0 (CONFLAG_DEFAULT)

        The flags field should be set to 0 under V34, or less.

    flags: 1 (CONFLAG_NODRAW_ON_NEWSIZE) (V37)

        The flags field can be set to 0, or 1 as of V37.  The
    flags field is ignored under V36, so can be set, though it
    will have no effect.  When set to 1, it means that you don't
    want the console.device to redraw the window when the window
    size is changed (assuming you have opened the console.device
    with a character map - unit numbers 1, or 3).  This flag is
    ignored if you have opened a console.device with a unit
    number of 0.  Typically you would use this flag when you
    want to perform your own window refresh on a newsize, and
    you want the benefits of a character mapped console.

    IO REQUEST
    io_Data		struct Window *window
            This is the window that will be used for this
            console.  It must be supplied if the unit in
            the OpenDevice call is 0 (see above).  The
            RPort of this window is potentially in use by
            the console whenever there is an outstanding
            write command.
    INPUTS
    "console.device" - a pointer to the name of the device to be opened.
    unit - the unit number to open on that device.
    IOStdReq - a pointer to a standard request block
    0 - a flag field of zero (CONFLAG_DEFAULT)
    1 - a flag field of one  (CONFLAG_NODRAW_ON_NEWSIZE) (V37)

    RESULTS
    error - zero if successful, else an error is returned.

    NOTES
    As noted above, opening the console.device with a unit number of 3
    allows the user to drag select text, and copy the selection with
    RIGHT AMIGA C.  The snip is copied to a private buffered managed
    by the console.device (as of V36).  The snip can be copied to
    any console.device window unless you are running a console to
    clipboard utility such as that provided with V37.

    The user pastes text into console.device windows by pressing
    RIGHT AMIGA V.  Both RIGHT AMIGA V, and RIGHT AMIGA C are swallowed
    by the console.device (unless you have asked for key presses as
    RAW INPUT EVENTS).  Text pasted in this way appears in the
    console read stream as if the user had typed all of the characters
    manually.  Additional input (e.g., user input, RAW INPUT EVENTS)
    are queued up after pastes.  Pastes can theoretically be quite
    large, though they are no larger than the amount of text
    which is visible in a console.device window.

    When running the console to clipboard utility, text snips
    are copied to the clipboard.device, and RIGHT AMIGA V key
    presses are broadcast as an escape sequence as part of the
    console.device read stream ("<CSI>0 v" - $9B,$30,$20,$76).

    It is left up to the application to decide what to do when this
    escape sequence is received.  Ideally the application
    will read the contents of the clipboard, and paste the text
    by using successive writes to the console.device.

    Because the contents of the clipboard.device can be quite
    large, your program should limit the size of writes to something
    reasonable (e.g., no more than 1K characters per CMD_WRITE, and
    ideally no more than 256 characters per write).  Your program
    should continue to read events from the console.device looking
    for user input, and possibly RAW INPUT EVENTS.  How you decide
    to deal with these events is left up to the application.

    If you are using a character mapped console you should receive
    Intuition events as RAW INPUT EVENTS from the console.device.
    By doing this you will hear about these events after the console
    device does.  This allows the console.device to deal with events
    such as window resizing, and refresh before your application.

    BUGS

    SEE ALSO
    exec/io.h, intuition/intuition.h

 console.device/RawKeyConvert                     console.device/RawKeyConvert

    NAME
    RawKeyConvert -- decode raw input classes

    SYNOPSIS
    actual = RawKeyConvert(event, buffer, length, keyMap)
    D0       	       A0     A1      D1      A2

    ConsoleDevice in A6 if called from Assembly Language.

    FUNCTION
    This console function converts input events of type
    IECLASS_RAWKEY to ANSI bytes, based on the keyMap, and
    places the result into the buffer.

    INPUTS
    event -  an InputEvent structure pointer.
    buffer - a byte buffer large enough to hold all anticipated
        characters generated by this conversion.
    length - maximum anticipation, i.e. the buffer size in bytes.
    keyMap - a KeyMap structure pointer, or null if the default
        console device key map is to be used.

    RESULTS
    actual - the number of characters in the buffer, or -1 if
        a buffer overflow was about to occur.

    ERRORS
    if actual is -1, a buffer overflow condition was detected.
    Not all of the characters in the buffer are valid.

    NOTES
    This function is different from standard device commands in
    that it is a function in the console device library vectors.
    In order to obtain a valid library base pointer for the
    console device (a.k.a. ConsoleDevice) call
    OpenDevice("console.device", -1, IOStdReq, 0),
    and then grab the io_Device pointer field out of the IOStdReq
    and use as ConsoleDevice.

    BUGS

    SEE ALSO
    exec/io.h, devices/inputevent.h, devices/keymap.h


Text_Autodocs/keyboard.doc

TABLE OF CONTENTS

keyboard.device/CMD_CLEAR
keyboard.device/KBD_ADDRESETHANDLER
keyboard.device/KBD_READEVENT
keyboard.device/KBD_READMATRIX
keyboard.device/KBD_REMRESETHANDLER
keyboard.device/KBD_RESETHANDLERDONE
 keyboard.device/CMD_CLEAR                           keyboard.device/CMD_CLEAR

   NAME
    CMD_CLEAR -- Clear the keyboard input buffer.

   FUNCTION
    Remove from the input buffer any keys transitions waiting to
    satisfy read requests.

   IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Device	preset by the call to OpenDevice
    io_Command	CMD_CLEAR
    io_Flags	IOB_QUICK set if quick I/O is possible

 keyboard.device/KBD_ADDRESETHANDLER       keyboard.device/KBD_ADDRESETHANDLER

   NAME
    KBD_ADDRESETHANDLER -- Add a keyboard reset handler.

   FUNCTION
    Add a function to the list of functions called to clean up
    before a hard reset generated at the keyboard.  The reset
    handler is called as:
        ResetHandler(handlerData)
                     a1

   IO REQUEST
    io_Message	mn_ReplyPort set
    io_Device	preset by OpenDevice
    io_Unit		preset by OpenDevice
    io_Command	KBD_ADDRESETHANDLER
    io_Data		a pointer to an interrupt structure.
        is_Data 	the handlerData pointer described above
        is_Code	the Handler function address

   NOTES
    Few of the Amiga keyboard models generate the communication codes
    used to implement this reset processing.  Specifically, only the
    Euro a1000 (rare), and the B2000 keyboard generate them.

    The interrupt structure is kept by the keyboard device until a
    RemResetHandler command is satisfied for it, but the
    KBD_ADDRESETHANDLER command itself is replied immediately.

 keyboard.device/KBD_READEVENT                   keyboard.device/KBD_READEVENT

   NAME
    KBD_READEVENT -- Return the next keyboard event.

   FUNCTION
    Read raw keyboard events from the keyboard and put them in the
    data area of the iORequest.  If there are no pending keyboard
    events, this command will not be satisfied, but if there are
    some events, but not as many as can fill IO_LENGTH, the
    request will be satisfied with those currently available.

   IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Device	preset by the call to OpenDevice
    io_Command	KBD_READEVENT
    io_Flags	IOB_QUICK set if quick I/O is possible
    io_Length	the size of the io_Data area in bytes: there
            are sizeof(inputEvent) bytes per input event.
    io_Data		a buffer area to fill with input events.  The
            fields of the input event are:
        ie_NextEvent
            links the events returned
        ie_Class
            is IECLASS_RAWKEY
        ie_Code
            contains the next key up/down reports
        ie_Qualifier
            only the shift and numeric pad bits are set
        ie_SubClass, ie_X, ie_Y, ie_TimeStamp
            are not used, and set to zero

   RESULTS
    This function sets the error field in the IORequest, and fills
    the IORequest with the next keyboard events (but not partial
    events).

 keyboard.device/KBD_READMATRIX                 keyboard.device/KBD_READMATRIX

   NAME
    KBD_READMATRIX -- Read the current keyboard key matrix.

   FUNCTION
    This function reads the up/down state of every key in the
    key matrix.

   IO REQUEST INPUT
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Device	preset by the call to OpenDevice
    io_Command	KBD_READMATRIX
    io_Flags	IOB_QUICK set if quick I/O is possible
    io_Length	the size of the io_Data area in bytes: this
            must be big enough to hold the key matrix.
    io_Data		a buffer area to fill with the key matrix:
            an array of bytes whose component bits reflect
            each keys state: the state of the key for
            keycode n is at bit (n MOD 8) in byte
            (n DIV 8) of this matrix.

   IO REQUEST OUTPUT
    io_Error
         IOERR_BADLENGTH - the io_Length was not exactly 13 bytes.
            The buffer is unchanged.  This is only returned
            by V33/V34 kickstart.
    io_Actual	the number of bytes filled in io_Data with key
            matrix data, i.e. the minimum of the supplied
            length and the internal key matrix size.

   NOTE
    For V33/V34 Kickstart, io_Length must be set to exactly 13 bytes.

   RESULTS
    This function sets the error field in the IORequest, and sets
    matrix to the current key matrix.

 keyboard.device/KBD_REMRESETHANDLER       keyboard.device/KBD_REMRESETHANDLER

   NAME
    KBD_REMRESETHANDLER -- Remove a keyboard reset handler.

   FUNCTION
    Remove a function previously added to the list of reset
    handler functions with KBD_ADDRESETHANDLER.

   IO REQUEST
    io_Message	mn_ReplyPort set
    io_Device	preset by OpenDevice
    io_Unit		preset by OpenDevice
    io_Command	KBD_REMRESETHANDLER
    io_Data		a pointer to the handler interrupt structure.

 keyboard.device/KBD_RESETHANDLERDONE     keyboard.device/KBD_RESETHANDLERDONE

   NAME
    KBD_RESETHANDLERDONE -- Indicate that reset handling is done.

   FUNCTION
    Indicate that reset cleanup associated with the handler has
    completed.  This command should be issued by all keyboard
    reset handlers so that the reset may proceed.

   IO REQUEST
    io_Message	mn_ReplyPort set
    io_Device	preset by OpenDevice
    io_Unit		preset by OpenDevice
    io_Command	KBD_RESETHANDLERDONE
    io_Data		a pointer to the handler interrupt structure.

   NOTES
    The keyboard processor itself performs the hardware reset, and
    will time out and perform the reset even if some reset handlers
    have not indicated yet that the reset may proceed.  This
    timeout is several seconds.


Text_Autodocs/printer.doc

TABLE OF CONTENTS

printer.device/CMD_FLUSH
printer.device/CMD_INVALID
printer.device/CMD_RESET
printer.device/CMD_START
printer.device/CMD_STOP
printer.device/CMD_WRITE
printer.device/PRD_DUMPRPORT
printer.device/PRD_PRTCOMMAND
printer.device/PRD_QUERY
printer.device/PRD_RAWWRITE
printer.device/PWrite
 printer.device/CMD_FLUSH                             printer.device/CMD_FLUSH

   NAME
    CMD_FLUSH -- abort all I/O requests (immediate)

   FUNCTION
    CMD_FLUSH aborts all stopped I/O at the unit.

   IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Device	preset by the call to OpenDevice
    io_Command	CMD_FLUSH
    io_Flags	IOB_QUICK set if quick I/O is possible

 printer.device/CMD_INVALID                         printer.device/CMD_INVALID

   NAME
    CMD_INVALID -- invalid command

   FUNCTION
    CMD_INVALID is always an invalid command, and sets the device
    error appropriately.

   IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Command	CMD_INVALID
    io_Flags	IOB_QUICK set if quick I/O is possible

 printer.device/CMD_RESET                             printer.device/CMD_RESET

   NAME
    CMD_RESET -- reset the printer

   FUNCTION
    CMD_RESET resets the printer device without destroying handles
    to the open device.

   IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Device	preset by the call to OpenDevice
    io_Command	CMD_RESET
    io_Flags	IOB_QUICK set if quick I/O is possible

 printer.device/CMD_START                             printer.device/CMD_START

   NAME
    CMD_START -- restart after stop (immediate)

   FUNCTION
    CMD_START restarts the unit after a stop command.

   IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Device	preset by the call to OpenDevice
    io_Command	CMD_START
    io_Flags	IOB_QUICK set if quick I/O is possible

 printer.device/CMD_STOP                               printer.device/CMD_STOP

   NAME
    CMD_STOP -- pause current and queued I/O requests (immediate)

   FUNCTION
    CMD_STOP pauses all queued requests for the unit, and tries to
    pause the current I/O request.  The only commands that will
    be subsequently allowed to be performed are immediate I/O
    requests, which include those to start, flush, and finish the
    I/O after the stop command.

   IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Device	preset by the call to OpenDevice
    io_Command	CMD_STOP
    io_Flags	IOB_QUICK set if quick I/O is possible

 printer.device/CMD_WRITE                             printer.device/CMD_WRITE

   NAME
      CMD_WRITE -- send output to the printer

   FUNCTION
      This function causes a buffer of characters to be written to the
      current printer port (usually parallel or serial).  The number of
      characters is specified in io_Length, unless -1 is used, in which
      case output is sent until a 0x00 is encountered.

      The Printer device, like the Console device, maps ANSI X3.64 style
      7-bit printer control codes to the control code set of the current
      printer.  The ANSI codes supported can be found below.

   NOTES
      Not all printers will support all functions.  In particular you may
      not assume that the MARGINS or TABS can be set.  Close to half the
      supported printers don't fully implement one or the other.  If you
      want the features of margins or tabs you will need to fake it
      internally by sending out spaces.

      Note that the printer device may have already sent out a "set
      margins" command to the printer.  If you are faking your own
      margins, be sure to cancel the old ones first.  (use the "aCAM"
      command)

      Defaults are set up so that if a normal AmigaDOS text file
      is sent to PRT:, it has the greatest chance of working.
      (AmigaDOS text files are defined as follows:)
              tabs            - every 8
              CR (0x0D)       - moves to start of current line
              LF (0x0A)       - moves to start of next line

   IO REQUEST
       io_Message      mn_ReplyPort set
       io_Device       preset by OpenDevice
       io_Unit         preset by OpenDevice
       io_Command      CMD_WRITE
       io_Length       number of characters to process, or if -1,
                       process until 0x00 encountered
       io_Data         pointer to block of data to process

   RESULTS
       io_Error : if CMD_WRITE succeeded, then io_Error will be zero.
              Otherwise io_Error will be non-zero.

   SEE ALSO
       printer.h, parallel.device, serial.device, Preferences

   ANSI X3.64 style COMMANDS

 aRIS         ESCc            hard reset
 aRIN         ESC#1           initialize to defaults
 aIND         ESCD            true linefeed (lf)
 aNEL         ESCE            return,lf
 aRI          ESCM            reverse lf              *

 aSGR0        ESC[0m          normal character set
 aSGR3        ESC[3m          italics on
 aSGR23       ESC[23m         italics off
 aSGR4        ESC[4m          underline on
 aSGR24       ESC[24m         underline off
 aSGR1        ESC[1m          boldface on
 aSGR22       ESC[22m         boldface off
 aSFC         SGR30-39        set foreground color
 aSBC         SGR40-49        set background color

 aSHORP0      ESC[0w          normal pitch
 aSHORP2      ESC[2w          elite on
 aSHORP1      ESC[1w          elite off
 aSHORP4      ESC[4w          condensed on
 aSHORP3      ESC[3w          condensed off
 aSHORP6      ESC[6w          enlarged on
 aSHORP5      ESC[5w          enlarged off

 aDEN6        ESC[6"z         shadow print on
 aDEN5        ESC[5"z         shadow print off
 aDEN4        ESC[4"z         doublestrike on
 aDEN3        ESC[3"z         doublestrike off
 aDEN2        ESC[2"z         Near Letter Quality (NLQ) on
 aDEN1        ESC[1"z         NLQ off

 aSUS2        ESC[2v          superscript on
 aSUS1        ESC[1v          superscript off
 aSUS4        ESC[4v          subscript on
 aSUS3        ESC[3v          subscript off
 aSUS0        ESC[0v          normalize the line      *
 aPLU         ESCL            partial line up         *
 aPLD         ESCK            partial line down       *

 aFNT0        ESC(B           US char set (default)   or Font 0
 aFNT1        ESC(R           French char set         or Font 1
 aFNT2        ESC(K           German char set         or Font 2
 aFNT3        ESC(A           UK char set             or Font 3
 aFNT4        ESC(E           Danish I char set       or Font 4
 aFNT5        ESC(H           Sweden char set         or Font 5
 aFNT6        ESC(Y           Italian char set        or Font 6
 aFNT7        ESC(Z           Spanish char set        or Font 7
 aFNT8        ESC(J           Japanese char set       or Font 8
 aFNT9        ESC(6           Norweign char set       or Font 9
 aFNT10       ESC(C           Danish II char set      or Font 10

 aPROP2       ESC[2p          proportional on         *
 aPROP1       ESC[1p          proportional off        *
 aPROP0       ESC[0p          proportional clear      *
 aTSS         ESC[n E         set proportional offset *
 aJFY5        ESC[5 F         auto left justify       *
 aJFY7        ESC[7 F         auto right justify      *
 aJFY6        ESC[6 F         auto full justify       *
 aJFY0        ESC[0 F         auto justify off        *
 aJFY3        ESC[3 F         letter space (justify)  *
 aJFY1        ESC[1 F         word fill(auto center)  *

 aVERP0       ESC[0z          1/8" line spacing
 aVERP1       ESC[1z          1/6" line spacing
 aSLPP        ESC[nt          set form length n
 aPERF        ESC[nq          set perforation skip to n lines (n>0)
 aPERF0       ESC[0q          perforation skip off

 aLMS         ESC#9           Left margin set         *
 aRMS         ESC#0           Right margin set        *
 aTMS         ESC#8           Top margin set          *
 aBMS         ESC#2           Bottom margin set       *
 aSTBM        ESC[Pn1;Pn2r    set T&B margins         *
 aSLRM        ESC[Pn1;Pn2s    set L&R margin          *
 aCAM         ESC#3           Clear margins

 aHTS         ESCH            Set horiz tab           *
 aVTS         ESCJ            Set vertical tabs       *
 aTBC0        ESC[0g          Clr horiz tab           *
 aTBC3        ESC[3g          Clear all h tab         *
 aTBC1        ESC[1g          Clr vertical tabs       *
 aTBC4        ESC[4g          Clr all v tabs          *
 aTBCALL      ESC#4           Clr all h & v tabs      *
 aTBSALL      ESC#5           Set default tabs (every 8)

 aEXTEND      ESC[Pn"x        Extended commands
                              This is a mechanism for printer drivers to
                              support extra commands which can be called
                              by ANSI control sequences
 aRAW         ESC[Pn"r        Next 'Pn' chars are raw (ie. they are not
                              parsed by the printer device, instead they
                              are sent directly to the printer.

 (*) indicates that sending this command may cause unexpected results
     on a large number of printers.

 printer.device/PRD_DUMPRPORT                     printer.device/PRD_DUMPRPORT

   NAME
    PRD_DUMPRPORT -- dump the specified RastPort to a graphics printer

   FUNCTION
    Print a rendition of the supplied RastPort, using the supplied
    ColorMap, position and scaling information, as specified in
    the printer preferences.

   IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible.
    io_Command	PRD_DUMPRPORT.
    io_Flags	IOB_QUICK set if quick I/O is possible.
    io_RastPort	ptr to a RastPort.
    io_ColorMap	ptr to a ColorMap.
    io_Modes	the 'modes' flag from a ViewPort structure,
            (the upper word is reserved and should be zero).

            If you are running under version 36, or greater
            of graphics.library, it is recommended that
            you fill in "io_Modes" with the ULONG (32-bit)
            value returned from calling:

            ULONG ModeID = GetVPModeID(struct ViewPort *);

            Doing so provides for upwards compatability with
            the new display modes available under V36
            (example: aspect ratio calculations for new
            display modes).

    io_SrcX		x offset into the RastPort to start printing from.
    io_SrcY		y offset into the RastPort to start printing from.
    io_SrcWidth	width of the RastPort to print (from io_SrcX).
    io_SrcHeight	height of the RastPort to print (from io_SrcY).
    io_DestCols	width of the printout in printer pixels.
    io_DestRows	height of the printout in printer pixels.
    io_Special	flag bits
            (some of which pertain to DestCols and DestRows).
            -if SPECIAL_MIL is set, then the associated
             parameter is specified in thousandths of
             an inch on the printer.  ie. if DestCols = 8000,
             DestRows = 10500 and SPECIAL_MILROWS and
             SPECIAL_MILCOLS is set then the printout would be
             8.000 x 10.500 inches.
            -if SPECIAL_FULL is set, then the specific dimension
             is set to the maximum possible as determined
             by the printer limits or the configuration
             limits; whichever is less.
            -if SPECIAL_FRAC is set, the parameter is
             taken to be a longword binary fraction
             of the maximum for that dimension.
            -if all bits for a dimension are clear,
             (ie. SPECIAL MIL/FULL/FRAC and ASPECT are NOT set)
             then the parameter is specified in printer pixels.
            -if SPECIAL_CENTER is set then the image will be
             put between the left and right edge of the paper.
            -if SPECIAL_ASPECT is set, one of the dimensions
             may be reduced/expanded to preserve the aspect
             ratio of the print.
            -SPECIAL_DENSITY(1-7) this allows for a maximum of 7
             different print densities.  DENSITY1 is the lowest
             density and the default.
            -SPECIAL_NOFORMFEED - this allows for the mixing of
             text and graphics or multiple graphic dumps on page
             oriented printers (usually laser jet printers).
             When this flag is set the page will not be ejected
             after a graphic dump.  If you perform another
             graphic dump without this flag set OR close the
             printer after printing text after a graphic dump,
             the page will be ejected.
            -if SPECIAL_TRUSTME is set then the printer specific
             driver is instructed to not issue a reset command
             before and after the dump.  If this flag is NOT
             checked by the printer specific driver then setting
             this flag has no effect.  Since we now recommend
             that printer driver writers no longer issue a reset
             command it is probably a safe idea to always set
             this flag when calling for a dump.
            -if SPECIAL_NOPRINT is set then the following is done:
             Compute print size, set 'io_DestCols' and
             'io_DestRows' in the calling program's 'IODRPReq'
             structure and exit, DON'T PRINT.  This allows the
             calling program to see what the final print size
             would be in printer pixels.  Note that it modifies
             the 'io_DestCols' and 'io_DestRows' fields of your
             'IODRPReq' structure.  It also sets the print
             density and updates the 'MaxXDots', 'MaxYDots',
             'XDotsInch', and 'YDotsInch' fields of the
             'PrinterExtendedData' structure.

    There following rules for the interpretation of io_DestRows and
    io_DestCols that may produce unexpected results when they are
    not greater than zero and io_Special is zero.  They have been
    retained for compatability.  The user will not trigger these
    other rules with well formed usage of io_Special.

    When io_Special is equal to 0, the following rules
    (from the V1.1 printer.device, and retained for compatibility
    reasons) take effect.  Remember, these special rules are
    for io_DestRows and io_DestCols and only take effect
    if io_Special is 0).

    a) DestCols>0 & DestRows>0 - use as absolute values.
       ie. DestCols=320 & DestRows=200 means that the picture
       will appear on the printer as 320x200 dots.
    b) DestCols=0 & DestRows>0 - use the printers maximum number
       of columns and print DestRows lines. ie. if DestCols=0
       and DestRows=200 than the picture will appear on the
       printer as wide as it can be and 200 dots high.
    c) DestCols=0 & DestRows=0 - same as above except the driver
       determines the proper number of lines to print based on
       the aspect ratio of the printer. ie. This results in the
       largest picture possible that is not distorted or inverted.
       Note: As of this writing, this is the call made by such
       program as DeluxePaint, GraphicCraft, and AegisImages.
    d) DestCols>0 &DestRows=0 - use the specified width and the
       driver determines the proper number of lines to print based
       on the aspect ratio of the printer. ie. if you desire a
       picture that is 500 pixels wide and aspect ratio correct,
       use DestCols=500 and DestRows=0.
    e) DestCols<0 or DestRows>0 - the final picture is either a
       reduction or expansion based on the fraction
       |DestCols| / DestRows in the proper aspect ratio.
       Some examples:
       1) if DestCols=-2 & DestRows=1 then the printed picture will
          be 2x the AMIGA picture and in the proper aspect ratio.
          (2x is derived from |-2| / 1 which gives 2.0)
       2) if DestCols=-1 & DestRows=2 then the printed picture will
          will be 1/2x the AMIGA picture in the proper aspect ratio.
          (1/2x is derived from |-1| / 2 which gives 0.5)

   NOTES
    The printer selected in preferences must have graphics
    capability to use this command.  The error 'PDERR_NOTGRAPHICS'
     is returned if the printer can not print graphics.

    Color printers may not be able to print black and white or
    greyscale pictures -- specifically, the Okimate 20 cannot print
    these with a color ribbon: you must use a black ribbon instead.
    If the printer has an input buffer option, use it.
    If the printer can be uni or bi directional, select
    uni-directional; this produces a much cleaner picture.
    Most printer drivers will attempt to set unidirectional
    printing if it is possible under software control.

    Please note that the width and height of the printable area on
    the printer is in terms of pixels and bounded by the following:
     a) WIDTH = (RIGHT_MARGIN - LEFT_MARGIN + 1) / CHARACTERS_PER_INCH
     b) HEIGHT = LENGTH / LINES_PER_INCH
       Margins are set by preferences.

    For BGR printer support, the YMC values in the printer
    specific render.c functions equate to BGR respectively, ie.
    yellow is blue, magenta is green, and cyan is red.

 Data Structures
 ---------------

    The printer specific and non-specific data structures can be read
    ONCE you have opened the printer device.  Here is a code fragment
    to illustrate how to do just that.

    #include <exec/types.h>
    #include <devices/printer.h>
    #include <devices/prtbase.h>
    #include <devices/prtgfx.h>

    struct IODRPReq PReq;
    struct PrinterData *PD;
    struct PrinterExtendedData *PED;

   open the printer device / if it opened...
   if (OpenDevice("printer.device", 0, &PReq, 0) == NULL) {
       get pointer to printer data
       PD = (struct PrinterData *)PReq.io_Device;
       get pointer to printer extended data
       PED = &PD->pd_SegmentData->ps_PED;
       let's see what's there
       printf("PrinterName = '%s', Version=%u, Revision=%u\n",
           PED->ped_PrinterName, PD->pd_SegmentData->ps_Version,
           PD->pd_SegmentData->ps_Revision,);
       printf("PrinterClass=%u, ColorClass=%u\n",
           PED->ped_PrinterClass, PED->ped_ColorClass);
       printf("MaxColumns=%u, NumCharSets=%u, NumRows=%u\n",
           PED->ped_MaxColumns, PED->ped_NumCharSets, PED->ped_NumRows);
       printf("MaxXDots=%lu, MaxYDots=%lu, XDotsInch=%u, YDotsInch=%u\n",
           PED->ped_MaxXDots, PED->ped_MaxYDots,
           PED->ped_XDotsInch, PED->ped_YDotsInch);
       CloseDevice(&PReq);
   }

 Preferences
 -----------

    If you want the user to be able to access the printer preferences items
 without having to run preferences (like DPAINT II's printer requester),
 here is what you do.  You can look at the printer's copy of preferences
 by referring to 'PD->pd_Preferences' (the printer device MUST already be
 opened at this point).  After you have this you could put up a requester
 and allow the user to change whatever parameters they wanted.
 BEAR IN MIND THAT YOU ARE RESPONSIBLE FOR RANGE CHECKING THESE SELECTIONS!
 Listed below are the printer preferences items and their valid values.

 PrintPitch         - PICA, ELITE, FINE.
 PrintQuality       - DRAFT, LETTER.
 PrintSpacing       - SIX_LPI, EIGHT_LPI.
 PrintLeftMargin    - 1 to PrintRightMargin.
 PrintRightMargin   - PrintLeftMargin to 999.
 PaperLength        - 1 to 999.
 PrintImage         - IMAGE_POSITIVE, IMAGE_NEGATIVE.
 PrintAspect        - ASPECT_HORIZ, ASPECT_VERT.
 PrintShade         - SHADE_BW, SHADE_GREYSCALE, SHADE_COLOR.
 PrintThreshold     - 1 to 15.
 PrintFlags         - CORRECT_RED, CORRECT_GREEN, CORRECT_BLUE, CENTER_IMAGE,
                      IGNORE_DIMENSIONS, BOUNDED_DIMENSIONS,
                      ABSOLUTE_DIMENSIONS, PIXEL_DIMENSIONS,
                      MULTIPLY_DIMENSIONS, INTEGER_SCALING,
                      ORDERED_DITHERING, HALFTONE_DITHERING.
                      FLOYD_DITHERING, ANTI_ALIAS, GREY_SCALE2
 PrintMaxWidth      - 0 to 65535.
 PrintMaxHeight     - 0 to 65535.
 PrintDensity       - 1 to 7.
 PrintXOffset       - 0 to 255.

 Asynchronous I/O
 ----------------

     The recommended way to do asynchronous i/o is...

 a) To send requests for i/o.

     struct IORequest *ioreq;
     struct MsgPort *port;
     UBYTE signal;

     port = ioreq->io_Message.mn_ReplyPort;
     signal = port->mp_SigBit;

     SendIO(ioreq);  send request
     Wait(signal);  wait for completion (go to sleep)
     while ((Msg = GetMsg(port)) != NULL) {  get ALL messages
     }

 b) To abort a previous request for i/o.

     struct IORequest *ioreq;

     AbortIO(ioreq);  abort request
     WaitIO(ioreq);  wait for reply

     at this point you can re-use 'ioreq'.

     Note that in the above examples 'ioreq' could be any one of...
     a) struct IOStdReq    a standard i/o request
     b) struct IODRPReq    a dumprport i/o request
     c) struct IOPrtCmdReq a printer command i/o request

     It is recommend that you do asynchronous i/o in your programs
     and give the user a way of aborting all requests.

         V1.3 Printer Driver Notes
         -------------------------

     In general densities which use more than one pass should only be
 used for B&W shade dumps.  They can be used for Grey-Scale or Color Shade
 dumps BUT the output may tend to look muddy or dark.  Also multiple pass
 Color dumps tend to dirty or smear the ribbon (ie. yellow will get
 contaminated with the other colors on the ribbon; you have been warned).

 Alphacom_AlphaPro_101
 ---------------------
 1. Daisywheel printer (text only).

 Brother_HR-15XL
 ---------------
 1. Daisywheel printer (text only).

 CalComp_ColorMaster
 -------------------
 1. Thermal transfer b&w/color printer (text and graphics).
 2. Use Black ribbon for non-color dumps; Color ribbon for color dumps.
 3. Linefeeds # of vertical dots printed.
 4. Densities supported are 203x200(1) dpi.
 5. This is a dual printer driver.  Select a PaperSize of 'Narrow Tractor'
    for use with the ColorMaster; 'Wide Tractor' for use with the
    ColorView-5912 (which uses 11 x 17 inch paper).

 CalComp_ColorMaster2
 -------------------
 1. Thermal transfer b&w/color printer (text and graphics).
 2. Use Black ribbon for non-color dumps; Color ribbon for color dumps.
 3. Linefeeds # of vertical dots printed.
 4. Densities supported are 203x200(1) dpi.
 5. This is a dual printer driver.  Select a PaperSize of 'Narrow Tractor'
    for use with the ColorMaster; 'Wide Tractor' for use with the
    ColorView-5912 (which uses 11 x 17 inch paper).
 6. This driver is the same as the Calcomp_ColorMaster driver EXCEPT it is
    approximately 2 times faster (during color dumps) and requires LOTS of
    memory (up to 1,272,003 bytes for a full 8 x 10 inch (1600 x 2000 dot)
    color dump).  Typically full-size (color) dumps are 1600 x 1149 dots and
    require 730,767 bytes.  Memory requirements for the ColorView-5912
    are up to 2,572,803 bytes for a full 10 x 16 inch (2048 x 3200 dot)
    color dump.  Typically full-size (color) dumps are 2048 x 2155 dots and
    require 1,732,623 bytes.  The memory requirements are 1/3 when doing a
    non-color printout (on both the ColorMaster and ColorView).

 Canon_PJ-1080A
 --------------
 1. Ink jet b&w/color printer (text and graphics).
 2. Linefeeds # of vertical dots printed.
 3. Densities supported are 83x84(1) dpi.

 CBM_MPS1000
 -----------
 1. Dot matrix b&w printer (text and graphics).
 2. Linefeeds # of vertical dots printed (-1/3 dot if PaperType = Single). *2
 3. Density	XDPI	YDPI	XYDPI	Comments
     1	120	 72	 8640
     2	120	144	17280	two pass
     3	240	 72	17280			*1
     4	120	216	25920	three pass
     5	240	144	34560	two pass	*1
     6	240	216	51840	three pass	*1
     7	same as 6

 Diablo_630
 ----------
 1. Daisywheel printer (text only).

 Diablo_Advantage_D25
 --------------------
 1. Daisywheel printer (text only).

 Diablo_C-150
 ------------
 1. Ink jet b&w/color printer (text and graphics).
 2. Always linefeeds 4 dots (limitation of printer).
 3. A PaperSize of 'Wide Tractor' selects a maximum print width of
    8.5 inches (for wide roll paper).
 5. Densities supported are 120x120(1) dpi.

 EpsonQ (24-pin Epson compatible)
 ------
 1. Dot matrix b&w/color printer (text and graphics).
 2. Drives all EpsonQ (LQ1500, LQ2500, etc.) compatible printers.
 3. Linefeeds # of vertical dots printed.
 4. Density	XDPI	YDPI	XYDPI	Comments
     1	 90	180	16200
     2	120	180	21600
     3	180	180	32400
     4	360	180	64800	*1
     5,6,7	same as 4
 5. A PaperSize of 'Wide Tractor' selects a maximum print width of
    13.6 inches (for wide carriage printers).
 6. A PaperType of 'Single' uses only 16 of the 24 pins, whereas a PaperType
    of 'Fanfold' uses all 24 pins.  The 'Single' option is useful for those
    printers which have a weak power supply and cannot drive all 24 pins
    continuously.  If during a single pass of the print head you notice that
    the top two thirds of the graphics are darker than the bottom one third
    then you will probably need to drop down to 16 pins.

 EpsonX[CBM_MPS-1250] (8/9-pin Epson compatible)
 --------------------
 1. Dot matrix b&w/color printer (text and graphics).
 2. Drives all EpsonX (EX/FX/JX/LX/MX/RX, etc.) compatible printers.
 3. Linefeeds # of vertical dots printed (-1/3 dot if PaperType = Single). *2
 4. Density	XDPI	YDPI	XYDPI	Comments
     1	120	 72	 8640
     2	120	144	17280	two pass
     3	240	 72	17280			*1
     4	120	216	25920	three pass
     5	240	144	34560	two pass	*1
     6	240	216	51840	three pass	*1
     7	same as 6

 5. A PaperSize of 'Wide Tractor' selects a maximum print width of
    13.6 inches (for wide carriage printers).
 6. Use this driver if you own a CBM_MPS-1250 (as it is EpsonX compatible).

 EpsonXOld (8/9-pin Epson compatible)
 ---------
 1. Dot matrix b&w printer (text and graphics).
 2. Drives all very old EpsonX (EX/FX/JX/LX/MX/RX, etc.) compatible printers.
 3. Linefeeds # of vertical dots printed.
 4. Density	XDPI	YDPI	XYDPI	Comments
     1	 60	72	 4320
     2	120	72	 8640	(double speed)			*1
     3	120	72	 8640
     4	240	72	17280					*1
     5	120	72	 8640	(for use on old Star printers)
     6	240	72	17280	(for use on old Star printers)	*1
     7	240	72	17280	(same as density 4)		*1
 5. A PaperSize of 'Wide Tractor' selects a maximum print width of
    13.6 inches (for wide carriage printers).
 6. Use this driver if the EpsonX driver does not work properly in graphics
    or text mode on your EpsonX compatible printer.

 generic
 -------
 1. Text only printer.

 Howtek_Pixelmaster
 ------------------
 1. Plastic ink jet b&w/color printer (text and graphics).
 2. Linefeeds # of vertical dots printed.
 3. Density	XDPI	YDPI	XYDPI	Comments
     1	 80	 80	 6400
     2	120	120	14400
     3	160	160	25600
     4	240	240	57600
     5,6,7	same as 4
 4. Maximum print area is 8.0 x 10.0 inches.

 HP_DeskJet
 ----------
 1. Ink jet non-color printer (text and graphics).
 2. Linefeeds # of vertical dots printed.
 3. Density	XDPI	YDPI	XYDPI	Comments
     1	 75	 75	 5625
     2	100	100	10000
     3	150	150	22500
     4	300	300	90000
     5,6,7	same as 4
 4. Maximum print area is 8.0 x 10.0 inches.

 HP_LaserJet (LaserJet+/LaserJetII compatible)
 -----------
 1. Laser engine non-color printer (text and graphics).
 2. Linefeeds # of vertical dots printed.
 3. Density	XDPI	YDPI	XYDPI	Comments
     1	 75	 75	 5625
     2	100	100	10000
     3	150	150	22500
     4	300	300	90000
     5,6,7	same as 4
 4. Maximum print area is 8.0 x 10.0 inches.

 HP_PaintJet
 -----------
 1. Ink jet b&w/color printer (text and graphics).
 2. Linefeeds # of vertical dots printed.
 3. Densities supported are 180x180(1) dpi.

 HP_ThinkJet
 ----------
 1. Ink jet non-color printer (text and graphics).
 2. Linefeeds # of vertical dots printed.
 3. Density	XDPI	YDPI	XYDPI	Comments
     1	 96	96	 9216
     2	192	96	18432
     3,4,5,6,7	same as 4

 Imagewriter II (Imagewriter compatible)
 --------------
 1. Dot matrix b&w/color printer (text and graphics).
 2. Linefeeds # of vertical dots printed.
 3. Density	XDPI	YDPI	XYDPI	Comments
     1	 80	 72	 5760
     2	120	 72	 8640
     3	144	 72	10368
     4	160	 72	11520
     5	120	144	17280	two pass
     6	144	144	20736	two pass
     7	160	144	23040	two pass

 Nec_Pinwriter (24-wire Pinwriter compatible (P5/P6/P7/P9/P2200))
 -------------
 1. Dot matrix b&w/color printer (text and graphics).
 2. Drives all Nec 24-wire Pinwriter compatible printers.
 3. Linefeeds # of vertical dots printed.
 4. Density	XDPI	YDPI	XYDPI	Comments
     1	 90	180	 16200
     2	120	180	 21600
     3	180	180	 32400
     4	120	360	 43200	two pass
     5	180	360	 64800	two pass
     6	360	180	 64800
     7	360	360	129600	two pass
 5. A PaperSize of 'Wide Tractor' selects a maximum print width of
    13.6 inches (for wide carriage printers).

 Okidata_92
 ----------
 1. Dot matrix non-color printer (text and graphics).
 2. Always linefeeds 7/72 inch (limitation of printer in graphics mode).
 3. Densities supported are 72x72 dpi.

 Okidata_293I
 ------------
 1. Dot matrix b&w/color printer (text and graphics).
 2. Drives 292 or 293 using the IBM interface module.
 3. Linefeeds # of vertical dots printed (-1/2 dot if PaperType = Single) *3
 4. Density	XDPI	YDPI	XYDPI	Comments
     1	120	144	17280
     2	240	144	34560
     3	120	288	34560	two pass
     4	240	288	69120	two pass
     5,6,7	same as 4
 5. A PaperSize of 'Wide Tractor' selects a maximum print width of
    13.6 inches (for wide carriage printers).

 Okimate-20
 ----------
 1. Thermal transfer b&w/color printer (text and graphics).
 2. Use Black ribbon for non-color dumps; Color ribbon for color dumps.
 3. Linefeeds an even # of dots printed. (ie. if 3 printed, 4 advanced).
 4. Densities supported are 120x144(1) dpi.

 Quadram_QuadJet
 ---------------
 1. Ink jet b&w/color printer (text and graphics).
 2. Linefeeds # of vertical dots printed.
 3. Densities supported are 83x84(1) dpi.

 Qume_LetterPro_20
 -----------------
 1. Daisywheel printer (text only).

 Seiko_5300
 ----------
 1. Thermal transfer b&w/color printer (graphics only).
 2. Use Black ribbon for non-color dumps; Color ribbon for color dumps.
 3. Density	XDPI	YDPI	XYDPI	Comments
     1	152	152	23104	drives CH-5301 printer
     2	203	203	41209	drives CH-5312 printer
     3	240	240	57600	drives CH-5303 printer
     4, 5,6,7	same as 3
     You must select the proper density to drive the specific printer
     that you have.
 4. This driver is not on the V1.3 Workbench or Extras disk.  It is
    available on BIX and directly from Seiko.

 Seiko_5300a
 -----------
 1. Thermal transfer b&w/color printer (graphics only).
 2. Use Black ribbon for non-color dumps; Color ribbon for color dumps.
 3. Density	XDPI	YDPI	XYDPI	Comments
     1	152	152	23104	drives CH-5301 printer
     2	203	203	41209	drives CH-5312 printer
     3	240	240	57600	drives CH-5303 printer
     4, 5,6,7	same as 3
     You must select the proper density to drive the specific printer
     that you have.
 4. This driver is the same as the Seiko_5300 driver EXCEPT it is
    approximately 2 times faster (during color dumps) and requires LOTS of
    memory (up to 1,564,569 bytes for a full 8 x 10 inch (1927 x 2173 dot)
    color dump).  Typically full-size (color) dumps are 1927 x 1248 dots
    and require 898,569 bytes.  The memory requirements are 1/3 when doing
    a non-color printout.
 5. This driver is not on the V1.3 Workbench or Extras disk.  It is
    available on BIX and directly from Seiko.

 Tektronix_4693D
 ---------------
 1. Thermal transfer b&w/color printer (graphics only).
 2. Densities supported are 300x300(1) dpi
 3. Due to the way the printer images a picture none of the printer
    preferences options affect the printout with the following exceptions:
    a)Aspect - Horizontal, Vertical
    b)Shade - B&W, Grey_Scale, Color
    ...as a result of this only full size pictures can be printed.
 4. Keypad menu option 3b COLOR ADJUSTMENT may be set from the keypad.
    For normal prints this option should be set to "do not adjust".
 5. Keypad menu option 3d VIDEO COLOR CORRECTION may be set from the keypad.
    For normal prints this option should be set to "do not adjust".
 6. Keypad menu option 5 BACKGROUND COLOR EXCHANGE may be set from the
    keypad.  For normal prints this option should be set to "print colors
    as received".
 7. Once a picture has been printed additional copies may be printed
    without resending by using the printers keypad.
 8. This driver is not on the V1.3 Workbench or Extras disk.  It is
    available on BIX and directly from Tektronix.

 Tektronix_4696
 --------------
 1. Ink jet b&w/color printer (text and graphics).
 2. Always linefeeds 4 dots (limitation of printer).
 3. Densities supported are 121x120(1), 242x120(black)(2) and
    242x120(color)(3).
    Selecting a density of 2 or higher really doesn't give you true 242 dpi
    resolution since the printer only has 121 x dots per inch.
    Instead this mode tells the printer to go into it's double pass mode.
    Here, it outputs a line of dots at 121 dpi; and outputs the line again
    (shifted to the right by 1/242 of an inch).  This produces much more
    vibrate colors and gives the illusion of more resolution.  One drawback
    is that large areas of solid colors (red, green, and blue specifically)
    tend to over-saturate the paper with ink.  Density1 outputs all colors
    in one pass.  Density 2 does a double pass on black.  Density 3 does a
    double pass on all colors.  Density 1 to 3 correspond to the printer's
    graphics printing modes 1 to 3 (respectively).
 4. This driver is not on the V1.3 Workbench or Extras disk.  It is
    available on BIX and directly from Tektronix.
 5. A PaperSize of 'Wide Tractor' selects a maximum print width of
    9.0 inches (for wide roll paper).

 Toshiba_P351C (24-pin Toshiba compatible)
 -------------
 1. Dot matrix b&w/color printer (text and graphics).
 2. Drives all Toshiba_P351C compatible printers.
 3. Linefeeds # of vertical dots printed.
 4. Density	XDPI	YDPI	XYDPI	Comments
     1	180	180	32400
     2	360	180	64800
     3,4,5,6,7	same as 2
 5. A PaperSize of 'Wide Tractor' selects a maximum print width of
    13.5 inches (for wide carriage printers).

 Toshiba_P351SX (24-pin Toshiba compatible)
 --------------
 1. Dot matrix b&w/color printer (text and graphics).
 2. Drives all Toshiba_P351SX (321SL, 321SLC, 341SL) compatible printers.
 3. Linefeeds # of vertical dots printed.
 4. Density	XDPI	YDPI	XYDPI	Comments
     1	180	180	 32400
     2	360	180	 64800
     3	180	360	 64800	two pass
     4	360	360	129600	two pass
     5,6,7	same as 4
 5. A PaperSize of 'Wide Tractor' selects a maximum print width of
    13.5 inches (for wide carriage printers).

 Xerox_4020
 ----------
 1. Ink jet b&w/color printer (text and graphics).
 2. Always linefeeds 4 dots (limitation of printer).
 3. This driver is IDENTICAL to the Diablo_C-150 driver EXCEPT it outputs
    all black dots TWICE.  This is a special feature of this printer and
    produces much more solid, darker black shades.  Please note that some
    printing time overhead results from this feature; if you don't want it
    use the Diablo_C-150 driver.
 4. Densities supported are 121x120(1) and 242x240(2) dpi.
    Selecting a density of 2 or higher really doesn't give you true 240 dpi
    resolution since the Xerox_4020 only has 121 x dots per inch.
    Instead this mode tells the printer to go into it's pseudo 240 dpi mode.
    Here, it outputs a line of dots at 121 dpi; moves the paper up 1/240 of
    an inch and outputs the line again (shifted to the right by 1/240 of an
    inch).  This produces much more vibrate colors and gives the illusion
    of more resolution.  One drawback is that large areas of solid colors
    (red, green, and blue specifically) tend to over-saturate the paper with
    ink.
 5. A PaperSize of 'Wide Tractor' selects a maximum print width of
    9.0 inches (for wide roll paper).

 Notes
 -----

 *0 - on most printers friction fed paper tends to produce better looking
      (ie. less horizontal banding) graphic dumps than tractor fed paper.

 *1 - in this mode the printer cannot print two consecutive dots in a row.
      It is recommended that you only use this density for B&W Shade dumps.

 *2 - only when 72 YDPI is selected.  This option is useful if you notice
      tiny white horizontal strips in your printout.

 *3 - only when 144 YDPI is selected.  This option is useful if you notice
      tiny white horizontal strips in your printout.

 printer.device/PRD_PRTCOMMAND                   printer.device/PRD_PRTCOMMAND

   NAME
       PRD_PRTCOMMAND -- send a command to the printer

   FUNCTION
      This function sends a command to either the parallel or serial
      device.  The printer device maps this command to the control
      code set of the current printer.  The commands supported can
      be found with the printer.device/Write command.  All printers
      may not support all functions.

   IO REQUEST IOPrtCmdReq
       io_Message      mn_ReplyPort set
       io_Device       preset by OpenDevice
       io_Unit         preset by OpenDevice
       io_Command      PRD_PRTCOMMAND
       io_PrtCommand   the actual command number
       io_Parm0        parameter for the command
       io_Parm1        parameter for the command
       io_Parm2        parameter for the command
       io_Parm3        parameter for the command

   RESULTS
       Errors: if the PRD_PRTCOMMAND succeeded, then io_Error will be zero.
       Otherwise io_Error will be non-zero.  An error of -1 indicates that
       the command is not supported by the current printer driver.  This
       could be used to check if the connected printer supports a particular
       command (italics for example).

   SEE ALSO
       printer.device/Write printer.h, parallel.device, Preferences

 printer.device/PRD_QUERY                             printer.device/PRD_QUERY

   NAME
    PRD_QUERY -- query printer port/line status

   FUNCTION
    This command returns the status of the printer port's lines and
    registers.  Since the printer port uses either the serial or
    parallel port for i/o, the actual status returned is either the
    serial or parallel port's status.

   IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Device	preset by the call to OpenDevice
    io_Command	PRD_QUERY
    io_Data		ptr to 2 UBYTES where result will be stored.

   RESULTS
     io_Data          BIT  ACTIVE  FUNCTION (SERIAL DEVICE)

             LSB       0    low    reserved
                       1    low    reserved
                       2    low    reserved
                       3    low    Data Set Ready
                       4    low    Clear To Send
                       5    low    Carrier Detect
                       6    low    Ready To Send
                       7    low    Data Terminal Ready
             MSB       8    high   read buffer overflow
                       9    high   break sent (most recent output)
                      10    high   break received (as latest input)
                      11    high   transmit x-OFFed
                      12    high   receive x-OFFed
                   13-15           reserved

     io_Data          BIT  ACTIVE  FUNCTION (PARALLEL DEVICE)

                       0     hi     printer busy (offline)
                       1     hi     paper out
                       2     hi     printer selected
                     (WARNING: the bit 2 line is also connected
                      to the serial port's ring indicator pin
                      on the A500 and A2000)
                     3-7            reserved

     io_Actual       1-parallel, 2-serial

 printer.device/PRD_RAWWRITE                       printer.device/PRD_RAWWRITE

   NAME
    PRD_RAWWRITE -- transparent write command

   FUNCTION
    This is a non standard write command that performs no
    processing on the data passed to it.

   IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Command	PRD_RAWWRITE
    io_Flags	IOB_QUICK set if quick I/O is possible
    io_Length	the number of bytes in io_Data
    io_Data		the raw bytes to write to the printer

 printer.device/PWrite                                   printer.device/PWrite

   NAME
    PWrite -- internal write to printer port

   SYNOPSIS
    error = (*PrinterData->pd_PWrite)(buffer, length);
    D0                                  A0      D0

   FUNCTION
    PWrite writes 'length' bytes directly to the printer.  This
    function is generally called by printer drivers to send
    their buffer(s) to the printer.

    This function is accessed by referencing off the PrinterData (PD)
    structure.  Below is a code fragment to show how to do get access
    to a pointer to the PrinterData (PD) structure.

    #include <exec/types.h>
    #include <devices/printer.h>
    #include <devices/prtbase.h>

    struct IODRPReq PReq;
    struct PrinterData *PD;
    struct PrinterExtendedData *PED;

    /* open the printer device (any version); if it opened... */
    if (OpenDevice("printer.device", 0, &PReq, 0) == NULL) {

        /* get pointer to printer data structure */
        PD = (struct PrinterData *)PReq.io_Device;

        /* write something directly to the printer */
        (*PD->pd_PWrite)("Hello world\n", 12);

        CloseDevice(&PReq); /* close the printer device */
    }


Text_Autodocs/trackdisk.doc

TABLE OF CONTENTS

trackdisk.device/CMD_CLEAR
trackdisk.device/CMD_READ
trackdisk.device/CMD_UPDATE
trackdisk.device/CMD_WRITE
trackdisk.device/TD_ADDCHANGEINT
trackdisk.device/TD_CHANGENUM
trackdisk.device/TD_CHANGESTATE
trackdisk.device/TD_EJECT
trackdisk.device/TD_FORMAT
trackdisk.device/TD_GETDRIVETYPE
trackdisk.device/TD_GETGEOMETRY
trackdisk.device/TD_GETNUMTRACKS
trackdisk.device/TD_MOTOR
trackdisk.device/TD_PROTSTATUS
trackdisk.device/TD_RAWREAD
trackdisk.device/TD_RAWWRITE
trackdisk.device/TD_REMCHANGEINT
trackdisk.device/TD_SEEK
 trackdisk.device/CMD_CLEAR                         trackdisk.device/CMD_CLEAR

   NAME
    CMD_CLEAR/ETD_CLEAR -- mark the track buffer as containing invalid
                   data.

   FUNCTION
    These commands mark the track buffer as invalid, forcing a
    reread of the disk on the next operation. ETD_UPDATE or CMD_UPDATE
    would be used to force data out to the disk before turning the motor
    off. ETD_CLEAR or CMD_CLEAR are usually used after having locked out
    the trackdisk.device via the use of the disk resource, when you
    wish to prevent the track from being updated, or when you wish to
    force the track to be re-read. ETD_CLEAR or CMD_CLEAR will not do an
    update, nor will an update command do a clear.

   IO REQUEST INPUT
    io_Device	preset by the call to OpenDevice()
    io_Unit		preset by the call to OpenDevice()
    io_Command	CMD_CLEAR or ETD_CLEAR
    io_Flags	0 or IOF_QUICK
    iotd_Count	(ETD_CLEAR only) maximum allowable change counter
            value.

   IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>

   SEE ALSO
    CMD_WRITE, CMD_UPDATE

 trackdisk.device/CMD_READ                           trackdisk.device/CMD_READ

   NAME
    CMD_READ/ETD_READ -- read sectors of data from a disk.

   FUNCTION
    These commands transfer data from the track buffer to a supplied
    buffer. If the desired sector is already in the track buffer, no disk
    activity is initiated. If the desired sector is not in the buffer, the
    track containing that sector is automatically read in. If the data in
    the current track buffer has been modified, it is written out to the
    disk before a new track is read. ETD_READ will read the sector label
    area if the iotd_SecLabel is non-NULL.

   IO REQUEST INPUT
    io_Device	preset by the call to OpenDevice()
    io_Unit		preset by the call to OpenDevice()
    io_Command	CMD_READ or ETD_READ
    io_Flags	0 or IOF_QUICK
    io_Data		pointer to the buffer where the data should be put
    io_Length	number of bytes to read, must be a multiple of
            TD_SECTOR.
    io_Offset	byte offset from the start of the disk describing
            where to read data from, must be a multiple of
            TD_SECTOR.
    iotd_Count	(ETD_READ only) maximum allowable change counter
            value.
    iotd_SecLabel	(ETD_READ only) NULL or sector label buffer pointer.
            If provided, the buffer must be a multiple of
            TD_LABELSIZE.

   IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>
   NOTES
    Under versions of Kickstart earlier than V36, the io_Data had to
    point to a buffer in chip memory. This restriction is no longer
    present as of Kickstart V36 and beyond.

   SEE ALSO
    CMD_WRITE

 trackdisk.device/CMD_UPDATE                       trackdisk.device/CMD_UPDATE

   NAME
    CMD_UPDATE/ETD_UPDATE -- write out the track buffer if it is dirty.

   FUNCTION
    The trackdisk device does not write data sectors unless it is
    necessary (you request that a different track be used) or until the
    user requests that an update be performed. This improves system speed
    by caching disk operations. These commands ensure that any
    buffered data is flushed out to the disk. If the track buffer has not
    been changed since the track was read in, these commands do nothing.
    ETD_UPDATE command checks for diskchange.

   IO REQUEST INPUT
    io_Device	preset by the call to OpenDevice()
    io_Unit		preset by the call to OpenDevice()
    io_Command	CMD_UPDATE or ETD_UPDATE
    io_Flags	0 or IOF_QUICK
    iotd_Count	(ETD_UPDATE only) maximum allowable change counter
            value.

   IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>

   SEE ALSO
    CMD_WRITE

 trackdisk.device/CMD_WRITE                         trackdisk.device/CMD_WRITE

   NAME
    CMD_WRITE/ETD_WRITE -- write sectors of data to a disk.

   FUNCTION
    These commands transfer data from a supplied buffer to the track
    buffer. If the track that contains this sector is already in the track
    buffer, no disk activity is initiated. If the desired sector is not in
    the buffer, the track containing that sector is automatically read in.
    If the data in the current track buffer has been modified, it is
    written out to the disk before the new track is read in for
    modification. ETD_WRITE will write the sector label area if
    iotd_SecLabel is non-NULL.

   IO REQUEST INPUT
    io_Device	preset by the call to OpenDevice()
    io_Unit		preset by the call to OpenDevice()
    io_Command	CMD_WRITE or ETD_WRITE
    io_Flags	0 or IOF_QUICK
    io_Data		pointer to the buffer where the data should be put
    io_Length	number of bytes to write, must be a multiple of
            TD_SECTOR.
    io_Offset	byte offset from the start of the disk describing
            where to write data to, must be a multiple of
            TD_SECTOR.
    iotd_Count	(ETD_WRITE only) maximum allowable change counter
            value.
    iotd_SecLabel	(ETD_WRITE only) NULL or sector label buffer pointer.
            If provided, the buffer must be a multiple of
            TD_LABELSIZE.

   IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>

   NOTES
    Under versions of Kickstart earlier than V36, the io_Data had to
    point to a buffer in chip memory. This restriction is no longer
    present as of Kickstart V36 and beyond.

   SEE ALSO
    CMD_READ, TD_FORMAT

 trackdisk.device/TD_ADDCHANGEINT             trackdisk.device/TD_ADDCHANGEINT

   NAME
    TD_ADDCHANGEINT -- add a disk change software interrupt handler.

   FUNCTION
    This command lets you add a software interrupt handler to the
    disk device that gets invoked whenever a disk insertion or removal
    occurs.

    You must pass in a properly initialized Exec Interrupt structure
    and be prepared to deal with disk insertions/removals
    immediately. From within the interrupt handler, you may only call the
    status commands that can use IOF_QUICK.

    To set up the handler, an Interrupt structure must be initialized.
    This structure is supplied as the io_Data to the TD_ADDCHANGEINT
    command. The handler then gets linked into the handler chain and
    gets invoked whenever a disk change happens. You must eventually
    remove the handler before you exit.

    This command only returns when the handler is removed. That is,
    the device holds onto the IO request until the TD_REMCHANGEINT command
    is executed with that same IO request. Hence, you must use SendIO()
    with this command.

   IO REQUEST INPUT
    io_Device	preset by the call to OpenDevice()
    io_Unit		preset by the call to OpenDevice()
    io_Command	TD_ADDCHANGEINT
    io_Flags	0
    io_Length	sizeof(struct Interrupt)
    io_Data		pointer to Interrupt structure

   IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>

   SEE ALSO
    TD_REMCHANGEINT, <devices/trackdisk.h>, <exec/interrupts.h>,
    exec.library/Cause()

 trackdisk.device/TD_CHANGENUM                   trackdisk.device/TD_CHANGENUM

   NAME
    TD_CHANGENUM -- return the current value of the disk-change counter.

   FUNCTION
    This command returns the current value of the disk-change counter (as
    used by the enhanced commands). The disk change counter is incremented
    each time a disk is inserted or removed from the trackdisk unit.

   IO REQUEST INPUT
    io_Device	preset by the call to OpenDevice()
    io_Unit		preset by the call to OpenDevice()
    io_Command	TD_CHANGENUM
    io_Flags	0 or IOF_QUICK

   IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>
    io_Actual - if io_Error is 0, this contains the current value of the
            disk-change counter.

 trackdisk.device/TD_CHANGESTATE               trackdisk.device/TD_CHANGESTATE

   NAME
    TD_CHANGESTATE -- check if a disk is currently in a drive.

   FUNCTION
    This command checks to see if there is currently a disk in a drive.

   IO REQUEST INPUT
    io_Device	preset by the call to OpenDevice()
    io_Unit		preset by the call to OpenDevice()
    io_Command	TD_CHANGESTATE
    io_Flags	0 or IOF_QUICK

   IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>
    io_Actual - if io_Error is 0, this tells you whether a disk is in
            the drive. 0 means there is a disk, while anything else
            indicates there is no disk.

 trackdisk.device/TD_EJECT                           trackdisk.device/TD_EJECT

   NAME
       TD_EJECT -- eject the disk in the drive, if possible.

   FUNCTION
    This command causes the drive to attempt to eject the disk in
    it, if any.  Note that the current trackdisk.device does not
    implement this command, but it might in the future, and other
    trackdisk-compatible drivers may implement this command.

   IO REQUEST INPUT
    io_Device	preset by the call to OpenDevice()
    io_Unit		preset by the call to OpenDevice()
    io_Command	TD_EJECT
    io_Flags	0 or IOF_QUICK

   IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>

 trackdisk.device/TD_FORMAT                         trackdisk.device/TD_FORMAT

   NAME
    TD_FORMAT/ETD_FORMAT -- format a track on a disk.

   FUNCTION
    These commands are used to write data to a track that either
    has not yet been formatted or has had a hard error on a standard write
    command. TD_FORMAT completely ignores all data currently on a track and
    does not check for disk change before performing the command. The
    io_Data field must point to at least one track worth of data. The
    io_Offset field must be track aligned, and the io_Length field must be
    in units of track length (that is, NUMSEC*TD_SECTOR).

    The device will format the requested tracks, filling each sector with
    the contents of the buffer pointed to by io_Data. You
    should do a read pass to verify the data.

    If you have a hard write error during a normal write, you may find it
    possible to use the TD_FORMAT command to reformat the track as part of
    your error recovery process. ETD_FORMAT will write the sector label
    area if iotd_SecLabel is non-NULL.

   IO REQUEST INPUT
    io_Device	preset by the call to OpenDevice()
    io_Unit		preset by the call to OpenDevice()
    io_Command	TD_FORMAT or ETD_FORMAT
    io_Flags	0 or IOF_QUICK
    io_Data		points to a buffer containing the data to write to the
            track, must be at least as large as io_Length.
    io_Length	number of bytes to format, must be a multiple of
            (TD_SECTORS * NUMSEC).
    io_Offset	byte offset from the start of the disk for the track to
            format, must be a multiple of (TD_SECTORS * NUMSEC).
    iotd_Count	(ETD_FORMAT only) maximum allowable change counter
            value.
    iotd_SecLabel	(ETD_FORMAT only) NULL or sector label buffer pointer.
            If provided, the buffer must be a multiple of
            (TD_LABELSIZE * NUMSEC).

   IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>

   NOTES
    Under versions of Kickstart earlier than V36, the io_Data had to
    point to a buffer in chip memory. This restriction is no longer
    present as of Kickstart V36 and beyond.

   SEE ALSO
    CMD_WRITE, TD_RAWWRITE

 trackdisk.device/TD_GETDRIVETYPE             trackdisk.device/TD_GETDRIVETYPE

   NAME
    TD_GETDRIVETYPE -- return the type of disk drive for the unit that was
               opened.

   FUNCTION
    This command returns the type of the disk drive to the user.
    This number will be a small integer and will come from the set of
    DRIVEXXX constants defined in <devices/trackdisk.h>.

    The only way you can actually use this command is if the trackdisk
    device understands the drive type of the hardware that is plugged in.
    This is because the OpenDevice() call will fail if the trackdisk device
    does not understand the drive type. To find raw drive identifiers see
    the disk.resource's DR_GETUNITID entry point.

   IO REQUEST INPUT
    io_Device	preset by the call to OpenDevice()
    io_Unit		preset by the call to OpenDevice()
    io_Command	TD_GETDRIVETYPE
    io_Flags	0 or IOF_QUICK

   IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>
    io_Actual - if io_Error is 0 this contains the drive type connected to
            this unit.

   SEE ALSO
    TD_GETNUMTRACKS, <devices/trackdisk.h>

 trackdisk.device/TD_GETGEOMETRY               trackdisk.device/TD_GETGEOMETRY

   NAME
       TD_GETGEOMETRY -- return the geometry of the drive.

   FUNCTION
    This command returns a full set of information about the
    layout of the drive. The information is returned in the
    DriveGeometry structure pointed to by io_Data.

   IO REQUEST INPUT
    io_Device	preset by the call to OpenDevice()
    io_Unit		preset by the call to OpenDevice()
    io_Command	TD_GETGEOMETRY
    io_Flags	0 or IOF_QUICK
    io_Data		Pointer to a DriveGeometry structure
    io_Length	sizeof(struct DriveGeometry)

   IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>

   NOTE
    This information may change when a disk in inserted when
    certain hardware is present.

   SEE ALSO
    TD_GETDRIVETYPE, TD_GETNUMTRACKS

 trackdisk.device/TD_GETNUMTRACKS             trackdisk.device/TD_GETNUMTRACKS

   NAME
    TD_GETNUMTRACKS -- return the number of tracks for the type of disk
               drive for the unit that was opened.

   FUNCTION
    This command returns the number of tracks that are available
    on the disk unit.

   IO REQUEST INPUT
    io_Device	preset by the call to OpenDevice()
    io_Unit		preset by the call to OpenDevice()
    io_Command	TD_GETNUMTRACKS
    io_Flags	0 or IOF_QUICK

   IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>
    io_Actual - if io_Error is 0 this contains the drive type connected to
            this unit.

   SEE ALSO
    TD_GETDRIVETYPE

 trackdisk.device/TD_MOTOR                           trackdisk.device/TD_MOTOR

   NAME
    TD_MOTOR/ETD_MOTOR -- control the on/off state of a drive motor.

   FUNCTION
    This command gives control over the disk motor. The motor may be
    turned on or off. When it is on, the drive light automatically turns
    on as well.

    If the motor is just being turned on, the device will delay the
    proper amount of time to allow the drive to come up to speed. Normally,
    turning the drive on is not necessary, the device does this
    automatically if it receives a request when the motor is off. However,
    turning the motor off is the programmer's responsibility.

    In addition, the standard instructions to the user are that it is safe
    to remove a disk from a drive if and only if the motor is off (that is,
    if the disk light is off).

   IO REQUEST INPUT
    io_Device	preset by the call to OpenDevice()
    io_Unit		preset by the call to OpenDevice()
    io_Command	TD_MOTOR or ETD_MOTOR
    io_Flags	0 or IOF_QUICK
    io_Length	the requested state of the motor, 0 to turn the motor
            off, and 1 to turn the motor on.
    iotd_Count	(ETD_MOTOR only) maximum allowable change counter
            value.

   IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>
    io_Actual - if io_Error is 0 this contains the previous state of the
            drive motor.

 trackdisk.device/TD_PROTSTATUS                 trackdisk.device/TD_PROTSTATUS

   NAME
    TD_PROTSTATUS -- return whether the current disk is write-protected.

   FUNCTION
    This command is used to determine whether the current disk is
    write-protected.

   IO REQUEST INPUT
    io_Device	preset by the call to OpenDevice()
    io_Unit		preset by the call to OpenDevice()
    io_Command	TD_PROTSTATUS
    io_Flags	0 or IOF_QUICK

   IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>
    io_Actual - if io_Error is 0, this tells you whether the disk in the
            drive is write-protected. 0 means the disk is NOT write-
            protected, while any other value indicates it is.

 trackdisk.device/TD_RAWREAD                       trackdisk.device/TD_RAWREAD

   NAME
    TD_RAWREAD/ETD_RAWREAD -- read raw data from the disk.

   FUNCTION
    These commands read a track of raw data from disk and deposits it in
    the provided buffer. The data is taken straight from the disk with
    no processing done on it. It will appear exactly as the bits come out
    off the disk, hopefully in some legal MFM format.

    This interface is intended for sophisticated programmers only.
    Amiga, Inc. reserves the right to make enhancements to the disk
    format in the future. We will provide compatibility via the
    CMD_READ and ETD_READ commands, anyone using TD_RAWREAD is
    bypassing this upwards compatibility, and may thus stop working.

   IO REQUEST INPUT
    io_Device	preset by the call to OpenDevice()
    io_Unit		preset by the call to OpenDevice()
    io_Command      TD_RAWREAD or ETD_RAWREAD.
    io_Flags	if the IOTDB_INDEXSYNC bit is set then the driver
            will make a best effort attempt to start reading
            from the index mark.  Note that there will be at
            least some delay, and perhaps a great deal of delay
            (for example if interrupts have been disabled).
    io_Length	Length of buffer in bytes, with a maximum of 32768
            bytes.
    io_Data		Pointer to CHIP memory buffer where raw track data is
            to be deposited.
    io_Offset	The number of the track to read in.
    iotd_Count	(ETD_RAWREAD only) maximum allowable change counter
            value.

   IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>

   NOTES
    The track buffer provided MUST be in CHIP memory

    There is a delay between the index pulse and the start of bits
    coming in from the drive (e.g. dma started). This delay
    is in the range of 135-200 microseconds. This delay breaks
    down as follows: 55 microsecs is software interrupt overhead
    (this is the time from interrupt to the write of the DSKLEN
    register). 66 microsecs is one horizontal line delay (remember
    that disk IO is synchronized with agnus' display fetches).
    The last variable (0-65 microsecs) is an additional scan line
    since DSKLEN is poked anywhere in the horizontal line. This leaves
    15 microsecs unaccounted for...  Sigh.

    In short, You will almost never get bits within the first 135
    microseconds of the index pulse, and may not get it until 200
    microseconds. At 4 microsecs/bit, this works out to be between
    4 and 7 bytes of user data of delay.

   BUGS
    This command does not work reliably under versions of Kickstart
    earlier than V36, especially on systems with 1 floppy drive.

   SEE ALSO
    TD_RAWWRITE

 trackdisk.device/TD_RAWWRITE                     trackdisk.device/TD_RAWWRITE

   NAME
    TD_RAWWRITE/ETD_RAWWRITE -- write raw data to the disk.

   FUNCTION
    This command writes a track of raw data from the provided buffer to
    the specified track on disk. The data is copied straight to the disk
    with no processing done on it. It will appear exactly on the disk as
    it is in the memory buffer, hopefully in a legal MFM format.

    This interface is intended for sophisticated programmers only.
    Amiga, Inc. reserves the right to make enhancements to the disk
    format in the future. We will provide compatibility via the
    CMD_WRITE and ETD_WRITE commands, anyone using TD_RAWWRITE is
    bypassing this upwards compatibility, and may thus stop working.

   IO REQUEST INPUT
    io_Device	preset by the call to OpenDevice()
    io_Unit		preset by the call to OpenDevice()
    io_Command      TD_RAWWRITE or ETD_RAWWRITE.
    io_Flags	if the IOTDB_INDEXSYNC bit is set then the driver
            will make a best effort attempt to start writing
            from the index mark.  Note that there will be at
            least some delay, and perhaps a great deal of delay
            (for example if interrupts have been disabled).
    io_Length	Length of buffer in bytes, with a maximum of 32768
            bytes.
    io_Data		Pointer to CHIP memory buffer where raw track data is
            to be taken.
    io_Offset	The number of the track to write to.
    iotd_Count	(ETD_RAWWRITE only) maximum allowable change counter
            value.

   IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>

   NOTES
    The track buffer provided MUST be in CHIP memory

    There is a delay between the index pulse and the start of bits
    going out to the driver (e.g. write gate enabled). This delay
    is in the range of 135-200 microseconds. This delay breaks
    down as follows: 55 microsecs is software interrupt overhead
    (this is the time from interrupt to the write of the DSKLEN
    register). 66 microsecs is one horizontal line delay (remember
    that disk IO is synchronized with agnus' display fetches).
    The last variable (0-65 microsecs) is an additional scan line
    since DSKLEN is poked anywhere in the horizontal line. This leaves
    15 microsecs unaccounted for...  Sigh.

    In short, You will almost never get bits within the first 135
    microseconds of the index pulse, and may not get it until 200
    microseconds. At 4 microsecs/bit, this works out to be between
    4 and 7 bytes of user data of delay.

   BUGS
    This command does not work reliably under versions of Kickstart
    earlier than V36, especially on systems with 1 floppy drive.

   SEE ALSO
    TD_RAWREAD

 trackdisk.device/TD_REMCHANGEINT             trackdisk.device/TD_REMCHANGEINT

   NAME
    TD_REMCHANGEINT -- remove a disk change software interrupt handler.

   FUNCTION
    This command removes a disk change software interrupt added
    by a previous use of TD_ADDCHANGEINT.

   IO REQUEST INPUT
    The same IO request used for TD_ADDCHANGEINT.

    io_Device	preset by the call to OpenDevice()
    io_Unit		preset by the call to OpenDevice()
    io_Command	TD_REMCHANGEINT
    io_Flags	0
    io_Length	sizeof(struct Interrupt)
    io_Data		pointer to Interrupt structure

   IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>

   BUGS
    This command did not function properly under versions of Kickstart
    earlier than V36. A valid workaround under these older versions of
    Kickstart is:

        Forbid();
        Remove(ioRequest);
        Permit();

    Do not use this workaround in versions of Kickstart >= V36, use
    TD_REMCHANGEINT instead (for future compatibility with V38+).

   SEE ALSO
    TD_ADDCHANGEINT, <devices/trackdisk.h>

 trackdisk.device/TD_SEEK                             trackdisk.device/TD_SEEK

   NAME
    TD_SEEK/ETD_SEEK -- control positioning of the drive heads.

   FUNCTION
    These commands are currently provided for internal diagnostics,
    disk repair, and head cleaning only.

    TD_SEEK and ETD_SEEK move the drive heads to the track specified. The
    io_Offset field should be set to the (byte) offset to which the seek is
    to occur. TD_SEEK and ETD_SEEK do not verify their position until the
    next read. That is, they only move the heads; they do not actually read
    any data.

   IO REQUEST INPUT
    io_Device	preset by the call to OpenDevice()
    io_Unit		preset by the call to OpenDevice()
    io_Command	TD_SEEK or ETD_SEEK
    io_Flags	0 or IOF_QUICK
    io_Offset	byte offset from the start of the disk describing
            where to move the head to.
    iotd_Count	(ETD_SEEK only) maximum allowable change counter
            value.

   IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>


Text_Autodocs/battclock.doc

TABLE OF CONTENTS

battclock.resource/ReadBattClock
battclock.resource/ResetBattClock
battclock.resource/WriteBattClock
 battclock.resource/ReadBattClock             battclock.resource/ReadBattClock

   NAME
    ReadBattClock -- Read time from clock chip.  (V36)

   SYNOPSIS
    AmigaTime = ReadBattClock( )

    ULONG ReadBattClock( void );
    D0

   FUNCTION
    This routine reads the time from the clock chip and returns it
    as the number of seconds from 01-jan-1978.

   INPUTS

   RESULTS
    AmigaTime       The number of seconds from 01-Jan-1978 that
                        the clock chip thinks it is.

   NOTES
    If the clock chip returns an invalid date, the clock chip is
    reset and 0 is returned.

   SEE ALSO

   BUGS

 battclock.resource/ResetBattClock           battclock.resource/ResetBattClock

   NAME
    ResetBattClock -- Reset the clock chip.  (V36)

   SYNOPSIS
    ResetBattClock( )

    void ResetBattClock( void );

   FUNCTION
    This routine does whatever is neeeded to put the clock chip
    into a working and usable state and also sets the date on the
    clock chip to 01-Jan-1978.

   INPUTS

   RESULTS

   NOTES

   SEE ALSO

   BUGS

 battclock.resource/WriteBattClock           battclock.resource/WriteBattClock

   NAME
    WriteBattClock -- Set the time on the clock chip.  (V36)

   SYNOPSIS
    WriteBattClock( AmigaTime )
                    D0

    void WriteBattClock( ULONG );

   FUNCTION
    This routine writes the time given in AmigaTime to the clock
    chip.

   INPUTS
    AmigaTime       The number of seconds from 01-Jan-1978 to the
                        time that should be written to the clock
                        chip.

   RESULTS

   NOTES

   SEE ALSO

   BUGS


Text_Autodocs/cia.doc

TABLE OF CONTENTS

cia.resource/AbleICR
cia.resource/AddICRVector
cia.resource/RemICRVector
cia.resource/SetICR
 cia.resource/AbleICR                                     cia.resource/AbleICR

   NAME
    AbleICR -- Enable/disable ICR interrupts.

   SYNOPSIS
    oldMask = AbleICR( Resource, mask )
    D0                 A6        D0

    WORD AbleICR( struct Library *, WORD );

   FUNCTION
    This function provides a means of enabling and disabling 8520
    CIA interrupt control registers. In addition it returns the
    previous enable mask.

   INPUTS
    mask            A bit mask indicating which interrupts to be
                        modified. If bit 7 is clear the mask
                        indicates interrupts to be disabled. If
                        bit 7 is set, the mask indicates
                        interrupts to be enabled. Bit positions
                        are identical to those in 8520 ICR.

   RESULTS
    oldMask         The previous enable mask before the requested
                        changes. To get the current mask without
                        making changes, call the function with a
                        null parameter.

   EXAMPLES
    Get the current mask:
        mask = AbleICR(0)
    Enable both timer interrupts:
        AbleICR(0x83)
    Disable serial port interrupt:
        AbleICR(0x08)

   EXCEPTIONS
    Enabling the mask for a pending interrupt will cause an
    immediate processor interrupt (that is if everything else is
    enabled). You may want to clear the pending interrupts with
    SetICR() prior to enabling them.

   NOTE
    The CIA resources are special in that there is more than one
    of them in the system. Because of this, the C language stubs
    in amiga.lib for the CIA resources require an extra parameter
    to specify which CIA resource to use. The synopsys for the
    amiga.lib stubs is as follows:

    oldMask = AbleICR( Resource, mask )
    D0                 A6        D0

    WORD AbleICR( struct Library *, WORD );

   SEE ALSO
    cia.resource/SetICR()

 cia.resource/AddICRVector                           cia.resource/AddICRVector

   NAME
    AddICRVector -- attach an interrupt handler to a CIA bit.

   SYNOPSIS
    interrupt = AddICRVector( Resource, iCRBit, interrupt )
    D0                        A6        D0      A1

    struct Interrupt *AddICRVector( struct Library *, WORD,
        struct Interrupt * );

   FUNCTION
    Assign interrupt processing code to a particular interrupt bit
    of the CIA ICR.  If the interrupt bit has already been
    assigned, this function will fail, and return a pointer to the
    owner interrupt.  If it succeeds, a null is returned.

    This function will also enable the CIA interrupt for the given
    ICR bit.

   INPUTS
    iCRBit          Bit number to set (0..4).
    interrupt       Pointer to interrupt structure.

   RESULT
    interrupt       Zero if successful, otherwise returns a
                        pointer to the current owner interrupt
                        structure.

   NOTE
    A processor interrupt may be generated immediatly if this call
    is successful.

    In general, it is probably best to only call this function
    while DISABLED so that the resource to which the interrupt
    handler is being attached may be set to a known state before
    the handler is called. You MUST NOT change the state of the
    resource before attaching your handler to it.

    The CIA resources are special in that there is more than one
    of them in the system. Because of this, the C language stubs
    in amiga.lib for the CIA resources require an extra parameter
    to specify which CIA resource to use. The synopsys for the
    amiga.lib stubs is as follows:

    interrupt = AddICRVector( Resource, iCRBit, interrupt )
    D0                        A6        D0      A1

    struct Interrupt *AddICRVector( struct Library *, WORD,
        struct Interrupt *);

    ***WARNING***

    Never assume that any of the CIA hardware is free for use.
    Always use the AddICRVector() function to obtain ownership
    of the CIA hardware registers your code will use.

    Note that there are two (2) interval timers per CIA.  If
    your application needs one of the interval timers, you
    can try to obtain any one of the four (4) until AddICRVector()
    succeeds.  If all four interval timers are in-use, your
    application should exit cleanly.

    If you just want ownership of a CIA hardware timer, or register,
    but do not want interrupts generated, use the AddICRVector()
    function to obtain ownership, and use the AbleICR() function
    to turn off (or on) interrupts as needed.

    Note that CIA-B generates level 6 interrupts (which can degrade
    system performance by blocking lower priority interrupts).  As
    usual, interrupt handling code should be optimized for speed.

    Always call RemICRVector() when your code exits to release
    ownership of any CIA hardware obtained with AddICRVector().

   SEE ALSO
    cia.resource/RemICRVector(), cia.resource/AbleICR()

 cia.resource/RemICRVector                           cia.resource/RemICRVector

   NAME
    RemICRVector -- Detach an interrupt handler from a CIA bit.

   SYNOPSIS
    RemICRVector( Resource, iCRBit, interrupt )
                  A6        D0      A1

    void RemICRVector( struct Library *, WORD, struct Interrupt *);

   FUNCTION
    Disconnect interrupt processing code for a particular
    interrupt bit of the CIA ICR.

    This function will also disable the CIA interrupt for the
    given ICR bit.

   INPUTS
    iCRBit          Bit number to set (0..4).
    interrupt       Pointer to interrupt structure.

   RESULT

   NOTE
    The CIA resources are special in that there is more than one
    of them in the system. Because of this, the C language stubs
    in amiga.lib for the CIA resources require an extra parameter
    to specify which CIA resource to use. The synopsys for the
    amiga.lib stubs is as follows:

    RemICRVector( Resource, iCRBit, interrupt )
                  A6        D0      A1

    void RemICRVector( struct Library *, WORD, struct Interrupt *);

   SEE ALSO
    cia.resource/AddICRVector()

 cia.resource/SetICR                                       cia.resource/SetICR

   NAME
    SetICR -- Cause, clear, and sample ICR interrupts.

   SYNOPSIS
    oldMask = SetICR( Resource, mask )
    D0                A6        D0

    WORD SetICR( struct Library *, WORD );

   FUNCTION
    This function provides a means of reseting, causing, and
    sampling 8520 CIA interrupt control registers.

   INPUTS
    mask            A bit mask indicating which interrupts to be
                        effected. If bit 7 is clear the mask
                        indicates interrupts to be reset.  If bit
                        7 is set, the mask indicates interrupts to
                        be caused. Bit positions are identical to
                        those in 8520 ICR.

   RESULTS
    oldMask         The previous interrupt register status before
                        making the requested changes.  To sample
                        current status without making changes,
                        call the function with a null parameter.

   EXAMPLES
    Get the interrupt mask:
        mask = SetICR(0)
    Clear serial port interrupt:
        SetICR(0x08)

   NOTE
    The CIA resources are special in that there is more than one
    of them in the system. Because of this, the C language stubs
    in amiga.lib for the CIA resources require an extra parameter
    to specify which CIA resource to use. The synopsys for the
    amiga.lib stubs is as follows:

    oldMask = SetICR( Resource, mask )
    D0                A6        D0

    WORD SetICR( struct Library *, WORD );

    ***WARNING***

    Never read the contents of the CIA interrupt control registers
    directly.  Reading the contents of one of the CIA interrupt
    control registers clears the register.  This can result in
    interrupts being missed by critical operating system code, and
    other applications.

   EXCEPTIONS
    Setting an interrupt bit for an enabled interrupt will cause
    an immediate interrupt.

   SEE ALSO
    cia.resource/AbleICR()


Text_Autodocs/filesysres.doc

TABLE OF CONTENTS

FileSystem.resource/--background--

FileSystem.resource/--background--           FileSystem.resource/--background--

   PURPOSE

    The FileSystem.resource is where boot disk drivers rendezvous
    to share file system code segments for partitions specified by
    dos type.  Prior to V36, it was created by the first driver
    that needed to use it.  For V36, its creation is ensured by the
    rom boot process.

   CONTENTS

    The FileSystem.resource is described in the include file
    resources/filesysres.h.  The nodes on it describe how to
    algorithmically convert the result of MakeDosNode (from the
    expansion.library) to a node appropriate for the dos type.

    FileSysEntry
        fse_Node		on fsr_FileSysEntries list
                ln_Name is of creator of this entry
        fse_DosType		DosType of this FileSys: e.g. 0x444f5301
                for the fast file system.
        fse_Version		high word is the version, low word is
                the revision.
        fse_PatchFlags	bits set for those of the following that
                need to be substituted into a standard
                device node for this file system: e.g.
                $180 for substitute SegList & GlobalVec
        fse_Type		device node type: zero
        fse_Task		standard dos "task" field
        fse_Lock		must be zero
        fse_Handler		for V36, if bit 31 is set, this is not
                an AmigaDOS partition.
        fse_StackSize	stacksize to use when starting task
        fse_Priority	task priority when starting task
        fse_Startup		startup msg: FileSysStartupMsg for disks
        fse_SegList		segment of code to run to start new task
        fse_GlobalVec	BCPL global vector when starting task

    no more entries need exist than those implied by fse_PatchFlags,
    so entries do not have a fixed size.  For V36, for example, the
    entry for the fast file system (fse_DosType 0x444f5301)
    contains a zero fse_PatchFlags, and thus no entries beyond that.


Text_Autodocs/potgo.doc

TABLE OF CONTENTS

potgo.resource/AllocPotBits
potgo.resource/FreePotBits
potgo.resource/WritePotgo
 potgo.resource/AllocPotBits                       potgo.resource/AllocPotBits

   NAME
    AllocPotBits -- Allocate bits in the potgo register.

   SYNOPSIS
    allocated = AllocPotBits(bits)
    D0                       D0

    UWORD AllocPotBits( UWORD );

   FUNCTION
    The AllocPotBits routine allocates bits in the hardware potgo
    register that the application wishes to manipulate via
    WritePotgo.  The request may be for more than one bit.  A
    user trying to allocate bits may find that they are
    unavailable because they are already allocated, or because
    the start bit itself (bit 0) has been allocated, or if
    requesting the start bit, because input bits have been
    allocated.  A user can block itself from allocation: i.e.
    it should FreePotgoBits the bits it has and re-AllocPotBits if
    it is trying to change an allocation involving the start bit.

   INPUTS
    bits - a description of the hardware bits that the application
        wishes to manipulate, loosely based on the register
        description itself:
        START (bit 0) - set if you wish to use start (i.e. start
            the proportional controller counters) with the
            input ports you allocate (below).  You must
            allocate all the DATxx ports you want to apply
            START to in this same call, with the OUTxx bit
            clear.
        DATLX (bit 8) - set if you wish to use the port associated
            with the left (0) controller, pin 5.
        OUTLX (bit 9) - set if you promise to use the LX port in
            output mode only.  The port is not set to output
            for you at this time -- this bit set indicates
            that you don't mind if STARTs are initiated at any
            time by others, since ports that are enabled for
            output are unaffected by START.
        DATLY (bit 10) - as DATLX but for the left (0) controller,
            pin 9.
        OUTLY (bit 11) - as OUTLX but for LY.
        DATRX (bit 12) - the right (1) controller, pin 5.
        OUTRX (bit 13) - OUT for RX.
        DATRY (bit 14) - the right (1) controller, pin 9.
        OUTRY (bit 15) - OUT for RY.

   RESULTS
    allocated - the START and DATxx bits of those requested that
        were granted.  The OUTxx bits are don't cares.

 potgo.resource/FreePotBits                         potgo.resource/FreePotBits

   NAME
    FreePotBits -- Free allocated bits in the potgo register.

   SYNOPSIS
    FreePotBits(allocated)
                D0

    void FreePotBits( UWORD );

   FUNCTION
    The FreePotBits routine frees previously allocated bits in the
    hardware potgo register that the application had allocated via
    AllocPotBits and no longer wishes to use.  It accepts the
    return value from AllocPotBits as its argument.

 potgo.resource/WritePotgo                           potgo.resource/WritePotgo

   NAME
    WritePotgo -- Write to the hardware potgo register.

   SYNOPSIS
    WritePotgo(word, mask)
               D0    D1

    void WritePotgo( UWORD, UWORD );

   FUNCTION
    The WritePotgo routine sets and clears bits in the hardware
    potgo register.  Only those bits specified by the mask are
    affected -- it is improper to set bits in the mask that you
    have not successfully allocated.  The bits in the high byte
    are saved to be maintained when other users write to the
    potgo register.  The START bit is not saved, it is written
    only explicitly as the result of a call to this routine with
    the START bit set: other users will not restart it.

   INPUTS
    word - the data to write to the hardware potgo register and
        save for further use, except the START bit, which is
        not saved.
    mask - those bits in word that are to be written.  Other
        bits may have been provided by previous calls to
        this routine, and default to zero.


Text_Autodocs/battmem.doc

TABLE OF CONTENTS

battmem.resource/ObtainBattSemaphore
battmem.resource/ReadBattMem
battmem.resource/ReleaseBattSemaphore
battmem.resource/WriteBattMem
 battmem.resource/ObtainBattSemaphore     battmem.resource/ObtainBattSemaphore

   NAME
    ObtainBattSemaphore -- Obtain access to nonvolatile ram. (V36)

   SYNOPSIS
    ObtainBattSemaphore( )

    void ObtainBattSemaphore( void );

   FUNCTION
    Aquires exclusive access to the system nonvolatile ram.

   INPUTS

   RESULTS

   NOTES

   SEE ALSO

   BUGS

 battmem.resource/ReadBattMem                     battmem.resource/ReadBattMem

   NAME
    ReadBattMem -- Read a bitstring from nonvolatile ram.  (V36)

   SYNOPSIS
    Error = ReadBattMem( Buffer, Offset, Len )
    D0                   A0      D0      D1

    ULONG ReadBattMem( APTR, ULONG, ULONG );

   FUNCTION
    Read a bitstring from nonvolatile ram.

   INPUTS
    Buffer          Where to put the bitstring.
    Offset          Bit offset of first bit to read.
    Len             Length of bitstring to read.

   RESULTS
    Error           Zero if no error.

   NOTES
    The battery-backed memory is checksummed. If a checksum error
    is detected, all bits in the battery-backed memory are
    silently set to zero.

    Bits in the battery-backed memory that do not exist are read
    as zero.

    Partial byte reads (less than 8 bits) result in the bits read
    being put in the low-order bits of the destination byte.

   SEE ALSO

   BUGS

 battmem.resource/ReleaseBattSemaphore   battmem.resource/ReleaseBattSemaphore

   NAME
    ReleaseBattSemaphore -- Allow nonvolatile ram to others.  (V36)

   SYNOPSIS
    ReleaseBattSemaphore( )

    void ReleaseBattSemaphore( void );

   FUNCTION
    Relinquish exclusive access to the system nonvolatile ram.

   INPUTS

   RESULTS

   NOTES

   SEE ALSO

   BUGS

 battmem.resource/WriteBattMem                   battmem.resource/WriteBattMem

   NAME
    WriteBattMem -- Write a bitstring to nonvolatile ram.  (V36)

   SYNOPSIS
    Error = WriteBattMem( Buffer, Offset, Len )
    D0                    A0      D0      D1

    ULONG WriteBattMem( APTR, ULONG, ULONG );

   FUNCTION
    Write a bitstring to the nonvolatile ram.

   INPUTS
    Buffer          Where to get the bitstring.
    Offset          Bit offset of first bit to write.
    Len             Length of bitstring to write.

   RESULTS
    Error           Zero if no error.

   NOTES
    The battery-backed memory is checksummed. If a checksum error
    is detected, all bits in the battery-backed memory are
    silently set to zero.

    Partial byte writes (less than 8 bits) result in the bits
    written being read from the low-order bits of the source byte.

   SEE ALSO

   BUGS


Text_Autodocs/disk.doc

TABLE OF CONTENTS

disk.resource/AllocUnit
disk.resource/FreeUnit
disk.resource/GetUnit
disk.resource/GetUnitID
disk.resource/GiveUnit
disk.resource/ReadUnitID
 disk.resource/AllocUnit                               disk.resource/AllocUnit

   NAME
       AllocUnit - allocate a unit of the disk

   SYNOPSIS
       Success = AllocUnit( unitNum ), DRResource
    D0     	             D0         A6

    BOOL AllocUnit(LONG);

   FUNCTION
    This routine allocates one of the units of the disk.  It should
    be called before trying to use the disk (via GetUnit).

    In reality, it is perfectly fine to use GetUnit/GiveUnit if AllocUnit
    fails.  Do NOT call FreeUnit if AllocUnit did not succeed.  This
    has been the case for all revisions of disk.resource.

   INPUTS
    unitNum -- a legal unit number (zero through three)

   RESULTS
    Success -- nonzero if successful.  zero on failure.

   EXCEPTIONS

   SEE ALSO

   BUGS

 disk.resource/FreeUnit                                 disk.resource/FreeUnit

   NAME
       FreeUnit - deallocate the disk

   SYNOPSIS
       FreeUnit( unitNum ), DRResource
          D0         A6

    void FreeUnit(LONG);

   FUNCTION
    This routine deallocates one of the units of the disk.  It should
    be called when done with the disk.  Do not call it if you did
    no successfully allocate the disk (there is no protection -- you
    will probably crash the disk system).

   INPUTS
    unitNum -- a legal unit number (zero through three)

   RESULTS

   EXCEPTIONS

   SEE ALSO
    FreeUnit

   BUGS
    Doesn't check if you own the unit, or even if anyone owns it.

 disk.resource/GetUnit                                   disk.resource/GetUnit

   NAME
       GetUnit - allocate the disk for a driver

   SYNOPSIS
       lastDriver = GetUnit( unitPointer ), DRResource
       D0		      A1             A6

    struct DiscResourceUnit *GetUnit(struct DiscResourceUnit *);

   FUNCTION
    This routine allocates the disk to a driver.  It is either
    immediately available, or the request is saved until the disk
    is available.  When it is available, your unitPointer is
    sent back to you (via ReplyMsg).  You may then reattempt the
    GetUnit.

    Allocating the disk allows you to use the disk's resources.
    Remember however that there are four units to the disk; you are
    only one of them.  Please be polite to the other units (by never
    selecting them, and by not leaving interrupts enabled, etc.).

    When you are done, please leave the disk in the following state:
        dmacon dma bit ON
        dsklen dma bit OFF (write a #DSKDMAOFF to dsklen)
        adkcon disk bits -- any way you want
        entena:disk sync and disk block interrupts -- Both DISABLED
        CIA resource index interrupt -- DISABLED
        8520 outputs -- doesn't matter, because all bits will be
        set to inactive by the resource.
        8520 data direction regs -- restore to original state.

    NOTE: GetUnit() does NOT turn on the interrupts for you.
          You must use AbleICR (for the index interrupt) or intena
          (for the diskbyte and diskblock interrupts) to turn them
          on.  You should turn them off before calling GiveUnit,
          as stated above.

   INPUTS
    unitPtr - a pointer you your disk resource unit structure.
        Note that the message filed of the structure MUST
        be a valid message, ready to be replied to.  Make sure
        ln_Name points to a null-terminated string, preferably
        one that identifies your program.

        You need to set up the three interrupt structures,
        in particular the IS_DATA and IS_CODE fields.  Set them
        to NULL if you don't need that interrupt.  Also, set
        the ln_Type of the interrupt structure to NT_INTERRUPT.
        WARNING: don't turn on a disk resource interrupt unless
        the IS_CODE for that interrupt points to executable code!

        IS_CODE will be called with IS_DATA in A1 when the
        interrupt occurs.  Preserve all regs but D0/D1/A0/A1.
        Do not make assumptions about A0.

   RESULTS
    lastDriver - if the disk is not busy, then the last unit
        to use the disk is returned.  This may be used to
        see if a driver needs to reset device registers.
        (If you were the last user, then no one has changed
        any of the registers.  If someone else has used it,
        then any allowable changes may have been made).  If the
        disk is busy, then a null is returned.

   EXCEPTIONS

   SEE ALSO
    GiveUnit

   BUGS

 disk.resource/GetUnitID                               disk.resource/GetUnitID

   NAME
       GetUnitID - find out what type of disk is out there

   SYNOPSIS
       idtype = GetUnitID( unitNum ), DRResource
    D0	            D0         A6

    LONG GetUnitID(LONG);

   FUNCTION
    Gets the drive ID for a given unit.  Note that this value may
    change if someone calls ReadUnitID, and the drive id changes.

   INPUTS
    unitNum -- a legal unit number (zero through three)

   RESULTS
    idtype -- the type of the disk drive.  Standard types are
        defined in the resource include file.

   EXCEPTIONS

   SEE ALSO
    ReadUnitID

   BUGS

 disk.resource/GiveUnit                                 disk.resource/GiveUnit

   NAME
       GiveUnit - Free the disk back up

   SYNOPSIS
       GiveUnit(), DRResource
                   A6

    void GiveUnit();

   FUNCTION
    This routine frees the disk after a driver is done with it.
    If others are waiting, it will notify them.

   INPUTS

   RESULTS

   EXCEPTIONS

   SEE ALSO
    GetUnit

   BUGS
    In pre-V36, GiveUnit didn't check if you owned the unit.  A patch
    for this was part of 1.3.1 SetPatch.  Fixed in V36.

 disk.resource/ReadUnitID                             disk.resource/ReadUnitID

   NAME
       ReadUnitID - reread and return the type of drive (V37)

   SYNOPSIS
       idtype = ReadUnitID( unitNum ), DRResource
    D0	               D0         A6

    ULONG ReadUnitID(LONG);

   FUNCTION
    Rereads the drive id for a specific unit (for handling drives
    that change ID according to what sort of disk is in them.  You
    MUST have done a GetUnit before calling this function!

   INPUTS
    unitNum -- a legal unit number (zero through three)

   RESULTS
    idtype -- the type of the disk drive.  Standard types are
        defined in the resource include file.

   EXCEPTIONS

   SEE ALSO
    GetUnitID

   BUGS


Text_Autodocs/misc.doc

TABLE OF CONTENTS

misc.resource/AllocMiscResource
misc.resource/FreeMiscResource
 misc.resource/AllocMiscResource               misc.resource/AllocMiscResource

    NAME
    AllocMiscResource - allocate one of the miscelaneous resources

   SYNOPSIS
    CurrentUser = AllocMiscResource( unitNum, name )
    D0				 D0	  A1

    char * AllocMiscResource(ULONG,char *);

   FUNCTION
    This routine attempts to allocate one of the miscellaneous resources
    If the resource had already been allocated, an error is returned. If
    you do get it, your name is associated with the resource (so a user
    can see who has it allocated).

    This function may not be called from interrupt code

   DESCRIPTION
    There are certain parts of the hardware that a multitasking- friendly
    program may need to take over.	The serial port is a good example. By
    grabbing the misc.resource for the serial port, the caller would
    "own" the hardware registers associated with that function.  Nobody
    else, including the system serial driver, is allowed to interfere.

    Resources are called in exactly the same manner as libraries.
    From assembly language, A6 must equal the resource base.  The
    offsets for the function are listed in the resources/misc.i
    include file (MR_ALLOCMISCRESOURCE for this function).

   INPUTS
    unitNum - the number of the resource you want to allocate
          (eg.  MR_SERIALBITS).
    name - a mnenonic name that will help the user figure out
        what piece of software is hogging a resource.
        (havoc breaks out if a name of null is passed in...)

   RESULTS
    CurrentUser - if the resource is busy, then the name of
        the current user is returned.  If the resource is
        free, then null is returned.

   BUGS

   SEE ALSO
    resources/misc.i, FreeMiscResource()
 misc.resource/FreeMiscResource                 misc.resource/FreeMiscResource

   NAME
    FreeMiscResource - make a resource available for reallocation

   SYNOPSIS
    FreeMiscResource( unitNum )
              D0

    void FreeMiscResource(ULONG);

   FUNCTION
    This routine frees one of the resources allocated
    by AllocMiscResource.  The resource is made available
    for reuse.

    FreeMiscResource must be called from the same task that
    called AllocMiscResource.  This function may not be called from
    interrupt code.

    INPUTS
    unitNum - the number of the miscellaneous resource to be freed.

    RESULTS
    Frees the appropriate resource.

    BUGS

    SEE ALSO
    resources/misc.i, AllocMiscResource()


Autodocs Table of Contents

Modules

   amigaguide
   amigaguide_dtc
   amiga_lib
   animation_dtc
   arexx_cl
   asl
   audio
   battclock
   battmem
   bevel_ic
   bitmap_ic
   bullet
   button_gc
   cardres
   cd
   checkbox_gc
   chooser_gc
   cia
   clicktab_gc
   clipboard
   colorwheel_gc
   commodities
   console
   datatypes
   ddebug_lib
   debug_lib
   disk
   diskfont
   dos
   drawlist_ic
   exec
   expansion
   filesysres
   fuelgauge_gc
   gadtools
   gameport
   getfile_gc
   getfont_gc
   getscreenmode_gc
   glyph_ic
   gradientslider_gc
   graphics
   icon
   iffparse
   input
   integer_gc
   intuition
   keyboard
   keymap
   label_ic
   layers
   layout_gc
   listbrowser_gc
   locale
   lowlevel
   mathffp
   mathieeedoubbas
   mathieeedoubtrans
   mathieeesingbas
   mathieeesingtrans
   mathtrans
   misc
   narrator
   nonvolatile
   page_gc
   palette_gc
   parallel
   penmap_ic
   picture_dtc
   port-handler
   potgo
   printer
   queue-handler
   radiobutton_gc
   reaction_lib
   realtime
   resource
   rexxsyslib
   scroller_gc
   serial
   sound_dtc
   speedbar_gc
   string_gc
   text_dtc
   timer
   trackdisk
   translator
   utility
   wb
   window_cl

Indices

  Library Function Index
  Device Command Index
  C Structure Index


Library Function Index

1169 entries in this index

AbleICR()                     AbortAslRequest()             AbortIO()
AbortPkt()                    ACrypt()                      ActivateAslRequest()
ActivateCxObj()               ActivateGadget()              ActivateLayoutGadget()
ActivateWindow()              AddAmigaGuideHostA()          AddAnimOb()
AddAppIconA()                 AddAppMenuItemA()             AddAppWindowA()
AddAppWindowDropZoneA()       AddBob()                      AddBootNode()
AddBuffers()                  AddClass()                    AddConfigDev()
AddDevice()                   AddDosEntry()                 AddDosNode()
AddDTObject()                 AddFont()                     AddFreeList()
AddGadget()                   AddGList()                    AddHead()
AddICRVector()                AddIEvents()                  AddIntServer()
AddKBInt()                    AddLibrary()                  AddMemHandler()
AddMemList()                  AddNamedObject()              AddPart()
AddPort()                     AddResource()                 AddSegment()
AddSemaphore()                AddTail()                     AddTask()
AddTime()                     AddTimerInt()                 AddTOF()
AddVBlankInt()                AddVSprite()                  afp()
Alert()                       AllocAbs()                    AllocAslRequest()
Allocate()                    AllocateTagItems()            AllocBitMap()
AllocChooserNodeA()           AllocClickTabNodeA()          AllocConfigDev()
AllocDBufInfo()               AllocDosObject()              AllocEntry()
AllocExpansionMem()           AllocFileRequest()            AllocIFF()
AllocListBrowserNodeA()       AllocLocalItem()              AllocMem()
AllocMiscResource()           AllocNamedObjectA()           AllocPooled()
AllocPotBits()                AllocRadioButtonNodeA()       AllocRaster()
AllocRemember()               AllocScreenBuffer()           AllocSignal()
AllocSpeedButtonNodeA()       AllocSpriteDataA()            AllocTrap()
AllocUnit()                   AllocVec()                    Amiga2Date()
amigaguide.datatype()         AmigaGuideSignal()            AndRectRegion()
AndRegionRegion()             Animate()                     animation.datatype()
ApplyTagChanges()             AreaCircle()                  AreaDraw()
AreaEllipse()                 AreaEnd()                     AreaMove()
ArgArrayDone()                ArgArrayInit()                ArgInt()
ArgString()                   arnd()                        AskFont()
AskKeyMapDefault()            AskSoftStyle()                AslRequest()
AssignAdd()                   AssignLate()                  AssignLock()
AssignPath()                  AttachCxObj()                 AttachPalExtra()
AttemptLockDosList()          AttemptLockLayerRom()         AttemptRemNamedObject()
AttemptSemaphore()            AttemptSemaphoreShared()      AutoRequest()
AvailFonts()                  AvailMem()                    BeginCardAccess()
BeginIO()                     BeginRefresh()                BeginUpdate()
BehindLayer()                 BestModeIDA()                 BEVEL_GetClass()
BitMapScale()                 BITMAP_GetClass()             BltBitMap()
BltBitMapRastPort()           BltClear()                    BltMaskBitMapRastPort()
BltPattern()                  BltTemplate()                 BrowserNodesA()
BuildEasyRequestArgs()        BuildSysRequest()             BumpRevision()
BUTTON_GetClass()             CacheClearE()                 CacheClearU()
CacheControl()                CachePostDMA()                CachePreDMA()
CalcIVG()                     CallErrHook()                 CallHook()
CallHookA()                   CallHookPkt()                 CardAccessSpeed()
CardChangeCount()             CardForceChange()             CardInterface()
CardMiscControl()             CardProgramVoltage()          CardResetCard()
CardResetRemove()             Cause()                       CBump()
CDInputHandler()              ChangeExtSpriteA()            ChangeMode()
ChangeScreenBuffer()          ChangeSprite()                ChangeToSelectedIconColor()
ChangeVPBitMap()              ChangeWindowBox()             ChangeWorkbenchSelectionA()
CHECKBOX_GetClass()           CheckDate()                   CheckIO()
CheckRexxMsg()                CheckSignal()                 ChooserLabelsA()
CHOOSER_GetClass()            ClearCxObjError()             ClearDMRequest()
ClearEOL()                    ClearMenuStrip()              ClearPointer()
ClearRectRegion()             ClearRegion()                 ClearRexxMsg()
ClearScreen()                 Cli()                         ClickTabsA()
CLICKTAB_GetClass()           CliInitNewcli()               CliInitRun()
ClipBlit()                    CloneTagItems()               Close()
CloseAmigaGuide()             CloseCatalog()                CloseClipboard()
CloseDevice()                 CloseEngine()                 CloseFont()
CloseIFF()                    CloseLibrary()                CloseLocale()
CloseMonitor()                CloseScreen()                 CloseWindow()
CloseWorkBench()              CloseWorkbenchObjectA()       CmpTime()
CoerceMethod()                CoerceMethodA()               CoerceMode()
ColdReboot()                  CollectionChunk()             CollectionChunks()
colorwheel.gadget()           CompareDates()                ConfigBoard()
ConvertHSBToRGB()             ConvertRGBToHSB()             ConvToLower()
ConvToUpper()                 CopyMem()                     CopyMemQuick()
CopySBitMap()                 CopyTuple()                   CreateArgstring()
CreateBehindHookLayer()       CreateBehindLayer()           CreateContext()
CreateCxObj()                 CreateDir()                   CreateExtIO()
CreateGadgetA()               CreateIORequest()             CreateMenusA()
CreateMsgPort()               CreateNewProc()               CreatePlayer()
CreatePool()                  CreatePort()                  CreateProc()
CreateRexxMsg()               CreateStdIO()                 CreateTask()
CreateUpfrontHookLayer()      CreateUpfrontLayer()          CurrentChunk()
CurrentDir()                  CurrentTime()                 CxBroker()
CxCustom()                    CxDebug()                     CxFilter()
CxMsgData()                   CxMsgID()                     CxMsgType()
CxObjError()                  CxObjType()                   CxSender()
CxSignal()                    CxTranslate()                 Date2Amiga()
DateStamp()                   DateToStr()                   dbf()
DDoFmt()                      Deallocate()                  Debug()
Delay()                       DeleteArgstring()             DeleteCxObj()
DeleteCxObjAll()              DeleteDiskObject()            DeleteExtIO()
DeleteFile()                  DeleteIORequest()             DeleteLayer()
DeleteMsgPort()               DeleteNV()                    DeletePlayer()
DeletePool()                  DeletePort()                  DeleteRexxMsg()
DeleteStdIO()                 DeleteTask()                  DeleteVar()
DeviceProc()                  DeviceTuple()                 DGetChar()
DGetNum()                     Disable()                     DisownBlitter()
DisplayAlert()                DisplayBeep()                 DisposeCxMsg()
DisposeDTObject()             DisposeFontContents()         DisposeLayerInfo()
DisposeObject()               DisposeRegion()               DivertCxMsg()
DMayGetChar()                 DoAsyncLayout()               DoCollision()
DoDTMethodA()                 DoGadgetMethodA()             DoHookClipRects()
DoIO()                        DoMethod()                    DoMethodA()
DoPkt()                       DoSuperMethod()               DoSuperMethodA()
DoubleClick()                 DPutChar()                    DPutFmt()
DPutStr()                     Draw()                        DrawBevelBoxA()
DrawBorder()                  DrawDTObjectA()               DrawEllipse()
DrawGList()                   DrawIconStateA()              DrawImage()
DrawImageState()              DRAWLIST_GetClass()           DupDiskObjectA()
DupLock()                     DupLockFromFH()               EasyRequestArgs()
ElapsedTime()                 Enable()                      EndCardAccess()
EndNotify()                   EndRefresh()                  EndRequest()
EndUpdate()                   Enqueue()                     EnqueueCxObj()
EntryHandler()                EraseImage()                  EraseRect()
ErrorReport()                 ExAll()                       ExAllEnd()
Examine()                     ExamineFH()                   Execute()
Exit()                        ExitHandler()                 ExNext()
Expunge()                     ExtendFont()                  ExternalSync()
FastRand()                    FattenLayerInfo()             Fault()
FGetC()                       FGets()                       FilePart()
FillRexxMsg()                 FilterTagChanges()            FilterTagItems()
FindArg()                     FindCliProc()                 FindCollection()
FindColor()                   FindConductor()               FindConfigDev()
FindDisplayInfo()             FindDosEntry()                FindLocalItem()
FindName()                    FindNamedObject()             FindPort()
FindProp()                    FindPropContext()             FindResident()
FindSegment()                 FindSemaphore()               FindTagItem()
FindTask()                    FindToolType()                FindVar()
Flood()                       Flush()                       FlushLayoutDomainCache()
FontExtent()                  Forbid()                      Format()
FormatDate()                  FormatString()                fpa()
FPutC()                       FPuts()                       FRead()
FreeArgs()                    FreeAslRequest()              FreeBitMap()
FreeBrowserNodes()            FreeChooserLabels()           FreeChooserNode()
FreeClass()                   FreeClickTabNode()            FreeClickTabs()
FreeColorMap()                FreeConfigDev()               FreeCopList()
FreeCprList()                 FreeDBufInfo()                FreeDeviceProc()
FreeDiskObject()              FreeDosEntry()                FreeDosObject()
FreeEntry()                   FreeExpansionMem()            FreeFileRequest()
FreeFreeList()                FreeGadgets()                 FreeGBuffers()
FreeIEvents()                 FreeIFF()                     FreeListBrowserList()
FreeListBrowserNode()         FreeLocalItem()               FreeMem()
FreeMenus()                   FreeMiscResource()            FreeNamedObject()
FreeNVData()                  FreePooled()                  FreePotBits()
FreeRadioButtonNode()         FreeRadioButtons()            FreeRaster()
FreeRemember()                FreeScreenBuffer()            FreeScreenDrawInfo()
FreeSignal()                  FreeSpeedButtonNode()         FreeSprite()
FreeSpriteData()              FreeSysRequest()              FreeTagItems()
FreeTrap()                    FreeUnit()                    FreeVec()
FreeVisualInfo()              FreeVPortCopLists()           FUELGAUGE_GetClass()
FWrite()                      GadgetMouse()                 GetAGString()
GetAmigaGuideAttr()           GetAmigaGuideMsg()            GetAmigaGuideString()
GetAPen()                     GetArgStr()                   GetAttr()
GetAttrs()                    GetBitMapAttr()               GetBPen()
GetCardMap()                  GetCatalogStr()               GetCC()
GetChooserNodeAttrsA()        GetClickTabNodeAttrsA()       GetCode()
GetColorMap()                 GetConsoleTask()              GetCopyNV()
GetCurrentBinding()           GetCurrentDirName()           GetDefaultPubScreen()
GetDefDiskObject()            GetDefPrefs()                 GetDeviceProc()
GetDiskObject()               GetDiskObjectNew()            GetDisplayInfoData()
GetDrMd()                     GetDTAttrsA()                 GetDTMethods()
GetDTString()                 GetDTTriggerMethods()         GetExtSpriteA()
GetFileSysTask()              GETFILE_GetClass()            GETFONT_GetClass()
GetGBuffers()                 GetIconRectangleA()           GetIconTagList()
GetKey()                      GetLanguageSelection()        GetListBrowserNodeAttrsA()
GetLocaleStr()                GetMsg()                      GetNVInfo()
GetNVList()                   GetOPen()                     GetPlayerAttrsA()
GetPrefs()                    GetProgramDir()               GetProgramName()
GetPrompt()                   GetRadioButtonNodeAttrsA()    GetRexxVar()
GetRGB32()                    GetRGB4()                     GetRPAttrA()
GetScreenData()               GetScreenDrawInfo()           GETSCREENMODE_GetClass()
GetSpeedButtonNodeAttrsA()    GetSprite()                   GetSysTime()
GetTagData()                  GetUniqueID()                 GetUnit()
GetUnitID()                   GetVar()                      GetVisualInfoA()
GetVPModeID()                 GfxAssociate()                GfxFree()
GfxLookUP()                   GfxNew()                      GiveUnit()
GLYPH_GetClass()              GoodID()                      GoodType()
gradientslider.gadget()       GT_BeginRefresh()             GT_EndRefresh()
GT_FilterIMsg()               GT_GetGadgetAttrsA()          GT_GetIMsg()
GT_PostFilterIMsg()           GT_RefreshWindow()            GT_ReplyIMsg()
GT_SetGadgetAttrsA()          HelpControl()                 HideAllListBrowserChildren()
HideListBrowserNodeChildren() HookEntry()                   HotKey()
IconControlA()                IDtoStr()                     IEEEDPAbs()
IEEEDPAcos()                  IEEEDPAdd()                   IEEEDPAsin()
IEEEDPAtan()                  IEEEDPCeil()                  IEEEDPCmp()
IEEEDPCos()                   IEEEDPCosh()                  IEEEDPDiv()
IEEEDPExp()                   IEEEDPFieee()                 IEEEDPFix()
IEEEDPFloor()                 IEEEDPFlt()                   IEEEDPLog()
IEEEDPLog10()                 IEEEDPMul()                   IEEEDPNeg()
IEEEDPPow()                   IEEEDPSin()                   IEEEDPSincos()
IEEEDPSinh()                  IEEEDPSqrt()                  IEEEDPSub()
IEEEDPTan()                   IEEEDPTanh()                  IEEEDPTieee()
IEEEDPTst()                   IEEESPAbs()                   IEEESPAcos()
IEEESPAdd()                   IEEESPAsin()                  IEEESPAtan()
IEEESPCeil()                  IEEESPCmp()                   IEEESPCos()
IEEESPCosh()                  IEEESPDiv()                   IEEESPExp()
IEEESPFieee()                 IEEESPFix()                   IEEESPFloor()
IEEESPFlt()                   IEEESPLog()                   IEEESPLog10()
IEEESPMul()                   IEEESPNeg()                   IEEESPPow()
IEEESPSin()                   IEEESPSincos()                IEEESPSinh()
IEEESPSqrt()                  IEEESPSub()                   IEEESPTan()
IEEESPTanh()                  IEEESPTieee()                 IEEESPTst()
IfAmigaXIP()                  Info()                        Inhibit()
InitArea()                    InitBitMap()                  InitCode()
InitGels()                    InitGMasks()                  InitIFF()
InitIFFasClip()               InitIFFasDOS()                InitLayers()
InitMasks()                   InitRastPort()                InitRequester()
InitResident()                InitSemaphore()               InitStruct()
InitTmpRas()                  InitView()                    InitVPort()
Input()                       Insert()                      InsertCxObj()
InstallClipRegion()           InstallLayerHook()            InstallLayerInfoHook()
INTEGER_GetClass()            InternalLoadSeg()             InternalUnLoadSeg()
IntuiTextLength()             InvertKeyMap()                InvertString()
IoErr()                       IsFileSystem()                IsInteractive()
IsRexxMsg()                   IsXXXX()                      ItemAddress()
KCmpStr()                     KGetChar()                    KGetNum()
KMayGetChar()                 KPrintF()                     KPutChar()
KPutStr()                     LABEL_GetClass()              LayoutIconA()
LayoutLimits()                LayoutMenuItemsA()            LayoutMenusA()
LAYOUT_GetClass()             LBAddNodeA()                  LBEditNodeA()
LBRemNode()                   LendMenus()                   LengthArgstring()
LibAllocPooled()              LibCreatePool()               LibDeletePool()
LibDoGadgetMethodA()          LibFreePooled()               ListBrowserSelectAll()
LISTBROWSER_GetClass()        LoadRGB32()                   LoadRGB4()
LoadSeg()                     LoadView()                    LocalItemData()
Lock()                        LockAmigaGuideBase()          LockDosList()
LockIBase()                   LockLayer()                   LockLayerInfo()
LockLayerRom()                LockLayers()                  LockPubScreen()
LockPubScreenList()           LockRealTime()                LockRecord()
LockRecords()                 LockRexxBase()                MakeClass()
MakeDosEntry()                MakeDosNode()                 MakeFunctions()
MakeLibrary()                 MakeLink()                    MakeScreen()
MakeVPort()                   MakeWorkbenchObjectVisibleA() MapANSI()
MapRawKey()                   MapTags()                     MatchEnd()
MatchFirst()                  MatchIX()                     MatchNext()
MatchPattern()                MatchPatternNoCase()          MatchToolValue()
MaxCli()                      ModeNotAvailable()            ModifyIDCMP()
ModifyProp()                  Move()                        MoveLayer()
MoveLayerInFrontOf()          MoveScreen()                  MoveSizeLayer()
MoveSprite()                  MoveWindow()                  MoveWindowInFrontOf()
MrgCop()                      NamedObjectName()             NameFromFH()
NameFromLock()                NewDiskObject()               NewDTObjectA()
NewFontContents()             NewLayerInfo()                NewList()
NewLoadSeg()                  NewModifyProp()               NewObject()
NewRegion()                   NewScaledDiskFont()           NextConductor()
NextDisplayInfo()             NextDosEntry()                NextObject()
NextPubScreen()               NextTagItem()                 ObtainBattSemaphore()
ObtainBestPenA()              ObtainConfigBinding()         ObtainDataTypeA()
ObtainDTDrawInfoA()           ObtainGIRPort()               ObtainInfoA()
ObtainPen()                   ObtainQuickVector()           ObtainSemaphore()
ObtainSemaphoreList()         ObtainSemaphoreShared()       OffGadget()
OffMenu()                     OldOpenLibrary()              OnGadget()
OnMenu()                      Open()                        OpenAmigaGuideA()
OpenAmigaGuideAsyncA()        OpenCatalog()                 OpenClipboard()
OpenDevice()                  OpenDiskFont()                OpenEngine()
OpenFont()                    OpenFromLock()                OpenIFF()
OpenLayoutWindowTagList()     OpenLibrary()                 OpenLocale()
OpenMonitor()                 OpenResource()                OpenScreen()
OpenScreenTagList()           OpenWindow()                  OpenWindowTagList()
OpenWorkBench()               OpenWorkbenchObjectA()        OrRectRegion()
OrRegionRegion()              Output()                      OwnBlitter()
OwnCard()                     PackBoolTags()                PackStructureTags()
PAGE_GetClass()               PALETTE_GetClass()            ParentChunk()
ParentDir()                   ParentOfFH()                  ParseDate()
ParseIFF()                    ParseIX()                     ParsePattern()
ParsePatternNoCase()          PathPart()                    PBothReady()
PeekQualifier()               PENMAP_GetClass()             Permit()
picture.datatype()            PointInImage()                PolyDraw()
PopChunk()                    port_handler()                PQuery()
PRead()                       PrintDTObjectA()              printf()
PrintFault()                  PrintIText()                  Procure()
PropChunk()                   PropChunks()                  PubScreenStatus()
PushChunk()                   PutDefDiskObject()            PutDiskObject()
PutIconTagList()              PutMsg()                      PutStr()
PWrite()                      QBlit()                       QBSBlit()
QueryKeys()                   QueryOverscan()               queue_handler()
RadioButtonsA()               RADIOBUTTON_GetClass()        RangeRand()
RawDoFmt()                    RawKeyConvert()               Read()
ReadArgs()                    ReadBattClock()               ReadBattMem()
ReadCardStatus()              ReadChunkBytes()              ReadChunkRecords()
ReadEClock()                  ReadExpansionByte()           ReadExpansionRom()
ReadItem()                    ReadJoyPort()                 ReadLink()
ReadPixel()                   ReadPixelArray8()             ReadPixelLine8()
ReadUnitID()                  RectFill()                    RefreshDTObjectA()
RefreshGadgets()              RefreshGList()                RefreshPageGadget()
RefreshTagItemClones()        RefreshWindowFrame()          Relabel()
ReleaseBattSemaphore()        ReleaseCard()                 ReleaseConfigBinding()
ReleaseDataType()             ReleaseDTDrawInfo()           ReleaseGIRPort()
ReleaseInfoA()                ReleaseNamedObject()          ReleasePen()
ReleaseSemaphore()            ReleaseSemaphoreList()        RemakeDisplay()
RemAssignList()               RemBob()                      RemConfigDev()
RemDevice()                   RemDosEntry()                 RemFont()
RemHead()                     RemIBob()                     RemICRVector()
RemIntServer()                RemKBInt()                    RemLibrary()
RemMemHandler()               RemNamedObject()              Remove()
RemoveAmigaGuideHostA()       RemoveAppIcon()               RemoveAppMenuItem()
RemoveAppWindow()             RemoveAppWindowDropZone()     RemoveClass()
RemoveCxObj()                 RemoveDTObject()              RemoveGadget()
RemoveGList()                 RemPort()                     RemResource()
RemSegment()                  RemSemaphore()                RemTail()
RemTask()                     RemTimerInt()                 RemTOF()
RemVBlankInt()                RemVSprite()                  Rename()
ReplyAmigaGuideMsg()          ReplyMsg()                    ReplyPkt()
ReportMouse()                 Request()                     RequestFile()
ResetBattClock()              ResetMenuStrip()              RethinkDisplay()
RethinkLayout()               RL_CloseResource()            RL_DisposeGroup()
RL_DisposeObject()            RL_GetObjectArray()           RL_NewGroupA()
RL_NewObjectA()               RL_OpenResource()             RL_SetResourceScreen()
RouteCxMsg()                  RunCommand()                  SameDevice()
SameLock()                    ScalerDiv()                   ScreenDepth()
ScreenPosition()              ScreenToBack()                ScreenToFront()
SCROLLER_GetClass()           ScrollLayer()                 ScrollRaster()
ScrollRasterBF()              ScrollVPort()                 ScrollWindowRaster()
SDivMod32()                   Seek()                        SelectInput()
SelectOutput()                SendAmigaGuideCmdA()          SendAmigaGuideContextA()
SendIO()                      SendPkt()                     SetABPenDrMd()
SetAmigaGuideAttrsA()         SetAmigaGuideContextA()       SetAPen()
SetArgStr()                   SetAttrsA()                   SetBPen()
SetChipRev()                  SetChooserNodeAttrsA()        SetClickTabNodeAttrsA()
SetCollision()                SetComment()                  SetConductorState()
SetConsoleTask()              SetCurrentBinding()           SetCurrentDirName()
SetCxObjPri()                 SetDefaultPubScreen()         SetDMRequest()
SetDrMd()                     SetDTAttrsA()                 SetEditHook()
SetExcept()                   SetFileDate()                 SetFileSize()
SetFileSysTask()              SetFilter()                   SetFilterIX()
SetFont()                     SetFunction()                 SetGadgetAttrsA()
SetICR()                      SetInfoA()                    SetIntVector()
SetIoErr()                    SetJoyPortAttrsA()            SetKeyMapDefault()
SetListBrowserNodeAttrsA()    SetLocalItemPurge()           SetMaxPen()
SetMenuStrip()                SetMode()                     SetMouseQueue()
SetNVProtection()             SetOPen()                     SetOutlinePen()
SetOwner()                    SetPageGadgetAttrsA()         SetPlayerAttrs()
SetPointer()                  SetPrefs()                    SetProgramDir()
SetProgramName()              SetPrompt()                   SetProtection()
SetPubScreenModes()           SetRadioButtonNodeAttrsA()    SetRast()
SetRexxVar()                  SetRGB32()                    SetRGB32CM()
SetRGB4()                     SetRGB4CM()                   SetRPAttrA()
SetSignal()                   SetSoftStyle()                SetSpeedButtonNodeAttrsA()
SetSR()                       SetSuperAttrs()               SetTaskPri()
SetTranslate()                SetVar()                      SetVBuf()
SetWindowPointerA()           SetWindowTitles()             SetWriteMask()
ShowAllListBrowserChildren()  ShowListBrowserNodeChildren() ShowTitle()
Signal()                      SizeLayer()                   SizeWindow()
SMult32()                     SMult64()                     SortGList()
sound.datatype()              SPAbs()                       SPAcos()
SPAdd()                       SPAsin()                      SPAtan()
SPCeil()                      SPCmp()                       SPCos()
SPCosh()                      SPDiv()                       SPEEDBAR_GetClass()
SPExp()                       SPFieee()                     SPFix()
SPFloor()                     SPFlt()                       SplitName()
SPLog()                       SPLog10()                     SPMul()
SPNeg()                       SPPow()                       sprintf()
SPSin()                       SPSincos()                    SPSinh()
SPSqrt()                      SPSub()                       SPTan()
SPTanh()                      SPTieee()                     SPTst()
StackSwap()                   StartNotify()                 StartTimerInt()
stdio()                       StopChunk()                   StopChunks()
StopOnExit()                  StopTimerInt()                StoreItemInContext()
StoreLocalItem()              StoreNV()                     StrConvert()
Stricmp()                     STRING_GetClass()             StripFont()
StrnCmp()                     Strnicmp()                    StrToDate()
StrToLong()                   SubTime()                     SumKickData()
SumLibrary()                  SuperState()                  Supervisor()
SwapBitsRastPortClipRect()    SyncSBitMap()                 SysReqHandler()
SystemControlA()              SystemTagList()               TagInArray()
Text()                        text.datatype()               TextExtent()
TextFit()                     TextLength()                  ThinLayerInfo()
TimedDisplayAlert()           TimeDelay()                   ToLower()
ToUpper()                     Translate()                   TypeOfMem()
UDivMod32()                   UMult32()                     UMult64()
UnGetC()                      UnLoadSeg()                   UnLock()
UnlockAmigaGuideBase()        UnLockDosList()               UnlockIBase()
UnlockLayer()                 UnlockLayerInfo()             UnlockLayerRom()
UnlockLayers()                UnlockPubScreen()             UnlockPubScreenList()
UnlockRealTime()              UnLockRecord()                UnLockRecords()
UnlockRexxBase()              UnpackStructureTags()         UpfrontLayer()
UserState()                   Vacate()                      VBeamPos()
VFPrintf()                    VFWritef()                    VideoControl()
ViewAddress()                 ViewPortAddress()             VPrintf()
Wait()                        WaitBlit()                    WaitBOVP()
WaitForChar()                 WaitIO()                      WaitPkt()
WaitPort()                    WaitTOF()                     WBenchToBack()
WBenchToFront()               WBInfo()                      WhichLayer()
WindowLimits()                WindowToBack()                WindowToFront()
WINDOW_GetClass()             WorkbenchControlA()           Write()
WriteBattClock()              WriteBattMem()                WriteChars()
WriteChunkBytes()             WriteChunkRecords()           WriteChunkyPixels()
WriteExpansionByte()          WritePixel()                  WritePixelArray8()
WritePixelLine8()             WritePotgo()                  XorRectRegion()
XorRegionRegion()             ZipWindow()


Device Command Index

128 entries in this index

ADCMD_ALLOCATE       ADCMD_FINISH         ADCMD_FREE           ADCMD_LOCK
ADCMD_PERVOL         ADCMD_SETPREC        ADCMD_WAITCYCLE      ALLOCATE_MEMORY
AM_EXECUTE           AM_HANDLEINPUT       CALL_ADDRESS         CBD_CHANGEHOOK
CBD_CURRENTREADID    CBD_CURRENTWRITEID   CBD_POST             CD_ADDCHANGEINT
CD_ADDFRAMEINT       CD_ASKDEFAULTKEYMAP  CD_ASKKEYMAP         CD_ATTENUATE
CD_CHANGENUM         CD_CHANGESTATE       CD_CONFIG            CD_EJECT
CD_GETGEOMETRY       CD_INFO              CD_MOTOR             CD_PAUSE
CD_PLAYLSN           CD_PLAYMSF           CD_PLAYTRACK         CD_PROTSTATUS
CD_QCODELSN          CD_QCODEMSF          CD_READ              CD_READXL
CD_REMCHANGEINT      CD_REMFRAMEINT       CD_SEARCH            CD_SEEK
CD_SETDEFAULTKEYMAP  CD_SETKEYMAP         CD_TOCLSN            CD_TOCMSF
CEND                 CINIT                CMD_CLEAR            CMD_FLUSH
CMD_INVALID          CMD_READ             CMD_RESET            CMD_START
CMD_STOP             CMD_UPDATE           CMD_WRITE            CMOVE
CWAIT                FREE_MEMORY          GET_CONTEXT_FRAME    GPD_ASKCTYPE
GPD_ASKTRIGGER       GPD_READEVENT        GPD_SETCTYPE         GPD_SETTRIGGER
IND_ADDHANDLER       IND_REMHANDLER       IND_SETMPORT         IND_SETMTRIG
IND_SETMTYPE         IND_SETPERIOD        IND_SETTHRESH        IND_WRITEEVENT
KBD_ADDRESETHANDLER  KBD_READEVENT        KBD_READMATRIX       KBD_REMRESETHANDLER
KBD_RESETHANDLERDONE LBM_ADDNODE          LBM_EDITNODE         LBM_REMNODE
NOP                  PDCMD_QUERY          PDCMD_SETPARAMS      PRD_DUMPRPORT
PRD_DUMPRPORTTAGS    PRD_EDITPREFS        PRD_PRTCOMMAND       PRD_QUERY
PRD_RAWWRITE         PRD_READPREFS        PRD_SETERRHOOK       PRD_WRITEPREFS
READ_ARRAY           READ_BYTE            READ_LONG            READ_WORD
RESET                RETURN_TO_SYSTEM     SDCMD_BREAK          SDCMD_QUERY
SDCMD_SETPARAMS      TD_ADDCHANGEINT      TD_CHANGENUM         TD_CHANGESTATE
TD_EJECT             TD_FORMAT            TD_GETDRIVETYPE      TD_GETGEOMETRY
TD_GETNUMTRACKS      TD_MOTOR             TD_PROTSTATUS        TD_RAWREAD
TD_RAWWRITE          TD_REMCHANGEINT      TD_SEEK              TR_ADDREQUEST
TR_GETSYSTIME        TR_SETSYSTIME        TURN_OFF_SINGLE      TURN_ON_SINGLE
WM_CLOSE             WM_HANDLEINPUT       WM_ICONIFY           WM_OPEN
WRITE_ARRAY          WRITE_BYTE           WRITE_LONG           WRITE_WORD


C Structure Index

384 entries in this index

AChain                     adtFrame                   adtNewFormatFrame
adtStart                   AmigaGuideMsg              AnalogSignalInterval
AnchorPath                 AnimComp                   AnimHeader
AnimOb                     apExecute                  AppIcon
AppIconRenderMsg           AppMessage                 AppWindow
AppWindowDropZoneMsg       AreaInfo                   ARexxCmd
ArticleDisposition         AssignList                 AvailFonts
AvailFontsHeader           BadBlockBlock              BadBlockEntry
BitMap                     BitMapHeader               BitScaleArgs
bltnode                    Bob                        BoolInfo
BootNode                   Border                     CardHandle
CardMemoryMap              Catalog                    CDInfo
CDXL                       CIA                        ClassLibrary
ClickMessage               ClipboardHandle            ClipboardUnitPartial
ClipHookMsg                ClipRect                   CliProcList
ClockData                  CollectionItem             collTable
ColorFontColors            ColorMap                   ColorRegister
ColorSpec                  ColorTextFont              ColorWheelHSB
ColorWheelRGB              ColumnInfo                 CommandLineInterface
Conductor                  ConfigDev                  ContextNode
ConUnit                    copinit                    CopIns
CopList                    CountryPrefs               cprlist
CSource                    CurrentBinding             Custom
DataType                   DataTypeHeader             DateStamp
DateTime                   DBufInfo                   DBufPacket
DefaultsArray              Device                     DeviceData
DeviceList                 DeviceNode                 DeviceTData
DevInfo                    DevProc                    DiagArea
DimensionInfo              DiscResource               DiscResourceUnit
DiskFontHeader             DiskObject                 DisplayInfo
DisplayMode                DosEnvec                   DosInfo
DosLibrary                 DosList                    DosPacket
DrawerData                 DrawInfo                   DrawList
DriveGeometry              DRPSourceMsg               dtDraw
dtFrameBox                 dtGeneral                  dtGoto
DTHookContext              DTMethod                   dtPrint
dtSelect                   DTSpecialInfo              dtTrigger
dtWrite                    EasyStruct                 EClockVal
ErrorString                ExAllControl               ExAllData
ExecBase                   ExpansionBase              ExpansionControl
ExpansionRom               ExtendedNode               ExtGadget
ExtIntuiMessage            ExtNewScreen               ExtNewWindow
ExtSprite                  FileHandle                 FileInfoBlock
FileLock                   FileRequester              FileSysEntry
FileSysHeaderBlock         FileSysResource            FileSysStartupMsg
FolderIndex                FontContents               FontContentsHeader
FontPrefs                  FontRequester              FrameInfo
FreeList                   Gadget                     GadgetInfo
GamePortTrigger            GelsInfo                   gfileFreelist
gfileRequest               gfRequest                  GfxBase
GlyphEngine                GlyphMap                   GlyphWidthEntry
gpClipRect                 gpDomain                   gpGoInactive
gpHitTest                  gpInput                    gpKeyGoInactive
gpKeyInput                 gpKeyTest                  gpLayout
gpRender                   GP_TEXTEDITOR_ARexxCmd     GP_TEXTEDITOR_ClearText
GP_TEXTEDITOR_HandleError  GP_TEXTEDITOR_MarkText     GP_TEXTEDITOR_Search
gsmRequest                 HDWLibrary                 Hook
IBox                       IconIdentifyMsg            IconSelectMsg
IControlPrefs              IENewTablet                IEPointerPixel
IEPointerTablet            IFFHandle                  IFFStreamCmd
Image                      impDomainFrame             impDraw
impErase                   impFrameBox                impHitTest
InfoData                   InputEvent                 InputPrefs
Interrupt                  IntuiMessage               IntuiText
IntuitionBase              IntVector                  IOAudio
IoBuff                     IOClipReq                  IODRPReq
IODRPTagsReq               IOExtTD                    IOPrefsReq
IOPrtCmdReq                IOPrtErrReq                IOPrtPrefsReq
IORequest                  IOStdReq                   Isrvstr
KeyMap                     KeyMapNode                 KeyMapResource
KeyQuery                   Layer                      Layer_Info
lbAddNode                  LBDrawMsg                  lbEditNode
lbHideChildren             lbRemNode                  lbShowChildren
lbSort                     LBSortMsg                  Library
Line                       List                       LoadSegBlock
LocalContextItem           Locale                     LocaleBase
LocalePrefs                LocalVar                   LVDrawMsg
MathIEEEBase               MathIEEEResource           MemChunk
MemEntry                   MemHandlerData             MemHeader
MemList                    Menu                       MenuItem
Message                    MinList                    MinNode
MonitorInfo                MonitorSpec                mouth_rb
MsgPort                    NamedObject                NameInfo
narrator_rb                NewAmigaGuide              NewBroker
NewGadget                  NewMenu                    NewScreen
NewWindow                  NexxStr                    Node
NotifyMessage              NotifyRequest              NVEntry
NVInfo                     OldDrawerData              opAddTail
opExpungeNode              opFindHost                 opGet
opMember                   opNodeIO                   opSet
opUpdate                   orRequest                  OverscanPrefs
PalettePrefs               PartitionBlock             pdtBlitPixelArray
PGX                        Player                     pmState
pmTime                     PointerPrefs               Preferences
PrefHeader                 PrinterData                PrinterDeviceUnitPrefs
PrinterExtendedData        PrinterGfxPrefs            PrinterPSPrefs
PrinterSegment             PrinterTxtPrefs            PrinterUnitPrefs
Process                    PropInfo                   PrtDriverPreferences
PrtErrMsg                  PubScreenNode              QCode
QueryHeader                RastPort                   RDArgs
ReactionPrefs              RealTimeBase               RecordLock
Rect32                     Rectangle                  Region
RegionRectangle            Remember                   Requester
Resident                   RexxArg                    RexxMsg
RexxMsgPort                RexxRsrc                   RexxTask
RGBTable                   RigidDiskBlock             RMSF
RootNode                   RxsLib                     SatisfyMsg
Screen                     ScreenBuffer               ScreenModePrefs
ScreenModeRequester        SCSICmd                    Segment
SemaphoreMessage           SemaphoreRequest           SerialPrefs
ServerProgressData         SGWork                     SignalSemaphore
SimpleSprite               SoftIntList                SoundPrefs
SpecialMonitor             SpecialPens                SrcNode
StackSwapStruct            StandardPacket             StoredProperty
StringExtend               StringInfo                 TabletData
TabletHookData             TagItem                    Task
TAvailFonts                TDU_PublicUnit             TextAttr
TextExtent                 TextFont                   TextFontExtension
TFontContents              timerequest                timeval
TmpRas                     TOCEntry                   TOCSummary
Tool                       ToolNode                   TP_AmigaXIP
TTextAttr                  UCopList                   UIPrefs
Unit                       UtilityBase                VecInfo
View                       ViewExtra                  ViewPort
ViewPortExtra              VoiceHeader                VSprite
WBArg                      WBPatternPrefs             WBStartup
Window                     wmHandle                   WorkbenchHiddenDevicePrefs
WorkbenchPrefs             XRef                       _Object


amigaguide.doc

     --background--
     --rexxhost--
     AddAmigaGuideHostA()
     AmigaGuideSignal()
     CloseAmigaGuide()
     GetAmigaGuideAttr()
     GetAmigaGuideMsg()
     GetAmigaGuideString()
     LockAmigaGuideBase()
     OpenAmigaGuideA()
     OpenAmigaGuideAsyncA()
     RemoveAmigaGuideHostA()
     ReplyAmigaGuideMsg()
     SendAmigaGuideCmdA()
     SendAmigaGuideContextA()
     SetAmigaGuideAttrsA()
     SetAmigaGuideContextA()
     UnlockAmigaGuideBase()


amigaguide.library/--background--

   PURPOSE
        The amigaguide.library provides a means whereby developers
        can easily add on-line help abilities to their applications.


amigaguide.library/--rexxhost--

   HOST INTERFACE
        amigaguide.library provides an ARexx function host interface that
        enables ARexx programs to take advantage of the features of
        AmigaGuide. The functions provided by the interface are directly
        related to the functions described herein, with the differences
        mostly being in the way they are called.

        The function host library vector is located at offset -30 from
        the library. This is the value you provide to ARexx in the
        AddLib() function call.

   FUNCTIONS
        ShowNode (PUBSCREEN,DATABASE,NODE,LINE,XREF)

        LoadXRef (NAME)

        GetXRef (NODE)

        AddXRef (WORD,FILE,LINE,TYPE)

        ExpungeXRef ()

   BUGS
        V39, V40 and V41 did not support the ExpungeXRef() and
        AddXRef() commands. This was fixed in V44.


amigaguide.library/AddAmigaGuideHostA

    NAME
        AddAmigaGuideHostA - Add a dynamic node host.           (V34)

    SYNOPSIS
        handle = AddAmigaGuideHostA (hook, name, attrs);
        d0                            a0    d0    a1

        AMIGAGUIDEHOST AddAmigaGuideHostA (struct Hook *, STRPTR,
                                          struct TagItem *);

    FUNCTION
        This function adds a callback hook to the dynamic node list.

        A dynamic node allows an application to incorporate context-
        sensitive or live project data within their help system.

    INPUTS
        hook - The callback hook.
        name - Name of the AmigaGuideHost database that you are adding.
            The name must be unique.
        attrs - Additional attributes.  None are defined at this time.

    RETURNS
        Returns NULL if unable to add the dynamic node host, otherwise
        returns a pointer to a handle that will eventually be passed
        to RemoveAmigaGuideHost() to remove the dynamic node host from
        the list.

    NOTES
        When AmigaGuide attempts to resolve a LINK command, it performs
        the following sequence of events.

           Splits the name into a path, a database and a node (only
             the node is required).
           Opens the database.
           Performs the following searches until the node is found:
             Search the local database.
             Search the local cross reference list.
             Search the local dynamic node host.
             Search the global help file (system help).
             Search the global cross reference list.
             Search the global dynamic node hosts.

    SEE ALSO
        RemoveAmigaGuideHostA()

    EXAMPLE

        /* Hook dispatcher */
        ULONG __asm hookEntry(
                register __a0 struct Hook *h,
                register __a2 VOID *obj,
                register __a1 VOID *msg)
        {
            /* Pass the parameters on the stack */
            return ((h->h_SubEntry)(h, obj, msg));
        }

        ULONG __saveds
        dispatchAmigaGuideHost (struct Hook *h, STRPTR db, Msg msg)
        {
            struct opNodeIO *onm = (struct opNodeIO *) msg;
            ULONG retval = 0;

            switch (msg->MethodID)
            {
                /* Does this node belong to you? */
                case HM_FINDNODE:
                    {
                        struct opFindHost *ofh = (struct opFindHost *) msg;

                        kprintf("Find [%s] in %sn", ofh->ofh_Node, db);

                        /* Return TRUE to indicate that it's your node,
                         * otherwise return FALSE. */
                         retval = TRUE;
                    }
                    break;

                /* Open a node. */
                case HM_OPENNODE:
                    kprintf("Open [%s] in %sn", onm->onm_Node, db);

                    /* Provide the contents of the node */
                    onm->onm_DocBuffer = TEMP_NODE;
                    onm->onm_BuffLen   = strlen(TEMP_NODE);

                    /* Indicate that we were able to open the node */
                    retval = TRUE;
                    break;

                /* Close a node, that has no users. */
                case HM_CLOSENODE:
                    kprintf("Close [%s] in %sn", onm->onm_Node, db);

                    /* Indicate that we were able to close the node */
                    retval = TRUE;
                    break;

                /* Free any extra memory */
                case HM_EXPUNGE:
                    kprintf("Expunge [%s]n", db);
                    break;

                default:
                    kprintf("Unknown method %ldn", msg->MethodID);
                    break;
            }

            return (retval);
        }

        main(int argc, char **argv)
        {
            struct Hook hook;
            AMIGAGUIDEHOST hh;

            /* Open the library */
            if (AmigaGuideBase = OpenLibrary("amigaguide.library", 33))
            {
                /* Initialize the hook */
                hook.h_Entry    = hookEntry;
                hook.h_SubEntry = dispatchAmigaGuideHost;

                /* Add the AmigaGuideHost to the system */
                if (hh = AddAmigaGuideHost(&hook, "ExampleHost", NULL))
                {
                    /* Wait until we're told to quit */
                    Wait(SIGBREAKF_CTRL_C);

                    /* Try removing the host */
                    while (RemoveAmigaGuideHost(hh, NULL) > 0)
                    {
                        /* Wait a while */
                        Delay(5);
                    }
                }

                /* close the library */
                CloseLibrary(AmigaGuideBase);
            }
        }

    BUGS
        When a dynamic node host is first added it will receive a
        HM_FINDNODE message with an onm_Node of "Main".  The
        AGA_HelpGroup attribute will always be zero for this
        particular message.


amigaguide.library/AmigaGuideSignal

   NAME
        AmigaGuideSignal - Obtain aysnc AmigaGuide signal.      (V34)

   SYNOPSIS
        signal = AmigaGuideSignal ( handle );
        d0                           a0

        ULONG AmigaGuideSignal (AMIGAGUIDECONTEXT);

   FUNCTION
        This function returns the signal bit to Wait on for AmigaGuideMsg's
        for a particular AmigaGuide database.

   INPUTS
        handle -- Handle to a AmigaGuide system.

   EXAMPLE
        ULONG sigw, sigh;
        AMIGAGUIDECONTEXT handle;

        /* get the signal bit to wait on for a AmigaGuide message */
        sigh = AmigaGuideSignal(handle);

        /* add the signal bit into the total signals to wait on */
        sigw |= sigh;

   RETURNS
        signal -- Signal bit to Wait on.

   SEE ALSO
        OpenAmigaGuideAsyncA(), GetAmigaGuideMsg(), ReplyAmigaGuideMsg()


amigaguide.library/CloseAmigaGuide

    NAME
        CloseAmigaGuide - Close a AmigaGuide client.            (V34)

    SYNOPSIS
        CloseAmigaGuide (handle);
                          a0

        VOID CloseAmigaGuide (AMIGAGUIDECONTEXT);

    FUNCTION
        Closes a synchronous, or asynchronous, AmigaGuide client.

        This function will also close all windows that were opened for
        the client.

    INPUTS
        handle - Handle to an AmigaGuide client.

    SEE ALSO
        OpenAmigaGuideA(), OpenAmigaGuideAsyncA()


amigaguide.library/GetAmigaGuideAttr

    NAME
        GetAmigaGuideAttr - Get an AmigaGuide attribute.        (V34)

    SYNOPSIS
        retval = GetAmigaGuideAttr (tag, handle, storage);
        d0                           d0    a0      a1

        LONG GetAmigaGuideAttr (Tag, AMIGAGUIDECONTEXT, ULONG *);

    FUNCTION
        This function is used to obtain attributes from AmigaGuide.

    INPUTS
        tag - Attribute to obtain.
        handle - Handle to an AmigaGuide system.
        storage - Pointer to appropriate storage for the answer.

    TAGS
        AGA_Path (BPTR) - Pointer to the current path used by
            AmigaGuide.

        AGA_XRefList (struct List *) - Pointer to the current
            cross reference list.

    RETURNS

    SEE ALSO
        SetAmigaGuideAttrsA()


amigaguide.library/GetAmigaGuideMsg

   NAME
        GetAmigaGuideMsg - Receive async AmigaGuide message.    (V34)

   SYNOPSIS
        msg = GetAmigaGuideMsg (handle);
        d0                       a0

        struct AmigaGuideMsg *GetAmigaGuideMsg (AMIGAGUIDECONTEXT);

   FUNCTION
        This function returns a SIPC message from the AmigaGuide system,
        if there is a message available.

   INPUTS
        handle - Handle to a AmigaGuide system.

   EXAMPLE

        AMIGAGUIDECONTEXT handle;
        struct AmigaGuideMsg *agm;

        /* get a AmigaGuide message */
        while (agm = GetAmigaGuideMsg(handle))
        {
            /* process the event */
            switch (agm->agm_Type)
            {
                case ToolCmdReplyID: /* a command has completed */
                    if (agm->agm_Pri_Ret)
                    {
                        /* An error occurred, the reason is in agm_Sec_Ret.
                         * The command string is in agm_Data
                         */
                    }
                    break;

                case ToolStatusID: /* status message */
                    if (agm->agm_Pri_Ret)
                    {
                        /* an error occurred, the reason is in agm_Sec_Ret */
                    }
                    break;

                default:
                    break;
            }

            /* reply to the AmigaGuide message */
            ReplyAmigaGuideMsg(agm);
        }

   RETURNS
        msg -- Pointer to a SIPC message or NULL if no message was
            available.

   SEE ALSO
        OpenAmigaGuideAsyncA(), AmigaGuideSignal(), ReplyAmigaGuideMsg()


amigaguide.library/GetAmigaGuideString

   NAME
        GetAmigaGuideString - Get an AmigaGuide string.
                                                               (V34)
   SYNOPSIS
        txt = GetAmigaGuideString (id);
        d0                         d0

        STRPTR GetAmigaGuideString (ULONG);

   FUNCTION
        This function is used to obtain a localized string given the
        ID.

   INPUTS
        ID -- Valid AmigaGuide string id.

   RETURNS
        A pointer to the string.   NULL for an invalid string.

   SEE ALSO


amigaguide.library/LockAmigaGuideBase

    NAME
        LockAmigaGuideBase - Lock an AmigaGuide client.         (V34)

    SYNOPSIS
        key = LockAmigaGuideBase (AMIGAGUIDECONTEXT handle);
        d0                                            a0

        LONG LockAmigaGuideBase (AMIGAGUIDECONTEXT);

    FUNCTION
        This function is used to lock the AmigaGuide context handle
        while working with data obtained with the the
        GetAmigaGuideAttr() function.

    INPUTS
        handle - AMIGAGUIDECONTEXT handle obtained with
            OpenAmigaGuideAsync().

    RETURNS
        Returns a key to pass to UnlockAmigaGuideBase().

    SEE ALSO
        UnlockAmigaGuideBase()


amigaguide.library/OpenAmigaGuideA

    NAME
        OpenAmigaGuideA - Open a synchronous AmigaGuide database.

    SYNOPSIS
        handle = OpenAmigaGuideA (nag, attrs);
        d0                         a0   a1

        AMIGAGUIDECONTEXT OpenAmigaGuideA (struct NewAmigaGuide *,
                                           struct TagItem *);

        handle = OpenAmigaGuide (nag, tag1, ...);

        AMIGAGUIDECONTEXT OpenAmigaGuide (struct NewAmigaGuide *,
                                          Tag tag1, ...);

    FUNCTION
        Opens a AmigaGuide database, complete with the first viewing
        window, for synchronous activity.

        Before you call OpenAmigaGuide(), you must initialize a NewAmigaGuide
        structure.  NewAmigaGuide is a structure that contains all the
        information needed to open a database.  The NewAmigaGuide structure
        must be retained until the call returns.

        The function will not return until the user closes all the
        windows.

    INPUTS
        nag - Pointer to an instance of a NewAmigaGuide structure.  That
            structure is initialized with the following data.

                  nag_Lock
                  Lock on the directory that the database is located in.
                  Not needed if nag_Name contains the complete path name.

                  nag_Name
                  Name of the AmigaGuide database.

                  nag_Screen
                  Screen to open the viewing windows on, NULL for the
                  Workbench screen.

                  nag_PubScreen
                  Pointer to the name of the public screen to open on.
                  Must already be opened.

                  nag_HostPort
                  Name of the applications' ARexx port (currently not used).

                  nag_ClientPort
                  Base name to use for the databases' ARexx port.

                  nag_Flags
                  Used to specify the requirements of this database.  The
                  flags are defined in <libraries/amigaguide.h>.

                  nag_Context
                  NULL terminated array of context nodes, in the form of:

                        /* context array */
                        STRPTR context[] =
                        {
                            "MAIN",
                            "INTRO",
                            "GADGETS",
                            NULL
                        };

                  The context array is not copied, but referenced,
                  therefore must remain static throughout the useage of
                  the AmigaGuide system.  This array is only referenced
                  when using the SetAmigaGuideContext() function.

                  nag_Node
                  Node to start at (does not work with OpenAmigaGuideAsync())
.

                  nag_Line
                  Line to start at (does not work with OpenAmigaGuideAsync())
.

                  nag_Extens
                  Used by V37 and beyond to pass additional arguments.

                  nag_Client
                  This is a private pointer, MUST be initialized to NULL.

        attrs - Additional attributes.

    TAGS
        AGA_HelpGroup (ULONG) -- Unique identifier used to identify the
            AmigaGuide help windows.  See OpenWindow() and GetUniqueID().

            Default for this tag is NULL.  Applicability is (I). (V39)

    EXAMPLE

        /* Short example showing synchronous AmigaGuide access */
        LONG ShowAmigaGuideFile (STRPTR name, STRPTR node, LONG line)
        {
            struct NewAmigaGuide nag = {NULL};
            AMIGAGUIDECONTEXT handle;
            LONG retval = 0L;

            /* Fill in the NewAmigaGuide structure */
            nag.nag_Name = name;
            nag.nag_Node = node;
            nag.nag_Line = line;

            /* Open the AmigaGuide client */
            if ( handle = OpenAmigaGuide(&nag, NULL))
            {
                /* Close the AmigaGuide client */
                CloseAmigaGuide(handle);
            }
            else
            {
                /* Get the reason for failure */
                retval = IoErr();
            }

            return (retval);
        }

    RETURNS
        handle - Handle to a AmigaGuide system.

    SEE ALSO
        OpenAmigaGuideAsyncA(), CloseAmigaGuide()


amigaguide.library/OpenAmigaGuideAsyncAmigaguide.library/OpenAmigaGuideAsyncA

   NAME
        OpenAmigaGuideAsyncA - Open an AmigaGuide database async (V34)

   SYNOPSIS
        handle = OpenAmigaGuideAsyncA (nag, attrs);
        d0                              a0   d0

        AMIGAGUIDECONTEXT OpenAmigaGuideAsyncA (struct NewAmigaGuide *,
                                                struct TagItem *);

        handle = OpenAmigaGuideAsync (nag, tag1, ...);

        AMIGAGUIDECONTEXT OpenAmigaGuideAsyncA (struct NewAmigaGuide *,
                                                Tag tag1, ...);

   FUNCTION
        Opens an AmigaGuide database for ansynchronous use.

        The NewAmigaGuide structure, and its pointers, must stay valid until
        an ActiveToolID or ToolStatusID message is received by the calling
        process.

        This function actually spawns OpenAmigaGuide() as another process,
        so, for further documentation, refer to the OpenAmigaGuide()
        function.

   INPUTS
        nag -- Pointer to a valid NewAmigaGuide structure.
            (see OpenAmigaGuide() for documentation on its useage).

        attrs -- Additional attributes.  See OpenAmigaGuideA().

   RETURNS
        handle -- Handle to an AmigaGuide system.

   SEE ALSO
        OpenAmigaGuideA(), CloseAmigaGuide()


amigaguide.library/RemoveAmigaGuideHostAgaguide.library/RemoveAmigaGuideHostA

    NAME
        RemoveAmigaGuideHostA - Remove a dynamic node host.     (V34)

    SYNOPSIS
        use = RemoveAmigaGuideHostA (key, attrs)
        d0                            a0   a1

        LONG RemoveAmigaGuideHostA (AMIGAGUIDEHOST, struct TagItem *);

        use = RemoveAmigaGuideHost (key, tag1, ...);

        LONG RemoveAmigaGuideHost (AMIGAGUIDEHOST, Tag, ...);

    FUNCTION
        This function removes a dynamic node host, that was added by
        AddAmigaGuideHost(), from the system.

    INPUTS
        key - Key that was returned by AddAmigaGuideHost().

        attrs - Additional attributes.  None are defined at this time.

    RETURNS
        use - Number of outstanding clients of this database.  You
            can not exit until use==0.

    SEE ALSO
        AddAmigaGuideHostA()


amigaguide.library/ReplyAmigaGuideMsg

   NAME
        ReplyAmigaGuideMsg - Reply to an AmigaGuide message.    (V34)

   SYNOPSIS
        ReplyAmigaGuideMsg ( msg );
                             a0

        VOID ReplyAmigaGuideMsg (struct AmigaGuideMsg *msg);

   FUNCTION
        This function is used to reply to an AmigaGuide SIPC message.

   INPUTS
        msg - Pointer to a SIPC message returned by a previous call to
            GetAmigaGuideMsg().

   SEE ALSO
        OpenAmigaGuideAsyncA(), AmigaGuideSignal(), GetAmigaGuideMsg()


amigaguide.library/SendAmigaGuideCmdA

   NAME
        SendAmigaGuideCmdA - Send a command string to AmigaGuide (V34)

   SYNOPSIS
        success = SendAmigaGuideCmdA (handle, cmd, attrs );
          d0                            a0    d0   d1

        BOOL SendAmigaGuideCmdA (AMIGAGUIDECONTEXT, STRPTR, struct TagItem *)
;

        success = SendAmigaGuideCmd (handle, cmd, tag1, ...);

        BOOL SendAmigaGuideCmd (AMIGAGUIDECONTEXT, STRPTR, Tag);

   FUNCTION
        This function sends a command string to an AmigaGuide system.  The
        command can consist of any valid AmigaGuide action command.

        The following are the currently valid action commands:

        ALINK <name> - Load the named node into a new window.

        LINK <name> - Load the named node.

        RX <macro> - Execute an ARexx macro.

        RXS <cmd> - Execute an ARexx string file.  To display a picture,
            use 'ADDRESS COMMAND DISPLAY <picture name>', to
            display a text file 'ADDRESS COMMAND MORE <doc>'.

        CLOSE - Close the window (should only be used on windows
            that were started with ALINK).

        QUIT - Shutdown the current database.

   INPUTS
        handle - Handle to an AmigaGuide system.

        cmd - Command string.

        attrs - Future expansion, must be set to NULL for now.

   TAGS
        AGA_Context (ULONG) - Data is used as an index into nag_Context
            array.  This is used to build and send a LINK command.

   EXAMPLE

        /* bring up help on a particular subject */
        SendAmigaGuideCmd(handle, "LINK MAIN", NULL);

   RETURNS
        Returns TRUE if the message was sent, otherwise returns FALSE.

   BUGS
        ALINK does not open a new window when using V39.

   SEE ALSO


amigaguide.library/SendAmigaGuideContextAguide.library/SendAmigaGuideContextA

   NAME
        SendAmigaGuideContextA - Align an AmigaGuide system on the context ID
.
                                                               (V34)
   SYNOPSIS
        success = SendAmigaGuideContextA (handle, attrs);
        d0                                 a0      d0

        BOOL SendAmigaGuideContextA (AMIGAGUIDECONTEXT, struct TagItem *);

        success = SendAmigaGuideContext (handle, tag1, ...);

        BOOL SendAmigaGuideContext (AMIGAGUIDECONTEXT, Tag, ...);

   FUNCTION
        This function is used to send a message to an AmigaGuide system to
        align it on the current context ID.

        This function effectively does a:

            SendAmigaGuideCmd(handle 'LINK ContextArray[contextID]', NULL);

   INPUTS
        handle - Handle to an AmigaGuide system.
        future - Future expansion, must be set to NULL for now.

   EXAMPLE

        struct IntuiMessage *imsg;

        ...

        case RAWKEY:
            switch (imsg->Code)
            {
                case 95:
                    /* bring up help on a particular subject */
                    SendAmigaGuideContext(handle, NULL);
                    break;
                ...
            }
            break;

        ...

   RETURNS
        success -- Returns TRUE if the message was sent, otherwise returns
            FALSE.

   SEE ALSO
        SetAmigaGuideContextA(), SendAmigaGuideCmdA()


amigaguide.library/SetAmigaGuideAttrsA

    NAME
        SetAmigaGuideAttrsA - Set an AmigaGuide attribute.      (V34)

    SYNOPSIS
        retval = SetAmigaGuideAttrsA (handle, attrs);
        d0                             a0      a1

        LONG SetAmigaGuideAttrsA (AMIGAGUIDECONTEXT, struct TagItem *);

        retval = SetAmigaGuideAttrs (handle, tag1, ...);

        LONG SetAmigaGuideAttrs (AMIGAGUIDECONTEXT, Tag, ...);

    FUNCTION
        This function is used to set AmigaGuide attributes.

    INPUTS
        handle -- Pointer to an AmigaGuide handle.

        attrs -- Attribute pairs to set.

    TAGS
        AGA_Activate (BOOL) - AmigaGuide activates the window when
            it receives a LINK command.  This tag allows the
            application developer to turn that feature off and on.

    SEE ALSO
        GetAmigaGuideAttr()


amigaguide.library/SetAmigaGuideContextAgaguide.library/SetAmigaGuideContextA

   NAME
        SetAmigaGuideContextA - Set the context ID for an AmigaGuide system.
                                                               (V34)
   SYNOPSIS
        success = SetAmigaGuideContextA ( handle, context, attrs );
        d0                                 a0       d0      d1

        BOOL SetAmigaGuideContextA (AMIGAGUIDECONTEXT, ULONG,
                                    struct TagItem *);

        success = SetAmigaGuideContext (handle, context, tag1, ...);

        BOOL SetAmigaGuideContext (AMIGAGUIDECONTEXT, ULONG, Tag, ...);

   FUNCTION
        This function, and the SendAmigaGuideContext() function, are used to
        provide a simple way to display a node based on a numeric value,
        instead of having to build up a slightly more complex command
        string.

   INPUTS
        handle -- Handle to an AmigaGuide system.

        context -- Index value of the desired node to display.

        future -- Future expansion, must be set to NULL for now.

   EXAMPLE

        /* sample context table */
        STRPTR ContextArray[] =
        {
            "MAIN",
            "FILEREQ",
            "PRINT",
            "ABOUT",
            NULL
        };

        /* quickie defines */
        #define HELP_MAIN      0
        #define HELP_FILEREQ   1
        #define HELP_PRINT     2
        #define HELP_ABOUT     3

        ...

        struct NewAmigaGuide nag = {NULL};

        /* initialize the context table */
        nag.nag_Context = ContextArray;

        ...

        /* bring up help on a particular subject */
        SetAmigaGuideContext(handle, HELP_ABOUT, NULL);

   RETURNS
        success - Returns TRUE if a valid context ID was passed,
            otherwise returns FALSE.

   SEE ALSO
        SendAmigaGuideContextA(), SendAmigaGuideCmdA()


amigaguide.library/UnlockAmigaGuideBasemigaguide.library/UnlockAmigaGuideBase

    NAME
        UnlockAmigaGuideBase - Unlock an AmigaGuide client.     (V34)

    SYNOPSIS
        UnlockAmigaGuideBase (key);
                              d0

        VOID UnlockAmigaGuideBase (LONG);

    FUNCTION
        This function is used to release a lock obtained with
        LockAmigaGuideBase().

    INPUTS
        key - Value returned by LockAmigaGuideBase().

    SEE ALSO
        LockAmigaGuideBase().


amigaguide_dtc.doc

     GetAGString()
     amigaguide.datatype()


amigaguide.class/GetAGString

    NAME
        GetAGString - Obtain localized AmigaGuide text  (V34)

    SYNOPSIS
        string = GetAGString (id);
        d0                      d0

        STRPTR GetAGString (LONG);

    FUNCTION
        This function is used to obtain a pointer to the string
        associated with the given ID.

    INPUTS
        id        - Catalog entry to obtain.

    RETURNS
        Returns a pointer to the NULL terminated string. NULL on
        failure.

    SEE ALSO


amigaguide/amigaguide.datatype

    NAME
        amigaguide.datatype -- data type for AmigaGuide databases.

    FUNCTION
        The amigaguide.datatype is the DataTypes class for AmigaGuide
        databases.

    METHODS
        OM_NEW -- Create a new AmigaGuide object.

        OM_GET -- Obtain the value of an attribute.

        OM_SET -- Set the values of multiple attributes.

        OM_UPDATE -- Update the values of multiple attributes.

        OM_DISPOSE -- Dispose of an AmigaGuide object.

        GM_LAYOUT -- Layout the object and notify the application of the
            title and size.

        GM_HITTEST -- Determine if the object has been hit with the
            mouse.

        GM_GOACTIVE -- Tell the object to go active.

        GM_HANDLEINPUT -- Handle input.

        GM_RENDER -- Cause the AmigaGuide database to render.

        DTM_GOTO -- Cause the AmigaGuide database to load and display
            document.

        DTM_TRIGGER -- Trigger an event.

            STM_COMMAND - Invoke an AmigaGuide command.

            STM_CONTENTS - Display the table of contents.

            STM_INDEX - Display the index.

            STM_HELP - Display the help file.

            STM_RETRACE - Retrace.

            STM_BROWSE_PREV - Go to the previous sequential document.

            STM_BROWSE_NEXT - Go to the next sequential document.

        DTM_PROCLAYOUT -- Layout (remap) the AmigaGuide database on the
            application's process.

        DTM_FRAMEBOX -- Obtain the display environment that the
            AmigaGuide database requires.

        DTM_SELECT -- Select an area in the AmigaGuide database.

        DTM_CLEARSELECTED -- Deselect the selected area of the
            AmigaGuide database.

        DTM_COPY -- Copy the selected area of the text to the clipboard
            as FTXT.  If no area is selected, then the entire text
            is copied.

        DTM_PRINT -- Print the selected area of the text.  If no area
            is selected, then the entire text is printed.

        DTM_WRITE -- Write the selected area of the text to a file.
            If no area is selected, then the entire text is saved.

    TAGS
        DTA_TriggerMethods -- List of the trigger methods supported.

            Applicability is (G).

        DTA_Methods -- List of the methods supported.

            Applicability is (G).

        DTA_TextAttr (struct TextAttr *) -- Text attribute to use for
            the AmigaGuide database.

            Applicability is (ISG).

        DTA_Name (STRPTR) -- Name of the AmigaGuide database.

            Applicability is (I).

        DTA_Handle (BPTR) -- File handle for the AmigaGuide database.

            Applicability is (I).

        DTA_NodeName (STRPTR) -- Document to display.

            Applicability is (I).

        TDTA_WordDelim (STRPTR) -- Characters used to deliminate words.

            Applicability is (IS). Defaults to "t *-,<>()[];"".

        AGA_HelpGroup (ULONG) -- Help group that the AmigaGuide object
            belongs in.

            Applicability is (I).

        AGA_Secure (BOOL) -- This tag allows you control whether
            AmigaGuide will execute the commands "ONOPEN", "ONCLOSE",
            "LINK RX", "LINK RXS" and "LINK SYSTEM". These commands
            present a potential security hole if, for example,
            AmigaGuide documents are displayed in an e-mail reader
            program. To disabled them, set the AGA_Secure tag to
            TRUE; in this case AmigaGuide will still recognize the
            commands but will not execute them.

            Applicability is (ISG). Defaults to FALSE. (V41)

    COMMANDS
        Commands must start in the very first column of a line, and
        can be the only thing on the line.  If a line begins with an
        @ sign, then it is interpreted as a command.

        The following commands can be used in the global section
        of a database.

          @$VER: <AmigaDOS version string>
          Specify the version of the database.  This command
          must always be in upper-case.

          @(C) <copyright>
          Specify the copyright notice for the database.

          @AUTHOR <name>
          Specify the author of the database.

          @DATABASE <name>
          Must be the very first line of an AmigaGuide document.

          @DNODE <name>
          Indicates the start of a dynamic node.  The AmigaGuide system
          uses the callback hooks to obtain the document from a document
          provider.  This is obsolete, do not use.

          @FONT <name> <size>
          Specify the font to use for the database.

          @HEIGHT <chars>
          How high, in characters, the largest document is.

          @HELP <name/node>
          Specify the name of the help node, which will be accessed
          by the Help button.  Can be a node in an external database.

          @INDEX <name/node>
          Specify the name of the index node, which will be accessed
          by the Index button.  Can be a node in an external database.

          @MACRO <name> <commands>
          This is used to construct a macro.  A macro can be used the
          same way as an attribute command, and can only consist of
          other attribute commands or macros.  The macro list is
          searched before the attribute command list is searched.  This
          is new for V40.

              @macro icom "@{i}$1 @{ui}"

              ...

              This is an @{icom "example"} of macro.

          @MASTER <path>
          Complete path of the source document used to define this
          AmigaGuide database.

          @NODE <name> <title>
          Indicate the start of a node (page/article/section). The first
          node, or main node, must be named MAIN.  MAIN must be the master
          table of contents for the database.

          @ONCLOSE <rxcommand>
          This is used to specify an ARexx macro file to execute when
          the database is closed.  The return value of the script has no
          effect on the database.  New for V40.

          @ONOPEN <rxcommand>
          This is used to specify an ARexx macro file to execute when
          the database is opened.  If the script returns an error, then
          the database will not be opened.  New for V40.

          @REM <remark>
          @REMARK <remark>
          This is used to place remarks in the database.  These remarks
          are not displayed to the user.

          @SMARTWRAP
          This is used to indicate that the text of the database is to
          wordwrapped using a more intelligent algorithm than @WORDWRAP.
          A paragraph doesn't need to be restricted to one physical
          line, but paragraphs must be separated by two line feeds.
          New for V40.

          @TAB <num>
          Number of spaces in a tab.  Defaults to 8.  New for V40.

          @WIDTH <chars>
          How wide, in characters, the largest document is.

          @WORDWRAP
          Turn on wordwrapping for the whole database.  A paragraph must
          be restrained to one physical line.

        The following commands can be used within nodes of a database.

          \
          A backslash is the escape character.  A backslash in front of
          the @ sign is used to escape it. The backslash has no effect
          as an escape character inside commands such as @ONOPEN or
          @{".." LINK ..}; in cases like these it is treated as a
          regular character.
          Please note that AmigaGuide V35 does not treat the backslash
          character as an escape character.

          @ENDNODE <name>
          Indicate the end of a node.  Must start at the beginning of a
          line.

          @FONT <name> <size>
          Specify the font to use for the node.

          @HELP <name/node>
          Specify the name of the help node, which will be accessed
          by the Help button.  Can be a node in an external database.

          @INDEX <name/node>
          Specify the name of the index node, which will be accessed
          by the Index button.  Can be a node in an external database.

          @KEYWORDS <keywords>
          Keywords of the node.  Someday when searching is
          reimplemented, there will be a keyword search.

          @NEXT <node name>
          Node to display when the user selects "Browse >"

          @ONCLOSE <rxcommand>
          This is used to specify an ARexx macro file to execute when
          the node is closed.  The return value of the script has no
          effect on the node.  New for V40.

          @ONOPEN <rxcommand>
          This is used to specify an ARexx macro file to execute when
          the node is opened.  If the script returns an error, then
          the node will not be opened.  New for V40.

          @PREV <node name>
          Node to display when the user selects "< Browse"

          @SMARTWRAP
          This is used to indicate that the text of the node is to
          wordwrapped using a more intelligent algorithm than @WORDWRAP.
          A paragraph doesn't need to be restricted to one physical
          line, but paragraphs must be separated by two line feeds.
          New for V40.

          @TAB <num>
          Number of spaces in a tab.  Defaults to 8.  New for V40.

          @TITLE <title>
          Title to display in the title bar of the window during the
          display of this node.  Must start at the beginning of a line.

          @TOC <node name>
          Name of the node that contains the table of contents for this
          node.  Defaults to MAIN.  This is the node that is displayed
          when the user presses the "Contents" button.

          @WORDWRAP
          Turn on wordwrapping for the node.  A paragraph must
          be restrained to one physical line.

          @{<label> <command>}
          Indicate a textual link point.  Can be anywhere in a line.
          Starting with 3.0, AmigaGuide can can link to graphics,
          sounds, animations and other DataTypes.

    ATTRIBUTES
        Following is a list of attributes that can be applied to the
        text of a node.

          @{AMIGAGUIDE}
          Displays the word AmigaGuide in bold followed by the ® symbol.
          New for V40.

          @{APEN}
          Use to change the foreground color to a specific pen number.
          New for V40.

          @{B}
          Turn bold on.

          @{BG <color>}
          Used to change the background text color.  Color can be:

            Text
            Shine
            Shadow
            Fill
            FillText
            Background
            Highlight

          @{BODY}
          Indicate that the following text is the body of the document.
          Word wrap will be turned back on if it is the default.  New
          for V40.

          @{BPEN}
          Use to change the background color to a specific pen number.
          New for V40.

          @{CLEARTABS}
          Restore the default tab stops.  New for V40.

          @{CODE}
          Indicate that the following text is not to be word-wrapped.
          New for V40.

          @{FG <color>}
          Used to change the foreground color.  The same colors can be
          used as in the FG command.

          @{I}
          Turn italic on.

          @{JCENTER}
          Turn on centering.  New for V40.

          @{JLEFT}
          Turn on left justification.  New for V40.

          @{JRIGHT}
          Turn on right justification.  New for V40.

          @{LINDENT}
          Set the number of spaces to indent the body of a paragraph.
          New for V40.

          @{LINE}
          Force a line feed without starting a new paragraph.  New for V40.

          @{PAR}
          Used to indicate the end of a paragraph.  This is the same as
          two sequential LF's in the source file.  New for V40.

          @{PARD}
          Restore the default settings for a paragraph.  Text pen to 1,
          background to 0, normal font, and no indentation.  New for V40.

          @{PARI}
          Set the number of spaces to indent the first line of a
          paragraph relative to the normal paragraph indentation.  The
          value may be a negative number.  New for V40.

          @{PLAIN}
          Used to turn off all @{B}, @{I}, and @{U} commands.  New for
          V40.

          @{SETTABS <n> ... <n>}
          This is used to establish tab stops.  New for V40.

          @{TAB}
          The same as character 9 in the source file.  New for V40.

          @{U}
          Turn underline on.

          @{UB}
          Turn bold off.

          @{UI}
          Turn italic off.

          @{UU}
          Turn underline off.

    AREXX COMMANDS
        AmigaGuide supports the following ARexx commands.

          BEEP
          DisplayBeep().

          CLOSE
          Close the current database.

          GETNODECOUNT
          Returns the number of nodes in the database using the RESULT
          variable.  New for V40.

          LINK
          Go to the named node.

          NEXT
          Go to the next physical node in the database.  Same as
          pressing the "Browse >" button.  New for V40.

          PREVIOUS
          Go to the previous physical node in the database.  Same as
          pressing the "Browse <" button.  New for V40.

          PRINT
          Print the current node.  Doesn't return until complete.  New for
          V40.

          QUIT
          Close the current database.

          RETRACE
          Go to the previous node in the database.  Same as pressing the
          "Retrace" button.  New for V40.


amiga_lib.doc

     ACrypt()
     AddTOF()
     afp()
     ArgArrayDone()
     ArgArrayInit()
     ArgInt()
     ArgString()
     arnd()
     BeginIO()
     CallHook()
     CallHookA()
     CheckRexxMsg()
     CoerceMethod()
     CoerceMethodA()
     CreateExtIO()
     CreatePort()
     CreateStdIO()
     CreateTask()
     CxCustom()
     CxDebug()
     CxFilter()
     CxSender()
     CxSignal()
     CxTranslate()
     dbf()
     DeleteExtIO()
     DeletePort()
     DeleteStdIO()
     DeleteTask()
     DoMethod()
     DoMethodA()
     DoSuperMethod()
     DoSuperMethodA()
     FastRand()
     fpa()
     FreeIEvents()
     GetRexxVar()
     HookEntry()
     HotKey()
     InvertString()
     LibAllocPooled()
     LibCreatePool()
     LibDeletePool()
     LibFreePooled()
     NewList()
     printf()
     RangeRand()
     RemTOF()
     SetRexxVar()
     SetSuperAttrs()
     sprintf()
     stdio()
     TimeDelay()


amiga.lib/ACrypt

   NAME
    ACrypt -- Encrypt a password

   SYNOPSIS
    newpass = ACrypt( buffer, password, username )

    UBYTE *ACrypt( UBYTE *, UBYTE *, UBYTE *) ;

   FUNCTION
    This function takes a buffer of at least 12 characters in length,
    an unencrypted password and the user's name (as known to the host
    system) and returns an encrypted password in the passed buffer.
    This is a one-way encryption. Normally, the user's encrypted
    password is stored in a file for future password comparison.

   INPUTS
    buffer     - a pointer to a buffer at least 12 bytes in length.
    password   - a pointer to an unencrypted password string.
    username   - a pointer to the user's name.

   RESULT
    newpass    - a pointer to the passed buffer if successful, NULL
                 upon failure. The encrypted password placed in the
                 buffer will be be eleven (11) characters in length
                 and will be NULL-terminated.

   EXAMPLE

    UBYTE *pw, *getpassword() ;
    UBYTE *user = "alf"
    UBYTE *newpass ;
    UBYTE buffer[16] ;         /* size >= 12 */

    pw = getpassword() ;   /* your own function */

    if((newpass = ACrypt(buffer, pw, user)) != NULL)
    {
        printf("pw = %sn", newpass) ; /* newpass = &buffer[0] */
    }
    else
    {
        printf("ACrypt failedn") ;
    }


amiga.lib/CallHook

   NAME
    CallHook -- Invoke a hook given a message on the stack.

   SYNOPSIS
    result = CallHook( hookPtr, obj, ... )

    ULONG CallHook( struct Hook *, Object *, ... );

   FUNCTION
    Like CallHookA(), CallHook() invoke a hook on the supplied
    hook-specific data (an "object") and a parameter packet ("message").
    However, CallHook() allows you to build the message on your stack.

   INPUTS
    hookPtr - A system-standard hook
    obj - hook-specific data object
    ... - The hook-specific message you wish to send.  The hook is
        expecting a pointer to the message, so a pointer into your
        stack will be sent.

   RESULT
    result - a hook-specific result.

   NOTES
    This function first appeared in the V37 release of amiga.lib.
    However, it does not depend on any particular version of the OS,
    and works fine even in V34.

   EXAMPLE
    If your hook's message was

        struct myMessage
        {
        ULONG mm_FirstGuy;
        ULONG mm_SecondGuy;
        ULONG mm_ThirdGuy;
        };

    You could write:

        result = CallHook( hook, obj, firstguy, secondguy, thirdguy );

    as a shorthand for:

        struct myMessage msg;

        msg.mm_FirstGuy = firstguy;
        msg.mm_SecondGuy = secondguy;
        msg.mm_ThirdGuy = thirdguy;

        result = CallHookA( hook, obj, &msg );

   SEE ALSO
    CallHookA(), utility.library/CallHookPkt(), <utility/hooks.h>


amiga.lib/CallHookA

   NAME
    CallHookA -- Invoke a hook given a pointer to a message.

   SYNOPSIS
    result = CallHookA( hookPtr, obj, message )

    ULONG CallHook( struct Hook *, Object *, APTR );

   FUNCTION
    Invoke a hook on the supplied hook-specific data (an "object")
    and a parameter packet ("message").  This function is equivalent
    to utility.library/CallHookPkt().

   INPUTS
    hookPtr - A system-standard hook
    obj - hook-specific data object
    message - The hook-specific message you wish to send

   RESULT
    result - a hook-specific result.

   NOTES
    This function first appeared in the V37 release of amiga.lib.
    However, it does not depend on any particular version of the OS,
    and works fine even in V34.

   SEE ALSO
    CallHook(), utility.library/CallHookPkt(), <utility/hooks.h>


amiga.lib/CoerceMethod

   NAME
    CoerceMethod -- Perform method on coerced object.

   SYNOPSIS
    result = CoerceMethod( cl, obj, MethodID, ... )

    ULONG CoerceMethod( struct IClass *, Object *, ULONG, ... );

   FUNCTION
    Boopsi support function that invokes the supplied message
    on the specified object, as though it were the specified
    class.  Equivalent to CoerceMethodA(), but allows you to
    build the message on the stack.

   INPUTS
    cl - pointer to boopsi class to receive the message
    obj - pointer to boopsi object
    ... - method-specific message built on the stack

   RESULT
    result - class and message-specific result.

   NOTES
    This function first appears in the V37 release of amiga.lib.
    While it intrinsically does not require any particular release
    of the system software to operate, it is designed to work with
    the boopsi subsystem of Intuition, which was only introduced
    in V36.

   SEE ALSO
    CoerceMethodA(), DoMethodA(), DoSuperMethodA(), <intuition/classusr.h>
    ROM Kernel Manual boopsi section


amiga.lib/CoerceMethodA

   NAME
    CoerceMethodA -- Perform method on coerced object.

   SYNOPSIS
    result = CoerceMethodA( cl, obj, msg )

    ULONG CoerceMethodA( struct IClass *, Object *, Msg );

   FUNCTION
    Boopsi support function that invokes the supplied message
    on the specified object, as though it were the specified
    class.

   INPUTS
    cl - pointer to boopsi class to receive the message
    obj - pointer to boopsi object
    msg - pointer to method-specific message to send

   RESULT
    result - class and message-specific result.

   NOTES
    This function first appears in the V37 release of amiga.lib.
    While it intrinsically does not require any particular release
    of the system software to operate, it is designed to work with
    the boopsi subsystem of Intuition, which was only introduced
    in V36.
    Some early example code may refer to this function as CM().

   SEE ALSO
    CoerceMethod(), DoMethodA(), DoSuperMethodA(), <intuition/classusr.h>
    ROM Kernel Manual boopsi section


amiga.lib/CreateTask

   NAME
    CreateTask -- Create task with given name, priority, stacksize

   SYNOPSIS
    task = CreateTask(name,pri,initPC,stackSize)

    struct Task *CreateTask(STRPTR,LONG,funcEntry,ULONG);

   FUNCTION
    This function simplifies program creation of sub-tasks by
    dynamically allocating and initializing required structures
    and stack space, and adding the task to Exec's task list
    with the given name and priority. A tc_MemEntry list is provided
    so that all stack and structure memory allocated by CreateTask()
    is automatically deallocated when the task is removed.

    An Exec task may not call dos.library functions or any function
    which might cause the loading of a disk-resident library, device,
    or file (since such functions are indirectly calls to dos.library).
    Only AmigaDOS Processes may call AmigaDOS; see the
    dos.library/CreateProc() or the dos.library/CreateNewProc()
    functions for more information.

    If other tasks or processes will need to find this task by name,
    provide a complex and unique name to avoid conflicts.

    If your compiler provides automatic insertion of stack-checking
    code, you may need to disable this feature when compiling sub-task
    code since the stack for the subtask is at a dynamically allocated
    location.  If your compiler requires 68000 registers to contain
    particular values for base relative addressing, you may need to
    save these registers from your main process, and restore them
    in your initial subtask code.

    The function entry initPC is generally provided as follows:

    In C:
    extern void functionName();
    char *tname = "unique name";
    task = CreateTask(tname, 0L, functionName, 4000L);

    In assembler:
        PEA	startLabel

   INPUTS
    name - a null-terminated name string
    pri - an Exec task priority between -128 and 127, normally 0
    funcEntry - the address of the first executable instruction
            of the subtask code
    stackSize - size in bytes of stack for the subtask. Don't cut it
            too close - system function stack usage may change.

   RESULT
    task - a pointer to the newly created task, or NULL if there was not
           enough memory.

   BUGS
    Under exec.library V37 or beyond, the AddTask() function used
    internally by CreateTask() can fail whereas it couldn't fail in
    previous versions of Exec. Prior to amiga.lib V37.14, this function
    did not check for failure of AddTask() and thus might return a
    pointer to a task structure even though the task was not actually
    added to the system.

    Prior to amiga.lib V40.20 low memory conditions could cause
    CreateTask() to malfunction. The implementation checked whether the
    initial AllocEntry() call would fail, but would use an inappropriate
    test condition.

   SEE ALSO
    DeleteTask(), exec/FindTask()


amiga.lib/CxDebug

   NAME
    CxDebug -- create a commodity debug object. (V36)

   SYNOPSIS
    debugObj = CxDebug(id);

    CxObj *CxDebug(LONG);

   FUNCTION
    This function creates a Commodities debug object. The action of this
    object on receiving a Commodities message is to print out information
    about the Commodities message through the serial port (using the
    kprintf() routine). The value of 'id' will also be displayed.

    Note that this is a synchronous occurrence (the printing is done by
    the input device task). If screen or file output is desired, using a
    sender object instead of a debug object is necessary, since such
    output is best done by your application process.

    This function is a C-language macro for CreateCxObj(), defined
    in <libraries/commodities.h>.

   INPUTS
    id - the id to assign to the debug object, this value is output
         whenever the debug object sends data to the serial port.

   RESULTS
    debugObj - a pointer to the debug object, or NULL if it could
           not be created.

   SEE ALSO
    commodities.library/CreateCxObj(), CxSender(), debug.lib/kprintf()


amiga.lib/CxSender

   NAME
    CxSender -- create a commodity sender object. (V36)

   SYNOPSIS
    senderObj = CxSender(port,id)

    CxObj *CxSender(struct MsgPort *,LONG);

   FUNCTION
    This function creates a Commodities sender object. The action
    of this object on receiving a Commodities message is to copy the
    Commodities message into a standard Exec Message, to put the value
    'id' in the message as well, and to send the message off to the
    message port 'port'.

    The value 'id' is used so that an application can monitor
    messages from several senders at a single port. It can be retrieved
    from the Exec message by using the function CxMsgID(). The value can
    be a simple integer ID, or a pointer to some application data
    structure.

    Note that Exec messages sent by sender objects arrive
    asynchronously at the destination port. Do not assume anything about
    the status of the Commodities message which was copied into the Exec
    message you received.

    All Exec messages sent to your ports must be replied. Messages may be
    replied after the sender object has been deleted.

    This function is a C-language macro for CreateCxObj(), defined
    in <libraries/commodities.h>.

   INPUTS
    port - the port for the sender to send messages to
    id - the id of the messages sent by the sender

   RESULTS
    senderObj - a pointer to the sender object, or NULL if it could
            not be created.

   SEE ALSO
    commodities.library/CreateCxObj(), commodities.library/CxMsgID(),
    exec.library/PutMsg(), exec.library/ReplyMsg()


amiga.lib/DoMethod

   NAME
    DoMethod -- Perform method on object.

   SYNOPSIS
    result = DoMethod( obj, MethodID, ... )

    ULONG DoMethod( Object *, ULONG, ... );

   FUNCTION
    Boopsi support function that invokes the supplied message
    on the specified object.  The message is invoked on the
    object's true class.  Equivalent to DoMethodA(), but allows
    you to build the message on the stack.

   INPUTS
    obj - pointer to boopsi object
    MethodID - which method to send (see <intuition/classusr.h>)
    ... - method-specific message built on the stack

   RESULT
    result - specific to the message and the object's class.

   NOTES
    This function first appears in the V37 release of amiga.lib.
    While it intrinsically does not require any particular release
    of the system software to operate, it is designed to work with
    the boopsi subsystem of Intuition, which was only introduced
    in V36.

   SEE ALSO
    DoMethodA(), CoerceMethodA(), DoSuperMethodA(), <intuition/classusr.h>
    ROM Kernel Manual boopsi section


amiga.lib/DoMethodA

   NAME
    DoMethodA -- Perform method on object.

   SYNOPSIS
    result = DoMethodA( obj, msg )

    ULONG DoMethodA( Object *, Msg );

   FUNCTION
    Boopsi support function that invokes the supplied message
    on the specified object.  The message is invoked on the
    object's true class.

   INPUTS
    obj - pointer to boopsi object
    msg - pointer to method-specific message to send

   RESULT
    result - specific to the message and the object's class.

   NOTES
    This function first appears in the V37 release of amiga.lib.
    While it intrinsically does not require any particular release
    of the system software to operate, it is designed to work with
    the boopsi subsystem of Intuition, which was only introduced
    in V36.
    Some early example code may refer to this function as DM().

   SEE ALSO
    DoMethod(), CoerceMethodA(), DoSuperMethodA(), <intuition/classusr.h>
    ROM Kernel Manual boopsi section


amiga.lib/DoSuperMethod

   NAME
    DoSuperMethod -- Perform method on object coerced to superclass.

   SYNOPSIS
    result = DoSuperMethod( cl, obj, MethodID, ... )

    ULONG DoSuperMethod( struct IClass *, Object *, ULONG, ... );

   FUNCTION
    Boopsi support function that invokes the supplied message
    on the specified object, as though it were the superclass
    of the specified class.  Equivalent to DoSuperMethodA(),
    but allows you to build the message on the stack.

   INPUTS
    cl - pointer to boopsi class whose superclass is to
        receive the message
    obj - pointer to boopsi object
    ... - method-specific message built on the stack

   RESULT
    result - class and message-specific result.

   NOTES
    This function first appears in the V37 release of amiga.lib.
    While it intrinsically does not require any particular release
    of the system software to operate, it is designed to work with
    the boopsi subsystem of Intuition, which was only introduced
    in V36.

   SEE ALSO
    CoerceMethodA(), DoMethodA(), DoSuperMethodA(), <intuition/classusr.h>
    ROM Kernel Manual boopsi section


amiga.lib/DoSuperMethodA

   NAME
    DoSuperMethodA -- Perform method on object coerced to superclass.

   SYNOPSIS
    result = DoSuperMethodA( cl, obj, msg )

    ULONG DoSuperMethodA( struct IClass *, Object *, Msg );

   FUNCTION
    Boopsi support function that invokes the supplied message
    on the specified object, as though it were the superclass
    of the specified class.

   INPUTS
    cl - pointer to boopsi class whose superclass is to
        receive the message
    obj - pointer to boopsi object
    msg - pointer to method-specific message to send

   RESULT
    result - class and message-specific result.

   NOTES
    This function first appears in the V37 release of amiga.lib.
    While it intrinsically does not require any particular release
    of the system software to operate, it is designed to work with
    the boopsi subsystem of Intuition, which was only introduced
    in V36.
    Some early example code may refer to this function as DSM().

   SEE ALSO
    CoerceMethodA(), DoMethodA(), DoSuperMethod(), <intuition/classusr.h>
    ROM Kernel Manual boopsi section


amiga.lib/fpa

   NAME
    fpa - convert fast floating point into ASCII string equivalent

   SYNOPSIS
    exp = fpa(fnum, &string[0]);

   FUNCTION
    Accepts an FFP number and the address of the ASCII string where it's
    converted output is to be stored.  The number is converted to a NULL
    terminated ASCII string in and stored at the address provided.
    Additionally, the base ten (10) exponent in binary form is returned.

   INPUTS
    fnum	   - Motorola Fast Floating Point number
    &string[0] - address for output of converted ASCII character string
             (16 bytes)

   RESULT
    &string[0] - converted ASCII character string
    exp	   - integer exponent value in binary form

   BUGS
    None


amiga.lib/HookEntry

   NAME
    HookEntry -- Assembler to HLL conversion stub for hook entry.

   SYNOPSIS
    result = HookEntry( struct Hook *, Object *, APTR )
    D0                  A0             A2        A1

   FUNCTION
    By definition, a standard hook entry-point must receive the
    hook in A0, the object in A2, and the message in A1.  If your
    hook entry-point is written in a high-level language and is
    expecting its parameters on the stack, then HookEntry() will
    put the three parameters on the stack and invoke the function
    stored in the hook h_SubEntry field.

    This function is only useful to hook implementers, and is
    never called from C.

   INPUTS
    hook - pointer to hook being invoked
    object - pointer to hook-specific data
    msg - pointer to hook-specific message

   RESULT
    result - a hook-specific result.

   NOTES
    This function first appeared in the V37 release of amiga.lib.
    However, it does not depend on any particular version of the OS,
    and works fine even in V34.

   EXAMPLE
    If your hook dispatcher is this:

    dispatch( struct Hook *hookPtr, Object *obj, APTR msg )
    {
        ...
    }

    Then when you initialize your hook, you would say:

    myhook.h_Entry = HookEntry;	/* amiga.lib stub */
    myhook.h_SubEntry = dispatch;	/* HLL entry */

   SEE ALSO
    CallHook(), CallHookA(), <utility/hooks.h>


amiga.lib/LibAllocPooled

    NAME
    LibAllocPooled -- Allocate memory with the pool manager (V33)

    SYNOPSIS
    memory=LibAllocPooled(poolHeader,memSize)
    d0                    a0         d0

    void *LibAllocPooled(void *,ULONG);

    FUNCTION
    This function is a copy of the pool functions in V39 and up of
    EXEC.  In fact, if you are running in V39, this function will
    notice and call the EXEC function.  This function works in
    V33 and up (1.2) Amiga system.

    The C code interface is _LibAllocPooled() and takes its arguments
    from the stack just like the C code interface for AllocPooled()
    in amiga.lib.  The assembly code interface is with the symbol
    _AsmAllocPooled: and takes the parameters in registers with the
    additional parameter of ExecBase being in a6 which can be used
    from SAS/C 6 by a prototype of:

    void * __asm AsmAllocPooled(register __a0 void *,
                                register __d0 ULONG,
                                register __a6 struct ExecBase *);

    Allocate memSize bytes of memory, and return a pointer. NULL is
    returned if the allocation fails.

    Doing a LibDeletePool() on the pool will free all of the puddles
    and thus all of the allocations done with LibAllocPooled() in that
    pool.  (No need to LibFreePooled() each allocation)

    INPUTS
    memSize - the number of bytes to allocate
    poolHeader - a specific private pool header.

    RESULT
    A pointer to the memory, or NULL.
    The memory block returned is long word aligned.

    NOTES
    The pool function do not protect an individual pool from
    multiple accesses.  The reason is that in most cases the pools
    will be used by a single task.  If your pool is going to
    be used by more than one task you must Semaphore protect
    the pool from having more than one task trying to allocate
    within the same pool at the same time.  Warning:  Forbid()
    protection *will not work* in the future.  *Do NOT* assume
    that we will be able to make it work in the future.  LibAllocPooled()
    may well break a Forbid() and as such can only be protected
    by a semaphore.

    To track sizes yourself, the following code can be used:
    *Assumes a6=ExecBase*

    ;
    ; Function to do AllocVecPooled(Pool,memSize)
    ;
    AllocVecPooled:	addq.l	#4,d0		; Get space for tracking
            move.l	d0,-(sp)	; Save the size
            jsr	LibAllocPooled	; Call pool...
            move.l	(sp)+,d1	; Get size back...
            tst.l	d0		; Check for error
            beq.s	avp_fail	; If NULL, failed!
            move.l	d0,a0		; Get pointer...
            move.l	d1,(a0)+	; Store size
            move.l	a0,d0		; Get result
    avp_fail:	rts			; return

    ;
    ; Function to do LibFreeVecPooled(pool,memory)
    ;
    FreeVecPooled:	move.l	-(a1),d0	; Get size / ajust pointer
            jmp	LibFreePooled

    SEE ALSO
    FreePooled(), CreatePool(), DeletePool(),
    LibFreePooled(), LibCreatePool(), LibDeletePool()


amiga.lib/LibCreatePool

    NAME
    LibCreatePool -- Generate a private memory pool header (V33)

    SYNOPSIS
    newPool=LibCreatePool(memFlags,puddleSize,threshSize)
    a0                    d0       d1         d2

    void *LibCreatePool(ULONG,ULONG,ULONG);

    FUNCTION
    This function is a copy of the pool functions in V39 and up of
    EXEC.  In fact, if you are running in V39, this function will
    notice and call the EXEC function.  This function works in
    V33 and up (1.2) Amiga system.

    The C code interface is _LibCreatePool() and takes its arguments
    from the stack just like the C code interface for CreatePool()
    in amiga.lib.  The assembly code interface is with the symbol
    _AsmCreatePool: and takes the parameters in registers with the
    additional parameter of ExecBase being in a6 which can be used
    from SAS/C 6 by a prototype of:

    void * __asm AsmCreatePool(register __d0 ULONG,
                               register __d1 ULONG,
                               register __d2 ULONG,
                               register __a6 struct ExecBase *);

    Allocate and prepare a new memory pool header.	Each pool is a
    separate tracking system for memory of a specific type.  Any number
    of pools may exist in the system.

    Pools automatically expand and shrink based on demand.	Fixed sized
    "puddles" are allocated by the pool manager when more total memory
    is needed.  Many small allocations can fit in a single puddle.
    Allocations larger than the threshSize are allocation in their own
    puddles.

    At any time individual allocations may be freed.  Or, the entire
    pool may be removed in a single step.

    INPUTS
    memFlags - a memory flags specifier, as taken by AllocMem.
    puddleSize - the size of Puddles...
    threshSize - the largest allocation that goes into normal puddles
                 This *MUST* be less than or equal to puddleSize
                 (LibCreatePool() will fail if it is not)

    RESULT
    The address of a new pool header, or NULL for error.

    SEE ALSO
    DeletePool(), AllocPooled(), FreePooled(), exec/memory.i,
    LibDeletePool(), LibAllocPooled(), LibFreePooled()


amiga.lib/LibDeletePool

    NAME
    LibDeletePool --  Drain an entire memory pool (V33)

    SYNOPSIS
    LibDeletePool(poolHeader)
                  a0

    void LibDeletePool(void *);

    FUNCTION
    This function is a copy of the pool functions in V39 and up of
    EXEC.  In fact, if you are running in V39, this function will
    notice and call the EXEC function.  This function works in
    V33 and up (1.2) Amiga system.

    The C code interface is _LibDeletePool() and takes its arguments
    from the stack just like the C code interface for DeletePool()
    in amiga.lib.  The assembly code interface is with the symbol
    _AsmDeletePool: and takes the parameters in registers with the
    additional parameter of ExecBase being in a6 which can be used
    from SAS/C 6 by a prototype of:

    void __asm AsmDeletePool(register __a0 void *,
                             register __a6 struct ExecBase *);

    Frees all memory in all puddles of the specified pool header, then
    deletes the pool header.  Individual free calls are not needed.

    INPUTS
    poolHeader - as returned by LibCreatePool().

    SEE ALSO
    CreatePool(), AllocPooled(), FreePooled(),
    LibCreatePool(), LibAllocPooled(), LibFreePooled()


amiga.lib/LibFreePooled

    NAME
    LibFreePooled -- Free pooled memory  (V33)

    SYNOPSIS
    LibFreePooled(poolHeader,memory,memSize)
              a0         a1     d0

    void LibFreePooled(void *,void *,ULONG);

    FUNCTION
    This function is a copy of the pool functions in V39 and up of
    EXEC.  In fact, if you are running in V39, this function will
    notice and call the EXEC function.  This function works in
    V33 and up (1.2) Amiga system.

    The C code interface is _LibFreePooled() and takes its arguments
    from the stack just like the C code interface for FreePooled()
    in amiga.lib.  The assembly code interface is with the symbol
    _AsmFreePooled: and takes the parameters in registers with the
    additional parameter of ExecBase being in a6 which can be used
    from SAS/C 6 by a prototype of:

    void __asm AsmFreePooled(register __a0 void *,
                             register __a1 void *,
                             register __d0 ULONG,
                             register __a6 struct ExecBase *);

    Deallocates memory allocated by LibAllocPooled().  The size of the
    allocation *MUST* match the size given to LibAllocPooled().
    The reason the pool functions do not track individual allocation
    sizes is because many of the uses of pools have small allocation
    sizes and the tracking of the size would be a large overhead.

    Only memory allocated by LibAllocPooled() may be freed with this
    function!

    Doing a LibDeletePool() on the pool will free all of the puddles
    and thus all of the allocations done with LibAllocPooled() in that
    pool.  (No need to LibFreePooled() each allocation)

    INPUTS
    memory - pointer to memory allocated by AllocPooled.
    poolHeader - a specific private pool header.

    NOTES
    The pool function do not protect an individual pool from
    multiple accesses.  The reason is that in most cases the pools
    will be used by a single task.  If your pool is going to
    be used by more than one task you must Semaphore protect
    the pool from having more than one task trying to allocate
    within the same pool at the same time.  Warning:  Forbid()
    protection *will not work* in the future.  *Do NOT* assume
    that we will be able to make it work in the future.  LibFreePooled()
    may well break a Forbid() and as such can only be protected
    by a semaphore.

    To track sizes yourself, the following code can be used:
    *Assumes a6=ExecBase*

    ;
    ; Function to do AllocVecPooled(Pool,memSize)
    ;
    AllocVecPooled:	addq.l	#4,d0		; Get space for tracking
            move.l	d0,-(sp)	; Save the size
            jsr	LibAllocPooled	; Call pool...
            move.l	(sp)+,d1	; Get size back...
            tst.l	d0		; Check for error
            beq.s	avp_fail	; If NULL, failed!
            move.l	d0,a0		; Get pointer...
            move.l	d1,(a0)+	; Store size
            move.l	a0,d0		; Get result
    avp_fail:	rts			; return

    ;
    ; Function to do LibFreeVecPooled(pool,memory)
    ;
    FreeVecPooled:	move.l	-(a1),d0	; Get size / ajust pointer
            jmp	LibFreePooled

    SEE ALSO
    AllocPooled(), CreatePool(), DeletePool(),
    LibAllocPooled(), LibCreatePool(), LibDeletePool()


amiga.lib/SetSuperAttrs

   NAME
    SetSuperAttrs -- Invoke OM_SET method on superclass with varargs.

   SYNOPSIS
    result = SetSuperAttrs( cl, obj, tag, ... )

    ULONG SetSuperAttrs( struct IClass *, Object *, ULONG, ... );

   FUNCTION
    Boopsi support function which invokes the OM_SET method on the
    superclass of the supplied class for the supplied object.  Allows
    the ops_AttrList to be supplied on the stack (i.e. in a varargs
    way).  The equivalent non-varargs function would simply be

        DoSuperMethod( cl, obj, OM_SET, taglist, NULL );

   INPUTS
    cl - pointer to boopsi class whose superclass is to
        receive the OM_SET message
    obj - pointer to boopsi object
    tag - list of tag-attribute pairs, ending in TAG_DONE

   RESULT
    result - class and message-specific result.

   NOTES
    This function first appears in the V37 release of amiga.lib.
    While it intrinsically does not require any particular release
    of the system software to operate, it is designed to work with
    the boopsi subsystem of Intuition, which was only introduced
    in V36.

   SEE ALSO
    CoerceMethodA(), DoMethodA(), DoSuperMethodA(), <intuition/classusr.h>
    ROM Kernel Manual boopsi section


amiga.lib/TimeDelay

   NAME
    TimeDelay -- Return after a period of time has elapsed.

   SYNOPSIS
    Error = TimeDelay( Unit, Seconds, MicroSeconds )
    D0                 D0    D1       D2

    LONG TimeDelay( LONG, ULONG, ULONG );

   FUNCTION
    Waits for the period of time specified before returning to the
    the caller.

   INPUTS
    Unit -- timer.device unit to open for this command.
    Seconds -- The seconds field of a timerequest is filled with
        this value. Check the documentation for what a particular
        timer.device unit expects there.
    MicroSeconds -- The microseconds field of a timerequest is
        filled with this value. Check the documentation for what
        a particular timer.device units expects there.

   RESULTS
    Error -- will be zero if all went well; otherwise, non-zero.

   NOTES
    Two likely reasons for failures are invalid unit numbers or
    no more free signal bits for this task.

    While this function first appears in V37 amiga.lib, it works
    on Kickstart V33 and higher.

   SEE ALSO
    timer.device/TR_ADDREQUEST,
    timer.device/TR_WAITUNTIL,
    timer.device/WaitUnitl()

   BUGS


animation_dtc.doc

     animation.datatype()


animation.datatype/animation.datatype

    NAME
        animation.datatype -- root data type for animations.

    FUNCTION
        The animation.datatype is the super-class for any animation related
        classes.

        This class is responsible for creating the controls, scaling,
        remapping and synchronization.

    METHODS
        OM_NEW -- Create a new animation object.

        OM_GET -- Obtain the value of an attribute.

        OM_SET -- Set the values of multiple attributes.

        OM_UPDATE -- Update the values of multiple attributes.

        OM_DISPOSE -- Dispose of a animation object.

        GM_LAYOUT -- Layout the object and notify the application of the
            title and size.

        GM_HITTEST -- Determine if the object has been hit with the
            mouse.

        GM_GOACTIVE -- Tell the object to go active.  On SELECTDOWN, the
            animation will start playing.

        GM_HANDLEINPUT -- Handle input.  Currently input (other than
            SELECTDOWN) doesn't affect the animation.

        GM_RENDER -- Cause the current frame to render.

        DTM_FRAMEBOX -- Obtain the display environment that the animation
            requires.

        DTM_TRIGGER -- Cause an event to occur.  Currently the only
            trigger event is STM_PLAY, which will cause the animation to
            start playing.

        DTM_COPY -- Copy the current frame to the clipboard as an IFF ILBM.

        DTM_WRITE -- Write the current frame to a file as an IFF ILBM.

        DTM_PRINT -- Print the current frame.

        ADTM_LOADFRAME -- Load a frame of the animation.

        ADTM_UNLOADFRAME -- Deallocate any memory allocated by
            ADTM_LOADFRAME.

        ADTM_START -- Start the animation.  This MUST be passed to the
            super-class AFTER the sub-class has started.

        ADTM_PAUSE -- Pause the animation.  This MUST be passed to the
            super-class BEFORE the sub-class pauses.

        ADTM_STOP -- Stop the animation.  This MUST be passed to the
            super-class BEFORE the sub-class stops.

        ADTM_LOCATE -- Used to locate a frame of the animation.

        ADTM_LOADNEWFORMATFRAME -- Load a new format frame of the animation,
            for more information, see <datatypes/animationclass.h>. (V44)

        ADTM_UNLOADNEWFORMATFRAME -- Deallocate any memory allocated by
            ADTM_LOADNEWFORMATFRAME. (V44)

    TAGS
        DTA_ControlPanel (BOOL) -- Determine whether the control
            panel is shown.  Defaults to TRUE.

            Applicability is (I).

        DTA_Immediate (BOOL) -- Indicate whether the animation
            should immediately begin playing.  Defaults to
            FALSE.

            Applicability is (I).

        DTA_Repeat (BOOL) -- Indicate whether the animation
            should loop. (V44)

            Default for this tag is FALSE. Applicability is (IS).

        ADTA_Remap (BOOL) -- Indicate whether the animation should be
            remapped or not.

            Applicability is (I).

        ADTA_ModeID (ULONG) -- Set and get the graphic mode id of the
            picture.

            Applicability is (ISG).

        ADTA_Width (ULONG) -- Width of a frame in pixels.

            Applicability is (IG).

        ADTA_Height (ULONG) -- Height of a frame in pixels.

            Applicability is (IG).

        ADTA_Depth (ULONG) -- Depth of the frame.

            Applicability is (IG).

        ADTA_Frames (ULONG) -- Number of frames in animation.

            Applicability is (ISG).

        ADTA_KeyFrame (struct BitMap *) -- Pointer to the key
            frame.

            Applicability is (ISG).

        ADTA_FramesPerSecond (ULONG) -- Number of frames per
            second to play.

        ADTA_NumColors (WORD) -- Number of colors used by the frame.

            Applicability is (ISG).

        ADTA_ColorRegisters (struct ColorRegister *) -- Color table; its
            contents should match the colours in the ADTA_CRegs table.

            Applicability is (G).

        ADTA_CRegs (ULONG *) -- Color table to use with SetRGB32CM().

            Applicability is (G).

        ADTA_GRegs (ULONG *) -- Color table; this table is initialized
            during the layout process and will contain the colours the
            picture will use after remapping. If no remapping takes
            place, these colours will match those in the ADTA_CRegs table.

        ADTA_ColorTable (UBYTE *) -- Shared pen table; this table is
            initialized during the layout process while the frames
            are being remapped.

            Applicability is (G).

        ADTA_ColorTable2 (UBYTE *) -- Shared pen table; in most places
            this table will be identical to the ADTA_ColorTable table.
            Some of the colours in this table might match the original
            colour palette a little better than the colours picked for
            the other table. The animation.datatype uses the two tables
            during remapping, alternating for each pixel.

            Applicability is (G).

        ADTA_Allocated (ULONG) --  OBSOLETE; DO NOT USE.

            Applicability is (G).

        ADTA_NumAlloc (UWORD) -- Number of colors allocated by the frame.
            In this context `allocated' refers to colours allocated via
            graphics.library/ObtainBestPenA.

            Applicability is (G).

        ADTA_BitMapHeader (struct BitMapHeader *) -- Set and get the
            base information for the animation.  BitMapHeader is defined in
            <datatypes/pictureclass.h>

            Applicability is (G).

        ADTA_Sample (BYTE *) -- Pointer to sample data.

            NOTE: this tag was only (IS) in V40; this has been fixed
                  in V44.

            Applicability is (ISG).

        ADTA_SampleLength (ULONG) -- Length of sample data.

            Applicability is (ISG).

        ADTA_Period (ULONG) -- Period to play back sample at.

            Applicability is (ISG).

        ADTA_Volume (ULONG) -- Volume to play back sample at (0..64).

            Applicability is (ISG).

        OBP_Precision (ULONG) -- Precision to use when obtaining colors.
            See the PRECISION_[..] defines in <graphics/view.h>.

            Applicability is (I). Defaults to PRECISION_IMAGE. (V44)

        ADTA_LeftSample (BYTE *) -- Pointer to left channel sample
            data. (V44)

            Applicability is (ISG).

        ADTA_RightSample (BYTE *) -- Pointer to right channel sample
            data. (V44)

            Applicability is (ISG).

        ADTA_SamplesPerSec (ULONG) -- Number of samples per second to play;
            if this is > 0, it takes precendence over ADTA_Period.

            Applicability is (ISG).

        ADTA_PreloadFrameCount (ULONG) -- Number of frames to preload. (V44)
            Frames are preloaded when starting animation playback. The
            loader will attempt to keep at least this number of frames
            available for the display process. Note that when changing this
            attribute the change does not take effect immediately.

            Default for this tag is 10. Applicability is (ISG).

    NOTES
        The ADTM_LOADNEWFORMATFRAME and ADTM_UNLOADNEWFORMATFRAME methods
        operate on struct adtNewFormatFrame format messages. The
        adtNewFormatFrame message is an extension of the adtFrame message
        with additional fields, such as required for stereo sound playback.
        By default, animation.datatype will load and unload frames allocated
        by its subclasses using the compatible ADTM_LOADFRAME and
        ADTM_UNLOADFRAME methods. If your subclass needs to use the extended
        adtNewFormatFrame format messages, it must say so by providing a
        list of supported methods for animation.datatype to query through
        the OM_GET/DTA_Methods tag. If both ADTM_LOADNEWFORMATFRAME and
        ADTM_UNLOADNEWFORMATFRAME are among the methods supported by your
        subclass, you will receive adtNewFormatFrame format messages instead
        of the compatible adtFrame messages.

        Please note that applications such as MultiView will query the
        methods supported by your class. Make sure that if you choose to
        implement support for the OM_GET/DTA_Methods tag the methods you
        return should also include the methods supported by your superclass.
        Otherwise, the user will be unable to use functions such as "Copy"
        or "Print".

        Since the adtNewFormatFrame message format may be enhanced in future
        releases of animation.datatype, your subclass may access only
        structure members that are known to exist in the message. To find
        out which members are available, check the
        adtNewFormatFrame->alf_Size member; it contains the total length of
        the data structure (in bytes). Remember which message length you
        require, then act accordingly. Please keep in mind that the
        structure member adtNewFormatFrame->alf_Size does not exist in the
        compatible adtFrame message data structure.


arexx_cl.doc

     --datasheet--
     AM_EXECUTE
     AM_HANDLEINPUT


arexx_cl/--datasheet--

    NAME
        arexx_cl -- ARexx interface class.

    SUPERCLASS
        rootclass

    DESCRIPTION
        This class provides you with a very easy way to implement an ARexx
        interface.  It will setup a unique ARexx port, start ARexx macros,
        parse commands and dispatch command handler functions.

        All ARexx class methods and the callbacks you provide it are run in
        the context of the task you call ARexx class from. Thus if your
        application is a process, DOS is safe to use.

    METHODS
        OM_NEW -- Passed to superclass first.  Sets up the port.

        OM_GET -- Returns requested attributes.  Passed onto superclass.

        OM_DISPOSE -- Closes the port and frees all resources.  Passed onto
            superclass

        AM_EXECUTE -- Executes an ARexx command or macro.

        AM_HANDLEINPUT -- Handles ARexx messages.

    ATTRIBUTES
        AREXX_HostName (STRPTR)
            The name of the host.  The ARexx portname is derived from this.
            In pretty much all cases, this should the same as your app's
            basename.  You should refrain from using names like "MYPROG_RX"
            or others with unnecessary suffixes.

            To create the portname, the hostname will be uppercased, and,
            unless AREXX_NoSlot is specified, a slot number will be
            appended.

            Applicability is (OM_NEW, OM_GET)

        AREXX_NoSlot (BOOL)
            Specifies that no slot number should be appended to the port
            name when it is being created.  This greatly increases the
            chances that your requested portname is in use, so your code
            must be sure to handle this situation.

            Defaults to FALSE.

            Applicability is (OM_NEW)

        AREXX_DefExtension (STRPTR)
            Default filename extension for macros started by your app.  Do
            not include the ".", just the extension text.   In pretty much
            all cases, this should be the same as your app's basename.  You
            should refrain from using extensions like "myrx".

            Defaults to "rexx".

            Applicability is (OM_NEW)

        AREXX_Commands (struct ARexxCmd *)
            The table of the commands supported by your ARexx interface.
            This will be a pointer to an array of struct ARexxCmd.  If this
            array is not passed then your host will not be able to process
            any ARexx commands.

            The following fields must be setup initially by the app before
            OM_NEW:

                ac_Name (STRPTR)
                The name of the command.  By convention this is usually all
                uppercase, though a case-insensitive comparisons will be
                done.

                ac_ID (WORD)
                A unique number identifying this command.

                ac_Func (*()(struct ARexxCmd *, struct RexxMsg *))
                A pointer to the function that will be called when this
                command is received by your programme.  The function will
                get past a pointer to its ARexxCmd entry and the RexxMsg
                structure received for the command.  You may use this
                for setting ARexx variables, but please note that is may
                be NULL

                ac_ArgTemplate (STRPTR)
                DOS ReadArgs()-style argument template for this command.

                ac_Flags (ULONG)
                Command flags.  Currently unused, but in order to remain
                compatable, you must ensure that this is NULL.

            These fields are ignored in OM_NEW and are set by the class
            when calling the ac_Func command callback.

                ac_ArgList (ULONG *)
                Result of ReadArgs() using the arguments received with the
                command and ac_ArgTemplate as the template.

                ac_RC (LONG)
                Primary result, the RC variable.  Also causes the RC2
                variable to return, and will cause RESULT to NOT be set.

                ac_RC2 (LONG)
                Secundary result, the RC2 variable.  This will not be set
                unless RC is non-zero.

                ac_Result (STRPTR)
                RESULT variable, this should be a string.  If you want to
                return a number, you will have to convert it to a string
                first.  This string will not be set if RC is non-zero.

            The array must be terminated with a NULL ac_Name field.

            Applicability is (OM_NEW)

        AREXX_ErrorCode (ULONG *)
            A pointer to storage space for OM_NEW to store an error code
            when it fails trying to create the object.  Possible values
            are:

            RXERR_NO_COMMAND_LIST - No command list was provided.
            RXERR_NO_PORT_NAME - No host base name was provided.
            RXERR_PORT_ALREADY_EXISTS - The  class  was unable to create a
                unique name of the base name you provided.
            RXERR_OUT_OF_MEMORY - Not enough free memory.

            No error code will be returned if you provide a NULL pointer.

            Defaults NULL.

            Applicability is (OM_NEW)

        AREXX_SigMask (ULONG)
            The signal mask for the object's message port.  This is the
            signal you will want to Wait() on so you know when there is
            activity at the ARexx port.

            Applicability is (OM_GET)

        AREXX_ReplyHook (struct Hook *)
            This is a function hook that will get called whenever your host
            replies to an ARexx message.  This generally happens after your
            host has sent a message (eg. via AM_EXECUTE) and the task
            receiving the message has completed its processing with the
            message.  This is most useful for checking return codes from
            commands sent via AM_EXECUTE.

            The object parameter in the hook function will point to the
            Object * that is yur host, and the message parameter will be
            the ARexx message that is being replied to (from which you
            could extract result codes).

            Defaults to NULL.

            Applicability is (OM_NEW, OM_GET)

    BUGS
        AREXX_HostName MUST be all uppercase in V40 otherwise the checks for
        an already existing port won't work right.


arexx_cl/AM_EXECUTE

    NAME
        AM_EXECUTE -- Execute an ARexx macro.

    FUNCTION
        This method allows you to execute a macro in another host.  The
        default host is the ARexx server.  This is how you would execute
        disk-based ARexx macros, by passing the name of the file as the
        command string to the ARexx server.

        This method uses the following custom message structure:

          struct apExecute
          {
              ULONG MethodID;
              STRPTR ape_CommandString;
              STRPTR ape_PortName;
              LONG *ape_RC;
              LONG *ape_RC2;
              STRPTR *ape_Result;
              BPTR ape_IO;
          };

        ape_CommandString (STRPTR)
            This must point to the command including arguments to execute.
            If the command is found in the host command list it will be
            executed.  Unknown commands will be shipped off to the ARexx
            server.

        ape_RC, ape_RC2, ape_Result (LONG *, LONG *, STRPTR *)
            After the command executed you will find the results in here if
            the command was one in your host, or if there was a problem
            sending the command to the specified host.  You will NOT get the
            result of the command if it is sent to another host, since the
            command is sent asychronously.  Use AREXX_ReplyHook for this.

        ape_IO (BPTR)
            If you execute a script using this method you can pass a pointer
            to the IO channel ARexx must  use here.  This IO channel will be
            closed automatically for you after the command executed.

    RESULT
        As errors are reported in acme_RC and acme_RC2 this method has no
        specific return code.


arexx_cl/AM_HANDLEINPUT

    NAME
        AM_HANDLEINPUT

    FUNCTION
        This method will handle all incoming and outgoing message traffic
        from your host.  When you are signalled you simply call this method
        and everything is done for you.

    RESULT
        No return code is specified for this method.


asl.doc

     AbortAslRequest()
     ActivateAslRequest()
     AllocAslRequest()
     AllocFileRequest()
     AslRequest()
     FreeAslRequest()
     FreeFileRequest()
     RequestFile()


asl.library/AbortAslRequest

   NAME
    AbortAslRequest -- attempt to abort an asl requester. (V44)

   SYNOPSIS
    AbortAslRequest(requester);
                       A0

    VOID AbortAslRequest(APTR requester);

   FUNCTION
    The different types of asl requesters are modal (as of V44). Yet at
    times it may be necessary to abort a modal requester from a different
    task context. AbortAslRequest() will attempt to tell the modal asl
    requester provided to shut down and perform as if the user had clicked
    on the requester's window close gadget. This may take some time to
    complete; be prepared to handle this.

   INPUTS
    requester - requester obtained from AllocAslRequest(), or NULL in
            which case this function does nothing.

   SEE ALSO
    AslRequest()


asl.library/ActivateAslRequest

   NAME
    ActivateAslRequest -- attempt to activate an asl requester. (V44)

   SYNOPSIS
    ActivateAslRequest(requester);
                          A0

    VOID ActivateAslRequest(APTR requester);

   FUNCTION
    The different types of asl requesters are modal (as of V44). Yet at
    times it may be necessary to activate a modal requester from a different
    task context.

   INPUTS
    requester - requester obtained from AllocAslRequest(), or NULL in
            which case this function does nothing.

   SEE ALSO
    AslRequest()


asl.library/AllocAslRequest

   NAME
    AllocAslRequest -- allocate an ASL requester. (V36)
    AllocAslRequestTags -- varargs stub for AllocAslRequest(). (V36)

   SYNOPSIS
    requester = AllocAslRequest(reqType,tagList);
    D0                          D0      A0

    APTR AllocAslRequest(ULONG,struct TagItem *);

    requester = AllocAslRequestTags(reqType,firstTag, ...);

    APTR AllocAslRequestTags(ULONG,Tag,...);

   FUNCTION
    Allocates an ASL requester data structure of the specified type.

   INPUTS
    type - type of requester to allocate. Currently defined types
           are ASL_FileRequest, ASL_FontRequest and ASL_ScreenModeRequest.
           ASL_ScreenModeRequest is available starting with asl.library
           V38 only.
    tags - pointer to an optional tag list specifying how to initialize the
           data structure returned by this function. See the
           documentation for AslRequest() for an explanation of
           how to use the currently defined tags.

   RESULT
    requester - an initialized requester data structure, or NULL on
                failure. The data structure returned corresponds to the
            requested type;
            ASL_FileRequest       -> (struct FileRequester *)
            ASL_FontRequest       -> (struct FontRequester *)
            ASL_ScreenModeRequest -> (struct ScreenModeRequester *)

   WARNING
    All ASL requester data structures are READ-ONLY and can only be
    modified by using tags!

    You must not specify requester options by using both pre-V38
    tags like ASLFR_Flags1 and V38 tags like ASLFR_DoSaveMode as
    this can lead to unexpected results.

    Take care when attaching an ASL requester to a simple refresh
    window or a window that already shares its IDCMP with other
    windows. In such cases you must ask for the ASL requester to
    allocate a private IDCMP (with the ASLFR_PrivateIDCMP,
    ASLFO_PrivateIDCMP and ASLSM_PrivateIDCMP tags) or your window
    will lose IDCMP_REFRESHWINDOW events and other messages.

   BUGS
    Under V38 and V39, the filtering functions for the file requester
    were only asked to filter drawer selections if the ASLFR_FilterDrawers
    tag was set to TRUE. The compatible behavior, reestablished in V40,
    is to always pass drawers for filtering.

   NOTES
    As of V38-V40 the ASL requester uses gadtools.library routines to
    create and maintain its user interface. Every IntuiMessage the library
    passes through the functions specified with ASLSM_IntuiMsgFunc and
    ASLSM_HookFunc will have been filtered through the
    gadtools.library/GT_GetIMsg() routine.

   SEE ALSO
    AslRequest(), FreeAslRequest()


asl.library/AllocFileRequest

   NAME
    AllocFileRequest -- allocates an ASL FileRequester structure. (V36)

   SYNOPSIS
    requester = AllocFileRequest()
    D0

    struct FileRequester *AllocFileRequest(VOID);

   NOTES
    This function is obsolete, please use AllocAslRequest() instead.

   SEE ALSO
    AllocAslRequest()


asl.library/AslRequest

   NAME
    AslRequest -- get input from user using an ASL requester. (V36)
    AslRequestTags -- varargs stub for AslRequest(). (V36)

   SYNOPSIS
    result = AslRequest(requester,tags);
    D0                  A0        A1

    BOOL AslRequest(APTR,struct TagItem *);

    result = AslRequestTags(requester,firstTag,...);

    BOOL AslRequestTags(APTR,Tag,...);

   FUNCTION
    Prompts the user for input, based on the specific type of
    requester and modifying tags. The actions and results
    are specific to the type of requester, but in general the action is
    to open a requesting window prompting the user for a specific input.
    If the user cancels or the system aborts the request, FALSE
    is returned, otherwise the requester's data structure reflects the
    user input.

    Note that tag values stay in effect for each use of the
    requester until they are cleared or modified by passing the
    same tag with a new value.

   INPUTS
    requester - requester structure allocated with AllocAslRequest(). If
            this parameter is NULL, this function will always return
            FALSE with a dos.library/IoErr() result of
            ERROR_NO_FREE_STORE.
    tags - pointer to an optional tag list which may be used to
           control features of the requester.

   TAGS
    Tags for use with the file requester:

    ASLFR_Window (struct Window *) - Parent window of requester. If no
            ASLFR_Screen tag is specified, the window structure
            is used to determine on which screen to open the
            requesting window. (V36)

    ASLFR_PubScreenName (STRPTR) - Name of a public screen to open on.
            This overrides the screen used by ASLFR_Window. (V38)

    ASLFR_Screen (struct Screen *) - Screen on which to open the requester.
            This overrides the screen used by ASLFR_Window or by
            ASLFR_PubScreenName. (V38)

    ASLFR_PrivateIDCMP (BOOL) - When set to TRUE, this tells ASL to
            allocate a new IDCMP port for the requesting window.
            If not specified or set to FALSE, and if ASLFR_Window
            is provided, the requesting window will share
            ASLFR_Window's IDCMP port. (V38)

    ASLFR_IntuiMsgFunc (struct Hook *) - A function to call whenever an
            unknown Intuition message arrives at the message port
            being used by the requesting window. The function
            receives the following parameters:
                A0 - (struct Hook *)
                A1 - (struct IntuiMessage *)
                A2 - (struct FileRequester *)
            (V38)

    ASLFR_SleepWindow (BOOL) - When set to TRUE, this tag will cause the
            window specified by ASLFR_Window to be "put to
            sleep". That is, a busy pointer will be displayed in
            the parent window, and no gadget or menu activity will
            be allowed. This is done by opening an invisible
            Intuition Requester in the parent window. (V38)

    ASLFR_UserData (APTR) - A 32-bit value that is simply copied in the
            fr_UserData field of the requester structure. (V38)

    ASLFR_TextAttr (struct TextAttr *) - Font to be used for the requesting
            window's gadgets and menus. If this tag is not provided
            or its value is NULL, the default font of the screen
            on which the requesting window opens will be used.
            This font must already be in memory as ASL calls
            OpenFont() and not OpenDiskFont(). As of V38, the font
            used in the file requester's file list must be
            monospaced. If the font provided with this tag is
            not monospaced, then the file list will use the current
            system default font as chosen in preferences. (V38)

    ASLFR_Locale (struct Locale *) - Locale to use for the requesting
            window. This determines the language used for the
            requester's gadgets and menus. If this tag is not
            provided or its value is NULL, the system's current
            default locale will be used. As of V38, items such as
            the date format always uses the system default locale.
            (V38)

    ASLFR_TitleText (STRPTR) - Title to use for the requesting window.
            Default is no title. (V36)

    ASLFR_PositiveText (STRPTR) - Label of the positive gadget in the
            requester. English default is "OK". Prior to V38, this
            string could not be longer than 6 characters. (V36)

    ASLFR_NegativeText (STRPTR) - Label of the negative gadget in the
            requester. English default is "Cancel". Prior to V38,
            this string could not be longer than 6 characters.
            (V36)

    ASLFR_InitialLeftEdge (WORD) - Suggested left edge of requesting
            window. (V36)

    ASLFR_InitialTopEdge (WORD) - Suggested top edge of requesting
            window. (V36)

    ASLFR_InitialWidth (WORD) - Suggested width of requesting window. (V36)

    ASLFR_InitialHeight (WORD) - Suggested height of requesting window.
            (V36)

    ASLFR_InitialFile (STRPTR) - Initial contents of the file requester's
            File text gadget. Default is empty. (V36)

    ASLFR_InitialDrawer (STRPTR) - Initial contents of the file
            requester's Drawer text gadget. Default is empty. (V36)

    ASLFR_InitialPattern (STRPTR) - Initial contents of the file
            requester's Pattern text gadget. Default is #?. (V36)

    ASLFR_InitialShowVolumes (BOOL) - When opening the file requester,
            read the list of active volumes, do not read the contents
            of the specified drawer. (V44)

    ASLFR_Flags1 (ULONG) - Bulk initialization of many of the requester's
            options. See <libraries/asl.h> for the possible
            flag values. Default is 0. (V36)

    ASLFR_Flags2 (ULONG) - Bulk initialization of many of the requester's
            options. See <libraries/asl.h> for the possible
            flag values. Default is 0. (V36)

    ASLFR_DoSaveMode (BOOL) - Set this tag to TRUE when the file requester
            is being used for saving. Default is FALSE. (V38)

    ASLFR_DoMultiSelect (BOOL) - Set this tag to TRUE to let the user
            select multiple files at once. This tag excludes
            save mode. Default is FALSE. (V38)

    ASLFR_DoPatterns (BOOL) - Set this tag to TRUE to cause a pattern
            gadget to be displayed. Default is FALSE. (V38)

    ASLFR_DrawersOnly (BOOL) - Set this tag to TRUE to cause the requester
            to only display drawers, and have no File gadget. This
            is useful to let the user choose a destination
            directory. Default is FALSE. (V38)

    ASLFR_FilterFunc (struct Hook *) - A function to call for each file
            encountered. If the function returns TRUE, the file is
            included in the file list, otherwise it is rejected
            and not displayed. The function receives the following
            parameters:
                A0 - (struct Hook *)
                A1 - (struct AnchorPath *)
                A2 - (struct FileRequester *)
            (V38)

    ASLFR_RejectIcons (BOOL) - Set this tag to TRUE to cause the requester
            not to display Workbench icons. This flag should
            normally be set. Default is FALSE. (V38)

    ASLFR_RejectPattern (UBYTE *) - Specifies an AmigaDOS pattern that is
            used to reject files. That is, any files with names
            matching this pattern are not included in the file
            list. Note that the pattern must have been
            parsed by dos.library/ParsePatternNoCase(). Default
            is ~(#?) which matches nothing. (V38)

    ASLFR_AcceptPattern (UBYTE *) - Specifies an AmigaDOS pattern that is
            used to accept files. That is, only files with names
            matching this pattern are included in the file list.
            Note that the pattern must have been parsed by
            dos.library/ParsePatternNoCase(). Default is #? which
            matches everything. (V38)

    ASLFR_FilterDrawers (BOOL) - Set this tag to TRUE if you want the
            ASLFR_RejectPattern, ASLFR_AcceptPattern, and the
            Pattern text gadget to also apply to drawer names.
            Normally, drawers are always displayed. Default is
            FALSE. (V38)

    ASLFR_HookFunc (APTR) - A function that is called if the
            FRF_FILTERFUNC or FRF_INTUIFUNC flags are specified in
            the ASLFR_Flags1 tag. The function will be called like
            so, with the arguments on the stack using the standard
            C pushing order:

                ULONG function(ULONG mask, APTR object,
                           struct FileRequester *fr)

            The Mask value is a copy of the specific ASLFR_Flags1
            value the callback is for, either FRF_FILTERFUNC or
            FRF_INTUIFUNC; object is a pointer to a data object
            (a (struct IntuiMessage *) for FRF_INTUIFUNC, and a
            (struct AnchorPath *) for FRF_FILTERFUNC).

            For FRF_FILTERFUNC, the function should return 0 if the
            file should be added to the list, non-zero if it
            shouldn't. For FRF_INTUIFUNC, the function should
            return the original (struct IntuiMessage *) it was
            passed.

    ASLFR_SetSortBy (ULONG) -- Criteria for sorting the file list.
            this must be one of ASLFRSORTBY_Name (sort by name),
            ASLFRSORTBY_Date (sort by date) or ASLFRSORTBY_Size
            (sort by size).
            Default is ASLFRSORTBY_Name. (V44)

    ASLFR_GetSortBy (ULONG *) -- Before leaving AslRequest(), the
            file requester will store its current sort criteria
            (ASLFRSORTBY_Name, ASLFRSORTBY_Date or ASLFRSORTBY_Size)
            in the ULONG pointed to by this tag.
            Default is NULL, i.e. no data is stored. (V44)

    ASLFR_SetSortDrawers (ULONG) -- Determines where drawers
            are placed in the sorted list; this must be one of
            ASLFRSORTDRAWERS_First (drawers appear before all
            other files), ASLFRSORTDRAWERS_Mix (drawers are sorted
            along with the the other files) or ASLFRSORTDRAWERS_Last
            (drawers appear after all other files).
            Default is ASLFRSORTDRAWERS_First. (V44)

    ASLFR_GetSortDrawers (ULONG *) -- Before leaving AslRequest(),
            the file requester will store its current drawer list
            placement (ASLFRSORTDRAWERS_First, ASLFRSORTDRAWERS_Mix
            or ASLFRSORTDRAWERS_Last) in the ULONG pointed to by
            this tag.
            Default is NULL, i.e. no data is stored. (V44)

    ASLFR_SetSortOrder (ULONG) -- Selects the order in which
            the list is sorted; this must be one of ASLFRSORTORDER_Ascend
            (smallest/oldest files first, largest/newest files last)
            or ASLFRSORTORDER_Descend (largest/newest files first,
            smallest/oldest files last).
            Default is ASLFRSORTORDER_Ascend. (V44)

    ASLFR_GetSortOrder (ULONG *) -- Before leaving AslRequest(),
            the file requester will store its current sort order
            (ASLFRSORTORDER_Ascend, ASLFRSORTORDER_Descend) in the
            ULONG pointed to by this tag.
            Default is NULL, i.e. no data is stored. (V44)

    ASLFR_PopToFront (BOOL) -- When set to TRUE, this tells ASL to
            bring the screen to the front the requester has opened on.
            The position of the screen will be adjusted, too, to bring
            the area into view the window has opened in. The screen
            brought to the front will be pushed into the background
            again when the requester window closes.
            Default is TRUE. (V44)

    Tags used for the font requester:

    ASLFO_Window (struct Window *) - Parent window of requester. If no
            ASLFO_Screen tag is specified, the window structure
            is used to determine on which screen to open the
            requesting window. (V36)

    ASLFO_PubScreenName (STRPTR) - Name of a public screen to open on.
            This overrides the screen used by ASLFO_Window. (V38)

    ASLFO_Screen (struct Screen *) - Screen on which to open the requester.
            This overrides the screen used by ASLFO_Window or by
            ASLFO_PubScreenName. (V38)

    ASLFO_PrivateIDCMP (BOOL) - When set to TRUE, this tells ASL to
            allocate a new IDCMP port for the requesting window.
            If not specified or set to FALSE, and if ASLFO_Window
            is provided, the requesting window will share
            ASLFO_Window's IDCMP port. (V38)

    ASLFO_IntuiMsgFunc (struct Hook *) - A function to call whenever an
            unknown Intuition message arrives at the message port
            being used by the requesting window. The function
            receives the following parameters:
                A0 - (struct Hook *)
                A1 - (struct IntuiMessage *)
                A2 - (struct FontRequester *)
            (V38)

    ASLFO_SleepWindow (BOOL) - When set to TRUE, this tag will cause the
            window specified by ASLFO_Window to be "put to
            sleep". That is, a busy pointer will be displayed in
            the parent window, and no gadget or menu activity will
            be allowed. This is done by opening an invisible
            Intuition Requester in the parent window. (V38)

    ASLFO_UserData (APTR) - A 32-bit value that is simply copied in the
            fo_UserData field of the requester structure. (V38)

    ASLFO_TextAttr (struct TextAttr *) - Font to be used for the requesting
            window's gadgets and menus. If this tag is not provided
            or its value is NULL, the default font of the screen
            on which the requesting window opens will be used.
            This font must already be in memory as ASL calls
            OpenFont() and not OpenDiskFont().
            (V38)

    ASLFO_Locale (struct Locale *) - Locale to use for the requesting
            window. This determines the language used for the
            requester's gadgets and menus. If this tag is not
            provided or its value is NULL, the system's current
            default locale will be used. (V38)

    ASLFO_TitleText (STRPTR) - Title to use for the requesting window.
            Default is no title. (V36)

    ASLFO_PositiveText (STRPTR) - Label of the positive gadget in the
            requester. English default is "OK". Prior to V38, this
            string could not be longer than 6 characters. (V36)

    ASLFO_NegativeText (STRPTR) - Label of the negative gadget in the
            requester. English default is "Cancel". Prior to V38,
            this string could not be longer than 6 characters.
            (V36)

    ASLFO_InitialLeftEdge (WORD) - Suggested left edge of requesting
            window. (V36)

    ASLFO_InitialTopEdge (WORD) - Suggested top edge of requesting
            window. (V36)

    ASLFO_InitialWidth (WORD) - Suggested width of requesting window. (V38)

    ASLFO_InitialHeight (WORD) - Suggested height of requesting window.
            (V38)

    ASLFO_InitialName (STRPTR) - Initial contents of the font requester's
            Name text gadget. Default is none. (V36)

    ASLFO_InitialSize (UWORD) - Initial contents of the font requester's
            Size numeric gadget (fo_Attr.ta_YSize). Default is 8.
            (V36)

    ASLFO_InitialStyle (UBYTE) - Initial setting of the font requester's
            Style gadget (fo_Attr.ta_Style). Default is FS_NORMAL.
            (V36)

    ASLFO_InitialFlags (UBYTE) - Initial setting of the font requester's
            fo_Flags field (fo_Attr.ta_Flags). Default is
            FPF_ROMFONT. (V36)

    ASLFO_InitialFrontPen (UBYTE) - Initial setting of the font requester's
            Front Color gadget (fo_FrontPen). This value also
            determines the color used to render the text in the
            sample font area. Default is 1. (V36)

    ASLFO_InitialBackPen (UBYTE) - Initial setting of the font requester's
            Back Color gadget (fo_BackPen). This value also
            determines the color used to render the background of
            the sample font area. Default is 0. (V36)

    ASLFO_InitialDrawMode (UBYTE) - Initial setting of the font
            requester's Mode gadget (fo_DrawMode). Default is
            JAM1. (V38)

    ASLFO_Flags (ULONG) - Bulk initialization of many of the requester's
            options. See <libraries/asl.h> for the possible
            flag values. Default is 0. (V36)

    ASLFO_DoFrontPen (BOOL) - Set this tag to TRUE to cause the requester
            to display the Front Color selection gadget. Default is
            FALSE. (V38)

    ASLFO_DoBackPen (BOOL) - Set this tag to TRUE to cause the requester
            to display the Back Color selection gadget. Default
            is FALSE. (V38)

    ASLFO_DoStyle (BOOL) - Set this tag to TRUE to cause the requester
            to display the Style checkboxes. Default is FALSE.
            (V38)

    ASLFO_DoDrawMode (BOOL) - Set this tag to TRUE to cause the requester
            to display the Mode cycle gadget. Default is FALSE.
            (V38)

    ASLFO_FixedWidthOnly (BOOL) - Set this tag to TRUE to cause the
            requester to only display fixed-width fonts. Default
            is FALSE. (V38)

    ASLFO_MinHeight (UWORD) - The minimum font height to let the user
            select. Default is 5. (V36)

    ASLFO_MaxHeight (UWORD) - The maximum font height to let the user
            select. Default is 24. (V36)

    ASLFO_FilterFunc (struct Hook *) - A function to call for each font
            encountered. If the function returns TRUE, the font is
            included in the font list, otherwise it is rejected
            and not displayed. The function receives the following
            parameters:
                A0 - (struct Hook *)
                A1 - (struct TextAttr *)
                A2 - (struct FontRequester *)
            (V38)

    ASLFO_HookFunc (APTR) - A function that is called if the
            FOF_FILTERFUNC or FOF_INTUIFUNC flags are specified in
            the ASLFO_Flags tag. The function will be called like
            so, with the arguments on the stack using the standard
            C pushing order:

                ULONG function(ULONG mask, APTR object,
                           struct FontRequester *fr)

            The Mask value is a copy of the specific ASLFO_Flags
            value the callback is for, either FOF_FILTERFUNC or
            FOF_INTUIFUNC; object is a pointer to a data object
            (a (struct IntuiMessage *) for FOF_INTUIFUNC, and a
            (struct TextAttr *) for FOF_FILTERFUNC).

            For FOF_FILTERFUNC, the function should return 1 if the
            font should be added to the list, 0 if it
            shouldn't. For FOF_INTUIFUNC, the function should
            return the original (struct IntuiMessage *) it was
            passed.

    ASLFO_MaxFrontPen (UBYTE) - The maximum number of pens that are offered
            to the user when the ASLFO_DoFrontPen tag is specified.
            Default is 255. (V40)

    ASLFO_MaxBackPen (UBYTE) - The maximum number of pens that are offered
            to the user when the ASLFO_DoBackPen tag is specified.
            Default is 255. (V40)

    ASLFO_ModeList (STRPTR *) - Replacement list of modes to display in
            Mode cycle gadget. The first string pointer is used
            as the name of the gadgets, and following strings are
            used as the different labels of the cycle gadget,
            until a NULL string pointer which denotes the end of
            the string pointer array. The first string in this
            array corresponds to JAM1, the second is JAM2, the
            third to COMPLEMENT. The array can be early terminated
            by not providing all entries. English default for
            the array is "Text" "Text+Field" and "Complement".
            (V36)

    ASLFO_FrontPens (UBYTE *) - Pointer to a table of pen numbers
            indicating  which colors should be used and edited
            by the palette gadget when the ASLFO_DoFrontPen tag is
            specified. This array must contain as many entries as
            there are colors displayed in the palette gadget. The
            Default is NULL, which causes a 1-to-1 mapping of pen
            numbers. (V40)

    ASLFO_BackPens (UBYTE *) - Pointer to a table of pen numbers
            indicating  which colors should be used and edited
            by the palette gadget when the ASLFO_DoBackPen tag is
            specified. This array must contain as many entries as
            there are colors displayed in the palette gadget. The
            Default is NULL, which causes a 1-to-1 mapping of pen
            numbers. (V40)

    ASLFO_PopToFront (BOOL) -- When set to TRUE, this tells ASL to
            bring the screen to the front the requester has opened on.
            The position of the screen will be adjusted, too, to bring
            the area into view the window has opened in. The screen
            brought to the front will be pushed into the background
            again when the requester window closes.
            Default is TRUE. (V44)

    Tags used for the screen mode requester (V38):

    ASLSM_Window (struct Window *) - Parent window of requester. If no
            ASLSM_Screen tag is specified, the window structure
            is used to determine on which screen to open the
            requesting window. (V38)

    ASLSM_PubScreenName (STRPTR) - Name of a public screen to open on.
            This overrides the screen used by ASLSM_Window. (V38)

    ASLSM_Screen (struct Screen *) - Screen on which to open the requester.
            This overrides the screen used by ASLSM_Window or by
            ASLSM_PubScreenName. (V38)

    ASLSM_PrivateIDCMP (BOOL) - When set to TRUE, this tells ASL to
            allocate a new IDCMP port for the requesting window.
            If not specified or set to FALSE, and if ASLSM_Window
            is provided, the requesting window will share
            ASLSM_Window's IDCMP port. (V38)

    ASLSM_IntuiMsgFunc (struct Hook *) - A function to call whenever an
            unknown Intuition message arrives at the message port
            being used by the requesting window. The function
            receives the following parameters:
                A0 - (struct Hook *)
                A1 - (struct IntuiMessage *)
                A2 - (struct ScreenModeRequester *)
            (V38)

    ASLSM_SleepWindow (BOOL) - When set to TRUE, this tag will cause the
            window specified by ASLSM_Window to be "put to
            sleep". That is, a busy pointer will be displayed in
            the parent window, and no gadget or menu activity will
            be allowed. This is done by opening an invisible
            Intuition Requester in the parent window. (V38)

    ASLSM_UserData (APTR) - A 32-bit value that is simply copied in the
            sm_UserData field of the requester structure. (V38)

    ASLSM_TextAttr (struct TextAttr *) - Font to be used for the requesting
            window's gadgets and menus. If this tag is not provided
            or its value is NULL, the default font of the screen
            on which the requesting window opens will be used.
            This font must already be in memory as ASL calls
            OpenFont() and not OpenDiskFont().
            (V38)

    ASLSM_Locale (struct Locale *) - Locale to use for the requesting
            window. This determines the language used for the
            requester's gadgets and menus. If this tag is not
            provided or its value is NULL, the system's current
            default locale will be used. (V38)

    ASLSM_TitleText (STRPTR) - Title to use for the requesting window.
            Default is no title. (V38)

    ASLSM_PositiveText (STRPTR) - Label of the positive gadget in the
            requester. English default is "OK". Prior to V38, this
            string could not be longer than 6 characters. (V36)

    ASLSM_NegativeText (STRPTR) - Label of the negative gadget in the
            requester. English default is "Cancel". Prior to V38,
            this string could not be longer than 6 characters.
            (V36)

    ASLSM_InitialLeftEdge (WORD) - Suggested left edge of requesting
            window. (V38)

    ASLSM_InitialTopEdge (WORD) - Suggested top edge of requesting
            window. (V38)

    ASLSM_InitialWidth (WORD) - Suggested width of requesting window. (V38)

    ASLSM_InitialHeight (WORD) - Suggested height of requesting window.
            (V38)

    ASLSM_InitialDisplayID (ULONG) - Initial setting of the Mode list view
            gadget (sm_DisplayID). Default is 0 (LORES_KEY). (V38)

    ASLSM_InitialDisplayWidth (ULONG) - Initial setting of the Width gadget
            (sm_DisplayWidth). Default is 640. (V38)

    ASLSM_InitialDisplayHeight (ULONG) - Initial setting of the Height
            gadget (sm_DisplayHeight). Default is 200. (V38)

    ASLSM_InitialDisplayDepth (UWORD) - Initial setting of the Colors
            gadget (sm_DisplayDepth). Default is 2. (V38)

    ASLSM_InitialOverscanType (UWORD) - Initial setting of the
            Overscan Type cycle gadget (sm_OverscanType).
            These values are the OSCAN_#? values from
            <intuition/screens.h>.

            User-space naming of overscan types is different than
            programmer-space:

            Under V38:
                 0               -->  "Regular Size"
                 OSCAN_TEXT      -->  "Text Size"
                 OSCAN_STANDARD  -->  "Graphics Size"
                 OSCAN_MAXIMUM   -->  "Maximum Size"

            Under V39 and above:
                 OSCAN_TEXT      -->  "Text Size"
                 OSCAN_STANDARD  -->  "Graphics Size"
                 OSCAN_MAXIMUM   -->  "Extreme Size"
                 OSCAN_VIDEO     -->  "Maximum Size"

            OSCAN_VIDEO is not supported prior to V39. The value
            0 corresponds to "Regular Size" under V38. Since this
            value isn't supported by Intuition's SA_Overscan
            tag, it was removed from ASL in V39. Asking for 0
            under V39 will yield OSCAN_TEXT.

            Default is OSCAN_TEXT. (V38)

    ASLSM_InitialAutoScroll (BOOL) - Initial setting of the AutoScroll
            cycle gadget (sm_AutoScroll). Default is TRUE. (V38)

    ASLSM_InitialInfoOpened (BOOL) - Whether to open the property
            information window automatically. Default is FALSE.
            (V38)

    ASLSM_InitialInfoLeftEdge (WORD) - Initial left edge of information
            window. (V38)

    ASLSM_InitialInfoTopEdge (WORD) - Initial top edge of information
            window. (V38)

    ASLSM_DoWidth (BOOL) - Set this tag to TRUE to cause the requester
            to display the Width numeric gadget. Default is FALSE.
            (V38)

    ASLSM_DoHeight (BOOL) - Set this tag to TRUE to cause the requester
            to display the Height numeric gadget. Default is FALSE.
            (V38)

    ASLSM_DoDepth (BOOL) - Set this tag to TRUE to cause the requester to
            display the Colors slider gadget. Default is FALSE.
            (V38)

    ASLSM_DoOverscanType (BOOL) - Set this tag to TRUE to cause the
            requester to display the Overscan Type cycle gadget.
            Default is FALSE. (V38)

    ASLSM_DoAutoScroll (BOOL) - Set this tag to TRUE to cause the requester
            to display the AutoScroll checkbox gadget. Default is
            FALSE. (V38)

    ASLSM_PropertyFlags (ULONG) - A mode must have these property flags to
            appear in the list of modes. Only the bits set in
            ASLSM_PropertyMask are considered. See the description
            of ASLSM_PropertyMask for more info. Default is
            DIPF_IS_WB. (V38)

    ASLSM_PropertyMask (ULONG) - A mask to apply to ASLSM_PropertyFlags
            to determine which bits to consider. The use of these
            two values is identical in concept to how Exec uses
            the two flag paraneters in exec.library/SetSignal().
            Default is DIPF_IS_WB. This is how this tag and the
            ASLSM_PropertyFlags tag interact:

            if ((displayInfo.PropertyFlags & propertyMask) ==
               (propertyFlags & propertyMask))
            {
                /* Mode accepted */
            }
            else
            {
                /* Mode rejected */
            }

            where "displayInfo" is a filled in DisplayInfo
            structure for a given mode. (V38)

    ASLSM_MinWidth (ULONG) - The minimum display width to let the user
            choose. Default is 16. (V38)

    ASLSM_MaxWidth (ULONG) - The maximum display width to let the user
            choose. Default is 16368. (V38)

    ASLSM_MinHeight (ULONG) - The minimum display height to let the user
            choose. Default is 16. (V38)

    ASLSM_MaxHeight (ULONG) - The maximum display height to let the user
            choose. Default is 16384. (V38)

    ASLSM_MinDepth (UWORD) - The minimum display depth to let the user
            choose. Default is 1. (V38)

    ASLSM_MaxDepth (UWORD) - The maximum display depth to let the user
            choose. Default is 24. (V38)

    ASLSM_FilterFunc (struct Hook *) - A function to call for each mode
            encountered. If the function returns TRUE, the mode is
            included in the file list, otherwise it is rejected
            and not displayed. The function receives the following
            parameters:
                A0 - (struct Hook *)
                A1 - (ULONG) mode id
                A2 - (struct ScreenModeRequester *)
            (V38)

    ASLSM_CustomSMList (struct List *) - Custom list of modes to let
            the user choose from. This is a list of DisplayNode
            nodes, see <libraries/asl.h> for the definition. (V38)

    ASLSM_PopToFront (BOOL) -- When set to TRUE, this tells ASL to
            bring the screen to the front the requester has opened on.
            The position of the screen will be adjusted, too, to bring
            the area into view the window has opened in. The screen
            brought to the front will be pushed into the background
            again when the requester window closes.
            Default is TRUE. (V44)

   RESULT
    result - FALSE if the user cancelled the requester or if something
         prevented the requester from opening. If TRUE, values in the
         requester structure will be set depending on the particular
         type of requester.

         Under V38, If the return value is FALSE, you can look
         at the result from the dos.library/IoErr() function to
         determine whether the requester was cancelled or simply
         failed to open. If dos.library/IoErr() returns 0, then the
         requester was cancelled, any other value indicates a failure
         to open. Current possible failure codes are
         ERROR_NO_FREE_STORE which indicates there was not enough
         memory, and ERROR_NO_MORE_ENTRIES which indicates no modes
         were available for display in the screen mode requester
         (usually because the application filter hook filtered them
         all away)

   WARNING
    All ASL requester data structures are READ-ONLY and can only be
    modified by using tags!

    You must not specify requester options by using both pre-V38
    tags like ASLFR_Flags1 and V38 tags like ASLFR_DoSaveMode as
    this can lead to unexpected results.

    Take care when attaching an ASL requester to a simple refresh
    window or a window that already shares its IDCMP with other
    windows. In such cases you must ask for the ASL requester to
    allocate a private IDCMP (with the ASLFR_PrivateIDCMP,
    ASLFO_PrivateIDCMP and ASLSM_PrivateIDCMP tags) or your window
    will lose IDCMP_REFRESHWINDOW events and other messages.

   BUGS
    Under V38 and V39, the filtering functions for the file requester
    were only asked to filter drawer selections if the ASLFR_FilterDrawers
    tag was set to TRUE. The compatible behavior, reestablished in V40,
    is to always pass drawers for filtering.

   NOTES
    As of V38-V40 the ASL requester uses gadtools.library routines to
    create and maintain its user interface. Every IntuiMessage the library
    passes through the functions specified with ASLSM_IntuiMsgFunc and
    ASLSM_HookFunc will have been filtered through the
    gadtools.library/GT_GetIMsg() routine.

   SEE ALSO
    AllocAslRequest(), FreeAslRequest()


asl.library/FreeAslRequest

   NAME
    FreeAslRequest -- frees resources allocated by AllocAslRequest(). (V36)

   SYNOPSIS
    FreeAslRequest(requester);
               A0

    VOID FreeAslRequest(APTR);

   FUNCTION
    FreeAslRequest() frees any system resources allocated by
    AllocAslRequest(). Once a requester has been freed, it can no
    longer be used with other calls to AslRequest().

   INPUTS
    requester - requester obtained from AllocAslRequest(), or NULL in
            which case this function does nothing.

   SEE ALSO
    AllocAslRequest()


asl.library/FreeFileRequest

   NAME
    FreeFileRequest -- free file requester structure. (V36)

   SYNOPSIS
    FreeFileRequest(requester);
            A0

    VOID FreeFileRequest(struct FileRequester *);

   NOTES
    This function is obsolete, please use AllocAslRequest() instead.

   SEE ALSO
    FreeAslRequest()


asl.library/RequestFile

   NAME
    RequestFile -- request user to select files. (V36)

   SYNOPSIS
    result = RequestFile(requester);
    D0                   A0

    BOOL RequestFile(struct FileRequester *);

   NOTES
    This function is obsolete, please use AslRequest() instead.

   SEE ALSO
    AslRequest()


audio.doc

     AbortIO()
     ADCMD_ALLOCATE
     ADCMD_FINISH
     ADCMD_FREE
     ADCMD_LOCK
     ADCMD_PERVOL
     ADCMD_SETPREC
     ADCMD_WAITCYCLE
     BeginIO()
     CloseDevice()
     CMD_CLEAR
     CMD_FLUSH
     CMD_READ
     CMD_RESET
     CMD_START
     CMD_STOP
     CMD_UPDATE
     CMD_WRITE
     Expunge()
     OpenDevice()


audio.device/CMD_WRITE

   NAME
       CMD_WRITE -- normal I/O entry point

   FUNCTION
       CMD_WRITE is a standard command for a single audio channel (io_Unit).
       If the allocation key (ioa_AllocKey) is correct, CMD_WRITE plays a
       sound using the selected channel; otherwise, it returns an error
       (ADIOERR_NOALLOCATION).  CMD_WRITE queues up requests if there is
       another write in progress or if the channel is stopped (CMD_STOP).
       When the write actually starts; if the ADIOF_PERVOL flag is set,
       CMD_WRITE loads volume (ioa_Volume) and period (ioa_Period), and if
       the ADIOF_WRITEMESSAGE flag is set, CMD_WRITE replies the write
       message (ioa_WriteMsg).  CMD_WRITE returns an error (IOERR_ABORTED) if
       it is canceled (AbortIO) or the channel is stolen (ADCMD_ALLOCATE).
       CMD_WRITE is only asynchronous if there is no error, in which case it
       clears the quick flag (IOF_QUICK) and replies the I/O request
       (mn_ReplyPort) after it finishes writting; otherwise, it is synchronous
       and only replies if the quick flag (IOF_QUICK) is clear.  Do not use
       CMD_WRITE in interrupt code at interrupt level 5 or higher.

   INPUTS
       mn_ReplyPort- pointer to message port that receives I/O request after
                     the write completes
       io_Device   - pointer to device node, must be set by (or copied from
                     I/O block set by) OpenDevice function
       io_Unit     - bit map of channel to write (bit 0 thru 3 corresponds to
                     channel 0 thru 3), if more then one bit is set lowest
                     bit number channel is written
       io_Command  - command number for CMD_WRITE
       io_Flags    - flags, must be cleared if not used:
                     ADIOF_PERVOL       - (SET) load volume and period
                     ADIOF_WRITEMESSAGE - (SET) reply message at write start
       ioa_AllocKey- allocation key, must be set by (or copied from I/O block
                     set by) OpenDevice function or ADCMD_ALLOCATE command
       ioa_Data    - pointer to waveform array (signed bytes (-128 thru 127)
                     in custom chip addressable ram and word aligned)
       ioa_Length  - length of the wave array in bytes (2 thru 131072, must
                     be even number)
       ioa_Period  - sample period in 279.365 ns increments (124 thru 65536,
                     anti-aliasing filter works below 300 to 500 depending on
                     waveform), if enabled by ADIOF_PERVOL
       ioa_Volume  - volume (0 thru 64, linear), if enabled by ADIOF_PERVOL
       ioa_Cycles  - number of times to repeat array (0 thru 65535, 0 for
                     infinite)
       ioa_WriteMsg- message replied at start of write,  if enabled by
                     ADIOF_WRITEMESSAGE

   OUTPUTS
       io_Unit     - bit map of channel successfully written (bit 0 thru 3
                     corresponds to channel 0 thru 3)
       io_Flags    - IOF_QUICK flag cleared if there is no error
       io_Error    - error number:
                     0                    - no error
                     IOERR_ABORTED        - canceled (AbortIO) or channel
                                            stolen
                     ADIOERR_NOALLOCATION - allocation key (ioa_AllocKey)
                                            does not match key for channel

   BUGS
       If CMD_WRITE starts the write immediately after stopping a previous
       write, you must set the ADIOF_PERVOL flag or else the new data pointer
       (ioa_Data) and length (ioa_Length) may not be loaded.


battmem.doc

     ObtainBattSemaphore()
     ReadBattMem()
     ReleaseBattSemaphore()
     WriteBattMem()


bevel_ic.doc

     --datasheet--
     --styleguide--
     BEVEL_GetClass()


bevel_ic/--datasheet--

    NAME
        bevel_ic -- create bevel BOOPSI objects

    SUPERCLASS
        imageclass

    REQUIRES
        None.

    DESCRIPTION
        This image class can create a varity of bevel boxes styles
        including those appropriate as gadget borders, titled or
        non-titled grouping boxes and more. This class is very simular
        in function to the frameiclass in OS 3.x rom, except this class
        supports the newer style bevels under OS 2.04 as well.

    METHODS
        OM_NEW -- Create the bevel image.  Passed to superclass, then OM_SET.

        OM_GET -- Get object attributes.  Passed to superclass first.

        OM_SET -- Set object attributes.  Passed to superclass first.

        IM_FRAMEBOX -- Initial attempt at this method, totally
            untested at this time. If you know what it is and need it
            then try it and report any bugs. :)

        IM_DRAW -- Renders the images.  Overrides the superclass.

        IM_DRAWFRAME -- Renders the images at the frame size.
            Any following IM_DRAW will be at this frame size w/o a
            overriding OM_SET. Overrides the superclass.

        IM_ERASE -- Erase the images.  Overrides the superclass.

        IM_ERASEFRAME -- Erase the images at the frame size.
            Overrides the superclass.

        All other methods are passed to the superclass, including OM_DISPOSE.

    ATTRIBUTES
        IA_Top (WORD)
        IA_Left (WORD)
        IA_Width (WORD)
        IA_Height (WORD)
            Set bevel image size and position.

            Applicability is (OM_NEW, OM_SET)

        IA_SupportsDisable (BOOL)
            Reports TRUE if the image class can render its own
            disable pattern.

            Applicability is (OM_GET)

        IA_APattern (UWORD *)
            Optional inner fill pattern for SetAfPt() when used in
            conjunction with BEVEL_FillPen. See also BEVEL_FillPattern.
            I missed the OS support of this tag, thus, it is duplicated
            in BEVEL_FillPattern which will remain for backwards
            compatibility.

            Defaults to NULL.

            Applicability is (OM_NEW, OM_SET)

        IA_APatSize (UWORD)
            Set pattern size for the pattern passed via IA_APattern.
            Defaults to 1. With BEVEL_FillPattern, the size was fixed.

            Applicability is (OM_NEW, OM_SET)

        IA_Recessed
            Inverts SHADOW/SHINEPEN and shading rendering pens.

            Applicability is (OM_NEW, OM_SET)

        IA_EdgesOnly
            See BEVEL_Transparent.

            Applicability is (OM_NEW, OM_SET)

        IA_FrameType
            Accepts all frameiclass frame types, and converts them
            the closest matching BEVEL_Style type honoring the
            current user preference settings.

            Applicability is (OM_SET)

        IA_Font (struct TextAttr *)
            Text Attribute to use for any label text.

            Applicability is (OM_NEW, OM_SET)

        IA_HighlightPen (UWORD)
        IA_FGPen (UWORD)
            Foreground pen.

            Defaults to SHINEPEN.

            Applicability is (OM_NEW, OM_SET)

        IA_ShadowPen (UWORD)
        IA_BGPen (UWORD)
            Background pen.

            Defaults to SHADOWPEN.

            Applicability is (OM_NEW, OM_SET)

        BEVEL_FillPen (WORD)
            Inner bevel area RectFill() pen number, ~0 means to
            ignore, and not to RectFill().

            Defaults to ~0.

            Applicability is (OM_NEW, OM_SET)

        BEVEL_FillPattern (UWORD *)
            Optional inner fill pattern for SetAfPt() when used in
            conjunction with BEVEL_FillPen.  See also: IA_APattern

            Defaults to NULL.

            Applicability is (OM_NEW, OM_SET)

        BEVEL_TextPen (WORD)
            Bevel text rendering pen number, ~0 will render
            in TEXTPEN.

            Defaults to ~0.

            Applicability is (OM_NEW, OM_SET)

        BEVEL_Style (BOOL)
            Specifies the bevel box style, may be one of the following;

                BVS_THIN       - thin/small bevel
                BVS_BUTTON     - standard button bevel (thin/thick pref)
                BVS_GROUP      - layout/grouping bevel (thin/thick pref)
                BVS_FIELD      - string/inputfield bevel (thin/thick pref)
                BVS_NONE       - no bevel
                BVS_DROPBOX    - standard dropbox
                BVS_SBAR_HORIZ - horizontal separator bar
                BVS_SBAR_VERT  - vertical separator bar
                BVS_BOX        - plain "black" box bevel
                BVS_STANDARD   - Simular to BVS_BUTTON, but no XEN!

            Defaults to BVS_BUTTON

            Applicability is (OM_NEW, OM_SET)

        BEVEL_Label (STRPTR)
            Specifies the text label for the bevel box.

            Defaults to NULL.

            Applicability is (OM_NEW, OM_SET)

        BEVEL_LabelPlace (WORD)
            Specifies label location, may be one of the following;

                BVJ_TOP_CENTER
                BVJ_TOP_LEFT
                BVJ_TOP_RIGHT
                BVJ_IN_CENTER
                BVJ_IN_LEFT
                BVJ_IN_RIGHT

            Defaults to BVJ_TOP_CENTER.

            NOTE: BVS_BOTTOM_* settings not yet implemented

            Applicability is (OM_NEW, OM_SET)

        BEVEL_InnerTop (WORD)
            Get only attribute, returns the inside-top offset of the
            bevel box accounting for any BVJ_TOP text label placements.

            Applicability is (OM_GET)

        BEVEL_InnerLeft (WORD)
            Get only attribute, returns the inside-left offset of the
            bevel box.

            Applicability is (OM_GET)

        BEVEL_InnerWidth (WORD)
            Get only attribute, returns the inside-width of the
            bevel box, basically the same as;

                IA_Width - (BEVEL_VertSize * 2) - 1

            Except this also accounts for the BVS_TOP label placements.

            Applicability is (OM_GET)

        BEVEL_InnerHeight (WORD)
            Get only attribute, returns the inside - height of the
            bevel box, basically the same as;

                IA_Height - (BEVEL_InnerTop + BEVEL_HorzSize) - 1

            with the exception that BEVEL_InnerHeight will account for
            any text label for a BVS_GROUP style bevel.

            Applicability is (OM_GET)

        BEVEL_HorizSize (WORD)
            Get only attribute, returns the nominal size (in pixels) of
            the horizontal lines the bevel will draw for the givel style.

            Applicability is (OM_GET)

        BEVEL_VertSize (WORD)
            Get only attribute, returns the nominal size (in pixels) of
            the vertical lines the bevel will draw for the given style.

            Applicability is (OM_GET)

        BEVEL_SoftStyle (WORD)
            Font softstyles to apply.
            See <graphics/text.h> SoftStyle definitions.

            Defaults to 0.

            Applicability is (OM_NEW, OM_SET)

        BEVEL_Transparent (BOOL)
            If set TRUE, bevel will not attempt to render or erase any
            part of the inner area of the bevel.

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_SET)

        BEVEL_ColorMap (struct ColorMap *)
            Screen viewport colormap pointer, use to obtain additional
            best-match pens for XEN and possibly other future multi-pen
            beveling options. MWB or NI3 palette recommended for best
            results.

            Defaults to NULL.

            Applicability is (OM_NEW, OM_SET)

        BEVEL_Flags (UWORD)
            Intentionally left undocumented! It is used for some hidden
            BVS_BUTTON xen style magic. Class authors inquire as needed.

            Defaults to 0.

            Applicability is (OM_NEW, OM_SET)


bevel_ic/--styleguide--

    BEVEL STYLE

        Several ReAction objects allow overriding the default bevel
        style. This is NOT recommended practice for application authors.
        But instead, its provided to add some extra flexability to BOOPSI
        class authors who may wish to sub-class a ReAction gadget or
        utilize it within a larger composite (model class) object.

        When using bevel.image directly be sure to select the appropriate
        bevel for your usage. Do not provide a bevel style override tag
        unless it makes sence to do so. The idea being that all applications
        and BOOPSI objects should be presented using a standard beveling
        style. For example, a button gadget using a BVS_FIELD string bevel
        would be an illogical choice.  Any button should use BVS_BUTTON, a
        text entry field should use BVS_FIELD, and ofcourse a layout group,
        if using a bevel, should use BVS_GROUP, BVS_SBAR_VERT or
        BVS_SBAR_HORIZ.


bevel_ic/BEVEL_GetClass

    NAME
        BEVEL_GetClass -- Gets the pointer to the bevel class.

    SYNOPSIS
        bevel_class = BEVEL_GetClass();
        D0

        Class * BEVEL_GetClass(VOID);

    FUNCTION
        Obtains the pointer to the Bevel image class for use with
        NewObject().  This function always returns a valid pointer so
        you do not need to check it.  The reason is that if the library
        opens fine, then the pointer returned is already setup.  (Of course
        this implies that if opening the library fails, you shouldn't be
        calling this.)

        Note that this function does not create the class, that is done
        when the class library is opened.

    INPUTS
        Nothing.

    RESULT
        bevel_class - Pointer to the Bevel image class.

    SEE ALSO


bitmap_ic.doc

     --datasheet--
     BITMAP_GetClass()


bitmap_id/--datasheet--

    NAME
        bitmap_ic -- Create image object using datatypes

    SUPERCLASS
        imageclass

    REQUIRES
        None.

    DESCRIPTION
        This image class can create an image given the name of a source
        file. It uses the datatypes system to create a bitmap used for
        rendering the image. Bitmap supports drawing itself in a selected
        state, and supports transparent images provided that the datatype
        supports transparency.

        Instead of a source file name, a ready-to-use bitmap can be passed
        with OM_NEW.

    METHODS
        OM_NEW -- Create the bitmap image.  Passed to superclass, then OM_SET.

        OM_GET -- Get object attributes.  Passed to superclass first.

        OM_SET -- Set object attributes.  Passed to superclass first.

        OM_UPDATE -- Set object notification attributes.  Passed to
            superclassfirst.

        IM_DRAW -- Renders the image.  Overrides the superclass.

        All other methods are passed to the superclass, including OM_DISPOSE.

    ATTRIBUTES
        IA_TopEdge (WORD)
        IA_LeftEdge (WORD)
        IA_Width (WORD)
        IA_Height (WORD)
            Set position and size of the image. If given, these must be
            greater then or equal to the maximum dimensions of the bitmaps
            used.

            If the image size is larger than one of the bitmap sizes, the
            bitmap will be drawn centered within in the image. The area
            surrounding the bitmap is NOT erased!

            Defaults to the maximum of the dimensions of the normal and
            selected bitmaps.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        BITMAP_SourceFile (STRPTR)
            Source file name of the image file to create the bitmap from,
            using the datatypes system.

            Applicability is (OM_NEW, OM_GET)

        BITMAP_Screen (struct Screen *)
            Pointer to the screen to use the image on. This attribute MUST
            be provided when creating an object of this class using the
            datatypes system.

            Applicability is (OM_NEW, OM_GET)

        BITMAP_Precision (ULONG)
            Precision to use when obtaining colors. See the PRECISION_
            defines in <graphics/view.h>

            Defaults to PRECISION_ICON.

            Applicability is (OM_NEW, OM_GET)

        BITMAP_Masking (BOOL)
            If set to TRUE, the image will be drawn using a transparent
            mask if the image source contains a transparent color.

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_GET)

        BITMAP_BitMap (struct BitMap *)
            Instead of letting the class create the bitmap using datatypes,
            you can create your own bitmap and pass it to the class.
            If you supply your own bitmap, you MUST set BITMAP_Width
            and BITMAP_Height too.
            Either BITMAP_SourceFile or BITMAP_BitMap must be given.

            Applicability is (OM_NEW, OM_GET)

        BITMAP_Width (LONG)
        BITMAP_Height (LONG)
            Set the dimensions of your own bitmap passed with
            BITMAP_BitMap, or get the dimensions of the bitmap created
            by the datatype.

            Applicability is (OM_NEW, OM_GET)

        BITMAP_MaskPlane (APTR)
            A mask plane. Only set this if you supply your own bitmap
            with BITMAP_BitMap.
            The mask plane will only be used if BITMAP_Masking is TRUE.

            Defaults to NULL.

            Applicability is (OM_NEW, OM_GET)

        BITMAP_SelectSourceFile (STRPTR)
            Source file name of the selected state image to create the
            bitmap from, using the datatypes system.

            Applicability is (OM_NEW, OM_GET)

        BITMAP_SelectBitMap (struct BitMap *)
            Your own bitmap to use for the selected state.
            If you supply your own bitmap, you MUST set BITMAP_SelectWidth
            and BITMAP_SelectHeight too.

            Applicability is (OM_NEW, OM_GET)

        BITMAP_SelectWidth (LONG)
        BITMAP_SelectHeight (LONG)
            Set the dimensions of your own selected statebitmap passed
            with BITMAP_SelectBitMap, or get the dimensions of the selected
            state bitmap created by the datatype.

            Applicability is (OM_NEW, OM_GET)

        BITMAP_SelectMaskPlane (APTR)
            A mask plane for the selected state bitmap. Only set this if
            you supply your own bitmap with BITMAP_SelectBitMap.
            The mask plane will only be used if BITMAP_Masking is TRUE.

            Defaults to NULL.

            Applicability is (OM_NEW, OM_GET)

        BITMAP_OffsetX (LONG)
        BITMAP_OffsetY (LONG)
            Together with BITMAP_BitMap, BITMAP_Width and BITMAP_Height
            these attributes determine which part of the bitmap to use
            for the image.
            These attributes will be ignored if the bitmap was created
            by the class using datatypes.

            Defaults to 0.

            Applicability is (OM_NEW, OM_GET)

        BITMAP_SelectOffsetX (LONG)
        BITMAP_SelectOffsetY (LONG)
            Together with BITMAP_SelectBitMap, BITMAP_SelectWidth and
            BITMAP_SelectHeight these attributes determine which part
            of the bitmap to use for the selected state image.
            These attributes will be ignored if the bitmap was created
            by the class using datatypes.

            Defaults to 0.

            Applicability is (OM_NEW, OM_GET)


bitmap_ic/BITMAP_GetClass

    NAME
        BITMAP_GetClass -- Gets the pointer to the bitmap class.

    SYNOPSIS
        bitmap_class = BITMAP_GetClass();
        D0

        Class * BITMAP_GetClass(VOID);

    FUNCTION
        Obtains the pointer to the BitMap image class for use with
        NewObject().  This function always returns a valid pointer so
        you do not need to check it.  The reason is that if the library
        opens fine, then the pointer returned is already setup.  (Of course
        this implies that if opening the library fails, you shouldn't be
        calling this.)

        Note that this function does not create the class, that is done
        when the class library is opened.

    INPUTS
        Nothing.

    RESULT
        bitmap_class - Pointer to the BitMap image class.

    SEE ALSO


bullet.doc

     --background--
     CloseEngine()
     ObtainInfoA()
     OpenEngine()
     ReleaseInfoA()
     SetInfoA()


bullet.library/--background--

   AMIGA FONTS
    The existence of a disk font is indicated by the existence of
    its associated font contents file, whose name has the suffix
    ".font".  It is this name that is used in the actual font
    open call of the application.  Amiga fonts are collected in
    the directory path(s) associated with the FONTS: assign.  It
    is this assign that is searched if no explicit path name is
    provided in the font open call: use of an explicit path is
    generally discouraged.  The actual bitmaps of traditional
    Amiga fonts are stored in a directory with the name of the
    font contents file stripped of its ".font" suffix.  This
    directory is usually in the same directory as the font
    contents file.  This traditional arrangement is supported by
    the FixFonts system application.

    For example:
        o   FONTS: is assigned to Sys:Fonts/
        o   Sys:Fonts/garnet.font exists and describes that the
        font "garnet.font" exists
        o   Sys:Fonts/garnet/ contains the bitmap images for
        sizes 9 and 16

    Other variations of file placement may exist, but they
    require custom tools to maintain -- tools available not from
    Commodore, but from other sources such as Fish disks.

    Font contents files are flagged with magic numbers that not
    only verify that they are a font contents files but also what
    variation of file structure they contain.

   OUTLINE TYPEFACES
    The existence of an outline typeface is indicated by a magic
    number in the font contents file.  They are further described
    in the associated outline typeface tag file, whose name is
    the that of the font contents file with the suffix ".otag"
    substituted for ".font".  This tag file contains a tag list
    that is to be processed and passed to the outline engine
    (i.e.  bullet.library) in order to select the associated
    typeface.  It also contains information applications may use
    to guide their use of the typeface.

   OTAG SPECIFICATION EXAMPLE
    Here are the steps necessary to go from an arbitrary font
    name into an environment where glyphs from that font
    can be accessed:
    1.  Read the header from the font contents (.font) file and
        verify that the magic cookie fch_ID is OFCH_ID.
        If it is not, then this is an Amiga bitmap font,
        not an outline font.
    2.  Read the associated outline tag (.otag) file into memory:
        a.  Validate that the OT_FileIdent exists and matches the
        file size.
        b.  Allocate a memory buffer and read the file into it.
        c.  Resolve addresses: for each tag with the OT_Indirect
        bit set, add the memory buffer origin to the
        associated data.
    3.  Find the OT_Engine tag and ensure that you have the
        proper engine open:
        a.  If you already have an engine handle for this engine
        name, you skip these steps.
        b.  append the suffix ".library" to the engine name.
        (e.g. "bullet" becomes "bullet.library").
        c.  use exec's OpenLibrary() to open the library.
        d.  use the engine's OpenEngine() to acquire an engine
        handle.
    4.  Pass the full path name of the .otag file to the engine
        with the OT_OTagPath tag using SetInfo().
    5.  Pass the memory copy of the .otag file to the engine with
        the OT_OTagList tag using SetInfo().  This step may be
        combined with step 4, passing first the path then the
        list in one call.
    The library is now ready to accept glyph metric information
    (e.g. size and glyph code) and produce glyph bitmaps.

   DISKFONT USE OF OTAG ENTRIES
    The diskfont library uses other entries from the outline tag
    (.otag) file.  The following are used both during inquiry of
    what typefaces exist (AvailFonts) and during creation of an
    Amiga TextFont (OpenDiskFont):
    o   OT_IsFixed is used to determine whether these outlines
        describe a PROPORTIONAL flagged font.
    o   OT_StemWeight is used to determine whether these outlines
        describe a BOLD style font.
    o   OT_SlantStyle is used to determine whether these outlines
        describe an ITALIC style font.
    o   OT_HorizStyle is used to determine whether these outlines
        describe an EXTENDED style font.
    The following are used only during OpenDiskFont:
    o   OT_YSizeFactor is used to convert the Amiga pixel height
        specification, which describes the distance from the
        lowest decender to the highest ascender, into a point
        size specification, which is related (via YSizeFactor)
        to a nominal character height.
    o   OT_SpaceWidth is used as the width of the space character.
    The following is used only during AvailFonts:
    o   OT_AvailSizes is used to generate a list of sizes
        available for the font.


bullet.library/CloseEngine

    NAME
    CloseEngine -- Release an engine handle

    SYNOPSIS
    CloseEngine(engineHandle)
                A0

    void CloseEngine(struct GlyphEngine *);

    FUNCTION
    This function releases the engine handle acquired with
    OpenEngine.  It first releases any data acquired with
    ObtainInfoA associated with the engineHandle that has not yet
    been released.

    INPUTS
    engineHandle -- the handle acquired via OpenEngine.  If zero,
        no operation is performed.

    RESULT
    This function has no result.  The only error that can occur is
    when the when an invalid engineHandle is supplied: the
    application is assumed not to do that.

    EXAMPLE
    EndGame(code, arg1, arg2, arg3, arg3)
    {
        ...
        CloseEngine(EngineHandle);
        ...
    }

    SEE ALSO
    OpenEngine()


bullet.library/ObtainInfoA

    NAME
    ObtainInfoA -- Inquire tagged font and/or glyph metrics
    ObtainInfo -- varargs form of ObtainInfoA

    SYNOPSIS
    error = ObtainInfoA(engineHandle, tagList)
                        A0            A1

    ULONG ObtainInfoA(struct GlyphEngine *, struct TagItem *);

    error = ObtainInfo(engineHandle, firstTag, ...)

    ULONG ObtainInfo(struct GlyphEngine *, Tag, ...);

    FUNCTION
    This function accepts a tagList whose tag field elements are
    valid for inquiry, and whose associated data fields are
    pointers to the destination in which to place the requested
    data.

    Tag items that refer to data indirectly (OT_Indirect is set)
    return pointers that may be allocated or cached by the
    library.  This data must be treated as read-only data.  When
    the application is done with the data acquired via ObtainInfoA,
    it must perform a ReleaseInfoA to allow the library to release
    the data.

    INPUTS
    engineHandle -- the handle acquired via OpenEngine.
    tagList -- a tagList containing OT_ tags valid for inquiry
        paired with the destination pointers for the inquiry
        results.  All destinations are longwords, whether they
        are pointers or values, and regardless of whether the
        value could fit in a smaller variable.

    RESULT
    This function returns a zero success indication, or a non-zero
    error code.

    EXAMPLE
        ULONG pointSize;
        struct GlyphMap *glyph;
        ...
        if (!ObtainInfo(EngineHandle, OT_Glyph, &glyph, TAG_DONE)) {
        ...
        ReleaseInfo(EngineHandle, OT_Glyph, glyph, TAG_DONE);
        }

    SEE ALSO
    ReleaseInfoA(), diskfont/diskfonttag.h, diskfont/oterrors.h


bullet.library/OpenEngine

    NAME
    OpenEngine -- Acquire engine handle

    SYNOPSIS
    engineHandle = OpenEngine()

    struct GlyphEngine *OpenEngine(void)

    FUNCTION
    This function establishes a context for access to the bullet
    library.  This context remains valid until it is closed via
    CloseEngine.  Each specific context isolates the specification
    of the various font attributes from other contexts concurrently
    accessing the bullet library.  A context can be shared among
    different tasks.

    RESULT
    This function returns an engineHandle, or NULL if for some
    reason no engineHandle can be created.

    EXAMPLE
        BulletBase = OpenLibrary("bullet.library", 0);
        if (!BulletBase)
        EndGame(ERROR_LibOpen, "bullet.library", 0);
        EngineHandle = OpenEngine();
        if (!EngineHandle)
        EndGame(ERROR_InternalCall, "OpenEngine");

    SEE ALSO
    CloseEngine()


bullet.library/ReleaseInfoA

    NAME
    ReleaseInfoA -- Release data obtained with ObtainInfoA
    ReleaseInfo -- varargs form of ReleaseInfoA

    SYNOPSIS
    error = ReleaseInfoA(engineHandle, tagList)
                         A0            A1

    ULONG ReleaseInfoA(struct GlyphEngine *, struct TagItem *);

    error = ReleaseInfo(engineHandle, firstTag, ...)

    ULONG ReleaseInfo(struct GlyphEngine *, Tag, ...);

    FUNCTION
    This function releases the data obtained with ObtainInfoA.
    Data associated with tags that are not indirect, i.e. for which
    OT_Indirect is not set, need not be released, but it is not an
    error to do so.  Released data may be immediately freed or may
    become a candidate to be expunged from memory when the system
    reaches a low memory condition, depending on the library's
    internal implementation.

    Each ReleaseInfoA tag item must be associated with a prior
    ObtainInfoA.

    INPUTS
    engineHandle -- the handle acquired via OpenEngine.
    tagList -- a tagList containing OT_ tags valid for inquiry
        paired with the data previously acquired for them with
        ObtainInfoA.  Null pointers quietly accepted and
        ignored for indirect data.

    RESULT
    This function has no result.  The only error that can occur is
    when the Obtain and Release pairs are mismatched: the
    application is assumed not to do that.

    EXAMPLE
        ULONG pointSize;
        struct GlyphMap *glyph;
        ...
        error = ObtainInfo(EngineHandle, OT_Glyph, &glyph, TAG_DONE);
        ...
        ReleaseInfo(EngineHandle, OT_Glyph, glyph, TAG_DONE);

    SEE ALSO
    ReleaseInfoA(), diskfont/diskfonttag.h, diskfont/oterrors.h


bullet.library/SetInfoA

    NAME
    SetInfoA -- Set font and/or glyph metrics
    SetInfo -- varargs form of SetInfoA

    SYNOPSIS
    error = SetInfoA(engineHandle, tagList)
                     A0            A1

    ULONG SetInfoA(struct GlyphEngine *, struct TagItem *);

    error = SetInfo(engineHandle, firstTag, ...)

    ULONG SetInfo(struct GlyphEngine *, Tag, ...);

    FUNCTION
    This function accepts a tagList whose tag field elements are
    valid for specification, and whose associated data fields are
    used to supply the specified data.

    Data that is supplied via an indirect pointer (OT_Indirect) to
    an array or structure is copied from that array or structure
    into the internal memory of the library.  Changes to the data
    after this call do not affect the engine.

    INPUTS
    engineHandle -- the handle acquired via OpenEngine.
    tagList -- a tagList containing OT_ tags valid for
        specification paired with the specification data.

    RESULT
    This function returns a zero success indication, or a non-zero
    error code.

    EXAMPLE
        if (!(error = SetInfo(EngineHandle, OT_PointHeight, fpoints,
            OT_GlyphCode, GC_daggerdbl, TAG_DONE)) {
        error = ObtainInfo(EngineHandle, OT_Glyph, &glyph);
        ...
        ReleaseInfo(EngineHandle, OT_Glyph, glyph);
        }

    SEE ALSO
    diskfont/diskfonttag.h, diskfont/oterrors.h,


button_gc.doc

     --datasheet--
     BUTTON_GetClass()


button_gc/--datasheet--

    NAME
        button_gc -- create button BOOPSI objects

    SUPERCLASS
        gadgetclass

    REQUIRES
        bevel.image, glyph.image

    DESCRIPTION
        The button gadget class is used to create action buttons that are
        momentary, toggle and sticky.  This class also supports relativity
        and placement within the window border.

        Advantages that this class provides:

         > Centered images.

         > Centered pen-sensitive glyphs.

         > Multi-frame images animation ability (NEW V42)

         > Ability to change the text and background colors for normal
           and selected buttons.

         > Supports window relativity.

         > Supports OS 3.0 BOOPSI Gadget HelpTest.

     METHODS
        OM_NEW -- Passed to superclass, defaults set, then OM_SET.

        OM_SET -- Passed to superclass, custom tags set.

        OM_GET -- Custom tag returned or passed to superclass.

        OM_UPDATE -- Passed to superclass, options set then rendered.

        OM_NOTIFY -- Tag set then passed to superclass.

        OM_DISPOSE -- MemPool memory freed, then Passed to superclass.

        GM_RENDER -- Passed to superclass, then button is rendered.

        GM_HITTEST -- Overrides supperclass, returns GMR_HITTEST.

        GM_GOACTIVE -- Passed to superclass, button activated.

        GM_HANDLEINPUT -- Overrides supperclass, all input processed.

        GM_GOINACTIVE -- Passed to superclass, button deactivated.

        GM_DOMAIN -- Returns GDOMAIN_MINIMUM and GDOMAIN_MAXIMUM dimensions.

        GM_KEYACTIVE -- Private method for keyboard control.

        GM_KEYINACTIVE -- Private method for keyboard control.

     ATTRIBUTES

        GA_ID (WORD)

            Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET, OM_NOTIFY)

        GA_Selected (BOOL)
            Determines whether the button is selected or not.
            Changing selection state will invoke GM_RENDER.

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_SET, OM_GET, OM_NOTIFY)

        GA_Disabled (BOOL)
            Determines whether the button is disabled or
            not.  Changing disable state will invoke GM_RENDER.  A disabled
            button's border and label are all rendered in SHADOWPEN and then
            dusted in a ghosting pattern.

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET,  OM_NOTIFY)

        GA_Text (STRPTR)
            Used to specify the NULL terminated string to use as the text
            for the gadget.  The Text() function is used to draw the text.
            NULL is valid input. Changing the label will invoke GM_RENDER.
            Text string is clipped to fit inside the button via the
            TextLength() function. The text string may contain varargs
            format specifiers compatible to RawDoFmt() if the varargs data
            is supplied via BUTTON_VarArgs.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

        GA_Image (struct Image *)
            Used to specify the image to use for the label of the gadget.
            The DrawImageState() function is used to draw the image.
            Changing the label will invoke GM_RENDER.

            Defaults to NULL.

            Applicability is (OM_NEW, OM_SET)

        GA_SelectImage (struct Image *)
            Used to specify the image to use for the label of the gadget
            in the selected state. The DrawImageState() function is used
            to draw the image. Changing the label will invoke GM_RENDER
            if the gadget is currently selected.

            Defaults to NULL.

            Applicability is (OM_NEW, OM_SET)

        GA_TextAttr (struct TextAttr *)
            Text attribute for the font to use for the text labels.

            Defaults to RPort->Font, which is often the screen or
            window preferences font.

            Applicability is (OM_NEW, OM_SET)

        GA_ReadOnly (BOOL)
            Read-only gadgets ignore activation attempts.

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

        BUTTON_AutoButton (UWORD)
            Used to create automatic button with one of the selected
            scaled image glyphs. Accepted settings are;

                BAG_POPFILE		- popup file selection glyph
                BAG_POPDRAWER   - popup drawer selection glyph
                BAG_POPFONT		- popup font selection glyph
                BAG_CHECKBOX	- checkmark glyph (same as checkbox.gadget)
                BAG_CANCELBOX   - NOT IMPLEMENETED!
                BAG_UPARROW		- up arrow
                BAG_DNARROW		- down arrow
                BAG_RTARROW		- right arrow
                BAG_LFARROW		- left arrow
                BAG_POPTIME		- popup time glyph
                BAG_POPSCREEN   - popup screen mode glyph

            Defaults to 0.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

        BUTTON_PushButton (BOOL)
            Used to indicate that the button stays pressed in when the
            user selects it with the mouse.  The button may
            programmatically be deselected using {GA_Selected, FALSE}.

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

        BUTTON_TextPen (LONG)
            Indicate the pen number used to render the IDS_NORMAL text.
            If ~0 is specified, then TEXTPEN is used.

            Defaults to ~0.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

        BUTTON_BackgroundPen (LONG)
            Indicate the pen number used to render the IDS_NORMAL
            background.  If ~0 is specified, then BACKGROUNDPEN
            is used.

            Defaults to ~0.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

        BUTTON_FillTextPen (LONG)
            Indicate the pen number used to render the IDS_SELECTED text.
            If ~0 is specified, then FILLTEXTPEN is used.

            Defaults to ~0.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

        BUTTON_FillPen (LONG)
            Indicate the pen number used to render the IDS_SELECTED
            background.  If ~0 is specified, then FILLPEN is used.

            Defaults to ~0.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

        BUTTON_BevelStyle (WORD)
            Button bevel box rendering style, passed to bevel.image.
            Supports:

                BVS_NONE
                BVS_THIN
                BVS_BUTTON
                BVS_GROUP

            Defaults to BVS_BUTTON.

            Applicability is (OM_NEW, OM_SET)

        BUTTON_Transparent (BOOL)
            Make button background rendering transparent.
            EraseRect() is used rather than RectFill() so that
            custom backfill rendering hooks maybe utilized.

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_SET)

        BUTTON_Justification    (WORD)
            Justification mode of button text label.
            Supports:

                BCJ_LEFT
                BCJ_CENTER
                BCJ_RIGHT

            Defaults to BJ_CENTER.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

        BUTTON_SoftStyle (WORD)
            Set the GA_TextAttr font's softstyle, ie BOLD, ITALICS, etc.
            See <graphics/text.h> SoftStyle definitions.

            Defaults to 0.

            Applicability is (OM_NEW, OM_SET)

        BUTTON_VarArgs (APTR)
            Varargs data array to supply data for RawDoFmt() when
            format specifiers are to be used in GA_Text text strings.
            The internal VarArgs result buffer is presently fixed at
            a maximum of 128 bytes, take care not to exceed this buffer.

            Defaults to NULL.

            Applicability is (OM_NEW, OM_SET)

        BUTTON_DomainString (STRPTR)
            Used to specify the NULL terminated string to use as the text
            to domain the gadgets minimum size. This string is NEVER
            rendered on screen. This is useful when you need to create
            a button with a empty ("") or NULL string, but want to enforce
            minimum size in a layout group based on some initializing
            string and the current preferenced font, rather some fixed
            pixel or weighted minimum.  Added by request.

            Defaults to NULL.

            Applicability is (OM_NEW, OM_SET)

        BUTTON_Integer (int)  (V42)
            Set an integer value to display a numeric string. Highly useful
            for interconnect notifications from sliders, scrollers, etc.
            Added by request.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

        BUTTON_BitMap (struct BitMap *)  (V42)
            Specify a BitMap to render in button, rather than image or
            text. Added by request, but use of bitmap.image is highly
            recommended for AmigaOS V39 and later.

            Defaults to NULL.

            Applicability is (OM_NEW, OM_SET)

        BUTTON_AnimButton (BOOL)  (V42)
            Is button animatable?  Use to turn animating on or off.

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_SET)

        BUTTON_AnimImages (struct Image *)  (V42)
            Sets an array of struct Images for animation

            Defaults to NULL.

            Applicability is (OM_NEW, OM_SET)

        BUTTON_SelAnimImages (struct Image *)  (V42)
            Sets an array of alternate images for a selected state
            if used, must contain an equal number of images as the
            array used for BUTTON_AnimImages.  It's wise to use the
            same sized images too

            Defaults to NULL.

            Applicability is (OM_NEW, OM_SET)

        BUTTON_MaxAnimImages (LONG)  (V42)
            Number of images available in the arrays

            Defaults to 0.

            Applicability is (OM_NEW, OM_SET)

        BUTTON_AnimImageNumber (LONG)  (V42)
            Current image number in the array(s) to use the range of
            available frames is 0 .. MaxAnimImages-1

            Defaults to 0.

            Applicability is (OM_NEW, OM_SET)

        BUTTON_AddAnimImageNumber (ULONG)  (V42)
           Value to be added to the current image number counter
           the counter will wrap around at MaxAnimImages

            Applicability is (OM_SET, OM_UPDATE)

        BUTTON_SubAnimImageNumber (ULONG)  (V42)
            Value to be subtracted from the current image number counter
            the counter will wrap around when less than 0

            Applicability is (OM_SET, OM_UPDATE)

    BUGS
        Unfortunetly, this class shares the same filename and tag range
        as the button gadget released by David Junod of C=, released in
        the GI1.lha V42 beta archive on BIX, and later the AT DevCD.
        We admit it, we screwed up... but its not a majorly serious issue
        as this class is atleast 90% compatible.

        A few rarely, possibly never, used tags of the original are NOT
        currently supported. The usage of BUTTON_PushButton in ReAction is
        not totally compatible to Junod's. Ours acts like GA_ToggleSelect
        of Junod's.

        Please report any incompatibilities immediatly.


button_gc/BUTTON_GetClass

    NAME
        BUTTON_GetClass -- Gets the pointer to the button class.

    SYNOPSIS
        button_class = BUTTON_GetClass();
        D0

        Class * BUTTON_GetClass(VOID);

    FUNCTION
        This function is only available in runtime linked version of the
        class, and is not in the compiler linker library button_gc.lib.

        Obtains the pointer to the Button gadget class for use with
        NewObject().  This function always returns a valid pointer so
        you do not need to check it.  The reason is that if the library
        opens fine, then the pointer returned is already setup.  (Of course
        this implies that if opening the library fails, you shouldn't be
        calling this.)

        Note that this function does not create the class, that is done
        when the class library is opened.

    INPUTS
        Nothing.

    RESULT
        button_class - Pointer to the Button gadget class.

    SEE ALSO


cardres.doc

     BeginCardAccess()
     CardAccessSpeed()
     CardChangeCount()
     CardForceChange()
     CardInterface()
     CardMiscControl()
     CardProgramVoltage()
     CardResetCard()
     CardResetRemove()
     CopyTuple()
     DeviceTuple()
     EndCardAccess()
     GetCardMap()
     IfAmigaXIP()
     OwnCard()
     ReadCardStatus()
     ReleaseCard()


card.resource/BeginCardAccess

   NAME
    BeginCardAccess -- Called before you begin credit-card memory access

   SYNOPSIS
    result=BeginCardAccess( handle )
    d0			a1

    BOOL BeginCardAccess( struct CardHandle * );

   FUNCTION
    This function should be called before you begin access
    to credit-card memory.

    Its effect will depend on the type of Amiga machine your
    code happens to be running on.  On some machines it
    will cause an access light to be turned ON.

   INPUTS
    handle - Same handle as that used when OwnCard() was called.

   RETURNS
    TRUE if you are still the owner of the credit-card, and
    memory access is permitted.  FALSE if you are no longer
    the owner of the credit-card (usually indicating that
    the card was removed).

   NOTES
    This function may be called from within a task, or from a level 1
    or level 2 interrupt.

    It is highly recommended that you call this function
    before accessing credit-card memory, as well as checking
    the return value.  If it is a return value of FALSE, you
    should stop accessing credit-card memory.

   SEE ALSO
    OwnCard(), EndCardAccess()


card.resource/CardAccessSpeed

   NAME
    CardAccessSpeed -- Select best possible memory access speed.

   SYNOPSIS
    result=CardAccessSpeed( handle, nanoseconds );
    d0			 a1      d0

    ULONG CardAccessSpeed( struct CardHandle *, ULONG );

   FUNCTION
    This function is used to set memory access speed for all CPU
    accesses to card memory.

    Typically this information would be determined by first examining
    the Card Information Structure.

    Then you would use this function to let the card.resource
    select the best possible access speed for you, however note
    that the range of possible access speeds may vary on some
    machines (depending on the type of credit-card interface
    hardware being provided).

   INPUTS
    handle - Same handle as that used when OwnCard() was called.

    nanoseconds - Preferred access speed in nanoseconds.

   RETURNS
    Speed - Access speed selected by resource (in nanoseconds).

    0  - Not successful.  Either because the credit-card was
    removed, or the access speed you requested is slower than
    that supported by the credit-card interface hardware.

   NOTES
    This function may be called from within a task, or from a level 1
    or level 2 interrupt.

   SEE ALSO
    OwnCard()


card.resource/CardChangeCount

   NAME
    CardChangeCount -- Obtain card change count.

   SYNOPSIS
    count = CardChangeCount( VOID )
    d0

    ULONG CardChangeChange( VOID );

   FUNCTION
    This function returns the card change count.  The
    counter is incremented by one for every removal, and
    for every successful insertion (a card which is inserted
    long enough to be debounced before it is removed again).

   RESULT
    The change count number.

   NOTES
    This function may be called from a task, or any level interrupt.

   SEE ALSO


card.resource/CardForceChange

   NAME
    CardForceChange -- Force a card change.

   SYNOPSIS
    success = CardForceChange( VOID )
    d0

    BOOL CardForceChange( VOID );

   FUNCTION
    This function is not intended for general use.  Its
    purpose is to force a credit-card change as if
    the user had removed, or inserted a card.

    This function is intended to be used by a utility program
    which needs to force the current card owner to release
    ownership of the card, thereby allowing the utility an
    opportunity to own the credit-card.

   RESULT
    TRUE if the function succeeded, FALSE if card change is
    not allowed.  This function will generally succeed, unless
    someone is using the card in reset remove mode at the time
    this function is called.

   NOTES
    This function should only be called from a task.

   SEE ALSO


card.resource/CardInterface

   NAME
    CardInterface -- Determine the type of card interface.

   SYNOPSIS
    return = CardInterface()
    d0

    ULONG CardInterface( void );

   FUNCTION
    This function is used to determine the type of credit-card
    (hardware) interface available.  For the most part the
    card.resource hides the hardware details from devices within its
    function calls.  However should we need to provide a work-around
    because of differences, or limitations imposed by future interface
    hardware, this function must be used to identify which interface
    is available.

   RETURN
    A ULONG value as defined in card.h/i.

   NOTES
    In general only I/O devices (e.g., a device which interfaces
    with a modem card) would need to provide work-arounds,
    or alternative code.  An example would be a change in the way
    interrupt requests from the card are handled.  Specific details
    will be provided as need in the future.  I/O devices) should abort
    properly if this function returns a value which is unknown.

    Current implementations (see card.h/i) -

    CARD_INTERFACE_AMIGA_0
    -------------------------------------------------------------

    The card slot can be configured for use as an I/O interface
    by using the CardMiscControl() function.

    The card slot inhibits writes to cards which do not negate
    the WP status bit.  This can be overridden by using the
    CardMiscControl() function.

    Changes in the interrupt request line are latched by a gate-array,
    and have to be obtained via the status change mechanism provided
    when you call the OwnCard() function.  The interrupt is cleared
    when you return from the status change interrupt.  A level 2
    interrupt is generated.  Usually you will want to clear the
    interrupt on the card at this time, and Signal() a task.  The IRQ
    line is the same as the RDY/BSY line.

    Changes in BVD1, WP, and RDY/BSY are also latched by the gate-array,
    and are obtainable via the status change mechanism provided by
    the OwnCard() function.  A level 2 interrupt is generated.

    Changes in BVD2 (also used for digital audio) have to be
    monitored via polling.  Generally this will cause no problem.
    Monitoring changes in BVD1 & BVD2 to monitor for low battery
    condition can be handled by a low priority tool which periodically
    checks the condition of both lines using the ReadCardStatus()
    function.

    As of card.resource V39 (check VERSION in resource base), the
    CardMiscControl() function can be used to enable/disable
    status change interrupts for changes in BVD1, BVD2, and the
    RDY/BSY status line.  Status change interrupts for WR
    (Write-protect enable/disable) are always enabled.  The default
    state of enabled/disabled status change interrupts noted above
    are unchanged, and automatically reset to the defaults when
    a card is removed, or when even a task releases ownership
    of the card.

    Some PC oriented eight (8) bit cards may require you read
    odd-byte I/O address registers at the corresponding even-byte
    address plus 64K.  There is sufficient I/O address space
    provided that exceeding I/O address space should not be a problem.

    Your code should wait at least 1 millisecond for Vpp to stabilize
    after voltage change (see CardProgramVoltage()).

    SEE ALSO
    CardMiscControl(), resources/card.i, resources/card.h


card.resource/CardMiscControl

   NAME
    CardMiscControl -- Set/Clear miscellaneous control bits

   SYNOPSIS
    control_bits=CardMiscControl( handle, control_bits );
    d0			 	a1      	d1

    UBYTE CardMiscControl( struct CardHandle *, UBYTE );

   FUNCTION
    Used to set/clear miscellaneous control bits (generally for
    use with I/O cards).

   INPUTS
    handle - Same handle as that used when OwnCard() was called.

    control_bits - A mask value of control bits to be turned on/off.

    The bit values which might be usable are defined in card.h/i.

    For example, to enable digital audio, and disable hardware
    write-protect (if supported), you would call this function with these
    values --

    CARDF_DISABLE_WP|CARDF_ENABLE_DIGAUDIO

    Then to turn off digital audio, but leave write-protect
    disable, you would use a value of --

    CARDF_DISABLE_WP

    Finally too reenable write protect, call this function with
    a mask value of 0.

   RETURNS
    control_bits - The same mask value you called this function
    with if successful.  If one, or more bits has been cleared
    in the return mask, this would indicate that the control bit
    is not being supported, or that the card has been removed
    by the user.

    For example, if you called this function with a mask value
    of --

    CARDF_DISABLE_WP|CARDF_ENABLE_DIGAUDIO

    And this function returned a value of --

    CARDF_DISABLE_WP

    This would indicate that it is not possible to enable digital
    audio (most likely because this feature has not been implemented).

   NOTES
    This function may be called from within a task, or from a level 1
    or level 2 interrupt.

    !!!IMPORTANT!!!

    You should ALWAYS try to enable digital audio for I/O cards
    as this will also configure the card socket for the I/O
    interface (if supported).

    Not all cards will connect the write-enable line (e.g.,
    some I/O cards).  On some machines (e.g., the A600) it will
    not be possible to write to such cards unless you disable
    write-protection by using this function.

    !!!NEW!!!

    For card.resource V39 (check resource base for VERSION before
    using), new bits have been defined which let you enable/disable
    particular status change interrupts.  See CardInterface() for
    defaults.  These new bits are backwards compatable with V37
    for which only the CARDB_DISABLE_WP, and CARDB_ENABLE_DIGAUDIO
    bits were defined.  These new bits allow you to enable, or
    disable specific status change interrupts including BVD1/SC,
    BVD2/DA, and BSY/IRQ.  The defaults for these status change
    interrupts are unchanged from V37, and WR (Write-protect) status
    change interrupts are always enabled as they use to be.

    An example of use:

    CARD_INTF_SETCLR!CARD_INTF_BVD1

    Would enable BVD1/SC status change interrupts, and not change
    the enable/disable state for BVD2/DA or BSY/IRQ status change
    interrupts.  If the change was made successfully, the
    CARD_INTB_BVD1 bit would be set in register D0 when this function
    returns.

   SEE ALSO
    CardInterface(), resources/card.h, resources/card.i


card.resource/CardProgramVoltage

   NAME
    CardProgramVoltage -- Set programming voltage.

   SYNOPSIS
    success=CardProgramVoltage( handle, voltage );
                    a1      d0

    LONG CardProgramVoltage( struct CardHandle *, ULONG );

   FUNCTION
    Used to set programming voltages (e.g., for FLASH-ROM/EPROM
    cards).

   INPUTS
    handle - Same handle as that used when OwnCard() was called.

    voltage - See card.i/h for valid values.

   RETURNS
    1  - Successful.

    0  - Not successful.  Most likely because the credit-card
    card has been removed, and you are no longer the owner.

    -1 - This function is not being supported.  On some machines
    with a minimal (hardware) credit-card interface, this feature
    may not be possible.

   NOTES
    This function may be called from within a task, or from a level 1
    or level 2 interrupt.

       !!!WARNING!!!

    Flash-ROM programming requires careful coding to prevent
    leaving the Erase command on too long.  Failure to observe
    the maximum time between the Erase command, and the Erase-Verify
    command can make a Flash-ROM card unusable.  Some Flash-ROM cards
    may provide an internal watch-dog timer which protects the card.

    Because of the relatively long time (e.g., 10ms) between Erase, and
    Erase-Verify which must be observed, the need for such critical
    timing can be problematic on a multi-tasking machine.

    Vendors of Flash-ROM's recommend a high priority interrupt
    generated by a 10ms timer be used to turn off Erase.  On the
    Amiga this can be accomplished by using a CIA-B interval timer.
    The timer.device also provides a mechanism for generating a low
    priority interrupt.  The timer.device is easier to use than CIA
    interval timers, though not as accurate or as safe.

    Even if the Flash-ROM card provides an internal watch-dog timer,
    implementation of the code during Erase should assume that
    the Flash-ROM does not.

   SEE ALSO
    OwnCard(), resources/card.h, resources/card.i


card.resource/CardResetCard

   NAME
    CardResetCard -- Reset credit-card.

   SYNOPSIS
    success=CardResetCard( handle );
                a1

    BOOL CardResetCard( struct CardHandle * );

   FUNCTION
    Used to reset a credit-card.  Some cards, such as some
    configurable cards can be reset.

    Asserts credit-card reset for at least 10us.

   INPUTS
    handle - Same handle as that used when OwnCard() was called.

   RETURNS
    TRUE  - Successful.

    FALSE  - Not successful.  Most likely because the credit-card
    card has been removed, and you are no longer the owner.

   NOTES
    This function may be called from within a task, or from a level 1
    or level 2 interrupt.

    ***IMPORTANT***

    It is the responsibility of the card owner to reset
    configurable cards, or any other type of card such as
    some I/O cards before calling ReleaseCard() if the owner
    has made use of that card such that it is no longer in its
    reset state (unless you are releasing the card because it
    has been removed).

    If the card manufacturer indicates that a certain amount
    of time must elapse between end of reset, and completion
    of card initialization, you should wait at least that long
    before releasing the card (unless you are releasing the card
    because it has been removed).

   SEE ALSO
    OwnCard(), ReleaseCard()


card.resource/CardResetRemove

   NAME
    CardResetRemove -- Set/Clear reset on card removal.

   SYNOPSIS
    success=CardResetRemove( handle, flag );
                 a1      d0

    BOOL CardResetRemove( struct CardHandle *, ULONG );

   FUNCTION
    Used to set/clear HARDWARE RESET on card change detect.

    This function should generally not be used by devices
    which support HOT-REMOVAL.  HARDWARE RESET on removal
    is generally intended for execute-in-place software, or
    ram cards whose memory has been added as system ram.

   INPUTS
    handle - Same handle as that used when OwnCard() was called.

    flag - TRUE if you want to SET HARDWARE RESET on credit
           card removal.  FALSE if you want to CLEAR HARDWARE
           RESET.

   RETURNS
    1  - Success.

    0  - Function failed (most likely because the card was removed
         by the user, and you are no longer the owner of the card).

    -1 - This function is not being made available.

   NOTES
    This function should only be called from a task.

   SEE ALSO
    OwnCard()


card.resource/CopyTuple

   NAME
    CopyTuple -- Find/copy a credit card tuple.

   SYNOPSIS
    success = CopyTuple( CardHandle, buffer, tuplecode, size );
    d0			a1	 a0	 d1	    d0

    BOOL CopyTuple( struct CardHandle *, UBYTE *, ULONG, ULONG );

   FUNCTION
    This function scans credit-card memory for a tuple, and
    if found, copies it into a supplied buffer.  The entire
    tuple (including the tuple code, and link) are copied to
    the supplied buffer.  The number of bytes copied to the
    buffer will be 2 bytes, plus the argument "size", or the
    value in the tuple LINK field (whichever is SMALLER).

    The software calling this function is responsible for
    examining the copy of the tuple (e.g., recognition of
    fields, recognition of stop bytes, etc. within the tuple).

    This function does the best job it can to find a tuple
    in attribute, or common memory.  It follows tuple chains,
    and skips odd bytes in attribute memory.

    This function monitors for credit-card removal while reading data.
    If the credit-card is removed while a byte is being read, it will
    stop searching, and return FALSE.

    This function does not protect against another task writing
    to credit-card memory while data is being read.  The device
    is responsible for single-threading reads/writes to the
    credit card as needed.

    This function can be used to find multiple tuple codes; this
    is a very rare case, so the mechanism provided for doing so is
    unusual.  See INPUTS below for more information.

    This function does not read bytes within the body of any tuples
    except for the tuple you want copied, and the basic compatibility
    tuples this function understands (see list below).

    On some machines this function may slow down memory access
    speed while reading the tuple chain.  This is done to prevent
    potential problems on slow cards.  By examining the CISTPL_DEVICE,
    and CISTPL_DEVICE_A tuples, you can determine the best possible
    memory access speed for the type of card inserted.  Because memory
    access speed may be slowed down, calls to this function should
    be single-threaded.

    The Card Information Structure must start with a CISTPL_DEVICE
    tuple stored as the first tuple in attribute memory.  If not,
    this function will search for a CISTPL_LINKTARGET tuple
    stored at byte 0 of common memory.  Therefore it is possible
    to store a CIS on cards which do not have any writeable
    attribute memory, though this may cause problems for other
    software implemented on other machines.  For example, some
    SRAM cards do not come with writeable attribute memory, and/or
    some may have OPTIONAL EEPROM memory which may not have been
    initialized by the card manufacturer.  While it could be
    argued that such cards do not conform to the PCMCIA PC Card
    Standard, such cards are cheaper, and therefore likely to be
    used.

   INPUTS
    CardHandle - Same handle as that used when OwnCard() was
    called.

    buffer - Pointer to a buffer where the tuple will be copied.

    The buffer should be at least as large as "size" + 8 (see
    use of "size" argument below).  Therefore the minimum buffer
    size is 8 bytes.  See NOTES below.

    tuplecode - The tuple code you want to search for.  This is
    a ULONG value.  The upper 16 bits should be 0, or a number between
    1-32K where a value of 0 means you want to find the first tuple
    match, a value of 1 the second, etc.  For example -

    0x41 means find the FIRST tuple equal to $41.

    ((1<<16)|(0x41)) means find the SECOND tuple equal to $41.

    ((2<<16)|(0x41)) means find the THIRD tuple equal to $41.

    size - The maximum number of bytes you want copied (not
           including the tuple code, and link).  The actual number
           of bytes copied may be less than "size" if the tuple
           link field is less than "size".

           A size of 0 will result in only the tuple code, and
           link being copied to your buffer if the tuple is found.

           If you do not care how many bytes are copied, any unsigned
           value of 255 or greater will do.  In this case a maximum
           of 257 bytes might be copied to your buffer (if the
           tuple link field is the maximum of 255).

           Other sizes are useful if you know the size of the tuple
           you want copied, or you know there are active registers
           stored within the tuple, and only want to copy a portion
           of a tuple.

   RETURNS

    TRUE if the tuple was found, and copied, else FALSE.
    This function may also return false if the CIS is believed
    to be corrupt, or if the card is removed while reading the
    tuples.

   NOTES

    This function can be called multiple times (adjusting the "size"
    argument) to read a tuple of variable length, or unknown size.

    Your supplied buffered is used by this function for working
    storage - the contents of it will be modified even if this
    function fails to find the tuple you want a copy of.

    This function should NOT be used to find/copy tuples of type :

    - CISTPL_LONGLINK_A
    - CISTPL_LONGLINK_C
    - CISTPL_NO_LINK
    - CISTPL_LINKTARGET
    - CISTPL_NULL
    - CISTPL_END

    These tuples are automatically handled for you by this function.

   SEE ALSO
    OwnCard()


card.resource/DeviceTuple

   NAME
    DeviceTuple -- Decode a device tuple

   SYNOPSIS
    return=DeviceTuple( tuple_data, storage)
                   a0		a1

    ULONG DeviceTuple( UBYTE *, struct DeviceTData *);

   FUNCTION
    Extracts SIZE, TYPE, and SPEED from a device tuple (generally
    obtained with CopyTuple()).

   INPUTS
    tuple_data - Pointer to a CISTPL_DEVICE tuple (generally obtained
    with CopyTuple()).

    storage - Pointer to a DeviceTData structure in which results
    are to be stored.

    struct	DeviceTData {
        ULONG	dtd_DTsize;		/* Size of card (bytes)	*/
        ULONG	dtd_DTspeed;		/* Speed in nanoseconds	*/
        UBYTE	dtd_DTtype;		/* Type of card		*/
        UBYTE	dtd_DTflags;		/* Other flags		*/
    };

   RETURN
    SIZE (same as dtd_DTsize) if the Device Tuple could be decoded.
    FALSE (0) if the tuple is believed to be invalid.  The tuple is
    considered to be invalid if:

        The tuple link value is 0.

        The device type/speed byte is $00, or $FF.

        The device type is DTYPE_EXTEND, which is undefined
        as of this writing.

        The extended speed byte is a value which is
        undefined as of this writing.

        The extended speed byte is extended again which is
        undefined as of this writing.

        The device Size byte is $FF.

   NOTES
    Some cards may not have a size specified in the device
    tuple.  An example would be an I/O card.  The size would be
    returned as one (1) in this case.

    You should not call this function with a partial CISTPL_DEVICE
    tuple, or the return values may be junk.

   SEE ALSO
    CopyTuple(), resources/card.h, resources/card.i


card.resource/EndCardAccess

   NAME
    EndCardAccess -- Called at the end of credit-card memory access

   SYNOPSIS
    result=EndCardAccess( handle )
    d0			a1

    ULONG EndCardAccess( struct CardHandle * );

   FUNCTION
    This function should be called when you are done accessing
    credit-card memory.

    Its effect will depend on the type of Amiga machine your
    code happens to be running on.  On some machines it
    will cause an access light to be turned OFF in approximately
    1/2 second.

    On machines which support an access light, the light will
    automatically be turned off when you call ReleaseCard().

   INPUTS
    handle - Same handle as that used when OwnCard() was called.

   RETURNS
    TRUE if you are still the owner of the credit-card.  FALSE
    if you are no longer the owner of the credit-card (usually
    indicating the card was removed).

   NOTES
    This function may be called from within a task, or from a level 1
    or level 2 interrupt.

    It is highly recommended that you call this function
    after accessing credit-card memory, as well as checking
    the return value.  If it is a return value of FALSE, you
    should stop accessing credit-card memory, and conclude
    that the card was removed before this function was called.

    On some machines it is possible that the credit-card will be
    removed before you receive the removed interrupt.

   SEE ALSO
    OwnCard(), ReleaseCard(), BeginCardAccess()


card.resource/GetCardMap

   NAME
    GetCardMap -- Obtain pointer to CardMemoryMap structure

   SYNOPSIS
    pointer=GetCardMap()
    d0

    struct CardMemoryMap *GetCardMap( void );

   FUNCTION
    Obtain pointer to a CardMemoryMap structure.  The structure
    is READ only.

    Devices should never assume credit-card memory appears
    at any particular place in memory.  By using this function
    to obtain pointers to the base memory locations of the various
    credit-card memory types, your device will continue to work
    properly should credit cards appear in different memory
    locations in future hardware.

   RETURNS
    Pointer to CardMemoryMap structure -

        struct CardMemoryMap {
        UBYTE	*cmm_CommonMemory;
        UBYTE	*cmm_AttributeMemory;
        UBYTE	*cmm_IOMemory;
        };

    As of card.resource V39, this structure has been extended to
    include the size of these memory regions.  See card.h/card.i
    for the new fields.  If card.resource V39, use the constants
    in the CardMemoryMap structure rather than hard coded constants
    for memory region size.

   NOTES
    If any pointer in the structure is NULL, it means this type
    of credit-card memory is not being made available.

   SEE ALSO
    resources/card.h, resources/card.i


card.resource/IfAmigaXIP

   NAME
    IfAmigaXIP -- Check if a card is an Amiga execute-in-place card.

   SYNOPSIS
    result=IfAmigaXIP( handle )
    d0		       a2

    struct Resident *IfAmigaXIP( struct CardHandle * );

   FUNCTION
    Check to see if a card in the slot is an Amiga execute-in-place
    card.  The Card Information Structure must have a valid
    CISTPL_AMIGAXIP tuple.

    Tuples can be treated like structures.  The format of a
    CISTPL_AMIGAXIP tuple is -

     struct TP_AmigaXIP {
        UBYTE	TPL_CODE;
        UBYTE	TPL_LINK;
        UBYTE	TP_XIPLOC[4];
        UBYTE	TP_XIPFLAGS;
        UBYTE	TP_XIPRESRV;
    };

    The TPL_CODE field must be equal to CISTPL_AMIGAXIP (0x91).

    The TPL_LINK field must be equal to the length of the body
    of a CISTPL_AMIGAXIP tuple (0x06).

    The TP_XIPLOC array is the memory location of your ROM-TAG
    stored in little-endian order.  This value is stored as an
    "offset" into common memory as is the standard for storing 32 bit
    bit pointers in tuples.

    For example, a pointer to a ROM-TAG stored at an offset of
    0x00000200 would be stored as four bytes like so:

        0x00, 0x02, 0x00, 0x00

    Currently credit-card common memory is mapped starting at
    memory location 0x600000.  Because a ROM-TAG is used,
    it is implied that execute-in-place code can be compiled/linked
    to use absolute references.  It is believed that most developers
    will not want to have to write pc-relative code only.

    The TP_XIPFLAGS field is treated as a set of flag bits.
    See card.i/h for defined bits.  All undefined bits MUST be
    0.

    The TP_XIPRESRV field must be 0 for now.

    The system polls for cards which have a CISTPL_AMIGAXIP tuple
    at the same time that it searches for devices to boot off.
    When a card with a valid CISTPL_AMIGAXIP tuple is found, the
    system will call your ROM-TAG via Exec's InitResident() function.

    The system examines the return code from InitResident().  A
    NULL return in D0 means you are done with the card, and it can
    be removed by the user.  A successful return indicates you are
    still using the card.  Some programs (e.g., some games) may
    never return.  The only requirement is that if you do return,
    you must leave the system in a "good" state (including returning
    most of, or all the memory you allocated).  The standard
    convention for preserving registers apply.

    Note that your execute-in-place code will not be called
    a second time, unless you have returned a non-successful
    result.  In this case your execute-in-place code MUST
    assume the user can remove, and insert your card again.
    There are a variety of ways to check for re-insertion
    (e.g., search for a message port, device, library, task,
    etc., that you created).

    Note that your execute-in-place code runs in an environment
    similar to boot block games; before DOS has been initialized!

    Your execute-in-place code should NOT try to initialize DOS
    because DOS requires a suitable disk-like device be at
    the head of the expansion base mountlist to boot off.

    If you need DOS, it is possible to boot off a credit-card using
    carddisk.device.  Such cards will require a valid
    CISTPL_DEVICE tuple, and CISTPL_FORMAT tuple.  A portion
    of the card can be used for a minimal number of data blocks
    like the method described above.

    However this method is not recommended, though it is anticipated
    that some developers will have thought of, and used this
    method anyway.  If you must do this, at least use the
    CardHandle returned by OwnCard() to set hardware reset
    on removal else the machine will likely crash anyway if
    the card is removed while your execute-in-place code is running.

   RETURNS
    Pointer to a ROM-TAG on the card, or NULL indicating that:

    o The card does not meet the above requirements, or
    o The card has been removed, or
    o You are not the owner of the credit-card.

   NOTES
    This function is being made public so developers can test
    test that their execute-in-place credit-cards meet the
    requirements for an Amiga execute-in-place card.  In general
    there is no reason for devices, or applications to use this
    function.

    Amiga execute-in-place software is identified via a tuple code
    reserved for manufacturer specific use, therefore the manufacturer
    of the card may freely use the CISTPL_VERS_1, or CISTPL_VERS_2
    tuples to place identification information on the credit-card.

    No attempt has been made to make use of the MS-DOS execute-in-place
    method; it is believed that most manufacturers of Amiga
    execute-in-place software will prefer a simple, and small
    scheme for running their execute-in-place code.

   SEE ALSO
    OwnCard(), resources/card.h, resources/card.i


card.resource/OwnCard

   NAME
    OwnCard -- Own credit card registers, and memory

   SYNOPSIS
    return = OwnCard( handle )
    d0		a1

    struct CardHandle *OwnCard( struct CardHandle * );

   FUNCTION
    This function is used to obtain immediate, or deferred
    ownership of a credit-card in the credit-card slot.

    Typically an EXEC STYLE DEVICE will be written to interface
    between an application, and a credit card in the slot.  While
    applications, and libraries can attempt to own a credit-card
    in the card slot, the rest of this documentation assumes a
    device interface will be used.

    Because credit-cards can be inserted, or removed by the user at
    any time (otherwise known as HOT-INSERTION, and HOT-REMOVAL),
    the card.resource provides devices with a protocol which
    lets many devices bid for ownership of a newly inserted card.

    In general, devices should support HOT-REMOVAL, however there
    are legitimate cases where HOT-REMOVAL is not practical.  For
    these cases this function allows you to own the resource using
    the CARDB_RESETREMOVE flag.  If the card is removed before your
    device calls ReleaseCard(), the machine will RESET.

   INPUTS
    handle - pointer to a CardHandle structure.

        struct CardHandle {
        struct Node 		 cah_CardNode;
        struct Interrupt	*cah_CardRemoved;
        struct Interrupt	*cah_CardInserted;
        struct Interrupt	*cah_CardStatus;
        UBYTE			 cah_CardFlags;
        };

    The following fields in the structure must be filled
    in by the application before calling OwnCard() -

    cah_CardNode.ln_Pri -

        See table below.  The Node field is used by the resource to
        add your handle to a sorted list of CardHandle structures.
        This list is used by the resource to notify devices when the
        device owns the credit-card.

        Your device will only be notified (at most) one time
        per card insertion, and perhaps less often if some
        higher priority device on the notification list retains
        ownership of a card in the slot.

    Priority	Comments
    --------------------------------------------------
        >= 21	Reserved for future use

        10-20	To be used by third party devices (e.g.,
            I/O CARD manufacturers) which look for
            specific card tuples to identify credit-cards.

        01-19	Reserved for future use

        00	To be used by general purpose devices which
            have loose card specification requirements.

        <= -1	Reserved for future use

    cah_CardNode.ln_Type -

        Must be set to 0 for now.  This field may be used in the
        future to identify an extended CardHandle structure.

    cah_CardNode.ln_Name -

        Must be initialized to NULL, or name of device which owns
        this structure.

    cah_CardRemoved -

        Pointer to an initialized interrupt structure.  Only the
        is_Data, and is_Code fields need to be initialized.  This
        is the interrupt code which will be called when a credit-card
        which your device owns is removed.  Once you receive this
        interrupt, all credit-card interface control registers are
        reset (e.g., programming voltage, access speed, etc.), and
        you should stop accessing the card as soon as possible.

        Because your code is called on interrupt time, you
        should do the least amount possible, and use little
        stack space.

        This pointer can be NULL if you have asked for reset
        on card-removal, and you never turn reset off.

    cah_ CardInserted -

        Pointer to an initialized interrupt structure.  Only the
        is_Data, and is_Code fields need to be initialized.  This
        is the code which will be called when your CardHandle owns
        the credit-card in the slot.

        Note that your code may be called on the context of
        an interrupt, or a task in FORBID, therefore you should
        do the least amount possible, and use little stack space.

        Note that it is possible to receive a card removed
        interrupt immediately before you receive this interrupt if
        the card is removed while your CardInserted interrupt
        is being called.

        Your device owns the credit-card until the card is manually
        removed by the user, or you release the card by calling
        ReleaseCard().

        Your device should examine the card in the slot (e.g., look
        for specific tuples), and decide if the card is of a type your
        device understands.

        If not, release ownership of the card by calling
        ReleaseCard() so that other devices will be given a chance to
        examine the current card in the credit-card slot.

    cah_CardStatus -

        Pointer to an initialized interrupt structure.  Only the
        is_Data, and is_Code fields need to be initialized.

        Note that your code will be called on the context of
        an interrupt, therefore you should do the least
        amount possible, and use little stack space.

        Note that it is possible to receive a card removed
        interrupt immediately before you receive this interrupt
        if the card is removed during this interrupt.

        If this pointer is NULL, you will not receive card status
        change interrupts.

        Your interrupt code will be called with a mask value in
        register D0, and a pointer to your data in A1.

        The mask value in D0 can be interpreted using the same bit
        definitions returned by ReadCardStatus().  Note that more
        than one bit may be set, and the mask only tells you what has
        changed, not the current state.

        Use ReadCardStatus() if you need to determine the current
        state of the status bits.

        Not all status change interrupts will necessarily be
        enabled on all systems.  For example, on some systems
        BVD2/DA status change interrupts will not be enabled so
        that digital audio can occur without generating many
        interrupts.  Status change interrupts are typically meant
        to be used for monitoring BSY/IRQ, WR, and BVD1/SC.  Battery
        voltage low detection would best be done by a separate
        utility which periodically polls BVD1 & BVD2 by using the
        ReadCardStatus() function.

        Typically the mask value in D0 MUST be returned unchanged
        on exit from your code.  The return value in D0 is then used
        to clear the source(s) of the interrupt.

        In the rare case that you need to keep a status change
        interrupt active, clear the appropriate bit(s) in D0 before
        returning via RTS.  Clear no bits other than those defined
        as valid bits for ReadCardStatus()!

        !!!NEW FOR V39!!!

        See definition of CARDB_POSTSTATUS below.

    cah_CardFlags -

        Optional flags (all other bits must be 0).

        - CARDB_RESETREMOVE means you want the machine to
          reset if the credit-card in the slot is removed
          while you own the credit-card.

        - CARDB_IFAVAILABLE means you only want ownership of
          the credit-card in the slot if it is immediately
          available.

        If it is available, your CardHandle structure will be added
        to a list so that you can be notified via an interrupt when
        the credit-card is removed by the user.

        If the credit-card is not immediately available (either
        because there is no credit-card in the slot, or because some
        other device owns the credit-card), your CardHandle structure
        will NOT be added to the notification list.

        - CARDB_DELAYOWNERSHIP means you never want a successful
          return from OwnCard() even if the credit-card is
          available.  Rather you will be notified of ownership
          via your cah_CardInserted interrupt.  If you use this flag,
          OwnCard() will always return -1.  This flag cannot be used
          with the CARDB_IFAVAILABLE flag.

        - CARDB_POSTSTATUS is new for V39 card.resource (check
          resource base VERSION before using).  It is meant to be
          used by drivers which want to service the card hardware
          AFTER the status change interrupt has been cleared on the
          gate array.  Previously a PORTS interrupt server had
          to be added to do this; this is somewhat more efficient, and
          easier to use.  Your status change interrupt is first called
          with status change bits in register D0.  You would examine
          these bits, and set a flag(s) for the POST callback.  When
          you return from the status change interrupt, the interrupt
          on the gate array is cleared (based on what you return in
          register D0), and your status change interrupt is immediately
          called again, but this time with 0 in D0.  The value you
          return in D0 for the POST callback case is ignored.

    ALL other fields are used by the resource, and no fields in the
    structure may be modified while the structure is in use by the
    resource.  If you need to make changes, you must remove your
    CardHandle (see ReleaseCard()), make the changes, and then call
    OwnCard() again.

   RESULTS
     0  - indicates success, your device owns the credit card.

    -1  - indicates that the card cannot be owned (most likely
          because there is no card in the credit card slot).

    ptr - indicates failure.  Returns pointer to the CardHandle
          structure which owns the credit card.

   NOTES
    This function should only be called from a task.

      CardHandle interrupts are called with a pointer to your data
    in A1, and a pointer to your code in A5.  With the exception
    of status change interrupts, D0-D1, A0-A1, and A5-A6 may be
    treated as scratch registers.  Status change interrupts are
    also called with meaningful data in D0, and expect D0 be
    preserved upon RTS from your code.  No other registers are
    guaranteed to contain initialized data.  All other registers
    must be preserved.

    SEE ALSO
    ReleaseCard(), ReadCardStatus(), resources/card.i, resources/card.h


card.resource/ReadCardStatus

   NAME
    ReadCardStatus -- Read credit card status register

   SYNOPSIS
    status=ReadCardStatus()
    d0

    UBYTE ReadCardStatus( void );

   FUNCTION
    Returns current state of the credit card status register.

    See card.h/i for bit definitions.

    Note that the meaning of the returned status bits may vary
    depending on the type of card inserted in the slot, and
    mode of operation.  Interpretation of the bits is left
    up to the application.

   RETURNS
    A UBYTE value to be interpreted as status bits.

   NOTES
    This function may be called from within a task, or from any level
    interrupt.

   SEE ALSO
    resources/card.h, resources/card.i


card.resource/ReleaseCard

   NAME
    ReleaseCard -- Release ownership of credit card

   SYNOPSIS
    ReleaseCard( handle, flags )
             a1	     d0

    void ReleaseCard( struct CardHandle *, ULONG );

   FUNCTION
    This function releases ownership of the credit card in the
    slot.

    The access light (if any) is automatically turned off
    (if it was turned on) when you release ownership of
    a card you owned, and all credit-card control registers
    are reset to their default state.

    You must call this function if -

    You own the credit-card, and want to release it so that
    other devices on the notification list will have a chance
    to examine the credit-card in the card slot.

    You took a Card Removed interrupt while you owned the
    credit-card.  If so, you MUST call this function, else
    no other task will be notified of newly inserted cards.  On
    some machines the credit-card interface hardware may also
    be left disabled until you respond to the card removed interrupt
    by calling this function.

    You want to remove yourself from the notification list (see
    optional flags below).

   INPUTS
    handle - Same handle as that used when OwnCard() was called.

    flags - Optional flags.

        - CARDB_REMOVEHANDLE means you want remove your
        CardHandle structure from the notification list
        whether or not you currently own the credit-card
        in the card slot.  The node structure in your
        CardHandle will be removed from the notification
        list, and ownership will be released if you were
        the owner of the card.

   NOTES
    This function should only be called from a task.

    SEE ALSO
    OwnCard(), resources/card.i, resources/card.h


cd.doc

     CD_ADDCHANGEINT
     CD_ADDFRAMEINT
     CD_ATTENUATE
     CD_CHANGENUM
     CD_CHANGESTATE
     CD_CONFIG
     CD_EJECT
     CD_GETGEOMETRY
     CD_INFO
     CD_MOTOR
     CD_PAUSE
     CD_PLAYLSN
     CD_PLAYMSF
     CD_PLAYTRACK
     CD_PROTSTATUS
     CD_QCODELSN
     CD_QCODEMSF
     CD_READ
     CD_READXL
     CD_REMCHANGEINT
     CD_REMFRAMEINT
     CD_SEARCH
     CD_SEEK
     CD_TOCLSN
     CD_TOCMSF
     CloseDevice()
     OpenDevice()


cd.device/CD_ADDCHANGEINT

   NAME
       CD_ADDCHANGEINT -- add a disk change software interrupt handler.

   FUNCTION
       This command lets you add a software interrupt handler to the
       disk device that gets invoked whenever a disk insertion or removal
       occurs.

       You must pass in a properly initialized Exec Interrupt structure
       and be prepared to deal with disk insertions/removals immediately.
       The interrupt is generated by the exec Cause function, so you must
       preserve A6.

       To set up the handler, an Interrupt structure must be initialized.
       This structure is supplied as the io_Data to the CD_ADDCHANGEINT
       command.  The handler then gets linked into the handler chain and
       gets invoked whenever a disk change happens.  You must eventually
       remove the handler before you exit.

       This command only returns when the handler is removed. That is,
       the device holds onto the IO request until the CD_REMCHANGEINT command
       is executed with that same IO request.  Hence, you must use SendIO()
       with this command.

   IO REQUEST INPUT
       io_Device       preset by the call to OpenDevice()
       io_Unit         preset by the call to OpenDevice()
       io_Command      CD_ADDCHANGEINT
       io_Length       sizeof(struct Interrupt)
       io_Data         pointer to Interrupt structure

   IO REQUEST RESULT
       io_Error - 0 for success, or an error code as defined in
                  <devices/cd.h>

   SEE ALSO
       CD_REMCHANGEINT, <devices/cd.h>, <exec/interrupts.h>,
       exec.library/Cause()


cd.device/CD_ADDFRAMEINT

   NAME
       CD_ADDFRAMEINT -- add a CD-frame software interrupt handler.

   IO REQUEST
       io_Device       preset by the call to OpenDevice()
       io_Unit         preset by the call to OpenDevice()
       io_Command      CD_ADDFRAMEINT
       io_Length       sizeof(struct Interrupt)
       io_Data         pointer to Interrupt structure

   RESULTS
       io_Error        0 for success, or an error code as defined in
                       <devices/cd.h>

   FUNCTION
       This command lets you add a software interrupt handler to the
       disk device that gets invoked whenever a new frame is encountered
       while CD audio is being played.

       You must pass in a properly initialized Exec Interrupt structure
       and be prepared to deal with frame interrupts immediately.
       The interrupt is generated by the exec Cause function, so you must
       preserve A6.

       To set up the handler, an Interrupt structure must be initialized.
       This structure is supplied in io_Data of the CD_ADDFRAMEINT
       command.  The handler then gets linked into the handler chain and
       gets invoked whenever a frame event occurs.  You must eventually
       remove the handler before you exit.

       This command only returns when the handler is removed. That is,
       the device holds onto the IO request until the CD_REMFRAMEINT command
       is executed with that same IO request.  Hence, you must use SendIO()
       with this command.

   NOTES
       The interrupt handler can be added before or after a play command is
       sent.  Interrupts will only be generated while CD audio is playing.
       Interrupts will not be generated when audio is paused.

   SEE ALSO
       CD_REMFRAMEINT, <devices/cd.h>, <exec/interrupts.h>,
       exec.library/Cause()


cd.device/CD_ATTENUATE

   NAME
       CD_ATTENUATE -- Attenuate CD audio volume (immediately or gradually)

   IO REQUEST
       io_Device       preset by the call to OpenDevice()
       io_Unit         preset by the call to OpenDevice()
       io_Command      CD_ATTENUATE
       io_Data         NULL
       io_Length       duration of volume fade in frames
       io_Offset       target volume level (0 - 0x7FFF) (-1 = status only)

   RESULTS
       io_Error        Returns an error if drive does not support attenuation
       io_Actual       current volume level (fade may be monitored)

   FUNCTION
       This command will ramp the CD audio volume up or down from its
       current value to the value contained in io_Offset.  The range is 0
       (silence) to 0x7FFF (full volume).  If -1 is specified as the target,
       the attenuation will not be modified; the current attenuation value
       will be returned in io_Actual.

       io_Length contains the duration of the fade.  In seconds, this is
       io_Length divided by the current frame rate (usually 75).

       Note that this command returns before the fade has completed.  Thus,
       once started, a fade cannot be aborted.  You can, however, send a
       new CD_ATTENUATE command, which will immediately override any fade
       currently in progress.  An io_Length of zero means attenuate
       immediately.

       If a gradual attenuation command is sent before the play command, the
       fade will begin as soon as the play command is sent.

   EXAMPLE

   NOTES
       This command has no effect on Amiga audio volume, only CD audio.

       If the drive does not support volume attenuation, but does support
       mute, a value of under $0800 should be considered mute, and equal
       to or above should be full volume.  If chunky attenuation is
       supported, the drive should do the best it can.  If the drive does
       not support volume attenuation at all, an error should be returned.
       Even if only mute is supported, if gradual attenuation is requested,
       the device should still emulate the fade command and mute based on
       the $0800 boundary.

   BUGS

   SEE ALSO
       CD_INFO


cd.device/CD_CHANGENUM

   NAME
       CD_CHANGENUM -- return the current value of the disk-change counter.

   FUNCTION
       This command returns the current value of the disk-change counter
       The disk change counter is incremented each time a disk is inserted
       or removed from the cd unit.

   IO REQUEST INPUT
       io_Device       preset by the call to OpenDevice()
       io_Unit         preset by the call to OpenDevice()
       io_Command      CD_CHANGENUM

   IO REQUEST RESULT
       io_Error - 0 for success, or an error code as defined in
                  <devices/cd.h>
       io_Actual - if io_Error is 0, this contains the current value of the
                   disk-change counter.


cd.device/CD_CHANGESTATE

   NAME
       CD_CHANGESTATE -- check if a "valid" disk is currently in a drive.

   FUNCTION
       This command checks to see if there is a "valid" disk in a drive.

   IO REQUEST INPUT
       io_Device       preset by the call to OpenDevice()
       io_Unit         preset by the call to OpenDevice()
       io_Command      CD_CHANGESTATE

   IO REQUEST RESULT
       io_Error - 0 for success, or an error code as defined in
                  <devices/cd.h>
       io_Actual - 0 means there is a disk while anything else indicates
                   there is no disk.

   NOTES
       A "valid" disk is a disk with a readable table of contents.


cd.device/CD_CONFIG

   NAME
       CD_CONFIG -- Set drive preferences

   IO REQUEST
       io_Device       preset by the call to OpenDevice()
       io_Unit         preset by the call to OpenDevice()
       io_Command      CD_CONFIG
       io_Data         pointer to first entry of TagList
       io_Length       0

   RESULTS
       io_Error        0 for success, or an error code as defined in
                       <devices/cd.h>

   FUNCTION
       This command sets one or more of the configuration items.
       The configuration items are:

       TAGCD_PLAYSPEED                 Default: 75
       TAGCD_READSPEED                 Default: 75 (do not count on this)
       TAGCD_READXLSPEED               Default: 75
       TAGCD_SECTORSIZE                Default: 2048
       TAGCD_XLECC                     Default: 1 (on)
       TAGCD_EJECTRESET                Default: can be 0 (off) or 1 (on)

       The speed settings are described in the number of frames (sectors)
       per second.  All CD-ROM drives are capable of the 75 frames/second
       rate.  Some drives are capable of 150 frames/second, and some even
       more.  To determine the maximum frame rate of the drive, use the
       CD_INFO command.  Valid values for caddyless Commodore CD-ROM drives
       are 75 and 150 (normal speed and double speed).  All other values are
       invalid.  You should always make sure the drive is capable of the
       configuration you are requesting by either using the CD_INFO command,
       and/or by checking for an error condition after submitting your
       request.

       There are three different types of CD-ROM sectors.  Mode 1 sectors
       (2048 bytes), mode 2 form 1 sectors (2048 bytes), and mode 2 form 2
       sectors (2328 bytes).  Normally, disks are encoded in Mode 1 format.
       Mode 2 form 1 is basically the same as mode 1; however, the mode 2
       form 2 sector format contains no CD-ROM error correction information.
       In order to read information encoded in this sector format, the
       drive's sector size must be configured to 2328 byte sectors.

       Error correction (ECC) of the READXL command can be turned off or
       on with this command.  Error correction can be implemented in either
       hardware or software (depending on the CD-ROM drive).  When ECC is
       implemented in software, CPU usage can become bursty.  Errors rarely
       occur on CDs unless they have numerous scratches, but when they do
       occur, they will cause a loss of CPU bandwith.  When ECC is
       implemented in hardware, no CPU bandwidth is lost -- in this case,
       ECC will always be on no matter how you configure the drive because
       it is free.  The READXL command is used primarily for displaying
       movie-like data.  In this case, speed is essential and data integrety
       is not; however, if the CPU is not being utilized during an XL
       animation there is no need to disable ECC (since the bandwidth is
       there to be used).  The only time ECC should be disabled is when you
       are doing intense calculations in the background of a READXL command,
       AND your program is time-critical.  Do not forget to change this back
       when you are done!

       To make the computer reset when a CD is ejected (for an application
       that does not exit), use the TAGCD_EJECTRESET tag.  When possible,
       titles should be able to exit cleanly back to Workbench.  Error
       conditions should be monitored when doing disk I/O.

   EXAMPLE
       /* Configure ReadXL for double-speed reading and turn off ECC when */
       /* the ReadXL command is used.                                     */

       struct TagItem ConfigList[] = {

           { TAGCD_READXLSPEED, 150 },
           { TAGCD_XLECC,       0   },
           { TAG_END,           0   }
           };

           ior->io_Command = CD_CONFIG;
           ior->io_Data    = (APTR)&ConfigList;
           ior->io_Length  = 0;
           DoIO(ior);

           if (ior->io_Error) printf("Could not be configuredn");

   NOTES
       Setting the configuration will not modify the behavior of a read or
       play command already in progress.

       This can be a very dangerous command.  If for instance you set
       TAGCD_SECTORSIZE to 2328, you will no longer be able to read any
       data encoded at 2048 byte sectors (e.g. the file system will not be
       able to read the disk anymore).  After you read any data stored with
       this sector format, you should immediately configure back to the
       original default value (even if the read failed -- the disk could
       be removed in the middle of your read).  You should NEVER use this
       command if you are not the exclusive owner of your disk.

   BUGS
       TAG_IGNORE, TAG_MORE, and TAG_SKIP do not work.  Do not use these.

       When switching speeds from single to double (or double to single),
       If the drive is prefetching in single-speed the data you are going
       to use in double-speed, the drive will not switch to double-speed
       (and visa versa).  To avoid this problem, switch to the desired speed,
       begin reading at least 4k into the data (just read two bytes), then
       begin reading at the beginning.  This will force the prefetch buffer
       to clear and issue a new read command with the desired speed.
       (Fixed in 40.24).

   SEE ALSO
       CD_INFO, <utility/tagitem.h>


cd.device/CD_EJECT

   NAME
       CD_EJECT -- Open or close the CD's drive door

   IO REQUEST
       io_Command      CD_EJECT
       io_Data         NULL
       io_Length       requested state of drive door (0 == close, 1 == open)
       io_Offset       0

   RESULTS
       io_Error        0 for success, or an error code as defined in
                       <devices/cd.h>
       io_Actual       previous state of drive door

   FUNCTION
       This command causes the CD-ROM drive's door to open or close.
       The desired state of the drive door is placed in io_Length.  The
       previous state of the drive door is returned in io_Actual.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO


cd.device/CD_GETGEOMETRY

   NAME
       CD_GETGEOMETRY -- return the geometry of the drive.

   FUNCTION
       This command returns a full set of information about the
       layout of the drive. The information is returned in the
       DriveGeometry structure pointed to by io_Data.

   IO REQUEST INPUT
       io_Device       preset by the call to OpenDevice()
       io_Unit         preset by the call to OpenDevice()
       io_Command      CD_GETGEOMETRY
       io_Data         pointer to a DriveGeometry structure
       io_Length       sizeof(struct DriveGeometry)

   IO REQUEST RESULT
       io_Error  - 0 for success, or an error code as defined in
                   <devices/cd.h>
       io_Actual - length of data transferred.

   SEE ALSO
       CD_GETNUMTRACKS, <devices/trackdisk.h>


cd.device/CD_INFO

   NAME
       CD_INFO -- Return information/status of device

   IO REQUEST
       io_Device       preset by the call to OpenDevice()
       io_Unit         preset by the call to OpenDevice()
       io_Command      CD_INFO
       io_Data         pointer to CDInfo structure
       io_Length       sizeof(struct CDInfo)

   RESULTS
       io_Error        0 for success, or an error code as defined in
                       <devices/cd.h>
       io_Actual       length of data transferred

   FUNCTION

       This command returns current configurations and status of the device
       driver.

   EXAMPLE

       struct CDInfo Info;

       ior->io_Command = CD_INFO;               /* Retrieve drive info.    */
       ior->io_Data    = (APTR)Info;            /* Here's where we want it */
       ior->io_Length  = sizeof(struct CDInfo); /* Return whole structure  */
       DoIO(ior);

       if (!ior->io_Error) {                    /* Command succeeded       */

           if (Info.Status & CDSTSF_PLAYING) printf("Audio is playingn");
           else                              printf("Audio not playingn");
           }

   NOTES

   BUGS

   SEE ALSO
       <devices/cd.h>


cd.device/CD_MOTOR

   NAME
       CD_MOTOR -- control the on/off state of a drive motor.

   FUNCTION
       This command gives control over the spindle motor.  The motor may be
       turned on or off.

       If the motor is just being turned on, the device will delay the
       proper amount of time to allow the drive to come up to speed.
       Turning the motor on or off manually is not necessary, the device does
       this automatically if it receives a request when the motor is off.

   IO REQUEST INPUT
       io_Device       preset by the call to OpenDevice()
       io_Unit         preset by the call to OpenDevice()
       io_Command      CD_MOTOR
       io_Length       the requested state of the motor, 0 to turn the motor
                       off, and 1 to turn the motor on.

   IO REQUEST RESULT
       io_Error - 0 for success, or an error code as defined in
                  <devices/cd.h>
       io_Actual - if io_Error is 0 this contains the previous state of the
                   drive motor.


cd.device/CD_PAUSE

   NAME
       CD_PAUSE -- Pause or unPause play command.

   IO REQUEST
       io_Device       preset by the call to OpenDevice()
       io_Unit         preset by the call to OpenDevice()
       io_Command      CD_PAUSE
       io_Data         NULL
       io_Length       pausemode : 1 = pause play; 0 = do not pause play;
       io_Offset       0

   RESULTS
       io_Actual - if io_Error is 0, this contains the previous pause state.

   FUNCTION
       This command will place the CD in, or take the CD out of pause mode.
       The desired pause state is placed in io_Length.  This command only
       effects play commands.  When the audio is playing and the pausemode
       is set, this command will immediately pause the audio output
       suspending the play command until the play is unpaused.  When audio
       is not playing and the pausemode is set, this command will set the
       pause mode (having no immediate effect).  When a play command is
       submitted, the laser will seek to the appropriate position and pause
       at that spot.  The play command will be suspended until the play is
       unpaused (or the play is aborted).

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO


cd.device/CD_PLAYLSN

   NAME
        CD_PLAYLSN -- Play a selected portion of CD audio (LSN form).

   IO REQUEST
       io_Device       preset by the call to OpenDevice()
       io_Unit         preset by the call to OpenDevice()
       io_Command      CD_PLAYLSN
       io_Data         NULL
       io_Length       length of play
       io_Offset       starting position

   RESULTS
       io_Error        0 for success, or an error code as defined in
                       <devices/cd.h>

   FUNCTION
       This command causes the drive to start playing CD audio from the
       specified position until the specified length has passed.

       io_Offset specifies the starting position.  io_Length contains
       the amount of time to play.  All data is specified in LSN format.

       A DoIO() will not return until the requested number of sectors
       have been played.  A SendIO() will return as soon as the PLAY
       has been started.  At this time other commands can be sent (like
       CD_PAUSE).  To stop a play before the specified length has been
       reached, use AbortIO().

   EXAMPLE
       /* Play two minutes, ten seconds of audio starting at 20 minutes, */
       /* 58 seconds, and 10 frames.                                     */

       ior->io_Command = CD_PLAYLSN;   /* Play CD audio           */
       ior->io_Offset  = 94360;        /* 20*(60*75) + 58*75 + 10 */
       ior->io_Length  = 9750;         /* 02*(60*75) + 10*75 + 00 */
       DoIO (ior);

   NOTES

   BUGS

   SEE ALSO
       CD_PLAYTRACK, CD_PAUSE, CD_SEARCH, CD_ATTENUATE


cd.device/CD_PLAYMSF

   NAME
        CD_PLAYMSF -- Play a selected portion of CD audio (MSF form).

   IO REQUEST
       io_Device       preset by the call to OpenDevice()
       io_Unit         preset by the call to OpenDevice()
       io_Command      CD_PLAYMSF
       io_Data         NULL
       io_Length       length of play
       io_Offset       starting position

   RESULTS
       io_Error        0 for success, or an error code as defined in
                       <devices/cd.h>

   FUNCTION
       This command causes the drive to start playing CD audio from the
       specified position until the specified length has passed.

       io_Offset specifies the starting position.  io_Length contains
       the amount of time to play.  All data is specified in MSF format.

       A DoIO() will not return until the requested number of sectors
       have been played.  A SendIO() will return as soon as the PLAY
       has been started.  At this time other commands can be sent (like
       CD_PAUSE).  To stop a play before the specified length has been
       reached, use AbortIO().

   EXAMPLE
       /* Play two minutes, ten seconds of audio starting at 20 minutes, */
       /* 58 seconds, and 10 frames.                                     */

       ior->io_Command = CD_PLAYMSF;   /* Play CD audio          */
       ior->io_Offset  = 0x00143A0A;   /* $14=20, $3A=58, $0A=10 */
       ior->io_Length  = 0x00020A00;   /* $02=02, $0A=10, $00=00 */
       DoIO (ior);

   NOTES

   BUGS

   SEE ALSO
       CD_PLAYTRACK, CD_PAUSE, CD_SEARCH, CD_ATTENUATE


cd.device/CD_PLAYTRACK

   NAME
       CD_PLAYTRACK -- Play one or more tracks of CD audio.

   IO REQUEST
       io_Device       preset by the call to OpenDevice()
       io_Unit         preset by the call to OpenDevice()
       io_Command      CD_PLAYTRACK
       io_Data         NULL
       io_Length       number of tracks to play
       io_Offset       start playing at beginning of this track

   RESULTS
       io_Error        0 for success, or an error code as defined in
                       <devices/cd.h>
   FUNCTION
       This command causes the drive to play the specified audio track(s).
       The command will return when the audio has completed.

       io_Offset specifies the track number (starting from 1).

       io_Length specifies the number of tracks to play (0 is invalid).

   EXAMPLE

       ior->io_Command = CD_PLAYTRACK;    /* Play audio tracks     */
       ior->io_Offset  = STARTTRACK;      /* Start with this track */
       ior->io_Length  = 3;               /* Play three tracks     */
       DoIO(ior);

   NOTES

       PLAY commands are asynchronous with many other CD commands.
       Using a separate I/O request, other commands can be sent to the device
       that can change the behavior of the PLAY command.

   BUGS

   SEE ALSO
       CD_PLAYMSF, CD_PLAYLSN, CD_PAUSE, CD_SEARCH, CD_ATTENUATE


cd.device/CD_PROTSTATUS

   NAME
       CD_PROTSTATUS -- return whether the current disk is write-protected.

   FUNCTION
       This command is used to determine whether the current disk is
       write-protected.  Currently, this function always returns write-
       protected status.  If write-once CDs are made available at some point,
       this may change.

   IO REQUEST INPUT
       io_Device       preset by the call to OpenDevice()
       io_Unit         preset by the call to OpenDevice()
       io_Command      CD_PROTSTATUS

   IO REQUEST RESULT
       io_Error - 0 for success, or an error code as defined in
                  <devices/cd.h>
       io_Actual - 0 means the disk is NOT write-protected, while any other
                   value indicates it is.


cd.device/CD_QCODELSN

   NAME
       CD_QCODELSN -- Report current disk position.

   IO REQUEST
       io_Device       preset by the call to OpenDevice()
       io_Unit         preset by the call to OpenDevice()
       io_Command      CD_QCODELSN
       io_Data         pointer to QCode structure
       io_Length       0 - MUST be zero (for future compatability)

   RESULTS
       io_Error        0 for success, or an error code as defined in
                       <devices/cd.h>

   FUNCTION
       This command reports current subcode Q channel time information.  This
       command only returns data when CD Audio is playing (or paused).  At
       any other time, an error is returned.  The Q-Code packet consists of:

       struct QCode {

           UBYTE        CtlAdr;        /* Data type / QCode type           */
           UBYTE        Track;         /* Track number                     */
           UBYTE        Index;         /* Track subindex number            */
           UBYTE        Zero;          /* The "Zero" byte of Q-Code packet */
           union LSNMSF TrackPosition; /* Position from start of track     */
           union LSNMSF DiskPosition;  /* Position from start of disk      */
           };

   EXAMPLE

       struct QCode qcode;

       ior->io_Command = CD_QCODELSN;  /* Retrieve TOC information */
       ior->io_Length  = 0;            /* MUST be zero             */
       ior->io_Data    = (APTR)qcode;  /* Here's where we want it  */
       DoIO (ior);

       if (!ior->io_Error) {           /* Command succeeded        */

           printf("Current position is: %ldn", qcode.DiskPosition.LSN);
           }

   NOTES
       This function may not return immediately.  It may take several frames
       to pass by before a valid Q-Code packet can be returned.  Use SendIO()
       and CheckIO() if response time is critical, and the information is
       not.

   BUGS

   SEE ALSO
       CD_PLAYMSF, CD_PLAYLSN, CD_PLAYTRACK, <devices/cd.h>


cd.device/CD_QCODEMSF

   NAME
       CD_QCODEMSF -- Report current disk position.

   IO REQUEST
       io_Device       preset by the call to OpenDevice()
       io_Unit         preset by the call to OpenDevice()
       io_Command      CD_QCODEMSF
       io_Data         pointer to QCode structure
       io_Length       0 - MUST be zero (for future compatability)

   RESULTS
       io_Error        0 for success, or an error code as defined in
                       <devices/cd.h>

   FUNCTION
       This command reports current subcode Q channel time information.  This
       command only returns data when CD Audio is playing (or paused).  At
       any other time, an error is returned.  The Q-Code packet consists of:

       struct QCode {

           UBYTE        CtlAdr;        /* Data type / QCode type           */
           UBYTE        Track;         /* Track number                     */
           UBYTE        Index;         /* Track subindex number            */
           UBYTE        Zero;          /* The "Zero" byte of Q-Code packet */
           union LSNMSF TrackPosition; /* Position from start of track     */
           union LSNMSF DiskPosition;  /* Position from start of disk      */
           };

   EXAMPLE

       struct QCode qcode;

       ior->io_Command = CD_QCODEMSF;  /* Retrieve TOC information */
       ior->io_Length  = 0;            /* MUST be zero             */
       ior->io_Data    = (APTR)qcode;  /* Here's where we want it  */
       DoIO (ior);

       if (!ior->io_Error) {           /* Command succeeded        */

           printf("Current position is: %02d:%02d:%02dn",
               qcode.DiskPosition.MSF.Minute,
               qcode.DiskPosition.MSF.Second,
               qcode.DiskPosition.MSF.Frame);
           }

   NOTES
       This function may not return immediately.  It may take several frames
       to pass by before a valid Q-Code packet can be returned.  Use SendIO()
       and CheckIO() if response time is critical, and the information is
       not.

   BUGS

   SEE ALSO
       CD_PLAYMSF, CD_PLAYLSN, CD_PLAYTRACK, <devices/cd.h>


cd.device/CD_READ

   NAME
       CD_READ -- read data from disk.

   FUNCTION
       Reads data from the CD into memory.  Data may be accessed on WORD
       boundaries (you are not restricted to sector boundaries as with
       normal disk devices).  Data lengths can also be described in WORD
       amounts.

   IO REQUEST INPUT
       io_Device       preset by the call to OpenDevice()
       io_Unit         preset by the call to OpenDevice()
       io_Command      CD_READ
       io_Data         pointer to the buffer where the data should be put
       io_Length       number of bytes to read, must be a WORD multiple.
       io_Offset       byte offset from the start of the disk describing
                       where to read data from, must be a WORD multiple.

   IO REQUEST RESULT
       io_Error  - 0 for success, or an error code as defined in
                   <devices/cd.h>
       io_Actual - if io_Error is 0, number of bytes actually transferred

   NOTES
       If an error occurs when attempting a CD_READ, the software will
       retry up to 10 times before giving up on the request.  If the
       drive is in double-speed and an error occurs, the software will
       retry once more in double-speed, and if this fails, will retry
       the next 9 times in single-speed.

   SEE ALSO
       CD_READXL


cd.device/CD_READXL

   NAME
       CD_READXL -- Read from CD-ROM into memory via transfer list.

   IO REQUEST
       io_Device       preset by the call to OpenDevice()
       io_Unit         preset by the call to OpenDevice()
       io_Command      CD_READXL
       io_Data         pointer to transfer list (i.e. struct List *).
       io_Length       maximum transfer length (WORD multiple) or 0.
       io_Offset       byte offset from the start of the disk describing
                       where to read data from, must be a WORD multiple.

   RESULTS
       io_Error        0 for success, or an error code as described in
                       <devices/cd.h>
       io_Actual       if io_Error is 0, number of bytes actually transferred

   FUNCTION
       This command starts reading data off the disk at the specified
       location and deposits it into memory according to the nodes in a
       transfer list.  The pointer to the list of transfer nodes is placed
       in io_Data.  If you have a non-circular transfer list, simply set
       io_Length to 0 (0 is special and means ignore io_Length) -- your
       transfer will end when your transfer list has been exhausted.  If you
       have a circular transfer list, the list will never end.  In this case,
       the transfer will terminate when io_Length bytes have been
       transferred.

       The fields in the CDXL node structure are:

       struct  CDXL {

           struct MinNode  Node;         /* double linkage                */
           char           *Buffer;       /* data destination              */
           LONG            Length;       /* must be even # bytes          */
           LONG            Actual;       /* bytes transferred             */
           APTR            IntData;      /* interrupt server data segment */
           VOID            (*IntCode)(); /* interrupt server code entry   */
           };

       The philosophy here is that you set up the buffers you want filled,
       create CDXL nodes describing the locations and sizes of these
       buffers, link all the nodes together in the order that you'd like
       (even make a circular list for animations), and execute the command.
       The data will be streamed into the appropriate buffers until the
       list has been exhausted, an entry with a Length of zero is
       encountered, io_Length bytes have been transferred (if io_Length is
       non-zero), or the command is aborted with AbortIO().

       If you fill in the (*IntCode)() field with a pointer to an interrupt
       routine, your routine will be called when the transfer for the node
       is complete.  Your code will be called before the driver proceeds to
       the next node.  The interrupt should follow the same rules as standard
       interrupts (see AddIntServer of Exec autodocs).  Register A2 will
       contain a pointer to the node just completed.  You may manipulate the
       list from within the interrupt. Your code must be brief (this is an
       interrupt).  When returning from this interrupt, D0 should be cleared
       and an RTS instruction should be used to return.

       Servers are called with the following register conventions:

           D0 - scratch
           D1 - scratch

           A0 - scratch
           A1 - server is_Data pointer (scratch)
           A2 - pointer to CDXL node just completed

           A5 - jump vector register (scratch)

           all other registers must be preserved

   EXAMPLE

   NOTES
       Try to make sure that small buffers are not overused.  Each time
       a node is completed, an interrupt is generated.  If you find that
       your computer is acting sluggish, or the CD_READXL command is
       aborting, you are probably generating too many interrupts.  It is
       not efficient to have more than a few of these interrupts generated
       within a vertical blank.

       Unlike the READ command, the READXL command will not retry a sector
       if there is an error.  Since the READXL command's purpose is primarily
       for animations, data streaming is considered more important than the
       data itself.  An error will be returned in io_Error if a data error
       did occur.  This command will never drop to a lower speed in the event
       of an error.

   BUGS

   SEE ALSO
       CMD_READ, CD_SEEK, Autodocs - AddIntServer


cd.device/CD_REMCHANGEINT

   NAME
       CD_REMCHANGEINT -- remove a disk change software interrupt handler.

   FUNCTION
       This command removes a disk change software interrupt added
       by a previous use of CD_ADDCHANGEINT.

   IO REQUEST INPUT
       The same IO request used for CD_ADDCHANGEINT.

       io_Device       preset by the call to OpenDevice()
       io_Unit         preset by the call to OpenDevice()
       io_Command      CD_REMCHANGEINT
       io_Length       sizeof(struct Interrupt)
       io_Data         pointer to Interrupt structure

   IO REQUEST RESULT
       io_Error - 0 for success, or an error code as defined in
                  <devices/cd.h>

   SEE ALSO
       CD_ADDCHANGEINT, <devices/cd.h>


cd.device/CD_REMFRAMEINT

   NAME
       CD_REMFRAMEINT -- remove a CD-frame interrupt handler.

   IO REQUEST
       The same IO request used for CD_ADDFRAMEINT.

       io_Device       preset by the call to OpenDevice()
       io_Unit         preset by the call to OpenDevice()
       io_Command      CD_REMFRAMEINT
       io_Length       sizeof(struct Interrupt)
       io_Data         pointer to Interrupt structure

   RESULTS
       io_Error        0 for success, or an error code as defined in
                       <devices/cd.h>

   FUNCTION
       This command removes a CD-frame software interrupt added
       by a previous use of CD_ADDFRAMEINT.

   BUGS

   SEE ALSO
       CD_ADDFRAMEINT, <devices/cd.h>


cd.device/CD_SEARCH

   NAME
       CD_SEARCH -- configure the mode in which PLAY commands play

   IO REQUEST
       io_Command      CD_SEARCH
       io_Data         NULL
       io_Length       searchmode
       io_Offset       0

   RESULTS
       io_Actual - if io_Error is 0, this contains the previous search mode.

   FUNCTION
       This command causes a play command to play in fast-forward,
       fast-reverse, or normal play mode.  These modes are defined as:

       CDMODE_NORMAL   0   Normal play (current speed setting)
       CDMODE_FFWD     1   Play in fast forward mode
       CDMODE_FREV     2   Play in fast reverse mode

       The search mode can be set before the play command is sent, or during
       a play.  If CD_SEARCH is sent before a play command is sent, the
       mode is set and the command immediately returns.  If the mode is set
       to REV mode, when the play command is sent the play will begin at the
       requested end position and work backwards to the start position.

       If CD_SEARCH is sent during a play, the play will automatically
       switch to the desired mode and continue playing until the original
       play command is completed.  If REV mode is set and the beginning of
       the play is encountered before switching back to forward play, the
       play command will terminate with no error.

   EXAMPLE
       /* Search in fast forward mode. */
       ior->io_Command = CD_SEARCH;
       ior->io_Data    = NULL;
       ior->io_Offset  = 0;
       ior->io_Length  = CDMODE_FFWD;
       DoIO(ior);

   NOTES

   BUGS

   SEE ALSO


cd.device/CD_SEEK

   NAME
       CD_SEEK -- position laser at specified location.

   FUNCTION
       CD_SEEK moves the laser to the approximate position specified.  The
       io_Offset field should be set to the offset to which the head is
       to be positioned.

   IO REQUEST INPUT
       io_Device       preset by the call to OpenDevice()
       io_Unit         preset by the call to OpenDevice()
       io_Command      CD_SEEK
       io_Offset       position where head is to be moved (always LSN format)

   IO REQUEST RESULT
       io_Error - 0 for success, or an error code as defined in
                  <devices/cd.h>


cd.device/CD_TOCLSN

   NAME
       CD_TOCLSN -- Return table of contents information from CD (LSN form).

   IO REQUEST
       io_Device       preset by the call to OpenDevice()
       io_Unit         preset by the call to OpenDevice()
       io_Command      CD_TOCLSN
       io_Data         pointer to array where TOC is to be stored
       io_Length       number of CDTOC entries to be fetched
       io_Offset       entry to begin at (entry 0 is summary information)

   RESULTS
       io_Error        0 for success, or an error code as defined in
                       <devices/cd.h>
       io_Actual       Actual number of entries copied

   FUNCTION
       This command returns the table of contents of the disk currently in
       the drive.  The table of contents consists of up to 100 entries.
       Entry zero is summary information describing the number of tracks
       and the total number of minutes on the disk.  Entries 1 through N
       contain information about each individual track.  All position
       information will be in LSN format.

       The io_Data field points to an array of CDTOC structures to receive
       the TOC data.

       The io_Length field specifies the total number of entries to be
       fetched.  The array pointed to by io_Data must be at least this many
       elements in size.

       The io_Offset field specifies the entry number at which to start
       copying TOC data into *io_Data.

       Entry zero (the summary entry) contains the following:

       struct TOCSummary {

           UBYTE        FirstTrack;    /* First track on disk (always 1)   */
           UBYTE        LastTrack;     /* Last track on disk               */
           union LSNMSF LeadOut;       /* Beginning of lead-out track      */
           };

       Track entries (entries 1 through number of tracks) contain:

       struct TOCEntry {

           UBYTE        CtlAdr;        /* Q-Code info                  */
           UBYTE        Track;         /* Track number                 */
           union LSNMSF Position;      /* Start position of this track */
           };

       CDTOC is described as a union between these two structures:

       union CDTOC {

           struct TOCSummary Summary;  /* First entry is summary info.  */
           struct TOCEntry   Entry;    /* Entries 1-N are track entries */
           };

   EXAMPLE

       union CDTOC tocarray[100];

       ior->io_Command = CD_TOCLSN;        /* Retrieve TOC information */
       ior->io_Offset  = 0;                /* Start with summary info  */
       ior->io_Length  = 100;              /* Max 99 tracks + summary  */
       ior->io_Data    = (APTR)tocarray;   /* Here's where we want it  */
       DoIO (ior);

       if (!ior->io_Error) {               /* Command succeeded        */

           firsttrack   = tocarray[0].Summary.FirstTrack;
           lasttrack    = tocarray[0].Summary.LastTrack;
           totalsectors = tocarray[0].Summary.LeadOut.LSN -
                          tocarray[1].Entry.Position.LSN;
           }

   NOTES

       In the above example, the amount of data on the disk is calculated as
       being equal to the location of the lead-out track minus the start of
       the first track (which is never zero).

   BUGS

   SEE ALSO


cd.device/CD_TOCMSF

   NAME
       CD_TOCMSF -- Return table of contents information from CD (MSF form).

   IO REQUEST
       io_Device       preset by the call to OpenDevice()
       io_Unit         preset by the call to OpenDevice()
       io_Command      CD_TOCMSF
       io_Data         pointer to array where TOC is to be stored
       io_Length       number of CDTOC entries to be fetched
       io_Offset       entry to begin at (entry 0 is summary information)

   RESULTS
       io_Error        0 for success, or an error code as defined in
                       <devices/cd.h>
       io_Actual       Actual number of entries copied

   FUNCTION
       This command returns the table of contents of the disk currently in
       the drive.  The table of contents consists of up to 100 entries.
       Entry zero is summary information describing the number of tracks
       and the total number of minutes on the disk.  Entries 1 through N
       contain information about each individual track.  All position
       information will be in MSF format.

       The io_Data field points to an array of CDTOC structures to receive
       the TOC data.

       The io_Length field specifies the total number of entries to be
       fetched.  The array pointed to by io_Data must be at least this many
       elements in size.

       The io_Offset field specifies the entry number at which to start
       copying TOC data into *io_Data.

       Entry zero (the summary entry) contains the following:

       struct TOCSummary {

           UBYTE        FirstTrack;    /* First track on disk (always 1)   */
           UBYTE        LastTrack;     /* Last track on disk               */
           union LSNMSF LeadOut;       /* Beginning of lead-out track      */
           };

       Track entries (entries 1 through number of tracks) contain:

       struct TOCEntry {

           UBYTE        CtlAdr;        /* Q-Code info                  */
           UBYTE        Track;         /* Track number                 */
           union LSNMSF Position;      /* Start position of this track */
           };

       CDTOC is described as a union between these two structures:

       union CDTOC {

           struct TOCSummary Summary;  /* First entry is summary info.  */
           struct TOCEntry   Entry;    /* Entries 1-N are track entries */
           };

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO


cd.device/CloseDevice

   NAME
       CloseDevice - terminate access to the CD

   SYNOPSIS
       CloseDevice(IORequest);
                   A1

   FUNCTION
       This function will terminate access to the unit openned with
       OpenDevice().

   INPUTS
       iORequest - pointer to a struct(IOStdReq)

   RESULTS

   NOTES

   SEE ALSO
       OpenDevice()


cd.device/OpenDevice

   NAME
       OpenDevice - Open a CD unit for access

   SYNOPSIS
       error = OpenDevice("cd.device", UnitNumber, IORequest, flags);
       D0                 A0           D0          A1         D1

   FUNCTION
       Opens the cd.device and creates an IORequest for use in accessing
       the CD.

   INPUTS
       UnitNumber - Normally zero; however, this is described as:
                    Ones digit      = Unit (SCSI unit number)
                    Tens digit      = LUN (disk within disk changer)
                    Hundreds digit  = Card number (SCSI card)
                    Thousands digit = Reserved (must be zero)
       IORequest  - Pointer to a struct(IOStdReq)
       flags      - Should be zero.

   RESULTS
       error        0 = success, otherwise this is an error.

   NOTES

   SEE ALSO
       CloseDevice()


checkbox_gc.doc

     --datasheet--
     CHECKBOX_GetClass()


checkbox_gc/--datasheet--

    NAME
        checkbox_gc -- create checkbox BOOPSI objects

    SUPERCLASS
        gadgetclass

    REQUIRES
        bevel.image, glyph.image

    DESCRIPTION
        The checkbox gadget class is used to create toggling check buttons.
        Selection of an associated option is denoted by the gadget being
        "checked", or in other words, containing a checkmark with in the
        checkbox. Unlike GadTools, GA_Height and GA_Width DO NOT specify
        the checkbox size, but rather the entire hit box area which
        includes the text label. The checkbox will maintain its aspect
        ratio when possible.

        Advantages that this class provides over the standard gadtools
        checkbox are:

         > Supports window relativity.

         > Ability to change background pen, text pen, and filltext pen.

         > Larger selection area, includes text label area.

         > Supports OS 3.0 BOOPSI Gadget HelpTest.

         > Aspect adaptive checkbox for any resolution and font.

    METHODS
        OM_NEW -- Passed to superclass first, defaults set, then OM_SET.

        OM_SET -- Passed to superclass first, then custom tags set & render.

        OM_GET -- Returns requested setting or passed to superclass

        OM_UPDATE -- Passed to superclass first, then custom tags set & render.

        OM_NOTIFY -- Tag set then passed to superclass.

        OM_DISPOSE -- Passed to superclass.

        GM_DOMAIN -- Returns aspect ratio corrected minimum and maximum
            sizes.

        GM_GOACTIVE -- Passed to superclass first, then check activated

        GM_GOINACTIVE -- Passed to superclass first, then check deactivated

        GM_HANDLEINPUT -- Overrides superclass.

        GM_HITTEST -- Overrides superclass, returns GMR_HITTEST.

        GM_RENDER -- Renders or erases checkmark glyph.

        GM_DOMAIN -- Returns GDOMAIN_MINIMUM, GDOMAIN_NOMINAL and
            GDOMAIN_MAXIMUM dimensions.

        GM_KEYACTIVE -- Private method for keyboard control.

        GM_KEYINACTIVE -- Private method for keyboard control.

    ATTRIBUTES

        GA_ID (WORD)
            Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_NOTIFY)

        GA_Text (STRPTR)
            Used to set the text label for the checkbox

            Defaults to NULL.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

        GA_TextAttr (struct TextAttr *)
            Used to set the text font to render the checkbox label.

            Defaults to RPort->Font, which is often the screen or
            window font.

            Applicability is (OM_NEW, OM_SET)

        GA_Selected (BOOL)
            Used to set the checkmark state via application control.

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_NOTIFY)

        GA_Disabled (BOOL)
            Used to disable the gadget, and render a disable ghost
            pattern of the checkbox.

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

        CHECKBOX_TextPen (WORD)
            Pen number used to render the text label.

            Defaults to TEXTPEN.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

        CHECKBOX_BackGroundPen (WORD)
            Pen number used to render the gadget background.

            Defaults to BACKGROUNDPEN.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

        CHECKBOX_TextPlace (WORD)
            Location of checkbox text label. Supports:

                PLACETEXT_RIGHT
                PLACETEXT_LEFT

            Defaults to PLACETEXT_RIGHT.

            Applicability is (OM_NEW)


checkbox_gc/CHECKBOX_GetClass

    NAME
        CHECKBOX_GetClass -- Gets the pointer to the checkbox class.

    SYNOPSIS
        checkbox_class = CHECKBOX_GetClass();
        D0

        Class * CHECKBOX_GetClass(VOID);

    FUNCTION
        This function is only available in runtime linked version of the
        class, checkbox.gadget and is not in the compiler linker library
        checkbox_gc.lib.

        Obtains the pointer to the CheckBox gadget class for use with
        NewObject().  This function always returns a valid pointer so
        you do not need to check it.  The reason is that if the library
        opens fine, then the pointer returned is already setup.  (Of course
        this implies that if opening the library fails, you shouldn't be
        calling this.)

        Note that this function does not create the class, that is done
        when the class library is opened.

    INPUTS
        Nothing.

    RESULT
        checkbox_class - Pointer to the CheckBox gadget class.

    SEE ALSO


chooser_gc.doc

     --datasheet--
     --styleguide--
     CHOOSER_GetClass()
     AllocChooserNodeA()
     FreeChooserNode()
     GetChooserNodeAttrsA()
     SetChooserNodeAttrsA()


chooser_gc/--datasheet--

     NAME
        chooser_gc -- A popup/dropdown small list selection gadget.

     SUPERCLASS
        gadgetclass

    REQUIRES
        bevel.image, glyph.image

     DESCRIPTION
        A chooser is a small-list selection object.  In its inactive mode it
        looks much like a button or cycle gadget.  When the button is pressed
        using the mouse, a menu displaying the items in the list is displayed.

        The chooser operates in either of two modes, pop-up and drop-down.
        Even though the may operate similarly internally, they are for two
        different functions.  Consult the chooser style guide for
        information on how to use these two modes.

        Advantages that this class provides:

         > Supports window relativity.

         > Supports OS 3.0 BOOPSI Gadget HelpTest.

         > Cycle2Menu style activation.

         > Supports tab-cycle activation and keyboard control.

     METHODS
        OM_NEW -- Create the chooser gadget.  Passed to superclass.

        OM_SET -- Set object attributes.  Passed to superclass first.

        OM_DISPOSE -- Cancels the chooser menu before being passed to
            superclass.

        OM_UPDATE -- Set object notification attributes & render.
            Passed to superclass first.

        OM_NOTIFY -- Notify object attributes. Passed to superclass last.

        GM_RENDER -- Renders the gadget imagry.  Overrides the superclass.

        GM_HITTEST -- Determines if mouse is within the gadget rectangle.
            Overrrides the superclass.

        GM_GOACTIVE -- Handles activation, pops up the chooser menu.
            Overrides the superclass.

        GM_HANDLEINPUT -- Handles input events once active.  Overrides the
            superclass.

        GM_GOINACTIVE -- Closes the chooser menu.  Overrides the superclass.

        GM_DOMAIN -- Calculates mix/max sizes. Overrides the superclass.

        GM_KEYACTIVE -- Activates gadget via keyboard, advances popup
            selection to the next item, if SHIFT is pressed, it selects
            the previous item. Invoked by window.class only.

        GM_KEYINACTIVE -- Deactivates gadget. Invoked by window.class only.

        All other methods are passed to the superclass.

     ATTRIBUTES

        GA_ID (WORD)
            Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET, OM_NOTIFY)

        GA_ReadOnly (BOOL)
            Set to TRUE to make the gadget non-selectable, but without
            a ghost pattern.

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET)

        GA_Disabled (BOOL)
            Set to TRUE to disable gadget, FALSE otherwise

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET)

        GA_TextAttr (struct TextAttr *)
            Font to use for the gadget text.

            Defaults to the screen's font.

            Applicability is (OM_NEW, OM_GET)

        CHOOSER_PopUp (BOOL)
            Sets the chooser to work in popup mode.
            Generally this mode is used for selecting an application mode or
            a state from a list of possible values.  This item is mutually
            exclusive to CHOOSER_DropDown, one of the two MUST be TRUE.

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET)

        CHOOSER_DropDown (BOOL)
            Sets the chooser to work in dropdown mode.  Generally for
            selecting an action to perform from a list of possible actions.
            This item is mutually exclusive to CHOOSER_PopUp, one of the
            two MUST be TRUE.

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET)

        CHOOSER_Title (STRPTR)
            Title to appear within the select box when in dropdown mode

            Defaults to NULL.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET)

        CHOOSER_Labels (struct List *)
            Exec List of labels.  Each node must be allocated with the
            AllocChooserNodeA() function.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET)

        CHOOSER_MaxLabels (WORD)
            Set the maximum number of labels that will be displayed in the
            chooser, regardless of the size of the list.

            Defaults to 12.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET)

        CHOOSER_Active (WORD) /* Obsolete */
        CHOOSER_Selected (WORD)
            Index of selected label in the list.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET, OM_NOTIFY)

        CHOOSER_Width (WORD)
            The width of the chooser menu.

            Defaults to the width of the gadget select box.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET)

        CHOOSER_AutoFit (BOOL)
            Set the width of the chooser menu so that it fits the widest
            label in the list.

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET)


chooser_gc/--styleguide--

    CHOOSER STYLE
        The Chooser has two very distinct modes of operation, drop-down and
        pop-up.  It is important to understand the differences between these
        two modes and to use the proper mode in the proper context.

    POP-UP CHOOSERS
        A popup is generally used for setting an application mode or state,
        and in many cases it can replace a cycle gadget or MX (radio buttons)
        gadget.  In this mode, there is a currently active item in the list
        of selections, which will be display in the gadget select button.
        This has the same advantage of a cycle menu in that it is compact,
        with the further advantage that all values can be displayed at once
        and therefore the list of values can be much larger, though generally
        no more than a dozen items should be displayed.

    DROP-DOWN CHOOSERS
        A dropdown chooser is for performing an action from a list of
        available actions.  In this mode, the gadget select box contains a
        title indicating what the actions are for.  These actions should all
        be closely related, and specific to a certain context within the
        application.  This can be used to replace a group of buttons, or a
        cycle gadget and a button where the cycle gadget modifies the
        behaviour of the button.  Since using the chooser in this mode makes
        functions effectively hidden, it should generally only be used where
        compactness is a signficant issue.

        An alternate use for a drop-down is to use it as a means of accessing
        a "hot list" for a string or integer gadget.  For example, in a word
        processor you might have a string gadget at the top of the screen for
        entering the text point size.  Beside that you could have a drop-down
        chooser that lists some common point sizes that would then be copied
        into your integer gadget and change the text size when you make a
        selection.  When a drop-down is used this way, it is generally
        desirable not to have the drop-down display a title within the gadget
        box (pass NULL for CHOOSER_Title) and to  make the gadget this enough
        so that just the arrow is displayed (use about 20 for GA_Width if not
        using the chooser within a layout group).


chooser_gc/CHOOSER_GetClass

    NAME
        CHOOSER_GetClass -- Gets the pointer to the chooser class.

    SYNOPSIS
        chooser_class = CHOOSER_GetClass();
        D0

        Class * CHOOSER_GetClass(VOID);

    FUNCTION
        This function is only available in runtime linked version of the
        class, and is not in the compiler linker library chooser_gc.lib.

        Obtains the pointer to the Chooser gadget class for use with
        NewObject().  This function always returns a valid pointer so
        you do not need to check it.  The reason is that if the library
        opens fine, then the pointer returned is already setup.  (Of course
        this implies that if opening the library fails, you shouldn't be
        calling this.)

        Note that this function does not create the class, that is done
        when the class library is opened.

    INPUTS
        Nothing.

    RESULT
        chooser_class - Pointer to the Chooser gadget class.

    SEE ALSO


chooser_gc/AllocChooserNodeA

    NAME
        AllocChooserNodeA -- Allocate a Chooser node.

    SYNOPSIS
        struct Node * AllocChooserNode(Tag, ...)
        node = AllocChooserNode(columns, Tag, ...)

        struct Node * AllocChooserNodeA(struct TagItem *)
        node = AllocChooserNodeA(taglist)

    FUNCTION
        Allocates a node that can be added to the Exec linked list of
        labels in the chooser.  This is the only way to allocate a
        node for this list, you cannot allocate nodes yourself because
        the Chooser class uses a private node structure.

    INPUTS
        taglist - Attributes for the node, passed onto SetChooserNodeAttrsA().

    RESULT
        node - A node that can be added into the Exec list of labels for
            a Chooser gadget.

    SEE ALSO
        FreeChooserNode(), SetChooserNodeAttrsA()


chooser_gc/FreeChooserNode

    NAME
        FreeChooserNode -- Free a Chooser node.

    SYNOPSIS
        VOID FreeChooserNode(struct Node *)
        FreeChooserNode(node)

    FUNCTION
        Frees a ChooserNode allocated with AllocChooserNodeA().

    INPUTS
        node - The node to free.

    SEE ALSO
        AllocChooserNodeA()


chooser_gc/GetChooserNodeAttrsA

    NAME
        GetChooserNodeAttrsA -- Get attributes about a Chooser node.

    SYNOPSIS
        VOID GetChooserNodeAttrs(struct Node *, Tag, ...)
        GetChooserNodeAttrs(node, firsttag, ...)

        VOID GetChooserNodeAttrsA(struct Node *, struct TagItem *)
        GetChooserNodeAttrsA(node, taglist)

    FUNCTION
        The Chooser uses a private node structure and all attributes
        are hidden, and must therefore be accessed with this function.

    INPUTS
        node - The Chooser node to get the information on.
        taglist - A tag list of attributes to get.  ti_Tag is the attribute
            to get and ti_Data is a pointer to a location to copy the result
            to.  The exception is LBNA_Column, which is used to specify a
            column to get attributes on.

    SEE ALSO
        SetChooserNodeAttrsA()


chooser_gc/SetChooserNodeAttrsA

    NAME
        SetChooserNodeAttrsA -- Set attributes of a Chooser node.

    SYNOPSIS
        VOID SetChooserNodeAttrs(struct Node *, Tag, ...)
        SetChooserNodeAttrs(node, firsttag, ...)

        VOID SetChooserNodeAttrsA(struct Node *, struct TagItem *)
        SetChooserNodeAttrsA(node, taglist)

    FUNCTION
        Changes attributes for a Chooser node.  Since the Chooser
        class uses a private node structure, this is the only way to change
        node attributes.

        You may NOT change node attributes when the node is in a list
        attached to a Chooser gadget.  You must first detach the list
        with CHOOSER_Labels, ~0 before you can change attributes, and
        then re-attach the list.

    TAGS
        CNA_Text (STRPTR)
        Text string to appear as a line in the Chooser menu. This tag
        must be supplied for the node.

        CNA_Image (struct Image *)
        Image to be placed to the left of the CNA_Text in the Chooser menu.

        CNA_SelImage (struct Image *)
        Selected state Image to be placed to the left of the CNA_Text in
        the Chooser menu.

        CNA_ReadOnly (BOOL) (V41.4)
        Item will not be highlight rendered when selected.

        CNA_Disabled (BOOL) (V41.5)
        Item can not be selected. No GADGETUP message is generated.

        CNA_Separator (BOOL) (V41.7)
        Separator (~~~~) Bar Item can not be selected. Simular to the
        separator bars in Intuition menus. No GADGETUP message is generated.

    INPUTS
        node - Node whose attributes you are changing.
        taglist - Tag list of attributes to change.

    SEE ALSO
        GetChooserNodeAttrsA()


cia.doc

     AbleICR()
     AddICRVector()
     RemICRVector()
     SetICR()


cia.resource/AbleICR

   NAME
    AbleICR -- Enable/disable ICR interrupts.

   SYNOPSIS
    oldMask = AbleICR( Resource, mask )
    D0                 A6        D0

    WORD AbleICR( struct Library *, WORD );

   FUNCTION
    This function provides a means of enabling and disabling 8520
    CIA interrupt control registers. In addition it returns the
    previous enable mask.

   INPUTS
    mask            A bit mask indicating which interrupts to be
                        modified. If bit 7 is clear the mask
                        indicates interrupts to be disabled. If
                        bit 7 is set, the mask indicates
                        interrupts to be enabled. Bit positions
                        are identical to those in 8520 ICR.

   RESULTS
    oldMask         The previous enable mask before the requested
                        changes. To get the current mask without
                        making changes, call the function with a
                        null parameter.

   EXAMPLES
    Get the current mask:
        mask = AbleICR(0)
    Enable both timer interrupts:
        AbleICR(0x83)
    Disable serial port interrupt:
        AbleICR(0x08)

   EXCEPTIONS
    Enabling the mask for a pending interrupt will cause an
    immediate processor interrupt (that is if everything else is
    enabled). You may want to clear the pending interrupts with
    SetICR() prior to enabling them.

   NOTE
    The CIA resources are special in that there is more than one
    of them in the system. Because of this, the C language stubs
    in amiga.lib for the CIA resources require an extra parameter
    to specify which CIA resource to use. The synopsis for the
    amiga.lib stubs is as follows:

    oldMask = AbleICR( Resource, mask )
    D0                 A6        D0

    WORD AbleICR( struct Library *, WORD );

   SEE ALSO
    cia.resource/SetICR()


cia.resource/AddICRVector

   NAME
    AddICRVector -- attach an interrupt handler to a CIA bit.

   SYNOPSIS
    interrupt = AddICRVector( Resource, iCRBit, interrupt )
    D0                        A6        D0      A1

    struct Interrupt *AddICRVector( struct Library *, WORD,
        struct Interrupt * );

   FUNCTION
    Assign interrupt processing code to a particular interrupt bit
    of the CIA ICR.  If the interrupt bit has already been
    assigned, this function will fail, and return a pointer to the
    owner interrupt.  If it succeeds, a null is returned.

    This function will also enable the CIA interrupt for the given
    ICR bit.

   INPUTS
    iCRBit          Bit number to set (0..4).
    interrupt       Pointer to interrupt structure.

   RESULT
    interrupt       Zero if successful, otherwise returns a
                        pointer to the current owner interrupt
                        structure.

   NOTE
    A processor interrupt may be generated immediately if this call
    is successful.

    In general, it is probably best to only call this function
    while DISABLED so that the resource to which the interrupt
    handler is being attached may be set to a known state before
    the handler is called. You MUST NOT change the state of the
    resource before attaching your handler to it.

    The CIA resources are special in that there is more than one
    of them in the system. Because of this, the C language stubs
    in amiga.lib for the CIA resources require an extra parameter
    to specify which CIA resource to use. The synopsis for the
    amiga.lib stubs is as follows:

    interrupt = AddICRVector( Resource, iCRBit, interrupt )
    D0                        A6        D0      A1

    struct Interrupt *AddICRVector( struct Library *, WORD,
        struct Interrupt *);

    ***WARNING***

    Never assume that any of the CIA hardware is free for use.
    Always use the AddICRVector() function to obtain ownership
    of the CIA hardware registers your code will use.

    Note that there are two (2) interval timers per CIA.  If
    your application needs one of the interval timers, you
    can try to obtain any one of the four (4) until AddICRVector()
    succeeds.  If all four interval timers are in-use, your
    application should exit cleanly.

    If you just want ownership of a CIA hardware timer, or register,
    but do not want interrupts generated, use the AddICRVector()
    function to obtain ownership, and use the AbleICR() function
    to turn off (or on) interrupts as needed.

    Note that CIA-B generates level 6 interrupts (which can degrade
    system performance by blocking lower priority interrupts).  As
    usual, interrupt handling code should be optimized for speed.

    Always call RemICRVector() when your code exits to release
    ownership of any CIA hardware obtained with AddICRVector().

   SEE ALSO
    cia.resource/RemICRVector(), cia.resource/AbleICR()


cia.resource/RemICRVector

   NAME
    RemICRVector -- Detach an interrupt handler from a CIA bit.

   SYNOPSIS
    RemICRVector( Resource, iCRBit, interrupt )
                  A6        D0      A1

    void RemICRVector( struct Library *, WORD, struct Interrupt *);

   FUNCTION
    Disconnect interrupt processing code for a particular
    interrupt bit of the CIA ICR.

    This function will also disable the CIA interrupt for the
    given ICR bit.

   INPUTS
    iCRBit          Bit number to set (0..4).
    interrupt       Pointer to interrupt structure.

   RESULT

   NOTE
    The CIA resources are special in that there is more than one
    of them in the system. Because of this, the C language stubs
    in amiga.lib for the CIA resources require an extra parameter
    to specify which CIA resource to use. The synopsis for the
    amiga.lib stubs is as follows:

    RemICRVector( Resource, iCRBit, interrupt )
                  A6        D0      A1

    void RemICRVector( struct Library *, WORD, struct Interrupt *);

   SEE ALSO
    cia.resource/AddICRVector()


cia.resource/SetICR

   NAME
    SetICR -- Cause, clear, and sample ICR interrupts.

   SYNOPSIS
    oldMask = SetICR( Resource, mask )
    D0                A6        D0

    WORD SetICR( struct Library *, WORD );

   FUNCTION
    This function provides a means of reseting, causing, and
    sampling 8520 CIA interrupt control registers.

   INPUTS
    mask            A bit mask indicating which interrupts to be
                        effected. If bit 7 is clear the mask
                        indicates interrupts to be reset.  If bit
                        7 is set, the mask indicates interrupts to
                        be caused. Bit positions are identical to
                        those in 8520 ICR.

   RESULTS
    oldMask         The previous interrupt register status before
                        making the requested changes.  To sample
                        current status without making changes,
                        call the function with a null parameter.

   EXAMPLES
    Get the interrupt mask:
        mask = SetICR(0)
    Clear serial port interrupt:
        SetICR(0x08)

   NOTE
    The CIA resources are special in that there is more than one
    of them in the system. Because of this, the C language stubs
    in amiga.lib for the CIA resources require an extra parameter
    to specify which CIA resource to use. The synopsis for the
    amiga.lib stubs is as follows:

    oldMask = SetICR( Resource, mask )
    D0                A6        D0

    WORD SetICR( struct Library *, WORD );

    ***WARNING***

    Never read the contents of the CIA interrupt control registers
    directly.  Reading the contents of one of the CIA interrupt
    control registers clears the register.  This can result in
    interrupts being missed by critical operating system code, and
    other applications.

   EXCEPTIONS
    Setting an interrupt bit for an enabled interrupt will cause
    an immediate interrupt.

   SEE ALSO
    cia.resource/AbleICR()


clicktab_gc.doc

     --datasheet--
     CLICKTAB_GetClass()
     AllocClickTabNodeA()
     FreeClickTabNode()
     GetClickTabNodeAttrsA()
     SetClickTabNodeAttrsA()


clicktab_gc/--datasheet--

    NAME
        clicktab.gadget--File folder tabs gadget.

    SUPERCLASS
        gadgetclass

    REQUIRES
        None.

    DESCRIPTION
        The tabs gadget class provides a custom control that has imagry
        similar in style to the tabs seen in a drawer full of file folders.
        The action of the gadget is the same as a conventional
        mutual-exclusion control in that only one tab can be active at a
        time and a tab is selected by clicking upon it.

        The purpose of the tabs gadget class is to provide functionality like
        the page selection cycle gadget on the top-right side of the AmigaOS
        2.1 PrinterPS preferences editor, but allowing all the choices to be
        visible at the same time. The tab "bar" allows strumming across the
        selections. The current selection is slightly raised and its text
        label displayed in bold.

    METHODS
        OM_NEW -- Create the button gadget.  Passed to superclass, then OM_SET.

        OM_GET -- Get an object attribute.  Passed to superclass for unknown
            attributes.

        OM_SET -- Set object attributes.  Passed to superclass first.

        OM_UPDATE -- Set object notification attributes.  Passed to superclass
            first.

        OM_NOTIFY -- Sets  taglist for notification and pass to superclass.

        GM_DOMAIN -- Calculate imagery & positioning, and return
            minimum/maximum domain size.

        GM_RENDER -- Renders the gadget imagry.  Overrides the superclass.

        GM_HITTEST -- Determines if mouse is within the gadget rectangle.
            Overrides the superclass.

        GM_GOACTIVE -- Handles activation, toggle-select and button-select.
            Overrides the superclass.

        GM_GOINACTIVE -- Deactivates object.  Overrides the superclass.

        GM_HANDLEINPUT -- Handles selection input, RMB undo/abort, etc.

        GM_KEYACTIVE -- Activates gadget via keyboard, selects appropriate
            tab based on input key.  Invoked by window.class only.

        GM_KEYINACTIVE -- Deactivates gadget.  Invoked by window.class only.

        All other methods are passed to the superclass, including OM_DISPOSE.

    ATTRIBUTES

        GA_ID (WORD)
            Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_NOTIFY)

        GA_Top (LONG)
            The top of the gadget.  Typically win->BorderTop + 2 for proper
            placement along the inner top of a window unless used within a
            layout gadget group, then placement is automatic.

        GA_Left (LONG)
            The left edge of the gadget.

        GA_Height (LONG)
            Height of the gadget.  Typically font height plus eight.

        GA_RelHeight (LONG)
            Like all other ReAction gadgets, this attribute is supported.
            However, due to the nature of the classes intended visuals
            it is stylistically a bad thing to do.

        GA_Disabled (BOOL) -- Determines whether the gadget is disabled or
            not.  Changing disable state will invoke GM_RENDER.  A disabled
            gadget's border and label are all rendered in SHADOWPEN and then
            dusted in a ghosting pattern that is rendered in SHADOWPEN.

            Defaults to FALSE.

        GA_TextAttr (struct TextAttr *)
            Optional text attribute for the font to use for the labels.

            Defaults to NULL.

        CLICKTAB_Labels (struct List *)
            A list of clicktab node structures used to indicate the labels
            for each of the tabs.

            Defaults to NULL.

            Applicability is (OM_NEW)

        CLICKTAB_Current (LONG)
            Currently selected tab.

            Defaults to 0.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_NOTIFY)

    NOTES

        This class is best suited for use in a ReAction layout group
        and requires receiving GM_DOMAIN prior to the first GM_RENDER
        in order to size & position its imagery correctly.


clicktab_gc/CLICKTAB_GetClass

    NAME
        CLICKTAB_GetClass  --  Gets the pointer to the clicktab class.

    SYNOPSIS
        clicktab_class = CLICKTAB_GetClass();
        D0

        Class * CLICKTAB_GetClass(VOID);

    FUNCTION
        Obtains the pointer to the ClickTab gadget class for use with
        NewObject().  This function always returns a valid pointer so
        you do not need to check it.  The reason is that if the library
        opens fine, then the pointer returned is already setup.  (Of course
        this implies that if opening the library fails, you shouldn't be
        calling this.)

        Note that this function does not create the class, that is done
        when the class library is opened.

    INPUTS
        Nothing.

    RESULT
        clicktab_class - Pointer to the ClickTab gadget class.

    SEE ALSO


clicktab_gc/AllocClickTabNodeA

    NAME
        AllocClickTabNodeA -- Allocate a ClickTab node.

    SYNOPSIS
        struct Node * AllocClickTabNode(Tag, ...)
        node = AllocClickTabNode(Tag, ...)

        struct Node * AllocClickTabNodeA(struct TagItem *)
        node = AllocClickTabNodeA(taglist)

    FUNCTION
        Allocates a node that can be added to the Exec linked list of
        labels in the clicktab.  This is the only way to allocate a
        node for this list, you cannot allocate nodes yourself because
        the ClickTab class uses a private node structure.

    INPUTS
        columns - How many columns your ClickTab has.
        taglist - Attributes for the node, passed onto SetClickTabNodeAttrsA().

    RESULT
        node - A node that can be added into the Exec list of labels for
            a ClickTab gadget.

    SEE ALSO
        FreeClickTabNode(), SetClickTabNodeAttrsA()


clicktab_gc/FreeClickTabNode

    NAME
        FreeClickTabNode -- Free a ClickTab node.

    SYNOPSIS
        VOID FreeClickTabNode(struct Node *)
        FreeClickTabNode(node)

    FUNCTION
        Frees a ClickTabNode allocated with AllocClickTabNodeA().

    INPUTS
        node - The node to free.

    SEE ALSO
        AllocClickTabNodeA()


clicktab_gc/GetClickTabNodeAttrsA

    NAME
        GetClickTabNodeAttrsA -- Get attributes about a ClickTab node.

    SYNOPSIS
        VOID GetClickTabNodeAttrs(struct Node *, Tag, ...)
        GetClickTabNodeAttrs(node, firsttag, ...)

        VOID GetClickTabNodeAttrsA(struct Node *, struct TagItem *)
        GetClickTabNodeAttrsA(node, taglist)

    FUNCTION
        The ClickTab uses a private node structure and all attributes
        are hidden, and must therefore be accessed with this function.

    INPUTS
        node - The ClickTab node to get the information on.
        taglist - A tag list of attributes to get.  ti_Tag is the attribute
            to get and ti_Data is a pointer to a location to copy the result
            to.  The exception is LBNA_Column, which is used to specify a
            column to get attributes on.

    SEE ALSO
        SetClickTabNodeAttrsA()


clicktab_gc/SetClickTabNodeAttrsA

    NAME
        SetClickTabNodeAttrsA -- Set attributes of a ClickTab node.

    SYNOPSIS
        VOID SetClickTabNodeAttrs(struct Node *, Tag, ...)
        SetClickTabNodeAttrs(node, firsttag, ...)

        VOID SetClickTabNodeAttrsA(struct Node *, struct TagItem *)
        SetClickTabNodeAttrsA(node, taglist)

    FUNCTION
        Changes attributes for a ClickTab node.  Since the ClickTab
        class uses a private node structure, this is the only way to change
        node attributes.

        You may NOT change node attributes when the node is in a list
        attached to a ClickTab gadget.  You must first detach the list
        with CLICKTAB_Labels, ~0 before you can change attributes, and
        then re-attach the list, and re-render the gadget to reflect
        any changes. This should include re-domaining the gadget.
        If used in a layout group, turn off domain caching for the
        clicktab object if you intend to dynamically alter the tabs
        and refresh the layout group with RethinkLayout().

    TAGS
        TNA_Text (STRPTR)

            Text string to appear as a line in the ClickTab menu node.

        TNA_Number (WORD)

            ID Number assigned to a ClickTab menu node

        TNA_TextPen (WORD)

            Specifies pen number to use for the label.

            Defaults to pens[TEXTPEN].

    INPUTS
        node - Node whose attributes you are changing.
        taglist - Tag list of attributes to change.

    SEE ALSO
        GetClickTabNodeAttrsA()


clipboard.doc

     CBD_CHANGEHOOK
     CBD_CURRENTREADID
     CBD_CURRENTWRITEID
     CBD_POST
     CMD_READ
     CMD_UPDATE
     CMD_WRITE


colorwheel_gc.doc

     colorwheel.gadget()
     ConvertHSBToRGB()
     ConvertRGBToHSB()


colorwheel.gadget/colorwheel.gadget

   NAME
    colorwheel.gadget -- create standard HSB color wheel BOOPSI objects
                 (V39)

   FUNCTION
    The color wheel class provides the ability to create gadgets
    enabling the user to control the hue and saturation components
    of an HSB (Hue-Saturation-Brightness) color space. The companion
    gradient slider class enables control of the brightness component of
    the color space.

    The color wheel can operate on screens of any depth, and adapts
    its rendering to the number of colors available. The system's pen
    sharing mechanism is used in order to maximize the number of colors
    used by the wheel. A color wheel gadget is (normally) responsible
    for choosing it's own color pens to draw in (using
    graphics.library/ObtainBestPen()). However, the creator of the gadget
    can "donate" some pens to the gadget, using the WHEEL_Donation
    tag.

    The reason that the color wheel picks its own colors is because
    it has the ability to display several different layouts depending
    on the number and variety of colors available. For example, when
    opening on a screen of low depth or when opening on a screen where
    all the pens have already been allocated exclusively, the gadget will
    display a "monochrome" version of the color wheel, where instead of
    colored segments, the letters "R" (for red), "G" (for green), "B"
    (for blue), "Y" (for yellow), "C" (for cyan) and "M" (for magenta)
    will be used as labels.

    You can talk to the color wheel using HSB or RGB, even though the
    color wheel only really deals with HSB in its user-interface. All
    communications with applications are performed with full 32-bit
    color component values.

   TAGS
    WHEEL_Hue (ULONG) -- Set and get the hue component of a color wheel.
        This is effectively the angle around the wheel where the
        desired color lies. If the wheel is currently displayed,
        the position of the selection knob will be moved to reflect
        the new hue.

        A hue value of 0 is all red, and nothing but red. Increasing
        the value moves the color towards all green at $55555555, full
        blue at $AAAAAAAA, and back to red at $FFFFFFFF.

        If you are setting or getting more than one color component at
        a time, it is more efficient to use the WHEEL_HSB tag.

        Default for this tag is 0. Applicability is (ISGNU).
        (V39)

    WHEEL_Saturation (ULONG) -- Set and get the saturation component of a
        color wheel. This is effectively the distance from the center
        of the wheel where the desired color lies. If the wheel is
        currently displayed, the position of the selection knob will
        be moved to reflect the new saturation.

        A saturation value of 0 puts the knob at the center of the
        wheel and always yields white. Increasing the value
        progressively moves the knob farther away from the center.
        until the value $FFFFFFFF is reached in which case the knob
        is as far as it can go.

        If you are setting or getting more than one color component at
        a time, it is more efficient to use the WHEEL_HSB tag.

        Default for this tag is $FFFFFFFF. Applicability is (ISGNU).
        (V39)

    WHEEL_Brightness (ULONG) -- Set and get the brightness component of a
        color wheel. The color wheel does not itself have any means of
        displaying or editing brightness, but it does maintain this
        value internally. Used with WHEEL_GradientSlider, this tag lets
        you control the value of a gradient slider object by passing
        WHEEL_Brightness to a color wheel.

        A brightness value of 0 means all black. Increasing the value
        progressively brightens the current color, until the value
        $FFFFFFFF is reached in which case the color is as bright as
        it gets.

        If you are setting or getting more than one color component at
        a time, it is more efficient to use the WHEEL_HSB tag.

        Default for this tag is $FFFFFFFF. Applicability is (ISGU).
        (V39)

    WHEEL_HSB (struct ColorWheelHSB *) -- Set and get the hue, saturation,
        and brightness components of a color wheel. This is a buik
        version of the separate WHEEL_Hue, WHEEL_Saturation, and
        WHEEL_Brightness tags.

        When setting this tag, initialize a ColorWheelHSB structure,
        and provide a pointer to it. When getting this tag, pass a
        pointer to a ColorWheelHSB structure, and the color wheel
        object will fill it in with the current values.

        Default for this tag is a hue of 0, a saturation of $FFFFFFFF,
        and a brightness of $FFFFFFFF. Applicability is (ISGU).
        (V39)

    WHEEL_Red (ULONG) -- Set and get the red component of a color wheel.
        If the wheel is currently displayed, the position of the
        selection knob will be moved to reflect the new amount of red.

        If you are setting or getting more than one color component at
        a time, it is more efficient to use the WHEEL_RGB tag.

        Default for this tag is $FFFFFFFF. Applicability is (ISGNU).
        (V39)

    WHEEL_Green (ULONG) -- Set and get the green component of a color
        wheel. If the wheel is currently displayed, the position of
        the selection knob will be moved to reflect the new amount of
        green.

        If you are setting or getting more than one color component at
        a time, it is more efficient to use the WHEEL_RGB tag.

        Default for this tag is 0. Applicability is (ISGNU).
        (V39)

    WHEEL_Blue (ULONG) -- Set and get the blue component of a color
        wheel. If the wheel is currently displayed, the position of
        the selection knob will be moved to reflect the new amount of
        blue.

        If you are setting or getting more than one color component at
        a time, it is more efficient to use the WHEEL_RGB tag.

        Default for this tag is 0. Applicability is (ISGNU).
        (V39)

    WHEEL_RGB (struct ColorWheelRGB *) -- Set and get the red, green,
        and brightness components of a color wheel. This is a buik
        version of the separate WHEEL_Red, WHEEL_Green, and
        WHEEL_Blue tags.

        When setting this tag, initialize a ColorWheelRGB structure,
        and provide a pointer to it. When getting this tag, pass a
        pointer to a ColorWheelRGB structure, and the color wheel
        object will fill it in with the current values.

        Default for this tag is a red of $FFFFFFFF, a green of 0, and
        a blue of 0. Applicability is (ISGU).
        (V39)

    WHEEL_Screen (struct Screen *) - Indicate the screen the color
        wheel is to open on. This is a required tag and must be
        provided when the wheel is created via NewObject().

        Applicability is (I). (V39)

    WHEEL_Abbrv (STRPTR) - When the color wheel is rendered on a display
        which doesn't have enough colors to allow it to draw itself
        in color, it automatically renders itself in monochrome
        instead. In such a case, the various color segments are
        identified by six letters G=Green, C=Cyan, B=Blue, M=Magenta,
        R=Red, and Y=Yellow. You can provide a replacement set of six
        letters. This is meant for localization of the wheel.

        Default for this tag is "GCBMRY". Applicability is (I). (V39)

    WHEEL_Donation (UWORD *) - Specifies an array of pens donated by
        the application for use by the color wheel. The array can
        contain any number of pens, and is terminated with a pen
        value of ~0. The wheel will change the RGB values of these
        pens to suit its needs, so be prepared for this. This means
        the pens should likely be allocated using the PENF_EXCLUSIVE
        option of the graphics.library/ObtainPen() function.

        Default for this tag is NULL. Applicability is (I). (V39)

    WHEEL_BevelBox (BOOL) - Set to TRUE if you want a raised bevelled box
        to be drawn around the wheel.

        Default for this tag is FALSE. Applicability is (I). (V39)

    WHEEL_MaxPens (ULONG) - Indicate the maximum number of shared color
        pens the wheel should attempt to allocate. This tag is useful
        if you wish to minimize the impact the wheel can have on your
        screen's pens.

        Default for this tag is 256. Applicability is (I). (V39)

    WHEEL_GradientSlider (struct Gadget *) - This tag lets you do simple
        linking of a gradient slider object to a color wheel object.
        You give this tag a pointer to a gradient slider object
        obtained previously from NewObject(). Once this is done,
        anytime the various tags that can affect the brightness
        component of the current color is sent to the color wheel,
        the color wheel automatically changes the value of the
        attached gradient slider to match that new brightness value.
        Reading the brightness value from the color wheel returns the
        current value indicated by the gradient slider.

        Using this tag effectively allows you to treat the color wheel
        and gradient slider as a single gadget. Once things are set up,
        all communications occur through the wheel object, and the
        gradient slider can pretty much be ignored by the application.

        Default for this tag is NULL. Applicability is (IS). (V39)

    GA_ID (UWORD) - Specify the gadget ID of a color wheel object.
        Applicability is (ISGNU). (V39)

   WARNING
    Once a color wheel has been created on a given screen, the wheel
    object must be deleted using DisposeObject() prior to closing the
    screen. This is because the wheel object allocates pens on the
    screen.

   BUGS
    Even though all communication with the color wheel is done using full
    32-bit color components, color calculations are currently done using
    16-bit math, which can cause certain rounding errors to appear.

    Prior to V40, the WHEEL_Red, WHEEL_Green, and WHEEL_Blue tags
    did not return the correct values when a gradient slider is linked
    with the color wheel using the WHEEL_GradientSlider tag. The
    workaround is to always use the WHEEL_RGB tag, and just extract the
    values from there.


colorwheel.gadget/ConvertHSBToRGB

   NAME
    ConvertHSBToRGB -- convert from an HSB color space to an RGB color
               space. (V39)

   SYNOPSIS
    ConvertHSBToRGB(hsb, rgb);
                A0   A1

    VOID ConvertHSBToRGB(struct ColorWheelHSB *, struct ColorWheelRGB *);

   FUNCTION
    Converts a color from an HSB representation to an RGB representation.

   INPUTS
    hsb - filled-in ColorWheelHSB structure containing the values to
          convert
    rgb - structure to receive the converted values

   BUGS
    Even though all communication with the color wheel is done using full
    32-bit color components, color calculations are currently done using
    16-bit math, which can cause certain rounding errors to appear.


colorwheel.gadget/ConvertRGBToHSB

   NAME
    ConvertRGBToHSB -- convert from an RGB color space to an HSB color
               space. (V39)

   SYNOPSIS
    ConvertRGBToHSB(rgb, hsb);
                A0   A1

    VOID ConvertRGBToHSB(struct ColorWheelRGB *, struct ColorWheelHSB *);

   FUNCTION
    Converts a color from an RGB representation to an HSB representation.

   INPUTS
    rgb - filled-in ColorWheelRGB structure containing the values to
          convert
    hsb - structure to receive the converted values

   BUGS
    Even though all communication with the color wheel is done using full
    32-bit color components, color calculations are currently done using
    16-bit math, which can cause certain rounding errors to appear.


commodities.doc

     ActivateCxObj()
     AddIEvents()
     AttachCxObj()
     ClearCxObjError()
     CreateCxObj()
     CxBroker()
     CxMsgData()
     CxMsgID()
     CxMsgType()
     CxObjError()
     CxObjType()
     DeleteCxObj()
     DeleteCxObjAll()
     DisposeCxMsg()
     DivertCxMsg()
     EnqueueCxObj()
     InsertCxObj()
     InvertKeyMap()
     MatchIX()
     ParseIX()
     RemoveCxObj()
     RouteCxMsg()
     SetCxObjPri()
     SetFilter()
     SetFilterIX()
     SetTranslate()


commodities.library/ActivateCxObj

   NAME
    ActivateCxObj -- change the activation state of a commodity object.
             (V36)

   SYNOPSIS
    previous = ActivateCxObj(co,true);
    D0			 A0 D0

    LONG ActivateCxObj(CxObj *,LONG);

   FUNCTION
    Commodity objects of all types maintain an activation state.
    If an object is "active", then it performs its particular action
    whenever a commodity message arrives. If the object is "inactive"
    no action is taken, and the message goes on to its next destination.

    All objects are created in the "active" state except brokers
    which are created "inactive". Thus, after you create your
    broker and hang a tree of objects off of it, you must remember
    to use this function to activate it. This causes it to divert all
    messages to your tree of objects.

    This function activates 'co' if 'true' is different than 0. and
    deactivates it otherwise. The previous activation state is
    returned.

   INPUTS
    co - the commodity object to affect (may be NULL)
    true - 0 to deactivate the object, anything else to activate it

   RESULTS
    previous - the previous activation state: 0 if the object was
           inactive or if 'co' was NULL, anything else if the object
           was active

   SEE ALSO
    CxBroker()


commodities.library/AddIEvents

   NAME
    AddIEvents -- add input events to commodities' input stream. (V36)

   SYNOPSIS
    AddIEvents(events)
           A0

    VOID AddIEvents(struct InputEvent *);

   FUNCTION
    This function adds a null-terminated linked list of input events to
    the input stream processed by commodities. It is a touch easier than
    using the input device directly.

    The contents of the input events are copied into commodity messages,
    so they may be disposed of as soon as this call returns.

    The messages are initially routed to the first broker in
    commodities' object list.

   INPUTS
    events - the list of input events to add (may be NULL)

   WARNING
    The cx_lib/InvertString() function creates lists of input events that
    are in reverse order. Thus, passing the result of InvertString()
    to this function will insert a series of input events that will
    generate a string that's a mirror image of the string passed to
    InvertString() originally.

    The solution to the above is to either flip the string before
    passing it to InvertString(), or flip the resulting list of input
    events.

   BUGS
    Prior to V40, this function did not copy the data pointed to by
    ie_EventAddress for any events of type IECLASS_NEWPOINTERPOS.

   SEE ALSO
    cx_lib/FreeIEvents()


commodities.library/AttachCxObj

   NAME
    AttachCxObj -- attach a commodity object to the end of an existing
               list of objects. (V36)

   SYNOPSIS
    AttachCxObj(headObj,co);
            A0      A1

    VOID AttachCxObj(CxObj *,CxObj *);

   FUNCTION
    Adds 'co' to the list of objects pointed to by 'headObj'. The
    new object is added at the end of the list.

   INPUTS
    headObj - pointer to a list of objects. If this value is NULL, then
          the entire tree of objects pointed to by 'co' is deleted
          and becomes invalid.
    co - the object to add to the list (may be NULL)

   RESULTS
    If 'co' is NULL, this function will record that fact in the
    internal accumulated error of 'headObj'. This error record
    can be retrieved using CxObjError() and cleared using
    ClearCxObjError().

   BUGS
    Until V38, passing a NULL 'headObj' parameter would cause low-memory
    access and unpredictable results.

   SEE ALSO
    CxObjError(), ClearCxObjError()


commodities.library/ClearCxObjError

   NAME
    ClearCxObjError -- clear the accumulated error value of a commodity
               object. (V36)

   SYNOPSIS
    ClearCxObjError(co);
                      A0

    VOID ClearCxObjError(CxObj *);

   FUNCTION
    This function clears the accumulated error value of commodity object
    'co'.

    It is unwise to do this to a filter if COERR_BADFILTER is set.
    This will fool commodities into thinking the filter is OK. Set
    another valid filter, or leave the error value alone.

   INPUTS
    co - the object to affect (may be NULL)

   SEE ALSO
    CxObjError()


commodities.library/CreateCxObj

   NAME
    CreateCxObj -- create a new commodity object. (V36)

   SYNOPSIS
    co = CreateCxObj(type,arg1,arg2);
    D0		 D0   A0   A1

    CxObj *CreateCxObj(ULONG,LONG,LONG);

   FUNCTION
    This function creates a commodity object of type 'type'. It is not
    proper to call this function directly. Each object creation routine
    except CxBroker() is defined as a macro in <libraries/commodities.h>
    These are independently documented.

    All functions which operate on a commodity object are made with
    a reference to the thirty-two bit value returned by this function
    (or by CxBroker()).

   INPUTS
    type - the type of object to create as defined in
           <libraries/commodities.h>
    arg1 - first argument, meaning depends on 'type'
    arg2 - second argument, meaning depends on 'type'

   RESULTS
    co - a pointer to the new object or NULL if it could not be created.
         A NULL return indicates typically a lack of system memory. Minor
         problems in creating an object, such as providing a bad filter
         description to cx_lib/CxFilter(), typically don't cause failure,
         but are recorded in an internal error field in the new object
         which can be accessed via CxObjError().

   SEE ALSO
    CxObjError(), cx_lib/CxFilter(), cx_lib/CxSender(),
    cx_lib/CxSignal(), cx_lib/CxTranslate(), cx_lib/CxDebug(),
    cx_lib/CxCustom(), CxBroker()


commodities.library/CxBroker

   NAME
    CxBroker -- create a commodity broker. (V36)

   SYNOPSIS
    broker = CxBroker(nb,error);
    D0		  A0 D0

    CxObj *CxBroker(struct NewBroker *,LONG *);

   FUNCTION
    This function creates a broker from the specification found in the
    NewBroker structure pointed to by 'nb'. The purpose and meaning of the
    fields of the NewBroker structure are described below. Also see
    <libraries/commodities.h> for more info.

    struct NewBroker
    {
        BYTE            nb_Version;
        STRPTR          nb_Name;
        STRPTR          nb_Title;
        STRPTR          nb_Descr;
        WORD            nb_Unique;
        WORD	    nb_Flags;
        BYTE            nb_Pri;
        struct MsgPort *nb_Port;
        WORD            nb_ReservedChannel;
    };

    nb_Version
    This is the way that future versions of commodities can identify
    which version of the NewBroker structure you are using. This should be
    set to NB_VERSION as defined in <libraries/commodities.h>

    nb_Name
    This is the name of the broker. This name is used to find the broker
    in commodities' object list and is the name shown in the listview
    gadget of the Exchange program. The name string is copied in the
    broker object upon creation so it can be discarded right after
    CxBroker() returns. The maximum length of the name string is defined
    by a constant in <libraries/commodities.h>.

    nb_Title, nb_Descr
    These are two strings which appear to the user in the Exchange
    program and describe the application the broker is representing.
    Note that these strings are copied into the broker object so they
    can be discarded right after CxBroker() returns. The maximum length
    of these strings that will be recognized are defined by constants in
    <libraries/commodities.h>.

    nb_Unique
    This field indicates what should happen if a broker of the same name
    (nb_Name) already exists in commodities' object list. Constants
    in <libraries/commodities.h> allow the caller to specify whether
    another broker is to be created, and whether any existing broker of
    the same name should be notified that an attempt at creating a
    duplicate has been made.

    nb_Pri
    This specifies with what priority the new broker is to be inserted
    within commodities' object list. Higher priority nodes appear
    earlier in a list. It is strongly recommended that the ToolTypes
    environment of an application be used to allow the end-user to set
    the priority of the broker.

   INPUTS
    nb - an initialized NewBroker structure
    error - a pointer to a longword where to store a failure code (may be
        NULL)

   RESULTS
    broker - a pointer to the broker object or NULL upon failure. If the
         'error' pointer is not NULL, a further diagnostic code is
         placed at that address. Error codes are defined in
         <libraries/commodities.h> and include:

            CBERR_OK
            No problems; broker created OK.

             CBERR_SYSERR
            System problems, not your fault, sign of low memory.

            CBERR_DUP
            The nb_Unique field specified that only one broker of
            'nb_Name' should be allowed, and one already exists.

            CBERR_VERSION
            The version specified in 'nb_Version' is unknown to the
            library.

   SEE ALSO
    SetCxObjPri(), <libraries/commodities.h>


commodities.library/CxMsgData

   NAME
    CxMsgData -- obtain a pointer to a commodity message's data area. (V36)

   SYNOPSIS
    data = CxMsgData(cxm);
    D0		 A0

    APTR CxMsgData(struct CxMsg *);

   FUNCTION
    Most commodity messages contain meaningful data such as an InputEvent
    structure. This function returns a pointer to this data.

    You may get a commodity message from a synchronous (custom object) or
    asynchronous (sender object) source. In the second case, 'data' is
    not valid after you have replied to the message.

   INPUTS
    cxm - the commodity message to get the data pointer from (may be NULL)

   RESULTS
    data - a pointer to the message's data, or NULL if 'cxm' is NULL.
           The meaning of the data varies depending on which kind of
           object is being inspected.

   BUGS
    Until V38, passing a NULL 'cxm' parameter would cause low-memory
    access and unpredictable results.

    Until V40, whenever the data pointer is a (struct InputEvent), the
    ie_EventAddress field of these structures was not reliable whenever
    the message was generated by a sender object.

   SEE ALSO
    cx_lib/CxSender(), cx_lib/CxCustom()


commodities.library/CxMsgID

   NAME
    CxMsgID -- obtain the ID of a commodity message. (V36)

   SYNOPSIS
    id = CxMsgID(cxm);
    D0	     A0

    LONG CxMsgID(struct CxMsg *);

   FUNCTION
    This function returns the value associated with the cause or source
    of the commodity message 'cxm'. Values are provided by the application
    when a sender or custom object is created.

   INPUTS
    cxm - the commodity message to inquire about (must NOT be NULL)

   RESULTS
    id - if not specified by the application, the ID value of a
         commodity message will be 0. It is suggested that using
         non-zero values in your program as a rule may identify some
         possible errors.

   SEE ALSO
    cx_lib/CxSender(), cx_lib/CxCustom()


commodities.library/CxMsgType

   NAME
    CxMsgType -- obtain the type of a commodity message. (V36)

   SYNOPSIS
    type = CxMsgType(cxm);
    D0		 A0

    ULONG CxMsgType(struct CxMsg *);

   FUNCTION
    This function returns the type of a commodity message. Possible values
    of 'type' are defined in <libraries/commodities.h>. Most commodity
    messages are of type CXM_IEVENT.

   INPUTS
    cxm - the commodity message to inquire about (must NOT be NULL)

   RESULTS
       type - the type of the commodity message, possible values are defined
           in <libraries/commodities.h>


commodities.library/CxObjError

   NAME
    CxObjError -- obtain a commodity object's accumulated error. (V36)

   SYNOPSIS
    error = CxObjError(co);
    D0		   A0

    LONG CxObjError(CxObj *);

   FUNCTION
    When a function acting on an object fails, it records the failure
    in the object. This function returns the accumulated error value.
    The values are represented by flag bits defined in
    <libraries/commodities.h>. Several errors may be recorded by multiple
    bits in 'error'.

    The currently defined errors are:

    COERR_ISNULL
      The value of parameter 'co' was in fact NULL. This error
      means "the problem with the object you inquire about is
      that it failed to be created."

      COERR_NULLATTACH
      Using the commodities' list manipulation functions, an attempt was
      made to add a NULL object to the list belonging to 'co'. This allows
      a line of code as follows to exist in an error-tolerant program:

        AttachCxObj(filter,CxSender(myport,MY_ID));

      COERR_BADFILTER
      The most recent filter specification for a filter object
      was faulty. This happens if no sense can be made out of a
      description string, or if an input expression (IX) has an
      invalid format or version byte. When this bit is set in a
      filter's error field, the filter will match nothing, but this
      is not the proper way to "turn off" a filter, use ActivateCxObj().

      COERR_BADTYPE
      A type specific operation, such as SetFilterIX(), was called
      for object 'co', but 'co' isn't of the proper type.

   INPUTS
    co - the commodity object to get the accumulated error from (may be
         NULL)

   RESULTS
    error - the accumulated error, or 0 if 'co' is NULL

   SEE ALSO
    SetFilter(), SetFilterIX(), AttachCxObj(), ActivateCxObj(),
    ClearCxObjError()


commodities.library/CxObjType

   NAME
    CxObjType -- obtain the type of a commodity object. (V36)

   SYNOPSIS
    type = CxObjType(co);
    D0		 A0

    ULONG CxObjType(CxObj *);

   FUNCTION
    This function should not really be necessary. It returns
    the type of a commodity object, which you should already
    know, since you created it in the first place.

   INPUTS
    co - the commodity object to inquire about (may be NULL)

   RESULTS
    type - the type of the commodity object, possible values are
           defined in <libraries/commodities.h>. Returns CX_INVALID
           if 'co' is NULL.

   SEE ALSO
    CreateCxObj()


commodities.library/DeleteCxObj

   NAME
    DeleteCxObj -- delete a commmodity object. (V36)

   SYNOPSIS
    DeleteCxObj(co);
                A0

    VOID DeleteCxObj(CxObj *);

   FUNCTION
    Deletes a commodity object of any type. If the object
    is linked into a list, it is first removed. Note that
    the handle 'co' is invalid after this function is called.

    Also note that deleting an object which has other objects attached
    to it may be undesirable. Use the function DeleteCxObjAll()
    to delete an entire sub-tree of objects.

   INPUTS
    co - the commodity object to delete (may be NULL)

   SEE ALSO
    DeleteCxObjAll()


commodities.library/DeleteCxObjAll

   NAME
    DeleteCxObjAll -- recursively delete a tree of commodity objects.
              (V36)

   SYNOPSIS
    DeleteCxObjAll(co);
               A0

    VOID DeleteCxObjAll(CxObj *);

   FUNCTION
    This function deletes the commodity object 'co', and
    recursively deletes all objects attached to it, and the
    objects attached to them, etc.

    If 'co' is linked into a list, it is first removed. Note
    that the handle 'co' is invalid after this function is called.

    This function is useful when an application exits: most
    applications can clean up completely by deleting the
    entire sub-tree of objects starting at their broker.

   INPUTS
    co - the first commodity object to delete (may be NULL)

   SEE ALSO
    DeleteCxObj()


commodities.library/DisposeCxMsg

   NAME
    DisposeCxMsg -- delete a commodity message. (V36)

   SYNOPSIS
    DisposeCxMsg(cxm);
             A0

    VOID DisposeCxMsg(struct CxMsg *);

   FUNCTION
    This function eliminates the commodity message pointed to by 'cxm'.
    Can be used to 'swallow' input events by disposing of every commodity
    message of type CXM_IEVENT.

    This function can only be called from within a custom object running
    on the input handler's context. It cannot be called from code running
    on a commodities' context, such as when receiving a CXM_IEVENT message
    from a sender object. CxMsg sent to a commodity program from a sender
    object must be sent back using ReplyMsg().

   INPUTS
    cxm - the commodity message to delete (must NOT be NULL)


commodities.library/DivertCxMsg

   NAME
    DivertCxMsg -- send a commodity message down an object list. (V36)

   SYNOPSIS
    DivertCxMsg(cxm,headObj,returnObj);
            A0  A1      A2

    VOID DivertCxMsg(struct CxMsg *,CxObj *,CxObj *);

   FUNCTION
    This function sends the commodity message 'cxm' down the list of
    objects attached to 'headObj'. The pointer 'returnObj' is first
    pushed onto the routing stack of 'cxm' so that when the end of the
    list of 'headObj' is reached the SUCCESSOR of 'returnObj' is the
    next destination.

    For example, when a filter finds a match with a message, the
    message is diverted down the filter's list like this:

      DivertCxMsg(cxm,filter,filter);

   INPUTS
    cxm - the commodity message to divert (must NOT be NULL)
    headObj - the list of objects to divert the message to
    returnObj - the object to use as a place holder

   SEE ALSO
    RouteCxMsg()


commodities.library/EnqueueCxObj

   NAME
    EnqueueCxObj -- insert a commodity object within a list of objects
                based on object priority. (V36)

   SYNOPSIS
    EnqueueCxObj(headObj,co);
             A0      A1

    VOID EnqueueCxObj(CxObj *,CxObj *);

   FUNCTION
    This function puts object 'co' into the list of object 'headObj'.
    The insertion point is determined by the object's priority. The
    objects are kept in the list from the highest priority to the
    lowest. New nodes are inserted in front of the first node with a
    lower priority. Hence a FIFO queue for nodes of equal priority.

    The priority of the commodity object can be set using SetCxObjPri().

   INPUTS
    headObj - pointer to a list of objects. If this value is NULL, then
          the entire tree of objects pointed to by 'co' is deleted
          and becomes invalid.
    co - the object to add to the list (may be NULL)

   RESULTS
    If 'co' is NULL, this function will record that fact in the
    internal accumulated error of 'headObj'. This error record
    can be retrieved using CxObjError() and cleared using
    ClearCxObjError().

   BUGS
    Until V38, passing a NULL 'headObj' parameter would cause low-memory
    access and unpredictable results.

   SEE ALSO
    SetCxObjPri(), CxObjError(), ClearCxObjError()


commodities.library/InsertCxObj

   NAME
    InsertCxObj -- insert a commodity object in a list after a given
               object. (V36)

   SYNOPSIS
    InsertCxObj(headObj,co,pred);
            A0      A1 A2

    VOID InsertCxObj(CxObj *,CxObj *,CxObj *);

   FUNCTION
    Adds 'co' to the list of objects pointed to by 'headObj' after
    object 'pred'.

   INPUTS
    headObj - pointer to a list of objects. If this value is NULL, then
          the entire tree of objects pointed to by 'co' is deleted
          and becomes invalid.
    co - the object to add to the list (may be NULL)
    pred - the object after which 'co' should be inserted. If this is NULL
           then 'co' is added to the head of the list.

   RESULTS
    If 'co' is NULL, this function will record that fact in the
    internal accumulated error of 'headObj'. This error record
    can be retrieved using CxObjError() and cleared using
    ClearCxObjError().

   BUGS
    Until V38, passing a NULL 'headObj' parameter would cause low-memory
    access and unpredictable results.

   SEE ALSO
    CxObjError(), ClearCxObjError()


commodities.library/InvertKeyMap

   NAME
    InvertKeyMap -- generate an input event from an ANSI code. (V36)

   SYNOPSIS
    success = InvertKeyMap(ansiCode,event,km)
    D0	 	       D0       A0    A1

    BOOL InvertKeyMap(ULONG,struct InputEvent *,struct KeyMap *);

   FUNCTION
    This function uses the system call MapANSI() to figure out what
    InputEvent translates to an ANSI character code 'ansiCode'. The
    InputEvent pointed to by 'event' is filled in with that information.
    The KeyMap 'km' is used for the translation, unless it is NULL, in
    which case the current system default keymap is used.

   INPUTS
    ansiCode - the ANSI code to convert to an input event
    event - the InputEvent to fill-in
    km - the keymap to use for the translation, or NULL to use the
         current system default keymap.

   RESULTS
    success - TRUE if the translation worked, FALSE otherwise.

   BUGS
    This function currently handles one-deep dead keys (such as
    <alt f>o ). It does not look up the high key map (keystrokes
    with scan codes greater than 0x40).

    Prior to V40, this function was not initializing the ie_SubClass
    and ie_TimeStamp fields of the InputEvent structure. A simple work
    around to the problem is to clear these values to 0 before making
    a call to this function:

        struct InputEvent ie;

            ie.ie_SubClass           = 0;
            ie.ie_TimeStamp.tv_secs  = 0;
            ie.ie_TimeStamp.tv_micro = 0;
            if (InvertKeyMap(ansiCode,&ie,NULL))
            ...

   SEE ALSO
    cx_lib/InvertString()


commodities.library/MatchIX

   NAME
    MatchIX -- see if an input event matches an initialized input
           expression. (V38)

   SYNOPSIS
    match = MatchIX(event,ix);
    D0		A0    A1

    BOOL MatchIX(struct InputEvent *,IX *);

   FUNCTION
    This function determines whether an input event matches an
    initialized input expression. Applications generally do not
    need to call this function as filter objects will normally provide
    all the event filtering needed. Nevertheless, MatchIX()
    can come in handy as it is the same function used to match an
    event to the various filter objects when an event makes its way
    through the input network.

   INPUTS
    event - the input event to match against the input expression
    ix - the input expression for the comparison

   RESULTS
    match - TRUE if the input event matches the input expression, or
        FALSE if not

   SEE ALSO
    <libraries/commodities.h>, ParseIX()


commodities.library/ParseIX

   NAME
    ParseIX -- initialize an input expression given a description string.
           (V36)

   SYNOPSIS
    failureCode = ParseIX(description,ix);
    D0		      A0          A1

    LONG ParseIX(STRPTR,IX *);

   FUNCTION
    Given an input description string and an allocated input
    expression, sets the fields of the input expression to
    correspond to the description string.

   INPUTS
    description - the string to parse
    ix - the input expression to hold the result of the parse

   RESULTS
    failureCode -  0 if all went well,
              -1 if tokens after end (code spec)
                  -2 if 'description' was NULL

   SEE ALSO
    <libraries/commodities.h>, MatchIX()


commodities.library/RemoveCxObj

   NAME
    RemoveCxObj -- remove a commodity object from a list. (V36)

   SYNOPSIS
    RemoveCxObj(co);
            A0

    VOID RemoveCxObj(CxObj *);

   FUNCTION
    This function removes 'co' from any list it may be a part of.
    Will not crash if 'co' is NULL, or if it has not been inserted
    in a list.

   INPUTS
    co - the object to remove (may be NULL)

   SEE ALSO
    AttachCxObj(), EnqueueCxObj(), InsertCxObj()


commodities.library/RouteCxMsg

   NAME
    RouteCxMsg -- set the next destination of a commodity message. (V36)

   SYNOPSIS
    RouteCxMsg(cxm,co);
           A0  A1

    VOID RouteCxMsg(struct CxMsg *,CxObj *);

   FUNCTION
    Establishes the next destination of a commodity message
    to be 'co', which must be a valid commodity object, and
    must be linked in ultimately to commodities' object list.

    Routing of an object is analogous to a 'goto' in a program.
    There is no effect on the message's routing stack.

   INPUTS
    cxm - the commodity message to route (must NOT be NULL)
    co - the commodity object to route the message to (must NOT be NULL)

   SEE ALSO
    DivertCxMsg()


commodities.library/SetCxObjPri

   NAME
    SetCxObjPri -- set the priority of a commodity object. (V36)

   SYNOPSIS
    oldPri = SetCxObjPri(co,pri)
    D0                   A0 D0

    LONG SetCxObjPri(CxObj *,LONG);

   FUNCTION
    This function sets the priority of a commodity object for the
    purposes of EnqueueCxObj().

    It is strongly recommended that the ToolTypes environment be
    utilized to provide end-user control over the priority of
     brokers, but application specific ordering of other objects
    within their lists is not dictated.

   INPUTS
    co - the commodity object to affect (may be NULL)
    pri - the object's new priority in the range -128 to +127. A value
          of 0 is normal.

   RESULTS
    oldPri - the previous priority of the object or 0 if 'co' was NULL.
         This value is only returned in V38 and beyond.

   BUGS
    This function will not reposition an object within its list when
    its priority changes. To attain the same effect, first remove the
    object from its list using RemoveCxObj(), set its priority using
    SetCxObjPri(), and reinsert it in the list using EnqueueCxObj().

   SEE ALSO
    EnqueueCxObj()


commodities.library/SetFilter

   NAME
    SetFilter -- change the matching condition of a commodity filter.
             (V36)

   SYNOPSIS
    SetFilter(filter,text);
          A0     A1

    VOID SetFilter(CxObj *,STRPTR);

   FUNCTION
    This function changes the matching condition of a commodity input
    filter to that described by the input description string 'text'.

   INPUTS
    filter - the filter object to affect (may be NULL)
    text - the new matching conditions for the filter

   RESULTS
    The internal error of 'filter' will have the COERR_BADFILTER
    bit set or cleared depending on the failure or success of this
    function.

   SEE ALSO
    SetFilterIX(), CxObjError()


commodities.library/SetFilterIX

   NAME
    SetFilterIX -- change the matching condition of a commodity filter.
               (V36)

   SYNOPSIS
    SetFilterIX(filter,ix);
            A0     A1

    VOID SetFilterIX(CxObj *,IX *);

   FUNCTION
    This function changes the matching condition of a commodity input
    filter to that described by the binary input expression pointed by
    'ix'.

    Input expressions are defined in <libraries/commodities.h>.
    It is important to remember that the first field of the input
    expression structure must indicate which version of the
    input expression structure is being used.

   INPUTS
    filter - the filter object to affect (may be NULL)
    ix - the new matching conditions for the filter

   RESULTS
    The internal error of 'filter' will have the COERR_BADFILTER
    bit set or cleared depending on the failure or success of this
    function.

   SEE ALSO
    SetFilter(), CxObjError()


commodities.library/SetTranslate

   NAME
    SetTranslate -- replace a translator object's translation list. (V36)

   SYNOPSIS
    SetTranslate(translator,events);
             A0         A1

    VOID SetTranslate(CxObj *,struct InputEvent *);

   FUNCTION
    This function replaces the translation list of a commodity
    translator object with the linked list starting at 'events'.

    A NULL value for 'events' indicates that the object 'translator'
    should swallow all commodity messages that are sent its way.

    Note that the input events are not copied into commodities' private
    memory, but the value of 'events' is used -- asynchronously to the
    application program -- to find a chain of InputEvents in the
    application's data space. At the time of translation, each input event
    is copied into its own new commodity message.

    The above means that no other commodities' user, nor
    commodities.library itself will be modifying your list of InputEvents.
    On the other hand, your program must not corrupt the input event
    chain that has been presented to a translator.

   INPUTS
    translator - the translator object to affect (may be NULL)
    events - the new input event translation list

   BUGS
    The list of input events manipulated by a translator object is
    inserted in reverse order in the commodities network, and come out
    of the network in reverse order as well. The cx_lib/InvertString()
    function creates lists of input events that are in reverse order so
    they can be used directly with translator objects.

   SEE ALSO
    <devices/inputevent.h>, cx_lib/CxTranslate()


console.doc

     CD_ASKDEFAULTKEYMAP
     CD_ASKKEYMAP
     CD_SETDEFAULTKEYMAP
     CD_SETKEYMAP
     CDInputHandler()
     CMD_CLEAR
     CMD_READ
     CMD_WRITE
     OpenDevice()
     RawKeyConvert()


console.device/CMD_WRITE

   NAME
    CMD_WRITE -- Write ANSI text to the console display.

   FUNCTION
    Write a text record to the display.  Interpret the ANSI
    control characters in the data as described below.  Note
    that the RPort of the console window is in use while this
    write command is pending.

   IO REQUEST INPUT
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Device	preset by the call to OpenDevice
    io_Unit		preset by the call to OpenDevice
    io_Command	CMD_WRITE
    io_Flags	IOF_QUICK if quick I/O possible, else zero
    io_Length	sizeof(*buffer), or -1 if io_Data is null
            terminated
    io_Data		a pointer to a buffer containing the ANSI text
            to write to the console device.

   IO REQUEST RESULTS
    io_Error	the error result (no errors are reported as of V36)
    io_Actual	the number of bytes written from io_Data
    io_Length	zero
    io_Data		original io_Data plus io_Actual

   ANSI CODES SUPPORTED

    Codes are specified in the standard fashion for ANSI documents,
    as the two 4 bit nibbles that comprise the character code,
    high nibble first, separated by a slash.  Thus 01/11 (ESC) is
    a character with the hex value 1B (or the decimal value 27).

    A character on the Amiga falls into one of the following four
    ranges:
    00/ 0-01/15	C0: ASCII control characters.  See below.
    02/ 0-07/15	G0: ASCII graphic characters.  These characters
            have an image that is displayed.  Note that the
            DEL character is displayed by the Console Device:
            it is not treated as control character here.
    08/ 0-09/15	C1: ANSI 3.41 control characters.  See below.
    10/ 0-15/15	G1: ECMA 94 Latin 1 graphic characters.

    Independent Control Functions (no introducer) --
    Code	Name	Definition
    -----	---	----------------------------------------------
    00/ 7	BEL	BELL: actually an Intuition DisplayBeep()
    00/ 8	BS	BACKSPACE
    00/ 9	HT	HORIZONTAL TAB
    00/10	LF	LINE FEED
    00/11	VT	VERTICAL TAB
    00/12	FF	FORM FEED
    00/13	CR	CARRIAGE RETURN
    00/14	SO	SHIFT OUT: causes all subsequent G0 (ASCII)
            characters to be shifted to G1 (ECMA 94/1)
            characters.
    00/15	SI	SHIFT IN: cancels the effect of SHIFT OUT.
    01/11	ESC	ESCAPE

    Code or Esc Name Definition
    -----	--- ---- ---------------------------------------------
    08/ 4	D   IND	 INDEX: move the active position down one line.
    08/ 5	E   NEL	 NEXT LINE
    08/ 8	H   HTS  HORIZONTAL TABULATION SET
    08/13	M   RI	 REVERSE INDEX
    09/11	[   CSI	 CONTROL SEQUENCE INTRODUCER: see next list

    ISO Compatible Escape Sequences (introduced by Esc) --
    Esc   Name Definition
    ----- ---- ---------------------------------------------------
    c     RIS  RESET TO INITIAL STATE: reset the console display.

    Control Sequences, with the number of indicated parameters.
    i.e. <CSI><parameters><control sequence letter(s)>.  Note the
    last entries consist of a space and a letter.  CSI is either
    9B or Esc[.  A minus after the number of parameters (#p)
    indicates less is valid.  Parameters are separated by
    semicolons, e.g. Esc[14;80H sets the cursor position to row
    14, column 80.
    CSI #p	Name Definition
    --- --- ---- -------------------------------------------------
    @   1-	ICH  INSERT CHARACTER
    A   1-	CUU  CURSOR UP
    B   1-	CUD  CURSOR DOWN
    C   1-	CUF  CURSOR FORWARD
    D   1-	CUB  CURSOR BACKWARD
    E   1-	CNL  CURSOR NEXT LINE
    F   1-	CPL  CURSOR PRECEDING LINE
    H   2-	CUP  CURSOR POSITION
    I   1-	CHT  CURSOR HORIZONTAL TABULATION
    J   1-	ED   ERASE IN DISPLAY (only to end of display)
    K   1-	EL   ERASE IN LINE (only to end of line)
    L   1-	IL   INSERT LINE
    M   1-	DL   DELETE LINE
    P   1-	DCH  DELETE CHARACTER
    R   2	CPR  CURSOR POSITION REPORT (in Read stream only)
    S   1-	SU   SCROLL UP
    T   1-	SD   SCROLL DOWN
    W   n	CTC  CURSOR TABULATION CONTROL
    Z   1-	CBT  CURSOR BACKWARD TABULATION
    f   2-	HVP  HORIZONTAL AND VERTICAL POSITION
    g   1-	TBC  TABULATION CLEAR
    h   n	SM   SET MODE: see modes below.
    l   n	RM   RESET MODE: see modes below.
    m   n	SGR  SELECT GRAPHIC RENDITION
    n   1-	DSR  DEVICE STATUS REPORT
    t   1-	aSLPP SET PAGE LENGTH (private Amiga sequence)
    u   1-	aSLL  SET LINE LENGTH (private Amiga sequence)
    x   1-	aSLO  SET LEFT OFFSET (private Amiga sequence)
    y   1-	aSTO  SET TOP OFFSET (private Amiga sequence)
    {   n	aSRE  SET RAW EVENTS (private Amiga sequence)
    |   8	aIER  INPUT EVENT REPORT (private Amiga Read sequence)
    }   n	aRRE  RESET RAW EVENTS (private Amiga sequence)
    ~   1	aSKR  SPECIAL KEY REPORT (private Amiga Read sequence)
     p  1-	aSCR  SET CURSOR RENDITION (private Amiga sequence)
     q  0	aWSR  WINDOW STATUS REQUEST (private Amiga sequence)
     r  4	aWBR  WINDOW BOUNDS REPORT (private Amiga Read sequence)
     s  0	aSDSS SET DEFAULT SGR SETTINGS (private Amiga sequence-V39)
     v  1	aRAV  RIGHT AMIGA V PRESS (private Amiga Read sequence-V37)

    Modes, set with <CSI><mode-list>h, and cleared with
    <CSI><mode-list>l, where the mode-list is one or more of the
    following parameters, separated by semicolons --
    Mode	Name Definition
    ------- ---- -------------------------------------------------
    20	LNM  LINEFEED NEWLINE MODE: if a linefeed is a newline
    >1	ASM  AUTO SCROLL MODE: if scroll at bottom of window
    ?7	AWM  AUTO WRAP MODE: if wrap at right edge of window

    NOTES
    The console.device recognizes these SGR sequences.
    Note that some of these are new to V36.

    SGR (SELECT GRAPHICS RENDITION)
        Selects colors, and other display characteristics
        for text.

    Syntax:
        <ESC>[graphic-rendition...m

    Example:
        <ESC>[1;7m   (sets bold, and reversed text)

    Parameters:

        0	- Normal colors, and attributes
        1	- Set bold
        2	- Set faint (secondary color)
        3	- Set italic
        4	- Set underscore
        7	- Set reversed character/cell colors
        8	- Set concealed mode.
        22	- Set normal color, not bold	(V36)
        23	- Italic off			(V36)
        24	- Underscore off		(V36)
        27	- Reversed off			(V36)
        28	- Concealed off			(V36)

        30-37	- Set character color
        39	- Reset to default character color

        40-47	- Set character cell color
        49	- Reset to default character cell color

        >0-7	- Set background color		(V36)
              Used to set the background color before
              any text is written.  The numeric parameter
              is prefixed by ">".  This also means that if
              you issue an SGR command with more than one
              parameter, you must issue the digit only
              parameters first, followed by any prefixed
              parameters.

    V39 console.device takes advantage of the ability to mask
    bitplanes for faster scrolling, clearing, and rendering.
    The actual number of bitplanes scrolled depends on which
    colors you set via the SGR sequences.  For those using
    the defaults of PEN color 1, and cell color 0, console.device
    only needs to scroll 1 bitplane.  The actual number
    of bitplanes scrolled is reset when ESCc is sent, and when
    the console window is entirely cleared (e.g., FF).  In
    general this should cause no compatability problems, unless
    you are mixing console rendering with graphic.library calls
    in the same portions of your window.  Console.device considers
    the number of bitplanes it must scroll, and the screen display
    depth so that interleaved bitplane scrolling can be taken
    advantage of in cases where performance is not significantly
    affected (interleaved scrolling, and masking are mutually
    exclusive).  The determination of how many planes to scroll
    is undefined, and may change in the future.

    V39 console.device supports a new private sequence (aSDSS)
    intended for use by users who prefer to change their default
    SGR settings.  When this private Amiga sequence is sent to the
    console, the current Pen color, Cell color, Text style, and
    Reverse mode (on or off), are set as defaults.  When ESC[0m
    is issued, the settings are restored to the preferred settings.
    ESC[39m, and ESC[49m are likewise affected.  In general
    applications should not make use of this private sequence as it
    is intended for users who would normally include it as part of
    their shell startup script.  The normal defaults are reset
    when ESCc is issued.

    BUGS
    Does not correctly display cursor in SuperBitMap layers for
    versions prior to V36.

    Concealed mode should not be used prior to V39 console.device.
    Prior to V39 concealed mode masked all rastport output, the
    effect of which varied.  As of V39, text output is simply
    hidden by setting the pen colors.  Scrolling, clearing,
    cursor rendering, etc., are unaffected.  For maximum
    compatability it is recommended you simply set the colors
    yourself, and not used concealed mode.

    V36-V37 character mapped mode console.device windows could
    crash, or behave erratically if you scroll text DOWN more
    than a full window's worth of text.  This bug has been fixed
    in V39 console.  The only work-around is to avoid sending
    scroll down, or cursor up commands which exceed the window
    rows (this is not a problem for unit 0 console windows).

    SEE ALSO
    ROM Kernel Manual (Volume 1), exec/io.h


datatypes.doc

     --background--
     --rexxhost--
     AddDTObject()
     DisposeDTObject()
     DoAsyncLayout()
     DoDTMethodA()
     DrawDTObjectA()
     GetDTAttrsA()
     GetDTMethods()
     GetDTString()
     GetDTTriggerMethods()
     NewDTObjectA()
     ObtainDataTypeA()
     ObtainDTDrawInfoA()
     PrintDTObjectA()
     RefreshDTObjectA()
     ReleaseDataType()
     ReleaseDTDrawInfo()
     RemoveDTObject()
     SetDTAttrsA()


datatypes.library/--background--

   PURPOSE
    The datatypes.library provides transparent data handling
    abilities to applications.  Application developers can register
    their data format with datatypes.library and provide a class
    library for handling their data within other applications.

   OVERVIEW

    * Object Oriented

    datatypes.library implementation is object oriented, using the
    boopsi functions of Intuition.  Each data class is implemented
    as a shared system library.

    * Embedded Objects

    datatypes.library provides the ability to embed different object
    types within an application.  For example, an application can
    embed an picture object or even an AmigaGuide document browser
    within their application's window.  Objects can also be embedded
    within other objects.

    * Gadget-like

    Embedded objects are actually boopsi gadgets.  That means that
    input handling is done on Intuition's task.  Time intensive
    operations, such as layout when the window size changes, are
    off-loaded to a sub-process.  Printing, clipboard operations,
    file read/write are also off-loaded to a separate process on an
    as-needed basis.

    * Trigger Methods

    Sometimes it is necessary for an application to provide
    additional controls for navigating through an object.  For
    example, with an AmigaGuide object it is necessary to have
    controls for "Contents", "Index", "Browse >", "Browse <".  Each
    class implements a method that returns the trigger methods, and
    the appropriate labels, that a class supports.

    * Format Conversion

    As long as the objects are sub-classes of the same class, data
    from one format can be written out as another format.  For
    example, it is possible to read in an ILBM file and write out a
    JPEG file, since both data types are sub-classes of PICTURE.

    * Future Compatible

    Each class implements a method that returns the supported
    methods within a class.  This way an application can ask an
    object if it is capable of any particular method, such as
    DTM_WRITE for example.

    * Data Type Detection

    datatypes.library provides the ability to examine a file or
    the clipboard to determine what type of data it contains.


datatypes.library/--rexxhost--

   HOST INTERFACE
    datatypes.library provides an ARexx function host interface that
    enables ARexx programs to take advantage of the features of data
    types.  The functions provided by the interface are directly
    related to the functions described herein, with the differences
    mostly being in the way they are called.

    The function host library vector is located at offset -30 from
    the library. This is the value you provide to ARexx in the
    AddLib() function call.

   FUNCTIONS
    ExamineDT(FILENAME/A,VARIABLENAME,STEM/S,VAR/S)

   EXAMPLE
    /* datatypes.rexx */
    PARSE ARG fname
    OPTIONS RESULTS

    /* Load the datatypes.library as a function host */
    IF ~SHOW('L','datatypes.library') THEN
       CALL ADDLIB('datatypes.library',0,-30)

       IF fname="" THEN DO
          SAY "Usage:"
          SAY "  rx datatypes <filename>"
          EXIT
       END

       SAY 'var test'
       type = ExamineDT(fname,,VAR)
       SAY type

       SAY 'stem test'
       CALL ExamineDT(fname,dtstem.,STEM)

       SAY '      Disk Key:' dtstem.DiskKey
       SAY 'Dir Entry Type:' dtstem.DirEntryType
       SAY '     File Name:' dtstem.FileName
       SAY '    Protection:' dtstem.Protection
       SAY '    Entry Type:' dtstem.EntryType
       SAY '          Size:' dtstem.Size
       SAY '        Blocks:' dtstem.NumBlocks
       SAY '          Date:' dtstem.Date
       SAY '       Comment:' dtstem.Comment
       SAY '          Type:' dtstem.BaseType
       SAY '     File Type:' dtstem.DataType
       SAY '     Base Name:' dtstem.BaseName
    EXIT


datatypes.library/AddDTObject

    NAME
    AddDTObject - Add an object to a window or requester.   (V39)

    SYNOPSIS
    realposition = AddDTObject (window, requester, object, position);
    d0			    a0      a1	       a2      d0

    LONG AddDTObject (struct Window *, struct Requester *,
              Object *, LONG);

    FUNCTION
    This function adds a single object to the gadget list of the given
    window or requester at the position in the list specified by the
    position argument.

    When the object is added to the gadget list, the object will
    receive a GM_LAYOUT message with the gpl_Initial field set to
    one.

    INPUTS
    window - Pointer to the window.

    requester - Must be NULL.

    object - Pointer to an object as returned by NewDTObjectA().

    position - Integer position in the list for the new gadget.
        -1 to add to the end of the list.

    RETURNS
    Returns the position of where the object was actually added.

    SEE ALSO
    RemoveDTObject(), intuition.library/AddGList()


datatypes.library/DisposeDTObject

    NAME
    DisposeDTObject - Delete a data type object.            (V39)

    SYNOPSIS
    DisposeDTObject (o);
             a0

    VOID DisposeDTObject (Object *);

    FUNCTION
    This function is used to dispose of a data type object that was
    obtained with NewDTObjectA().

    INPUTS
    o - Pointer to an object as returned by NewDTObjectA().
        NULL is a valid input.

    SEE ALSO
    NewDTObjectA()


datatypes.library/DoAsyncLayout

    NAME
    DoAsyncLayout - Call the DTM_ASYNCLAYOUT method on a separate process.
                                                               (V39)

    SYNOPSIS
    retval = DoAsyncLayout (object, gpl);
    d0			a0	a1

    ULONG DoAsyncLayout (Object *, struct gpLayout *);

    FUNCTION
    This function is used to asyncronously perform the object's
    DTM_ASYNCLAYOUT method.  This is used to offload the layout method
    from input.device.

    The DTM_ASYNCLAYOUT method must exit when SIGBREAKF_CTRL_C signal
    is set.   This indicates that the data has become obsolete and
    the DTM_ASYNCLAYOUT method will be called again.

    INPUTS
    object - Pointer to the data types object.
    gpl - Pointer to a gpLayout message.

    RETURNS

    SEE ALSO


datatypes.library/DoDTMethodA

    NAME
    DoDTMethodA - Do a datatypes method.                    (V39)

    SYNOPSIS
    retval = DoDTMethodA (o, win, req, msg);
    d0		      a0 a1   a2   a3

    ULONG DoDTMethodA (Object *, struct Window *,
               struct Requester *, Msg);

    retval = DoDTMethod (o, win, req, data, ...);

    ULONG DoDTMethod (Object *, struct Window *,
              struct Requester *, ULONG, ...);

    FUNCTION
    This function is used to perform a datatypes method.

    INPUTS
    o - Pointer to an object as returned by NewDTObjectA().

    win - Window that the object is attached to.

    req - Requester that the object is attached to.

    msg - The message to send to the object.

    RETURNS
    Returns the value returned by the method.

    SEE ALSO
    intuition.library/DoGadgetMethod()


datatypes.library/DrawDTObjectA

    NAME
    DrawDTObjectA - Draw a DataTypes object.                (V44)

    SYNOPSIS
    retval = DrawDTObjectA (rp, o, x, y, w, h, th, tv, attrs);
    d0			a0  a1 d0 d1 d2 d3 d4  d5  a2

    LONG DrawDTObjectA (struct RastPort *rp, Object *, LONG x, LONG y,
                LONG w, LONG h, LONG th, LONG tv,
                struct TagItem *);

    retval = DrawDTObject (rp, o, x, y, w, h, th, tv, tag1, ...);

    LONG DrawDTObjectA (struct RastPort *rp, Object *, LONG x, LONG y,
                LONG w, LONG h, LONG th, LONG tv, Tag, ...);

    FUNCTION
    This function is used to draw a DataTypes object into a RastPort.

    This function can be used for strip printing the object or
    embedding it within a document.

    You must successfully call ObtainDTDrawInfoA() before using
    this function.

    This function invokes the object's DTM_DRAW method.

    Clipping MUST be turned on within the RastPort.  This means
    that there must be a valid layer structure attached to the
    RastPort.

    INPUTS
    rp - Pointer to the RastPort to draw into.
    o - Pointer to an object returned by NewDTObjectA().
    x - Left-most point of area to draw into.
    y - Top-most point of area to draw into.
    w - Width of area to draw into.
    h - Height of area to draw into.
    th - Horizontal top in units.
    tv - Vertical top in units.
    attrs - Additional attributes.

    TAGS
    none defined at this time.

    RETURNS
    TRUE to indicate that it was able to render, FALSE on failure.

    SEE ALSO
    ObtainDTDrawInfo(), ReleaseDTDrawInfo()


datatypes.library/GetDTAttrsA

    NAME
    GetDTAttrsA - Obtain attributes for an object.          (V39)

    SYNOPSIS
    retval = GetDTAttrsA (o, attrs);
    d0		      a0  a2

    ULONG GetDTAttrsA (Object *, struct TagItem *);

    retval = GetDTAttrs (o, tag1, ...);

    ULONG GetDTAttrs (Object *, Tag tag1, ...);

    FUNCTION
    This function is used to get the attributes of a data type
    object.

    INPUTS
    o - Pointer to an object as returned by NewDTObjectA().

    attrs - Attributes to get, terminated with TAG_DONE.  The data
        element of each pair contains the address of the storage
        variable.

    RETURNS
    retval - Contains the number of attributes the system was able
        to obtain.

    SEE ALSO
    SetDTAttrsA(), intuition.library/GetAttr()


datatypes.library/GetDTMethods

    NAME
    GetDTMethods - Obtain methods an object supports.       (V39)

    SYNOPSIS
    methods = GetDTMethods (object);
    d0			a0

    ULONG GetDTMethods (Object *);

    FUNCTION
    This function is used to obtain a list of methods that an
    object supports.

    INPUTS
    object - Pointer to an object as returned by NewDTObjectA().

    RETURNS
    Returns a pointer to a ~0 terminated ULONG array.  This array
    is only valid until the object is disposed off.

    SEE ALSO
    GetDTTriggerMethods()


datatypes.library/GetDTString

    NAME
    GetDTString - Obtain a DataTypes string.                (V39)

    SYNOPSIS
    str = GetDTString (id);
    d0		   d0

    STRPTR GetDTString (ULONG id);

    FUNCTION
    This function is used to obtain a pointer to a localized
    DataTypes string.

    INPUTS
    id - ID of the string to obtain.

    RETURNS
    A pointer to a NULL terminated string.

    SEE ALSO


datatypes.library/GetDTTriggerMethods

    NAME
    GetDTTriggerMethods - Obtain trigger methods supported by an object
                                                               (V39)

    SYNOPSIS
    methods = GetDTTriggerMethods (object);
    d0				a0

    struct DTMethods *GetDTTriggerMethods (Object *);

    FUNCTION
    This function is used to obtain a list of trigger methods that an
    object supports.  This is so that an application can provide
    the appropriate controls for an object.  For example, an AmigaGuide
    object needs controls for "Contents", "Index", "Retrace", "Browse <",
    and "Browse >",

    INPUTS
    object - Pointer to an object as returned by NewDTObjectA().

    RETURNS
    Returns a pointer to a NULL terminated DTMethod list.  This list is
    only valid until the object is disposed off.

    EXAMPLE
    To call the method:

        DoMethod (object, DTM_TRIGGER, dtm[button]->dtm_Method);

    SEE ALSO
    GetDTMethods()


datatypes.library/NewDTObjectA

    NAME
    NewDTObjectA - Create an data type object.              (V39)

    SYNOPSIS
    o = NewDTObjectA (name, attrs);
    d0		  d0   a0

    Object *NewDTObjectA (APTR, struct TagItem *);

    o = NewDTObject (name, tag1, ...);

    Object *NewDTObject (APTR, Tag tag1, ...);

    FUNCTION
    This is the method for creating datatype objects from
    'boopsi' classes.  Boopsi' stands for "basic object-oriented
    programming system for Intuition".)

    You further specify initial "create-time" attributes for the
    object via a TagItem list, and they are applied to the
    resulting datatype object that is returned.

    INPUTS
    name - Name of the data source.  Usually an existing file name.

    attrs - Pointer to a taglist containing additional arguments.

    TAGS
    DTA_SourceType - Specify the type of source data; such as coming
        from a file or clipboard (defaults to DTST_FILE).  If
        source type is clipboard, then the name field contains the
        numeric clipboard unit. If source type is DTST_MEMORY,
        the name field will be ignored (V44).

    DTA_Handle - Can optionally be used instead of the name field.
        Must be a valid FileHandle if DTA_SourceType is DTST_FILE.
        Must be a valid IFFHandle if DTA_SourceType is DTST_CLIPBOARD.
        Will be ignored if DTA_SourceType is DTST_MEMORY.

    DTA_DataType - Specify the class of data.  Data is a pointer to a
        valid DataType.  This is only used when attempting to create
        a new object that doesn't have any source data.

    DTA_GroupID - Specify that the object must be of this type, or
        NewDTObject() will fail with IoErr() of
        ERROR_OBJECT_WRONG_TYPE.

    DTA_SourceAddress (APTR) -- For DTST_MEMORY source data, this
        specifies the memory address at which the source data is
        located. This must be non-NULL. This attribute is required
        for DTST_MEMORY source data (V44).

    DTA_SourceSize (ULONG) -- For DTST_MEMORY source data, this
        specifies the size of the source data (in bytes). This must
        be greater than 0. This attribute is required for DTST_MEMORY
        source data (V44).

    GA_Left, GA_RelRight, GA_Top, GA_RelBottom, GA_Width, GA_RelWidth,
    GA_Height, GA_RelHeight - Specify the placement of the object
        within the destination window.

    GA_ID - Specify the object ID.

    GA_UserData - Specify the application specific data for the
        object.

    RETURNS
    A boopsi object, which may be used in different contexts such
    as a gadget or image, and may be manipulated by generic functions.
    You eventually free the object using DisposeDTObject().

    A NULL return indicates failure.  Use IoErr() to get error value.
    Following is a summary of the error number used and there meaning
    as it relates to DataTypes.

    ERROR_REQUIRED_ARG_MISSING - Indicates that a required attribute
        wasn't passed in.
    ERROR_BAD_NUMBER - An invalid group ID was passed in.
    ERROR_OBJECT_WRONG_TYPE - Object data type doesn't match
        DTA_GroupID.
    ERROR_NO_FREE_STORE - Not enough memory.
    DTERROR_UNKNOWN_DATATYPE - Unable to open the class library
        associated with the data type.
    DTERROR_COULDNT_OPEN - Unable to open the data object.
    ERROR_NOT_IMPLEMENTED - Unknown handle type.

    NOTES
    This function invokes the OM_NEW "method" for the class specified.

    The DTST_MEMORY source type introduced in V44 makes in-memory
    data available to subclasses as if the data were stored in a
    file. Thus, subclasses will see the data as DTST_FILE. Since
    the data does not correspond to an on-disk file, subclasses
    and examine hook code must not assume that they will be able
    to reopen the "file" whose data has been provided to them.

    EXAMPLE
    STRPTR fileName = "s:startup-sequence"
    Object *o;

    /* Simplest use is to just open an existing file */
    if (o = NewDTObject ((APTR)fileName, NULL))
    {
        /* Free the object when we are done with it */
        DisposeDTObject (o);
    }

    SEE ALSO
    AddDTObject(), DisposeDTObject(), RemoveDTObject(),
    intuition.library/NewObjectA()


datatypes.library/ObtainDataTypeA

   NAME
    ObtainDataTypeA - Examines a handle and return its DataType.
                                                               (V39)
   SYNOPSIS
    dtn = ObtainDataTypeA (type, handle, attrs);
    d0			d0    a0      a1

    struct DataType *ObtainDataTypeA (ULONG, APTR, struct TagItem *);

    dtn = ObtainDataType (type, handle, tag1, ...);

    struct DataType *ObtainDataType (ULONG, APTR, Tag tag1, ...);

   FUNCTION
    This function examines the data that the handle points to,
    and returns a DataType record that describes the data.

   INPUTS
    type - Type of handle.

    handle - Handle to examine.
        For DTST_FILE, handle must be BPTR lock.
        For DTST_CLIPBOARD, handle must be struct IFFHandle *.
        For DTST_MEMORY, handle will be ignored (you need
        to specify the additional information required by this
        source type through the attrs list).

    attrs - Additional attributes (see TAGS).

   TAGS
    DTA_SourceAddress (APTR) -- For DTST_MEMORY source data, this
        specifies the memory address at which the source data is
        located. This must be non-NULL. This attribute is required
        for DTST_MEMORY source data (V44).

    DTA_SourceSize (ULONG) -- For DTST_MEMORY source data, this
        specifies the size of the source data (in bytes). This must
        be greater than 0. This attribute is required for DTST_MEMORY
        source data (V44).

   NOTES
    The datatypes.library maintains a sorted list of all the
    DataType descriptors.  The descriptor can consist of a
    function, a data mask for the first 64 bytes of the data,
    and a name pattern.

    The sort order for the list is:

        Descriptors with a function and no mask or name pattern.
        Descriptors with a function and a mask or name pattern.
        Descriptors with no function and a mask or name pattern.

    Within each group, they are also sorted in descending priority
    and descending mask length.

    The DTST_MEMORY source type introduced in V44 makes in-memory
    data available to subclasses as if the data were stored in a
    file. Thus, subclasses will see the data as DTST_FILE. Since
    the data does not correspond to an on-disk file, subclasses
    and examine hook code must not assume that they will be able
    to reopen the "file" whose data has been provided to them.

   RETURNS
    Success returns a pointer to a DataType.  You must call
    FreeDataType() when you are done with the handle.

    A NULL return indicates failure.  Use IoErr() to get error value.
    Following is a summary of the error number used and there meaning
    as it relates to DataTypes.

    ERROR_NO_FREE_STORE - Not enough memory.
    ERROR_OBJECT_NOT_FOUND - Unable to open the data object.
    ERROR_NOT_IMPLEMENTED - Unknown handle type.

   SEE ALSO
    FreeDataType()


datatypes.library/ObtainDTDrawInfoA

    NAME
    ObtainDTDrawInfoA - Obtain a DataTypes object for drawing. (V44)

    SYNOPSIS
    handle = ObtainDTDrawInfoA (o, attrs);
    d0			    a0 a1

    APTR ObtainDTDrawInfoA (Object *, struct TagItem *);

    handle = ObtainDTDrawInfo (o, tag1, ...);

    APTR ObtainDTDrawInfo (Object *, Tag, ...);

    FUNCTION
    This function is used to prepare a DataTypes object for
    drawing into a RastPort.

    This function will send the DTM_OBTAINDRAWINFO method
    to the object using the opSet message structure.

    INPUTS
    o - Pointer to an object as returned by NewDTObjectA().
    attrs - Additional attributes.

    RETURNS
    Returns a opaque handle that must be passed to ReleaseDTDrawInfo()
    when the application is done drawing the object.

    NOTE
    This function implies a layout operation. Thus, you must not
    add the object in question to a window or requester and use
    ObtainDTDrawInfo() on it.

    TAGS
    none defined at this time.

    SEE ALSO
    DrawDTObjectA(), ReleaseDTDrawInfo()


datatypes.library/PrintDTObjectA

    NAME
    PrintDTObjectA - Call the DTM_PRINT method on a separate process.
                                                               (V39)

    SYNOPSIS
    retval = PrintDTObjectA (object, window, requester, msg);
    d0			 a0	 a1	 a2	    a3

    ULONG PrintDTObjectA (Object *, struct Window *, struct Requester *,
                  struct dtPrint *);

    retval = PrintDTObject (object, window, requester, data, ...);

    ULONG PrintDTObject (Object *, struct Window *, struct Requester *,
                 ULONG, ...);

    FUNCTION
    This function is used to asyncronously perform the object's DTM_PRINT
    method.

    Once the application has performed the PrintDTObjectA() function,
    it must not manipulate the printerIO union until it receives a
    IDCMP_IDCMPUPDATE message that contains the DTA_PrinterStatus
    tag.

    To abort a print, the application sends the DTM_ABORTPRINT method
    to the object.  This in turn signals the print process with a
    SIGBREAKF_CTRL_C.

    INPUTS
    object - Pointer to the DataTypes object.
    window - Pointer to the window that the object has been added to.
    requester - Pointer to the requester that the object has been
        added to.

    RETURNS
    Returns TRUE if successful, FALSE on error.

    SEE ALSO


datatypes.library/RefreshDTObjectA

    NAME
    RefreshDTObjectA - Refresh a datatypes object.          (V39)

    SYNOPSIS
    RefreshDTObjectA (object, window, req, attrs)
               a0	   a1	   a2	a3

    VOID RefreshDTObjectA (Object *, struct Window *,
                    struct Requester *, struct TagItem *);

    RefreshDTObject (object, window, req, tag1, ...);

    VOID RefreshDTObject (Object *, struct Window *,
                   struct Requester *, Tag tag1, ...);

    FUNCTION
    Refreshes the specified object, by sending the GM_RENDER method to
    the object.

    INPUTS
    object - Pointer to an object as returned by NewDTObjectA().

    window - Pointer to the window.

    req - Must be NULL.

    attrs - Additional attributes (currently none are defined).

    SEE ALSO
    AddDTObject(), RemoveDTObject(), intuition.library/RefreshGList()


datatypes.library/ReleaseDataType

    NAME
    ReleaseDataType - Release a DataType structure.         (V39)

    SYNOPSIS
    ReleaseDataType (dtn);
              a0

    VOID ReleaseDataType (struct DataType *);

    FUNCTION
    This function is used to release a DataType structure obtained
    by ObtainDataTypeA().

    INPUTS
    dtn - DataType structure returned by ObtainDataTypeA().  NULL
        is a valid input.

    SEE ALSO
    ObtainDataTypeA()


datatypes.library/ReleaseDTDrawInfo

    NAME
    ReleaseDTDrawInfo - Release a DataTypes object from drawing. (V44)

    SYNOPSIS
    ReleaseDTDrawInfo (o, handle);
               a0 a1

    VOID ReleaseDTDrawInfo (Object *, APTR);

    FUNCTION
    This function is used to release the information obtained
    with ObtainDTDrawInfoA().

    This function invokes the object's DTM_RELEASEDRAWINFO method
    using the opMember message structure.

    INPUTS
    handle - Pointer to an object returned by ObtainDTDrawInfoA().

    SEE ALSO
    DrawDTObjectA(), ObtainDTDrawInfo()


datatypes.library/RemoveDTObject

    NAME
    RemoveDTObject - Remove an object from a window.        (V39)

    SYNOPSIS
    position = RemoveDTObject (window, object);
    d0			    a0	    a1

    LONG RemoveDTObject (struct Window *, Object *);

    FUNCTION
    Removes the object from the window's object list.  This will wait
    until the AsyncLayout process is complete.  The object will
    receive a DTM_REMOVEDTOBJECT message to inform the object it has
    been removed.

    INPUTS
    window - Pointer to the window.

    object - Pointer to an object as returned by NewDTObjectA().

    RETURNS
    Returns the ordinal position of the removed object.  If the
    object wasn't found in the appropriate list then a -1 is
    returned.

    SEE ALSO
    AddDTObject(), intuition.library/RemoveGList()


datatypes.library/SetDTAttrsA

    NAME
    SetDTAttrsA - Set attributes for an object.             (V39)

    SYNOPSIS
    retval = SetDTAttrsA (o, win, req, attrs);
    d0		      a0  a1   a2   a3

    ULONG SetDTAttrsA (Object *, struct Window *, struct Requester *,
               struct TagItem *);

    retval = SetDTAttrs (o, win, req, tag1, ...);

    ULONG SetDTAttrs (Object *, struct Window *, struct Requester *,
              Tag tag1, ...);

    FUNCTION
    This function is used to set the attributes of a data type
    object.

    INPUTS
    o - Pointer to an object as returned by NewDTObjectA().

    win - Window that the object has been added to.

    attrs - Attributes to set, terminated with TAG_DONE.

    TAGS
    see <datatypes/datatypesclass.h> for tags.

    SEE ALSO
    GetDTAttrsA(), intuition.library/SetGadgetAttrsA()


ddebug_lib.doc

     DDoFmt()
     DGetChar()
     DGetNum()
     DMayGetChar()
     DPutChar()
     DPutFmt()
     DPutStr()
     KCmpStr()


ddebug.lib/DDoFmt

   NAME
    DDoFmt -- format data into a character stream.

   SYNOPSIS
    DDoFmt(FormatString, DataStream, PutChProc, PutChData);
          A0	    A1		A2	   A3

   FUNCTION
    perform "C"-language-like formatting of a data stream,
    outputting the result a character at a time

   INPUTS
    FormatString - a "C"-language-like null terminated format
        string, with the following supported % types:
    DataStream - a stream of data that is interpreted according to
        the format string.
    PutChProc - the procedure to call with each character to be
        output, called as:
        PutChProc(Char,  PutChData);
              D0-0:8 A3
        the procedure is called with a null Char at the end of
        the format string.
    PutChData - an address register that passes thru to PutChProc.


ddebug.lib/DGetChar

   NAME
    DGetChar - get a character from the parallel port

   SYNOPSIS
    char = DGetChar()
    D0

   FUNCTION
    get the next character from the parallel port.


ddebug.lib/DGetNum

   NAME
    DGetNum - get a number from the parallel port

   SYNOPSIS
    number = DGetNum()
    D0

   FUNCTION
    get a signed decimal integer from the parallel port.


ddebug.lib/DMayGetChar

   NAME
    DMayGetChar - return a char iff present, but don't block

   SYNOPSIS
    flagChar = DMayGetChar()
    D0

   FUNCTION
    return either a -1, saying that there is no char present, or
    the char that was waiting


ddebug.lib/DPutChar

   NAME
    DPutChar - put a character to the parallel port

   SYNOPSIS
    char = DPutChar(char)
    D0	       D0

   FUNCTION
    put a character to the parallel port.


ddebug.lib/DPutFmt

   NAME
    DPutFmt - print formatted data to the parallel port

   SYNOPSIS
    DPutFmt(format,values)
           A0     A1

   FUNCTION
    print formatted data to the parallel port


ddebug.lib/DPutStr

   NAME
    DPutStr - put a string to the parallel port

   SYNOPSIS
    DPutStr(string)
           A0

   FUNCTION
    put a null terminated string to the parallel port.


ddebug.lib/KCmpStr

   NAME
    KCmpStr - compare two null terminated strings

   SYNOPSIS
    mismatch = KCmpStr(string1, string2)
    D0		  A0	   A1

   FUNCTION
    string1 is compared to string2 using the ASCII collating
    sequence.


debug_lib.doc

     KCmpStr()
     KGetChar()
     KGetNum()
     KMayGetChar()
     KPrintF()
     KPutChar()
     KPutStr()


debug.lib/KCmpStr

   NAME
    KCmpStr - compare two null terminated strings

   SYNOPSIS
    mismatch = KCmpStr(string1, string2)
    D0         A0        A1

   FUNCTION
    string1 is compared to string2 using the ASCII collating
    sequence.  0 indicates the strings are identical.


disk.doc

     AllocUnit()
     FreeUnit()
     GetUnit()
     GetUnitID()
     GiveUnit()
     ReadUnitID()


disk.resource/FreeUnit

   NAME
       FreeUnit - deallocate the disk

   SYNOPSIS
       FreeUnit( unitNum ), DRResource
          D0         A6

    void FreeUnit(LONG);

   FUNCTION
    This routine deallocates one of the units of the disk.  It should
    be called when done with the disk.  Do not call it if you did
    no successfully allocate the disk (there is no protection -- you
    will probably crash the disk system).

   INPUTS
    unitNum -- a legal unit number (zero through three)

   RESULTS

   EXCEPTIONS

   SEE ALSO
    FreeUnit()

   BUGS
    Doesn't check if you own the unit, or even if anyone owns it.


disk.resource/GetUnit

   NAME
       GetUnit - allocate the disk for a driver

   SYNOPSIS
       lastDriver = GetUnit( unitPointer ), DRResource
       D0		      A1             A6

    struct DiscResourceUnit *GetUnit(struct DiscResourceUnit *);

   FUNCTION
    This routine allocates the disk to a driver.  It is either
    immediately available, or the request is saved until the disk
    is available.  When it is available, your unitPointer is
    sent back to you (via ReplyMsg).  You may then reattempt the
    GetUnit.

    Allocating the disk allows you to use the disk's resources.
    Remember however that there are four units to the disk; you are
    only one of them.  Please be polite to the other units (by never
    selecting them, and by not leaving interrupts enabled, etc.).

    When you are done, please leave the disk in the following state:
        dmacon dma bit ON
        dsklen dma bit OFF (write a #DSKDMAOFF to dsklen)
        adkcon disk bits -- any way you want
        intena:disk sync and disk block interrupts -- Both DISABLED
        CIA resource index interrupt -- DISABLED
        8520 outputs -- doesn't matter, because all bits will be
        set to inactive by the resource.
        8520 data direction regs -- restore to original state.

    NOTE: GetUnit() does NOT turn on the interrupts for you.
          You must use AbleICR (for the index interrupt) or intena
          (for the diskbyte and diskblock interrupts) to turn them
          on.  You should turn them off before calling GiveUnit,
          as stated above.

   INPUTS
    unitPtr - a pointer you your disk resource unit structure.
        Note that the message filed of the structure MUST
        be a valid message, ready to be replied to.  Make sure
        ln_Name points to a null-terminated string, preferably
        one that identifies your program.

        You need to set up the three interrupt structures,
        in particular the IS_DATA and IS_CODE fields.  Set them
        to NULL if you don't need that interrupt.  Also, set
        the ln_Type of the interrupt structure to NT_INTERRUPT.
        WARNING: don't turn on a disk resource interrupt unless
        the IS_CODE for that interrupt points to executable code!

        IS_CODE will be called with IS_DATA in A1 when the
        interrupt occurs.  Preserve all regs but D0/D1/A0/A1.
        Do not make assumptions about A0.

   RESULTS
    lastDriver - if the disk is not busy, then the last unit
        to use the disk is returned.  This may be used to
        see if a driver needs to reset device registers.
        (If you were the last user, then no one has changed
        any of the registers.  If someone else has used it,
        then any allowable changes may have been made).  If the
        disk is busy, then a null is returned.

   EXCEPTIONS

   SEE ALSO
    GiveUnit()

   BUGS


disk.resource/GetUnitID

   NAME
       GetUnitID - find out what type of disk is out there

   SYNOPSIS
       idtype = GetUnitID( unitNum ), DRResource
    D0	            D0         A6

    LONG GetUnitID(LONG);

   FUNCTION
    Gets the drive ID for a given unit.  Note that this value may
    change if someone calls ReadUnitID, and the drive id changes.

   INPUTS
    unitNum -- a legal unit number (zero through three)

   RESULTS
    idtype -- the type of the disk drive.  Standard types are
        defined in the resource include file.

   EXCEPTIONS

   SEE ALSO
    ReadUnitID()

   BUGS


disk.resource/GiveUnit

   NAME
       GiveUnit - Free the disk back up

   SYNOPSIS
       GiveUnit(), DRResource
                   A6

    void GiveUnit();

   FUNCTION
    This routine frees the disk after a driver is done with it.
    If others are waiting, it will notify them.

   INPUTS

   RESULTS

   EXCEPTIONS

   SEE ALSO
    GetUnit()

   BUGS
    In pre-V36, GiveUnit didn't check if you owned the unit.  A patch
    for this was part of 1.3.1 SetPatch.  Fixed in V36.


disk.resource/ReadUnitID

   NAME
       ReadUnitID - reread and return the type of drive (V37)

   SYNOPSIS
       idtype = ReadUnitID( unitNum ), DRResource
    D0	               D0         A6

    ULONG ReadUnitID(LONG);

   FUNCTION
    Rereads the drive id for a specific unit (for handling drives
    that change ID according to what sort of disk is in them.  You
    MUST have done a GetUnit before calling this function!

   INPUTS
    unitNum -- a legal unit number (zero through three)

   RESULTS
    idtype -- the type of the disk drive.  Standard types are
        defined in the resource include file.

   EXCEPTIONS

   SEE ALSO
    GetUnitID()

   BUGS


diskfont.doc

     AvailFonts()
     DisposeFontContents()
     NewFontContents()
     NewScaledDiskFont()
     OpenDiskFont()


diskfont.library/AvailFonts

   NAME
    AvailFonts -- Inquire available memory & disk fonts.

   SYNOPSIS
    error = AvailFonts(buffer, bufBytes, flags);
                       A0      D0        D1

    LONG AvailFonts( struct AvailFontsHeader *buffer, LONG bufBytes
        ULONG flags );

   FUNCTION
    AvailFonts fills a user supplied buffer with the structure,
    described below, that contains information about all the
    fonts available in memory and/or on disk.  Those fonts
    available on disk need to be loaded into memory and opened
    via OpenDiskFont, those already in memory are accessed via
    OpenFont.  The TextAttr structure required by the open calls
    is part of the information AvailFonts supplies.

    When AvailFonts fails, it returns the number of extra bytes
    it needed to complete the command.  Add this number to your
    current buffer size, allocate a new buffer, and try again.

   INPUTS
    buffer - memory to be filled with struct AvailFontsHeader
        followed by an array of AvailFonts elements, which
        contains entries for the available fonts and their
        names.

    bufBytes - the number of bytes in the buffer
    flags - AFF_MEMORY is set to search memory for fonts to fill
        the structure, AFF_DISK is set to search the disk for
        fonts to fill the structure.  AFF_SCALED is set to
        not filter out memory fonts that are not designed.
        AFF_BITMAP is set to filter out fonts that are not
        stored in Amiga font format, i.e. to filter out
        outline fonts.  Any combination may be specified.
        AFF_TAGGED is set to fill the buffer with TAvailFonts
        elements instead of AvailFonts elements.

   RESULTS
    buffer - filled with struct AvailFontsHeader followed by the
        [T]AvailFonts elements, There will be duplicate entries
        for fonts found both in memory and on disk, differing
        only by type.  The existance of a disk font in the
        buffer indicates that it exists as an entry in a font
        contents file -- the underlying font file has not been
        checked for validity, thus an OpenDiskFont of it may
        fail.
    error - if non-zero, this indicates the number of bytes needed
        for AvailFonts in addition to those supplied.  Thus
        structure elements were not returned because of
        insufficient bufBytes.

   EXAMPLE
    int afShortage, afSize;
    struct AvailFontsHeader *afh;

    ...

    afSize = 400;
    do {
        afh = (struct AvailFontsHeader *) AllocMem(afSize, 0);
        if (afh) {
            afShortage = AvailFonts(afh, afSize, AFF_MEMORY|AFF_DISK);
            if (afShortage) {
                FreeMem(afh, afSize);
                afSize += afShortage;
            }
        }
        else {
            fail("AllocMem of AvailFonts buffer afh failedn");
            break;
        }
    }
        while (afShortage);

    /*
     * if (afh) non-zero here, then:
     * 1. it points to a valid AvailFontsHeader
     * 2. it must have FreeMem(afh, afSize) called for it after use
     */


diskfont.library/DisposeFontContents

   NAME
    DisposeFontContents -- Free the result from NewFontContents. (V34)

   SYNOPSIS
    DisposeFontContents(fontContentsHeader)
                A1

    VOID DisposeFontContents( struct FontContentsHeader * );

   FUNCTION
    This function frees the array of FontContents entries
    returned by NewFontContents.

   INPUTS
    fontContentsHeader - a struct FontContentsHeader pointer
        returned by NewFontContents.

   EXCEPTIONS
     This command was first made available as of version 34.

    A fontContentsHeader other than one acquired by a call
    NewFontContents will crash.

   SEE ALSO
    NewFontContents() to get structure freed here.


diskfont.library/NewFontContents

   NAME
    NewFontContents -- Create a FontContents image for a font. (V34)

   SYNOPSIS
    fontContentsHeader = NewFontContents(fontsLock,fontName)
       D0                                   A0        A1

    struct FontContentsHeader *NewFontContents( BPTR, char * );

   FUNCTION
    This function creates a new array of FontContents entries
    that describe all the fonts associated with the fontName,
    specifically, all those in the font directory whose name
    is that of the font sans the ".font" suffix.

   INPUTS
    fontsLock - a DOS lock on the FONTS: directory (or other
        directory where the font contents file and associated
        font directory resides).
    fontName - the font name, with the ".font" suffix, which
        is also the name of the font contents file.

   RESULT
    fontContentsHeader - a struct FontContentsHeader pointer.

   EXCEPTIONS
    This command was first made available as of version 34.

    D0 is zero if the fontName is does not have a ".font" suffix,
    if the fontName is too long, if a DOS error occurred, or if
    memory could not be allocated for the fontContentsHeader.

   SEE ALSO
    DisposeFontContents() to free the structure acquired here.


diskfont.library/OpenDiskFont

   NAME
       OpenDiskFont - load and get a pointer to a disk font.

   SYNOPSIS
       font = OpenDiskFont(textAttr)
       D0                  A0

   FUNCTION
       This function finds the font with the specified textAttr on
       disk, loads it into memory, and returns a pointer to the font
       that can be used in subsequent SetFont and CloseFont calls.
       It is important to match this call with a corresponding
       CloseFont call for effective management of font memory.

       If the font is already in memory, the copy in memory is used.
       The disk copy is not reloaded.

   INPUTS
       textAttr - a TextAttr structure that describes the text font
               attributes desired.

   RESULTS
       D0 is zero if the desired font cannot be found.

   NOTES
       As of V36, OpenDiskFont() will automatically attempt to
       construct a font for you if:

               You have requested a font size which does not exist
               as a designed font, and

               You have not set the DESIGNED bit in the ta_Flags
               field of the TextAttr, or TTextAttr struct.

       Constructed fonts are created by scaling a designed font.
       A designed font is one which typically resides on disk,
       or in ROM (e.g., a font which has been designed by hand
       using a drawing tool).  Designed fonts generally look better
       than fonts constructed by the font scaler, but designed
       fonts also require disk space for each font size.

       Always set the DESIGNED bit if you do not want constructed fonts,
       or use AvailFonts() to find out which font sizes already exist.

       As of V37 the diskfont.library supported built-in outline
       fonts.  Then in V38 the outline font engine was moved to
       a new library, "bullet.library."

   BUGS
       This routine will not work well with font names whose file
       name components are longer than the maximum allowed
       (30 characters).


dos.doc

     AbortPkt()
     AddBuffers()
     AddDosEntry()
     AddPart()
     AddSegment()
     AllocDosObject()
     AssignAdd()
     AssignLate()
     AssignLock()
     AssignPath()
     AttemptLockDosList()
     ChangeMode()
     CheckSignal()
     Cli()
     CliInitNewcli()
     CliInitRun()
     Close()
     CompareDates()
     CreateDir()
     CreateNewProc()
     CreateProc()
     CurrentDir()
     DateStamp()
     DateToStr()
     Delay()
     DeleteFile()
     DeleteVar()
     DeviceProc()
     DoPkt()
     DupLock()
     DupLockFromFH()
     EndNotify()
     ErrorReport()
     ExAll()
     ExAllEnd()
     Examine()
     ExamineFH()
     Execute()
     Exit()
     ExNext()
     Fault()
     FGetC()
     FGets()
     FilePart()
     FindArg()
     FindCliProc()
     FindDosEntry()
     FindSegment()
     FindVar()
     Flush()
     Format()
     FPutC()
     FPuts()
     FRead()
     FreeArgs()
     FreeDeviceProc()
     FreeDosEntry()
     FreeDosObject()
     FWrite()
     GetArgStr()
     GetConsoleTask()
     GetCurrentDirName()
     GetDeviceProc()
     GetFileSysTask()
     GetProgramDir()
     GetProgramName()
     GetPrompt()
     GetVar()
     Info()
     Inhibit()
     Input()
     InternalLoadSeg()
     InternalUnLoadSeg()
     IoErr()
     IsFileSystem()
     IsInteractive()
     LoadSeg()
     Lock()
     LockDosList()
     LockRecord()
     LockRecords()
     MakeDosEntry()
     MakeLink()
     MatchEnd()
     MatchFirst()
     MatchNext()
     MatchPattern()
     MatchPatternNoCase()
     MaxCli()
     NameFromFH()
     NameFromLock()
     NewLoadSeg()
     NextDosEntry()
     Open()
     OpenFromLock()
     Output()
     ParentDir()
     ParentOfFH()
     ParsePattern()
     ParsePatternNoCase()
     PathPart()
     PrintFault()
     PutStr()
     Read()
     ReadArgs()
     ReadItem()
     ReadLink()
     Relabel()
     RemAssignList()
     RemDosEntry()
     RemSegment()
     Rename()
     ReplyPkt()
     RunCommand()
     SameDevice()
     SameLock()
     Seek()
     SelectInput()
     SelectOutput()
     SendPkt()
     SetArgStr()
     SetComment()
     SetConsoleTask()
     SetCurrentDirName()
     SetFileDate()
     SetFileSize()
     SetFileSysTask()
     SetIoErr()
     SetMode()
     SetOwner()
     SetProgramDir()
     SetProgramName()
     SetPrompt()
     SetProtection()
     SetVar()
     SetVBuf()
     SplitName()
     StartNotify()
     StrToDate()
     StrToLong()
     SystemTagList()
     UnGetC()
     UnLoadSeg()
     UnLock()
     UnLockDosList()
     UnLockRecord()
     UnLockRecords()
     VFPrintf()
     VFWritef()
     VPrintf()
     WaitForChar()
     WaitPkt()
     Write()
     WriteChars()


dos.library/AddPart

   NAME
    AddPart -- Appends a file/dir to the end of a path (V36)

   SYNOPSIS
    success = AddPart( dirname, filename, size )
    D0                   D1        D2      D3

    BOOL AddPart( STRPTR, STRPTR, ULONG )

   FUNCTION
    This function adds a file, directory, or subpath name to a directory
    path name taking into account any required separator characters.  If
    filename is a fully-qualified path it will totally replace the current
    value of dirname.

   INPUTS
    dirname  - the path to add a file/directory name to.
    filename - the filename or directory name to add.  May be a relative
           pathname from the current directory (example: foo/bar).
           Can deal with leading '/'(s), indicating one directory up
           per '/', or with a ':', indicating it's relative to the
           root of the appropriate volume.
    size     - size in bytes of the space allocated for dirname.  Must
           not be 0.

   RESULT
    success - non-zero for ok, FALSE if the buffer would have overflowed.
          If an overflow would have occured, dirname will not be
          changed.

   BUGS
    Doesn't check if a subpath is legal (i.e. doesn't check for ':'s) and
    doesn't handle leading '/'s in 2.0 through 2.02 (V36).  V37 fixes
    this, allowing filename to be any path, including absolute.

   SEE ALSO
    FilePart(), PathPart()


dos.library/AllocDosObject

   NAME
    AllocDosObject -- Creates a dos object (V36)

   SYNOPSIS
    ptr = AllocDosObject(type, tags)
    D0                    D1    D2

    void *AllocDosObject(ULONG, struct TagItem *)

    ptr = AllocDosObjectTagList(type, tags)
    D0                 	     D1    D2

    void *AllocDosObjectTagList(ULONG, struct TagItem *)

    ptr = AllocDosObjectTags(type, Tag1, ...)

    void *AllocDosObjectTags(ULONG, ULONG, ...)

   FUNCTION
    Create one of several dos objects, initializes it, and returns it
    to you.  Note the DOS_STDPKT returns a pointer to the sp_Pkt of the
    structure.

    This function may be called by a task for all types and tags defined
    in the V37 includes (DOS_FILEHANDLE through DOS_RDARGS and ADO_FH_Mode
    through ADO_PromptLen, respectively).  Any future types or tags
    will be documented as to whether a task may use them.

   INPUTS
    type - type of object requested
    tags - pointer to taglist with additional information

   RESULT
    packet - pointer to the object or NULL

   BUGS
    Before V39, DOS_CLI should be used with care since FreeDosObject()
    can't free it.

   SEE ALSO
    FreeDosObject(), <dos/dostags.h>, <dos/dos.h>


dos.library/AttemptLockDosList

   NAME
    AttemptLockDosList -- Attempt to lock the Dos Lists for use (V36)

   SYNOPSIS
    dlist = AttemptLockDosList(flags)
    D0			    D1

    struct DosList *AttemptLockDosList(ULONG)

   FUNCTION
    Locks the dos device list in preparation to walk the list.  If the
    list is 'busy' then this routine will return NULL.  See LockDosList()
    for more information.

   INPUTS
    flags - Flags stating which types of nodes you want to lock.

   RESULT
    dlist - Pointer to the beginning of the list or NULL.  Not a valid
        node!

   BUGS
    In V36 through V39.23 dos, this would return NULL or 0x00000001 for
    failure.  Fixed in V39.24 dos (after kickstart 39.106).

   SEE ALSO
    LockDosList(), UnLockDosList(), Forbid(), NextDosEntry()


dos.library/CheckSignal

   NAME
    CheckSignal -- Checks for break signals (V36)

   SYNOPSIS
    signals = CheckSignal(mask)
    D0		      D1

    ULONG CheckSignal(ULONG)

   FUNCTION
    This function checks to see if any signals specified in the mask have
    been set and if so, returns them.  Otherwise it returns FALSE.
    All signals specified in mask will be cleared.

   INPUTS
    mask    - Signals to check for.

   RESULT
    signals - Signals specified in mask that were set.

   SEE ALSO


dos.library/DateToStr

   NAME
    DateToStr -- Converts a DateStamp to a string (V36)

   SYNOPSIS
    success = DateToStr( datetime )
    D0                      D1

    BOOL DateToStr(struct DateTime *)

   FUNCTION
    DateToStr converts an AmigaDOS DateStamp to a human
    readable ASCII string as requested by your settings in the
    DateTime structure.

   INPUTS
    DateTime - a pointer to an initialized DateTime structure.

    The DateTime structure should be initialized as follows:

    dat_Stamp - a copy of the datestamp you wish to convert to
          ascii.

    dat_Format - a format	byte which specifies the format	of the
          dat_StrDate.	This can be any	of the following
          (note: If value used is something other than those
          below, the default of	FORMAT_DOS is used):

          FORMAT_DOS:	  AmigaDOS format (dd-mmm-yy).

          FORMAT_INT:	  International	format (yy-mmm-dd).

          FORMAT_USA:	  American format (mm-dd-yy).

          FORMAT_CDN:	  Canadian format (dd-mm-yy).

          FORMAT_DEF:	  default format for locale.

    dat_Flags - a	flags byte.  The only flag which affects this
          function is:

          DTF_SUBST:	  If set, a string such	as Today,
                  Monday, etc.,	will be	used instead
                  of the dat_Format specification if
                  possible.
          DTF_FUTURE:	  Ignored by this function.

    dat_StrDay - pointer to a buffer to receive the day of the
          week string.	(Monday, Tuesday, etc.). If null, this
          string will not be generated.

    dat_StrDate -	pointer	to a buffer to receive the date
          string, in the format	requested by dat_Format,
          subject to possible modifications by DTF_SUBST.  If
          null,	this string will not be	generated.

    dat_StrTime -	pointer	to a buffer to receive the time	of day
          string. If NULL, this	will not be generated.

   RESULT
    success	- a zero return indicates that the DateStamp was
          invalid, and could not be converted.	Non-zero
          indicates that the call succeeded.

   SEE ALSO
    DateStamp(), StrtoDate(), <dos/datetime.h>


dos.library/ErrorReport

   NAME
    ErrorReport -- Displays a Retry/Cancel requester for an error (V36)

   SYNOPSIS
    status = ErrorReport(code, type, arg1, device)
    D0                    D1    D2    D3     D4

    BOOL ErrorReport(LONG, LONG, ULONG, struct MsgPort *)

   FUNCTION
    Based on the request type, this routine formats the appropriate
    requester to be displayed.  If the code is not understood, it returns
    DOS_TRUE immediately.  Returns DOS_TRUE if the user selects CANCEL or
    if the attempt to put up the requester fails, or if the process
    pr_WindowPtr is -1.  Returns FALSE if the user selects Retry.  The
    routine will retry on DISKINSERTED for appropriate error codes.
    These return values are the opposite of what AutoRequest returns.

    Note: this routine sets IoErr() to code before returning.

   INPUTS
    code   - Error code to put a requester up for.
       Current valid error codes are:
        ERROR_DISK_NOT_VALIDATED
        ERROR_DISK_WRITE_PROTECTED
        ERROR_DISK_FULL
        ERROR_DEVICE_NOT_MOUNTED
        ERROR_NOT_A_DOS_DISK
        ERROR_NO_DISK
        ABORT_DISK_ERROR	/* read/write error */
        ABORT_BUSY		/* you MUST replace... */
    type   - Request type:
                       REPORT_LOCK   - arg1 is a lock (BPTR).
                       REPORT_FH     - arg1 is a filehandle (BPTR).
            REPORT_VOLUME - arg1 is a volumenode (C pointer).
            REPORT_INSERT - arg1 is the string for the volumename
                    (will be split on a ':').
                    With ERROR_DEVICE_NOT_MOUNTED puts
                    up the "Please insert..." requester.
    arg1   - variable parameter (see type)
    device - (Optional) Address of handler task for which report is to be
                made.  Only required for REPORT_LOCK, and only if arg1==NULL.

   RESULT
    status - Cancel/Retry indicator (0 means Retry)

   SEE ALSO
    Fault(), IoErr()


dos.library/ExAll

   NAME
    ExAll -- Examine an entire directory (V36)

   SYNOPSIS
    continue = ExAll(lock, buffer, size, type, control)
    D0               D1     D2     D3    D4     D5

    BOOL ExAll(BPTR,STRPTR,LONG,LONG,struct ExAllControl *)

   FUNCTION
    Examines an entire directory.

 Lock must be on a directory.  Size is the size of the buffer supplied.
 The buffer will be filled with (partial) ExAllData structures, as
 specified by the type field.

 Type is a value from those shown below that determines which information is
 to be stored in the buffer.  Each higher value adds a new thing to the list
 as described in the table below:-

    ED_NAME		FileName
    ED_TYPE		Type
    ED_SIZE		Size in bytes
    ED_PROTECTION	Protection bits
    ED_DATE		3 longwords of date
    ED_COMMENT	Comment (will be NULL if no comment)
            Note: the V37 ROM/disk filesystem returns this
            incorrectly as a BSTR.  See BUGS for a workaround.
    ED_OWNER	owner user-id and group-id (if supported)  (V39)

 Thus, ED_NAME gives only filenames, and ED_OWNER gives everything.

 NOTE: V37 dos.library, when doing ExAll() emulation, and RAM: filesystem
 will return an error if passed ED_OWNER.  If you get ERROR_BAD_NUMBER,
 retry with ED_COMMENT to get everything but owner info.  All filesystems
 supporting ExAll() must support through ED_COMMENT, and must check Type
 and return ERROR_BAD_NUMBER if they don't support the type.

 The V37 ROM/disk filesystem doesn't fill in the comment field correctly
 if you specify ED_OWNER.  See BUGS for a workaround if you need to use
 ED_OWNER.

 The ead_Next entry gives a pointer to the next entry in the buffer.  The
 last entry will have NULL in ead_Next.

 The control structure is required so that FFS can keep track if more than
 one call to ExAll is required.  This happens when there are more names in
 a directory than will fit into the buffer.  The format of the control
 structure is as follows:-

 NOTE: the control structure MUST be allocated by AllocDosObject!!!

 Entries:  This field tells the calling application how many entries are
        in the buffer after calling ExAll.  Note: make sure your code
        handles the 0 entries case, including 0 entries with continue
        non-zero.

 LastKey:  This field ABSOLUTELY MUST be initialised to 0 before calling
        ExAll for the first time.  Any other value will cause nasty
        things to happen.  If ExAll returns non-zero, then this field
        should not be touched before making the second and subsequent
        calls to ExAll.  Whenever ExAll returns non-zero, there are more
        calls required before all names have been received.

        As soon as a FALSE return is received then ExAll has completed
        (if IoErr() returns ERROR_NO_MORE_ENTRIES - otherwise it returns
        the error that occured, similar to ExNext.)

 MatchString
        If this field is NULL then all filenames will be returned.  If
        this field is non-null then it is interpreted as a pointer to
        a string that is used to pattern match all file names before
        accepting them and putting them into the buffer.  The default
        AmigaDOS caseless pattern match routine is used.  This string
        MUST have been parsed by ParsePatternNoCase()!

 MatchFunc:
        Contains a pointer to a hook for a routine to decide if the entry
        will be included in the returned list of entries.  The entry is
        filled out first, and then passed to the hook.  If no MatchFunc is
        to be called then this entry should be NULL.  The hook is
        called with the following parameters (as is standard for hooks):

        BOOL = MatchFunc( hookptr, data, typeptr )
                a0	a1	a2
        (a0 = ptr to hook, a1 = ptr to filled in ExAllData, a2 = ptr
         to longword of type).

        MatchFunc should return FALSE if the entry is not to be
        accepted, otherwise return TRUE.

    Note that Dos will emulate ExAll() using Examine() and ExNext()
    if the handler in question doesn't support the ExAll() packet.

   INPUTS
    lock    - Lock on directory to be examined.
    buffer  - Buffer for data returned (MUST be at least word-aligned,
          preferably long-word aligned).
    size    - Size in bytes of 'buffer'.
    type    - Type of data to be returned.
    control - Control data structure (see notes above).  MUST have been
          allocated by AllocDosObject!

   RESULT
    continue - Whether or not ExAll is done.  If FALSE is returned, either
           ExAll has completed (IoErr() == ERROR_NO_MORE_ENTRIES), or
           an error occurred (check IoErr()).  If non-zero is returned,
           you MUST call ExAll again until it returns FALSE.

   EXAMPLE

   eac = AllocDosObject(DOS_EXALLCONTROL,NULL);
   if (!eac) ...
   ...
   eac->eac_LastKey = 0;
   do {
       more = ExAll(lock, EAData, sizeof(EAData), ED_FOO, eac);
       if ((!more) && (IoErr() != ERROR_NO_MORE_ENTRIES)) {
           * ExAll failed abnormally *
           break;
       }
       if (eac->eac_Entries == 0) {
           * ExAll failed normally with no entries *
           continue;                   * ("more" is *usually* zero) *
       }
       ead = (struct ExAllData *) EAData;
       do {
           * use ead here *
           ...
           * get next ead *
           ead = ead->ed_Next;
       } while (ead);

   } while (more);
   ...
   FreeDosObject(DOS_EXALLCONTROL,eac);

   BUGS
    In V36, there were problems with ExAll (particularily with
    eac_MatchString, and ed_Next with the ramdisk and the emulation
    of it in Dos for handlers that do not support the packet.  It is
    advised you only use this under V37 and later.

    The V37 ROM/disk filesystem incorrectly returned comments as BSTR's
    (length plus characters) instead of CSTR's (null-terminated).  See
    the next bug for a way to determine if the filesystem is a V37
    ROM/disk filesystem.  Fixed in V39.

    The V37 ROM/disk filesystem incorrectly handled values greater than
    ED_COMMENT.  Because of this, ExAll() information is trashed if
    ED_OWNER is passed to it.  Fixed in V39.  To work around this, use
    the following code to identify if a filesystem is a V37 ROM/disk
    filesystem:

 // return TRUE if this is a V37 ROM filesystem, which doesn't (really)
 // support ED_OWNER safely

 BOOL CheckV37(BPTR lock)
 {
     struct FileLock *l = BADDR(lock);
     struct Resident *resident;
     struct DosList *dl;
     BOOL result = FALSE;

     dl = LockDosList(LDF_READ|LDF_DEVICES);

     // if the lock has a volume and no device, we won't find it,
    // so we know it's not a V37 ROM/disk filesystem
     do {
         dl = NextDosEntry(dl,LDF_READ|LDF_DEVICES);
         if (dl && (dl->dol_Task == l->fl_Task))
         {
         // found the filesystem - test isn't actually required,
        // but we know the filesystem we're looking for will always
        // have a startup msg.  If we needed to examine the message,
        // we would need a _bunch_ of checks to make sure it's not
        // either a small value (like port-handler uses) or a BSTR.
         if (dl->dol_misc.dol_handler.dol_Startup)
         {
             // try to make sure it's the ROM fs or l:FastFileSystem
             if (resident =
                 FindRomTag(dl->dol_misc.dol_handler.dol_SegList))
             {
                 if (resident->rt_Version < 39 &&
                     (strncmp(resident->rt_IdString,"fs 37.",
                          strlen("fs 37.")) == 0 ||
                      strncmp(resident->rt_Name,"ffs 37.",
                          strlen("ffs 37.")) == 0))
                 {
                     result = TRUE;
                 }
             }
         }
         break;
         }
     } while (dl);

     UnLockDosList(LDF_READ|LDF_DEVICES);

     return result;
 }

   SEE ALSO
    Examine(), ExNext(), ExamineFH(), MatchPatternNoCase(),
    ParsePatternNoCase(), AllocDosObject(), ExAllEnd()


dos.library/ExAllEnd

   NAME
    ExAllEnd -- Stop an ExAll() (V39)

   SYNOPSIS
    ExAllEnd(lock, buffer, size, type, control)
              D1     D2     D3    D4     D5

    ExAllEnd(BPTR,STRPTR,LONG,LONG,struct ExAllControl *)

   FUNCTION
    Stops an ExAll() on a directory before it hits NO_MORE_ENTRIES.
    The full set of arguments that had been passed to ExAll() must be
    passed to ExAllEnd(), so it can handle filesystems that can't abort
    an ExAll() directly.

   INPUTS
    lock    - Lock on directory to be examined.
    buffer  - Buffer for data returned (MUST be at least word-aligned,
          preferably long-word aligned).
    size    - Size in bytes of 'buffer'.
    type    - Type of data to be returned.
    control - Control data structure (see notes above).  MUST have been
          allocated by AllocDosObject!

   SEE ALSO
    ExAll(), AllocDosObject()


dos.library/Fault

   NAME
    Fault -- Returns the text associated with a DOS error code (V36)

   SYNOPSIS
    len = Fault(code, header, buffer, len)
    D0           D1     D2      D3    D4

    LONG Fault(LONG, STRPTR, STRPTR, LONG)

   FUNCTION
    This routine obtains the error message text for the given error code.
    The header is prepended to the text of the error message, followed
    by a colon.  Puts a null-terminated string for the error message into
    the buffer.  By convention, error messages should be no longer than 80
    characters (+1 for termination), and preferably no more than 60.
    The value returned by IoErr() is set to the code passed in.  If there
    is no message for the error code, the message will be "Error code
    <number>n".

    The number of characters put into the buffer is returned, which will
    be 0 if the code passed in was 0.

   INPUTS
    code   - Error code
    header - header to output before error text
    buffer - Buffer to receive error message.
    len    - Length of the buffer.

   RESULT
    len    - number of characters put into buffer (may be 0)

   SEE ALSO
    IoErr(), SetIoErr(), PrintFault()

   BUGS
    In older documentation, the return was shown as BOOL success.  This
    was incorrect, it has always returned the length.


dos.library/FGets

   NAME
    FGets -- Reads a line from the specified input (buffered) (V36)

   SYNOPSIS
    buffer = FGets(fh, buf, len)
    D0             D1  D2   D3

    STRPTR FGets(BPTR, STRPTR, ULONG)

   FUNCTION
    This routine reads in a single line from the specified input stopping
    at a NEWLINE character or EOF.  In either event, UP TO the number of
    len specified bytes minus 1 will be copied into the buffer.  Hence if
    a length of 50 is passed and the input line is longer than 49 bytes,
    it will return 49 characters.  It returns the buffer pointer normally,
    or NULL if EOF is the first thing read.

    If terminated by a newline, the newline WILL be the last character in
    the buffer.  This is a buffered read routine.  The string read in IS
    null-terminated.

   INPUTS
    fh  - filehandle to use for buffered I/O
    buf - Area to read bytes into.
    len - Number of bytes to read, must be > 0.

   RESULT
    buffer - Pointer to buffer passed in, or NULL for immediate EOF or for
         an error.  If NULL is returnd for an EOF, IoErr() will return
         0.

   BUGS
    In V36 and V37, it copies one more byte than it should if it doesn't
    hit an EOF or newline.  In the example above, it would copy 50 bytes
    and put a null in the 51st.  This is fixed in dos V39.  Workaround
    for V36/V37: pass in buffersize-1.

   SEE ALSO
    FRead(), FPuts(), FGetC()


dos.library/FindCliProc

   NAME
    FindCliProc -- returns a pointer to the requested CLI process (V36)

   SYNOPSIS
    proc = FindCliProc(num)
    D0             D1

    struct Process *FindCliProc(ULONG)

   FUNCTION
    This routine returns a pointer to the CLI process associated with the
    given CLI number.  If the process isn't an active CLI process, NULL is
    returned.  NOTE: should normally be called inside a Forbid(), if you
    must use this function at all.

   INPUTS
    num  - Task number of CLI process (range 1-N)

   RESULT
    proc - Pointer to given CLI process

   SEE ALSO
    Cli(), Forbid(), MaxCli()


dos.library/Flush

   NAME
    Flush -- Flushes buffers for a buffered filehandle (V36)

   SYNOPSIS
    success = Flush(fh)
    D0		D1

    LONG Flush(BPTR)

   FUNCTION
    Flushes any pending buffered writes to the filehandle.  All buffered
    writes will also be flushed on Close().  If the filehandle was being
    used for input, it drops the buffer, and tries to Seek() back to the
    last read position  (so subsequent reads or writes will occur at the
    expected position in the file).

   INPUTS
    fh	- Filehandle to flush.

   RESULT
    success - Success or failure.

   BUGS
    Before V37 release, Flush() returned a random value.  As of V37,
    it always returns success (this will be fixed in some future
    release).

    The V36 and V37 releases didn't properly flush filehandles which
    have never had a buffered IO done on them.  This commonly occurs
    on redirection of input of a command, or when opening a file for
    input and then calling CreateNewProc() with NP_Arguments, or when
    using a new filehandle with SelectInput() and then calling
    RunCommand().  This is fixed in V39.  A workaround would be to
    do FGetC(), then UnGetC(), then Flush().

   SEE ALSO
    FputC(), FGetC(), UnGetC(), Seek(), Close(), CreateNewProc(),
    SelectInput(), RunCommand()


dos.library/FPutC

   NAME
    FPutC -- Write a character to the specified output (buffered) (V36)

   SYNOPSIS
    char = FPutC(fh, char)
    D0           D1   D2

    LONG FPutC(BPTR, LONG)

   FUNCTION
    Writes a single character to the output stream.  This call is
    buffered.  Use Flush() between buffered and unbuffered I/O on a
    filehandle.  Interactive filehandles are flushed automatically
    on a newline, return, '0', or line feed.

   INPUTS
    fh   - filehandle to use for buffered I/O
    char - character to write

   RESULT
    char - either the character written, or EOF for an error.

   BUGS
    Older autodocs indicated that you should pass a UBYTE.  The
    correct usage is to pass a LONG in the range 0-255.

   SEE ALSO
    FGetC(), UnGetC(), Flush()


dos.library/FPuts

   NAME
    FPuts -- Writes a string the the specified output (buffered) (V36)

   SYNOPSIS
    error = FPuts(fh, str)
    D0            D1  D2

    LONG FPuts(BPTR, STRPTR)

   FUNCTION
    This routine writes an unformatted string to the filehandle.  No
    newline is appended to the string.  This routine is buffered.

   INPUTS
    fh    - filehandle to use for buffered I/O
    str   - Null-terminated string to be written to default output

   RESULT
    error - 0 normally, otherwise -1.  Note that this is opposite of
        most other Dos functions, which return success.

   SEE ALSO
    FGets(), FPutC(), FWrite(), PutStr()


dos.library/FreeArgs

   NAME
    FreeArgs - Free allocated memory after ReadArgs() (V36)

   SYNOPSIS
    FreeArgs(rdargs)
               D1

    void FreeArgs(struct RDArgs *)

   FUNCTION
    Frees memory allocated to return arguments in from ReadArgs().  If
    ReadArgs allocated the RDArgs structure it will be freed.  If NULL
    is passed in this function does nothing.

   INPUTS
    rdargs - structure returned from ReadArgs() or NULL.

   SEE ALSO
    ReadArgs(), ReadItem(), FindArg()


dos.library/FreeDosObject

   NAME
    FreeDosObject -- Frees an object allocated by AllocDosObject() (V36)

   SYNOPSIS
    FreeDosObject(type, ptr)
               D1   D2

    void FreeDosObject(ULONG, void *)

   FUNCTION
    Frees an object allocated by AllocDosObject().  Do NOT call for
    objects allocated in any other way.

   INPUTS
    type - type passed to AllocDosObject()
    ptr  - ptr returned by AllocDosObject()

   BUGS
    Before V39, DOS_CLI objects will only have the struct
    CommandLineInterface freed, not the strings it points to.  This
    is fixed in V39 dos.  Before V39, you can workaround this bug by
    using FreeVec() on cli_SetName, cli_CommandFile, cli_CommandName,
    and cli_Prompt, and then setting them all to NULL.  In V39 or
    above, do NOT use the workaround.

   SEE ALSO
    AllocDosObject(), FreeVec(), <dos/dos.h>


dos.library/FWrite

   NAME
    FWrite -- Writes a number of blocks to an output (buffered) (V36)

   SYNOPSIS
    count = FWrite(fh, buf, blocklen, blocks)
    D0	       D1  D2     D3        D4

    LONG FWrite(BPTR, STRPTR, ULONG, ULONG)

   FUNCTION
    Attempts to write a number of blocks, each blocklen long, from the
    specified buffer to the output stream.  May return less than the
    number of blocks requested, if there is some error such as a full
    disk or r/w error.  This call is buffered.

   INPUTS
    fh	 - filehandle to use for buffered I/O
    buf      - Area to write bytes from.
    blocklen - number of bytes per block.  Must be > 0.
    blocks	 - number of blocks to write.  Must be > 0.

   RESULT
    count - Number of _blocks_ written.  On an error, the number of
        blocks actually written is returned.

   BUGS
    Doesn't clear IoErr() before starting.  If you want to find out
    about errors, use SetIoErr(0L) before calling.

   SEE ALSO
    FPutC(), FRead(), FPuts()


dos.library/GetProgramName

   NAME
    GetProgramName -- Returns the current program name (V36)

   SYNOPSIS
    success = GetProgramName(buf, len)
    D0                       D1   D2

    BOOL GetProgramName(STRPTR, LONG)

   FUNCTION
    Extracts the program name from the CLI structure and puts it
    into the buffer.  If the buffer is too small, the name is truncated.
    If no CLI structure is present, a null string is returned in the
    buffer, and failure from the call (with IoErr() ==
    ERROR_OBJECT_WRONG_TYPE);

   INPUTS
    buf     - Buffer to hold extracted name
    len     - Number of bytes of space in buffer

   RESULT
    success - Success/failure indicator

   SEE ALSO
    SetProgramName()


dos.library/GetVar

   NAME
    GetVar -- Returns the value of a local or global variable (V36)

   SYNOPSIS
    len = GetVar( name, buffer, size, flags )
    D0	       D1     D2     D3    D4

    LONG GetVar( STRPTR, STRPTR, LONG, ULONG )

   FUNCTION
    Gets the value of a local or environment variable.  It is advised to
     only use ASCII strings inside variables, but not required.  This stops
    putting characters into the destination when a n is hit, unless
    GVF_BINARY_VAR is specified.  (The n is not stored in the buffer.)

   INPUTS
    name   - pointer to a variable name.
    buffer - a user allocated area which will be used to store
         the value associated with the variable.
    size   - length of the buffer region in bytes.
    flags  - combination of type of var to get value of (low 8 bits), and
         flags to control the behavior of this routine.  Currently
         defined flags include:

            GVF_GLOBAL_ONLY - tries to get a global env variable.
            GVF_LOCAL_ONLY  - tries to get a local variable.
            GVF_BINARY_VAR  - don't stop at n
            GVF_DONT_NULL_TERM - no null termination (only valid
                      for binary variables). (V37)

         The default is to try to get a local variable first, then
         to try to get a global environment variable.

   RESULT
    len -   Size of environment variable.  -1 indicates that the
        variable was not defined (if IoErr() returns
        ERROR_OBJECT_NOT_FOUND - it returns ERROR_BAD_NUMBER if
        you specify a size of 0).  If the value would overflow
        the user buffer, the buffer is truncated.  The buffer
        returned is null-terminated (even if GVF_BINARY_VAR is
        used, unless GVF_DONT_NULL_TERM is in effect).  If it
        succeeds, len is the number of characters put in the buffer
        (not including null termination), and IoErr() will return the
        the size of the variable (regardless of buffer size).

   BUGS
    LV_VAR is the only type that can be global.
    Under V36, we documented (and it returned) the size of the variable,
    not the number of characters transferred.  For V37 this was changed
    to the number of characters put in the buffer, and the total size
    of the variable is put in IoErr().
    GVF_DONT_NULL_TERM only works for local variables under V37.  For
    V39, it also works for globals.

   SEE ALSO
    SetVar(), DeleteVar(), FindVar(), <dos/var.h>


dos.library/InternalLoadSeg

   NAME
    InternalLoadSeg -- Low-level load routine (V36)

   SYNOPSIS
    seglist = InternalLoadSeg(fh,table,functionarray,stack)
    D0			  D0  A0        A1	  A2

    BPTR InternalLoadSeg(BPTR,BPTR,LONG *,LONG *)

   FUNCTION
    Loads from fh.  Table is used when loading an overlay, otherwise
    should be NULL.  Functionarray is a pointer to an array of functions.
    Note that the current Seek position after loading may be at any point
    after the last hunk loaded.  The filehandle will not be closed.  If a
    stacksize is encoded in the file, the size will be stuffed in the
    LONG pointed to by stack.  This LONG should be initialized to your
    default value: InternalLoadSeg() will not change it if no stacksize
    is found. Clears unused portions of Code and Data hunks (as well as
    BSS hunks).  (This also applies to LoadSeg() and NewLoadSeg()).

    If the file being loaded is an overlaid file, this will return
    -(seglist).  All other results will be positive.

    NOTE to overlay users: InternalLoadSeg() does NOT return seglist in
    both D0 and D1, as LoadSeg does.  The current ovs.asm uses LoadSeg(),
    and assumes returns are in D1.  We will support this for LoadSeg()
    ONLY.

   INPUTS
    fh	      - Filehandle to load from.
    table	      - When loading an overlay, otherwise ignored.
    functionarray - Array of function to be used for read, alloc, and free.
       FuncTable[0] ->  Actual = ReadFunc(readhandle,buffer,length),DOSBase
                    D0                D1         D2     D3      A6
       FuncTable[1] ->  Memory = AllocFunc(size,flags), Execbase
                    D0                 D0   D1      a6
       FuncTable[2] ->  FreeFunc(memory,size), Execbase
                             A1     D0     A6
    stack         - Pointer to storage (ULONG) for stacksize.

   RESULT
    seglist	      - Seglist loaded or NULL.  NOT returned in D1!

   BUGS
    Really should use tags.

   SEE ALSO
    LoadSeg(), UnLoadSeg(), NewLoadSeg(), InternalUnLoadSeg()


dos.library/LockDosList

   NAME
    LockDosList -- Locks the specified Dos Lists for use (V36)

   SYNOPSIS
    dlist = LockDosList(flags)
    D0		     D1

    struct DosList *LockDosList(ULONG)

   FUNCTION
    Locks the dos device list in preparation to walk the list.
    If the list is 'busy' then this routine will not return until it is
    available.  This routine "nests": you can call it multiple times, and
    then must unlock it the same number of times.  The dlist
    returned is NOT a valid entry: it is a special value.  Note that
    for 1.3 compatibility, it also does a Forbid() - this will probably
    be removed at some future time.  The 1.3 Forbid() locking of this
    list had some race conditions.  The pointer returned by this is NOT
    an actual DosList pointer - you should use on of the other DosEntry
    calls to get actual pointers to DosList structures (such as
    NextDosEntry()), passing the value returned by LockDosList()
    as the dlist value.

    Note for handler writers: you should never call this function with
    LDF_WRITE, since it can deadlock you (if someone has it read-locked
    and they're trying to send you a packet).  Use AttemptLockDosList()
    instead, and effectively busy-wait with delays for the list to be
    available.  The other option is that you can spawn a process to
    add the entry safely.

    As an example, here's how you can search for all volumes of a specific
    name and do something with them:

    2.0 way:

        dl = LockDosList(LDF_VOLUMES|LDF_READ);
        while (dl = FindDosEntry(dl,name,LDF_VOLUMES))
        {
            Add to list of volumes to process or break out of
            the while loop.
            (You could try using it here, but I advise
            against it for compatability reasons if you
            are planning on continuing to examine the list.)
        }

        process list of volumes saved above, or current entry if
        you're only interested in the first one of that name.

        UnLockDosList(LDF_VOLUMES|LDF_READ);
                  * must not use dl after this! *

    1.3/2.0 way:

        if (version >= 36)
            dl = LockDosList(LDF_VOLUMES|LDF_READ);
        else {
            Forbid();
            /* tricky! note dol_Next is at offset 0! */
            dl = &(...->di_DeviceList);
        }

        while (version >= 36 ?
                dl = FindDosEntry(dl,name,LDF_VOLUMES) :
                    dl = yourfindentry(dl,name,DLT_VOLUME))
        {
            Add to list of volumes to process, or break out of
            the while loop.
            Do NOT lock foo1/foo2 here if you will continue
            to examine the list - it breaks the forbid
            and the list may change on you.
        }

        process list of volumes saved above, or current entry if
        you're only interested in the first one of that name.

        if (version >= 36)
            UnLockDosList(LDF_VOLUMES|LDF_READ);
        else
            Permit();
        * must not use dl after this! *
        ...

        struct DosList *
        yourfindentry (struct DosList *dl, STRPTRname, type)
        {
        * tricky - depends on dol_Next being at offset 0,
           and the initial ptr being a ptr to di_DeviceList! *
            while (dl = dl->dol_Next)
            {
                if (dl->dol_Type == type &&
                stricmp(name,BADDR(dl->dol_Name)+1) == 0)
                {
                break;
                }
            }
            return dl;
        }

   INPUTS
    flags - Flags stating which types of nodes you want to lock.

   RESULT
    dlist - Pointer to the head of the list.  NOT a valid node!

   SEE ALSO
    AttemptLockDosList(), UnLockDosList(), Forbid(), NextDosEntry()


dos.library/LockRecord

   NAME
    LockRecord -- Locks a portion of a file (V36)

   SYNOPSIS
    success = LockRecord(fh,offset,length,mode,timeout)
    D0                   D1   D2     D3    D4    D5

    BOOL LockRecord(BPTR,ULONG,ULONG,ULONG,ULONG)

   FUNCTION
    This locks a portion of a file for exclusive access.  Timeout is how
    long to wait in ticks (1/50 sec) for the record to be available.

    Valid modes are:
        REC_EXCLUSIVE
        REC_EXCLUSIVE_IMMED
        REC_SHARED
        REC_SHARED_IMMED
    For the IMMED modes, the timeout is ignored.

    Record locks are tied to the filehandle used to create them.  The
    same filehandle can get any number of exclusive locks on the same
    record, for example.  These are cooperative locks, they only
    affect other people calling LockRecord().

   INPUTS
    fh      - File handle for which to lock the record
    offset  - Record start position
    length  - Length of record in bytes
    mode    - Type of lock requester
    timeout - Timeout interval in ticks.  0 is legal.

   RESULT
    success - Success or failure

   BUGS
    In 2.0 through 2.02 (V36), LockRecord() only worked in the ramdisk.
    Attempting to lock records on the disk filesystem causes a crash.
    This was fixed for V37.

   SEE ALSO
    LockRecords(), UnLockRecord(), UnLockRecords()


dos.library/MatchPatternNoCase

   NAME
    MatchPatternNoCase --  Checks for a pattern match with a string (V37)

   SYNOPSIS
    match = MatchPatternNoCase(pat, str)
    D0                         D1   D2

    BOOL MatchPatternNoCase(STRPTR, STRPTR)

   FUNCTION
    Checks for a pattern match with a string.  The pattern must be a
    tokenized string output by ParsePatternNoCase().  This routine is
    case-insensitive.

    NOTE: this routine is highly recursive.  You must have at least
    1500 free bytes of stack to call this (it will cut off it's
    recursion before going any deeper than that and return failure).
    That's _currently_ enough for about 100 levels deep of #, (, ~, etc.

   INPUTS
    pat - Special pattern string to match as returned by ParsePatternNoCase()
    str - String to match against given pattern

   RESULT
    match - success or failure of pattern match.  On failure,
        IoErr() will return 0 or ERROR_TOO_MANY_LEVELS (starting
        with V37 - before that there was no stack checking).

   BUGS
    See ParsePatternNoCase().

   SEE ALSO
    ParsePatternNoCase(), MatchPattern(), MatchFirst(), MatchNext()


dos.library/NameFromFH

   NAME
    NameFromFH -- Get the name of an open filehandle (V36)

   SYNOPSIS
    success = NameFromFH(fh, buffer, len)
    D0                   D1    D2    D3

    BOOL NameFromFH(BPTR, STRPTR, LONG)

   FUNCTION
    Returns a fully qualified path for the filehandle.  This routine is
    guaranteed not to write more than len characters into the buffer.  The
    name will be null-terminated.  See NameFromLock() for more information.

    Note: Older filesystems that don't support ExamineFH() will cause
    NameFromFH() to fail with ERROR_ACTION_NOT_SUPPORTED.

   INPUTS
    fh     - Lock of object to be examined.
    buffer - Buffer to store name.
    len    - Length of buffer.

   RESULT
    success - Success/failure indicator.

   SEE ALSO
    NameFromLock(), ExamineFH()


dos.library/ParsePattern

   NAME
    ParsePattern -- Create a tokenized string for MatchPattern() (V36)

   SYNOPSIS
    IsWild = ParsePattern(Source, Dest, DestLength)
    d0                      D1     D2      D3

    LONG ParsePattern(STRPTR, STRPTR, LONG)

   FUNCTION
    Tokenizes a pattern, for use by MatchPattern().  Also indicates if
    there are any wildcards in the pattern (i.e. whether it might match
    more than one item).  Note that Dest must be at least 2 times as
    large as Source plus bytes to be (almost) 100% certain of no
    buffer overflow.  This is because each input character can currently
    expand to 2 tokens (with one exception that can expand to 3, but
    only once per string).  Note: this implementation may change in
    the future, so you should handle error returns in all cases, but
    the size above should still be a reasonable upper bound for a buffer
    allocation.

    The patterns are fairly extensive, and approximate some of the ability
    of Unix/grep "regular expression" patterns.  Here are the available
    tokens:

    ?	Matches a single character.
    #	Matches the following expression 0 or more times.
    (ab|cd)	Matches any one of the items seperated by '|'.
    ~	Negates the following expression.  It matches all strings
        that do not match the expression (aka ~(foo) matches all
        strings that are not exactly "foo").
    [abc]	Character class: matches any of the characters in the class.
    [~bc]	Character class: matches any of the characters not in the
        class.
    a-z	Character range (only within character classes).
    %	Matches 0 characters always (useful in "(foo|bar|%)").
    *	Synonym for "#?", not available by default in 2.0.  Available
        as an option that can be turned on.

    "Expression" in the above table means either a single character
    (ex: "#?"), or an alternation (ex: "#(ab|cd|ef)"), or a character
    class (ex: "#[a-zA-Z]").

   INPUTS
    source     - unparsed wildcard string to search for.
       dest       - output string, gets tokenized version of input.
    DestLength - length available in destination (should be at least as
             twice as large as source + 2 bytes).

   RESULT
    IsWild - 1 means there were wildcards in the pattern,
         0 means there were no wildcards in the pattern,
        -1 means there was a buffer overflow or other error

   BUGS
    In V37 this call didn't always set IoErr() to something useful on an
    error.  Fixed in V39.

   SEE ALSO
    ParsePatternNoCase(), MatchPattern(), MatchFirst(), MatchNext()


dos.library/ParsePatternNoCase

   NAME
    ParsePatternNoCase -- Create a tokenized string for
                        MatchPatternNoCase() (V37)

   SYNOPSIS
    IsWild = ParsePatternNoCase(Source, Dest, DestLength)
    d0                            D1     D2      D3

    LONG ParsePatternNoCase(STRPTR, STRPTR, LONG)

   FUNCTION
    Tokenizes a pattern, for use by MatchPatternNoCase().  Also indicates
    if there are any wildcards in the pattern (i.e. whether it might match
    more than one item).  Note that Dest must be at least 2 times as
    large as Source plus 2 bytes.

    For a description of the wildcards, see ParsePattern().

   INPUTS
    source     - unparsed wildcard string to search for.
       dest       - output string, gets tokenized version of input.
    DestLength - length available in destination (should be at least as
             twice as large as source + 2 bytes).

   RESULT
    IsWild - 1 means there were wildcards in the pattern,
         0 means there were no wildcards in the pattern,
        -1 means there was a buffer overflow or other error

   BUGS
    In V37 this call didn't always set IoErr() to something useful on an
    error.  Fixed in V39.
    In V37, it didn't properly convert character-classes ([x-y]) to
    upper case.  Workaround: convert the input pattern to upper case
    using ToUpper() from utility.library before calling
    ParsePatternNoCase().  Fixed in V39 dos.

   SEE ALSO
    ParsePattern(), MatchPatternNoCase(), MatchFirst(), MatchNext(),
    utility.library/ToUpper()


dos.library/ReadArgs

   NAME
    ReadArgs - Parse the command line input (V36)

   SYNOPSIS
    result = ReadArgs(template, array, rdargs)
    D0                   D1      D2      D3

    struct RDArgs * ReadArgs(STRPTR, LONG *, struct RDArgs *)

   FUNCTION
    Parses and argument string according to a template.  Normally gets
    the arguments by reading buffered IO from Input(), but also can be
    made to parse a string.  MUST be matched by a call to FreeArgs().

    ReadArgs() parses the commandline according to a template that is
    passed to it.  This specifies the different command-line options and
    their types.  A template consists of a list of options.  Options are
    named in "full" names where possible (for example, "Quick" instead of
    "Q").  Abbreviations can also be specified by using "abbrev=option"
    (for example, "Q=Quick").

    Options in the template are separated by commas.  To get the results
    of ReadArgs(), you examine the array of longwords you passed to it
    (one entry per option in the template).  This array should be cleared
    (or initialized to your default values) before passing to ReadArgs().
    Exactly what is put in a given entry by ReadArgs() depends on the type
    of option.  The default is a string (a sequence of non-whitespace
    characters, or delimited by quotes, which will be stripped by
    ReadArgs()), in which case the entry will be a pointer.

    Options can be followed by modifiers, which specify things such as
    the type of the option.  Modifiers are specified by following the
    option with a '/' and a single character modifier.  Multiple modifiers
    can be specified by using multiple '/'s.  Valid modifiers are:

    /S - Switch.  This is considered a boolean variable, and will be
         set if the option name appears in the command-line.  The entry
         is the boolean (0 for not set, non-zero for set).

    /K - Keyword.  This means that the option will not be filled unless
         the keyword appears.  For example if the template is "Name/K",
         then unless "Name=<string>" or "Name <string>" appears in the
         command line, Name will not be filled.

    /N - Number.  This parameter is considered a decimal number, and will
         be converted by ReadArgs.  If an invalid number is specified,
         an error will be returned.  The entry will be a pointer to the
         longword number (this is how you know if a number was specified).

    /T - Toggle.  This is similar to a switch, but when specified causes
         the boolean value to "toggle".  Similar to /S.

    /A - Required.  This keyword must be given a value during command-line
         processing, or an error is returned.

    /F - Rest of line.  If this is specified, the entire rest of the line
         is taken as the parameter for the option, even if other option
         keywords appear in it.

    /M - Multiple strings.  This means the argument will take any number
         of strings, returning them as an array of strings.  Any arguments
         not considered to be part of another option will be added to this
         option.  Only one /M should be specified in a template.  Example:
         for a template "Dir/M,All/S" the command-line "foo bar all qwe"
         will set the boolean "all", and return an array consisting of
         "foo", "bar", and "qwe".  The entry in the array will be a pointer
         to an array of string pointers, the last of which will be NULL.

         There is an interaction between /M parameters and /A parameters.
         If there are unfilled /A parameters after parsing, it will grab
         strings from the end of a previous /M parameter list to fill the
         /A's.  This is used for things like Copy ("From/A/M,To/A").

    ReadArgs() returns a struct RDArgs if it succeeds.  This serves as an
    "anchor" to allow FreeArgs() to free the associated memory.  You can
    also pass in a struct RDArgs to control the operation of ReadArgs()
    (normally you pass NULL for the parameter, and ReadArgs() allocates
    one for you).  This allows providing different sources for the
    arguments, providing your own string buffer space for temporary
    storage, and extended help text.  See <dos/rdargs.h> for more
    information on this.  Note: if you pass in a struct RDArgs, you must
    still call FreeArgs() to release storage that gets attached to it,
    but you are responsible for freeing the RDArgs yourself.

    If you pass in a RDArgs structure, you MUST reset (clear or set)
    RDA_Buffer for each new call to RDArgs.  The exact behavior if you
    don't do this varies from release to release and case to case; don't
    count on the behavior!

    See BUGS regarding passing in strings.

   INPUTS
    template - formatting string
    array    - array of longwords for results, 1 per template entry
    rdargs   - optional rdargs structure for options.  AllocDosObject
           should be used for allocating them if you pass one in.

   RESULT
    result   - a struct RDArgs or NULL for failure.

   BUGS
    In V36, there were a couple of minor bugs with certain argument
    combinations (/M/N returned strings, /T didn't work, and /K and
    /F interacted).  Also, a template with a /K before any non-switch
    parameter will require the argument name to be given in order for
    line to be accepted (i.e. "parm/K,xyzzy/A" would require
    "xyzzy=xxxxx" in order to work - "xxxxx" would not work).  If you
    need to avoid this for V36, put /K parameters after all non-switch
    parameters.  These problems should be fixed for V37.

    Currently (V37 and before) it requires any strings passed in to have
    newlines at the end of the string.  This may or may not be fixed in
    the future.

   SEE ALSO
    FindArg(), ReadItem(), FreeArgs(), AllocDosObject()


dos.library/ReadItem

   NAME
    ReadItem - reads a single argument/name from command line (V36)

   SYNOPSIS
    value = ReadItem(buffer, maxchars, input)
    D0                D1        D2      D3

    LONG ReadItem(STRPTR, LONG, struct CSource *)

   FUNCTION
    Reads a "word" from either Input() (buffered), or via CSource, if it
    is non-NULL (see <dos/rdargs.h> for more information).  Handles
    quoting and some '*' substitutions (*e and *n) inside quotes (only).
    See dos/dos.h for a listing of values returned by ReadItem()
    (ITEM_XXXX).  A "word" is delimited by whitespace, quotes, '=', or
    an EOF.

    ReadItem always unreads the last thing read (UnGetC(fh,-1)) so the
    caller can find out what the terminator was.

   INPUTS
    buffer   - buffer to store word in.
    maxchars - size of the buffer
    input    - CSource input or NULL (uses FGetC(Input()))

   RESULT
    value - See <dos/dos.h> for return values.

   BUGS
    Doesn't actually unread the terminator.

   SEE ALSO
    ReadArgs(), FindArg(), UnGetC(), FGetC(), Input(), <dos/dos.h>,
    <dos/rdargs.h>, FreeArgs()


dos.library/RemAssignList

   NAME
    RemAssignList -- Remove an entry from a multi-dir assign (V36)

   SYNOPSIS
    success = RemAssignList(name,lock)
    D0                  	 D1   D2

    BOOL RemAssignList(STRPTR,BPTR)

   FUNCTION
    Removes an entry from a multi-directory assign.  The entry removed is
    the first one for which SameLock with 'lock' returns that they are on
    the same object.  The lock for the entry in the list is unlocked (not
    the entry passed in).

   INPUTS
    name - Name of device to remove lock from (without trailing ':')
    lock - Lock associated with the object to remove from the list

   RESULT
    success - Success/failure indicator.

   BUGS
    In V36 through V39.23 dos, it would fail to remove the first lock
    in the assign.  Fixed in V39.24 dos (after the V39.106 kickstart).

   SEE ALSO
    Lock(), AssignLock(), AssignPath(), AssignLate(), DupLock(),
    AssignAdd(), UnLock()


dos.library/Seek

    NAME
    Seek -- Set the current position for reading and writing

    SYNOPSIS
    oldPosition = Seek( file, position, mode )
    D0		    D1	  D2	    D3

    LONG Seek(BPTR, LONG, LONG)

    FUNCTION
    Seek() sets the read/write cursor for the file 'file' to the
    position 'position'. This position is used by both Read() and
    Write() as a place to start reading or writing. The result is the
    current absolute position in the file, or -1 if an error occurs, in
    which case IoErr() can be used to find more information. 'mode' can
    be OFFSET_BEGINNING, OFFSET_CURRENT or OFFSET_END. It is used to
    specify the relative start position. For example, 20 from current
    is a position 20 bytes forward from current, -20 is 20 bytes back
    from current.

    So that to find out where you are, seek zero from current. The end
    of the file is a Seek() positioned by zero from end. You cannot
    Seek() beyond the end of a file.

    INPUTS
    file - BCPL pointer to a file handle
    position - integer
    mode - integer

    RESULTS
    oldPosition - integer

    BUGS
    The V36 and V37 ROM filesystem (and V36/V37 l:fastfilesystem)
    returns the current position instead of -1 on an error.  It sets
    IoErr() to 0 on success, and an error code on an error.  This bug
    was fixed in the V39 filesystem.

    SEE ALSO
    Read(), Write(), SetFileSize()


dos.library/SelectOutput

   NAME
    SelectOutput -- Select a filehandle as the default output channel (V36)

   SYNOPSIS
    old_fh = SelectOutput(fh)
    D0                    D1

    BPTR SelectOutput(BPTR)

   FUNCTION
    Set the current output as the default output for the process.
    This changes the value returned by Output().  old_fh should
    be closed or saved as needed.

   INPUTS
    fh     - Newly desired output handle

   RESULT
    old_fh - Previous current output

   SEE ALSO
    Output(), SelectInput(), Input()


dos.library/SendPkt

   NAME
    SendPkt -- Sends a packet to a handler (V36)

   SYNOPSIS
    SendPkt(packet, port, replyport)
         D1     D2	D3

    void SendPkt(struct DosPacket *,struct MsgPort *,struct MsgPort *)

   FUNCTION
    Sends a packet to a handler and does not wait.  All fields in the
    packet must be initialized before calling this routine.  The packet
    will be returned to replyport.  If you wish to use this with
    WaitPkt(), use the address of your pr_MsgPort for replyport.

   INPUTS
    packet - packet to send, must be initialized and have a message.
    port   - pr_MsgPort of handler process to send to.
    replyport - MsgPort for the packet to come back to.

   NOTES
    Callable from a task.

   SEE ALSO
    DoPkt(), WaitPkt(), AllocDosObject(), FreeDosObject(), AbortPkt()


dos.library/SetFileSize

   NAME
    SetFileSize -- Sets the size of a file (V36)

   SYNOPSIS
    newsize = SetFileSize(fh, offset, mode)
    D0                    D1    D2     D3

    LONG SetFileSize(BPTR, LONG, LONG)

   FUNCTION
    Changes the file size, truncating or extending as needed.  Not all
    handlers may support this; be careful and check the return code.  If
    the file is extended, no values should be assumed for the new bytes.
    If the new position would be before the filehandle's current position
    in the file, the filehandle will end with a position at the
    end-of-file.  If there are other filehandles open onto the file, the
    new size will not leave any filehandle pointing past the end-of-file.
    You can check for this by looking at the new size (which would be
    different than what you requested).

    The seek position should not be changed unless the file is made
    smaller than the current seek position.  However, see BUGS.

    Do NOT count on any specific values to be in any extended area.

   INPUTS
    fh     - File to be truncated/extended.
    offset - Offset from position determined by mode.
    mode   - One of OFFSET_BEGINNING, OFFSET_CURRENT, or OFFSET_END.

   RESULT
    newsize - position of new end-of-file or -1 for error.

   BUGS
    The RAM: filesystem and the normal Amiga filesystem act differently
    in where the file position is left after SetFileSize().  RAM: leaves
    you at the new end of the file (incorrectly), while the Amiga ROM
    filesystem leaves the seek position alone, unless the new position
    is less than the current position, in which case you're left at the
    new EOF.

    The best workaround is to not make any assumptions about the seek
    position after SetFileSize().

   SEE ALSO
    Seek()


dos.library/SetOwner

    NAME
    SetOwner -- Set owner information for a file or directory (V39)

    SYNOPSIS
    success = SetOwner( name, owner_info )
    D0		     D1       D2

    BOOL SetOwner (STRPTR, LONG)

    FUNCTION
    SetOwner() sets the owner information for the file or directory.
    This value is a 32-bit value that is normally split into 16 bits
    of owner user id (bits 31-16), and 16 bits of owner group id (bits
    15-0).  However, other than returning them as shown by Examine()/
    ExNext()/ExAll(), the filesystem take no interest in the values.
    These are primarily for use by networking software (clients and
    hosts), in conjunction with the FIBF_OTR_xxx and FIBF_GRP_xxx
    protection bits.

    This entrypoint did not exist in V36, so you must open at least V37
    dos.library to use it.  V37 dos.library will return FALSE to this
    call.

    INPUTS
    name	   - pointer to a null-terminated string
    owner_info - owner uid (31:16) and group id (15:0)

    RESULTS
    success - boolean

    SEE ALSO
    SetProtect(), Examine(), ExNext(), ExAll(), <dos/dos.h>


dos.library/SetProtection

    NAME
    SetProtection -- Set protection for a file or directory

    SYNOPSIS
    success = SetProtection( name, mask )
    D0			 D1    D2

    BOOL SetProtection (STRPTR, LONG)

    FUNCTION
    SetProtection() sets the protection attributes on a file or
    directory.  See <dos/dos.h> for a listing of protection bits.

    Before V36, the ROM filesystem didn't respect the Read and Write
    bits.  In V36 or later and in the FFS, the Read and Write
    bits are respected.

    The archive bit should be cleared by the filesystem whenever the file
    is changed.  Backup utilities will generally set the bit after
    backing up each file.

    The V36 Shell looks at the execute bit, and will refuse to execute
    a file if it is set.

    Other bits will be defined in the <dos/dos.h> include files.  Rather
    than referring to bits by number you should use the definitions in
    <dos/dos.h>.

    INPUTS
    name - pointer to a null-terminated string
    mask - the protection mask required

    RESULTS
    success - boolean

    SEE ALSO
    SetComment(), Examine(), ExNext(), <dos/dos.h>


dos.library/SetVBuf

   NAME
    SetVBuf -- set buffering modes and size (V39)

   SYNOPSIS
    error = SetVBuf(fh, buff, type, size)
    D0		D1   D2    D3    D4

    LONG SetVBuf(BPTR, STRPTR, LONG, LONG)

   FUNCTION
    Changes the buffering modes and buffer size for a filehandle.
    With buff == NULL, the current buffer will be deallocated and a
    new one of (approximately) size will be allocated.  If buffer is
    non-NULL, it will be used for buffering and must be at least
    max(size,208) bytes long, and MUST be longword aligned.  If size
    is -1, then only the buffering mode will be changed.

    Note that a user-supplied buffer will not be freed if it is later
    replaced by another SetVBuf() call, nor will it be freed if the
    filehandle is closed.

    Has no effect on the buffersize of filehandles that were not created
    by AllocDosObject().

   INPUTS
    fh   - Filehandle
    buff - buffer pointer for buffered I/O or NULL.  MUST be LONG-aligned!
    type - buffering mode (see <dos/stdio.h>)
    size - size of buffer for buffered I/O (sizes less than 208 bytes
           will be rounded up to 208), or -1.

   RESULT
    error - 0 if successful.  NOTE: opposite of most dos functions!
        NOTE: fails if someone has replaced the buffer without
        using SetVBuf() - RunCommand() does this.  Remember to
        check error before freeing user-supplied buffers!

   BUGS
    Not implemented until after V39.  From V36 up to V39, always
    returned 0.

   SEE ALSO
    FputC(), FGetC(), UnGetC(), Flush(), FRead(), FWrite(), FGets(),
    FPuts(), AllocDosObject()


dos.library/SplitName

   NAME
    SplitName -- splits out a component of a pathname into a buffer (V36)

   SYNOPSIS
    newpos = SplitName(name, separator, buf, oldpos, size)
    D0                  D1      D2      D3     D4     D5

    WORD SplitName(STRPTR, UBYTE, STRPTR, WORD, LONG)

   FUNCTION
    This routine splits out the next piece of a name from a given file
    name.  Each piece is copied into the buffer, truncating at size-1
    characters.  The new position is then returned so that it may be
    passed in to the next call to splitname.  If the separator is not
    found within 'size' characters, then size-1 characters plus a null will
    be put into the buffer, and the position of the next separator will
    be returned.

    If a a separator cannot be found, -1 is returned (but the characters
    from the old position to the end of the string are copied into the
    buffer, up to a maximum of size-1 characters).  Both strings are
    null-terminated.

    This function is mainly intended to support handlers.

   INPUTS
    name      - Filename being parsed.
    separator - Separator charactor to split by.
    buf       - Buffer to hold separated name.
    oldpos    - Current position in the file.
    size 	  - Size of buf in bytes (including null termination).

   RESULT
    newpos    - New position for next call to splitname.  -1 for last one.

   BUGS
    In V36 and V37, path portions greater than or equal to 'size' caused
    the last character of the portion to be lost when followed by a
    separator.  Fixed for V39 dos.  For V36 and V37, the suggested work-
    around is to call SplitName() with a buffer one larger than normal
    (for example, 32 bytes), and then set buf[size-2] to '0' (for example,
    buf[30] = '0';).

   SEE ALSO
    FilePart(), PathPart(), AddPart()


dos.library/StrToLong

   NAME
    StrToLong -- string to long value (decimal) (V36)

   SYNOPSIS
    characters = StrToLong(string,value)
    D0                       D1    D2

    LONG StrToLong(STRPTR, LONG *)

   FUNCTION
    Converts decimal string into LONG value.  Returns number of characters
    converted.  Skips over leading spaces & tabs (included in count).  If
    no decimal digits are found (after skipping leading spaces & tabs),
    StrToLong returns -1 for characters converted, and puts 0 into value.

   INPUTS
    string - Input string.
    value  - Pointer to long value.  Set to 0 if no digits are converted.

   RESULT
    result - Number of characters converted or -1.

   BUGS
    Before V39, if there were no convertible characters it returned the
    number of leading white-space characters (space and tab in this case).


dos.library/SystemTagList

   NAME
    SystemTagList -- Have a shell execute a command line (V36)

   SYNOPSIS
    error = SystemTagList(command, tags)
    D0		        D1      D2

    LONG SystemTagList(STRPTR, struct TagItem *)

    error = System(command, tags)
    D0		 D1      D2

    LONG System(STRPTR, struct TagItem *)

    error = SystemTags(command, Tag1, ...)

    LONG SystemTags(STRPTR, ULONG, ...)

   FUNCTION
    Similar to Execute(), but does not read commands from the input
    filehandle.  Spawns a Shell process to execute the command, and
    returns the returncode the command produced, or -1 if the command
    could not be run for any reason.  The input and output filehandles
    will not be closed by System, you must close them (if needed) after
    System returns, if you specified them via SYS_Input or SYS_Output.

    By default the new process will use your current Input() and Output()
    filehandles.  Normal Shell command-line parsing will be done
    including redirection on 'command'.  The current directory and path
    will be inherited from your process.  Your path will be used to find
    the command (if no path is specified).

    Note that you may NOT pass the same filehandle for both SYS_Input
    and SYS_Output.  If you want input and output to both be to the same
    CON: window, pass a SYS_Input of a filehandle on the CON: window,
    and pass a SYS_Output of NULL.  The shell will automatically set
    the default Output() stream to the window you passed via SYS_Input,
    by opening "*" on that handler.

    If used with the SYS_Asynch flag, it WILL close both it's input and
    output filehandles after running the command (even if these were
    your Input() and Output()!)

    Normally uses the boot (ROM) shell, but other shells can be specified
    via SYS_UserShell and SYS_CustomShell.  Normally, you should send
    things written by the user to the UserShell.  The UserShell defaults
    to the same shell as the boot shell.

    The tags are passed through to CreateNewProc() (tags that conflict
    with SystemTagList() will be filtered out).  This allows setting
    things like priority, etc for the new process.  The tags that are
    currently filtered out are:

        NP_Seglist
        NP_FreeSeglist
        NP_Entry
        NP_Input
        NP_Output
        NP_CloseInput
        NP_CloseOutput
        NP_HomeDir
        NP_Cli

   INPUTS
    command - Program and arguments
    tags    - see <dos/dostags.h>.  Note that both SystemTagList()-
          specific tags and tags from CreateNewProc() may be passed.

   RESULT
    error	- 0 for success, result from command, or -1.  Note that on
          error, the caller is responsible for any filehandles or other
          things passed in via tags.  -1 will only be returned if
          dos could not create the new shell.  If the command is not
          found the shell will return an error value, normally
          RETURN_ERROR.

   SEE ALSO
    Execute(), CreateNewProc(), <dos/dostags.h>, Input(), Output()


dos.library/VFWritef

   NAME
    VFWritef - write a BCPL formatted string to a file (buffered) (V36)

   SYNOPSIS
    count = VFWritef(fh, fmt, argv)
    D0               D1  D2    D3

    LONG VFWritef(BPTR, STRPTR, LONG *)

    count = FWritef(fh, fmt, ...)

    LONG FWritef(BPTR, STRPTR, ...)

   FUNCTION
    Writes the formatted string and values to the specified file.  This
    routine is assumed to handle all internal buffering so that the
    formatting string and resultant formatted values can be arbitrarily
    long.  The formats are in BCPL form.  This routine is buffered.

    Supported formats are:  (Note x is in base 36!)
        %S  - string (CSTR)
        %Tx - writes a left-justified string in a field at least
              x bytes long.
        %C  - writes a single character
        %Ox - writes a number in octal, maximum x characters wide
        %Xx - writes a number in hex, maximum x characters wide
        %Ix - writes a number in decimal, maximum x characters wide
        %N  - writes a number in decimal, any length
        %Ux - writes an unsigned number, maximum x characters wide
        %$  - ignore parameter

    Note: 'x' above is actually the character value - '0'.

   INPUTS
    fh    - filehandle to write to
    fmt   - BCPL style formatting string
    argv  - Pointer to array of formatting values

   RESULT
    count - Number of bytes written or -1 for error

   BUGS
    As of V37, VFWritef() does NOT return a valid return value.  In
    order to reduce possible errors, the prototypes supplied for the
    system as of V37 have it typed as VOID.

   SEE ALSO
    VFPrintf(), VFPrintf(), FPutC()


dos.library/WaitForChar

    NAME
    WaitForChar -- Determine if chars arrive within a time limit

    SYNOPSIS
    status = WaitForChar( file, timeout )
    D0		      D1    D2

    BOOL WaitForChar(BPTR, LONG)

    FUNCTION
    If a character is available to be read from 'file' within the
    time (in microseconds) indicated by 'timeout', WaitForChar()
    returns -1 (TRUE). If a character is available, you can use Read()
    to read it.  Note that WaitForChar() is only valid when the I/O
    stream is connected to a virtual terminal device. If a character is
    not available within 'timeout', a 0 (FALSE) is returned.

    BUGS
    Due to a bug in the timer.device in V1.2/V1.3, specifying a timeout
    of zero for WaitForChar() can cause the unreliable timer & floppy
    disk operation.

    INPUTS
    file - BCPL pointer to a file handle
    timeout - integer

    RESULTS
    status - boolean

    SEE ALSO
    Read(), FGetC()


dos.library/WriteChars

   NAME
    WriteChars -- Writes bytes to the the default output (buffered) (V36)

   SYNOPSIS
    count = WriteChars(buf, buflen)
    D0                 D1   D2

    LONG WriteChars(STRPTR, LONG)

   FUNCTION
    This routine writes a number of bytes to the default output.  The
    length is returned.  This routine is buffered.

   INPUTS
    buf    - buffer of characters to write
    buflen - number of characters to write

   RESULT
    count - Number of bytes written.  -1 (EOF) indicates an error

   SEE ALSO
    FPuts(), FPutC(), FWrite(), PutStr()


drawlist_ic.doc

     --datasheet--
     DRAWLIST_GetClass()


drawlist_ic/--datasheet--

    NAME
        drawlist_ic -- create drawlist BOOPSI objects

    SUPERCLASS
        imageclass

    REQUIRES
        None.

    DESCRIPTION
        This image class can create custom scaled glyphs via a
        "drawlist". The drawlist is an array of drawing directives
        such as lines, areafills, etc. All coordinates are based
        on an imaginary grid of a user specified size, then
        ScalerDiv() is used to scale these coordinates to the desired
        image size to be rendered. This is a lower level class utilized
        by glyph.image, if you create some interesting drawlist, please
        consider passing them on to others, or to us for inclusion.

    METHODS
        OM_NEW -- Create the drawlist image.  Passed to superclass, then
            OM_SET.

        OM_GET -- Get object attributes.  Passed to superclass first.

        OM_SET -- Set object attributes.  Passed to superclass first.

        OM_UPDATE -- Set object notification attributes.  Passed to
            superclass first.

        IM_DRAW -- Renders the images.  Overrides the superclass.
        IM_DRAWFRAME -- Renders the images scaled to thee frame size.
            Overrides the superclass.

        All other methods are passed to the superclass, including OM_DISPOSE.

    ATTRIBUTES
        DRAWLIST_Directives (struct DrawList *)
            An array of drawlist directive structures are passed
            to specify the vectors and render operation. The last
            entry must be DLST_END!

            struct DrawList
            {
                WORD dl_Directive;
                WORD dl_X1, dl_Y1;
                WORD dl_X2, dl_Y2;
                WORD dl_Pen;
            };

            The following directives are supported;

            DLST_END      - End the directive list.
            DLST_LINE     - Render a line from dl_x1,dl_y1 to dl_x2,dl_y2
            DLST_RECT     - Cause a RectFill() of size dl_x1,dl_y1,dl_x2,dl_y2
            DLST_LINEPAT  - Set the line pattern to value held in dl_Pen
            DLST_FILLPAT  - Set the fill pattern to value held in dl_Pen
            DLST_LINESIZE - Set the drawlist line thickness via dl_Pen
            DLST_AMOVE    - AreaMove() using dl_x1,dl_y1
            DLST_ADRAW    - AreaDraw() using dl_x1,dl_y1
            DLST_AFILL    - Cause the AreaFill() operation
            DLST_FILL     - Flood() an area.
            DLST_ELLIPSE  - AreaEllipse()
            DLST_CIRCLE   - AreaCircle()
            DLST_BEVELBOX - currently unsupported (alpha function removed)
            DLST_ARC      - currently unsupported
            DLST_START    - currently unsupported
            DLST_BOUNDS   - currently unsupported

            Defaults to NULL.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        DRAWLIST_RefHeight (WORD)
            Reference height of the drawlist imagary grid.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        DRAWLIST_RefWidth (WORD)
            Reference width of the drawlist imagary grid.

            Applicability is (OM_NEW, OM_SET, OM_GET)


drawlist_ic/DRAWLIST_GetClass

    NAME
        DRAWLIST_GetClass -- Gets the pointer to the drawlist class.

    SYNOPSIS
        drawlist_class = DRAWLIST_GetClass();
        D0

        Class * DRAWLIST_GetClass(VOID);

    FUNCTION
        Obtains the pointer to the DrawList image class for use with
        NewObject().  This function always returns a valid pointer so
        you do not need to check it.  The reason is that if the library
        opens fine, then the pointer returned is already setup.  (Of course
        this implies that if opening the library fails, you shouldn't be
        calling this.)

        Note that this function does not create the class, that is done
        when the class library is opened.

    INPUTS
        Nothing.

    RESULT
        drawlist_class - Pointer to the DrawList image class.

    SEE ALSO


exec.doc

     AbortIO()
     AddDevice()
     AddHead()
     AddIntServer()
     AddLibrary()
     AddMemHandler()
     AddMemList()
     AddPort()
     AddResource()
     AddSemaphore()
     AddTail()
     AddTask()
     Alert()
     AllocAbs()
     Allocate()
     AllocEntry()
     AllocMem()
     AllocPooled()
     AllocSignal()
     AllocTrap()
     AllocVec()
     AttemptSemaphore()
     AttemptSemaphoreShared()
     AvailMem()
     CacheClearE()
     CacheClearU()
     CacheControl()
     CachePostDMA()
     CachePreDMA()
     Cause()
     CheckIO()
     CloseDevice()
     CloseLibrary()
     ColdReboot()
     CopyMem()
     CopyMemQuick()
     CreateIORequest()
     CreateMsgPort()
     CreatePool()
     Deallocate()
     Debug()
     DeleteIORequest()
     DeleteMsgPort()
     DeletePool()
     Disable()
     DoIO()
     Enable()
     Enqueue()
     FindName()
     FindPort()
     FindResident()
     FindSemaphore()
     FindTask()
     Forbid()
     FreeEntry()
     FreeMem()
     FreePooled()
     FreeSignal()
     FreeTrap()
     FreeVec()
     GetCC()
     GetMsg()
     InitCode()
     InitResident()
     InitSemaphore()
     InitStruct()
     Insert()
     MakeFunctions()
     MakeLibrary()
     ObtainQuickVector()
     ObtainSemaphore()
     ObtainSemaphoreList()
     ObtainSemaphoreShared()
     OldOpenLibrary()
     OpenDevice()
     OpenLibrary()
     OpenResource()
     Permit()
     Procure()
     PutMsg()
     RawDoFmt()
     ReleaseSemaphore()
     ReleaseSemaphoreList()
     RemDevice()
     RemHead()
     RemIntServer()
     RemLibrary()
     RemMemHandler()
     Remove()
     RemPort()
     RemResource()
     RemSemaphore()
     RemTail()
     RemTask()
     ReplyMsg()
     SendIO()
     SetExcept()
     SetFunction()
     SetIntVector()
     SetSignal()
     SetSR()
     SetTaskPri()
     Signal()
     StackSwap()
     SumKickData()
     SumLibrary()
     SuperState()
     Supervisor()
     TypeOfMem()
     UserState()
     Vacate()
     Wait()
     WaitIO()
     WaitPort()
     --Overview--
     ALLOCATE_MEMORY
     CALL_ADDRESS
     FREE_MEMORY
     GET_CONTEXT_FRAME
     NOP
     READ_ARRAY
     READ_BYTE
     READ_LONG
     READ_WORD
     RESET
     RETURN_TO_SYSTEM
     TURN_OFF_SINGLE
     TURN_ON_SINGLE
     WRITE_ARRAY
     WRITE_BYTE
     WRITE_LONG
     WRITE_WORD


exec.library/AbortIO

   NAME
    AbortIO - attempt to abort an in-progress I/O request

   SYNOPSIS
    AbortIO(iORequest)
            A1

    VOID AbortIO(struct IORequest *);

   FUNCTION
    Ask a device to abort a previously started IORequest.  This is done
    by calling the device's ABORTIO vector, with your given IORequest.

    AbortIO is a command the device that may or may not grant.  If
    successful, the device will stop processing the IORequest, and
    reply to it earlier than it would otherwise have done.

   NOTE
    AbortIO() does NOT Remove() the IORequest from your ReplyPort, OR
    wait for it to complete.  After an AbortIO() you must wait normally
    for the reply message before actually reusing the request.

    If a request has already completed when AbortIO() is called, no
    action is taken.

   EXAMPLE
        AbortIO(timer_request);
        WaitIO(timer_request);
        /* Message is free to be reused */

   INPUTS
    iORequest - pointer to an I/O request block (must have been used
        at least once.  May be active or finished).

   SEE ALSO
    WaitIO(), DoIO(), SendIO(), CheckIO()


exec.library/AddDevice

   NAME
    AddDevice -- add a device to the system

   SYNOPSIS
    AddDevice(device)
          A1

    void AddDevice(struct Device *);

   FUNCTION
    This function adds a new device to the system device list, making
    it available to other programs.  The device must be ready to be
    opened at this time.

   INPUTS
    device - pointer to a properly initialized device node

   SEE ALSO
    RemDevice(), OpenDevice(), CloseDevice(), MakeLibrary()


exec.library/AddHead

   NAME
    AddHead -- insert node at the head of a list

   SYNOPSIS
    AddHead(list, node)
        A0    A1

    void AddHead(struct List *, struct Node *)

   FUNCTION
    Add a node to the head of a doubly linked list. Assembly
    programmers may prefer to use the ADDHEAD macro from
    "exec/lists.i".

   WARNING
    This function does not arbitrate for access to the list.  The
    calling task must be the owner of the involved list.

   INPUTS
    list - a pointer to the target list header
    node - the node to insert at head

   SEE ALSO
    AddTail(), Enqueue(), Insert(), Remove(), RemHead(), RemTail()


exec.library/AddIntServer

   NAME
    AddIntServer -- add an interrupt server to a system server chain

   SYNOPSIS
    AddIntServer(intNum, interrupt)
             D0-0:4  A1

    void AddIntServer(ULONG, struct Interrupt *);

   FUNCTION
    This function adds a new interrupt server to a given server chain.
    The node is located on the chain in a priority dependent position.
    If this is the first server on a particular chain, interrupts will
    be enabled for that chain.

    Each link in the chain will be called in priority order until the
    chain ends or one of the servers returns with the 68000's Z condition
    code clear (indicating non-zero).  Servers on the chain should return
    with the Z flag clear if the interrupt was specifically for that
    server, and no one else.  VERTB servers should always return Z set.
    (Take care with High Level Language servers, the language may not
    have a mechanism for reliably setting the Z flag on exit).

    Servers are called with the following register conventions:

        D0 - scratch
        D1 - scratch

        A0 - scratch
        A1 - server is_Data pointer (scratch)

        A5 - jump vector register (scratch)
        A6 - scratch

        all other registers must be preserved

   INPUTS
    intNum - the Paula interrupt bit number (0 through 14). Processor
         level seven interrupts (NMI) are encoded as intNum 15.
         The PORTS, COPER, VERTB, EXTER and NMI interrupts are
         set up as server chains.
    interrupt - pointer to an Interrupt structure.
         By convention, the LN_NAME of the interrupt structure must
         point a descriptive string so that other users may
         identify who currently has control of the interrupt.

   WARNING
    Some compilers or assemblers may optimize code in unexpected ways,
    affecting the conditions codes returned from the function.  Watch
    out for a "MOVEM" instruction (which does not affect the condition
    codes) turning into "MOVE" (which does).

   BUGS
    The graphics library's VBLANK server, and some user code, currently
    assume that address register A0 will contain a pointer to the custom
    chips. If you add a server at a priority of 10 or greater, you must
    compensate for this by providing the expected value ($DFF000).

   SEE ALSO
    RemIntServer(), SetIntVector(), hardware/intbits.i,exec/interrupts.i


exec.library/AddLibrary

   NAME
    AddLibrary -- add a library to the system

   SYNOPSIS
    AddLibrary(library)
           A1

    void AddLibrary(struct Library *);

   FUNCTION
    This function adds a new library to the system, making it available
    to other programs.  The library should be ready to be opened at
    this time.  It will be added to the system library name list, and
    the checksum on the library entries will be calculated.

   INPUTS
    library - pointer to a properly initialized library structure

   SEE ALSO
    RemLibrary(), CloseLibrary(), OpenLibrary(), MakeLibrary()


exec.library/AddMemHandler

   NAME
    AddMemHandler - Add a low memory handler to exec                 (V39)

   SYNOPSIS
    AddMemHandler(memHandler)
                  A1

    VOID AddMemHandler(struct Interrupt *);

   FUNCTION
    This function adds a low memory handler to the system.  The handler
    is described in the Interrupt structure.  Due to multitasking
    issues, the handler must be ready to run the moment this function
    call is made.  (The handler may be called before the call returns)

   NOTE
    Adding a handler from within a handler will cause undefined
    actions.  It is safe to add a handler to the list while within
    a handler but the newly added handler may or may not be called
    for the specific failure currently running.

   EXAMPLE
    struct Interrupt *myInt;  /* Assume it is allocated */

    myInt->is_Node.ln_Pri=50;  /* Relatively early; before RAMLIB */

    /* Please fill in the name field! */
    myInt->is_Node.ln_Name="Example Handler";

    myInt->is_Data=(APTR)mydata_pointer;
    myInt->is_Code=myhandler_code;

    AddMemHandler(myInt);
    ... /* and so on */

    _myhandler_code:
            ; This is the handler code
            ; We are passed a pointer to struct MemHandlerData
            ; in a0, the value of is_Data in a1 and
            ; ExecBase in a6.
            ; We must not break forbid!!!
    ;
    ; Start off assuming we did nothing
    ;
        moveq.l	#MEM_DID_NOTHING,d0
        move.l	memh_RequestFlags(a0),d1
        btst.l	#MEMB_CHIP,d1	; Did the failure happen in CHIP
        beq.s	handler_nop	; If not, we have nothing to do
        bsr	DoMyMagic	; Do the magic...
        ; DoMyMagic frees whatever we can and returns d0 set...
    handler_nop:
        rts			; Return with d0 set...

   INPUTS
    memHandler - A pointer to a completely filled in Interrupt structure
                 The priority field determine the position of the handler
                 with respect to other handlers in the system.  The higher
                 the priority, the earlier the handler is called.
                 Positive priorities will have the handler called before
                 any of the library expunge vectors are called.  Negative
                 priority handlers will be called after the library
                 expunge routines are called.
                 (Note:  RAMLIB is a handler at priority 0)

   SEE ALSO
    RemMemHandler(), exec/interrupts.i


exec.library/AddMemList

   NAME
    AddMemList - add memory to the system free pool

   SYNOPSIS
    AddMemList( size, attributes, pri, base, name )
                     D0      D1        D2   A0    A1

    void AddMemList(ULONG, ULONG, LONG, APTR, STRPTR);

   FUNCTION
    Add a new region of memory to the system free pool.  The first few
    bytes will be used to hold the MemHeader structure.  The remainder
    will be made available to the rest of the world.

   INPUTS
    size - the size (in bytes) of the memory area
    attributes - the attributes word that the memory pool will have
    pri  - the priority for this memory.  CHIP memory has a pri of -10,
           16 bit expansion memory has a priority of 0.  The higher the
           priority, the closer to the head of the memory list it will
           be placed.
    base - the base of the new memory area
    name - the name that will be used in the memory header, or NULL
           if no name is to be provided.  This name is not copied, so it
           must remain valid for as long as the memory header is in the
           system.

   NOTES
    *DO NOT* add memory to the system with the attribute of MEMF_KICK.
    EXEC will mark your memory as such if it is of the right type.

   SEE ALSO
    AllocMem(), exec/memory.h


exec.library/AddPort

   NAME
    AddPort -- add a public message port to the system

   SYNOPSIS
    AddPort(port)
        A1

    void AddPort(struct MsgPort *);

   FUNCTION
    This function attaches a message port structure to the system's
    public message port list, where it can be found by the FindPort()
    function.  The name and priority fields of the port structure must
    be initialized prior to calling this function.	If the user does
    not require the priority field, it should be initialized to zero.

    Only ports that will be searched for with FindPort() need to
    be added to the system list.  In addition, adding ports is often
    useful during debugging.  If the port will be searched for,
    the priority field should be at least 1 (to avoid the large number
    of inactive ports at priority zero).  If the port will be searched
    for often, set the priority in the 50-100 range (so it will be
    before other less used ports).

    Once a port has been added to the naming list, you must be careful
    to remove the port from the list (via RemPort) before deallocating
    its memory.

   NOTE
    A point of confusion is that clearing a MsgPort structure to all
    zeros is not enough to prepare it for use.  As mentioned in the
    Exec chapter of the ROM Kernel Manual, the List for the MsgPort
    must be initialized.  This is automatically handled by AddPort(),
    and amiga.lib/CreatePort.  This initialization can be done manually
    with amiga.lib/NewList or the assembly NEWLIST macro.

    Do not AddPort an active port.

   INPUTS
    port - pointer to a message port

   SEE ALSO
    RemPort(), FindPort(), amiga.lib/CreatePort(), amiga.lib/NewList()


exec.library/AddResource

   NAME
    AddResource -- add a resource to the system

   SYNOPSIS
    AddResource(resource)
            A1

    void AddResource(APTR);

   FUNCTION
    This function adds a new resource to the system and makes it
    available to other users.  The resource must be ready to be called
    at this time.

    Resources currently have no system-imposed structure, however they
    must start with a standard named node (LN_SIZE), and should with
    a standard Library node (LIB_SIZE).

   INPUTS
    resource - pointer an initialized resource node

   SEE ALSO
    RemResource(), OpenResource(), MakeLibrary()


exec.library/AddSemaphore

   NAME
    AddSemaphore -- initialize then add a signal semaphore to the system

   SYNOPSIS
    AddSemaphore(signalSemaphore)
             A1

    void AddSemaphore(struct SignalSemaphore *);

   FUNCTION
    This function attaches a signal semaphore structure to the system's
    public signal semaphore list.  The name and priority fields of the
    semaphore structure must be initialized prior to calling this
    function.  If you do not want to let others rendezvous with this
    semaphore, use InitSemaphore() instead.

    If a semaphore has been added to the naming list, you must be
    careful to remove the semaphore from the list (via RemSemaphore)
    before deallocating its memory.

    Semaphores that are linked together in an allocation list (which
    ObtainSemaphoreList() would use) may not be added to the system
    naming list, because the facilities use the link field of the
    signal semaphore in incompatible ways

   INPUTS
       signalSemaphore -- an signal semaphore structure

   BUGS
    Does not work in Exec <V36.  Instead use this code:

        #include <exec/execbase.h>
        #include <exec/nodes.h>
        extern struct ExecBase *SysBase;
        ...
        void LocalAddSemaphore(s)
        struct SignalSemaphore *s;
        {
        s->ss_Link.ln_Type=NT_SIGNALSEM;
        InitSemaphore(s);
        Forbid();
        Enqueue(&SysBase->SemaphoreList,s);
        Permit();
        }

   SEE ALSO
    RemSemaphore(), FindSemaphore(), InitSemaphore()


exec.library/AddTail

   NAME
    AddTail -- append node to tail of a list

   SYNOPSIS
    AddTail(list, node)
                A0    A1

    void AddTail(struct List *, struct Node *);

   FUNCTION
    Add a node to the tail of a doubly linked list.  Assembly
    programmers may prefer to use the ADDTAIL macro from
    "exec/lists.i".

   WARNING
    This function does not arbitrate for access to the list.  The
    calling task must be the owner of the involved list.

   INPUTS
    list - a pointer to the target list header
    node - a pointer to the node to insert at tail of the list

   SEE ALSO
    AddHead(), Enqueue(), Insert(), Remove(), RemHead(), RemTail()


exec.library/AddTask

   NAME
    AddTask -- add a task to the system

   SYNOPSIS
    result = AddTask(task, initialPC, finalPC)
     D0               A1    A2         A3

    APTR AddTask(struct Task *, APTR, APTR);

   FUNCTION
    Add a task to the system.  A reschedule will be run; the task with
    the highest priority in the system will start to execute (this may
    or may not be the new task).

    Certain fields of the task control block must be initialized and a
    stack allocated prior to calling this function.  The absolute
    smallest stack that is allowable is something in the range of 100
    bytes, but in general the stack size is dependent on what
    subsystems are called. In general 256 bytes is sufficient if only
    Exec is called, and 4K will do if anything in the system is called.
    DO NOT UNDERESTIMATE.  If you use a stack sniffing utility,
    leave a healthy pad above the minimum value.  The system guarantees
    that its stack operations will leave the stack longword aligned.

    This function will temporarily use space from the new task's stack
    for the task's initial set of registers.  This space is allocated
    starting at the SPREG location specified in the task control block
    (not from SPUPPER).  This means that a task's stack may contain
    static data put there prior to its execution.  This is useful for
    providing initialized global variables or some tasks may want to
    use this space for passing the task its initial arguments.

    A task's initial registers are set to zero (except the PC).

    The TC_MEMENTRY field of the task structure may be extended by
    the user to hold additional MemLists (as returned by AllocEntry()).
    These will be automatically be deallocated at RemTask() time.
    If the code you have used to start the task has already added
    something to the MEMENTRY list, simply use AddHead to add your
    new MemLists in.  If no initialization has been done, a NewList will
    need to be performed.

   INPUTS
    task  - pointer to the task control block (TCB).  All unset fields
        must be zero.
    initialPC - the initial entry point's address
    finalPC - the finalization code entry point's address.  If zero,
          the system will use a general finalizer. This pointer is
          placed on the stack as if it were the outermost return
          address.

   RESULTS
    For V36, AddTask returns either a NULL or the address of the new
    task.  Old code need not check this.

   WARNING
    Tasks are a low-level building block, and are unable to call
    dos.library, or any system function that might call dos.library.
    See the AmigaDOS CreateProc() for information on Processes.

   SEE ALSO
    RemTask(), FindTask(), amiga.lib/CreateTask(), dos/CreateProc(),
    amiga.lib/NewList()


exec.library/Alert

   NAME
    Alert -- alert the user of an error

   SYNOPSIS
    Alert(alertNum)
          D7

    void Alert(ULONG);

   FUNCTION
    Alerts the user of a serious system problem.  This function will
    bring the system to a grinding halt, and do whatever is necessary
    to present the user with a message stating what happened.
    Interrupts are disabled, and an attempt to post the alert is made.
    If that fails, the system is reset.  When the system comes up
    again, Exec notices the cause of the failure and tries again to
    post the alert.

    If the Alert is a recoverable type, this call MAY return.

    This call may be made at any time, including interrupts.
    (Well, only in interrupts if it is non-recoverable)

    New, for V39:
    The alert now times out based on the value in LastAlert[3]
    This value is transfered accross warm-reboots and thus will let
    you set it once.  The value is the number of frames that need to
    be displayed before the alert is auto-answered.  A value of
    0 will thus make the alert never be displayed.  Note that
    it is recommended that applications *NOT* change the value in
    LastAlert[] since the main reason for this is to make
    unattended operation of the Amiga (in production enviroments)
    possible.

   POST-MORTEM DIAGNOSIS
    There are several options for determining the cause of a crash.
    Descriptions of each alert number can be found in the "alerts.h"
    include file.

    A remote terminal can be attached to the Amiga's first built-in
    serial port.  Set the communication parameters to 9600 baud, 8 bits,
    no parity.  Before resetting the machine, the Alert function will
    blink the power LED 10 times.  While the power indicator is flashing,
    pressing DELETE on the remote terminal will invoke the ROM debugger.

   INPUT
    alertNum   - a number indicating the particular alert.  -1 is
                 not a valid input.

   NOTE
    Much more needs to be said about this function and its implications.

   SEE ALSO
    exec/alerts.h


exec.library/AllocAbs

   NAME
    AllocAbs -- allocate at a given location

   SYNOPSIS
    memoryBlock = AllocAbs(byteSize, location)
    D0		       D0	 A1

    void *AllocAbs(ULONG, APTR);

   FUNCTION
    This function attempts to allocate memory at a given absolute
    memory location.  Often this is used by boot-surviving entities
    such as recoverable ram-disks.	If the memory is already being
    used, or if there is not enough memory to satisfy the request,
    AllocAbs will return NULL.

    This block may not be exactly the same as the requested block
    because of rounding, but if the return value is non-zero, the block
    is guaranteed to contain the requested range.

   INPUTS
    byteSize - the size of the desired block in bytes
           This number is rounded up to the next larger
           block size for the actual allocation.
    location - the address where the memory MUST be.

   RESULT
    memoryBlock - a pointer to the newly allocated memory block, or
              NULL if failed.

   NOTE
    If the free list is corrupt, the system will panic with alert
    AN_MemCorrupt, $01000005.

    The 8 bytes past the end of an AllocAbs will be changed by Exec
    relinking the next block of memory.  Generally you can't trust
    the first 8 bytes of anything you AllocAbs.

   SEE ALSO
    AllocMem(), FreeMem()


exec.library/Allocate

   NAME
    Allocate - allocate a block of memory

   SYNOPSIS
    memoryBlock=Allocate(memHeader, byteSize)
    D0		     A0 	D0

    void *Allocate(struct MemHeader *, ULONG);

   FUNCTION
    This function is used to allocate blocks of memory from a given
    private free memory pool (as specified by a MemHeader and its
    memory chunk list).  Allocate will return the first free block that
    is greater than or equal to the requested size.

    All blocks, whether free or allocated, will be block aligned;
    hence, all allocation sizes are rounded up to the next block even
    value (e.g. the minimum allocation resolution is currently 8
    bytes.  A request for 8 bytes will use up exactly 8 bytes.  A
    request for 7 bytes will also use up exactly 8 bytes.).

    This function can be used to manage an application's internal data
    memory.  Note that no arbitration of the MemHeader and associated
    free chunk list is done.  You must be the owner before calling
    Allocate.

   INPUTS
    memHeader - points to the local memory list header.
    byteSize - the size of the desired block in bytes.

   RESULT
    memoryBlock - a pointer to the just allocated free block.
           If there are no free regions large enough to satisfy the
           request, return zero.

   EXAMPLE
    #include <exec/types.h>
    #include <exec/memory.h>
    void *AllocMem();
    #define BLOCKSIZE 4096L /* Or whatever you want */

    void main()
    {
    struct MemHeader *mh;
    struct MemChunk  *mc;
    APTR   block1;
    APTR   block2;

        /* Get the MemHeader needed to keep track of our new block */
        mh = (struct MemHeader *)
         AllocMem((long)sizeof(struct MemHeader), MEMF_CLEAR );
        if( !mh )
        exit(10);

        /* Get the actual block the above MemHeader will manage */
        mc = (struct MemChunk *)AllocMem( BLOCKSIZE, 0L );
        if( !mc )
        {
        FreeMem( mh, (long)sizeof(struct MemHeader) ); exit(10);
        }

        mh->mh_Node.ln_Type = NT_MEMORY;
        mh->mh_Node.ln_Name = "myname";
        mh->mh_First = mc;
        mh->mh_Lower = (APTR) mc;
        mh->mh_Upper = (APTR) ( BLOCKSIZE + (ULONG) mc );
        mh->mh_Free  = BLOCKSIZE;

        /* Set up first chunk in the freelist */
        mc->mc_Next  = NULL;
        mc->mc_Bytes = BLOCKSIZE;

        block1 = (APTR) Allocate( mh, 20L );
        block2 = (APTR) Allocate( mh, 314L );
        printf("mh=$%lx mc=$%lxn",mh,mc);
        printf("Block1=$%lx, Block2=$%lxn",block1,block2);

        FreeMem( mh, (long)sizeof(struct MemHeader) );
        FreeMem( mc, BLOCKSIZE );
    }

   NOTE
    If the free list is corrupt, the system will panic with alert
    AN_MemCorrupt, $01000005.

   SEE ALSO
    Deallocate(), exec/memory.h


exec.library/AllocEntry

   NAME
    AllocEntry -- allocate many regions of memory

   SYNOPSIS
    memList = AllocEntry(memList)
    D0		     A0

    struct MemList *AllocEntry(struct MemList *);

   FUNCTION
    This function takes a memList structure and allocates enough memory
    to hold the required memory as well as a MemList structure to keep
    track of it.

    These MemList structures may be linked together in a task control
    block to keep track of the total memory usage of this task. (See
    the description of TC_MEMENTRY under RemTask).

   INPUTS
    memList -- A MemList structure filled in with MemEntry structures.

   RESULTS
    memList -- A different MemList filled in with the actual memory
        allocated in the me_Addr field, and their sizes in me_Length.
        If enough memory cannot be obtained, then the requirements of
        the allocation that failed is returned and bit 31 is set.

        WARNING: The result is unusual!  Bit 31 indicates failure.

   EXAMPLES
    The user wants five regions of 2, 4, 8, 16, and 32 bytes in size
    with requirements of MEMF_CLEAR, MEMF_PUBLIC, MEMF_CHIP!MEMF_CLEAR,
    MEMF_CLEAR, and MEMF_PUBLIC!MEMF_CLEAR respectively.  The
    following code fragment would do that:

        MemListDecl:
        DS.B	LN_SIZE 	    * reserve space for list node
        DC.W	5		    * number of entries
        DC.L	MEMF_CLEAR		    * entry #0
        DC.L	2
        DC.L	MEMF_PUBLIC		    * entry #1
        DC.L	4
        DC.L	MEMF_CHIP!MEMF_CLEAR	    * entry #2
        DC.L	8
        DC.L	MEMF_CLEAR	   	    * entry #3
        DC.L	16
        DC.L	MEMF_PUBLIC!MEMF_CLEAR	    * entry #4
        DC.L	32

        start:
        LEA.L	MemListDecl(PC),A0
        JSR	_LVOAllocEntry(a6)
        BCLR.L	#31,D0
        BEQ.S	success

        ------- Type of memory that we failed on is in D0

   BUGS
    If any one of the allocations fails, this function fails to back
    out fully.  This is fixed by the "SetPatch" program on V1.3
    Workbench disks.

   SEE ALSO
    exec/memory.h


exec.library/AllocMem

   NAME
    AllocMem -- allocate memory given certain requirements

   SYNOPSIS
    memoryBlock = AllocMem(byteSize, attributes)
    D0		       D0	 D1

    void *AllocMem(ULONG, ULONG);

   FUNCTION
    This is the memory allocator to be used by system code and
    applications.  It provides a means of specifying that the allocation
    should be made in a memory area accessible to the chips, or
    accessible to shared system code.

    Memory is allocated based on requirements and options.	Any
    "requirement" must be met by a memory allocation, any "option" will
    be applied to the block regardless.  AllocMem will try all memory
    spaces until one is found with the proper requirements and room for
    the memory request.

   INPUTS
    byteSize - the size of the desired block in bytes.  (The operating
        system will automatically round this number to a multiple of
        the system memory chunk size)

    attributes -
        requirements

        If no flags are set, the system will return the best
        available memory block.  For expanded systems, the fast
        memory pool is searched first.

        MEMF_CHIP:	If the requested memory will be used by
                the Amiga custom chips, this flag *must*
                be set.

                Only certain parts of memory are reachable
                by the special chip sets' DMA circuitry.
                Chip DMA includes screen memory, images that
                are blitted, audio data, copper lists, sprites
                and Pre-V36 trackdisk.device buffers.

        MEMF_FAST:	This is non-chip memory.  If no flag is set
                MEMF_FAST is taken as the default.

                DO NOT SPECIFY MEMF_FAST unless you know
                exactly what you are doing!  If MEMF_FAST is
                set, AllocMem() will fail on machines that
                only have chip memory!  This flag may not
                be set when MEMF_CHIP is set.

        MEMF_PUBLIC:	Memory that must not be mapped, swapped,
                or otherwise made non-addressable. ALL
                MEMORY THAT IS REFERENCED VIA INTERRUPTS
                AND/OR BY OTHER TASKS MUST BE EITHER PUBLIC
                OR LOCKED INTO MEMORY! This includes both
                code and data.

        MEMF_LOCAL:	This is memory that will not go away
                after the CPU RESET instruction.  Normally,
                autoconfig memory boards become unavailable
                after RESET while motherboard memory
                may still be available.  This memory type
                is now automatically set in V36.  Pre-V36
                systems may not have this memory type
                and AllocMem() will then fail.

        MEMF_24BITDMA:	This is memory that is within the address
                range of 24-bit DMA devices.  (Zorro-II)
                This is required if you run a Zorro-II
                DMA device on a machine that has memory
                beyond the 24-bit addressing limit of
                Zorro-II.  This memory type
                is now automatically set in V36.  Pre-V36
                systems may not have this memory type
                and AllocMem() will then fail.

        MEMF_KICK:	This memory is memory that EXEC was able
                to access during/before the KickMem and
                KickTags are processed.  This means that
                if you wish to use these, you should allocate
                memory with this flag.  This flag is
                automaticly set by EXEC in V39.  Pre-V39
                systems may not have this memory type and
                AllocMem() will then fail.  Also, *DO NOT*
                ever add memory the system with this flag
                set.  EXEC will set the flag as needed
                if the memory matches the needs of EXEC.

        options

        MEMF_CLEAR:	The memory will be initialized to all
                zeros.

        MEMF_REVERSE:	This allocates memory from the top of
                the memory pool.  It searches the pools
                in the same order, such that FAST memory
                will be found first.  However, the
                memory will be allocated from the highest
                address available in the pool.  This
                option is new as of V36.  Note that this
                option has a bug in pre-V39 systems.

        MEMF_NO_EXPUNGE	This will prevent an expunge to happen on
                a failed memory allocation.  This option is
                new to V39 and will be ignored in V37.
                If a memory allocation with this flag
                set fails, the allocator will not cause
                any expunge operations.  (See AddMemHandler())

   RESULT
    memoryBlock - a pointer to the newly allocated memory block.
        If there are no free memory regions large enough to satisfy
        the request, zero will be returned.  The pointer must be
        checked for zero before the memory block may be used!
        The memory block returned is long word aligned.

   WARNING
    The result of any memory allocation MUST be checked, and a viable
    error handling path taken.  ANY allocation may fail if memory has
    been filled.

   EXAMPLES
    AllocMem(64,0L)		- Allocate the best available memory
    AllocMem(25,MEMF_CLEAR) - Allocate the best available memory, and
                  clear it before returning.
    AllocMem(128,MEMF_CHIP) - Allocate chip memory
    AllocMem(128,MEMF_CHIP|MEMF_CLEAR) - Allocate cleared chip memory
    AllocMem(821,MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR) - Allocate cleared,
        public, chip memory.

   NOTE
    If the free list is corrupt, the system will panic with alert
    AN_MemCorrupt, $01000005.

    This function may not be called from interrupts.

    A DOS process will have its pr_Result2 field set to
    ERROR_NO_FREE_STORE if the memory allocation fails.

   SEE ALSO
    FreeMem()


exec.library/AllocPooled

    NAME
    AllocPooled -- Allocate memory with the pool manager (V39)

    SYNOPSIS
    memory=AllocPooled(poolHeader,memSize)
    d0                 a0         d0

    void *AllocPooled(void *,ULONG);

    FUNCTION
    Allocate memSize bytes of memory, and return a pointer. NULL is
    returned if the allocation fails.

    Doing a DeletePool() on the pool will free all of the puddles
    and thus all of the allocations done with AllocPooled() in that
    pool.  (No need to FreePooled() each allocation)

    INPUTS
    memSize - the number of bytes to allocate
    poolHeader - a specific private pool header.

    RESULT
    A pointer to the memory, or NULL.
    The memory block returned is long word aligned.

    NOTES
    The pool function do not protect an individual pool from
    multiple accesses.  The reason is that in most cases the pools
    will be used by a single task.  If your pool is going to
    be used by more than one task you must Semaphore protect
    the pool from having more than one task trying to allocate
    within the same pool at the same time.  Warning:  Forbid()
    protection *will not work* in the future.  *Do NOT* assume
    that we will be able to make it work in the future.  AllocPooled()
    may well break a Forbid() and as such can only be protected
    by a semaphore.

    To track sizes yourself, the following code can be used:
    Assumes a6=ExecBase

    ;
    ; Function to do AllocVecPooled(Pool,memSize)
    ;
    AllocVecPooled:	addq.l	#4,d0		; Get space for tracking
            move.l	d0,-(sp)	; Save the size
            jsr	_LVOAllocPooled(a6)	; Call pool...
            move.l	(sp)+,d1	; Get size back...
            tst.l	d0		; Check for error
            beq.s	avp_fail	; If NULL, failed!
            move.l	d0,a0		; Get pointer...
            move.l	d1,(a0)+	; Store size
            move.l	a0,d0		; Get result
    avp_fail:	rts			; return

    ;
    ; Function to do FreeVecPooled(pool,memory)
    ;
    FreeVecPooled:	move.l	-(a1),d0	; Get size / ajust pointer
            jmp	_LVOFreePooled(a6)

    SEE ALSO
    FreePooled(), CreatePool(), DeletePool()


exec.library/AllocSignal

   NAME
    AllocSignal -- allocate a signal bit

   SYNOPSIS
    signalNum = AllocSignal(signalNum)
    D0			D0

    BYTE AllocSignal(BYTE);

   FUNCTION
    Allocate a signal bit from the current tasks' pool.  Either a
    particular bit, or the next free bit may be allocated.	The signal
    associated with the bit will be properly initialized (cleared).  At
    least 16 user signals are available per task.  Signals should be
    deallocated before the task exits.

    If the signal is already in use (or no free signals are available)
    a -1 is returned.

    Allocated signals are only valid for use with the task that
    allocated them.

   WARNING
    Signals may not be allocated or freed from exception handling code.

   INPUTS
    signalNum - the desired signal number {of 0..31} or -1 for no
            preference.

   RESULTS
    signalNum - the signal bit number allocated {0..31}. If no signals
            are available, this function returns -1.

   SEE ALSO
    FreeSignal()


exec.library/AllocTrap

   NAME
    AllocTrap -- allocate a processor trap vector

   SYNOPSIS
    trapNum = AllocTrap(trapNum)
    D0		    D0

    LONG AllocTrap(LONG);

   FUNCTION
    Allocate a trap number from the current task's pool.  These trap
    numbers are those associated with the 68000 TRAP type instructions.
    Either a particular number, or the next free number may be
    allocated.

    If the trap is already in use (or no free traps are available) a -1
    is returned.

    This function only affects the currently running task.

    Traps are sent to the trap handler pointed at by tc_TrapCode.
    Unless changed by user code, this points to a standard trap
    handler.  The stack frame of the exception handler will be:

        0(SP) = Exception vector number.  This will be in the
            range of 32 to 47 (corresponding to the
            Trap #1...Trap #15 instructions).
        4(SP) = 68000/68010/68020/68030, etc. exception frame

    tc_TrapData is not used.

   WARNING
    Traps may not be allocated or freed from exception handling code.
    You are not allowed to write to the exception table yourself.  In
    fact, on some machines you will have trouble finding it - the VBR
    register may be used to remap its location.

   INPUTS
    trapNum - the desired trap number {of 0..15} or -1
          for no preference.

   RESULTS
    trapNum - the trap number allocated {of 0..15}.  If no traps are
          available, this function returns -1.	Instructions of the
          form "Trap #trapNum" will be sent to the task's trap
          handler.

   SEE ALSO
    FreeTrap()


exec.library/AllocVec

   NAME
    AllocVec -- allocate memory and keep track of the size  (V36)

   SYNOPSIS
    memoryBlock = AllocVec(byteSize, attributes)
    D0		       D0	 D1

    void *AllocVec(ULONG, ULONG);

   FUNCTION
    This function works identically to AllocMem(), but tracks the size
    of the allocation.

    See the AllocMem() documentation for details.

   WARNING
    The result of any memory allocation MUST be checked, and a viable
    error handling path taken.  ANY allocation may fail if memory has
    been filled.

   SEE ALSO
    FreeVec(), AllocMem()


exec.library/AttemptSemaphoreShared

   NAME
    AttemptSemaphoreShared -- try to obtain without blocking       (V37)

   SYNOPSIS
    success = AttemptSemaphoreShared(signalSemaphore)
    D0			         A0

    LONG AttemptSemaphoreShared(struct SignalSemaphore *);

   FUNCTION
    This call is similar to ObtainSemaphoreShared(), except that it
    will not block if the semaphore could not be locked.

   INPUT
       signalSemaphore -- an initialized signal semaphore structure

   RESULT
    success -- TRUE if the semaphore was granted, false if some
        other task already possessed the semaphore in exclusive mode.

   NOTE
    This call does NOT preserve registers.

    Starting in V39 this call will grant the semaphore if the
    caller is already the owner of an exclusive lock on the semaphore.
    In pre-V39 systems this would not be the case.  If you need this
    feature you can do the following workaround:

    LONG myAttemptSempahoreShared(struct SignalSemaphore *ss)
    {
    LONG result;

        /* Try for a shared semaphore */
        if (!(result=AttemptSemaphoreShared(ss)))
        {
            /* Now try for the exclusive one... */
            result=AttempSemaphore(ss);
        }
        return(result);
    }

   SEE ALSO
    ObtainSemaphore() ObtainSemaphoreShared(), ReleaseSemaphore(),
    exec/semaphores.h


exec.library/CacheClearE

   NAME
    CacheClearE - Cache clearing with extended control (V37)

   SYNOPSIS
    CacheClearE(address,length,caches)
                a0      d0     d1

    void CacheClearE(APTR,ULONG,ULONG);

   FUNCTION
    Flush out the contents of the CPU instruction and/or data caches.
    If dirty data cache lines are present, push them to memory first.

    Motorola CPUs have separate instruction and data caches.  A data
    write does not update the instruction cache.  If an instruction is
    written to memory or modified, the old instruction may still exist
    in the cache.  Before attempting to execute the code, a flush of
    the instruction cache is required.

    For most systems, the data cache is not updated by Direct Memory
    Access (DMA), or if some external factor changes shared memory.

    Caches must be cleared after *any* operation that could cause
    invalid or stale data.  The most common cases are DMA and modifying
    instructions using the processor.

    Some examples:
            Self modifying code
            Building Jump tables
            Run-time code patches
            Relocating code for use at different addresses.
            Loading code from disk

   INPUTS
    address - Address to start the operation.  This may be rounded
          due to hardware granularity.
    length	- Length of area to be cleared, or $FFFFFFFF to indicate all
          addresses should be cleared.
    caches  - Bit flags to indicate what caches to affect.  The current
          supported flags are:
            CACRF_ClearI	;Clear instruction cache
            CACRF_ClearD	;Clear data cache
          All other bits are reserved for future definition.

   NOTES
    On systems with a copyback mode cache, any dirty data is pushed
    to memory as a part of this operation.

    Regardless of the length given, the function will determine the most
    efficient way to implement the operation.  For some cache systems,
    including the 68030, the overhead partially clearing a cache is often
    too great.  The entire cache may be cleared.

    For all current Amiga models, Chip memory is set with Instruction
    caching enabled, data caching disabled.  This prevents coherency
    conflicts with the blitter or other custom chip DMA.  Custom chip
    registers are marked as non-cacheable by the hardware.

    The system takes care of appropriately flushing the caches for normal
    operations.  The instruction cache is cleared by all calls that
    modify instructions, including LoadSeg(), MakeLibrary() and
    SetFunction().

   SEE ALSO
    exec/execbase.i, CacheControl(), CacheClearU()


exec.library/CacheClearU

   NAME
    CacheClearU - User callable simple cache clearing (V37)

   SYNOPSIS
    CacheClearU()

    void CacheClearU(void);

   FUNCTION
    Flush out the contents of any CPU instruction and data caches.
    If dirty data cache lines are present, push them to memory first.

    Caches must be cleared after *any* operation that could cause
    invalid or stale data.  The most common cases are DMA and modifying
    instructions using the processor.  See the CacheClearE() autodoc
    for a more complete description.

    Some examples of when the cache needs clearing:
            Self modifying code
            Building Jump tables
            Run-time code patches
            Relocating code for use at different addresses.
            Loading code from disk

   SEE ALSO
    exec/execbase.i, CacheControl(), CacheClearE()


exec.library/CacheControl

   NAME
    CacheControl - Instruction & data cache control

   SYNOPSIS
    oldBits = CacheControl(cacheBits,cacheMask)
    D0                     D0        D1

    ULONG CacheControl(ULONG,ULONG);

   FUNCTION
    This function provides global control of any instruction or data
    caches that may be connected to the system.  All settings are
    global -- per task control is not provided.

    The action taken by this function will depend on the type of
    CPU installed.  This function may be patched to support external
    caches, or different cache architectures.  In all cases the function
    will attempt to best emulate the provided settings.  Use of this
    function may save state specific to the caches involved.

    The list of supported settings is provided in the exec/execbase.i
    include file.  The bits currently defined map directly to the Motorola
    68030 CPU CACR register.  Alternate cache solutions may patch into
    the Exec cache functions.  Where possible, bits will be interpreted to
    have the same meaning on the installed cache.

   INPUTS
    cacheBits - new values for the bits specified in cacheMask.

    cacheMask - a mask with ones for all bits to be changed.

   RESULT
    oldBits   - the complete prior values for all settings.

   NOTE
    As a side effect, this function clears all caches.

   SEE ALSO
    exec/execbase.i, CacheClearU(), CacheClearE()


exec.library/CachePostDMA

   NAME
    CachePostDMA - Take actions after to hardware DMA  (V37)

   SYNOPSIS
    CachePostDMA(vaddress,&length,flags)
                 a0       a1      d0

    CachePostDMA(APTR,LONG *,ULONG);

   FUNCTION
    Take all appropriate steps after Direct Memory Access (DMA).  This
    function is primarily intended for writers of DMA device drivers.  The
    action will depend on the CPU type installed, caching modes, and the
    state of any Memory Management Unit (MMU) activity.

    As implemented
        68000 - Do nothing
        68010 - Do nothing
        68020 - Do nothing
        68030 - Flush the data cache
        68040 - Flush matching areas of the data cache
        ????? - External cache boards, Virtual Memory Systems, or
            future hardware may patch this vector to best emulate
            the intended behavior.
            With a Bus-Snooping CPU, this function my end up
            doing nothing.

   INPUTS
    address	- Same as initially passed to CachePreDMA
    length	- Same as initially passed to CachePreDMA
    flags	- Values:
            DMA_NoModify - If the area was not modified (and
            thus there is no reason to flush the cache) set
            this bit.

            DMA_ReadFromRAM - Indicates that this DMA is a
            read from RAM to the DMA device (ie - a write
            to the hard drive)  This flag is not required
            but if used must match in both the PreDMA and
            PostDMA calls.  This flag *should* be used to
            help the system provide the best performance.
            This flag is safe in all versions of CachePostDMA()

   SEE ALSO
    exec/execbase.i, CachePreDMA(), CacheClearU(), CacheClearE()


exec.library/CachePreDMA

   NAME
    CachePreDMA - Take actions prior to hardware DMA  (V37)

   SYNOPSIS
    paddress = CachePreDMA(vaddress,&length,flags)
    d0                     a0       a1      d0

    APTR CachePreDMA(APTR,LONG *,ULONG);

   FUNCTION
    Take all appropriate steps before Direct Memory Access (DMA).  This
    function is primarily intended for writers of DMA device drivers.  The
    action will depend on the CPU type installed, caching modes, and the
    state of any Memory Management Unit (MMU) activity.

    This function supports advanced cache architectures that have
    "copyback" modes.  With copyback, write data may be cached, but not
    actually flushed out to memory.  If the CPU has unflushed data at the
    time of DMA, data may be lost.

    As implemented
        68000 - Do nothing
        68010 - Do nothing
        68020 - Do nothing
        68030 - Do nothing
        68040 - Write any matching dirty cache lines back to memory.
            As a side effect of the 68040's design, matching data
            cache lines are also invalidated -- future CPUs may
            be different.
        ????? - External cache boards, Virtual Memory Systems, or
            future hardware may patch this vector to best emulate
            the intended behavior.
            With a Bus-Snooping CPU, this function my end up
            doing nothing.

   INPUTS
    address	- Base address to start the action.
    length	- Pointer to a longword with a length.
    flags	- Values:
            DMA_Continue - Indicates this call is to complete
            a prior request that was broken up.

            DMA_ReadFromRAM - Indicates that this DMA is a
            read from RAM to the DMA device (ie - a write
            to the hard drive)  This flag is not required
            but if used must match in both the PreDMA and
            PostDMA calls.  This flag *should* be used to
            help the system provide the best performance.
            This flag is safe in all versions of CachePreDMA()

   RESULTS
    paddress- Physical address that corresponds to the input virtual
          address.
    &length	- This length value will be updated to reflect the contiguous
          length of physical memory present at paddress.  This may
          be smaller than the requested length.  To get the mapping
          for the next chunk of memory, call the function again with
          a new address, length, and the DMA_Continue flag.

   NOTE
    Due to processor granularity, areas outside of the address range
    may be affected by the cache flushing actions.  Care has been taken
    to ensure that no harm is done outside the range, and that activities
    on overlapping cache lines won't harm data.

   SEE ALSO
    exec/execbase.i, CachePostDMA(), CacheClearU(), CacheClearE()


exec.library/CheckIO

   NAME
    CheckIO -- get the status of an IORequest

   SYNOPSIS
    result = CheckIO(IORequest)
    D0		 A1

    struct IORequest *CheckIO(struct IORequest *);

   FUNCTION
    This function determines the current state of an I/O request and
    returns FALSE if the I/O has not yet completed.  This function
    effectively hides the internals of the I/O completion mechanism.

    CheckIO() will NOT remove the returned IORequest from the reply port.
    This is best performed with WaitIO(). If the request has already
    completed, WaitIO() will return quickly. Use of the Remove()
    function is dangerous, since other tasks may still be adding things
    to your message port; a Disable() would be required.

    This function should NOT be used to busy loop (looping until IO is
    complete).  WaitIO() is provided for that purpose.

   INPUTS
    iORequest - pointer to an I/O request block

   RESULTS
    result - NULL if I/O is still in progress.  Otherwise
         D0 points to the IORequest block.

   NOTE
    CheckIO can hang if called on an IORequest that has never been used.
    This occurs if LN_TYPE of the IORequest is set to "NT_MESSAGE".
    Instead simply set LN_TYPE to 0.

   SEE ALSO
    DoIO(), SendIO(), WaitIO(), AbortIO()


exec.library/CloseDevice

   NAME
    CloseDevice -- conclude access to a device

   SYNOPSIS
    CloseDevice(iORequest)
            A1

    void CloseDevice(struct IORequest *);

   FUNCTION
    This function informs the device that access to a device/unit
    previously opened has been concluded.  The device may perform
    certain house-cleaning operations.

    The user must ensure that all outstanding IORequests have been
    returned before closing the device.  The AbortIO function can kill
    any stragglers.

    After a close, the I/O request structure is free to be reused.
    Starting with V36 exec it is safe to CloseDevice() with an
    IORequest that is either cleared to zeros, or failed to
    open.

   INPUTS
    iORequest - pointer to an I/O request structure

   SEE ALSO
    OpenDevice()


exec.library/CloseLibrary

   NAME
    CloseLibrary -- conclude access to a library

   SYNOPSIS
    CloseLibrary(library)
             A1

    void CloseLibrary(struct Library *);

   FUNCTION
    This function informs the system that access to the given library
    has been concluded.  The user must not reference the library or any
    function in the library after this close.

    Starting with V36, it is safe to pass a NULL instead of
    a library pointer.

   INPUTS
    library - pointer to a library node

   NOTE
    Library writers must pass a SegList pointer or NULL back from their
    open point.  This value is used by the system, and not visible as
    a return code from CloseLibrary.

   SEE ALSO
    OpenLibrary()


exec.library/CopyMem

   NAME
    CopyMem - general purpose memory copy function

   SYNOPSIS
    CopyMem( source, dest, size )
         A0	 A1    D0

    void CopyMem(APTR,APTR,ULONG);

   FUNCTION
    CopyMem is a general purpose, fast memory copy function.  It can
    deal with arbitrary lengths, with its pointers on arbitrary
    alignments.  It attempts to optimize larger copies with more
    efficient copies, it uses byte copies for small moves, parts of
    larger copies, or the entire copy if the source and destination are
    misaligned with respect to each other.

    Arbitrary overlapping copies are not supported.

    The internal implementation of this function will change from
    system to system, and may be implemented via hardware DMA.

   INPUTS
    source - a pointer to the source data region
    dest  - a pointer to the destination data region
    size  - the size (in bytes) of the memory area.  Zero copies
        zero bytes

   SEE ALSO
    CopyMemQuick()


exec.library/CopyMemQuick

   NAME
    CopyMemQuick - optimized memory copy function

   SYNOPSIS
    CopyMemQuick( source, dest, size )
              A0      A1    D0

    void CopyMemQuick(ULONG *,ULONG *,ULONG);

   FUNCTION
    CopyMemQuick is a highly optimized memory copy function, with
    restrictions on the size and alignment of its arguments. Both the
    source and destination pointers must be longword aligned.  In
    addition, the size must be an integral number of longwords (e.g.
    the size must be evenly divisible by four).

    Arbitrary overlapping copies are not supported.

    The internal implementation of this function will change from system
    to system, and may be implemented via hardware DMA.

   INPUTS
    source - a pointer to the source data region, long aligned
    dest -  a pointer to the destination data region, long aligned
    size -  the size (in bytes) of the memory area.  Zero copies
        zero bytes.

   SEE ALSO
    CopyMem()


exec.library/CreateIORequest

   NAME
    CreateIORequest() -- create an IORequest structure  (V36)

   SYNOPSIS
    ioReq = CreateIORequest( ioReplyPort, size );
     D0                       A0           D0

    struct IORequest *CreateIORequest(struct MsgPort *, ULONG);

   FUNCTION
    Allocates memory for and initializes a new IO request block
    of a user-specified number of bytes.  The number of bytes
    must be at least as large as a "struct Message".

   INPUTS
    ioReplyPort - Pointer to a port for replies (an initialized message
        port, as created by CreateMsgPort() ).  If NULL, this
        function fails.
    size - the size of the IO request to be created.

   RESULT
    ioReq - A pointer to the new IORequest block, or NULL.

   SEE ALSO
    DeleteIORequest(), CreateMsgPort(), amiga.lib/CreateExtIO()


exec.library/CreatePool

    NAME
    CreatePool -- Generate a private memory pool header (V39)

    SYNOPSIS
    newPool=CreatePool(memFlags,puddleSize,threshSize)
    d0                 d0       d1         d2

    void *CreatePool(ULONG,ULONG,ULONG);

    FUNCTION
    Allocate and prepare a new memory pool header.	Each pool is a
    separate tracking system for memory of a specific type.  Any number
    of pools may exist in the system.

    Pools automatically expand and shrink based on demand.	Fixed sized
    "puddles" are allocated by the pool manager when more total memory
    is needed.  Many small allocations can fit in a single puddle.
    Allocations larger than the threshSize are allocation in their own
    puddles.

    At any time individual allocations may be freed.  Or, the entire
    pool may be removed in a single step.

    INPUTS
    memFlags - a memory flags specifier, as taken by AllocMem.
    puddleSize - the size of Puddles...
    threshSize - the largest allocation that goes into normal puddles
                 This *MUST* be less than or equal to puddleSize
                 (CreatePool() will fail if it is not)

    RESULT
    The address of a new pool header, or NULL for error.

    SEE ALSO
    DeletePool(), AllocPooled(), FreePooled(), exec/memory.i


exec.library/Deallocate

   NAME
    Deallocate -- deallocate a block of memory

   SYNOPSIS
    Deallocate(memHeader, memoryBlock, byteSize)
           A0	      A1	   D0

    void Deallocate(struct MemHeader *,APTR,ULONG);

   FUNCTION
    This function deallocates memory by returning it to the appropriate
    private free memory pool.  This function can be used to free an
    entire block allocated with the above function, or it can be used
    to free a sub-block of a previously allocated block.  Sub-blocks
    must be an even multiple of the memory chunk size (currently 8
    bytes).

    This function can even be used to add a new free region to an
    existing MemHeader, however the extent pointers in the MemHeader
    will no longer be valid.

    If memoryBlock is not on a block boundary (MEM_BLOCKSIZE) then it
    will be rounded down in a manner compatible with Allocate().  Note
    that this will work correctly with all the memory allocation
    functions, but may cause surprises if one is freeing only part of a
    region.  The size of the block will be rounded up, so the freed
    block will fill to an even memory block boundary.

   INPUTS
    memHeader - points to the memory header this block is part of.
    memoryBlock - address of memory block to free.
    byteSize - the size of the block in bytes. If NULL, nothing
           happens.

   SEE ALSO
    Allocate(), exec/memory.h


exec.library/Debug

   NAME
    Debug -- run the system debugger

   SYNOPSIS
    Debug(flags)
          D0

    void Debug(ULONG);

   FUNCTION
    This function calls the system debugger.  By default this debugger
    is "SAD" in >= V39 and "ROM-WACK" in < V39.  Other debuggers are
    encouraged to take over this entry point (via SetFunction()) so
    that when an application calls Debug(), the alternative debugger
    will get control.  Currently a zero is passed to allow future
    expansion.

   NOTE
    The Debug() call may be made when the system is in a questionable
    state; if you have a SetFunction() patch, make few assumptions, be
    prepared for Supervisor mode, and be aware of differences in the
    Motorola stack frames on the 68000,'10,'20,'30,'40 (etc.)

   BUGS
    In ROMWack, calling this function in SUPERVISOR state would have
    caused the a5 register to be trashed and the user stack pointer to
    be trashed.  As of V39 (and the instroduction of SAD) this is no
    longer the case.  However, calling this function in Supervisor
    state is a bit "tricky" at best...

    Note that due to a bug, pre-V40 SAD had the command
    codes wrong.  See the SAD autodoc for more details.

   SEE ALSO
    SetFunction()
    your favorite debugger's manual...
    the SAD autodocs...
    the ROM-WACK chapter of the ROM Kernel Manual... (pre-V39)


exec.library/DeletePool

    NAME
    DeletePool --  Drain an entire memory pool (V39)

    SYNOPSIS
    DeletePool(poolHeader)
               a0

    void DeletePool(void *);

    FUNCTION
    Frees all memory in all pudles of the specified pool header, then
    deletes the pool header.  Individual free calls are not needed.

    INPUTS
    poolHeader - as returned by CreatePool().

    SEE ALSO
    CreatePool(), AllocPooled(), FreePooled()


exec.library/Disable

    NAME
    Disable -- disable interrupt processing.

    SYNOPSIS
    Disable();

    void Disable(void);

    FUNCTION
    Prevents interrupts from being handled by the system, until a
    matching Enable() is executed.  Disable() implies Forbid().

    DO NOT USE THIS CALL WITHOUT GOOD JUSTIFICATION.  THIS CALL IS
    VERY DANGEROUS!

    RESULTS
    All interrupt processing is deferred until the task executing makes
    a call to Enable() or is placed in a wait state.  Normal task
    rescheduling does not occur while interrupts are disabled.  In order
    to restore normal interrupt processing, the programmer must execute
    exactly one call to Enable() for every call to Disable().

    IMPORTANT REMINDER:

    It is important to remember that there is a danger in using
    disabled sections.  Disabling interrupts for more than ~250
    microseconds will prevent vital system functions (especially serial
    I/0) from operating in a normal fashion.

    Think twice before using Disable(), then think once more.
    After all that, think again.  With enough thought, the need
    for a Disable() can often be eliminated.  For the user of many
    device drivers, a write to disable *only* the particular interrupt
    of interest can replace a Disable().  For example:
            MOVE.W	#INTF_PORTS,_intena
    Do not use a macro for Disable(), insist on the real thing.

    This call may be made from interrupts, it will have the effect
    of locking out all higher-level interrupts (lower-level interrupts
    are automatically disabled by the CPU).

        Note: In the event of a task entering a Wait() after disabling
              interrupts, the system "breaks" the disabled state and runs
              normally until the task which called Disable() is rescheduled.

    NOTE
    This call is guaranteed to preserve all registers.

    SEE ALSO
    Forbid(), Permit(), Enable()


exec.library/DoIO

   NAME
    DoIO -- perform an I/O command and wait for completion

   SYNOPSIS
    error = DoIO(iORequest)
    D0	     A1

    BYTE DoIO(struct IORequest *);

   FUNCTION
    This function requests a device driver to perform the I/O command
    specified in the I/O request.  This function will always wait until
    the I/O request is fully complete.

    DoIO() handles all the details, including Quick I/O, waiting for
    the request, and removing the reply message, etc..

   IMPLEMENTATION
    This function first tries to complete the IO via the "Quick I/O"
    mechanism.  The io_Flags field is always set to IOF_QUICK (0x01)
    before the internal device call.

    The LN_TYPE field is used internally to flag completion.  Active
    requests have type NT_MESSAGE.  Requests that have been replied
    have type NT_REPLYMSG.  It is illegal to start IO using a
    still active IORequest, or a request with type NT_REPLYMSG.

   INPUTS
    iORequest - pointer to an IORequest initialized by OpenDevice()

   RESULTS
    error - a sign-extended copy of the io_Error field of the
        IORequest.  Most device commands require that the error
        return be checked.

   SEE ALSO
    SendIO(), CheckIO(), WaitIO(), AbortIO(), amiga.lib/BeginIO


exec.library/Enable

   NAME
    Enable -- permit system interrupts to resume.

   SYNOPSIS
    Enable();

    void Enable(void);

   FUNCTION
    Allow system interrupts to again occur normally, after a matching
    Disable() has been executed.

   RESULTS
    Interrupt processing is restored to normal operation. The
    programmer must execute exactly one call to Enable() for every call
    to Disable().

    NOTE
    This call is guaranteed to preserve all registers.

   SEE ALSO
    Forbid(), Permit(), Disable()


exec.library/Enqueue

   NAME
    Enqueue -- insert or append node to a system queue

   SYNOPSIS
    Enqueue(list, node)
        A0    A1

    void Enqueue(struct List *, struct Node *);

   FUNCTION
    Insert or append a node into a system queue.  The insert is
    performed based on the node priority -- it will keep the list
    properly sorted.  New nodes will be inserted in front of the first
    node with a lower priority.   Hence a FIFO queue for nodes of equal
    priority

   WARNING
    This function does not arbitrate for access to the list.  The
    calling task must be the owner of the involved list.

   INPUTS
    list - a pointer to the system queue header
    node - the node to enqueue.  This must be a full featured node
           with type, priority and name fields.

   SEE ALSO
    AddHead(), AddTail(), Insert(), Remove(), RemHead(), RemTail()


exec.library/FindResident

   NAME
    FindResident - find a resident module by name

   SYNOPSIS
    resident = FindResident(name)
    D0			A1

    struct Resident *FindResident(STRPTR);

   FUNCTION
    Search the system resident tag list for a resident tag ("ROMTag") with
    the given name.  If found return a pointer to the resident tag
    structure, else return zero.

    Resident modules are used by the system to pull all its parts
    together at startup.  Resident tags are also found in disk based
    devices and libraries.

   INPUTS
    name - pointer to name string

   RESULT
    resident - pointer to the resident tag structure or
        zero if none found.

    SEE ALSO
    exec/resident.h, InitResident()


exec.library/Forbid

    NAME
    Forbid -- forbid task rescheduling.

    SYNOPSIS
    Forbid()

    void Forbid(void);

    FUNCTION
    Prevents other tasks from being scheduled to run by the dispatcher,
    until a matching Permit() is executed, or this task is scheduled to
    Wait().  Interrupts are NOT disabled.

    DO NOT USE THIS CALL WITHOUT GOOD JUSTIFICATION.  THIS CALL IS
    DANGEROUS!

    RESULTS
    The current task will not be rescheduled as long as it is ready to
    run.  In the event that the current task enters a wait state, other
    tasks may be scheduled.  Upon return from the wait state, the original
    task will continue to run without disturbing the Forbid().

    Calls to Forbid() nest. In order to restore normal task rescheduling,
    the programmer must execute exactly one call to Permit() for every
    call to Forbid().

    WARNING
    In the event of a task entering a Wait() after a Forbid(), the system
    "breaks" the forbidden state and runs normally until the task which
    called Forbid() is rescheduled.  If caution is not taken, this can
    cause subtle bugs, since any device or DOS call will (in effect)
    cause your task to wait.

    Forbid() is not useful or safe from within interrupt code
    (All interrupts are always higher priority than tasks, and
    interrupts are allowed to break a Forbid()).

    NOTE
    This call is guaranteed to preserve all registers.

    SEE ALSO
    Permit(), Disable(), ObtainSemaphore(), ObtainSemaphoreShared()


exec.library/FreeEntry

   NAME
    FreeEntry -- free many regions of memory

   SYNOPSIS
    FreeEntry(memList)
          A0
    void FreeEntry(struct MemList *);

   FUNCTION
    This function takes a memList structure (as returned by AllocEntry)
    and frees all the entries.

   INPUTS
    memList -- pointer to structure filled in with MemEntry
           structures

   SEE ALSO
    AllocEntry()


exec.library/FreeMem

   NAME
    FreeMem -- deallocate with knowledge

   SYNOPSIS
    FreeMem(memoryBlock, byteSize)
        A1	     D0

    void FreeMem(void *,ULONG);

   FUNCTION
    Free a region of memory, returning it to the system pool from which
    it came.  Freeing partial blocks back into the system pool is
    unwise.

   NOTE
    If a block of memory is freed twice, the system will Guru. The
    Alert is AN_FreeTwice ($01000009).   If you pass the wrong pointer,
    you will probably see AN_MemCorrupt $01000005.  Future versions may
    add more sanity checks to the memory lists.

   INPUTS
    memoryBlock - pointer to the memory block to free
    byteSize - the size of the desired block in bytes.  (The operating
        system will automatically round this number to a multiple of
        the system memory chunk size)

   SEE ALSO
    AllocMem()


exec.library/FreePooled

    NAME
    FreePooled -- Free pooled memory  (V39)

    SYNOPSIS
    FreePooled(poolHeader,memory,memSize)
           a0         a1     d0

    void FreePooled(void *,void *,ULONG);

    FUNCTION
    Deallocates memory allocated by AllocPooled().  The size of the
    allocation *MUST* match the size given to AllocPooled().
    The reason the pool functions do not track individual allocation
    sizes is because many of the uses of pools have small allocation
    sizes and the tracking of the size would be a large overhead.

    Only memory allocated by AllocPooled() may be freed with this
    function!

    Doing a DeletePool() on the pool will free all of the puddles
    and thus all of the allocations done with AllocPooled() in that
    pool.  (No need to FreePooled() each allocation)

    INPUTS
    memory - pointer to memory allocated by AllocPooled.
    poolHeader - a specific private pool header.

    NOTES
    The pool function do not protect an individual pool from
    multiple accesses.  The reason is that in most cases the pools
    will be used by a single task.  If your pool is going to
    be used by more than one task you must Semaphore protect
    the pool from having more than one task trying to allocate
    within the same pool at the same time.  Warning:  Forbid()
    protection *will not work* in the future.  *Do NOT* assume
    that we will be able to make it work in the future.  FreePooled()
    may well break a Forbid() and as such can only be protected
    by a semaphore.

    To track sizes yourself, the following code can be used:
    Assumes a6=ExecBase

    ;
    ; Function to do AllocVecPooled(Pool,memSize)
    ;
    AllocVecPooled:	addq.l	#4,d0		; Get space for tracking
            move.l	d0,-(sp)	; Save the size
            jsr	_LVOAllocPooled(a6)	; Call pool...
            move.l	(sp)+,d1	; Get size back...
            tst.l	d0		; Check for error
            beq.s	avp_fail	; If NULL, failed!
            move.l	d0,a0		; Get pointer...
            move.l	d1,(a0)+	; Store size
            move.l	a0,d0		; Get result
    avp_fail:	rts			; return

    ;
    ; Function to do FreeVecPooled(pool,memory)
    ;
    FreeVecPooled:	move.l	-(a1),d0	; Get size / ajust pointer
            jmp	_LVOFreePooled(a6)

    SEE ALSO
    AllocPooled(), CreatePool(), DeletePool()


exec.library/FreeVec

   NAME
    FreeVec -- return AllocVec() memory to the system  (V36)

   SYNOPSIS
    FreeVec(memoryBlock)
        A1

    void FreeVec(void *);

   FUNCTION
    Free an allocation made by the AllocVec() call.  The memory will
    be returned to the system pool from which it came.

   NOTE
    If a block of memory is freed twice, the system will Guru. The
    Alert is AN_FreeTwice ($01000009).   If you pass the wrong pointer,
    you will probably see AN_MemCorrupt $01000005.  Future versions may
    add more sanity checks to the memory lists.

   INPUTS
    memoryBlock - pointer to the memory block to free, or NULL.

   SEE ALSO
    AllocVec()


exec.library/GetMsg

   NAME
    GetMsg -- get next message from a message port

   SYNOPSIS
    message = GetMsg(port)
    D0		 A0

    struct Message *GetMsg(struct MsgPort *);

   FUNCTION
    This function receives a message from a given message port. It
    provides a fast, non-copying message receiving mechanism. The
    received message is removed from the message port.

    This function will not wait.  If a message is not present this
    function will return zero.  If a program must wait for a message,
    it can Wait() on the signal specified for the port or use the
    WaitPort() function.  There can only be one task waiting for any
    given port.

    Getting a message does not imply to the sender that the message is
    free to be reused by the sender.  When the receiver is finished
    with the message, it may ReplyMsg() it back to the sender.

    Getting a signal does NOT always imply a message is ready.  More
    than one message may arrive per signal, and signals may show up
    without messages.  Typically you must loop to GetMsg() until it
    returns zero, then Wait() or WaitPort().

   INPUT
    port - a pointer to the receiver message port

   RESULT
    message - a pointer to the first message available.  If
          there are no messages, return zero.
          Callers must be prepared for zero at any time.

   SEE ALSO
    PutMsg(), ReplyMsg(), WaitPort(), Wait(), exec/ports.h


exec.library/InitCode

   NAME
    InitCode - initialize resident code modules (internal function)

   SYNOPSIS
    InitCode(startClass, version)
         D0          D1

    void InitCode(ULONG,ULONG);

   FUNCTION
    (This function may be ignored by application programmers)

    Call InitResident() for all resident modules in the ResModules array
    with the given startClass and with versions equal or greater than
    that specified.  The segList parameter is passed as zero.

    Resident modules are used by the system to pull all its parts
    together at startup.  Modules are initialized in a prioritized order.

    Modules that do not have a startclass should be of priority -120.
    RTF_AFTERDOS modules should start at -100 (working down).

   INPUTS
    startClass - the class of code to be initialized:
        BITDEF RT,COLDSTART,0
        BITDEF RT,SINGLETASK,1	;ExecBase->ThisTask==0 (V36 only)
        BITDEF RT,AFTERDOS,2	;(V36 only)
    version - a major version number

    SEE ALSO
    ResidentTag (RT) structure definition (resident.h)


exec.library/InitResident

   NAME
    InitResident - initialize resident module

   SYNOPSIS
    object = InitResident(resident, segList)
    D0	               A1        D1

    APTR InitResident(struct Resident *,ULONG);

   FUNCTION
    Initialize a ROMTag.  ROMTags are used to link system modules
    together.  Each disk based device or library must contain a
    ROMTag structure in the first code hunk.

    Once the validity of the ROMTag is verified, the RT_INIT pointer
    is jumped to  with the following registers:
        D0 = 0
        A0 = segList
         A6 = ExecBase

   INPUTS
    resident - Pointer to a ROMTag
    segList  - SegList of the loaded object, if loaded from disk.
           Libraries & Devices will cache this value for later
           return at close or expunge time.  Pass NULL for ROM
           modules.

   RESULTS
    object	- Return value from the init code, usually the library
          or device base.  NULL for failure.

   AUTOINIT FEATURE
    An automatic method of library/device base and vector table
    initialization is also provided by InitResident().  The initial code
    hunk of the library or device should contain "MOVEQ #-1,d0; RTS;".
    Following that must be an initialized Resident structure with
    RTF_AUTOINIT set in rt_Flags, and an rt_Init pointer which points
    to four longwords.  These four longwords will be used in a call
    to MakeLibrary();

        - The size of your library/device base structure including initial
          Library or Device structure.

        - A pointer to a longword table of standard, then library
          specific function offsets, terminated with -1L.
          (short format offsets are also acceptable)

        - Pointer to data table in exec/InitStruct format for
          initialization of Library or Device structure.

        - Pointer to library initialization function, or NULL.
        Calling sequence:
            D0 = library base
            A0 = segList
            A6 = ExecBase
          This function must return in D0 the library/device base to be
          linked into the library/device list.  If the initialization
          function fails, the device memory must be manually deallocated,
          then NULL returned in D0.

   SEE ALSO
    exec/resident.i, FindResident()


exec.library/InitSemaphore

   NAME
    InitSemaphore -- initialize a signal semaphore

   SYNOPSIS
    InitSemaphore(signalSemaphore)
              A0

    void InitSemaphore(struct SignalSemaphore *);

   FUNCTION
    This function initializes a signal semaphore and prepares it for
    use.  It does not allocate anything, but does initialize list
    pointers and the semaphore counters.

    Semaphores are often used to protect critical data structures
    or hardware that can only be accessed by one task at a time.
    After initialization, the address of the SignalSemaphore may be
    made available to any number of tasks.  Typically a task will
    try to ObtainSemaphore(), passing this address in.  If no other
    task owns the semaphore, then the call will lock and return
    quickly.  If more tasks try to ObtainSemaphore(), they will
    be put to sleep.  When the owner of the semaphore releases
    it, the next waiter in turn will be woken up.

    Semaphores are often preferable to the old-style Forbid()/Permit()
    type arbitration.  With Forbid()/Permit() *all* other tasks are
    prevented from running.  With semaphores, only those tasks that
    need access to whatever the semaphore protects are subject
    to waiting.

   INPUT
    signalSemaphore -- a signal semaphore structure (with all fields
               set to zero before the call)

   SEE ALSO
    ObtainSemaphore(), ObtainSemaphoreShared(), AttemptSemaphore(),
    ReleaseSemaphore(), Procure(), Vacate(), exec/semaphores.h


exec.library/Insert

   NAME
    Insert -- insert a node into a list

   SYNOPSIS
    Insert(list, node, listNode)
           A0    A1    A2

    void Insert(struct List *, struct Node *, struct Node *);

   FUNCTION
    Insert a node into a doubly linked list AFTER a given node
    position.  Insertion at the head of a list is possible by passing a
    zero value for listNode, though the AddHead function is slightly
    faster for that special case.

   WARNING
    This function does not arbitrate for access to the list.  The
    calling task must be the owner of the involved list.

   INPUTS
    list - a pointer to the target list header
    node - the node to insert
    listNode - the node after which to insert

    SEE ALSO
    AddHead(), AddTail(), Enqueue(), RemHead(), Remove(), RemTail()


exec.library/MakeFunctions

   NAME
    MakeFunctions -- construct a function jump table

   SYNOPSIS
    tableSize = MakeFunctions(target, functionArray, funcDispBase)
    D0			  A0	  A1		 A2

    ULONG MakeFunctions(APTR,APTR,APTR);

   FUNCTION
    A low level function used by MakeLibrary to build jump tables of
    the type used by libraries, devices and resources.  It allows the
    table to be built anywhere in memory, and can be used both for
    initialization and replacement. This function also supports function
    pointer compression by expanding relative displacements into absolute
    pointers.

    The processor instruction cache is cleared after the table building.

   INPUT
    destination - the target address for the high memory end of the
        function jump table.  Typically this will be the library
        base pointer.

    functionArray - pointer to an array of function pointers or
        function displacements.  If funcDispBase is zero, the array
        is assumed to contain absolute pointers to functions. If
        funcDispBase is not zero, then the array is assumed to
        contain word displacements to functions.  In both cases,
        the array is terminated by a -1 (of the same size as the
        actual entry.

    funcDispBase - pointer to the base about which all function
        displacements are relative.  If zero, then the function
        array contains absolute pointers.

   RESULT
    tableSize - size of the new table in bytes (for LIB_NEGSIZE).

   SEE ALSO
    MakeLibrary()


exec.library/MakeLibrary

   NAME
    MakeLibrary -- construct a library

   SYNOPSIS
    library = MakeLibrary(vectors, structure, init, dSize, segList)
    D0		      A0       A1	  A2	D0     D1

    struct Library *MakeLibrary
                  (APTR,struct InitStruct *,APTR,ULONG,BPTR);

   FUNCTION
    This function is used for constructing a library vector and data
    area.  The same call is used to make devices.  Space for the library
    is allocated from the system's free memory pool.  The data portion of
    the library is initialized.  init may point to a library specific
    entry point.

   NOTE
    Starting with V36, the library base is longword adjusted.  The
    lib_PosSize and lib_NegSize fields of the library structure are
    adjusted to match.

   INPUTS
    vectors - pointer to an array of function pointers or function
        displacements.	If the first word of the array is -1, then
        the array contains relative word displacements (based off
        of vectors); otherwise, the array contains absolute
        function pointers. The vector list is terminated by a -1
        (of the same size as the pointers).

    structure - points to an "InitStruct" data region.  If NULL,
        then it will not be used.

    init -	If non-NULL, an entry point that will be called before adding
        the library to the system.  Registers are as follows:
            d0 = libAddr 	;Your Library Address
            a0 = segList	;Your AmigaDOS segment list
            a6 = ExecBase	;Address of exec.library
        The result of the init function must be the library address,
        or NULL for failure.   If NULL, the init point must manually
        deallocate the library base memory (based on the sizes stored
        in lib_PosSize and lib_NegSize).

    dSize - the size of the library data area, including the
        standard library node data.  This must be at leas
        sizeof(struct Library).

       segList - pointer to an AmigaDOS SegList (segment list).
         This is passed to a library's init code, and is used later
         for removing the library from memory.

   RESULT
    library - the reference address of the library.  This is the
          address used in references to the library, not the
          beginning of the memory area allocated.  If the library
          vector table require more system memory than is
          available, this function will return NULL.

   SEE ALSO
    InitStruct(), InitResident(), exec/initializers.i


exec.library/ObtainQuickVector

   NAME
    ObtainQuickVector -- obtain and install a Quick Interrupt vector (V39)

   SYNOPSIS
    vector=ObtainQuickVector(interruptCode)
    d0                       a0

    ULONG ObtainQuickVector(APTR);

   FUNCTION
    This function will install the code pointer into the quick interrupt
    vector it allocates and returns to you the interrupt vector that
    your Quick Interrupt system needs to use.

    This function may also return 0 if no vectors are available.  Your
    hardware should be able to then fall back to using the shared
    interrupt server chain should this happen.

    The interrupt code is a direct connect to the physical interrupt.
    This means that it is the responsibility of your code to do all
    of the context saving/restoring required by interrupt code.

    Also, due to the performance of the interrupt controller, you may
    need to also watch for "false" interrupts.  These are interrupts
    that come in just after a DISABLE.  The reason this happens is
    because the interrupt may have been posted before the DISABLE
    hardware access is completed.  For example:

    myInt:		move.l	d0,-(sp)	; Save d0...
            move.w	_intenar,d0	; Get interrupt enable state
            btst.l	#INTB_INTEN,d0	; Check if pending disable
            bne.s	realInt		; If not, do real one...
    exitInt:	move.l	(sp)+,d0	; Restore d0
            rte			; Return from int...
    ;
    realInt:	; Now do your int code...  d0 is already saved
            ; ALL other registers need to be saved if needed
            ; This includes a0/a1/d0/d1 as this is an interrupt
            ; and not a function call...
            ;
            bra.s	exitInt		; Exit interrupt...

    If your interrupt will not play with system (OS) structures and your
    own structures are safe to play with you do not need to check for
    the disable.  It is only needed for when the system is in disable but
    that "one last interrupt" still got through.

   NOTE
    This function was not implemented fully until V39.  Due to a mis-cue
    it is not safe to call in V37 EXEC.  (Sorry)

   INPUTS
    A pointer to your interrupt code.  This code is not an EXEC interrupt
    but is dirrectly connected to the hardware interrupt.  Thus, the
    interrupt code must not modify any registers and must return via
    an RTE.

   RESULTS
    The 8-bit vector number used for Zorro-III Quick Interrupts
    If it returns 0, no quick interrupt was allocatable.  The device
    should at this point switch to using the shared interrupt server
    method.

   SEE ALSO


exec.library/ObtainSemaphore

   NAME
    ObtainSemaphore -- gain exclusive access to a semaphore

   SYNOPSIS
    ObtainSemaphore(signalSemaphore)
            A0

    void ObtainSemaphore(struct SignalSemaphore *);

   FUNCTION
    Signal semaphores are used to gain exclusive access to an object.
    ObtainSemaphore is the call used to gain this access.  If another
    user currently has the semaphore locked the call will block until
    the object is available.

    If the current task already has locked the semaphore and attempts to
    lock it again the call will still succeed.  A "nesting count" is
    incremented each time the current owning task of the semaphore calls
    ObtainSemaphore().  This counter is decremented each time
    ReleaseSemaphore() is called.  When the counter returns to zero the
    semaphore is actually released, and the next waiting task is called.

    A queue of waiting tasks is maintained on the stacks of the waiting
    tasks.	Each will be called in turn as soon as the current task
    releases the semaphore.

    Signal Semaphores are different than Procure()/Vacate() semaphores.
    The former requires less CPU time, especially if the semaphore is
    not currently locked.  They require very little set up and user
    thought.  The latter flavor of semaphore make no assumptions about
    how they are used -- they are completely general.  Unfortunately
    they are not as efficient as signal semaphores, and require the
    locker to have done some setup before doing the call.

   INPUT
       signalSemaphore -- an initialized signal semaphore structure

   NOTE
    This function preserves all registers (see BUGS).

   BUGS
    Until V37, this function could destroy A0.

   SEE ALSO
    ObtainSemaphoreShared(), InitSemaphore(), ReleaseSemaphore(),
    AttemptSemaphore(), ObtainSemaphoreList(), Procure(), Vacate()


exec.library/ObtainSemaphoreList

   NAME
    ObtainSemaphoreList -- get a list of semaphores.

   SYNOPSIS
    ObtainSemaphoreList(list)
                A0

    void ObtainSemaphoreList(struct List *);

   FUNCTION
    Signal semaphores may be linked together into a list. This function
    takes a list of these semaphores and attempts to lock all of them at
    once. This call is preferable to applying ObtainSemaphore() to each
    element in the list because it attempts to lock all the elements
    simultaneously, and won't deadlock if someone is attempting to lock
    in some other order.

    This function assumes that only one task at a time will attempt to
    lock the entire list of semaphores.  In other words, there needs to
    be a higher level lock (perhaps another signal semaphore...) that is
    used before someone attempts to lock the semaphore list via
    ObtainSemaphoreList().

    Note that deadlocks may result if this call is used AND someone
    attempts to use ObtainSemaphore() to lock more than one semaphore on
    the list.  If you wish to lock more than semaphore (but not all of
    them) then you should obtain the higher level lock (see above)

   INPUT
       list -- a list of signal semaphores

   SEE ALSO
    ObtainSemaphoreShared(), InitSemaphore(), ReleaseSemaphore(),
    AttemptSemaphore(), ObtainSemaphoreShared(), Procure(), Vacate()


exec.library/ObtainSemaphoreShared

    NAME
    ObtainSemaphoreShared -- gain shared access to a semaphore (V36)

    SYNOPSIS
    ObtainSemaphoreShared(signalSemaphore)
                          a0

    void ObtainSemaphoreShared(struct SignalSemaphore *);

    FUNCTION
    A lock on a signal semaphore may either be exclusive, or shared.
    Exclusive locks are granted by the ObtainSemaphore() and
    AttemptSemaphore() functions.  Shared locks are granted by
    ObtainSemaphoreShared().  Calls may be nested.

    Any number of tasks may simultaneously hold a shared lock on a
    semaphore.  Only one task may hold an exclusive lock.  A typical
    application is a list that is often read, but only occasionally
    written to.

    Any exlusive locker will be held off until all shared lockers
    release the semaphore.  Likewise, if an exlusive lock is held,
    all potential shared lockers will block until the exclusive lock
    is released.  All shared lockers are restarted at the same time.

    EXAMPLE
        ObtainSemaphoreShared(ss);
        /* read data */
        ReleaseSemaohore(ss);

        ObtainSemaphore(ss);
        /* modify data */
        ReleaseSemaohore(ss);

    NOTES
    While this function was added for V36, the feature magically works
    with all older semaphore structures.

    A task owning a shared lock must not attempt to get an exclusive
    lock on the same semaphore.

    Starting in V39, if the caller already has an exclusive lock on the
    semaphore it will return with another nesting of the lock.  Pre-V39
    this would cause a deadlock.  For pre-V39 use, you can use the
    following workaround:

        /* Try to get the shared semaphore */
        if (!AttemptSemaphoreShared(ss))
        {
            /* Check if we can get the exclusive version */
            if (!AttemptSemaphore(ss))
            {
                /* Oh well, wait for the shared lock */
                ObtainSemaphoreShared(ss));
            }
        }
        :
        :
        ReleaseSemaphore(ss);

    INPUT
    signalSemaphore -- an initialized signal semaphore structure

    NOTE
    This call is guaranteed to preserve all registers, starting with
    V37 exec.

    RESULT

    SEE ALSO
    ObtainSemaphore(), InitSemaphore(), ReleaseSemaphore(),
    AttemptSemaphore(), ObtainSemaphoreList(), Procure(), Vacate()


exec.library/OldOpenLibrary

   NAME
    OldOpenLibrary -- obsolete OpenLibrary

   SYNOPSIS
    library = OldOpenLibrary(libName)
    D0			 A1

    struct Library *OldOpenLibrary(APTR);

   FUNCTION
    The 1.0 release of the Amiga system had an incorrect version of
    OpenLibrary that did not check the version number during the
    library open.  This obsolete function is provided so that object
    code compiled using a 1.0 system will still run.

    This exactly the same as "OpenLibrary(libName,0L);"

   INPUTS
    libName - the name of the library to open

   RESULTS
    library - a library pointer for a successful open, else zero

   SEE ALSO
    CloseLibrary()


exec.library/OpenDevice

   NAME
    OpenDevice -- gain access to a device

   SYNOPSIS
    error = OpenDevice(devName, unitNumber, iORequest, flags)
    D0		   A0	    D0		A1	   D1

    BYTE OpenDevice(STRPTR,ULONG,struct IORequest *,ULONG);

   FUNCTION
    This function opens the named device/unit and initializes the given
    I/O request block.  Specific documentation on opening procedures
    may come with certain devices.

    The device may exist in memory, or on disk; this is transparent to
    the OpenDevice caller.

    A full path name for the device name is legitimate.  For example
    "test:devs/fred.device".  This allows the use of custom devices
    without requiring the user to copy the device into the system's
    DEVS: directory.

   NOTES
    All calls to OpenDevice should have matching calls to CloseDevice!

    Devices on disk cannot be opened until after DOS has been
    started.

    As of V36 tasks can safely call OpenDevice, though DOS may open
    system requesters (e.g., asking the user to insert the Workbench
    disk if DEVS: is not online).  You must call this function from a
    DOS Process if you want to turn off DOS requesters.

   INPUTS
    devName - requested device name

    unitNumber - the unit number to open on that device.  The format of
        the unit number is device specific.  If the device does
        not have separate units, send a zero.

    iORequest - the I/O request block to be returned with
        appropriate fields initialized.

    flags - additional driver specific information.  This is sometimes
        used to request opening a device with exclusive access.

   RESULTS
    error - Returns a sign-extended copy of the io_Error field
        of the IORequest.  Zero if successful, else an error code
        is returned.

   BUGS
    AmigaDOS file names are not case sensitive, but Exec lists are.  If
    the library name is specified in a different case than it exists on
    disk, unexpected results may occur.

    Prior to V36, tasks could not make OpenDevice calls requiring disk
    access (since tasks are not allowed to make dos.library calls).
    Now OpenDevice is protected from tasks.

   SEE ALSO
    CloseDevice(), DoIO(), SendIO(), CheckIO(), AbortIO(), WaitIO()


exec.library/OpenLibrary

   NAME
    OpenLibrary -- gain access to a library

   SYNOPSIS
    library = OpenLibrary(libName, version)
    D0		      A1       D0

    struct Library *OpenLibrary(STRPTR, ULONG);

   FUNCTION
    This function returns a pointer to a library that was previously
    installed into the system.  If the requested library is exists, and
    if the library version is greater than or equal to the requested
    version, then the open will succeed.

    The library may exist in memory, or on disk; this is transparent to
    the OpenLibrary caller.  Only Processes are allowed to call
    OpenLibrary (since OpenLibrary may in turn call dos.library).

    A full path name for the library name is legitimate.  For example
    "wp:libs/wp.library".  This allows the use of custom libraries
    without requiring the user to copy the library into the system's
    LIBS: directory.

   NOTES
    All calls to OpenLibrary should have matching calls to CloseLibrary!

    Libraries on disk cannot be opened until after DOS has been
    started.

    As of V36 tasks can safely call OpenLibrary, though DOS may open
    system requesters (e.g., asking the user to insert the Workbench
    disk if LIBS: is not online).  You must call this function from a
    DOS Process if you want to turn off DOS requesters.

   INPUTS
    libName - the name of the library to open

    version - the version of the library required.

   RESULTS
    library - a library pointer for a successful open, else zero

   BUGS
    AmigaDOS file names are not case sensitive, but Exec lists are. If
    the library name is specified in a different case than it exists on
    disk, unexpected results may occur.

    Prior to V36, tasks could not make OpenLibrary calls requiring disk
    access (since tasks are not allowed to make dos.library calls).
    Now OpenLibrary is protected from tasks.

    The version number of the resident tag in disk based library must
    match the version number of the library, or V36 may fail to load it.

   SEE ALSO
    CloseLibrary()


exec.library/Permit

    NAME
    Permit -- permit task rescheduling.

    SYNOPSIS
    Permit()

    void Permit(void);

    FUNCTION
    Allow other tasks to be scheduled to run by the dispatcher, after a
    matching Forbid() has been executed.

    RESULTS
    Other tasks will be rescheduled as they are ready to run. In order
    to restore normal task rescheduling, the programmer must execute
    exactly one call to Permit() for every call to Forbid().

    NOTE
    This call is guaranteed to preserve all registers.

    SEE ALSO
    Forbid(), Disable(), Enable()


exec.library/Procure

   NAME
    Procure -- bid for a semaphore                                   (V39)

   SYNOPSIS
    Procure(semaphore, bidMessage)
        A0	    A1

    VOID Procure(struct SignalSemaphore *, struct SemaphoreMessage *);

   FUNCTION
    This function is used to obtain a semaphore in an async manner.
    Like ObtainSemaphore(), it will obtain a SignalSemaphore for you
    but unlike ObtainSemaphore(), you will not block until you get
    the semaphore.  Procure() will just post a request for the semaphore
    and will return.  When the semaphore is available (which could
    be at any time) the bidMessage will ReplyMsg() and you will own
    the semaphore.  This lets you wait on multiple semaphores at once
    and to continue processing while waiting for the semaphore.

    NOTE:  Pre-V39, Procure() and Vacate() did not work correctly.
    They also did not operate on SignalSemaphore semaphores.
    Old (and broken) MessageSemaphore use as of V39 will no longer work.

   INPUT
    semaphore - The SignalSemaphore that you wish to Procure()
    bidMessage- The SemaphoreMessage that you wish replied when
        you obtain access to the semaphore.  The message's
        ssm_Semaphore field will point at the semaphore that
        was obtained.  If the ssm_Semaphore field is NULL,
        the Procure() was aborted via Vacate().
        The mn_ReplyPort field of the message must point to
        a valid message port.
        To obtain a shared semaphore, the ln_Name field
        must be set to 1.  For an exclusive lock, the ln_Name
        field must be 0.  No other values are valid.

   BUGS
    Before V39, Procure() and Vacate() used a different semaphore
    system that was very broken.  This new system is only available
    as of V39 even though the LVOs are the same.

   SEE ALSO
    ObtainSemaphoreShared(), InitSemaphore(), ReleaseSemaphore(),
    AttemptSemaphore(), ObtainSemaphoreList(), Vacate(), ObtainSemaphore()


exec.library/PutMsg

   NAME
    PutMsg -- put a message to a message port

   SYNOPSIS
    PutMsg(port, message)
           A0    A1

    void PutMsg(struct MsgPort *, struct Message *);

   FUNCTION
    This function attaches a message to the end of a given message port.
    It provides a fast, non-copying message sending mechanism.

    Messages can be attached to only one port at a time.  The message
    body can be of any size or form.  Because messages are not copied,
    cooperating tasks share the same message memory.  The sender task
    must not recycle the message until it has been replied by the
    receiver.  Of course this depends on the message handling conventions
    setup by the involved tasks.  If the ReplyPort field is non-zero,
    when the message is replied by the receiver, it will be sent back to
    that port.

    Any one of the following actions can be set to occur when a message
    is put:

        1. no special action
        2. signal a given task (specified by MP_SIGTASK)
        3. cause a software interrupt (specified by MP_SIGTASK)

    The action is selected depending on the value found in the MP_FLAGS
    of the destination port.

   IMPLEMENTATION
    1.  Sets the LN_TYPE field to "NT_MESSAGE".
    2.  Attaches the message to the destination port.
    3.  Performs the specified arrival action at the destination.

   INPUT
    port - pointer to a message port
    message - pointer to a message

   SEE ALSO
    GetMsg(), ReplyMsg(), exec/ports.h


exec.library/RemDevice

   NAME
    RemDevice -- remove a device from the system

   SYNOPSIS
    RemDevice(device)
              A1

    void RemDevice(struct Device *);

   FUNCTION
    This function calls the device's EXPUNGE vector, which requests
    that a device delete itself.  The device may refuse to do this if
    it is busy or currently open. This is not typically called by user
    code.

    There are certain, limited circumstances where it may be
    appropriate to attempt to specifically flush a certain device.
    Example:

     /* Attempts to flush the named device out of memory. */
     #include <exec/types.h>
     #include <exec/execbase.h>

     void FlushDevice(name)
     STRPTR name;
     {
     struct Device *result;

        Forbid();
        if(result=(struct Device *)FindName(&SysBase->DeviceList,name))
        RemDevice(result);
        Permit();
     }

   INPUTS
    device - pointer to a device node

   SEE ALSO
    AddLibrary()


exec.library/RemHead

   NAME
    RemHead -- remove the head node from a list

   SYNOPSIS
    node = RemHead(list)
    D0	       A0

    struct Node *RemHead(struct List *);

   FUNCTION
    Get a pointer to the head node and remove it from the list.
    Assembly programmers may prefer to use the REMHEAD macro from
    "exec/lists.i".

   WARNING
    This function does not arbitrate for access to the list.  The
    calling task must be the owner of the involved list.

   INPUTS
    list - a pointer to the target list header

   RESULT
    node - the node removed or zero when empty list

   SEE ALSO
    AddHead(), AddTail(), Enqueue(), Insert(), Remove(), RemTail()


exec.library/RemIntServer

   NAME
    RemIntServer -- remove an interrupt server from a server chain

   SYNOPSIS
    RemIntServer(intNum, interrupt)
             D0      A1

    void RemIntServer(ULONG,struct Interrupt *);

   FUNCTION
    This function removes an interrupt server node from the given
    server chain.

    If this server was the last one on this chain, interrupts for this
    chain are disabled.

   INPUTS
    intNum - the Paula interrupt bit (0..14)
    interrupt - pointer to an interrupt server node

   BUGS
    Before V36 Kickstart, the feature that disables the interrupt
    would not function.  For most server chains this does not
    cause a problem.

   SEE ALSO
    AddIntServer(), hardware/intbits.h


exec.library/RemMemHandler

   NAME
    RemMemHandler - Remove low memory handler from exec              (V39)

   SYNOPSIS
    RemMemHandler(memHandler)
                  A1

    VOID RemMemHandler(struct Interrupt *);

   FUNCTION
    This function removes the low memory handler from the system.
    This function can be called from within a handler.  If removing
    oneself, it is important that the handler returns MEM_ALL_DONE.

   NOTE
    When removing a handler, the handler may be called until this
    function returns.  Thus, the handler must still be valid until
    then.

   INPUTS
    memHandler - Pointer to a handler added with AddMemHandler()

   SEE ALSO
    AddMemHandler(), exec/interrupts.i


exec.library/Remove

   NAME
    Remove -- remove a node from a list

   SYNOPSIS
    Remove(node)
           A1

    void Remove(struct Node *);

   FUNCTION
    Unlink a node from whatever list it is in.  Nodes that are not part
    of a list must not be passed to this function!  Assembly programmers
    may prefer to use the REMOVE macro from "exec/lists.i".

   WARNING
    This function does not arbitrate for access to the list.  The
    calling task must be the owner of the involved list.

   INPUTS
    node - the node to remove

   SEE ALSO
    AddHead(), AddTail(), Enqueue(), Insert(), RemHead(), RemTail()


exec.library/RemPort

   NAME
    RemPort -- remove a message port from the system

   SYNOPSIS
    RemPort(port)
        A1

    void RemPort(struct MsgPort *);

   FUNCTION
    This function removes a message port structure from the system's
    message port list.  Subsequent attempts to rendezvous by name with
    this port will fail.

   INPUTS
    port - pointer to a message port

   SEE ALSO
    AddPort(), FindPort()


exec.library/RemResource

   NAME
    RemResource -- remove a resource from the system

   SYNOPSIS
    RemResource(resource)
           A1

    void RemResource(APTR);

   FUNCTION
    This function removes an existing resource from the system resource
    list.  There must be no outstanding users of the resource.

   INPUTS
    resource - pointer to a resource node

   SEE ALSO
    AddResource()


exec.library/RemSemaphore

   NAME
    RemSemaphore -- remove a signal semaphore from the system

   SYNOPSIS
    RemSemaphore(signalSemaphore)
             A1

    void RemSemaphore(struct SignalSemaphore *);

   FUNCTION
    This function removes a signal semaphore structure from the
    system's signal semaphore list.  Subsequent attempts to
    rendezvous by name with this semaphore will fail.

   INPUTS
       signalSemaphore -- an initialized signal semaphore structure

   SEE ALSO
    AddSemaphore(), FindSemaphore()


exec.library/RemTail

   NAME
    RemTail -- remove the tail node from a list

   SYNOPSIS
    node = RemTail(list)
    D0	       A0

    struct Node *RemTail(struct List *);

   FUNCTION
    Remove the last node from a list, and return a pointer to it. If
    the list is empty, return zero. Assembly programmers may prefer to
    use the REMTAIL macro from "exec/lists.i".

   WARNING
    This function does not arbitrate for access to the list.  The
    calling task must be the owner of the involved list.

   INPUTS
    list - a pointer to the target list header

   RESULT
    node - the node removed or zero when empty list

   SEE ALSO
    AddHead(), AddTail(), Enqueue(), Insert(), Remove(), RemHead()


exec.library/RemTask

   NAME
    RemTask -- remove a task from the system

   SYNOPSIS
    RemTask(task)
        A1

    void RemTask(struct Task *);

   FUNCTION
    This function removes a task from the system.  Deallocation of
    resources should have been performed prior to calling this
    function.  Removing some other task is very dangerous.	Generally
    is is best to arrange for tasks to call RemTask(0L) on themselves.

    RemTask will automagically free any memory lists attached to the
    task's TC_MEMENTRY list.

   INPUTS
    task - pointer to the task node representing the task to be
           removed.  A zero value indicates self removal, and will
           cause the next ready task to begin execution.

   BUGS
    Before V36 if RemTask() was called on a task other than the current
    task, and that task was created with amiga.lib/CreateTask, there was
    a slight chance of a crash.  The problem can be hidden by bracketing
    RemTask() with Forbid()/Permit().

   SEE ALSO
    AddTask(), AllocEntry(), amiga.lib/DeleteTask()


exec.library/ReplyMsg

   NAME
    ReplyMsg -- put a message to its reply port

   SYNOPSIS
    ReplyMsg(message)
         A1

    void ReplyMsg(struct Message *);

   FUNCTION
    This function sends a message to its reply port.  This is usually
    done when the receiver of a message has finished and wants to
    return it to the sender (so that it can be re-used or deallocated,
    whatever).

    This call may be made from interrupts.

   INPUT
    message - a pointer to the message

   IMPLEMENTATION
    1> Places "NT_REPLYMSG" into LN_TYPE.
    2> Puts the message to the port specified by MN_REPLYPORT
       If there is no replyport, sets LN_TYPE to "NT_FREEMSG" (use this
       feature only with extreme care).

   SEE ALSO
    GetMsg(), PutMsg(), exec/ports.h


exec.library/SendIO

   NAME
    SendIO -- initiate an I/O command

   SYNOPSIS
    SendIO(iORequest)
           A1

    void SendIO(struct IORequest *);

   FUNCTION
    This function requests the device driver start processing the given
    I/O request.  The device will return control without waiting for
    the I/O to complete.

    The io_Flags field of the IORequest will be set to zero before the
    request is sent.  See BeginIO() for more details.

   INPUTS
    iORequest - pointer to an I/O request, or a device specific
            extended IORequest.

   SEE ALSO
    DoIO(), CheckIO(), WaitIO(), AbortIO()


exec.library/SetExcept

   NAME
    SetExcept -- define certain signals to cause exceptions

   SYNOPSIS
    oldSignals = SetExcept(newSignals, signalMask)
    D0		       D0	   D1

    ULONG SetExcept(ULONG,ULONG);

   FUNCTION
    This function defines which of the task's signals will cause a
    private task exception.  When any of the signals occurs the task's
    exception handler will be dispatched.  If the signal occurred prior
    to calling SetExcept, the exception will happen immediately.

    The user function pointed to by the task's tc_ExceptCode gets
    called as:

        newExcptSet = <exceptCode>(signals, exceptData),SysBase
        D0			       D0	A1	    A6

        signals - The set of signals that caused this exception.  These
        Signals have been disabled from the current set of signals
        that can cause an exception.

        exceptData - A copy of the task structure tc_ExceptData field.

        newExcptSet - The set of signals in NewExceptSet will be re-
        enabled for exception generation.  Usually this will be the
        same as the Signals that caused the exception.

   INPUTS
    newSignals - the new values for the signals specified in
        signalMask.
    signalMask - the set of signals to be effected

   RESULTS
    oldSignals - the prior exception signals

   EXAMPLE
    Get the current state of all exception signals:
        SetExcept(0,0)
    Change a few exception signals:
        SetExcept($1374,$1074)

   SEE ALSO
    Signal(), SetSignal()


exec.library/SetSignal

   NAME
    SetSignal -- define the state of this task's signals

   SYNOPSIS
    oldSignals = SetSignal(newSignals, signalMask)
    D0		       D0	   D1

    ULONG SetSignal(ULONG,ULONG);

   FUNCTION
    This function can query or modify the state of the current task's
    received signal mask.  Setting the state of signals is considered
    dangerous.  Reading the state of signals is safe.

   INPUTS
    newSignals - the new values for the signals specified in
             signalSet.
    signalMask - the set of signals to be affected.

   RESULTS
    oldSignals - the prior values for all signals

   EXAMPLES
    Get the current state of all signals:
        SetSignal(0L,0L);
    Clear the CTRL-C signal:
        SetSignal(0L,SIGBREAKF_CTRL_C);

    Check if the CTRL-C signal was pressed:

        #include <libraries/dos.h>

        /* Check & clear CTRL_C signal */
        if(SetSignal(0L,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
        {
        printf("CTRL-C pressed!n");
        }

   SEE ALSO
    Signal(), Wait()


exec.library/Signal

   NAME
    Signal -- signal a task

   SYNOPSIS
    Signal(task, signals)
           A1    D0

    void Signal(struct Task *,ULONG);

   FUNCTION
    This function signals a task with the given signals.  If the task
    is currently waiting for one or more of these signals, it will be
    made ready and a reschedule will occur. If the task is not waiting
    for any of these signals, the signals will be posted to the task
    for possible later use. A signal may be sent to a task regardless
    of whether it is running, ready, or waiting.

    This function is considered "low level".  Its main purpose is to
    support multiple higher level functions like PutMsg.

    This function is safe to call from interrupts.

   INPUT
    task - the task to be signalled
    signals - the signals to be sent

   SEE ALSO
    Wait(), SetSignal()


exec.library/StackSwap

   NAME
    StackSwap - EXEC supported method of replacing task's stack      (V37)

   SYNOPSIS
    StackSwap(newStack)
              A0

    VOID StackSwap(struct StackSwapStruct *);

   FUNCTION
    This function will, in an EXEC supported manner, swap the
    stack of your task with the given values in StackSwap.
    The StackSwapStruct structure will then contain the values
    of the old stack such that the old stack can be restored.
    This function is new in V37.

   NOTE
    If you do a stack swap, only the new stack is set up.
    This function does not copy the stack or do anything else
    other than set up the new stack for the task.  It is
    generally required that you restore your stack before
    exiting.

   INPUTS
    newStack - A structure that contains the values for the
        new upper and lower stack bounds and the new stack
        pointer.  This structure will have its values
        replaced by those in you task such that you can
        restore the stack later.

   RESULTS
    newStack - The structure will now contain the old stack.
        This means that StackSwap(foo); StackSwap(foo);
        will effectively do nothing.

   SEE ALSO
    AddTask(), RemTask(), exec/tasks.h


exec.library/SumKickData

   NAME
    SumKickData -- compute the checksum for the Kickstart delta list

   SYNOPSIS
    checksum = SumKickData()
    D0

    ULONG SumKickData(void);

   FUNCTION
    The Amiga system has some ROM (or Kickstart) resident code that
    provides the basic functions for the machine.  This code is
    unchangeable by the system software.  This function is part of a
    support system to modify parts of the ROM.

    The ROM code is linked together at run time via ROMTags (also known
    as Resident structures, defined in exec/resident.h).  These tags tell
    Exec's low level boot code what subsystems exist in which regions of
    memory.  The current list of ROMTags is contained in the ResModules
    field of ExecBase.  By default this list contains any ROMTags found
    in the address ranges $F80000-$FFFFFF and $F00000-$F7FFFF.

    There is also a facility to selectively add or replace modules to the
    ROMTag list.  These modules can exist in RAM, and the memory they
    occupy will be deleted from the memory free list during the boot
    process.  SumKickData() plays an important role in this run-time
    modification of the ROMTag array.

    Three variables in ExecBase are used in changing the ROMTag array:
    KickMemPtr, KickTagPtr, and KickCheckSum. KickMemPtr points to a
    linked list of MemEntry structures. The memory that these MemEntry
    structures reference will be allocated (via AllocAbs) at boot time.
    The MemEntry structure itself must also be in the list.

    KickTagPtr points to a long-word array of the same format as the
    ResModules array.  The array has a series of pointers to ROMTag
    structures.  The array is either NULL terminated, or will have an
    entry with the most significant bit (bit 31) set.  The most
    significant bit being set says that this is a link to another
    long-word array of ROMTag entries.  This new array's address can be
    found by clearing bit 31.

    KickCheckSum has the result of SumKickData().  It is the checksum of
    both the KickMemPtr structure and the KickTagPtr arrays.  If the
    checksum does not compute correctly then both KickMemPtr and
    KickTagPtr will be ignored.

    If all the memory referenced by KickMemPtr can't be allocated then
    KickTagPtr will be ignored.

    There is one more important caveat about adding ROMTags. All this
    ROMTag magic is run very early on in the system -- before expansion
    memory is added to the system. Therefore any memory in this
    additional ROMTag area must be addressable at this time. This means
    that your ROMTag code, MemEntry structures, and resident arrays
    cannot be in expansion memory.  There are two regions of memory that
    are acceptable:  one is chip memory, and the other is "Ranger" memory
    (memory in the range between $C00000-$D80000).

    Remember that changing an existing ROMTag entry falls into the
    "heavy magic" category -- be very careful when doing it.  The odd are
    that you will blow yourself out of the water.

   NOTE
    SumKickData was introduced in the 1.2 release

   RESULT
    Value to be stuffed into ExecBase->KickCheckSum.

   WARNING
    After writing to KickCheckSum, you should push the data cache.
    This prevents potential problems with large copyback style caches.
    A call to CacheClearU will do fine.

   SEE ALSO
    InitResident(), FindResident()


exec.library/SumLibrary

   NAME
    SumLibrary -- compute and check the checksum on a library

   SYNOPSIS
    SumLibrary(library)
           A1

    void SumLibrary(struct Library *);

   FUNCTION
    SumLibrary computes a new checksum on a library.  It can also be
    used to check an old checksum.	If an old checksum does not match,
    and the library has not been marked as changed, then the system
    will call Alert().

    This call could also be periodically made by some future
    system-checking task.

   INPUTS
    library - a pointer to the library to be changed

   NOTE
    An alert will occur if the checksum fails.

   SEE ALSO
    SetFunction()


exec.library/SuperState

   NAME
    SuperState -- enter supervisor state with user stack

   SYNOPSIS
    oldSysStack = SuperState()
    D0

    APTR SuperState(void);

   FUNCTION
    Enter supervisor mode while running on the user's stack. The user
    still has access to user stack variables.  Be careful though, the
    user stack must be large enough to accommodate space for all
    interrupt data -- this includes all possible nesting of interrupts.
    This function does nothing when called from supervisor state.

   RESULTS
    oldSysStack - system stack pointer; save this.	It will come in
              handy when you return to user state.  If the system
              is already in supervisor mode, oldSysStack is zero.

   SEE ALSO
    UserState(), Supervisor()


exec.library/Supervisor

   NAME
    Supervisor -- trap to a short supervisor mode function

   SYNOPSIS
    result = Supervisor(userFunc)
    Rx                   A5

    ULONG Supervisor(void *);

   FUNCTION
    Allow a normal user-mode program to execute a short assembly language
    function in the supervisor mode of the processor.  Supervisor() does
    not modify or save registers; the user function has full access to the
    register set.   All rules that apply to interrupt code must be
    followed.  In addition, no system calls are permitted.  The function
    must end with an RTE instruction.

   EXAMPLE
        ;Obtain the Exception Vector base.  68010 or greater only!
        MOVECtrap:	movec.l	VBR,d0	;$4e7a,$0801
                rte

   INPUTS
    userFunc - A pointer to a short assembly language function ending
           in RTE.  The function has full access to the register set.

   RESULTS
    result   - Whatever values the userFunc left in the registers.

   SEE ALSO
    SuperState(),UserState()


exec.library/UserState

   NAME
    UserState -- return to user state with user stack

   SYNOPSIS
    UserState(sysStack)
          D0

    void UserState(APTR);

   FUNCTION
    Return to user state with user stack, from supervisor state with
    user stack.  This function is normally used in conjunction with the
    SuperState function above.

    This function must not be called from the user state.

   INPUT
    sysStack - supervisor stack pointer

   BUGS
    This function is broken in V33/34 Kickstart.  Fixed in V1.31 setpatch.

   SEE ALSO
    SuperState(), Supervisor()


exec.library/Vacate

   NAME
    Vacate -- release a bitMessage from Procure()                    (V39)

   SYNOPSIS
    Vacate(semaphore, bidMessage)
           A0         A1

    void Vacate(struct SignalSemaphore *,struct SemaphoreMessage *);

   FUNCTION
    This function can be used to release a semaphore obtained via
    Procure().  However, the main purpose for this call is to be
    able to remove a bid for a semaphore that has not yet responded.
    This is required when a Procure() was issued and the program
    no longer needs to get the semaphore and wishes to cancel the
    Procure() request.  The canceled request will be replied with
    the ssm_Semaphore field set to NULL.  If you own the semaphore,
    the message was already replied and only the ssm_Semaphore field
    will be cleared.

    NOTE:  Pre-V39, Procure() and Vacate() did not work correctly.
    They also did not operate on SignalSemaphore semaphores.
    Old (and broken) MessageSemaphore use as of V39 will no longer work.

   INPUT
    semaphore - The SignalSemaphore that you wish to Vacate()
    bidMessage- The SemaphoreMessage that you wish to abort.
        The message's ssm_Semaphore field will be cleared.
        The message will be replied if it is still on the waiting
        list.  If it is not on the waiting list, it is assumed
        that the semaphore is owned and it will be released.

   BUGS
    Before V39, Procure() and Vacate() used a different semaphore
    system that was very broken.  This new system is only available
    as of V39 even though the LVOs are the same.

   SEE ALSO
    ObtainSemaphoreShared(), InitSemaphore(), ReleaseSemaphore(),
    AttemptSemaphore(), ObtainSemaphoreList(), Procure(), ObtainSemaphore()


exec.library/WaitIO

   NAME
    WaitIO -- wait for completion of an I/O request

   SYNOPSIS
    error = WaitIO(iORequest)
    D0	       A1

    BYTE WaitIO(struct IORequest *);

   FUNCTION
    This function waits for the specified I/O request to complete, then
    removes it from the replyport.	If the I/O has already completed,
    this function will return immediately.

    This function should be used with care, as it does not return until
    the I/O request completes; if the I/O never completes, this
    function will never return, and your task will hang.  If this
    situation is a possibility, it is safer to use the Wait() function.
    Wait() will return return when any of a specified set of signal is
    received.  This is how I/O timeouts can be properly handled.

   WARNING
    If this IORequest was "Quick" or otherwise finished BEFORE this
    call, this function drops though immediately, with no call to
    Wait().  A side effect is that the signal bit related the port may
    remain set.  Expect this.

    When removing a known complete IORequest from a port, WaitIO() is the
    preferred method.  A simple Remove() would require a Disable/Enable
    pair!

   INPUTS
    iORequest - pointer to an I/O request block

   RESULTS
    error - zero if successful, else an error is returned
        (a sign extended copy of io_Error).

   SEE ALSO
    DoIO(), SendIO(), CheckIO(), AbortIO()


exec.library/WaitPort

   NAME
    WaitPort -- wait for a given port to be non-empty

   SYNOPSIS
    message = WaitPort(port)
    D0		   A0

    struct Message *WaitPort(struct MsgPort *);

   FUNCTION
    This function waits for the given port to become non-empty.  If
    necessary, the Wait() function will be called to wait for the port
    signal.  If a message is already present at the port, this function
    will return immediately.  The return value is always a pointer to
    the first message queued (but it is not removed from the queue).

   CAUTION
    More than one message may be at the port when this returns.  It is
    proper to call the GetMsg() function in a loop until all messages
    have been handled, then wait for more to arrive.

    To wait for more than one port, combine the signal bits from each
    port into one call to the Wait() function, then use a GetMsg() loop
    to collect any and all messages.  It is possible to get a signal
    for a port WITHOUT a message showing up.  Plan for this.

   INPUT
    port - a pointer to the message port

   RETURN
    message - a pointer to the first available message

   SEE ALSO
    GetMsg()


SAD/--Overview--

    Simple Amiga Debugging Kernel, known as "SAD"
    It is in EXEC starting in V39

        -- General description --

 The Simple Amiga Debugging Kernel (SAD) is a set of very simple control
 routines stored in the Kickstart ROM that would let debuggers control the
 Amiga's development enviroment from the outside.  These tools would make
 it possible to do remote machine development/debugging via just the
 on-board serial port.

 This set of control routines is very simple and yet completely flexible,
 thus making it possible to control the whole machine.

        -- Technical Issues --

 SAD will make use of the motherboard serial port that exists in all
 Amiga systems.  The connection via the serial port lets the system be
 able to execute SAD without needing any of the system software up and
 running. (SAD will play with the serial port directly)

 With some minor changes to the Amiga hardware, an NMI-like line could
 be hooked up to a pin on the serial port.  This would let external
 control of the machine and would let the external controller stop the
 machine no matter what state it is in.  (NMI is that way)

 In order to function correctly, SAD requires the some of the EXEC
 CPU control functions work and that ExecBase be valid.  Beyond that,
 SAD does not require the OS to be running.

        -- Command Overview --

 The basic commands needed to operate SAD are as follows:

 Read and Write memory as byte, word, and longword.
 Get the register frame address (contains all registers)
 JSR to Address
 Return to system operation  (return from interrupt)

 These basic routines will let the system do whatever is needed.
 Since the JSR to address and memory read/write routines can be used
 to download small sections of code that could be used to do more
 complex things, this basic command set is thus flexible enough
 to even replace itself.

 Caches will automatically be flushed as needed after each write.
 (A call to CacheClearU() will be made after the write and before
 the command done sequence)

        -- Technical Command Descriptions --

 Since the communications with SAD is via a serial port, data formats
 have been defined for minimum overhead while still giving reasonable data
 reliability.  SAD will use the serial port at default 9600 baud but the
 external tools can change the serial port's data rate if it wishes.  It
 would need to make sure that it will be able to reconnect.  SAD sets
 the baud rate to 9600 each time it is entered.  However, while within
 SAD, a simple command to write a WORD to the SERPER register would
 change the baud rate.  This will remain in effect until you exit and
 re-enter SAD or until you change the register again.  (This can be usefull
 if you need to transfer a large amount of data)

 All commands have a basic format that they will follow.  All commands have
 both an ACK and a completion message.

 Basic command format is:

 SENDER:	$AF <command byte> [<data bytes as needed by command>]

 Receive:
 Command ACK:  $00 <command byte>

 Command Done: $1F <command byte> [<data if needed>]

 Waiting: $53 $41 $44 $BF

 Waiting when called from Debug():	$53 $41 $44 $3F

 Waiting when in dead-end crash:	$53 $41 $44 $21

 The data sequence will be that SAD will emit a $BF and then wait for a
 command. If no command is received within <2> seconds, it will emit $BF
 again and loop back.  (This is the "heart beat" of SAD)  When called from
 Debug() and not the NMI hook, SAD will use $3F as the "heart beat"

 If SAD does not get a responce after <10> heartbeats, it will return to
 the system.  (Execute an RTS or RTE as needed)  This is to prevent a full
 hang.  The debugger at the other end can keep SAD happy by sending a
 NO-OP command.

 All I/O in SAD times out.  During the transmition of a command, if
 more than 2 seconds pass between bytes of data SAD will time out
 and return to the prompt.  This is mainly to help make sure that
 SAD can never get into an i-loop situation.

        -- Data Structure Issues --

 While executing in SAD, you may have full access to machine from the CPU
 standpoint.  However, this could also be a problem.  It is important to
 understand that when entered via NMI that many system lists may be in
 unstable state.  (NMI can happen in the middle of the AllocMem routine
 or task switch, etc)

 Also, since you are doing debugging, it is up to you to determin what
 operations can be done and what can not be done.  A good example is
 that if you want to write a WORD or LONG that the address will need to
 be even on 68000 processors.  Also, if you read or write memory that does
 not exist, you may get a bus error.  Following system structures may
 require that you check the pointers at each step.

 When entered via Debug(), you are now running as a "task" so you will
 be able to assume some things about system structures.  This means that
 you are in supervisor state and that you can assume that the
 system is at least not between states.  However, remember that since
 you are debugging the system, some bad code could cause data structures
 to be invalid.  Again, standard debugging issues are in play.  SAD just
 gives you the hooks to do whatever you need.

 Note:  When SAD prompts with $BF you will be in full disable/forbid
 state.  When $3F prompting, SAD will only do a Forbid().  It is possible
 for you to then disable interrupts as needed.  This is done such that it
 is possible to "run" the system from SAD when called with Debug().

        -- Data Frames and the Registers --

 SAD generates a special data frame that can be used to read what
 registers contain and to change the contents of the registers.
 See the entry for GET_CONTEXT_FRAME for more details

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

 BUGS
    In V39 EXEC, the WRITE_BYTE command was not connected and this
    caused all of the command numbers to be off-by-one.  For example,
    the READ_WORD command is listed as command $05 but in V39 is $04.
    However, the ACK of the commands are still correct.

    Also, in V39 EXEC, the READ_WORD command would return the wrong
    data.

    To determin if you are in V39 or V40 SAD, you can issue a simple
    SAD command at the start of the session.  By sending a READ_WORD
    command, you may either get a READ_WORD (V40) or a READ_LONG (V39)
    ACK'ed back.  So the data stream for a safe test would be:

    Send: $AF $05 $00 $F8 $00 $00               ; Read start of ROM...
    Recv: $00 $05 ....   You have V40 SAD
    Recv: $00 $06 ....   You have V39 SAD

    Note that you should be ready to read either 2 or 4 bytes of
    result depending on the ACK sent by the system.


SAD/ALLOCATE_MEMORY

 ALLOCATE MEMORY

 Command:	$AF $0A
 Data:		$qq $rr $ss $tt $hh $ii $jj $kk

 Allocate a chunk of memory that is <$qqrrsstt> bytes in size.  Note
 that this call is only safe when SAD is in $3F prompting mode (called
 from Debug()) and even then may be unsafe if the system is in bad shape.
 (You are debugging after all)  The returned address will be available to
 you until you release it.  (It is obtained via a call to AllocVec())  The
 type of memory allocated is <$hhiijjkk>.  Note that the allocation may
 fail. In that case, the address returned will be $00000000.

 Command ACK:	$00 $0A
 Command DONE:	$1F $0A $ww $xx $yy $zz


SAD/CALL_ADDRESS

 CALL ADDRESS - JSR to the given address.

 Command:	$AF $07
 Data:		$ww $xx $yy $zz

 Call the following address as a subroutine.  No registers will be
 set up but the context frame will exist.  Standard calling
 conventions apply (d0/d1/a0/a1 are available, rest must be saved)
 The command will be ACK'ed when received.
 Command ACK:	$00 $07
 Command DONE:	$1F $07


SAD/FREE_MEMORY

 FREE MEMORY

 Command:	$AF $0B
 Data:		$ww $xx $yy $zz

 Free the memory allocated with the ALLOCATE MEMORY command.  This command
 has the same restrictions as ALLOCATE MEMORY.  Memory is released by
 calling FreeVec() on the address <$wwxxyyzz>

 Command ACK:	$00 $0B
 Command DONE:	$1F $0B


SAD/GET_CONTEXT_FRAME

 GET CONTEXT FRAME

 Command:	$AF $09
 Data:		<none>

 This command will return a pointer to the saved context.  This will be
 a pointer to all of the registers that were saved on the stack along
 with some other details.  Returns frame address <$wwxxyyzz>

 The pointer returned is to the following structure:

 STRUCTURE	SAD_FRAME,0
    ; The first three are READ-ONLY...  Mainly used to make it
    ; easier to understand what is going on in the system.
    ULONG	SAD_VBR		; Current VBR (always 0 on 68000 CPUs)
    ULONG	SAD_AttnFlags	; ULONG copy of the flags (UPPER WORD==0)
    ULONG	SAD_ExecBase	; ExecBase
    ; These fields are the user registers...  The registers are
    ; restored from these fields on exit from SAD...
    ; Note that USP is only valid if SR was *NOT* supervisor...
    ULONG	SAD_USP		; User stack pointer
    ULONG	SAD_D0		; User register d0
    ULONG	SAD_D1		; User register d1
    ULONG	SAD_D2		; User register d2
    ULONG	SAD_D3		; User register d3
    ULONG	SAD_D4		; User register d4
    ULONG	SAD_D5		; User register d5
    ULONG	SAD_D6		; User register d6
    ULONG	SAD_D7		; User register d7
    ULONG	SAD_A0		; User register a0
    ULONG	SAD_A1		; User register a1
    ULONG	SAD_A2		; User register a2
    ULONG	SAD_A3		; User register a3
    ULONG	SAD_A4		; User register a4
    ULONG	SAD_A5		; User register a5
    ULONG	SAD_A6		; User register a6
    ; This is for SAD internal use...  It is the prompt that
    ; SAD is using...  Changing this will have no effect on SAD.
    ULONG	SAD_PROMPT	; SAD Prompt Longword...  (internal use)
    ; From here on down is the standard exception frame
    ; The first two entries (SR and PC) are standard on all 680x0 CPUs
    UWORD	SAD_SR		; Status register (part of exception frame)
    ULONG	SAD_PC		; Return address (part of exception frame)

 Command ACK:	$00 $09
 Command DONE:	$1F $09 $ww $xx $yy $zz


SAD/NOP

 NO-OP - Do nothing other than tell SAD you are still there...

 Command:	$AF $00
 Data:		<none>

 This just tells SAD you are still there.  Required so that timeouts do
 not exit SAD while you are not doing anything.

 This command will *NOT* be ACK'ed.  It will just cause the timeout to
 be restarted.


SAD/READ_ARRAY

 READ ARRAY - Read a range of bytes

 Command:	$AF $0F
 Data:		$ww $xx $yy $zz $qq $rr $ss $tt

 Read a range of bytes from address <$wwxxyyzz> for <$qqrrsstt> bytes
 Will return that number of bytes...

 Command will be ACK'ed when received.
 Command ACK:	$00 $0F
 Command DONE:	$1F $0F $uu [$uu ...]


SAD/READ_BYTE

 READ BYTE - Read a byte from the given address

 Command:	$AF $04
 Data:		$ww $xx $yy $zz

 Read a byte from address <$wwxxyyzz>  Returns <$qq> as result

 Command will be ACK'ed when received.
 Command ACK:	$00 $04
 Command DONE:	$1F $04 $qq


SAD/READ_LONG

 READ LONG - Read a long from the given address

 Command:	$AF $06
 Data:		$ww $xx $yy $zz

 Read a long from address <$wwxxyyzz>  Returns <$qqrrsstt> as result

 Command will be ACK'ed when received.
 Command ACK:	$00 $06
 Command DONE:	$1F $06 $qq $rr $ss $tt


SAD/READ_WORD

 READ WORD - Read a word from the given address		(V40 SAD)

 Command:	$AF $05
 Data:		$ww $xx $yy $zz

 Read a word from address <$wwxxyyzz>  Returns <$qqrr> as result

 Command will be ACK'ed when received.
 Command ACK:	$00 $05
 Command DONE:	$1F $05 $qq $rr

 BUGS
    This command does not return correct values in pre-V40 EXEC.


SAD/RESET

 RESET - Reset the computer...

 Command:	$AF $10
 Data:		$FF $FF $FF $FF

 This command will reset the computer.  the $FFFFFFFF value is there
 mainly to prevent false reset.  This command will only be ACK'ed as
 the computer will be reset afterwards...

 Command will be ACK'ed when received.
 Command ACK:	$00 $10


SAD/RETURN_TO_SYSTEM

 RETURN TO SYSTEM

 Command:	$AF $08
 Data:		$00 $00 $00 $00

 This command will return <exit> from SAD back to whatever started it.
 The 4 $00 are required as a "safty" to this command.  The command
 will be ACK'ed only as it will have lost control of the system.

 Command ACK:	$00 $08


SAD/TURN_OFF_SINGLE

 TURN OFF SINGLE STEPPING

 Command:	$AF $0D
 Data:		$ww $xx $yy $zz

 This command will turn off SAD single stepping mode.  You need to pass
 to it the address returned from the call to turn on single stepping mode.

 Command ACK:	$00 $0D
 Command DONE:	$1F $0D


SAD/TURN_ON_SINGLE

 TURN ON SINGLE STEPPING

 Command:	$AF $0C
 Data:		<none>

 This command will turn on SAD single stepping mode.  This means that SAD
 will single step (via 68000 trace mode) the system.  SAD will take over
 the TRACE exception vector during this time.  This command will return
 the contents of the vector such that you can return this value when
 you wish to turn off single stepping mode.  Note that turning on single
 stepping mode while in $BF prompting will cause the step to be taken
 and then SAD will execute in $3F mode (non-NMI)
 The command returns <$wwxxyyzz> which you must use when turning off
 the single-step mode.

 Command ACK:	$00 $0C
 Command DONE:	$1F $0C $ww $xx $yy $zz


SAD/WRITE_ARRAY

 WRITE ARRAY - Write a range of bytes

 Command:	$AF $0E
 Data:		$ww $xx $yy $zz $qq $rr $ss $tt

 Write a range of bytes to address <$wwxxyyzz> for <$qqrrsstt> bytes
 After the computer sends the ACK, you must then send the byte stream...

 Command will be ACK'ed when received.
 Command ACK:	$00 $0E
 Command DONE:	$1F $0E


SAD/WRITE_BYTE

 WRITE BYTE - Write the given data to the address given	(V40 SAD)

 Command:	$AF $01
 Data:		$ww $xx $yy $zz $qq

 Write the byte <$qq> to address <$wwxxyyzz>

 Command will be ACK'ed when received.
 Command ACK:	$00 $01
 Command DONE:	$1F $01

 BUGS
    This command does not exists in pre-V40 EXEC.
    This command can be emulated with the WRITE_ARRAY command with
    a length of 1.


SAD/WRITE_LONG

 WRITE LONG - Write the given data to the address given

 Command:	$AF $03
 Data:		$ww $xx $yy $zz $qq $rr $ss $tt

 Write the long <$qqrrsstt> to address <$wwxxyyzz>

 Command will be ACK'ed when received.
 Command ACK:	$00 $03
 Command DONE:	$1F $03


SAD/WRITE_WORD

 WRITE WORD - Write the given data to the address given

 Command:	$AF $02
 Data:		$ww $xx $yy $zz $qq $rr

 Write the word <$qqrr> to address <$wwxxyyzz>

 Command will be ACK'ed when received.
 Command ACK:	$00 $02
 Command DONE:	$1F $02


expansion.doc

     AddBootNode()
     AddConfigDev()
     AddDosNode()
     AllocConfigDev()
     AllocExpansionMem()
     ConfigBoard()
     FindConfigDev()
     FreeConfigDev()
     FreeExpansionMem()
     GetCurrentBinding()
     MakeDosNode()
     ObtainConfigBinding()
     ReadExpansionByte()
     ReadExpansionRom()
     ReleaseConfigBinding()
     RemConfigDev()
     SetCurrentBinding()
     WriteExpansionByte()


expansion.library/AddBootNode

   NAME
    AddBootNode -- Add a BOOTNODE to the system (V36)

   SYNOPSIS
    ok = AddBootNode( bootPri, flags, deviceNode, configDev )
    D0		  D0	   D1	  A0	      A1

    BOOL AddBootNode( BYTE,ULONG,struct DeviceNode *,struct ConfigDev * );

   FUNCTION
    This function will do one of two things:

        1> If dos is running, add a new disk type device immediatly.
        2> If dos is not yet running, save information for later
           use by the system.

   FUNCTION
    This routine makes sure that your disk device (or a device
    that wants to be treated as if it was a disk...) will be
    entered into the system.  If the dos is already up and
    running, then it will be entered immediately.  If the dos
    has not yet been run then the data will be recorded, and the
    dos will get it later.

    We try and boot off of each device in turn, based on priority.
    Floppies have a hard-coded priority.

    There is only one additional piece of magic done by AddBootNode.
    If there is no executable code specified in the deviceNode
    structure (e.g. dn_SegList, dn_Handler, and dn_Task are all
    null) then the standard dos file handler is used for your
    device.

    Documentation note: a "task" as used here is a dos-task, not
    an exec-task.  A dos-task, in the strictest sense, is the
    address of an exec-style message port.	In general, it is
    a pointer to a process's pr_MsgPort field (e.g. a constant
    number of bytes after an exec task).

    Autoboot from an expansion card before DOS is running requires
    the card's ConfigDev structure.

    Pass a NULL ConfigDev pointer to create a non-bootable node.

   INPUTS
    bootPri -- a BYTE quantity with the boot priority for this disk.
        This priority is only for which disks should be looked at:
        the actual disk booted from will be the first disk with
        a valid boot block.  If no disk is found then the "bootme"
        hand will come up and the bootstrap code will wait for
        a floppy to be inserted.  Recommend priority assignments are:

        +5   -- unit zero for the floppy disk.	The floppy should
            always be highest priority to allow the user to
            abort out of a hard disk boot.
         0   -- the run of the mill hard disk
        -5   -- a "network" disk (local disks should take priority).
        -128 -- don't even bother to boot from this device.

    flags -- additional flag bits for the call:
        ADNF_STARTPROC (bit 0) -- start a handler process immediately.
        Normally the process is started only when the device node
        is first referenced.  This bit is meaningless if you
        have already specified a handler process (non-null dn_Task).

    deviceNode -- a legal DOS device node, properly initialized.
        Typically this will be the result of a MakeDosNode().
        Special cases may require a custom-built device node.

    configDev -- a valid board's ConfigDev structure.  This is required
        for autoboot before DOS is running and if left NULL will
        result in an non-bootable node.

   RESULTS
    ok - non-zero everything went ok, zero if we ran out of memory
        or some other weirdness happened.

   NOTE
    This function eliminates the need to manually Enqueue a BOOTNODE
    onto an expansion.library list.  Be sure V36 expansion.library is
    available before calling this function!

   SEE ALSO
    AddDosNode()


expansion.library/AddConfigDev

   NAME
    AddConfigDev - add a new ConfigDev structure to the system

   SYNOPSIS
    AddConfigDev( configDev )
                  A0

   FUNCTION
    (Not typically called by user code)

    This routine adds the specified ConfigDev structure to the
    list of Configuration Devices in the system.

   INPUTS
    configDev - a valid ConfigDev structure.

   RESULTS

   EXCEPTIONS

   SEE ALSO
    RemConfigDev()

   BUGS


expansion.library/AddDosNode

   NAME
    AddDosNode -- mount a disk to the system

   SYNOPSIS
    ok = AddDosNode( bootPri, flags, deviceNode )
    D0		 D0	  D1	 A0

    BOOL AddDosNode( BYTE,ULONG,struct DeviceNode *);

   FUNCTION
    This is the old (pre V36) function that works just like
    AddBootNode().  It should only be used if you *MUST* work
    in a 1.3 system and you don't need to autoboot.

   RESULTS
    ok - non-zero everything went ok, zero if we ran out of memory
        or some other weirdness happened.

   EXAMPLE
    /* enter a bootable disk into the system.  Start a file handler
    ** process immediately.
    */
    if(  AddDosNode( 0, ADNF_STARTPROC, MakeDosNode( paramPacket ) )  )
        ...AddDosNode ok...

   BUGS
    Before V36 Kickstart, no function existed to add BOOTNODES.
    If an older expansion.library is in use, driver code will need
    to manually construct a BootNode and Enqueue() it to eb_Mountlist.
    If you have a V36 or better expansion.library, your code should
    use AddBootNode().

   SEE ALSO
    MakeDosNode(), AddBootNode()


expansion.library/AllocConfigDev

   NAME
    AllocConfigDev - allocate a ConfigDev structure

   SYNOPSIS
    configDev = AllocConfigDev()
    D0

   FUNCTION
    This routine returns the address of a ConfigDev structure.
    It is provided so new fields can be added to the structure
    without breaking old, existing code.  The structure is cleared
    when it is returned to the user.

   INPUTS

   RESULTS
    configDev - either a valid ConfigDev structure or NULL.

   EXCEPTIONS

   SEE ALSO
    FreeConfigDev()

   BUGS


expansion.library/AllocExpansionMem

   NAME
    AllocExpansionMem - allocate expansion memory

   SYNOPSIS
    startSlot = AllocExpansionMem( numSlots, slotOffset )
    D0                             D0        D1

   FUNCTION
    (Not typically called by user code)

    This function allocates numslots of expansion space (each slot
    is E_SLOTSIZE bytes).  It returns the slot number of the
    start of the expansion memory.  The EC_MEMADDR macro may be
    used to convert this to a memory address.

    Boards that fit the expansion architecture have alignment
    rules.  Normally a board must be on a binary boundary of its
    size.  Four and Eight megabyte boards have special rules.
    User defined boards might have other special rules.

    If AllocExpansionMem() succeeds, the startSlot will satisfy
    the following equation:

        (startSlot - slotOffset) MOD slotAlign = 0

   INPUTS
    numSlots - the number of slots required.
    slotOffset - an offset from that boundary for startSlot.

   RESULTS
    startSlot - the slot number that was allocated, or -1 for error.

   EXAMPLES

        AllocExpansionMem( 2, 0 )

    Tries to allocate 2 slots on a two slot boundary.

        AllocExpansionMem( 64, 32 )

    This is the allocation rule for 4 meg boards.  It allocates
    4 megabytes (64 slots) on an odd 2 meg boundary.

   EXCEPTIONS

   SEE ALSO
    FreeExpansionMem()

   BUGS


expansion.library/ConfigBoard

   NAME
    ConfigBoard - configure a board

   SYNOPSIS
    error = ConfigBoard( board, configDev )
    D0                   A0     A1

   FUNCTION
    This routine configures an expansion board.  The board
    will generally live at E_EXPANSIONBASE, but the base is
    passed as a parameter to allow future compatibility.
    The configDev parameter must be a valid configDev that
    has already had ReadExpansionRom() called on it.

    ConfigBoard will allocate expansion memory and place
    the board at its new address.  It will update configDev
    accordingly.  If there is not enough expansion memory
    for this board then an error will be returned.

   INPUTS
    board - the current address that the expansion board is
        responding.
    configDev - an initialized ConfigDev structure, returned
        by AllocConfigDev.

   RESULTS
    error - non-zero if there was a problem configuring this board
        (Can return EE_OK or EE_NOEXPANSION)

   SEE ALSO
    FreeConfigDev()


expansion.library/FreeConfigDev

   NAME
    FreeConfigDev - free a ConfigDev structure

   SYNOPSIS
    FreeConfigDev( configDev )
                   A0

   FUNCTION
    This routine frees a ConfigDev structure as returned by
    AllocConfigDev.

   INPUTS
    configDev - a valid ConfigDev structure.

   RESULTS

   EXCEPTIONS

   SEE ALSO
    AllocConfigDev()

   BUGS


expansion.library/FreeExpansionMem

   NAME
    FreeExpansionMem - allocate standard device expansion memory

   SYNOPSIS
    FreeExpansionMem( startSlot, numSlots )
                      D0         D1

   FUNCTION
    (Not typically called by user code)

    This function allocates numslots of expansion space (each slot
    is E_SLOTSIZE bytes).  It is the inverse function of
    AllocExpansionMem().

   INPUTS
    startSlot - the slot number that was allocated, or -1 for error.
    numSlots - the number of slots to be freed.

   RESULTS

   EXAMPLES

   EXCEPTIONS
    If the caller tries to free a slot that is already in the
    free list, FreeExpansionMem will Alert() (e.g. crash the
    system).

   SEE ALSO
    AllocExpansionMem()

   BUGS


expansion.library/GetCurrentBinding

   NAME
    GetCurrentBinding - gets static board configuration area

   SYNOPSIS
    actual = GetCurrentBinding( currentBinding, size )
                                A0              D0:16

   FUNCTION
    This function writes the contents of the "currentBinding"
    structure out of a private place.  It may be set via
    SetCurrentBinding().  This is really a kludge, but it is
    the only way to pass extra arguments to a newly configured
    device.

    A CurrentBinding structure has the name of the currently
    loaded file, the product string that was associated with
    this driver, and a pointer to the head of a singly linked
    list of ConfigDev structures (linked through the cd_NextCD
    field).

    Many devices may not need this information; they have hard
    coded into themselves their manufacture number.  It is
    recommended that you at least check that you can deal with
    the product code in the linked ConfigDev structures.

   INPUTS
    currentBinding - a pointer to a CurrentBinding structure

    size - The size of the user's binddriver structure.
        Do not pass in less than sizeof(struct CurrentBinding).

   RESULTS
    actual - the true size of a CurrentBinding structure is returned.

   SEE ALSO
    SetCurrentBinding()


expansion.library/MakeDosNode

   NAME
    MakeDosNode -- construct dos data structures that a disk needs

   SYNOPSIS
    deviceNode = MakeDosNode( parameterPkt )
    D0			  A0

    struct DeviceNode * MakeDosNode( void * );

   FUNCTION
    This routine manufactures the data structures needed to enter
    a dos disk device into the system.  This consists of a DeviceNode,
    a FileSysStartupMsg, a disk environment vector, and up to two
    bcpl strings.  See the libraries/dosextens.h and
    libraries/filehandler.h include files for more information.

    MakeDosNode will allocate all the memory it needs, and then
    link the various structure together.  It will make sure all
    the structures are long-word aligned (as required by the DOS).
    It then returns the information to the user so he can
    change anything else that needs changing.  Typically he will
    then call AddDosNode() to enter the new device into the dos
    tables.

   INPUTS
    parameterPkt - a longword array containing all the information
        needed to initialize the data structures.  Normally I
        would have provided a structure for this, but the variable
        length of the packet caused problems.  The two strings are
        null terminated strings, like all other exec strings.

        longword	description
        --------	-----------
        0		string with dos handler name
        1		string with exec device name
        2		unit number (for OpenDevice)
        3		flags (for OpenDevice)
        4		# of longwords in rest of environment
        5-n 	file handler environment (see libraries/filehandler.h)

   RESULTS
    deviceNode - pointer to initialize device node structure, or
        null if there was not enough memory.  You may need to change
        certain fields before passing the DeviceNode to AddDosNode().

   EXAMPLES
    /* set up a 3.5" Amiga format floppy drive for unit 1 */

    char execName[] = "trackdisk.device";
    char dosName[] = "df1";

    ULONG parmPkt[] = {
        (ULONG) dosName,
        (ULONG) execName,
        1,			/* unit number */
        0,			/* OpenDevice flags */

        /* here is the environment block */
        16, 		/* table upper bound */
        512>>2,		/* # longwords in a block */
        0,			/* sector origin -- unused */
        2,			/* number of surfaces */
        1,			/* secs per logical block -- leave as 1 */
        11, 		/* blocks per track */
        2,			/* reserved blocks -- 2 boot blocks */
        0,			/* ?? -- unused */
        0,			/* interleave */
        0,			/* lower cylinder */
        79, 		/* upper cylinder */
        5,			/* number of buffers */
        MEMF_CHIP,		/* type of memory for buffers */
        (~0 >> 1),          /* largest transfer size (largest signed #) */
        ~1, 		/* addmask */
        0,			/* boot priority */
        0x444f5300, 	/* dostype: 'DOS0' */
    };

    struct Device Node *node, *MakeDosNode();

    node = MakeDosNode( parmPkt );

   SEE ALSO
    AddDosNode(), libraries/dosextens.h, libraries/filehandler.h


expansion.library/ReadExpansionByte

   NAME
    ReadExpansionByte - read a byte nybble by nybble.

   SYNOPSIS
    byte = ReadExpansionByte( board, offset )
    D0                        A0     D0

   FUNCTION
    (Not typically called by user code)

     ReadExpansionByte reads a byte from a new-style expansion
    board.  These boards have their readable data organized
    as a series of nybbles in memory.  This routine reads
    two nybbles and returns the byte value.

    In general, this routine will only be called by ReadExpansionRom.

    The offset is a byte offset, as if into a ExpansionRom structure.
    The actual memory address read will be four times larger.
    The macros EROFFSET and ECOFFSET are provided to help get
    these offsets from C.

   INPUTS
    board - a pointer to the base of a new style expansion board.
    offset - a logical offset from the board base

   RESULTS
    byte - a byte of data from the expansion board.

   EXAMPLES
    byte = ReadExpansionByte( cd->BoardAddr, EROFFSET( er_Type ) );
    ints = ReadExpansionByte( cd->BoardAddr, ECOFFSET( ec_Interrupt ) );

   SEE ALSO
    WriteExpansionByte(), ReadExpansionRom()


expansion.library/ReadExpansionRom

   NAME
    ReadExpansionRom - read a boards configuration ROM space

   SYNOPSIS
    error = ReadExpansionRom( board, configDev )
    D0                        A0     A1

   FUNCTION
    (Not typically called by user code)

    ReadExpansionRom reads a the ROM portion of an expansion
    device in to cd_Rom portion of a ConfigDev structure.
    This routine knows how to detect whether or not there is
    actually a board there,

    In addition, the ROM portion of a new style expansion board
    is encoded in ones-complement format (except for the first
    two nybbles -- the er_Type field).  ReadExpansionRom knows
    about this and un-complements the appropriate fields.

   INPUTS
    board - a pointer to the base of a new style expansion board.
    configDev - the ConfigDev structure that will be read in.
    offset - a logical offset from the configdev base

   RESULTS
    error - If the board address does not contain a valid new style
        expansion board, then error will be non-zero.

   EXAMPLES

    configDev = AllocConfigDev();
    if( ! configDev ) panic();

    error = ReadExpansionBoard( board, configDev );
    if( ! error ) {
        configDev->cd_BoardAddr = board;
        ConfigBoard( configDev );
    }

   SEE ALSO
    ReadExpansionByte(), WriteExpansionByte()


expansion.library/RemConfigDev

   NAME
    RemConfigDev - remove a ConfigDev structure from the system

   SYNOPSIS
    RemConfigDev( configDev )
                  A0

   FUNCTION
    (Not typically called by user code)

    This routine removes the specified ConfigDev structure from the
    list of Configuration Devices in the system.

   INPUTS
    configDev - a valid ConfigDev structure.

   RESULTS

   EXCEPTIONS

   SEE ALSO
    AddConfigDev()

   BUGS


expansion.library/SetCurrentBinding

   NAME
    SetCurrentBinding - sets static board configuration area

   SYNOPSIS
    SetCurrentBinding( currentBinding, size )
                       A0		   D0:16

   FUNCTION
    This function records the contents of the "currentBinding"
    structure in a private place.  It may be read via
    GetCurrentBinding().  This is really a kludge, but it is
    the only way to pass extra arguments to a newly configured
    device.

    A CurrentBinding structure has the name of the currently
    loaded file, the product string that was associated with
    this driver, and a pointer to the head of a singly linked
    list of ConfigDev structures (linked through the cd_NextCD
    field).

    Many devices may not need this information; they have hard
    coded into themselves their manufacture number.  It is
    recommended that you at least check that you can deal with
    the product code in the linked ConfigDev structures.

   INPUTS
    currentBinding - a pointer to a CurrentBinding structure

    size - The size of the user's binddriver structure.  No
        more than this much data will be copied.  If size is
        less than the library's idea a CurrentBinding size,
        then the library's structure will be null padded.

   SEE ALSO
    GetCurrentBinding()


expansion.library/WriteExpansionByte

   NAME
    WriteExpansionByte - write a byte nybble by nybble.

   SYNOPSIS
    WriteExpansionByte( board, offset, byte )
                A0     D0      D1

   FUNCTION
    (Not typically called by user code)

    WriteExpansionByte writes a byte to a new-style expansion
    board.  These boards have their writeable data organized
    as a series of nybbles in memory.  This routine writes
    two nybbles in a very careful manner to work with all
    types of new expansion boards.

    To make certain types of board less expensive, an expansion
    board's write registers may be organized as either a
    byte-wide or nybble-wide register.  If it is nybble-wide
    then it must latch the less significant nybble until the
    more significant nybble is written.  This allows the
    following algorithm to work with either type of board:

        write the low order nybble to bits D15-D12 of
            byte (offset*4)+2

        write the entire byte to bits D15-D8 of
            byte (offset*4)

    The offset is a byte offset into a ExpansionRom structure.
    The actual memory address read will be four times larger.
    The macros EROFFSET and ECOFFSET are provided to help get
    these offsets from C.

   INPUTS
    board - a pointer to the base of a new style expansion board.
    offset - a logical offset from the configdev base
    byte - the byte of data to be written to the expansion board.

   EXAMPLES
    WriteExpansionByte( cd->BoardAddr, ECOFFSET( ec_Shutup ),  0 );
    WriteExpansionByte( cd->BoardAddr, ECOFFSET( ec_Interrupt ), 1 );

   SEE ALSO
    ReadExpansionByte(), ReadExpansionRom()


fuelgauge_gc.doc

     --datasheet--
     FUELGAUGE_GetClass()


fuelgauge_gc/--datasheet--

    NAME
        fuelgauge_gc -- create fuelgauge BOOPSI objects

    SUPERCLASS
        gadgetclass

    REQUIRES
        bevel.image

    DESCRIPTION
        The fuelgauge gadget class is used to display stage of completion
        of some operation, such as formating a floppy. Or, perhaps as
        a means of indication, such as free drive space.

        Advantages that this class provides:

         > Supports window relativity.

         > Optional tick marks, and short ticks.

         > Ability to change background pen, text pen, and filltext pen.

         > Supports OS 3.0 BOOPSI Gadget HelpTest.

    METHODS
        OM_NEW -- Passed to superclass to creates object instance

        OM_SET -- Sets all possible settings, then passed to superclass

        OM_GET -- Returns requested setting or passed to superclass

        OM_DISPOSE -- Passed to superclass

        GM_HITTEST -- Returns 0.

        GM_RENDER -- Passed to superclass, then renders fuelgauge

        GM_DOMAIN -- Returns GDOMAIN_MINIMUM, GDOMAIN_NOMINAL and
            GDOMAIN_MAXIMUM dimensions.

        GM_GOACTIVE -- NO OP
        GM_HANDLEINPUT -- NO OP
        GM_GOINACTIVE -- NO OP

    ATTRIBUTES

        GA_Text (STRPTR)
            Used to specify the NULL terminated string to use
            as the text for the gadget.  The Text() function is used to draw
            the text. NULL is valid input, and will enable the default
            centered percentage rendering. Changing the label will invoke
            GM_RENDER. Text string is clipped to fit inside the gauge via
            the TextFit() function. The text string may contain varargs
            format specifiers compatible to RawDoFmt() if the varargs data
            is supplied via FUELGAUGE_VarArgs.

            Applicability is (OM_NEW, OM_SET)

        FUELGAUGE_Min (LONG)
            Minimum value of the gauge.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET, OM_NOTIFY)

        FUELGAUGE_Max (LONG)
            Maximum value of the gauge.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET, OM_NOTIFY)

        FUELGAUGE_Level (LONG)
            Current gauge setting, usually something between Min and Max.
            Base on Min, Max and Current a percentage can be calculated
            and displayed by the gadget.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET, OM_NOTIFY)

        FUELGAUGE_Orientation (WORD)
            Sets the orientation of the fuel gauge to vertical or
            horizontal.

            Accepted values as defined in <gadgets/fuelgauge.h> are:

               FGORIENT_HORIZ
               FGORIENT_VERT

            Defaults to FGORIENT_HORIZ

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

        FUELGAUGE_Percent (WORD)
            Enable/Disable Percentage display.
            Percentage is displayed in the center of the gauge using
            the requested font, provided it fits within the gadget bounds.

            Defaults to TRUE

            Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET)

        FUELGAUGE_Ticks (BOOL)
            Sets the number of "tickmarks" rendered along the bottom
            of the gadget. Take note, the tickmarks are rendered within
            the gadgets size dimentions. Values greater than 0 enable
            the tick mark(s).

            Defaults to 0

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

        FUELGAUGE_ShortTicks (BOOL)
            Enables rendering of "shortticks", smaller size tickmarks
            rendered in between the larger tick marks.

            Defaults to FALSE,

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

        FUELGAUGE_TickSize (WORD)
            Sets the size, in pixels, of the large tickmarks.
            Shorttick size is TickHeight / 2. Note, if NOT setting
            FUELGAUGE_Ticks non-zero, then you may need to 0 this as
            well depending on the fuelgauge release version!

            Defaults to 5 pixels

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

        FUELGAUGE_TickPen (WORD)
            Pen number used to render the tickmarks.

            Defaults to SHINEPEN.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

        FUELGAUGE_PercentPen (WORD)
            Pen number used to render the percentage text label.

            Defaults to TEXTPEN.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

        FUELGAUGE_EmptyPen (WORD)
            Pen number used to render the empty section of the gauge.

            Defaults to BACKGROUNDPEN.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

        FUELGAUGE_FillPen (WORD)
            Pen number used to render the filled section of the gauge.

            Defaults to BACKGROUNDPEN.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

        FUELGAUGE_VarArgs (APTR)
            Varargs data array to supply data for RawDoFmt() when
            format specifiers are to be used in GA_Text text strings.
            The VarArgs internal result buffer is 128 bytes, take care
            not to exceed this buffer.

            Defaults to NULL.

            Applicability is (OM_NEW, OM_SET)

        FUELGAUGE_Justification (WORD)
            Justification mode of fuelgauge (GA_Text) text label.
            Percentage rendering, when enabled, is always centered.

            Supports:

                FGJ_LEFT
                FGJ_CENTER

            Defaults to FGJ_LEFT.

            Applicability is (OM_NEW, OM_SET)


fuelgauge_gc/FUELGAUGE_GetClass

    NAME
        FUELGAUGE_GetClass -- Gets the pointer to the fuelgauge class.

    SYNOPSIS
        fuelgauge_class = FUELGAUGE_GetClass();
        D0

        Class * FUELGAUGE_GetClass(VOID);

    FUNCTION
        Obtains the pointer to the FuelGauge gadget class for use with
        NewObject().  This function always returns a valid pointer so
        you do not need to check it.  The reason is that if the library
        opens fine, then the pointer returned is already setup.  (Of course
        this implies that if opening the library fails, you shouldn't be
        calling this.)

        Note that this function does not create the class, that is done
        when the class library is opened.

    INPUTS
        Nothing.

    RESULT
        fuelgauge_class - Pointer to the FuelGauge gadget class.

    SEE ALSO


gadtools.doc

     CreateContext()
     CreateGadgetA()
     CreateMenusA()
     DrawBevelBoxA()
     FreeGadgets()
     FreeMenus()
     FreeVisualInfo()
     GetVisualInfoA()
     GT_BeginRefresh()
     GT_EndRefresh()
     GT_FilterIMsg()
     GT_GetGadgetAttrsA()
     GT_GetIMsg()
     GT_PostFilterIMsg()
     GT_RefreshWindow()
     GT_ReplyIMsg()
     GT_SetGadgetAttrsA()
     LayoutMenuItemsA()
     LayoutMenusA()


gadtools.library/CreateContext

   NAME
    CreateContext -- create a place for GadTools context data. (V36)

   SYNOPSIS
    gad = CreateContext(glistpointer);
    D0                  A0

    struct Gadget *CreateContext(struct Gadget **);

   FUNCTION
    Creates a place for GadTools to store any context data it might
    need for your window.  In reality, an unselectable invisible
    gadget is created, with room for the context data.
    This function also establishes the linkage from a glist type
    pointer to the individual gadget pointers.  Call this function
    before any of the other gadget creation calls.

   INPUTS
    glistptr - address of a pointer to a Gadget, which was previously
               set to NULL.  When all the gadget creation is done, you may
               use that pointer as your NewWindow.FirstGadget, or
               in intuition.library/AddGList(),
               intuition.library/RefreshGList(), FreeGadgets(), etc.

   RESULT
    gad - pointer to context gadget, or NULL if failure.

   EXAMPLE

    struct Gadget *gad;
    struct Gadget *glist = NULL;
    gad = CreateContext(&glist);
    /*  Other creation calls go here */
    if (gad)
    {
        myNewWindow.FirstGadget = glist;
        if ( myWindow = OpenWindow(&myNewWindow) )
        {
        GT_RefreshWindow(win,NULL);
        /* other stuff */
        CloseWindow(myWindow);
        }
    }
    FreeGadgets(glist);


gadtools.library/CreateGadgetA

   NAME
    CreateGadgetA -- allocate and initialize a gadtools gadget. (V36)
    CreateGadget -- varargs stub for CreateGadgetA(). (V36)

   SYNOPSIS
    gad = CreateGadgetA(kind, previous, newgad, tagList)
    D0                  D0    A0        A1      A2

    struct Gadget *CreateGadgetA(ULONG, struct Gadget *,
                                 struct NewGadget *, struct TagItem *);

    gad = CreateGadget(kind, previous, newgad, firsttag, ...)

    struct Gadget *CreateGadget(ULONG, struct Gadget *,
                                struct NewGadget *, Tag, ...);

   FUNCTION
    CreateGadgetA() allocates and initializes a new gadget of the
    specified kind, and attaches it to the previous gadget.  The
    gadget is created based on the supplied kind, NewGadget structure,
    and tags.

   INPUTS
    kind - kind of gadget is to be created, one of the XXX_KIND values
           defined in <libraries/gadtools.h>
    previous - pointer to the previous gadget that this new gadget
               is to be attached to. This function will fail if this value
           is NULL
    newgad - a filled in NewGadget structure describing the desired
             gadget's size, position, label, etc.
    tagList - pointer to an array of tags providing optional extra
          parameters, or NULL

   TAGS
    All kinds:
    GT_Underscore - Indicates the symbol that precedes the character in
        the gadget label to be underscored.  This can be to indicate
        keyboard equivalents for gadgets (note that GadTools does not
        process the keys - it just displays the underscore).  For example,
        to underscore the "M" in "Mode":
        ng.ng_GadgetText = "_Mode:";
        gad = CreateGadget(..._KIND, &ng, prev,
            GT_Underscore, '_',
            ...
            );
        (V37)

    BUTTON_KIND (action buttons):
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE). (V36)
    GA_Immediate (BOOL) - Hear IDCMP_GADGETDOWN events from button gadget
        (defaults to FALSE). (V39)

    CHECKBOX_KIND (on/off items):
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE).
    GTCB_Checked (BOOL) - Initial state of checkbox (defaults to FALSE)
        (V36)
    GTCB_Scaled (BOOL) - If true, then checkbox imagery will be scaled to
        fit the gadget's width & height.  Otherwise, a fixed size of
        CHECKBOXWIDTH by CHECKBOXHEIGHT will be used. (defaults to FALSE)
        (V39)

    CYCLE_KIND (multiple state selections):
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE). (V37)
    GTCY_Labels (STRPTR *) - Pointer to NULL-terminated array of strings
        that are the choices offered by the cycle gadget. This tag is
        required. (V36)
    GTCY_Active (UWORD) - The ordinal number (counting from zero) of
        the initially active choice of a cycle gadget (defaults to zero).
        (V36)

    INTEGER_KIND (numeric entry):
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE). (V36)
    GA_Immediate (BOOL) - Hear IDCMP_GADGETDOWN events from integer
        gadget (defaults to FALSE). (V39)
    GA_TabCycle (BOOL) - Set to TRUE so that pressing <TAB> or <Shift-TAB>
        will activate the next or previous such gadget. (defaults to TRUE,
        unlike regular Intuition string gadgets which default to FALSE).
        (V37)
    GTIN_Number (LONG) - The initial contents of the integer gadget
        (defaults to 0). (V36)
    GTIN_MaxChars (UWORD) - The maximum number of digits that the
        integer gadget is to hold (defaults to 10). (V36)
    GTIN_EditHook (struct Hook *) - Hook to use as a custom
        integer gadget edit hook (StringExtend->EditHook) for this gadget.
        GadTools will allocate the StringExtend->WorkBuffer for you.
        (defaults to NULL). (V37)
    STRINGA_ExitHelp (BOOL) - Set to TRUE to have the help-key cause an
        exit from the integer gadget.  You will then receive an
        IDCMP_GADGETUP event with Code = 0x5F (rawkey for help).
        (defaults to FALSE) (V37)
    STRINGA_Justification - Controls the justification of the contents of
        an integer gadget.  Choose one of STRINGLEFT, STRINGRIGHT, or
        STRINGCENTER (defaults to STRINGLEFT). (V37)
    STRINGA_ReplaceMode (BOOL) - If TRUE, this integer gadget is in
        replace-mode (defaults to FALSE (insert-mode)). (V37)

    LISTVIEW_KIND (scrolling list):
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE). (V39)
    GTLV_Top (WORD) - Top item visible in the listview.  This value
        will be made reasonable if out-of-range (defaults to 0). (V36)
    GTLV_MakeVisible (WORD) - Number of an item that should be forced
        within the visible area of the listview by doing minimal scrolling.
        This tag overrides GTLV_Top. (V39)
    GTLV_Labels (struct List *) - List of nodes whose ln_Name fields
        are to be displayed in the listview. (V36)
    GTLV_ReadOnly (BOOL) - If TRUE, then listview is read-only
        (defaults to FALSE). (V36)
    GTLV_ScrollWidth (UWORD) - Width of scroll bar for listview.
        Must be greater than zero (defaults to 16). (V36)
    GTLV_ShowSelected (struct Gadget *) - NULL to have the currently
        selected item displayed beneath the listview under V37 or with
        a highlight bar in V39. If not NULL, this is a pointer to
        an already-created GadTools STRING_KIND gadget to have an
        editable display of the currently selected item. If the tag is
        not present, the currently selected item will not be displayed.
        (V36)
    GTLV_Selected (UWORD) - Ordinal number of currently selected
        item, or ~0 to have no current selection (defaults to ~0). (V36)
    LAYOUTA_Spacing (UWORD) - Extra space to place between lines of
        listview (defaults to 0). (V36)
    GTLV_ItemHeight (UWORD) - The exact height of an item. This is
        normally useful for listviews that use the GTLV_CallBack
        rendering hook (defaults to ng->ng_TextAttr->ta_YSize). (V39)
    GTLV_CallBack (struct Hook *) - Callback hook for various listview
        operations. As of V39, the only callback supported is for custom
        rendering of individual items in the listview. The call back hook
        is called with:
        A0 - struct Hook *
        A1 - struct LVDrawMsg *
        A2 - struct Node *
        The callback hook *must* check the lvdm_MethodID field of the
        message and only do processing if it equals LV_DRAW. If any
        other value is passed, the callback hook must return LVCB_UNKNOWN
    GTLV_MaxPen (UWORD) - The maximum pen number used by rendering
        in a custom rendering callback hook. This is used to optimize
        the rendering and scrolling of the listview display (default is
        the maximum pen number used by all of TEXTPEN, BACKGROUNDPEN,
        FILLPEN, TEXTFILLPEN, and BLOCKPEN. (V39)

    MX_KIND (mutually exclusive, radio buttons):
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE). (V39)
    GTMX_Labels (STRPTR *) - Pointer to a NULL-terminated array of
        strings which are to be the labels beside each choice in a
        set of mutually exclusive gadgets. This tag is required. (V36)
    GTMX_Active (UWORD) - The ordinal number (counting from zero) of
        the initially active choice of an mx gadget (defaults to 0). (V36)
    GTMX_Spacing (UWORD) - The amount of space between each choice
        of a set of mutually exclusive gadgets.  This amount is added
        to the font height to produce the vertical shift between
        choices (defaults to 1). (V36)
    GTMX_Scaled (BOOL) - If true, then mx gadget imagery will be scaled
        to fit the gadget's width & height.  Otherwise, a fixed size of
        MXWIDTH by MXHEIGHT will be used. When setting this tag to TRUE,
        you should typically set the height of the gadget to be
        (ng.ng_TextAttr->ta_YSize + 1). (defaults to FALSE.) (V39)
    GTMX_TitlePlace - One of PLACETEXT_LEFT, PLACETEXT_RIGHT,
        PLACETEXT_ABOVE, or PLACETEXT_BELOW, indicating where the title
        of the gadget is to be displayed. Without this tag, the
        NewGadget.ng_GadgetText field is ignored for MX_KIND gadgets.
        (V39)
    LAYOUTA_Spacing - FOR COMPATIBILITY ONLY.  Use GTMX_Spacing instead.
        The number of extra pixels to insert between each choice of a
        mutually exclusive gadget.  This is added to the present gadget
        image height (9) to produce the true spacing between choices.
        (defaults to FontHeight-8, which is zero for 8-point font users).
        (V36)

    NUMBER_KIND (read-only numeric):
    GTNM_Number (LONG) - A signed long integer to be displayed as a read-only
        number (defaults to 0). (V36)
    GTNM_Border (BOOL) - If TRUE, this flag asks for a recessed border to
        be placed around the gadget. (V36)
    GTNM_FrontPen (UBYTE) - The pen to use when rendering the number
        (defaults to DrawInfo->dri_Pens[TEXTPEN]). (V39)
    GTNM_BackPen (UBYTE) - The pen to use when rendering the background
        of the number (defaults to leaving the background untouched).
        (V39)
    GTNM_Justification (UBYTE) - Determines how the number is rendered
        within the gadget box. GTJ_LEFT will make the rendering be
        flush with the left side of the gadget, GTJ_RIGHT will make it
        flush with the right side, and GTJ_CENTER will center the number
        within the gadget box. Under V39, using this tag also required
        using {GTNM_Clipped, TRUE}, otherwise the text would not show
        up in the gadget. This has been fixed in V40.
        (defaults to GTJ_LEFT). (V39)
    GTNM_Format (STRPTR) - C-Style formatting string to apply on the number
        before display. Be sure to use the 'l' (long) modifier. This string
        is processed using exec.library/RawDoFmt(), so refer to that
        function for details. (defaults to "%ld") (V39)
    GTNM_MaxNumberLen (ULONG) - Maximum number of bytes that can be
        generated by applying the GTNM_Format formatting string to the
        number (excluding the NULL terminator). (defaults to 10). (V39)
    GTNM_Clipped (BOOL) - Determine whether text should be clipped to
        the gadget dimensions (defaults to FALSE for gadgets without
        borders, TRUE for gadgets with borders). (V39)

    PALETTE_KIND (color selection):
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE). (V36)
    GTPA_Depth (UWORD) - Number of bitplanes in the palette
        (defaults to 1). (V36)
    GTPA_Color (UBYTE) - Initially selected color of the palette. This
        number is a pen number, and not the ordinal color number within
        the palette gadget itself. (defaults to 1). (V36)
    GTPA_ColorOffset (UBYTE) - First color to use in palette
        (defaults to 0). (V36)
    GTPA_IndicatorWidth (UWORD) - The desired width of the current-color
        indicator, if you want one to the left of the palette. (V36)
    GTPA_IndicatorHeight (UWORD) - The desired height of the current-color
        indicator, if you want one above the palette. (V36)
    GTPA_ColorTable (UBYTE *) - Pointer to a table of pen numbers
        indicating  which colors should be used and edited by the palette
        gadget. This array must contain as many entries as there are
        colors displayed in the palette gadget. The array provided with
        this tag must remain valid for the life of the gadget or until a
        new table is provided. (default is NULL, which causes a 1-to-1
        mapping of pen numbers). (V39)
    GTPA_NumColors (UWORD) - Number of colors to display in the palette
        gadget. This override GTPA_Depth and allows numbers which aren't
        powers of 2. (defaults to 2) (V39)

    SCROLLER_KIND (for scrolling through areas or lists):
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE). (V36)
    GA_RelVerify (BOOL) - Hear every IDCMP_GADGETUP event from scroller
        (defaults to FALSE). (V36)
    GA_Immediate (BOOL) - Hear every IDCMP_GADGETDOWN event from scroller
        (defaults to FALSE). (V36)
    GTSC_Top (WORD) - Top visible in area scroller represents
        (defaults to 0). (V36)
    GTSC_Total (WORD) - Total in area scroller represents
        (defaults to 0). (V36)
    GTSC_Visible (WORD) - Number visible in scroller (defaults to 2). (V36)
    GTSC_Arrows (UWORD) - Asks for arrows to be attached to the scroller.
        The value supplied will be taken as the width of each arrow button
        for a horizontal scroller, or the height of each button for a
        vertical scroller (the other dimension will match the whole
        scroller). (V36)
    PGA_Freedom - Whether scroller is horizontal or vertical.
        Choose LORIENT_VERT or LORIENT_HORIZ (defaults to LORIENT_HORIZ).
        (V36)

    SLIDER_KIND (to indicate level or intensity):
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE). (V36)
    GA_RelVerify (BOOL) - If you want to hear each slider IDCMP_GADGETUP
        event (defaults to FALSE). (V36)
    GA_Immediate (BOOL) - If you want to hear each slider IDCMP_GADGETDOWN
        event (defaults to FALSE). (V36)
    GTSL_Min (WORD) - Minimum level for slider (defaults to 0). (V36)
    GTSL_Max (WORD) - Maximum level for slider (defaults to 15). (V36)
    GTSL_Level (WORD) - Current level of slider (defaults to 0). (V36)
    GTSL_MaxLevelLen (UWORD) - Maximum length in characters of level string
        when rendered beside slider (defaults to 2). (V36)
    GTSL_LevelFormat (STRPTR) - C-Style formatting string for slider
        level.  Be sure to use the 'l' (long) modifier.  This string
        is processed using exec.library/RawDoFmt(), so refer to that
        function for details. (defaults to "%ld"). (V36)
    GTSL_LevelPlace - One of PLACETEXT_LEFT, PLACETEXT_RIGHT,
        PLACETEXT_ABOVE, or PLACETEXT_BELOW, indicating where the level
        indicator is to go relative to slider (default to PLACETEXT_LEFT).
        (V36)
    GTSL_DispFunc ( LONG (*function)(struct Gadget *, WORD) ) - Function
        to calculate level to be displayed.  A number-of-colors slider
        might want to set the slider up to think depth, and have a
        (1 << n) function here.  Defaults to none.  Your function must
        take a pointer to gadget as the first parameter, the level
        (a WORD) as the second, and return the result as a LONG. (V36)
    GTSL_MaxPixelLen (ULONG) - Indicates the maximum pixel size used up
        by the level display for any value of the slider. This is mostly
        useful when dealing with proportional fonts. (defaults to
        FontWidth*MaxLevelLen). (V39)
    GTSL_Justification (UBYTE) - Determines how the level display is to
        be justified within its alotted space. Choose one of GTJ_LEFT,
        GTJ_RIGHT, or GTJ_CENTER (defaults to GTJ_LEFT). (V39)
    PGA_Freedom - Set to LORIENT_VERT or LORIENT_HORIZ to have a
        vertical or horizontal slider (defaults to LORIENT_HORIZ). (V36)

    STRING_KIND (text-entry):
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (defaults to FALSE). (V36)
    GA_Immediate (BOOL) - Hear IDCMP_GADGETDOWN events from string
        gadget (defaults to FALSE). (V39)
    GA_TabCycle (BOOL) - Set to TRUE so that pressing <TAB> or <Shift-TAB>
        will activate the next or previous such gadget. (defaults to TRUE,
        unlike regular Intuition string gadgets which default to FALSE).
        (V37)
    GTST_String (STRPTR) - The initial contents of the string gadget,
        or NULL (default) if string is to start empty. (V36)
    GTST_MaxChars (UWORD) - The maximum number of characters that the
        string gadget is to hold. (V36)
    GTST_EditHook (struct Hook *) - Hook to use as a custom string gadget
        edit hook (StringExtend->EditHook) for this gadget. GadTools will
        allocate the StringExtend->WorkBuffer for you. (defaults to NULL).
        (V37)
    STRINGA_ExitHelp (BOOL) - Set to TRUE to have the help-key cause an
        exit from the string gadget.  You will then receive an
        IDCMP_GADGETUP event with Code = 0x5F (rawkey for help).
        (V37)
    STRINGA_Justification - Controls the justification of the contents of
        a string gadget.  Choose one of STRINGLEFT, STRINGRIGHT, or
        STRINGCENTER (defaults to STRINGLEFT). (V37)
    STRINGA_ReplaceMode (BOOL) - If TRUE, this string gadget is in
        replace-mode (defaults to FALSE (insert-mode)). (V37)

    TEXT_KIND (read-only text):
    GTTX_Text - Pointer to a NULL terminated string to be displayed,
        as a read-only text-display gadget, or NULL. (defaults to NULL)
        (V36)
    GTTX_CopyText (BOOL) -	This flag instructs the text-display gadget
        to copy the supplied text string, instead of using only
        pointer to the string.  This only works for the initial value
        of GTTX_Text set at CreateGadget() time.  If you subsequently
        change GTTX_Text, the new text will be referenced by pointer,
        not copied.  Do not use this tag with a NULL GTTX_Text. (V37)
    GTTX_Border (BOOL) - If TRUE, this flag asks for a recessed
        border to be placed around the gadget. (V36)
    GTTX_FrontPen (UBYTE) - The pen to use when rendering the text
        (defaults to DrawInfo->dri_Pens[TEXTPEN]). (V39)
    GTTX_BackPen (UBYTE) - The pen to use when rendering the background
        of the text (defaults to leaving the background untouched).
        (V39)
    GTTX_Justification (UBYTE) - Determines how the text is rendered
        within the gadget box. GTJ_LEFT will make the rendering be
        flush with the left side of the gadget, GTJ_RIGHT will make it
        flush with the right side, and GTJ_CENTER will center the text
        within the gadget box. Under V39, using this tag also required
        using {GTNM_Clipped, TRUE}, otherwise the text would not show
        up in the gadget. This has been fixed in V40.
        (defaults to GTJ_LEFT). (V39)
    GTTX_Clipped (BOOL) - Determine whether text should be clipped to
        the gadget dimensions (defaults to FALSE for gadgets without
        borders, TRUE for gadgets with borders). (V39)

   RESULT
    gad - pointer to the new gadget, or NULL if the allocation failed
          or if previous was NULL.

   NOTES
    Note that the ng_VisualInfo and ng_TextAttr fields of the
    NewGadget structure must be set to valid VisualInfo and
    TextAttr pointers, or this function will fail.

    Starting with V37, string and integer gadgets have the GFLG_TABCYCLE
    feature automatically.  If the user presses Tab or Shift-Tab while
    in a string or integer gadget, the next or previous one in
    sequence will be activated.  You will hear an IDCMP_GADGETUP message
    with a code of 0x09.  Use {GA_TabCycle, FALSE} to supress this.

   SEE ALSO
    FreeGadgets(), GT_SetGadgetAttrs(), GetVisualInfo(),
    <libraries/gadtools.h>


gadtools.library/CreateMenusA

   NAME
    CreateMenusA -- allocate and fill out a menu structure. (V36)
    CreateMenus -- varargs stub for CreateMenus(). (V36)

   SYNOPSIS
    menu = CreateMenusA(newmenu, tagList)
    D0                  A0       A1

    struct Menu *CreateMenusA(struct NewMenu *, struct TagItem *);

    menu = CreateMenus(newmenu, firsttag, ...)

    struct Menu *CreateMenus(struct NewMenu *, Tag, ...);

   FUNCTION
    CreateMenusA() allocates and initializes a complete menu
    structure based on the supplied array of NewMenu structures.
    Optionally, CreateMenusA() can allocate and initialize a complete
    set of menu items and sub-items for a single menu title.  This
    is dictated by the contents of the array of NewMenus.

   INPUTS
    newmenu - pointer to an array of initialized struct NewMenus.
    tagList - pointer to an array of tags providing optional extra
          parameters, or NULL.

   TAGS
    GTMN_FrontPen (UBYTE) - Pen number to be used for menu text.
        (Under V39 and higher, this tag also exists for LayoutMenusA()
        and LayoutMenuItemsA()).  (defaults to zero).
    GTMN_FullMenu (BOOL) - Requires that the NewMenu specification
        describes a complete menu strip, not a fragment.  If a fragment
        is found, CreateMenusA() will fail with a secondary error of
        GTMENU_INVALID.  (defaults to FALSE). (V37)
    GTMN_SecondaryError (ULONG *) - Supply a pointer to a NULL-initialized
        ULONG to receive a descriptive error code.  Possible values:
        GTMENU_INVALID - NewMenu structure describes an illegal
            menu.  (CreateMenusA() will fail with a NULL result).
        GTMENU_TRIMMED - NewMenu structure has too many menus, items,
            or subitems (CreateMenusA() will succeed, returning a
            trimmed-down menu structure).
        GTMENU_NOMEM - CreateMenusA() ran out of memory.
        (V37)

   RESULT
    menu - pointer to the resulting initialized menu structure (or
              the resulting FirstItem), with all the links for menu items
              and subitems in place.
              The result will be NULL if CreateMenusA() could not allocate
              memory for the menus, or if the NewMenu array had an
              illegal arrangement (eg. NM_SUB following NM_TITLE).
              (see also the GTMN_SecondaryError tag above).

   NOTES
    The strings you supply for menu text are not copied, and must
    be preserved for the life of the menu.
    The resulting menus have no positional information.  You will
    want to call LayoutMenusA() (or LayoutMenuItemsA()) to supply that.
    CreateMenusA() automatically provides you with a UserData field
    for each menu, menu-item or sub-item.  Use the GTMENU_USERDATA(menu)
    or GTMENUITEM_USERDATA(menuitem) macro to access it.

   BUGS
    Prior to V39, if you put images into menus using IM_ITEM
    or IM_SUB for a NewMenu->nm_Type, the image supplied had to
    be an ordinary struct Image.  Starting with V39, you can use
    boopsi images.

   SEE ALSO
    LayoutMenusA(), FreeMenus(), gadtools.h/GTMENU_USERDATA(),
    gadtools.h/GTMENUITEM_USERDATA()


gadtools.library/DrawBevelBoxA

   NAME
    DrawBevelBoxA -- draw a bevelled box. (V36)
    DrawBevelBox -- varargs stub for DrawBevelBoxA(). (V36)

   SYNOPSIS
    DrawBevelBoxA(rport, left, top, width, height, tagList);
                  A0     D0    D1   D2     D3      A1

    VOID DrawBevelBoxA(struct RastPort *, WORD, WORD, WORD, WORD,
                       struct TagItem *taglist);

    DrawBevelBox(rport, left, top, width, height, firsttag, ...);

    VOID DrawBevelBox(struct RastPort *, WORD, WORD, WORD, WORD,
                      Tag, ...);

   FUNCTION
    This function renders a bevelled box of specified dimensions
    and type into the supplied RastPort.

   INPUTS
    rport - RastPort into which the box is to be drawn.
    left - left edge of the box.
    top - top edge of the box.
    width - width of the box.
    height - height of the box.
    tagList - pointer to an array of tags providing extra parameters

   TAGS
    GTBB_Recessed (BOOL) - Set to anything for a recessed-looking box.
            If absent, the box defaults, it would be raised. (V36)

    GTBB_FrameType (ULONG) - Determines what kind of box this function
            renders. BBFT_BUTTON generates a box like what is
            used around GadTools BUTTON_KIND gadgets. BBFT_RIDGE
            generates a box like what is used around GadTools
            STRING_KIND gadgets. Finally, BBFT_ICONDROPBOX
            generates a box suitable for a standard icon drop
            box imagery. (defaults to BBFT_BUTTON). (V39)

    GT_VisualInfo (APTR) - You MUST supply the value you obtained
            from an earlier call to GetVisualInfoA() with this
            tag. (V36)

   NOTES
    DrawBevelBox() is a rendering operation, not a gadget. That
    means you must refresh it at the appropriate time, like any
    other rendering operation.

   SEE ALSO
    GetVisualInfoA(), <libraries/gadtools.h>


gadtools.library/FreeGadgets

   NAME
    FreeGadgets -- free a linked list of gadgets. (V36)

   SYNOPSIS
    FreeGadgets(glist)
                A0

    VOID FreeGadgets(struct Gadget *glist);
                     A0

   FUNCTION
    Frees any GadTools gadgets found on the linked list of gadgets
    beginning with the specified one.  Frees all the memory that was
    allocated by CreateGadgetA().  This function will return safely
    with no action if it receives a NULL parameter.

   INPUTS
    glist - pointer to first gadget in list to be freed.

   SEE ALSO
    CreateGadgetA()


gadtools.library/FreeMenus

   NAME
    FreeMenus -- frees memory allocated by CreateMenusA(). (V36)

   SYNOPSIS
    FreeMenus(menu)
              A0

    VOID FreeMenus(struct Menu *);

   FUNCTION
    Frees the menus allocated by CreateMenusA().  It is safe to
    call this function with a NULL parameter.

   INPUTS
    menu - pointer to menu structure (or first MenuItem) obtained
           from CreateMenusA().

   SEE ALSO
    CreateMenusA()


gadtools.library/FreeVisualInfo

   NAME
    FreeVisualInfo -- return any resources taken by GetVisualInfo. (V36)

   SYNOPSIS
    FreeVisualInfo(vi)
                   A0

    VOID FreeVisualInfo(APTR);

   FUNCTION
    FreeVisualInfo() returns any memory or other resources that
    were allocated by GetVisualInfoA().  You should only call this function
    once you are done with using the gadgets (i.e. after CloseWindow()),
    but while the screen is still valid (i.e. before CloseScreen() or
    UnlockPubScreen()).

   INPUTS
    vi - pointer that was obtained by calling GetVisualInfoA(). This
         value may be NULL.

   SEE ALSO
    GetVisualInfoA()


gadtools.library/GetVisualInfoA

   NAME
    GetVisualInfoA -- get information GadTools needs for visuals. (V36)
    GetVisualInfo -- varargs stub for GetVisualInfoA(). (V36)

   SYNOPSIS
    vi = GetVisualInfoA(screen, tagList)
    D0                  A0      A1

    APTR vi = GetVisualInfoA(struct Screen *, struct TagItem *);

    vi = GetVisualInfo(screen, firsttag, ...)

    APTR vi = GetVisualInfo(struct Screen *, Tag, ...);

   FUNCTION
    Get a pointer to a (private) block of data containing various bits
    of information that GadTools needs to ensure the best quality
    visuals.  Use the result in the NewGadget structure of any gadget
    you create, or as a parameter to the various menu calls.  Once the
    gadgets/menus are no longer needed (after the last CloseWindow),
    call FreeVisualInfo().

   INPUTS
    screen - pointer to the screen you will be opening on. This parameter
         may be NULL, in which case this function fails.
    tagList - pointer to an array of tags providing optional extra
          parameters, or NULL.

   TAGS
    There are currently no tags defined for this function.

   RESULT
    vi - pointer to private data, or NULL for failure

   SEE ALSO
    FreeVisualInfo(), intuition/LockPubScreen(),
    intuition/UnlockPubScreen()


gadtools.library/GT_BeginRefresh

   NAME
    GT_BeginRefresh -- begin refreshing friendly to GadTools. (V36)

   SYNOPSIS
    GT_BeginRefresh(win)
                    A0

    VOID GT_BeginRefresh(struct Window *);

   FUNCTION
    Invokes the intuition.library/BeginRefresh() function in a manner
    friendly to the Gadget Toolkit.  This function call permits the
    GadTools gadgets to refresh themselves at the correct time.
    Call GT_EndRefresh() function when done.

   INPUTS
    win - pointer to Window structure for which a IDCMP_REFRESHWINDOW
          IDCMP event was received.

   NOTES
    The nature of GadTools precludes the use of the IDCMP flag
    WFLG_NOCAREREFRESH.  You must handle IDCMP_REFRESHWINDOW events
    in at least the minimal way, namely:

        case IDCMP_REFRESHWINDOW:
            GT_BeginRefresh(win);
            GT_EndRefresh(win, TRUE);
            break;

   SEE ALSO
    intuition.library/BeginRefresh()


gadtools.library/GT_EndRefresh

   NAME
    GT_EndRefresh -- end refreshing friendly to GadTools. (V36)

   SYNOPSIS
    GT_EndRefresh(win, complete)
                  A0   D0

    VOID GT_EndRefresh(struct Window *, BOOL complete);

   FUNCTION
    Invokes the intuition.library/EndRefresh() function in a manner
    friendly to the Gadget Toolkit.  This function call permits
    GadTools gadgets to refresh themselves at the correct time.
    Call this function to EndRefresh() when you have used
    GT_BeginRefresh().

   INPUTS
    win - pointer to Window structure for which a IDCMP_REFRESHWINDOW
          IDCMP event was received.
    complete - TRUE when done with refreshing.

   SEE ALSO
    intuition.library/EndRefresh()


gadtools.library/GT_FilterIMsg

   NAME
    GT_FilterIMsg -- filter an IntuiMessage through GadTools. (V36)

   SYNOPSIS
    modimsg = GT_FilterIMsg(imsg)
    D0                      A1

    struct IntuiMessage *GT_FilterIMsg(struct IntuiMessage *);

   FUNCTION
    NOTE WELL:  Extremely few programs will actually need this function.
    You almost certainly should be using GT_GetIMsg() and GT_ReplyIMsg()
    only, and not GT_FilterIMsg() and GT_PostFilterIMsg().

    GT_FilterIMsg() takes the supplied IntuiMessage and asks the
    Gadget Toolkit to consider and possibly act on it.  Returns
    NULL if the message was only of significance to a GadTools gadget
    (i.e. not to you), else returns a pointer to a modified IDCMP
    message, which may contain additional information.

    You should examine the Class, Code, and IAddress fields of
    the returned message to learn what happened.  Do not make
    interpretations based on the original imsg.

    You should use GT_PostFilterIMsg() to revert to the original
    IntuiMessage once you are done with the modified one.

   INPUTS
    imsg - an IntuiMessage you obtained from a Window's UserPort.

   RESULT
    modimsg - a modified IntuiMessage, possibly with extra information
              from GadTools, or NULL. When NULL, the message passed in to
          the function should be sent back to Intuition via ReplyMsg()

   NOTES
    Starting with V39, this function actually expects and returns
    pointers to ExtIntuiMessage structures, but the prototype was not
    changed for source code compatibility with older software.

   WARNING
    If this function returns NULL, you must call ReplyMsg() on the
    IntuiMessage you passed in to GT_FilterIMsg(). That is, if the
    message was processed by the toolkit you must reply this message
    to Intuition since gadtools will not do this automatically.

   SEE ALSO
    GT_GetIMsg(), GT_PostFilterIMsg()


gadtools.library/GT_GetGadgetAttrsA

   NAME
    GT_GetGadgetAttrsA -- request the attributes of a GadTools gadget. (V39)
    GT_GetGadgetAttrs -- varargs stub for GT_GetGadgetAttrsA(). (V39)

   SYNOPSIS
    numProcessed = GT_GetGadgetAttrsA(gad, win, req, taglist)
                                      A0   A1   A2   A3

    LONG GT_GetGadgetAttrsA(struct Gadget *, struct Window *,
                            struct Requester *, struct TagItem *);

    numProcessed = GT_GetGadgetAttrs(gad, win, req, firsttag, ...)

    LONG GT_GetGadgetAttrs(struct Gadget *, struct Window *,
                              struct Requester *, Tag, ...);

   FUNCTION
    Retrieve the attributes of the specified gadget, according to the
    attributes chosen in the tag list.  For each entry in the tag list,
    ti_Tag identifies the attribute, and ti_Data is a pointer to
    the long variable where you wish the result to be stored.

   INPUTS
    gad - pointer to the gadget in question. May be NULL, in which case
          this function returns 0
    win - pointer to the window containing the gadget.
    req - reserved for future use, should always be NULL
    taglist - pointer to TagItem list.

   TAGS
    BUTTON_KIND:
    GA_Disabled (BOOL) - TRUE if this gadget is disabled,
        FALSE otherwise. (V39)

    CHECKBOX_KIND:
    GA_Disabled (BOOL) - TRUE if this gadget is disabled,
        FALSE otherwise. (V39)
    GTCB_Checked (BOOL) - TRUE if this gadget is currently checked,
        FALSE otherwise. (V39)

    CYCLE_KIND:
    GA_Disabled (BOOL) - TRUE if this gadget is disabled,
        FALSE otherwise. (V39)
    GTCY_Active (UWORD) - The ordinal number (counting from zero) of
        the active choice of a cycle gadget. (V39)
    GTCY_Labels (STRPTR *) - The NULL-terminated array of strings
        that are the choices offered by the cycle gadget. (V39)

    INTEGER_KIND:
    GA_Disabled (BOOL) - TRUE if this gadget is disabled,
        FALSE otherwise. (V39)
    GTIN_Number (ULONG) - The contents of the integer gadget. (V39)

    LISTVIEW_KIND:
    GA_Disabled (BOOL) - TRUE if this gadget is disabled,
        FALSE otherwise. (V39)
    GTLV_Top (WORD) - Ordinal number of the top item visible
        in the listview. (V39)
    GTLV_Labels (struct List *) - The list of nodes whose ln_Name fields
        are displayed in the listview. (V39)
    GTLV_Selected (UWORD) - Ordinal number of currently selected
        item. Returns ~0 if no item is selected. (V39)

    MX_KIND:
    GA_Disabled (BOOL) - TRUE if this gadget is disabled,
        FALSE otherwise. (V39)
    GTMX_Active (UWORD) - The ordinal number (counting from zero) of
        the active choice of an mx gadget. (V39)

    NUMBER_KIND:
    GTNM_Number - The signed long integer that is displayed in
        the read-only number. (V39)

    PALETTE_KIND:
    GA_Disabled (BOOL) - TRUE if this gadget is disabled,
        FALSE otherwise. (V39)
    GTPA_Color (UBYTE) - The selected color of the palette. (V39)
    GTPA_ColorOffset (UBYTE) - First color used in palette. (V39)
    GTPA_ColorTable (UBYTE *) - Pointer to a table of pen numbers
        indicating  which colors should be used and edited by the palette
        gadget. May be NULL, which causes a 1-to-1 mapping of pen numbers.
        (V39)

    SCROLLER_KIND:
    GA_Disabled (BOOL) - TRUE if this gadget is disabled,
        FALSE otherwise. (V39)
    GTSC_Top (WORD) - Top visible in scroller. (V39)
    GTSC_Total (WORD) - Total in scroller area. (V39)
    GTSC_Visible (WORD) - Number visible in scroller. (V39)

    SLIDER_KIND:
    GA_Disabled (BOOL) - TRUE if this gadget is disabled,
        FALSE otherwise. (V39)
    GTSL_Min (WORD) - Minimum level for slider. (V39)
    GTSL_Max (WORD) - Maximum level for slider. (V39)
    GTSL_Level (WORD) - Current level of slider. (V39)

    STRING_KIND:
    GA_Disabled (BOOL) - TRUE if this gadget is disabled,
        FALSE otherwise. (V39)
    GTST_String (STRPTR) - Returns a pointer to the string gadget's
        buffer. (V39)

    TEXT_KIND:
    GTTX_Text - Pointer to the string to be displayed in the
        read-only text-display gadget. (V39)

   RESULT
    numProcessed - the number of attributes successfully filled in.

   EXAMPLE
        long top = 0;
        long selected = 0;
        long result;
        result = GT_GetGadgetAttrs( listview_gad, win, NULL,
            GTLV_Top, &top,
            GTLV_Selected, &selected,
            TAG_DONE );
        if ( result != 2 )
        {
            printf( "Something's wrong!" );
        }

   WARNING
    The pointers you provide within the tag list to store the return
    values MUST POINT TO LONGWORDS. That is, even if the type of a
    return value is defined as (UWORD *), you must pass a pointer to
    a longword of memory.

   SEE ALSO
    GT_SetGadgetAttrs()


gadtools.library/GT_GetIMsg

   NAME
    GT_GetIMsg -- get an IntuiMessage, with GadTools processing. (V36)

   SYNOPSIS
    imsg = GT_GetIMsg(intuiport)
    D0                A0

    struct IntuiMessage *GT_GetIMsg(struct MsgPort *);

   FUNCTION
    Use GT_GetIMsg() in place of the usual exec.library/GetMsg() when
    reading IntuiMessages from your window's UserPort.  If needed,
    the GadTools dispatcher will be invoked, and suitable processing
    will be done for gadget actions.  This function returns a pointer
    to a modified IntuiMessage (which is a copy of the original,
    possibly with some supplementary information from GadTools).
    If there are no messages (or if the only messages are meaningful
    only to GadTools, NULL will be returned.

   INPUTS
    intuiport - the Window->UserPort of a window that is using the
                Gadget Toolkit.

   RESULT
    imsg - pointer to modified IntuiMessage, or NULL if there are
           no applicable messages.

   NOTES
    Be sure to use GT_ReplyIMsg() and not exec.library/ReplyMsg() on
    messages obtained with GT_GetIMsg().
    If you intend to do more with the resulting message than read
    its fields, act on it, and reply it, you may find GT_FilterIMsg()
    more appropriate.

    Starting with V39, this function actually returns a pointer to an
    ExtIntuiMessage structure, but the prototype was not changed for
    source code compatibility with older software.

   SEE ALSO
    GT_ReplyIMsg(), GT_FilterIMsg()


gadtools.library/GT_PostFilterIMsg

   NAME
    GT_PostFilterIMsg -- return the unfiltered message after
                         GT_FilterIMsg() was called, and clean up. (V36)

   SYNOPSIS
    imsg = GT_PostFilterIMsg(modimsg)
    D0                       A1

    struct IntuiMessage *GT_PostFilterIMsg(struct IntuiMessage *);

   FUNCTION
    NOTE WELL:  Extremely few programs will actually need this function.
    You almost certainly should be using GT_GetIMsg() and GT_ReplyIMsg()
    only, and not GT_FilterIMsg() and GT_PostFilterIMsg().

    Performs any clean-up necessitated by a previous call to
    GT_FilterIMsg().  The original IntuiMessage is now yours to handle.
    Do not interpret the fields of the original IntuiMessage, but
    rather use only the one you got from GT_FilterIMsg().  You
    may only do message related things at this point, such as queueing
    it up or replying it.  Since you got the message with
    exec.library/GetMsg(), your responsibilities do include replying
    it with exec.library/ReplyMsg(). This function may be safely
    called with a NULL parameter.

   INPUTS
    modimsg - a modified IntuiMessage obtained with GT_FilterIMsg(),
              or NULL in which case this function does nothing and
              returns NULL

   RESULT
    imsg - a pointer to the original IntuiMessage, if GT_FilterIMsg()
           returned non-NULL.

   NOTES
    Be sure to use exec.library/ReplyMsg() on the original IntuiMessage
    you obtained with GetMsg(), (which is the what you passed to
    GT_FilterIMsg()), and not on the parameter of this function.

    Starting with V39, this function actually expects and returns
    pointers to ExtIntuiMessage structures, but the prototype was not
    changed for source code compatibility with older software.

   SEE ALSO
    GT_FilterIMsg()


gadtools.library/GT_RefreshWindow

   NAME
    GT_RefreshWindow -- refresh all GadTools gadgets in a window. (V36)

   SYNOPSIS
    GT_RefreshWindow(win, req)
                     A0   A1

    VOID GT_RefreshWindow(struct Window *, struct Requester *);

   FUNCTION
    Perform the initial refresh of all the GadTools gadgets you have
    created.  After you have opened your window, you must call this
    function.  Or, if you have opened your window without gadgets,
    you add the gadgets with intuition.library/AddGList(),
    refresh them using intuition.library/RefreshGList(), then call
    this function.
    You should not need this function at other times.

   INPUTS
    win - pointer to the Window containing GadTools gadgets.
    req - reserved for future use, should always be NULL

   SEE ALSO
    GT_BeginRefresh()


gadtools.library/GT_ReplyIMsg

   NAME
    GT_ReplyIMsg -- reply a message obtained with GT_GetIMsg(). (V36)

   SYNOPSIS
    GT_ReplyIMsg(imsg)
                 A1

    VOID GT_ReplyIMsg(struct IntuiMessage *);

   FUNCTION
    Reply a modified IntuiMessage obtained with GT_GetIMsg().
    If you use GT_GetIMsg(), use this function where you would normally
    have used exec.library/ReplyMsg().
    You may safely call this routine with a NULL pointer (nothing
    will be done).

   INPUTS
    imsg - a modified IntuiMessage obtained with GT_GetIMsg(), or NULL
           in which case this function does nothing

   NOTES
    When using GadTools, you MUST explicitly GT_ReplyIMsg()
    all messages you receive.  You cannot depend on CloseWindow()
    to handle messages you have not replied.

    Starting with V39, this function actually expects a pointer to an
    ExtIntuiMessage structure, but the prototype was not changed for
    source code compatibility with older software.

   SEE ALSO
    GT_GetIMsg()


gadtools.library/GT_SetGadgetAttrsA

   NAME
    GT_SetGadgetAttrsA -- change the attributes of a GadTools gadget. (V36)
    GT_SetGadgetAttrs -- varargs stub for GT_SetGadgetAttrsA(). (V36)

   SYNOPSIS
    GT_SetGadgetAttrsA(gad, win, req, tagList)
                       A0   A1   A2   A3

    VOID GT_SetGadgetAttrsA(struct Gadget *, struct Window *,
                            struct Requester *, struct TagItem *);

    GT_SetGadgetAttrs(gad, win, req, firsttag, ...)

    VOID GT_SetGadgetAttrs(struct Gadget *, struct Window *,
                           struct Requester *, Tag, ...);

   FUNCTION
    Change the attributes of the specified gadget, according to the
    attributes chosen in the tag list. If an attribute is not provided
    in the tag list, its value remains unchanged.

   INPUTS
    gad - pointer to the gadget in question. Starting with V39, this
          value may be NULL in which case this function does nothing
    win - pointer to the window containing the gadget. Starting with V39,
          this value may be NULL in which case the internal attributes of
          the gadgets are altered but no rendering occurs.
    req - reserved for future use, should always be NULL
    tagList - pointer to an array of tags providing optional extra
          parameters, or NULL.

   TAGS
    BUTTON_KIND:
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise.
        (V36)

    CHECKBOX_KIND:
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise.
        (V36)
    GTCB_Checked (BOOL) - State of checkbox. (V36)

    CYCLE_KIND:
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (V37)
    GTCY_Active (UWORD) - The ordinal number (counting from zero) of
        the active choice of a cycle gadget. (V36)
    GTCY_Labels (STRPTR *) - Pointer to NULL-terminated array of strings
        that are the choices offered by the cycle gadget. (V37)

    INTEGER_KIND:
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (V36)
    GTIN_Number (ULONG) - New value of the integer gadget (V36)

    LISTVIEW_KIND:
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (V39)
    GTLV_Top (WORD) - Top item visible in the listview.  This value
        will be made reasonable if out-of-range. (V36)
    GTLV_MakeVisible (WORD) - Number of an item that should be forced
        within the visible area of the listview by doing minimal scrolling.
        This tag overrides GTLV_Top. (V39)
    GTLV_Labels (struct List *) - List of nodes whose ln_Name fields
        are to be displayed in the listview.  Use a value of ~0 to
        "detach" your List from the display.  You must detach your list
        before modifying the List structure, since GadTools reserves
        the right to traverse it on another task's schedule.  When you
        are done, attach the list by using the tag pair
        {GTLV_Labels, list}. (V36)
    GTLV_Selected (UWORD) - Ordinal number of currently selected
        item. Starting with V39, you can provide ~0 to cause the currently
        selected item to be deselected. (V36)

    MX_KIND:
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (V39)
    GTMX_Active (UWORD) - The ordinal number (counting from zero) of
        the active choice of an mx gadget. (V36)

    NUMBER_KIND:
    GTNM_Number (LONG) - A signed long integer to be displayed in
        the number gadget. (V36)
    GTNM_FrontPen (UBYTE) - The pen to use when rendering the number. (V39)
    GTNM_BackPen (UBYTE) - The pen to use when rendering the background
        of the number. (V39)
    GTNM_Justification (UBYTE) - Determines how the number is rendered
        within the gadget box. GTJ_LEFT will make the rendering be
        flush with the left side of the gadget, GTJ_RIGHT will make it
        flush with the right side, and GTJ_CENTER will center the number
        within the gadget box. (V39)
    GTNM_Format (STRPTR) - C-Style formatting string to apply on the number
        before display. Be sure to use the 'l' (long) modifier. This string
        is processed using exec.library/RawDoFmt(), so refer to that
        function for details. (V39)

    PALETTE_KIND:
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (V36)
    GTPA_Color (UBYTE) - Selected color of the palette. This
        number is a pen number, and not the ordinal color number within
        the palette gadget itself. (V36)
    GTPA_ColorOffset (UBYTE) - First color to use in palette (V39)
    GTPA_ColorTable (UBYTE *) - Pointer to a table of pen numbers
        indicating  which colors should be used and edited by the palette
        gadget. This array must contain as many entries as there are
        colors displayed in the palette gadget. The array provided with
        this tag must remain valid for the life of the gadget or until a
        new table is provided. A NULL table pointer causes a 1-to-1
        mapping of pen numbers. (V39)

    SCROLLER_KIND:
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (V36)
    GTSC_Top (WORD) - Top visible in scroller. (V36)
    GTSC_Total (WORD) - Total in scroller area. (V36)
    GTSC_Visible (WORD) - Number visible in scroller. (V36)

    SLIDER_KIND:
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (V36)
    GTSL_Min (WORD) - Minimum level for slider. (V36)
    GTSL_Max (WORD) - Maximum level for slider. (V36)
    GTSL_Level (WORD) - Current level of slider. (V36)
    GTSL_LevelFormat (STRPTR) - C-Style formatting string for slider
        level.  Be sure to use the 'l' (long) modifier.  This string
        is processed using exec.library/RawDoFmt(), so refer to that
        function for details. (V39)
    GTSL_DispFunc ( LONG (*function)(struct Gadget *, WORD) ) - Function
        to calculate level to be displayed.  A number-of-colors slider
        might want to set the slider up to think depth, and have a
        (1 << n) function here.  Your function must
        take a pointer to gadget as the first parameter, the level
        (a WORD) as the second, and return the result as a LONG. (V39)
    GTSL_Justification (UBYTE) - Determines how the level display is to
        be justified within its alotted space. Choose one of GTJ_LEFT,
        GTJ_RIGHT, or GTJ_CENTER. (V39)

    STRING_KIND:
    GA_Disabled (BOOL) - Set to TRUE to disable gadget, FALSE otherwise
        (V36)
    GTST_String (STRPTR) - New contents of the string gadget,
        or NULL to reset the gadget to the empty state. (V36)

    TEXT_KIND:
    GTTX_Text - New NULL terminated string to be displayed in the text
        gadget. NULL means to clear the gadget. (V36)
    GTTX_FrontPen (UBYTE) - The pen to use when rendering the text. (V39)
    GTTX_BackPen (UBYTE) - The pen to use when rendering the background
        of the text. (V39)
    GTTX_Justification (UBYTE) - Determines how the text is rendered
        within the gadget box. GTJ_LEFT will make the rendering be
        flush with the left side of the gadget, GTJ_RIGHT will make it
        flush with the right side, and GTJ_CENTER will center the text
        within the gadget box. (V39)

   NOTES
    This function may not be called inside of a GT_BeginRefresh() /
    GT_EndRefresh() session.  (As always, restrict yourself to simple
    rendering functions).

   SEE ALSO
    GT_GetGadgetAttrs()


gadtools.library/LayoutMenuItemsA

   NAME
    LayoutMenuItemsA -- position all the menu items. (V36)
    LayoutMenuItems -- varargs stub for LayoutMenuItemsA(). (V36)

   SYNOPSIS
    success = LayoutMenuItemsA(menuitem, vi, tagList)
    D0                         A0        A1  A2

    BOOL LayoutMenuItemsA(struct MenuItem *, APTR, struct TagItem *);

    success = LayoutMenuItems(menuitem, vi, firsttag, ...)

    BOOL LayoutMenuItemsA(struct MenuItem *, APTR, Tag, ...);

   FUNCTION
    Lays out all the menu items and sub-items according to
    the supplied visual information and tag parameters.  You would use this
    if you used CreateMenusA() to make a single menu-pane (with sub-items,
    if any), instead of a whole menu strip.
    This routine attempts to columnize and/or shift the MenuItems in
    the event that a menu would be too tall or too wide.

   INPUTS
    menuitem - pointer to first MenuItem in a linked list of
               items.
    vi - pointer returned by GetVisualInfoA().
    tagList - pointer to an array of tags providing optional extra
          parameters, or NULL.

   TAGS
    GTMN_Menu (struct Menu *) - Pointer to the Menu structure whose
        FirstItem is the MenuItem supplied above.  If the menu items are
        such that they need to be columnized or shifted, the Menu
        structure is needed to perform the complete calculation.
        It is suggested you always provide this information. (V36)

    For the following tags, please see the description under
    LayoutMenusA().  Their behavior is identical when used in
    LayoutMenuItemsA().

        GTMN_TextAttr
        GTMN_NewLookMenus
        GTMN_Checkmark
        GTMN_AmigaKey
        GTMN_FrontPen

   RESULT
    success - TRUE if successful, FALSE otherwise (signifies that
              the TextAttr wasn't openable).

   BUGS
    If a menu ends up being wider than the whole screen, it will
    run off the right-hand side.

   SEE ALSO
    CreateMenusA(), GetVisualInfoA()


gadtools.library/LayoutMenusA

   NAME
    LayoutMenusA -- position all the menus and menu items. (V36)
    LayoutMenus -- varargs stub for LayoutMenusA(). (V36)

   SYNOPSIS
    success = LayoutMenusA(menu, vi, tagList)
    D0                     A0    A1  A2

    BOOL LayoutMenusA(struct Menu *, APTR, struct TagItem *);

    success = LayoutMenus(menu, vi, firsttag, ...)

    BOOL LayoutMenus(struct Menu *, APTR, Tag, ...);

   FUNCTION
    Lays out all the menus, menu items and sub-items in the supplied
    menu according to the supplied visual information and tag parameters.
    This routine attempts to columnize and/or shift the MenuItems in
    the event that a menu would be too tall or too wide.

   INPUTS
    menu - pointer to menu obtained from CreateMenusA().
    vi - pointer returned by GetVisualInfoA().
    tagList - pointer to an array of tags providing optional extra
          parameters, or NULL.

   TAGS
    GTMN_TextAttr (struct TextAttr *) - Text Attribute to use for
        menu-items and sub-items.  If not supplied, the screen's
        font will be used.  This font must be openable via OpenFont()
        when this function is called. (V36)
    GTMN_NewLookMenus (BOOL) - If you ask for WA_NewLookMenus for your
        window, you should ask for this tag as well.  This informs GadTools
        to use the appropriate checkmark, Amiga-key, and colors. (V39)
    GTMN_Checkmark (struct Image *) - If you are using a custom image for a
        checkmark (WA_Checkmark), also pass it to GadTools, so it can lay
        the menus out accordingly. (V39)
    GTMN_AmigaKey (struct Image *) - If you are using a custom image for
        the Amiga-key in menus (WA_AmigaKey), also pass it to GadTools, so
        it can lay the menus out accordingly. (V39)
    GTMN_FrontPen (ULONG) - This tag has existed for CreateMenus(), but now
        LayoutMenusA() has it too.  If a legitimate pen number is supplied,
        it is used for coloring the menu items (in preference to
        anything passed to CreateMenus()).  If GTMN_NewLookMenus
        has been specified, this tag defaults to using the
        screen's BARDETAILPEN, else it defaults to "do nothing".
        For visual consistency, we recommend you omit this tag in all
        functions, and let the defaults be used. (V39)

   RESULT
    success - TRUE if successful, FALSE otherwise (signifies that
              the TextAttr wasn't openable).

   NOTES
    When using this function, there is no need to also call
    LayoutMenuItemsA().

   BUGS
    If a menu ends up being wider than the whole screen, it will
    run off the right-hand side.

   SEE ALSO
    CreateMenusA(), GetVisualInfoA()


gameport.doc

     GPD_ASKCTYPE
     GPD_ASKTRIGGER
     GPD_READEVENT
     GPD_SETCTYPE
     GPD_SETTRIGGER


gameport.device/GPD_READEVENT

   NAME
    GPD_READEVENT -- Return the next game port event.

   FUNCTION
    Read game port events from the game port and put them in the
    data area of the iORequest.  If there are no pending game port
    events, this command will not be satisfied, but if there are
    some events, but not as many as can fill IO_LENGTH, the
    request will be satisfied with those currently available.

   IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Device	preset by the call to OpenDevice
    io_Unit		preset by the call to OpenDevice
    io_Command	GPD_READEVENT
    io_Flags	IOB_QUICK set if quick I/O is possible
    io_Length	the size of the io_Data area in bytes: there
            are sizeof(inputEvent) bytes per input event.
    io_Data		a buffer area to fill with input events.  The
            fields of the input event are:
        ie_NextEvent
            links the events returned
        ie_Class
            is IECLASS_RAWMOUSE
        ie_SubClass
            is 0 for the left, 1 for the right game port
        ie_Code
            contains any gameport button reports.  No
            report is indicated by the value 0xff.
        ie_Qualifier
            only the relative and button bits are set
        ie_X, ie_Y
            the x and y values for this report, in either
            relative or absolute device dependent units.
        ie_TimeStamp
            the delta time since the last report, given
            not as a standard timestamp, but as the frame
            count in the TV_SECS field.

   RESULTS
    This function sets the error field in the iORequest, and fills
    the iORequest with the next game port events (but not partial
    events).

   SEE ALSO
    gameport.device/GPD_SETCTYPE, gameport.device/GPD_SETTRIGGER


getfile_gc.doc

     --datasheet--
     GETFILE_GetClass()


getfile.gadget/--datasheet--

   NAME
       getfile_gc -- create getfile BOOPSI objects

   SUPERCLASS
       gadgetclass

   DESCRIPTION
       The getfile gadget class is used to get files and drawers from a file
       requester in an easy and consistent way.  It consists of two button
       gadgets, one read-only and one popfile/popdrawer button, that are
       used to select the file(s)/drawer and show the result.

       Advantages that this class provides:

       > Consistent behaviour and look in all applications using this class
         instead of doing their own file and drawer routines.

       > Easy to use.

    METHODS
       OM_NEW -- Passed to superclass, defaults set, then OM_SET. Children
                 created.

       OM_SET -- Passed to superclass, custom tags set.

       OM_GET -- Custom tag returned or passed to superclass.

       OM_UPDATE -- Passed to superclass, options set then rendered.

       OM_DISPOSE -- Children disposed of, then passed to superclass.

       GM_RENDER -- Passed to superclass, then children are rendered.

       GM_HITTEST -- Overrides superclass, returns GMR_GADGETHIT if within
                 the popfile/drawer button.

       GM_HELPTEST -- Overrides superclass, returns GMR_HELPHIT if within
                 the domain of the gadget.

       GM_GOACTIVE -- Passed to superclass, passed to popfile/drawer button.

       GM_HANDLEINPUT -- Overrides superclass, all input processed.

       GM_GOINACTIVE -- Passed to superclass, popfile/drawer button deactivated.

       GM_DOMAIN -- Returns GDOMAIN_MINIMUM and GDOMAIN_MAXIMUM dimensions.

       GM_KEYACTIVE -- Private method for keyboard control.

       GM_KEYINACTIVE -- Private method for keyboard control.

       GFILE_REQUEST -- getfile gadget method for invoking the file requester.

       GFILE_FREELIST -- getfile gadget method for freeing allocated list
                   of files.

    ATTRIBUTES
       Most of these tags operate the same as the ASLFR_#? tags in ASL library.
       See <asl.library/AslRequest> for detailed descriptions.

       GETFILE_TitleText (STRPTR)
          Requester title text.

          Defaults to NULL.

          Applicability is (OM_NEW, OM_SET).

       GETFILE_LeftEdge (WORD)
       GETFILE_TopEdge  (WORD)
          Requester placement coordinates.

          Defaults to leftedge: 30, topedge: 20.

          Applicability is (OM_NEW, OM_SET, OM_GET).

       GETFILE_Width  (WORD)
       GETFILE_Height (WORD)
          Requester dimensions.

          Default height: 200, width: 300.

          Applicability is (OM_NEW, OM_SET, OM_GET).

       GETFILE_File (STRPTR)
          Contents of file gadget.

          Defaults to NULL.

          Applicability is (OM_NEW, OM_SET, OM_GET, OM_NOTIFY).

       GETFILE_Drawer (STRPTR)
          Contents of drawer gadget.

          Defaults to NULL.

          Applicability is (OM_NEW, OM_SET, OM_GET, OM_NOTIFY).

       GETFILE_FullFile (STRPTR)
          Complete qualified file name. Replaces GETFILE_Drawer and GETFILE_File.

          Defaults to NULL.

          Applicability is (OM_NEW, OM_SET, OM_GET, OM_NOTIFY).

       GETFILE_FullFileExpand (BOOL)
          GETFILE_FullFile will give complete file name(s) expanded with
          NameFromLock() to remove relative paths.

          Defaults to TRUE.

          Applicability is (OM_NEW, OM_SET).

       GETFILE_Pattern (STRPTR)
          Contents of pattern gadget.

          Defaults to "#?".

          Applicability is (OM_NEW, OM_SET, OM_GET).

       GETFILE_DoSaveMode (BOOL)
          Being used for saving?

          Defaults to FALSE.

          Applicability is (OM_NEW, OM_SET).

       GETFILE_DoMultiSelect (BOOL)
          Do multi-select of files?

          Defaults to FALSE.

          Applicability is (OM_NEW, OM_SET).

       GETFILE_DoPatterns (BOOL)
          Display a Pattern gadget?

          Defaults to FALSE.

          Applicability is (OM_NEW, OM_SET).

       GETFILE_DrawersOnly   (BOOL)
          Don't display files?

          Defaults to FALSE.

          Applicability is (OM_NEW, OM_SET).

       GETFILE_FilterFunc (struct Hook *)
          Function to filter files.

          Defaults to none.

          Applicability is (OM_NEW, OM_SET).

       GETFILE_RejectIcons   (BOOL)
          Display .info files?

          Defaults to FALSE.

          Applicability is (OM_NEW, OM_SET).

       GETFILE_RejectPattern   (UBYTE *)
          Don't display files matching pattern.

          Defaults to none.

          Applicability is (OM_NEW, OM_SET).

       GETFILE_AcceptPattern (UBYTE *)
          Accept only files matching pattern.

          Defaults to none.

          Applicability is (OM_NEW, OM_SET).

       GETFILE_FilterDrawers (BOOL)
          Also filter drawers with pattern.

          Defaults to FALSE.

          Applicability is (OM_NEW, OM_SET).

       GETFILE_Filelist (struct List *)
          If the GETFILE_DoMultiSelect tags was used, you can get a pointer
          to the list of selected files/drawers using this tag. The ln_Name
          part of each node will contain the filename/drawername for each
          selected file with a fully qualified path, even if you didn't use
          the GETFILE_FullFileExpand.
          In single-selected mode, the list will contain the single selected
          file for notification purposes. Don't forget to free the list using
          the GFILE_FREELIST method! This list is not suitable to be shown
          directly in a listbrowser gadget without conversion as default, use
          GETFILE_LBNodeStruct for that.

          Applicability is (OM_GET, OM_NOTIFY).

       GETFILE_LBNodeStruct (BOOL)
          GETFILE_Filelist will give a list with ListBrowserNodes instead of
          normal struct Node node structures. NOTE: This tag requires that
          listbrowser.gadget is installed.

          Defaults to FALSE.

          Applicability is (OM_NEW).

          DO NOT USE THIS TAG YET SINCE SOME INTERNAL ISSUES HAVE NOT BEEN
          SORTED OUT YET!

       GETFILE_ReadOnly (BOOL)
          If TRUE, a read-only recessed button gadget is used to present the
          file/drawer information. If FALSE, an editable string gadget is used.
          The gadget will send the supported attributes in a OM_NOTIFY when a
          this tag is FALSE and the user is finished editing the content of the
          string gadget. The application can be aware of all changes to the
          string gadget by setting ICA_TARGET to TARGET_IDCMP for this
          getfile gadget instance and watching IDCMP_IDCMPUPDATE messages.
          See the provided example program for an example on how this can be
          done.

          Defaults to TRUE.

          Applicability is (OM_NEW).


getfile.gadget/GETFILE_GetClass

   NAME
       GETFILE_GetClass -- Gets the pointer to the file requester class

   SYNOPSIS
       getfile_class = GETFILE_GetClass();
       D0

       Class * GETFILE_GetClass( void );

   FUNCTION
       Obtains the pointer to the getfile gadget class for use with
       NewObject().  This function always returns a valid pointer so
       you do not need to check it.  The reason is that if the library
       opens fine, then the pointer returned is already setup.  (Of course
       this implies that if opening the library fails, you shouldn't be
       calling this.)

       Note that this function does not create the class, that is done
       when the class library is opened.

   INPUTS

   RESULT
       getfile_class - Pointer to the getfile gadget class.

   EXAMPLE

   NOTES
       The GFILE_REQUEST method will return 0 if no file is selected and
       the GETFILE_DrawersOnly tag is not used, even is the user selected
       the positive response in the requester. If a file is selected (the
       file gadget in the file requester is not empty), it will return 1.

   BUGS

   SEE ALSO


getfont_gc.doc

     --datasheet--
     GETFONT_GetClass()


getfont.gadget/--datasheet--

   NAME
       getfont_gc -- create getfont BOOPSI objects

   SUPERCLASS
       gadgetclass

   REQUIRES
       button.gadget

   DESCRIPTION
       The getfont gadget class is used to get fonts and font attributes from a
       font requester in an easy and consistent way.  It consists of two button
       gadgets, one read-only and one popfont button, that are used to select
       the font and show the result.

       Advantages that this class provides:

       > Consistent behaviour and look in all applications using this class
         instead of doing their own font selection routines.

       > Easy to use.

    METHODS
       OM_NEW -- Passed to superclass, defaults set, then OM_SET. Children
                 created.

       OM_SET -- Passed to superclass, custom tags set.

       OM_GET -- Custom tag returned or passed to superclass.

       OM_UPDATE -- Passed to superclass, options set then rendered.

       OM_DISPOSE -- Children disposed of, then passed to superclass.

       GM_RENDER -- Passed to superclass, then children are rendered.

       GM_HITTEST -- Overrides superclass, returns GMR_GADGETHIT if within
                 the popfile/drawer button.

       GM_HELPTEST -- Overrides superclass, returns GMR_HELPHIT if within
                 the domain of the gadget.

       GM_GOACTIVE -- Passed to superclass, passed to popfile/drawer button.

       GM_HANDLEINPUT -- Overrides superclass, all input processed.

       GM_GOINACTIVE -- Passed to superclass, popfile/drawer button deactivated.

       GM_DOMAIN -- Returns GDOMAIN_MINIMUM and GDOMAIN_MAXIMUM dimensions.

       GM_KEYACTIVE -- Private method for keyboard control.

       GM_KEYINACTIVE -- Private method for keyboard control.

       GFONT_REQUEST -- getfont gadget method for invoking the font requester.

    ATTRIBUTES
       Most of these tags operate the same as the ASLFO_#? tags in ASL library.
       See <asl.library/AslRequest> for detailed descriptions.

       GETFONT_TitleText (STRPTR)
          Requester title text.

          Defaults to NULL.

          Applicability is (OM_NEW, OM_SET).

       GETFONT_TextAttr (struct TextAttr *)
          Font to show in the gadget. The textattr.ta_Style, textattr.ta_Name
          and textattr.ta_YSize fields are used by the font requester
          as default values in OM_NEW and contain the information about the
          font in the other methods.

          Defaults to none.

          Applicability is (OM_NEW, OM_SET, OM_GET, OM_NOTIFY).

       GETFONT_DoFrontPen (BOOL)
          Do front pen.

          Defaults to FALSE.

          Applicability is (OM_NEW, OM_SET).

       GETFONT_DoBackPen (BOOL)
          Do back pen.

          Default to FALSE.

          Applicability is (OM_NEW, OM_SET).

       GETFONT_DoStyle (BOOL)
          Do style.

          Defaults to FALSE.

          Applicability is (OM_NEW, OM_SET).

       GETFONT_DoDrawMode (BOOL)
          Do draw mode.

          Defaults to FALSE.

          Applicability is (OM_NEW, OM_SET).

       GETFONT_MinHeight (UWORD)
          Minimum font height.

          Defaults to 6.

          Applicability is (OM_NEW, OM_SET).

       GETFONT_MaxHeight (UWORD)
          Maximum font height.

          Defaults to 20.

          Applicability is (OM_NEW, OM_SET).

       GETFONT_FixedWidthOnly (BOOL)
          Only show fixed width fonts.

          Defaults to FALSE.

          Applicability is (OM_NEW, OM_SET).

       GETFONT_Height (WORD)
          Height of the font requester.

          Defaults to 200.

          Applicability is (OM_NEW, OM_SET, OM_GET).

       GETFONT_Width (WORD)
          Width of the font requester.

          Defaults to 300.

          Applicability is (OM_NEW, OM_SET, OM_GET).

       GETFONT_LeftEdge (WORD)
          Left edge of the font requester.

          Defaults to 30.

          Applicability is (OM_NEW, OM_SET, OM_GET).

       GETFONT_TopEdge (WORD)
          Top edge of the font requester.

          Defaults to 20.

          Applicability is (OM_NEW, OM_SET, OM_GET).

       GETFONT_FrontPen (UBYTE)
          Front pen.

          Defaults to 1.

          Applicability is (OM_NEW, OM_SET, OM_GET, OM_NOTIFY).

       GETFONT_BackPen (UBYTE)
          Back pen.

          Defaults to 0.

          Applicability is (OM_NEW, OM_SET, OM_GET, OM_NOTIFY).

       GETFONT_DrawMode (UBYTE)
          Draw mode.

          Defaults to JAM1.

          Applicability is (OM_NEW, OM_SET, OM_GET, OM_NOTIFY).

       GETFONT_MaxFrontPen (UBYTE)
          Max number of colors in front palette.

          Defaults to 255.

          Applicability is (OM_NEW, OM_SET).

       GETFONT_MaxBackPen (UBYTE)
          Max number of colors in back palette.

          Defaults to 255.

          Applicability is (OM_NEW, OM_SET).

       GETFONT_ModeList (STRPTR *)
          Substitute list for drawmodes.

          Defaults to none.

          Applicability is (OM_NEW, OM_SET).

       GETFONT_FrontPens (UBYTE *)
          Color table for front pen palette.

          Defaults to none.

          Applicability is (OM_NEW, OM_SET).

       GETFONT_BackPens (UBYTE *)
          Color table for back pen palette.

          Defaults to none.

          Applicability is (OM_NEW, OM_SET).

       GETFONT_SoftStyle (UBYTE)
          SoftStyle, provided only for making mapping to button.gadget
          easier. Textattr.ta_Style in the GETFONT_TextAttr attribute
          will provide the style in other cases.

          Applicability is (OM_GET, OM_NOTIFY).


getfont.gadget/GETFONT_GetClass

   NAME
       GETFONT_GetClass -- Gets the pointer to the font requester class

   SYNOPSIS
       getfont_class = GETFONT_GetClass();
       D0

       Class * GETFONT_GetClass( void );

   FUNCTION
       Obtains the pointer to the getfont gadget class for use with
       NewObject().  This function always returns a valid pointer so
       you do not need to check it.  The reason is that if the library
       opens fine, then the pointer returned is already setup.  (Of course
       this implies that if opening the library fails, you shouldn't be
       calling this.)

       Note that this function does not create the class, that is done
       when the class library is opened.

   INPUTS

   RESULT
       getfont_class - Pointer to the getfont gadget class.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO


getscreenmode_gc.doc

     --datasheet--
     GETSCREENMODE_GetClass()


getscreenmode.gadget/--datasheet--

   NAME
       getscreenmode_gc -- create getscreenmode BOOPSI objects

   SUPERCLASS
       gadgetclass

   REQUIRES
       button.gadget

   DESCRIPTION
       The getscreenmode gadget class is used to get screenmodes from a
       screenmode requester in an easy and consistent way.  It consists of
       two button gadgets, one read-only and one popscreenmode button,
       that are used to select the screenmode and show the result.

       Advantages that this class provides:

       > Consistent behaviour and look in all applications using this class
         instead of doing their own screenmode selection routines.

       > Easy to use.

    METHODS
       OM_NEW -- Passed to superclass, defaults set, then OM_SET. Children
                 created.

       OM_SET -- Passed to superclass, custom tags set.

       OM_GET -- Custom tag returned or passed to superclass.

       OM_UPDATE -- Passed to superclass, options set then rendered.

       OM_DISPOSE -- Children disposed of, then passed to superclass.

       GM_RENDER -- Passed to superclass, then children are rendered.

       GM_HITTEST -- Overrides superclass, returns GMR_GADGETHIT if within
                 the popscreenmode button.

       GM_HELPTEST -- Overrides superclass, returns GMR_HELPHIT if within
                 the domain of the gadget.

       GM_GOACTIVE -- Passed to superclass, passed to popfile/drawer button.

       GM_HANDLEINPUT -- Overrides superclass, all input processed.

       GM_GOINACTIVE -- Passed to superclass, popfile/drawer button deactivated.

       GM_DOMAIN -- Returns GDOMAIN_MINIMUM and GDOMAIN_MAXIMUM dimensions.

       GM_KEYACTIVE -- Private method for keyboard control.

       GM_KEYINACTIVE -- Private method for keyboard control.

       GSM_REQUEST -- getscreenmode gadget method for invoking the screenmode requester.

    ATTRIBUTES
       Most of these tags operate the same as the ASLSM_#? tags in ASL library.
       See <asl.library/AslRequest> for detailed descriptions.

       GETSCREENMODE_TitleText (STRPTR)
          Title of the screenmode requester.

          Default to none.

          Applicability is (OM_NEW, OM_SET).

       GETSCREENMODE_Height (WORD)
          Height of the screenmode requester.

          Defaults to 200.

          Applicability is (OM_NEW, OM_SET, OM_GET).

       GETSCREENMODE_Width (WORD)
          Width of the screenmode requester.

          Defaults to 300.

          Applicability is (OM_NEW, OM_SET, OM_GET).

       GETSCREENMODE_LeftEdge (WORD)
          Left edge of the screenmode requester.

          Defaults to 30.

          Applicability is (OM_NEW, OM_SET, OM_GET).

       GETSCREENMODE_TopEdge (WORD)
          Top edge of the screenmode requester.

          Defaults to 20.

          Applicability is (OM_NEW, OM_SET, OM_GET).

       GETSCREENMODE_DisplayID (ULONG)
          Display id of screenmode.

          Defaults to 0 (LORES_KEY).

          Applicability is (OM_NEW, OM_SET, OM_GET, OM_NOTIFY).

       GETSCREENMODE_DisplayWidth (ULONG)
          Display width.

          Defaults to 640.

          Applicability is (OM_NEW, OM_SET, OM_GET, OM_NOTIFY).

       GETSCREENMODE_DisplayHeight (ULONG)
          Display height.

          Defaults to 200.

          Applicability is (OM_NEW, OM_SET, OM_GET, OM_NOTIFY).

       GETSCREENMODE_DisplayDepth (UWORD)
          Display depth.

          Defaults to 2.

          Applicability is (OM_NEW, OM_SET, OM_GET, OM_NOTIFY).

       GETSCREENMODE_OverscanType (UWORD)
          Type of overscan.

          Defaults to OSCAN_TEXT.

          Applicability is (OM_NEW, OM_SET, OM_GET, OM_NOTIFY).

       GETSCREENMODE_AutoScroll (BOOL)
          Autoscroll setting.

          Defaults to TRUE.

          Applicability is (OM_NEW, OM_SET, OM_NOTIFY).

       GETSCREENMODE_InfoOpened (BOOL)
          Info window initially opened?

          Defaults to FALSE.

          Applicability is (OM_NEW, OM_SET).

       GETSCREENMODE_InfoLeftEdge (WORD)
          Info window left edge.

          Defaults to 30.

          Applicability is (OM_NEW, OM_SET, OM_GET).

       GETSCREENMODE_InfoTopEdge (WORD)
          Info window top edge.

          Defaults to 20.

          Applicability is (OM_NEW, OM_SET, OM_GET).

       GETSCREENMODE_DoWidth (BOOL)
          Display Width gadget?

          Defaults to FALSE.

          Applicability is (OM_NEW, OM_SET).

       GETSCREENMODE_DoHeight (BOOL)
          Display Height gadget?

          Defaults to FALSE.

          Applicability is (OM_NEW, OM_SET).

       GETSCREENMODE_DoDepth (BOOL)
          Display Depth gadget?

          Defaults to FALSE.

          Applicability is (OM_NEW, OM_SET).

       GETSCREENMODE_DoOverscanType (BOOL)
          Display Overscan Type gadget?

          Defaults to FALSE.

          Applicability is (OM_NEW, OM_SET).

       GETSCREENMODE_DoAutoScroll (BOOL)
          Display AutoScroll gadget?

          Defaults to FALSE.

          Applicability is (OM_NEW, OM_SET).

       GETSCREENMODE_PropertyFlags (ULONG)
          Must have these Property flags.

          Defaults to DIPF_IS_WB.

          Applicability is (OM_NEW, OM_SET).

       GETSCREENMODE_PropertyMask (ULONG)
          Only these should be looked at.

          Defaults to DIPF_IS_WB.

          Applicability is (OM_NEW, OM_SET).

       GETSCREENMODE_MinWidth (ULONG)
          Minimum display width to allow.

          Defaults to 16.

          Applicability is (OM_NEW, OM_SET).

       GETSCREENMODE_MaxWidth (ULONG)
          Maximum display width to allow.

          Defaults to 16368.

          Applicability is (OM_NEW, OM_SET).

       GETSCREENMODE_MinHeight (ULONG)
          Minimum display height to allow.

          Defaults to 16.

          Applicability is (OM_NEW, OM_SET).

       GETSCREENMODE_MaxHeight (ULONG)
          Maximum display height to allow.

          Defaults to 16368.

          Applicability is (OM_NEW, OM_SET).

       GETSCREENMODE_MinDepth (ULONG)
          Minimum display depth to allow.

          Defaults to 1.

          Applicability is (OM_NEW, OM_SET).

       GETSCREENMODE_MaxDepth (ULONG)
          Maximum display depth to allow.

          Defaults to 24.

          Applicability is (OM_NEW, OM_SET).

       GETSCREENMODE_FilterFunc (struct Hook *)
          Function to filter mode id's.

          Defaults to none.

          Applicability is (OM_NEW, OM_SET).

       GETSCREENMODE_CustomSMList (struct List *)
          Exec list of struct DisplayMode.

          Defaults to none.

          Applicability is (OM_NEW, OM_SET).


getscreenmode.gadget/GETSCREENMODE_GetClass

   NAME
       GETSCREENMODE_GetClass -- Gets the pointer to the screenmode
                                 requester class

   SYNOPSIS
       getscreenmode_class = GETSCREENMODE_GetClass();
       D0

       Class * GETSCREENMODE_GetClass( void );

   FUNCTION
       Obtains the pointer to the getscreenmode gadget class for use with
       NewObject().  This function always returns a valid pointer so
       you do not need to check it.  The reason is that if the library
       opens fine, then the pointer returned is already setup.  (Of course
       this implies that if opening the library fails, you shouldn't be
       calling this.)

       Note that this function does not create the class, that is done
       when the class library is opened.

   INPUTS

   RESULT
       getscreenmode_class - Pointer to the getscreenmode gadget class.

   EXAMPLE

   NOTES

   BUGS

   SEE ALSO


glyph_ic.doc

     --datasheet--
     GLYPH_GetClass()


glyph_ic/--datasheet--

    NAME
        glyph_ic -- create glyph BOOPSI objects

    SUPERCLASS
        imageclass

    REQUIRES
        drawlist.image

    DESCRIPTION
        This image class can create scaled glyphs suitable for use
        as gadget imagery or informational requestor imagery.
        Either a penmap or drawlist scaled image is created internally,
        and external user prefered glyph style sets may become possible
        at a later date.

    METHODS
        OM_NEW -- Create the glyph image. Passed to superclass, then OM_SET.

        OM_GET -- Get object attributes. Passed to superclass first.

        OM_SET -- Set object attributes.
            Passed to superclass first.

        OM_UPDATE -- Set object notification attributes. Passed to
            superclass first.

        IM_DRAW -- Renders the image. Overrides the superclass.

        IM_DRAWFRAME -- Renders the image scaled to fit in the frame.
            Following IM_DRAW will be this size. Overrides the superclass.

        All other methods are passed to the superclass.

    ATTRIBUTES
        GLYPH_Glyph (LONG)
            Selects any one of the built-in scaled image glyphs.

            Current supported and defined in <gadgets/glyph.h>:

            GLYPH_NONE - No image.
            GLYPH_DOWNARROW - Indicates downward movement control.
            GLYPH_UPARROW - Indicates upward movement control.
            GLYPH_LEFTARROW - Indicates left movement control.
            GLYPH_RIGHTARROW - Indicates right movement control.
            GLYPH_DROPDOWN - Denotes a drop-down menu.
            GLYPH_POPUP - Denotes a pop-up menu.
            GLYPH_CHECKMARK - Indicates a toggle.
            GLYPH_POPFONT - Font selection.
            GLYPH_POPFILE - File selection.
            GLYPH_POPDRAWER - Drawer (directory) selection.
            GLYPH_POPSCREENMODE - Screenmode selection.
            GLYPH_POPTIME - Time selection.
            GLYPH_RADIOBUTTON - Mutual exclusion item.
            GLYPH_RETURNARROW - RETURN key controlled.

            Defaults to GLYPH_POPFILE.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)


glyph_ic/GLYPH_GetClass

    NAME
        GLYPH_GetClass -- Gets the pointer to the glyph class.

    SYNOPSIS
        glyph_class = GLYPH_GetClass();
        D0

        Class * GLYPH_GetClass(VOID);

    FUNCTION
        Obtains the pointer to the Glyph image class for use with
        NewObject().  This function always returns a valid pointer so
        you do not need to check it.  The reason is that if the library
        opens fine, then the pointer returned is already setup.  (Of course
        this implies that if opening the library fails, you shouldn't be
        calling this.)

        Note that this function does not create the class, that is done
        when the class library is opened.

    INPUTS
        Nothing.

    RESULT
        glyph_class - Pointer to the Glyph image class.

    SEE ALSO


gradientslider_gc.doc

     gradientslider.gadget()


gradientslider.gadget/gradientslider.gadgetlider.gadget/gradientslider.gadget

   NAME
    gradientslider.gadget -- create a slider with a range of colors as its
                 background. (V39)

   FUNCTION
    The gradientslider gadget class is a type of non-proportional slider.
    The primary feature of the gradient slider is it's appearance. Unlike
    normal sliders, a gradient slider can display a "spread of colors" or
    "color gradient" in the slider container box. The "knob" or "thumb"
    of the slider appears to slide on top of this color gradient.

    The color gradient effect is built-up using a combination of multiple
    pens and half-tone dithering. The application must tell the slider
    exactly which pens to use in creating the gradient effect, and in
    what order to use them. Essentially, it does this by passing an
    array of pens (terminated by ~0, just like a PenSpec) to the slider.
    The first pen in the array is used as the color at the top of
    the slider (or left, if it is horizontal), and the last color in the
    array is used at the bottom (or right). The other pens will be
    used at evenly spaced intervals in between. Dithering is used to
    smoothly fade between the pens, allowing the illusion of a continuous
    change in color.

   TAGS
    GRAD_MaxVal (ULONG) - Set the maximum value that the slider can
        represent, in the range 0..$FFFF. Default for this tag is
        $FFFF. Applicability is (ISGU). (V39)

    GRAD_CurVal (ULONG) - Set or get the current value of the slider, in
        the range 0..$FFFF. Default for this tag is 0. Applicability is
        (ISGNU). (V39)

    GRAD_SkipVal (ULONG) - Set the amount by which the slider should
        advance whenever the user clicks on either side of the knob.
        Default for this tag is $1111. Applicability is (ISGU).
        (V39)

    GRAD_KnobPixels (UWORD) - Set the size of the knob in pixels.
        Default for this tag is 5. Applicability is (I).
        (V39)

    GRAD_PenArray (UWORD *) - Specifies an array of pens that the slider
        should use to create its gradient background. The array can
        contain any number of pens, and is terminated with a pen
        value of ~0. These pens can be allocated as shared, since
        their RGB value is not altered by the slider. The first pen
        is used on the top or left of the slider, and the last pen is
        used on the bottom or right. All other pens are evenly spaced
        out and used in between. Dithering is used between the pens
        to enhance the smoothness of the gradient transition.

        A NULL pen array causes the background of the slider to be
        rendered in the screen's background color. A pen array
        containing only a single pen causes the background to be
        rendered using that pen.

        Default for this tag is NULL. Applicability is (ISU).
        (V39)

    PGA_FREEDOM (ULONG) - Determines the orientation of the slider. This
        can be LORIENT_HORIZ for a horizontal slider, or LORIENT_VERT
        for a vertical one. Default for this tag is LORIENT_HORIZ.
        Applicability is (I). (V39)


graphics.doc

     AddAnimOb()
     AddBob()
     AddFont()
     AddVSprite()
     AllocBitMap()
     AllocDBufInfo()
     AllocRaster()
     AllocSpriteDataA()
     AndRectRegion()
     AndRegionRegion()
     Animate()
     AreaCircle()
     AreaDraw()
     AreaEllipse()
     AreaEnd()
     AreaMove()
     AskFont()
     AskSoftStyle()
     AttachPalExtra()
     AttemptLockLayerRom()
     BestModeIDA()
     BitMapScale()
     BltBitMap()
     BltBitMapRastPort()
     BltClear()
     BltMaskBitMapRastPort()
     BltPattern()
     BltTemplate()
     CalcIVG()
     CBump()
     CEND
     ChangeExtSpriteA()
     ChangeSprite()
     ChangeVPBitMap()
     CINIT
     ClearEOL()
     ClearRectRegion()
     ClearRegion()
     ClearScreen()
     ClipBlit()
     CloseFont()
     CloseMonitor()
     CMOVE
     CoerceMode()
     CopySBitMap()
     CWAIT
     DisownBlitter()
     DisposeRegion()
     DoCollision()
     Draw()
     DrawEllipse()
     DrawGList()
     EraseRect()
     ExtendFont()
     FindColor()
     FindDisplayInfo()
     Flood()
     FontExtent()
     FreeBitMap()
     FreeColorMap()
     FreeCopList()
     FreeCprList()
     FreeDBufInfo()
     FreeGBuffers()
     FreeRaster()
     FreeSprite()
     FreeSpriteData()
     FreeVPortCopLists()
     GetAPen()
     GetBitMapAttr()
     GetBPen()
     GetColorMap()
     GetDisplayInfoData()
     GetDrMd()
     GetExtSpriteA()
     GetGBuffers()
     GetOPen()
     GetRGB32()
     GetRGB4()
     GetRPAttrA()
     GetSprite()
     GetVPModeID()
     GfxAssociate()
     GfxFree()
     GfxLookUP()
     GfxNew()
     InitArea()
     InitBitMap()
     InitGels()
     InitGMasks()
     InitMasks()
     InitRastPort()
     InitTmpRas()
     InitView()
     InitVPort()
     LoadRGB32()
     LoadRGB4()
     LoadView()
     LockLayerRom()
     MakeVPort()
     ModeNotAvailable()
     Move()
     MoveSprite()
     MrgCop()
     NewRegion()
     NextDisplayInfo()
     ObtainBestPenA()
     ObtainPen()
     OpenFont()
     OpenMonitor()
     OrRectRegion()
     OrRegionRegion()
     OwnBlitter()
     PolyDraw()
     QBlit()
     QBSBlit()
     ReadPixel()
     ReadPixelArray8()
     ReadPixelLine8()
     RectFill()
     ReleasePen()
     RemBob()
     RemFont()
     RemIBob()
     RemVSprite()
     ScalerDiv()
     ScrollRaster()
     ScrollRasterBF()
     ScrollVPort()
     SetABPenDrMd()
     SetAPen()
     SetBPen()
     SetChipRev()
     SetCollision()
     SetDrMd()
     SetFont()
     SetMaxPen()
     SetOPen()
     SetOutlinePen()
     SetRast()
     SetRGB32()
     SetRGB32CM()
     SetRGB4()
     SetRGB4CM()
     SetRPAttrA()
     SetSoftStyle()
     SetWriteMask()
     SortGList()
     StripFont()
     SyncSBitMap()
     Text()
     TextExtent()
     TextFit()
     TextLength()
     UnlockLayerRom()
     VBeamPos()
     VideoControl()
     WaitBlit()
     WaitBOVP()
     WaitTOF()
     WriteChunkyPixels()
     WritePixel()
     WritePixelArray8()
     WritePixelLine8()
     XorRectRegion()
     XorRegionRegion()


graphics.library/AddFont

   NAME
    AddFont -- add a font to the system list

   SYNOPSIS
    AddFont(textFont)
            A1

    void AddFont(struct TextFont *);

   FUNCTION
    This function adds the text font to the system, making it
    available for use by any application.  The font added must be
    in public memory, and remain until successfully removed.

   INPUTS
    textFont - a TextFont structure in public ram.

   RESULT

   NOTES
    This function will set the tf_Accessors to 0.

   BUGS

   SEE ALSO
    SetFont()  RemFont()  graphics/text.h


graphics.library/AllocBitMap

   NAME
    AllocBitMap -- Allocate a bitmap and attach bitplanes to it. (V39)

   SYNOPSIS
    bitmap=AllocBitMap(sizex,sizey,depth, flags, friend_bitmap)
                       d0    d1    d2     d3       a0

    struct BitMap *AllocBitMap(ULONG,ULONG,ULONG,ULONG, struct BitMap *);

   FUNCTION
    Allocates and initializes a bitmap structure. Allocates and initializes
    bitplane data, and sets the bitmap's planes to point to it.

   INPUTS
    sizex = the width (in pixels) desired for the bitmap data.

    sizey = the height (in pixels) desired.

    depth = the number of bitplanes deep for the allocation.
        Pixels with AT LEAST this many bits will be allocated.

    flags = BMF_CLEAR to specify that the allocated raster should be
            filled with color 0.

            BMF_DISPLAYABLE to specify that this bitmap data should
            be allocated in such a manner that it can be displayed.
            Displayable data has more severe alignment restrictions
            than non-displayable data in some systems.

            BMF_INTERLEAVED tells graphics that you would like your
            bitmap to be allocated with one large chunk of display
            memory for all bitplanes. This minimizes color flashing
            on deep displays. If there is not enough contiguous RAM
        for an interleaved bitmap, graphics.library will fall
        back to a non-interleaved one.

            BMF_MINPLANES causes graphics to only allocate enough space
            in the bitmap structure for "depth" plane pointers. This
        is for system use and should not be used by applications use
        as it is inefficient, and may waste memory.

    friend_bitmap = pointer to another bitmap, or NULL. If this pointer
            is passed, then the bitmap data will be allocated in
            the most efficient form for blitting to friend_bitmap.

   BUGS

   NOTES
    When allocating using a friend bitmap, it is not safe to assume
    anything about the structure of the bitmap data if that friend
    BitMap might not be a standard amiga bitmap (for instance, if
    the workbench is running on a non-amiga display device, its
    Screen->RastPort->BitMap won't be in standard amiga format.
    The only safe operations to perform on a non-standard BitMap are:

            - blitting it to another bitmap, which must be either a standard
              Amiga bitmap, or a friend of this bitmap.

            - blitting from this bitmap to a friend bitmap or to a standard
              Amiga bitmap.

            - attaching it to a rastport and making rendering calls.

    Good arguments to pass for the friend_bitmap are your window's
    RPort->BitMap, and your screen's RastPort->BitMap.
    Do NOT pass &(screenptr->BitMap)!

    BitMaps not allocated with BMF_DISPLAYABLE may not be used as
    Intuition Custom BitMaps or as RasInfo->BitMaps.  They may be blitted
    to a BMF_DISPLAYABLE BitMap, using one of the BltBitMap() family of
    functions.

   SEE ALSO
    FreeBitMap()


graphics.library/AllocDBufInfo

   NAME
       AllocDBufInfo -- Allocate structure for multi-buffered animation (V39)

   SYNOPSIS
       AllocDBufInfo(vp)
              a0

    struct DBufInfo * AllocDBufInfo(struct ViewPort *)

   FUNCTION
    Allocates a structure which is used by the ChangeVPBitMap()
    routine.

   INPUTS
       vp  =  A pointer to a ViewPort structure.

   BUGS

   NOTES
    Returns 0 if there is no memory available or if the display mode
    of the viewport does not support double-buffering.

    The only fields of the DBufInfo structure which can be used by application
    programs are the dbi_SafeMessage, dbi_DispMessage, dbi_UserData1 and
    dbi_UserData2 fields.

    dbi_SafeMessage and dbi_DispMessage are standard exec message structures
    which may be used for synchronizing your animation with the screen update.

    dbi_SafeMessage is a message which is replied to when it is safe to write to
    the old BitMap (the one which was installed when you called ChangeVPBitMap).

    dbi_DispMessage is replied to when it is safe to call ChangeVPBitMap again
    and be certain that the new frame has been seen at least once.

    The dbi_UserData1 and dbi_UserData2 fields, which are stored after each
    message, are for your application to stuff any data into that it may need
    to examine when looking at the reply coming into the ReplyPort for either
    of the embedded Message structures.

    DBufInfo structures MUST be allocated with this function. The size of
    the structure will grow in future releases.

    The following fragment shows proper double buffering synchronization:

    int SafeToChange=TRUE, SafeToWrite=TRUE, CurBuffer=1;
    struct MsgPort *ports[2];    /* reply ports for DispMessage and SafeMessage
*/
    struct BitMap *BmPtrs[2];
    struct DBufInfo *myDBI;

    ... allocate bitmap pointers, DBufInfo, set up viewports, etc.

    myDBI->dbi_SafeMessage.mn_ReplyPort=ports[0];
    myDBI->dbi_DispMessage.mn_ReplyPort=ports[1];
    while (! done)
    {
        if (! SafeToWrite)
        while(! GetMsg(ports[0])) Wait(1l<<(ports[0]->mp_SigBit));
        SafeToWrite=TRUE;

        ... render to bitmap # CurBuffer.

        if (! SafeToChange)
        while(! GetMsg(ports[1])) Wait(1l<<(ports[1]->mp_SigBit));
        SafeToChange=TRUE;
        WaitBlit();         /* be sure rendering has finished */
        ChangeVPBitMap(vp,BmPtrs[CurBuffer],myDBI);
        SafeToChange=FALSE;
        SafeToWrite=FALSE;
        CurBuffer ^=1;	/* toggle current buffer */
    }
       if (! SafeToChange)	/* cleanup pending messages */
        while(! GetMsg(ports[1])) Wait(1l<<(ports[1]->mp_SigBit));
       if (! SafeToWrite)	/* cleanup */
        while(! GetMsg(ports[0])) Wait(1l<<(ports[0]->mp_SigBit));

   SEE ALSO
    FreeDBufInfo() ChangeVPBitMap()


graphics.library/AllocRaster

   NAME
    AllocRaster -- Allocate space for a bitplane.

   SYNOPSIS
    planeptr = AllocRaster( width, height )
       d0                    d0     d1

    PLANEPTR AllocRaster(ULONG,ULONG);

   FUNCTION
    This function calls the memory allocation routines
    to allocate memory space for a bitplane "width" bits
    wide and "height" bits high.

   INPUTS
    width	- number of columns in bitplane
    height	- number of rows in bitplane

   RESULT
    planeptr - pointer to first word in bitplane, or NULL if
           it was not possible to allocate the desired
           amount of memory.

   NOTES
    In order to assure proper alignment of display memory, the
    AllocBitMap() function should be used instead of AllocRaster
    when you wish to allocate display memory (rasters which are
    attached to a ViewPort or Screen).

   BUGS

   SEE ALSO
    FreeRaster() graphics/gfx.h


graphics.library/AllocSpriteDataA

   NAME
    AllocSpriteDataA -- allocate sprite data and convert from a bitmap. (V39)
    AllocSpriteData -- varargs stub for AllocSpriteData(). (V39)

   SYNOPSIS
    SpritePtr | 0 = AllocSpriteDataA(bitmap,taglist)
     d0	 	                 a2      a1

    struct ExtSprite *AllocSpriteDataA( struct BitMap *, struct TagItem * );

    extsprite=AllocSpriteData(bitmap,tags,...TAG_END)

    FUNCTION
    Allocate memory to hold a sprite image, and convert the passed-in
    bitmap data to the appropriate format. The tags allow specification
    of width, scaling, and other options.

   INPUTS
    bitmap - ptr to a bitmap. This bitmap provides the source data for the
        sprite image.

    tags -
        SPRITEA_Width specifies how many pixels wide you desire
        the sprite to be. Specifying a width wider than the hardware
        can handle will cause the function to return failure. If the
        bitmap passed in is narrower than the width asked for, then
        it will be padded on the right with transparent pixels.
        Defaults to 16.

        SPRITEA_XReplication controls the horizontal pixel replication factor
        used when converting the bitmap data. Valid values are:
            0 - perform a 1 to 1 conversion
            1 - each pixel from the source is replicated twice
                in the output.
            2 - each pixel is replicated 4 times.
               -1 - skip every other pixel in the source bitmap
               -2 - only include every fourth pixel from the source.

            This tag is useful for converting data from one resolution
        to another. For instance, hi-res bitmap data can be correctly
        converted for a lo-res sprite by using an x replication factor
        of -1. Defaults to 0.

        SPRITEA_YReplication controls the vertical pixel replication factor
        in the same manner as SPRITEA_XReplication controls the horizontal.

        SPRITEA_OutputHeight specifies how tall the resulting sprite
        should be. Defaults to the bitmap height. The bitmap MUST be at
        least as tall as the output height.

        SPRITEA_Attached tells the function that you wish to convert
        the data for the second sprite in an attached sprite pair.
        This will cause AllocSpriteData() to take its data from the
        3rd and 4th bitplanes of the passed in bitmap.

    Bitplane data is not required to be in chip ram for this function.

   RESULTS
    SpritePtr = a pointer to a ExtSprite structure, or 0 if there is
    a failure. You should pass this pointer to FreeSpriteData() when finished
    with the sprite.

   BUGS
        Under V39, the appropriate attach bits would not be set in the sprite
    data.
        The work-around is to set the bits manually. Bit 7 of the second
    word should be set. On a 32 bit sprite, bit 7 of the 3rd word should
    also be set. For a 64 bit sprite, bit 7 of the 5th word should also be
    set. This should NOT be done under V40, as the bug is fixed.

   SEE ALSO
    FreeSpriteData() FreeSprite() ChangeSprite() MoveSprite() GetExtSpriteA()
    AllocBitMap() graphics/sprite.h


graphics.library/AndRegionRegion

   NAME
       AndRegionRegion -- Perform 2d AND operation of one region
                       with second region, leaving result in second region.

   SYNOPSIS
       status = AndRegionRegion(region1,region2)
          d0                       a0      a1

    BOOL AndregionRegion(struct Region *, struct Region * );

   FUNCTION
       Remove any portion of region2 that is not in region1.

   INPUTS
       region1 - pointer to Region structure
       region2 - pointer to Region structure to use and for result

   RESULTS
    status - return TRUE if successful operation
         return FALSE if ran out of memory

   BUGS

   SEE ALSO
    OrRegionRegion() AndRectRegion() graphics/regions.h


graphics.library/AreaEnd

   NAME
    AreaEnd -- Process table of vectors and ellipses and produce areafill.

   SYNOPSIS
    error = AreaEnd(rp)
      d0  	        A1

    LONG AreaEnd( struct RastPort * );

   FUNCTION
    Trigger the filling operation.
    Process the vector buffer and generate required
    fill into the raster planes. After the fill is complete, reinitialize
    for the next AreaMove or AreaEllipse. Use the raster set up by
    InitTmpRas when generating an areafill mask.

   RESULT
    error - zero for success, or -1 if an error occurred anywhere.

   INPUTS
    rp - pointer to a RastPort structure which specifies where the filled
         regions will be rendered to.

   BUGS

   SEE ALSO
    InitArea() AreaMove() AreaDraw() AreaEllipse()  InitTmpRas()
    graphics/rastport.h


graphics.library/AttachPalExtra

   NAME
       AttachPalExtra -- Allocate and attach a palette sharing structure to a

                      colormap. (V39)

   SYNOPSIS
       status=AttachPalExtra( cm, vp)
                           a0  a1

    LONG AttachPalExtra( Struct ColorMap *, struct ViewPort *);

   FUNCTION
    Allocates and attaches a PalExtra structure to a ColorMap.
    This is necessary for color palette sharing to work. The
    PalExtra structure will be freed by FreeColorMap().
    The set of available colors will be determined by the mode
    and depth of the viewport.

   INPUTS
    cm  =  A pointer to a color map created by GetColorMap().

    vp   = A pointer to the viewport structure associated with
           the ColorMap.

   RESULTS
    status - 0 if sucessful, else an error number. The only currently
             defined error number is out of memory (1).

   BUGS

   NOTES
    This function is for use with custom ViewPorts and custom ColorMaps,
    as Intuition attaches a PalExtra to all of its Screens.
    If there is already a PalExtra associated with the ColorMap, then
    this function will do nothing.

   SEE ALSO
    GetColorMap() FreeColorMap() ObtainPen() ObtainBestPenA()


graphics.library/AttemptLockLayerRom

                           *
   NAME
    AttemptLockLayerRom -- Attempt to Lock Layer structure
                     by ROM(gfx lib) code

   SYNOPSIS
    gotit = AttemptLockLayerRom( layer )
     d0			      a5

    BOOL AttempLockLayerRom( struct Layer * );

   FUNCTION
    Query the current state of the lock on this Layer. If it is
    already locked then return FALSE, could not lock. If the
    Layer was not locked then lock it and return TRUE.
    This call does not destroy any registers.
    This call nests so that callers in this chain will not lock
    themselves out.

   INPUTS
    layer - pointer to Layer structure

   RESULT
    gotit - TRUE or FALSE depending on whether the Layer was
        successfully locked by the caller.

   SEE ALSO
    LockLayerRom() UnlockLayerRom()


graphics.library/BestModeIDA

   NAME
    BestModeIDA -- calculate the best ModeID with given parameters (V39)
    BestModeID  -- varargs stub for BestModeIDA()

   SYNOPSIS
    ID = BestModeIDA(TagItems)
    d0               a0

    ULONG BestModeIDA(struct TagItem *);

    ID = BestModeID(Tag1, ...)

    ULONG BestModeID(ULONG, ...);

   FUNCTION
    To determine the best ModeID to fit the parameters set in the TagList.

   INPUTS
    TagItems - A pointer to an array of TagItems.

   TAGS
    BIDTAG_DIPFMustHave (ULONG) - Mask of DIPF_ flags
           (from DisplayInfo->PropertyFlags) that the returned ModeID
           must have.
           Default - NULL

    BIDTAG_DIPFMustNotHave (ULONG) - Mask of DIPF_ flags that the
           returned ModeID must not have.
           Default - SPECIAL_FLAGS

    BIDTAG_ViewPort (struct ViewPort *) - ViewPort for which a best-fit
           ModeID is sought.
           Default - NULL

    BIDTAG_NominalWidth (UWORD),
    BIDTAG_NominalHeight (UWORD) - together make the aspect ratio.
           These values override the vp->DWidth and vp->DHeight values
           in the given ViewPort.
           Default - SourceID NominalDimensionInfo if BIDTAG_SourceID is
           passed, or vp->DWidth and vp->DHeight if BIDTAG_ViewPort is
           passed, or 640 x 200.

    BIDTAG_DesiredWidth (UWORD),
    BIDTAG_DesiredHeight (UWORD) - Used to distinguish between two
           mode IDs with identical aspect ratios.
           Default - same values as NominalWidth and NominalHeight.

    BIDTAG_Depth (UBYTE) - minimum the returned ModeID must support.
           Default - vp->RasInfo->BitMap->Depth if BIDTAG_ViewPort is
           passed, else 1.

    BIDTAG_MonitorID (ULONG) - returned ModeID must use this monitor.
           Default - will not restrict the search to any particular monitor

    BIDTAG_SourceID (ULONG) - Use this ModeID instead of a ViewPort.
           If specified, the DIPFMustHave mask is made up of the
           ((DisplayInfo->PropertyFlags of this ID & SPECIAL_FLAGS) |
            DIPFMustHave flags).
           Default - VPModeID(vp) if BIDTAG_ViewPort was passed, else the
           DIPFMustHave and DIPFMustNotHave masks are left unchanged.

    BIDTAG_RedBits (UBYTE),
    BIDTAG_BlueBits (UBYTE),
    BIDTAG_Greenits (UBYTE) - Minimum bits per gun the resultant
           ModeID must support.
           Default - 4 bits per gun.

   RESULTS
    ID      - ID of the best mode to use, or INVALID_ID if a match could
              not be found.

   NOTES
    This function takes into account the Compatability of the Monitor
    being matched to, and the source ViewPort or ModeID.
    Incompatibilitys will cause a result of INVALID_ID.

    BIDTAG_NominalWidth, BIDTAG_NominalHeight,
    BIDTAG_DesiredWidth, BIDTAG_DesiredHeight, must all be non-0.

    The comparisons are made against the DimensionInfo->Nominal values.
    ie, this will not return a best fit against overscan dimensions.

   EXAMPLE
    IFF Display Program with a HAM image, to be displayed in the same
    monitor type as the Workbench ViewPort.

    ID = BestModeID(BIDTAG_NominalWidth, IFFImage->Width,
                    BIDTAG_NominalHeight, IFFImage->Height,
                    BIDTAG_Depth, IFFImage->Depth,
                    BIDTAG_DIPFMustHave, DIPF_IS_HAM,
                    BIDTAG_MonitorID, (GetVPModeID(WbVP) & MONITOR_ID_MASK),
                    TAG_END);

    To make an interlace version of a ViewPort:

    ID = BestModeID(BIDTAG_ViewPort, ThisViewPort,
                    BIDTAG_MustHave, DIFP_IS_LACE,
                    TAG_END);

   SEE ALSO
    <graphics/modeid.h> <graphics/displayinfo.h>


graphics.library/BitMapScale

   NAME
    BitMapScale -- Perform raster scaling on a bit map. (V36)

   SYNOPSIS
    BitMapScale(bitScaleArgs)
                A0

    void BitMapScale(struct BitScaleArgs *);

   FUNCTION
    Scale a source bit map to a non-overlapping destination
    bit map.

   INPUTS
    bitScaleArgs - structure of parameters describing scale:
        bsa_SrcX, bsa_SrcY - origin of the source bits.
        bsa_SrcWidth, bsa_SrcHeight - number of bits to scale from in x
        and y.
        bsa_DestX, bsa_DestY - origin of the destination.
        bsa_DestWidth, bsa_DestHeight - resulting number of bits in x
        and y.  NOTE: these values are set by this function.
        bsa_XSrcFactor:bsa_XDestFactor - equivalent to the ratio
            srcWidth:destWidth, but not necessarily the same
            numbers.  Each must be in the range 1..16383.
        bsa_YSrcFactor:bsa_YDestFactor - equivalent to the ratio
            srcHeight:destHeight, but not necessarily the same
            numbers.  Each must be in the range 1..16383.
        bsa_SrcBitMap - source of the bits to scale.
        bsa_DestBitMap - destination for the bits to scale.  This had
            better be big enough!
        bsa_Flags - future scaling options.  Set it to zero!
        bsa_XDDA, bsa_YDDA - for future use.  Need not be set by user.
        bsa_Reserved1, bsa_Reserved2 - for future use.  Need not be set.

   RESULT
    The destWidth, destHeight fields are set by this function as
    described above.

   NOTES
    o   This function may use the blitter.
    o   Overlapping source and destination bit maps are not
        supported.
    o   No check is made to ensure destBitMap is big enough: use
        ScalerDiv to calculate a destination dimension.

   BUGS
    o   This function does not use the HighRes Agnus 'Big Blit'
        facility. You should not use XSrcFactor == XDestFactor,
        where SrcWidth or DestWidth > 1024.

    o   Also, the blitter is used when expanding in the Y direction.
        You should not expand in the Y direction if
        ((DestX & 0xf) + DestWidth) >= 1024 pixels. (Up to 1008 pixels
        is always safe).

   SEE ALSO
    ScalerDiv()  graphics/scale.h


graphics.library/BltBitMap

   NAME
    BltBitMap -- Move a rectangular region of bits in a BitMap.

   SYNOPSIS
    planecnt = BltBitMap(SrcBitMap, SrcX, SrcY, DstBitMap,
    D0                   A0         D0:16 D1:16 A1
        DstX, DstY, SizeX, SizeY, Minterm, Mask [, TempA])
        D2:16 D3:16 D4:16  D5:16  D6:8     D7:8   [A2]

    ULONG BltBitMap(struct BitMap *, WORD, WORD, struct BitMap *,
        WORD, WORD, WORD, WORD, UBYTE, UBYTE, UWORD *);

   FUNCTION
    Perform non-destructive blits to move a rectangle from one
    area in a BitMap to another area, which can be on a different
    BitMap.
    This blit is assumed to be friendly: no error conditions (e.g.
    a rectangle outside the BitMap bounds) are tested or reported.

   INPUTS
    SrcBitMap, DstBitMap - the BitMap(s) containing the
          rectangles
        - the planes copied from the source to the destination are
          only those whose plane numbers are identical and less
          than the minimum Depth of either BitMap and whose Mask
          bit for that plane is non-zero.
        - as a special case, if a plane pointer in the SrcBitMap
          is zero, it acts as a pointer to a plane of all zeros, and
          if the plane pointer is 0xffffffff, it acts as a pointer
          to a plane of all ones.  (Note: new for V36)
        - SrcBitMap and DstBitMap can be identical if they point
          to actual planes.
    SrcX, SrcY - the x and y coordinates of the upper left corner
        of the source rectangle.  Valid range is positive
        signed integer such that the raster word's offset
        0..(32767-Size)
    DstX, DstY - the x and y coordinates of the upper left
        corner of the destination for the rectangle.  Valid
        range is as for Src.
    SizeX, SizeY - the size of the rectangle to be moved.  Valid
        range is (X: 1..976; Y: 1..1023 such that final raster
        word's offset is 0..32767)
    Minterm - the logic function to apply to the rectangle when
        A is non-zero (i.e. within the rectangle).  B is the
        source rectangle and C, D is the destination for the
        rectangle.
        - $0C0 is a vanilla copy
        - $030 inverts the source before the copy
        - $050 ignores the source and inverts the destination
        - see the hardware reference manual for other combinations
    Mask - the write mask to apply to this operation.  Bits set
        indicate the corresponding planes (if not greater than
        the minimum plane count) are to participate in the
        operation.  Typically this is set to 0xff.
    TempA - If the copy overlaps exactly to the left or right
        (i.e. the scan line addresses overlap), and TempA is
        non-zero, it points to enough chip accessible memory
        to hold a line of A source for the blit (ie CHIP RAM).
        BltBitMap will allocate (and free) the needed TempA if
        none is provided and one is needed.  Blit overlap is
        determined from the relation of the first non-masked
        planes in the source and destination bit maps.

   RESULTS
    planecnt - the number of planes actually involved in the blit.

   NOTES
    o   This function may use the blitter.

   SEE ALSO
    ClipBlit()  graphics/gfx.h  hardware/blit.h


graphics.library/BltClear

   NAME

    BltClear - Clear a block of memory words to zero.

   SYNOPSIS
    BltClear( memBlock, bytecount, flags )
            a1         d0       d1

    void BltClear( void *, ULONG, ULONG );

   FUNCTION
    For memory that is local and blitter accessible, the most
    efficient way to clear a range of memory locations is
       to use the system's most efficient data mover, the blitter.
       This command accepts the starting location and count and clears
       that block to zeros.

   INPUTS
    memBloc	- pointer to local memory to be cleared
          memBlock is assumed to be even.
    flags	- set bit 0 to force function to wait until
          the blit is done.
          set bit 1 to use row/bytesperrow.

    bytecount - if (flags & 2) == 0 then
                even number of bytes to clear.
            else
                low 16 bits is taken as number of bytes
                per row and upper 16 bits taken as
                number of rows.

    This function is somewhat hardware dependent. In the rows/bytesperrow
    mode (with the pre-ECS blitter) rows must be <- 1024. In bytecount mode
    multiple runs of the blitter may be used to clear all the memory.

    Set bit 2 to use the upper 16 bits of the Flags as the data to fill
    memory with instead of 0 (V36).

   RESULT
    The block of memory is initialized.

   BUGS

   SEE ALSO


graphics.library/BltPattern

   NAME
    BltPattern --  Using standard drawing rules for areafill,
                     blit through a mask.

   SYNOPSIS
       BltPattern(rp, mask, xl, yl, maxx, maxy, bytecnt)
                  a1,  a0   d0  d1   d2   d3     d4

    void BltPattern
       (struct RastPort *, void *, SHORT, SHORT, SHORT, SHORT, SHORT);

   FUNCTION
       Blit using drawmode,areafill pattern, and mask
       at position rectangle (xl,yl) (maxx,maxy).

   INPUTS
       rp    -  points to the destination RastPort for the blit.
       mask  -  points to 2 dimensional mask if needed
                if mask == NULL then use a rectangle.
       xl,yl -  coordinates of upper left of rectangular region in RastPort
       maxx,maxy - points to lower right of rectangular region in RastPort
       bytecnt - BytesPerRow for mask

   RESULT

   SEE ALSO
    AreaEnd()


graphics.library/BltTemplate

   NAME
    BltTemplate -- Cookie cut a shape in a rectangle to the RastPort.

   SYNOPSIS
    BltTemplate(SrcTemplate, SrcX, SrcMod, rp,
                A0           D0:16  D1:16  A1
        DstX,  DstY, SizeX, SizeY)
        D2:16  D3:16 D4:16  D5:16

    void BltTemplate(UWORD *, WORD, WORD, struct RastPort *,
         WORD, WORD, WORD, WORD);

   FUNCTION
    This function draws the image in the template into the
    RastPort in the current color and drawing mode at the
    specified position.  The template is assumed not to overlap
    the destination.
    If the template falls outside the RastPort boundary, it is
    truncated to that boundary.

    Note: the SrcTemplate pointer should point to the "nearest" word
       (rounded down) of the template mask. Fine alignment of the mask
       is achieved by setting the SrcX bit offseet within the range
       of 0 to 15 decimal.

   INPUTS
    SrcTemplate  - pointer to the first (nearest) word of the template mask.
    SrcX         - x bit offset into the template mask (range 0..15).
    SrcMod       - number of bytes per row in template mask.
    rp           - pointer to destination RastPort.
    DstX, DstY   - x and y coordinates of the upper left
                   corner of the destination for the blit.
    SizeX, SizeY - size of the rectangle to be used as the
                   template.

   NOTES
    o   This function may use the blitter.

   SEE ALSO
    BltBitMap()  graphics/rastport.h


graphics.library/CalcIVG

   NAME
    CalcIVG -- Calculate the number of blank lines above a ViewPort (V39)

   SYNOPSIS
    count = CalcIVG(View, ViewPort)
     d0.w           a0    a1

    UWORD CalcIVG(struct View *, struct ViewPort *);

   FUNCTION
    To calculate the maximum number of blank lines above a viewport needed to
    load all the copper instructions, after accounting for the viewport
    bandwidth and size.

   INPUTS
    View       - pointer to the View
    ViewPort   - pointer to the ViewPort you are interested in.

   RESULT
    count      - the number of ViewPort resolution scan lines needed to
                 execute all the copper instructions for ViewPort,
                 or 0 if any error.

   NOTES
    The number of copper instructions comes from the vp->vp_DspIns list.
    Although there may be other copper instructions in the final list (from
    UCopIns, SprIns and ClrIns) they are currently ignored for this
    function. This also means that if the ViewPort has never been made
    (for example, the ViewPort of an intuition screen was opened behind)
    then vp->vp_DspIns is NULL.

    Although CalcIVG() returns the true number of lines needed by the
    copper, intuition still maintains an inter-screen gap of 3 non-laced
    lines (6 interlaced). Therefore, for intuition screens use:
    MAX(CalcIVG(v, vp), (islaced ? 6 : 3))

   SEE ALSO
    GfxNew()  VideoControl()  graphics/view.h


graphics.library/CBump

   NAME
    CBump -  increment user copper list pointer (bump to next position in list).

   SYNOPSIS
    CBump( c )
          a1

    void CBump( struct UCopList * );

   FUNCTION
    Increment pointer to space for next instruction in user copper list.

   INPUTS
    c - pointer to UCopList structure

   RESULTS
    User copper list pointer is incremented to next position.
    Pointer is repositioned to next user copperlist instruction block
    if the current block is full.

        Note: CBump is usually invoked for the programmer as part of the
              macro definitions CWAIT or CMOVE.

   BUGS

   SEE ALSO
    CINIT() CWAIT() CMOVE() CEND() graphics/copper.h


graphics.library/CEND

   NAME
    CEND -- Terminate user copper list.

   SYNOPSIS
    CEND( c )

    struct UCopList *c;

   FUNCTION
    Add instruction to terminate user copper list.

   INPUTS
    c - pointer to UCopList structure

   RESULTS
    This is actually a macro that calls the macro CWAIT(c,10000,255)
    10000 is a magical number that the graphics.library uses.
    I hope display technology doesn't catch up too fast!

   BUGS

   SEE ALSO
    CINIT() CWAIT() CMOVE() graphics/copper.h


graphics.library/ChangeExtSpriteA

   NAME
       ChangeExtSpriteA -- Change the sprite image pointer. (V39)

   SYNOPSIS
       ChangeExtSpriteA( vp, oldsprite, newsprite, tags)
                           a0  a1   	 a2	    a3

    success=ChangeExtSpriteA(struct ViewPort *, struct ExtSprite *,
            struct ExtSprite *, struct TagList *);

    success=ChangeExtSprite(vp,old_sp,new_sp,tag,....);

   FUNCTION
    Attempt to change which sprite is displayed for a given
    sprite engine.

   INPUTS
       vp - pointer to ViewPort structure that this sprite is
          relative to,  or 0 if relative only top of View
    oldsprite - pointer the old ExtSprite structure
    newsprite - pointer to the new ExtSprite structure.

   RESULTS
     success - 0 if there was an error.
   BUGS

   SEE ALSO
    FreeSprite() ChangeSprite() MoveSprite() AllocSpriteDataA()
    graphics/sprite.h


graphics.library/ChangeVPBitMap

   NAME
       ChangeVPBitMap -- change display memory address for multi-buffered
              animation (V39)

   SYNOPSIS
       ChangeVPBitMap(vp,bm,db)
                   a0 a1 a2

    void ChangeVPBitMap(struct ViewPort *, struct BitMap *, struct DBufInfo *);

   FUNCTION
    Changes the area of display memory which will be displayed in a
    viewport. This can be used to implement double (or triple)
    buffering, a method of achieving smooth animation.

   INPUTS
    vp  =  a pointer to a viewport
       bm  = a pointer to a BitMap structure. This BitMap structure must be
          of the same layout as the one attached to the viewport (same
          depth, alignment, and BytesPerRow).
    db  =  A pointer to a DBufInfo.

   BUGS

   NOTES
    This will set the vp->RasInfo->BitMap field to the bm pointer which is
    passed.

    When using the synchronization features, you MUST carefully insure that
    all messages have been replied to before calling FreeDBufInfo or
    calling ChangeVPBitMap with the same DBufInfo.

   SEE ALSO
    AllocDBufInfo() AllocBitMap()


graphics.library/CINIT

   NAME
    CINIT -- Initialize user copperlist to accept intermediate
         user copper instructions.

   SYNOPSIS
     cl = CINIT( ucl , n )

    cl = UCopperListInit( ucl , n )
                  a0    d0

    struct CopList *UCopperListInit( struct UCopList *, UWORD );

   FUNCTION
    Allocates and/or initialize copperlist structures/buffers
    internal to a UCopList structure.

    This is a macro that calls UCopListInit. You must pass a
    (non-initialized) UCopList to CINIT (CINIT will NOT allocate
    a new UCopList if ucl==0 ). If (ucl != 0) it will initialize the
    intermediate data buffers internal to a UCopList.

    The maximum number of intermediate copper list instructions
    that these internal CopList data buffers contain is specified
    as the parameter n.

   INPUTS
    ucl - pointer to UCopList structure
    n - number of instructions buffer must be able to hold

   RESULTS
    cl- a pointer to a buffer which will accept n intermediate copper
        instructions.

    NOTE: this is NOT a UCopList pointer, rather a pointer to the
          UCopList's->FirstCopList sub-structure.

   BUGS
    CINIT will not actually allocate a new UCopList if ucl==0.
    Instead you must allocate a block MEMF_PUBLIC|MEMF_CLEAR, the
    sizeof(struct UCopList) and pass it to this function.

    The system's FreeVPortCopLists function will take care of
    deallocating it if they are called.

    Prior to release V36 the  CINIT macro had { } braces surrounding
    the definition, preventing the proper return of the result value.
    These braces have been removed for the V36 include definitions.

   SEE ALSO
     CINIT() CMOVE() CEND() graphics/copper.h


graphics.library/ClearRegion

   NAME
       ClearRegion -- Remove all rectangles from region.

   SYNOPSIS
       ClearRegion(region)
                     a0

    viod ClearRegion( struct Region * );

   FUNCTION
       Clip away all rectangles in the region leaving nothing.

   INPUTS
       region - pointer to Region structure

   BUGS

   SEE ALSO
    NewRegion() graphics/regions.h


graphics.library/ClipBlit

   NAME
    ClipBlit  --  Calls BltBitMap() after accounting for windows

   SYNOPSIS
    ClipBlit(Src, SrcX, SrcY, Dest, DestX, DestY, XSize, YSize, Minterm)
             A0   D0    D1    A1    D2     D3     D4     D5     D6

    void ClipBlit
         (struct RastPort *, WORD, WORD, struct RastPort *, WORD, WORD,
          WORD, WORD, UBYTE);

   FUNCTION
    Performs the same function as BltBitMap(), except that it
    takes into account the Layers and ClipRects of the layer library,
    all of which are (and should be) transparent to you.  So, whereas
    BltBitMap() requires pointers to BitMaps, ClipBlit requires pointers to
    the RastPorts that contain the Bitmaps, Layers, etcetera.

    If you are going to blit blocks of data around via the RastPort of your
    Intuition Window, you must call this routine (rather than BltBitMap()).

    Either the Src RastPort, the Dest RastPort, both, or neither, can have
    Layers. This routine takes care of all cases.

    See BltBitMap() for a thorough explanation.

   INPUTS
    Src          = pointer to the RastPort of the source for your blit
    SrcX, SrcY   = the topleft offset into Src for your data
    Dest         = pointer to the RastPort to receive the blitted data
    DestX, DestY = the topleft offset into the destination RastPort
    XSize        = the width of the blit (must be ta least 1)
    YSize        = the height of the blit (must be at least 1)
    Minterm      = the boolean blitter function, where SRCB is associated
                   with the Src RastPort and SRCC goes to the Dest RastPort

   RESULT

   BUGS

   SEE ALSO
    BltBitMap()


graphics.library/CloseMonitor

   NAME
    CloseMonitor -- close a MonitorSpec (V36)

   SYNOPSIS
    error = CloseMonitor( monitor_spec )
    d0                    a0

    LONG CloseMonitor( struct MonitorSpec * );

   FUNCTION
    Relinquish access to a MonitorSpec.

   INPUTS
    monitor_spec - a pointer to a MonitorSpec opened via OpenMonitor(),
    or NULL.

   RESULTS
    error - FALSE if MonitorSpec closed uneventfully.
            TRUE if MonitorSpec could not be closed.

   BUGS

   SEE ALSO
    OpenMonitor()


graphics.library/CMOVE

   NAME
    CMOVE -- append copper move instruction to user copper list.

   SYNOPSIS
    CMOVE( c , a , v )

    CMove( c , a , v )
          a1  d0  d1
    CBump( c )
          a1

    void CMove( struct UCopList *, void *, WORD );

   FUNCTION
    Add instruction to move value v to hardware register a.

   INPUTS
    c - pointer to UCopList structure
    a - hardware register
    v - 16 bit value to be written

   RESULTS
    This is actually a macro that calls CMove(c,&a,v)
    and then calls CBump(c) to bump the local pointer
    to the next instruction. Watch out for macro side affects.

   BUGS

   SEE ALSO
    CINIT() CWAIT() CEND() graphics/copper.h


graphics.library/CoerceMode

   NAME
    CoerceMode -- calculate ViewPort mode coercion (V39)

   SYNOPSIS
    ID = CoerceMode(RealViewPort, MonitorID, Flags);
    d0              a0            d0         d1

    ULONG CoerceMode(struct ViewPort *, ULONG, ULONG);

   FUNCTION
    To determine the best mode in the MonitorID to coerce RealViewPort to,
    given the restrictions set in Flags.

   INPUTS
    RealViewPort - ViewPort to coerce
    MonitorID    - Montor number to coerce to (ie a mode masked with
                   MONITOR_ID_MASK).
    Flags        - PRESERVE_COLORS - keep the number of bitplanes
                   in the ViewPort.
                   AVOID_FLICKER - do not coerce to an interlace mode

   RESULTS
    ID      - ID of the best mode to coerce to, or INVALID_ID if could not
              coerce (see NOTES).

   NOTES
    This function takes into account the compatibility of the Monitor
    being coerced to, and the ViewPort that is being coerced.
    Incompatibilities will cause a result of INVALID_ID.

   EXAMPLE
    newmode = CoerceMode(vp, VGA_MONITOR_ID, PRESERVE_COLORS);

   SEE ALSO
    <graphics/coerce.h> <graphics/displayinfo.h>


graphics.library/CWAIT

   NAME
    CWAIT -- Append copper wait instruction to user copper list.

   SYNOPSIS
    CWAIT( c , v , h )

    CWait( c , v , h )
           a1  d0  d1
    CBump( c )
          a1

    void CWait( struct UCopList *, WORD, WORD)

   FUNCTION
    Add instruction to wait for vertical beam position v and
    horizontal position h to this intermediate copper list.

   INPUTS
    c - pointer to UCopList structure
    v - vertical beam position (relative to top of viewport)
    h - horizontal beam position

   RESULTS
    this is actually a macro that calls CWait(c,v,h)
    and then calls CBump(c) to bump the local pointer
    to the next instruction.

   BUGS
    User waiting for horizontal values of greater than 222 decimal
    is illegal.

   SEE ALSO
     CINIT() CMOVE() CEND() graphics/copper.h


graphics.library/DisownBlitter

   NAME
       DisownBlitter -- return blitter to free state.

   SYNOPSIS
       DisownBlitter()

    void DisownBlitter( void );

   FUNCTION
    Free blitter up for use by other blitter users.

   INPUTS

   RETURNS

   SEE ALSO
       OwnBlitter()


graphics.library/DrawEllipse

    NAME
    DrawEllipse -- Draw an ellipse centered at cx,cy with vertical
       and horizontal radii of a,b respectively.

    SYNOPSIS
    DrawEllipse( rp, cx, cy, a, b )
             a1  d0  d1  d2 d3

    void DrawEllipse( struct RastPort *, SHORT, SHORT, SHORT, SHORT);

    FUNCTION
       Creates an elliptical outline within the rectangular region
    specified by the parameters, using the current foreground pen color.

    INPUTS
    rp - pointer to the RastPort into which the ellipse will be drawn.
    cx - x coordinate of the centerpoint relative to the rastport.
    cy - y coordinate of the centerpoint relative to the rastport.
    a - the horizontal radius of the ellipse (note: a must be > 0)
    b - the vertical radius of the ellipse (note: b must be > 0)

    BUGS

    NOTES
    this routine does not clip the ellipse to a non-layered rastport.

    SEE ALSO
    DrawCircle macro
    graphics/gfxmacros.h
    graphics/rastport.h


graphics.library/ExtendFont

   NAME
    ExtendFont -- ensure tf_Extension has been built for a font (V36)

   SYNOPSIS
    success = ExtendFont(font, fontTags)
    D0                   A0    A1

    ULONG ExtendFont(struct TextFont *, struct TagItem *);

    success = ExtendFontTags(font, Tag1, ...)  (V39)

    ULONG ExtendFontTags(struct TextFont *, ULONG, ...);

   FUNCTION
    To extend a TextFont structure.

   INPUTS
    font - The font to extend.
    fontTags - An optional taglist.  If NULL, then a default is used.
               Currently, the only tag defined is TA_DeviceDPI.

   RESULT
    success - 1 if the TextFont was properly extended, else 0.

   NOTES
    The varargs stub was missing from amiga.lib until V39.

   SEE ALSO
    graphics/text.h


graphics.library/FindColor

   NAME
    FindColor -- Find the closest matching color in a colormap. (V39)

   SYNOPSIS
    color = FindColor(  cm,  R,   G,    B , maxpen)
                       a3   d1   d2    d3   d4

    ULONG FindColor( struct ColorMap *, ULONG, ULONG, ULONG,LONG);

   INPUTS
    cm = colormap
    R = red level   (32 bit left justified fraction)
    G = green level (32 bit left justified fraction)
    B = blue level  (32 bit left justified fraction)
    MaxPen = the maximum entry in the color table to search. A value of
            -1 will limt the search to only those pens which could be
            rendered in (for instance, it will not examine the sprite
            colors on a 4 color screen).

   RESULT
    The system will attempt to find the color in the passed colormap
    which most closely matches the RGB values passed. No new pens will
    be allocated, and you should not ReleasePen() the returned pen.
    This function is not sensitive to palette sharing issues. Its
    intended use is for:

            (a) programs which pop up on public screens when those
                screens are not using palette sharing. You might
                use this function as a fallback when ObtainBestPenA()
                says that there are no sharable pens.

            (b) Internal color matching by an application which is
                either running on a non-public screen, or which
                wants to match colors to an internal color table
                which may not be associated with any displayed screen.

   BUGS

   NOTES
    In order to use the MaxPen=-1 feature, you must have initialized
    palette sharing via AttachPalExtra() (all intuition screens do this).
    Otherwise, MaxPen=-1 will search all colors in the colormap.

   SEE ALSO
    ObtainBestPenA() GetColorMap() ObtainPen() ReleasePen()


graphics.library/FreeBitMap

   NAME
    FreeBitMap -- free a bitmap created by AllocBitMap (V39)

   SYNOPSIS
    FreeBitMap(bm)
               a0

    VOID FreeBitMap(struct BitMap *)

   FUNCTION
    Frees bitmap and all associated bitplanes

   INPUTS
    bm  =  A pointer to a BitMap structure. Passing a NULL-pointer
           (meaning "do nothing") is OK.

   BUGS

   NOTES
    Be careful to insure that any rendering done to the bitmap has
    completed (by calling WaitBlit()) before you call this function.

   SEE ALSO
    AllocBitMap()


graphics.library/FreeColorMap

   NAME
       FreeColorMap -- Free the ColorMap structure and return memory
                        to free memory pool.

   SYNOPSIS
       FreeColorMap( colormap )
                       a0

    void FreeColorMap(struct ColorMap *);

   FUNCTION
    Return the memory to the free memory pool that was allocated
    with GetColorMap.

   INPUTS
    colormap - pointer to ColorMap allocated with GetColorMap.

          Passing a NULL pointer (meaning "do nothing") is
          acceptable (V39).

   RESULT
    The space is made available for others to use.

   BUGS

   SEE ALSO
       SetRGB4() GetColorMap() graphics/view.h


graphics.library/FreeDBufInfo

   NAME
       FreeDBufInfo -- free information for multi-buffered animation (V39)

   SYNOPSIS
       FreeDBufInfo(db)
                 a1

    void FreeDBufInfo(struct DBufInfo *)

   FUNCTION
    Frees a structure obtained from AllocDBufInfo

   INPUTS
       db  =  A pointer to a DBufInfo.

   BUGS

   NOTES
    FreeDBufInfo(NULL) is a no-op.

   SEE ALSO
    AllocDBufInfo() ChangeVPBitMap()


graphics.library/FreeRaster

   NAME
       FreeRaster -- Release an allocated area to the system free memory pool
.

   SYNOPSIS
       FreeRaster( p, width, height)
           a0   d0:16  d1:16

    void FreeRaster( PLANEPTR, USHORT, USHORT);

   FUNCTION
    Return the memory associated with this PLANEPTR of size
    width and height to the MEMF_CHIP memory pool.

   INPUTS
       p  =  a pointer to a memory space  returned  as  a
             result of a call to AllocRaster.

    width - the width in bits of the bitplane.
    height - number of rows in bitplane.

   BUGS

   NOTES
       Width and height should be the same values with which you
       called AllocRaster in the first place.

   SEE ALSO
    AllocRaster() graphics/gfx.h


graphics.library/FreeSpriteData

   NAME
    FreeSpriteData -- free sprite data allocated by AllocSpriteData() (V39)

   SYNOPSIS
    FreeSpriteData(extsp)
            a2

    void FreeSpriteData(struct ExtSprite *);

   FUNCTION

   INPUTS
    extsp - The extended sprite structure to be freed. Passing NULL is a
    NO-OP.

   SEE ALSO
    FreeSpriteData() FreeSprite() ChangeSprite() MoveSprite() GetExtSprite()
    AllocBitMap() graphics/sprite.h


graphics.library/GetAPen

   NAME
       GetAPen -- Get the A Pen value for a RastPort (V39).

   SYNOPSIS
       pen = GetAPen  ( rp )
     d0		 a0

    ULONG GetAPen(struct RastPort *)

   FUNCTION
    Return the current value of the A pen for the rastport. This function
    should be used instead of peeking the structure directly, because future
    graphics devices may store it differently, for instance, using more bits.

   INPUTS
       rp  =  a pointer to a valid RastPort structure.

   BUGS

   NOTES

   SEE ALSO
    SetAPen() graphics/gfx.h


graphics.library/GetBitMapAttr

   NAME
    GetBitMapAttr -- Returns information about a bitmap (V39)

   SYNOPSIS
    value=GetBitMapAttr(bitmap,attribute_number);
      d0	                 a0       d1

    ULONG GetBitMapAttr(struct BitMap *,ULONG);

   FUNCTION
    Determines information about a bitmap. This function should be used
    instead of reading the bitmap structure fields directly. This will
    provide future compatibility.

   INPUTS
    bm  =  A pointer to a BitMap structure.

    attribute_number = A number telling graphics which attribute
                       of the bitmap should be returned:

                    BMA_HEIGHT returns the height in pixels
                    BMA_WIDTH  returns the width in pixels.
                    BMA_DEPTH  returns the depth. This is the number of
                            bits which are required to store the information
                            for one pixel in the bitmap.
                    BMA_FLAGS  returns a longword bitfield describing
                            various attributes which the bitmap may have.
                            Currently defined flags are BMF_DISPLAYABLE,
                            BMF_INTERLEAVED (see AllocBitMap()). The flag
                            BMF_STANDARD returns will be set if the
                            bitmap is represented as planar data in Amiga
                            Chip RAM.

   BUGS

   NOTES

    Unknown attributes are reserved for future use, and return zero.

    BMF_DISPLAYABLE will only be set if the source bitmap meets all of the
    required alignment restrictions. A bitmap which does not meet these
    restrictions may still be displayable at some loss of efficiency.

    Size values returned by this function may not exactly match the values
    which were passed to AllocBitMap(), due to alignment restrictions.

   SEE ALSO
    AllocBitMap()


graphics.library/GetBPen

   NAME
       GetBPen -- Get the B Pen value for a RastPort (V39).

   SYNOPSIS
       pen = GetBPen  ( rp )
    d0	   	 a0

    ULONG GetBPen(struct RastPort *)

   FUNCTION
    Return the current value of the B pen for the rastport. This function
    should be used instead of peeking the structure directly, because future
    graphics devices may store it differently, using more bits.

   INPUTS
       rp  =  a pointer to a valid RastPort structure.

   BUGS

   NOTES

   SEE ALSO
    SetBPen() graphics/gfx.h


graphics.library/GetColorMap

   NAME
       GetColorMap -- allocate and initialize Colormap

   SYNOPSIS
       cm = GetColorMap( entries )
       d0		    d0

    struct ColorMap *GetColorMap( ULONG);

   FUNCTION
       Allocates, initializes and returns a pointer to a ColorMap
       data structure, later enabling calls to SetRGB4/SetRGB32
       and LoadRGB4/LoadRGB32 to load colors for a view port. The
       ColorTable pointer in the ColorMap structure points to a
       hardware specific colormap data structure. You should not
       count on it being anything you can understand. Use
       GetRGB4()/GetRGB32() to query it or SetRGB4CM/SetRGB32CM
       to set it directly.

   INPUTS
    entries - number of entries for this colormap

    RESULT
    The pointer value returned by this routine, if nonzero,
       may be stored into the ViewPort.ColorMap pointer.
       If a value of 0 is returned, the system was unable
       to allocate enough memory space for the required
       data structures.

   BUGS

   SEE ALSO
       SetRGB4() FreeColorMap()


graphics.library/GetDrMd

   NAME
       GetDrMd -- Get the draw mode value for a RastPort (V39).

   SYNOPSIS
       mode = GetDrMd  ( rp )
    d0                a0

    ULONG GetDrMd(struct RastPort *)

   FUNCTION
    Return the current value of the draw mode for the rastport. This function
    should be used instead of peeking the structure directly, because future
    graphics devices may store it differently.

   INPUTS
       rp  =  a pointer to a valid RastPort structure.

   BUGS

   NOTES

   SEE ALSO
    SetDrMd() graphics/gfx.h


graphics.library/GetExtSpriteA

   NAME
    GetExtSpriteA -- Attempt to get a sprite for the extended sprite
                     manager. (V39)
    GetExtSprite -- varargs stub for GetExtSpriteA. (V39)

   SYNOPSIS
    Sprite_Number = GetExtSpriteA( sprite, tags )  (V39)
        d0			        a2      a1

    LONG GetExtSpriteA( struct ExtSprite *, struct TagItem * );

    spritenum=GetExtSprite(sprite,tags,...);

   FUNCTION
    Attempt to allocate one of the eight sprites for private use
    with the extended sprite manager.

   INPUTS
    sprite - ptr to programmer's ExtSprite (from AllocSpriteData()).
    tags - a standard tag list:

        GSTAG_SPRITE_NUM	specifies a specific sprite to get by number.

        GSTAG_ATTACHED specifies that you wish to get a sprite pair.
            the tag data field points to a ExtSprite structure
            for the second sprite. You must free both sprites.

   RESULTS
    Sprite_number = a sprite number or -1 for an error.
        This call will fail if no sprites could be allocated, or
        if you try to allocate a sprite which would require
        a mode change when there are other sprites of incompatible
        modes in use.

   BUGS

    GSTAG_ATTACHED does not work in version 39. When running under V39,
    you should attach the second sprite with a separate GetExtSprite call.

   SEE ALSO
    FreeSprite() ChangeSprite() MoveSprite() GetSprite() graphics/sprite.h


graphics.library/GetOPen

   NAME
       GetOPen -- Get the O Pen value for a RastPort (V39).

   SYNOPSIS
       pen = GetOPen  ( rp )
    d0		 a0

    ULONG GetOPen(struct RastPort *)

   FUNCTION
    Return the current value of the O pen for the rastport. This function
    should be used instead of peeking the structure directly, because future
    graphics devices may store it differently, for instance, using more bits.

   INPUTS
       rp  =  a pointer to a valid RastPort structure.

   BUGS

   NOTES

   SEE ALSO
    SetOutlinePen() graphics/gfx.h


graphics.library/GetRGB32

   NAME
    GetRGB32 -- Set a series of color registers for this Viewport. (V39)

   SYNOPSIS
    GetRGB32(  cm,  firstcolor, ncolors, table )
               a0   d0   		d1    a1

       void GetRGB32( struct ColorMap *, ULONG, ULONG, ULONG *);

   INPUTS
    cm = colormap
    firstcolor = the first color register to get
    ncolors = the number of color registers to set.
    table=a pointer to a series of 32-bit RGB triplets.

   RESULT
    The ULONG data pointed to by 'table' will be filled with the 32 bit
    fractional RGB values from the colormap.
   BUGS

   NOTES
    'Table' should point to at least ncolors*3 longwords.

   SEE ALSO
    LoadRGB4() GetColorMap() LoadRGB32() SetRGB32CM() graphics/view.h


graphics.library/GetRPAttrA

   NAME
       GetRPAttrA -- examine rastport settings via a tag list
    GetRPAttrs  -- varargs stub for GetRPAttrA

   SYNOPSIS
       GetRPAttrA(rp,tags)
                  a0   a1

    void GetRPAttrA(struct RastPort *, struct TagItem *);

    GetRPAttrs(rp,attr1,&result1,...);

   FUNCTION
       Read the settings of a rastport into variables. The
    ti_Tag field of the TagItem specifies which attribute
    should be read, and the ti_Data field points at the
    location where the result hsould be stored. All current
    tags store the return data as LONGs (32 bits).

    currently available tags are:

        RPTAG_Font		Font for Text()
        RPTAG_SoftStyle		style for text (see graphics/text.h)
        RPTAG_APen		Primary rendering pen
        RPTAG_BPen		Secondary rendering pen
        RPTAG_DrMd 		Drawing mode (see graphics/rastport.h)
        RPTAG_OutLinePen 	Area Outline pen
        RPTAG_WriteMask 	Bit Mask for writing.
        RPTAG_MaxPen 		Maximum pen to render (see SetMaxPen())
        RPTAG_DrawBounds	Determine the area that will be rendered
                    into by rendering commands. Can be used
                    to optimize window refresh. Pass a pointer
                    to a rectangle in the tag data. On return,
                    the rectangle's MinX will be greater than
                    its MaxX if there are no active cliprects.

   INPUTS
    rp - pointer to the RastPort to examine.
    tags - a standard tag list specifying the attributes to be read,
        and where to store their values.

   RESULT

   BUGS

   SEE ALSO
    GetAPen() GetBPen() GetDrMd() GetOutLinePen()
    SetRPAttrA() graphics/rpattr.h


graphics.library/GetSprite

   NAME
    GetSprite -- Attempt to get a sprite for the simple sprite manager.

   SYNOPSIS
    Sprite_Number = GetSprite( sprite, pick )
        d0			    a0      d0

    WORD GetSprite( struct SimpleSprite *, WORD );

   FUNCTION
    Attempt to allocate one of the eight sprites for private use
    with the simple sprite manager. This must be done before using
    further calls to the simple sprite machine. If the programmer
    wants to use 15 color sprites, they must allocate both sprites
    and set the 'SPRITE_ATTACHED' bit in the odd sprite's posctldata
    array.

   INPUTS
    sprite - ptr to programmers SimpleSprite structure.
    pick - number in the range of 0-7 or
      -1 if programmer just wants the next one.

   RESULTS
    If pick is 0-7 attempt to allocate the sprite. If the sprite
    is already allocated then return -1.
    If pick -1 allocate the next sprite starting search at 0.
    If no sprites are available return -1 and fill -1 in num entry
    of SimpleSprite structure.
    If the sprite is available for allocation, mark it allocated
    and fill in the 'num' entry of the SimpleSprite structure.
    If successful return the sprite number.

   BUGS

   SEE ALSO
    FreeSprite() ChangeSprite() MoveSprite() GetSprite() graphics/sprite.h


graphics.library/GfxFree

   NAME
       GfxFree -- free a graphics extended data structure (V36)

   SYNOPSIS
       GfxFree( node );
                 a0

    void GfxFree(struct ExtendedNode *);

   FUNCTION
    Free a special graphics extended data structure (each of which
    begins with an ExtendedNode structure).

   INPUTS
    node = pointer to a graphics extended data structure obtained via
           GfxNew().

   RESULT
    the node is deallocated from memory. graphics will disassociate
    this special graphics extended node from any associated data
    structures, if necessary, before freeing it (see GfxAssociate()).

   BUGS
    an Alert() will be called if you attempt to free any structure
    other than a graphics extended data structure obtained via GfxFree().

   SEE ALSO
    graphics/gfxnodes.h GfxNew() GfxAssociate() GfxLookUp()


graphics.library/InitRastPort

   NAME
    InitRastPort -- Initialize raster port structure

   SYNOPSIS
       InitRastPort( rp )
              a1

    void InitRastPort(struct RastPort *rp);

   FUNCTION
       Initialize a RastPort structure to standard values.

   INPUTS
    rp	= pointer to a RastPort structure.

   RESULT
    all entries in RastPort get zeroed out, with the following exceptions:

        Mask, FgPen, AOLPen, and LinePtrn are set to -1.
        The DrawMode is set to JAM2
        The font is set to the standard system font

   NOTES
    The struct Rastport describes a control structure
       for a write-able raster. The RastPort structure
       describes how a complete single playfield display
       will be written into. A RastPort structure is
       referenced whenever any drawing or filling
       operations are to be performed on a section of
       memory.

       The section of memory which is being used in this
       way may or may not be presently a part of the
       current actual onscreen display memory. The name
       of the actual memory section which is linked to
       the RastPort is referred to here as a "raster" or
       as a bitmap.

       NOTE: Calling the routine InitRastPort only
       establishes various defaults. It does NOT
       establish where, in memory, the rasters are
       located. To do graphics with this RastPort the user
    must set up the BitMap pointer in the RastPort.

   BUGS

   SEE ALSO
       graphics/rastport.h


graphics.library/InitTmpRas

   NAME
    InitTmpRas -- Initialize area of local memory for usage by
            areafill, floodfill, text.

   SYNOPSIS
       InitTmpRas(tmpras, buffer, size)
                      a0	     a1     d0

    void InitTmpRas( struct TmpRas *, void *, ULONG );

   FUNCTION
    The area of memory pointed to by buffer is set up to be used
    by RastPort routines that may need to get some memory for
    intermediate operations in preparation to putting the graphics
    into the final BitMap.
    Tmpras is used to control the usage of buffer.

   INPUTS
    tmpras - pointer to a TmpRas structure to be linked into
        a RastPort
    buffer - pointer to a contiguous piece of chip memory.
    size - size in bytes of buffer

   RESULT
    makes buffer available for users of RastPort

   BUGS
    Would be nice if RastPorts could share one TmpRas.

   SEE ALSO
    AreaEnd() Flood() Text() graphics/rastport.h


graphics.library/InitVPort

   NAME
    InitVPort - Initialize ViewPort structure.

   SYNOPSIS
    InitVPort( vp )
           a0

    void InitViewPort( struct ViewPort * );

   FUNCTION
    Initialize ViewPort structure to default values.

   INPUTS
    vp - pointer to a ViewPort structure

   RESULT
    ViewPort structure set to all 0's. (1.0,1.1)
       New field added SpritePriorities, initialized to 0x24 (1.2)

   BUGS

   SEE ALSO
    MakeVPort() graphics/view.h


graphics.library/LoadRGB32

   NAME
    LoadRGB32 -- Set a series of color registers for this Viewport. (V39)

   SYNOPSIS
    LoadRGB32(  vp,  table )
                a0   a1

    void LoadRGB32( struct ViewPort *, ULONG *);

   INPUTS
    vp = viewport
    table = a pointer to a series of records which describe which colors to
            modify.
   RESULT
    The selected color registers are changed to match your specs.
   BUGS

   NOTES

    Passing a NULL "table" is ignored.
    The format of the table passed to this function is a series of records,
    each with the following format:

            1 Word with the number of colors to load
            1 Word with the first color to be loaded.
            3 longwords representing a left justified 32 bit rgb triplet.
            The list is terminated by a count value of 0.

       examples:
            ULONG table[]={1l<<16+0,0xffffffff,0,0,0} loads color register
                    0 with 100% red.
            ULONG table[]={256l<<16+0,r1,g1,b1,r2,g2,b2,.....0} can be used
                    to load an entire 256 color palette.

    Lower order bits of the palette specification will be discarded,
    depending on the color palette resolution of the target graphics
    device. Use 0xffffffff for the full value, 0x7fffffff for 50%,
    etc. You can find out the palette range for your screen by
    querying the graphics data base.

    LoadRGB32 is faster than SetRGB32, even for one color.

   SEE ALSO
    LoadRGB4() GetColorMap() GetRGB32() SetRGB32CM() graphics/view.h


graphics.library/LoadRGB4

   NAME
    LoadRGB4 -- Load RGB color values from table.

   SYNOPSIS
    LoadRGB4( vp, colors , count )
                 a0  	a1     d0:16

    void LoadRGB4( struct ViewPort *, UWORD *, WORD);

   FUNCTION
       load the count words of the colormap from table starting at
    entry 0.

   INPUTS
    vp - pointer to ViewPort, whose colors you wish to change
    colors - pointer to table of RGB values set up as an array
             of USHORTS
             background--  0x0RGB
            color1	  --  0x0RGB
            color2    --  0x0RGB
             etc.         UWORD per value.
        The colors are interpreted as 15 = maximum intensity.
                                      0 = minimum intensity.
    count	= number of UWORDs in the table to load into the
      colormap starting at color 0(background) and proceeding
      to the next higher color number

   RESULTS
    The ViewPort should have a pointer to a valid ColorMap to store
    the colors in.
    Updates the hardware copperlist to reflect the new colors.
    Updates the intermediate copperlist with the new colors.

   BUGS

    NOTE: Under V36 and up, it is not safe to call this function
    from an interrupt, due to semaphore protection of graphics
    copper lists.

   SEE ALSO
    SetRGB4() GetRGB4() GetColorMap() graphics/view.h


graphics.library/LockLayerRom

   NAME
    LockLayerRom -- Lock Layer structure by ROM(gfx lib) code.

   SYNOPSIS
    LockLayerRom( layer )
               a5

    void LockLayerRom( struct Layer * );

   FUNCTION
    Return when the layer is locked and no other task may
    alter the ClipRect structure in the Layer structure.
    This call does not destroy any registers.
    This call nests so that callers in this chain will not lock
    themselves out.
    Do not have the Layer locked during a call to intuition.
    There is a potential deadlock problem here, if intuition
    needs to get other locks as well.
    Having the layer locked prevents other tasks from using the
    layer library functions, most notably intuition itself. So
    be brief.
    layers.library's LockLayer is identical to LockLayerRom.

   INPUTS
    layer - pointer to Layer structure

   RESULTS
    The layer is locked and the task can render assuming the
    ClipRects will not change out from underneath it until
    an UnlockLayerRom is called.

   SEE ALSO
    UnlockLayerRom() layers.library/LockLayer() graphics/clip.h


graphics.library/MakeVPort

   NAME
    MakeVPort -- generate display copper list for a viewport.

   SYNOPSIS
    error =  MakeVPort( view, viewport )
     d0                   a0     a1

    ULONG MakeVPort( struct View *, struct ViewPort * );

   FUNCTION
    Uses information in the View, ViewPort, ViewPort->RasInfo to
    construct and intermediate copper list for this ViewPort.

   INPUTS
    view - pointer to a View structure
    viewport - pointer to a ViewPort structure
         The viewport must have valid pointer to a RasInfo.

   RESULTS
    constructs intermediate copper list and puts pointers in
    viewport.DspIns
    If the ColorMap ptr in ViewPort is NULL then it uses colors
    from the default color table.
    If DUALPF in Modes then there must be a second RasInfo pointed
    to by the first RasInfo

    From V39, MakeVPort can return a ULONG error value (previous versions
    returned void), to indicate that either not enough memory could be
    allocated for MakeVPort's use, or that the ViewPort mode
    and bitplane alignments are incorrect for the bitplane's depth.

    You should check for these error values - they are defined in
    <graphics/view.h>.

   BUGS
    In V37 and earlier, narrow Viewports (whose righthand edge is
    less than 3/4 of the way across the display) do not work properly.

   SEE ALSO
    InitVPort() MrgCop() graphics/view.h intuition.library/MakeScreen()
    intuition.library/RemakeDisplay() intuition.library/RethinkDisplay()


graphics.library/ModeNotAvailable

   NAME
    ModeNotAvailable -- check to see if a DisplayID isn't available. (V36)

   SYNOPSIS
    error =  ModeNotAvailable( modeID )
    d0		           d0

    ULONG	ModeNotAvailable( ULONG);

   FUNCTION
    returns an error code, indicating why this modeID is not available,
    or NULL if there is no reason known why this mode should not be there.

   INPUTS
    modeID -- a 32 bit DisplayInfoRecord identifier.

   RESULT
    error -- a general indication of why this modeID is not available,
         or NULL if there is no reason why it shouldn't be available.

   NOTE
    ULONG return values from this function are a proper superset of the
    DisplayInfo.NotAvailable field (defined in graphics/displayinfo.h).

    ModeNotAvailable() will return INVALID_ID when given a non-existant
    moe ID.

   BUGS

   SEE ALSO
    graphics/displayinfo.h, GetVPModeID()


graphics.library/Move

   NAME
    Move -- Move graphics pen position.

   SYNOPSIS
    Move( rp,   x,    y)
          a1  d0:16 d1:16

    void Move( struct RastPort *, SHORT, SHORT );

   FUNCTION
    Move graphics pen position to (x,y) relative to upper left (0,0)
    of RastPort. This sets the starting point for subsequent Draw()
    and Text() calls.

   INPUTS
    rp - pointer to a RastPort structure
    x,y - point in the RastPort

   RESULTS

   BUGS

   SEE ALSO
    Draw() graphics/rastport.h


graphics.library/MoveSprite

   NAME
    MoveSprite -- Move sprite to a point relative to top of viewport.

   SYNOPSIS
    MoveSprite(vp, sprite, x, y)
               A0  A1      D0 D1

    void MoveSprite(struct ViewPort *,struct SimpleSprite *, WORD, WORD);

   FUNCTION
    Move sprite image to new place on display.

   INPUTS
    vp - pointer to ViewPort structure
         if vp = 0, sprite is positioned relative to View.
    sprite - pointer to SimpleSprite structure
    (x,y)  - new position relative to top of viewport or view.

   RESULTS
    Calculate the hardware information for the sprite and
    place it in the posctldata array. During next video display
    the sprite will appear in new position.

   BUGS
    Sprites really appear one pixel to the left of the position you specify.
    This bug affects the apparent display position of the sprite on the
    screen,	but does not affect the numeric position relative to the
    viewport or view. This behaviour only applies to SimpleSprites,
    not to ExtSprites.

   SEE ALSO
    FreeSprite()  ChangeSprite()  GetSprite()  graphics/sprite.h


graphics.library/MrgCop

   NAME
       MrgCop -- Merge together coprocessor instructions.

   SYNOPSIS
       error = MrgCop( View )
       d0              A1

    ULONG MrgCop( struct View * );

   FUNCTION
       Merge together the display, color, sprite and user coprocessor
       instructions into a single coprocessor instruction stream.  This
       essentially creates a per-display-frame program for the coprocessor.
       This function MrgCop is used, for example, by the graphics animation
       routines which effectively add information into an essentially
       static background display.  This changes some of the user
       or sprite instructions, but not those which have formed the
       basic display in the first place.  When all forms of coprocessor
       instructions are merged together, you will have a complete per-
       frame instruction list for the coprocessor.

       Restrictions:  Each of the coprocessor instruction lists MUST be
       internally sorted in min to max Y-X order.  The merge routines
       depend on this! Each list must be terminated using CEND(copperlist).

   INPUTS
       View - a pointer to the view structure whose coprocessor
              instructions are to be merged.

   RESULT
       The view structure will now contain a complete, sorted/merged
       list of instructions for the coprocessor, ready to be used by
       the display processor.  The display processor is told to use
       this new instruction stream through the instruction LoadView().

    From V39, MrgCop() can return a ULONG error value (previous versions
    returned void), to indicate that either there was insufficient memory
    to build the system copper lists, or that MrgCop() had no work to do
    if, for example, there were no ViewPorts in the list.

    You should check for these error values - they are defined in
    <graphics/view.h>.

   BUGS

   SEE ALSO
       InitVPort() MakeVPort() LoadView() graphics/view.h
    intuition.library/RethinkDisplay()


graphics.library/ObtainBestPenA

   NAME
    ObtainBestPenA --- Search for the closest color match, or allocate a
                       new one. (V39)
    ObtainBestPen  --- varargs stub for ObtainBestPenA

   SYNOPSIS
    color | -1 =ObtainBestPenA(  cm,  R,   G,    B,    taglist)
                                 a0   d1   d2    d3       a1

    LONG ObtainBestPenA( struct ColorMap *, ULONG, ULONG,
            ULONG, struct TagItem *);

    color = ObtainBestPen(cm,r,g,b,tags....);

   INPUTS
    cm = colormap
    R = red level   (32 bit left justified fraction)
    G = green level (32 bit left justified fraction)
    B = blue level  (32 bit left justified fraction)
    taglist = a pointer to a standard tag list specifying the color
              matching settings desired:

            OBP_Precision - specifies the desired precision for the
                    match. Should be PRECISION_GUI, PRECISION_ICON, or
                    PRECISION_IMAGE or PRECISION_EXACT.
                    Defaults to PRECISION_IMAGE.

            OBP_FailIfBad - specifies that you want ObtainBestPen to return
                    a failure value if there is not a color within the
                    given tolerance, instead of returning the closest color.
                    With OBP_FailIfBad==FALSE, ObtainBestPen will only fail
                    if the ViewPort contains no sharable colors.
                    Defaults to FALSE.

   FUNCTION
    This function can be used by applications to figure out
    what pen to use to represent a given color.

    The system will attempt to find the color in your viewport closest
    to the specified color. If there is no color within your tolerance,
    then a new one will be allocated, if available. If none is available,
    then the closest one found will be returned.

   RESULT
    The correct pen value, or -1 if no sharable palette entries are available.

   BUGS

   NOTES
    If this call succceeds, then you must call ReleasePen() when you are
    done with the color.

    The error metric used for ObtainBestPen() is based on the magnitude
    squared between the two RGB values, scaled by the percentage of free
    entries.

   SEE ALSO
    GetColorMap() ObtainPen() ReleasePen()


graphics.library/ObtainPen

   NAME
    ObtainPen -- Obtain a free palette entry for use by your program. (V39)

   SYNOPSIS
    n = ObtainPen( cm, n, r, g, b, flags)
    d0	       a0 d0  d1 d2 d3  d4

    LONG ObtainPen(struct ColorMap *,ULONG,ULONG,ULONG,ULONG,ULONG);

   FUNCTION
    Attempt to allocate an entry in the colormap for use by the application.
    If successful, you should ReleasePen() this entry after you have finished
    with it.

    Applications needing exclusive use of a color register (say for color
    cycling) will typically call this function with n=-1. Applications needing
    only the shared use of a color will typically use ObtainBestPenA() instead.
    Other uses of this function are rare.

   INPUTS
    cm  =  A pointer to a color map created by GetColorMap().
    n   =  The index of the desired entry, or -1 if any one is acceptable
    rgb =  The RGB values (32 bit left justified fractions) to set the new
           palette entry to.
    flags= PEN_EXCLUSIVE - tells the system that you want exclusive
           (non-shared) use of this pen value. Default is shared access.

           PEN_NO_SETCOLOR - tells the system to not change the rgb values
           for the selected pen. Really only makes sense for exclusive pens.

   RESULTS

    n   =  The allocated pen. -1 will be returned if there is no pen available
           for you.

   BUGS

   NOTES
    When you allocate a palette entry in non-exclusive mode, you
    should not change it (via SetRGB32), because other programs on the
    same screen may be using it. With PEN_EXCLUSIVE mode, you can
    change the returned entry at will.

    To avoid visual artifacts, you should not free up a palette
    entry until you are sure that your application is not displaying
    any pixels in that color at the time you free it. Otherwise, another
    task could allocate and set that color index, thus changing the colors
    of your pixels.

    Generally, for shared access, you should use ObtainBestPenA()
    instead, since it will not allocate a new color if there is one
    "close enough" to the one you want already.
    If there is no Palextra attached to the colormap, then this
    routine will always fail.

   SEE ALSO
    GetColorMap() ReleasePen() AttachPalExtra() ObtainBestPenA()


graphics.library/OpenFont

   NAME
    OpenFont -- Get a pointer to a system font.

   SYNOPSIS
    font = OpenFont(textAttr)
    D0              A0

    struct TextFont *OpenFont(struct TextAttr *);

   FUNCTION
    This function searches the system font space for the graphics
    text font that best matches the attributes specified.  The
    pointer to the font returned can be used in subsequent
    SetFont and CloseFont calls.  It is important to match this
    call with a corresponding CloseFont call for effective
    management of ram fonts.

   INPUTS
    textAttr - a TextAttr or TTextAttr structure that describes the
               text font attributes desired.

   RESULT
    font is zero if the desired font cannot be found.  If the named
    font is found, but the size and style specified are not
    available, a font with the nearest attributes is returned.

   BUGS
    Prior to V39 this function would return a TextFont pointer
    for any font which matched exactly in Y size, regardless of
    differences in DPI, or DotSize.

    As part of fixing this bug it is REQUIRED that you use pass the
    same TextAttr (or TTextAttr) to this function that was used when
    OpenDiskFont() was called.

    OpenFont(), and OpenDiskFont() use WeighTAMatch() to measure
    how well two fonts match.  WeightTAMatch() was a public function
    in graphics.library V36-V37; it is now a system PRIVATE function
    as of V39.

   SEE ALSO
    CloseFont()  SetFont()
    diskfont.library/OpenDiskFont  graphics/text.h
    intuition/intuition.h


graphics.library/QBlit

   NAME

    QBlit -- Queue up a request for blitter usage

   SYNOPSIS
    QBlit( bp )
           a1

    void QBlit( struct bltnode * );

   FUNCTION
    Link a request for the use of the blitter to the end of the
       current blitter queue.  The pointer bp points to a blit structure
       containing, among other things, the link information, and the
       address of your routine which is to be called when the blitter
       queue finally gets around to this specific request.  When your
       routine is called, you are in control of the blitter ... it is
       not busy with anyone else's requests.  This means that you can
       directly specify the register contents and start the blitter.
       See the description of the blit structure and the uses of QBlit
       in the section titled Graphics Support in the OS Kernel Manual.
       Your code must be written to run either in supervisor or user
       mode on the 68000.

   INPUTS
    bp - pointer to a blit structure

   RESULT
    Your routine is called when the blitter is ready for you.
    In general requests for blitter usage through this channel are
    put in front of those who use the blitter via OwnBlitter and
    DisownBlitter. However for small blits there is more overhead
    using the queuer than Own/Disown Blitter.

   NOTES
    Code which uses QBlit(), or QBSBlit() should make use of
    the pointer to a cleanup routine in the bltnode structure.
    The cleanup routine may be called on the context of an
    interrupt, therefore the routine may set a flag, and signal
    a task, but it may not call FreeMem() directly.  Use of
    the cleanup routine is the only safe way to signal that
    your bltnode has completed.

   BUGS
    QBlit(), and QBSBlit() have been rewritten for V39 due to
    various long standing bugs in earlier versions of this code.

   SEE ALSO
    QBSBlit() hardware/blit.h


graphics.library/QBSBlit

   NAME

    QBSBlit -- Synchronize the blitter request with the video beam.

   SYNOPSIS

    QBSBlit( bsp )
         a1

    void QBSBlit( struct bltnode * );

   FUNCTION
    Call a user routine for use of the blitter, enqueued separately from
       the QBlit queue.  Calls the user routine contained in the blit
       structure when the video beam is located at a specified position
       onscreen.   Useful when you are trying to blit into a visible part
       of the screen and wish to perform the data move while the beam is
       not trying to display that same area.  (prevents showing part of
       an old display and part of a new display simultaneously).  Blitter
       requests on the QBSBlit queue take precedence over those on the
       regular blitter queue. The beam position is specified in the blitnode.

   INPUTS
    bsp - pointer to a blit structure.  See description in the
             Graphics Support section of the manual for more info.

   RESULT
       User routine is called when the QBSBlit queue reaches this
       request AND the video beam is in the specified position.
       If there are lots of blits going on and the video beam
       has wrapped around back to the top it will call all the
       remaining bltnodes as fast as it can to try and catch up.

   NOTES
       QBlit(), and QBSBlit() have been rewritten for V39.  Queued
       blits are now handled in FIFO order.  Tasks trying to
       OwnBlitter() are now given a fair share of the total
       blitter time available.  QBSBlit() is no longer queued
       separately from nodes added by QBlit().  This fixes the
       ordering dependencies listed under BUGS in prior autodoc
       notes.

   BUGS

   SEE ALSO
    QBlit() hardware/blit.h


graphics.library/ReadPixelArray8

   NAME
    ReadPixelArray8 -- read the pen number value of a rectangular array
    of pixels starting at a specified x,y location and continuing
    through to another x,y location within a certain RastPort. (V36)

   SYNOPSIS
    count = ReadPixelArray8(rp,xstart,ystart,xstop,ystop,array,temprp)
    D0                      A0 D0:16  D1:16  D2:16 D3:16 A2    A1

     LONG ReadPixelArray8(struct  RastPort *, UWORD, UWORD, UWORD, UWORD,
       UBYTE *, struct RastPort *);

   FUNCTION
    For each pixel in a rectangular region, combine the bits from each
    of the bit-planes used to describe a particular RastPort into the pen
    number selector which that bit combination normally forms for the
    system hardware selection of pixel color.

   INPUTS
    rp    -  pointer to a RastPort structure
    (xstart,ystart) - starting point in the RastPort
    (xstop,ystop)   - stopping point in the RastPort
    array - pointer to an array of UBYTEs from which to fetch the pixel data
            allocate at least ((((width+15)>>4)<<4)*(ystop-ystart+1)) bytes.
    temprp - temporary rastport (copy of rp with Layer set == NULL,
             temporary memory allocated for
             temprp->BitMap with Rows set == 1,
             temprp->BytesPerRow == (((width+15)>>4)<<1),
             and temporary memory allocated for
             temprp->BitMap->Planes[])

   RESULT
    For each pixel in the array:
        Pen - (0..255) number at that position is returned
    count   - the number of pixels read.

   NOTE
    xstop must be >= xstart
    ystop must be >= ystart

   BUGS

   SEE ALSO
    ReadPixel()  ReadPixelLine8()  graphics/rastport.h


graphics.library/ReleasePen

   NAME
    ReleasePen -- Release an allocated palette entry to the free pool. (V39)

   SYNOPSIS
    ReleasePen( cm, n)
                a0 d0

    void ReleasePen( Struct ColorMap *, ULONG);

   FUNCTION
    Return the palette entry for use by other applications.
    If the reference count for this palette entry goes to zero,
    then it may be reset to another RGB value.

   INPUTS
       cm  =  A pointer to a color map created by GetColorMap().

    n   =  A palette index obtained via any of the palette allocation
           functions. Passing a -1 will result in this call doing
           nothing.

   BUGS

   NOTES
    This function works for both shared and exclusive palette entries.

   SEE ALSO
    GetColorMap() ObtainPen() ObtainBestPenA()


graphics.library/ScrollRaster

   NAME
   ScrollRaster -- Push bits in rectangle in raster around by
                   dx,dy towards 0,0 inside rectangle.
   SYNOPSIS
   ScrollRaster(rp, dx, dy, xmin, ymin, xmax, ymax)
                A1  D0  D1  D2    D3    D4    D5

   void ScrollRaster
        (struct RastPort *, WORD, WORD, WORD, WORD, WORD, WORD);

   FUNCTION
   Move the bits in the raster by (dx,dy) towards (0,0)
   The space vacated is RectFilled with BGPen.
   Limit the scroll operation to the rectangle defined
   by (xmin,ymin)(xmax,ymax). Bits outside will not be
   affected. If xmax,ymax is outside the rastport then use
   the lower right corner of the rastport.
   If you are dealing with a SimpleRefresh layered RastPort you
   should check rp->Layer->Flags & LAYERREFRESH to see if
   there is any damage in the damage list.  If there is you should
   call the appropriate BeginRefresh(Intuition) or BeginUpdate(graphics)
   routine sequence.

   INPUTS
   rp - pointer to a RastPort structure
   dx,dy are integers that may be positive, zero, or negative
   xmin,ymin - upper left of bounding rectangle
   xmax,ymax - lower right of bounding rectangle

   EXAMPLE
   ScrollRaster(rp,0,1,minx,miny,maxx,maxy) /* shift raster up by one row */
   ScrollRaster(rp,-1,-1,minx,miny,maxx,maxy)
          /* shift raster down and to the right by 1 pixel

   BUGS
   In 1.2/V1.3 if you ScrollRaster a SUPERBITMAP exactly left or
   right, and there is no TmpRas attached to the RastPort, the system
   will allocate one for you, but will never free it or record its
   location. This bug has been fixed for V36.  The workaround for
   1.2/1.3 is to attach a valid TmpRas of size at least
   MAXBYTESPERROW to the RastPort before the call.

   Beginning with V36 ScrollRaster adds the shifted areas into the
   damage list for SIMPLE_REFRESH windows. Due to unacceptable
   system overhead, the decision was made NOT to propagate this
   shifted area damage for SMART_REFRESH windows.

   SEE ALSO
   ScrollRasterBF() graphics/rastport.h


graphics.library/ScrollRasterBF

   NAME
   ScrollRasterBF -- Push bits in rectangle in raster around by
                   dx,dy towards 0,0 inside rectangle. Newly empty areas
           will be filled via EraseRect(). (V39)

   SYNOPSIS
   ScrollRasterBF(rp, dx, dy, xmin, ymin, xmax, ymax)
                A1  D0  D1  D2    D3    D4    D5

   void ScrollRasterBF
        (struct RastPort *, WORD, WORD, WORD, WORD, WORD, WORD);

   FUNCTION
   Move the bits in the raster by (dx,dy) towards (0,0)
   The space vacated is filled by calling EraseRect().
   Limit the scroll operation to the rectangle defined
   by (xmin,ymin)(xmax,ymax). Bits outside will not be
   affected. If xmax,ymax is outside the rastport then use
   the lower right corner of the rastport.
   If you are dealing with a SimpleRefresh layered RastPort you
   should check rp->Layer->Flags & LAYERREFRESH to see if
   there is any damage in the damage list.  If there is you should
   call the appropriate BeginRefresh(Intuition) or BeginUpdate(graphics)
   routine sequence.

   INPUTS
   rp - pointer to a RastPort structure
   dx,dy are integers that may be positive, zero, or negative
   xmin,ymin - upper left of bounding rectangle
   xmax,ymax - lower right of bounding rectangle

   NOTES

   This call is exactly the same as ScrollRaster, except that it calls
   EraseRect() instead of RectFill() when clearing the newly exposed
   area. This allows use of a custom layer backfill hook.

   BUGS

   SEE ALSO
   ScrollRaster() EraseRect() intuition.library/ScrollWindowRaster()
   graphics/rastport.h


graphics.library/ScrollVPort

   NAME
    ScrollVPort -- Reinterpret RasInfo information in ViewPort to reflect
            the current Offset values.

   SYNOPSIS
    ScrollVPort( vp )
             a0

    void ScrollVPort(struct ViewPort *vp);

   FUNCTION
    After the programmer has adjusted the Offset values in
    the RasInfo structures of ViewPort, change the
    the copper lists to reflect the the Scroll positions.
    Changing the BitMap ptr in RasInfo and not changing the
    the Offsets will effect a double buffering affect.

   INPUTS
       vp - pointer to a ViewPort structure
         that is currently be displayed.
   RESULTS
    modifies hardware and intermediate copperlists to reflect
    new RasInfo

   BUGS
       pokes not fast enough to avoid some visible hashing of display (V37)
    This function was re-written in V39 and is ~10 times faster than
    before.

   SEE ALSO
    MakeVPort() MrgCop() LoadView()  graphics/view.h


graphics.library/SetABPenDrMd

   NAME
     SetABPenDrMd -- Set pen colors and draw mode for a RastPort. (V39)

   SYNOPSIS
    SetABPenDrMd( rp, apen, bpen, mode )
                   a1  d0     d1    d2

    void SetABPenDrMd( struct RastPort *, ULONG, ULONG, ULONG );

   FUNCTION
    Set the pen values and drawing mode for lines, fills and text.
    Get the bit definitions from rastport.h

   INPUTS
    rp - pointer to RastPort structure.
    apen - primary pen value
    bpen - secondary pen value
    mode - 0-255, some combinations may not make much sense.

   RESULT
    The mode set is dependent on the bits selected.
    Changes minterms to reflect new drawing mode and colors.
    Sets line drawer to restart pattern.

    NOTES
    This call is essentially the same as a sequence of
    SetAPen()/SetBPen()/SetDrMD() calls, except that it is
    significantly faster. The minterms will only be generated
    once, or not at all if nothing changed (warning to illegal
    RastPort pokers!).

   BUGS

   SEE ALSO
    SetAPen() SetBPen() SetDrMd() graphics/rastport.h


graphics.library/SetChipRev

   NAME
    SetChipRev -- turns on the features of a Chip Set  (V39)

   SYNOPSIS
    chiprevbits = SetChipRev(ChipRev)
                               d0

    ULONG SetChipRev(ULONG);

   FUNCTION
    Enables the features of the requested Chip Set if available,
    and updates the graphics database accordingly.

   INPUTS
    ChipRev - Chip Rev that you would like to be enabled.

   RESULT
    chiprevbits - Actual bits set in GfxBase->ChipRevBits0.

   NOTES
    This routine should only be called once. It will be called by the system
    in the startup-sequence, but is included in the autodocs for authors
    of bootblock-games that wish to take advantage of post-ECS features.

   SEE ALSO
    <graphics/gfxbase.h>


graphics.library/SetDrMd

   NAME
     SetDrMd -- Set drawing mode for a RastPort

   SYNOPSIS
    SetDrMd( rp, mode )
         a1  d0:8

    void SetDrMd( struct RastPort *, UBYTE );

   FUNCTION
    Set the drawing mode for lines, fills and text.
    Get the bit definitions from rastport.h

   INPUTS
    rp - pointer to RastPort structure.
    mode - 0-255, some combinations may not make much sense.

   RESULT
    The mode set is dependent on the bits selected.
    Changes minterms to reflect new drawing mode.
    Sets line drawer to restart pattern.

   BUGS

   SEE ALSO
    SetAPen() SetBPen() graphics/rastport.h


graphics.library/SetMaxPen

   NAME
       SetMaxPen -- set maximum pen value for a rastport (V39).

   SYNOPSIS
       SetMaxPen ( rp, maxpen)
               a0   d0

    void SetMaxPen(struct RastPort *,ULONG)

   FUNCTION
    This will instruct the graphics library that the owner of the rastport
    will not be rendering in any colors whose index is >maxpen. If there
    are any speed optimizations which the graphics device can make based
    on this fact (for instance, setting the pixel write mask), they will
    be done.

    Basically this call sets the rastport mask, if this would improve
    speed. On devices where masking would slow things down (like with
    chunky pixels), it will be a no-op.

   INPUTS
       rp  =  a pointer to a valid RastPort structure.
    maxpen =  a longword pen value.

   BUGS

   NOTES
    The maximum pen value passed must take into account not only which
    colors you intend to render in the future, but what colors you will
    be rendering on top of.
    SetMaxPen(rp,0) doesn't make much sense.

   SEE ALSO
    SetWriteMask()


graphics.library/SetOutlinePen

   NAME
       SetOutlinePen -- Set the Outline Pen value for a RastPort (V39).

   SYNOPSIS
       old_pen=SetOutlinePen  ( rp, pen )
      d0	                 a0   d0

    ULONG SetOutlinePen(struct RastPort *,ULONG)

   FUNCTION
    Set the current value of the O pen for the rastport and turn on area outline
    mode. This function should be used instead of poking the structure directly,
    because future graphics devices may store it differently, for instance,
    using more bits.

   INPUTS
       rp  =  a pointer to a valid RastPort structure.
    pen =  a longword pen number

    returns the previous outline pen
   BUGS

   NOTES

   SEE ALSO
    GetOPen() graphics/gfxmacros.h


graphics.library/SetRGB32

   NAME
    SetRGB32 -- Set one color register for this Viewport. (V39)

   SYNOPSIS
    SetRGB32(  vp,  n,   r,    g,    b)
               a0  d0   d1    d2    d3

    void SetRGB32( struct ViewPort *, ULONG, ULONG, ULONG, ULONG );

   INPUTS
    vp = viewport
    n = the number of the color register to set.
    r = red level   (32 bit left justified fraction)
    g = green level (32 bit left justified fraction)
    b = blue level  (32 bit left justified fraction)

   RESULT
    If there is a ColorMap for this viewport, then the value will
    be stored in the ColorMap.
    The selected color register is changed to match your specs.
    If the color value is unused then nothing will happen.

   BUGS

   NOTES
    Lower order bits of the palette specification will be discarded,
    depending on the color palette resolution of the target graphics
    device. Use 0xffffffff for the full value, 0x7fffffff for 50%,
    etc. You can find out the palette range for your screen by
    querying the graphics data base.

   SEE ALSO
    GetColorMap() GetRGB32() SetRGB32CM() LoadRGB32() graphics/view.h


graphics.library/SetRGB32CM

   NAME
       SetRGB32CM -- Set one color register for this ColorMap. (V39)

   SYNOPSIS
       SetRGB32CM(  cm,  n,   r,    g,    b)
                    a0  d0   d1    d2    d3

       void SetRGB4CM( struct ColorMap *, ULONG, ULONG, ULONG , ULONG);

   INPUTS
    cm = colormap
       n = the number of the color register to set. Must not exceed the numbe
r of colors
        allocated for the colormap.
       r = red level (32 bit unsigned left justified fraction)
       g = green level
       b = blue level

   RESULT
    Store the (r,g,b) triplet at index n of the ColorMap structure.
       This function can be used to set up a ColorMap before before
    linking it into a viewport.

   BUGS

   SEE ALSO
       GetColorMap() GetRGB32() SetRGB32() SetRGB4CM() graphics/view.h


graphics.library/SetRGB4CM

   NAME
       SetRGB4CM -- Set one color register for this ColorMap.

   SYNOPSIS
       SetRGB4CM(  cm,  n,   r,    g,    b)
                   a0  d0  d1:4  d2:4  d3:4

       void SetRGB4CM( struct ColorMap *, SHORT, UBYTE, UBYTE, UBYTE );

   INPUTS
    cm = colormap
       n = the number of the color register to set. Ranges from 0 to 31
        on current Amiga displays.
       r = red level (0-15)
       g = green level (0-15)
       b = blue level (0-15)

   RESULT
    Store the (r,g,b) triplet at index n of the ColorMap structure.
       This function can be used to set up a ColorMap before before
    linking it into a viewport.

   BUGS

   SEE ALSO
       GetColorMap() GetRGB4() SetRGB4() graphics/view.h


graphics.library/SetRPAttrA

   NAME
       SetRPAttrA -- modify rastport settings via a tag list
    SetRPAttrs  -- varargs stub for SetRPAttrA

   SYNOPSIS
       SetRPAttrA(rp,tags)
                  a0   a1

    void SetRPAttrA(struct RastPort *, struct TagItem *);

    SetRPAttrs(rp,tag,...);

   FUNCTION
       Modify settings of a rastport, based on the taglist passed.
    currently available tags are:

        RPTAG_Font		Font for Text()
        RPTAG_SoftStyle		style for text (see graphics/text.h)
        RPTAG_APen		Primary rendering pen
        RPTAG_BPen		Secondary rendering pen
        RPTAG_DrMd 		Drawing mode (see graphics/rastport.h)
        RPTAG_OutLinePen 	Area Outline pen
        RPTAG_WriteMask 	Bit Mask for writing.
        RPTAG_MaxPen 		Maximum pen to render (see SetMaxPen())

   INPUTS
    rp - pointer to the RastPort to modify.
    tags - a standard tag list

   RESULT

   BUGS

   SEE ALSO
    SetFont() SetSoftStyle() SetAPen() SetBPen() SetDrMd() SetOutLinePen()
    SetWriteMask() SetMaxPen() GetRPAttrA() graphics/rpattr.h


graphics.library/SetWriteMask

   NAME
       SetWriteMask -- Set the pixel write mask value for a RastPort (V39).

   SYNOPSIS
       success=SetWriteMask ( rp, msk )
      d0	               a0   d0

    ULONG SetWriteMask(struct RastPort *,ULONG)

   FUNCTION
    Set the current value of the bit write mask for the rastport.
    bits of the pixel with zeros in their mask will not be modified by
    subsequent drawing operations.

   INPUTS
       rp  =  a pointer to a valid RastPort structure.
    msk =  a longword mask value.

    Graphics devices which do not support per-bit masking will
    return 0 (failure).
   BUGS

   NOTES

   SEE ALSO
    graphics/gfxmacros.h


graphics.library/TextExtent

   NAME
    TextExtent -- Determine raster extent of text data. (V36)

   SYNOPSIS
    TextExtent(rp, string, count, textExtent)
               A1  A0      D0:16  A2

    void textExtent(struct RastPort *, STRPTR, WORD,
         struct TextExtent *);

   FUNCTION
    This function determines a more complete metric of the space
    that a text string would render into than the TextLength()
    function.

   INPUTS
    rp     - a pointer to the RastPort which describes where the
             text attributes reside.
    string - the address of the string to determine the length of.
    count  - the number of characters in the string.
                If zero, there are no characters in the string.
    textExtent - a structure to hold the result.

   RESULTS
    textExtent is filled in as follows:
        te_Width  - same as TextLength() result: the rp_cp_x
                    advance that rendering this text would cause.
        te_Height - same as tf_YSize.  The height of the
                    font.
        te_Extent.MinX - the offset to the left side of the
                    rectangle this would render into.  Often zero.
        te_Extent.MinY - same as -tf_Baseline.  The offset
                    from the baseline to the top of the rectangle
                    this would render into.
        te_Extent.MaxX - the offset of the left side of the
                    rectangle this would render into.  Often the
                    same as te_Width-1.
        te_Extent.MaxY - same as tf_YSize-tf_Baseline-1.
                    The offset from the baseline to the bottom of
                    the rectangle this would render into.

   SEE ALSO
    TextLength()  Text()  TextFit()
    graphics/text.h  graphics/rastport.h


graphics.library/TextFit

   NAME
    TextFit - count characters that will fit in a given extent (V36)

   SYNOPSIS
    chars = TextFit(rastport, string, strLen, textExtent,
    D0              A1        A0      D0      A2
            constrainingExtent, strDirection,
            A3                  D1
            constrainingBitWidth, constrainingBitHeight)
            D2                    D3

    ULONG TextFit(struct RastPort *, STRPTR, UWORD,
        struct TextExtent *, struct TextExtent *, WORD, UWORD, UWORD);

   FUNCTION
    This function determines how many of the characters of the
    provided string will fit into the space described by the
    constraining parameters.  It also returns the extent of
    that number of characters.

   INPUTS
    rp     - a pointer to the RastPort which describes where the
             text attributes reside.
    string - the address of string to determine the constraint of
    strLen - The number of characters in the string.
             If zero, there are no characters in the string.
    textExtent - a structure to hold the extent result.
    constrainingExtent - the extent that the text must fit in.
        This can be NULL, indicating only the constrainingBit
        dimensions will describe the constraint.
    strDirection - the offset to add to the string pointer to
        get to the next character in the string.  Usually 1.
        Set to -1 and the string to the end of the string to
        perform a TextFit() anchored at the end.  No other value
        is valid.
    constrainingBitWidth - an alternative way to specify the
        rendering box constraint width that is independent of
        the rendering origin.  Range 0..32767.
    constrainingBitHeight - an alternative way to specify the
        rendering box constraint height that is independent of
        the rendering origin.  Range 0..32767.

   RESULTS
    chars - the number of characters from the origin of the
            given string that will fit in both the constraining
            extent (which specifies a CP bound and a rendering
            box relative to the origin) and in the rendering width
            and height specified.

   NOTES
    The result is zero chars and an empty textExtent when the fit
    cannot be performed.  This occurs not only when no text will
    fit in the provided constraints, but also when:
    -   the RastPort rp's rp_TxSpacing sign and magnitude is so
        great it reverses the path of the text.
    -   the constrainingExtent does not include x = 0.

   BUGS
    Under V37, TextFit() would return one too few characters if the
    font was proportional. This can be worked around by passing
    (constrainingBitWidth + 1) for proportional fonts. This is fixed
    for V39.

   SEE ALSO
    TextExtent()  TextLength()  Text()
    graphics/text.h  graphics/rastport.h


graphics.library/TextLength

   NAME
    TextLength -- Determine raster length of text data.

   SYNOPSIS
    length = TextLength(rp, string, count)
    D0                  A1  A0      D0:16

    WORD TextLength(struct RastPort *, STRPTR, WORD);

   FUNCTION
    This graphics function determines the length that text data
    would occupy if output to the specified RastPort with the
    current attributes.  The length is specified as the number of
    raster dots: to determine what the current position would be
    after a Text() using this string, add the length to cp_x
    (cp_y is unchanged by Text()).  Use the newer TextExtent() to
    get more information.

   INPUTS
    rp     - a pointer to the RastPort which describes where the
             text attributes reside.
    string - the address of string to determine the length of
    count  - the string length.  If zero, there are no characters
             in the string.

   RESULTS
    length - the number of pixels in x this text would occupy, not
             including any negative kerning that may take place at
             the beginning of the text string, nor taking into
             account the effects of any clipping that may take
             place.

   NOTES
    Prior to V36, the result length occupied only the low word of
    d0 and was not sign extended into the high word.

   BUGS
    A length that would overflow single word arithmetic is not
    calculated correctly.

   SEE ALSO
    TextExtent()  Text()  TextFit()
    graphics/text.h  graphics/rastport.h


graphics.library/UnlockLayerRom

   NAME
    UnlockLayerRom -- Unlock Layer structure by ROM(gfx lib) code.

   SYNOPSIS
    UnlockLayerRom( layer )
             a5

    void UnlockLayerRom( struct Layer * );

   FUNCTION
    Release the lock on this layer. If the same task has called
    LockLayerRom more than once than the same number of calls to
    UnlockLayerRom must happen before the layer is actually freed
    so that other tasks may use it.
    This call does destroy scratch registers.
    This call is identical to UnlockLayer (layers.library).

   INPUTS
    layer - pointer to Layer structure

   BUGS

   SEE ALSO
    LockLayerRom() layers.library/UnlockLayer() graphics/clip.h


graphics.library/VideoControl

   NAME
    VideoControl -- Modify the operation of a ViewPort's ColorMap (V36)
    VideoControlTags -- varargs stub for VideoControl (V36)
   SYNOPSIS
    error = VideoControl( cm , tags )
    d0                    a0   a1

    ULONG VideoControl( struct ColorMap *, struct TagItem * );

    error= VideoControlTags(cm, tags,...);

   FUNCTION
    Process the commands in the VideoControl command TagItem buffer
    using cm as the target, with respect to its "attached" ViewPort.

    viewport commands:

    VTAG_ATTACH_CM     [_SET        | _GET] -- set/get attached viewport
    VTAG_VIEWPORTEXTRA [_SET        | _GET] -- set/get attached vp_extra
    VTAG_NORMAL_DISP   [_SET        | _GET] -- set/get DisplayInfoHandle
                                               (natural mode)
    VTAG_COERCE_DISP   [_SET        | _GET] -- set/get DisplayInfoHandle
                                               (coerced mode)
    VTAG_PF1_BASE      [_SET        | _GET] -- set/get color base for
                                               first playfield. (V39)
    VTAG_PF2_BASE      [_SET        | _GET] -- set/get color base for
                                               second playfield. (V39)
    VTAG_SPODD_BASE    [_SET        | _GET] -- set/get color base for odd
                                               sprites. (V39)
    VTAG_SPEVEN_BASE   [_SET        | _GET] -- set/get color base for even
                                               sprites. (V39)
    VTAG_BORDERSPRITE  [_SET        | _GET] -- on/off/inquire sprites in
                                               borders. (V39)
    VTAG_SPRITERESN    [_SET        | _GET] -- set/get sprite resolution
                  (legal values are SPRITERESN_ECS/_140NS/_70NS/_35NS.
                   see graphics/view.h) (V39)
    VTAG_PF1_TO_SPRITEPRI [_SET     | _GET] -- set/get playfield1 priority
                                                  with respect to sprites (V3
9)
    VTAG_PF2_TO_SPRITEPRI [_SET     | _GET] -- set/get playfield2 priority
                                                  with respect to sprites (V3
9)
    (These two require that the ColorMap is attached to a ViewPort to be
     effective).

    genlock commands:

    VTAG_BORDERBLANK   [_SET | _CLR | _GET] -- on/off/inquire blanking
    VTAG_BORDERNOTRANS [_SET | _CLR | _GET] -- on/off/inquire notransparency
    VTAG_CHROMAKEY     [_SET | _CLR | _GET] -- on/off/inquire chroma mode
    VTAG_BITPLANEKEY   [_SET | _CLR | _GET] -- on/off/inquire bitplane mode
    VTAG_CHROMA_PEN    [_SET | _CLR | _GET] -- set/clr/get chromakey pen #
    VTAG_CHROMA_PLANE  [_SET |      | _GET] -- set/get bitplanekey plane #

    control commands:

    VTAG_IMMEDIATE	- normally, VideoControl changes do not occur until the
            next MakeVPort. Using this tag, some changes can be made to
            happen immediately. The tag data is a pointer to a longword
            flag variable which will be cleared if all changes happened
            immediately. See the example. (V39)

    VTAG_FULLPALETTE   [_SET | _CLR | _GET] -- enable/disable loading of all
            colors in the copper list.
            Normally, graphics will only load the color which are necessary
            for the viewport, based upon the screen depth and mode. In order
            to use the color palette banking features, you may need to use
            this tag to tell graphics to load ALL colors, regardless of
            screen depth. (V39)

    VC_IntermediateCLUpdate
    VC_IntermediateCLUpdate_Query
             When set, graphics will update the intermediate copper
         lists on colour changes. When FALSE, graphics won't update
             the intermediate copperlists, so ScrollVPort(),
             ChangeVPBitMap() and colour loading functions will be faster.
             This value is TRUE by default. (V40)

    VC_NoColorPaletteLoad
    VC_NoColorPaletteLoad_Query
             When set, only colour 0 will be loaded for this ViewPort,
             hence the inter-ViewPort gap will be smaller. The colours for
             this ViewPort are inherited from the next higher ViewPort. The
         results are undefined if this is the first or only ViewPort in
             the display, and undefined when used in conjunction with
             VTAG_FULLPALETTE (!?!).
             This value is FALSE by default. (V40)

    VC_DUALPF_Disable
    VC_DUALPF_Disable_Query
        When set, disables the setting of the dual-playfield
        bit in bplcon0. When used with a dual-playfield mode
        screen, this allows using separate scroll and bitmaps
        for the odd and even bitplanes, without going through
        the normal dual-playfield priority and palette selection.
        With appropriate palette setup, this can be used for
        transparency effects, etc.

    copper commands

    VTAG_USERCLIP      [_SET | _CLR | _GET] -- on/off/inquire clipping of
                                               UserCopperList at bottom
                                               edge of ColorMap->cm_vp
                                               (defaults to off)

    buffer commands:

    VTAG_NEXTBUF_CM                         -- link to more VTAG commands
    VTAG_END_CM                             -- terminate command buffer

    batch mode commands:

    (if you want your videocontrol taglist to be processed in "batch"
     mode, that is, at the next MakeVPort() for the ColorMap->cm_vp;
     you may install a static list of videocontrol TagItems into the
     ColorMap with the BATCH_ITEMS_SET command; and then enable/disable
     batch mode processing of those items via the BATCH_CM control
     command)

    VTAG_BATCH_CM      [_SET | _CLR | _GET] -- on/off/inquire batch mode
    VTAG_BATCH_ITEMS   [_SET | _ADD | _GET] -- set/add/get batched TagLists

    private commands (used internally by intuition -- do not call):

    VTAG_VPMODEID      [_SET | _CLR | _GET] -- force GetVPModeID() return

   INPUTS
    cm   = pointer to struct ColorMap obtained via GetColorMap().
    tags = pointer to a table of videocontrol tagitems.

   RESULT
    error = NULL if no error occurred in the control operation.
    (non-NULL if bad colormap pointer, no tagitems or bad tag)

    The operating characteristics of the ColorMap and its attached
    ViewPort are modified. The result will be incorporated into the
    ViewPort when its copper lists are reassembled via MakeVPort().

    Note that you must NOT change colors in the viewport (via SetRGB4(),
    LoadRGB4(), SetRGB4(), etc.) after changing any of the color palette
    offsets (VTAG_PF1_BASE, etc), without first remaking the ViewPort.

   NOTES
    Sprite resolutions is controlled by two sets of tags, SPRITERESN
    and DEFSPRITERESN. If you don't set the sprite resolution, it will
    follow the intuition-controlled "default" sprite resolution. Setting
    the sprite resolution to one of the SPRITERESN_ values will allow the
    application to override intuition's control of it.

    This function will modify the contents of the TagList you pass to it by
    changing _GET tags to the corresponding _SET or _CLR tag. The
    exceptions to this rule are documented as such above (such as
    VTAG_IMMEDIATE).

    The new tags added for V40 have the prefix VC_ instead of VTAG_. These
    tags work in the same manner as all other tags in the system, and will
    not be modified by VideoControl().

   EXAMPLE
    must_remake=-1;
    error=VideoControl(myvp->ColorMap,VTAG_BORDERBLANK_SET,-1,
                       (GFXBase->lib_Version>=39)?VTAG_IMMEDIATE:TAG_IGNORE,
                        &must_remake);
    if (must_remake) { MakeVPort(myview,myvp); MrgCop(myview); }

   EXAMPLE
    struct TagItem VCTags[] =
    {
        {VTAG_BORDERBLANK_GET, NULL},
        {VTAG_SPRITERESN_SET, SPRITERESN_35NS},
        {TAG_DONE, NULL},
    };
    BOOL bblank = FALSE;

    if (VideoControl(cm, VCTags) == NULL)
    {
        bblank = (VCTags[0].ti_Tag == VTAG_BORDERBLANK_SET);
    }

   EXAMPLE
    struct TagItem VCTags[] =
    {
        {VC_NoColorPaletteLoad_Query, NULL},
        {TAG_DONE},
    };
    ULONG query;

    VCTags[0].ti_Data = (ULONG)&query;
    if (VideoControl(cm, VCTags) == NULL)
    {
        printf("Palette loading is %sn", (query ? "off" : "on"));
    }

   BUGS

   SEE ALSO
    graphics/videocontrol.h, GetColorMap(), FreeColorMap()


graphics.library/WaitBlit

   NAME
       WaitBlit -- Wait for the blitter to be finished before proceeding
                   with anything else.

   SYNOPSIS
       WaitBlit()

    void WaitBlit( void );

   FUNCTION
    WaitBlit returns when the blitter is idle. This function should
    normally only be used when dealing with the blitter in a
    synchronous manner, such as when using OwnBlitter and DisownBlitter.
    WaitBlit does not wait for all blits queued up using QBlit or
    QBSBlit. You should call WaitBlit if you are just about to modify or
    free some memory that the blitter may be using.

   INPUTS
       none

   RESULT
       Your program waits until the blitter is finished.
    This routine does not use any the CPU registers.
    do/d1/a0/a1 are preserved by this routine.
    It may change the condition codes though.

   BUGS
    When examining bits with the CPU right after a blit, or when freeing
    temporary memory used by the blitter, a WaitBlit() may be required.

    Note that many graphics calls fire up the blitter, and let it run.
    The CPU does not need to wait for the blitter to finish before
    returning.

    Because of a bug in Agnus (prior to all revisions of fat Agnus)
     this code may return too soon when the blitter has, in fact, not
    started the blit yet, even though BltSize has been written.

    This most often occurs in a heavily loaded system with extended memory,
    HIRES, and 4 bitplanes.

    WaitBlit currently tries to avoid this Agnus problem by testing
    the BUSY bit multiple times to make sure the blitter has started.
    If the blitter is BUSY at first check, this function busy waits.

    This initial hardware bug was fixed as of the first "Fat Agnus" chip,
    as used in all A500 and A2000 computers.

    Because of a different bug in Agnus (currently all revisions thru ECS)
     this code may return too soon when the blitter has, in fact, not
    stopped the blit yet, even though blitter busy has been cleared.

    This most often occurs in a heavily loaded system with extended memory,
    in PRODUCTIVITY mode, and 2 bitplanes.

    WaitBlit currently tries to avoid this Agnus problem by testing
    the BUSY bit multiple times to make sure the blitter has really
    written its final word of destination data.

   SEE ALSO
    OwnBlitter() DisownBlitter() hardware/blit.h


graphics.library/WaitTOF

   NAME
       WaitTOF -- Wait for the top of the next video frame.

   SYNOPSIS
       WaitTOF()

    void WaitTOF( void );

   FUNCTION
       Wait  for vertical blank to occur and all vertical blank
       interrupt routines to complete before returning to caller.

   INPUTS
       none

   RESULT
    Places this task on the TOF wait queue. When the vertical blank
    interrupt comes around, the interrupt service routine will fire off
    signals to all the tasks doing WaitTOF. The highest priority task
    ready will get to run then.

   BUGS

   SEE ALSO
    exec.library/Wait() exec.library/Signal()


graphics.library/WriteChunkyPixels

   NAME
    WriteChunkyPixels -- write the pen number value of a rectangular array
    of pixels starting at a specified x,y location and continuing
    through to another x,y location within a certain RastPort. (V40)

   SYNOPSIS
    WriteChunkyPixels(rp,xstart,ystart,xstop,ystop,array,bytesperrow)
                      A0 D0     D1     D2    D3    A2     D4

    VOID WriteChunkyPixels(struct  RastPort *, LONG, LONG,
         LONG, LONG, UBYTE *, LONG);

   FUNCTION
    For each pixel in a rectangular region, decode the pen number selector
    from a linear array of pen numbers into the bit-planes used to describe
    a particular rastport.

   INPUTS
    rp     -  pointer to a RastPort structure
    (xstart,ystart) -  starting point in the RastPort
    (xstop,ystop)   -  stopping point in the RastPort
    array  - pointer to an array of UBYTEs from which to fetch the
             pixel data.
    bytesperrow - The number of bytes per row in the source array.
        This should be at least as large as the number of pixels
        being written per line.

   RESULT

   NOTE
    xstop must be >= xstart
    ystop must be >= ystart
    The source array can be in fast RAM.

   ===chunky-to-planar conversion HW:

   GfxBase->ChunkyToPlanarPtr is either NULL, or a pointer to a HW
   register used to aid in the process of converting 8-bit chunky
   pixel data into the bit-plane format used by the Amiga custom
   display chips. If NULL, then such hardware is not present.

   If an expansion device provides hardware which operates compatibly,
   than it can install the HW address into this pointer at boot time,
   and the system will use it.

   This pointer may be used for direct access to the chunky-to-planar
   conversion HW, if more is desired than the straight chunky-pixel
   copy that is performed by WriteChunkyPixels().

   If using the hardware directly, it should only be accessed when
   the task using it has control of the blitter (via OwnBlitter()),
   since this is the locking used to arbitrate usage of this device.

   The hardware may be viewed as a device which accepts 32 8-bit
   chunky pixels and outputs 8 longwords of bitplane data.

   For proper operation, exactly 8 longwords (containing 32 pixels)
   of chunky data should be written to *(GfxBase->ChunkyToPlanarPtr).
   After the data is written, bitplane data (starting with plane 0)
   can be read back a longword at a time. There is no need to read
   back all 8 longwords if the high-order bitplanes are not needed.

   Since WriteChunkyPixels is not (currently) particularly fast on
   systems without the chunky-to-planar hardware, time critical
   applications (games, etc) may want to use their own custom conversion
   routine if GfxBase->ChunkyToPlanarPtr is NULL, and call
   WriteChunkyPixels() otherwise.

   This pointer is only present in GfxBase in versions of graphics.library
   >= 40, so this should be checked before the pointer is read.

   BUGS
    Not very fast on systems without chunky-to-planar conversion
    hardware.

   SEE ALSO
    WritePixel()  graphics/rastport.h


graphics.library/WritePixelArray8

   NAME
    WritePixelArray8 -- write the pen number value of a rectangular array
    of pixels starting at a specified x,y location and continuing
    through to another x,y location within a certain RastPort. (V36)

   SYNOPSIS
    count = WritePixelArray8(rp,xstart,ystart,xstop,ystop,array,temprp)
    D0                       A0 D0:16  D1:16  D2:16 D3:16  A2   A1

    LONG WritePixelArray8(struct  RastPort *, UWORD, UWORD,
         UWORD, UWORD, UBYTE *, struct  RastPort *);

   FUNCTION
    For each pixel in a rectangular region, decode the pen number selector
    from a linear array of pen numbers into the bit-planes used to describe
    a particular rastport.

   INPUTS
    rp     -  pointer to a RastPort structure
    (xstart,ystart) -  starting point in the RastPort
    (xstop,ystop)   -  stopping point in the RastPort
    array  - pointer to an array of UBYTEs from which to fetch the
             pixel data. Allocate at least
             ((((width+15)>>4)<<4)*(ystop-ystart+1)) bytes.
    temprp - temporary rastport (copy of rp with Layer set == NULL,
             temporary memory allocated for
             temprp->BitMap with Rows set == 1,
             temprp->BitMap with BytesPerRow == (((width+15)>>4)<<1),
             and temporary memory allocated for
             temprp->BitMap->Planes[])

   RESULT
    count will be set to the number of pixels plotted.

   NOTE
    xstop must be >= xstart
    ystop must be >= ystart

   BUGS

   SEE ALSO
    WritePixel()  graphics/rastport.h


graphics.library/WritePixelLine8

   NAME
    WritePixelLine8 -- write the pen number value of a horizontal line
    of pixels starting at a specified x,y location and continuing
    right for count pixels. (V36)

   SYNOPSIS
    count = WritePixelLine8(rp,xstart,ystart,width,array,temprp)
    D0                      A0 D0:16  D1:16  D2    A2    A1

    LONG WritePixelLine8(struct RastPort *, UWORD, UWORD,
         UWORD, UBYTE *, struct RastPort *);

   FUNCTION
    For each pixel in a horizontal region, decode the pen number selector
    from a linear array of pen numbers into the bit-planes used to describe
    a particular rastport.

   INPUTS
    rp    -  pointer to a RastPort structure
    (x,y) - a point in the RastPort
    width - count of horizontal pixels to write
    array - pointer to an array of UBYTEs from which to fetch the pixel data
            allocate at least (((width+15)>>4)<<4) bytes.
    temprp - temporary rastport (copy of rp with Layer set == NULL,
             temporary memory allocated for
             temprp->BitMap with Rows set == 1,
             temprp->BitMap BytesPerRow == (((width+15)>>4)<<1),
             and temporary memory allocated for
             temprp->BitMap->Planes[])

   RESULT
    Count will be set to the number of pixels plotted

   NOTE
    width must be non negative

   BUGS

   SEE ALSO
    WritePixel()  graphics/rastport.h


icon.doc

     AddFreeList()
     BumpRevision()
     ChangeToSelectedIconColor()
     DeleteDiskObject()
     DrawIconStateA()
     DupDiskObjectA()
     FindToolType()
     FreeDiskObject()
     FreeFreeList()
     GetDefDiskObject()
     GetDiskObject()
     GetDiskObjectNew()
     GetIconRectangleA()
     GetIconTagList()
     IconControlA()
     LayoutIconA()
     MatchToolValue()
     NewDiskObject()
     PutDefDiskObject()
     PutDiskObject()
     PutIconTagList()


icon.library/AddFreeList

   NAME
    AddFreeList - add memory to a free list.

   SYNOPSIS
    status = AddFreeList(free, mem, len)
      D0                  A0    A1   A2

    BOOL AddFreeList(struct FreeList *, APTR, ULONG);

   FUNCTION
    This routine adds the specified memory to the free list.
    The free list will be extended (if required).  If there
    is not enough memory to complete the call, NULL is returned.

    Note that AddFreeList() does NOT allocate the requested memory.
    It only records the memory in the free list.

   INPUTS
    free -- a pointer to a FreeList structure
    mem -- the base of the memory to be recorded
    len -- the length of the memory to be recorded

   RESULTS
    status -- TRUE if the call succeeded else FALSE;

   SEE ALSO
    exec.library/AllocEntry
    exec.library/FreeEntry
    icon.library/FreeFreeList
    workbench/workbench.h


icon.library/BumpRevision

   NAME
    BumpRevision - reformat a name for a second copy.

   SYNOPSIS
    result = BumpRevision(newbuf, oldname)
      D0                    A0      A1

    STRPTR BumpRevision(STRPTR, STRPTR);

   FUNCTION
    BumpRevision takes a name and turns it into a "copy_of_name".
    It knows how to deal with copies of copies.  The routine
    will truncate the new name to the maximum dos name size
    (currently 30 characters).

   INPUTS
    newbuf - the new buffer that will receive the name
             (it must be at least 31 characters long).
    oldname - the original name

   RESULTS
    result - a pointer to newbuf

   EXAMPLE
    oldname                          newbuf
    -------                          ------
    "foo"                            "copy_of_foo"
    "copy_of_foo"                    "copy_2_of_foo"
    "copy_2_of_foo"                  "copy_3_of_foo"
    "copy_199_of_foo"                "copy_200_of_foo"
    "copy foo"                       "copy_of_copy foo"
    "copy_0_of_foo"                  "copy_1_of_foo"
    "012345678901234567890123456789" "copy_of_0123456789012345678901"


icon.library/ChangeToSelectedIconColor

   NAME
    ChangeToSelectedIconColor -- Modify an RGB colour value for use in
        a selected icon image (V44)

   SYNOPSIS
    ChangeToSelectedIconColor(cr)
                              A0

    VOID ChangeToSelectedIconColor(struct ColorRegister *cr);

   FUNCTION
    This function will change the provided RGB colour value to make it
    suitable for use in an icon's select image. This may involve darkening
    or toning the colour. Usually, icon.library calls this function
    when creating a select image for palette mapped icons which do not
    contain "real" select images.

   INPUTS
    cr -- Pointer to a ColorRegister, containing the RGB colour value
        to be changed.


icon.library/DeleteDiskObject

   NAME
    DeleteDiskObject - Delete a Workbench disk object from disk.     (V37)

   SYNOPSIS
    result = DeleteDiskObject(name)
      D0                      A0

    BOOL DeleteDiskObject(STRPTR);

   FUNCTION
    This routine will try to delete a Workbench disk object from disk.
    The name parameter will have ".info" postpended to it, and the
    icon file of that name will be deleted.  If the call fails,
    it will return FALSE. The reason for the failure may be obtained
    via dos.library/IoErr().

    This call also updates the Workbench screen if needed.

    Using this routine protects you from any future changes to
    the way icons are stored within the system.

   INPUTS
    name -- name of the object (char *)

   RESULTS
    result -- TRUE if it worked, FALSE if not.

   EXAMPLE

    error = 0;

    /* Check if you have the right library version */
    if(IconBase->lib_Version > 36)
    {
        if (!DeleteDiskObject(name))
            error = IoErr();
    }
    else
    {
        /* Delete name plus ".info" */
    }

    if (error != 0)
    {
        /* Do error routine...*/
    }

   SEE ALSO
    dos.library/IoErr
    icon.library/PutDiskObject
    icon.library/GetDiskObject
    icon.library/FreeDiskObject
    icon.library/GetIconTagList
    icon.library/PutIconTagList


icon.library/DrawIconStateA

   NAME
    DrawIconStateA -- Draw an icon as if it were an image (V44)

   SYNOPSIS
    DrawIconStateA(rp,icon,label,leftEdge,topEdge,state,tags)
                   A0 A1   A2    D0       D1      D2    A3

    VOID DrawIconStateA(struct RastPort *rp,struct DiskObject *icon,
                        STRPTR label,LONG leftEdge,LONG topEdge,
                        ULONG state,struct TagItem *tags);

    DrawIconState(rp,icon,label,leftEdge,topEdge,state,...);

    VOID DrawIconState(struct RastPort *rp,struct DiskObject *icon,
                       STRPTR label,LONG leftEdge,LONG topEdge,
                       ULONG state,...);

   FUNCTION
    This function will draw an icon as if it were an image; if
    a label is provided, it will be printed below it.

   INPUTS
    rp -- Pointer to the RastPort to draw into; the RastPort clipping
        rules, font, style, text colours and drawing mode will be used.
    icon -- Pointer to a struct DiskObject.
    label -- Pointer to a NUL-terminated string, or NULL if
        no label text is to be printed.
    leftEdge, topEdge -- Coordinates at which the icon image
        should be drawn, including its border; please note that the
        icon label may extend in whole or in part beyond the
        leftEdge you have specified.
    state -- Select how and which icon image should be drawn;
        see intuition/imageclass.h for supported states.
    tags -- Additional drawing options

   TAGS
    ICONDRAWA_DrawInfo (struct DrawInfo *) -- Drawing information data
        associated with the RastPort to draw into. The DrawInfo
        contents affect the colours of the border drawn around the
        icon image and also carry display aspect ratio information.
        If this tag is NULL, the default rendering pens for the
        screen selected via IconControl(...,ICONA_SetGlobalScreen,...)
        will be used instead.

        This tag defaults to NULL.

    ICONDRAWA_Frameless (BOOL) -- Draw the icon without the
        surrounding border.

        This tag defaults to FALSE.

    ICONDRAWA_Borderless (BOOL) -- Draw the icon without the
        surrounding border and frame.

        This tag defaults to FALSE.

    ICONDRAWA_EraseBackground (BOOL) -- When drawing a frameless
        icon, erase the icon background before drawing the icon.

        This tag defaults to TRUE.

   EXAMPLE
    /* Draw the icon in its normal state, without
     * a label but including a frame.
     */
    struct RastPort *rp;
    struct DiskObject *icon;

    DrawIconStateA(rp,icon,NULL,0,0,IDS_NORMAL,NULL);

    /* The same again, but without a frame. */
    DrawIconState(rp,icon,NULL,0,0,IDS_NORMAL,
        ICONDRAWA_Frameless,TRUE,
    TAG_DONE);

    /* Draw the icon in selected state with a border; the
     * frame colours come from the given DrawInfo.
     */
    struct DrawInfo *drawInfo;

    DrawIconState(rp,icon,NULL,0,0,IDS_SELECTED,
        ICONDRAWA_DrawInfo,drawInfo,
    TAG_DONE);

   SEE ALSO
    workbench/icon.h
    workbench/workbench.h
    intuition/imageclass.h
    intuition/screens.h
    intuition.library/DrawImageState
    icon.library/GetIconRectangleA
    icon.library/IconControlA


icon.library/DupDiskObjectA

   NAME
    DupDiskObjectA -- Duplicate an icon (V44)

   SYNOPSIS
    icon = DupDiskObjectA(icon,tags);
    D0                    A0   A1

    struct DiskObject * DupDiskObjectA(struct DiskObject *icon,
                                       struct TagItem *tags);

    icon = DupDiskObject(icon,tag1,...);

    struct DiskObject * DupDiskObject(struct DiskObject *icon,
                                      Tag tag1,...);

   FUNCTION
    This function is used to create a duplicate of a DiskObject
    in memory. It can also be used to create an extended
    ("native") DiskObject data structure from an existing,
    traditional format DiskObject data structure.

   INPUTS
    icon -- Pointer to the icon to be duplicated.
    tags -- Control options.

   TAGS
    ICONDUPA_DuplicateDrawerData (BOOL) -- Duplicate the DrawerData,
        if available.

        This tag defaults to TRUE.

    ICONDUPA_DuplicateImages (BOOL) -- Duplicate the icon images;
        note that this DOES NOT include the associated image
        data. To get the image data duplicated, too, also use
        the ICONDUPA_DuplicateImageData tag.

        This tag defaults to TRUE.

    ICONDUPA_DuplicateImageData (BOOL) -- Duplicate the icon image
        data; this tag works together with the ICONDUPA_DuplicateImages
        tag. If ICONDUPA_DuplicateImageData is set to TRUE, you must
        also set ICONDUPA_DuplicateImages to TRUE.

        This tag defaults to TRUE.

    ICONDUPA_DuplicateDefaultTool (BOOL) -- Duplicate the icon default
        tool, if available.

        This tag defaults to TRUE.

    ICONDUPA_DuplicateToolTypes (BOOL) -- Duplicate the icon tool
        types, if available.

        This tag defaults to TRUE.

    ICONDUPA_DuplicateToolWindow (BOOL) -- Duplicate the icon tool
        window if available.

        This tag defaults to TRUE.

    ICONDUPA_ActivateImageData (BOOL) -- If the source icon contains
        palette mapped image data that was never put to use (this
        happens if it is retrieved with the GetDiskObject() call rather
        than the new GetIconTagList() call), this tag will cause the
        image data to be analyzed and an attempt to be made to use that
        image data in the duplicate. The resulting icon will be remapped
        for display on the default screen, such as the Workbench screen.

        This tag defaults to FALSE.

    ICONA_ErrorCode (LONG *) -- Pointer to a LONG word variable to
        store error codes in. Note that this variable will be
        initialized regardless of whether an error occured or not.
        Thus, you can check for an error condition by comparing the
        variable contents against 0; 0 indicates success, all other
        values are error codes as defined by dos.library.

   RESULT
    icon -- Pointer to a struct DiskObject or NULL in case of error.
        You can use IoErr() to retrieve the error code or use the
        ICONA_ErrorCode tag instead.

   NOTES
    Any data you chose not to have duplicated will be set to NULL.
    For example, if you specified "ICONDUPA_DuplicateImages,FALSE",
    then the resulting icon's do_Gadget.GadgetRender and
    do_Gadget.SelectRender will both be NULL.

   SEE ALSO
    dos.library/IoErr
    workbench/icon.h
    workbench/workbench.h


icon.library/FindToolType

   NAME
    FindToolType - find the value of a ToolType variable.

   SYNOPSIS
    value = FindToolType(toolTypeArray, typeName)
      D0                      A0           A1

    STRPTR FindToolType(STRPTR *, STRPTR);

   FUNCTION
    This function searches a tool type array for a given entry,
    and returns a pointer to that entry.  This is useful for
    finding standard tool type variables.  The returned
    value is not a new copy of the string but is only
    a pointer to the part of the string after typeName.

   INPUTS
    toolTypeArray -- an array of strings (STRPTR *).
    typeName -- the name of the tooltype entry (STRPTR).

   RESULTS
    value -- a pointer to a string that is the value bound to typeName,
            or NULL if typeName is not in the toolTypeArray.

   EXAMPLE
    Assume the tool type array has two strings in it:
        "FILETYPE=text"
        "TEMPDIR=:t"

    FindToolType( toolTypeArray, "FILETYPE" ) returns "text"
    FindToolType( toolTypeArray, "filetype" ) returns "text"
    FindToolType( toolTypeArray, "TEMPDIR" )  returns ":t"
    FindToolType( toolTypeArray, "MAXSIZE" )  returns NULL
    FindToolType( toolTypeArray, "text" )     returns NULL
    FindToolType( toolTypeArray, ":t" )       returns NULL

   NOTES
    icon.library V44 tolerates tool type strings with additional
    blanks around the '=' character, such as in "FILETYPE = text".
    Older icon.library versions did not support this.

   SEE ALSO
    icon.library/MatchToolValue


icon.library/FreeDiskObject

   NAME
    FreeDiskObject - free all memory in a Workbench disk object.

   SYNOPSIS
    FreeDiskObject(diskobj)
                   A0

    void FreeDiskObject(struct DiskObject *);

   FUNCTION
    This routine frees all memory in a Workbench disk object, and the
    object itself.  It is implemented via FreeFreeList().

    GetDiskObject() takes care of all the initialization required
    to set up the object's free list.  This procedure may ONLY
    be called on a DiskObject allocated via GetDiskObject().

   INPUTS
    diskobj -- a pointer to a DiskObject structure; as of V44,
        a NULL diskobj pointer will be ignored.

   SEE ALSO
    icon.library/GetDiskObject
    icon.library/PutDiskObject
    icon.library/DeleteDiskObject
    icon.library/FreeFreeList
    icon.library/GetIconTagList
    icon.library/PutIconTagList


icon.library/FreeFreeList

   NAME
    FreeFreeList - free all memory in a free list.

   SYNOPSIS
    FreeFreeList(free)
                 A0

    void FreeFreeList(struct FreeList *);

   FUNCTION
    This routine frees all memory in a free list, and the
    free list itself.  It is useful for easily getting
    rid of all memory in a series of structures.  There is
    a free list in a Workbench object, and this contains
    all the memory associated with that object.

    A FreeList is a list of MemList structures.  See the
    MemList and MemEntry documentation for more information.

    If the FreeList itself is in the free list, it must be
    in the first MemList in the FreeList.

   INPUTS
    free -- a pointer to a FreeList structure; as of V44
        a NULL free parameter will be ignored.

   SEE ALSO
    exec.library/AllocEntry
    exec.library/FreeEntry
    icon.library/AddFreeList
    workbench/workbench.h


icon.library/GetDefDiskObject

   NAME
    GetDefDiskObject - read default wb disk object from disk.       (V36)

   SYNOPSIS
    diskobj = GetDefDiskObject(def_type)
      D0                          D0

    struct DiskObject *GetDefDiskObject(LONG);

   FUNCTION
    This routine reads in a default Workbench disk object from disk.
    The valid def_types can be found in workbench/workbench.h and
    currently include WBDISK thru WBKICK. If the call fails,
    it will return NULL. The reason for the failure may be obtained
    via IoErr().

    Using this routine protects you from any future changes to
    the way default icons are stored within the system.

   INPUTS
    def_type -- default icon type (WBDISK thru WBKICK).

   RESULTS
    diskobj -- the default Workbench disk object in question

   NOTES
    icon.library V36 through V40 did not support the WBDEVICE default
    icon type.

   SEE ALSO
    dos.library/IoErr
    icon.library/PutDefDiskObject
    icon.library/PutIconTagList


icon.library/GetDiskObject

   NAME
    GetDiskObject - read in a Workbench disk object from disk.

   SYNOPSIS
    diskobj = GetDiskObject(name)
      D0                      A0

    struct DiskObject *GetDiskObject(STRPTR);

   FUNCTION
    This routine reads in a Workbench disk object in from disk.  The
    name parameter will have ".info" postpended to it, and the
    icon file of that name will be read.  If the call fails,
    it will return NULL.  The reason for the failure may be obtained
    via IoErr().

    Using this routine protects you from any future changes to
    the way icons are stored within the system.

    A FreeList structure is allocated just after the DiskObject
    structure; FreeDiskObject makes use of this to get rid of the
    memory that was allocated.

   INPUTS
    name -- name of the object (STRPTR) or NULL if you just want a
            DiskObject structure allocated for you (useful when
            calling AddAppIcon() in workbench.library).

   RESULTS
    diskobj -- the Workbench disk object in question

   SEE ALSO
    dos.library/IoErr
    icon.library/DeleteDiskObject
    icon.library/FreeDiskObject
    icon.library/GetDiskObjectNew
    icon.library/GetIconTagList
    icon.library/NewDiskObject
    icon.library/PutDiskObject
    icon.library/PutIconTagList
    workbench.library/AddAppIconA


icon.library/GetDiskObjectNew

   NAME
    GetDiskObjectNew - read in a Workbench disk object from disk.    (V36)

   SYNOPSIS
    diskobj = GetDiskObjectNew(name)
      D0                      A0

    struct DiskObject *GetDiskObjectNew(STRPTR);

   FUNCTION
    This routine reads in a Workbench disk object in from disk.  The
    name parameter will have ".info" postpended to it, and the
    icon file of that name will be read.  If the call fails,
    it will return zero.  The reason for the failure may be obtained
    via IoErr().

    Using this routine protects you from any future changes to
    the way icons are stored within the system.

    A FreeList structure is allocated just after the DiskObject
    structure; FreeDiskObject makes use of this to get rid of the
    memory that was allocated.

    This call is functionally identical to GetDiskObject() with one
    exception. If its call to GetDiskObject() fails, this function calls
    GetDefDiskObject(). This is useful when there is no .info file for the
    icon you are trying to get a disk object for. Applications that use
    workbench application windows MUST use this call if they want to handle
    the user dropping an icon (that doesn't have a ".info" file) on their
    window. The V2.0 icon editor program is an example of a Workbench
    application window that uses this call.

   INPUTS
    name -- name of the object (STRPTR) or NULL if you just want a
            DiskObject structure allocated for you (useful when
            calling AddAppIcon() in workbench.library).

   RESULTS
    diskobj -- the Workbench disk object in question

   SEE ALSO
    dos.library/IoErr
    icon.library/FreeDiskObject
    icon.library/GetDiskObject
    icon.library/PutDiskObject
    icon.library/DeleteDiskObject
    icon.library/GetIconTagList
    icon.library/PutIconTagList
    workbench.library/AddAppIconA


icon.library/GetIconRectangleA

   NAME
    GetIconRectangleA -- Query the size of the area an icon renders into (V44)

   SYNOPSIS
    success = GetIconRectangleA(rp,icon,label,rectangle,tags)
    D0                          A0 A1   A2    A3        A4

    BOOL GetIconRectangleA(struct RastPort *rp,struct DiskObject *icon,
                           STRPTR label,struct Rectangle *rectangle,
                           struct TagItem *tags);

    success = GetIconRectangle(rp,icon,label,rectangle,...);

    BOOL GetIconRectangle(struct RastPort *rp,struct DiskObject *icon,
                          STRPTR label,struct Rectangle *rectangle,...);

   FUNCTION
    This function will calculate the size of the area icon rendering
    would affect.

   INPUTS
    rp -- Pointer to the RastPort to use for calculating the
        the size of the label with respect to the font and
        style options currently in use; this parameter may be
        NULL if the label is NULL, too.
    icon -- Pointer to a struct DiskObject.
    label -- Pointer to a NUL-terminated string, or NULL if
        no label text is to enter the calculation.
    rectangle -- Pointer to a struct Rectangle to fill in. The
        contents will take the size of the icon image, the icon
        border size and -- if you provide RastPort and label
        text -- the icon label into account. Due to how labels
        are printed, the rectangle->MinX and rectangle->MinY
        members may be negative.
    tags -- Additional drawing options to be taken into account.

   TAGS
    ICONDRAWA_DrawInfo (struct DrawInfo *) -- Drawing information data
        associated with the RastPort parameter passed in.

        This tag defaults to NULL.

    ICONDRAWA_Borderless (BOOL) -- When calculating the size of
        the rectangle, this tag allows you to leave the icon
        border size out of the equation.

        This tag defaults to FALSE.

   RESULTS
    success -- TRUE if the parameters were well-formed and
        the output data fits into the Rectangle data
        structure (which may not be the case if the image
        is too large for a signed 16 bit integer to hold).

   EXAMPLE
    /* Find out how large an icon is. */
    struct DiskObject *icon;
    struct Rectangle rect;

    if(GetIconRectangleA(NULL,NULL,icon,NULL,&rect,NULL))
    {
        LONG width,height;

        width = rect.MaxX - rect.MinX + 1;
        height = rect.MaxY - rect.MinY + 1;

        Printf("icon is %ld×%ld pixels in size.n",
            width,height);
    }

    /* Find out which area the icon rendering would
     * cover if a label would be printed below it.
     */
    struct RastPort *rp;

    if(GetIconRectangle(rp,NULL,icon,"a rather long label text",&rect,TAG_DONE))
    {
        Printf("icon plus label would cover the area %ld,%ld×%ld,%ldn",
            rect.MinX,rect.MinY,rect.MaxX,rect.MaxY);
    }

   NOTES
    This function can be used to optimize on-screen rendering by
    precalculating the area rendering would cover. To make sure that
    the precalculated area size matches the one covered by the actual
    drawing operation, the RastPorts you use for measuring and for
    drawing should share the same font and the same text styles.

    The image size calculated by this function can be
    slightly larger than the data you will find in the icon's
    do_Gadget.GadgetRender Image structure since the icon border
    will be taken into account. This happens regardless of whether
    icon.library was switched into frameless icon rendering mode
    or whether the icon is frameless. To obtain the size of the
    icon without taking the border into account, use the
    ICONDRAWA_Borderless tag.

   SEE ALSO
    workbench/icon.h
    workbench/workbench.h
    icon.library/DrawIconState
    icon.library/IconControlA


icon.library/GetIconTagList

   NAME
    GetIconTagList -- Retrieve an icon (V44)

   SYNOPSIS
    icon = GetIconTagList(name,tags);
    D0                    A0   A1

    struct DiskObject * GetIconTagList(STRPTR name,struct TagItem *tags);

    icon = GetIconTags(name,tag1,...);

    struct DiskObject * GetIconTags(STRPTR name,Tag tag1,...);

   FUNCTION

    This function is used to retrieve an icon; the icon can
    belong to a file/drawer/volume or it can be a default icon.

   INPUTS
    name -- Name of the object an icon is to be retrieved for,
        or NULL if a default icon is to be retrieved.
    tags -- Retrieval options.

   TAGS
    ICONGETA_GetDefaultType (LONG) -- Type of the default icon
        to retrieve; must be one of WBDISK, WBDRAWER, WBTOOL,
        WBPROJECT, WBGARBAGE, WBDEVICE or WBKICK.

        If this tag is used, the "name" parameter will be ignored.

    ICONGETA_GetDefaultName (STRPTR) -- Name of the default object
        type to retrieve a default icon for. If the named default
        icon cannot be found, NULL will be returned. To avoid
        this, also specify ICONGETA_GetDefaultType: this will provide
        a fall-back and return a "default" default icon instead.

        If this tag is used, the "name" parameter will be ignored.

    ICONGETA_FailIfUnavailable (BOOL) -- If there is no icon for
        the specified object, this tag will control how to
        proceed: if ICONGETA_FailIfUnavailable is set to TRUE,
        NULL and an error code will be returned; if set to FALSE,
        icon.library will first invoke the global identification
        hook (see icon.library/IconControlA) and then, if necessary,
        provide a default icon for the object in question.

        This tag defaults to TRUE.

    ICONGETA_GetPaletteMappedIcon (BOOL) -- By default, icon.library
        will try to retrieve the palette mapped version of an icon. To
        change this, set the ICONGETA_GetPaletteMappedIcon tag to FALSE.

        This tag defaults to TRUE.

    ICONGETA_RemapIcon (BOOL) -- Palette mapped icons will usually
        be automatically remapped for display on the screen
        selected using IconControlA(). If you do not want this to
        happen because, for example, you want to use LayoutIcon()
        instead, you can set the ICONGETA_RemapIcon tag to FALSE.
        Take care when doing this as the icon returned to you
        will have NULL pointers in the do_Gadget.GadgetRender
        and do_Gadget.SelectRender members.

        This tag defaults to TRUE.

    ICONGETA_IsDefaultIcon (LONG *) -- When retrieving an icon with
        the ICONGETA_FailIfUnavailable tag set to FALSE, you may
        receive a default icon because there is no on-disk icon
        file for the object you wanted to retrieve it for. This
        type of default icon is also known as a "fake" icon.
        To find out whether you have received a fake icon, use the
        ICONGETA_IsDefaultIcon tag.

    ICONGETA_GenerateImageMasks (BOOL) -- When loading icons with
        transparent colours or backfill imagery, bit plane masks
        will be generated for later use with DrawIconStateA().
        If you do not need these masks, set this tag to FALSE.

        This tag defaults to TRUE.

    ICONGETA_Screen (struct Screen *) -- Pointer to the screen
        to remap the icon to; if set to NULL, this keeps the
        icon from getting remapped in the first place (see
        ICONGETA_RemapIcon for the consequences).

        This tag defaults to the default screen to remap to, as
        preset by IconControlA().

    ICONGETA_Label (STRPTR) -- The label text to be printed below
        the icon when it is put to use lateron. This parameter
        can be useful to figure out the type of the icon to
        be retrieved by the identification hook. For example,
        Workbench may label unreadable disk icons as "DF0:????".
        The identification hook could key on this and supply an
        appropriate icon for the disk.

        This tag defaults to NULL.

    ICONA_ErrorCode (LONG *) -- Pointer to a LONG word variable to
        store error codes in. Note that this variable will be
        initialized regardless of whether an error occured or not.
        Thus, you can check for an error condition by comparing the
        variable contents against 0; 0 indicates success, all other
        values are error codes as defined by dos.library.

   RESULT
    icon -- Pointer to a struct DiskObject or NULL in case of error.
        You can use IoErr() to retrieve the error code or use the
        ICONA_ErrorCode tag instead.

   EXAMPLE

    /* Retrieve the default drawer icon. */
    struct DiskObject *icon;
    LONG errorCode;

    icon = GetIconTags(NULL,
        ICONGETA_GetDefaultType,WBDRAWER,
        ICONA_ErrorCode,&errorCode,
    TAG_DONE);

    if(icon == NULL)
    {
        Printf("could not retrieve default drawer icon;n");
        PrintFault(errorCode,NULL);
    }

    /* Retrieve the default "picture" icon. */
    icon = GetIconTags(NULL,
        ICONGETA_GetDefaultName,"picture",
    TAG_DONE);

    /* Retrieve the default "picture" icon; if there is no
     * such default icon, retrieve the default project
     * icon instead.
     */
    icon = GetIconTags(NULL,
        ICONGETA_GetDefaultName,"picture",
        ICONGETA_GetDefaultType,WBPROJECT,
    TAG_DONE);

    /* Retrieve the regular, non-palette-mapped version of
     * an icon.
     */
    icon = GetIconTags("file",
        ICONGETA_GetPaletteMappedIcon,FALSE,
    TAG_DONE);

    /* Retrieve the icon for a file; if there is no icon associated
     * with it, retrieve a default icon that matches the file.
     * Also, remember whether we got a real icon or a fake one.
     */
    LONG isFakeIcon;

    icon = GetIconTags("file",
        ICONGETA_FailIfUnavailable,FALSE,
        ICONGETA_IsDefaultIcon,&isFakeIcon,
    TAG_DONE);

    if(icon != NULL)
    {
        Printf("got an icon at 0x%08lx, and it is a %s icon.n",
            icon,isFakeIcon ? "fake" : "real");
    }

   NOTES
    This function is a superset of GetDefDiskObject(), GetDiskObject()
    and GetDiskObjectNew().

    If a palette-mapped icon is set to allocate its colours from the
    default screen, such as the Workbench screen, icon.library may
    resort to remap its colours in the course of Workbench screen
    close/reopen transitions. This means that you cannot depend upon
    the icon's image bitmaps to stay the same size, shape or colour.
    If this is what you need, you should either create your own images
    from the palette mapped data or make copies of the icon image
    bitmaps and the associated colour table.

    If during Workbench close/open transitions the global remap
    screen becomes NULL, GetIconTagList() may refuse to return a
    remapped icon and return with an error (ERROR_REQUIRED_ARG_MISSING)
    instead.

   SEE ALSO
    workbench/icon.h
    workbench/workbench.h
    icon.library/GetDiskObject
    icon.library/GetDiskObjectNew
    icon.library/GetDefDiskObject
    icon.library/IconControlA
    icon.library/PutIconTagList


icon.library/IconControlA

   NAME
    IconControlA -- Set and get icon and icon.library options (V44)

   SYNOPSIS
    processed = IconControlA(icon,tags);
    D0                       A0   A1

    ULONG IconControlA(struct DiskObject *,struct TagItem *);

    processed = IconControl(icon,tag1,...);

    ULONG IconControl(struct DiskObject *,Tag tag1,...);

   FUNCTION

    This function is used to modify and query icon and icon.library
    options.

   INPUTS
    icon -- Pointer to a struct DiskObject, or NULL if global
        options are to be modified/queried.
    tags -- Options to modify/query.

   TAGS
    ICONCTRLA_SetGlobalScreen (struct Screen *) -- Pointer to the
        screen to remap palette mapped icons to. This is commonly
        used by workbench.library after it has initialized itself
        and before/after screen open/close transitions. If the
        screen is set to NULL, the icon colour remapping strategy is
        changed: colours are no longer allocated from a screen
        and the colours to map to will come from a default colour
        colour table with four palette entries. Please note that
        once you select a screen to remap to, you cannot tell
        icon.library to use a different screen; you first need to
        tell icon.library to "let go" of the previously selected
        screen by passing a NULL ICONCTRLA_SetGlobalScreen parameter.
        You can set a different screen only after this is done.

    ICONCTRLA_GetGlobalScreen (struct Screen **) -- Pointer to the
        screen to remap palette mapped icons to.

    ICONCTRLA_SetGlobalPrecision (LONG) -- Set the global colour
        allocation precision used when remapping icons for
        display. Default is PRECISION_ICON.

    OBP_Precision (LONG) -- Can be used as an alias for the
        ICONCTRLA_SetGlobalPrecision tag.

    ICONCTRLA_GetGlobalPrecision (LONG *) -- Get the global colour
        allocation precision used when remapping icons for
        display.

    ICONCTRLA_SetGlobalEmbossRect (struct Rectangle *) -- Set the
        frame sizes used for drawing icons. The Rectangle
        must be initialized as follows:

            Rectangle->MinX  Width of left edge border (negative),
                             must be in the range [-255..-1]
            Rectangle->MinY  Height of top edge border (negative),
                             must be in the range [-255..-1]
            Rectangle->MaxX  Width of right edge border (positive),
                             must be in the range [1..255]
            Rectangle->MaxY  Height of bottom edge border (positive),
                             must be in the range [1..255]

    ICONCTRLA_GetGlobalEmbossRect (struct Rectangle *) -- Get the
        frame sizes used for drawing icons.

    ICONCTRLA_SetGlobalFrameless (BOOL) -- Select whether icons
        should always be drawn without a surrounding frame.
        This option defaults to FALSE.

    ICONCTRLA_GetGlobalFrameless (LONG *) -- Query whether icons
        are always drawn without a surrounding frame.

    ICONCTRLA_SetGlobalIdentifyHook (struct Hook *) -- Set the
        hook that is invoked when trying to find an icon
        for a file/drawer/volume that does not have an
        icon associated with it. If set to NULL, no hook
        will be called. The hook will be called with the
        following parameters:

        hookFunc(hook,reserved,iim)
                  A0     A2    A1

        VOID hookFunc(struct Hook *hook,APTR reserved,
                      struct IconIdentifyMsg *iim);

        The reserved parameter will be set to NULL (V44).

        The icon identification message contents are as follows:

            iim_SysBase
            iim_DOSBase
            iim_UtilityBase
            iim_IconBase
                Library base pointers set up for your use.

            iim_FileLock
                A lock on the object to return an icon for.
                This lock is guaranteed to be non-NULL.

            iim_ParentLock
                A lock on the object's parent directory. This
                may be NULL if iim_FileLock points to a volume's
                root directory. In such a case you should return
                a WBDISK type icon instead of a WBDRAWER icon.

            iim_FIB
                An initialized FileInfoBlock structure; prior
                to passing iim_FIB to you, Examine(iim_FileLock,iim_FIB)
                was called. Unlike the other members of this data
                structure, you may modify the contents of iim_FIB.

            iim_FileHandle
                If the object to return an icon for is a file,
                this member will contain a file handle that can
                be used to Read() its contents. The file read
                position will be set to the beginning of
                the file. Note that this member can be NULL.

            iim_Tags
                A copy of the tag item list passed to GetIconTagList();
                if you are going to call GetIconTagList() in your
                hook, be sure to include this list as part of the
                tag list you pass to it.

                NOTE: This list does not include the tag
                      ICONA_FailIfUnavailable. Keep in mind that
                      the use of this tag can trigger a recursion
                      if the icon you tried to retrieve via
                      GetIconTagList() does not exist: your hook
                      code will be invoked again.

        With the exception of iim_FIB, all members of the
        IconIdentifyMsg are read-only; you may pass them to
        functions like Read(), Examine(), etc. but you
        may not Close() files, UnLock() locks or perform
        other functions that may result in the data structures
        getting deallocated or trashed.

        When you manage to find the right icon type for the object
        to be examined, you should return a pointer to a
        struct DiskObject that can be freed using FreeDiskObject()
        lateron. Note that you cannot just return a pointer to a
        statically initialized data structure in your code, you
        must return a pointer to a DiskObject allocated by icon.library
        itself, such as through GetIconTagList(), DupDiskObjectA()
        or NewDiskObject().

        The icon you return will be checked to make sure that its
        type matches the corresponding object. For example, returning
        a WBDRAWER icon for a volume root directory will cause that
        icon to be released and to be ignored.

    ICONCTRLA_GetGlobalIdentifyHook (struct Hook **) -- Get the
        hook that is invoked when trying to find an icon
        for a file/drawer/volume that does not have an
        icon associated with it.

    ICONCTRLA_SetGlobalMaxNameLength (LONG) -- icon.library has
        a built-in file name length limit that affects whether
        icon files are read and written. Currently, the default
        for this value is 25 characters. This is sufficient for
        an icon file name acceptable with the ROM filing system.
        This limit has two effects: if an icon file is to be
        written whose name would be longer than the limit,
        icon.library will silently abort the write attempt and
        pretend that the icon file has been written; this is done
        in order to avoid overwriting the original data file with
        the icon file. If an icon file was read that turns out to
        contain invalid icon data, another test is done in order to
        find out whether the file name was longer than the limit. If
        this is the case, it is assumed that the data was read from
        the original file rather than from the icon file. The library
        then pretends that the icon file was not found.

        This tag can be used to set this length limit. The limit
        must be in the range [8..255].

    ICONCTRLA_GetGlobalMaxNameLength (LONG *) -- Retrieve the
        file name length limit used by icon.library.

    ICONCTRLA_SetGlobalNewIconsSupport (BOOL) -- Select whether
        icon.libray should read and return coloured icon images stored
        in NewIcons format.
        This option defaults to TRUE.

    ICONCTRLA_GetGlobalNewIconsSupport (LONG *) -- Query whether
        icon.library will read and return coloured icon images
        stored in NewIcons format.

    ICONCTRLA_SetGlobalColorIconSupport (BOOL) -- Select whether
        icon.libray should read and return coloured icon images.
        This option defaults to TRUE.

    ICONCTRLA_GetGlobalColorIconSupport (LONG *) -- Query whether
        icon.library will read and return coloured icon images.

    ICONA_ErrorCode (LONG *) -- Pointer to a LONG word variable to
        store error codes in. Note that this variable will be
        initialized regardless of whether an error occured or not.
        Thus, you can check for an error condition by comparing the
        variable contents against 0; 0 indicates success, all other
        values are error codes as defined by dos.library.

    ICONA_ErrorTagItem (struct TagItem **) -- When an error occurs
        whilst processing the tag item list passed to IconControl(),
        you can have a pointer to the item that caused the error
        passed back via the ICONA_ErrorTagItem tag. Note that for
        TagItem lists allocated from the stack the address passed
        back to you may no longer be valid when control returns from
        IconControl().

    The following tags need a valid icon parameter to operate on.
    If the parameter is missing or invalid, it will be registered
    as an error.

    ICONCTRLA_GetImageMask1 (PLANEPTR *) -- Pointer to the mask plane
        for the regular icon image (icon->do_Gadget.GadgetRender).
        Note that this may be NULL.

    ICONCTRLA_GetImageMask2 (PLANEPTR *) -- Pointer to the mask plane
        for the alternate icon image (icon->do_Gadget.SelectRender).
        Note that this may be NULL.

    ICONCTRLA_SetTransparentColor1 (LONG) -- Set the transparent
        colour for a palette mapped icon image, in this case the
        regular icon image (icon->do_Gadget.GadgetRender). The
        colour must be among the valid palette entries, e.g. for
        a 16 colour image, the transparent colour may not be
        larger than 15. To make the icon image opaque, set its
        transparent colour to -1.

    ICONCTRLA_GetTransparentColor1 (LONG *) -- Get the transparent
        colour for a palette mapped icon image, in this case the
        regular icon image (icon->do_Gadget.GadgetRender). If
        the image is opaque, its "transparent colour" will be
        returned as -1. Note that this data is valid only for
        palette mapped icons; for other types, you may not
        receive any meaningful result.

    ICONCTRLA_SetTransparentColor2 (LONG) -- Set the transparent
        colour for a palette mapped icon image, in this case the
        alternate icon image (icon->do_Gadget.SelectRender). The
        colour must be among the valid palette entries, e.g. for
        a 16 colour image, the transparent colour may not be
        larger than 15. To make the icon image opaque, set its
        transparent colour to -1. Please note that you can set
        the alternate image transparent colour only if there is
        an alternate image.

    ICONCTRLA_GetTransparentColor2 (LONG *) -- Get the transparent
        colour for a palette mapped icon image, in this case the
        alternate icon image (icon->do_Gadget.SelectRender). If
        the image is opaque, its "transparent colour" will be
        returned as -1. Note that this data is valid only for
        palette mapped icons; for other types, you may not
        receive any meaningful result. Likewise, if there is
        no alternate image, no information may be available.

    ICONCTRLA_SetPalette1 (struct ColorRegister *) -- Set the colour
        palette for a palette mapped icon image, in this case the
        regular icon image (icon->do_Gadget.GadgetRender).

    ICONCTRLA_GetPalette1 (struct ColorRegister **) -- Get the colour
        palette for a palette mapped icon image, in this case the
        regular icon image (icon->do_Gadget.GadgetRender). Note
        that this data is valid only for palette mapped icons; for
        other types, you may not receive any meaningful result.
        Note that the number of palette entries in this table
        matches the number of colours in use when the icon
        was first created.

    ICONCTRLA_SetPalette2 (struct ColorRegister *) -- Set the colour
        palette for a palette mapped icon image, in this case the
        alternate icon image (icon->do_Gadget.SelectRender).

    ICONCTRLA_GetPalette2 (struct ColorRegister **) -- Get the colour
        palette for a palette mapped icon image, in this case the
        alternate icon image (icon->do_Gadget.SelectRender). Note
        that this data is valid only for palette mapped icons; for
        other types, you may not receive any meaningful result.
        If there is no alternate image, no information may be
        available.
        Note that the number of palette entries in this table
        matches the number of colours in use when the icon
        was first created.

    ICONCTRLA_SetPaletteSize1 (ULONG) -- Set the size of the colour
        palette to be used for a palette mapped icon image, in
        this case the regular icon image (icon->do_Gadget.GadgetRender).
        This value must be in the range [1..256].

    ICONCTRLA_GetPaletteSize1 (ULONG *) -- Get the size of the colour
        palette to be used for a palette mapped icon image, in
        this case the regular icon image (icon->do_Gadget.GadgetRender).
        Note that this data is valid only for palette mapped icons; for
        other types, you may not receive any meaningful result.

    ICONCTRLA_SetPaletteSize2 (ULONG) -- Set the size of the colour
        palette to be used for a palette mapped icon image, in
        this case the alternate icon image (icon->do_Gadget.SelectRender).
        This value must be in the range [1..256].

    ICONCTRLA_GetPaletteSize2 (ULONG *) -- Get the size of the colour
        palette to be used for a palette mapped icon image, in
        this case the alternate icon image (icon->do_Gadget.SelectRender).
        Note that this data is valid only for palette mapped icons; for
        other types, you may not receive any meaningful result.
        If there is no alternate image, no information may be
        available.

    ICONCTRLA_SetImageData1 (UBYTE *) -- Set the image data to be used for
        a palette mapped icon image, in this case the regular icon
        image (icon->do_Gadget.GadgetRender). There must be exactly
        as many bytes of image data as the image width multiplied
        by its height requires.

        To drop the palette mapped image data associated with an icon,
        use "ICONCTRLA_SetImageData1,NULL,".

    ICONCTRLA_GetImageData1 (UBYTE **) -- Get the image data to be used for
        a palette mapped icon image, in this case the regular icon
        image (icon->do_Gadget.GadgetRender). Note that this data is
        valid only for palette mapped icons; for other types, you may
        not receive any meaningful result.

    ICONCTRLA_SetImageData2 (UBYTE *) -- Set the image data to be used for
        a palette mapped icon image, in this case the alternate icon
        image (icon->do_Gadget.SelectRender). There must be exactly
        as many bytes of image data as the image width multiplied
        by its height requires.

        To drop the palette mapped image data associated with the alternate
        image of an icon, use "ICONCTRLA_SetImageData2,NULL,".

    ICONCTRLA_GetImageData2 (UBYTE **) -- Get the image data to be used for
        a palette mapped icon image, in this case the alternate icon
        image (icon->do_Gadget.SelectRender). Note that this data is
        valid only for palette mapped icons; for other types, you may
        not receive any meaningful result. If there is no alternate
        image, no information may be available.

    ICONCTRLA_SetFrameless (BOOL) -- Select whether the icon should be
        drawn without a frame. This option defaults to FALSE.

    ICONCTRLA_GetFrameless (LONG *) -- Query whether the icon should be
        drawn without a frame.

    ICONCTRLA_SetNewIconsSupport (BOOL) -- Select whether palette mapped
        icon images that were originally stored in NewIcons format
        should be written back in the same format. This option
        defaults to TRUE.

    ICONCTRLA_GetNewIconsSupport (LONG *) -- Query whether palette mapped
        icon images that were originally stored in NewIcons format
        should be written back in the same format.

    ICONCTRLA_SetAspectRatio (UBYTE) -- Set the icon aspect ratio; this
        consists of a numerator and a denominator packed into a
        single byte (the PACK_ICON_ASPECT_RATIO() macro can be used
        for encoding this parameter). If the icon aspect ratio is
        unknown, ICON_ASPECT_RATIO_UNKNOWN should be used.

    ICONCTRLA_GetAspectRatio (UBYTE *) -- Get the icon aspect ratio; this
        consists of a numerator and a denominator packed into a
        single byte (the UNPACK_ICON_ASPECT_RATIO() macro can be used
        for decoding this value). If the icon aspect ratio is unknown,
        ICON_ASPECT_RATIO_UNKNOWN will be returned.

    ICONCTRLA_SetWidth (ULONG) -- Select the palette mapped icon image
        width. This value must be in the range [1..256].

    ICONCTRLA_GetWidth (ULONG *) -- Query the palette mapped icon image
        width. Note that this data is valid only for palette mapped icons;
        for other types, you may not receive any meaningful result.

    ICONCTRLA_SetHeight (ULONG) -- Select the palette mapped icon image
        height. This value must be in the range [1..256].

    ICONCTRLA_GetHeight (ULONG *) -- Query the palette mapped icon image
        height. Note that this data is valid only for palette mapped icons;
        for other types, you may not receive any meaningful result.

    ICONCTRLA_IsPaletteMapped (LONG *) -- Query whether the icon is using
        palette mapped icon images.

    ICONCTRLA_IsNewIcon (LONG *) -- Query whether the icon is of the
        NewIcon type.

    ICONCTRLA_IsNativeIcon (LONG *) -- There is an important difference
        between struct DiskObject icons allocated by icon.library itself
        (these are the so-called "native" icons) and statically initialized
        icons which consist solely of a simple struct DiskObject which may
        be part of a program's static data area. For example, you can
        attach a palette mapped icon image to a "native" icon, which is
        something you cannot do with a statically allocated icon. To help
        you tell the two types apart, you can use the ICONCTRLA_IsNativeIcon
        query tag.

    ICONGETA_IsDefaultIcon (LONG *) -- Query whether this icon is associated
        with a file/drawer/volume or is a "fake" icon that was constructed
        for an object that has no icon associated with it.

    ICONCTRLA_GetScreen (struct Screen **) -- Get the screen this icon
        has been remapped to and whose colour map it uses. Note that this
        data is valid only for palette mapped icons; for other types, you
        may not receive any meaningful result.

        This tag may return NULL if the icon is not currently associated
        with a screen.

    ICONCTRLA_HasRealImage2 (LONG *) -- icon.library may generate an
        alternate image for palette mapped icons if there is no image
        data stored for this image. To find out whether an icon
        was generated or is part of the original icon image, use the
        ICONCTRLA_HasRealImage2 tag.

   RESULT
    processed -- Number of tags that were processed correctly, i.e.
        the number of tags whose parameters are in order, for which
        information could be returned, etc. If processing stops because of
        an error, the number returned by this function will be smaller
        than the number of tag items passed in. The same happens if
        the information you wanted to obtain is unavailable. In any
        case, check the error code this routine can set up for you.

   EXAMPLE
    /* Check if the icon is palette mapped. */
    LONG isPaletteMapped;
    LONG errorCode;
    struct DiskObject *icon;

    if(IconControl(icon,
        ICONCTRLA_IsPaletteMapped,&isPaletteMapped,
        ICONA_ErrorCode,&errorCode,
    TAG_DONE) == 1)
    {
        Printf("the icon %s palette mappedn",
            isPaletteMapped ? "is" : "is not");
    }
    else
    {
        Printf("could not query icon information;n");
        PrintFault(errorCode,NULL);
    }

    /* Set the icon colour remapping precision. */
    IconControl(NULL,
        ICONCTRLA_SetGlobalPrecision,PRECISION_EXACT,
    TAG_DONE);

    /* Query the embossing rectangle dimensions and
     * the identification hook.
     */
    struct Rectangle rect;
    struct Hook *hook;

    if(IconControl(NULL,
        ICONCTRLA_GetGlobalEmbossRect,&rect,
        ICONCTRLA_GetGlobalIdentifyHook,&hook,
    TAG_DONE) == 2)
    {
        Printf("embossing rect: %ld,%ld,%ld,%ldn",
            rect.MinX,rect.MaxX,rect.MinY,rect.MaxY);
        Printf("identification hook: 0x%08lxn",
            hook);
    }

   NOTES
    Changing an icon's palette or image data does not automatically
    produce a different icon image you can use. To do this, you
    must re-layout it using LayoutIcon().

    When querying parameters, make sure to always pass in a pointer
    to a LONG word variable to store the result in.

    Some get/set operations may cause additional memory to be
    allocated. This may fail; be prepared.

    IconControl() processes the tag item list in sequential order.
    This has consequences for several tags, such as the palette size
    and the transparent colour. For example, if you want to make
    colour #14 of an icon image transparent, make sure to have the
    palette size set to at least 15 colours before you try to change
    the transparent colour. Otherwise, IconControl() may refuse to
    set the transparent colour to #14 since it won't know that there
    should be more than 14 colours in that image at the time you try
    to set it. Therefore, if you wanted to change the palette size and
    the transparent colour in the same tag item list, make sure that the
    palette size change tag appears before the transparent colour change
    tag.

    As described above, some of the operations on icons are not
    supported for DiskObjects not allocated through icon.library. In
    such cases you will receive an error code ERROR_ACTION_NOT_KNOWN.

   SEE ALSO
    dos.library/IoErr
    icon.library/DupDiskObjectA
    icon.library/GetIconTagList
    icon.library/LayoutIcon
    icon.library/NewDiskObject
    graphics.library/BltMaskBitMapRastPort
    graphics.library/ObtainBestPenA
    utility.library/CallHookPkt
    graphics/view.h
    workbench/icon.h
    workbench/workbench.h


icon.library/LayoutIconA

   NAME
    LayoutIconA -- Adapt a palette-mapped icon for display (V44)

   SYNOPSIS
    success = LayoutIconA(icon,screen,tags);
    D0                    A0   A1     A2

    BOOL LayoutIconA(struct DiskObject *icon,struct Screen *screen,
                     struct TagItem *tags);

    success = LayoutIcon(icon,screen,...);

    BOOL LayoutIcon(struct DiskObject *icon,struct Screen *screen,...);

   FUNCTION
    This function will prepare an icon for display, either on a
    specific screen or using a default colour palette. It is
    useful only for palette mapped icons.

   INPUTS
    icon -- The icon to be remapped. This must be a palette mapped
        icon.
    screen -- Pointer to a screen to remap the icon for or NULL
        to remap the icon to use the system default colour palette
        or something very similar to it (this means: four colours
        only).
    tags -- Additional rendering options.

   TAGS
    OBP_Precision (LONG) -- Pen colour allocation precision.
        Default is the same precision as set in the global
        icon.library settings (see IconControlA()).

   OUTPUTS
    success -- TRUE if the icon could be remapped, FALSE if
        the remapping failed for some reason. In case of
        of failure, icon.library will try its best to keep
        the icon in a presentable state, but this may fail.
        In case of failure, the error code can be retrieved
        using dos.library/IoErr.

   NOTES
    You must make sure that the screen you remap to does not
    go away while there is an icon to use its colours. For
    a public screen, the easiest way to guarantee this is
    to keep it locked (see intuition.library/LockPubScreen).
    For custom screens, just don't close them! If you have to close
    the screen or need to keep your icon around until after a screen
    is closed, you should call LayoutIcon() with a NULL screen
    parameter. This will release all pens the icon has allocated
    and remap the icon to a default set of colours. Alternatively,
    you can dispose of the icon via FreeDiskObject() which
    will also release all pens the icon has allocated, including
    the icon itself, of course.

    Icons remapped to the global default screen (normally, that
    would be the Workbench screen) may get changed and remapped
    again during Workbench close/open transitions. To prevent
    this from taking place, just make sure that the Workbench
    screen does not close (e.g. via LockPubScreen("Workbench")).

   SEE ALSO
    dos.library/IoErr
    graphics.library/ObtainBestPenA
    graphics.library/ReleasePen
    icon.library/FreeDiskObject
    icon.library/GetIconTagList
    icon.library/IconControl
    intuition.library/LockPubScreen
    intuition.library/UnlockPubScreen
    graphics/view.h


icon.library/MatchToolValue

   NAME
    MatchToolValue - check a tool type variable for a particular value.

   SYNOPSIS
    result = MatchToolValue(typeString, value)
      D0                        A0        A1

    BOOL MatchToolValue(STRPTR, STRPTR);

   FUNCTION
    MatchToolValue is useful for parsing a tool type value for
    a known value.  It knows how to parse the syntax for a tool
    type value (in particular, it knows that '|' separates
    alternate values).  Note that the parsing is case insensitive.

   INPUTS
    typeString -- a ToolType value (as returned by FindToolType)
    value -- you are interested if value appears in typeString

   RESULTS
    result -- TRUE if the value was in typeString else FALSE.

   EXAMPLE
    Assume there are two type strings:
        type1 = "text"
        type2 = "a|b|c"

    MatchToolValue( type1, "text" ) returns TRUE
    MatchToolValue( type1, "TEXT" ) returns TRUE
    MatchToolValue( type1, "data" ) returns FALSE
    MatchToolValue( type2, "a" )    returns TRUE
    MatchToolValue( type2, "b" )    returns TRUE
    MatchToolValue( type2, "d" )    returns FALSE
    MatchToolValue( type2, "a|b" )  returns FALSE

   NOTES
    icon.library V44 skips blank spaces surrounding the typeString
    options and the value string. Older icon.library versions did
    not support this.

   SEE ALSO
    icon.library/FindToolType
    utility.library/Stricmp


icon.library/NewDiskObject

   NAME
    NewDiskObject -- Create an empty icon (V44)

   SYNOPSIS
    icon = NewDiskObject(type)
    D0                   D0

    struct DiskObject * NewDiskObject(LONG type);

   FUNCTION
    This function is used to create an "empty" DiskObject
    structure, which has no image data associated with it.
    Still, all the necessary structures are in place,
    you just have to fill them in.

   INPUTS
    type -- Icon type to create, this must be one of WBDISK,
        WBDRAWER, WBTOOL, WBPROJECT, WBGARBAGE, WBDEVICE or WBKICK.

   RESULT
    icon -- Pointer to a struct DiskObject or NULL in case of error.
        You can use IoErr() to retrieve the error code.

   NOTES
    The DiskObject returned by this function will have a zero
    width and height Image in the do_Gadget.GadgetRender member
    and the do_Gadget.Width/do_Gadget.Height members will both
    be 0, too.

   SEE ALSO
    dos.library/IoErr
    workbench/icon.h
    workbench/workbench.h


icon.library/PutDefDiskObject

   NAME
    PutDefDiskObject - write disk object as the default for its type.  (V36)

   SYNOPSIS
    status = PutDefDiskObject(diskobj)
      D0                        A0

    BOOL PutDefDiskObject(struct DiskObject *);

   FUNCTION
    This routine writes out a DiskObject structure, and its
    associated information.  If the call fails, FALSE will
    be returned.  The reason for the failure may be obtained
    via IoErr().

    Note that this function calls PutDiskObject() internally which means
    that this call (if sucessful) notifies workbench than an icon has
    been created/modified.

    Using this routine protects you from any future changes to
    the way default icons are stored within the system.

   INPUTS
    diskobj -- a pointer to a DiskObject

   RESULTS
    status -- TRUE if the call succeeded else FALSE

   SEE ALSO
    dos.library/IoErr
    icon.library/GetDefDiskObject
    icon.library/GetIconTagList
    icon.library/PutDiskObject


icon.library/PutDiskObject

   NAME
    PutDiskObject - write out a DiskObject to disk.

   SYNOPSIS
    status = PutDiskObject(name, diskobj)
     D0                    A0      A1

    BOOL PutDiskObject(STRPTR, struct DiskObject *);

   FUNCTION
    This routine writes out a DiskObject structure, and its
    associated information.  The file name of the info
    file will be the name parameter with ".info" postpended
    to it.  If the call fails, FALSE will be returned.  The
    reason for the failure may be obtained via IoErr().

    As of release V2.0, PutDiskObject() (if successful) notifies Workbench
    when an icon has been created/modified.

    Using this routine protects you from any future changes to
    the way icons are stored within the system.

   INPUTS
    name -- name of the object (pointer to a character string)
    diskobj -- a pointer to a DiskObject

   RESULTS
    status -- TRUE if the call succeeded else FALSE

   NOTES
    It is recommended that if you wish to copy an icon from one place
    to another than you use GetDiskObject() and PutDiskObject()
    and do not copy them directly.

   SEE ALSO
    dos.library/IoErr
    icon.library/DeleteDiskObject
    icon.library/FreeDiskObject
    icon.library/GetDiskObject
    icon.library/GetIconTagList
    icon.library/PutIconTagList


icon.library/PutIconTagList

   NAME
    PutIconTagList -- Store an icon (V44)

   SYNOPSIS
    success = PutIconTagList(name,icon,tags);
    D0                       A0   A1   A2

    BOOL PutIconTagList(STRPTR name,struct DiskObject *icon,
                        struct TagItem *tags);

    success = PutIconTags(name,icon,tag1,...);

    BOOL PutIconTags(STRPTR name,struct DiskObject *icon,
                        Tag tag1,...);

   FUNCTION
    This function is used to store an icon; the icon can
    belong to a file/drawer/volume or it can be a default icon.

   INPUTS
    name -- Name of the object the icon is to be stored for,
        or NULL if a default icon is to be stored.
    icon -- The icon to be stored.
    tags -- Storage options.

   TAGS
    ICONPUTA_NotifyWorkbench (BOOL) -- Set this to TRUE to notify
        Workbench of the fact that an icon was changed.

        This tag defaults to FALSE.

    ICONPUTA_PutDefaultType (LONG) -- Type of the default icon
        this icon is to replace; must be one of WBDISK, WBDRAWER,
        WBTOOL, WBPROJECT, WBGARBAGE, WBDEVICE or WBKICK.

        If this tag is used, the "name" parameter will be ignored.

    ICONPUTA_PutDefaultName (STRPTR) -- Name of the default object
        type this icon is to be stored as.

        If this tag is used, the "name" parameter will be ignored.

    ICONPUTA_DropPlanarIconImage (BOOL) -- If you decide that the
        palette mapped icon imagery is sufficient to represent
        an icon, you can tell icon.library not to store the original,
        planar icon image data with the icon file. To do this,
        set this tag to TRUE. Instead of the planar icon images,
        a single default image will be stored. This can result
        in space savings but may not look too pretty.

        This tag defaults to FALSE.

    ICONPUTA_DropChunkyIconImage (BOOL) -- This tag can be used to
        keep the chunky icon image data from getting written
        to disk.

        This tag defaults to FALSE.

    ICONPUTA_DropNewIconToolTypes (BOOL) -- This tag controls whether
        any NewIcon tool types will be omitted when writing the
        icon to disk. TRUE will omit the data.

        This tag defaults to FALSE.

    ICONPUTA_OptimizeImageSpace (BOOL) -- A palette mapped icon
        image might not use the entire icon palette. By default,
        icon.library does not bother about this, it expects the
        creator of the icon to choose its palette efficiently.
        But just in case, you can tell icon.library to attempt
        to identify how many colours are really in use and to
        optimize its image compressor for them. This may take
        extra time and is not recommended for daily use.

        This tag defaults to FALSE.

    ICONPUTA_OnlyUpdatePosition (BOOL) -- This tag can be used to
        reduce the overhead in updating icon information on disk
        if the only information changed is the icon position.
        For this case, you can set this tag to TRUE. The icon
        to be modified will have only its do_CurrentX/do_CurrentY
        member values changed, the remainer will stay unmodified.
        Please note that this tag only takes effect if the
        ICONPUTA_PutDefaultType and ICONPUTA_PutDefaultName tags
        are omitted.

        This tag defaults to FALSE.

    ICONPUTA_PreserveOldIconImages (BOOL) -- Before writing a
        palette mapped icon back to disk, icon.library will make
        sure that the original planar image data is stored in the
        file. If you don't want that to happen, set this option to
        FALSE. This tag will allow you to change the planar icon
        image data written back to disk.

        This tag defaults to TRUE.

    ICONA_ErrorCode (LONG *) -- Pointer to a LONG word variable to
        store error codes in. Note that this variable will be
        initialized regardless of whether an error occured or not.
        Thus, you can check for an error condition by comparing the
        variable contents against 0; 0 indicates success, all other
        values are error codes as defined by dos.library.

   RESULT
    success -- TRUE if the icon file could be stored, FALSE otherwise.
        You can use IoErr() to retrieve the error code or use the
        ICONA_ErrorCode tag instead.

   EXAMPLE
    /* Store an icon as the default "picture" icon. */
    struct DiskObject *icon;
    LONG errorCode;
    BOOL success;

    success = PutIconTags(NULL,icon,
        ICONPUTA_PutDefaultName,"picture",
        ICONA_ErrorCode,&errorCode,
    TAG_DONE);

    if(success == FALSE)
    {
        Printf("could not store default picture icon;n");
        PrintFault(errorCode,NULL);
    }

   NOTES
    This function is a superset of PutDefDiskObject() and PutDiskObject().

    If the name of the icon file to be stored would be too long to fit
    (as set with IconControl(..., ICONCTRLA_SetGlobalMaxNameLength, ...))
    then PutIconTagList() will silently pretend that the icon file has
    been written to disk. However, it will not store the icon file on the
    disk since there would a risk of accidentally overwriting the file the
    icon belongs to. If you want to know whether the icon you wrote was
    in fact written to disk, provide an error code pointer with the
    ICONA_ErrorCode tag. If the name of the file was too long,
    PutIconTagList() will still pretend that the icon file was written
    successfully, but the error code ERROR_TOO_MANY_LEVELS will be stored
    in the variable you passed in with the ICONA_ErrorCode tag.

   SEE ALSO
    workbench/icon.h
    workbench/workbench.h
    icon.library/GetIconTagList
    icon.library/PutDefDiskObject
    icon.library/PutDiskObject


iffparse.doc

     AllocIFF()
     AllocLocalItem()
     CloseClipboard()
     CloseIFF()
     CollectionChunk()
     CollectionChunks()
     CurrentChunk()
     EntryHandler()
     ExitHandler()
     FindCollection()
     FindLocalItem()
     FindProp()
     FindPropContext()
     FreeIFF()
     FreeLocalItem()
     GoodID()
     GoodType()
     IDtoStr()
     InitIFF()
     InitIFFasClip()
     InitIFFasDOS()
     LocalItemData()
     OpenClipboard()
     OpenIFF()
     ParentChunk()
     ParseIFF()
     PopChunk()
     PropChunk()
     PropChunks()
     PushChunk()
     ReadChunkBytes()
     ReadChunkRecords()
     SetLocalItemPurge()
     StopChunk()
     StopChunks()
     StopOnExit()
     StoreItemInContext()
     StoreLocalItem()
     WriteChunkBytes()
     WriteChunkRecords()


iffparse.library/AllocIFF

   NAME
    AllocIFF -- create a new IFFHandle structure. (V36)

   SYNOPSIS
    iff = AllocIFF()
    D0

    struct IFFHandle *AllocIFF(VOID);

   FUNCTION
    Allocates and initializes a new IFFHandle structure.
    This function is the only supported way to create an IFFHandle
    structure since there are private fields that need to be initialized.

   RESULT
    iff - pointer to IFFHandle structure or NULL if the allocation failed.

   SEE ALSO
    FreeIFF(), <libraries/iffparse.h>


iffparse.library/AllocLocalItem

   NAME
    AllocLocalItem -- create a local context item structure. (V36)

   SYNOPSIS
    item = AllocLocalItem(type, id, ident, dataSize);
    D0                    D0    D1  D2     D3

    struct LocalContextItem *AllocLocalItem(LONG, LONG, LONG, LONG);

   FUNCTION
    Allocates and initializes a LocalContextItem structure with "dataSize"
    bytes of associated user data. This is the only supported way to
    create such an item. The user data can be accessed with the
    LocalItemData() function. An item created with this function
    automatically has its purge vectors set up correctly to dispose of
    itself and its associated user data area. Any additional cleanup
    should be done with a user-supplied purge vector.

   INPUTS
    type,id - additional longword identification values
    ident - longword identifier for class of context item
    dataSize - number of bytes of user data to allocate for this item

   RESULT
    item - pointer to initialized LocalContextItem or NULL if the
           allocation failed.

   SEE ALSO
    FreeLocalItem(), LocalItemData(), StoreLocalItem(),
    StoreItemInContext(), SetLocalItemPurge(), <libraries/iffparse.h>


iffparse.library/CloseClipboard

   NAME
    CloseClipboard -- close and free an open ClipboardHandle. (V36)

   SYNOPSIS
    CloseClipboard(clipHandle);
                   A0

    VOID CloseClipboard(struct ClipboardHandle *);

   FUNCTION
    Closes the clipboard.device and frees the ClipboardHandle structure.

   INPUTS
    clipHandle - pointer to ClipboardHandle struct created with
                 OpenClipboard(). Starting with V39, this may be NULL.

   SEE ALSO
    OpenClipboard(), InitIFFasClip(), <libraries/iffparse.h>


iffparse.library/CloseIFF

   NAME
    CloseIFF -- close an IFF context. (V36)

   SYNOPSIS
    CloseIFF(iff);
             A0

    VOID CloseIFF(struct IFFHandle *);

   FUNCTION
    Completes an IFF read or write operation by closing the IFF context
    established for this IFFHandle structure. The IFFHandle structure
    itself is left ready for re-use and a new context can be opened with
    OpenIFF(). This function can be used for cleanup if a read or write
    fails partway through.

    As part of its cleanup operation, CloseIFF() calls the client-
    supplied stream hook vector. The IFFStreamCmd packet will be set
    as follows:

        sc_Command:	IFFCMD_CLEANUP
        sc_Buf:		(Not applicable)
        sc_NBytes:	(Not applicable)

    This operation is NOT permitted to fail;  any error code returned
    will be ignored (best to return 0, though). DO NOT write to this
    structure.

   INPUTS
    iff - pointer to IFFHandle structure previously opened with
          OpenIFF(). Starting with V39, this may be NULL.

   SEE ALSO
    OpenIFF(), InitIFF(), <libraries/iffparse.h>


iffparse.library/CollectionChunk

   NAME
    CollectionChunk -- declare a chunk type for collection. (V36)

   SYNOPSIS
    error = CollectionChunk(iff, type, id);
    D0                      A0   D0    D1

    LONG CollectionChunk(struct IFFHandle *, LONG, LONG);

   FUNCTION
    Installs an entry handler for chunks with the given type and id so
    that the contents of those chunks will be stored as they are
    encountered. This is like PropChunk() except that more than one
    chunk of this type can be stored in lists which can be returned by
    FindCollection(). The storage of these chunks still follows the
    property chunk scoping rules for IFF files so that at any given
    point, stored collection chunks will be valid in the current context.

   INPUTS
    iff - pointer to IFFHandle structure (does not need to be open)
    type - type code for the chunk to declare (ex. "ILBM")
    id - identifier for the chunk to declare (ex. "CRNG")

   RESULT
    error - 0 if successful or an IFFERR_#? error code if unsuccessful.

   SEE ALSO
    CollectionChunks(), FindCollection(), PropChunk(),
    <libraries/iffparse.h>


iffparse.library/CollectionChunks

   NAME
    CollectionChunks -- declare many collection chunks at once. (V36)

   SYNOPSIS
    error = CollectionChunks(iff, propArray, numPairs);
    D0                       A0   A1         D0

    LONG CollectionChunks(struct IFFHandle *, LONG *, LONG);

   FUNCTION
    Declares multiple collection chunks from a list. The propArray argument
    is a pointer to an array of longwords arranged in pairs. The format
    for the list is as follows:

        TYPE1, ID1, TYPE2, ID2, ..., TYPEn, IDn

    The argument numPairs is the number of pairs. CollectionChunks() just calls
    CollectionChunk() numPairs times.

   INPUTS
    iff - pointer to IFFHandle structure (does not need to be open)
    propArray - pointer to array of longword chunk types and identifiers
    numPairs - number of pairs in array.

   RESULT
    error - 0 if successful or an IFFERR_#? error code if unsuccessful

   SEE ALSO
    CollectionChunk(), <libraries/iffparse.h>


iffparse.library/CurrentChunk

   NAME
    CurrentChunk -- get context node for current chunk. (V36)

   SYNOPSIS
    top = CurrentChunk(iff);
    D0                 A0

    struct ContextNode *CurrentChunk(struct IFFHandle *);

   FUNCTION
    Returns the top context node for the given IFFHandle structure. The top
    context node corresponds to the chunk most recently pushed on the
    stack, which is the chunk where the stream is currently positioned.
    The ContextNode structure contains information on the type of chunk
    currently being parsed (or written), its size and the current
    position within the chunk.

   INPUTS
    iff - pointer to IFFHandle structure

   RESULT
    top - pointer to top context node or NULL if none

   SEE ALSO
    PushChunk(), PopChunk(), ParseIFF(), ParentChunk(),
    <libraries/iffparse.h>


iffparse.library/EntryHandler

   NAME
    EntryHandler -- add an entry handler to the IFFHandle context. (V36)

   SYNOPSIS
    error = EntryHandler(iff, type, id, position, handler, object);
    D0                   A0   D0    D1  D2        A1       A2

    LONG EntryHandler(struct IFFHandle *, LONG, LONG, LONG,
                      struct Hook *, APTR);

   FUNCTION
    Installs an entry handler vector for a specific type of chunk into
    the context for the given IFFHandle structure. Type and id are the
    longword identifiers for the chunk to handle. The handler is a client-
    supplied standard Hook structure, properly initialized. position
    tells where to put the handler in the context. The handler will be
    called whenever the parser enters a chunk of the given type, so the
    IFF stream will be positioned to read the first data byte in the
    chunk. The handler will execute in the same context as whoever
    called ParseIFF(). The handler will be called (through the hook)
    with the following arguments:

        A0:	the Hook pointer you passed.
        A2:	the 'object' pointer you passed.
        A1:	pointer to a LONG containing the value
            IFFCMD_ENTRY.

    The error code your call-back routine returns will affect the parser
    in three different ways:

    Return value		Result
    ------------		------
    0:			Normal success;  ParseIFF() will continue
                through the file.
    IFF_RETURN2CLIENT:	ParseIFF() will stop and return the value 0.
                (StopChunk() is internally implemented using
                this return value.)
    Any other value:	ParseIFF() will stop and return the value
                you supplied. This is how errors should be
                returned.

   INPUTS
    iff - pointer to IFFHandle structure.
    type - type code for chunk to handle (ex. "ILBM").
    id - ID code for chunk to handle (ex. "CMAP").
    position- local context item position. One of the IFFSLI_#? codes.
    handler - pointer to Hook structure.
    object - a client-defined pointer which is passed in A2 during call-
         back.

   RESULT
    error - 0 if successful or an IFFERR_#? error code if unsuccessful.

   BUGS
    Returning the values IFFERR_EOF or IFFERR_EOC from the call-back
    routine *may* confuse the parser.

    There is no way to explicitly remove a handler once installed.
    However, by installing a do-nothing handler using IFFSLI_TOP,
    previous handlers will be overridden until the context expires.

   SEE ALSO
    ExitHandler(), StoreLocalItem(), StoreItemInContext(),
    <utility/hooks.h>, <libraries/iffparse.h>


iffparse.library/ExitHandler

   NAME
    ExitHandler -- add an exit handler to the IFFHandle context. (V36)

   SYNOPSIS
    error = ExitHandler(iff, type, id, position, handler, object);
    D0                  A0   D0    D1  D2        A1       A2

    LONG ExitHandler(struct IFFHandle *, LONG, LONG, LONG,
                     struct Hook *, APTR object(;

   FUNCTION
    Installs an exit handler vector for a specific type of chunk into the
    context for the given IFFHandle structure. Type and id are the longword
    identifiers for the chunk to handle. The handler is a client-supplied
    standard Hook structure, properly initialized. Position tells
    where to put the handler in the context. The handler will be called
    just before the parser exits the given chunk in the "pause" parse
    state. The IFF stream may not be positioned predictably within the
    chunk. The handler will execute in the same context as whoever
    called ParseIFF(). The handler will be called (through the hook)
    with the following arguments:

        A0:	the Hook pointer you passed.
        A2:	the 'object' pointer you passed.
        A1:	pointer to a LONG containing the value
            IFFCMD_EXIT.

    The error code your call-back routine returns will affect the parser
    in three different ways:

    Return value		Result
    ------------		------
    0:			Normal success;  ParseIFF() will continue
                through the file.
    IFF_RETURN2CLIENT:	ParseIFF() will stop and return the value 0.
                (StopChunk() is internally implemented using
                this return value.)
    Any other value:	ParseIFF() will stop and return the value
                you supplied. This is how errors should be
                returned.

   INPUTS
    iff - pointer to IFFHandle structure.
    type - type code for chunk to handle (ex. "ILBM").
    id - identifier code for chunk to handle (ex. "CMAP").
    position - local context item position. One of the IFFSLI_#? codes.
    handler - pointer to Hook structure.
    object - a client-defined pointer which is passed in A2 during call-
         back.

   RESULT
    error - 0 if successful or an IFFERR_#? error code if unsuccessful.

   BUGS
    Returning the values IFFERR_EOF or IFFERR_EOC from the call-back
    routine *may* confuse the parser.

    There is no way to explicitly remove a handler once installed.
    However, by installing a do-nothing handler using IFFSLI_TOP,
    previous handlers will be overridden until the context expires.

   SEE ALSO
    EntryHandler(), StoreLocalItem(), StoreItemInContext(),
    <utility/hooks.h>, <libraries/iffparse.h>


iffparse.library/FindCollection

   NAME
    FindCollection -- get a pointer to the current list of collection
              items. (V36)

   SYNOPSIS
    ci = FindCollection(iff, type, id);
    D0                  A0   D0    D1

    struct CollectionItem *FindCollection(struct IFFHandle *, LONG, LONG);

   FUNCTION
    Returns a pointer to a list of CollectionItem structures for each of
    the collection chunks of the given type encountered so far in the
    course of parsing this IFF file. The items appearing first in the
    list will be the ones encountered most recently.

   INPUTS
    iff - pointer to IFFHandle structure.
    type - type code to search for.
    id - identifier code to search for.

   RESULT
    ci - pointer to last collection chunk encountered with
         links to previous ones.

   SEE ALSO
    CollectionChunk(), CollectionChunks(), <libraries/iffparse.h>


iffparse.library/FindLocalItem

   NAME
    FindLocalItem -- return a local context item from the context stack.
                     (V36)

   SYNOPSIS
    lci = FindLocalItem(iff, type, id, ident);
    D0                  A0   D0    D1  D2

    struct LocalContextItem	*FindLocalItem(struct IFFHandle	*,
                                           LONG, LONG, LONG);

   FUNCTION
    Searches the context stack of the given IFFHandle structure for a
    local context item which matches the given ident, type and id. This
    function searches the context stack from the most current context
    backwards, so that the item found (if any) will be the one with
    greatest precedence in the context stack.

   INPUTS
    iff - pointer to IFFHandle structure.
    type - type code to search for.
    id - ID code to search for.
    ident - ident code for the class of context item to search for
        (ex. "exhd" -- exit handler).

   RESULT
    lci - pointer to local context item, or NULL if nothing matched.

   SEE ALSO
    StoreLocalItem(), <libraries/iffparse.h>


iffparse.library/FindProp

   NAME
    FindProp -- search for a stored property chunk. (V36)

   SYNOPSIS
    sp = FindProp(iff, type, id);
    D0            A0   D0    D1

    struct StoredProperty *FindProp(struct IFFHandle *, LONG, LONG);

   FUNCTION
    Searches for the stored property which is valid in the given context.
    Property chunks are automatically stored by ParseIFF() when
    pre-declared by PropChunk() or PropChunks(). The StoredProperty
    struct, if found, contains a pointer to a data buffer containing the
    contents of the stored property.

   INPUTS
    iff - pointer to IFFHandle structure.
    type - type code for chunk to search for (ex. "ILBM").
    id - identifier code for chunk to search for (ex. "CMAP").

   RESULT
    sp - pointer to stored property, or NULL if none found.

   SEE ALSO
    PropChunk(), PropChunks(), <libraries/iffparse.h>


iffparse.library/FindPropContext

   NAME
    FindPropContext -- get the property context for the current state.
                       (V36)

   SYNOPSIS
    cn = FindPropContext(iff);
    D0                   A0

    struct ContextNode *FindPropContext(struct IFFHandle *);

   FUNCTION
    Locates the context node which would be the scoping chunk for
    properties in the current parsing state. (Huh?)  This is used for
    locating the proper scoping context for property chunks i.e. the
    scope from which a property would apply. This is usually the FORM
    or LIST with the highest precedence in the context stack.

    If you don't understand this, read the IFF spec a couple more times.

   INPUTS
    iff - pointer to IFFHandle structure.

   RESULT
    cn - ContextNode of property scoping chunk.

   SEE ALSO
    CurrentChunk(), ParentChunk(), StoreItemInContext(),
    <libraries/iffparse.h>


iffparse.library/FreeIFF

   NAME
    FreeIFF -- deallocate an IFFHandle structure. (V36)

   SYNOPSIS
    FreeIFF(iff);
            A0

    VOID FreeIFF(struct IFFHandle *);

   FUNCTION
    Deallocates all resources associated with this IFFHandle structure.
    The structure MUST have already been closed with CloseIFF().

   INPUTS
    iff - pointer to IFFHandle structure to free. Starting with V39,
          this may be NULL.

   SEE ALSO
    AllocIFF(), CloseIFF(), <libraries/iffparse.h>


iffparse.library/FreeLocalItem

   NAME
    FreeLocalItem -- deallocate a local context item structure. (V36)

   SYNOPSIS
    FreeLocalItem(localItem);
                  A0

    VOID FreeLocalItem(struct LocalContextItem *);

   FUNCTION
    Frees the memory for the local context item and any associated user
    memory as allocated with AllocLocalItem(). User purge vectors should
    call this function after they have freed any other resources
    associated with this item.

    Note that FreeLocalItem() does NOT call the custom purge vector set
    up through SetLocalItemPurge(); all it does is free the local context
    item. (This implies that your custom purge vector would want to call
    this to ultimately free the LocalContextItem.)

   INPUTS
    localItem - pointer to LocalContextItem created with AllocLocalItem.
                Starting with V39, this may be NULL.

   SEE ALSO
    AllocLocalItem(), <libraries/iffparse.h>


iffparse.library/GoodID

   NAME
    GoodID -- test if an identifier follows the IFF 85 specification. (V36)

   SYNOPSIS
    isok = GoodID(id);
    D0            D0

    LONG GoodID(LONG);

   FUNCTION
    Tests the given longword identifier to see if it meets all the EA IFF
    85 specifications for a chunk ID. If so, it returns non-zero,
    otherwise 0.

   INPUTS
    id - potential 32 bit identifier.

   RESULT
    isok - non-zero if this is a valid ID, 0 otherwise.

   SEE ALSO
    GoodType()


iffparse.library/GoodType

   NAME
    GoodType -- test if a type follows the IFF 85 specification. (V36)

   SYNOPSIS
    isok = GoodType(type)
    D0              D0

    LONG GoodType(LONG);

   FUNCTION
    Tests the given longword type identifier to see if it meets all the
    EA IFF 85 specifications for a FORM type (requirements for a FORM
    type are more stringent than those for a simple chunk ID). If it
    complies, GoodType() returns non-zero, otherwise 0.

   INPUTS
    type - potential 32 bit format type identifier.

   RESULT
    isok - non-zero if this is a valid type id, 0 otherwise.

   SEE ALSO
    GoodID()


iffparse.library/IDtoStr

   NAME
    IDtoStr -- convert a longword identifier to a null-terminated string.
               (V36)

   SYNOPSIS
    str = IDtoStr(id, buf);
    D0            D0  A0

    STRPTR IDtoStr(LONG, STRPTR);

   FUNCTION
    Writes the ASCII equivalent of the given longword ID into buf as a
    null-terminated string.

   INPUTS
    id - longword ID.
    buf - character buffer to accept string (at least 5 chars).

   RESULT
    str - the value of 'buf'.


iffparse.library/InitIFF

   NAME
    InitIFF -- initialize an IFFHandle structure as a user stream. (V36)

   SYNOPSIS
    InitIFF(iff, flags, streamHook);
            A0   D0     A1

    VOID InitIFF(struct IFFHandle *, LONG, struct Hook *);

   FUNCTION
    Initializes an IFFHandle as a general user-defined stream by
    allowing the user to declare a hook that the library will call to
    accomplish the low-level reading, writing, and seeking of the stream.
    Flags are the stream I/O flags for the specified stream; typically a
    combination of the IFFF_?SEEK flags.

    The stream vector is called with the following arguments:

        A0:	pointer to streamhook.
        A2:	pointer to IFFHandle structure.
        A1:	pointer to IFFStreamCmd structure.

    The IFFStreamCmd packet appears as follows:

        sc_Command:	Contains an IFFCMD_#? value
        sc_Buf:		Pointer to memory buffer
        sc_NBytes:	Number of bytes involved in operation

    The values taken on by sc_Command, and their meaning, are as follows:

    IFFCMD_INIT:
        Prepare your stream for reading. This is used for certain
        streams that can't be read immediately upon opening, and need
        further preparation. (The clipboard.device is an example of
        such a stream.)  This operation is allowed to fail;  any
        error code will be returned directly to the client. sc_Buf
        and sc_NBytes have no meaning here.
    IFFCMD_CLEANUP:
        Terminate the transaction with the associated stream. This
        is used with streams that can't simply be closed. (Again,
        the clipboard is an example of such a stream.)  This
        operation is not permitted to fail;  any error returned will
        be ignored (best to return 0, though). sc_Buf and sc_NBytes
        have no meaning here.
    IFFCMD_READ:
        Read from the stream. You are to read sc_NBytes from the
        stream and place them in the buffer pointed to by sc_Buf.
        Any (non-zero) error returned will be remapped by the parser
        into IFFERR_READ.
    IFFCMD_WRITE:
        Write to the stream. You are to write sc_NBytes to the
        stream from the buffer pointed to by sc_Buf. Any (non-zero)
        error returned will be remapped by the parser into
        IFFERR_WRITE.
    IFFCMD_SEEK:
        Seek on the stream. You are to perform a seek on the stream
        relative to the current position. sc_NBytes is signed;
        negative values mean seek backward, positive values mean seek
        forward. sc_Buf has no meaning here. Any (non-zero) error
        returned will be remapped by the parser into IFFERR_SEEK.

    All errors are returned in D0. A return of 0 indicates success.
    UNDER NO CIRCUMSTANCES are you permitted to write to the IFFStreamCmd
    structure.

   INPUTS
    iff - pointer to IFFHandle structure to initialize.
    flags - stream I/O flags for the IFFHandle.
    streamHook - pointer to Hook structure.

   SEE ALSO
    <utility/hooks.h>, <libraries/iffparse.h>


iffparse.library/InitIFFasClip

   NAME
    InitIFFasClip -- initialize an IFFHandle as a clipboard stream. (V36)

   SYNOPSIS
    InitIFFasClip(iff);
                  A0

    VOID InitIFFasClip(struct IFFHandle *);

   FUNCTION
    Initializes the given IFFHandle to be a clipboard stream. The
    function initializes the stream processing vectors to operate on
    streams of the ClipboardHandle type. The iff_Stream field will still
    need to be initialized to point to a ClipboardHandle as returned from
    OpenClipboard().

   INPUTS
    iff - pointer to IFFHandle structure.

   SEE ALSO
    InitIFF(), OpenClipboard(), <libraries/iffparse.h>


iffparse.library/InitIFFasDOS

   NAME
    InitIFFasDOS -- initialize an IFFHandle as a DOS stream. (V36)

   SYNOPSIS
    InitIFFasDOS(iff)
                 A0

    InitIFFasDOS(struct IFFHandle *);

   FUNCTION
    The function initializes the given IFFHandle to operate on DOS
    streams. The iff_Stream field will need to be initialized as a BPTR
    returned from the DOS function Open().

   INPUTS
    iff - pointer to IFFHandle structure.

   SEE ALSO
    InitIFF()


iffparse.library/LocalItemData

   NAME
    LocalItemData -- get pointer to user data for local context item. (V36)

   SYNOPSIS
    data = LocalItemData(localItem);
    D0                   A0

    APTR LocalItemData(struct LocalContextItem *);

   FUNCTION
    Returns pointer to the user data associated with the given local
    context item. The size of the data area depends on the "dataSize"
    argument used when allocating this item. If the pointer to the item
    given (localItem) is NULL, this function returns NULL.

   INPUTS
    localItem - pointer to local context item or NULL.

   RESULT
    data - pointer to user data area or NULL if localItem is NULL.

   BUGS
    Currently, there is no way to determine the size of the user data
    area; you have to 'know'.

   SEE ALSO
    AllocLocalItem(), FreeLocalItem(), <libraries/iffparse.h>


iffparse.library/OpenClipboard

   NAME
    OpenClipboard -- create a handle on a clipboard unit. (V36)

   SYNOPSIS
    ch = OpenClipboard(unitNumber)
    D0                 D0

    struct ClipboardHandle *OpenClipboard(LONG);

   FUNCTION
    Opens the clipboard.device and opens a stream for the specified unit
    (usually PRIMARY_CLIP). This handle structure will be used as the
    clipboard stream for IFFHandles initialized as clipboard streams by
    InitIFFasClip().

   INPUTS
    unitNumber - clipboard unit number (usually PRIMARY_CLIP).

   RESULT
    ch - pointer to ClipboardHandle structure or NULL if unsuccessful.

   BUGS
    This function had several bugs prior to V39.

       First bug was that if the clipboard.device couldn't open, two calls
    to FreeSignal() were made with uninitialized values as parameters.
    The result of this was a corrupt signal mask in the Task field.

    Second bug was that OpenDevice() was called with an IO request that
    didn't have a valid MsgPort pointer in it.

    Third bug was that the two message ports allocated by the function
    (ClipboardHandle->cbh_CBport and ClipboardHandle->cbh_SatisfyPort)
    were not being initialized correctly and would cause a system crash
    if a message ever got to either of them.

   SEE ALSO
    InitIFFasClip(), CloseClipboard(), <libraries/iffparse.h>


iffparse.library/OpenIFF

   NAME
    OpenIFF -- prepare an IFFHandle to read or write a new IFF stream.
               (V36)

   SYNOPSIS
    error = OpenIFF(iff, rwMode);
    D0              A0   D0

    LONG OpenIFF(struct IFFHandle *, LONG);

   FUNCTION
    Initializes an IFFHandle structure for a new read or write. The
    direction of the I/O is given by the value of rwMode, which can be
    either IFFF_READ or IFFF_WRITE.

    As part of its initialization procedure, OpenIFF() calls the client-
    supplied stream hook vector. The IFFStreamCmd packet will contain
    the following:

        sc_Command:	IFFCMD_INIT
        sc_Buf:		(Not applicable)
        sc_NBytes:	(Not applicable)

    This operation is permitted to fail. DO NOT write to this structure.

   INPUTS
    iff - pointer to IFFHandle structure. Starting with V39, this may be
          NULL, in which case IFFERR_NOMEM is returned.
    rwMode - IFFF_READ or IFFF_WRITE

   RESULT
    error - contains an error code or 0 if successful

   SEE ALSO
    CloseIFF(), InitIFF(), <libraries/iffparse.h>


iffparse.library/ParentChunk

   NAME
    ParentChunk -- get the nesting context node for the given chunk. (V36)

   SYNOPSIS
    parent = ParentChunk(contextNode);
    D0                   A0

    struct ContextNode *ParentChunk(struct ContextNode *);

   FUNCTION
    Returns a context node for the chunk containing the chunk for the
    given context node. This function effectively moves down the context
    stack into previously pushed contexts. For example, to get a
    ContextNode pointer for the enclosing FORM chunk while reading a data
    chunk, use: ParentChunk(CurrentChunk(iff)) to find this pointer.
    The ContextNode structure contains information on the type of chunk
    and its size.

   INPUTS
    contextNode - pointer to a context node.

   RESULT
    parent - pointer to the enclosing context node or NULL if none.

   SEE ALSO
    CurrentChunk(), <libraries/iffparse.h>


iffparse.library/ParseIFF

   NAME
    ParseIFF -- parse an IFF file from an IFFHandle structure stream. (V36)

   SYNOPSIS
    error = ParseIFF(iff, control);
    D0               A0   D0

    LONG ParseIFF(struct IFFHandle *, LONG);

   FUNCTION
    This is the biggie.

    Traverses a file opened for read by pushing chunks onto the context
    stack and popping them off directed by the generic syntax of IFF
    files. As it pushes each new chunk, it searches the context stack
    for handlers to apply to chunks of that type. If it finds an entry
    handler it will invoke it just after entering the chunk. If it finds
    an exit handler it will invoke it just before leaving the chunk.
    Standard handlers include entry handlers for pre-declared
    property chunks and collection chunks and entry and exit handlers for
    for stop chunks - that is, chunks which will cause the ParseIFF()
    function to return control to the client. Client programs can also
    provide their own custom handlers.

    The control flag can have three values:

    IFFPARSE_SCAN:
        In this normal mode, ParseIFF() will only return control to
        the caller when either:
            1) an error is encountered,
            2) a stop chunk is encountered, or a user handler
               returns the special IFF_RETURN2CLIENT code, or
            3) the end of the logical file is reached, in which
               case IFFERR_EOF is returned.

        ParseIFF() will continue pushing and popping chunks until one
        of these conditions occurs. If ParseIFF() is called again
        after returning, it will continue to parse the file where it
        left off.

    IFFPARSE_STEP and _RAWSTEP:
        In these two modes, ParseIFF() will return control to the
        caller after every step in the parse, specifically, after
        each push of a context node and just before each pop. If
        returning just before a pop, ParseIFF() will return
        IFFERR_EOC, which is not an error, per se, but is just an
        indication that the most recent context is ending. In STEP
        mode, ParseIFF() will invoke the handlers for chunks, if
        any, before returning. In RAWSTEP mode, ParseIFF() will not
        invoke any handlers and will return right away. In both
        cases the function can be called multiple times to step
        through the parsing of the IFF file.

   INPUTS
    iff - pointer to IFFHandle structure.
    control	- control code (IFFPARSE_SCAN, _STEP or _RAWSTEP).

   RESULT
    error - 0 or IFFERR_#? value or return value from user handler.

   SEE ALSO
    PushChunk(), PopChunk(), EntryHandler(), ExitHandler(),
    PropChunk(), CollectionChunk(), StopChunk(), StopOnExit(),
    <libraries/iffparse.h>


iffparse.library/PopChunk

   NAME
    PopChunk -- pop top context node off context stack. (V36)

   SYNOPSIS
    error = PopChunk(iff);
    D0               A0

    LONG PopChunk(struct IFFHandle *);

   FUNCTION
    Pops top context chunk and frees all associated local context items.
    The function is normally called only for writing files and signals
    the end of a chunk.

   INPUTS
    iff - pointer to IFFHandle structure.

   RESULT
    error - 0 if successful or an IFFERR_#? error code if unsuccessful.

   SEE ALSO
    PushChunk(), <libraries/iffparse.h>


iffparse.library/PropChunk

   NAME
    PropChunk -- specify a property chunk to store. (V36)

   SYNOPSIS
    error = PropChunk(iff, type, id);
    D0                A0   D0    D1

    LONG PropChunk(struct IFFHandle *, LONG, LONG);

   FUNCTION
    Installs an entry handler for chunks with the given type and ID so
    that the contents of those chunks will be stored as they are
    encountered. The storage of these chunks follows the property chunk
    scoping rules for IFF files so that at any given point, a stored
    property chunk returned by FindProp() will be the valid property for
    the current context.

   INPUTS
    iff - pointer to IFFHandle structure (does not need to be open).
    type - type code for the chunk to declare (ex. "ILBM").
    id - identifier for the chunk to declare (ex. "CMAP").

   RESULT
    error - 0 if successful or an IFFERR_#? error code if unsuccessful.

   SEE ALSO
    PropChunks(), FindProp(), CollectionChunk(), <libraries/iffparse.h>


iffparse.library/PropChunks

   NAME
    PropChunks -- declare many property chunks at once. (V36)

   SYNOPSIS
    error = PropChunks(iff, propArray, numPairs);
    D0                 A0   A1         D0

    LONG PropChunks(struct IFFHandle *, LONG *, LONG);

   FUNCTION
    Declares multiple property chunks from a list. The propArray argument
    if a pointer to an array of longwords arranged in pairs, and has the
    following format:

        TYPE1, ID1, TYPE2, ID2, ..., TYPEn, IDn

    The argument numPairs is the number of pairs. PropChunks() just calls
    PropChunk() numPairs times.

   INPUTS
    iff - pointer to IFFHandle structure.
    propArray - pointer to array of longword chunk types and identifiers.
    numPairs - number of pairs in the array.

   RESULT
    error - 0 if successful or an IFFERR_#? error code if unsuccessful.

   SEE ALSO
    PropChunk(), <libraries/iffparse.h>


iffparse.library/PushChunk

   NAME
    PushChunk -- push a new context node on the context stack. (V36)

   SYNOPSIS
    error = PushChunk(iff, type, id, size);
    D0                A0   D0    D1  D2

    LONG PushChunk(struct IFFHandle *, LONG, LONG, LONG);

   FUNCTION
    Pushes a new context node on the context stack by reading it from the
    stream if this is a read file, or by creating it from the passed
    parameters if this is a write file. Normally this function is only
    called in write mode, where the type and id codes specify the new
    chunk to create. If this is a leaf chunk, i.e. a local chunk inside
    a FORM or PROP chunk, then the type argument is ignored. If the size
    is specified then the chunk writing functions will enforce this size.
    If the size is given as IFFSIZE_UNKNOWN, the chunk will expand to
    accommodate whatever is written into it.

   INPUTS
    iff - pointer to IFFHandle structure.
    type - chunk type specifier (ex. ILBM) (ignored for read mode or
           leaf chunks).
    id - chunk id specifier (ex. CMAP) (ignored for read mode).
    size - size of the chunk to create or IFFSIZE_UNKNOWN (ignored for
           read mode).

   RESULT
    error - 0 if successful or an IFFERR_#? error code if not unsuccessful.

   SEE ALSO
    PopChunk(), WriteChunkRecords(), WriteChunkBytes(),
    <libraries/iffparse.h>


iffparse.library/ReadChunkBytes

   NAME
    ReadChunkBytes -- read bytes from the current chunk into a buffer.
                      (V36)

   SYNOPSIS
    actual = ReadChunkBytes(iff, buf, numBytes);
    D0                      A0   A1   D0

    LONG ReadChunkBytes(struct IFFHandle *, APTR buf, LONG);

   FUNCTION
    Reads the IFFHandle stream into the buffer for the specified number
    of bytes. Reads are limited to the size of the current chunk and
    attempts to read past the end of the chunk will truncate. This
    function returns positive number of bytes read or a negative error
    code.

   INPUTS
    iff - pointer to IFFHandle structure.
    buf - pointer to buffer area to receive data.
    numBytes - number of bytes to read.

   RESULT
    actual - (positive) number of bytes read if successful or a
         (negative) IFFERR_#? error code if unsuccessful.

   SEE ALSO
    ReadChunkRecords(), ParseIFF(), WriteChunkBytes(),
    <libraries/iffparse.h>


iffparse.library/ReadChunkRecords

   NAME
    ReadChunkRecords -- read record elements from the current chunk into
                a buffer. (V36)

   SYNOPSIS
    actual = ReadChunkRecords(iff, buf, bytesPerRecord, numRecords);
    D0                        A0   A1   D0              D1

    LONG ReadChunkRecords(struct IFFHandle *, APTR, LONG, LONG);

   FUNCTION
    Reads records from the current chunk into buffer. Truncates attempts
    to read past end of chunk (only whole records are read; remaining
    bytes that are not of a whole record size are left unread and
    available for ReadChunkBytes()).

   INPUTS
    iff - pointer to IFFHandle structure.
    buf - pointer to buffer area to receive data.
    bytesPerRecord	- size of data records to read.
    numRecords - number of data records to read.

   RESULT
    actual - (positive) number of whole records read if successful or a
         (negative) IFFERR_#? error code if unsuccessful.

   SEE ALSO
    ReadChunkBytes(), ParseIFF(), WriteChunkRecords(),
    <libraries/iffparse.h>


iffparse.library/SetLocalItemPurge

   NAME
    SetLocalItemPurge -- set purge vector for a local context item. (V36)

   SYNOPSIS
    SetLocalItemPurge(localItem, purgeHook);
                      A0         A1

    VOID SetLocalItemPurge(struct LocalContextItem *, struct Hook *);

   FUNCTION
    Sets a local context item to use a client-supplied cleanup (purge)
    vector for disposal when its context is popped. The purge vector
    will be called when the ContextNode containing this local item is
    popped off the context stack and is about to be deleted itself. If
    the purge vector has not been set, the parser will use FreeLocalItem()
    to delete the item, but if this function is used to set the purge
    vector, the supplied vector will be called with the following
    arguments:

        A0:	pointer to purgeHook.
        A2:	pointer to LocalContextItem to be freed.
        A1:	pointer to a LONG containing the value
            IFFCMD_PURGELCI.

    The user purge vector is then responsible for calling FreeLocalItem()
    as part of its own cleanup. Although the purge vector can return a
    value, it will be ignored -- purge vectors must always work (best to
    return 0, though).

   INPUTS
    localItem - pointer to a local context item.
    purgeHook - pointer to a Hook structure.

   SEE ALSO
    AllocLocalItem(), FreeLocalItem(), <utility/hooks.h>
    <libraries/iffparse.h>


iffparse.library/StopChunk

   NAME
    StopChunk -- declare a chunk which should cause ParseIFF to return.
                 (V36)

   SYNOPSIS
    error = StopChunk(iff, type, id);
    D0                A0   D0    D1

    LONG StopChunk(struct IFFHandle *, LONG, LONG);		 type;

   FUNCTION
    Installs an entry handler for the specified chunk which will cause
    the ParseIFF() function to return control to the caller when this
    chunk is encountered. This is only of value when ParseIFF() is
    called with the IFFPARSE_SCAN control code.

   INPUTS
    iff - pointer to IFFHandle structure (need not be open).
    type - type code for chunk to declare (ex. "ILBM").
    id - identifier for chunk to declare (ex. "BODY").

   RESULT
    error - 0 if successful or an IFFERR_#? error code if unsuccessful.

   SEE ALSO
    StopChunks(), ParseIFF(), <libraries/iffparse.h>


iffparse.library/StopChunks

   NAME
    StopChunks -- declare many stop chunks at once. (V36)

   SYNOPSIS
    error = StopChunks(iff, propArray, numPairs);
    D0                 A0   A1         D0

    LONG StopChunks(struct IFFHandle *, LONG *, LONG);

   FUNCTION
    (is to StopChunk() as PropChunks() is to PropChunk().)

   INPUTS
    iff - pointer to IFFHandle structure.
    propArray - pointer to array of longword chunk types and identifiers.
    numPairs - number of pairs in the array.

   RESULT
    error - 0 if successful or an IFFERR_#? error code if unsuccessful.

   SEE ALSO
    StopChunk(), <libraries/iffparse.h>


iffparse.library/StopOnExit

   NAME
    StopOnExit -- declare a stop condition for exiting a chunk. (V36)

   SYNOPSIS
    error = StopOnExit(iff, type, id);
    D0                 A0   D0    D1

    LONG StopOnExit(struct IFFHandle *, LONG, LONG);

   FUNCTION
    Installs an exit handler for the specified chunk which will cause the
    ParseIFF() function to return control to the caller when this chunk
    is exhausted. ParseIFF() will return IFFERR_EOC when the declared
    chunk is about to be popped. This is only of value when ParseIFF()
    is called with the IFFPARSE_SCAN control code.

   INPUTS
    iff - pointer to IFFHandle structure (need not be open).
    type - type code for chunk to declare (ex. "ILBM").
    id - identifier for chunk to declare (ex. "BODY").

   RESULT
    error - 0 if successful or an IFFERR_#? error code if unsuccessful.

   SEE ALSO
    ParseIFF(), <libraries/iffparse.h>


iffparse.library/StoreItemInContext

   NAME
    StoreItemInContext -- store local context item in given context node.
                          (V36)

   SYNOPSIS
    StoreItemInContext(iff, localItem, contextNode);
                       A0   A1         A2

    VOID StoreItemInContext(struct IFFHandle *, struct LocalContextItem *,
                               struct ContextNode *);

   FUNCTION
    Adds the LocalContextItem to the list of items for the given context
    node. If an LCI with the same Type, ID, and Ident is already
    present in the ContextNode, it will be purged and replaced with the
    new one. This is a raw form of StoreLocalItem().

   INPUTS
    iff - pointer to IFFHandle structure for this context.
    localItem - pointer to a LocalContextItem to be stored.
    contextNode - pointer to context node in which to store item.

   SEE ALSO
    StoreLocalItem(), <libraries/iffparse.h>


iffparse.library/StoreLocalItem

   NAME
    StoreLocalItem -- insert a local context item into the context stack.
                      (V36)

   SYNOPSIS
    error = StoreLocalItem(iff, localItem, position);
    D0                     A0   A1         D0

    LONG StoreLocalItem(struct IFFHandle *, struct LocalContextItem	*,
                        LONG);

   FUNCTION
    Adds the local context item to the list of items for one of the
    context nodes on the context stack and purges any other item in the
    same context with the same ident, type and id. The position argument
    determines where in the stack to add the item:

    IFFSLI_ROOT:
        Add item to list at root (default) stack position.
    IFFSLI_TOP:
        Add item to the top (current) context node.
    IFFSLI_PROP:
        Add element in top property context. Top property context is
        either the top FORM chunk, or the top LIST chunk, whichever
        is closer to the top of the stack.

    Items added to the root context, or added to the top context before
    the IFFHandle has been opened or after it has been closed, are put in
    the default context. That is, they will be the local items found
    only after all other context nodes have been searched. Items in the
    default context are also immune to being purged until the IFFHandle
    structure itself is deleted with FreeIFF(). This means that handlers
    installed in the root context will still be there after an IFFHandle
    structure has been opened and closed. (Note that this implies that
    items stored in a higher context will be deleted when that context
    ends.)

   INPUTS
    iff - pointer to IFFHandle structure.
    localItem - pointer to LocalContextItem struct to insert.
    position - where to store the item (IFFSLI_ROOT, _TOP or _PROP).

   RESULT
    error - 0 if successful or an IFFERR_#? error code if unsuccessful.

   SEE ALSO
    FindLocalItem(), StoreItemInContext(), EntryHandler(), ExitHandler(),
    <libraries/iffparse.h>


iffparse.library/WriteChunkBytes

   NAME
    WriteChunkBytes -- write data from a buffer into the current chunk.
                       (V36)

   SYNOPSIS
    error = WriteChunkBytes(iff, buf, numBytes);
    D0                      A0   A1   D0

    LONG WriteChunkBytes(struct IFFHandle *, APTR, LONG);

   FUNCTION
    Writes "numBytes" bytes from the specified buffer into the current
    chunk. If the current chunk was pushed with IFFSIZE_UNKNOWN, the size
    of the chunk gets increased by the size of the buffer written. If
    the size was specified for this chunk, attempts to write past the end
    of the chunk will be truncated.

   INPUTS
    iff - pointer to IFFHandle structure.
    buf - pointer to buffer area with bytes to be written.
    numBytes - number of bytes to write.

   RESULT
    error - (positive) number of bytes written if successful or a
        (negative) IFFERR_#? error code if unsuccessful.

   SEE ALSO
    PushChunk(), PopChunk(), WriteChunkRecords(), <libraries/iffparse.h>


iffparse.library/WriteChunkRecords

   NAME
    WriteChunkRecords -- write records from a buffer to the current
                 chunk. (V36)

   SYNOPSIS
    error = WriteChunkRecords(iff, buf, recsize, numrec);
    D0                        A0   A1   D0       D1

    LONG WriteChunkRecords(struct IFFHandle *, APTR, LONG, LONG);

   FUNCTION
    Writes record elements from the buffer into the top chunk. This
    function operates much like ReadChunkBytes().

   INPUTS
    iff - pointer to IFFHandle structure.
    buf - pointer to buffer area containing data.
    recsize	- size of data records to write.
    numrec - number of data records to write.

   RESULT
    error - (positive) number of whole records written if successful
        or a (negative) IFFERR_#? error code if unsuccessful.

   SEE ALSO
    WriteChunkBytes(), <libraries/iffparse.h>


input.doc

     IND_ADDHANDLER
     IND_REMHANDLER
     IND_SETMPORT
     IND_SETMTRIG
     IND_SETMTYPE
     IND_SETPERIOD
     IND_SETTHRESH
     IND_WRITEEVENT
     PeekQualifier()


integer_gc.doc

     --datasheet--
     INTEGER_GetClass()


integer_gc/--datasheet--

     NAME
        integer_gc -- A numeric entry gadget with arrows.

     SUPERCLASS
        gadgetclass

    REQUIRES
        bevel.image

     DESCRIPTION
        This gadget is a special form of a strggclass gadget for entering
        positive or negative long integers.  The user can type in the number
        or use the arrows to adjust the number up or down.

        Advantages that this class provides:

         > Supports window relativity.

         > Optionally creates arrows for adjusting the value.

         > Definable minimum and maximum values as well as maximum number
           of characters.

         > Supports OS 3.0 BOOPSI Gadget HelpTest.

     METHODS
        OM_NEW -- Create the integer gadget.  Passed to superclass.

        OM_SET -- Set object attributes.  Passed to superclass first.

        OM_DISPOSE -- Cancels the integer menu before being passed onto
            superclass.

        OM_UPDATE -- Set object notification attributes.  Passed to superclass
            first.

        GM_RENDER -- Renders the gadget imagry.  Overrides the superclass.

        GM_GOACTIVE -- Handles activation, pops up the integer menu.  Overrides
            the superclass.

        GM_HANDLEINPUT -- Handles input events once active.  Overrides the
            superclass.

        GM_GOINACTIVE -- Closes the integer menu.  Overrides the superclass.

        All other methods are passed to the superclass.

     ATTRIBUTES
        GA_Disabled (BOOL)
            Set to TRUE to disable gadget, FALSE otherwise

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        GA_TextAttr (struct TextAttr *)
            Font to use for the gadget text.

            Defaults to the screen's font.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        INTEGER_Number (LONG)
            The value for the integer gadget.  The class will adjust this
            number to fit into the range you define.  The current value for
            INTEGER_Number will be returned in IntuiMessage.Code on
            IDCMP_GADGETUP as a WORD.  Note that since the gadget handles
            values of size LONG, the value returned in IntuiMessage.Code
            will only be valid if the ranges you are allowing fit into a
            WORD value.  Otherwise you will have to use GetAttr().

            Defaults to 0.

            Applicability is (OM_NEW, OM_SET, OM_GET, OM_NOTIFY)

        INTEGER_MaxChars (WORD)
            Maximum number of characters you are allowing the number to be.
            This is including an optional negative sign (-).

            Defaults to 10.

            Applicability is (OM_NEW, OM_SET, OM_GET, OM_NOTIFY)

        INTEGER_Minimum (LONG)
            Minimum value the number can have.

            Applicability is (OM_NEW, OM_SET, OM_GET, OM_NOTIFY)

        INTEGER_Maximum (LONG)
            Maximum value the number can have.

            Applicability is (OM_NEW, OM_SET, OM_GET, OM_NOTIFY)

        INTEGER_Arrows (BOOL)
            Should arrows be displayed for adjusting the number?  The class
            is smart enough to not render arrows if the gadget becomes too
            small.

            Defaults to TRUE.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        INTEGER_MinVisible (UWORD)
            If set, this tag specifies the minimum number of numeric
            characters which should be visible at the gadgets minimum
            domain size. This tag effects GM_DOMAIN's result to tweak
            the display in a pleasing way.

            Defaults to 0.

            Applicability is (OM_NEW, OM_SET)

        All strggclass tags can be used with OM_NEW, OM_SET and OM_GET
        except for STRINGA_LongVal and STRINGA_MaxChars.  Use INTEGER_Number
        and INTEGER_MaxChars instead.


integer_gc/INTEGER_GetClass

    NAME
        INTEGER_GetClass -- Gets the pointer to the integer class.

    SYNOPSIS
        integer_class = INTEGER_GetClass();
        D0

        Class * INTEGER_GetClass(VOID);

    FUNCTION
        Obtains the pointer to the Integer gadget class for use with
        NewObject().  This function always returns a valid pointer so
        you do not need to check it.  The reason is that if the library
        opens fine, then the pointer returned is already setup.  (Of course
        this implies that if opening the library fails, you shouldn't be
        calling this.)

        Note that this function does not create the class, that is done
        when the class library is opened.

    INPUTS
        Nothing.

    RESULT
        integer_class - Pointer to the Integer gadget class.

    SEE ALSO


intuition.doc

     ActivateGadget()
     ActivateWindow()
     AddClass()
     AddGadget()
     AddGList()
     AllocRemember()
     AllocScreenBuffer()
     AutoRequest()
     BeginRefresh()
     BuildEasyRequestArgs()
     BuildSysRequest()
     ChangeScreenBuffer()
     ChangeWindowBox()
     ClearDMRequest()
     ClearMenuStrip()
     ClearPointer()
     CloseScreen()
     CloseWindow()
     CloseWorkBench()
     CurrentTime()
     DisplayAlert()
     DisplayBeep()
     DisposeObject()
     DoGadgetMethodA()
     DoubleClick()
     DrawBorder()
     DrawImage()
     DrawImageState()
     EasyRequestArgs()
     EndRefresh()
     EndRequest()
     EraseImage()
     FreeClass()
     FreeRemember()
     FreeScreenBuffer()
     FreeScreenDrawInfo()
     FreeSysRequest()
     GadgetMouse()
     GetAttr()
     GetDefaultPubScreen()
     GetDefPrefs()
     GetPrefs()
     GetScreenData()
     GetScreenDrawInfo()
     HelpControl()
     InitRequester()
     IntuiTextLength()
     ItemAddress()
     LendMenus()
     LockIBase()
     LockPubScreen()
     LockPubScreenList()
     MakeClass()
     MakeScreen()
     ModifyIDCMP()
     ModifyProp()
     MoveScreen()
     MoveWindow()
     MoveWindowInFrontOf()
     NewModifyProp()
     NewObject()
     NextObject()
     NextPubScreen()
     ObtainGIRPort()
     OffGadget()
     OffMenu()
     OnGadget()
     OnMenu()
     OpenScreen()
     OpenScreenTagList()
     OpenWindow()
     OpenWindowTagList()
     OpenWorkBench()
     PointInImage()
     PrintIText()
     PubScreenStatus()
     QueryOverscan()
     RefreshGadgets()
     RefreshGList()
     RefreshWindowFrame()
     ReleaseGIRPort()
     RemakeDisplay()
     RemoveClass()
     RemoveGadget()
     RemoveGList()
     ReportMouse()
     Request()
     ResetMenuStrip()
     RethinkDisplay()
     ScreenDepth()
     ScreenPosition()
     ScreenToBack()
     ScreenToFront()
     ScrollWindowRaster()
     SetAttrsA()
     SetDefaultPubScreen()
     SetDMRequest()
     SetEditHook()
     SetGadgetAttrsA()
     SetMenuStrip()
     SetMouseQueue()
     SetPointer()
     SetPrefs()
     SetPubScreenModes()
     SetWindowPointerA()
     SetWindowTitles()
     ShowTitle()
     SizeWindow()
     SysReqHandler()
     TimedDisplayAlert()
     UnlockIBase()
     UnlockPubScreen()
     UnlockPubScreenList()
     ViewAddress()
     ViewPortAddress()
     WBenchToBack()
     WBenchToFront()
     WindowLimits()
     WindowToBack()
     WindowToFront()
     ZipWindow()


intuition.library/ActivateWindow

    NAME
    ActivateWindow -- Activate an Intuition window.

    SYNOPSIS
    ActivateWindow( Window )
                    A0

    VOID ActivateWindow( struct Window * );

    FUNCTION
    Activates an Intuition window.

    Note that this call may have its action deferred: you cannot assume
    that when this call is made the selected window has become active.
    This action will be postponed while the user plays with gadgets and
    menus, or sizes and drags windows.  You may detect when the window
    actually has become active by the IDCMP_ACTIVEWINDOW IDCMP message.

    This call is intended to provide flexibility but not to confuse the
    user.  Please call this function synchronously with some action
    by the user.

    INPUTS
    Window = a pointer to a Window structure

    RESULT
    None.

    BUGS
    Some versions of the documentation claimed that this function
    had a meaningful return value under V36 and higher.  That is
    not true.

    Calling this function in a tight loop can blow out Intuition's
    deferred action queue.

    SEE ALSO
    OpenWindow(), and the WFLG_ACTIVATE window flag


intuition.library/AllocScreenBuffer

    NAME
    AllocScreenBuffer -- Get a ScreenBuffer for double-buffering. (V39)

    SYNOPSIS
    sbuffer = AllocScreenBuffer( Screen, BitMap, flags )
    D0                           A0      A1      D0

    struct ScreenBuffer *AllocScreenBuffer( struct Screen *,
        struct BitMap *, ULONG );

    FUNCTION
    Allocates a ScreenBuffer structure and usually a BitMap.  This
    structure can be used for double (or multiple) buffering in
    Intuition screens.  You may use this call to obtain a ScreenBuffer
    structure for the screen's initial BitMap, or for other BitMaps
    you intend to swap in.

    AllocScreenBuffer() also allocates a graphics.library DBufInfo
    structure.  The ScreenBuffer structure this call returns contains
    a pointer to that DBufInfo structure, which is free for your use.
    See graphics.library/AllocDBufInfo() for full details on using
    this structure to achieve notification of when it is safe to
    render into an old buffer and when it is right to switch again.

    INPUTS
    Screen = pointer to the screen to double-buffer
    BitMap = For CUSTOMBITMAP screens, you may pre-allocate
        a BitMap matching the screen's BitMap's properties, and
        pass that in, to get a ScreenBuffer referring to that
        BitMap.  Set this parameter to NULL if you'd prefer
        that Intuition allocate the alternate buffer.  This parameter
        must be NULL for non-CUSTOMBITMAP screens.
    Flags = Set a combination of these flags:
        For non-CUSTOMBITMAP screens, set SB_SCREEN_BITMAP in order to
        get a ScreenBuffer referring to the screen's actual BitMap.
        (For CUSTOMBITMAP screens, just set the BitMap parameter
        to the BitMap you passed to OpenScreen()).
        Set SB_COPY_BITMAP if you would like the screen's BitMap
        copied into this ScreenBuffer's BitMap.  This is required
        to get any menu-bar or gadget imagery into each
        ScreenBuffer's BitMap.  If the screen has no Intuition
        rendering, you may omit this flag.  Also, when allocating
        a ScreenBuffer for the screen's initial BitMap, this flag
        should not be set.

    RESULT
    Pointer to a valid ScreenBuffer structure, or NULL if failure.
    You may render into the resulting BitMap as appropriate.
    You may use the sb_DBufInfo field to access graphics.library
    ViewPort-buffering features such as learning when it is safe
    to reuse the previous BitMap.  If not, you risk writing into
    the on-screen BitMap, which can damage menu or gadget rendering!

    NOTES

    The role of SB_SCREEN_BITMAP is to wrap a ScreenBuffer around
    the actual current BitMap used by the non-CUSTOMBITMAP screen.
    The words actual or current are used instead of initial, since
    an application could do some double-buffering, leave the
    non-initial buffer installed into the screen, free up the
    others, then re-allocate ScreenBuffer structures to do more
    double-buffering.  In that case, the actual screen BitMap is
    not necessarily the initial one.

    The role of SB_COPY_BITMAP is to say "please put whatever
    imagery is currently on-screen into this new BitMap too".
    That's how the screen titlebar and other imagery get copied
    over into each buffer.

    BUGS

    SEE ALSO
    FreeScreenBuffer(), ChangeScreenBuffer(),
    graphics.library/AllocDBufInfo(), graphics.library/ChangeVPBitMap()


intuition.library/AutoRequest

    NAME
    AutoRequest -- Automatically build and get response from a requester.

    SYNOPSIS
    Response = AutoRequest( Window, BodyText, PosText, NegText,
    D0                      A0      A1        A2       A3
            PosFlags, NegFlags, Width, Height )
            D0        D1        D2     D3

    BOOL AutoRequest( struct Window *, struct IntuiText *,
        struct IntuiText *, struct IntuiText *,
        ULONG, ULONG, WORD, WORD );

    FUNCTION
    This procedure automatically builds a requester for you and then
    waits for a response from the user, or for the system to satisfy your
    request.  If the response is positive, this procedure returns TRUE.
    If the response is negative, this procedure returns FALSE.

    An IDCMPFlag specification is created by bitwise "or'ing" your
    PosFlags, NegFlags, and the IDCMP classes IDCMP_GADGETUP and
    IDCMP_RAWKEY.  You may specify zero flags for either the PosFlags
    or NegFlags arguments.

    The IntuiText arguments, and the width and height values, are
    passed directly to the BuildSysRequest() procedure along with
    your window pointer and the IDCMP flags.  Please refer to
    BuildSysRequest() for a description of the IntuiText that you are
    expected to supply when calling this routine.  It's an important
    but long-winded description that need not be duplicated here.

    If the BuildSysRequest() procedure does not return a pointer
    to a window, it will return TRUE or FALSE (not valid structure
    pointers) instead, and these BOOL values will be returned to
    you immediately.

    On the other hand, if a valid window pointer is returned, that
    window will have had its IDCMP ports and flags initialized according
    to your specifications.  AutoRequest() then waits for IDCMP messages
    on the UserPort, which satisfies one of four requirements:
    -   either the message is of a class that matches
        one of your PosFlags arguments (if you've supplied
        any), in which case this routine returns TRUE.  Or
    -   the message class matches one of your NegFlags
        arguments (if you've supplied any), in which case
        this routine returns FALSE.  Or
    -   the IDCMP message is of class IDCMP_GADGETUP, which means that
        one of the two gadgets, as provided with the PosText and NegText
        arguments, was selected by the user.  If the TRUE gadget
        was selected, TRUE is returned.  If the FALSE gadget was
        selected, FALSE is returned.
    -   Lastly, two IDCMP_RAWKEY messages may satisfy the request: those
        for the V and B keys with the left Amiga key depressed.
        These keys, satisfy the gadgets on the left or right side of
        the requester--TRUE or FALSE--, respectively.

        NOTE: For V36, these two keys left-Amiga-B and V are processed
        through the default keymap.

    When the dust has settled, this routine calls FreeSysRequest() if
    necessary to clean up the requester and any other allocated memory.

    NOTE: For V36, this function now switches the processor stack
    to ensure sufficient stack space for the function to succeed.

    INPUTS
    Window = pointer to a Window structure.  See BuildSysRequest()
        for a full discussion.
    BodyText = pointer to an IntuiText structure
    PosText = pointer to an IntuiText structure, may by NULL.
    NegText = pointer to an IntuiText structure, MUST be valid!
    PosFlags = flags for the IDCMP
    NegFlags = flags for the IDCMP
    Width, Height = the sizes to be used for the rendering of the requester

    NOTE for V36: The width and height parameters are ignored, as
    are several other specifications in the IntuiText, to make
    AutoRequest() requesters retroactively conform to the new look
    designed for EasyRequest().

    RESULT
    The return value is either TRUE or FALSE.  See the text above for a
    complete description of the chain of events that might lead to either
    of these values being returned.

    NOTES
    When DOS brings up AutoRequests() on your process (eg.
    "Please insert volume XXX in any drive", they normally come
    up on the Workbench screen.  If you set your Process pr_WindowPtr
    field to point to one of your windows, then DOS will bring its
    requesters up on the same screen as that window.  A pr_WindowPtr
    of -1 prevents requesters from coming up at all.
    (Some FileSystem requesters cannot be redirected or supressed).

    BUGS
    The requester no longer devolves into a call to DisplayAlert()
    if there is not enough memory for the requester.

    SEE ALSO
    EasyRequestArgs(), BuildSysRequest(), SysReqHandler()


intuition.library/BeginRefresh

    NAME
    BeginRefresh -- Sets up a window for optimized refreshing.

    SYNOPSIS
    BeginRefresh( Window )
              A0

    VOID BeginRefresh( struct Window * );

    FUNCTION
    This routine sets up your window for optimized refreshing.

    Its role is to provide Intuition integrated access to the Layers
    library function BeginUpdate().  Its additional contribution is
    to be sure that locking protocols for layers are followed, by
    locking both layers of a WFLG_GIMMEZEROZERO window only after the
    parent Layer_Info has been locked.  Also, the WFLG_WINDOWREFRESH
    flag is set in your window, for your information.

    The purpose of BeginUpdate(), and hence BeginRefresh(), is to
    restrict rendering in a window (layer) to the region that needs
    refreshing after an operation such as window sizing or uncovering.
    This restriction to the "damage region" persists until you call
    EndRefresh().

    For instance, if you have a WFLG_SIMPLE_REFRESH window which is
    partially concealed and the user brings it to the front, you can
    receive an IDCMP_REFRESHWINDOW message asking you to refresh your
    display.  If you call BeginRefresh() before doing any of the
    rendering, then the layer that underlies your window will be arranged
    so that the only rendering that will actually take place will be that
    which goes to the newly-revealed areas.  This is very performance-
    efficient, and visually attractive.

    After you have performed your refresh of the display, you should call
    EndRefresh() to reset the state of the layer and the window.  Then you
    may proceed with rendering to the entire window as usual.

    You learn that your window needs refreshing by receiving either a
    message of class IDCMP_REFRESHWINDOW through the IDCMP, or an input
    event of class IECLASS_REFRESHWINDOW through the Console device.
    Whenever you are told that your window needs refreshing, you should
    call BeginRefresh() and EndRefresh() to clear the refresh-needed
    state, even if you don't plan on doing any rendering.  You may relieve
    yourself of even this burden by setting the WFLG_NOCAREREFRESH flag
    when opening your window.

    NOTES
    WARNING: You should only perform simple graphics refreshing
    operations between BeginRefresh() and EndRefresh().  These include
    any graphics.library drawing functions or the simple Intuition
    rendering functions (DrawImage(), PrintIText(), DrawBorder(), and
    so on).  In particular, do not call RefreshGadgets(), RefreshGList(),
    RefreshWindowFrame(), etc., since any of the complex Intuition
    functions run the risk of creating a deadlock.  Also avoid any
    other high-level calls in Intuition or ones that might invoke
    Intuition.  This means no calling SetPointer(), no calling
    LockIBase(), no dos.library functions (since an EasyRequest()
    might result), etc.  Keep it simple.

    By the time the application receives its IDCMP_REFRESHWINDWOW
    message, Intuition has already repaired any damaged regions
    of the window border or the gadgets in the window, so attempts
    to redraw gadgets or borders are as unnecessary as they are
    dangerous.

    ANOTHER WARNING: The concept of multiple refresh passes using
    EndRefresh( w, FALSE ) is not completely sound without further
    protection.  The reason is that between two sessions, more
    damage can occur to your window.  Your final EndRefresh( w, TRUE )
    will dispose of all damage, including the new, and your
    initial refreshing pass will never get the chance to refresh
    the new damage.

    To avoid this, you must protect your session using LockLayerInfo()
    which will prevent Intuition from performing window operations
    or anything else which might cause further damage from occurring.
    Again, while holding the LayerInfo lock make no Intuition
    function calls dealing with gadgets; just render.

    You can, however, call InstallClipRegion() for the different
    refresh passes, if you have two clip regions.

    SIMILAR WARNING: Your program and Intuition "share" your window
    layer's DamageList.  BeginRefresh() helps arbitrate this
    sharing, but the lower-level function layers.library/BeginUpdate()
    does not.  It isn't really supported to use BeginUpdate() on
    a window's layer, but if you do--for whatever reason--it is
    critical that you first acquire the LayerInfo lock as in
    the above example: even if you only have one pass of refresh
    rendering to do.  Otherwise, the refreshing of your window's
    borders and gadgets can be incomplete, and the problem might
    occur only under certain conditions of task priority and
    system load.

    EXAMPLE
    Code fragment for "two pass" window refreshing, in response
    to an IDCMP_REFRESHWINDOW message:
    switch ( imsg->Class )
    {
    ...
    case IDCMP_REFRESHWINDOW:
        window = imsg->IDCMPWindow;

        /* this lock only needed for "two-pass" refreshing */
        LockLayerInfo( &window->WScreen->LayerInfo );

        /* refresh pass for region 1 */
        origclip = InstallClipRegion( window->WLayer, region1 );
        BeginRefresh( window );
        myRefreshRegion1( window );
        EndRefresh( window, FALSE );

        /* refresh pass for region 2 */
        InstallClipRegion( window->WLayer, region2 );
        BeginRefresh( window );
        myRefreshRegion2( window );
        EndRefresh( window, TRUE );		/* and dispose damage list */

        /* restore and unlock */
        InstallClipRegion( window->WLayer, origclip );
        UnlockLayerInfo( &window->WScreen->LayerInfo );
        break;
    ...
    }

    INPUTS
    Window = pointer to the window structure which needs refreshing

    RESULT
    None

    BUGS
    This function should check the return code of
    layers.library/BeginUpdate(), and abort if that function fails.

    SEE ALSO
       EndRefresh(), layers.library/BeginUpdate(), OpenWindow()
    layer.library/InstallClipRegion(), layers.library/LockLayerInfo()
    The "Windows" chapter of the Intuition Reference Manual


intuition.library/BuildEasyRequestArgs

    NAME
    BuildEasyRequestArgs -- Simple creation of system request. (V36)
    BuildEasyRequest -- Varargs stub for BuildEasyRequestArgs(). (V36)

    SYNOPSIS
    ReqWindow = BuildEasyRequestArgs( RefWindow, easyStruct, IDCMP, Args )
    D0                                A0         A1          D0     A3

    struct Window *BuildEasyRequestArgs( struct Window *,
        struct EasyStruct *, ULONG, APTR );

    ReqWindow = BuildEasyRequest( RefWindow, easyStruct, IDCMP, Arg1, ... )

    struct Window *BuildEasyRequest( struct Window *,
        struct EasyStruct *, ULONG, APTR, ... );

    FUNCTION
    This function is to EasyRequest() as BuildSysRequest() is to
    AutoRequest(): it returns a pointer to the system requester
    window.  The input from that window can then be processed
    under application control.

    It is recommended that this processing be done with
    SysReqHandler(), so that future enhancement to the
    processing will be enjoyed.

    After you have determined that the requester is satisfied or
    cancelled, you must free this requester using FreeSysRequest().

    Please see the autodoc for EasyRequest().

    NOTE: This function switches the processor stack to ensure
    sufficient stack space for the function to complete.

    INPUTS
    Window = reference window for requester: determines the
        requester window title and screen.
    easyStruct = pointer to EasyStruct structure, as described
        in the EasyRequest() autodocs.
    IDCMP = (NOT A POINTER) provided application specific IDCMP
        flags for the system requester window.
    Args = see EasyRequestArgs()

    RESULT
    A pointer to the system request window opened.  In the event
    of problems, you may also be returned the value '0' which
    is to be interpreted as the "FALSE, Cancel" choice, or
    (if you have a second gadget defined) the value '1', which
    is to be taken to mean the equivalent of your corresponding
    left-most gadget.

    If there is a problem creating the window, a recoverable alert may
    be substituted for the requester, and the result, either 0 or 1,
    returned.

    BUGS
    Does not put up alternative alert.
    See also BUGS listed for EasyRequestArgs().

    SEE ALSO
    EasyRequestArgs(), FreeSysRequest(), SysReqHandler(),
    BuildSysRequest(), AutoRequest()


intuition.library/BuildSysRequest

    NAME
    BuildSysRequest -- Build and display a system requester.

    SYNOPSIS
    ReqWindow = BuildSysRequest( Window, BodyText, PosText, NegText,
    D0                           A0      A1        A2       A3
                   IDCMPFlags, Width, Height )
               D0          D1     D2

    struct Window *BuildSysRequest( struct Window *, struct IntuiText *,
        struct IntuiText *, struct IntuiText *, ULONG, WORD, WORD );

    FUNCTION
    This procedure builds a system requester based on the supplied
    information.  If all goes well and the requester is constructed,
    this procedure returns a pointer to the window in which the requester
    appears.  That window will have its IDCMP initialized to reflect the
    flags found in the IDCMPFlags argument.  You may then wait on those
    ports to detect the user's response to your requester, which response
    may include either selecting one of the gadgets or causing some other
    event to be noticed by Intuition (like IDCMP_DISKINSERTED, for
    instance).  After the requester is satisfied, you should call the
    FreeSysRequest() procedure to remove the requester and free up
    any allocated memory.

    See the autodoc for SysReqHandler() for more information on the
    how to handle the IntuiMessages this window will receive.

    The requester used by this function has the NOISYREQ flag bit set,
    which means that the set of IDCMPFlags that may be used here
    include IDCMP_RAWKEY, IDCMP_MOUSEBUTTONS, and others.

    In release previous to V36, if the requester could not be built,
    this function would try to call DisplayAlert() with the same
    information, with more or less favorable results.  In V36,
    the requesters themselves require less memory (SIMPLEREQ), but
    there is no alert attempt.

    The function may return TRUE (1) or FALSE if it cannot post
    the requester.  (V36 will always return FALSE, but be sure to
    test for TRUE in case somebody reinstates the fallback alert.)

    If the window argument you supply is equal to NULL, a new window will
    be created for you in the Workbench screen, or the default
    public screen, for V36.  If you want the requester
    created by this routine to be bound to a particular window (i.e.,
    to appear in the same screen as the window), you should
    not supply a window argument of NULL.

    New for V36: if you pass a NULL window pointer, the system requester
    will appear on the default public screen, which is not always
    the Workbench.

    The text arguments are used to construct the display.  Each is a
    pointer to an instance of the structure IntuiText.

    The BodyText argument should be used to describe the nature of
    the requester.  As usual with IntuiText data, you may link several
    lines of text together, and the text may be placed in various
    locations in the requester.  This IntuiText pointer will be stored
    in the ReqText variable of the new requester.

    The PosText argument describes the text that you want associated
    with the user choice of "Yes,  TRUE,  Retry,  Good."  If the requester
    is successfully opened, this text will be rendered in a gadget in
    the lower-left of the requester, which gadget will have the
    GadgetID field set to TRUE.  If the requester cannot be opened and
    the DisplayAlert() mechanism is used, this text will be rendered in
    the lower-left corner of the alert display with additional text
    specifying that the left mouse button will select this choice.  This
    pointer can be set to NULL, which specifies that there is no TRUE
    choice that can be made.

    The NegText argument describes the text that you want associated
    with the user choice of "No,  FALSE,  Cancel,  Bad."  If the requester
    is successfully opened, this text will be rendered in a gadget in
    the lower-right of the requester, which gadget will have the
    GadgetID field set to FALSE.  If the requester cannot be opened and
    the DisplayAlert() mechanism is used, this text will be rendered in
    the lower-right corner of the alert display with additional text
    specifying that the right mouse button will select this choice.  This
    pointer cannot be set to NULL.  There must always be a way for the
    user to cancel this requester.

    The Positive and Negative Gadgets created by this routine have
    the following features:
          - GTYP_BOOLGADGET
          - GACT_RELVERIFY
          - GTYP_REQGADGET
          - GACT_TOGGLESELECT

    When defining the text for your gadgets, you may find it convenient
    to use the special constants used by Intuition for the construction
    of the gadgets.  These include defines like AUTODRAWMODE, AUTOLEFTEDGE,
    AUTOTOPEDGE and AUTOFRONTPEN.  You can find these in your local
    intuition.h (or intuition.i) file.

    These hard-coded constants are not very resolution or font
    sensitive, but V36 will override them to provide more modern
    layout.

    New for V36, linked lists of IntuiText are not correctly supported
    for gadget labels.

    The width and height values describe the size of the requester.  All
    of your BodyText must fit within the width and height of your
    requester.  The gadgets will be created to conform to your sizes.

    VERY IMPORTANT NOTE:  for this release of this procedure, a new window
    is opened in the same screen as the one containing your window.
    Future alternatives may be provided as a function distinct from this
    one.

    NOTE: This function will pop the screen the requester and its
    window appears in to the front of all screens.  New for V36,
    if the user doesn't perform any other screen arrangement before
    finishing with the requester, a popped screen will be pushed
    back behind.

    INPUTS
    Window = pointer to a Window structure
    BodyText = pointer to an IntuiText structure
    PosText = pointer to an IntuiText structure
    NegText = pointer to an IntuiText structure
    IDCMPFlags = the IDCMP flags you want used for the initialization of the
           IDCMP of the window containing this requester
    Width, Height = the size required to render your requester

    NOTE for V36: the width and height you pass are ignored, as
    are some of the parameters of your IntuiText, so that Intuition
    can make the Requesters real nice for the new look.

    RESULT
    If the requester was successfully created, the value
    returned by this procedure is a pointer to the window in which the
    requester is rendered.  If the requester could not be created,
    this routine might have called DisplayAlert() before returning
    (it depends on the version) and will pass back TRUE if the user
    pressed the left mouse button and FALSE if the user pressed the
    right mouse button.   If the version of Intuition doesn't
    call DisplayAlert(), or if it does, and there's not enough
    memory for the alert, the value of FALSE is returned.

    BUGS
    This procedure currently opens a window in the Screen which
    contains the window which is passed as a parameter, or the
    default public screen, if that parameter is NULL.  Although
    not as originally envisioned, this will probably always be the
    behavior of this function.

    DisplayAlert() is not called in version V36.

    It's almost impossible to make complete, correct account
    of different system fonts, window border dimensions, and
    screen resolution to get the layout of a System Requester
    just right using this routine.  For V36, we recommend the
    automatic layout implemented in BuildEasyRequestArgs() and
    EasyRequestArgs().

    SEE ALSO
    FreeSysRequest(), DisplayAlert(), ModifyIDCMP(), exec.library/Wait(),
    Request(), AutoRequest(), EasyRequestArgs(), BuildEasyRequestArgs()


intuition.library/ChangeScreenBuffer

    NAME
    ChangeScreenBuffer -- Swap the screen's BitMap. (V39)

    SYNOPSIS
    success = ChangeScreenBuffer( Screen, ScreenBuffer )
    D0                            A0      A1

    ULONG ChangeScreenBuffer( struct Screen *, struct ScreenBuffer * );

    FUNCTION
    Performs double (or multiple) buffering on an Intuition screen
    in an Intuition-cooperative manner.  The BitMap associated
    with the supplied ScreenBuffer will be installed in the
    specified screen, if possible.  The previously-installed BitMap
    is available for re-use upon receiving a signal from
    graphics.library.  See the graphics.library autodocs for
    graphics.library/AllocDBufInfo() and graphics.library/ChangeVPBitMap()
    for details.

    INPUTS
    Screen: pointer to the screen whose bitmap is to be swapped.
    ScreenBuffer: pointer to a ScreenBuffer structure obtained from
        AllocScreenBuffer().

    RESULT
    Returns non-zero if the operation succeeded.  Returns zero
    if the operation cannot be performed.  This function will
    fail if Intuition's state cannot permit it, for example the
    user is playing with menus or gadgets.

    NOTES
    It is not required to restore the original ScreenBuffer
    before closing the screen. Simply FreeScreenBuffer() each
    buffer (including the original and the currently-installed one)
    then close the screen.	Of course, you cannot call
    ChangeScreenBuffer() after freeing the currently-installed one.

    BUGS

    SEE ALSO
    AllocScreenBuffer(), FreeScreenBuffer(),
    graphics.library/ChangeVPBitMap()


intuition.library/ClearPointer

    NAME
    ClearPointer -- Clear the mouse pointer definition from a window.

    SYNOPSIS
    ClearPointer( Window )
              A0

    VOID ClearPointer( struct Window * );

    FUNCTION
    Clears the window of its own definition of the Intuition mouse pointer.
    After calling ClearPointer(), every time this window is the active
    one the default Intuition pointer will be the pointer displayed
    to the user.  If your window is the active one when this routine
    is called, the change will take place immediately.

    Custom definitions of the mouse pointer which this function clears
    are installed by a call to SetPointer().

    INPUTS
    Window = pointer to the window to be cleared of its pointer definition

    RESULT
    None

    BUGS

    SEE ALSO
    SetWindowPointerA(), SetPointer()


intuition.library/CloseScreen

    NAME
    CloseScreen -- Close an Intuition screen.

    SYNOPSIS
    Success = CloseScreen( Screen )
    D0 (V36)               A0

    BOOL CloseScreen( struct Screen * );
    /* returns BOOL in V36 and greater */

    FUNCTION
    Unlinks the screen, unlinks the viewport, deallocates everything that
    Intuition allocated when the screen was opened (using OpenScreen()).
    Doesn't care whether or not there are still any windows attached to the
    screen.  Doesn't try to close any attached windows; in fact, ignores
    them altogether (but see below for changes in V36).

    If this is the last screen to go, attempts to reopen Workbench.

    New for V36: this function will refuse to close the screen
    if there are windows open on the screen or if there are any
    outstanding screen locks (see LockPubScreen()) when
    CloseScreen() is called.  This avoids the almost certain crash
    when a screen is closed out from under a window.

    INPUTS
    Screen = pointer to the screen to be closed.

    RESULT
    New for V36: returns TRUE (1) if screen is closed,
    returns FALSE (0) if screen had open windows when
    called.

    BUGS

    SEE ALSO
    OpenScreen()


intuition.library/DisplayAlert

    NAME
    DisplayAlert -- Create the display of an alert message.

    SYNOPSIS
    Response = DisplayAlert( AlertNumber, String, Height )
    D0			 D0           A0      D1

    BOOL DisplayAlert( ULONG, UBYTE *, UWORD );

    FUNCTION
    Creates an alert display with the specified message.

    If the system can recover from this alert, it's a RECOVERY_ALERT and
    this routine waits until the user presses one of the mouse buttons,
    after which the display is restored to its original state and a
    BOOL value is returned by this routine to specify whether or not
    the user pressed the LEFT mouse button.

    If the system cannot recover from this alert, it's a DEADEND_ALERT
    and this routine returns immediately upon creating the alert display.
    The return value is FALSE.

    NOTE: Starting with V33, if Intuition can't get enough
    memory for a RECOVERY_ALERT, the value FALSE will be returned.

    AlertNumber is a LONG value, historically related to the value
    sent to the Alert() routine.  But the only bits that are pertinent to
    this routine are the ALERT_TYPE bit(s).  These bits must be set to
    either RECOVERY_ALERT for alerts from which the system may safely
    recover, or DEADEND_ALERT for those fatal alerts.  These states are
    described in the paragraph above.   There is a third type of
    alert, the DAISY_ALERT, which is used only by the Exec.

    The string argument points to an AlertMessage string.  The AlertMessage
    string is comprised of one or more substrings, each of which is
    composed of the following components:
           - first, a 16-bit x-coordinate and an 8-bit y-coordinate,
             describing where on the alert display you want this string
             to appear.  The y-coordinate describes the offset to the
             baseline of the text.
           - then, the bytes of the string itself, which must be
             null-terminated (end with a byte of zero)
           - lastly, the continuation byte, which specifies whether or
             not there's another substring following this one.  If the
             continuation byte is non-zero, there IS another substring
             to be processed in this alert message.  If the continuation
             byte is zero, this is the last substring in the message.

    The last argument, Height, describes how many video lines tall you
    want the alert display to be.

    New for V36: Alerts are always rendered in Topaz 8 (80 column font),
    regardless of the system default font.  Also, RECOVERY_ALERTs are
    displayed in amber, while DEADEND_ALERTs are still red.  Alerts
    no longer push down the application screens to be displayed.  Rather,
    they appear alone in a black display.

    Also new for V36: Alerts block each other out, and input
    during an alert is deprived of the rest of the system.  Internal
    input buffers still cause alert clicks to be processed by
    applications sometimes.

    INPUTS
    AlertNumber = the number of this alert message.  The only pertinent
        bits of this number are the ALERT_TYPE bit(s).  The rest of the
           number is ignored by this routine.
    String = pointer to the alert message string, as described above
    Height = minimum display lines required for your message

    RESULT
    A BOOL value of TRUE or FALSE.  If this is a DEADEND_ALERT, FALSE
    is always the return value.  If this is a RECOVERY_ALERT. The return
    value will be TRUE if the user presses the left mouse button in
    response to your message, and FALSE if the user presses the right hand
    button is response to your text, or if the alert could not
    be posted.

    BUGS
    If the system is worse off than you think, the level of your alert
    may become DEADEND_ALERT without you ever knowing about it.  This
    will NOT happen due simply to low memory.  Rather, the alert
    display will be skipped, and FALSE will be returned.

    The left and right button clicks satisfying the alerts are
    unfortunately passed to	the normal applications, because of
    some internal system input buffering.

    SEE ALSO
    TimedDisplayAlert()


intuition.library/DisplayBeep

    NAME
    DisplayBeep -- Flash the video display.

    SYNOPSIS
    DisplayBeep( Screen )
             A0

    VOID DisplayBeep( struct Screen * );

    FUNCTION
    "Beeps" the video display by flashing the background color of the
    specified screen.  If the screen argument is NULL, every screen
    in the display will be beeped.  Flashing everyone's screen is not
    a polite thing to do, so this should be reserved for dire
    circumstances.

    The reason such a routine is supported is because the Amiga has
    no internal bell or speaker.  When the user needs to know of
    an event that is not serious enough to require the use of a requester,
    the DisplayBeep() function may be called.

    New for V36:  Intuition now calls DisplayBeep through the
    external library vector.  This means that if you call SetFunction()
    to replace DisplayBeep with an audible beep, for example, then
    your change will affect even Intuition's calls to DisplayBeep.

    INPUTS
    Screen = pointer to a screen.  If NULL, every screen in the display
           will be flashed

    RESULT
    None

    NOTES
    Since this function changes color zero of the affected screen(s),
    surprising results could occur if the screen's owner reading
    colors or perhaps cycling them.

    BUGS

    SEE ALSO


intuition.library/DisposeObject

    NAME
    DisposeObject -- Deletes a 'boopsi' object. (V36)

    SYNOPSIS
    DisposeObject( Object )
                   A0

    VOID DisposeObject( APTR );

    FUNCTION
    Deletes a boopsi object and all of it auxiliary data.
    These objects are all created by NewObject().  Objects
    of certain classes "own" other objects, which will also
    be deleted when the object is passed to DisposeObject().
    Read the per-class documentation carefully to be aware
    of these instances.

    INPUTS
    Object = abstract pointer to a boopsi object returned by NewObject().
        The pointer may be NULL, in which case this function has
        no effect.

    NOTES
    This function invokes the OM_DISPOSE method.

    RESULT
    None.

    BUGS

    SEE ALSO
    NewObject(), SetAttrs(), GetAttr(), MakeClass(),
    Document "Basic Object-Oriented Programming System for Intuition"
    and the "boopsi Class Reference" document.


intuition.library/DoGadgetMethodA

    NAME
    DoGadgetMethodA -- Invoke method on a boopsi gadget. (V39)
    DoGadgetMethod -- Varargs stub for DoGadgetMethodA(). (V39)

    SYNOPSIS
    result = DoGadgetMethodA( Gadget, Window, Requester, Message )
    D0		          A0      A1      A2         A3

    ULONG DoGadgetMethodA( struct Gadget *, struct Window *,
        struct Requester *, Msg );

    result = DoGadgetMethod( Gadget, Window, Requester, MethodID, ...)

    ULONG DoGadgetMethod( struct Gadget *, struct Window *,
        struct Requester *, ULONG, ... );

    FUNCTION
    Same as the DoMethod() function of amiga.lib, but provides context
    information and arbitration for classes which implement custom
    Intuition gadgets.

    You should use this function for boopsi gadget objects,
    or for "models" which propagate information to gadgets.

    Unlike DoMethod(), this function provides a GadgetInfo pointer
    (if possible) when invoking the method.  Some classes may
    require or benefit from this.

    INPUTS
    Gadget = abstract pointer to a boopsi gadget
    Window = window gadget has been added to using AddGList() or AddGadget()
    Requester = for REQGADGETs, requester containing the gadget
    Msg = the boopsi message to send

    RESULT
    The object does whatever it wants with the message you sent,
    which might include updating its gadget visuals.

    The return value is defined per-method.

    NOTES
    This function invokes the specified method with a GadgetInfo
    derived from the 'Window' and 'Requester' pointers.  The GadgetInfo
    is passed as the second parameter of the message, except for
    OM_NEW, OM_SET, OM_NOTIFY, and OM_UPDATE, where the GadgetInfo
    is passed as the third parameter.

    Implementers of new gadget methods should ensure that the
    GadgetInfo is the second long-word of their message!

    SEE ALSO
    NewObject(), DisposeObject(), GetAttr(), MakeClass(),
    Document "Basic Object-Oriented Programming System for Intuition"
    and the "boopsi Class Reference" document.


intuition.library/EasyRequestArgs

    NAME
    EasyRequestArgs -- Easy alternative to AutoRequest(). (V36)
    EasyRequest -- Varargs stub for EasyRequestArgs(). (V36)

    SYNOPSIS
    num = EasyRequestArgs( Window, easyStruct, IDCMP_ptr, ArgList )
    D0                     A0      A1          A2         A3

    LONG EasyRequestArgs( struct Window *, struct EasyStruct *,
        ULONG *, APTR );

    num = EasyRequest( Window, easyStruct, IDCMP_ptr, Arg1, Arg2, ... )

    LONG EasyRequest( struct Window *, struct EasyStruct *,
        ULONG *, APTR, ... );

    ( from intuition.h )
    struct EasyStruct {
        ULONG	es_StructSize;
        ULONG	es_Flags;
        UBYTE	*es_Title;
        UBYTE	*es_TextFormat;
        UBYTE	*es_GadgetFormat;
    };

    FUNCTION
    This function provides a simpler method of using a 'System
    Requester' than provided by AutoRequest().  It performs layout
    and size calculations sensitive to the current font and screen
    resolution.

    It provides for the descriptive 'body' text and the gadget
    text to be constructed from 'printf' style format strings.

    It also provides a general way for the requester to be
    sensitive to particular IDCMP messages.

    The first function listed is the actual Intuition library
    function.  It is passed the arguments for the formatting
    operations as a pointer to the first argument.

    The second function uses a C-style variable number of argument
    (varargs) calling convention.  It should be implemented as
    a call to the first function, and might be supplied by your
    compiler vendor, in amiga.lib, or using the first example below,
    for most C compilers.

    NOTE: The formatting is done by exec.library/RawDoFmt(), so
    be aware that to display a 32-bit integer argument, for
    example, you must say "%ld", not "%d", since RawDoFmt() is
    "word-oriented."

    NOTE: This function switches the processor stack to ensure
    sufficient stack space for the function to complete.

    EXAMPLES
    /* varargs interface works for most C compilers */
    EasyRequest( w, es, ip, arg1 )
    struct Window	*w;
    struct EasyStruct *es;
    ULONG		  *ip;
    int		  arg1;
    {
        return ( EasyRequestArgs( w, es, ip, &arg1 ) );
    }

    /*********************************************/

    /* typical use */
    struct EasyStruct volumeES = {
        sizeof (struct EasyStruct),
        0,
        "Volume Request",
        "Please insert volume %s in any drive.",
        "Retry|Cancel",
    };
    #define CANCEL	(0)

    Volume	*
    getVolume( volname )
    UBYTE	*volname;
    {
        Volume	*vptr;
        Volume	*findVolume();
        UWORD	reply;
        ULONG	iflags;

        iflags = IDCMP_DISKINSERTED;

    while ( ((vptr = findVolume( volname )) == NULL) &&
     (EasyRequest( w, &volumeES, &iflags, volname ) != CANCEL) )
        /* loop */ ;

        /* note that in some circumstances, you will have to
           re-initialize the value of 'iflags'.  Here, it
           is either unchanged, or returned as the single
           IDCMPFlag value IDCMP_DISKINSERTED.  If you combine
           multiple  IDCMPFlag values in 'iflags,' only
           one will be returned, so you must reinitialize
           'iflags' to be the combination.
          */
        return ( vptr );
    }

    INPUTS
    Window = Reference window pointer, determines the screen and
        title of the requester window.  This can be NULL, which
        means the requester is to appear on the Workbench screen,
        or default public screen, if defined.
    IDCMP_ptr = Pointer to IDCMP flags that you want to terminate
        the requester.  This pointer may be NULL.
    easyStruct = Pointer to EasyStruct structure with fields
        interpreted as follows:

    es_StructSize = sizeof (struct EasyStruct), for future extension.
    es_Flags = 0 for now, in the future may specify other options.
    es_Title = Title of system requester window.  If this is NULL,
        the title will be taken to be the same as the title of 'Window',
        if provided, or else "System Request."
    es_TextFormat = Format string, a la RawDoFmt(), for message in
        requester body.  Lines are separated by the newline character.
        This character is represented in C by 'n', in the Amiga Shell
        by "*N", etc.  Formatting '%' functions are supported exactly
        as in RawDoFmt().
    es_GadgetFormat = Format string for gadgets.  Text for separate
        gadgets is separated by '|'.  Format functions are supported.
        You MUST specify at least one gadget.

    ArgList = Arguments for format commands.   Arguments for
        GadFmt follow arguments for TextFmt.

    RESULT
    0, 1, ..., N = Successive GadgetID values, for the gadgets
        you specify for the requester.  NOTE: The numbering
        from left to right is actually: 1, 2, ..., N, 0.
        This is for compatibility with AutoRequest(), which has
        FALSE for the rightmost gadget.

    -1 = Means that one of the caller-supplied IDCMPFlags occurred.
        The IDCMPFlag value is in the longword pointed to by IDCMP_ptr.

    NOTES
    When DOS brings up EasyRequests() on your process (eg.
    "Please insert volume XXX in any drive", they normally come
    up on the default public screen, which is usually the Workbench
    screen.  If you set your Process pr_WindowPtr field to point to
    one of your windows, then DOS will bring its requesters up on the
    same screen as that window.  A pr_WindowPtr of -1 prevents
    requesters from coming up at all.
    (Some FileSystem requesters cannot be redirected or supressed).

    BUGS
    Does not fall back to a recoverable alert if the requester
     cannot be created.

    Does not handle case when gadgets don't fit or window title
    is too long, although it does trim trailing spaces from the
    title for calculating dimensions.

    PLANS
    Possible enhancements include: centering of text, size-sensitive
    layout,  window-relative requester, vertical gadget layout,
    window placement, more keyboard shortcuts.

    We also reserve the use of the newline character ('n') in
    gadget format strings for future use as a line separator.

    SEE ALSO
    exec.library/RawDoFmt(), BuildEasyRequestArgs(), SysReqHandler(),
    AutoRequest(), BuildSysRequest()


intuition.library/FreeScreenBuffer

    NAME
    FreeScreenBuffer -- Free a ScreenBuffer structure. (V39)

    SYNOPSIS
    FreeScreenBuffer( Screen, ScreenBuffer )
                      A0      A1

    VOID FreeScreenBuffer( struct Screen *, struct ScreenBuffer * );

    FUNCTION
    Frees a ScreenBuffer structure you got from AllocScreenBuffer(),
    and releases associated resources.  You must call FreeScreenBuffer()
    before you close your screen.

    INPUTS
    Screen: pointer to the screen this ScreenBuffer is associated with.
    ScreenBuffer: pointer to a ScreenBuffer structure obtained from
        AllocScreenBuffer().  It is safe to call this function with
        a NULL argument.  It will have no effect.

    RESULT
    None.

    NOTES
    Originally, FreeScreenBuffer() did not WaitBlit() before freeing
    a BitMap.  The intent was that the application should do this.
    However, as this sort of thing is easily forgotten, WaitBlit()
    was added in V40.  Application writers should ensure that freeing
    the buffer is safe by calling WaitBlit() themselves.

    The SB_SCREEN_BITMAP flag instructs AllocScreenBuffer() to provide
    a ScreenBuffer referring to the screen's actual bitmap.  When
    you are done changing screen buffers, you must FreeScreenBuffer()
    the currently-installed ScreenBuffer before you close the screen.
    Intuition will recognize when FreeScreenBuffer() is called for
    the currently-installed ScreenBuffer, and will know to free the
    supporting structures but not the BitMap.  CloseScreen() will
    take care of that.

    BUGS

    SEE ALSO
    AllocScreenBuffer(), ChangeScreenBuffer(),
    graphics.library/ChangeVPBitMap()


intuition.library/FreeScreenDrawInfo

   NAME
     FreeScreenDrawInfo -- Finish using a DrawInfo structure. (V36)

   SYNOPSIS
    FreeScreenDrawInfo( Screen, DrInfo )
                A0      A1

    VOID FreeScreenDrawInfo( struct Screen *, struct DrawInfo * );

   FUNCTION
    Declares that you are finished with the DrawInfo structure
    returned by GetScreenDrawInfo().

   INPUTS
     Screen - pointer to screen passed to GetScreenDrawInfo().
    DrInfo - pointer to DrawInfo returned by GetScreenDrawInfo().
        A NULL DrawInfo pointer is a valid parameter, signifying
        "do nothing".

   RESULT
     None

   NOTES
    This function, and GetScreenDrawInfo(), don't really do much, but
    they provide an upward compatibility path.  That means that
    if you misuse them today, they probably won't cause a problem,
    although they may someday later.  So, please be very careful
    only to use the DrawInfo structure between calls to
    GetScreenDrawInfo() and FreeScreenDrawInfo(), and be sure
    that you don't forget FreeScreenDrawInfo().

   BUGS

   SEE ALSO
    GetScreenDrawInfo()


intuition.library/FreeSysRequest

    NAME
    FreeSysRequest -- Free resources gotten by a call to BuildSysRequest().

    SYNOPSIS
    FreeSysRequest( Window )
                A0

    VOID FreeSysRequest( struct Window * );

    FUNCTION
    This routine frees up all memory allocated by a successful call to
    the BuildSysRequest() procedure.  If BuildSysRequest() returned a
    pointer to a window, then you are able to wait on the message port
    of that window to detect an event which satisfies the requester.
    When you want to remove the requester, you call this procedure.  It
    ends the requester and deallocates any memory used in the creation
    of the requester.  It also closes the special window that was opened
    for your system requester.

    For V36: It's OK if you pass a NULL or a TRUE (1) value to
    this function.  Also, this function properly disposes of
    requesters gotten using BuildEasyRequestArgs().

    INPUTS
    Window = value of the window pointer returned by a successful call to
           the BuildSysRequest() procedure

    RESULT
    None

    BUGS

    SEE ALSO
    BuildSysRequest(), AutoRequest(), CloseWindow()


intuition.library/GetDefaultPubScreen

    NAME
    GetDefaultPubScreen -- Get name of default public screen. (V36)

    SYNOPSIS
    GetDefaultPubScreen( Namebuff )
                 A0

    VOID GetDefaultPubScreen( UBYTE * );

    FUNCTION
    Provides the name of the current default public screen.
    Only anticipated use is for Public Screen Manager utilities,
    since it is easy to open a visitor window on the default
    public screen without specifying the name.

    INPUTS
    Namebuff = a buffer of MAXPUBSCREENNAME.  This can be NULL.

    RESULT
    None.  Will provide the string "Workbench" in Namebuff if there
    is no current default public screen.

    NOTES
    This function actually "returns" in register D0 a pointer
    to the public screen.  Unfortunately, the lifespan of
    this pointer is not ensured; the screen could be closed
    at any time.  The *ONLY* legitimate use we can see for
    this return value is to compare for identity with the pointer
    to a public screen you either have a window open in, or
    a lock on using LockPubScreen(), to determine if that
    screen is in fact the default screen.

    Also note that if there no default public screen has been set,
    the return value of this function will be zero, and not a pointer
    to the Workbench screen.

    BUGS
    The function prototype does not reflect the return value.

    SEE ALSO
    SetDefaultPubScreen(), OpenWindow()


intuition.library/GetPrefs

    NAME
    GetPrefs -- Get the current Intuition Preferences structure.

    SYNOPSIS
    Prefs = GetPrefs( PrefBuffer, Size )
    D0		  A0          D0

    struct Preferences *GetPrefs( struct Preferences *, WORD );

    FUNCTION
    Gets a copy of the current Intuition Preferences structure.
    Writes the data into the buffer you specify.  The number of bytes you
    want copied is specified by the size argument.

    It is legal to take a partial copy of the Preferences structure.
    The more pertinent preferences variables have been grouped near
    the top of the structure to facilitate the memory conservation
    that can be had by taking a copy of only some of the Preferences
    structure.

    New for V36:  A new and more extensible method for supplying
    Preferences has been introduced in V36, and relies on file
    system notification.  The Intuition preferences items rely
    also on the IPrefs program.  Certain elements of the
    Preferences structure have been superseded by this new method.
    As much as possible, the Preferences structure returned by
    GetPrefs() reflect the current state of Preferences.  However,
    it is impossible to represent some of the V36-style preferences
    items using the existing Preferences structure.

    INPUTS
    PrefBuffer = pointer to the memory buffer to receive your copy of the
           Intuition Preferences
    Size = the number of bytes in your PrefBuffer, the number of bytes
           you want copied from the system's internal Preference settings

    RESULT
    Returns your parameter PrefBuffer.

    BUGS

    SEE ALSO
    GetDefPrefs(), SetPrefs()


intuition.library/HelpControl

    NAME
    HelpControl -- Enable/disable Gadget-Help feature. (V39)

    SYNOPSIS
    HelpControl( window, flags )
                 A0      D0

    VOID HelpControl( struct Window *, ULONG );

    FUNCTION
    This function can be used to turn Gadget-Help on or off for
    your window.  Gadget-Help will also be enabled/disabled
    accordingly for all other windows which share the same
    help-group.  This allows Gadget-Help to be well-behaved
    for multiple-window applications.

    INPUTS
    window - Pointer to the window you wish to affect.  (Other windows
        will also be affected, as explained above.
    flags - Currently, HC_GADGETHELP or zero are the allowed values.

    RESULT
    One or more windows will have Gadget-Help turned on or off.

    NOTES
    You must use utility.library/GetUniqueID() to get a help-group
    identifier.  Never ever supply your own!

    SEE ALSO
    WA_HelpGroup


intuition.library/ItemAddress

    NAME
    ItemAddress -- Returns the address of the specified MenuItem.

    SYNOPSIS
    Item = ItemAddress( MenuStrip, MenuNumber )
    D0		    A0         D0

    struct MenuItem *ItemAddress( struct Menu *, UWORD );

    FUNCTION
    This routine feels through the specified menu strip and returns the
    address of the item specified by the menu number.  Typically,
    you will use this routine to get the address of a menu item from
    a menu number sent to you by Intuition after user has chosen from
    a window's menus.

       This routine requires that the arguments are well-defined.
    MenuNumber may be equal to MENUNULL, in which case this routine returns
    NULL.  If MenuNumber doesn't equal MENUNULL, it's presumed to be a
    valid item number selector for your menu strip, which includes:
           - a valid menu number
           - a valid item number
           - if the item specified by the above two components has a
             sub-item, the menu number may have a sub-item component, too.

    Note that there must be BOTH a menu number and an item number.
    Because a sub-item specifier is optional, the address returned by
    this routine may point to either an item or a sub-item.

    INPUTS
    MenuStrip = a pointer to the first menu in your menu strip
    MenuNumber = the value which contains the packed data that selects
           the menu and item (and sub-item).  See the Intuition Reference
        Manual for information on menu numbers.

    RESULT
    If MenuNumber == MENUNULL, this routine returns NULL,
    else this routine returns the address of the menu item specified
    by MenuNumber.

    BUGS

    SEE ALSO
    The "Menus" chapter of the Intuition Reference Manual,
    or the Amiga ROM Kernel Manual


intuition.library/LendMenus

    NAME
    LendMenus -- Lend window's menu action to another window. (V39)

    SYNOPSIS
    LendMenus( fromWindow, toWindow )
               A0          A1

    VOID LendMenus( struct Window *, struct Window * );

    FUNCTION
    This function is used to "lend" the menus of one window to
    another.  This means that menu events (for example, the user
    presses the mouse menu button) will take place in another
    window's menu (using that other window's menu strip and screen).

    The sole intended use of this function is to unify two
    windows on different screens that are attached.  (See
    SA_Parent, SA_FrontChild, SA_BackChild).  An example would
    be a program with a full-sized parent screen which has a
    short control panel screen attached in the front.  Pressing the
    menu button even when the control panel window of the canvas
    screen is active can now cause the menus of the parent screen
    to appear.

    INPUTS
    fromWindow = pointer to the Window structure whose menu actions
        are to go to another window.
    toWindow = pointer to the Window structure whose menus are to
        be displayed in place of the fromWindow's.  If NULL, turns
        off menu-lending from the fromWindow.

    RESULT
    None.

    BUGS
    The current behavior is such that the toWindow is temporarily
    activated.  This may not continue to be the case.  Be prepared
    to handle this!

    SEE ALSO
    SetMenuStrip(), ClearMenuStrip()


intuition.library/LockPubScreenList

    NAME
    LockPubScreenList -- Prevent changes to the system list. (V36)

    SYNOPSIS
    List = LockPubScreenList()
    D0

    struct List *LockPubScreenList( VOID );

    FUNCTION
    Arbitrates access to public screen list	while you quickly
    make a copy of it for display to the user.

    Note that this is intended only for the Public Screen Manager
    program.

    NOTES
    The nodes on the list are PubScreenNode structures.
    Act quickly while holding this lock.  The restrictions
    on LockIBase() apply here as well.

    INPUTS
    None.

    RESULT
    A pointer to the public screen list.

    BUGS

    SEE ALSO
    UnlockPubScreenList(), OpenScreen(), Intuition V36 update documentation


intuition.library/MakeScreen

    NAME
    MakeScreen -- Do an Intuition-integrated MakeVPort() of a screen.

    SYNOPSIS
    failure = MakeScreen( Screen )
    D0 (V39)              A0

    LONG MakeScreen( struct Screen * );
    /* Returns LONG in V39 and greater */

    FUNCTION
    This procedure allows you to do a MakeVPort() for the viewport of your
    custom screen in an Intuition-integrated way.  This way you can
    do your own screen manipulations without worrying about interference
    with Intuition's usage of the same viewport.

    The operation of this function is as follows:
        - Block until the Intuition View structure is not in being changed.
        - Set the view modes correctly to reflect if there is a (visible)
          interlaced screen.
        - call MakeVPort(), passing the Intuition View and your screen's
          ViewPort.
        - Unlocks the Intuition View.

    After calling this routine, you should call RethinkDisplay() to
    incorporate the new viewport of your custom screen into the
    Intuition display.

    NOTE: Intuition may determine that because of a change in global
    interlace needs that all viewports need to be remade, so
    it may effectively call RemakeDisplay().

    INPUTS
    Screen = address of the custom screen structure

    RESULT
    Starting with V39, returns zero for success, non-zero for failure.
    Probable cause of failure is failure of graphics.library/MakeVPort().
    Prior to V39, the return code is invalid.  Do not interpret it when
    running on pre-V39 systems!

    BUGS

    SEE ALSO
    RethinkDisplay(), RemakeDisplay(), graphics.library/MakeVPort()


intuition.library/ModifyIDCMP

    NAME
    ModifyIDCMP -- Modify the state of a window's IDCMPFlags.

    SYNOPSIS
    Success = ModifyIDCMP( Window, IDCMPFlags )
    D0 (V37)               A0      D0

    BOOL ModifyIDCMP( struct Window *, ULONG );
    /* returns BOOL in V37 and greater */

    FUNCTION
    This routine modifies the state of your window's IDCMP (Intuition
    Direct Communication Message Port).  The state is modified to reflect
    your desires as described by the flag bits in the value IDCMPFlags.

    The four actions that might be taken are:

       - if there is currently no IDCMP in the given window, and IDCMPFlags
         is zero, nothing happens
       - if there is currently no IDCMP in the given window, and any of the
         IDCMPFlags is selected (set), then the IDCMP of the window is
         created, including allocating and initializing the message ports
         and allocating a signal bit for your port.  See the "Input and
         Output Methods" chapter of the Intuition Reference Manual for full
      details
       - if the IDCMP for the given window exists, and the
         IDCMPFlags argument is zero, this says that you want
         Intuition to close the ports, free the buffers and free
         your signal bit.  You MUST be the same task that was active
         when this signal bit was allocated (either by ModifyIDCMP()
      or OpenWindow() ).
       - if the IDCMP for the given window is opened, and the IDCMPFlags
         argument is not zero, this means that you want to change the
         state of which events will be broadcast to you through the IDCMP

    NOTE:  You can set up the Window->UserPort to any port of your own
    before you call ModifyIDCMP().  If IDCMPFlags is non-null but
    your UserPort is already initialized, Intuition will assume that
    it's a valid port with task and signal data preset and Intuition
    won't disturb your set-up at all, Intuition will just allocate
    the Intuition message port half of it.  The converse is true
    as well:  if UserPort is NULL when you call here with
    IDCMPFlags == NULL, Intuition will deallocate only the Intuition
    side of the port.

    This allows you to use a port that you already have allocated:
       - OpenWindow() with IDCMPFlags equal to NULL (open no ports)
       - set the UserPort variable of your window to any valid port of your
         own choosing
       - call ModifyIDCMP with IDCMPFlags set to what you want
       - then, to clean up later, set UserPort equal to NULL before calling
         CloseWindow() (leave IDCMPFlags alone)  BUT FIRST: you must make
      sure that no messages sent your window are queued at the port,
      since they will be returned to the memory free pool.

    For an example of how to close a window with a shared IDCMP,
    see the description for CloseWindow().

    INPUTS
    Window = pointer to the Window structure containing the IDCMP ports
    IDCMPFlags = the flag bits describing the new desired state of
        the IDCMP.  The flags are:

        - IDCMP_REQVERIFY is the flag which, like IDCMP_SIZEVERIFY and ...

        - IDCMP_MENUVERIFY (see immediately below), specifies that you
          want to make sure that your graphical state is quiescent
          before something extraordinary happens.  In this case, the
          extraordinary event is that a rectangle of graphical data is
          about to be blasted into your Window.  If you're drawing
          directly into its screen, you probably will wish to make sure
          that you've ceased drawing before the user is allowed to bring
          up the DMRequest you've set up, and the same for when system
          has a request for the user.  Set this flag to ask for that
          verification step.

        - IDCMP_REQCLEAR is the flag you set to hear a message whenever
          a requester is cleared from your window.  If you are using
          IDCMP_REQVERIFY to arbitrate access to your screen's bitmap, it
          is safe to start your output once you have heard an
          IDCMP_REQCLEAR for each IDCMP_REQSET.

        - IDCMP_REQSET is a flag that you set to receive a broadcast
          for each requester that is opened in your window.  Compare
          this with IDCMP_REQCLEAR above.  This function is distinct
          from IDCMP_REQVERIFY.  This functions merely tells you that a
          requester has opened, whereas IDCMP_REQVERIFY requires you to
          respond before the requester is opened.

        - IDCMP_MENUVERIFY is the flag you set to have Intuition stop
          and wait for you to finish all graphical output to your
          window before rendering the menus.  Menus are currently
          rendered in the most memory-efficient way, which involves
          interrupting output to all windows in the screen before the
          menus are drawn.  If you need to finish your graphical
          output before this happens, you can set this flag to make
          sure that you do.

        - IDCMP_SIZEVERIFY means that you will be doing output to your
          window which depends on a knowledge of the current size of the
          window.  If the user wants to resize the window,  you may want
          to make sure that any queued output completes before the sizing
          takes place (critical text, for instance).  If this is the
          case, set this flag.   Then, when the user wants to size,
          Intuition will send you the IDCMP_SIZEVERIFY message and Wait()
          until you reply that it's OK to proceed with the sizing. NOTE:
          when we say that Intuition will Wait() until you reply, what
          we're really saying is that user will WAIT until you reply, which
          suffers the great negative potential of User-Unfriendliness.
          So remember:  use this flag sparingly, and, as always with any
          IDCMP Message you receive, reply to it promptly!  Then, after
          user has sized the window, you can find out about it using
          IDCMP_NEWSIZE.

        With all the "VERIFY" functions, it is not save to leave them
        enabled at any time when your task may not be able to respond
        for a long period.

        It is NEVER safe to call AmigaDOS, directly or indirectly, when
        a "VERIFY" function is active.  If AmigaDOS needs to put up a
        disk requester for you, your task might end up waiting for the
        requester to be satisfied, at the same time as Intuition is
        waiting for your response.  The result is a complete machine
        lockup.  USE ModifyIDCMP() TO TURN OFF ANY VERIFY MESSAGES
        BEFORE CALLING dos.library!!

        For V36: If you do not respond to the verification IntuiMessages
        within the user specified timeout duration, Intuition will abort
        the operation.  This eliminates the threat of these easy
        deadlocks, but can result in a confused user.  Please try
        hard to continue to avoid "logical deadlocks".

        - IDCMP_NEWSIZE is the flag that tells Intuition to send an IDCMP
          message to you after the user has resized your window.  At
          this point, you could examine the size variables in your
          window structure to discover the new size of the window.
          See also the IDCMP_CHANGEWINDOW IDCMP flag.

        - IDCMP_REFRESHWINDOW when set will cause a message to be sent
          whenever your window needs refreshing.  This flag makes
          sense only with WFLG_SIMPLE_REFRESH and WFLG_SMART_REFRESH
          windows.

        - IDCMP_MOUSEBUTTONS will get reports about mouse-button up/down
          events broadcast to you (Note:  only the ones that
          don't mean something to Intuition.  If the user clicks the
          select button over a gadget, Intuition deals with it and you
          don't find out about it through here).

        - IDCMP_MOUSEMOVE will work only if you've set the
          WFLG_REPORTMOUSE flag above, or if one of your gadgets has the
          GACT_FOLLOWMOUSE flag set.  Then all mouse movements will be
          reported here, providing your window is active.

        - IDCMP_GADGETDOWN means that when the User "selects" a gadget
          you've created with the GACT_IMMEDIATE flag set, the fact
          will be broadcast through the IDCMP.

        - IDCMP_GADGETUP means that when the user "releases" a gadget that
          you've created with the GACT_RELVERIFY flag set, the fact
          will be broadcast through the IDCMP.  This message is
          only generated if the release is "good", such as releasing
          the select button over a Boolean gadget, or typing ENTER
          in a string gadget.

        - IDCMP_MENUPICK selects that menu number data will be sent via
          the IDCMP.

        - IDCMP_CLOSEWINDOW means broadcast the IDCMP_CLOSEWINDOW event
          through the IDCMP rather than the console.

        - IDCMP_RAWKEY selects that all IDCMP_RAWKEY events are
          transmitted via the IDCMP.  Note that these are absolutely RAW
          keycodes, which you will have to translate before using.
          Setting this and the MOUSE flags effectively eliminates the need
          to open a Console device to get input from the keyboard and
          mouse.  Of course, in exchange you lose all of the console
          features, most notably the "cooking" of input data and
          the systematic output of text to your window.

        - IDCMP_VANILLAKEY is for developers who don't want the hassle
          of IDCMP_RAWKEYS.  This flag will return all the keycodes after
          translation via the current country-dependent keymap.  When
          you set this flag, you will get IntuiMessages where the Code
          field has a decoded ANSI character code representing the key
          struck on the keyboard.  Only codes that map to a single
          character are returned: you can't read such keys as HELP or
          the function keys with IDCMP_VANILLAKEY.

          NEW FOR V36: If you have both IDCMP_RAWKEY and IDCMP_VANILLAKEY
          set, Intuition will send an IDCMP_RAWKEY event for those
          *downstrokes* which do not map to single-byte characters
          ("non-vanilla" keys).  In this way you can easily detect cursor
          keys, function keys, and the Help key without sacrificing the
          convenience of IDCMP_VANILLAKEY.  NB: A side-effect of having
          both IDCMP_RAWKEY and IDCMP_VANILLAKEY set is that you never
          hear IDCMP_RAWKEY upstrokes, even for keys that caused
          IDCMP_RAWKEY downstrokes.

        - IDCMP_INTUITICKS gives you simple timer events from Intuition
          when your window is the active one; it may help you avoid
          opening and managing the timer device.  With this flag set,
          you will get only one queued-up INTUITICKS message at a
          time.  If Intuition notices that you've been sent an
          IDCMP_INTUITICKS message and haven't replied to it, another
          message will not be sent.  Intuition receives timer events and
          considers sending you an IDCMP_INTUITICKS message approximately
          ten times a second.

        - IDCMP_DELTAMOVE gives raw (unscaled) input event delta X/Y
          values.  This is so you can detect mouse motion regardless of
          screen/window/display boundaries.  This works a little
          strangely: if you set both IDCMP_MOUSEMOVE and IDCMP_DELTAMOVE.
          IDCMPFlags, you will get IDCMP_MOUSEMOVE messages with delta
          x/y values in the MouseX and MouseY fields of the
          IDCMPMessage.

        - IDCMP_NEWPREFS indicates you wish to be notified when the
          system-wide Preferences changes.  For V36, there is a new
          environment mechanism to replace Preferences, which we
          recommend you consider using instead.

        - Set IDCMP_ACTIVEWINDOW and IDCMP_INACTIVEWINDOW to get messages
          when those events happen to your window.  Take care not to
          confuse this "ACTIVEWINDOW" with the familiar sounding, but
          totally different "WINDOWACTIVE" flag.  These two flags have
          been supplanted by "IDCMP_ACTIVEWINDOW" and "WFLG_WINDOWACTIVE".
          Use the new equivalent terms to avoid confusion.

        - Set IDCMP_DISKINSERTED or IDCMP_DISKREMOVED to learn when
          removable disks are inserted or removed, respectively.

        - IDCMP_IDCMPUPDATE is a new class for V36 which is used as
          a channel of communication from custom and boopsi gadgets
          to your application.

        - IDCMP_CHANGEWINDOW is a new class for V36 that will be sent
          to your window whenever its dimensions or position are changed
          by the user or the functions SizeWindow(), MoveWindow(),
          ChangeWindowBox(), or ZipWindow().

        - IDCMP_MENUHELP is new for V37.  If you specify the WA_MenuHelp
          tag when you open your window, then when the user presses the
          HELP key on the keyboard during a menu session, Intuition will
          terminate the menu session and issue this even in place of an
          IDCMP_MENUPICK message.
        - NEVER follow the NextSelect link for MENUHELP messages.
        - You will be able to hear MENUHELP for ghosted menus.
          (This lets you tell the user why the option is ghosted.)
        - Be aware that you can receive a MENUHELP message whose code
          corresponds to a menu header or an item that has sub-items
          (which does not happen for MENUPICK).  The code may also be
          MENUNULL.
        - LIMITATION:  if the user extend-selects some checkmarked
          items with the mouse, then presses MENUHELP, your
          application will only hear the MENUHELP report.  You
          must re-examine the state of your checkmarks when you
          get a MENUHELP.
        - Availability of MENUHELP in V36 is not directly
          controllable.  We apologize...

        - IDCMP_GADGETHELP is new for V39.  If you turn on
          gadget help for your window (using the HelpControl())
          function, then Intuition will send IDCMP_GADGETHELP
          messages when the mouse passes over certain gadgets or
          your window.  The IntuiMessage->Code field is normally
          ~0, but a boopsi gadget can return any word value it wishes.

          Ordinarily, gadget help is only processed for the active
          window.  When Intuition has determined that the mouse is
          pointing at a gadget which has the GMORE_GADGETHELP
          property, you will be sent an IDCMP_GADGETHELP message
          whose IAddress points to the gadget.  When the mouse is
          over your window but not over any help-aware gadget, you
          will be sent a message whose IAddress is the window
          itself.  When the mouse is not over your window,
          Intuition sends a message whose IAddress is zero.

          A multi-window application can use the WA_HelpGroup or
          WA_HelpGroupWindow tags to indicate that all its windows
          belong in a group.  (The help group identifier should be
          obtained with utility.library/GetUniqueID().) This makes
          Intuition test gadget help in all windows of the group
          when any one of them is the active one.  Inactive windows
          whose WA_HelpGroup matches the active window's receive
          IDCMP_GADGETHELP messages when the mouse is over that
          window or any of its help-aware gadgets.  The GADGETHELP
          message with an IAddress of zero means the mouse is not
          over the active window or any other window of the same
          group.  It is always sent to the active window (which is
          not necessarily the window in your group that last got a
          message).

          To maximize performance, gadget help is not checked
          while the mouse is travelling quickly, or if it has not
          moved at all since the last test.  As well, if Intuition
          discovers that the mouse is still over same gadget and
          that gadget does not wish to send a different
          IntuiMessage->Code from the last message, no new
          IntuiMessage is sent.

    RESULT
    Starting in V37, this function returns NULL if it was unable
    to create the necessary message ports.  (The possibility of
    failure exists in earlier releases, but no return code was offered).
    Do not check the return code under V36 or earlier.

    BUGS

    SEE ALSO
    OpenWindowTagList(), OpenWindow(), CloseWindow()


intuition.library/ModifyProp

    NAME
    ModifyProp -- Modify the current parameters of a proportional gadget.

    SYNOPSIS
    ModifyProp( Gadget, Window, Requester,
            A0	    A1	    A2
                   Flags, HorizPot, VertPot, HorizBody, VertBody )
            D0	   D1	     D2	      D3	 D4

    VOID ModifyProp( struct Gadget *, struct Window *,
        struct Requester *, UWORD, UWORD, UWORD, UWORD, UWORD );

    FUNCTION
    Modifies the parameters of the specified proportional gadget.  The
    gadget's internal state is then recalculated and the imagery
    is redisplayed in the window or requester that contains the gadget.

    The requester variable can point to a requester structure.  If the
    gadget has the GTYP_REQGADGET flag set, the gadget is in a requester
    and the window pointer must point to the window of the requester.
    If this is not the gadget of a requester, the requester argument may
    be NULL.

    NOTE: this function causes all gadgets from the proportional
    gadget to the end of the gadget list to be refreshed, for
    reasons of compatibility.
    For more refined display updating, use NewModifyProp().

    New for V36: ModifyProp() refreshing consists of redrawing gadgets
    completely.  NewModifyProp() has changed this behavior (see
    NewModifyProp()).

    INPUTS
    PropGadget = pointer to a proportional gadget
    Window = pointer to the window containing the gadget or the window
        containing the requester containing the gadget.
    Requester = pointer to a requester (may be NULL if this isn't
        a requester gadget)
    Flags = value to be stored in the Flags field of the PropInfo
    HorizPot = value to be stored in the HorizPot field of the PropInfo
    VertPot = value to be stored in the VertPot field of the PropInfo
    HorizBody = value to be stored in the HorizBody field of the PropInfo
    VertBody = value to be stored in the VertBody field of the PropInfo

    RESULT
    None

    BUGS

    SEE ALSO
    NewModifyProp()
    The Intuition Reference Manual and Amiga ROM Kernel Manual contain
    more information on Proportional Gadgets.


intuition.library/MoveScreen

    NAME
    MoveScreen -- Attempt to move the screen by the increments provided.

    SYNOPSIS
    MoveScreen( Screen, DeltaX, DeltaY )
            A0      D0      D1

    VOID MoveScreen( struct Screen *, WORD, WORD );

    FUNCTION
    Moves the screen the specified increment, specified in screen
    pixel resolution coordinates.

    New for V36: Screen movement limits have been greatly relaxed,
    to support screen scrolling.  In particular, negative values
    for screen LeftEdge and TopEdge may now be valid.

       If the DeltaX and DeltaY variables you specify would move the screen
       in a way that violates any restrictions, the screen will be moved
       as far as possible.  You may examine the LeftEdge and TopEdge fields
    of the Screen structure after this function returns to see where
    the screen really ended up.

    INPUTS
    Screen = pointer to a Screen structure
    DeltaX = amount to move the screen on the x-axis
        Note that DeltaX no longer (V36) need be set to zero
    DeltaY = amount to move the screen on the y-axis
        Note that these coordinates are in the same resolution
        as the screen (such as HIRES or INTERLACE)

    RESULT
    None

    BUGS

    SEE ALSO
    ScreenPosition(), RethinkDisplay()


intuition.library/NextObject

    NAME
    NextObject -- iterate through the object on an Exec list. (V36)

    SYNOPSIS
    object = NextObject( objectPtrPtr )
    D0                   A0

    APTR NextObject( APTR );

    FUNCTION
    This function is for boopsi class implementors only.

    When you collect a set of boopsi objects on an Exec List
    structure by invoking their OM_ADDMEMBER method, you
    can (only) retrieve them by iterations of this function.

    Works even if you remove and dispose the returned list
    members in turn.

    INPUTS
    Initially, you set a pointer variable to equal the
    lh_Head field of the list (or mlh_Head field of a MinList).
    You pass the *address* of that pointer repeatedly
    to NextObject() until it returns NULL.

    EXAMPLE

    /* here is the OM_DISPOSE case of some class's dispatcher */
    case OM_DISPOSE:
        /* dispose members	*/
        object_state = mydata->md_CollectionList.lh_Head;
        while ( member_object = NextObject( &object_state ) )
        {
        DoMethod( member_object, OM_REMOVE ); /* remove from list */
        DoMethodA( member, msg );	/* and pass along dispose	*/
        }

    RESULT
    Returns pointers to each object in the list in turn, and NULL
    when there are no more.

    NOTES

    BUGS

    SEE ALSO
    DisposeObject(), SetAttrs(), GetAttr(), MakeClass(),
    Document "Basic Object-Oriented Programming System for Intuition"
    and the "boopsi Class Reference" document.


intuition.library/NextPubScreen

    NAME
    NextPubScreen -- Identify next public screen in the cycle. (V36)

    SYNOPSIS
    Buff = NextPubScreen( Screen, NameBuff )
    D0                    A0      A1

    UBYTE *NextPubScreen( struct Screen *, UBYTE * );

    FUNCTION
    Returns name of next public screen in system rotation, to
    allow visitor windows to provide function to "jump" among
    public-screens in a cycle.

    INPUTS
    Screen = pointer to the screen your window is currently open in,
      or NULL, if you don't have a pointer to a public screen.
    NameBuff = pointer to a buffer of MAXPUBSCREENNAME+1 characters,
      for Intuition to fill in with the name of the next public
      screen in rotation.

    RESULT
    Returns NULL if there are no public screens, otherwise a
    pointer to your NameBuff.

    NOTES
    There is no guarantee that the public screen whose name
    was returned by this function will exist or be in "public" state
    by the time you call LockPubScreen(), etc.  You must handle
    cases where LockPubScreen(), etc. will fail.

    Note that this function may return the name of a public screen
    which is open but in "private mode" (see PubScreenStatus() and
    PSNF_PRIVATE).

    BUGS
    Due to a bug, your buffer needs to be (MAXPUBSCREENNAME + 1)
    characters big, which is one more than originally documented.

    The starting screen and cycle order of the public screens isn't
    defined, so do not draw conclusions about the order you
    see in the current version of Intuition.  We reserve the
    right to add meaning to the ordering at a future time.

    SEE ALSO
    OpenScreen(), Intuition V36 update documentation


intuition.library/OffGadget

    NAME
    OffGadget -- Disable the specified gadget.

    SYNOPSIS
    OffGadget( Gadget, Window, Requester )
           A0      A1      A2

    VOID OffGadget( struct Gadget *, struct Window *,
        struct Requester * );

    FUNCTION
    This command disables the specified gadget.  When a gadget is
    disabled, these things happen:
         - its imagery is displayed ghosted
         - the GFLG_DISABLED flag is set
         - the gadget cannot be selected by User

    The window parameter must point to the window which contains the
    gadget, or which contains the requester that contains the gadget.
    The requester parameter must only be valid if the gadget has the
    GTYP_REQGADGET flag set, a requirement for all requester gadgets.

       NOTE:  it's never safe to tinker with the gadget list yourself.  Don't
       supply some gadget that Intuition hasn't already processed in
       the usual way.

        NOTE: for compatibility reasons, this function will refresh all
    gadgets in a requester, and all gadgets from gadget to the
    end of the gadget list if gadget is in a window.

    If you want to improve on this behavior, you may perform the
    equivalent operation yourself: remove a gadget or gadgets,
    change the state of their GFLG_DISABLED flag, replace the
    gadgets using AddGList(), and selectively call RefreshGList().

    INPUTS
    Gadget = pointer to the gadget that you want disabled
    Window = pointer to a window structure containing the gadget or
        containing the requester which contains the gadget
    Requester = pointer to a requester (may by NULL if this isn't
           a requester gadget (i.e. GTYP_REQGADGET is not set)).

    RESULT
    None

    BUGS

    SEE ALSO
    OnGadget(), AddGadget(), RefreshGadgets()


intuition.library/OnGadget

    NAME
    OnGadget -- Enable the specified gadget.

    SYNOPSIS
    OnGadget( Gadget, Window, Requester )
          A0      A1      A2

    VOID OnGadget( struct Gadget *, struct Window *,
        struct Requester * );

    FUNCTION
    This command enables the specified gadget.  When a gadget is
    enabled, these things happen:
        - its imagery is displayed normally (not ghosted)
        - the GFLG_DISABLED flag is cleared
        - the gadget can thereafter be selected by the user

    The window parameter must point to the window which contains the
    gadget, or which contains the requester that contains the gadget
    The requester parameter must only be valid if the gadget has the
    GTYP_REQGADGET flag set, a requirement for all requester gadgets.

       NOTE:  it's never safe to tinker with the gadget list yourself.  Don't
       supply some gadget that Intuition hasn't already processed in
       the usual way.

        NOTE: for compatibility reasons, this function will refresh all
    gadgets in a requester, and all gadgets from gadget to the
    end of the gadget list if gadget is in a window.

    If you want to improve on this behavior, you may perform the
    equivalent operation yourself: remove a gadget or gadgets,
    change the state of their GFLG_DISABLED flag, replace the
    gadgets using AddGList(), and selectively call RefreshGList().

    INPUTS
    Gadget = pointer to the gadget that you want disabled
    Window = pointer to a window structure containing the gadget or
        containing the requester which contains the gadget
    Requester = pointer to a requester (may by NULL if this isn't
           a requester gadget (i.e. GTYP_REQGADGET is not set)).

    RESULT
    None

    BUGS
    Traditional gadgets are rendered very simply.  This can result
    in incomplete clearing away of the ghosting pattern when
    OnGadget() is used.  For example, a button whose imagery consists
    of an IntuiText inside a rectangular Border doesn't have the
    button interior cleared by OnGadget().  This is because OnGadget()
    clears the GFLG_DISABLED flag then redraws the gadget.  Redrawing
    this gadget consists of redrawing the border and text.  Nothing
    redraws the field.

    The solution to this type of problem is to either use a gadget
    whose imagery is a struct Image that covers the whole select area,
    or to manually remove the gadget, erase the gadget's select area
    (say using EraseRect()), then clear the GFLG_DISABLED flag,
    add the gadget back to the window, and refresh it.

    SEE ALSO
    OffGadget()


intuition.library/OpenScreen

    NAME
    OpenScreen -- Open an Intuition screen.

    SYNOPSIS
    Screen = OpenScreen( NewScreen )
    D0		     A0

    struct Screen *OpenScreen( struct NewScreen * );

    or

    struct Screen *OpenScreen( struct ExtNewScreen * );

    FUNCTION
    Opens an Intuition screen according to the specified parameters
    found in the NewScreen structure.

    Does all the allocations, sets up the screen structure and all
    substructures completely, and links this screen's viewport into
    Intuition's View structure.

    Before you call OpenScreen(), you must initialize an instance of
    a NewScreen structure.  NewScreen is a structure that contains
    all of the arguments needed to open a screen.  The NewScreen
    structure may be discarded immediately after OpenScreen() returns.

    The SHOWTITLE flag is set to TRUE by default when a screen is opened.
    To change this, you must call the routine ShowTitle().

    INPUTS
    NewScreen = pointer to an instance of a NewScreen structure.

    New for V36:
    In addition to the information contained in the NewScreen structure,
    Intuition now recognizes extended data passed in the form
    of an array of TagItem structures (from <utility/tagitem.h>),
    commonly called a "tag list."

    There are two ways to provide this array.  The first is to
    use the new Intuition entry point OpenScreenTagList() and
    pass the tag list as a parameter.  This is the recommended
    method, and has a convenient format variation for C programs
    using a variable number of arguments.

    An older way used for some V36 development uses the OpenScreen()
    entry point, and an extension of the NewScreen structure named
    ExtNewScreen.  See the documentation of the flag NS_EXTENDED,
    below.

    While we recommend that you use OpenScreenTagList() rather than
    OpenScreen() when using the extension tag list, we document
    the tag ID values here, so that all parameters for opening
    a screen can be found in one place.

    NewScreen is initialized with the following information:
    -------------------------------------------------------------
    Left = initial x-position of your screen (should be zero for
    releases prior to V36)

    Top = initial y-position of the opening screen
    (Note: Left and Top are specified relative to the Intuition's view,
    in same resolution as the screen pixels.)

    Width = the width for this screen's RastPort

    Height = the height for this screen's RastPort, or the constant
        STDSCREENHEIGHT to get the current default height (at
        this time guaranteed to be at least 200 rows).  The normal
        width and height for a particular system is stored by
        the graphics.library in GfxBase->NormalDisplayRows and
        GfxBase->NormalDisplayColumns.  These values will be different
        depending on factors such as PAL video and overscan.

        For V36, a new constant STDSCREENWIDTH is introduced.  It
        serves the similar function for screen width.  Both
        STDSCREENWIDTH and STDSCREENHEIGHT indicate that your
        screen RastPort is to be the same dimensions as your
        DisplayClip rectangle.  If you do not specify either a
        standard or custom DisplayClip, the OSCAN_TEXT region
        will be used, which corresponds to the standard dimensions
        of V35 and earlier.

        Furthermore, if you are using OpenScreenTagList(), and you
        specify STDSCREENWIDTH, and you DO NOT provide a NewScreen
        pointer, and you DO NOT provide sA_Left, then Intuition
        will automatically set the LeftEdge of the screen to
        be the left edge of the screen's DisplayClip region.
        Likewise for STDSCREENHEIGHT and the screen's TopEdge.

    Depth = number of bitplanes

    DetailPen = pen number for details (like gadgets or text in title bar)
        The common value for this pen is 0.

    BlockPen = pen number for block fills (like title bar)
        The common value for this pen is 1.

    Type = screen type values
        Set these flags as desired from the set:
        CUSTOMSCREEN -- this is your own screen, not a system screen.
        CUSTOMBITMAP -- this custom screen has bit maps supplied
        in the bitmap field of the NewScreen structure.  Intuition is
        not to allocate any raster bitmaps.
        SCREENBEHIND -- your screen will be created behind all other open
        screens.  This allows a program to prepare imagery in the
        screen, change its colors, and so on, bringing it to the
        front when it is presentable.
        SCREENQUIET -- Intuition will not render system screen gadgets or
        screen title.  In concert with the WFLG_RMBTRAP flag on all
        your screen's windows, this flag will prevent Intuition from
        rendering into your screen's bitplanes.  Without WFLG_RMBTRAP
        (or using the IDCMP_MENUVERIFY facility to cancel menu
        operations), this flag will prevent Intuition from clearing
        your menu bar, which is probably unacceptable.  The menu bar
        layer may still overwrite  a portion of your screen bitmap
        when the screen is opened.  (V36: it won't clobber your bits
        any more.)
        NS_EXTENDED for this screen to use extended attributes pointed
        to by the 'Extended' field, below.

    ViewModes = the appropriate argument for the data type ViewPort.Modes.
           These include:
           HIRES for this screen to be HIRES width.
           LACE for the display to switch to interlace.
           SPRITES for this screen to use sprites (the pointer
        sprite is always displayed)
           DUALPF for dual-playfield mode (not supported yet)
        [For V36: The ViewModes field is superseded by a TagItem with
        tag value SA_DisplayID.]

    Font = pointer to the default TextAttr structure for text in this
        screen and all windows that open in this screen.  Text that uses
        this TextAttr includes title bars of both screen and windows,
        string gadgets, and menu titles.  Of course, IntuiText that
        specifies a NULL TextAttr field will use the screen/window default
        fonts.  NOTE: Intuition will *NOT* call OpenDiskFont(), so
        the TextAttr you supply must be in memory.  The ways to ensure
        that are to either use a ROM font (Topaz 8 or 9) or first
        call OpenDiskFont() to load the font, and don't close it
        until after your screen is successfully opened.
        [For V36: this is superseded by SA_Font and SA_SysFont.]

    DefaultTitle = pointer to a line of text that will be displayed along
        the screen's title bar.  Null terminated, or just a NULL pointer
           to get no text
        [For V36: superseded by SA_Title.]

    Gadgets = This field should be set to NULL, since no user gadgets may
        be attached to a screen with the current versions of Intuition.

    CustomBitMap = if you're not supplying a custom bitmap, this value is
           ignored.  However, if you have your own display memory that you
           want used for this screen, the CustomBitMap field should point to
        the BitMap structure that describes your display memory.  See the
           "Screens" chapter and the "Amiga ROM Kernel Manual" for more
           information about bitmaps.
        [For V36: this is superseded by SA_BitMap.]

    [ All TagItem extensions below are new for V36.]
    Extension = if NS_EXTENDED is set in NewScreen.Type, this pointer
        should point to an array (or chain of arrays) of TagItems,
        as defined in the include file <utility/tagitem.h>.   This
        field is only defined in the structure ExtNewScreen.
        The values to use for TagItem.ti_Tag are defined below.  We
        recommend that V36-specific applications use the new Intuition
        entry point OpenScreenTagList(), rather than using this field.
        The ExtNewScreen structure is a convenient way to give V36
        Intuition some information that V34 and earlier Intuition will
        ignore.

        Each TagItem is an optional tagged data structure which identifies
        an additional parameter to OpenScreen().  The applicable tag ID
        values for TagItem.ti_Tag and their corresponding data follow.

        Several of the tag items are alternative (and overriding) versions
        to familiar fields in NewScreen.  (Defaults only apply if
        NewScreen == NULL).  They are:

    SA_Left
    SA_Top
    SA_Width
    SA_Height
        The defaults for the SA_Left, SA_Top, SA_Width, and
        SA_Height tags end up being a bit complex.  If none of
        these tags are specified, and no NewScreen structure is
        used, then the left/top/width/height correctly match the
        display clip of your screen (see SA_DClip and
        SA_Overscan).

        The difficulty comes with overscanned screens, because the
        normal value of SA_Left or SA_Top for such a screen may be
        non-zero.  If a NewScreen structure is supplied, then the
        left/top/width/height come originally from there.  If no
        NewScreen structure is supplied, but a non-default
        SA_Width (SA_Height) is specified, then SA_Left (SA_Top)
        defaults to zero instead.  In these cases, the left and
        top edge may not be what you want.

        If you need to specify explicit width or height, or supply
        a NewScreen, you must supply correct values for SA_Left
        and SA_Top.  The correct normal values are the display
        clip rectangle's MinX and MinY values respectively.  If
        you are using the SA_DClip tag, then you already have a
        rectangle to consult for these values.  If you are using
        SA_Overscan to get one of the standard overscan types, you
        may use QueryOverscan() to get a rectangle for that
        overscan type.

    SA_Depth (defaults to 1)
    SA_DetailPen (defaults to 0)
    SA_BlockPen (defaults to 1)
    SA_Title (defaults to NULL)
    SA_Font (defaults to NULL, meaning user's preferred monospace font)
    SA_BitMap (whose existence also implies CUSTOMBITMAP).

        Several tags are Booleans, which means that depending on whether
        their corresponding ti_Data field is zero (FALSE) or non-zero
        (TRUE), they specify Boolean attributes.  The ones corresponding
        to Boolean flags in the NewScreen.Type field are:

    SA_ShowTitle (defaults to TRUE)
    SA_Behind (equiv. to SCREENBEHIND) (defaults to FALSE)
    SA_Quiet (equiv. to SCREENQUIET) (defaults to FALSE)

        The following tags provide extended information to Intuition
        when creating a screen:

    SA_Type: ti_Data corresponds to the SCREENTYPE bits of the
        NewScreen.Type field.  This should be one of PUBLICSCREEN or
        CUSTOMSCREEN.  The other bits of the NewScreen.Type field
        must be set with the appropriate tags (SA_Behind, SA_Quiet,
        etc.)

    SA_DisplayID: ti_Data is a 32-bit extended display mode ID, as
      defined in the <graphics/modeid.h> include file (V39 and up)
      or in <graphics/displayinfo.h> (V37 and V38).

    SA_Overscan: ti_Data contains a defined constant specifying
        one of the system standard overscan dimensions appropriate for
        the display mode of the screen.  Used with the Width and
        Height dimensions STDSCREENWIDTH and STDSCREEN, this makes
        it trivial to open an overscanned or standard dimension
        screen.  You may also hand-pick your various dimensions
        for overscanned or other screens, by specifying screen position
        and dimensions explicitly, and by using SA_DClip to explicitly
        specify an overscanned DisplayClip region.

        The values for ti_Data of this tag are as follows:

        OSCAN_TEXT - Text Overscan region.  A region which is completely
        on screen and readable ("text safe").  A preferences data
        setting, this is backward equivalent with the old MoreRows,
        and specifies the DisplayClip and default dimensions of the
        Workbench screen.  This is the default.

        OSCAN_STANDARD - Also a preferences setting, this specifies
        a rectangle whose edges are "just out of view."  This yields
        the most efficient position and dimensions of on-monitor
        presentations, such as games and artwork.

        OSCAN_MAX - This is the largest rectangular region that the
        graphics library can handle "comfortably" for a given mode.
        Screens can smoothly scroll (hardware pan) within this region,
        and any DisplayClip or Screen region within this rectangle
        is also legal.  It is not a preferences item, but reflects
        the limits of the graphics hardware and software.

        OSCAN_VIDEO - This is the largest region that the graphics
        library can display, comfortable or not.  There is no guarantee
        that all smaller rectangles are valid.  This region is
        typically out of sight on any monitor or TV, but provides our
        best shot at "edge-to-edge" video generation.

        Remember, using overscan drastically effects memory use and
        chip memory bandwidth.  Always use the smallest (standard)
        overscan region that works for your application.

    SA_DClip: ti_Data is a pointer to a rectangle which explicitly
        defines a DisplayClip region for this screen.  See QueryOverscan()
        for the role of the DisplayClip region.

        Except for overscan display screens, this parameter is
        unnecessary, and specifying a standard value using SA_Overscan
        is normally an easier way to get overscan.

    SA_AutoScroll: this is a Boolean tag item, which specifies that
        this screens is to scroll automatically when the mouse pointer
        reaches the edge of the screen.  The operation of this requires
        that the screen dimensions be larger than its DisplayClip
        region.

    SA_PubName: If this field is present (and ti_Data is non-NULL),
        it means that the screen is a public screen, and that
        the public screen name string is pointed to by ti_Data.
        Public screens are opened in "PRIVATE" mode and must
        be made public using PubScreenStatus( screen, 0 ).

    SA_Pens: The ti_Data field (if non-NULL) points to a UWORD
        array of pen specification, as defined for struct DrawInfo.
        This array will be used to initialize the screen's
        DrawInfo.dri_Pens array.

        SA_Pens is also used to decide that a screen is ready
        to support the full-blown "new look" graphics.  If you
        want the 3D embossed look, you must provide this tag,
        and the ti_Data value cannot be NULL.  If it points
        to a "minimal" array, containing just the terminator ~0,
        you can specify "new look" without providing any values
        for the pen array.

        The way the DrawInfo pens are determined is Intuition
        picks a default pen-array.  Then, any pens you supply with
        SA_Pens override the defaults, up until the ~0 in your
        array.

        If the screen is monochrome or old-look, the default will
        be the standard two-color pens.

        If the screen is two or more planes deep, the default will
        be the standard four-color pens, which now include the
        new-look menu colors.

        If the screen has the SA_LikeWorkbench property, the
        default will be the user's preferred pen-array, changeable
        through preferences.

    The following two tag items specify the task and signal to be issued
    to notify when the last "visitor" window closes on a public screen.
    This support is to assist envisioned public screen manager programs.

    SA_PubTask:  Task to be signalled.  If absent (and SA_PubSig is
        valid), use the task which called OpenScreen() or
        OpenScreenTagList()).

    SA_PubSig:  Data is a UBYTE signal number (not flag) used to notify
        a task when the last visitor window closes on a public screen.

    SA_Colors: ti_Data points to an array of ColorSpec structures
        (terminated with ColorIndex = -1) which specify initial
        values of the screen's color palette.

    SA_FullPalette: this is a Boolean attribute.  Prior to V36, there
        were just 7 RGB color values that Intuition maintained
        in its user preferences (playfield colors 0-3, and colors
        17-19 for the sprite).  When opening a screen, the color
        map for the screens viewport is first initialized by
        graphics (graphics.library/GetColorMap()) then these
        seven values are overridden to take the preferences values.

        In V36, Intuition maintains a full set of 32 preferences colors.
        If you specify TRUE for SA_FullPalette, Intuition will
        override ALL color map entries with its full suite of
        preferred colors.  (Defaults to FALSE).

    SA_ErrorCode: ti_Data points to a ULONG in which Intuition will
        stick an extended error code if OpenScreen[TagList]() fails.
        Values are of this include 0, for success, and:
        OSERR_NOMONITOR	- monitor for display mode not available.
        OSERR_NOCHIPS	- you need newer custom chips for display mode.
        OSERR_NOMEM		- couldn't get normal memory
        OSERR_NOCHIPMEM	- couldn't get chip memory
        OSERR_PUBNOTUNIQUE	- public screen name already used
        OSERR_UNKNOWNMODE	- don't recognize display mode requested
        OSERR_TOODEEP	- screen too deep to be displayed on
                  this hardware (V39)
        OSERR_ATTACHFAIL	- An illegal attachment of screens was
                  requested (V39)

        NOTE: These values are not the same as some similar return
        values defined in graphics.library/ModeNotAvailable().

    SA_SysFont: ti_Data selects one of the system standard fonts
        specified in preferences.  This tag item overrides the
        NewScreen.Font field and the SA_Font tag item.

        Values recognized in ti_Data at present are:
        0 - old DefaultFont, fixed-width, the default.
        1 - Workbench screen preferred font.  You have to
            be very font sensitive to handle a proportional or
            larger than traditional screen font.

        NOTE WELL: if you select sysfont 1, windows opened on
        your screen will not inherit the screen font, but rather
        the window RastPort will be initialized to the old-style
        DefaultFont (sysfont 0).

    Attached screen tags:  V39 supports attached screens, where
        one or more child screens can be associated with a parent
        screen.  Attached screens depth-arrange as a group, and
        always remain adjacent depth-wise.  Independent
        depth-arrangement of child screens is possible through
        the V39 ScreenDepth() call.  If a child screen is
        made non-draggable through {SA_Draggable, FALSE}, then
        it will drag exclusively with the parent.  Normal child
        screens drag independently of the parent, but are pulled
        down when the parent is.  Use the SA_Parent, SA_FrontChild,
        and SA_BackChild tags to attach screens.

    SA_Parent:  If you wish to attach this screen to an
        already-open parent screen, use this tag and set
        ti_Data to point to the parent screen.  See also
        SA_FrontChild and SA_BackChild.  (V39).

    SA_FrontChild:  If you wish to attach an already-open child
        screen to this screen, set ti_Data to point to the child
        screen.  The child screen will come to the front of the
        family defined by the parent screen you are opening.  See
        also SA_Parent and SA_BackChild.  (V39)

    SA_BackChild:  If you wish to attach an already-open child
        screen to this screen, set ti_Data to point to the child
        screen.  The child screen will go to the back of the family
        defined by the parent screen you are opening.  See also
        SA_Parent and SA_FrontChild.  (V39)

    SA_BackFill:  ti_Data is a pointer to a backfill hook for
        the screen's Layer_Info.
        (see layers.library/InstallLayerInfoHook()).  (V39).

    SA_Draggable:  ti_Data is a boolean.  Set to FALSE if you
        wish your screen to be non-draggable.  This tag should be
        used very sparingly!.  Defaults to TRUE.  For child screens
        (see SA_Parent, SA_FrontChild, and SA_BackChild) this tag
        has a slightly different meaning:  non-draggable child
        screens are non-draggable with respect to their parent,
        meaning they always drag exactly with the parent, as
        opposed to having relative freedom.  Also see
        ScreenPosition().  (V39)

    SA_Exclusive:  ti_Data is a boolean.  Set to TRUE if you
        never want your screen to share the display with another
        screen.  This means that your screen can't be pulled down,
        and will not appear behind other screens that are pulled
        down.  Your screen may still be depth arranged, though.  Use
        this tag sparingly!  Defaults to FALSE.  Starting with V40,
        attached screens may be SA_Exclusive.  Setting SA_Exclusive
        for each screen will produce an exclusive family.  (V39).

    SA_SharePens:  For those pens in the screen's
        DrawInfo->dri_Pens, Intuition obtains them in shared mode
        (see graphics.library/ObtainPen()).  For compatibility,
        Intuition obtains the other pens of a public screen as
        PENF_EXCLUSIVE.  Screens that wish to manage the pens
        themselves should generally set this tag to TRUE.  This
        instructs Intuition to leave the other pens unallocated.
        Defaults to FALSE.  (V39).

    SA_Colors32:  Tag to set the screen's initial palette colors
        at 32 bits-per-gun.  ti_Data is a pointer to a table to be
        passed to the graphics.library/LoadRGB32() function.  This
        format supports both runs of color registers and sparse
        registers.  See the autodoc for that function for full
        details.  Any color set here has precedence over the same
        register set by SA_Colors.  (V39).

    SA_Interleaved:  ti_Data is a boolean.  Set to TRUE to
        request an interleaved bitmap for your screen.  Defaults to
        FALSE.  If the system cannot allocate an interleaved bitmap for
        you, it will attempt to allocate a non-interleaved one (V39).

    SA_VideoControl:  ti_Data points to a taglist that will be
        passed to VideoControl() after your screen is open.  You
        might use this to turn on border-sprites, for example.
        (V39).

    SA_ColorMapEntries:  ti_Data is the number of entries that
        you wish Intuition to allocate for this screen's ColorMap.
        While Intuition allocates a suitable number for ordinary
        use, certain graphics.library features require a
        ColorMap which is larger than default.  (The default value is
        1<<depth, but not less than 32).  (V39)

    SA_LikeWorkbench:  ti_Data is boolean.  Set to TRUE to get
        a screen just like the Workbench screen.  This is the
        best way to inherit all the characteristics of the
        Workbench, including depth, colors, pen-array, screen mode,
        etc.  Individual attributes can be overridden through the
        use of tags.  (SA_LikeWorkbench itself overrides things
        specified in the NewScreen structure).  Attention
        should be paid to hidden assumptions when doing this.  For
        example, setting the depth to two makes assumptions about
        the pen values in the DrawInfo pens.  Note that this
        tag requests that Intuition ATTEMPT to open the screen
        to match the Workbench.  There are fallbacks in case
        that fails, so it is not correct to make enquiries about
        the Workbench screen then make strong assumptions about
        what you're going to get.  (Defaults to FALSE).  (V39)

     SA_MinimizeISG:  ti_Data is boolean.  For compatibility,
        Intuition always ensures that the inter-screen gap is at
        least three non-interlaced lines.  If your application
        would look best with the smallest possible inter-screen
        gap, set ti_Data to TRUE.  If you use the new graphics
        VideoControl() VC_NoColorPaletteLoad tag for your screen's
        ViewPort, you should also set this tag.  (V40)

    RESULT
    If all is well, returns the pointer to your new screen
    If anything goes wrong, returns NULL, with further error
    specification in the variable pointed to by the SA_ErrorCode
    data field (V36 and later).

    NOTES
    By default, AmigaDOS requesters related to your process are put on
    the Workbench screen (these are messages like "Disk Full").  If
    you wish them to show up on custom screens, DOS must be told.
    This fragment shows the procedure.  More information is available
    in the AmigaDOS manuals.  Sample code fragment:

    #include "libraries/dosextens.h"
        ...
    struct Process	*process;
    struct Window	*window;
    APTR		temp;
        ...
        process = (struct Process *) FindTask(NULL);
        temp = process->pr_WindowPtr;	(save old value)
        process->pr_WindowPtr = (APTR) window;
        ( use a pointer to any open window on your screen )
            ...
        your code goes here
            ...
        process->pr_WindowPtr = temp;
        ( restore value BEFORE CloseWindow() )
        CloseWindow(window);

    A VERY IMPORTANT NOTE about the Screen->BitMap.  In the future,
    bitmaps will need to grow.  The embedded instance of a bitmap
    in the screen will no longer be large enough to hold the whole
    description of the bitmap.

    YOU ARE STRONGLY URGED to use Screen->RastPort.BitMap in place of
    &Screen->BitMap whenever and whereever possible.

    BUGS

    SEE ALSO
    OpenScreenTagList(), OpenWindow(), PrintIText(), CloseScreen(),
    QueryOverscan() PubScreenStatus(), The Intuition Reference Manual,
    utility/tagitem.h, graphics.library/ModeNotAvailable(),
    diskfont.library/OpenDiskFont(), graphics.library/GetColorMap()


intuition.library/OpenScreenTagList

   NAME
    OpenScreenTagList -- OpenScreen() with TagItem extension array. (V36)
    OpenScreenTags -- Varargs stub for OpenScreenTagList. (V36)

   SYNOPSIS
    Screen = OpenScreenTagList( NewScreen, TagItems )
    D0	  		    A0         A1

    struct Screen *OpenScreenTagList( struct NewScreen *,
        struct TagItem * );

    Screen = OpenScreenTags( NewScreen, Tag1, ... )

    struct Screen *OpenScreenTags( struct NewScreen *,
        ULONG, ... );

   FUNCTION
    Provides an extension to the parameters passed to OpenScreen().
    This extensions is in the form of (a pointer to) an array of
    TagItem structures, which have to fields: ti_Tag, an ID identifying
    the meaning of the other field, ti_Data.  See <utility/tagitem.h>.

    The tag items can supplement or override the values in NewScreen.
    In fact, you can pass a NULL value of the NewScreen pointer.
    For that matter, if you pass NULL in both arguments, you'll get
    a screen with defaults in all fields, including display mode,
    depth, colors, dimension, title, and so on.  We ask that
    you at least supply a title when you open a screen.

    See OpenScreen() documentation for parameter specifications.

   INPUTS
     NewScreen     - (optional) pointer to a NewScreen structure.
     TagItems      - (optional) pointer to (an array of) TagItem
            structures, terminated by the value TAG_END.

   RESULT
     Screen	- an open Intuition screen.  See OpenScreen() for
        extended error codes when Screen is returned NULL.

   EXAMPLE
    The version using a variable number of arguments must be
    created for each particular compiler, and may not have
    an analogue in all versions.  For vanilla, 32-bit C
    parameter passing conventions, this works (and will
    appear in amiga.lib):

    struct Screen	*
    OpenScreenTags( ns, tag1 )
    struct NewScreen	*ns;
    ULONG			tag1;
    {
        struct Screen	*OpenScreenTagList();

        return ( OpenScreenTagList( ns, (struct TagItem *) &tag1 ) );
    }

   NOTES
    We recommend this extension to OpenScreen() over using the
    field ExtNewScreen.Extension.  However, the ExtNewScreen.Extension
    is a convenient way to supply a few tags to V36 Intuition which
    will be ignored by V34 Intuition.  See OpenScreen() documentation
    for lots of details.

    A VERY IMPORTANT NOTE about the Screen->BitMap.  In the future,
    bitmaps will need to grow.  The embedded instance of a bitmap
    in the screen will no longer be large enough to hold the whole
    description of the bitmap.

    YOU ARE STRONGLY URGED to use Screen->RastPort.BitMap in place of
    &Screen->BitMap whenever and whereever possible.

   BUGS

   SEE ALSO
    OpenScreen()


intuition.library/OpenWindow

    NAME
    OpenWindow -- Open an Intuition window.

    SYNOPSIS
       Window = OpenWindow( NewWindow )
    D0                   A0

    struct Window *OpenWindow( struct NewWindow * );

    FUNCTION
    Opens an Intuition window of the given dimensions and position,
    with the properties specified in the NewWindow structure.
    Allocates everything you need to get going.

    New for V36: there is an extensive discussion of public Screens
    and visitor windows at the end of this section.  Also,
    you can provide extensions to the NewWindow parameters using
    and array of TagItem structures.  See the discussion below,
    and the documentation for the function OpenScreenTagList().

    Before you call OpenWindow(), you must initialize an instance of
    a NewWindow structure.  NewWindow is a structure that contains
    all of the arguments needed to open a window.  The NewWindow
    structure may be discarded immediately after it is used to open
    the window.

    If Type == CUSTOMSCREEN, you must have opened your own screen
    already via a call to OpenScreen().  Then Intuition uses your screen
    argument for the pertinent information needed to get your window
    going.  On the other hand, if type == one of the Intuition's standard
    screens, your screen argument is ignored.  Instead,
    Intuition will check to see whether or not that screen
    already exists:  if it doesn't, it will be opened first before
    Intuition opens your window in the standard screen.

    New for V36: If you specify Type == WBENCHSCREEN, then your
    window will appear on the Workbench screen, unless the global
    public screen mode SHANGHAI is set, in which case your window
    will be "hijacked" to the default public screen.  See also
    SetPubScreenModes().

    New for V36: If the WFLG_NW_EXTENDED flag is set, it means that the
    field 'ExtNewWindow->Extension' points to an array of TagItems, as
    defined in intuition/tagitem.h.  This provides an extensible means
    of providing extra parameters to OpenWindow.  For compatibility
    reasons, we could not add the 'Extension' field to the NewWindow
    structure, so we have define a new structure ExtNewWindow, which
    is identical to NewWindow with the addition of the Extension field.

    We recommend that rather than using ExtNewWindow.Extension, you
    use the new Intuition function OpenWindowTagList() and its
    varargs equivalent OpenWindowTags().  We document the window
    attribute tag ID's (ti_Tag values) here, rather than in
    OpenWindowTagList(), so that you can find all the parameters
    for a new window defined in one place.

    If the WFLG_SUPER_BITMAP flag is set, the bitmap variable must point
    to your own bitmap.

    The DetailPen and the BlockPen are used for system rendering; for
    instance, the title bar is first filled using the BlockPen, and then
    the gadgets and text are rendered using DetailPen.  You can either
    choose to supply special pens for your window, or, by setting either
    of these arguments to -1, the screen's pens will be used instead.

    Note for V36: The DetailPen and BlockPen no longer determine
    what colors will be used for window borders, if your window
    opens on a "full-blown new look screen."

    INPUTS
    NewWindow = pointer to an instance of a NewWindow structure.  That
               structure is initialized with the following data:
   -------------------------------------------------------------------------
    Left = the initial x-position for your window
    Top = the initial y-position for your window
    Width = the initial width of this window
    Height = the initial height of this window

    DetailPen = pen number (or -1) for the rendering of window details
         (like gadgets or text in title bar)
    BlockPen = pen number (or -1) for window block fills (like title bar)
    [For V36: Title bar colors are determined otherwise.]

    Flags = specifiers for your requirements of this window, including:
         which system gadgets you want attached to your window:

        - WFLG_DRAGBAR allows this window to be dragged
        - WFLG_DEPTHGADGET lets the user depth-arrange this window
        - WFLG_CLOSEGADGET attaches the standard close gadget
        - WFLG_SIZEGADGET allows this window to be sized.

        If you ask for the WFLG_SIZEGADGET gadget, you must specify one or
        both of the flags WFLG_SIZEBRIGHT and WFLG_SIZEBBOTTOM below; if
        you don't, the default is WFLG_SIZEBRIGHT.  See the following items
        WFLG_SIZEBRIGHT and WFLG_SIZEBBOTTOM for more details.

        - WFLG_SIZEBRIGHT is a special system gadget flag that
          you set to specify whether or not you want the
          RIGHT border adjusted to account for the physical size
          of the sizing gadget.  The sizing gadget must, after
          all, take up room in either the right or bottom border
          (or both, if you like) of the window.  Setting either
          this or the WFLG_SIZEBBOTTOM flag selects which edge
          will take up the slack.  This will be particularly
          useful to applications that want to use the extra space
          for other gadgets (like a proportional gadget and two
          Booleans done up to look like scroll bars) or, for
          for instance, applications that want every possible
          horizontal bit and are willing to lose lines vertically.
          NOTE:  if you select WFLG_SIZEGADGET, you must select
          either WFLG_SIZEBRIGHT or WFLG_SIZEBBOTTOM or both.  If
          you select neither, the default is WFLG_SIZEBRIGHT.
        - WFLG_SIZEBBOTTOM is a special system gadget flag that
          you set to specify whether or not you want the
          BOTTOM border adjusted to account for the physical size
          of the sizing gadget.  For details, refer to
          WFLG_SIZEBRIGHT above.

        - WFLG_GIMMEZEROZERO for easy but expensive output

        what type of window layer you want, either:
        - WFLG_SIMPLE_REFRESH
        - WFLG_SMART_REFRESH
        - WFLG_SUPER_BITMAP

        - WFLG_BACKDROP for whether or not you want this window to be one
          of Intuition's special backdrop windows.  See WFLG_BORDERLESS
          as well.

        - WFLG_REPORTMOUSE for whether or not you want to "listen" to
          mouse movement events whenever your window is the active
          one.  After you've opened your window, if you want to change
          you can later change the status of this via a call to
          ReportMouse().  Whether or not your window is listening to
          mouse is affected by gadgets too, since they can cause you
          to start getting reports too if you like.  The mouse move
          reports (either InputEvents or messages on the IDCMP) that
          you get will have the x/y coordinates of the current mouse
          position, relative to the upper-left corner of your window
          (WFLG_GIMMEZEROZERO notwithstanding).  This flag can work in
          conjunction with the IDCMP Flag called IDCMP_MOUSEMOVE, which
          allows you to listen via the IDCMP.

        - WFLG_BORDERLESS should be set if you want a window with no
          border padding.  Your window may have the border variables
          set anyway, depending on what gadgetry you've requested for
          the window, but you won't get the standard border lines and
          spacing that comes with typical windows.

          This is a good way to take over the entire screen, since you
          can have a window cover the entire width of the screen using
          this flag.  This will work particularly well in conjunction
          with the WFLG_BACKDROP flag (see above), since it allows you
          to open a window that fills the ENTIRE screen.  NOTE:  this is
          not a flag that you want to set casually, since it may cause
          visual confusion on the screen.  The window borders are the
          only dependable visual division between various windows and
          the background screen.  Taking away that border takes away
          that visual cue, so make sure that your design doesn't need
          it at all before you proceed.

        - WFLG_ACTIVATE is the flag you set if you want this window to
          automatically become the active window.  The active
          window is the one that receives input from the keyboard and
          mouse.  It's usually a good idea to to have the window you
          open when your application first starts up be an ACTIVATED
          one, but all others opened later not be ACTIVATED (if the
          user is off doing something with another screen, for
          instance, your new window will change where the input is
          going, which would have the effect of yanking the input rug
          from under the user).  Please use this flag thoughtfully and
          carefully.

          Some notes: First, your window may or may not be active
          by the time this function returns.  Use the IDCMP_ACTIVEWINDOW
          IDCMP message to know when your window has become active.
          Also, be very careful not to mistakenly specify the
          obsolete flag names WINDOWACTIVE or ACTIVEWINDOW.  These are
          used in other contexts, and their values unintentionally added
          to your flags can cause most unfortunate results.  To avoid
          confusion, they are now know as WFLG_WINDOWACTIVE and
          IDCMP_ACTIVEWINDOW.

        - WFLG_RMBTRAP, when set, causes the right mouse button events
          to be trapped and broadcast as events.  You can receive
          these events through either the IDCMP or the console.

        - WFLG_NOCAREREFRESH indicates that you do not wish to
          be responsible for calling BeginRefresh() and EndRefresh()
          when your window has exposed regions (i.e., when the
          IDCMP_REFRESHWINDOW message would be generated).  See also
          the descriptions of these two functions.

        - WFLG_NW_EXTENDED (V36) indicates that NewWindow in fact points
          to an ExtNewWindow structure, and that the 'Extension'
          field points to an array of TagItem structures, with
          meaning described below.

        - WFLG_NEWLOOKMENUS (V39) Requests new-look menu treatment.
          Menu colors are derived from the screen DrawInfo BARDETAILPEN,
          BARBLOCKPEN, and BARTRIMPEN, instead of window detail and
          block pens.  Also requests that a suitably scaled and colored
          Amiga-key symbol and checkmark symbol be used in the menus.
          Applications using WFLG_NEWLOOKMENUS need to use the new screen
          DrawInfo pens to color their MenuItem and SubItem imagery.
          If your application uses GadTools, the {GTMN_NewLookMenus,TRUE}
          tag-item should be passed to the menu layout calls.

          (NB: For the menus to actually appear with improved colors,
          the screen's opener must supply suitable values for the
          new menu pens in the DrawInfo.  If this is not the case,
          then an application requesting NewLookMenus will get the
          scaled Amiga-key and checkmark but in V37-compatible colors.
          Note that the screen's DrawInfo will always contain valid
          values for the new pens;  they just may correspond to the
          "old look").

    IDCMPFlags = IDCMP is the acronym for Intuition Direct Communications
        Message Port.  (It's Intuition's sole acronym.) If any of the
        IDCMP Flags is selected, Intuition will create a pair of
        message ports and use them for direct communications with the
        task opening this window (as compared with broadcasting
        information via the Console device).  See the "Input and
        Output Methods" chapter of the Intuition Reference Manual for
        complete details.

        You request an IDCMP by setting any of these flags.  Except
        for the special VERIFY flags, every other flag you set tells
        Intuition that if a given event occurs which your program
        wants to know about, it is to broadcast the details of that
        event through the IDCMP rather than via the Console device.
        This allows a program to interface with Intuition directly,
        rather than going through the Console device.

        Many programs have elected to use IDCMP communication
        exclusively, and not to associate a console with their
        windows at all.  Some operations, such as IDCMP_MENUVERIFY,
        can ONLY be achieved using IDCMP.

           The IDCMP flags you can set are described in the
        ModifyIDCMP() autodoc.

    Gadgets = the pointer to the first of a linked list of the your own
          Gadgets which you want attached to this Window.  Can be NULL
          if you have no Gadgets of your own

       CheckMark = a pointer to an instance of the struct Image where can
          be found the imagery you want used when any of your
          menu items is to be checkmarked.  If you don't want to
          supply your own imagery and you want to just use
          Intuition's own checkmark, set this argument to NULL

       Text = a null-terminated line of text to appear on the title bar of
          your window (may be null if you want no text)

       Type = the screen type for this window.  If this equal CUSTOMSCREEN,
          you must have already opened a CUSTOMSCREEN (see text above).
          Types available include:
          - WBENCHSCREEN
          - CUSTOMSCREEN
          - PUBLICSCREEN (new for V36, see text below)

       Screen = if your type is one of Intuition's standard screens, then
          this argument is ignored.  However, if Type == CUSTOMSCREEN,
          this must point to the structure of your own screen

       BitMap = if you have specified WFLG_SUPER_BITMAP as the type of
           refreshing you want for this window, then this value points to a
           instance of the struct bitmap.  However, if the refresh type
           is NOT WFLG_SUPER_BITMAP, this pointer is ignored.

       MinWidth, MinHeight, MaxWidth, MaxHeight = the size limits for this
          window.  These must be reasonable values, which is to say that
          the minimums cannot be greater than the current size, nor can
          the maximums be smaller than the current size.  If they are,
          they're ignored.  Any one of these can be initialized to zero,
          which means that that limit will be set to the current
          dimension of that axis.  The limits can be changed after the
          Window is opened by calling the WindowLimits() routine.

          NOTE: ORIGINALLY, we stated that:

          "If you haven't requested the WFLG_SIZEGADGET option, these
          variables are ignored so you don't have to initialize them."

          It is now clear that a variety of programs take it upon
          themselves to call SizeWindow() (or ChangeWindowBox()) without
          your program's consent or consulting your WFLG_SIZEGADGE
          option.  To protect yourself against the results, we strongly
          urge that if you supply suitable values for these fields even
          if you do not specify WFLG_SIZEGADGET.

          The maximums may be LARGER than the current size, or even
          larger than the current screen.  The maximums should be set to
          the highest value your application can handle.  This allows
          users with larger display devices to take full advantage of
          your software.  If there is no good reason to limit the size,
          then don't.  -1 or ~0 indicates that the maximum size is only
          limited by the size of the window's screen.

          See also the docs on the function WindowLimits() for more
          information.

       Extension (New for V36) = a pointer to an array (or chain of arrays)
        of TagItems to specify additional parameters to OpenWindow().
        TagItems in general are described in utility/tagitem.h,
        and the OpenWindow tags are defined in intuition/intuition.h
        and described here.  For items pertaining to Public Screens
        and visitor windows, please see below.

    Here are the TagItem.ti_Tag values that are defined for OpenWindow
    (and OpenWindowTagList()).

    Certain tags simply override equivalent values in NewWindow,
    and allow you to open a window using OpenWindowTagList() without
    having a NewWindow structure at all.  In each case, cast
    the corresponding data to ULONG and put it in ti_Data.

    The compatible tag items include:

    WA_Left
    WA_Top
    WA_Width
    WA_Height
    WA_DetailPen	- NOTE: only overrides NewWindow.DetailPen of -1!
    WA_BlockPen	- NOTE: only overrides NewWindow.BlockPen of -1!
    WA_IDCMP
    WA_Flags	- initial values for Flags before looking at other
              Boolean component Tag values
    WA_Gadgets
    WA_Title
    WA_CustomScreen	- also implies CUSTOMSCREEN property
    WA_SuperBitMap	- also implies WFLG_SUPER_BITMAP refresh mode.
    WA_MinWidth
    WA_MinHeight
    WA_MaxWidth
    WA_MaxHeight

    These Boolean tag items are alternatives to the NewWindow.Flags
    Boolean attributes with similar names.

    WA_SizeGadget		- equivalent to WFLG_SIZEGADGET
    WA_DragBar		- equivalent to WFLG_DRAGBAR
    WA_DepthGadget		- equivalent to WFLG_DEPTHGADGET
    WA_CloseGadget		- equivalent to WFLG_CLOSEGADGET
    WA_Backdrop		- equivalent to WFLG_BACKDROP
    WA_ReportMouse		- equivalent to WFLG_REPORTMOUSE
    WA_NoCareRefresh	- equivalent to WFLG_NOCAREREFRESH
    WA_Borderless		- equivalent to WFLG_BORDERLESS
    WA_Activate		- equivalent to WFLG_ACTIVATE
    WA_RMBTrap		- equivalent to WFLG_RMBTRAP
    WA_WBenchWindow		- equivalent to WFLG_WBENCHWINDOW
                  (system PRIVATE)
    WA_SimpleRefresh 	- only specify if TRUE
    WA_SmartRefresh 	- only specify if TRUE
    WA_SizeBRight		- equivalent to WFLG_SIZEBRIGHT
    WA_SizeBBottom		- equivalent to WFLG_SIZEBBOTTOM
    WA_GimmeZeroZero 	- equivalent to WFLG_GIMMEZEROZERO
    WA_NewLookMenus		- equivalent to WFLG_NEWLOOKMENUS

    The following tag items specify new attributes of a window.

    WA_ScreenTitle - You can specify the screen title associated
        with your window this way, and avoid a call to SetWindowTitles()
        when your window opens.

    WA_AutoAdjust - a Boolean attribute which says that it's OK
        to move or even shrink the dimensions of this window
        to fit it on the screen, within the dimension
        limits specified by MinWidth and MinHeight.
        Someday, this processing might be sensitive to the
        currently visible portion of the screen the window
        will be opening on, so don't draw too many conclusions
        about the auto-adjust algorithms.
        (Normally, this attribute defaults to FALSE.  However,
        if you call OpenWindowTags() or OpenWindowTagList()
        with a NULL NewWindow pointer, this attribute defaults
        to TRUE).

    WA_InnerWidth
    WA_InnerHeight - You can specify the dimensions of the interior
        region of your window, independent of what the border
        thicknesses will be.  You probably want to specify
        WA_AutoAdjust to allow Intuition to move your window
        or even shrink it so that it is completely on screen.

        Note: using these tags puts some reasonable restrictions
        on the gadgets you can specify as "border" gadgets when
        you open your window.  Since border gadgets determine
        the border dimensions and hence the overall dimensions of
        your window, those dimensions cannot be used calculating
        the position or dimensions of border gadgets.

        Here's the complete list of restrictions:
        - GACT_LEFTBORDER gadgets cannot be GFLG_RELWIDTH if
          WA_InnerWidth is used.
        - GACT_RIGHTBORDER gadgets MUST be GFLG_RELRIGHT if
          WA_InnerWidth is used.
        - GACT_TOPBORDER gadgets cannot be GFLG_RELHEIGHT if
          WA_InnerHeight is used.
        - GACT_BOTTOMBORDER gadgets MUST be GFLG_RELBOTTOM if
          WA_InnerHeight is used.

    WA_PubScreenName - This tag item declares that you want your window
        to open as a visitor window on the public screen whose name
        is pointed to by (UBYTE *) ti_Data.

    WA_PubScreen - Open as a visitor window on the public screen
        whose address if provided as (struct Screen *) ti_Data.
        To ensure that this screen remains open long enough, you
        must either:
        1) Be the screen's owner
        2) have another window already open on the screen
        3) use LockPubScreen()
        Using exec.library/Forbid() is not sufficient.

        You can provide ti_Data to be NULL (zero), without any
        of the above precautions, to specify the default public screen.

    WA_PubScreenFallBack - This Boolean attribute specifies that a
        visitor window should "fall back" to opening on the default
        public screen if the explicitly specify public screen is not
        available.

    WA_WindowName - this visionary specification of a window
        rendezvous name string is not yet implemented.

    WA_Colors - this equally great idea about associating a palette
        specification with the active window may not ever be implemented.

    WA_Zoom - ti_Data points to an array of four WORD's to be used
        as the initial Left/Top/Width/Height of the "alternate
        Zoom position and dimensions."  The presence of this tag
        item implies that you want a Zoom gadget, even though you
        might not have a sizing gadget.
        New for V39: if the initial zoom-box left and top are
        both set to ~0, then Intuition will give your window
        "size-only" zooming, meaning that zooming the window
        will not affect the left/top unless the window needs
        to be moved on-screen.

    WA_MouseQueue - This tag specifies a limit for the number
        of outstanding IDCMP_MOUSEMOVE IntuiMessages that Intuition
        will send to your window.  You can change the value of this
        limit after the window is open using SetMouseQueue().

    WA_RptQueue - This tag specifies a limit for the number of
        outstanding repeated-IDCMP_RAWKEY, repeated-IDCMP_VANILLAKEY,
        and repeated-IDCMP_IDCMPUPDATE IntuiMessages that Intuition will
        send to your window.  Currently, there is no function to adjust
        the repeat-key queue.

    WA_BackFill - ti_Data is a pointer to a Hook structure that
        the Layers library will call when your window needs
        "backfilling."  See layers.library/InstallLayerHook().

     WA_MenuHelp - ti_Data is a boolean.  If true, enables the MenuHelp
        feature for this window.  See IDCMP_MENUHELP above.  (V37)

    WA_NotifyDepth - ti_Data is a boolean.  Set to true if you
        would also like IDCMP_CHANGEWINDOW events sent to your window
        when it is depth-arranged.  Normally, such events are only
        sent for movement or resizing of the window.
        IDCMP_CHANGEWINDOW events originating from
        depth-arrangement have a Code equal to CWCODE_DEPTH, as
        opposed to CWCODE_MOVESIZE.  (V39)

    WA_Checkmark - (ti_Data is struct Image *) Image to use as a
        checkmark in menus.  Prior to V39, or if WA_NewLookMenus
        is not specified, the default will be the traditional
        checkmark in the original colors.  Under V39 and higher,
        if you have requested WA_NewLookMenus then the default will
        be an appropriately colored checkmark scaled to the screen's
        font.  Alternately, you can provide a custom one, which you
        can design yourself or get from sysiclass (use this if
        your menu-font is different from the screen's font).

    WA_AmigaKey - (ti_Data is struct Image *) Image to use as
        the Amiga-key symbol in menus.  If WA_NewLookMenus is not
        specified, the default will be the traditional Amiga-key
        symbol in the original colors.  If you've requested
        WA_NewLookMenus, then the default will be an appropriately
        colored Amiga-key scaled to the screen's font.
        Alternately, you can provide a custom one, which you can
        design yourself or get from sysiclass (use this if your
        menu-font is different from the screen's font).  (V39)

    WA_Pointer - (APTR) The pointer you wish to associate with
        your window.  If NULL, you are requesting the Preferences
        default pointer.  Custom pointers should be allocated by
        performing a NewObject() on "pointerclass".  (See
        <intuition/pointerclass.h>).  Defaults to NULL.  This tag is
        also recognized by SetWindowPointerA().  (V39)

    WA_BusyPointer (BOOL) - Set to TRUE to request the Preferences
        busy-pointer.  If FALSE, your pointer will be as requested
        by WA_Pointer.  Defaults to FALSE.  This tag is also
        recognized by SetWindowPointerA().  (V39)

    WA_PointerDelay - (BOOL) Set to TRUE to defer changing your
        pointer for a brief instant.  This is typically used along
        with setting the busy pointer, especially when the
        application knows it may be busy for a very short while.  If
        the application clears the pointer or sets another pointer
        before the delay expires, the pending pointer change is
        cancelled.  This reduces short flashes of the busy pointer.
        This tag is also recognized by SetWindowPointerA().  (V39)

    WA_HelpGroup - (ULONG) Normally, only the active window can
        receive IDCMP_GADGETHELP messages.  However, an application
        with multiple windows will want all its windows to be able
        to receive help when any of them are active.  First obtain a
        unique help ID with utility.library/GetUniqueID(), then
        pass it as ti_Data of this tag to all your windows.  See
        HelpControl().  (V39)

    WA_HelpGroupWindow - (struct Window *) Instead of using
        WA_HelpGroup, you can pass a pointer to another window
        whose HelpGroup you wish this window to belong to.  (V39)

    WA_TabletMessages - (BOOL) Set to TRUE to request extended
        IntuiMessages for your window.  If a tablet driver is
        generating IESUBCLASS_NEWTABLET input events, you will be
        able to receive extended tablet information with most
        IntuiMessages.  See the eim_TabletData field of the
        ExtIntuiMessage structure.  Defaults to FALSE.  (V39)

   NOTES
    Regarding Public Screens, you can specify a window to be a
    "visitor window" on a public screen in one of several ways.
    In each case, you must be sure not to specify a NewWindow
    type of CUSTOMSCREEN.  You should use the value PUBLICSCREEN.

    There are actually several ways you can specify which screen
    you want a visitor window to be opened on:

        1) Specify the name of the public screen WA_PubScreenName,
        or a NULL pointer, in ti_Data.  The name might have been
        provided by the user.  A NULL pointer means to use the
        default public screen.

        If the named screen cannot be found, the default public screen
        will be used if the Boolean attribute WA_PubScreenFallBack
        is TRUE.

        2) Specify a pointer to a public screen using the
        WA_PubScreen tag item.  The WA_PubScreenFallBack
        attribute has no effect.  You can specify the default
        public screen by providing a NULL pointer.

        You can also specify the pointer by setting NewWindow.Type
        to PUBLICSCREEN, and specifying the public screen pointer
        in NewWindow.Screen.  The WA_PubScreen tag item has precedent
        over this technique.

        Unless NULL, the screen pointer provided MUST be a valid
        public screen.  You may ensure this several ways:

        - Be the owner of the screen.
        - Have a window already open on the screen.
        - Use LockPubScreen() to prevent the screen from closing.
        - specifying the WFLG_VISITOR bit in NewWindow.Flags is not
          supported.

        It is anticipated that the last will be the most common method
        of opening public screens because you often want to examine
        properties of the screen your window will be using in order
        to compensate for differences in dimension, depth, and font.

        The standard sequence for this method is as follows:
        LockPubScreen()	- obtain a pointer and a promise
        layout window	- adapt your window to the screen you will use
        OpenWindow()	- using the pointer you specify
        UnlockPubScreen()	- once your window is open, you can let go
                  of the lock on the public screen
        ... normal window even processing ...
        CloseWindow().

    Regarding "service" windows, such as those opened for a system
    requester or file requester associated with a given "client"window.
    These windows should NOT be "visitor" windows.  Open them
    using NewWindow.Type = CUSTOMSCREEN and NewWindow.Screen
    equal to the screen of the client window (window->WScreen).
    You can also use WA_CustomScreen, which has precedence.

    This ensures that the requester service window will be allowed to
    open on the same screen as the client window, even if that
    screen is not a public screen, or has private status.

    This has an implication for service/client protocol: when you
    pass a window pointer to any system requester routine or
    to a routine which creates some other other service window,
    you MUST keep your window open until the client window
    is closed.

    If a requester service will allow a NULL client window, this
    should indicate to open the service window on the default public
    screen (probably Workbench).  The correct way to get a pointer
    to this screen is to call LockPubScreen( NULL ).  In this
    case, you want to open as a visitor window, which means you
    should use either PUBLICSCREEN or WA_PubScreen, described above.
    You should call UnlockPubScreen() after your visitor window is open.

    As of V36, gadgets in the right and bottom border
    (specified with GACT_RIGHTBORDER and GACT_BOTTOMBORDER) only
    contribute to the dimensions of the borders if they are also
    GFLG_RELRIGHT and GFLG_RELBOTTOM, respectively.

    RESULT
    If all is well, returns the pointer to your new Window
    If anything goes wrong, returns NULL

    BUGS
    When you open a window, Intuition will set the font of
    the window's RastPort to the font of the window's screen.
    This does not work right for GimmeZeroZero windows: the
    BorderRPort RastPort has the font set correctly, but
    Window.RPort is set up with the system default font.
    For compatibility reasons, we won't be fixing this problem.

    Also, there is a compatibility trick going on with the
    default font of your window's RastPort if the screen's
    font is "fancy."  See the SA_SysFont attribute described
    under OpenScreen().

    Unless you arrange otherwise, each window you open will allocate
    a signal for your task from the 16 "user signals."
    If no signal is available, your window will not be able
    to be opened.  In early V36 versions and before, Intuition didn't
    check this condition, but just left you with an unusable port.

    SEE ALSO
       OpenWindowTagList(), OpenScreen(), ModifyIDCMP(), SetWindowTitles(),
    LockPubScreen(), SetDefaultPubScreen(), ZipWindow(),
    layers.library/InstallLayerHook(), SetPubScreenModes()


intuition.library/PointInImage

   NAME
    PointInImage -- Tests whether an image "contains" a point. (V36)

   SYNOPSIS
    DoesContain = PointInImage( Point, Image )
    D0	  		    D0     A0

    BOOL PointInImage( struct Point, struct Image * );

   FUNCTION
    Tests whether a point is properly contained in an image.
    The intention of this is to provide custom gadgets a means
    to delegate "image mask" processing to the Image, where
    it belongs (superseding things like BOOLMASK).  After all,
    a rounded rect image with a drop shadow knows more about
    what points are inside it than anybody else should.

    For traditional Intuition Images, this routine checks if
    the point is in the Image box (LeftEdge/RightEdge/Width/Height).

   INPUTS
     Point	- Two words, X/Y packed into a LONG, with high word
        containing 'X'.  This is what you get if you pass
        a Point structure (not a pointer!) using common
        C language parameter conventions.
    Image - a pointer to a standard or custom Image data object.
        NOTE: If 'Image' is NULL, this function returns TRUE.

   RESULT
     DoesContain - Boolean result of the test.

   EXAMPLE

   NOTES

   BUGS
    Only applies to the first image, does not follow NextImage
    linked list.  This might be preferred.

   SEE ALSO


intuition.library/PubScreenStatus

    NAME
    PubScreenStatus -- Change status flags for a public screen. (V36)

    SYNOPSIS
    ResultFlags = PubScreenStatus( Screen, StatusFlags )
    D0		   	       A0      D0

    UWORD PubScreenStatus( struct Screen *, UWORD );

    FUNCTION
    Changes status flags for a given public screen.  The only
    flag bit currently defined is PSNF_PRIVATE.  Thus,
    PubScreenStatus( screen, PSNF_PRIVATE ) makes a screen
    private, while PubScreenStatus( screen, 0 ) makes it public.

    Do not apply this function to a screen if your program
    isn't the screen's "owner", in particular, don't call
    this function for the Workbench screen.

    INPUTS
    Screen = pointer to public screen
    StatusFlags = Any of the PSNF_ flags (only PSNF_PRIVATE is
        currently defined).

    RESULT
    Returns 0 in the lowest order bit of the return value
    if the screen wasn't public, or because it can not be taken
    private because visitors are open in it.

    All other bits in the return code are reserved for future
    enhancement.

    BUGS

    SEE ALSO
    OpenScreen(), Intuition V36 update documentation


intuition.library/QueryOverscan

    NAME
    QueryOverscan -- Inquire about a standard overscan region. (V36)

    SYNOPSIS
    success = QueryOverscan( DisplayID, Rect, OScanType )
    D0                       A0         A1    D0

    LONG QueryOverscan( ULONG, struct Rectangle *, WORD );

    FUNCTION
    This function fills in a rectangle with one of the system
    overscan dimensions, scaled appropriately for the mode of
    the DisplayID it is passed.

    There are three types of system overscan values:
    OSCAN_TEXT: completely visible, by user preference.  Used
      for Workbench screen and screen dimensions STDSCREENWIDTH
      and STDSCREENHEIGHT.  Left/Top is always 0,0.
    OSCAN_STANDARD: just beyond visible bounds of monitor, by
      user preference.  Left/Top may be negative.
    OSCAN_MAX: The largest region we can display, AND display
      any smaller region (see note below).
    OSCAN_VIDEO: The absolute largest region that the graphics.library
      can display.  This region must be used as-is.

    INPUTS
    DisplayID -- A 32-bit identifier for a display mode, as defined
      in the <graphics/modeid.h> include file (V39 and up) or in
      <graphics/displayinfo.h> (V37/V38).

      NOTE: If you only intend to use one of the four standard
      overscan dimensions as is, and open your screen to exactly
      the DisplayClip dimensions, you can specify one of
      the OSCAN_ values using the SA_Overscan tag to the
      OpenScreenTagList() function and omit all of SA_Left, SA_Top,
      SA_Width, and SA_Height.  This also requires that you do
      not supply a NewScreen structure, since it always contains
      left/top/width/height information.

      If you wish to supply a NewScreen structure, then you are
      supplying left/top/width/height information.  This information
      can be taken from the rectangle resulting from this function:
        NewScreen.LeftEdge = Rect.MinX;
        NewScreen.TopEdge = Rect.MinY;
        NewScreen.Width = STDSCREENWIDTH;
            /* or ( Rect.MaxX - Rect.MinX + 1 ) */
        NewScreen.Height = STDSCREENHEIGHT;
            /* or ( Rect.MaxY - Rect.Miny + 1 ) */

    Rect -- pointer to a Rectangle structure which this function
      will fill out with its return values.  Note that to convert
      a rectangle to a screen "Height" you do (MaxY - MinY + 1), and
      similarly for "Width."  The rectangle may be passed directly
      to OpenScreen() as a DisplayClip region (SA_DClip).

    RESULT
    0 (FALSE) if the MonitorSpec your NewScreen requests
    does not exist.  Non-zero (TRUE) if it does.

    BUGS
    Change in parameter V36.A17 might cause problems for some.

    SEE ALSO
    OpenScreen(), Intuition V36 update documentation


intuition.library/RemakeDisplay

    NAME
    RemakeDisplay -- Remake the entire Intuition display.

    SYNOPSIS
    failure = RemakeDisplay()
    D0 (V39)

    LONG RemakeDisplay( VOID );
    /* Returns LONG in V39 and greater */

    FUNCTION
    This is the big one.

    This procedure remakes the entire View structure for the
    Intuition display.  It does the equivalent of MakeScreen() for
    every screen in the system, and then it calls the internal
    equivalent of RethinkDisplay().

    WARNING:  This routine can take many milliseconds to run, so
    do not use it lightly.

    Calling MakeScreen() followed by RethinkDisplay() is typically
    a more efficient method for affecting changes to a single
    screen's ViewPort.

    INPUTS
    None

    RESULT
    Starting with V39, returns zero for success, non-zero for failure.
    Probable cause of failure is failure of graphics.library/MakeVPort()
    or of graphics.library/MrgCop().
    Prior to V39, the return code is invalid.  Do not interpret it when
    running on pre-V39 systems!

    BUGS

    SEE ALSO
    MakeScreen(), RethinkDisplay(), graphics.library/MakeVPort()
    graphics.library/MrgCop(), graphics.library/LoadView()


intuition.library/Request

    NAME
    Request -- Activate a requester.

    SYNOPSIS
    Success = Request( Requester, Window )
    D0		   A0         A1

    BOOL Request( struct Requester *, struct Window * );

    FUNCTION
    Links in and displays a requester into the specified window.

    This routine ignores the window's IDCMP_REQVERIFY flag.

    INPUTS
    Requester = pointer to the requester to be displayed
    Window = pointer to the window into which this requester goes

    New for V36: the POINTREL flag now has meaning if the requester
    is not a DMR (Double-Menu Requester):
    If POINTREL is set this requester should be placed in the center
    of the window, offset by Requester.RelLeft and Requester.RelTop.
    If the requester doesn't fit in the window, its position will be
    adjusted to show the upper-left corner.

    RESULT
    If the requester is successfully opened, TRUE is returned.  Otherwise,
    if the requester could not be opened, FALSE is returned.

    BUGS
    It turns out that the return code of this function is not
    always correct under V34 and prior.  If your requester does
    not have an ENDGADGET, then you can examine window->FirstRequest
    to see if your requester successfully opened.  (A requester with
    an ENDGADGET can go away all by itself before you get the chance
    to look).  Under V36 and higher, the return code from this routine
    is fine.

    There is a maximum of 8 requesters that are supported in
    a window that can be changed in size, position, or depth.

    SEE ALSO
    The Requesters section of the Intuition Reference Manual


intuition.library/RethinkDisplay

    NAME
    RethinkDisplay -- Grand manipulation of the entire Intuition display.

    SYNOPSIS
    failure = RethinkDisplay()
    D0 (V39)

    LONG RethinkDisplay( VOID );
    /* Returns LONG in V39 and greater */

    FUNCTION
    This function performs the Intuition global display reconstruction.
    This includes rethinking about all of the  ViewPorts and their
    relationship to one another and reconstructing the entire display
    based on the results of this rethinking.

    Specifically, and omitting many internal details, the operation
    consists of this:

        Determine which ViewPorts are invisible and set their VP_HIDE
        ViewPort Mode flag. VP_HIDE flags are also set for screens that
        may not be simultaneously displayed with the frontmost (V36).

        If a change to a viewport height, or changing interlace or
        monitor scan rates require, MakeVPort() is called for specific
        screen viewports.  After this phase, the intermediate Copper lists
        for each screen's viewport are correctly set up.

        MrgCop() and LoadView() are then called to get these Copper lists
        in action, thus establishing the new state of the Intuition
        display.

    You may perform a MakeScreen() on your Custom Screen before calling
    this routine.  The results will be incorporated in the new display, but
    changing the INTERLACE ViewPort mode for one screens must be reflected
    in the Intuition View, which is left to Intuition.

    WARNING:  This routine can take several milliseconds to run, so
    do not use it lightly.

    New for V36: This routine is substantially changed to support
    new screen modes.  In particular, if screen rearrangement has
    caused a change in interlace mode or scan rate, this routine
    will remake the copper lists for each screen's viewport.

    INPUTS
    None

    RESULT
    Starting with V39, returns zero for success, non-zero for failure.
    Probable cause of failure is failure of graphics.library/MakeVPort()
    or of graphics.library/MrgCop().
    Prior to V39, the return code is invalid.  Do not interpret it when
    running on pre-V39 systems!

    BUGS
    In V35 and earlier, an interlaced screen coming to the front
    may not trigger a complete remake as required when the global
    interlace state is changed.  In some cases, this can be compensated
    for by setting the viewport DHeight field to 0 for hidden screens.

    SEE ALSO
    RemakeDisplay(), graphics.library/MakeVPort(), graphics.library/MrgCop(),
    graphics.library/LoadView(), MakeScreen()


intuition.library/ScreenDepth

    NAME
    ScreenDepth -- Depth arrange a screen with extra control. (V39)

    SYNOPSIS
    ScreenDepth( screen, flags, reserved )
                 A0      D0     A1

    VOID ScreenDepth( struct Screen *, ULONG, APTR );

    FUNCTION
    Brings the specified screen to the front or back, based on
    the supplied flags.  Also allows control of screen
    depth-arranging within screen families.

    INPUTS
    screen = a pointer to the screen to move
    flags = one of SDEPTH_TOFRONT or SDEPTH_TOBACK (bringing the
        screen to front or back respectively).  If the screen
        is an attached screen, then you may also specify
        SDEPTH_INFAMILY to move the screen within the screen
        family.  If the screen is an attached screen and
        SDEPTH_INFAMILY is not specified, then the whole family
        will move, which is also the behavior of the ScreenToFront()
        and ScreenToBack() functions, as well as the user-interface
        controls.
    reserved = must be NULL for now.

    RESULT
    None

    NOTES
    ONLY the application which owns the screen should use
    SDEPTH_INFAMILY.  It is incorrect style (and against the
    intentions of the screen opener) for programs such as
    commodities or mouse-helpers to move child screens around
    in their family.  (Note that this is a style-behavior
    requirement;  there is no technical requirement that the
    task calling this function need be the task which opened
    the screen).

    BUGS

    SEE ALSO
    ScreenToFront(), ScreenToBack(),
    SA_Parent, SA_FrontChild, SA_BackChild


intuition.library/ScreenPosition

    NAME
    ScreenPosition -- Move screens with greater control. (V39)

    SYNOPSIS
    ScreenPosition( Screen, flags, x1, y1, x2, y2 )
                    A0      D0     D1  D2  D3  D4

    VOID ScreenPosition( struct Screen *, ULONG, LONG, LONG, LONG, LONG );

    FUNCTION
    Moves the screen to the specified position or by the specified
    increment, in screen pixel resolution coordinates.

    If the x1 and y1 variables you specify would move the screen in
    a way that violates any restrictions, the screen will be moved
    as far as possible.  You may examine the LeftEdge and TopEdge
    fields of the Screen structure after this function returns to
    see where the screen really ended up.

    Note that negative values for screen LeftEdge and TopEdge are
    valid for screens bigger than their display clip.

    INPUTS
    Screen = pointer to a Screen structure
    flags = Set to one of SPOS_RELATIVE, SPOS_ABSOLUTE, or
        SPOS_MAKEVISIBLE.   You may additionally set SPOS_FORCEDRAG
        if you need.  Use SPOS_RELATIVE (zero) for normal use
        (move screen a relative amount expressed by x1,y1).  Set
        the SPOS_ABSOLUTE flag if you wish x1 and y1 to be absolute
        coordinates to move the screen to.  Set SPOS_MAKEVISIBLE to
        position an oversized scrolling screen so that the rectangle
        described by (x1,y1)-(x2,y2) is on the visible part of
        the display. (A word-processor may wish to support
        autoscrolling as the user types.  In that case, it could
        call ScreenPosition() with the SPOS_MAKEVISIBLE flag and
        a rectangle that encompasses the cursor with some space
        around it.

        In addition to any one of the above choices, you can
        additionally set SPOS_FORCEDRAG if you wish to reposition
        a screen that was opened with the {SA_Draggable,FALSE}
        attribute.

    x1,y1 = Absolute position or change in position you wish to apply
        to the screen, when using SPOS_ABSOLUTE or SPOS_RELATIVE.
        When using SPOS_MAKEVISIBLE, these variables describe
        the upper-left corner of the rectangle you would like to
        ensure is on the visible part of a scrolling screen.
    x2,y2 = Ignored when using SPOS_ABSOLUTE or SPOS_RELATIVE.
        When using SPOS_MAKEVISIBLE, these variables describe
        the lower-right corner of the rectangle you would like to
        ensure is on the visible part of a scrolling screen.

        Note that these coordinates are in the same resolution
        as the screen (such as HIRES or INTERLACE)

    RESULT
    None

    NOTES
    ONLY the owner of the screen should use SPOS_FORCEDRAG.
    It is incorrect style (and against the intentions of the
    screen opener) for programs such as commodities or
    mouse-helpers to move non-draggable screens.

    BUGS

    SEE ALSO
    MoveScreen(), RethinkDisplay()


intuition.library/ScreenToBack

    NAME
    ScreenToBack -- Send the specified screen to the back of the display.

    SYNOPSIS
    ScreenToBack( Screen )
              A0

    VOID ScreenToBack( struct Screen * );

    FUNCTION
    Sends the specified screen to the back of the display.

    INPUTS
    Screen = pointer to a Screen structure

    RESULT
    None

    BUGS

    SEE ALSO
    ScreenDepth(), ScreenToFront()


intuition.library/ScreenToFront

    NAME
    ScreenToFront -- Make the specified screen the frontmost.

    SYNOPSIS
    ScreenToFront( Screen )
               A0

    VOID ScreenToFront( struct Screen * );

    FUNCTION
    Brings the specified Screen to the front of the display.

    INPUTS
    Screen = a pointer to a Screen structure

    RESULT
    None

    BUGS

    SEE ALSO
    ScreenDepth(), ScreenToBack()


intuition.library/ScrollWindowRaster

   NAME
        ScrollWindowRaster -- Intuition-friendly ScrollRasterBF() (V39)

   SYNOPSIS
        ScrollWindowRaster(win, dx, dy, xmin, ymin, xmax, ymax)
                           A1   D0  D1  D2    D3    D4    D5

        void ScrollWindowRaster(struct Window *, WORD, WORD,
            WORD, WORD, WORD, WORD);

   FUNCTION
        Calls graphics.library/ScrollRasterBF(), which moves
        the bits in the raster by (dx,dy) towards (0,0)
        The space vacated is filled by calling EraseRect().
        NOTE: that vacated space is _not_ considered damage!
        The scroll operation is limited to the rectangle defined
        by (xmin,ymin)-(xmax,ymax). Bits outside will not be
        affected. If (xmax,ymax) is outside the rastport then use
        the lower right corner of the rastport.

        If a window is partly obscured, then it is possible for
        ScrollWindowRaster() to scroll some of the obscured
        area into view.  If the window is simple-refresh, then
        the formerly obscured area is damage, and the application
        needs to repair it.  If Intuition detects damage as a result
        of ScrollWindowRaster(), it will send an IDCMP_REFRESHWINDOW
        event to the application's window.  This handling of damage
        is the principal reason ScrollWindowRaster() is preferred
        to ScrollRaster() and ScrollRasterBF().

   INPUTS
        win - pointer to a Window structure
        dx,dy are integers that may be postive, zero, or negative
        xmin,ymin - upper left of bounding rectangle
        xmax,ymax - lower right of bounding rectangle

   NOTES
        This call uses ScrollRasterBF(), which calls EraseRect()
        when clearing the newly exposed area. This allows use of
        a custom layer backfill hook.

        IMPORTANT:  boopsi gadgets should use ScrollRaster() or
        ScrollRasterBF() directly!  Never call ScrollWindowRaster()
        from inside a boopsi gadget's method handler.  Note that
        Intuition will detect and handle damage caused by such use
        of ScrollRaster() or ScrollRasterBF(), for gadgets with
        the GMORE_SCROLLRASTER property.

        VERY IMPORTANT:  if you have any gadgets in your simple-refresh
        window with the GMORE_SCROLLRASTER property, you must use
        ScrollWindowRaster() instead of ScrollRaster() or ScrollRasterBF().
        Handling of gadget scroll damage is incompatible with continued
        use of these graphics functions in an Intuition window.
        NB:  If you're using a gadget class whose source code you do
        not control, that class might be using GMORE_SCROLLRASTER or
        might start to in a future version.  For that reason, you
        should use ScrollWindowRaster() if you are using any such gadgets.

   BUGS
        In intuition.library V39 and V40 ScrollWindowRaster() must
        be considered unsafe in connection with gadget event handling
        and windows which do not have the WA_NoCareRefresh attribute set.
        A race condition may occur which will cause write accesses
        to unallocated memory and keep the IDCMP_REFRESHWINDOW message
        from getting delivered.

        The recommended workaround for this problem is to use
        ScrollWindowRaster() only in SMART_REFRESH windows which have
        the WA_NoCareRefresh attribute set. Of course, which such
        windows there will be no difference in functionality between
        ScrollWindowRaster() and ScrollRasterBF().

   SEE ALSO
        graphics.library/ScrollRaster(), graphics.library/ScrollRasterBF()
        graphics.library/EraseRect(), WA_BackFill


intuition.library/SetEditHook

    NAME
    SetEditHook -- Set global processing for string gadgets. (V36)

    SYNOPSIS
    OldHook = SetEditHook( Hook )
    D0                     A0

    struct Hook *SetEditHook( struct Hook * );

    FUNCTION
    Sets new global editing hook for string gadgets.

    WARNING: The use and integration of this function has not
    been explored, and thus should be considered a risky function.
    Do *NOT* use this in a commercial product until further notice.

    INPUTS
    Hook -- A pointer to a struct Hook which determines a function
      in your code to be called every time the user types a key.
      This is done before control is passed to the gadget custom
      editing hook, so affects ALL string gadgets.

    RESULT
    Returns previous global edit hook structure.  You may need this
    hook if you wish to invoke the previous edit hook's behavior
    in addition to your own.

    NOTES
    There are a few key differences between a global edit hook and the
    more famililar per-gadget StringExtend->EditHook field.  In the
    case of the latter, the hook's creator supplies a WorkBuffer.
    Intuition's idea of the result of a keystroke is stored in
    the SGWork structure (which references the WorkBuffer).  The
    state of the gadget before Intuition's hook acted is available in
    the StringInfo->Buffer, ->BufferPos, and ->NumChars fields.

    In the case of a global editing hook, your hook _becomes_
    Intuition's hook, which affects all gadgets, most of which
    do not have a WorkBuffer.  This means that if you invoke
    Intuition's original hook (which you got as the result of this
    function), there isn't any easy way for you to "undo" that after
    the fact.  This means that if Intuition's behavior for certain
    keystrokes is incompatible with your hook's objectives, then
    you must avoid calling Intuition's hook for those keys.  One
    approach is to run through your hook's code first, acting on
    those keys you wish to recognize.  Then, call Intuition's
    hook for those keys you do not recognize, or for those keys
    whose default actions you wish to add to.

    Do not forget to set SGA_REDISPLAY when needed (see sghooks.h),
    and please be sure to give the SGWork->EditOp field a value
    which is as meaningful as possible.

    Currently, only SGH_KEY messages are sent to the global edit
    hook, though custom edit hooks do receive SGH_CLICK messages
    in addition.

    Finally, there is currently no arbitration between a global
    edit hook and a custom edit hook as to ownership of keystrokes.
    It would be fair to expect that a custom edit hook would be
    written to match the current Intuition edit hook.  If your
    global edit hook acts on (say) up and down arrow keystrokes,
    an undesirable result may occur if some string gadget's custom
    hook also acts on these keystrokes.  There is currently
    no easy way to resolve this issue.

    BUGS

    SEE ALSO


intuition.library/SetGadgetAttrsA

    NAME
    SetGadgetAttrsA -- Specify attribute values for a boopsi gadget. (V36)
    SetGadgetAttrs -- Varargs stub for SetGadgetAttrsA(). (V36)

    SYNOPSIS
    result = SetGadgetAttrsA( Gadget, Window, Requester, TagList )
    D0		          A0      A1      A2         A3

    ULONG SetGadgetAttrsA( struct Gadget *, struct Window *,
        struct Requester *, struct TagItem * );

    result = SetGadgetAttrs( Gadget, Window, Requester, Tag1, ...)

    ULONG SetGadgetAttrs( struct Gadget *, struct Window *,
        struct Requester *, ULONG, ... );

    FUNCTION
    Same as SetAttrs(), but provides context information and
    arbitration for classes which implement custom Intuition gadgets.

    You should use this function for boopsi gadget objects which have
    already been added to a requester or a window, or for "models" which
    propagate information to gadget already added.

    Typically, the gadgets will refresh their visuals to reflect
    changes to visible attributes, such as the value of a slider,
    the text in a string-type gadget, the selected state of a button.

    You can use this as a replacement for SetAttrs(), too, if you
    specify NULL for the 'Window' and 'Requester' parameters.

    INPUTS
    Gadget = abstract pointer to a boopsi gadget
    Window = window gadget has been added to using AddGList() or AddGadget()
    Requester = for REQGADGETs, requester containing the gadget
    TagList = array of TagItem structures with attribute/value pairs.

    RESULT
    The object does whatever it wants with the attributes you provide,
    which might include updating its gadget visuals.

    The return value tends to be non-zero if the changes would require
    refreshing gadget imagery, if the object is a gadget.

    NOTES
    This function invokes the OM_SET method with a GadgetInfo
    derived from the 'Window' and 'Requester' pointers.

    BUGS
    Prior to V39, this function ran with inadequate locking against
    the calls that Intuition's input task makes to the gadgets.
    To run properly prior to V39, this function, input processing,
    and and the gadget's dispatcher must be mutually re-entrant.

    SEE ALSO
    NewObject(), DisposeObject(), GetAttr(), MakeClass(),
    Document "Basic Object-Oriented Programming System for Intuition"
    and the "boopsi Class Reference" document.


intuition.library/SetPointer

    NAME
    SetPointer -- Specify a pointer sprite image for a window.

    SYNOPSIS
    SetPointer( Window, Pointer, Height, Width, XOffset, YOffset )
            A0      A1       D0      D1     D2       D3

    VOID SetPointer( struct Window *, UWORD *, WORD, WORD, WORD, WORD );

    FUNCTION
    Sets up the window with the sprite definition for the pointer.
    Then, whenever the window is the active one, the pointer
    image will change to the window's version.  If the window is
    the active one when this routine is called, the change takes
    place immediately.

    The XOffset and YOffset parameters are used to offset the
    upper-left corner of the hardware sprite image from what Intuition
    regards as the current position of the pointer.  Another way of
    describing it is as the offset from the "hot spot" of the pointer
    to the top-left corner of the sprite.  For instance, if you specify
    offsets of zero, zero, then the top-left corner of your sprite
    image will be placed at the mouse position.  On the other hand,
    if you specify an XOffset of -7 (remember, sprites are 16 pixels
    wide) then your sprite will be centered over the mouse position.
    If you specify an XOffset of -15, the right-edge of the sprite
    will be over the mouse position.

    INPUTS
    Window = pointer to the window to receive this pointer definition
    Pointer = pointer to the data definition of a sprite
    Height = the height of the pointer
    Width = the width of the sprite (must be less than or equal to sixteen)
    XOffset = the offset for your sprite from the mouse position
    YOffset = the offset for your sprite from the mouse position

    RESULT
    None

    BUGS

    SEE ALSO
    SetWindowPointerA(), ClearPointer(), ROM Kernel Manual: Libraries


intuition.library/SetPrefs

    NAME
    SetPrefs -- Set Intuition preferences data.

    SYNOPSIS
    Prefs = SetPrefs( PrefBuffer, Size, Inform )
    D0		  A0          D0    D1

    struct Preferences *SetPrefs( struct Preferences *, LONG, BOOL );

    FUNCTION
    Sets new preferences values.  Copies the first 'Size' bytes
    from your preferences buffer to the system preferences table,
    and puts them into effect.

    The 'Inform' parameter, if TRUE, indicates that an IDCMP_NEWPREFS
    message is to be sent to all windows that have the IDCMP_NEWPREFS
    IDCMPFlag set.

    It is legal to set a partial copy of the Preferences structure.
    The most frequently changed values are grouped at the beginning
    of the Preferences structure.

    New for V36:  A new and more extensible method for supplying
    Preferences has been introduced in V36, and relies on file
    system notification.  The Intuition preferences items rely
    also on the IPrefs program.  Certain elements of the
    Preferences structure have been superseded by this new method.
    (Elements are generally superseded as new hardware or software
    features demand more information than fits in struct Preferences.
    Parts of struct Preferences must be ignored so that applications
    calling GetPrefs(), modifying some other part of struct Preferences,
    then calling SetPrefs(), don't end up truncating the extended
    data).

    Pointer Preferences:  Starting with V36, pointer changes
    submitted through SetPrefs() are only heeded until the first
    time IPrefs informs Intuition of a V36-style pointer preferences
    file.  In V39 and higher, only the pointer from the initial
    SetPrefs() (i.e. devs:system-configuration) is heeded.

    Palette Preferences:  Starting with V39, color changes submitted
    through SetPrefs() are ignored after the first time IPrefs sends
    Intuition new style palette preferences.

    FontHeight and LaceWB:  These are only respected from
    devs:system-configuration.

    View centering and size:  Changes to ViewX/YOffset and
    Row/ColumnSizeChange only apply to the default monitor
    (NTSC or PAL), and not to other monitors such as Productivity.

    Other fields may be superseded in the future.

    INPUTS
    PrefBuffer = pointer to the memory buffer which contains your
        desired settings for Intuition preferences
    Size = the number of bytes in your PrefBuffer, the number of bytes
           you want copied to the system's internal preference settings
    Inform = whether you want the information of a new preferences
        setting propagated to all windows.

    NOTES
    Unless you are responding to a user's explicit request to
    change Preferences (for example, you are writing a Preferences
    editor), you should probably avoid using this function.
    The user's Preferences should be respected, not overridden.

    RESULT
    Returns your parameter PrefBuffer.

    BUGS

    SEE ALSO
    GetDefPrefs(), GetPrefs()


intuition.library/SetWindowPointerA

    NAME
    SetWindowPointerA -- Select a pointer for your window. (V39)
    SetWindowPointer -- Varargs stub for SetWindowPointerA(). (V39)

    SYNOPSIS
    SetWindowPointerA( window, taglist )
                       A0      A1

    VOID SetWindowPointerA( struct Window *, struct TagItem * );

    SetWindowPointer( window, tag1, ... )

    VOID SetWindowPointer( struct Window *, ULONG tag1, ... );

    FUNCTION
    Allows you to set the pointer image associated with the
    specified window.  Whenever the window is the active one,
    the pointer image will change to the window's version.
    If the window is the active one when this routine is
    called, the change takes place immediately.

    INPUTS
    window = pointer to the window to receive this pointer definition
    taglist = pointer to a taglist describing your pointer

    TAGS
    The same three tags are also accepted by OpenWindowTagList(),
    which allows you to establish the initial pointer at the
    time you open your window.

    WA_Pointer (APTR) - The pointer you wish to associate with
        your window.  If NULL, you are requesting the Preferences
        default pointer.  Custom pointers should be allocated
        by performing a NewObject() on "pointerclass".
        (See <intuition/pointerclass.h>).  Defaults to NULL.

    WA_BusyPointer (BOOL) - Set to TRUE to request the Preferences
        busy-pointer.  If FALSE, your pointer will be as requested
        by WA_Pointer.  Defaults to FALSE.

    WA_PointerDelay (BOOL) - Set to TRUE to defer changing your
        pointer for a brief instant.  This is typically used
        along with setting the busy pointer, especially when
        the application knows it may be busy for a very short
        while.  If the application clears the pointer or sets
        another pointer before the delay expires, the pending
        pointer change is cancelled.  This reduces short
        flashes of the busy pointer.

    RESULT
    None

    EXAMPLE
    This example sets the standard busy pointer with pointer-delay,
    does a bit of work, then clears the pointer:

        /* Put up the busy pointer, with pointer-delay */
        SetWindowPointer( win,
            WA_BusyPointer, TRUE,
            WA_PointerDelay, TRUE,
            TAG_DONE );

        /* Do busy stuff here */

        /* No tags means "clear the pointer" */
        SetWindowPointer( win,
            TAG_DONE );

    BUGS

    SEE ALSO
    SetPointer(), ClearPointer(), ROM Kernel Manual: Libraries


intuition.library/SysReqHandler

    NAME
    SysReqHandler -- Handle system requester input. (V36)

    SYNOPSIS
    num = SysReqHandler( Window, IDCMPFlagsPtr, WaitInput )
    D0                   A0      A1             D0

    LONG SysReqHandler( struct Window *, ULONG *, BOOL );

    FUNCTION
    Handles input for a window returned by either BuildSysRequest()
    or BuildEasyRequest().  These functions with SysReqHandler()
    you can perform an "asynchronous" EasyRequest() or AutoRequest().
    That is to say, you can perform other processing while you
    wait for the requester to be satisfied.

    Each time this function is called, it will process all
    IDCMPMessages that the window has received.  If the parameter
    'WaitInput' is non-zero, SysReqHandler() will wait for input
    (by calling WaitPort()) if there are no IDCMP messages.

    SysReqHandler() returns the same values as EasyRequest(): A gadget
    ID greater than equal to 0, and  -1 if one of the other IDCMP
    events were received.

    An additional value of -2 is returned if the input processed
    does not satisfy the requester.  In this case, you might
    perform some processing and call SysReqHandler() again.

    Note: this function does NOT terminate the system request.
    Not only must you call FreeSysRequest() to eliminate the request,
    but you may also continue processing after an event which would
    normally terminate a normal call to EasyRequest().

    EXAMPLE
    Implementation of EasyRequest() input loop:

    window = BuildEasyRequest( ... )
    while ( (retval = SysReqHandler( window, idcmp_ptr, TRUE )) == -2 )
    {
        /* loop	*/;
    }
    FreeSysRequest( window );

    EXAMPLE
    Request a volume, but don't remove the requester when the
    user inserts the wrong disk:

    struct EasyStruct volumeES = {
        sizeof (struct EasyStruct),
        0,
        "Volume Request",
        "Please insert volume %s in any drive.",
        "Cancel"
    };

    Volume *
    getVolume( volname )
    UBYTE	*volname;
    {
        struct Window	*window;
        Volume		*volume = NULL;
        Volume		*findVolume();
        int			retval;

        window = BuildEasyRequest( NULL, &volumeES, IDCMP_DISKINSERTED,
                  volname );

        while ( (retval = SysReqHandler( window, NULL, TRUE )) != 0 )
        {
            /* not cancelled yet	*/

            /* when IDCMP_DISKINSERTED, check for volume */
            if (( retval == -1 ) && (volume = findVolume( volname )))
            break;
        }
        FreeSysRequest( window );
        return ( volume );
    }

    INPUTS
    Window = Window pointer returned from BuildSysRequest() or
        BuildEasyRequest().  Those functions can also return
        values '0' or '1', and these values may also be
        passed to SysReqHandler(), which will immediately
        return the same value.

    IDCMPFlagsPtr = If you passed application specific IDCMP
        flags to BuildSysRequest() or BuildEasyRequest(),
        SysReqHandler() will return -1 if that IDCMP message
        is received.  If IDCMPFlagsPtr is non-null, it
        points to a ULONG where the IDCMP class received
        will be copied for your examination.

        This pointer can be NULL if you have provided no
        application specific IDCMP flags or if you do
        not need to know which application specific IDCMP
        event occurred.

        If you provide more than on flag in the flags variable
        this pointer points to, you will have to refresh
        the variable whenever -1 is returned, since the
        variable will have been changed to show just the
        single IDCMP Class bit that caused the return.

    WaitInput = Specifies that you want SysReqHandler() to
            to wait for IDCMP input if there is none pending.

    RESULT
    0, 1, ..., N = Successive GadgetID values, for the gadgets
        you specify for the requester.  NOTE: The numbering
        from left to right is actually: 1, 2, ..., N, 0.
        This is for compatibility with AutoRequests which has
        FALSE for the rightmost gadget.

    -1 = Means that one of the caller-supplied IDCMPFlags occurred.
        The IDCMPFlag value is in the longword pointed to by UDCMP_ptr.

    -2 = input processed did not satisfy the requester. One example
        is a keystroke that does not satisfy the requester.  Another
        example is if there is no input pending and you specified
        FALSE for WaitInput.

    BUGS

    SEE ALSO
    exec.library/WaitPort()


intuition.library/TimedDisplayAlert

    NAME
    TimedDisplayAlert -- Display an alert with automatic time-out. (V39)

    SYNOPSIS
    Response = TimedDisplayAlert( AlertNumber, String, Height, Time )
    D0                            D0           A0      D1      A1

    BOOL TimedDisplayAlert( ULONG, UBYTE *, UWORD, ULONG );

    FUNCTION
    This function is equivalent to DisplayAlert(), except that if
    the user fails to respond in a given time, the alert comes
    down automatically.  See the autodoc for DisplayAlert() for
    full details.

    INPUTS
    AlertNumber = the number of this alert message.  The only pertinent
        bits of this number are the ALERT_TYPE bit(s).  The rest of the
           number is ignored by this routine.
    String = pointer to the alert message string, as described above
    Height = minimum display lines required for your message
    Time = length of time the alert should wait for the user to
        respond.  This time is the number of video frames the
        alert should remain up for.

    RESULT
    A BOOL value of TRUE or FALSE.  If this is a DEADEND_ALERT, FALSE
    is always the return value.  If this is a RECOVERY_ALERT. The return
    value will be TRUE if the user presses the left mouse button in
    response to your message, and FALSE if the user presses the right hand
    button is response to your text, or if the alert could not
    be posted.  If the alert times out, the return value will be FALSE.

    BUGS

    SEE ALSO
    DisplayAlert()


intuition.library/WindowLimits

    NAME
    WindowLimits -- Set the minimum and maximum limits of a window.

    SYNOPSIS
    Success = WindowLimits( Window, MinWidth, MinHeight, MaxWidth,
    D0		        A0      D0        D1         D2
                            MaxHeight )
                            D3

    BOOL WindowLimits( struct Window *, WORD, WORD, UWORD, UWORD );

    FUNCTION
    Sets the minimum and maximum limits of the window's size.  Until this
    routine is called, the window's size limits are equal to the initial
    values established in the OpenWindow() function.

    After a call to this routine, the Window will be able to be sized
    to any dimensions within the specified limits.

    If you don't want to change any one of the dimensions, set the limit
    argument for that dimension to zero.  If any of the limit arguments
    is equal to zero, that argument is ignored and the initial setting
    of that parameter remains undisturbed.

    If any of the arguments is out of range (minimums greater than the
    current size, maximums less than the current size), that limit
    will be ignored, though the others will still take effect if they
    are in range.  If any are out of range, the return value from this
    procedure will be FALSE.  If all arguments are valid, the return
    value will be TRUE.

    If you want your window to be able to become "as large as possible"
    you may put -1 (i.e. ~0) in either or both Max arguments.  But
    please note: screen sizes may vary for several reasons, and you
    must be able to handle any possible size of window you might end
    up with if you use this method.  Note that you can use the function
    LockPubScreen() to find out how big the screen your window will
    appear in is.  You may also refer to the WScreen field in your
    window structure, providing that your window remains open,
    which will ensure that the screen remains open, and thus the
    pointer remains valid.

    If the user is currently sizing this window, the new limits will
    not take effect until after the sizing is completed.

    INPUTS
    Window = pointer to a Window structure
    MinWidth, MinHeight, MaxWidth, MaxHeight = the new limits for the size
            of this window.  If any of these is set to zero, it will
            be ignored and that setting will be unchanged.

    RESULT
    Returns TRUE if everything was in order.  If any of the parameters was
    out of range (minimums greater than current size, maximums less than
    current size), FALSE is returned and the errant limit request is
    not fulfilled (though the valid ones will be).

    BUGS

    SEE ALSO
    LockPubScreen()


keyboard.doc

     CMD_CLEAR
     KBD_ADDRESETHANDLER
     KBD_READEVENT
     KBD_READMATRIX
     KBD_REMRESETHANDLER
     KBD_RESETHANDLERDONE


keymap.doc

     AskKeyMapDefault()
     MapANSI()
     MapRawKey()
     SetKeyMapDefault()


keymap.library/AskKeyMapDefault

   NAME
    AskKeyMapDefault -- Ask for a pointer to the current default
                        keymap. (V36)

   SYNOPSIS
    keyMap = AskKeyMapDefault()

    struct KeyMap *AskKeyMapDefault( VOID );

   FUNCTION
    Return a pointer to the keymap used by the keymap library for
    MapRawKey and MapANSI when a keymap is not specified.

   RESULTS
    keyMap - a pointer to a keyMap structure.  This key map is
        guaranteed to be permanently allocated: it will remain in
        memory till the machine is reset.

   BUGS
    The keymap.h include file should be in the libraries/ or perhaps
    resources/ directory, but is in the devices/ directory for
    compatibility reasons.

   SEE ALSO
    devices/keymap.h, keymap.library/SetKeyMapDefault(),
    console.device ...KEYMAP functions


keymap.library/MapRawKey

   NAME
    MapRawKey -- Decode single raw key input event to an ANSI
                 string. (V36)

   SYNOPSIS
    actual = MapRawKey(event, buffer, length, keyMap)
    D0                 A0     A1      D1      A2

    WORD MapRawKey( struct InputEvent *, STRPTR, WORD,
        struct Keymap * );

   FUNCTION
    This console function converts input events of type
    IECLASS_RAWKEY to ANSI bytes, based on the keyMap, and
    places the result into the buffer.

   INPUTS
    event -  an InputEvent structure pointer.  The event list is
        not traversed.
    buffer - a byte buffer large enough to hold all anticipated
        characters generated by this conversion.
    length - maximum anticipation, i.e. the buffer size in bytes.
    keyMap - a KeyMap structure pointer, or null if the default
        key map is to be used.

   RESULT
    actual - the number of characters in the buffer, or -1 if
        a buffer overflow was about to occur.

   EXAMPLE
    ...
    #define	BUFFERLEN	80	/* length of longest expected mapping /*
    char buffer[BUFFERLEN];
    struct InputEvent ie;
    ...
        KeymapBase = OpenLibrary("keymap.library", 0);
        ...
        ie.ie_Class = IECLASS_RAWKEY;
        ie.ie_SubClass = 0;
        for (;;) {
        WaitPort(window->UserPort);
        while (im = (struct IntuiMessage *) GetMsg(window->UserPort)) {
            switch (im->Class) {
            case RAWKEY:
                ie.ie_Code = im->Code;
                ie.ie_Qualifier = im->Qualifier;
                /* recover dead key codes & qualifiers */
                ie.ie_EventAddress = (APTR *) *((ULONG *)im->IAddress);
                actual = MapRawKey(&ie, buffer, BUFFERLEN, 0);
                for (i = 0; i < actual; i++)
                ReportChar(buffer[i]);
                break;
            ...
            }
            ...
        }
        }

   ERRORS
    if actual is -1, a buffer overflow condition was detected.
    Not all of the characters in the buffer are valid.

   SEE ALSO
    devices/inputevent.h, devices/keymap.h


label_ic.doc

     --datasheet--
     LABEL_GetClass()


label_ic/--datasheet--

    NAME
        label_ic -- Image class for creating idenification labels

    SUPERCLASS
        imageclass

    REQUIRES
        None.

    DESCRIPTION
        Label is an image class suitable for creating identification labels,
        such as might appear next to or inside a gadget, or as some kind of
        title in a window.  A label consists of text and graphics mixed in
        a variety of ways.

    METHODS
        OM_NEW--Create the label image.  Passed to superclass, then OM_SET.

        OM_GET--Get object attributes.  Passed to superclass first.

        OM_SET--Set object attributes.  Passed to superclass first.

        OM_UPDATE--Set object notification attributes.  Passed to superclass
            first.

        IM_DRAW--Renders the images.  Overrides the superclass.

        All other methods are passed to the superclass, including OM_DISPOSE.

    ATTRIBUTES
        IA_Font (struct TextAttr *)
            Font to use for any label text.  Only affects text passed AFTER
            this tag is given.  If you did not use the LABEL_DrawInfo tag
            then you MUST use this tag to specify what font to use.

            Applicability is (OM_NEW)

        IA_FGPen (LONG)
            Foreground pen for any label text.  Only affects text passed AFTER
            this tag is given.

            Defaults to pen 1.

            Applicability is (OM_NEW)

        IA_BGPen (LONG)
            Background pen for any label text.  Only affects text passed AFTER
            this tag is given.

            Defaults to pen 0.

            Applicability is (OM_NEW)

        IA_Mode (UBYTE)
            Draw mode for rendering text.  Only affects text passed AFTER
            this tag is given.

            Defaults to JAM1.

            Applicability is (OM_NEW)

        LABEL_DrawInfo (struct DrawInfo *)
            Contains important pen information.  This is used to get default
            font information.  If you do not use IA_Font to specify fonts
            then you MUST pass the screen DrawInfo before you give the
            LABEL_Text tag.

            Defaults to NULL.

            Applicability is (OM_NEW, OM_GET)

        LABEL_Text (STRPTR)
            A text string to render.  A 'n' in the string will cause the
            text position to move to a new line.  The first underscore ('_')
            in the string will be used to underline the proceeding character
            in the string.  Any number of text strings and images can be
            provided in a label, mixed at will.

            Applicability is (OM_NEW)

        LABEL_SoftStyle (UBYTE)
            SoftStyle for any label text.  Only affects text passed AFTER
            this tag is given.

            Defaults to FS_NORMAL.

            Applicability is (OM_NEW)

        LABEL_Image (struct Image *)
            An image to render.  Any number of text strings and images can
            be provided in a label, mixed at will.

            Applicability is (OM_NEW)

        LABEL_DisposeImage (BOOL)
            Indicates that you want the NEXT image passed via LABEL_Image
            to be disposed automatically when the label instance is
            disposed.  This implies that the next image passed MUST be a
            BOOPSI image (since static images cannot be disposed).  This
            will only affect the next image passed, therefore you must
            specify this tag for every image you wish to have disposed of
            automatically.

            Defaults to FALSE.

            Applicability is (OM_NEW)

        LABEL_Mapping (UWORD *)
            Pen mapping array, affects the NEXT image passed via
            LABEL_Image ONLY.  You should pass a mapping for non-BOOPSI
            images only, it is expected that BOOPSI images would be
            correctly pen-mapped.

            The mapping array must have at least as many elements as the
            image has bit planes (i.e. 1 << Image.Depth).  For element
            i in the array you put in the new pen that you want pen i in
            your image to be mapped to.  For a typical 4-colour image, you
            might use the following mapping:

                UWORD mapping[4];
                struct DrawInfo *drinfo;

                /* Before hand we'll have obtained the screen's DrawInfo.
                 */
                mapping[0] = drinfo->dri_Pens[BACKGROUNDPEN];
                mapping[1] = drinfo->dri_Pens[SHADOWPEN];
                mapping[2] = drinfo->dri_Pens[SHINEPEN];
                mapping[3] = drinfo->dri_Pens[FILLPEN];

            Applicability is (OM_NEW)

        LABEL_Justification (UWORD)
            Justification for entire label.  This can be either LJ_LEFT
            (the default), LJ_CENTRE or LJ_RIGHT.

            Applicability is (OM_NEW, OM_GET)

        LABEL_Key (UWORD)
            For getting the key that was underscored in text passed with
            LABEL_Text.

            Applicability is (OM_GET)

    SEE ALSO
        intuition.library/GetScreenDrawInfo()


label_ic/LABEL_GetClass

    NAME
        LABEL_GetClass -- Gets the pointer to the label image class.

    SYNOPSIS
        label_class = LABEL_GetClass();
        D0

        Class * LABEL_GetClass(VOID);

    FUNCTION
        Obtains the pointer to the Label gadget class for use with
        NewObject().  This function always returns a valid pointer so
        you do not need to check it.  The reason is that if the library
        opens fine, then the pointer returned is already setup.  (Of course
        this implies that if opening the library fails, you shouldn't be
        calling this.)

        Note that this function does not create the class, that is done
        when the class library is opened.

    INPUTS
        Nothing.

    RESULT
        label_class - Pointer to the Label gadget class.

    SEE ALSO


layers.doc

     BeginUpdate()
     BehindLayer()
     CreateBehindHookLayer()
     CreateBehindLayer()
     CreateUpfrontHookLayer()
     CreateUpfrontLayer()
     DeleteLayer()
     DisposeLayerInfo()
     DoHookClipRects()
     EndUpdate()
     FattenLayerInfo()
     InitLayers()
     InstallClipRegion()
     InstallLayerHook()
     InstallLayerInfoHook()
     LockLayer()
     LockLayerInfo()
     LockLayers()
     MoveLayer()
     MoveLayerInFrontOf()
     MoveSizeLayer()
     NewLayerInfo()
     ScrollLayer()
     SizeLayer()
     SwapBitsRastPortClipRect()
     ThinLayerInfo()
     UnlockLayer()
     UnlockLayerInfo()
     UnlockLayers()
     UpfrontLayer()
     WhichLayer()


layers.library/BeginUpdate

    NAME
    BeginUpdate -- Prepare to repair damaged layer.

    SYNOPSIS
    result = BeginUpdate( l )
    d0                    a0

    LONG BeginUpdate( struct Layer *);

    FUNCTION
    Convert damage list to ClipRect list and swap in for
    programmer to redraw through. This routine simulates
    the ROM library environment. The idea is to only render in the
    "damaged" areas, saving time over redrawing all of the layer.
    The layer is locked against changes made by the layer library.

    INPUTS
    l - pointer to a layer

    RESULTS
    result - TRUE if damage list converted to ClipRect list successfully.
             FALSE if list conversion aborted. (probably out of memory)

    BUGS
    If BeginUpdate returns FALSE, programmer must abort the attempt to
    refresh this layer and instead call EndUpdate( l, FALSE ) to restore
    original ClipRect and damage list.

    SEE ALSO
    EndUpdate(), graphics/layers.h, graphics/clip.h


layers.library/CreateBehindHookLayer

    NAME                                                              (V36)
    CreateBehindHookLayer -- Create a new layer behind all existing layers,
                             using supplied callback BackFill hook.

    SYNOPSIS
    result = CreateBehindHookLayer(li,bm,x0,y0,x1,y1,flags,hook,[,bm2])
    d0                             a0 a1 d0 d1 d2 d3 d4    a3   [ a2 ]

    struct Layer *CreateBehindHookLayer(struct Layer_Info *, struct BitMap *,
        LONG, LONG, LONG, LONG, LONG, struct Hook *, ... );

    FUNCTION
    Create a new Layer of position and size (x0,y0)->(x1,y1)
    Make this layer of type found in flags.
    Install Layer->BackFill callback Hook.
    If SuperBitMap, use bm2 as pointer to real SuperBitMap,
    and copy contents of Superbitmap into display layer.
    If this layer is a backdrop layer then place it behind all
    other layers including other backdrop layers. If this is
    not a backdrop layer then place it behind all nonbackdrop
    layers.

    Note: when using SUPERBITMAP, you should also set LAYERSMART flag.

    INPUTS
    li - pointer to LayerInfo structure
    bm - pointer to common BitMap used by all Layers
    x0,y0 - upper left hand corner of layer
    x1,y1 - lower right hand corner of layer
    flags - various types of layers supported as bit sets.
            (for bit definitions, see graphics/layers.h )
    hook -  Layer->BackFill callback Hook (see InstallLayerHook())

            If hook is LAYERS_BACKFILL, the default backfill is
            used for the layer.  (Same as pre-2.0)

            As of V39:
        If hook is LAYERS_NOBACKFILL, the layer will not be
            backfilled (NO-OP).

    bm2 - pointer to optional Super BitMap

    RESULTS
    result - pointer to Layer structure if successful
             NULL if not successful

    BUGS

    SEE ALSO
    InstallLayerHook(), DeleteLayer(), graphics/layers.h, graphics/clip.h,
    graphics/gfx.h, utility/hooks.h


layers.library/CreateBehindLayer

    NAME
    CreateBehindLayer -- Create a new layer behind all existing layers.

    SYNOPSIS
    result = CreateBehindLayer(li,bm,x0,y0,x1,y1,flags [,bm2])
    d0                         a0 a1 d0 d1 d2 d3   d4  [ a2 ]

    struct Layer *CreateBehindLayer(struct Layer_Info *, struct BitMap *,
        LONG, LONG, LONG, LONG, LONG, ... );

    FUNCTION
    Create a new Layer of position and size (x0,y0)->(x1,y1)
    Make this layer of type found in flags.
    If SuperBitMap, use bm2 as pointer to real SuperBitMap,
    and copy contents of Superbitmap into display layer.
    If this layer is a backdrop layer then place it behind all
    other layers including other backdrop layers. If this is
    not a backdrop layer then place it behind all nonbackdrop
    layers.

    Note: when using SUPERBITMAP, you should also set LAYERSMART flag.

    INPUTS
    li - pointer to LayerInfo structure
    bm - pointer to common BitMap used by all Layers
    x0,y0 - upper left hand corner of layer
    x1,y1 - lower right hand corner of layer
    flags - various types of layers supported as bit sets.
            (for bit definitions, see graphics/layers.h )
    bm2 - pointer to optional Super BitMap

    RESULTS
    result - pointer to Layer structure if successful
             NULL if not successful

    BUGS

    SEE ALSO
    DeleteLayer(), graphics/layers.h, graphics/clip.h, graphics/gfx.h


layers.library/CreateUpfrontHookLayer

    NAME                                                              (V36)
    CreateUpfrontHookLayer -- Create a new layer on top of existing layers,
                              using supplied callback BackFill hook.

    SYNOPSIS
    result = CreateUpfrontHookLayer(li,bm,x0,y0,x1,y1,flags,hook,[,bm2])
    d0                              a0 a1 d0 d1 d2 d3   d4  a3   [ a2 ]

    struct Layer *CreateUpfrontHookLayer(struct Layer_Info *, struct BitMap *,
        LONG, LONG, LONG, LONG, LONG, struct Hook *, ... );

    FUNCTION
    Create a new Layer of position and size (x0,y0)->(x1,y1)
    and place it on top of all other layers.
    Make this layer of type found in flags
    Install Layer->BackFill callback hook.
    if SuperBitMap, use bm2 as pointer to real SuperBitMap.
    and copy contents of Superbitmap into display layer.

    Note: when using SUPERBITMAP, you should also set LAYERSMART flag.

    INPUTS
    li - pointer to LayerInfo structure
    bm - pointer to common BitMap used by all Layers
    x0,y0 - upper left hand corner of layer
    x1,y1 - lower right hand corner of layer
    flags - various types of layers supported as bit sets.
    hook -  Layer->BackFill callback Hook (see InstallLayerHook())

            If hook is LAYERS_BACKFILL, the default backfill is
            used for the layer.  (Same as pre-2.0)

            As of V39:
        If hook is LAYERS_NOBACKFILL, the layer will not be
            backfilled (NO-OP).

    bm2 - pointer to optional Super BitMap

    RESULTS
    result - pointer to Layer structure if successful
             NULL if not successful

    BUGS

    SEE ALSO
    InstallLayerHook(), DeleteLayer(), graphics/layers.h, graphics/clip.h,
    graphics/gfx.h, utility/hooks.h


layers.library/CreateUpfrontLayer

    NAME
    CreateUpfrontLayer -- Create a new layer on top of existing layers.

    SYNOPSIS
    result = CreateUpfrontLayer(li,bm,x0,y0,x1,y1,flags [,bm2])
    d0                          a0 a1 d0 d1 d2 d3   d4  [ a2 ]

    struct Layer *CreateUpfrontLayer(struct Layer_Info *, struct BitMap *,
        LONG, LONG, LONG, LONG, LONG, ... );

    FUNCTION
    Create a new Layer of position and size (x0,y0)->(x1,y1)
    and place it on top of all other layers.
    Make this layer of type found in flags
    if SuperBitMap, use bm2 as pointer to real SuperBitMap.
    and copy contents of Superbitmap into display layer.

    Note: when using SUPERBITMAP, you should also set LAYERSMART flag.

    INPUTS
    li - pointer to LayerInfo structure
    bm - pointer to common BitMap used by all Layers
    x0,y0 - upper left hand corner of layer
    x1,y1 - lower right hand corner of layer
    flags - various types of layers supported as bit sets.
    bm2 - pointer to optional Super BitMap

    RESULTS
    result - pointer to Layer structure if successful
             NULL if not successful

    BUGS

    SEE ALSO
       DeleteLayer(), graphics/layers.h, graphics/clip.h, graphics/gfx.h


layers.library/DisposeLayerInfo

    NAME
    DisposeLayerInfo -- Return all memory for LayerInfo to memory pool

    SYNOPSIS
    DisposeLayerInfo( li )
                      a0

    void DisposeLayerInfo( struct Layer_Info *);

    FUNCTION
    return LayerInfo and any other memory attached to this LayerInfo
    to memory allocator.

    Note: if you wish to delete the layers associated with this Layer_Info
        structure, remember to call DeleteLayer() for each of the layers
        before calling DisposeLayerInfo().

    INPUTS
    li - pointer to LayerInfo structure

    EXAMPLE

    -- delete the layers associated this Layer_Info structure --

    DeleteLayer(li,simple_layer);
    DeleteLayer(li,smart_layer);

    -- see documentation on DeleteLayer about deleting SuperBitMap layers --
    my_super_bitmap_ptr = super_layer->SuperBitMap;
    DeleteLayer(li,super_layer);

    -- now dispose of the Layer_Info structure itself --
    DisposeLayerInfo(li);

    BUGS

    SEE ALSO
    DeleteLayer(), graphics/layers.h


layers.library/DoHookClipRects

    NAME
    DoHookClipRects - Do the given hook for each of the ClipRects    (V39)

    SYNOPSIS
    DoHookClipRects(hook,rport,rect)
                    a0   a1    a2

    void DoHookClipRects(struct Hook *,struct RastPort *,struct Rectangle *);

    FUNCTION
    This function will call the given hook for each cliprect in the
    layer that can be rendered into.  This is how the backfill hook
    in Layers is implemented.  This means that hidden simple-refresh
    cliprects will be ignored.  It will call the SuperBitMap cliprects,
    smart refresh off-screen cliprects, and all on screen cliprects.
    If the rect parameter is not NULL, the cliprects are bounded to
    the rectangle given.

    INPUTS
    hook - pointer to layer callback Hook which will be called
           with object == (struct RastPort *) result->RastPort
           and message == [ (Layer *) layer, (struct Rectangle) bounds,
                            (LONG) offsetx, (LONG) offsety ]

           This hook should fill the Rectangle in the RastPort
           with the BackFill pattern appropriate for offset x/y.

           If hook is LAYERS_BACKFILL, the default backfill is
           used for the layer.

           If hook is LAYERS_NOBACKFILL, the layer will not be
           backfilled (NO-OP).

    rport- A pointer to the RastPort that is to be operated on.
           This function will lock the layer if the RastPort is
           layered...
           If the rport is non-layered your hook will be called with
           the rectangle as passed, the RastPort, and a NULL layer...

    rect - The bounding rectangle that should be used on the layer.
           This rectangle "clips" the cliprects to the bound given.
           If this is NULL, no bounding will take place.
           *MUST* not be NULL if the RastPort is non-layered!

    NOTES
    The RastPort you are passed back is the same one passed to the
    function.  You should *not* use "layered" rendering functions
    on this RastPort.  Generally, you will wish to do BitMap operations
    such as BltBitMap().  The callback is a raw, low-level rendering
    call-back.  If you need to call a rendering operation with a
    RastPort, make sure you use a copy of the RastPort and NULL the
    Layer pointer.

    SEE ALSO
    graphics/clip.h utility/hooks.h


layers.library/EndUpdate

    NAME
    EndUpdate -- remove damage list and restore state of layer to normal.

    SYNOPSIS
    EndUpdate( l, flag )
               a0  d0

    void EndUpdate( struct Layer *, UWORD);

    FUNCTION
    After the programmer has redrawn his picture he calls this
    routine to restore the ClipRects to point to his standard
    layer tiling. The layer is then unlocked for access by the
    layer library.

    Note: use flag = FALSE if you are only making a partial update.
        You may use the other region functions (graphics functions such as
        OrRectRegion, AndRectRegion, and XorRectRegion ) to clip adjust
        the DamageList to reflect a partial update.

    INPUTS
    l - pointer to a layer
    flag - use TRUE if update was completed. The damage list is cleared.
           use FALSE if update not complete. The damage list is retained.

    EXAMPLE

    -- begin update for first part of two-part refresh --
    BeginUpdate(my_layer);

    -- do some refresh, but not all --
    my_partial_refresh_routine(my_layer);

    -- end update, false (not completely done refreshing yet) --
    EndUpdate(my_layer, FALSE);

    -- begin update for last part of refresh --
    BeginUpdate(my_layer);

    -- do rest of refresh --
    my_complete_refresh_routine(my_layer);

    -- end update, true (completely done refreshing now) --
    EndUpdate(my_layer, TRUE);

    BUGS

    SEE ALSO
    BeginUpdate(), graphics/layers.h, graphics/clip.h


layers.library/FattenLayerInfo

    NAME
    FattenLayerInfo -- convert 1.0 LayerInfo to 1.1 LayerInfo
    OBSOLETE OBSOLETE OBSOLETE OBSOLETE OBSOLETE

    SYNOPSIS
    OBSOLETE OBSOLETE OBSOLETE OBSOLETE OBSOLETE
    FattenLayerInfo( li )
                     a0

    LONG FattenLayerInfo( struct Layer_Info *);
    OBSOLETE OBSOLETE OBSOLETE OBSOLETE OBSOLETE

    FUNCTION
    V1.1 software and any later releases need to have more info in the
    Layer_Info structure. To do this in a 1.0 supportable manner requires
    allocation and deallocation of the memory whenever most
    layer library functions are called.  To prevent unnecessary
    allocation/deallocation FattenLayerInfo will preallocate the
    necessary data structures and fake out the layer library into
    thinking it has a LayerInfo gotten from NewLayerInfo.
    NewLayerInfo is the approved method for getting this structure.
    When a program needs to give up the LayerInfo structure it
    must call ThinLayerInfo before freeing the memory. ThinLayerInfo
    is not necessary if New/DisposeLayerInfo are used however.

    INPUTS
    li - pointer to LayerInfo structure

    BUGS

    SEE ALSO

    NewLayerInfo(), ThinLayerInfo(), DisposeLayerInfo(), graphics/layers.h


layers.library/InitLayers

    NAME
    InitLayers -- Initialize Layer_Info structure
    OBSOLETE OBSOLETE OBSOLETE OBSOLETE OBSOLETE

    SYNOPSIS
    OBSOLETE OBSOLETE OBSOLETE OBSOLETE OBSOLETE
    InitLayers( li )
                a0

    void InitLayers( struct Layer_Info *);
    OBSOLETE OBSOLETE OBSOLETE OBSOLETE OBSOLETE

    FUNCTION
    Initialize Layer_Info structure in preparation to use
    other layer operations on this list of layers.
    Make the Layers unlocked (open), available to layer operations.

    INPUTS
    li - pointer to LayerInfo structure

    BUGS

    SEE ALSO
    NewLayerInfo(), DisposeLayerInfo(), graphics/layers.h


layers.library/InstallClipRegion

    NAME
    InstallClipRegion -- Install clip region in layer

    SYNOPSIS
    oldclipregion = InstallClipRegion( l,  region )
    d0                                 a0  a1

    struct Region *InstallClipRegion( struct Layer *, struct Region *);

    FUNCTION
    Installs a transparent Clip region in the layer. All
    subsequent graphics calls will be clipped to this region.
    You MUST remember to call InstallClipRegion(l,NULL) before
    calling DeleteLayer(l) or the Intuition function CloseWindow()
     if you have installed a non-NULL ClipRegion in l.

    INPUTS
    l - pointer to a layer
    region - pointer to a region

    RESULTS
    oldclipregion - The pointer to the previous ClipRegion that
        was installed. Returns NULL if no previous ClipRegion installed.

        Note: If the system runs out of memory while computing the
            resulting ClipRects the LAYERS_CLIPRECTS_LOST bit will
            be set in l->Flags.

    BUGS
    If the system runs out of memory during normal layer operations,
    the ClipRect list may get swept away and not restored.
    As soon as there is enough memory and the layer library
    gets called again the ClipRect list will be rebuilt.

    SEE ALSO
    BeginUpdate() EndUpdate(),
    graphics/layers.h, graphics/clip.h, graphics/regions.h


layers.library/InstallLayerHook

    NAME
    InstallLayerHook -- safely install a new Layer->BackFill hook.    (V36)

    SYNOPSIS
    oldhook = InstallLayerHook( layer, hook )
    d0                          a0     a1

    struct Hook *InstallLayerHook( struct Layer *, struct Hook *);

    FUNCTION
    Installs a new Layer->Backfill Hook, waiting until it is safe to do
    so. Locks the layer while substituting the new Hook and removing the
    old one. If a new Hook is not provided, will install the default layer
    BackFill Hook.

    INPUTS
    layer - pointer to the layer in which to install the Backfill Hook.
    hook -  pointer to layer callback Hook which will be called
            with object == (struct RastPort *) result->RastPort
            and message == [ (Layer *) layer, (struct Rectangle) bounds,
                             (LONG) offsetx, (LONG) offsety ]

            This hook should fill the Rectangle in the RastPort
            with the BackFill pattern appropriate for offset x/y.

            If hook is LAYERS_BACKFILL, the default backfill is
            used for the layer.  (Same as pre-2.0)

            As of V39:
        If hook is LAYERS_NOBACKFILL, the layer will not be
            backfilled (NO-OP).

    RESULTS
    oldhook - pointer to the Layer->BackFill Hook that was previously
              active.  Returns NULL if it was the default hook.
          In V39, it could return 1 if there was no hook.

    EXAMPLE
    The following hook is a very simple example that does rather little
    but gives the basis idea of what is going on.

    *
    * This is the code called by the layer hook...
    * Note that some other setup is required for this to work, including
    * the definition of the PrivateData structure (pd_...) and the
    * definition of the BitMapPattern structure (bmp_...)
    *
    CoolHook:	xdef	CoolHook
            movem.l	d2-d7/a3-a6,-(sp)	; Save these...
            move.l	h_SubEntry(a0),a4	; (my private data #1 here)
            move.l	h_Data(a0),a5		; Put data into address reg
    *
    * Now, we do the rendering...
    * Note that the layer may not be important...  But it is here...
    *
            move.l	(a1)+,a0		; Get the layer...
    *
    * a1 now points at the rectangle...
    *
            move.l	pd_GfxBase(a4),a6	; Point at GfxBase
            move.l	bmp_Pattern(a5),d0	; Get PatternBitMap
            beq	SimpleCase		; None?  Simple (0) case
    *
    * Now do the complex case of a pattern...
    *
            move.l	a1,a3			; Pointer to rectangle
            addq.l	#8,a1			; Get past rectangle
            move.l	(a1)+,d2		; X Offset (For pattern)
            move.l	(a1)+,d3		; Y Offset
        ;
        ; Whatever complex blitting you would do in the complex case
        ; goes here
        ;
    *
    * No bitmap, so just do the simple (0) minterm case...
    *
    SimpleCase:	moveq.l	#0,d2			; Clear d2
            move.w	ra_MinX(a1),d2		; Get X pos
    *
            moveq.l	#0,d3
            move.w	ra_MinY(a1),d3		; Get Y pos
    *
            moveq.l	#0,d4
            move.w	ra_MaxX(a1),d4
            sub.l	d2,d4
            addq.l	#1,d4			; Get X size
    *
            moveq.l	#0,d5
            move.w	ra_MaxY(a1),d5
            sub.l	d3,d5
            addq.l	#1,d5			; Get Y size
    *
            move.l	d2,d0			; X Source
            move.l	d3,d1			; Y Source
            moveq.l	#0,d6			; NULL minterm
            moveq.l	#-1,d7			; FF mask
    *
            move.l	rp_BitMap(a2),a1	; Get bitmap
            move.l	a1,a0
            CALLSYS	BltBitMap		; Do the backfill-0
    *
    HookDone:	movem.l	(sp)+,d2-d7/a3-a6	; Restore
            rts

    NOTES
    The RastPort you are passed back is the same one passed to the
    function.  You should *not* use "layered" rendering functions
    on this RastPort.  Generally, you will wish to do BitMap operations
    such as BltBitMap().  The callback is a raw, low-level rendering
    call-back.  If you need to call a rendering operation with a
    RastPort, make sure you use a copy of the RastPort and NULL the
    Layer pointer.

    BUGS

    SEE ALSO
    graphics/clip.h utility/hooks.h


layers.library/InstallLayerInfoHook

    NAME
    InstallLayerInfoHook - Install a backfill hook for non-layer      (V39)

    SYNOPSIS
    oldhook=InstallLayerInfoHook(li,hook)
    d0                           a0 a1

    struct Hook *InstallLayerInfoHook(struct Layer_Info *,struct Hook *);

    FUNCTION
    This function will install a backfill hook for the Layer_Info
    structure passed.  This backfill hook will be used to clear the
    background area where no layer exists.  The hook function is
    passed the RastPort and the bounds just like the layer backfill
    hook.  Note that this hook could be called for any layer.

    INPUTS
    li - pointer to LayerInfo structure

    hook -  pointer to layer callback Hook which will be called
            with object == (struct RastPort *) result->RastPort
            and message == [ (ULONG) undefined, (struct Rectangle) bounds ]

            This hook should fill the Rectangle in the RastPort
            with the BackFill pattern appropriate for rectangle given.

            If hook is LAYERS_BACKFILL, the default backfill is
            used.  (Same as pre-2.0)

        If hook is LAYERS_NOBACKFILL, there will be no
            backfill.  (NO-OP).

    RESULTS
    oldhook - Returns the backfill hook that was in the Layer_Info.
              Returns LAYERS_BACKFILL if the default was installed.
              Returns LAYERS_NOBACKFILL if there was a NO-OP hook.
              Returns -1 if there was some failure.

    EXAMPLE
    See the example in InstallLayerHook.  Note that both the Layer
    pointer and the OffsetX/Y values are not available in the
    LayerInfo backfill hook.

    NOTES
    When the hook is first installed, it is *NOT* called.  It is up
    to the application to know if it is safe to fill in the area.
    Since the hook will be called when a layer is deleted, the easiest
    way to have layers call this hook is to create and delete a backdrop
    layer that is the size of the area.

    Also, note that currently the first long word of the hook message
    contains an undefined value.  This value may look like a layer pointer.
    It is *not* a layer pointer.

    The RastPort you are passed back is the same one passed to the
    function.  You should *not* use "layered" rendering functions
    on this RastPort.  Generally, you will wish to do BitMap operations
    such as BltBitMap().  The callback is a raw, low-level rendering
    call-back.  If you need to call a rendering operation with a
    RastPort, make sure you use a copy of the RastPort and NULL the
    Layer pointer.

    SEE ALSO
    InstallLayerHook()


layers.library/LockLayer

    NAME
    LockLayer -- Lock layer to make changes to ClipRects.

    SYNOPSIS
    LockLayer( dummy, l )
               a0     a1

    void LockLayer( LONG, struct Layer *);

    FUNCTION
    Make this layer unavailable for other tasks to use.
    If another task is already using this layer then wait for
    it to complete and then reserve the layer for your own use.
    (this function does the same thing as graphics.library/LockLayerRom)

    Note: if you wish to lock MORE THAN ONE layer at a time, you
        must call LockLayerInfo() before locking those layers and
        then call UnlockLayerInfo() when you have finished. This
        is to prevent system "deadlocks".

    Further Note: while you hold the lock on a layer, Intuition will block
        on operations such as windowsizing, dragging, menus, and depth
        arranging windows in this layer's screen.  It is recommended that
        YOU do not make Intuition function calls while the layer is locked.

    INPUTS
    dummy - unused
    l - pointer to a layer

    BUGS

    SEE ALSO
    UnlockLayer(), LockLayerInfo(), UnlockLayerInfo(),
    graphics.library/LockLayerRom(), graphics/layers.h, graphics/clip.h


layers.library/LockLayerInfo

    NAME
    LockLayerInfo -- Lock the LayerInfo structure.

    SYNOPSIS
    LockLayerInfo( li )
                   a0

    void LockLayerInfo( struct Layer_Info *);

    FUNCTION
    Before doing an operation that requires the LayerInfo
    structure, make sure that no other task is also using the
    LayerInfo structure.  LockLayerInfo() returns when the
    LayerInfo belongs to this task.  There should be
    an UnlockLayerInfo for every LockLayerInfo.

    Note: All layer routines presently LockLayerInfo() when they
    start up and UnlockLayerInfo() as they exit.  Programmers
    will need to use these Lock/Unlock routines if they wish
    to do something with the LayerStructure that is not
    supported by the layer library.

    INPUTS
    li - pointer to Layer_Info structure

    BUGS

    SEE ALSO
    UnlockLayerInfo(), graphics/layers.h


layers.library/LockLayers

    NAME
    LockLayers -- lock all layers from graphics output.

    SYNOPSIS
    LockLayers( li )
                a0

    void LockLayers( struct Layer_Info *);

    FUNCTION
    First calls LockLayerInfo()
    Make all layers in this layer list locked.

    INPUTS
    li - pointer to Layer_Info structure

    BUGS

    SEE ALSO
    LockLayer(), LockLayerInfo(), graphics/layers.h


layers.library/MoveLayer

    NAME
    MoveLayer -- Move layer to new position in BitMap.

    SYNOPSIS
    result = MoveLayer( dummy, l, dx, dy )
    d0                  a0     a1 d0  d1

    LONG MoveLayer( LONG, struct Layer *, LONG, LONG);

    FUNCTION
    Move this layer to new position in shared BitMap.
    If any refresh layers become revealed, collect damage and
    set REFRESH bit in layer Flags.

    INPUTS
    dummy - unused
    l - pointer to a nonbackdrop layer
    dx - delta to add to current x position
    dy - delta to add to current y position

    RETURNS
    result - TRUE if operation successful
             FALSE if failed (out of memory)

    BUGS
    May not handle (dx,dy) which attempts to move the layer outside the
    layer's RastPort->BitMap bounds .

    SEE ALSO
    graphics/layers.h, graphics/clip.h


layers.library/ScrollLayer

    NAME
    ScrollLayer -- Scroll around in a superbitmap, translate coordinates
                      in non-superbitmap layer.

    SYNOPSIS
    ScrollLayer( dummy, l, dx, dy )
                 a0     a1 d0  d1

    void ScrollLayer( LONG, struct Layer *, LONG, LONG);

    FUNCTION
    For a SuperBitMap Layer:
    Update the SuperBitMap from the layer display, then copy bits
    between Layer and SuperBitMap to reposition layer over different
    portion of SuperBitMap.
    For nonSuperBitMap layers, all (x,y) pairs are adjusted by
    the scroll(x,y) value in the layer.  To cause (0,0) to actually
    be drawn at (3,10) use ScrollLayer(-3,-10). This can be useful
    along with InstallClipRegion to simulate Intuition GZZWindows
    without the overhead of an extra layer.

    INPUTS
    dummy - unused
    l - pointer to a layer
    dx - delta to add to current x scroll value
    dy - delta to add to current y scroll value

    BUGS
    May not handle (dx,dy) which attempts to move the layer outside the
    layer's SuperBitMap bounds.

    SEE ALSO
    graphics/layers.h


layers.library/SwapBitsRastPortClipRectayers.library/SwapBitsRastPortClipRect

    NAME
    SwapBitsRastPortClipRect -- Swap bits between common bitmap
                                and obscured ClipRect

    SYNOPSIS
    SwapBitsRastPortClipRect( rp, cr )
                              a0  a1

    void SwapBitsRastPortClipRect( struct RastPort *, struct ClipRect *);

    FUNCTION
    Support routine useful for those that need to do some
    operations not done by the layer library.  Allows programmer
    to swap the contents of a small BitMap with a subsection of
    the display. This is accomplished without using extra memory.
    The bits in the display RastPort are exchanged with the
    bits in the ClipRect's BitMap.

    Note: the ClipRect structures which the layer library allocates are
    actually a little bigger than those described in the graphics/clip.h
    include file.  So be warned that it is not a good idea to have
    instances of cliprects in your code.

    INPUTS
    rp - pointer to rastport
    cr - pointer to cliprect to swap bits with

    NOTE
    Because the blit operation started by this function is done asynchronously,
    it is imperative that a WaitBlit() be performed before releasing or using
    the processor to modify any of the associated structures.

    BUGS

    SEE ALSO
    graphics/clip.h, graphics/rastport.h, graphics/clip.h


layers.library/ThinLayerInfo

    NAME
    ThinLayerInfo -- convert 1.1 LayerInfo to 1.0 LayerInfo.
    OBSOLETE OBSOLETE OBSOLETE OBSOLETE OBSOLETE

    SYNOPSIS
    OBSOLETE OBSOLETE OBSOLETE OBSOLETE OBSOLETE
    ThinLayerInfo( li )
                   a0

    void ThinLayerInfo( struct Layer_Info *);
    OBSOLETE OBSOLETE OBSOLETE OBSOLETE OBSOLETE

    FUNCTION
    return the extra memory needed that was allocated with
    FattenLayerInfo. This is must be done prior to freeing
    the Layer_Info structure itself. V1.1 software should be
    using DisposeLayerInfo.

    INPUTS
    li - pointer to LayerInfo structure

    BUGS

    SEE ALSO
    DisposeLayerInfo(), FattenLayerInfo(), graphics/layers.h


layers.library/UnlockLayerInfo

    NAME
    UnlockLayerInfo -- Unlock the LayerInfo structure.

    SYNOPSIS
    UnlockLayerInfo( li )
                     a0

    void UnlockLayerInfo( struct Layer_Info *);

    FUNCTION
    After the operation is complete that required a LockLayerInfo,
    unlock the LayerInfo structure so that  other tasks may
    affect the layers.

    INPUTS
    li - pointer to the Layer_Info structure

     BUGS

     SEE ALSO
    LockLayerInfo(), graphics/layers.h


layers.library/UnlockLayers

    NAME
    UnlockLayers -- Unlock all layers from graphics output.
                    Restart graphics output to layers that have been waiting

    SYNOPSIS
    UnlockLayers( li )
                  a0

    void UnlockLayers( struct Layer_Info *);

    FUNCTION
    Make all layers in this layer list unlocked.
    Then call UnlockLayerInfo

    INPUTS
    li - pointer to the Layer_Info structure

    BUGS

    SEE ALSO
    LockLayers(), UnlockLayer(), graphics/layers.h


layout_gc.doc

     --datasheet--
     ActivateLayoutGadget()
     FlushLayoutDomainCache()
     LAYOUT_GetClass()
     LayoutLimits()
     RethinkLayout()


layout_gc/--datasheet--

    NAME
        layout.gadget-- An automatic GUI layout arrangement gadget.

    SUPERCLASS
        gadgetclass

    REQUIRES
        bevel.image

    DESCRIPTION
        The layout gadget is used to automatically calculate the
        positions and sizes of BOOPSI gadgets and images in a resizable
        window. Instead of handling the positions of gadgets by hand,
        you can just describe your window layout in a hierarchical
        fashion, and the layout gadget will do the rest.

        The basic method of layout of a group is as follows:
        - Calculate the minimum and maximum size of each gadget.
        - Calculate the weight totals for the group. Substract the size
          of the fixed size (weighted size 0) gadgets from the total
          size of the group.
        - Distribute the remaining space in the group according to the
          relative weighs of the children.
        - If extra space remains, distribute it evenly between the
          children.

    PRIVATE METHODS
        LAYOUT_ACTIVATEOBJECT -- Used by ActivateLayoutGadget(), sets
        the handleinput path to a gadget somewhere in a layout hierarchy.

        LAYOUT_TABCYCLE -- Sets the gadget attributes based on the
        gadget in the end of the handleinput path.

        LAYOUT_FIRSTCYCLE -- Sets the handleinput path to the first tab
        cycle gadget in a layout hierarchy.

        LAYOUT_LASTCYCLE -- Sets the handleinput path to the last tab
        cycle gadget in a layout hierarchy.

        LAYOUT_FLUSHDOMAINS -- Flushes all domain caches below a certain
        level.

        LAYOUT_FINDKEY -- Find a gadget with a key in the CommKey list.

        LAYOUT_FINDACTIVE -- Find the active gadget pointer.

        LAYOUT_FINDHELP -- Find the last gadget that returned helphit.

    METHODS
        GM_HANDLEINPUT -- Passed to the currently active child

        GM_DOMAIN -- Passed to all children

        GM_RENDER -- Passed to all children When invoked
            by input.device, the stack is first swapped to provide
            more workspace.

        GM_LAYOUT -- Passed to all children after first setting
            their size and position with SetAttrs. When invoked
            by input.device, the stack is first swapped to provide
            more workspace.

        GM_HITTEST -- Passed to the child in whose domain
            rectangle the pointer is

        GM_HELPTEST -- Passed to the child in whose domain
            rectangle the pointer is

        GM_GOACTIVE -- Passed to the currently "active" child (one
            that returned GM_HITTEST)

        GM_GOINACTIVE -- Passed to the currently active child

        OM_SET -- Passed to superclass after scanning the
            taglist for layout specific tags

        OM_UPDATE -- Passed to superclass after scanning the
            taglist for layout specific tags

        OM_GET -- Passed to superclass for non-layout tags

        OM_NEW -- Passed to superclass, then adding all the
            children on the taglist to the private list.

        OM_DISPOSE -- Passed to all children (thus disposing all
            of them), then to superclass.

        GM_CLIPRECT -- Passed to all children.

        DTM_PROCLAYOUT -- Like GM_LAYOUT, but passes DTM_PROCLAYOUT
            forward. Useful if the layout group contains only
            datatype objects.

        All other methods are passed to the superclass.

  ATTRIBUTES
      Attributes global to the whole layout group. Pass all of these
      BEFORE adding child objects:

      GA_ReadOnly (BOOL)
          Disables input to the entire layout group and its chidren.
          This tag is NOT propagated to children. The input blocking
          occurs within the layout object itself.

          Defaults to FALSE

          Applicability is (OM_NEW, OM_SET, OM_UPDATE)

      GA_Disabled (BOOL)
          Disables entire layout group and its chidren. This tag
          is propagated all children. When setting/clearing this
          tag, take care to re-set/re-clear any children you want
          included from this mass disabling ability.

          Defaults to FALSE

          Applicability is (OM_NEW, OM_SET, OM_UPDATE)

      GA_TextAttr (struct TextAttr *)
          The font that will be used for the group label.

          Defaults to NULL (uses rastport default font).

          Applicability is (OM_NEW)

      LAYOUT_Orientation (ULONG)
          Whether the objects of this group are arranged horizontally or
          vertically. Possible values are LORIENT_HORIZONTAL and
          LORIENT_VERTICAL.

          Defaults to LORIENT_HORIZONTAL.

          Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET)

      LAYOUT_FixedHoriz (BOOL)
          Whether the width of this layout group is fixed to the width
          assigned by the window or parent layout group. If set to FALSE,
          the gadget will minimize its width to the smallest possible
          value. Generally you will have to also set LAYOUT_ShrinkWrap
          (below) to TRUE also. It is recommended that this tag is used
          only in the top layout group. Using a weighted width of 0 gives
          more predictable results elsewhere.

          Defaults to TRUE.

          Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET)

      LAYOUT_FixedVert (BOOL)
          Whether the height of this layout group is fixed to the height
          assigned by the window or parent layout group. If set to FALSE,
          the gadget will minimize its height to the smallest possible
          value. Generally you will have to also set LAYOUT_ShrinkWrap
          (below) to TRUE also. It is recommended that this tag is used
          only in the top layout group. Using a weighted height of 0 gives
          more predictable results elsewhere.

          Defaults to TRUE.

          Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET)

      LAYOUT_HorizAlignment (ULONG)
          The horizontal alignment of the objects in this layout group.
          Possible values are LALIGN_LEFT, LALIGN_RIGHT, and
          LALIGN_CENTER.

          Defaults to LALIGN_LEFT.

          Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET)

      LAYOUT_VertAlignment (ULONG)
          The vertical alignment of the objects in this layout group.
          Possible values are LALIGN_TOP, LALIGN_BOTTOM, and
          LALIGN_CENTER.

          Defaults to LALIGN_TOP.

          Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET)

      LAYOUT_ShrinkWrap (BOOL)
          If set to TRUE, the layout group will shrink the interspacing
          of the child objects to minimum. Normally all extra space (if
          the total maximum size of the child objects is less than the
          size of the layoutgroup) is evenly distributed between the
          gadgets.

          Defaults to FALSE.

          Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET)

      LAYOUT_EvenSize (BOOL)
          If TRUE, the layout group will try to reserve enough space to
          make the minimum size of each child object equal to the minimum
          of the largest child. Using this attribute makes it possible to
          have neatly arranged horizontal rows or grids of gadgets. This
          can take quite a bit of room, however, depending on the gadgets.

          Defaults to FALSE.

          Applicability is (OM_NEW, OM_SET, OM_UPDATE)

      LAYOUT_SpaceInner (BOOL)
         Should layout leave space between objects or not. Set to FALSE
         if objects in a group should be put immediately beside each
         other.

         Defaults to TRUE.

         Applicability is (OM_NEW, OM_SET, OM_UPDATE)

      LAYOUT_SpaceOuter (BOOL)
         Should layout leave space around the group's objects or not.
         Set to TRUE if the objects should not be laid out using the
         whole group container box (for example if the group has a
         bevel around it).

         Defaults to FALSE.

         Applicability is (OM_NEW, OM_SET, OM_UPDATE)

      LAYOUT_InnerSpacing (ULONG)
          The minimum space left between objects. The value is in "virtual
          pixels", ie absolute pixels assuming bevel is configured for
          thin lines. If bevel configuration is something else, the value
          will be adjusted accordingly.

          Please avoid using this tag, if you do not require absolute
          control over the spacing. The LAYOUT_SpaceInner boolean is
          provided to tell whether there should be spacing or whether
          objects should be immediately connected to each other.

          Defaults to INTERSPACING.

          Applicability is (OM_NEW, OM_SET, OM_UPDATE)

      LAYOUT_TopSpacing
      LAYOUT_BottomSpacing
      LAYOUT_LeftSpacing
      LAYOUT_RightSpacing (ULONG)
          The minimum space left to the top, bottom, left and right of
          the group, respectively. This value is in "virtual pixels", see
          LAYOUT_Spacing above.

          Please avoid using this tag, if you do not require absolute
          control over the spacing. The LAYOUT_SpaceOuter boolean is
          provided to tell whether there should be spacing or whether
          objects should be immediately connected to each other.

          If you use one of these tags to override a LAYOUT_SpaceOuter,
          pass this tag AFTER the LAYOUT_SpaceOuter tag.

          Defaults to 0.

          Applicability is (OM_NEW, OM_SET, OM_UPDATE)

      LAYOUT_BevelStyle (ULONG)
          The style of the bevel drawn around the group. This value is
          passed to bevel.image.

          Defaults to BVS_NONE.

          Applicability is (OM_NEW, OM_SET, OM_UPDATE)

      LAYOUT_BevelState (ULONG)
          The state of the bevel drawn around the group. Used to
          DrawImageState() the bevel.image.

          Defaults to IDS_NORMAL.

          Applicability is (OM_NEW, OM_SET, OM_UPDATE)

      LAYOUT_Label (STRPTR)
          The label drawn in the group bevel. This value is passed to
          bevel.image. Note that if LAYOUT_BevelStyle is set to BVS_NONE,
          no bevel will be rendered, and thus this label will not be used
          either.

          No default (bevel.image default used)

          Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET)

      LAYOUT_LabelImage (Object *)
          The BOOPSI image to use as the group bevel label. Passed to
          bevel.image.

          See LAYOUT_Label.

          Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET)

      LAYOUT_LabelPlace (ULONG)
          The position of the label (See LAYOUT_Label).

          Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET)

      LAYOUT_RemoveChild (Object *)
          Pointer to an object you wish to remove from the layout
          hierarchy. The object will be disposed of, so after using this
          tag, the pointer will be invalid.

          Applicability is (OM_SET)

      LAYOUT_AddChild (Object *)
          Pointer to an object you wish to add to the list of gadgets for
          this layout hierarchy level.

          Applicability is (OM_NEW)

      LAYOUT_AddImage (Object *)
          Same as LAYOUT_AddChild, but will mark the object as an
          imageclass subclass (meaning that IM_DRAW will be used instead
          of GM_RENDER to display it, and that none of the gadgetclass
          methods apply to it).

          Applicability is (OM_NEW)

      LAYOUT_ModifyChild (Object *)
          Inform layout gadget that the following child specific tags in
          the taglist apply to the specified object. LAYOUT_AddChild will
          do this automatically for new objects.

          Applicability is (OM_SET)

      LAYOUT_RelVerify (BOOL)
          When a gadget returns a code that normally makes Intuition send
          an IDCMP_GADGETUP message to the application, layout.gadget
          will send a notification message (OM_NOTIFY, IDCMP_IDCMPUPDATE)
          with the essential information of the gadgetup message. This is
          because in certain situations the IDCMP_GADGETUP message can
          not be sent (in particular, when tab cycling between gadgets).
          The notification will consist of GA_ID set to the ID of the
          gadget in question, this LAYOUT_RelVerify tag set to TRUE, and
          the LAYOUT_RelCode tag (below) set to the gadget's return code
          (IntuiMessage.Code field of the IDCMP_GADGETUP).

          Applicability is (OM_NOTIFY)

      LAYOUT_RelCode (UWORD)
          A copy of the IntuiMessage.Code field of the IDCMP_GADGETUP in
          question, sent via OM_NOTIFY (ie. received as OM_UPDATE or
          IDCMP_IDCMPUPDATE).

          Applicability is (OM_NOTIFY)

      LAYOUT_TabVerify (BOOL)
          If the gadget release was triggered by tab cycling, this
          attribute will be TRUE in the release verify IDCMPUPDATE. This
          lets you distinguish, for example, between pressing tab and
          enter in a string gadget.

          Applicability is (OM_NOTIFY)

      LAYOUT_RelAddress (struct Gadget *)
          Address of the gadget that sent the gadgetup is provided in the
          gadgetup notification using this tag.

          Applicability is (OM_NOTIFY)

      LAYOUT_HelpHit (UWORD)
          When a gadget returns a hit for helptest, the return code, along

          with GA_ID, is notified using this tag.

          Applicability is (OM_NOTIFY)

      LAYOUT_Parent (Object *)
          Set automatically by layout.gadget for all child objects, this
          attribute points to the parent layout object. If NULL, the
          layout object is the window's topmost layout.
          When an object is added to the layout hierarchy, it will
          receive this tag in OM_SET. If you so wish, you may use this to
          let the gadget talk to its parent layout group.
          Any group gadget that should work with layout.gadget must
          support this attribute.

          Applicability is (OM_SET, OM_GET)

      LAYOUT_DeferLayout (BOOL)
          By setting this tag to TRUE in your window's top layout, you
          can defer the layout and refresh process off the input.device
          context to your application. This will make input.device more
          responsive, and drop the (possibly quite heavy) process of
          recalculating the display to normal application priority
          instead of the priority 20
          of input.device. Input handling will be retained in input.device
          context, to keep the GUI responsive.
          If you use this tag, you must listen to LAYOUT_RequestLayout
          and LAYOUT_RequestRefresh notifications and process them in
          prompt manner, or your GUI will not display properly, if at all.

          Applicability is (OM_NEW, OM_SET)

      LAYOUT_RequestLayout (Object *)
          If the above LAYOUT_DeferLayout tag is set to TRUE, the gadget
          will defer GM_LAYOUT methods invoked by input.device and notify
          its IC target with this tag. You should be listening to it in
          your application IDCMP handler (IDCMP_IDCMPUPDATE) and calling
          RethinkLayout with FALSE for refresh flag when receiving one.

          Defaults to FALSE.

          Applicability is (OM_NOTIFY)

      LAYOUT_RequestRefresh (Object *)
          If the above LAYOUT_DeferLayout tag is set to TRUE, the gadget
          will defer GM_RENDER methods invoked by input.device and notify
          its IC target with this tag. You should be listening to it in
          your application IDCMP handler (IDCMP_IDCMPUPDATE) and calling
          RefreshGList when receiving one.

          Defaults to FALSE.

          Applicability is (OM_NOTIFY)

      LAYOUT_TextPen (WORD)
          The pen that will be used for group label text. See bevel.image.

          Applicability is (OM_NEW)

      LAYOUT_FillPen (WORD)
          The pen that will be used for the group fill pattern. See
          bevel.image.

          Applicability is (OM_NEW)

      LAYOUT_FillPattern (UWORD *)
          The fill pattern for the group. See bevel.image.

          Defaults to none.

          Applicability is (OM_NEW)

      GA_BackFill (struct Hook *)
          A layer backfill hook to use in the group to provide a more
          complex background pattern.

          Defaults to clear for the main layout, and none for sublayouts.

          Applicability is (OM_NEW)

      LAYOUT_LabelColumn (ULONG)
          The side where the on which side of the gadget the label will
          be placed in the group. Valid values are PLACETEXT_LEFT and
          PLACETEXT_RIGHT. See CHILD_Label.

          Defaults to PLACETEXT_LEFT.

          Applicability is (OM_NEW, OM_SET, OM_NOTIFY)

      LAYOUT_LabelWidth (ULONG)
          The width of the label column in a vertical group. This attribute
          may be used to justify several layout groups.

          Applicability is (OM_SET, OM_GET)

      LAYOUT_AlignLabels (Object *)
          A pointer to another layout instance that should have equal
          label width with this one. Set to a cycle between all the
          groups, these will automatically justify their labels with each
          other. This attribute should be set as soon as possible, ie. in
          OM_NEW or OM_SET directly afterwards, before the layout size is
          calculated.

          Applicability is (OM_NEW, OM_SET)

      LAYOUT_Inversed (BOOL) (V42.27)
          Causes children to be added to the layout group via
          AddHead() vs AddTail().

          Applicability is (OM_NET, OM_SET)

      Attributes referring to the "current" child object:

      CHILD_MinWidth, CHILD_MinHeight (ULONG)
          The minimum width and height of the object, in pixels. Setting
          this attribute means that GM_DOMAIN is not respected in that
          direction.

          Defaults to ~0, which means that the layout gadget will ask the
          object, using GM_DOMAIN.

          Applicability is (OM_NEW, OM_SET, OM_UPDATE)

      CHILD_MaxWidth, CHILD_MaxHeight (ULONG)
          As above, for the maximum size.

          Applicability is (OM_NEW, OM_SET, OM_UPDATE)

      CHILD_NominalSize (BOOL)
          If this attribute is TRUE, layout will use GDOMAIN_NOMINAL
          instead of GDOMAIN_MINIMUM when requesting the minimum size of
          the gadget. This is useful when the minimum size of a gadget
          looks unattractive, but the gadget will return a more attractive
          size with GDOMAIN_NOMINAL.

          Defaults to FALSE.

          Applicability is (OM_NEW, OM_SET, OM_UPDATE)

      CHILD_WeightedWidth (ULONG)
          The relative width of the child object. See the DESCRIPTION
          above for the layout method. If set to 0, the child will always
          be rendered in the minimum size (specified by either GM_DOMAIN
          or CHILD_MinWidth). Use CHILD_MinWidth and a weighted with of 0
          instead of CHILD_MinWidth and CHILD_MaxWidth. The latter method
          will also work, but will slow down the layout. As a special
          rule, many BOOPSI images using bitmap data can not be resized
          from the initial size. Fix their size by setting MinWidth and
          MinHeight, and the weight to 0.

          Defaults to 100.

          Applicability is (OM_NEW, OM_SET, OM_UPDATE)

      CHILD_WeightedHeight (ULONG)
          The relative height of the child object. See CHILD_WeightedWidth.

          Applicability is (OM_NEW, OM_SET, OM_UPDATE)

      CHILD_WeightMinimum (BOOL)
          Setting this tag to TRUE will make the layout group set the
          weighted width and height to the minimum values set with
          CHILD_MinWidth and CHILD_MinHeight or returned by GM_DOMAIN. This
          allows creating layout groups where the relative size of the
          objects always remains the same. Be warned that if the object
          does not support GM_DOMAIN and minimum size is not set manually,
          the weight will be set to 2 (the default minimum size of an
          object). Normally you would want to set this tag for every
          resizable object in a layout group.

          Defaults to FALSE.

          Applicability is (OM_NEW)

      CHILD_ReplaceObject
          CHILD_ReplaceImage (Object *)
          Replace the current child object with the one specified. The
          current object will be disposed of. See LAYOUT_AddChild,
          LAYOUT_AddImage, LAYOUT_RemoveChild, LAYOUT_ModifyChild.

          Applicability is (OM_SET)

      CHILD_CacheDomain (BOOL)
          To speed up resizing, layout gadget will normally cache the
          first values returned by GM_DOMAIN and use that cache for
          subsequent relayouts, instead of calling GM_DOMAIN again.
          Normally this will have the same results all the time. If you
          have a custom gadget that might return varying values between
          calls to GM_DOMAIN (ie the minimum or maximum size of it could
          vary during runtime), set this tag to FALSE for that object and
          all its parent groups. Note that since layout groups are aware
          of their parent layouts, they can disable caching in the
          hierarchy above them automatically,  if you SetAttr this
          attribute _AFTER_ creating the whole layout hierarchy.

          Defaults to TRUE.

          Applicability is (OM_NEW, OM_SET) (OM_SET preferred)

      CHILD_Label (Object *)
          The imageclass object, preferably label.image, to use as the
          object's label. These labels are supported only left or right
          aligned groups, and will be placed in the left or right of the
          gadget even in horizontal groups. All the labels will take the
          space of the widest label. Label-less objects will be laid out
          in full width; if you want to leave the label column empty, use
          the special value LCLABEL_NOLABEL. Every object in a group gets
          the same amount of space reserved for a label, whether they have
          a label or not. This also (or in particular) applies to
          horizontal groups; usually the correct effect is reached by
          putting the label on the group itself instead of one of the
          objects in it. See LAYOUT_LabelColumn.

          Defaults to NULL.

          Applicability is (OM_NEW, OM_SET)

      CHILD_NoDispose (BOOL)
          By setting this attribute, you inform the layout object that
          this child object should not be automatically disposed when
          the layout object itself is disposed. This attribute allows
          sharing objects between layouts.

          Default is FALSE.

          Applicability is (OM_NEW, OM_SET)

      CHILD_ScaledWidth (UWORD) (V42.27)
          Scales the child minimum domain size to a larger value;

          minwidth = minwidth + ((minsize * scalewidth)/100)

          Default is 0.

          Applicability is (OM_NEW, OM_SET)

      CHILD_ScaledHeight (UWORD) (V42.27)
          Scales the child minimum domain size to a larger value;

          minheight = minheight + ((minsize * scaleheight)/100)

          Default is 0.

          Applicability is (OM_NEW, OM_SET)

  NOTES
      Setting the attributes via SetGadgetAttrs() (OM_SET) will not
      automatically rerender the display! Call RethinkLayout() to
      relayout and refresh display after SetGadgetAttrs().

      In this document, the terms layout, group, and object are used
      intermixed. Most of the time, layout and group are used as
      synonyms. Virtually any object referred to could also be a
      layout group.

      To make defining layout hierarchies easier, the reaction_macros.h
      include file defines a set of macros that hide NewObject()
      calls. This will clean up the rather large tag lists for the
      creation of layout groups. See the ReAction examples for use of
      these macros, and layout.gadget in general.

      In relation to above, remember that in AmigaOS (as of V40), the
      stack size is restricted. During the beta test period, the
      average size of a layout group for a whole window seemed to
      average at approximately 1 KB. Building as large tag lists as
      this on stack is rather slow, as well as easily overflowing the
      small default stacks of AmigaOS. For windows with relatively
      static layouts that are opened often, consider building tag
      lists as static data and passing a pointer to them for
      NewObjectA(). If this is too much work, make sure that your
      program's stack is large enough to hold  the tag list. If it is
      too small, you can use the V37 Exec StackSwap() call to replace
      it with a larger one, or simply set the global variable long
      __stack to a large enough value, if the startup code you link
      with provides stack swap support, as for example the c.o of
      SAS/C 5.x and above does.

      Due to Intuition limitations, IDCMP_GADGETUP messages are not
      fully supported. The IAddress will always point to the root
      layout object of the window, not the actual gadget the message
      originates from. Use GadgetID to distinguish between gadgets.
      When using tab cycle, GADGETUP messages will be lost
      altogether. However, layout.gadget sends a notification for all
      gadgetups, containing the tags GA_ID, LAYOUT_RelVerify and
      LAYOUT_RelCode, containing, respectively, the ID, TRUE, and the
      IntuiMessage.Code value it returned. Additionally a
      LAYOUT_TabVerify tag will be TRUE or FALSE depending on whether
      the gadget release was triggered by tab cycle.
      Use of models and/or IDCMP_IDCMPUPDATE is encouraged.

  SEE ALSO
      ReAction example source for usage.


layout_gc/ActivateLayoutGadget

  NAME
      ActivateLayoutGadget -- Activate a gadget within a layout window.

  SYNOPSIS
      Success = ActivateLayoutGadget( Gadget, Window, Request, Object )
      d0                              a0      a1      a2       d0

      BOOL ActivateLayoutGadget( struct Gadget *, struct Window *,
              struct Requester *, ULONG );

  FUNCTION
      The equivalent of intuition.library ActivateGadget() for a
      window controlled by layout.gadget. If successful, this means
      that the user does not need to click in the gadget before
      typing.

      The gadget parameter MUST point to the root layout gadget in
      the window, and the object parameter to the gagdet you wish
      to activate. This works by calling the private
      LAYOUT_ACTIVATEOBJECT method to search the layout hierarchy for
      the specified gadget, and set the handleinput path to that
      gadget, and finally calling ActivateGadget for the root object.

      The rules of calling ActivateGadget() apply to
      ActivateLayoutGadget() also.

  INPUTS
      Gadget = pointer to the root layout obejct for the window.
      Window = pointer to the window the gadget is in.
      Requester = pointer to a requester (may be NULL)
      Object = pointer to the BOOPSI object you wish to activate.

  RESULT
      If the conditions above (and those of ActivateGadget()) are
      met, the function will return TRUE, else FALSE.

  NOTES
      Not only string gadgets can be activated this way. Many
      ReAction gadget classes, such as the button.gadget, also
      support keyboard control, and thus may be activated this way.

      An attempt to activate a gadget that is not currently visible
      (as on a hidden page) will fail.

  SEE ALSO
      intuition.library/ActivateGadget()


layout_gc/FlushLayoutDomainCache

  NAME
      FlushLayoutDomainCache -- Flush layout domain cache below a level.

  SYNOPSIS
      FlushLayoutDomainCache( layout )
                              a0

      void FlushLayoutDomainCache( struct Gadget * )

  FUNCTION
      Layout gadget normally caches GM_DOMAIN results from the child
      objects to speed up window re-layout. However, on some rare
      occassions a gadget's minimum or maximum domain might change
      after creation. For these instances layout gadget provides two
      methods of controlling the domain cache. You can set a caching on
      a child-by-child basis, using the CHILD_CacheDomain attribute, so
      that on each relayout the domain is calculated again. This
      method might have an extra performance hit, if the domain
      changes infrequently. It also has to be set for each parent
      layout level, which makes the amount of extra calculations grow
      quickly. The other method, for the cases where the application
      will know when a gadget's domain changes, it can call
      FlushLayoutDomainCache() with a pointer to the parent layout object.
      This call will flush the whole hierarchy, so that the next window
      re-layout will re-calculate child domains.

  INPUTS
      layout = the layout object to flush. This should be the topmost
                  layout object for the window.

  SEE ALSO
            --datasheet-- (CHILD_CacheDomain attribute)


layout_gc/LAYOUT_GetClass

  NAME
      LAYOUT_GetClass -- Gets the pointer to the layout class.

  SYNOPSIS
      layout_class = LAYOUT_GetClass();
      D0

      Class * LAYOUT_GetClass(VOID);

  FUNCTION
      Obtains the pointer to the layout gadget class for use with
      NewObject().  This function always returns a valid pointer so
      you do not need to check it.  The reason is that if the library
      opens fine, then the pointer returned is already setup.  (Of
      course this implies that if opening the library fails, you
      shouldn't be calling this.)

      Note that this function does not create the class, that is done
      when the class library is opened.

  INPUTS
      Nothing.

  RESULT
      LayoutClass - Pointer to the layout gadget class.


layout_gc/LayoutLimits

  NAME
      LayoutLimits -- easy way to find out max and min size of layout

  SYNOPSIS
      LayoutLimits( layout, limits, font, screen );
                    a0      a1      a2    a3

      void LayoutLimits( struct Gadget *, struct LayoutLimits *,
                              struct TextFont *, struct Screen * )

  FUNCTION
      This function is an easy way of getting the minimum and maximum
      limit of the layout group. Effectively it create a RastPort and
      execute the GM_DOMAIN method for both minimum and maximum size
      of the object filling in the LayoutLimits structure with the size
      values. The font passed to this call will most likely affect the
      results, so use the font you will use with the window. If you
      pass a NULL for the font, the system default font (monospaced)
      will be used. If you pass the optional screen pointer, the
      gadget will be provided a DrawInfo. This will let the gadget
      adjust to the aspect ratio of the screen.

      If you use the resulting size for OpenWindow() or WindowLimits(),
      remember that the results do not include window borders.

  INPUTS
      layout = the layout object to get the size on.
      limits = a pointer to the struct LayoutLimits to fill.
      font = the TextFont to use on the domain requests. May be NULL
              for system default font.
      screen = optional pointer to the screen on which the layout
              will be used on, or NULL.

  NOTES
      This function will invoke the object's GM_DOMAIN method twice,
      with a NULL GadgetInfo. If you call it providing a screen
      pointer, the taglist of the message will contain that screen's
      DrawInfo (GA_DrawInfo) for aspect information.

  SEE ALSO
      gadgetclass/GM_DOMAIN


layout_gc/RethinkLayout

  NAME
      RethinkLayout -- Relayout and render the layout. (V39)

  SYNOPSIS
      RethinkLayout( layout, window, requester, refresh );
                      a0        a1        a2

      void RethinkLayout( struct Gadget *, struct Window *,
                              struct Requester *, BOOL )

  FUNCTION
      Relayout and refresh the layout page. Call this function after
      a call SetGadgetAttrs() returns 1 to display the changes in the
      layout.  According to BOOPSI rules, a gadget will return a value
      of 1 from OM_SET to tell the application to refresh. This is what
      this function is for. Basically, it will call the GM_LAYOUT and
      GM_RENDER methods of the layout.

  INPUTS
      layout = the layout to refresh. Doesn't have to be the topmost
                  object in the hierarchy, if the changes do not affect
                  it.
      window = the window to which the layout (or its parent) is
                  attached to.
      requester = the window's requester, or NULL.
      refresh = whether layout.gadget should also refresh the display.

  NOTES
      This function emulates a DoGadgetMethod() on V37 and V38 systems.

      The refresh flag is provided for several reasons. First, when using
      LAYOUT_DeferLayout, you should not refresh upon receiving a
      LAYOUT_RequestLayout notification. Second, datatypes have an
      asynchronous layout, and should not be attempted to refresh before
      that is finished. Wait for DTA_Sync, and then RefreshGList( layout,
      window, requester, 1 ).

  SEE ALSO
      intuition.library/RefreshGList(), intuition.library/SetGadgetAttrsA(),
      intuition.library/DoGadgetMethod()


listbrowser_gc.doc

     --datasheet--
     LISTBROWSER_GetClass()
     LBM_ADDNODE
     LBM_EDITNODE
     LBM_REMNODE
     AllocListBrowserNodeA()
     FreeListBrowserList()
     FreeListBrowserNode()
     GetListBrowserNodeAttrsA()
     HideAllListBrowserChildren()
     HideListBrowserNodeChildren()
     ListBrowserSelectAll()
     SetListBrowserNodeAttrsA()
     ShowAllListBrowserChildren()
     ShowListBrowserNodeChildren()


listbrowser_gc/--datasheet--

     NAME
        listbrowser_gc -- For browsing linked lists in various ways.

     SUPERCLASS
        gadgetclass

     DESCRIPTION
        This gadget is very similar to the LISTVIEW_KIND gadget in
        gadtools.library, with numerous enhancements.  It displays a list in
        a scrolling view so that you can browse through it an select items
        in various ways.

        Advantages that this class provides:

         > Allows the user to select multiple items (either by dragging or
           shift-key selection).

         > Displays items in multiple columns.

         > Displays items as a mixture of text and images in different.
           colours.

         > Items can have checkboxes that can be toggled on and off.

         > Text items can be edited in place.

         > Hierarchical display of items supported.

         > Can displays column headers.

         > Allows allows horizontal scrolling of the list.

         > Supports window relativity.

         > Supports OS 3.0 BOOPSI Gadget HelpTest.

         > Supports layout.gadget/window.class backfills.

     METHODS

        OM_NEW -- Create the list browser gadget.  Passed to superclass then
            calls OM_SET.

        OM_SET -- Set object attributes.  Passed to superclass first.

        OM_DISPOSE -- Frees up the list browser gadget.

        OM_UPDATE -- Set object notification attributes.  Passed to
            superclass first.

        GM_RENDER -- Renders the gadget imagery.  Overrides the superclass.

        GM_GOACTIVE -- Handles activation, and selection of the scrollbars
            and arrows.  Overrides the superclass.

        GM_HANDLEINPUT -- Handles input events once active.  Overrides the
            superclass.

        GM_GOINACTIVE -- Closes the chooser menu.  Overrides the superclass.

        LBM_ADDNODE -- Adds a node to the attached list.

        LBM_EDITNODE -- Edit an attached nodes attributes.

        LBM_REMNODE -- Removes a node from the attached list.

        LBM_SORT -- Sort attached list on specified column (V42)

        LBM_SHOWCHILDREN --  (V42)

        LBM_HIDECHILDREN --  (V42)

        All other methods are passed to the superclass.

     ATTRIBUTES
        GA_Disabled (BOOL)
            Set to TRUE to disable gadget, FALSE otherwise.

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        GA_ReadOnly (BOOL)
            Specifies that the list browser be read-only.  This means that
            no nodes within the list can be selected, the user can just
            scroll through and view the list.  The frame of the list will be
            rendered as recessed as a visual cue that no nodes can be
            selected.

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        GA_TextAttr (struct TextAttr *)
            Font to use for the contents of the list browser.

            Defaults to the screen's font.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        LISTBROWSER_Top (LONG)
            Sets the node that is to appear at the top of list browser view.
            Must be positive.  If its beyond the maximum possible value,
            the last page in the list will be displayed.

            Defauts to 0.

            Applicability is (OM_NEW, OM_SET, OM_GET, OM_NOTIFY)

        LISTBROWSER_MakeVisible (LONG)
            Ensures that the specified is within the view and will scroll
            only when necessary (unlike LISTBROWSER_Top which will always
            scrolls).

            Defaults to 0.

            Applicability is (OM_NEW, OM_SET)

        LISTBROWSER_Labels (struct List *)
            An Exec list.  Nodes in this list must be allocated with
            AllocListBrowserNodeA().

            A value of ~0 or NULL indicates that the list is "detached".
            This must be done before you can modify a list already attached
            to a list browser. After detaching, you should carry out your
            updates to the list as quickly as possibly and then re-attach.
            When a list browser is initially added to a window it MUST have
            a list attached to it, ~0 is not valid in this case.

            If you are using the LISTBROWSER_AutoFit attribute, the column
            sizes will NOT be re-calculated when you change lists, you must
            pass LISTBROWSER_AutoFit, TRUE again to adjust the column sizes
            to fit your new list.

            Note that when changing lists, you may want to reset certain
            other attributes, such as LISTBROWSER_Selected, as this value
            will be retained even when changing lists.

            NOTE: Lists can NOT be shared amongst other list browsers
            simultaneously.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        LISTBROWSER_Spacing (WORD)
            If you would like additional spacing between nodes in your
            ListBrowser, use this tag to define how many extra pixels you
            want.

            Defaults to 0.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        LISTBROWSER_Selected (LONG)
            Sets the node in a single-select list that will be selected.
            Any previously selected node(s) will be deselected.  Note
            that a node can become selected without being visible.  A
            value of -1 ( (ULONG)~0 ) is used to say that no item is
            selected.  The results of this tag are undefined in a multi-
            select list browser.

            This value is returned in the IntuitMessage.Code field.

            Defaults to -1.

            Applicability is (OM_NEW, OM_SET, OM_GET, OM_NOTIFY)

        LISTBROWSER_SelectedNode (struct Node *)
            This is the same as LISTBROWSER_Selected, except that you refer
            to a node by its actual node structure.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        LISTBROWSER_MultiSelect (BOOL)
            Puts the list browser into multi-select mode.  In multi-select
            mode the user can select several items from the list by either
            dragging the mouse over items, or holding down the shift key and
            click items to add them to the ones selected.  Nodes can be
            deselected by holding down the shift key and clicking on selected
            node.

            Selected nodes will have the LBNA_Selected attribute set to
            TRUE (see GetListBrowserNodeAttrs()).

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        LISTBROWSER_PersistSelect (BOOL)
            When the list browser is in multi-select mode, this flag changes
            the selection behaviour so that shift does NOT have to be held
            down to select multiple nodes

            Please be aware that this is distinctly NON-STANDARD behaviour
            and therefore should be used with extreme discretion.  About
            the only time this may be appropriate is when you are dealing
            with long lists where users are typically having to select a
            large number of nodes.  Because there is no simple way to clear
            all selections when in this, some method should exist in your
            user interface for clearing all selections.

            This has no meaning if the list browser is not in multi-select
            mode.

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        LISTBROWSER_ShowSelected (BOOL)
            Specifies that you want the selected item in a single-select
            list browser to be remain visible after it is selected, until
            another item is selected.  This tag has undefined results in
            a multi-select list browser.

            Defaults to TRUE.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        LISTBROWSER_NumSelected (LONG)
            The number of items selected in a multi-select list browser.
            This contains a meaningless value if your listbrowser is not
            multi-select.

            Applicability is (OM_GET)

        LISTBROWSER_RelEvent (ULONG)
            Describes the event that caused the gadget release of the list
            browser.  Currently defined events are:

                LBRE_NORMAL - Normal selection of an item.
                LBRE_HIDECHILDREN - The user tried to hide children in a
                    hierarchical listbrowser.
                LBRE_SHOWCHILDREN - The user tried to show children in a
                    hierarchical listbrowser.
                LBRE_EDIT - The contents of a node were edited.
                LBRE_DOUBLECLICK - The node was double-clicked on.

                Additional return values added with V42;

                LBRE_CHECKED - A checkbox node was checked.
                LBRE_UNCHECKED_ - A checkbox node was unchecked.
                LBRE_TITLECLICK - A column's title was clicked.
                LBRE_COLUMNADJUST - A column's separator was clicked/dragged.

            Applicability is (OM_GET)

        LISTBROWSER_VertSeparators (BOOL)
        LISTBROWSER_Separators (BOOL)
            Specifies that bevelled lines be drawn as separators between
            each column.  Has no effect if the list only has one column.

            Defaults to TRUE.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        LISTBROWSER_HorizSeparators	(BOOL) (V41)
            Renders horizontal lines below each node.  This is useful if your
            listbrowser is very wide, and you want to make it easier for
            users to follow the rows of data.

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_GET, OM_SET)

        LISTBROWSER_Borderless (BOOL)
            Create a view without a border.  Useful if you wish the list
            browser to take up the entire window, and have an attached
            scroller in the window border.

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        LISTBROWSER_ColumnInfo (struct ColumnInfo *)
            Provides the column layout info for the list browser.  This is
            an array of struct ColumnInfo.  The array must have one entry
            per column, plus one terminating entry where the ci_Width field
            is -1.  Each field in an array entry is filled in as follows:

                ci_Width (WORD)
                This specifies the percentage of the view width you want the
                column to be.  If a virtual width is given, this will be a
                percentage of that, otherwise it will be a percentage of the
                actual gadget width.  Since you are specifying a percentage,
                the actual size of the column will automatically adjust as the
                virtual or actual width of the gadget changes.

                ci_Title (STRPTR)
                If you have specified LISTBROWSER_ColumnTitles, TRUE then
                you MUST fill in the titles you wish to appear for each column
                here.

                ci_Flags (ULONG)
                Flags for the column, suported by V42 and later only.

                     CIF_WEIGHTED -- weighted width column (default)
                     CIF_FIXED -- fixed pixel width specided in ci_Width.
                     CIF_DRAGGABLE -- separator is user draggable.
                     CIF_NOSEPARATORS -- no separator on this column.
                     CIF_SORTABLE -- column is sortable.

            Passing NULL for the ColumnInfo means that you want a single
            column taking up the entire width of the gadget with no title.

            NOTES: ColumnInfo can NOT be shared amongst other list browsers
            simultaneously.  While the ColumInfo is in use by list browser,
            you may not modify it.  If you wish to make any modifications
            to it, then first detach the list, make your modifications then
            re-attach the list AND give use LISTBROWSER_ColumnInfo tag
            again.  List browser may modify the contents of this structure.

            Defaults to NULL.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        LISTBROWSER_ColumnTitles (BOOL)
            Show titles above each column.

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        LISTBROWSER_AutoFit (BOOL)
            Informs the ListBrowser that you want your column widths
            calculated automatically for you to best fit the items in the
            list attached to it.  This will make your gadget a virtual
            width gadget, with the virtual width being the width needed to
            fit all columns.

            For this to work, you must still pass LISTBROWSER_ColumnInfo with
            a ColumInfo structure that has entries for each column, as normal.
            The only change being that the initial values of the ci_Width
            field will be ignored, and instead will be filled in by
            ListBrowser.

            If you are using the LISTBROWSER_AutoFit attribute, the column
            sizes will NOT be re-calculated when you change lists with
            LISTBROWSER_Label, you must pass LISTBROWSER_AutoFit, TRUE again
            to adjust the column sizes to fit your new list.

            Note for V42, with autofit enabled, wordwrap columns presently
            will NOT rewrap. This is an internal chicken and the egg issue.

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        LISTBROWSER_VirtualWidth (WORD)
            Allows rendering beyond the right edge of the view area in the
            gadget.

            Defaults to 0.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        LISTBROWSER_Left (WORD)
            The left offset of the view.  This is only useful in combination
            with either LISTBROWER_VirtualWidth or LISTBROWSER_AutoFit to
            reveal horizontal parts of the view that might be hidden.  The
            offset is specified in terms of pixels.

            Defaults to 0.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        LISTBROWSER_VerticalProp (BOOL)
            Creates a vertical scrollbar with arrows for scrolling up and
            down through the list.

            Defaults to TRUE.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        LISTBROWSER_HorizontalProp (BOOL)
            Creates a horizontal scrollbar with arrows for scrolling
            sideways across the view.  Not useful unless you've used
            LISTBROWSER_VirtualWidth or LISTBROWSER_AutoFit since there
            would be nothing horizontally hidden.

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        LISTBROWSER_VPropTotal
        LISTBROWSER_VPropTop
        LISTBROWSER_VPropVisible
        LISTBROWSER_HPropTotal
        LISTBROWSER_HPropTop
        LISTBROWSER_HPropVisible
            These tags are for getting the status of the two prop gadgets
            for the listbrowser.  These are read-only and are intended for
            linking external prop gadgets to a listbrowser.

            Applicability is:
            LISTBROWSER_VPropTotal, LISTBROWSER_VPropVisible,
            LISTBROWSER_HPropTotal, LISTBROWSER_HPropVisible:
                (OM_GET, OM_NOTIFY)
            LISTBROWSER_VPropTop, LISTBROWSER_HPropTop:
                (OM_SET, OM_GET, OM_NOTIFY)

        LISTBROWSER_Position (ULONG)
            Alters the view position within the listbrowser gadget.  See
            the include file for possible positions.  This tag exists mainly
            to make complex keyboard controls simple.

            Applicability is (OM_SET)

        LISTBROWSER_MouseX (WORD)
        LISTBROWSER_MouseY (WORD)
            Returns the co-ordinates of the mouse within the gadgets box
            when the mouse button was last released in the gadget.

            Applicability is (OM_GET)

        LISTBROWSER_ScrollRaster (BOOL)
            When this option is set, ListBrowser will use ScrollRaster() for
            extra fast scrolling.  This option is safe to use if the gadget
            will be in a Smart Refresh or Super Bitmap window.

            If the gadget will be in a Simple Refresh window, you should be
            aware of an Intuition bug that will cause layer damage to not
            be updated properly.  This problem only exists under V37 of
            Intuition, as ListBrowser sets the GMORE_SCROLLRASTER flag which
            causes proper updates in V39 and above.  HOWEVER, if you are
            using ScrollRaster() in a window that contains a ListBrowser,
            you MUST check the version of Intuition and use
            ScrollWindowRaster() instead if the version is 39 or higher!

            Defaults to TRUE.

            Applicability is (OM_NEW, OM_GET, OM_SET)

        LISTBROWSER_Hierarchical (BOOL)
            Puts the ListBrowser into hierarchical mode, where nodes can be
            browsed in a hierarchically by "generation", and generations can
            be hidden.

            See the LBNA_Generation node tag.

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_GET, OM_SET)

        LISTBROWSER_ShowImage (struct Image *)
        LISTBROWSER_HideImage (struct Image *)
        LISTBROWSER_LeafImage (struct Image *)
            You can replace the images for showing a generation, hiding a
            generation and the leaf (no children) image with your own.  If
            you do not provide any of them, default images will be rendered
            for you.

            Defaults to NULL.

            Applicability is (OM_NEW, OM_GET, OM_SET)

        LISTBROWSER_Editable (BOOL)
            If you want to enable in place editing of selected node columns,
            you must set this flag to TRUE.  Note that
            LISTBROWSER_ShowSelected must also be TRUE for node editing to
            work properly.

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_GET, OM_SET)

        LISTBROWSER_EditNode (LONG)
            The number of a node that you want to start editing.  You must
            also specify the column you want to edit with
            LISTBROWSER_EditColumn, and then activate the gadget using
            ActivateGadget() (or ActivateLayoutGadget() if the listbrowser
            is being used with layout.gadget).

            This tag will also make the given node the selected node.

            Defaults to -1.

            Applicability is (OM_NEW, OM_SET)

        LISTBROWSER_EditColumn (WORD)
            The number of a column that you want to start editing.  You must
            also specify the node number you want to edit with
            LISTBROWSER_EditNode, and then activate the gadget using
            ActivateGadget() (or ActivateLayoutGadget() if the listbrowser
            is being used with layout.gadget).

            Defaults to -1.

            Applicability is (OM_NEW, OM_SET)

        LISTBROWSER_EditTags (struct TagList *)
            Tags that you want to be passed to the string gadget used when
            editing gadget text.  Though you could theoretically pass any
            tags to the gadget, you should generally not pass tags that
            affect the position of the gadget.

            Defaults to NULL.

            Applicability is (OM_NEW, OM_GET, OM_SET)

        LISTBROWSER_RelColumn (WORD)
            The column the mouse was over when the button is released.  This
            is most useful in a listbrowser with editable nodes in different
            columns.  By checking both this and LISTBROWSER_RelEvent on
            gadget release, you can tell if a node was edited and what column
            of that node was edited.

            This  will not contain valid data if the mouse button was
            released over a read-only node or if your listbrowser is in read-
            only mode.

            Applicability is (OM_GET)

        LISTBROWSER_CheckImage (struct Image *)  (V41)
            Provide a custom image for a checkbox node while that node is
            in the checked state.  A NULL image means that listbrowser
            render some default imagery.

            Defaults to NULL.

            Applicability is (OM_NEW, OM_GET, OM_SET)

        LISTBROWSER_UncheckedImage (struct Image *)  (V41)
            Provide a custom image for a checkbox node while that node is
            in the unchecked state.  A NULL image means that listbrowser
            render some default imagery.

            Defaults to NULL.

            Applicability is (OM_NEW, OM_GET, OM_SET)

        LISTBROWSER_TotalNodes (LONG)  (V41)
            Return the total number of nodes currently attached to the
            listbrowser.

            Applicability is (OM_GET)

        LISTBROWSER_MinNodeSize (LONG)  (V42)
            Minimum Node size for MemPool optimization, useful when
            coupled with LBNA_NodeSize and using the internal pool.

            Applicability is (OM_NEW,OM_SET)

        LISTBROWSER_TitleClickable (BOOL)  (V42)
            Enables column-title bar clicking when TRUE.

            Defaults to FALSE.

            Applicability is (OM_NEW,OM_SET)

        LISTBROWSER_MinVisible (LONG)  (V42)
            Minimum visible node count. This is a causes the
            minimum domain to be large enough to hold the specified number
            of nodes using the the estimated average node height.
            Note *ESTIMATED* this is not garanteed results. The result may
            be slightly less or greater than specified, and potentially
            alot greater if other objects within the layout group cause the
            listbrowser to layout larger than its minimum domain.

            Applicability is (OM_NEW,OM_SET)

        LISTBROWSER_PersistSelect (BOOL)  (V42)
            When set TRUE, SHIFT key is NOT required for multi-select.

            Defaults to FALSE.

            Applicability is (OM_NEW,OM_SET)

        LISTBROWSER_CursorSelect (LOng)  (V42)
            Keyboard cursor selected node number.

            Defaults to 0.

            Applicability is (OM_SET, OM_GET)

        LISTBROWSER_CursorNode (struct Node *)  (V42)
            Keyboard cursor selected node pointer.

            Defaults to NULL.

            Applicability is (OM_GET)

        LISTBROWSER_FastRender (BOOL)  (V42)
            Enables use of mask planes on non-CyberGraphx screens.
            Also turns off custom pen support.

            The potential performance improvement with deep ECS or
            AGA displays can be *HUGE* for complex multi-column lists.

            Defaults to FALSE.

            Applicability is (OM_NET, OM_SET)

        LISTBROWSER_TotalVisibleNodes (LONG)  (V42)
            Total visible node count (estimated).

            Defaults to 0.

            Applicability is (OM_GET)

        LISTBROWSER_WrapText (BOOL)  (V42)
            Enables word-wrapping of column nodes flagged for word wrap.
            Wrapping is delimited by a space, 'n' newline, or 't' tab.

            Defaults to 0.

            Applicability is (OM_NEW, OM_SET)

    BUGS
        Versions 41.250 and below do not support LISTBROWSER_PersistSelect.
        Versions 41.631 and below do not support LISTBROWSER_FastRender correctly.

    SEE ALSO
        graphics.library/ScrollRaster(), intuition.library/ActivateGadget(),
        intuition.library/ScrollWindowRaster(), layers.library,
        layout.gadget/ActivateLayoutGadget()


listbrowser_gc/LISTBROWSER_GetClass

    NAME
        LISTBROWSER_GetClass -- Gets the pointer to the listbrowser class.

    SYNOPSIS
        listbrowser_class = LISTBROWSER_GetClass();
        D0

        Class * LISTBROWSER_GetClass(VOID);

    FUNCTION
        Obtains the pointer to the ListBrowser gadget class for use with
        NewObject().  This function always returns a valid pointer so
        you do not need to check it.  The reason is that if the library
        opens fine, then the pointer returned is already setup.  (Of course
        this implies that if opening the library fails, you shouldn't be
        calling this.)

        Note that this function does not create the class, that is done
        when the class library is opened.

    INPUTS
        Nothing.

    RESULT
        listbrowser_class - Pointer to the ListBrowser gadget class.

    SEE ALSO


listbrowser_gc/LBM_ADDNODE

    NAME
        LBM_ADDNODE -- Adds a node to the attached list.

    FUNCTION
        Allocates a new node and adds it to the list currently attached to
        the listbrowser (if there is one attached).  If rendering
        information is available, then any necessary refreshing will take
        place.  You do not need to detach your list first.

        This method takes the following message structure:

          struct lbAddNode
          {
              ULONG MethodID;                 /* LBM_ADDNODE */
              struct GadgetInfo *lba_GInfo;   /* to provide rendering info */
              struct Node *lba_Node;          /* Insert() after this node */
              struct TagItem *lba_NodeAttrs;  /* AllocListBrowserNodeA()
                                                 taglist */
          };

    RESULT
        Returns a pointer to the allocated node, or NULL on failure.

    SEE ALSO
        LBM_EDITNODE, LBM_REMNODE, reaction.lib/LBAddNode


listbrowser_gc/LBM_EDITNODE

    NAME
        LBM_EDITNODE -- Edit an attached nodes attributes.

    FUNCTION
        Changes attributes of a node attached to a listbrowser.  If rendering
        information is available, then any necessary refreshing will take
        place.  You do not need to detach your list first.

        This method takes the following message structure:

          struct lbEditNode
          {
              ULONG MethodID;                 /* LBM_EDITNODE */
              struct GadgetInfo *lbe_GInfo;   /* to provide rendering info */
              struct Node *lbe_Node;          /* modify this node */
              struct TagItem *lbe_NodeAttrs;  /* SetListBrowserNodeAttrsA()
                                                 taglist */
          };

    RESULT
        Returns non-zero on success, zero on failure.

    SEE ALSO
        LBM_ADDNODE, LBM_REMNODE, reaction.lib/LBEditNode


listbrowser_gc/LBM_REMNODE

    NAME
        LBM_REMNODE -- Removes a node from the attached list.

    FUNCTION
        Removes and de-allocates a node from the list currently attached
        to the listbrowser.  If rendering information is available, then
        any necessary refreshing will take place.  You do not need to
        detach your list first.

        This method takes the following message structure:

          struct lbRemNode
          {
              ULONG MethodID;               /* LBM_REMNODE */
              struct GadgetInfo *lbr_GInfo; /* to provide rendering info */
              struct Node *lbr_Node;        /* Remove() this node */
          };

    RESULT
        Returns non-zero on success, zero on failure.

    SEE ALSO
        LBM_ADDNODE, LBM_REMNODE, reaction.lib/LBRemNode


listbrowser_gc/AllocListBrowserNodeA

    NAME
        AllocListBrowserNodeA -- Allocate a ListBrowser node.

    SYNOPSIS
        struct Node * AllocListBrowserNode(UWORD, Tag, ...)
        node = AllocListBrowserNode(columns, Tag, ...)

        struct Node * AllocListBrowserNodeA(UWORD, struct TagItem *)
        node = AllocListBrowserNodeA(columns, taglist)

    FUNCTION
        Allocates a node that can be added to the Exec linked list of
        labels in the listbrowser.  This is the only way to allocate a
        node for this list, you cannot allocate nodes yourself because
        the ListBrowser class uses a private node structure.

    TAGS
        See SetListBrowserNodeAttrsA() for the list of supported tags.  In
        addition, AllocListBrowserNodeA() supports the following additional
        tags:

        LBNA_NodeSize (ULONG) (V41)
        The size in bytes of the public portion of the node structure that
        should be allocated.  Usually the default (sizeof(struct Node)) will
        suffice, unless you wish to have a custom node structure embedded
        within the ListBrowser node, in which case you'd provide the size
        of that structure.  Then the node returned can be treated as an
        instance of your custom node structure.

        Defaults to sizeof(struct Node).

    INPUTS
        columns - How many columns your ListBrowser has.
        taglist - Attributes for the node, passed onto
            SetListBrowserNodeAttrsA().

    RESULT
        node - A node that can be added into the Exec list of labels for
            a ListBrowser gadget.

    SEE ALSO
        FreeListBrowserNode(), SetListBrowserNodeAttrsA()


listbrowser_gc/FreeListBrowserList

    NAME
        FreeListBrowserList -- Free a list of ListBrowser nodes.

    SYNOPSIS
        VOID FreeListBrowserList(struct List *)
        FreeListBrowserList(List)

    FUNCTION
        Frees a list of ListBrowser nodes allocated.

    INPUTS
        list - The list of nodes to free.

    SEE ALSO
        FreeListBrowserNode()


listbrowser_gc/FreeListBrowserNode

    NAME
        FreeListBrowserNode -- Free a ListBrowser node.

    SYNOPSIS
        VOID FreeListBrowserNode(struct Node *)
        FreeListBrowserNode(node)

    FUNCTION
        Frees a ListBrowser node allocated with AllocListBrowserNodeA().

    INPUTS
        node - The node to free.

    SEE ALSO
        AllocListBrowserNodeA()


listbrowser_gc/GetListBrowserNodeAttrsA

    NAME
        GetListBrowserNodeAttrsA -- Get attributes about a ListBrowser node.

    SYNOPSIS
        VOID GetListBrowserNodeAttrs(struct Node *, Tag, ...)
        GetListBrowserNodeAttrs(node, firsttag, ...)

        VOID GetListBrowserNodeAttrsA(struct Node *, struct TagItem *)
        GetListBrowserNodeAttrsA(node, taglist)

    FUNCTION
        The ListBrowser uses a private node structure and all attributes
        are hidden, and must therefore be accessed with this function.

    TAGS
        See SetListBrowserNodeAttrsA() for the list of supported tags.

    INPUTS
        node - The ListBrowser node to get the information on.
        taglist - A tag list of attributes to get.  ti_Tag is the attribute
            to get and ti_Data is a pointer to a location to copy the result
            to.  The exception is LBNA_Column, which is used to specify a
            column to get attributes on.

    SEE ALSO
        SetListBrowserNodeAttrsA()


listbrowser_gc/ListBrowserSelectAll

    NAME
        ListBrowserSelectAll -- Select all nodes in a multiselect ListBrowser.

    SYNOPSIS
        VOID ListBrowserSelectAll(struct List *);
        ListBrowserSelectAll(list);

    FUNCTION
        Sets the LBNA_Selected bit to TRUE in all nodes in list.  This is a
        quick way to select all nodes in a multi-select ListBrowser.

        Note that as with any modifications to a ListBrowser list, the list
        MUST be detached to the listbrowser at the time of modification.

    INPUTS
        list - a list of ListBrowser nodes, not currently attached to a
            ListBrowser.


listbrowser_gc/HideAllListBrowserChildren

    NAME
        HideAllListBrowserChildren -- Hide all children in a ListBrowser.

    SYNOPSIS
        VOID HideAllListBrowserChildren(struct List *);
        HideAllListBrowserChildren(list);

    FUNCTION
        Hides all children in a hierarchical ListBrowser, "collapsing" all
        generations so that only root generation nodes are shown.

        Note that as with any modifications to a ListBrowser list, the list
        MUST be detached to the listbrowser at the time of modification.

    INPUTS
        list - a list of ListBrowser nodes, not currently attached to a
            ListBrowser.


listbrowser_gc/HideListBrowserNodeChildren

    NAME
        HideListBrowserNodeChildren -- Hide a ListBrowser node's children

    SYNOPSIS
        VOID HideListBrowserNodeChildren(struct Node *);
        HideListBrowserNodeChildren(node);

    FUNCTION
        Hides the children of a ListBrowser node.  It will only hide the
        next generation, nodes of higher generations will not be modified.

        Note that as with any modifications to a ListBrowser list, the list
        must NOT be detached to the listbrowser at the time of modification.

    INPUTS
        node - the node whose children you will be hiding.  The node must
            NOT be in a list that that is currently attached to a ListBrowser.


listbrowser_gc/SetListBrowserNodeAttrsA

    NAME
        SetListBrowserNodeAttrsA -- Set attributes of a ListBrowser node.

    SYNOPSIS
        VOID SetListBrowserNodeAttrs(struct Node *, Tag, ...)
        SetListBrowserNodeAttrs(node, firsttag, ...)

        VOID SetListBrowserNodeAttrsA(struct Node *, struct TagItem *)
        SetListBrowserNodeAttrsA(node, taglist)

    FUNCTION
        Changes attributes for a ListBrowser node.  Since the ListBrowser
        class uses a private node structure, this is the only way to change
        node attributes.

        You may NOT change node attributes when the node is in a list
        attached to a ListBrowser gadget.  You must first detach the list
        with LISTBROWSER_Labels, ~0 before you can change attributes, and
        then re-attach the list.

    TAGS
        LBNA_Selected (BOOL)

        If this node is currently selected or not in a multi-select
        list browser.  This field is not meaningful in a single-
        select list browser.

        LBNA_Flags (ULONG)

        Flags for this node.  See ListBrowser.h for available flags.

        LBNA_Generation (WORD)

        Sets which "generation" this node belongs to, if the ListBrowser
        is to be in hierarchical mode.  If you were to draw the nodes out
        in a sort of family tree, the generation would refer to the level
        in the tree.

        Generations start at 1.  A generation 1 node's children will be
        generation 2, you cannot skip generations.  Nodes need not have
        children and generations can go as deep as you like, limited by
        the available stack of input.device.

        LBNA_UserData (APTR)

        Abritrary user data for this node.

        LBNA_Column (WORD)

        A column (from 0 to number_of_columns-1) that the column
        attribute tags below (LBNA_Text, LBNA_Integer, LBNA_FGPen,
        LBNA_BGPen, LBNA_Image, LBNA_SelImage, LBNA_Justification)
        affect.  You typically specify the column to work on, and
        then the column attributes for that column, then the next
        column followed by its attributes, etc.

        LBNCA_Text (STRPTR)

        Text that is to appear in the corresponding column for
        this node.  Only one of LBNA_Text, LBNA_Integer and
        LBNCA_Image may be non-NULL, specifying the type of contents
        for this column.  Each column of a node need not have the
        same type of contents.  Similarly, the same column in
        different nodes also need not have the same type of contents.

        LBNCA_CopyText (BOOL)

        Specifies that you want the LBNCA_Text copied to an internal
        buffer by ListBrowser.

        LBNCA_Editable (BOOL)

        Specifies that this item can be edited.  If the user clicks
        twice on this entry, the text will become a string gadget
        where the user can edit the contents.  This will only work
        if the contents are text (given with LBNCA_Text) AND if
        LBNCA_CopyText was used.  You MUST also specify LBNCA_MaxChars
        to specify how long the edited text can be.

        LBNCA_MaxChars(WORD)

        Maximum number of characters an editable text entry can be.

        LBNCA_Integer (LONG *)

        A pointer to an integer to display in this column, or NULL.

        LBNCA_FGPen, LBNA_BGPen (WORD)

        The pens to be used for rendering the text or integer in
        this column.  Requires that the LBFLG_CUSTOMPENS flag be
        specified, otherwise the default system pens will be used.

        LBNCA_Image, LBNA_SelImage (struct Image *)

        Specifies that the column should contain an image.  The
        selected image is optional, if not provided, LBNA_Image will
        be rendered in the IDS_SELECTED state when then node is
        selected.

        LBNCA_Justification (WORD)

        Specifies a justification for the column, either LCJ_LEFT,
        LCJ_CENTRE or LCJ_RIGHT.

        LBNA_CheckBox (BOOL) (V41)

        Means that this node will be a checkbox node, that can be toggled
        on or off.

        Defaults to FALSE.

        LBNA_Checked (BOOL) (V41)

        Indicates whether a checkbox node is in the checked or unchecked
        state.

        Defaults to FALSE.

        LBNCA_EditTags (struct TagItem *) (V41)

        Tags that you want to be passed to the string gadget used when
        editing gadget text.  Though you could theoretically pass any
        tags to the gadget, you should generally not pass tags that
        affect the position of the gadget.

        Defaults to NULL.

        LBNCA_RenderHook (struct Hook *) (V41)

        A custom render hook for this node column.  You hook will
        receive a pointer to struct Node of the node in question as its
        object, and the following structure in the message pointer:

          struct LBDrawMsg
          {
              ULONG lbdm_MethodID;            /* LV_DRAW */
              struct RastPort *lbdm_RastPort; /* Where to render to */
              struct DrawInfo *lbdm_DrawInfo; /* Useful to have around */
              struct Rectangle lbdm_Bounds;   /* Limits of where to render */
              ULONG lbdm_State;               /* How to render */
          };

        LBDrawMsg.lbdm_State will be either LBR_SELECTED or LBR_NORMAL.  The
        hook should return LBCB_OK if rendering was successful, or
        LBCB_UNKNOWN if lbdm_Method doesn't equal LV_DRAW.  No rendering
        should be performed in this case.

        Note that this is HIGHLY compatible with a GadTools listhook.

        Defaults to NULL.

        LBNCA_HookHeight (WORD) (V41)

        The height of this column, when using LBNCA_RenderHook.

        LBNA_MemPool (APTR) (V42)

        Specifies a custom memory pool to allocate listbrowser nodes from.

        Defaults to NULL (internal pool).

        LBNCA_WordWrap (BOOL) (V42)

        Specifies this column's text can be word wrapped. Useful in
        weighted column displays or fixed pixels columns. Primarily
        this feature exists at the request of IRC client authors.

        Initial implementation in V42.630 is slow. Improvement to be made.

        Defaults to FALSE.

    INPUTS
        node - Node whose attributes you are changing.
        taglist - Tag list of attributes to change.

    SEE ALSO
        GetListBrowserNodeAttrsA()


listbrowser_gc/ShowAllListBrowserChildren

    NAME
        ShowAllListBrowserChildren -- Show all children in a ListBrowser

    SYNOPSIS
        VOID ShowAllListBrowserChildren(struct List *);
        ShowAllListBrowserChildren(list);

    FUNCTION
        Shows all children in a hierarchical ListBrowser, no matter what
        generation they are in.

        Note that as with any modifications to a ListBrowser list, the list
        must NOT be attached to the listbrowser at the time of modification.

    INPUTS
        list - a list of ListBrowser nodes, not currently attached to a
            ListBrowser.


listbrowser_gc/ShowListBrowserNodeChildren

    NAME
        ShowListBrowserNodeChildren -- Show children of a ListBrowser node.

    SYNOPSIS
        VOID ShowListBrowserNodeChildren(struct Node *, WORD);
        ShowListBrowserNodeChildren(node, depth);

    FUNCTION
        Show the children of a ListBrowser node.  The next depth generations
        will be shown.  To only show the next generation, use a depth of 1.

        Note that as with any modifications to a ListBrowser list, the list
        must NOT be attached to the listbrowser at the time of modification.

    INPUTS
        node - the node whose children you will be showing.  The node must
            NOT be in a list that that is currently attached to a ListBrowser.
        depth - how many generations deep to show.


locale.doc

     --environment_vars--
     --rexxhost--
     --structures--
     CloseCatalog()
     CloseLocale()
     ConvToLower()
     ConvToUpper()
     FormatDate()
     FormatString()
     GetCatalogStr()
     GetLocaleStr()
     IsXXXX()
     OpenCatalog()
     OpenLocale()
     ParseDate()
     StrConvert()
     StrnCmp()


locale.library/--environment_vars--

    Starting with V40, locale.library maintains a global environment
    variable called "Language" which contains the name of the current
    default language as used in the system. This is the name of the
    language associated with the Locale structure returned by
    OpenLocale(NULL).

   EXAMPLE
    From a shell:

        Echo "The system language currently is: $Language"

    will print the name of the current system language ("english",
    "français", etc)


locale.library/--rexxhost--

   HOST INTERFACE
    locale.library provides an ARexx function host interface that enables
    ARexx programs to take advantage of system localization. The
    functions provided by the interface are directly related to the
    functions described herein, with the differences mostly being
    in the way they are called.

    The function host library vector is located at offset -30 from the
    library. This is the value you provide to ARexx in the AddLib()
    function call.

   FUNCTIONS
    CloseCatalog (CATALOG/N/A)
    ConvToLower (CHARACTER/A)
    ConvToUpper (CHARACTER/A)
    GetCatalogStr (CATALOG/A,STRING/N/A,DEFAULT/A)
    IsAlNum (CHARACTER/A)
    IsAlpha (CHARACTER/A)
    IsCntrl (CHARACTER/A)
    IsDigit (CHARACTER/A)
    IsGraph (CHARACTER/A)
    IsLower (CHARACTER/A)
    IsPrint (CHARACTER/A)
    IsPunct (CHARACTER/A)
    IsSpace (CHARACTER/A)
    IsUpper (CHARACTER/A)
    IsXDigit (CHARACTER/A)
    OpenCatalog (NAME/A,BUILTINLANGUAGE/A,VERSION/N/A)
    Strncmp (STRING1/A,STRING2/A,TYPE/N/A)

   EXAMPLE
    /* localetest.rexx */

    /* Make sure locale is loaded as a function host */
    IF ~SHOW(L,'locale.library') THEN DO
      CALL ADDLIB('locale.library',0,-30)
    END;

    say ConvToLower("A");
    say ConvToUpper("b");
    say IsAlpha("1");

    catalog = OpenCatalog("sys/workbench.catalog","english",0);
    say GetCatalogStr(catalog,34,"default");
    say CloseCatalog(catalog);
    say StrnCmp("test","test",2);


locale.library/--structures--

    The Locale structure is the main public structure provided by
    locale.library. The structure is defined in <libraries/locale.h>
    and consists of the following fields:

    STRPTR loc_LocaleName
        Locale's name.

    STRPTR loc_LanguageName
        The language of the driver bound to this locale.

    STRPTR loc_PrefLanguages[10]
        The ordered list of preferred languages for this locale.

    ULONG loc_Flags
        Locale flags. Currently always 0.

    ULONG loc_CodeSet
        Specifies the code set required by this locale. Currently, this
        value is always 0.

    ULONG loc_CountryCode
        The international country code.

    ULONG loc_TelephoneCode
        The international telephone code for the country.

    LONG loc_GMTOffset
        The offset in minutes of the current location from GMT.
        Positive indicates a Westerly direction from GMT,
        negative Easterly.

    UBYTE loc_MeasuringSystem
        The measuring system being used.

    STRPTR loc_DateTimeFormat
        The date and time format string, ready to pass to FormatDate()

    STRPTR loc_DateFormat
        The date format string.

    STRPTR loc_TimeFormat
        The time format string.

    STRPTR loc_ShortDateTimeFormat
        The short date and time format string, ready to pass to
        FormatDate()

    STRPTR loc_ShortDateFormat
        The short date format string.

    STRPTR loc_ShortTimeFormat
        The short time format string.

    STRPTR loc_DecimalPoint
        The decimal point character used to format non-monetary quantities.

    STRPTR loc_GroupSeparator
        The characters used to separate groups of digits before the
        decimal-point character in formatted non-monetary quantities.

    STRPTR loc_FracGroupSeparator
        The characters used to separate groups of digits after the
        decimal-point character in formatted non-monetary quantities.

    STRPTR loc_Grouping
        A string whose elements indicate the size of each group of digits
        before the decimal-point character in formatted non-monetary
        quantities.

    STRPTR loc_FracGrouping
        A string whose elements indicate the size of each group of digits
        after the decimal-point character in formatted non-monetary
        quantities.

    STRPTR loc_MonDecimalPoint
        The decimal-point used to format monetary quantities.

    STRPTR loc_MonGroupSeparator
        The separator for groups of digits before the decimal-point in
        monetary quantities.

    STRPTR loc_MonFracGroupSeparator
        The separator for groups of digits after the decimal-point in
        monetary quantities.

    STRPTR loc_MonGrouping
        A string whose elements indicate the size of each group of digits
        before the decimal-point character in monetary quantities.

    STRPTR loc_MonFracGrouping
        A string whose elements indicate the size of each group of digits
        after the decimal-point character in monetary quantities.

    UBYTE loc_MonFracDigits
        The number of fractional digits (those after the decimal-point)
        to be displayed in a formatted monetary quantity.

    UBYTE loc_MonIntFracDigits
        The number of fractional digits (those after the decimal-point)
        to be displayed in an internationally formatted monetary quantity.

    STRPTR loc_MonCS
        The local currency symbol applicable to the current locale.

    STRPTR loc_MonSmallCS
        The currency symbol for small amounts.

    STRPTR loc_MonIntCS
        The international currency symbol applicable to the current
        locale. The first three characters contain the alphabetic
        international currency symbol in accordance with those specified
        in ISO 4217 Codes for the Representation of Currency and Funds.
        The fourth character (immediately preceding the NULL) is the
        character used to separate the international currency symbol from
        the monetary quantity.

    STRPTR loc_MonPositiveSign
        The string used to indicate a non-negative monetary quantity.

    UBYTE loc_MonPositiveSpaceSep
        Specifies the number of spaces separating the currency symbol from
        the non-negative monetary quantity.

    UBYTE loc_MonPositiveSignPos
        Set to a value indicating the positioning of loc_MonPositiveSign
        for a non-negative monetary quantity.

    UBYTE loc_MonPositiveCSPos
        Set to 1 or 0 if loc_MonCS respectively precedes or succeeds
        the value for a non-negative monetary quantity.

    STRPTR loc_MonNegativeSign
        The string used to indicate a negative monetary quantity.

    UBYTE loc_MonNegativeSpaceSep
        Specifies the number of spaces separating the currency symbol from
        the negative monetary quantity.

    UBYTE loc_MonNegativeSignPos
        Set to a value indicating the positioning of loc_MonNegativeSign
        for a negative monetary quantity.

    UBYTE loc_MonNegativeCSPos
        Set to 1 or 0 if loc_MonCS respectively precedes or succeeds
        the value for a negative monetary quantity.

    The grouping tables pointed to by loc_Grouping, loc_FracGrounping,
    loc_MonGrouping, and loc_MonFracGrouping contain a stream of bytes
    with the following values:

        255		No further grouping is to be performed.

        0		The previous element is to be repeatedly used for the
            remainder of the digits.

        1..254	The integer value is the number of digits that comprise
            the current group. The next element is examined to
            determine the size of the next group of digits before
            the current group.

    The values of loc_MonPositiveSignPos and loc_MonNegativeSignPos are
    interpreted according to the following:

        0		Parentheses surround the quantity and currency symbol

        1		The sign string precedes the quantity and
            currency symbol

        2		The sign string succeeds the quantity and
            currency symbol

        3		The sign string immediately precedes the
            currency symbol

        4		The sign string immediately succeeds the
            currency symbol.


locale.library/CloseCatalog

   NAME
    CloseCatalog -- close a message catalog. (V38)

   SYNOPSIS
    CloseCatalog(catalog);
                 A0

    VOID CloseCatalog(struct Catalog *);

   FUNCTION
    Concludes access to a message catalog. The usage count of the
    catalog is decremented. When this count reaches 0, the catalog
    can be expunged from system memory whenever a memory panic occurs.

   INPUTS
    catalog - the message catalog to close. A NULL catalog is a valid
          parameter and is simply ignored.

   SEE ALSO
    OpenCatalog(), GetCatalogStr()


locale.library/CloseLocale

   NAME
    CloseLocale -- close a locale. (V38)

   SYNOPSIS
    CloseLocale(locale);
                A0

    VOID CloseLocale(struct Locale *);

   FUNCTION
    Concludes access to a locale.

   INPUTS
    locale - an opened locale. A NULL locale is a valid
         parameter and is simply ignored.

   SEE ALSO
    OpenLocale(), <libraries/locale.h>


locale.library/ConvToLower

   NAME
    ConvToLower -- convert a character to lower case. (V38)

   SYNOPSIS
    char = ConvToLower(locale,character);
    D0	           A0     D0

    ULONG ConvToLower(struct Locale *,ULONG);

   FUNCTION
    This function tests if the character specified is upper case. If it is
    then the lower case version of that character is returned, and if it
    isn't then the original character is returned.

   INPUTS
    locale - the locale to use for the conversion
    character - the character to convert

   RESULT
    char - a (possibly) converted character

   NOTE
    This function requires a full 32-bit character be passed-in in order
    to support multi-byte character sets.


locale.library/ConvToUpper

   NAME
    ConvToUpper -- convert a character to upper case. (V38)

   SYNOPSIS
    char = ConvToUpper(locale,character);
    D0	           A0     D0

    ULONG ConvToUpper(struct Locale *,ULONG);

   FUNCTION
    This function tests if the character specified is lower case. If it is
    then the upper case version of that character is returned, and if it
    isn't then the original character is returned.

   INPUTS
    locale - the locale to use for the conversion
    character - the character to convert

   RESULT
    char - a (possibly) converted character

   NOTE
    This function requires a full 32-bit character be passed-in in order
    to support multi-byte character sets.


locale.library/FormatDate

   NAME
    FormatDate -- generate a date string based on a date formatting
              template. (V38)

   SYNOPSIS
    FormatDate(locale,fmtTemplate,date,putCharFunc);
               A0     A1          A2   A3

    VOID FormatDate(struct Locale *,STRPTR,struct DateStamp *,
                    struct Hook *);

   FUNCTION
    This function processes a formatting template and generates
    a stream of bytes that's sent one character at a time to the
    putCharFunc callback hook.

   INPUTS
    locale - the locale to use for the formatting
    fmtTemplate - the NULL-terminated template describing the desired
              format for the date. This is constructed just like
              C-language printf() statements, except that different
              formatting codes are used. Just like in C, formatting
              codes start with a % followed by the formatting command.
              The following commands are accepted by this function:

                    %a - abbreviated weekday name
                    %A - weekday name
                    %b - abbreviated month name
                    %B - month name
                    %c - same as "%a %b %d %H:%M:%S %Y"
                    %C - same as "%a %b %e %T %Z %Y"
                    %d - day number with leading 0s
                    %D - same as "%m/%d/%y"
                    %e - day number with leading spaces
                    %h - abbreviated month name
                    %H - hour using 24-hour style with leading 0s
                    %I - hour using 12-hour style with leading 0s
                    %j - julian date
                    %m - month number with leading 0s
                    %M - the number of minutes with leading 0s
                    %n - insert a linefeed
                    %p - AM or PM strings
                    %q - hour using 24-hour style
                    %Q - hour using 12-hour style
                    %r - same as "%I:%M:%S %p"
                    %R - same as "%H:%M"
                    %S - number of seconds with leadings 0s
                    %t - insert a tab character
                    %T - same as "%H:%M:%S"
                    %U - week number, taking Sunday as first day of week
                    %w - weekday number
                    %W - week number, taking Monday as first day of week
                    %x - same as "%m/%d/%y"
                    %X - same as "%H:%M:%S"
                    %y - year using two digits with leading 0s
                    %Y - year using four digits with leading 0s

                  If the template parameter is NULL, a single NULL byte
              is sent to putCharFunc.
    date - the date to format into a string
    putCharFunc - a callback hook invoked for every character generated,
              including for the terminating NULL character. The hook
              is called with:

             A0 - address of Hook structure
            A1 - character for hook to process (not a pointer!)
                    A2 - locale pointer

   SEE ALSO
    ParseDate(), <libraries/locale.h>, <dos/dos.h>


locale.library/FormatString

   NAME
    FormatString -- format data into a character stream. (V38)

   SYNOPSIS
    next = FormatString(locale,fmtTemplate,dataStream,putCharFunc);
    D0                  A0     A1          A2         A3

    APTR FormatString(struct Locale *,STRPTR,APTR,struct Hook *);

   FUNCTION
    This function performs C-language-like formatting of a data stream,
    outputting the result a character at a time. Where % formatting
    commands are found in the formatting template, they are replaced with
    the corresponding elements in 'dataStream'. %% must be used in the
    string if a % is desired in the output.

    An extension to the standard C-language printf() conventions used
    by FormatString() is argument position specification. Specifying the
    argument position lets the order of the % commands change while the
    arguments provided remain the same. Using the C printf() call as an
    example:
        printf("%d eyes, %d feet and %d ears",eyes,feet,ears);
        printf("%3$d ears, %1$d eyes and %2$d feet",eyes,feet,ears);
    These two statements would produce the following output:
        "2 eyes, 3 feet and 4 ears" for the first
        "4 ears, 2 eyes and 3 feet" for the second

    The argument positioning feature lets you change the format string
    being processed while keeping the data stream the same. This is
    an invaluable tool when translating strings to different languages.

   INPUTS
    locale - the locale to use for the formatting
    fmtTemplate - a C-language-like NULL-terminated format string,
              with the following supported % options:

      %[arg_pos$][flags][width][.limit][length]type

      arg_pos - ordinal position of the argument for this command within
            the array of arguments pointed to by 'dataStream'
        $     - must follow the arg_pos value, if specified
      flags   - only one allowed. '-' specifies left justification.
      width   - field width. If the first character is a '0', the
                field is padded with leading 0s.
        .     - must precede the field limit value, if specified
      limit   - maximum number of characters to output from a string.
                (only valid for %s or %b).
      length  - size of input data defaults to word (16-bit) for types c,
            d, u and x, 'l' changes this to long (32-bit).
      type    - supported types are:
                      b - BSTR, data is 32-bit BPTR to byte count followed
                          by a byte string. A NULL BPTR is treated as an
                  empty string.
                      d - signed decimal
              D - signed decimal using the locale's formatting
                  conventions
              u - unsigned decimal
              U - unsigned decimal using the locale's formatting
                  conventions
                      x - hexadecimal with hex digits in uppercase
              X - hexadecimal with hex digits in lowercase
                      s - string, a 32-bit pointer to a NULL-terminated
                          byte string. A NULL pointer is treated
                          as an empty string.
                      c - character

                  If the formatting template parameter is NULL, the
              function returns without outputting anything. Note the
              meaning of %x and %X are swapped with respect to
              standard C conventions. This is for compatibility with
              exec.library/RawDoFmt().

    dataStream - a stream of data that is interpreted according to
             the format string. Often this is a pointer into
             the task's stack.
    putCharFunc - a callback hook invoked for every character generated,
              including for the terminating NULL character. The hook
              is called with:

             A0 - address of Hook structure
            A1 - character for hook to process (not a pointer!)
                    A2 - locale pointer

             the function is called with a NULL char at the end of
             the format string.

   RESULT
    next - A pointer to beyond the last data element used in 'dataStream'
           (the next argument that would have been processed).
           This allows multiple formatting passes to be made using the
           same data.

   WARNING
    This function formats word values in the data stream. If your compiler
    defaults to longs, you must add an "l" to your specifications. This
    can get strange for characters, which might look like "%lc".

   SEE ALSO
    exec.library/RawDoFmt()


locale.library/GetCatalogStr

   NAME
    GetCatalogStr -- get a string from a message catalog. (V38)

   SYNOPSIS
    string = GetCatalogStr(catalog,stringNum,defaultString);
    D0                     A0      D0        A1

    STRPTR GetCatalogStr(struct Catalog *,LONG,STRPTR);

   FUNCTION
    This function returns a specific string within a message catalog.
    If the catalog parameter is NULL, or the requested message does not
    exist, then defaultString is returned.

   INPUTS
    catalog - a message catalog as obtained from OpenCatalog(), or NULL
    stringNum - a message number within the catalog
    defaultString - string to return in case "catalog" is NULL or
                    "stringNum" can't be found

   RESULT
    string - a pointer to a NULL-terminated string. The returned string
         is READ-ONLY, do NOT modify! This string pointer is valid
         only as long as the catalog remains open.

   SEE ALSO
    OpenCatalog(), CloseCatalog()


locale.library/GetLocaleStr

   NAME
    GetLocaleStr -- get a standard string from a locale. (V38)

   SYNOPSIS
    string = GetLocaleStr(locale,stringNum);
    D0                    A0     D0

    STRPTR GetLocaleStr(struct Locale *,ULONG);

   FUNCTION
    This function returns a specific string associated with the given
    locale.

   INPUTS
    locale - a valid locale
    stringNum - the number of the string to get a pointer to. See the
            constants defined in <libraries/locale.h> for the
            possible values.

   RESULT
    string - a pointer to a NULL-terminated string, or NULL if the
         requested string number was out of bounds. The returned
         string is READ-ONLY, do NOT modify! This string pointer
         is valid only as long as the locale remains open.

   SEE ALSO
    OpenLocale(), CloseLocale(), <libraries/locale.h>


locale.library/IsXXXX

   NAME
    IsXXXX -- determine whether a character is of a certain type. (V38)

   SYNOPSIS
    state = IsXXXX(locale,character);
    D0	       A0     D0

    BOOL IsXXXX(struct Locale *,ULONG);

   FUNCTION
    These functions determine whether the character specified is of a
    certain type, according to the supplied locale.

    IsAlNum() - test if alphanumeric character
    IsAlpha() - test if alphabetical character
    IsCntrl() - test if control character
    IsDigit() - test if decimal digit character
    IsGraph() - test if visible character
    IsLower() - test if lower case character
    IsPrint() - test if blank
    IsPunct() - test if punctuation character
    IsSpace() - test if white space character
    IsUpper() - test if upper case character
    IsXDigit() - test if hexadecimal digit

   INPUTS
    locale - the locale to use for the test
    character - the character to test

   RESULT
    state - TRUE if the character is of the required type, FALSE otherwise

   NOTE
    These functions require full 32-bit characters be passed-in in order
    to support multi-byte character sets.


locale.library/OpenCatalog

   NAME
    OpenCatalogA -- open a message catalog. (V38)
    OpenCatalog -- varargs stub for OpenCatalogA(). (V38)

   SYNOPSIS
    catalog = OpenCatalogA(locale,name,tagList);
    D0                     A0     A1   A2

    struct Catalog *OpenCatalogA(struct Locale *,STRPTR,struct TagItem *);

    catalog = OpenCatalog(locale,name,firstTag, ...);

    struct Catalog *OpenCatalog(struct Locale *,STRPTR,Tag, ...);

   FUNCTION
    This function opens a message catalog. Catalogs contain all the
    text strings that an application uses. These strings can easily
    be replaced by strings in a different language, which causes the
    application to magically start operating in that new language.

    Catalogs originally come from disk files. This function searches for
    them in the following places:

        PROGDIR:Catalogs/languageName/name
        LOCALE:Catalogs/languageName/name

    where languageName is the name of the language associated with the
    locale parameter. So assuming an application called WizPaint:

        catalog = OpenCatalog(NULL,
                      "WizPaint.catalog",
                      OC_BuiltInLanguage,"english",
                      TAG_DONE);

    Passing NULL as first parameter to OpenCatalog() indicates you
    wish to use the system's default locale. Assuming the default locale
    specifies "deutsch" as language, OpenCatalog() tries to open the
    catalog as:

        PROGDIR:Catalogs/deutsch/WizPaint.catalog

    and if that file is not found, then OpenCatalog() tries to open it
    as:

        LOCALE:Catalogs/deutsch/WizPaint.catalog

    PROGDIR: is not always checked before LOCALE: is. If the volume which
    PROGDIR: is assigned to is NOT currently mounted, and if the one
    which LOCALE: is assigned to IS mounted, then LOCALE: is checked
    first, followed by PROGDIR: if needed. This is done in order to
    minimize the number of disk swaps on floppy systems.

    The OC_BuiltInLanguage tag specifies the language of the strings
    that are built into the application. If the language of the
    built-in strings matches that of the locale, then no catalog
    need be loaded from disk and the built-in strings can be used
    directly.

    locale.library caches text catalogs in order to minimize disk
    access. As such, OpenCatalog() may or may not cause disk access.
    This fact should be taken into consideration. Unused catalogs are
    automatically flushed from the system when there is not enough
    memory. When there is disk access, it is possible a DOS requester
    may be opened asking for a volume to be inserted. You can avoid this
    requester opening by setting your process' pr_WindowPtr field to -1.

   INPUTS
    locale - the locale for which the catalog should be opened, or NULL.
         When NULL, then the system's default locale is used. This
         should generally be NULL
    name - the NULL-terminated name of the catalog to open, typically
           the application name with a ".catalog" extension
    tagList - pointer to an array of tags providing optional extra
          parameters, or NULL

   TAGS
    OC_BuiltInLanguage (STRPTR) - language of built-in strings of the
                      application. That is, this tag identifies
                      the language used for the "defaultString"
                      parameter used in the GetCatalogStr()
                      function. Default is "english". Providing
                      this tag and setting its value to NULL
                      indicates that there are no built-in
                      strings.

    OC_BuiltInCodeSet (ULONG) - code set of built-in strings. Default is 0.
                    THIS TAG SHOULD ALWAYS BE SET TO 0 FOR NOW.

    OC_Language (STRPTR) - language explicitly requested for the catalog.
                   A catalog of this language will be returned if
                   possible, otherwise a catalog in one of the
                   user's preferred languages. This tag should
                   normally not be provided as it overrides the
                   user's preferences.

    OC_Version (UWORD) - catalog version number required. Default is 0
                 which means to accept any version of the catalog
                 that is found. Note that if a version is
                 specified, the catalog's version much match it
                 exactly. This is different from version numbers
                 used by OpenLibrary().

   RESULT
    catalog - a message catalog to use with GetCatalogStr() or NULL.
          A NULL result does not necessarily indicate an error.
          If OpenCatalog() determines that the built-in strings of
          the application can be used instead of an external catalog
          from disk, then NULL is returned. To determine whether
          a NULL result actually indicates an error, look at the
          return value of dos.library/IoErr(). 0 means no error.

          GetCatalogStr() interprets a NULL catalog as meaning to use
          the built-in strings.

   NOTE
    In most cases, failing to open a catalog should not be considered a
    fatal error, and the application should continue operating and
    simply use the built-in set of strings instead of the disk-based
    catalog. Note that GetCatalogStr() accepts a NULL catalog pointer for
    this very reason.

    Also note that displaying an error message when a catalog fails to
    open can be a meaningless endeavor as the message is likely in a
    language the user does not understand.

   SEE ALSO
    CloseCatalog(), GetCatalogStr()


locale.library/OpenLocale

   NAME
    OpenLocale -- open a locale. (V38)

   SYNOPSIS
    locale = OpenLocale(name);
    D0                  A0

    struct Locale *OpenLocale(STRPTR);

   FUNCTION
    This function opens a named locale. Locales contain many parameters
    that an application needs to consider when being integrated into
    different languages, territories and customs. Using the information
    stored in a locale instead of hard-coding it into an application,
    lets the application dynamically adapt to the user's environment.

    Locales originally come from disk files which are created by the
    user using the Locale preferences editor. Passing a NULL instead of
    a name causes this function to return the current default locale.
    This is what most applications will do.

    Every locale specifies a language, and special language drivers
    must be loaded from disk depending on which language is being used.
    These files include for example:

        LOCALE:Languages/français.language
        LOCALE:Languages/dansk.language
        LOCALE:Languages/italiano.language

   INPUTS
    name - the NULL-terminated name of the locale to open, or NULL to open
           the current default locale. This should generally be NULL. The
           name you supply must be a pathname leading to a locale
           preferences file. This is an IFF PREF file as saved by
           Locale prefs, that can contain both LCLE and CTRY chunks.
           See <prefs/locale.h> for definitions.

   RESULT
    locale - a pointer to an initialized Locale structure, or NULL if the
         locale could not be loaded. In the case of a NULL return, the
         DOS IoErr() function can be called to obtain more information
         on the failure.

         When passing a NULL name parameter to this function, you are
         guaranteed a valid return.

   SEE ALSO
    CloseLocale(), <libraries/locale.h>, <prefs/locale.h>


locale.library/ParseDate

   NAME
    ParseDate -- interpret a string according to the date formatting
             template and convert it into a DateStamp. (V38)

   SYNOPSIS
    state = ParseDate(locale,date,fmtTemplate,getCharFunc);
    D0	          A0     A1   A2          A3

    BOOL ParseDate(struct Locale *,struct DateStamp *,STRPTR,struct Hook *);

   FUNCTION
    This function converts a stream of characters into an AmigaDOS
    DateStamp structure. The characters are obtained from the
    getCharFunc callback hook and the formatting template is used
    to direct the parse.

   INPUTS
    locale - the locale to use for the formatting
    date - place to put the converted date, this may be NULL in which
           case this routine can be used to simply validate a date
    fmtTemplate - the date template describing the expected format of the
              data. See FormatDate() documentation for a description of
              date templates. The following formatting controls from
              FormatDate() can be used in ParseDate():
                    %a %A %b %B %d %e %h %H %I %m %M %p %S %y %Y
    getCharFunc - a callback hook invoked whenever a character is required.
              The hook should return the next character to process,
              with a NULL character to indicate the end of the string.
              The hook is called with:

             A0 - address of Hook structure
                    A1 - locale pointer
            A2 - NULL

                  The hook returns the character to process in D0. Note
              that a complete 32-bit result is expected in D0, not
              just 8 bits.

   RESULT
    state - TRUE if the parsing went OK, or FALSE if the input did not
        match the template

   SEE ALSO
    FormatDate(), <dos/dos.h>


locale.library/StrConvert

   NAME
    StrConvert -- transform a string according to collation information.
              (V38)

   SYNOPSIS
    length = StrConvert(locale,string,buffer,bufferSize,type);
    D0                  A0     A1     A2     D0         D1

    ULONG StrConvert(struct Locale *,STRPTR,APTR,ULONG,ULONG);

   FUNCTION
    This function transforms the passed string and places the resulting
    into the supplied buffer. No more than bufferSize bytes are copied
    into the buffer.

    The transformation is such that if the C strcmp() function is applied
    to two transformed strings, it returns a value corresponding to
    the result returned by the StrnCmp() function applied to the two
    original strings.

   INPUTS
    locale - the locale to use for the transformation
    string - NULL-terminated string to transform
    buffer - buffer where to put the transformed string
    bufferSize - maximum number of bytes to deposit in the buffer
                 StrConvert() may require more storage than
             the unconverted string does
    type - describes how the transformation is to be performed. See
           the documentation on StrnCmp() for more information on the
           comparison types available

   RESULT
    length - length of the transformed string which is the number of bytes
         deposited in the buffer minus 1 (since strings are NULL-
         terminated)

   SEE ALSO
    StrnCmp(), <libraries/locale.h>


locale.library/StrnCmp

   NAME
    StrnCmp -- localized string comparison. (V38)

   SYNOPSIS
    result = StrnCmp(locale,string1,string2,length,type);
    D0               A0     A1      A2      D0     D1

    LONG StrnCmp(struct Locale *,STRPTR,STRPTR,LONG,ULONG);

   FUNCTION
    Compares string1 to string2 according to the collation information
    provided by the locale and returns an integer greater than,
    equal to, or less than zero, accordingly as the string pointed to
    by string1 is greater than, equal to, or less than the string
    pointed to by string2.

    The length parameter specifies how many characters to compare, or if
    the length is specified as -1 then the strings are compared until
    a NULL is encountered.

    The type parameter dictates how the comparison is to be performed.

   INPUTS
    locale - the locale to use for this comparison
    string1	- NULL-terminated string
    string2	- NULL-terminated string
    length - the maximum number of characters to be compared, or -1 to
         compare all characters until a NULL is encountered
    type - describes how the comparison is to be performed. The following
           values can be passed:
         SC_ASCII causes an ASCII-based case-insensitive comparison
         to be performed. SC_ASCII is the fastest of the comparison
         types, but it uses ASCII ordering and considers accented
         characters different than their non-accented counterparts.

         SC_COLLATE1 causes the characters to be compared using their
         primary sorting order. This effectively produces a comparison
         that ignores letter case and diacritical marks. That is,
         letters such as "e" and "é" are treated as if they were both
         "e".

         SC_COLLATE2 causes the characters to be compared using both
         their primary and secondary sorting order. SC_COLLATE2 is
         slower than SC_COLLATE1. This is the type of comparison to
         use when sorting data to be presented to the user. It operates
         in two passes. First it performs a comparison equivalent to
         SC_COLLATE1. If both strings compare the same, then a second
         pass is made using the secondary sorting order, which gives
         finer resolution to the comparison. For example, SC_COLLATE1
         would return the following strings as identical:
            "père"  and  "pere"
         since SC_COLLATE1 ignores diacritical marks. SC_COLLATE2
         would make a second pass over the string comparing
         diacritical marks instead of actual characters.

   RESULT
    result - relationship between string1 and string2
            <0 means string1 < string2
            =0 means string1 = string2
            >0 means string1 > string2

   SEE ALSO
    OpenLocale(), CloseLocale(), StrConvert()


lowlevel.doc

     AddKBInt()
     AddTimerInt()
     AddVBlankInt()
     ElapsedTime()
     GetKey()
     GetLanguageSelection()
     QueryKeys()
     ReadJoyPort()
     RemKBInt()
     RemTimerInt()
     RemVBlankInt()
     SetJoyPortAttrsA()
     StartTimerInt()
     StopTimerInt()
     SystemControlA()


lowlevel.library/AddKBInt

   NAME
    AddKBInt -- adds a routine to the keyboard interrupt. (V40)

   SYNOPSIS
    intHandle = AddKBInt(intRoutine, intData);
    D0                   A0          A1

    APTR AddKBInt(APTR, APTR);

   FUNCTION
    This routine extends the functionality of the keyboard interrupt to
    include intRoutine. Since this is an extention of the normal
    keyboard interrupt all of the keyboard handshaking is handled. The
    keyboard error codes are filtered out and not passed to intRoutine.

    The routine is called whenever the user enters a key on the
    keyboard.

    The routine is called from within an interrupt, so normal
    restrictions apply. The routine must preserve the following
    registers: A2, A3, A4, A7, D2-D7. Other registers are
    scratch, except for D0, which MUST BE SET TO 0 upon
    exit. On entry to the routine, A1 holds 'intData' and A5
    holds 'intRoutine', and D0 contains the rawkey code read
    from the keyboard.

    The routine is not called when a reset is received from the
    keyboard.

    This is a low level function that does not fit the normal Amiga
    multitasking model. The interrupt installed will have no knowledge
    of which window/screen currently has input focus.

    If your program is to exit without reboot, you MUST call RemKBInt()
    before exiting.

    Only one interrupt routine may be added to the system.  ALWAYS
    check the return value in case some other task has previously
    used this function.

   INPUTS
    intRoutine - the routine to invoke every vblank. This routine should
             be as short as possible to minimize its effect on overall
             system performance.
    intData - data passed to the routine in register A1. If more than one
          long word of data is required this should be a pointer to
          a structure that contains the required data.

   RESULT
    intHandle - a handle used to manipulate the interrupt, or NULL
            if it was not possible to attach the routine.

   SEE ALSO
    RemKBInt()


lowlevel.library/AddTimerInt

   NAME
    AddTimerInt -- adds an interrupt that is executed at regular
               intervals. (V40)

   SYNOPSIS
    intHandle = AddTimerInt(intRoutine, intData);
    D0                      A0          A1

    APTR AddTimerInt(APTR, APTR);

   FUNCTION
    Calling this routine causes the system to allocate a CIA timer
    and set up 'intRoutine' to service any interrupts caused by the timer.
    Although the timer is allocated it is neither running, nor enabled.
    StartIntTimer() must be called to establish the time interval and
    start the timer.

    The routine is called from within an interrupt, so normal
    restrictions apply. The routine must preserve the following
    registers: A2, A3, A4, A7, D2-D7. Other registers are
    scratch, except for D0, which MUST BE SET TO 0 upon
    exit. On entry to the routine, A1 holds 'intData' and A5
    holds 'intRoutine'.

    Only a single CIA timer will be allocated by this routine. So this
    routine may only be called once without an intervening call to
    RemTimerInt().

    The CIA timer used by this routine is not guaranteed to always be
    the same. This routine utilizes the CIA resource and uses an
    unallocated CIA timer.

    If your program is to exit without reboot, you MUST match all
    calls to this function with calls to RemTimerInt() before exiting.

    Even if you only use the function once in your program; checking
    the return value will make your program more tolerant for
    mulititasking on the Amiga computer platforms.

   INPUTS
    intRoutine - the routine to invoke upon timer interrupts. This routine
             should be as short as possible to minimize its effect on
             overall system performance.
    intData - data passed to the routine in register A1. If more than one
          long word of data is required this should be a pointer to
          a structure that contains the required data.

   RESULT
    intHandle - a handle used to manipulate the interrupt, or NULL
            if it was not possible to attach the routine.

   SEE ALSO
    RemTimerInt(), StopTimerInt(), StartTimerInt()


lowlevel.library/AddVBlankInt

   NAME
    AddVBlankInt -- adds a routine executed every vertical blank. (V40)

   SYNOPSIS
    intHandle = AddVBlankInt(intRoutine, intData);
    D0		         a0	  a1

    APTR AddVBlankInt(APTR, APTR);

   FUNCTION
    Lets you attach a routine to the system which will get called
    everytime a vertical blanking interrupt occurs.

    The routine is called from within an interrupt, so normal
    restrictions apply. The routine must preserve the following
    registers: A2, A3, A4, A7, D2-D7. Other registers are
    scratch, except for D0, which MUST BE SET TO 0 upon
    exit. On entry to the routine, A1 holds 'intData' and A5
    holds 'intRoutine'.

    If your program is to exit without reboot, you MUST call
    RemVBlankInt() before exiting.

    Only one interrupt routine may be added to the system.  ALWAYS check
    the return value in case some other task has previously used this
    function.

   INPUTS
    intRoutine - the routine to invoke every vblank. This routine should
             be as short as possible to minimize its effect on overall
             system performance.
    intData - data passed to the routine in register A1. If more than one
          long word of data is required this should be a pointer to
          a structure that contains the required data.

   RESULT
    intHandle - a handle used to manipulate the interrupt, or NULL
            if it was not possible to attach the routine.

   SEE ALSO
    RemVBlankInt()


lowlevel.library/ElapsedTime

   NAME
    ElapsedTime -- returns the time elapsed since it was last called. (V40)

   SYNOPSIS
    fractionalSeconds = ElapsedTime(context);
    D0                              A0

    ULONG ElapsedTime(struct EClockVal *);

   FUNCTION
    This function utilizes the timer.device/ReadEClock() function to get
    an accurate elapsed time value. Since the context needs to be
    established the first call to this routine will return a nonsense
    value.

    The return value for this function only allows for sixteen bits
    worth for the integer number of seconds and sixteen bits for the
    factional number of seconds.

    With sixteen bits worth of integer seconds this function can be
    used to timer an interval up to about 16 hours. If the actual time
    interval is larger this function will return this maximum value.

    The sixteen bits for fractional seconds gives a resolution of
    approximately 20 microseconds. However, it is not recomended
    to expect this function to be accurate for a time interval of
    less than 200 microseconds.

   INPUTS
    context - pointer to an EClockVal structure. The first time you
          call this function, you should initialize the structure
          to 0s. You should then reuse the same structure for
          subsequent calls to this function, as this is how the
          elapsed time is calculated.

   RESULT
    fractionalSeconds - The elapsed time as a fixed point 32-bit
                        number with the point fixed in the middle.
                        That is, the upper order sixteen bits represent
                        the number of seconds elapsed. The low order
                        sixteen bit represent the fractional number of
                        seconds elapsed. This value is limited to about
                        sixteen hours. Although this value is precise
                        to nearly 20 microseconds it is only accurate to
                        within 200 microseconds.

   WARNING
    The first call to this function will return a non-sense value. Only
    rely on its result starting with the second call.

   SEE ALSO
    timer.device/ReadEClock()


lowlevel.library/GetKey

   NAME
    GetKey -- returns the currently pressed rawkey code and qualifiers.
          (V40)

   SYNOPSIS
    key = GetKey();
    D0

    ULONG GetKey(VOID);

   FUNCTION
    This function returns the currently pressed non-qualifier key and
    all pressed qualifiers.

    This function is safe within an interrupt.

    This is a low level function that does not fit the normal Amiga
    multitasking model. The values returned by this function are
    not modified by which window/screen currently has input focus.

   RESULT
    key - key code for the last non-qualifier key pressed in the low
          order word. If no key is pressed this word will be FF. The
          upper order word contains the qualifiers which can be found
          within the long word as follows:
                    Qualifier               Key
                    LLKB_LSHIFT             Left Shift
                    LLKB_RSHIFT             Rigt Shift
                    LLKB_CAPSLOCK           Caps Lock
                    LLKB_CONTROL            Control
                    LLKB_LALT               Left Alt
                    LLKB_RALT               Right Alt
                    LLKB_LAMIGA             Left Amiga
                    LLKB_RAMIGA             Right Amiga

   SEE ALSO
    <libraries/lowlevel.h>


lowlevel.library/GetLanguageSelection

   NAME
    GetLanguageSelection -- returns the current language selection. (V40)

   SYNOPSIS
    language = GetLanguageSelection();
    D0

    ULONG GetLanguageSelection (VOID);

   FUNCTION
    Determine what the user has specified as a language.

   RESULT
    language - user specified language, or zero if none has yet been
           specified. See <libraries/lowlevel.h> for a definition
           of the currently supported language.

   SEE ALSO
    <libraries/lowlevel.h>, locale.doc


lowlevel.library/QueryKeys

   NAME
    QueryKeys -- return the states for a set of keys. (V40)

   SYNOPSIS
    QueryKeys(queryArray, arraySize);
              A0          D1

    VOID QueryKeys(struct KeyQuery *, UBYTE);

   FUNCTION
    Scans the keyboard to determine which of the rawkey codes
    listed in the QueryArray are currently pressed. The state for each
    key is returned in the array.

    This function may be invoked from within an interrupt, but the size
    of QueryArray should be kept as small as possible.

    This is a low level function that does not fit the normal Amiga
    multitasking model. The values returned have no knowledge
    of which window/screen currently has input focus.

   INPUTS
    queryArray - an array of KeyQuery structures. The kq_KeyCode fields
             of these structures should be filled with the rawkey
             codes you wish to query about. Upon return from this
             function, the kq_Pressed field of these structures
             will be set to TRUE if the associated key is down,
                 and FALSE if not.
    arraySize - number of key code entries in queryArray

   SEE ALSO
    <libraries/lowlevel.h>


lowlevel.library/ReadJoyPort

   NAME
    ReadJoyPort -- return the state of the selected joy/mouse port. (V40)

   SYNOPSIS
    portState = ReadJoyPort(portNumber);
    D0                      D0

    ULONG ReadJoyPort(ULONG);

   FUNCTION
    This function is used to determine what device is attached to the
    joy port and the current position/button state. The user may attach
    a mouse, game controller, or joystick to the port and this function
    will dynamically detect which device is attached and return the
    appropriatly formatted portState.

    To determine the type of controller that is attached, this function
    clocks the game controller and/or interprets changes in the joy
    port data. Valid clocked data from the game controller is immediately
    detected. However, to accuratly determine if a mouse or joystick is
    attached, several calls to this function are required along with some
    movement at the joy port by the user.

    This function always executes immediatly.

    This is a low level single threaded function that does not fit the
    normal Amiga multitasking model. Only one task can be executing
    this routine at any time. All others will return immediately with
    JP_TYPE_NOTAVAIL.

    The nature of this routine is not meant to encourage non-multitasking
    friendly programming practices like polling loops. If your task
    is waiting for a transition to be returned use a WaitTOF() between
    calls to minimize the total system impact.

    When called the first time, for each port, this function attempts to
    acquire certain system resources. In order to aquire these resources
    this function MUST be called from a task, or a DOS process. If this
    function fails to aquire the necessary resources, it will
    return with JP_TYPE_NOTAVAIL. Once the resources are aquired (return
    value other than JP_TYPE_NOTAVAIL) this function may be used in
    interrupts.

   INPUTS
    portNumber - port to read, in the range 0 to 3.

   RESULT
    portState - bit map that identifies the device and the current
                state of that device. The format of the bit map is
                dependant on the type of device attached.

                The following constants from <libraries/lowlevel.h>
                are used to determine which device is attached and
                the state of that device.

                The type of device can be determined by applying
                the mask JP_TYPE_MASK to the return value and comparing
                the resultant value with the following:

                    JP_TYPE_NOTAVAIL        port data unavailable
                    JP_TYPE_GAMECTLR        game controller
                    JP_TYPE_MOUSE           mouse
                    JP_TYPE_JOYSTK          joystick
                    JP_TYPE_UNKNOWN         unknown device

                If type = JP_TYPE_GAMECTLR the bit map of portState is:
                    JPF_BUTTON_BLUE         Blue - Stop
                    JPF_BUTTON_RED          Red - Select
                    JPF_BUTTON_YELLOW       Yellow - Repeat
                    JPF_BUTTON_GREEN        Green - Shuffle
                    JPF_BUTTON_FORWARD      Charcoal - Forward
                    JPF_BUTTON_REVERSE      Charcoal - Reverse
                    JPF_BUTTON_PLAY         Grey - Play/Pause
                    JPF_JOY_UP              Up
                    JPF_JOY_DOWN            Down
                    JPF_JOY_LEFT            Left
                    JPF_JOY_RIGHT           Right

                If type = JP_TYPE_JOYSTK the bit map of portState is:
                    JPF_BUTTON_BLUE         Right
                    JPF_BUTTON_RED          Fire
                    JPF_JOY_UP              Up
                    JPF_JOY_DOWN            Down
                    JPF_JOY_LEFT            Left
                    JPF_JOY_RIGHT           Right

                If type = JP_TYPE_MOUSE the bit map of portState is:
                    JPF_BUTTON_BLUE         Right mouse
                    JPF_BUTTON_RED          Left mouse
                    JPF_BUTTON_PLAY         Middle mouse
                    JP_MVERT_MASK           Mask for vertical counter
                    JP_MHORZ_MASK           Mask for horizontal counter

   SEE ALSO
    SetJoyPortAttrs()


lowlevel.library/RemKBInt

  NAME
    RemKBInt -- remove a previously installed keyboard interrupt. (V40)

  SYNOPSIS
    RemKBInt(intHandle);
             A1

    VOID RemKBInt(APTR);

  FUNCTION
    Remove a keyboard interrupt routine previously added with AddKBInt().

  INPUTS
    intHandle - handle obtained from AddKBInt(). This may be NULL,
            in which case this function does nothing.

  SEE ALSO
    AddKBInt()


lowlevel.library/RemTimerInt

   NAME
    RemTimerInt -- remove a previously installed timer interrupt. (V40)

   SYNOPSIS
    RemTimerInt(intHandle);
                A1

    VOID RemTimerInt(APTR);

   FUNCTION
    Removes a timer interrupt routine previously installed with
    AddTimerInt.

   INPUTS
    intHandle - handle obtained from AddTimerInt(). This may be NULL,
            in which case this function does nothing.

   SEE ALSO
    AddTimerInt(), StopTimerInt(), StartTimerInt()


lowlevel.library/RemVBlankInt

   NAME
    RemVBlankInt -- remove a previously installed vertical blank routine.
            (V40)

   SYNOPSIS
    RemVBlankInt(intHandle);
             A1

    VOID RemVBlankInt(APTR);

   FUNCTION
    Removes a vertical blank interrupt routine previously added with
    AddVBlankInt().

   INPUTS
    intHandle - handle obtained from AddVBlankInt(). This may be NULL,
            in which case this function does nothing.

   SEE ALSO
    AddVBlankInt()


lowlevel.library/SetJoyPortAttrsA

   NAME
    SetJoyPortAttrsA -- change the attributes of a port.  (V40.27)
    SetJoyPortAttrs -- varargs stub for SetJoyPortAttrsA().  (V40.27)

   SYNOPSIS
    success = SetJoyPortAttrsA(portNumber, tagList);
    D0                         D0          A1

    BOOL SetJoyPortAttrsA(ULONG, struct TagItem *);

    Success = SetJoyPortAttrs(portNumber, firstTag, ...);

    BOOL SetJoyPortAttrs(Tag, ...);

   FUNCTION
    This function allows modification of several attributes held by
    ReadJoyPort() about both it's operation and the type of controller
    currently plugged into the port.

    ReadJoyPort()'s default behavior is to attempt to automatically
    sense the type of controller plugged into any given port, when
    asked to read that port. This behavior is beneficial, to allow
    simple detection of the type of controller plugged into the port.
    Unfortunately, rare cases are possible where extremely fine
    mouse movements appear to be real joystick movements. Also, this
    ability to auto-sense the controller type causes most reads to
    take longer than if there were no auto-sensing.

    SetJoyPortAttrs() is intended to provide for both of these cases.
    It allows the programmer to notify ReadJoyPort() to stop spending
    time attempting to sense which type of controller is in use -- and,
    optionally, to force ReadJoyPort() into utilizing a certain
    controller type.

   INPUTS
    portNumber - the joyport in question (0-3).
    tagList - a pointer to an array of tags providing parameters
              to SetJoyPortAttrs(); if NULL, the function
              will return TRUE, but do nothing.

   TAGS
    SJA_Type (ULONG) - Sets the current controller type to the mouse,
            joystick, or game controller. Supply one of
            SJA_TYPE_GAMECTLR, SJA_TYPE_MOUSE, SJA_TYPE_JOYSTK,
            or SJA_TYPE_AUTOSENSE. If SJA_TYPE_AUTOSENSE is used,
            ReadJoyPort() will attempt to determine the type of
            controller plugged into the given port automatically.
            If one of the other types is used, ReadJoyPort() will
            make no attempt to read the given controller as
            anything other than the type specified. The default
            type is SJA_AUTOSENSE.

                     Note -- if you set the type to anything other than
                     auto-sense, it's your responsibility to return it
                     to auto-sense mode before exiting.

    SJA_Reinitialize (VOID) - Return a given port to it's initial state,
                 forcing a port to deallocate any allocated resources;
                     return the implied type to SJA_TYPE_AUTOSENSE.

   RESULT
    success - TRUE if everything went according to plan, or FALSE upon
          failure

   SEE ALSO
    ReadJoyPort(), <libraries/lowlevel.h>


lowlevel.library/StartTimerInt

   NAME
    StartTimerInt -- start the timer associated with the timer interrupt.
             (V40)

   SYNOPSIS
    StartTimerInt(intHandle, timeInterval, continuous);
                  A1         D0            D1

    VOID StartTimerInt(APTR, ULONG, BOOL);

   FUNCTION
    This routine starts a stopped timer that is assocatied with a
    timer interrupt created by AddTimerInt().

   INPUTS
    intHandle - handle obtained from AddTimerInt().
    timeInterval - number of micoseconds between interrupts. The
                   maximum value allowed is 90,000. If higher values
                   are passed there will be unexpected results.
    continuous - FALSE for a one shot interrupt. TRUE for multiple
                 interrupts.

   SEE ALSO
    AddTimerInt(), RemTimerInt(), StopTimerInt()


lowlevel.library/StopTimerInt

   NAME
    StopTimerInt -- stop the timer associated with the timer interrupt.
            (V40)

   SYNOPSIS
    StopTimerInt(intHandle);
                 A1

    VOID StopTimerInt(APTR);

   FUNCTION
    Stops the timer associated with the timer interrupt handle passed.
    This is used to stop a continuous timer started by
    StartTimerInt().

   INPUTS
    intHandle - handle obtained from AddTimerInt().

   SEE ALSO
    AddTimerInt(), RemTimerInt(), StartTimerInt()


lowlevel.library/SystemControlA

   NAME
    SystemControlA - Method for selectively disabling OS features. (V40)
    SystemControl - varargs stub for SystemControlA().

   SYNOPSIS
    failTag = SystemControlA(tagList);
    D0                       A1

    ULONG SystemControlA(struct TagItem *);

    failTag = SystemControl(firstTag, ...);

    ULONG SystemControl(Tag, ...);

   FUNCTION
    This function is used to alter the operation of the system. Some of
    the alterations involve controlling what are normally regarded as
    system resources. In order to minimize confusion only one task is
    allowed to control any part of the system resources. This prevents
    the possiblity of two tasks fighting, each controlling a part of the
    system. If a tag is identified as task exclusive, it means that
    only one task can hold (set to TRUE) that tag. If
    another task attempts to set the same tag to TRUE, the call to
    SystemControl() will fail.

    It is important to remember that SystemControl() can fail.

    This is a low level function and certain tags do not fit the normal
    Amiga multitasking model.

   INPUTS
    tagList - pointer to an array of tags listing the features of the
              system to be enabled/disabled.

   TAGS
    SCON_TakeOverSys (BOOL)
        TRUE -	Takes over the CPU to ensure that a program gets every
            ounce of CPU time (with the exception of crucial
            interrupts). When in this mode, the CPU will belong
            completely to the program. Task switching will be
            disabled and the program will get all CPU cycles. This
            means any calls to the OS that involve multitasking in
            some way will not execute correctly. Other tasks will
            not run until this tag is used with FALSE. However,
            during a Wait() on a signal, multitasking will
            automatically be turned back on until the signal is
            received. Once received, multitasking will again be
            disabled and the CPU will be exclusive to the owning
            program.
        FALSE - Relinquishes the CPU and reenables multitasking.
            This tag is task exculsive. This tag nests. A task may
            take over the CPU several times before relinquishing
            it.

    SCON_KillReq (BOOL)
           TRUE - 	Disables system requesters.  These are the reasons for
            NOT disabling system requesters:

                        1- No calls in the program will cause a system
                   requester.
                        2- The only thing that could cause a requester
                   to appear is the lack of a CD in the drive and
                   SCON_CDReboot is set to CDReboot_On, therefore a
                   requester can't appear.
                    3- The only disk I/O is via a CD with SCON_CDReboot
                   set to CDReboot_On and/or nonvolatile.library.

                When requesters should not be disabled.
                GAME PROGRAMS:
                No DOS calls are used after loading; or SCON_CDReboot
            is CDReboot_On; and nonvolatile.library is used for
            loading and saving user data.

                This fits the above case since; After loading either
            DOS calls are not used fitting reason 1, or the game
            is accessing the CD and has SCON_CDReboot set to
            CDReboot_On fitting reason 2. The game accesses high
            scores, game position, etc through nonvolatile.library,
            fitting reason 3.

        FALSE -	Enables requesters for the program.

        This tag nests. Tasks may disable requesters several times before
        enabling them.  However, there must be a matching number of calls.

    SCON_CDReboot (ULONG)
        CDReboot_On - Ejecting the CD will cause a reboot of the
            system. Use this only if the program cannot deal with
            error conditions.
        CDReboot_Off - Ejecting the CD will not cause a reboot of the
                system. Use this if the program needs to insert CDs
            while running.
        CDReboot_Default - Restore the default reboot behavior for this
            system. This should be used upon exit, if this tag had
            been used to change the reboot behaviour. For the CD32
             this value is synonomous with CDReboot_On. For Amiga
            computers this value is synonomous with CDReboot_Off.

        Note that the default reboot behavior differs depending on the
        platform. If a program requires a specific behavior it must
        use this function to set the behavior. For example, a CD audio
        mixer would use this tag with the data CDReboot_Off. This will
        allow the changing of audio CDs on the game machine as well as
        Amiga computers.

        If, however, there is no error detection code at all this tag
        should be used with the data CDReboot_On.

        It is hoped that no program will require CDReboot_On. If all
        programs check for error condition and recover gracefully such a
        call should never be necessary. With the default behavior the
        CD32 will always reset on disk ejects, and programs
        run from Amiga computers will not reset. Thus, leaving the
        default will increase the market for a program to include both
        types of platforms.

        This tag does not nest.

    SCON_StopInput (BOOL) - When TRUE, stops input.device from using any
        CPU cycles. Also prevents input.device from passing along any
        events from either the keyboard and/or port 0.

        This tag is task exclusive. This tag is NOT reversible.
        Attempting to reverse will result in confused/garbled input
        events.

    SCON_AddCreateKeys (ULONG) - Starts creating rawkey codes for the
        joystick/game controller on the given unit. The unit value is
        checked for validity and must be either 0 or 1. Each different unit
        used results in some code added to the VBlank interrupt chain.
        This tag nests. The tag SCON_RemCreateKeys is used to undo this
        tag. Tasks may create rawkey codes several times before stopping
        them.

        Note that when operating in an Intuition window, the controller's
        blue button is the equivilent of the mouse menu button. Therefore,
        Intuition will be capturing most blue button events. If
        notificiation of these events is important, review the
        documentation for WFLG_RMBTRAP in the
        intuition.library/OpenWindow() autodoc.

    SCON_RemCreateKeys (ULONG) - stops rawkey codes for the joystick/game
        controller on the given unit. The unit value is checked for
        validity and must be either 0 or 1.

   RESULT
    failTag - zero if all tags succeeded. A non-zero return indicates a
          tag that has failed. It is possible that other tags may
              fail as well.

              If any tag fails there will be no change in the system due
              to other tags.

   SEE ALSO
    <libraries/lowlevel.h>


mathffp.doc

     SPAbs()
     SPAdd()
     SPCeil()
     SPCmp()
     SPDiv()
     SPFix()
     SPFloor()
     SPFlt()
     SPMul()
     SPNeg()
     SPSub()
     SPTst()


mathffp.library/SPDiv

NAME
    SPDiv -- Divide two floating point numbers.

SYNOPSIS
    fnum3 = SPDiv(fnum1, fnum2)
    D0	      D1     D0

    float SPDiv(float fnum1, float fnum2);

FUNCTION
    Accepts two floating point numbers and returns the arithmetic
    division of said numbers.

INPUTS
    fnum1 	- floating point number.
    fnum2	- floating point number.

RESULT

    fnum3 	- floating point number (fnum3 = fnum2/fnum1).

BUGS
    None.

SEE ALSO


mathffp.library/SPFlt

NAME
    SPFlt -- Convert integer number to fast floating point.

SYNOPSIS
    fnum = SPFlt(inum)
    D0	     D0

    float SPFlt(inet inum);

FUNCTION
    Accepts an integer and returns the converted
    floating point result of said number.

INPUTS
    inum 	- signed integer number

RESULT
    fnum 	- floating point number

BUGS
    None.

SEE ALSO


mathieeedoubbas.doc

     IEEEDPAbs()
     IEEEDPAdd()
     IEEEDPCeil()
     IEEEDPCmp()
     IEEEDPDiv()
     IEEEDPFix()
     IEEEDPFloor()
     IEEEDPFlt()
     IEEEDPMul()
     IEEEDPNeg()
     IEEEDPSub()
     IEEEDPTst()


mathieeedoubbas.library/IEEEDPAdd

   NAME
    IEEEDPAdd -- add one double precision IEEE number to another

   SYNOPSIS
      x   = IEEEDPAdd(  y  ,  z  );
    d0/d1		  d0/d1 d2/d3

    double	x,y,z;

   FUNCTION
    Compute x = y + z in IEEE double precision.

   INPUTS
    y -- IEEE double precision floating point value
    z -- IEEE double precision floating point value

   RESULT
    x -- IEEE double precision floating point value

   BUGS

   SEE ALSO
    IEEEDPSub()


mathieeedoubbas.library/IEEEDPCeil

   NAME
    IEEEDPCeil -- compute Ceil function of IEEE double precision number

   SYNOPSIS
      x   = IEEEDPCeil(  y  );
    d0/d1		   d0/d1

    double	x,y;

   FUNCTION
    Calculate the least integer greater than or equal to x and return it.
    This value may have more than 32 bits of significance.
    This identity is true.  Ceil(x) = -Floor(-x).

   INPUTS
    y -- IEEE double precision floating point value

   RESULT
    x -- IEEE double precision floating point value

   BUGS

   SEE ALSO
    IEEEDPFloor()


mathieeedoubbas.library/IEEEDPDiv

   NAME
    IEEEDPDiv -- divide one double precision IEEE by another

   SYNOPSIS
      x   = IEEEDPDiv(  y  ,  z  );
    d0/d1		  d0/d1 d2/d3

    double	x,y,z;

   FUNCTION
    Compute x = y / z in IEEE double precision.

   INPUTS
    y -- IEEE double precision floating point value
    z -- IEEE double precision floating point value

   RESULT
    x -- IEEE double precision floating point value

   BUGS

   SEE ALSO
    IEEEDPMul()


mathieeedoubbas.library/IEEEDPFix

   NAME
    IEEEDPFix -- convert IEEE double float to integer

   SYNOPSIS
    x   = IEEEDPFix(  y  );
    d0		d0/d1

    long	x;
    double	y;

   FUNCTION
    Convert IEEE double precision argument to a 32 bit signed integer
    and return result.

   INPUTS
    y -- IEEE double precision floating point value

   RESULT
    if no overflow occured then return
        x -- 32 bit signed integer
    if overflow return largest +- integer
        For round to zero

   BUGS

   SEE ALSO
    IEEEDPFlt()


mathieeedoubbas.library/IEEEDPFloor

   NAME
    IEEEDPFloor -- compute Floor function of IEEE double precision number

   SYNOPSIS
      x   = IEEEDPFloor(  y  );
    d0/d1		    d0/d1

    double	x,y;

   FUNCTION
    Calculate the largest integer less than or equal to x and return it.
    This value may have more than 32 bits of significance.

   INPUTS
    y -- IEEE double precision floating point value

   RESULT
    x -- IEEE double precision floating point value

   BUGS

   SEE ALSO
    IEEEDPCeil()


mathieeedoubbas.library/IEEEDPFlt

   NAME
    IEEEDPFlt -- convert integer to IEEE double precision number

   SYNOPSIS
      x   = IEEEDPFlt(  y  );
    d0/d1		   d0

    double	x;
    long	y;

   FUNCTION
    Convert a signed 32 bit value to a double precision IEEE value
    and return it in d0/d1. No exceptions can occur with this
    function.

   INPUTS
    y -- 32 bit integer in d0

   RESULT
    x is a 64 bit double precision IEEE value

   BUGS

   SEE ALSO
    IEEEDPFix()


mathieeedoubbas.library/IEEEDPMul

   NAME
    IEEEDPMul -- multiply one double precision IEEE number by another

   SYNOPSIS
      x   = IEEEDPMul(  y  ,  z  );
    d0/d1		  d0/d1 d2/d3

    double	x,y,z;

   FUNCTION
    Compute x = y * z in IEEE double precision.

   INPUTS
    y -- IEEE double precision floating point value
    z -- IEEE double precision floating point value

   RESULT
    x -- IEEE double precision floating point value

   BUGS

   SEE ALSO
    IEEEDPDiv()


mathieeedoubbas.library/IEEEDPSub

   NAME
    IEEEDPSub -- subtract one double precision IEEE number from another

   SYNOPSIS
      x   = IEEEDPSub(  y  ,  z  );
    d0/d1		  d0/d1 d2/d3

    double	x,y,z;

   FUNCTION
    Compute x = y - z in IEEE double precision.

   INPUTS
    y -- IEEE double precision floating point value
    z -- IEEE double precision floating point value

   RESULT
    x -- IEEE double precision floating point value

   BUGS

   SEE ALSO
    IEEEDPAdd()


mathieeedoubtrans.doc

     IEEEDPAcos()
     IEEEDPAsin()
     IEEEDPAtan()
     IEEEDPCos()
     IEEEDPCosh()
     IEEEDPExp()
     IEEEDPFieee()
     IEEEDPLog()
     IEEEDPLog10()
     IEEEDPPow()
     IEEEDPSin()
     IEEEDPSincos()
     IEEEDPSinh()
     IEEEDPSqrt()
     IEEEDPTan()
     IEEEDPTanh()
     IEEEDPTieee()


mathieeedoubtrans.library/IEEEDPSinh

   NAME
    IEEEDPSinh -- compute the hyperbolic sine of a floating point number

   SYNOPSIS
      x   = IEEEDPSinh(  y  );
    d0/d1		   d0/d1

    double	x,y;

   FUNCTION
    Compute hyperbolic sine of y in IEEE double precision

   INPUTS
    y - IEEE double precision floating point value

   RESULT
    x - IEEE double precision floating point value

   BUGS

   SEE ALSO
    IEEEDPCosh(), IEEEDPTanh()


mathieeesingbas.doc

     IEEESPAbs()
     IEEESPAdd()
     IEEESPCeil()
     IEEESPCmp()
     IEEESPDiv()
     IEEESPFix()
     IEEESPFloor()
     IEEESPFlt()
     IEEESPMul()
     IEEESPNeg()
     IEEESPSub()
     IEEESPTst()


mathieeesingbas.library/IEEESPAdd

   NAME
    IEEESPAdd -- add one single precision IEEE number to another

   SYNOPSIS
      x   = IEEESPAdd(  y  ,  z  );
     d0		   d0     d1

    float	x,y,z;

   FUNCTION
    Compute x = y + z in IEEE single precision.

   INPUTS
    y -- IEEE single precision floating point value
    z -- IEEE single precision floating point value

   RESULT
    x -- IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEESPSub()


mathieeesingbas.library/IEEESPCeil

   NAME
    IEEESPCeil -- compute Ceil function of IEEE single precision number

   SYNOPSIS
      x   = IEEESPCeil(  y  );
     d0		     d0

    float	x,y;

   FUNCTION
    Calculate the least integer greater than or equal to x and return it.
    This identity is true.  Ceil(x) = -Floor(-x).

   INPUTS
    y -- IEEE single precision floating point value

   RESULT
    x -- IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEESPFloor()


mathieeesingbas.library/IEEESPDiv

   NAME
    IEEESPDiv -- divide one single precision IEEE by another

   SYNOPSIS
      x   = IEEESPDiv(  y  ,  z  );
     d0		   d0    d1

    float	x,y,z;

   FUNCTION
    Compute x = y / z in IEEE single precision.
    Note that the Motorola fast floating point Div routine reverses
    the order of the arguments for the C interface, although the
    dividend is still in d0 and the divisor is in d1.

   INPUTS
    y -- IEEE single precision floating point value
    z -- IEEE single precision floating point value

   RESULT
    x -- IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEESPMul()


mathieeesingbas.library/IEEESPFix

   NAME
    IEEESPFix -- convert IEEE single float to integer

   SYNOPSIS
    x   = IEEESPFix(  y  );
    d0		 d0

    long	x;
    float	y;

   FUNCTION
    Convert IEEE single precision argument to a 32 bit signed integer
    and return result.

   INPUTS
    y -- IEEE single precision floating point value

   RESULT
    if no overflow occured then return
        x -- 32 bit signed integer
    if overflow return largest +- integer
        For round to zero

   BUGS

   SEE ALSO
    IEEESPFlt()


mathieeesingbas.library/IEEESPFloor

   NAME
    IEEESPFloor -- compute Floor function of IEEE single precision number

   SYNOPSIS
      x   = IEEESPFloor(  y  );
      d0		      d0

    float	x,y;

   FUNCTION
    Calculate the largest integer less than or equal to x and return it.

   INPUTS
    y -- IEEE single precision floating point value

   RESULT
    x -- IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEESPCeil()


mathieeesingbas.library/IEEESPFlt

   NAME
    IEEESPFlt -- convert integer to IEEE single precision number

   SYNOPSIS
      x   = IEEESPFlt(  y  );
     d0		   d0

    float	x;
    long	y;

   FUNCTION
    Convert a signed 32 bit value to a single precision IEEE value
    and return it in d0. No exceptions can occur with this
    function.

   INPUTS
    y -- 32 bit integer in d0

   RESULT
    x is a 32 bit single precision IEEE value

   BUGS

   SEE ALSO
    IEEESPFix()


mathieeesingbas.library/IEEESPMul

   NAME
    IEEESPMul -- multiply one double precision IEEE number by another

   SYNOPSIS
      x   = IEEESPMul(  y  ,  z  );
     d0		   d0    d1

    float	x,y,z;

   FUNCTION
    Compute x = y * z in IEEE single precision.

   INPUTS
    y -- IEEE single precision floating point value
    z -- IEEE single precision floating point value

   RESULT
    x -- IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEESPDiv()


mathieeesingbas.library/IEEESPSub

   NAME
    IEEESPSub -- subtract one single precision IEEE number from another

   SYNOPSIS
      x   = IEEESPSub(  y  ,  z  );
     d0		   d0     d1

    float	x,y,z;

   FUNCTION
    Compute x = y - z in IEEE single precision.

   INPUTS
    y -- IEEE single precision floating point value
    z -- IEEE single precision floating point value

   RESULT
    x -- IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEESPAdd()


mathieeesingtrans.doc

     IEEESPAcos()
     IEEESPAsin()
     IEEESPAtan()
     IEEESPCos()
     IEEESPCosh()
     IEEESPExp()
     IEEESPFieee()
     IEEESPLog()
     IEEESPLog10()
     IEEESPPow()
     IEEESPSin()
     IEEESPSincos()
     IEEESPSinh()
     IEEESPSqrt()
     IEEESPTan()
     IEEESPTanh()
     IEEESPTieee()


mathieeesingtrans.library/IEEESPSinh

   NAME
    IEEESPSinh -- compute the hyperbolic sine of a floating point number

   SYNOPSIS
      x   = IEEESPSinh(  y  );
    d0		   d0

    float	x,y;

   FUNCTION
    Compute hyperbolic sine of y in IEEE single precision

   INPUTS
    y - IEEE single precision floating point value

   RESULT
    x - IEEE single precision floating point value

   BUGS

   SEE ALSO
    IEEESPCosh(), IEEESPTanh()


mathtrans.doc

     SPAcos()
     SPAsin()
     SPAtan()
     SPCos()
     SPCosh()
     SPExp()
     SPFieee()
     SPLog()
     SPLog10()
     SPPow()
     SPSin()
     SPSincos()
     SPSinh()
     SPSqrt()
     SPTan()
     SPTanh()
     SPTieee()


mathtrans.library/SPAcos

NAME

    SPAcos - obtain the arccosine of the floating point number

SYNOPSIS

    fnum2 = SPAcos(fnum1);
                       d0.l
    float fnum2;
    float fnum1;

FUNCTION

    Accepts a floating point number representing the cosine
    of an angle and returns the value of said angle in
    radians

INPUTS

    fnum1 - Motorola fast floating point number

RESULT

    fnum2 - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPSin()


mathtrans.library/SPAsin

NAME

    SPAsin - obtain the arcsine of the floating point number

SYNOPSIS

    fnum2 = SPAsin(fnum1);
                       d0.l
    float fnum2;
    float fnum1;

FUNCTION

    Accepts a floating point number representing the sine
    of an angle and returns the value of said angle in
    radians

INPUTS

    fnum1 - Motorola fast floating point number

RESULT

    fnum2 - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPCos()


mathtrans.library/SPAtan

NAME

    SPAtan - obtain the arctangent of the floating point number

SYNOPSIS

    fnum2 = SPAtan(fnum1);
                       d0.l
    float fnum2;
    float fnum1;

FUNCTION

    Accepts a floating point number representing the tangent
    of an angle and returns the value of said angle in
    radians

INPUTS

    fnum1 - Motorola fast floating point number

RESULT

    fnum2 - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPTan()


mathtrans.library/SPCos

NAME

    SPCos - obtain the cosine of the floating point number

SYNOPSIS

    fnum2 = SPCos(fnum1);
                       d0.l
    float fnum2;
    float fnum1;

FUNCTION

    Accepts a floating point number representing an angle
    in radians and returns the cosine of said angle.

INPUTS

    fnum1 - Motorola fast floating point number

RESULT

    fnum2 - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPAcos()


mathtrans.library/SPCosh

NAME

    SPCosh - obtain the hyperbolic cosine of the floating point number

SYNOPSIS

    fnum2 = SPCosh(fnum1);
                       d0.l
    float fnum2;
    float fnum1;

FUNCTION

    Accepts a floating point number representing an angle
    in radians and returns the hyperbolic cosine of said angle.

INPUTS

    fnum1 - Motorola fast floating point number

RESULT

    fnum2 - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPSinh()


mathtrans.library/SPExp

NAME

    SPExp - obtain the exponential (e**X) of the floating point number

SYNOPSIS

    fnum2 = SPExp(fnum1);
                      d0.l
    float fnum2;
    float fnum1;

FUNCTION

    Accepts a floating point number and returns the value
    of e raised to the fnum1 power

INPUTS

    fnum1 - Motorola fast floating point number

RESULT

    fnum2 - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPLog()


mathtrans.library/SPFieee

NAME

    SPFieee - convert single precision ieee to FFP number

SYNOPSIS

    fnum = SPFieee(ieeenum);
                       d0.l
    float fnum;
    float ieeenum;

FUNCTION

    Accepts a standard single precision format
    returns the same number, converted to Motorola
    fast floating point number

INPUTS

    ieeenum - IEEE Single Precision Floating Point

RESULT

    fnum - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPTieee()


mathtrans.library/SPLog

NAME

    SPLog - obtain the natural logarithm of the floating point number

SYNOPSIS

    fnum2 = SPLog(fnum1);
                      d0.l
    float fnum2;
    float fnum1;

FUNCTION

    Accepts a floating point number and returns the natural
    logarithem (base e) of said number

INPUTS

    fnum1 - Motorola fast floating point number

RESULT

    fnum2 - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPExp()


mathtrans.library/SPLog10

NAME

    SPLog10 - obtain the naperian logarithm(base 10) of the
          floating point number

SYNOPSIS

    fnum2 = SPLog10(fnum1);
                        d0.l
    float fnum2;
    float fnum1;

FUNCTION

    Accepts a floating point number and returns the naperian
    logarithm (base 10) of said number

INPUTS

    fnum1 - Motorola fast floating point number

RESULT

    fnum2 - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPExp(), SpLog()


mathtrans.library/SPPow

NAME

    SPPow - raise a number to a power

SYNOPSIS

    result = SPPow(fnum1, fnum2);
                      d1.l    d0.l
    float fnum1, fnum2;
    float result;

FUNCTION

    Accepts two floating point numbers and returns the
    result of fnum2 raised to the fnum1 power

INPUTS

    fnum1 - Motorola fast floating point number
    fnum2 - Motorola fast floating point number

RESULT

    result - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPExp(), SPLog()


mathtrans.library/SPSin

NAME

    SPSin - obtain the sine of the floating point number

SYNOPSIS

    fnum2 = SPSin(fnum1);
                       d0.l
    float fnum2;
    float fnum1;

FUNCTION

    Accepts a floating point number representing an angle
    in radians and returns the sine of said angle.

INPUTS

    fnum1 - Motorola fast floating point number

RESULT

    fnum2 - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPAsin()


mathtrans.library/SPSincos

NAME

    SPSincos - obtain the sine and cosine of a number

SYNOPSIS

    fnum3 = SPSincos(pfnum2, fnum1);
                         d1.l,   d0.l
    float *pfnum2;
    float fnum1;
    float fnum3;

FUNCTION

    Accepts a floating point number (fnum1) representing
    an angle in radians and a pointer to another floating
    point number (pfnum2). It computes the cosine and places it in
    *pfnum2. It computes the sine and returns it as a result.

INPUTS

    fnum1 - Motorola fast floating point number
    pfnum2 - pointer to Motorola fast floating point number

RESULT

    *pfnum2 - Motorola fast floating point number (cosine)
    fnum3 - Motorola fast floating point number (sine)

BUGS

    None

SEE ALSO

    SPSin(), SPCos()


mathtrans.library/SPSinh

NAME

    SPSinh - obtain the hyperbolic sine of the floating point number

SYNOPSIS

    fnum2 = SPSinh(fnum1);
                       d0.l
    float fnum2;
    float fnum1;

FUNCTION

    Accepts a floating point number representing an angle
    in radians and returns the hyperbolic sine of said angle.

INPUTS

    fnum1 - Motorola fast floating point number

RESULT

    fnum2 - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPCosh()


mathtrans.library/SPSqrt

NAME

    SPSqrt - obtain the square root of the floating point number

SYNOPSIS

    fnum2 = SPSqrt(fnum1);
                      d0.l
    float fnum2;
    float fnum1;

FUNCTION

    Accepts a floating point number and returns the square toot
    of said number

INPUTS

    fnum1 - Motorola fast floating point number

RESULT

    fnum2 - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPPow(), SPMul()


mathtrans.library/SPTan

NAME

    SPTan - obtain the tangent of the floating point number

SYNOPSIS

    fnum2 = SPTan(fnum1);
                       d0.l
    float fnum2;
    float fnum1;

FUNCTION

    Accepts a floating point number representing an angle
    in radians and returns the tangent of said angle.

INPUTS

    fnum1 - Motorola fast floating point number

RESULT

    fnum2 - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPAtan()


mathtrans.library/SPTanh

NAME

    SPTanh - obtain the hyperbolic tangent of the floating point number

SYNOPSIS

    fnum2 = SPTanh(fnum1);
                       d0.l
    float fnum2;
    float fnum1;

FUNCTION

    Accepts a floating point number representing an angle
    in radians and returns the hyperbolic tangent of said angle.

INPUTS

    fnum1 - Motorola fast floating point number

RESULT

    fnum2 - Motorola fast floating point number

BUGS

    None

SEE ALSO

    SPSinh(), SPCosh()


mathtrans.library/SPTieee

NAME

    SPTieee - convert FFP number to single precision ieee

SYNOPSIS

    ieeenum = SPTieee(fnum);
                         d0.l
    float ieeenum;
    float fnum;

FUNCTION

       Accepts a Motorola fast floating point number and
       returns the same number, converted into IEEE
       standard single precision format

INPUTS

    fnum - Motorola fast floating point number

RESULT

    ieeenum - IEEE Single Precision Floating Point

BUGS

    None

SEE ALSO

    SPFieee()


narrator.doc

     AbortIO()
     OpenDevice()
     CMD_FLUSH
     CMD_READ
     CMD_RESET
     CMD_START
     CMD_STOP
     CMD_WRITE
     CloseDevice()


narrator.device/CMD_READ

   NAME
    CMD_READ - Query the narrator device for mouth shape or other
           synchronization events.

   SYNOPSIS
    Standard device command.

   FUNCTION
    Currently, there are three events which the user can inquire
    about from the narrator device.  These are: mouth shape changes,
    start of word, and start of syllable.  Each read request returns
    information about any or all of these events as determined by
    the bits set in the sync field of the read IORequest block.  In
    the case of mouth shape changes, each shape returned is guaranteed
    to be different from the previously returned shape to allow
    updating to be done only when necessary.  Each read request is
    associated with a write request	by information contained in the
    IORequest block used to open the device.  Since the first field
    in the read IORequest block is a write IORequest structure, this
    association is easily made by copying the write IORequest block
    (after the OpenDevice call) into the voice field of the read
    IORequest block.  If there is no write in progress or in the
    device input queue with the same pseudo unit number as the read
    request, the read will be returned to the user with an error.  This
    is also how the user knows that the write request has finished and
    that s/he should not issue any more reads.  Note that in this case
    the mouth shapes may not be different from previously returned values.

   INPUTS
    mouth_rb IORequest block with the voice field (a narrator_rb
    structure) copied from the associated write request with the
    following fields modified:

       io_Message - Pointer to message port for read request
       io_Command - CMD_READ
       io_Error   - Clear before issuing first read
       width      - 0
       height     - 0

   RESULTS
    As long as the speech is in progress, each read returns the
    following information in the mouth_rb IORequest block.

    If mouth shape changes are requested the following fields are
    modified:
       width  - Contains mouth width value in arbitrary units
       height - Contains mouth height value in arbitrary units
       shape  - Compressed form of mouth shapes (internal use only)

    ******	NEW FOR V37 NARRATOR

    If word synchronization is requested:
       sync   - Bit NDB_WORDSYNC is set

    If syllable synchronization is requested:
       sync   - Bit NDB_SYLSYNC is set

    Note that any or all of the above fields can be set and it is
    the user's responsibility to check for all possibilities.

   SEE ALSO
    CMD_WRITE
    Exec input/output documentation.


nonvolatile.doc

     --background--
     DeleteNV()
     FreeNVData()
     GetCopyNV()
     GetNVInfo()
     GetNVList()
     SetNVProtection()
     StoreNV()


nonvolatile.library/--background--

   PURPOSE
    The nonvolatile library provides a simple means for an application
    developer to manage nonvolatile storage.

   OVERVIEW
    The nonvolatile library is meant to be used transparently across all
    configurations. Currently, nonvolatile storage may consist of NVRAM
    and/or disk devices. nonvolatile.library will automatically
    access the best nonvolatile storage available in the system. Disk
    based storage will be selected first and if not available, NVRAM
    storage will be accessed.

    * NVRAM

    On low-end diskless Amiga platforms, NVRAM may be available. This
    RAM will maintain its data contents when the system is powered down.
    This is regardless of whether batteries or battery-backed clock are
    present. The data stored in NVRAM is accessible only through the
    ROM-based nonvolatile library funtion calls. The size of NVRAM
    storage	is dependant on the system platform and is attainable through
    the GetNVInfo() function.

    * Disk

    In keeping with the general configurability of the Amiga, the actual
    disk location used by nonvolatile library when storing to disk may be
    changed by the user.

    The prefs directory is used on the Amiga for storing many user
    configurable options. The location for nonvolatile disk storage
    is contained in the file prefs/env-archive/sys/nv_location. This
    file should contain a data string that specifies a lockable location.
    If the string does not specify a lockable location, the file will
    be ignored.

    When opened, the nonvolatile library will search all drives within
    the system until it finds this file and successfully accomplishes
    a Lock on the location specified in the file. To force a rescan of
    all drives, the library may be closed and reopened or execute the
    GetNVInfo() function.

    A simple method for creating a floppy disk for saving nonvolatile
    data is the following:

    Format a disk with the volume name NV
    Create a file prefs/env-archive/sys/nv_location on this disk with
      the following contents:  NV:nonvolatile
    Create a directory nonvolatile

    The following is a script file that can be used to make a floppy
    for use with nonvolatile library:

    .KEY DRIVE/A,DISK
    .BRA {
    .KET }
    format Drive {DRIVE} Name {DISK$NV} noicons ffs
    makedir {DRIVE}prefs
    makedir {DRIVE}nonvolatile
    makedir {DRIVE}prefs/env-archive
    makedir {DRIVE}prefs/env-archive/sys
    echo {DISK$NV}:nonvolatile >{DRIVE}prefs/env-archive/sys/nv_location

    !!!NOTE!!!

    Because NVRAM performs disk access, you must open and use its
    functionality from a DOS process, not an EXEC task.  Normally
    your CDGS application is invoked as a DOS process so this
    requirement generally should cause you no concern.  You just
    need to be aware of this requirement should you create an
    EXEC task and try to invoke nonvolatile.library from that task.


nonvolatile.library/DeleteNV

   NAME
    DeleteNV -- remove an entry from nonvoltatile storage. (V40)

   SYNOPSIS
    success = DeleteNV(appName, itemName, killRequesters);
    D0		   A0	    A1	      D1

    BOOL DeleteNV(STRPTR, STRPTR, BOOL);

   FUNCTION
    Searches the nonvolatile storage for the indicated entry and removes
    it.

    The strings appName and itemName may not contain the '/' or ':'
    characters. It is recommended that these characters be blocked
    from user input when requesting AppName and ItemName strings.

   INPUTS
    appName - NULL terminated string identifing the application that
          created the data. Maximum length is 31.
    ItemName - NULL terminated string uniquely identifing the data
           within the application. Maximum length is 31.
    killRequesters - suppress system requesters flag. TRUE if all system
             requesters are to be suppressed during this function.
             FALSE if system requesters are allowed.

   RESULT
    success - TRUE will be returned if the entry is found and deleted.
          If the entry is not found, FALSE will be returned.


nonvolatile.library/FreeNVData

   NAME
    FreeNVData -- release the memory allocated by a function of this
              library. (V40)

   SYNOPSIS
    FreeNVData(data);
           A0

    VOID FreeNVData(APTR);

   FUNCTION
    Frees a block of memory that was allocated by any of the following:
    GetCopyNV(), GetNVInfo(), GetNVList().

   INPUTS
    data - pointer to the memory block to be freed. If passed NULL,
           this function does nothing.

   SEE ALSO
    GetCopyNV(), GetNVInfo(), GetNVList()


nonvolatile.library/GetCopyNV

   NAME
    GetCopyNV -- return a copy of an item stored in nonvolatile storage.
             (V40)

   SYNOPSIS
    data = GetCopyNV(appName, itemName, killRequesters);
    D0		 A0	  A1	    D1

    APTR GetCopyNV(STRPTR, STRPTR, BOOL);

   FUNCTION
    Searches the nonvolatile storage for the indicated appName and
    itemName. A pointer to a copy of this data will be returned.

    The strings appName and itemName may not contain the '/' or ':'
    characters. It is recommended that these characters be blocked
    from user input when requesting appName and itemName strings.

   INPUTS
    appName - NULL terminated string indicating the application name
          to be found. Maximum length is 31.
    itemName - NULL terminated string indicated the item within the
           application to be found. Maximum length is 31.
    killRequesters - Suppress system requesters flag. TRUE if all system
             requesters are to be suppressed during this function.
             FALSE if system requesters are allowed.

   RESULT
    data - pointer to a copy of the data found in the nonvolatile storage
           assocated with appName and itemName. NULL will be returned
           if there is insufficient memory or the appName/itemName does
           not exist.

   SEE ALSO
    FreeNVData(), <libraries/nonvolatile.h>


nonvolatile.library/GetNVInfo

   NAME
    GetNVInfo -- report information on the current nonvolatile storage.
             (V40)

   SYNOPSIS
    information = GetNVInfo(killRequesters);
    D0			D1

    struct NVInfo *GetNVInfo(BOOL);

   FUNCTION
    Finds the user's preferred nonvolatile device and reports information
    about it.

   INPUTS
    killRequesters - suppress system requesters flag. TRUE if all system
             requesters are to be suppressed during this function.
             FALSE if system requesters are allowed.

   RESULT
    information - pointer to an NVInfo structure. This structure contains
              information on the NV storage media with the largest
              storage. The structure contains 2 longword fields:
              nvi_MaxStorage and nvi_FreeStorage. Both values are
              rounded down to the nearest ten. The nvi_MaxStorage
              field is defined as the total amount of nonvolatile
              storage available on this device. The nvi_FreeStorage is
              defined as the amount of available space for NVDISK or
              the amount of non-locked storage for NVRAM. For NVDISK,
              the nvi_FreeStorage takes into account the amount of
              overhead room required to store a new App/Item. This
              amount is 3 blocks to allow room for storing a new Item
              file and possibly a new App directory. For NVRAM, the
              amount of overhead is 5 bytes. However, the amount of
              room required to store a new NVRAM item depends on the
              length of the App and Item names. Refer to StoreNV()
              function for storage details.

              This function may return NULL in the case of failure.

   SEE ALSO
    FreeNVData(), StoreNV(), <libraries/nonvolatile.h>


nonvolatile.library/GetNVList

   NAME
    GetNVList -- return a list of the items stored in nonvolatile
             storage. (V40)

   SYNOPSIS
    list = GetNVList(appName, killRequesters);
    D0		 A0	  D1

    struct MinList *GetNVList(STRPTR, BOOL);

   FUNCTION
    Returns a pointer to an Exec list of nonvolatile Items associated
    with the appName requested.

    The string appName may not contain the '/' or ':' characters.
    It is recommended that these characters be blocked from user input
    when requesting an appName string.

   INPUTS
    appName - NULL terminated string indicating the application name
          to be matched. Maximum length is 31.
    killRequesters - Suppress system requesters flag. TRUE if all system
             requesters are to be suppressed during this function.
             FALSE if system requesters are allowed.

   RESULT
    list - a pointer to an Exec MinList of NVEntries. A NULL will be
           returned if there is insufficient memory. If there are no
           entries in the nonvolatile storage for the AppName, an
           empty list will be returned.

   NOTE
    The protection field contains more bits than are required for
    storing the delete protection status. These bits are reserved
    for other system usage and may not be zero. When checking for
    the delete status use either the field mask NVIF_DELETE, or the
    bit definition NVIB_DELETE.

   SEE ALSO
    FreeNVData(), SetNVProtection()


nonvolatile.library/SetNVProtection

   NAME
    SetNVProtection -- set the protection flags. (V40)

   SYNOPSIS
    success = SetNVProtection(appName, itemName, mask, killRequesters);
    D0			  A0	   A1	     D2    D1

    BOOL SetNVProtection(STRPTR, STRPTR, LONG, BOOL);

   FUNCTION
    Sets the protection attributes for an item currently in the
    nonvolatile storage.

    Although 'mask' is LONG only the delete bit, NVEF_DELETE/NVEB_DELETE,
    may be set. If any other bits are set this function will return
    FALSE.

    The strings appName and itemName may not contain the '/' or ':'
    characters. It is recommended that these characters be blocked
    from user input when requesting AppName and ItemName strings.

   INPUTS
    appName - NULL terminated string indicating the application name
          to be matched. Maximum length is 31.
    itemName - NULL terminated string indicated the item within the
           application to be found. Maximum length is 31.
    mask - the new protection mask. Only set the delete bit otherwise
           this function WILL CRASH.
    killRequesters - suppress system requesters flag. TRUE if all system
             requesters are to be suppressed during this function.
             FALSE if system requesters are allowed.

   RESULT
    success - FALSE if the protection could not be change (ie the data
          does not exist).

   SEE ALSO
    GetNVList(), <libraries/nonvolatile.h>


nonvolatile.library/StoreNV

   NAME
    StoreNV -- store data in nonvolatile storage. (V40)

   SYNOPSIS
    error = StoreNV(appName, itemName, data, length, killRequesters);
    D0		A0	 A1	   A2    D0	 D1

    UWORD StoreNV(STRPTR, STRPTR, APTR, ULONG, BOOL);

   FUNCTION
    Saves some data in nonvolatile storage. The data is tagged with
    AppName and ItemName so it can be retrieved later. No single
    item should be larger than one fourth of the maximum storage as
    returned by GetNVInfo().

    There is no data compression associated with this function.

    The strings, AppName and ItemName, should be short, but descriptive.
    They need to be short since the string is stored with the data and
    the nonvolatile storage for a stand alone game system is limited.
    The game system allows the user to selectively remove entries from
    storage, so the string should be desriptive.

    The strings AppName and ItemName may not contain the '/' or ':'
    characters. It is recommended that these characters be blocked
    from user input when requesting AppName and ItemName strings.

   INPUTS
    appName - NULL terminated string identifying the application
          creating the data. Maximum length is 31.
    itemName - NULL terminated string uniquely identifying the data
           within the application. Maximum length is 31.
    data - pointer to the memory block to be stored.
    length - number of bytes to be stored in the units of tens of
         bytes. For example, if you have 23 bytes to store length = 3;
         147 byte then length = 15.
    killRequesters - suppress system requesters flag. TRUE if all system
             requesters are to be suppressed during this function.
             FALSE if system requesters are allowed.

   RESULT
    error - 0                means no error,
            NVERR_BADNAME    error in AppName, or ItemName.
            NVERR_WRITEPROT  Nonvolatile storage is read only.
            NVERR_FAIL       Failure in writing data (nonvolatile storage
                 full, or write protected).
            NVERR_FATAL      Fatal error when accessing nonvolatile
                 storage, possible loss of previously saved
                 nonvolatile data.

   SEE ALSO
    GetCopyNV(), GetNVInfo()


page_gc.doc

     --datasheet--
     PAGE_GetClass()
     RefreshPageGadget()
     SetPageGadgetAttrsA()


page_gc/--datasheet--

  NAME
      page.gadget -- a gadget for easy creation of GUI pages.

  SUPERCLASS
      gadgetclass

  DESCRIPTION
      Page gadget takes a list of BOOPSI objects and treats each as a
      single page of a multi-page GUI group. Used together with
      tabs.gadget and layout.gadget, it allows complex GUI layouts with
      hidden objects with virtually no work for the developer.

      This gadget class is contained within the layout.gadget binary.
      Thus, you will need to OpenLibrary layout.gadget, but not
      page.gadget.

  METHODS
      GM_DOMAIN
      GM_RENDER
      GM_LAYOUT
      DTM_PROCLAYOUT
      OM_SET
      OM_UPDATE
      OM_NEW
      OM_DISPOSE

      All other methods are passed to the currently visible object.

  ATTRIBUTES
      PAGE_Add (Object *)
          A BOOPSI gadget (probably a layout.gadget) to add to the end of
          the page list.

          Applicability is (OM_NET, OM_SET)

      PAGE_Remove (Object *)
          Pointer to a gadget to remove from the page list. page.gadget
          will automatically dispose all attached objects when disposed of.

          Applicability is (OM_SET)

      PAGE_Current (ULONG)
          Sets/gets the currently visible page. Note that OM_SET will NOT
          trigger a rerender, call RethinkLayout() afterwards. OM_UPDATE
          will rerender automatically.

          Applicability is (OM_NEW, OM_SET, OM_UPDATE)

      PAGE_FixedVert, PAGE_FixedHoriz (BOOL)
          Like the respective tags of layout.gadget, these will, if set
          to FALSE, force the group's dimensions to the smallest possible
          in the respective direction.

          Applicability is (OM_NEW, OM_SET, OM_UPDATE)

  SEE ALSO
            layout.gadget/--datasheet--
      ReAction example source for usage.


page_gc/PAGE_GetClass

  NAME
      PAGE_GetClass -- Gets the pointer to the Page class.

  SYNOPSIS
      page_class = PAGE_GetClass();
      D0

      Class * PAGE_GetClass(VOID);

  FUNCTION
      Obtains the pointer to the page gadget class for use with
      NewObject().  This function always returns a valid pointer so
      you do not need to check it.  The reason is that if the library
      opens fine, then the pointer returned is already setup.  (Of course
      this implies that if opening the library fails, you shouldn't be
      calling this.)

      Note that this function does not create the class, that is done
      when the class library is opened.

  INPUTS
      Nothing.

  NOTES
      PAGE_GetClass() is contained in layout.gadget. There is no PageBase,
      just LayoutBase.

  RESULT
      page_class - Pointer to the page gadget class.


page_gc/RefreshPageGadget

   NAME
       RefreshPageGadget -- Refresh gadget in a paged layout

   SYNOPSIS
       RefreshPageGadget(gad, page, win, req)
                         A0     A1       A2   A3

       void RefreshPageGadget(struct Gadget *, Object *,
               struct Window *, struct Requester *)

   FUNCTION
       Like RefreshGList(gad,win,req,1), but passes a NULL window and
       requester pointer if the gadget is not on the currently visible
       page.


page_gc/SetPageGadgetAttrsA

   NAME
       SetPageGadgetAttrsA -- Set gadget attributes in a paged layout
       SetPageGadgetAttrs -- Varargs stub for SetPageGadgetAttrsA

   SYNOPSIS
       value = SetPageGadgetAttrsA(gad, page, win, req, tags)
       D0                            A0     A1       A2   A3   A4

       ULONG SetPageGadgetAttrsA(struct Gadget *, Object *,
               struct Window *, struct Requester *, struct TagItem *)

       ULONG SetPageGadgetAttrs(struct Gadget *, Object *,
               struct Window *, struct Requester *, ULONG, ...)

   FUNCTION
       Like SetGadgetAttrs, but passes a NULL window and requester pointer
       if the gadget is not on the currently visible page.


palette_gc.doc

     --datasheet--
     --styleguide--
     PALETTE_GetClass()


palette_gc/--datasheet--

     NAME
        palette_gc -- A colour selection gadget.

     SUPERCLASS
        gadgetclass

     REQUIRES
        bevel.image

     DESCRIPTION
        This gadget is equivalent to the GadTools PALETTE_KIND gadget, but
        implemented as a BOOPSI gadget class.  It displays a palette of
        colours, allowing the user to select one.

        Advantages that this class provides:

         > Right mouse button cancels gadget action.

         > Supports window relativity.

         > Supports gadget interconnections.

         > Supports OS 3.0 BOOPSI Gadget HelpTest.

     METHODS
        OM_NEW -- Create the palette gadget, calls OM_SET.  Passed to
            superclass.

        OM_SET -- Set object attributes.  Passed to superclass first.

        OM_GET -- Get object attributes.  Passed to superclass first.

        OM_NOTIFY -- Notify connections of attribute changes.

        OM_DISPOSE -- Frees resources and calls superclass.

        OM_UPDATE -- Calls OM_SET.

        GM_DOMAIN -- Return the maximum and minimum size of the gadget.

        GM_RENDER -- Renders the gadget imagry.  Overrides the superclass.

        GM_KEYACTIVE -- Handles keyboard activation.

        GM_KEYINACTIVE -- Handles keyboard de-activation.

        GM_GOACTIVE -- Activate the gadget on mouse click only.  Overrides
            the superclass.

        GM_HANDLEINPUT -- Handles input events once active.  Overrides the
            superclass.

        GM_GOINACTIVE -- Deactivates the gadget.  Passed to the superclass.

        All other methods are passed to the superclass.

     ATTRIBUTES
        GA_Disabled (BOOL)
            Set to TRUE to disable gadget, FALSE otherwise

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        PALETTE_Colour (UBYTE)
            Initially selected color of the palette. This number is a pen
            number, and not the ordinal color number within the palette
            gadget itself.  The exception is when PALETTE_ColourTable is
            used, in which case you will get an index into your table.

            Defaults to 0.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        PALETTE_ColourOffset (UBYTE)
            First color to use in screen palette.

            Defaults to 0.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        PALETTE_ColourTable (UBYTE *)
            Pointer to a table of pen numbers indicating  which colors
            should be used and edited by the palette gadget. This array
            must contain as many entries as there are colors displayed in
            the palette gadget PLUS the colour offset.  The array provided
            with this tag must remain valid for the life of the gadget or
            until a new table is provided.

            Default is NULL, which causes a 1-to-1 mapping of pen numbers.

            Applicability is (OM_NEW, OM_SET, OM_GET)

        PALETTE_NumColours (UWORD)
            Number of colors to display in the palette gadget.  Currently
            this MUST be a power of

            Defaults to 2.

            Applicability is (OM_NEW, OM_SET, OM_GET)


palette_gc/--styleguide--

    PALETTE STYLE
        The usability of a palette gadget decreases as the number of
        colours it is displaying increases.  If there is a possibility
        that your palette gadget may be displaying a large number of
        colours (say, greater than 16), you should provide a means to
        simplify the colour selection.  Two possibilities would be to
        divide your colour palette into banks, and have users switch
        banks via a chooser gadget for example.  Another possibility
        would be to attach a scroller gadget to allow the user to
        scroll through the available colours, displaying just a
        subset of them on screen at a time.  You may also want to sort
        your colours in some logical manner and use PALETTE_ColourTable.


palette_gc/PALETTE_GetClass

    NAME
        PALETTE_GetClass -- Gets the pointer to the palette class.

    SYNOPSIS
        palette_class = PALETTE_GetClass();
        D0

        Class * PALETTE_GetClass(VOID);

    FUNCTION
        Obtains the pointer to the Palette gadget class for use with
        NewObject().  This function always returns a valid pointer so
        you do not need to check it.  The reason is that if the library
        opens fine, then the pointer returned is already setup.  (Of course
        this implies that if opening the library fails, you shouldn't be
        calling this.)

        Note that this function does not create the class, that is done
        when the class library is opened.

    INPUTS
        Nothing.

    RESULT
        palette_class - Pointer to the Palette gadget class.

    SEE ALSO


parallel.doc

     CMD_CLEAR
     CMD_FLUSH
     CMD_READ
     CMD_RESET
     CMD_START
     CMD_STOP
     CMD_WRITE
     OpenDevice()
     PDCMD_QUERY
     PDCMD_SETPARAMS


parallel.device/OpenDevice

   NAME
    Open -- a request to open the parallel port

   SYNOPSIS
    error = OpenDevice("parallel.device", unit, ioExtPar, flags)
    D0                  A0                D0    A1        D1

   FUNCTION
    This function allows the requestor software access to the parallel
    device.  Unless the shared-access bit (bit 5 of io_ParFlags) is
    set, exclusive use is granted and no other access is allowed
    until the owner closes the device.

    A FAST_MODE, can be specified (bit 3 of io_Parflags) to speed up
    transfers to high-speed printers. Rather than waiting for the printer
    to acknowledge a character using the *ACK interrupt, this mode will
    send out data as long as the BUSY signal is low. The printer must be
    able to raise the BUSY signal within 3 micro-seconds on A2630s,
    otherwise data will be lost. Should be used only in an exclusive-
    access Open().

    A SLOWMODE mode can be specified (bit 4 of io_ParFlags) when very
    slow printers are used. If the printer acknowledges data at less
    than 5000 bytes per second, then this mode will actually save CPU
    time, although it consumes much more with high-speed printers.

    The PTermArray of the ioExtPar is initialized only if the EOFMODE
    bit (bit 1 of io_ParFlags) is set. The PTermArray can be further
    modified using the PDCMD_SETPARAMS command.

   INPUTS
    "parallel.device" - a pointer to literal string "parallel.device"
    unit - Must be zero for future compatibility
    ioExtPar - pointer to an IO Request block of structure IOExtPar to
           be initialized by the Open() function. The io_ParFlags
           field must be set as desired.
    flags - Must be zero for future compatibility

   RESULTS
    d0 -- same as io_Error
    io_Error -- if the Open succeded, then io_Error will be null.
            If the Open failed, then io_Error will be non-zero.

   SEE ALSO
    exec/CloseDevice()


penmap_ic.doc

     --datasheet--
     PENMAP_GetClass()


penmap_ic/--datasheet--

    NAME
        penmap_ic -- create penmap BOOPSI objects

    SUPERCLASS
        imageclass

    REQUIRES
        None.

    DESCRIPTION
        This class will yield color remapped images on any public screen.
        It also supports bitmap scaling. If used with V39 or or greater
        of AmigaOS it can take advantage of pen sharing.

    METHODS
        OM_NEW -- Create the penmap image.  Passed to superclass,
            then OM_SET.

        OM_GET -- Get object attributes.  Passed to superclass first.

        OM_SET -- Set object attributes.  Passed to superclass first.

        OM_UPDATE -- Set object notification attributes.  Passed to
            superclass first.

        IM_DRAW -- Renders the image. Supports IDS_NORMAL and
            IDS_SELECTED drawing states, and does not require
            a DrawInfo structure. The graphics.library function
            BitMapScale () to scale the image if required.

        IM_DRAWFRAME -- Renders the image scaled to the frame size
            specified. Supports IDS_NORMAL and IDS_SELECTED drawing
            states, and does not require a DrawInfo structure.
            The graphics.library function BitMapScale () to scale
            the image.

        IM_HITFRAME -- Asks the object if a point would be inside it
            if the object was confined (scaled) to the given
            rectangular bounds. Returns TRUE if the given point would
            be inside the object, otherwise FALSE.

        IM_ERASEFRAME -- Erase the object using the rectangular
            frame size.

        All other methods are passed to the superclass, including OM_DISPOSE.

    ATTRIBUTES

        IA_Left (WORD)
        IA_Top (WORD)
            Set starting position/offset of image.
            Defaults to 0.

           (Applicability is OM_NEW, OM_SET, OM_GET)

        IA_Width (WORD)
        IA_Height (WORD)
            Set size of the image, scaling via BitMapScale() if different
            from the chunky image data size.

            Defaults to width and height of IA_Data.

           (Applicability is OM_NEW, OM_SET, OM_GET)

        IA_BGPen
            Specify background pen of a normal image.

            Defaults to BACKGROUNDPEN of the screen passed in PENMAP_Screen.

           (Applicability is OM_NEW, OM_SET, OM_GET)

        IA_Pens
            Sets the pens which the values in the data array represents.

           (Applicability is OM_NEW, OM_GET)

        IA_Data
           Chunky format image data for normal render.

           The data format is a UBYTE array of chunky pen numbers.
           Note this data must be WORD aligned, as the first 4 bytes
           are accessed as two WORDs which specify the width and
           height of the following chunky image data.

           Defaults to NULL.

           (Applicability is OM_NEW, OM_SET)

        PENMAP_SelectedData
           Chunky format image data for selected image render.

           (Applicability is OM_NEW, OM_SET)

        PENMAP_Palette
           An array of ULONG describing the palette for the picture.
           If you are obtaining pens yourself, you should only pass the
           IA_Pens attribute at object creation time.

           The format of the array is:

           ULONG palette[] =
           {
               number_triplets,
               red1, green1, blue1,
               red2, green2, blue2,
               ...
           };

           (Applicability is OM_NEW, OM_GET)

        PENMAP_Screen (struct Screen *)
            Pointer to the screen to use image on. This attribute MUST
            be provided when creating an object of this class.

           Defaults to NULL.

           (Applicability is OM_NEW, OM_GET)

        PENMAP_Transparent (BOOL)
           Remaps chunky pen 0 to the BACKGROUNDPEN.

           Defaults to FALSE.

           (Applicability is OM_NEW, OM_SET)

        PENMAP_Precision
            Set the precision for ObtainBestPen() when penmap is used
            under AmigaOS 3.0 or later. See the ObtainBestPen autodoc
            for more details.

            Defaults to PRECISION_IMAGE.

            Applicability is (OM_NEW, OM_SET)

        PENMAP_ColorMap (struct ColorMap *)
            Pointer to a colormap to use in obtaining best matching pens.
            This tag or, PENMAP_Screen must be provided when creating an
            object of this class. If PENMAP_Screen is passed, penmap will
            use Screen->ViewPort.ColorMap.

           Defaults to NULL.

           (Applicability is OM_NEW, OM_GET)

        PENMAP_MaskBlit (BOOL)
           Causes penmap to render on screen using a mask plane. This
           mask plane is created dynamically by the class.

           The mask is created by OR'ing the source bitplanes in to a single
           mask plane using some nifty blitting techniques. This tag should
           be used if penmap objects are used in a layout group that may
           contain a user or program specified backfill. This will allow the
           backfill pattern to flow around the image, making it transparent.

           Defaults to FALSE.

           (Applicability is OM_NEW, OM_SET)


penmap_ic/PENMAP_GetClass

    NAME
        PENMAP_GetClass -- Gets the pointer to the penmap class.

    SYNOPSIS
        penmap_class = PENMAP_GetClass();
        D0

        Class * PENMAP_GetClass(VOID);

    FUNCTION
        Obtains the pointer to the PenMap image class for use with
        NewObject().  This function always returns a valid pointer so
        you do not need to check it.  The reason is that if the library
        opens fine, then the pointer returned is already setup.  (Of course
        this implies that if opening the library fails, you shouldn't be
        calling this.)

        Note that this function does not create the class, that is done
        when the class library is opened.

    INPUTS
        Nothing.

    RESULT
        penmap_class - Pointer to the PenMap image class.

    SEE ALSO


picture_dtc.doc

     picture.datatype()


picture.datatype/picture.datatype

   NAME
    picture.datatype -- the root data type for pictures.

   FUNCTION
    The picture.datatype is the super-class for any picture related
    classes.

   METHODS
    OM_NEW -- Create a new picture object.

    OM_GET -- Obtain the value of an attribute.

    OM_SET -- Set the values of multiple attributes.

    OM_UPDATE -- Update the values of multiple attributes.

    OM_DISPOSE -- Dispose of a picture object.

    GM_LAYOUT -- Layout the object and notify the application of the
        title and size.

    GM_HITTEST -- Determine if the object has been hit with the
        mouse.

    GM_GOACTIVE -- Tell the object to go active.

    GM_HANDLEINPUT -- Handle input.

    GM_RENDER -- Cause the graphic to render.

    DTM_PROCLAYOUT -- Layout (remap) the picture on the application's
        process.

    DTM_FRAMEBOX -- Obtain the display environment that the picture
        requires.

    DTM_SELECT -- Select an area in the picture.

    DTM_CLEARSELECTED -- Deselect the selected area of the picture.

    DTM_COPY -- Copy the selected area of the picture to the clipboard
        as an ILBM.  If no area is selected, then the entire picture
        is copied.

    DTM_PRINT -- Print the selected area of the picture.  If no area
        is selected, then the entire picture is printed.

    DTM_WRITE -- Write the selected area of the picture to a file as an
        ILBM.  If no area is selected, then the entire picture is
        saved.

    PDTM_WRITEPIXELARRAY -- Transfer pixel data to the picture
        object. Requires that PDTA_SourceMode==PMODE_V43, as
        described below. (V43)

    PDTM_READPIXELARRAY -- Transfer pixel data from the picture
        object. Requires that PDTA_DestMode==PMODE_V43, as
        described below. (V43)

   TAGS
    OBP_Precision (ULONG) -- Precision to use when obtaining colors.
        See the PRECISION_[..] defines in <graphics/view.h>.
        Applicability is (I). Defaults to PRECISION_IMAGE.

    PDTA_ModeID (ULONG) -- Set and get the graphic mode id of the
        picture (see <graphics/modeid.h>).

        Applicability is (ISG).

    PDTA_BitMapHeader (struct BitMapHeader *) -- Get the
        base information for the picture.  BitMapHeader is defined in
        <datatypes/pictureclass.h>

        Applicability is (G).

    PDTA_BitMap (struct BitMap *) -- Pointer to a class-allocated
        bitmap, that will end up being freed by the picture class in the
        OM_DISPOSE method.

        Applicability is (ISG).

    PDTA_ColorRegisters (struct ColorRegister *) -- Color table; its
        contents should match the colours in the PDTA_CRegs table.

        Applicability is (G).

    PDTA_CRegs (ULONG *) -- Color table to use with SetRGB32CM().

        Applicability is (G).

    PDTA_GRegs (ULONG *) -- Color table; this table is initialized
        during the layout process and will contain the colours the
        picture will use after remapping. If no remapping takes
        place, these colours will match those in the PDTA_CRegs table.

        Applicability is (G).

    PDTA_ColorTable (UBYTE *) -- Shared pen table; this table is
        initialized during the layout process while the picture
        is being remapped.

        Applicability is (G).

    PDTA_ColorTable2 (UBYTE *) -- Shared pen table; in most places
        this table will be identical to the PDTA_ColorTable table.
        Some of the colours in this table might match the original
        colour palette a little better than the colours picked for
        the other table. The picture.datatype uses the two tables
        during remapping, alternating for each pixel.

        Applicability is (G).

    PDTA_Allocated (ULONG) -- OBSOLETE; DO NOT USE

    PDTA_NumColors (UWORD) -- Number of colors used by the picture.

        Applicability is (ISG).

    PDTA_NumAlloc (UWORD) -- Number of colors allocated by the picture.
        In this context `allocated' refers to colours allocated via
        graphics.library/ObtainBestPenA.
        Applicability is (G).

    PDTA_Remap (BOOL) -- Indicate whether the picture should be
        remapped or not.

        Applicability is (I). Defaults to TRUE.

    PDTA_Screen (struct Screen *) -- Pointer to the screen to remap
        the picture to.  Only used if the object is not going to be
        added to a window.

        Applicability is (IS). Defaults to NULL.

    PDTA_FreeSourceBitMap (BOOL) -- Indicate whether the source
        bitmap should be freed immediately by the picture.datatype
        after the GM_LAYOUT method is called.

        Applicability is (IS). Defaults to FALSE.

    PDTA_Grab (Point *) -- Pointer to a Point structure, that
        defines the grab point of the picture.

        Applicability is (ISG).

    PDTA_DestBitMap (struct BitMap *) -- Pointer to the remapped
        bitmap.

        Applicability is (G).

    PDTA_ClassBitMap (struct BitMap *) -- Pointer to the BitMap
        allocated by the subclass (e.g. ilbm.datatype) which read
        the picture. picture.datatype will never free this bitmap,
        the subclass is responsible for doing this.

        Applicability is (ISG).

    PDTA_NumSparse (UWORD) -- Number of entries in the sparse color
        table.

        Applicability is (I). Defaults to 0.

    PDTA_SparseTable (UBYTE *) -- Pointer to a table of pen numbers
        indicating which colors should be used when remapping the
        picture.  This array must contain as many entries as indicated
        by the PDTA_NumSparse tag.

        Applicability is (I). Defaults to NULL.

    PDTA_SourceMode (LONG) -- Used by subclass implementors only; this
        tag determines whether the picture.datatype expects a bitmap
        as the input parameter (PMODE_V42) or accepts PDTM_WRITEPIXELARRAY
        messages instead (PMODE_V43).

        Applicability is (ISG). Defaults to PMODE_V42. (V43)

    PDTA_DestMode (LONG) -- Used by application software writers only;
        this tag determines whether the picture.datatype will return
        only standard format BitMaps (PMODE_V42) or whether it will
        return BitMaps about whose memory layout the caller should
        not speculate (PMODE_V43). If set to PMODE_V43, you must not
        examine the contents of the BitMap you receive from
        picture.datatype.

        Applicability is (ISG). Defaults to PMODE_V43. (V43)

    PDTA_UseFriendBitMap (BOOL) -- If set to TRUE, all BitMap
        allocations done by picture.datatype will be done with
        a friend BitMap as a reference (see graphics.library/AllocBitMap).

        Applicability is (ISG). Defaults to TRUE. (V43)

    PDTA_MaskPlane (PLANEPTR) -- Pointer to a bit plane suitable
        for use with BltMaskBitMapRastPort(), or NULL if the
        picture has no transparent colours.

        Applicability is (G). Defaults to NULL. (V43)

    PDTA_WhichPicture (ULONG) -- Index number of the picture to load.
        For several pictures to be stored in the same file, index
        number 0 would refer to the first picture, index number 1 would
        refer to the second picture, etc. This tag works together with
        the PDTA_GetNumPictures tag. To load a specific picture from
        a file, first check how many pictures there are. This is done
        by asking the picture.datatype subclass to load the first
        picture and also to count the number of pictures, like this:

            Object * picture;
            ULONG numPictures;

            /* Note: you must always initialize this value
             *       prior to querying the number of pictures
             *       stored in a file.
             */
            numPictures = PDTANUMPICTURES_Unknown;
            picture = NewDTObject(...,
                          PDTA_WhichPicture,0,
                          PDTA_GetNumPictures,&numPictures,
                          ...
                      TAG_DONE);

            /* Now check if there is more than a single picture
             * in this file.
             */
            if(numPictures != PDTANUMPICTURES_Unknown &&
               numPictures > 1)
            {
                Object * secondPicture;

                picture = NewDTObject(...,
                              PDTA_WhichPicture,1,
                              ...
                          TAG_DONE);

                ...
            }

        Older picture.datatype subclasses may not support the
        PDTA_WhichPicture and PDTA_GetNumPictures tags. The only way
        to find out is by using the query tag PDTA_GetNumPictures.
        If the subclass supports both the PDTA_GetNumPictures and
        PDTA_WhichPicture tags, it will modify the value stored in
        the variable passed with PDTA_GetNumPictures.

        If the requested picture is unavailable (e.g. you might ask
        for picture #10, whereas there are only three pictures in a
        file) the subclass will return NULL and set the error
        code DTERROR_NOT_AVAILABLE. This does not signify that the file
        in question was not found, it just tells you that the picture
        with the requested index number is not available.

        Note that for older picture.datatype subclasses, the
        PDTA_WhichPicture tag will be ignored. No matter which value
        you supply, you will always receive the first picture stored
        in the file.

        Applicability is (I). Defaults to 0. (V44)

    PDTA_GetNumPictures (ULONG *) -- Query the number of pictures
        stored in a file. For an example of its use, see the description
        for the PDTA_WhichPicture tag.

        Note that older picture.datatype subclasses will ignore this
        tag. Consequently, the variable you pass in may not be modified.
        Therefore you should initialize it to the constant value
        PDTANUMPICTURES_Unknown before you pass it to NewDTObject().

        This tag is unusual in that it does not operate on an already
        existing object in the GetDTAttrs() context. This was done for
        practical reasons, i.e. while the picture.datatype subclass is
        still processing the image data it may be much more convenient
        to count the number of pictures in a file than it would be later
        when the file has already been read.

        Applicability is (I). Defaults to NULL. (V44)

    PDTA_MaxDitherPens (ULONG) -- Maximum number of pens to use during
        colour quantization.

        Applicability is (ISG). Defaults to 125. (V44)

    PDTA_DitherQuality (ULONG) -- Quality of the dithering algorithm to
        be used during colour quantization. A value of 0 yields no or
        only little picture quality improvement while a value of 2 will
        yield noticeably better picture quality. Generally, the higher
        the quality you demand, the better the output will look like.

        Applicability is (ISG). Defaults to 1. (V44)

    PDTA_AllocatedPens (UBYTE *) -- Get the pointer to the table of
        allocated pens. Each entry stands for the pen assigned to the
        colour of the corresponding palette entry. Please note that
        you may receive NULL as a return value instead of a pointer
        and that the table may not hold any valid information unless
        the value returned with the PDTA_NumAlloc tag is greater
        than zero.

        Applicability is (G). (V44)

   NOTES
    The PDTA_Allocated tag should not be used since it was never
    implemented in any way the documentation suggested.

    picture.datatype V44 no longer suffers from the layout restrictions
    present in older picture.datatype revisions. This means for example,
    that for an extra-halfbrite picture you need no longer open a
    custom screen to display it. Any screen will do. The same holds
    true for hold-and-modify pictures.

    Writing greyscale data to a picture (via the PBPAFMT_GREY8 pixel
    format and the PDTM_WRITEPIXELARRAY method) automatically
    configures the picture colour palette when the first line is
    written. The palette is reset to 256 shades of grey with 0 = black
    and 255 = white. If you do not want this to happen, do not use the
    PBPAFMT_GREY8 pixel format: use PBPAFMT_LUT8 instead. This will
    give you complete control over the picture's colour palette.


port-handler.doc

     port_handler()


port-handler/port_handler

   NAME
    port_handler -- standard serial/parallel/printer port handler.

   SYNOPSIS
    Open("PRT:[RAW/TRANSPARENT/UNIT=<Unit number>]",...);

    Open("SER:[BAUD=<speed>/CONTROL=<settings>/UNIT=<Unit number>]",...);

    Open("PAR:[UNIT=<Unit number>]",...);

   FUNCTION
    Port-handler allows AmigaDOS to interface to a standard parallel
    device, a standard printer device, and a standard serial device.

    Accessing "PAR:" connects AmigaDOS to the system's parallel port.
    By default this will use parallel.device, unit 0. To use a
    different unit number, such as 1, specify "PAR:UNIT=1" instead.

    Accessing "PRT:" connects AmigaDOS to the system's printer. Data
    written to PRT: is processed by the Amiga's printer device, handling
    conversions of ANSI sequences, and sent to the printer. Accessing
    "PRT:RAW" instead causes carriage return translation to be turned
    off in the printer device while printing. To send data transparently
    to the printer, without any translation or escape sequence substitution
    whatsoever, use "PRT:TRANSPARENT". The TRANSPARENT and RAW switches
    are mutually exclusive. By default "PRT:" will access printer.device,
    unit 0. To use a different unit number, such as 1, specify "PRT:UNIT=1"
    instead. The keywords can be combined, such as in "PRT:RAW/UNIT=1".

    Accessing "SER:" connects AmigaDOS to the system's default serial port.
    Following SER:, the baud rate and some control information can be
    supplied. This is done in the form "SER:baud/control" where baud is
    a number indicating the baud rate, and where control is a 3 letter
    sequence denoting the number of read/write bits, the parity, and the
    number of stop bits. For example, "SER:9600/8N1" connects to the
    serial port, sets the baud rate to 9600, with 8 bit data, no parity,
    and 1 stop bit. The possible control settings are:

            1st character: 7 or 8
            2nd character: N (No parity), O (Odd parity), E (Even parity)
                           M (Mark parity), S (Space parity)
            3rd character: 1 or 2

    Specifying no baud rate or control values when accessing SER: gives you
    the values set in Serial preferences.
    To override the default unit number, use the UNIT keyword, as with the
    PRT: and PAR: devices described above. For example, to access unit 1
    with 38400 bps you could use "SER:38400/UNIT=1".

   PACKETS
    ACTION_FINDINPUT
    ACTION_FINDOUTPUT
    ACTION_FINDUPDATE
    ACTION_READ
    ACTION_WRITE
    ACTION_END
    ACTION_IS_FILESYSTEM

   MOUNTLIST ENTRIES
    dos.library automatically mounts PAR:, PRT:, and SER: upon
    system boot up. The mount entries used by dos.library are equivalent
    to:

       SER:    Handler   = L:Port-Handler
               Priority  = 5
               StackSize = 800
               GlobVec   = 1
               Startup   = 0
       #

       PAR:    Handler   = L:Port-Handler
               Priority  = 5
               StackSize = 800
               GlobVec   = 1
               Startup   = 1
       #

       PRT:    Handler   = L:Port-Handler
               Priority  = 5
               StackSize = 1000
               GlobVec   = 1
               Startup   = 2
       #

    Starting with V40, you can also provide disk-based mount entries
    which let you use port-handler as a serial handler on various devices
    and units. The form of these mount entries is:

       SER0:   EHandler  = L:Port-Handler
               Priority  = 5
               StackSize = 800
               GlobVec   = 1
               Device    = serial.device
               Unit      = 0
               Flags     = 0
               Control   = "8N1"
               Baud      = 9600
    #

    The "Device", "Unit" and "Flags" keywords define the parameters
    that the handler uses for OpenDevice(). "Baud" and "Control"
    define the default values for baud rate and control information for
    whenever that serial handler is accessed by name only, without
    explicit baud rate and control information specified.

   NOTE
    Prior to V40, the baud rate and control information for SER: were
    only recognized if an A2232 multi-serial card was installed in the
    system. Starting with V40, these values are always recognized.

    The TRANSPARENT, UNIT, BAUD and CONTROL keywords were introduced
    with Port-Handler V44. For the different devices, the argument
    templates are:

        PRT:RAW/S,TRANSPARENT/S,UNIT/K/N
        SER:BAUD/N,UNIT/K/N,CONTROL/F
        PAR:UNIT/K/N

    Instead of blank spaces, keywords must be separated by slashes ("/").


printer.doc

     --background--
     CallErrHook()
     CMD_FLUSH
     CMD_INVALID
     CMD_RESET
     CMD_START
     CMD_STOP
     CMD_WRITE
     PBothReady()
     PRD_DUMPRPORT
     PRD_DUMPRPORTTAGS
     PRD_EDITPREFS
     PRD_PRTCOMMAND
     PRD_QUERY
     PRD_RAWWRITE
     PRD_READPREFS
     PRD_SETERRHOOK
     PRD_WRITEPREFS
     PQuery()
     PRead()
     PWrite()


printer.device/--background--

The printer.device gots a lot of new features with V44:

    - It is now possible to print hi- and true-color bitmaps
    - Planar bitmaps are read faster
    - Much more stable if wrong parameters for PRD_DUMPRPORT are used
    - A lot of new features for printer drivers are supported.

    Creating a driver for printer.device now gets much easier: the driver
    does not have to scale the bitmap anymore and can use its own
    algorithms for nearly everything (color conversion, color correction,
    all dither methods, anti aliasing). The driver is now run in a
    DOS process instead of a exec task so loading preferences or saving
    the output to a file is not longer a multithreading task.

    The driver gives more information for the preferences user interface
    (names of dither algorithms, names of shading algorithms, information
    about density interpretation) and for the printing itself (left and
    top border on paper, more page formats).

    Drivers can have its own preferences which can be edited and
    stored from every application. Driver can also have its own
    preferences editor (like PrinterPS).


printer.device/CallErrHook

   NAME
    CallErrHook -- internal call of error hook

   SYNOPSIS
    result = (*PrinterData->pd_CallErrHook)(hook, iorequest, msg);
    D0

    LONG CallErrHook(struct Hook *, struct IORequest *, struct PrtErrMsg *);

   FUNCTION
    An application can set an error hook that is called in case of
    errors to display an formated and localized error message to the
    user. The driver can set an error hook to format and localize
    custom error messages and to call the application's error hook. This
    is done by calling PD->pd_CallErrHook() from the printer.device.
    CallErrHook will do additional formating like setting a title of
    the error message if no is set by the driver and then calls the
    application's error hook.

   RESULT
    The return value of the hook is returned from CallErrHook.


printer.device/PBothReady

   NAME
    PBothReady - wait until output is finished

   FUNCTION
    The function PBothReady should only be called from drivers. It waits
    until the output to the printer is finished.


printer.device/PRD_DUMPRPORT

   NAME
    PRD_DUMPRPORT -- dump the specified RastPort to a graphics printer

   FUNCTION
    Print a rendition of the supplied RastPort, using the supplied
    ColorMap, position and scaling information, as specified in
    the printer preferences.

   IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible.
    io_Command	PRD_DUMPRPORT.
    io_Flags	IOB_QUICK set if quick I/O is possible.
    io_RastPort	ptr to a RastPort.
    io_ColorMap	ptr to a ColorMap.
    io_Modes	the 'modes' flag from a ViewPort structure,
            (the upper word is reserved and should be zero).

            If you are running under version 36, or greater
            of graphics.library, it is recommended that
            you fill in "io_Modes" with the ULONG (32-bit)
            value returned from calling:

            ULONG ModeID = GetVPModeID(struct ViewPort *);

            Doing so provides for upwards compatability with
            the new display modes available under V36
            (example: aspect ratio calculations for new
            display modes).

    io_SrcX		x offset into the RastPort to start printing from.
    io_SrcY		y offset into the RastPort to start printing from.
    io_SrcWidth	width of the RastPort to print (from io_SrcX).
    io_SrcHeight	height of the RastPort to print (from io_SrcY).
    io_DestCols	width of the printout in printer pixels.
    io_DestRows	height of the printout in printer pixels.
    io_Special	flag bits
            (some of which pertain to DestCols and DestRows).
            -if SPECIAL_MIL is set, then the associated
             parameter is specified in thousandths of
             an inch on the printer.  ie. if DestCols = 8000,
             DestRows = 10500 and SPECIAL_MILROWS and
             SPECIAL_MILCOLS is set then the printout would be
             8.000 x 10.500 inches.
            -if SPECIAL_FULL is set, then the specific dimension
             is set to the maximum possible as determined
             by the printer limits or the configuration
             limits; whichever is less.
            -if SPECIAL_FRAC is set, the parameter is
             taken to be a longword binary fraction
             of the maximum for that dimension.
            -if all bits for a dimension are clear,
             (ie. SPECIAL MIL/FULL/FRAC and ASPECT are NOT set)
             then the parameter is specified in printer pixels.
            -if SPECIAL_CENTER is set then the image will be
             put between the left and right edge of the paper.
            -if SPECIAL_ASPECT is set, one of the dimensions
             may be reduced/expanded to preserve the aspect
             ratio of the print.
            -SPECIAL_DENSITY(1-7) this allows for a maximum of 7
             different print densities.  DENSITY1 is the lowest
             density and the default.
            -SPECIAL_NOFORMFEED - this allows for the mixing of
             text and graphics or multiple graphic dumps on page
             oriented printers (usually laser jet printers).
             When this flag is set the page will not be ejected
             after a graphic dump.  If you perform another
             graphic dump without this flag set OR close the
             printer after printing text after a graphic dump,
             the page will be ejected.
            -if SPECIAL_TRUSTME is set then the printer specific
             driver is instructed to not issue a reset command
             before and after the dump.  If this flag is NOT
             checked by the printer specific driver then setting
             this flag has no effect.  Since we now recommend
             that printer driver writers no longer issue a reset
             command it is probably a safe idea to always set
             this flag when calling for a dump.
            -if SPECIAL_NOPRINT is set then the following is done:
             Compute print size, set 'io_DestCols' and
             'io_DestRows' in the calling program's 'IODRPReq'
             structure and exit, DON'T PRINT.  This allows the
             calling program to see what the final print size
             would be in printer pixels.  Note that it modifies
             the 'io_DestCols' and 'io_DestRows' fields of your
             'IODRPReq' structure.  It also sets the print
             density and updates the 'MaxXDots', 'MaxYDots',
             'XDotsInch', and 'YDotsInch' fields of the
             'PrinterExtendedData' structure.

    There following rules for the interpretation of io_DestRows and
    io_DestCols that may produce unexpected results when they are
    not greater than zero and io_Special is zero.  They have been
    retained for compatability.  The user will not trigger these
    other rules with well formed usage of io_Special.

    When io_Special is equal to 0, the following rules
    (from the V1.1 printer.device, and retained for compatibility
    reasons) take effect.  Remember, these special rules are
    for io_DestRows and io_DestCols and only take effect
    if io_Special is 0).

    a) DestCols>0 & DestRows>0 - use as absolute values.
       ie. DestCols=320 & DestRows=200 means that the picture
       will appear on the printer as 320x200 dots.
    b) DestCols=0 & DestRows>0 - use the printers maximum number
       of columns and print DestRows lines. ie. if DestCols=0
       and DestRows=200 than the picture will appear on the
       printer as wide as it can be and 200 dots high.
    c) DestCols=0 & DestRows=0 - same as above except the driver
       determines the proper number of lines to print based on
       the aspect ratio of the printer. ie. This results in the
       largest picture possible that is not distorted or inverted.
       Note: As of this writing, this is the call made by such
       program as DeluxePaint, GraphicCraft, and AegisImages.
    d) DestCols>0 &DestRows=0 - use the specified width and the
       driver determines the proper number of lines to print based
       on the aspect ratio of the printer. ie. if you desire a
       picture that is 500 pixels wide and aspect ratio correct,
       use DestCols=500 and DestRows=0.
    e) DestCols<0 or DestRows>0 - the final picture is either a
       reduction or expansion based on the fraction
       |DestCols| / DestRows in the proper aspect ratio.
       Some examples:
       1) if DestCols=-2 & DestRows=1 then the printed picture will
          be 2x the AMIGA picture and in the proper aspect ratio.
          (2x is derived from |-2| / 1 which gives 2.0)
       2) if DestCols=-1 & DestRows=2 then the printed picture will
          will be 1/2x the AMIGA picture in the proper aspect ratio.
          (1/2x is derived from |-1| / 2 which gives 0.5)

   NOTES
    The printer selected in preferences must have graphics
    capability to use this command.  The error 'PDERR_NOTGRAPHICS'
     is returned if the printer can not print graphics.

    Color printers may not be able to print black and white or
    greyscale pictures -- specifically, the Okimate 20 cannot print
    these with a color ribbon: you must use a black ribbon instead.
    If the printer has an input buffer option, use it.
    If the printer can be uni or bi directional, select
    uni-directional; this produces a much cleaner picture.
    Most printer drivers will attempt to set unidirectional
    printing if it is possible under software control.

    Please note that the width and height of the printable area on
    the printer is in terms of pixels and bounded by the following:
     a) WIDTH = (RIGHT_MARGIN - LEFT_MARGIN + 1) / CHARACTERS_PER_INCH
     b) HEIGHT = LENGTH / LINES_PER_INCH
    Margins are set by preferences.

    For BGR printer support, the YMC values in the printer
    specific render.c functions equate to BGR respectively, ie.
    yellow is blue, magenta is green, and cyan is red.

    For version 2.1 of the Operating System (the Localization
    release), some of the printer drivers have been modified to
    support European A size paper (e.g., "A4").  See preferences.h
    for a list of defined sizes.  For most printers, this means
    the maximum X dots will be calculated based on millimeters
    minus 1/2 inch (approx 13 mm) - this is consistent with existing
    driver calculations (e.g., 8.0 inches wide for US_LETTER, and
    US_LEGAL sizes).

    Some printers, like the HP_LaserJet, and HP_DeskJet also
    calculate maximum Y dots.

    For all modified printer drivers, selecting paper sizes larger
    than the printer can handle may result in unexpected, or
    clipped results.  This allows for the possibility of using
    these drivers with future printers which may physically
    [and internally] support these larger sizes of paper.

    It is assumed that the user will make reasonable choices when
    selecting paper size (e.g., not select WIDE TRACTOR for a
    NARROW TRACTOR printer).

 Data Structures
 ---------------

    The printer specific and non-specific data structures can be read
    ONCE you have opened the printer device.  Here is a code fragment
    to illustrate how to do just that.

    #include <exec/types.h>
    #include <devices/printer.h>
    #include <devices/prtbase.h>
    #include <devices/prtgfx.h>

    struct IODRPReq PReq;
    struct PrinterData *PD;
    struct PrinterExtendedData *PED;

   open the printer device / if it opened...
   if (OpenDevice("printer.device", 0, &PReq, 0) == NULL) {
       get pointer to printer data
       PD = (struct PrinterData *)PReq.io_Device;
       get pointer to printer extended data
       PED = &PD->pd_SegmentData->ps_PED;
       let's see what's there
       printf("PrinterName = '%s', Version=%u, Revision=%un",
           PED->ped_PrinterName, PD->pd_SegmentData->ps_Version,
           PD->pd_SegmentData->ps_Revision,);
       printf("PrinterClass=%u, ColorClass=%un",
           PED->ped_PrinterClass, PED->ped_ColorClass);
       printf("MaxColumns=%u, NumCharSets=%u, NumRows=%un",
           PED->ped_MaxColumns, PED->ped_NumCharSets, PED->ped_NumRows);
       printf("MaxXDots=%lu, MaxYDots=%lu, XDotsInch=%u, YDotsInch=%un",
           PED->ped_MaxXDots, PED->ped_MaxYDots,
           PED->ped_XDotsInch, PED->ped_YDotsInch);
       CloseDevice(&PReq);
   }

 Preferences
 -----------

    If you want the user to be able to access the printer preferences items
 without having to run preferences (like DPAINT II's printer requester),
 here is what you do.  You can look at the printer's copy of preferences
 by referring to 'PD->pd_Preferences' (the printer device MUST already be
 opened at this point).  After you have this you could put up a requester
 and allow the user to change whatever parameters they wanted.
 BEAR IN MIND THAT YOU ARE RESPONSIBLE FOR RANGE CHECKING THESE SELECTIONS!
 Listed below are the printer preferences items and their valid values.

 PrintPitch         - PICA, ELITE, FINE.
 PrintQuality       - DRAFT, LETTER.
 PrintSpacing       - SIX_LPI, EIGHT_LPI.
 PrintLeftMargin    - 1 to PrintRightMargin.
 PrintRightMargin   - PrintLeftMargin to 999.
 PaperLength        - 1 to 999.
 PrintImage         - IMAGE_POSITIVE, IMAGE_NEGATIVE.
 PrintAspect        - ASPECT_HORIZ, ASPECT_VERT.
 PrintShade         - SHADE_BW, SHADE_GREYSCALE, SHADE_COLOR.
 PrintThreshold     - 1 to 15.
 PrintFlags         - CORRECT_RED, CORRECT_GREEN, CORRECT_BLUE, CENTER_IMAGE,
                      IGNORE_DIMENSIONS, BOUNDED_DIMENSIONS,
                      ABSOLUTE_DIMENSIONS, PIXEL_DIMENSIONS,
                      MULTIPLY_DIMENSIONS, INTEGER_SCALING,
                      ORDERED_DITHERING, HALFTONE_DITHERING.
                      FLOYD_DITHERING, ANTI_ALIAS, GREY_SCALE2
 PrintMaxWidth      - 0 to 65535.
 PrintMaxHeight     - 0 to 65535.
 PrintDensity       - 1 to 7.
 PrintXOffset       - 0 to 255.

 Asynchronous I/O
 ----------------

     The recommended way to do asynchronous i/o is...

 a) To send requests for i/o.

     struct IORequest *ioreq;
     struct MsgPort *port;
     UBYTE signal;

     port = ioreq->io_Message.mn_ReplyPort;
     signal = port->mp_SigBit;

     SendIO(ioreq);  send request
     Wait(signal);  wait for completion (go to sleep)
     while ((Msg = GetMsg(port)) != NULL) {  get ALL messages
     }

 b) To abort a previous request for i/o.

     struct IORequest *ioreq;

     AbortIO(ioreq);  abort request
     WaitIO(ioreq);  wait for reply

     at this point you can re-use 'ioreq'.

     Note that in the above examples 'ioreq' could be any one of...
     a) struct IOStdReq    a standard i/o request
     b) struct IODRPReq    a dumprport i/o request
     c) struct IOPrtCmdReq a printer command i/o request

     It is recommend that you do asynchronous i/o in your programs
     and give the user a way of aborting all requests.

         V1.3 Printer Driver Notes
         -------------------------

     In general densities which use more than one pass should only be
 used for B&W shade dumps.  They can be used for Grey-Scale or Color Shade
 dumps BUT the output may tend to look muddy or dark.  Also multiple pass
 Color dumps tend to dirty or smear the ribbon (ie. yellow will get
 contaminated with the other colors on the ribbon; you have been warned).

 Alphacom_AlphaPro_101
 ---------------------
 1. Daisywheel printer (text only).

 Brother_HR-15XL
 ---------------
 1. Daisywheel printer (text only).

 CalComp_ColorMaster
 -------------------
 1. Thermal transfer b&w/color printer (text and graphics).
 2. Use Black ribbon for non-color dumps; Color ribbon for color dumps.
 3. Linefeeds # of vertical dots printed.
 4. Densities supported are 203x200(1) dpi.
 5. This is a dual printer driver.  Select a PaperSize of 'Narrow Tractor'
    for use with the ColorMaster; 'Wide Tractor' for use with the
    ColorView-5912 (which uses 11 x 17 inch paper).

 CalComp_ColorMaster2
 -------------------
 1. Thermal transfer b&w/color printer (text and graphics).
 2. Use Black ribbon for non-color dumps; Color ribbon for color dumps.
 3. Linefeeds # of vertical dots printed.
 4. Densities supported are 203x200(1) dpi.
 5. This is a dual printer driver.  Select a PaperSize of 'Narrow Tractor'
    for use with the ColorMaster; 'Wide Tractor' for use with the
    ColorView-5912 (which uses 11 x 17 inch paper).
 6. This driver is the same as the Calcomp_ColorMaster driver EXCEPT it is
    approximately 2 times faster (during color dumps) and requires LOTS of
    memory (up to 1,272,003 bytes for a full 8 x 10 inch (1600 x 2000 dot)
    color dump).  Typically full-size (color) dumps are 1600 x 1149 dots and
    require 730,767 bytes.  Memory requirements for the ColorView-5912
    are up to 2,572,803 bytes for a full 10 x 16 inch (2048 x 3200 dot)
    color dump.  Typically full-size (color) dumps are 2048 x 2155 dots and
    require 1,732,623 bytes.  The memory requirements are 1/3 when doing a
    non-color printout (on both the ColorMaster and ColorView).

 Canon_PJ-1080A
 --------------
 1. Ink jet b&w/color printer (text and graphics).
 2. Linefeeds # of vertical dots printed.
 3. Densities supported are 83x84(1) dpi.

 CBM_MPS1000
 -----------
 1. Dot matrix b&w printer (text and graphics).
 2. Linefeeds # of vertical dots printed (-1/3 dot if PaperType = Single). *2
 3. Density	XDPI	YDPI	XYDPI	Comments
     1	120	 72	 8640
     2	120	144	17280	two pass
     3	240	 72	17280			*1
     4	120	216	25920	three pass
     5	240	144	34560	two pass	*1
     6	240	216	51840	three pass	*1
     7	same as 6
 4. Print width for US_LETTER size paper is 8.0 inches.
 5. As of version 35.48, this driver calculates maximum X dots for
    European A size paper as defined in preferences.h.  Some of
    these sizes are too large for this printer.

 Diablo_630
 ----------
 1. Daisywheel printer (text only).

 Diablo_Advantage_D25
 --------------------
 1. Daisywheel printer (text only).

 Diablo_C-150
 ------------
 1. Ink jet b&w/color printer (text and graphics).
 2. Always linefeeds 4 dots (limitation of printer).
 3. A PaperSize of 'Wide Tractor' selects a maximum print width of
    8.5 inches (for wide roll paper).
 5. Densities supported are 120x120(1) dpi.

 EpsonQ (24-pin Epson compatible)
 ------
 1. Dot matrix b&w/color printer (text and graphics).
 2. Drives all EpsonQ (LQ1500, LQ2500, etc.) compatible printers.
 3. Linefeeds # of vertical dots printed.
 4. Density	XDPI	YDPI	XYDPI	Comments
     1	 90	180	16200
     2	120	180	21600
     3	180	180	32400
     4	360	180	64800	*1
     5,6,7	same as 4
 5. A PaperSize of 'Wide Tractor' selects a maximum print width of
    13.6 inches (for wide carriage printers).
 6. A PaperType of 'Single' uses only 16 of the 24 pins, whereas a PaperType
    of 'Fanfold' uses all 24 pins.  The 'Single' option is useful for those
    printers which have a weak power supply and cannot drive all 24 pins
    continuously.  If during a single pass of the print head you notice that
    the top two thirds of the graphics are darker than the bottom one third
    then you will probably need to drop down to 16 pins.
 7. As of version 35.71, this driver calculates maximum X dots for
    European A size paper as defined in preferences.h.  The calculation
    is based on millimeters minus 1/2 inch (approx 13mm).  Maximum
    paper width is 13.6 inches, so some European A sizes are too large
    for this printer.

 EpsonX[CBM_MPS-1250] (8/9-pin Epson compatible)
 --------------------
 1. Dot matrix b&w/color printer (text and graphics).
 2. Drives all EpsonX (EX/FX/JX/LX/MX/RX, etc.) compatible printers.
 3. Linefeeds # of vertical dots printed (-1/3 dot if PaperType = Single). *2
 4. Density	XDPI	YDPI	XYDPI	Comments
     1	120	 72	 8640
     2	120	144	17280	two pass
     3	240	 72	17280			*1
     4	120	216	25920	three pass
     5	240	144	34560	two pass	*1
     6	240	216	51840	three pass	*1
     7	same as 6

 5. A PaperSize of 'Wide Tractor' selects a maximum print width of
    13.6 inches (for wide carriage printers).
 6. Use this driver if you own a CBM_MPS-1250 (as it is EpsonX compatible).
 7. As of version 35.42, this driver calculates maximum X dots for
    European A size paper as defined in preferences.h.  The calculation
    is based on millimeters minus 1/2 inch (approx 13mm).  Maximum
    paper width is 13.6 inches, so some European A sizes are too large
    for this printer.

 EpsonXOld (8/9-pin Epson compatible)
 ---------
 1. Dot matrix b&w printer (text and graphics).
 2. Drives all very old EpsonX (EX/FX/JX/LX/MX/RX, etc.) compatible printers.
 3. Linefeeds # of vertical dots printed.
 4. Density	XDPI	YDPI	XYDPI	Comments
     1	 60	72	 4320
     2	120	72	 8640	(double speed)			*1
     3	120	72	 8640
     4	240	72	17280					*1
     5	120	72	 8640	(for use on old Star printers)
     6	240	72	17280	(for use on old Star printers)	*1
     7	240	72	17280	(same as density 4)		*1
 5. A PaperSize of 'Wide Tractor' selects a maximum print width of
    13.6 inches (for wide carriage printers).
 6. Use this driver if the EpsonX driver does not work properly in graphics
    or text mode on your EpsonX compatible printer.

 generic
 -------
 1. Text only printer.

 Howtek_Pixelmaster
 ------------------
 1. Plastic ink jet b&w/color printer (text and graphics).
 2. Linefeeds # of vertical dots printed.
 3. Density	XDPI	YDPI	XYDPI	Comments
     1	 80	 80	 6400
     2	120	120	14400
     3	160	160	25600
     4	240	240	57600
     5,6,7	same as 4
 4. Maximum print area is 8.0 x 10.0 inches.

 HP_DeskJet
 ----------
 1. Ink jet non-color printer (text and graphics).
 2. Linefeeds # of vertical dots printed.
 3. Density	XDPI	YDPI	XYDPI	Comments
     1	 75	 75	 5625
     2	100	100	10000
     3	150	150	22500
     4	300	300	90000
     5,6,7	same as 4
 4. Maximum print area is 8.0 x 10.0 inches US_LEGAL, and 8.0 x
    13.0 inches US_LETTER.
 5. As of version 35.29, the driver will calculate maximum area
    size for European A size paper as defined in preferences.h.
    The driver calculates the maximum X, and Y dots based on
    millimeters, minus 1/2 inch from the width, and minus 1"
    from the height (approx 13mm, and 26mm respectively).
    Therefore the margin area is consistent with US paper sizes.
 6. Some European A sizes are too large for this printer.

 HP_LaserJet (LaserJet+/LaserJetII compatible)
 -----------
 1. Laser engine non-color printer (text and graphics).
 2. Linefeeds # of vertical dots printed.
 3. Density	XDPI	YDPI	XYDPI	Comments
     1	 75	 75	 5625
     2	100	100	10000
     3	150	150	22500
     4	300	300	90000
     5,6,7	same as 4
 4. Maximum print area is 8.0 x 10.0 inches US_LEGAL, and 8.0 x
    13.0 inches US_LETTER.
 5. As of version 35.59, the driver will calculate maximum area
    size for European A size paper as defined in preferences.h.
    The driver calculates the maximum X, and Y dots based on
    millimeters, minus 1/2 inch from the width, and minus 1"
    from the height (approx 13 mm, and 26 mm respectively).
    Therefore the margin area is consistent with US paper sizes.
 6. Some European A sizes are too large for this printer.

 HP_PaintJet
 -----------
 1. Ink jet b&w/color printer (text and graphics).
 2. Linefeeds # of vertical dots printed.
 3. Densities supported are 180x180(1) dpi.

 HP_ThinkJet
 ----------
 1. Ink jet non-color printer (text and graphics).
 2. Linefeeds # of vertical dots printed.
 3. Density	XDPI	YDPI	XYDPI	Comments
     1	 96	96	 9216
     2	192	96	18432
     3,4,5,6,7	same as 4
 4. This printer prints 640 dots X in 96 DPI mode, and 120 dots
    X in 192 DPI mode.  Other sizes are not supported by the
    printer.

 Imagewriter II (Imagewriter compatible)
 --------------
 1. Dot matrix b&w/color printer (text and graphics).
 2. Linefeeds # of vertical dots printed.
 3. Density	XDPI	YDPI	XYDPI	Comments
     1	 80	 72	 5760
     2	120	 72	 8640
     3	144	 72	10368
     4	160	 72	11520
     5	120	144	17280	two pass
     6	144	144	20736	two pass
     7	160	144	23040	two pass

 Nec_Pinwriter (24-wire Pinwriter compatible (P5/P6/P7/P9/P2200))
 -------------
 1. Dot matrix b&w/color printer (text and graphics).
 2. Drives all NEC 24-wire Pinwriter compatible printers.
 3. Linefeeds # of vertical dots printed.
 4. Density	XDPI	YDPI	XYDPI	Comments
     1	 90	180	 16200
     2	120	180	 21600
     3	180	180	 32400
     4	120	360	 43200	two pass
     5	180	360	 64800	two pass
     6	360	180	 64800
     7	360	360	129600	two pass
 5. A PaperSize of 'Wide Tractor' selects a maximum print width of
    13.6 inches (for wide carriage printers).
 6. As of version 35.17, this driver calculates maximum X dots for
    European A size paper as defined in preferences.h.  The calculation
    is based on millimeters minus 1/2 inch (approx 13mm).  Maximum
    paper width is 13.6 inches, so some European A sizes are too large
    for this printer.

 Okidata_92
 ----------
 1. Dot matrix non-color printer (text and graphics).
 2. Always linefeeds 7/72 inch (limitation of printer in graphics mode).
 3. Densities supported are 72x72 dpi.

 Okidata_293I
 ------------
 1. Dot matrix b&w/color printer (text and graphics).
 2. Drives 292 or 293 using the IBM interface module.
 3. Linefeeds # of vertical dots printed (-1/2 dot if PaperType = Single) *3
 4. Density	XDPI	YDPI	XYDPI	Comments
     1	120	144	17280
     2	240	144	34560
     3	120	288	34560	two pass
     4	240	288	69120	two pass
     5,6,7	same as 4
 5. A PaperSize of 'Wide Tractor' selects a maximum print width of
    13.6 inches (for wide carriage printers).

 Okimate-20
 ----------
 1. Thermal transfer b&w/color printer (text and graphics).
 2. Use Black ribbon for non-color dumps; Color ribbon for color dumps.
 3. Linefeeds an even # of dots printed. (ie. if 3 printed, 4 advanced).
 4. Densities supported are 120x144(1) dpi.

 Quadram_QuadJet
 ---------------
 1. Ink jet b&w/color printer (text and graphics).
 2. Linefeeds # of vertical dots printed.
 3. Densities supported are 83x84(1) dpi.

 Qume_LetterPro_20
 -----------------
 1. Daisywheel printer (text only).

 Seiko_5300
 ----------
 1. Thermal transfer b&w/color printer (graphics only).
 2. Use Black ribbon for non-color dumps; Color ribbon for color dumps.
 3. Density	XDPI	YDPI	XYDPI	Comments
     1	152	152	23104	drives CH-5301 printer
     2	203	203	41209	drives CH-5312 printer
     3	240	240	57600	drives CH-5303 printer
     4, 5,6,7	same as 3
     You must select the proper density to drive the specific printer
     that you have.
 4. This driver is not on the V1.3 Workbench or Extras disk.  It is
    available on BIX and directly from Seiko.

 Seiko_5300a
 -----------
 1. Thermal transfer b&w/color printer (graphics only).
 2. Use Black ribbon for non-color dumps; Color ribbon for color dumps.
 3. Density	XDPI	YDPI	XYDPI	Comments
     1	152	152	23104	drives CH-5301 printer
     2	203	203	41209	drives CH-5312 printer
     3	240	240	57600	drives CH-5303 printer
     4, 5,6,7	same as 3
     You must select the proper density to drive the specific printer
     that you have.
 4. This driver is the same as the Seiko_5300 driver EXCEPT it is
    approximately 2 times faster (during color dumps) and requires LOTS of
    memory (up to 1,564,569 bytes for a full 8 x 10 inch (1927 x 2173 dot)
    color dump).  Typically full-size (color) dumps are 1927 x 1248 dots
    and require 898,569 bytes.  The memory requirements are 1/3 when doing
    a non-color printout.
 5. This driver is not on the V1.3 Workbench or Extras disk.  It is
    available on BIX and directly from Seiko.

 Tektronix_4693D
 ---------------
 1. Thermal transfer b&w/color printer (graphics only).
 2. Densities supported are 300x300(1) dpi
 3. Due to the way the printer images a picture none of the printer
    preferences options affect the printout with the following exceptions:
    a)Aspect - Horizontal, Vertical
    b)Shade - B&W, Grey_Scale, Color
    ...as a result of this only full size pictures can be printed.
 4. Keypad menu option 3b COLOR ADJUSTMENT may be set from the keypad.
    For normal prints this option should be set to "do not adjust".
 5. Keypad menu option 3d VIDEO COLOR CORRECTION may be set from the keypad.
    For normal prints this option should be set to "do not adjust".
 6. Keypad menu option 5 BACKGROUND COLOR EXCHANGE may be set from the
    keypad.  For normal prints this option should be set to "print colors
    as received".
 7. Once a picture has been printed additional copies may be printed
    without resending by using the printers keypad.
 8. This driver is not on the V1.3 Workbench or Extras disk.  It is
    available on BIX and directly from Tektronix.

 Tektronix_4696
 --------------
 1. Ink jet b&w/color printer (text and graphics).
 2. Always linefeeds 4 dots (limitation of printer).
 3. Densities supported are 121x120(1), 242x120(black)(2) and
    242x120(color)(3).
    Selecting a density of 2 or higher really doesn't give you true 242 dpi
    resolution since the printer only has 121 x dots per inch.
    Instead this mode tells the printer to go into it's double pass mode.
    Here, it outputs a line of dots at 121 dpi; and outputs the line again
    (shifted to the right by 1/242 of an inch).  This produces much more
    vibrate colors and gives the illusion of more resolution.  One drawback
    is that large areas of solid colors (red, green, and blue specifically)
    tend to over-saturate the paper with ink.  Density1 outputs all colors
    in one pass.  Density 2 does a double pass on black.  Density 3 does a
    double pass on all colors.  Density 1 to 3 correspond to the printer's
    graphics printing modes 1 to 3 (respectively).
 4. This driver is not on the V1.3 Workbench or Extras disk.  It is
    available on BIX and directly from Tektronix.
 5. A PaperSize of 'Wide Tractor' selects a maximum print width of
    9.0 inches (for wide roll paper).

 Toshiba_P351C (24-pin Toshiba compatible)
 -------------
 1. Dot matrix b&w/color printer (text and graphics).
 2. Drives all Toshiba_P351C compatible printers.
 3. Linefeeds # of vertical dots printed.
 4. Density	XDPI	YDPI	XYDPI	Comments
     1	180	180	32400
     2	360	180	64800
     3,4,5,6,7	same as 2
 5. A PaperSize of 'Wide Tractor' selects a maximum print width of
    13.5 inches (for wide carriage printers).

 Toshiba_P351SX (24-pin Toshiba compatible)
 --------------
 1. Dot matrix b&w/color printer (text and graphics).
 2. Drives all Toshiba_P351SX (321SL, 321SLC, 341SL) compatible printers.
 3. Linefeeds # of vertical dots printed.
 4. Density	XDPI	YDPI	XYDPI	Comments
     1	180	180	 32400
     2	360	180	 64800
     3	180	360	 64800	two pass
     4	360	360	129600	two pass
     5,6,7	same as 4
 5. A PaperSize of 'Wide Tractor' selects a maximum print width of
    13.5 inches (for wide carriage printers).

 Xerox_4020
 ----------
 1. Ink jet b&w/color printer (text and graphics).
 2. Always linefeeds 4 dots (limitation of printer).
 3. This driver is IDENTICAL to the Diablo_C-150 driver EXCEPT it outputs
    all black dots TWICE.  This is a special feature of this printer and
    produces much more solid, darker black shades.  Please note that some
    printing time overhead results from this feature; if you don't want it
    use the Diablo_C-150 driver.
 4. Densities supported are 121x120(1) and 242x240(2) dpi.
    Selecting a density of 2 or higher really doesn't give you true 240 dpi
    resolution since the Xerox_4020 only has 121 x dots per inch.
    Instead this mode tells the printer to go into it's pseudo 240 dpi mode.
    Here, it outputs a line of dots at 121 dpi; moves the paper up 1/240 of
    an inch and outputs the line again (shifted to the right by 1/240 of an
    inch).  This produces much more vibrate colors and gives the illusion
    of more resolution.  One drawback is that large areas of solid colors
    (red, green, and blue specifically) tend to over-saturate the paper with
    ink.
 5. A PaperSize of 'Wide Tractor' selects a maximum print width of
    9.0 inches (for wide roll paper).

 Notes
 -----

 *0 - on most printers friction fed paper tends to produce better looking
      (ie. less horizontal banding) graphic dumps than tractor fed paper.

 *1 - in this mode the printer cannot print two consecutive dots in a row.
      It is recommended that you only use this density for B&W Shade dumps.

 *2 - only when 72 YDPI is selected.  This option is useful if you notice
      tiny white horizontal strips in your printout.

 *3 - only when 144 YDPI is selected.  This option is useful if you notice
      tiny white horizontal strips in your printout.


printer.device/PRD_DUMPRPORTTAGS

   NAME
    PRD_DUMPRPORTTAGS -- dump the specified RastPort to a printer (V44)

   FUNCTION
    Print a rendition of the supplied RastPort, using the supplied
    ColorMap, position and scaling information, as specified in
    the printer preferences.

   IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible.
    io_Command	PRD_DUMPRPORT.
    io_Flags	IOB_QUICK set if quick I/O is possible.
    io_RastPort	ptr to a RastPort.
    io_ColorMap	ptr to a ColorMap.
    io_Modes	the 'modes' flag from a ViewPort structure,
            (the upper word is reserved and should be zero).

            If you are running under version 36, or greater
            of graphics.library, it is recommended that
            you fill in "io_Modes" with the ULONG (32-bit)
            value returned from calling:

            ULONG ModeID = GetVPModeID(struct ViewPort *);

            Doing so provides for upwards compatability with
            the new display modes available under V36
            (example: aspect ratio calculations for new
            display modes).

    io_SrcX		x offset into the RastPort to start printing from.
    io_SrcY		y offset into the RastPort to start printing from.
    io_SrcWidth	width of the RastPort to print (from io_SrcX).
    io_SrcHeight	height of the RastPort to print (from io_SrcY).
    io_DestCols	width of the printout in printer pixels.
    io_DestRows	height of the printout in printer pixels.
    io_Special	flag bits
    io_TagList	a list of tags to specify more parameters for the
            dump.

   TAGS
    DRPA_SourceHook	a pointer to struct Hook which is called to read
            the source data. io_RastPort and io_ColorMap are
            ignored and should be NULL.

            The hook is called with object == NULL and message
            is a pointer to struct DRPSourceMsg. It must read
            an array of source data.

            Each pixel of the array is an ULONG of form
            0x00RRGGBB.

            Some printer drivers have set PPCB_NOSTRIPE which
            means they cannot print in stripes. Using
            DRPA_SourceHook is the best way for printing for such
            printers because you can still prepare the printer
            source data in stripes then.

            The Source Hook is always called in the context of
            the printer driver DOS process.

    DRPA_AspectX	the X aspect ratio.
    DRPA_AspectY	the Y aspect ratio. This values overwrites the
            aspect ratio from GfxBase or io_Modes and is used
            for scaling.


printer.device/PRD_EDITPREFS

   NAME
    PRD_EDITPREFS - open the driver preferences window (V44)

   FUNCTION
    New drivers can have own preferences. This commands ask the driver
    to open a window to allow the user to change the prefs. Typically
    this is done with an DoIO() call.

    Every application should have a button "Driver Options..." (that
    calls PRD_EDITPREFS) in its printer dialog.

   IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible.
    io_Command	PRD_EDITPREFS
    io_Flags	IOB_QUICK set if quick I/O is possible.
    io_TagList	a list of tags to specify more parameters

    The following tags are currently defined:

    PPRA_Window (struct Window *)	a pointer to a window. This prefs
        window will open on the same screen and lock the window from
        user input.
    PPRA_Screen (struct Screen *)	a pointer to a screen. That can be
        used if no window is open.
    PPRA_PubScreen (STRPTR)	a name of a public screen that will be used
        to open the window. This can be NULL to use the default
        public screen.


printer.device/PRD_PRTCOMMAND

   NAME
       PRD_PRTCOMMAND -- send a command to the printer

   FUNCTION
      This function sends a command to either the parallel or serial
      device.  The printer device maps this command to the control
      code set of the current printer.  The commands supported can
      be found with the printer.device/Write command.  All printers
      may not support all functions.

   IO REQUEST IOPrtCmdReq
       io_Message      mn_ReplyPort set
       io_Device       preset by OpenDevice
       io_Unit         preset by OpenDevice
       io_Command      PRD_PRTCOMMAND
       io_PrtCommand   the actual command number
       io_Parm0        parameter for the command
       io_Parm1        parameter for the command
       io_Parm2        parameter for the command
       io_Parm3        parameter for the command

   RESULTS
       Errors: if the PRD_PRTCOMMAND succeeded, then io_Error will be zero.
       Otherwise io_Error will be non-zero.  An error of -1 indicates that
       the command is not supported by the current printer driver.  This
       could be used to check if the connected printer supports a particular
       command (italics for example).

   SEE ALSO
       printer.device/PWrite() printer.h, parallel.device, Preferences


printer.device/PRD_READPREFS

   NAME
    PRD_READPREFS - read the current driver preferences in a buffer (V44)

   FUNCTION
    This is a non standard read command that reads the driver
    preferences.

   IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Command	PRD_READPREFS
    io_Flags	IOB_QUICK set if quick I/O is possible
    io_Length	the size of the buffer in io_Data
    io_Data		a buffer
    io_Actual	the number of bytes copied to the buffer.

    If the read fails because the buffer is too small you should double
    the size of the buffer and try it again.

    Never interpret the contents of the buffer. You are allowed to save
    it to file (as one block of data) and of course to write it back to
    the driver (PRD_WRITEPREFS).

    If you close the printer device between PRD_EDITPREFS and the
    actual printing (CMD_WRITE or PRD_DUMPRPORTTAGS) you must read
    the prefs after PRD_EDITPREFS and write it back before printing
    or the driver may forget the user changes.


printer.device/PRD_SETERRHOOK

   NAME
    PRD_SETERRHOOK -- set a hook for error messages (V44)

   FUNCTION
    This command sets a hook that will be called if the printer.device
    returns with an error from any other I/O command. This allows
    printer drivers to use private error messages.

   IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Device	preset by the call to OpenDevice
    io_Command	PRD_SETERRORHOOK
    io_Hook		a pointer to a hook that will be called

    Two standard hook values a defined:

    PDHOOK_NONE	no error hook is to be used
    PDHOOK_STD	EasyRequest() is used to display the error message

    The hook gets a pointer to the IORequest that caused the error as
    the object and a pointer to the following structure as message:

struct PrtErrMsg {
    ULONG pe_Version;
    ULONG pe_ErrorLevel;
    struct Window *pe_Window; /* window for EasyRequest() */
    struct EasyStruct *pe_ES;
    ULONG *pe_IDCMP;
    APTR pe_ArgList;
};
    pe_Version	the message version number PDHOOK_VERSION
    pe_ErrorLevel	one of RETURN_WARN, RETURN_ERROR, RETURN_FAIL
    pe_Window	a window pointer (for EasyRequest()) or NULL
    pe_ES		a pointer to the error message structure
    pe_IDCMP	a pointer to IDCMP Flags for EasyRequest()
    pe_ArgList	a pointer to an array of arguments

    The simplest case is to use that structure to call EasyRequest()
    or to printf() a message to a console (use the error message from
    pe_ES and the pe_ArgList).


printer.device/PRD_WRITEPREFS

   NAME
    PRD_WRITEPREFS - write the current driver prefs from a buffer (V44)

   FUNCTION
    This is a non standard write command that writes the driver
    preferences.

   IO REQUEST
    io_Message	mn_ReplyPort set if quick I/O is not possible
    io_Command	PRD_WRITEPREFS
    io_Flags	IOB_QUICK set if quick I/O is possible
    io_Length	the length of the buffer
    io_Data		a buffer
    io_Actual	the number of bytes copied to the driver prefs.

    The printer driver checks the buffer before copying it to its
    preferences. So you don't have to worry about changing the printer
    driver between PRD_READPREFS and PRD_WRITEPREFS.


printer.device/PQuery

   NAME
    PQuery - read number of chars in input buffer

   SYNOPSIS
    error = (*PrinterData->pd_PQuery)(*length);
    D0

    LONG PRead(LONG *);

   FUNCTION
       PQuery reads the number of data in the input buffer which can be
       read from the printer port. The variable length points to is set
       to the number of readable chars.


printer.device/PRead

   NAME
    PRead - internal read from printer port

   SYNOPSIS
    error = (*PrinterData->pd_PRead)(buffer, length, tv);
    D0

    LONG PRead(UBYTE *, ULONG *, struct timeval *);

   FUNCTION
    PRead reads a buffer of data from the printer port. The variable
    length points to is set to the actual number of read bytes.

    tv points to a struct timeval or is NULL in which case the default
    time is PrinterExtendedData.ped_TimeoutSecs. If the time of tv
    ellapes before the CMD_READ at the printer port is done two different
    things may happen: If at least one char is read PRead() returns. If
    no char is read but PQuery returns a value larger 0 the read is
    repeated with that length to read all outstanding data.


printer.device/PWrite

   NAME
    PWrite -- internal write to printer port

   SYNOPSIS
    error = (*PrinterData->pd_PWrite)(buffer, length);
    D0

    LONG PWrite(UBYTE *, ULONG);

   FUNCTION
    PWrite writes 'length' bytes directly to the printer.  This
    function is generally called by printer drivers to send
    their buffer(s) to the printer.

    This function is accessed by referencing off the PrinterData (PD)
    structure.  Below is a code fragment to show how to do get access
    to a pointer to the PrinterData (PD) structure.

    #include <exec/types.h>
    #include <devices/printer.h>
    #include <devices/prtbase.h>

    struct IODRPReq PReq;
    struct PrinterData *PD;
    struct PrinterExtendedData *PED;

    /* open the printer device (any version); if it opened... */
    if (OpenDevice("printer.device", 0, &PReq, 0) == NULL) {

        /* get pointer to printer data structure */
        PD = (struct PrinterData *)PReq.io_Device;

        /* write something directly to the printer */
        (*PD->pd_PWrite)("Hello worldn", 12);

        CloseDevice(&PReq); /* close the printer device */
    }


queue-handler.doc

     queue_handler()


queue-handler/queue_handler

   NAME
       queue_handler -- an 'infinite' pipe (FIFO) handler. (V37)

   SYNOPSIS
       Open("PIPE:[channel_name][[/[buf_size]][/max_buffers]]]");

   FUNCTION
       Queue-handler takes data from the output channel, buffers it up,
       allocating more memory as needed, and sends it to the input channel,
       as requested by the applications. Queue-handler never locks the output
       channel unless max_buffers was specified. Buffer size can be
       specified only on the first reference to a particular channel.

       Queue-handler works by invoking a seperate process every time an
       open packet is received, and uses a FIFO buffer pool approach to
       track the actual data.

   INPUTS
       channel_name - unique channel name to specify. Must begin with a
                      non-numeric character. The channel_name is
                      optional.

       buf_size - Size in bytes of the buffers to allocate
                  (default is 4096). The buf_size is optional.

       max_buffers - maximum number of buffers allowed. Will suspend
                     the output channel if exceeded. A max_buffers value of 0
                     indicates there should be no fixed limit on the number
                     of buffers allocated.

    PACKETS
    ACTION_FINDINPUT
    ACTION_FINDOUTPUT
    ACTION_FINDUPDATE
    ACTION_READ
    ACTION_WRITE
    ACTION_END
    ACTION_IS_FILESYSTEM

   MOUNTLIST ENTRIES
    This is the default mountlist entry used for Queue-Handler:

           PIPE:   Handler   = L:Queue-Handler
                   Priority  = 5
                   StackSize = 3000
                   GlobVec   = -1
           #

    Below is an extended mountlist entry which lets you specify a default
    number of buffers, and their size. There are some extra fields added
    at the end of the mountlist entry which aren't used for anything, but
    the Mount command requires that these fields be present. In this
    mountlist, the "Buffers" field indicates the default maximum number
    of buffers, and "SectorSize" indicates the size of these buffers.

           PIPE:    FileSystem = L:Queue-Handler
                    Priority   = 5
                    StackSize  = 3000
                    GlobVec    = -1
                    SectorSize = 1024
                    Buffers    = 2

                    /* these are unused, but required by Mount */
                Surfaces        = 1
                SectorsPerTrack = 1
                LowCyl          = 0
                HighCyl         = 1
                Device          = ""
                Unit            = 0
    #

   EXAMPLE
       From process 1:
           list >pipe: work: all

       From process 2:
           type pipe:

       To gather the results of several C compilations:
           lc >pipe:ll foo
           lc >pipe:ll bar
           lc >pipe:ll road
           lc >pipe:ll kill
           type pipe:ll

       To use channel names:
           list >pipe:crazy
           copy #?.c to >pipe:all_c/32000  ;Specifies a channel 'all_c' and
                                           ;a buffer size of 32000
                                           ;bytes

       To set a limit on the number of buffers to 5:
           dir >pipe://5       ; create a channel without a channel-name, and
                               ; only allow 5 buffer entries.

   BUGS
       Full checking is not done to ensure that the application can't read
       from a write channel or vice-versa. The results of this operation
       shall be undefined. Don't do it.


radiobutton_gc.doc

     --datasheet--
     RADIOBUTTON_GetClass()
     AllocRadioButtonNodeA()
     FreeRadioButtonNode()
     GetRadioButtonNodeAttrsA()
     SetRadioButtonNodeAttrsA()


radiobutton_gc/--datasheet--

    NAME
        radiobutton_gc -- create radiobutton BOOPSI objects

    SUPERCLASS
        gadgetclass

     REQUIRES
        bevel.image, glyph.image

    DESCRIPTION
        The radiobutton gadget class is used to create a mutually exclusive
        (MX) selection button group. Selection of an associated option is
        denoted by the depressed/filled button. Unlike GadTools, GA_Width and
        GA_Height to not specify the size of a single radio button. Instead
        it marks the entire domain of the gadget which allows for easier
        group layout. When used outside of a layout group you must be
        sure to provide enough space for the gadget to completly render
        all radio buttons and labels. However, within a layout group such
        as ReAction's own layout.gadget this is automatic and of no
        concern to the application programmer.

        Advantages that this class provides over the standard gadtools
        radiobutton (MX_KIND) are:

         > Strumming of the radio buttons with the mouse.

         > Aspect correct scaled buttons with any screen resolution or font.

         > Works under OS 2.0 or greater.

    METHODS
        OM_NEW -- Passed to superclass first, defaults set, then OM_SET.

        OM_SET -- Passed to superclass first, then custom tags set.

        OM_GET -- Returns requested setting or passed to superclass

        OM_DISPOSE -- Passed to superclass.

        GM_GOACTIVE -- Passed to superclass first, then radio activated

        GM_GOINACTIVE -- Passed to superclass first, then radio deactivated

        GM_HANDLEINPUT -- Handles button selection/strum. Overrides superclass.

        GM_HITTEST -- Overrides superclass, returns GMR_HITTEST.

        GM_RENDER -- Renders radio button(s).

        GM_DOMAIN -- Returns GDOMAIN_MINIMUM and GDOMAIN_MAXIMUM dimensions.

        GM_KEYACTIVE -- Activates button via keyboard. Advances selection
            to the next item (down), if SHIFT is pressed, it selects
            the previous item (up). Invoked by window.class only.

        GM_KEYINACTIVE -- Deactivates gadget. Invoked by window.class only.

        All other methods are passed to the superclass.

    ATTRIBUTES
        GA_ID (WORD)
            Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_NOTIFY)

        GA_TextAttr (struct TextAttr *)
            Used to set the text font to render the radiobutton labels.

            Defaults to RPort->Font, which is often the screen or
            window font.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

        RADIOBUTTON_Labels (struct List *)
            Used to set the text labels for the radiobutton group.

            Defaults to NULL.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

        RADIOBUTTON_Spacing (WORD)
            Spacing between the radio buttons.

            Defaults to 1.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_NOTIFY)

        RADIOBUTTON_Selected (WORD)
            Currently selected radio button number.

            Defaults to 0.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

        RADIOBUTTON_LabelPlace (WORD)
            Location of radiobutton text labels. Supports:

                PLACETEXT_RIGHT

            Defaults to PLACETEXT_RIGHT.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

    NOTES
        GA_Height and GA_Width DO NOT specify the actual button size, but
        rather the entire "hit box" area which includes the text label.
        When being used with layout.gadget it will domain to a proper
        size to hold the number of buttons and largest text labels.
        Take care when designing interfaces with out layout to set
        a proper height and width to hold the radiobutton imagery.
        This may be done via sending a BOOPSI GM_DOMAIN GDOMAIN_MINIMUM
        method message to the object with DoGadgetMethod(), or computing
        a minimum size based on font height and length. In otherwords,
        use layout, its alot easier! :)


radiobutton_gc/RADIOBUTTON_GetClass

    NAME
        RADIOBUTTON_GetClass -- Gets the pointer to the radiobutton class.

    SYNOPSIS
        radiobutton_class = RADIOBUTTON_GetClass();
        D0

        Class * RADIOBUTTON_GetClass(VOID);

    FUNCTION
        Obtains the pointer to the RadioButton gadget class for use with
        NewObject().  This function always returns a valid pointer so
        you do not need to check it.  The reason is that if the library
        opens fine, then the pointer returned is already setup.  (Of course
        this implies that if opening the library fails, you shouldn't be
        calling this.)

        Note that this function does not create the class, that is done
        when the class library is opened.

    INPUTS
        Nothing.

    RESULT
        radiobutton_class - Pointer to the RadioButton gadget class.

    SEE ALSO


radiobutton_gc/AllocRadioButtonNodeA

    NAME
        AllocRadioButtonNodeA -- Allocate a RadioButton node. (V40)

    SYNOPSIS
        struct Node * AllocRadioButtonNode(UWORD, Tag, ...)
        node = AllocRadioButtonNode(columns, Tag, ...)

        struct Node * AllocRadioButtonNodeA(UWORD, struct TagItem *)
        node = AllocRadioButtonNodeA(taglist)

    FUNCTION
        Allocates a node that can be added to the Exec linked list of
        labels in the radiobutton.  This is the only way to allocate a
        node for this list, you cannot allocate nodes yourself because
        the RadioButton class uses a private node structure.

    INPUTS
        taglist - Attributes for the node, passed onto
            SetRadioButtonNodeAttrsA().

    RESULT
        node - A node that can be added into the Exec list of labels for
            a RadioButton gadget.

    SEE ALSO
        FreeRadioButtonNode(), SetRadioButtonNodeAttrsA()


radiobutton_gc/FreeRadioButtonNode

    NAME
        FreeRadioButtonNode -- Free a RadioButton node. (V40)

    SYNOPSIS
        VOID FreeRadioButtonNode(struct Node *)
        FreeRadioButtonNode(node)

    FUNCTION
        Frees a RadioButtonNode allocated with AllocRadioButtonNodeA().

    INPUTS
        node - The node to free.

    SEE ALSO
        AllocRadioButtonNodeA()


radiobutton_gc/GetRadioButtonNodeAttrsA

    NAME
        GetRadioButtonNodeAttrsA -- Get attributes about a RadioButton node. (V40)

    SYNOPSIS
        VOID GetRadioButtonNodeAttrs(struct Node *, Tag, ...)
        GetRadioButtonNodeAttrs(node, firsttag, ...)

        VOID GetRadioButtonNodeAttrsA(struct Node *, struct TagItem *)
        GetRadioButtonNodeAttrsA(node, taglist)

    FUNCTION
        The RadioButton uses a private node structure and all attributes
        are hidden, and must therefore be accessed with this function.

    INPUTS
        node - The RadioButton node to get the information on.
        taglist - A tag list of attributes to get.  ti_Tag is the attribute
        to get and ti_Data is a pointer to a location to copy the result
        to.

    SEE ALSO
        SetRadioButtonNodeAttrsA()


radiobutton_gc/SetRadioButtonNodeAttrsA

    NAME
        SetRadioButtonNodeAttrsA -- Set attributes of a RadioButton node. (V40)

    SYNOPSIS
        VOID SetRadioButtonNodeAttrs(struct Node *, Tag, ...)
        SetRadioButtonNodeAttrs(node, firsttag, ...)

        VOID SetRadioButtonNodeAttrsA(struct Node *, struct TagItem *)
        SetRadioButtonNodeAttrsA(node, taglist)

    FUNCTION
        Changes attributes for a RadioButton node.  Since the RadioButton
        class uses a private node structure, this is the only way to change
        node attributes.

        You may NOT change node attributes when the node is in a list
        attached to a RadioButton gadget.  You must first detach the list
        with RADIOBUTTON_Labels, ~0 before you can change attributes, and
        then re-attach the list.

    TAGS
        RBNA_Label (STRPTR)

    INPUTS
        node - Node whose attributes you are changing.
        taglist - Tag list of attributes to change.

    SEE ALSO
        GetRadioButtonNodeAttrsA()


reaction_lib.doc

     --datasheet--
     BrowserNodesA()
     ChooserLabelsA()
     ClickTabsA()
     FreeBrowserNodes()
     FreeChooserLabels()
     FreeRadioButtons()
     GetAttrs()
     GetCode()
     LBAddNodeA()
     LBEditNodeA()
     LBRemNode()
     LibDoGadgetMethodA()
     OpenLayoutWindowTagList()
     RadioButtonsA()
     GetCode()
     FreeClickTabs()


reaction.lib/--datasheet--

   NAME
       reaction.lib -- ReAction support functions link library

   DESCRIPTION
       This library contains the autoinitialization code for the shared
       library versions of the ReAction BOOPSI classes, thus sparing the
       programmer from having to OpenLibrary() the classes manually. It
       also contains stub functions for the node taglist allocation
       functions of certain classes. These can be used by the DICE
       compiler, which does not support #pragma tagcall.

       Autoinitialization works just like normal SAS/C library autoinit.
       By declaring the class base extern in all source files (easiest
       done by #including the "proto" header, such as proto/layout.h),
       the SAS/C linker will take the class base, together with the code
       to open the class on program startup (and to close it on exit)
       from this library. The same autoinitialisation code should also
       work for DICE.

       The version number to use for OpenLibrary() is contained in the
       variable long __reactionversion. If you do not set this global
       variable in your source code, it will be linked from this library,
       With the release of V41 or greater classes in Release 2.0, it has
       been considered prudent to requier them, so you should set this
       value to 41. Note however, that classes NOT part of the ReAction
       package are not effected by __reactionversion and will open with
       any version available.

       If the opening of a class fails, the autoinit code will cause the
       program to exit with an error message of "Can't open version Y of
       X". If you wish to continue without using a certain class, you
       will have to open it manually.

   SUPPORTED CLASSES
       Version 1 of reaction.lib supports the following ReAction classes.
       The version variable of each class is listed after the shared class
       name.

       images/bevel.image
       images/bitmap.image
       gadgets/button.gadget
       gadgets/checkbox.gadget
       gadgets/chooser.gadget
       gadgets/datebrowser.gadget
       images/drawlist.image
       gadgets/fuelgauge.gadget
       gadgets/getfile.gadget
       gadgets/getfont.gadget
       gadgets/getscreenmode.gadget
       images/glyph.image
       gadgets/integer.gadget
       images/label.image
       gadgets/layout.gadget
       gadgets/listbrowser.gadget
       gadgets/radiobutton.gadget
       gadgets/scroller.gadget
       gadgets/slider.gadget
       gadgets/space.gadget
       gadgets/speedbar.gadget
       gadgets/string.gadget

       Additionally, to help programmers, reaction.lib contains
       autoinitialization for the following shared classes NOT part of
       the ReAction package. Please remember that these gadgets do not
       necessarily contain a CLASS_GetClass() type function for getting
       the base class. Some of them have registered class names, some
       have a function with another name. Some don't have functions at
       all, in which case special care must be taken to make sure the
       autoinit code is loaded (reference the class base variable, for
       example TapeDeckBase, somewhere within the source). Refer to the
       documentation of these classes to find out more.

       gadgets/calendar.gadget
       gadgets/colorwheel.gadget
       gadgets/gradientslider.gadget
       images/led.image
       gadgets/statusbar.gadget
       gadgets/tabs.gadget
       gadgets/tapedeck.gadget
       gadgets/textfield.gadget

   EXAMPLE
       The following program will print out the class base of
       layout.gadget and the base address of gradientslider.gadget (which
       doesn't have functions or a proto header) when compiled and linked
       with reaction.lib:

       #include <proto/layout.h>
       #include <proto/dos.h>

       extern void *GradientSliderBase;
       long __reactionversion = 37;

       main()
       {
           Printf( "layout.gadget minimum version %ld class base is %lxn",
                   __layoutversion, LAYOUT_GetClass() );
           Printf( "explicit reference to GradientSliderBase will force "
                   "initialization:n base address is %lxn",
                   GradientSliderBase );
       }


reaction.lib/BrowserNodesA

   NAME
       BrowserNodesA -- Make a linked list of listbrowser nodes
       BrowserNodes -- varags stub for BrowserNodesA

   SYNOPSIS
       list = BrowserNodesA( array )
       list = BrowserNodes( label, ... )
       struct List *BrowserNodesA( STRPTR * )
       struct List *BrowserNodes( STRPTR, ... )

   FUNCTION
       Make a linked list of single column listbrowser nodes from the
       NULL terminated label array. The labels are not copied, so they
       must stay valid until the list is free'd.

   INPUTS
       array -- a NULL terminated array of string pointers.

   RESULTS
       list -- a linked list of chooser nodes


reaction.lib/ChooserLabelsA

   NAME
       ChooserLabelsA -- Make a linked list of chooser labels
       ChooserLabels -- varags stub for ChooserLabelsA

   SYNOPSIS
       list = ChooserLabelsA( array )
       list = ChooserLabels( label, ... )
       struct List *ChooserLabelsA( STRPTR * )
       struct List *ChooserLabels( STRPTR, ... )

   FUNCTION
       Make a linked list of chooser nodes from the NULL terminated
       label array. The labels are not copied, so they must stay
       valid until the list is free'd.

   INPUTS
       array -- a NULL terminated array of string pointers.

   RESULTS
       list -- a linked list of chooser nodes


reaction.lib/ClickTabsA

   NAME
       ClickTabsA -- Make a linked list of clicktab nodes
       ClickTabs -- varags stub for ClickTabsA

   SYNOPSIS
       list = ClickTabsA( array )
       list = ClickTabs( label, ... )
       struct List *ClickTabsA( STRPTR * )
       struct List *ClickTabs( STRPTR, ... )

   FUNCTION
       Make a linked list of clicktab nodes from the NULL terminated
       label array. The labels are not copied, so they must stay
       valid until the list is free'd.

   INPUTS
       array -- a NULL terminated array of string pointers.

   RESULTS
       list -- a linked list of clicktab nodes


reaction.lib/FreeBrowserNodes

   NAME
       FreeBrowserNodes -- Free a linked list of chooser labels

   SYNOPSIS
       FreeBrowserNodes( list )
       void FreeBrowserNodes( struct List * )

   FUNCTION
       Free a linked list of chooser labels allocated with
       BrowserNodesA().

   INPUTS
       list -- the list to free

   RESULTS
       None


reaction.lib/FreeChooserLabels

   NAME
       FreeChooserLabels -- Free a linked list of chooser labels

   SYNOPSIS
       FreeChooserLabels( list )
       void FreeChooserLabels( struct List * )

   FUNCTION
       Free a linked list of chooser labels allocated with
       ChooserLabelsA().

   INPUTS
       list -- the list to free

   RESULTS
       None


reaction.lib/FreeClickTabs

   NAME
       FreeClickTabs -- Free a linked list of chooser labels

   SYNOPSIS
       FreeClickTabs( list )
       void FreeClickTabs( struct List * )

   FUNCTION
       Free a linked list of chooser labels allocated with
       ClickTabsA().

   INPUTS
       list -- the list to free

   RESULTS
       None


reaction.lib/FreeRadioButtons

   NAME
       FreeRadioButtons -- Free a linked list of radiobuttons

   SYNOPSIS
       FreeRadioButtons( list )
       void FreeRadioButtons( struct List * )

   FUNCTION
       Free a linked list of radiobuttons allocated with
       RadioButtonsA().

   INPUTS
       list -- the list to free

   RESULTS
       None


reaction.lib/GetAttrs

   NAME
       GetAttrsA -- Get multiple object attributes
       GetAttrs -- Varargs stub to GetAttrsA

   SYNOPSIS
       count = GetAttrsA( object, taglist )

       count = GetAttrs( object, tag, address, ... )

       ULONG GetAttrsA( Object *, struct TagItem * )

       ULONG GetAttrs( Object *, Tag, ... )

   FUNCTION
       Gets multiple attributes of an object iin a single call.
       Remember that while the function returns the number of
       attributes that were getable, it can not inform WHICH
       attributes, if any, were not. Thus, you shouldn't use this
       function when you are not sure that an attribute is getable.

   INPUTS
       object - pointer to the object that should be queried
       taglist - a list of tag and ULONG address pairs to fill

   RESULTS
       The number of attributes that succeeded.


reaction.lib/GetCode

   NAME
       GetCode -- return the true IDCMP message code

   SYNOPSIS
       code = GetCode( imsg )

       UWORD GetCode( struct IntuiMessage * )

   FUNCTION
       Returns the true IntuiMessage code field. Layout.gadget replaces
       the IDCMP_GADGETUP message with an IDCMP_IDCMPUPDATE. This function
       will return the "gadgetup code" from the IDCMPUPDATE taglist if it
       is found there, and otherwise the normal imsg->Code.

   INPUTS
       imsg -- a pointer to an IntuiMessage

   RESULTS
       The message's code field


reaction.lib/LBAddNodeA

   NAME
       LBAddNodeA -- V41 listbrowser.gadget LBM_ADDNODE method stub
       LBAddNode -- Varargs version of LBAddNodeA

   SYNOPSIS
       node = LBAddNodeA( gadget, window, requester, node, tags )

       struct Node *LBAddNodeA( struct Gadget *, struct Window *,
           struct Requester *, struct Node *, struct TagItem * );

       node = LBAddNode( gadget, window, requester, node, tag, ... )

       struct Node *LBAddNode( struct Gadget *, sruct Window *,
           struct Requester *, struct Node *, ULONG, ... );

   FUNCTION
       A function stub for calling LibDoGadgetMethodA() to allocate
       and add a new node to a listbrowser list. The main advantage
       of this function is to let you inline the vararg LBNA taglist.

   INPUTS
       gadget = listbrowser object
       window = the window in which the gadget is, or NULL
       requester = the requester of the window, or NULL
       node = the node before which to add the new node. NULL for
           beginning of the list
       tags = the LBNA node allocation taglist

   RESULT
       A pointer to the newly allocated node, or NULL on failure.

   NOTES
       This function uses the LibDoGadgetMethodA() function also
       defined in this link library.

   SEE ALSO
       LibDoGadgetMethodA()


reaction.lib/LBEditNodeA

   NAME
       LBEditNodeA -- V41 listbrowser.gadget LBM_EDITNODE method stub
       LBEditNode -- Varargs version of LBEditNodeA

   SYNOPSIS
       success = LBEditNodeA( gadget, window, requester, node, tags )

       ULONG LBEditNodeA( struct Gadget *, struct Window *,
           struct Requester *, struct Node *, struct TagItem * );

       success = LBEditNode( gadget, window, requester, node, tag, ... )

       ULONG LBEditNode( struct Gadget *, sruct Window *,
           struct Requester *, struct Node *, ULONG, ... );

   FUNCTION
       A function stub for calling LibDoGadgetMethodA() to modify an
       existing node on a listbrowser list. The main advantage
       of this function is to let you inline the vararg LBNA taglist.

   INPUTS
       gadget = listbrowser object
       window = the window in which the gadget is, or NULL
       requester = the requester of the window, or NULL
       node = the node to modify
       tags = the LBNA node modification taglist

   RESULT
       Nonzero on success.

   NOTES
       This function uses the LibDoGadgetMethodA() function also
       defined in this link library.

   SEE ALSO
       LibDoGadgetMethodA()


reaction.lib/LBRemNode

   NAME
       LBRemNode -- V41 listbrowser.gadget LBM_REMNODE method stub

   SYNOPSIS
       node = LBRemNode( gadget, window, requester, node )

       ULONG LBRemNode( struct Gadget *, struct Window *,
           struct Requester *, struct Node * );

   FUNCTION
       A function stub for calling LibDoGadgetMethodA() to remove and
       free a node from a listbrowser list. This function mostly
       exists for completeness's sake.

   INPUTS
       gadget = listbrowser object
       window = the window in which the gadget is, or NULL
       requester = the requester of the window, or NULL
       node = the node to free

   RESULT
       Nonzero on success.

   NOTES
       This function uses the LibDoGadgetMethodA() function also
       defined in this link library.

   SEE ALSO
       LibDoGadgetMethodA()


reaction.lib/LibDoGadgetMethodA

   NAME
       LibDoGadgetMethodA -- DoGadgetMethodA for V37 machines
       LibDoGadgetMethod -- Varargs stub for LibDoGadgetMethodA

   SYNOPSIS
       result = LibDoGadgetMethodA( Gadget, Window, Requester, Message )
       D0                  A0      A1      A2         A3

       ULONG LibDoGadgetMethodA( struct Gadget *, struct Window *,
           struct Requester *, Msg );

       result = LibDoGadgetMethod( Gadget, Window, Requester, MethodID, ...)

       ULONG LibDoGadgetMethod( struct Gadget *, struct Window *,
           struct Requester *, ULONG, ... );

   FUNCTION
       Same as the DoGadgetMethod() function of intuition.library V39,
       this function invokes a BOOPSI method and provides context
       information for classes which implement custom Intuition gadgets.

       You should use this function for boopsi gadget objects,
       or for "models" which propagate information to gadgets.

       Unlike DoMethod(), this function provides a GadgetInfo pointer
       (if possible) when invoking the method.  Some classes may
       require or benefit from this.

       On a V39 machine, this function calls the Intuition function.

   INPUTS
       Gadget = abstract pointer to a boopsi gadget
       Window = window gadget has been added to using AddGList() or AddGadget()
       Requester = for REQGADGETs, requester containing the gadget
       Msg = the boopsi message to send

   RESULT
       The object does whatever it wants with the message you sent,
       which might include updating its gadget visuals.

       The return value is defined per-method.

   NOTES
       This function invokes the specified method with a GadgetInfo
       derived from the 'Window' and 'Requester' pointers.  The GadgetInfo
       is passed as the second parameter of the message, except for
       OM_NEW, OM_SET, OM_NOTIFY, and OM_UPDATE, where the GadgetInfo
       is passed as the third parameter.

       Implementers of new gadget methods should ensure that the
       GadgetInfo is the second long-word of their message!

   SEE ALSO
       NewObject(), DisposeObject(), GetAttr(), MakeClass(),
       Document "Basic Object-Oriented Programming System for Intuition"
       and the "boopsi Class Reference" document.


reaction.lib/OpenLayoutWindowTagList

   NAME
       OpenLayoutWindowTagList -- Open a window at a suitable size for layout
       OpenLayoutWindowTags -- Varags stub for OpenLayoutWindowTagList

   SYNOPSIS
       window = OpenLayoutWindowTagList( layout, screen, taglist )

       struct Window *OpenLayoutWindowTagList( struct Gadget *,
               struct Screen *, struct TagList * )

       window = OpenLayoutWindowTags( layout, screen, tag, ... )

       struct Window *OpenLayoutWindowTags( struct Gadget *,
               struct Screen *, Tag, ... )

   FUNCTION
       Determines the minimum size that will fit a layout and opens the window
       at that size. The sizing limits of the window will be set according to
       the layout's limits, and the layout will be added to the window,
       making it relative to window size. The layout will fit the whole inner
       size of the window. It will not be rendered, so you must call
       RefreshGadgets(), possibly after adding your border gadgets.

       This function will set InnerWidth, InnerHeight, and the screen for the
       window. Other tags you have to pass yourself.

   INPUTS
       layout -- the layout hierarcy for the window
       screen -- pointer to the screen the window will be opened on
       taglist -- the additional tags for the window.

   RESULTS
       A pointer to the opened window or NULL if the open failed.


reaction.lib/RadioButtonsA

   NAME
       RadioButtonsA -- Make a linked list of radiobuttons
       RadioButtons -- varags stub for RadioButtonsA

   SYNOPSIS
       list = RadioButtonsA( array )
       list = RadioButtons( label, ... )
       struct List *RadioButtonsA( STRPTR * )
       struct List *RadioButtons( STRPTR, ... )

   FUNCTION
       Make a linked list of radiobutton nodes from the NULL terminated
       label array. The labels are not copied, so they must stay
       valid until the list is free'd.

   INPUTS
       array -- a NULL terminated array of string pointers.

   RESULTS
       list -- a linked list of radiobutton nodes


realtime.doc

     CreatePlayer()
     DeletePlayer()
     ExternalSync()
     FindConductor()
     GetPlayerAttrsA()
     LockRealTime()
     NextConductor()
     SetConductorState()
     SetPlayerAttrs()
     UnlockRealTime()


realtime.library/CreatePlayer

   NAME
    CreatePlayerA -- create a player and link it to a conductor. (V37)
    CreatePlayer -- varargs stub for CreatePlayerA(). (V37)

   SYNOPSIS
    player = CreatePlayerA(tagList);
    D0                     A0

    struct Player *CreatePlayerA(struct TagItem *);

    player = CreatePlayer(firstTag, ...);

    struct Player *CreatePlayer(Tag, ...);

   FUNCTION
    Creates a player structure with the desired attributes.

   INPUTS
    tagList - pointer to an array of tags providing optional extra
          parameters, or NULL

   TAGS
    PLAYER_Name (STRPTR) - name of the player (generally the
            application's name). Default is no name. (V37)

    PLAYER_Hook (struct Hook *) - function to call when time changes
            occur. Default is no function. The Hook is called
            with:

                A0 - address of Hook structure
                A1 - message, currently pmTime or pmState
                        A2 - address of Player structure

            Note that your hook function is not necessarily called
            TICK_FREQ times per second. This is the maximum number
            of times it can be called. (V37)

    PLAYER_Priority (BYTE) - priority for the player, from -128 to +127.
            Default is 0. (V37)

    PLAYER_Conductor (STRPTR) - name of the conductor to link with. If
            this conductor doesn't exist, it is created
            automatically. If ~0 is passed, creates a private
            conductor. (V37)

    PLAYER_Ready (BOOL) - set/clear the "ready" flag. Default is FALSE.
            (V37)

    PLAYER_AlarmTime (LONG) - sets this player's alarm time, and the
            PLAYERF_ALARMSET flag. (V37)

    PLAYER_Alarm (BOOL) - if TRUE sets the PLAYERF_ALARMSET flag, FALSE
            clears the flag. Default is FALSE. (V37)

    PLAYER_AlarmSigTask (struct Task *) - task to signal on notify or
            alarm. Default is no task. Having no task automatically
            forces the PLAYERF_ALARMSET flag off. (V37)

    PLAYER_AlarmSigBit (BYTE) - signal bit to use on alarm or -1 to
            disable. Default is -1. Having a signal bit of -1
            automatically forces the PLAYERF_ALARMSET flag
            off. (V37)

    PLAYER_Quiet (BOOL) - when TRUE, this player is ignored. Mainly
            used by external sync applications. Default is FALSE.
            (V37)

    PLAYER_UserData (VOID *) - sets the player's UserData value.
            Default is NULL. (V37)

    PLAYER_ID (UWORD) - sets the player's ID value. Default is 0. (V37)

    PLAYER_Conducted (BOOL) - if TRUE sets the PLAYERF_CONDUCTED flag,
            FALSE clears the flag. Default is FALSE. (V37)

    PLAYER_ExtSync (BOOL) - if TRUE, attempts to become external sync
            source. (V37)

    PLAYER_ErrorCode (LONG *) - optional pointer to a longword which
            will receive an error code whenever this function
            fails. Possible error values currently include:
              RTE_NOMEMORY - memory allocation failed
              RTE_NOTIMER  - timer (CIA) allocation failed

   RESULTS
    player - a pointer to a Player structure on success or NULL on
         failure. When NULL is returned, an error code can be returned
         in the longword variable pointed to by the optional
         PLAYER_ErrorCode tag.

   SEE ALSO
    DeletePlayer(), GetPlayerAttrs(), SetPlayerAttrs()


realtime.library/DeletePlayer

   NAME
    DeletePlayer -- delete a player. (V37)

   SYNOPSIS
    DeletePlayer(player);
                 A0

    VOID DeletePlayer(struct Player *);

   FUNCTION
    Deletes the specified player.

    Flushes the conductor that the player was connected to if this
    is the last player connected to that conductor.

   INPUTS
    player - Player structure to delete, as allocated by
         CreatePlayer(). May be NULL, in which case this function
         does nothing.

   SEE ALSO
    CreatePlayer()


realtime.library/ExternalSync

   NAME
    ExternalSync -- provide external source clock for a player's
            conductor. (V37)

   SYNOPSIS
    result = ExternalSync(player, minTime, maxTime);
    D0		      A0      D0       D1

    BOOL ExternalSync(struct Player *, LONG, LONG);

   FUNCTION
    Allows external applications to constrain conductor time between
    minTime and maxTime, with the restraint that time can never run
    backwards. Does nothing if the given player is not the
    current External Sync source.

   INPUTS
    player - player referencing the conductor to change
    minTime, maxTime - time constraints

   RESULTS
    result - TRUE if everything went OK, FALSE if the player is not the
         current sync source or there is no conductor for the player.


realtime.library/FindConductor

   NAME
    FindConductor -- find a conductor by name. (V37)

   SYNOPSIS
    conductor = FindConductor(name);
    D0			  A0

    struct Conductor *FindConductor(STRPTR);

   FUNCTION
    Returns the conductor with the given name or NULL if not found.

    The conductor list must be locked before calling this function. This
    is done by calling LockRealTime(RT_CONDUCTORS).

   INPUTS
    name - name of conductor to find.

   RESULTS
    conductor - pointer to a Conductor structure, or NULL if not found.

   SEE ALSO
    NextConductor(), LockRealTime(), UnlockRealTime()


realtime.library/GetPlayerAttrsA

   NAME
    GetPlayerAttrsA -- get the attributes of a player. (V37)
    GetPlayerAttrs -- varargs stub for GetPlayerAttrsA(). (V37)

   SYNOPSIS
    numProcessed = GetPlayerAttrsA(player, tagList);
    D0                             A0      A1

    ULONG GetPlayerAttrsA(struct Player *, struct TagItem *);

    numProcessed = GetPlayerAttrs(player, firstTag, ...);

    ULONG GetPlayerAttrs(struct Player *, Tag, ...);

   FUNCTION
    Retrieves the attributes of the specified player, according to the
    attributes chosen in the tag list. For each entry in the tag list,
    ti_Tag identifies the attribute, and ti_Data is a pointer to
    the longword variable where you wish the result to be stored.

   INPUTS
    player - pointer to the player in question. May be NULL, in which case
             this function returns 0
    tagList - pointer to TagItem list.

   TAGS
    PLAYER_Name (STRPTR) - return the name of the player, or NULL
            if this is an unnamed player. (V37)

    PLAYER_Hook (struct Hook *) - returns a pointer to the current
            function called when time changes occur, or NULL
            if no function is currently installed. (V37)

    PLAYER_Priority (BYTE) - returns the priority for the player. (V37)

    PLAYER_Conductor (STRPTR) - returns the name of the conductor this
            player is currently linked with, or NULL if the
            player is not linked to a conductor. (V37)

    PLAYER_Ready (BOOL) - gets the state of the "ready" flag. (V37)

    PLAYER_AlarmTime (LONG) - gets the current alarm time for this
            player. (V37)

    PLAYER_Alarm (BOOL) - returns TRUE if this player's alarm is
            currently on. (V37)

    PLAYER_AlarmSigTask (struct Task *) - returns a pointer to the task to
            signal on notify or alarm, or NULL if there is no
            task to signal. (V37)

    PLAYER_AlarmSigBit (BYTE) - returns the signal bit to use on alarm or
            -1 if no signal. (V37)

    PLAYER_Quiet (BOOL) - returns TRUE if this player is currently being
            ignored. FALSE if not. (V37)

    PLAYER_UserData (VOID *) - returns the current value of this player's
            UserData. (V37)

    PLAYER_ID (UWORD) - gets the value of this player's ID. (V37)

    PLAYER_Conducted (BOOL) - returns TRUE if this player is currently
            being conducted. (V37)

    PLAYER_ExtSync (BOOL) - returns TRUE if this player is the current
            external sync source. (V37)

   RESULTS
    numProcessed - the number of attributes successfully filled in.

   SEE ALSO
    CreatePlayer(), SetPlayerAttrs()


realtime.library/LockRealTime

   NAME
    LockRealTime -- prevent other tasks from changing internal structures.
            (V37)

   SYNOPSIS
    lockHandle = LockRealTime(lockType);
    D0                        D0

    APTR LockRealTime(ULONG);

   FUNCTION
    This routine will lock the internal sempahores in the RealTime library.
    If they are already locked by another task, this routine will wait
    until they are free.

   INPUTS
    lockType - the internal list to lock. Only RT_CONDUCTORS is
           currently defined.

   RESULT
    handle - if lockType is valid, returns a value that must be passed
         later to UnlockRealTime() to unlock the list. Returns NULL
         if passed an invalid lock type.

   SEE ALSO
    UnlockRealTime()


realtime.library/NextConductor

   NAME
    NextConductor -- return the next conductor on realtime.library's
             conductor list. (V37)

   SYNOPSIS
    conductor = NextConductor(previousConductor);
    D0			  A0

    struct Conductor *NextConductor(struct Conductor *);

   FUNCTION
    Returns the next conductor on realtime.library's conductor list. If
    previousConductor is NULL, returns the first conductor in the list.
    Returns NULL if no more conductors.

    The conductor list must be locked before calling this function. This
    is done by calling LockRealTime(RT_CONDUCTORS).

   INPUTS
    previousConductor - previous conductor or NULL to get first conductor.

   RESULTS
    conductor - next conductor on the list, or NULL if no more.

   SEE ALSO
    FindConductor(), LockRealTime(), UnlockRealTime()


realtime.library/SetConductorState

   NAME
    SetConductorState -- change the play state of a player's
                 conductor. (V37)

   SYNOPSIS
    result = SetConductorState(player, state, time);
    D0			   A0	   D0     D1

    LONG SetConductorState(struct Player *, ULONG, LONG);

   FUNCTION
    Changes the play state of the conductor referenced by the
    player. The states can be CONDSTATE_STOPPED, CONDSTATE_PAUSED,
    CONDSTATE_LOCATE, CONDSTATE_RUNNING, or the special value
    CONDSTATE_METRIC which asks the highest priority conducted node
    to do a CONDSTATE_LOCATE, or the special value CONDSTATE_SHUTTLE
    which informs the players that the clock value is changing, but the
    clock isn't actually running. Note that going from CONDSTATE_PAUSED
    to CONDSTATE_RUNNING does not reset the cdt_ClockTime of the
    conductor.

   INPUTS
    player - player referencing the conductor to change
    state - new play state of conductor
    time - start time offset in realtime.library heartbeat units

   RESULTS
    result - 0 if everything went OK, or a realtime.library error code
         if an error occured. These currently include RTE_PLAYING
         and RTE_NOCONDUCTOR.


realtime.library/SetPlayerAttrs

   NAME
    SetPlayerAttrsA -- set the attributes of a player. (V37)
    SetPlayerAttrs -- varargs stub for SetPlayerAttrsA(). (V37)

   SYNOPSIS
    result = SetPlayerAttrsA(player, tagList);
    D0                       A0      A1

    BOOL SetPlayerAttrsA(struct Player *, struct TagItem *);

    result = SetPlayerAttrs(player,firstTag, ...);

    BOOL SetPlayerAttrs(struct Player *, Tag, ...);

   FUNCTION
    Changes the attributes of the specified player, according to the
    attributes chosen in the tag list. If an attribute is not provided
    in the tag list, its value remains unchanged.

   INPUTS
    player - player to set the attributes of.
    tagList - pointer to an array of tags specifying the attributes
          to change, or NULL.

   TAGS
    PLAYER_Name (STRPTR) - name of the player (generally the
            application's name). (V37)

    PLAYER_Hook (struct Hook *) - function to call when time changes
            occur. The Hook is called
            with:

                A0 - address of Hook structure
                A1 - message, currently pmTime or pmState
                        A2 - address of Player structure

            Note that your hook function is not necessarily called
            TICK_FREQ times per second. This is the maximum number
            of times it can be called. (V37)

    PLAYER_Priority (BYTE) - priority for the player, from -128 to +127.
            (V37)

    PLAYER_Conductor (STRPTR) - name of the conductor to link with. If
            NULL, delink from conductor. (V37)

    PLAYER_Ready (BOOL) - set/clear the "ready" flag. (V37)

    PLAYER_AlarmTime (LONG) - sets this player's alarm time, and the
            PLAYERF_ALARMSET flag. (V37)

    PLAYER_Alarm (BOOL) - if TRUE sets the PLAYERF_ALARMSET flag, FALSE
            clears the flag. (V37)

    PLAYER_AlarmSigTask (struct Task *) - task to signal on notify or
            alarm. Setting this to NULL automatically clears the
            PLAYERF_ALARMSET flag. (V37)

    PLAYER_AlarmSigBit (BYTE) - signal bit to use on alarm or -1 to
            disable. Setting this to -1 automatically clears the
            PLAYERF_ALARMSET. (V37)

    PLAYER_Quiet (BOOL) - when TRUE, this player is ignored. Mainly
            used by external sync applications. (V37)

    PLAYER_UserData (VOID *) - sets this player's UserData value. (V37)

    PLAYER_ID (UWORD) - sets this player's ID value. (V37)

    PLAYER_Conducted (BOOL) - if TRUE sets the PLAYERF_CONDUCTED flag,
            FALSE clears the flag. (V37)

    PLAYER_ExtSync (BOOL) - if TRUE, attempt to become external sync
            source. If FALSE, release external sync. (V37)

    PLAYER_ErrorCode (LONG *) - optional pointer to a longword which
            will receive an error code whenever this function
            fails. Possible error values currently include:
              RTE_NOMEM   - memory allocation failed
              RTE_NOTIMER - timer (CIA) allocation failed

   RESULTS
    result - TRUE if all went well, FALSE if there was an error.
         When an error occurs, an error code can be returned
         in the longword variable pointed to by the optional
         PLAYER_ErrorCode tag.

   SEE ALSO
    CreatePlayer(), DeletePlayer(), GetPlayerAttrs()


realtime.library/UnlockRealTime

   NAME
    UnlockRealTime -- unlock internal lists. (V37)

   SYNOPSIS
    UnlockRealTime(lockHandle);
                   A0

    VOID UnlockRealTime(APTR);

   FUNCTION
    Undoes the effects of LockRealTime().

   INPUTS
    lockHandle - value returned by LockRealTime(). May be NULL.

   SEE ALSO
    LockRealTime()


resource.doc

     --background--
     RL_CloseResource()
     RL_DisposeGroup()
     RL_DisposeObject()
     RL_GetObjectArray()
     RL_NewGroupA()
     RL_NewObjectA()
     RL_OpenResource()
     RL_SetResourceScreen()


resource.library/--background--

   NAME
    resource.library -- resource handling for BOOPSI classes

   DESCRIPTION
    The resource.library offers an API to handle resource objects
    (an object file created from ReActor or similar BOOPSI creator
    tools). One can create BOOPSI objects and groups of BOOPSI
    objects and resource tracking is completly done by
    resource.library.

    A resource object ist an AmigaDOS hunk object file that contains
    data structures with all necessary informations for creating BOOPSI
    objects. Special class informations allows to handle intuition
    BOOPSI objects.

    Strings are automatically localized if needed. The resource
    objects contains references to labels (for the locale string IDs)
    and strings (for the default strings) which has to be linked with
    symbol definitions from the application (a new catcomp version is
    available to create assembler source files for those definitions).

    The default label for the resource object is _RCTResource (defined
    by ReActor). Use a statement like

        extern char RCTResource[];

    to access the resource object. The variable RCTResource has to be
    used as the first argument to RL_OpenResource.


resource.library/RL_CloseResource

   NAME
    RL_CloseResource - close and free a resource object (V44)

   SYNOPSIS
    RL_CloseResource(resource)
                       A0

    VOID RL_CloseResource(RESOURCEFILE);

   FUNCTION
    This routine closes a resource object that was previously opened with
    RL_OpenResource. It frees all objects and object groups.

   INPUTS
    resource -- a pointer to a resource. A value of NULL is acceptable
                which means a no-op.

   RESULTS

   SEE ALSO
    resource.library/RL_OpenResource


resource.library/RL_DisposeGroup

   NAME
    RL_DisposeGroup - dispose a group of objects (V44)

   SYNOPSIS
    RL_DisposeGroup(resource, group)
                     A0        A1

    VOID RL_DisposeGroup(RESOURCEFILE, Object **);

   FUNCTION
    Disposes a group of objects that was allocated with RL_NewGroupA.
    Never dispose a object from the group with RL_DisposeObject,
    DisposeObject or DisposeDTObject.

   INPUTS
    resource -- a pointer to a resource
    group -- a pointer to an array of pointers to Object. A value of
             NULL is acceptable which means a no-op.

   RESULTS

   SEE ALSO
    resource.library/RL_NewGroupA


resource.library/RL_DisposeObject

   NAME
    RL_DisposeObject - dispose an object (V44)

   SYNOPSIS
    RL_DisposeObject(resource, object)
                      A0        A1

    VOID RL_DisposeObject(RESOURCEFILE, Object *);

   FUNCTION
    Dispose an object that was allocated with RL_NewObjectA.

   INPUTS
    resource -- a pointer to a resource
    object -- a pointer to an Object. A value of NULL is acceptable which
              means a no-op.

   RESULTS

   SEE ALSO
    resource.library/RL_NewObjectA


resource.library/RL_GetObjectArray

   NAME
    RL_GetObjectArray - get a pointer to a group of objects (V44)

   SYNOPSIS
    group = RL_GetObjectArray(resource,object,id)
     D0                        A0       A1    D0

    Object **RL_GetObjectArray(RESOURCEFILE, Object *, RESOURCEID);

   FUNCTION
    If you allocated an Object using RL_NewObjectA a lot of additional
    Objects and group of Objects may be allocated automatically. This
    functions returns a pointer to a group of objects with a given group
    ID.

    Never release the group with RL_DisposeGroupA. The group is released
    automatically if the object is released

   INPUTS
    resource -- a pointer to a resource
    object -- a pointer to an Object
    id -- a numeric id of a object group

   RESULTS
    group -- a pointer to an array of pointers to Object

   SEE ALSO
    resource.library/RL_NewObjectA
    resource.library/RL_NewGroupA


resource.library/RL_NewGroupA

   NAME
    RL_NewGroupA - allocate a group of objects (V44)

   SYNOPSIS
    group = RL_NewGroupA(resource,id,taglist)
     D0                   A0      D0  A1

    Object **RL_NewGroupA(RESOURCEFILE, RESOURCEID, struct TagItem *);

   FUNCTION
    The routine allocates a group of objects with a given numeric id.

   INPUTS
    resource -- a pointer to a resource
    id -- a numeric id
    taglist -- a pointer to an array of TagItem. Currently no tags are
               defined.

   RESULTS
    group -- a pointer to an array of pointers to Object or NULL.

   SEE ALSO
    resource.library/RL_DisposeGroup
    resource.library/RL_GetObjectArray


resource.library/RL_NewObjectA

   NAME
    RL_NewObjectA - create a new object (V44)

   SYNOPSIS
    object = RL_NewObjectA(resource,id,taglist)
     D0                     A0      D0  A1

    Object *RL_NewObjectA(RESOURCEFILE, RESOURCEID, struct TagItem *);;

   FUNCTION
    The routine creates a new object with a given numeric id.

   INPUTS
    resource -- a pointer to a resource
    id -- a numeric id
    taglist -- a pointer to an array of TagItem. The tags are moved
               forward to the call of NewObjectA, NewDTObjectA or
               whatever is called to create the object

   RESULTS
    object -- a pointer to an Object or NULL.

   SEE ALSO
    intuition.library/NewObjectA
    datatypes.library/NewDTObjectA
    resource.library/RL_DisposeObject


resource.library/RL_OpenResource

   NAME
    RL_OpenResource - open a resource (V44)

   SYNOPSIS
    resource = RL_OpenResource(resobject, screen, catalog)
     D0                         A0         A1      A2

    RESOURCEFILE RL_OpenResource(APTR, struct Screen *, struct Catalog *);

   FUNCTION
    This routine opens a resource object.

    If you give a NULL for the parameter screen do not call RL_NewObjectA
    or RL_NewGroupA. You must first set a screen with
    RL_SetResourceScreen.

   INPUTS
    resobject -- a pointer to a resource object
    screen -- a pointer to a Screen. This may be NULL
    catalog -- a pointer to a Catalog. This may be NULL

   RESULTS
    resource -- a pointer to a resource or NULL

   EXAMPLE

    extern char RCTResource[];
    struct Screen *screen;

    screen = LockPubScreen(NULL);
    RESOURCEFILE resource = RL_OpenResource(RCTResource, screen, NULL);
    if (resource)
    {
        /* create your objects here */
    }
    RL_CloseResource(resource);
    UnlockPubScreen(NULL,screen);

   SEE ALSO
    intuition.library/LockPubScreen
    intuition.library/OpenScreenTagList
    locale.library/OpenCatalogA
    resource.library/RL_CloseResource
    resource.library/RL_SetResourceScreen


resource.library/RL_SetResourceScreen

   NAME
    RL_SetResourceScreen - sets or clears the screen (V44)

   SYNOPSIS
    success = RL_SetResourceScreen(resource, screen)
     D0                             A0        A1

    BOOL RL_SetResourceScreen(RESOURCEFILE, struct Screen *);

   FUNCTION
    This routine sets or clears the screen of the resource. You must clear
    the screen before you close or unlock it. You must set a valid screen
    before you call NewObjectA or NewGroupA.

    Setting a new screen does not mean that the allocated objects are
    automatically adapt to the new screen. This function only controls
    the internal housekeeping of the screen (and related structures). If
    you cannot adapt the allocated objects to a new screen (like setting
    an attribute with the new screen value) you must dispose and
    recreate them.

    If you set the same screen pointer as was before this function does
    nothing but returns TRUE.

   INPUTS
    resource -- a pointer to a resource
    screen --  a pointer to a Screen or NULL

   RESULTS
    success -- TRUE if the screen is successfully set or cleared.

   SEE ALSO
    resource.library/RL_OpenResource


rexxsyslib.doc

     ClearRexxMsg()
     CreateArgstring()
     CreateRexxMsg()
     DeleteArgstring()
     DeleteRexxMsg()
     FillRexxMsg()
     IsRexxMsg()
     LengthArgstring()
     LockRexxBase()
     UnlockRexxBase()


scroller_gc.doc

     --datasheet--
     SCROLLER_GetClass()


scroller_gc/--datasheet--

    NAME
        scroller_gc -- create scroller BOOPSI objects

    SUPERCLASS
        gadgetclass

    REQUIRES
        bevel.image, glyph.image

    DESCRIPTION
        The scroller gadget is a propgclass wrapper class and is used
        to create proportional scroller or linear slider gadgets.
        To create a linear slider, SCROLLER_Visible must be set to 1, and
        SCROLLER_Top will range in value from 0 to SCROLLER_Total - 1.

        The IntuiMessage.Code field will contain the SCROLLER_Top
        attribute, cast to a WORD.

        Advantages that this class provides are:

         > Supports window relativity.

         > Supports OS 3.0 BOOPSI Notification/Update.

         > Special signaling ability.

         > Optional scroller arrow buttons.

         > Supports usage in window boarders.

    METHODS
        OM_NEW -- Create the scroller gadget. Also allocates an
            instance of the bevel and glyph image classes.
            Passed to superclass then calls OM_SET.

        OM_SET -- Set object attributes. Passed to superclass first.

        OM_DISPOSE -- Frees up the scroller gadget as well as the
            bevel and glyph image instances. Passed to superclass last.

        OM_UPDATE -- Set object notification attributes. Passed to
            superclass first.

        GM_RENDER -- Renders the gadget imagery. Overrides the superclass.

        GM_GOACTIVE -- Handles activation. Overrides the superclass.

        GM_HANDLEINPUT -- Handles input events once active. Overrides
            the superclass.

        GM_GOINACTIVE -- Overrides the superclass. Handles deactivation.

        GM_HELPTEST -- Test if mouse is within gadget hit area.

        GM_HITTEST -- Test if mouse is within gadget hit area.

        GM_DOMAIN -- Returns GDOMAIN_MINIMUM and GDOMAIN_MAXIMUM dimensions.

        All other methods are passed to the superclass.

    ATTRIBUTES
        SCROLLER_Top (LONG)
            Set the current top value of the scroller within the
            proportional range. (V40)

            Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET)

        SCROLLER_Visible (LONG)
            Set the visible portion of the proportional range. (V40)

            (OM_NEW, OM_SET, OM_UPDATE, OM_GET)

        SCROLLER_Total (LONG)
            Set the total range of the scroller. (V40)

            Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET)

        SCROLLER_Orientation
            Define orientation of the scroller.

            Accepted values as defined in <gadgets/scroller.h> are:

                SORIENT_VERT
                SORIENT_HORIZ

            Defines are found in <gadgets/scroller.h> and are synomyms for
            the propgclass FREEVERT and FREEHORIZ. (V40)

            Applicability is (OM_NEW, OM_GET)

        SCROLLER_Arrows (BOOL)
            Enable rendering of optional scroller arrows. (V40)

            Applicability is (OM_NEW, OM_GET)

        SCROLLER_ArrowDelta (WORD) (V41)
            Allows you to change the amount that clicking an arrow causes
            the scroller to move by.

            Defaults to 1.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE, OM_GET)

        SCROLLER_SignalTask (struct Task *)  (V42)
            Signal the specified Task while scroller is active.  This is
            very useful to reduce the load on input.device because you can
            render from some other task (application, or anything else)
            that waits for this signal and then GetAttr() SCROLLER_Top, etc.

            Defaults to NULL (no signaling).

            Applicability is (OM_NEW, OM_SET)

        SCROLLER_SignalTaskBit (ULONG)  (V42)
            Signal with this Bit. See also; SCROLLER_SignalTask.

            Applicability is (OM_NEW, OM_SET)


scroller_gc/SCROLLER_GetClass

    NAME
        SCROLLER_GetClass -- Gets the pointer to the scroller class.

    SYNOPSIS
        scroller_class = SCROLLER_GetClass();
        D0

        Class * SCROLLER_GetClass(VOID);

    FUNCTION
        Obtains the pointer to the Scroller gadget class for use with
        NewObject().  This function always returns a valid pointer so
        you do not need to check it.  The reason is that if the library
        opens fine, then the pointer returned is already setup.  (Of course
        this implies that if opening the library fails, you shouldn't be
        calling this.)

        Note that this function does not create the class, that is done
        when the class library is opened.

    INPUTS
        Nothing.

    RESULT
        scroller_class - Pointer to the Scroller gadget class.

    SEE ALSO


serial.doc

     AbortIO()
     BeginIO()
     CloseDevice()
     CMD_CLEAR
     CMD_FLUSH
     CMD_READ
     CMD_RESET
     CMD_START
     CMD_STOP
     CMD_WRITE
     OpenDevice()
     SDCMD_BREAK
     SDCMD_QUERY
     SDCMD_SETPARAMS


serial.device/CloseDevice

   NAME
       CloseDevice -- close the serial port

   SYNOPSIS
       CloseDevice(deviceNode)
                    A1
   FUNCTION
       This is an exec call that terminates communication with the
       serial device.  Upon closing, the device's input buffer is freed.

       Note that all IORequests MUST be complete before closing.
    If any are pending, your program must AbortIO() then WaitIO()
       to complete them.

   INPUTS
       deviceNode - pointer to the device node, set by Open

   SEE ALSO
       serial.device/OpenDevice()


serial.device/OpenDevice

   NAME
       OpenDevice -- Request an opening of the serial device.

   SYNOPSIS
       error = OpenDevice("serial.device", unit, ioRequest, flags)
       D0                  A0              D0    A1         D1

    BYTE OpenDevice(STRPTR, ULONG, struct IOExtSer *, ULONG);

   FUNCTION
       This is an exec call.  Exec will search for the serial.device, and
       if found, will pass this call on to the device.

       Unless the shared-access bit (bit 5 of io_SerFlags) is set,
       exclusive use is granted and no other access to that unit is
       allowed until the owner closes it.  All the serial-specific fields
       in the ioRequest are initialized to their most recent values (or
       the Preferences default, for the first time open).

       If support of 7-wire handshaking (i.e. RS232-C CTS/RTS protocol)
       is required, use the serial.device/SDCMD_SETPARAMS command.
    This feature should also be specified at inital OpenDevice() time.

   INPUTS
       "serial.device"	- pointer to literal string "serial.device"
       unit      	- Must be zero, or a user setable unit number.
              (This field is used by multiple port controllers)
                         Zero specifies the default serial port.
       ioRequest 	- pointer to an ioRequest block of size io_ExtSerSize
                         to be initialized by the serial.device.
                         (see devices/serial.h for the definition)
                           NOTE use of io_SerFlags (see FUNCTION above)
        IMPORTANT: The ioRequest block MUST be of size io_ExtSerSize,
               and zeroed (with the exeptions as noted)!
       flags     	- Must be zero for future compatibility

   RESULTS
       D0 	  - same as io_Error
       io_Error  - If the Open succeded, then io_Error will be null.
                   If the Open failed, then io_Error will be non-zero.
       io_Device - A pointer to whatever device will handle the calls
                   for this unit.  This pointer may be different depending
                   on what unit is requested.

   BUGS
    If 7-wire handshaking is specified, a timeout "feature" is enabled.
    If the device holds off the computer for more than about 30-60
    seconds, the device will return the write request with the error
    SerErr_TimerErr.  Don't depend on this, however.  If you want a timeout,
    set up the timer.device and wait for either timer, or serial IO to
    complete.

    On open, the serial.device allocates the misc.resource for the
    serial port.  It does not return it until the serial.device is
    expunged from memory.  It should return it when no more openers
    exist.   This code can force a specified device to try and
    expunge.  Of course, if the device is in use nothing will happen:

    #include "exec/types.h"
    #include "exec/execbase.h"
    #include "proto/exec.h"

    void FlushDevice(char *);
    extern struct ExecBase *SysBase;

    void main()
    {
        FlushDevice("serial.device");	/* or parallel.device */
    }

    /*
     * Attempts to flush the named device out of memory.
     * If it fails, no status is returned; examination of
     * the problem will reveal that information has no
     * valid use after the Permit().
     */
    void FlushDevice(name)
    char  *name;
    {
    struct Device *result;

        Forbid();
        if( result=(struct Device *)FindName(&SysBase->DeviceList,name) )
        RemDevice(result);
        Permit();
    }

   SEE ALSO
    serial.device/CloseDevice()
    serial.device/SDCMD_SETPARAMS
    devices/serial.h


serial.device/SDCMD_SETPARAMS

   NAME
       SetParams -- change parameters for the serial port

   FUNCTION
       This command allows the caller to change parameters for the
       serial device. Except for xON-xOFF enable/disable, it will
       reject a setparams call if any reads or writes are active
       or pending.
          Note specifically:

    1. Valid input for io_Baud is between 112 and 292000 baud inclusive;
       asynchronous i/o above 32KB (especially on a busy system) may
       be ambitious.
    2. The EOFMODE and QUEUEDBRK bits of io_SerFlags can be set/reset
       in the io_Rqst block without a call to SetParams. The SHARED
       and 7WIRE bits of io_SerFlags can be used in OpenDevice calls.
       ALL OTHER PARAMETERS CAN ONLY BE CHANGED BY THE SetParams
       COMMAND.
    3. RBufLen must be at least 64.  The buffer may be any multiple of
    64 bytes.
    4. If not used, io_ExtFlags MUST be set to zero.
    5. xON-xOFF is by default enabled. The XDISABLED bit is the only
       parameter that can be changed via a SetParams call while the
       device is active. Note that this will return the value
       SerErr_DevBusy in the io_Error field.

    xON/xOFF handshaking is inappropriate for certain binary transfer
    protocalls, such as Xmodem.  The binary data might contain the
    xON (ASCII 17) and xOFF (ASCII 19) characters.

    6. If trying to run MIDI, you should set the RAD_BOOGIE bit of
       io_SerFlags to eliminate unneeded overhead. Specifically, this skips
       checks for parity, x-OFF handling, character lengths other than
       8 bits, and testing for a break signal. Setting RAD_BOOGIE will
       also set the XDISABLED bit.
       Note that writing data (that's already in MIDI format) at MIDI rates
       is easily accomplished. Using this driver alone for MIDI reads may,
       however, may not be reliable, due to MIDI timestamping requirements,
       and possibility of overruns in a busy multitasking and/or display
       intensive environment.
    7. If you select mark or space parity (see io_ExtFlags in serial.h),
       this will cause the SERB_PARTY_ON bit to be set, and the setting
       of SERB_PARTY_ODD to be ignored.
    8. For best results, set the RAD_BOOGIE flag whenever possible.  See
    #6 for details.
    9. Note that at this time parity is *not* calculated for the xON-xOFF
    characters.  If you have a system that is picky about the parity of
    these, you must set your own xON-xOFF characters in io_CtlChar.
   10. 7WIRE (CTS/RTS) handshake is bi-directional.  The external side
    is expected to drop CTS several character times before the external
    buffer is full.  The Amiga will drop RTS several character times
    before the Amiga's buffer is full.

   IO REQUEST
       io_Message      mn_ReplyPort initialized
       io_Device       preset by OpenDevice
       io_Unit         preset by OpenDevice
       io_Command      SDCMD_SETPARAMS (0x0B)
              NOTE that the following fields are filled in by Open
                       to reflect the serial device's current configuration.
       io_CtlChar      a longword containing byte values for the
                       xON,xOFF,INQ,ACK fields (respectively)
                       (INQ/ACK not used at this time)
       io_RBufLen      length in bytes of input buffer
              NOTE that any change in buffer size causes the
                       current buffer to be deallocated and a new,
                       correctly sized one to be allocated. Thusly,
                       the CONTENTS OF THE OLD BUFFER ARE LOST.
       io_ExtFlags     additional serial flags (bitdefs in devices/serial.h)
            mark & space parity may be specified here.
       io_Baud         baud rate for reads AND writes. (See 1 above)
       io_BrkTime      duration of break signal in MICROseconds
       io_TermArray    ASCII descending-ordered 8-byte array of
                       termination characters. If less than 8 chars
                       used, fill out array w/lowest valid value.
                       Terminators are checked only if EOFMODE bit of
                       io_Serflags is set. (e.g. x512F040303030303 )
       io_ReadLen      number of bits in read word (1-8) not including parity
       io_WriteLen     number of bits in write word (1-8) "      "       "
       io_StopBits     number of stop bits (0, 1 or 2)
       io_SerFlags     see devices/serial.h for bit equates, NOTE that x00
                       yields exclusive access, xON/OFF-enabled, no
                       parity checking, 3-wire protocol and TermArray
                       inactive.

   RESULTS
       Error -- if the SetParams succeded, then Error will be null.
           If the SetParams failed, then the Error will be non-zero.

   SEE ALSO
    exec/OpenDevice()


sound_dtc.doc

     sound.datatype()


sound.datatype/sound.datatype

    NAME
        sound.datatype -- root data type for sounds.

    FUNCTION
        The sound.datatype is the super-class for any sound related
        classes.

    METHODS
        OM_NEW -- Create a new sound object.

        OM_GET -- Obtain the value of an attribute.

        OM_SET -- Set the values of multiple attributes.

        OM_UPDATE -- Update the values of multiple attributes.

        OM_DISPOSE -- Dispose of a sound object.

        GM_LAYOUT -- Layout the object and notify the application of the
            title and size.

        GM_HITTEST -- Determine if the object has been hit with the
            mouse.

        GM_GOACTIVE -- Tell the object to go active.  On SELECTDOWN, the
            sound will start playing.

        GM_HANDLEINPUT -- Handle input.  Currently input (other than
            SELECTDOWN) doesn't affect the sound.

        GM_RENDER -- Cause the graphic to render.  Currently the graphic
            for the sound is just a static icon.

        DTM_TRIGGER -- Cause an event to occur.  Currently the only
            trigger event is STM_PLAY, which will cause the sound to start
            playing.

            NOTE: Subclasses which support streaming data access may
                  support more than just the STM_PLAY event.

        DTM_COPY -- Copy the entire sound to the clipboard as 8SVX.

            NOTE: Up to and including V40 sound.datatype never stored
                  a valid VoiceHeader with the file. This was fixed in V44.

                  Subclasses which support streaming data access may not
                  support this method.

        DTM_WRITE -- Write the entire sound to a file as 8SVX.

            NOTE: Up to and including V40 sound.datatype never stored
                  a valid VoiceHeader with the file. This was fixed in V44.

                  Subclasses which support streaming data access may not
                  support this method.

    TAGS
        SDTA_VoiceHeader (struct VoiceHeader *) -- Set and get the base
            information for the sound.  VoiceHeader is defined in
            <datatypes/soundclass.h>.

            NOTE: Up to and including V40 sound.datatype never returned
                  a valid VoiceHeader for OM_GET and the VoiceHeader data
                  was ignored in the OM_NEW/OM_SET cases. This was fixed
                  in V44.

            Applicability is (ISG).

        SDTA_Sample (BYTE *) -- Set and get the sound data.  Starting
            with V40 the sample data does not need to be in CHIP memory.
            Starting with V44 the sample data does not need to start
            on a WORD-aligned address. Setting SDTA_Sample to NULL
            will stop sound replay if sound.datatype was started
            playing with a non-NULL SDTA_Sample parameter.

            The SDTA_Sample parameter selects mono playback on any
            sound channel that is currently available.

            NOTE: For streaming sound playback, SDTA_LeftSample,
                  SDTA_RightSample, and SDTA_Sample will all be
                  NULL (V44).

            Applicability is (ISG).

        SDTA_SampleLength (ULONG) -- Length of the sound data in bytes.
            Starting with V44 the sample data does not need to be
            an even number of bytes. Setting SDTA_SampleLength to 0
            will stop sound replay.

            Applicability is (ISG).

        SDTA_Period (UWORD) -- Set and get the period of the sound
            (in timing intervals per sample). This attribute can be
            used to affect a playing sound. Please note that the
            Amiga audio hardware does not reliably support playback
            periods shorter than 124; sound.datatype will limit the
            period to valid intervals (V44).

            Default for this tag is 394.  Applicability is (ISG).

        SDTA_Volume (UWORD) -- Set and get the volume of the sound. This
            attribute can be used to affect a playing sound.

            Valid range is from 0 to 64.  Default for this tag is 64.
            Applicability is (ISG).

        SDTA_Cycles (UWORD) -- Set and get the number of cycles the
            sound will be played.

            Default for this tag is 1.  Applicability is (ISG).

        The following tags are new for V40.

        SDTA_SignalTask (struct Task *) -- Task to signal when the
            is complete, or if SDTA_Continuous is TRUE, when
            the next buffer is needed.

            Default for this tag is NULL. Applicability is (IS).

        SDTA_SignalBit (ULONG) -- Signal mask to use with SDTA_SignalTask
            or 0 to disable.

            NOTE: Due to a bug in sound.datatype V40 SDTA_SignalBit was
                  actually implemented as a signal mask as opposed to a
                  bit number. The documentation now reflects this. If you
                  intend to use a signal bit number instead of the mask,
                  use the new V44 tag SDTA_SignalBitNumber below.

            Default for this tag is 0. Applicability is (IS).

        SDTA_Continuous (BOOL) -- Used to indicate that the sound
            datatype will be fed a continuous stream of data.

            Default for this tag is FALSE. Applicability is (I).

        The following tags are new for V44.

        SDTA_SignalBitMask (ULONG) -- Signal mask to use with SDTA_SignalTask
            or 0 to disable. This tag is an alias for SDTA_SignalBit.

            Default for this tag is 0. Applicability is (IS).

        SDTA_SignalBitNumber (BYTE) -- Signal bit to use with SDTA_SignalTask
            or -1 to disable.

            Default for this tag is -1. Applicability is (IS).

        SDTA_SamplesPerSec (UWORD) -- Set and get the replay frequency of
            a sound (in Hz). This attribute can be used to affect a playing
            sound. Unlike the SDTA_Period tag, which serves the same purpose,
            this tag automatically takes the system clock value into account.
            Please note that the Amiga audio hardware does not reliably
            support playback rates beyond 28,000 samples per second;
            sound.datatype will limit the replay frequency to valid
            intervals.

            Applicability is (ISG).

        SDTA_ReplayPeriod (struct timeval *) -- Get the replay period,
            i.e. the time it takes for the complete sound to be played.
            If the sample size has not been set yet, the timeval tv_sec
            and tv_micro members will be set to 0. If the sample is to
            be played continuously, both timeval members will be set
            to 0xFFFFFFFF.

            Applicability is (G).

        SDTA_Pan (BYTE) -- Set the stereo panning; this must be set to
            a number in the range of -64..64. A value of -64 will
            pan the sound to the left channel, silencing the right
            channel; a value of 64 will pan the sound to the right
            channel and silence the left channel. To center playback,
            use a panning value of 0. The panning value only takes
            effect if a stereo sound is being played.

            Default for this tag is 0. Applicability is (IS).

        SDTA_FreeSampleData (BOOL) -- This tag controls whether
            sound.datatype will call FreeVec() on the sample data
            attached to an object. If the SDTA_Continuous attribute was
            set to TRUE, sound.datatype will never free any data attached
            to an object. It is safe to attach the same sample to
            more than one channel as sound.datatype will make sure that
            no sample data is freed twice.

            Default for this tag is FALSE. Applicability is (IS).

        SDTA_LeftSample (BYTE *) -- Set and get the left channel sound data.
            The sample data does not need to be in CHIP memory and does
            not need to start on a WORD-aligned address. Setting
            SDTA_LeftSample to NULL will stop sound replay if sound.datatype
            was started playing with a non-NULL SDTA_LeftSample parameter.

            The SDTA_LeftSample parameter alone selects mono playback on
            any left sound channel that is currently available. Used together
            with the SDTA_RightSample parameter, stereo playback on any
            available stereo channels is selected.

            The SDTA_LeftSample parameter takes precedence over the
            the SDTA_Sample parameter.

            NOTE: For streaming sound playback, SDTA_LeftSample,
                  SDTA_RightSample, and SDTA_Sample will all be
                  NULL (V44).

            Applicability is (ISG).

        SDTA_RightSample (BYTE *) -- Set and get the right channel sound data
.
            The sample data does not need to be in CHIP memory and does
            not need to start on a WORD-aligned address. Setting
            SDTA_RightSample to NULL will stop sound replay if sound.datatype
            was started playing with a non-NULL SDTA_RightSample parameter.

            The SDTA_RightSample parameter alone selects mono playback on
            any right sound channel that is currently available. Used
            together with the SDTA_LeftSample parameter, stereo playback
            on any available stereo channels is selected.

            The SDTA_RightSample parameter takes precedence over the
            the SDTA_Sample parameter.

            NOTE: For streaming sound playback, SDTA_LeftSample,
                  SDTA_RightSample, and SDTA_Sample will all be
                  NULL (V44).

            Applicability is (ISG).

        SDTA_SyncSampleChange (BOOL) -- If SDTA_Continuous was set to TRUE,
            sound.datatype will expect a continuous stream of data to be
            played. By specifying "SDTA_SyncSampleChange,TRUE" you request
            that new sound data will be played only if the old data has
            been played completely (otherwise, playback would restart
            immediately with the new sound). If playback is currently in
            progress, the Task to change the sample data will be made to
            wait until playback of the old sound has finished.

            Default for this tag is FALSE. Applicability is (IS).

        DTA_Immediate (BOOL) -- Select and query whether playback should
            start immediately after the object has passed the layout
            process.

            Default for this tag is FALSE. Applicability is (ISG).

        DTA_Repeat (BOOL) -- Select and query whether playback should
            loop indefinitely, regardless of the current SDTA_Cycles
            settings.

            Default for this tag is FALSE. Applicability is (ISG).

    NOTES
        You cannot switch between mono and stereo playback on the fly while
        the sound is still playing. First, stop the sound, then change the
        SDTA_Sample/SDTA_LeftSample/SDTA_LeftSample attributes.

        The sound.datatype implementation has been cleaned up for V44 to
        allow for streaming subclasses to be written. Such subclasses will
        always return NULL when their SDTA_LeftSample, SDTA_RightSample and
        SDTA_Sample attributes are queried. However, they will never return
        0 for the SDTA_SampleLength and SDTA_SamplesPerSec attributes since
        these can be used to calculate the length of the entire sample.
        Streaming subclasses will respond to the DTM_TRIGGER method, to
        start, stop playback, etc. but may not support any other methods
        which rely upon the entire sample to reside in memory.


speedbar_gc.doc

     --datasheet--
     SPEEDBAR_GetClass()
     AllocSpeedButtonNodeA()
     FreeSpeedButtonNode()
     GetSpeedButtonNodeAttrsA()
     SetSpeedButtonNodeAttrsA()


speedbar_gc/--datasheet--

    NAME
        speedbar_gc -- create speedbar BOOPSI objects

    SUPERCLASS
        gadgetclass

    REQUIRES
        bevel.image

    DESCRIPTION
        This classes provides a simple way to create and manage
        "Speed Bars", also commonly called Button Bars, Tool Docs, etc.

        A speed bar is a horizontal row or vertical column of button
        gadgets, usually with an image face denoting some program function.
        The speedbar gadget could be placed in the main programs window
        or perhaps its own window to form a floating speedbar/tooldoc.

        An advantages that this class provides:

         > Speedbar button strip created & removed as a single gadget.

         > Help strings for each button can be provided, and displayed
           in a window title bar while a button is depressed.

         > Supports Right Mouse Button abort.

         > Supports window relativity.

         > Custom centered images.

         > Ability to change background color of the speed bar strip
           or use fill hook pattern.

         > Horizontal or Vertical speed bar orientation.

         > Supports hiding and exposing speed buttons in the bar.

         > Supports scrolling additional speed buttons in to view
           via holding down the SHIFT key while clicking and
           dragging the mouse left/right or up/down depending on
           the SPEEDBAR_Orientation setting.

         > Supports OM_NOTIFY and may be attached to either
           button.gadget, scroller.gadget and/or propgclass to scroll
           the speed buttons if more buttons exist that are visible
           within its bounds. However, this as a slight unresolvable bug.

    METHODS
        OM_NEW -- Passed to superclass, defaults set, then OM_SET.

        OM_SET -- Passed to superclass, options tags set then rendered.

        OM_GET -- Custom tag returned or passed to superclass.

        OM_UPDATE -- Passed to superclass, options set then rendered.

        OM_NOTIFY -- Passed to superclass, options set then rendered.

        OM_DISPOSE -- Passed to superclass.

        GM_RENDER -- Passed to superclass, then speedbar is rendered.

        GM_HITTEST -- Overrides supperclass, returns GMR_HITTEST.

        GM_GOACTIVE -- Passed to superclass, speedbar activated.

        GM_HANDLEINPUT -- Overrides supperclass, all input processed.

        GM_GOINACTIVE -- Passed to superclass, speedbar deactivated.

        GM_DOMAIN -- Returns GDOMAIN_MINIMUM and GDOMAIN_MAXIMUM dimensions.

    ATTRIBUTES
        SPEEDBAR_Buttons (struct List *)
            An Exec list.  Nodes in this list must be allocated with
            AllocSpeedButtonNodeA().

            See the included SpeedBarTest.c example for additional information.
            Passing a NULL list will remove all buttons from the speedbar and
            detatch the buttons.  Passing ~0 will detach all buttons but not
            erase the display, useful when working on the list data, or while
            changing button lists.

            Applicability is (OM_NEW,OM_SET,OM_GET)

        SPEEDBAR_Orientation (WORD)
            Define orientation of the speedbar's button strip.

            Accepted values as defined in <gadgets/speedbar.h> are:

               SBORIENT_HORIZ
               SBORIENT_VERT

            Defaults to SBORIENT_HORIZ

            Applicability is (OM_NEW,OM_SET,OM_GET)

        SPEEDBAR_Background (WORD)
            Background colour to appear behind gadget.

            Defaults to 0.

            Applicability is (OM_NEW,OM_SET,OM_GET)

        SPEEDBAR_Window (struct Window *)
            This Window's TitleBar will changed to the selected button's
            help text while the button remains selected.

            Defaults to NULL.

            Applicability is (OM_NEW,OM_SET,OM_GET)

            NOTE: SPEEDBAR_Screen is *NOT* implemented.

        SPEEDBAR_StrumBar (BOOL)
            Enable "strumming" mode, where by you can drag the mouse
            over the button bar to view the help titles and release
            mouse button select the speed button under the mouse.

            Defaults to FALSE.

            Applicability is (OM_NEW,OM_SET)

            NOTE: SPEEDBAR_StrumBar has been disabled to support other
                  features available now, and in the future.

        SPEEDBAR_OffButton (SHORT)
            Disconnect a specified button ID from the speedbar display,
            but does not remove or deallocate button from the list.

            Applicability is (OM_SET, OM_UPDATE)

        SPEEDBAR_OnButton (SHORT)
            Reconnect specified button ID to the speedbar.

            Applicability is (OM_SET, OM_UPDATE)

        SPEEDBAR_ScrollLeft (BOOL)
            Scrolls the speedbuttons to the Left or Up depending on
            gadget orientation.

            Applicability is (OM_SET, OM_UPDATE)

        SPEEDBAR_ScrollRight (BOOL)
            Scrolls the speedbuttons to the Right or Down depending on
            gadget orientation.

            Applicability is (OM_SET, OM_UPDATE)

        SPEEDBAR_Top (WORD)
            Set or retrieve the SpeedButton ID of the Top (read First
            Visible) gadget in the button list.

            Applicability is (OM_SET, OM_UPDATE, OM_GET, OM_NOTIFY)

        SPEEDBAR_Visible (WORD)
            Retrieve the number of speed buttons visible within
            the gadget's container bounds.

            Applicability is (OM_GET, OM_NOTIFY)

        SPEEDBAR_Total (WORD)
            Retrieve the total number of speed buttons in the button list.
            SPEEDBAR_Total, SPEEDBAR_Visible and SPEEDBAR_Top could be
            mapped to a scroller's matching PGA tags to scroll the button
            list if so desired.

            Applicability is (OM_GET, OM_NOTIFY)

        SPEEDBAR_BevelStyle (WORD)
            Set bevel box style around the speed bar. In some cases
            complex speedbars might be built via a series of speedbars
            in a layout object group and it would be desirable to
            select other bevel styles such as BVS_NONE, which under any
            bevel style preferences in use, it will not render a bevel.

            Defaults to BVS_BUTTON.

            Applicability is (ON_NEW, OM_SET, OM_GET)


speedbar_gc/SPEEDBAR_GetClass

    NAME
        SPEEDBAR_GetClass -- Gets the pointer to the speedbar class. (V40)

    SYNOPSIS
        speedbar_class = SPEEDBAR_GetClass();
        D0

        Class * SPEEDBAR_GetClass(VOID);

    FUNCTION
        Obtains the pointer to the SpeedBar gadget class for use with
        NewObject().  This function always returns a valid pointer so
        you do not need to check it.  The reason is that if the library
        opens fine, then the pointer returned is already setup.  (Of course
        this implies that if opening the library fails, you shouldn't be
        calling this.)

        Note that this function does not create the class, that is done
        when the class library is opened.

    INPUTS
        Nothing.

    RESULT
        speedbar_class - Pointer to the SpeedBar gadget class.

    SEE ALSO


speedbar_gc/AllocSpeedButtonNodeA

    NAME
        AllocSpeedButtonNodeA -- Allocate a SpeedBar node. (V40)

    SYNOPSIS
        struct Node * AllocSpeedButtonNode(UWORD, Tag, ...)
        node = AllocSpeedButtonNode(number, Tag, ...)

        struct Node * AllocSpeedButtonNodeA(UWORD, struct TagItem *)
        node = AllocSpeedButtonNodeA(number, taglist)

    FUNCTION
        Allocates a node that can be added to the Exec linked list of
        labels in the speedbar.  This is the only way to allocate a
        node for this list, you cannot allocate nodes yourself because
        the SpeedBar class uses a private node structure.

    INPUTS
        number - Places value in node->sbn_Node.ln_Pri, and is the
            numeric ID of the button within the bar. Note the current
            limitation, ln_Pri is a BYTE. This will be addressed, and
            *posibly* made obsolete and overridden by SBNA_ButtonID.

        taglist - Attributes for the node, passed onto
            SetSpeedButtonNodeAttrsA().

    RESULT
        node - A node that can be added into the Exec list of labels for
            a SpeedBar gadget.

    SEE ALSO
        FreeSpeedButtonNode(), SetSpeedButtonNodeAttrsA()


speedbar_gc/FreeSpeedButtonNode

    NAME
        FreeSpeedButtonNode -- Free a SpeedBar node. (V40)

    SYNOPSIS
        VOID FreeSpeedButtonNode(struct Node *)
        FreeSpeedButtonNode(node)

    FUNCTION
        Frees a SpeedButtonNode allocated with AllocSpeedButtonNodeA().

    INPUTS
        node - The node to free.

    SEE ALSO
        AllocSpeedButtonNodeA()


speedbar_gc/GetSpeedButtonNodeAttrsA

    NAME
        GetSpeedButtonNodeAttrsA -- Get attributes about a SpeedBar node. (V40)

    SYNOPSIS
        VOID GetSpeedButtonNodeAttrs(struct Node *, Tag, ...)
        GetSpeedButtonNodeAttrs(node, firsttag, ...)

        VOID GetSpeedButtonNodeAttrsA(struct Node *, struct TagItem *)
        GetSpeedButtonNodeAttrsA(node, taglist)

    FUNCTION
        The SpeedBar uses a private node structure and all attributes
        are hidden, and must therefore be accessed with this function.

    INPUTS
        node - The SpeedBar node to get the information on.
        taglist - A tag list of attributes to get.  ti_Tag is the attribute
            to get and ti_Data is a pointer to a location to copy the result
            to.

    SEE ALSO
        SetSpeedButtonNodeAttrsA()


speedbar_gc/SetSpeedButtonNodeAttrsA

    NAME
        SetSpeedButtonNodeAttrsA -- Set attributes of a SpeedBar node. (V40)

    SYNOPSIS
        VOID SetSpeedButtonNodeAttrs(struct Node *, Tag, ...)
        SetSpeedButtonNodeAttrs(node, firsttag, ...)

        VOID SetSpeedButtonNodeAttrsA(struct Node *, struct TagItem *)
        SetSpeedButtonNodeAttrsA(node, taglist)

    FUNCTION
        Changes attributes for a SpeedBar node.  Since the SpeedBar
        class uses a private node structure, this is the only way to change
        node attributes.

        You may NOT change node attributes when the node is in a list
        attached to a SpeedBar gadget.  You must first detach the list
        with SPEEDBAR_Labels, ~0 before you can change attributes, and
        then re-attach the list.

    TAGS
        SBNA_Left (WORD)
        Left spacing offset of button from left of bar, set automatically.

        SBNA_Top (WORD)
        Top spacing offset of button from top of bar, set automatically.

        SBNA_Width (WORD)
        Width Of Button - these are set automatically.

        SBNA_Height (WORD)
        Height Of Button - these are set automatically.

        SBNA_Image (struct Image *)
        Standard Image or BOOPSI Image to be displayed in this button.

        SBNA_SelImage (struct Image *)
        Standard Image or BOOPSI Image to be displayed in this button
        when selected.

        SBNA_Spacing (WORD)
        Spacing between this button and the last button.

        SBNA_Highlight (WORD)
        Button selecting highlight mode, ant one of the following
        is supported:

                SBH_NONE        - Do not highlight.
                SBH_BACKFILL    - BackFill will FILLPEN
                SBH_RECESS      - Shift image right and down when selected.
                SBH_IMAGE       - Display alternate image (SBNA_SelImage)

        SBNA_Enabled (BOOL)
        Enabled (hidden/shown) state of a speed button.

        SBNA_Help (STRPTR)
        String Pointer to optional help text place in window titlebar
        when this speed button is active/selected.

        SBNA_UserData (APTR)
        User Data, use as desired.

        SBNA_Disabled (BOOL) (V41)
        Marks this button as disabled, it will render with a ghost pattern
        and will not allow it to be selected.

        SBNA_Toggle (BOOL) (V41)
        Designates the button as a boolean toggle button. Defaults FALSE.

        SBNA_Selected (BOOL) (V41)
        The current selection state of a Toggle/MX button. Defaults FALSE.

        SBNA_MXGroup (BOOL) (V41)
        Set the MXGroup a button belongs in. This setting implies the
        SBNA_Toggle setting as TRUE also. The default is ~0, or not
        in any MXGroup. Note, a single speedbar can contain several
        MX groupings and mixtures of toggles and normal selections!

    INPUTS
        node - Node whose attributes you are changing.
        taglist - Tag list of attributes to change.

    SEE ALSO
        GetSpeedButtonNodeAttrsA()


string_gc.doc

     --datasheet--
     STRING_GetClass()


string_gc/--datasheet--

   NAME
        string_gc -- create string BOOPSI objects

    SUPERCLASS
        gadgetclass

    REQUIRES
        bevel.image

    DESCRIPTION
        The string gadget class is used to create single line
        editable strings. This class also supports window relativity.
        This class is a subclass of rom strgclass which automatically
        creates a field bevel and supports GM_DOMAIN for layout groups.

     METHODS
        OM_NEW -- Passed to superclass, strgclass allocated, then OM_SET.

        OM_SET -- Passed to superclass, and strgclass is set.

        OM_UPDATE -- Passed to superclass, and strgclass is set then
            rendered.

        OM_DISPOSE -- Disposes strgclass object, then passed to superclass.

        GM_RENDER -- Passed to superclass, then strgclass object

        GM_HITTEST -- Overrides supperclass, returns GMR_HITTEST.

        GM_GOACTIVE -- Passed to superclass, strgclass, string activated

        GM_HANDLEINPUT -- Routes input to strgclass object.

        GM_GOINACTIVE -- Passed to superclass, strgclass, string deactivated.

        GM_DOMAIN -- Returns GDOMAIN_MINIMUM, GDOMAIN_NOMINAL and
            GDOMAIN_MAXIMUM dimensions.

     ATTRIBUTES
        GA_Disabled (BOOL)
            Determines whether the string is disabled or not.
            Changing disable state will invoke GM_RENDER.  A disabled
            string is dusted in a ghosting pattern that is rendered
            in SHADOWPEN.

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

        GA_TextAttr (struct TextAttr *)
            Text attribute for the font to use for the string.

            Defaults to RPort->Font, which is often the screen or
            window font.

            Applicability is (OM_NEW)

        GA_ReadOnly (BOOL)
            Read-only gadgets ignore activation attempts.

            Defaults to FALSE.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

        STRINGA_MinVisible (WORD) (V41)
            Set the minimum number of characters that should be
            visible for a 'GDOMAIN_MIMIMUM' domain size. Nominal
            domain sizes to twice this minimum. This is a handy
            addition (also present in V40.35) to ensure a mimimum
            number characters will be visible in a string gadget.

            Defaults to 4.

            Applicability is (OM_NEW, OM_SET, OM_UPDATE)

     NOTES

        The string class passes all tags to its strgclass child,
        please see strgclass tags & autodocs, and look in
        <intuition/gadgetclass.h> for the STRINGA_ tags.

        WARNING: string.gadget is ROM strgclass wrapper, depending on
        string.gadget version. Passing GA_Text can crash strgclass,
        please use STRING_TextVal as its intended. STRINGA_Font and
        STRINGA_LongVal are not directly supported, for numeric
        strings use our more powerful integer.gadget class. To specify
        the font for the gadget, use GA_TextAttr which is consistant
        with all other ReAction gadget attributes.


string_gc/STRING_GetClass

    NAME
        STRING_GetClass -- Gets the pointer to the string class.

    SYNOPSIS
        string_class = STRING_GetClass();
        D0

        Class * STRING_GetClass(VOID);

    FUNCTION
        Obtains the pointer to the String gadget class for use with
        NewObject().  This function always returns a valid pointer so
        you do not need to check it.  The reason is that if the library
        opens fine, then the pointer returned is already setup.  (Of course
        this implies that if opening the library fails, you shouldn't be
        calling this.)

        Note that this function does not create the class, that is done
        when the class library is opened.

    INPUTS
        Nothing.

    RESULT
        string_class - Pointer to the String gadget class.

    SEE ALSO


text_dtc.doc

     text.datatype()


text.datatype/text.datatype

    NAME
    text.datatype -- Root data type for text.

    FUNCTION
    The text.datatype is the super-class for any text related classes.

    METHODS
    OM_NEW -- Create a new text object.

    OM_GET -- Obtain the value of an attribute.

    OM_SET -- Set the values of multiple attributes.

    OM_UPDATE -- Update the values of multiple attributes.

    OM_DISPOSE -- Dispose of a text object.

    GM_LAYOUT -- Layout the object and notify the application of the
        title and size.

    GM_HITTEST -- Determine if the object has been hit with the
        mouse.

    GM_GOACTIVE -- Tell the object to go active.

    GM_HANDLEINPUT -- Handle input.

    GM_RENDER -- Cause the text to render.

    DTM_PROCLAYOUT -- Layout (remap) the text on the application's
        process.

    DTM_FRAMEBOX -- Obtain the display environment that the text
        requires.

    DTM_SELECT -- Select an area in the text.

    DTM_CLEARSELECTED -- Deselect the selected area of the text.

    DTM_COPY -- Copy the selected area of the text to the clipboard
        as FTXT.  If no area is selected, then the entire text
        is copied.

    DTM_PRINT -- Print the selected area of the text.  If no area
        is selected, then the entire text is printed.

    DTM_WRITE -- Write the selected area of the text to a file.
        If no area is selected, then the entire text is saved.

    TAGS
    DTA_TextAttr (struct TextAttr *) -- Text attribute to use for
        the text.

        Applicability is (ISG).

    DTA_TextFont (struct TextFont *) -- Text font to use for
        the text.

        Applicability is (G).

    TDTA_Buffer (STRPTR) -- Pointer to the text data.

        Applicability is (ISG).

    TDTA_BufferLen (ULONG) -- Length of text data.

        Applicability is (ISG).

    TDTA_LineList (struct List *) -- List of lines.  The elements
        of the list are Line structures (see <datatype/textclass.h>

        Applicability is (G).

    TDTA_WordSelect (STRPTR) -- Word that has been double-clicked on.

        Applicability is (NU).

    TDTA_WordDelim (STRPTR) -- Characters used deliminate words.

        Applicability is (IS).

    TDTA_WordWrap (BOOL) -- Used to turn word wrap on and off.
        Defaults to off.

        Applicability is (ISG).

    SEE ALSO
    ascii.datatype


timer.doc

     --background--
     AbortIO()
     AddTime()
     CmpTime()
     GetSysTime()
     ReadEClock()
     SubTime()
     TR_ADDREQUEST
     TR_GETSYSTIME
     TR_SETSYSTIME


trackdisk.doc

     CMD_CLEAR
     CMD_READ
     CMD_UPDATE
     CMD_WRITE
     TD_ADDCHANGEINT
     TD_CHANGENUM
     TD_CHANGESTATE
     TD_EJECT
     TD_FORMAT
     TD_GETDRIVETYPE
     TD_GETGEOMETRY
     TD_GETNUMTRACKS
     TD_MOTOR
     TD_PROTSTATUS
     TD_RAWREAD
     TD_RAWWRITE
     TD_REMCHANGEINT
     TD_SEEK


trackdisk.device/TD_EJECT

   NAME
       TD_EJECT -- eject (or load) the disk in the drive, if possible.

   FUNCTION
    This command causes the drive to attempt to eject the disk in
    it, if any.  Note that the current trackdisk.device does not
    implement this command, but it might in the future, and other
    trackdisk-compatible drivers may implement this command.  Some
    devices may be able to load disks on command also.

   IO REQUEST INPUT
    io_Device	preset by the call to OpenDevice()
    io_Unit		preset by the call to OpenDevice()
    io_Command	TD_EJECT
    io_Flags	0 or IOF_QUICK
    io_Length	0 (load, if supported) or 1 (eject)

   IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>

   BUGS
    The pre-V40 autodoc didn't mention io_Length.  Because of this, for
    devices that can never support load, a driver might want to eject if
    io_Length is 0.


trackdisk.device/TD_RAWREAD

   NAME
    TD_RAWREAD/ETD_RAWREAD -- read raw data from the disk.

   FUNCTION
    These commands read a track of raw data from disk and deposits it in
    the provided buffer. The data is taken straight from the disk with
    no processing done on it. It will appear exactly as the bits come out
    off the disk, hopefully in some legal MFM format.

    This interface is intended for sophisticated programmers only.
    Amiga reserves the right to make enhancements to the disk
    format in the future. We will provide compatibility via the
    CMD_READ and ETD_READ commands, anyone using TD_RAWREAD is
    bypassing this upwards compatibility, and may thus stop working.

   IO REQUEST INPUT
    io_Device	preset by the call to OpenDevice()
    io_Unit		preset by the call to OpenDevice()
    io_Command      TD_RAWREAD or ETD_RAWREAD.
    io_Flags	if the IOTDB_INDEXSYNC bit is set then the driver
            will make a best effort attempt to start reading
            from the index mark.  Note that there will be at
            least some delay, and perhaps a great deal of delay
            (for example if interrupts have been disabled).
    io_Length	Length of buffer in bytes, with a maximum of 32768
            bytes.
    io_Data		Pointer to CHIP memory buffer where raw track data is
            to be deposited.
    io_Offset	The number of the track to read in.
    iotd_Count	(ETD_RAWREAD only) maximum allowable change counter
            value.

   IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>

   NOTES
    The track buffer provided MUST be in CHIP memory

    There is a delay between the index pulse and the start of bits
    coming in from the drive (e.g. dma started). This delay
    is in the range of 135-200 microseconds. This delay breaks
    down as follows: 55 microsecs is software interrupt overhead
    (this is the time from interrupt to the write of the DSKLEN
    register). 66 microsecs is one horizontal line delay (remember
    that disk IO is synchronized with agnus' display fetches).
    The last variable (0-65 microsecs) is an additional scan line
    since DSKLEN is poked anywhere in the horizontal line. This leaves
    15 microsecs unaccounted for...  Sigh.

    In short, You will almost never get bits within the first 135
    microseconds of the index pulse, and may not get it until 200
    microseconds. At 4 microsecs/bit, this works out to be between
    4 and 7 bytes of user data of delay.

   BUGS
    This command does not work reliably under versions of Kickstart
    earlier than V36, especially on systems with 1 floppy drive.

   SEE ALSO
    TD_RAWWRITE


trackdisk.device/TD_RAWWRITE

   NAME
    TD_RAWWRITE/ETD_RAWWRITE -- write raw data to the disk.

   FUNCTION
    This command writes a track of raw data from the provided buffer to
    the specified track on disk. The data is copied straight to the disk
    with no processing done on it. It will appear exactly on the disk as
    it is in the memory buffer, hopefully in a legal MFM format.

    This interface is intended for sophisticated programmers only.
    Amiga reserves the right to make enhancements to the disk
    format in the future. We will provide compatibility via the
    CMD_WRITE and ETD_WRITE commands, anyone using TD_RAWWRITE is
    bypassing this upwards compatibility, and may thus stop working.

   IO REQUEST INPUT
    io_Device	preset by the call to OpenDevice()
    io_Unit		preset by the call to OpenDevice()
    io_Command      TD_RAWWRITE or ETD_RAWWRITE.
    io_Flags	if the IOTDB_INDEXSYNC bit is set then the driver
            will make a best effort attempt to start writing
            from the index mark.  Note that there will be at
            least some delay, and perhaps a great deal of delay
            (for example if interrupts have been disabled).
    io_Length	Length of buffer in bytes, with a maximum of 32768
            bytes.
    io_Data		Pointer to CHIP memory buffer where raw track data is
            to be taken.
    io_Offset	The number of the track to write to.
    iotd_Count	(ETD_RAWWRITE only) maximum allowable change counter
            value.

   IO REQUEST RESULT
    io_Error - 0 for success, or an error code as defined in
               <devices/trackdisk.h>

   NOTES
    The track buffer provided MUST be in CHIP memory

    There is a delay between the index pulse and the start of bits
    going out to the driver (e.g. write gate enabled). This delay
    is in the range of 135-200 microseconds. This delay breaks
    down as follows: 55 microsecs is software interrupt overhead
    (this is the time from interrupt to the write of the DSKLEN
    register). 66 microsecs is one horizontal line delay (remember
    that disk IO is synchronized with agnus' display fetches).
    The last variable (0-65 microsecs) is an additional scan line
    since DSKLEN is poked anywhere in the horizontal line. This leaves
    15 microsecs unaccounted for...  Sigh.

    In short, You will almost never get bits within the first 135
    microseconds of the index pulse, and may not get it until 200
    microseconds. At 4 microsecs/bit, this works out to be between
    4 and 7 bytes of user data of delay.

   BUGS
    This command does not work reliably under versions of Kickstart
    earlier than V36, especially on systems with 1 floppy drive.

   SEE ALSO
    TD_RAWREAD


utility.doc

     AddNamedObject()
     AllocateTagItems()
     AllocNamedObjectA()
     Amiga2Date()
     ApplyTagChanges()
     AttemptRemNamedObject()
     CallHookPkt()
     CheckDate()
     CloneTagItems()
     Date2Amiga()
     FilterTagChanges()
     FilterTagItems()
     FindNamedObject()
     FindTagItem()
     FreeNamedObject()
     FreeTagItems()
     GetTagData()
     GetUniqueID()
     MapTags()
     NamedObjectName()
     NextTagItem()
     PackBoolTags()
     PackStructureTags()
     RefreshTagItemClones()
     ReleaseNamedObject()
     RemNamedObject()
     SDivMod32()
     SMult32()
     SMult64()
     Stricmp()
     Strnicmp()
     TagInArray()
     ToLower()
     ToUpper()
     UDivMod32()
     UMult32()
     UMult64()
     UnpackStructureTags()


utility.library/AddNamedObject

   NAME
    AddNamedObject -- add a named object to the given namespace. (V39)

   SYNOPSIS
    success = AddNamedObject(nameSpace, object);
    D0			 A0         A1

    BOOL AddNamedObject(struct NamedObject *, struct NamedObject *);

   FUNCTION
    Adds a new item to a NameSpace.  If the NameSpace doesn't support
    duplicate names, a search for a duplicate will be made, and
    0 (failure) will be returned.  Otherwise, the entry will be
    Enqueue()ed to the NameSpace.

   INPUTS
    nameSpace - the name space to add to (NULL for root namespace)
    object - the object to add  (If NULL, will return failure)

   RESULT
    success - whether the operation succeeded.  Check this always!

   SEE ALSO
    AttemptRemNamedObject(), RemNamedObject()


utility.library/AllocateTagItems

   NAME
    AllocateTagItems -- allocate a tag list. (V36)

   SYNOPSIS
    tagList = AllocateTagItems(numTags);
    D0		           D0

    struct TagItem *AllocateTagItems(ULONG);

   FUNCTION
    Allocates the specified number of usable TagItems slots.

    Note that to access the TagItems in 'tagList', you should use
    the function NextTagItem(). This will insure you respect any
    chaining (TAG_MORE) and secret hiding places (TAG_IGNORE) that
    this function might generate.

   INPUTS
    numTags - the number of TagItem slots you want to allocate.

   RESULTS
    tagList	- the allocated chain of TagItem structures, or NULL if
              there was not enough memory. An allocated tag list must
              eventually be freed using FreeTagItems().

   SEE ALSO
    <utility/tagitem.h>, FreeTagItems(), CloneTagItems()


utility.library/AllocNamedObjectA

   NAME
    AllocNamedObjectA -- allocate a named object. (V39)

   SYNOPSIS
    object = AllocNamedObjectA(name, tagList);
    D0                         A0    A1

    struct NamedObject *AllocNamedObjectA(STRPTR, struct TagItem *);

    object = AllocNamedObject(name, Tag1, ...);

    struct NamedObject *AllocNamedObject(STRPTR, ULONG, ...);

   FUNCTION
    Allocates a NamedObject and initializes it as needed to the
    name given. This object can then be used as an object in the
    namespaces. Tags can be given to make an object contain a
    namespace such that nested namespaces can be built.
    When the object is allocated, it automatically has one use.
    If you later wish to release this object such that others may
    remove it from the namespace you must do a ReleaseNamedObject().

   INPUTS
    name - name for the object (must not be NULL)
    tagList - tags with additional information for the allocation or NULL

   TAGS
    ANO_NameSpace - BOOL tag, default FALSE.  If this tag is
                    TRUE, the named object will also have a
                    name space attached to it.
    ANO_UserSpace - ULONG tag, default 0.  If this tag is non-NULL
                    it defines the size (in bytes) of the user
                    space to be allocated with the named object
                    and that will be pointed to by the no_Object
                    pointer.  This memory is long-word aligned.
                    If no space is defined, no_Object will be NULL.
    ANO_Priority  - BYTE tag, default 0.  This tag lets you pick
                    a priority for the named object for when it is
                    placed into a name space.
    ANO_Flags     - ULONG tag, default 0.  This tag lets you set
                    the flags of the NameSpace (if you allocated
                    one)  There currently are only TWO flags.
                    Do *NOT* set *any* other bits as they are for
                    future use!!!  (You can't read them anyway)
                    The flags are:
                    NSF_NODUPS	- Name space must be unique.
                    NSF_CASE	- Name space is case sensitive

   RESULT
    object - the object allocated, or NULL for failure. The object
             is defined as a pointer to a pointer.  You can do what you
             wish with the pointer. (It may be NULL or contain a pointer
             to memory that you had asked for in the tags.)

   SEE ALSO
    FreeNamedObject(), <utility/name.h>


utility.library/Amiga2Date

   NAME
    Amiga2Date -- fill in a ClockData structure based on a system
              time stamp (V36)

   SYNOPSIS
    Amiga2Date(seconds,result);
               D0      A0

    VOID Amiga2Date(ULONG,struct ClockData *);

   FUNCTION
    Fills in a ClockData structure with the date and time calculated
    from a ULONG containing the number of seconds from 01-Jan-1978
    to the date.

   INPUTS
    seconds - the number of seconds from 01-Jan-1978.
    result - a pointer to a ClockData structure that will be altered
         by this function

   SEE ALSO
    CheckDate(), Date2Amiga()


utility.library/ApplyTagChanges

   NAME
    ApplyTagChanges -- change a tag list based on a second tag list. (V39)

   SYNOPSIS
    ApplyTagChanges(list,changeList);
            A0   A1

    VOID ApplyTagChanges(struct TagItem *, struct TagItem *);

   FUNCTION
    For any tag that appears in both 'list' and 'changeList', this
    function will change the ti_Data field of the tag in 'list' to
    match the ti_Data field of the tag in 'changeList'. In effect,
    'changeList' contains a series of new values for tags already in
    'list'. Any tag in 'changeList' that is not in 'list' is ignored.

   INPUTS
    list - a list of existing tags (may be NULL)
    changeList - a list of tags to modify 'list' with (may be NULL)

   SEE ALSO
    <utility/tagitem.h>, FilterTagChanges()


utility.library/AttemptRemNamedObject

   NAME
    AttemptRemNamedObject -- attempt to remove a named object. (V39)

   SYNOPSIS
    result = AttemptRemNamedObject(object);
    D0                             A0

    LONG AttemptRemNamedObject(struct NamedObject *);

   FUNCTION
    Attempts to remove an object from whatever NameSpace it's in.
    You must have found the object first (in order to get a use count)
    before trying to remove it.  If the object is in use or is
    in the process of being removed, this function will return
    a failure code.  If the object is fully removed, the object will
    then be available to be FreeNamedObject().

   INPUTS
    object - the object to attempt to remove  The object must be valid

   RESULT
    success - FALSE if object is still in use (somewhere)
              TRUE if object was removed

   SEE ALSO
    RemNamedObject(), AddNamedObject(), ReleaseNamedObject()


utility.library/CallHookPkt

   NAME
    CallHookPkt -- invoke a Hook function callback. (V36)

   SYNOPSIS
    return = CallHookPkt(hook,object,message);
    D0		     A0   A2	 A1

    ULONG CallHookPkt(struct Hook *,APTR,APTR);

   FUNCTION
    Performs the callback standard defined by a Hook structure.
    This function is really very simple; it effectively performs
    a JMP to Hook->h_Entry.

    It is probably just as well to do this operation in an
    assembly language function linked in to your program, possibly
    from a compiler supplied library or a builtin function.

    It is anticipated that C programs will often call a 'varargs'
    variant of this function which will be named CallHook. This
    function must be provided in a compiler specific library, but
    an example of use would be:

    result = CallHook(hook,dataobject,COMMAND_ID,param1,param2);

    The function CallHook() can be implemented in many C compilers
    like this:

    ULONG CallHook(struct Hook *hook, APTR object, ULONG command, ... )
    {
        return(CallHookPkt(hook,object,(APTR)&command));
    }

   INPUTS
    hook - pointer to an initialized Hook structure as defined in
           <utility/hooks.h>
    object - useful data structure in the particular context the hook is
         being used for.
    message - pointer to a message to be passed to the hook. This is not
          an Exec Message structure, but is a message in the OOP sense.

   RESULTS
    return - the value returned by the hook function.

   WARNING
    The functions called through this function should follow normal
    register conventions unless EXPLICITLY documented otherwise (and
    they have a good reason too).

   SEE ALSO
    <utility/hooks.h>


utility.library/CheckDate

   NAME
    CheckDate -- checks a ClockData structure for legal date. (V36)

   SYNOPSIS
    seconds = CheckDate(date);
    D0                  A0

    ULONG CheckDate(struct ClockData *);

   FUNCTION
    Determines if the ClockData structure contains legal date information
    and returns the number of seconds from 01-Jan-1978 to that date, or 0
    if the ClockData structure contains illegal data.

   INPUTS
    date - a filled-in ClockData structure

   RESULTS
    seconds	- 0 if date is invalid, otherwise the number of seconds from
          01-Jan-1978 to the date

   BUGS
    The wday field of the ClockData structure is not checked.

   SEE ALSO
    Amiga2Date(), Date2Amiga()


utility.library/CloneTagItems

   NAME
    CloneTagItems -- copy a tag list. (V36)

   SYNOPSIS
    clone = CloneTagItems(original);
    D0		      A0

    struct TagItem *CloneTagItems(struct TagItem *);

   FUNCTION
    Copies the essential contents of a tag list into a new tag list.

    The cloning is such that calling FindTagItem() with a given tag on
    the original or cloned tag lists will always return the same
    tag value. That is, the ordering of the tags is maintained.

   INPUTS
    original - tag list to clone. May be NULL, in which case an
           empty tag list is returned.

   RESULTS
    clone - copy of the original tag list, or NULL if there was not enough
        memory. This tag list must eventually by freed by calling
        FreeTagItems().

   SEE ALSO
    <utility/tagitem.h>, AllocateTagItems(), FreeTagItems(),
    RefreshTagItemClones()


utility.library/Date2Amiga

   NAME
    Date2Amiga -- calculate seconds from 01-Jan-1978. (V36)

   SYNOPSIS
    seconds = Date2Amiga(date);
    D0                   A0

    ULONG Date2Amiga(struct ClockData *);

   FUNCTION
    Calculates the number of seconds from 01-Jan-1978 to the date
    specified in the ClockData structure.

   INPUTS
    date - pointer to a ClockData structure containing the date of
           interest.

   RESULTS
    seconds	- the number of seconds from 01-Jan-1978 to the date specified.

   WARNING
    This function does no sanity checking of the data in the ClockData
    structure.

   SEE ALSO
    Amiga2Date(), CheckDate()


utility.library/FilterTagChanges

   NAME
    FilterTagChanges -- eliminate tags which specify no change. (V36)

   SYNOPSIS
    FilterTagChanges(changeList,originalList,apply);
             A0	    A1           D0

    VOID FilterTagChanges(struct TagItem *, struct TagItem *, ULONG);

   FUNCTION
    This function goes through changeList. For each item found in
    changeList, if the item is also present in originalList, and their
    data values are identical, then the tag is removed from changeList.
    If the two tag's data values are different and the 'apply' value is
    non-zero, then the tag data in originalList will be updated to match
    the value from changeList.

   INPUTS
    changeList - list of new tags (may be NULL)
    originalList - a list of existing tags (may be NULL)
    apply - boolean specification as to whether the data values in
        originalList are to be updated to the data values in
        changeList.

   EXAMPLE
    Assume you have an attribute list for an object (originalList)
    which looks like this:

        {ATTR_Size,  "large"},
        {ATTR_Color, "orange"},
        {ATTR_Shape, "square"}

    If you receive a new tag list containing some changes (changeList),
    which looks like this:

        {ATTR_Size,  "large"},
        {ATTR_Shape, "triangle"}

    If you call FilterTagChanges(), changeList will be modified to
    contain only those attributes which are different from those
    in originalList. All other items will have their tag values set to
    TAG_IGNORE. The resulting changeList will become:

        {TAG_IGNORE, "large"},
        {ATTR_Shape, "triangle"}

    If 'apply' was set to 0, originalList would be unchanged. If 'apply'
    was non-zero, originalList would be changed to:

        {ATTR_Size,  "large"},
        {ATTR_Color, "orange"},
        {ATTR_Shape, "triangle"}

   SEE ALSO
    <utility/tagitem.h>, ApplyTagChanges()


utility.library/FilterTagItems

   NAME
    FilterTagItems -- remove selected items from a tag list. (V36)

   SYNOPSIS
    numValid = FilterTagItems(tagList,filterArray,logic);
    D0		          A0	  A1	      D0

    ULONG FilterTagItems(struct TagItem *,Tag *,ULONG);

   FUNCTION
    Removes tag items from a tag list (by changing ti_Tag to
    TAG_IGNORE) depending on whether its ti_Tag value is
    found in an array of tag values.

    If the 'logic' parameter is TAGFILTER_AND, then all items
    not appearing in 'tagArray' are excluded from 'tagList'.

    If 'logic' is TAGFILTER_NOT, then items not found in 'tagArray'
    are preserved, and the ones in the array are cast out.

   INPUTS
    tagList	- input list of tag items which is to be filtered by having
          selected items changed to TAG_IGNORE.
    filterArray - an array of tag values, terminated by TAG_DONE, as
              specified in the documentation for TagInArray().
    logic - specification whether items in 'tagArray' are to be included
        or excluded in the filtered result.

   RESULTS
    numValid - number of valid items left in resulting filtered list.

   SEE ALSO
    <utility/tagitem.h>, TagInArray()


utility.library/FindNamedObject

   NAME
    FindNamedObject -- find the next object of a given name. (V39)

   SYNOPSIS
    object = FindNamedObject(nameSpace, name, lastObject);
    D0                       A0         A1    A2

    struct NamedObject *FindNamedObject(struct NamedObject *, STRPTR,
                        struct NamedObject *);

   FUNCTION
    Finds an object and adds to the open count of the object. The
    object is guaranteed not to be freed until ReleaseNamedObject() is
    called. The name comparison is caseless, using the current
    locale string comparison routines.

    If name is NULL, then all objects will be matched.

    If lastObject is non-NULL, it must be an object from the same
    NameSpace found on a previous call to FindNamedObject(). It
    will not be freed by this call. The search will start at the
    node after lastobject, if non-NULL.

    nameSpace is the name space from the named object given
    or the root name space if NULL is given.

   INPUTS
    nameSpace - the name space to search
    name - the name of the object to search for
    lastObject - the starting point for the search or NULL

   RESULT
    object - the first match found, or NULL for no match

   SEE ALSO
    ReleaseNamedObject(), <utility/name.h>


utility.library/FindTagItem

   NAME
    FindTagItem -- scan a tag list for a specific tag. (V36)

   SYNOPSIS
    tag = FindTagItem(tagValue,tagList);
    D0		  D0	   A0

    struct TagItem *FindTagItem(Tag,struct TagItem *);

   FUNCTION
    Scans a tag list and returns a pointer to the first item with
    ti_Tag matching the 'tagValue' parameter.

   INPUTS
    tagValue - tag value to search for
    tagList	- tag item list to search (may be NULL)

   RESULTS
    tag - a pointer to the item with ti_Tag matching 'tagValue' or NULL
          if no match was found.

   SEE ALSO
    <utility/tagitem.h>, GetTagData(), PackBoolTags(), NextTagItem()


utility.library/FreeNamedObject

   NAME
    FreeNamedObject -- frees a name object. (V39)

   SYNOPSIS
    FreeNamedObject(object);
            A0

    VOID FreeNamedObject(struct NamedObject *);

   FUNCTION
    Free one of a number of structures used by utility.library.
    The item must not be a member of any NameSpace, and no one
    may have it open other than yourself. If the object also
    contained a NameSpace, that namespace must be empty.
    Any additional space allocated via the datasize parameter
    for AllocNamedObject() is also released.

   INPUTS
    object - the object to be freed

   SEE ALSO
    AllocNamedObjectA()


utility.library/FreeTagItems

   NAME
    FreeTagItems -- free an allocated tag list. (V36)

   SYNOPSIS
    FreeTagItems(tagList);
             A0

    VOID FreeTagItems(struct TagItem *);

   FUNCTION
    Frees the memory of a TagItem list allocated either by
    AllocateTagItems() or CloneTagItems().

   INPUTS
    tagList - list to free, must have been obtained from
          AllocateTagItems() or CloneTagItems() (may be NULL)

   SEE ALSO
    <utility/tagitem.h>, AllocateTagItems(), CloneTagItems()


utility.library/GetTagData

   NAME
    GetTagData -- obtain the data corresponding to a tag. (V36)

   SYNOPSIS
    value = GetTagData(tagValue,defaultVal,tagList);
    D0		   D0	    D1	       A0

    ULONG GetTagData(Tag,ULONG,struct TagItem *);

   FUNCTION
    Searches a tag list for a matching tag, and returns the
    corresponding ti_Data value for the TagItem found. If no match is
    found, this function returns the value passed in as 'default'.

   INPUTS
    tagValue - tag value to search for.
    defaultVal - value to be returned if tagValue is not found.
    tagList - the tag list to search.

   RESULTS
    value - the ti_Data value for the first matching TagItem, or 'default'
        if a ti_Tag matching 'Tag' is not found.

   SEE ALSO
    <utility/tagitem.h>, FindTagItem(), PackBoolTags(), NextTagItem()


utility.library/GetUniqueID

   NAME
    GetUniqueID -- return a relatively unique number. (V39)

   SYNOPSIS
    id = GetUniqueID();
    D0

    ULONG GetUniqueID(VOID);

   FUNCTION
    Returns a unique value each time it is called. This is useful for
    things that need unique ID such as the GadgetHelp ID, etc.
    Note that this is only unique for 4,294,967,295 calls to this
    function. Under normal use this is not a problem.
    This function is safe in interrupts.

   RESULT
    id - a 32-bit value that is unique.


utility.library/MapTags

   NAME
    MapTags	-- convert ti_Tag values in a list via map pairing. (V36)

   SYNOPSIS
    MapTags(tagList,mapList,mapType);
        A0	A1      D0

    VOID MapTags(struct TagItem *,struct TagItem *,ULONG);

   FUNCTION
    Apply a "mapping list" mapList to tagList.

    If the ti_Tag field of an item in tagList appears as ti_Tag in some
    item in mapList, overwrite ti_Tag with the corresponding ti_Data
    from the map list.

    The mapType parameter specifies how the mapping operation is to
    proceed, with the following available types:

        MAP_REMOVE_NOT_FOUND
        If a tag in tagList does not appear in the mapList, remove
        it from tagList.

        MAP_KEEP_NOT_FOUND
        To have items which do not appear in the mapList survive the
        mapping process as-is.

    MapTags() is central to BOOPSI gadget interconnections where you want
    to convert the tag values from one space (the sender) to another (the
    receiver).

    The procedure will change the values of the input tag list
    tagList (but not mapList).

    You can "filter" a list by passing MAP_REMOVE_NOT_FOUND as mapType,
    and having the data items in mapList equal the corresponding tags.

    You can perform the inverse filter ("everything but") by passing
    a mapType of MAP_KEEP_NOT_FOUND, and creating a map item for every tag
    you want to filter out, pairing it with a mapped data value of
    TAG_IGNORE.

    For safety and "order independence" of tag item arrays, if you
    attempt to map some tag to the value TAG_DONE, the value TAG_IGNORE
    will be substituted instead.

   INPUTS
    tagList	- input list of tag items which is to be mapped to tag values
          as specified in mapList.
    mapList - a "mapping list" tag list which pairs tag values expected to
          appear in tagList with new values to be substituted in the
          ti_Tag fields of tagList (may be NULL)
    mapType - one of the available mapping types as defined in
          <utility/tagitem.h>

   EXAMPLE
    /* Consider this source list: */
        struct TagItem list[] =
        {
        {MY_SIZE, 	71},
        {MY_WEIGHT, 	200},
        {TAG_DONE,	}
           };

    /* And the mapping list: */
        struct TagItem map[] =
        {
        {MY_SIZE, 	HIS_TALL},
        {TAG_DONE,	}
        };

    /* Then after MapTags(list,map,MAP_REMOVE_NOT_FOUND), 'list' will
       become: */
        {HIS_TALL,71},
        {TAG_IGNORE,},
        {TAG_DONE,}

    /* Or after MapTags(list,map,MAP_KEEP_NOT_FOUND), 'list' will
       become: */
        {HIS_TALL,  71},
        {MY_WEIGHT, 200},
        {TAG_DONE,  }

   BUGS
    Prior to V39, the mapType parameter did not work. The function
    always behaved as if the parameter was set to MAP_KEEP_NOT_FOUND.

   SEE ALSO
    <utility/tagitem.h>, ApplyTagChanges(), FilterTagChanges()


utility.library/NamedObjectName

   NAME
    NamedObjectName -- return the name of the object. (V39)

   SYNOPSIS
    name = NamedObjectName(object);
    D0                     A0

    STRPTR NamedObjectName(struct NamedObject *);

   FUNCTION
    Returns the name of the object passed in...
    Note that the name string is passed back as just a pointer to
    a read-only name. If the object goes away, so does the name.

   INPUTS
    object - the object, may be NULL in which case this function
         returns NULL.

   RESULT
    name - pointer to the name string, or NULL if 'object' is NULL.

   SEE ALSO
    FindNamedObject(), RemNamedObject()


utility.library/NextTagItem

   NAME
    NextTagItem -- iterate through a tag list. (V36)

   SYNOPSIS
    tag = NextTagItem(tagItemPtr);
    D0		  A0

    struct TagItem *NextTagItem(struct TagItem **);

   FUNCTION
    Iterates through a tag list, skipping and chaining as dictated by
    system tags. TAG_SKIP will cause it to skip the entry and a number
    of following tags as specified in ti_Data. TAG_IGNORE ignores that
    single entry, and TAG_MORE has a pointer to another array of tags (and
    terminates the current array!). TAG_DONE also terminates the current
    array. Each call returns either the next tagitem you should examine,
    or NULL when the end of the list has been reached.

   INPUTS
    tagItemPtr - doubly-indirect reference to a TagItem structure.
             The pointer will be changed to keep track of the
             iteration.

   RESULTS
    nextTag	- each TagItem in the array or chain of arrays that should be
          processed according to system tag values defined in
          <utility/tagitem.h>) is returned in turn with successive
          calls.

   EXAMPLE
    Iterate(struct TagItem *tags);
    {
    struct TagItem *tstate;
    struct TagItem *tag;

        tstate = tags;
        while (tag = NextTagItem(&tstate))
        {
        switch (tag->ti_Tag)
        {
             case TAG1: ...
                   break;

             case TAG2: ...
                   break;

            ...
        }
        }
       }

   WARNING
    Do NOT use the value of *tagItemPtr, but rather use the pointer
    returned by NextTagItem().

   SEE ALSO
    <utility/tagitem.h>, GetTagData(), PackBoolTags(), FindTagItem()


utility.library/PackBoolTags

   NAME
    PackBoolTags -- builds a "flag" word from a tag list. (V36)

   SYNOPSIS
    flags = PackBoolTags(initialFlags,tagList,boolMap);
    D0		     D0		  A0      A1

    ULONG PackBoolTags(ULONG,struct TagItem *,struct TagItem *);

   FUNCTION
    Picks out the boolean tag items in a tag list and converts
    them into bit-flag representations according to a correspondence
    defined by the tag list 'boolMap'.

    A boolean tag item is one where only the logical value of
    the ti_Data is relevant. If this field is 0, the value is
    FALSE, otherwise TRUE.

   INPUTS
    initialFlags - a starting set of bit-flags which will be changed
               by the processing of TRUE and FALSE boolean tags
               in tagList.
    tagList	- a TagItem list which may contain several tag items defined to
          be boolean by their presence in boolMap. The logical value of
          ti_Data determines whether a tag item causes the bit-flag
          value related by boolMap to be set or cleared in the returned
          flag longword.
    boolMap	- a tag list defining the boolean tags to be recognized, and
          the bit (or bits) in the returned longword that are to be set
          or cleared when a boolean Tag is found to be TRUE or FALSE in
          tagList.

   RESULTS
    flags - the accumulated longword of bit-flags, starting with
        initialFlags and modified by each boolean tag item
        encountered.

   EXAMPLE
    /* define some nice user tag values ... */
    enum mytags { tag1 = TAG_USER+1, tag2, tag3, tag4, tag5 };

    /* this TagItem list defines the correspondence between boolean tags
     * and bit-flag values.
     */
    struct TagItem boolMap[] =
    {
        {tag1,     0x0001},
        {tag2,     0x0002},
        {tag3,     0x0004},
        {tag4,     0x0008},
        {TAG_DONE, }
    };

    /* You are probably passed these by some client, and you want
     * to "collapse" the boolean content into a single longword.
     */

    struct TagItem boolExample[] =
    {
        {tag1,     TRUE},
        {tag2,     FALSE},
        {tag5,     Irrelevant},
        {tag3,     TRUE},
        {TAG_DONE, }
    };

    /* Perhaps 'boolFlags' already has a current value of 0x800002. */
    boolFlags = PackBoolTags(boolFlags,boolExample,boolMap);

    /* The resulting new value of 'boolFlags' will be 0x80005. /*

   WARNING
    In a case where there is duplication of a tag in tagList, the
    last of the identical tags will hold sway.

   SEE ALSO
    <utility/tagitem.h>, GetTagData(), FindTagItem(), NextTagItem()


utility.library/PackStructureTags

   NAME
    PackStructureTags -- pack a structure with values from taglist. (V39)

   SYNOPSIS
    num = PackStructureTags(pack,packTable,tagList);
    D0                      A0   A1        A2

    ULONG PackStructureTags(APTR,ULONG *,struct TagItem *);

   FUNCTION
    For each table entry, a FindTagItem() will be done and if the
    matching tag is found in the taglist, the data field will be
    packed into the given structure based on the packtable
    definition.

   INPUTS
    pack - a pointer to the data area to fill in.
    packTable - a pointer to the packing information table.
            See <utility/pack.h> for definition and macros.
    tagList - a pointer to the taglist to pack into the structure

   RESULTS
    num - the number of tag items packed

   SEE ALSO
    <utility/pack.h>, FindTagItem(), UnpackStructureTags()


utility.library/RefreshTagItemClones

   NAME
    RefreshTagItemClones -- rejuvenate a clone from the original. (V36)

   SYNOPSIS
    RefreshTagItemClones(clone,original)
                 A0	   A1

    VOID RefreshTagItemClones(struct TagItem *,struct TagItem *);

   FUNCTION
    If (and only if) the tag list 'clone' was created from 'original' by
    CloneTagItems(), and if 'original' has not been changed in any way,
    you can reset the clone list to its original state by using this
    function.

   INPUTS
    clone - return value from CloneTagItems(original)
    original - a tag list that hasn't changed since CloneTagItems()

   SEE ALSO
    <utility/tagitem.h>, CloneTagItems(), AllocateTagItems(),
    FreeTagItems(), ApplyTagChanges()


utility.library/ReleaseNamedObject

   NAME
    ReleaseNamedObject -- free a named object. (V39)

   SYNOPSIS
    ReleaseNamedObject(object);
               A0

    VOID ReleaseNamedObject(struct NamedObject *);

   FUNCTION
    Decrements the open count of the object. If the object has been
    removed, and the count goes to 0, the remover will be notified
    that the object is now free.

   INPUTS
    object - the object to release.  (No action if NULL)

   SEE ALSO
    FindNamedObject(), RemNamedObject()


utility.library/RemNamedObject

   NAME
    RemNamedObject -- remove a named object. (V39)

   SYNOPSIS
    RemNamedObject(object, message);
                   A0      A1

    VOID RemNamedObject(struct NamedObject *, struct Message *);

   FUNCTION
    This function will post a request to release the object
    from whatever NameSpace it is in.  It will reply the message
    when the object is fully removed.  The message.mn_Node.ln_Name
    field will contain the object pointer or NULL if the object
    was removed by another process.

    This function will effectively do a ReleaseNamedObject()
    thus you must have "found" the object first.

   INPUTS
    object - the object to remove: Must be a valid NamedObject.
    message - message to ReplyMsg() (must be supplied)

   RESULT
    The message is replied with the ln_Name field either being
    the object or NULL. If it contains the object, the object
    is completely removed.

   SEE ALSO
    AttemptRemNamedObject(), AddNamedObject(), ReleaseNamedObject()


utility.library/SDivMod32

   NAME
    SDivMod32 -- signed 32 by 32 bit division and modulus. (V36)

   SYNOPSIS
    quotient:remainder = SDivMod32(dividend,divisor);
    D0       D1                    D0       D1

    LONG:LONG SDivMod32(LONG,LONG);

   FUNCTION
    Divides the signed 32 bit dividend by the signed 32 bit divisor
    and returns a signed 32 bit quotient and remainder.

   INPUTS
    dividend - signed 32 bit dividend.
    divisor - signed 32 bit divisor.

   RESULTS
    quotient - signed 32 quotient of the division.
    remainder - signed 32 remainder of the division.

   NOTES
    Unlike other Amiga library function calls, the utility.library
    32 bit math routines do NOT require A6 to be loaded with a
    pointer to the library base. A6 can contain anything the application
    wishes. This is in order to avoid overhead in calling them.

    In addition, the utility.library math routines preserve all
    address registers including A0 and A1

   SEE ALSO
    SMult32(), UDivMod32(), UMult32(), SMult64(), UMult64()


utility.library/SMult32

   NAME
    SMult32 -- signed 32 by 32 bit multiply with 32 bit result. (V36)

   SYNOPSIS
    result = SMult32(arg1,arg2);
    D0               D0   D1

    LONG SMult32(LONG,LONG);

   FUNCTION
    Returns the signed 32 bit result of multiplying arg1 by arg2.

   INPUTS
    arg1, arg2 - numbers to multiply

   RESULTS
    result - the signed 32 bit result of multiplying arg1 by arg2.

   NOTES
    Unlike other Amiga library function calls, the utility.library
    32 bit math routines do NOT require A6 to be loaded with a
    pointer to the library base. A6 can contain anything the application
    wishes. This is in order to avoid overhead in calling them.

    In addition, the utility.library math routines preserve all
    address registers including A0 and A1

   SEE ALSO
    SDivMod32(), UDivMod32(), UMult32(), SMult64(), UMult64()


utility.library/SMult64

   NAME
    SMult64 -- signed 32 by 32 bit multiply with 64 bit result. (V39)

   SYNOPSIS
    result = SMult64(arg1,arg2);
    D0:D1            D0   D1

    LONG SMult64(LONG,LONG);

   FUNCTION
    Returns the signed 64 bit result of multiplying arg1 by arg2.

   INPUTS
    arg1, arg2 - numbers to multiply

   RESULTS
    result - the signed 64 bit result of multiplying arg1 by arg2.

   NOTES
    Unlike other Amiga library function calls, the utility.library
    32 bit math routines do NOT require A6 to be loaded with a
    pointer to the library base. A6 can contain anything the application
    wishes. This is in order to avoid overhead in calling them.

    In addition, the utility.library math routines preserve all
    address registers including A0 and A1

   SEE ALSO
    SDivMod32(), UDivMod32(), UMult32(), UMult64()


utility.library/Stricmp

   NAME
    Stricmp	-- case-insensitive string comparison. (V37)

   SYNOPSIS
    result = Stricmp(string1,string2);
    D0		 A0      A1

    LONG Stricmp(STRPTR,STRPTR);

   FUNCTION
    This function compares two strings, ignoring case using a generic
    case conversion routine. If the strings have different lengths,
    the shorter is treated as if it were extended with zeros.

   INPUTS
    string1, string2 - strings to be compared

   RESULTS
    result - relationship between string1 and string2
            <0 means string1 < string2
            =0 means string1 = string2
            >0 means string1 > string2

   NOTES
    Whenever locale.library is installed in a system, this function is
    replaced by language-specific code. This means that depending on
    which language the user has currently selected, identical pairs of
    strings may return different values when passed to this function.
    This fact must be taken into consideration when using this function.

   SEE ALSO
    Strnicmp(), locale.library/StrnCmp()


utility.library/Strnicmp

   NAME
    Strnicmp -- length-limited case-insensitive string compare. (V37)

   SYNOPSIS
    result = Strnicmp(string1,string2,length);
    D0		  A0      A1	  D0

    LONG Strnicmp(STRPTR,STRPTR,LONG);

   FUNCTION
    This function compares two strings, ignoring case using a generic
    case conversion routine. If the strings have different lengths,
    the shorter is treated as if it were extended with zeros. This function
    never compares more than 'length' characters.

   INPUTS
    string1, string2 - strings to be compared
    length - maximum number of characters to examine

   RESULTS
    result - relationship between string1 and string2
            <0 means string1 < string2
            =0 means string1 = string2
            >0 means string1 > string2

   NOTES
    Whenever locale.library is installed in a system, this function is
    replaced by language-specific code. This means that depending on
    which language the user has currently selected, identical pairs of
    strings may return different values when passed to this function.
    This fact must be taken into consideration when using this function.

   SEE ALSO
    Stricmp(), locale.library/StrnCmp()


utility.library/TagInArray

   NAME
    TagInArray -- check if a tag value appears in an array of tag values.
              (V36)

   SYNOPSIS
    result = TagInArray(tagValue,tagArray);
    D0	            D0	     A0

    BOOL TagInArray(Tag,Tag *);

   FUNCTION
    Performs a quick scan to see if a tag value appears in an array
    terminated with TAG_DONE. Returns TRUE if the value is found.

    The 'tagArray' must be terminated by TAG_DONE. Note that this is an
    array of tag values, NOT an array of TagItems.

   INPUTS
    tagValue - tag value to search array for in array.
    tagArray - a simple array of tag values terminated by TAG_DONE.

   RESULTS
    result - TRUE if tagValue was found in tagArray.

   SEE ALSO
    <utility/tagitem.h>, FilterTagItems()


utility.library/ToLower

   NAME
    ToLower -- convert a character to lower case. (V37)

   SYNOPSIS
    char = ToLower(char);
    D0	       D0

    UBYTE ToLower(UBYTE);

   FUNCTION
    Converts a character to lower case, handling international character
    sets.

   INPUTS
    char - character to be converted.

   RESULTS
    char - lower case version of the input character.

   NOTES
    Whenever locale.library is installed in a system, this function is
    replaced by language-specific code. This means that depending on
    which language the user has currently selected, a given character may
    return different results when passed to this function. This fact must
    be taken into consideration when using this function.

   SEE ALSO
    ToUpper(), locale.library/ConvToLower()


utility.library/ToUpper

   NAME
    ToUpper -- convert a character to upper case. (V37)

   SYNOPSIS
    char = ToUpper(char);
    D0	       D0

    UBYTE ToUpper(UBYTE);

   FUNCTION
    Converts a character to upper case, handling international character
    sets.

   INPUTS
    char - character to be converted.

   RESULTS
    char - upper case version of input character.

   NOTES
    Whenever locale.library is installed in a system, this function is
    replaced by language-specific code. This means that depending on
    which language the user has currently selected, a given character may
    return different results when passed to this function. This fact must
    be taken into consideration when using this function.

   SEE ALSO
    ToUpper(), locale.library/ConvToLower()


utility.library/UDivMod32

   NAME
    UDivMod32 -- unsigned 32 by 32 bit division and modulus. (V36)

   SYNOPSIS
    quotient:remainder = UDivMod32(dividend,divisor);
    D0       D1                    D0       D1

    ULONG:ULONG UDivMod32(ULONG,ULONG);

   FUNCTION
    Divides the unsigned 32 bit dividend by the unsigned 32 bit divisor
    and returns an unsigned 32 bit quotient and remainder.

   INPUTS
    dividend - unsigned 32 bit dividend.
    divisor - unsigned 32 bit divisor.

   RESULTS
    quotient - unsigned 32 quotient of the division.
    remainder - unsigned 32 remainder of the division.

   NOTES
    Unlike other Amiga library function calls, the utility.library
    32 bit math routines do NOT require A6 to be loaded with a
    pointer to the library base. A6 can contain anything the application
    wishes. This is in order to avoid overhead in calling them.

    In addition, the utility.library math routines preserve all
    address registers including A0 and A1

   SEE ALSO
    SDivMod32(), SMult32(), UMult32()


utility.library/UMult32

   NAME
    UMult32 -- unsigned 32 by 32 bit multiply with 32 bit result. (V36)

   SYNOPSIS
    result = UMult32(arg1,arg2);
    D0               D0   D1

    ULONG UMult32(ULONG,ULONG);

   FUNCTION
    Returns the unsigned 32 bit result of multiplying arg1 by arg2.

   INPUTS
    arg1, arg2 - numbers to multiply

   RESULTS
    result - the unsigned 32 bit result of multiplying arg1 by arg2.

   NOTES
    Unlike other Amiga library function calls, the utility.library
    32 bit math routines do NOT require A6 to be loaded with a
    pointer to the library base. A6 can contain anything the application
    wishes. This is in order to avoid overhead in calling them.

    In addition, the utility.library math routines preserve all
    address registers including A0 and A1

   SEE ALSO
    SDivMod32(), SMult32(), UDivMod32(), SMult64(), UMult64()


utility.library/UMult64

   NAME
    UMult64 -- unsigned 32 by 32 bit multiply with 64 bit result. (V39)

   SYNOPSIS
    result = UMult64(arg1,arg2);
    D0:D1               D0   D1

    ULONG UMult64(ULONG,ULONG);

   FUNCTION
    Returns the unsigned 64 bit result of multiplying arg1 by arg2.

   INPUTS
    arg1, arg2 - numbers to multiply

   RESULTS
    result - the unsigned 64 bit result of multiplying arg1 by arg2.

   NOTES
    Unlike other Amiga library function calls, the utility.library
    32 bit math routines do NOT require A6 to be loaded with a
    pointer to the library base. A6 can contain anything the application
    wishes. This is in order to avoid overhead in calling them.

    In addition, the utility.library math routines preserve all
    address registers including A0 and A1

   SEE ALSO
    SDivMod32(), SMult32(), UDivMod32(), SMult64()


utility.library/UnpackStructureTags

   NAME
    UnpackStructureTags -- unpack a structure to values in taglist. (V39)

   SYNOPSIS
    num = UnpackStructureTags(pack,packTable,tagList);
    D0                        A0   A1        A2

    ULONG UnpackStructureTags(APTR,ULONG *,struct TagItem *);

   FUNCTION
    For each table entry, a FindTagItem() will be done and if the
    matching tag is found in the taglist, the data in the structure
    will be placed into the memory pointed to by the tag's ti_Data.
    ti_Data *must* point to a LONGWORD.

   INPUTS
    pack - a pointer to the data area to be unpacked
    packTable - a pointer to the packing information table.
            See <utility/pack.h> for definition and macros
    tagList - a pointer to the taglist to unpack into

   RESULTS
    num - the number of tag items unpacked

   SEE ALSO
    <utility/pack.h>, FindTagItem(), PackStructureTags()


wb.doc

     AddAppIconA()
     AddAppMenuItemA()
     AddAppWindowA()
     AddAppWindowDropZoneA()
     ChangeWorkbenchSelectionA()
     CloseWorkbenchObjectA()
     MakeWorkbenchObjectVisibleA()
     OpenWorkbenchObjectA()
     RemoveAppIcon()
     RemoveAppMenuItem()
     RemoveAppWindow()
     RemoveAppWindowDropZone()
     WBInfo()
     WorkbenchControlA()


workbench.library/AddAppIconA

   NAME
    AddAppIconA - add an icon to Workbench's list of AppIcons.       (V36)

   SYNOPSIS
    AppIcon = AddAppIconA(id, userdata, text, msgport,
       D0                 D0     D1      A0     A1

                          lock, diskobj, taglist)
                          A2      A3      A4

    struct AppIcon *AddAppIconA(ULONG, ULONG, char *,
            struct MsgPort *, BPTR, struct DiskObject *,
            struct TagItem *);

    Alternate, varargs version:
    struct AppIcon *AddAppIcon(ULONG, ULONG, char *,
                               struct MsgPort *, BPTR,
                               struct DiskObject *,
                               tag1, data1,
                               tag2, data2,
                               ...
                               TAG_END );

   FUNCTION
    Attempt to add an icon to Workbench's list of AppIcons.  If
    successful, the icon is displayed on the Workbench backdrop (the
    same place disk icons are displayed).

    This call is provided to allow applications to be notified when
    a graphical object (not neccessarely associated with a file)
    gets 'manipulated'.

    The notification consists of an AppMessage (found in workbench.h/i)
    of type 'MTYPE_APPICON' arriving at the message port you specified.

    The types of 'manipulation' that can occur are:

    1. Double-clicking on the icon.  am_NumArgs will be zero and
       am_ArgList will be NULL.
    2. Dropping an icon or icons on your AppIcon.  am_NumArgs will
       be the number of icons dropped on your AppIcon plus one.
       am_ArgList will be an array of pointers to WBArg structures.
       Refer to the 'WBStartup Message' section of the RKM for more info.
    3. Dropping your AppIcon on another icon.  NOT SUPPORTED.
    4. Invoking an "Icons" menu item with your icon selected. (V44)
       You have to tell Workbench which menu items your icon
       responds to using the tag item list you provide to AddAppIconA().
       When one of the supported menu items is invoked, you
       will receive an AppMessage with the am_Class entry set to
       a value out of AMCLASSICON_Open..AMCLASSICON_EmptyTrash,
       corresponding to the menu item used.

   INPUTS
    id - this variable is strictly for your own use and is ignored by
         Workbench.  Typical uses in C are in switch and case statements,
         and in assembly language table lookup.
    userdata - this variable is strictly for your own use and is ignored
               by Workbench.
    text - name of icon (char *)
    lock - NULL    (Currently unused)
    msgport - pointer to message port Workbench will use to send you an
              AppMessage message of type 'MTYPE_APPICON' when your icon
              gets 'manipulated' (explained above).
    diskobj - pointer to a DiskObject structure filled in as follows:
        do_Magic - NULL
        do_Version - NULL
        do_Gadget - a gadget structure filled in as follows:
            NextGadget - NULL
            LeftEdge - NULL
            TopEdge - NULL
            Width - width of icon hit-box
            Height - height of icon hit-box
            Flags - NULL or GADGHIMAGE
            Activation - NULL
            GadgetType - NULL
            GadgetRender - pointer to Image structure filled in as follows:
                LeftEdge - NULL
                TopEdge - NULL
                Width - width of image (must be <= Width of hit box)
                Height - height of image (must be <= Height of hit box)
                Depth - # of bit-planes in image
                ImageData - pointer to actual word aligned bits (CHIP MEM)
                PlanePick - Plane mask ((1 << depth) - 1)
                PlaneOnOff - 0
                NextImage - NULL
            SelectRender - pointer to alternate Image struct or NULL
            GadgetText - NULL
            MutualExclude - NULL
            SpecialInfo - NULL
            GadgetID - NULL
            UserData - NULL
        do_Type - NULL
        do_DefaultTool - NULL
        do_ToolTypes - NULL
        do_CurrentX - NO_ICON_POSITION (recommended)
        do_CurrentY - NO_ICON_POSITION (recommended)
        do_DrawerData - NULL
        do_ToolWindow - NULL
        do_StackSize - NULL

    (an easy way to create one of these (a DiskObject) is to create an icon
     with the V2.0 icon editor and save it out.  Your application can then
     call GetDiskObject on it and pass that to AddAppIcon.)

    taglist - ptr to a list of tag items.  Must be NULL for V2.0.

   TAGS
    WBAPPICONA_SupportsOpen (BOOL) -- Set this to TRUE if your
        AppIcon should respond to the "Open" menu, to FALSE
        otherwise. Note that with this attribute set to FALSE,
        users will still be able to double-click on your AppIcon
        and drop icons on it. This attribute solely controls
        whether the "Open" menu item will be available.

        This tag defaults to TRUE. (V44)

    WBAPPICONA_SupportsCopy (BOOL) -- Set this to TRUE if your
        AppIcon should respond to the "Copy" menu, to FALSE
        otherwise.

        This tag defaults to FALSE. (V44)

    WBAPPICONA_SupportsRename (BOOL) -- Set this to TRUE if your
        AppIcon should respond to the "Rename" menu, to FALSE
        otherwise.

        This tag defaults to FALSE. (V44)

    WBAPPICONA_SupportsInformation (BOOL) -- Set this to TRUE if your
        AppIcon should respond to the "Information" menu, to FALSE
        otherwise.

        This tag defaults to FALSE. (V44)

    WBAPPICONA_SupportsSnapshot (BOOL) -- Set this to TRUE if your
        AppIcon should respond to the "Snapshot" menu, to FALSE
        otherwise.

        This tag defaults to FALSE. (V44)

    WBAPPICONA_SupportsUnSnapshot (BOOL) -- Set this to TRUE if your
        AppIcon should respond to the "UnSnapshot" menu, to FALSE
        otherwise.

        This tag defaults to FALSE. (V44)

    WBAPPICONA_SupportsLeaveOut (BOOL) -- Set this to TRUE if your
        AppIcon should respond to the "Leave Out" menu, to FALSE
        otherwise.

        This tag defaults to FALSE. (V44)

    WBAPPICONA_SupportsPutAway (BOOL) -- Set this to TRUE if your
        AppIcon should respond to the "Put Away" menu, to FALSE
        otherwise.

        This tag defaults to FALSE. (V44)

    WBAPPICONA_SupportsDelete (BOOL) -- Set this to TRUE if your
        AppIcon should respond to the "Delete" menu, to FALSE
        otherwise.

        This tag defaults to FALSE. (V44)

    WBAPPICONA_SupportsFormatDisk (BOOL) -- Set this to TRUE if your
        AppIcon should respond to the "Format Disk" menu, to FALSE
        otherwise.

        This tag defaults to FALSE. (V44)

    WBAPPICONA_SupportsEmptyTrash (BOOL) -- Set this to TRUE if your
        AppIcon should respond to the "Empty Trash" menu, to FALSE
        otherwise.

        This tag defaults to FALSE. (V44)

    WBAPPICONA_PropagatePosition (BOOL) -- Set this to TRUE if you
        want the AppIcon's position to be propagated back to the
        original DiskObject you passed to this function. By
        default, Workbench will make a copy of that DiskObject's
        icon imagery, allowing you to free the DiskObject.
        But if you specify "WBAPPICONA_PropagatePosition,TRUE,"
        Workbench will assume that you will not free it and
        that the AppIcon's current position should be stored
        in its do_CurrentX/do_CurrentY members.

        This tag defaults to FALSE. (V44)

    WBAPPICONA_RenderHook (struct Hook *) -- Pointer to a hook that
        will be invoked when rendering your AppIcon. With this hook
        and WorkbenchControlA() you can create dynamic or animated
        AppIcons. Your hook will be called with the following
        parameters and has to return a result value:

        result = hookFunc(hook,reserved,arm)
          D0               A0     A2     A1

        LONG hookFunc(struct Hook *hook,APTR reserved,
                      struct AppIconRenderMsg *arm);

        The reserved parameter will be set to NULL (V44).

        If your hook code returns TRUE, the AppIcon's regular image
        will be drawn. If your code returns FALSE, the regular image
        will not be drawn; this allows you to do all the icon's on-screen
        rendering with the exception of the icon image used when dragging
        the icon on the screen.

        The render message contents are as follows:

            arm_RastPort
                A pointer to the RastPort to render into.

            arm_Icon
                A pointer to the Icon to be rendered.

            arm_Label
                A pointer to the label text to be printed
                below the icon.

            arm_Tags
                Further control tags which you should pass on
                to icon.library/DrawIconStateA, should you
                call this routine.

            arm_Left
            arm_Top
                Rendering origin; note that these coordinates
                DO NOT take the embossing border sizes into
                account.

            arm_Width
            arm_Height
                Size of the Icon's image area; you should limit
                your drawing to this area.

            arm_State
                An icon drawing state, such as used by
                icon.library/DrawIconStateA.

        Note that all the data in the render message is read-only.

        This tag defaults to NULL. (V44)

    WBAPPICONA_NotifySelectState (BOOL) -- Set this tag to TRUE
        if you want to be be notified whenever the AppIcon becomes
        selected or unselected. You will hear only state transitions,
        i.e. changes from selected to unselected state and the other
        way round. On a state transition you will receive AppMessages
        with the AppMessage->am_Class member set to AMCLASSICON_Selected
        or AMCLASSICON_Unselected, respectively.

        This tag defaults to FALSE. (V44)

   RESULTS
    AppIcon - a pointer to an AppIcon structure which you pass to
              RemoveAppIcon when you want to remove the icon
              from Workbench's list of AppIcons.  NULL
              if Workbench was unable to add your icon; typically
              happens when Workbench is not running or under low
              memory conditions.

   EXAMPLE
    You could design a print-spooler icon and add it to the Workbench.
    Any file dropped on the print spooler would be printed.  If the
    user double-clicked (opened) your printer-spooler icon, you could
    open a window showing the status of the print spool, allow changes
    to print priorities, allow deletions, etc.  If you registered this
    window as an 'AppWindow' (explained in workbench.library/AddAppWindow)
    files could also be dropped in the window and added to the spool.

   NOTES
    For this function call to succeed, Workbench must be open. This
    means that the LoadWB command was executed and the Workbench
    screen has been opened.

   SEE ALSO
    workbench.library/RemoveAppIcon
    workbench.library/WorkbenchControlA
    icon.library/DrawIconStateA

   BUGS
    In workbench.library versions 36 through 40 Info cannot be obtained
    on appicons.


workbench.library/AddAppMenuItemA

   NAME
    AddAppMenuItemA - add a menu item to Workbench's list            (V36)
                         of AppMenuItems.

   SYNOPSIS
    AppMenuItem = AddAppMenuItemA(id, userdata, text, msgport, taglist)
    D0                            D0     D1      A0     A1       A2

    struct AppMenuItem *AddAppMenuItemA(ULONG, ULONG, char *,
                                        struct MsgPort *,
                                        struct TagItem *);

    Alternate, varargs version:
    struct AppMenuItem *AddAppMenuItem(ULONG, ULONG, char *,
                                       struct MsgPort *,
                                       tag1, data1,
                                       tag2, data2,
                                       ...
                                       TAG_END );

   FUNCTION
    Attempt to add the text as a menu item to Workbench's list
    of AppMenuItems (the 'Tools' menu strip).

   INPUTS
    id - this variable is strictly for your own use and is ignored by
         Workbench.  Typical uses in C are in switch and case statements,
         and in assembly language table lookup.
    userdata - this variable is strictly for your own use and is ignored
               by Workbench.
    text - text for the menu item (char *); starting with V44, any menu
           label consisting entirely of '-', '_' or '~' characters will
           result in a separator bar to be added in place of a textual
           item.
    msgport - pointer to message port Workbench will use to send you an
              AppMessage message of type 'MTYPE_APPMENUITEM' when your
              menuitem gets selected.
    taglist - ptr to a list of tag items.  Must be NULL for V2.0.

   TAGS
    WBAPPMENUA_CommandKeyString (STRPTR) -- Command key to assign to
        this AppMenu. This must be a NUL-terminated string. If the
        string is empty, it will be ignored. Also, if the command key
        is already in use by a different menu item it will be ignored,
        too. In any case, only the first character of the string will
        be used (V44).

        This tag defaults to NULL.

   RESULTS
    AppMenuItem - a pointer to an appmenuitem structure which you pass to
                  RemoveAppMenuItem when you want to remove the menuitem
                  from Workbench's list of AppMenuItems.  NULL if
                  workbench was unable to add your menu item; typically
                  happens when Workbench is not running or under low
                  memory conditions.

              Starting with V44 NULL will be returned if you attempt to
              add an AppMenu item to a menu which already contains 63
              menu items.

   NOTES
    For this function call to succeed, Workbench must be open. This
    means that the LoadWB command was executed and the Workbench
    screen has been opened.

   SEE ALSO
    workbench.library/RemoveAppMenuItem

   BUGS
    workbench.library V37 through V40 does not limit the number of menu
    items to 63. Any menu items after the 63rd will not be selectable.
    This bug was fixed in V44.


workbench.library/AddAppWindowA

   NAME
    AddAppWindowA - add a window to Workbench's list of AppWindows.  (V36)

   SYNOPSIS
    AppWindow = AddAppWindowA(id, userdata, window, msgport, taglist)
    D0                        D0     D1       A0      A1       A2

    struct AppWindow *AddAppWindowA(ULONG, ULONG, struct Window *,
                                    struct MsgPort *, struct TagItem *);

    Alternate, varargs version:
    struct AppWindow *AddAppWindow(ULONG, ULONG, struct Window *,
                                   struct MsgPort *
                                   tag1, data1,
                                   tag2, data2,
                                   ...
                                   TAG_END );

   FUNCTION
    Attempt to add the window to Workbench's list of AppWindows.
    Normally non-Workbench windows (those not opened by Workbench)
    cannot have icons dropped in them.  This call is provided to
    allow applications to be notified when an icon or icons get
    dropped inside a window that they have registered with Workbench.
    The notification consists of an AppMessage (found in workbench.h/i)
    of type 'MTYPE_APPWINDOW' arriving at the message port you specified.
    What you do with the list of icons (pointed to by am_ArgList) is
    up to you, but generally you would want to call GetDiskObjectNew on
    them.

   INPUTS
    id - this variable is strictly for your own use and is ignored by
         Workbench.  Typical uses in C are in switch and case statements,
         and in assembly language table lookup.
    userdata - this variable is strictly for your own use and is ignored
               by Workbench.
    window - pointer to window to add.
    msgport - pointer to message port Workbench will use to send you an
              AppMessage message of type 'MTYPE_APPWINDOW' when your
              window gets an icon or icons dropped in it.
    taglist - ptr to a list of tag items.  Must be NULL for V2.0.

   RESULTS
    AppWindow - a pointer to an AppWindow structure which you pass to
                RemoveAppWindow when you want to remove the window
                from Workbench's list of AppWindows.  NULL
                if Workbench was unable to add your window; typically
                happens when Workbench is not running or under low
                memory conditions.

   SEE ALSO
    workbench.library/AddAppWindowDropZoneA
    workbench.library/RemoveAppWindow

   NOTES
    The V2.0 icon editor is an example of an AppWindow.  Note that app
    window applications generally want to call GetDiskObjectNew
    (as opposed to GetDiskObject) to get the disk object for the icon
    dropped in the window.

    For this function call to succeed, Workbench must be open. This
    means that the LoadWB command was executed and the Workbench
    screen has been opened.

    When removing an AppWindow, all its drop zones will be automatically
    removed.


workbench.library/AddAppWindowDropZoneAorkbench.library/AddAppWindowDropZoneA

   NAME
    AddAppWindowDropZoneA -- Designate an AppWindow area as suitable for
        dropping icons on. (V44)

   SYNOPSIS
    dropZone = AddAppWindowDropZoneA(appWindow,id,userData,tags)
       D0                               A0    D0    D1     A1

    struct AppWindowDropZone * AddAppWindowDropZoneA(struct AppWindow *aw,
                               ULONG id,ULONG userData,
                               struct TagItem * tags);

    dropZone = AddAppWindowDropZone(appWindow,id,userData,zone,...)

    struct AppWindowDropZone * AddAppWindowDropZone(struct AppWindow *aw,
                               ULONG id,ULONG userData,...);

   FUNCTION
    Once it is created, Workbench will allow the user to drop an
    icon anywhere inside an AppWindow, regardless of whether the
    icon was dropped on an area designated for dropping icons on
    or not. With AddAppWindowDropZoneA() you can tell Workbench
    which AppWindow areas are suitable for dropping icons on.

   INPUTS
    aw -- An AppWindow data structure, as returned by
        workbench.library/AddAppWindowA.
    id -- This variable is strictly for your own use and is ignored by
        Workbench. Typical uses in C are in switch and case statements,
        and in assembly language table lookup. Later, when an icon is
        dropped on the designated area, the AppMessage sent to your
        port will have the am_ID member set to this value.
    userData -- this variable is strictly for your own use and is ignored
        by Workbench. Later, when an icon is dropped on the designated area,
        the AppMessage sent to your port will have the am_UserData member
        set to this value.
    tags -- List of attributes to control the position and size
        of the drop zone.

   TAGS
    WBDZA_Left (WORD) -- Left edge of the drop zone; a value of
        0 would create a zone located at the left corner of the
        window.

    WBDZA_RelRight (WORD) -- Left edge of the drop zone, relative
        to the window width; a value of -10 would create a zone located
        10 pixels left of the window right edge.

    WBDZA_Top (WORD) -- Top edge of the drop zone; a value of
        0 would create a zone located at the top corner of the
        window.

    WBDZA_RelBottom (WORD) -- Top edge of the drop zone, relative
        to the window height; a value of -10 would create a zone located
        10 pixels above the window bottom edge.

    WBDZA_Width (WORD) -- Width of the drop zone.

    WBDZA_RelWidth (WORD) -- Width of the drop zone, relative to the
        width of the window; a value of -20 would create a zone that
        is by 20 pixels narrower than the window.

    WBDZA_Height (WORD) -- Height of the drop zone.

    WBDZA_RelHeight (WORD) -- Height of the drop zone, relative to the
        height of the window; a value of -20 would create a zone that
        is by 20 pixels smaller than the window.

    WBDZA_Box (struct IBox *) -- Position and size of the drop zone.

    WBDZA_Hook (struct Hook *) -- Pointer to a hook that will be
        invoked whenever the mouse enters or leaves your drop zone
        area. Your hook will be called with the following parameters:

        result = hookFunc(hook,reserved,arm)
          D0               A0     A2     A1

        LONG hookFunc(struct Hook *hook,APTR reserved,
                      struct AppWindowDropZoneMsg *adzm);

        The reserved parameter will be set to NULL (V44).
        For future enhancement, make sure that your hook
        function always returns NULL (V44).

        The drop zone message contents are as follows:

            adzm_RastPort
                A pointer to the RastPort to render into.
                Typically, this is the RastPort of the window
                the drop zone is attached to.

            adzm_DropZoneBox
                This member describes the position and size
                of the drop zone. The zone is guaranteed to
                be a valid area, i.e. the Width and Height
                will both be greater than 0 and the Left/Top
                will be well within the bounds of the window
                containing the drop zone.

            adzm_ID
            adzm_UserData
                These two come straight from the values you passed
                as the id and userData parameters to
                AddAppWindowDropZoneA().

            adzm_Action
                Depending upon whether the mouse has just entered
                or left the drop zone area, this variable will be
                set to ADZMACTION_Enter or to ADZMACTION_Leave.
                Any other values for adzm_Action should be ignored.

                When the mouse enters the drop zone, do your drop
                zone area highlighting. When the mouse leaves the
                drop zone, remove any highlighting done in the
                previous ADZMACTION_Enter pass.

                Note that the mouse leaving your drop zone box
                does not imply that no icons will be dropped on it.
                You may still receive a notification lateron, telling
                you that your drop zone had icons dropped on it.
                The hook function is solely for highlighting and
                unhighlighting the drop zone area.

        A final word of warning: when your hook code is called, you
        must limit your rendering to simple drawing operations
        from graphics.library; if you do anything complex that
        involves Intuition locking and unlocking the display,
        such as refreshing gadgets or locking IntuitionBase,
        you will deadlock the operating system. You have been
        warned!

   RESULT
    dropZone -- A newly created drop zone identifier, or NULL if
        it could not be created; use dos.library/IoErr to find out
        what caused it to fail.

   NOTES
    Once an AppWindow has a drop zone installed, Workbench will send
    a new type of AppMessage to your port if icons are dropped on
    a drop zone. Instead of AMTYPE_APPWINDOW type messages you
    will receive AMTYPE_APPWINDOWZONE messages. In fact, you will
    no longer hear any AMTYPE_APPWINDOW type messages since Workbench
    will allow users to drop icons only on drop zones. Be prepared
    to handle this.

    Adding a drop zone to an AppWindow does not guarantee that only
    AMTYPE_APPWINDOWZONE type messages will arrive at your message
    port. In fact, the user may be able to drop an icon on the window
    before the first drop zone is installed. Be prepared to handle
    this.

    Workbench checks drop zones in the order in which they were added
    to the AppWindow. Thus, if two zones overlap, the zone that was
    added first will be reported as hit.

    An AppWindow starts out with its entire area available for dropping
    icons on. Thus, you may receive AppMessages for icons dropped upon
    your AppWindow before you have added the first drop zone to it.
    Be prepared to handle this.

    Drop zones must be created with a position and a size. If you omit
    either one, this routine will fail.

    When an icon is dropped on a drop zone, the AppMessage am_MouseX and
    am_MouseY members will be relative to the window top left corner;
    they WILL NOT be relative to the left/top edge of the drop zone.

   SEE ALSO
    dos.library/IoErr
    workbench.library/AddAppWindowA


workbench.library/ChangeWorkbenchSelectionA.library/ChangeWorkbenchSelectionA

   NAME
    ChangeWorkbenchSelectionA -- Change the selection states of icons
        displayed by Workbench. (V44)

   SYNOPSIS
    success = ChangeWorkbenchSelectionA(name,hook,tags)
       D0                                A0   A1   A2

    BOOL ChangeWorkbenchSelectionA(STRPTR name,struct Hook *hook,
                                   struct TagItem *tags);

    success = ChangeWorkbenchSelection(name,hook,...);

    BOOL ChangeWorkbenchSelection(STRPTR name,struct Hook *hook,...);

   FUNCTION
    The icons displayed inside each Workbench window can be in selected
    or in unselected state. This routine allows you to change this state
    for every icon found in a particular window.

   INPUTS
    name -- Name of the drawer whose icons should be submitted to the
        callback hook for testing; pass NULL as the name to have the
        icons in the Workbench backdrop (where disks and AppIcons live)
        passed through the hook. Note that the drawer whose icons you
        want to change must be open before you can make any changes.

    hook -- Hook to be invoked for each icon in the window.

        The hook code will be invoked with the following parameters

        action = hookFunc(hook,reserved,ism)
           D0                A0     A2    A1

        ULONG hookFunc(struct Hook *hook,APTR reserved,
                       struct IconSelectMsg *ism);

        The reserved parameter will be set to NULL (V44).

        The IconSelectMsg contents are as follows:

            ism_Length
                Size of the IconSelectMsg data structure (in bytes).
                Since this message may need to grow in the future,
                always compare this value against the message size
                you expect. For V44, ism_Length is guaranteed to
                contain a value of 36. Expect this value to become
                larger in the future.

            ism_Drawer
                A lock on the drawer the object in question resides
                in. This may be NULL for the Workbench backdrop (where
                disks and AppIcons live).

            ism_Name
                Name of the object in question; please note that for
                disk icons the name does not end with a colon character
                (":").

            ism_Type
                This is one of WBDISK, WBDRAWER, WBTOOL, WBPROJECT,
                WBGARBAGE, WBDEVICE, WBKICK or WBAPPICON.

            ism_Selected
                TRUE if the object in question is currently selected,
                FALSE otherwise.

            ism_Tags
                The list of tag items passed to ChangeWorkbenchSelectionA().

            ism_DrawerWindow
                If the object in question is a drawer or disk and its
                associated window is currently open, then you will find
                a pointer to it here.

            ism_ParentWindow
                This is a pointer to the window the object resides in.

            ism_Left
            ism_Top
            ism_Width
            ism_Height
                These denote the position and size of the object in
                question, relative to the top left edge of the window
                it resides in.

        With the exception of the ism_Left and ism_Top members, the
        IconSelectMsg is read-only. The ism_Left/ism_Top members can
        be used to change the position of the icon.

        You hook code must return one of the following values:

            ISMACTION_Unselect
                Unselect the icon

            ISMACTION_Select
                Select the icon

            ISMACTION_Ignore
                Do not change the selection state of the icon.

            ISMACTION_Stop
                Do not change the selection state of the icon. Do not
                invoke the hook function again.

    tags -- Additional options.

   TAGS
    No tags are defined yet (V44).

   RESULTS
    result -- FALSE if the drawer in question could not be found,
        TRUE otherwise. If FALSE is returned, you can query the error
        code using dos.library/IoErr().

   EXAMPLE
    /* Select the icon labeled "Prefs" in the drawer "SYS:". */
    struct Hook hook;

    /* This hook code is responsible for selecting the icon. */
    BOOL
    SelectPrefs(struct Hook *hook,APTR reserved,struct IconSelectMsg *ism)
    {
        /* Remember the old icon select status; if the icon name
         * does not match "Prefs", this is what we will return,
         * not changing anything.
         */
        BOOL selected = ism->ism_Selected;

        /* If the name matches, select it. Otherwise, leave its
         * select state alone.
         */
        if(Stricmp(ism->ism_Name,"Prefs") == 0)
            selected = TRUE;

        return(selected);
    }

    .
    .
    .

    /* Set up the hook data structure. */
    hook.h_Entry = HookEntry;
    hook.h_SubEntry = (HOOKFUNC)SelectPrefs;

    /* And finally change the selection. */
    ChangeWorkbenchSelection("SYS:",&hook,TAG_END);

   NOTES
    The name of the drawer to work on is interpreted relative
    to the current directory of the program to call
    ChangeWorkbenchSelectionA().

    For this function call to succeed, Workbench must be open. This
    means that the LoadWB command was executed and the Workbench
    screen has been opened.

    While the user is dragging icons, no on-screen rendering may
    take place. In this state Workbench may refuse to execute the
    ChangeWorkbenchSelection() call and return an error code instead
    (ERROR_OBJECT_IN_USE).

   SEE ALSO
    dos.library/IoErr


workbench.library/CloseWorkbenchObjectAorkbench.library/CloseWorkbenchObjectA

   NAME
    CloseWorkbenchObjectA -- Close a drawer as if the user had clicked
        on the window close gadget. (V44)

   SYNOPSIS
    success = CloseWorkbenchObjectA(name,tags)
       D0                            A0   A1

    BOOL CloseWorkbenchObjectA(STRPTR name,struct TagItem *tags);

    success = CloseWorkbenchObject(name,...);

    BOOL CloseWorkbenchObject(STRPTR name,...);

   FUNCTION
    This routine attempts to close the named object as if the user
    had clicked on its drawer window close gadget.

   INPUTS
    name -- Name of the drawer to be closed.

    tags -- Additional options.

   TAGS
    No tags are defined yet (V44).

   RESULTS
    result -- FALSE if the object in question could not be closed,
        TRUE otherwise. If FALSE is returned, you can query the error
        code using dos.library/IoErr().

   EXAMPLE
    /* Close the drawer "SYS:" */
    CloseWorkbenchObjectA("SYS:",NULL);

   NOTES
    The name of the drawer to be closed is interpreted relative
    to the current directory of the program to call
    CloseWorkbenchObjectA().

    For this function call to succeed, Workbench must be open. This
    means that the LoadWB command was executed and the Workbench
    screen has been opened.

    While the user is dragging icons, no on-screen rendering may
    take place. In this state Workbench may refuse to execute the
    CloseWorkbenchObject() call and return an error code instead
    (ERROR_OBJECT_IN_USE).

   SEE ALSO
    dos.library/IoErr
    workbench.library/OpenWorkbenchObjectA


workbench.library/MakeWorkbenchObjectVisibleArary/MakeWorkbenchObjectVisibleA

   NAME
    MakeWorkbenchObjectVisibleA -- Change a Workbench window in such a
        way as to make a particular icon visible. (V44)

   SYNOPSIS
    success = MakeWorkbenchObjectVisibleA(name,tags)
       D0                                  A0   A1

    BOOL MakeWorkbenchObjectVisibleA(STRPTR name,struct TagItem *tags);

    success = MakeWorkbenchObjectVisible(name,...);

    BOOL MakeWorkbenchObjectVisible(STRPTR name,...);

   FUNCTION
    Due to how the scrollers of a Workbench window affect the positions
    of the icons inside that window, some icons may not be drawn inside
    the bounds of the window. By using MakeWorkbenchObjectVisibleA()
    the window scrollers can be made to scroll such a "hidden" icon
    into view.

   INPUTS
    name -- Name of the icon to make visible. Note that the window
        the icon resides in must already be open.

    tags -- Additional options.

   TAGS
    No tags are defined yet (V44).

   RESULTS
    result -- FALSE if the icon in question could not be found,
        TRUE otherwise. If FALSE is returned, you can query the error
        code using dos.library/IoErr().

   EXAMPLE
    /* Make the icon for the drawer "SYS:" visible. */
    MakeWorkbenchObjectVisible("SYS:",TAG_END);

   NOTES
    The name of the icon to make visible is interpreted relative
    to the current directory of the program to call
    MakeWorkbenchObjectVisibleA().

    For this function call to succeed, Workbench must be open. This
    means that the LoadWB command was executed and the Workbench
    screen has been opened.

    While the user is dragging icons, no on-screen rendering may
    take place. In this state Workbench may refuse to execute the
    MakeWorkbenchObjectVisible() call and return an error code instead
    (ERROR_OBJECT_IN_USE).

   SEE ALSO
    dos.library/IoErr


workbench.library/OpenWorkbenchObjectA

   NAME
    OpenWorkbenchObjectA -- Open a drawer or launch a program as if
        the user had double-clicked on an icon. (V44)

   SYNOPSIS
    success = OpenWorkbenchObjectA(name,tags)
       D0                           A0   A1

    BOOL OpenWorkbenchObjectA(STRPTR name,struct TagItem *tags);

    success = OpenWorkbenchObject(name,...);

    BOOL OpenWorkbenchObject(STRPTR name,...);

   FUNCTION
    This routine attempts to open the named object as if the user
    had double-clicked on its icon. This allows you to open drawers
    under program control or to have Workbench launch your programs.

   INPUTS
    name -- Name of the object to be opened; this can be a drawer
        name, a tool name or a project name.

    tags -- Additional options.

   TAGS
    WBOPENA_ArgLock (BPTR) -- Corresponds to the WBArg->wa_Lock
        entry of a WBStartup message, to be sent to a program
        to be launched. The lock you provide will be duplicated
        when it is put into a WBArg list.

        The WBOPENA_ArgLock determines the lock parameters
        to be associated with all following WBOPENA_ArgName tags.

        This tag defaults to NULL.

    WBOPENA_ArgName (STRPTR) -- Corresponds to the WBArg->wa_Name
        entry of a WBStartup message to be sent to a program
        to be launched. This tag can be used to construct a list
        of parameters to pass to the tool/project to be launched.
        It works in conjunction with the WBOPENA_ArgLock tag.
        The name you provide will be duplicated when it is put
        into a WBArg list.

   RESULTS
    result -- FALSE if the object in question could not be opened,
        TRUE otherwise. Note that TRUE may be returned even if
        the program the object represents could not be launched;
        this is due to limitations in the current (V44) Workbench
        design. If FALSE is returned, you can query the error
        code using dos.library/IoErr().

   EXAMPLE
    /* Launch Multiview with S:Startup-Sequence as its parameter. */
    OpenWorkbenchObject("MultiView",
        WBOPENA_ArgLock, Lock("S:",SHARED_LOCK),
        WBOPENA_ArgName, "Startup-Sequence",
    TAG_DONE);

    /* Launch the application "Paint" with the project files "Image1"
     * and "Image2", which are both found in the drawer "Paint:Pictures".
     */
    OpenWorkbenchObject("Paint",
        WBOPENA_ArgLock, Lock("Paint:Pictures",SHARED_LOCK),
        WBOPENA_ArgName, "Image1",
        WBOPENA_ArgName, "Image2",
    TAG_DONE);

    /* Launch the application "Paint" with the project files "Image1"
     * and "Anim1", which are both found in the drawers "Paint:Pictures"
     * and "Paint:Animations", respectively.
     */
    OpenWorkbenchObject("Paint",
        WBOPENA_ArgLock, Lock("Paint:Pictures",SHARED_LOCK),
        WBOPENA_ArgName, "Image1",
        WBOPENA_ArgLock, Lock("Paint:Animations",SHARED_LOCK),
        WBOPENA_ArgName, "Anim1",
    TAG_DONE);

   NOTES
    You need not specify fully qualified path names for programs to
    be launched. Workbench will look for files without fully
    qualified path names along its default Shell search path.
    In any case, Workbench will look for the tool to be launched
    in the current directory of the program that called
    OpenWorkbenchObjectA(). The same holds true for drawers.

    When launching a program, Workbench will automatically figure
    out which tool to use if the object in question is actually a
    project file with a project icon. Note that if the project
    icon's default tool cannot be found, you will not see any
    error message.

    Workbench transparently supports launching of Shell programs,
    but this is not recommended. You should always launch Shell
    programs from your own process.

    When you open a drawer, all WBOPENA_Arg[..] parameters you may
    have provided will be ignored.

    For this function call to succeed, Workbench must be open. This
    means that the LoadWB command was executed and the Workbench
    screen has been opened.

    While the user is dragging icons, no on-screen rendering may
    take place. In this state Workbench may refuse to execute the
    OpenWorkbenchObject() call and return an error code instead
    (ERROR_OBJECT_IN_USE).

   SEE ALSO
    dos.library/IoErr
    workbench.library/CloseWorkbenchObjectA
    <workbench/startup.h>


workbench.library/RemoveAppIcon

   NAME
    RemoveAppIcon - remove an icon from Workbench's list            (V36)
                         of AppIcons.

   SYNOPSIS
    success = RemoveAppIcon(AppIcon)
         D0                      A0

    BOOL RemoveAppIcon(struct AppIcon *);

   FUNCTION
    Attempt to remove an AppIcon from Workbench's list of AppIcons.

   INPUTS
    AppIcon - pointer to an AppIcon structure returned by AddAppIcon.

   RESULTS
    success - TRUE if the icon could be removed, FALSE otherwise.

   NOTES
    As with anything that deals with asynchronous operation, you will need
    to do a final check for messages on your AppMessage port for messages
    that may have come in between the last time you checked and the
    call to remove the AppIcon.

   SEE ALSO
    workbench.library/AddAppIconA


workbench.library/RemoveAppMenuItem

   NAME
    RemoveAppMenuItem - remove a menu item from Workbench's list     (V36)
                        of AppMenuItems.

   SYNOPSIS
    success = RemoveAppMenuItem(AppMenuItem)
         D0                            A0

    BOOL RemoveAppMenuItem(struct AppMenuItem *);

   FUNCTION
    Attempt to remove an AppMenuItem from Workbench's list
    of AppMenuItems.

   INPUTS
    AppMenuItem - pointer to an AppMenuItem structure returned by
                  AddAppMenuItem.

   RESULTS
    success - TRUE if the menu could be removed, FALSE otherwise.

   NOTES
    As with anything that deals with asynchronous operation, you will need
    to do a final check for messages on your AppMessage port for messages
    that may have come in between the last time you checked and the
    call to removed the AppMenuItem.

   SEE ALSO
    workbench.library/AddAppMenuItemA


workbench.library/RemoveAppWindow

   NAME
    RemoveAppWindow - remove a window from Workbench's list         (V36)
                          of AppWindows.

   SYNOPSIS
    success = RemoveAppWindow(AppWindow)
         D0                        A0

    BOOL RemoveAppWindow(struct AppWindow *);

   FUNCTION
    Attempt to remove an appwindow from Workbench's list of AppWindows.

   INPUTS
    AppWindow - pointer to an AppWindow structure returned by
                AddAppWindow.

   RESULTS
    success - TRUE if the window could be removed, FALSE otherwise.

   NOTES
    As with anything that deals with asynchronous operation, you will need
    to do a final check for messages on your AppMessage port for messages
    that may have come in between the last time you checked and the
    call to removed the AppWindow.

    Before the AppWindow is removed, all its drop zones will be removed
    first. There is no need for you to call RemoveAppWindowDropZone()
    for every single one.

   SEE ALSO
    workbench.library/AddAppWindowA
    workbench.library/RemoveAppWindowDropZone


workbench.library/RemoveAppWindowDropZoneench.library/RemoveAppWindowDropZone

   NAME
    RemoveAppWindowDropZone -- Remove a drop zone from an AppWindow.

   SYNOPSIS
    success = RemoveAppWindowDropZone(appWindow,dropZone)
      D0                                 A0        A1

    BOOL RemoveAppWindowDropZone(struct AppWindow *,
                                 struct AppWindowDropZone *);

   FUNCTION
    Attempt to remove a drop zone from an AppWindow.

   INPUTS
    appWindow -- pointer to an AppWindow structure returned by
        workbench.library/AddAppWindowA. A value of NULL will be
        ignored.
    dropZone -- pointer to an AppWindowDropZone returned by
        workbench.library/AddAppWindowDropZoneA. A value of NULL will
        be ignored.

   RESULTS
    success - TRUE if the drop zone could be removed, FALSE otherwise.
        The reason for the failure can be obtained using
        dos.library/IoErr. This routine may fail if the specified drop
        zone is not registered with the AppWindow.

   NOTES
    Due to the asynchronous nature of Workbench/user interaction, you
    may receive AppIcon drop zone messages for zones that you have
    just removed. These messages may arrive in the time between your
    code calling RemoveAppWindowDropZone() and Workbench responding
    to the drop zone removal request. Be prepared to handle this. Once
    a drop zone is removed, it will generate no new AppMessages.

   SEE ALSO
    workbench.library/AddAppWindowDropZoneA


workbench.library/WBInfo

   NAME
    WBInfo - Bring up the Information requester                     (V39)

   SYNOPSIS
    worked = WBInfo(lock, name, screen)
    d0              a0    a1    a2

    ULONG WBInfo(BPTR, STRPTR, struct Screen *);

   FUNCTION
    This is the LVO that Workbench calls to bring up the Icon Information
    requester.  External applications may also call this requester.
    In addition, if someone were to wish to replace this requester
    with another one, they could do so via a SetFunction.

   INPUTS
    lock   - A lock on the parent directory
    name   - The name of the icon contained within above directory
    screen - A screen pointer on which the requester is to show up

   RESULTS
    worked - Returns TRUE if the requester came up, FALSE if it did not.

   NOTE
    Note that this LVO may be called many times by different tasks
    before other calls return.  Thus, the code must be 100% re-entrant.

   SEE ALSO
    icon.library


workbench.library/WorkbenchControlA

   NAME
    WorkbenchControlA -- Query or modify Workbench and icon
        options. (V44)

   SYNOPSIS
    success = WorkbenchControlA(name,tags)
       D0                       A0   A1

    BOOL WorkbenchControlA(STRPTR name,struct TagItem *tags);

    success = WorkbenchControl(name,...);

    BOOL WorkbenchControl(STRPTR name,...);

   FUNCTION
    With this function you can query or modify global Workbench
    parameters or local icon options.

   INPUTS
    name -- Name of an object to query or modify.

    tags -- Additional options.

   TAGS
    WBCTRLA_IsOpen (LONG *) -- Check if the named object is
        currently open. In this case, the function "name"
        parameter refers to the drawer that should be
        tested; the result value will be set to TRUE if
        the named drawer is currently open, FALSE otherwise.

    WBCTRLA_DuplicateSearchPath (BPTR *) -- This is a safe way
        to obtain a copy of the Workbench search path list.
        You will receive a BPTR to a path list, such as can
        be stored in the cli_CommandDir pointer of a
        CommandLineInterface structure. Note that this is really
        a copy of the Workbench search path list and not a reference
        to the data associated with the Workbench process. Thus,
        it can be freed by FreeDosObject(DOS_CLI,..), if part of
        a CommandLineInterface structure.

    WBCTRLA_FreeSearchPath (BPTR) -- If you did not attach the
        data returned by the WBCTRLA_DuplicateSearchPath
        to a CLI, to be freed automatically later, you can
        pass it back to WorkbenchControlA() to be released.

    WBCTRLA_GetDefaultStackSize (ULONG *) -- Get the default stack
        size used by Workbench when launching Shell programs
        or programs without a valid stack size number.

        The default stack size is 4096 bytes.

    WBCTRLA_SetDefaultStackSize (ULONG) -- Set the default stack
        size used by Workbench when launching Shell programs
        or programs without a valid stack size number. You cannot
        set a stack size number smaller than 4096 bytes

    WBCTRLA_RedrawAppIcon (struct AppIcon *) -- This tag will cause
        Workbench to redraw an AppIcon. Note that due to which state
        the Workbench is currently in, it may refuse to redraw the
        icon.

    WBCTRLA_GetProgramList (struct List **) -- You can obtain a list
        of currently running Workbench programs; every entry of this
        list will have the complete path to the program and the
        program name in its Node->ln_Name. When you no longer need
        the list, don't forget to free it again using the tag
        WBCTRLA_FreeProgramList.

        Note that the list you will receive may be empty. Be
        prepared to handle this.

    WBCTRLA_FreeProgramList (struct List *) -- With this tag you can
        free the list allocated by the WBCTRLA_GetProgramList tag.

    WBCTRLA_GetSelectedIconList (struct List **) -- You can obtain a
        list of currently selected icons; every entry of this
        list will have the complete path to the icon and the
        icon name in its Node->ln_Name. Some icons do not enter the
        list, such as AppIcons. When you no longer need the list,
        don't forget to free it again using the tag
        WBCTRLA_FreeSelectedIconList.

        Note that the list you will receive may be empty. Be
        prepared to handle this.

    WBCTRLA_FreeSelectedIconList (struct List *) -- With this tag
        you can free the list allocated by the
        WBCTRLA_GetSelectedIconList tag.

    WBCTRLA_GetOpenDrawerList (struct List **) -- You can obtain a
        list of currently open drawers and volumes; every entry of this
        list will have the complete drawer path name in its Node->ln_Name.
        When you no longer need the list, don't forget to free it
        again using the tag WBCTRLA_FreeOpenDrawerList.

        Note that the list you will receive may be empty. Be
        prepared to handle this.

    WBCTRLA_FreeOpenDrawerList (struct List *) -- With this tag
        you can free the list allocated by the
        WBCTRLA_GetOpenDrawerList tag.

    WBCTRLA_AddHiddenDeviceName (STRPTR) -- Name of a device which
        Workbench should not display a disk or device icon for.
        Any such device will be effectively hidden from the Workbench
        backdrop. The name must include a terminating colon character,
        such as in "DF0:".

        Note that adding new entries to this list may not immediately
        take effect.

    WBCTRLA_RemoveHiddenDeviceName (STRPTR) -- Name of a device on
        the list of devices to be hidden which should be removed.
        The name must include a terminating colon character,
        such as in "DF0:". Trying to remove an entry from the list
        that is not on it will have no effect.

        Note that removing entries from this list may not immediately
        take effect.

    WBCTRLA_GetHiddenDeviceList (struct List **) -- This will obtain
        the list of devices whose contents which Workbench will not
        display.

        Note that the list you will receive may be empty. Be
        prepared to handle this.

    WBCTRLA_FreeHiddenDeviceList (struct List *) -- With this tag
        you can free the list allocated by the
        WBCTRLA_GetHiddenDeviceList tag.

    WBCTRLA_GetTypeRestartTime (ULONG *) -- Get the number of seconds
        that have to pass before typing the next character in a drawer
        window will restart with a new file name.

    WBCTRLA_SetTypeRestartTime (ULONG) -- Set the number of seconds
        that have to pass before typing the next character in a drawer
        window will restart with a new file name. You must specify a
        number greater than 0. Default type restart time is 3 seconds.

   RESULTS
    result -- FALSE if the requested action could not be performed,
        TRUE otherwise. If FALSE is returned, you can query the error
        code using dos.library/IoErr().

   NOTES
    If this function returns FALSE, the expected result is undefined.
    For example, if you tried to obtain the list of currently running
    programs via the WBCTRLA_GetProgramList tag and WorkbenchControl()
    failed with an error code, do not expect the List pointer you
    passed in to be initialized.

    This function may only be called by a Process.

    This function may not process all tags if the Workbench is not
    currently open. For V44, the following tags are support if
    Workbench is closed:

        WBCTRLA_SetDefaultStackSize
        WBCTRLA_GetDefaultStackSize
        WBCTRLA_FreeHiddenDeviceList
        WBCTRLA_GetHiddenDeviceList
        WBCTRLA_AddHiddenDeviceName
        WBCTRLA_RemoveHiddenDeviceName
        WBCTRLA_SetTypeRestartTime
        WBCTRLA_GetTypeRestartTime

   EXAMPLE
    /* Obtain a copy of the Workbench search path list, then
     * release it again.
     */
    BPTR pathList;

    if(WorkbenchControl(NULL,
        WBCTRLA_DuplicateSearchPath,&pathList,
    TAG_DONE))
    {
        WorkbenchControl(NULL,
            WBCTRLA_FreeSearchPath,pathList,
        TAG_DONE);
    }

    /* Check if the drawer "SYS:" is open. */
    LONG isOpen;

    if(WorkbenchControl("SYS:",
        WBCTRLA_IsOpen,&isOpen,
    TAG_DONE))
    {
        Printf("Drawer "SYS:" is %s.n",
            isOpen ? "open" : "closed");
    }

    /* Print the list of all currently running
     * Workbench programs, then free the list again.
     */
    struct List * list;

    if(WorkbenchControl(NULL,
        WBCTRLA_GetProgramList,&list,
    TAG_DONE))
    {
        struct Node * node;

        for(node = list->lh_Head ;
            node->ln_Succ != NULL ;
            node = node->ln_Succ)
        {
            Printf("%sn",node->ln_Name);
        }

        WorkbenchControl(NULL,
            WBCTRLA_FreeProgramList,list,
        TAG_DONE);
    }

   SEE ALSO
    dos.library/FreeDosObject
    dos.library/IoErr
    <dos/dosextens.h>


window_cl.doc

     --datasheet--
     WINDOW_GetClass()
     WM_CLOSE
     WM_HANDLEINPUT
     WM_ICONIFY
     WM_OPEN


window_cl/--datasheet--

   NAME
       window_cl -- create Intuition Window objects

   SUPERCLASS
       rootclass

   REQUIRES
       layout.gadget, drawlist.image

   DESCRIPTION
       This class creates standard Intuition Windows, and intelligently
       handles some ReAction house keeping for KeyBoard Control, Defer
       Layout processing, etc. Window class properly handles processing
       messages using shared window message ports as well as safely
       closing intuition windows. Window class will also intialize
       your window's parent layout group properly.

       All windowclass methods and the callback hooks you provide it are
       ran in the context of the task you call windowclass from. Thus if
       your application is a process, DOS is safe to use. However,
       remember the Intuition rules about DOS and IDCMP VERIFY messages.

       Window.class requires layout.gadget.

   WINDOW REFRESH
       Usually, when all the graphics in your window are handled by
       ReAction, you should not explicitly set the window refresh method
       to either smart or simple refresh. This is a user preference
       setting, and windowclass will automatically choose it. However,
       if your program for some reason requires one or the other refresh
       method and can not use the other, set the refresh type in your
       window object creation taglist.

   BACKFILL PATTERNS
       Window.class will install the default backfill pattern on any
       window for which you do not pass a pointer to a custom backfill
       hook. The pattern bitmaps are cached by window.class, minimizing
       memory usage.

       If your windows have elements that look bad or do not work with
       a backfill pattern, install the default NULL backfill to the
       layout group(s) containing them.

       The backfill installed by window.class is NOT a standard, global
       window layer backfill hook. It is in fact passed to each of the
       layout groups of the window, which will install it during
       refreshes. This approach was chosen because datatypes fail to
       render correctly if their background has been backfilled. This
       method has the side effect that a gadget that is not aware of
       ReAction's method to install a backfill will only have a
       backfill during window refresh (GM_RENDER coming through from
       the parent layout), not during GM_HANDLEINPUT. To make the
       class use the backfill during input handling, it should have
       GA_BackFill as a settable attribute, and install that
       backfill hook before erasing its imagery.

   METHODS
       OM_NEW -- Passed to superclass first, defaults set, then OM_SET.

       OM_SET -- Passed to superclass first, then custom tags set.

       OM_GET -- Returns requested setting or passed to superclass

       OM_DISPOSE -- Child object disposed then passed to superclass.

       WM_OPEN -- Locks default pub screen if needed, domains child layout
           group min/max size, opens window, attaches layout to window.

       WM_CLOSE -- Closes the intuition window, but does not dispose
           the layout group.

       WM_ICONIFY -- Create AppIcon, and invokes WM_CLOSE.

       WM_HANDLEINPUT -- Handles IDCMP input processing, defer layout
           refresh requests, and returns the item ID and Code of
           and selected gadget or menu attached to the window.
           Transparently handles keyboard control.

       WM_NEWPREFS -- Handles update and visual refresh of new
           preference settings.

       WM_RETHINK -- Re-evaluate layout requirements and adjust
           window size if needed in support of dynamicly changing
           layout groups.. eg, adding, replacing and removing objects.

   ATTRIBUTES

       The following standard Intuition Window Tags are supported;

       You may set these while the window is NOT open, at NewObject()
       time or SetAttrs() - between WM_CLOSE and WM_OPEN for example.

           WA_Flags
           WA_NoCareRefresh
           WA_SimpleRefresh
           WA_SmartRefresh
           WA_CloseGadget
           WA_DepthGadget
           WA_SizeGadget
           WA_SizeBRight
           WA_SizeBBottom
           WA_DragBar
           WA_GimmeZeroZero
           WA_Borderless
           WA_Activate
           WA_RMBTrap
           WA_Backdrop
           WA_SuperBitMap
           WA_BackFill
           WA_PubScreen
           WA_CustomScreen
           WA_HelpGroup
           WA_MenuHelp
           WA_Zoom
           WA_NotifyDepth

       You may set any of these at any time, NewObject() or SetAttrs();

           WA_Top
           WA_Left
           WA_InnerWidth
           WA_InnerHeight
           WA_Width
           WA_Height
           WA_Title (NOTE: Calls SetWindowTitles() if the window is open)
           WA_IDCMP (NOTE: Calls ModifyIDCMP() if needed)
           WA_BusyPointer (NOTE: Creates/Removes a NULL requester)

       You may GetAttr() these at any time;

           WA_Top
           WA_Left
           WA_InnerWidth
           WA_Height
           WA_Width
           WA_InnerHeight
           WA_PubScreen
           WA_CustomScreen
           WA_Title
           WA_ScreenTitle
           WA_Zoom

           Note well, WA_InnerHeight, and WA_InnerWidth will be 0
           unless previously set until the window has been opened
           atleast once. These values are not computed until the
           first window open.

       These are the Window Class specific attributes.

       You may set these while the window is NOT open, at NewObject()
       time or SetAttrs() - between WM_CLOSE and WM_OPEN for example.

       WINDOW_Position (UWORD)
           Set the intial opening position of the window.
           See Also, WINDOW_RefWindow.

               WPOS_CENTERSCREEN - Center in visible screen clip.
               WPOS_CENTERMOUSE  - Center under mouse.
               WPOS_TOPLEFT      - Open Top/Left, just below screen bar.
               WPOS_CENTERWINDOW - Center in some other window.
               WPOS_FULLSCREEN   - Open Top/Left, and fill the screen clip.

           If WINDOW_RefWindow is set, WPOS_CENTERSCREEN will center
           in the refwindow, not the screen. As of 42.42, WPOS_FULLSCREEN
           remains broken, window will open a minimum size.

           Applicability is (OM_NEW, OM_SET)

       WINDOW_LockWidth (ULONG)
           If TRUE, lock the width of the window, ie, disallow
           resizing in this orientation.

           Defaults to FALSE.

           Applicability is (OM_NEW, OM_SET)

       WINDOW_LockHeight (ULONG)
           If TRUE, lock the height of the window, ie, disallow
           resizing in this orientation.

           Defaults to FALSE.

           Applicability is (OM_NEW, OM_SET)

       WINDOW_SharedPort (struct MsgPort *)
           Pointer to a custom UserPort this window should share.

           Defaults to NULL.

           Applicability is (OM_NEW, OM_SET, OM_GET)

       WINDOW_AppPort (struct MsgPort *)
           Pointer to a MsgPort this window should use for AppMessages.
           By passing this tag the window turns into an AppWindow and
           you can use the WM_ICONIFY method. WindowClass must use the
           ID field of the AppMessages to identify the window to which
           the message was intended. You can use the UserData field
           yourself.

           Defaults to NULL.

           Applicability is (OM_NEW, OM_SET)

       WINDOW_AppWindow (BOOL)
           By providing an AppPort and setting this to TRUE, the window
           will be made a Workbench AppWindow. If you don't set this
           attribute, the AppPort will only be used to support
           iconification.

           Defaults to FALSE.

           Applicability is (OM_NEW, OM_SET)

       WINDOW_IconifyGadget (BOOL)
           Set to TRUE to add an iconification gadget to the window
           titlebar. Please note that currently windowclass detects
           the iconify gadget being pressed by using the gadget ID
           0xfffe.  Do not use this ID in your application.

           Defaults to FALSE.

           Applicability is (OM_NEW, OM_SET)

       WINDOW_BackFillName (STRPTR)
           Name for the custom backfill to use instead of global CAPrefs
           backfill. If you use this tag, make it a user preference.

           Defaults to NULL.

           Applicability is (OM_NEW, OM_SET)

       It is legal and safe to set any of these at any time, OM_NEW or
       OM_SET regardless of of the window being open or not, if
       not applicable, the setting will be ignored.

       WA_BusyPointer (BOOL)
           Set the window to a busy state. It will set busy pointer
           on the window. Setting the busy state will also clear the
           DeferLayout state, clearing the busy state restores the
           DeferLayout state to its last value.

           This is done since, its a logical assumption if the application
           is busy enough that a pointer change is waranted, then its
           probably busy to respond to defer requests in a timely fashion.

           Note, the window put to sleep creating a NULL requester.
           In prior versions of window class before V42.40, the layout
           group was set to readonly, and menu strip removed.

           Applicability is (OM_NEW, OM_SET)

       WINDOW_Layout (Object *)
       WINDOW_ParentLayout
       WINDOW_ParentGroup
           Pointer to the parent level layout group object which
           will be added to the window.

           Note the tag has 2 aliased definitions which are now
           obsolete but still supported in the include files.

           Defaults to NULL.

           Applicability is (OM_NEW, OM_SET)

       WINDOW_Zoom (BOOL)
           Cause the window to to be zipped via ZipWindow().

           Applicability is (OM_NEW, OM_SET)

       WINDOW_FrontBack (BOOL)
           Changes window depth arrangement via WindowToFront() or
           WindowToBack(). Accepted settings;

               WT_FRONT - bring window to front.
               WT_BACK  - put window to back

           Applicability is (OM_NEW, OM_SET)

       WINDOW_UserData (APTR)
           Pointer to your user data. Take note, this is *NOT* the
           same pointer as the Intuition Window's UserData.

           Defaults to NULL.

           Applicability is (OM_NEW, OM_SET, OM_GET)

       WINDOW_GadgetUserData (UWORD)
           Determines how a gadget's UserData should be interpreted.
           If the userdata is non-null, and this setting is not
           WGUD_IGNORE, then the (hook) function will be called
           when the gadget is selected.

           A function gets the hook's "object" argument in a0 and the
           "message" argument in a1.

           Possible values are;

               WGUD_HOOK   - UserData is hook pointer (struct Hook *).
               WGUD_FUNC   - UserData is a pointer to function.
               WGUD_IGNORE - Ignore UserData.

           Defaults to WGUD_IGNORE.

           Applicability is (OM_NEW, OM_SET)

       WINDOW_MenuUserData (UWORD)
           Like the WINDOW_GadgetUserData tag, but for menus. Using
           this implies that WINDOW_MenuStrip has been created with
           GadTools or otherwise has a 32 bit UserData field after
           each menuitem.

           Applicability is (OM_NEW, OM_SET)

       WINDOW_MenuStrip (struct Menu *)
           Pointer to a menu to add to window with SetMenuStrip().
           Closing the window via CA_CloseWindow, will remove
           the menustrip before closing the window.  Disposing the
           window does NOT free the menu strip.

           Defaults to NULL.

           Applicability is (OM_NEW, OM_SET)

       WINDOW_Window (struct Window *)
           Pointer to the Intuition Window, or NULL when the
           window is closed.  Take care NOT to do a CloseWindow()
           or you will invalidate window.class's internal pointer
           and window states.

           Applicability is (OM_GET)

       WINDOW_SigMask (ULONG)
           Window signal bit mask.

           Applicability is (OM_GET)

       WINDOW_IconTitle (STRPTR)
           The title of the icon when the window is iconified.

           Defaults to window title.

           Applicability is (OM_NEW, OM_SET, OM_UPDATE)

       WINDOW_Icon (struct DiskObject *)
           The icon to use when iconifying.

           Defaults to ENV:Sys/def_window.info or the default project
           window.

           Applicability is (OM_NEW, OM_SET, OM_UPDATE)

       WINDOW_GadgetHelp (BOOL)
           Set to TRUE to enabled gadget help processing.

           Defaults to FALSE.

           Applicability is (OM_NEW, OM_SET, OM_UPDATE)

       WINDOW_IDCMPHook (struct Hook *)
           Pointer to a Hook that should be called for IDCMP messages.
           When the hook is called, the data argument points to the
           window object and message argument to the IntuiMessage.

           Defaults to NULL.

           Applicability is (OM_NEW, OM_SET)

       WINDOW_IDCMPHookBits (ULONG)
           If WINDOW_IDCMPHook is set, it will be called for IDCMP
           messages matching this bit mask.

           Defaults to 0L.

           Applicability is (OM_NEW, OM_SET)

       WINDOW_AppMsgHook (struct Hook *)
           Pointer to a hook that should be called for AppMessages.
           When this called, the function data argument will point to
           the window object and data argument to the AppMessage.

           Defaults to NULL.

           Applicability is (OM_NEW, OM_SET)

       WINDOW_RefWindow (struct Window *)
           Pointer to an Intuition window whose location will be the
           reference used for WINDOW_Position rather than the screen.

           Defaults to NULL.

           Applicability is (OM_NEW, OM_SET)

       WINDOW_InputEvent (struct InputEvent *)
           Pointer to an InputEvent structure which will be valid AFTER
           receiving a WHMI_RAWKEY return code from window class.
           This is a "fake" event, the structure is filled in based on
           the IntuiMessage and other data, and is suitable for calling
           MapRawKey(), infact this is how window class handles managing
           gadget keyboard control.

           Applicability is (OM_GET)


window_cl/WINDOW_GetClass

   NAME
       WINDOW_GetClass -- Gets the pointer to the checkbox class.

   SYNOPSIS
       window_class = WINDOW_GetClass();
       D0

       Class * WINDOW_GetClass(VOID);

   FUNCTION
       This function is only available in runtime linked version of the
       class, window.class and is not in the compiler linker library
       window_cl.lib.

       Obtains the pointer to the Window class for use with NewObject().
       This function always returns a valid pointer so you do not
       need to check it.  The reason is that if the library opens
       fine, then the pointer returned is already setup.  (Of course
       this implies that if opening the library fails, you shouldn't be
       calling this.)

       Note that this function does not create the class, that is done
       when the class library is opened.

   INPUTS
       Nothing.

   RESULT
       window_class - Pointer to the window class.


window_cl/WM_CLOSE

   NAME
       WM_CLOSE -- Close a window

   SYNOPSIS
       DoMethod( winobj, WM_CLOSE );

   FUNCTION
       Close the window of this object. The gadgets are not disposed,
       only detached of a window. If the window is sharing a message
       port with another window, the port will be cleaned of message
       intended for this window. If the window was iconified, the icon
       will be removed.


window_cl/WM_HANDLEINPUT

   NAME
       WM_HANDLEINPUT -- IDCMP input handling method

   SYNOPSIS
       result = DoMethod( winobj, WM_HANDLEINPUT, &code );

   FUNCTION
       This method is used to handle the IDCMP input of a window. Call
       this method when the signal bit of the window's UserPort is
       set. This method will return when it encounters a message that
       requires notifying your application or when the message port no
       longer contains messages for the window.

       The return value is two-part. The upper word describes the
       class of the event the value represents, and the lower word is
       a modifier that describes the event.

       Defined class return codes are:

       WMHI_IGNORE            Ignore this event
       WMHI_LASTMSG        No more messages
       WMHI_CLOSEWINDOW    Close gadget hit
       WMHI_GADGETUP        Gadget hit.
       WMHI_INACTIVE        Window went inactive.
       WMHI_ACTIVE            Window was activated.
       WMHI_NEWSIZE        Window was resized.
       WMHI_MENUPICK        A menu item was selected.
       WMHI_MENUHELP        Help was pressed in a menu.
       WMHI_GADGETHELP        A gadget sends a help message.
       WMHI_ICONIFY        Window should be iconified.
       WMHI_UNICONIFY        Window was deiconified.
       WMHI_RAWKEY            Raw key code
       WMHI_VANILLAKEY        Vanilla key code
       WMHI_CHANGEWINDOW    Window moved (or depth arranged)

       The value of the lower word is defined for WMHI_GADGETUP and
       WMHI_GADGETHELP as the ID of the gadget, and for WMHI_MENUPICK
       and WMHI_MENUHELP as the menu code. WMHI_GAGDETHELP uses the
       special values 0 and WMHI_GADGETMASK as messages "pointer not
       over your window" and "pointer over your window but not over a
       gadget".

       WMHI_RAWKEY returns the raw key ID of the key being
       pressed (to get the qualifiers also, you have to use the IDCMP
       hook), and WMHI_VANILLAKEY returns the ASCII value of the key.
       WMHI_VANILLAKEY is only returned when you set IDCMP_VANILLAKEY.
       Windowclass itself does not need vanilla key IDCMP.

       WMHI_NEWSIZE returns some extra information in the low word:
       if WMF_ZOOMED is set, the window is now in zoomed state. If
       WMF_ZIPWINDOW is set, this resize was caused by either a
       click of the zoom gadget or a call to ZipWindow().

       WMHI_CHANGEWINDOW is returned when the window is moved. For
       resizing of the window, listen to WMHI_NEWSIZE. By setting
       WA_NotifyDepth, this event will also be returned for depth
       arranging. The lower word contains CWCODE_DEPTH in this case.

       WMHI_CLASSMASK masks the lower word of the result code out,
       while WMHI_GADGETMASK and WMHI_MENUMASK mask out the high word,
       leaving only the ID part of the result value.

       A generic application side of WM_HANDLEINPUT looks like this:

       GetAttr( WINDOW_SigMask, winobj, &wsig );

       mask = Wait(wsig);    /* maybe other signals */

       if (mask & wsig)
           while ((result = DoMethod( winobj, WM_HANDLEINPUT, &code ))
                   != WMHI_LASTMSG)
               switch (result & WMHI_CLASSMASK)
               {
               case WMHI_CLOSEWINDOW:
                   close = TRUE;
                   break;

               case WMHI_GADGETUP:
                   switch (result & WMHI_GADGETMASK)
                   {
                   /* handle the gadgets here */
                   }

               /* handle whatever other events you want here */
               }

       if (close)
           DisposeObject( winobj ); /* destroy the window */

       If you have set up the window to use a shared message port, you
       can simply call this method on each of the windows:

       if (mask & wsig)
       {
           WmHandleInputWin1();
           WmHandleInputWin2();
           WmHandleInputWin3();
       }

   INPUTS
       code -- A pointer to a WORD that should be set to contain the
               Code value from the IntuiMessage.

   RESULTS
       Windowclass will automatically respond with an appropriate
       action to many input events. When it does not know what to do
       with an event, it will return with a value as descibed above.


window_cl/WM_ICONIFY

   NAME
       WM_ICONIFY -- Hide this window to an icon

   SYNOPSIS
       DoMethod( winobj, WM_ICONIFY );

   FUNCTION
       Close the window and put an icon on the Workbench for it.


window_cl/WM_OPEN

   NAME
       WM_OPEN -- Open a window

   SYNOPSIS
       window = DoMethod( winobj, WM_OPEN );

   FUNCTION
       This function opens the window the object should be handling.
       If the window is already open, it does nothing. If no shared
       message port is set, a message port will be created for this
       window.

   RESULTS
       window -- a pointer to the struct Window for this window, or
               NULL if the window could not be opened.


window_cl/WM_RETHINK

   NAME
       WM_RETHINK -- Re-evaluate an open window's size requirement

   SYNOPSIS
       window = DoMethod( winobj, WM_RETHINK );

   FUNCTION
       This function re-evaluates the layout group's minimum size
       and adjusts the window size to contain it if needed.

   RESULTS
       Non-Zero if implemented.


include/dos/dosasl.h

#ifndef DOS_DOSASL_H
#define DOS_DOSASL_H
/*
**
**	$VER: dosasl.h 36.16 (2.5.1991)
**	Includes Release 44.1
**
**	Pattern-matching structure definitions
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**
*/

#ifndef EXEC_LIBRARIES_H
#include <exec/libraries.h>
#endif

#ifndef EXEC_LISTS_H
#include <exec/lists.h>
#endif

#ifndef DOS_DOS_H
#include <dos/dos.h>
#endif

/***********************************************************************
************************ PATTERN MATCHING ******************************
************************************************************************

* structure expected by MatchFirst, MatchNext.
* Allocate this structure and initialize it as follows:
*
* Set ap_BreakBits to the signal bits (CDEF) that you want to take a
* break on, or NULL, if you don't want to convenience the user.
*
* If you want to have the FULL PATH NAME of the files you found,
* allocate a buffer at the END of this structure, and put the size of
* it into ap_Strlen.  If you don't want the full path name, make sure
* you set ap_Strlen to zero.  In this case, the name of the file, and stats
* are available in the ap_Info, as per usual.
*
* Then call MatchFirst() and then afterwards, MatchNext() with this structure.
* You should check the return value each time (see below) and take the
* appropriate action, ultimately calling MatchEnd() when there are
* no more files and you are done.  You can tell when you are done by
* checking for the normal AmigaDOS return code ERROR_NO_MORE_ENTRIES.
*
*/

struct AnchorPath {
    struct AChain	*ap_Base;	/* pointer to first anchor */
#define	ap_First ap_Base
    struct AChain	*ap_Last;	/* pointer to last anchor */
#define ap_Current ap_Last
    LONG	ap_BreakBits;	/* Bits we want to break on */
    LONG	ap_FoundBreak;	/* Bits we broke on. Also returns ERROR_BREAK */
    BYTE	ap_Flags;	/* New use for extra word. */
    BYTE	ap_Reserved;
    WORD	ap_Strlen;	/* This is what ap_Length used to be */
#define	ap_Length ap_Flags	/* Old compatability for LONGWORD ap_Length */
    struct	FileInfoBlock ap_Info;
    UBYTE	ap_Buf[1];	/* Buffer for path name, allocated by user */
    /* FIX! */
};

#define	APB_DOWILD	0	/* User option ALL */
#define APF_DOWILD	1

#define	APB_ITSWILD	1	/* Set by MatchFirst, used by MatchNext	 */
#define APF_ITSWILD	2	/* Application can test APB_ITSWILD, too */
                /* (means that there's a wildcard	 */
                /* in the pattern after calling		 */
                /* MatchFirst).				 */

#define	APB_DODIR	2	/* Bit is SET if a DIR node should be */
#define APF_DODIR	4	/* entered. Application can RESET this */
                /* bit after MatchFirst/MatchNext to AVOID */
                /* entering a dir. */

#define	APB_DIDDIR	3	/* Bit is SET for an "expired" dir node. */
#define APF_DIDDIR	8

#define	APB_NOMEMERR	4	/* Set on memory error */
#define APF_NOMEMERR	16

#define	APB_DODOT	5	/* If set, allow conversion of '.' to */
#define APF_DODOT	32	/* CurrentDir */

#define APB_DirChanged	6	/* ap_Current->an_Lock changed */
#define APF_DirChanged	64	/* since last MatchNext call */

#define APB_FollowHLinks 7	/* follow hardlinks on DODIR - defaults   */
#define APF_FollowHLinks 128	/* to not following hardlinks on a DODIR. */

struct AChain {
    struct AChain *an_Child;
    struct AChain *an_Parent;
    BPTR	an_Lock;
    struct FileInfoBlock an_Info;
    BYTE	an_Flags;
    UBYTE	an_String[1];	/* FIX!! */
};

#define	DDB_PatternBit	0
#define	DDF_PatternBit	1
#define	DDB_ExaminedBit	1
#define	DDF_ExaminedBit	2
#define	DDB_Completed	2
#define	DDF_Completed	4
#define	DDB_AllBit	3
#define	DDF_AllBit	8
#define	DDB_Single	4
#define	DDF_Single	16

/*
 * Constants used by wildcard routines, these are the pre-parsed tokens
 * referred to by pattern match.  It is not necessary for you to do
 * anything about these, MatchFirst() MatchNext() handle all these for you.
 */

#define P_ANY		0x80	/* Token for '*' or '#?  */
#define P_SINGLE	0x81	/* Token for '?' */
#define P_ORSTART	0x82	/* Token for '(' */
#define P_ORNEXT	0x83	/* Token for '|' */
#define P_OREND	0x84	/* Token for ')' */
#define P_NOT		0x85	/* Token for '~' */
#define P_NOTEND	0x86	/* Token for */
#define P_NOTCLASS	0x87	/* Token for '^' */
#define P_CLASS	0x88	/* Token for '[]' */
#define P_REPBEG	0x89	/* Token for '[' */
#define P_REPEND	0x8A	/* Token for ']' */
#define P_STOP		0x8B	/* token to force end of evaluation */

/* Values for an_Status, NOTE: These are the actual bit numbers */

#define COMPLEX_BIT	1	/* Parsing complex pattern */
#define EXAMINE_BIT	2	/* Searching directory */

/*
 * Returns from MatchFirst(), MatchNext()
 * You can also get dos error returns, such as ERROR_NO_MORE_ENTRIES,
 * these are in the dos.h file.
 */

#define ERROR_BUFFER_OVERFLOW	303	/* User or internal buffer overflow */
#define ERROR_BREAK		304	/* A break character was received */
#define ERROR_NOT_EXECUTABLE	305	/* A file has E bit cleared */

#endif /* DOS_DOSASL_H */


include/datatypes/animationclass.h

#ifndef	DATATYPES_ANIMATIONCLASS_H
#define	DATATYPES_ANIMATIONCLASS_H
/*
**	$VER: animationclass.h 44.2 (27.3.1999)
**	Includes Release 44.1
**
**	Interface definitions for DataType animation objects.
**
**	(C) Copyright 1992-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef	UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

#ifndef	DATATYPES_DATATYPESCLASS_H
#include <datatypes/datatypesclass.h>
#endif

#ifndef	DATATYPES_PICTURECLASS_H
#include <datatypes/pictureclass.h>
#endif

#ifndef	DATATYPES_SOUNDCLASS_H
#include <datatypes/soundclass.h>
#endif

#ifndef	LIBRARIES_IFFPARSE_H
#include <libraries/iffparse.h>
#endif

/*****************************************************************************/

#define	ANIMATIONDTCLASS		"animation.datatype"

/*****************************************************************************/

/* Animation attributes */
#define	ADTA_Dummy		(DTA_Dummy + 600)
#define	ADTA_ModeID		PDTA_ModeID

/* (struct BitMap *) Key frame (first frame) bitmap */
#define	ADTA_KeyFrame		PDTA_BitMap

#define	ADTA_ColorRegisters	PDTA_ColorRegisters
#define	ADTA_CRegs		PDTA_CRegs
#define	ADTA_GRegs		PDTA_GRegs
#define	ADTA_ColorTable		PDTA_ColorTable
#define	ADTA_ColorTable2	PDTA_ColorTable2
#define	ADTA_Allocated		PDTA_Allocated
#define	ADTA_NumColors		PDTA_NumColors
#define	ADTA_NumAlloc		PDTA_NumAlloc

/* (BOOL) : Remap animation (defaults to TRUE) */
#define	ADTA_Remap		PDTA_Remap

/* (struct Screen *) Screen to remap to */
#define	ADTA_Screen		PDTA_Screen

#define	ADTA_Width		(ADTA_Dummy + 1)
#define	ADTA_Height		(ADTA_Dummy + 2)
#define	ADTA_Depth		(ADTA_Dummy + 3)
/* (ULONG) Number of frames in the animation */
#define	ADTA_Frames		(ADTA_Dummy + 4)

/* (ULONG) Current frame */
#define	ADTA_Frame		(ADTA_Dummy + 5)

/* (ULONG) Frames per second */
#define	ADTA_FramesPerSecond	(ADTA_Dummy + 6)

/* (LONG) Amount to change frame by when fast forwarding or
 * rewinding.  Defaults to 10.
 */
#define	ADTA_FrameIncrement	(ADTA_Dummy + 7)

/* (ULONG) Number of frames to preload; defaults to 10 */
#define	ADTA_PreloadFrameCount	(ADTA_Dummy + 8)	/* (V44) */

/* Sound attributes */
#define	ADTA_Sample		SDTA_Sample
#define	ADTA_SampleLength	SDTA_SampleLength
#define	ADTA_Period		SDTA_Period
#define	ADTA_Volume		SDTA_Volume
#define	ADTA_Cycles		SDTA_Cycles

#define	ADTA_LeftSample		SDTA_LeftSample		/* (V44) */
#define	ADTA_RightSample	SDTA_RightSample	/* (V44) */
#define	ADTA_SamplesPerSec	SDTA_SamplesPerSec	/* (V44) */

/*****************************************************************************/

#define ID_ANIM         MAKE_ID('A','N','I','M')
#define ID_ANHD         MAKE_ID('A','N','H','D')
#define ID_DLTA         MAKE_ID('D','L','T','A')

/*****************************************************************************/

/*  Required ANHD structure describes an ANIM frame */
struct AnimHeader
{
    UBYTE	 ah_Operation;	/*  The compression method:
                     0	set directly (normal ILBM BODY),
                     1	XOR ILBM mode,
                     2	Long Delta mode,
                     3	Short Delta mode,
                     4	Generalized short/long Delta mode,
                     5	Byte Vertical Delta mode
                     6	Stereo op 5 (third party)
                    74	(ascii 'J') reserved for Eric Graham's
                        compression technique (details to be
                        released later). */

    UBYTE	 ah_Mask;	/* (XOR mode only - plane mask where each
                   bit is set =1 if there is data and =0
                   if not.) */

    UWORD	 ah_Width;      /* (XOR mode only - width and height of the */
    UWORD	 ah_Height;	/* area represented by the BODY to eliminate */
                /* unnecessary un-changed data) */

    WORD	 ah_Left;	/* (XOR mode only - position of rectangular */
    WORD	 ah_Top;	/* area representd by the BODY) */

    ULONG	 ah_AbsTime;	/* Timing for a frame relative to the time
                   the first frame was displayed, in
                   jiffies (1/60 sec) */

    ULONG	 ah_RelTime;	/* Timing for frame relative to time
                                   previous frame was displayed - in
                   jiffies (1/60 sec) */

    UBYTE	 ah_Interleave;	/* Indicates how may frames back this data is to
                   modify.  0 defaults to indicate two frames back
                   (for double buffering). n indicates n frames back.
                   The main intent here is to allow values
                   of 1 for special applications where
                   frame data would modify the immediately
                   previous frame. */

    UBYTE	 ah_Pad0;	/* Pad byte, not used at present. */

    ULONG	 ah_Flags;	/* 32 option bits used by options=4 and 5.
                   At present only 6 are identified, but the
                   rest are set =0 so they can be used to
                   implement future ideas.  These are defined
                   for option 4 only at this point.  It is
                   recommended that all bits be set =0 for
                   option 5 and that any bit settings
                   used in the future (such as for XOR mode)
                   be compatible with the option 4
                   bit settings.   Player code should check
                   undefined bits in options 4 and 5 to assure
                   they are zero.

                   The six bits for current use are:

                    bit #	set =0			set =1
                    ===============================================
                    0		short data		long data
                    1		set       		XOR
                    2		separate info		one info list
                        for each plane		for all planes
                    3		not RLC			RLC (run length coded)
                    4		horizontal		vertical
                    5		short info offsets	long info offsets
                */

    UBYTE	 ah_Pad[16];	/* This is a pad for future use for future
                   compression modes. */
};

/*****************************************************************************/

#define	ADTM_Dummy		(0x700)

/* Used to load a frame of the animation */
#define	ADTM_LOADFRAME		(0x701)

/* Used to unload a frame of the animation */
#define	ADTM_UNLOADFRAME	(0x702)

/* Used to start the animation */
#define	ADTM_START		(0x703)

/* Used to pause the animation (don't reset the timer) */
#define	ADTM_PAUSE		(0x704)

/* Used to stop the animation */
#define	ADTM_STOP		(0x705)

/* Used to locate a frame in the animation (as set by a slider...) */
#define	ADTM_LOCATE		(0x706)

/* Used to load a new format frame of the animation (V44) */
#define	ADTM_LOADNEWFORMATFRAME	(0x707)

/* Used to unload a new format frame of the animation (V44) */
#define	ADTM_UNLOADNEWFORMATFRAME (0x708)

/*****************************************************************************/

/* ADTM_LOADFRAME, ADTM_UNLOADFRAME */
struct adtFrame
{
    ULONG		 MethodID;
    ULONG		 alf_TimeStamp;		/* Timestamp of frame to load */

    /* The following fields are filled in by the ADTM_LOADFRAME method, */
    /* and are read-only for any other methods. */

    ULONG		 alf_Frame;		/* Frame number */
    ULONG		 alf_Duration;		/* Duration of frame */

    struct BitMap	*alf_BitMap;		/* Loaded BitMap */
    struct ColorMap	*alf_CMap;		/* Colormap, if changed */

    BYTE		*alf_Sample;		/* Sound data */
    ULONG		 alf_SampleLength;
    ULONG		 alf_Period;

    APTR		 alf_UserData;		/* Used by load frame for extra data */
};

/* ADTM_LOADNEWFORMATFRAME, ADTM_UNLOADNEWFORMATFRAME */
struct adtNewFormatFrame
{
    ULONG		MethodID;
    ULONG		alf_TimeStamp;		/* Timestamp of frame to load */

    /* The following fields are filled in by the ADTM_NEWLOADFRAME method, */
    /* and are read-only for any other methods. */

    ULONG		alf_Frame;		/* Frame number */
    ULONG		alf_Duration;		/* Duration of frame */

    struct BitMap *	alf_BitMap;		/* Loaded BitMap */
    struct ColorMap *	alf_CMap;		/* Colormap, if changed */

    BYTE *		alf_Sample;		/* Sound data */
    ULONG		alf_SampleLength;
    ULONG		alf_Period;

    APTR		alf_UserData;		/* Used by load frame for extra data */

    ULONG		alf_Size;		/* Size of this data structure (in bytes) */

    BYTE *		alf_LeftSample;		/* Sound for left channel, or NULL if none */
    BYTE *		alf_RightSample;	/* Sound for right channel, or NULL if none */
    ULONG		alf_SamplesPerSec;	/* Replay speed; if > 0, this overrides alf_Period */
};

/* ADTM_START, ADTM_PAUSE, ADTM_STOP, ADTM_LOCATE */
struct adtStart
{
    ULONG		 MethodID;
    ULONG		 asa_Frame;		/* Frame # to start at */
};

/*****************************************************************************/

#endif	/* DATATYPES_ANIMATIONCLASS_H */


include/libraries/amigaguide.h

#ifndef LIBRARIES_AMIGAGUIDE_H
#define LIBRARIES_AMIGAGUIDE_H
/*
**	$VER: amigaguide.h 44.1 (14.3.1999)
**	Includes Release 44.1
**
**	Interface definitions for AmigaGuide(tm) hypertext system
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	    All Rights Reserved
*/
#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif /* EXEC_TYPES_H */

#ifndef EXEC_LISTS_H
#include <exec/lists.h>
#endif /* EXEC_LISTS_H */

#ifndef EXEC_NODES_H
#include <exec/nodes.h>
#endif /* EXEC_NODES_H */

#ifndef EXEC_SEMAPHORES_H
#include <exec/semaphores.h>
#endif

#ifndef INTUITION_INTUITION_H
#include <intuition/intuition.h>
#endif

#ifndef INTUITION_SCREENS_H
#include <intuition/screens.h>
#endif

#ifndef INTUITION_CLASSUSR_H
#include <intuition/classusr.h>
#endif

#ifndef DOS_DOS_H
#include <dos/dos.h>
#endif

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

#ifndef APSH_TOOL_ID
#define	APSH_TOOL_ID 11000L
#define	StartupMsgID		(APSH_TOOL_ID+1L)	/* Startup message */
#define	LoginToolID		(APSH_TOOL_ID+2L)	/* Login a tool SIPC port */
#define	LogoutToolID		(APSH_TOOL_ID+3L)	/* Logout a tool SIPC port */
#define	ShutdownMsgID		(APSH_TOOL_ID+4L)	/* Shutdown message */
#define	ActivateToolID		(APSH_TOOL_ID+5L)	/* Activate tool */
#define	DeactivateToolID	(APSH_TOOL_ID+6L)	/* Deactivate tool */
#define	ActiveToolID		(APSH_TOOL_ID+7L)	/* Tool Active */
#define	InactiveToolID		(APSH_TOOL_ID+8L)	/* Tool Inactive */
#define	ToolStatusID		(APSH_TOOL_ID+9L)	/* Status message */
#define	ToolCmdID		(APSH_TOOL_ID+10L)	/* Tool command message */
#define	ToolCmdReplyID		(APSH_TOOL_ID+11L)	/* Reply to tool command */
#define	ShutdownToolID		(APSH_TOOL_ID+12L)	/* Shutdown tool */
#endif

/* Attributes accepted by GetAmigaGuideAttr() */
#define	AGA_Dummy		(TAG_USER)
#define	AGA_Path		(AGA_Dummy+1)
#define	AGA_XRefList		(AGA_Dummy+2)
#define	AGA_Activate		(AGA_Dummy+3)
#define	AGA_Context		(AGA_Dummy+4)

#define	AGA_HelpGroup		(AGA_Dummy+5)
    /* (ULONG) Unique identifier */

#define	AGA_Reserved1		(AGA_Dummy+6)
#define	AGA_Reserved2		(AGA_Dummy+7)
#define	AGA_Reserved3		(AGA_Dummy+8)

#define	AGA_ARexxPort		(AGA_Dummy+9)
    /* (struct MsgPort *) Pointer to the ARexx message port (V40) */

#define	AGA_ARexxPortName	(AGA_Dummy+10)
   /* (STRPTR) Used to specify the ARexx port name (V40) (not copied) */

#define AGA_Secure		(AGA_Dummy+11)
   /* (BOOL) Disable "ONOPEN", "ONCLOSE" and "LINK RX", "LINK RXS", "LINK SYSTEM" commands (V41) */

typedef void *AMIGAGUIDECONTEXT;

struct AmigaGuideMsg
{
    struct Message	 agm_Msg;			/* Embedded Exec message structure */
    ULONG		 agm_Type;			/* Type of message */
    APTR		 agm_Data;			/* Pointer to message data */
    ULONG		 agm_DSize;			/* Size of message data */
    ULONG		 agm_DType;			/* Type of message data */
    ULONG		 agm_Pri_Ret;			/* Primary return value */
    ULONG		 agm_Sec_Ret;			/* Secondary return value */
    APTR		 agm_System1;
    APTR		 agm_System2;
};

/* Allocation description structure */
struct NewAmigaGuide
{
    BPTR		 nag_Lock;			/* Lock on the document directory */
    STRPTR		 nag_Name;			/* Name of document file */
    struct Screen	*nag_Screen;			/* Screen to place windows within */
    STRPTR		 nag_PubScreen;			/* Public screen name to open on */
    STRPTR		 nag_HostPort;			/* Application's ARexx port name */
    STRPTR		 nag_ClientPort;		/* Name to assign to the clients ARexx port */
    STRPTR		 nag_BaseName;			/* Base name of the application */
    ULONG		 nag_Flags;			/* Flags */
    STRPTR		*nag_Context;			/* NULL terminated context table */
    STRPTR		 nag_Node;			/* Node to align on first (defaults to Main) */
    LONG		 nag_Line;			/* Line to align on */
    struct TagItem	*nag_Extens;			/* Tag array extension */
    VOID		*nag_Client;			/* Private! MUST be NULL */
};

/* public Client flags */
#define	HTF_LOAD_INDEX		(1L<<0)			/* Force load the index at init time */
#define	HTF_LOAD_ALL		(1L<<1)			/* Force load the entire database at init */
#define	HTF_CACHE_NODE		(1L<<2)			/* Cache each node as visited */
#define	HTF_CACHE_DB		(1L<<3)			/* Keep the buffers around until expunge */
#define	HTF_UNIQUE		(1L<<15)		/* Unique ARexx port name */
#define	HTF_NOACTIVATE		(1L<<16)		/* Don't activate window */

#define	HTFC_SYSGADS		0x80000000

/* Callback function ID's */
#define	HTH_OPEN		0
#define	HTH_CLOSE		1

#define	HTERR_NOT_ENOUGH_MEMORY		100L
#define	HTERR_CANT_OPEN_DATABASE	101L
#define	HTERR_CANT_FIND_NODE		102L
#define	HTERR_CANT_OPEN_NODE		103L
#define	HTERR_CANT_OPEN_WINDOW		104L
#define	HTERR_INVALID_COMMAND		105L
#define	HTERR_CANT_COMPLETE		106L
#define	HTERR_PORT_CLOSED		107L
#define	HTERR_CANT_CREATE_PORT		108L
#define	HTERR_KEYWORD_NOT_FOUND		113L

typedef struct AmigaGuideHost *AMIGAGUIDEHOST;

/* Cross reference node */
struct XRef
{
    struct Node		 xr_Node;			/* Embedded node */
    UWORD		 xr_Pad;			/* Padding */
    struct DocFile	*xr_DF;				/* Document defined in */
    STRPTR		 xr_File;			/* Name of document file */
    STRPTR		 xr_Name;			/* Name of item */
    LONG		 xr_Line;			/* Line defined at */
    ULONG                xr_Reserved[2];		/* Don't touch! (V44) */
};

#define	XRSIZE	(sizeof (struct XRef))

/* Types of cross reference nodes */
#define	XR_GENERIC	0
#define	XR_FUNCTION	1
#define	XR_COMMAND	2
#define	XR_INCLUDE	3
#define	XR_MACRO	4
#define	XR_STRUCT	5
#define	XR_FIELD	6
#define	XR_TYPEDEF	7
#define	XR_DEFINE	8

/* Callback handle */
struct AmigaGuideHost
{
    struct Hook		 agh_Dispatcher;		/* Dispatcher */
    ULONG		 agh_Reserved;			/* Must be 0 */
    ULONG		 agh_Flags;
    ULONG		 agh_UseCnt;			/* Number of open nodes */
    APTR		 agh_SystemData;		/* Reserved for system use */
    APTR		 agh_UserData;			/* Anything you want... */
};

/* Methods */
#define	HM_FINDNODE	1
#define	HM_OPENNODE	2
#define	HM_CLOSENODE	3
#define	HM_EXPUNGE	10		/* Expunge DataBase */

/* HM_FINDNODE */
struct opFindHost
{
    ULONG MethodID;
    struct TagItem *ofh_Attrs;		/*  R: Additional attributes */
    STRPTR ofh_Node;			/*  R: Name of node */
    STRPTR ofh_TOC;			/*  W: Table of Contents */
    STRPTR ofh_Title;			/*  W: Title to give to the node */
    STRPTR ofh_Next;			/*  W: Next node to browse to */
    STRPTR ofh_Prev;			/*  W: Previous node to browse to */
};

/* HM_OPENNODE, HM_CLOSENODE */
struct opNodeIO
{
    ULONG MethodID;
    struct TagItem *onm_Attrs;		/*  R: Additional attributes */
    STRPTR onm_Node;			/*  R: Node name and arguments */
    STRPTR onm_FileName;		/*  W: File name buffer */
    STRPTR onm_DocBuffer;		/*  W: Node buffer */
    ULONG onm_BuffLen;			/*  W: Size of buffer */
    ULONG onm_Flags;			/* RW: Control flags */
};

/* onm_Flags */
#define	HTNF_KEEP	(1L<<0)	/* Don't flush this node until database is
                 * closed. */
#define	HTNF_RESERVED1	(1L<<1)	/* Reserved for system use */
#define	HTNF_RESERVED2	(1L<<2)	/* Reserved for system use */
#define	HTNF_ASCII	(1L<<3)	/* Node is straight ASCII */
#define	HTNF_RESERVED3	(1L<<4)	/* Reserved for system use */
#define	HTNF_CLEAN	(1L<<5)	/* Remove the node from the database */
#define	HTNF_DONE	(1L<<6)	/* Done with node */

/* onm_Attrs */
#define	HTNA_Dummy	(TAG_USER)
#define	HTNA_Screen	(HTNA_Dummy+1)	/* (struct Screen *) Screen that window resides in */
#define	HTNA_Pens	(HTNA_Dummy+2)	/* Pen array (from DrawInfo) */
#define	HTNA_Rectangle	(HTNA_Dummy+3)	/* Window box */

#define	HTNA_HelpGroup	(HTNA_Dummy+5)	/* (ULONG) unique identifier */

/* HM_EXPUNGE */
struct opExpungeNode
{
    ULONG MethodID;
    struct TagItem *oen_Attrs;		/*  R: Additional attributes */
};

#endif /* LIBRARIES_AMIGAGUIDE_H */


include/graphics/monitor.h

#ifndef	GRAPHICS_MONITOR_H
#define	GRAPHICS_MONITOR_H
/*
**	$VER: monitor.h 39.7 (9.6.1992)
**	Includes Release 44.1
**
**	graphics monitorspec definintions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef	EXEC_SEMAPHORES_H
#include	<exec/semaphores.h>
#endif

#ifndef	GRAPHICS_GFXNODES_H
#include	<graphics/gfxnodes.h>
#endif

#ifndef	GRAPHICS_GFX_H
#include	<graphics/gfx.h>
#endif

struct	MonitorSpec
{
    struct	ExtendedNode	ms_Node;
    UWORD	ms_Flags;
    LONG	ratioh;
    LONG	ratiov;
    UWORD	total_rows;
    UWORD	total_colorclocks;
    UWORD	DeniseMaxDisplayColumn;
    UWORD	BeamCon0;
    UWORD	min_row;
    struct	SpecialMonitor	*ms_Special;
    UWORD	ms_OpenCount;
    LONG	(*ms_transform)();
    LONG	(*ms_translate)();
    LONG	(*ms_scale)();
    UWORD	ms_xoffset;
    UWORD	ms_yoffset;
    struct	Rectangle	ms_LegalView;
    LONG	(*ms_maxoscan)();	/* maximum legal overscan */
    LONG	(*ms_videoscan)();	/* video display overscan */
    UWORD	DeniseMinDisplayColumn;
    ULONG	DisplayCompatible;
    struct	List DisplayInfoDataBase;
    struct	SignalSemaphore DisplayInfoDataBaseSemaphore;
    LONG	(*ms_MrgCop)();
    LONG	(*ms_LoadView)();
    LONG	(*ms_KillView)();
};

#define	TO_MONITOR		0
#define	FROM_MONITOR		1
#define	STANDARD_XOFFSET	9
#define	STANDARD_YOFFSET	0

#define MSB_REQUEST_NTSC	0
#define MSB_REQUEST_PAL		1
#define MSB_REQUEST_SPECIAL	2
#define MSB_REQUEST_A2024	3
#define MSB_DOUBLE_SPRITES	4
#define	MSF_REQUEST_NTSC	(1 << MSB_REQUEST_NTSC)
#define	MSF_REQUEST_PAL		(1 << MSB_REQUEST_PAL)
#define	MSF_REQUEST_SPECIAL		(1 << MSB_REQUEST_SPECIAL)
#define	MSF_REQUEST_A2024		(1 << MSB_REQUEST_A2024)
#define MSF_DOUBLE_SPRITES		(1 << MSB_DOUBLE_SPRITES)

/* obsolete, v37 compatible definitions follow */
#define	REQUEST_NTSC		(1 << MSB_REQUEST_NTSC)
#define	REQUEST_PAL		(1 << MSB_REQUEST_PAL)
#define	REQUEST_SPECIAL		(1 << MSB_REQUEST_SPECIAL)
#define	REQUEST_A2024		(1 << MSB_REQUEST_A2024)

#define	DEFAULT_MONITOR_NAME	"default.monitor"
#define	NTSC_MONITOR_NAME	"ntsc.monitor"
#define	PAL_MONITOR_NAME	"pal.monitor"
#define	STANDARD_MONITOR_MASK	( REQUEST_NTSC | REQUEST_PAL )

#define	STANDARD_NTSC_ROWS	262
#define	STANDARD_PAL_ROWS	312
#define	STANDARD_COLORCLOCKS	226
#define	STANDARD_DENISE_MAX	455
#define	STANDARD_DENISE_MIN	93
#define	STANDARD_NTSC_BEAMCON	( 0x0000 )
#define	STANDARD_PAL_BEAMCON	( DISPLAYPAL )

#define	SPECIAL_BEAMCON	( VARVBLANK | LOLDIS | VARVSYNC | VARHSYNC | VARBEAM | CSBLANK | VSYNCTRUE)

#define	MIN_NTSC_ROW	21
#define	MIN_PAL_ROW	29
#define	STANDARD_VIEW_X	0x81
#define	STANDARD_VIEW_Y	0x2C
#define	STANDARD_HBSTRT	0x06
#define	STANDARD_HSSTRT	0x0B
#define	STANDARD_HSSTOP	0x1C
#define	STANDARD_HBSTOP	0x2C
#define	STANDARD_VBSTRT	0x0122
#define	STANDARD_VSSTRT	0x02A6
#define	STANDARD_VSSTOP	0x03AA
#define	STANDARD_VBSTOP	0x1066

#define	VGA_COLORCLOCKS (STANDARD_COLORCLOCKS/2)
#define	VGA_TOTAL_ROWS	(STANDARD_NTSC_ROWS*2)
#define	VGA_DENISE_MIN	59
#define	MIN_VGA_ROW	29
#define	VGA_HBSTRT	0x08
#define	VGA_HSSTRT	0x0E
#define	VGA_HSSTOP	0x1C
#define	VGA_HBSTOP	0x1E
#define	VGA_VBSTRT	0x0000
#define	VGA_VSSTRT	0x0153
#define	VGA_VSSTOP	0x0235
#define	VGA_VBSTOP	0x0CCD

#define	VGA_MONITOR_NAME	"vga.monitor"

/* NOTE: VGA70 definitions are obsolete - a VGA70 monitor has never been
 * implemented.
 */
#define	VGA70_COLORCLOCKS (STANDARD_COLORCLOCKS/2)
#define	VGA70_TOTAL_ROWS 449
#define	VGA70_DENISE_MIN 59
#define	MIN_VGA70_ROW	35
#define	VGA70_HBSTRT	0x08
#define	VGA70_HSSTRT	0x0E
#define	VGA70_HSSTOP	0x1C
#define	VGA70_HBSTOP	0x1E
#define	VGA70_VBSTRT	0x0000
#define	VGA70_VSSTRT	0x02A6
#define	VGA70_VSSTOP	0x0388
#define	VGA70_VBSTOP	0x0F73

#define	VGA70_BEAMCON	(SPECIAL_BEAMCON ^ VSYNCTRUE)
#define	VGA70_MONITOR_NAME	"vga70.monitor"

#define	BROADCAST_HBSTRT	0x01
#define	BROADCAST_HSSTRT	0x06
#define	BROADCAST_HSSTOP	0x17
#define	BROADCAST_HBSTOP	0x27
#define	BROADCAST_VBSTRT	0x0000
#define	BROADCAST_VSSTRT	0x02A6
#define	BROADCAST_VSSTOP	0x054C
#define	BROADCAST_VBSTOP	0x1C40
#define	BROADCAST_BEAMCON	( LOLDIS | CSBLANK )
#define	RATIO_FIXEDPART	4
#define	RATIO_UNITY	(1 << RATIO_FIXEDPART)

struct	AnalogSignalInterval
{
    UWORD	asi_Start;
    UWORD	asi_Stop;
};

struct	SpecialMonitor
{
    struct	ExtendedNode	spm_Node;
    UWORD	spm_Flags;
    LONG	(*do_monitor)();
    LONG	(*reserved1)();
    LONG	(*reserved2)();
    LONG	(*reserved3)();
    struct	AnalogSignalInterval	hblank;
    struct	AnalogSignalInterval	vblank;
    struct	AnalogSignalInterval	hsync;
    struct	AnalogSignalInterval	vsync;
};

#endif	/* GRAPHICS_MONITOR_H */


include/graphics/gels.h

#ifndef	GRAPHICS_GELS_H
#define	GRAPHICS_GELS_H
/*
**	$VER: gels.h 39.0 (21.8.1991)
**	Includes Release 44.1
**
**	include file for AMIGA GELS (Graphics Elements)
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

/* VSprite flags */
/* user-set VSprite flags: */
#define SUSERFLAGS  0x00FF    /* mask of all user-settable VSprite-flags */
#define VSPRITE     0x0001    /* set if VSprite, clear if Bob */
#define SAVEBACK    0x0002    /* set if background is to be saved/restored */
#define OVERLAY     0x0004    /* set to mask image of Bob onto background */
#define MUSTDRAW    0x0008    /* set if VSprite absolutely must be drawn */
/* system-set VSprite flags: */
#define BACKSAVED   0x0100    /* this Bob's background has been saved */
#define BOBUPDATE   0x0200    /* temporary flag, useless to outside world */
#define GELGONE     0x0400    /* set if gel is completely clipped (offscreen) */
#define VSOVERFLOW  0x0800    /* VSprite overflow (if MUSTDRAW set we draw!) */

/* Bob flags */
/* these are the user flag bits */
#define BUSERFLAGS  0x00FF    /* mask of all user-settable Bob-flags */
#define SAVEBOB     0x0001    /* set to not erase Bob */
#define BOBISCOMP   0x0002    /* set to identify Bob as AnimComp */
/* these are the system flag bits */
#define BWAITING    0x0100    /* set while Bob is waiting on 'after' */
#define BDRAWN	    0x0200    /* set when Bob is drawn this DrawG pass*/
#define BOBSAWAY    0x0400    /* set to initiate removal of Bob */
#define BOBNIX	    0x0800    /* set when Bob is completely removed */
#define SAVEPRESERVE 0x1000   /* for back-restore during double-buffer*/
#define OUTSTEP     0x2000    /* for double-clearing if double-buffer */

/* defines for the animation procedures */
#define ANFRACSIZE  6
#define ANIMHALF    0x0020
#define RINGTRIGGER 0x0001

/* UserStuff definitions
 *  the user can define these to be a single variable or a sub-structure
 *  if undefined by the user, the system turns these into innocuous variables
 *  see the manual for a thorough definition of the UserStuff definitions
 *
 */
#ifndef VUserStuff	      /* VSprite user stuff */
#define VUserStuff WORD
#endif

#ifndef BUserStuff	      /* Bob user stuff */
#define BUserStuff WORD
#endif

#ifndef AUserStuff	      /* AnimOb user stuff */
#define AUserStuff WORD
#endif

/*********************** GEL STRUCTURES ***********************************/

struct VSprite
{
/* --------------------- SYSTEM VARIABLES ------------------------------- */
/* GEL linked list forward/backward pointers sorted by y,x value */
    struct VSprite   *NextVSprite;
    struct VSprite   *PrevVSprite;

/* GEL draw list constructed in the order the Bobs are actually drawn, then
 *  list is copied to clear list
 *  must be here in VSprite for system boundary detection
 */
    struct VSprite   *DrawPath;     /* pointer of overlay drawing */
    struct VSprite   *ClearPath;    /* pointer for overlay clearing */

/* the VSprite positions are defined in (y,x) order to make sorting
 *  sorting easier, since (y,x) as a long integer
 */
    WORD OldY, OldX;	      /* previous position */

/* --------------------- COMMON VARIABLES --------------------------------- */
    WORD Flags;	      /* VSprite flags */

/* --------------------- USER VARIABLES ----------------------------------- */
/* the VSprite positions are defined in (y,x) order to make sorting
 *  sorting easier, since (y,x) as a long integer
 */
    WORD Y, X;		      /* screen position */

    WORD Height;
    WORD Width;	      /* number of words per row of image data */
    WORD Depth;	      /* number of planes of data */

    WORD MeMask;	      /* which types can collide with this VSprite*/
    WORD HitMask;	      /* which types this VSprite can collide with*/

    WORD *ImageData;	      /* pointer to VSprite image */

/* borderLine is the one-dimensional logical OR of all
 *  the VSprite bits, used for fast collision detection of edge
 */
    WORD *BorderLine;	      /* logical OR of all VSprite bits */
    WORD *CollMask;	      /* similar to above except this is a matrix */

/* pointer to this VSprite's color definitions (not used by Bobs) */
    WORD *SprColors;

    struct Bob *VSBob;	      /* points home if this VSprite is part of
                   a Bob */

/* planePick flag:  set bit selects a plane from image, clear bit selects
 *  use of shadow mask for that plane
 * OnOff flag: if using shadow mask to fill plane, this bit (corresponding
 *  to bit in planePick) describes whether to fill with 0's or 1's
 * There are two uses for these flags:
 *	- if this is the VSprite of a Bob, these flags describe how the Bob
 *	  is to be drawn into memory
 *	- if this is a simple VSprite and the user intends on setting the
 *	  MUSTDRAW flag of the VSprite, these flags must be set too to describe
 *	  which color registers the user wants for the image
 */
    BYTE PlanePick;
    BYTE PlaneOnOff;

    VUserStuff VUserExt;      /* user definable:  see note above */
};

struct Bob
/* blitter-objects */
{
/* --------------------- SYSTEM VARIABLES --------------------------------- */

/* --------------------- COMMON VARIABLES --------------------------------- */
    WORD Flags;	/* general purpose flags (see definitions below) */

/* --------------------- USER VARIABLES ----------------------------------- */
    WORD *SaveBuffer;	/* pointer to the buffer for background save */

/* used by Bobs for "cookie-cutting" and multi-plane masking */
    WORD *ImageShadow;

/* pointer to BOBs for sequenced drawing of Bobs
 *  for correct overlaying of multiple component animations
 */
    struct Bob *Before; /* draw this Bob before Bob pointed to by before */
    struct Bob *After;	/* draw this Bob after Bob pointed to by after */

    struct VSprite   *BobVSprite;   /* this Bob's VSprite definition */

    struct AnimComp  *BobComp;	    /* pointer to this Bob's AnimComp def */

    struct DBufPacket *DBuffer;     /* pointer to this Bob's dBuf packet */

    BUserStuff BUserExt;	    /* Bob user extension */
};

struct AnimComp
{
/* --------------------- SYSTEM VARIABLES --------------------------------- */

/* --------------------- COMMON VARIABLES --------------------------------- */
    WORD Flags;		    /* AnimComp flags for system & user */

/* timer defines how long to keep this component active:
 *  if set non-zero, timer decrements to zero then switches to nextSeq
 *  if set to zero, AnimComp never switches
 */
    WORD Timer;

/* --------------------- USER VARIABLES ----------------------------------- */
/* initial value for timer when the AnimComp is activated by the system */
    WORD TimeSet;

/* pointer to next and previous components of animation object */
    struct AnimComp  *NextComp;
    struct AnimComp  *PrevComp;

/* pointer to component component definition of next image in sequence */
    struct AnimComp  *NextSeq;
    struct AnimComp  *PrevSeq;

/* address of special animation procedure */
    WORD (*AnimCRoutine) __CLIB_PROTOTYPE((struct AnimComp *));

    WORD YTrans;     /* initial y translation (if this is a component) */
    WORD XTrans;     /* initial x translation (if this is a component) */

    struct AnimOb    *HeadOb;

    struct Bob	     *AnimBob;
};

struct AnimOb
{
/* --------------------- SYSTEM VARIABLES --------------------------------- */
    struct AnimOb    *NextOb, *PrevOb;

/* number of calls to Animate this AnimOb has endured */
    LONG Clock;

    WORD AnOldY, AnOldX;	    /* old y,x coordinates */

/* --------------------- COMMON VARIABLES --------------------------------- */
    WORD AnY, AnX;		    /* y,x coordinates of the AnimOb */

/* --------------------- USER VARIABLES ----------------------------------- */
    WORD YVel, XVel;		    /* velocities of this object */
    WORD YAccel, XAccel;	    /* accelerations of this object */

    WORD RingYTrans, RingXTrans;    /* ring translation values */

                        /* address of special animation
                       procedure */
    WORD (*AnimORoutine) __CLIB_PROTOTYPE((struct AnimOb *));

    struct AnimComp  *HeadComp;     /* pointer to first component */

    AUserStuff AUserExt;	    /* AnimOb user extension */
};

/* dBufPacket defines the values needed to be saved across buffer to buffer
 *  when in double-buffer mode
 */
struct DBufPacket
{
    WORD BufY, BufX;		    /* save the other buffers screen coordinates */
    struct VSprite   *BufPath;	    /* carry the draw path over the gap */

/* these pointers must be filled in by the user */
/* pointer to other buffer's background save buffer */
    WORD *BufBuffer;
};

/* ************************************************************************ */

/* these are GEL functions that are currently simple enough to exist as a
 *  definition.  It should not be assumed that this will always be the case
 */
#define InitAnimate(animKey) {*(animKey) = NULL;}
#define RemBob(b) {(b)->Flags |= BOBSAWAY;}

/* ************************************************************************ */

#define B2NORM	    0
#define B2SWAP	    1
#define B2BOBBER    2

/* ************************************************************************ */

/* a structure to contain the 16 collision procedure addresses */
struct collTable
{
    /* NOTE: This table actually consists of two different types of
     *       pointers. The first table entry is for collision testing,
     *       the other are for reporting collisions. The first function
     *       pointer looks like this:
     *
     *          LONG (*collPtrs[0])(struct VSprite *,WORD);
     *
     *       The remaining 15 function pointers look like this:
     *
     *          VOID (*collPtrs[1..15])(struct VSprite *,struct VSPrite *);
     */
    LONG (*collPtrs[16]) __CLIB_PROTOTYPE((struct VSprite *,struct VSPrite *));
};

#endif	/* GRAPHICS_GELS_H */


include/classes/arexx.h

#ifndef CLASSES_AREXX_H
#define CLASSES_AREXX_H
/*
**	$VER: arexx.h 44.1 (19.10.1999)
**	Includes Release 44.1
**
**	arexx.class definitions
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_MEMORY_H
#include <exec/memory.h>
#endif

#ifndef DOS_DOS_H
#include <dos/dos.h>
#endif

#ifndef DOS_RDARGS_H
#include <dos/rdargs.h>
#endif

#ifndef REXX_STORAGE_H
#include <rexx/storage.h>
#endif

#ifndef REXX_RXSLIB_H
#include <rexx/rxslib.h>
#endif

#ifndef REXX_ERRORS_H
#include <rexx/errors.h>
#endif

#ifndef INTUITION_CLASSES_H
#include <intuition/classes.h>
#endif

#ifndef INTUITION_CLASSUSR_H
#include <intuition/classusr.h>
#endif

#ifndef UTILITY_HOOKS_H
#include <utility/hooks.h>
#endif

/*****************************************************************************/

/* Tags supported by the arexx class
 */
#define AREXX_Dummy				(REACTION_Dummy+0x30000)

#define AREXX_HostName			(AREXX_Dummy+1)
    /* (STRPTR) */
#define AREXX_DefExtension		(AREXX_Dummy+2)
    /* (STRPTR) */
#define AREXX_Commands			(AREXX_Dummy+3)
    /* (struct ARexxCmd *) */
#define AREXX_ErrorCode			(AREXX_Dummy+4)
    /* (ULONG *) */
#define AREXX_SigMask			(AREXX_Dummy+5)
    /* (ULONG) */
#define AREXX_NoSlot			(AREXX_Dummy+6)
    /* (BOOL) */
#define AREXX_ReplyHook			(AREXX_Dummy+7)
    /* (struct Hook *) */
#define AREXX_MsgPort			(AREXX_Dummy+8)
    /* (struct MsgPort *) */

/* Possible error result codes
 */
#define RXERR_NO_COMMAND_LIST     (1L)
#define RXERR_NO_PORT_NAME        (2L)
#define RXERR_PORT_ALREADY_EXISTS (3L)
#define RXERR_OUT_OF_MEMORY       (4L)

/* I can't spell, don't use this.
 */
#define AREXX_DefExtention	AREXX_DefExtension

/*****************************************************************************/

/* Methods Supported by the ARexx Class.
 */
#define AM_HANDLEEVENT                (0x590001)
    /* ARexx class event-handler. */

#define AM_EXECUTE                    (0x590002)
    /* Execute a host command. */

#define AM_FLUSH                      (0x590003)
    /* Flush rexx port. */

/* AM_EXECUTE message.
 */
struct apExecute
{
    ULONG MethodID;				/* AM_EXECUTE */
    STRPTR ape_CommandString;	/* Command string to execute */
    STRPTR ape_PortName;		/* Port to send to (usually RXSDIR) */
    LONG *ape_RC;				/* RC pointer */
    LONG *ape_RC2;				/* RC2 pointer */
    STRPTR *ape_Result;			/* Result pointer */
    BPTR ape_IO;				/* I/O handle */
};

/*****************************************************************************/

/* An array of these structures must be passed at object-create time.
 */
struct ARexxCmd
{
    STRPTR ac_Name;			/* Command name */
    UWORD ac_ID;			/* Unique ID */

    /* NOTE: The function pointed to by ac_Func() will be called
     *       with parameters in CPU registers. Register usage
     *       is as follows:
     *
     *       VOID ac_Func(struct ARexxCmd * cmd, struct RexxMsg * rm)
     *                                       A0                   A1
     */
    VOID (*ac_Func)();

    STRPTR ac_ArgTemplate;	/* DOS-style argument template */
    ULONG ac_Flags;			/* Unused, make NULL */
    ULONG *ac_ArgList;		/* Result of ReadArgs() */
    LONG ac_RC;				/* Primary result */
    LONG ac_RC2;			/* Secondary result */
    STRPTR ac_Result;		/* RESULT variable */
};

#endif /* CLASSES_AREXX_H */


include/workbench/workbench.h

#ifndef WORKBENCH_WORKBENCH_H
#define WORKBENCH_WORKBENCH_H
/*
**	$VER: workbench.h 44.30 (27.9.1999)
**	Includes Release 44.1
**
**	workbench.library general definitions
**
**	Copyright © 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TASKS_H
#include <exec/tasks.h>
#endif

#ifndef DOS_DOS_H
#include <dos/dos.h>
#endif

#ifndef INTUITION_INTUITION_H
#include <intuition/intuition.h>
#endif

#define	WBDISK		1
#define	WBDRAWER	2
#define	WBTOOL		3
#define	WBPROJECT	4
#define	WBGARBAGE	5
#define	WBDEVICE	6
#define	WBKICK		7
#define WBAPPICON	8

struct OldDrawerData { /* pre V36 definition */
    struct NewWindow	dd_NewWindow;	/* args to open window */
    LONG		dd_CurrentX;	/* current x coordinate of origin */
    LONG		dd_CurrentY;	/* current y coordinate of origin */
};
/* the amount of DrawerData actually written to disk */
#define OLDDRAWERDATAFILESIZE	(sizeof(struct OldDrawerData))

struct DrawerData {
    struct NewWindow	dd_NewWindow;	/* args to open window */
    LONG		dd_CurrentX;	/* current x coordinate of origin */
    LONG		dd_CurrentY;	/* current y coordinate of origin */
    ULONG		dd_Flags;	/* flags for drawer */
    UWORD		dd_ViewModes;	/* view mode for drawer */
};
/* the amount of DrawerData actually written to disk */
#define DRAWERDATAFILESIZE	(sizeof(struct DrawerData))

/* definitions for dd_ViewModes */
#define DDVM_BYDEFAULT		0	/* default (inherit parent's view mode) */
#define DDVM_BYICON		1	/* view as icons */
#define DDVM_BYNAME		2	/* view as text, sorted by name */
#define DDVM_BYDATE		3	/* view as text, sorted by date */
#define DDVM_BYSIZE		4	/* view as text, sorted by size */
#define DDVM_BYTYPE		5	/* view as text, sorted by type */

/* definitions for dd_Flags */
#define	DDFLAGS_SHOWDEFAULT	0	/* default (show only icons) */
#define	DDFLAGS_SHOWICONS	1	/* show only icons */
#define	DDFLAGS_SHOWALL		2	/* show all files */

struct DiskObject {
    UWORD		do_Magic; /* a magic number at the start of the file */
    UWORD		do_Version; /* a version number, so we can change it */
    struct Gadget 	do_Gadget;	/* a copy of in core gadget */
    UBYTE		do_Type;
    STRPTR		do_DefaultTool;
    STRPTR *		do_ToolTypes;
    LONG		do_CurrentX;
    LONG		do_CurrentY;
    struct DrawerData *	do_DrawerData;
    STRPTR		do_ToolWindow;	/* only applies to tools */
    LONG		do_StackSize;	/* only applies to tools */

};

#define WB_DISKMAGIC	0xe310	/* a magic number, not easily impersonated */
#define WB_DISKVERSION	1	/* our current version number */
#define WB_DISKREVISION	1	/* our current revision number */
/* I only use the lower 8 bits of Gadget.UserData for the revision # */
#define WB_DISKREVISIONMASK	255

struct FreeList {
    WORD		fl_NumFree;
    struct List		fl_MemList;
};

/* workbench does different complement modes for its gadgets.
** It supports separate images, complement mode, and backfill mode.
** The first two are identical to intuitions GFLG_GADGIMAGE and GFLG_GADGHCOMP.
** backfill is similar to GFLG_GADGHCOMP, but the region outside of the
** image (which normally would be color three when complemented)
** is flood-filled to color zero.
*/
#define GFLG_GADGBACKFILL 0x0001
#define GADGBACKFILL	  0x0001    /* an old synonym */

/* if an icon does not really live anywhere, set its current position
** to here
*/
#define NO_ICON_POSITION	(0x80000000)

/* workbench now is a library.  this is it's name */
#define WORKBENCH_NAME		"workbench.library"

/****************************************************************************/

/* If you find am_Version >= AM_VERSION, you know this structure has
 * at least the fields defined in this version of the include file
 */
#define	AM_VERSION	1

struct AppMessage {
    struct Message am_Message;	/* standard message structure */
    UWORD am_Type;		/* message type */
    ULONG am_UserData;		/* application specific */
    ULONG am_ID;		/* application definable ID */
    LONG am_NumArgs;		/* # of elements in arglist */
    struct WBArg *am_ArgList;	/* the arguments themselves */
    UWORD am_Version;		/* will be >= AM_VERSION */
    UWORD am_Class;		/* message class */
    WORD am_MouseX;		/* mouse x position of event */
    WORD am_MouseY;		/* mouse y position of event */
    ULONG am_Seconds;		/* current system clock time */
    ULONG am_Micros;		/* current system clock time */
    ULONG am_Reserved[8];	/* avoid recompilation */
};

/* types of app messages */
#define AMTYPE_APPWINDOW        7	/* app window message    */
#define AMTYPE_APPICON	        8	/* app icon message      */
#define AMTYPE_APPMENUITEM      9	/* app menu item message */
#define AMTYPE_APPWINDOWZONE   10	/* app window drop zone message    */

/* Classes of AppIcon messages (V44) */
#define AMCLASSICON_Open	0	/* The "Open" menu item was invoked,
                     * the icon got double-clicked or an
                     * icon got dropped on it.
                     */
#define AMCLASSICON_Copy	1	/* The "Copy" menu item was invoked */
#define AMCLASSICON_Rename	2	/* The "Rename" menu item was invoked */
#define AMCLASSICON_Information	3	/* The "Information" menu item was invoked */
#define AMCLASSICON_Snapshot	4	/* The "Snapshot" menu item was invoked */
#define AMCLASSICON_UnSnapshot	5	/* The "UnSnapshot" menu item was invoked */
#define AMCLASSICON_LeaveOut	6	/* The "Leave Out" menu item was invoked */
#define AMCLASSICON_PutAway	7	/* The "Put Away" menu item was invoked */
#define AMCLASSICON_Delete	8	/* The "Delete" menu item was invoked */
#define AMCLASSICON_FormatDisk	9	/* The "Format Disk" menu item was invoked */
#define AMCLASSICON_EmptyTrash	10	/* The "Empty Trash" menu item was invoked */

#define AMCLASSICON_Selected	11	/* The icon is now selected */
#define AMCLASSICON_Unselected	12	/* The icon is now unselected */

/*
 * The following structures are private.  These are just stub
 * structures for code compatibility...
 */
struct AppWindow		{ void * aw_PRIVATE;   };
struct AppWindowDropZone	{ void * awdz_PRIVATE; };
struct AppIcon			{ void * ai_PRIVATE;   };
struct AppMenuItem		{ void * ami_PRIVATE;  };

/****************************************************************************/

#define	WBA_Dummy (TAG_USER+0xA000)

/****************************************************************************/

/* Tags for use with AddAppIconA() */

/* AppIcon responds to the "Open" menu item (BOOL). */
#define WBAPPICONA_SupportsOpen		(WBA_Dummy+1)

/* AppIcon responds to the "Copy" menu item (BOOL). */
#define WBAPPICONA_SupportsCopy		(WBA_Dummy+2)

/* AppIcon responds to the "Rename" menu item (BOOL). */
#define WBAPPICONA_SupportsRename	(WBA_Dummy+3)

/* AppIcon responds to the "Information" menu item (BOOL). */
#define WBAPPICONA_SupportsInformation	(WBA_Dummy+4)

/* AppIcon responds to the "Snapshot" menu item (BOOL). */
#define WBAPPICONA_SupportsSnapshot	(WBA_Dummy+5)

/* AppIcon responds to the "UnSnapshot" menu item (BOOL). */
#define WBAPPICONA_SupportsUnSnapshot	(WBA_Dummy+6)

/* AppIcon responds to the "LeaveOut" menu item (BOOL). */
#define WBAPPICONA_SupportsLeaveOut	(WBA_Dummy+7)

/* AppIcon responds to the "PutAway" menu item (BOOL). */
#define WBAPPICONA_SupportsPutAway	(WBA_Dummy+8)

/* AppIcon responds to the "Delete" menu item (BOOL). */
#define WBAPPICONA_SupportsDelete	(WBA_Dummy+9)

/* AppIcon responds to the "FormatDisk" menu item (BOOL). */
#define WBAPPICONA_SupportsFormatDisk	(WBA_Dummy+10)

/* AppIcon responds to the "EmptyTrash" menu item (BOOL). */
#define WBAPPICONA_SupportsEmptyTrash	(WBA_Dummy+11)

/* AppIcon position should be propagated back to original DiskObject (BOOL). */
#define WBAPPICONA_PropagatePosition	(WBA_Dummy+12)

/* Callback hook to be invoked when rendering this icon (struct Hook *). */
#define WBAPPICONA_RenderHook		(WBA_Dummy+13)

/* AppIcon wants to be notified when its select state changes (BOOL). */
#define	WBAPPICONA_NotifySelectState	(WBA_Dummy+14)

/****************************************************************************/

/* Tags for use with AddAppMenuA() */

/* Command key string for this AppMenu (STRPTR). */
#define	WBAPPMENUA_CommandKeyString	 (WBA_Dummy+15)

/****************************************************************************/

/* Tags for use with OpenWorkbenchObjectA() */

/* Corresponds to the wa_Lock member of a struct WBArg */
#define WBOPENA_ArgLock			(WBA_Dummy+16)

/* Corresponds to the wa_Name member of a struct WBArg */
#define WBOPENA_ArgName			(WBA_Dummy+17)

/****************************************************************************/

/* Tags for use with WorkbenchControlA() */

/* Check if the named drawer is currently open (LONG *). */
#define WBCTRLA_IsOpen			(WBA_Dummy+18)

/* Create a duplicate of the Workbench private search path list (BPTR *). */
#define WBCTRLA_DuplicateSearchPath	(WBA_Dummy+19)

/* Free the duplicated search path list (BPTR). */
#define WBCTRLA_FreeSearchPath		(WBA_Dummy+20)

/* Get the default stack size for launching programs with (ULONG *). */
#define WBCTRLA_GetDefaultStackSize	(WBA_Dummy+21)

/* Set the default stack size for launching programs with (ULONG). */
#define WBCTRLA_SetDefaultStackSize	(WBA_Dummy+22)

/* Cause an AppIcon to be redrawn (struct AppIcon *). */
#define WBCTRLA_RedrawAppIcon		(WBA_Dummy+23)

/* Get a list of currently running Workbench programs (struct List **). */
#define WBCTRLA_GetProgramList		(WBA_Dummy+24)

/* Release the list of currently running Workbench programs (struct List *). */
#define WBCTRLA_FreeProgramList		(WBA_Dummy+25)

/* Get a list of currently selected icons (struct List **). */
#define	WBCTRLA_GetSelectedIconList	(WBA_Dummy+36)

/* Release the list of currently selected icons (struct List *). */
#define	WBCTRLA_FreeSelectedIconList	(WBA_Dummy+37)

/* Get a list of currently open drawers (struct List **). */
#define	WBCTRLA_GetOpenDrawerList	(WBA_Dummy+38)

/* Release the list of currently open icons (struct List *). */
#define	WBCTRLA_FreeOpenDrawerList	(WBA_Dummy+39)

/* Get the list of hidden devices (struct List **). */
#define	WBCTRLA_GetHiddenDeviceList	(WBA_Dummy+42)

/* Release the list of hidden devices (struct List *). */
#define	WBCTRLA_FreeHiddenDeviceList	(WBA_Dummy+43)

/* Add the name of a device which Workbench should never try to
 * read a disk icon from (STRPTR).
 */
#define	WBCTRLA_AddHiddenDeviceName	(WBA_Dummy+44)

/* Remove a name from list of hidden devices (STRPTR). */
#define	WBCTRLA_RemoveHiddenDeviceName	(WBA_Dummy+45)

/* Get the number of seconds that have to pass before typing
 * the next character in a drawer window will restart
 * with a new file name (ULONG *).
 */
#define	WBCTRLA_GetTypeRestartTime	(WBA_Dummy+47)

/* Set the number of seconds that have to pass before typing
 * the next character in a drawer window will restart
 * with a new file name (ULONG).
 */
#define	WBCTRLA_SetTypeRestartTime	(WBA_Dummy+48)

/****************************************************************************/

/* Tags for use with AddAppWindowDropZoneA() */

/* Zone left edge (WORD) */
#define WBDZA_Left	(WBA_Dummy+26)

/* Zone left edge, if relative to the right edge of the window (WORD) */
#define WBDZA_RelRight	(WBA_Dummy+27)

/* Zone top edge (WORD) */
#define WBDZA_Top	(WBA_Dummy+28)

/* Zone top edge, if relative to the bottom edge of the window (WORD) */
#define WBDZA_RelBottom	(WBA_Dummy+29)

/* Zone width (WORD) */
#define WBDZA_Width	(WBA_Dummy+30)

/* Zone width, if relative to the window width (WORD) */
#define WBDZA_RelWidth	(WBA_Dummy+31)

/* Zone height (WORD) */
#define WBDZA_Height	(WBA_Dummy+32)

/* Zone height, if relative to the window height (WORD) */
#define WBDZA_RelHeight	(WBA_Dummy+33)

/* Zone position and size (struct IBox *). */
#define WBDZA_Box	(WBA_Dummy+34)

/* Hook to invoke when the mouse enters or leave a drop zone (struct Hook *). */
#define WBDZA_Hook	(WBA_Dummy+35)

/****************************************************************************/

/* Reserved tags; don't use! */
#define	WBA_Reserved1	(WBA_Dummy+40)
#define	WBA_Reserved2	(WBA_Dummy+41)
#define	WBA_Reserved3	(WBA_Dummy+46)
#define	WBA_Reserved4	(WBA_Dummy+49)
#define	WBA_Reserved5	(WBA_Dummy+50)
#define	WBA_Reserved6	(WBA_Dummy+51)
#define	WBA_Reserved7	(WBA_Dummy+52)
#define	WBA_Reserved8	(WBA_Dummy+53)
#define	WBA_Reserved9	(WBA_Dummy+54)
#define	WBA_Reserved10	(WBA_Dummy+55)
#define	WBA_Reserved11	(WBA_Dummy+56)
#define	WBA_Reserved12	(WBA_Dummy+57)
#define	WBA_Reserved13	(WBA_Dummy+58)
#define	WBA_Reserved14	(WBA_Dummy+59)
#define	WBA_Reserved15	(WBA_Dummy+60)
#define	WBA_Reserved16	(WBA_Dummy+61)
#define	WBA_Reserved17	(WBA_Dummy+62)
#define	WBA_Reserved18	(WBA_Dummy+63)
#define	WBA_Reserved19	(WBA_Dummy+64)

/****************************************************************************/

#define	WBA_LAST_TAG (WBA_Dummy+63)

/****************************************************************************/

/* The message your AppIcon rendering hook gets invoked with. */
struct AppIconRenderMsg
{
    struct RastPort *	arm_RastPort;	/* RastPort to render into */
    struct DiskObject *	arm_Icon;	/* The icon to be rendered */
    STRPTR			arm_Label;	/* The icon label txt */
    struct TagItem *	arm_Tags;	/* Further tags to be passed on
                         * to DrawIconStateA().
                         */

    WORD			arm_Left;	/* \ Rendering origin, not taking the */
    WORD			arm_Top;	/* / button border into account. */

    WORD			arm_Width;	/* \ Limit your rendering to */
    WORD			arm_Height;	/* / this area. */

    ULONG			arm_State;	/* IDS_SELECTED, IDS_NORMAL, etc. */
};

/****************************************************************************/

/* The message your drop zone hook gets invoked with. */
struct AppWindowDropZoneMsg
{
    struct RastPort *	adzm_RastPort;		/* RastPort to render into. */
    struct IBox		adzm_DropZoneBox;	/* Limit your rendering to this area. */
    ULONG			adzm_ID;		/* \ These come from straight */
    ULONG			adzm_UserData;		/* / from AddAppWindowDropZoneA(). */
    LONG			adzm_Action;		/* See below for a list of actions. */
};

#define ADZMACTION_Enter	(0)
#define ADZMACTION_Leave	(1)

/****************************************************************************/

/* The message your icon selection change hook is invoked with. */
struct IconSelectMsg
{
    /* Size of this data structure (in bytes). */
    ULONG			ism_Length;

    /* Lock on the drawer this object resides in,
     * NULL for Workbench backdrop (devices).
     */
    BPTR			ism_Drawer;

    /* Name of the object in question. */
    STRPTR			ism_Name;

    /* One of WBDISK, WBDRAWER, WBTOOL, WBPROJECT,
     * WBGARBAGE, WBDEVICE, WBKICK or WBAPPICON.
     */
    UWORD			ism_Type;

    /* TRUE if currently selected, FALSE otherwise. */
    BOOL			ism_Selected;

    /* Pointer to the list of tag items passed to
     * ChangeWorkbenchSelectionA().
     */
    struct TagItem *	ism_Tags;

    /* Pointer to the window attached to this icon,
     * if the icon is a drawer-like object.
     */
    struct Window *		ism_DrawerWindow;

    /* Pointer to the window the icon resides in. */
    struct Window *		ism_ParentWindow;

    /* Position and size of the icon; note that the
     * icon may not entirely reside within the visible
     * bounds of the parent window.
     */
    WORD			ism_Left;
    WORD			ism_Top;
    WORD			ism_Width;
    WORD			ism_Height;
};

/* These are the values your hook code can return. */
#define ISMACTION_Unselect	(0)	/* Unselect the icon */
#define ISMACTION_Select	(1)	/* Select the icon */
#define ISMACTION_Ignore	(2)	/* Do not change the selection state. */
#define ISMACTION_Stop		(3)	/* Do not invoke the hook code again,
                     * leave the icon as it is.
                     */

/****************************************************************************/

#endif  /* !WORKBENCH_WORKBENCH_H */


include/graphics/rastport.h

#ifndef	GRAPHICS_RASTPORT_H
#define	GRAPHICS_RASTPORT_H
/*
**	$VER: rastport.h 39.0 (21.8.1991)
**	Includes Release 44.1
**
**
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef GRAPHICS_GFX_H
#include <graphics/gfx.h>
#endif

struct AreaInfo
{
    WORD   *VctrTbl;	     /* ptr to start of vector table */
    WORD   *VctrPtr;	     /* ptr to current vertex */
    BYTE    *FlagTbl;	      /* ptr to start of vector flag table */
    BYTE    *FlagPtr;	      /* ptrs to areafill flags */
    WORD   Count;	     /* number of vertices in list */
    WORD   MaxCount;	     /* AreaMove/Draw will not allow Count>MaxCount*/
    WORD   FirstX,FirstY;    /* first point for this polygon */
};

struct TmpRas
{
    BYTE *RasPtr;
    LONG Size;
};

/* unoptimized for 32bit alignment of pointers */
struct GelsInfo
{
    BYTE sprRsrvd;	      /* flag of which sprites to reserve from
                 vsprite system */
    UBYTE Flags;	      /* system use */
    struct VSprite *gelHead, *gelTail; /* dummy vSprites for list management*/
    /* pointer to array of 8 WORDS for sprite available lines */
    WORD *nextLine;
    /* pointer to array of 8 pointers for color-last-assigned to vSprites */
    WORD **lastColor;
    struct collTable *collHandler;     /* addresses of collision routines */
    WORD leftmost, rightmost, topmost, bottommost;
   APTR firstBlissObj,lastBlissObj;    /* system use only */
};

struct RastPort
{
    struct  Layer *Layer;
    struct  BitMap   *BitMap;
    UWORD  *AreaPtrn;	     /* ptr to areafill pattern */
    struct  TmpRas *TmpRas;
    struct  AreaInfo *AreaInfo;
    struct  GelsInfo *GelsInfo;
    UBYTE   Mask;	      /* write mask for this raster */
    BYTE    FgPen;	      /* foreground pen for this raster */
    BYTE    BgPen;	      /* background pen  */
    BYTE    AOlPen;	      /* areafill outline pen */
    BYTE    DrawMode;	      /* drawing mode for fill, lines, and text */
    BYTE    AreaPtSz;	      /* 2^n words for areafill pattern */
    BYTE    linpatcnt;	      /* current line drawing pattern preshift */
    BYTE    dummy;
    UWORD  Flags;	     /* miscellaneous control bits */
    UWORD  LinePtrn;	     /* 16 bits for textured lines */
    WORD   cp_x, cp_y;	     /* current pen position */
    UBYTE   minterms[8];
    WORD   PenWidth;
    WORD   PenHeight;
    struct  TextFont *Font;   /* current font address */
    UBYTE   AlgoStyle;	      /* the algorithmically generated style */
    UBYTE   TxFlags;	      /* text specific flags */
    UWORD   TxHeight;	      /* text height */
    UWORD   TxWidth;	      /* text nominal width */
    UWORD   TxBaseline;       /* text baseline */
    WORD    TxSpacing;	      /* text spacing (per character) */
    APTR    *RP_User;
    ULONG   longreserved[2];
#ifndef GFX_RASTPORT_1_2
    UWORD   wordreserved[7];  /* used to be a node */
    UBYTE   reserved[8];      /* for future use */
#endif
};

/* drawing modes */
#define JAM1	    0	      /* jam 1 color into raster */
#define JAM2	    1	      /* jam 2 colors into raster */
#define COMPLEMENT  2	      /* XOR bits into raster */
#define INVERSVID   4	      /* inverse video for drawing modes */

/* these are the flag bits for RastPort flags */
#define FRST_DOT    0x01      /* draw the first dot of this line ? */
#define ONE_DOT     0x02      /* use one dot mode for drawing lines */
#define DBUFFER     0x04      /* flag set when RastPorts
                 are double-buffered */

         /* only used for bobs */

#define AREAOUTLINE 0x08      /* used by areafiller */
#define NOCROSSFILL 0x20      /* areafills have no crossovers */

/* there is only one style of clipping: raster clipping */
/* this preserves the continuity of jaggies regardless of clip window */
/* When drawing into a RastPort, if the ptr to ClipRect is nil then there */
/* is no clipping done, this is dangerous but useful for speed */

#endif	/* GRAPHICS_RASTPORT_H */


include/libraries/aml.h

#ifndef LIBRARIES_AML_H
#define LIBRARIES_AML_H
/*
**	$VER: aml.h 44.1 (19.10.1999)
**	Includes Release 44.1
**
**	AML library structures and constants
**
**	(C) Copyright 1999 Amiga, Inc.
**	    All Rights Reserved
*/

/*****************************************************************************/

#ifndef	EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef	EXEC_NODES_H
#include <exec/nodes.h>
#endif

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

/*****************************************************************************/

#define	AmlName "aml.library"
#define AML_TB	(TAG_USER+0x80000)

/*****************************************************************************/

/* Server Attribute Tags
 */
#define SERVERA_Dummy 		(TAG_USER+0x100)
#define SERVERA_HostName	(SERVERA_Dummy+0)
#define SERVERA_HostPort	(SERVERA_Dummy+1)
#define SERVERA_Directory	(SERVERA_Dummy+2)
#define SERVERA_UserName	(SERVERA_Dummy+3)
#define SERVERA_PassWord	(SERVERA_Dummy+4)
#define SERVERA_Type		(SERVERA_Dummy+5)
#define SERVERA_Flags		(SERVERA_Dummy+6)
#define SERVERA_Socket		(SERVERA_Dummy+7)
#define SERVERA_UserData	(SERVERA_Dummy+8)
#define SERVERA_ProgressHook	(SERVERA_Dummy+9)
#define SERVERA_SpoolFile	(SERVERA_Dummy+10)
#define SERVERA_NewsGroup	(SERVERA_Dummy+11)
#define SERVERA_LogFile		(SERVERA_Dummy+12)
#define SERVERA_MaxSize		(SERVERA_Dummy+13)
#define SERVERA_MaxLines	(SERVERA_Dummy+14)
#define SERVERA_MaxWarning	(SERVERA_Dummy+15)

/* Values for SERVERA_Type
 */
#define SVRTYPE_SMTP	(0)	/* sending data via smtp */
#define SVRTYPE_POP3	(1)	/* pop retrieval and local folders */
#define SVRTYPE_IMAP	(2)	/* unsupported */
#define SVRTYPE_NNTP	(3)	/* unsupported */
#define SVRTYPE_LDAP	(4)	/* unsupported */
#define SVRTYPE_FILE	(5)	/* For address/file "servers" */

/* Structure used for progress callbacks.
 */
struct ServerProgressData
{
    ULONG spd_Type;
    ULONG spd_Action;
    ULONG spd_Flags;

    /* X of Y progress */
    ULONG spd_Current;
    ULONG spd_Total;

    /* (sub) progress on each of X thru Y */
    ULONG spd_CSize;
    ULONG spd_TSize;
};

/* Values for spd_Type
 */
#define SPDT_SERVER	(0)
#define SPDT_FOLDER	(1)
#define SPDT_ARTICLE	(2)
#define SPDT_PART	(3)
#define SPDT_ADDRESS	(4)
#define SPDT_DECODER	(5)

/* Values for spd_Action
 */
#define SPDA_ERROR	(~0)
#define SPDA_NONE	(0)
#define SPDA_SCANINDEX	(1)
#define SPDA_EDITINDEX	(2)
#define SPDA_DELETE	(3)
#define SPDA_PARSING	(4)
#define SPDA_POPGET	(5)
#define SPDA_SMTPSEND	(6)
#define SPDA_DECODING	(7)
#define SPDA_CONNECT	(8)
#define SPDA_DISCONNECT	(9)
#define SPDA_SENDPASS	(10)
#define SPDA_SENDUSER	(11)

/* Flags for spd_Flags
 */
#define SPDF_INITIAL	(1 << 0)
#define SPDF_UPDATE	(1 << 1)
#define SPDF_END	(1 << 2)
#define SPDF_STATUS	(1 << 3)

/* Structure for article retrieval folder routing callback.
 */
struct ArticleDisposition
{
    APTR  ad_Article;
    APTR  ad_Folder;
    ULONG ad_MsgSize;
    ULONG ad_MsgNumber;
    ULONG ad_MsgTotal;
};

/* Flags for GetServerArticles()
 */
#define GSAF_DELETE	(1)
#define GSAF_SPOOL	(2)
#define GSAF_STATUS	(4)

/*****************************************************************************/

/* Folder Attribute Tags
 */
#define FOLDERA_Dummy 		(TAG_USER+0x200)
#define FOLDERA_Path		(FOLDERA_Dummy+0)
#define FOLDERA_Name		(FOLDERA_Dummy+1)
#define FOLDERA_DefaultName	(FOLDERA_Dummy+2)
#define FOLDERA_SpoolFile	(FOLDERA_Dummy+3)
#define FOLDERA_MsgCount	(FOLDERA_Dummy+4)
#define FOLDERA_Flags		(FOLDERA_Dummy+5)
#define FOLDERA_Accessed	(FOLDERA_Dummy+6)
#define FOLDERA_Created		(FOLDERA_Dummy+7)
#define FOLDERA_UserData	(FOLDERA_Dummy+8)
#define FOLDERA_FirstMsgID	(FOLDERA_Dummy+9)
#define FOLDERA_LastMsgID	(FOLDERA_Dummy+10)
#define FOLDERA_LastRead	(FOLDERA_Dummy+11)
#define FOLDERA_NumRead		(FOLDERA_Dummy+12)

/* Values for FOLDERA_DefaultName
 */
#define FOLDER_DEF_INBOX	(0)
#define FOLDER_DEF_OUTBOX	(1)
#define FOLDER_DEF_TRASH	(2)
#define FOLDER_DEF_DRAFTS	(3)
#define FOLDER_DEF_SAVED	(4)
#define FOLDER_DEF_SPOOL	(5)

/* Folder indexing public data structure.
 */
struct FolderIndex
{
    ULONG fi_Number;
    ULONG fi_Status;
    ULONG fi_Size;
    ULONG fi_Date;
    UBYTE fi_From[64];
    UBYTE fi_To[64];
    UBYTE fi_Subject[128];
};

/* Flags for FolderIndex.fi_Status and ARTICLEA_Status
 */
#define STATUS_UNREAD	(1L << 1)
#define STATUS_REPLIED	(1L << 2)
#define STATUS_EDITED	(1L << 3)
#define STATUS_FORWARD	(1L << 4)
#define STATUS_DELETED	(1L << 5)
#define STATUS_SAVED	(1L << 6)
#define STATUS_NEW	(1L << 7)
#define STATUS_MARKED	(1L << 8)
#define STATUS_MUNREAD	(1L << 9)
#define STATUS_UUCODE	(1L << 10)
#define STATUS_SECURE	(1L << 11)
#define STATUS_AUTH	(1L << 12)
#define STATUS_BOUNCED	(1L << 13)

/* Field Identifiers for SortFolderIndex()
 */
#define FIELD_NUMBER    0
#define FIELD_TO        1
#define FIELD_SUBJECT   2
#define FIELD_FROM      3
#define FIELD_SIZE      4
#define FIELD_DATE      5
#define FIELD_THREAD    6

/*****************************************************************************/

/* Article Attribute Tags
 */
#define ARTICLEA_Dummy 			(TAG_USER+0x300)
#define ARTICLEA_To			(ARTICLEA_Dummy+0)
#define ARTICLEA_Cc			(ARTICLEA_Dummy+1)
#define ARTICLEA_Bcc			(ARTICLEA_Dummy+2)
#define ARTICLEA_From			(ARTICLEA_Dummy+3)
#define ARTICLEA_ReplyTo		(ARTICLEA_Dummy+4)
#define ARTICLEA_Date			(ARTICLEA_Dummy+5)
#define ARTICLEA_DateVal		(ARTICLEA_Dummy+6)
#define ARTICLEA_Subject		(ARTICLEA_Dummy+7)
#define ARTICLEA_ContentEncoding	(ARTICLEA_Dummy+8)
#define ARTICLEA_ContentType		(ARTICLEA_Dummy+9)
#define ARTICLEA_ContentSubType		(ARTICLEA_Dummy+10)
#define ARTICLEA_ContentTypeParams	(ARTICLEA_Dummy+11)
#define ARTICLEA_Flags			(ARTICLEA_Dummy+12)
#define ARTICLEA_Status			ARTICLEA_Flags
#define ARTICLEA_XFace			(ARTICLEA_Dummy+13)
#define ARTICLEA_MessageID		(ARTICLEA_Dummy+14)
#define ARTICLEA_Reference		(ARTICLEA_Dummy+15)
#define ARTICLEA_Groups			(ARTICLEA_Dummy+16) /* NNTP NEWS ONLY */
#define ARTICLEA_UserData		(ARTICLEA_Dummy+17)
#define ARTICLEA_ReturnReceipt		(ARTICLEA_Dummy+18)
#define ARTICLEA_SigFile		(ARTICLEA_Dummy+19)
#define ARTICLEA_CustomHeaders		(ARTICLEA_Dummy+20)
#define ARTICLEA_NumParts		(ARTICLEA_Dummy+21)
#define ARTICLEA_Organization		(ARTICLEA_Dummy+22)
#define ARTICLEA_Number			(ARTICLEA_Dummy+23)

#define PARTA_Name			(ARTICLEA_Dummy+50)
#define PARTA_ContentType		(ARTICLEA_Dummy+51)
#define PARTA_ContentSubType		(ARTICLEA_Dummy+52)
#define PARTA_ContentTypeParams		(ARTICLEA_Dummy+53)
#define PARTA_Flags			(ARTICLEA_Dummy+54)
#define PARTA_ContentEncoding		(ARTICLEA_Dummy+55)
#define PARTA_DataFilename		(ARTICLEA_Dummy+56)
#define PARTA_DataFile			(ARTICLEA_Dummy+57)
#define PARTA_DataString		(ARTICLEA_Dummy+58)
#define PARTA_DataBuffer		(ARTICLEA_Dummy+59)
#define PARTA_DataLength		(ARTICLEA_Dummy+60)
#define PARTA_ContentDesc		(ARTICLEA_Dummy+61)

/* Values for AddFolderArticle(..., type, ...);
 */
#define ARTICLE_TYPE_FILE	(0)
#define ARTICLE_TYPE_ARTICLE	(1)
#define ARTICLE_TYPE_BUFFER	(2)

/*****************************************************************************/

/* Address Attribute Tags
 */
#define ADDRESSA_Dummy 			(TAG_USER+0x400)
#define ADDRESSA_Name			(ADDRESSA_Dummy+0)
#define ADDRESSA_Address		(ADDRESSA_Dummy+1)
#define ADDRESSA_City			(ADDRESSA_Dummy+2)
#define ADDRESSA_State			(ADDRESSA_Dummy+3)
#define ADDRESSA_Zip			(ADDRESSA_Dummy+4)
#define ADDRESSA_Country		(ADDRESSA_Dummy+5)
#define ADDRESSA_Phone			(ADDRESSA_Dummy+6)
#define ADDRESSA_Fax			(ADDRESSA_Dummy+7)
#define ADDRESSA_Comments		(ADDRESSA_Dummy+8)
#define ADDRESSA_Group			(ADDRESSA_Dummy+9)
#define ADDRESSA_Flags			(ADDRESSA_Dummy+10)
#define ADDRESSA_URL			(ADDRESSA_Dummy+11)
#define ADDRESSA_EMail			(ADDRESSA_Dummy+12)
#define ADDRESSA_UserData		(ADDRESSA_Dummy+13)
#define ADDRESSA_PartialMatch		(ADDRESSA_Dummy+14)
#define ADDRESSA_ICQ			(ADDRESSA_Dummy+15)
#define ADDRESSA_FTP			(ADDRESSA_Dummy+16)
#define ADDRESSA_Company		(ADDRESSA_Dummy+17)
#define ADDRESSA_JobTitle		(ADDRESSA_Dummy+18)
#define ADDRESSA_MobilePhone		(ADDRESSA_Dummy+19)
#define ADDRESSA_ImageFile		(ADDRESSA_Dummy+20)
#define ADDRESSA_EntryType		(ADDRESSA_Dummy+21)
#define ADDRESSA_EntryID		(ADDRESSA_Dummy+22)
#define ADDRESSA_EntryGeneration	(ADDRESSA_Dummy+23)

/* ADDRESSA_EntryType (defaults to ENTRY_USER)
 */
#define ENTRY_USER	(1)
#define ENTRY_WWW	(2)
#define ENTRY_FTP	(3)
#define ENTRY_CHAT	(4)
#define ENTRY_GROUP	(5)

/*****************************************************************************/

/* Decoder tags
 */
#define DECODERA_Dummy		(TAG_USER+0x500)
#define DECODERA_SourceFile	(DECODERA_Dummy+1)
#define DECODERA_SourceHandle	(DECODERA_Dummy+3)
#define DECODERA_SourceBuffer	(DECODERA_Dummy+5)
#define DECODERA_SourceLen	(DECODERA_Dummy+7)
#define DECODERA_DestFile	(DECODERA_Dummy+2)
#define DECODERA_DestHandle	(DECODERA_Dummy+4)
#define DECODERA_DestBuffer	(DECODERA_Dummy+6)
#define DECODERA_DestLen	(DECODERA_Dummy+8)
#define DECODERA_Lines		(DECODERA_Dummy+9)
#define DECODERA_Flags		(DECODERA_Dummy+10)
#define DECODERA_Boundary	(DECODERA_Dummy+11)

/* Values for DECODERA_Flags
 */
#define DECF_USEBOUNDARY	(1L << 0)

/* En/decoding type values.
 */
#define DECODE_ERROR	(-1)
#define DECODE_COPY	(0)
#define DECODE_QP	(1)
#define DECODE_B64	(2)
#define DECODE_UU	(3)
#define DECODE_HEX	(6)
#define DECODE_ROT	(7)

#define ENCODE_ERROR	(-1)
#define ENCODE_COPY	(0)
#define ENCODE_QP	(1)
#define ENCODE_B64	(2)
#define ENCODE_UU	(3)
#define ENCODE_8BIT	(4)
#define ENCODE_7BIT	(5)
#define ENCODE_HEX	(6)
#define ENCODE_ROT	(7)

/*****************************************************************************/

#endif /* LIBRARIES_AML_H */


include/dos/dosextens.h

#ifndef DOS_DOSEXTENS_H
#define DOS_DOSEXTENS_H
/*
**	$VER: dosextens.h 36.41 (14.5.1992)
**	Includes Release 44.1
**
**	DOS structures not needed for the casual AmigaDOS user
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TASKS_H
#include <exec/tasks.h>
#endif
#ifndef EXEC_PORTS_H
#include <exec/ports.h>
#endif
#ifndef EXEC_LIBRARIES_H
#include <exec/libraries.h>
#endif
#ifndef EXEC_SEMAPHORES_H
#include <exec/semaphores.h>
#endif
#ifndef DEVICES_TIMER_H
#include <devices/timer.h>
#endif

#ifndef DOS_DOS_H
#include <dos/dos.h>
#endif

/* All DOS processes have this structure */
/* Create and Device Proc returns pointer to the MsgPort in this structure */
/* dev_proc = (struct Process *) (DeviceProc(..) - sizeof(struct Task)); */

struct Process {
    struct  Task    pr_Task;
    struct  MsgPort pr_MsgPort; /* This is BPTR address from DOS functions  */
    WORD    pr_Pad;		/* Remaining variables on 4 byte boundaries */
    BPTR    pr_SegList;		/* Array of seg lists used by this process  */
    LONG    pr_StackSize;	/* Size of process stack in bytes	    */
    APTR    pr_GlobVec;		/* Global vector for this process (BCPL)    */
    LONG    pr_TaskNum;		/* CLI task number of zero if not a CLI	    */
    BPTR    pr_StackBase;	/* Ptr to high memory end of process stack  */
    LONG    pr_Result2;		/* Value of secondary result from last call */
    BPTR    pr_CurrentDir;	/* Lock associated with current directory   */
    BPTR    pr_CIS;		/* Current CLI Input Stream		    */
    BPTR    pr_COS;		/* Current CLI Output Stream		    */
    APTR    pr_ConsoleTask;	/* Console handler process for current window*/
    APTR    pr_FileSystemTask;	/* File handler process for current drive   */
    BPTR    pr_CLI;		/* pointer to CommandLineInterface	    */
    APTR    pr_ReturnAddr;	/* pointer to previous stack frame	    */
    APTR    pr_PktWait;		/* Function to be called when awaiting msg  */
    APTR    pr_WindowPtr;	/* Window for error printing		    */

    /* following definitions are new with 2.0 */
    BPTR    pr_HomeDir;		/* Home directory of executing program	    */
    LONG    pr_Flags;		/* flags telling dos about process	    */
    void    (*pr_ExitCode)();	/* code to call on exit of program or NULL  */
    LONG    pr_ExitData;	/* Passed as an argument to pr_ExitCode.    */
    UBYTE   *pr_Arguments;	/* Arguments passed to the process at start */
    struct MinList pr_LocalVars; /* Local environment variables		    */
    ULONG   pr_ShellPrivate;	/* for the use of the current shell	    */
    BPTR    pr_CES;		/* Error stream - if NULL, use pr_COS	    */
};  /* Process */

/*
 * Flags for pr_Flags
 */
#define	PRB_FREESEGLIST		0
#define	PRF_FREESEGLIST		1
#define	PRB_FREECURRDIR		1
#define	PRF_FREECURRDIR		2
#define	PRB_FREECLI		2
#define	PRF_FREECLI		4
#define	PRB_CLOSEINPUT		3
#define	PRF_CLOSEINPUT		8
#define	PRB_CLOSEOUTPUT		4
#define	PRF_CLOSEOUTPUT		16
#define	PRB_FREEARGS		5
#define	PRF_FREEARGS		32

/* The long word address (BPTR) of this structure is returned by
 * Open() and other routines that return a file.  You need only worry
 * about this struct to do async io's via PutMsg() instead of
 * standard file system calls */

struct FileHandle {
   struct Message *fh_Link;	 /* EXEC message	      */
   struct MsgPort *fh_Port;	 /* Reply port for the packet */
   struct MsgPort *fh_Type;	 /* Port to do PutMsg() to
                  * Address is negative if a plain file */
   LONG fh_Buf;
   LONG fh_Pos;
   LONG fh_End;
   LONG fh_Funcs;
#define fh_Func1 fh_Funcs
   LONG fh_Func2;
   LONG fh_Func3;
   LONG fh_Args;
#define fh_Arg1 fh_Args
   LONG fh_Arg2;
}; /* FileHandle */

/* This is the extension to EXEC Messages used by DOS */

struct DosPacket {
   struct Message *dp_Link;	 /* EXEC message	      */
   struct MsgPort *dp_Port;	 /* Reply port for the packet */
                 /* Must be filled in each send. */
   LONG dp_Type;		 /* See ACTION_... below and
                  * 'R' means Read, 'W' means Write to the
                  * file system */
   LONG dp_Res1;		 /* For file system calls this is the result
                  * that would have been returned by the
                  * function, e.g. Write ('W') returns actual
                  * length written */
   LONG dp_Res2;		 /* For file system calls this is what would
                  * have been returned by IoErr() */
/*  Device packets common equivalents */
#define dp_Action  dp_Type
#define dp_Status  dp_Res1
#define dp_Status2 dp_Res2
#define dp_BufAddr dp_Arg1
   LONG dp_Arg1;
   LONG dp_Arg2;
   LONG dp_Arg3;
   LONG dp_Arg4;
   LONG dp_Arg5;
   LONG dp_Arg6;
   LONG dp_Arg7;
}; /* DosPacket */

/* A Packet does not require the Message to be before it in memory, but
 * for convenience it is useful to associate the two.
 * Also see the function init_std_pkt for initializing this structure */

struct StandardPacket {
   struct Message   sp_Msg;
   struct DosPacket sp_Pkt;
}; /* StandardPacket */

/* Packet types */
#define ACTION_NIL		0
#define ACTION_STARTUP		0
#define ACTION_GET_BLOCK	2	/* OBSOLETE */
#define ACTION_SET_MAP		4
#define ACTION_DIE		5
#define ACTION_EVENT		6
#define ACTION_CURRENT_VOLUME	7
#define ACTION_LOCATE_OBJECT	8
#define ACTION_RENAME_DISK	9
#define ACTION_WRITE		'W'
#define ACTION_READ		'R'
#define ACTION_FREE_LOCK	15
#define ACTION_DELETE_OBJECT	16
#define ACTION_RENAME_OBJECT	17
#define ACTION_MORE_CACHE	18
#define ACTION_COPY_DIR		19
#define ACTION_WAIT_CHAR	20
#define ACTION_SET_PROTECT	21
#define ACTION_CREATE_DIR	22
#define ACTION_EXAMINE_OBJECT	23
#define ACTION_EXAMINE_NEXT	24
#define ACTION_DISK_INFO	25
#define ACTION_INFO		26
#define ACTION_FLUSH		27
#define ACTION_SET_COMMENT	28
#define ACTION_PARENT		29
#define ACTION_TIMER		30
#define ACTION_INHIBIT		31
#define ACTION_DISK_TYPE	32
#define ACTION_DISK_CHANGE	33
#define ACTION_SET_DATE		34

#define ACTION_SCREEN_MODE	994

#define ACTION_READ_RETURN	1001
#define ACTION_WRITE_RETURN	1002
#define ACTION_SEEK		1008
#define ACTION_FINDUPDATE	1004
#define ACTION_FINDINPUT	1005
#define ACTION_FINDOUTPUT	1006
#define ACTION_END		1007
#define ACTION_SET_FILE_SIZE	1022	/* fast file system only in 1.3 */
#define ACTION_WRITE_PROTECT	1023	/* fast file system only in 1.3 */

/* new 2.0 packets */
#define ACTION_SAME_LOCK	40
#define ACTION_CHANGE_SIGNAL	995
#define ACTION_FORMAT		1020
#define ACTION_MAKE_LINK	1021
/**/
/**/
#define ACTION_READ_LINK	1024
#define ACTION_FH_FROM_LOCK	1026
#define ACTION_IS_FILESYSTEM	1027
#define ACTION_CHANGE_MODE	1028
/**/
#define ACTION_COPY_DIR_FH	1030
#define ACTION_PARENT_FH	1031
#define ACTION_EXAMINE_ALL	1033
#define ACTION_EXAMINE_FH	1034

#define ACTION_LOCK_RECORD	2008
#define ACTION_FREE_RECORD	2009

#define ACTION_ADD_NOTIFY	4097
#define ACTION_REMOVE_NOTIFY	4098

/* Added in V39: */
#define ACTION_EXAMINE_ALL_END	1035
#define ACTION_SET_OWNER	1036

/* Tell a file system to serialize the current volume. This is typically
 * done by changing the creation date of the disk. This packet does not take
 * any arguments.  NOTE: be prepared to handle failure of this packet for
 * V37 ROM filesystems.
 */
#define	ACTION_SERIALIZE_DISK	4200

/*
 * A structure for holding error messages - stored as array with error == 0
 * for the last entry.
 */
struct ErrorString {
    LONG  *estr_Nums;
    UBYTE *estr_Strings;
};

/* DOS library node structure.
 * This is the data at positive offsets from the library node.
 * Negative offsets from the node is the jump table to DOS functions
 * node = (struct DosLibrary *) OpenLibrary( "dos.library" .. )	     */

struct DosLibrary {
    struct Library dl_lib;
    struct RootNode *dl_Root; /* Pointer to RootNode, described below */
    APTR    dl_GV;	      /* Pointer to BCPL global vector	      */
    LONG    dl_A2;	      /* BCPL standard register values	      */
    LONG    dl_A5;
    LONG    dl_A6;
    struct ErrorString *dl_Errors;	  /* PRIVATE pointer to array of error msgs */
    struct timerequest *dl_TimeReq;	  /* PRIVATE pointer to timer request */
    struct Library     *dl_UtilityBase;   /* PRIVATE ptr to utility library */
    struct Library     *dl_IntuitionBase; /* PRIVATE ptr to intuition library */
};  /*	DosLibrary */

/*			       */

struct RootNode {
    BPTR    rn_TaskArray;	     /* [0] is max number of CLI's
                      * [1] is APTR to process id of CLI 1
                      * [n] is APTR to process id of CLI n */
    BPTR    rn_ConsoleSegment; /* SegList for the CLI			   */
    struct  DateStamp rn_Time; /* Current time				   */
    LONG    rn_RestartSeg;     /* SegList for the disk validator process   */
    BPTR    rn_Info;	       /* Pointer to the Info structure		   */
    BPTR    rn_FileHandlerSegment; /* segment for a file handler	   */
    struct MinList rn_CliList; /* new list of all CLI processes */
                   /* the first cpl_Array is also rn_TaskArray */
    struct MsgPort *rn_BootProc; /* private ptr to msgport of boot fs	   */
    BPTR    rn_ShellSegment;   /* seglist for Shell (for NewShell)	   */
    LONG    rn_Flags;	       /* dos flags */
};  /* RootNode */

#define RNB_WILDSTAR	24
#define RNF_WILDSTAR	(1L<<24)
#define RNB_PRIVATE1	1	/* private for dos */
#define RNF_PRIVATE1	2

/* ONLY to be allocated by DOS! */
struct CliProcList {
    struct MinNode cpl_Node;
    LONG cpl_First;	     /* number of first entry in array */
    struct MsgPort **cpl_Array;
                 /* [0] is max number of CLI's in this entry (n)
                  * [1] is CPTR to process id of CLI cpl_First
                  * [n] is CPTR to process id of CLI cpl_First+n-1
                  */
};

struct DosInfo {
    BPTR    di_McName;	       /* PRIVATE: system resident module list	    */
#define di_ResList di_McName
    BPTR    di_DevInfo;	       /* Device List				    */
    BPTR    di_Devices;	       /* Currently zero			    */
    BPTR    di_Handlers;       /* Currently zero			    */
    APTR    di_NetHand;	       /* Network handler processid; currently zero */
    struct  SignalSemaphore di_DevLock;	   /* do NOT access directly! */
    struct  SignalSemaphore di_EntryLock;  /* do NOT access directly! */
    struct  SignalSemaphore di_DeleteLock; /* do NOT access directly! */
};  /* DosInfo */

/* structure for the Dos resident list.  Do NOT allocate these, use	  */
/* AddSegment(), and heed the warnings in the autodocs!			  */

struct Segment {
    BPTR seg_Next;
    LONG seg_UC;
    BPTR seg_Seg;
    UBYTE seg_Name[4];	/* actually the first 4 chars of BSTR name */
};

#define CMD_SYSTEM	-1
#define CMD_INTERNAL	-2
#define CMD_DISABLED	-999

/* DOS Processes started from the CLI via RUN or NEWCLI have this additional
 * set to data associated with them */

struct CommandLineInterface {
    LONG   cli_Result2;	       /* Value of IoErr from last command	  */
    BSTR   cli_SetName;	       /* Name of current directory		  */
    BPTR   cli_CommandDir;     /* Head of the path locklist		  */
    LONG   cli_ReturnCode;     /* Return code from last command		  */
    BSTR   cli_CommandName;    /* Name of current command		  */
    LONG   cli_FailLevel;      /* Fail level (set by FAILAT)		  */
    BSTR   cli_Prompt;	       /* Current prompt (set by PROMPT)	  */
    BPTR   cli_StandardInput;  /* Default (terminal) CLI input		  */
    BPTR   cli_CurrentInput;   /* Current CLI input			  */
    BSTR   cli_CommandFile;    /* Name of EXECUTE command file		  */
    LONG   cli_Interactive;    /* Boolean; True if prompts required	  */
    LONG   cli_Background;     /* Boolean; True if CLI created by RUN	  */
    BPTR   cli_CurrentOutput;  /* Current CLI output			  */
    LONG   cli_DefaultStack;   /* Stack size to be obtained in long words */
    BPTR   cli_StandardOutput; /* Default (terminal) CLI output		  */
    BPTR   cli_Module;	       /* SegList of currently loaded command	  */
};  /* CommandLineInterface */

/* This structure can take on different values depending on whether it is
 * a device, an assigned directory, or a volume.  Below is the structure
 * reflecting volumes only.  Following that is the structure representing
 * only devices. Following that is the unioned structure representing all
 * the values
 */

/* structure representing a volume */

struct DeviceList {
    BPTR		dl_Next;	/* bptr to next device list */
    LONG		dl_Type;	/* see DLT below */
    struct MsgPort *	dl_Task;	/* ptr to handler task */
    BPTR		dl_Lock;	/* not for volumes */
    struct DateStamp	dl_VolumeDate;	/* creation date */
    BPTR		dl_LockList;	/* outstanding locks */
    LONG		dl_DiskType;	/* 'DOS', etc */
    LONG		dl_unused;
    BSTR		dl_Name;	/* bptr to bcpl name */
};

/* device structure (same as the DeviceNode structure in filehandler.h) */

struct	      DevInfo {
    BPTR  dvi_Next;
    LONG  dvi_Type;
    APTR  dvi_Task;
    BPTR  dvi_Lock;
    BSTR  dvi_Handler;
    LONG  dvi_StackSize;
    LONG  dvi_Priority;
    LONG  dvi_Startup;
    BPTR  dvi_SegList;
    BPTR  dvi_GlobVec;
    BSTR  dvi_Name;
};

/* combined structure for devices, assigned directories, volumes */

struct DosList {
    BPTR		dol_Next;	 /* bptr to next device on list */
    LONG		dol_Type;	 /* see DLT below */
    struct MsgPort     *dol_Task;	 /* ptr to handler task */
    BPTR		dol_Lock;
    union {
    struct {
    BSTR	dol_Handler;	/* file name to load if seglist is null */
    LONG	dol_StackSize;	/* stacksize to use when starting process */
    LONG	dol_Priority;	/* task priority when starting process */
    ULONG	dol_Startup;	/* startup msg: FileSysStartupMsg for disks */
    BPTR	dol_SegList;	/* already loaded code for new task */
    BPTR	dol_GlobVec;	/* BCPL global vector to use when starting
                 * a process. -1 indicates a C/Assembler
                 * program. */
    } dol_handler;

    struct {
    struct DateStamp	dol_VolumeDate;	 /* creation date */
    BPTR			dol_LockList;	 /* outstanding locks */
    LONG			dol_DiskType;	 /* 'DOS', etc */
    } dol_volume;

    struct {
    UBYTE	*dol_AssignName;     /* name for non-or-late-binding assign */
    struct AssignList *dol_List; /* for multi-directory assigns (regular) */
    } dol_assign;

    } dol_misc;

    BSTR		dol_Name;	 /* bptr to bcpl name */
    };

/* structure used for multi-directory assigns. AllocVec()ed. */

struct AssignList {
    struct AssignList *al_Next;
    BPTR		   al_Lock;
};

/* definitions for dl_Type */
#define DLT_DEVICE	0
#define DLT_DIRECTORY	1	/* assign */
#define DLT_VOLUME	2
#define DLT_LATE	3	/* late-binding assign */
#define DLT_NONBINDING	4	/* non-binding assign */
#define DLT_PRIVATE	-1	/* for internal use only */

/* structure return by GetDeviceProc() */
struct DevProc {
    struct MsgPort *dvp_Port;
    BPTR		dvp_Lock;
    ULONG		dvp_Flags;
    struct DosList *dvp_DevNode;	/* DON'T TOUCH OR USE! */
};

/* definitions for dvp_Flags */
#define DVPB_UNLOCK	0
#define DVPF_UNLOCK	(1L << DVPB_UNLOCK)	/* PRIVATE! */
#define DVPB_ASSIGN	1
#define DVPF_ASSIGN	(1L << DVPB_ASSIGN)

/* Flags to be passed to LockDosList(), etc */
#define LDB_DEVICES	2
#define LDF_DEVICES	(1L << LDB_DEVICES)
#define LDB_VOLUMES	3
#define LDF_VOLUMES	(1L << LDB_VOLUMES)
#define LDB_ASSIGNS	4
#define LDF_ASSIGNS	(1L << LDB_ASSIGNS)
#define LDB_ENTRY	5
#define LDF_ENTRY	(1L << LDB_ENTRY)
#define LDB_DELETE	6
#define LDF_DELETE	(1L << LDB_DELETE)

/* you MUST specify one of LDF_READ or LDF_WRITE */
#define LDB_READ	0
#define LDF_READ	(1L << LDB_READ)
#define LDB_WRITE	1
#define LDF_WRITE	(1L << LDB_WRITE)

/* actually all but LDF_ENTRY (which is used for internal locking) */
#define LDF_ALL		(LDF_DEVICES|LDF_VOLUMES|LDF_ASSIGNS)

/* a lock structure, as returned by Lock() or DupLock() */
struct FileLock {
    BPTR		fl_Link;	/* bcpl pointer to next lock */
    LONG		fl_Key;		/* disk block number */
    LONG		fl_Access;	/* exclusive or shared */
    struct MsgPort *	fl_Task;	/* handler task's port */
    BPTR		fl_Volume;	/* bptr to DLT_VOLUME DosList entry */
};

/* error report types for ErrorReport() */
#define REPORT_STREAM		0	/* a stream */
#define REPORT_TASK		1	/* a process - unused */
#define REPORT_LOCK		2	/* a lock */
#define REPORT_VOLUME		3	/* a volume node */
#define REPORT_INSERT		4	/* please insert volume */

/* Special error codes for ErrorReport() */
#define ABORT_DISK_ERROR	296	/* Read/write error */
#define ABORT_BUSY		288	/* You MUST replace... */

/* types for initial packets to shells from run/newcli/execute/system. */
/* For shell-writers only */
#define RUN_EXECUTE		-1
#define RUN_SYSTEM		-2
#define RUN_SYSTEM_ASYNCH	-3

/* Types for fib_DirEntryType.	NOTE that both USERDIR and ROOT are	 */
/* directories, and that directory/file checks should use <0 and >=0.	 */
/* This is not necessarily exhaustive!	Some handlers may use other	 */
/* values as needed, though <0 and >=0 should remain as supported as	 */
/* possible.								 */
#define ST_ROOT		1
#define ST_USERDIR	2
#define ST_SOFTLINK	3	/* looks like dir, but may point to a file! */
#define ST_LINKDIR	4	/* hard link to dir */
#define ST_FILE		-3	/* must be negative for FIB! */
#define ST_LINKFILE	-4	/* hard link to file */
#define ST_PIPEFILE	-5	/* for pipes that support ExamineFH */

#endif	/* DOS_DOSEXTENS_H */


include/diskfont/diskfont.h

#ifndef	DISKFONT_DISKFONT_H
#define	DISKFONT_DISKFONT_H
/*
**	$VER: diskfont.h 38.0 (18.6.1992)
**	Includes Release 44.1
**
**	diskfont library definitions
**
**	(C) Copyright 1990 Robert R. Burns
**	    All Rights Reserved
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef     EXEC_NODES_H
#include <exec/nodes.h>
#endif
#ifndef     EXEC_LISTS_H
#include <exec/lists.h>
#endif
#ifndef     GRAPHICS_TEXT_H
#include <graphics/text.h>
#endif

#define     MAXFONTPATH 256   /* including null terminator */

struct FontContents {
    char    fc_FileName[MAXFONTPATH];
    UWORD   fc_YSize;
    UBYTE   fc_Style;
    UBYTE   fc_Flags;
};

struct TFontContents {
    char    tfc_FileName[MAXFONTPATH-2];
    UWORD   tfc_TagCount;	/* including the TAG_DONE tag */
    /*
     *	if tfc_TagCount is non-zero, tfc_FileName is overlayed with
     *	Text Tags starting at:	(struct TagItem *)
     *	    &tfc_FileName[MAXFONTPATH-(tfc_TagCount*sizeof(struct TagItem))]
     */
    UWORD   tfc_YSize;
    UBYTE   tfc_Style;
    UBYTE   tfc_Flags;
};

#define  FCH_ID		0x0f00	/* FontContentsHeader, then FontContents */
#define  TFCH_ID	0x0f02	/* FontContentsHeader, then TFontContents */
#define  OFCH_ID	0x0f03	/* FontContentsHeader, then TFontContents,
                 * associated with outline font */

struct FontContentsHeader {
    UWORD   fch_FileID;		/* FCH_ID */
    UWORD   fch_NumEntries;	/* the number of FontContents elements */
    /* struct FontContents fch_FC[], or struct TFontContents fch_TFC[]; */
};

#define  DFH_ID		0x0f80
#define  MAXFONTNAME	32	/* font name including ".font\0" */

struct DiskFontHeader {
    /* the following 8 bytes are not actually considered a part of the	*/
    /* DiskFontHeader, but immediately preceed it. The NextSegment is	*/
    /* supplied by the linker/loader, and the ReturnCode is the code	*/
    /* at the beginning of the font in case someone runs it...		*/
    /*	 ULONG dfh_NextSegment;			\* actually a BPTR	*/
    /*	 ULONG dfh_ReturnCode;			\* MOVEQ #0,D0 : RTS	*/
    /* here then is the official start of the DiskFontHeader...		*/
    struct Node dfh_DF;		/* node to link disk fonts */
    UWORD   dfh_FileID;		/* DFH_ID */
    UWORD   dfh_Revision;	/* the font revision */
    LONG    dfh_Segment;	/* the segment address when loaded */
    char    dfh_Name[MAXFONTNAME]; /* the font name (null terminated) */
    struct TextFont dfh_TF;	/* loaded TextFont structure */
};

/* unfortunately, this needs to be explicitly typed */
/* used only if dfh_TF.tf_Style FSB_TAGGED bit is set */
#define	dfh_TagList	dfh_Segment	/* destroyed during loading */

#define     AFB_MEMORY	0
#define     AFF_MEMORY	0x0001
#define     AFB_DISK	1
#define     AFF_DISK	0x0002
#define     AFB_SCALED	2
#define     AFF_SCALED	0x0004
#define     AFB_BITMAP	3
#define     AFF_BITMAP	0x0008

#define     AFB_TAGGED	16	/* return TAvailFonts */
#define     AFF_TAGGED	0x10000L

struct AvailFonts {
    UWORD   af_Type;		/* MEMORY, DISK, or SCALED */
    struct TextAttr af_Attr;	/* text attributes for font */
};

struct TAvailFonts {
    UWORD   taf_Type;		/* MEMORY, DISK, or SCALED */
    struct TTextAttr taf_Attr;	/* text attributes for font */
};

struct AvailFontsHeader {
    UWORD   afh_NumEntries;	 /* number of AvailFonts elements */
    /* struct AvailFonts afh_AF[], or struct TAvailFonts afh_TAF[]; */
};

#endif	/* DISKFONT_DISKFONT_H */


include/devices/hardblocks.h

#ifndef	DEVICES_HARDBLOCKS_H
#define	DEVICES_HARDBLOCKS_H
/*
**	$VER: hardblocks.h 44.2 (20.10.1999)
**	Includes Release 44.1
**
**	File System identifier blocks for hard disks
**
**	(C) Copyright 1988-1999 Amiga, Inc.
**	(C) Copyright 1999 Joanne Dow licensed to Amiga, Inc.
**	    All Rights Reserved
*/

/*	Changes
**	  Expanded envec
**	  Added storage for driveinit name up to 31 letters.
**	  Added storage for filesysten name up to 83 letters.
**/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif /* EXEC_TYPES_H */

/*--------------------------------------------------------------------
 *
 *	This file describes blocks of data that exist on a hard disk
 *	to describe that disk.	They are not generically accessable to
 *	the user as they do not appear on any DOS drive.  The blocks
 *	are tagged with a unique identifier, checksummed, and linked
 *	together.  The root of these blocks is the RigidDiskBlock.
 *
 *	The RigidDiskBlock must exist on the disk within the first
 *	RDB_LOCATION_LIMIT blocks.  This inhibits the use of the zero
 *	cylinder in an AmigaDOS partition: although it is strictly
 *	possible to store the RigidDiskBlock data in the reserved
 *	area of a partition, this practice is discouraged since the
 *	reserved blocks of a partition are overwritten by "Format",
 *	"Install", "DiskCopy", etc.  The recommended disk layout,
 *	then, is to use the first cylinder(s) to store all the drive
 *	data specified by these blocks: i.e. partition descriptions,
 *	file system load images, drive bad block maps, spare blocks,
 *	etc.
 *
 *	Though all descriptions in this file contemplate 512 blocks
 *	per track this desecription works functionally with any block
 *	size. The LSEG blocks should make most efficient use of the
 *	disk block size possible, for example. While this specification
 *	can support 256 byte sectors that is deprecated at this time.
 *
 *	This version adds some modest storage spaces for inserting
 *	the actual source filename for files installed on the RDBs
 *	as either DriveInit code or Filesystem code. This makes
 *	creating a mountfile suitable for use with the "C:Mount"
 *	command that can be used for manually mounting the disk if
 *	ever required.
 *
 *------------------------------------------------------------------*/

/*
 *  NOTE
 *	optional block addresses below contain $ffffffff to indicate
 *	a NULL address, as zero is a valid address
 */
struct RigidDiskBlock {
    ULONG   rdb_ID;		/* 4 character identifier */
    ULONG   rdb_SummedLongs;	/* size of this checksummed structure */
    LONG    rdb_ChkSum;		/* block checksum (longword sum to zero) */
    ULONG   rdb_HostID;		/* SCSI Target ID of host */
    ULONG   rdb_BlockBytes;	/* size of disk blocks */
    ULONG   rdb_Flags;		/* see below for defines */
    /* block list heads */
    ULONG   rdb_BadBlockList;	/* optional bad block list */
    ULONG   rdb_PartitionList;	/* optional first partition block */
    ULONG   rdb_FileSysHeaderList; /* optional file system header block */
    ULONG   rdb_DriveInit;	/* optional drive-specific init code */
                /* DriveInit(lun,rdb,ior): "C" stk & d0/a0/a1 */
    ULONG   rdb_Reserved1[6];	/* set to $ffffffff */
    /* physical drive characteristics */
    ULONG   rdb_Cylinders;	/* number of drive cylinders */
    ULONG   rdb_Sectors;	/* sectors per track */
    ULONG   rdb_Heads;		/* number of drive heads */
    ULONG   rdb_Interleave;	/* interleave */
    ULONG   rdb_Park;		/* landing zone cylinder */
    ULONG   rdb_Reserved2[3];
    ULONG   rdb_WritePreComp;	/* starting cylinder: write precompensation */
    ULONG   rdb_ReducedWrite;	/* starting cylinder: reduced write current */
    ULONG   rdb_StepRate;	/* drive step rate */
    ULONG   rdb_Reserved3[5];
    /* logical drive characteristics */
    ULONG   rdb_RDBBlocksLo;	/* low block of range reserved for hardblocks */
    ULONG   rdb_RDBBlocksHi;	/* high block of range for these hardblocks */
    ULONG   rdb_LoCylinder;	/* low cylinder of partitionable disk area */
    ULONG   rdb_HiCylinder;	/* high cylinder of partitionable data area */
    ULONG   rdb_CylBlocks;	/* number of blocks available per cylinder */
    ULONG   rdb_AutoParkSeconds; /* zero for no auto park */
    ULONG   rdb_HighRDSKBlock;	/* highest block used by RDSK */
                /* (not including replacement bad blocks) */
    ULONG   rdb_Reserved4;
    /* drive identification */
    char    rdb_DiskVendor[8];
    char    rdb_DiskProduct[16];
    char    rdb_DiskRevision[4];
    char    rdb_ControllerVendor[8];
    char    rdb_ControllerProduct[16];
    char    rdb_ControllerRevision[4];
    char    rdb_DriveInitName[40]; // jdow: Filename for driveinit source
                   // jdow: as a terminated string.
};

#define	IDNAME_RIGIDDISK	0x5244534B	/* 'RDSK' */

#define	RDB_LOCATION_LIMIT	16

#define	RDBFB_LAST	0	/* no disks exist to be configured after */
#define	RDBFF_LAST	0x01L	/*   this one on this controller */
#define	RDBFB_LASTLUN	1	/* no LUNs exist to be configured greater */
#define	RDBFF_LASTLUN	0x02L	/*   than this one at this SCSI Target ID */
#define	RDBFB_LASTTID	2	/* no Target IDs exist to be configured */
#define	RDBFF_LASTTID	0x04L	/*   greater than this one on this SCSI bus */
#define	RDBFB_NORESELECT 3	/* don't bother trying to perform reselection */
#define	RDBFF_NORESELECT 0x08L	/*   when talking to this drive */
#define	RDBFB_DISKID	4	/* rdb_Disk... identification valid */
#define	RDBFF_DISKID	0x10L
#define	RDBFB_CTRLRID	5	/* rdb_Controller... identification valid */
#define	RDBFF_CTRLRID	0x20L
                /* added 7/20/89 by commodore: */
#define RDBFB_SYNCH	6	/* drive supports scsi synchronous mode */
#define RDBFF_SYNCH	0x40L	/* CAN BE DANGEROUS TO USE IF IT DOESN'T! */

/*------------------------------------------------------------------*/
struct BadBlockEntry {
    ULONG   bbe_BadBlock;	/* block number of bad block */
    ULONG   bbe_GoodBlock;	/* block number of replacement block */
};

struct BadBlockBlock {
    ULONG   bbb_ID;		/* 4 character identifier */
    ULONG   bbb_SummedLongs;	/* size of this checksummed structure */
    LONG    bbb_ChkSum;		/* block checksum (longword sum to zero) */
    ULONG   bbb_HostID;		/* SCSI Target ID of host */
    ULONG   bbb_Next;		/* block number of the next BadBlockBlock */
    ULONG   bbb_Reserved;
    struct BadBlockEntry bbb_BlockPairs[61]; /* bad block entry pairs */
    /* note [61] assumes 512 byte blocks */
};

#define	IDNAME_BADBLOCK		0x42414442	/* 'BADB' */

/*------------------------------------------------------------------*/
struct PartitionBlock {
    ULONG   pb_ID;		/* 4 character identifier */
    ULONG   pb_SummedLongs;	/* size of this checksummed structure */
    LONG    pb_ChkSum;		/* block checksum (longword sum to zero) */
    ULONG   pb_HostID;		/* SCSI Target ID of host */
    ULONG   pb_Next;		/* block number of the next PartitionBlock */
    ULONG   pb_Flags;		/* see below for defines */
    ULONG   pb_Reserved1[2];
    ULONG   pb_DevFlags;	/* preferred flags for OpenDevice */
    UBYTE   pb_DriveName[32];	/* preferred DOS device name: BSTR form */
                /* (not used if this name is in use) */
    ULONG   pb_Reserved2[15];	/* filler to 32 longwords */
    ULONG   pb_Environment[20];	/* environment vector for this partition */
    ULONG   pb_EReserved[12];	/* reserved for future environment vector */
};

#define	IDNAME_PARTITION	0x50415254	/* 'PART' */

#define	PBFB_BOOTABLE	0	/* this partition is intended to be bootable */
#define	PBFF_BOOTABLE	1L	/*   (expected directories and files exist) */
#define	PBFB_NOMOUNT	1	/* do not mount this partition (e.g. manually */
#define	PBFF_NOMOUNT	2L	/*   mounted, but space reserved here) */

/*------------------------------------------------------------------*/
struct FileSysHeaderBlock {
    ULONG   fhb_ID;		/* 4 character identifier */
    ULONG   fhb_SummedLongs;	/* size of this checksummed structure */
    LONG    fhb_ChkSum;		/* block checksum (longword sum to zero) */
    ULONG   fhb_HostID;		/* SCSI Target ID of host */
    ULONG   fhb_Next;		/* block number of next FileSysHeaderBlock */
    ULONG   fhb_Flags;		/* see below for defines */
    ULONG   fhb_Reserved1[2];
    ULONG   fhb_DosType;	/* file system description: match this with */
                /* partition environment's DE_DOSTYPE entry */
    ULONG   fhb_Version;	/* release version of this code */
    ULONG   fhb_PatchFlags;	/* bits set for those of the following that */
                /*   need to be substituted into a standard */
                /*   device node for this file system: e.g. */
                /*   0x180 to substitute SegList & GlobalVec */
    ULONG   fhb_Type;		/* device node type: zero */
    ULONG   fhb_Task;		/* standard dos "task" field: zero */
    ULONG   fhb_Lock;		/* not used for devices: zero */
    ULONG   fhb_Handler;	/* filename to loadseg: zero placeholder */
    ULONG   fhb_StackSize;	/* stacksize to use when starting task */
    LONG    fhb_Priority;	/* task priority when starting task */
    LONG    fhb_Startup;	/* startup msg: zero placeholder */
    LONG    fhb_SegListBlocks;	/* first of linked list of LoadSegBlocks: */
                /*   note that this entry requires some */
                /*   processing before substitution */
    LONG    fhb_GlobalVec;	/* BCPL global vector when starting task */
    ULONG   fhb_Reserved2[23];	/* (those reserved by PatchFlags) */
    char    fhb_FileSysName[84]; /* File system file name as loaded. */
};

#define	IDNAME_FILESYSHEADER	0x46534844	/* 'FSHD' */

/*------------------------------------------------------------------*/
struct LoadSegBlock {
    ULONG   lsb_ID;		/* 4 character identifier */
    ULONG   lsb_SummedLongs;	/* size of this checksummed structure */
    LONG    lsb_ChkSum;		/* block checksum (longword sum to zero) */
    ULONG   lsb_HostID;		/* SCSI Target ID of host */
    ULONG   lsb_Next;		/* block number of the next LoadSegBlock */
    ULONG   lsb_LoadData[123];	/* data for "loadseg" */
    /* note [123] assumes 512 byte blocks */
};

#define	IDNAME_LOADSEG		0x4C534547	/* 'LSEG' */

#endif	/* DEVICES_HARDBLOCKS_H */


include/graphics/gfx.h

#ifndef	GRAPHICS_GFX_H
#define	GRAPHICS_GFX_H
/*
**	$VER: gfx.h 39.5 (19.3.1992)
**	Includes Release 44.1
**
**	general include file for application programs
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#define BITSET	0x8000
#define BITCLR	0

#define AGNUS
#ifdef AGNUS
#define TOBB(a)      ((long)(a))
#else
#define TOBB(a)      ((long)(a)>>1)  /* convert Chip adr to Bread Board Adr */
#endif

struct Rectangle
{
    WORD   MinX,MinY;
    WORD   MaxX,MaxY;
};

struct Rect32
{
    LONG    MinX,MinY;
    LONG    MaxX,MaxY;
};

typedef struct tPoint
{
    WORD x,y;
} Point;

typedef UBYTE *PLANEPTR;

struct BitMap
{
    UWORD   BytesPerRow;
    UWORD   Rows;
    UBYTE   Flags;
    UBYTE   Depth;
    UWORD   pad;
    PLANEPTR Planes[8];
};

/* This macro is obsolete as of V39. AllocBitMap() should be used for allocating
   bitmap data, since it knows about the machine's particular alignment
   restrictions.
*/
#define RASSIZE(w,h)	((ULONG)(h)*( ((ULONG)(w)+15)>>3&0xFFFE))

/* flags for AllocBitMap, etc. */
#define BMB_CLEAR 0
#define BMB_DISPLAYABLE 1
#define BMB_INTERLEAVED 2
#define BMB_STANDARD 3
#define BMB_MINPLANES 4

#define BMF_CLEAR (1l<<BMB_CLEAR)
#define BMF_DISPLAYABLE (1l<<BMB_DISPLAYABLE)
#define BMF_INTERLEAVED (1l<<BMB_INTERLEAVED)
#define BMF_STANDARD (1l<<BMB_STANDARD)
#define BMF_MINPLANES (1l<<BMB_MINPLANES)

/* the following are for GetBitMapAttr() */
#define BMA_HEIGHT 0
#define BMA_DEPTH 4
#define BMA_WIDTH 8
#define BMA_FLAGS 12

#endif	/* GRAPHICS_GFX_H */


include/datatypes/pictureclass.h

#ifndef	DATATYPES_PICTURECLASS_H
#define	DATATYPES_PICTURECLASS_H
/*
**  $VER: pictureclass.h 44.1 (15.4.1999)
**  Includes Release 44.1
**
**  Interface definitions for DataType picture objects.
**
**  Copyright © 1992-1999 Amiga, Inc.
**	All Rights Reserved
*/

#ifndef	UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

#ifndef	DATATYPES_DATATYPESCLASS_H
#include <datatypes/datatypesclass.h>
#endif

#ifndef	LIBRARIES_IFFPARSE_H
#include <libraries/iffparse.h>
#endif

/*****************************************************************************/

#define	PICTUREDTCLASS "picture.datatype"

/*****************************************************************************/

/* Picture attributes */

/* Mode ID of the picture (ULONG) */
#define	PDTA_ModeID		(DTA_Dummy + 200)

/* Bitmap header information (struct BitMapHeader *) */
#define	PDTA_BitMapHeader	(DTA_Dummy + 201)

/* Pointer to a class-allocated bitmap, that will end
 * up being freed by picture.class when DisposeDTObject()
 * is called (struct BitMap *).
 */
#define	PDTA_BitMap		(DTA_Dummy + 202)

/* Picture colour table (struct ColorRegister *) */
#define	PDTA_ColorRegisters	(DTA_Dummy + 203)

/* Color table to use with SetRGB32CM() (ULONG *) */
#define	PDTA_CRegs		(DTA_Dummy + 204)

/* Color table; this table is initialized during the layout
 * process and will contain the colours the picture will use
 * after remapping. If no remapping takes place, these colours
 * will match those in the PDTA_CRegs table (ULONG *).
 */
#define	PDTA_GRegs		(DTA_Dummy + 205)

/* Shared pen table; this table is initialized during the layout
 * process while the picture is being remapped (UBYTE *).
 */
#define	PDTA_ColorTable		(DTA_Dummy + 206)

/* Shared pen table; in most places this table will be identical to
 * the PDTA_ColorTable table. Some of the colours in this table might
 * match the original colour palette a little better than the colours
 * picked for the other table. The picture.datatype uses the two tables
 * during remapping, alternating for each pixel (UBYTE *).
 */
#define	PDTA_ColorTable2	(DTA_Dummy + 207)

/* OBSOLETE; DO NOT USE */
#define	PDTA_Allocated		(DTA_Dummy + 208)

/* Number of colors used by the picture. (UWORD) */
#define	PDTA_NumColors		(DTA_Dummy + 209)

/* Number of colors allocated by the picture (UWORD) */
#define	PDTA_NumAlloc		(DTA_Dummy + 210)

/* Remap the picture (BOOL); defaults to TRUE */
#define	PDTA_Remap		(DTA_Dummy + 211)

/* Screen to remap to (struct Screen *) */
#define	PDTA_Screen		(DTA_Dummy + 212)

/* Free the source bitmap after remapping (BOOL) */
#define	PDTA_FreeSourceBitMap	(DTA_Dummy + 213)

/* Pointer to a Point structure */
#define	PDTA_Grab		(DTA_Dummy + 214)

/* Pointer to the destination (remapped) bitmap */
#define	PDTA_DestBitMap		(DTA_Dummy + 215)

/* Pointer to class-allocated bitmap, that will end
 * up being freed by the class after DisposeDTObject()
 * is called (struct BitMap *)
 */
#define	PDTA_ClassBitMap	(DTA_Dummy + 216)

/* Number of colors used for sparse remapping (UWORD) */
#define	PDTA_NumSparse		(DTA_Dummy + 217)

/* Pointer to a table of pen numbers indicating
 * which colors should be used when remapping the image.
 * This array must contain as many entries as there
 * are colors specified with PDTA_NumSparse (UBYTE *).
 */
#define	PDTA_SparseTable	(DTA_Dummy + 218)

/* Index number of the picture to load (ULONG). (V44) */
#define PDTA_WhichPicture	(DTA_Dummy + 219)

/* Get the number of pictures stored in the file (ULONG *). (V44) */
#define PDTA_GetNumPictures	(DTA_Dummy + 220)

/* Maximum number of colours to use for dithering (ULONG). (V44) */
#define PDTA_MaxDitherPens	(DTA_Dummy + 221)

/* Quality of the dithering algorithm to be used during colour
 * quantization (ULONG). (V44)
 */
#define PDTA_DitherQuality	(DTA_Dummy + 222)

/* Pointer to the allocated pen table (UBYTE *). (V44) */
#define PDTA_AllocatedPens	(DTA_Dummy + 223)

/*****************************************************************************/

/* When querying the number of pictures stored in a file, the
 * following value denotes "the number of pictures is unknown".
 */
#define PDTANUMPICTURES_Unknown (0)

/*****************************************************************************/

/* V43 extensions (attributes) */

/* Set the sub datatype interface mode (LONG); see "Interface modes" below */
#define PDTA_SourceMode		(DTA_Dummy + 250)

/* Set the app datatype interface mode (LONG); see "Interface modes" below */
#define PDTA_DestMode		(DTA_Dummy + 251)

/* Allocates the resulting bitmap as a friend bitmap (BOOL) */
#define PDTA_UseFriendBitMap	(DTA_Dummy + 255)

/* NULL or mask plane for use with BltMaskBitMapRastPort() (PLANEPTR) */
#define PDTA_MaskPlane		(DTA_Dummy + 258)

/*****************************************************************************/

/* Interface modes */
#define PMODE_V42 (0)	/* Compatibility mode */
#define PMODE_V43 (1)	/* Extended mode */

/*****************************************************************************/

/* V43 extensions (methods) */

#define PDTM_Dummy (DTM_Dummy + 0x60)

/* Transfer pixel data to the picture object in the specified format */
#define PDTM_WRITEPIXELARRAY (PDTM_Dummy + 0)

/* Transfer pixel data from the picture object in the specified format */
#define PDTM_READPIXELARRAY (PDTM_Dummy + 1)

/* PDTM_WRITEPIXELARRAY, PDTM_READPIXELARRAY */
struct pdtBlitPixelArray
{
    ULONG	MethodID;
    APTR	pbpa_PixelData;		/* The pixel data to transfer to/from */
    ULONG	pbpa_PixelFormat;	/* Format of the pixel data (see "Pixel Formats" below) */
    ULONG	pbpa_PixelArrayMod;	/* Number of bytes per row */
    ULONG	pbpa_Left;		/* Left edge of the rectangle to transfer pixels to/from */
    ULONG	pbpa_Top;		/* Top edge of the rectangle to transfer pixels to/from */
    ULONG	pbpa_Width;		/* Width of the rectangle to transfer pixels to/from */
    ULONG	pbpa_Height;		/* Height of the rectangle to transfer pixels to/from */
};

/* Pixel formats */
#define PBPAFMT_RGB	0	/* 3 bytes per pixel (red, green, blue) */
#define PBPAFMT_RGBA	1	/* 4 bytes per pixel (red, green, blue, alpha channel) */
#define PBPAFMT_ARGB	2	/* 4 bytes per pixel (alpha channel, red, green, blue) */
#define PBPAFMT_LUT8	3	/* 1 byte per pixel (using a separate colour map) */
#define PBPAFMT_GREY8	4	/* 1 byte per pixel (0==black, 255==white) */

/*****************************************************************************/

/* Masking techniques */
#define	mskNone			0
#define	mskHasMask		1
#define	mskHasTransparentColor	2
#define	mskLasso		3
#define	mskHasAlpha		4

/* Compression techniques */
#define	cmpNone			0
#define	cmpByteRun1		1
#define	cmpByteRun2		2	/* NOTE: unused (V44) */

/* Bitmap header (BMHD) structure */
struct BitMapHeader
{
    UWORD	bmh_Width;		/* Width in pixels */
    UWORD	bmh_Height;		/* Height in pixels */
    WORD	bmh_Left;		/* Left position */
    WORD	bmh_Top;		/* Top position */
    UBYTE	bmh_Depth;		/* Number of planes */
    UBYTE	bmh_Masking;		/* Masking type */
    UBYTE	bmh_Compression;	/* Compression type */
    UBYTE	bmh_Pad;
    UWORD	bmh_Transparent;	/* Transparent color */
    UBYTE	bmh_XAspect;
    UBYTE	bmh_YAspect;
    WORD	bmh_PageWidth;
    WORD	bmh_PageHeight;
};

/*****************************************************************************/

/* Color register structure */
struct ColorRegister
{
    UBYTE red, green, blue;
};

/*****************************************************************************/

/* IFF types that may be in pictures */
#define	ID_ILBM	MAKE_ID('I','L','B','M')
#define	ID_BMHD	MAKE_ID('B','M','H','D')
#define	ID_CMAP	MAKE_ID('C','M','A','P')
#define	ID_CRNG	MAKE_ID('C','R','N','G')
#define	ID_GRAB	MAKE_ID('G','R','A','B')
#define	ID_SPRT	MAKE_ID('S','P','R','T')
#define	ID_DEST	MAKE_ID('D','E','S','T')
#define	ID_CAMG	MAKE_ID('C','A','M','G')

#ifndef ID_BODY
#define	ID_BODY	MAKE_ID('B','O','D','Y')
#endif /* ID_BODY */

#endif	/* DATATYPES_PICTURECLASS_H */


include/graphics/scale.h

#ifndef	GRAPHICS_SCALE_H
#define	GRAPHICS_SCALE_H
/*
**	$VER: scale.h 39.0 (21.8.1991)
**	Includes Release 44.1
**
**	structure argument to BitMapScale()
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

struct BitScaleArgs {
    UWORD   bsa_SrcX, bsa_SrcY;			/* source origin */
    UWORD   bsa_SrcWidth, bsa_SrcHeight;	/* source size */
    UWORD   bsa_XSrcFactor, bsa_YSrcFactor;	/* scale factor denominators */
    UWORD   bsa_DestX, bsa_DestY;		/* destination origin */
    UWORD   bsa_DestWidth, bsa_DestHeight;	/* destination size result */
    UWORD   bsa_XDestFactor, bsa_YDestFactor;	/* scale factor numerators */
    struct BitMap *bsa_SrcBitMap;		/* source BitMap */
    struct BitMap *bsa_DestBitMap;		/* destination BitMap */
    ULONG   bsa_Flags;				/* reserved.  Must be zero! */
    UWORD   bsa_XDDA, bsa_YDDA;			/* reserved */
    LONG    bsa_Reserved1;
    LONG    bsa_Reserved2;
};
#endif	/* GRAPHICS_SCALE_H */


include/hardware/blit.h

#ifndef	HARDWARE_BLIT_H
#define	HARDWARE_BLIT_H
/*
**	$VER: blit.h 39.1 (18.9.1992)
**	Includes Release 44.1
**
**	Defines for direct hardware use of the blitter.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#define HSIZEBITS 6
#define VSIZEBITS 16-HSIZEBITS
#define HSIZEMASK 0x3f	      /* 2^6 -- 1 */
#define VSIZEMASK 0x3FF       /* 2^10 - 1 */

/* all agnii support horizontal blit of at least 1024 bits (128 bytes) wide */
/* some agnii support horizontal blit of up to 32768 bits (4096 bytes) wide */

#ifndef	 NO_BIG_BLITS
#define  MINBYTESPERROW 128
#define  MAXBYTESPERROW 4096
#else
#define  MAXBYTESPERROW 128
#endif

/* definitions for blitter control register 0 */

#define ABC    0x80
#define ABNC   0x40
#define ANBC   0x20
#define ANBNC  0x10
#define NABC   0x8
#define NABNC  0x4
#define NANBC  0x2
#define NANBNC 0x1

/* some commonly used operations */
#define A_OR_B	  ABC|ANBC|NABC | ABNC|ANBNC|NABNC
#define A_OR_C	  ABC|NABC|ABNC | ANBC|NANBC|ANBNC
#define A_XOR_C   NABC|ABNC   | NANBC|ANBNC
#define A_TO_D	  ABC|ANBC|ABNC|ANBNC

#define BC0B_DEST 8
#define BC0B_SRCC 9
#define BC0B_SRCB   10
#define BC0B_SRCA 11
#define BC0F_DEST 0x100
#define BC0F_SRCC 0x200
#define BC0F_SRCB 0x400
#define BC0F_SRCA 0x800

#define BC1F_DESC   2	      /* blitter descend direction */

#define DEST 0x100
#define SRCC 0x200
#define SRCB 0x400
#define SRCA 0x800

#define ASHIFTSHIFT  12       /* bits to right align ashift value */
#define BSHIFTSHIFT  12       /* bits to right align bshift value */

/* definations for blitter control register 1 */
#define LINEMODE     0x1
#define FILL_OR      0x8
#define FILL_XOR     0x10
#define FILL_CARRYIN 0x4
#define ONEDOT	     0x2      /* one dot per horizontal line */
#define OVFLAG	     0x20
#define SIGNFLAG     0x40
#define BLITREVERSE  0x2

#define SUD	     0x10
#define SUL	     0x8
#define AUL	     0x4

#define OCTANT8   24
#define OCTANT7   4
#define OCTANT6   12
#define OCTANT5   28
#define OCTANT4   20
#define OCTANT3   8
#define OCTANT2   0
#define OCTANT1   16

/* stuff for blit qeuer */
struct bltnode
{
    struct  bltnode *n;
    int     (*function)();
    char    stat;
    short   blitsize;
    short   beamsync;
    int     (*cleanup)();
};

/* defined bits for bltstat */
#define CLEANUP 0x40
#define CLEANME CLEANUP

#endif	/* HARDWARE_BLIT_H */


include/intuition/intuition.h

#ifndef INTUITION_INTUITION_H
#define INTUITION_INTUITION_H TRUE
/*
**  $VER: intuition.h 38.26 (15.2.1993)
**  Includes Release 44.1
**
**  Interface definitions for Intuition applications.
**
**  (C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef GRAPHICS_GFX_H
#include <graphics/gfx.h>
#endif

#ifndef GRAPHICS_CLIP_H
#include <graphics/clip.h>
#endif

#ifndef GRAPHICS_VIEW_H
#include <graphics/view.h>
#endif

#ifndef GRAPHICS_RASTPORT_H
#include <graphics/rastport.h>
#endif

#ifndef GRAPHICS_LAYERS_H
#include <graphics/layers.h>
#endif

#ifndef GRAPHICS_TEXT_H
#include <graphics/text.h>
#endif

#ifndef EXEC_PORTS_H
#include <exec/ports.h>
#endif

#ifndef DEVICES_INPUTEVENT_H
#include <devices/inputevent.h>
#endif

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

/*
 * NOTE:  intuition/iobsolete.h is included at the END of this file!
 */

/* ======================================================================== */
/* === Menu =============================================================== */
/* ======================================================================== */
struct Menu
{
    struct Menu *NextMenu;	/* same level */
    WORD LeftEdge, TopEdge;	/* position of the select box */
    WORD Width, Height;	/* dimensions of the select box */
    UWORD Flags;		/* see flag definitions below */
    BYTE *MenuName;		/* text for this Menu Header */
    struct MenuItem *FirstItem; /* pointer to first in chain */

    /* these mysteriously-named variables are for internal use only */
    WORD JazzX, JazzY, BeatX, BeatY;
};

/* FLAGS SET BY BOTH THE APPLIPROG AND INTUITION */
#define MENUENABLED 0x0001	/* whether or not this menu is enabled */

/* FLAGS SET BY INTUITION */
#define MIDRAWN 0x0100		/* this menu's items are currently drawn */

/* ======================================================================== */
/* === MenuItem =========================================================== */
/* ======================================================================== */
struct MenuItem
{
    struct MenuItem *NextItem;	/* pointer to next in chained list */
    WORD LeftEdge, TopEdge;	/* position of the select box */
    WORD Width, Height;		/* dimensions of the select box */
    UWORD Flags;		/* see the defines below */

    LONG MutualExclude;		/* set bits mean this item excludes that */

    APTR ItemFill;		/* points to Image, IntuiText, or NULL */

    /* when this item is pointed to by the cursor and the items highlight
     *	mode HIGHIMAGE is selected, this alternate image will be displayed
     */
    APTR SelectFill;		/* points to Image, IntuiText, or NULL */

    BYTE Command;		/* only if appliprog sets the COMMSEQ flag */

    struct MenuItem *SubItem;	/* if non-zero, points to MenuItem for submenu */

    /* The NextSelect field represents the menu number of next selected
     *	item (when user has drag-selected several items)
     */
    UWORD NextSelect;
};

/* FLAGS SET BY THE APPLIPROG */
#define CHECKIT		0x0001	/* set to indicate checkmarkable item */
#define ITEMTEXT	0x0002	/* set if textual, clear if graphical item */
#define COMMSEQ		0x0004	/* set if there's an command sequence */
#define MENUTOGGLE	0x0008	/* set for toggling checks (else mut. exclude) */
#define ITEMENABLED	0x0010	/* set if this item is enabled */

/* these are the SPECIAL HIGHLIGHT FLAG state meanings */
#define HIGHFLAGS	0x00C0	/* see definitions below for these bits */
#define HIGHIMAGE	0x0000	/* use the user's "select image" */
#define HIGHCOMP	0x0040	/* highlight by complementing the selectbox */
#define HIGHBOX		0x0080	/* highlight by "boxing" the selectbox */
#define HIGHNONE	0x00C0	/* don't highlight */

/* FLAGS SET BY BOTH APPLIPROG AND INTUITION */
#define CHECKED	0x0100	/* state of the checkmark */

/* FLAGS SET BY INTUITION */
#define ISDRAWN		0x1000	/* this item's subs are currently drawn */
#define HIGHITEM	0x2000	/* this item is currently highlighted */
#define MENUTOGGLED	0x4000	/* this item was already toggled */

/* ======================================================================== */
/* === Requester ========================================================== */
/* ======================================================================== */
struct Requester
{
    struct Requester *OlderRequest;
    WORD LeftEdge, TopEdge;		/* dimensions of the entire box */
    WORD Width, Height;			/* dimensions of the entire box */
    WORD RelLeft, RelTop;		/* for Pointer relativity offsets */

    struct Gadget *ReqGadget;		/* pointer to a list of Gadgets */
    struct Border *ReqBorder;		/* the box's border */
    struct IntuiText *ReqText;		/* the box's text */
    UWORD Flags;			/* see definitions below */

    /* pen number for back-plane fill before draws */
    UBYTE BackFill;
    /* Layer in place of clip rect	*/
    struct Layer *ReqLayer;

    UBYTE ReqPad1[32];

    /* If the BitMap plane pointers are non-zero, this tells the system
     * that the image comes pre-drawn (if the appliprog wants to define
     * its own box, in any shape or size it wants!);  this is OK by
     * Intuition as long as there's a good correspondence between
     * the image and the specified Gadgets
     */
    struct BitMap *ImageBMap;	/* points to the BitMap of PREDRAWN imagery */
    struct Window *RWindow;	/* added.  points back to Window */

    struct Image  *ReqImage;	/* new for V36: drawn if USEREQIMAGE set */

    UBYTE ReqPad2[32];
};

/* FLAGS SET BY THE APPLIPROG */
#define POINTREL	0x0001
              /* if POINTREL set, TopLeft is relative to pointer
               * for DMRequester, relative to window center
               * for Request().
               */
#define PREDRAWN	0x0002
    /* set if Requester.ImageBMap points to predrawn Requester imagery */
#define NOISYREQ	0x0004
    /* if you don't want requester to filter input	   */
#define SIMPLEREQ	0x0010
    /* to use SIMPLEREFRESH layer (recommended)	*/

/* New for V36		*/
#define USEREQIMAGE	0x0020
    /*  render linked list ReqImage after BackFill
     * but before gadgets and text
     */
#define NOREQBACKFILL	0x0040
    /* don't bother filling requester with Requester.BackFill pen	*/

/* FLAGS SET BY INTUITION */
#define REQOFFWINDOW	0x1000	/* part of one of the Gadgets was offwindow */
#define REQACTIVE	0x2000	/* this requester is active */
#define SYSREQUEST	0x4000	/* (unused) this requester caused by system */
#define DEFERREFRESH	0x8000	/* this Requester stops a Refresh broadcast */

/* ======================================================================== */
/* === Gadget ============================================================= */
/* ======================================================================== */
struct Gadget
{
    struct Gadget *NextGadget;	/* next gadget in the list */

    WORD LeftEdge, TopEdge;	/* "hit box" of gadget */
    WORD Width, Height;		/* "hit box" of gadget */

    UWORD Flags;		/* see below for list of defines */

    UWORD Activation;		/* see below for list of defines */

    UWORD GadgetType;		/* see below for defines */

    /* appliprog can specify that the Gadget be rendered as either as Border
     * or an Image.  This variable points to which (or equals NULL if there's
     * nothing to be rendered about this Gadget)
     */
    APTR GadgetRender;

    /* appliprog can specify "highlighted" imagery rather than algorithmic
     * this can point to either Border or Image data
     */
    APTR SelectRender;

    struct IntuiText *GadgetText;   /* text for this gadget */

    /* MutualExclude, never implemented, is now declared obsolete.
     * There are published examples of implementing a more general
     * and practical exclusion in your applications.
     *
     * Starting with V36, this field is used to point to a hook
     * for a custom gadget.
     *
     * Programs using this field for their own processing will
     * continue to work, as long as they don't try the
     * trick with custom gadgets.
     */
    LONG MutualExclude;  /* obsolete */

    /* pointer to a structure of special data required by Proportional,
     * String and Integer Gadgets
     */
    APTR SpecialInfo;

    UWORD GadgetID;	/* user-definable ID field */
    APTR UserData;	/* ptr to general purpose User data (ignored by In) */
};

struct ExtGadget
{
    /* The first fields match struct Gadget exactly */
    struct ExtGadget *NextGadget; /* Matches struct Gadget */
    WORD LeftEdge, TopEdge;	  /* Matches struct Gadget */
    WORD Width, Height;		  /* Matches struct Gadget */
    UWORD Flags;		  /* Matches struct Gadget */
    UWORD Activation;		  /* Matches struct Gadget */
    UWORD GadgetType;		  /* Matches struct Gadget */
    APTR GadgetRender;		  /* Matches struct Gadget */
    APTR SelectRender;		  /* Matches struct Gadget */
    struct IntuiText *GadgetText; /* Matches struct Gadget */
    LONG MutualExclude;		  /* Matches struct Gadget */
    APTR SpecialInfo;		  /* Matches struct Gadget */
    UWORD GadgetID;		  /* Matches struct Gadget */
    APTR UserData;		  /* Matches struct Gadget */

    /* These fields only exist under V39 and only if GFLG_EXTENDED is set */
    ULONG MoreFlags;		/* see GMORE_ flags below */
    WORD BoundsLeftEdge;	/* Bounding extent for gadget, valid   */
    WORD BoundsTopEdge;		/* only if GMORE_BOUNDS is set.  The   */
    WORD BoundsWidth;		/* GFLG_RELxxx flags affect these      */
    WORD BoundsHeight;		/* coordinates as well.	       */
};

/* --- Gadget.Flags values	--- */
/* combinations in these bits describe the highlight technique to be used */
#define GFLG_GADGHIGHBITS 0x0003
#define GFLG_GADGHCOMP	  0x0000  /* Complement the select box */
#define GFLG_GADGHBOX	  0x0001  /* Draw a box around the image */
#define GFLG_GADGHIMAGE	  0x0002  /* Blast in this alternate image */
#define GFLG_GADGHNONE	  0x0003  /* don't highlight */

#define GFLG_GADGIMAGE		  0x0004  /* set if GadgetRender and SelectRender
                   * point to an Image structure, clear
                   * if they point to Border structures
                   */

/* combinations in these next two bits specify to which corner the gadget's
 *  Left & Top coordinates are relative.  If relative to Top/Left,
 *  these are "normal" coordinates (everything is relative to something in
 *  this universe).
 *
 * Gadget positions and dimensions are relative to the window or
 * requester which contains the gadget
 */
#define GFLG_RELBOTTOM	  0x0008  /* vert. pos. is relative to bottom edge */
#define GFLG_RELRIGHT	  0x0010  /* horiz. pos. is relative to right edge */
#define GFLG_RELWIDTH	  0x0020  /* width is relative to req/window	*/
#define GFLG_RELHEIGHT	  0x0040  /* height is relative to req/window	*/

/* New for V39: GFLG_RELSPECIAL allows custom gadget implementors to
 * make gadgets whose position and size depend in an arbitrary way
 * on their window's dimensions.  The GM_LAYOUT method will be invoked
 * for such a gadget (or any other GREL_xxx gadget) at suitable times,
 * such as when the window opens or the window's size changes.
 */
#define GFLG_RELSPECIAL	  0x4000  /* custom gadget has special relativity.
                   * Gadget box values are absolutes, but
                   * can be changed via the GM_LAYOUT method.
                   */
#define GFLG_SELECTED	  0x0080  /* you may initialize and look at this	*/

/* the GFLG_DISABLED flag is initialized by you and later set by Intuition
 * according to your calls to On/OffGadget().  It specifies whether or not
 * this Gadget is currently disabled from being selected
 */
#define GFLG_DISABLED	  0x0100

/* These flags specify the type of text field that Gadget.GadgetText
 * points to.  In all normal (pre-V36) gadgets which you initialize
 * this field should always be zero.  Some types of gadget objects
 * created from classes will use these fields to keep track of
 * types of labels/contents that different from IntuiText, but are
 * stashed in GadgetText.
 */

#define GFLG_LABELMASK	  0x3000
#define GFLG_LABELITEXT	  0x0000  /* GadgetText points to IntuiText	*/
#define	GFLG_LABELSTRING  0x1000  /* GadgetText points to (UBYTE *)	*/
#define GFLG_LABELIMAGE	  0x2000  /* GadgetText points to Image (object)	*/

/* New for V37: GFLG_TABCYCLE */
#define GFLG_TABCYCLE	  0x0200  /* (string or custom) gadget participates in
                   * cycling activation with Tab or Shift-Tab
                   */
/* New for V37: GFLG_STRINGEXTEND.  We discovered that V34 doesn't properly
 * ignore the value we had chosen for the Gadget->Activation flag
 * GACT_STRINGEXTEND.  NEVER SET THAT FLAG WHEN RUNNING UNDER V34.
 * The Gadget->Flags bit GFLG_STRINGEXTEND is provided as a synonym which is
 * safe under V34, and equivalent to GACT_STRINGEXTEND under V37.
 * (Note that the two flags are not numerically equal)
 */
#define GFLG_STRINGEXTEND 0x0400  /* this String Gadget has StringExtend	*/

/* New for V39: GFLG_IMAGEDISABLE.  This flag is automatically set if
 * the custom image of this gadget knows how to do disabled rendering
 * (more specifically, if its IA_SupportsDisable attribute is TRUE).
 * Intuition uses this to defer the ghosting to the image-class,
 * instead of doing it itself (the old compatible way).
 * Do not set this flag yourself - Intuition will do it for you.
 */

#define GFLG_IMAGEDISABLE 0x0800  /* Gadget's image knows how to do disabled
                   * rendering
                   */

/* New for V39:  If set, this bit means that the Gadget is actually
 * a struct ExtGadget, with new fields and flags.  All V39 boopsi
 * gadgets are ExtGadgets.  Never ever attempt to read the extended
 * fields of a gadget if this flag is not set.
 */
#define GFLG_EXTENDED	  0x8000  /* Gadget is extended */

/* ---	Gadget.Activation flag values	--- */
/* Set GACT_RELVERIFY if you want to verify that the pointer was still over
 * the gadget when the select button was released.  Will cause
 * an IDCMP_GADGETUP message to be sent if so.
 */
#define GACT_RELVERIFY	  0x0001

/* the flag GACT_IMMEDIATE, when set, informs the caller that the gadget
 *  was activated when it was activated.  This flag works in conjunction with
 *  the GACT_RELVERIFY flag
 */
#define GACT_IMMEDIATE	  0x0002

/* the flag GACT_ENDGADGET, when set, tells the system that this gadget,
 * when selected, causes the Requester to be ended.  Requesters
 * that are ended are erased and unlinked from the system.
 */
#define GACT_ENDGADGET	  0x0004

/* the GACT_FOLLOWMOUSE flag, when set, specifies that you want to receive
 * reports on mouse movements while this gadget is active.
 * You probably want to set the GACT_IMMEDIATE flag when using
 * GACT_FOLLOWMOUSE, since that's the only reasonable way you have of
 * learning why Intuition is suddenly sending you a stream of mouse
 * movement events.  If you don't set GACT_RELVERIFY, you'll get at
 * least one Mouse Position event.
 * Note: boolean FOLLOWMOUSE gadgets require GACT_RELVERIFY to get
 * _any_ mouse movement events (this unusual behavior is a compatibility
 * hold-over from the old days).
 */
#define GACT_FOLLOWMOUSE  0x0008

/* if any of the BORDER flags are set in a Gadget that's included in the
 * Gadget list when a Window is opened, the corresponding Border will
 * be adjusted to make room for the Gadget
 */
#define GACT_RIGHTBORDER  0x0010
#define GACT_LEFTBORDER	  0x0020
#define GACT_TOPBORDER	  0x0040
#define GACT_BOTTOMBORDER 0x0080
#define GACT_BORDERSNIFF  0x8000  /* neither set nor rely on this bit	*/

#define GACT_TOGGLESELECT 0x0100  /* this bit for toggle-select mode */
#define GACT_BOOLEXTEND	  0x2000  /* this Boolean Gadget has a BoolInfo	*/

/* should properly be in StringInfo, but aren't	*/
#define GACT_STRINGLEFT	  0x0000  /* NOTE WELL: that this has value zero	*/
#define GACT_STRINGCENTER 0x0200
#define GACT_STRINGRIGHT  0x0400
#define GACT_LONGINT	  0x0800  /* this String Gadget is for Long Ints	*/
#define GACT_ALTKEYMAP	  0x1000  /* this String has an alternate keymap	*/
#define GACT_STRINGEXTEND 0x2000  /* this String Gadget has StringExtend	*/
                  /* NOTE: NEVER SET GACT_STRINGEXTEND IF YOU
                   * ARE RUNNING ON LESS THAN V36!  SEE
                   * GFLG_STRINGEXTEND (ABOVE) INSTEAD
                   */

#define GACT_ACTIVEGADGET 0x4000  /* this gadget is "active".  This flag
                   * is maintained by Intuition, and you
                   * cannot count on its value persisting
                   * while you do something on your program's
                   * task.  It can only be trusted by
                   * people implementing custom gadgets
                   */

/* note 0x8000 is used above (GACT_BORDERSNIFF);
 * all Activation flags defined */

/* --- GADGET TYPES ------------------------------------------------------- */
/* These are the Gadget Type definitions for the variable GadgetType
 * gadget number type MUST start from one.  NO TYPES OF ZERO ALLOWED.
 * first comes the mask for Gadget flags reserved for Gadget typing
 */
#define GTYP_GADGETTYPE	0xFC00	/* all Gadget Global Type flags (padded) */

#define GTYP_SCRGADGET		0x4000	/* 1 = ScreenGadget, 0 = WindowGadget */
#define GTYP_GZZGADGET		0x2000	/* 1 = for WFLG_GIMMEZEROZERO borders */
#define GTYP_REQGADGET		0x1000	/* 1 = this is a Requester Gadget */

/* GTYP_SYSGADGET means that Intuition ALLOCATED the gadget.
 * GTYP_SYSTYPEMASK is the mask you can apply to tell what type of
 * system-gadget it is.  The possible types follow.
 */
#define GTYP_SYSGADGET		0x8000
#define GTYP_SYSTYPEMASK	0x00F0

/* These definitions describe system gadgets in V36 and higher: */
#define GTYP_SIZING		0x0010	/* Window sizing gadget */
#define GTYP_WDRAGGING		0x0020	/* Window drag bar */
#define GTYP_SDRAGGING		0x0030	/* Screen drag bar */
#define GTYP_WDEPTH		0x0040	/* Window depth gadget */
#define GTYP_SDEPTH		0x0050	/* Screen depth gadget */
#define GTYP_WZOOM		0x0060	/* Window zoom gadget */
#define GTYP_SUNUSED		0x0070	/* Unused screen gadget */
#define GTYP_CLOSE		0x0080	/* Window close gadget */

/* These definitions describe system gadgets prior to V36: */
#define GTYP_WUPFRONT		GTYP_WDEPTH	/* Window to-front gadget */
#define GTYP_SUPFRONT		GTYP_SDEPTH	/* Screen to-front gadget */
#define GTYP_WDOWNBACK		GTYP_WZOOM	/* Window to-back gadget */
#define GTYP_SDOWNBACK		GTYP_SUNUSED	/* Screen to-back gadget */

/* GTYP_GTYPEMASK is a mask you can apply to tell what class
 * of gadget this is.  The possible classes follow.
 */
#define GTYP_GTYPEMASK		0x0007

#define GTYP_BOOLGADGET		0x0001
#define GTYP_GADGET0002		0x0002
#define GTYP_PROPGADGET		0x0003
#define GTYP_STRGADGET		0x0004
#define GTYP_CUSTOMGADGET	0x0005

/* This bit in GadgetType is reserved for undocumented internal use
 * by the Gadget Toolkit, and cannot be used nor relied on by
 * applications:	0x0100
 */

/* New for V39.  Gadgets which have the GFLG_EXTENDED flag set are
 * actually ExtGadgets, which have more flags.	The GMORE_xxx
 * identifiers describe those flags.  For GMORE_SCROLLRASTER, see
 * important information in the ScrollWindowRaster() autodoc.
 * NB: GMORE_SCROLLRASTER must be set before the gadget is
 * added to a window.
 */
#define GMORE_BOUNDS	   0x00000001L /* ExtGadget has valid Bounds */
#define GMORE_GADGETHELP   0x00000002L /* This gadget responds to gadget help */
#define GMORE_SCROLLRASTER 0x00000004L /* This (custom) gadget uses ScrollRaster */

/* ======================================================================== */
/* === BoolInfo======================================================= */
/* ======================================================================== */
/* This is the special data needed by an Extended Boolean Gadget
 * Typically this structure will be pointed to by the Gadget field SpecialInfo
 */
struct BoolInfo
{
    UWORD  Flags;	/* defined below */
    UWORD  *Mask;	/* bit mask for highlighting and selecting
             * mask must follow the same rules as an Image
             * plane.  Its width and height are determined
             * by the width and height of the gadget's
             * select box. (i.e. Gadget.Width and .Height).
             */
    ULONG  Reserved;	/* set to 0	*/
};

/* set BoolInfo.Flags to this flag bit.
 * in the future, additional bits might mean more stuff hanging
 * off of BoolInfo.Reserved.
 */
#define BOOLMASK	0x0001	/* extension is for masked gadget */

/* ======================================================================== */
/* === PropInfo =========================================================== */
/* ======================================================================== */
/* this is the special data required by the proportional Gadget
 * typically, this data will be pointed to by the Gadget variable SpecialInfo
 */
struct PropInfo
{
    UWORD Flags;	/* general purpose flag bits (see defines below) */

    /* You initialize the Pot variables before the Gadget is added to
     * the system.  Then you can look here for the current settings
     * any time, even while User is playing with this Gadget.  To
     * adjust these after the Gadget is added to the System, use
     * ModifyProp();  The Pots are the actual proportional settings,
     * where a value of zero means zero and a value of MAXPOT means
     * that the Gadget is set to its maximum setting.
     */
    UWORD HorizPot;	/* 16-bit FixedPoint horizontal quantity percentage */
    UWORD VertPot;	/* 16-bit FixedPoint vertical quantity percentage */

    /* the 16-bit FixedPoint Body variables describe what percentage of
     * the entire body of stuff referred to by this Gadget is actually
     * shown at one time.  This is used with the AUTOKNOB routines,
     * to adjust the size of the AUTOKNOB according to how much of
     * the data can be seen.  This is also used to decide how far
     * to advance the Pots when User hits the Container of the Gadget.
     * For instance, if you were controlling the display of a 5-line
     * Window of text with this Gadget, and there was a total of 15
     * lines that could be displayed, you would set the VertBody value to
     *	   (MAXBODY / (TotalLines / DisplayLines)) = MAXBODY / 3.
     * Therefore, the AUTOKNOB would fill 1/3 of the container, and
     * if User hits the Cotainer outside of the knob, the pot would
     * advance 1/3 (plus or minus) If there's no body to show, or
     * the total amount of displayable info is less than the display area,
     * set the Body variables to the MAX.  To adjust these after the
     * Gadget is added to the System, use ModifyProp();
     */
    UWORD HorizBody;		/* horizontal Body */
    UWORD VertBody;		/* vertical Body */

    /* these are the variables that Intuition sets and maintains */
    UWORD CWidth;	/* Container width (with any relativity absoluted) */
    UWORD CHeight;	/* Container height (with any relativity absoluted) */
    UWORD HPotRes, VPotRes;	/* pot increments */
    UWORD LeftBorder;		/* Container borders */
    UWORD TopBorder;		/* Container borders */
};

/* --- FLAG BITS ---------------------------------------------------------- */
#define AUTOKNOB	0x0001	/* this flag sez:  gimme that old auto-knob */
/* NOTE: if you do not use an AUTOKNOB for a proportional gadget,
 * you are currently limited to using a single Image of your own
 * design: Intuition won't handle a linked list of images as
 * a proportional gadget knob.
 */

#define FREEHORIZ	0x0002	/* if set, the knob can move horizontally */
#define FREEVERT	0x0004	/* if set, the knob can move vertically */
#define PROPBORDERLESS	0x0008	/* if set, no border will be rendered */
#define KNOBHIT		0x0100	/* set when this Knob is hit */
#define PROPNEWLOOK	0x0010	/* set this if you want to get the new
                 * V36 look
                 */

#define KNOBHMIN	6	/* minimum horizontal size of the Knob */
#define KNOBVMIN	4	/* minimum vertical size of the Knob */
#define MAXBODY		0xFFFF	/* maximum body value */
#define MAXPOT			0xFFFF	/* maximum pot value */

/* ======================================================================== */
/* === StringInfo ========================================================= */
/* ======================================================================== */
/* this is the special data required by the string Gadget
 * typically, this data will be pointed to by the Gadget variable SpecialInfo
 */
struct StringInfo
{
    /* you initialize these variables, and then Intuition maintains them */
    UBYTE *Buffer;	/* the buffer containing the start and final string */
    UBYTE *UndoBuffer;	/* optional buffer for undoing current entry */
    WORD BufferPos;	/* character position in Buffer */
    WORD MaxChars;	/* max number of chars in Buffer (including NULL) */
    WORD DispPos;	/* Buffer position of first displayed character */

    /* Intuition initializes and maintains these variables for you */
    WORD UndoPos;	/* character position in the undo buffer */
    WORD NumChars;	/* number of characters currently in Buffer */
    WORD DispCount;	/* number of whole characters visible in Container */
    WORD CLeft, CTop;	/* topleft offset of the container */

    /* This unused field is changed to allow extended specification
     * of string gadget parameters.  It is ignored unless the flag
     * GACT_STRINGEXTEND is set in the Gadget's Activation field
     * or the GFLG_STRINGEXTEND flag is set in the Gadget Flags field.
     * (See GFLG_STRINGEXTEND for an important note)
     */
    /* struct Layer *LayerPtr;	--- obsolete --- */
    struct StringExtend *Extension;

    /* you can initialize this variable before the gadget is submitted to
     * Intuition, and then examine it later to discover what integer
     * the user has entered (if the user never plays with the gadget,
     * the value will be unchanged from your initial setting)
     */
    LONG LongInt;

    /* If you want this Gadget to use your own Console keymapping, you
     * set the GACT_ALTKEYMAP bit in the Activation flags of the Gadget,
     * and then set this variable to point to your keymap.  If you don't
     * set the GACT_ALTKEYMAP, you'll get the standard ASCII keymapping.
     */
    struct KeyMap *AltKeyMap;
};

/* ======================================================================== */
/* === IntuiText ========================================================== */
/* ======================================================================== */
/* IntuiText is a series of strings that start with a location
 *  (always relative to the upper-left corner of something) and then the
 *  text of the string.  The text is null-terminated.
 */
struct IntuiText
{
    UBYTE FrontPen, BackPen;	/* the pen numbers for the rendering */
    UBYTE DrawMode;		/* the mode for rendering the text */
    WORD LeftEdge;		/* relative start location for the text */
    WORD TopEdge;		/* relative start location for the text */
    struct TextAttr *ITextFont;	/* if NULL, you accept the default */
    UBYTE *IText;		/* pointer to null-terminated text */
    struct IntuiText *NextText; /* pointer to another IntuiText to render */
};

/* ======================================================================== */
/* === Border ============================================================= */
/* ======================================================================== */
/* Data type Border, used for drawing a series of lines which is intended for
 *  use as a border drawing, but which may, in fact, be used to render any
 *  arbitrary vector shape.
 *  The routine DrawBorder sets up the RastPort with the appropriate
 *  variables, then does a Move to the first coordinate, then does Draws
 *  to the subsequent coordinates.
 *  After all the Draws are done, if NextBorder is non-zero we call DrawBorder
 *  on NextBorder
 */
struct Border
{
    WORD LeftEdge, TopEdge;	/* initial offsets from the origin */
    UBYTE FrontPen, BackPen;	/* pens numbers for rendering */
    UBYTE DrawMode;		/* mode for rendering */
    BYTE Count;			/* number of XY pairs */
    WORD *XY;			/* vector coordinate pairs rel to LeftTop */
    struct Border *NextBorder;	/* pointer to any other Border too */
};

/* ======================================================================== */
/* === Image ============================================================== */
/* ======================================================================== */
/* This is a brief image structure for very simple transfers of
 * image data to a RastPort
 */
struct Image
{
    WORD LeftEdge;		/* starting offset relative to some origin */
    WORD TopEdge;		/* starting offsets relative to some origin */
    WORD Width;			/* pixel size (though data is word-aligned) */
    WORD Height;
    WORD Depth;			/* >= 0, for images you create		*/
    UWORD *ImageData;		/* pointer to the actual word-aligned bits */

    /* the PlanePick and PlaneOnOff variables work much the same way as the
     * equivalent GELS Bob variables.  It's a space-saving
     * mechanism for image data.  Rather than defining the image data
     * for every plane of the RastPort, you need define data only
     * for the planes that are not entirely zero or one.  As you
     * define your Imagery, you will often find that most of the planes
     * ARE just as color selectors.  For instance, if you're designing
     * a two-color Gadget to use colors one and three, and the Gadget
     * will reside in a five-plane display, bit plane zero of your
     * imagery would be all ones, bit plane one would have data that
     * describes the imagery, and bit planes two through four would be
     * all zeroes.  Using these flags avoids wasting all
     * that memory in this way:  first, you specify which planes you
     * want your data to appear in using the PlanePick variable.  For
     * each bit set in the variable, the next "plane" of your image
     * data is blitted to the display.	For each bit clear in this
     * variable, the corresponding bit in PlaneOnOff is examined.
     * If that bit is clear, a "plane" of zeroes will be used.
     * If the bit is set, ones will go out instead.  So, for our example:
     *	 Gadget.PlanePick = 0x02;
     *	 Gadget.PlaneOnOff = 0x01;
     * Note that this also allows for generic Gadgets, like the
     * System Gadgets, which will work in any number of bit planes.
     * Note also that if you want an Image that is only a filled
     * rectangle, you can get this by setting PlanePick to zero
     * (pick no planes of data) and set PlaneOnOff to describe the pen
     * color of the rectangle.
     *
     * NOTE:  Intuition relies on PlanePick to know how many planes
     * of data are found in ImageData.	There should be no more
     * '1'-bits in PlanePick than there are planes in ImageData.
     */
    UBYTE PlanePick, PlaneOnOff;

    /* if the NextImage variable is not NULL, Intuition presumes that
     * it points to another Image structure with another Image to be
     * rendered
     */
    struct Image *NextImage;
};

/* ======================================================================== */
/* === IntuiMessage ======================================================= */
/* ======================================================================== */
struct IntuiMessage
{
    struct Message ExecMessage;

    /* the Class bits correspond directly with the IDCMP Flags, except for the
     * special bit IDCMP_LONELYMESSAGE (defined below)
     */
    ULONG Class;

    /* the Code field is for special values like MENU number */
    UWORD Code;

    /* the Qualifier field is a copy of the current InputEvent's Qualifier */
    UWORD Qualifier;

    /* IAddress contains particular addresses for Intuition functions, like
     * the pointer to the Gadget or the Screen
     */
    APTR IAddress;

    /* when getting mouse movement reports, any event you get will have the
     * the mouse coordinates in these variables.  the coordinates are relative
     * to the upper-left corner of your Window (WFLG_GIMMEZEROZERO
     * notwithstanding).  If IDCMP_DELTAMOVE is set, these values will
     * be deltas from the last reported position.
     */
    WORD MouseX, MouseY;

    /* the time values are copies of the current system clock time.  Micros
     * are in units of microseconds, Seconds in seconds.
     */
    ULONG Seconds, Micros;

    /* the IDCMPWindow variable will always have the address of the Window of
     * this IDCMP
     */
    struct Window *IDCMPWindow;

    /* system-use variable */
    struct IntuiMessage *SpecialLink;
};

/* New for V39:
 * All IntuiMessages are now slightly extended.  The ExtIntuiMessage
 * structure has an additional field for tablet data, which is usually
 * NULL.  If a tablet driver which is sending IESUBCLASS_NEWTABLET
 * events is installed in the system, windows with the WA_TabletMessages
 * property set will find that eim_TabletData points to the TabletData
 * structure.  Applications must first check that this field is non-NULL;
 * it will be NULL for certain kinds of message, including mouse activity
 * generated from other than the tablet (i.e. the keyboard equivalents
 * or the mouse itself).
 *
 * NEVER EVER examine any extended fields when running under pre-V39!
 *
 * NOTE: This structure is subject to grow in the future.  Making
 * assumptions about its size is A BAD IDEA.
 */

struct ExtIntuiMessage
{
    struct IntuiMessage eim_IntuiMessage;
    struct TabletData *eim_TabletData;
};

/* --- IDCMP Classes ------------------------------------------------------ */
/* Please refer to the Autodoc for OpenWindow() and to the Rom Kernel
 * Manual for full details on the IDCMP classes.
 */
#define IDCMP_SIZEVERIFY	0x00000001L
#define IDCMP_NEWSIZE		0x00000002L
#define IDCMP_REFRESHWINDOW	0x00000004L
#define IDCMP_MOUSEBUTTONS	0x00000008L
#define IDCMP_MOUSEMOVE		0x00000010L
#define IDCMP_GADGETDOWN	0x00000020L
#define IDCMP_GADGETUP		0x00000040L
#define IDCMP_REQSET		0x00000080L
#define IDCMP_MENUPICK		0x00000100L
#define IDCMP_CLOSEWINDOW	0x00000200L
#define IDCMP_RAWKEY		0x00000400L
#define IDCMP_REQVERIFY		0x00000800L
#define IDCMP_REQCLEAR		0x00001000L
#define IDCMP_MENUVERIFY	0x00002000L
#define IDCMP_NEWPREFS		0x00004000L
#define IDCMP_DISKINSERTED	0x00008000L
#define IDCMP_DISKREMOVED	0x00010000L
#define IDCMP_WBENCHMESSAGE	0x00020000L  /*	System use only		*/
#define IDCMP_ACTIVEWINDOW	0x00040000L
#define IDCMP_INACTIVEWINDOW	0x00080000L
#define IDCMP_DELTAMOVE		0x00100000L
#define IDCMP_VANILLAKEY	0x00200000L
#define IDCMP_INTUITICKS	0x00400000L
/*  for notifications from "boopsi" gadgets	*/
#define IDCMP_IDCMPUPDATE	0x00800000L  /* new for V36	*/
/* for getting help key report during menu session	*/
#define IDCMP_MENUHELP		0x01000000L  /* new for V36	*/
/* for notification of any move/size/zoom/change window		*/
#define IDCMP_CHANGEWINDOW	0x02000000L  /* new for V36	*/
#define IDCMP_GADGETHELP	0x04000000L  /* new for V39	*/

/* NOTEZ-BIEN:				0x80000000 is reserved for internal use   */

/* the IDCMP Flags do not use this special bit, which is cleared when
 * Intuition sends its special message to the Task, and set when Intuition
 * gets its Message back from the Task.  Therefore, I can check here to
 * find out fast whether or not this Message is available for me to send
 */
#define IDCMP_LONELYMESSAGE	0x80000000L

/* --- IDCMP Codes -------------------------------------------------------- */
/* This group of codes is for the IDCMP_CHANGEWINDOW message */
#define CWCODE_MOVESIZE	0x0000	/* Window was moved and/or sized */
#define CWCODE_DEPTH	0x0001	/* Window was depth-arranged (new for V39) */

/* This group of codes is for the IDCMP_MENUVERIFY message */
#define MENUHOT		0x0001	/* IntuiWants verification or MENUCANCEL    */
#define MENUCANCEL	0x0002	/* HOT Reply of this cancels Menu operation */
#define MENUWAITING	0x0003	/* Intuition simply wants a ReplyMsg() ASAP */

/* These are internal tokens to represent state of verification attempts
 * shown here as a clue.
 */
#define OKOK		MENUHOT	/* guy didn't care			*/
#define OKABORT		0x0004	/* window rendered question moot	*/
#define OKCANCEL	MENUCANCEL /* window sent cancel reply		*/

/* This group of codes is for the IDCMP_WBENCHMESSAGE messages */
#define WBENCHOPEN	0x0001
#define WBENCHCLOSE	0x0002

/* A data structure common in V36 Intuition processing	*/
struct IBox
{
    WORD Left;
    WORD Top;
    WORD Width;
    WORD Height;
};

/* ======================================================================== */
/* === Window ============================================================= */
/* ======================================================================== */
struct Window
{
    struct Window *NextWindow;		/* for the linked list in a screen */

    WORD LeftEdge, TopEdge;		/* screen dimensions of window */
    WORD Width, Height;			/* screen dimensions of window */

    WORD MouseY, MouseX;		/* relative to upper-left of window */

    WORD MinWidth, MinHeight;		/* minimum sizes */
    UWORD MaxWidth, MaxHeight;		/* maximum sizes */

    ULONG Flags;			/* see below for defines */

    struct Menu *MenuStrip;		/* the strip of Menu headers */

    UBYTE *Title;			/* the title text for this window */

    struct Requester *FirstRequest;	/* all active Requesters */

    struct Requester *DMRequest;	/* double-click Requester */

    WORD ReqCount;			/* count of reqs blocking Window */

    struct Screen *WScreen;		/* this Window's Screen */
    struct RastPort *RPort;		/* this Window's very own RastPort */

    /* the border variables describe the window border.  If you specify
     * WFLG_GIMMEZEROZERO when you open the window, then the upper-left of
     * the ClipRect for this window will be upper-left of the BitMap (with
     * correct offsets when in SuperBitMap mode; you MUST select
     * WFLG_GIMMEZEROZERO when using SuperBitMap).  If you don't specify
     * ZeroZero, then you save memory (no allocation of RastPort, Layer,
     * ClipRect and associated Bitmaps), but you also must offset all your
     * writes by BorderTop, BorderLeft and do your own mini-clipping to
     * prevent writing over the system gadgets
     */
    BYTE BorderLeft, BorderTop, BorderRight, BorderBottom;
    struct RastPort *BorderRPort;

    /* You supply a linked-list of Gadgets for your Window.
     * This list DOES NOT include system gadgets.  You get the standard
     * window system gadgets by setting flag-bits in the variable Flags (see
     * the bit definitions below)
     */
    struct Gadget *FirstGadget;

    /* these are for opening/closing the windows */
    struct Window *Parent, *Descendant;

    /* sprite data information for your own Pointer
     * set these AFTER you Open the Window by calling SetPointer()
     */
    UWORD *Pointer;	/* sprite data */
    BYTE PtrHeight;	/* sprite height (not including sprite padding) */
    BYTE PtrWidth;	/* sprite width (must be less than or equal to 16) */
    BYTE XOffset, YOffset;	/* sprite offsets */

    /* the IDCMP Flags and User's and Intuition's Message Ports */
    ULONG IDCMPFlags;	/* User-selected flags */
    struct MsgPort *UserPort, *WindowPort;
    struct IntuiMessage *MessageKey;

    UBYTE DetailPen, BlockPen;	/* for bar/border/gadget rendering */

    /* the CheckMark is a pointer to the imagery that will be used when
     * rendering MenuItems of this Window that want to be checkmarked
     * if this is equal to NULL, you'll get the default imagery
     */
    struct Image *CheckMark;

    UBYTE *ScreenTitle;	/* if non-null, Screen title when Window is active */

    /* These variables have the mouse coordinates relative to the
     * inner-Window of WFLG_GIMMEZEROZERO Windows.  This is compared with the
     * MouseX and MouseY variables, which contain the mouse coordinates
     * relative to the upper-left corner of the Window, WFLG_GIMMEZEROZERO
     * notwithstanding
     */
    WORD GZZMouseX;
    WORD GZZMouseY;
    /* these variables contain the width and height of the inner-Window of
     * WFLG_GIMMEZEROZERO Windows
     */
    WORD GZZWidth;
    WORD GZZHeight;

    UBYTE *ExtData;

    BYTE *UserData;	/* general-purpose pointer to User data extension */

    /** 11/18/85: this pointer keeps a duplicate of what
     * Window.RPort->Layer is _supposed_ to be pointing at
     */
    struct Layer *WLayer;

    /* NEW 1.2: need to keep track of the font that
     * OpenWindow opened, in case user SetFont's into RastPort
     */
    struct TextFont *IFont;

    /* (V36) another flag word (the Flags field is used up).
     * At present, all flag values are system private.
     * Until further notice, you may not change nor use this field.
     */
    ULONG	MoreFlags;

    /**** Data beyond this point are Intuition Private.  DO NOT USE ****/
};

/* --- Flags requested at OpenWindow() time by the application --------- */
#define WFLG_SIZEGADGET	    0x00000001L	/* include sizing system-gadget? */
#define WFLG_DRAGBAR	    0x00000002L	/* include dragging system-gadget? */
#define WFLG_DEPTHGADGET    0x00000004L	/* include depth arrangement gadget? */
#define WFLG_CLOSEGADGET    0x00000008L	/* include close-box system-gadget? */

#define WFLG_SIZEBRIGHT	    0x00000010L	/* size gadget uses right border */
#define WFLG_SIZEBBOTTOM    0x00000020L	/* size gadget uses bottom border */

/* --- refresh modes ------------------------------------------------------ */
/* combinations of the WFLG_REFRESHBITS select the refresh type */
#define WFLG_REFRESHBITS    0x000000C0L
#define WFLG_SMART_REFRESH  0x00000000L
#define WFLG_SIMPLE_REFRESH 0x00000040L
#define WFLG_SUPER_BITMAP   0x00000080L
#define WFLG_OTHER_REFRESH  0x000000C0L

#define WFLG_BACKDROP	    0x00000100L	/* this is a backdrop window */

#define WFLG_REPORTMOUSE    0x00000200L	/* to hear about every mouse move */

#define WFLG_GIMMEZEROZERO  0x00000400L	/* a GimmeZeroZero window	*/

#define WFLG_BORDERLESS	    0x00000800L	/* to get a Window sans border */

#define WFLG_ACTIVATE	    0x00001000L	/* when Window opens, it's Active */

/* --- Other User Flags --------------------------------------------------- */
#define WFLG_RMBTRAP	    0x00010000L	/* Catch RMB events for your own */
#define WFLG_NOCAREREFRESH  0x00020000L	/* not to be bothered with REFRESH */

/* - V36 new Flags which the programmer may specify in NewWindow.Flags	*/
#define WFLG_NW_EXTENDED    0x00040000L	/* extension data provided	*/
                    /* see struct ExtNewWindow	*/

/* - V39 new Flags which the programmer may specify in NewWindow.Flags	*/
#define WFLG_NEWLOOKMENUS   0x00200000L	/* window has NewLook menus	*/

/* These flags are set only by Intuition.  YOU MAY NOT SET THEM YOURSELF! */
#define WFLG_WINDOWACTIVE   0x00002000L	/* this window is the active one */
#define WFLG_INREQUEST	    0x00004000L	/* this window is in request mode */
#define WFLG_MENUSTATE	    0x00008000L	/* Window is active with Menus on */
#define WFLG_WINDOWREFRESH  0x01000000L	/* Window is currently refreshing */
#define WFLG_WBENCHWINDOW   0x02000000L	/* WorkBench tool ONLY Window */
#define WFLG_WINDOWTICKED   0x04000000L	/* only one timer tick at a time */

/* V36 and higher flags to be set only by Intuition: */
#define WFLG_VISITOR	    0x08000000L	/* visitor window		*/
#define WFLG_ZOOMED	    0x10000000L	/* identifies "zoom state"	*/
#define WFLG_HASZOOM	    0x20000000L	/* window has a zoom gadget	*/

/* --- Other Window Values ---------------------------------------------- */
#define DEFAULTMOUSEQUEUE	(5)	/* no more mouse messages	*/

/* --- see struct IntuiMessage for the IDCMP Flag definitions ------------- */

/* ======================================================================== */
/* === NewWindow ========================================================== */
/* ======================================================================== */
/*
 * Note that the new extension fields have been removed.  Use ExtNewWindow
 * structure below to make use of these fields
 */
struct NewWindow
{
    WORD LeftEdge, TopEdge;		/* screen dimensions of window */
    WORD Width, Height;			/* screen dimensions of window */

    UBYTE DetailPen, BlockPen;		/* for bar/border/gadget rendering */

    ULONG IDCMPFlags;			/* User-selected IDCMP flags */

    ULONG Flags;			/* see Window struct for defines */

    /* You supply a linked-list of Gadgets for your Window.
     *	This list DOES NOT include system Gadgets.  You get the standard
     *	system Window Gadgets by setting flag-bits in the variable Flags (see
     *	the bit definitions under the Window structure definition)
     */
    struct Gadget *FirstGadget;

    /* the CheckMark is a pointer to the imagery that will be used when
     * rendering MenuItems of this Window that want to be checkmarked
     * if this is equal to NULL, you'll get the default imagery
     */
    struct Image *CheckMark;

    UBYTE *Title;			  /* the title text for this window */

    /* the Screen pointer is used only if you've defined a CUSTOMSCREEN and
     * want this Window to open in it.	If so, you pass the address of the
     * Custom Screen structure in this variable.  Otherwise, this variable
     * is ignored and doesn't have to be initialized.
     */
    struct Screen *Screen;

    /* WFLG_SUPER_BITMAP Window?  If so, put the address of your BitMap
     * structure in this variable.  If not, this variable is ignored and
     * doesn't have to be initialized
     */
    struct BitMap *BitMap;

    /* the values describe the minimum and maximum sizes of your Windows.
     * these matter only if you've chosen the WFLG_SIZEGADGET option,
     * which means that you want to let the User to change the size of
     * this Window.  You describe the minimum and maximum sizes that the
     * Window can grow by setting these variables.  You can initialize
     * any one these to zero, which will mean that you want to duplicate
     * the setting for that dimension (if MinWidth == 0, MinWidth will be
     * set to the opening Width of the Window).
     * You can change these settings later using SetWindowLimits().
     * If you haven't asked for a SIZING Gadget, you don't have to
     * initialize any of these variables.
     */
    WORD MinWidth, MinHeight;	    /* minimums */
    UWORD MaxWidth, MaxHeight;	     /* maximums */

    /* the type variable describes the Screen in which you want this Window to
     * open.  The type value can either be CUSTOMSCREEN or one of the
     * system standard Screen Types such as WBENCHSCREEN.  See the
     * type definitions under the Screen structure.
     */
    UWORD Type;

};

/* The following structure is the future NewWindow.  Compatibility
 * issues require that the size of NewWindow not change.
 * Data in the common part (NewWindow) indicates the the extension
 * fields are being used.
 * NOTE WELL: This structure may be subject to future extension.
 * Writing code depending on its size is not allowed.
 */
struct ExtNewWindow
{
    WORD LeftEdge, TopEdge;
    WORD Width, Height;

    UBYTE DetailPen, BlockPen;
    ULONG IDCMPFlags;
    ULONG Flags;
    struct Gadget *FirstGadget;

    struct Image *CheckMark;

    UBYTE *Title;
    struct Screen *Screen;
    struct BitMap *BitMap;

    WORD MinWidth, MinHeight;
    UWORD MaxWidth, MaxHeight;

    /* the type variable describes the Screen in which you want this Window to
     * open.  The type value can either be CUSTOMSCREEN or one of the
     * system standard Screen Types such as WBENCHSCREEN.  See the
     * type definitions under the Screen structure.
     * A new possible value for this field is PUBLICSCREEN, which
     * defines the window as a 'visitor' window.  See below for
     * additional information provided.
     */
    UWORD Type;

    /* ------------------------------------------------------- *
     * extensions for V36
     * if the NewWindow Flag value WFLG_NW_EXTENDED is set, then
     * this field is assumed to point to an array ( or chain of arrays)
     * of TagItem structures.  See also ExtNewScreen for another
     * use of TagItems to pass optional data.
     *
     * see below for tag values and the corresponding data.
     */
    struct TagItem	*Extension;
};

/*
 * The TagItem ID's (ti_Tag values) for OpenWindowTagList() follow.
 * They are values in a TagItem array passed as extension/replacement
 * values for the data in NewWindow.  OpenWindowTagList() can actually
 * work well with a NULL NewWindow pointer.
 */

#define WA_Dummy	(TAG_USER + 99)	/* 0x80000063	*/

/* these tags simply override NewWindow parameters */
#define WA_Left			(WA_Dummy + 0x01)
#define WA_Top			(WA_Dummy + 0x02)
#define WA_Width		(WA_Dummy + 0x03)
#define WA_Height		(WA_Dummy + 0x04)
#define WA_DetailPen		(WA_Dummy + 0x05)
#define WA_BlockPen		(WA_Dummy + 0x06)
#define WA_IDCMP		(WA_Dummy + 0x07)
            /* "bulk" initialization of NewWindow.Flags */
#define WA_Flags		(WA_Dummy + 0x08)
#define WA_Gadgets		(WA_Dummy + 0x09)
#define WA_Checkmark		(WA_Dummy + 0x0A)
#define WA_Title		(WA_Dummy + 0x0B)
            /* means you don't have to call SetWindowTitles
             * after you open your window
             */
#define WA_ScreenTitle		(WA_Dummy + 0x0C)
#define WA_CustomScreen		(WA_Dummy + 0x0D)
#define WA_SuperBitMap		(WA_Dummy + 0x0E)
            /* also implies WFLG_SUPER_BITMAP property	*/
#define WA_MinWidth		(WA_Dummy + 0x0F)
#define WA_MinHeight		(WA_Dummy + 0x10)
#define WA_MaxWidth		(WA_Dummy + 0x11)
#define WA_MaxHeight		(WA_Dummy + 0x12)

/* The following are specifications for new features	*/

#define WA_InnerWidth		(WA_Dummy + 0x13)
#define WA_InnerHeight		(WA_Dummy + 0x14)
            /* You can specify the dimensions of the interior
             * region of your window, independent of what
             * the border widths will be.  You probably want
             * to also specify WA_AutoAdjust to allow
             * Intuition to move your window or even
             * shrink it so that it is completely on screen.
             */

#define WA_PubScreenName	(WA_Dummy + 0x15)
            /* declares that you want the window to open as
             * a visitor on the public screen whose name is
             * pointed to by (UBYTE *) ti_Data
             */
#define WA_PubScreen		(WA_Dummy + 0x16)
            /* open as a visitor window on the public screen
             * whose address is in (struct Screen *) ti_Data.
             * To ensure that this screen remains open, you
             * should either be the screen's owner, have a
             * window open on the screen, or use LockPubScreen().
             */
#define WA_PubScreenFallBack	(WA_Dummy + 0x17)
            /* A Boolean, specifies whether a visitor window
             * should "fall back" to the default public screen
             * (or Workbench) if the named public screen isn't
             * available
             */
#define WA_WindowName		(WA_Dummy + 0x18)
            /* not implemented	*/
#define WA_Colors		(WA_Dummy + 0x19)
            /* a ColorSpec array for colors to be set
             * when this window is active.	This is not
             * implemented, and may not be, since the default
             * values to restore would be hard to track.
             * We'd like to at least support per-window colors
             * for the mouse pointer sprite.
             */
#define WA_Zoom		(WA_Dummy + 0x1A)
            /* ti_Data points to an array of four WORD's,
             * the initial Left/Top/Width/Height values of
             * the "alternate" zoom position/dimensions.
             * It also specifies that you want a Zoom gadget
             * for your window, whether or not you have a
             * sizing gadget.
             */
#define WA_MouseQueue		(WA_Dummy + 0x1B)
            /* ti_Data contains initial value for the mouse
             * message backlog limit for this window.
             */
#define WA_BackFill		(WA_Dummy + 0x1C)
            /* provides a "backfill hook" for your window's Layer.
             * See layers.library/CreateUpfrontHookLayer().
             */
#define WA_RptQueue		(WA_Dummy + 0x1D)
            /* initial value of repeat key backlog limit	*/

    /* These Boolean tag items are alternatives to the NewWindow.Flags
     * boolean flags with similar names.
     */
#define WA_SizeGadget		(WA_Dummy + 0x1E)
#define WA_DragBar		(WA_Dummy + 0x1F)
#define WA_DepthGadget		(WA_Dummy + 0x20)
#define WA_CloseGadget		(WA_Dummy + 0x21)
#define WA_Backdrop		(WA_Dummy + 0x22)
#define WA_ReportMouse		(WA_Dummy + 0x23)
#define WA_NoCareRefresh	(WA_Dummy + 0x24)
#define WA_Borderless		(WA_Dummy + 0x25)
#define WA_Activate		(WA_Dummy + 0x26)
#define WA_RMBTrap		(WA_Dummy + 0x27)
#define WA_WBenchWindow		(WA_Dummy + 0x28)	/* PRIVATE!! */
#define WA_SimpleRefresh	(WA_Dummy + 0x29)
            /* only specify if TRUE	*/
#define WA_SmartRefresh		(WA_Dummy + 0x2A)
            /* only specify if TRUE	*/
#define WA_SizeBRight		(WA_Dummy + 0x2B)
#define WA_SizeBBottom		(WA_Dummy + 0x2C)

    /* New Boolean properties	*/
#define WA_AutoAdjust		(WA_Dummy + 0x2D)
            /* shift or squeeze the window's position and
             * dimensions to fit it on screen.
             */

#define WA_GimmeZeroZero	(WA_Dummy + 0x2E)
            /* equiv. to NewWindow.Flags WFLG_GIMMEZEROZERO	*/

/* New for V37: WA_MenuHelp (ignored by V36) */
#define WA_MenuHelp		(WA_Dummy + 0x2F)
            /* Enables IDCMP_MENUHELP:  Pressing HELP during menus
             * will return IDCMP_MENUHELP message.
             */

/* New for V39:  (ignored by V37 and earlier) */
#define WA_NewLookMenus		(WA_Dummy + 0x30)
            /* Set to TRUE if you want NewLook menus */
#define WA_AmigaKey		(WA_Dummy + 0x31)
            /* Pointer to image for Amiga-key equiv in menus */
#define WA_NotifyDepth		(WA_Dummy + 0x32)
            /* Requests IDCMP_CHANGEWINDOW message when
             * window is depth arranged
             * (imsg->Code = CWCODE_DEPTH)
             */

/* WA_Dummy + 0x33 is obsolete */

#define WA_Pointer		(WA_Dummy + 0x34)
            /* Allows you to specify a custom pointer
             * for your window.  ti_Data points to a
             * pointer object you obtained via
             * "pointerclass". NULL signifies the
             * default pointer.
             * This tag may be passed to OpenWindowTags()
             * or SetWindowPointer().
             */

#define WA_BusyPointer		(WA_Dummy + 0x35)
            /* ti_Data is boolean.	Set to TRUE to
             * request the standard busy pointer.
             * This tag may be passed to OpenWindowTags()
             * or SetWindowPointer().
             */

#define WA_PointerDelay		(WA_Dummy + 0x36)
            /* ti_Data is boolean.	Set to TRUE to
             * request that the changing of the
             * pointer be slightly delayed.  The change
             * will be called off if you call NewSetPointer()
             * before the delay expires.  This allows
             * you to post a busy-pointer even if you think
             * the busy-time may be very short, without
             * fear of a flashing pointer.
             * This tag may be passed to OpenWindowTags()
             * or SetWindowPointer().
             */

#define WA_TabletMessages	(WA_Dummy + 0x37)
            /* ti_Data is a boolean.  Set to TRUE to
             * request that tablet information be included
             * in IntuiMessages sent to your window.
             * Requires that something (i.e. a tablet driver)
             * feed IESUBCLASS_NEWTABLET InputEvents into
             * the system.	For a pointer to the TabletData,
             * examine the ExtIntuiMessage->eim_TabletData
             * field.  It is UNSAFE to check this field
             * when running on pre-V39 systems.  It's always
             * safe to check this field under V39 and up,
             * though it may be NULL.
             */

#define WA_HelpGroup		(WA_Dummy + 0x38)
            /* When the active window has gadget help enabled,
             * other windows of the same HelpGroup number
             * will also get GadgetHelp.  This allows GadgetHelp
             * to work for multi-windowed applications.
             * Use GetGroupID() to get an ID number.  Pass
             * this number as ti_Data to all your windows.
             * See also the HelpControl() function.
             */

#define WA_HelpGroupWindow	(WA_Dummy + 0x39)
            /* When the active window has gadget help enabled,
             * other windows of the same HelpGroup will also get
             * GadgetHelp.	This allows GadgetHelp to work
             * for multi-windowed applications.  As an alternative
             * to WA_HelpGroup, you can pass a pointer to any
             * other window of the same group to join its help
             * group.  Defaults to NULL, which has no effect.
             * See also the HelpControl() function.
             */

/* HelpControl() flags:
 *
 * HC_GADGETHELP - Set this flag to enable Gadget-Help for one or more
 * windows.
 */

#define HC_GADGETHELP	(1)

#ifndef INTUITION_SCREENS_H
#include <intuition/screens.h>
#endif

#ifndef INTUITION_PREFERENCES_H
#include <intuition/preferences.h>
#endif

/* ======================================================================== */
/* === Remember =========================================================== */
/* ======================================================================== */
/* this structure is used for remembering what memory has been allocated to
 * date by a given routine, so that a premature abort or systematic exit
 * can deallocate memory cleanly, easily, and completely
 */
struct Remember
{
    struct Remember *NextRemember;
    ULONG RememberSize;
    UBYTE *Memory;
};

/* === Color Spec ====================================================== */
/* How to tell Intuition about RGB values for a color table entry.
 * NOTE:  The way the structure was defined, the color value was
 * right-justified within each UWORD.  This poses problems for
 * extensibility to more bits-per-gun.	The SA_Colors32 tag to
 * OpenScreenTags() provides an alternate way to specify colors
 * with greater precision.
 */
struct ColorSpec
{
    WORD	ColorIndex;	/* -1 terminates an array of ColorSpec	*/
    UWORD	Red;	/* only the _bottom_ 4 bits recognized */
    UWORD	Green;	/* only the _bottom_ 4 bits recognized */
    UWORD	Blue;	/* only the _bottom_ 4 bits recognized */
};

/* === Easy Requester Specification ======================================= */
/* see also autodocs for EasyRequest and BuildEasyRequest	*/
/* NOTE: This structure may grow in size in the future		*/
struct EasyStruct {
    ULONG	es_StructSize;	/* should be sizeof (struct EasyStruct )*/
    ULONG	es_Flags;	/* should be 0 for now			*/
    UBYTE	*es_Title;	/* title of requester window		*/
    UBYTE	*es_TextFormat;	/* 'printf' style formatting string	*/
    UBYTE	*es_GadgetFormat; /* 'printf' style formatting string	*/
};

/* ======================================================================== */
/* === Miscellaneous ====================================================== */
/* ======================================================================== */

/* = MACROS ============================================================== */
#define MENUNUM(n) (n & 0x1F)
#define ITEMNUM(n) ((n >> 5) & 0x003F)
#define SUBNUM(n) ((n >> 11) & 0x001F)

#define SHIFTMENU(n) (n & 0x1F)
#define SHIFTITEM(n) ((n & 0x3F) << 5)
#define SHIFTSUB(n) ((n & 0x1F) << 11)

#define FULLMENUNUM( menu, item, sub )	\
    ( SHIFTSUB(sub) | SHIFTITEM(item) | SHIFTMENU(menu) )

#define SRBNUM(n)    (0x08 - (n >> 4))	/* SerRWBits -> read bits per char */
#define SWBNUM(n)    (0x08 - (n & 0x0F))/* SerRWBits -> write bits per chr */
#define SSBNUM(n)    (0x01 + (n >> 4))	/* SerStopBuf -> stop bits per chr */
#define SPARNUM(n)   (n >> 4)		/* SerParShk -> parity setting	  */
#define SHAKNUM(n)   (n & 0x0F)	/* SerParShk -> handshake mode	  */

/* = MENU STUFF =========================================================== */
#define NOMENU 0x001F
#define NOITEM 0x003F
#define NOSUB  0x001F
#define MENUNULL 0xFFFF

/* = =RJ='s peculiarities ================================================= */
#define FOREVER for(;;)
#define SIGN(x) ( ((x) > 0) - ((x) < 0) )
#define NOT !

/* these defines are for the COMMSEQ and CHECKIT menu stuff.  If CHECKIT,
 * I'll use a generic Width (for all resolutions) for the CheckMark.
 * If COMMSEQ, likewise I'll use this generic stuff
 */
#define CHECKWIDTH	19
#define COMMWIDTH	27
#define LOWCHECKWIDTH	13
#define LOWCOMMWIDTH	16

/* these are the AlertNumber defines.  if you are calling DisplayAlert()
 * the AlertNumber you supply must have the ALERT_TYPE bits set to one
 * of these patterns
 */
#define ALERT_TYPE	0x80000000L
#define RECOVERY_ALERT	0x00000000L	/* the system can recover from this */
#define DEADEND_ALERT	0x80000000L	/* no recovery possible, this is it */

/* When you're defining IntuiText for the Positive and Negative Gadgets
 * created by a call to AutoRequest(), these defines will get you
 * reasonable-looking text.  The only field without a define is the IText
 * field; you decide what text goes with the Gadget
 */
#define AUTOFRONTPEN	0
#define AUTOBACKPEN	1
#define AUTODRAWMODE	JAM2
#define AUTOLEFTEDGE	6
#define AUTOTOPEDGE	3
#define AUTOITEXTFONT	NULL
#define AUTONEXTTEXT	NULL

/* --- RAWMOUSE Codes and Qualifiers (Console OR IDCMP) ------------------- */
#define SELECTUP	(IECODE_LBUTTON | IECODE_UP_PREFIX)
#define SELECTDOWN	(IECODE_LBUTTON)
#define MENUUP		(IECODE_RBUTTON | IECODE_UP_PREFIX)
#define MENUDOWN	(IECODE_RBUTTON)
#define MIDDLEUP	(IECODE_MBUTTON | IECODE_UP_PREFIX)
#define MIDDLEDOWN	(IECODE_MBUTTON)
#define ALTLEFT		(IEQUALIFIER_LALT)
#define ALTRIGHT	(IEQUALIFIER_RALT)
#define AMIGALEFT	(IEQUALIFIER_LCOMMAND)
#define AMIGARIGHT	(IEQUALIFIER_RCOMMAND)
#define AMIGAKEYS	(AMIGALEFT | AMIGARIGHT)

#define CURSORUP	0x4C
#define CURSORLEFT	0x4F
#define CURSORRIGHT	0x4E
#define CURSORDOWN	0x4D
#define KEYCODE_Q	0x10
#define KEYCODE_Z	0x31
#define KEYCODE_X	0x32
#define KEYCODE_V	0x34
#define KEYCODE_B	0x35
#define KEYCODE_N	0x36
#define KEYCODE_M	0x37
#define KEYCODE_LESS	0x38
#define KEYCODE_GREATER 0x39

/* New for V39, Intuition supports the IESUBCLASS_NEWTABLET subclass
 * of the IECLASS_NEWPOINTERPOS event.	The ie_EventAddress of such
 * an event points to a TabletData structure (see below).
 *
 * The TabletData structure contains certain elements including a taglist.
 * The taglist can be used for special tablet parameters.  A tablet driver
 * should include only those tag-items the tablet supports.  An application
 * can listen for any tag-items that interest it.  Note: an application
 * must set the WA_TabletMessages attribute to TRUE to receive this
 * extended information in its IntuiMessages.
 *
 * The definitions given here MUST be followed.  Pay careful attention
 * to normalization and the interpretation of signs.
 *
 * TABLETA_TabletZ:  the current value of the tablet in the Z direction.
 * This unsigned value should typically be in the natural units of the
 * tablet.  You should also provide TABLETA_RangeZ.
 *
 * TABLETA_RangeZ:  the maximum value of the tablet in the Z direction.
 * Normally specified along with TABLETA_TabletZ, this allows the
 * application to scale the actual Z value across its range.
 *
 * TABLETA_AngleX:  the angle of rotation or tilt about the X-axis.  This
 * number should be normalized to fill a signed long integer.  Positive
 * values imply a clockwise rotation about the X-axis when viewing
 * from +X towards the origin.
 *
 * TABLETA_AngleY:  the angle of rotation or tilt about the Y-axis.  This
 * number should be normalized to fill a signed long integer.  Positive
 * values imply a clockwise rotation about the Y-axis when viewing
 * from +Y towards the origin.
 *
 * TABLETA_AngleZ:  the angle of rotation or tilt about the Z axis.  This
 * number should be normalized to fill a signed long integer.  Positive
 * values imply a clockwise rotation about the Z-axis when viewing
 * from +Z towards the origin.
 *
 *	Note: a stylus that supports tilt should use the TABLETA_AngleX
 *	and TABLETA_AngleY attributes.	Tilting the stylus so the tip
 *	points towards increasing or decreasing X is actually a rotation
 *	around the Y-axis.  Thus, if the stylus tip points towards
 *	positive X, then that tilt is represented as a negative
 *	TABLETA_AngleY.  Likewise, if the stylus tip points towards
 *	positive Y, that tilt is represented by positive TABLETA_AngleX.
 *
 * TABLETA_Pressure:  the pressure reading of the stylus.  The pressure
 * should be normalized to fill a signed long integer.	Typical devices
 * won't generate negative pressure, but the possibility is not precluded.
 * The pressure threshold which is considered to cause a button-click is
 * expected to be set in a Preferences program supplied by the tablet
 * vendor.  The tablet driver would send IECODE_LBUTTON-type events as
 * the pressure crossed that threshold.
 *
 * TABLETA_ButtonBits:	ti_Data is a long integer whose bits are to
 * be interpreted at the state of the first 32 buttons of the tablet.
 *
 * TABLETA_InProximity:  ti_Data is a boolean.	For tablets that support
 * proximity, they should send the {TABLETA_InProximity,FALSE} tag item
 * when the stylus is out of proximity.  One possible use we can forsee
 * is a mouse-blanking commodity which keys off this to blank the
 * mouse.  When this tag is absent, the stylus is assumed to be
 * in proximity.
 *
 * TABLETA_ResolutionX:  ti_Data is an unsigned long integer which
 * is the x-axis resolution in dots per inch.
 *
 * TABLETA_ResolutionY:  ti_Data is an unsigned long integer which
 * is the y-axis resolution in dots per inch.
 */

#define TABLETA_Dummy		(TAG_USER + 0x3A000)
#define TABLETA_TabletZ		(TABLETA_Dummy + 0x01)
#define TABLETA_RangeZ		(TABLETA_Dummy + 0x02)
#define TABLETA_AngleX		(TABLETA_Dummy + 0x03)
#define TABLETA_AngleY		(TABLETA_Dummy + 0x04)
#define TABLETA_AngleZ		(TABLETA_Dummy + 0x05)
#define TABLETA_Pressure	(TABLETA_Dummy + 0x06)
#define TABLETA_ButtonBits	(TABLETA_Dummy + 0x07)
#define TABLETA_InProximity	(TABLETA_Dummy + 0x08)
#define TABLETA_ResolutionX	(TABLETA_Dummy + 0x09)
#define TABLETA_ResolutionY	(TABLETA_Dummy + 0x0A)

/* If your window sets WA_TabletMessages to TRUE, then it will receive
 * extended IntuiMessages (struct ExtIntuiMessage) whose eim_TabletData
 * field points at a TabletData structure.  This structure contains
 * additional information about the input event.
 */

struct TabletData
{
    /* Sub-pixel position of tablet, in screen coordinates,
     * scaled to fill a UWORD fraction:
     */
    UWORD td_XFraction, td_YFraction;

    /* Current tablet coordinates along each axis: */
    ULONG td_TabletX, td_TabletY;

    /* Tablet range along each axis.  For example, if td_TabletX
     * can take values 0-999, td_RangeX should be 1000.
     */
    ULONG td_RangeX, td_RangeY;

    /* Pointer to tag-list of additional tablet attributes.
     * See <intuition/intuition.h> for the tag values.
     */
    struct TagItem *td_TagList;
};

/* If a tablet driver supplies a hook for ient_CallBack, it will be
 * invoked in the standard hook manner.  A0 will point to the Hook
 * itself, A2 will point to the InputEvent that was sent, and
 * A1 will point to a TabletHookData structure.  The InputEvent's
 * ie_EventAddress field points at the IENewTablet structure that
 * the driver supplied.
 *
 * Based on the thd_Screen, thd_Width, and thd_Height fields, the driver
 * should scale the ient_TabletX and ient_TabletY fields and store the
 * result in ient_ScaledX, ient_ScaledY, ient_ScaledXFraction, and
 * ient_ScaledYFraction.
 *
 * The tablet hook must currently return NULL.	This is the only
 * acceptable return-value under V39.
 */

struct TabletHookData
{
    /* Pointer to the active screen:
     * Note: if there are no open screens, thd_Screen will be NULL.
     * thd_Width and thd_Height will then describe an NTSC 640x400
     * screen.	Please scale accordingly.
     */
    struct Screen *thd_Screen;

    /* The width and height (measured in pixels of the active screen)
     * that your are to scale to:
     */
    ULONG thd_Width;
    ULONG thd_Height;

    /* Non-zero if the screen or something about the screen
     * changed since the last time you were invoked:
     */
    LONG thd_ScreenChanged;
};

/* Include obsolete identifiers: */
#ifndef INTUITION_IOBSOLETE_H
#include <intuition/iobsolete.h>
#endif

#endif


include/libraries/expansionbase.h

#ifndef LIBRARIES_EXPANSIONBASE_H
#define LIBRARIES_EXPANSIONBASE_H
/*
**	$VER: expansionbase.h 36.15 (21.10.1991)
**	Includes Release 44.1
**
**	Definitions for the expansion library base
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif	/* EXEC_TYPES_H */

#ifndef EXEC_LIBRARIES_H
#include <exec/libraries.h>
#endif	/* EXEC_LIBRARIES_H */

#ifndef EXEC_SEMAPHORES_H
#include <exec/semaphores.h>
#endif	/* EXEC_SEMAPHORES_H */

#ifndef LIBRARIES_CONFIGVARS_H
#include <libraries/configvars.h>
#endif	/* LIBRARIES_CONFIGVARS_H */

/* BootNodes are scanned by dos.library at startup.  Items found on the
   list are started by dos. BootNodes are added with the AddDosNode() or
   the V36 AddBootNode() calls. */
struct BootNode
{
    struct Node bn_Node;
    UWORD	bn_Flags;
    APTR	bn_DeviceNode;
};

/* expansion.library has functions to manipulate most of the information in
   ExpansionBase.  Direct access is not permitted.  Use FindConfigDev()
   to scan the board list. */
struct	ExpansionBase
{
    struct Library	LibNode;
    UBYTE	Flags;				/* read only (see below) */
    UBYTE	eb_Private01;			/* private */
    ULONG	eb_Private02;			/* private */
    ULONG	eb_Private03;			/* private */
    struct	CurrentBinding	eb_Private04;	/* private */
    struct	List	eb_Private05;		/* private */
    struct	List	MountList;	/* contains struct BootNode entries */
    /* private */
};

/* error codes */
#define EE_OK		0
#define EE_LASTBOARD	40  /* could not shut him up */
#define EE_NOEXPANSION	41  /* not enough expansion mem; board shut up */
#define EE_NOMEMORY	42  /* not enough normal memory */
#define EE_NOBOARD	43  /* no board at that address */
#define EE_BADMEM	44  /* tried to add bad memory card */

/* Flags */
#define EBB_CLOGGED	0	/* someone could not be shutup */
#define EBF_CLOGGED	(1<<0)
#define EBB_SHORTMEM	1	/* ran out of expansion mem */
#define EBF_SHORTMEM	(1<<1)
#define EBB_BADMEM	2	/* tried to add bad memory card */
#define EBF_BADMEM	(1<<2)
#define EBB_DOSFLAG	3	/* reserved for use by AmigaDOS */
#define EBF_DOSFLAG	(1<<3)
#define EBB_KICKBACK33	4	/* reserved for use by AmigaDOS */
#define EBF_KICKBACK33	(1<<4)
#define EBB_KICKBACK36	5	/* reserved for use by AmigaDOS */
#define EBF_KICKBACK36	(1<<5)
/* If the following flag is set by a floppy's bootblock code, the initial
   open of the initial shell window will be delayed until the first output
   to that shell.  Otherwise the 1.3 compatible behavior applies. */
#define EBB_SILENTSTART	6
#define EBF_SILENTSTART	(1<<6)

/* Magic kludge for CC0 use */
#define	EBB_START_CC0	7
#define	EBF_START_CC0	(1<<7)

#endif	/* LIBRARIES_EXPANSIONBASE_H */


include/resources/card.h

#ifndef	RESOURCES_CARD_H
#define RESOURCES_CARD_H 1

/*
**	$VER: card.h 1.11 (14.12.1992)
**	Includes Release 44.1
**
**	card.resource include file
**
**	(C) Copyright 1991-1999 Amiga, Inc.
**	    All Rights Reserved
**
*/
#ifndef	EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef	EXEC_NODES_H
#include <exec/nodes.h>
#endif

#ifndef	EXEC_INTERRUPTS_H
#include <exec/interrupts.h>
#endif

#define CARDRESNAME	"card.resource"

/* Structures used by the card.resource				*/

struct	CardHandle {
    struct Node cah_CardNode;
    struct Interrupt *cah_CardRemoved;
    struct Interrupt *cah_CardInserted;
    struct Interrupt *cah_CardStatus;
    UBYTE	cah_CardFlags;
};

struct	DeviceTData {
    ULONG	dtd_DTsize;	/* Size in bytes		*/
    ULONG	dtd_DTspeed;	/* Speed in nanoseconds		*/
    UBYTE	dtd_DTtype;	/* Type of card			*/
    UBYTE	dtd_DTflags;	/* Other flags			*/
};

struct	CardMemoryMap {
    UBYTE	*cmm_CommonMemory;
    UBYTE	*cmm_AttributeMemory;
    UBYTE	*cmm_IOMemory;

/* Extended for V39 - These are the size of the memory spaces above */

    ULONG	cmm_CommonMemSize;
    ULONG	cmm_AttributeMemSize;
    ULONG	cmm_IOMemSize;

};

/* CardHandle.cah_CardFlags for OwnCard() function		*/

#define	CARDB_RESETREMOVE	0
#define CARDF_RESETREMOVE	(1<<CARDB_RESETREMOVE)

#define	CARDB_IFAVAILABLE	1
#define	CARDF_IFAVAILABLE	(1<<CARDB_IFAVAILABLE)

#define CARDB_DELAYOWNERSHIP	2
#define CARDF_DELAYOWNERSHIP	(1<<CARDB_DELAYOWNERSHIP)

#define CARDB_POSTSTATUS	3
#define CARDF_POSTSTATUS	(1<<CARDB_POSTSTATUS)

/* ReleaseCreditCard() function flags				*/

#define	CARDB_REMOVEHANDLE	0
#define	CARDF_REMOVEHANDLE	(1<<CARDB_REMOVEHANDLE)

/* ReadStatus() return flags					*/

#define	CARD_STATUSB_CCDET		6
#define CARD_STATUSF_CCDET		(1<<CARD_STATUSB_CCDET)

#define CARD_STATUSB_BVD1		5
#define	CARD_STATUSF_BVD1		(1<<CARD_STATUSB_BVD1)

#define CARD_STATUSB_SC			5
#define CARD_STATUSF_SC			(1<<CARD_STATUSB_SC)

#define CARD_STATUSB_BVD2		4
#define	CARD_STATUSF_BVD2		(1<<CARD_STATUSB_BVD2)

#define CARD_STATUSB_DA			4
#define CARD_STATUSF_DA			(1<<CARD_STATUSB_DA)

#define CARD_STATUSB_WR			3
#define	CARD_STATUSF_WR			(1<<CARD_STATUSB_WR)

#define CARD_STATUSB_BSY		2
#define CARD_STATUSF_BSY		(1<<CARD_STATUSB_BSY)

#define CARD_STATUSB_IRQ		2
#define CARD_STATUSF_IRQ		(1<<CARD_STATUSB_IRQ)

/* CardProgramVoltage() defines */

#define CARD_VOLTAGE_0V		0	/* Set to default; may be the same as 5V */
#define CARD_VOLTAGE_5V		1
#define CARD_VOLTAGE_12V	2

/* CardMiscControl() defines */

#define	CARD_ENABLEB_DIGAUDIO	1
#define	CARD_ENABLEF_DIGAUDIO	(1<<CARD_ENABLEB_DIGAUDIO)

#define	CARD_DISABLEB_WP	3
#define	CARD_DISABLEF_WP	(1<<CARD_DISABLEB_WP)

/*
 * New CardMiscControl() bits for V39 card.resource.  Use these bits to set,
 * or clear status change interrupts for BVD1/SC, BVD2/DA, and BSY/IRQ.
 * Write-enable/protect change interrupts are always enabled.  The defaults
 * are unchanged (BVD1/SC is enabled, BVD2/DA is disabled, and BSY/IRQ is enabled).
 *
 * IMPORTANT -- Only set these bits for V39 card.resource or greater (check
 * resource base VERSION)
 *
 */

#define	CARD_INTB_SETCLR	7
#define	CARD_INTF_SETCLR	(1<<CARD_INTB_SETCLR)

#define	CARD_INTB_BVD1		5
#define	CARD_INTF_BVD1		(1<<CARD_INTB_BVD1)

#define	CARD_INTB_SC		5
#define	CARD_INTF_SC		(1<<CARD_INTB_SC)

#define	CARD_INTB_BVD2		4
#define	CARD_INTF_BVD2		(1<<CARD_INTB_BVD2)

#define	CARD_INTB_DA		4
#define	CARD_INTF_DA		(1<<CARD_INTB_DA)

#define	CARD_INTB_BSY		2
#define	CARD_INTF_BSY		(1<<CARD_INTB_BSY)

#define	CARD_INTB_IRQ		2
#define	CARD_INTF_IRQ		(1<<CARD_INTB_IRQ)

/* CardInterface() defines */

#define	CARD_INTERFACE_AMIGA_0	0

/*
 * Tuple for Amiga execute-in-place software (e.g., games, or other
 * such software which wants to use execute-in-place software stored
 * on a credit-card, such as a ROM card).
 *
 * See documentatin for IfAmigaXIP().
 */

#define	CISTPL_AMIGAXIP	0x91

struct	TP_AmigaXIP {
    UBYTE	TPL_CODE;
    UBYTE	TPL_LINK;
    UBYTE	TP_XIPLOC[4];
    UBYTE	TP_XIPFLAGS;
    UBYTE	TP_XIPRESRV;
    };
/*

    ; The XIPFLAGB_AUTORUN bit means that you want the machine
    ; to perform a reset if the execute-in-place card is inserted
    ; after DOS has been started.  The machine will then reset,
    ; and execute your execute-in-place code the next time around.
    ;
    ; NOTE -- this flag may be ignored on some machines, in which
    ; case the user will have to manually reset the machine in the
    ; usual way.

*/

#define	XIPFLAGSB_AUTORUN	0
#define XIPFLAGSF_AUTORUN	(1<<XIPFLAGSB_AUTORUN)

#endif	/* RESOURCES_CARD_H */


include/libraries/locale.h

#ifndef LIBRARIES_LOCALE_H
#define LIBRARIES_LOCALE_H
/*
**	$VER: locale.h 38.12 (24.2.1993)
**	Includes Release 44.1
**
**	locale.library interface structures and definitions
**
**	(C) Copyright 1991-1999 Amiga, Inc.
**	All Rights Reserved
*/

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef EXEC_NODES_H
#include <exec/nodes.h>
#endif

#ifndef EXEC_LISTS_H
#include <exec/lists.h>
#endif

#ifndef EXEC_LIBRARIES_H
#include <exec/libraries.h>
#endif

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

/*****************************************************************************/

/* constants for GetLocaleStr() */
#define DAY_1		1	/* Sunday    */
#define DAY_2		2	/* Monday    */
#define DAY_3		3	/* Tuesday   */
#define DAY_4		4	/* Wednesday */
#define DAY_5		5	/* Thursday  */
#define DAY_6		6	/* Friday    */
#define DAY_7		7	/* Saturday  */

#define ABDAY_1	8	/* Sun */
#define ABDAY_2	9	/* Mon */
#define ABDAY_3	10	/* Tue */
#define ABDAY_4	11	/* Wed */
#define ABDAY_5	12	/* Thu */
#define ABDAY_6	13	/* Fri */
#define ABDAY_7	14	/* Sat */

#define MON_1		15	/* January   */
#define MON_2		16	/* February  */
#define MON_3		17	/* March     */
#define MON_4		18	/* April     */
#define MON_5		19	/* May	     */
#define MON_6		20	/* June      */
#define MON_7		21	/* July      */
#define MON_8		22	/* August    */
#define MON_9		23	/* September */
#define MON_10		24	/* October   */
#define MON_11		25	/* November  */
#define MON_12		26	/* December  */

#define ABMON_1	27	/* Jan */
#define ABMON_2	28	/* Feb */
#define ABMON_3	29	/* Mar */
#define ABMON_4	30	/* Apr */
#define ABMON_5	31	/* May */
#define ABMON_6	32	/* Jun */
#define ABMON_7	33	/* Jul */
#define ABMON_8	34	/* Aug */
#define ABMON_9	35	/* Sep */
#define ABMON_10	36	/* Oct */
#define ABMON_11	37	/* Nov */
#define ABMON_12	38	/* Dec */

#define YESSTR		39	/* affirmative response for yes/no queries */
#define NOSTR		40	/* negative response for yes/no queries    */

#define AM_STR		41	/* AM */
#define PM_STR		42	/* PM */

#define SOFTHYPHEN	43	/* soft hyphenation */
#define HARDHYPHEN	44	/* hard hyphenation */

#define OPENQUOTE	45	/* start of quoted block */
#define CLOSEQUOTE	46	/* end of quoted block	 */

#define YESTERDAYSTR	47	/* Yesterday */
#define TODAYSTR	48	/* Today     */
#define TOMORROWSTR	49	/* Tomorrow  */
#define FUTURESTR	50	/* Future    */

#define MAXSTRMSG	51	/* current number of defined strings */

/*****************************************************************************/

/* OpenLibrary("locale.library",0) returns a pointer to this structure */
struct LocaleBase
{
    struct Library lb_LibNode;
    BOOL	   lb_SysPatches;   /* TRUE if locale installed its patches */
};

/*****************************************************************************/

/* This structure must only be allocated by locale.library and is READ-ONLY! */
struct Locale
{
    STRPTR  loc_LocaleName;	      /* locale's name		     */
    STRPTR  loc_LanguageName;	      /* language of this locale     */
    STRPTR  loc_PrefLanguages[10];    /* preferred languages	     */
    ULONG   loc_Flags;		      /* always 0 for now	     */

    ULONG   loc_CodeSet;	      /* always 0 for now	     */
    ULONG   loc_CountryCode;	      /* user's country code	     */
    ULONG   loc_TelephoneCode;	      /* country's telephone code    */
    LONG    loc_GMTOffset;	      /* minutes from GMT	     */
    UBYTE   loc_MeasuringSystem;      /* what measuring system?      */
    UBYTE   loc_CalendarType;	      /* what calendar type?	     */
    UBYTE   loc_Reserved0[2];

    STRPTR  loc_DateTimeFormat;       /* regular date & time format  */
    STRPTR  loc_DateFormat;	      /* date format by itself	     */
    STRPTR  loc_TimeFormat;	      /* time format by itself	     */

    STRPTR  loc_ShortDateTimeFormat;  /* short date & time format    */
    STRPTR  loc_ShortDateFormat;      /* short date format by itself */
    STRPTR  loc_ShortTimeFormat;      /* short time format by itself */

    /* for numeric values */
    STRPTR  loc_DecimalPoint;	      /* character before the decimals */
    STRPTR  loc_GroupSeparator;       /* separates groups of digits    */
    STRPTR  loc_FracGroupSeparator;   /* separates groups of digits    */
    UBYTE  *loc_Grouping;	      /* size of each group	       */
    UBYTE  *loc_FracGrouping;	      /* size of each group	       */

    /* for monetary values */
    STRPTR  loc_MonDecimalPoint;
    STRPTR  loc_MonGroupSeparator;
    STRPTR  loc_MonFracGroupSeparator;
    UBYTE  *loc_MonGrouping;
    UBYTE  *loc_MonFracGrouping;
    UBYTE   loc_MonFracDigits;	      /* digits after the decimal point   */
    UBYTE   loc_MonIntFracDigits;     /* for international representation */
    UBYTE   loc_Reserved1[2];

    /* for currency symbols */
    STRPTR  loc_MonCS;		      /* currency symbol	      */
    STRPTR  loc_MonSmallCS;	      /* symbol for small amounts     */
    STRPTR  loc_MonIntCS;	      /* internationl (ISO 4217) code */

    /* for positive monetary values */
    STRPTR  loc_MonPositiveSign;      /* indicate positive money value	 */
    UBYTE   loc_MonPositiveSpaceSep;  /* determine if separated by space */
    UBYTE   loc_MonPositiveSignPos;   /* position of positive sign	 */
    UBYTE   loc_MonPositiveCSPos;     /* position of currency symbol	 */
    UBYTE   loc_Reserved2;

    /* for negative monetary values */
    STRPTR  loc_MonNegativeSign;      /* indicate negative money value	 */
    UBYTE   loc_MonNegativeSpaceSep;  /* determine if separated by space */
    UBYTE   loc_MonNegativeSignPos;   /* position of negative sign	 */
    UBYTE   loc_MonNegativeCSPos;     /* position of currency symbol	 */
    UBYTE   loc_Reserved3;
};

/* constants for Locale.loc_MeasuringSystem */
#define MS_ISO		0	/* international metric system */
#define MS_AMERICAN	1	/* american system	       */
#define MS_IMPERIAL	2	/* imperial system	       */
#define MS_BRITISH	3	/* british system	       */

/* constants for Locale.loc_CalendarType */
#define CT_7SUN 0   /* 7 days a week, Sunday is the first day	 */
#define CT_7MON 1   /* 7 days a week, Monday is the first day	 */
#define CT_7TUE 2   /* 7 days a week, Tuesday is the first day	 */
#define CT_7WED 3   /* 7 days a week, Wednesday is the first day */
#define CT_7THU 4   /* 7 days a week, Thursday is the first day  */
#define CT_7FRI 5   /* 7 days a week, Friday is the first day	 */
#define CT_7SAT 6   /* 7 days a week, Saturday is the first day  */

/* constants for Locale.loc_MonPositiveSpaceSep and Locale.loc_MonNegativeSpaceSep */
#define SS_NOSPACE 0  /* cur. symbol is NOT separated from value with a space */
#define SS_SPACE   1  /* cur. symbol IS separated from value with a space     */

/* constants for Locale.loc_MonPositiveSignPos and Locale.loc_MonNegativeSignPos */
#define SP_PARENS    0	/* () surround the quantity and currency_symbol   */
#define SP_PREC_ALL  1	/* sign string comes before amount and symbol	  */
#define SP_SUCC_ALL  2	/* sign string comes after amount and symbol	  */
#define SP_PREC_CURR 3	/* sign string comes right before currency symbol */
#define SP_SUCC_CURR 4	/* sign string comes right after currency symbol  */

/* constants for Locale.loc_MonPositiveCSPos and Locale.loc_MonNegativeCSPos */
#define CSP_PRECEDES 0	/* currency symbol comes before value */
#define CSP_SUCCEEDS 1	/* currency symbol comes after value  */

/* elements of the byte arrays pointed to by:
 *   Locale.loc_Grouping
 *   Locale.loc_FracGrouping
 *   Locale.loc_MonGrouping
 *   Locale.loc_MonFracGrouping
 * are interpreted as follows:
 *
 *    255     indicates that no further grouping is to be performed
 *    0       indicates that the previous element is to be repeatedly used
 *	      for the remainder of the digits
 *    <other> the number of digits that comprises the current group
 */

/*****************************************************************************/

/* Tags for OpenCatalog() */
#define OC_TagBase	   (TAG_USER + 0x90000)
#define OC_BuiltInLanguage OC_TagBase+1   /* language of built-in strings    */
#define OC_BuiltInCodeSet  OC_TagBase+2   /* code set of built-in strings    */
#define OC_Version	   OC_TagBase+3   /* catalog version number required */
#define OC_Language	   OC_TagBase+4   /* preferred language of catalog   */

/*****************************************************************************/

/* Comparison types for StrnCmp() */
#define SC_ASCII    0
#define SC_COLLATE1 1
#define SC_COLLATE2 2

/*****************************************************************************/

/* This structure must only be allocated by locale.library and is READ-ONLY! */
struct Catalog
{
    struct Node cat_Link;	/* for internal linkage    */
    UWORD	cat_Pad;	/* to longword align	   */
    STRPTR	cat_Language;	/* language of the catalog */
    ULONG	cat_CodeSet;	/* currently always 0	   */
    UWORD	cat_Version;	/* version of the catalog  */
    UWORD	cat_Revision;	/* revision of the catalog */
};

/*****************************************************************************/

#endif	/* LIBRARIES_LOCALE_H */


include/devices/cd.h

#ifndef DEVICES_CD_H
#define DEVICES_CD_H
/*
**	$VER: cd.h 1.11 (12.8.1993)
**	Includes Release 44.1
**
**	cd.device include file
**
**	(C) Copyright 1992-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#include <exec/types.h>
#include <exec/nodes.h>

/**************************************************************************
 *									  *
 *   CD Commands							  *
 *									  *
 **************************************************************************/

#define CD_RESET	     1
#define CD_READ	     2
#define CD_WRITE	     3
#define CD_UPDATE	     4
#define CD_CLEAR	     5
#define CD_STOP	     6
#define CD_START	     7
#define CD_FLUSH	     8
#define CD_MOTOR	     9
#define CD_SEEK	    10
#define CD_FORMAT	    11
#define CD_REMOVE	    12
#define CD_CHANGENUM	    13
#define CD_CHANGESTATE	    14
#define CD_PROTSTATUS	    15

#define CD_GETDRIVETYPE     18
#define CD_GETNUMTRACKS     19
#define CD_ADDCHANGEINT     20
#define CD_REMCHANGEINT     21
#define CD_GETGEOMETRY	    22
#define CD_EJECT	    23

#define CD_INFO	    32
#define CD_CONFIG	    33
#define CD_TOCMSF	    34
#define CD_TOCLSN	    35

#define CD_READXL	    36

#define CD_PLAYTRACK	    37
#define CD_PLAYMSF	    38
#define CD_PLAYLSN	    39
#define CD_PAUSE	    40
#define CD_SEARCH	    41

#define CD_QCODEMSF	    42
#define CD_QCODELSN	    43
#define CD_ATTENUATE	    44

#define CD_ADDFRAMEINT	    45
#define CD_REMFRAMEINT	    46

/**************************************************************************
 *									  *
 *   Device Driver Error Codes						  *
 *									  *
 **************************************************************************/

#define CDERR_OPENFAIL	     (-1) /* device/unit failed to open	  */
#define CDERR_ABORTED	     (-2) /* request terminated early		  */
#define CDERR_NOCMD	     (-3) /* command not supported by device	  */
#define CDERR_BADLENGTH      (-4) /* invalid length (IO_LENGTH/IO_OFFSET) */
#define CDERR_BADADDRESS     (-5) /* invalid address (IO_DATA misaligned) */
#define CDERR_UNITBUSY	     (-6) /* device opens ok, but unit is busy	  */
#define CDERR_SELFTEST	     (-7) /* hardware failed self-test		  */

#define CDERR_NotSpecified   20   /* general catchall			  */
#define CDERR_NoSecHdr	     21   /* couldn't even find a sector	  */
#define CDERR_BadSecPreamble 22   /* sector looked wrong		  */
#define CDERR_BadSecID	     23   /* ditto				  */
#define CDERR_BadHdrSum      24   /* header had incorrect checksum	  */
#define CDERR_BadSecSum      25   /* data had incorrect checksum	  */
#define CDERR_TooFewSecs     26   /* couldn't find enough sectors	  */
#define CDERR_BadSecHdr      27   /* another "sector looked wrong"	  */
#define CDERR_WriteProt      28   /* can't write to a protected disk	  */
#define CDERR_NoDisk	     29   /* no disk in the drive		  */
#define CDERR_SeekError      30   /* couldn't find track 0		  */
#define CDERR_NoMem	     31   /* ran out of memory			  */
#define CDERR_BadUnitNum     32   /* asked for a unit > NUMUNITS	  */
#define CDERR_BadDriveType   33   /* not a drive cd.device understands	  */
#define CDERR_DriveInUse     34   /* someone else allocated the drive	  */
#define CDERR_PostReset      35   /* user hit reset; awaiting doom	  */
#define CDERR_BadDataType    36   /* data on disk is wrong type	  */
#define CDERR_InvalidState   37   /* invalid cmd under current conditions */

#define CDERR_Phase	     42   /* illegal or unexpected SCSI phase	  */
#define CDERR_NoBoard	     50   /* open failed for non-existant board   */

/**************************************************************************
 *									  *
 * Configuration							  *
 *									  *
 *	 The drive is configured by TagList items defined as follows:	  *
 *									  *
 **************************************************************************/

#define TAGCD_PLAYSPEED	0x0001
#define TAGCD_READSPEED	0x0002
#define TAGCD_READXLSPEED	0x0003
#define TAGCD_SECTORSIZE	0x0004
#define TAGCD_XLECC		0x0005
#define TAGCD_EJECTRESET	0x0006

/**************************************************************************
 *									  *
 * Information								  *
 *									  *
 *	Information/Status structure describes current speed settings	  *
 *	for read and play commands, sector size, audio attenuation	  *
 *	precision, and drive status.					  *
 *									  *
 **************************************************************************/

struct CDInfo {
                /*				      Default	  */
    UWORD   PlaySpeed;	    /* Audio play speed	      (75)	  */
    UWORD   ReadSpeed;	    /* Data-rate of CD_READ command   (Max)	  */
    UWORD   ReadXLSpeed;    /* Data-rate of CD_READXL command (75)	  */
    UWORD   SectorSize;     /* Number of bytes per sector     (2048)	  */
    UWORD   XLECC;	    /* CDXL ECC enabled/disabled		  */
    UWORD   EjectReset;     /* Reset on eject enabled/disabled		  */
    UWORD   Reserved1[4];   /* Reserved for future expansion		  */

    UWORD   MaxSpeed;	    /* Maximum speed drive can handle (75, 150)   */
    UWORD   AudioPrecision; /* 0 = no attenuator, 1 = mute only,	  */
                /* other = (# levels - 1)			  */
    UWORD   Status;	    /* See flags below				  */
    UWORD   Reserved2[4];   /* Reserved for future expansion		  */
    };

/* Flags for Status */

#define CDSTSB_CLOSED	 0 /* Drive door is closed			  */
#define CDSTSB_DISK	 1 /* A disk has been detected			  */
#define CDSTSB_SPIN	 2 /* Disk is spinning (motor is on)		  */
#define CDSTSB_TOC	 3 /* Table of contents read.  Disk is valid.	  */
#define CDSTSB_CDROM	 4 /* Track 1 contains CD-ROM data		  */
#define CDSTSB_PLAYING	 5 /* Audio is playing				  */
#define CDSTSB_PAUSED	 6 /* Pause mode (pauses on play command)	  */
#define CDSTSB_SEARCH	 7 /* Search mode (Fast Forward/Fast Reverse)	  */
#define CDSTSB_DIRECTION 8 /* Search direction (0 = Forward, 1 = Reverse) */

#define CDSTSF_CLOSED	 0x0001
#define CDSTSF_DISK	 0x0002
#define CDSTSF_SPIN	 0x0004
#define CDSTSF_TOC	 0x0008
#define CDSTSF_CDROM	 0x0010
#define CDSTSF_PLAYING	 0x0020
#define CDSTSF_PAUSED	 0x0040
#define CDSTSF_SEARCH	 0x0080
#define CDSTSF_DIRECTION 0x0100

/* Modes for CD_SEARCH */

#define CDMODE_NORMAL	0	  /* Normal play at current play speed	  */
#define CDMODE_FFWD	1	  /* Fast forward play (skip-play forward)*/
#define CDMODE_FREV	2	  /* Fast reverse play (skip-play reverse)*/

/**************************************************************************
 *									  *
 * Position Information						  *
 *									  *
 *	Position information can be described in two forms: MSF and LSN   *
 *	form.  MSF (Minutes, Seconds, Frames) form is a time encoding.	  *
 *	LSN (Logical Sector Number) form is frame (sector) count.	  *
 *	The desired form is selected using the io_Flags field of the	  *
 *	IOStdReq structure.  The flags and the union are described	  *
 *	below.								  *
 *									  *
 **************************************************************************/

struct RMSF {

    UBYTE   Reserved;	    /* Reserved (always zero) */
    UBYTE   Minute;	    /* Minutes (0-72ish)      */
    UBYTE   Second;	    /* Seconds (0-59)	      */
    UBYTE   Frame;	    /* Frame   (0-74)	      */
    };

union LSNMSF {

    struct  RMSF MSF;	    /* Minute, Second, Frame  */
    ULONG   LSN;	    /* Logical Sector Number  */
    };

/**************************************************************************
 *									  *
 * CD Transfer Lists							  *
 *									  *
 *	A CDXL node is a double link node; however only single linkage	  *
 *	is used by the device driver.  If you wish to construct a	  *
 *	transfer list manually, it is only neccessary to define the	  *
 *	mln_Succ pointer of the MinNode.  You may also use the Exec	  *
 *	list functions by defining a List or MinList structure and by	  *
 *	using the AddHead/AddTail functions to create the list.  This	  *
 *	will create a double-linked list.  Although a double-linked	  *
 *	list is not required by the device driver, you may wish use it	  *
 *	for your own purposes.	Don't forget to initialize the		  *
 *	the List/MinList before using it!				  *
 *									  *
 **************************************************************************/

struct	CDXL {

    struct MinNode    Node;	       /* double linkage		  */
    char	     *Buffer;	       /* data destination (word aligned) */
    LONG	      Length;	       /* must be even # bytes		  */
    LONG	      Actual;	       /* bytes transferred		  */
    APTR	      IntData;	       /* interrupt server data segment   */
    VOID	      (*IntCode)();    /* interrupt server code entry	  */
    };

/**************************************************************************
 *									  *
 * CD Table of Contents						  *
 *									  *
 *	The CD_TOC command returns an array of CDTOC entries.		  *
 *	Entry zero contains summary information describing how many	  *
 *	tracks the disk has and the play-time of the disk.		  *
 *	Entries 1 through N (N = Number of tracks on disk) contain	  *
 *	information about the track.					  *
 *									  *
 **************************************************************************/

struct TOCSummary {

    UBYTE	 FirstTrack; /* First track on disk (always 1)		  */
    UBYTE	 LastTrack;  /* Last track on disk			  */
    union LSNMSF LeadOut;    /* Beginning of lead-out track (end of disk) */
    };

struct TOCEntry {

    UBYTE	 CtlAdr;     /* Q-Code info		     */
    UBYTE	 Track;      /* Track number		     */
    union LSNMSF Position;   /* Start position of this track */
    };

union CDTOC {

    struct TOCSummary Summary;	/* First entry (0) is summary information */
    struct TOCEntry   Entry;	/* Entries 1-N are track entries	  */
    };

/**************************************************************************
 *									  *
 * Q-Code Packets							  *
 *									  *
 *	Q-Code packets are only returned when audio is playing.	  *
 *	Currently, only position packets are returned (ADR_POSITION)	  *
 *	The other ADR_ types are almost never encoded on the disk	  *
 *	and are of little use anyway.  To avoid making the QCode	  *
 *	structure a union, these other ADR_ structures are not defined.   *
 *									  *
 **************************************************************************/

struct QCode {

    UBYTE	 CtlAdr;	/* Data type / QCode type	    */
    UBYTE	 Track;	/* Track number		    */
    UBYTE	 Index;	/* Track subindex number	    */
    UBYTE	 Zero;		/* The "Zero" byte of Q-Code packet */
    union LSNMSF TrackPosition; /* Position from start of track     */
    union LSNMSF DiskPosition;	/* Position from start of disk	    */
    };

#define CTLADR_CTLMASK 0xF0   /* Control field */

#define CTL_CTLMASK    0xD0   /* To be ANDed with CtlAdr before compared  */

#define CTL_2AUD       0x00   /* 2 audio channels without preemphasis	  */
#define CTL_2AUDEMPH   0x10   /* 2 audio channels with preemphasis	  */
#define CTL_4AUD       0x80   /* 4 audio channels without preemphasis	  */
#define CTL_4AUDEMPH   0x90   /* 4 audio channels with preemphasis	  */
#define CTL_DATA       0x40   /* CD-ROM Data				  */

#define CTL_COPYMASK   0x20   /* To be ANDed with CtlAdr before compared  */

#define CTL_COPY       0x20   /* When true, this audio/data can be copied */

#define CTLADR_ADRMASK 0x0F   /* Address field				  */

#define ADR_POSITION   0x01   /* Q-Code is position information	  */
#define ADR_UPC        0x02   /* Q-Code is UPC information (not used)	  */
#define ADR_ISRC       0x03   /* Q-Code is ISRC (not used)		  */
#define ADR_HYBRID     0x05   /* This disk is a hybrid disk		  */

#endif


include/hardware/cia.h

#ifndef	HARDWARE_CIA_H
#define	HARDWARE_CIA_H
/*
**	$VER: cia.h 39.1 (18.9.1992)
**	Includes Release 44.1
**
**	registers and bits in the Complex Interface Adapter (CIA) chip
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif /* EXEC_TYPES_H */

/*
 * ciaa is on an ODD address (e.g. the low byte) -- $bfe001
 * ciab is on an EVEN address (e.g. the high byte) -- $bfd000
 *
 * do this to get the definitions:
 *    extern struct CIA ciaa, ciab;
 */

struct CIA {
    UBYTE   ciapra;
    UBYTE   pad0[0xff];
    UBYTE   ciaprb;
    UBYTE   pad1[0xff];
    UBYTE   ciaddra;
    UBYTE   pad2[0xff];
    UBYTE   ciaddrb;
    UBYTE   pad3[0xff];
    UBYTE   ciatalo;
    UBYTE   pad4[0xff];
    UBYTE   ciatahi;
    UBYTE   pad5[0xff];
    UBYTE   ciatblo;
    UBYTE   pad6[0xff];
    UBYTE   ciatbhi;
    UBYTE   pad7[0xff];
    UBYTE   ciatodlow;
    UBYTE   pad8[0xff];
    UBYTE   ciatodmid;
    UBYTE   pad9[0xff];
    UBYTE   ciatodhi;
    UBYTE   pad10[0xff];
    UBYTE   unusedreg;
    UBYTE   pad11[0xff];
    UBYTE   ciasdr;
    UBYTE   pad12[0xff];
    UBYTE   ciaicr;
    UBYTE   pad13[0xff];
    UBYTE   ciacra;
    UBYTE   pad14[0xff];
    UBYTE   ciacrb;
};

/* interrupt control register bit numbers */
#define CIAICRB_TA	0
#define CIAICRB_TB	1
#define CIAICRB_ALRM	2
#define CIAICRB_SP	3
#define CIAICRB_FLG	4
#define CIAICRB_IR	7
#define CIAICRB_SETCLR	7

/* control register A bit numbers */
#define CIACRAB_START	0
#define CIACRAB_PBON	1
#define CIACRAB_OUTMODE 2
#define CIACRAB_RUNMODE 3
#define CIACRAB_LOAD	4
#define CIACRAB_INMODE	5
#define CIACRAB_SPMODE	6
#define CIACRAB_TODIN	7

/* control register B bit numbers */
#define CIACRBB_START	0
#define CIACRBB_PBON	1
#define CIACRBB_OUTMODE 2
#define CIACRBB_RUNMODE 3
#define CIACRBB_LOAD	4
#define CIACRBB_INMODE0 5
#define CIACRBB_INMODE1 6
#define CIACRBB_ALARM	7

/* interrupt control register masks */
#define CIAICRF_TA	(1L<<CIAICRB_TA)
#define CIAICRF_TB	(1L<<CIAICRB_TB)
#define CIAICRF_ALRM	(1L<<CIAICRB_ALRM)
#define CIAICRF_SP	(1L<<CIAICRB_SP)
#define CIAICRF_FLG	(1L<<CIAICRB_FLG)
#define CIAICRF_IR	(1L<<CIAICRB_IR)
#define CIAICRF_SETCLR	(1L<<CIAICRB_SETCLR)

/* control register A register masks */
#define CIACRAF_START	(1L<<CIACRAB_START)
#define CIACRAF_PBON	(1L<<CIACRAB_PBON)
#define CIACRAF_OUTMODE (1L<<CIACRAB_OUTMODE)
#define CIACRAF_RUNMODE (1L<<CIACRAB_RUNMODE)
#define CIACRAF_LOAD	(1L<<CIACRAB_LOAD)
#define CIACRAF_INMODE	(1L<<CIACRAB_INMODE)
#define CIACRAF_SPMODE	(1L<<CIACRAB_SPMODE)
#define CIACRAF_TODIN	(1L<<CIACRAB_TODIN)

/* control register B register masks */
#define CIACRBF_START	(1L<<CIACRBB_START)
#define CIACRBF_PBON	(1L<<CIACRBB_PBON)
#define CIACRBF_OUTMODE (1L<<CIACRBB_OUTMODE)
#define CIACRBF_RUNMODE (1L<<CIACRBB_RUNMODE)
#define CIACRBF_LOAD	(1L<<CIACRBB_LOAD)
#define CIACRBF_INMODE0 (1L<<CIACRBB_INMODE0)
#define CIACRBF_INMODE1 (1L<<CIACRBB_INMODE1)
#define CIACRBF_ALARM	(1L<<CIACRBB_ALARM)

/* control register B INMODE masks */
#define CIACRBF_IN_PHI2 0
#define CIACRBF_IN_CNT	(CIACRBF_INMODE0)
#define CIACRBF_IN_TA	(CIACRBF_INMODE1)
#define CIACRBF_IN_CNT_TA  (CIACRBF_INMODE0|CIACRBF_INMODE1)

/*
 * Port definitions -- what each bit in a cia peripheral register is tied to
 */

/* ciaa port A (0xbfe001) */
#define CIAB_GAMEPORT1	(7)   /* gameport 1, pin 6 (fire button*) */
#define CIAB_GAMEPORT0	(6)   /* gameport 0, pin 6 (fire button*) */
#define CIAB_DSKRDY	(5)   /* disk ready* */
#define CIAB_DSKTRACK0	(4)   /* disk on track 00* */
#define CIAB_DSKPROT	(3)   /* disk write protect* */
#define CIAB_DSKCHANGE	(2)   /* disk change* */
#define CIAB_LED	(1)   /* led light control (0==>bright) */
#define CIAB_OVERLAY	(0)   /* memory overlay bit */

/* ciaa port B (0xbfe101) -- parallel port */

/* ciab port A (0xbfd000) -- serial and printer control */
#define CIAB_COMDTR	(7)   /* serial Data Terminal Ready* */
#define CIAB_COMRTS	(6)   /* serial Request to Send* */
#define CIAB_COMCD	(5)   /* serial Carrier Detect* */
#define CIAB_COMCTS	(4)   /* serial Clear to Send* */
#define CIAB_COMDSR	(3)   /* serial Data Set Ready* */
#define CIAB_PRTRSEL	(2)   /* printer SELECT */
#define CIAB_PRTRPOUT	(1)   /* printer paper out */
#define CIAB_PRTRBUSY	(0)   /* printer busy */

/* ciab port B (0xbfd100) -- disk control */
#define CIAB_DSKMOTOR	(7)   /* disk motorr* */
#define CIAB_DSKSEL3	(6)   /* disk select unit 3* */
#define CIAB_DSKSEL2	(5)   /* disk select unit 2* */
#define CIAB_DSKSEL1	(4)   /* disk select unit 1* */
#define CIAB_DSKSEL0	(3)   /* disk select unit 0* */
#define CIAB_DSKSIDE	(2)   /* disk side select* */
#define CIAB_DSKDIREC	(1)   /* disk direction of seek* */
#define CIAB_DSKSTEP	(0)   /* disk step heads* */

/* ciaa port A (0xbfe001) */
#define CIAF_GAMEPORT1	(1L<<7)
#define CIAF_GAMEPORT0	(1L<<6)
#define CIAF_DSKRDY	(1L<<5)
#define CIAF_DSKTRACK0	(1L<<4)
#define CIAF_DSKPROT	(1L<<3)
#define CIAF_DSKCHANGE	(1L<<2)
#define CIAF_LED	(1L<<1)
#define CIAF_OVERLAY	(1L<<0)

/* ciaa port B (0xbfe101) -- parallel port */

/* ciab port A (0xbfd000) -- serial and printer control */
#define CIAF_COMDTR	(1L<<7)
#define CIAF_COMRTS	(1L<<6)
#define CIAF_COMCD	(1L<<5)
#define CIAF_COMCTS	(1L<<4)
#define CIAF_COMDSR	(1L<<3)
#define CIAF_PRTRSEL	(1L<<2)
#define CIAF_PRTRPOUT	(1L<<1)
#define CIAF_PRTRBUSY	(1L<<0)

/* ciab port B (0xbfd100) -- disk control */
#define CIAF_DSKMOTOR	(1L<<7)
#define CIAF_DSKSEL3	(1L<<6)
#define CIAF_DSKSEL2	(1L<<5)
#define CIAF_DSKSEL1	(1L<<4)
#define CIAF_DSKSEL0	(1L<<3)
#define CIAF_DSKSIDE	(1L<<2)
#define CIAF_DSKDIREC	(1L<<1)
#define CIAF_DSKSTEP	(1L<<0)

#endif	/* HARDWARE_CIA_H */


include/intuition/classes.h

#ifndef	INTUITION_CLASSES_H
#define INTUITION_CLASSES_H
/*
**  $VER: classes.h 40.0 (15.2.1994)
**  Includes Release 44.1
**
**  Used only by class implementors
**
**  (C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
*/

/*****************************************************************************/

#ifndef	EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef	EXEC_LIBRARIES_H
#include <exec/libraries.h>
#endif

#ifndef UTILITY_HOOKS_H
#include <utility/hooks.h>
#endif

#ifndef	INTUITION_CLASSUSR_H
#include <intuition/classusr.h>
#endif

/*****************************************************************************/
/***************** "White Box" access to struct IClass ***********************/
/*****************************************************************************/

/* This structure is READ-ONLY, and allocated only by Intuition */
typedef struct IClass
{
    struct Hook		 cl_Dispatcher;		/* Class dispatcher */
    ULONG		 cl_Reserved;		/* Must be 0  */
    struct IClass	*cl_Super;		/* Pointer to superclass */
    ClassID		 cl_ID;			/* Class ID */

    UWORD		 cl_InstOffset;		/* Offset of instance data */
    UWORD		 cl_InstSize;		/* Size of instance data */

    ULONG		 cl_UserData;		/* Class global data */
    ULONG		 cl_SubclassCount;	/* Number of subclasses */
    ULONG		 cl_ObjectCount;	/* Number of objects */
    ULONG		 cl_Flags;

} Class;

#define	CLF_INLIST	0x00000001L
    /* class is in public class list */

/*****************************************************************************/

/* add offset for instance data to an object handle */
#define INST_DATA(cl,o)		((void *)(((UBYTE *)o)+cl->cl_InstOffset))

/*****************************************************************************/

/* sizeof the instance data for a given class */
#define SIZEOF_INSTANCE(cl)	((cl)->cl_InstOffset + (cl)->cl_InstSize \
            + sizeof (struct _Object))

/*****************************************************************************/
/***************** "White box" access to struct _Object **********************/
/*****************************************************************************/

/* We have this, the instance data of the root class, PRECEDING the "object".
 * This is so that Gadget objects are Gadget pointers, and so on.  If this
 * structure grows, it will always have o_Class at the end, so the macro
 * OCLASS(o) will always have the same offset back from the pointer returned
 * from NewObject().
 *
 * This data structure is subject to change.  Do not use the o_Node embedded
 * structure. */
struct _Object
{
    struct MinNode	 o_Node;
    struct IClass	*o_Class;

};

/*****************************************************************************/

/* convenient typecast	*/
#define _OBJ(o)			((struct _Object *)(o))

/* get "public" handle on baseclass instance from real beginning of obj data */
#define BASEOBJECT(_obj)	((Object *)(_OBJ(_obj)+1))

/* get back to object data struct from public handle */
#define _OBJECT(o)		(_OBJ(o) - 1)

/* get class pointer from an object handle	*/
#define OCLASS(o)		((_OBJECT(o))->o_Class)

/*****************************************************************************/

/* BOOPSI class libraries should use this structure as the base for their
 * library data.  This allows developers to obtain the class pointer for
 * performing object-less inquiries. */
struct ClassLibrary
{
    struct Library	 cl_Lib;	/* Embedded library */
    UWORD		 cl_Pad;	/* Align the structure */
    Class		*cl_Class;	/* Class pointer */

};

/*****************************************************************************/

#endif


include/gadgets/texteditor.h

#ifndef GADGETS_TEXTEDITOR_H
#define GADGETS_TEXTEDITOR_H
/*
**	$VER: texteditor.h 44.1 (19.10.1999)
**	Includes Release 44.1
**
**	Definitions for texteditor.gadget BOOPSI class
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

/*****************************************************************************/

#ifndef REACTION_REACTION_H
#include <reaction/reaction.h>
#endif

#ifndef INTUITION_GADGETCLASS_H
#include <intuition/gadgetclass.h>
#endif

#ifndef IMAGES_BEVEL_H
#include <images/bevel.h>
#endif

/*****************************************************************************/

#define   TEXTEDITOR_Dummy   (REACTION_Dummy + 0x26000)

#define   GA_TEXTEDITOR_AreaMarked        (TEXTEDITOR_Dummy + 0x14)
#define   GA_TEXTEDITOR_ColorMap          (TEXTEDITOR_Dummy + 0x2f)
#define   GA_TEXTEDITOR_Contents          (TEXTEDITOR_Dummy + 0x02)
#define   GA_TEXTEDITOR_CursorX           (TEXTEDITOR_Dummy + 0x04)
#define   GA_TEXTEDITOR_CursorY           (TEXTEDITOR_Dummy + 0x05)
#define   GA_TEXTEDITOR_DoubleClickHook   (TEXTEDITOR_Dummy + 0x06)
#define   GA_TEXTEDITOR_ExportHook        (TEXTEDITOR_Dummy + 0x08)
#define   GA_TEXTEDITOR_ExportWrap        (TEXTEDITOR_Dummy + 0x09)
#define   GA_TEXTEDITOR_FixedFont         (TEXTEDITOR_Dummy + 0x0a)
#define   GA_TEXTEDITOR_Flow              (TEXTEDITOR_Dummy + 0x0b)
#define   GA_TEXTEDITOR_HasChanged        (TEXTEDITOR_Dummy + 0x0c)
#define   GA_TEXTEDITOR_HorizontalScroll  (TEXTEDITOR_Dummy + 0x2d) /* Private and experimental! */
#define   GA_TEXTEDITOR_ImportHook        (TEXTEDITOR_Dummy + 0x0e)
#define   GA_TEXTEDITOR_ImportWrap        (TEXTEDITOR_Dummy + 0x10)
#define   GA_TEXTEDITOR_InsertMode        (TEXTEDITOR_Dummy + 0x0f)
#define   GA_TEXTEDITOR_KeyBindings       (TEXTEDITOR_Dummy + 0x11)
#define   GA_TEXTEDITOR_NumLock           (TEXTEDITOR_Dummy + 0x18)
#define   GA_TEXTEDITOR_Pen               (TEXTEDITOR_Dummy + 0x2e)
#define   GA_TEXTEDITOR_PopWindow_Open    (TEXTEDITOR_Dummy + 0x03) /* Private!!! */
#define   GA_TEXTEDITOR_Prop_DeltaFactor  (TEXTEDITOR_Dummy + 0x0d)
#define   GA_TEXTEDITOR_Prop_Entries      (TEXTEDITOR_Dummy + 0x15)
#define   GA_TEXTEDITOR_Prop_First        (TEXTEDITOR_Dummy + 0x20)
#define   GA_TEXTEDITOR_Prop_Release      (TEXTEDITOR_Dummy + 0x01) /* Private!!! */
#define   GA_TEXTEDITOR_Prop_Visible      (TEXTEDITOR_Dummy + 0x16)
#define   GA_TEXTEDITOR_Quiet             (TEXTEDITOR_Dummy + 0x17)
#define   GA_TEXTEDITOR_ReadOnly          (TEXTEDITOR_Dummy + 0x19)
#define   GA_TEXTEDITOR_RedoAvailable     (TEXTEDITOR_Dummy + 0x13)
#define   GA_TEXTEDITOR_Separator         (TEXTEDITOR_Dummy + 0x2c)
#define   GA_TEXTEDITOR_StyleBold         (TEXTEDITOR_Dummy + 0x1c)
#define   GA_TEXTEDITOR_StyleItalic       (TEXTEDITOR_Dummy + 0x1d)
#define   GA_TEXTEDITOR_StyleUnderline    (TEXTEDITOR_Dummy + 0x1e)
#define   GA_TEXTEDITOR_TypeAndSpell      (TEXTEDITOR_Dummy + 0x07)
#define   GA_TEXTEDITOR_UndoAvailable     (TEXTEDITOR_Dummy + 0x12)
#define   GA_TEXTEDITOR_WrapBorder        (TEXTEDITOR_Dummy + 0x21)

#undef    TEXTEDITOR_Dummy
#define   TEXTEDITOR_Dummy   (0x45000)

#define   GM_TEXTEDITOR_AddKeyBindings    (TEXTEDITOR_Dummy + 0x22)
#define   GM_TEXTEDITOR_ARexxCmd          (TEXTEDITOR_Dummy + 0x23)
#define   GM_TEXTEDITOR_BlockInfo         (TEXTEDITOR_Dummy + 0x30)
#define   GM_TEXTEDITOR_ClearText         (TEXTEDITOR_Dummy + 0x24)
#define   GM_TEXTEDITOR_ExportText        (TEXTEDITOR_Dummy + 0x25)
#define   GM_TEXTEDITOR_HandleError       (TEXTEDITOR_Dummy + 0x1f)
#define   GM_TEXTEDITOR_InsertText        (TEXTEDITOR_Dummy + 0x26)
#define   GM_TEXTEDITOR_MacroBegin        (TEXTEDITOR_Dummy + 0x27)
#define   GM_TEXTEDITOR_MacroEnd          (TEXTEDITOR_Dummy + 0x28)
#define   GM_TEXTEDITOR_MacroExecute      (TEXTEDITOR_Dummy + 0x29)
#define   GM_TEXTEDITOR_MarkText          (TEXTEDITOR_Dummy + 0x2c)
#define   GM_TEXTEDITOR_Replace           (TEXTEDITOR_Dummy + 0x2a)
#define   GM_TEXTEDITOR_Search            (TEXTEDITOR_Dummy + 0x2b)
struct    GP_TEXTEDITOR_ARexxCmd          { ULONG MethodID; struct GadgetInfo *GInfo; STRPTR command; };
struct    GP_TEXTEDITOR_BlockInfo         { ULONG MethodID; struct GadgetInfo *GInfo; ULONG *startx; ULONG *starty; ULONG *stopx; ULONG *stopy; };
struct    GP_TEXTEDITOR_ClearText         { ULONG MethodID; struct GadgetInfo *GInfo; };
struct    GP_TEXTEDITOR_ExportText        { ULONG MethodID; struct GadgetInfo *GInfo; };
struct    GP_TEXTEDITOR_HandleError       { ULONG MethodID; struct GadgetInfo *GInfo; ULONG errorcode; }; /* See below for error codes */
struct    GP_TEXTEDITOR_InsertText        { ULONG MethodID; struct GadgetInfo *GInfo; STRPTR text; LONG pos; }; /* See below for positions */
struct    GP_TEXTEDITOR_MarkText          { ULONG MethodID; struct GadgetInfo *GInfo; ULONG start_crsr_x; ULONG start_crsr_y; ULONG stop_crsr_x; ULONG stop_crsr_y; };
struct    GP_TEXTEDITOR_Replace           { ULONG MethodID; struct GadgetInfo *GInfo; STRPTR newstring; ULONG flags; };
struct    GP_TEXTEDITOR_Search            { ULONG MethodID; struct GadgetInfo *GInfo; STRPTR string; ULONG flags; }; /* See below for flags */

#define   GV_TEXTEDITOR_ExportHook_Plain       0x00000000
#define   GV_TEXTEDITOR_ExportHook_EMail       0x00000001

#define   GV_TEXTEDITOR_Flow_Left              0x00000000
#define   GV_TEXTEDITOR_Flow_Center            0x00000001
#define   GV_TEXTEDITOR_Flow_Right             0x00000002
#define   GV_TEXTEDITOR_Flow_Justified         0x00000003

#define   GV_TEXTEDITOR_ImportHook_Plain       0x00000000
#define   GV_TEXTEDITOR_ImportHook_EMail       0x00000002
#define   GV_TEXTEDITOR_ImportHook_MIME        0x00000003
#define   GV_TEXTEDITOR_ImportHook_MIMEQuoted  0x00000004

#define   GV_TEXTEDITOR_InsertText_Cursor      0x00000000
#define   GV_TEXTEDITOR_InsertText_Top         0x00000001
#define   GV_TEXTEDITOR_InsertText_Bottom      0x00000002

#define   GV_TEXTEDITOR_LengthHook_Plain       0x00000000
#define   GV_TEXTEDITOR_LengthHook_ANSI        0x00000001
#define   GV_TEXTEDITOR_LengthHook_HTML        0x00000002
#define   GV_TEXTEDITOR_LengthHook_MAIL        0x00000003

#define   GF_TEXTEDITOR_Search_FromTop       (1 << 0)
#define   GF_TEXTEDITOR_Search_Next          (1 << 1)
#define   GF_TEXTEDITOR_Search_CaseSensitive (1 << 2)
#define   GF_TEXTEDITOR_Search_DOSPattern    (1 << 3)
#define   GF_TEXTEDITOR_Search_Backwards     (1 << 4)

/* Error codes given as argument to GM_TEXTEDITOR_HandleError */
#define   Error_ClipboardIsEmpty         0x01
#define   Error_ClipboardIsNotFTXT       0x02
#define   Error_MacroBufferIsFull        0x03
#define   Error_MemoryAllocationFailed   0x04
#define   Error_NoAreaMarked             0x05
#define   Error_NoMacroDefined           0x06
#define   Error_NothingToRedo            0x07
#define   Error_NothingToUndo            0x08
#define   Error_NotEnoughUndoMem         0x09 /* This will cause all the stored undos to be freed */
#define   Error_StringNotFound           0x0a
#define   Error_NoBookmarkInstalled      0x0b
#define   Error_BookmarkHasBeenLost      0x0c

struct ClickMessage
{
   STRPTR  LineContents;  /* This field is ReadOnly!!! */
   ULONG   ClickPosition;
};

/* Definitions for Separator type */

#define LNSB_Top             0 /* Mutual exclude: */
#define LNSB_Middle          1 /* Placement of    */
#define LNSB_Bottom          2 /*  the separator  */
#define LNSB_StrikeThru      3 /* Let separator go thru the textfont */
#define LNSB_Thick           4 /* Extra thick separator */

#define LNSF_Top             (1<<LNSB_Top)
#define LNSF_Middle          (1<<LNSB_Middle)
#define LNSF_Bottom          (1<<LNSB_Bottom)
#define LNSF_StrikeThru      (1<<LNSB_StrikeThru)
#define LNSF_Thick           (1<<LNSB_Thick)

#endif /* GADGETS_TEXTEDITOR_H */


include/libraries/iffparse.h

#ifndef IFF_IFFPARSE_H
#define IFF_IFFPARSE_H
/*
**	$VER: iffparse.h 39.1 (1.6.1992)
**	Includes Release 44.1
**
**	iffparse.library structures and constants
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	(C) Copyright 1989-1990 Stuart Ferguson and Leo L. Schwab
**	All Rights Reserved
*/

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef EXEC_LISTS_H
#include <exec/lists.h>
#endif

#ifndef EXEC_PORTS_H
#include <exec/ports.h>
#endif

#ifndef DEVICES_CLIPBOARD_H
#include <devices/clipboard.h>
#endif

/*****************************************************************************/

/* Structure associated with an active IFF stream.
 * "iff_Stream" is a value used by the client's read/write/seek functions -
 * it will not be accessed by the library itself and can have any value
 * (could even be a pointer or a BPTR).
 *
 * This structure can only be allocated by iffparse.library
 */
struct IFFHandle
{
    ULONG iff_Stream;
    ULONG iff_Flags;
    LONG  iff_Depth;	/*  Depth of context stack */
};

/* bit masks for "iff_Flags" field */
#define IFFF_READ	0L			 /* read mode - default    */
#define IFFF_WRITE	1L			 /* write mode		   */
#define IFFF_RWBITS	(IFFF_READ | IFFF_WRITE) /* read/write bits	   */
#define IFFF_FSEEK	(1L<<1)		 /* forward seek only	   */
#define IFFF_RSEEK	(1L<<2)		 /* random seek	   */
#define IFFF_RESERVED	0xFFFF0000L		 /* Don't touch these bits */

/*****************************************************************************/

/* When the library calls your stream handler, you'll be passed a pointer
 * to this structure as the "message packet".
 */
struct IFFStreamCmd
{
    LONG sc_Command;	/* Operation to be performed (IFFCMD_) */
    APTR sc_Buf;	/* Pointer to data buffer	       */
    LONG sc_NBytes;	/* Number of bytes to be affected      */
};

/*****************************************************************************/

/* A node associated with a context on the iff_Stack. Each node
 * represents a chunk, the stack representing the current nesting
 * of chunks in the open IFF file. Each context node has associated
 * local context items in the (private) LocalItems list.  The ID, type,
 * size and scan values describe the chunk associated with this node.
 *
 * This structure can only be allocated by iffparse.library
 */
struct ContextNode
{
    struct MinNode cn_Node;
    LONG	   cn_ID;
    LONG	   cn_Type;
    LONG	   cn_Size;	/*  Size of this chunk		   */
    LONG	   cn_Scan;	/*  # of bytes read/written so far */
};

/*****************************************************************************/

/* Local context items live in the ContextNode's.  Each class is identified
 * by its lci_Ident code and has a (private) purge vector for when the
 * parent context node is popped.
 *
 * This structure can only be allocated by iffparse.library
 */
struct LocalContextItem
{
    struct MinNode lci_Node;
    ULONG	   lci_ID;
    ULONG	   lci_Type;
    ULONG	   lci_Ident;
};

/*****************************************************************************/

/* StoredProperty: a local context item containing the data stored
 * from a previously encountered property chunk.
 */
struct StoredProperty
{
    LONG sp_Size;
    APTR sp_Data;
};

/*****************************************************************************/

/* Collection Item: the actual node in the collection list at which
 * client will look. The next pointers cross context boundaries so
 * that the complete list is accessable.
 */
struct CollectionItem
{
    struct CollectionItem *ci_Next;
    LONG		   ci_Size;
    APTR		   ci_Data;
};

/*****************************************************************************/

/* Structure returned by OpenClipboard(). You may do CMD_POSTs and such
 * using this structure. However, once you call OpenIFF(), you may not
 * do any more of your own I/O to the clipboard until you call CloseIFF().
 */
struct ClipboardHandle
{
    struct IOClipReq cbh_Req;
    struct MsgPort   cbh_CBport;
    struct MsgPort   cbh_SatisfyPort;
};

/*****************************************************************************/

/* IFF return codes. Most functions return either zero for success or
 * one of these codes. The exceptions are the read/write functions which
 * return positive values for number of bytes or records read or written,
 * or a negative error code. Some of these codes are not errors per sae,
 * but valid conditions such as EOF or EOC (End of Chunk).
 */
#define IFFERR_EOF	  -1L	/* Reached logical end of file	*/
#define IFFERR_EOC	  -2L	/* About to leave context	*/
#define IFFERR_NOSCOPE	  -3L	/* No valid scope for property	*/
#define IFFERR_NOMEM	  -4L	/* Internal memory alloc failed */
#define IFFERR_READ	  -5L	/* Stream read error		*/
#define IFFERR_WRITE	  -6L	/* Stream write error		*/
#define IFFERR_SEEK	  -7L	/* Stream seek error		*/
#define IFFERR_MANGLED	  -8L	/* Data in file is corrupt	*/
#define IFFERR_SYNTAX	  -9L	/* IFF syntax error		*/
#define IFFERR_NOTIFF	  -10L	/* Not an IFF file		*/
#define IFFERR_NOHOOK	  -11L	/* No call-back hook provided	*/
#define IFF_RETURN2CLIENT -12L	/* Client handler normal return */

/*****************************************************************************/

#define MAKE_ID(a,b,c,d)	\
    ((ULONG) (a)<<24 | (ULONG) (b)<<16 | (ULONG) (c)<<8 | (ULONG) (d))

/* Universal IFF identifiers */
#define ID_FORM		MAKE_ID('F','O','R','M')
#define ID_LIST		MAKE_ID('L','I','S','T')
#define ID_CAT			MAKE_ID('C','A','T',' ')
#define ID_PROP		MAKE_ID('P','R','O','P')
#define ID_NULL		MAKE_ID(' ',' ',' ',' ')

/* Identifier codes for universally recognized local context items */
#define IFFLCI_PROP		MAKE_ID('p','r','o','p')
#define IFFLCI_COLLECTION	MAKE_ID('c','o','l','l')
#define IFFLCI_ENTRYHANDLER	MAKE_ID('e','n','h','d')
#define IFFLCI_EXITHANDLER	MAKE_ID('e','x','h','d')

/*****************************************************************************/

/* Control modes for ParseIFF() function */
#define IFFPARSE_SCAN	 0L
#define IFFPARSE_STEP	 1L
#define IFFPARSE_RAWSTEP 2L

/*****************************************************************************/

/* Control modes for StoreLocalItem() function */
#define IFFSLI_ROOT  1L  /* Store in default context	  */
#define IFFSLI_TOP   2L  /* Store in current context	  */
#define IFFSLI_PROP  3L  /* Store in topmost FORM or LIST */

/*****************************************************************************/

/* Magic value for writing functions. If you pass this value in as a size
 * to PushChunk() when writing a file, the parser will figure out the
 * size of the chunk for you. If you know the size, is it better to
 * provide as it makes things faster.
 */
#define IFFSIZE_UNKNOWN -1L

/*****************************************************************************/

/* Possible call-back command values */
#define IFFCMD_INIT	0	/* Prepare the stream for a session */
#define IFFCMD_CLEANUP	1	/* Terminate stream session	    */
#define IFFCMD_READ	2	/* Read bytes from stream	    */
#define IFFCMD_WRITE	3	/* Write bytes to stream	    */
#define IFFCMD_SEEK	4	/* Seek on stream		    */
#define IFFCMD_ENTRY	5	/* You just entered a new context   */
#define IFFCMD_EXIT	6	/* You're about to leave a context  */
#define IFFCMD_PURGELCI 7	/* Purge a LocalContextItem	    */

/*****************************************************************************/

/* Obsolete IFFParse definitions, here for source code compatibility only.
 * Please do NOT use in new code.
 *
 * #define IFFPARSE_V37_NAMES_ONLY to remove these older names
 */
#ifndef IFFPARSE_V37_NAMES_ONLY
#define IFFSCC_INIT	IFFCMD_INIT
#define IFFSCC_CLEANUP	IFFCMD_CLEANUP
#define IFFSCC_READ	IFFCMD_READ
#define IFFSCC_WRITE	IFFCMD_WRITE
#define IFFSCC_SEEK	IFFCMD_SEEK
#endif

/*****************************************************************************/

#endif /* IFFPARSE_H */


include/devices/clipboard.h

#ifndef     DEVICES_CLIPBOARD_H
#define     DEVICES_CLIPBOARD_H
/*
**	$VER: clipboard.h 36.5 (2.11.1990)
**	Includes Release 44.1
**
**	clipboard.device structure definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef	EXEC_TYPES_H
#include <exec/types.h>
#endif
#ifndef	EXEC_NODES_H
#include <exec/nodes.h>
#endif
#ifndef	EXEC_LISTS_H
#include <exec/lists.h>
#endif
#ifndef	EXEC_PORTS_H
#include <exec/ports.h>
#endif

#define	CBD_POST		(CMD_NONSTD+0)
#define	CBD_CURRENTREADID	(CMD_NONSTD+1)
#define	CBD_CURRENTWRITEID	(CMD_NONSTD+2)
#define	CBD_CHANGEHOOK		(CMD_NONSTD+3)

#define	CBERR_OBSOLETEID	1

struct ClipboardUnitPartial {
    struct  Node cu_Node;	/* list of units */
    ULONG   cu_UnitNum;		/* unit number for this unit */
    /* the remaining unit data is private to the device */
};

struct IOClipReq {
    struct Message io_Message;
    struct Device *io_Device;	/* device node pointer	*/
    struct ClipboardUnitPartial *io_Unit; /* unit node pointer */
    UWORD   io_Command;		/* device command */
    UBYTE   io_Flags;		/* including QUICK and SATISFY */
    BYTE    io_Error;		/* error or warning num */
    ULONG   io_Actual;		/* number of bytes transferred */
    ULONG   io_Length;		/* number of bytes requested */
    STRPTR  io_Data;		/* either clip stream or post port */
    ULONG   io_Offset;		/* offset in clip stream */
    LONG    io_ClipID;		/* ordinal clip identifier */
};

#define	PRIMARY_CLIP	0	/* primary clip unit */

struct SatisfyMsg {
    struct Message sm_Msg;	/* the length will be 6 */
    UWORD   sm_Unit;		/* which clip unit this is */
    LONG    sm_ClipID;		/* the clip identifier of the post */
};

struct ClipHookMsg {
    ULONG   chm_Type;		/* zero for this structure format */
    LONG    chm_ChangeCmd;	/* command that caused this hook invocation: */
                /*   either CMD_UPDATE or CBD_POST */
    LONG    chm_ClipID;		/* the clip identifier of the new data */
};

#endif	/* DEVICES_CLIPBOARD_H */


include/graphics/clip.h

#ifndef	GRAPHICS_CLIP_H
#define	GRAPHICS_CLIP_H
/*
**	$VER: clip.h 39.0 (2.12.1991)
**	Includes Release 44.1
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef GRAPHICS_GFX_H
#include <graphics/gfx.h>
#endif
#ifndef EXEC_SEMAPHORES_H
#include <exec/semaphores.h>
#endif
#ifndef UTILITY_HOOKS_H
#include <utility/hooks.h>
#endif

#define NEWLOCKS

struct Layer
{
    struct  Layer *front,*back;
    struct  ClipRect	*ClipRect;  /* read by roms to find first cliprect */
    struct  RastPort	*rp;
    struct  Rectangle	bounds;
    UBYTE   reserved[4];
    UWORD   priority;		    /* system use only */
    UWORD   Flags;		    /* obscured ?, Virtual BitMap? */
    struct  BitMap *SuperBitMap;
    struct  ClipRect *SuperClipRect; /* super bitmap cliprects if VBitMap != 0*/
                  /* else damage cliprect list for refresh */
    APTR    Window;		  /* reserved for user interface use */
    WORD    Scroll_X,Scroll_Y;
    struct  ClipRect *cr,*cr2,*crnew;	/* used by dedice */
    struct  ClipRect *SuperSaveClipRects; /* preallocated cr's */
    struct  ClipRect *_cliprects;	/* system use during refresh */
    struct  Layer_Info	*LayerInfo;	/* points to head of the list */
    struct  SignalSemaphore Lock;
    struct  Hook *BackFill;
    ULONG   reserved1;
    struct  Region *ClipRegion;
    struct  Region *saveClipRects;	/* used to back out when in trouble*/
    WORD    Width,Height;		/* system use */
    UBYTE   reserved2[18];
    /* this must stay here */
    struct  Region  *DamageList;    /* list of rectangles to refresh
                       through */
};

struct ClipRect
{
    struct  ClipRect *Next;	    /* roms used to find next ClipRect */
    struct  ClipRect *prev;	    /* Temp use in layers (private) */
    struct  Layer   *lobs;	    /* Private use for layers */
    struct  BitMap  *BitMap;	    /* Bitmap for layers private use */
    struct  Rectangle	bounds;     /* bounds of cliprect */
    void    *_p1;		    /* Layers private use!!! */
    void    *_p2;		    /* Layers private use!!! */
    LONG    reserved;		    /* system use (Layers private) */
#ifdef NEWCLIPRECTS_1_1
    LONG    Flags;		    /* Layers private field for cliprects */
                    /* that layers allocates... */
#endif				    /* MUST be multiple of 8 bytes to buffer */
};

/* internal cliprect flags */
#define CR_NEEDS_NO_CONCEALED_RASTERS  1
#define CR_NEEDS_NO_LAYERBLIT_DAMAGE   2

/* defines for code values for getcode */
#define ISLESSX 1
#define ISLESSY 2
#define ISGRTRX 4
#define ISGRTRY 8

#endif	/* GRAPHICS_CLIP_H */


include/utility/date.h

#ifndef UTILITY_DATE_H
#define UTILITY_DATE_H
/*
**	$VER: date.h 39.1 (20.1.1992)
**	Includes Release 44.1
**
**	Date conversion routines ClockData definition.
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	All Rights Reserved
*/

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

/*****************************************************************************/

struct ClockData
{
    UWORD sec;
    UWORD min;
    UWORD hour;
    UWORD mday;
    UWORD month;
    UWORD year;
    UWORD wday;
};

/*****************************************************************************/

#endif /* UTILITY_DATE_H */


include/graphics/text.h

#ifndef	GRAPHICS_TEXT_H
#define	GRAPHICS_TEXT_H
/*
**	$VER: text.h 39.0 (21.8.1991)
**	Includes Release 44.1
**
**	graphics library text structures
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef	EXEC_PORTS_H
#include	<exec/ports.h>
#endif	/* EXEC_PORTS_H */

#ifndef	GRAPHICS_GFX_H
#include	<graphics/gfx.h>
#endif	/* GRAPHICS_GFX_H */

#ifndef	UTILITY_TAGITEM_H
#include	<utility/tagitem.h>
#endif	/* UTILITY_TAGITEM_H */

/*------ Font Styles ------------------------------------------------*/
#define	FS_NORMAL	0	/* normal text (no style bits set) */
#define	FSB_UNDERLINED	0	/* underlined (under baseline) */
#define	FSF_UNDERLINED	0x01
#define	FSB_BOLD	1	/* bold face text (ORed w/ shifted) */
#define	FSF_BOLD	0x02
#define	FSB_ITALIC	2	/* italic (slanted 1:2 right) */
#define	FSF_ITALIC	0x04
#define	FSB_EXTENDED	3	/* extended face (wider than normal) */
#define	FSF_EXTENDED	0x08

#define	FSB_COLORFONT	6	/* this uses ColorTextFont structure */
#define	FSF_COLORFONT	0x40
#define	FSB_TAGGED	7	/* the TextAttr is really an TTextAttr, */
#define	FSF_TAGGED	0x80

/*------ Font Flags -------------------------------------------------*/
#define	FPB_ROMFONT	0	/* font is in rom */
#define	FPF_ROMFONT	0x01
#define	FPB_DISKFONT	1	/* font is from diskfont.library */
#define	FPF_DISKFONT	0x02
#define	FPB_REVPATH	2	/* designed path is reversed (e.g. left) */
#define	FPF_REVPATH	0x04
#define	FPB_TALLDOT	3	/* designed for hires non-interlaced */
#define	FPF_TALLDOT	0x08
#define	FPB_WIDEDOT	4	/* designed for lores interlaced */
#define	FPF_WIDEDOT	0x10
#define	FPB_PROPORTIONAL 5	/* character sizes can vary from nominal */
#define	FPF_PROPORTIONAL 0x20
#define	FPB_DESIGNED	6	/* size explicitly designed, not constructed */
                /* note: if you do not set this bit in your */
                /* textattr, then a font may be constructed */
                /* for you by scaling an existing rom or disk */
                /* font (under V36 and above). */
#define	FPF_DESIGNED	0x40
    /* bit 7 is always clear for fonts on the graphics font list */
#define	FPB_REMOVED	7	/* the font has been removed */
#define	FPF_REMOVED	(1<<7)

/****** TextAttr node, matches text attributes in RastPort **********/
struct TextAttr {
    STRPTR  ta_Name;		/* name of the font */
    UWORD   ta_YSize;		/* height of the font */
    UBYTE   ta_Style;		/* intrinsic font style */
    UBYTE   ta_Flags;		/* font preferences and flags */
};

struct TTextAttr {
    STRPTR  tta_Name;		/* name of the font */
    UWORD   tta_YSize;		/* height of the font */
    UBYTE   tta_Style;		/* intrinsic font style */
    UBYTE   tta_Flags;		/* font preferences and flags */
    struct TagItem *tta_Tags;	/* extended attributes */
};

/****** Text Tags ***************************************************/
#define	TA_DeviceDPI	(1|TAG_USER)	/* Tag value is Point union: */
                    /* Hi word XDPI, Lo word YDPI */

#define	MAXFONTMATCHWEIGHT	32767	/* perfect match from WeighTAMatch */

/****** TextFonts node **********************************************/
struct TextFont {
    struct Message tf_Message;	/* reply message for font removal */
                /* font name in LN	  \    used in this */
    UWORD   tf_YSize;		/* font height		  |    order to best */
    UBYTE   tf_Style;		/* font style		  |    match a font */
    UBYTE   tf_Flags;		/* preferences and flags  /    request. */
    UWORD   tf_XSize;		/* nominal font width */
    UWORD   tf_Baseline;	/* distance from the top of char to baseline */
    UWORD   tf_BoldSmear;	/* smear to affect a bold enhancement */

    UWORD   tf_Accessors;	/* access count */

    UBYTE   tf_LoChar;		/* the first character described here */
    UBYTE   tf_HiChar;		/* the last character described here */
    APTR    tf_CharData;	/* the bit character data */

    UWORD   tf_Modulo;		/* the row modulo for the strike font data */
    APTR    tf_CharLoc;		/* ptr to location data for the strike font */
                /*   2 words: bit offset then size */
    APTR    tf_CharSpace;	/* ptr to words of proportional spacing data */
    APTR    tf_CharKern;	/* ptr to words of kerning data */
};

/* unfortunately, this needs to be explicitly typed */
#define	tf_Extension	tf_Message.mn_ReplyPort

/*-----	tfe_Flags0 (partial definition) ----------------------------*/
#define TE0B_NOREMFONT	0	/* disallow RemFont for this font */
#define TE0F_NOREMFONT	0x01

struct TextFontExtension {	/* this structure is read-only */
    UWORD   tfe_MatchWord;		/* a magic cookie for the extension */
    UBYTE   tfe_Flags0;			/* (system private flags) */
    UBYTE   tfe_Flags1;			/* (system private flags) */
    struct TextFont *tfe_BackPtr;	/* validation of compilation */
    struct MsgPort *tfe_OrigReplyPort;	/* original value in tf_Extension */
    struct TagItem *tfe_Tags;		/* Text Tags for the font */
    UWORD  *tfe_OFontPatchS;		/* (system private use) */
    UWORD  *tfe_OFontPatchK;		/* (system private use) */
    /* this space is reserved for future expansion */
};

/******	ColorTextFont node ******************************************/
/*-----	ctf_Flags --------------------------------------------------*/
#define	CT_COLORMASK	0x000F	/* mask to get to following color styles */
#define	CT_COLORFONT	0x0001	/* color map contains designer's colors */
#define	CT_GREYFONT	0x0002	/* color map describes even-stepped */
                /* brightnesses from low to high */
#define	CT_ANTIALIAS	0x0004	/* zero background thru fully saturated char */

#define	CTB_MAPCOLOR	0	/* map ctf_FgColor to the rp_FgPen if it's */
#define	CTF_MAPCOLOR	0x0001	/* is a valid color within ctf_Low..ctf_High */

/*----- ColorFontColors --------------------------------------------*/
struct ColorFontColors {
    UWORD   cfc_Reserved;	/* *must* be zero */
    UWORD   cfc_Count;		/* number of entries in cfc_ColorTable */
    UWORD  *cfc_ColorTable;	/* 4 bit per component color map packed xRGB */
};

/*-----	ColorTextFont ----------------------------------------------*/
struct ColorTextFont {
    struct TextFont ctf_TF;
    UWORD   ctf_Flags;		/* extended flags */
    UBYTE   ctf_Depth;		/* number of bit planes */
    UBYTE   ctf_FgColor;	/* color that is remapped to FgPen */
    UBYTE   ctf_Low;		/* lowest color represented here */
    UBYTE   ctf_High;		/* highest color represented here */
    UBYTE   ctf_PlanePick;	/* PlanePick ala Images */
    UBYTE   ctf_PlaneOnOff;	/* PlaneOnOff ala Images */
    struct ColorFontColors *ctf_ColorFontColors; /* colors for font */
    APTR    ctf_CharData[8];	/*pointers to bit planes ala tf_CharData */
};

/****** TextExtent node *********************************************/
struct TextExtent {
    UWORD   te_Width;		/* same as TextLength */
    UWORD   te_Height;		/* same as tf_YSize */
    struct Rectangle te_Extent;	/* relative to CP */
};

#endif	/* GRAPHICS_TEXT_H */


include/graphics/view.h

#ifndef GRAPHICS_VIEW_H
#define GRAPHICS_VIEW_H
/*
**	$VER: view.h 39.34 (31.5.1993)
**	Includes Release 44.1
**
**	graphics view/viewport definintions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#define ECS_SPECIFIC

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef EXEC_SEMAPHORES_H
#include <exec/semaphores.h>
#endif

#ifndef GRAPHICS_GFX_H
#include <graphics/gfx.h>
#endif

#ifndef GRAPHICS_COPPER_H
#include <graphics/copper.h>
#endif

#ifndef GRAPHICS_GFXNODES_H
#include <graphics/gfxnodes.h>
#endif

#ifndef GRAPHICS_MONITOR_H
#include <graphics/monitor.h>
#endif

#ifndef GRAPHICS_DISPLAYINFO_H
#include <graphics/displayinfo.h>
#endif

#ifndef HARDWARE_CUSTOM_H
#include <hardware/custom.h>
#endif

struct ViewPort
{
    struct	ViewPort *Next;
    struct	ColorMap *ColorMap;	/* table of colors for this viewport */
                    /* if this is nil, MakeVPort assumes default values */
    struct	CopList  *DspIns;	/* used by MakeVPort() */
    struct	CopList  *SprIns;	/* used by sprite stuff */
    struct	CopList  *ClrIns;	/* used by sprite stuff */
    struct	UCopList *UCopIns;	/* User copper list */
    WORD	DWidth,DHeight;
    WORD	DxOffset,DyOffset;
    UWORD	Modes;
    UBYTE	SpritePriorities;
    UBYTE	ExtendedModes;
    struct	RasInfo *RasInfo;
};

struct View
{
    struct	ViewPort *ViewPort;
    struct	cprlist *LOFCprList;   /* used for interlaced and noninterlaced */
    struct	cprlist *SHFCprList;   /* only used during interlace */
    WORD	DyOffset,DxOffset;   /* for complete View positioning */
                   /* offsets are +- adjustments to standard #s */
    UWORD	Modes;		   /* such as INTERLACE, GENLOC */
};

/* these structures are obtained via GfxNew */
/* and disposed by GfxFree */
struct ViewExtra
{
    struct ExtendedNode n;
    struct View *View;		/* backwards link */
    struct MonitorSpec *Monitor;	/* monitors for this view */
    UWORD TopLine;
};

/* this structure is obtained via GfxNew */
/* and disposed by GfxFree */
struct ViewPortExtra
{
    struct ExtendedNode n;
    struct ViewPort *ViewPort;	/* backwards link */
    struct Rectangle DisplayClip;	/* MakeVPort display clipping information */
    /* These are added for V39 */
    APTR   VecTable;		/* Private */
    APTR   DriverData[2];
    UWORD  Flags;
    Point  Origin[2];		/* First visible point relative to the DClip.
                     * One for each possible playfield.
                     */
    ULONG cop1ptr;			/* private */
    ULONG cop2ptr;			/* private */
};

/* All these VPXF_ flags are private */
#define VPXB_FREE_ME		0
#define VPXF_FREE_ME		(1 << VPXB_FREE_ME)
#define VPXB_LAST		1
#define VPXF_LAST		(1 << VPXB_LAST)
#define VPXB_STRADDLES_256	4
#define VPXF_STRADDLES_256	(1 << VPXB_STRADDLES_256)
#define VPXB_STRADDLES_512	5
#define VPXF_STRADDLES_512	(1 << VPXB_STRADDLES_512)

#define EXTEND_VSTRUCT	0x1000	/* unused bit in Modes field of View */

#define VPF_A2024	      0x40	/* VP?_ fields internal only */
#define VPF_TENHZ	      0x20
#define VPB_A2024	      6
#define VPB_TENHZ	      4

/* defines used for Modes in IVPargs */

#define GENLOCK_VIDEO	0x0002
#define LACE		0x0004
#define DOUBLESCAN	0x0008
#define SUPERHIRES	0x0020
#define PFBA		0x0040
#define EXTRA_HALFBRITE 0x0080
#define GENLOCK_AUDIO	0x0100
#define DUALPF		0x0400
#define HAM		0x0800
#define EXTENDED_MODE	0x1000
#define VP_HIDE	0x2000
#define SPRITES	0x4000
#define HIRES		0x8000

struct RasInfo	/* used by callers to and InitDspC() */
{
   struct   RasInfo *Next;	    /* used for dualpf */
   struct   BitMap *BitMap;
   WORD    RxOffset,RyOffset;	   /* scroll offsets in this BitMap */
};

struct ColorMap
{
    UBYTE	Flags;
    UBYTE	Type;
    UWORD	Count;
    APTR	ColorTable;
    struct	ViewPortExtra *cm_vpe;
    APTR	LowColorBits;
    UBYTE	TransparencyPlane;
    UBYTE	SpriteResolution;
    UBYTE	SpriteResDefault;	/* what resolution you get when you have set SPRITERESN_DEFAULT */
    UBYTE	AuxFlags;
    struct	ViewPort *cm_vp;
    APTR	NormalDisplayInfo;
    APTR	CoerceDisplayInfo;
    struct	TagItem *cm_batch_items;
    ULONG	VPModeID;
    struct	PaletteExtra *PalExtra;
    UWORD	SpriteBase_Even;
    UWORD	SpriteBase_Odd;
    UWORD	Bp_0_base;
    UWORD	Bp_1_base;

};

/* if Type == 0 then ColorMap is V1.2/V1.3 compatible */
/* if Type != 0 then ColorMap is V38	   compatible */
/* the system will never create other than V39 type colormaps when running V39 */

#define COLORMAP_TYPE_V1_2	0x00
#define COLORMAP_TYPE_V1_4	0x01
#define COLORMAP_TYPE_V36 COLORMAP_TYPE_V1_4	/* use this definition */
#define COLORMAP_TYPE_V39	0x02

/* Flags variable */
#define COLORMAP_TRANSPARENCY	0x01
#define COLORPLANE_TRANSPARENCY	0x02
#define BORDER_BLANKING		0x04
#define BORDER_NOTRANSPARENCY	0x08
#define VIDEOCONTROL_BATCH	0x10
#define USER_COPPER_CLIP	0x20
#define BORDERSPRITES	0x40

#define CMF_CMTRANS	0
#define CMF_CPTRANS	1
#define CMF_BRDRBLNK	2
#define CMF_BRDNTRAN	3
#define CMF_BRDRSPRT	6

#define SPRITERESN_ECS		0
/* ^140ns, except in 35ns viewport, where it is 70ns. */
#define SPRITERESN_140NS	1
#define SPRITERESN_70NS		2
#define SPRITERESN_35NS		3
#define SPRITERESN_DEFAULT	-1

/* AuxFlags : */
#define CMAB_FULLPALETTE 0
#define CMAF_FULLPALETTE (1<<CMAB_FULLPALETTE)
#define CMAB_NO_INTERMED_UPDATE 1
#define CMAF_NO_INTERMED_UPDATE (1<<CMAB_NO_INTERMED_UPDATE)
#define CMAB_NO_COLOR_LOAD 2
#define CMAF_NO_COLOR_LOAD (1 << CMAB_NO_COLOR_LOAD)
#define CMAB_DUALPF_DISABLE 3
#define CMAF_DUALPF_DISABLE (1 << CMAB_DUALPF_DISABLE)

struct PaletteExtra				/* structure may be extended so watch out! */
{
    struct SignalSemaphore pe_Semaphore;		/* shared semaphore for arbitration	*/
    UWORD	pe_FirstFree;				/* *private*				*/
    UWORD	pe_NFree;				/* number of free colors		*/
    UWORD	pe_FirstShared;				/* *private*				*/
    UWORD	pe_NShared;				/* *private*				*/
    UBYTE	*pe_RefCnt;				/* *private*				*/
    UBYTE	*pe_AllocList;				/* *private*				*/
    struct ViewPort *pe_ViewPort;			/* back pointer to viewport		*/
    UWORD	pe_SharableColors;			/* the number of sharable colors.	*/
};

/* flags values for ObtainPen */

#define PENB_EXCLUSIVE 0
#define PENB_NO_SETCOLOR 1

#define PENF_EXCLUSIVE (1l<<PENB_EXCLUSIVE)
#define PENF_NO_SETCOLOR (1l<<PENB_NO_SETCOLOR)

/* obsolete names for PENF_xxx flags: */

#define PEN_EXCLUSIVE PENF_EXCLUSIVE
#define PEN_NO_SETCOLOR PENF_NO_SETCOLOR

/* precision values for ObtainBestPen : */

#define PRECISION_EXACT	-1
#define PRECISION_IMAGE	0
#define PRECISION_ICON	16
#define PRECISION_GUI	32

/* tags for ObtainBestPen: */
#define OBP_Precision 0x84000000
#define OBP_FailIfBad 0x84000001

/* From V39, MakeVPort() will return an error if there is not enough memory,
 * or the requested mode cannot be opened with the requested depth with the
 * given bitmap (for higher bandwidth alignments).
 */

#define MVP_OK		0	/* you want to see this one */
#define MVP_NO_MEM	1	/* insufficient memory for intermediate workspace */
#define MVP_NO_VPE	2	/* ViewPort does not have a ViewPortExtra, and
                 * insufficient memory to allocate a temporary one.
                 */
#define MVP_NO_DSPINS	3	/* insufficient memory for intermidiate copper
                 * instructions.
                 */
#define MVP_NO_DISPLAY	4	/* BitMap data is misaligned for this viewport's
                 * mode and depth - see AllocBitMap().
                 */
#define MVP_OFF_BOTTOM	5	/* PRIVATE - you will never see this. */

/* From V39, MrgCop() will return an error if there is not enough memory,
 * or for some reason MrgCop() did not need to make any copper lists.
 */

#define MCOP_OK		0	/* you want to see this one */
#define MCOP_NO_MEM	1	/* insufficient memory to allocate the system
                 * copper lists.
                 */
#define MCOP_NOP	2	/* MrgCop() did not merge any copper lists
                 * (eg, no ViewPorts in the list, or all marked as
                 * hidden).
                 */

struct DBufInfo {
    APTR	dbi_Link1;
    ULONG	dbi_Count1;
    struct Message dbi_SafeMessage;		/* replied to when safe to write to old bitmap */
    APTR dbi_UserData1;			/* first user data */

    APTR	dbi_Link2;
    ULONG	dbi_Count2;
    struct Message dbi_DispMessage;	/* replied to when new bitmap has been displayed at least
                            once */
    APTR	dbi_UserData2;			/* second user data */
    ULONG	dbi_MatchLong;
    APTR	dbi_CopPtr1;
    APTR	dbi_CopPtr2;
    APTR	dbi_CopPtr3;
    UWORD	dbi_BeamPos1;
    UWORD	dbi_BeamPos2;
};

#endif	/* GRAPHICS_VIEW_H */


include/gadgets/colorwheel.h

#ifndef GADGETS_COLORWHEEL_H
#define GADGETS_COLORWHEEL_H
/*
**	$VER: colorwheel.h 44.1 (19.10.1999)
**	Includes Release 44.1
**
**	Definitions for the colorwheel BOOPSI class
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

/*****************************************************************************/

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

/*****************************************************************************/

/* For use with the WHEEL_HSB tag */
struct ColorWheelHSB
{
    ULONG cw_Hue;
    ULONG cw_Saturation;
    ULONG cw_Brightness;
};

/* For use with the WHEEL_RGB tag */
struct ColorWheelRGB
{
    ULONG cw_Red;
    ULONG cw_Green;
    ULONG cw_Blue;
};

/*****************************************************************************/

#define WHEEL_Dummy	     (TAG_USER+0x04000000)
#define WHEEL_Hue	     (WHEEL_Dummy+1)   /* set/get Hue		   */
#define WHEEL_Saturation     (WHEEL_Dummy+2)   /* set/get Saturation	    */
#define WHEEL_Brightness     (WHEEL_Dummy+3)   /* set/get Brightness	    */
#define WHEEL_HSB	     (WHEEL_Dummy+4)   /* set/get ColorWheelHSB     */
#define WHEEL_Red	     (WHEEL_Dummy+5)   /* set/get Red		    */
#define WHEEL_Green	     (WHEEL_Dummy+6)   /* set/get Green	    */
#define WHEEL_Blue	     (WHEEL_Dummy+7)   /* set/get Blue		    */
#define WHEEL_RGB	     (WHEEL_Dummy+8)   /* set/get ColorWheelRGB     */
#define WHEEL_Screen	     (WHEEL_Dummy+9)   /* init screen/enviroment    */
#define WHEEL_Abbrv	     (WHEEL_Dummy+10)  /* "GCBMRY" if English	    */
#define WHEEL_Donation	     (WHEEL_Dummy+11)  /* colors donated by app     */
#define WHEEL_BevelBox	     (WHEEL_Dummy+12)  /* inside a bevel box	    */
#define WHEEL_GradientSlider (WHEEL_Dummy+13)  /* attached gradient slider  */
#define WHEEL_MaxPens	     (WHEEL_Dummy+14)  /* max # of pens to allocate */

/*****************************************************************************/

#endif /* GADGETS_COLORWHEEL_H */


include/gadgets/listbrowser.h

#ifndef GADGETS_LISTBROWSER_H
#define GADGETS_LISTBROWSER_H
/*
**	$VER: listbrowser.h 44.1 (19.10.1999)
**	Includes Release 44.1
**
**  Definitions for the ListBrowser BOOPSI class
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

/*****************************************************************************/

#ifndef REACTION_REACTION_H
#include <reaction/reaction.h>
#endif

#ifndef INTUITION_GADGETCLASS_H
#include <intuition/gadgetclass.h>
#endif

/*****************************************************************************/

/* LBM_ADDNODE creates a listbrowser node and inserts it to the currently
 * attached list. The number of columns is automatically set according to the
 * object's column number. If the node would become visible, it is automatically
 * rendered. This method returns the address of the new node. (V41)
 */
#define LBM_ADDNODE (0x580001L)

struct lbAddNode
{
    ULONG MethodID;					/* LBM_ADDNODE */
    struct GadgetInfo *lba_GInfo;	/* to provide rendering info */
    struct Node *lba_Node;      	/* Insert() after this node */
    struct TagItem *lba_NodeAttrs;	/* LBNA taglist */
};

/* LBM_REMNODE removes and frees the chosen node. If the node was visible, the
 * display is updated. The method returns 1 if the operation was successful.
 * (V41)
 */
#define LBM_REMNODE (0x580002L)

struct lbRemNode
{
    ULONG MethodID;					/* LBM_REMNODE */
    struct GadgetInfo *lbr_GInfo;	/* to provide rendering info */
    struct Node *lbr_Node;			/* Remove() this node */
};

/* LBM_EDITNODE changes the chosen node's attributes and renders the
 * changes. The method returns 1 if the operation was successful. (V41)
 */
#define LBM_EDITNODE (0x580003L)

struct lbEditNode
{
    ULONG MethodID;					/* LBM_EDITNODE */
    struct GadgetInfo *lbe_GInfo;	/* to provide rendering info */
    struct Node *lbe_Node;			/* modify this node */
    struct TagItem *lbe_NodeAttrs;	/* according to this taglist */
};

/* LBM_SORT
 */
#define LBM_SORT (0x580004L)

struct lbSort
{
    ULONG MethodID;					/* LBM_SORT */
    struct GadgetInfo *lbs_GInfo;	/* to provide rendering info */
    ULONG lbs_Column;				/* Column to sort by */
    ULONG lbs_Reverse;				/* Reverse sort */
    struct Hook *lbs_CompareHook;	/* Optional hook to compare items */
};

/* LBM_SHOWCHILDREN
 */
#define LBM_SHOWCHILDREN (0x580005L)

struct lbShowChildren
{
    ULONG MethodID;					/* LBM_SHOWCHILDREN */
    struct GadgetInfo *lbsc_GInfo;	/* to provide rendering info */
    struct Node *lbsc_Node;			/* Starting ParentNode, NULL means start at root. */
    WORD lbsc_Depth;				/* Depth to Show */
};

/* LBM_HIDECHILDREN
 */
#define LBM_HIDECHILDREN (0x580006L)

struct lbHideChildren
{
    ULONG MethodID;					/* LBM_HIDECHILDREN */
    struct GadgetInfo *lbhc_GInfo;	/* to provide rendering info */
    struct Node *lbhc_Node;			/* Starting ParentNode, NULL means start at root. */
    WORD lbhc_Depth;				/* Depth to Hide */
};

/*****************************************************************************/

/* ListBrowser Node attributes.
 */
#define LBNA_Dummy			(TAG_USER+0x5003500)

#define	LBNA_Selected		(LBNA_Dummy+1)
    /* (BOOL) If the node is to be selected.  Defaults to FALSE. */

#define	LBNA_Flags			(LBNA_Dummy+2)
    /* (ULONG) Flags for the node.  Defaults to 0. */

#define	LBNA_UserData		(LBNA_Dummy+3)
    /* (ULONG) User data.  Defaults to NULL. */

#define	LBNA_Column			(LBNA_Dummy+4)
    /* (WORD) Column in the node that the attributes below effect.   Defaults
     * to 0.*/

#define	LBNCA_Text			(LBNA_Dummy+5)
    /* (STRPTR) Text to display in the column.  Defaults to NULL. */

#define	LBNCA_Integer		(LBNA_Dummy+6)
    /* (LONG *) Pointer to an integer to display in the column.  Defaults to NULL. */

#define	LBNCA_FGPen			(LBNA_Dummy+7)
    /* (WORD) Column foreground pen. */

#define	LBNCA_BGPen			(LBNA_Dummy+8)
    /* (WORD) Column background pen. */

#define	LBNCA_Image			(LBNA_Dummy+9)
    /* (struct Image *) Image to display in the column.  Defaults to NULL. */

#define	LBNCA_SelImage		(LBNA_Dummy+10)
    /* (struct Image *) Image to display in column when selected.  Defaults
     * to NULL. */

#define	LBNCA_HorizJustify	(LBNA_Dummy+11)
#define LBNCA_Justification	LBNCA_HorizJustify
    /* (ULONG) Column justification.  Defaults to LCJ_LEFT. */

#define	LBNA_Generation		(LBNA_Dummy+12)
    /* Node generation.  Defaults to 0. */

#define	LBNCA_Editable		(LBNA_Dummy+13)
    /* (BOOL) If this column is editable.  Requires LBNCA_CopyText. Defaults
     * to FALSE. */

#define	LBNCA_MaxChars		(LBNA_Dummy+14)
    /* (WORD) Maximum characters in an editable entry.  Required when using
     * LBNCA_Editable. */

#define	LBNCA_CopyText		(LBNA_Dummy+15)
    /* Copy the LBNCA_Text contents to an internal buffer. */

#define	LBNA_CheckBox		(LBNA_Dummy+16)
    /* (BOOL) this is a checkbox node */

#define	LBNA_Checked		(LBNA_Dummy+17)
    /* (BOOL) is checked if true */

#define	LBNA_NodeSize		(LBNA_Dummy+18)
    /* (ULONG) size of custom node and optimzie mempool puddles */

#define	LBNCA_EditTags		(LBNA_Dummy+19)
    /* (struct TagItem *) taglist sent to editable string */

#define	LBNCA_RenderHook	(LBNA_Dummy+20)
    /* (struct Hook *) effectivly the same as gadtools listview hook */

#define	LBNCA_HookHeight	(LBNA_Dummy+22)
    /* (WORD) height in pixels of the hook function rendering */

#define	LBNA_MemPool	(LBNA_Dummy+23)
    /* (APTR) exec memory pool to use */

#define	LBNA_NumColumns	(LBNA_Dummy+24)
    /* (WORD) for GetListBrowserNodeAttrs() only! */

#define	LBNA_Priority	(LBNA_Dummy+25)
    /* (UBYTE) Sets the exec node->ln_Pri */

#define	LBNCA_CopyInteger	(LBNA_Dummy+26)
    /* (BOOL) AllocListBrowserNodeAttrs() or SetListBrowserNodeAttrs() only! */

#define	LBNCA_WordWrap		(LBNA_Dummy+27)
    /* (BOOL) WordWrap this node's LBNCA_Text data */

#define	LBNCA_VertJustify	(LBNA_Dummy+28)
    /* (ULONG) Row justification.  Defaults to LRJ_BOTTOM. */

/* Flags for the LBNA_Flags node attribute.
 */
#define LBFLG_READONLY 1
#define LBFLG_CUSTOMPENS 2
#define LBFLG_HASCHILDREN 4
#define LBFLG_SHOWCHILDREN 8
#define LBFLG_HIDDEN 16

/* Justification modes for the LBNA_HorizJustify node column attribute.
 */
#define LCJ_LEFT 0
#define LCJ_CENTER 1
#define LCJ_RIGHT 2

#define LCJ_CENTRE LCJ_CENTER

/* Justification modes for the LBNA_VertJustify node column attribute.
 */
#define LRJ_BOTTOM 0
#define LRJ_CENTER 1
#define LRJ_TOP 2

#define LRJ_CENTRE LRJ_CENTER

/* These definitions are for the LBNCA_RenderHook tag.
 */

/* The different types of messages that a listview callback hook can see.
 */
#define LB_DRAW 0x202L					/* Draw yourself, with state */

/* Possible return values from a render hook.
 */
#define LBCB_OK 0						/* callback understands this message type */
#define LBCB_UNKNOWN 1					/* callback does not understand this message */

/* States for LBDrawMsg.lbdm_State.
 */
#define LBR_NORMAL 0					/* The usual */
#define LBR_SELECTED 1					/* For selected gadgets	*/

/* Structure of LB_DRAW messages, object is a (struct Node *).
 */
struct LBDrawMsg
{
    ULONG lbdm_MethodID;				/* LV_DRAW */
    struct RastPort *lbdm_RastPort;		/* Where to render to */
    struct DrawInfo *lbdm_DrawInfo;		/* Useful to have around */
    struct Rectangle lbdm_Bounds;		/* Limits of where to render */
    ULONG lbdm_State;					/* How to render */
};

/* Sort Hook Data Structure.
 */
struct LBSortMsg
{
    ULONG lbsm_TypeA;
    union
    {
        LONG Integer;
        STRPTR Text;
    } lbsm_DataA;
    APTR lbsm_UserDataA;

    ULONG lbsm_TypeB;
    union
    {
        LONG Integer;
        STRPTR Text;
    } lbsm_DataB;
    APTR lbsm_UserDataB;
};

/*****************************************************************************/

/* Information for columns of the list browser.
 */
struct ColumnInfo
{
    WORD ci_Width;
    STRPTR ci_Title;
    ULONG ci_Flags;
};

/* Possible ColumnInfo Flags
 */
#define CIF_WEIGHTED 0	/* weighted width column */
#define CIF_FIXED 1		/* fixed pixel width column */
#define CIF_DRAGGABLE 2
#define CIF_NOSEPARATORS 4
#define CIF_SORTABLE 8

/*****************************************************************************/

/* Additional attributes defined by the List Browser class
 */
#define LISTBROWSER_Dummy			(REACTION_Dummy+0x0003000)

#define	LISTBROWSER_Top				(LISTBROWSER_Dummy+1)
    /* (LONG) Top position node. Defauts to 0. */

#define	LISTBROWSER_Reserved1		(LISTBROWSER_Dummy+2)
    /* RESERVED */

#define	LISTBROWSER_Labels			(LISTBROWSER_Dummy+3)
    /* (struct List *) Defaults to ~0. */

#define	LISTBROWSER_Selected		(LISTBROWSER_Dummy+4)
    /* (LONG) numeric index of node currently selected; Defaults to -1. */

#define	LISTBROWSER_SelectedNode	(LISTBROWSER_Dummy+5)
    /* (struct Node *) node currently seleted */

#define	LISTBROWSER_MultiSelect		(LISTBROWSER_Dummy+6)
    /* (BOOL) Defaults to FALSE. */

#define LISTBROWSER_VertSeparators	(LISTBROWSER_Dummy+7)
#define LISTBROWSER_Separators		LISTBROWSER_VertSeparators
    /* (BOOL) Render column separators. Defaults to TRUE. */

#define LISTBROWSER_ColumnInfo		(LISTBROWSER_Dummy+8)
    /* (struct ColumnInfo *) Defaults to NULL. */

#define LISTBROWSER_MakeVisible		(LISTBROWSER_Dummy+9)
    /* (LONG) Defaults to 0. */

#define LISTBROWSER_VirtualWidth	(LISTBROWSER_Dummy+10)
    /* (WORD) Defaults to 0. */

#define LISTBROWSER_Borderless		(LISTBROWSER_Dummy+11)
    /* (BOOL) Defaults to FALSE. */

#define LISTBROWSER_VerticalProp	(LISTBROWSER_Dummy+12)
    /* (BOOL) Defaults to TRUE. */

#define LISTBROWSER_HorizontalProp	(LISTBROWSER_Dummy+13)
    /* (BOOL) Defaults to FALSE. */

#define	LISTBROWSER_Left			(LISTBROWSER_Dummy+14)
    /* (WORD) Defaults to 0. */

#define	LISTBROWSER_Reserved2		(LISTBROWSER_Dummy+15)
    /* RESERVED */

#define	LISTBROWSER_AutoFit			(LISTBROWSER_Dummy+16)
    /* (BOOL) Defaults to FALSE. */

#define	LISTBROWSER_ColumnTitles	(LISTBROWSER_Dummy+17)
    /* (BOOL) Defaults to FALSE. */

#define	LISTBROWSER_ShowSelected	(LISTBROWSER_Dummy+18)
    /* (BOOL) Defaults to FALSE. */

#define	LISTBROWSER_VPropTotal		(LISTBROWSER_Dummy+19)
#define	LISTBROWSER_VPropTop		(LISTBROWSER_Dummy+20)
#define	LISTBROWSER_VPropVisible	(LISTBROWSER_Dummy+21)
    /* State of the vertical prop gadget (if any). */

#define	LISTBROWSER_HPropTotal		(LISTBROWSER_Dummy+22)
#define	LISTBROWSER_HPropTop		(LISTBROWSER_Dummy+23)
#define	LISTBROWSER_HPropVisible	(LISTBROWSER_Dummy+24)
    /* State of the horizontal prop gadget (if any). */

#define	LISTBROWSER_MouseX			(LISTBROWSER_Dummy+25)
#define	LISTBROWSER_MouseY			(LISTBROWSER_Dummy+26)
    /* (WORD) Returns position of mouse release. */

#define	LISTBROWSER_Hierarchical	(LISTBROWSER_Dummy+27)
    /* (BOOL) Enables ListTree mode. Defaults to FALSE. */

#define	LISTBROWSER_ShowImage		(LISTBROWSER_Dummy+28)
    /* (struct Image *) ListTree expanded branchh custom image. Defaults to NULL. */

#define	LISTBROWSER_HideImage		(LISTBROWSER_Dummy+29)
    /* (struct Image *) ListTree colapsed branch custom image. Defaults to NULL. */

#define	LISTBROWSER_LeafImage		(LISTBROWSER_Dummy+30)
    /* (struct Image *) ListTree branch item custom image. Defaults to NULL. */

#define	LISTBROWSER_ScrollRaster	(LISTBROWSER_Dummy+31)
    /* (BOOL) See autodocs for Intuition V37 bug.  Defaults to TRUE. */

#define	LISTBROWSER_Spacing			(LISTBROWSER_Dummy+32)
    /* (WORD) Defaults to 0. */

#define	LISTBROWSER_Editable		(LISTBROWSER_Dummy+33)
    /* (WORD) Defaults to FALSE. */

#define	LISTBROWSER_EditNode		(LISTBROWSER_Dummy+35)
    /* (LONG) Specify a node to edit. */

#define	LISTBROWSER_EditColumn		(LISTBROWSER_Dummy+36)
    /* (WORD) Specify a column to edit */

#define	LISTBROWSER_EditTags		(LISTBROWSER_Dummy+39)
    /* (struct TagItem *) Taglist passed to editible node string gadget.
       Defaults to NULL. */

#define	LISTBROWSER_Position		(LISTBROWSER_Dummy+34)
    /* (ULONG) See possible values below. */

#define	LISTBROWSER_RelEvent		(LISTBROWSER_Dummy+37)
    /* (ULONG) See possible values below. */

#define	LISTBROWSER_NumSelected		(LISTBROWSER_Dummy+38)
    /* (LONG) Number of selected nodes. */

#define	LISTBROWSER_RelColumn		(LISTBROWSER_Dummy+40)
    /* (WORD) Column number clicked on. */

#define	LISTBROWSER_HorizSeparators	(LISTBROWSER_Dummy+41)
    /* (BOOL) Show horizontal node separators */

#define	LISTBROWSER_CheckImage		(LISTBROWSER_Dummy+42)
    /* (struct Image *) Custom checkbox image, Checked state. */

#define	LISTBROWSER_UncheckedImage	(LISTBROWSER_Dummy+43)
    /* (struct Image *) Custom checkbox image, UnChecked state. */

#define	LISTBROWSER_TotalNodes		(LISTBROWSER_Dummy+44)
    /* (LONG) Total node count. */

#define	LISTBROWSER_MinNodeSize		(LISTBROWSER_Dummy+45)
    /* (LONG) Minimum Node size for custom MemPool custom node optimization */

#define	LISTBROWSER_TitleClickable	(LISTBROWSER_Dummy+46)
    /* (BOOL) Allow column-title bar clicking. */

#define	LISTBROWSER_MinVisible		(LISTBROWSER_Dummy+47)
    /* (LONG) Minimum visible node count. This is a causes the
     * minimum domain to be large enough to hold the specified number of
     * nodes using the the estimated average node height. Note, ESTIMATED,
     * this is not garanteed results. The result may be slightly more or
     * less than specified, and potentially alot greater if other objects
     * within the layout group cause the listbrowser to layout larger
     * than its minimum domain.
     */

#define	LISTBROWSER_Reserved6		(LISTBROWSER_Dummy+48)
    /* RESERVED */

#define	LISTBROWSER_Reserved7		(LISTBROWSER_Dummy+49)
    /* RESERVED */

#define	LISTBROWSER_PersistSelect	(LISTBROWSER_Dummy+50)
    /* (LONG) When set TRUE, SHIFT key is NOT required for multi-select. */

#define	LISTBROWSER_CursorSelect	(LISTBROWSER_Dummy+51)
    /* (LONG) Keyboard Cursor Selected Node Number */

#define	LISTBROWSER_CursorNode		(LISTBROWSER_Dummy+52)
    /* (struct Node *) Keyboard Cursor Selected Node */

#define	LISTBROWSER_FastRender		(LISTBROWSER_Dummy+53)
    /* (BOOL) Causes use of mask planes, and turns off custom pen support */
    /* The improvement with deep ECS or AGA display is *HUGE*. */

#define	LISTBROWSER_TotalVisibleNodes	(LISTBROWSER_Dummy+54)
    /* (LONG) Total visible node count. */

#define	LISTBROWSER_WrapText	(LISTBROWSER_Dummy+55)
    /* (BOOL) Enable word wrap of text nodes */

/* Possible values for LISTBROWSER_Position.
 */
#define LBP_LINEUP 1
#define LBP_LINEDOWN 2
#define LBP_PAGEUP 3
#define LBP_PAGEDOWN 4
#define LBP_TOP 5
#define LBP_BOTTOM 6
#define LBP_SHIFTLEFT 10
#define LBP_SHIFTRIGHT 11
#define LBP_LEFTEDGE 12
#define LBP_RIGHTEDGE 13

/* Possible values for LISTBROWSER_RelEvent.
 */
#define LBRE_NORMAL 1
#define LBRE_HIDECHILDREN 2
#define LBRE_SHOWCHILDREN 4
#define LBRE_EDIT 8
#define LBRE_DOUBLECLICK 16
#define LBRE_CHECKED 32
#define LBRE_UNCHECKED 64
#define LBRE_TITLECLICK 128
#define LBRE_COLUMNADJUST 256

/*****************************************************************************/

#endif /* GADGETS_LISTBROWSER_H */


include/libraries/realtime.h

#ifndef LIBRARIES_REALTIME_H
#define LIBRARIES_REALTIME_H
/*
**	$VER: realtime.h 40.3 (5.4.1993)
**	Includes Release 44.1
**
**	realtime.library timing and syncing system
**
**	(C) Copyright 1993-1999 Amiga, Inc.
**	All Rights Reserved
*/

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef EXEC_LISTS_H
#include <exec/lists.h>
#endif

#ifndef EXEC_LIBRARIES_H
#include <exec/libraries.h>
#endif

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

#ifndef UTILITY_HOOKS_H
#include <utility/hooks.h>
#endif

/*****************************************************************************/

/* realtime.library's idea of time is based on a clock which emits a pulse
 * 1200 times a second (1.2kHz). All time values maintained by realtime.library
 * are based on this number. For example, the field RealTimeBase->rtb_Time
 * expresses an amount of time equivalent to (RealTimeBase->rtb_Time/TICK_FREQ)
 * seconds.
 */
#define TICK_FREQ 1200

/*****************************************************************************/

/* Each Conductor represents a group of applications which wish to remain
 * synchronized together.
 *
 * This structure must only be allocated by realtime.library and is
 * READ-ONLY!
 */
struct Conductor
{
    struct Node    cdt_Link;
    UWORD	   cdt_Reserved0;
    struct MinList cdt_Players;		 /* this conductor's players	  */
    ULONG	   cdt_ClockTime;	 /* current time of this sequence */
    ULONG	   cdt_StartTime;	 /* start time of this sequence   */
    ULONG	   cdt_ExternalTime;	 /* time from external unit	  */
    ULONG	   cdt_MaxExternalTime;  /* upper limit on sync'd time	  */
    ULONG	   cdt_Metronome;	 /* MetricTime highest pri node   */
    UWORD	   cdt_Reserved1;
    UWORD	   cdt_Flags;		 /* conductor flags		  */
    UBYTE	   cdt_State;		 /* playing or stopped		  */
};

/* Flag bits for Conductor.cdt_Flags */
#define CONDUCTF_EXTERNAL (1<<0)   /* clock is externally driven */
#define CONDUCTF_GOTTICK  (1<<1)   /* received 1st external tick */
#define CONDUCTF_METROSET (1<<2)   /* cdt_Metronome filled in	 */
#define CONDUCTF_PRIVATE  (1<<3)   /* conductor is private	 */

#define CONDUCTB_EXTERNAL 0
#define CONDUCTB_GOTTICK  1
#define CONDUCTB_METROSET 2
#define CONDUCTB_PRIVATE  3

/* constants for Conductor.cdt_State and SetConductorState() */
#define CONDSTATE_STOPPED     0	  /* clock is stopped		   */
#define CONDSTATE_PAUSED      1	  /* clock is paused		   */
#define CONDSTATE_LOCATE      2	  /* go to 'running' when ready    */
#define CONDSTATE_RUNNING     3	  /* run clock NOW		   */

/* These do not actually exist as Conductor states, but are used as additional
 * arguments to SetConductorState()
 */
#define CONDSTATE_METRIC     -1	  /* ask high node to locate	   */
#define CONDSTATE_SHUTTLE    -2	  /* time changing but not running */
#define CONDSTATE_LOCATE_SET -3	  /* maestro done locating	   */

/*****************************************************************************/

/* The Player is the connection between a Conductor and an application.
 *
 * This structure must only be allocated by realtime.library and is
 * READ-ONLY!
 */
struct Player
{
    struct Node       pl_Link;
    BYTE	      pl_Reserved0;
    BYTE	      pl_Reserved1;
    struct Hook      *pl_Hook;		 /* player's hook function	 */
    struct Conductor *pl_Source;	 /* pointer to parent context	 */
    struct Task      *pl_Task;		 /* task to signal for alarm	 */
    LONG	      pl_MetricTime;	 /* current time in app's metric */
    LONG	      pl_AlarmTime;	 /* time to wake up		 */
    void	     *pl_UserData;	 /* for application use	 */
    UWORD	      pl_PlayerID;	 /* for application use	 */
    UWORD	      pl_Flags;	 /* general Player flags	 */
};

/* Flag bits for Player.pl_Flags */
#define PLAYERF_READY	  (1<<0)   /* player is ready to go!	    */
#define PLAYERF_ALARMSET  (1<<1)   /* alarm is set		    */
#define PLAYERF_QUIET	  (1<<2)   /* a dummy player, used for sync */
#define PLAYERF_CONDUCTED (1<<3)   /* give me metered time	    */
#define PLAYERF_EXTSYNC   (1<<4)   /* granted external sync	    */

#define PLAYERB_READY	  0
#define PLAYERB_ALARMSET  1
#define PLAYERB_QUIET	  2
#define PLAYERB_CONDUCTED 3
#define PLAYERB_EXTSYNC   4

/*****************************************************************************/

/* Tags for CreatePlayer(), SetPlayerAttrs(), and GetPlayerAttrs() */
#define PLAYER_Base	    (TAG_USER+64)
#define PLAYER_Hook	    (PLAYER_Base+1)   /* set address of hook function */
#define PLAYER_Name	    (PLAYER_Base+2)   /* name of player	      */
#define PLAYER_Priority     (PLAYER_Base+3)   /* priority of player	      */
#define PLAYER_Conductor    (PLAYER_Base+4)   /* set conductor for player     */
#define PLAYER_Ready	    (PLAYER_Base+5)   /* the "ready" flag	      */
#define PLAYER_AlarmTime    (PLAYER_Base+12)  /* alarm time (sets PLAYERF_ALARMSET) */
#define PLAYER_Alarm	    (PLAYER_Base+13)  /* sets/clears PLAYERF_ALARMSET flag  */
#define PLAYER_AlarmSigTask (PLAYER_Base+6)   /* task to signal for alarm/notify    */
#define PLAYER_AlarmSigBit  (PLAYER_Base+8)   /* signal bit for alarm (or -1) */
#define PLAYER_Conducted    (PLAYER_Base+7)   /* sets/clears PLAYERF_CONDUCTED flag   */
#define PLAYER_Quiet	    (PLAYER_Base+9)   /* don't process time thru this */
#define PLAYER_UserData     (PLAYER_Base+10)
#define PLAYER_ID	    (PLAYER_Base+11)
#define PLAYER_ExtSync	    (PLAYER_Base+14)  /* attempt/release to ext sync  */
#define PLAYER_ErrorCode    (PLAYER_Base+15)  /* error return value	      */

/*****************************************************************************/

/* Method types for messages sent via a Player's hook */
#define PM_TICK     0
#define PM_STATE    1
#define PM_POSITION 2
#define PM_SHUTTLE  3

/* used for PM_TICK, PM_POSITION and PM_SHUTTLE methods */
struct pmTime
{
    ULONG pmt_Method;	     /* PM_TICK, PM_POSITION, or PM_SHUTTLE */
    ULONG pmt_Time;
};

/* used for the PM_STATE method */
struct pmState
{
    ULONG pms_Method;	     /* PM_STATE */
    ULONG pms_OldState;
};

/*****************************************************************************/

/* Possible lock types for LockRealTime() */
#define RT_CONDUCTORS 0   /* conductor list */

/*****************************************************************************/

/* realtime.library error codes */
#define RTE_NOMEMORY	801   /* memory allocation failed      */
#define RTE_NOCONDUCTOR 802   /* player needs a conductor      */
#define RTE_NOTIMER	803   /* timer (CIA) allocation failed */
#define RTE_PLAYING	804   /* can't shuttle while playing   */

/*****************************************************************************/

/* OpenLibrary("realtime.library",0) returns a pointer to this structure.
 * All fields are READ-ONLY.
 */
struct RealTimeBase
{
    struct Library rtb_LibNode;
    UBYTE	   rtb_Reserved0[2];

    ULONG	   rtb_Time;	     /* current time			     */
    ULONG	   rtb_TimeFrac;     /* fixed-point fraction part of time    */
    UWORD	   rtb_Reserved1;
    WORD	   rtb_TickErr;      /* nanosecond error from ideal Tick     */
};				     /* length to real tick length	     */

/* Actual tick length is: 1/TICK_FREQ + rtb_TickErr/1e9 */

#define RealTime_TickErr_Min -705
#define RealTime_TickErr_Max  705

/*****************************************************************************/

#endif /* LIBRARIES_REALTIME_H */


include/libraries/configvars.h

#ifndef LIBRARIES_CONFIGVARS_H
#define LIBRARIES_CONFIGVARS_H
/*
**	$VER: configvars.h 36.14 (22.4.1991)
**	Includes Release 44.1
**
**	Software structures used by AutoConfig (tm) boards
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef	EXEC_TYPES_H
#include <exec/types.h>
#endif	/* EXEC_TYPES_H */

#ifndef EXEC_NODES_H
#include <exec/nodes.h>
#endif /* EXEC_NODES_H */

#ifndef LIBRARIES_CONFIGREGS_H
#include <libraries/configregs.h>
#endif /* LIBRARIES_CONFIGREGS_H */

/*
** At early system startup time, one ConfigDev structure is created for
** each board found in the system.  Software may seach for ConfigDev
** structures by vendor & product ID number.  For debugging and diagnostic
** use, the entire list can be accessed.  See the expansion.library document
** for more information.
*/
struct ConfigDev {
    struct Node		cd_Node;
    UBYTE		cd_Flags;	/* (read/write) */
    UBYTE		cd_Pad;		/* reserved */
    struct ExpansionRom	cd_Rom;		/* copy of board's expansion ROM */
    APTR		cd_BoardAddr; /* where in memory the board was placed */
    ULONG		cd_BoardSize;	/* size of board in bytes */
    UWORD		cd_SlotAddr;	/* which slot number (PRIVATE) */
    UWORD		cd_SlotSize;	/* number of slots (PRIVATE) */
    APTR		cd_Driver;	/* pointer to node of driver */
    struct ConfigDev *	cd_NextCD;	/* linked list of drivers to config */
    ULONG		cd_Unused[4];	/* for whatever the driver wants */
};

/* cd_Flags */
#define	CDB_SHUTUP	0	/* this board has been shut up */
#define	CDB_CONFIGME	1	/* this board needs a driver to claim it */
#define	CDB_BADMEMORY	2	/* this board contains bad memory */
#define	CDB_PROCESSED	3	/* private flag */

#define	CDF_SHUTUP	0x01
#define	CDF_CONFIGME	0x02
#define	CDF_BADMEMORY	0x04
#define	CDF_PROCESSED	0x08

/*
** Boards are usually "bound" to software drivers.
** This structure is used by GetCurrentBinding() and SetCurrentBinding()
*/
struct CurrentBinding {
    struct ConfigDev *	cb_ConfigDev;		/* first configdev in chain */
    UBYTE *		cb_FileName;		/* file name of driver */
    UBYTE *		cb_ProductString;	/* product # string */
    UBYTE **		cb_ToolTypes;		/* tooltypes from disk object */
};

#endif /* LIBRARIES_CONFIGVARS_H */


include/devices/conunit.h

#ifndef DEVICES_CONUNIT_H
#define DEVICES_CONUNIT_H
/*
**	$VER: conunit.h 36.15 (20.11.1990)
**	Includes Release 44.1
**
**	Console device unit definitions
**
**	(C) Copyright 1986-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef	EXEC_TYPES_H
#include	<exec/types.h>
#endif

#ifndef EXEC_PORTS_H
#include	<exec/ports.h>
#endif

#ifndef DEVICES_CONSOLE_H
#include	<devices/console.h>
#endif

#ifndef DEVICES_KEYMAP_H
#include	<devices/keymap.h>
#endif

#ifndef DEVICES_INPUTEVENT_H
#include	<devices/inputevent.h>
#endif

/* ----	console unit numbers for OpenDevice() */
#define	CONU_LIBRARY	-1	/* no unit, just fill in IO_DEVICE field */
#define	CONU_STANDARD	0	/* standard unmapped console */

/* ---- New unit numbers for OpenDevice() - (V36) */

#define	CONU_CHARMAP	1	/* bind character map to console */
#define	CONU_SNIPMAP	3	/* bind character map w/ snip to console */

/* ---- New flag defines for OpenDevice() - (V37) */

#define CONFLAG_DEFAULT			0
#define CONFLAG_NODRAW_ON_NEWSIZE	1

#define	PMB_ASM		(M_LNM+1)	/* internal storage bit for AS flag */
#define	PMB_AWM		(PMB_ASM+1)	/* internal storage bit for AW flag */
#define	MAXTABS		80

struct	ConUnit {
    struct  MsgPort cu_MP;
    /* ---- read only variables */
    struct  Window *cu_Window;	/* intuition window bound to this unit */
    WORD    cu_XCP;		/* character position */
    WORD    cu_YCP;
    WORD    cu_XMax;		/* max character position */
    WORD    cu_YMax;
    WORD    cu_XRSize;		/* character raster size */
    WORD    cu_YRSize;
    WORD    cu_XROrigin;	/* raster origin */
    WORD    cu_YROrigin;
    WORD    cu_XRExtant;	/* raster maxima */
    WORD    cu_YRExtant;
    WORD    cu_XMinShrink;	/* smallest area intact from resize process */
    WORD    cu_YMinShrink;
    WORD    cu_XCCP;		/* cursor position */
    WORD    cu_YCCP;

    /* ---- read/write variables (writes must must be protected) */
    /* ---- storage for AskKeyMap and SetKeyMap */
    struct  KeyMap cu_KeyMapStruct;
    /* ---- tab stops */
    UWORD   cu_TabStops[MAXTABS]; /* 0 at start, 0xffff at end of list */

    /* ---- console rastport attributes */
    BYTE    cu_Mask;
    BYTE    cu_FgPen;
    BYTE    cu_BgPen;
    BYTE    cu_AOLPen;
    BYTE    cu_DrawMode;
    BYTE    cu_Obsolete1;	/* was cu_AreaPtSz -- not used in V36 */
    APTR    cu_Obsolete2;	/* was cu_AreaPtrn -- not used in V36 */
    UBYTE   cu_Minterms[8];	/* console minterms */
    struct  TextFont *cu_Font;
    UBYTE   cu_AlgoStyle;
    UBYTE   cu_TxFlags;
    UWORD   cu_TxHeight;
    UWORD   cu_TxWidth;
    UWORD   cu_TxBaseline;
    WORD    cu_TxSpacing;

    /* ---- console MODES and RAW EVENTS switches */
    UBYTE   cu_Modes[(PMB_AWM+7)/8];	/* one bit per mode */
    UBYTE   cu_RawEvents[(IECLASS_MAX+8)/8];
};

#endif	/* DEVICES_CONUNIT_H */


include/graphics/copper.h

#ifndef GRAPHICS_COPPER_H
#define GRAPHICS_COPPER_H
/*
**	$VER: copper.h 39.10 (31.5.1993)
**	Includes Release 44.1
**
**	graphics copper list intstruction definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#define COPPER_MOVE 0	    /* pseude opcode for move #XXXX,dir */
#define COPPER_WAIT 1	    /* pseudo opcode for wait y,x */
#define CPRNXTBUF   2	    /* continue processing with next buffer */
#define CPR_NT_LOF  0x8000  /* copper instruction only for short frames */
#define CPR_NT_SHT  0x4000  /* copper instruction only for long frames */
#define CPR_NT_SYS  0x2000  /* copper user instruction only */

struct CopIns
{
    WORD   OpCode; /* 0 = move, 1 = wait */
    union
    {
        struct CopList *nxtlist;
        struct
    {
            union
            {
                WORD VWaitPos;	      /* vertical beam wait */
                WORD DestAddr;	      /* destination address of copper move */
            } u1;
            union
            {
                WORD HWaitPos;	      /* horizontal beam wait position */
                WORD DestData;	      /* destination immediate data to send */
            } u2;
        } u4;
    } u3;
};

/* shorthand for above */
#define NXTLIST     u3.nxtlist
#define VWAITPOS    u3.u4.u1.VWaitPos
#define DESTADDR    u3.u4.u1.DestAddr
#define HWAITPOS    u3.u4.u2.HWaitPos
#define DESTDATA    u3.u4.u2.DestData

/* structure of cprlist that points to list that hardware actually executes */
struct cprlist
{
    struct cprlist *Next;
    UWORD   *start;	    /* start of copper list */
    WORD   MaxCount;	   /* number of long instructions */
};

struct CopList
{
    struct  CopList *Next;  /* next block for this copper list */
    struct  CopList *_CopList;	/* system use */
    struct  ViewPort *_ViewPort;    /* system use */
    struct  CopIns *CopIns; /* start of this block */
    struct  CopIns *CopPtr; /* intermediate ptr */
    UWORD   *CopLStart;     /* mrgcop fills this in for Long Frame*/
    UWORD   *CopSStart;     /* mrgcop fills this in for Short Frame*/
    WORD   Count;	   /* intermediate counter */
    WORD   MaxCount;	   /* max # of copins for this block */
    WORD   DyOffset;	   /* offset this copper list vertical waits */
#ifdef V1_3
    UWORD   *Cop2Start;
    UWORD   *Cop3Start;
    UWORD   *Cop4Start;
    UWORD   *Cop5Start;
#endif
    UWORD  SLRepeat;
    UWORD  Flags;
};

/* These CopList->Flags are private */
#define EXACT_LINE 1
#define HALF_LINE 2

struct UCopList
{
    struct UCopList *Next;
    struct CopList  *FirstCopList; /* head node of this copper list */
    struct CopList  *CopList;	   /* node in use */
};

/* Private graphics data structure. This structure has changed in the past,
 * and will continue to change in the future. Do Not Touch!
 */

struct copinit
{
    UWORD vsync_hblank[2];
    UWORD diagstrt[12];      /* copper list for first bitplane */
    UWORD fm0[2];
    UWORD diwstart[10];
    UWORD bplcon2[2];
    UWORD sprfix[2*8];
    UWORD sprstrtup[(2*8*2)];
    UWORD wait14[2];
    UWORD norm_hblank[2];
    UWORD jump[2];
    UWORD wait_forever[6];
    UWORD   sprstop[8];
};

#endif	/* GRAPHICS_COPPER_H */


include/prefs/locale.h

#ifndef PREFS_LOCALE_H
#define PREFS_LOCALE_H
/*
**	$VER: locale.h 38.4 (5.12.1991)
**	Includes Release 44.1
**
**	File format for locale preferences
**
**	(C) Copyright 1991-1999 Amiga, Inc.
**	All Rights Reserved
*/

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef LIBRARIES_IFFPARSE_H
#include <libraries/iffparse.h>
#endif

/*****************************************************************************/

#define ID_LCLE MAKE_ID('L','C','L','E')
#define ID_CTRY MAKE_ID('C','T','R','Y')

struct CountryPrefs
{
    ULONG cp_Reserved[4];
    ULONG cp_CountryCode;
    ULONG cp_TelephoneCode;
    UBYTE cp_MeasuringSystem;

    char  cp_DateTimeFormat[80];
    char  cp_DateFormat[40];
    char  cp_TimeFormat[40];

    char  cp_ShortDateTimeFormat[80];
    char  cp_ShortDateFormat[40];
    char  cp_ShortTimeFormat[40];

    /* for numeric values */
    char  cp_DecimalPoint[10];
    char  cp_GroupSeparator[10];
    char  cp_FracGroupSeparator[10];
    UBYTE cp_Grouping[10];
    UBYTE cp_FracGrouping[10];

    /* for monetary values */
    char  cp_MonDecimalPoint[10];
    char  cp_MonGroupSeparator[10];
    char  cp_MonFracGroupSeparator[10];
    UBYTE cp_MonGrouping[10];
    UBYTE cp_MonFracGrouping[10];
    UBYTE cp_MonFracDigits;
    UBYTE cp_MonIntFracDigits;

    /* for currency symbols */
    char  cp_MonCS[10];
    char  cp_MonSmallCS[10];
    char  cp_MonIntCS[10];

    /* for positive monetary values */
    char  cp_MonPositiveSign[10];
    UBYTE cp_MonPositiveSpaceSep;
    UBYTE cp_MonPositiveSignPos;
    UBYTE cp_MonPositiveCSPos;

    /* for negative monetary values */
    char  cp_MonNegativeSign[10];
    UBYTE cp_MonNegativeSpaceSep;
    UBYTE cp_MonNegativeSignPos;
    UBYTE cp_MonNegativeCSPos;

    UBYTE cp_CalendarType;
};

struct LocalePrefs
{
    ULONG		lp_Reserved[4];
    char		lp_CountryName[32];
    char		lp_PreferredLanguages[10][30];
    LONG		lp_GMTOffset;
    ULONG		lp_Flags;
    struct CountryPrefs lp_CountryData;
};

/*****************************************************************************/

#endif /* PREFS_LOCALE_H */


include/dos/rdargs.h

#ifndef DOS_RDARGS_H
#define DOS_RDARGS_H
/*
**
**	$VER: rdargs.h 36.6 (12.7.1990)
**	Includes Release 44.1
**
**	ReadArgs() structure definitions
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef EXEC_NODES_H
#include <exec/nodes.h>
#endif

/**********************************************************************
 *
 * The CSource data structure defines the input source for "ReadItem()"
 * as well as the ReadArgs call.  It is a publicly defined structure
 * which may be used by applications which use code that follows the
 * conventions defined for access.
 *
 * When passed to the dos.library functions, the value passed as
 * struct *CSource is defined as follows:
 *	if ( CSource == 0)	Use buffered IO "ReadChar()" as data source
 *	else			Use CSource for input character stream
 *
 * The following two pseudo-code routines define how the CSource structure
 * is used:
 *
 * long CS_ReadChar( struct CSource *CSource )
 * {
 *	if ( CSource == 0 )	return ReadChar();
 *	if ( CSource->CurChr >= CSource->Length )	return ENDSTREAMCHAR;
 *	return CSource->Buffer[ CSource->CurChr++ ];
 * }
 *
 * BOOL CS_UnReadChar( struct CSource *CSource )
 * {
 *	if ( CSource == 0 )	return UnReadChar();
 *	if ( CSource->CurChr <= 0 )	return FALSE;
 *	CSource->CurChr--;
 *	return TRUE;
 * }
 *
 * To initialize a struct CSource, you set CSource->CS_Buffer to
 * a string which is used as the data source, and set CS_Length to
 * the number of characters in the string.  Normally CS_CurChr should
 * be initialized to ZERO, or left as it was from prior use as
 * a CSource.
 *
 **********************************************************************/

struct CSource {
    UBYTE	*CS_Buffer;
    LONG	CS_Length;
    LONG	CS_CurChr;
};

/**********************************************************************
 *
 * The RDArgs data structure is the input parameter passed to the DOS
 * ReadArgs() function call.
 *
 * The RDA_Source structure is a CSource as defined above;
 * if RDA_Source.CS_Buffer is non-null, RDA_Source is used as the input
 * character stream to parse, else the input comes from the buffered STDIN
 * calls ReadChar/UnReadChar.
 *
 * RDA_DAList is a private address which is used internally to track
 * allocations which are freed by FreeArgs().  This MUST be initialized
 * to NULL prior to the first call to ReadArgs().
 *
 * The RDA_Buffer and RDA_BufSiz fields allow the application to supply
 * a fixed-size buffer in which to store the parsed data.  This allows
 * the application to pre-allocate a buffer rather than requiring buffer
 * space to be allocated.  If either RDA_Buffer or RDA_BufSiz is NULL,
 * the application has not supplied a buffer.
 *
 * RDA_ExtHelp is a text string which will be displayed instead of the
 * template string, if the user is prompted for input.
 *
 * RDA_Flags bits control how ReadArgs() works.  The flag bits are
 * defined below.  Defaults are initialized to ZERO.
 *
 **********************************************************************/

struct RDArgs {
    struct	CSource RDA_Source;	/* Select input source */
    LONG	RDA_DAList;		/* PRIVATE. */
    UBYTE	*RDA_Buffer;		/* Optional string parsing space. */
    LONG	RDA_BufSiz;		/* Size of RDA_Buffer (0..n) */
    UBYTE	*RDA_ExtHelp;		/* Optional extended help */
    LONG	RDA_Flags;		/* Flags for any required control */
};

#define RDAB_STDIN	0	/* Use "STDIN" rather than "COMMAND LINE" */
#define RDAF_STDIN	1
#define RDAB_NOALLOC	1	/* If set, do not allocate extra string space.*/
#define RDAF_NOALLOC	2
#define RDAB_NOPROMPT	2	/* Disable reprompting for string input. */
#define RDAF_NOPROMPT	4

/**********************************************************************
 * Maximum number of template keywords which can be in a template passed
 * to ReadArgs(). IMPLEMENTOR NOTE - must be a multiple of 4.
 **********************************************************************/
#define MAX_TEMPLATE_ITEMS	100

/**********************************************************************
 * Maximum number of MULTIARG items returned by ReadArgs(), before
 * an ERROR_LINE_TOO_LONG.  These two limitations are due to stack
 * usage.  Applications should allow "a lot" of stack to use ReadArgs().
 **********************************************************************/
#define MAX_MULTIARGS		128

#endif /* DOS_RDARGS_H */


include/hardware/custom.h

#ifndef	HARDWARE_CUSTOM_H
#define	HARDWARE_CUSTOM_H
/*
**	$VER: custom.h 39.1 (18.9.1992)
**	Includes Release 44.1
**
**	Offsets of Amiga custom chip registers
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif /* EXEC_TYPES_H */

/*
 * do this to get base of custom registers:
 * extern struct Custom custom;
 */

struct Custom {
    UWORD   bltddat;
    UWORD   dmaconr;
    UWORD   vposr;
    UWORD   vhposr;
    UWORD   dskdatr;
    UWORD   joy0dat;
    UWORD   joy1dat;
    UWORD   clxdat;
    UWORD   adkconr;
    UWORD   pot0dat;
    UWORD   pot1dat;
    UWORD   potinp;
    UWORD   serdatr;
    UWORD   dskbytr;
    UWORD   intenar;
    UWORD   intreqr;
    APTR    dskpt;
    UWORD   dsklen;
    UWORD   dskdat;
    UWORD   refptr;
    UWORD   vposw;
    UWORD   vhposw;
    UWORD   copcon;
    UWORD   serdat;
    UWORD   serper;
    UWORD   potgo;
    UWORD   joytest;
    UWORD   strequ;
    UWORD   strvbl;
    UWORD   strhor;
    UWORD   strlong;
    UWORD   bltcon0;
    UWORD   bltcon1;
    UWORD   bltafwm;
    UWORD   bltalwm;
    APTR    bltcpt;
    APTR    bltbpt;
    APTR    bltapt;
    APTR    bltdpt;
    UWORD   bltsize;
    UBYTE   pad2d;
    UBYTE   bltcon0l;	/* low 8 bits of bltcon0, write only */
    UWORD   bltsizv;
    UWORD   bltsizh;	/* 5e */
    UWORD   bltcmod;
    UWORD   bltbmod;
    UWORD   bltamod;
    UWORD   bltdmod;
    UWORD   pad34[4];
    UWORD   bltcdat;
    UWORD   bltbdat;
    UWORD   bltadat;
    UWORD   pad3b[3];
    UWORD   deniseid;	/* 7c */
    UWORD   dsksync;
    ULONG   cop1lc;
    ULONG   cop2lc;
    UWORD   copjmp1;
    UWORD   copjmp2;
    UWORD   copins;
    UWORD   diwstrt;
    UWORD   diwstop;
    UWORD   ddfstrt;
    UWORD   ddfstop;
    UWORD   dmacon;
    UWORD   clxcon;
    UWORD   intena;
    UWORD   intreq;
    UWORD   adkcon;
    struct  AudChannel {
      UWORD *ac_ptr; /* ptr to start of waveform data */
      UWORD ac_len;	/* length of waveform in words */
      UWORD ac_per;	/* sample period */
      UWORD ac_vol;	/* volume */
      UWORD ac_dat;	/* sample pair */
      UWORD ac_pad[2];	/* unused */
    } aud[4];
    APTR    bplpt[8];
    UWORD   bplcon0;
    UWORD   bplcon1;
    UWORD   bplcon2;
    UWORD   bplcon3;
    UWORD   bpl1mod;
    UWORD   bpl2mod;
    UWORD   bplcon4;
    UWORD   clxcon2;
    UWORD   bpldat[8];
    APTR    sprpt[8];
    struct  SpriteDef {
      UWORD pos;
      UWORD ctl;
      UWORD dataa;
      UWORD datab;
    } spr[8];
    UWORD   color[32];
    UWORD htotal;
    UWORD hsstop;
    UWORD hbstrt;
    UWORD hbstop;
    UWORD vtotal;
    UWORD vsstop;
    UWORD vbstrt;
    UWORD vbstop;
    UWORD sprhstrt;
    UWORD sprhstop;
    UWORD bplhstrt;
    UWORD bplhstop;
    UWORD hhposw;
    UWORD hhposr;
    UWORD beamcon0;
    UWORD hsstrt;
    UWORD vsstrt;
    UWORD hcenter;
    UWORD diwhigh;	/* 1e4 */
    UWORD padf3[11];
    UWORD fmode;
};

#ifdef ECS_SPECIFIC

/* defines for beamcon register */
#define VARVBLANK	0x1000	/* Variable vertical blank enable */
#define LOLDIS		0x0800	/* long line disable */
#define CSCBLANKEN	0x0400	/* redirect composite sync */
#define VARVSYNC	0x0200	/* Variable vertical sync enable */
#define VARHSYNC	0x0100	/* Variable horizontal sync enable */
#define VARBEAM	0x0080	/* variable beam counter enable */
#define DISPLAYDUAL	0x0040	/* use UHRES pointer and standard pointers */
#define DISPLAYPAL	0x0020	/* set decodes to generate PAL display */
#define VARCSYNC	0x0010	/* Variable composite sync enable */
#define CSBLANK	0x0008	/* Composite blank out to CSY* pin */
#define CSYNCTRUE	0x0004	/* composite sync true signal */
#define VSYNCTRUE	0x0002	/* vertical sync true */
#define HSYNCTRUE	0x0001	/* horizontal sync true */

/* new defines for bplcon0 */
#define USE_BPLCON3	1

/* new defines for bplcon2 */
#define BPLCON2_ZDCTEN		(1<<10) /* colormapped genlock bit */
#define BPLCON2_ZDBPEN		(1<<11) /* use bitplane as genlock bits */
#define BPLCON2_ZDBPSEL0	(1<<12) /* three bits to select one */
#define BPLCON2_ZDBPSEL1	(1<<13) /* of 8 bitplanes in */
#define BPLCON2_ZDBPSEL2	(1<<14) /* ZDBPEN genlock mode */

/* defines for bplcon3 register */
#define BPLCON3_EXTBLNKEN	(1<<0)	/* external blank enable */
#define BPLCON3_EXTBLKZD	(1<<1)	/* external blank ored into trnsprncy */
#define BPLCON3_ZDCLKEN	(1<<2)	/* zd pin outputs a 14mhz clock*/
#define BPLCON3_BRDNTRAN	(1<<4)	/* border is opaque */
#define BPLCON3_BRDNBLNK	(1<<5)	/* border is opaque */

#endif	/* ECS_SPECIFIC */

#endif	/* HARDWARE_CUSTOM_H */


include/datatypes/datatypes.h

#ifndef  DATATYPES_DATATYPES_H
#define  DATATYPES_DATATYPES_H
/*
**	$VER: datatypes.h 39.6 (22.4.1993)
**	Includes Release 44.1
**
**	Copyright © 1991-1999 Amiga, Inc.
**	    All Rights Reserved
*/

/*****************************************************************************/

#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif
#ifndef  EXEC_LISTS_H
#include <exec/lists.h>
#endif
#ifndef  EXEC_NODES_H
#include <exec/nodes.h>
#endif
#ifndef  EXEC_LIBRARIES_H
#include <exec/libraries.h>
#endif
#ifndef  LIBRARIES_IFFPARSE_H
#include <libraries/iffparse.h>
#endif
#ifndef	DOS_DOS_H
#include <dos/dos.h>
#endif

/*****************************************************************************/

#define ID_DTYP MAKE_ID('D','T','Y','P')

/*****************************************************************************/

#define ID_DTHD MAKE_ID('D','T','H','D')

struct DataTypeHeader
{
    STRPTR	 dth_Name;				/* Descriptive name of the data type */
    STRPTR	 dth_BaseName;				/* Base name of the data type */
    STRPTR	 dth_Pattern;				/* Match pattern for file name. */
    WORD	*dth_Mask;				/* Comparision mask */
    ULONG	 dth_GroupID;				/* Group that the DataType is in */
    ULONG	 dth_ID;				/* ID for DataType (same as IFF FORM type) */
    WORD	 dth_MaskLen;				/* Length of comparision mask */
    WORD	 dth_Pad;				/* Unused at present (must be 0) */
    UWORD	 dth_Flags;				/* Flags */
    UWORD	 dth_Priority;				/* Priority */
};

#define	DTHSIZE	sizeof(struct DataTypeHeader)

/*****************************************************************************/

/* Basic type */
#define	DTF_TYPE_MASK	0x000F
#define	DTF_BINARY	0x0000
#define	DTF_ASCII	0x0001
#define	DTF_IFF		0x0002
#define	DTF_MISC	0x0003

/* Set if case is important */
#define	DTF_CASE	0x0010

/* Reserved for system use */
#define	DTF_SYSTEM1	0x1000

/*****************************************************************************
 *
 * GROUP ID and ID
 *
 * This is used for filtering out objects that you don't want.	For
 * example, you could make a filter for the ASL file requester so
 * that it only showed the files that were pictures, or even to
 * narrow it down to only show files that were ILBM pictures.
 *
 * Note that the Group ID's are in lower case, and always the first
 * four characters of the word.
 *
 * For ID's; If it is an IFF file, then the ID is the same as the
 * FORM type.  If it isn't an IFF file, then the ID would be the
 * first four characters of name for the file type.
 *
 *****************************************************************************/

/* System file, such as; directory, executable, library, device, font, etc. */
#define	GID_SYSTEM	MAKE_ID ('s','y','s','t')

/* Formatted or unformatted text */
#define	GID_TEXT	MAKE_ID ('t','e','x','t')

/* Formatted text with graphics or other DataTypes */
#define	GID_DOCUMENT	MAKE_ID ('d','o','c','u')

/* Sound */
#define	GID_SOUND	MAKE_ID ('s','o','u','n')

/* Musical instruments used for musical scores */
#define	GID_INSTRUMENT	MAKE_ID ('i','n','s','t')

/* Musical score */
#define	GID_MUSIC	MAKE_ID ('m','u','s','i')

/* Still picture */
#define	GID_PICTURE	MAKE_ID ('p','i','c','t')

/* Animated picture */
#define	GID_ANIMATION	MAKE_ID ('a','n','i','m')

/* Animation with audio track */
#define	GID_MOVIE	MAKE_ID ('m','o','v','i')

/*****************************************************************************/

/* A code chunk contains an embedded executable that can be loaded
 * with InternalLoadSeg. */
#define ID_CODE MAKE_ID('D','T','C','D')

/* DataTypes comparision hook context (Read-Only).  This is the
 * argument that is passed to a custom comparision routine. */
struct DTHookContext
{
    /* Libraries that are already opened for your use */
    struct Library		*dthc_SysBase;
    struct Library		*dthc_DOSBase;
    struct Library		*dthc_IFFParseBase;
    struct Library		*dthc_UtilityBase;

    /* File context */
    BPTR			 dthc_Lock;		/* Lock on the file */
    struct FileInfoBlock	*dthc_FIB;		/* Pointer to a FileInfoBlock */
    BPTR			 dthc_FileHandle;	/* Pointer to the file handle (may be NULL) */
    struct IFFHandle		*dthc_IFF;		/* Pointer to an IFFHandle (may be NULL) */
    STRPTR			 dthc_Buffer;		/* Buffer */
    ULONG			 dthc_BufferLength;	/* Length of the buffer */
};

/*****************************************************************************/

#define ID_TOOL MAKE_ID('D','T','T','L')

struct Tool
{
    UWORD	 tn_Which;				/* Which tool is this */
    UWORD	 tn_Flags;				/* Flags */
    STRPTR	 tn_Program;				/* Application to use */
};

#define	TSIZE	sizeof(struct Tool)

/* defines for tn_Which */
#define	TW_INFO			1
#define	TW_BROWSE		2
#define	TW_EDIT			3
#define	TW_PRINT		4
#define	TW_MAIL			5

/* defines for tn_Flags */
#define	TF_LAUNCH_MASK		0x000F
#define	TF_SHELL		0x0001
#define	TF_WORKBENCH		0x0002
#define	TF_RX			0x0003

/*****************************************************************************/

#define	ID_TAGS	MAKE_ID('D','T','T','G')

/*****************************************************************************/

#ifndef	DATATYPE
#define	DATATYPE
struct DataType
{
    struct Node			 dtn_Node1;		/* Reserved for system use */
    struct Node			 dtn_Node2;		/* Reserved for system use */
    struct DataTypeHeader	*dtn_Header;		/* Pointer to the DataTypeHeader */
    struct List			 dtn_ToolList;		/* List of tool nodes */
    STRPTR			 dtn_FunctionName;	/* Name of comparision routine */
    struct TagItem		*dtn_AttrList;		/* Object creation tags */
    ULONG			 dtn_Length;		/* Length of the memory block */
};
#endif

#define	DTNSIZE	sizeof(struct DataType)

/*****************************************************************************/

struct ToolNode
{
    struct Node	 tn_Node;				/* Embedded node */
    struct Tool  tn_Tool;				/* Embedded tool */
    ULONG	 tn_Length;				/* Length of the memory block */
};

#define	TNSIZE	sizeof(struct ToolNode)

/*****************************************************************************/

#ifndef	ID_NAME
#define	ID_NAME	MAKE_ID('N','A','M','E')
#endif

/*****************************************************************************/

/* Text ID's */
#define DTERROR_UNKNOWN_DATATYPE		2000
#define DTERROR_COULDNT_SAVE			2001
#define DTERROR_COULDNT_OPEN			2002
#define DTERROR_COULDNT_SEND_MESSAGE		2003

/* New for V40 */
#define	DTERROR_COULDNT_OPEN_CLIPBOARD		2004
#define	DTERROR_Reserved			2005
#define	DTERROR_UNKNOWN_COMPRESSION		2006
#define	DTERROR_NOT_ENOUGH_DATA			2007
#define	DTERROR_INVALID_DATA			2008

/* New for V44 */
#define	DTERROR_NOT_AVAILABLE			2009

/* Offset for types */
#define	DTMSG_TYPE_OFFSET			2100

/*****************************************************************************/

#endif	 /* DATATYPES_DATATYPES_H */


include/dos/dos.h

#ifndef DOS_DOS_H
#define DOS_DOS_H
/*
**	$VER: dos.h 36.27 (5.4.1992)
**	Includes Release 44.1
**
**	Standard C header for AmigaDOS
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#define	 DOSNAME  "dos.library"

/* Predefined Amiga DOS global constants */

#define DOSTRUE (-1L)
#define DOSFALSE (0L)

/* Mode parameter to Open() */
#define MODE_OLDFILE	     1005   /* Open existing file read/write
                     * positioned at beginning of file. */
#define MODE_NEWFILE	     1006   /* Open freshly created file (delete
                     * old file) read/write, exclusive lock. */
#define MODE_READWRITE	     1004   /* Open old file w/shared lock,
                     * creates file if doesn't exist. */

/* Relative position to Seek() */
#define OFFSET_BEGINNING    -1	    /* relative to Begining Of File */
#define OFFSET_CURRENT	     0	    /* relative to Current file position */
#define OFFSET_END	     1	    /* relative to End Of File	  */

#define OFFSET_BEGINING	    OFFSET_BEGINNING  /* ancient compatibility */

#define BITSPERBYTE	     8
#define BYTESPERLONG	     4
#define BITSPERLONG	     32
#define MAXINT		     0x7FFFFFFF
#define MININT		     0x80000000

/* Passed as type to Lock() */
#define SHARED_LOCK	     -2	    /* File is readable by others */
#define ACCESS_READ	     -2	    /* Synonym */
#define EXCLUSIVE_LOCK	     -1	    /* No other access allowed	  */
#define ACCESS_WRITE	     -1	    /* Synonym */

struct DateStamp {
   LONG	 ds_Days;	      /* Number of days since Jan. 1, 1978 */
   LONG	 ds_Minute;	      /* Number of minutes past midnight */
   LONG	 ds_Tick;	      /* Number of ticks past minute */
}; /* DateStamp */

#define TICKS_PER_SECOND      50   /* Number of ticks in one second */

/* Returned by Examine() and ExNext(), must be on a 4 byte boundary */
struct FileInfoBlock {
   LONG	  fib_DiskKey;
   LONG	  fib_DirEntryType;  /* Type of Directory. If < 0, then a plain file.
                  * If > 0 a directory */
   char	  fib_FileName[108]; /* Null terminated. Max 30 chars used for now */
   LONG	  fib_Protection;    /* bit mask of protection, rwxd are 3-0.	   */
   LONG	  fib_EntryType;
   LONG	  fib_Size;	     /* Number of bytes in file */
   LONG	  fib_NumBlocks;     /* Number of blocks in file */
   struct DateStamp fib_Date;/* Date file last changed */
   char	  fib_Comment[80];  /* Null terminated comment associated with file */

   /* Note: the following fields are not supported by all filesystems.	*/
   /* They should be initialized to 0 sending an ACTION_EXAMINE packet.	*/
   /* When Examine() is called, these are set to 0 for you.		*/
   /* AllocDosObject() also initializes them to 0.			*/
   UWORD  fib_OwnerUID;		/* owner's UID */
   UWORD  fib_OwnerGID;		/* owner's GID */

   char	  fib_Reserved[32];
}; /* FileInfoBlock */

/* FIB stands for FileInfoBlock */

/* FIBB are bit definitions, FIBF are field definitions */
/* Regular RWED bits are 0 == allowed. */
/* NOTE: GRP and OTR RWED permissions are 0 == not allowed! */
/* Group and Other permissions are not directly handled by the filesystem */
#define FIBB_OTR_READ	   15	/* Other: file is readable */
#define FIBB_OTR_WRITE	   14	/* Other: file is writable */
#define FIBB_OTR_EXECUTE   13	/* Other: file is executable */
#define FIBB_OTR_DELETE    12	/* Other: prevent file from being deleted */
#define FIBB_GRP_READ	   11	/* Group: file is readable */
#define FIBB_GRP_WRITE	   10	/* Group: file is writable */
#define FIBB_GRP_EXECUTE   9	/* Group: file is executable */
#define FIBB_GRP_DELETE    8	/* Group: prevent file from being deleted */

#define FIBB_SCRIPT    6	/* program is a script (execute) file */
#define FIBB_PURE      5	/* program is reentrant and rexecutable */
#define FIBB_ARCHIVE   4	/* cleared whenever file is changed */
#define FIBB_READ      3	/* ignored by old filesystem */
#define FIBB_WRITE     2	/* ignored by old filesystem */
#define FIBB_EXECUTE   1	/* ignored by system, used by Shell */
#define FIBB_DELETE    0	/* prevent file from being deleted */

#define FIBF_OTR_READ	   (1<<FIBB_OTR_READ)
#define FIBF_OTR_WRITE	   (1<<FIBB_OTR_WRITE)
#define FIBF_OTR_EXECUTE   (1<<FIBB_OTR_EXECUTE)
#define FIBF_OTR_DELETE    (1<<FIBB_OTR_DELETE)
#define FIBF_GRP_READ	   (1<<FIBB_GRP_READ)
#define FIBF_GRP_WRITE	   (1<<FIBB_GRP_WRITE)
#define FIBF_GRP_EXECUTE   (1<<FIBB_GRP_EXECUTE)
#define FIBF_GRP_DELETE    (1<<FIBB_GRP_DELETE)

#define FIBF_SCRIPT    (1<<FIBB_SCRIPT)
#define FIBF_PURE      (1<<FIBB_PURE)
#define FIBF_ARCHIVE   (1<<FIBB_ARCHIVE)
#define FIBF_READ      (1<<FIBB_READ)
#define FIBF_WRITE     (1<<FIBB_WRITE)
#define FIBF_EXECUTE   (1<<FIBB_EXECUTE)
#define FIBF_DELETE    (1<<FIBB_DELETE)

/* Standard maximum length for an error string from fault.  However, most */
/* error strings should be kept under 60 characters if possible.  Don't   */
/* forget space for the header you pass in. */
#define FAULT_MAX	82

/* All BCPL data must be long word aligned.  BCPL pointers are the long word
 *  address (i.e byte address divided by 4 (>>2)) */
typedef long  BPTR;		    /* Long word pointer */
typedef long  BSTR;		    /* Long word pointer to BCPL string	 */

/* Convert BPTR to typical C pointer */
#ifdef OBSOLETE_LIBRARIES_DOS_H
#define BADDR( bptr )	(((ULONG)bptr) << 2)
#else
/* This one has no problems with CASTing */
#define BADDR(x)	((APTR)((ULONG)(x) << 2))
#endif
/* Convert address into a BPTR */
#define MKBADDR(x)	(((LONG)(x)) >> 2)

/* BCPL strings have a length in the first byte and then the characters.
 * For example:	 s[0]=3 s[1]=S s[2]=Y s[3]=S				 */

/* returned by Info(), must be on a 4 byte boundary */
struct InfoData {
   LONG	  id_NumSoftErrors;	/* number of soft errors on disk */
   LONG	  id_UnitNumber;	/* Which unit disk is (was) mounted on */
   LONG	  id_DiskState;		/* See defines below */
   LONG	  id_NumBlocks;		/* Number of blocks on disk */
   LONG	  id_NumBlocksUsed;	/* Number of block in use */
   LONG	  id_BytesPerBlock;
   LONG	  id_DiskType;		/* Disk Type code */
   BPTR	  id_VolumeNode;	/* BCPL pointer to volume node (see DosList) */
   LONG	  id_InUse;		/* Flag, zero if not in use */
}; /* InfoData */

/* ID stands for InfoData */
    /* Disk states */
#define ID_WRITE_PROTECTED 80	 /* Disk is write protected */
#define ID_VALIDATING	   81	 /* Disk is currently being validated */
#define ID_VALIDATED	   82	 /* Disk is consistent and writeable */

    /* Disk types */
/* ID_INTER_* use international case comparison routines for hashing */
/* Any other new filesystems should also, if possible. */
#define ID_NO_DISK_PRESENT	(-1)
#define ID_UNREADABLE_DISK	(0x42414400L)	/* 'BAD\0' */
#define ID_DOS_DISK		(0x444F5300L)	/* 'DOS\0' */
#define ID_FFS_DISK		(0x444F5301L)	/* 'DOS\1' */
#define ID_INTER_DOS_DISK	(0x444F5302L)	/* 'DOS\2' */
#define ID_INTER_FFS_DISK	(0x444F5303L)	/* 'DOS\3' */
#define ID_FASTDIR_DOS_DISK	(0x444F5304L)	/* 'DOS\4' */
#define ID_FASTDIR_FFS_DISK	(0x444F5305L)	/* 'DOS\5' */
#define ID_NOT_REALLY_DOS	(0x4E444F53L)	/* 'NDOS'  */
#define ID_KICKSTART_DISK	(0x4B49434BL)	/* 'KICK'  */
#define ID_MSDOS_DISK		(0x4d534400L)	/* 'MSD\0' */

/* Errors from IoErr(), etc. */
#define ERROR_NO_FREE_STORE		  103
#define ERROR_TASK_TABLE_FULL		  105
#define ERROR_BAD_TEMPLATE		  114
#define ERROR_BAD_NUMBER		  115
#define ERROR_REQUIRED_ARG_MISSING	  116
#define ERROR_KEY_NEEDS_ARG		  117
#define ERROR_TOO_MANY_ARGS		  118
#define ERROR_UNMATCHED_QUOTES		  119
#define ERROR_LINE_TOO_LONG		  120
#define ERROR_FILE_NOT_OBJECT		  121
#define ERROR_INVALID_RESIDENT_LIBRARY	  122
#define ERROR_NO_DEFAULT_DIR		  201
#define ERROR_OBJECT_IN_USE		  202
#define ERROR_OBJECT_EXISTS		  203
#define ERROR_DIR_NOT_FOUND		  204
#define ERROR_OBJECT_NOT_FOUND		  205
#define ERROR_BAD_STREAM_NAME		  206
#define ERROR_OBJECT_TOO_LARGE		  207
#define ERROR_ACTION_NOT_KNOWN		  209
#define ERROR_INVALID_COMPONENT_NAME	  210
#define ERROR_INVALID_LOCK		  211
#define ERROR_OBJECT_WRONG_TYPE		  212
#define ERROR_DISK_NOT_VALIDATED	  213
#define ERROR_DISK_WRITE_PROTECTED	  214
#define ERROR_RENAME_ACROSS_DEVICES	  215
#define ERROR_DIRECTORY_NOT_EMPTY	  216
#define ERROR_TOO_MANY_LEVELS		  217
#define ERROR_DEVICE_NOT_MOUNTED	  218
#define ERROR_SEEK_ERROR		  219
#define ERROR_COMMENT_TOO_BIG		  220
#define ERROR_DISK_FULL			  221
#define ERROR_DELETE_PROTECTED		  222
#define ERROR_WRITE_PROTECTED		  223
#define ERROR_READ_PROTECTED		  224
#define ERROR_NOT_A_DOS_DISK		  225
#define ERROR_NO_DISK			  226
#define ERROR_NO_MORE_ENTRIES		  232
/* added for 1.4 */
#define ERROR_IS_SOFT_LINK		  233
#define ERROR_OBJECT_LINKED		  234
#define ERROR_BAD_HUNK			  235
#define ERROR_NOT_IMPLEMENTED		  236
#define ERROR_RECORD_NOT_LOCKED		  240
#define ERROR_LOCK_COLLISION		  241
#define ERROR_LOCK_TIMEOUT		  242
#define ERROR_UNLOCK_ERROR		  243

/* error codes 303-305 are defined in dosasl.h */

/* These are the return codes used by convention by AmigaDOS commands */
/* See FAILAT and IF for relvance to EXECUTE files		      */
#define RETURN_OK			    0  /* No problems, success */
#define RETURN_WARN			    5  /* A warning only */
#define RETURN_ERROR			   10  /* Something wrong */
#define RETURN_FAIL			   20  /* Complete or severe failure*/

/* Bit numbers that signal you that a user has issued a break */
#define SIGBREAKB_CTRL_C   12
#define SIGBREAKB_CTRL_D   13
#define SIGBREAKB_CTRL_E   14
#define SIGBREAKB_CTRL_F   15

/* Bit fields that signal you that a user has issued a break */
/* for example:	 if (SetSignal(0,0) & SIGBREAKF_CTRL_C) cleanup_and_exit(); */
#define SIGBREAKF_CTRL_C   (1<<SIGBREAKB_CTRL_C)
#define SIGBREAKF_CTRL_D   (1<<SIGBREAKB_CTRL_D)
#define SIGBREAKF_CTRL_E   (1<<SIGBREAKB_CTRL_E)
#define SIGBREAKF_CTRL_F   ((long)1<<SIGBREAKB_CTRL_F)

/* Values returned by SameLock() */
#define LOCK_DIFFERENT		-1
#define LOCK_SAME		0
#define LOCK_SAME_VOLUME	1	/* locks are on same volume */
#define LOCK_SAME_HANDLER	LOCK_SAME_VOLUME
/* LOCK_SAME_HANDLER was a misleading name, def kept for src compatibility */

/* types for ChangeMode() */
#define CHANGE_LOCK	0
#define CHANGE_FH	1

/* Values for MakeLink() */
#define LINK_HARD	0
#define LINK_SOFT	1	/* softlinks are not fully supported yet */

/* values returned by ReadItem */
#define	ITEM_EQUAL	-2		/* "=" Symbol */
#define ITEM_ERROR	-1		/* error */
#define ITEM_NOTHING	0		/* *N, ;, endstreamch */
#define ITEM_UNQUOTED	1		/* unquoted item */
#define ITEM_QUOTED	2		/* quoted item */

/* types for AllocDosObject/FreeDosObject */
#define DOS_FILEHANDLE		0	/* few people should use this */
#define DOS_EXALLCONTROL	1	/* Must be used to allocate this! */
#define	DOS_FIB			2	/* useful */
#define DOS_STDPKT		3	/* for doing packet-level I/O */
#define DOS_CLI			4	/* for shell-writers, etc */
#define DOS_RDARGS		5	/* for ReadArgs if you pass it in */

#endif	/* DOS_DOS_H */


include/dos/datetime.h

#ifndef DOS_DATETIME_H
#define DOS_DATETIME_H

/*
**	$VER: datetime.h 36.7 (12.7.1990)
**	Includes Release 44.1
**
**	Date and time C header for AmigaDOS
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**
*/

#ifndef DOS_DOS_H
#include <dos/dos.h>
#endif

/*
 *	Data structures and equates used by the V1.4 DOS functions
 * StrtoDate() and DatetoStr()
 */

/*--------- String/Date structures etc */
struct DateTime {
    struct DateStamp dat_Stamp;	/* DOS DateStamp */
    UBYTE	dat_Format;		/* controls appearance of dat_StrDate */
    UBYTE	dat_Flags;		/* see BITDEF's below */
    UBYTE	*dat_StrDay;		/* day of the week string */
    UBYTE	*dat_StrDate;		/* date string */
    UBYTE	*dat_StrTime;		/* time string */
};

/* You need this much room for each of the DateTime strings: */
#define	LEN_DATSTRING	16

/*	flags for dat_Flags */

#define DTB_SUBST	0		/* substitute Today, Tomorrow, etc. */
#define DTF_SUBST	1
#define DTB_FUTURE	1		/* day of the week is in future */
#define DTF_FUTURE	2

/*
 *	date format values
 */

#define FORMAT_DOS	0		/* dd-mmm-yy */
#define FORMAT_INT	1		/* yy-mm-dd  */
#define FORMAT_USA	2		/* mm-dd-yy  */
#define FORMAT_CDN	3		/* dd-mm-yy  */
#define FORMAT_MAX	FORMAT_CDN

#endif /* DOS_DATETIME_H */


include/libraries/hdwrench.h

#ifndef LIBRARIES_HDWRENCH_H
#define LIBRARIES_HDWRENCH_H

/*
**	$VER: hdwrench.h 44.3 (29.7.1999)
**	Includes Release 44.1
**
**	Disk Prep Support Library API includes
**
**	(C) Copyright 1999 Joanne B. Dow, Wizardess Designs,
**	    for license to Amiga, Inc.
**
**	    All Rights Reserved
*/

/*****************************************************************************/

#ifndef EXEC_LIBRARIES_H
#include <exec/libraries.h>
#endif

#ifndef DEVICES_HARDBLOCKS_H
#include <devices/hardblocks.h>
#endif

/*****************************************************************************/

struct HDWLibrary
{
        struct Library       ml_Lib;
        ULONG                ml_SegList;
        ULONG                ml_Flags;
        APTR                 ml_ExecBase; /* pointer to exec base  */
        long                *ml_relocs;   /* pointer to relocs.    */
        struct HDWLibrary   *ml_origbase; /* pointer to original library base  */
        long                 ml_numjmps;
};

#define  HDWBaseName    "hdwrench.library"

/* === General Constant Defines === */

/* Artificial unassigned value for the RDB structures. */
#define UNASSIGNED  (ULONG) -131L

/* End block number link within RDB structures */
#define RDBEND      (ULONG) -1L

#define DEFAULT_RDBBLOCKSHI 63

/* === Structure & Typedefs === */

typedef struct
{
    USHORT  ready [ 16 ];   /* Tests ready and first block read */
    USHORT  there [ 16 ];   /* Tests as "there" but fails other tests */
} ValidIDstruct;

/* Actual disk read write return structure: */
struct rw_return                /* Should fit within a ULONG */
{
    USHORT  success;            /* Error code */
    USHORT  failed_word;        /* 0 on reads. */
    USHORT  block_written;      /* 0 on reads. */
};

enum rw_success_val             /* Return values for rw_return.success field. */
{
    success = 0,                /* 0 */
    success_on_retry_write,     /* 1 */
    success_on_retry_read,      /* 2 */
    failed_on_write,            /* 3 */
    failed_on_reread,           /* 4 */
    illegal_command,            /* 5 */
    io_command_failure,         /* 6 */
    scsi_command_failure,       /* 7 */
    out_of_memory,              /* 8 */
    no_more_disk_blocks,        /* 9 */
    rdsk_not_located,           /* 10 */
    io_device_not_open,         /* 11 */
    invalid_blocksize_found,    /* 12 */
    no_callback_hook,           /* 13 */
    user_aborted,               /* 14 */
    operation_not_permitted     /* 15 */
};

/* Internal bootblock structure. Create dummy structures to pass to read
 * and write functions as necessary. Be sure that bb_BlockNum is filled in
 * and that the actual size of the data area pointed to by the union is
 * sufficiently large to contain one disk block.
 */
typedef struct bootblock
{
    struct MinNode   bb_Node;
    LONG             allocsize;
    LONG             bb_BlockNum;
    WORD             bb_Changed;
    LONG             unit;              /* Unit number for THIS set of RDBs. */
    char             DeviceName [32];   /* Device name */
    struct rw_return bb_RWErrors;
    BOOL             wflag;             /* Written out flag. */
    BYTE             spares[4-sizeof(BOOL)];/* Fill out short word */

    union
    {
        struct       RigidDiskBlock bd_RDB;
        struct       PartitionBlock bd_PB;
        struct       FileSysHeaderBlock bd_FHB;
        struct       LoadSegBlock bd_LSB;
        struct       BadBlockBlock bd_BB;
        UBYTE        bd_Bytes[512];     /* NB: This is the MINIMUM size we */
        UWORD        bd_Words[256];     /* can have here. It MAY be extended */
        ULONG        bd_Longs[128];     /* if actual block size is larger. */
    } bb_Data;
} BootBlock;

/*  ==== Error report values for other functions ==== */
#define E_NOERROR           0

#define E_ILLEGAL_SLASH     200
#define E_EOF_IN_COMMENT    201
#define E_ILLEGAL_STAR      202
#define E_TOKEN_TO_LONG     203
#define E_MEMORY_PANIC      204
#define E_PREMATURE_EOF     205
#define E_MISSING_EQUALS    206
#define E_ILLEGAL_T_F       207
#define E_ILLEGAL_TOKEN     208
#define E_DUPLICATE_DISK    209
#define E_NOT_LEGAL_NAME    210
#define E_EXCEEDED_SIZE_LIM 211
#define E_FILE_WRITE_ERROR  212
#define E_TOOMANY_FS        213
#define E_FSAVE_CONFUSION   214
#define E_FS_CANNOT_OPEN    215
#define E_LOST_IN_RDB_SPACE 216
#define E_FS_WRITE_ERROR    217
#define E_MULTIPLE_RDSKS    218
#define E_RDSK_NOT_1ST      219
#define E_NO_RDBS_LOADED    220
#define E_RDBS_ALREADY_IN   221     /* RDBs already loaded. */
#define E_FAILED_FILEOPEN   222
#define E_FILE_READ_FAILED  223
#define E_FILE_NOT_RDBS     224
#define E_NO_BLOCKSIZE_SPEC 225
#define E_FILE_WRITE_FAILED 226
#define E_MEMORYP_NULL      227     /* prospective "memp" is null */
#define E_ILLEGAL_BLOCKSIZE 228
#define E_INSUFFICIENT_MEM  229
#define E_RENUMBER_FAILED   230
#define E_BLOCKS_EXCEEDED   231     /* Too many RDB blocks */
#define E_INCOMPLETE_FSDESC 232
#define E_FS_NOT_FOUND      233
#define E_LIST_SCREWEDUP    234
#define E_NO_SUCH_DIR       235
#define E_EXALL_ERROR       236
#define E_UNIT_DIFFERS      237

#define T_RENUMBER_LEFT     300

#define W_DUPLICATE_FS      100
#define W_FS_NO_WRITE       101

/* Definitions for type field in FileSave */
#define DRIVEINIT   0
#define FILESYSTEM  1

struct DefaultsArray
{
    ULONG   TotalBlocks;
    UWORD   BytesPerBlock;
    UWORD   BlocksPerSurface;
    UWORD   Surfaces;
    UWORD   Cylinders;          /* note: MaxCyl = Cylinders - 1; */
    UWORD   UnusedBlocks;
};

/* Defaults Array filling error bit array */
#define DA_NOERRORS             0
#define DA_NO_CAPACITY_REPORT   1
#define DA_NO_OPTIMIZE          2
#define DA_BAD_MODESENSE_4      4
#define DA_BAD_MODESENSE_3      8
#define DA_FAILED               256
#define DA_NO_DRIVE_OPEN        DA_FAILED
#define DA_RIDICULOUS_VALUES    ( DA_FAILED << 1 )

/* Defaults Array filling "Optimize" Flags */
#define DA_OPTIMIZE             1   /* Optimize storage if possible */
#define DA_HUGE                 2   /* Allow partitioning huge disks */
#define DA_HF_WAY               4   /* Use the old HardFrame algorithm */
/* Note: DA_HF_WAY is forces DA_OPTIMIZE and DA_HUGE off. */
/*       DA_BAD_MODESENSE_3 and DA_BAD_MODESENSE_4 only happen with DA_HF_WAY */
/*       Errors below DA_FAILED are informational. */

/*  ==== Mountfile Recognized Strings ==== */
#ifdef DONT_EVER_COMPILE_ME /* This stuff is for reference only, thank you. */

#ifdef FORREAL
#define EXTERN
#else
#define EXTERN  extern
#endif

EXTERN const char   *_Tokens[]
#ifdef FORREAL
= {
    "/",                    /*0 */
    "#",
    "=",
    "device",
    "surfaces",
    "blockspertrack",
    "reserved",
    "prealloc",
    "interleave",
    "lowcyl",
    "highcyl",              /* 10 */
    "buffers",
    "bufmemtype",
    "maxtransfer",
    "mask",
    "bootpri",
    "dostype",
    "unit",
    "flags",
    "stacksize",
    "priority",             /* 20 */
    "globvec",
    "filesystem",
    "mount",
    "heads",
    "bytesperblock",
    "disk",
    "rdblow",
    "rdbhi",
    "reselect",
    "hilun",                /* 30 */
    "hiid",
    "hidrive",
    "cylinders",
    "cylinderblocks",
    "mincyl",
    "maxcyl",
    "hicard",
    "blocksize",
    "bootable",
    "readonly",             /* 40 */
    "driveinit",
    "baud",
    "control",
    "bootblocks",
    "synch",
    "sectorsperblock",
    "\xff"
}
#endif
;

#define TSLASH          0
#define THACK           1
#define TEQUALS         2
#define TDEVICE         3
#define TSURFACES       4
#define TBLOCKSPERTRACK 5
#define TRESERVED       6
#define TPREALLOC       7
#define TINTERLEAVE     8
#define TLOWCYL         9
#define THICYL          10
#define TBUFFERS        11
#define TBUFMEMTYPE     12
#define TMAXTRANSFER    13
#define TMASK           14
#define TBOOTPRI        15
#define TDOSTYPE        16
#define TUNIT           17
#define TFLAGS          18
#define TSTACKSIZE      19
#define TPRIORITY       20
#define TGLOBVEC        21
#define TFILESYSTEM     22
#define TMOUNT          23
#define THEADS          24
#define TBYTESPERBLOCK  25
#define TDISK           26
#define TRDBLOW         27
#define TRDBHI          28
#define TRESELECT       29
#define THILUN          30
#define THIID           31
#define TLASTDRIVE      32
#define TCYLINDERS      33
#define TCYLINDERBLOCKS 34
#define TMINCYL         35
#define TMAXCYL         36
#define THICARD         37
#define TBLOCKSIZE      38
#define TBOOTABLE       39
#define TREADONLY       40
#define TDRIVEINIT      41
#define TBAUD           42
#define TCONTROL        43
#define TBOOTBLOCKS     44
#define TSYNCH          45
#define TSECSPERBLOCK   46

#define TokenCount      46
#define TNOMATCH        TokenCount + 1

#endif /* COMPILEME */

typedef struct
{
    STRPTR  devicename;
    LONG    board;
    LONG    address;
    LONG    lun;
    STRPTR  messagestring;
    LONG    extra;
    LONG    param1;
    LONG    param2;
    LONG    param3;
} HDWCallbackMsg;

#define EXTRA_BEFORE_TEST       0
#define EXTRA_AFTER_TEST        1
#define EXTRA_BEFORE_FORMAT     2       /* with no way to stop once you start.*/
#define EXTRA_BEFORE_VERIFY     3       /* Setup the verify requester and
                                           return "go ahead" */
#define EXTRA_UPDATE_VERIFY     4       /* New string for requester - return
                                           any Abort received */
#define EXTRA_VERIFY_REASSIGN   5       /* New string - return "Yes" or "No" */
#define EXTRA_VERIFY_FINISHED   6       /* Notify user, accept OK, close */

#define INQBUFSIZE  36  /* Standard size of Inquiry buffer */

/****************************************************************************/

/*
 *	Callback messages for the hdwrench.library tester program.
 *	These strings are "suggested" English strings for use with
 *	the hdwrench.library callback hook.
 */

#ifdef USE_SUGGESTED_MESSAGES
    /* MESSAGE */                                   /* .extra usages */
char *callback_messages[] =
{
    /* A) FINDVALID_SCANNING_STRING */              /* 0 and 1 */
    "Scanning: %s: %d%d%d",         /* from message: devicename, board, lun, addr */

    /* B) LONGTIME_NOABORT_WARNING */               /* 2 */
    "You are about to format LUN %d on\n"
    "drive %d attached to board %d\n\n"
    "***WARNING WARNING WARNING***\n"
    "It can take up to several hours\n"
    "to format a hard disk. And there\n"
    "is no safe way to abort.\n\n"
    "Are you VERY sure you want to do this?\n",
    /* C) LONGTIME_VERIFY_WARNING */                /* 3 */
    "LUN %d on drive %d on board %d\n"
    "            Note\n"
    "It can take up to several hours\n"
    "to verify a hard disk. However,\n"
    "you can abort during verify.\n\n"
    "No data will be changed on the\n"
    "drive.\n\n"
    "Do you wish to continue?\n",

    /* D) FORMAT_USER_ABORTED_STRING */             /* 6 */
    "User Aborted. Your drive is safe!\n",

    /* E) FORMAT_MOUNTED_DRIVE */                   /* 4 */
    "%s\nShould we format a mounted drive?\n",

    /* F) FORMAT_NOT_PERMITTED */                   /* 6 */
    "%s\nFormatting the system disk\nis not permitted. Aborting...\n",

    /* G) FORMAT_UNRECOGNIZED_STATUS */             /* 6 */
    "Unrecognized SCSI status byte 0x%2.2x returned.\n",

    /* H) FORMAT_RESERVATION_CONFLICT */            /* 6 */
    "Device is reserved by another initiator.\n",

    /* I) FORMAT_DRIVE_BUSY */                      /* 6 */
    "Drive is busy.\n",

    /* J) FORMAT_COMMAND_PROBLEM */                 /* 6 */
    "Unknown problem issuing SCSI Direct command!\n",

    /* K) FORMAT_SUCCESS_STRING */                  /* 6 */
    "Format completed with no errors.",

    /* L) FORMAT_FAILED_STRING */                   /* 6 maybe */
    "Format failed! Your drive may be dead.\n",

    /* M) VERIFY_USER_ABORTED_STRING */             /* 6 */
    "User Aborted.\n",

    /* N) VERIFY_READCAPACITY_FAILED */             /* 6 */
    "ReadCapacity failed! Verify impossible.\n",

    /* O) VERIFY_PROGRESS */                        /* 4 */
    "Verifying blocks %d to %d of %d.\r",

    /* P) VERIFY_REASSIGN_Q */                      /* 5 */
    "Block %d is bad.\n"
    "Reassign this bad block?",

    /* Q) VERIFY_COMPLETED_STRING */                /* 6 */
    "Verify completed:\n"
    "    %d errors,\n"
    "    %d successful reassignments,\n"
    "and %d failed reassignments\n",

    /* R) VERIFY_ERROR_UNKNOWN_LOC */               /* 4 */
    "Medium error at unknown location!\n"
    "You should back up the drive and low-level format\n",

    /* S) VERIFY_HARDWARE_ERROR */                  /* 4 */
    "Hardware error %ld!\n",

    /* T) VERIFY_RECOVERED_ERROR */                 /* 4 */
    "Recovered read error at block %ld\n",

    /* U) VERIFY_RECOVERED_UNKNOWN_LOC */           /* 4 */
    "Recovered error at unknown location!\n"
    "You should consider backing up the\n"
    "drive and reformatting\n",

    /* V) VERIFY_ILLEGAL_REQUEST */                 /* 4 */
    "Drive returned an Illegal Request Error (%ld)\n",

    /* W) VERIFY_UNKNOWN_ERROR */
    "Unknown error: sense key %ld (more)\n"
    "Device returned sense code %ld (more)\n"
    "Consult drive documentation\n",

    /* X) VERIFY_CONTINUE */                        /* 4 */
    "Continuing verify at block %d...\n",

    /* Y) VERIFY_SEEK_ERROR */                      /* 4 */
    "seek eror!\n",

    /* Z) VERIFY_MEDIUM_ERROR */                    /* 4 */
    "Medium error at unknown location!\n"
    "You should back up the drive and low-level format\n",

    /* [) VERIFY_ILLEGAL_COMMAND */                 /* 4 */
    "Illegal command!\n",

    /* \) VERIFY_ILLEGAL_ADDRESS */                 /* 4 */
    "Illegal address %ld!",

    /* ]) VERIFY_BAD_ARGUEMENT */                   /* 4 */
    "Bad command arguement!\n",

    /* ^) VERIFY_CARTRIDGE_CHANGED */               /* 4 */
    "Cartridge changed",

    /* _) VERIFY_ILLEGAL_LUN */                     /* 4 */
    "Invalid LUN addressed!",

    /* `) VERIFY_UNFORMATTED_DRIVE */               /* 4 */
    "Unformatted drive!",

    /* a) VERIFY_NONEXTENDED_SENSE */               /* 4 */
    "Non-extended sense error is 0x%x",

    /* b) VERIFY_NO_SCSI_ERROR_RETURNED */          /* 4 */
    "Device didn't return good sense data!",

    /* other */
    "Illegal callback message %x"                   /* any */
};

#define MIN_MESSAGE 'A'
#define MAX_MESSAGE 'b'

#endif /* USE_SUGGESTED_MESSAGES */

#endif	/* LIBRARIES_HDWRENCH_H */


include/exec/devices.h

#ifndef	EXEC_DEVICES_H
#define	EXEC_DEVICES_H
/*
**	$VER: devices.h 39.0 (15.10.1991)
**	Includes Release 44.1
**
**	Include file for use by Exec device drivers
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_LIBRARIES_H
#include <exec/libraries.h>
#endif /* EXEC_LIBRARIES_H */

#ifndef EXEC_PORTS_H
#include <exec/ports.h>
#endif /* EXEC_PORTS_H */

/****** Device ******************************************************/

struct Device {
    struct  Library dd_Library;
};

/****** Unit ********************************************************/

struct Unit {
    struct  MsgPort unit_MsgPort;	/* queue for unprocessed messages */
                    /* instance of msgport is recommended */
    UBYTE   unit_flags;
    UBYTE   unit_pad;
    UWORD   unit_OpenCnt;		/* number of active opens */
};

#define UNITF_ACTIVE	(1<<0)
#define UNITF_INTASK	(1<<1)

#endif	/* EXEC_DEVICES_H */


include/devices/prtbase.h

#ifndef DEVICES_PRTBASE_H
#define DEVICES_PRTBASE_H
/*
**	$VER: prtbase.h 44.1 (19.10.1999)
**	Includes Release 44.1
**
**	printer driver structure definitions
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

#ifndef  EXEC_DEVICES_H
#include <exec/devices.h>
#endif

#ifndef  DEVICES_PARALLEL_H
#include <devices/parallel.h>
#endif

#ifndef  DEVICES_SERIAL_H
#include <devices/serial.h>
#endif

#ifndef  DEVICES_TIMER_H
#include <devices/timer.h>
#endif

#ifndef  DOS_DOSEXTENS_H
#include <dos/dosextens.h>
#endif

#ifndef  INTUITION_INTUITION_H
#include <intuition/intuition.h>
#endif

/****************************************************************************/

struct DeviceData
{
    struct Library	dd_Device;	/* standard library node */
    APTR		dd_Segment;	/* A0 when initialized */
    APTR		dd_ExecBase;	/* A6 for exec */
    APTR		dd_CmdVectors;	/* command table for device commands */
    APTR		dd_CmdBytes;	/* bytes describing which command queue */
    UWORD		dd_NumCommands;	/* the number of commands supported */
};

/****************************************************************************/

/* IO Flags */
#define IOB_QUEUED	4
#define IOB_CURRENT	5
#define IOB_SERVICING	6
#define IOB_DONE	7

#define IOF_QUEUED	(1L<<IOB_QUEUED)
#define IOF_CURRENT	(1L<<IOB_CURRENT)
#define IOF_SERVICING	(1L<<IOB_SERVICING)
#define IOF_DONE	(1L<<IOB_DONE)

/* pd_Flags */
#define PB_IOR0		0
#define PB_IOR1		1
#define PB_IOOPENED	2
#define PB_EXPUNGED	7

#define PBF_IOR0	(1L<<PB_IOR0)
#define PBF_IOR1	(1L<<PB_IOR1)
#define PBF_IOOPENDED	(1L<<PB_IOOPENED)
#define PBF_EXPUNGED	(1L<<PB_EXPUNGED)

/* du_Flags (actually placed in pd_Unit.mp_Node.ln_Pri) */
#define DUB_STOPPED	0

#define DUF_STOPPED	(1L<<DUB_STOPPED)

#define P_OLDSTKSIZE	0x0800	/* stack size for child task (OBSOLETE) */
#define P_STKSIZE	0x1000	/* stack size for child task */
#define P_BUFSIZE	256	/* size of internal buffers for text i/o */
#define P_SAFESIZE	128	/* safety margin for text output buffer */

/****************************************************************************/

/*
    "struct PrinterData" was a very bad concept in the old V1.0 days
    because it is both: the device and the unit.

    Starting with V44 PrinterData may be duplicated for many Units. But all
    new fields that are specific to the Unit  are now part of the new
    "struct PrinterUnit". Don't touch the private fields!

    A note on the function pointers in these data structure definitions:
    unless otherwise specified, all functions expect that their parameters
    are passed on the *stack* rather than in CPU registers. Every parameter
    must be passed a 32 bit long word, i.e. an "UWORD" will use the same
    stack space as an "ULONG".
*/

struct PrinterData
{
    struct DeviceData pd_Device;

    /* PRIVATE & OBSOLETE: the one and only unit */
    struct MsgPort pd_Unit;

    /* the printer specific segment */
    BPTR pd_PrinterSegment;

    /* the segment printer type */
    UWORD pd_PrinterType;

    /* the segment data structure */
    struct PrinterSegment * pd_SegmentData;

    /* the raster print buffer */
    UBYTE * pd_PrintBuf;

    /* the write function:
     *
     *	LONG PWrite(APTR data,
     *	            LONG len);
     */
    LONG (*pd_PWrite)();

    /* write function's done:
     *
     *	LONG PBothReady(VOID);
     */
    LONG (*pd_PBothReady)();

    /* PRIVATE: port I/O request 0 */
    union {
        struct IOExtPar pd_p0;
        struct IOExtSer pd_s0;
    } pd_ior0;

    #define pd_PIOR0 pd_ior0.pd_p0
    #define pd_SIOR0 pd_ior0.pd_s0

    /* PRIVATE:  and 1 for double buffering */
    union {
        struct IOExtPar pd_p1;
        struct IOExtSer pd_s1;
    } pd_ior1;

    #define pd_PIOR1 pd_ior1.pd_p1
    #define pd_SIOR1 pd_ior1.pd_s1

    /* PRIVATE: timer I/O request */
    struct timerequest pd_TIOR;

    /* PRIVATE: and message reply port */
    struct MsgPort pd_IORPort;

    /* PRIVATE: write task */
    struct Task pd_TC;

    /* PRIVATE: and stack space (OBSOLETE) */
    UBYTE pd_OldStk[P_OLDSTKSIZE];

    /* PRIVATE: device flags */
    UBYTE pd_Flags;

    /* PRIVATE: padding */
    UBYTE pd_pad;

    /* the latest preferences */
    struct Preferences pd_Preferences;

    /* PRIVATE: wait function switch */
    UBYTE pd_PWaitEnabled;

    /**************************************************************
     *
     * New fields for V2.0:
     *
     *************************************************************/

    /* PRIVATE: padding */
    UBYTE pd_Flags1;

    /* PRIVATE: stack space (OBSOLETE) */
    UBYTE pd_Stk[P_STKSIZE];

    /**************************************************************
     *
     *  New fields for V3.5 (V44):
     *
     *************************************************************/

    /* PRIVATE: the Unit. pd_Unit is obsolete */
    struct PrinterUnit * pd_PUnit;

    /* the read function:
     *
     *	LONG pd_PRead(char * buffer,
     *	              LONG * length,
     *	              struct timeval * tv);
     */
    LONG (*pd_PRead)();

    /* call application's error hook:
     *
     *	LONG pd_CallErrorHook(struct Hook * hook,
     *	                      struct printerIO * ior,
     *	                      struct PrtErrMsg * pem);
     */
    LONG (*pd_CallErrHook)();

    /* unit number */
    ULONG pd_UnitNumber;

    /* name of loaded driver */
    STRPTR pd_DriverName;

    /* the query function:
     *
     *	LONG pd_PQuery(LONG * numofchars);
     */
    LONG (*pd_PQuery)();
};

/****************************************************************************/

/* Printer Class */
#define PPCB_GFX	0	/* graphics (bit position) */
#define PPCF_GFX	0x1	/* graphics (and/or flag) */
#define PPCB_COLOR	1	/* color (bit position) */
#define PPCF_COLOR	0x2	/* color (and/or flag) */

#define PPC_BWALPHA	0x00	/* black&white alphanumerics */
#define PPC_BWGFX	0x01	/* black&white graphics */
#define PPC_COLORALPHA	0x02	/* color alphanumerics */
#define PPC_COLORGFX	0x03	/* color graphics */

#define PPCB_EXTENDED	2	/* extended PED structure (V44) */
#define PPCF_EXTENDED	0x4

/*
    Some printer drivers (PrinterPS) do not support
    strip printing. An application has to print a page
    using a single print request or through clever use
    of the PRD_DUMPRPORTTAGS printing callback hook.
*/
#define PPCB_NOSTRIP	3	/* no strip printing, please */
#define PPCF_NOSTRIP	0x8

/* Color Class */
#define	PCC_BW		0x01	/* black&white only */
#define	PCC_YMC		0x02	/* yellow/magenta/cyan only */
#define	PCC_YMC_BW	0x03	/* yellow/magenta/cyan or black&white */
#define	PCC_YMCB	0x04	/* yellow/magenta/cyan/black */
#define	PCC_4COLOR	0x04	/* a flag for YMCB and BGRW */
#define	PCC_ADDITIVE	0x08	/* not ymcb but blue/green/red/white */
#define	PCC_WB		0x09	/* black&white only, 0 == BLACK */
#define	PCC_BGR		0x0A	/* blue/green/red */
#define	PCC_BGR_WB	0x0B	/* blue/green/red or black&white */
#define	PCC_BGRW	0x0C	/* blue/green/red/white */

/*
    The picture must be scanned once for each color component, as the
    printer can only define one color at a time.  ie. If 'PCC_YMC' then
    first pass sends all 'Y' info to printer, second pass sends all 'M'
    info, and third pass sends all C info to printer.  The CalComp
    PlotMaster is an example of this type of printer.
*/
#define PCC_MULTI_PASS	0x10	/* see explanation above */

/****************************************************************************/

struct PrinterExtendedData
{
    /* printer name, null terminated */
    char * ped_PrinterName;

    /* called after LoadSeg:
     *
     *	LONG ped_Init(struct PrinterData * pd);
     */
    VOID (*ped_Init)();

    /* called before UnLoadSeg:
     *
     *	VOID ped_Expunge(VOID);
     */
    VOID (*ped_Expunge)();

    /* called at OpenDevice:
     *
     *	LONG ped_Open(struct printerIO * ior);
     */
    LONG (*ped_Open)();

    /* called at CloseDevice:
     *
     *	VOID ped_Close(struct printerIO * ior);
     */
    VOID (*ped_Close)();

    /* printer class */
    UBYTE ped_PrinterClass;

    /* color class */
    UBYTE ped_ColorClass;

    /* number of print columns available */
    UBYTE ped_MaxColumns;

    /* number of character sets */
    UBYTE ped_NumCharSets;

    /* number of 'pins' in print head */
    UWORD ped_NumRows;

    /* number of dots max in a raster dump */
    ULONG ped_MaxXDots;

    /* number of dots max in a raster dump */
    ULONG ped_MaxYDots;

    /* horizontal dot density */
    UWORD ped_XDotsInch;

    /* vertical dot density */
    UWORD ped_YDotsInch;

    /* printer text command table */
    STRPTR ** ped_Commands;

    /* special command handler:
     *
     *	LONG ped_DoSpecial(UWORD * command,
     *	                   UBYTE output_buffer[],
     *	                   BYTE * current_line_position,
     *	                   BYTE * current_line_spacing,
     *	                   BYTE * crlf_flag,
     *	                   UBYTE params[]);
     */
    LONG (*ped_DoSpecial)();

    /* raster render function:
     *
     *	LONG ped_Render(LONG ct,LONG x,LONG y,LONG status);
     */
    LONG (*ped_Render)();

    /* good write timeout */
    LONG ped_TimeoutSecs;

    /**************************************************************
     *
     * The following only exists if the segment version is >= 33:
     *
     *************************************************************/

    /* Conversion strings for the extended font */
    STRPTR * ped_8BitChars;

    /* Set if text printed, otherwise 0 */
    LONG ped_PrintMode;

    /**************************************************************
     *
     * The following only exists if the segment version is >= 34:
     *
     *************************************************************/

    /* ptr to conversion function for all chars:
     *
     *	LONG ped_ConvFunc(UBYTE * buf,
     *	                  UBYTE c,
     *	                  LONG crlf_flag);
     */
    LONG (*ped_ConvFunc)();

    /**************************************************************
     *
     * The following only exists if the segment version is >= 44
     * AND PPCB_EXTENDED is set in ped_PrinterClass:
     *
     *************************************************************/

    /* Attributes and features */
    struct TagItem * ped_TagList;

    /* driver specific preferences:
     *
     *	LONG ped_DoPreferences(struct printerIO * ior,
     *	                       LONG command);
     */
    LONG (*ped_DoPreferences)();

    /* custom error handling:
     *
     *	VOID ped_CallErrHook(struct printerIO * ior,
     *	                     struct Hook * hook);
     */
    VOID (*ped_CallErrHook)();
};

/****************************************************************************/

/* The following tags are used to define more printer driver features */

#define PRTA_Dummy (TAG_USER + 0x50000)

/****************************************************************************/

/* V44 features */
#define PRTA_8BitGuns		(PRTA_Dummy + 1) /* LBOOL */
#define PRTA_ConvertSource	(PRTA_Dummy + 2) /* LBOOL */
#define PRTA_FloydDithering	(PRTA_Dummy + 3) /* LBOOL */
#define PRTA_AntiAlias		(PRTA_Dummy + 4) /* LBOOL */
#define PRTA_ColorCorrection	(PRTA_Dummy + 5) /* LBOOL */
#define PRTA_NoIO		(PRTA_Dummy + 6) /* LBOOL */
#define PRTA_NewColor		(PRTA_Dummy + 7) /* LBOOL */
#define PRTA_ColorSize		(PRTA_Dummy + 8) /* LONG */
#define PRTA_NoScaling		(PRTA_Dummy + 9) /* LBOOL */

/* User interface */
#define PRTA_DitherNames	(PRTA_Dummy + 20) /* STRPTR * */
#define PRTA_ShadingNames	(PRTA_Dummy + 21) /* STRPTR * */
#define PRTA_ColorCorrect	(PRTA_Dummy + 22) /* LBOOL */
#define PRTA_DensityInfo	(PRTA_Dummy + 23) /* STRPTR * */

/* Hardware page borders */
#define PRTA_LeftBorder		(PRTA_Dummy + 30) /* LONG, inches/1000 */
#define PRTA_TopBorder		(PRTA_Dummy + 31) /* LONG, inches/1000 */

#define PRTA_MixBWColor		(PRTA_Dummy + 32) /* LBOOL */

/* Driver Preferences */
#define PRTA_Preferences	(PRTA_Dummy + 40) /* LBOOL */

/****************************************************************************/

struct PrinterSegment
{
    BPTR				ps_NextSegment;
    ULONG				ps_runAlert;	/* MOVEQ #0,D0 : RTS */
    UWORD				ps_Version;	/* segment version */
    UWORD				ps_Revision;	/* segment revision */
    struct PrinterExtendedData	ps_PED;		/* printer extended data */
};

/****************************************************************************/

/*
    Driver specific preferences. This structure is device specific: every
    driver must base its preferences structure on this to allow version
    checking etc.

    The application will read/write this structure as an I/O buffer.
*/
struct PrtDriverPreferences
{
    UWORD    pdp_Version;				/* PRIVATE! driver specific version */
    UBYTE    pdp_PrinterID[32];			/* PRIVATE! driver specific id */
    char     pdp_PrefName[FILENAME_SIZE-16];
    ULONG    pdp_Length;				/* size of this structure */

    /* .. more driver private fields follow .. */
};

#endif /* DEVICES_PRTBASE_H */


include/dos/filehandler.h

#ifndef DOS_FILEHANDLER_H
#define DOS_FILEHANDLER_H
/*
**	$VER: filehandler.h 44.1 (24.8.1999)
**	Includes Release 44.1
**
**	device and file handler specific code for AmigaDOS
**
**	(C) Copyright 1986-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef	DOS_DOS_H
#include <dos/dos.h>
#endif

/* The disk "environment" is a longword array that describes the
 * disk geometry.  It is variable sized, with the length at the beginning.
 * Here are the constants for a standard geometry.
 */

struct DosEnvec {
    ULONG de_TableSize;	     /* Size of Environment vector */
    ULONG de_SizeBlock;	     /* in longwords: Physical disk block size */
    ULONG de_SecOrg;	     /* not used; must be 0 */
    ULONG de_Surfaces;	     /* # of heads (surfaces). drive specific */
    ULONG de_SectorPerBlock; /* N de_SizeBlock sectors per logical block */
    ULONG de_BlocksPerTrack; /* blocks per track. drive specific */
    ULONG de_Reserved;	     /* DOS reserved blocks at start of partition. */
    ULONG de_PreAlloc;	     /* DOS reserved blocks at end of partition */
    ULONG de_Interleave;     /* usually 0 */
    ULONG de_LowCyl;	     /* starting cylinder. typically 0 */
    ULONG de_HighCyl;	     /* max cylinder. drive specific */
    ULONG de_NumBuffers;     /* Initial # DOS of buffers.  */
    ULONG de_BufMemType;     /* type of mem to allocate for buffers */
    ULONG de_MaxTransfer;    /* Max number of bytes to transfer at a time */
    ULONG de_Mask;	     /* Address Mask to block out certain memory */
    LONG  de_BootPri;	     /* Boot priority for autoboot */
    ULONG de_DosType;	     /* ASCII (HEX) string showing filesystem type;
                  * 0X444F5300 is old filesystem,
                  * 0X444F5301 is fast file system */
    ULONG de_Baud;	     /* Baud rate for serial handler */
    ULONG de_Control;	     /* Control word for handler/filesystem */
    ULONG de_BootBlocks;     /* Number of blocks containing boot code */

};

/* these are the offsets into the array */
/* DE_TABLESIZE is set to the number of longwords in the table minus 1 */

#define DE_TABLESIZE	0	/* minimum value is 11 (includes NumBuffers) */
#define DE_SIZEBLOCK	1	/* in longwords: standard value is 128 */
#define DE_SECORG	2	/* not used; must be 0 */
#define DE_NUMHEADS	3	/* # of heads (surfaces). drive specific */
#define DE_SECSPERBLK	4	/* not used; must be 1 */
#define DE_BLKSPERTRACK 5	/* blocks per track. drive specific */
#define DE_RESERVEDBLKS 6	/* unavailable blocks at start.	 usually 2 */
#define DE_PREFAC	7	/* not used; must be 0 */
#define DE_INTERLEAVE	8	/* usually 0 */
#define DE_LOWCYL	9	/* starting cylinder. typically 0 */
#define DE_UPPERCYL	10	/* max cylinder.  drive specific */
#define DE_NUMBUFFERS	11	/* starting # of buffers.  typically 5 */
#define DE_MEMBUFTYPE	12	/* type of mem to allocate for buffers. */
#define DE_BUFMEMTYPE	12	/* same as above, better name
                 * 1 is public, 3 is chip, 5 is fast */
#define DE_MAXTRANSFER	13	/* Max number bytes to transfer at a time */
#define DE_MASK		14	/* Address Mask to block out certain memory */
#define DE_BOOTPRI	15	/* Boot priority for autoboot */
#define DE_DOSTYPE	16	/* ASCII (HEX) string showing filesystem type;
                 * 0X444F5300 is old filesystem,
                 * 0X444F5301 is fast file system */
#define DE_BAUD		17	/* Baud rate for serial handler */
#define DE_CONTROL	18	/* Control word for handler/filesystem */
#define DE_BOOTBLOCKS	19	/* Number of blocks containing boot code */

/* The file system startup message is linked into a device node's startup
** field.  It contains a pointer to the above environment, plus the
** information needed to do an exec OpenDevice().
*/
struct FileSysStartupMsg {
    ULONG	fssm_Unit;	/* exec unit number for this device */
    BSTR	fssm_Device;	/* null terminated bstring to the device name */
    BPTR	fssm_Environ;	/* ptr to environment table (see above) */
    ULONG	fssm_Flags;	/* flags for OpenDevice() */
};

/* The include file "libraries/dosextens.h" has a DeviceList structure.
 * The "device list" can have one of three different things linked onto
 * it.	Dosextens defines the structure for a volume.  DLT_DIRECTORY
 * is for an assigned directory.  The following structure is for
 * a dos "device" (DLT_DEVICE).
*/

struct DeviceNode {
    BPTR	dn_Next;	/* singly linked list */
    ULONG	dn_Type;	/* always 0 for dos "devices" */
    struct MsgPort *dn_Task;	/* standard dos "task" field.  If this is
                 * null when the node is accesses, a task
                 * will be started up */
    BPTR	dn_Lock;	/* not used for devices -- leave null */
    BSTR	dn_Handler;	/* filename to loadseg (if seglist is null) */
    ULONG	dn_StackSize;	/* stacksize to use when starting task */
    LONG	dn_Priority;	/* task priority when starting task */
    BPTR	dn_Startup;	/* startup msg: FileSysStartupMsg for disks */
    BPTR	dn_SegList;	/* code to run to start new task (if necessary).
                 * if null then dn_Handler will be loaded. */
    BPTR	dn_GlobalVec;	/* BCPL global vector to use when starting
                 * a task.  -1 means that dn_SegList is not
                 * for a bcpl program, so the dos won't
                 * try and construct one.  0 tell the
                 * dos that you obey BCPL linkage rules,
                 * and that it should construct a global
                 * vector for you.
                 */
    BSTR	dn_Name;	/* the node name, e.g. '\3','D','F','3' */
};

#endif	/* DOS_FILEHANDLER_H */


include/libraries/configregs.h

#ifndef LIBRARIES_CONFIGREGS_H
#define LIBRARIES_CONFIGREGS_H
/*
**	$VER: configregs.h 36.13 (15.2.1991)
**	Includes Release 44.1
**
**	AutoConfig (tm) hardware register and bit definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif	/* EXEC_TYPES_H */

/*
** AutoConfig (tm) boards each contain a 32 byte "ExpansionRom" area that is
** read by the system software at configuration time.  Configuration of each
** board starts when the ConfigIn* signal is passed from the previous board
** (or from the system for the first board).  Each board will present it's
** ExpansionRom structure at location $00E80000 to be read by the system.
** This file defines the appearance of the ExpansionRom area.
**
** Expansion boards are actually organized such that only one nybble per
** 16 bit word contains valid information.  The low nybbles of each
** word are combined to fill the structure below. (This table is structured
** as LOGICAL information.  This means that it never corresponds exactly
** with a physical implementation.)
**
** The ExpansionRom space is further split into two regions:  The first 16
** bytes are read-only.  Except for the er_type field, this area is inverted
** by the system software when read in.  The second 16 bytes contain the
** control portion, where all read/write registers are located.
**
** The system builds one "ConfigDev" structure for each board found.  The
** list of boards can be examined using the expansion.library/FindConfigDev
** function.
**
** A special "hacker" Manufacturer ID number is reserved for test use:
** 2011 ($7DB).  When inverted this will look like $F824.
*/

struct ExpansionRom {		/* -First 16 bytes of the expansion ROM */
    UBYTE	er_Type;	/* Board type, size and flags */
    UBYTE	er_Product;	/* Product number, assigned by manufacturer */
    UBYTE	er_Flags;	/* Flags */
    UBYTE	er_Reserved03;	/* Must be zero ($ff inverted) */
    UWORD	er_Manufacturer; /* Unique ID,ASSIGNED BY AMIGA, INC.! */
    ULONG	er_SerialNumber; /* Available for use by manufacturer */
    UWORD	er_InitDiagVec; /* Offset to optional "DiagArea" structure */
    UBYTE	er_Reserved0c;
    UBYTE	er_Reserved0d;
    UBYTE	er_Reserved0e;
    UBYTE	er_Reserved0f;
};

/*
** Note that use of the ec_BaseAddress register is tricky.  The system
** will actually write twice.  First the low order nybble is written
** to the ec_BaseAddress register+2 (D15-D12).	Then the entire byte is
** written to ec_BaseAddress (D15-D8).	This allows writing of a byte-wide
** address to nybble size registers.
*/

struct ExpansionControl {	/* -Second 16 bytes of the expansion ROM */
    UBYTE	ec_Interrupt;	/* Optional interrupt control register */
    UBYTE	ec_Z3_HighBase; /* Zorro III   : Config address bits 24-31 */
    UBYTE	ec_BaseAddress; /* Zorro II/III: Config address bits 16-23 */
    UBYTE	ec_Shutup;	/* The system writes here to shut up a board */
    UBYTE	ec_Reserved14;
    UBYTE	ec_Reserved15;
    UBYTE	ec_Reserved16;
    UBYTE	ec_Reserved17;
    UBYTE	ec_Reserved18;
    UBYTE	ec_Reserved19;
    UBYTE	ec_Reserved1a;
    UBYTE	ec_Reserved1b;
    UBYTE	ec_Reserved1c;
    UBYTE	ec_Reserved1d;
    UBYTE	ec_Reserved1e;
    UBYTE	ec_Reserved1f;
};

/*
** many of the constants below consist of a triplet of equivalent
** definitions: xxMASK is a bit mask of those bits that matter.
** xxBIT is the starting bit number of the field.  xxSIZE is the
** number of bits that make up the definition.	This method is
** used when the field is larger than one bit.
**
** If the field is only one bit wide then the xxB_xx and xxF_xx convention
** is used (xxB_xx is the bit number, and xxF_xx is mask of the bit).
*/

/* manifest constants */
#define E_SLOTSIZE		0x10000
#define E_SLOTMASK		0xffff
#define E_SLOTSHIFT		16

/* these define the free regions of Zorro memory space.
** THESE MAY WELL CHANGE FOR FUTURE PRODUCTS!
*/
#define E_EXPANSIONBASE	0x00e80000	/* Zorro II  config address */
#define EZ3_EXPANSIONBASE	0xff000000	/* Zorro III config address */

#define E_EXPANSIONSIZE	0x00080000	/* Zorro II  I/O type cards */
#define E_EXPANSIONSLOTS	8

#define E_MEMORYBASE		0x00200000	/* Zorro II  8MB space */
#define E_MEMORYSIZE		0x00800000
#define E_MEMORYSLOTS		128

#define EZ3_CONFIGAREA		0x40000000	/* Zorro III space */
#define EZ3_CONFIGAREAEND	0x7FFFFFFF	/* Zorro III space */
#define EZ3_SIZEGRANULARITY	0x00080000	/* 512K increments */

/**** er_Type definitions (ttldcmmm) ***************************************/

/* er_Type board type bits -- the OS ignores "old style" boards */
#define ERT_TYPEMASK		0xc0	/* Bits 7-6 */
#define ERT_TYPEBIT		6
#define ERT_TYPESIZE		2
#define ERT_NEWBOARD		0xc0
#define ERT_ZORROII		ERT_NEWBOARD
#define ERT_ZORROIII		0x80

/* other bits defined in er_Type */
#define ERTB_MEMLIST		5   /* Link RAM into free memory list */
#define ERTB_DIAGVALID		4   /* ROM vector is valid */
#define ERTB_CHAINEDCONFIG	3   /* Next config is part of the same card */

#define ERTF_MEMLIST		(1<<5)
#define ERTF_DIAGVALID		(1<<4)
#define ERTF_CHAINEDCONFIG	(1<<3)

/* er_Type field memory size bits */
#define ERT_MEMMASK		0x07	/* Bits 2-0 */
#define ERT_MEMBIT		0
#define ERT_MEMSIZE		3

/**** er_Flags byte -- for those things that didn't fit into the type byte ****/
/**** the hardware stores this byte in inverted form			   ****/
#define ERFF_MEMSPACE		(1<<7)	/* Wants to be in 8 meg space. */
#define ERFB_MEMSPACE		7	/* (NOT IMPLEMENTED) */

#define ERFF_NOSHUTUP		(1<<6)	/* Board can't be shut up */
#define ERFB_NOSHUTUP		6

#define ERFF_EXTENDED		(1<<5)	/* Zorro III: Use extended size table */
#define ERFB_EXTENDED		5	/*	      for bits 0-2 of er_Type */
                    /* Zorro II : Must be 0 */

#define ERFF_ZORRO_III		(1<<4)	/* Zorro III: must be 1 */
#define ERFB_ZORRO_III		4	/* Zorro II : must be 0 */

#define ERT_Z3_SSMASK		0x0F	/* Bits 3-0.  Zorro III Sub-Size.  How */
#define ERT_Z3_SSBIT		0	/* much space the card actually uses   */
#define ERT_Z3_SSSIZE		4	/* (regardless of config granularity)  */
                    /* Zorro II : must be 0	       */

/* ec_Interrupt register (unused) ********************************************/
#define ECIB_INTENA		1
#define ECIB_RESET		3
#define ECIB_INT2PEND		4
#define ECIB_INT6PEND		5
#define ECIB_INT7PEND		6
#define ECIB_INTERRUPTING	7

#define ECIF_INTENA		(1<<1)
#define ECIF_RESET		(1<<3)
#define ECIF_INT2PEND		(1<<4)
#define ECIF_INT6PEND		(1<<5)
#define ECIF_INT7PEND		(1<<6)
#define ECIF_INTERRUPTING	(1<<7)

/* figure out amount of memory needed by this box/board */
#define ERT_MEMNEEDED(t)	\
    (((t)&ERT_MEMMASK)? 0x10000 << (((t)&ERT_MEMMASK) -1) : 0x800000 )

/* same as ERT_MEMNEEDED, but return number of slots */
#define ERT_SLOTSNEEDED(t)	\
    (((t)&ERT_MEMMASK)? 1 << (((t)&ERT_MEMMASK)-1) : 0x80 )

/* convert a expansion slot number into a memory address */
#define EC_MEMADDR(slot)		((slot) << (E_SLOTSHIFT) )

/* a kludge to get the byte offset of a structure */
#define EROFFSET(er)	((int)&((struct ExpansionRom *)0)->er)
#define ECOFFSET(ec)	\
 (sizeof(struct ExpansionRom)+((int)&((struct ExpansionControl *)0)->ec))

/***************************************************************************
**
** these are the specifications for the diagnostic area.  If the Diagnostic
** Address Valid bit is set in the Board Type byte (the first byte in
** expansion space) then the Diag Init vector contains a valid offset.
**
** The Diag Init vector is actually a word offset from the base of the
** board.  The resulting address points to the base of the DiagArea
** structure.  The structure may be physically implemented either four,
** eight, or sixteen bits wide.  The code will be copied out into
** ram first before being called.
**
** The da_Size field, and both code offsets (da_DiagPoint and da_BootPoint)
** are offsets from the diag area AFTER it has been copied into ram, and
** "de-nibbleized" (if needed).  (In other words, the size is the size of
** the actual information, not how much address space is required to
** store it.)
**
** All bits are encoded with uninverted logic (e.g. 5 volts on the bus
** is a logic one).
**
** If your board is to make use of the boot facility then it must leave
** its config area available even after it has been configured.  Your
** boot vector will be called AFTER your board's final address has been
** set.
**
****************************************************************************/

struct DiagArea {
    UBYTE	da_Config;	/* see below for definitions */
    UBYTE	da_Flags;	/* see below for definitions */
    UWORD	da_Size;	/* the size (in bytes) of the total diag area */
    UWORD	da_DiagPoint;	/* where to start for diagnostics, or zero */
    UWORD	da_BootPoint;	/* where to start for booting */
    UWORD	da_Name;	/* offset in diag area where a string */
                /*   identifier can be found (or zero if no */
                /*   identifier is present). */

    UWORD	da_Reserved01;	/* two words of reserved data.	must be zero. */
    UWORD	da_Reserved02;
};

/* da_Config definitions */
/*
** DAC_BYTEWIDE can be simulated using DAC_NIBBLEWIDE.
*/
#define DAC_BUSWIDTH	0xC0 /* two bits for bus width */
#define DAC_NIBBLEWIDE	0x00
#define DAC_BYTEWIDE	0x40 /* BUG: Will not work under V34 Kickstart! */
#define DAC_WORDWIDE	0x80

#define DAC_BOOTTIME	0x30	/* two bits for when to boot */
#define DAC_NEVER	0x00	/* obvious */
#define DAC_CONFIGTIME	0x10	/* call da_BootPoint when first configing */
                /*   the device */
#define DAC_BINDTIME	0x20	/* run when binding drivers to boards */

/*
**
** These are the calling conventions for the diagnostic callback
** (from da_DiagPoint):
**
** A7 -- points to at least 2K of stack
** A6 -- ExecBase
** A5 -- ExpansionBase
** A3 -- your board's ConfigDev structure
** A2 -- Base of diag/init area that was copied
** A0 -- Base of your board
**
** Your board must return a value in D0.  If this value is NULL, then
** the diag/init area that was copied in will be returned to the free
** memory pool.
*/

#endif /* LIBRARIES_CONFIGREGS_H */


include/graphics/displayinfo.h

#ifndef	GRAPHICS_DISPLAYINFO_H
#define	GRAPHICS_DISPLAYINFO_H
/*
**	$VER: displayinfo.h 39.13 (31.5.1993)
**	Includes Release 44.1
**
**	include define file for displayinfo database
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif /* EXEC_TYPES_H */

#ifndef GRAPHICS_GFX_H
#include <graphics/gfx.h>
#endif /* GRAPHICS_GFX_H */

#ifndef GRAPHICS_MONITOR_H
#include <graphics/monitor.h>
#endif /* GRAPHICS_MONITOR_H */

#ifndef GRAPHICS_MODEID_H
#include <graphics/modeid.h>
#endif /* GRAPHICS_MODEID_H */

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif /* UTILITY_TAGITEM_H */

/* the "public" handle to a DisplayInfoRecord */

typedef APTR DisplayInfoHandle;

/* datachunk type identifiers */

#define DTAG_DISP		0x80000000
#define DTAG_DIMS		0x80001000
#define DTAG_MNTR		0x80002000
#define DTAG_NAME		0x80003000
#define DTAG_VEC		0x80004000	/* internal use only */

struct QueryHeader
{
    ULONG	StructID;	/* datachunk type identifier */
    ULONG	DisplayID;	/* copy of display record key	*/
    ULONG	SkipID;		/* TAG_SKIP -- see tagitems.h */
    ULONG	Length;		/* length of local data in double-longwords */
};

struct DisplayInfo
{
    struct	QueryHeader Header;
    UWORD	NotAvailable;	/* if NULL available, else see defines */
    ULONG	PropertyFlags;	/* Properties of this mode see defines */
    Point	Resolution;	/* ticks-per-pixel X/Y		       */
    UWORD	PixelSpeed;	/* aproximation in nanoseconds	       */
    UWORD	NumStdSprites;	/* number of standard amiga sprites    */
    UWORD	PaletteRange;	/* OBSOLETE - use Red/Green/Blue bits instead */
    Point	SpriteResolution; /* std sprite ticks-per-pixel X/Y    */
    UBYTE	pad[4];		/* used internally */
    UBYTE	RedBits;	/* number of Red bits this display supports (V39) */
    UBYTE	GreenBits;	/* number of Green bits this display supports (V39) */
    UBYTE	BlueBits;	/* number of Blue bits this display supports (V39) */
    UBYTE	pad2[5];	/* find some use for this. */
    ULONG	reserved[2];	/* terminator */
};

/* availability */

#define DI_AVAIL_NOCHIPS	0x0001
#define DI_AVAIL_NOMONITOR	0x0002
#define DI_AVAIL_NOTWITHGENLOCK	0x0004

/* mode properties */

#define DIPF_IS_LACE		0x00000001
#define DIPF_IS_DUALPF		0x00000002
#define DIPF_IS_PF2PRI		0x00000004
#define DIPF_IS_HAM		0x00000008

#define DIPF_IS_ECS		0x00000010	/* note: ECS modes (SHIRES, VGA, and **
                                            ** PRODUCTIVITY) do not support      **
                                            ** attached sprites.		     **
                                            */
#define DIPF_IS_AA		0x00010000	/* AA modes - may only be available
                        ** if machine has correct memory
                        ** type to support required
                        ** bandwidth - check availability.
                        ** (V39)
                        */
#define DIPF_IS_PAL		0x00000020
#define DIPF_IS_SPRITES		0x00000040
#define DIPF_IS_GENLOCK		0x00000080

#define DIPF_IS_WB		0x00000100
#define DIPF_IS_DRAGGABLE	0x00000200
#define DIPF_IS_PANELLED	0x00000400
#define DIPF_IS_BEAMSYNC	0x00000800

#define DIPF_IS_EXTRAHALFBRITE	0x00001000

/* The following DIPF_IS_... flags are new for V39 */
#define DIPF_IS_SPRITES_ATT		0x00002000	/* supports attached sprites */
#define DIPF_IS_SPRITES_CHNG_RES	0x00004000	/* supports variable sprite resolution */
#define DIPF_IS_SPRITES_BORDER		0x00008000	/* sprite can be displayed in the border */
#define DIPF_IS_SCANDBL			0x00020000	/* scan doubled */
#define DIPF_IS_SPRITES_CHNG_BASE	0x00040000
                                            /* can change the sprite base colour */
#define DIPF_IS_SPRITES_CHNG_PRI	0x00080000
                                            /* can change the sprite priority
                                            ** with respect to the playfield(s).
                                            */
#define DIPF_IS_DBUFFER		0x00100000	/* can support double buffering */
#define DIPF_IS_PROGBEAM	0x00200000	/* is a programmed beam-sync mode */
#define DIPF_IS_FOREIGN		0x80000000	/* this mode is not native to the Amiga */

struct DimensionInfo
{
    struct	QueryHeader Header;
    UWORD	MaxDepth;	      /* log2( max number of colors ) */
    UWORD	MinRasterWidth;       /* minimum width in pixels      */
    UWORD	MinRasterHeight;      /* minimum height in pixels     */
    UWORD	MaxRasterWidth;       /* maximum width in pixels      */
    UWORD	MaxRasterHeight;      /* maximum height in pixels     */
    struct	Rectangle   Nominal;  /* "standard" dimensions	      */
    struct	Rectangle   MaxOScan; /* fixed, hardware dependent    */
    struct	Rectangle VideoOScan; /* fixed, hardware dependent    */
    struct	Rectangle   TxtOScan; /* editable via preferences     */
    struct	Rectangle   StdOScan; /* editable via preferences     */
    UBYTE	pad[14];
    ULONG	reserved[2];	      /* terminator */
};

struct MonitorInfo
{
    struct	QueryHeader Header;
    struct	MonitorSpec  *Mspc;   /* pointer to monitor specification  */
    Point	ViewPosition;	      /* editable via preferences	   */
    Point	ViewResolution;       /* standard monitor ticks-per-pixel  */
    struct	Rectangle ViewPositionRange;  /* fixed, hardware dependent */
    UWORD	TotalRows;	      /* display height in scanlines	   */
    UWORD	TotalColorClocks;     /* scanline width in 280 ns units    */
    UWORD	MinRow;	      /* absolute minimum active scanline  */
    WORD	Compatibility;	      /* how this coexists with others	   */
    UBYTE	pad[32];
    Point	MouseTicks;
    Point	DefaultViewPosition;  /* original, never changes */
    ULONG	PreferredModeID;      /* for Preferences */
    ULONG	reserved[2];	      /* terminator */
};

/* monitor compatibility */

#define MCOMPAT_MIXED	0	/* can share display with other MCOMPAT_MIXED */
#define MCOMPAT_SELF	1	/* can share only within same monitor */
#define MCOMPAT_NOBODY -1	/* only one viewport at a time */

#define DISPLAYNAMELEN 32

struct NameInfo
{
    struct	QueryHeader Header;
    UBYTE	Name[DISPLAYNAMELEN];
    ULONG	reserved[2];	      /* terminator */
};

/******************************************************************************/

/* The following VecInfo structure is PRIVATE, for our use only
 * Touch these, and burn! (V39)
 */

struct VecInfo
{
    struct	QueryHeader   Header;
    APTR	Vec;
    APTR	Data;
    UWORD	Type;
    UWORD	pad[3];
    ULONG	reserved[2];
};

#endif	/* GRAPHICS_DISPLAYINFO_H */


include/resources/disk.h

#ifndef	RESOURCES_DISK_H
#define RESOURCES_DISK_H
/*
**	$VER: disk.h 27.11 (21.11.1990)
**	Includes Release 44.1
**
**	disk.h -- external declarations for the disk resource
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef	EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef	EXEC_LISTS_H
#include <exec/lists.h>
#endif

#ifndef	EXEC_PORTS_H
#include <exec/ports.h>
#endif

#ifndef	EXEC_INTERRUPTS_H
#include <exec/interrupts.h>
#endif

#ifndef	EXEC_LIBRARIES_H
#include <exec/libraries.h>
#endif

/********************************************************************
*
* Resource structures
*
********************************************************************/

struct DiscResourceUnit {
    struct Message dru_Message;
    struct Interrupt dru_DiscBlock;
    struct Interrupt dru_DiscSync;
    struct Interrupt dru_Index;
};

struct DiscResource {
    struct Library		dr_Library;
    struct DiscResourceUnit	*dr_Current;
    UBYTE			dr_Flags;
    UBYTE			dr_pad;
    struct Library		*dr_SysLib;
    struct Library		*dr_CiaResource;
    ULONG			dr_UnitID[4];
    struct List		dr_Waiting;
    struct Interrupt		dr_DiscBlock;
    struct Interrupt		dr_DiscSync;
    struct Interrupt		dr_Index;
    struct Task			*dr_CurrTask;
};

/* dr_Flags entries */
#define DRB_ALLOC0	0	/* unit zero is allocated */
#define DRB_ALLOC1	1	/* unit one is allocated */
#define DRB_ALLOC2	2	/* unit two is allocated */
#define DRB_ALLOC3	3	/* unit three is allocated */
#define DRB_ACTIVE	7	/* is the disc currently busy? */

#define DRF_ALLOC0	(1<<0)	/* unit zero is allocated */
#define DRF_ALLOC1	(1<<1)	/* unit one is allocated */
#define DRF_ALLOC2	(1<<2)	/* unit two is allocated */
#define DRF_ALLOC3	(1<<3)	/* unit three is allocated */
#define DRF_ACTIVE	(1<<7)	/* is the disc currently busy? */

/********************************************************************
*
* Hardware Magic
*
********************************************************************/

#define	DSKDMAOFF	0x4000	/* idle command for dsklen register */

/********************************************************************
*
* Resource specific commands
*
********************************************************************/

/*
 * DISKNAME is a generic macro to get the name of the resource.
 * This way if the name is ever changed you will pick up the
 *  change automatically.
 */

#define DISKNAME	"disk.resource"

#define	DR_ALLOCUNIT	(LIB_BASE - 0*LIB_VECTSIZE)
#define	DR_FREEUNIT	(LIB_BASE - 1*LIB_VECTSIZE)
#define	DR_GETUNIT	(LIB_BASE - 2*LIB_VECTSIZE)
#define	DR_GIVEUNIT	(LIB_BASE - 3*LIB_VECTSIZE)
#define	DR_GETUNITID	(LIB_BASE - 4*LIB_VECTSIZE)
#define	DR_READUNITID	(LIB_BASE - 5*LIB_VECTSIZE)

#define	DR_LASTCOMM	(DR_READUNITID)

/********************************************************************
*
* drive types
*
********************************************************************/

#define	DRT_AMIGA	(0x00000000)
#define	DRT_37422D2S	(0x55555555)
#define DRT_EMPTY	(0xFFFFFFFF)
#define DRT_150RPM	(0xAAAAAAAA)

#endif /* RESOURCES_DISK_H */


include/libraries/asl.h

#ifndef	LIBRARIES_ASL_H
#define	LIBRARIES_ASL_H
/*
**	$VER: asl.h 44.1 (12.5.1999)
**	Includes Release 44.1
**
**	ASL library structures and constants
**
**	Copyright © 1989-1999 Amiga, Inc.
**	Copyright © 1989-1990 Charlie Heath
**	All Rights Reserved
*/

/*****************************************************************************/

#ifndef	EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef	EXEC_NODES_H
#include <exec/nodes.h>
#endif

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

#ifndef WORKBENCH_STARTUP_H
#include <workbench/startup.h>
#endif

#ifndef GRAPHICS_TEXT_H
#include <graphics/text.h>
#endif

#ifndef GRAPHICS_DISPLAYINFO_H
#include <graphics/displayinfo.h>
#endif

/*****************************************************************************/

#define	AslName "asl.library"
#define ASL_TB	(TAG_USER+0x80000)

/*****************************************************************************/

/* Types of requesters known to ASL, used as arguments to AllocAslRequest() */
#define	ASL_FileRequest	      0
#define	ASL_FontRequest	      1
#define	ASL_ScreenModeRequest 2

/*****************************************************************************
 *
 * ASL File Requester data structures and constants
 *
 * This structure must only be allocated by asl.library amd is READ-ONLY!
 * Control of the various fields is provided via tags when the requester
 * is created with AllocAslRequest() and when it is displayed via
 * AslRequest()
 */
struct FileRequester
{
    UBYTE	  fr_Reserved0[4];
    STRPTR	  fr_File;	      /* Contents of File gadget on exit    */
    STRPTR	  fr_Drawer;	      /* Contents of Drawer gadget on exit  */
    UBYTE	  fr_Reserved1[10];
    WORD	  fr_LeftEdge;	      /* Coordinates of requester on exit   */
    WORD	  fr_TopEdge;
    WORD	  fr_Width;
    WORD	  fr_Height;
    UBYTE	  fr_Reserved2[2];
    LONG	  fr_NumArgs;	      /* Number of files selected	    */
    struct WBArg *fr_ArgList;	      /* List of files selected	    */
    APTR	  fr_UserData;	      /* You can store your own data here   */
    UBYTE	  fr_Reserved3[8];
    STRPTR	  fr_Pattern;	      /* Contents of Pattern gadget on exit */
};

/* File requester tag values, used by AllocAslRequest() and AslRequest() */

/* Window control */
#define ASLFR_Window	      ASL_TB+2	 /* Parent window		     */
#define ASLFR_Screen	      ASL_TB+40  /* Screen to open on if no window   */
#define ASLFR_PubScreenName   ASL_TB+41  /* Name of public screen	     */
#define ASLFR_PrivateIDCMP    ASL_TB+42  /* Allocate private IDCMP?	     */
#define ASLFR_IntuiMsgFunc    ASL_TB+70  /* Function to handle IntuiMessages */
#define ASLFR_SleepWindow     ASL_TB+43  /* Block input in ASLFR_Window?     */
#define ASLFR_UserData	      ASL_TB+52  /* What to put in fr_UserData	     */
#define ASLFR_PopToFront      ASL_TB+131 /* Make the requester window visible
                                          * when it opens (V44)
                                          */

/* Text display */
#define ASLFR_TextAttr	      ASL_TB+51  /* Text font to use for gadget text */
#define ASLFR_Locale	      ASL_TB+50  /* Locale ASL should use for text   */
#define ASLFR_TitleText       ASL_TB+1	 /* Title of requester		     */
#define ASLFR_PositiveText    ASL_TB+18  /* Positive gadget text	     */
#define ASLFR_NegativeText    ASL_TB+19  /* Negative gadget text	     */

/* Initial settings */
#define ASLFR_InitialLeftEdge ASL_TB+3	 /* Initial requester coordinates    */
#define ASLFR_InitialTopEdge  ASL_TB+4
#define ASLFR_InitialWidth    ASL_TB+5	 /* Initial requester dimensions     */
#define ASLFR_InitialHeight   ASL_TB+6
#define ASLFR_InitialFile     ASL_TB+8	 /* Initial contents of File gadget  */
#define ASLFR_InitialDrawer   ASL_TB+9	 /* Initial contents of Drawer gadg. */
#define ASLFR_InitialPattern  ASL_TB+10  /* Initial contents of Pattern gadg.*/
#define ASLFR_InitialShowVolumes ASL_TB+130 /* Initially, show the volume list (V44) */

/* Options */
#define ASLFR_Flags1	      ASL_TB+20  /* Option flags		     */
#define ASLFR_Flags2	      ASL_TB+22  /* Additional option flags	     */
#define ASLFR_DoSaveMode      ASL_TB+44  /* Being used for saving?	     */
#define ASLFR_DoMultiSelect   ASL_TB+45  /* Do multi-select?		     */
#define ASLFR_DoPatterns      ASL_TB+46  /* Display a Pattern gadget?	     */

/* Filtering */
#define ASLFR_DrawersOnly     ASL_TB+47  /* Don't display files?	     */
#define ASLFR_FilterFunc      ASL_TB+49  /* Function to filter files	     */
#define ASLFR_RejectIcons     ASL_TB+60  /* Display .info files?	     */
#define ASLFR_RejectPattern   ASL_TB+61  /* Don't display files matching pat */
#define ASLFR_AcceptPattern   ASL_TB+62  /* Accept only files matching pat   */
#define ASLFR_FilterDrawers   ASL_TB+63  /* Also filter drawers with patterns*/
#define	ASLFR_HookFunc	      ASL_TB+7	 /* Combined callback function	     */

/* Sorting */
#define ASLFR_SetSortBy       ASL_TB+124 /* Sort criteria (name, date, size) */
#define ASLFR_GetSortBy       ASL_TB+125
#define ASLFR_SetSortDrawers  ASL_TB+126 /* Placement of drawers in the list */
#define ASLFR_GetSortDrawers  ASL_TB+127
#define ASLFR_SetSortOrder    ASL_TB+128 /* Order (ascending or descending)  */
#define ASLFR_GetSortOrder    ASL_TB+129

/* Flag bits for the ASLFR_Flags1 tag */
#define	FRB_FILTERFUNC	   7
#define	FRB_INTUIFUNC	   6
#define	FRB_DOSAVEMODE	   5
#define	FRB_PRIVATEIDCMP   4
#define FRB_DOMULTISELECT  3
#define	FRB_DOPATTERNS	   0

#define	FRF_FILTERFUNC	   (1L << FRB_FILTERFUNC)
#define	FRF_INTUIFUNC	   (1L << FRB_INTUIFUNC)
#define	FRF_DOSAVEMODE	   (1L << FRB_DOSAVEMODE)
#define	FRF_PRIVATEIDCMP   (1L << FRB_PRIVATEIDCMP)
#define	FRF_DOMULTISELECT  (1L << FRB_DOMULTISELECT)
#define	FRF_DOPATTERNS	   (1L << FRB_DOPATTERNS)

/* Flag bits for the ASLFR_Flags2 tag */
#define	FRB_DRAWERSONLY    0
#define	FRB_FILTERDRAWERS  1
#define	FRB_REJECTICONS    2

#define	FRF_DRAWERSONLY    (1L << FRB_DRAWERSONLY)
#define	FRF_FILTERDRAWERS  (1L << FRB_FILTERDRAWERS)
#define	FRF_REJECTICONS    (1L << FRB_REJECTICONS)

/* Sort criteria for the ASLFR_SetSortBy/ASLFR_GetSortBy tags */
#define ASLFRSORTBY_Name   0
#define ASLFRSORTBY_Date   1
#define ASLFRSORTBY_Size   2

/* Drawer placement for the ASLFR_SetSortDrawers/ASLFR_GetSortDrawers tags */
#define ASLFRSORTDRAWERS_First  0
#define ASLFRSORTDRAWERS_Mix    1
#define ASLFRSORTDRAWERS_Last   2

/* Sort order for the ASLFR_SetSortOrder/ASLFR_GetSortOrder tags */
#define ASLFRSORTORDER_Ascend   0
#define ASLFRSORTORDER_Descend  1

/*****************************************************************************
 *
 * ASL Font Requester data structures and constants
 *
 * This structure must only be allocated by asl.library amd is READ-ONLY!
 * Control of the various fields is provided via tags when the requester
 * is created with AllocAslRequest() and when it is displayed via
 * AslRequest()
 */
struct FontRequester
{
    UBYTE	     fo_Reserved0[8];
    struct TextAttr  fo_Attr;		/* Returned TextAttr		    */
    UBYTE	     fo_FrontPen;	/* Returned front pen		    */
    UBYTE	     fo_BackPen;	/* Returned back pen		    */
    UBYTE	     fo_DrawMode;	/* Returned drawing mode	    */
    UBYTE	     fo_Reserved1;
    APTR	     fo_UserData;	/* You can store your own data here */
    WORD	     fo_LeftEdge;	/* Coordinates of requester on exit */
    WORD	     fo_TopEdge;
    WORD	     fo_Width;
    WORD	     fo_Height;
    struct TTextAttr fo_TAttr;		/* Returned TTextAttr		    */
};

/* Font requester tag values, used by AllocAslRequest() and AslRequest() */

/* Window control */
#define ASLFO_Window	      ASL_TB+2	 /* Parent window		     */
#define ASLFO_Screen	      ASL_TB+40  /* Screen to open on if no window   */
#define ASLFO_PubScreenName   ASL_TB+41  /* Name of public screen	     */
#define ASLFO_PrivateIDCMP    ASL_TB+42  /* Allocate private IDCMP?	     */
#define ASLFO_IntuiMsgFunc    ASL_TB+70  /* Function to handle IntuiMessages */
#define ASLFO_SleepWindow     ASL_TB+43  /* Block input in ASLFO_Window?     */
#define ASLFO_UserData	      ASL_TB+52  /* What to put in fo_UserData	     */
#define ASLFO_PopToFront      ASL_TB+131 /* Make the requester window visible
                                          * when it opens (V44)
                                          */

/* Text display */
#define ASLFO_TextAttr	      ASL_TB+51  /* Text font to use for gadget text */
#define ASLFO_Locale	      ASL_TB+50  /* Locale ASL should use for text   */
#define ASLFO_TitleText       ASL_TB+1	 /* Title of requester		     */
#define ASLFO_PositiveText    ASL_TB+18  /* Positive gadget text	     */
#define ASLFO_NegativeText    ASL_TB+19  /* Negative gadget text	     */

/* Initial settings */
#define ASLFO_InitialLeftEdge ASL_TB+3	 /* Initial requester coordinates    */
#define ASLFO_InitialTopEdge  ASL_TB+4
#define ASLFO_InitialWidth    ASL_TB+5	 /* Initial requester dimensions     */
#define ASLFO_InitialHeight   ASL_TB+6
#define ASLFO_InitialName     ASL_TB+10  /* Initial contents of Name gadget  */
#define ASLFO_InitialSize     ASL_TB+11  /* Initial contents of Size gadget  */
#define ASLFO_InitialStyle    ASL_TB+12  /* Initial font style		     */
#define ASLFO_InitialFlags    ASL_TB+13  /* Initial font flags for TextAttr  */
#define ASLFO_InitialFrontPen ASL_TB+14  /* Initial front pen		     */
#define ASLFO_InitialBackPen  ASL_TB+15  /* Initial back pen		     */
#define ASLFO_InitialDrawMode ASL_TB+59  /* Initial draw mode		     */

/* Options */
#define ASLFO_Flags	      ASL_TB+20  /* Option flags		     */
#define ASLFO_DoFrontPen      ASL_TB+44  /* Display Front color selector?    */
#define ASLFO_DoBackPen       ASL_TB+45  /* Display Back color selector?     */
#define ASLFO_DoStyle	      ASL_TB+46  /* Display Style checkboxes?	     */
#define ASLFO_DoDrawMode      ASL_TB+47  /* Display DrawMode cycle gadget?   */

/* Filtering */
#define ASLFO_FixedWidthOnly  ASL_TB+48  /* Only allow fixed-width fonts?    */
#define ASLFO_MinHeight       ASL_TB+16  /* Minimum font height to display   */
#define ASLFO_MaxHeight       ASL_TB+17  /* Maximum font height to display   */
#define ASLFO_FilterFunc      ASL_TB+49  /* Function to filter fonts	     */
#define	ASLFO_HookFunc	      ASL_TB+7	 /* Combined callback function	     */
#define ASLFO_MaxFrontPen     ASL_TB+66  /* Max # of colors in front palette */
#define ASLFO_MaxBackPen      ASL_TB+67  /* Max # of colors in back palette  */

/* Custom additions */
#define	ASLFO_ModeList	      ASL_TB+21	 /* Substitute list for drawmodes    */
#define ASLFO_FrontPens       ASL_TB+64  /* Color table for front pen palette*/
#define ASLFO_BackPens	      ASL_TB+65  /* Color table for back pen palette */

/* Flag bits for ASLFO_Flags tag */
#define	FOB_DOFRONTPEN	   0
#define	FOB_DOBACKPEN	   1
#define	FOB_DOSTYLE	   2
#define	FOB_DODRAWMODE	   3
#define	FOB_FIXEDWIDTHONLY 4
#define	FOB_PRIVATEIDCMP   5
#define	FOB_INTUIFUNC	   6
#define	FOB_FILTERFUNC	   7

#define	FOF_DOFRONTPEN	   (1L << FOB_DOFRONTPEN)
#define	FOF_DOBACKPEN	   (1L << FOB_DOBACKPEN)
#define	FOF_DOSTYLE	   (1L << FOB_DOSTYLE)
#define	FOF_DODRAWMODE	   (1L << FOB_DODRAWMODE)
#define	FOF_FIXEDWIDTHONLY (1L << FOB_FIXEDWIDTHONLY)
#define	FOF_PRIVATEIDCMP   (1L << FOB_PRIVATEIDCMP)
#define	FOF_INTUIFUNC	   (1L << FOB_INTUIFUNC)
#define	FOF_FILTERFUNC	   (1L << FOB_FILTERFUNC)

/*****************************************************************************
 *
 * ASL Screen Mode Requester data structures and constants
 *
 * This structure must only be allocated by asl.library and is READ-ONLY!
 * Control of the various fields is provided via tags when the requester
 * is created with AllocAslRequest() and when it is displayed via
 * AslRequest()
 */
struct ScreenModeRequester
{
    ULONG sm_DisplayID;	   /* Display mode ID		       */
    ULONG sm_DisplayWidth;	   /* Width of display in pixels       */
    ULONG sm_DisplayHeight;	   /* Height of display in pixels      */
    UWORD sm_DisplayDepth;	   /* Number of bit-planes of display  */
    UWORD sm_OverscanType;	   /* Type of overscan of display      */
    BOOL  sm_AutoScroll;	   /* Display should auto-scroll?      */

    ULONG sm_BitMapWidth;	   /* Used to create your own BitMap   */
    ULONG sm_BitMapHeight;

    WORD  sm_LeftEdge;		   /* Coordinates of requester on exit */
    WORD  sm_TopEdge;
    WORD  sm_Width;
    WORD  sm_Height;

    BOOL  sm_InfoOpened;	   /* Info window opened on exit?      */
    WORD  sm_InfoLeftEdge;	   /* Last coordinates of Info window  */
    WORD  sm_InfoTopEdge;
    WORD  sm_InfoWidth;
    WORD  sm_InfoHeight;

    APTR  sm_UserData;		   /* You can store your own data here */
};

/* An Exec list of custom modes can be added to the list of available modes.
 * The DimensionInfo structure must be completely initialized, including the
 * Header. See <graphics/displayinfo.h>. Custom mode ID's must be in the range
 * 0xFFFF0000..0xFFFFFFFF. Regular properties which apply to your custom modes
 * can be added in the dn_PropertyFlags field. Custom properties are not
 * allowed.
 */
struct DisplayMode
{
    struct Node	 dm_Node;	      /* see ln_Name	       */
    struct DimensionInfo dm_DimensionInfo;    /* mode description      */
    ULONG		 dm_PropertyFlags;    /* applicable properties */
};

/* ScreenMode requester tag values, used by AllocAslRequest() and AslRequest() */

/* Window control */
#define ASLSM_Window	      ASL_TB+2	 /* Parent window		     */
#define ASLSM_Screen	      ASL_TB+40  /* Screen to open on if no window   */
#define ASLSM_PubScreenName   ASL_TB+41  /* Name of public screen	     */
#define ASLSM_PrivateIDCMP    ASL_TB+42  /* Allocate private IDCMP?	     */
#define ASLSM_IntuiMsgFunc    ASL_TB+70  /* Function to handle IntuiMessages */
#define ASLSM_SleepWindow     ASL_TB+43  /* Block input in ASLSM_Window?     */
#define ASLSM_UserData	      ASL_TB+52  /* What to put in sm_UserData	     */
#define ASLSM_PopToFront      ASL_TB+131 /* Make the requester window visible
                                          * when it opens (V44)
                                          */

/* Text display */
#define ASLSM_TextAttr	      ASL_TB+51  /* Text font to use for gadget text */
#define ASLSM_Locale	      ASL_TB+50  /* Locale ASL should use for text   */
#define ASLSM_TitleText       ASL_TB+1	 /* Title of requester		     */
#define ASLSM_PositiveText    ASL_TB+18  /* Positive gadget text	     */
#define ASLSM_NegativeText    ASL_TB+19  /* Negative gadget text	     */

/* Initial settings */
#define ASLSM_InitialLeftEdge ASL_TB+3	 /* Initial requester coordinates    */
#define ASLSM_InitialTopEdge  ASL_TB+4
#define ASLSM_InitialWidth    ASL_TB+5	 /* Initial requester dimensions     */
#define ASLSM_InitialHeight   ASL_TB+6
#define ASLSM_InitialDisplayID	   ASL_TB+100 /* Initial display mode id     */
#define ASLSM_InitialDisplayWidth  ASL_TB+101 /* Initial display width	     */
#define ASLSM_InitialDisplayHeight ASL_TB+102 /* Initial display height      */
#define ASLSM_InitialDisplayDepth  ASL_TB+103 /* Initial display depth	     */
#define ASLSM_InitialOverscanType  ASL_TB+104 /* Initial type of overscan    */
#define ASLSM_InitialAutoScroll    ASL_TB+105 /* Initial autoscroll setting  */
#define ASLSM_InitialInfoOpened    ASL_TB+106 /* Info wndw initially opened? */
#define ASLSM_InitialInfoLeftEdge  ASL_TB+107 /* Initial Info window coords. */
#define ASLSM_InitialInfoTopEdge   ASL_TB+108

/* Options */
#define ASLSM_DoWidth	      ASL_TB+109  /* Display Width gadget?	     */
#define ASLSM_DoHeight	      ASL_TB+110  /* Display Height gadget?	     */
#define ASLSM_DoDepth	      ASL_TB+111  /* Display Depth gadget?	     */
#define ASLSM_DoOverscanType  ASL_TB+112  /* Display Overscan Type gadget?   */
#define ASLSM_DoAutoScroll    ASL_TB+113  /* Display AutoScroll gadget?      */

/* Filtering */
#define ASLSM_PropertyFlags   ASL_TB+114  /* Must have these Property flags  */
#define ASLSM_PropertyMask    ASL_TB+115  /* Only these should be looked at  */
#define ASLSM_MinWidth	      ASL_TB+116  /* Minimum display width to allow  */
#define ASLSM_MaxWidth	      ASL_TB+117  /* Maximum display width to allow  */
#define ASLSM_MinHeight       ASL_TB+118  /* Minimum display height to allow */
#define ASLSM_MaxHeight       ASL_TB+119  /* Maximum display height to allow */
#define ASLSM_MinDepth	      ASL_TB+120  /* Minimum display depth	     */
#define ASLSM_MaxDepth	      ASL_TB+121  /* Maximum display depth	     */
#define ASLSM_FilterFunc      ASL_TB+122  /* Function to filter mode id's    */

/* Custom additions */
#define ASLSM_CustomSMList    ASL_TB+123  /* Exec list of struct DisplayMode */

/*****************************************************************************/

#define ASL_LAST_TAG ASL_TB+131

/*****************************************************************************
 *
 * Obsolete ASL definitions, here for source code compatibility only.
 * Please do NOT use in new code.
 *
 * #define ASL_V38_NAMES_ONLY to remove these older names
 */
#ifndef ASL_V38_NAMES_ONLY
#define rf_File		 fr_File
#define rf_Dir		 fr_Drawer
#define rf_LeftEdge	 fr_LeftEdge
#define rf_TopEdge	 fr_TopEdge
#define rf_Width	 fr_Width
#define rf_Height	 fr_Height
#define rf_NumArgs	 fr_NumArgs
#define rf_ArgList	 fr_ArgList
#define rf_UserData	 fr_UserData
#define rf_Pat		 fr_Pattern
#define ASL_Dummy	 (TAG_USER + 0x80000)
#define ASL_Hail	 ASL_Dummy+1
#define ASL_Window	 ASL_Dummy+2
#define	ASL_LeftEdge	 ASL_Dummy+3
#define	ASL_TopEdge	 ASL_Dummy+4
#define	ASL_Width	 ASL_Dummy+5
#define	ASL_Height	 ASL_Dummy+6
#define	ASL_HookFunc	 ASL_Dummy+7
#define	ASL_File	 ASL_Dummy+8
#define	ASL_Dir		 ASL_Dummy+9
#define	ASL_FontName	 ASL_Dummy+10
#define	ASL_FontHeight	 ASL_Dummy+11
#define	ASL_FontStyles	 ASL_Dummy+12
#define	ASL_FontFlags	 ASL_Dummy+13
#define	ASL_FrontPen	 ASL_Dummy+14
#define	ASL_BackPen	 ASL_Dummy+15
#define	ASL_MinHeight	 ASL_Dummy+16
#define	ASL_MaxHeight	 ASL_Dummy+17
#define	ASL_OKText	 ASL_Dummy+18
#define	ASL_CancelText	 ASL_Dummy+19
#define	ASL_FuncFlags	 ASL_Dummy+20
#define	ASL_ModeList	 ASL_Dummy+21
#define	ASL_ExtFlags1	 ASL_Dummy+22
#define	ASL_Pattern	 ASL_FontName
/* remember what I said up there? Do not use these anymore! */
#define	FILB_DOWILDFUNC	 7L
#define	FILB_DOMSGFUNC	 6L
#define	FILB_SAVE	 5L
#define	FILB_NEWIDCMP	 4L
#define FILB_MULTISELECT 3L
#define	FILB_PATGAD	 0L
#define	FILF_DOWILDFUNC	 (1L << FILB_DOWILDFUNC)
#define	FILF_DOMSGFUNC	 (1L << FILB_DOMSGFUNC)
#define	FILF_SAVE	 (1L << FILB_SAVE)
#define	FILF_NEWIDCMP	 (1L << FILB_NEWIDCMP)
#define	FILF_MULTISELECT (1L << FILB_MULTISELECT)
#define	FILF_PATGAD	 (1L << FILB_PATGAD)
#define	FIL1B_NOFILES	 0L
#define	FIL1B_MATCHDIRS	 1L
#define	FIL1F_NOFILES	 (1L << FIL1B_NOFILES)
#define	FIL1F_MATCHDIRS	 (1L << FIL1B_MATCHDIRS)
#define	FONB_FRONTCOLOR	0
#define	FONB_BACKCOLOR	1
#define	FONB_STYLES	2
#define	FONB_DRAWMODE	3
#define	FONB_FIXEDWIDTH	4
#define	FONB_NEWIDCMP	5
#define	FONB_DOMSGFUNC	6
#define	FONB_DOWILDFUNC	7
#define	FONF_FRONTCOLOR	(1L << FONB_FRONTCOLOR)
#define	FONF_BACKCOLOR	(1L << FONB_BACKCOLOR)
#define	FONF_STYLES	(1L << FONB_STYLES)
#define	FONF_DRAWMODE	(1L << FONB_DRAWMODE)
#define	FONF_FIXEDWIDTH	(1L << FONB_FIXEDWIDTH)
#define	FONF_NEWIDCMP	(1L << FONB_NEWIDCMP)
#define	FONF_DOMSGFUNC	(1L << FONB_DOMSGFUNC)
#define	FONF_DOWILDFUNC	(1L << FONB_DOWILDFUNC)
#endif

/*****************************************************************************/

#endif /* LIBRARIES_ASL_H */


include/intuition/screens.h

#ifndef INTUITION_SCREENS_H
#define INTUITION_SCREENS_H TRUE
/*
**  $VER: screens.h 38.25 (15.2.1993)
**  Includes Release 44.1
**
**  The Screen and NewScreen structures and attributes
**
**  (C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef GRAPHICS_GFX_H
#include <graphics/gfx.h>
#endif

#ifndef GRAPHICS_CLIP_H
#include <graphics/clip.h>
#endif

#ifndef GRAPHICS_VIEW_H
#include <graphics/view.h>
#endif

#ifndef GRAPHICS_RASTPORT_H
#include <graphics/rastport.h>
#endif

#ifndef GRAPHICS_LAYERS_H
#include <graphics/layers.h>
#endif

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

/*
 * NOTE:  intuition/iobsolete.h is included at the END of this file!
 */

/* ======================================================================== */
/* === DrawInfo ========================================================= */
/* ======================================================================== */

/* This is a packet of information for graphics rendering.  It originates
 * with a Screen, and is gotten using GetScreenDrawInfo( screen );
 */

/* You can use the Intuition version number to tell which fields are
 * present in this structure.
 *
 * DRI_VERSION of 1 corresponds to V37 release.
 * DRI_VERSION of 2 corresponds to V39, and includes three new pens
 *	and the dri_CheckMark and dri_AmigaKey fields.
 *
 * Note that sometimes applications need to create their own DrawInfo
 * structures, in which case the DRI_VERSION won't correspond exactly
 * to the OS version!!!
 */
#define DRI_VERSION	(2)

struct DrawInfo
{
    UWORD	dri_Version;	/* will be  DRI_VERSION			*/
    UWORD	dri_NumPens;	/* guaranteed to be >= 9		*/
    UWORD	*dri_Pens;	/* pointer to pen array			*/

    struct TextFont	*dri_Font;	/* screen default font		*/
    UWORD	dri_Depth;	/* (initial) depth of screen bitmap	*/

    struct {	  /* from DisplayInfo database for initial display mode	*/
    UWORD	X;
    UWORD	Y;
    }		dri_Resolution;

    ULONG	dri_Flags;		/* defined below		*/
/* New for V39: dri_CheckMark, dri_AmigaKey. */
    struct Image	*dri_CheckMark;	/* pointer to scaled checkmark image
                     * Will be NULL if DRI_VERSION < 2
                     */
    struct Image	*dri_AmigaKey;	/* pointer to scaled Amiga-key image
                     * Will be NULL if DRI_VERSION < 2
                     */
    ULONG	dri_Reserved[5];	/* avoid recompilation ;^)	*/
};

#define DRIF_NEWLOOK	0x00000001L	/* specified SA_Pens, full treatment */

/* rendering pen number indexes into DrawInfo.dri_Pens[]	*/
#define DETAILPEN	 (0x0000)	/* compatible Intuition rendering pens	*/
#define BLOCKPEN	 (0x0001)	/* compatible Intuition rendering pens	*/
#define TEXTPEN		 (0x0002)	/* text on background			*/
#define SHINEPEN	 (0x0003)	/* bright edge on 3D objects		*/
#define SHADOWPEN	 (0x0004)	/* dark edge on 3D objects		*/
#define FILLPEN		 (0x0005)	/* active-window/selected-gadget fill	*/
#define FILLTEXTPEN	 (0x0006)	/* text over FILLPEN			*/
#define BACKGROUNDPEN	 (0x0007)	/* may not always be color 0		*/
#define HIGHLIGHTTEXTPEN (0x0008)	/* special color text, on background	*/
/* New for V39, only present if DRI_VERSION >= 2: */
#define BARDETAILPEN	 (0x0009)	/* text/detail in screen-bar/menus */
#define BARBLOCKPEN	 (0x000A)	/* screen-bar/menus fill */
#define BARTRIMPEN	 (0x000B)	/* trim under screen-bar */

#define NUMDRIPENS	 (0x000C)

/* New for V39:  It is sometimes useful to specify that a pen value
 * is to be the complement of color zero to three.  The "magic" numbers
 * serve that purpose:
 */
#define PEN_C3		0xFEFC		/* Complement of color 3 */
#define PEN_C2		0xFEFD		/* Complement of color 2 */
#define PEN_C1		0xFEFE		/* Complement of color 1 */
#define PEN_C0		0xFEFF		/* Complement of color 0 */

/* ======================================================================== */
/* === Screen ============================================================= */
/* ======================================================================== */

/* VERY IMPORTANT NOTE ABOUT Screen->BitMap.  In the future, bitmaps
 * will need to grow.  The embedded instance of a bitmap in the screen
 * will no longer be large enough to hold the whole description of
 * the bitmap.
 *
 * YOU ARE STRONGLY URGED to use Screen->RastPort.BitMap in place of
 * &Screen->BitMap whenever and whereever possible.
 */

struct Screen
{
    struct Screen *NextScreen;		/* linked list of screens */
    struct Window *FirstWindow;		/* linked list Screen's Windows */

    WORD LeftEdge, TopEdge;		/* parameters of the screen */
    WORD Width, Height;			/* parameters of the screen */

    WORD MouseY, MouseX;		/* position relative to upper-left */

    UWORD Flags;			/* see definitions below */

    UBYTE *Title;			/* null-terminated Title text */
    UBYTE *DefaultTitle;		/* for Windows without ScreenTitle */

    /* Bar sizes for this Screen and all Window's in this Screen */
    /* Note that BarHeight is one less than the actual menu bar
     * height.	We're going to keep this in V36 for compatibility,
     * although V36 artwork might use that extra pixel
     *
     * Also, the title bar height of a window is calculated from the
     * screen's WBorTop field, plus the font height, plus one.
     */
    BYTE BarHeight, BarVBorder, BarHBorder, MenuVBorder, MenuHBorder;
    BYTE WBorTop, WBorLeft, WBorRight, WBorBottom;

    struct TextAttr *Font;		/* this screen's default font	   */

    /* the display data structures for this Screen */
    struct ViewPort ViewPort;		/* describing the Screen's display */
    struct RastPort RastPort;		/* describing Screen rendering	   */
    struct BitMap BitMap;		/* SEE WARNING ABOVE!		   */
    struct Layer_Info LayerInfo;	/* each screen gets a LayerInfo    */

    /* Only system gadgets may be attached to a screen.
     *	You get the standard system Screen Gadgets automatically
     */
    struct Gadget *FirstGadget;

    UBYTE DetailPen, BlockPen;		/* for bar/border/gadget rendering */

    /* the following variable(s) are maintained by Intuition to support the
     * DisplayBeep() color flashing technique
     */
    UWORD SaveColor0;

    /* This layer is for the Screen and Menu bars */
    struct Layer *BarLayer;

    UBYTE *ExtData;

    UBYTE *UserData;	/* general-purpose pointer to User data extension */

    /**** Data below this point are SYSTEM PRIVATE ****/
};

/* --- FLAGS SET BY INTUITION --------------------------------------------- */
/* The SCREENTYPE bits are reserved for describing various Screen types
 * available under Intuition.
 */
#define SCREENTYPE	0x000F	/* all the screens types available	*/
/* --- the definitions for the Screen Type ------------------------------- */
#define WBENCHSCREEN	0x0001	/* identifies the Workbench screen	*/
#define PUBLICSCREEN	0x0002	/* public shared (custom) screen	*/
#define CUSTOMSCREEN	0x000F	/* original custom screens		*/

#define SHOWTITLE	0x0010	/* this gets set by a call to ShowTitle() */

#define BEEPING		0x0020	/* set when Screen is beeping (private)	*/

#define CUSTOMBITMAP	0x0040	/* if you are supplying your own BitMap */

#define SCREENBEHIND	0x0080	/* if you want your screen to open behind
                 * already open screens
                 */
#define SCREENQUIET	0x0100	/* if you do not want Intuition to render
                 * into your screen (gadgets, title)
                 */
#define SCREENHIRES	0x0200	/* do not use lowres gadgets  (private)	*/

#define NS_EXTENDED	0x1000		/* ExtNewScreen.Extension is valid	*/
/* V36 applications can use OpenScreenTagList() instead of NS_EXTENDED	*/

#define AUTOSCROLL	0x4000	/* screen is to autoscoll		*/

/* New for V39: */
#define PENSHARED	0x0400	/* Screen opener set {SA_SharePens,TRUE} */

#define STDSCREENHEIGHT -1	/* supply in NewScreen.Height		*/
#define STDSCREENWIDTH -1	/* supply in NewScreen.Width		*/

/*
 * Screen attribute tag ID's.  These are used in the ti_Tag field of
 * TagItem arrays passed to OpenScreenTagList() (or in the
 * ExtNewScreen.Extension field).
 */

/* Screen attribute tags.  Please use these versions, not those in
 * iobsolete.h.
 */

#define SA_Dummy	(TAG_USER + 32)
/*
 * these items specify items equivalent to fields in NewScreen
 */
#define SA_Left		(SA_Dummy + 0x0001)
#define SA_Top		(SA_Dummy + 0x0002)
#define SA_Width	(SA_Dummy + 0x0003)
#define SA_Height	(SA_Dummy + 0x0004)
            /* traditional screen positions	and dimensions	*/
#define SA_Depth	(SA_Dummy + 0x0005)
            /* screen bitmap depth				*/
#define SA_DetailPen	(SA_Dummy + 0x0006)
            /* serves as default for windows, too		*/
#define SA_BlockPen	(SA_Dummy + 0x0007)
#define SA_Title	(SA_Dummy + 0x0008)
            /* default screen title				*/
#define SA_Colors	(SA_Dummy + 0x0009)
            /* ti_Data is an array of struct ColorSpec,
             * terminated by ColorIndex = -1.  Specifies
             * initial screen palette colors.
             * Also see SA_Colors32 for use under V39.
             */
#define SA_ErrorCode	(SA_Dummy + 0x000A)
            /* ti_Data points to LONG error code (values below)*/
#define SA_Font		(SA_Dummy + 0x000B)
            /* equiv. to NewScreen.Font			*/
#define SA_SysFont	(SA_Dummy + 0x000C)
            /* Selects one of the preferences system fonts:
             *	0 - old DefaultFont, fixed-width
             *	1 - WB Screen preferred font
             */
#define SA_Type		(SA_Dummy + 0x000D)
            /* ti_Data is PUBLICSCREEN or CUSTOMSCREEN.  For other
             * fields of NewScreen.Type, see individual tags,
             * eg. SA_Behind, SA_Quiet.
             */
#define SA_BitMap	(SA_Dummy + 0x000E)
            /* ti_Data is pointer to custom BitMap.  This
             * implies type of CUSTOMBITMAP
             */
#define SA_PubName	(SA_Dummy + 0x000F)
            /* presence of this tag means that the screen
             * is to be a public screen.  Please specify
             * BEFORE the two tags below
             */
#define SA_PubSig	(SA_Dummy + 0x0010)
#define SA_PubTask	(SA_Dummy + 0x0011)
            /* Task ID and signal for being notified that
             * the last window has closed on a public screen.
             */
#define SA_DisplayID	(SA_Dummy + 0x0012)
            /* ti_Data is new extended display ID from
             * <graphics/displayinfo.h> (V37) or from
             * <graphics/modeid.h> (V39 and up)
             */
#define SA_DClip	(SA_Dummy + 0x0013)
            /* ti_Data points to a rectangle which defines
             * screen display clip region
             */
#define SA_Overscan	(SA_Dummy + 0x0014)
            /* Set to one of the OSCAN_
             * specifiers below to get a system standard
             * overscan region for your display clip,
             * screen dimensions (unless otherwise specified),
             * and automatically centered position (partial
             * support only so far).
             * If you use this, you shouldn't specify
             * SA_DClip.  SA_Overscan is for "standard"
             * overscan dimensions, SA_DClip is for
             * your custom numeric specifications.
             */
#define SA_Obsolete1	(SA_Dummy + 0x0015)
            /* obsolete S_MONITORNAME			*/

/** booleans **/
#define SA_ShowTitle	(SA_Dummy + 0x0016)
            /* boolean equivalent to flag SHOWTITLE		*/
#define SA_Behind	(SA_Dummy + 0x0017)
            /* boolean equivalent to flag SCREENBEHIND	*/
#define SA_Quiet	(SA_Dummy + 0x0018)
            /* boolean equivalent to flag SCREENQUIET	*/
#define SA_AutoScroll	(SA_Dummy + 0x0019)
            /* boolean equivalent to flag AUTOSCROLL	*/
#define SA_Pens		(SA_Dummy + 0x001A)
            /* pointer to ~0 terminated UWORD array, as
             * found in struct DrawInfo
             */
#define SA_FullPalette	(SA_Dummy + 0x001B)
            /* boolean: initialize color table to entire
             *  preferences palette (32 for V36), rather
             * than compatible pens 0-3, 17-19, with
             * remaining palette as returned by GetColorMap()
             */

#define SA_ColorMapEntries (SA_Dummy + 0x001C)
            /* New for V39:
             * Allows you to override the number of entries
             * in the ColorMap for your screen.  Intuition
             * normally allocates (1<<depth) or 32, whichever
             * is more, but you may require even more if you
             * use certain V39 graphics.library features
             * (eg. palette-banking).
             */

#define SA_Parent	(SA_Dummy + 0x001D)
            /* New for V39:
             * ti_Data is a pointer to a "parent" screen to
             * attach this one to.	Attached screens slide
             * and depth-arrange together.
             */

#define SA_Draggable	(SA_Dummy + 0x001E)
            /* New for V39:
             * Boolean tag allowing non-draggable screens.
             * Do not use without good reason!
             * (Defaults to TRUE).
             */

#define SA_Exclusive	(SA_Dummy + 0x001F)
            /* New for V39:
             * Boolean tag allowing screens that won't share
             * the display.  Use sparingly!  Starting with 3.01,
             * attached screens may be SA_Exclusive.  Setting
             * SA_Exclusive for each screen will produce an
             * exclusive family.   (Defaults to FALSE).
             */

#define SA_SharePens	(SA_Dummy + 0x0020)
            /* New for V39:
             * For those pens in the screen's DrawInfo->dri_Pens,
             * Intuition obtains them in shared mode (see
             * graphics.library/ObtainPen()).  For compatibility,
             * Intuition obtains the other pens of a public
             * screen as PEN_EXCLUSIVE.  Screens that wish to
             * manage the pens themselves should generally set
             * this tag to TRUE.  This instructs Intuition to
             * leave the other pens unallocated.
             */

#define SA_BackFill	(SA_Dummy + 0x0021)
            /* New for V39:
             * provides a "backfill hook" for your screen's
             * Layer_Info.
             * See layers.library/InstallLayerInfoHook()
             */

#define SA_Interleaved	(SA_Dummy + 0x0022)
            /* New for V39:
             * Boolean tag requesting that the bitmap
             * allocated for you be interleaved.
             * (Defaults to FALSE).
             */

#define SA_Colors32	(SA_Dummy + 0x0023)
            /* New for V39:
             * Tag to set the screen's initial palette colors
             * at 32 bits-per-gun.	ti_Data is a pointer
             * to a table to be passed to the
             * graphics.library/LoadRGB32() function.
             * This format supports both runs of color
             * registers and sparse registers.  See the
             * autodoc for that function for full details.
             * Any color set here has precedence over
             * the same register set by SA_Colors.
             */

#define SA_VideoControl	(SA_Dummy + 0x0024)
            /* New for V39:
             * ti_Data is a pointer to a taglist that Intuition
             * will pass to graphics.library/VideoControl(),
             * upon opening the screen.
             */

#define SA_FrontChild	(SA_Dummy + 0x0025)
            /* New for V39:
             * ti_Data is a pointer to an already open screen
             * that is to be the child of the screen being
             * opened.  The child screen will be moved to the
             * front of its family.
             */

#define SA_BackChild	(SA_Dummy + 0x0026)
            /* New for V39:
             * ti_Data is a pointer to an already open screen
             * that is to be the child of the screen being
             * opened.  The child screen will be moved to the
             * back of its family.
             */

#define SA_LikeWorkbench	(SA_Dummy + 0x0027)
            /* New for V39:
             * Set ti_Data to 1 to request a screen which
             * is just like the Workbench.	This gives
             * you the same screen mode, depth, size,
             * colors, etc., as the Workbench screen.
             */

#define SA_Reserved		(SA_Dummy + 0x0028)
            /* Reserved for private Intuition use */

#define SA_MinimizeISG		(SA_Dummy + 0x0029)
            /* New for V40:
             * For compatibility, Intuition always ensures
             * that the inter-screen gap is at least three
             * non-interlaced lines.  If your application
             * would look best with the smallest possible
             * inter-screen gap, set ti_Data to TRUE.
             * If you use the new graphics VideoControl()
             * VC_NoColorPaletteLoad tag for your screen's
             * ViewPort, you should also set this tag.
             */

/* this is an obsolete tag included only for compatibility with V35
 * interim release for the A2024 and Viking monitors
 */
#ifndef NSTAG_EXT_VPMODE
#define NSTAG_EXT_VPMODE (TAG_USER | 1)
#endif

/* OpenScreen error codes, which are returned in the (optional) LONG
 * pointed to by ti_Data for the SA_ErrorCode tag item
 */
#define OSERR_NOMONITOR	   (1)	/* named monitor spec not available	*/
#define OSERR_NOCHIPS	   (2)	/* you need newer custom chips		*/
#define OSERR_NOMEM	   (3)	/* couldn't get normal memory		*/
#define OSERR_NOCHIPMEM	   (4)	/* couldn't get chipmem			*/
#define OSERR_PUBNOTUNIQUE (5)	/* public screen name already used	*/
#define OSERR_UNKNOWNMODE  (6)	/* don't recognize mode asked for	*/
#define OSERR_TOODEEP	   (7)	/* Screen deeper than HW supports	*/
#define OSERR_ATTACHFAIL   (8)	/* Failed to attach screens		*/
#define OSERR_NOTAVAILABLE (9)	/* Mode not available for other reason	*/

/* ======================================================================== */
/* === NewScreen ========================================================== */
/* ======================================================================== */
/* note: to use the Extended field, you must use the
 * new ExtNewScreen structure, below
 */
struct NewScreen
{
    WORD LeftEdge, TopEdge, Width, Height, Depth;  /* screen dimensions */

    UBYTE DetailPen, BlockPen;	/* for bar/border/gadget rendering	*/

    UWORD ViewModes;		/* the Modes for the ViewPort (and View) */

    UWORD Type;			/* the Screen type (see defines above)	*/

    struct TextAttr *Font;	/* this Screen's default text attributes */

    UBYTE *DefaultTitle;	/* the default title for this Screen	*/

    struct Gadget *Gadgets;	/* UNUSED:  Leave this NULL		*/

    /* if you are opening a CUSTOMSCREEN and already have a BitMap
     * that you want used for your Screen, you set the flags CUSTOMBITMAP in
     * the Type field and you set this variable to point to your BitMap
     * structure.  The structure will be copied into your Screen structure,
     * after which you may discard your own BitMap if you want
     */
    struct BitMap *CustomBitMap;
};

/*
 * For compatibility reasons, we need a new structure for extending
 * NewScreen.  Use this structure is you need to use the new Extension
 * field.
 *
 * NOTE: V36-specific applications should use the
 * OpenScreenTagList( newscreen, tags ) version of OpenScreen().
 * Applications that want to be V34-compatible as well may safely use the
 * ExtNewScreen structure.  Its tags will be ignored by V34 Intuition.
 *
 */
struct ExtNewScreen
{
    WORD LeftEdge, TopEdge, Width, Height, Depth;
    UBYTE DetailPen, BlockPen;
    UWORD ViewModes;
    UWORD Type;
    struct TextAttr *Font;
    UBYTE *DefaultTitle;
    struct Gadget *Gadgets;
    struct BitMap *CustomBitMap;

    struct TagItem	*Extension;
                /* more specification data, scanned if
                 * NS_EXTENDED is set in NewScreen.Type
                 */
};

/* === Overscan Types ===	*/
#define OSCAN_TEXT	(1)	/* entirely visible	*/
#define OSCAN_STANDARD	(2)	/* just past edges	*/
#define OSCAN_MAX	(3)	/* as much as possible	*/
#define OSCAN_VIDEO	(4)	/* even more than is possible	*/

/* === Public Shared Screen Node ===	*/

/* This is the representative of a public shared screen.
 * This is an internal data structure, but some functions may
 * present a copy of it to the calling application.  In that case,
 * be aware that the screen pointer of the structure can NOT be
 * used safely, since there is no guarantee that the referenced
 * screen will remain open and a valid data structure.
 *
 * Never change one of these.
 */

struct PubScreenNode	{
    struct Node		psn_Node;	/* ln_Name is screen name */
    struct Screen	*psn_Screen;
    UWORD		psn_Flags;	/* below		*/
    WORD		psn_Size;	/* includes name buffer	*/
    WORD		psn_VisitorCount; /* how many visitor windows */
    struct Task		*psn_SigTask;	/* who to signal when visitors gone */
    UBYTE		psn_SigBit;	/* which signal	*/
};

#define PSNF_PRIVATE	(0x0001)

/* NOTE: Due to a bug in NextPubScreen(), make sure your buffer
 * actually has MAXPUBSCREENNAME+1 characters in it!
 */
#define MAXPUBSCREENNAME	(139)	/* names no longer, please	*/

/* pub screen modes	*/
#define SHANGHAI	0x0001	/* put workbench windows on pub screen */
#define POPPUBSCREEN	0x0002	/* pop pub screen to front when visitor opens */

/* New for V39:  Intuition has new screen depth-arrangement and movement
 * functions called ScreenDepth() and ScreenPosition() respectively.
 * These functions permit the old behavior of ScreenToFront(),
 * ScreenToBack(), and MoveScreen().  ScreenDepth() also allows
 * independent depth control of attached screens.  ScreenPosition()
 * optionally allows positioning screens even though they were opened
 * {SA_Draggable,FALSE}.
 */

/* For ScreenDepth(), specify one of SDEPTH_TOFRONT or SDEPTH_TOBACK,
 * and optionally also SDEPTH_INFAMILY.
 *
 * NOTE: ONLY THE OWNER OF THE SCREEN should ever specify
 * SDEPTH_INFAMILY.  Commodities, "input helper" programs,
 * or any other program that did not open a screen should never
 * use that flag.  (Note that this is a style-behavior
 * requirement;  there is no technical requirement that the
 * task calling this function need be the task which opened
 * the screen).
 */

#define	SDEPTH_TOFRONT			(0)	/* Bring screen to front */
#define SDEPTH_TOBACK		(1)	/* Send screen to back */
#define SDEPTH_INFAMILY		(2)	/* Move an attached screen with
                     * respect to other screens of
                     * its family
                     */

/* Here's an obsolete name equivalent to SDEPTH_INFAMILY: */
#define SDEPTH_CHILDONLY	SDEPTH_INFAMILY

/* For ScreenPosition(), specify one of SPOS_RELATIVE, SPOS_ABSOLUTE,
 * or SPOS_MAKEVISIBLE to describe the kind of screen positioning you
 * wish to perform:
 *
 * SPOS_RELATIVE: The x1 and y1 parameters to ScreenPosition() describe
 *	the offset in coordinates you wish to move the screen by.
 * SPOS_ABSOLUTE: The x1 and y1 parameters to ScreenPosition() describe
 *	the absolute coordinates you wish to move the screen to.
 * SPOS_MAKEVISIBLE: (x1,y1)-(x2,y2) describes a rectangle on the
 *	screen which you would like autoscrolled into view.
 *
 * You may additionally set SPOS_FORCEDRAG along with any of the
 * above.  Set this if you wish to reposition an {SA_Draggable,FALSE}
 * screen that you opened.
 *
 * NOTE: ONLY THE OWNER OF THE SCREEN should ever specify
 * SPOS_FORCEDRAG.  Commodities, "input helper" programs,
 * or any other program that did not open a screen should never
 * use that flag.
 */

#define SPOS_RELATIVE		(0)	/* Coordinates are relative */

#define SPOS_ABSOLUTE		(1)	/* Coordinates are expressed as
                     * absolutes, not relatives.
                     */

#define SPOS_MAKEVISIBLE	(2)	/* Coordinates describe a box on
                     * the screen you wish to be
                     * made visible by autoscrolling
                     */

#define SPOS_FORCEDRAG		(4)	/* Move non-draggable screen */

/* New for V39: Intuition supports double-buffering in screens,
 * with friendly interaction with menus and certain gadgets.
 * For each buffer, you need to get one of these structures
 * from the AllocScreenBuffer() call.  Never allocate your
 * own ScreenBuffer structures!
 *
 * The sb_DBufInfo field is for your use.  See the graphics.library
 * AllocDBufInfo() autodoc for details.
 */
struct ScreenBuffer
{
    struct BitMap *sb_BitMap;		/* BitMap of this buffer */
    struct DBufInfo *sb_DBufInfo;	/* DBufInfo for this buffer */
};

/* These are the flags that may be passed to AllocScreenBuffer().
 */
#define SB_SCREEN_BITMAP	1
#define SB_COPY_BITMAP		2

/* Include obsolete identifiers: */
#ifndef INTUITION_IOBSOLETE_H
#include <intuition/iobsolete.h>
#endif

#endif


include/images/drawlist.h

#ifndef IMAGES_DRAWLIST_H
#define IMAGES_DRAWLIST_H
/*
**	$VER: drawlist.h 44.1 (19.10.1999)
**	Includes Release 44.1
**
**  Definitions for the drawlist.image BOOPSI class
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

/*****************************************************************************/

#ifndef REACTRION_REACTION_H
#include <reaction/reaction.h>
#endif

#ifndef INTUITION_IMAGECLASS_H
#include <intuition/imageclass.h>
#endif

/*****************************************************************************/

#define DRAWLIST_Dummy		(REACTION_Dummy + 0x17000)

#define DRAWLIST_Directives	(DRAWLIST_Dummy+1)
    /* (struct DrawList *) Pointer to drawlist directive array. */

#define DRAWLIST_RefHeight	(DRAWLIST_Dummy+2)
    /* (WORD) Reference height of drawlist. */

#define DRAWLIST_RefWidth	(DRAWLIST_Dummy+3)
    /* (WORD) Reference width of drawlist. */

#define DRAWLIST_DrawInfo	(DRAWLIST_Dummy+4)
    /* Obsolete!! Do not use. */

/*****************************************************************************/

/* DrawList Primitive Directives
 */

#define DLST_END		0

#define DLST_LINE		1
#define DLST_RECT		2
#define DLST_FILL		3
#define DLST_ELLIPSE	4
#define DLST_CIRCLE		5
#define DLST_LINEPAT	6
#define DLST_FILLPAT	7
#define DLST_AMOVE		8
#define DLST_ADRAW		9
#define DLST_AFILL		10
#define DLST_BEVELBOX	11
#define DLST_ARC		12
#define DLST_START		13
#define DLST_BOUNDS		13
#define DLST_LINESIZE	14

/*****************************************************************************/

/* Pass an array of these via DRAWLIST_Directives.
 * Last entry must be DLST_END!
 */

struct DrawList
{
    WORD dl_Directive;
    UWORD dl_X1, dl_Y1;
    UWORD dl_X2, dl_Y2;
    WORD dl_Pen;
};

#endif /* IMAGES_DRAWLIST_H */


include/devices/trackdisk.h

#ifndef DEVICES_TRACKDISK_H
#define DEVICES_TRACKDISK_H

/*
**
**	$VER: trackdisk.h 33.13 (28.11.1990)
**	Includes Release 44.1
**
**	trackdisk device structure and value definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
**
*/

#ifndef EXEC_IO_H
#include <exec/io.h>
#endif

#ifndef EXEC_DEVICES_H
#include <exec/devices.h>
#endif

/*
 *--------------------------------------------------------------------
 *
 * Physical drive constants
 *
 *--------------------------------------------------------------------
 */

/* OBSOLETE -- use the TD_GETNUMTRACKS command! */
/*#define	NUMCYLS	80*/		/*  normal # of cylinders */
/*#define	MAXCYLS	(NUMCYLS+20)*/	/* max # cyls to look for during cal */
/*#define	NUMHEADS 2*/
/*#define	NUMTRACKS (NUMCYLS*NUMHEADS)*/

#define	NUMSECS	11
#define NUMUNITS 4

/*
 *--------------------------------------------------------------------
 *
 * Useful constants
 *
 *--------------------------------------------------------------------
 */

/*-- sizes before mfm encoding */
#define	TD_SECTOR 512
#define	TD_SECSHIFT 9		/* log TD_SECTOR */

/*
 *--------------------------------------------------------------------
 *
 * Driver Specific Commands
 *
 *--------------------------------------------------------------------
 */

/*
 *-- TD_NAME is a generic macro to get the name of the driver.	This
 *-- way if the name is ever changed you will pick up the change
 *-- automatically.
 *--
 *-- Normal usage would be:
 *--
 *-- char internalName[] = TD_NAME;
 *--
 */

#define	TD_NAME	"trackdisk.device"

#define	TDF_EXTCOM (1<<15)		/* for internal use only! */

#define	TD_MOTOR	(CMD_NONSTD+0)	/* control the disk's motor */
#define	TD_SEEK		(CMD_NONSTD+1)	/* explicit seek (for testing) */
#define	TD_FORMAT	(CMD_NONSTD+2)	/* format disk */
#define	TD_REMOVE	(CMD_NONSTD+3)	/* notify when disk changes */
#define	TD_CHANGENUM	(CMD_NONSTD+4)	/* number of disk changes */
#define	TD_CHANGESTATE	(CMD_NONSTD+5)	/* is there a disk in the drive? */
#define	TD_PROTSTATUS	(CMD_NONSTD+6)	/* is the disk write protected? */
#define	TD_RAWREAD	(CMD_NONSTD+7)	/* read raw bits from the disk */
#define	TD_RAWWRITE	(CMD_NONSTD+8)	/* write raw bits to the disk */
#define	TD_GETDRIVETYPE	(CMD_NONSTD+9)	/* get the type of the disk drive */
#define	TD_GETNUMTRACKS	(CMD_NONSTD+10)	/* # of tracks for this type drive */
#define	TD_ADDCHANGEINT	(CMD_NONSTD+11)	/* TD_REMOVE done right */
#define	TD_REMCHANGEINT	(CMD_NONSTD+12)	/* remove softint set by ADDCHANGEINT */
#define TD_GETGEOMETRY	(CMD_NONSTD+13) /* gets the disk geometry table */
#define TD_EJECT	(CMD_NONSTD+14) /* for those drives that support it */
#define	TD_LASTCOMM	(CMD_NONSTD+15)

/*
 *
 * The disk driver has an "extended command" facility.	These commands
 * take a superset of the normal IO Request block.
 *
 */

#define	ETD_WRITE	(CMD_WRITE|TDF_EXTCOM)
#define	ETD_READ	(CMD_READ|TDF_EXTCOM)
#define	ETD_MOTOR	(TD_MOTOR|TDF_EXTCOM)
#define	ETD_SEEK	(TD_SEEK|TDF_EXTCOM)
#define	ETD_FORMAT	(TD_FORMAT|TDF_EXTCOM)
#define	ETD_UPDATE	(CMD_UPDATE|TDF_EXTCOM)
#define	ETD_CLEAR	(CMD_CLEAR|TDF_EXTCOM)
#define	ETD_RAWREAD	(TD_RAWREAD|TDF_EXTCOM)
#define	ETD_RAWWRITE	(TD_RAWWRITE|TDF_EXTCOM)

/*
 *
 * extended IO has a larger than normal io request block.
 *
 */

struct IOExtTD {
    struct	IOStdReq iotd_Req;
    ULONG	iotd_Count;
    ULONG	iotd_SecLabel;
};

/*
 *  This is the structure returned by TD_DRIVEGEOMETRY
 *  Note that the layout can be defined three ways:
 *
 *  1. TotalSectors
 *  2. Cylinders and CylSectors
 *  3. Cylinders, Heads, and TrackSectors.
 *
 *  #1 is most accurate, #2 is less so, and #3 is least accurate.  All
 *  are usable, though #2 and #3 may waste some portion of the available
 *  space on some drives.
 */
struct DriveGeometry {
    ULONG	dg_SectorSize;		/* in bytes */
    ULONG	dg_TotalSectors;	/* total # of sectors on drive */
    ULONG	dg_Cylinders;		/* number of cylinders */
    ULONG	dg_CylSectors;		/* number of sectors/cylinder */
    ULONG	dg_Heads;		/* number of surfaces */
    ULONG	dg_TrackSectors;	/* number of sectors/track */
    ULONG	dg_BufMemType;		/* preferred buffer memory type */
                    /* (usually MEMF_PUBLIC) */
    UBYTE	dg_DeviceType;		/* codes as defined in the SCSI-2 spec*/
    UBYTE	dg_Flags;		/* flags, including removable */
    UWORD	dg_Reserved;
};

/* device types */
#define DG_DIRECT_ACCESS	0
#define DG_SEQUENTIAL_ACCESS	1
#define DG_PRINTER		2
#define DG_PROCESSOR		3
#define DG_WORM			4
#define DG_CDROM		5
#define DG_SCANNER		6
#define DG_OPTICAL_DISK		7
#define DG_MEDIUM_CHANGER	8
#define DG_COMMUNICATION	9
#define DG_UNKNOWN		31

/* flags */
#define DGB_REMOVABLE		0
#define DGF_REMOVABLE		1

/*
** raw read and write can be synced with the index pulse.  This flag
** in io request's IO_FLAGS field tells the driver that you want this.
*/

#define IOTDB_INDEXSYNC	4
#define IOTDF_INDEXSYNC (1<<4)
/*
** raw read and write can be synced with a $4489 sync pattern.	This flag
** in io request's IO_FLAGS field tells the driver that you want this.
*/
#define IOTDB_WORDSYNC	5
#define IOTDF_WORDSYNC (1<<5)

/* labels are TD_LABELSIZE bytes per sector */

#define	TD_LABELSIZE 16

/*
** This is a bit in the FLAGS field of OpenDevice.  If it is set, then
** the driver will allow you to open all the disks that the trackdisk
** driver understands.	Otherwise only 3.5" disks will succeed.
*/

#define TDB_ALLOW_NON_3_5	0
#define TDF_ALLOW_NON_3_5	(1<<0)

/*
**  If you set the TDB_ALLOW_NON_3_5 bit in OpenDevice, then you don't
**  know what type of disk you really got.  These defines are for the
**  TD_GETDRIVETYPE command.  In addition, you can find out how many
**  tracks are supported via the TD_GETNUMTRACKS command.
*/

#define	DRIVE3_5	1
#define	DRIVE5_25	2
#define	DRIVE3_5_150RPM	3

/*
 *--------------------------------------------------------------------
 *
 * Driver error defines
 *
 *--------------------------------------------------------------------
 */

#define	TDERR_NotSpecified	20	/* general catchall */
#define	TDERR_NoSecHdr		21	/* couldn't even find a sector */
#define	TDERR_BadSecPreamble	22	/* sector looked wrong */
#define	TDERR_BadSecID		23	/* ditto */
#define	TDERR_BadHdrSum		24	/* header had incorrect checksum */
#define	TDERR_BadSecSum		25	/* data had incorrect checksum */
#define	TDERR_TooFewSecs	26	/* couldn't find enough sectors */
#define	TDERR_BadSecHdr		27	/* another "sector looked wrong" */
#define	TDERR_WriteProt		28	/* can't write to a protected disk */
#define	TDERR_DiskChanged	29	/* no disk in the drive */
#define	TDERR_SeekError		30	/* couldn't find track 0 */
#define	TDERR_NoMem		31	/* ran out of memory */
#define	TDERR_BadUnitNum	32	/* asked for a unit > NUMUNITS */
#define	TDERR_BadDriveType	33	/* not a drive that trackdisk groks */
#define	TDERR_DriveInUse	34	/* someone else allocated the drive */
#define	TDERR_PostReset		35	/* user hit reset; awaiting doom */

/*
 *--------------------------------------------------------------------
 *
 * public portion of the unit structure
 *
 *--------------------------------------------------------------------
 */

struct TDU_PublicUnit {
    struct	Unit tdu_Unit;		/* base message port */
    UWORD	tdu_Comp01Track;	/* track for first precomp */
    UWORD	tdu_Comp10Track;	/* track for second precomp */
    UWORD	tdu_Comp11Track;	/* track for third precomp */
    ULONG	tdu_StepDelay;		/* time to wait after stepping */
    ULONG	tdu_SettleDelay;	/* time to wait after seeking */
    UBYTE	tdu_RetryCnt;		/* # of times to retry */
    UBYTE	tdu_PubFlags;		/* public flags, see below */
    UWORD	tdu_CurrTrk;		/* track the heads are over... */
                    /* ONLY ACCESS WHILE UNIT IS STOPPED! */
    ULONG	tdu_CalibrateDelay;	/* time to wait after stepping */
                    /* during a recalibrate */
    ULONG	tdu_Counter;		/* counter for disk changes... */
                    /* ONLY ACCESS WHILE UNIT IS STOPPED! */
};

/* flags for tdu_PubFlags */
#define TDPB_NOCLICK	0
#define TDPF_NOCLICK	(1L << 0)

#endif	/* DEVICES_TRACKDISK_H */


include/devices/printer.h

#ifndef DEVICES_PRINTER_H
#define DEVICES_PRINTER_H
/*
**	$VER: printer.h 44.1 (19.10.1999)
**	Includes Release 44.1
**
**	printer.device structure definitions
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_DEVICES_H
#include <exec/devices.h>
#endif

#ifndef INTUITION_INTUITION_H
#include <intuition/intuition.h>
#endif

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

/****************************************************************************/

/* V34-V40 commands */
#define PRD_RAWWRITE		(CMD_NONSTD+0)
#define PRD_PRTCOMMAND		(CMD_NONSTD+1)
#define PRD_DUMPRPORT		(CMD_NONSTD+2)
#define PRD_QUERY		(CMD_NONSTD+3)

/* V44 commands */
#define PRD_RESETPREFS		(CMD_NONSTD+4)	/* PRIVATE: do not use! */
#define PRD_LOADPREFS		(CMD_NONSTD+5)	/* PRIVATE: do not use! */
#define PRD_USEPREFS		(CMD_NONSTD+6)	/* PRIVATE: do not use! */
#define PRD_SAVEPREFS		(CMD_NONSTD+7)	/* PRIVATE: do not use! */
#define PRD_READPREFS		(CMD_NONSTD+8)
#define PRD_WRITEPREFS		(CMD_NONSTD+9)
#define PRD_EDITPREFS		(CMD_NONSTD+10)
#define PRD_SETERRHOOK		(CMD_NONSTD+11)
#define PRD_DUMPRPORTTAGS	(CMD_NONSTD+12)

/****************************************************************************/

/* printer command definitions */

#define aRIS	0	/* ESCc  reset                    ISO */
#define aRIN	1	/* ESC#1 initialize               +++ */
#define aIND	2	/* ESCD  lf                       ISO */
#define aNEL	3	/* ESCE  return,lf                ISO */
#define aRI	4	/* ESCM  reverse lf               ISO */

#define aSGR0	5	/* ESC[0m normal char set         ISO */
#define aSGR3	6	/* ESC[3m italics on              ISO */
#define aSGR23	7	/* ESC[23m italics off            ISO */
#define aSGR4	8	/* ESC[4m underline on            ISO */
#define aSGR24	9	/* ESC[24m underline off          ISO */
#define aSGR1	10	/* ESC[1m boldface on             ISO */
#define aSGR22	11	/* ESC[22m boldface off           ISO */
#define aSFC	12	/* SGR30-39  set foreground color ISO */
#define aSBC	13	/* SGR40-49  set background color ISO */

#define aSHORP0	14	/* ESC[0w normal pitch            DEC */
#define aSHORP2	15	/* ESC[2w elite on                DEC */
#define aSHORP1	16	/* ESC[1w elite off               DEC */
#define aSHORP4	17	/* ESC[4w condensed fine on       DEC */
#define aSHORP3	18	/* ESC[3w condensed off           DEC */
#define aSHORP6	19	/* ESC[6w enlarged on             DEC */
#define aSHORP5	20	/* ESC[5w enlarged off            DEC */

#define aDEN6	21	/* ESC[6"z shadow print on        DEC (sort of) */
#define aDEN5	22	/* ESC[5"z shadow print off       DEC */
#define aDEN4	23	/* ESC[4"z doublestrike on        DEC */
#define aDEN3	24	/* ESC[3"z doublestrike off       DEC */
#define aDEN2	25	/* ESC[2"z  NLQ on                DEC */
#define aDEN1	26	/* ESC[1"z  NLQ off               DEC */

#define aSUS2	27	/* ESC[2v superscript on          +++ */
#define aSUS1	28	/* ESC[1v superscript off         +++ */
#define aSUS4	29	/* ESC[4v subscript on            +++ */
#define aSUS3	30	/* ESC[3v subscript off           +++ */
#define aSUS0	31	/* ESC[0v normalize the line      +++ */
#define aPLU	32	/* ESCL  partial line up          ISO */
#define aPLD	33	/* ESCK  partial line down        ISO */

#define aFNT0	34	/* ESC(B US char set        or Typeface  0 (default) */
#define aFNT1	35	/* ESC(R French char set    or Typeface  1 */
#define aFNT2	36	/* ESC(K German char set    or Typeface  2 */
#define aFNT3	37	/* ESC(A UK char set        or Typeface  3 */
#define aFNT4	38	/* ESC(E Danish I char set  or Typeface  4 */
#define aFNT5	39	/* ESC(H Sweden char set    or Typeface  5 */
#define aFNT6	40	/* ESC(Y Italian char set   or Typeface  6 */
#define aFNT7	41	/* ESC(Z Spanish char set   or Typeface  7 */
#define aFNT8	42	/* ESC(J Japanese char set  or Typeface  8 */
#define aFNT9	43	/* ESC(6 Norweign char set  or Typeface  9 */
#define aFNT10	44	/* ESC(C Danish II char set or Typeface 10 */

/*
    Suggested typefaces are:

     0 - default typeface.
     1 - Line Printer or equiv.
     2 - Pica or equiv.
     3 - Elite or equiv.
     4 - Helvetica or equiv.
     5 - Times Roman or equiv.
     6 - Gothic or equiv.
     7 - Script or equiv.
     8 - Prestige or equiv.
     9 - Caslon or equiv.
    10 - Orator or equiv.
*/

#define aPROP2	45	/* ESC[2p  proportional on        +++ */
#define aPROP1	46	/* ESC[1p  proportional off       +++ */
#define aPROP0	47	/* ESC[0p  proportional clear     +++ */
#define aTSS	48	/* ESC[n E set proportional offset ISO */
#define aJFY5	49	/* ESC[5 F auto left justify      ISO */
#define aJFY7	50	/* ESC[7 F auto right justify     ISO */
#define aJFY6	51	/* ESC[6 F auto full justify      ISO */
#define aJFY0	52	/* ESC[0 F auto justify off       ISO */
#define aJFY3	53	/* ESC[3 F letter space (justify) ISO (special) */
#define aJFY1	54	/* ESC[1 F word fill(auto center) ISO (special) */

#define aVERP0	55	/* ESC[0z  1/8" line spacing      +++ */
#define aVERP1	56	/* ESC[1z  1/6" line spacing      +++ */
#define aSLPP	57	/* ESC[nt  set form length n      DEC */
#define aPERF	58	/* ESC[nq  perf skip n (n>0)      +++ */
#define aPERF0	59	/* ESC[0q  perf skip off          +++ */

#define aLMS	60	/* ESC#9   Left margin set        +++ */
#define aRMS	61	/* ESC#0   Right margin set       +++ */
#define aTMS	62	/* ESC#8   Top margin set         +++ */
#define aBMS	63	/* ESC#2   Bottom marg set        +++ */
#define aSTBM	64	/* ESC[Pn1;Pn2r  T&B margins      DEC */
#define aSLRM	65	/* ESC[Pn1;Pn2s  L&R margin       DEC */
#define aCAM	66	/* ESC#3   Clear margins          +++ */

#define aHTS	67	/* ESCH    Set horiz tab          ISO */
#define aVTS	68	/* ESCJ    Set vertical tabs      ISO */
#define aTBC0	69	/* ESC[0g  Clr horiz tab          ISO */
#define aTBC3	70	/* ESC[3g  Clear all h tab        ISO */
#define aTBC1	71	/* ESC[1g  Clr vertical tabs      ISO */
#define aTBC4	72	/* ESC[4g  Clr all v tabs         ISO */
#define aTBCALL	73	/* ESC#4   Clr all h & v tabs     +++ */
#define aTBSALL	74	/* ESC#5   Set default tabs       +++ */
#define aEXTEND	75	/* ESC[Pn"x extended commands     +++ */

#define aRAW	76	/*	ESC[Pn"r	Next	'Pn' chars are raw +++ */

/****************************************************************************/

/* For PRD_PRTCOMMAND */
struct IOPrtCmdReq
{
    struct Message	io_Message;
    struct Device *	io_Device;	/* device node pointer  */
    struct Unit *	io_Unit;	/* unit (driver private)*/
    UWORD		io_Command;	/* device command */
    UBYTE		io_Flags;
    BYTE		io_Error;	/* error or warning num */
    UWORD		io_PrtCommand;	/* printer command */
    UBYTE		io_Parm0;	/* first command parameter */
    UBYTE		io_Parm1;	/* second command parameter */
    UBYTE		io_Parm2;	/* third command parameter */
    UBYTE		io_Parm3;	/* fourth command parameter */
};

/****************************************************************************/

/* For PRD_DUMPRPORT */
struct IODRPReq
{
    struct Message		io_Message;
    struct Device *		io_Device;	/* device node pointer  */
    struct Unit *		io_Unit;	/* unit (driver private)*/
    UWORD			io_Command;	/* device command */
    UBYTE			io_Flags;
    BYTE			io_Error;	/* error or warning num */
    struct RastPort *	io_RastPort;	/* raster port */
    struct ColorMap *	io_ColorMap;	/* color map */
    ULONG			io_Modes;	/* graphics viewport modes */
    UWORD			io_SrcX;	/* source x origin */
    UWORD			io_SrcY;	/* source y origin */
    UWORD			io_SrcWidth;	/* source x width */
    UWORD			io_SrcHeight;	/* source x height */
    LONG			io_DestCols;	/* destination x width */
    LONG			io_DestRows;	/* destination y height */
    UWORD			io_Special;	/* option flags */
};

/****************************************************************************/

/* For PRD_DUMPRPORTTAGS (V44) */
struct IODRPTagsReq
{
    struct Message		io_Message;
    struct Device *		io_Device;	/* device node pointer  */
    struct Unit *		io_Unit;	/* unit (driver private)*/
    UWORD			io_Command;	/* device command */
    UBYTE			io_Flags;
    BYTE			io_Error;	/* error or warning num */
    struct RastPort *	io_RastPort;	/* raster port */
    struct ColorMap *	io_ColorMap;	/* color map */
    ULONG			io_Modes;	/* graphics viewport modes */
    UWORD			io_SrcX;	/* source x origin */
    UWORD			io_SrcY;	/* source y origin */
    UWORD			io_SrcWidth;	/* source x width */
    UWORD			io_SrcHeight;	/* source x height */
    LONG			io_DestCols;	/* destination x width */
    LONG			io_DestRows;	/* destination y height */
    UWORD			io_Special;	/* option flags */
    struct TagItem *	io_TagList;	/* tag list with additional info */
};

/****************************************************************************/

#define SPECIAL_MILCOLS		0x0001	/* DestCols specified in 1/1000" */
#define SPECIAL_MILROWS		0x0002	/* DestRows specified in 1/1000" */
#define SPECIAL_FULLCOLS	0x0004	/* make DestCols maximum possible */
#define SPECIAL_FULLROWS	0x0008	/* make DestRows maximum possible */
#define SPECIAL_FRACCOLS	0x0010	/* DestCols is fraction of FULLCOLS */
#define SPECIAL_FRACROWS	0x0020	/* DestRows is fraction of FULLROWS */
#define SPECIAL_CENTER		0x0040	/* center image on paper */
#define SPECIAL_ASPECT		0x0080	/* ensure correct aspect ratio */
#define SPECIAL_DENSITY1	0x0100	/* lowest resolution (dpi) */
#define SPECIAL_DENSITY2	0x0200	/* next res */
#define SPECIAL_DENSITY3	0x0300	/* next res */
#define SPECIAL_DENSITY4	0x0400	/* next res */
#define SPECIAL_DENSITY5	0x0500	/* next res */
#define SPECIAL_DENSITY6	0x0600	/* next res */
#define SPECIAL_DENSITY7	0x0700	/* highest res */
#define SPECIAL_NOFORMFEED	0x0800	/* don't eject paper on gfx prints */
#define SPECIAL_TRUSTME		0x1000	/* don't reset on gfx prints */

/*
    Compute print size, set 'io_DestCols' and 'io_DestRows' in the calling
    program's 'IODRPReq' structure and exit, DON'T PRINT.  This allows the
    calling program to see what the final print size would be in printer
    pixels.  Note that it modifies the 'io_DestCols' and 'io_DestRows'
    fields of your 'IODRPReq' structure.  Also, set the print density and
    update the 'MaxXDots', 'MaxYDots', 'XDotsInch', and 'YDotsInch' fields
    of the 'PrinterExtendedData' structure.
*/
#define SPECIAL_NOPRINT		0x2000	/* see above */

/****************************************************************************/

#define PDERR_NOERR		0	/* clean exit, no errors */
#define PDERR_CANCEL		1	/* user cancelled print */
#define PDERR_NOTGRAPHICS	2	/* printer cannot output graphics */
#define PDERR_INVERTHAM		3	/* OBSOLETE */
#define PDERR_BADDIMENSION	4	/* print dimensions illegal */
#define PDERR_DIMENSIONOVFLOW	5	/* OBSOLETE */
#define PDERR_INTERNALMEMORY	6	/* no memory for internal variables */
#define PDERR_BUFFERMEMORY	7	/* no memory for print buffer */

/*
    Note : this is an internal error that can be returned from the render
    function to the printer device.  It is NEVER returned to the user.
    If the printer device sees this error it converts it 'PDERR_NOERR'
    and exits gracefully.  Refer to the document on
    'How to Write a Graphics Printer Driver' for more info.
*/
#define PDERR_TOOKCONTROL	8	/* Took control in case 0 of render */

#define PDERR_BADPREFERENCES	9	/* preferences file corrupt */

/*
    Note: all error codes < 32 are reserved for printer.device.
    All error codes >= 32 and < 127 are reserved for driver specific
    errors. Negative errors are reserved for system use (standard I/O
    errors) and error code 127 is reserved for future expansion.
*/
#define PDERR_LASTSTANDARD	31
#define PDERR_FIRSTCUSTOM	32
#define PDERR_LASTCUSTOM	126

/* internal use */
#define SPECIAL_DENSITYMASK	0x0700	/* masks out density values */
#define SPECIAL_DIMENSIONSMASK \
    (SPECIAL_MILCOLS|SPECIAL_MILROWS|SPECIAL_FULLCOLS|SPECIAL_FULLROWS\
    |SPECIAL_FRACCOLS|SPECIAL_FRACROWS|SPECIAL_ASPECT)

/****************************************************************************/

/* The following tags are used for PRD_DUMPRPORTTAGS */

#define DRPA_Dummy (TAG_USER + 0x60000)

/****************************************************************************/

/* The following tags are not implemented but reserved for future use. */

#define DRPA_ICCProfile		(DRPA_Dummy+1) /* APTR */
#define DRPA_ICCName		(DRPA_Dummy+2) /* STRPTR */
#define DRPA_NoColCorrect	(DRPA_Dummy+3) /* LBOOL */

/****************************************************************************/

/* If the following tag is used io_RastPort and io_ColorMap are
   ignored.
*/
#define DRPA_SourceHook   (DRPA_Dummy+4) /* struct Hook * */

/* The source hook (DRPA_SourceHook) is called with object NULL and
   message is a pointer to the following struct.

        VOID hook(struct Hook * hook,
                  APTR dummy,
                  struct DRPSourceMsg * drpm);
*/
struct DRPSourceMsg {
    LONG x;
    LONG y;
    LONG width;
    LONG height;
    ULONG *buf; /* fill this buffer with 0x00RRGGBB pixels */
};

/****************************************************************************/

/* If these tags are used io_Modes is ignored for aspect ratio */

#define DRPA_AspectX      (DRPA_Dummy+5) /* ULONG */
#define DRPA_AspectY      (DRPA_Dummy+6) /* ULONG */

/****************************************************************************/

/* The following tags are used for PRD_EDITPREFS */

#define PPRA_Dummy (TAG_USER + 0x70000)

/****************************************************************************/

/* Request to edit prefs (for PRD_EDITPREFS; V44) */

struct IOPrtPrefsReq
{
    struct Message		io_Message;
    struct Device *		io_Device;	/* device node pointer  */
    struct Unit *		io_Unit;	/* unit (driver private)*/
    UWORD			io_Command;	/* device command */
    UBYTE			io_Flags;
    BYTE			io_Error;	/* error or warning num */
    struct  TagItem *	io_TagList;	/* requester tag list */
};

#define PPRA_Window	(PPRA_Dummy+1) /* struct Window * */
#define PPRA_Screen	(PPRA_Dummy+2) /* struct Screen * */
#define PPRA_PubScreen	(PPRA_Dummy+3) /* STRPTR */

/****************************************************************************/

/* Request to set error hook (for PRD_SETERRHOOK; V44)*/

#define PDHOOK_NONE	((struct Hook *) NULL)
#define PDHOOK_STD	((struct Hook *) 1)

struct IOPrtErrReq
{
    struct Message	io_Message;
    struct Device *	io_Device;	/* device node pointer  */
    struct Unit *	io_Unit;	/* unit (driver private)*/
    UWORD		io_Command;	/* device command */
    UBYTE		io_Flags;
    BYTE		io_Error;	/* error or warning num */
    struct Hook *	io_Hook;
};

/****************************************************************************/

/*
    The error hook is called with the IORequest that caused the error as
    object (2nd Parameter) and a pointer to struct PrtErrMsg as message
    (3rd Parameter):

        VOID hook(struct Hook * hook,
                  struct printerIO * ior,
                  struct PrtErrMsg * pem);
*/
struct PrtErrMsg
{
    ULONG			pe_Version;	/* Version of this struct */
    ULONG			pe_ErrorLevel;	/* RETURN_WARN, RETURN_ERROR, RETURN_FAIL */
    struct Window *		pe_Window;	/* window for EasyRequest() */
    struct EasyStruct *	pe_ES;
    ULONG *			pe_IDCMP;
    APTR			pe_ArgList;
};

#define PDHOOK_VERSION 1

/****************************************************************************/

/* PRIVATE: Request to change prefs temporary. DO NOT USE! */

struct IOPrefsReq
{
    struct Message			io_Message;
    struct Device *			io_Device;	/* device node pointer  */
    struct Unit *			io_Unit;	/* unit (driver private)*/
    UWORD				io_Command;	/* device command */
    UBYTE				io_Flags;
    BYTE				io_Error;	/* error or warning num */
    struct PrinterTxtPrefs *	io_TxtPrefs;
    struct PrinterUnitPrefs *	io_UnitPrefs;
    struct PrinterDeviceUnitPrefs *	io_DevUnitPrefs;
    struct PrinterGfxPrefs *	io_GfxPrefs;
};

#endif /* DEVICES_PRINTER_H */


include/datatypes/datatypesclass.h

#ifndef	DATATYPES_DATATYPESCLASS_H
#define	DATATYPES_DATATYPESCLASS_H
/*
**  $VER: datatypesclass.h 44.1 (17.4.1999)
**  Includes Release 44.1
**
**  Interface definitions for DataType objects.
**
**  Copyright © 1992-1999 Amiga, Inc.
**	All Rights Reserved
*/

#ifndef	UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

#ifndef	DATATYPES_DATATYPES_H
#include <datatypes/datatypes.h>
#endif

#ifndef	INTUITION_INTUITION_H
#include <intuition/intuition.h>
#endif

#ifndef	DEVICES_PRINTER_H
#include <devices/printer.h>
#endif

#ifndef	DEVICES_PRTBASE_H
#include <devices/prtbase.h>
#endif

/*****************************************************************************/

#define	DATATYPESCLASS		"datatypesclass"

/*****************************************************************************/

#define	DTA_Dummy		(TAG_USER+0x1000)

/*****************************************************************************/

/* Generic attributes */

/* (struct TextAttr *) Pointer to the default TextAttr to use for
 * the text within the object.
 */
#define	DTA_TextAttr		(DTA_Dummy+10)

/* (LONG) Current top vertical unit */
#define	DTA_TopVert		(DTA_Dummy+11)

/* (LONG) Number of visible vertical units */
#define	DTA_VisibleVert		(DTA_Dummy+12)

/* (LONG) Total number of vertical units */
#define	DTA_TotalVert		(DTA_Dummy+13)

/* (LONG) Number of pixels per vertical unit */
#define	DTA_VertUnit		(DTA_Dummy+14)

/* (LONG) Current top horizontal unit */
#define	DTA_TopHoriz		(DTA_Dummy+15)

/* (LONG)  Number of visible horizontal units */
#define	DTA_VisibleHoriz	(DTA_Dummy+16)

/* (LONG) Total number of horizontal units */
#define	DTA_TotalHoriz		(DTA_Dummy+17)

/* (LONG) Number of pixels per horizontal unit */
#define	DTA_HorizUnit		(DTA_Dummy+18)

/* (UBYTE *) Name of the current element within the object. */
#define	DTA_NodeName		(DTA_Dummy+19)

/* (UBYTE *) Title of the object. */
#define	DTA_Title		(DTA_Dummy+20)

/* (struct DTMethod *) Pointer to a NULL terminated array of
 * supported trigger methods.
 */
#define	DTA_TriggerMethods	(DTA_Dummy+21)

/* (APTR) Object specific data. */
#define	DTA_Data		(DTA_Dummy+22)

/* (struct TextFont *) Default font to use for text within the
 * object.
 */
#define	DTA_TextFont		(DTA_Dummy+23)

/* (ULONG *) Pointer to a ~0 terminated array of supported
 * methods.
 */
#define	DTA_Methods		(DTA_Dummy+24)

/* (LONG) Printer error message.  Error numbers are defined in
 * <devices/printer.h>
 */
#define	DTA_PrinterStatus	(DTA_Dummy+25)

/* PRIVATE (struct Process *) Pointer to the print process. */
#define	DTA_PrinterProc		(DTA_Dummy+26)

/* PRIVATE (struct Process *) Pointer to the layout process. */
#define	DTA_LayoutProc		(DTA_Dummy+27)

/* Used to turn the applications' busy pointer off and on */
#define	DTA_Busy		(DTA_Dummy+28)

/* Used to indicate that new information has been loaded into
 * an object.  This is for models that cache the DTA_TopVert-
 * like tags
 */
#define	DTA_Sync		(DTA_Dummy+29)

/* The base name of the class */
#define	DTA_BaseName		(DTA_Dummy+30)

/* Group that the object must belong in */
#define	DTA_GroupID		(DTA_Dummy+31)

/* Error level */
#define	DTA_ErrorLevel		(DTA_Dummy+32)

/* datatypes.library error number */
#define	DTA_ErrorNumber		(DTA_Dummy+33)

/* Argument for datatypes.library error */
#define	DTA_ErrorString		(DTA_Dummy+34)

/* New for V40. (UBYTE *) specifies the name of the
 * realtime.library conductor.	Defaults to "Main".
 */
#define	DTA_Conductor		(DTA_Dummy+35)

/* New for V40. (BOOL) Indicate whether a control panel should be
 * embedded within the object (in the animation datatype, for
 * example).  Defaults to TRUE.
 */
#define	DTA_ControlPanel	(DTA_Dummy+36)

/* New for V40. (BOOL) Indicate whether the object should
 * immediately begin playing.  Defaults to FALSE.
 */
#define	DTA_Immediate		(DTA_Dummy+37)

/* New for V40. (BOOL) Indicate that the object should repeat
 * playing.  Defaults to FALSE.
 */
#define	DTA_Repeat		(DTA_Dummy+38)

/* New for V44. Address of a DTST_MEMORY source type
 * object (APTR).
 */
#define DTA_SourceAddress	(DTA_Dummy+39)

/* New for V44. Size of a DTST_MEMORY source type
 * object (ULONG).
 */
#define DTA_SourceSize		(DTA_Dummy+40)

/* Reserved tag; DO NOT USE (V44) */
#define DTA_Reserved		(DTA_Dummy+41)

/* DTObject attributes */
#define	DTA_Name		(DTA_Dummy+100)
#define	DTA_SourceType		(DTA_Dummy+101)
#define	DTA_Handle		(DTA_Dummy+102)
#define	DTA_DataType		(DTA_Dummy+103)
#define	DTA_Domain		(DTA_Dummy+104)

/* DON'T USE THE FOLLOWING FOUR TAGS.  USE THE CORRESPONDING TAGS IN
 * <intuition/gadgetclass.h> */
#define	DTA_Left		(DTA_Dummy+105)
#define	DTA_Top			(DTA_Dummy+106)
#define	DTA_Width		(DTA_Dummy+107)
#define	DTA_Height		(DTA_Dummy+108)

#define	DTA_ObjName		(DTA_Dummy+109)
#define	DTA_ObjAuthor		(DTA_Dummy+110)
#define	DTA_ObjAnnotation	(DTA_Dummy+111)
#define	DTA_ObjCopyright	(DTA_Dummy+112)
#define	DTA_ObjVersion		(DTA_Dummy+113)
#define	DTA_ObjectID		(DTA_Dummy+114)
#define	DTA_UserData		(DTA_Dummy+115)
#define	DTA_FrameInfo		(DTA_Dummy+116)

/* DON'T USE THE FOLLOWING FOUR TAGS.  USE THE CORRESPONDING TAGS IN
 * <intuition/gadgetclass.h> */
#define	DTA_RelRight		(DTA_Dummy+117)
#define	DTA_RelBottom		(DTA_Dummy+118)
#define	DTA_RelWidth		(DTA_Dummy+119)
#define	DTA_RelHeight		(DTA_Dummy+120)

#define	DTA_SelectDomain	(DTA_Dummy+121)
#define	DTA_TotalPVert		(DTA_Dummy+122)
#define	DTA_TotalPHoriz		(DTA_Dummy+123)
#define	DTA_NominalVert		(DTA_Dummy+124)
#define	DTA_NominalHoriz	(DTA_Dummy+125)

/* Printing attributes */

/* (LONG) Destination X width */
#define	DTA_DestCols		(DTA_Dummy+400)

/* (LONG) Destination Y height */
#define	DTA_DestRows		(DTA_Dummy+401)

/* (UWORD) Option flags */
#define	DTA_Special		(DTA_Dummy+402)

/* (struct RastPort *) RastPort to use when printing. (V40) */
#define	DTA_RastPort		(DTA_Dummy+403)

/* (STRPTR) Pointer to base name for ARexx port (V40) */
#define	DTA_ARexxPortName	(DTA_Dummy+404)

/*****************************************************************************/

#define	DTST_RAM		1
#define	DTST_FILE		2
#define	DTST_CLIPBOARD		3
#define	DTST_HOTLINK		4
#define	DTST_MEMORY		5	/* New for V44 */

/*****************************************************************************/

/* Attached to the Gadget.SpecialInfo field of the gadget.  Don't access directly,
 * use the Get/Set calls instead.
 */
struct DTSpecialInfo
{
    struct SignalSemaphore	 si_Lock;	/* Locked while in DoAsyncLayout() */
    ULONG			 si_Flags;

    LONG			 si_TopVert;	/* Top row (in units) */
    LONG			 si_VisVert;	/* Number of visible rows (in units) */
    LONG			 si_TotVert;	/* Total number of rows (in units) */
    LONG			 si_OTopVert;	/* Previous top (in units) */
    LONG			 si_VertUnit;	/* Number of pixels in vertical unit */

    LONG			 si_TopHoriz;	/* Top column (in units) */
    LONG			 si_VisHoriz;	/* Number of visible columns (in units) */
    LONG			 si_TotHoriz;	/* Total number of columns (in units) */
    LONG			 si_OTopHoriz;	/* Previous top (in units) */
    LONG			 si_HorizUnit;	/* Number of pixels in horizontal unit */
};

/* Object is in layout processing */
#define	DTSIF_LAYOUT		(1L<<0)

/* Object needs to be layed out */
#define	DTSIF_NEWSIZE		(1L<<1)

#define	DTSIF_DRAGGING		(1L<<2)
#define	DTSIF_DRAGSELECT	(1L<<3)

#define	DTSIF_HIGHLIGHT		(1L<<4)

/* Object is being printed */
#define	DTSIF_PRINTING		(1L<<5)

/* Object is in layout process */
#define	DTSIF_LAYOUTPROC	(1L<<6)

/*****************************************************************************/

struct DTMethod
{
    STRPTR	 dtm_Label;
    STRPTR	 dtm_Command;
    ULONG	 dtm_Method;
};

/*****************************************************************************/

#define	DTM_Dummy		(0x600)

/* Inquire what environment an object requires */
#define	DTM_FRAMEBOX		(0x601)

/* Same as GM_LAYOUT except guaranteed to be on a process already */
#define	DTM_PROCLAYOUT		(0x602)

/* Layout that is occurring on a process */
#define	DTM_ASYNCLAYOUT		(0x603)

/* When a RemoveDTObject() is called */
#define	DTM_REMOVEDTOBJECT	(0x604)

#define	DTM_SELECT		(0x605)
#define	DTM_CLEARSELECTED	(0x606)

#define	DTM_COPY		(0x607)
#define	DTM_PRINT		(0x608)
#define	DTM_ABORTPRINT		(0x609)

#define	DTM_NEWMEMBER		(0x610)
#define	DTM_DISPOSEMEMBER	(0x611)

#define	DTM_GOTO		(0x630)
#define	DTM_TRIGGER		(0x631)

#define	DTM_OBTAINDRAWINFO	(0x640)
#define	DTM_DRAW		(0x641)
#define	DTM_RELEASEDRAWINFO	(0x642)

#define	DTM_WRITE		(0x650)

/* Used to ask the object about itself */
struct FrameInfo
{
    ULONG		 fri_PropertyFlags;		/* DisplayInfo (graphics/displayinfo.h) */
    Point		 fri_Resolution;		/* DisplayInfo */

    UBYTE		 fri_RedBits;
    UBYTE		 fri_GreenBits;
    UBYTE		 fri_BlueBits;

    struct
    {
    ULONG Width;
    ULONG Height;
    ULONG Depth;

    } fri_Dimensions;

    struct Screen	*fri_Screen;
    struct ColorMap	*fri_ColorMap;

    ULONG		 fri_Flags;
};

#define	FIF_SCALABLE	0x1
#define	FIF_SCROLLABLE	0x2
#define	FIF_REMAPPABLE	0x4

/* DTM_REMOVEDTOBJECT, DTM_CLEARSELECTED, DTM_COPY, DTM_ABORTPRINT */
struct dtGeneral
{
    ULONG		 MethodID;
    struct GadgetInfo	*dtg_GInfo;
};

/* DTM_SELECT */
struct dtSelect
{
    ULONG		 MethodID;
    struct GadgetInfo	*dts_GInfo;
    struct Rectangle	 dts_Select;
};

/* DTM_FRAMEBOX */
struct dtFrameBox
{
    ULONG		 MethodID;
    struct GadgetInfo	*dtf_GInfo;
    struct FrameInfo	*dtf_ContentsInfo;	/* Input */
    struct FrameInfo	*dtf_FrameInfo;		/* Output */
    ULONG		 dtf_SizeFrameInfo;
    ULONG		 dtf_FrameFlags;
};

#ifndef	FRAMEF_SPECIFY
#define FRAMEF_SPECIFY	(1<<0)	/* Make do with the dimensions of FrameBox provided. */
#endif

/* DTM_GOTO */
struct dtGoto
{
    ULONG		 MethodID;
    struct GadgetInfo	*dtg_GInfo;
    STRPTR		 dtg_NodeName;		/* Node to goto */
    struct TagItem	*dtg_AttrList;		/* Additional attributes */
};

/* DTM_TRIGGER */
struct dtTrigger
{
    ULONG		 MethodID;
    struct GadgetInfo	*dtt_GInfo;
    ULONG		 dtt_Function;
    APTR		 dtt_Data;
};

#define	STM_PAUSE		1
#define	STM_PLAY		2
#define	STM_CONTENTS		3
#define	STM_INDEX		4
#define	STM_RETRACE		5
#define	STM_BROWSE_PREV		6
#define	STM_BROWSE_NEXT		7

#define	STM_NEXT_FIELD		8
#define	STM_PREV_FIELD		9
#define	STM_ACTIVATE_FIELD	10

#define	STM_COMMAND		11

/* New for V40 */
#define	STM_REWIND		12
#define	STM_FASTFORWARD		13
#define	STM_STOP		14
#define	STM_RESUME		15
#define	STM_LOCATE		16

/* Printer IO request */
union printerIO
{
    struct IOStdReq ios;
    struct IODRPReq iodrp;
    struct IOPrtCmdReq iopc;
};

/* DTM_PRINT */
struct dtPrint
{
    ULONG		 MethodID;
    struct GadgetInfo	*dtp_GInfo;		/* Gadget information */
    union printerIO	*dtp_PIO;		/* Printer IO request */
    struct TagItem	*dtp_AttrList;		/* Additional attributes */
};

/* DTM_DRAW */
struct dtDraw
{
    ULONG		 MethodID;
    struct RastPort	*dtd_RPort;
    LONG		 dtd_Left;
    LONG		 dtd_Top;
    LONG		 dtd_Width;
    LONG		 dtd_Height;
    LONG		 dtd_TopHoriz;
    LONG		 dtd_TopVert;
    struct TagItem	*dtd_AttrList;		/* Additional attributes */
};

/* DTM_WRITE */
struct dtWrite
{
    ULONG		 MethodID;
    struct GadgetInfo	*dtw_GInfo;		/* Gadget information */
    BPTR		 dtw_FileHandle;	/* File handle to write to */
    ULONG		 dtw_Mode;
    struct TagItem	*dtw_AttrList;		/* Additional attributes */
};

/* Save data as IFF data */
#define	DTWM_IFF	0

/* Save data as local data format */
#define	DTWM_RAW	1

#endif /* DATATYPES_DATATYPESCLASS_H */


include/devices/timer.h

#ifndef DEVICES_TIMER_H
#define DEVICES_TIMER_H 1
/*
**	$VER: timer.h 36.16 (25.1.1991)
**	Includes Release 44.1
**
**	Timer device name and useful definitions.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**		All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef EXEC_IO_H
#include <exec/io.h>
#endif

/* unit defintions */
#define UNIT_MICROHZ	0
#define UNIT_VBLANK	1
#define UNIT_ECLOCK	2
#define UNIT_WAITUNTIL	3
#define	UNIT_WAITECLOCK	4

#define TIMERNAME	"timer.device"

struct timeval {
    ULONG tv_secs;
    ULONG tv_micro;
};

struct EClockVal {
    ULONG ev_hi;
    ULONG ev_lo;
};

struct timerequest {
    struct IORequest tr_node;
    struct timeval tr_time;
};

/* IO_COMMAND to use for adding a timer */
#define TR_ADDREQUEST	CMD_NONSTD
#define TR_GETSYSTIME	(CMD_NONSTD+1)
#define TR_SETSYSTIME	(CMD_NONSTD+2)

#endif /* DEVICES_TIMER_H */


include/dos/exall.h

#ifndef DOS_EXALL_H
#define DOS_EXALL_H
/*
**
**	$VER: exall.h 36.6 (5.4.1992)
**	Includes Release 44.1
**
**	include file for ExAll() data structures
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef UTILITY_HOOKS_H
#include <utility/hooks.h>
#endif

/* NOTE: V37 dos.library, when doing ExAll() emulation, and V37 filesystems  */
/* will return an error if passed ED_OWNER.  If you get ERROR_BAD_NUMBER,    */
/* retry with ED_COMMENT to get everything but owner info.  All filesystems  */
/* supporting ExAll() must support through ED_COMMENT, and must check Type   */
/* and return ERROR_BAD_NUMBER if they don't support the type.		     */

/* values that can be passed for what data you want from ExAll() */
/* each higher value includes those below it (numerically)	 */
/* you MUST chose one of these values */
#define	ED_NAME		1
#define	ED_TYPE		2
#define ED_SIZE		3
#define ED_PROTECTION	4
#define ED_DATE		5
#define ED_COMMENT	6
#define ED_OWNER	7

/*
 *   Structure in which exall results are returned in.	Note that only the
 *   fields asked for will exist!
 */

struct ExAllData {
    struct ExAllData *ed_Next;
    UBYTE  *ed_Name;
    LONG	ed_Type;
    ULONG	ed_Size;
    ULONG	ed_Prot;
    ULONG	ed_Days;
    ULONG	ed_Mins;
    ULONG	ed_Ticks;
    UBYTE  *ed_Comment;	/* strings will be after last used field */
    UWORD	ed_OwnerUID;	/* new for V39 */
    UWORD	ed_OwnerGID;
};

/*
 *   Control structure passed to ExAll.  Unused fields MUST be initialized to
 *   0, expecially eac_LastKey.
 *
 *   eac_MatchFunc is a hook (see utility.library documentation for usage)
 *   It should return true if the entry is to returned, false if it is to be
 *   ignored.
 *
 *   This structure MUST be allocated by AllocDosObject()!
 */

struct ExAllControl {
    ULONG	eac_Entries;	 /* number of entries returned in buffer      */
    ULONG	eac_LastKey;	 /* Don't touch inbetween linked ExAll calls! */
    UBYTE  *eac_MatchString; /* wildcard string for pattern match or NULL */
    struct Hook *eac_MatchFunc; /* optional private wildcard function     */
};

#endif /* DOS_EXALL_H */


include/exec/execbase.h

#ifndef EXEC_EXECBASE_H
#define EXEC_EXECBASE_H
/*
**	$VER: execbase.h 39.6 (18.1.1993)
**	Includes Release 44.1
**
**	Definition of the exec.library base structure.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_LISTS_H
#include <exec/lists.h>
#endif /* EXEC_LISTS_H */

#ifndef EXEC_INTERRUPTS_H
#include <exec/interrupts.h>
#endif /* EXEC_INTERRUPTS_H */

#ifndef EXEC_LIBRARIES_H
#include <exec/libraries.h>
#endif /* EXEC_LIBRARIES_H */

#ifndef EXEC_TASKS_H
#include <exec/tasks.h>
#endif /* EXEC_TASKS_H */

/* Definition of the Exec library base structure (pointed to by location 4).
** Most fields are not to be viewed or modified by user programs.  Use
** extreme caution.
*/
struct ExecBase {
    struct Library LibNode; /* Standard library node */

/******** Static System Variables ********/

    UWORD	SoftVer;	/* kickstart release number (obs.) */
    WORD	LowMemChkSum;	/* checksum of 68000 trap vectors */
    ULONG	ChkBase;	/* system base pointer complement */
    APTR	ColdCapture;	/* coldstart soft capture vector */
    APTR	CoolCapture;	/* coolstart soft capture vector */
    APTR	WarmCapture;	/* warmstart soft capture vector */
    APTR	SysStkUpper;	/* system stack base   (upper bound) */
    APTR	SysStkLower;	/* top of system stack (lower bound) */
    ULONG	MaxLocMem;	/* top of chip memory */
    APTR	DebugEntry;	/* global debugger entry point */
    APTR	DebugData;	/* global debugger data segment */
    APTR	AlertData;	/* alert data segment */
    APTR	MaxExtMem;	/* top of extended mem, or null if none */

    UWORD	ChkSum;	/* for all of the above (minus 2) */

/****** Interrupt Related ***************************************/

    struct	IntVector IntVects[16];

/****** Dynamic System Variables *************************************/

    struct	Task *ThisTask; /* pointer to current task (readable) */

    ULONG	IdleCount;	/* idle counter */
    ULONG	DispCount;	/* dispatch counter */
    UWORD	Quantum;	/* time slice quantum */
    UWORD	Elapsed;	/* current quantum ticks */
    UWORD	SysFlags;	/* misc internal system flags */
    BYTE	IDNestCnt;	/* interrupt disable nesting count */
    BYTE	TDNestCnt;	/* task disable nesting count */

    UWORD	AttnFlags;	/* special attention flags (readable) */

    UWORD	AttnResched;	/* rescheduling attention */
    APTR	ResModules;	/* resident module array pointer */
    APTR	TaskTrapCode;
    APTR	TaskExceptCode;
    APTR	TaskExitCode;
    ULONG	TaskSigAlloc;
    UWORD	TaskTrapAlloc;

/****** System Lists (private!) ********************************/

    struct	List MemList;
    struct	List ResourceList;
    struct	List DeviceList;
    struct	List IntrList;
    struct	List LibList;
    struct	List PortList;
    struct	List TaskReady;
    struct	List TaskWait;

    struct	SoftIntList SoftInts[5];

/****** Other Globals *******************************************/

    LONG	LastAlert[4];

    /* these next two variables are provided to allow
    ** system developers to have a rough idea of the
    ** period of two externally controlled signals --
    ** the time between vertical blank interrupts and the
    ** external line rate (which is counted by CIA A's
    ** "time of day" clock).  In general these values
    ** will be 50 or 60, and may or may not track each
    ** other.  These values replace the obsolete AFB_PAL
    ** and AFB_50HZ flags.
    */
    UBYTE	VBlankFrequency;	/* (readable) */
    UBYTE	PowerSupplyFrequency;	/* (readable) */

    struct	List SemaphoreList;

    /* these next two are to be able to kickstart into user ram.
    ** KickMemPtr holds a singly linked list of MemLists which
    ** will be removed from the memory list via AllocAbs.  If
    ** all the AllocAbs's succeeded, then the KickTagPtr will
    ** be added to the rom tag list.
    */
    APTR	KickMemPtr;	/* ptr to queue of mem lists */
    APTR	KickTagPtr;	/* ptr to rom tag queue */
    APTR	KickCheckSum;	/* checksum for mem and tags */

/****** V36 Exec additions start here **************************************/

    UWORD	ex_Pad0;		/* Private internal use */
    ULONG	ex_LaunchPoint;		/* Private to Launch/Switch */
    APTR	ex_RamLibPrivate;
    /* The next ULONG contains the system "E" clock frequency,
    ** expressed in Hertz.	The E clock is used as a timebase for
    ** the Amiga's 8520 I/O chips. (E is connected to "02").
    ** Typical values are 715909 for NTSC, or 709379 for PAL.
    */
    ULONG	ex_EClockFrequency;	/* (readable) */
    ULONG	ex_CacheControl;	/* Private to CacheControl calls */
    ULONG	ex_TaskID;		/* Next available task ID */

    ULONG	ex_Reserved1[5];

    APTR	ex_MMULock;		/* private */

    ULONG	ex_Reserved2[3];

/****** V39 Exec additions start here **************************************/

    /* The following list and data element are used
     * for V39 exec's low memory handler...
     */
    struct	MinList	ex_MemHandlers;	/* The handler list */
    APTR	ex_MemHandler;		/* Private! handler pointer */
};

/****** Bit defines for AttnFlags (see above) ******************************/

/*  Processors and Co-processors: */
#define AFB_68010	0	/* also set for 68020 */
#define AFB_68020	1	/* also set for 68030 */
#define AFB_68030	2	/* also set for 68040 */
#define AFB_68040	3
#define AFB_68881	4	/* also set for 68882 */
#define AFB_68882	5
#define	AFB_FPU40	6	/* Set if 68040 FPU */
/*
 * The AFB_FPU40 bit is set when a working 68040 FPU
 * is in the system.  If this bit is set and both the
 * AFB_68881 and AFB_68882 bits are not set, then the 68040
 * math emulation code has not been loaded and only 68040
 * FPU instructions are available.  This bit is valid *ONLY*
 * if the AFB_68040 bit is set.
 */

#define AFB_PRIVATE	15	/* Just what it says */

#define AFF_68010	(1L<<0)
#define AFF_68020	(1L<<1)
#define AFF_68030	(1L<<2)
#define AFF_68040	(1L<<3)
#define AFF_68881	(1L<<4)
#define AFF_68882	(1L<<5)
#define	AFF_FPU40	(1L<<6)

#define AFF_PRIVATE	(1L<<15)

/* #define AFB_RESERVED8   8 */
/* #define AFB_RESERVED9   9 */

/****** Selected flag definitions for Cache manipulation calls **********/

#define CACRF_EnableI	    (1L<<0)  /* Enable instruction cache */
#define CACRF_FreezeI	    (1L<<1)  /* Freeze instruction cache */
#define CACRF_ClearI	    (1L<<3)  /* Clear instruction cache  */
#define CACRF_IBE	    (1L<<4)  /* Instruction burst enable */
#define CACRF_EnableD	    (1L<<8)  /* 68030 Enable data cache  */
#define CACRF_FreezeD	    (1L<<9)  /* 68030 Freeze data cache  */
#define CACRF_ClearD	    (1L<<11) /* 68030 Clear data cache	 */
#define CACRF_DBE	    (1L<<12) /* 68030 Data burst enable */
#define CACRF_WriteAllocate (1L<<13) /* 68030 Write-Allocate mode
                    (must always be set!)	 */
#define	CACRF_EnableE	    (1L<<30) /* Master enable for external caches */
                     /* External caches should track the */
                     /* state of the internal caches */
                     /* such that they do not cache anything */
                     /* that the internal cache turned off */
                     /* for. */
#define CACRF_CopyBack	    (1L<<31) /* Master enable for copyback caches */

#define DMA_Continue	    (1L<<1)  /* Continuation flag for CachePreDMA */
#define DMA_NoModify	    (1L<<2)  /* Set if DMA does not update memory */
#define	DMA_ReadFromRAM     (1L<<3)  /* Set if DMA goes *FROM* RAM to device */

#endif	/* EXEC_EXECBASE_H */


include/graphics/gfxnodes.h

#ifndef	GRAPHICS_GFXNODES_H
#define	GRAPHICS_GFXNODES_H
/*
**	$VER: gfxnodes.h 39.0 (21.8.1991)
**	Includes Release 44.1
**
**	graphics extended node definintions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_NODES_H
#include <exec/nodes.h>
#endif

struct	ExtendedNode	{
struct	Node	*xln_Succ;
struct	Node	*xln_Pred;
UBYTE	xln_Type;
BYTE	xln_Pri;
char	*xln_Name;
UBYTE	xln_Subsystem;
UBYTE	xln_Subtype;
LONG	xln_Library;
LONG	(*xln_Init)();
};

#define SS_GRAPHICS	0x02

#define	VIEW_EXTRA_TYPE		1
#define	VIEWPORT_EXTRA_TYPE	2
#define	SPECIAL_MONITOR_TYPE	3
#define	MONITOR_SPEC_TYPE	4

#endif	/* GRAPHICS_GFXNODES_H */


include/graphics/sprite.h

#ifndef	GRAPHICS_SPRITE_H
#define	GRAPHICS_SPRITE_H
/*
**	$VER: sprite.h 39.6 (16.6.1992)
**	Includes Release 44.1
**
**
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#define SPRITE_ATTACHED 0x80

struct SimpleSprite
{
    UWORD *posctldata;
    UWORD height;
    UWORD   x,y;    /* current position */
    UWORD   num;
};

struct ExtSprite
{
    struct SimpleSprite es_SimpleSprite;	/* conventional simple sprite structure */
    UWORD	es_wordwidth;			/* graphics use only, subject to change */
    UWORD	es_flags;			/* graphics use only, subject to change */
};

/* tags for AllocSpriteData() */
#define SPRITEA_Width		0x81000000
#define SPRITEA_XReplication	0x81000002
#define SPRITEA_YReplication	0x81000004
#define SPRITEA_OutputHeight	0x81000006
#define SPRITEA_Attached	0x81000008
#define SPRITEA_OldDataFormat	0x8100000a	/* MUST pass in outputheight if using this tag */

/* tags for GetExtSprite() */
#define GSTAG_SPRITE_NUM 0x82000020
#define GSTAG_ATTACHED	 0x82000022
#define GSTAG_SOFTSPRITE 0x82000024

/* tags valid for either GetExtSprite or ChangeExtSprite */
#define GSTAG_SCANDOUBLED	0x83000000	/* request "NTSC-Like" height if possible. */

#endif	/* GRAPHICS_SPRITE_H */


include/resources/filesysres.h

#ifndef	RESOURCES_FILESYSRES_H
#define	RESOURCES_FILESYSRES_H
/*
**	$VER: filesysres.h 36.4 (3.5.1990)
**	Includes Release 44.1
**
**	FileSystem.resource description
**
**	(C) Copyright 1988-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef	EXEC_NODES_H
#include	<exec/nodes.h>
#endif
#ifndef	EXEC_LISTS_H
#include	<exec/lists.h>
#endif
#ifndef	DOS_DOS_H
#include	<dos/dos.h>
#endif

#define	FSRNAME	"FileSystem.resource"

struct FileSysResource {
    struct Node fsr_Node;		/* on resource list */
    char   *fsr_Creator;		/* name of creator of this resource */
    struct List fsr_FileSysEntries;	/* list of FileSysEntry structs */
};

struct FileSysEntry {
    struct Node fse_Node;	/* on fsr_FileSysEntries list */
                /* ln_Name is of creator of this entry */
    ULONG   fse_DosType;	/* DosType of this FileSys */
    ULONG   fse_Version;	/* Version of this FileSys */
    ULONG   fse_PatchFlags;	/* bits set for those of the following that */
                /*   need to be substituted into a standard */
                /*   device node for this file system: e.g. */
                /*   0x180 for substitute SegList & GlobalVec */
    ULONG   fse_Type;		/* device node type: zero */
    CPTR    fse_Task;		/* standard dos "task" field */
    BPTR    fse_Lock;		/* not used for devices: zero */
    BSTR    fse_Handler;	/* filename to loadseg (if SegList is null) */
    ULONG   fse_StackSize;	/* stacksize to use when starting task */
    LONG    fse_Priority;	/* task priority when starting task */
    BPTR    fse_Startup;	/* startup msg: FileSysStartupMsg for disks */
    BPTR    fse_SegList;	/* code to run to start new task */
    BPTR    fse_GlobalVec;	/* BCPL global vector when starting task */
    /* no more entries need exist than those implied by fse_PatchFlags */
};

#endif	/* RESOURCES_FILESYSRES_H */


include/prefs/font.h

#ifndef PREFS_FONT_H
#define PREFS_FONT_H
/*
**	$VER: font.h 38.2 (27.9.1991)
**	Includes Release 44.1
**
**	File format for font preferences
**
**	(C) Copyright 1991-1999 Amiga, Inc.
**	All Rights Reserved
*/

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef LIBRARIES_IFFPARSE_H
#include <libraries/iffparse.h>
#endif

#ifndef GRAPHICS_TEXT_H
#include <graphics/text.h>
#endif

/*****************************************************************************/

#define ID_FONT MAKE_ID('F','O','N','T')

#define FONTNAMESIZE (128)

struct FontPrefs
{
    LONG	    fp_Reserved[3];
    UWORD	    fp_Reserved2;
    UWORD	    fp_Type;
    UBYTE	    fp_FrontPen;
    UBYTE	    fp_BackPen;
    UBYTE	    fp_DrawMode;
    struct TextAttr fp_TextAttr;
    BYTE	    fp_Name[FONTNAMESIZE];
};

/* constants for FontPrefs.fp_Type */
#define FP_WBFONT     0
#define FP_SYSFONT    1
#define FP_SCREENFONT 2

/*****************************************************************************/

#endif /* PREFS_FONT_H */


include/intuition/cghooks.h

#ifndef INTUITION_CGHOOKS_H
#define INTUITION_CGHOOKS_H 1
/*
**  $VER: cghooks.h 38.1 (11.11.1991)
**  Includes Release 44.1
**
**  Custom Gadget processing
**
**  (C) Copyright 1988-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef INTUITION_INTUITION_H
#include <intuition/intuition.h>
#endif

/*
 * Package of information passed to custom and 'boopsi'
 * gadget "hook" functions.  This structure is READ ONLY.
 */
struct GadgetInfo {

    struct Screen		*gi_Screen;
    struct Window		*gi_Window;	/* null for screen gadgets */
    struct Requester		*gi_Requester;	/* null if not GTYP_REQGADGET */

    /* rendering information:
     * don't use these without cloning/locking.
     * Official way is to call ObtainRPort()
     */
    struct RastPort		*gi_RastPort;
    struct Layer		*gi_Layer;

    /* copy of dimensions of screen/window/g00/req(/group)
     * that gadget resides in.	Left/Top of this box is
     * offset from window mouse coordinates to gadget coordinates
     *		screen gadgets:			0,0 (from screen coords)
     *	window gadgets (no g00):	0,0
     *	GTYP_GZZGADGETs (borderlayer):		0,0
     *	GZZ innerlayer gadget:		borderleft, bordertop
     *	Requester gadgets:		reqleft, reqtop
     */
    struct IBox			gi_Domain;

    /* these are the pens for the window or screen	*/
    struct {
    UBYTE	DetailPen;
    UBYTE	BlockPen;
    }				gi_Pens;

    /* the Detail and Block pens in gi_DrInfo->dri_Pens[] are
     * for the screen.	Use the above for window-sensitive
     * colors.
     */
    struct DrawInfo		*gi_DrInfo;

    /* reserved space: this structure is extensible
     * anyway, but using these saves some recompilation
     */
    ULONG			gi_Reserved[6];
};

/*** system private data structure for now ***/
/* prop gadget extra info	*/
struct PGX	{
    struct IBox	pgx_Container;
    struct IBox	pgx_NewKnob;
};

/* this casts MutualExclude for easy assignment of a hook
 * pointer to the unused MutualExclude field of a custom gadget
 */
#define CUSTOM_HOOK( gadget ) ( (struct Hook *) (gadget)->MutualExclude)

#endif


include/devices/gameport.h

#ifndef DEVICES_GAMEPORT_H
#define DEVICES_GAMEPORT_H
/*
**	$VER: gameport.h 36.1 (5.11.1990)
**	Includes Release 44.1
**
**	GamePort device command definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef	EXEC_TYPES_H
#include	<exec/types.h>
#endif

#ifndef	EXEC_IO_H
#include	<exec/io.h>
#endif

/******	 GamePort commands ******/
#define	 GPD_READEVENT	   (CMD_NONSTD+0)
#define	 GPD_ASKCTYPE	   (CMD_NONSTD+1)
#define	 GPD_SETCTYPE	   (CMD_NONSTD+2)
#define	 GPD_ASKTRIGGER	   (CMD_NONSTD+3)
#define	 GPD_SETTRIGGER	   (CMD_NONSTD+4)

/******	 GamePort structures ******/

/* gpt_Keys */
#define	 GPTB_DOWNKEYS	   0
#define	 GPTF_DOWNKEYS	   (1<<0)
#define	 GPTB_UPKEYS	   1
#define	 GPTF_UPKEYS	   (1<<1)

struct GamePortTrigger {
   UWORD gpt_Keys;	   /* key transition triggers */
   UWORD gpt_Timeout;	   /* time trigger (vertical blank units) */
   UWORD gpt_XDelta;	   /* X distance trigger */
   UWORD gpt_YDelta;	   /* Y distance trigger */
};

/****** Controller Types ******/
#define	 GPCT_ALLOCATED	   -1	 /* allocated by another user */
#define	 GPCT_NOCONTROLLER 0

#define	 GPCT_MOUSE	   1
#define	 GPCT_RELJOYSTICK  2
#define	 GPCT_ABSJOYSTICK  3

/****** Errors ******/
#define	 GPDERR_SETCTYPE   1	 /* this controller not valid at this time */

#endif	/* DEVICES_GAMEPORT_H */


include/gadgets/getfile.h

#ifndef GADGETS_GETFILE_H
#define GADGETS_GETFILE_H
/*
**	$VER: getfile.h 44.1 (19.10.1999)
**	Includes Release 44.1
**
**  Definitions for the getfile.gadget BOOPSI class
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

/*****************************************************************************/

#ifndef REACTION_REACTION_H
#include <reaction/reaction.h>
#endif

#ifndef INTUITION_GADGETCLASS_H
#include <intuition/gadgetclass.h>
#endif

/*****************************************************************************/

/* Attributes defined by the getfile.gadget class
 */
#define GETFILE_Dummy			(REACTION_Dummy + 0x60000)

#define GETFILE_TitleText		(GETFILE_Dummy+1)
    /* (STRPTR) Requester title text (default: None) (OM_NEW, OM_SET) */

#define GETFILE_LeftEdge		(GETFILE_Dummy+2)
#define GETFILE_TopEdge			(GETFILE_Dummy+3)
    /* (WORD) Requester coordinates  (default leftedge: 30, topedge: 20) (OM_NEW, OM_SET, OM_GET) */

#define GETFILE_Width			(GETFILE_Dummy+4)
#define GETFILE_Height			(GETFILE_Dummy+5)
    /* (WORD) Requester dimensions (default height: 200, width: 300) (OM_NEW, OM_SET, OM_GET) */

#define GETFILE_File			(GETFILE_Dummy+6)
    /* (STRPTR) Contents of File gadget (default: None) (OM_NEW, OM_SET, OM_GET, OM_NOTIFY) */

#define GETFILE_Drawer			(GETFILE_Dummy+7)
    /* (STRPTR) Contents of Drawer gadget (default: None) (OM_NEW, OM_SET, OM_GET, OM_NOTIFY) */

#define GETFILE_FullFile		(GETFILE_Dummy+8)
    /* (STRPTR) Complete file name. Replaces GETFILE_Drawer and GETFILE_File (default: None)
            (OM_NEW, OM_SET, OM_GET, OM_NOTIFY)
    */

#define GETFILE_FullFileExpand	(GETFILE_Dummy+9)
    /* (BOOL) GETFILE_FullFile will give complete file name(s) expanded with NameFromLock() to
            remove relative paths. (default: TRUE) (OM_NEW, OM_SET)
    */

#define GETFILE_Pattern			(GETFILE_Dummy+10)
    /* (STRPTR) Contents of Pattern gadget (default: "#?") (OM_NEW, OM_SET, OM_GET) */

#define GETFILE_DoSaveMode		(GETFILE_Dummy+11)
    /* (BOOL) Being used for saving? (default: FALSE) (OM_NEW, OM_SET) */

#define GETFILE_DoMultiSelect	(GETFILE_Dummy+12)
    /* (BOOL) Do multi-select? (default: FALSE) (OM_NEW, OM_SET) */

#define GETFILE_DoPatterns		(GETFILE_Dummy+13)
    /* (BOOL) Display a Pattern gadget? (default: FALSE) (OM_NEW, OM_SET) */

#define GETFILE_DrawersOnly		(GETFILE_Dummy+14)
    /* (BOOL) Don't display files? (default: FALSE) (OM_NEW, OM_SET) */

#define GETFILE_FilterFunc		(GETFILE_Dummy+15)
    /* (struct Hook *) Function to filter files (default: None) (OM_NEW, OM_SET)  */

#define GETFILE_RejectIcons		(GETFILE_Dummy+16)
    /* (BOOL) Display .info files? (default: FALSE) (OM_NEW, OM_SET)  */

#define GETFILE_RejectPattern	(GETFILE_Dummy+17)
    /* (UBYTE *) Don't display files matching pattern (default: None) (OM_NEW, OM_SET) */

#define GETFILE_AcceptPattern	(GETFILE_Dummy+18)
    /* (UBYTE *) Accept only files matching pattern (default: None) (OM_NEW, OM_SET) */

#define GETFILE_FilterDrawers	(GETFILE_Dummy+19)
    /* (BOOL) Also filter drawers with pattern (default: FALSE) (OM_NEW, OM_SET) */

#define GETFILE_Filelist		(GETFILE_Dummy+20)
    /* (struct List *) If the GETFILE_DoMultiSelect tags was used, you can get a pointer
            to the list of selected files/drawers using this tag. The ln_Name part of
            each node will contain the filename/drawername for each selected file with
            a fully qualified path, even if you didn't use the GETFILE_FullFileExpand.
            In single-selected mode, the list will contain the single selected file for
            notification purposes. Don't forget to free the list using the GFILE_FREELIST
            method! (OM_GET, OM_NOTIFY) */

#define GETFILE_LBNodeStructs	(GETFILE_Dummy+21)
    /* (BOOL) GETFILE_Filelist will give a list with ListBrowserNodes instead of normal
            struct Node node structures (default: FALSE) (OM_NEW) */

#define GETFILE_ReadOnly		(GETFILE_Dummy+22)
    /* (BOOL) If TRUE, a read-only recessed button gadget is used to present the
            file/drawer information. If FALSE, an editable string gadget is used.
            (default: TRUE) (OM_NEW) */

#define GETFILE_FilePartOnly	(GETFILE_Dummy+23)
    /* (BOOL) display file part only - valid ONLY in readonly mode!
     */

/*****************************************************************************/

/*
 * getfile.gadget methods
 */
#define GFILE_REQUEST	(0x620001L)
#define GFILE_FREELIST	(0x620002L)

/* The GFILE_REQUEST method should be called whenever you want to open
 * a file/dir requester.
 */

struct gfileRequest
{
    ULONG MethodID;					/* GFILE_REQUEST */
    struct Window *gfile_Window;	/* The window that will be locked when the requester is active. MUST be provided! */
};

/* The GFILE_FREELIST method SHOULD be called when you are done doing a multiselect
 * a file/dir select using the tag GETFILE_DoMultiSelect and have processed the result.
 * This method will free the list of struct Node structures.  If you do not free this
 * list using this method, the list will not be freed until you dispose the class.
 */

struct gfileFreelist
{
    ULONG MethodID;					/* GFILE_FREELIST */
    struct List *gfile_Filelist;	/* The list of struct Node obtained using the GETFILE_Filelist tag in OM_GET.
                                        Can be NULL, in which case this method will do nothing. */
};

/* macros for calling the methods easily */

#define gfRequestFile(obj, win)		DoMethod(obj, GFILE_REQUEST, win)
#define gfRequestDir(obj, win)		DoMethod(obj, GFILE_REQUEST, win)
#define gfFreeFilelist(obj, list)	DoMethod(obj, GFILE_FREELIST, list)

#endif /* GADGETS_GETFILE_H */


include/gadgets/getfont.h

#ifndef GADGETS_GETFONT_H
#define GADGETS_GETFONT_H
/*
**	$VER: getfont.h 44.1 (19.10.1999)
**	Includes Release 44.1
**
**  Definitions for the getfont.gadget BOOPSI class
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

/*****************************************************************************/

#ifndef REACTION_REACTION_H
#include <reaction/reaction.h>
#endif

#ifndef INTUITION_GADGETCLASS_H
#include <intuition/gadgetclass.h>
#endif

/*****************************************************************************/

/* Attributes defined by the getfont.gadget class
 */
#define GETFONT_Dummy			(REACTION_Dummy + 0x40000)

#define	GETFONT_TextAttr		(GETFONT_Dummy+1)
    /* (struct TextAttr *) Font to show in the gadget (default: None)
                (OM_NEW, OM_SET, OM_GET, OM_NOTIFY) */

#define	GETFONT_DoFrontPen		(GETFONT_Dummy+2)
    /* (BOOL) Do front pen (default: FALSE) (OM_NEW, OM_SET) */

#define	GETFONT_DoBackPen		(GETFONT_Dummy+3)
    /* (BOOL) Do back pen (default: FALSE) (OM_NEW, OM_SET) */

#define	GETFONT_DoStyle			(GETFONT_Dummy+4)
    /* (BOOL) Do style (default: FALSE) (OM_NEW, OM_SET) */

#define	GETFONT_DoDrawMode		(GETFONT_Dummy+5)
    /* (BOOL) Do draw mode (default: FALSE) (OM_NEW, OM_SET) */

#define	GETFONT_MinHeight		(GETFONT_Dummy+6)
    /* (UWORD) Minimum font height (default: 6) (OM_NEW, OM_SET) */

#define	GETFONT_MaxHeight		(GETFONT_Dummy+7)
    /* (UWORD) Maximum font height (default: 20) (OM_NEW, OM_SET) */

#define	GETFONT_FixedWidthOnly	(GETFONT_Dummy+8)
    /* (BOOL) Only show fixed width fonts (default: FALSE) (OM_NEW, OM_SET) */

#define	GETFONT_TitleText		(GETFONT_Dummy+9)
    /* (STRPTR) Title of the ASL font requester (default: None) (OM_NEW, OM_SET) */

#define	GETFONT_Height			(GETFONT_Dummy+10)
    /* (WORD) Height of the ASL font requester (default: 200) (OM_NEW, OM_SET, OM_GET) (ASL V38) */

#define	GETFONT_Width			(GETFONT_Dummy+11)
    /* (WORD) Width of the ASL font requester (default: 300) (OM_NEW, OM_SET, OM_GET) (ASL V38) */

#define	GETFONT_LeftEdge		(GETFONT_Dummy+12)
    /* (WORD) Left edge of the ASL font requester (default: 30) (OM_NEW, OM_SET, OM_GET) */

#define	GETFONT_TopEdge			(GETFONT_Dummy+13)
    /* (WORD) Top edge of the ASL font requester (default: 20) (OM_NEW, OM_SET, OM_GET) */

#define	GETFONT_FrontPen		(GETFONT_Dummy+14)
    /* (UBYTE) Front pen (default: 1) (OM_NEW, OM_SET, OM_GET, OM_NOTIFY) */

#define	GETFONT_BackPen			(GETFONT_Dummy+15)
    /* (UBYTE) Back pen (default: 0) (OM_NEW, OM_SET, OM_GET, OM_NOTIFY) */

#define	GETFONT_DrawMode		(GETFONT_Dummy+16)
    /* (UBYTE) Draw mode (default: JAM1) (OM_NEW, OM_SET, OM_GET, OM_NOTIFY) */

#define	GETFONT_MaxFrontPen		(GETFONT_Dummy+17)
    /* (UBYTE) Max number of colors in front palette (default: 255) (OM_NEW, OM_SET) (ASL V40) */

#define	GETFONT_MaxBackPen		(GETFONT_Dummy+18)
    /* (UBYTE) Max number of colors in back palette (default: 255) (OM_NEW, OM_SET) (ASL V40) */

#define	GETFONT_ModeList		(GETFONT_Dummy+19)
    /* (STRPTR *) Substitute list for drawmodes (default: None) (OM_NEW, OM_SET) */

#define	GETFONT_FrontPens		(GETFONT_Dummy+20)
    /* (UBYTE *) Color table for front pen palette (default: None) (OM_NEW, OM_SET) (ASL V40) */

#define	GETFONT_BackPens		(GETFONT_Dummy+21)
    /* (UBYTE *) Color table for back pen palette (default: None) (OM_NEW, OM_SET) (ASL V40) */

#define	GETFONT_SoftStyle		(GETFONT_Dummy+22)
    /* (UBYTE) SoftStyle, provided only for making mapping to button.gadget easier (OM_GET, OM_NOTIFY)
            textattr.ta_Style in the GETFONT_TextAttr attribute will provide the style in other
            cases.
    */

/*****************************************************************************/

/*
 * getfont.gadget methods
 */
#define GFONT_REQUEST	(0x600001L)

/* The GFONT_REQUEST method should be called whenever you want to open
 * a font requester.
 */

struct gfRequest
{
    ULONG MethodID;				/* GFONT_REQUEST */
    struct Window *gfr_Window;	/* The window that will be locked when the requester is active. MUST be provided! */
};

#define gfRequestFont(obj, win)	DoMethod(obj, GFONT_REQUEST, win)

#endif /* GADGETS_GETFONT_H */


include/graphics/gfxbase.h

#ifndef GRAPHICS_GFXBASE_H
#define GRAPHICS_GFXBASE_H
/*
**	$VER: gfxbase.h 39.21 (21.4.1993)
**	Includes Release 44.1
**
**	graphics base definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_LISTS_H
#include <exec/lists.h>
#endif
#ifndef EXEC_LIBRARIES_H
#include <exec/libraries.h>
#endif
#ifndef EXEC_INTERRUPTS_H
#include <exec/interrupts.h>
#endif
#ifndef	GRAPHICS_MONITOR_H
#include <graphics/monitor.h>
#endif

struct GfxBase
{
    struct	Library  LibNode;
    struct	View *ActiView;
    struct	copinit *copinit;	/* ptr to copper start up list */
    LONG	*cia;			/* for 8520 resource use */
    LONG	*blitter;		/* for future blitter resource use */
    UWORD	*LOFlist;
    UWORD	*SHFlist;
    struct	bltnode *blthd,*blttl;
    struct	bltnode *bsblthd,*bsblttl;
    struct	Interrupt vbsrv,timsrv,bltsrv;
    struct	List	 TextFonts;
    struct	TextFont *DefaultFont;
    UWORD	Modes;			/* copy of current first bplcon0 */
    BYTE	VBlank;
    BYTE	Debug;
    WORD	BeamSync;
    WORD	system_bplcon0;		/* it is ored into each bplcon0 for display */
    UBYTE	SpriteReserved;
    UBYTE	bytereserved;
    UWORD	Flags;
    WORD	BlitLock;
    WORD	BlitNest;

    struct	List BlitWaitQ;
    struct	Task *BlitOwner;
    struct	List TOF_WaitQ;
    UWORD	DisplayFlags;		/* NTSC PAL GENLOC etc*/
                    /* flags initialized at power on */
    struct	SimpleSprite **SimpleSprites;
    UWORD	MaxDisplayRow;		/* hardware stuff, do not use */
    UWORD	MaxDisplayColumn;	/* hardware stuff, do not use */
    UWORD	NormalDisplayRows;
    UWORD	NormalDisplayColumns;
    /* the following are for standard non interlace, 1/2 wb width */
    UWORD	NormalDPMX;		/* Dots per meter on display */
    UWORD	NormalDPMY;		/* Dots per meter on display */
    struct	SignalSemaphore *LastChanceMemory;
    UWORD	*LCMptr;
    UWORD	MicrosPerLine;		/* 256 time usec/line */
    UWORD	MinDisplayColumn;
    UBYTE	ChipRevBits0;
    UBYTE	MemType;
    UBYTE	crb_reserved[4];
    UWORD	monitor_id;
    ULONG	hedley[8];
    ULONG	hedley_sprites[8];	/* sprite ptrs for intuition mouse */
    ULONG	hedley_sprites1[8];	/* sprite ptrs for intuition mouse */
    WORD	hedley_count;
    UWORD	hedley_flags;
    WORD	hedley_tmp;
    LONG	*hash_table;
    UWORD	current_tot_rows;
    UWORD	current_tot_cclks;
    UBYTE	hedley_hint;
    UBYTE	hedley_hint2;
    ULONG	nreserved[4];
    LONG	*a2024_sync_raster;
    UWORD	control_delta_pal;
    UWORD	control_delta_ntsc;
    struct	MonitorSpec *current_monitor;
    struct	List MonitorList;
    struct	MonitorSpec *default_monitor;
    struct	SignalSemaphore *MonitorListSemaphore;
    VOID	*DisplayInfoDataBase;
    UWORD	TopLine;
    struct	SignalSemaphore *ActiViewCprSemaphore;
    ULONG	*UtilBase;		/* for hook and tag utilities. had to change because of name clash	*/
    ULONG	*ExecBase;		/* to link with rom.lib	*/
    UBYTE	*bwshifts;
    UWORD	*StrtFetchMasks;
    UWORD	*StopFetchMasks;
    UWORD	*Overrun;
    WORD	*RealStops;
    UWORD	SpriteWidth;	/* current width (in words) of sprites */
    UWORD	SpriteFMode;		/* current sprite fmode bits	*/
    BYTE	SoftSprites;	/* bit mask of size change knowledgeable sprites */
    BYTE	arraywidth;
    UWORD	DefaultSpriteWidth;	/* what width intuition wants */
    BYTE	SprMoveDisable;
    UBYTE	WantChips;
    UBYTE	BoardMemType;
    UBYTE	Bugs;
    ULONG	*gb_LayersBase;
    ULONG	ColorMask;
    APTR	IVector;
    APTR	IData;
    ULONG	SpecialCounter;		/* special for double buffering */
    APTR	DBList;
    UWORD	MonitorFlags;
    UBYTE	ScanDoubledSprites;
    UBYTE	BP3Bits;
    struct	AnalogSignalInterval MonitorVBlank;
    struct	MonitorSpec *natural_monitor;
    APTR	ProgData;
    UBYTE	ExtSprites;
    UBYTE	pad3;
    UWORD	GfxFlags;
    ULONG	VBCounter;
    struct	SignalSemaphore *HashTableSemaphore;
    ULONG	*HWEmul[9];
};

#define ChunkyToPlanarPtr HWEmul[0]

/* Values for GfxBase->DisplayFlags */
#define NTSC		1
#define GENLOC		2
#define PAL		4
#define TODA_SAFE	8
#define REALLY_PAL	16	/* what is actual crystal frequency
                 (as opposed to what bootmenu set the agnus to)?
                 (V39) */
#define LPEN_SWAP_FRAMES	32
                /* LightPen software could set this bit if the
                 * "lpen-with-interlace" fix put in for V39
                 * does not work. This is true of a number of
                 * Agnus chips.
                 * (V40).
                 */

#define BLITMSG_FAULT	4

/* bits defs for ChipRevBits */
#define	GFXB_BIG_BLITS	0
#define	GFXB_HR_AGNUS	0
#define GFXB_HR_DENISE	1
#define GFXB_AA_ALICE	2
#define GFXB_AA_LISA	3
#define GFXB_AA_MLISA	4	/* internal use only. */

#define GFXF_BIG_BLITS	1
#define	GFXF_HR_AGNUS	1
#define GFXF_HR_DENISE	2
#define GFXF_AA_ALICE	4
#define GFXF_AA_LISA	8
#define GFXF_AA_MLISA	16	/* internal use only */

/* Pass ONE of these to SetChipRev() */
#define SETCHIPREV_A	GFXF_HR_AGNUS
#define SETCHIPREV_ECS	(GFXF_HR_AGNUS | GFXF_HR_DENISE)
#define SETCHIPREV_AA	(GFXF_AA_ALICE | GFXF_AA_LISA | SETCHIPREV_ECS)
#define SETCHIPREV_BEST 0xffffffff

/* memory type */
#define BUS_16		0
#define NML_CAS		0
#define BUS_32		1
#define DBL_CAS		2
#define BANDWIDTH_1X	(BUS_16 | NML_CAS)
#define BANDWIDTH_2XNML	BUS_32
#define BANDWIDTH_2XDBL	DBL_CAS
#define BANDWIDTH_4X	(BUS_32 | DBL_CAS)

/* GfxFlags (private) */
#define NEW_DATABASE	1

#define GRAPHICSNAME	"graphics.library"

#endif	/* GRAPHICS_GFXBASE_H */


include/diskfont/glyph.h

#ifndef  DISKFONT_GLYPH_H
#define  DISKFONT_GLYPH_H
/*
**	$VER: glyph.h 9.1 (19.6.1992)
**	Includes Release 44.1
**
**	glyph.h -- structures for glyph libraries
**
**	(C) Copyright 1991-1992 Robert R. Burns
**	    All Rights Reserved
*/

#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef  EXEC_LIBRARIES_H
#include <exec/libraries.h>
#endif

#ifndef  EXEC_NODES_H
#include <exec/nodes.h>
#endif

/* A GlyphEngine must be acquired via OpenEngine and is read-only */
struct GlyphEngine {
    struct Library *gle_Library; /* engine library */
    char *gle_Name;		/* library basename: e.g. "bullet" */
    /* private library data follows... */
};

typedef LONG FIXED;		/* 32 bit signed w/ 16 bits of fraction */

struct GlyphMap {
    UWORD   glm_BMModulo;	/* # of bytes in row: always multiple of 4 */
    UWORD   glm_BMRows;		/* # of rows in bitmap */
    UWORD   glm_BlackLeft;	/* # of blank pixel columns at left */
    UWORD   glm_BlackTop;	/* # of blank rows at top */
    UWORD   glm_BlackWidth;	/* span of contiguous non-blank columns */
    UWORD   glm_BlackHeight;	/* span of contiguous non-blank rows */
    FIXED   glm_XOrigin;	/* distance from upper left corner of bitmap */
    FIXED   glm_YOrigin;	/*   to initial CP, in fractional pixels */
    WORD    glm_X0;		/* approximation of XOrigin in whole pixels */
    WORD    glm_Y0;		/* approximation of YOrigin in whole pixels */
    WORD    glm_X1;		/* approximation of XOrigin + Width */
    WORD    glm_Y1;		/* approximation of YOrigin + Width */
    FIXED   glm_Width;		/* character advance, as fraction of em width */
    UBYTE  *glm_BitMap;		/* actual glyph bitmap */
};

struct GlyphWidthEntry {
    struct MinNode gwe_Node;	/* on list returned by OT_WidthList inquiry */
    UWORD   gwe_Code;		/* entry's character code value */
    FIXED   gwe_Width;		/* character advance, as fraction of em width */
};
#endif	 /* DISKFONT_GLYPH_H */


include/reaction/reaction_class.h

#ifndef REACTION_REACTION_CLASS_H
#define REACTION_REACTION_CLASS_H
/*
**	$VER: reaction_class.h 44.1 (19.10.1999)
**	Includes Release 44.1
**
**	reaction class author definitions
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef INTUITION_CGHOOKS_H
#include <intuition/cghooks.h>
#endif

/*
 * PRIVATE!
 */
struct SpecialPens
{
    WORD sp_Version;	/* Currently 0 */
    LONG sp_DarkPen;	/* XEN/Thick extended locked pen */
    LONG sp_LightPen;	/* XEN/Thick extended locked pen */
    /* NOTE: This structure may grow! */
};

/*****************************************************************************
 * Custom method defined and supported by some Reaction Gadgets
 * When this method is supported by more (all?) Reaction Gadgets
 * this structure may move to intuition/gadgetclass.h
 */
#define GM_CLIPRECT  (0x550001L)

/* The GM_CLIPRECT method is used to pass a gadget a cliprect
 * it should install before rendering to ObtainGIRPort() rastports
 * to support proper usage within virtual groups.
 */

struct gpClipRect
{
    ULONG                MethodID;       /* GM_CLIPRECT              */
    struct GadgetInfo   *gpc_GInfo;      /* GadgetInfo               */
    struct Rectangle    *gpc_ClipRect;   /* Rectangle To Clip To     */
    ULONG                gpc_Flags;      /* Flags                    */
};

/* Possible return values from GM_CLIPRECT
 */
#define GMC_VISIBLE			2
#define GMC_PARTIAL			1
#define GMC_INVISIBLE		0

/**************************************************************************/

#endif /* REACTION_REACTION_CLASS_H */


include/intuition/gadgetclass.h

#ifndef INTUITION_GADGETCLASS_H
#define INTUITION_GADGETCLASS_H
/*
**	$VER: gadgetclass.h 44.1 (19.10.1999)
**	Includes Release 44.1
**
**	Custom and 'boopsi' gadget class interface
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

/*****************************************************************************/

#ifndef INTUITION_INTUITION_H
#include <intuition/intuition.h>
#endif

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

/*****************************************************************************/

/* NOTE:  <intuition/iobsolete.h> is included at the END of this file! */

/*****************************************************************************/

/* Gadget class attributes */
#define	GA_Dummy 		(TAG_USER+0x30000)

#define	GA_Left			(GA_Dummy+1)
    /* (LONG) Left edge of the gadget relative to the left edge of
     * the window */

#define	GA_RelRight		(GA_Dummy+2)
    /* (LONG) Left edge of the gadget relative to the right edge of
     * the window */

#define	GA_Top			(GA_Dummy+3)
    /* (LONG) Top edge of the gadget relative to the top edge of
     * the window */

#define	GA_RelBottom		(GA_Dummy+4)
    /* (LONG) Top edge of the gadget relative to the bottom edge
     * of the window */

#define	GA_Width		(GA_Dummy+5)
    /* (LONG) Width of the gadget */

#define	GA_RelWidth		(GA_Dummy+6)
    /* (LONG) Width of the gadget relative to the width of the
     * window */

#define	GA_Height		(GA_Dummy+7)
    /* (LONG) Height of the gadget */

#define	GA_RelHeight		(GA_Dummy+8)
    /* (LONG) Height of the gadget relative to the height of
     * the window */

#define	GA_Text			(GA_Dummy+9)
    /* (STRPTR) Gadget imagry is NULL terminated string */

#define	GA_Image		(GA_Dummy+10)
    /* (struct Image *) Gadget imagry is an image */

#define	GA_Border		(GA_Dummy+11)
    /* (struct Border *) Gadget imagry is a border */

#define	GA_SelectRender		(GA_Dummy+12)
    /* (struct Image *) Selected gadget imagry */

#define	GA_Highlight		(GA_Dummy+13)
    /* (UWORD) One of GFLG_GADGHNONE, GFLG_GADGHBOX, GFLG_GADGHCOMP,
     * or GFLG_GADGHIMAGE */

#define	GA_Disabled		(GA_Dummy+14)
    /* (BOOL) Indicate whether gadget is disabled or not.
     * Defaults to FALSE. */

#define	GA_GZZGadget		(GA_Dummy+15)
    /* (BOOL) Indicate whether the gadget is for
     * WFLG_GIMMEZEROZERO window borders or not.  Defaults
     * to FALSE. */

#define	GA_ID			(GA_Dummy+16)
    /* (UWORD) Gadget ID assigned by the application */

#define	GA_UserData		(GA_Dummy+17)
    /* (APTR) Application specific data */

#define	GA_SpecialInfo		(GA_Dummy+18)
    /* (APTR) Gadget specific data */

#define	GA_Selected		(GA_Dummy+19)
    /* (BOOL) Indicate whether the gadget is selected or not.
     * Defaults to FALSE */

#define	GA_EndGadget		(GA_Dummy+20)
    /* (BOOL) When set tells the system that when this gadget
     * is selected causes the requester that it is in to be
     * ended.  Defaults to FALSE. */

#define	GA_Immediate		(GA_Dummy+21)
    /* (BOOL) When set indicates that the gadget is to
     * notify the application when it becomes active.  Defaults
     * to FALSE. */

#define	GA_RelVerify		(GA_Dummy+22)
    /* (BOOL) When set indicates that the application wants to
     * verify that the pointer was still over the gadget when
     * the select button is released.  Defaults to FALSE. */

#define	GA_FollowMouse		(GA_Dummy+23)
    /* (BOOL) When set indicates that the application wants to
     * be notified of mouse movements while the gadget is active.
     * It is recommmended that GA_Immediate and GA_RelVerify are
     * also used so that the active gadget can be tracked by the
     * application.  Defaults to FALSE. */

#define	GA_RightBorder		(GA_Dummy+24)
    /* (BOOL) Indicate whether the gadget is in the right border
     * or not.  Defaults to FALSE. */

#define	GA_LeftBorder		(GA_Dummy+25)
    /* (BOOL) Indicate whether the gadget is in the left border
     * or not.  Defaults to FALSE. */

#define	GA_TopBorder		(GA_Dummy+26)
    /* (BOOL) Indicate whether the gadget is in the top border
     * or not.  Defaults to FALSE. */

#define	GA_BottomBorder		(GA_Dummy+27)
    /* (BOOL) Indicate whether the gadget is in the bottom border
     * or not.  Defaults to FALSE. */

#define	GA_ToggleSelect		(GA_Dummy+28)
    /* (BOOL) Indicate whether the gadget is toggle-selected
     * or not.  Defaults to FALSE. */

#define	GA_SysGadget		(GA_Dummy+29)
    /* (BOOL) Reserved for system use to indicate that the
     * gadget belongs to the system.  Defaults to FALSE. */

#define	GA_SysGType		(GA_Dummy+30)
    /* (UWORD) Reserved for system use to indicate the
     * gadget type. */

#define	GA_Previous		(GA_Dummy+31)
    /* (struct Gadget *) Previous gadget in the linked list.
     * NOTE: This attribute CANNOT be used to link new gadgets
     * into the gadget list of an open window or requester.
     * You must use AddGList(). */

#define	GA_Next			(GA_Dummy+32)
    /* (struct Gadget *) Next gadget in the linked list. */

#define	GA_DrawInfo		(GA_Dummy+33)
    /* (struct DrawInfo *) Some gadgets need a DrawInfo at creation time */

/* You should use at most ONE of GA_Text, GA_IntuiText, and GA_LabelImage */
#define GA_IntuiText		(GA_Dummy+34)
    /* (struct IntuiText *) Label is an IntuiText. */

#define GA_LabelImage		(GA_Dummy+35)
    /* (Object *) Label is an image object. */

#define GA_TabCycle		(GA_Dummy+36)
    /* (BOOL) Indicate whether gadget is part of TAB/SHIFT-TAB cycle
     * activation.  Defaults to FALSE.  New for V37. */

#define GA_GadgetHelp		(GA_Dummy+37)
    /* (BOOL) Indicate whether gadget is to send IDCMP_GADGETHELP.
     * Defaults to FALSE.  New for V39. */

#define GA_Bounds		(GA_Dummy+38)
    /* (struct IBox *) Copied into the extended gadget's bounds.
     * New for V39. */

#define GA_RelSpecial		(GA_Dummy+39)
    /* (BOOL) Indicate whether gadget has special relativity.  Defaults to
     * FALSE.  New for V39. */

#define	GA_TextAttr		(GA_Dummy+40)
    /* (struct TextAttr *) Indicate the font to use for the gadget.
     * New for V42. */

#define	GA_ReadOnly		(GA_Dummy+41)
    /* (BOOL) Indicate that the gadget is read-only (non-selectable).
     * Defaults to FALSE. New for V42. */

#define	GA_Underscore		(GA_Dummy+42)
    /* (UBYTE) Underscore/escape character for keyboard shortcuts.
     * Defaults to '_' . New for V44. */

#define	GA_ActivateKey		(GA_Dummy+43)
    /* (STRPTR) Set/Get the gadgets shortcut/activation key(s)
     * Defaults to NULL. New for V44. */

#define	GA_BackFill		(GA_Dummy+44)
    /* (struct Hook *) Backfill pattern hook.
     * Defaults to NULL. New for V44. */

#define	GA_GadgetHelpText		(GA_Dummy+45)
    /* (STRPTR) **RESERVERD/PRIVATE DO NOT USE**
     * Defaults to NULL. New for V44. */

#define	GA_UserInput		(GA_Dummy+46)
    /* (BOOL) Notification tag indicates this notification is from the activite
     * gadget receiving user input - an attempt to make IDCMPUPDATE more efficient.
     * Defaults to FALSE. New for V44. */

/*****************************************************************************/

/* PROPGCLASS attributes */
#define PGA_Dummy	(TAG_USER+0x31000)
#define PGA_Freedom	(PGA_Dummy+0x0001)
    /* only one of FREEVERT or FREEHORIZ */
#define PGA_Borderless	(PGA_Dummy+0x0002)
#define PGA_HorizPot	(PGA_Dummy+0x0003)
#define PGA_HorizBody	(PGA_Dummy+0x0004)
#define PGA_VertPot	(PGA_Dummy+0x0005)
#define PGA_VertBody	(PGA_Dummy+0x0006)
#define PGA_Total	(PGA_Dummy+0x0007)
#define PGA_Visible	(PGA_Dummy+0x0008)
#define PGA_Top		(PGA_Dummy+0x0009)
/* New for V37: */
#define PGA_NewLook	(PGA_Dummy+0x000A)

/*****************************************************************************/

/* STRGCLASS attributes */
#define STRINGA_Dummy  		(TAG_USER     +0x32000)
#define STRINGA_MaxChars	(STRINGA_Dummy+0x0001)
/* Note:  There is a minor problem with Intuition when using boopsi integer
 * gadgets (which are requested by using STRINGA_LongInt).  Such gadgets
 * must not have a STRINGA_MaxChars to be bigger than 15.  Setting
 * STRINGA_MaxChars for a boopsi integer gadget will cause a mismatched
 * FreeMem() to occur.
 */

#define STRINGA_Buffer		(STRINGA_Dummy+0x0002)
#define STRINGA_UndoBuffer	(STRINGA_Dummy+0x0003)
#define STRINGA_WorkBuffer	(STRINGA_Dummy+0x0004)
#define STRINGA_BufferPos	(STRINGA_Dummy+0x0005)
#define STRINGA_DispPos		(STRINGA_Dummy+0x0006)
#define STRINGA_AltKeyMap	(STRINGA_Dummy+0x0007)
#define STRINGA_Font		(STRINGA_Dummy+0x0008)
#define STRINGA_Pens		(STRINGA_Dummy+0x0009)
#define STRINGA_ActivePens	(STRINGA_Dummy+0x000A)
#define STRINGA_EditHook	(STRINGA_Dummy+0x000B)
#define STRINGA_EditModes	(STRINGA_Dummy+0x000C)

/* booleans */
#define STRINGA_ReplaceMode	(STRINGA_Dummy+0x000D)
#define STRINGA_FixedFieldMode	(STRINGA_Dummy+0x000E)
#define STRINGA_NoFilterMode	(STRINGA_Dummy+0x000F)

#define STRINGA_Justification	(STRINGA_Dummy+0x0010)
    /* GACT_STRINGCENTER, GACT_STRINGLEFT, GACT_STRINGRIGHT */
#define STRINGA_LongVal		(STRINGA_Dummy+0x0011)
#define STRINGA_TextVal		(STRINGA_Dummy+0x0012)

#define STRINGA_ExitHelp	(STRINGA_Dummy+0x0013)
    /* STRINGA_ExitHelp is new for V37, and ignored by V36.
     * Set this if you want the gadget to exit when Help is
     * pressed.  Look for a code of 0x5F, the rawkey code for Help */

#define SG_DEFAULTMAXCHARS	(128)

/*****************************************************************************/

/* Gadget layout related attributes */
#define	LAYOUTA_Dummy 		(TAG_USER+0x38000)
#define LAYOUTA_LayoutObj	(LAYOUTA_Dummy+0x0001)
#define LAYOUTA_Spacing		(LAYOUTA_Dummy+0x0002)
#define LAYOUTA_Orientation	(LAYOUTA_Dummy+0x0003)

#define	LAYOUTA_ChildMaxWidth	(LAYOUTA_Dummy+0x0004)
    /* (BOOL) Child objects are of equal width.  Should default to TRUE for
     * gadgets with a horizontal orientation.  New for V42. */
#define	LAYOUTA_ChildMaxHeight	(LAYOUTA_Dummy+0x0005)
    /* (BOOL) Child objects are of equal height.  Should default to TRUE for
     * gadgets with a vertical orientation.  New for V42. */

/* orientation values */
#define LORIENT_NONE	0
#define LORIENT_HORIZ	1
#define LORIENT_VERT	2

/*****************************************************************************/

/* Gadget Method ID's */
#define GM_Dummy	(-1)
    /* not used for anything */

#define GM_HITTEST	(0)
    /* return GMR_GADGETHIT if you are clicked on (whether or not you
     * are disabled). */

#define GM_RENDER	(1)
    /* draw yourself, in the appropriate state */

#define GM_GOACTIVE	(2)
    /* you are now going to be fed input */

#define GM_HANDLEINPUT	(3)
    /* handle that input */

#define GM_GOINACTIVE	(4)
    /* whether or not by choice, you are done */

#define GM_HELPTEST	(5)
    /* Will you send gadget help if the mouse is at the specified coordinates?
     * See below for possible GMR_ values. */

#define GM_LAYOUT	(6)
    /* re-evaluate your size based on the GadgetInfo domain.
     * Do NOT re-render yourself yet, you will be called when it is
     * time... */

#define GM_DOMAIN	(7)
    /* Used to obtain the sizing requirements of an object.  Does not
     * require an object. */

#define GM_KEYTEST	(8)
    /* return GMR_GADGETHIT if you activation key matches (whether or not you
     * are disabled). */

#define GM_KEYGOACTIVE	(9)

#define GM_KEYGOINACTIVE	(10)

/*****************************************************************************/

/* Parameter "Messages" passed to gadget class methods	*/

/* GM_HITTEST and GM_HELPTEST send this message.
 * For GM_HITTEST, gpht_Mouse are coordinates relative to the gadget
 * select box.  For GM_HELPTEST, the coordinates are relative to
 * the gadget bounding box (which defaults to the select box).
 */
struct gpHitTest
{
    ULONG		MethodID;
    struct GadgetInfo	*gpht_GInfo;
    struct
    {
    WORD	X;
    WORD	Y;
    }			gpht_Mouse;
};

/* For GM_HITTEST, return GMR_GADGETHIT if you were indeed hit,
 * otherwise return zero.
 *
 * For GM_HELPTEST, return GMR_NOHELPHIT (zero) if you were not hit.
 * Typically, return GMR_HELPHIT if you were hit.
 * It is possible to pass a UWORD to the application via the Code field
 * of the IDCMP_GADGETHELP message.  Return GMR_HELPCODE or'd with
 * the UWORD-sized result you wish to return.
 *
 * GMR_HELPHIT yields a Code value of ((UWORD) ~0), which should
 * mean "nothing particular" to the application.
 */

#define GMR_GADGETHIT	(0x00000004)	/* GM_HITTEST hit */

#define GMR_NOHELPHIT	(0x00000000)	/* GM_HELPTEST didn't hit */
#define GMR_HELPHIT	(0xFFFFFFFF)	/* GM_HELPTEST hit, return code = ~0 */
#define GMR_HELPCODE	(0x00010000)	/* GM_HELPTEST hit, return low word as code */

/*****************************************************************************/

/* GM_RENDER	*/
struct gpRender
{
    ULONG		MethodID;
    struct GadgetInfo	*gpr_GInfo;	/* gadget context		*/
    struct RastPort	*gpr_RPort;	/* all ready for use		*/
    LONG		gpr_Redraw;	/* might be a "highlight pass"	*/
};

/* values of gpr_Redraw	*/
#define GREDRAW_UPDATE	(2)	/* incremental update, e.g. prop slider	*/
#define GREDRAW_REDRAW	(1)	/* redraw gadget	*/
#define GREDRAW_TOGGLE	(0)	/* toggle highlight, if applicable	*/

/*****************************************************************************/

/* GM_GOACTIVE, GM_HANDLEINPUT	*/
struct gpInput
{
    ULONG		MethodID;
    struct GadgetInfo	*gpi_GInfo;
    struct InputEvent	*gpi_IEvent;
    LONG		*gpi_Termination;
    struct
    {
    WORD	X;
    WORD	Y;
    }			gpi_Mouse;

    /* (V39) Pointer to TabletData structure, if this event originated
     * from a tablet which sends IESUBCLASS_NEWTABLET events, or NULL if
     * not.
     *
     * DO NOT ATTEMPT TO READ THIS FIELD UNDER INTUITION PRIOR TO V39!
     * IT WILL BE INVALID!
     */
    struct TabletData	*gpi_TabletData;
};

/* GM_HANDLEINPUT and GM_GOACTIVE  return code flags	*/
/* return GMR_MEACTIVE (0) alone if you want more input.
 * Otherwise, return ONE of GMR_NOREUSE and GMR_REUSE, and optionally
 * GMR_VERIFY.
 */
#define GMR_MEACTIVE	(0)
#define GMR_NOREUSE	(1 << 1)
#define GMR_REUSE	(1 << 2)
#define GMR_VERIFY	(1 << 3)	/* you MUST set gpi_Termination */

/* New for V37:
 * You can end activation with one of GMR_NEXTACTIVE and GMR_PREVACTIVE,
 * which instructs Intuition to activate the next or previous gadget
 * that has GFLG_TABCYCLE set.
 */
#define GMR_NEXTACTIVE	(1 << 4)
#define GMR_PREVACTIVE	(1 << 5)

/*****************************************************************************/

/* GM_GOINACTIVE */
struct gpGoInactive
{
    ULONG		MethodID;
    struct GadgetInfo	*gpgi_GInfo;

    /* V37 field only!  DO NOT attempt to read under V36! */
    ULONG		gpgi_Abort;	/* gpgi_Abort=1 if gadget was aborted
                     * by Intuition and 0 if gadget went
                     * inactive at its own request
                     */
};

/*****************************************************************************/

/* New for V39: Intuition sends GM_LAYOUT to any GREL_ gadget when
 * the gadget is added to the window (or when the window opens, if
 * the gadget was part of the NewWindow.FirstGadget or the WA_Gadgets
 * list), or when the window is resized.  Your gadget can set the
 * GA_RelSpecial property to get GM_LAYOUT events without Intuition
 * changing the interpretation of your gadget select box.  This
 * allows for completely arbitrary resizing/repositioning based on
 * window size.
 */
/* GM_LAYOUT */
struct gpLayout
{
    ULONG		MethodID;
    struct GadgetInfo	*gpl_GInfo;
    ULONG		gpl_Initial;	/* non-zero if this method was invoked
                     * during AddGList() or OpenWindow()
                     * time.  zero if this method was invoked
                     * during window resizing. */
};

/*****************************************************************************/

/* The GM_DOMAIN method is used to obtain the sizing requirements of an
 * object for a class before ever creating an object. */

/* GM_DOMAIN */
struct gpDomain
{
    ULONG		 MethodID;
    struct GadgetInfo	*gpd_GInfo;
    struct RastPort	*gpd_RPort;	/* RastPort to layout for */
    LONG		 gpd_Which;
    struct IBox		 gpd_Domain;	/* Resulting domain */
    struct TagItem	*gpd_Attrs;	/* Additional attributes */
};

#define	GDOMAIN_MINIMUM		(0)
    /* Minimum size */

#define	GDOMAIN_NOMINAL		(1)
    /* Nominal size */

#define	GDOMAIN_MAXIMUM		(2)
    /* Maximum size */

/*****************************************************************************/

/* The GM_KEYTEST method is used to determin if a key press matches an
 * object's activation key(s). */

/* GM_KEYTEST send this message.
 */
struct gpKeyTest
{
    ULONG		 MethodID;
    struct GadgetInfo	*gpkt_GInfo;
    struct IntuiMessage *gpkt_IMsg;	/* The IntuiMessage that triggered this */
    ULONG		 gpkt_VanillaKey;
};

/*****************************************************************************/

/* The GM_KEYGOACTIVE method is called to "simulate" a gadget going down.
 * A gadget should render itself in a selected state when receiving
 * this message. If the class supports this method, it must return
 * GMR_KEYACTIVE.
 *
 * If a gadget returns zero for this method, it will subsequently be
 * activated via ActivateGadget() with a NULL IEvent.
 */

struct gpKeyInput
{
    ULONG MethodID;			/* GM_KEYGOACTIVE */
    struct GadgetInfo	*gpk_GInfo;
    struct InputEvent	*gpk_IEvent;
    LONG		*gpk_Termination;
};

#define GMR_KEYACTIVE	(1 << 4)
#define GMR_KEYVERIFY	(1 << 5)	/* you MUST set gpk_Termination */

/* The GM_KEYGOINACTIVE method is called to simulate the gadget release.
 * Upon receiving this message, the gadget should do everything a
 * normal gadget release would do.
 */

struct gpKeyGoInactive
{
    ULONG MethodID;			/* GM_KEYGOINACTIVE */
    struct GadgetInfo *gpki_GInfo;
    ULONG gpki_Abort;			/* TRUE if input was aborted */
};

/*****************************************************************************/

/* Include obsolete identifiers: */
#ifndef INTUITION_IOBSOLETE_H
#include <intuition/iobsolete.h>
#endif

/*****************************************************************************/

#endif


include/gadgets/getscreenmode.h

#ifndef GADGETS_GETSCREENMODE_H
#define GADGETS_GETSCREENMODE_H
/*
**	$VER: getscreenmode.h 44.1 (19.10.1999)
**	Includes Release 44.1
**
**  Definitions for the getscreenmode.gadget BOOPSI class
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

/*****************************************************************************/

#ifndef REACTION_REACTION_H
#include <reaction/reaction.h>
#endif

#ifndef INTUITION_GADGETCLASS_H
#include <intuition/gadgetclass.h>
#endif

/*****************************************************************************/

/* Attributes defined by the getfont.gadget class
 */
#define GETSCREENMODE_Dummy				(REACTION_Dummy + 0x41000)

#define	GETSCREENMODE_TitleText			(GETSCREENMODE_Dummy+1)
    /* (STRPTR) Title of the screenmode requester (default: None) (OM_NEW, OM_SET) */

#define	GETSCREENMODE_Height			(GETSCREENMODE_Dummy+2)
    /* (WORD) Height of the screenmode requester (default: 200) (OM_NEW, OM_SET, OM_GET) */

#define	GETSCREENMODE_Width				(GETSCREENMODE_Dummy+3)
    /* (WORD) Width of the screenmode requester (default: 300) (OM_NEW, OM_SET, OM_GET) */

#define	GETSCREENMODE_LeftEdge			(GETSCREENMODE_Dummy+4)
    /* (WORD) Left edge of the screenmode requester (default: 30) (OM_NEW, OM_SET, OM_GET) */

#define	GETSCREENMODE_TopEdge			(GETSCREENMODE_Dummy+5)
    /* (WORD) Top edge of the screenmode requester (default: 20) (OM_NEW, OM_SET, OM_GET) */

#define	GETSCREENMODE_DisplayID			(GETSCREENMODE_Dummy+6)
    /* (ULONG) display id of screenmode (default: 0 (LORES_KEY)) (OM_NEW, OM_SET, OM_GET, OM_NOTIFY) */

#define	GETSCREENMODE_DisplayWidth		(GETSCREENMODE_Dummy+7)
    /* (ULONG) Display width (default: 640) (OM_NEW, OM_SET, OM_GET, OM_NOTIFY) */

#define	GETSCREENMODE_DisplayHeight		(GETSCREENMODE_Dummy+8)
    /* (ULONG) Display height (default: 200) (OM_NEW, OM_SET, OM_GET, OM_NOTIFY) */

#define	GETSCREENMODE_DisplayDepth		(GETSCREENMODE_Dummy+9)
    /* (UWORD) Display depth (default: 2) (OM_NEW, OM_SET, OM_GET, OM_NOTIFY) */

#define	GETSCREENMODE_OverscanType		(GETSCREENMODE_Dummy+10)
    /* (UWORD) Type of overscan (default: OSCAN_TEXT) (OM_NEW, OM_SET, OM_GET, OM_NOTIFY) */

#define	GETSCREENMODE_AutoScroll		(GETSCREENMODE_Dummy+11)
    /* (BOOL) Autoscroll setting(default: TRUE) (OM_NEW, OM_SET, OM_NOTIFY) */

#define	GETSCREENMODE_InfoOpened		(GETSCREENMODE_Dummy+12)
    /* (BOOL) Info window initially opened?(default: FALSE) (OM_NEW, OM_SET) */

#define	GETSCREENMODE_InfoLeftEdge		(GETSCREENMODE_Dummy+13)
    /* (WORD) Info window left edge (default: 30) (OM_NEW, OM_SET, OM_GET) */

#define	GETSCREENMODE_InfoTopEdge		(GETSCREENMODE_Dummy+14)
    /* (WORD) Info window top edge (default: 20) (OM_NEW, OM_SET, OM_GET) */

#define	GETSCREENMODE_DoWidth			(GETSCREENMODE_Dummy+15)
    /* (BOOL) Display Width gadget? (default: FALSE) (OM_NEW, OM_SET) */

#define	GETSCREENMODE_DoHeight			(GETSCREENMODE_Dummy+16)
    /* (BOOL) Display Height gadget? (default: FALSE) (OM_NEW, OM_SET) */

#define	GETSCREENMODE_DoDepth			(GETSCREENMODE_Dummy+17)
    /* (BOOL) Display Depth gadget? (default: FALSE) (OM_NEW, OM_SET) */

#define	GETSCREENMODE_DoOverscanType	(GETSCREENMODE_Dummy+18)
    /* (BOOL) Display Overscan Type gadget? (default: FALSE) (OM_NEW, OM_SET) */

#define	GETSCREENMODE_DoAutoScroll		(GETSCREENMODE_Dummy+19)
    /* (BOOL) Display AutoScroll gadget? (default: FALSE) (OM_NEW, OM_SET) */

#define	GETSCREENMODE_PropertyFlags		(GETSCREENMODE_Dummy+20)
    /* (ULONG) Must have these Property flags (default: DIPF_IS_WB) (OM_NEW, OM_SET) */

#define	GETSCREENMODE_PropertyMask		(GETSCREENMODE_Dummy+21)
    /* (ULONG) Only these should be looked at (default: DIPF_IS_WB) (OM_NEW, OM_SET) */

#define	GETSCREENMODE_MinWidth			(GETSCREENMODE_Dummy+22)
    /* (ULONG) Minimum display width to allow (default: 16) (OM_NEW, OM_SET) */

#define	GETSCREENMODE_MaxWidth			(GETSCREENMODE_Dummy+23)
    /* (ULONG) Maximum display width to allow (default: 16368) (OM_NEW, OM_SET) */

#define	GETSCREENMODE_MinHeight			(GETSCREENMODE_Dummy+24)
    /* (ULONG) Minimum display height to allow (default: 16) (OM_NEW, OM_SET) */

#define	GETSCREENMODE_MaxHeight			(GETSCREENMODE_Dummy+25)
    /* (ULONG) Maximum display height to allow (default: 16368) (OM_NEW, OM_SET) */

#define	GETSCREENMODE_MinDepth			(GETSCREENMODE_Dummy+26)
    /* (ULONG) Minimum display depth to allow (default: 1) (OM_NEW, OM_SET) */

#define	GETSCREENMODE_MaxDepth			(GETSCREENMODE_Dummy+27)
    /* (ULONG) Maximum display depth to allow (default: 24) (OM_NEW, OM_SET) */

#define	GETSCREENMODE_FilterFunc		(GETSCREENMODE_Dummy+28)
    /* (struct Hook *) Function to filter mode id's (default: None) (OM_NEW, OM_SET) */

#define	GETSCREENMODE_CustomSMList		(GETSCREENMODE_Dummy+29)
    /* (struct List *) Exec list of struct DisplayMode (default: None) (OM_NEW, OM_SET) */

/*****************************************************************************/

/*
 * getfont.gadget methods
 */
#define GSM_REQUEST	(0x610001L)

/* The GSM_REQUEST method should be called whenever you want to open
 * a screenmode requester.
 */

struct gsmRequest
{
    ULONG MethodID;				/* GSM_REQUEST */
    struct Window *gsmr_Window;	/* The window that will be locked when the requester is active.
                                If not provided, no window will be locked and no visual updating
                                of any gadgets will take place. This should be the window the gadget
                                resides in. */
};

#define RequestScreenMode(obj, win)	DoMethod(obj, GSM_REQUEST, win)

#endif /* GADGETS_GETSCREENMODE_H */


include/utility/hooks.h

#ifndef UTILITY_HOOKS_H
#define UTILITY_HOOKS_H
/*
**	$VER: hooks.h 39.2 (16.6.1993)
**	Includes Release 44.1
**
**	Callback hooks
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	All Rights Reserved
*/

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef EXEC_NODES_H
#include <exec/nodes.h>
#endif

/*****************************************************************************/

struct Hook
{
    struct MinNode h_MinNode;
    ULONG	   (*h_Entry)();	/* assembler entry point */
    ULONG	   (*h_SubEntry)();	/* often HLL entry point */
    APTR	   h_Data;		/* owner specific	 */
};

/* Useful definition for casting function pointers:
 * hook.h_SubEntry = (HOOKFUNC)AFunction
 */
typedef unsigned long (*HOOKFUNC)();

/* Hook calling conventions.
 *
 * The function pointed to by Hook.h_Entry is called with the following
 * parameters:
 *
 *	A0 - pointer to hook data structure itself
 *	A1 - pointer to parameter structure ("message")
 *	A2 - Hook specific address data ("object")
 *
 * Control will be passed to the routine h_Entry.  For many
 * High-Level Languages (HLL), this will be an assembly language
 * stub which pushes registers on the stack, does other setup,
 * and then calls the function at h_SubEntry.
 *
 * The standard C receiving code is:
 *
 *    HookFunc(struct Hook *hook, APTR object, APTR message)
 *
 * Note that register natural order differs from this convention for C
 * parameter order, which is A0,A2,A1.
 *
 * The assembly language stub for "vanilla" C parameter conventions
 * could be:
 *
 * _hookEntry:
 *	move.l	a1,-(sp)		; push message packet pointer
 *	move.l	a2,-(sp)		; push object pointer
 *	move.l	a0,-(sp)		; push hook pointer
 *	move.l	h_SubEntry(a0),a0	; fetch C entry point ...
 *	jsr	(a0)			; ... and call it
 *	lea	12(sp),sp		; fix stack
 *	rts
 *
 * With this function as your interface stub, you can write a Hook setup
 * function as:
 *
 * InitHook(struct Hook *hook, ULONG (*c_function)(), APTR userdata)
 * {
 * ULONG (*hookEntry)();
 *
 *     hook->h_Entry	= hookEntry;
 *     hook->h_SubEntry = c_function;
 *     hook->h_Data	= userdata;
 * }
 *
 * With a compiler capable of registerized parameters, such as SAS C, you
 * can put the C function in the h_Entry field directly. For example, for
 * SAS C:
 *
 *   ULONG __saveds __asm HookFunc(register __a0 struct Hook *hook,
 *				   register __a2 APTR	      object,
 *				   register __a1 APTR	      message);
 *
 */

/*****************************************************************************/

#endif /* UTILITY_HOOKS_H */


include/workbench/icon.h

#ifndef WORKBENCH_ICON_H
#define WORKBENCH_ICON_H
/*
**	$VER: icon.h 44.39 (18.9.1999)
**	Includes Release 44.1
**
**	External declarations for icon.library
**
**	Copyright © 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef GRAPHICS_VIEW_H
#include <graphics/view.h>
#endif /* !GRAPHICS_VIEW_H */

#ifndef INTUITION_IMAGECLASS_H
#include <intuition/imageclass.h>
#endif /* !INTUITION_IMAGECLASS_H */

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif /* !UTILITY_TAGITEM_H */

#ifndef DATATYPES_PICTURECLASS_H
#include <datatypes/pictureclass.h>
#endif /* !DATATYPES_PICTURECLASS_H */

#ifndef DOS_DOS_H
#include <dos/dos.h>
#endif /* !DOS_DOS_H */

/****************************************************************************/

#define ICONNAME "icon.library"

/****************************************************************************/

#define ICONA_Dummy (TAG_USER+0x9000)

/****************************************************************************/

/* Error reporting (LONG *) */
#define ICONA_ErrorCode 	(ICONA_Dummy+1)

/* Points to the tag item that caused the error (struct TagItem **). */
#define ICONA_ErrorTagItem	(ICONA_Dummy+75)

/****************************************************************************/

/* Global options for IconControlA() */

/* Screen to use for remapping Workbench icons to (struct Screen *) */
#define ICONCTRLA_SetGlobalScreen		(ICONA_Dummy+2)
#define ICONCTRLA_GetGlobalScreen		(ICONA_Dummy+3)

/* Icon color remapping precision; defaults to PRECISION_ICON (LONG) */
#define ICONCTRLA_SetGlobalPrecision		(ICONA_Dummy+4)
#define ICONCTRLA_GetGlobalPrecision		(ICONA_Dummy+5)

/* Icon frame size dimensions (struct Rectangle *) */
#define ICONCTRLA_SetGlobalEmbossRect		(ICONA_Dummy+6)
#define ICONCTRLA_GetGlobalEmbossRect		(ICONA_Dummy+7)

/* Render image without frame (BOOL) */
#define ICONCTRLA_SetGlobalFrameless		(ICONA_Dummy+8)
#define ICONCTRLA_GetGlobalFrameless		(ICONA_Dummy+9)

/* Enable NewIcons support (BOOL) */
#define ICONCTRLA_SetGlobalNewIconsSupport	(ICONA_Dummy+10)
#define ICONCTRLA_GetGlobalNewIconsSupport	(ICONA_Dummy+11)

/* Enable color icon support (BOOL) */
#define ICONCTRLA_SetGlobalColorIconSupport	(ICONA_Dummy+77)
#define ICONCTRLA_GetGlobalColorIconSupport	(ICONA_Dummy+78)

/* Set/Get the hook to be called when identifying a file (struct Hook *) */
#define ICONCTRLA_SetGlobalIdentifyHook		(ICONA_Dummy+12)
#define ICONCTRLA_GetGlobalIdentifyHook		(ICONA_Dummy+13)

/* Set/get the maximum length of a file/drawer name supported
 * by icon.library (LONG).
 */
#define ICONCTRLA_SetGlobalMaxNameLength	(ICONA_Dummy+67)
#define ICONCTRLA_GetGlobalMaxNameLength	(ICONA_Dummy+68)

/****************************************************************************/

/* Per icon local options for IconControlA() */

/* Get the icon rendering masks (PLANEPTR) */
#define ICONCTRLA_GetImageMask1		(ICONA_Dummy+14)
#define ICONCTRLA_GetImageMask2		(ICONA_Dummy+15)

/* Transparent image color; set to -1 if opaque */
#define ICONCTRLA_SetTransparentColor1	(ICONA_Dummy+16)
#define ICONCTRLA_GetTransparentColor1	(ICONA_Dummy+17)
#define ICONCTRLA_SetTransparentColor2	(ICONA_Dummy+18)
#define ICONCTRLA_GetTransparentColor2	(ICONA_Dummy+19)

/* Image color palette (struct ColorRegister *) */
#define ICONCTRLA_SetPalette1		(ICONA_Dummy+20)
#define ICONCTRLA_GetPalette1		(ICONA_Dummy+21)
#define ICONCTRLA_SetPalette2		(ICONA_Dummy+22)
#define ICONCTRLA_GetPalette2		(ICONA_Dummy+23)

/* Size of image color palette (LONG) */
#define ICONCTRLA_SetPaletteSize1	(ICONA_Dummy+24)
#define ICONCTRLA_GetPaletteSize1	(ICONA_Dummy+25)
#define ICONCTRLA_SetPaletteSize2	(ICONA_Dummy+26)
#define ICONCTRLA_GetPaletteSize2	(ICONA_Dummy+27)

/* Image data; one by per pixel (UBYTE *) */
#define ICONCTRLA_SetImageData1		(ICONA_Dummy+28)
#define ICONCTRLA_GetImageData1		(ICONA_Dummy+29)
#define ICONCTRLA_SetImageData2		(ICONA_Dummy+30)
#define ICONCTRLA_GetImageData2		(ICONA_Dummy+31)

/* Render image without frame (BOOL) */
#define ICONCTRLA_SetFrameless		(ICONA_Dummy+32)
#define ICONCTRLA_GetFrameless		(ICONA_Dummy+33)

/* Enable NewIcons support (BOOL) */
#define ICONCTRLA_SetNewIconsSupport	(ICONA_Dummy+34)
#define ICONCTRLA_GetNewIconsSupport	(ICONA_Dummy+35)

/* Icon aspect ratio (UBYTE *) */
#define ICONCTRLA_SetAspectRatio	(ICONA_Dummy+36)
#define ICONCTRLA_GetAspectRatio	(ICONA_Dummy+37)

/* Icon dimensions; valid only for palette mapped icon images (LONG) */
#define ICONCTRLA_SetWidth		(ICONA_Dummy+38)
#define ICONCTRLA_GetWidth		(ICONA_Dummy+39)
#define ICONCTRLA_SetHeight		(ICONA_Dummy+40)
#define ICONCTRLA_GetHeight		(ICONA_Dummy+41)

/* Check whether the icon is palette mapped (LONG *). */
#define ICONCTRLA_IsPaletteMapped	(ICONA_Dummy+42)

/* Get the screen the icon is attached to (struct Screen **). */
#define ICONCTRLA_GetScreen		(ICONA_Dummy+43)

/* Check whether the icon has a real select image (LONG *). */
#define ICONCTRLA_HasRealImage2		(ICONA_Dummy+44)

/* Check whether the icon is of the NewIcon type (LONG *). */
#define ICONCTRLA_IsNewIcon		(ICONA_Dummy+79)

/* Check whether this icon was allocated by icon.library
 * or if consists solely of a statically allocated
 * struct DiskObject. (LONG *).
 */
#define ICONCTRLA_IsNativeIcon		(ICONA_Dummy+80)

/****************************************************************************/

/* Icon aspect ratio is not known. */
#define ICON_ASPECT_RATIO_UNKNOWN (0)

/* Pack the aspect ratio into a single byte. */
#define PACK_ICON_ASPECT_RATIO(num,den) (((num) << 4) | (den))

/* Unpack the aspect ratio stored in a single byte. */
#define UNPACK_ICON_ASPECT_RATIO(v,num,den)	\
    do					\
    {					\
        num	= (((v) >> 4) & 15);	\
        den	= ( (v)       & 15);	\
    }					\
    while(0)

/****************************************************************************/

/* Tags for use with GetIconTagList() */

/* Default icon type to retrieve (LONG) */
#define ICONGETA_GetDefaultType		(ICONA_Dummy+45)

/* Retrieve default icon for the given name (STRPTR) */
#define ICONGETA_GetDefaultName		(ICONA_Dummy+46)

/* Return a default icon if the requested icon
 * file cannot be found (BOOL).
 */
#define ICONGETA_FailIfUnavailable	(ICONA_Dummy+47)

/* If possible, retrieve a palette mapped icon (BOOL). */
#define ICONGETA_GetPaletteMappedIcon	(ICONA_Dummy+48)

/* Set if the icon returned is a default icon (BOOL *). */
#define ICONGETA_IsDefaultIcon		(ICONA_Dummy+49)

/* Remap the icon to the default screen, if possible (BOOL). */
#define ICONGETA_RemapIcon		(ICONA_Dummy+50)

/* Generate icon image masks (BOOL). */
#define ICONGETA_GenerateImageMasks	(ICONA_Dummy+51)

/* Label text to be assigned to the icon (STRPTR). */
#define ICONGETA_Label			(ICONA_Dummy+52)

/* Screen to remap the icon to (struct Screen *). */
#define ICONGETA_Screen			(ICONA_Dummy+69)

/****************************************************************************/

/* Tags for use with PutIconTagList() */

/* Notify Workbench of the icon being written (BOOL) */
#define ICONPUTA_NotifyWorkbench	(ICONA_Dummy+53)

/* Store icon as the default for this type (LONG) */
#define ICONPUTA_PutDefaultType		(ICONA_Dummy+54)

/* Store icon as a default for the given name (STRPTR) */
#define ICONPUTA_PutDefaultName		(ICONA_Dummy+55)

/* When storing a palette mapped icon, don't save the
 * the original planar icon image with the file. Replace
 * it with a tiny replacement image.
 */
#define ICONPUTA_DropPlanarIconImage	(ICONA_Dummy+56)

/* Don't write the chunky icon image data to disk. */
#define ICONPUTA_DropChunkyIconImage	(ICONA_Dummy+57)

/* Don't write the NewIcons tool types to disk. */
#define ICONPUTA_DropNewIconToolTypes	(ICONA_Dummy+58)

/* If this tag is enabled, the writer will examine the
 * icon image data to find out whether it can compress
 * it more efficiently. This may take extra time and
 * is not generally recommended.
 */
#define ICONPUTA_OptimizeImageSpace	(ICONA_Dummy+59)

/* Don't write the entire icon file back to disk,
 * only change the do->do_CurrentX/do->do_CurrentY
 * members.
 */
#define ICONPUTA_OnlyUpdatePosition	(ICONA_Dummy+72)

/* Before writing a palette mapped icon back to disk,
 * icon.library will make sure that the original
 * planar image data is stored in the file. If you
 * don't want that to happen, set this option to
 * FALSE. This will allow you to change the planar icon
 * image data written back to disk.
 */
#define ICONPUTA_PreserveOldIconImages	(ICONA_Dummy+84)

/****************************************************************************/

/* For use with the file identification hook. */

struct IconIdentifyMsg
{
    /* Libraries that are already opened for your use. */
    struct Library *	iim_SysBase;
    struct Library *	iim_DOSBase;
    struct Library *	iim_UtilityBase;
    struct Library *	iim_IconBase;

    /* File context information. */
    BPTR			iim_FileLock;	/* Lock on the object to return an icon for. */
    BPTR			iim_ParentLock;	/* Lock on the object's parent directory, if available. */
    struct FileInfoBlock *	iim_FIB;	/* Already initialized for you. */
    BPTR			iim_FileHandle;	/* If non-NULL, pointer to the file to examine,
                         * positioned right at the first byte, ready
                         * for you to use.
                         */
    struct TagItem *	iim_Tags;	/* Tags passed to GetIconTagList(). */
};

/****************************************************************************/

/* Tags for use with DupDiskObjectA() */

/* Duplicate do_DrawerData */
#define ICONDUPA_DuplicateDrawerData	(ICONA_Dummy+60)

/* Duplicate the Image structures. */
#define ICONDUPA_DuplicateImages	(ICONA_Dummy+61)

/* Duplicate the image data (Image->ImageData) itself. */
#define ICONDUPA_DuplicateImageData	(ICONA_Dummy+62)

/* Duplicate the default tool. */
#define ICONDUPA_DuplicateDefaultTool	(ICONA_Dummy+63)

/* Duplicate the tool types list. */
#define ICONDUPA_DuplicateToolTypes	(ICONA_Dummy+64)

/* Duplicate the tool window. */
#define ICONDUPA_DuplicateToolWindow	(ICONA_Dummy+65)

/* If the icon to be duplicated is in fact a palette mapped
 * icon which has never been set up to be displayed on the
 * screen, turn the duplicate into that palette mapped icon.
 */
#define ICONDUPA_ActivateImageData	(ICONA_Dummy+82)

/****************************************************************************/

/* Tags for use with DrawIconStateA() and GetIconRectangleA(). */

/* Drawing information to use (struct DrawInfo *). */
#define ICONDRAWA_DrawInfo		(ICONA_Dummy+66)

/* Draw the icon without the surrounding frame (BOOL). */
#define ICONDRAWA_Frameless		(ICONA_Dummy+70)

/* Erase the background before drawing a frameless icon (BOOL). */
#define ICONDRAWA_EraseBackground	(ICONA_Dummy+71)

/* Draw the icon without the surrounding border and frame (BOOL). */
#define ICONDRAWA_Borderless		(ICONA_Dummy+83)

/****************************************************************************/

/* Reserved tags; don't use! */
#define ICONA_Reserved1	(ICONA_Dummy+73)
#define ICONA_Reserved2	(ICONA_Dummy+74)
#define ICONA_Reserved3 (ICONA_Dummy+76)
#define ICONA_Reserved4 (ICONA_Dummy+81)
#define ICONA_Reserved5 (ICONA_Dummy+85)
#define ICONA_Reserved6 (ICONA_Dummy+86)
#define ICONA_Reserved7 (ICONA_Dummy+87)
#define ICONA_Reserved8 (ICONA_Dummy+88)

/****************************************************************************/

#define ICONA_LAST_TAG (ICONA_Dummy+88)

/****************************************************************************/

#endif  /* !WORKBENCH_ICON_H */


include/prefs/icontrol.h

#ifndef PREFS_ICONTROL_H
#define PREFS_ICONTROL_H
/*
**	$VER: icontrol.h 39.1 (1.10.1992)
**	Includes Release 44.1
**
**	File format for intuition control preferences
**
**	(C) Copyright 1991-1999 Amiga, Inc.
**	All Rights Reserved
*/

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef LIBRARIES_IFFPARSE_H
#include <libraries/iffparse.h>
#endif

/*****************************************************************************/

#define ID_ICTL MAKE_ID('I','C','T','L')

struct IControlPrefs
{
    LONG  ic_Reserved[4];	/* System reserved		*/
    UWORD ic_TimeOut;		/* Verify timeout		*/
    WORD  ic_MetaDrag;		/* Meta drag mouse event	*/
    ULONG ic_Flags;		/* IControl flags (see below)	*/
    UBYTE ic_WBtoFront;		/* CKey: WB to front		*/
    UBYTE ic_FrontToBack;	/* CKey: front screen to back	*/
    UBYTE ic_ReqTrue;		/* CKey: Requester TRUE		*/
    UBYTE ic_ReqFalse;		/* CKey: Requester FALSE	*/
};

/* flags for IControlPrefs.ic_Flags */
#define ICB_COERCE_COLORS 0
#define ICB_COERCE_LACE   1
#define ICB_STRGAD_FILTER 2
#define ICB_MENUSNAP	  3
#define ICB_MODEPROMOTE   4

#define ICF_COERCE_COLORS (1<<0)
#define ICF_COERCE_LACE   (1<<1)
#define ICF_STRGAD_FILTER (1<<2)
#define ICF_MENUSNAP	  (1<<3)
#define ICF_MODEPROMOTE   (1<<4)

/*****************************************************************************/

#endif /* PREFS_ICONTROL_H */


include/devices/inputevent.h

#ifndef DEVICES_INPUTEVENT_H
#define DEVICES_INPUTEVENT_H
/*
**	$VER: inputevent.h 36.10 (26.6.1992)
**	Includes Release 44.1
**
**	input event definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef DEVICES_TIMER_H
#include <devices/timer.h>
#endif

#ifndef UTILITY_HOOKS_H
#include <utility/hooks.h>
#endif

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

/*----- constants --------------------------------------------------*/

/*  --- InputEvent.ie_Class --- */
/* A NOP input event */
#define IECLASS_NULL			0x00
/* A raw keycode from the keyboard device */
#define IECLASS_RAWKEY			0x01
/* The raw mouse report from the game port device */
#define IECLASS_RAWMOUSE		0x02
/* A private console event */
#define IECLASS_EVENT			0x03
/* A Pointer Position report */
#define IECLASS_POINTERPOS		0x04
/* A timer event */
#define IECLASS_TIMER			0x06
/* select button pressed down over a Gadget (address in ie_EventAddress) */
#define IECLASS_GADGETDOWN		0x07
/* select button released over the same Gadget (address in ie_EventAddress) */
#define IECLASS_GADGETUP		0x08
/* some Requester activity has taken place.  See Codes REQCLEAR and REQSET */
#define IECLASS_REQUESTER		0x09
/* this is a Menu Number transmission (Menu number is in ie_Code) */
#define IECLASS_MENULIST		0x0A
/* User has selected the active Window's Close Gadget */
#define IECLASS_CLOSEWINDOW		0x0B
/* this Window has a new size */
#define IECLASS_SIZEWINDOW		0x0C
/* the Window pointed to by ie_EventAddress needs to be refreshed */
#define IECLASS_REFRESHWINDOW		0x0D
/* new preferences are available */
#define IECLASS_NEWPREFS		0x0E
/* the disk has been removed */
#define IECLASS_DISKREMOVED		0x0F
/* the disk has been inserted */
#define IECLASS_DISKINSERTED		0x10
/* the window is about to be been made active */
#define IECLASS_ACTIVEWINDOW		0x11
/* the window is about to be made inactive */
#define IECLASS_INACTIVEWINDOW		0x12
/* extended-function pointer position report (V36) */
#define IECLASS_NEWPOINTERPOS		0x13
/* Help key report during Menu session (V36) */
#define IECLASS_MENUHELP		0x14
/* the Window has been modified with move, size, zoom, or change (V36) */
#define	IECLASS_CHANGEWINDOW		0x15

/* the last class */
#define IECLASS_MAX			0x15

/*  --- InputEvent.ie_SubClass --- */
/*  IECLASS_NEWPOINTERPOS */
/*	like IECLASS_POINTERPOS */
#define IESUBCLASS_COMPATIBLE	0x00
/*	ie_EventAddress points to struct IEPointerPixel */
#define IESUBCLASS_PIXEL	0x01
/*	ie_EventAddress points to struct IEPointerTablet */
#define IESUBCLASS_TABLET	0x02
/*	ie_EventAddress points to struct IENewTablet */
#define IESUBCLASS_NEWTABLET	   0x03

/* pointed to by ie_EventAddress for IECLASS_NEWPOINTERPOS,
 * and IESUBCLASS_PIXEL.
 *
 * You specify a screen and pixel coordinates in that screen
 * at which you'd like the mouse to be positioned.
 * Intuition will try to oblige, but there will be restrictions
 * to positioning the pointer over offscreen pixels.
 *
 * IEQUALIFIER_RELATIVEMOUSE is supported for IESUBCLASS_PIXEL.
 */

struct IEPointerPixel	{
    struct Screen	*iepp_Screen;	/* pointer to an open screen */
    struct {				/* pixel coordinates in iepp_Screen */
    WORD	X;
    WORD	Y;
    }			iepp_Position;
};

/* pointed to by ie_EventAddress for IECLASS_NEWPOINTERPOS,
 * and IESUBCLASS_TABLET.
 *
 * You specify a range of values and a value within the range
 * independently for each of X and Y (the minimum value of
 * the ranges is always normalized to 0).
 *
 * Intuition will position the mouse proportionally within its
 * natural mouse position rectangle limits.
 *
 * IEQUALIFIER_RELATIVEMOUSE is not supported for IESUBCLASS_TABLET.
 */
struct IEPointerTablet	{
    struct {
    UWORD	X;
    UWORD	Y;
    }			iept_Range;	/* 0 is min, these are max	*/
    struct {
    UWORD	X;
    UWORD	Y;
    }			iept_Value;	/* between 0 and iept_Range	*/

    WORD		iept_Pressure;	/* -128 to 127 (unused, set to 0)  */
};

/* The ie_EventAddress of an IECLASS_NEWPOINTERPOS event of subclass
 * IESUBCLASS_NEWTABLET points at an IENewTablet structure.
 *
 *
 * IEQUALIFIER_RELATIVEMOUSE is not supported for IESUBCLASS_NEWTABLET.
 */

struct IENewTablet
{
    /* Pointer to a hook you wish to be called back through, in
     * order to handle scaling.  You will be provided with the
     * width and height you are expected to scale your tablet
     * to, perhaps based on some user preferences.
     * If NULL, the tablet's specified range will be mapped directly
     * to that width and height for you, and you will not be
     * called back.
     */
    struct Hook *ient_CallBack;

    /* Post-scaling coordinates and fractional coordinates.
     * DO NOT FILL THESE IN AT THE TIME THE EVENT IS WRITTEN!
     * Your driver will be called back and provided information
     * about the width and height of the area to scale the
     * tablet into.  It should scale the tablet coordinates
     * (perhaps based on some preferences controlling aspect
     * ratio, etc.) and place the scaled result into these
     * fields.	The ient_ScaledX and ient_ScaledY fields are
     * in screen-pixel resolution, but the origin ( [0,0]-point )
     * is not defined.	The ient_ScaledXFraction and
     * ient_ScaledYFraction fields represent sub-pixel position
     * information, and should be scaled to fill a UWORD fraction.
     */
    UWORD ient_ScaledX, ient_ScaledY;
    UWORD ient_ScaledXFraction, ient_ScaledYFraction;

    /* Current tablet coordinates along each axis: */
    ULONG ient_TabletX, ient_TabletY;

    /* Tablet range along each axis.  For example, if ient_TabletX
     * can take values 0-999, ient_RangeX should be 1000.
     */
    ULONG ient_RangeX, ient_RangeY;

    /* Pointer to tag-list of additional tablet attributes.
     * See <intuition/intuition.h> for the tag values.
     */
    struct TagItem *ient_TagList;
};

/*  --- InputEvent.ie_Code --- */
/*  IECLASS_RAWKEY */
#define IECODE_UP_PREFIX		0x80
#define IECODE_KEY_CODE_FIRST		0x00
#define IECODE_KEY_CODE_LAST		0x77
#define IECODE_COMM_CODE_FIRST		0x78
#define IECODE_COMM_CODE_LAST		0x7F

/*  IECLASS_ANSI */
#define IECODE_C0_FIRST			0x00
#define IECODE_C0_LAST			0x1F
#define IECODE_ASCII_FIRST		0x20
#define IECODE_ASCII_LAST		0x7E
#define IECODE_ASCII_DEL		0x7F
#define IECODE_C1_FIRST			0x80
#define IECODE_C1_LAST			0x9F
#define IECODE_LATIN1_FIRST		0xA0
#define IECODE_LATIN1_LAST		0xFF

/*  IECLASS_RAWMOUSE */
#define IECODE_LBUTTON			0x68	/* also uses IECODE_UP_PREFIX */
#define IECODE_RBUTTON			0x69
#define IECODE_MBUTTON			0x6A
#define IECODE_NOBUTTON			0xFF

/*  IECLASS_EVENT (V36) */
#define IECODE_NEWACTIVE		0x01	/* new active input window */
#define IECODE_NEWSIZE			0x02	/* resize of window */
#define IECODE_REFRESH			0x03	/* refresh of window */

/*  IECLASS_REQUESTER */
/*	broadcast when the first Requester (not subsequent ones) opens up in */
/*	the Window */
#define IECODE_REQSET			0x01
/*	broadcast when the last Requester clears out of the Window */
#define IECODE_REQCLEAR			0x00

/*  --- InputEvent.ie_Qualifier --- */
#define IEQUALIFIER_LSHIFT		0x0001
#define IEQUALIFIER_RSHIFT		0x0002
#define IEQUALIFIER_CAPSLOCK		0x0004
#define IEQUALIFIER_CONTROL		0x0008
#define IEQUALIFIER_LALT		0x0010
#define IEQUALIFIER_RALT		0x0020
#define IEQUALIFIER_LCOMMAND		0x0040
#define IEQUALIFIER_RCOMMAND		0x0080
#define IEQUALIFIER_NUMERICPAD		0x0100
#define IEQUALIFIER_REPEAT		0x0200
#define IEQUALIFIER_INTERRUPT		0x0400
#define IEQUALIFIER_MULTIBROADCAST	0x0800
#define IEQUALIFIER_MIDBUTTON		0x1000
#define IEQUALIFIER_RBUTTON		0x2000
#define IEQUALIFIER_LEFTBUTTON		0x4000
#define IEQUALIFIER_RELATIVEMOUSE	0x8000

#define IEQUALIFIERB_LSHIFT		0
#define IEQUALIFIERB_RSHIFT		1
#define IEQUALIFIERB_CAPSLOCK		2
#define IEQUALIFIERB_CONTROL		3
#define IEQUALIFIERB_LALT		4
#define IEQUALIFIERB_RALT		5
#define IEQUALIFIERB_LCOMMAND		6
#define IEQUALIFIERB_RCOMMAND		7
#define IEQUALIFIERB_NUMERICPAD		8
#define IEQUALIFIERB_REPEAT		9
#define IEQUALIFIERB_INTERRUPT		10
#define IEQUALIFIERB_MULTIBROADCAST	11
#define IEQUALIFIERB_MIDBUTTON		12
#define IEQUALIFIERB_RBUTTON		13
#define IEQUALIFIERB_LEFTBUTTON		14
#define IEQUALIFIERB_RELATIVEMOUSE	15

/*----- InputEvent -------------------------------------------------*/

struct InputEvent {
    struct  InputEvent *ie_NextEvent;	/* the chronologically next event */
    UBYTE   ie_Class;			/* the input event class */
    UBYTE   ie_SubClass;		/* optional subclass of the class */
    UWORD   ie_Code;			/* the input event code */
    UWORD   ie_Qualifier;		/* qualifiers in effect for the event*/
    union {
    struct {
        WORD    ie_x;		/* the pointer position for the event*/
        WORD    ie_y;
    } ie_xy;
    APTR	ie_addr;		/* the event address */
    struct {
        UBYTE   ie_prev1DownCode;	/* previous down keys for dead */
        UBYTE   ie_prev1DownQual;	/*   key translation: the ie_Code */
        UBYTE   ie_prev2DownCode;	/*   & low byte of ie_Qualifier for */
        UBYTE   ie_prev2DownQual;	/*   last & second last down keys */
    } ie_dead;
    } ie_position;
    struct timeval ie_TimeStamp;	/* the system tick at the event */
};

#define	ie_X			ie_position.ie_xy.ie_x
#define	ie_Y			ie_position.ie_xy.ie_y
#define	ie_EventAddress		ie_position.ie_addr
#define	ie_Prev1DownCode	ie_position.ie_dead.ie_prev1DownCode
#define	ie_Prev1DownQual	ie_position.ie_dead.ie_prev1DownQual
#define	ie_Prev2DownCode	ie_position.ie_dead.ie_prev2DownCode
#define	ie_Prev2DownQual	ie_position.ie_dead.ie_prev2DownQual

#endif	/* DEVICES_INPUTEVENT_H */


include/intuition/imageclass.h

#ifndef INTUITION_IMAGECLASS_H
#define INTUITION_IMAGECLASS_H
/*
**	$VER: imageclass.h 44.1 (19.10.1999)
**	Includes Release 44.1
**
**	definitions for the system image classes
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

/******************************************************/

#ifndef INTUITION_INTUITION_H
#include <intuition/intuition.h>
#endif

/*
 * NOTE:  <intuition/iobsolete.h> is included at the END of this file!
 */

#define CUSTOMIMAGEDEPTH	(-1)
/* if image.Depth is this, it's a new Image class object */

/* some convenient macros and casts */
#define GADGET_BOX( g )	( (struct IBox *) &((struct Gadget *)(g))->LeftEdge )
#define IM_BOX( im )	( (struct IBox *) &((struct Image *)(im))->LeftEdge )
#define IM_FGPEN( im )	( (im)->PlanePick )
#define IM_BGPEN( im )	( (im)->PlaneOnOff )

/******************************************************/
#define IA_Dummy		(TAG_USER + 0x20000)
#define IA_Left			(IA_Dummy + 0x01)
#define IA_Top			(IA_Dummy + 0x02)
#define IA_Width		(IA_Dummy + 0x03)
#define IA_Height		(IA_Dummy + 0x04)
#define IA_FGPen		(IA_Dummy + 0x05)
            /* IA_FGPen also means "PlanePick"	*/
#define IA_BGPen		(IA_Dummy + 0x06)
            /* IA_BGPen also means "PlaneOnOff"	*/
#define IA_Data			(IA_Dummy + 0x07)
            /* bitplanes, for classic image,
             * other image classes may use it for other things
             */
#define IA_LineWidth		(IA_Dummy + 0x08)
#define IA_Pens			(IA_Dummy + 0x0E)
            /* pointer to UWORD pens[],
             * ala DrawInfo.Pens, MUST be
             * terminated by ~0.  Some classes can
             * choose to have this, or SYSIA_DrawInfo,
             * or both.
             */
#define IA_Resolution		(IA_Dummy + 0x0F)
            /* packed uwords for x/y resolution into a longword
             * ala DrawInfo.Resolution
             */

/**** see class documentation to learn which	*****/
/**** classes recognize these			*****/
#define IA_APattern		(IA_Dummy + 0x10)
#define IA_APatSize		(IA_Dummy + 0x11)
#define IA_Mode			(IA_Dummy + 0x12)
#define IA_Font			(IA_Dummy + 0x13)
#define IA_Outline		(IA_Dummy + 0x14)
#define IA_Recessed		(IA_Dummy + 0x15)
#define IA_DoubleEmboss		(IA_Dummy + 0x16)
#define IA_EdgesOnly		(IA_Dummy + 0x17)

/**** "sysiclass" attributes			*****/
#define SYSIA_Size		(IA_Dummy + 0x0B)
            /* #define's below		*/
#define SYSIA_Depth		(IA_Dummy + 0x0C)
            /* this is unused by Intuition.  SYSIA_DrawInfo
             * is used instead for V36
             */
#define SYSIA_Which		(IA_Dummy + 0x0D)
            /* see #define's below	*/
#define SYSIA_DrawInfo		(IA_Dummy + 0x18)
            /* pass to sysiclass, please */

/*****	obsolete: don't use these, use IA_Pens	*****/
#define SYSIA_Pens		IA_Pens
#define IA_ShadowPen		(IA_Dummy + 0x09)
#define IA_HighlightPen		(IA_Dummy + 0x0A)

/* New for V39: */
#define SYSIA_ReferenceFont	(IA_Dummy + 0x19)
            /* Font to use as reference for scaling
             * certain sysiclass images
             */
#define IA_SupportsDisable	(IA_Dummy + 0x1a)
            /* By default, Intuition ghosts gadgets itself,
             * instead of relying on IDS_DISABLED or
             * IDS_SELECTEDDISABLED.  An imageclass that
             * supports these states should return this attribute
             * as TRUE.  You cannot set or clear this attribute,
             * however.
             */

#define IA_FrameType		(IA_Dummy + 0x1b)
            /* Starting with V39, FrameIClass recognizes
             * several standard types of frame.  Use one
             * of the FRAME_ specifiers below.	Defaults
             * to FRAME_DEFAULT.
             */

#define IA_Underscore		(IA_Dummy + 0x1c)
            /* V44, Indicate underscore keyboard shortcut for image labels.
             * (UBYTE) Defaults to '_'
             */

#define IA_Scalable			(IA_Dummy + 0x1d)
            /* V44, Attribute indicates this image is allowed
             * to/can scale its rendering.
             * (BOOL) Defaults to FALSE.
             */

#define IA_ActivateKey			(IA_Dummy + 0x1e)
            /* V44, Used to get an underscored label shortcut.
             * Useful for labels attached to string gadgets.
             * (UBYTE) Defaults to NULL.
             */

#define IA_Screen			(IA_Dummy + 0x1f)
            /* V44 Screen pointer, may be useful/required by certain classes.
             * (struct Screen *)
             */

#define IA_Precision			(IA_Dummy + 0x20)
            /* V44 Precision value, typically pen precision but may be
             * used for similar custom purposes.
             * (ULONG)
             */

/** next attribute: (IA_Dummy + 0x21)	**/
/*************************************************/

/* data values for SYSIA_Size	*/
#define SYSISIZE_MEDRES	(0)
#define SYSISIZE_LOWRES	(1)
#define SYSISIZE_HIRES	(2)

/*
 * SYSIA_Which tag data values:
 * Specifies which system gadget you want an image for.
 * Some numbers correspond to internal Intuition #defines
 */
#define DEPTHIMAGE	(0x00L)	/* Window depth gadget image */
#define ZOOMIMAGE	(0x01L)	/* Window zoom gadget image */
#define SIZEIMAGE	(0x02L)	/* Window sizing gadget image */
#define CLOSEIMAGE	(0x03L)	/* Window close gadget image */
#define SDEPTHIMAGE	(0x05L)	/* Screen depth gadget image */
#define LEFTIMAGE	(0x0AL)	/* Left-arrow gadget image */
#define UPIMAGE		(0x0BL)	/* Up-arrow gadget image */
#define RIGHTIMAGE	(0x0CL)	/* Right-arrow gadget image */
#define DOWNIMAGE	(0x0DL)	/* Down-arrow gadget image */
#define CHECKIMAGE	(0x0EL)	/* GadTools checkbox image */
#define MXIMAGE		(0x0FL)	/* GadTools mutual exclude "button" image */
/* New for V39: */
#define	MENUCHECK	(0x10L)	/* Menu checkmark image */
#define AMIGAKEY	(0x11L)	/* Menu Amiga-key image */

/* Data values for IA_FrameType (recognized by FrameIClass)
 *
 * FRAME_DEFAULT:  The standard V37-type frame, which has
 *	thin edges.
 * FRAME_BUTTON:  Standard button gadget frames, having thicker
 *	sides and nicely edged corners.
 * FRAME_RIDGE:  A ridge such as used by standard string gadgets.
 *	You can recess the ridge to get a groove image.
 * FRAME_ICONDROPBOX: A broad ridge which is the standard imagery
 *	for areas in AppWindows where icons may be dropped.
 */

#define FRAME_DEFAULT		0
#define FRAME_BUTTON		1
#define FRAME_RIDGE		2
#define FRAME_ICONDROPBOX	3

/* image message id's	*/
#define    IM_DRAW	0x202L	/* draw yourself, with "state" */
#define    IM_HITTEST	0x203L	/* return TRUE if click hits image	*/
#define    IM_ERASE	0x204L	/* erase yourself */
#define    IM_MOVE	0x205L	/* draw new and erase old, smoothly	*/

#define    IM_DRAWFRAME	0x206L	/* draw with specified dimensions */
#define    IM_FRAMEBOX	0x207L	/* get recommended frame around some box*/
#define    IM_HITFRAME	0x208L	/* hittest with dimensions */
#define    IM_ERASEFRAME 0x209L	/* erase with dimensions */
#define    IM_DOMAINFRAME	0x20AL  /* query image for its domain info (V44) */

/* image draw states or styles, for IM_DRAW */
/* Note that they have no bitwise meanings (unfortunately) */
#define    IDS_NORMAL		(0L)
#define    IDS_SELECTED		(1L)	/* for selected gadgets	    */
#define    IDS_DISABLED		(2L)	/* for disabled gadgets	    */
#define	   IDS_BUSY		(3L)	/* for future functionality */
#define    IDS_INDETERMINATE	(4L)	/* for future functionality */
#define    IDS_INACTIVENORMAL	(5L)	/* normal, in inactive window border */
#define    IDS_INACTIVESELECTED	(6L)	/* selected, in inactive border */
#define    IDS_INACTIVEDISABLED	(7L)	/* disabled, in inactive border */
#define	   IDS_SELECTEDDISABLED (8L)	/* disabled and selected    */

/* oops, please forgive spelling error by jimm */
#define IDS_INDETERMINANT IDS_INDETERMINATE

/* IM_FRAMEBOX	*/
struct impFrameBox {
    ULONG		MethodID;
    struct IBox	*imp_ContentsBox;	/* input: relative box of contents */
    struct IBox	*imp_FrameBox;		/* output: rel. box of encl frame  */
    struct DrawInfo	*imp_DrInfo;	/* NB: May be NULL */
    ULONG	imp_FrameFlags;
};

#define FRAMEF_SPECIFY	(1<<0)	/* Make do with the dimensions of FrameBox
                 * provided.
                 */

/* IM_DRAW, IM_DRAWFRAME	*/
struct impDraw
{
    ULONG		MethodID;
    struct RastPort	*imp_RPort;
    struct
    {
    WORD	X;
    WORD	Y;
    }			imp_Offset;

    ULONG		imp_State;
    struct DrawInfo	*imp_DrInfo;	/* NB: May be NULL */

    /* these parameters only valid for IM_DRAWFRAME */
    struct
    {
    WORD	Width;
    WORD	Height;
    }			imp_Dimensions;
};

/* IM_ERASE, IM_ERASEFRAME	*/
/* NOTE: This is a subset of impDraw	*/
struct impErase
{
    ULONG		MethodID;
    struct RastPort	*imp_RPort;
    struct
    {
    WORD	X;
    WORD	Y;
    }			imp_Offset;

    /* these parameters only valid for IM_ERASEFRAME */
    struct
    {
    WORD	Width;
    WORD	Height;
    }			imp_Dimensions;
};

/* IM_HITTEST, IM_HITFRAME	*/
struct impHitTest
{
    ULONG		MethodID;
    struct
    {
    WORD	X;
    WORD	Y;
    }			imp_Point;

    /* these parameters only valid for IM_HITFRAME */
    struct
    {
    WORD	Width;
    WORD	Height;
    }			imp_Dimensions;
};

/* The IM_DOMAINFRAME method is used to obtain the sizing
 * requirements of an image object within a layout group.
 */

/* IM_DOMAINFRAME */
struct impDomainFrame
{
    ULONG		 MethodID;
    struct DrawInfo	*imp_DrInfo;	/* DrawInfo */
    struct RastPort	*imp_RPort;	/* RastPort to layout for */
    LONG	 	 imp_Which;	/* what size - min/nominal/max */
    struct IBox		 imp_Domain;	/* Resulting domain */
    struct TagItem	*imp_Attrs;	/* Additional attributes */
};

/* Accepted vales for imp_Which.
 */
#define IDOMAIN_MINIMUM		(0)
#define IDOMAIN_NOMINAL		(1)
#define IDOMAIN_MAXIMUM		(2)

/* Include obsolete identifiers: */
#ifndef INTUITION_IOBSOLETE_H
#include <intuition/iobsolete.h>
#endif

#endif


include/prefs/input.h

#ifndef PREFS_INPUT_H
#define PREFS_INPUT_H
/*
**	$VER: input.h 38.2 (28.6.1991)
**	Includes Release 44.1
**
**	File format for input preferences
**
**	(C) Copyright 1991-1999 Amiga, Inc.
**	All Rights Reserved
*/

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef LIBRARIES_IFFPARSE_H
#include <libraries/iffparse.h>
#endif

#ifndef DEVICES_TIMER_H
#include <devices/timer.h>
#endif

/*****************************************************************************/

#define ID_INPT MAKE_ID('I','N','P','T')

struct InputPrefs
{
    char	   ip_Keymap[16];
    UWORD	   ip_PointerTicks;
    struct timeval ip_DoubleClick;
    struct timeval ip_KeyRptDelay;
    struct timeval ip_KeyRptSpeed;
    WORD	   ip_MouseAccel;
};

/*****************************************************************************/

#endif /* PREFS_INPUT_H */


include/exec/interrupts.h

#ifndef	EXEC_INTERRUPTS_H
#define	EXEC_INTERRUPTS_H
/*
**	$VER: interrupts.h 39.1 (18.9.1992)
**	Includes Release 44.1
**
**	Callback structures used by hardware & software interrupts
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_NODES_H
#include <exec/nodes.h>
#endif /* EXEC_NODES_H */

#ifndef EXEC_LISTS_H
#include <exec/lists.h>
#endif /* EXEC_LISTS_H */

struct Interrupt {
    struct  Node is_Node;
    APTR    is_Data;		    /* server data segment  */
    VOID    (*is_Code)();	    /* server code entry    */
};

struct IntVector {		/* For EXEC use ONLY! */
    APTR    iv_Data;
    VOID    (*iv_Code)();
    struct  Node *iv_Node;
};

struct SoftIntList {		/* For EXEC use ONLY! */
    struct List sh_List;
    UWORD  sh_Pad;
};

#define SIH_PRIMASK (0xf0)

/* this is a fake INT definition, used only for AddIntServer and the like */
#define INTB_NMI	15
#define INTF_NMI	(1L<<15)

#endif	/* EXEC_INTERRUPTS_H */


include/intuition/intuitionbase.h

#ifndef INTUITION_INTUITIONBASE_H
#define INTUITION_INTUITIONBASE_H 1
/*
**  $VER: intuitionbase.h 38.0 (12.6.1991)
**  Includes Release 44.1
**
**  Public part of IntuitionBase structure and supporting structures
**
**  (C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef EXEC_LIBRARIES_H
#include <exec/libraries.h>
#endif

#ifndef INTUITION_INTUITION_H
#include <intuition/intuition.h>
#endif

#ifndef EXEC_INTERRUPTS_H
#include <exec/interrupts.h>
#endif

/* these are the display modes for which we have corresponding parameter
 *  settings in the config arrays
 */
#define DMODECOUNT	0x0002	/* how many modes there are */
#define HIRESPICK	0x0000
#define LOWRESPICK	0x0001

#define EVENTMAX 10		/* size of event array */

/* these are the system Gadget defines */
#define RESCOUNT	2
#define HIRESGADGET	0
#define LOWRESGADGET	1

#define GADGETCOUNT	8
#define UPFRONTGADGET	0
#define DOWNBACKGADGET	1
#define SIZEGADGET	2
#define CLOSEGADGET	3
#define DRAGGADGET	4
#define SUPFRONTGADGET	5
#define SDOWNBACKGADGET	6
#define SDRAGGADGET	7

/* ======================================================================== */
/* === IntuitionBase ====================================================== */
/* ======================================================================== */
/*
 * Be sure to protect yourself against someone modifying these data as
 * you look at them.  This is done by calling:
 *
 * lock = LockIBase(0), which returns a ULONG.	When done call
 * UnlockIBase(lock) where lock is what LockIBase() returned.
 */

/* This structure is strictly READ ONLY */
struct IntuitionBase
{
    struct Library LibNode;

    struct View ViewLord;

    struct Window *ActiveWindow;
    struct Screen *ActiveScreen;

    /* the FirstScreen variable points to the frontmost Screen.  Screens are
     * then maintained in a front to back order using Screen.NextScreen
     */
    struct Screen *FirstScreen; /* for linked list of all screens */

    ULONG Flags;	/* values are all system private */
    WORD	MouseY, MouseX;
            /* note "backwards" order of these		*/

    ULONG Seconds;	/* timestamp of most current input event */
    ULONG Micros;	/* timestamp of most current input event */

    /* I told you this was private.
     * The data beyond this point has changed, is changing, and
     * will continue to change.
     */
};

#endif


include/devices/audio.h

#ifndef DEVICES_AUDIO_H
#define DEVICES_AUDIO_H
/*
**	$VER: audio.h 36.3 (29.8.1990)
**	Includes Release 44.1
**
**	audio.device include file
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_IO_H
#include <exec/io.h>
#endif

#define AUDIONAME		"audio.device"

#define ADHARD_CHANNELS		4

#define ADALLOC_MINPREC		-128
#define ADALLOC_MAXPREC		127

#define ADCMD_FREE		(CMD_NONSTD+0)
#define ADCMD_SETPREC		(CMD_NONSTD+1)
#define ADCMD_FINISH		(CMD_NONSTD+2)
#define ADCMD_PERVOL		(CMD_NONSTD+3)
#define ADCMD_LOCK		(CMD_NONSTD+4)
#define ADCMD_WAITCYCLE		(CMD_NONSTD+5)
#define ADCMD_ALLOCATE		32

#define ADIOB_PERVOL		4
#define ADIOF_PERVOL		(1<<4)
#define ADIOB_SYNCCYCLE		5
#define ADIOF_SYNCCYCLE		(1<<5)
#define ADIOB_NOWAIT		6
#define ADIOF_NOWAIT		(1<<6)
#define ADIOB_WRITEMESSAGE	7
#define ADIOF_WRITEMESSAGE	(1<<7)

#define ADIOERR_NOALLOCATION	-10
#define ADIOERR_ALLOCFAILED	-11
#define ADIOERR_CHANNELSTOLEN	-12

struct IOAudio {
    struct IORequest ioa_Request;
    WORD ioa_AllocKey;
    UBYTE *ioa_Data;
    ULONG ioa_Length;
    UWORD ioa_Period;
    UWORD ioa_Volume;
    UWORD ioa_Cycles;
    struct Message ioa_WriteMsg;
};

#endif	/* DEVICES_AUDIO_H */


include/rexx/rexxio.h

#ifndef REXX_REXXIO_H
#define REXX_REXXIO_H
/*
**	$VER: rexxio.h 1.4 (8.11.1991)
**	Includes Release 44.1
**
**	Header file for ARexx Input/Output related structures
**
**	(C) Copyright 1986,1987,1988,1989,1990 William S. Hawes
**	(C) Copyright 1990-1999 Amiga, Inc.
**		All Rights Reserved
*/

#ifndef REXX_STORAGE_H
#include <rexx/storage.h>
#endif

#define RXBUFFSZ  204		       /* buffer length		*/

/*
 * The IoBuff is a resource node used to maintain the File List.  Nodes
 * are allocated and linked into the list whenever a file is opened.
 */
struct IoBuff {
   struct RexxRsrc iobNode;	       /* structure for files/strings	*/
   APTR     iobRpt;		       /* read/write pointer		*/
   LONG     iobRct;		       /* character count		*/
   LONG     iobDFH;		       /* DOS filehandle		*/
   APTR     iobLock;		       /* DOS lock			*/
   LONG     iobBct;		       /* buffer length		*/
   BYTE     iobArea[RXBUFFSZ];	       /* buffer area			*/
   };				       /* size: 256 bytes		*/

/* Access mode definitions						*/
#define RXIO_EXIST   -1	       /* an external filehandle	*/
#define RXIO_STRF    0		       /* a "string file"		*/
#define RXIO_READ    1		       /* read-only access		*/
#define RXIO_WRITE   2		       /* write mode			*/
#define RXIO_APPEND  3		       /* append mode (existing file)	*/

/*
 * Offset anchors for SeekF()
 */
#define RXIO_BEGIN   -1L	       /* relative to start		*/
#define RXIO_CURR    0L	       /* relative to current position	*/
#define RXIO_END     1L	       /* relative to end		*/

/* The Library List contains just plain resource nodes.		*/

#define LLOFFSET(rrp) (rrp->rr_Arg1)   /* "Query" offset		*/
#define LLVERS(rrp)   (rrp->rr_Arg2)   /* library version		*/

/*
 * The RexxClipNode structure is used to maintain the Clip List.  The value
 * string is stored as an argstring in the rr_Arg1 field.
 */
#define CLVALUE(rrp) ((STRPTR) rrp->rr_Arg1)

/*
 * A message port structure, maintained as a resource node.  The ReplyList
 * holds packets that have been received but haven't been replied.
 */
struct RexxMsgPort {
   struct RexxRsrc rmp_Node;	       /* linkage node			*/
   struct MsgPort  rmp_Port;	       /* the message port		*/
   struct List	   rmp_ReplyList;      /* messages awaiting reply	*/
   };

/*
 * DOS Device types
 */
#define DT_DEV	  0L		       /* a device			*/
#define DT_DIR	  1L		       /* an ASSIGNed directory	*/
#define DT_VOL	  2L		       /* a volume			*/

/*
 * Private DOS packet types
 */
#define ACTION_STACK 2002L	       /* stack a line			*/
#define ACTION_QUEUE 2003L	       /* queue a line			*/

#endif


include/exec/io.h

#ifndef	EXEC_IO_H
#define	EXEC_IO_H
/*
**	$VER: io.h 39.0 (15.10.1991)
**	Includes Release 44.1
**
**	Message structures used for device communication
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_PORTS_H
#include <exec/ports.h>
#endif /* EXEC_PORTS_H */

struct IORequest {
    struct  Message io_Message;
    struct  Device  *io_Device;     /* device node pointer  */
    struct  Unit    *io_Unit;	    /* unit (driver private)*/
    UWORD   io_Command;	    /* device command */
    UBYTE   io_Flags;
    BYTE    io_Error;		    /* error or warning num */
};

struct IOStdReq {
    struct  Message io_Message;
    struct  Device  *io_Device;     /* device node pointer  */
    struct  Unit    *io_Unit;	    /* unit (driver private)*/
    UWORD   io_Command;	    /* device command */
    UBYTE   io_Flags;
    BYTE    io_Error;		    /* error or warning num */
    ULONG   io_Actual;		    /* actual number of bytes transferred */
    ULONG   io_Length;		    /* requested number bytes transferred*/
    APTR    io_Data;		    /* points to data area */
    ULONG   io_Offset;		    /* offset for block structured devices */
};

/* library vector offsets for device reserved vectors */
#define DEV_BEGINIO	(-30)
#define DEV_ABORTIO	(-36)

/* io_Flags defined bits */
#define IOB_QUICK	0
#define IOF_QUICK	(1<<0)

#define CMD_INVALID	0
#define CMD_RESET	1
#define CMD_READ	2
#define CMD_WRITE	3
#define CMD_UPDATE	4
#define CMD_CLEAR	5
#define CMD_STOP	6
#define CMD_START	7
#define CMD_FLUSH	8

#define CMD_NONSTD	9

#endif	/* EXEC_IO_H */


include/graphics/graphint.h

#ifndef	GRAPHICS_GRAPHINT_H
#define	GRAPHICS_GRAPHINT_H
/*
**	$VER: graphint.h 39.0 (23.9.1991)
**	Includes Release 44.1
**
**
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_NODES_H
#include <exec/nodes.h>
#endif

/* structure used by AddTOFTask */
struct Isrvstr
{
    struct Node is_Node;
    struct Isrvstr *Iptr;   /* passed to srvr by os */
    LONG (*code)();
    LONG (*ccode) __CLIB_PROTOTYPE((APTR));
    APTR Carg;
};

#endif	/* GRAPHICS_GRAPHINT_H */


include/devices/keymap.h

#ifndef	DEVICES_KEYMAP_H
#define	DEVICES_KEYMAP_H
/*
**	$VER: keymap.h 36.3 (13.4.1990)
**	Includes Release 44.1
**
**	key map definitions for keymap.resource, keymap.library, and
**	console.device
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_NODES_H
#include	<exec/nodes.h>
#endif
#ifndef EXEC_LISTS_H
#include	<exec/lists.h>
#endif

struct	 KeyMap {
    UBYTE   *km_LoKeyMapTypes;
    ULONG   *km_LoKeyMap;
    UBYTE   *km_LoCapsable;
    UBYTE   *km_LoRepeatable;
    UBYTE   *km_HiKeyMapTypes;
    ULONG   *km_HiKeyMap;
    UBYTE   *km_HiCapsable;
    UBYTE   *km_HiRepeatable;
};

struct	KeyMapNode {
    struct Node kn_Node;	/* including name of keymap */
    struct KeyMap kn_KeyMap;
};

/* the structure of keymap.resource */
struct	KeyMapResource {
    struct Node kr_Node;
    struct List kr_List;	/* a list of KeyMapNodes */
};

/* Key Map Types */
#define  KC_NOQUAL   0
#define  KC_VANILLA  7		/* note that SHIFT+ALT+CTRL is VANILLA */
#define  KCB_SHIFT   0
#define  KCF_SHIFT   0x01
#define  KCB_ALT     1
#define  KCF_ALT     0x02
#define  KCB_CONTROL 2
#define  KCF_CONTROL 0x04
#define  KCB_DOWNUP  3
#define  KCF_DOWNUP  0x08

#define  KCB_DEAD    5		/* may be dead or modified by dead key: */
#define  KCF_DEAD    0x20	/*   use dead prefix bytes		*/

#define  KCB_STRING  6
#define  KCF_STRING  0x40

#define  KCB_NOP     7
#define  KCF_NOP     0x80

/* Dead Prefix Bytes */
#define DPB_MOD	0
#define DPF_MOD	0x01
#define DPB_DEAD	3
#define DPF_DEAD	0x08

#define DP_2DINDEXMASK	0x0f	/* mask for index for 1st of two dead keys */
#define DP_2DFACSHIFT	4	/* shift for factor for 1st of two dead keys */

#endif	/* DEVICES_KEYMAP_H */


include/libraries/lowlevel.h

#ifndef LIBRARIES_LOWLEVEL_H
#define LIBRARIES_LOWLEVEL_H

/*
**	$VER: lowlevel.h 40.6 (30.7.1993)
**	Includes Release 44.1
**
**	lowlevel.library interface structures and definitions.
**
**	(C) Copyright-1999 Amiga, Inc.
**	All Rights Reserved
*/

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

/*****************************************************************************/

/* structure for use with QueryKeys() */
struct KeyQuery
{
    UWORD kq_KeyCode;
    BOOL  kq_Pressed;
};

/*****************************************************************************/

/* bits in the return value of GetKey() */
#define LLKB_LSHIFT	16
#define LLKB_RSHIFT	17
#define LLKB_CAPSLOCK	18
#define LLKB_CONTROL	19
#define LLKB_LALT	20
#define LLKB_RALT	21
#define LLKB_LAMIGA	22
#define LLKB_RAMIGA	23

#define LLKF_LSHIFT	(1<<LLKB_LSHIFT)
#define LLKF_RSHIFT	(1<<LLKB_RSHIFT)
#define LLKF_CAPSLOCK	(1<<LLKB_CAPSLOCK)
#define LLKF_CONTROL	(1<<LLKB_CONTROL)
#define LLKF_LALT	(1<<LLKB_LALT)
#define LLKF_RALT	(1<<LLKB_RALT)
#define LLKF_LAMIGA	(1<<LLKB_LAMIGA)
#define LLKF_RAMIGA	(1<<LLKB_RAMIGA)

/*****************************************************************************/

/* Tags for SetJoyPortAttrs() */
#define SJA_Dummy	 (TAG_USER+0xc00100)
#define SJA_Type	 (SJA_Dummy+1) /* force type to mouse, joy, game cntrlr */
#define SJA_Reinitialize (SJA_Dummy+2) /* free potgo bits, reset to autosense	*/

/* Controller types for SJA_Type tag */
#define SJA_TYPE_AUTOSENSE 0
#define SJA_TYPE_GAMECTLR  1
#define SJA_TYPE_MOUSE	   2
#define SJA_TYPE_JOYSTK    3

/*****************************************************************************/

/* ReadJoyPort() return value definitions */

/* Port types */
#define JP_TYPE_NOTAVAIL  (00<<28)	  /* port data unavailable    */
#define JP_TYPE_GAMECTLR  (01<<28)	  /* port has game controller */
#define JP_TYPE_MOUSE	  (02<<28)	  /* port has mouse	      */
#define JP_TYPE_JOYSTK	  (03<<28)	  /* port has joystick	      */
#define JP_TYPE_UNKNOWN   (04<<28)	  /* port has unknown device  */
#define JP_TYPE_MASK	  (15<<28)	  /* controller type	      */

/* Button types, valid for all types except JP_TYPE_NOTAVAIL */
#define JPB_BUTTON_BLUE    23	  /* Blue - Stop; Right Mouse		     */
#define JPB_BUTTON_RED	   22	  /* Red - Select; Left Mouse; Joystick Fire */
#define JPB_BUTTON_YELLOW  21	  /* Yellow - Repeat			     */
#define JPB_BUTTON_GREEN   20	  /* Green - Shuffle			     */
#define JPB_BUTTON_FORWARD 19	  /* Charcoal - Forward		     */
#define JPB_BUTTON_REVERSE 18	  /* Charcoal - Reverse		     */
#define JPB_BUTTON_PLAY    17	  /* Grey - Play/Pause; Middle Mouse	     */
#define JPF_BUTTON_BLUE    (1<<JPB_BUTTON_BLUE)
#define JPF_BUTTON_RED	   (1<<JPB_BUTTON_RED)
#define JPF_BUTTON_YELLOW  (1<<JPB_BUTTON_YELLOW)
#define JPF_BUTTON_GREEN   (1<<JPB_BUTTON_GREEN)
#define JPF_BUTTON_FORWARD (1<<JPB_BUTTON_FORWARD)
#define JPF_BUTTON_REVERSE (1<<JPB_BUTTON_REVERSE)
#define JPF_BUTTON_PLAY    (1<<JPB_BUTTON_PLAY)
#define JP_BUTTON_MASK	   (JPF_BUTTON_BLUE|JPF_BUTTON_RED|JPF_BUTTON_YELLOW|JPF_BUTTON_GREEN|JPF_BUTTON_FORWARD|JPF_BUTTON_REVERSE|JPF_BUTTON_PLAY)

/* Direction types, valid for JP_TYPE_GAMECTLR and JP_TYPE_JOYSTK */
#define JPB_JOY_UP	  3
#define JPB_JOY_DOWN	  2
#define JPB_JOY_LEFT	  1
#define JPB_JOY_RIGHT	  0
#define JPF_JOY_UP	  (1<<JPB_JOY_UP)
#define JPF_JOY_DOWN	  (1<<JPB_JOY_DOWN)
#define JPF_JOY_LEFT	  (1<<JPB_JOY_LEFT)
#define JPF_JOY_RIGHT	  (1<<JPB_JOY_RIGHT)
#define JP_DIRECTION_MASK (JPF_JOY_UP|JPF_JOY_DOWN|JPF_JOY_LEFT|JPF_JOY_RIGHT)

/* Mouse position reports, valid for JP_TYPE_MOUSE */
#define JP_MHORZ_MASK	(255<<0)	/* horzizontal position */
#define JP_MVERT_MASK	(255<<8)	/* vertical position	*/
#define JP_MOUSE_MASK	(JP_MHORZ_MASK|JP_MVERT_MASK)

/* Obsolete ReadJoyPort() definitions, here for source code compatibility only.
 * Please do NOT use in new code.
 */
#define JPB_BTN1  JPB_BUTTON_BLUE
#define JPF_BTN1  JPF_BUTTON_BLUE
#define JPB_BTN2  JPB_BUTTON_RED
#define JPF_BTN2  JPF_BUTTON_RED
#define JPB_BTN3  JPB_BUTTON_YELLOW
#define JPF_BTN3  JPF_BUTTON_YELLOW
#define JPB_BTN4  JPB_BUTTON_GREEN
#define JPF_BTN4  JPF_BUTTON_GREEN
#define JPB_BTN5  JPB_BUTTON_FORWARD
#define JPF_BTN5  JPF_BUTTON_FORWARD
#define JPB_BTN6  JPB_BUTTON_REVERSE
#define JPF_BTN6  JPF_BUTTON_REVERSE
#define JPB_BTN7  JPB_BUTTON_PLAY
#define JPF_BTN7  JPF_BUTTON_PLAY
#define JPB_UP	  JPB_JOY_UP
#define JPF_UP	  JPF_JOY_UP
#define JPB_DOWN  JPB_JOY_DOWN
#define JPF_DOWN  JPF_JOY_DOWN
#define JPB_LEFT  JPB_JOY_LEFT
#define JPF_LEFT  JPF_JOY_LEFT
#define JPB_RIGHT JPB_JOY_RIGHT
#define JPF_RIGHT JPF_JOY_RIGHT

/*****************************************************************************/

/* Tags for SystemControl() */
#define SCON_Dummy	   (TAG_USER+0x00C00000)
#define SCON_TakeOverSys   (SCON_Dummy+0)
#define SCON_KillReq	   (SCON_Dummy+1)
#define SCON_CDReboot	   (SCON_Dummy+2)
#define SCON_StopInput	   (SCON_Dummy+3)
#define SCON_AddCreateKeys (SCON_Dummy+4)
#define SCON_RemCreateKeys (SCON_Dummy+5)

/* Reboot control values for use with SCON_CDReboot tag */
#define CDReboot_On		1
#define CDReboot_Off		0
#define CDReboot_Default	2

/*****************************************************************************/

/* Rawkey codes returned when using SCON_AddCreateKeys with SystemControl() */

#define RAWKEY_PORT0_BUTTON_BLUE	0x72
#define RAWKEY_PORT0_BUTTON_RED	0x78
#define RAWKEY_PORT0_BUTTON_YELLOW	0x77
#define RAWKEY_PORT0_BUTTON_GREEN	0x76
#define RAWKEY_PORT0_BUTTON_FORWARD	0x75
#define RAWKEY_PORT0_BUTTON_REVERSE	0x74
#define RAWKEY_PORT0_BUTTON_PLAY	0x73
#define RAWKEY_PORT0_JOY_UP		0x79
#define RAWKEY_PORT0_JOY_DOWN		0x7A
#define RAWKEY_PORT0_JOY_LEFT		0x7C
#define RAWKEY_PORT0_JOY_RIGHT		0x7B

#define RAWKEY_PORT1_BUTTON_BLUE	0x172
#define RAWKEY_PORT1_BUTTON_RED	0x178
#define RAWKEY_PORT1_BUTTON_YELLOW	0x177
#define RAWKEY_PORT1_BUTTON_GREEN	0x176
#define RAWKEY_PORT1_BUTTON_FORWARD	0x175
#define RAWKEY_PORT1_BUTTON_REVERSE	0x174
#define RAWKEY_PORT1_BUTTON_PLAY	0x173
#define RAWKEY_PORT1_JOY_UP		0x179
#define RAWKEY_PORT1_JOY_DOWN		0x17A
#define RAWKEY_PORT1_JOY_LEFT		0x17C
#define RAWKEY_PORT1_JOY_RIGHT		0x17B

#define RAWKEY_PORT2_BUTTON_BLUE	0x272
#define RAWKEY_PORT2_BUTTON_RED	0x278
#define RAWKEY_PORT2_BUTTON_YELLOW	0x277
#define RAWKEY_PORT2_BUTTON_GREEN	0x276
#define RAWKEY_PORT2_BUTTON_FORWARD	0x275
#define RAWKEY_PORT2_BUTTON_REVERSE	0x274
#define RAWKEY_PORT2_BUTTON_PLAY	0x273
#define RAWKEY_PORT2_JOY_UP		0x279
#define RAWKEY_PORT2_JOY_DOWN		0x27A
#define RAWKEY_PORT2_JOY_LEFT		0x27C
#define RAWKEY_PORT2_JOY_RIGHT		0x27B

#define RAWKEY_PORT3_BUTTON_BLUE	0x372
#define RAWKEY_PORT3_BUTTON_RED	0x378
#define RAWKEY_PORT3_BUTTON_YELLOW	0x377
#define RAWKEY_PORT3_BUTTON_GREEN	0x376
#define RAWKEY_PORT3_BUTTON_FORWARD	0x375
#define RAWKEY_PORT3_BUTTON_REVERSE	0x374
#define RAWKEY_PORT3_BUTTON_PLAY	0x373
#define RAWKEY_PORT3_JOY_UP		0x379
#define RAWKEY_PORT3_JOY_DOWN		0x37A
#define RAWKEY_PORT3_JOY_LEFT		0x37C
#define RAWKEY_PORT3_JOY_RIGHT		0x37B

/*****************************************************************************/

/* Return values for GetLanguageSelection() */
#define LANG_UNKNOWN	0
#define LANG_AMERICAN	1	/* American English */
#define LANG_ENGLISH	2	/* British English  */
#define LANG_GERMAN	3
#define LANG_FRENCH	4
#define LANG_SPANISH	5
#define LANG_ITALIAN	6
#define LANG_PORTUGUESE 7
#define LANG_DANISH	8
#define LANG_DUTCH	9
#define LANG_NORWEGIAN	10
#define LANG_FINNISH	11
#define LANG_SWEDISH	12
#define LANG_JAPANESE	13
#define LANG_CHINESE	14
#define LANG_ARABIC	15
#define LANG_GREEK	16
#define LANG_HEBREW	17
#define LANG_KOREAN	18

/*****************************************************************************/

#endif /* LIBRARIES_LOWLEVEL_H */


include/graphics/layers.h

#ifndef	GRAPHICS_LAYERS_H
#define	GRAPHICS_LAYERS_H
/*
**	$VER: layers.h 39.4 (14.4.1992)
**	Includes Release 44.1
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_LISTS_H
#include <exec/lists.h>
#endif

#ifndef EXEC_SEMAPHORES_H
#include <exec/semaphores.h>
#endif

#define LAYERSIMPLE		1
#define LAYERSMART		2
#define LAYERSUPER		4
#define LAYERUPDATING		0x10
#define LAYERBACKDROP		0x40
#define LAYERREFRESH		0x80
#define	LAYERIREFRESH		0x200
#define	LAYERIREFRESH2		0x400
#define LAYER_CLIPRECTS_LOST	0x100	/* during BeginUpdate */
                    /* or during layerop */
                    /* this happens if out of memory */

struct Layer_Info
{
struct	Layer		*top_layer;
struct	Layer		*check_lp;		/* !! Private !! */
struct	ClipRect	*obs;
struct	ClipRect	*FreeClipRects;		/* !! Private !! */
    LONG		PrivateReserve1;	/* !! Private !! */
    LONG		PrivateReserve2;	/* !! Private !! */
struct	SignalSemaphore	Lock;			/* !! Private !! */
struct	MinList		gs_Head;		/* !! Private !! */
    WORD		PrivateReserve3;	/* !! Private !! */
    VOID		*PrivateReserve4;	/* !! Private !! */
    UWORD		Flags;
    BYTE		fatten_count;		/* !! Private !! */
    BYTE		LockLayersCount;	/* !! Private !! */
    WORD		PrivateReserve5;	/* !! Private !! */
    VOID		*BlankHook;		/* !! Private !! */
    VOID		*LayerInfo_extra;	/* !! Private !! */
};

#define NEWLAYERINFO_CALLED 1

/*
 * LAYERS_NOBACKFILL is the value needed to get no backfill hook
 * LAYERS_BACKFILL is the value needed to get the default backfill hook
 */
#define	LAYERS_NOBACKFILL	((struct Hook *)1)
#define	LAYERS_BACKFILL		((struct Hook *)0)

#endif	/* GRAPHICS_LAYERS_H */


include/exec/libraries.h

#ifndef	EXEC_LIBRARIES_H
#define	EXEC_LIBRARIES_H
/*
**	$VER: libraries.h 39.2 (10.4.1992)
**	Includes Release 44.1
**
**	Definitions for use when creating or using Exec libraries
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_NODES_H
#include <exec/nodes.h>
#endif /* EXEC_NODES_H */

/*------ Special Constants ---------------------------------------*/
#define LIB_VECTSIZE	6	/* Each library entry takes 6 bytes */
#define LIB_RESERVED	4	/* Exec reserves the first 4 vectors */
#define LIB_BASE	(-LIB_VECTSIZE)
#define LIB_USERDEF	(LIB_BASE-(LIB_RESERVED*LIB_VECTSIZE))
#define LIB_NONSTD	(LIB_USERDEF)

/*------ Standard Functions --------------------------------------*/
#define LIB_OPEN	(-6)
#define LIB_CLOSE	(-12)
#define LIB_EXPUNGE	(-18)
#define LIB_EXTFUNC	(-24)	/* for future expansion */

/*------ Library Base Structure ----------------------------------*/
/* Also used for Devices and some Resources */
struct Library {
    struct  Node lib_Node;
    UBYTE   lib_Flags;
    UBYTE   lib_pad;
    UWORD   lib_NegSize;	    /* number of bytes before library */
    UWORD   lib_PosSize;	    /* number of bytes after library */
    UWORD   lib_Version;	    /* major */
    UWORD   lib_Revision;	    /* minor */
    APTR    lib_IdString;	    /* ASCII identification */
    ULONG   lib_Sum;		    /* the checksum itself */
    UWORD   lib_OpenCnt;	    /* number of current opens */
};	/* Warning: size is not a longword multiple! */

/* lib_Flags bit definitions (all others are system reserved) */
#define LIBF_SUMMING	(1<<0)	    /* we are currently checksumming */
#define LIBF_CHANGED	(1<<1)	    /* we have just changed the lib */
#define LIBF_SUMUSED	(1<<2)	    /* set if we should bother to sum */
#define LIBF_DELEXP	(1<<3)	    /* delayed expunge */

/* Temporary Compatibility */
#define lh_Node	lib_Node
#define lh_Flags	lib_Flags
#define lh_pad		lib_pad
#define lh_NegSize	lib_NegSize
#define lh_PosSize	lib_PosSize
#define lh_Version	lib_Version
#define lh_Revision	lib_Revision
#define lh_IdString	lib_IdString
#define lh_Sum		lib_Sum
#define lh_OpenCnt	lib_OpenCnt

#endif	/* EXEC_LIBRARIES_H */


include/datatypes/textclass.h

#ifndef	DATATYPES_TEXTCLASS_H
#define	DATATYPES_TEXTCLASS_H
/*
**  $VER: textclass.h 39.3 (3.8.1992)
**  Includes Release 44.1
**
**  Interface definitions for DataType text objects.
**
**  (C) Copyright 1992-1999 Amiga, Inc.
**	All Rights Reserved
*/

#ifndef	UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

#ifndef	DATATYPES_DATATYPESCLASS_H
#include <datatypes/datatypesclass.h>
#endif

#ifndef	LIBRARIES_IFFPARSE_H
#include <libraries/iffparse.h>
#endif

/*****************************************************************************/

#define	TEXTDTCLASS		"text.datatype"

/*****************************************************************************/

/* Text attributes */
#define	TDTA_Buffer		(DTA_Dummy + 300)
#define	TDTA_BufferLen		(DTA_Dummy + 301)
#define	TDTA_LineList		(DTA_Dummy + 302)
#define	TDTA_WordSelect		(DTA_Dummy + 303)
#define	TDTA_WordDelim		(DTA_Dummy + 304)
#define	TDTA_WordWrap		(DTA_Dummy + 305)
     /* Boolean. Should the text be word wrapped.  Defaults to false. */

/*****************************************************************************/

/* There is one Line structure for every line of text in our document.	*/
struct Line
{
    struct MinNode	 ln_Link;		/* to link the lines together */
    STRPTR		 ln_Text;		/* pointer to the text for this	line */
    ULONG		 ln_TextLen;		/* the character length of the text for this line */
    UWORD		 ln_XOffset;		/* where in the	line the text starts */
    UWORD		 ln_YOffset;		/* line the text is on */
    UWORD		 ln_Width;		/* Width of line in pixels */
    UWORD		 ln_Height;		/* Height of line in pixels */
    UWORD		 ln_Flags;		/* info	on the line */
    BYTE		 ln_FgPen;		/* foreground pen */
    BYTE		 ln_BgPen;		/* background pen */
    ULONG		 ln_Style;		/* Font style */
    APTR		 ln_Data;		/* Link data... */
};

/*****************************************************************************/

/* Line.ln_Flags */

/* Line Feed */
#define	LNF_LF		(1L << 0)

/* Segment is a link */
#define	LNF_LINK	(1L << 1)

/* ln_Data is a pointer to an DataTypes object */
#define	LNF_OBJECT	(1L << 2)

/* Object is selected */
#define	LNF_SELECTED	(1L << 3)

/*****************************************************************************/

/* IFF types that may be text */
#define	ID_FTXT		MAKE_ID('F','T','X','T')
#define	ID_CHRS		MAKE_ID('C','H','R','S')

/*****************************************************************************/

#endif	/* DATATYPES_TEXTCLASS_H */


include/exec/lists.h

#ifndef EXEC_LISTS_H
#define EXEC_LISTS_H
/*
**	$VER: lists.h 39.0 (15.10.1991)
**	Includes Release 44.1
**
**	Definitions and macros for use with Exec lists
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_NODES_H
#include <exec/nodes.h>
#endif /* EXEC_NODES_H */

/*
 *  Full featured list header.
 */
struct List {
   struct  Node *lh_Head;
   struct  Node *lh_Tail;
   struct  Node *lh_TailPred;
   UBYTE   lh_Type;
   UBYTE   l_pad;
};	/* word aligned */

/*
 * Minimal List Header - no type checking
 */
struct MinList {
   struct  MinNode *mlh_Head;
   struct  MinNode *mlh_Tail;
   struct  MinNode *mlh_TailPred;
};	/* longword aligned */

/*
 *	Check for the presence of any nodes on the given list.	These
 *	macros are even safe to use on lists that are modified by other
 *	tasks.	However; if something is simultaneously changing the
 *	list, the result of the test is unpredictable.
 *
 *	Unless you first arbitrated for ownership of the list, you can't
 *	_depend_ on the contents of the list.  Nodes might have been added
 *	or removed during or after the macro executes.
 *
 *		if( IsListEmpty(list) )		printf("List is empty\n");
 */
#define IsListEmpty(x) \
    ( ((x)->lh_TailPred) == (struct Node *)(x) )

#define IsMsgPortEmpty(x) \
    ( ((x)->mp_MsgList.lh_TailPred) == (struct Node *)(&(x)->mp_MsgList) )

#endif	/* EXEC_LISTS_H */


include/dos/var.h

#ifndef DOS_VAR_H
#define DOS_VAR_H
/*
**
**	$VER: var.h 36.11 (2.6.1992)
**	Includes Release 44.1
**
**	include file for dos local and environment variables
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**
*/

#ifndef EXEC_NODES_H
#include <exec/nodes.h>
#endif

/* the structure in the pr_LocalVars list */
/* Do NOT allocate yourself, use SetVar()!!! This structure may grow in */
/* future releases!  The list should be left in alphabetical order, and */
/* may have multiple entries with the same name but different types.	*/

struct LocalVar {
    struct Node lv_Node;
    UWORD	lv_Flags;
    UBYTE	*lv_Value;
    ULONG	lv_Len;
};

/*
 * The lv_Flags bits are available to the application.	The unused
 * lv_Node.ln_Pri bits are reserved for system use.
 */

/* bit definitions for lv_Node.ln_Type: */
#define LV_VAR			0	/* an variable */
#define LV_ALIAS		1	/* an alias */
/* to be or'ed into type: */
#define LVB_IGNORE		7	/* ignore this entry on GetVar, etc */
#define LVF_IGNORE		0x80

/* definitions of flags passed to GetVar()/SetVar()/DeleteVar() */
/* bit defs to be OR'ed with the type: */
/* item will be treated as a single line of text unless BINARY_VAR is used */
#define GVB_GLOBAL_ONLY		8
#define GVF_GLOBAL_ONLY		0x100
#define GVB_LOCAL_ONLY		9
#define GVF_LOCAL_ONLY		0x200
#define GVB_BINARY_VAR		10		/* treat variable as binary */
#define GVF_BINARY_VAR		0x400
#define GVB_DONT_NULL_TERM	11	/* only with GVF_BINARY_VAR */
#define GVF_DONT_NULL_TERM	0x800

/* this is only supported in >= V39 dos.  V37 dos ignores this. */
/* this causes SetVar to affect ENVARC: as well as ENV:.	*/
#define GVB_SAVE_VAR		12	/* only with GVF_GLOBAL_VAR */
#define GVF_SAVE_VAR		0x1000

#endif /* DOS_VAR_H */


include/libraries/gadtools.h

#ifndef LIBRARIES_GADTOOLS_H
#define LIBRARIES_GADTOOLS_H
/*
**	$VER: gadtools.h 39.9 (19.8.1992)
**	Includes Release 44.1
**
**	gadtools.library definitions
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	All Rights Reserved
*/

/*------------------------------------------------------------------------*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

#ifndef INTUITION_INTUITION_H
#include <intuition/intuition.h>
#endif

#ifndef INTUITION_GADGETCLASS_H
#include <intuition/gadgetclass.h>
#endif

/*------------------------------------------------------------------------*/

/* The kinds (almost classes) of gadgets that GadTools supports.
 * Use these identifiers when calling CreateGadgetA()
 */

#define GENERIC_KIND	0
#define BUTTON_KIND	1
#define CHECKBOX_KIND	2
#define INTEGER_KIND	3
#define LISTVIEW_KIND	4
#define MX_KIND		5
#define NUMBER_KIND	6
#define CYCLE_KIND	7
#define PALETTE_KIND	8
#define SCROLLER_KIND	9
/* Kind number 10 is reserved */
#define SLIDER_KIND	11
#define STRING_KIND	12
#define TEXT_KIND	13

#define NUM_KINDS	14

/*------------------------------------------------------------------------*/

/* 'Or' the appropriate set together for your Window IDCMPFlags: */

#define ARROWIDCMP	(IDCMP_GADGETUP | IDCMP_GADGETDOWN |\
    IDCMP_INTUITICKS | IDCMP_MOUSEBUTTONS)

#define BUTTONIDCMP	(IDCMP_GADGETUP)
#define CHECKBOXIDCMP	(IDCMP_GADGETUP)
#define INTEGERIDCMP	(IDCMP_GADGETUP)
#define LISTVIEWIDCMP	(IDCMP_GADGETUP | IDCMP_GADGETDOWN |\
    IDCMP_MOUSEMOVE | ARROWIDCMP)

#define MXIDCMP		(IDCMP_GADGETDOWN)
#define NUMBERIDCMP	(0L)
#define CYCLEIDCMP	(IDCMP_GADGETUP)
#define PALETTEIDCMP	(IDCMP_GADGETUP)

/* Use ARROWIDCMP|SCROLLERIDCMP if your scrollers have arrows: */
#define SCROLLERIDCMP	(IDCMP_GADGETUP | IDCMP_GADGETDOWN | IDCMP_MOUSEMOVE)
#define SLIDERIDCMP	(IDCMP_GADGETUP | IDCMP_GADGETDOWN | IDCMP_MOUSEMOVE)
#define STRINGIDCMP	(IDCMP_GADGETUP)

#define TEXTIDCMP	(0L)

/*------------------------------------------------------------------------*/

/* Generic NewGadget used by several of the gadget classes: */

struct NewGadget
{
    WORD ng_LeftEdge, ng_TopEdge;	/* gadget position */
    WORD ng_Width, ng_Height;		/* gadget size */
    UBYTE *ng_GadgetText;		/* gadget label */
    struct TextAttr *ng_TextAttr;	/* desired font for gadget label */
    UWORD ng_GadgetID;			/* gadget ID */
    ULONG ng_Flags;			/* see below */
    APTR ng_VisualInfo;			/* Set to retval of GetVisualInfo() */
    APTR ng_UserData;			/* gadget UserData */
};

/* ng_Flags control certain aspects of the gadget.  The first five control
 * the placement of the descriptive text.  Each gadget kind has its default,
 * which is usually PLACETEXT_LEFT.  Consult the autodocs for details.
 */

#define PLACETEXT_LEFT	0x0001	/* Right-align text on left side */
#define PLACETEXT_RIGHT	0x0002	/* Left-align text on right side */
#define PLACETEXT_ABOVE	0x0004	/* Center text above */
#define PLACETEXT_BELOW	0x0008	/* Center text below */
#define PLACETEXT_IN	0x0010	/* Center text on */

#define NG_HIGHLABEL	0x0020	/* Highlight the label */

/*------------------------------------------------------------------------*/

/* Fill out an array of these and pass that to CreateMenus(): */

struct NewMenu
{
    UBYTE nm_Type;		/* See below */
    /* Compiler inserts a PAD byte here */
    STRPTR nm_Label;		/* Menu's label */
    STRPTR nm_CommKey;		/* MenuItem Command Key Equiv */
    UWORD nm_Flags;		/* Menu or MenuItem flags (see note) */
    LONG nm_MutualExclude;	/* MenuItem MutualExclude word */
    APTR nm_UserData;		/* For your own use, see note */
};

/* Needed only by inside IM_ definitions below */
#define MENU_IMAGE	128

/* nm_Type determines what each NewMenu structure corresponds to.
 * for the NM_TITLE, NM_ITEM, and NM_SUB values, nm_Label should
 * be a text string to use for that menu title, item, or sub-item.
 * For IM_ITEM or IM_SUB, set nm_Label to point at the Image structure
 * you wish to use for this item or sub-item.
 * NOTE: At present, you may only use conventional images.
 * Custom images created from Intuition image-classes do not work.
 */
#define NM_TITLE	1	/* Menu header */
#define NM_ITEM		2	/* Textual menu item */
#define NM_SUB		3	/* Textual menu sub-item */

#define IM_ITEM		(NM_ITEM|MENU_IMAGE)	/* Graphical menu item */
#define IM_SUB		(NM_SUB|MENU_IMAGE)	/* Graphical menu sub-item */

/* The NewMenu array should be terminated with a NewMenu whose
 * nm_Type equals NM_END.
 */
#define NM_END		0	/* End of NewMenu array */

/* Starting with V39, GadTools will skip any NewMenu entries whose
 * nm_Type field has the NM_IGNORE bit set.
 */
#define NM_IGNORE	64

/* nm_Label should be a text string for textual items, a pointer
 * to an Image structure for graphical menu items, or the special
 * constant NM_BARLABEL, to get a separator bar.
 */
#define NM_BARLABEL	((STRPTR)-1)

/* The nm_Flags field is used to fill out either the Menu->Flags or
 * MenuItem->Flags field.  Note that the sense of the MENUENABLED or
 * ITEMENABLED bit is inverted between this use and Intuition's use,
 * in other words, NewMenus are enabled by default.  The following
 * labels are provided to disable them:
 */
#define NM_MENUDISABLED	MENUENABLED
#define NM_ITEMDISABLED	ITEMENABLED

/* New for V39:  NM_COMMANDSTRING.  For a textual MenuItem or SubItem,
 * point nm_CommKey at an arbitrary string, and set the NM_COMMANDSTRING
 * flag.
 */
#define NM_COMMANDSTRING COMMSEQ

/* The following are pre-cleared (COMMSEQ, ITEMTEXT, and HIGHxxx are set
 * later as appropriate):
 * Under V39, the COMMSEQ flag bit is not cleared, since it now has
 * meaning.
 */
#define NM_FLAGMASK	(~(COMMSEQ | ITEMTEXT | HIGHFLAGS))
#define NM_FLAGMASK_V39	(~(ITEMTEXT | HIGHFLAGS))

/* You may choose among CHECKIT, MENUTOGGLE, and CHECKED.
 * Toggle-select menuitems are of type CHECKIT|MENUTOGGLE, along
 * with CHECKED if currently selected.	Mutually exclusive ones
 * are of type CHECKIT, and possibly CHECKED too.  The nm_MutualExclude
 * is a bit-wise representation of the items excluded by this one,
 * so in the simplest case (choose 1 among n), these flags would be
 * ~1, ~2, ~4, ~8, ~16, etc.  See the Intuition Menus chapter.
 */

/* A UserData pointer can be associated with each Menu and MenuItem structure.
 * The CreateMenus() call allocates space for a UserData after each
 * Menu or MenuItem (header, item or sub-item).  You should use the
 * GTMENU_USERDATA() or GTMENUITEM_USERDATA() macro to extract it.
 */

#define GTMENU_USERDATA(menu) (* ( (APTR *)(((struct Menu *)menu)+1) ) )
#define GTMENUITEM_USERDATA(menuitem) (* ( (APTR *)(((struct MenuItem *)menuitem)+1) ) )

/* Here is an old one for compatibility.  Do not use in new code! */
#define MENU_USERDATA(menuitem) (* ( (APTR *)(menuitem+1) ) )

/* These return codes can be obtained through the GTMN_SecondaryError tag */
#define GTMENU_TRIMMED	0x00000001	/* Too many menus, items, or subitems,
                     * menu has been trimmed down
                     */
#define GTMENU_INVALID	0x00000002	/* Invalid NewMenu array */
#define GTMENU_NOMEM	0x00000003	/* Out of memory */

/*------------------------------------------------------------------------*/

/* Starting with V39, checkboxes and mx gadgets can be scaled to your
 * specified gadget width/height.  Use the new GTCB_Scaled or GTMX_Scaled
 * tags, respectively.	Under V37, and by default in V39, the imagery
 * is of the following fixed size:
 */

/* MX gadget default dimensions: */
#define MX_WIDTH	17
#define MX_HEIGHT	9

/* Checkbox default dimensions: */
#define CHECKBOX_WIDTH	26
#define CHECKBOX_HEIGHT	11

/*------------------------------------------------------------------------*/

/* Tags for GadTools functions: */

#define GT_TagBase	     TAG_USER + 0x80000

#define GTVI_NewWindow	     GT_TagBase+1  /* Unused */
#define GTVI_NWTags	     GT_TagBase+2  /* Unused */

#define GT_Private0	     GT_TagBase+3  /* (private) */

#define GTCB_Checked	     GT_TagBase+4  /* State of checkbox */

#define GTLV_Top	     GT_TagBase+5  /* Top visible one in listview */
#define GTLV_Labels	     GT_TagBase+6  /* List to display in listview */
#define GTLV_ReadOnly	     GT_TagBase+7  /* TRUE if listview is to be
                        * read-only
                        */
#define GTLV_ScrollWidth     GT_TagBase+8  /* Width of scrollbar */

#define GTMX_Labels	     GT_TagBase+9  /* NULL-terminated array of labels */
#define GTMX_Active	     GT_TagBase+10 /* Active one in mx gadget */

#define GTTX_Text	     GT_TagBase+11 /* Text to display */
#define GTTX_CopyText	     GT_TagBase+12 /* Copy text label instead of
                        * referencing it
                        */

#define GTNM_Number	     GT_TagBase+13 /* Number to display */

#define GTCY_Labels	     GT_TagBase+14 /* NULL-terminated array of labels */
#define GTCY_Active	     GT_TagBase+15 /* The active one in the cycle gad */

#define GTPA_Depth	     GT_TagBase+16 /* Number of bitplanes in palette */
#define GTPA_Color	     GT_TagBase+17 /* Palette color */
#define GTPA_ColorOffset     GT_TagBase+18 /* First color to use in palette */
#define GTPA_IndicatorWidth  GT_TagBase+19 /* Width of current-color indicator */
#define GTPA_IndicatorHeight GT_TagBase+20 /* Height of current-color indicator */

#define GTSC_Top	     GT_TagBase+21 /* Top visible in scroller */
#define GTSC_Total	     GT_TagBase+22 /* Total in scroller area */
#define GTSC_Visible	     GT_TagBase+23 /* Number visible in scroller */
#define GTSC_Overlap	     GT_TagBase+24 /* Unused */

/*  GT_TagBase+25 through GT_TagBase+37 are reserved */

#define GTSL_Min	     GT_TagBase+38 /* Slider min value */
#define GTSL_Max	     GT_TagBase+39 /* Slider max value */
#define GTSL_Level	     GT_TagBase+40 /* Slider level */
#define GTSL_MaxLevelLen     GT_TagBase+41 /* Max length of printed level */
#define GTSL_LevelFormat     GT_TagBase+42 /* Format string for level */
#define GTSL_LevelPlace      GT_TagBase+43 /* Where level should be placed */
#define GTSL_DispFunc	     GT_TagBase+44 /* Callback for number calculation
                        * before display
                        */

#define GTST_String	     GT_TagBase+45 /* String gadget's displayed string */
#define GTST_MaxChars	     GT_TagBase+46 /* Max length of string */

#define GTIN_Number	     GT_TagBase+47 /* Number in integer gadget */
#define GTIN_MaxChars	     GT_TagBase+48 /* Max number of digits */

#define GTMN_TextAttr	     GT_TagBase+49 /* MenuItem font TextAttr */
#define GTMN_FrontPen	     GT_TagBase+50 /* MenuItem text pen color */

#define GTBB_Recessed	     GT_TagBase+51 /* Make BevelBox recessed */

#define GT_VisualInfo	     GT_TagBase+52 /* result of VisualInfo call */

#define GTLV_ShowSelected    GT_TagBase+53 /* show selected entry beneath
        * listview, set tag data = NULL for display-only, or pointer
        * to a string gadget you've created
        */
#define GTLV_Selected	     GT_TagBase+54 /* Set ordinal number of selected
                        * entry in the list
                        */
#define GT_Reserved1	     GT_TagBase+56 /* Reserved for future use */

#define GTTX_Border	     GT_TagBase+57 /* Put a border around
                        * Text-display gadgets
                        */
#define GTNM_Border	     GT_TagBase+58 /* Put a border around
                        * Number-display gadgets
                        */

#define GTSC_Arrows	     GT_TagBase+59 /* Specify size of arrows for
                        * scroller
                        */

#define GTMN_Menu	     GT_TagBase+60 /* Pointer to Menu for use by
                        * LayoutMenuItems()
                        */
#define GTMX_Spacing	     GT_TagBase+61 /* Added to font height to
        * figure spacing between mx choices.  Use this instead
        * of LAYOUTA_SPACING for mx gadgets.
        */

/* New to V37 GadTools.  Ignored by GadTools V36 */
#define GTMN_FullMenu	     GT_TagBase+62 /* Asks CreateMenus() to
        * validate that this is a complete menu structure
        */
#define GTMN_SecondaryError  GT_TagBase+63 /* ti_Data is a pointer
        * to a ULONG to receive error reports from CreateMenus()
        */
#define GT_Underscore	     GT_TagBase+64 /* ti_Data points to the symbol
        * that preceeds the character you'd like to underline in a
        * gadget label
        */
#define GTST_EditHook	     GT_TagBase+55 /* String EditHook */
#define GTIN_EditHook	     GTST_EditHook /* Same thing, different name,
        * just to round out INTEGER_KIND gadgets
        */

/* New to V39 GadTools.  Ignored by GadTools V36 and V37 */
#define GTMN_Checkmark	     GT_TagBase+65 /* ti_Data is checkmark img to use */
#define GTMN_AmigaKey	     GT_TagBase+66 /* ti_Data is Amiga-key img to use */
#define GTMN_NewLookMenus    GT_TagBase+67 /* ti_Data is boolean */

/* New to V39 GadTools.  Ignored by GadTools V36 and V37.
 * Set to TRUE if you want the checkbox or mx image scaled to
 * the gadget width/height you specify.  Defaults to FALSE,
 * for compatibility.
 */
#define GTCB_Scaled	     GT_TagBase+68 /* ti_Data is boolean */
#define GTMX_Scaled	     GT_TagBase+69 /* ti_Data is boolean */

#define GTPA_NumColors	     GT_TagBase+70 /* Number of colors in palette */

#define GTMX_TitlePlace      GT_TagBase+71 /* Where to put the title */

#define GTTX_FrontPen	     GT_TagBase+72 /* Text color in TEXT_KIND gad */
#define GTTX_BackPen	     GT_TagBase+73 /* Bgrnd color in TEXT_KIND gad */
#define GTTX_Justification   GT_TagBase+74 /* See GTJ_#? constants */

#define GTNM_FrontPen	     GT_TagBase+72 /* Text color in NUMBER_KIND gad */
#define GTNM_BackPen	     GT_TagBase+73 /* Bgrnd color in NUMBER_KIND gad */
#define GTNM_Justification   GT_TagBase+74 /* See GTJ_#? constants */
#define GTNM_Format	     GT_TagBase+75 /* Formatting string for number */
#define GTNM_MaxNumberLen    GT_TagBase+76 /* Maximum length of number */

#define GTBB_FrameType	     GT_TagBase+77 /* defines what kind of boxes
                        * DrawBevelBox() renders. See
                        * the BBFT_#? constants for
                        * possible values
                        */

#define GTLV_MakeVisible     GT_TagBase+78 /* Make this item visible */
#define GTLV_ItemHeight      GT_TagBase+79 /* Height of an individual item */

#define GTSL_MaxPixelLen     GT_TagBase+80 /* Max pixel size of level display */
#define GTSL_Justification   GT_TagBase+81 /* how should the level be displayed */

#define GTPA_ColorTable      GT_TagBase+82 /* colors to use in palette */

#define GTLV_CallBack	     GT_TagBase+83 /* general-purpose listview call back */
#define GTLV_MaxPen	     GT_TagBase+84 /* maximum pen number used by call back */

#define GTTX_Clipped	     GT_TagBase+85 /* make a TEXT_KIND clip text */
#define GTNM_Clipped	     GT_TagBase+85 /* make a NUMBER_KIND clip text */

/* Old definition, now obsolete: */
#define GT_Reserved0	     GTST_EditHook

/*------------------------------------------------------------------------*/

/* Justification types for GTTX_Justification and GTNM_Justification tags */
#define GTJ_LEFT   0
#define GTJ_RIGHT  1
#define GTJ_CENTER 2

/*------------------------------------------------------------------------*/

/* Bevel box frame types for GTBB_FrameType tag */
#define BBFT_BUTTON	 1  /* Standard button gadget box */
#define BBFT_RIDGE	 2  /* Standard string gadget box */
#define BBFT_ICONDROPBOX 3  /* Standard icon drop box	  */

/*------------------------------------------------------------------------*/

/* Typical suggested spacing between "elements": */
#define INTERWIDTH	8
#define INTERHEIGHT	4

/*------------------------------------------------------------------------*/

/* "NWay" is an old synonym for cycle gadgets */
#define NWAY_KIND	CYCLE_KIND
#define NWAYIDCMP	CYCLEIDCMP
#define GTNW_Labels	GTCY_Labels
#define GTNW_Active	GTCY_Active

/*------------------------------------------------------------------------*/

/* These two definitions are obsolete, but are here for backwards
 * compatibility.  You never need to worry about these:
 */
#define GADTOOLBIT	(0x8000)
/* Use this mask to isolate the user part: */
#define GADTOOLMASK	(~GADTOOLBIT)

/*------------------------------------------------------------------------*/

/* These definitions are for the GTLV_CallBack tag */

/* The different types of messages that a listview callback hook can see */
#define LV_DRAW       0x202L	/* draw yourself, with state */

/* Possible return values from a callback hook */
#define LVCB_OK       0		/* callback understands this message type    */
#define LVCB_UNKNOWN  1		/* callback does not understand this message */

/* states for LVDrawMsg.lvdm_State */
#define LVR_NORMAL	      0	/* the usual		     */
#define LVR_SELECTED	      1	/* for selected gadgets	     */
#define LVR_NORMALDISABLED    2		/* for disabled gadgets	     */
#define	LVR_SELECTEDDISABLED  8		/* disabled and selected     */

/* structure of LV_DRAW messages, object is a (struct Node *) */
struct LVDrawMsg
{
    ULONG	      lvdm_MethodID;   /* LV_DRAW		    */
    struct RastPort  *lvdm_RastPort;   /* where to render to	    */
    struct DrawInfo  *lvdm_DrawInfo;   /* useful to have around     */
    struct Rectangle  lvdm_Bounds;     /* limits of where to render */
    ULONG	      lvdm_State;      /* how to render	    */
};

/*------------------------------------------------------------------------*/

#endif /* LIBRARIES_GADTOOLS_H */


include/libraries/mathlibrary.h

#ifndef	LIBRARIES_MATHLIBRARY_H
#define	LIBRARIES_MATHLIBRARY_H
/*
**	$VER: mathlibrary.h 1.6 (13.7.1990)
**	Includes Release 44.1
**
**	Data structure returned by OpenLibrary of:
**	mathieeedoubbas.library,mathieeedoubtrans.library
**	mathieeesingbas.library,mathieeesingtrans.library
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_LIBRARIES_H
#include <exec/libraries.h>
#endif

struct MathIEEEBase
{
    struct Library MathIEEEBase_LibNode;
    unsigned char	MathIEEEBase_reserved[18];
    int	(*MathIEEEBase_TaskOpenLib)();
    int	(*MathIEEEBase_TaskCloseLib)();
    /*	This structure may be extended in the future */
};
/*
* Math resources may need to know when a program opens or closes this
* library. The functions TaskOpenLib and TaskCloseLib are called when
* a task opens or closes this library. They are initialized to point to
* local initialization pertaining to 68881 stuff if 68881 resources
* are found. To override the default the vendor must provide appropriate
* hooks in the MathIEEEResource. If specified, these will be called
* when the library initializes.
*/

#endif	/* LIBRARIES_MATHLIBRARY_H */


include/resources/mathresource.h

#ifndef	RESOURCES_MATHRESOURCE_H
#define	RESOURCES_MATHRESOURCE_H
/*
**	$VER: mathresource.h 1.2 (13.7.1990)
**	Includes Release 44.1
**
**	Data structure returned by OpenResource of:
**	"MathIEEE.resource"
**
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_NODES_H
#include <exec/nodes.h>
#endif

/*
*	The 'Init' entries are only used if the corresponding
*	bit is set in the Flags field.
*
*	So if you are just a 68881, you do not need the Init stuff
*	just make sure you have cleared the Flags field.
*
*	This should allow us to add Extended Precision later.
*
*	For Init users, if you need to be called whenever a task
*	opens this library for use, you need to change the appropriate
*	entries in MathIEEELibrary.
*/

struct MathIEEEResource
{
    struct	Node	MathIEEEResource_Node;
    unsigned short	MathIEEEResource_Flags;
    unsigned short	*MathIEEEResource_BaseAddr; /* ptr to 881 if exists */
    void	(*MathIEEEResource_DblBasInit)();
    void	(*MathIEEEResource_DblTransInit)();
    void	(*MathIEEEResource_SglBasInit)();
    void	(*MathIEEEResource_SglTransInit)();
    void	(*MathIEEEResource_ExtBasInit)();
    void	(*MathIEEEResource_ExtTransInit)();
};

/* definations for MathIEEEResource_FLAGS */
#define	MATHIEEERESOURCEF_DBLBAS	(1<<0)
#define	MATHIEEERESOURCEF_DBLTRANS	(1<<1)
#define	MATHIEEERESOURCEF_SGLBAS	(1<<2)
#define	MATHIEEERESOURCEF_SGLTRANS	(1<<3)
#define	MATHIEEERESOURCEF_EXTBAS	(1<<4)
#define	MATHIEEERESOURCEF_EXTTRANS	(1<<5)

#endif	/* RESOURCES_MATHRESOURCE_H */


include/exec/memory.h

#ifndef	EXEC_MEMORY_H
#define	EXEC_MEMORY_H
/*
**	$VER: memory.h 39.3 (21.5.1992)
**	Includes Release 44.1
**
**	Definitions and structures used by the memory allocation system
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_NODES_H
#include <exec/nodes.h>
#endif /* EXEC_NODES_H */

/****** MemChunk ****************************************************/

struct	MemChunk {
    struct  MemChunk *mc_Next;	/* pointer to next chunk */
    ULONG   mc_Bytes;		/* chunk byte size	*/
};

/****** MemHeader ***************************************************/

struct	MemHeader {
    struct  Node mh_Node;
    UWORD   mh_Attributes;	/* characteristics of this region */
    struct  MemChunk *mh_First; /* first free region		*/
    APTR    mh_Lower;		/* lower memory bound		*/
    APTR    mh_Upper;		/* upper memory bound+1	*/
    ULONG   mh_Free;		/* total number of free bytes	*/
};

/****** MemEntry ****************************************************/

struct	MemEntry {
union {
    ULONG   meu_Reqs;		/* the AllocMem requirements */
    APTR    meu_Addr;		/* the address of this memory region */
    } me_Un;
    ULONG   me_Length;		/* the length of this memory region */
};

#define me_un	    me_Un	/* compatibility - do not use*/
#define me_Reqs     me_Un.meu_Reqs
#define me_Addr     me_Un.meu_Addr

/****** MemList *****************************************************/

/* Note: sizeof(struct MemList) includes the size of the first MemEntry! */
struct	MemList {
    struct  Node ml_Node;
    UWORD   ml_NumEntries;	/* number of entries in this struct */
    struct  MemEntry ml_ME[1];	/* the first entry	*/
};

#define ml_me	ml_ME		/* compatability - do not use */

/*----- Memory Requirement Types ---------------------------*/
/*----- See the AllocMem() documentation for details--------*/

#define MEMF_ANY    (0L)	/* Any type of memory will do */
#define MEMF_PUBLIC (1L<<0)
#define MEMF_CHIP   (1L<<1)
#define MEMF_FAST   (1L<<2)
#define MEMF_LOCAL  (1L<<8)	/* Memory that does not go away at RESET */
#define MEMF_24BITDMA (1L<<9)	/* DMAable memory within 24 bits of address */
#define	MEMF_KICK   (1L<<10)	/* Memory that can be used for KickTags */

#define MEMF_CLEAR   (1L<<16)	/* AllocMem: NULL out area before return */
#define MEMF_LARGEST (1L<<17)	/* AvailMem: return the largest chunk size */
#define MEMF_REVERSE (1L<<18)	/* AllocMem: allocate from the top down */
#define MEMF_TOTAL   (1L<<19)	/* AvailMem: return total size of memory */

#define	MEMF_NO_EXPUNGE	(1L<<31) /*AllocMem: Do not cause expunge on failure */

/*----- Current alignment rules for memory blocks (may increase) -----*/
#define MEM_BLOCKSIZE	8L
#define MEM_BLOCKMASK	(MEM_BLOCKSIZE-1)

/****** MemHandlerData **********************************************/
/* Note:  This structure is *READ ONLY* and only EXEC can create it!*/
struct MemHandlerData
{
    ULONG	memh_RequestSize;	/* Requested allocation size */
    ULONG	memh_RequestFlags;	/* Requested allocation flags */
    ULONG	memh_Flags;		/* Flags (see below) */
};

#define	MEMHF_RECYCLE	(1L<<0)	/* 0==First time, 1==recycle */

/****** Low Memory handler return values ***************************/
#define	MEM_DID_NOTHING	(0)	/* Nothing we could do... */
#define	MEM_ALL_DONE	(-1)	/* We did all we could do */
#define	MEM_TRY_AGAIN	(1)	/* We did some, try the allocation again */

#endif	/* EXEC_MEMORY_H */


include/exec/ports.h

#ifndef	EXEC_PORTS_H
#define	EXEC_PORTS_H
/*
**	$VER: ports.h 39.0 (15.10.1991)
**	Includes Release 44.1
**
**	Message ports and Messages.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_NODES_H
#include <exec/nodes.h>
#endif /* EXEC_NODES_H */

#ifndef EXEC_LISTS_H
#include <exec/lists.h>
#endif /* EXEC_LISTS_H */

#ifndef EXEC_TASKS_H
#include <exec/tasks.h>
#endif /* EXEC_TASKS_H */

/****** MsgPort *****************************************************/

struct MsgPort {
    struct  Node mp_Node;
    UBYTE   mp_Flags;
    UBYTE   mp_SigBit;		/* signal bit number	*/
    void   *mp_SigTask;		/* object to be signalled */
    struct  List mp_MsgList;	/* message linked list	*/
};

#define mp_SoftInt mp_SigTask	/* Alias */

/* mp_Flags: Port arrival actions (PutMsg) */
#define PF_ACTION	3	/* Mask */
#define PA_SIGNAL	0	/* Signal task in mp_SigTask */
#define PA_SOFTINT	1	/* Signal SoftInt in mp_SoftInt/mp_SigTask */
#define PA_IGNORE	2	/* Ignore arrival */

/****** Message *****************************************************/

struct Message {
    struct  Node mn_Node;
    struct  MsgPort *mn_ReplyPort;  /* message reply port */
    UWORD   mn_Length;		    /* total message length, in bytes */
                    /* (include the size of the Message */
                    /* structure in the length) */
};

#endif	/* EXEC_PORTS_H */


include/exec/nodes.h

#ifndef	EXEC_NODES_H
#define	EXEC_NODES_H
/*
**	$VER: nodes.h 39.0 (15.10.1991)
**	Includes Release 44.1
**
**	Nodes & Node type identifiers.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif /* EXEC_TYPES_H */

/*
 *  List Node Structure.  Each member in a list starts with a Node
 */

struct Node {
    struct  Node *ln_Succ;	/* Pointer to next (successor) */
    struct  Node *ln_Pred;	/* Pointer to previous (predecessor) */
    UBYTE   ln_Type;
    BYTE    ln_Pri;		/* Priority, for sorting */
    char    *ln_Name;		/* ID string, null terminated */
};	/* Note: word aligned */

/* minimal node -- no type checking possible */
struct MinNode {
    struct MinNode *mln_Succ;
    struct MinNode *mln_Pred;
};

/*
** Note: Newly initialized IORequests, and software interrupt structures
** used with Cause(), should have type NT_UNKNOWN.  The OS will assign a type
** when they are first used.
*/
/*----- Node Types for LN_TYPE -----*/
#define NT_UNKNOWN	0
#define NT_TASK		1	/* Exec task */
#define NT_INTERRUPT	2
#define NT_DEVICE	3
#define NT_MSGPORT	4
#define NT_MESSAGE	5	/* Indicates message currently pending */
#define NT_FREEMSG	6
#define NT_REPLYMSG	7	/* Message has been replied */
#define NT_RESOURCE	8
#define NT_LIBRARY	9
#define NT_MEMORY	10
#define NT_SOFTINT	11	/* Internal flag used by SoftInits */
#define NT_FONT		12
#define NT_PROCESS	13	/* AmigaDOS Process */
#define NT_SEMAPHORE	14
#define NT_SIGNALSEM	15	/* signal semaphores */
#define NT_BOOTNODE	16
#define NT_KICKMEM	17
#define NT_GRAPHICS	18
#define NT_DEATHMESSAGE	19

#define NT_USER		254	/* User node types work down from here */
#define NT_EXTENDED	255

#endif	/* EXEC_NODES_H */


include/devices/narrator.h

#ifndef DEVICES_NARRATOR_H
#define DEVICES_NARRATOR_H
/*
**	$VER: narrator.h 1.7 (12.3.1991)
**	Includes Release 44.1
**
**	V37 Narrator device C language include file
**
**	Copyright 1990, 1991 Joseph Katz/Mark Barton.
**	All rights reserved.
**
**	This include file (narrator.h) may be freely distributed
**	as long as the above copyright notice remains intact.
**
*/

#ifndef EXEC_IO_H
#include <exec/io.h>
#endif

        /*	    Device Options	*/

#define NDB_NEWIORB	0	/* Use new extended IORB		*/
#define NDB_WORDSYNC	1	/* Generate word sync messages		*/
#define NDB_SYLSYNC	2	/* Generate syllable sync messages	*/

#define NDF_NEWIORB	(1 << NDB_NEWIORB)
#define NDF_WORDSYNC	(1 << NDB_WORDSYNC)
#define NDF_SYLSYNC	(1 << NDB_SYLSYNC)

        /*	    Error Codes		*/

#define ND_NoMem	-2	/* Can't allocate memory		*/
#define ND_NoAudLib	-3	/* Can't open audio device		*/
#define ND_MakeBad	-4	/* Error in MakeLibrary call		*/
#define ND_UnitErr	-5	/* Unit other than 0			*/
#define ND_CantAlloc	-6	/* Can't allocate audio channel(s)	*/
#define ND_Unimpl	-7	/* Unimplemented command		*/
#define ND_NoWrite	-8	/* Read for mouth without write first	*/
#define ND_Expunged	-9	/* Can't open, deferred expunge bit set	*/
#define ND_PhonErr     -20	/* Phoneme code spelling error			*/
#define ND_RateErr     -21	/* Rate out of bounds			*/
#define ND_PitchErr    -22	/* Pitch out of bounds				*/
#define ND_SexErr      -23	/* Sex not valid			*/
#define ND_ModeErr     -24	/* Mode not valid			*/
#define ND_FreqErr     -25	/* Sampling frequency out of bounds	*/
#define ND_VolErr      -26	/* Volume out of bounds		*/
#define ND_DCentErr    -27	/* Degree of centralization out of bounds */
#define ND_CentPhonErr -28	/* Invalid central phon			*/

        /* Input parameters and defaults */

#define DEFPITCH    110		/* Default pitch			*/
#define DEFRATE     150		/* Default speaking rate (wpm)			*/
#define DEFVOL	    64		/* Default volume (full)		*/
#define DEFFREQ     22200	/* Default sampling frequency (Hz)	*/
#define MALE	    0		/* Male vocal tract			*/
#define FEMALE	    1		/* Female vocal tract			*/
#define NATURALF0   0		/* Natural pitch contours		*/
#define ROBOTICF0   1		/* Monotone pitch			*/
#define MANUALF0    2		/* Manual setting of pitch contours	*/
#define DEFSEX	    MALE	/* Default sex					*/
#define DEFMODE     NATURALF0	/* Default mode			*/
#define	DEFARTIC    100		/* 100% articulation (normal)		*/
#define DEFCENTRAL  0		/* No centralization			*/
#define DEFF0PERT   0		/* No F0 Perturbation			*/
#define DEFF0ENTHUS 32		/* Default F0 enthusiasm (in 32nds)	*/
#define DEFPRIORITY 100		/* Default speaking priority		*/

            /*	Parameter bounds	*/

#define MINRATE     40		/* Minimum speaking rate		*/
#define MAXRATE     400		/* Maximum speaking rate		*/
#define MINPITCH    65		/* Minimum pitch			*/
#define MAXPITCH    320		/* Maximum pitch			*/
#define MINFREQ     5000	/* Minimum sampling frequency		*/
#define MAXFREQ     28000	/* Maximum sampling frequency		*/
#define MINVOL	    0		/* Minimum volume			*/
#define MAXVOL	    64		/* Maximum volume			*/
#define MINCENT      0		/* Minimum degree of centralization	*/
#define MAXCENT    100		/* Maximum degree of centralization	*/

        /*    Standard Write request	*/

struct narrator_rb {
    struct IOStdReq  message;	/* Standard IORB		*/
    UWORD	rate;			/* Speaking rate (words/minute) */
    UWORD	pitch;			/* Baseline pitch in Hertz		*/
    UWORD	mode;			/* Pitch mode			*/
    UWORD	sex;			/* Sex of voice			*/
    UBYTE	*ch_masks;		/* Pointer to audio alloc maps	*/
    UWORD	nm_masks;		/* Number of audio alloc maps	*/
    UWORD	volume;			/* Volume. 0 (off) thru 64	*/
    UWORD	sampfreq;		/* Audio sampling freq			*/
    UBYTE	mouths;			/* If non-zero, generate mouths */
    UBYTE	chanmask;		/* Which ch mask used (internal)*/
    UBYTE	numchan;		/* Num ch masks used (internal) */
    UBYTE	flags;			/* New feature flags		*/
    UBYTE	F0enthusiasm;		/* F0 excursion factor		*/
    UBYTE	F0perturb;		/* Amount of F0 perturbation	*/
    BYTE	F1adj;			/* F1 adjustment in ±5% steps	*/
    BYTE	F2adj;				/* F2 adjustment in ±5% steps	*/
    BYTE	F3adj;			/* F3 adjustment in ±5% steps	*/
    BYTE	A1adj;			/* A1 adjustment in decibels	*/
    BYTE	A2adj;			/* A2 adjustment in decibels	*/
    BYTE	A3adj;			/* A3 adjustment in decibels	*/
    UBYTE	articulate;		/* Transition time multiplier	*/
    UBYTE	centralize;		/* Degree of vowel centralization */
    char	*centphon;		/* Pointer to central ASCII phon  */
    BYTE	AVbias;			/* AV bias			*/
    BYTE	AFbias;			/* AF bias			*/
    BYTE	priority;		/* Priority while speaking	*/
    BYTE	pad1;			/* For alignment		*/
    };

        /*    Standard Read request	*/

struct mouth_rb {
    struct	narrator_rb voice;	/* Speech IORB			*/
    UBYTE	width;			/* Width (returned value)	*/
    UBYTE	height;			/* Height (returned value)	*/
    UBYTE	shape;			/* Internal use, do not modify	*/
    UBYTE	sync;			/* Returned sync events		*/
    };

#endif	/* DEVICES_NARRATOR_H */


include/utility/name.h

#ifndef UTILITY_NAME_H
#define	UTILITY_NAME_H
/*
**	$VER: name.h 39.5 (11.8.1993)
**	Includes Release 44.1
**
**	Namespace definitions
**
**	(C) Copyright 1992-1999 Amiga, Inc.
**	All Rights Reserved
**/

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

/*****************************************************************************/

/* The named object structure */
struct NamedObject
{
    APTR no_Object;	/* Your pointer, for whatever you want */
};

/* Tags for AllocNamedObject() */
#define	ANO_NameSpace	4000	/* Tag to define namespace	*/
#define	ANO_UserSpace	4001	/* tag to define userspace	*/
#define	ANO_Priority	4002	/* tag to define priority	*/
#define	ANO_Flags	4003	/* tag to define flags		*/

/* Flags for tag ANO_Flags */
#define	NSB_NODUPS	0
#define	NSB_CASE	1

#define	NSF_NODUPS	(1L << NSB_NODUPS)	/* Default allow duplicates */
#define	NSF_CASE	(1L << NSB_CASE)	/* Default to caseless... */

/*****************************************************************************/

#endif /* UTILITY_NAME_H */


include/libraries/commodities.h

#ifndef LIBRARIES_COMMODITIES_H
#define LIBRARIES_COMMODITIES_H
/*
**	$VER: commodities.h 38.4 (24.2.1993)
**	Includes Release 44.1
**
**	Commodities definitions
**
**	(C) Copyright 1990-1999 Amiga, Inc.
**	All Rights Reserved
*/

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef EXEC_PORTS_H
#include <exec/ports.h>
#endif

/*****************************************************************************/

/* object creation macros */
#define CxFilter(d)	    CreateCxObj((LONG) CX_FILTER,     (LONG) d,     0)
#define CxSender(port,id)   CreateCxObj((LONG) CX_SEND,       (LONG) port,  (LONG) id)
#define CxSignal(task,sig)  CreateCxObj((LONG) CX_SIGNAL,     (LONG) task,  (LONG) sig)
#define CxTranslate(ie)     CreateCxObj((LONG) CX_TRANSLATE,  (LONG) ie,    0)
#define CxDebug(id)	    CreateCxObj((LONG) CX_DEBUG,      (LONG) id,    0)
#define CxCustom(action,id) CreateCxObj((LONG) CX_CUSTOM,     (LONG)action, (LONG)id)

/*****************************************************************************/

struct NewBroker
{
    BYTE	    nb_Version;   /* Must be set to NB_VERSION */
    STRPTR	    nb_Name;
    STRPTR	    nb_Title;
    STRPTR	    nb_Descr;
    WORD	    nb_Unique;
    WORD	    nb_Flags;
    BYTE	    nb_Pri;
    struct MsgPort *nb_Port;
    WORD	    nb_ReservedChannel;
};

/* constant for NewBroker.nb_Version */
#define NB_VERSION 5	    /* Version of NewBroker structure */

/* Sizes for various buffers */
#define CBD_NAMELEN  24
#define CBD_TITLELEN 40
#define CBD_DESCRLEN 40

/* Flags for NewBroker.nb_Unique */
#define NBU_DUPLICATE 0
#define NBU_UNIQUE    1        /* will not allow duplicates	      */
#define NBU_NOTIFY    2        /* sends CXM_UNIQUE to existing broker */

/* Flags for NewBroker.nb_Flags */
#define COF_SHOW_HIDE 4

/*****************************************************************************/

/* Fake data types for system private objects */
#ifndef COMMODITIES_BASE_H
typedef LONG CxObj;
typedef LONG CxMsg;
#endif

/* Pointer to a function returning a LONG */
typedef LONG (*PFL)();

/*****************************************************************************/

/* Commodities object types */
#define CX_INVALID	0     /* not a valid object (probably null) */
#define CX_FILTER	1     /* input event messages only	    */
#define CX_TYPEFILTER	2     /* obsolete, do not use		    */
#define CX_SEND	3     /* sends a message		    */
#define CX_SIGNAL	4     /* sends a signal		    */
#define CX_TRANSLATE	5     /* translates input event into chain  */
#define CX_BROKER	6     /* application representative	    */
#define CX_DEBUG	7     /* dumps info to serial port	    */
#define CX_CUSTOM	8     /* application provides function	    */
#define CX_ZERO	9     /* system terminator node	    */

/*****************************************************************************/

/* Commodities message types */
#define CXM_IEVENT  (1 << 5)
#define CXM_COMMAND (1 << 6)

/* Only CXM_IEVENT messages are passed through the input network. Other types
 * of messages are sent to an optional port in your broker. This means that
 * you must test the message type in your message handling, if input messages
 * and command messages come to the same port.
 *
 * CXM_IEVENT: Messages of this type rattle around the Commodities input
 *	       network. They are sent to you by a Sender object, and passed
 *	       to you as a synchronous function call by a Custom object.
 *
 *	       The message port or function entry point is stored in the
 *	       object, and the ID field of the message will be set to what
 *	       you arrange issuing object.
 *
 *	       The data section of the message will point to the input event
 *	       triggering the message.
 *
 * CXM_COMMAND: These messages are sent to a port attached to your Broker.
 *		They are sent to you when the controller program wants your
 *		program to do something. The ID value identifies the command.
 */

/* ID values associated with a message of type CXM_COMMAND */
#define CXCMD_DISABLE	(15)  /* please disable yourself	 */
#define CXCMD_ENABLE	(17)  /* please enable yourself	 */
#define CXCMD_APPEAR	(19)  /* open your window, if you can	 */
#define CXCMD_DISAPPEAR (21)  /* go dormant			 */
#define CXCMD_KILL	(23)  /* go away for good		 */
#define CXCMD_LIST_CHG	(27)  /* Someone changed the broker list */
#define CXCMD_UNIQUE	(25)  /* someone tried to create a broker
                   * with your name. Suggest you appear.
                   */

/*****************************************************************************/

struct InputXpression
{
    UBYTE ix_Version;	  /* must be set to IX_VERSION */
    UBYTE ix_Class;	  /* class must match exactly  */

    UWORD ix_Code;	  /* Bits that we want */
    UWORD ix_CodeMask;	  /* Set bits here to indicate which bits in ix_Code
               * are don't care bits.
               */
    UWORD ix_Qualifier;   /* Bits that we want */
    UWORD ix_QualMask;	  /* Set bits here to indicate which bits in
               * ix_Qualifier are don't care bits
               */
    UWORD ix_QualSame;	  /* synonyms in qualifier */
};
typedef struct InputXpression IX;

/* constant for InputXpression.ix_Version */
#define IX_VERSION 2

/* constants for InputXpression.ix_QualSame */
#define IXSYM_SHIFT 1	/* left- and right- shift are equivalent     */
#define IXSYM_CAPS  2	/* either shift or caps lock are equivalent  */
#define IXSYM_ALT   4	/* left- and right- alt are equivalent	     */

#define IXSYM_SHIFTMASK (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)
#define IXSYM_CAPSMASK	(IXSYM_SHIFTMASK | IEQUALIFIER_CAPSLOCK)
#define IXSYM_ALTMASK	(IEQUALIFIER_LALT | IEQUALIFIER_RALT)

/* constant for InputXpression.ix_QualMask */
#define IX_NORMALQUALS	0x7FFF	 /* avoid RELATIVEMOUSE */

/* matches nothing */
#define NULL_IX(ix)   ((ix)->ix_Class == IECLASS_NULL)

/*****************************************************************************/

/* Error returns from CxBroker() */
#define CBERR_OK      0  /* No error				   */
#define CBERR_SYSERR  1  /* System error, no memory, etc	   */
#define CBERR_DUP     2  /* uniqueness violation		   */
#define CBERR_VERSION 3  /* didn't understand NewBroker.nb_Version */

/*****************************************************************************/

/* Return values from CxObjError() */
#define COERR_ISNULL	 1   /* you called CxObjError(NULL)	   */
#define COERR_NULLATTACH 2   /* someone attached NULL to my list   */
#define COERR_BADFILTER  4   /* a bad filter description was given */
#define COERR_BADTYPE	 8   /* unmatched type-specific operation  */

/*****************************************************************************/

#endif /* LIBRARIES_COMMODITIES_H */


include/rexx/storage.h

#ifndef REXX_STORAGE_H
#define REXX_STORAGE_H
/*
**	$VER: storage.h 1.4 (8.11.1991)
**	Includes Release 44.1
**
**	Header file to define ARexx data structures.
**
**	(C) Copyright 1986,1987,1988,1989,1990 William S. Hawes
**	(C) Copyright 1990-1999 Amiga, Inc.
**		All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef EXEC_NODES_H
#include <exec/nodes.h>
#endif

#ifndef EXEC_LISTS_H
#include <exec/lists.h>
#endif

#ifndef EXEC_PORTS_H
#include <exec/ports.h>
#endif

#ifndef EXEC_LIBRARIES_H
#include <exec/libraries.h>
#endif

/* The NexxStr structure is used to maintain the internal strings in REXX.
 * It includes the buffer area for the string and associated attributes.
 * This is actually a variable-length structure; it is allocated for a
 * specific length string, and the length is never modified thereafter
 * (since it's used for recycling).
 */

struct NexxStr {
   LONG     ns_Ivalue;		       /* integer value		*/
   UWORD    ns_Length;		       /* length in bytes (excl null)	*/
   UBYTE    ns_Flags;		       /* attribute flags		*/
   UBYTE    ns_Hash;		       /* hash code			*/
   BYTE     ns_Buff[8];	       /* buffer area for strings	*/
   };				       /* size: 16 bytes (minimum)	*/

#define NXADDLEN 9		       /* offset plus null byte	*/
#define IVALUE(nsPtr) (nsPtr->ns_Ivalue)

/* String attribute flag bit definitions				*/
#define NSB_KEEP     0		       /* permanent string?		*/
#define NSB_STRING   1		       /* string form valid?		*/
#define NSB_NOTNUM   2		       /* non-numeric?			*/
#define NSB_NUMBER   3		       /* a valid number?		*/
#define NSB_BINARY   4		       /* integer value saved?		*/
#define NSB_FLOAT    5		       /* floating point format?	*/
#define NSB_EXT      6		       /* an external string?		*/
#define NSB_SOURCE   7		       /* part of the program source?	*/

/* The flag form of the string attributes				*/
#define NSF_KEEP     (1 << NSB_KEEP  )
#define NSF_STRING   (1 << NSB_STRING)
#define NSF_NOTNUM   (1 << NSB_NOTNUM)
#define NSF_NUMBER   (1 << NSB_NUMBER)
#define NSF_BINARY   (1 << NSB_BINARY)
#define NSF_FLOAT    (1 << NSB_FLOAT )
#define NSF_EXT      (1 << NSB_EXT   )
#define NSF_SOURCE   (1 << NSB_SOURCE)

/* Combinations of flags						*/
#define NSF_INTNUM   (NSF_NUMBER | NSF_BINARY | NSF_STRING)
#define NSF_DPNUM    (NSF_NUMBER | NSF_FLOAT)
#define NSF_ALPHA    (NSF_NOTNUM | NSF_STRING)
#define NSF_OWNED    (NSF_SOURCE | NSF_EXT    | NSF_KEEP)
#define KEEPSTR      (NSF_STRING | NSF_SOURCE | NSF_NOTNUM)
#define KEEPNUM      (NSF_STRING | NSF_SOURCE | NSF_NUMBER | NSF_BINARY)

/* The RexxArg structure is identical to the NexxStr structure, but
 * is allocated from system memory rather than from internal storage.
 * This structure is used for passing arguments to external programs.
 * It is usually passed as an "argstring", a pointer to the string buffer.
 */

struct RexxArg {
   LONG     ra_Size;		       /* total allocated length	*/
   UWORD    ra_Length;		       /* length of string		*/
   UBYTE    ra_Flags;		       /* attribute flags		*/
   UBYTE    ra_Hash;		       /* hash code			*/
   BYTE     ra_Buff[8];	       /* buffer area			*/
   };				       /* size: 16 bytes (minimum)	*/

/* The RexxMsg structure is used for all communications with REXX
 * programs.  It is an EXEC message with a parameter block appended.
 */

struct RexxMsg {
   struct Message rm_Node;	       /* EXEC message structure	*/
   APTR     rm_TaskBlock;	       /* global structure (private)	*/
   APTR     rm_LibBase;	       /* library base (private)	*/
   LONG     rm_Action;		       /* command (action) code	*/
   LONG     rm_Result1;	       /* primary result (return code)	*/
   LONG     rm_Result2;	       /* secondary result		*/
   STRPTR   rm_Args[16];	       /* argument block (ARG0-ARG15)	*/

   struct MsgPort *rm_PassPort;        /* forwarding port		*/
   STRPTR   rm_CommAddr;	       /* host address (port name)	*/
   STRPTR   rm_FileExt;	       /* file extension		*/
   LONG     rm_Stdin;		       /* input stream (filehandle)	*/
   LONG     rm_Stdout;		       /* output stream (filehandle)	*/
   LONG     rm_avail;		       /* future expansion		*/
   };				       /* size: 128 bytes		*/

/* Field definitions							*/
#define ARG0(rmp) (rmp->rm_Args[0])    /* start of argblock		*/
#define ARG1(rmp) (rmp->rm_Args[1])    /* first argument		*/
#define ARG2(rmp) (rmp->rm_Args[2])    /* second argument		*/

#define MAXRMARG  15		       /* maximum arguments		*/

/* Command (action) codes for message packets				*/
#define RXCOMM	  0x01000000	       /* a command-level invocation	*/
#define RXFUNC	  0x02000000	       /* a function call		*/
#define RXCLOSE   0x03000000	       /* close the REXX server	*/
#define RXQUERY   0x04000000	       /* query for information	*/
#define RXADDFH   0x07000000	       /* add a function host		*/
#define RXADDLIB  0x08000000	       /* add a function library	*/
#define RXREMLIB  0x09000000	       /* remove a function library	*/
#define RXADDCON  0x0A000000	       /* add/update a ClipList string	*/
#define RXREMCON  0x0B000000	       /* remove a ClipList string	*/
#define RXTCOPN   0x0C000000	       /* open the trace console	*/
#define RXTCCLS   0x0D000000	       /* close the trace console	*/

/* Command modifier flag bits						*/
#define RXFB_NOIO    16	       /* suppress I/O inheritance?	*/
#define RXFB_RESULT  17	       /* result string expected?	*/
#define RXFB_STRING  18	       /* program is a "string file"?	*/
#define RXFB_TOKEN   19	       /* tokenize the command line?	*/
#define RXFB_NONRET  20	       /* a "no-return" message?	*/

/* The flag form of the command modifiers				*/
#define RXFF_NOIO    (1L << RXFB_NOIO  )
#define RXFF_RESULT  (1L << RXFB_RESULT)
#define RXFF_STRING  (1L << RXFB_STRING)
#define RXFF_TOKEN   (1L << RXFB_TOKEN )
#define RXFF_NONRET  (1L << RXFB_NONRET)

#define RXCODEMASK   0xFF000000
#define RXARGMASK    0x0000000F

/* The RexxRsrc structure is used to manage global resources.  Each node
 * has a name string created as a RexxArg structure, and the total size
 * of the node is saved in the "rr_Size" field.  The REXX systems library
 * provides functions to allocate and release resource nodes.  If special
 * deletion operations are required, an offset and base can be provided in
 * "rr_Func" and "rr_Base", respectively.  This "autodelete" function will
 * be called with the base in register A6 and the node in A0.
 */

struct RexxRsrc {
   struct Node rr_Node;
   WORD     rr_Func;		       /* "auto-delete" offset		*/
   APTR     rr_Base;		       /* "auto-delete" base		*/
   LONG     rr_Size;		       /* total size of node		*/
   LONG     rr_Arg1;		       /* available ...		*/
   LONG     rr_Arg2;		       /* available ...		*/
   };				       /* size: 32 bytes		*/

/* Resource node types							*/
#define RRT_ANY      0		       /* any node type ...		*/
#define RRT_LIB      1		       /* a function library		*/
#define RRT_PORT     2		       /* a public port		*/
#define RRT_FILE     3		       /* a file IoBuff		*/
#define RRT_HOST     4		       /* a function host		*/
#define RRT_CLIP     5		       /* a Clip List node		*/

/* The RexxTask structure holds the fields used by REXX to communicate with
 * external processes, including the client task.  It includes the global
 * data structure (and the base environment).  The structure is passed to
 * the newly-created task in its "wake-up" message.
 */

#define GLOBALSZ  200		       /* total size of GlobalData	*/

struct RexxTask {
   BYTE     rt_Global[GLOBALSZ];       /* global data structure	*/
   struct MsgPort rt_MsgPort;	       /* global message port		*/
   UBYTE    rt_Flags;		       /* task flag bits		*/
   BYTE     rt_SigBit;		       /* signal bit			*/

   APTR     rt_ClientID;	       /* the client's task ID		*/
   APTR     rt_MsgPkt;		       /* the packet being processed	*/
   APTR     rt_TaskID;		       /* our task ID			*/
   APTR     rt_RexxPort;	       /* the REXX public port		*/

   APTR     rt_ErrTrap;	       /* Error trap address		*/
   APTR     rt_StackPtr;	       /* stack pointer for traps	*/

   struct List rt_Header1;	       /* Environment list		*/
   struct List rt_Header2;	       /* Memory freelist		*/
   struct List rt_Header3;	       /* Memory allocation list	*/
   struct List rt_Header4;	       /* Files list			*/
   struct List rt_Header5;	       /* Message Ports List		*/
   };

/* Definitions for RexxTask flag bits					*/
#define RTFB_TRACE   0		       /* external trace flag		*/
#define RTFB_HALT    1		       /* external halt flag		*/
#define RTFB_SUSP    2		       /* suspend task?		*/
#define RTFB_TCUSE   3		       /* trace console in use?	*/
#define RTFB_WAIT    6		       /* waiting for reply?		*/
#define RTFB_CLOSE   7		       /* task completed?		*/

/* Definitions for memory allocation constants				*/
#define MEMQUANT  16L		       /* quantum of memory space	*/
#define MEMMASK   0xFFFFFFF0	       /* mask for rounding the size	*/

#define MEMQUICK  (1L << 0 )	       /* EXEC flags: MEMF_PUBLIC	*/
#define MEMCLEAR  (1L << 16)	       /* EXEC flags: MEMF_CLEAR	*/

/* The SrcNode is a temporary structure used to hold values destined for
 * a segment array.  It is also used to maintain the memory freelist.
 */

struct SrcNode {
   struct SrcNode *sn_Succ;	       /* next node			*/
   struct SrcNode *sn_Pred;	       /* previous node		*/
   APTR     sn_Ptr;		       /* pointer value		*/
   LONG     sn_Size;		       /* size of object		*/
   };				       /* size: 16 bytes		*/

#endif


include/dos/notify.h

#ifndef DOS_NOTIFY_H
#define DOS_NOTIFY_H
/*
**
**	$VER: notify.h 36.8 (29.8.1990)
**	Includes Release 44.1
**
**	dos notification definitions
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef EXEC_PORTS_H
#include <exec/ports.h>
#endif

#ifndef EXEC_TASKS_H
#include <exec/tasks.h>
#endif

/* use of Class and code is discouraged for the time being - we might want to
   change things */
/* --- NotifyMessage Class ------------------------------------------------ */
#define NOTIFY_CLASS	0x40000000

/* --- NotifyMessage Codes ------------------------------------------------ */
#define NOTIFY_CODE	0x1234

/* Sent to the application if SEND_MESSAGE is specified.		    */

struct NotifyMessage {
    struct Message nm_ExecMessage;
    ULONG  nm_Class;
    UWORD  nm_Code;
    struct NotifyRequest *nm_NReq;	/* don't modify the request! */
    ULONG  nm_DoNotTouch;		/* like it says!  For use by handlers */
    ULONG  nm_DoNotTouch2;		/* ditto */
};

/* Do not modify or reuse the notifyrequest while active.		    */
/* note: the first LONG of nr_Data has the length transfered		    */

struct NotifyRequest {
    UBYTE *nr_Name;
    UBYTE *nr_FullName;		/* set by dos - don't touch */
    ULONG nr_UserData;		/* for applications use */
    ULONG nr_Flags;

    union {

        struct {
        struct MsgPort *nr_Port;	/* for SEND_MESSAGE */
        } nr_Msg;

        struct {
        struct Task *nr_Task;		/* for SEND_SIGNAL */
        UBYTE nr_SignalNum;		/* for SEND_SIGNAL */
        UBYTE nr_pad[3];
        } nr_Signal;
    } nr_stuff;

    ULONG nr_Reserved[4];		/* leave 0 for now */

    /* internal use by handlers */
    ULONG nr_MsgCount;		/* # of outstanding msgs */
    struct MsgPort *nr_Handler;	/* handler sent to (for EndNotify) */
};

/* --- NotifyRequest Flags ------------------------------------------------ */
#define NRF_SEND_MESSAGE	1
#define NRF_SEND_SIGNAL		2
#define NRF_WAIT_REPLY		8
#define NRF_NOTIFY_INITIAL	16

/* do NOT set or remove NRF_MAGIC!  Only for use by handlers! */
#define NRF_MAGIC	0x80000000

/* bit numbers */
#define NRB_SEND_MESSAGE	0
#define NRB_SEND_SIGNAL		1
#define NRB_WAIT_REPLY		3
#define NRB_NOTIFY_INITIAL	4

#define NRB_MAGIC		31

/* Flags reserved for private use by the handler: */
#define NR_HANDLER_FLAGS	0xffff0000

#endif /* DOS_NOTIFY_H */


include/libraries/nonvolatile.h

#ifndef LIBRARIES_NONVOLATILE_H
#define LIBRARIES_NONVOLATILE_H

/*
**	$VER: nonvolatile.h 40.8 (30.7.1993)
**	Includes Release 44.1
**
**	nonvolatile.library interface structures and defintions.
**
**	(C) Copyright 1992-1999 Amiga, Inc.
**	All Rights Reserved
*/

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef EXEC_NODES_H
#include <exec/nodes.h>
#endif

/*****************************************************************************/

struct NVInfo
{
    ULONG nvi_MaxStorage;
    ULONG nvi_FreeStorage;
};

/*****************************************************************************/

struct NVEntry
{
    struct MinNode nve_Node;
    STRPTR	   nve_Name;
    ULONG	   nve_Size;
    ULONG	   nve_Protection;
};

/* bit definitions for mask in SetNVProtection().  Also used for
 * NVEntry.nve_Protection.
 */
#define NVEB_DELETE  0
#define NVEB_APPNAME 31

#define NVEF_DELETE  (1<<NVEB_DELETE)
#define NVEF_APPNAME (1<<NVEB_APPNAME)

/*****************************************************************************/

/* errors from StoreNV() */
#define NVERR_BADNAME	1
#define NVERR_WRITEPROT 2
#define NVERR_FAIL	3
#define NVERR_FATAL	4

/*****************************************************************************/

/* determine the size of data returned by this library */
#define SizeNVData(DataPtr) ((((ULONG *) DataPtr)[-1]) - 4)

/*****************************************************************************/

#endif /* LIBRARIES_NONVOLATILE_H */


include/intuition/classusr.h

#ifndef	INTUITION_CLASSUSR_H
#define INTUITION_CLASSUSR_H	1
/*
**  $VER: classusr.h 38.2 (14.4.1992)
**  Includes Release 44.1
**
**  For application users of Intuition object classes
**
**  (C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef UTILITY_HOOKS_H
#include <utility/hooks.h>
#endif

/*** User visible handles on objects, classes, messages ***/
typedef ULONG	Object;		/* abstract handle */

typedef	UBYTE	*ClassID;

/* you can use this type to point to a "generic" message,
 * in the object-oriented programming parlance.  Based on
 * the value of 'MethodID', you dispatch to processing
 * for the various message types.  The meaningful parameter
 * packet structure definitions are defined below.
 */
typedef struct {
    ULONG MethodID;
    /* method-specific data follows, some examples below */
}		*Msg;

/*
 * Class id strings for Intuition classes.
 * There's no real reason to use the uppercase constants
 * over the lowercase strings, but this makes a good place
 * to list the names of the built-in classes.
 */
#define ROOTCLASS	"rootclass"		/* classusr.h	  */
#define IMAGECLASS	"imageclass"		/* imageclass.h   */
#define FRAMEICLASS	"frameiclass"
#define SYSICLASS	"sysiclass"
#define FILLRECTCLASS	"fillrectclass"
#define GADGETCLASS	"gadgetclass"		/* gadgetclass.h  */
#define PROPGCLASS	"propgclass"
#define STRGCLASS	"strgclass"
#define BUTTONGCLASS	"buttongclass"
#define FRBUTTONCLASS	"frbuttonclass"
#define GROUPGCLASS	"groupgclass"
#define ICCLASS		"icclass"		/* icclass.h	  */
#define MODELCLASS	"modelclass"
#define ITEXTICLASS	"itexticlass"
#define POINTERCLASS	"pointerclass"		/* pointerclass.h */

/* Dispatched method ID's
 * NOTE: Applications should use Intuition entry points, not direct
 * DoMethod() calls, for NewObject, DisposeObject, SetAttrs,
 * SetGadgetAttrs, and GetAttr.
 */

#define OM_Dummy	(0x100)
#define OM_NEW		(0x101)	/* 'object' parameter is "true class"	*/
#define OM_DISPOSE	(0x102)	/* delete self (no parameters)		*/
#define OM_SET		(0x103)	/* set attributes (in tag list)		*/
#define OM_GET		(0x104)	/* return single attribute value	*/
#define OM_ADDTAIL	(0x105)	/* add self to a List (let root do it)	*/
#define OM_REMOVE	(0x106)	/* remove self from list		*/
#define OM_NOTIFY	(0x107)	/* send to self: notify dependents	*/
#define OM_UPDATE	(0x108)	/* notification message from somebody	*/
#define OM_ADDMEMBER	(0x109)	/* used by various classes with lists	*/
#define OM_REMMEMBER	(0x10A)	/* used by various classes with lists	*/

/* Parameter "Messages" passed to methods	*/

/* OM_NEW and OM_SET	*/
struct opSet {
    ULONG		MethodID;
    struct TagItem	*ops_AttrList;	/* new attributes	*/
    struct GadgetInfo	*ops_GInfo;	/* always there for gadgets,
                     * when SetGadgetAttrs() is used,
                     * but will be NULL for OM_NEW
                     */
};

/* OM_NOTIFY, and OM_UPDATE	*/
struct opUpdate {
    ULONG		MethodID;
    struct TagItem	*opu_AttrList;	/* new attributes	*/
    struct GadgetInfo	*opu_GInfo;	/* non-NULL when SetGadgetAttrs or
                     * notification resulting from gadget
                     * input occurs.
                     */
    ULONG		opu_Flags;	/* defined below	*/
};

/* this flag means that the update message is being issued from
 * something like an active gadget, a la GACT_FOLLOWMOUSE.  When
 * the gadget goes inactive, it will issue a final update
 * message with this bit cleared.  Examples of use are for
 * GACT_FOLLOWMOUSE equivalents for propgadclass, and repeat strobes
 * for buttons.
 */
#define OPUF_INTERIM	(1<<0)

/* OM_GET	*/
struct opGet {
    ULONG		MethodID;
    ULONG		opg_AttrID;
    ULONG		*opg_Storage;	/* may be other types, but "int"
                     * types are all ULONG
                     */
};

/* OM_ADDTAIL	*/
struct opAddTail {
    ULONG		MethodID;
    struct List		*opat_List;
};

/* OM_ADDMEMBER, OM_REMMEMBER	*/
#define  opAddMember opMember
struct opMember {
    ULONG		MethodID;
    Object		*opam_Object;
};

#endif


include/classes/requester.h

#ifndef CLASSES_REQUESTER_H
#define CLASSES_REQUESTER_H
/*
**	$VER: requester.h 44.1 (19.10.1999)
**	Includes Release 44.1
**
**	requester.class definitions
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

/*****************************************************************************/

#ifndef REACTION_REACTION_H
#include <reaction/reaction.h>
#endif

/*****************************************************************************/

/* Attributes defined by the requester.gadget class
 */
#define REQ_Dummy				(REACTION_Dummy + 0x45000)
#define REQS_Dummy				(REQ_Dummy + 0x100)
#define REQI_Dummy				(REQ_Dummy + 0x200)
#define REQP_Dummy				(REQ_Dummy + 0x300)

#define	REQ_Type				(REQ_Dummy+1)
    /* (ULONG) Type of requester. See definitions below.
            (default: REQTYPE_INFO) (OM_NEW, OM_SET, RM_OPENREQ) */

#define	REQ_TitleText			(REQ_Dummy+2)
    /* (UBYTE *) Title text of the requester (default: None)
                (OM_NEW, OM_SET, RM_OPENREQ) */

#define	REQ_BodyText			(REQ_Dummy+3)
    /* (UBYTE *) Body text of the requester (default: None)
                (OM_NEW, OM_SET, RM_OPENREQ) */

#define	REQ_GadgetText			(REQ_Dummy+4)
    /* (UBYTE *) Gadget text(s) for the requester
            (default: " _Ok | _Cancel ") (OM_NEW, OM_SET, RM_OPENREQ) */

#define	REQ_ReturnCode			(REQ_Dummy+5)
    /* (ULONG) Last return code of the requester (default: 0)
                (OM_GET) */

#define	REQ_TabSize				(REQ_Dummy+6) /* NOT IMPLEMENTED YET */
    /* (ULONG) Tab size to use when formatting the bodytext (default: 8)
                (OM_NEW, OM_SET, RM_OPENREQ) */

/**********************************
* integer request type attributes *
**********************************/

#define REQI_Minimum 			(REQI_Dummy+1)
    /* (LONG) Minimum allowed value (default: MININT) (OM_NEW, OM_SET, RM_OPENREQ) */

#define REQI_Maximum 			(REQI_Dummy+2)
    /* (LONG) Maximum allowed value (default: MAXINT) (OM_NEW, OM_SET, RM_OPENREQ) */

#define	REQI_Invisible			(REQI_Dummy+3) /* NOT IMPLEMENTED YET */
    /* (BOOL) Integer input will be echoed with '.' and not what the user
            actually types (default: FALSE) (OM_NEW, OM_SET, RM_OPENREQ) */

#define	REQI_Number				(REQI_Dummy+4)
    /* (LONG) Number to show in gadget (default: 0)
            (OM_NEW, OM_SET, OM_GET, RM_OPENREQ) */

#define	REQI_Arrows				(REQI_Dummy+5)
    /* (BOOL) Show arrows to the right of the integer gadget (default: FALSE)
            (OM_NEW, OM_SET, RM_OPENREQ) */

#define	REQI_MaxChars			(REQI_Dummy+6)
    /* (UWORD) Maximum number of characters for the number (including negative
            sign). (default: 10) (OM_NEW, OM_SET, RM_OPENREQ) */

/*********************************
* string request type attributes *
*********************************/

#define	REQS_AllowEmpty 		(REQS_Dummy+1)
    /* (BOOL) Allow empty string to be accepted. (default: FALSE)
            (OM_NEW, OM_SET, RM_OPENREQ) */

#define	REQS_Invisible			(REQI_Invisible) /* NOT IMPLEMENTED YET */
    /* (BOOL) String input will be echoed with '.' and not what the user
            actually types (default: FALSE) (OM_NEW, OM_SET, RM_OPENREQ) */

#define	REQS_Buffer				(REQS_Dummy+2)
    /* (UBYTE *) Buffer used in the string gadget. MUST be provided.
            (OM_NEW, OM_SET, RM_OPENREQ) */

#define	REQS_ShowDefault		(REQS_Dummy+3)
    /* (BOOL) Show content of REQS_Buffer in string gadget. (default: TRUE)
            (OM_NEW, OM_SET, RM_OPENREQ) */

#define	REQS_MaxChars			(REQS_Dummy+4)
    /* (ULONG) Maximum number of characters in string gadget. Must not be
            larger than size of REQS_Buffer - 1. (default: 127)
            (OM_NEW, OM_SET, RM_OPENREQ) */

#define	REQS_ChooserArray		(REQS_Dummy+5)
    /* (UBYTE **) An array of strings that will be added to a chooser gadget
            to the right of the string gadget.
            (OM_NEW, OM_SET, RM_OPENREQ) */

#define	REQS_ChooserActive	(REQS_Dummy+6)
    /* (ULONG) The current active entry among the strings passed in
            using REQS_ChooserOptions.  (default: 0)
            (OM_NEW, OM_SET, OM_GET, RM_OPENREQ) */

/**********************************
* progress window type attributes *
**********************************/

#define REQP_Total				(REQP_Dummy+1)
    /* (ULONG) Total number of levels for the progressbar. (default: 100)
            (OM_NEW, OM_SET, RM_OPENREQ) */
#define REQP_Current			(REQP_Dummy+2)
    /* (ULONG) The current level of the progressbar. (default: 0)
            (OM_NEW, OM_SET, RM_OPENREQ) */
#define REQP_AbortText			REQ_GadgetText
    /* (UBYTE *) Text to be put into the gadget that will abort the progressbar.
            If not present, no gadget will be created.
            (OM_NEW, OM_SET, RM_OPENREQ) */
#define REQP_ProgressText		REQ_BodyText
    /* (UBYTE *) Text to be shown over the progressbar.
            (OM_NEW, OM_SET, RM_OPENREQ) */
#define REQP_OpenInactive		(REQP_Dummy+3)
    /* (BOOL) Open window inactive if ta_Data is TRUE.
            (OM_NEW, RM_OPENREQ) */
#define REQP_NoText				(REQP_Dummy+4)
    /* (BOOL)  No text-gadget in progressbar if ti_Data is TRUE
            (OM_NEW, RM_OPENREQ) */
#define REQP_Dynamic			(REQP_Dummy+5)
    /* (BOOL)  TRUE if the pb should size automatically when
        a too long progresstext is set. Default is TRUE.
        (OM_NEW, OM_SET, RM_OPENREQ) */
#define REQP_CenterWindow		(REQP_Dummy+6)
    /* (struct Window *) The progressbar is centered over this window.
        (OM_NEW, OM_SET, RM_OPENREQ) */
#define REQP_LastPosition		(REQP_Dummy+7)
    /* (BOOL) Open progressbar on the same place the last was. Default is TRUE.
        (OM_NEW, OM_SET, RM_OPENREQ) */
#define REQP_Percent			(REQP_Dummy+8)
    /* (BOOL) Render numeric percentage display.
        (OM_NEW, RM_OPENREQ) */
#define REQP_Ticks				(REQP_Dummy+9)
    /* (WORD) If present, how many tick marks
        (OM_NEW, RM_OPENREQ) */
#define REQP_ShortTicks			(REQP_Dummy+10)
    /* (BOOL) Enable small intermediate tick marks.
        (OM_NEW, RM_OPENREQ) */

/*****************************************************************************/

/*
 * requester.class methods
 */
#define RM_OPENREQ		(0x650001L)

/* The RM_OPENREQ method should be called whenever you want to open
 * a requester.
 */

struct orRequest
{
    ULONG MethodID;				/* RM_OPENREQ */
    struct TagItem *or_Attrs;	/* List of tag attributes */
    struct Window *or_Window;	/* Reference window for requester. */
    struct Screen *or_Screen;	/* Reference screen for requester. REQUIRED if or_Window is */
                                /* not supplied */
};

/* The REQ_Type must be used to set what type of requester you
 * want to use. Here are the definitions:
 */
#define REQTYPE_INFO		0		/* Normal information/query requester like EasyRequest() */
#define REQTYPE_INTEGER		1		/* Get an integer from the user */
#define REQTYPE_STRING		2		/* Get a string from the user */
#define REQTYPE_PROGRESS	3		/* Progressbar window (NOT IMPLEMENTED YET) */

/* Useful macros */
#ifndef RequesterObject
#define OpenRequester(obj, win)	DoMethod(obj, RM_OPENREQ, NULL, win, NULL, TAG_DONE)
#define RequesterObject			NewObject(REQUESTER_GetClass(), NULL
#endif

#endif /* CLASSES_REQUESTER_H */


include/prefs/overscan.h

#ifndef PREFS_OVERSCAN_H
#define PREFS_OVERSCAN_H
/*
**	$VER: overscan.h 38.4 (22.10.1992)
**	Includes Release 44.1
**
**	File format for overscan preferences
**
**	(C) Copyright 1991-1999 Amiga, Inc.
**	All Rights Reserved
*/

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef LIBRARIES_IFFPARSE_H
#include <libraries/iffparse.h>
#endif

#ifndef GRAPHICS_GFX_H
#include <graphics/gfx.h>
#endif

/*****************************************************************************/

#define ID_OSCN MAKE_ID('O','S','C','N')

#define OSCAN_MAGIC  0xFEDCBA89

struct OverscanPrefs
{
    ULONG	     os_Reserved;
    ULONG	     os_Magic;
    UWORD	     os_HStart;
    UWORD	     os_HStop;
    UWORD	     os_VStart;
    UWORD	     os_VStop;
    ULONG	     os_DisplayID;
    Point	     os_ViewPos;
    Point	     os_Text;
    struct Rectangle os_Standard;
};

/* os_HStart, os_HStop, os_VStart, os_VStop can only be looked at if
 * os_Magic equals OSCAN_MAGIC. If os_Magic is set to any other value,
 * these four fields are undefined
 */

/*****************************************************************************/

#endif /* PREFS_OVERSCAN_H */


include/prefs/palette.h

#ifndef PREFS_PALETTE_H
#define PREFS_PALETTE_H
/*
**	$VER: palette.h 39.2 (15.6.1992)
**	Includes Release 44.1
**
**	File format for palette preferences
**
**	(C) Copyright 1992-1999 Amiga, Inc.
**	All Rights Reserved
*/

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef LIBRARIES_IFFPARSE_H
#include <libraries/iffparse.h>
#endif

#ifndef INTUITION_INTUITION_H
#include <intuition/intuition.h>
#endif

/*****************************************************************************/

#define ID_PALT MAKE_ID('P','A','L','T')

struct PalettePrefs
{
    LONG	     pap_Reserved[4];	 /* System reserved		   */
    UWORD	     pap_4ColorPens[32];
    UWORD	     pap_8ColorPens[32];
    struct ColorSpec pap_Colors[32];	 /* Used as full 16-bit RGB values */
};

/*****************************************************************************/

#endif /* PREFS_PALETTE_H */


include/prefs/pointer.h

#ifndef PREFS_POINTER_H
#define PREFS_POINTER_H
/*
**	$VER: pointer.h 39.2 (9.6.1992)
**	Includes Release 44.1
**
**	File format for pointer preferences
**
**	(C) Copyright 1991-1999 Amiga, Inc.
**	All Rights Reserved
*/

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef LIBRARIES_IFFPARSE_H
#include <libraries/iffparse.h>
#endif

/*****************************************************************************/

#define ID_PNTR MAKE_ID('P','N','T','R')

/*****************************************************************************/

struct PointerPrefs
{
    ULONG pp_Reserved[4];
    UWORD pp_Which;				/* 0=NORMAL, 1=BUSY */
    UWORD pp_Size;				/* see <intuition/pointerclass.h> */
    UWORD pp_Width;				/* Width in pixels */
    UWORD pp_Height;				/* Height in pixels */
    UWORD pp_Depth;				/* Depth */
    UWORD pp_YSize;				/* YSize */
    UWORD pp_X, pp_Y;				/* Hotspot */

    /* Color Table:  numEntries = (1 << pp_Depth) - 1 */

    /* Data follows */
};

/*****************************************************************************/

/* constants for PointerPrefs.pp_Which */
#define	WBP_NORMAL	0
#define	WBP_BUSY	1

/*****************************************************************************/

struct RGBTable
{
    UBYTE t_Red;
    UBYTE t_Green;
    UBYTE t_Blue;
};

/*****************************************************************************/

#endif /* PREFS_POINTER_H */


include/intuition/preferences.h

#ifndef INTUITION_PREFERENCES_H
#define INTUITION_PREFERENCES_H TRUE
/*
**  $VER: preferences.h 38.2 (16.9.1992)
**  Includes Release 44.1
**
**  Structure definition for old-style preferences
**
**  (C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef DEVICES_TIMER_H
#include <devices/timer.h>
#endif

/* ======================================================================== */
/* === Preferences ======================================================== */
/* ======================================================================== */

/* these are the definitions for the printer configurations */
#define	FILENAME_SIZE	30	/* Filename size */
#define DEVNAME_SIZE	16	/* Device-name size */

#define	POINTERSIZE (1 + 16 + 1) * 2	/* Size of Pointer data buffer */

/* These defines are for the default font size.  These actually describe the
 * height of the defaults fonts.  The default font type is the topaz
 * font, which is a fixed width font that can be used in either
 * eighty-column or sixty-column mode.	The Preferences structure reflects
 * which is currently selected by the value found in the variable FontSize,
 * which may have either of the values defined below.  These values actually
 * are used to select the height of the default font.  By changing the
 * height, the resolution of the font changes as well.
 */
#define TOPAZ_EIGHTY 8
#define TOPAZ_SIXTY 9

/* Note:  Starting with V36, and continuing with each new version of
 * Intuition, an increasing number of fields of struct Preferences
 * are ignored by SetPrefs().  (Some fields are obeyed only at the
 * initial SetPrefs(), which comes from the devs:system-configuration
 * file).  Elements are generally superseded as new hardware or software
 * features demand more information than fits in struct Preferences.
 * Parts of struct Preferences must be ignored so that applications
 * calling GetPrefs(), modifying some other part of struct Preferences,
 * then calling SetPrefs(), don't end up truncating the extended
 * data.
 *
 * Consult the autodocs for SetPrefs() for further information as
 * to which fields are not always respected.
 */

struct Preferences
{
    /* the default font height */
    BYTE FontHeight;			/* height for system default font  */

    /* constant describing what's hooked up to the port */
    UBYTE PrinterPort;			/* printer port connection	   */

    /* the baud rate of the port */
    UWORD BaudRate;			/* baud rate for the serial port   */

    /* various timing rates */
    struct timeval KeyRptSpeed;		/* repeat speed for keyboard	   */
    struct timeval KeyRptDelay;		/* Delay before keys repeat	   */
    struct timeval DoubleClick;		/* Interval allowed between clicks */

    /* Intuition Pointer data */
    UWORD PointerMatrix[POINTERSIZE];	/* Definition of pointer sprite    */
    BYTE XOffset;			/* X-Offset for active 'bit'	   */
    BYTE YOffset;			/* Y-Offset for active 'bit'	   */
    UWORD color17;			/***********************************/
    UWORD color18;			/* Colours for sprite pointer	   */
    UWORD color19;			/***********************************/
    UWORD PointerTicks;			/* Sensitivity of the pointer	   */

    /* Workbench Screen colors */
    UWORD color0;			/***********************************/
    UWORD color1;			/*  Standard default colours	   */
    UWORD color2;			/*   Used in the Workbench	   */
    UWORD color3;			/***********************************/

    /* positioning data for the Intuition View */
    BYTE ViewXOffset;			/* Offset for top lefthand corner  */
    BYTE ViewYOffset;			/* X and Y dimensions		   */
    WORD ViewInitX, ViewInitY;		/* View initial offset values	   */

    BOOL EnableCLI;			/* CLI availability switch */

    /* printer configurations */
    UWORD PrinterType;			/* printer type		   */
    UBYTE PrinterFilename[FILENAME_SIZE];/* file for printer	   */

    /* print format and quality configurations */
    UWORD PrintPitch;			/* print pitch			   */
    UWORD PrintQuality;			/* print quality		   */
    UWORD PrintSpacing;			/* number of lines per inch	   */
    UWORD PrintLeftMargin;		/* left margin in characters	   */
    UWORD PrintRightMargin;		/* right margin in characters	   */
    UWORD PrintImage;			/* positive or negative		   */
    UWORD PrintAspect;			/* horizontal or vertical	   */
    UWORD PrintShade;			/* b&w, half-tone, or color	   */
    WORD PrintThreshold;		/* darkness ctrl for b/w dumps	   */

    /* print paper descriptors */
    UWORD PaperSize;			/* paper size			   */
    UWORD PaperLength;			/* paper length in number of lines */
    UWORD PaperType;			/* continuous or single sheet	   */

    /* Serial device settings: These are six nibble-fields in three bytes */
    /* (these look a little strange so the defaults will map out to zero) */
    UBYTE   SerRWBits;	 /* upper nibble = (8-number of read bits)	*/
             /* lower nibble = (8-number of write bits)	*/
    UBYTE   SerStopBuf;  /* upper nibble = (number of stop bits - 1)	*/
             /* lower nibble = (table value for BufSize)	*/
    UBYTE   SerParShk;	 /* upper nibble = (value for Parity setting)	*/
             /* lower nibble = (value for Handshake mode)	*/
    UBYTE   LaceWB;	 /* if workbench is to be interlaced		*/

    UBYTE   Pad[ 12 ];
    UBYTE   PrtDevName[DEVNAME_SIZE];	/* device used by printer.device
                     * (omit the ".device")
                     */
    UBYTE   DefaultPrtUnit;	/* default unit opened by printer.device */
    UBYTE   DefaultSerUnit;	/* default serial unit */

    BYTE    RowSizeChange;	/* affect NormalDisplayRows/Columns	*/
    BYTE    ColumnSizeChange;

    UWORD    PrintFlags;	/* user preference flags */
    UWORD    PrintMaxWidth;	/* max width of printed picture in 10ths/in */
    UWORD    PrintMaxHeight;	/* max height of printed picture in 10ths/in */
    UBYTE    PrintDensity;	/* print density */
    UBYTE    PrintXOffset;	/* offset of printed picture in 10ths/inch */

    UWORD    wb_Width;		/* override default workbench width  */
    UWORD    wb_Height;		/* override default workbench height */
    UBYTE    wb_Depth;		/* override default workbench depth  */

    UBYTE    ext_size;		/* extension information -- do not touch! */
                /* extension size in blocks of 64 bytes */
};

/* Workbench Interlace (use one bit) */
#define LACEWB			(1<< 0)
#define LW_RESERVED	1		/* internal use only */

/* Enable_CLI	*/
#define SCREEN_DRAG	(1<<14)
#define MOUSE_ACCEL	(1L<<15)

/* PrinterPort */
#define PARALLEL_PRINTER 0x00
#define SERIAL_PRINTER	0x01

/* BaudRate */
#define BAUD_110	0x00
#define BAUD_300	0x01
#define BAUD_1200	0x02
#define BAUD_2400	0x03
#define BAUD_4800	0x04
#define BAUD_9600	0x05
#define BAUD_19200	0x06
#define BAUD_MIDI	0x07

/* PaperType */
#define FANFOLD	0x00
#define SINGLE		0x80

/* PrintPitch */
#define PICA		0x000
#define ELITE		0x400
#define FINE		0x800

/* PrintQuality */
#define DRAFT		0x000
#define LETTER		0x100

/* PrintSpacing */
#define SIX_LPI		0x000
#define EIGHT_LPI	0x200

/* Print Image */
#define IMAGE_POSITIVE	0x00
#define IMAGE_NEGATIVE	0x01

/* PrintAspect */
#define ASPECT_HORIZ	0x00
#define ASPECT_VERT	0x01

/* PrintShade */
#define SHADE_BW	0x00
#define SHADE_GREYSCALE	0x01
#define SHADE_COLOR	0x02

/* PaperSize (all paper sizes have a zero in the lowest nybble) */
#define US_LETTER	0x00
#define US_LEGAL	0x10
#define N_TRACTOR	0x20
#define W_TRACTOR	0x30
#define CUSTOM		0x40

/* New PaperSizes for V36: */
#define EURO_A0	0x50		/* European size A0: 841 x 1189 */
#define EURO_A1	0x60		/* European size A1: 594 x 841 */
#define EURO_A2	0x70		/* European size A2: 420 x 594 */
#define EURO_A3	0x80		/* European size A3: 297 x 420 */
#define EURO_A4	0x90		/* European size A4: 210 x 297 */
#define EURO_A5	0xA0		/* European size A5: 148 x 210 */
#define EURO_A6	0xB0		/* European size A6: 105 x 148 */
#define EURO_A7	0xC0		/* European size A7: 74 x 105 */
#define EURO_A8	0xD0		/* European size A8: 52 x 74 */

/* PrinterType */
#define CUSTOM_NAME		0x00
#define	ALPHA_P_101		0x01
#define BROTHER_15XL		0x02
#define CBM_MPS1000		0x03
#define DIAB_630		0x04
#define DIAB_ADV_D25		0x05
#define DIAB_C_150		0x06
#define EPSON			0x07
#define EPSON_JX_80		0x08
#define OKIMATE_20		0x09
#define QUME_LP_20		0x0A
/* new printer entries, 3 October 1985 */
#define HP_LASERJET		0x0B
#define HP_LASERJET_PLUS	0x0C

/* Serial Input Buffer Sizes */
#define SBUF_512	0x00
#define SBUF_1024	0x01
#define SBUF_2048	0x02
#define SBUF_4096	0x03
#define SBUF_8000	0x04
#define SBUF_16000	0x05

/* Serial Bit Masks */
#define	SREAD_BITS	0xF0 /* for SerRWBits	*/
#define	SWRITE_BITS	0x0F

#define	SSTOP_BITS	0xF0 /* for SerStopBuf	*/
#define	SBUFSIZE_BITS	0x0F

#define	SPARITY_BITS	0xF0 /* for SerParShk	*/
#define SHSHAKE_BITS	0x0F

/* Serial Parity (upper nibble, after being shifted by
 * macro SPARNUM() )
 */
#define SPARITY_NONE	 0
#define SPARITY_EVEN	 1
#define SPARITY_ODD	 2
/* New parity definitions for V36: */
#define SPARITY_MARK	 3
#define SPARITY_SPACE	 4

/* Serial Handshake Mode (lower nibble, after masking using
 * macro SHANKNUM() )
 */
#define SHSHAKE_XON	 0
#define SHSHAKE_RTS	 1
#define SHSHAKE_NONE	 2

/* new defines for PrintFlags */

#define CORRECT_RED	    0x0001  /* color correct red shades */
#define CORRECT_GREEN	    0x0002  /* color correct green shades */
#define CORRECT_BLUE	    0x0004  /* color correct blue shades */

#define CENTER_IMAGE	    0x0008  /* center image on paper */

#define IGNORE_DIMENSIONS   0x0000 /* ignore max width/height settings */
#define BOUNDED_DIMENSIONS  0x0010  /* use max width/height as boundaries */
#define ABSOLUTE_DIMENSIONS 0x0020  /* use max width/height as absolutes */
#define PIXEL_DIMENSIONS    0x0040  /* use max width/height as prt pixels */
#define MULTIPLY_DIMENSIONS 0x0080 /* use max width/height as multipliers */

#define INTEGER_SCALING     0x0100  /* force integer scaling */

#define ORDERED_DITHERING   0x0000 /* ordered dithering */
#define HALFTONE_DITHERING  0x0200  /* halftone dithering */
#define FLOYD_DITHERING     0x0400 /* Floyd-Steinberg dithering */

#define ANTI_ALIAS	    0x0800 /* anti-alias image */
#define GREY_SCALE2	    0x1000 /* for use with hi-res monitor */

/* masks used for checking bits */

#define CORRECT_RGB_MASK    (CORRECT_RED|CORRECT_GREEN|CORRECT_BLUE)
#define DIMENSIONS_MASK     (BOUNDED_DIMENSIONS|ABSOLUTE_DIMENSIONS|PIXEL_DIMENSIONS|MULTIPLY_DIMENSIONS)
#define DITHERING_MASK	    (HALFTONE_DITHERING|FLOYD_DITHERING)

#endif


include/prefs/prefhdr.h

#ifndef PREFS_PREFHDR_H
#define PREFS_PREFHDR_H
/*
**	$VER: prefhdr.h 38.1 (19.6.1991)
**	Includes Release 44.1
**
**	File format for preferences header
**
**	(C) Copyright 1991-1999 Amiga, Inc.
**	All Rights Reserved
*/

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef LIBRARIES_IFFPARSE_H
#include <libraries/iffparse.h>
#endif

/*****************************************************************************/

#define ID_PREF	 MAKE_ID('P','R','E','F')
#define ID_PRHD	 MAKE_ID('P','R','H','D')

struct PrefHeader
{
    UBYTE ph_Version;	/* version of following data */
    UBYTE ph_Type;	/* type of following data    */
    ULONG ph_Flags;	/* always set to 0 for now   */
};

/*****************************************************************************/

#endif /* PREFS_PREFHDR_H */


include/prefs/printertxt.h

#ifndef PREFS_PRINTERTXT_H
#define PREFS_PRINTERTXT_H
/*
**	$VER: printertxt.h 44.1 (19.10.1999)
**	Includes Release 44.1
**
**	File format for text printer preferences
**
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

/*****************************************************************************/

#ifndef LIBRARIES_IFFPARSE_H
#include <libraries/iffparse.h>
#endif

/*****************************************************************************/

#define ID_PTXT MAKE_ID('P','T','X','T')
#define ID_PUNT MAKE_ID('P','U','N','T')
#define ID_PDEV MAKE_ID('P','D','E','V')

#define	DRIVERNAMESIZE 30		/* Filename size     */
#define  DEVICENAMESIZE 32		/* .device name size */
#define  UNITNAMESIZE   32    /* Unit name size    */

struct PrinterTxtPrefs
{
    LONG  pt_Reserved[4];		/* System reserved	      */
    UBYTE pt_Driver[DRIVERNAMESIZE];	/* printer driver filename    */
    UBYTE pt_Port;			/* printer port connection    */

    UWORD pt_PaperType;
    UWORD pt_PaperSize;
    UWORD pt_PaperLength;		/* Paper length in # of lines */

    UWORD pt_Pitch;
    UWORD pt_Spacing;
    UWORD pt_LeftMargin;		/* Left margin		      */
    UWORD pt_RightMargin;		/* Right margin	      */
    UWORD pt_Quality;
};

/* constants for PrinterTxtPrefs.pt_Port */
#define PP_PARALLEL 0
#define PP_SERIAL   1

/* constants for PrinterTxtPrefs.pt_PaperType */
#define PT_FANFOLD  0
#define PT_SINGLE   1

/* constants for PrinterTxtPrefs.pt_PaperSize */
#define PS_US_LETTER	0
#define PS_US_LEGAL	1
#define PS_N_TRACTOR	2
#define PS_W_TRACTOR	3
#define PS_CUSTOM	4
#define PS_EURO_A0	5		/* European size A0: 841 x 1189 */
#define PS_EURO_A1	6		/* European size A1: 594 x 841	*/
#define PS_EURO_A2	7		/* European size A2: 420 x 594	*/
#define PS_EURO_A3	8		/* European size A3: 297 x 420	*/
#define PS_EURO_A4	9		/* European size A4: 210 x 297	*/
#define PS_EURO_A5	10		/* European size A5: 148 x 210	*/
#define PS_EURO_A6	11		/* European size A6: 105 x 148	*/
#define PS_EURO_A7	12		/* European size A7: 74 x 105	*/
#define PS_EURO_A8	13		/* European size A8: 52 x 74	*/

/* constants for PrinterTxtPrefs.pt_PrintPitch */
#define PP_PICA	 0
#define PP_ELITE 1
#define PP_FINE	 2

/* constants for PrinterTxtPrefs.pt_PrintSpacing */
#define PS_SIX_LPI   0
#define PS_EIGHT_LPI 1

/* constants for PrinterTxtPrefs.pt_PrintQuality */
#define PQ_DRAFT  0
#define PQ_LETTER 1

/* PrinterUnitPrefs is used from printer.device to open
   the connection device
*/
struct PrinterUnitPrefs
{
    LONG  pu_Reserved[4];		  /* System reserved		  */
    LONG  pu_UnitNum;			  /* Unit number for OpenDevice() */
    ULONG pu_OpenDeviceFlags;		  /* Flags for OpenDevice()	  */
    UBYTE pu_DeviceName[DEVICENAMESIZE];  /* Name for OpenDevice()	  */
};

/* PrinterDeviceUnitPrefs is used as descriptor for printer device
   units.
*/
struct PrinterDeviceUnitPrefs
{
    LONG  pd_Reserved[4];	/* System reserved		  */
    LONG  pd_UnitNum;           /* Unit number for OpenDevice()	  */
    UBYTE pd_UnitName[UNITNAMESIZE]; /* Symbolic name of the unit */
};

/*****************************************************************************/

#endif /* PREFS_PRINTERTXT_H */


include/prefs/printergfx.h

#ifndef PREFS_PRINTERGFX_H
#define PREFS_PRINTERGFX_H
/*
**	$VER: printergfx.h 38.2 (3.7.1991)
**	Includes Release 44.1
**
**	File format for graphics printer preferences
**
**	(C) Copyright 1991-1999 Amiga, Inc.
**	All Rights Reserved
*/

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef LIBRARIES_IFFPARSE_H
#include <libraries/iffparse.h>
#endif

/*****************************************************************************/

#define ID_PGFX MAKE_ID('P','G','F','X')

struct PrinterGfxPrefs
{
    LONG  pg_Reserved[4];
    UWORD pg_Aspect;
    UWORD pg_Shade;
    UWORD pg_Image;
    WORD  pg_Threshold;
    UBYTE pg_ColorCorrect;
    UBYTE pg_Dimensions;
    UBYTE pg_Dithering;
    UWORD pg_GraphicFlags;
    UBYTE pg_PrintDensity;		/* Print density 1 - 7 */
    UWORD pg_PrintMaxWidth;
    UWORD pg_PrintMaxHeight;
    UBYTE pg_PrintXOffset;
    UBYTE pg_PrintYOffset;
};

/* constants for PrinterGfxPrefs.pg_Aspect */
#define PA_HORIZONTAL 0
#define PA_VERTICAL   1

/* constants for PrinterGfxPrefs.pg_Shade */
#define PS_BW		0
#define PS_GREYSCALE	1
#define PS_COLOR	2
#define PS_GREY_SCALE2	3

/* constants for PrinterGfxPrefs.pg_Image */
#define PI_POSITIVE 0
#define PI_NEGATIVE 1

/* flags for PrinterGfxPrefs.pg_ColorCorrect */
#define PCCB_RED   1	/* color correct red shades   */
#define PCCB_GREEN 2	/* color correct green shades */
#define PCCB_BLUE  3	/* color correct blue shades  */

#define PCCF_RED   (1<<0)
#define PCCF_GREEN (1<<1)
#define PCCF_BLUE  (1<<2)

/* constants for PrinterGfxPrefs.pg_Dimensions */
#define PD_IGNORE   0  /* ignore max width/height settings */
#define PD_BOUNDED  1  /* use max w/h as boundaries	   */
#define PD_ABSOLUTE 2  /* use max w/h as absolutes	   */
#define PD_PIXEL    3  /* use max w/h as prt pixels	   */
#define PD_MULTIPLY 4  /* use max w/h as multipliers	   */

/* constants for PrinterGfxPrefs.pg_Dithering */
#define PD_ORDERED	0  /* ordered dithering	*/
#define PD_HALFTONE	1  /* halftone dithering	*/
#define PD_FLOYD	2  /* Floyd-Steinberg dithering */

/* flags for PrinterGfxPrefs.pg_GraphicsFlags */
#define PGFB_CENTER_IMAGE	0	/* center image on paper */
#define PGFB_INTEGER_SCALING	1	/* force integer scaling */
#define PGFB_ANTI_ALIAS		2	/* anti-alias image	 */

#define PGFF_CENTER_IMAGE	(1<<0)
#define PGFF_INTEGER_SCALING	(1<<1)
#define PGFF_ANTI_ALIAS		(1<<2)

/*****************************************************************************/

#endif /* PREFS_PRINTERGFX_H */


include/prefs/printerps.h

#ifndef PREFS_PRINTERPS_H
#define PREFS_PRINTERPS_H
/*
**	$VER: printerps.h 38.6 (6.5.1993)
**	Includes Release 44.1
**
**	File format for PostScript printer preferences
**
**	(C) Copyright 1991-1999 Amiga, Inc.
**	All Rights Reserved
*/

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef LIBRARIES_IFFPARSE_H
#include <libraries/iffparse.h>
#endif

/*****************************************************************************/

#define ID_PSPD MAKE_ID('P','S','P','D')

struct PrinterPSPrefs
{
    LONG  ps_Reserved[4];		/* System reserved */

    /* Global printing attributes */
    UBYTE ps_DriverMode;
    UBYTE ps_PaperFormat;
    UBYTE ps_Reserved1[2];
    LONG  ps_Copies;
    LONG  ps_PaperWidth;
    LONG  ps_PaperHeight;
    LONG  ps_HorizontalDPI;
    LONG  ps_VerticalDPI;

    /* Text Options */
    UBYTE ps_Font;
    UBYTE ps_Pitch;
    UBYTE ps_Orientation;
    UBYTE ps_Tab;
    UBYTE ps_Reserved2[8];

    /* Text Dimensions */
    LONG  ps_LeftMargin;
    LONG  ps_RightMargin;
    LONG  ps_TopMargin;
    LONG  ps_BottomMargin;
    LONG  ps_FontPointSize;
    LONG  ps_Leading;
    UBYTE ps_Reserved3[8];

    /* Graphics Options */
    LONG  ps_LeftEdge;
    LONG  ps_TopEdge;
    LONG  ps_Width;
    LONG  ps_Height;
    UBYTE ps_Image;
    UBYTE ps_Shading;
    UBYTE ps_Dithering;
    UBYTE ps_Reserved4[9];

    /* Graphics Scaling */
    UBYTE ps_Aspect;
    UBYTE ps_ScalingType;
    UBYTE ps_Reserved5;
    UBYTE ps_Centering;
    UBYTE ps_Reserved6[8];
};

/* All measurements are in Millipoints which is 1/1000 of a point, or
 * in other words 1/72000 of an inch
 */

/* constants for PrinterPSPrefs.ps_DriverMode */
#define DM_POSTSCRIPT  0
#define DM_PASSTHROUGH 1

/* constants for PrinterPSPrefs.ps_PaperFormat */
#define PF_USLETTER 0
#define PF_USLEGAL  1
#define PF_A4	    2
#define PF_CUSTOM   3

/* constants for PrinterPSPrefs.ps_Font */
#define FONT_COURIER	  0
#define FONT_TIMES	  1
#define FONT_HELVETICA	  2
#define FONT_HELV_NARROW  3
#define FONT_AVANTGARDE   4
#define FONT_BOOKMAN	  5
#define FONT_NEWCENT	  6
#define FONT_PALATINO	  7
#define FONT_ZAPFCHANCERY 8

/* constants for PrinterPSPrefs.ps_Pitch */
#define PITCH_NORMAL	 0
#define PITCH_COMPRESSED 1
#define PITCH_EXPANDED	 2

/* constants for PrinterPSPrefs.ps_Orientation */
#define ORIENT_PORTRAIT  0
#define ORIENT_LANDSCAPE 1

/* constants for PrinterPSPrefs.ps_Tab */
#define TAB_4	  0
#define TAB_8	  1
#define TAB_QUART 2
#define TAB_HALF  3
#define TAB_INCH  4

/* constants for PrinterPSPrefs.ps_Image */
#define IM_POSITIVE 0
#define IM_NEGATIVE 1

/* constants for PrinterPSPrefs.ps_Shading */
#define SHAD_BW        0
#define SHAD_GREYSCALE 1
#define SHAD_COLOR     2

/* constants for PrinterPSPrefs.ps_Dithering */
#define DITH_DEFAULT 0
#define DITH_DOTTY   1
#define DITH_VERT    2
#define DITH_HORIZ   3
#define DITH_DIAG    4

/* constants for PrinterPSPrefs.ps_Aspect */
#define ASP_HORIZ 0
#define ASP_VERT  1

/* constants for PrinterPSPrefs.ps_ScalingType */
#define ST_ASPECT_ASIS	  0
#define ST_ASPECT_WIDE	  1
#define ST_ASPECT_TALL	  2
#define ST_ASPECT_BOTH	  3
#define ST_FITS_WIDE	  4
#define ST_FITS_TALL	  5
#define ST_FITS_BOTH	  6

/* constants for PrinterPSPrefs.ps_Centering */
#define CENT_NONE  0
#define CENT_HORIZ 1
#define CENT_VERT  2
#define CENT_BOTH  3

/*****************************************************************************/

#endif /* PREFS_PRINTERPS_H */


include/prefs/reaction.h

#ifndef PREFS_REACTION_H
#define PREFS_REACTION_H
/*
**	$VER: reaction.h 44.1 (19.10.1999)
**	Includes Release 44.1
**
**	Reaction preferences file definitions
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef LIBRARIES_IFFPARSE_H
#include <libraries/iffparse.h>
#endif

#ifndef GRAPHICS_TEXT_H
#include <graphics/text.h>
#endif

/*****************************************************************************/

#define ID_RACT MAKE_ID('R','A','C','T')

#define FONTNAMESIZE (128)

struct ReactionPrefs
{
    UWORD     rp_BevelType; /* see <reaction/reaction_prefs.h> */
    UWORD     rp_GlyphType; /* see (reaction/reaction_prefs.h> */
    UWORD     rp_LayoutSpacing;
    BOOL      rp_3DProp;
    UWORD     rp_LabelPen;
    UWORD     rp_LabelPlace;
    BOOL      rp_3DLabel;
    BOOL      rp_SimpleRefresh;
    BOOL      rp_3DLook;
    struct TextAttr rp_FallbackAttr;
    struct TextAttr rp_LabelAttr;
    UBYTE     rp_FallbackName[FONTNAMESIZE];
    UBYTE     rp_LabelName[FONTNAMESIZE];
    UBYTE     rp_Pattern[256];
};

#endif /* PREFS_REACTION_H */


include/dos/record.h

#ifndef DOS_RECORD_H
#define DOS_RECORD_H
/*
**
**	$VER: record.h 36.5 (12.7.1990)
**	Includes Release 44.1
**
**	include file for record locking
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**
*/

#ifndef DOS_DOS_H
#include <dos/dos.h>
#endif

/* Modes for LockRecord/LockRecords() */
#define REC_EXCLUSIVE		0
#define REC_EXCLUSIVE_IMMED	1
#define REC_SHARED		2
#define REC_SHARED_IMMED	3

/* struct to be passed to LockRecords()/UnLockRecords() */

struct RecordLock {
    BPTR	rec_FH;		/* filehandle */
    ULONG	rec_Offset;	/* offset in file */
    ULONG	rec_Length;	/* length of file to be locked */
    ULONG	rec_Mode;	/* Type of lock */
};

#endif /* DOS_RECORD_H */


include/graphics/regions.h

#ifndef	GRAPHICS_REGIONS_H
#define	GRAPHICS_REGIONS_H
/*
**	$VER: regions.h 39.0 (21.8.1991)
**	Includes Release 44.1
**
**
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef GRAPHICS_GFX_H
#include <graphics/gfx.h>
#endif

struct RegionRectangle
{
    struct RegionRectangle *Next,*Prev;
    struct Rectangle bounds;
};

struct Region
{
    struct Rectangle bounds;
    struct RegionRectangle *RegionRectangle;
};

#endif	/* GRAPHICS_REGIONS_H */


include/exec/resident.h

#ifndef	EXEC_RESIDENT_H
#define	EXEC_RESIDENT_H
/*
**	$VER: resident.h 39.0 (15.10.1991)
**	Includes Release 44.1
**
**	Resident/ROMTag stuff.	Used to identify and initialize code modules.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif /* EXEC_TYPES_H */

struct Resident {
    UWORD rt_MatchWord;	/* word to match on (ILLEGAL)	*/
    struct Resident *rt_MatchTag; /* pointer to the above	*/
    APTR  rt_EndSkip;		/* address to continue scan	*/
    UBYTE rt_Flags;		/* various tag flags		*/
    UBYTE rt_Version;		/* release version number	*/
    UBYTE rt_Type;		/* type of module (NT_XXXXXX)	*/
    BYTE  rt_Pri;		/* initialization priority */
    char  *rt_Name;		/* pointer to node name	*/
    char  *rt_IdString;	/* pointer to identification string */
    APTR  rt_Init;		/* pointer to init code	*/
};

#define RTC_MATCHWORD	0x4AFC	/* The 68000 "ILLEGAL" instruction */

#define RTF_AUTOINIT	(1<<7)	/* rt_Init points to data structure */
#define RTF_AFTERDOS	(1<<2)
#define RTF_SINGLETASK	(1<<1)
#define RTF_COLDSTART	(1<<0)

/* Compatibility: (obsolete) */
/* #define RTM_WHEN	   3 */
#define RTW_NEVER	0
#define RTW_COLDSTART	1

#endif	/* EXEC_RESIDENT_H */


include/rexx/rxslib.h

#ifndef REXX_RXSLIB_H
#define REXX_RXSLIB_H
/*
**	$VER: rxslib.h 1.6 (8.11.1991)
**	Includes Release 44.1
**
**	The header file for the REXX Systems Library
**
**	(C) Copyright 1987,1988,1989,1990 William S. Hawes
**	(C) Copyright 1990-1999 Amiga, Inc.
**		All Rights Reserved
*/

#ifndef REXX_STORAGE_H
#include <rexx/storage.h>
#endif

#define RXSNAME  "rexxsyslib.library"
#define RXSDIR	 "REXX"
#define RXSTNAME "ARexx"

/* The REXX systems library structure.	This should be considered as	*/
/* semi-private and read-only, except for documented exceptions.	*/

struct RxsLib {
   struct Library rl_Node;	       /* EXEC library node		*/
   UBYTE    rl_Flags;		       /* global flags			*/
   UBYTE    rl_Shadow;		       /* shadow flags			*/
   APTR     rl_SysBase;	       /* EXEC library base		*/
   APTR     rl_DOSBase;	       /* DOS library base		*/
   APTR     rl_IeeeDPBase;	       /* IEEE DP math library base	*/
   LONG     rl_SegList;	       /* library seglist		*/
   LONG     rl_NIL;		       /* global NIL: filehandle	*/
   LONG     rl_Chunk;		       /* allocation quantum		*/
   LONG     rl_MaxNest;	       /* maximum expression nesting	*/
   struct NexxStr *rl_NULL;	       /* static string: NULL		*/
   struct NexxStr *rl_FALSE;	       /* static string: FALSE		*/
   struct NexxStr *rl_TRUE;	       /* static string: TRUE		*/
   struct NexxStr *rl_REXX;	       /* static string: REXX		*/
   struct NexxStr *rl_COMMAND;	       /* static string: COMMAND	*/
   struct NexxStr *rl_STDIN;	       /* static string: STDIN		*/
   struct NexxStr *rl_STDOUT;	       /* static string: STDOUT	*/
   struct NexxStr *rl_STDERR;	       /* static string: STDERR	*/
   STRPTR    rl_Version;	       /* version string		*/

   STRPTR    rl_TaskName;	       /* name string for tasks	*/
   LONG      rl_TaskPri;	       /* starting priority		*/
   LONG      rl_TaskSeg;	       /* startup seglist		*/
   LONG      rl_StackSize;	       /* stack size			*/
   STRPTR    rl_RexxDir;	       /* REXX directory		*/
   STRPTR    rl_CTABLE;	       /* character attribute table	*/
   STRPTR    rl_Notice;	       /* copyright notice		*/

   struct MsgPort rl_RexxPort;	       /* REXX public port		*/
   UWORD     rl_ReadLock;	       /* lock count			*/
   LONG      rl_TraceFH;	       /* global trace console		*/
   struct List rl_TaskList;	       /* REXX task list		*/
   WORD      rl_NumTask;	       /* task count			*/
   struct List rl_LibList;	       /* Library List header		*/
   WORD      rl_NumLib;	       /* library count		*/
   struct List rl_ClipList;	       /* ClipList header		*/
   WORD      rl_NumClip;	       /* clip node count		*/
   struct List rl_MsgList;	       /* pending messages		*/
   WORD      rl_NumMsg;	       /* pending count		*/
   struct List rl_PgmList;	       /* cached programs		*/
   WORD      rl_NumPgm;	       /* program count		*/

   UWORD     rl_TraceCnt;	       /* usage count for trace console */
   WORD      rl_avail;
   };

/* Global flag bit definitions for RexxMaster				*/
#define RLFB_TRACE RTFB_TRACE	       /* interactive tracing?		*/
#define RLFB_HALT  RTFB_HALT	       /* halt execution?		*/
#define RLFB_SUSP  RTFB_SUSP	       /* suspend execution?		*/
#define RLFB_STOP  6		       /* deny further invocations	*/
#define RLFB_CLOSE 7		       /* close the master		*/

#define RLFMASK    (1<<RLFB_TRACE) | (1<<RLFB_HALT) | (1<<RLFB_SUSP)

/* Initialization constants						*/
#define RXSCHUNK   1024	       /* allocation quantum		*/
#define RXSNEST    32		       /* expression nesting limit	*/
#define RXSTPRI    0		       /* task priority		*/
#define RXSSTACK   4096	       /* stack size			*/

/* Character attribute flag bits used in REXX.				*/
#define CTB_SPACE   0		       /* white space characters	*/
#define CTB_DIGIT   1		       /* decimal digits 0-9		*/
#define CTB_ALPHA   2		       /* alphabetic characters	*/
#define CTB_REXXSYM 3		       /* REXX symbol characters	*/
#define CTB_REXXOPR 4		       /* REXX operator characters	*/
#define CTB_REXXSPC 5		       /* REXX special symbols		*/
#define CTB_UPPER   6		       /* UPPERCASE alphabetic		*/
#define CTB_LOWER   7		       /* lowercase alphabetic		*/

/* Attribute flags							*/
#define CTF_SPACE   (1 << CTB_SPACE)
#define CTF_DIGIT   (1 << CTB_DIGIT)
#define CTF_ALPHA   (1 << CTB_ALPHA)
#define CTF_REXXSYM (1 << CTB_REXXSYM)
#define CTF_REXXOPR (1 << CTB_REXXOPR)
#define CTF_REXXSPC (1 << CTB_REXXSPC)
#define CTF_UPPER   (1 << CTB_UPPER)
#define CTF_LOWER   (1 << CTB_LOWER)

#endif


include/prefs/screenmode.h

#ifndef PREFS_SCREENMODE_H
#define PREFS_SCREENMODE_H
/*
**	$VER: screenmode.h 38.4 (25.6.1992)
**	Includes Release 44.1
**
**	File format for screen mode preferences
**
**	(C) Copyright 1991-1999 Amiga, Inc.
**	All Rights Reserved
*/

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef LIBRARIES_IFFPARSE_H
#include <libraries/iffparse.h>
#endif

/*****************************************************************************/

#define ID_SCRM MAKE_ID('S','C','R','M')

struct ScreenModePrefs
{
    ULONG smp_Reserved[4];
    ULONG smp_DisplayID;
    UWORD smp_Width;
    UWORD smp_Height;
    UWORD smp_Depth;
    UWORD smp_Control;
};

/* flags for ScreenModePrefs.smp_Control */
#define SMB_AUTOSCROLL 1

#define SMF_AUTOSCROLL (1<<0)

/*****************************************************************************/

#endif /* PREFS_SCREENMODE_H */


include/devices/scsidisk.h

#ifndef	DEVICES_SCSIDISK_H
#define	DEVICES_SCSIDISK_H
/*
**	$VER: scsidisk.h 44.1 (17.04.1999)
**	Includes Release 44.1
**
**	SCSI exec-level device command
**
**	(C) Copyright 1988-1999 Amiga, Inc.
**	    All Rights Reserved
**
**	(C) Copyright 1999 by Joanne Dow, Wizardess Designs, licensed to
**		Amiga Inc.
**		All Rights Reserved
*/

/*
**	Changes:
**		Added new numbering scheme for handling WIDE SCSI devices.
**		Note that at this time only support for up to 16 IDs is
**		contemplated in most designs although this numbering system
**		can consider far far more.
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif /* EXEC_TYPES_H */

/*--------------------------------------------------------------------
 *
 *   SCSI Command
 *	Several Amiga SCSI controller manufacturers are converging on
 *	standard ways to talk to their controllers.  This include
 *	file describes an exec-device command (e.g. for hddisk.device)
 *	that can be used to issue SCSI commands
 *
 *   UNIT NUMBERS
 *	Unit numbers to the OpenDevice call have encoded in them which
 *	SCSI device is being referred to.  The three decimal digits of
 *	the unit number refer to the SCSI Target ID (bus address) in
 *	the 1's digit, the SCSI logical unit (LUN) in the 10's digit,
 *	and the controller board in the 100's digit.
 *
 *	Examples:
 *		  0	drive at address 0
 *		 12	LUN 1 on multiple drive controller at address 2
 *		104	second controller board, address 4
 *		 88	not valid: both logical units and addresses
 *			range from 0..7.
 *
 *   CAVEATS
 *	Original 2090 code did not support this command.
 *
 *	Commodore 2090/2090A unit numbers are different.  The SCSI
 *	logical unit is the 100's digit, and the SCSI Target ID
 *	is a permuted 1's digit: Target ID 0..6 maps to unit 3..9
 *	(7 is reserved for the controller).
 *
 *	    Examples:
 *		  3	drive at address 0
 *		109	drive at address 6, logical unit 1
 *		  1	not valid: this is not a SCSI unit.  Perhaps
 *			it's an ST506 unit.
 *
 *	Some controller boards generate a unique name (e.g. 2090A's
 *	iddisk.device) for the second controller board, instead of
 *	implementing the 100's digit.
 *
 *	With the advent of wide SCSI the scheme above fails miserably.
 *	A new scheme was adopted by Phase V, who appear to be the only
 *	source of wide SCSI for the Amiga at this time. Thus their
 *	numbering system kludge is adopted here. When the ID or LUN is
 *	above 7 the new numbering scheme is used.
 *
 *	Unit =
 *		Board * 10 * 1000 * 1000 +
 *		LUN	  * 10 * 1000		 +
 *		ID	  * 10				 +
 *		HD_WIDESCSI;
 *
 *	There are optional restrictions on the alignment, bus
 *	accessability, and size of the data for the data phase.
 *	Be conservative to work with all manufacturer's controllers.
 *
 *------------------------------------------------------------------*/

#define HD_WIDESCSI	8	/* Wide SCSI detection bit. */
#define	HD_SCSICMD	28	/* issue a SCSI command to the unit */
                /* io_Data points to a SCSICmd */
                /* io_Length is sizeof(struct SCSICmd) */
                /* io_Actual and io_Offset are not used */

struct SCSICmd {
    UWORD  *scsi_Data;		/* word aligned data for SCSI Data Phase */
                /* (optional) data need not be byte aligned */
                /* (optional) data need not be bus accessable */
    ULONG   scsi_Length;	/* even length of Data area */
                /* (optional) data can have odd length */
                /* (optional) data length can be > 2**24 */
    ULONG   scsi_Actual;	/* actual Data used */
    UBYTE  *scsi_Command;	/* SCSI Command (same options as scsi_Data) */
    UWORD   scsi_CmdLength;	/* length of Command */
    UWORD   scsi_CmdActual;	/* actual Command used */
    UBYTE   scsi_Flags;		/* includes intended data direction */
    UBYTE   scsi_Status;	/* SCSI status of command */
    UBYTE  *scsi_SenseData;	/* sense data: filled if SCSIF_[OLD]AUTOSENSE */
                /* is set and scsi_Status has CHECK CONDITION */
                /* (bit 1) set */
    UWORD   scsi_SenseLength;	/* size of scsi_SenseData, also bytes to */
                /* request w/ SCSIF_AUTOSENSE, must be 4..255 */
    UWORD   scsi_SenseActual;	/* amount actually fetched (0 means no sense) */
};

/*----- scsi_Flags -----*/
#define	SCSIF_WRITE		0	/* intended data direction is out */
#define	SCSIF_READ		1	/* intended data direction is in */
#define	SCSIB_READ_WRITE	0	/* (the bit to test) */

#define	SCSIF_NOSENSE		0	/* no automatic request sense */
#define	SCSIF_AUTOSENSE		2	/* do standard extended request sense */
                    /* on check condition */
#define	SCSIF_OLDAUTOSENSE	6	/* do 4 byte non-extended request */
                    /* sense on check condition */
#define	SCSIB_AUTOSENSE		1	/* (the bit to test) */
#define	SCSIB_OLDAUTOSENSE	2	/* (the bit to test) */

/*----- SCSI io_Error values -----*/
#define	HFERR_SelfUnit		40	/* cannot issue SCSI command to self */
#define	HFERR_DMA		41	/* DMA error */
#define	HFERR_Phase		42	/* illegal or unexpected SCSI phase */
#define	HFERR_Parity		43	/* SCSI parity error */
#define	HFERR_SelTimeout	44	/* Select timed out */
#define	HFERR_BadStatus		45	/* status and/or sense error */

/*----- OpenDevice io_Error values -----*/
#define	HFERR_NoBoard		50	/* Open failed for non-existant board */

#endif	/* DEVICES_SCSIDISK_H */


include/exec/semaphores.h

#ifndef	EXEC_SEMAPHORES_H
#define	EXEC_SEMAPHORES_H
/*
**	$VER: semaphores.h 39.1 (7.2.1992)
**	Includes Release 44.1
**
**	Definitions for locking functions.
**
**	(C) Copyright 1986-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_NODES_H
#include <exec/nodes.h>
#endif /* EXEC_NODES_H */

#ifndef EXEC_LISTS_H
#include <exec/lists.h>
#endif /* EXEC_LISTS_H */

#ifndef EXEC_PORTS_H
#include <exec/ports.h>
#endif /* EXEC_PORTS_H */

#ifndef EXEC_TASKS_H
#include <exec/tasks.h>
#endif /* EXEC_TASKS_H */

/****** SignalSemaphore *********************************************/

/* Private structure used by ObtainSemaphore() */
struct SemaphoreRequest
{
    struct MinNode	sr_Link;
    struct Task	*sr_Waiter;
};

/* Signal Semaphore data structure */
struct SignalSemaphore
{
    struct Node		ss_Link;
    WORD			ss_NestCount;
    struct MinList		ss_WaitQueue;
    struct SemaphoreRequest	ss_MultipleLink;
    struct Task		*ss_Owner;
    WORD			ss_QueueCount;
};

/****** Semaphore procure message (for use in V39 Procure/Vacate) ****/
struct SemaphoreMessage
{
    struct Message		ssm_Message;
    struct SignalSemaphore	*ssm_Semaphore;
};

#define	SM_SHARED	(1L)
#define	SM_EXCLUSIVE	(0L)

/****** Semaphore (Old Procure/Vacate type, not reliable) ***********/

struct Semaphore	/* Do not use these semaphores! */
{
    struct MsgPort	sm_MsgPort;
    WORD		sm_Bids;
};

#define sm_LockMsg mp_SigTask

#endif	/* EXEC_SEMAPHORES_H */


include/prefs/serial.h

#ifndef PREFS_SERIAL_H
#define PREFS_SERIAL_H
/*
**	$VER: serial.h 38.2 (10.7.1991)
**	Includes Release 44.1
**
**	File format for serial preferences
**
**	(C) Copyright 1991-1999 Amiga, Inc.
**	All Rights Reserved
*/

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef LIBRARIES_IFFPARSE_H
#include <libraries/iffparse.h>
#endif

/*****************************************************************************/

#define ID_SERL MAKE_ID('S','E','R','L')

struct SerialPrefs
{
    LONG  sp_Reserved[3];		/* System reserved		    */
    ULONG sp_Unit0Map;			/* What unit 0 really refers to     */
    ULONG sp_BaudRate;			/* Baud rate			    */

    ULONG sp_InputBuffer;		/* Input buffer: 0 - 65536	    */
    ULONG sp_OutputBuffer;		/* Future: Output: 0 - 65536	    */

    UBYTE sp_InputHandshake;		/* Input handshaking		    */
    UBYTE sp_OutputHandshake;		/* Future: Output handshaking	    */

    UBYTE sp_Parity;			/* Parity			    */
    UBYTE sp_BitsPerChar;		/* I/O bits per character	    */
    UBYTE sp_StopBits;			/* Stop bits			    */
};

/* constants for SerialPrefs.sp_Parity */
#define PARITY_NONE	0
#define PARITY_EVEN	1
#define PARITY_ODD	2
#define PARITY_MARK	3		/* Future enhancement */
#define PARITY_SPACE	4		/* Future enhancement */

/* constants for SerialPrefs.sp_Input/OutputHandshaking */
#define HSHAKE_XON	0
#define HSHAKE_RTS	1
#define HSHAKE_NONE	2

/*****************************************************************************/

#endif /* PREFS_SERIAL_H */


include/intuition/sghooks.h

#ifndef INTUITION_SGHOOKS_H
#define INTUITION_SGHOOKS_H TRUE
/*
**  $VER: sghooks.h 38.1 (11.11.1991)
**  Includes Release 44.1
**
**  string gadget extensions and hooks
**
**  (C) Copyright 1988-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

struct StringExtend {
    /* display specifications	*/
    struct TextFont *Font;	/* must be an open Font (not TextAttr)	*/
    UBYTE	Pens[2];	/* color of text/backgroun		*/
    UBYTE	ActivePens[2];	/* colors when gadget is active		*/

    /* edit specifications	*/
    ULONG	InitialModes;	/* initial mode flags, below		*/
    struct Hook *EditHook;	/* if non-NULL, must supply WorkBuffer	*/
    UBYTE	*WorkBuffer;	/* must be as large as StringInfo.Buffer*/

    ULONG	Reserved[4];	/* set to 0				*/
};

struct SGWork	{
    /* set up when gadget is first activated	*/
    struct Gadget	*Gadget;	/* the contestant itself	*/
    struct StringInfo	*StringInfo;	/* easy access to sinfo		*/
    UBYTE		*WorkBuffer;	/* intuition's planned result	*/
    UBYTE		*PrevBuffer;	/* what was there before	*/
    ULONG		Modes;		/* current mode			*/

    /* modified for each input event	*/
    struct InputEvent	*IEvent;	/* actual event: do not change	*/
    UWORD		Code;		/* character code, if one byte	*/
    WORD		BufferPos;	/* cursor position		*/
    WORD		NumChars;
    ULONG		Actions;	/* what Intuition will do	*/
    LONG		LongInt;	/* temp storage for longint	*/

    struct GadgetInfo	*GadgetInfo;	/* see cghooks.h		*/
    UWORD		EditOp;		/* from constants below		*/
};

/* SGWork.EditOp -
 * These values indicate what basic type of operation the global
 * editing hook has performed on the string before your gadget's custom
 * editing hook gets called.  You do not have to be concerned with the
 * value your custom hook leaves in the EditOp field, only if you
 * write a global editing hook.
 *
 * For most of these general edit operations, you'll want to compare
 * the BufferPos and NumChars of the StringInfo (before global editing)
 * and SGWork (after global editing).
 */

#define EO_NOOP		(0x0001)
    /* did nothing							*/
#define EO_DELBACKWARD	(0x0002)
    /* deleted some chars (maybe 0).				*/
#define EO_DELFORWARD	(0x0003)
    /* deleted some characters under and in front of the cursor	*/
#define EO_MOVECURSOR	(0x0004)
    /* moved the cursor						*/
#define EO_ENTER	(0x0005)
    /* "enter" or "return" key, terminate				*/
#define EO_RESET	(0x0006)
    /* current Intuition-style undo					*/
#define EO_REPLACECHAR	(0x0007)
    /* replaced one character and (maybe) advanced cursor		*/
#define EO_INSERTCHAR	(0x0008)
    /* inserted one char into string or added one at end		*/
#define EO_BADFORMAT	(0x0009)
    /* didn't like the text data, e.g., Bad LONGINT			*/
#define EO_BIGCHANGE	(0x000A)	/* unused by Intuition	*/
    /* complete or major change to the text, e.g. new string	*/
#define EO_UNDO		(0x000B)	/* unused by Intuition	*/
    /* some other style of undo					*/
#define EO_CLEAR	(0x000C)
    /* clear the string						*/
#define EO_SPECIAL	(0x000D)	/* unused by Intuition	*/
    /* some operation that doesn't fit into the categories here	*/

/* Mode Flags definitions (ONLY first group allowed as InitialModes)	*/
#define SGM_REPLACE	(1L << 0)	/* replace mode			*/
/* please initialize StringInfo with in-range value of BufferPos
 * if you are using SGM_REPLACE mode.
 */

#define SGM_FIXEDFIELD	(1L << 1)	/* fixed length buffer		*/
                    /* always set SGM_REPLACE, too	*/
#define SGM_NOFILTER	(1L << 2)	/* don't filter control chars	*/

/* SGM_EXITHELP is new for V37, and ignored by V36: */
#define SGM_EXITHELP	(1L << 7)	/* exit with code = 0x5F if HELP hit */

/* These Mode Flags are for internal use only				*/
#define SGM_NOCHANGE	(1L << 3)	/* no edit changes yet		*/
#define SGM_NOWORKB	(1L << 4)	/* Buffer == PrevBuffer		*/
#define SGM_CONTROL	(1L << 5)	/* control char escape mode	*/
#define SGM_LONGINT	(1L << 6)	/* an intuition longint gadget	*/

/* String Gadget Action Flags (put in SGWork.Actions by EditHook)	*/
#define SGA_USE		(0x1L)	/* use contents of SGWork		*/
#define SGA_END		(0x2L)	/* terminate gadget, code in Code field	*/
#define SGA_BEEP	(0x4L)	/* flash the screen for the user	*/
#define SGA_REUSE	(0x8L)	/* reuse input event			*/
#define SGA_REDISPLAY	(0x10L)	/* gadget visuals changed		*/

/* New for V37: */
#define SGA_NEXTACTIVE	(0x20L)	/* Make next possible gadget active.	*/
#define SGA_PREVACTIVE	(0x40L)	/* Make previous possible gadget active.*/

/* function id for only existing custom string gadget edit hook	*/

#define SGH_KEY		(1L)	/* process editing keystroke		*/
#define SGH_CLICK	(2L)	/* process mouse click cursor position	*/

/* Here's a brief summary of how the custom string gadget edit hook works:
 *	You provide a hook in StringInfo.Extension.EditHook.
 *	The hook is called in the standard way with the 'object'
 *	a pointer to SGWork, and the 'message' a pointer to a command
 *	block, starting either with (longword) SGH_KEY, SGH_CLICK,
 *	or something new.
 *
 *	You return 0 if you don't understand the command (SGH_KEY is
 *	required and assumed).	Return non-zero if you implement the
 *	command.
 *
 *   SGH_KEY:
 *	There are no parameters following the command longword.
 *
 *	Intuition will put its idea of proper values in the SGWork
 *	before calling you, and if you leave SGA_USE set in the
 *	SGWork.Actions field, Intuition will use the values
 *	found in SGWork fields WorkBuffer, NumChars, BufferPos,
 *	and LongInt, copying the WorkBuffer back to the StringInfo
 *	Buffer.
 *
 *	NOTE WELL: You may NOT change other SGWork fields.
 *
 *	If you clear SGA_USE, the string gadget will be unchanged.
 *
 *	If you set SGA_END, Intuition will terminate the activation
 *	of the string gadget.  If you also set SGA_REUSE, Intuition
 *	will reuse the input event after it deactivates your gadget.
 *
 *	In this case, Intuition will put the value found in SGWork.Code
 *	into the IntuiMessage.Code field of the IDCMP_GADGETUP message it
 *	sends to the application.
 *
 *	If you set SGA_BEEP, Intuition will call DisplayBeep(); use
 *	this if the user has typed in error, or buffer is full.
 *
 *	Set SGA_REDISPLAY if the changes to the gadget warrant a
 *	gadget redisplay.  Note: cursor movement requires a redisplay.
 *
 *	Starting in V37, you may set SGA_PREVACTIVE or SGA_NEXTACTIVE
 *	when you set SGA_END.  This tells Intuition that you want
 *	the next or previous gadget with GFLG_TABCYCLE to be activated.
 *
 *   SGH_CLICK:
 *	This hook command is called when Intuition wants to position
 *	the cursor in response to a mouse click in the string gadget.
 *
 *	Again, here are no parameters following the command longword.
 *
 *	This time, Intuition has already calculated the mouse position
 *	character cell and put it in SGWork.BufferPos.	The previous
 *	BufferPos value remains in the SGWork.StringInfo.BufferPos.
 *
 *	Intuition will again use the SGWork fields listed above for
 *	SGH_KEY.  One restriction is that you are NOT allowed to set
 *	SGA_END or SGA_REUSE for this command.	Intuition will not
 *	stand for a gadget which goes inactive when you click in it.
 *
 *	You should always leave the SGA_REDISPLAY flag set, since Intuition
 *	uses this processing when activating a string gadget.
 */

#endif


include/prefs/sound.h

#ifndef PREFS_SOUND_H
#define PREFS_SOUND_H
/*
**	$VER: sound.h 38.2 (20.6.1991)
**	Includes Release 44.1
**
**	File format for sound preferences
**
**	(C) Copyright 1991-1999 Amiga, Inc.
**	All Rights Reserved
*/

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef LIBRARIES_IFFPARSE_H
#include <libraries/iffparse.h>
#endif

/*****************************************************************************/

#define ID_SOND MAKE_ID('S','O','N','D')

struct SoundPrefs
{
    LONG  sop_Reserved[4];	      /* System reserved	    */
    BOOL  sop_DisplayQueue;	      /* Flash the display?	    */
    BOOL  sop_AudioQueue;	      /* Make some sound?	    */
    UWORD sop_AudioType;	      /* Type of sound, see below   */
    UWORD sop_AudioVolume;	      /* Volume of sound, 0..64     */
    UWORD sop_AudioPeriod;	      /* Period of sound, 127..2500 */
    UWORD sop_AudioDuration;	      /* Length of simple beep	    */
    char  sop_AudioFileName[256];     /* Filename of 8SVX file	    */
};

/* constants for SoundPrefs.sop_AudioType */
#define SPTYPE_BEEP	0	/* simple beep sound */
#define SPTYPE_SAMPLE	1	/* sampled sound     */

/*****************************************************************************/

#endif /* PREFS_SOUND_H */


include/exec/tasks.h

#ifndef	EXEC_TASKS_H
#define	EXEC_TASKS_H
/*
**	$VER: tasks.h 39.3 (18.9.1992)
**	Includes Release 44.1
**
**	Task Control Block, Signals, and Task flags.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_NODES_H
#include <exec/nodes.h>
#endif /* EXEC_NODES_H */

#ifndef EXEC_LISTS_H
#include <exec/lists.h>
#endif /* EXEC_LISTS_H */

/* Please use Exec functions to modify task structure fields, where available.
 */
struct Task {
    struct  Node tc_Node;
    UBYTE   tc_Flags;
    UBYTE   tc_State;
    BYTE    tc_IDNestCnt;	    /* intr disabled nesting*/
    BYTE    tc_TDNestCnt;	    /* task disabled nesting*/
    ULONG   tc_SigAlloc;	    /* sigs allocated */
    ULONG   tc_SigWait;	    /* sigs we are waiting for */
    ULONG   tc_SigRecvd;	    /* sigs we have received */
    ULONG   tc_SigExcept;	    /* sigs we will take excepts for */
    UWORD   tc_TrapAlloc;	    /* traps allocated */
    UWORD   tc_TrapAble;	    /* traps enabled */
    APTR    tc_ExceptData;	    /* points to except data */
    APTR    tc_ExceptCode;	    /* points to except code */
    APTR    tc_TrapData;	    /* points to trap data */
    APTR    tc_TrapCode;	    /* points to trap code */
    APTR    tc_SPReg;		    /* stack pointer	    */
    APTR    tc_SPLower;	    /* stack lower bound    */
    APTR    tc_SPUpper;	    /* stack upper bound + 2*/
    VOID    (*tc_Switch)();	    /* task losing CPU	  */
    VOID    (*tc_Launch)();	    /* task getting CPU  */
    struct  List tc_MemEntry;	    /* Allocated memory. Freed by RemTask() */
    APTR    tc_UserData;	    /* For use by the task; no restrictions! */
};

/*
 * Stack swap structure as passed to StackSwap()
 */
struct	StackSwapStruct {
    APTR	stk_Lower;	/* Lowest byte of stack */
    ULONG	stk_Upper;	/* Upper end of stack (size + Lowest) */
    APTR	stk_Pointer;	/* Stack pointer at switch point */
};

/*----- Flag Bits ------------------------------------------*/
#define TB_PROCTIME	0
#define TB_ETASK	3
#define TB_STACKCHK	4
#define TB_EXCEPT	5
#define TB_SWITCH	6
#define TB_LAUNCH	7

#define TF_PROCTIME	(1L<<0)
#define TF_ETASK	(1L<<3)
#define TF_STACKCHK	(1L<<4)
#define TF_EXCEPT	(1L<<5)
#define TF_SWITCH	(1L<<6)
#define TF_LAUNCH	(1L<<7)

/*----- Task States ----------------------------------------*/
#define TS_INVALID	0
#define TS_ADDED	1
#define TS_RUN		2
#define TS_READY	3
#define TS_WAIT	4
#define TS_EXCEPT	5
#define TS_REMOVED	6

/*----- Predefined Signals -------------------------------------*/
#define SIGB_ABORT	0
#define SIGB_CHILD	1
#define SIGB_BLIT	4	/* Note: same as SINGLE */
#define SIGB_SINGLE	4	/* Note: same as BLIT */
#define SIGB_INTUITION	5
#define	SIGB_NET	7
#define SIGB_DOS	8

#define SIGF_ABORT	(1L<<0)
#define SIGF_CHILD	(1L<<1)
#define SIGF_BLIT	(1L<<4)
#define SIGF_SINGLE	(1L<<4)
#define SIGF_INTUITION	(1L<<5)
#define	SIGF_NET	(1L<<7)
#define SIGF_DOS	(1L<<8)

#endif	/* EXEC_TASKS_H */


include/utility/tagitem.h

#ifndef UTILITY_TAGITEM_H
#define UTILITY_TAGITEM_H
/*
**	$VER: tagitem.h 40.1 (19.7.1993)
**	Includes Release 44.1
**
**	Extended specification mechanism
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	All Rights Reserved
*/

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

/*****************************************************************************/

/* Tags are a general mechanism of extensible data arrays for parameter
 * specification and property inquiry. In practice, tags are used in arrays,
 * or chain of arrays.
 *
 */

typedef ULONG Tag;

struct TagItem
{
    Tag	  ti_Tag;	/* identifies the type of data */
    ULONG ti_Data;	/* type-specific data	       */
};

/* constants for Tag.ti_Tag, control tag values */
#define TAG_DONE   (0L)	  /* terminates array of TagItems. ti_Data unused */
#define TAG_END	   (0L)   /* synonym for TAG_DONE			  */
#define	TAG_IGNORE (1L)	  /* ignore this item, not end of array		  */
#define	TAG_MORE   (2L)	  /* ti_Data is pointer to another array of TagItems
               * note that this tag terminates the current array
               */
#define	TAG_SKIP   (3L)	  /* skip this and the next ti_Data items	  */

/* differentiates user tags from control tags */
#define TAG_USER   ((ULONG)(1L<<31))

/* If the TAG_USER bit is set in a tag number, it tells utility.library that
 * the tag is not a control tag (like TAG_DONE, TAG_IGNORE, TAG_MORE) and is
 * instead an application tag. "USER" means a client of utility.library in
 * general, including system code like Intuition or ASL, it has nothing to do
 * with user code.
 */

/*****************************************************************************/

/* Tag filter logic specifiers for use with FilterTagItems() */
#define TAGFILTER_AND 0		/* exclude everything but filter hits	*/
#define TAGFILTER_NOT 1		/* exclude only filter hits		*/

/*****************************************************************************/

/* Mapping types for use with MapTags() */
#define MAP_REMOVE_NOT_FOUND 0	/* remove tags that aren't in mapList */
#define MAP_KEEP_NOT_FOUND   1	/* keep tags that aren't in mapList   */

/*****************************************************************************/

#endif /* UTILITY_TAGITEM_H */


include/reaction/reaction_prefs.h

#ifndef REACTION_REACTION_PREFS_H
#define REACTION_REACTION_PREFS_H
/*
**	$VER: reaction_prefs.h 44.1 (19.10.1999)
**	Includes Release 44.1
**
**	Reaction preferences definitions
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_SEMAPHORES_H
#include <exec/semaphores.h>
#endif

/*
 * Obtain this semaphore while reading the preferences
 */
#define RAPREFSSEMAPHORE "REACTION-PREFS"

/* WARNING: This structure has been changing, and will continue to change.
 * In the future, this structure might possible be accesssed at a higher
 * level via a tag list. For now, except for class authors wishing our
 * support in handling prefs, this is data is to be considered off limits.
 */

#define ClassActPrefs UIPrefs

struct UIPrefs
{
    /* Set PrefsVersion to 1 */
    struct SignalSemaphore	 cap_Semaphore;
    UWORD					 cap_PrefsVersion;
    UWORD					 cap_PrefsSize;
    UBYTE					 cap_BevelType;
    UWORD					 cap_LayoutSpacing;
    BOOL					 cap_3DLook;
    UWORD					 cap_LabelPen;
    UBYTE					 cap_LabelPlace;
    UBYTE					 cap_3DLabel;
    ULONG					*cap_Reserved1;
    BOOL					 cap_SimpleRefresh;
    UBYTE					 cap_Pattern[256];
    ULONG					*cap_Reserved2;

    BOOL					 cap_3DProp;
    BOOL					 cap_Reserved3;

    UBYTE					 cap_GlyphType;	/* currently unsupported/unused!! */
    UBYTE					 cap_Reserved4;

    struct TextAttr			*cap_FallbackAttr;
    struct TextAttr			*cap_LabelAttr;
};

/* Bevel Types */
#define BVT_GT      0	/* GadTools style 2:1 bevels */
#define BVT_THIN    1	/* CA 1:1 bevels */
#define BVT_THICK   2	/* CA 2:1 4 color thick bevels */
#define BVT_XEN     3	/* 4 color Xen-Style inspired 1/2 shine bevels */
#define BVT_XENTHIN 4	/* 3 color Xen-Style inspired thin 1/2 shine 1:1 bevels */

/* Glyph Types */
#define GLT_GT    0
#define GLT_FLAT  1
#define GLT_3D    2

#endif /* REACTION_REACTION_PREFS_H */


include/utility/utility.h

#ifndef UTILITY_UTILITY_H
#define UTILITY_UTILITY_H
/*
**	$VER: utility.h 39.2 (18.9.1992)
**	Includes Release 44.1
**
**	utility.library include file
**
**	(C) Copyright 1992-1999 Amiga, Inc.
**	All Rights Reserved
*/

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef EXEC_LIBRARIES_H
#include <exec/libraries.h>
#endif

/*****************************************************************************/

#define UTILITYNAME "utility.library"

struct UtilityBase
{
    struct Library ub_LibNode;
    UBYTE	   ub_Language;
    UBYTE	   ub_Reserved;
};

/*****************************************************************************/

#endif /* UTILITY_UTILITY_H */


include/datatypes/soundclass.h

#ifndef	DATATYPES_SOUNDCLASS_H
#define	DATATYPES_SOUNDCLASS_H
/*
**	$VER: soundclass.h 44.7 (6.6.1999)
**	Includes Release 44.1
**
**	Interface definitions for DataType sound objects.
**
**	Copyright © 1992-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef	UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

#ifndef	DATATYPES_DATATYPESCLASS_H
#include <datatypes/datatypesclass.h>
#endif

#ifndef	LIBRARIES_IFFPARSE_H
#include <libraries/iffparse.h>
#endif

#ifndef	DEVICES_TIMER_H
#include <devices/timer.h>
#endif

/*****************************************************************************/

#define	SOUNDDTCLASS		"sound.datatype"

/*****************************************************************************/

/* Sound attributes */
#define	SDTA_Dummy		(DTA_Dummy + 500)
#define	SDTA_VoiceHeader	(SDTA_Dummy + 1)

/* (BYTE *) Sample data */
#define	SDTA_Sample		(SDTA_Dummy + 2)

/* (ULONG) Length of the sample data in UBYTEs */
#define	SDTA_SampleLength	(SDTA_Dummy + 3)

/* (UWORD) Period */
#define	SDTA_Period		(SDTA_Dummy + 4)

/* (UWORD) Volume. Range from 0 to 64 */
#define	SDTA_Volume		(SDTA_Dummy + 5)

#define	SDTA_Cycles		(SDTA_Dummy + 6)

/* The following tags are new for V40 */

/* (struct Task *) Task to signal when sound is complete or next buffer needed. */
#define	SDTA_SignalTask		(SDTA_Dummy + 7)

/* (ULONG) Signal mask to use on completion or 0 to disable
 *
 *         NOTE: Due to a bug in sound.datatype V40 SDTA_SignalBit
 *               was actually implemented as a signal mask as opposed
 *               to a bit number. The documentation now reflects
 *               this. If you intend to use a signal bit number
 *               instead of the mask, use the new V44 tag
 *               SDTA_SignalBitNumber below.
 */
#define	SDTA_SignalBit		(SDTA_Dummy + 8)
#define	SDTA_SignalBitMask	SDTA_SignalBit

/* (BOOL) Playing a continuous stream of data.  Defaults to FALSE. */
#define	SDTA_Continuous		(SDTA_Dummy + 9)

/* The following tags are new for V44 */

/* (BYTE) Signal bit to use on completion or -1 to disable */
#define	SDTA_SignalBitNumber	(SDTA_Dummy + 10)

/* (UWORD) Samples per second */
#define	SDTA_SamplesPerSec	(SDTA_Dummy + 11)

/* (struct timeval *) Sample replay period */
#define	SDTA_ReplayPeriod	(SDTA_Dummy + 12)

/* (BYTE *) Sample data */
#define	SDTA_LeftSample		(SDTA_Dummy + 13)
#define	SDTA_RightSample	(SDTA_Dummy + 14)

/* (BYTE) Stereo panning */
#define	SDTA_Pan		(SDTA_Dummy + 15)

/* (BOOL) FreeVec() all sample data upon OM_DISPOSE. */
#define	SDTA_FreeSampleData	(SDTA_Dummy + 16)

/* (BOOL) Wait for the current sample to be played back before
 * switching to the new sample data.
 */
#define	SDTA_SyncSampleChange	(SDTA_Dummy + 17)

/*****************************************************************************/

/* Data compression methods */
#define CMP_NONE     0
#define CMP_FIBDELTA 1

/*****************************************************************************/

/* Unity = Fixed 1.0 = maximum volume */
#define Unity 0x10000UL

/*****************************************************************************/

struct VoiceHeader
{
    ULONG vh_OneShotHiSamples;	/* # samples in the high octave 1-shot part */
    ULONG vh_RepeatHiSamples;	/* # samples in the high octave repeat part */
    ULONG vh_SamplesPerHiCycle;	/* # samples/cycle in high octave, else 0 */
    UWORD vh_SamplesPerSec;		/* data sampling rate */
    UBYTE vh_Octaves;		/* # of octaves of waveforms */
    UBYTE vh_Compression;		/* data compression technique used */
    ULONG vh_Volume;		/* playback nominal volume from 0 to Unity
                     * (full volume). Map this value into
                     * the output hardware's dynamic range.
                     */
};

/*****************************************************************************/

/* Channel allocation */
#define SAMPLETYPE_Left		(2L)
#define SAMPLETYPE_Right	(4L)
#define SAMPLETYPE_Stereo	(6L)

typedef long SampleType;

/*****************************************************************************/

/* IFF types */
#define ID_8SVX	MAKE_ID('8','S','V','X')
#define ID_VHDR	MAKE_ID('V','H','D','R')
#define ID_CHAN	MAKE_ID('C','H','A','N')
#define ID_BODY	MAKE_ID('B','O','D','Y')

/*****************************************************************************/

#endif	/* DATATYPES_SOUNDCLASS_H */


include/workbench/startup.h

#ifndef WORKBENCH_STARTUP_H
#define WORKBENCH_STARTUP_H
/*
**	$VER: startup.h 36.3 (11.7.1990)
**	Includes Release 44.1
**
**	workbench startup definitions
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef EXEC_PORTS_H
#include <exec/ports.h>
#endif

#ifndef DOS_DOS_H
#include <dos/dos.h>
#endif

struct WBStartup {
    struct Message	sm_Message;	/* a standard message structure */
    struct MsgPort *	sm_Process;	/* the process descriptor for you */
    BPTR		sm_Segment;	/* a descriptor for your code */
    LONG		sm_NumArgs;	/* the number of elements in ArgList */
    char *		sm_ToolWindow;	/* description of window */
    struct WBArg *	sm_ArgList;	/* the arguments themselves */
};

struct WBArg {
    BPTR		wa_Lock;	/* a lock descriptor */
    BYTE *		wa_Name;	/* a string relative to that lock */
};

#endif	/* !WORKBENCH_STARTUP_H */


include/prefs/wbpattern.h

#ifndef PREFS_WBPATTERN_H
#define PREFS_WBPATTERN_H
/*
**	$VER: wbpattern.h 44.1 (19.10.1999)
**	Includes Release 44.1
**
**	File format for wbpattern preferences
**
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

/*****************************************************************************/

#ifndef LIBRARIES_IFFPARSE_H
#include <libraries/iffparse.h>
#endif

/*****************************************************************************/

#define ID_PTRN MAKE_ID('P','T','R','N')

/*****************************************************************************/

struct WBPatternPrefs
{
    ULONG	 wbp_Reserved[4];
    UWORD	 wbp_Which;			/* Which pattern is it */
    UWORD	 wbp_Flags;
    BYTE	 wbp_Revision;			/* Must be set to zero */
    BYTE	 wbp_Depth;			/* Depth of pattern */
    UWORD	 wbp_DataLength;		/* Length of following data */
};

/*****************************************************************************/

/* constants for WBPatternPrefs.wbp_Which */
#define	WBP_ROOT	0
#define	WBP_DRAWER	1
#define	WBP_SCREEN	2

/* wbp_Flags values */
#define	WBPF_PATTERN	0x0001
    /* Data contains a pattern */

#define	WBPF_NOREMAP	0x0010
    /* Don't remap the pattern */

    /* PDTA_DitherQuality: see pictureclass.h */
#define	WBPF_DITHER_MASK	0x0300
#define	WBPF_DITHER_DEF		0x0000 /* DitherQuality: Default */
#define	WBPF_DITHER_BAD		0x0100 /* DitherQuality: 0 */
#define	WBPF_DITHER_GOOD	0x0200 /* DitherQuality: 2 */
#define	WBPF_DITHER_BEST	0x0300 /* DitherQuality: 4 */

    /* OBP_Precision: see pictureclass.h */
#define	WBPF_PRECISION_MASK	0x0C00
#define	WBPF_PRECISION_DEF	0x0000
#define	WBPF_PRECISION_ICON	0x0400
#define	WBPF_PRECISION_IMAGE	0x0800
#define	WBPF_PRECISION_EXACT	0x0C00

/*****************************************************************************/

#define MAXDEPTH	3	/*  Max depth supported (8 colors) */
#define DEFPATDEPTH	2	/*  Depth of default patterns */

/*  Pattern width & height: */
#define PAT_WIDTH	16
#define PAT_HEIGHT	16

/*****************************************************************************/

#endif /* PREFS_WBPATTERN_H */


include/classes/window.h

#ifndef CLASSES_WINDOW_H
#define CLASSES_WINDOW_H
/*
**	$VER: window.h 44.1 (19.10.1999)
**	Includes Release 44.1
**
**	window.class definitions
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

/****************************************************************************/

#ifndef REACTION_REACTION_H
#include <reaction/reaction.h>
#endif

/****************************************************************************/

/*
** Attributes specific to window.class
*/

#define WINDOW_Dummy			(REACTION_Dummy + 0x25000)

#define WINDOW_Window        (WINDOW_Dummy + 1)
    /* (struct Window *) Return the pointer to the real      */
    /*                   Intuition window structure.         */

#define WINDOW_SigMask       (WINDOW_Dummy + 2)
    /* (ULONG) Return the signal bit that you must wait for  */
    /*         this window to know if the window as received */
    /*         any input.                                    */
    /* Defaults to 0.                                        */

#define WINDOW_MenuStrip     (WINDOW_Dummy + 4)
    /* (struct MenuStrip *) A list of Menu structure that will */
    /*                 be used as the menu of this window    */
    /*                 when open.                            */
    /* Defaults to NULL.                                     */

#define WINDOW_Layout	(WINDOW_Dummy + 5)
#define WINDOW_ParentLayout   	WINDOW_Layout
#define WINDOW_ParentGroup		WINDOW_Layout
    /* (Object *)        Layout group object for the window  */
    /* Defaults to NULL.                                     */

#define WINDOW_UserData      (WINDOW_Dummy + 6)
    /* (APTR) A value that will be stored in the Window      */
    /*        Object structure.                              */
    /* Defaults to NULL.                                     */

#define WINDOW_SharedPort    (WINDOW_Dummy + 7)
    /* (struct MsgPort *) A port that will be used for this  */
    /*                    window.  The port will not be      */
    /*                    closed at dispose time.            */
    /* Defaults to NULL.                                     */

#define WINDOW_Zoom          (WINDOW_Dummy + 8)
    /* When TRUE, it will act as a click on the zoom button. */

#define WINDOW_FrontBack     (WINDOW_Dummy + 9)
    /* (UWORD) Only WT_FRONT and WT_BACK can be used here.   */
    /*         This put the window in front or in back of    */
    /*         others windows                                */

#define WINDOW_Activate      (WINDOW_Dummy +10)
    /* (BOOL) Activate the window (and its master group) if  */
    /*        set to TRUE and the                            */
    /*        window is open.                                */

#define WINDOW_LockWidth     (WINDOW_Dummy +11)
    /* (BOOL) Lock the window from resize in width.          */
    /* Defaults to FALSE.                                    */

#define WINDOW_LockHeight    (WINDOW_Dummy +12)
    /* (BOOL) Lock the window from resize in height.         */
    /* Defaults to FALSE.                                    */

#define WINDOW_AppPort       (WINDOW_Dummy +13)
    /* (struct MsgPort *) A shared message port for appmessages */
    /* 	You must pass this to be able to iconify the window. */
    /* Defaults to NULL.                                     */

#define WINDOW_Position		 (WINDOW_Dummy +14)
    /* (ULONG) The initial position to open at.				 */

#define WINDOW_IDCMPHook     (WINDOW_Dummy +15)
    /* (struct Hook *) Defaults to NULL.                     */

#define WINDOW_IDCMPHookBits (WINDOW_Dummy +16)
    /* (ULONG) Defaults to 0L.                               */

#define WINDOW_GadgetUserData	(WINDOW_Dummy +17)
#define WINDOW_InterpretUserData	WINDOW_GadgetUserData
    /* (UWORD) How Gadget.UserData is interpreted.           */
    /* Defaults to WGUD_IGNORE */

#define WINDOW_MenuUserData	(WINDOW_Dummy +25)
    /* (UWORD) How GTMENUITEM_USERDATA is interpreted.		*/

#define WGUD_HOOK 0		/* Gadget/MenuItem UserData points to a Hook */
#define WGUD_FUNC 1		/* Points to a function */
#define WGUD_IGNORE 2	/* App private, don't touch it */

#define WINDOW_IconTitle	 (WINDOW_Dummy +18)
    /* (STRPTR) Title of the iconified window.               */

#define WINDOW_AppMsgHook	 (WINDOW_Dummy +19)
    /* (struct Hook *) Defaults to NULL.                     */

#define WINDOW_Icon			 (WINDOW_Dummy +20)
    /* (struct DiskObject *) Custom icon for the window.     */

#define WINDOW_AppWindow	 (WINDOW_Dummy +21)
    /* (BOOL) Make the window a Workbench AppWindow. */

#define WINDOW_GadgetHelp	 (WINDOW_Dummy +22)
    /* (BOOL) Set gadget-help on/off. */

#define WINDOW_IconifyGadget (WINDOW_Dummy +23)
    /* (BOOL) Add an iconification gadget to window title bar. */

#define WINDOW_TextAttr		 (WINDOW_Dummy +24)
    /* (struct TextAttr *)Default font for window. If not set, use screen font. */

#define WINDOW_BackFillName	 (WINDOW_Dummy +26)
    /* (STRPTR) replaces the default backfill pattern with this file,
     * loaded through datatypes.
     */

#define WINDOW_RefWindow	 (WINDOW_Dummy +41)
    /* (struct Window *) Causes WINDOW_Position to be relative to
     * to this window vs the screen. (V42)
     */

#define WINDOW_InputEvent	 (WINDOW_Dummy +42)
    /* (struct InputEvent *) returns a pointer to an inputevent
     * which will be current *ONLY* after a WHMI_RAWKEY. (V42)
     */

#define WINDOW_HintInfo		 (WINDOW_Dummy +43)
    /* (struct HintInfo *) Static Array of help hints. (V43 BETA)
     */

#define WINDOW_KillWindow		(WINDOW_Dummy +44)
#define WINDOW_Application		(WINDOW_Dummy +45)
    /* ** PRIVATE TAGS SET/GET BY APPLICATION CLASS! ** (V43 BETA)
     */

#define WINDOW_InterpretIDCMPHook	(WINDOW_Dummy +46)
    /* Interpret IDCMPHook results. (V43 BETA)
     */

#define WINDOW_Parent			(WINDOW_Dummy +47)
    /* ** PRIVATE TAGS SET/GET BY APPLICATION CLASS! ** (V43 BETA)
     */

#define WINDOW_PreRefreshHook	(WINDOW_Dummy +48)
    /* (struct Hook *) window.class calls this hook BEFORE RefreshGList() */

#define WINDOW_PostRefreshHook	(WINDOW_Dummy +49)
    /* (struct Hook *) window.class calls this hook AFTER RefreshGList() */

#define WINDOW_AppWindowPtr	(WINDOW_Dummy +50)
    /* (struct AppWindow *) GetAttr()'able pointer to AddAppWindow() result.*/

/*** PRIVATE ***/

#define WINDOW_VertProp		(WINDOW_Dummy +27)
    /* (BOOL) Enable vertical border scroller if true. */

#define WINDOW_VertObject	(WINDOW_Dummy +28)
    /* (Object *) OM_GET the vertical scroller object pointer. */

#define WINDOW_HorizProp	(WINDOW_Dummy +29)
    /* (BOOL) Enable horizontal border scroller if true. */

#define WINDOW_HorizObject	(WINDOW_Dummy +30)
    /* (Object *) OM_GET the horizontal scroller object pointer. */

/****************************************************************************/

/* Pre-defined WM_HANDLEINPUT return codes.
 */
#define WMHI_LASTMSG               (0L)	/* No more messages                 */
#define WMHI_IGNORE               (~0L)	/* Ignore                           */
#define WMHI_GADGETMASK		   (0xffff) /* Gadget ID mask value             */
#define WMHI_MENUMASK		   (0xffff)	/* Menu ID mask value               */
#define WMHI_KEYMASK			   (0xff)   /* Key code mask value              */
#define WMHI_CLASSMASK 	   (0xffff0000)	/* Event class mask value			*/
#define WMHI_CLOSEWINDOW        (1<<16) /* The close gadget was clicked     */
                                        /* or a hook function trigged close */
#define WMHI_GADGETUP			(2<<16)	/* A gadget was released			*/
#define WMHI_INACTIVE           (3<<16) /* The window was de-activated      */
#define WMHI_ACTIVE             (4<<16) /* The window was activated         */
#define WMHI_NEWSIZE			(5<<16) /* The window was resized           */
#define WMHI_MENUPICK			(6<<16)	/* A menu item was picked			*/
#define WMHI_MENUHELP			(7<<16) /* Help was hit in a menu			*/
#define WMHI_GADGETHELP			(8<<16)	/* A gadget returns a help code		*/
#define WMHI_ICONIFY			(9<<16) /* Window requests to be iconified  */
#define WMHI_UNICONIFY		   (10<<16)	/* Window was uniconified           */
#define WMHI_RAWKEY            (11<<16) /* Raw key codes                    */
#define WMHI_VANILLAKEY        (12<<16) /* Vanilla key codes                */
#define WMHI_CHANGEWINDOW	   (13<<16) /* Window moved (or depth arranged) */
#define WMHI_INTUITICK         (14<<16) /* IDCMP intuitick (maximum 10 per second) */
#define WMHI_MOUSEMOVE         (15<<16) /* IDCMP mouse move */
#define WMHI_MOUSEBUTTONS      (16<<16) /* IDCMP mouse buttons */
#define WMHI_DISPOSEDWINDOW	   (17<<16) /* hook function triggered disposal */

/****************************************************************************/

#define WMF_ZOOMED			   (0x0001) /* Window is in zoomed state		*/
#define WMF_ZIPWINDOW		   (0x0002) /* This resize toggled zoom state	*/

/****************************************************************************/

/* Possible WINDOW_FrontBack values
 */
#define WT_FRONT   TRUE
#define WT_BACK    FALSE

/* Possible WINDOW_Position values
 */
#define WPOS_CENTERSCREEN        (1L)   /* Center on the screen             */
#define WPOS_CENTERMOUSE         (2L)   /* Center under the mouse           */
#define WPOS_TOPLEFT             (3L)   /* Top-left of the screen           */
#define WPOS_CENTERWINDOW        (4L)   /* Center in another window         */
#define WPOS_FULLSCREEN          (5L)   /* Top-left of, and fill the screen */

/****************************************************************************/

/*
 * Window Methods
 */
#define WM_HANDLEINPUT	(0x570001L)

/* The WM_HANDLEINPUT method should be called by for each received
 * IDCMP message.
 * If the message could be linked to a gadget in the window, the WORD
 * pointed to by wmh_Code will be set to the gadget's return code.
 */

struct wmHandle
{
    ULONG MethodID;						/* WM_HANDLEINPUT */
    WORD *wmh_Code;						/* The code from the gadget */
};

#define WM_OPEN			(0x570002L)
#define WM_CLOSE		(0x570003L)
#define WM_NEWPREFS		(0x570004L)
#define WM_ICONIFY		(0x570005L)
#define WM_RETHINK		(0x570006L)

#endif /* CLASSES_WINDOW_H */


include/prefs/workbench.h

#ifndef PREFS_WORKBENCH_H
#define PREFS_WORKBENCH_H
/*
**	$VER: workbench.h 44.1 (19.10.1999)
**	Includes Release 44.1
**
**	Workbench preferences file definitions
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef LIBRARIES_IFFPARSE_H
#include <libraries/iffparse.h>
#endif

#ifndef GRAPHICS_GFX_H
#include <graphics/gfx.h>
#endif

/*****************************************************************************/

#define ID_WBNC MAKE_ID('W','B','N','C')

struct WorkbenchPrefs
{
    /* settings from workbench.library */
    ULONG		wbp_DefaultStackSize;	/* in bytes */
    ULONG		wbp_TypeRestartTime;	/* in seconds */
    /* settings from icon.library */
    ULONG		wbp_IconPrecision;	/* PRECISION_#? values */
    struct Rectangle	wbp_EmbossRect;
    BOOL		wbp_Borderless;
    LONG		wbp_MaxNameLength;
    BOOL		wbp_NewIconsSupport;
    BOOL		wbp_ColorIconSupport;
};

#define ID_WBHD MAKE_ID('W','B','H','D')

struct WorkbenchHiddenDevicePrefs
{
    UBYTE		whdp_Name[0];	/* C String including NUL char */
};

/*****************************************************************************/

#endif /* PREFS_WORKBENCH_H */


include/exec/types.h

#ifndef	EXEC_TYPES_H
#define	EXEC_TYPES_H
/*
**	$VER: types.h 40.1 (10.8.1993)
**	Includes Release 44.1
**
**	Data typing.  Must be included before any other Amiga include.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#define INCLUDE_VERSION	44 /* Version of the include files in use. (Do not
                  use this label for OpenLibrary() calls!) */

#define GLOBAL	extern	    /* the declaratory use of an external */
#define IMPORT	extern	    /* reference to an external */
#define STATIC	static	    /* a local static variable */
#define REGISTER register   /* a (hopefully) register variable */

#ifndef VOID
#define VOID void
#endif

#ifndef CONST
#define CONST const
#endif

  /*  WARNING: APTR was redefined for the V36 Includes!  APTR is a   */
 /*  32-Bit Absolute Memory Pointer.  C pointer math will not	    */
/*  operate on APTR --	use "ULONG *" instead.			   */
#ifndef APTR_TYPEDEF
#define APTR_TYPEDEF
typedef void *		APTR;	    /* 32-bit untyped pointer */
#endif
typedef long		LONG;	    /* signed 32-bit quantity */
typedef unsigned long	ULONG;	    /* unsigned 32-bit quantity */
typedef unsigned long	LONGBITS;   /* 32 bits manipulated individually */
typedef short		WORD;	    /* signed 16-bit quantity */
typedef unsigned short	UWORD;	    /* unsigned 16-bit quantity */
typedef unsigned short	WORDBITS;   /* 16 bits manipulated individually */
#if __STDC__
typedef signed char	BYTE;	    /* signed 8-bit quantity */
#else
typedef char		BYTE;	    /* signed 8-bit quantity */
#endif
typedef unsigned char	UBYTE;	    /* unsigned 8-bit quantity */
typedef unsigned char	BYTEBITS;   /* 8 bits manipulated individually */
typedef unsigned short	RPTR;	    /* signed relative pointer */

#ifdef __cplusplus
typedef char *		STRPTR;     /* string pointer (NULL terminated) */
#else
typedef unsigned char *	STRPTR;     /* string pointer (NULL terminated) */
#endif

typedef CONST char *	CONST_STRPTR; /* constant string pointer (NULL terminated) */

/* For compatibility only: (don't use in new code) */
typedef short		SHORT;	    /* signed 16-bit quantity (use WORD) */
typedef unsigned short	USHORT;     /* unsigned 16-bit quantity (use UWORD) */
typedef short		COUNT;
typedef unsigned short	UCOUNT;
typedef ULONG		CPTR;

/* Types with specific semantics */
typedef float		FLOAT;
typedef double		DOUBLE;
typedef short		BOOL;
typedef unsigned char	TEXT;

#ifndef TRUE
#define TRUE		1
#endif
#ifndef FALSE
#define FALSE		0
#endif
#ifndef NULL
#define NULL		0L
#endif

#define BYTEMASK	0xFF

 /* #define LIBRARY_VERSION is now obsolete.  Please use LIBRARY_MINIMUM */
/* or code the specific minimum library version you require.		*/
#define LIBRARY_MINIMUM	33 /* Lowest version supported */

/* Some structure definitions include prototypes for function pointers.
 * This may not work with `C' compilers that do not comply to the ANSI
 * standard, which we will have to work around.
 */
#if __STDC__
#define __CLIB_PROTOTYPE(a) a
#else
#define __CLIB_PROTOTYPE(a)
#endif /* __STDC__ */

#endif	/* EXEC_TYPES_H */


include/diskfont/diskfonttag.h

#ifndef  DISKFONT_DISKFONTTAG_H
#define  DISKFONT_DISKFONTTAG_H
/*
**	$VER: diskfonttag.h 10.4 (14.7.1992)
**	Includes Release 44.1
**
**	diskfonttag.h -- tag definitions for .otag files
**
**	(C) Copyright 1990-1992 Robert R. Burns
**	    All Rights Reserved
*/
#ifndef	EXEC_TYPES_H
#include	<exec/types.h>
#endif

#ifndef	UTILITY_TAGITEM_H
#include	<utility/tagitem.h>
#endif

/* Level 0 entries never appear in the .otag tag list, but appear in font
 * specifications */
#define  OT_Level0	TAG_USER
/* Level 1 entries are required to exist in the .otag tag list */
#define  OT_Level1	(TAG_USER | 0x1000)
/* Level 2 entries are optional typeface metric tags */
#define  OT_Level2	(TAG_USER | 0x2000)
/* Level 3 entries are required for some OT_Engines */
#define  OT_Level3	(TAG_USER | 0x3000)
/* Indirect entries are at (tag address + data offset) */
#define  OT_Indirect	0x8000

/********************************************************************/
/* font specification and inquiry tags */

/* !  tags flagged with an exclaimation mark are valid for
 *    specification.
 *  ? tags flagged with a question mark are valid for inquiry
 *
 * fixed binary numbers are encoded as 16 bits of integer and
 * 16 bits of fraction.  Negative values are indicated by twos
 * complement of all 32 bits.
 */

/* !  OT_DeviceDPI specifies the target device dots per inch -- X DPI is
 *    in the high word, Y DPI in the low word. */
#define  OT_DeviceDPI	(OT_Level0 | 0x01)	/* == TA_DeviceDPI */

/* !  OT_DotSize specifies the target device dot size as a percent of
 *    it's resolution-implied size -- X percent in high word, Y percent
 *    in low word. */
#define  OT_DotSize	(OT_Level0 | 0x02)

/* !  OT_PointHeight specifies the requested point height of a typeface,
 *    specifically, the height and nominal width of the em-square.
 *    The point referred to here is 1/72".  It is encoded as a fixed
 *    binary number. */
#define  OT_PointHeight	(OT_Level0 | 0x08)

/* !  OT_SetFactor specifies the requested set width of a typeface.
 *    It distorts the width of the em-square from that specified by
 *    OT_PointHeight.  To compensate for a device with different
 *    horizontal and vertical resolutions, OT_DeviceDPI should be used
 *    instead.	For a normal aspect ratio, set to 1.0 (encoded as
 *    0x00010000).  This is the default value. */
#define  OT_SetFactor	(OT_Level0 | 0x09)

/* !  OT_Shear... specifies the Sine and Cosine of the vertical stroke
 *    angle, as two fixed point binary fractions.  Both must be specified:
 *    first the Sine and then the Cosine.  Setting the sine component
 *    changes the Shear to an undefined value, setting the cosine
 *    component completes the Shear change to the new composite value.
 *    For no shear, set to 0.0, 1.0 (encoded as 0x00000000, 0x00010000).
 *    This is the default value. */
#define  OT_ShearSin	(OT_Level0 | 0x0a)
#define  OT_ShearCos	(OT_Level0 | 0x0b)

/* !  OT_Rotate... specifies the Sine and Cosine of the baselin rotation
 *    angle, as two fixed point binary fractions.  Both must be specified:
 *    first the Sine and then the Cosine.  Setting the sine component
 *    changes the Shear to an undefined value, setting the cosine
 *    component completes the Shear change to the new composite value.
 *    For no shear, set to 0.0, 1.0 (encoded as 0x00000000, 0x00010000).
 *    This is the default value. */
#define  OT_RotateSin	(OT_Level0 | 0x0c)
#define  OT_RotateCos	(OT_Level0 | 0x0d)

/* !  OT_Embolden... specifies values to algorithimically embolden -- or,
 *    when negative, lighten -- the glyph.  It is encoded as a fixed point
 *    binary fraction of the em-square.  The X and Y components can be
 *    changed indendently.  For normal characters, set to 0.0, 0.0
 *    (encoded as 0x00000000, 0x00000000).  This is the default value. */
#define  OT_EmboldenX	(OT_Level0 | 0x0e)
#define  OT_EmboldenY	(OT_Level0 | 0x0f)

/* !  OT_PointSize is an old method of specifying the point size,
 *    encoded as (points * 16). */
#define  OT_PointSize	(OT_Level0 | 0x10)

/* !  OT_GlyphCode specifies the glyph (character) code to use with
 *    subsequent operations.  For example, this is the code for an
 *    OT_Glyph inquiry */
#define  OT_GlyphCode	(OT_Level0 | 0x11)

/* !  OT_GlyphCode2 specifies the second glyph code.  For example,
 *    this is the right glyph of the two glyphs of an OT_KernPair
 *    inquiry */
#define  OT_GlyphCode2	(OT_Level0 | 0x12)

/* !  OT_GlyphWidth specifies a specific width for a glyph.
 *    It sets a specific escapement (advance) width for subsequent
 *    glyphs.  It is encoded as a fixed binary fraction of the em-square.
 *    To revert to using the font-defined escapement for each glyph, set
 *    to 0.0 (encoded as 0x00000000).  This is the default value. */
#define  OT_GlyphWidth	(OT_Level0 | 0x13)

/* !  OT_OTagPath and
 * !  OT_OTagList specify the selected typeface.  Both must be specified:
 *    first the Path and then the List.  Setting the path name changes
 *    changes the typeface to an undefined value, providing the List
 *    completes the typeface selection to the new typeface.  OTagPath
 *    is the null terminated full file path of the .otag file associated
 *    with the typeface.  OTagList is a memory copy of the processed
 *    contents of that .otag file (i.e. with indirections resolved).
 *    There are no default values for the typeface. */
#define  OT_OTagPath	(OT_Level0 | OT_Indirect | 0x14)
#define  OT_OTagList	(OT_Level0 | OT_Indirect | 0x15)

/*  ? OT_GlyphMap supplies a read-only struct GlyphMap pointer that
 *    describes a bitmap for a glyph with the current attributes. */
#define  OT_GlyphMap	(OT_Level0 | OT_Indirect | 0x20)

/*  ? OT_WidthList supplies a read-only struct MinList of struct
 *    GlyphWidthEntry nodes for glyphs that are defined from GlyphCode
 *    to GlyphCode2, inclusive.  The widths are represented as fixed
 *    binary fractions of the em-square, ignoring any effect of
 *    SetFactor or GlyphWidth.	A width would need to be converted to
 *    a distance along the baseline in device units by the
 *    application. */
#define  OT_WidthList	(OT_Level0 | OT_Indirect | 0x21)

/*  ? OT_...KernPair supplies the kern adjustment to be added to the
 *    current position after placement of the GlyphCode glyph and
 *    before placement of the GlyphCode2 glyph.  Text kern pairs are
 *    for rendering body text.	Display kern pairs are generally
 *    tighter values for display (e.g. headline) purposes.  The
 *    adjustment is represented as a fixed binary fraction of the
 *    em-square, ignoring any effect of SetFactor.  This number would
 *    need to be converted to a distance along the baseline in device
 *    units by the application. */
#define  OT_TextKernPair (OT_Level0 | OT_Indirect | 0x22)
#define  OT_DesignKernPair (OT_Level0 | OT_Indirect | 0x23)

/*  ? OT_Underlined is an unsigned word which is used to request
 *    algorithimic underlining for the engine when rendering the glyph.
 *    Bullet.library currently does not support this tag, though it
 *    may be used by other engines in the future.  The default for
 *    any engine which supports this tag must be OTUL_None.  Engines which
 *    do not support this tag should return an appropriate OTERR value.
 *
 *    As of V39, diskfont.library will request underlining if specified
 *    in the TextAttr, or TTextAttr passed to OpenDiskFont().  Diskfont
 *    will first request Broken underlining (like the Text() function
 *    does when SetSoftStyle() is used), and then Solid underlining if
 *    the engine returns an error.  If the engine returns an error for
 *    both, then diskfont.library attempts to find, or create the best
 *    non-underlined font that it can. */
#define  OT_UnderLined		(OT_Level0 | 0x24)

#define  OTUL_None		0
#define  OTUL_Solid		1
#define  OTUL_Broken		2
#define  OTUL_DoubleSolid	3
#define  OUTL_DoubleBroken	4

/*  ? OT_StrikeThrough is a boolean which is used to request
 *    algorithimic strike through when rendering the glyph.
 *    Bullet.library currently does not support this tag, though it
 *    may be used by other engines in the future.  The default for
 *    any engined which supports this tag must be FALSE.  Engines which
 *    do not support this tag should return an appropriate OTERR value. */
#define  OT_StrikeThrough	(OT_Level0 | 0x25)

/********************************************************************/
/* .otag tags */

/* suffix for files in FONTS: that contain these tags */
#define  OTSUFFIX	".otag"

/* OT_FileIdent both identifies this file and verifies its size.
 * It is required to be the first tag in the file. */
#define  OT_FileIdent	(OT_Level1 | 0x01)

/* OT_Engine specifies the font engine this file is designed to use */
#define  OT_Engine	(OT_Level1 | OT_Indirect | 0x02)
#define  OTE_Bullet	"bullet"

/* OT_Family is the family name of this typeface */
#define  OT_Family	(OT_Level1 | OT_Indirect | 0x03)

/* The name of this typeface is implicit in the name of the .otag file */
/* OT_BName is used to find the bold variant of this typeface */
#define  OT_BName	(OT_Level2 | OT_Indirect | 0x05)
/* OT_IName is used to find the italic variant of this typeface */
#define  OT_IName	(OT_Level2 | OT_Indirect | 0x06)
/* OT_BIName is used to find the bold italic variant of this typeface */
#define  OT_BIName	(OT_Level2 | OT_Indirect | 0x07)

/* OT_SymSet is used to select the symbol set that has the OT_YSizeFactor
 * described here.  Other symbol sets might have different extremes */
#define  OT_SymbolSet	(OT_Level1 | 0x10)

/* OT_YSizeFactor is a ratio to assist in calculating the Point height
 * to BlackHeight relationship -- high word: Point height term, low
 * word: Black height term -- pointSize = ysize*<high>/<low> */
#define  OT_YSizeFactor	(OT_Level1 | 0x11)

/* OT_SpaceWidth specifies the width of the space character relative
 * to the character height */
#define  OT_SpaceWidth	(OT_Level2 | 0x12)

/* OT_IsFixed is a boolean indicating that all the characters in the
 * typeface are intended to have the same character advance */
#define  OT_IsFixed	(OT_Level2 | 0x13)

/* OT_SerifFlag is a boolean indicating if the character has serifs */
#define  OT_SerifFlag	(OT_Level1 | 0x14)

/* OT_StemWeight is an unsigned byte indicating the weight of the character */
#define  OT_StemWeight	(OT_Level1 | 0x15)

#define  OTS_UltraThin	  8	/*   0- 15 */
#define  OTS_ExtraThin	 24	/*  16- 31 */
#define  OTS_Thin	 40	/*  32- 47 */
#define  OTS_ExtraLight	 56	/*  48- 63 */
#define  OTS_Light	 72	/*  64- 79 */
#define  OTS_DemiLight	 88	/*  80- 95 */
#define  OTS_SemiLight	104	/*  96-111 */
#define  OTS_Book	120	/* 112-127 */
#define  OTS_Medium	136	/* 128-143 */
#define  OTS_SemiBold	152	/* 144-159 */
#define  OTS_DemiBold	168	/* 160-175 */
#define  OTS_Bold	184	/* 176-191 */
#define  OTS_ExtraBold	200	/* 192-207 */
#define  OTS_Black	216	/* 208-223 */
#define  OTS_ExtraBlack	232	/* 224-239 */
#define  OTS_UltraBlack	248	/* 240-255 */

/* OT_SlantStyle is an unsigned byte indicating the font posture */
#define  OT_SlantStyle	(OT_Level1 | 0x16)
#define  OTS_Upright	0
#define  OTS_Italic	1	/* Oblique, Slanted, etc. */
#define  OTS_LeftItalic	2	/* Reverse Slant */

/* OT_HorizStyle is an unsigned byte indicating the appearance width */
#define  OT_HorizStyle	(OT_Level1 | 0x17)
#define  OTH_UltraCompressed	 16	/*   0- 31 */
#define  OTH_ExtraCompressed	 48	/*  32- 63 */
#define  OTH_Compressed		 80	/*  64- 95 */
#define  OTH_Condensed		112	/*  96-127 */
#define  OTH_Normal		144	/* 128-159 */
#define  OTH_SemiExpanded	176	/* 160-191 */
#define  OTH_Expanded		208	/* 192-223 */
#define  OTH_ExtraExpanded	240	/* 224-255 */

/* OT_SpaceFactor specifies the width of the space character relative
 * to the character height */
#define  OT_SpaceFactor	(OT_Level2 | 0x18)

/* OT_InhibitAlgoStyle indicates which ta_Style bits, if any, should
 * be ignored even if the font does not already have that quality.
 * For example, if FSF_BOLD is set and the typeface is not bold but
 * the user specifies bold, the application or diskfont library is
 * not to use OT_Embolden to achieve a bold result. */
#define  OT_InhibitAlgoStyle (OT_Level2 | 0x19)

/* OT_AvailSizes is an indirect pointer to sorted UWORDs, 0th is count */
#define  OT_AvailSizes	(OT_Level1 | OT_Indirect | 0x20)
#define  OT_MAXAVAILSIZES	20	/* no more than 20 sizes allowed */

/* OT_SpecCount is the count number of parameters specified here */
#define  OT_SpecCount	(OT_Level1 | 0x100)

/* Specs can be created as appropriate for the engine by ORing in the
 * parameter number (1 is first, 2 is second, ... up to 15th) */
#define  OT_Spec	(OT_Level1 | 0x100)
/* OT_Spec1 is the (first) parameter to the font engine to select
 * this particular typeface */
#define  OT_Spec1	(OT_Level1 | 0x101)

#endif	 /* DISKFONT_DISKFONTTAG_H */


include/diskfont/oterrors.h

#ifndef  DISKFONT_OTERRORS_H
#define  DISKFONT_OTERRORS_H
/*
**	$VER: oterrors.h 8.1 (19.6.1992)
**	Includes Release 44.1
**
**	oterrors.h -- error results from outline libraries
**
**	(C) Copyright 1991-1992 Robert R. Burns
**	    All Rights Reserved
*/

/* PRELIMINARY */
#define  OTERR_Failure		-1	/* catch-all for error */
#define  OTERR_Success		0	/* no error */
#define  OTERR_BadTag		1	/* inappropriate tag for function */
#define  OTERR_UnknownTag	2	/* unknown tag for function */
#define  OTERR_BadData		3	/* catch-all for bad tag data */
#define  OTERR_NoMemory		4	/* insufficient memory for operation */
#define  OTERR_NoFace		5	/* no typeface currently specified */
#define  OTERR_BadFace		6	/* typeface specification problem */
#define  OTERR_NoGlyph		7	/* no glyph specified */
#define  OTERR_BadGlyph		8	/* bad glyph code or glyph range */
#define  OTERR_NoShear		9	/* shear only partially specified */
#define  OTERR_NoRotate		10	/* rotate only partially specified */
#define  OTERR_TooSmall		11	/* typeface metrics yield tiny glyphs */
#define  OTERR_UnknownGlyph	12	/* glyph not known by engine */

#endif	 /* DISKFONT_OTERRORS_H */


include/devices/console.h

#ifndef DEVICES_CONSOLE_H
#define DEVICES_CONSOLE_H
/*
**	$VER: console.h 36.11 (7.11.1990)
**	Includes Release 44.1
**
**	Console device command definitions
**
**	(C) Copyright 1986-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include	<exec/types.h>
#endif

#ifndef EXEC_IO_H
#include	<exec/io.h>
#endif	/* EXEC_IO_H */

/****** Console commands ******/
#define CD_ASKKEYMAP		(CMD_NONSTD+0)
#define CD_SETKEYMAP		(CMD_NONSTD+1)
#define CD_ASKDEFAULTKEYMAP	(CMD_NONSTD+2)
#define CD_SETDEFAULTKEYMAP	(CMD_NONSTD+3)

/****** SGR parameters ******/

#define SGR_PRIMARY	0
#define SGR_BOLD	1
#define SGR_ITALIC	3
#define SGR_UNDERSCORE	4
#define SGR_NEGATIVE	7

#define	SGR_NORMAL	22	/* default foreground color, not bold */
#define	SGR_NOTITALIC	23
#define	SGR_NOTUNDERSCORE 24
#define	SGR_POSITIVE	27

/* these names refer to the ANSI standard, not the implementation */
#define SGR_BLACK	30
#define SGR_RED		31
#define SGR_GREEN	32
#define SGR_YELLOW	33
#define SGR_BLUE	34
#define SGR_MAGENTA	35
#define SGR_CYAN	36
#define SGR_WHITE	37
#define SGR_DEFAULT	39

#define SGR_BLACKBG	40
#define SGR_REDBG	41
#define SGR_GREENBG	42
#define SGR_YELLOWBG	43
#define SGR_BLUEBG	44
#define SGR_MAGENTABG	45
#define SGR_CYANBG	46
#define SGR_WHITEBG	47
#define SGR_DEFAULTBG	49

/* these names refer to the implementation, they are the preferred */
/* names for use with the Amiga console device. */
#define SGR_CLR0	30
#define SGR_CLR1	31
#define SGR_CLR2	32
#define SGR_CLR3	33
#define SGR_CLR4	34
#define SGR_CLR5	35
#define SGR_CLR6	36
#define SGR_CLR7	37

#define SGR_CLR0BG	40
#define SGR_CLR1BG	41
#define SGR_CLR2BG	42
#define SGR_CLR3BG	43
#define SGR_CLR4BG	44
#define SGR_CLR5BG	45
#define SGR_CLR6BG	46
#define SGR_CLR7BG	47

/****** DSR parameters ******/

#define DSR_CPR		6

/****** CTC parameters ******/
#define CTC_HSETTAB	0
#define CTC_HCLRTAB	2
#define CTC_HCLRTABSALL	5

/******	TBC parameters ******/
#define TBC_HCLRTAB	0
#define TBC_HCLRTABSALL	3

/******	SM and RM parameters ******/
#define M_LNM	20	/* linefeed newline mode */
#define M_ASM	">1"	/* auto scroll mode */
#define M_AWM	"?7"	/* auto wrap mode */

#endif	/* DEVICES_CONSOLE_H */


include/dos/dostags.h

#ifndef DOS_DOSTAGS_H
#define DOS_DOSTAGS_H
/*
**
**	$VER: dostags.h 36.11 (29.4.1991)
**	Includes Release 44.1
**
**	Tag definitions for all Dos routines using tags
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**
*/

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

/*****************************************************************************/
/* definitions for the System() call */

#define SYS_Dummy	(TAG_USER + 32)
#define	SYS_Input	(SYS_Dummy + 1)
                /* specifies the input filehandle  */
#define	SYS_Output	(SYS_Dummy + 2)
                /* specifies the output filehandle */
#define	SYS_Asynch	(SYS_Dummy + 3)
                /* run asynch, close input/output on exit(!) */
#define	SYS_UserShell	(SYS_Dummy + 4)
                /* send to user shell instead of boot shell */
#define	SYS_CustomShell	(SYS_Dummy + 5)
                /* send to a specific shell (data is name) */
/*	SYS_Error, */

/*****************************************************************************/
/* definitions for the CreateNewProc() call */
/* you MUST specify one of NP_Seglist or NP_Entry.  All else is optional. */

#define	NP_Dummy (TAG_USER + 1000)
#define	NP_Seglist	(NP_Dummy + 1)
                /* seglist of code to run for the process  */
#define	NP_FreeSeglist	(NP_Dummy + 2)
                /* free seglist on exit - only valid for   */
                /* for NP_Seglist.  Default is TRUE.	   */
#define	NP_Entry	(NP_Dummy + 3)
                /* entry point to run - mutually exclusive */
                /* with NP_Seglist! */
#define	NP_Input	(NP_Dummy + 4)
                /* filehandle - default is Open("NIL:"...) */
#define	NP_Output	(NP_Dummy + 5)
                /* filehandle - default is Open("NIL:"...) */
#define	NP_CloseInput	(NP_Dummy + 6)
                /* close input filehandle on exit	   */
                /* default TRUE				   */
#define	NP_CloseOutput	(NP_Dummy + 7)
                /* close output filehandle on exit	   */
                /* default TRUE				   */
#define	NP_Error	(NP_Dummy + 8)
                /* filehandle - default is Open("NIL:"...) */
#define	NP_CloseError	(NP_Dummy + 9)
                /* close error filehandle on exit	   */
                /* default TRUE				   */
#define	NP_CurrentDir	(NP_Dummy + 10)
                /* lock - default is parent's current dir  */
#define	NP_StackSize	(NP_Dummy + 11)
                /* stacksize for process - default 4000    */
#define	NP_Name		(NP_Dummy + 12)
                /* name for process - default "New Process"*/
#define	NP_Priority	(NP_Dummy + 13)
                /* priority - default same as parent	   */
#define	NP_ConsoleTask	(NP_Dummy + 14)
                /* consoletask - default same as parent    */
#define	NP_WindowPtr	(NP_Dummy + 15)
                /* window ptr - default is same as parent  */
#define	NP_HomeDir	(NP_Dummy + 16)
                /* home directory - default curr home dir  */
#define	NP_CopyVars	(NP_Dummy + 17)
                /* boolean to copy local vars-default TRUE */
#define	NP_Cli		(NP_Dummy + 18)
                /* create cli structure - default FALSE    */
#define	NP_Path		(NP_Dummy + 19)
                /* path - default is copy of parents path  */
                /* only valid if a cli process!	   */
#define	NP_CommandName	(NP_Dummy + 20)
                /* commandname - valid only for CLI	   */
#define	NP_Arguments	(NP_Dummy + 21)
/* cstring of arguments - passed with str in a0, length in d0.	*/
/* (copied and freed on exit.)	Default is 0-length NULL ptr.	*/
/* NOTE: not operational until V37 - see BIX/TechNotes for	*/
/* more info/workaround.  In V36, the registers were random.	*/
/* You must NEVER use NP_Arguments with a NP_Input of NULL.	*/

/* FIX! should this be only for cli's? */
#define	NP_NotifyOnDeath (NP_Dummy + 22)
                /* notify parent on death - default FALSE  */
                /* Not functional yet. */
#define	NP_Synchronous	(NP_Dummy + 23)
                /* don't return until process finishes -   */
                /* default FALSE.			   */
                /* Not functional yet. */
#define	NP_ExitCode	(NP_Dummy + 24)
                /* code to be called on process exit	   */
#define	NP_ExitData	(NP_Dummy + 25)
                /* optional argument for NP_EndCode rtn -  */
                /* default NULL				   */

/*****************************************************************************/
/* tags for AllocDosObject */

#define ADO_Dummy	(TAG_USER + 2000)
#define	ADO_FH_Mode	(ADO_Dummy + 1)
                /* for type DOS_FILEHANDLE only		   */
                /* sets up FH for mode specified.
                   This can make a big difference for buffered
                   files.				   */
    /* The following are for DOS_CLI */
    /* If you do not specify these, dos will use it's preferred values */
    /* which may change from release to release.  The BPTRs to these   */
    /* will be set up correctly for you.  Everything will be zero,	   */
    /* except cli_FailLevel (10) and cli_Background (DOSTRUE).	   */
    /* NOTE: you may also use these 4 tags with CreateNewProc.	   */

#define	ADO_DirLen	(ADO_Dummy + 2)
                /* size in bytes for current dir buffer    */
#define	ADO_CommNameLen	(ADO_Dummy + 3)
                /* size in bytes for command name buffer   */
#define	ADO_CommFileLen	(ADO_Dummy + 4)
                /* size in bytes for command file buffer   */
#define	ADO_PromptLen	(ADO_Dummy + 5)
                /* size in bytes for the prompt buffer	   */

/*****************************************************************************/
/* tags for NewLoadSeg */
/* no tags are defined yet for NewLoadSeg */

#endif /* DOS_DOSTAGS_H */


include/libraries/dos.h

#ifndef LIBRARIES_DOS_H
#define LIBRARIES_DOS_H
/*
**	$VER: dos.h 36.2 (12.7.1990)
**	Includes Release 44.1
**
**	Standard C header for AmigaDOS
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef DOS_DOS_H
#include <dos/dos.h>
#endif

#endif /* LIBRARIES_DOS_H */


include/dos/stdio.h

#ifndef DOS_STDIO_H
#define DOS_STDIO_H
/*
**
**	$VER: stdio.h 36.6 (1.11.1991)
**	Includes Release 44.1
**
**	ANSI-like stdio defines for dos buffered I/O
**
**	(C) Copyright 1989-1999 Amiga, Inc.
**	    All Rights Reserved
**
*/

#define ReadChar()		FGetC(Input())
#define WriteChar(c)		FPutC(Output(),(c))
#define UnReadChar(c)		UnGetC(Input(),(c))
/* next one is inefficient */
#define ReadChars(buf,num)	FRead(Input(),(buf),1,(num))
#define ReadLn(buf,len)		FGets(Input(),(buf),(len))
#define WriteStr(s)		FPuts(Output(),(s))
#define VWritef(format,argv)	VFWritef(Output(),(format),(argv))

/* types for SetVBuf */
#define BUF_LINE	0	/* flush on \n, etc */
#define BUF_FULL	1	/* never flush except when needed */
#define BUF_NONE	2	/* no buffering */

/* EOF return value */
#define ENDSTREAMCH	-1

#endif	/* DOS_STDIO_H */


include/exec/alerts.h

#ifndef EXEC_ALERTS_H
#define EXEC_ALERTS_H
/*
**	$VER: alerts.h 39.3 (12.5.1992)
**	Includes Release 44.1
**
**	Alert numbers, as displayed by system crashes.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

/*********************************************************************
*
*  Format of the alert error number:
*
*    +-+-------------+----------------+--------------------------------+
*    |D|  SubSysId   |	General Error |    SubSystem Specific Error    |
*    +-+-------------+----------------+--------------------------------+
*     1    7 bits	   8 bits		   16 bits
*
*		     D:  DeadEnd alert
*	      SubSysId:  indicates ROM subsystem number.
*	 General Error:  roughly indicates what the error was
*	Specific Error:  indicates more detail
**********************************************************************/

/**********************************************************************
*
*  Hardware/CPU specific alerts:  They may show without the 8 at the
*  front of the number.  These are CPU/68000 specific.	See 680x0
*  programmer's manuals for more details.
*
**********************************************************************/
#define	ACPU_BusErr	0x80000002	/* Hardware bus fault/access error */
#define	ACPU_AddressErr	0x80000003	/* Illegal address access (ie: odd) */
#define	ACPU_InstErr	0x80000004	/* Illegal instruction */
#define	ACPU_DivZero	0x80000005	/* Divide by zero */
#define	ACPU_CHK	0x80000006	/* Check instruction error */
#define	ACPU_TRAPV	0x80000007	/* TrapV instruction error */
#define	ACPU_PrivErr	0x80000008	/* Privilege violation error */
#define	ACPU_Trace	0x80000009	/* Trace error */
#define	ACPU_LineA	0x8000000A	/* Line 1010 Emulator error */
#define	ACPU_LineF	0x8000000B	/* Line 1111 Emulator error */
#define	ACPU_Format	0x8000000E	/* Stack frame format error */
#define	ACPU_Spurious	0x80000018	/* Spurious interrupt error */
#define	ACPU_AutoVec1	0x80000019	/* AutoVector Level 1 interrupt error */
#define	ACPU_AutoVec2	0x8000001A	/* AutoVector Level 2 interrupt error */
#define	ACPU_AutoVec3	0x8000001B	/* AutoVector Level 3 interrupt error */
#define	ACPU_AutoVec4	0x8000001C	/* AutoVector Level 4 interrupt error */
#define	ACPU_AutoVec5	0x8000001D	/* AutoVector Level 5 interrupt error */
#define	ACPU_AutoVec6	0x8000001E	/* AutoVector Level 6 interrupt error */
#define	ACPU_AutoVec7	0x8000001F	/* AutoVector Level 7 interrupt error */

/*********************************************************************
*
*  General Alerts
*
*  For example: timer.device cannot open math.library would be 0x05038015
*
*	Alert(AN_TimerDev|AG_OpenLib|AO_MathLib);
*
*********************************************************************/

/*------ alert types */
#define AT_DeadEnd	0x80000000
#define AT_Recovery	0x00000000

/*------ general purpose alert codes */
#define AG_NoMemory	0x00010000
#define AG_MakeLib	0x00020000
#define AG_OpenLib	0x00030000
#define AG_OpenDev	0x00040000
#define AG_OpenRes	0x00050000
#define AG_IOError	0x00060000
#define AG_NoSignal	0x00070000
#define AG_BadParm	0x00080000
#define AG_CloseLib	0x00090000	/* usually too many closes */
#define AG_CloseDev	0x000A0000	/* or a mismatched close */
#define AG_ProcCreate	0x000B0000	/* Process creation failed */

/*------ alert objects: */
#define AO_ExecLib	0x00008001
#define AO_GraphicsLib	0x00008002
#define AO_LayersLib	0x00008003
#define AO_Intuition	0x00008004
#define AO_MathLib	0x00008005
#define AO_DOSLib	0x00008007
#define AO_RAMLib	0x00008008
#define AO_IconLib	0x00008009
#define AO_ExpansionLib 0x0000800A
#define AO_DiskfontLib	0x0000800B
#define AO_UtilityLib	0x0000800C
#define	AO_KeyMapLib	0x0000800D

#define AO_AudioDev	0x00008010
#define AO_ConsoleDev	0x00008011
#define AO_GamePortDev	0x00008012
#define AO_KeyboardDev	0x00008013
#define AO_TrackDiskDev 0x00008014
#define AO_TimerDev	0x00008015

#define AO_CIARsrc	0x00008020
#define AO_DiskRsrc	0x00008021
#define AO_MiscRsrc	0x00008022

#define AO_BootStrap	0x00008030
#define AO_Workbench	0x00008031
#define AO_DiskCopy	0x00008032
#define AO_GadTools	0x00008033
#define AO_Unknown	0x00008035

/*********************************************************************
*
*   Specific Alerts:
*
*   For example:   exec.library -- corrupted memory list
*
*	    ALERT  AN_MemCorrupt	;8100 0005
*
*********************************************************************/

/*------ exec.library */
#define AN_ExecLib	0x01000000
#define AN_ExcptVect	0x01000001 /* 68000 exception vector checksum (obs.) */
#define AN_BaseChkSum	0x01000002 /* Execbase checksum (obs.) */
#define AN_LibChkSum	0x01000003 /* Library checksum failure */

#define AN_MemCorrupt	0x81000005 /* Corrupt memory list detected in FreeMem */
#define AN_IntrMem	0x81000006 /* No memory for interrupt servers */
#define AN_InitAPtr	0x01000007 /* InitStruct() of an APTR source (obs.) */
#define AN_SemCorrupt	0x01000008 /* A semaphore is in an illegal state
                      at ReleaseSemaphore() */
#define AN_FreeTwice	0x01000009 /* Freeing memory already freed */
#define AN_BogusExcpt	0x8100000A /* illegal 68k exception taken (obs.) */
#define AN_IOUsedTwice	0x0100000B /* Attempt to reuse active IORequest */
#define AN_MemoryInsane 0x0100000C /* Sanity check on memory list failed
                      during AvailMem(MEMF_LARGEST) */
#define AN_IOAfterClose 0x0100000D /* IO attempted on closed IORequest */
#define AN_StackProbe	0x0100000E /* Stack appears to extend out of range */
#define AN_BadFreeAddr	0x0100000F /* Memory header not located. [ Usually an
                      invalid address passed to FreeMem() ] */
#define	AN_BadSemaphore	0x01000010 /* An attempt was made to use the old
                      message semaphores. */

/*------ graphics.library */
#define AN_GraphicsLib	0x02000000
#define AN_GfxNoMem	0x82010000	/* graphics out of memory */
#define AN_GfxNoMemMspc 0x82010001	/* MonitorSpec alloc, no memory */
#define AN_LongFrame	0x82010006	/* long frame, no memory */
#define AN_ShortFrame	0x82010007	/* short frame, no memory */
#define AN_TextTmpRas	0x02010009	/* text, no memory for TmpRas */
#define AN_BltBitMap	0x8201000A	/* BltBitMap, no memory */
#define AN_RegionMemory 0x8201000B	/* regions, memory not available */
#define AN_MakeVPort	0x82010030	/* MakeVPort, no memory */
#define AN_GfxNewError	0x0200000C
#define AN_GfxFreeError 0x0200000D

#define AN_GfxNoLCM	0x82011234	/* emergency memory not available */

#define AN_ObsoleteFont 0x02000401	/* unsupported font description used */

/*------ layers.library */
#define AN_LayersLib	0x03000000
#define AN_LayersNoMem	0x83010000	/* layers out of memory */

/*------ intuition.library */
#define AN_Intuition	0x04000000
#define AN_GadgetType	0x84000001	/* unknown gadget type */
#define AN_BadGadget	0x04000001	/* Recovery form of AN_GadgetType */
#define AN_CreatePort	0x84010002	/* create port, no memory */
#define AN_ItemAlloc	0x04010003	/* item plane alloc, no memory */
#define AN_SubAlloc	0x04010004	/* sub alloc, no memory */
#define AN_PlaneAlloc	0x84010005	/* plane alloc, no memory */
#define AN_ItemBoxTop	0x84000006	/* item box top < RelZero */
#define AN_OpenScreen	0x84010007	/* open screen, no memory */
#define AN_OpenScrnRast 0x84010008	/* open screen, raster alloc, no memory */
#define AN_SysScrnType	0x84000009	/* open sys screen, unknown type */
#define AN_AddSWGadget	0x8401000A	/* add SW gadgets, no memory */
#define AN_OpenWindow	0x8401000B	/* open window, no memory */
#define AN_BadState	0x8400000C	/* Bad State Return entering Intuition */
#define AN_BadMessage	0x8400000D	/* Bad Message received by IDCMP */
#define AN_WeirdEcho	0x8400000E	/* Weird echo causing incomprehension */
#define AN_NoConsole	0x8400000F	/* couldn't open the Console Device */
#define	AN_NoISem	0x04000010	/* Intuition skipped obtaining a sem */
#define	AN_ISemOrder	0x04000011	/* Intuition obtained a sem in bad order */

/*------ math.library */
#define AN_MathLib	0x05000000

/*------ dos.library */
#define AN_DOSLib	0x07000000
#define AN_StartMem	0x07010001 /* no memory at startup */
#define AN_EndTask	0x07000002 /* EndTask didn't */
#define AN_QPktFail	0x07000003 /* Qpkt failure */
#define AN_AsyncPkt	0x07000004 /* Unexpected packet received */
#define AN_FreeVec	0x07000005 /* Freevec failed */
#define AN_DiskBlkSeq	0x07000006 /* Disk block sequence error */
#define AN_BitMap	0x07000007 /* Bitmap corrupt */
#define AN_KeyFree	0x07000008 /* Key already free */
#define AN_BadChkSum	0x07000009 /* Invalid checksum */
#define AN_DiskError	0x0700000A /* Disk Error */
#define AN_KeyRange	0x0700000B /* Key out of range */
#define AN_BadOverlay	0x0700000C /* Bad overlay */
#define AN_BadInitFunc	0x0700000D /* Invalid init packet for cli/shell */
#define AN_FileReclosed 0x0700000E /* A filehandle was closed more than once */

/*------ ramlib.library */
#define AN_RAMLib	0x08000000
#define AN_BadSegList	0x08000001	/* no overlays in library seglists */

/*------ icon.library */
#define AN_IconLib	0x09000000

/*------ expansion.library */
#define AN_ExpansionLib 0x0A000000
#define AN_BadExpansionFree	0x0A000001 /* freeed free region */

/*------ diskfont.library */
#define AN_DiskfontLib	0x0B000000

/*------ audio.device */
#define AN_AudioDev	0x10000000

/*------ console.device */
#define AN_ConsoleDev	0x11000000
#define AN_NoWindow	0x11000001	/* Console can't open initial window */

/*------ gameport.device */
#define AN_GamePortDev	0x12000000

/*------ keyboard.device */
#define AN_KeyboardDev	0x13000000

/*------ trackdisk.device */
#define AN_TrackDiskDev 0x14000000
#define AN_TDCalibSeek	0x14000001	/* calibrate: seek error */
#define AN_TDDelay	0x14000002	/* delay: error on timer wait */

/*------ timer.device */
#define AN_TimerDev	0x15000000
#define AN_TMBadReq	0x15000001 /* bad request */
#define AN_TMBadSupply	0x15000002 /* power supply -- no 50/60Hz ticks */

/*------ cia.resource */
#define AN_CIARsrc	0x20000000

/*------ disk.resource */
#define AN_DiskRsrc	0x21000000
#define AN_DRHasDisk	0x21000001	/* get unit: already has disk */
#define AN_DRIntNoAct	0x21000002	/* interrupt: no active unit */

/*------ misc.resource */
#define AN_MiscRsrc	0x22000000

/*------ bootstrap */
#define AN_BootStrap	0x30000000
#define AN_BootError	0x30000001	/* boot code returned an error */

/*------ Workbench */
#define AN_Workbench			0x31000000
#define AN_NoFonts			0xB1000001
#define AN_WBBadStartupMsg1		0x31000001
#define AN_WBBadStartupMsg2		0x31000002
#define AN_WBBadIOMsg			0x31000003	/* Hacker code? */
#define AN_WBReLayoutToolMenu		0xB1010009	/* GadTools broke? */

/*------ DiskCopy */
#define AN_DiskCopy	0x32000000

/*------ toolkit for Intuition */
#define AN_GadTools	0x33000000

/*------ System utility library */
#define AN_UtilityLib	0x34000000

/*------ For use by any application that needs it */
#define AN_Unknown	0x35000000

#endif /* EXEC_ALERTS_H */


include/hardware/intbits.h

#ifndef	HARDWARE_INTBITS_H
#define	HARDWARE_INTBITS_H
/*
**	$VER: intbits.h 39.1 (18.9.1992)
**	Includes Release 44.1
**
**	bits in the interrupt enable (and interrupt request) register
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#define  INTB_SETCLR	(15)  /* Set/Clear control bit. Determines if bits */
        /* written with a 1 get set or cleared. Bits */
        /* written with a zero are allways unchanged */
#define  INTB_INTEN	(14)  /* Master interrupt (enable only ) */
#define  INTB_EXTER	(13)  /* External interrupt */
#define  INTB_DSKSYNC	(12)  /* Disk re-SYNChronized */
#define  INTB_RBF	(11)  /* serial port Receive Buffer Full */
#define  INTB_AUD3	(10)  /* Audio channel 3 block finished */
#define  INTB_AUD2	(9)   /* Audio channel 2 block finished */
#define  INTB_AUD1	(8)   /* Audio channel 1 block finished */
#define  INTB_AUD0	(7)   /* Audio channel 0 block finished */
#define  INTB_BLIT	(6)   /* Blitter finished */
#define  INTB_VERTB	(5)   /* start of Vertical Blank */
#define  INTB_COPER	(4)   /* Coprocessor */
#define  INTB_PORTS	(3)   /* I/O Ports and timers */
#define  INTB_SOFTINT	(2)   /* software interrupt request */
#define  INTB_DSKBLK	(1)   /* Disk Block done */
#define  INTB_TBE	(0)   /* serial port Transmit Buffer Empty */

#define  INTF_SETCLR	(1L<<15)
#define  INTF_INTEN	(1L<<14)
#define  INTF_EXTER	(1L<<13)
#define  INTF_DSKSYNC	(1L<<12)
#define  INTF_RBF	(1L<<11)
#define  INTF_AUD3	(1L<<10)
#define  INTF_AUD2	(1L<<9)
#define  INTF_AUD1	(1L<<8)
#define  INTF_AUD0	(1L<<7)
#define  INTF_BLIT	(1L<<6)
#define  INTF_VERTB	(1L<<5)
#define  INTF_COPER	(1L<<4)
#define  INTF_PORTS	(1L<<3)
#define  INTF_SOFTINT	(1L<<2)
#define  INTF_DSKBLK	(1L<<1)
#define  INTF_TBE	(1L<<0)

#endif	/* HARDWARE_INTBITS_H */


include/libraries/dosextens.h

#ifndef LIBRARIES_DOSEXTENS_H
#define LIBRARIES_DOSEXTENS_H
/*
**	$VER: dosextens.h 36.2 (12.7.1990)
**	Includes Release 44.1
**
**	DOS structures not needed for the casual AmigaDOS user
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef DOS_DOSEXTENS_H
#include <dos/dosextens.h>
#endif

#endif /* LIBRARIES_DOSEXTENS_H */


include/libraries/filehandler.h

#ifndef LIBRARIES_FILEHANDLER_H
#define LIBRARIES_FILEHANDLER_H
/*
**	$VER: filehandler.h 36.2 (12.7.1990)
**	Includes Release 44.1
**
**	device and file handler specific code for AmigaDOS
**
**	(C) Copyright 1986-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef DOS_FILEHANDLER_H
#include <dos/filehandler.h>
#endif

#endif /* LIBRARIES_FILEHANDLER_H */


include/gadgets/fuelgauge.h

#ifndef GADGETS_FUELGAUGE_H
#define GADGETS_FUELGAUGE_H
/*
**	$VER: fuelgauge.h 44.1 (19.10.1999)
**	Includes Release 44.1
**
**  Definitions for the fuelgauge.gadget BOOPSI class
**
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

/*****************************************************************************/

#ifndef REACTION_REACTION_H
#include <reaction/reaction.h>
#endif

#ifndef INTUITION_GADGETCLASS_H
#include <intuition/gadgetclass.h>
#endif

/*****************************************************************************/

#define FUELGAUGE_Dummy			(REACTION_Dummy + 0x12000)

#define FUELGAUGE_Min			(FUELGAUGE_Dummy + 1)
    /* (LONG) fuelgauge minimum value. */

#define FUELGAUGE_Max			(FUELGAUGE_Dummy + 2)
    /* (LONG) fuelgauge maximum value. */

#define FUELGAUGE_Level			(FUELGAUGE_Dummy + 3)
    /* (LONG) fuelgauge level (value between min and max). */

#define FUELGAUGE_Orientation	(FUELGAUGE_Dummy + 4)
    /* (WORD) orientation mode. */

#define FUELGAUGE_Percent		(FUELGAUGE_Dummy + 5)
    /* (BOOL) render numeric percentage display. */

#define FUELGAUGE_Ticks			(FUELGAUGE_Dummy + 6)
    /* (WORD) enable tick marks if number of ticks set is not 0. */

#define FUELGAUGE_ShortTicks	(FUELGAUGE_Dummy + 7)
    /* (WORD) enable small intermediate tick marks. */

#define FUELGAUGE_TickSize		(FUELGAUGE_Dummy + 8)
    /* (WORD) height of  large tick makrs. */

#define FUELGAUGE_TickPen		(FUELGAUGE_Dummy + 9)
    /* (WORD) tickmark pen. */

#define FUELGAUGE_PercentPen	(FUELGAUGE_Dummy + 10)
    /* (WORD) pen number to use for inner gauge percange rendering. */

#define FUELGAUGE_FillPen		(FUELGAUGE_Dummy + 11)
    /* (WORD) pen number to use for the fuelbar. */

#define FUELGAUGE_EmptyPen		(FUELGAUGE_Dummy + 12)
    /* (WORD) fuelgauge background/empty pen number. */

#define FUELGAUGE_VarArgs		(FUELGAUGE_Dummy + 13)
    /* argument array for GA_Text varargs string */

#define FUELGAUGE_Justification	(FUELGAUGE_Dummy + 14)
    /* GA_Text justification mode */

/*****************************************************************************/

/* FUELGAUGE_Orientation modes
 */
#define FGORIENT_HORIZ 0
#define FGORIENT_VERT 1

/* FUELGAUGE_Justification modes
 */
#define FGJ_LEFT	0	// default
#define FGJ_CENTER	1
#define FGJ_CENTRE FGJ_CENTER	// english/canadian spellings

/* Obsolete, DO NOT USE!
 */
#define FUELGAUGE_HORIZONTAL FGORIENT_HORIZ
#define FUELGAUGE_VERTICAL FGORIENT_VERT

#endif /* GADGETS_FUELGAUGE_H */


include/graphics/gfxmacros.h

#ifndef	GRAPHICS_GFXMACROS_H
#define	GRAPHICS_GFXMACROS_H
/*
**	$VER: gfxmacros.h 39.3 (31.5.1993)
**	Includes Release 44.1
**
**
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef  GRAPHICS_RASTPORT_H
#include <graphics/rastport.h>
#endif

#ifndef  GRAPHICS_GFXBASE_H
#include <graphics/gfxbase.h>
#endif

#ifndef  HARDWARE_CUSTOM_H
#include <hardware/custom.h>
#endif

#ifndef  HARDWARE_DMABITS_H
#include <hardware/dmabits.h>
#endif

/* NOTE: Define the following symbol in your source code
 *       if you need the old style macros defined below.
 *       Otherwise you will get the more robust versions
 *       instead.
 */
#ifdef OLD_GRAPHICS_GFXMACROS_H
#define ON_DISPLAY	custom.dmacon = BITSET|DMAF_RASTER;
#define OFF_DISPLAY	custom.dmacon = BITCLR|DMAF_RASTER;
#define ON_SPRITE	custom.dmacon = BITSET|DMAF_SPRITE;
#define OFF_SPRITE	custom.dmacon = BITCLR|DMAF_SPRITE;

#define ON_VBLANK	custom.intena = BITSET|INTF_VERTB;
#define OFF_VBLANK	custom.intena = BITCLR|INTF_VERTB;

#define SetDrPt(w,p)	{(w)->LinePtrn = p;(w)->Flags |= FRST_DOT;(w)->linpatcnt=15;}
#define SetAfPt(w,p,n)	{(w)->AreaPtrn = p;(w)->AreaPtSz = n;}

#define SetOPen(w,c)	{(w)->AOlPen = c;(w)->Flags |= AREAOUTLINE;}
#define SetWrMsk(w,m)	{(w)->Mask = m;}

/* the SafeSetxxx macros are backwards (pre V39 graphics) compatible versions */
/* using these macros will make your code do the right thing under V39 AND V37 */
#define SafeSetOutlinePen(w,c)	  {if (GfxBase->LibNode.lib_Version<39) { (w)->AOlPen = c;(w)->Flags |= AREAOUTLINE;} else SetOutlinePen(w,c); }
#define SafeSetWriteMask(w,m)	{if (GfxBase->LibNode.lib_Version<39) { (w)->Mask = (m);} else SetWriteMask(w,m); }

/* synonym for GetOPen for consistency with SetOutlinePen */
#define GetOutlinePen(rp) GetOPen(rp)

#define BNDRYOFF(w)	{(w)->Flags &= ~AREAOUTLINE;}

#define CINIT(c,n)	  UCopperListInit(c,n);
#define CMOVE(c,a,b)	{ CMove(c,&a,b);CBump(c); }
#define CWAIT(c,a,b)	{ CWait(c,a,b);CBump(c); }
#define CEND(c)	{ CWAIT(c,10000,255); }

#define DrawCircle(rp,cx,cy,r)	DrawEllipse(rp,cx,cy,r,r);
#define AreaCircle(rp,cx,cy,r)	AreaEllipse(rp,cx,cy,r,r);
#else /* OLD_GRAPHICS_GFXMACROS_H */

#define ON_DISPLAY	custom.dmacon = BITSET|DMAF_RASTER
#define OFF_DISPLAY	custom.dmacon = BITCLR|DMAF_RASTER
#define ON_SPRITE	custom.dmacon = BITSET|DMAF_SPRITE
#define OFF_SPRITE	custom.dmacon = BITCLR|DMAF_SPRITE

#define ON_VBLANK	custom.intena = BITSET|INTF_VERTB
#define OFF_VBLANK	custom.intena = BITCLR|INTF_VERTB

#define SetDrPt(w,p)	do { \
                (w)->LinePtrn = (p); \
                (w)->Flags |= FRST_DOT; \
                (w)->linpatcnt = 15; \
            } while (0)

#define SetAfPt(w,p,n)	do { \
                (w)->AreaPtrn = p; \
                (w)->AreaPtSz = n; \
            } while (0)

#define SetOPen(w,c)	do { \
                (w)->AOlPen = c; \
                (w)->Flags |= AREAOUTLINE; \
            } while (0)

#define SetWrMsk(w,m)	do { \
                (w)->Mask = m; \
            } while (0)

/* the SafeSetxxx macros are backwards (pre V39 graphics) compatible versions */
/* using these macros will make your code do the right thing under V39 AND V37 */

#define SafeSetOutlinePen(w,c)	do { \
                    if (GfxBase->LibNode.lib_Version < 39) \
                        SetOPen(w,c); \
                    else \
                        SetOutlinePen(w,c); \
                } while (0)

#define SafeSetWriteMask(w,m)	do { \
                    if (GfxBase->LibNode.lib_Version < 39) \
                        SetWrMsk(w,m); \
                    else \
                        SetWriteMask(w,m); \
                } while (0)

/* synonym for GetOPen for consistency with SetOutlinePen */
#define GetOutlinePen(rp) GetOPen(rp)

#define BNDRYOFF(w)	do { \
                (w)->Flags &= ~AREAOUTLINE; \
            } while (0)

#define CINIT(c,n)	UCopperListInit(c,n)

#define CMOVE(c,a,b)	do { \
                CMove(c,&a,b); \
                CBump(c); \
            } while (0)

#define CWAIT(c,a,b)	do { \
                CWait(c,a,b); \
                CBump(c); \
            } while (0)

#define CEND(c)		do { \
                CWAIT(c,10000,255); \
            } while (0)

#define DrawCircle(rp,cx,cy,r)	DrawEllipse(rp,cx,cy,r,r)
#define AreaCircle(rp,cx,cy,r)	AreaEllipse(rp,cx,cy,r,r)

#endif /* OLD_GRAPHICS_GFXMACROS_H */

#endif	/* GRAPHICS_GFXMACROS_H */


include/graphics/modeid.h

#ifndef GRAPHICS_MODEID_H
#define GRAPHICS_MODEID_H
/*
**	$VER: modeid.h 39.9 (27.5.1993)
**	Includes Release 44.1
**
**	include define file for graphics display mode IDs.
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef GRAPHICS_DISPLAYINFO_H
#include <graphics/displayinfo.h>
#endif

#define INVALID_ID			~0

/* With all the new modes that are available under V38 and V39, it is highly
 * recommended that you use either the asl.library screenmode requester,
 * and/or the V39 graphics.library function BestModeIDA().
 *
 * DO NOT interpret the any of the bits in the ModeID for its meaning. For
 * example, do not interpret bit 3 (0x4) as meaning the ModeID is interlaced.
 * Instead, use GetDisplayInfoData() with DTAG_DISP, and examine the DIPF_...
 * flags to determine a ModeID's characteristics. The only exception to
 * this rule is that bit 7 (0x80) will always mean the ModeID is
 * ExtraHalfBright, and bit 11 (0x800) will always mean the ModeID is HAM.
 */

/* normal identifiers */

#define MONITOR_ID_MASK			0xFFFF1000

#define DEFAULT_MONITOR_ID		0x00000000
#define NTSC_MONITOR_ID			0x00011000
#define PAL_MONITOR_ID			0x00021000

/* the following 22 composite keys are for Modes on the default Monitor.
 * NTSC & PAL "flavors" of these particular keys may be made by or'ing
 * the NTSC or PAL MONITOR_ID with the desired MODE_KEY...
 *
 * For example, to specifically open a PAL HAM interlaced ViewPort
 * (or intuition screen), you would use the modeid of
 * (PAL_MONITOR_ID | HAMLACE_KEY)
 */

#define LORES_KEY			0x00000000
#define HIRES_KEY			0x00008000
#define SUPER_KEY			0x00008020
#define HAM_KEY				0x00000800
#define LORESLACE_KEY			0x00000004
#define HIRESLACE_KEY			0x00008004
#define SUPERLACE_KEY			0x00008024
#define HAMLACE_KEY			0x00000804
#define LORESDPF_KEY			0x00000400
#define HIRESDPF_KEY			0x00008400
#define SUPERDPF_KEY			0x00008420
#define LORESLACEDPF_KEY		0x00000404
#define HIRESLACEDPF_KEY		0x00008404
#define SUPERLACEDPF_KEY		0x00008424
#define LORESDPF2_KEY			0x00000440
#define HIRESDPF2_KEY			0x00008440
#define SUPERDPF2_KEY			0x00008460
#define LORESLACEDPF2_KEY		0x00000444
#define HIRESLACEDPF2_KEY		0x00008444
#define SUPERLACEDPF2_KEY		0x00008464
#define EXTRAHALFBRITE_KEY		0x00000080
#define EXTRAHALFBRITELACE_KEY		0x00000084
/* New for AA ChipSet (V39) */
#define HIRESHAM_KEY			0x00008800
#define SUPERHAM_KEY			0x00008820
#define HIRESEHB_KEY			0x00008080
#define SUPEREHB_KEY			0x000080a0
#define HIRESHAMLACE_KEY		0x00008804
#define SUPERHAMLACE_KEY		0x00008824
#define HIRESEHBLACE_KEY		0x00008084
#define SUPEREHBLACE_KEY		0x000080a4
/* Added for V40 - may be useful modes for some games or animations. */
#define LORESSDBL_KEY			0x00000008
#define LORESHAMSDBL_KEY		0x00000808
#define LORESEHBSDBL_KEY		0x00000088
#define HIRESHAMSDBL_KEY		0x00008808

/* VGA identifiers */

#define VGA_MONITOR_ID			0x00031000

#define VGAEXTRALORES_KEY		0x00031004
#define VGALORES_KEY			0x00039004
#define VGAPRODUCT_KEY			0x00039024
#define VGAHAM_KEY			0x00031804
#define VGAEXTRALORESLACE_KEY		0x00031005
#define VGALORESLACE_KEY		0x00039005
#define VGAPRODUCTLACE_KEY		0x00039025
#define VGAHAMLACE_KEY			0x00031805
#define VGAEXTRALORESDPF_KEY		0x00031404
#define VGALORESDPF_KEY			0x00039404
#define VGAPRODUCTDPF_KEY		0x00039424
#define VGAEXTRALORESLACEDPF_KEY	0x00031405
#define VGALORESLACEDPF_KEY		0x00039405
#define VGAPRODUCTLACEDPF_KEY		0x00039425
#define VGAEXTRALORESDPF2_KEY		0x00031444
#define VGALORESDPF2_KEY		0x00039444
#define VGAPRODUCTDPF2_KEY		0x00039464
#define VGAEXTRALORESLACEDPF2_KEY	0x00031445
#define VGALORESLACEDPF2_KEY		0x00039445
#define VGAPRODUCTLACEDPF2_KEY		0x00039465
#define VGAEXTRAHALFBRITE_KEY		0x00031084
#define VGAEXTRAHALFBRITELACE_KEY	0x00031085
/* New for AA ChipSet (V39) */
#define VGAPRODUCTHAM_KEY		0x00039824
#define VGALORESHAM_KEY			0x00039804
#define VGAEXTRALORESHAM_KEY		VGAHAM_KEY
#define VGAPRODUCTHAMLACE_KEY		0x00039825
#define VGALORESHAMLACE_KEY		0x00039805
#define VGAEXTRALORESHAMLACE_KEY	VGAHAMLACE_KEY
#define VGAEXTRALORESEHB_KEY		VGAEXTRAHALFBRITE_KEY
#define VGAEXTRALORESEHBLACE_KEY	VGAEXTRAHALFBRITELACE_KEY
#define VGALORESEHB_KEY			0x00039084
#define VGALORESEHBLACE_KEY		0x00039085
#define VGAEHB_KEY			0x000390a4
#define VGAEHBLACE_KEY			0x000390a5
/* These ModeIDs are the scandoubled equivalents of the above, with the
 * exception of the DualPlayfield modes, as AA does not allow for scandoubling
 * dualplayfield.
 */
#define VGAEXTRALORESDBL_KEY		0x00031000
#define VGALORESDBL_KEY			0x00039000
#define VGAPRODUCTDBL_KEY		0x00039020
#define VGAEXTRALORESHAMDBL_KEY		0x00031800
#define VGALORESHAMDBL_KEY		0x00039800
#define VGAPRODUCTHAMDBL_KEY		0x00039820
#define VGAEXTRALORESEHBDBL_KEY		0x00031080
#define VGALORESEHBDBL_KEY		0x00039080
#define VGAPRODUCTEHBDBL_KEY		0x000390a0

/* a2024 identifiers */

#define A2024_MONITOR_ID		0x00041000

#define A2024TENHERTZ_KEY		0x00041000
#define A2024FIFTEENHERTZ_KEY		0x00049000

/* prototype identifiers (private) */

#define PROTO_MONITOR_ID		0x00051000

/* These monitors and modes were added for the V38 release. */

#define EURO72_MONITOR_ID		0x00061000

#define EURO72EXTRALORES_KEY		0x00061004
#define EURO72LORES_KEY			0x00069004
#define EURO72PRODUCT_KEY		0x00069024
#define EURO72HAM_KEY			0x00061804
#define EURO72EXTRALORESLACE_KEY	0x00061005
#define EURO72LORESLACE_KEY		0x00069005
#define EURO72PRODUCTLACE_KEY		0x00069025
#define EURO72HAMLACE_KEY		0x00061805
#define EURO72EXTRALORESDPF_KEY		0x00061404
#define EURO72LORESDPF_KEY		0x00069404
#define EURO72PRODUCTDPF_KEY		0x00069424
#define EURO72EXTRALORESLACEDPF_KEY	0x00061405
#define EURO72LORESLACEDPF_KEY		0x00069405
#define EURO72PRODUCTLACEDPF_KEY	0x00069425
#define EURO72EXTRALORESDPF2_KEY	0x00061444
#define EURO72LORESDPF2_KEY		0x00069444
#define EURO72PRODUCTDPF2_KEY		0x00069464
#define EURO72EXTRALORESLACEDPF2_KEY	0x00061445
#define EURO72LORESLACEDPF2_KEY		0x00069445
#define EURO72PRODUCTLACEDPF2_KEY	0x00069465
#define EURO72EXTRAHALFBRITE_KEY	0x00061084
#define EURO72EXTRAHALFBRITELACE_KEY	0x00061085
/* New AA modes (V39) */
#define EURO72PRODUCTHAM_KEY		0x00069824
#define EURO72PRODUCTHAMLACE_KEY	0x00069825
#define EURO72LORESHAM_KEY		0x00069804
#define EURO72LORESHAMLACE_KEY		0x00069805
#define EURO72EXTRALORESHAM_KEY		EURO72HAM_KEY
#define EURO72EXTRALORESHAMLACE_KEY	EURO72HAMLACE_KEY
#define EURO72EXTRALORESEHB_KEY		EURO72EXTRAHALFBRITE_KEY
#define EURO72EXTRALORESEHBLACE_KEY	EURO72EXTRAHALFBRITELACE_KEY
#define EURO72LORESEHB_KEY		0x00069084
#define EURO72LORESEHBLACE_KEY		0x00069085
#define EURO72EHB_KEY			0x000690a4
#define EURO72EHBLACE_KEY		0x000690a5
/* These ModeIDs are the scandoubled equivalents of the above, with the
 * exception of the DualPlayfield modes, as AA does not allow for scandoubling
 * dualplayfield.
 */
#define EURO72EXTRALORESDBL_KEY		0x00061000
#define EURO72LORESDBL_KEY		0x00069000
#define EURO72PRODUCTDBL_KEY		0x00069020
#define EURO72EXTRALORESHAMDBL_KEY	0x00061800
#define EURO72LORESHAMDBL_KEY		0x00069800
#define EURO72PRODUCTHAMDBL_KEY		0x00069820
#define EURO72EXTRALORESEHBDBL_KEY	0x00061080
#define EURO72LORESEHBDBL_KEY		0x00069080
#define EURO72PRODUCTEHBDBL_KEY		0x000690a0

#define EURO36_MONITOR_ID		0x00071000

/* Euro36 modeids can be ORed with the default modeids a la NTSC and PAL.
 * For example, Euro36 SuperHires is
 * (EURO36_MONITOR_ID | SUPER_KEY)
 */

#define SUPER72_MONITOR_ID		0x00081000

/* Super72 modeids can be ORed with the default modeids a la NTSC and PAL.
 * For example, Super72 SuperHiresLace (800x600) is
 * (SUPER72_MONITOR_ID | SUPERLACE_KEY).
 * The following scandoubled Modes are the exception:
 */
#define SUPER72LORESDBL_KEY		0x00081008
#define SUPER72HIRESDBL_KEY		0x00089008
#define SUPER72SUPERDBL_KEY		0x00089028
#define SUPER72LORESHAMDBL_KEY		0x00081808
#define SUPER72HIRESHAMDBL_KEY		0x00089808
#define SUPER72SUPERHAMDBL_KEY		0x00089828
#define SUPER72LORESEHBDBL_KEY		0x00081088
#define SUPER72HIRESEHBDBL_KEY		0x00089088
#define SUPER72SUPEREHBDBL_KEY		0x000890a8

/* These monitors and modes were added for the V39 release. */

#define DBLNTSC_MONITOR_ID		0x00091000

#define DBLNTSCLORES_KEY		0x00091000
#define DBLNTSCLORESFF_KEY		0x00091004
#define DBLNTSCLORESHAM_KEY		0x00091800
#define DBLNTSCLORESHAMFF_KEY		0x00091804
#define DBLNTSCLORESEHB_KEY		0x00091080
#define DBLNTSCLORESEHBFF_KEY		0x00091084
#define DBLNTSCLORESLACE_KEY		0x00091005
#define DBLNTSCLORESHAMLACE_KEY		0x00091805
#define DBLNTSCLORESEHBLACE_KEY		0x00091085
#define DBLNTSCLORESDPF_KEY		0x00091400
#define DBLNTSCLORESDPFFF_KEY		0x00091404
#define DBLNTSCLORESDPFLACE_KEY		0x00091405
#define DBLNTSCLORESDPF2_KEY		0x00091440
#define DBLNTSCLORESDPF2FF_KEY		0x00091444
#define DBLNTSCLORESDPF2LACE_KEY	0x00091445
#define DBLNTSCHIRES_KEY		0x00099000
#define DBLNTSCHIRESFF_KEY		0x00099004
#define DBLNTSCHIRESHAM_KEY		0x00099800
#define DBLNTSCHIRESHAMFF_KEY		0x00099804
#define DBLNTSCHIRESLACE_KEY		0x00099005
#define DBLNTSCHIRESHAMLACE_KEY		0x00099805
#define DBLNTSCHIRESEHB_KEY		0x00099080
#define DBLNTSCHIRESEHBFF_KEY		0x00099084
#define DBLNTSCHIRESEHBLACE_KEY		0x00099085
#define DBLNTSCHIRESDPF_KEY		0x00099400
#define DBLNTSCHIRESDPFFF_KEY		0x00099404
#define DBLNTSCHIRESDPFLACE_KEY		0x00099405
#define DBLNTSCHIRESDPF2_KEY		0x00099440
#define DBLNTSCHIRESDPF2FF_KEY		0x00099444
#define DBLNTSCHIRESDPF2LACE_KEY	0x00099445
#define DBLNTSCEXTRALORES_KEY		0x00091200
#define DBLNTSCEXTRALORESHAM_KEY	0x00091a00
#define DBLNTSCEXTRALORESEHB_KEY	0x00091280
#define DBLNTSCEXTRALORESDPF_KEY	0x00091600
#define DBLNTSCEXTRALORESDPF2_KEY	0x00091640
#define DBLNTSCEXTRALORESFF_KEY		0x00091204
#define DBLNTSCEXTRALORESHAMFF_KEY	0x00091a04
#define DBLNTSCEXTRALORESEHBFF_KEY	0x00091284
#define DBLNTSCEXTRALORESDPFFF_KEY	0x00091604
#define DBLNTSCEXTRALORESDPF2FF_KEY	0x00091644
#define DBLNTSCEXTRALORESLACE_KEY	0x00091205
#define DBLNTSCEXTRALORESHAMLACE_KEY	0x00091a05
#define DBLNTSCEXTRALORESEHBLACE_KEY	0x00091285
#define DBLNTSCEXTRALORESDPFLACE_KEY	0x00091605
#define DBLNTSCEXTRALORESDPF2LACE_KEY	0x00091645

#define DBLPAL_MONITOR_ID		0x000a1000

#define DBLPALLORES_KEY			0x000a1000
#define DBLPALLORESFF_KEY		0x000a1004
#define DBLPALLORESHAM_KEY		0x000a1800
#define DBLPALLORESHAMFF_KEY		0x000a1804
#define DBLPALLORESEHB_KEY		0x000a1080
#define DBLPALLORESEHBFF_KEY		0x000a1084
#define DBLPALLORESLACE_KEY		0x000a1005
#define DBLPALLORESHAMLACE_KEY		0x000a1805
#define DBLPALLORESEHBLACE_KEY		0x000a1085
#define DBLPALLORESDPF_KEY		0x000a1400
#define DBLPALLORESDPFFF_KEY		0x000a1404
#define DBLPALLORESDPFLACE_KEY		0x000a1405
#define DBLPALLORESDPF2_KEY		0x000a1440
#define DBLPALLORESDPF2FF_KEY		0x000a1444
#define DBLPALLORESDPF2LACE_KEY		0x000a1445
#define DBLPALHIRES_KEY			0x000a9000
#define DBLPALHIRESFF_KEY		0x000a9004
#define DBLPALHIRESHAM_KEY		0x000a9800
#define DBLPALHIRESHAMFF_KEY		0x000a9804
#define DBLPALHIRESLACE_KEY		0x000a9005
#define DBLPALHIRESHAMLACE_KEY		0x000a9805
#define DBLPALHIRESEHB_KEY		0x000a9080
#define DBLPALHIRESEHBFF_KEY		0x000a9084
#define DBLPALHIRESEHBLACE_KEY			0x000a9085
#define DBLPALHIRESDPF_KEY		0x000a9400
#define DBLPALHIRESDPFFF_KEY		0x000a9404
#define DBLPALHIRESDPFLACE_KEY		0x000a9405
#define DBLPALHIRESDPF2_KEY		0x000a9440
#define DBLPALHIRESDPF2FF_KEY		0x000a9444
#define DBLPALHIRESDPF2LACE_KEY		0x000a9445
#define DBLPALEXTRALORES_KEY		0x000a1200
#define DBLPALEXTRALORESHAM_KEY		0x000a1a00
#define DBLPALEXTRALORESEHB_KEY		0x000a1280
#define DBLPALEXTRALORESDPF_KEY		0x000a1600
#define DBLPALEXTRALORESDPF2_KEY	0x000a1640
#define DBLPALEXTRALORESFF_KEY		0x000a1204
#define DBLPALEXTRALORESHAMFF_KEY	0x000a1a04
#define DBLPALEXTRALORESEHBFF_KEY	0x000a1284
#define DBLPALEXTRALORESDPFFF_KEY	0x000a1604
#define DBLPALEXTRALORESDPF2FF_KEY	0x000a1644
#define DBLPALEXTRALORESLACE_KEY	0x000a1205
#define DBLPALEXTRALORESHAMLACE_KEY	0x000a1a05
#define DBLPALEXTRALORESEHBLACE_KEY	0x000a1285
#define DBLPALEXTRALORESDPFLACE_KEY	0x000a1605
#define DBLPALEXTRALORESDPF2LACE_KEY	0x000a1645

/* Use these tags for passing to BestModeID() (V39) */

#define SPECIAL_FLAGS (DIPF_IS_DUALPF | DIPF_IS_PF2PRI | DIPF_IS_HAM | DIPF_IS_EXTRAHALFBRITE)

#define BIDTAG_DIPFMustHave	0x80000001	/* mask of the DIPF_ flags the ModeID must have */
                /* Default - NULL */
#define BIDTAG_DIPFMustNotHave	0x80000002	/* mask of the DIPF_ flags the ModeID must not have */
                /* Default - SPECIAL_FLAGS */
#define BIDTAG_ViewPort		0x80000003	/* ViewPort for which a ModeID is sought. */
                /* Default - NULL */
#define BIDTAG_NominalWidth	0x80000004	/* \ together make the aspect ratio and */
#define BIDTAG_NominalHeight	0x80000005	/* / override the vp->Width/Height. */
                /* Default - SourceID NominalDimensionInfo,
                 * or vp->DWidth/Height, or (640 * 200),
                 * in that preferred order.
                 */
#define BIDTAG_DesiredWidth	0x80000006	/* \ Nominal Width and Height of the */
#define BIDTAG_DesiredHeight	0x80000007	/* / returned ModeID. */
                /* Default - same as Nominal */
#define BIDTAG_Depth		0x80000008	/* ModeID must support this depth. */
                /* Default - vp->RasInfo->BitMap->Depth or 1 */
#define BIDTAG_MonitorID	0x80000009	/* ModeID must use this monitor. */
                /* Default - use best monitor available */
#define BIDTAG_SourceID		0x8000000a	/* instead of a ViewPort. */
                /* Default - VPModeID(vp) if BIDTAG_ViewPort is
                 * specified, else leave the DIPFMustHave and
                 * DIPFMustNotHave values untouched.
                 */
#define BIDTAG_RedBits		0x8000000b	/* \ 				*/
#define BIDTAG_BlueBits		0x8000000c	/* } Match up from the database */
#define BIDTAG_GreenBits	0x8000000d	/* /				*/
                /* Default - 4 */
#define BIDTAG_GfxPrivate	0x8000000e	/* Private */

#endif /* GRAPHICS_MODEID_H */


include/graphics/coerce.h

#ifndef GRAPHICS_COERCE_H
#define GRAPHICS_COERCE_H
/*
**	$VER: coerce.h 39.3 (15.2.1993)
**	Includes Release 44.1
**
**	mode coercion definitions
**
**	(C) Copyright 1992-1999 Amiga, Inc.
**	    All Rights Reserved
*/

/* These flags are passed (in combination) to CoerceMode() to determine the
 * type of coercion required.
 */

/* Ensure that the mode coerced to can display just as many colours as the
 * ViewPort being coerced.
 */
#define PRESERVE_COLORS 1

/* Ensure that the mode coerced to is not interlaced. */
#define AVOID_FLICKER 2

/* Coercion should ignore monitor compatibility issues. */
#define IGNORE_MCOMPAT 4

#define BIDTAG_COERCE 1	/* Private */

#endif


include/graphics/rpattr.h

#ifndef GRAPHICS_RPATTR_H
#define GRAPHICS_RPATTR_H
/*
**	$VER: rpattr.h 39.2 (31.5.1993)
**	Includes Release 44.1
**
**	tag definitions for GetRPAttr, SetRPAttr
**
*/

#define RPTAG_Font		0x80000000		/* get/set font */
#define RPTAG_APen		0x80000002		/* get/set apen */
#define RPTAG_BPen		0x80000003		/* get/set bpen */
#define RPTAG_DrMd		0x80000004		/* get/set draw mode */
#define RPTAG_OutLinePen	0x80000005	/* get/set outline pen */
#define RPTAG_OutlinePen	0x80000005	/* get/set outline pen. corrected case. */
#define RPTAG_WriteMask	0x80000006	/* get/set WriteMask */
#define RPTAG_MaxPen		0x80000007	/* get/set maxpen */

#define RPTAG_DrawBounds	0x80000008	/* get only rastport draw bounds. pass &rect */

#endif	/* GRAPHICS_RPATTR_H */


include/graphics/videocontrol.h

#ifndef	GRAPHICS_VIDEOCONTROL_H
#define	GRAPHICS_VIDEOCONTROL_H
/*
**	$VER: videocontrol.h 39.8 (31.5.1993)
**	Includes Release 44.1
**
**	include define file for videocontrol commands
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif /* EXEC_TYPES_H */

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif /* UTILITY_TAGITEM_H */

#define	VTAG_END_CM				0x00000000
#define	VTAG_CHROMAKEY_CLR		0x80000000
#define	VTAG_CHROMAKEY_SET		0x80000001
#define	VTAG_BITPLANEKEY_CLR		0x80000002
#define	VTAG_BITPLANEKEY_SET		0x80000003
#define	VTAG_BORDERBLANK_CLR		0x80000004
#define	VTAG_BORDERBLANK_SET		0x80000005
#define	VTAG_BORDERNOTRANS_CLR		0x80000006
#define	VTAG_BORDERNOTRANS_SET		0x80000007
#define	VTAG_CHROMA_PEN_CLR		0x80000008
#define	VTAG_CHROMA_PEN_SET		0x80000009
#define	VTAG_CHROMA_PLANE_SET		0x8000000A
#define	VTAG_ATTACH_CM_SET		0x8000000B
#define	VTAG_NEXTBUF_CM			0x8000000C
#define	VTAG_BATCH_CM_CLR		0x8000000D
#define	VTAG_BATCH_CM_SET		0x8000000E
#define	VTAG_NORMAL_DISP_GET		0x8000000F
#define	VTAG_NORMAL_DISP_SET		0x80000010
#define	VTAG_COERCE_DISP_GET		0x80000011
#define	VTAG_COERCE_DISP_SET		0x80000012
#define	VTAG_VIEWPORTEXTRA_GET		0x80000013
#define	VTAG_VIEWPORTEXTRA_SET		0x80000014
#define	VTAG_CHROMAKEY_GET		0x80000015
#define	VTAG_BITPLANEKEY_GET		0x80000016
#define	VTAG_BORDERBLANK_GET		0x80000017
#define	VTAG_BORDERNOTRANS_GET		0x80000018
#define	VTAG_CHROMA_PEN_GET		0x80000019
#define	VTAG_CHROMA_PLANE_GET		0x8000001A
#define	VTAG_ATTACH_CM_GET		0x8000001B
#define	VTAG_BATCH_CM_GET		0x8000001C
#define	VTAG_BATCH_ITEMS_GET		0x8000001D
#define	VTAG_BATCH_ITEMS_SET		0x8000001E
#define	VTAG_BATCH_ITEMS_ADD		0x8000001F
#define	VTAG_VPMODEID_GET		0x80000020
#define	VTAG_VPMODEID_SET		0x80000021
#define	VTAG_VPMODEID_CLR		0x80000022
#define	VTAG_USERCLIP_GET		0x80000023
#define	VTAG_USERCLIP_SET		0x80000024
#define	VTAG_USERCLIP_CLR		0x80000025
/* The following tags are V39 specific. They will be ignored (returing error -3) by
    earlier versions */
#define VTAG_PF1_BASE_GET		0x80000026
#define VTAG_PF2_BASE_GET		0x80000027
#define VTAG_SPEVEN_BASE_GET		0x80000028
#define VTAG_SPODD_BASE_GET		0x80000029
#define VTAG_PF1_BASE_SET		0x8000002a
#define VTAG_PF2_BASE_SET		0x8000002b
#define VTAG_SPEVEN_BASE_SET		0x8000002c
#define VTAG_SPODD_BASE_SET		0x8000002d
#define VTAG_BORDERSPRITE_GET		0x8000002e
#define VTAG_BORDERSPRITE_SET		0x8000002f
#define VTAG_BORDERSPRITE_CLR		0x80000030
#define VTAG_SPRITERESN_SET		0x80000031
#define VTAG_SPRITERESN_GET		0x80000032
#define VTAG_PF1_TO_SPRITEPRI_SET	0x80000033
#define VTAG_PF1_TO_SPRITEPRI_GET	0x80000034
#define VTAG_PF2_TO_SPRITEPRI_SET	0x80000035
#define VTAG_PF2_TO_SPRITEPRI_GET	0x80000036
#define VTAG_IMMEDIATE			0x80000037
#define VTAG_FULLPALETTE_SET		0x80000038
#define VTAG_FULLPALETTE_GET		0x80000039
#define VTAG_FULLPALETTE_CLR		0x8000003A
#define VTAG_DEFSPRITERESN_SET		0x8000003B
#define VTAG_DEFSPRITERESN_GET		0x8000003C

/* all the following tags follow the new, rational standard for videocontrol tags:
 * VC_xxx,state		set the state of attribute 'xxx' to value 'state'
 * VC_xxx_QUERY,&var	get the state of attribute 'xxx' and store it into the longword
 *			pointed to by &var.
 *
 * The following are new for V40:
 */

#define VC_IntermediateCLUpdate		0x80000080
    /* default=true. When set graphics will update the intermediate copper
     * lists on color changes, etc. When false, it won't, and will be faster.
     */
#define VC_IntermediateCLUpdate_Query	0x80000081

#define VC_NoColorPaletteLoad		0x80000082
    /* default = false. When set, graphics will only load color 0
     * for this ViewPort, and so the ViewPort's colors will come
     * from the previous ViewPort's.
     *
     * NB - Using this tag and VTAG_FULLPALETTE_SET together is undefined.
     */
#define VC_NoColorPaletteLoad_Query	0x80000083

#define VC_DUALPF_Disable		0x80000084
    /* default = false. When this flag is set, the dual-pf bit
       in Dual-Playfield screens will be turned off. Even bitplanes
       will still come from the first BitMap and odd bitplanes
       from the second BitMap, and both R[xy]Offsets will be
       considered. This can be used (with appropriate palette
       selection) for cross-fades between differently scrolling
       images.
       When this flag is turned on, colors will be loaded for
       the viewport as if it were a single viewport of depth
       depth1+depth2 */
#define VC_DUALPF_Disable_Query		0x80000085

#endif	/* GRAPHICS_VIDEOCONTROL_H */


include/devices/prtgfx.h

#ifndef DEVICES_PRTGFX_H
#define DEVICES_PRTGFX_H
/*
**	$VER: prtgfx.h 44.1 (19.10.1999)
**	Includes Release 44.1
**
**	graphics printer driver structure definitions
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef GRAPHICS_RASTPORT_H
#include <graphics/rastport.h>
#endif

/****************************************************************************/

#define	PCMYELLOW	0		/* byte index for yellow */
#define	PCMMAGENTA	1		/* byte index for magenta */
#define	PCMCYAN		2		/* byte index for cyan */
#define	PCMBLACK	3		/* byte index for black */
#define PCMBLUE		PCMYELLOW	/* byte index for blue */
#define PCMGREEN	PCMMAGENTA	/* byte index for green */
#define PCMRED		PCMCYAN		/* byte index for red */
#define PCMWHITE	PCMBLACK	/* byte index for white */

/****************************************************************************/

union colorEntry
{
    ULONG	colorLong;	/* quick access to all of YMCB */
    UBYTE	colorByte[4];	/* 1 entry for each of YMCB */
    BYTE	colorSByte[4];	/* ditto (except signed) */
};

/****************************************************************************/

struct PrtInfo /* printer info */
{
    LONG			(*pi_render)();		/* PRIVATE - DO NOT USE! */
    struct RastPort *	pi_rp;			/* PRIVATE - DO NOT USE! */
    struct RastPort *	pi_temprp;		/* PRIVATE - DO NOT USE! */
    UWORD *			pi_RowBuf;		/* PRIVATE - DO NOT USE! */
    UWORD *			pi_HamBuf;		/* PRIVATE - DO NOT USE! */
    union colorEntry *	pi_ColorMap;		/* PRIVATE - DO NOT USE! */
    union colorEntry *	pi_ColorInt;		/* color intensities for entire row */
    union colorEntry *	pi_HamInt;		/* PRIVATE - DO NOT USE! */
    union colorEntry *	pi_Dest1Int;		/* PRIVATE - DO NOT USE! */
    union colorEntry *	pi_Dest2Int;		/* PRIVATE - DO NOT USE! */
    UWORD *			pi_ScaleX;		/* array of scale values for X */
    UWORD *			pi_ScaleXAlt;		/* PRIVATE - DO NOT USE! */
    UBYTE *			pi_dmatrix;		/* pointer to dither matrix */
    UWORD *			pi_TopBuf;		/* PRIVATE - DO NOT USE! */
    UWORD *			pi_BotBuf;		/* PRIVATE - DO NOT USE! */

    UWORD			pi_RowBufSize;		/* PRIVATE - DO NOT USE! */
    UWORD			pi_HamBufSize;		/* PRIVATE - DO NOT USE! */
    UWORD			pi_ColorMapSize;	/* PRIVATE - DO NOT USE! */
    UWORD			pi_ColorIntSize;	/* PRIVATE - DO NOT USE! */
    UWORD			pi_HamIntSize;		/* PRIVATE - DO NOT USE! */
    UWORD			pi_Dest1IntSize;	/* PRIVATE - DO NOT USE! */
    UWORD			pi_Dest2IntSize;	/* PRIVATE - DO NOT USE! */
    UWORD			pi_ScaleXSize;		/* PRIVATE - DO NOT USE! */
    UWORD			pi_ScaleXAltSize;	/* PRIVATE - DO NOT USE! */

    UWORD			pi_PrefsFlags;		/* PRIVATE - DO NOT USE! */
    ULONG			pi_special;		/* PRIVATE - DO NOT USE! */
    UWORD			pi_xstart;		/* PRIVATE - DO NOT USE! */
    UWORD			pi_ystart;		/* PRIVATE - DO NOT USE! */
    UWORD			pi_width;		/* source width (in pixels) */
    UWORD			pi_height;		/* source height (in pixels) */
    ULONG			pi_pc;			/* PRIVATE - DO NOT USE! */
    ULONG			pi_pr;			/* PRIVATE - DO NOT USE! */
    UWORD			pi_ymult;		/* PRIVATE - DO NOT USE! */
    UWORD			pi_ymod;		/* PRIVATE - DO NOT USE! */
    WORD			pi_ety;			/* PRIVATE - DO NOT USE! */
    UWORD			pi_xpos;		/* offset to start printing picture */
    UWORD			pi_threshold;		/* threshold value (from prefs) */
    UWORD			pi_tempwidth;		/* PRIVATE - DO NOT USE! */
    UWORD			pi_flags;		/* PRIVATE - DO NOT USE! */

    /* V44 additions */
    UWORD *			pi_ReduceBuf;		/* PRIVATE - DO NOT USE! */
    UWORD			pi_ReduceBufSize;	/* PRIVATE - DO NOT USE! */
    struct Hook *		pi_SourceHook;		/* PRIVATE - DO NOT USE! */
    ULONG *			pi_InvertHookBuf;	/* RESERVED - DO NOT USE! */
};

#endif	/* DEVICES_PRTGFX_H */


include/libraries/resource.h

#ifndef LIBRARIES_RESOURCE_H
#define LIBRARIES_RESOURCE_H
/*
**	$VER: resource.h 44.1 (19.10.1999)
**	Includes Release 44.1
**
**	resource.library definitions
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

typedef APTR RESOURCEFILE;
typedef ULONG RESOURCEID;

/* A gadget ID (Tag GA_ID) may contain the ID and the group ID
   ored together. The following definitions must be used to extract
   the original gadget ID (1024 different IDs are possible) and the
   group id (63 different group IDs are possible).
*/
#define RL_GADGETMASK 0x03FF
#define RL_GROUPMASK  0xFC00
#define RL_GADGETID(x) ((x) & RL_GADGETMASK)
#define RL_GROUPID(x) (((x) & RL_GROUPMASK) >> 10)

#endif /* LIBRARIES_RESOURCE_H */


include/gadgets/scroller.h

#ifndef GADGETS_SCROLLER_H
#define GADGETS_SCROLLER_H
/*
**	$VER: scroller.h 44.1 (19.10.1999)
**	Includes Release 44.1
**
**  Definitions for the scroller.gadget BOOPSI class
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

/*****************************************************************************/

#ifndef REACTION_REACTION_H
#include <reaction/reaction.h>
#endif

#ifndef INTUITION_GADGETCLASS_H
#include <intuition/gadgetclass.h>
#endif

/*****************************************************************************/

/* Additional attributes defined by the scroller.gadget class
 */

#define SCROLLER_Dummy			(REACTION_Dummy+0x0005000)

#define SCROLLER_Top			(SCROLLER_Dummy+1L)
    /* (WORD) scroller Top value (Defaults to 0). */

#define SCROLLER_Visible		(SCROLLER_Dummy+2L)
    /* (WORD) visible part of total. */

#define SCROLLER_Total			(SCROLLER_Dummy+3L)
    /* (WORD) total scroller size. */

#define SCROLLER_Orientation	(SCROLLER_Dummy+4L)
    /* (WORD) Vertical or Horizontal mode. */

#define SCROLLER_Arrows			(SCROLLER_Dummy+5L)
    /* (BOOL) Render arrows. */

#define SCROLLER_Stretch		(SCROLLER_Dummy+6L)
    /* (BOOL) AutoExpand/Stretch Total. */

#define SCROLLER_ArrowDelta		(SCROLLER_Dummy+7L)
    /* (WORD) Change arrow click makes. */

#define SCROLLER_SignalTask		(SCROLLER_Dummy+10L)
    /* (struct Task *) Signal this Task while scroller is active */

#define SCROLLER_SignalTaskBit	(SCROLLER_Dummy+11L)
    /* (ULONG) Signal with this Bit. */

/*****************************************************************************/

/* SCROLLER_Orientation Modes
 */

#define SORIENT_HORIZ	FREEHORIZ
#define SORIENT_VERT	FREEVERT

#define SCROLLER_HORIZONTAL	SORIENT_HORIZ
#define SCROLLER_VERTICAL	SORIENT_VERT

#endif /* GADGETS_SCROLLER_H */


include/devices/serial.h

#ifndef DEVICES_SERIAL_H
#define DEVICES_SERIAL_H
/*
**	$VER: serial.h 33.6 (6.11.1990)
**	Includes Release 44.1
**
**	external declarations for the serial device
**
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef   EXEC_IO_H
#include <exec/io.h>
#endif /* EXEC_IO_H */

           /* array of termination char's */
           /* to use,see serial.doc setparams */

 struct  IOTArray {
    ULONG TermArray0;
    ULONG TermArray1;
};

#define SER_DEFAULT_CTLCHAR 0x11130000	/* default chars for xON,xOFF */
/* You may change these via SETPARAMS.	At this time, parity is not
   calculated for xON/xOFF characters.	You must supply them with the
   desired parity. */

/******************************************************************/
/* CAUTION !!  IF YOU ACCESS the serial.device, you MUST (!!!!) use an
   IOExtSer-sized structure or you may overlay innocent memory !! */
/******************************************************************/

 struct  IOExtSer {
    struct	 IOStdReq IOSer;

/*     STRUCT	MsgNode
*   0	APTR	 Succ
*   4	APTR	 Pred
*   8	UBYTE	 Type
*   9	UBYTE	 Pri
*   A	APTR	 Name
*   E	APTR	 ReplyPort
*  12	UWORD	 MNLength
*     STRUCT   IOExt
*  14	APTR	 io_Device
*  18	APTR	 io_Unit
*  1C	UWORD	 io_Command
*  1E	UBYTE	 io_Flags
*  1F	BYTE	 io_Error
*     STRUCT   IOStdExt
*  20	ULONG	 io_Actual
*  24	ULONG	 io_Length
*  28	APTR	 io_Data
*  2C	ULONG	 io_Offset
*
*  30 */
   ULONG   io_CtlChar;	  /* control char's (order = xON,xOFF,INQ,ACK) */
   ULONG   io_RBufLen;	  /* length in bytes of serial port's read buffer */
   ULONG   io_ExtFlags;   /* additional serial flags (see bitdefs below) */
   ULONG   io_Baud;	  /* baud rate requested (true baud) */
   ULONG   io_BrkTime;	  /* duration of break signal in MICROseconds */
   struct  IOTArray io_TermArray; /* termination character array */
   UBYTE   io_ReadLen;	  /* bits per read character (# of bits) */
   UBYTE   io_WriteLen;   /* bits per write character (# of bits) */
   UBYTE   io_StopBits;   /* stopbits for read (# of bits) */
   UBYTE   io_SerFlags;   /* see SerFlags bit definitions below  */
   UWORD   io_Status;
};
   /* status of serial port, as follows:
*		   BIT	ACTIVE	FUNCTION
*		    0	 ---	reserved
*		    1	 ---	reserved
*		    2	 high	Connected to parallel "select" on the A1000.
*				Connected to both the parallel "select" and
*				serial "ring indicator" pins on the A500
*				& A2000.  Take care when making cables.
*		    3	 low	Data Set Ready
*		    4	 low	Clear To Send
*		    5	 low	Carrier Detect
*		    6	 low	Ready To Send
*		    7	 low	Data Terminal Ready
*		    8	 high	read overrun
*		    9	 high	break sent
*		   10	 high	break received
*		   11	 high	transmit x-OFFed
*		   12	 high	receive x-OFFed
*		13-15		reserved
*/

#define   SDCMD_QUERY		CMD_NONSTD	/* $09 */
#define   SDCMD_BREAK	       (CMD_NONSTD+1)	/* $0A */
#define   SDCMD_SETPARAMS      (CMD_NONSTD+2)	/* $0B */

#define SERB_XDISABLED	7	/* io_SerFlags xOn-xOff feature disabled bit */
#define SERF_XDISABLED	(1<<7)	/*    "     xOn-xOff feature disabled mask */
#define	SERB_EOFMODE	6	/*    "     EOF mode enabled bit */
#define	SERF_EOFMODE	(1<<6)	/*    "     EOF mode enabled mask */
#define	SERB_SHARED	5	/*    "     non-exclusive access bit */
#define	SERF_SHARED	(1<<5)	/*    "     non-exclusive access mask */
#define SERB_RAD_BOOGIE 4	/*    "     high-speed mode active bit */
#define SERF_RAD_BOOGIE (1<<4)	/*    "     high-speed mode active mask */
#define	SERB_QUEUEDBRK	3	/*    "     queue this Break ioRqst */
#define	SERF_QUEUEDBRK	(1<<3)	/*    "     queue this Break ioRqst */
#define	SERB_7WIRE	2	/*    "     RS232 7-wire protocol */
#define	SERF_7WIRE	(1<<2)	/*    "     RS232 7-wire protocol */
#define	SERB_PARTY_ODD	1	/*    "     parity feature enabled bit */
#define	SERF_PARTY_ODD	(1<<1)	/*    "     parity feature enabled mask */
#define	SERB_PARTY_ON	0	/*    "     parity-enabled bit */
#define	SERF_PARTY_ON	(1<<0)	/*    "     parity-enabled mask */

/* These now refect the actual bit positions in the io_Status UWORD */
#define	IO_STATB_XOFFREAD 12	   /* io_Status receive currently xOFF'ed bit */
#define	IO_STATF_XOFFREAD (1<<12)  /*	 "     receive currently xOFF'ed mask */
#define	IO_STATB_XOFFWRITE 11	   /*	 "     transmit currently xOFF'ed bit */
#define	IO_STATF_XOFFWRITE (1<<11) /*	 "     transmit currently xOFF'ed mask */
#define	IO_STATB_READBREAK 10	   /*	 "     break was latest input bit */
#define	IO_STATF_READBREAK (1<<10) /*	 "     break was latest input mask */
#define	IO_STATB_WROTEBREAK 9	   /*	 "     break was latest output bit */
#define	IO_STATF_WROTEBREAK (1<<9) /*	 "     break was latest output mask */
#define	IO_STATB_OVERRUN 8	   /*	 "     status word RBF overrun bit */
#define	IO_STATF_OVERRUN (1<<8)	   /*	 "     status word RBF overrun mask */

#define	SEXTB_MSPON	1	/* io_ExtFlags. Use mark-space parity, */
                /*	    instead of odd-even. */
#define	SEXTF_MSPON	(1<<1)	/*    "     mark-space parity mask */
#define	SEXTB_MARK	0	/*    "     if mark-space, use mark */
#define	SEXTF_MARK	(1<<0)	/*    "     if mark-space, use mark mask */

#define SerErr_DevBusy	       1
#define SerErr_BaudMismatch    2 /* baud rate not supported by hardware */
#define SerErr_BufErr	       4 /* Failed to allocate new read buffer */
#define SerErr_InvParam        5
#define SerErr_LineErr	       6
#define SerErr_ParityErr       9
#define SerErr_TimerErr       11 /*(See the serial/OpenDevice autodoc)*/
#define SerErr_BufOverflow    12
#define SerErr_NoDSR	      13
#define SerErr_DetectedBreak  15

#ifdef DEVICES_SERIAL_H_OBSOLETE
#define SerErr_InvBaud	       3	/* unused */
#define SerErr_NotOpen	       7	/* unused */
#define SerErr_PortReset       8	/* unused */
#define SerErr_InitErr	      10	/* unused */
#define SerErr_NoCTS	      14	/* unused */

/* These defines refer to the HIGH ORDER byte of io_Status.  They have
   been replaced by the new, corrected ones above */
#define	IOSTB_XOFFREAD	4	/* iost_hob receive currently xOFF'ed bit */
#define	IOSTF_XOFFREAD	(1<<4)	/*    "     receive currently xOFF'ed mask */
#define	IOSTB_XOFFWRITE 3	/*    "     transmit currently xOFF'ed bit */
#define	IOSTF_XOFFWRITE (1<<3)	/*    "     transmit currently xOFF'ed mask */
#define	IOSTB_READBREAK 2	/*    "     break was latest input bit */
#define	IOSTF_READBREAK (1<<2)	/*    "     break was latest input mask */
#define	IOSTB_WROTEBREAK 1	/*    "     break was latest output bit */
#define	IOSTF_WROTEBREAK (1<<1) /*    "     break was latest output mask */
#define	IOSTB_OVERRUN	0	/*    "     status word RBF overrun bit */
#define	IOSTF_OVERRUN	(1<<0)	/*    "     status word RBF overrun mask */

#define	IOSERB_BUFRREAD 7	/* io_Flags from read buffer bit */
#define	IOSERF_BUFRREAD (1<<7)	/*    "     from read buffer mask */
#define	IOSERB_QUEUED	6	/*    "     rqst-queued bit */
#define	IOSERF_QUEUED	(1<<6)	/*    "     rqst-queued mask */
#define	IOSERB_ABORT	5	/*    "     rqst-aborted bit */
#define	IOSERF_ABORT	(1<<5)	/*    "     rqst-aborted mask */
#define	IOSERB_ACTIVE	4	/*    "     rqst-qued-or-current bit */
#define	IOSERF_ACTIVE	(1<<4)	/*    "     rqst-qued-or-current mask */
#endif

#define SERIALNAME     "serial.device"

#endif /* DEVICES_SERIAL_H */


include/gadgets/speedbar.h

#ifndef GADGETS_SPEEDBAR_H
#define GADGETS_SPEEDBAR_H
/*
**	$VER: speedbar.h 44.1 (19.10.1999)
**	Includes Release 44.1
**
**  Definitions for the speedbar.gadget BOOPSI class
**
**	(C) Copyright 1987-1999 Amiga, Inc.
**	    All Rights Reserved
*/

/*****************************************************************************/

#ifndef REACTION_REACTION_H
#include <reaction/reaction.h>
#endif

#ifndef INTUITION_GADGETCLASS_H
#include <intuition/gadgetclass.h>
#endif

/*****************************************************************************/

/* Defines for the speedbar node attributes.
 */
#define SBNA_Dummy		(TAG_USER+0x010000)

#define SBNA_Left		(SBNA_Dummy+1)
    /* (WORD) left offset of button. */

#define SBNA_Top		(SBNA_Dummy+2)
    /* (WORD) top offset of button. */

#define SBNA_Width		(SBNA_Dummy+3)
    /* (WORD) width of button. */

#define SBNA_Height		(SBNA_Dummy+4)
    /* (WORD) height of button. */

#define SBNA_UserData	(SBNA_Dummy+5)
    /* (APTR) user data, have a blast. */

#define SBNA_Enabled	(SBNA_Dummy+6)
    /* (BOOL) Is this button enabled?. */

#define SBNA_Spacing	(SBNA_Dummy+7)
    /* (WORD) spacing from last button. */

#define SBNA_Highlight	(SBNA_Dummy+8)
    /* (WORD) highlight mode (see below). */

#define SBNA_Image		(SBNA_Dummy+9)
    /* (strcut Image *) render image pointer. */

#define SBNA_SelImage	(SBNA_Dummy+10)
    /* (strcut Image *) select image pointer. */

#define SBNA_Help		(SBNA_Dummy+11)
    /* (UBYTE *) optional help text message pointer. */

#define SBNA_Toggle		(SBNA_Dummy+12)
    /* (BOOL) Make button a toggle button */

#define SBNA_Selected	(SBNA_Dummy+13)
    /* (BOOL) Sets state of a toggle button */

#define SBNA_MXGroup	(SBNA_Dummy+14)
    /* (BOOL) Mutual Exclusion Group Button, implies SBNA_Toggle */

#define SBNA_Disabled	(SBNA_Dummy+15)
    /* (BOOL) Disable this button, ghost pattern to be rendered */

/* Possible highlight modes.
 */
#define SBH_NONE		0
#define SBH_BACKFILL	1
#define SBH_RECESS		2
#define SBH_IMAGE		3

/*****************************************************************************/

/* Additional attributes defined by the speedbar.gadget class
 */
#define SPEEDBAR_Dummy			(REACTION_Dummy + 0x13000)

#define	SPEEDBAR_Buttons		(SPEEDBAR_Dummy+1)
    /* (struct List *) button list */

#define	SPEEDBAR_Orientation	(SPEEDBAR_Dummy+2)
    /* (WORD) Horizontal/vertical mode */

#define	SPEEDBAR_Background		(SPEEDBAR_Dummy+3)
    /* (UWORD) SpeedBar Background color */

#define	SPEEDBAR_Window			(SPEEDBAR_Dummy+4)
    /* (struct Window *) Window for WindowBar help */

#define SPEEDBAR_StrumBar		(SPEEDBAR_Dummy+5)
    /* (BOOL) Allow struming of button bar */

#define	SPEEDBAR_OnButton		(SPEEDBAR_Dummy+6)
    /* (WORD) Turn on a button by id# */

#define	SPEEDBAR_OffButton		(SPEEDBAR_Dummy+7)
    /* (WORD) Turn off a button by id# */

#define	SPEEDBAR_ScrollLeft		(SPEEDBAR_Dummy+8)
    /* (WORD) Scroll buttons left */

#define	SPEEDBAR_ScrollRight	(SPEEDBAR_Dummy+9)
    /* (WORD) Scroll buttons right */

#define	SPEEDBAR_Top			(SPEEDBAR_Dummy+10)
    /* (WORD) First visible */

#define	SPEEDBAR_Visible		(SPEEDBAR_Dummy+11)
    /* (WORD) Number visible */

#define	SPEEDBAR_Total			(SPEEDBAR_Dummy+12)
    /* (WORD) Total in list */

#define SPEEDBAR_Help			(SPEEDBAR_Dummy+13)
    /* (STRPTR) Window/Screen Help Text */

#define SPEEDBAR_BevelStyle		(SPEEDBAR_Dummy+14)
    /* (WORD) Bevel box style (BVS_BUTTON,BVS_THIN,BVS_NONE) */

#define SPEEDBAR_Selected			(SPEEDBAR_Dummy+15)
    /* (STRPTR) last selected speedbar node number */

#define SPEEDBAR_SelectedNode	(SPEEDBAR_Dummy+16)
    /* (STRPTR) last selected speedbar node pointer */

#define SPEEDBAR_EvenSize	(SPEEDBAR_Dummy+17)
    /* (BOOL) size all buttons in bar evenly, using the largest image */

/*****************************************************************************/

/* SPEEDBAR_Orientation Modes
 */
#define SBORIENT_HORIZ	0
#define SBORIENT_VERT	1

/* OBSOLETE DO NOT USE.
 */
#define SPEEDBAR_HORIZONTAL	SBORIENT_HORIZ
#define SPEEDBAR_VERTICAL	SBORIENT_VERT

#endif /* GADGETS_SPEEDBAR_H */


include/utility/pack.h

#ifndef UTILITY_PACK_H
#define UTILITY_PACK_H
/*
**	$VER: pack.h 39.3 (10.2.1993)
**	Includes Release 44.1
**
**	Control attributes for Pack/UnpackStructureTags()
**
**	(C) Copyright 1992-1999 Amiga, Inc.
**	All Rights Reserved
*/

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

/*****************************************************************************/

/* PackTable definition:
 *
 * The PackTable is a simple array of LONGWORDS that are evaluated by
 * PackStructureTags() and UnpackStructureTags().
 *
 * The table contains compressed information such as the tag offset from
 * the base tag. The tag offset has a limited range so the base tag is
 * defined in the first longword.
 *
 * After the first longword, the fields look as follows:
 *
 *	+--------- 1 = signed, 0 = unsigned (for bits, 1=inverted boolean)
 *	|
 *	|  +------ 00 = Pack/Unpack, 10 = Pack, 01 = Unpack, 11 = special
 *	| / \
 *	| | |  +-- 00 = Byte, 01 = Word, 10 = Long, 11 = Bit
 *	| | | / \
 *	| | | | | /----- For bit operations: 1 = TAG_EXISTS is TRUE
 *	| | | | | |
 *	| | | | | | /-------------------- Tag offset from base tag value
 *	| | | | | | |		      \
 *	m n n o o p q q q q q q q q q q r r r s s s s s s s s s s s s s
 *					\   | |		      |
 *	Bit offset (for bit operations) ----/ |		      |
 *					      \ 		      |
 *	Offset into data structure -----------------------------------/
 *
 * A -1 longword signifies that the next longword will be a new base tag
 *
 * A 0 longword signifies that it is the end of the pack table.
 *
 * What this implies is that there are only 13-bits of address offset
 * and 10 bits for tag offsets from the base tag.  For most uses this
 * should be enough, but when this is not, either multiple pack tables
 * or a pack table with extra base tags would be able to do the trick.
 * The goal here was to make the tables small and yet flexible enough to
 * handle most cases.
 */

#define	PSTB_SIGNED 31
#define PSTB_UNPACK 30	  /* Note that these are active low... */
#define PSTB_PACK   29	  /* Note that these are active low... */
#define	PSTB_EXISTS 26	  /* Tag exists bit true flag hack...  */

#define	PSTF_SIGNED (1L << PSTB_SIGNED)
#define PSTF_UNPACK (1L << PSTB_UNPACK)
#define PSTF_PACK   (1L << PSTB_PACK)

#define	PSTF_EXISTS (1L << PSTB_EXISTS)

/*****************************************************************************/

#define PKCTRL_PACKUNPACK 0x00000000
#define PKCTRL_PACKONLY   0x40000000
#define PKCTRL_UNPACKONLY 0x20000000

#define PKCTRL_BYTE	  0x80000000
#define PKCTRL_WORD	  0x88000000
#define PKCTRL_LONG	  0x90000000

#define PKCTRL_UBYTE	  0x00000000
#define PKCTRL_UWORD	  0x08000000
#define PKCTRL_ULONG	  0x10000000

#define PKCTRL_BIT	  0x18000000
#define PKCTRL_FLIPBIT	  0x98000000

/*****************************************************************************/

/* Macros used by the next batch of macros below. Normally, you don't use
 * this batch directly. Then again, some folks are wierd
 */

#define PK_BITNUM1(flg) ((flg) == 0x01 ? 0 : (flg) == 0x02 ? 1 : (flg) == 0x04 ? 2 : (flg) == 0x08 ? 3 : (flg) == 0x10 ? 4 : (flg) == 0x20 ? 5 : (flg) == 0x40 ? 6 : 7)
#define PK_BITNUM2(flg) ((flg < 0x100 ? PK_BITNUM1(flg) : 8+PK_BITNUM1(flg >> 8)))
#define PK_BITNUM(flg) ((flg < 0x10000 ? PK_BITNUM2(flg) : 16+PK_BITNUM2(flg >> 16)))
#define PK_WORDOFFSET(flg) ((flg) < 0x100 ? 1 : 0)
#define PK_LONGOFFSET(flg) ((flg) < 0x100  ? 3 : (flg) < 0x10000 ? 2 : (flg) < 0x1000000 ? 1 : 0)
#define PK_CALCOFFSET(type,field) ((ULONG)(&((struct type *)0)->field))

/*****************************************************************************/

/* Some handy dandy macros to easily create pack tables
 *
 * Use PACK_STARTTABLE() at the start of a pack table. You pass it the
 * base tag value that will be handled in the following chunk of the pack
 * table.
 *
 * PACK_ENDTABLE() is used to mark the end of a pack table.
 *
 * PACK_NEWOFFSET() lets you change the base tag value used for subsequent
 * entries in the table
 *
 * PACK_ENTRY() lets you define an entry in the pack table. You pass it the
 * base tag value, the tag of interest, the type of the structure to use,
 * the field name in the structure to affect and control bits (combinations of
 * the various PKCTRL_XXX bits)
 *
 * PACK_BYTEBIT() lets you define a bit-control entry in the pack table. You
 * pass it the same data as PACK_ENTRY, plus the flag bit pattern this tag
 * affects. This macro should be used when the field being affected is byte
 * sized.
 *
 * PACK_WORDBIT() lets you define a bit-control entry in the pack table. You
 * pass it the same data as PACK_ENTRY, plus the flag bit pattern this tag
 * affects. This macro should be used when the field being affected is word
 * sized.
 *
 * PACK_LONGBIT() lets you define a bit-control entry in the pack table. You
 * pass it the same data as PACK_ENTRY, plus the flag bit pattern this tag
 * affects. This macro should be used when the field being affected is longword
 * sized.
 *
 * EXAMPLE:
 *
 *    ULONG packTable[] =
 *    {
 *	   PACK_STARTTABLE(GA_Dummy),
 *	   PACK_ENTRY(GA_Dummy,GA_Left,Gadget,LeftEdge,PKCTRL_WORD|PKCTRL_PACKUNPACK),
 *	   PACK_ENTRY(GA_Dummy,GA_Top,Gadget,TopEdge,PKCTRL_WORD|PKCTRL_PACKUNPACK),
 *	   PACK_ENTRY(GA_Dummy,GA_Width,Gadget,Width,PKCTRL_UWORD|PKCTRL_PACKUNPACK),
 *	   PACK_ENTRY(GA_Dummy,GA_Height,Gadget,Height,PKCTRL_UWORD|PKCTRL_PACKUNPACK),
 *	   PACK_WORDBIT(GA_Dummy,GA_RelVerify,Gadget,Activation,PKCTRL_BIT|PKCTRL_PACKUNPACK,GACT_RELVERIFY)
 *	   PACK_ENDTABLE
 *    };
 */

#define PACK_STARTTABLE(tagbase)			   (tagbase)
#define PACK_NEWOFFSET(tagbase)			   (-1L),(tagbase)
#define PACK_ENDTABLE					   0
#define PACK_ENTRY(tagbase,tag,type,field,control)	   (control | ((tag-tagbase) << 16L) | PK_CALCOFFSET(type,field))
#define PACK_BYTEBIT(tagbase,tag,type,field,control,flags) (control | ((tag-tagbase) << 16L) | PK_CALCOFFSET(type,field) | (PK_BITNUM(flags) << 13L))
#define PACK_WORDBIT(tagbase,tag,type,field,control,flags) (control | ((tag-tagbase) << 16L) | (PK_CALCOFFSET(type,field)+PK_WORDOFFSET(flags)) | ((PK_BITNUM(flags)&7) << 13L))
#define PACK_LONGBIT(tagbase,tag,type,field,control,flags) (control | ((tag-tagbase) << 16L) | (PK_CALCOFFSET(type,field)+PK_LONGOFFSET(flags)) | ((PK_BITNUM(flags)&7) << 13L))

/*****************************************************************************/

#endif /* UTILITY_PACK_H */


Amiga® RKM Libraries: Contents

   NOTE:

   PREFACE

  Chapter 1  INTRODUCTION

  Contents:  USER INTERFACE LIBRARIES
             EXEC LIBRARIES
             GRAPHICS LIBRARIES
             ADDITIONAL LIBRARIES

             APPENDICES

   INDEX


Amiga® RKM Libraries: User Interface Libraries

  Chapters
  --------
   2  Intuition and the Amiga Graphical User Interface
   3  Intuition Screens
   4  Intuition Windows
   5  Intuition Gadgets
   6  Intuition Menus
   7  Intuition Requesters and Alerts
   8  Intuition Images, Line Drawing and Text
   9  Intuition Input and Output Methods
  10  Intuition Mouse and Keyboard
  11  Intuition Special Functions
  12  BOOPSI - Object-Oriented Intuition
  13  Preferences
  14  Workbench and Icon Library
  15  GadTools Library
  16  ASL Library


Amiga® RKM Libraries: Exec Library

  Chapters
  --------
  17  Introduction to Exec
  18  Exec Libraries
  19  Exec Device I/O
  20  Exec Memory Allocation
  21  Exec Tasks
  22  Exec Signals
  23  Exec Lists and Queues
  24  Exec Messages and Ports
  25  Exec Semaphores
  26  Exec Interrupts


Amiga® RKM Libraries: Graphics Libraries

  Chapters
  --------
  27  Graphics Primitives
  28  Graphics Sprites, Bobs and Animation
  29  Graphics Libraries and Text
  30  Layers Library


Amiga® RKM Libraries: Additional Libraries

  Chapters
  --------
  31  Commodities Exchange Library
  32  Expansion
  33  IFFParse Library
  34  Keymap Library
  35  Math Libraries
  36  Translator Library
  37  Utility Library


Amiga® RKM Libraries: Appendices

  Appendices
  ----------
  A  Linker Libraries
  B  BOOPSI Reference
  C  Example Library
  D  Troubleshooting Your Software
  E  Release 2 Compatibility
  F  Sample Startup Code


Amiga® RKM Libraries: Preface

This edition of the Amiga ROM Kernel Reference Manual: Libraries provides
the latest information on how to program the Amiga line of personal
computers.  It has been updated for Release 2 of the Amiga
operating system and covers the newest Amiga computer systems including
the A3000.

This book is meant to help you learn how to program the Amiga.  It assumes
some previous experience with programming and familiarity with computers
in general.  Although it is not required, a knowledge of the C programming
language will make it much easier to understand the material in this book.
Most of the Amiga operating system is written in C (with the rest written
in 68000 assembly language), hence C is the language used for the
programming examples.

This book is intended for the following audiences:

   *  C and assembly language programmers who want to create
      application software for the Amiga line of personal computers.

   *  Amiga software developers who want to upgrade their software for
      Release 2 of the operating system.

   *  Anyone who wants to know more about how the Amiga system
      software works.

The Amiga system software is organized into related groups of functions
called libraries.  The same organization is used for this book.  Here is a
brief overview of the contents:

   *  Chapter 1, Introduction to Amiga System Libraries. A look at
      the Amiga software and hardware architecture with an introduction
      to the basic elements of Amiga programming.

   *  Chapters 2-16, User Interface Libraries. An in-depth tutorial
      on how to create a graphic user interface for Amiga application
      software using Intuition and related modules including GadTools,
      Workbench, BOOPSI and ASL.

   *  Chapters 17-26, Exec Library. The details on how Exec,
      the system's master module, controls the system with working
      examples of interrupt processing code, subtask creation, lists
      and queues, semaphores, message passing and signalling.

   *  Chapters 27-30, Graphic Libraries. A complete explanation of
      the functions in the graphic and layers library that drive the
      Amiga's display hardware with examples of text rendering, line
      drawing, animation and more.

   *  Chapters 31-37, Additional Libraries. Tutorials on how to
      use the Amiga commodities, DOS, IFFParse, keymap, translator
      and other important libraries in the operating system.

   *  Appendices. Special sections containing a debugging and
      troubleshooting guide plus a working example library for
      programmers who want to extend the capabilities of the operating
      system.

We suggest that you use this book according to your level of familiarity
with the Amiga system.  Beginners should read the first four chapters and
try the examples to get the basics.  Then browse through the Exec chapters
to get a deeper understanding of how the system works.

Advanced Amiga programmers should read the chapters on new libraries like
 IFFParse  and GadTools to find out what's new in Release 2.  Also be
sure to review the new Utility library to see how tag item lists have
been used to implement many of the system improvements in Release 2.

There are four other manuals in the Amiga Technical Reference Series.  The
Amiga ROM Kernel Reference Manual:Devices is a companion book to this
volume detailing how to write code for the Amiga's lower level I/O
hardware.  The Amiga ROM Kernel Reference Manual: Includes and Autodocs is
an alphabetically organized reference of ROM function summaries and system
include files.  Both these books are required reading for the serious
programmer.

Also available are the Amiga User Interface Style Guide, an application
design specification and reference work describing how a standard Amiga
application should look and feel; and the Amiga Hardware Reference
Manual, an in-depth description of the custom chips and other hardware
components underlying the Amiga's sophisticated design.


Amiga® RKM Libraries: 1 Introduction to Amiga System Libraries

The Amiga, like other microcomputers, contains a ROM full of routines that
make programming the machine easier.  The purpose of this book is to show
you how to use these routines.  Perhaps the best way to learn Amiga
programming is by following examples and that is the method used in this
book.  Before starting though it will be helpful to go over some Amiga
fundamentals.  This section presents some of the basics that all Amiga
programmers need to know.

 Programming in the Amiga Environment
 About the Examples
 General Amiga Development Guidelines
 1.3 Compatibility Issues
 Commodore Applications and Technical Support (CATS)
 Error Reports


1 Introduction to Libraries / Programming in the Amiga Environment

To program in the Amiga's dynamic environment you need to understand these
special features of the Amiga's design:

  * Multitasking (without memory protection)

  * Shared libraries of functions

  * Dynamic memory architecture (no memory map)

  * Operating system versions

  * Custom chips with DMA access (two kinds of memory)

 Multitasking             Dynamic Memory Architecture   The Custom Chips
 Libraries of Functions   Operating System Versions


1 / Programming in the Amiga Environment / Multitasking

The key feature of the Amiga's operating system design is multitasking.
Multitasking means many programs, or tasks, reside in memory at the same
time sharing system resources with one another.  Programs take turns
running so it appears that many programs are running simultaneously.

Multitasking is based on the concept that a program spends most of its
time waiting for things to happen.  A program waits for events like key
presses, mouse movement, or disk activity.  While a program is waiting,
the CPU is idle.  The CPU could be used to run a different program during
this idle period if there was a convenient method for rapidly switching
from one program to another.  This is what multitasking does.

 What the System Does For You
 What the System Doesn't Do For You


1 / / Multitasking / What the System Does For You

The Amiga uses preemptive multitasking which means that the operating
system keeps track of all the tasks in memory and decides which one should
run.  The system checks hundreds of times per second to see which task
should be run based on whether or not it is waiting, and other factors.
Since the system handles all the work of task switching, multitasking is
transparent to the application.  From the application's point of view, it
appears to have the machine all to itself.

The Amiga OS also manages the sharing of resources between tasks.  This is
important because in order for a variety of tasks to run independently in
the Amiga's multitasking environment, tasks must be prevented from
interfering with one another.  Imagine if five tasks were allowed to use
the parallel port at the same time.  The result would be I/O chaos.  To
prevent this, the operating system provides an arbitration method (usually
a function call) for every system resource.  For instance you must call a
function, AllocMem(), to get exclusive access to a block of memory.


1 / / Multitasking / What the System Doesn't Do For You

The Amiga operating system handles most of the housekeeping needed for
multitasking, but this does not mean that applications don't have to worry
about multitasking at all.  The current generation of Amiga systems do not
have hardware memory protection, so there is nothing to stop a task from
using memory it has not legally acquired.  An errant task can easily
corrupt some other task by accidentally overwriting its instructions or
data.  Amiga programmers need to be extra careful with memory; one bad
memory pointer can cause the machine to crash (debugging utilities such as
MungWall and Enforcer will prevent this).

In fact, Amiga programmers need to be careful with every system resource,
not just memory.  All system resources from audio channels to the floppy
disk drives are shared among tasks.  Before using a resource, you must ask
the system for access to the resource.  This may fail if the resource is
already being used by another task.

Once you have control of a resource, no other task can use it, so give it
up as soon as you are finished.  When your program exits, you must give
everything back whether it's memory, access to a file, or an I/O port. You
are responsible for this, the system will not do it for you automatically.
  ______________________________________________________________________
 |                                                                      |
 | What Every Amiga Programmer Should Know:                             |
 | ----------------------------------------                             |
 | The Amiga is a multitasking computer.  Keep in mind that other       |
 | tasks are running at the same time as your application.  Always ask  |
 | the system for control of any resource you need; some other task may |
 | already be using it.  Give it back as soon as you are done; another  |
 | task may want to use it.  This applies to just about every computing |
 | activity your application can perform.                               |
 |______________________________________________________________________|


1 / Programming in the Amiga Environment / Libraries of Functions

Most of the routines that make up the Amiga's operating system are
organized into groups called libraries.  In order to call a function on
the Amiga you must first open the library that contains the function.  For
example, if you want to call the Read() function to read data from disk
you must first open the DOS library.

The system's master library, called Exec, is always open.  Exec keeps
track of all the other libraries and is in charge of opening and closing
them.  One Exec function, OpenLibrary(), is used to open all the other
libraries.

Almost any program you write for the Amiga will have to call the
OpenLibrary() function.  Usage is as follows:

    struct Library *LibBase;      /* Global: declare this above main() */

    main()
    {
    LibBase = OpenLibrary("library.name",version);

    if(!LibBase) { /* Library did not open, so exit        */ }
    else         { /* Library opened, so use its functions */ }
    }

LibBase
    This is a pointer to the library structure in memory, often referred
    to as the library base.  The library base must be global because the
    system uses it to handle the library's function calls.  The name of
    this pointer is established by the system (you cannot use any name
    you want).  Refer to the list below for the appropriate name.

library.name
    This is a C string that describes the name of the library you wish to
    open.  The list of Amiga library names is given below.

version
    This should be set to the earliest acceptable library version.  A
    value of 0 matches any version.  A value of 33 means you require at
    least version 33, or a later version of the library.  If the library
    version in the system is older than the one you specify,
    OpenLibrary() will fail (return 0).

The following table shows all the function libraries that are currently
part of the Amiga system software.  Column one shows the name string to
use with OpenLibrary(); column two shows the name of the global variable
you should use to hold the pointer to the library; column three shows the
oldest version of the library still in use.

         Table 1-1: Parameters to Use With OpenLibrary()

                                                    Oldest Version
     Library Name              Library Base Name        In Use
    (library.name)*               (LibBase)            (version)
    --------------             -----------------    --------------
    asl.library                AslBase                    36
    commodities.library        CxBase                     36
    diskfont.library           DiskfontBase               33
    dos.library                DOSBase                    33
    exec.library               SysBase                    33
    expansion.library          ExpansionBase              33
    gadtools.library           GadToolsBase               36
    graphics.library           GfxBase                    33
    icon.library               IconBase                   33
    iffparse.library           IFFParseBase               36
    intuition.library          IntuitionBase              33
    keymap.library             KeymapBase                 33
    layers.library             LayersBase                 33
    mathffp.library            MathBase                   33
    mathtrans.library          MathTransBase              33
    mathieeedoubbas.library    MathIeeeDoubBasBase        33
    mathieeedoubtrans.library  MathIeeeDoubTransBase      33
    mathieeesingbas.library    MathIeeeSingBasBase        33
    mathieeesingtrans.library  MathIeeeSingTransBase      33
    rexxsyslib.library         RexxSysBase                36
    translator.library         TranslatorBase             33
    utility.library            UtilityBase                36
    wb.library          WorkbenchBase              33

  * Other libraries may exist that are not supplied by Amiga, Inc. since
    it is a feature of the operating system to allow such libraries.

 Opening a Library in C            Another Kind of Function Library
 Opening a Library in Assembler    Libraries, Devices and Resources


1 / / Libraries of Functions / Opening a Library in C

Call OpenLibrary() to open an Amiga function library. OpenLibrary()
returns the address of the library structure (or library base) which you
must assign to a specific global system variable as specified in the
table above (case is important).

If the library cannot open for some reason, the OpenLibrary() function
returns zero.  Here's a brief example showing how it's used in C.

     easy.c


1 / / Libraries of Functions / Opening a Library in Assembler

Here's the same example written in 68000 assembler.  The principles are
the same as with : you must always open a library before using any of its
functions.  However, in assembler, library bases are treated a little
differently than in C.  In C, you assign the library base you get from
OpenLibrary() to a global variable and forget about it (the system handles
the rest).  In assembler, the library base must always be in register A6
whenever calling any of the functions in the library.

You get the library base for any library except Exec, by calling
OpenLibrary().  For Exec, you get the library base from the longword in
memory location 4 ($0000 0004). Exec is opened automatically by the system
at boot time, and its library base is stored there.

     easy.asm

The Amiga library functions are set up to accept parameters in certain
68000 registers and always return results in data register D0.  This
allows programs and functions written in assembler to communicate quickly.
It also eliminates the dependence on the stack frame conventions of any
particular language.

Amiga library functions use registers D0, D1, A0 and A1 for work space and
use register A6 to hold the library base.  Do not expect these registers
to be the same after calling a function.  All routines return a full 32
bit longword unless noted otherwise.


1 / / Libraries of Functions / Another Kind of Function Library

The Amiga has two kinds of libraries: run-time libraries and link
libraries.  All the libraries discussed so far are run-time libraries.
Run-time libraries make up most of the Amiga's operating system and are
the main topic of this book.

There is another type of library known as a link library.  Even though a
link library is a collection of functions just like a run-time library,
there are some major differences in the two types.

Run-time libraries
    A run-time, or shared library is a group of functions managed by Exec
    that resides either in ROM or on disk (in the LIBS: directory).  A
    run-time library must be opened before it can be used (as explained
    above).  The functions in a run-time library are accessed dynamically
    at run-time and can be used by many programs at once even though only
    one copy of the library is in memory.  A disk based run-time library
    is loaded into memory only if requested by a program and can be
    automatically flushed from memory when no longer needed.

Link libraries
    A link library is a group of functions on disk that are managed by
    the compiler at link time.  Link libraries do not have to be opened
    before they are used, instead you must link your code with the
    library when you compile a program.  The functions in a link library
    are actually copied into every program that uses them.  For instance
    the exit() function used in the C program listed above is not part of
    any of the libraries that make up the Amiga OS.  It comes from the
    link library supplied with the compiler (lc.lib for SAS/Lattice C or
    c.lib for Manx Aztec C).  The code that performs the exit() function
    is copied into the program when it is compiled.


1 / / Libraries of Functions / Libraries, Devices and Resources

Most of the Amiga's OS routines are organized into groups of shared
run-time libraries.  The Amiga also has specialized function groups called
devices and resources that programmers use to perform basic I/O operations
or access low-level hardware.

Devices and resources are similar in concept to a shared run-time library.
They are managed by Exec and must be opened before they can be used.
Their functions are separate from the programs that use them and are
accessed dynamically at run time.  Multiple programs can access the device
or resource even though only one copy exists in memory (a few resources
can only be used by one program at a time.)

   ________________      ________________
  |                |    |                |
  | AmigaDOS CLI   |    |   Workbench    |
  | & utilities    |    | Icons/Drawers/ |
  |                |    |   Utilities    |
  |________________|    |________________|
         |   |_________       |   |
         |    _________|______|   |
         |   |      ___|____      |
         |   |     /        \     |
         |   |    / Console  \    |
         |   |   |  Device    |   |
         |   |    \          /    |
         |   |     \________/     |
         |   |         |______    |
   ______|___|_____        ___|___|________
  |                |      |                |
  |   AmigaDOS     |      |   Intuition    |
  |   Processes,   |      | Windows,Menus  |
  |  File System   |      | Gadgets,Events |
  |________________|      |________________|
         |              ______|   |   |______
         |          ___|____      |   _______|________
         |         /        \     |  |                |
         |        /  Input   \    |  |    Layers      |
         |       |   Device   |   |  |    Library     |
         |        \          /    |  |                |
         |         \________/     |  |________________|
         |             |          |    ______|
         |             |     _____|___|______
         |             |    |                |
         |             |    |    Graphics    |
         |             |    |   Rendering    |
         |             |    |   Text, Gels   |
         |             |    |________________|
     ____|___       ___|____        |         ________       ________
    /        \     /        \       |        /        \     /        \
   /  SCSI &  \   / Keyboard \      |       /  Audio   \   /  Serial  \
  | Trackdisk  | | & Gameport |     |      |   Device   | | & Parallel |
   \  Device  /   \  Devices /      |       \          /   \  Devices /
    \________/     \________/       |        \________/     \________/
         |             |            |             |              |
   ______|_____________|____________|_____________|______________|______
  |                                                                     |
  |    Exec: Tasks, Messages, Interrupts, I/O, Libraries and Devices    |
  |_____________________________________________________________________|
         |             |            |             |            |
   ______|_____________|____________|_____________|____________|________
  |              |            |             |             |             |
  | Disk Control |  Keyboard  |  Graphics   |    Audio    |  I/O Ports  |
  |              |  & Mouse   |             |             |             |
  |______________|____________|_____________|_____________|_____________|

                Figure 1-1: Amiga System Software Hierarchy

Devices and resources are managed by Exec just as libraries are.  For more
information on devices and resources, see the chapter on Exec Device I/O
later in this book or refer to the Amiga ROM Kernel Reference Manual:
Devices for detailed descriptions of each device.
  _____________________________________________________________________
 |                                                                     |
 | What Every Amiga Programmer Should Know:                            |
 | ----------------------------------------                            |
 | The functions in the Amiga OS are accessed through shared run-time  |
 | libraries.  Libraries must be opened before their functions may be  |
 | used.  The system's master library, Exec, is always open.  The Exec |
 | function OpenLibrary() is used to open all other libraries.         |
 |_____________________________________________________________________|


1 / Programming in the Amiga Environment / Dynamic Memory Architecture

Unlike some microcomputer operating systems, the Amiga OS relies on
absolute memory addresses as little as possible.  Instead the Amiga OS
uses a technique (sometimes referred to as soft machine architecture)
which allows system routines and data structures to be positioned anywhere
in memory.

Amiga run-time libraries may be positioned anywhere in memory because they
are always accessed through a jump table.  Each library whether in ROM or
loaded from disk has an associated Library structure and jump table in RAM.

                            Low Memory
                               /|\
                                |
                       _________|_________
                      |                   |
                      |  JMP Function  N  |
                      |         ·         |
                      |         ·         |
                      |  JMP Function  3  |
                      |  JMP Function  2  |
                      |  JMP Function  1  |
      Library Base____|___________________|
                      |                   |
                      | Library Structure |
                      |___________________|
                      |                   |
                      |     Data Area     |
                      |___________________|
                                |
                                |
                               \|/
                           High Memory

      Figure 1-2: Amiga Library Structure and Jump Table

The system knows where the jump table starts in RAM because when a library
is opened for the first time, Exec creates the library structure and keeps
track of its location.  The order of the entries in the library's jump
table is always preserved between versions of the OS but the functions
they point to can be anywhere in memory.  Hence, system routines in ROM
may be moved from one version of the OS to another.  Given the location of
the jump table and the appropriate offset into the table, any function can
always be found.

Not only are system routines relocatable but system data structures are
too.  In the Amiga's multitasking environment, multiple applications run
at the same time and each may have its own screen, memory, open files, and
even its own subtasks.  Since any number of application tasks are run and
stopped at the user's option, system data structures have to be set up as
needed.  They cannot be set up ahead of time at a fixed memory location
because there is no way to tell how many and what type will be needed.

The Amiga system software manages this confusion by using linked lists of
information about items such as libraries, tasks, screens, files and
available memory.  A linked list is a chain of data items with each data
item containing a pointer to the next item in the chain.  Given a pointer
to the first item in a linked list, pointers to all the other items in the
chain can be found.

 Exec: The System Executive


1 / / Dynamic Memory Architecture / Exec: The System Executive

On the Amiga, the module that keeps track of linked lists is Exec, the
system executive.  Exec is the heart of the Amiga operating system since
it also is in charge of multitasking, granting access to system resources
(like memory) and managing the Amiga library system.

As previously discussed, memory location 4 ($0000 0004), also known as
SysBase, contains a pointer to the Exec library structure.  This is the
only absolutely defined location in the Amiga operating system.  A program
need only know where to find the Exec library to find, use and manipulate
all other system code and data.

                             $04 Sysbase
                                  |
                                  |
                             Exec Library
                                  |
     _____________________________|_____________________________
    |         |         |         |         |         |         |
    |         |         |         |         |         |         |
LIBRARIES  DEVICES    MEMORY  RESOURCES   INTS      PORTS     TASKS
    |         |         |         |         |         |         |
   DOS    Trackdisk   Chunk 1   Potgo      END      IDCMP       |
    |         |         |         |                   |         |
Graphics    Serial    Chunk 2   Keymap              IDCMP      / \
    |         |         |         |                   |       /   \
Intuition  Parallel    END      CIAA              Workbench  /     \
    |         |                   |                   |     /    WAITING
Expansion  Printer              CIAB                 END   /        |
    |         |                   |                       /    File System
  Layers    Input               Disk                     /          |
    |         |                   |                   READY    File System
 Mathffp   Keyboard             MISC                    |           |
    |         |                   |                   Shell    Input.device
   Icon    Gameport              END                    |           |
    |         |                                        RAM         END
 Diskfont   Timer                                       |
    |         |                                    Application
   END      Audio                                    Task 1
              |                                         |
           Console                                 Application
              |                                      Task 2
             END                                        |
                                                       END

         Figure 1-3: Exec and the Organization of the Amiga OS

The diagram above shows how the entire Amiga operating system is built as
a tree starting at SysBase.  Exec keeps linked lists of all the system
libraries, devices, memory, tasks and other data structures.  Each of
these in turn can have its own variables and linked lists of data
structures built onto it.  In this way, the flexibility of the OS is
preserved so that upgrades can be made without jeopardizing compatibility.
  _______________________________________________________________________
 |                                                                       |
 | What Every Amiga Programmer Should Know:                              |
 | ----------------------------------------                              |
 | The Amiga has a dynamic memory map.  There are no fixed locations for |
 | operating system variables and routines.  Do not call ROM routines or |
 | access system data structures directly.  Instead use the indirect     |
 | access methods provided by the system.                                |
 |_______________________________________________________________________|


1 / Programming in the Amiga Environment / Operating System Versions

The Amiga operating system has undergone several major revisions
summarized in the table below.  The latest revision is Release 2
(corresponds to library versions 36 and above).

  System library
  version number  Kickstart release
  --------------  -----------------
       0          Any version
       30         Kickstart V1.0 (obsolete)
       31         Kickstart V1.1 (NTSC only - obsolete)
       32         Kickstart V1.1 (PAL only - obsolete)
       33         Kickstart V1.2 (the oldest revision still in use)
       34         Kickstart V1.3 (adds autoboot to V33)
       35         Special Kickstart version to support A2024
                  high-resolution monitor
       36         Kickstart V2.0 (old version of Release 2)
       37         Kickstart V2.04 (current version of Release 2)

The examples listed throughout this book assume you are using Release 2.

Many of the libraries and functions documented in this manual are
available in all versions of the Amiga operating system.  Others are
completely new and cannot be used unless you have successfully opened the
appropriate version of the library.

To find out which functions are new with Release 2 refer to the ROM Kernel
Reference Manual: Includes and Autodocs.  The functions which are new are
marked with (V36) or (V37) in the NAME line of the function Autodoc.
These new functions require you to use a matching version number (36, 37,
or higher) when opening the library.

Exit gracefully and informatively if the required library version is not
available.

 About Release 2


1 / / Operating System Versions / About Release 2

Release 2 first appeared on the Amiga 3000.  This initial version
corresponds to Kickstart V2.00, system library version number V36.
Release 2 was subsequently revised and this older version is now
considered obsolete.

Programs written for Release 2 should use only the later version
corresponding to Kickstart V2.04, system library version number V37.  If
your system is using the earlier version of Release 2, you should upgrade
your system.  (Upgrade kits may be obtained from an authorized Amiga
service center.)
  _____________________________________________________________________
 |                                                                     |
 | What Every Amiga Programmer Should Know:                            |
 | ----------------------------------------                            |
 | Some libraries or specific functions are not available in older     |
 | versions of the Amiga operating system.  Be sure to ask for the     |
 | lowest library version that meets the requirements of your program. |
 |_____________________________________________________________________|


1 / Programming in the Amiga Environment / The Custom Chips

The most important feature of the Amiga's hardware design is the set of
custom chips that perform specialized tasks independently of the CPU. Each
of the custom chips (named Paula, Agnus, and Denise) is dedicated to a
particular job:

Paula   (8364)            Audio, floppy disk, serial, interrupts
Agnus   (8361/8370/8372)  Copper (video coprocessor), blitter, DMA control
Denise  (8362)            Color registers, color DACs (Digital to Analog
                          Converters) and sprites

The custom chips can perform work independently of the CPU because they
have DMA, or Direct Memory Access, capability.  DMA means the custom chips
can access special areas of memory by themselves without any CPU
involvement.  (On computer systems without DMA, the CPU must do some or
all of the memory handling for support chips.)  The Amiga's custom chips
make multitasking especially effective because they can handle things like
rendering graphics and playing sound independently, giving the CPU more
time to handle the overhead of task-switching and other important jobs.

 Custom Chip Revisions    Two Kinds of Memory


1 / / The Custom Chips / Custom Chip Revisions

The custom chips have been revised as the Amiga platform has evolved and
newer models of the Amiga developed.  The latest revision of the Amiga
custom chips is known as the Enhanced Chip Set, or ECS.  Certain features
of the Amiga operating system, such as higher resolution screens and
special genlock modes, require the ECS version of the custom chips.  In
this book, features that require ECS are noted in the accompanying text.
For more details about the special features of ECS, see Appendix C of
the Amiga Hardware Reference Manual.


1 / / The Custom Chips / Two Kinds of Memory

To keep the Amiga running efficiently, the Amiga has two memory buses and
two kinds of memory.  Chip memory is memory that both the CPU and
custom chips can access.  Fast memory is memory that only the CPU (and
certain expansion cards) can access.  Since Chip memory is shared, CPU
access may be slowed down if the custom chips are doing heavy-duty
processing.  CPU access to Fast memory is never slowed down by contention
with the custom chips.

The distinction between Chip memory and Fast memory is very important for
Amiga programmers to keep in mind because any data accessed directly by
the custom chips such as video display data, audio data or sprite data
must be in Chip memory.
  _________________________________________________________________
 |                                                                 |
 | What Every Amiga Programmer Should Know:                        |
 | ----------------------------------------                        |
 | The Amiga has two kinds of memory: Chip memory and Fast memory. |
 | Use the right kind.                                             |
 |_________________________________________________________________|


1 Introduction to Amiga System Libraries / About the Examples

For the most part, the examples in this book are written in C (there are a
few 68000 assembly language examples too).

C examples have been compiled under SAS C, version 5.10a.  The compiler
options used with each example are noted in the comments preceding the
code.

In general, the examples are also compatible with Manx Aztec C 68K,
version 5.0d, and other C compilers, however some changes will usually be
necessary.  Specifically, all the C examples assume that the automatic
Ctrl-C feature of the compiler has been disabled.  For SAS C (and Lattice
C revisions 4.0 and greater) this is handled with:

    /* Add this before main() to override the default Ctrl-C handling
     * provided in SAS (Lattice) C.  Ctrl-C event will be ignored */

    int CXBRK ( void )   { return(0); }
    int chkabort( void ) { return(0); }

For Manx Aztec C, replace the above with:

    /* Add this near the top */
            #include <functions.h>

    /* Add this before main() */
            extern int Enable_Abort;   /* reference abort enable */

    /* Add this after main(), as the first active line in the program */
            Enable_Abort=0;         /* turn off CTRL-C */

Other changes may be required depending on the example and the C compiler
you are using.  Most of the C examples in this book use the following
special option flags of the SAS/C compiler (set the equivalent option of
whatever compiler you are using):

-b1 = Small data model.
-cf = Check for function prototypes.
  i = Ignore #include statements that are identical to one already given.
  s = Store all literal strings that are identical in the same place.
  t = Enable warnings for structures that are used before they are defined.

 -v = Do not include stack checking code with each function.
 -y = Load register A4 with the data section base address on function
      entry.  The -v and -y flags are are generally only needed for parts
      of the program that are called directly by the system such as
      interrupt servers, subtasks, handlers and callback hook functions.

Except where noted, each example was linked with the standard SAS/C
startup code c.o, the SAS/C linker library lc.lib and the Amiga linker
library amiga.lib.  The SAS/C compiler defaults to 32-bit ints.  If your
development environment uses 16-bit ints you may need to explicitly cast
certain arguments as longs (for example 1L << sigbit instead of 1 <<
sigbit).

The 68000 assembly language examples have been assembled under the
Innovatronics CAPE assembler V2.x, the HiSoft Devpac assembler V1.2, and
the Lake Forest Logic ADAPT assembler 1.0.  No substantial changes should
be required to switch between assemblers.


1 Introduction to Libraries / General Amiga Development Guidelines

In the earlier sections of this chapter, the basic environment of the
Amiga operating system was discussed.  This section presents specific
guidelines that all Amiga programmers must follow.  Some of these
guidelines are for advanced programmers or apply only to code written in
assembly language.

  * Check for memory loss.  Arrange your Workbench screen so that you
    have a Shell available and can start your program without rearranging
    any windows.  In the Shell window type Avail flush several times (the
    flush option requires the Release 2 version of the Avail command).
    Note the total amount of free memory.  Run your program (do not
    rearrange any windows other than those created by the program) and
    then exit.  At the Shell, type Avail flush several times again.
    Compare the total amount of free memory with the earlier figure.
    They should be the same.  Any difference indicates that your
    application is not freeing some memory it used or is not closing a
    disk-loaded library, device or font it opened.  Note that under
    Release 2, a small amount of memory loss is normal if your
    application is the first to use the audio or narrator device.

  * Use all of the program debugging and stress tools that are available
    when writing and testing your code.  New debugging tools such as
    Enforcer, MungWall, and Scratch can help find uninitialized pointers,
    attempted use of freed memory and misuse of scratch registers or
    condition codes (even in programs that appear to work perfectly).

  * Always make sure you actually get any system resource that you ask
    for.  This applies to memory, windows, screens, file handles,
    libraries, devices, ports, etc.  Where an error value or return is
    possible, ensure that there is a reasonable failure path.  Many
    poorly written programs will appear to be reliable, until some error
    condition (such as memory full or a disk problem) causes the program
    to continue with an invalid or null pointer, or branch to untested
    error handling code.

  * Always clean up after yourself.  This applies for both normal program
    exit and program termination due to error conditions. Anything that
    was opened must be closed, anything allocated must be deallocated.
    It is generally correct to do closes and deallocations in reverse
    order of the opens and allocations.  Be sure to check your
    development language manual and startup code; some items may be
    closed or deallocated automatically for you, especially in abort
    conditions.  If you write in the C language, make sure your code
    handles Ctrl-C properly.

  * Remember that memory, peripheral configurations, and ROMs differ
    between models and between individual systems.  Do not make
    assumptions about memory address ranges, storage device names, or the
    locations of system structures or code.  Never call ROM routines
    directly.  Beware of any example code you find that calls routines at
    addresses in the $F0 0000 - $FF FFFF range.  These are ROM routines
    and they will move with every OS release.  The only supported
    interface to system ROM code is through the library, device, and
    resource calls.

  * Never assume library bases or structures will exist at any particular
    memory location.  The only absolute address in the system is $0000
    0004, which contains a pointer to the Exec library base. Do not
    modify or depend on the format of private system structures. This
    includes the poking of copper lists, memory lists, and library bases.

  * Never assume that programs can access hardware resources directly.
    Most hardware is controlled by system software that will not respond
    well to interference from other programs.  Shared hardware requires
    programs to use the proper sharing protocols.  Use the defined
    interface; it is the best way to ensure that your software will
    continue to operate on future models of the Amiga.

  * Never access shared data structures directly without the proper
    mutual exclusion (locking).  Remember that other tasks may be
    accessing the same structures.

  * The system does not monitor the size of a program's stack.  (Your
    compiler may have an option to do this for you.)  Take care that your
    program does not cause stack overflow and provide extra stack space
    for the possibility that some functions may use up additional stack
    space in future versions of the OS.

  * Never use a polling loop to test signal bits.  If your program waits
    for external events like menu selection or keystrokes, do not bog
    down the multitasking system by busy-waiting in a loop.  Instead, let
    your task go to sleep by Wait()ing on its signal bits.  For example:

        signals = (ULONG)Wait(  (1<<windowPtr->UserPort->mp_SigBit) |
                                    (1<<consoleMsgPortPtr->mp_SigBit)  );

    This turns the signal bit number for each port into a mask, then
    combines them as the argument for the Exec library Wait() function.
    When your task wakes up, handle all of the messages at each port
    where the mp_SigBit is set.  There may be more than one message per
    port, or no messages at the port.  Make sure that you ReplyMsg() to
    all messages that are not replies themselves.  If you have no signal
    bits to Wait() on, use Delay() or WaitTOF() to provide a measured
    delay.

  * Tasks (and processes) execute in 680x0 user mode.  Supervisor mode is
    reserved for interrupts, traps, and task dispatching.  Take extreme
    care if your code executes in supervisor mode.  Exceptions while in
    supervisor mode are deadly.

  * Most system functions require a particular execution environment.
    All DOS functions and any functions that might call DOS (such as the
    opening of a disk-resident library, font, or device) can only be
    executed from a process.  A task is not sufficient.  Most other ROM
    kernel functions may be executed from tasks.  Only a few may be
    executed from interrupts.

  * Never disable interrupts or multitasking for long periods.  If you
    use Forbid() or Disable(), you should be aware that execution of any
    system function that performs the Wait() function will temporarily
    suspend the Forbid() or Disable() state, and allow multitasking and
    interrupts to occur.  Such functions include almost all forms of DOS
    and device I/O, including common stdio functions like printf().

  * Never tie up system resources unless it is absolutely necessary. For
    example, if your program does not require constant use of the
    printer, open the printer device only when you need it.  This will
    allow other tasks to use the printer while your program is running.
    You must provide a reasonable error response if a resource is not
    available when you need it.

  * All data for the custom chips must reside in Chip memory (type
    MEMF_CHIP).  This includes bitplanes, sound samples, trackdisk
    buffers, and images for sprites, bobs, pointers, and gadgets.  The
    AllocMem() call takes a flag for specifying the type of memory. A
    program that specifies the wrong type of memory may appear to run
    correctly because many Amigas have only Chip memory.  (On all models
    of the Amiga, the first 512K of memory is Chip memory.  In later
    models, Chip memory may occupy up to the first one or two megabytes).

    However, once expansion memory has been added to an Amiga (type
    MEMF_FAST), any memory allocations will be made in the expansion
    memory area by default.  Hence, a program can run correctly on an
    unexpanded Amiga which has only Chip memory while crashing on an
    Amiga which has expanded memory.  A developer with only Chip memory
    may fail to notice that memory was incorrectly specified.

    Most compilers have options to mark specific data structures or
    object modules so that they will load into Chip RAM.  Some older
    compilers provide the Atom utility for marking object modules.  If
    this method is unacceptable, use the AllocMem() call to dynamically
    allocate Chip memory, and copy your data there.

    When making allocations that do not require Chip memory, do not
    explicitly ask for Fast memory.  Instead ask for memory type
    MEMF_PUBLIC or 0L as appropriate.  If Fast memory is available, you
    will get it.

  * Never use software delay loops!  Under the multitasking operating
    system, the time spent in a loop can be better used by other tasks.
    Even ignoring the effect it has on multitasking, timing loops are
    inaccurate and will wait different amounts of time depending on the
    specific model of Amiga computer.  The timer device provides
    precision timing for use under the multitasking system and it works
    the same on all models of the Amiga.  The AmigaDOS Delay() function
    or the graphics library WaitTOF() function provide a simple interface
    for longer delays.  The 8520 I/O chips provide timers for developers
    who are bypassing the operating system (see the Amiga Hardware
    Reference Manual for more information).

  * Always obey structure conventions!

      · All non-byte fields must be word-aligned.  Longwords should be
        longword-aligned for performance.

      · All address pointers should be 32 bits (not 24 bits).  Never use
        the upper byte for data.

      · Fields that are not defined to contain particular initial values
        must be initialized to zero.  This includes pointer fields.

      · All reserved or unused fields must be initialized to zero for
        future compatibility.

      · Data structures to be accessed by the custom chips, public data
        structures (such as a task control block), and structures which
        must be longword aligned must not be allocated on a program's
        stack.

      · Dynamic allocation of structures with AllocMem() provides
        longword aligned memory of a specified type with optional
        initialization to zero, which is useful in the allocation of
        structures.

 For 68010/68020/68030/68040 Compatibility
 Hardware Programming Guidelines
 Additional Assembler Development Guidelines


1 / General Development Guidelines / 68010/020/030/040 Compatibility

Special care must be taken to be compatible with the entire family of
68000 processors:

  * Do not use the upper 8 bits of a pointer for storing unrelated
    information.  The 68020, 68030, and 68040 use all 32 bits for
    addressing.

  * Do not use signed variables or signed math for addresses.

  * Do not use software delay loops, and do not make assumptions about
    the order in which asynchronous tasks will finish.

  * The stack frame used for exceptions is different on each member of
    the 68000 family.  The type identification in the frame must be
    checked! In addition, the interrupt autovectors may reside in a
    different location on processors with a VBR register.

  * Do not use the MOVE SR,<dest> instruction!  This 68000 instruction
    acts differently on other members of the 68000 family.  If you want
    to get a copy of the processor condition codes, use the Exec library
    GetCC() function.

  * Do not use the CLR instruction on a hardware register which is
    triggered by Write access.  The 68020 CLR instruction does a single
    Write access.  The 68000 CLR instruction does a Read access first,
    then a Write access.  This can cause a hardware register to be
    triggered twice.  Use MOVE.x #0, <address> instead.

  * Self-modifying code is strongly discouraged.  All 68000 family
    processors have a pre-fetch feature.  This means the CPU loads
    instructions ahead of the current program counter.  Hence, if your
    code modifies or decrypts itself just ahead of the program counter,
    the pre-fetched instructions may not match the modified instructions.
    The more advanced processors prefetch more words.  If self-modifying
    code must be used, flushing the cache is the safest way to prevent
    troubles.

  * The 68020, 68030 and 68040 processors all have instruction caches.
    These caches store recently used instructions, but do not monitor
    writes.  After modifying or directly loading instructions, the cache
    must be flushed.  See the Exec library CacheClearU() Autodoc for more
    details.  If your code takes over the machine, flushing the cache
    will be trickier.  You can account for the current processors, and
    hope the same techniques will work in the future:

        CACRF_ClearI  EQU     $0008     ;Bit for clear instruction cache
        ;
        ;Supervisor mode only. Use this only if you have taken over
        ;the machine.  Read and store the ExecBase processor AttnFlags
        ;flags at boot time, call this code only if the "68020 or
        ; better" bit was set.
        ;
        ClearICache:  dc.w    $4E7A,$0002  ;MOVEC CACR,D0
                      tst.w   d0           ;movec does not affect CC's
                      bmi.s   cic_040      ;A 68040 with enabled cache!
                      ori.w   #CACRF_ClearI,d0
                      dc.w    $4E7B,$0002  ;MOVEC D0,CACR
                      bra.s   cic_exit
        cic_040:      dc.w    $f4b8        ;CPUSHA (IC)
        cic_exit:


1 / General Development Guidelines / Hardware Programming Guidelines

If you find it necessary to program the hardware directly, then it is your
responsibility to write code that will work correctly on the various
models and configurations of the Amiga.  Be sure to properly request and
gain control of the hardware resources you are manipulating, and be
especially careful in the following areas:

  * Kickstart 2.0 uses the 8520 Complex Interface Adaptor (CIA) chips
    differently than 1.3 did.  To ensure compatibility, you must always
    ask for CIA access using the cia.resource AddICRVector() and
    RemICRVector() functions.  Do not make assumptions about what the
    system might be using the CIA chips for.  If you write directly to
    the CIA chip registers, do not expect system services such as the
    trackdisk device to function.  If you are leaving the system up, do
    not read or write to the CIA Interrupt Control Registers directly;
    use the cia.resource AbleICR(), and SetICR() functions.  Even if you
    are taking over the machine, do not assume the initial contents of
    any of the CIA registers or the state of any enabled interrupts.

  * All custom chip registers are Read-only or Write-only.  Do not read
    Write-only registers, and do not write to Read-only registers.

  * Never write data to, or interpret data from the unused bits or
    addresses in the custom chip space.  To be software-compatible with
    future chip revisions, all undefined bits must be set to zeros on
    writes, and must be masked out on reads before interpreting the
    contents of the register.

  * Never write past the current end of custom chip space.  Custom chips
    may be extended or enhanced to provide additional registers, or to
    use bits that are currently undefined in existing registers.

  * Never read, write, or use any currently undefined address ranges or
    registers.  The current and future usage of such areas is reserved
    and is subject to change.

  * Never assume that a hardware register will be initialized to any
    particular value.  Different versions of the OS may leave registers
    set to different values.  Check the Amiga Hardware Reference Manual
    to ensure that you are setting up all the registers that affect your
    code.


1 / General Guidelines / Additional Assembler Development Guidelines

If you are writing in assembly language there are some extra rules to keep
in mind in addition to those listed above.

  * Never use the TAS instruction on the Amiga.  System DMA can conflict
    with this instruction's special indivisible read-modify-write cycle.

  * System functions must be called with register A6 containing the
    library or device base.  Libraries and devices assume A6 is valid at
    the time of any function call.  Even if a particular function does
    not currently require its base register, you must provide it for
    compatibility with future system software releases.

  * Except as noted, system library functions use registers D0, D1, A0,
    and A1 as scratch registers and you must consider their former
    contents to be lost after a system library call.  The contents of all
    other registers will be preserved.  System functions that provide a
    result will return the result in D0.

  * Never depend on processor condition codes after a system call. The
    caller must test the returned value before acting on a condition
    code.  This is usually done with a TST or MOVE instruction.


1 Introduction to Amiga System Libraries / 1.3 Compatibility Issues

This 3rd edition of the Amiga Technical Reference Series focuses on the
Release 2 version of the Amiga operating system (Kickstart V2.04, V37).
Release 2 of the operating system was first shipped on the Amiga 3000 and
now available as an upgrade kit for the Amiga 500 and Amiga 2000 models to
replace the older 1.3 (V34) operating system.  Release 2 contains several
new libraries and hundreds of new library functions and features to assist
application writers.

 Design Decisions
 Compatible Libraries


1 / 1.3 Compatibility Issues / Design Decisions

The latest Amiga models, including all A3000's, are running Release 2.
But many older Amigas are still running 1.3 at this time.  Depending on
your application and your market, you may choose to require the Release 2
operating system as a minimum platform.  This can be a reasonable
requirement for vertical markets and professional applications.  Release 2
can also be a reasonable requirement for new revisions of existing
software products, since you could continue to ship the older
1.3-compatible release in the same package.  If you have made the decision
to require Release 2, then you are free to take advantage of all of the
new libraries and features that Release 2 provides.

Throughout this latest edition of the Amiga Technical Reference Series,
features, functions and libraries that are new for Release 2 are usually
indicated by (V36) or (V37) in the description of the feature.  Such
features are not available on Amiga models that are running 1.3 (V34) or
earlier versions of the OS.  Unconditional use of Release 2 functions will
cause a program to fail when it is run on a machine with the 1.3 OS.  It
is very important to remember this when designing and writing your code.

Developers of consumer-priced productivity, entertainment and utility
software may not yet be ready to write applications that require
Release 2, but even these developers can enhance their products by taking
advantage of Release 2 while remaining 1.3 compatible.

There are three basic methods that will allow you to take advantage of
enhanced Release 2 features while remaining 1.3 compatible:

      * Transparent Release 2 Extensions

      * Conditional Code

      * Compatible Libraries

 Transparent Release 2 Extensions
 Conditional Code
 ASL Requesters
 DOS System(), CreateNewProc(), and CON: Enhancements
 The Display Database
 ARexx


1 / / Design Decisions / Transparent Release 2 Extensions

To provide Release 2 enhancements while remaining compatible with the
older 1.3 version of the OS, several familiar 1.3 system structures have
been extended to include an optional pointer to additional information.
The new extended versions of such structures are generally defined in the
same include file as the original structure.  These extended structures
are passed to the same 1.3 system functions as the unextended structure
(e.g., OpenWindow(), OpenScreen(), AddGadget(), OpenDiskFont()).  The
existence of the extended information is signified by setting a new flag
bit in the structure.  (In one case, PROPNEWLOOK, only the flag bit itself
is significant).  These extensions are transparent to previous versions of
the operating system.  Only the Release 2 operating system will recognize
the bit and act on the extended information.

The table below lists the flag bit for each structure to specify that
extended information is present.

Original  Extended   Flag Field  Flag Bit           Defined In
--------  --------   ----------  --------           ----------
NewScreen ExtNewScreen Type      NS_EXTENDED       <intuition/screens.h>
NewWindow ExtNewWindow Flags     WFLG_NW_EXTENDED  <intuition/intuition.h>
Gadget    Gadget       Flags     GFLG_STRINGEXTEND <intuition/intuition.h>
PropInfo  PropInfo     Flags     PROPNEWLOOK       <intuition/intuition.h
TextAttr  TTextAttr    tta_Style FSF_TAGGED        <graphics/text.h>

Through the use of such extensions, applications can request special
Release 2 features in a 1.3-compatible manner.  When the application is
run on a Release 2 machine, the enhanced capabilities will be active.

The enhancements available through these extensions include:

   Screen: Overscan, 3D Look (SA_Pens), public screens, PAL/NTSC, new modes
   Window: Autoadjust sizing, inner dimensions, menu help
   Gadget: Control of font, pens, and editing of string gadgets
 PropInfo: Get 3D Look proportional gadgets when running under Release 2
TTextAttr: Control width of scaled fonts

Extensible longword arrays called TagItem lists are used to specify the
extended information for many of these structures.  Tag lists provide an
open-ended and backwards-compatible method of growing system structures by
storing all new specifications in an extendible array of longwords pairs.

Another transparent Release 2 extension is the diskfont library's ability
to scale bitmap and outline fonts to arbitrary sizes and the availability
of scalable outline fonts.  Make sure that these new scalable fonts are
available to your application by not setting the FPF_DESIGNED flag for
AvailFonts() or OpenDiskFont().  Allow the user to create new font sizes
by providing a way for her to manually enter the desired font size (the
1.3 OS returns the closest size, Release 2 returns the requested size).

See the Intuition and graphics library chapters, and the include file
comments for additional information.  See the "Utility Library" chapter
for more information on TagItems and tag lists.


1 / / Design Decisions / Conditional Code

Conditional code provides a second way to take advantage of Release 2
enhancements in a 1.3-compatible application.  The basic idea is to add
low overhead conditional code, based on library version, to make use of
selected Release 2 features if they are available.  There are some
powerful and beneficial Release 2 features which are definitely worth
conditional code.

The control flow for such conditional code is always based on whether a
particular version of a library is available.  Failure of OpenLibrary()
(i.e., return value of NULL) means that the library version requested is
not available.  The version number of a library that successfully opened
can be checked by testing LibBase->lib_Version.  Always check for a
version greater or equal to the version you need.

    Examples of conditional library checking code:

    /* Checking for presence of a new Release 2 library */
    if( AslBase = OpenLibrary("asl.library", 37L) )
            { /* OK to use the ASL requester */ }
    else
            { /* Must use a different method */ }

    /* Check version of an existing library with new Release 2 features */
    if(GfxBase->lib_Version >= 37)   { /* then allow new genlock modes */}


1 / / Design Decisions / ASL Requesters

The Release 2 ASL library provides standard file and font requesters.
Allocation and use of an ASL requester can be handled by coding a simple
subroutine to use the ASL requester if available.  Otherwise use fallback
code or a public domain requester. By now, many of you have probably coded
your own requesters and you may be quite attached to them.  In that case,
at least give your users the option to use the ASL requester if they wish.
By using the ASL requesters, you can provide a familiar interface to your
users, gain the automatic benefit of all ASL file requester improvements,
and stop maintaining your own requester code.


1 / / Design / DOS System(), CreateNewProc(), and CON: Enhancements

If your program currently uses the 1.3 AmigaDOS Execute() or CreateProc()
functions, then it is definitely worth conditional code to use their V37
replacements when running under Release 2.  The System() function of
Release 2 allows you to pass a command line to AmigaDOS as if it had been
typed at a Shell window.  System() can run synchronously with return
values or asynchronously with automatic cleanup and it also sets up a
proper stdio environment when passed a DOS filehandle for SYS_Input and
NULL for SYS_Output.  In combination with enhanced Release 2 CON:
features, System() can provide a suitable execution environment on either
Workbench or a custom screen.  The CreateNewProc() function provides
additional control and ease in process creation.

CON: input and output in custom Intuition screens and windows is now
supported.  New options in the Release 2 console handler (CON:) provide
the ability to open a CON: on any public Intuition screen, or to attach a
CON: to an existing Intuition window.  Additional options can add a close
gadget or create an AUTO console window which will only open if accessed
for read or write.  Add conditional code to use these system-supported
methods when running under Release 2 or later versions of the OS.  Note
that additional CON: option keywords can be easily removed under 1.3 at
runtime by terminating the CON: string with NULL after the window title.
Consult The AmigaDOS Manual by Bantam Books for additional information on
Release 2 CON: and DOS features.


1 / / Design Decisions / The Display Database

The Release 2 graphics library and the Enhanced Chip Set (ECS) provide
programmable display modes and enhanced genlock capabilities.  Users with
Release 2 and ECS may wish to use your application in one of the newer
display modes.  The Release 2 display database provides information on all
of the display modes available with the user's machine and monitor.  In
addition, it provides useful information on the capabilities and aspect
ratio of each mode (DisplayInfo.Resolution.x and .y).  A new function
named ModeNotAvailable() allows you to easily check if particular modes
are available.

The ExtNewScreen structure used with Intuition's OpenScreen() function
allows you to specify new display modes with the SA_DisplayID tag and a
longword ModeID.  The Release 2 graphics library VideoControl() function
provides greatly enhanced genlock capabilities for machines with ECS and a
genlock.  Little conditional code is required to support these features.
See the graphics library chapters and Autodocs for more information.


1 / / Design Decisions / ARexx

Add conditional ARexx capabilities to your program.  ARexx is available on
all Release 2 machines, and many 1.3 users have purchased ARexx
separately.  ARexx capability adds value to your product and allows users
and vertical market developers to create custom and hybrid applications.
Add the ability to control your application externally via ARexx, and
internally via ARexx macros.  Allow the user to execute ARexx scripts to
control other programs, including the ability to pass information from
your program to other applications.  For more information on adding ARexx
functionality to your application, see the Amiga Programmer's Guide to
ARexx, a publication by Commodore Applications and Technical Support
(CATS).  Contact your local Amiga support organization for information
on ordering this book.


1 / 1.3 Compatibility Issues / Compatible Libraries

Compatible libraries provide a third method for using Release 2 while
remaining 1.3-compatible.  Some Release 2 libraries are 1.3-compatible and
may be distributed with your product if you have a 1.3 Workbench License
and an amendment to distribute the additional library.

 IFFParse Library
 Single Precision IEEE Math Libraries
 Third Party Compatible Libraries


1 / / Compatible Libraries / IFFParse Library

The new IFFParse library is compatible with both Release 2 and the 1.3
version of the OS.  IFFParse is a run-time library which provides low
level code for writing, reading, and parsing IFF files.  Use of IFFParse
library and the new IFF example code modules can significantly reduce your
development and debugging time.  In addition, the IFFParse code modules
provide effortless handing of the clipboard device.  See the IFFParse
Library chapter in this book and the IFF Appendix of the Amiga ROM
Kernel Reference Manual: Devices for additional information.


1 / / Compatible Libraries / Single Precision IEEE Math Libraries

The Release 2 single precision IEEE math libraries are also compatible
with 1.3.  These libraries provide single-precision math functions that
will use a math coprocessor if available.


1 / / Compatible Libraries / Third Party Compatible Libraries

Developers of new code may wish to take advantage of the ease with which a
user interface can be created using the Release 2 GadTools and ASL support
libraries.  These new libraries are not 1.3-compatible but there are some
third party development efforts towards providing 1.3-compatible versions
of them.  You may wish to explore this possibility.


1 / Introduction / Commodore Applications and Technical Support (CATS)

Commodore maintains a technical support group dedicated to helping
developers achieve their goals with the Amiga.  Currently, technical
support programs are available to meet the needs of both smaller,
independent software developers and larger corporations.  Subscriptions to
Commodore's technical support publication, Amiga Mail, is available to
anyone with an interest in the latest news, Commodore software and
hardware changes, and tips for developers.

To request an application for Commodore's developer support program, or a
list of CATS technical publications send a self-addressed, stamped, 9" x
12" envelope to:

        CATS-Information
        1200 West Wilson Drive
        West Chester, PA  19380-4231


1 Introduction to Amiga System Libraries / Error Reports

In a complex technical manual, errors are often found after publication.
When errors in this manual are found, they will be corrected in a
subsequent printing.  Updates will be published in Amiga Mail, Commodore's
technical support publication.

Bug reports can be sent to Commodore electronically or by mail.  Submitted
reports must be clear, complete, and concise.  Reports must include a
telephone number and enough information so that the bug can be quickly
verified from your report (i.e., please describe the bug and the steps
that produced it).

        Amiga Software Engineering Group
        ATTN: BUG REPORTS
        Commodore Business Machines
        1200 Wilson Drive
        West Chester, PA  19380-4231
        USA

        BIX:    amiga.com/bug.reports(Commercial developers)
                amiga.cert/bug.reports(Certified developers)
                amiga.dev/bugs(Others)

        USENET: bugs@commodore.COM  or  uunet!cbmvax!bugs


Amiga® RKM Libraries: Index

        Note: Numbers will refer to page numbers in
    the `Amiga® ROM Kernal Reference Manual: Libraries'
              3rd edition, ISBN 0-201-56774-1

             Misc.           H              P
              A              I              Q
              B              J              R
              C              K              S
              D              L              T
              E              M              U
              F              N              V
              G              O           W X Y Z


Misc Index

1.3 - compatibility, 18
2.0 - compatibility, 923, differences, 923
32-bit math, 878 - example, 879, function reference, 883, functions, 878
3D Look - window title bar, 107, windows, 79
4703, 517
68000 - crash, 916
68020, 917
68030, 917
68040 - crash, 916
680x0, -->
68881, 845, 853
68882, 853


680x0 Index

680x0
  68040, 479
  Cache, 479
  caches, 477
  CopyBack mode, 479
  development guidelines, 15
  Exceptions, 473
  Floating Point Unit, 477
  FPU, 477
  GetCC(), 478
  Interrupt stack, 477
  ISP, 477
  Master stack, 477
  MSP, 477
  Paged Memory Management Unit, 477
  PMMU, 477
  programming guidelines, 17
  Register usage conventions,
  self-modifying code, 478
  SetSR(), 478
  SSP, 477
  Stack, 477
  Supervisor Mode, 477
  Supervisor stack, 477
  User stack, 477
  USP, 477


A Index

AbortIO(), 451
Accessing a Device, 446
Activate - window on open, 110
ActivateCxObj(), 731
ActivateGadget(), 150, 166, 321
ActivateWindow(), 91, 115
active gadget, 323
Active Window, -->
AddAnimOb(), 659, 668
AddBob(), 641, 668
AddBootNode(), 759, 776
AddClass(), 312, 330
AddDosNode(), 759, 776
AddGadget(), 166
AddGList(), 122, 129, 166
ADDHEAD, 498
AddHead(), 492, 498, 520
AddIEvents(), 749
AddIntServer(), 525
AddLibrary(), 443
AddPort(), 501, 511
AddPublicSemaphore(), 511
Address error, 474
AddSemaphore(), 511, 515
ADDTAIL, 498
AddTail(), 492, 498, 520
AddTask(), 466, 480
AddTOF(), 888
AddVSprite(), 627, 668
Adjust - window size, 111
AFF_DISK, 689
AFF_MEMORY, 689
AFF_SCALED, 689
AFF_TAGGED, 689
afp(), 888
Agnus, 11
Alert, -->
Alert(), 520
AllocAslRequest(), 416
AllocAslRequestTags(), 421
Allocate(), 462
Allocating memory, 455
AllocEntry(), 459, 461, 462
AllocIFF(), 344, 810
AllocLocalItem(), 790, 810
AllocMem(), 274, 284, 288, 430, 455, 457, 466
AllocRaster(), 98, 552, 610, allocating memory, 560
AllocRemember(), 283, 284, 284, 285, 288, 289
AllocSignal(), 254, 476, 482, 485
AllocTrap(), 476, 480
AllocVec(), 430
Alt Key, 282 - with right Amiga key, 176
Alternate - Alt key, 282, window size zoom, 108
Amiga -->
Amiga Key Glyph - menus, 184
Amiga keys - as command keys, 282, Workbench shortcuts, 281
Amiga.lib, 438, 885, stub, 438
AndRectRegion(), 722
AndRegionRegion(), 722
ANFRACSIZE, 661
Animate(), 660, 668
Animation, -->
AnimComp structure, 652
ANIMHALF, 661
AnimOb structure, 652
ANSI Codes, 90
AOlPen - in filling, 584, in RastPort, 584
Area pattern, 585
AreaCircle(), 590, 611
AreaDraw(), 611 - adding a vertex, 589, in area fill, 582
AreaEllipse(), 590, 611
AreaEnd(), 611 - drawing and filling shapes, 590, in area fill, 582
AreaInfo pointer, 582
AreaMove(), 611 - beginning a polygon, 589, in area fill, 582
ARexx, 21, 888
ArgArrayDone(), 735, 888
ArgArrayInit(), 735, 888
ArgInt(), 735, 888
ArgString(), 735, 888
arnd(), 888
AskKeyMapDefault(), 812
AskSoftStyle(), 675
ASL, -->
ASL Library, 20
asl.library - see ASL
AslRequest(), 416
AslRequestTags(), 421
ASL_BackPen, 423
ASL_CancelText, 417
ASL_Dir, 417
ASL_File, 417
ASL_FontFlags, 423
ASL_FontHeight, 423
ASL_FontName, 423
ASL_FontStyles, 423
ASL_FrontPen, 423
ASL_FuncFlags, 419
ASL_Hail, 417
ASL_Height, 417
ASL_Hookfunc, 425
ASL_LeftEdge, 417
ASL_MaxHeight, 423
ASL_MinHeight, 423
ASL_ModeList, 423
ASL_OKText, 417
ASL_TopEdge, 417
ASL_Width, 417
Aspect Ratio, 20
AttachCxObj(), 737
AttemptSemaphore(), 513, 513, 515
attributes, -->
AUD0-AUD3 Interrupts, 519
Audio device, 925
AUserStuff, 651
Autoboot, 760
AUTOCONFIG - hardware manufacturer number, 756, see Expansion, AUTOCONFIG
AUTOKNOB, 147
AutoRequest(), 97, 188, 201, 211, 215, 216, 222
AUTOSCROLL, 49
Autovector Address, 518
AvailFonts(), 688
AvailFonts structure, 688
AvailFontsHeader structure, 688
AvailMem(), 459
A-Pen - see FgPen


Active Window Index

Active Window, 78, 90
  input focus, 248
  menu verify, 186
  notification, 82, 91


Alert Index

Alert, 220
  application, 220
  DEADEND_ALERT, 220
  DisplayAlert(), 221
  positioning, 220
  RECOVERY_ALERT, 220
  screen mode ID, 220
  software error, 474
  system, 220


Amiga Index

Amiga
  custom chips, 11
  development guidelines, 13
  memory architecture,
  operating system versions, 10
  Register usage conventions,


Animation Index

Animation
  AddBob(), 641
  Animate(), 660
  AnimComp
    animation concepts, 652
    AnimComp flags, 659
    custom animation routine, 660
    ring motion control, 654
    sequenced drawing, 654
    sequencing components, 656
    sequencing within components, 655
    setting animation timing, 655
    setting component position, 655
    setting up ring motion control, 659
    setting up simple motion control, 658
    simple motion control, 654
    specifying components, 655
  AnimOb, 656
    adding an AnimOb, 659
    custom animation routine, 660
    moving the objects, 660
    setting AnimOb position, 658
    special numbering system, 661
    the AnimKey, 659
    typical function call sequence, 660
  Bob
    attaching a Bob to a VSprite, 635
    behavior for unselected bitplanes, 639
    Bob flags, 636
    changing a Bob, 642
    double-buffering, 645
    ImageShadow, 635
    setting bitplanes, 639
    setting collision detection, 639
    setting color, 638
    setting depth, 638
    setting image, 637
    setting rendering priority, 640
    setting rendering restrictions, 640
    setting shadow mask, 638
    setting shape, 637
    setting size, 637
    struct VSprite differences for Bobs, 634
    system selected rendering priorities, 640
    using Bobs, 634
    VSprite flags for Bobs, 634
  collision detection, 646
    adding user-defined data to GELs, 651
    AUserStuff, 651
    BorderLine for faster detection, 648
    boundary collision flags, 650
    building the collision handler table, 646
    BUserStuff, 651
    initializing collision detection, 646
    parameters to user-defined routines, 650, 650
    processing of multiple collisions, 650
    selective collision detection, 649
    sensitive areas, 647
    setting the collision mask, 647
    specifying collision boundaries, 650
    UserExt, 651
    VUserStuff, 651
  DoCollision(), 646
  DrawGList(), 642
  Examples - complete bobs example, 642
  InitMasks(), 648
  introduction, 613
  RemBob(), 641
  RemIBob(), 641
  SetCollision(), 647
  SortGList(), 642
  struct Bob, 635
  struct CollTable, 646
  struct DBufPacket, 645


ASL Index

ASL, 415
  AllocAslRequest(), 416
  AllocAslRequestTags(), 421
  AslRequest(), 416
  AslRequestTags(), 421
  Basic ASL Requester Tags, 417
  calling custom functions, 425
  creating a file requester, 416
  custom function parameters, 426
  custom screens, 421
  directory requester, 422
  Examples
    custom hook function, 426
    file requester with multiple selection, 419
    file requester with pattern matching, 419
    font requester, 424
    simple file requester, 417
  font requester, 422
  font requester flags, 423
  Font Requester Tags, 423
  FreeAslRequest(), 416
  function reference, 428
  hook function flags, 425
  save requester, 421
  special flags, 419
  struct FileRequester, 416
  struct FontRequester, 422


attributes Index

attribute
  Boopsi, 293 - attribute/value pairs, 294
  mapping, 299 - see ICA_MAP
  OM_GET, 311
  setting, 309


B Index

Backdrop -->
Backdrop Layer, 706
Background pen, 584
BACKGROUNDPEN, 58, 141
Backup - of display areas, 705
Beam synchronization, 600
BeginIO(), 448, 449, 520, 886
BeginRefresh(), 95, 97, 97, 110, 115, 128, 244, 261, 721
BeginUpdate(), 128, 711, 721
Behind - open screen, 49
BehindLayer(), 708, 711
Bell - visible, 75
BgPen - in RastPort, 584
BindDrivers, 758
BitMap -->
BitMap Structure -->
BitMapScale(), 598, 612
BitPlane -->
BLIT Interrupts, 519
Blitter -->
Block - graphics with layers, 708
Block Input, 203
Block Pen, 106
BLOCKPEN, 57
BltBitMap(), 596, 597, 612
BltBitMapRastPort(), 596, 597, 612
BltClear(), 592, 612
BltMaskBitMapRastPort(), 596, 598, 612
bltnode structure, 600 - creating, 601, linking blitter requests, 600
BltPattern(), 594, 612
BltTemplate(), 595, 596, 612
BNDRYOFF(), 590, 611
Bob structure, 635
Bobs - introduction, 613, simple definition, 615
BoolInfo structure, 139
BOOLMASK, 139
Boopsi -->
Border -->
Border structure -->
BORDERHIT, 648
Borderless -->
bottommost - in GelsInfo, 624
Box - menu item, 180
Break key, 432
Broadcast - IDCMP events, 248
BuildEasyRequest(), 217, 218-219, 222
BuildEasyRequestArgs(), 219, 222
BuildSysRequest(), 218, 222
Bus error, 474
BUserStuff, 651
Busy Pointer, 274
buttongclass, 297
buttonglclass, 315
B-Pen - see BgPen


Backdrop Index

Backdrop
  advantages over screen, 92
  attribute, 110
  hide screen title, 92
  window depth arrangement, 92
  window system gadgets, 92
  window type, 92, 92


BitMap Index

BitMap, 64
  address, 552
  and Intuition graphics, 223, 224
  custom for screen, 48
  in requester, 205
  initializing, 582
  larger than layer, 706
  menu items, 169
  requester, 206
  scaling, 598
  software clipping, 590
  with write mask, 583


BitMap Structure Index

BitMap Structure, 39, 98, 111, 213, 226, 703, 705, 706
  in dual-playfield display, 579
  in super bitmap layers, 706
  preparing, 552


BitPlane Index

BitPlane
  and Image data, 227
  color of unused, 230
  extracting a rectangle from, 595
  in dual-playfield display, 578
  in Image structure, 225
  picking, 230


Blitter Index

Blitter
  in Bob animation, 615
  in copying data, 599
  minterm, 597
  programming, 600
  VBEAM counter, 601


Boopsi Index

Boopsi, 291 - see also Appendix B: Boopsi Class Reference
  AddClass(), 312
  attribute, 293
  attributes - OM_GET, 311, setting, 295, 296, 309
  Boopsi and Tags, 294
  Building on Existing Public Classes, 306
  Building Rkmmodelclass, 306
  buttonglclass, 315
  Callback Hooks, 312
  caveats - message, 293, struct GadgetInfo, 316
  class, 292
    creating, 305
    custom, 305
    private, 293
    public, 293
  class reference, 891
  Creating an Object, 294
  dispatcher, 305
  Dispatcher Hook, 312
  DisposeObject(), 295
  Disposing of an Object, 295
  DoMethod(), 302
  DoMethodA(), 302
  DoSuperMethod(), 310
  DoSuperMethodA(), 308, 310
  Example
    custom gadget class, 323
    custom model subclass, 312
    Talk2boopsi.c, 299
  function descriptions, 330
  gadget, 291
    ActivateGadget(), 321
    active gadget, 323
    GFLG_DISABLED, 321
    GMR_MEACTIVE, 321
    GMR_NEXTACTIVE, 321
    GMR_NOREUSE, 321
    GMR_PREVACTIVE, 321
    GMR_REUSE, 321
    GM_GOINACTIVE, 322
    handling input, 320
    implemention of, 318
    Methods, 318
    ObtainGIRPort(), 323
    ReleaseGIRPort(), 323
    RemoveGList(), 322
    rendering a gadget, 319
  gadgetclass, 292, 297
    buttongclass, 297
    frbuttonclass, 298
    groupgclass, 297
    propgclass, 297
    strgclass, 297
  GA_RelVerify, 301
  GetAttr(), 296, 301
  getting attributes, 296
  GFLG_RELVERIFY, 301
  GMR_GADGETHIT, 320
  GM_GOACTIVE, 318, 320
  GM_GOINACTIVE, 318
  GM_HANDLEINPUT, 318, 321
  GM_HITTEST, 318, 320
  GM_RENDER, 318, 319
  GREDRAW_REDRAW, 319
  GREDRAW_TOGGLE, 319
  GREDRAW_UPDATE, 319
  handling input, 320
  ICA_MAP - Boopsi gadgets, 299, icclass, 302
  ICA_TARGET, 309 - Boopsi gadgets, 298, 302, icclass, 302
  icclass, 292, 297, 302
  ICSPECIAL_CODE - Boopsi gadgets, 302
  IDCMP_GADGETUP, 301
  IDCMP_IDCMPUPDATE - Boopsi gadgets, 302
  imageclass, 292, 297
    fillrectclass, 297
    frameiclass, 297
    itexticlass, 297
    sysiclass, 297
  Images, 291
  inheritance, 293, 306, 311
  input events, 321
  instance, 292
  instance data, 293, 308 - initializing, 308
  INST_DATA() macro, 309
  Intuition public classes, 297
  MakeClass(), 311
  Making Objects Talk to Each Other, 298
  Making Objects Talk to the Application, 301
  message, 293 - final, 309, interim, 309
  methods, 293
  modelclass, 302
  Msg, 307
  NewObject(), 295
  NewObjectA(), 294
  object, 292
  ObtainGIRPort(), 319
  obtaining gadget RastPort, 319
  OM_ADDMEMBER, 302, 307
  OM_ADDTAIL, 307
  OM_DISPOSE, 296, 307
  OM_GET, 296, 307, 311
  OM_NEW, 296, 307, 308
  OM_NOTIFY, 307, 309
  OM_REMMEMBER, 307
  OM_REMOVE, 307
  OM_SET, 296, 305, 307, 309 - Boopsi gadgets, 298
  OM_UPDATE, 307, 309 - Boopsi gadgets, 298
  OOP Overview, 292
  OPUF_INTERIM, 309
  RemoveClass(), 312
  rootclass, 292, 297
  SetAttrs(), 295
  SetGadgetAttrs(), 295, 305
  setting attributes, 295
  struct GadgetInfo, 316, 318
  struct gpGoInactive, 322
  struct gpHitTest, 320
  struct gpInput, 320
  struct gpRender, 319
  struct Hook, 312
  struct InputEvent, 321
  struct Msg, 303
  struct opGet, 311
  struct opMember, 303
  struct opSet, 305, 308
  struct opUpdate, 309
  subclass, 292
  superclass, 292
  typedef Class, 305
  user input, 321
  White Boxes--The Transparent Base Classes, 316
  Writing a Dispatcher, 307


Border Index

Border
  calculating window border size, 89
  containing size gadget, 109
  dimensions (from window), 105
  gadgets in, 88
  graphics offsets, 89
  in requester, 204
  in requester gadgets, 206
  position, 224
  rast port, 105
  size precalculation, 41
  using, 234
  window 88-89


Border structure Index

Border structure, 123, 212, 223, 224, 224, 234-235, 235, 238
  BackPen, 234
  Count, 234
  data organization, 237
  definition, 234
  DrawMode, 234
  FrontPen, 234, 237
  LeftEdge, 234, 235, 238, 238
  NextBorder, 235, 238
  TopEdge, 234, 235, 238, 238
  XY 234, 235, 237-238


Borderless Index

Borderless
  advantages over screen, 93
  attribute, 110
  window type, 92, 93
  with backdrop, 93


C Index

CacheClearE(), 479
CacheClearU(), 479
CachePostDMA(), 479
CachePreDMA(), 479
Caches, 477
Callback Hooks, 312
CallHook(), 890
CallHookA(), 890
Cancel - in requester, 203
Cause(), 520, 527
Caveats -->
CBERR_DUO, 731
CBERR_OK, 731
CBERR_SYSERR, 731
CBERR_VERSION, 731
CBump(), 603, 612
CDB_CONFIGME, 756
CDB_SHUTUP, 756
CDF_CONFIGME, 756
CDF_SHUTUP, 756
CD_ASKKEYMAP, 813
CD_SETKEYMAP, 813
CEND(), 603, 612
ChangeSprite(), 619, 668
ChangeWindowBox(), 112, 115
Character Mapped - applications, 249
CHECKED, 175, 181, 182, 182, 191
CheckIO(), 450
CHECKIT, 181-182, 182, 182, 191
Checkmark -->
CheckRexxMsg(), 888
CHECKWIDTH, 182
Chip Memory -->
CHK instruction, 474
CIA, 926
CINIT(), 602, 612
Class, 292 - custom, 305, dispatcher, 305, MakeClass(), 311
Class typedef, 305
ClearCxObjError(), 742
ClearDMRequest(), 210, 222
ClearEOL(), 675
ClearMenuStrip(), 111, 171, 175, 186, 200
ClearPointer(), 114, 115, 274, 282
ClearRectRegion(), 722
ClearRegion(), 722
ClearScreen(), 675
Clicking - definition, 265
ClipBlit(), 596, 598, 612
Clipping -->
Clipping Graphics - layers, 719
Clipping Rectangles -->
Clipping region - in VSprites with GELGONE, 624
Close - enable gadget, 109
Close Gadget - window, 78, 82
Close vector, 437
CloseIFF(), 344, 810
CloseLibrary(), 436
CloseMonitor(), 568, 611
CloseScreen(), 42, 53, 76
CloseWindow(), 82, 109, 115, 175
CloseWindowSafely(), 254, 255
CloseWorkBench(), 52, 76
Closing A Device, 450 - outstanding IORequests, 451
CMOVE(), 603, 612
CoerceMethod(), 330, 890
CoerceMethodA(), 330, 890
Coercion, 565 - screens, 66
COERR_BADFILTER, 742
COERR_BADTYPE, 742
COERR_ISNULL, 742
COERR_NULLATTACH, 742
CollectionChunk(), 785, 810
CollectionItem(), 785
CollTable structure, 646
Color -->
Color mode - in Flood() fill, 591
Color Registers, 228
ColorFontColors structure, 698
ColorMap, 64, 553
ColorSpec Structure, 47 - ColorIndex, 47
ColorTextFont structure, 697
Command Key, 184 - menu item, 190, menus, 170, symbol position, 185
Commodities -->
commodities.library - see Commodities
COMMSEQ, 184, 190, 191
COMMWIDTH, 185
Compatibility -->
Compatibility notes, 923
Compatibility problems, 917, 918, 918, 918, 919, 918, 918
COMPLEMENT, 234, 237, 240, 243, 585
CON: - on custom screen, 20
ConfigDev structure, 756
Console - handler (CON:), 20
Console Device, 90, 246 - input/output, 248
console.device - CD_ASKKEYMAP, 813, CD_SETKEYMAP, 813
ContextNode structure, 789
Control (Ctrl) key, 282
Control-C, 432
Coordinates - in Border structure, 237
COPER, 519, 525
COPER Interrupts, 519, 525
Copper -->
Copper list -->
Coprocessor - copper list, 65
Copy - rectangles, 720, 721
Copying - data, 597, rectangles, 597
CopyMem(), 288, 459
CopyMemQuick(), 459
CopySBitMap(), 98
CPU Priority Level, 519
Crash, 916 - 68000, 916, 68040, 916
Crashing - with drawing routines, 588, with fill routines, 590
CreateBehindLayer(), 710, 710
CreateContext(), 399, 413
CreateExtIO(), 886
CreateGadget(), 380, 413
CreateGadgetA(), 413
CreateMenus(), 374, 413
CreateMenusA(), 374, 413
CreateMsgPort(), 501
CreateNewProc(), 20
CreatePort(), 254, 501, 887
CreateStdIO(), 887
CreateTask(), 467, 887
CreateUpfrontLayer(), 710, 710, 712
Critical section, 470
Ctrl, 282
CT_COLORFONT, 697
CT_GREYFONT, 697
CurrentBinding structure, 759
CurrentChunk(), 344, 789, 810
CurrentTime(), 288, 289
Custom - screen window on, 82, 107
Custom Chips, 11
Custom Gadgets - see Boopsi
CUSTOMBITMAP, 48
CUSTOMSCREEN, 107
CWAIT(), 602, 612
CxBroker(), 730
CXCMD_APPEAR, 734
CXCMD_DISABLE, 734
CXCMD_DISAPPEAR, 734
CXCMD_ENABLE, 734
CXCMD_KILL, 734
CxCustom(), 744, 889
CxDebug(), 745, 889
CxFilter(), 736, 889
CxMsgData(), 731
CxMsgID(), 731
CxMsgType(), 731
CXM_COMMAND, 731
CXM_IEVENT, 731
CxObjError(), 742
CxSender(), 741, 889
CxSignal(), 743, 889
CxTranslate(), 741, 889
CX_POPKEY, 734
CX_POPUP, 734
CX_PRIORITY, 734
__chip, 227


Caveats Index

Caveats
  Boopsi - message, 293, struct GadgetInfo, 316
  Gadgets
    do not share knob imagery, 143
    do not use image lists for knobs, 143
    GimmeZeroZero window border, 136
    imagery and the selection box, 124
    mouse tracking with boolean gadgets, 136
  GadTools
    GadTools enforces Intuition limits, 375
    GADTOOL_TYPE bit, 401
    GT_SetGadgetAttrs() and GT_BeginRefresh(), 386
    PLACETEXT with GENERIC_KIND gadgets, 398
    post-processing, 368
    preserve bits set by CreatsGadget(), 398
    refreshing the display, 382
    restrictions on gadgets, 411
    side effects, 412
  keymap - key numbers over hex 67, 818
  preferences - printer device, 334
  Text - don't assume Topaz-8, 672


Checkmark Index

Checkmark
  custom (for menus), 107
  menu items, 181
  menus, 170
  mutual exclude, 182
  positioning, 182
  size, 182
  tracking, 182, 185


Chip Memory Index

Chip Memory, 11, 288, 431, 456
  Image data, 227
  in Border structure, 237
  sprite data, 274
  with Image data, 226


Clipping Index

Clipping
  in area fill, 590
  in filling, 590
  in line drawing, 588
  requester, 204


Clipping Rectangles Index

Clipping Rectangles
  in layers, 704, 711, 712, 719
  modifying regions, 722


Color Index

Color
  ColorMap structure, 553
  flickering, 633
  full screen palette, 47, 59
  in Border structure, 237
  in dual playfield mode, 545
  in flood fill, 590
  in hold-and-modify mode, 580-581
  in the Image structure, 227-228
  Intuition text, 242
  of individual pixel, 587
  Playfield and VSprites, 633
  relationship to bitplanes, 539
  relationship to depth of BitMap, 543
  Simple Sprites, 618
  single-color raster, 593
  specifying for screen, 47, 65
  sprites, 546
  transparency, 626
  VSprite, 626
  with plane pick, 230
  with PlaneOnOff, 230


Commodities Index

Commodities
  ActivateCxObj(), 731
  AddIEvents(), 749
  ArgArrayDone(), 735
  ArgArrayInit(), 735
  ArgInt(), 735
  ArgString(), 735
  AttachCxObj(), 737
  ClearCxObjError(), 742
  connecting CxObjects, 737
  controller commands, 734
  controlling CxMessages, 746
  custom CxObject function arguments, 744
  custom CxObjects, 744
  custom input handlers, 727
  CxBroker(), 730
  CxCustom(), 744
  CxDebug(), 745
  CxFilter(), 736
  CxMessage, 729, 731
  CxMessage types, 731
  CxMsgData(), 731
  CxMsgID(), 731
  CxMsgType(), 731
  CxObject, 729, 729-730 - broker, 730
  CxObject error values, 742
  CxObject errors, 742
  CxObjError(), 742
  CxSender(), 741
  CxSignal(), 743
  CxTranslate(), 741
  debug CxObjects, 745
  DeleteCxObj(), 734
  DeleteCxObjAll(), 734
  DisposeCxMsg(), 746
  DivertCxMsg(), 746
  EnqueueCxObj(), 737
  error codes, 731
  event classes, 736
  Examples
    custom CxObject for swapping mouse buttons, 744
    hotkey pop-up shell commodity, 750
    input description strings, 737
    monitoring user inactivity, 747
    opening a broker commodity, 731
    simple hot key commodity, 738
  filtering events, 736
  FreeIEvents(), 749
  function reference, 753
  generating new input events, 749
  input description strings, 736
  InputXpression.ix_QualSame bits, 745
  InsertCxObj(), 737
  InvertString(), 749
  IX structure, 745
  IX.ix_QualSame bits, 745
  ParseIX(), 746
  RemoveCxObj(), 737
  requiring uniqueness, 743
  RouteCxMsg(), 746
  sender CxObjects, 741
  SetCxObjPri(), 737
  SetFilter(), 746
  SetFilterIX(), 746
  SetTranslate(), 742
  shutting down a commodity, 734
  signal CxObjects, 743
  struct InputXpression, 745
  struct NewBroker, 730
  tool types, 734
  translate CxObjects, 741
  uniqueness, 743
  using the IX structure, 746


Compatibility Index

Compatibility
  international, 922
  open screen, 43
  open window, 80
  with 2.0, 923


Copper Index

Copper, 65
  changing colors, 553
  display instructions, 555
  in drawing VSprites, 633
  in interlaced displays, 579
  MakeVPort(), 560
  MrgCop(), 555
  programming, 602


Copper list Index

Copper list, 603
  deallocation, 560
  merge screens, 66
  update screen's, 66
  user, 602 - clipping of, 603


D Index

DAC_BINDTIME, 761
DAC_BOOTTIME, 761
DAC_BUSWIDTH, 761
DAC_BYTEWIDE, 761
DAC_CONFIGTIME, 761
DAC_NEVER, 761
DAC_NIBBLEWIDE, 761
DAC_WORDWIDE, 761
Damage List - in layers, 711, 719
Dates -->
dbf(), 888
DBufPacket structure, 645
DEADEND_ALERT, 220, 221
DeadKeyConvert(), 262, 277
Deadlock -->
Deallocate(), 462
Deallocate - region, 720
Deallocation - memory, 455
Debugging, 921
Debug.lib, 886
Default - pens in screen, 55, public screen, 59
Default Public Screen, 52
DeleteCxObj(), 734
DeleteCxObjAll(), 734
DeleteDiskObject(), 353
DeleteExtIO(), 886
DeleteLayer(), 710
DeleteMsgPort(), 502
DeletePort(), 254, 502, 887
DeleteStdIO(), 887
DeleteTask(), 467, 887
Delta Move - mouse coordinates, 268
Denise, 11
Depth - BitMap, 543, in VSprite structure, 625
Depth Gadget -->
Detail Pen, 106
DETAILPEN, 57
Determining Chip Versions, 537
Device -->
Device (Exec), 435
DHeight - in ViewPort, 542, 550, in ViewPort display memory, 549
DiagArea structure, 761
DimensionInfo structure, 543
DISABLE, 519, 530 - mutual-exclusion mechanism, 519
DISABLE macro, 470
Disable(), 470, 480, 520, 530
Disabling - interrupts, 470, 520, 530, maximum disable period, 471
Disk - inserted message, 262, removed message, 262
DiskFontHeader structure, 699
diskfont.library - see Text
DisownBlitter(), 599, 599, 612
Dispatcher, 305
Display Clip, 40, 46, 49, 59, 61, 62, 86 - default, 63
Display Colors, 536
Display Database, 20 - display limitations, 47, display mode, 47
Display Modes, 47, 536, 545 - screens, 37
Display Requirements - Table, 536
Display width - affect of overscan on, 535, effect of resolution on, 547
DisplayAlert(), 221, 222
DisplayBeep(), 75, 204
DisplayClip, 541
DisplayID, 59
DisplayInfo - handle, 564
DisplayInfo structure, 553, 567
DisplayInfoHandle, 566, 567
DisposeCxMsg(), 746
DisposeObject(), 295, 330
DisposeRegion(), 720
DivertCxMsg(), 746
DMA - displaying the View, 555, playfield, 543
DoCollision(), 646, 668
DoIO(), 447, 449
DoMethod(), 302, 330, 890
DoMethodA(), 302, 330, 890
DOS - compatibility, 925, problems, 917
DOS Commands - executing, 20
DosEnvc structure, 760
DoSuperMethod(), 310, 330, 890
DoSuperMethodA(), 308, 310, 330, 890
Dotted lines, 585
Double Click - definition, 265, right mouse button, 202, 210
Double Menu Requester, 210
Double-buffering - allocations for, 579, Copper in, 579, Copper lists, 629
DoubleClick(), 269, 282
Drag - definition, 265, enable gadget, 109
Drag Bar - cancel window drag, 77, screens, 39, window, 77
Drag Select, 267 - menus, 169
Draw(), 588, 611 - in line drawing, 588, multiple line drawing, 589
DrawBevelBox(), 403, 413
DrawBevelBoxA(), 403, 413
DrawBorder(), 224, 224, 235, 237, 244
DrawCircle(), 588, 611
DrawEllipse(), 588, 611
DrawerData structure, 352
DrawGList(), 288, 642, 668 - preparing the GELS list, 628
DrawImage(), 224, 224, 225, 226, 227, 244
DrawInfo structure -->
Drawing -->
Drawing pens - color, 584, current position, 587
DrawMode -->
DRI_VERSION, 55
DSKBLK Interrupts, 519
DSKSYNC Interrupts, 519
Dual playfield -->
DUALPF, 70, 545
DWidth - in ViewPort, 542, 550, in ViewPort display memory, 549
DxOffset - effect on display window, 550, in ViewPort display memory, 549
DyOffset - effect on display window, 550, in ViewPort display memory, 549


Dates Index

Dates, 881
  example, 882
  function reference, 884
  functions, 881
  structure, 881


Deadlock Index

Deadlock
  verify messages, 219, 250, 263
  with layers, 708
  with menus, 188
  with menuverify, 216


Depth Gadget Index

Depth Gadget
  enable gadget, 109
  keyboard qualifier, 78
  screens, 74
  window, 78


Device Index

Device
  asynchronous IORequests, 449
  closing, 450
  commands, 448
  device base address pointer, 452
  device names, 447
  device specific command prefixes, 448
  devices with functions, 452
  error checking, 450
  error indications, 450
  gracefully exiting, 451
  opening, 447
  passing IORequests, 447
  problems, 917
  romtag, 444
  sharing library bases, 467
  standard Exec commands, 448
  synchronous IORequests, 449
  task structure fields for, 466


DrawInfo structure Index

DrawInfo structure, 47, 55, 56, 58, 59, 106, 225, 238
  dri_Font, 58
  dri_Pens, 57, 107
  dri_Version, 55


Drawing Index

Drawing
  and Intuition text, 240
  changing part of drawing area, 594
  clearing memory, 592
  colors, 584
  in complement mode, 585
  lines, 588
  memory for, 582
  modes, 585
  moving source to destination, 595
  pens, 584
  pixels, 587
  shapes, 590
  turning off outline, 590
  with Image structure, 225, 227


DrawMode Index

DrawMode
  and Intuition text, 239
  border, 234
  in Border structure, 237
  in flood fill, 591
  in stencil drawing, 594
  Intuition text, 242
  with BltTemplate(), 596


Dual playfield Index

Dual playfield
  bitplanes, 578
  color map, 554
  colors, 545
  priority, 578
  with screens, 70


E Index

EasyRequest(), 112, 188, 201, 211, 215, 216, 216-217, 218, 219, 222
EasyRequestArgs(), 112, 215-216, 222
EasyStruct structure -->
ECS, 11 - and genlock, 607, determining chip versions, 537
Emergency - message, 220
ENABLE, 530
ENABLE macro, 470
Enable(), 470, 480, 520, 530
End gadget - requester, 206
EndNotify(), 336, 344
EndRefresh(), 95, 97, 97, 110, 115, 128, 244, 261, 721
EndRequest(), 112, 203, 206, 222
EndUpdate(), 128, 711, 721
Enhanced Chip Set, 11
Enqueue(), 492, 498
EnqueueCxObj(), 737
EntryHandler(), 797, 798, 810
EO_BADFORMAT, 160
EO_BIGCHANGE, 160
EO_CLEAR, 160
EO_DELBACKWARD, 160
EO_DELFORWARD, 160
EO_ENTER, 160
EO_INSERTCHAR, 160
EO_MOVECURSOR, 160
EO_NOOP, 160
EO_REPLACECHAR, 160
EO_RESET, 160
EO_SPECIAL, 160
EO_UNDO, 160
EraseImage(), 225
EraseRect(), 225
Error -->
Errors, 915
Escape Sequences, 90 - ANSI, 248, console device, 248
Event Loop - IDCMP, 250, 251
Events, 481
Examples -->
Exception signal, 473
Exceptions -->
Exec -->
ExecBase Structure, 518, 520
exec/errors.h, 450
ExitHandler(), 797, 810
Expansion -->
ExpansionRom structure, 757
Expunge vector, 437
Extended - new screen structure, 46
EXTER, 519, 525, 526
EXTER Interrupts, 519, 525
ExternFont(), 682
ExtNewScreen structure, 43, 45
ExtNewWindow structure, 80, 106
Extra-Half-Brite - Clearing Plane 6, 583, Setting Plane 6, 583
Extra-Half-Brite mode, 580
EXTRA_HALFBRITE, 545-546


EasyStruct structure Index

EasyStruct structure, 216
  es_Flags, 216
  es_GadgetFormat, 216, 217
  es_StructSize, 216
  es_TextFormat, 216, 217
  es_Title, 216


Error Index

Error
  display, 204
  incorrect custom chips, 45
  monitor not available, 45
  no Chip memory, 45
  no memory, 45
  open screen, 45
  screen name collision, 45
  unknown mode, 45


Examples Index

Examples
  Animation - complete bobs example, 642
  ASL
    custom hook function, 426
    file requester with multiple selection, 419
    file requester with pattern matching, 419
    font requester, 424
    simple file requester, 417
  Boopsi
    custom gadget class, 323
    custom model subclass, 312
    Talk2boopsi.c, 299
  Commodities
    custom CxObject for swapping mouse buttons, 744
    hotkey pop-up shell commodity, 750
    input description strings, 737
    monitoring user inactivity, 747
    opening a broker commodity, 731
    simple hot key commodity, 738
  compiler flags used, 12
  Exec
    building and reading a list, 495
    calling a library function, 437
    Ctrl-C Processing, 433
    library source code, 909
    open an Exec Library, 438
    opening a library (in assembler),
    opening a library (in C),
    semaphores, 514
    signals.c, 484
    simpletask.c, 467
    task creation, 467
    task list, 471
    task trap, 475
    using an Exec device, 453
  Expansion
    DiagArea in RAM, 762
    list AUTOCONFIG boards, 757
    sample autoboot code, 763
    sample AUTOCONFIG ROM, 767
  Gadgets
    creating a simple gadget, 120
    scroller support functions, 144
    slider support functions, 145
    string gadget with edit hooks, 162
    updating a string gadget, 151
  GadTools
    complete GadTools example, 406
    gadget message filtering, 403
    NewMenu structure, 369
    slider gadget setup, 393
    using CreateContext(), 400
    using gadgets, 383
    using the menu system, 372
    using VisualInfo functions, 399
  graphics, 571
    animtools.c, 661
    RGBBoxes.c, 556
    UserCopperExample.c, 603
  IFFParse - ClipFTXT.c, 803, Sift.c, 807
  Intuition
    allocremember.c, 285
    blocking input with a requester, 207
    CloseWindowSafely() for shared IDCMPs, 255
    compleximage.c, 231
    custompointer.c, 275
    displayalert.c, 221
    easyintuition33.c, 34
    easyintuition37.c, 32
    easyrequest.c, 217
    IDCMP event loop, 251
    input event loop, 31
    intuitext.c, 241
    rawkey.c, 277
    read mouse, 269
    remembertest.c, 286
    shadowborder.c, 235
    simpleimage.c, 228
  Keymap
    AskKeyMap(), 813
    German keymap excerpt, 824
    mapping RAWKEY events to character sequences, 814
    mapping text to keypresses, 816
    SetKeyMap(), 813
  Menus - menu layout, 192, simple menu, 172
  Messages - skeleton of waiting for a signal, 434
  Preferences
    prefs file change notification, 336
    read and parse IFF Prefs, 341
  Screens
    cloning a public screen, 59
    double buffered screen, 67
    dual playfield screen, 70
    finding the Workbench screen, 51
    opening a new look screen, 42
    opening screens compatibly, 44
    using a public screen, 56
  Text
    list available fonts, 690
    measuring and fitting text, 678
    render a text file to a window, 684
    sample font source, 699
    skeleton for opening a font, 671
    skeleton for selecting aspect ratio, 683
    skeleton for soft styling a font, 675
    skeleton using AvailFonts(), 689
  Windows
    calculating window border size, 89
    opening a window with tags, 80
    superbitmap window, 99
    using public screens, 83
    window sized to the visible display, 86
  Workbench
    AppIcon, 360
    AppMenuItem, 361
    AppWindow, 363
    icon creation and parsing, 355
    parse Workbench and CLI args, 349


Exceptions Index

Exceptions, 473
  680x0, 473
  Exec, 473
  SetExcept(), 473
  synchronous, 474
  tc_ExceptCode, 473
  tc_ExceptData, 473


Exec Index

Exec
  CloseLibrary(), 436
  Device, 435
  examples
    building and reading a list, 495
    calling a library function, 437
    Ctrl-C Processing, 433
    library source code, 909
    Open an Exec Library, 438
    opening a library (in assembler),
    opening a library (in C),
    semaphores, 514
    task signalling, 484
    tasklist.c, 471
    trap_c.c, 475
  introduction to,
  Kickstart version, 435
  Library, 435 - version, 435
  Library Vector Offset - see LVO
  LINKLIB macro, 438
  LVO, 436, 437
  MEMF_CHIP, 14
  MEMF_FAST, 14
  Messages - interprocess communication, 433
  multitasking, 429
  OpenLibrary(), , , 435
  process, 430
  quantum, 430
  SetSignal(), 433
  Signals, 432
  struct Library, 436, 441
  struct Task, 465
  task, 429, 430
  Wait(), 30, 31, 432


Expansion Index

Expansion, 924
  AddBootNode(), 759, 776
  AddDosNode(), 759, 776
  autoboot - BOOT, 768, DIAG, 761, ROMTAG INIT, 768
  AUTOCONFIG, 755 - hardware manufacturer number, 756
  ConfigDev flags, 756
  device drivers, 758
  DiagArea flags, 761
  disk based expansion board drivers, 758
  examples
    DiagArea in RAM, 762
    list AUTOCONFIG boards, 757
    sample autoboot code, 763
    sample AUTOCONFIG ROM, 767
  expansion board drivers - Autoboot, 760, ROM based, 760
  FileSysRes, 775
  FileSysResource, 769
  FindConfigDev(), 756, 757, 776
  GetCurrentBinding(), 759, 776
  Hardware Manufacturer Number, 756
  InitResident(), 759
  MakeDosNode(), 759, 776
  ObtainConfigBinding(), 759
  ReleaseConfigBinding(), 759
  RigidDiskBlock, 769, - see also "SCSI Device" in RKM:Devices
    BadBlockBlock, 772
    Environment, 773
    FileSysHeaderBlock, 774
    LoadSegBlock, 775
    PartitionBlock, 773
  RigidDiskBlock specification, 770
  SetCurrentBinding(), 759, 776
  struct ConfigDev, 756
  struct CurrentBinding, 759
  struct DiagArea, 761
  struct DosEnvc, 760
  struct ExpansionRom, 757


F Index

Fast floating-point library, 833
Fast Memory, 11, 431, 456
FastRand(), 887
FCH_ID, 698
fclose(), 887
fgetc(), 887
FgPen -->
File - requester, 20
FileRequester structure, 416
FileSysResource, 769
FILF_DOMSGFUNC, 425
FILF_DOWILDFUNC, 425
FILF_MULTISELECT, 419
FILF_NEWIDCMP, 419
FILF_PATGAD, 419
FILF_SAVE, 419
FILLPEN, 58
fillrectclass, 297
FILLTEXTPEN, 58
Filter - IDCMP messages, 250
FinalPC, 463
FindCollection(), 785, 810
FindConfigDev(), 756, 757, 776
FindDisplayInfo(), 567, 567, 611
FindLocalItem(), 791, 810
FindName(), 493, 498, 520
FindPort(), 502, 520
FindProp(), 344, 783, 810
FindPropContext(), 798, 810
FindSemaphore(), 514, 515
FindTask(), 49, 480, 520
FindToolType(), 354
First-In-First-Out (FIFO), 492, 499
Flags -->
Flicker - menu items, 181
Flood(), 590, 611
Follow mouse, 273
FONF_BACKCOLOR, 423
FONF_DOMSGFUNC, 425
FONF_DOWILDFUNC, 425
FONF_DRAWMODE, 423
FONF_FIXEDWIDTH, 423
FONF_FRONTCOLOR, 423
FONF_STYLES, 423
Font -->
FontContents structure, 698
FontContentsHeader structure, 698
FontExtent(), 155, 676
FontPrefs structure, 338
FontRequester structure, 422
Forbid(), 110, 366, 470, 480, 520
Foreground pen, 584
Format String - easy requester, 217
fpa(), 888
FPF_DESIGNED, 671
FPF_DISKFONT, 671
FPF_PROPORTIONAL, 671
FPF_REVPATH, 671
FPF_ROMFONT, 671
FPF_TALLDOT, 671
FPF_WIDEDOT, 671
fprintf(), 887
fputc(), 887
fputs(), 887
frameiclass, 297
frbuttonclass, 298
Free memory, 463
FreeAslRequest(), 416
FreeClass(), 330
FreeColorMap(), 560, 610
FreeCprList(), 560, 610
FreeDiskObject(), 353
FreeEntry(), 459, 462
FreeGadgets(), 382, 413
FreeGBuffers(), 668
FREEHORIZ, 147
FreeIEvents(), 749, 889
FreeIFF(), 344, 810
FreeLocalItem(), 799, 810
FreeMem(), 284, 431, 455, 457
FreeMenus(), 377, 413
FreeRaster(), 560, 610
FreeRemember(), 283, 284, 284-285, 289
FreeScreenDrawInfo(), 56, 76, 244
FreeSignal(), 476, 482, 485
FreeSprite(), 620, 668
FreeSysRequest(), 219, 222
FreeTrap(), 476, 480
FreeVec(), 431
FREEVERT, 147
FreeVisualInfo(), 413
FreeVPortCopLists(), 560, 610
FSF_BOLD, 671
FSF_EXTENDED, 671
FSF_ITALIC, 671
FSF_UNDERLINED, 671
FTXT, 799
FULLMENU(), 178
FULLMENUNUM(), 200


FgPen Index

FgPen
  in complement mode, 585
  in flood fill, 590, 591
  in JAM1 mode, 584
  in line drawing, 588
  in RastPort, 584
  in rectangle fill, 592
  with BltTemplate(), 596


Flags Index

Flags
  menu item, 191
  new window, 111
  window, 109
  with BNDRYOFF() macro, 590


Font Index

Font, 930
  in easy requester, 215
  in screen, 59
  Intuition text, 243
  life, 58
  menu layout, 179
  outline, 19
  preferred, 48
  preferred monospace, 48
  requester, 20
  SA_Font, 58
  SA_SysFont, 58
  scaling, 19
  screen, 47, 58
  system font in screen, 48
  window, 85
  window title, 107


G Index

GACT_ALTKEYMAP, 137
GACT_BOOLEXTEND, 137
GACT_BOOLEXTENDED, 138
GACT_BOTTOMBORDER, 126, 137
GACT_ENDGADGET, 136, 206
GACT_FOLLOWMOUSE, 131, 136, 258, 273
GACT_IMMEDIATE, 123, 124, 131, 136, 259
GACT_LEFTBORDER, 126, 137
GACT_LONGINT, 133, 137, 150, 160
GACT_RELVERIFY, 123, 124, 131, 136, 259
GACT_RIGHTBORDER, 126, 136
GACT_STRINGCENTER, 137, 154
GACT_STRINGEXTEND, 137
GACT_STRINGLEFT, 137, 154, 155
GACT_STRINGRIGHT, 137, 154
GACT_TOGGLESELECT, 136, 138
GACT_TOPBORDER, 126, 137
Gadget -->
Gadget structure -->
Gadget Toolkit - see GadTools
gadgetclass, 292, 297
GadgetInfo structure, 318
GadTools -->
Gameport device, 925
GA_Disabled, 386, 387, 389, 390, 392, 394, 396
GA_Immediate, 392, 394
GA_RelVerify, 301, 392, 394
GA_TabCycle, 387
GA_Underscore, 404
GELGONE Flag - in VSprite structure, 624
GELS - introduction, 613, types, 614
GelsInfo, 583
GelsInfo structure, 632
Genlock, 607, 607 - control, 20
GetAttr(), 296, 301, 330
GetCC(), 478
getchar(), 887
GetColorMap(), 47, 553, 560, 564, 610
GetCurrentBinding(), 759, 776
GetDefaultPubScreen(), 50, 76
GetDefDiskObject(), 353
GetDefPrefs(), 332, 344
GetDiskObject(), 353
GetDiskObjectNew(), 353
GetDisplayInfoData(), 543, 567, 611
GetGBuffers(), 668
GetMsg(), 434, 505, 520
GetPrefs(), 262, 332, 344
GetRexxVar(), 888
GetRGB4(), 554
GetScreenData(), 51, 59, 75, 76
GetScreenDrawInfo(), 56, 59, 76, 244
GetSprite(), 619, 668
GetVisualInfo(), 398, 413
GetVisualInfoA(), 398, 413
GetVPModeID(), 59, 566, 611
GFLG_DISABLED, 130, 135, 321
GFLG_GADGHBOX, 127, 128, 129, 134
GFLG_GADGHCOMP, 127, 127, 134
GFLG_GADGHIMAGE, 127, 128, 129, 134
GFLG_GADGHNONE, 127, 134
GFLG_GADGIMAGE, 122, 123, 123, 128, 134
GFLG_RELBOTTOM, 125, 128, 135
GFLG_RELHEIGHT, 125, 128, 135
GFLG_RELRIGHT, 124-125, 128, 135
GFLG_RELVERIFY - Boopsi gadgets, 301
GFLG_RELWIDTH, 125, 128, 135
GFLG_SELECTED, 135
GFLG_STRINGEXTEND, 135, 155, 157
GFLG_TABCYCLE, 135, 154
GfxAssociate(), 551, 611
GfxBase Structure, 243 - DefaultFont, 58, 85, 241, 243
GfxFree(), 551, 611
GfxLookUp(), 551
GfxNew(), 551, 611
Ghosted - menus, 185
GimmeZeroZero -->
GMR_GADGETHIT, 320
GMR_MEACTIVE, 321
GMR_NEXTACTIVE, 321
GMR_NOREUSE, 321
GMR_PREVACTIVE, 321
GMR_REUSE, 321
GM_GOACTIVE, 318, 320
GM_GOINACTIVE, 318, 322
GM_HANDLEINPUT, 318, 321
GM_HITTEST, 318, 320
GM_RENDER, 318, 319
gpGoInactive structure, 322
gpHitTest structure, 320
gpInput structure, 320
gpRender structure, 319
Graphics -->
graphics.library - see also Text
GREDRAW_REDRAW, 319
GREDRAW_TOGGLE, 319
GREDRAW_UPDATE, 319
groupgclass, 297
GTCB_Checked, 389
GTCY_Active, 390
GTCY_Labels, 390
GTIN_MaxChars, 387
GTIN_Number, 387
GTLV_Labels, 394
GTLV_ReadOnly, 395
GTLV_ScrollWidth, 395
GTLV_Selected, 395
GTLV_ShowSelected, 395
GTLV_Top, 395
GTMENU_INVALID, 375
GTMENUITEM_USERDATA(), 372
GTMENU_NOMEM, 375
GTMENU_TRIMMED, 375
GTMENU_USERDATA(), 372
GTMN_FrontPen(), 374
GTMN_FullMenu, 374
GTMN_Menu, 376
GTMN_SecondaryError, 375
GTMN_TextAttr, 375, 376
GTMX_Active, 389
GTMX_Labels, 389
GTMX_Spacing, 390
GTNM_Border, 397
GTNM_Number, 397
GTPA_Color, 396
GTPA_ColorOffset, 396
GTPA_Depth, 396
GTPA_IndicatorHeight, 396
GTPA_IndicatorWidth, 396
GTSC_Arrows, 394
GTSC_Top, 393
GTSC_Total, 393
GTSC_Visible, 393
GTSL_DispFunc, 392
GTSL_Level, 391
GTSL_LevelFormat, 391
GTSL_LevelPlace, 391
GTSL_Max, 391
GTSL_MaxLevelLen, 391
GTSL_Min, 391
GTST_MaxChars, 387
GTST_String, 386
GTTX_Border, 397
GTTX_CopyText, 397
GTTX_Text, 397
GTYP_BOOLGADGET, 133, 138
GTYP_CUSTOMGADGET, 133
GTYP_GZZGADGET, 89, 93, 133, 136
GTYP_PROPGADGET, 133
GTYP_REQGADGET, 133, 206, 212
GTYP_STRGADGET, 133, 154
GT_BeginRefresh(), 402, 413
GT_EndRefresh(), 402, 413
GT_FilterIMsg(), 402, 413
GT_GetIMsg(), 381, 413
GT_PostFilterIMsg(), 402, 413
GT_RefreshWindow(), 401, 413
GT_ReplyIMsg(), 381, 413
GT_SetGadgetAttrs(), 385, 413
GT_SetGadgetAttrsA(), 385, 413
GUI - see Boopsi


Gadget Index

Gadget, 318 - see Also BOOPSI and GadTools
  actions with SGH_KEY, 161
  ActivateGadget(), 150, 166, 321
  activating a string gadget, 150
  Activation flags, 123-124, 126, 131, 136-137, 154
  active gadget, 323
  AddGadget(), 166
  AddGList(), 122, 129, 166
  adding a gadget, 121
  adjusting borders, 126
  alternate border, 118, 127, 128
  alternate image, 118, 127, 128
  and requester, 204
  Auto-Knob for proportional gadgets, 143
  BeginRefresh(), 128
  BeginUpdate(), 128
  boolean gadgets, 129
  boolinfo flags, 139
  border gadgets, 126
  Border Structure, 128
  box gadget highlighting, 127, 128
  button gadget, 118
  Caveats
    do not share knob imagery, 143
    do not use image lists for knobs, 143
    GimmeZeroZero window border, 136
    imagery and the selection box, 124
    mouse tracking with boolean gadgets, 136
  close gadget, 119
  complement gadget highlighting, 127, 127
  custom gadgets, 166
  defined, 28
  depth gadget, 119
  disabling, 118, 130
  down, 268
  down message, 259
  drag gadget, 119
  enabling, 118, 130
  EndRefresh(), 128
  EndUpdate(), 128
  Examples
    creating a simple gadget, 120
    scroller support functions, 144
    slider support functions, 145
    string gadget with edit hooks, 162
    updating a string gadget, 151
  FontExtent(), 155
  gadget flags, 122, 124, 127, 128, 128, 134, 154, 157
  gadget imagery, 122
  Gadget Structure, 119
  GadgetID, 134
  gadgets without imagery, 123
  GFLG_DISABLED, 321
  ghosted - see Gadgets disabling
  GMR_MEACTIVE, 321
  GMR_NEXTACTIVE, 321
  GMR_NOREUSE, 321
  GMR_PREVACTIVE, 321
  GMR_REUSE, 321
  GM_GOINACTIVE, 322
  Help key in string gadgets, 158
  highlighting, 118
  highlighting gadgets, 127
  highlighting mutual exclude, 139
  hit-select boolean gadget, 138
  IDCMP Messages, 123-124, 128, 131
  Image Structure, 128
  imageless gadgets for mouse tracking, 123
  implemention of, 318
  in borders, 932
  in new window, 107
  in requester, 204, 206
  in window border, 93
  integer gadget, 150
  Intuition Message classes, 119
  Knob on proportional gadgets, 142
  left mouse button, 118
  Methods, 318
  modifying gadgets, 122
  ModifyProp(), 166
  mutually exclusive, 140
  NewModifyProp(), 147, 148, 166
  ObtainGIRPort(), 323
  OffGadget(), 130, 166
  OnGadget(), 130, 166
  position, 124
  PropInfo flags, 140, 147
  proportional gadget, 118, 140
  proportional gadget container, 142
  proportional gadget increment, 144
  proportional gadget knob, 142
  RefreshGadgets(), 166
  RefreshGList(), 128, 129, 130, 166
  refreshing gadgets, 128
  relative position, 124
  relative size, 124
  ReleaseGIRPort(), 323
  RemoveGadget(), 166
  RemoveGList(), 122, 166, 322
  removing a gadget, 121
  screen gadgets, 119
  Scroller, 141, 141
  select box size, 125
  select button, 118
  SetEditHook(), 166
  SGWork editing actions, 160
  SGWork editing operations, 160
  size gadget, 119, 124
  Slider, 141, 142
  SpecialInfo, 134
  string gadget, 118, 148
  string gadget editing, 158
  string gadget modes, 157
  string gadget with an alternate keymap, 156
  struct BoolInfo, 139
  struct Border, 123
  struct Gadget, 132
  struct IntuiMessage, 119
  struct IntuiText, 123
  struct PropInfo, 143, 144, 147
  struct SGWork, 159
  struct StringExtend, 157
  struct StringInfo, 154, 155
  system gadgets, 77, 91, 119
  text gadget, 118
  text justification, 154
  toggle-select boolean gadget, 138
  types of gadgets, 133, 138
  up, 268
  up message, 259
  UserData, 134
  using relative positioning, 125
  window gadgets, 119
  zoom gadget, 119


Gadget structure Index

Gadget structure, 132, 224, 352
  1.3 compatible usage, 19
  activation, 93, 206
  GadgetType, 206, 212


GadTools Index

GadTools, 192, 367
  BUTTON_KIND
    GA_Disabled, 386, 387
    GA_TabCycle, 387
    GTIN_MaxChars, 387
    GTIN_Number, 387
    GTST_MaxChars, 387
    GTST_String, 386
    STRINGA_ExitHelp, 387
    STRINGA_Justification, 387
    STRINGA_ReplaceMode, 387
  caveats
    GadTools enforces Intuition limits, 375
    GT_SetGadgetAttrs() and GT_BeginRefresh(), 386
    PLACETEXT with GENERIC_KIND gadgets, 398
    post-processing, 368
    preserve bits set by CreatsGadget(), 398
    refreshing the display, 382
    restrictions on gadgets, 411
    side effects, 412
  CHECKBOX_KIND
    GA_Disabled, 389
    GTCB_Checked, 389
  controlling gadgets from the keyboard, 404
  CreateContext(), 399
  CreateGadget(), 380
  CreateMenus(), 374
  CreateMenusA(), 374
  creating gadgets, 380
  CYCLE_KIND
    GA_Disabled, 390
    GTCY_Active, 390
    GTCY_Labels, 390
  DrawBevelBox(), 403
  DrawBevelBoxA(), 403
  examples
    complete GadTools example, 406
    gadget message filtering, 403
    NewMenu structure, 369
    slider gadget setup, 393
    using CreateContext(), 400
    using gadgets, 383
    using the menu system, 372
    using VisualInfo functions, 399
  features of, 368
  FreeGadgets(), 382
  FreeMenus(), 377
  function descriptions, 413
  gadget types, 378, 386
    button, 378, 386
    checkboxes, 378, 389
    cycle, 378, 390
    generic gadget, 398
    integer, 378, 386
    listviews, 378, 394
    mutually exclusive, 378, 389
    numeric-display, 378, 397
    palette, 378, 396
    scrollers, 378, 393
    sliders, 378, 391
    string, 378, 386
    text-display, 378, 397
  gadgets, 378
  GetVisualInfo(), 398
  GetVisualInfoA(), 398
  GTMENUITEM_USERDATA(), 372
  GTMENU_USERDATA(), 372
  GTMN_FrontPen(), 374
  GTMN_TextAttr, 375
  GT_BeginRefresh(), 402
  GT_EndRefresh(), 402
  GT_FilterIMsg(), 402
  GT_GetIMsg(), 381
  GT_PostFilterIMsg(), 402
  GT_RefreshWindow(), 401
  GT_ReplyIMsg(), 381
  GT_SetGadgetAttrs(), 385
  GT_SetGadgetAttrsA(), 385
  handling gadget messages, 381
  IDCMP flags, 382
  implementing gadget keyboard equivalents, 404
  language-sensitive menus, 378
  LayoutMenuItems(), 376
  LayoutMenuItemsA(), 376
  LayoutMenus(), 375
  LayoutMenusA(), 375
  LISTVIEW_KIND
    GTLV_Labels, 394
    GTLV_ReadOnly, 395
    GTLV_ScrollWidth, 395
    GTLV_Selected, 395
    GTLV_ShowSelected, 395
    GTLV_Top, 395
    LAYOUTA_Spacing, 395
  menu layout, 180
  menus, 368
  menus and intuimessages, 377
  minimal IDCMP_REFRESHWINDOW processing, 402
  modifying gadgets - struct, 385
  MX_KIND
    GTMX_Active, 389
    GTMX_Labels, 389
    GTMX_Spacing, 390
  NUMBER_KIND
    GTNM_Border, 397
    GTNM_Number, 397
  PALETTE_KIND
    GA_Disabled, 396
    GTPA_Color, 396
    GTPA_ColorOffset, 396
    GTPA_Depth, 396
    GTPA_IndicatorHeight, 396
    GTPA_IndicatorWidth, 396
  programming gadgets, 378
  restrictions on menus, 377
  reusing a NewGadget structure, 401
  SCROLLER_KIND
    GA_Disabled, 394
    GA_Immediate, 394
    GA_RelVerify, 394
    GTSC_Arrows, 394
    GTSC_Top, 393
    GTSC_Total, 393
    GTSC_Visible, 393
    PGA_Freedom, 394
  SLIDER_KIND
    GA_Disabled, 392
    GA_Immediate, 392
    GA_RelVerify, 392
    GTSL_DispFunc, 392
    GTSL_Level, 391
    GTSL_LevelFormat, 391
    GTSL_LevelPlace, 391
    GTSL_Max, 391
    GTSL_MaxLevelLen, 391
    GTSL_Min, 391
    PGA_Freedom, 392
    processing IntuiMessages, 392
  struct NewGadget, 379
  struct NewMenu, 370
  TEXT_KIND
    GTTX_Border, 397
    GTTX_CopyText, 397
    GTTX_Text, 397


GimmeZeroZero Index

GimmeZeroZero, 133
  attribute, 110
  border rast port, 105
  clipping alternative, 93
  description, 93
  gadget in border, 89
  mouse position, 105, 273
  offset alternative, 89
  opening, 93
  requester limit, 204
  requester positioning, 93
  use of resources, 93
  window type, 92, 93
  with borderless, 92
  with superbitmap, 96


Graphics Index

Graphics
  display modes, 536
  examples
    Animation tools, 661
    simple ViewPort creation, 556
    User copper list, 603
    WBClone.c, 571
  high level interface, 223
  images, 919
  in windows, 85
  layers locking, 707, 726
  screen data organization, 39
  struct AnimComp, 652
  struct AnimOb, 652
  struct bltnode, 600
  struct RastPort, 581
  text - see Text
  using from Intuition, 223
  with layers, 704


H Index

HAM, 545-546, 580-581
Hardware - differences, 926
Hardware Interrupts, 517
Hardware Sprites - reserving, 632
Height - by inner dimension, 108
Height variable - in VSprite structure, 625
Help - menu, 111, 260
HIGHBOX, 192
HIGHCOMP, 191
HIGHFLAGS, 191
HIGHIMAGE, 190, 192, 225
HIGHITEM, 192
Highlighting - menu item, 191, menus, 169, 169
HIGHLIGHTTEXTPEN, 58
HIGHNONE, 192
HIRES, 545
Hold-and-modify mode, 580
Hook structure, 312
HookEntry.asm, 794
Hooks -->
Hot Spot - mouse, 266
HotKey(), 889


Hooks Index

Hooks, 875
  example, 877
  function, 875
  function reference, 883
  structure, 875
  usage, 876


I Index

ICA_MAP - Boopsi gadgets, 299, icclass, 302
ICA_TARGET, 309 - Boopsi gadgets, 298, 302, icclass, 302
icclass, 292, 297, 302
Icon - creation, 350, parsing, 350
Icon library, 350
IControlPrefs structure, 338
ICSPECIAL_CODE - Boopsi gadgets, 302
IDCMP -->
IDCMP_ACTIVEWINDOW, 91, 176, 261
IDCMP_CHANGEWINDOW, 263
IDCMP_CLOSEWINDOW, 248, 259
IDCMP_DELTAMOVE, 256, 259, 268-269
IDCMP_DISKINSERTED, 262
IDCMP_DISKREMOVED, 262
IDCMP_GADGETDOWN, 119, 123, 124, 259, 268
IDCMP_GADGETUP, 119, 123, 124, 131, 259, 268 - Boopsi gadgets, 301
IDCMP_IDCMPUPDATE, 263 - Boopsi gadgets, 302
IDCMP_INACTIVEWINDOW, 91, 261
IDCMP_INTUITICKS, 74, 258, 262-263
IDCMP_LONELYMESSAGE, 263
IDCMP_MENUBUTTONS, 186
IDCMP_MENUHELP, 111, 178, 179, 258, 260
IDCMP_MENUPICK, 176, 177, 177, 179, 185, 186, 187, 187, 259, 268
IDCMP_MENUVERIFY, 49, 186, 186, 186, 187, 188, 216, 259-260, 263-264
IDCMP_MOUSEBUTTONS, 110, 131, 175, 187, 258, 268, 269
IDCMP_MOUSEMOVE, 93, 109, 124, 131, 256, 258, 259, 268, 269, 273
IDCMP_NEWPREFS, 262, 332
IDCMP_NEWSIZE, 112, 260
IDCMP_RAWKEY, 256, 261-262, 277, 277
IDCMP_REFRESHWINDOW, 97, 110, 128, 261
IDCMP_REQCLEAR, 105, 210, 210, 260
IDCMP_REQSET, 105, 210, 210, 260
IDCMP_REQVERIFY, 211, 260, 263-264
IDCMP_SIZEVERIFY, 91, 250, 261, 263-264
IDCMP_UPDATE, 277
IDCMP_VANILLAKEY, 256, 261, 277
IDCMP_WBENCHMESSAGE, 263
IDNestCnt Counter, 530
IEQUALIFIER_CAPSLOCK, 282
IEQUALIFIER_CONTROL, 282
IEQUALIFIER_LALT, 282
IEQUALIFIER_LCOMMAND, 282
IEQUALIFIER_LEFTBUTTON, 282
IEQUALIFIER_LSHIFT, 282
IEQUALIFIER_MIDBUTTON, 282
IEQUALIFIER_NUMERICPAD, 282
IEQUALIFIER_RALT, 282
IEQUALIFIER_RBUTTON, 282
IEQUALIFIER_RCOMMAND, 282
IEQUALIFIER_REPEAT, 277, 282
IEQUALIFIER_RSHIFT, 282
IFEMPTY, 498
IFF -->
IFFHandle structure, 780
IFFParse -->
IFNOTEMPTY, 498
ILBM, 799
Illegal instruction, 474
Image - menu item, 169, 190, position, 224
Image structure -->
imageclass, 292, 297
ImageData - changing VSprites, 627
ImageData pointer - in VSprite structure, 625
Imagery - in requester, 204, in requester gadgets, 206
Images - see also Boopsi
IM_ITEM, 370
IM_SUB, 370
inheritance, 293, 306, 311
InitArea(), 582, 611
InitBitMap(), 98, 552, 610
InitGels(), 668
InitGMasks(), 668
InitIFF(), 781, 810
InitIFFasClip(), 781, 810
InitIFFasDOS(), 344, 781, 810
InitMasks(), 648, 668
InitRastPort(), 582, 611
InitRequester(), 203, 211, 222
InitResident(), 759
InitSemaphore(), 511, 515
InitStruct(), 462
InitTmpRas(), 583
InitView(), 610, 709
InitVPort(), 553, 610, 709
Input - and Intuition, 245, block with requester, 203, out-of-sync, 920
Input Device, 245, 246 - input stream, 246
Input Event, 323 - menus, 176, mouse, 266, processing menu events, 177
Input Event Loop, 30
Input Focus, 78, 248
Input Handler, 246, 247
Input Stream, 246
InputEvent Structure, 246, 321 - ie_Qualifier, 256
InputPrefs structure, 339
InputXpression structure, 745
Insert(), 492, 498
InsertCxObj(), 737
InstallClipRegion(), 703, 711, 719, 720-721, 723
Instance, 292
Instance data, 293, 308 - initializing, 308
INST_DATA() macro, 309
INT2, 519
INT6, 519
INTB_VERTB, 521
INTEN Interrupts, 519
INTENA, 517, 518
INTENA Register, 517
INTENAR, 521
Interconnection class - see icclass
International Characters - as menu command keys, 184
International compatibility, 922
International strings -->
Interprocess communication, 433, 499
Interrupt stack, 477
Interrupt Structure -->
Interrupts -->
INTREQ, 517, 518
INTREQ Register, 517
INTREQR, 521
IntuiMessage structure -->
IntuiText - in requester, 204, position, 224
IntuiText structure -->
IntuiTextLength(), 241, 243, 244
Intuition -->
Intuition public classes, 297
IntuitionBase Structure, 283, 283-284
INVERSVID, 240, 243, 585
InvertString(), 749, 889
IORequest, 446 - creating, 446
IPL0, 517
IPL1, 517
IPL2, 517
ISDRAWN, 192
IsListEmpt, 498
ISP, 477
Item Number, 177 - terminator, 177
ItemAddress(), 177, 200
ITEMENABLED, 175, 191
ItemFill, 225
ITEMNUM(), 177, 178
ITEMTEXT, 190, 191, 192, 225
itexticlass, 297
IX structure, 745
IXSYM_ALT, 745
IXSYM_CAPS, 745
IXSYM_SHIFT, 745
.info file, 345


IDCMP Index

IDCMP, 31, 247
  application allocated, 249
  Boopsi, 301
  creation, 249
  definition, 90
  discard messages, 113
  Flags, 257
  freeing, 249
  in easy requesters, 215
  input events, 249
  message structure, 250
  queue limits, 113
  requester, 210
  shared, 253-254
  WA_IDCMP tag, 107


IFF Index

IFF, 777
  Chunk, 778
  example file, 780
  FORM, 778-779 - size, 780
  FORM types, 799
  FTXT, 803
  ILBM, 800, 801, 802
  introduction, 778
  Preferences, 338


IFFParse Index

IFFParse, 777
  context stack, 789
  custom chunk handler, 797, 798
  custom stream handler, 793-795, 795
  error handling, 792
  examples
    examining IFF files, 807
    parsing FTXT for the clipboard, 803
  reading files, 784
  streams, 781
  struct ContextNode, 789
  struct IFFHandle, 780
  writing files, 787


Image structure Index

Image structure, 180, 190, 191, 192, 223, 224, 224-225, 225, 353
  bit-plane organization, 227
  calculation of data size, 226
  color computation, 228
  Depth, 226, 231
  Height, 226, 231
  ImageData, 226, 227, 231
  LeftEdge, 226, 240
  NextImage, 226
  PlaneOnOff, 226, 230-231
  PlanePick, 226, 230
  TopEdge, 226, 240
  Width, 226, 231


International strings Index

International strings, 880
  example, 880
  function reference, 883
  functions, 880


Interrupt Structure Index

Interrupt Structure, 520, 521, 521, 525, 527
  is_Data, 521, 524, 525
  is_Node, 525


Interrupts Index

Interrupts, 917
  68000 interrupt request signals, 517
  68000 priority levels, 517
  autovectors, 518
  deferred, 519
  disable, 520
  disabling, 530
  Exceptions, 473
  handlers, 519, 521
  hardware registers, 517
  non-maskable (NMI), 519
  priorities, 519
  server return value, 525
  servers, 519, 525
  software, 527
  Task private, 473


IntuiMessage structure Index

IntuiMessage structure, 119, 247, 250, 256
  Class, 256-257, 257, 268
  Code, 186, 256, 258, 259-260, 261, 268
  ExecMessage, 256
  IAddress, 257, 259, 262, 263
  IDCMPWindow, 257
  Micros, 257
  MouseX, 256, 268, 273
  MouseY, 256, 268, 273
  Qualifier, 256, 261, 282
  Seconds, 257
  SpecialLink, 257


IntuiText structure Index

IntuiText structure, 123, 180, 190, 191, 192, 213, 223, 224, 239, 239-240,
                     240, 243
  BackPen, 239, 242-243
  DrawMode, 239
  FrontPen, 239-240, 242-243
  IText, 240, 241
  ITextFont, 240, 241, 243
  LeftEdge, 240, 240
  NextText, 240, 243
  TopEdge, 240, 240


Intuition Index

Intuition, 619, 927
  3D look, 26
  and other user interface libraries, 24
  BeginRefresh(), 95, 97, 97
  Boopsi - see Boopsi
  Boopsi class reference, 891
  busy pointer, 207
  CloseWindow(), 82
  components of the user interface, 25, 27
  EndRefresh(), 95, 97, 97
  examples
    alert, 221
    blockinput.c, 207
    closewindowsafely.c (for shared IDCMPs), 255
    complex Image drawing, 231
    custom pointer, 275
    easy requester, 217
    input event loop, 31
    IDCMP processing, 251
    Intuition basics (all OS versions), 34
    Intuition basics (Release 2), 32
    Intuition text rendering, 241
    memory functions, 285, 286
    mousetest.c, 269
    raw key processing, 277
    reusing Border structures, 235
    simple Image drawing, 228
  ExtNewWindow structure, 80
  font, 243
  graphics features, 223
  IDCMP, 31
  input event loop, 30, 31
  introduction, 23
  line drawing, 234
  NewWindow structure, 80
  OpenWindow(), 80
  OpenWindowTagList(), 80
  OpenWindowTags(), 80
  QueryOverscan(), 86
  struct EasyStruct, 216
  struct Image, 225
  struct IntuiMessage, 256
  struct IntuiText Structure, 239
  struct Menu, 188
  struct MenuItem, 189
  struct Remember, 285
  struct Requester, 211
  struct Window, 104
  text, 239


J Index

JAM1, 234, 237, 239, 242-243, 585 - with INVERSVID, 585
JAM1 mode - in drawing, 584
JAM2, 239, 242-243, 585
JAM2 mode - in drawing, 584
Justification - menu item text, 190


K Index

KCF_ALT, 820-821
KCF_CONTROL, 820-821
KCF_DOWNUP, 820
KCF_SHIFT, 820-821
KCF_STRING, 820
KCmpStr(), 890
KC_NOQUAL, 820-821
KC_VANILLA, 820-821
Key Mapping, 277
Keyboard -->
Keyboard Layout, 828
Keyboard Qualifier, 282
Keyboard Shortcut - screens, 74
Keymap -->
KeyMap structure, 812
keymap.library, 811
KGetChar(), 890
KGetNum(), 890
Kickstart version, 435
KMayGetChar(), 890
KNOBHIT, 140, 147
KPrintF(), 890
KPutChar(), 890
KPutStr(), 890


Keyboard Index

Keyboard
  and menus, 176
  as alternate to mouse, 280
  menu shortcuts, 184
  qualifiers, 282
  raw key, 277
  repeat queue limit, 108, 114
  Shortcut, 281, 281
  vanilla key, 277
  with easy requesters, 217


Keymap Index

Keymap, 811
  alternate key maps, 821
  AskKeyMap(), 813
  AskKeyMapDefault(), 812
  capsable keys, 822
  caveats - key numbers over hex 67, 818
  dead-class keys, 823
  double-dead keys, 826
  Examples
    AskKeyMap(), 813
    German keymap excerpt, 824
    mapping RAWKEY events to character sequences, 814
    mapping text to keypresses, 816
    SetKeyMap(), 813
  high key map, 818
  KCF_ALT, 820-821
  KCF_CONTROL, 820-821
  KCF_DOWNUP, 820
  KCF_SHIFT, 820-821
  KCF_STRING, 820
  KC_NOQUAL, 820-821
  KC_VANILLA, 820-821
  key map standards, 823
  keymapping, 829
  keymapping qualifiers, 819, 820
  keytype table, 820
  low key map, 818
  MapANSI(), 816
  MapRawKey(), 814
  mouse button events, 831
  qualifiers, 820
  repeatable keys, 822
  SetKeyMap(), 813
  SetKeyMapDefault(), 813
  string output keys, 821
  struct KeyMap, 812


L Index

LACE, 545 - in View and ViewPort, 548
Last-In-First-Out (LIFO), 492
Layer Structure -->
LAYERBACKDROP, 706
Layer_Info - locking, 97
Layer_Info Structure, 284, 704, 707, 707-708, 709, 710
LAYERREFRESH, 261
Layers -->
LAYERSIMPLE, 705
LAYERSMART, 205, 705
LAYERSUPER, 705
Layout - menu, 179
LAYOUTA_Spacing, 395
LayoutMenuItems(), 376, 413
LayoutMenuItemsA(), 376, 413
LayoutMenus(), 375, 413
LayoutMenusA(), 375, 413
Left Amiga Key -->
Left Mouse Button - selection, 266, with alert, 220, with menus, 169
leftmost - in GelsInfo, 624
Length - of Intuition text, 241
Libraries -->
Library -->
Library (Exec) -->
Library structure, 436, 441
Library Vector Offset - see LVO
Limits - change for window, 108, message queue, 113, window size, 85
Line 1010 emulator, 474
Line 1111 emulator, 474
Line drawing, 588
Line pattern, 585
Lines -->
LINKLIB macro, 438
List structure, 490, 520
Lists -->
LoadRGB4(), 554, 610
LoadRGB4CM(), 554
LoadSeg(), 479
LoadView() -->
LocalItemData(), 790, 810
Lock -->
LockIBase(), 283, 289
Locking, 473
LockLayer(), 707, 708
LockLayerInfo(), 707-708, 708
LockLayers(), 708
LockPubScreen(), 50, 51, 53, 53, 54, 56, 59, 75, 76, 83, 108
LockPubScreenList(), 54, 76
Logic equations - blitter, 596
Logical And, 719, 722, 722
Logical Exclusive-Or, 719, 722, 722
Logical Not, 721, 722
Logical Or, 719, 722, 722
Long-frame Copper list, 579
LOWCHECKWIDTH, 182
LOWCOMMWIDTH, 185
LVO, 436, 437


Layer Structure Index

Layer Structure, 214, 284, 704
  bounds, 704
  DamageList, 711, 719
  Flags, 705
  RastPort, 204


Layers Index

Layers, 205, 703, 929
  accessing, 707, 711
  alternative to GimmeZeroZero, 93
  backdrop, 706
  blocking output, 711
  clipping rectangle list, 719
  creating, 710, 710
  creating the workspace, 709
  damage list, 97
  deleting, 710
  introduction, 703
  moving, 711
  opening, 706
  order, 711
  redrawing, 711
  requester, 204
  scrolling, 711
  sizing, 711
  sub-layer operations, 712
  updating, 711
  windows, 170
  with screens, 65


Left Amiga Key Index

Left Amiga Key, 184
  with easy requesters, 217
  with system requesters, 217


Libraries Index

Libraries
  adding, 443
  calling a library function, 437
  relation to devices, 442
  sharing library bases, 467


Library Index

Library
  CLOSE vector, 442
  example library source code, 909
  EXPUNGE vector, 442
  OPEN vector, 442
  RESERVED vector, 442
  romtag, 444


Library (Exec) Index

Library (Exec), 435
  Close vector, 437
  Exec - OpenLibrary(), 435
  Expunge vector, 437
  Library Vector Offset - see LVO
  LVO, 436, 437
  Open vector, 437
  OpenLibrary(), 435
  Reserved vector, 437
  version, 435


Lines Index

Lines
  and Intuition graphics, 234
  multiple, 589
  patterned, 589
  with Intuition graphics, 223


Lists Index

Lists
  empty lists, 494
  prioritized insertion, 492
  scanning a list, 494
  searching by name, 493
  shared lists, 497


LoadView() Index

LoadView(), 66, 610, 709
  effect of freeing memory, 560
  in display ViewPorts, 555


Lock Index

Lock, 916, 917
  CloseWorkBench(), 52
  IntuitionBase, 283
  layer info, 97
  layers, 97, 284
  public screen, 50, 51, 53, 83, 108
  public screen list, 54
  window input, 203


M Index

Macros - menus, 178, 185, 200
MakeClass(), 311, 330
MakeDosNode(), 759, 776
MakeLibrary(), 443
MakeScreen(), 66, 70, 76
MakeVPort() -->
MapANSI(), 816
MapRawKey(), 814
Masking interrupts, 471
Master stack, 477
MatchToolValue(), 354
Math library, 833
mathffp.library, 835
mathieeedoubbas.library, 853
MathIeeeDoubTransBase, 857
mathieeedoubtrans.library, 857
mathieeesingbas.library, 845
MathIeeeSingTransBase, 849
mathieeesingtrans.library, 849
mathtrans.library, 838
MAXBODY, 143, 144
MAXPOT, 142, 143
MemChunk structure, 463
MemEntry structure, 460, 461
MEMF_24BITDMA, 431, 456
MEMF_ANY, 431, 456
MEMF_CHIP, 14, 227, 274, 288, 431, 456
MEMF_CLEAR, 211, 431, 456
MEMF_FAST, 14, 431, 456
MEMF_LOCAL, 431, 456
MEMF_PUBLIC, 431, 456
MEMF_REVERSE, 431, 456
MemHeader structure, 462
MemList structure, 459, 461
Memory -->
Memory allocation - Intuition, 284
Menu -->
Menu Bar, 168
Menu Help, 111
Menu Number -->
Menu Shortcut, 184
Menu structure -->
MENUCANCEL, 186
MENUDOWN, 110, 258, 268
MENUENABLED, 189
MENUHOT, 186
MenuItem structure -->
MENUNULL, 176, 177-178, 178, 179, 187, 191, 259-260
MENUNUM(), 177
MENUSTATE, 186
MENUTOGGLE, 182, 191
MENUUP, 110, 186, 187, 258, 268
MENUWAITING, 186
Message Port -->
Message Queue - IDCMP, 250
Message Structure, 250, 694
Messages -->
Messages arrival action, 500
Messages (Boopsi), 293 - final, 309, interim, 309
Methods, 293
MIDDLEDOWN, 258
MIDDLEUP, 258
MIDRAWN, 189
MinList structure, 489
MinNode structure, 488
Minterm, 596
Modal requesters, 202
Mode ID - of alert screen, 220
ModeID, 545, 550, 563, 565 - DisplayInfo, 567, MonitorSpec, 568
modelclass, 302
ModeNotAvailable(), 568, 611
Modes - display, 536, 545, ViewPort, 545, 550
Modify Clipping Region, 719
ModifyIDCMP(), 107, 188, 211, 216, 219, 249-250, 253-254, 257, 264, 264
ModifyProp(), 166
Modulo, 595
MonitorSpec structure, 568
Monochrome Screen - and Intuition graphics, 225
Mouse -->
Mouse button - right, 175
Mouse button events, 831
Mouse Movement - enable events, 273
Mouse Position - message, 256
Move(), 588, 611, 674
MOVEC, 517
MoveLayer(), 708, 711
MoveLayerInFrontOf(), 708, 711
MoveScreen(), 40, 74, 76
MoveSizeLayer(), 711
MoveSprite(), 288, 620, 668
MoveWindow(), 112, 115
MoveWindowInFrontOf(), 112, 113, 115
MrgCop() -->
Msg structure, 303, 307
MsgPort structure, 500 - SigTask, 254
MSP, 477
Multiple Asynchronous IORequests, 449
Multiple Gadgets - in easy request, 217
Multiple Select - menu, 169, 267, menu processing, 176
Multiple Tasks - with layers, 707
Multitasking, 429
Mutual Exclude - menu, 168, 181, 182, menu item, 190
Mutual exclusion, 473
myLabelLayer(), 712


MakeVPort() Index

MakeVPort(), 66, 555, 610, 709
  allocating memory, 560
  and Simple Sprites, 619
  in double-buffering, 579


Memory Index

Memory
  allocation, 455
  allocation for BitMap, 552
  allocation with Intuition, 284
  allocation within interrupt code, 457
  AllocMem(), 430, 455
  AllocMem()/Vec() flags, 431
  AllocVec(), 430
  Chip, 431
  Chip memory, 14
  Chip memory (defined), 11
  clearing, 456, 592
  deallocation, 455
  deallocation with Intuition, 284
  deallocation within interrupt code, 457
  Fast, 14, 431, 456
  Fast (defined), 11
  for area fill, 582
  free, 455, 463
  freeing, 560
  freeing Workbench screen, 52
  FreeMem(), 431, 455
  FreeVec(), 431
  location of, 456
  loss, 919, 920, 920, 920, 920
  problems, 916
  public, 431, 456
  remember key, 285
  Remember Structure, 285
  size
    allocation, 455
    deallocation, 455
  special-purpose chip, 456


Menu Index

Menu, 167
  active window, 79
  Amiga key glyph, 170
  cancelling menu operations, 186
  changing, 175
  checkmark, 182
  command key shortcuts, 281
  custom checkmark, 107
  defined, 29
  disable, 110, 111, 170
  disabling, 175, 185
  double-menu requester, 267
  enable, 170
  Enabling, 185
  Examples - menu layout, 192, simple menu, 172
  flickering, 920
  help, 111, 260
  highlighting, 169
  input events, 177
  Items, 168
  layer operation, 712
  layout, 179
  limitations, 170
  linking, 176
  macros, 178, 200
  maximum number of menu choices, 170
  menu help, 178, 179
  menu snap, 74
  mouse button, 267
  multi-select, 267
  overview, 167
  positioning, 170
  processing, 171
  processing input events, 178
  right mouse button, 168
  select box, 188
  select message, 259
  selection, 267, 268
  setting up, 171
  sharing, 176
  standards, 169
  SubItems, 168
  SubMenus, 168
  verify message, 259
  with multiple windows, 171, 176


Menu Number Index

Menu Number, 177, 178, 185
  construction, 178
  conversion, 177
  decoding, 178
  disabling, 185
  extraction, 178
  terminator, 177
  valid, 178


Menu structure Index

Menu structure, 179, 188-189, 189-190
  BeatX, 189
  BeatY, 189
  definition, 188
  FirstItem, 189, 189
  Flags, 189
  Height, 188
  JazzX, 189
  JazzY, 189
  LeftEdge, 188, 189
  MenuName, 189
  NextMenu, 188
  TopEdge, 188, 189
  Width, 188


MenuItem structure Index

MenuItem structure, 176, 177, 180, 181, 182, 184, 189-191, 224
  Command, 184, 190, 191
  definition, 189
  Flags, 181, 184, 190
  Height, 190
  ItemFill, 180, 190, 191
  LeftEdge, 182, 190
  MenuItem, 191
  MutualExclude, 182-183, 190
  NextItem, 189
  NextSelect, 176, 177, 191
  SelectFill, 190, 191, 192
  SubItem, 190
  TopEdge, 190
  Width, 190


Message Port Index

Message Port, 446
  creation, 446, 501
  deletion, 501
  IDCMP, 249
  Intuition, 247
  public, 501


Messages Index

Messages, 499
  discarded by Intuition, 113
  emergency, 220
  Examples - skeleton of waiting for a signal, 434
  GetMsg(), 434
  getting, 505
  IDCMP, 90
  interprocess communication, 433
  mouse, 268
  putting, 503
  queue limits, 113
  replying, 505
  waiting for, 504
  waiting for messages and signals, 435


Mouse Index

Mouse
  basic activities, 265
  button usage, 266
  click, 265
  combining buttons and movement, 268
  double click, 265
  drag, 265
  dragging, 268
  enable reporting, 109
  hot spot, 266
  keyboard as alternate, 280
  left (select) button, 266
  menu button, 267
  message queue limit, 114
  move, 265
  movement coordinates, 268
  position in GimmeZeroZero, 93
  position relative to window, 105
  position reporting, 114
  press, 265
  queue limits, 108, 268
  right (information transfer) button, 267
  with alert, 220


MrgCop() Index

MrgCop(), 66, 610, 709
  in graphics display, 555
  installing VSprites, 628
  merging Copper lists, 560


N Index

NBU_NOTIFY, 743
NBU_UNIQUE, 743
Nested Disabled Sections, 530
New Look, 55 - SA_Pens, 47, screen, 42
NewBroker structure, 730
NewGadget structure, 379
NewLayerInfo(), 710
NewList(), 491
NEWLIST, 498
NewList(), 498, 887
NewMenu structure, 370
NewModifyProp(), 147, 148, 166
NewObject(), 295, 330
NewObjectA(), 294, 330
NewRegion(), 720, 722
NewScreen - SPRITE flag, 619
NewScreen Structure, 42, 43, 46
NewWindow structure -->
Next - in ViewPort structure, 553
NEXTNODE, 498
NextPubScreen(), 54, 76
NMI, 519, 519, 525
NMI Interrupts, 519, 525
NM_BARLABEL, 371
NM_END, 370
NM_ITEM, 370
NM_ITEMENABLED, 371
NM_MENUENABLED, 371
NM_SUM, 370
NM_TITLE, 370
Node structure, 488 - ln_name, 54, ln_Pri, 525, 527
Nodes -->
NO_ICON_POSITION, 352
NOISYREQ, 203, 213
NOITEM, 177, 179, 185
NOMENU, 177
NOREQBACKFILL, 204, 213-214
NOSUB, 177, 179, 185
Notification - use by preferences, 336
Notify - close requester, 210, open requester, 210
NS_EXTENDED, 43, 45, 46
NT_INTERRUPT, 527
NT_SOFTINT, 527


NewWindow structure Index

NewWindow structure, 80, 106, 352
  BitMap, 111
  BlockPen, 106
  CheckMark, 107
  DetailPen, 106
  extended new window structure, 80
  FirstGadget, 107
  flags, 109-111
  Height, 106
  IDCMPFlags, 107
  LeftEdge, 106
  MaxHeight, 108
  MaxWidth, 108
  MinHeight, 108
  MinWidth, 108
  Screen, 107
  Title, 107
  TopEdge, 106
  Type, 107
  Width, 106


Nodes Index

Nodes
  initialization, 489
  inserting, 491
  priority, 489
  removing, 491
  successor and predecessor, 488
  text names, 489
  type, 489


O Index

O-Pen - see AOlPen
Object, 292
Object Oriented Programming - see Boopsi
Object Oriented Programming System for Intuition - see Boopsi
ObtainConfigBinding(), 759
ObtainGIRPort(), 319, 323, 330
ObtainSemaphore(), 512, 513, 513, 514, 514, 515
ObtainSemaphoreList(), 510, 514, 515
ObtainSemaphoreShared(), 513, 515
OFF_DISPLAY, 610
OffGadget(), 130, 166
OffMenu(), 185, 189, 191, 200
OM_ADDMEMBER, 302, 307
OM_ADDTAIL, 307
ON_DISPLAY, 610
OM_DISPOSE, 307 - see also Appendix B and DisposeObject()
OM_GET, 307, 311 - see also Appendix B and GetAttr()
OM_NEW, 307, 308 - see also Appendix B and NewObject()
OM_NOTIFY, 307, 309
OM_REMMEMBER, 307
OM_REMOVE, 307
OM_SET -->
OM_UPDATE, 307, 309 - Boopsi gadgets, 298
OnGadget(), 130, 166
OnMenu(), 185, 189, 191, 200
Open vector, 437
Open(), 263
OpenClipboard(), 781, 810
OpenDevice(), 447
OpenDiskFont(), 188, 243, 670, 675
OpenFont(), 243, 670, 675
OpenIFF(), 344, 782, 810
Opening a device, 447
OpenLibrary(), , , 188, 263, 435
OpenMonitor(), 568, 611
OpenScreen(), 42, 43, 45, 46, 76
OpenScreenTagList(), 42, 45, 45, 46, 53, 56, 59, 76
OpenScreenTags(), 42, 42, 45, 46, 76
OpenWindow(), 80, 115
OpenWindowTagList(), 53, 80, 82, 83, 85, 90, 92, 92, 93, 97, 98, 104, 107,
                     107, 108, 115, 175, 249, 254
OpenWindowTags(), 80, 115
OpenWorkBench(), 52-53, 76
opGet structure, 311
opMember structure, 303
opSet structure, 305, 308
Optimized Refresh - layers, 705, 711, 719
OPUF_INTERIM, 309
opUpdate structure, 309
OrRectRegion(), 722
OrRegionRegion(), 722
OSCAN_MAX, 62
OSCAN_STANDARD, 62
OSCAN_TEXT, 62, 86
OSCAN_VIDEO, 62
OSERR_NOCHIPMEM, 45
OSERR_NOCHIPS, 45
OSERR_NOMEM, 45
OSERR_NOMONITOR, 45
OSERR_PUBNOTUNIQUE, 45
OSERR_UNKNOWNMODE, 45
Outline mode - in Flood() fill, 591
Outline pen, 584
Output -->
Overscan -->
OverscanPrefs structure, 339
OwnBlitter(), 599, 599, 612


OM_SET Index

OM_SET, 305, 307, 309
  Boopsi gadgets, 298
  see also Appendix B and SetAttrs()/SetGadgetAttrs()


Output Index

Output
  and Intuition, 245, 248
  and the console device, 248
  and the graphics library, 248


Overscan Index

Overscan
  autoscroll, 74
  cloning, 59
  coordinate reference, 46
  display clip, 49, 61
  effect on the Viewing Area, 533
  finding display clip, 63
  maximum, 62
  maximum custom value, 62
  preference, 62
  preset values, 62
  QueryOverscan(), 59
  restrictions, 66
  SA_DClip, 49, 62
  SA_Overscan, 49
  screen dimensions, 46
  screen offsets, 46
  standard, 49, 62
  text, 46, 62
  video, 62
  VideoControl(), 63
  ViewPortExtra Structure, 63
  visible area, 63, 86


P Index

ParentChunk(), 789, 810
ParseIFF(), 344, 782, 810
ParseIX(), 746
PA_SOFTINT, 527
Paula, 11, 517
PC, 518
Pens -->
Performance - loss of, 920, 920
Permit(), 110, 470, 480, 520
PFBA, 545 - in dual playfield mode, 547
PGA_Freedom, 392, 394
Philosophy, 23
Pixel width, 548
PlaneOnOff - in Image structure, 226, using, 230
PlanePick - in Image structure, 226, using, 230
PLANEPTR, 552
Pointer -->
Pointer Relative - requester, 206
POINTREL, 205-206, 210, 212, 213
PolyDraw(), 589, 611
Polygons, 589
PopChunk(), 787, 810
POPPUBSCREEN, 52, 83
Port, 499 - named, 502, rendezvous at, 502
PORTS, 519, 525, 526
PORTS Interrupts, 519, 525
Position -->
PRED, 498
PREDRAWN, 212, 213, 214
Preemptive Task Scheduling, 518
Preferences -->
Preferences structure (1.3), 333
PrefHeader structure, 337
PrinterGfxPrefs structure, 339
PrinterTxtPrefs structure, 340
printf(), 887
PrintIText(), 224, 224, 240, 240, 243, 244
Private class, 293
Privilege violation, 474
Process, 430
Process structure, 430, 434 - pr_WindowPtr, 219
Processes, 466
Processor - interrupt priority levels, 471
Productivity Mode, 537, 561
Programming guidelines, 13
PROPBORDERLESS, 140, 147
PropChunk(), 344, 783, 810
propgclass, 297
PropInfo structure, 147
PROPNEWLOOK, 140, 147
PSNF_PRIVATE, 54
Public class, 293
Public memory, 431, 456
Public Screen -->
PUBLICSCREEN, 108
PubScreenNode Structure -->
PubScreenStatus(), 53, 76
PushChunk(), 787, 810
putchar(), 887
PutDefDiskObject(), 353
PutDiskObject(), 353
PutMsg(), 503, 520
puts(), 887


Pens Index

Pens
  and Intuition text, 239
  background, 58
  block, 47, 57, 106
  compatible, 55
  custom, 56
  detail, 47, 57, 106
  DrawInfo, 106
  fill, 58
  from public screen, 56
  highlight text, 58
  in Border structure, 238
  Intuition text, 242
  monochrome, 55
  new look, 55
  SA_Pens, 47
  screens, 59
  shadow, 58
  shine (highlight), 58
  text, 57
  text on fill, 58
  with graphics, 85
  Workbench, 57


Pointer Index

Pointer, 272
  active window, 79
  ClearPointer(), 274
  color, 274
  custom, 273
  data definition, 274
  default, 114
  hot spot, 266, 274
  keyboard control, 280
  position, 114, 272
  resolution, 272
  set, 114, 273
  SetPointer(), 273, 274


Position Index

Position
  border, 234
  Intuition graphics, 224
  Intuition text, 240
  of Image structure, 226
  screen, 40
  window, 106


Preferences Index

Preferences, 25, 331, 929
  AllocIFF(), 344
  CloseIFF(), 344
  CurrentChunk(), 344
  editor (IControl), 75
  EndNotify(), 336, 344
  ENVARC:sys, 335
  ENV:sys, 335
  examples - prefnotify.c, 336, showprefs.c, 341
  file format (2.0), 337, 340
  FindProp(), 344
  font, 48, 58, 59, 85, 179-180
  FreeIFF(), 344
  GetDefPrefs(), 332, 344
  GetPrefs(), 332, 344
  IControl, 281
  IDCMP_NEWPREFS, 262, 332
  IFF chunks, 338
  InitIFFasDOS(), 344
  introduction, 25
  Intuition, 75, 281
  notification, 336
  OpenIFF(), 344
  overscan, 40, 59, 62
  palette, 47
  ParseIFF(), 344
  pointer, 274
  printer device, 334
  PropChunk(), 344
  public screens, 83
  reading (1.3), 332
  reading (2.0), 335
  screen data, 59
  SetPrefs(), 334, 344
  setting (1.3), 334
  setting (2.0), 335
  StartNotify(), 336, 344
  struct FontPrefs, 338
  struct IControlPrefs, 338
  struct InputPrefs, 339
  struct OverscanPrefs, 339
  struct Preferences (1.3), 333
  struct PrefHeader, 337
  struct PrinterGfxPrefs, 339
  struct PrinterTxtPrefs, 340
  struct ScreenModePrefs, 340
  struct SerialPrefs, 340


Public Screen Index

Public Screen, 52, 53
  access by name, 83
  accessing, 50
  and Intuition graphics, 225
  cloning, 59
  closing, 53
  copying pens, 56
  default, 52, 59, 82
  display clip, 59
  example, 56, 83
  font, 59
  get default, 50
  global modes, 52, 83
  jumping, 83
  list, 54
  locking, 50, 51
  making private, 53
  making public, 53
  mode, 59
  name, 49, 53
  name collision, 45
  next, 54, 83
  notification, 49, 53
  POPPUBSCREEN, 52, 83
  requesters, 219, 219
  set default, 50
  SHANGHAI, 52, 83
  sharing, 65
  status, 53
  structures, 54
  visitor window, 82
  WA_PubScreen, 108
  WA_PubScreenFallBack, 108
  WA_PubScreenName, 108
  window fallback, 83
  windows on, 77, 82
  Workbench, 52


PubScreenNode Structure Index

PubScreenNode Structure, 54
  ln_Name, 54
  psn_Flags, 54
  psn_Node, 54
  psn_Screen, 54


Q Index

QBlit(), 599, 612 - linking bltnodes, 600
QBSBlit(), 599, 612 - avoiding flicker, 600, linking bltnodes, 600
Qualifier -->
Quantum, 430
QueryOverscan(), 59, 63, 76, 86
Queue Limit -->
Queues, 492
QuickIO, 448
Quiet - screen, 49


Qualifier Index

Qualifier, 281-282
  Alt, 282
  Amiga, 282
  Caps Lock, 282
  Ctrl, 282
  mouse button, 282
  numeric pad, 282
  repeat, 277, 282
  Shift, 282


Queue Limit Index

Queue Limit, 113
  IDCMP_UPDATE, 277
  keyboard repeat, 108
  mouse, 108
  mouse move, 268
  raw key, 277
  vanilla key, 277


R Index

RangeRand(), 887
RasInfo, 550
RasInfo Structure, 70, 552
RASSIZE(), 610
RASSIZE() macro, 551
Raster -->
RastPort - and Windows, 587, Area buffer, 582, pointer to, 587, pens, 584
RastPort Structure, 39, 58, 64, 65, 85, 224, 224, 225, 227, 230, 235, 240,
                    243, 581, 669, 670, 704, 710 - in layers, 704
Raw Key, 277 - codes, 90, queue limit, 277
RawDoFmt(), 217
RawKeyConvert(), 262, 277
RBF Interrupts, 519
RBFHandler, 523
RDB - see RigidDiskBlock
ReadChunkBytes(), 810
ReadChunkRecords(), 810
ReadPixel(), 588, 611
RECOVERY_ALERT, 220, 221
Rectangle fill, 591
Rectangle scrolling, 593
Rectangle Structure, 62, 676, 721 - with regions, 720
RectFill(), 591, 611
Refresh -->
RefreshGadgets(), 97, 166
RefreshGList(), 128, 130, 166
RefreshWindowFrame(), 97, 115
Regions -->
Register parameters, 521
Register usage conventions,
Release 2 - extensions, 18, migrating to, 18, versus 1.3, 19
ReleaseConfigBinding(), 759
ReleaseGIRPort(), 323, 330
ReleaseSemaphore(), 513, 514, 515
ReleaseSemaphoreList(), 514, 515
RemakeDisplay(), 66, 76
Remap Coordinates, 703
RemBob(), 641, 668
Remember Structure, 284, 284-285, 285, 285-286
REMHEAD, 498
RemHead(), 492, 498, 520
REMHEADQ, 498
RemIBob(), 641, 668
RemIntServer(), 525
REMOVE, 494, 498
Remove(), 492, 498
RemoveClass(), 312, 330
RemoveCxObj(), 737
RemoveGadget(), 166
RemoveGList(), 122, 166, 322
RemPort(), 502
RemSemaphore(), 513, 515
REMTAIL, 498
RemTail(), 492, 498, 520
RemTask(), 469, 480
RemTOF(), 888
RemVSprite(), 627, 668
Render - border, 235, requesters, 204
Repeat Qualifier, 277
Replying, 499, 505
ReplyMsg(), 249, 253, 263, 505, 520
ReportMouse(), 114, 268, 273, 282
REQACTIVE, 214
REQOFFWINDOW, 214
Request(), 112, 202, 203, 211, 222
Requester -->
Requester Structure -->
Reserved vector, 437
ResetMenuStrip(), 111, 175, 176, 200
Resident structure, 444
Resolution - pointer position, 272
Restricting Graphics - with layers, 710
RethinkDisplay(), 66, 70, 76
RHeight, 549
Right Amiga Key, 184 - with Alt key, 176
Right Justification - menu item text, 190
Right Mouse Button -->
rightmost - in GelsInfo, 624
RigidDiskBlock, 769
RigidDiskBlock specification, 770
RINGTRIGGER, 659
romtag, 444
rootclass, 292, 297
RouteCxMsg(), 746
RTE, 521
RTS, 521, 525
RWidth, 549
RxOffset -->
RyOffset -->


Raster Index

Raster
  allocation, 98
  depth, 544
  dimensions, 549
  in dual-playfield mode, 545
  memory allocation, 551
  one color, 593
  RasInfo structure, 550
  scrolling, 593


Refresh Index

Refresh
  disable reporting, 97, 110
  events with smart refresh, 110
  layers, 705, 711
  locking layers, 97
  optimized window, 97
  simple refresh, 705
  smart refresh, 705
  super bitmap, 706
  window notification, 97


Regions Index

Regions, 703
  changing, 722
  clearing, 722
  creating, 720
  for clipping, 93
  removing, 720


Requester Index

Requester - see ASL
  advantages over menus, 170
  and the IDCMP, 211
  clear message, 260
  count for window, 105
  defined, 30
  direct rendering, 205
  disabling system requesters, 219
  double menu, 202, 203, 210, 211
  easy requester, 215
  ending, 204
  file, 20
  font, 20
  initialization, 211
  limits, 204
  low level use of easy request, 218
  modal, 202
  multiple, 204
  pointer relative, 210
  position in GimmeZeroZero, 93
  positioning, 205, 212
  refreshing, 205
  rendering, 204
  set message, 260
  system requester, 219
  text in easy requester, 215
  title in easy requester, 216
  true, 202
  verify message, 260


Requester Structure Index

Requester Structure, 204, 211-212, 224, 235
  BackFill, 204, 213, 214
  Flags, 210, 212, 213, 214
  Height, 212
  ImageBMap, 205, 213, 214
  LeftEdge, 205, 210, 212
  OlderRequest, 212
  RelLeft, 206, 210, 212
  RelTop, 206, 210, 212
  ReqBorder, 212
  ReqGadget, 212
  ReqImage, 213, 214
  ReqLayer, 205, 214
  ReqPad1, 214
  ReqPad2, 214
  ReqText, 213
  RWindow, 214
  TopEdge, 205, 210, 212
  Width, 212


Right Mouse Button Index

Right Mouse Button
  cancel window drag, 77
  cancel window sizing, 78
  disable menu, 110
  information transfer, 266
  trap, 268
  with alert, 220


RxOffset Index

RxOffset
  effect on display, 549
  in RasInfo structure, 550
  in ViewPort display memory, 549


RyOffset Index

RyOffset
  effect on display, 549
  in RasInfo structure, 550
  in ViewPort display memory, 549


S Index

SA_AutoScroll, 49, 63
SA_Behind, 49
SA_BitMap, 48
SA_BlockPen, 47
SA_Colors, 47
SA_DClip, 49, 62, 62, 63
SA_Depth, 47
SA_DetailPen, 47
SA_DisplayID, 45, 47, 59
SA_ErrorCode, 45, 46
SA_Font, 47, 58, 85
SA_FullPalette, 47
SA_Height, 46
SA_Left, 40, 46
SA_Overscan, 49, 62, 63
SA_Pens, 47, 55, 56-57
SA_PubName, 49, 53
SA_PubSig, 49, 53
SA_PubTask, 49, 53
SA_Quiet, 49
SA_ShowTitle, 49
SA_SysFont, 48, 58, 59
SA_Title, 47
SA_Top, 40, 46
SA_Type, 48-49
SA_Width, 46
ScalerDiv(), 598
Screen Structure -->
SCREENBEHIND, 49
ScreenModePrefs structure, 340
SCREENQUIET, 49
Screens -->
ScreenToBack(), 74, 76
ScreenToFront(), 74, 76
Scrolling -->
ScrollLayer(), 98, 706, 707-708, 711
ScrollRaster(), 261, 593, 612
ScrollVPort(), 552
Select Box - menu, 188, menu item, 190
Select Button - with menus, 169
SELECTDOWN, 258, 268
SelectFill, 225
Selection - menus, 169
SELECTUP, 258, 268
Self-modifying code, 478
Semaphores, 473, 510 - function prototype summary, 510
Sending A Command To A Device, 448
SendIO(), 448, 449, 520
Serial device, 925
SerialPrefs structure, 340
SetAfPt(), 585, 611
SetAPen(), 584, 611, 672
SetAttrs(), 295, 330
SetBPen(), 584, 611, 672
SetCollision(), 647, 668
SetCurrentBinding(), 759, 776
SetCxObjPri(), 737
SetDefaultPubScreen(), 50, 76
SetDMRequest(), 210, 222
SetDrMd(), 585
SetDrMode(), 611, 672
SetDrPt(), 585, 589, 611
SetEditHook(), 166
SetExcept(), 473
SetFilter(), 746
SetFilterIX(), 746
SetFont(), 670
SetFunction(), 442
SetGadgetAttrs(), 295, 305, 330
SetIntVector(), 518, 521
SetKeyMap(), 831
SetKeyMapDefault(), 813
SetLocalItemPurge(), 799, 810
SetMenuStrip(), 111, 171, 175, 176, 200
SetMouseQueue(), 114, 269, 282
SetOPen(), 584, 611
SetPointer(), 114, 115, 273, 274, 282
SetPrefs(), 262, 289, 289, 334, 344
SetPubScreenModes(), 52, 76, 83
SetRast(), 593, 612
SetRexxVar(), 888
SetRGB4(), 275
SetRGB4CM(), 554, 610
SetSignal(), 433, 484, 485
SetSoftStyle(), 675
SetSR(), 478
SetSuperAttrs(), 330, 890
SetTaskPri(), 469, 480
SetTranslate(), 742
SetWindowTitles(), 107, 113, 115
SetWrMask(), 611
SGA_BEEP, 160, 161
SGA_END, 160, 161, 161
SGA_NEXTACTIVE, 160, 161
SGA_PREVACTIVE, 160, 161
SGA_REDISPLAY, 160, 161, 161
SGA_REUSE, 160, 161, 161
SGA_USE, 160, 161, 161
SGH_CLICK, 158, 161, 161
SGH_KEY, 158, 160, 161
SGM_EXITHELP, 158
SGM_FIXEDFIELD, 158
SGM_NOFILTER, 158
SGM_REPLACE, 157
SGWork structure, 159
SHADOWPEN, 58, 238
SHANGHAI, 52, 83
Share - IDCMP, 254
Share Display, 703 - layers, 703
Sharing - of layers, 707
Shift Select, 267
SHIFTITEM(), 200
SHIFTMENU(), 200
SHIFTSUB(), 200
SHINEPEN, 58, 238
Shortcut, 184
Short-frame Copper list, 579
SHOWTITLE, 49
ShowTitle(), 49, 65, 75, 76, 92
Signal(), 484, 485, 520
Signal bit - IDCMP, 254
Signal bit number, 500
Signal Semaphore, 510
Signals -->
Simple Refresh - attribute, 110, requester, 205
Simple Refresh Layer, 705
Simple Refresh Window, 94
Simple Sprite -->
SIMPLEREQ, 205
SimpleSprite structure, 617
Single-buffering, 550
Size -->
Size Gadget - cancel window sizing, 78, window, 78
Size Limits - window, 108
SizeLayer(), 706, 708, 711
SizeWindow(), 112, 115
Sizing - of layer, 705, window limits, 89
Smart Refresh - attribute, 110, refresh events, 110, requester, 205
Smart Refresh Layer, 705
Smart Refresh Window, 94
SOFTINT Interrupts, 519
Software error, 474
Software interrupts, 499, 500, 517, 519, 527
SortGList(), 642, 668 - ordering GEL list, 628
SprColors - changing VSprites, 627
SprColors pointer -->
sprintf(), 887
Sprite -->
Sprite Animation - introduction, 614
Sprite DMA, 633
spriteimage - structure, 620
SPRITES, 545-546
sprRsrvd GelsInfo member - in reserving Sprites, 632
SSP, 477
Stack -->
Stack overflows, 469
Stack size, 352
Standards - menus, 169
StartNotify(), 336, 344
Startup-sequence, 933
STDSCREENHEIGHT, 46, 62
STDSCREENWIDTH, 46, 62
StopChunk(), 783, 810
StopOnExit(), 785, 810
StoreItemInContext(), 791, 810
StoreLocalItem(), 791, 810
Strap, 925
strgclass, 297
STRINGA_ExitHelp, 387
STRINGA_Justification, 387
STRINGA_ReplaceMode, 387
StringExtend structure, 157
StringInfo structure, 155
struct GadgetInfo, 316
Structures -->
Stub, 438
subclass, 292
SubItems - number, 177, number terminator, 177
SUBNUM(), 177
SUCC, 498
SuperBitMap theory, 706
SuperBitMap Layer, 705
SuperBitMap Refresh -->
SuperBitMap Window, 94 - example, 99
superclass, 292
SUPERHIRES, 545
Supervisor Modes, 475, 477, 518, 520
Supervisor stack, 477
SwapBitsRastPortClipRect(), 712
Synchronization - of layers, 707
SyncSBitMap(), 98
SysBase Structure, 521
sysiclass, 297
SysReqHandler(), 217, 218-219
SYSREQUEST, 214
SysRequestHandler(), 222
System(), 20
System Request - easy requester, 219
System stack, 475, 520


Screen Structure Index

Screen Structure, 40, 45, 54, 58, 82, 108, 235
  1.3 compatible usage, 19
  BarLayer, 40
  BitMap, 40
  BlockPen, 55
  DetailPen, 55
  Font, 41, 58, 215
  LayerInfo, 40
  LeftEdge, 40, 86
  MouseX, 40
  MouseY, 40
  RastPort, 40
  TopEdge, 40, 86
  UserData, 41
  ViewPort, 40, 64
  WBorBottom, 40, 89
  WBorLeft, 40, 89
  WBorRight, 40, 89
  WBorTop, 40, 89


Screens Index

Screens
  aspect ratio, 20
  autoscroll, 74
  attributes, 46
  color selection, 47, 65
  CON: on, 20
  coordinate reference, 46
  data structures, 39
  defined, 27
  display modes, 20, 37
  DisplayBeep(), 75
  Examples
    cloning a public screen, 59
    double buffered screen, 67
    dual playfield screen, 70
    finding the Workbench screen, 51
    opening a new look screen, 42
    opening screens compatibly, 44
    using a public screen, 56
  font, 59
  from window, 105
  hide title, 92
  menu snap, 74
  mode for alert, 220
  MoveScreen(), 74
  multiple screens, 38
  positioning, 40
  ShowTitle(), 65
  tag items, 46
  title bar, 49, 65, 75
  using layers with, 65
  Workbench, 75


Scrolling Index

Scrolling
  a RastPort, 593
  auto screen, 49
  keyboard qualifiers, 74
  screens, 63, 74


Signals Index

Signals, 432
  allocation, 482
  coordination, 481
  exception, 473
  IDCMP, 250
  on arrival of messages, 500
  waiting for, 482
  waiting for messages and signals, 435


Simple Sprite Index

Simple Sprite
  allocation, 619
  colors, 618 - and ViewPorts, 618
  functions, 619
  GfxBase, 632
  in Intuition, 619
  position, 617
  simple definition, 614


Size Index

Size
  by inner dimension, 108
  change window limits, 108
  enable gadget, 109
  window auto-adjust, 111


SprColors pointer Index

SprColors pointer
  in VSprite structure, 626
  in VSprite troubleshooting, 632


Sprite Index

Sprite
  and Intuition, 288
  color, 546
  data definition, 274
  display, 543
  in animation, 555
  in Intuition windows & screens, 288
  pairs, 618
  reserving, 632


Stack Index

Stack, 477
  Interrupt stack, 477
  ISP, 477
  Master stack, 477
  MSP, 477
  overflow, 916
  SSP, 477
  Supervisor stack, 477
  User stack, 477
  USP, 477


Structures Index

Structures
  access to global system structures, 470
  AnimComp, 652
  AnimOb, 652
  AvailFonts, 688
  AvailFontsHeader, 688
  bltnode, 600
  Bob, 635
  BoolInfo, 139
  Border, 123
  Class, 305
  CollTable, 646
  ColorFontColors, 698
  ColorTextFont, 697
  ConfigDev, 756
  ContextNode, 789
  CurrentBinding, 759
  DBufPacket, 645
  DiagArea, 761
  DiskFontHeader, 699
  DosEnvc, 760
  EasyStruct, 216
  ExpansionRom, 757
  FileRequester, 416
  FontContents, 698
  FontContentsHeader, 698
  FontPrefs, 338
  FontRequester, 422
  Gadget, 132
  GadgetInfo, 316, 318
  gpGoInactive, 322
  gpHitTest, 320
  gpInput, 320
  gpRender, 319
  Hook, 312
  IControlPrefs, 338
  IFFHandle, 780
  Image, 225
  InputEvent, 321
  InputPrefs, 339
  InputXpression, 745
  IntuiMessage, 119, 256
  IntuiText, 123, 239
  IX, 745
  Keymap, 812
  Library, 436, 441
  Menu, 188
  MenuItem, 189
  Message, 694
  Msg, 303, 307
  NewBroker, 730
  NewGadget, 379
  NewMenu, 370
  opGet, 311
  opMember, 303
  opSet, 305, 308
  opUpdate, 309
  OverscanPrefs, 339
  Preferences (1.3), 333
  PrefHeader, 337
  PrinterGfxPrefs, 339
  PrinterTxtPrefs, 340
  Process, 430, 434
  PropInfo, 147
  RastPort, 581, 669, 670
  Rectangle, 676
  Remember, 285
  Requester, 211
  ScreenModePrefs, 340
  SerialPrefs, 340
  SGWork, 159
  shared, 470
  StringExtend, 157
  StringInfo, 155
  Task, 430, 465
  TAvailFonts, 689
  TextAttr, 671, 682
  TextExtent, 676
  TextFont, 674, 681, 694
  TextFontExtension, 681, 683, 696
  TFontContents, 699
  TTextAttr, 682
  Window, 104


SuperBitMap Refresh Index

SuperBitMap Refresh
  attribute, 111
  creating, 98
  description, 96
  memory requirements, 96
  update responsibility, 96


T Index

TA_DeviceDPI, 682
Tag lists -->
TagItem Structure - ti_Data, 45, 108
TagItems - screen, 46
Tags -->
Task signal, 499
Task Structure, 49, 430, 465
Task-Relative Interrupts, 517
Tasks -->
TAvailFonts structure, 689
TBE Interrupts, 519
tc_MemEntry, 461
Terminal - virtual, 77
Testing, 922
Text(), 670
Text -->
Text structure - 1.3 compatible usage, 19
TextAttr Structure, 47, 58, 240, 243, 671, 682
TextExtent(), 676
TextExtent structure, 676
TextFit(), 676
TextFont Structure, 58, 674, 681, 694
TextFontExtension structure, 681, 683, 696
TextLength(), 676
TEXTPEN, 57
TFCH_ID, 698
TFontContents structure, 699
Time - getting current values, 288
TimeDelay(), 888
Timer device, 926
Title -->
Title Bar -->
TmpRas, 583
ToolTypes -->
topmost - in GelsInfo, 624
Trace, 474
Trackdisk - problems, 921
Trackdisk device, 926
Translate(), 865 - output buffer, 866
Translator library, 865 - exception rules, 866
TRAP -->
TRAP instruction, 469
Traps, 474 - instructions, 476, supervisor mode, 475, trap handler, 475
TRAPV instruction, 474
Troubleshooting guide, 915
TSTLIST, 498
TSTLST2, 498
TSTNODE, 498
TTextAttr structure, 682
Type - of interrupt, 519, screen, 48
TypeOfMem(), 459


Tag lists Index

Tag lists
  copying, 871
  creating, 871
  filtering, 872
  mapping, 874
  reading, 873
    boolean, 874
    random access, 874
    sequential, 873


Tags Index

Tags, 867
  advanced use, 871
  function reference, 883
  functions, 868
  simple example, 869
  simple usage, 868
  structures, 867
  with open screen, 43
  with OpenWindow(), 80


Tasks Index

Tasks, 429, 430, 917
  cleanup, 469
  communication, 481
  coordination, 481
  creation, 466, 467 - stack, 466
  exclusion, 470
  deallocation of system resources, 469
  finalPC, 469
  forbidding, 470
  initialPC, 469
  non-preemptive, 470
  priority, 469
  sharing library bases, 467
  stack
    minimum size, 468
    overflows, 469
    supervisor mode, 468
    user mode, 468
  switching, 932
  termination, 469


Text Index

Text
  about Amiga fonts, 669
  and Intuition graphics, 239
  AskSoftStyle(), 675
  aspect ratio, 681, 682
  AvailFonts(), 688
  AvailFonts flags, 689
  Caveats - don't assume Topaz-8, 672
  ClearEOL(), 675
  ClearScreen(), 675
  cloning a RastPort, 673
  color fonts, 697
  ColorTextFont flags, 697
  COMPLEMENT, 673
  Compugraphic fonts, 670, 681, 682, 683
  dots per inch, 682
  drawing modes, 672
  Examples
    list available fonts, 690
    measuring and fitting text, 678
    render a text file to a window, 684
    sample font source, 699
    skeleton for opening a font, 671
    skeleton for selecting aspect ratio, 683
    skeleton for soft styling a font, 675
    skeleton using AvailFonts(), 689
  ExternFont(), 682
  font bitmaps, 695
  font flags, 671
  font preferences, 671
  font scaling, 670, 681
  font style flags, 671
  FontContentsHeader file IDs, 698
  FontExtent(), 676
  format of a font file, 698
  in easy requester, 215
  in requester gadgets, 206
  Intellifont engine, 670
  INVERSEVID, 673
  JAM1, 672
  JAM2, 673
  kerning, 696
  length, 241
  making the text fit, 676
  menu item, 169, 190
  Move(), 674
  OpenDiskFont(), 670, 675
  OpenFont(), 670, 675
  outline fonts, 670, 682, 683
  rendering the text, 673
  selecting a font, 670
  SetAPen(), 672
  SetBPen(), 672
  SetDrMode(), 672
  SetFont(), 670
  SetSoftStyle(), 675
  setting the font style, 675
  struct AvailFonts, 688
  struct AvailFontsHeader, 688
  struct ColorFontColors, 698
  struct ColorTextFont, 697
  struct DiskFontHeader, 699
  struct FontContents, 698
  struct FontContentsHeader, 698
  struct Message, 694
  struct RastPort, 669, 670
  struct Rectangle, 676
  struct TAvailFonts, 689
  struct TextAttr, 671, 682
  struct TextExtent, 676
  struct TextFont, 674, 681, 694
  struct TextFontExtension, 681, 683, 696
  struct TFontContents, 699
  struct TTextAttr, 682
  Text(), 670
  TextExtent(), 676
  TextFit(), 676
  TextLength(), 676
  with Intuition graphics, 223


Title Index

Title
  active window, 79
  font, 107
  screen, 47
  screen (from window), 107
  window, 107


Title Bar Index

Title Bar
  hidden (screen), 49
  menus, 168
  screens, 39, 49, 75
  window, 89


ToolTypes Index

ToolTypes
  array, 354
  DONOTWAIT, 354
  parsing, 354
  standard, 354
  STARTPRI, 354
  TOOLPRI, 354


TRAP Index

TRAP
  address error, 474
  bus error, 474
  CHK instruction, 474
  illegal instruction, 474
  line 1010 emulator, 474
  line 1111 emulator, 474
  privilege violation, 474
  trace, 474
  trap instructions, 474
  TRAPV instruction, 474
  zero divide, 474


U Index

UCopList structure, 602
UnlockIBase(), 283, 289
UnlockLayer(), 707, 708
UnlockLayerInfo(), 708, 708
UnlockLayers(), 708
UnlockPubScreen(), 51, 56, 76
UnlockPubScreenList(), 54, 76
UpfrontLayer(), 708, 711
User Interface - libraries, 24
User stack, 477
USEREQIMAGE, 204, 213
UserExt, 651
Using A Device, 447
USP, 477
Utility -->


Utility Index

Utility, 867
  32-bit math, 878
  callback hooks, 875
  date functions, 881
  function reference, 883
  international strings, 880
  tags, 867


V Index

Vanilla Key, 277 - queue limit, 277
VBEAM counter, 601
VBR, 517
Verify - requester, 211, window sizing, 91
VERTB, 519, 525
VERTB interrupts, 519, 525
VertBServer, 527
VGA Mode 3 - 8514/A, 537, 561
Video Parameters - Intuition control, 38
Video priority - in dual-playfield mode, 545
VideoControl() -->
View - origin, 62, preparing, 551
View Structure, 64, 66, 551 - function, 540
ViewAddress(), 64, 76
ViewExtra, 551
ViewExtra structure, 568
ViewPort -->
ViewPort Structure, 39, 64, 66, 187, 552
ViewPortAddress(), 64, 76
ViewPortExtra, 551
ViewPortExtra Structure, 59, 63, 86, 551, 553 - DisplayClip, 46
Virtual terminal, 27 - window, 77
Visible Area - screen, 40
Visible Display - easy request, 217
Visitor Window, 82
VSOVERFLOW Flag - in VSprite structure, 624, reserving Sprites, 632
VSprite -->
VSprite Flags - and True VSprites, 624
VTAG_USERCLIP_SET, 603
VUserStuff, 651


VideoControl() Index

VideoControl(), 59, 63, 86, 545, 550, 553, 564, 603, 608, 611
  ColorMap, 564
  genlock, 607
  ViewPort, 564


ViewPort Index

ViewPort
  and Simple Sprite colors, 618
  ColorMap, 542
  colors, 543, 553
  display instructions, 555
  display memory, 549
  displaying, 541
  function, 541
  Height, 542
  interlaced, 548
  low-resolution, 553
  modes, 544, 545
  Modes in Release 2, 564
  multiple, 553
  parameters, 542
  Width, 543
  width of and sprite display, 543


VSprite Index

VSprite
  building the Copper list, 628
  changing, 627
  color, 626
  hardware Sprite assignment, 628, 633
  Playfield colors, 633
  position, 624
  shape, 625
  simple definition, 614
  size, 625
  sorting the GEL list, 628
  troubleshooting, 632


W,X,Y,Z Index

WA_Activate, 91, 110
WA_AutoAdjust, 108, 111
WA_Backdrop, 92, 110
WA_BlockPen, 106
WA_Borderless, 93, 110
WA_Checkmark, 107, 181
WA_CloseGadget, 107, 109
WA_CustomScreen, 82, 107
WA_DepthGadget, 107, 109
WA_DetailPen, 106
WA_DragBar, 107, 109
WA_Flags, 106, 111, 175
WA_Gadgets, 107
WA_GimmeZeroZero, 93, 110
WA_Height, 106
WA_IDCMP, 90, 107, 186
WA_InnerHeight, 108
WA_InnerWidth, 108
WA_Left, 106
WA_MaxHeight, 108
WA_MaxWidth, 108
WA_MenuHelp, 111, 179, 258, 260
WA_MinHeight, 108
WA_MinWidth, 108
WA_MouseQueue, 108, 114, 269
WA_NoCareRefresh, 97, 110
WA_PubScreen, 83, 108
WA_PubScreenFallBack, 53, 83, 108
WA_PubScreenName, 53, 83, 108
WA_ReportMouse, 109, 258
WA_RMBTrap, 110, 251, 258
WA_RptQueue, 108, 114, 277
WA_ScreenTitle, 107
WA_SimpleRefresh, 110, 261
WA_SizeBBottom, 109
WA_SizeBRight, 109
WA_SizeGadget, 109
WA_SmartRefresh, 110, 261
WA_SuperBitMap, 98, 111
WA_Title, 107
WA_Top, 106
WA_Width, 106
WA_Zoom, 107, 108
Wait(), 30, 31, 250, 432, 449, 470, 471, 483, 485, 505
WaitBlit(), 587, 592, 599, 599, 612
WaitBOVP(), 560
WaitIO(), 449, 451
WaitPort(), 449, 504
WaitTOF(), 560, 629
WBenchToBack(), 52, 76
WBenchToFront(), 52, 76
WFLG_ACTIVATE, 91, 110
WFLG_BACKDROP, 92, 110
WFLG_BORDERLESS, 88, 93, 110
WFLG_CLOSEGADGET, 109
WFLG_DEPTHGADGET, 109
WFLG_DRAGBAR, 109
WFLG_GIMMEZEROZERO, 93, 96, 110
WFLG_NOCAREREFRESH, 97, 110
WFLG_NW_EXTENDED, 80, 106
WFLG_REPORTMOUSE, 109, 273
WFLG_RMBTRAP, 49, 110, 111, 175, 268 - setting, 110
WFLG_SIMPLE_REFRESH, 110
WFLG_SIZEBBOTTOM, 109, 126
WFLG_SIZEBRIGHT, 109, 126
WFLG_SIZEGADGET, 109
WFLG_SMART_REFRESH, 110, 205
WFLG_SUPER_BITMAP, 98, 111
WFLG_WINDOWCLOSE, 107
WFLG_WINDOWDEPTH, 107
WFLG_WINDOWDRAG, 107
WFLG_WINDOWSIZING, 108
WhichLayer(), 708
White Boxes--The Transparent Base Classes - Boopsi, 316
Width - by inner dimension, 108
Width variable - in VSprite structure, 625
Window -->
Window structure -->
WindowLimits(), 89, 108, 115
WindowToBack(), 112, 113, 115
WindowToFront(), 112, 113, 115
Workbench -->
WriteChunkBytes(), 787
WriteChunkRecords(), 787
WritePixel(), 587, 611

XorRectRegion(), 722
XorRegionRegion(), 722

Z, 525
Zero divide, 474
ZipWindow(), 112, 113, 115
Zoom -->
Zorro II - see Expansion, AUTOCONFIG
Zorro III - see Expansion, AUTOCONFIG


Window Index

Window, 917
  activate message, 261
  advantages over menus, 170
  automatic size adjust, 111
  backdrop window type, 92
  borderless window type, 93
  borders, 932
  change message, 263
  close message, 259
  defined, 27
  dimensions, 85
  Examples
    calculating window border size, 89
    opening a window with tags, 80
    superbitmap window, 99
    using public screens, 83
    window sized to the visible display, 86
  GimmeZeroZero window type, 93
  inactive message, 261
  maximum height, 108
  maximum width, 108
  menus, 169
  minimum height, 108
  minimum width, 108
  new size message, 260
  pointer position, 273
  position change notify, 91
  positioning, 40
  problems, 921, 921
  refresh message, 261
  requester limit, 204
  simple refresh, 94
  size change notify, 91
  size limits, 108
  size verify message, 261
  smart refresh, 94
  super bit map, 94
  user positioning, 77


Window structure Index

Window structure, 219, 235, 273
  1.3 compatible usage, 19
  BorderBottom, 88, 89, 105
  BorderLeft, 88, 89, 105
  BorderRight, 88, 89, 105
  BorderRPort, 105
  BorderTop, 88, 89, 105
  definition, 104
  FirstRequest, 214
  Flags, 110, 186
  GZZHeight, 93
  GZZMouseX, 93, 105, 273
  GZZMouseY, 93, 105, 273
  GZZWidth, 93
  Height, 89, 105
  IDCMPFlags, 249-250
  LeftEdge, 105
  MessageKey, 249
  MouseX, 105, 269
  MouseY, 105, 269
  ReqCount, 105
  RPort, 105
  TopEdge, 105
  UserData, 105
  UserPort (IDCMP), 31, 249, 253-254, 257
  Width, 89, 105
  WindowPort, 249, 253-254
  WScreen, 105


Workbench Index

Workbench, 25, 52, 929
  AppMessage, 359
  close screen, 52
  introduction, 25
  open screen, 52
  screen, 75, 933
  screen to back, 52
  screen to front, 52
  shortcut key functions, 281
  stack size, 352
  startup code, 364
  startup message, 364
  start-up message, 364
  ToolTypes, 354
  windows on screen, 82
  .info file, 345


Zoom Index

Zoom, 113
  alternate size, 78, 108
  enable gadget, 108
  ZipWindow(), 112, 113


RKM Libraries: 2 Intuition and the Amiga Graphical User Interface

Intuition is the collective name for the function libraries, data
structures and other elements needed to create a graphical interface for
Amiga applications.  Programmers use Intuition to perform user interface
chores such as opening windows, managing menus, monitoring gadgets,
reading the mouse position and so forth.

Newcomers to the Amiga sometimes think of Intuition as the Amiga's
operating system but it is not.  Intuition is just one component that
together with Exec, AmigaDOS, and other subsystems make up the whole
operating system.  Intuition is the most visible part of the operating
system though since it provides the graphical user interface familiar to
all Amiga users.

 About User Interfaces          How an Application Sees Intuition
 How the User Sees Intuition    A Simple Intuition Program


2 Intuition and the Graphical User Interface / About User Interfaces

What is a user interface? This sweeping phrase covers all aspects of
communication between the user and the computer.  It includes the
innermost mechanisms of the computer and rises to the height of defining a
philosophy to guide the interaction between human and machine.  Intuition
is, above all else, a philosophy turned into software.

Intuition's user interface philosophy is simple to describe:  the
interaction between the user and the computer should be consistent, simple
and enjoyable; in a word, intuitive.  Intuition supplies the tools needed
to turn this philosophy into practice.

Implicit in this philosophy is the idea that the user interface should be
graphical.  A graphical user interface, or GUI, is a visually oriented
method of communicating with a computer in which system resources are
represented by pictorial symbols that can be manipulated with a pointing
device such as a mouse.  Other types of user interfaces are possible such
as the Amiga's Shell in which text commands are entered by typing them at
the keyboard.  For more information about user interfaces, refer to the
Amiga User Interface Style Guide.

 Elements of the Amiga Graphical User Interface System
 Goals of Intuition


2 / User Interfaces / Elements of the Graphical User Interface System

There is more to the Amiga user interface than Intuition.  To build a
complete user interface, application writers need to understand these
other elements of the system software.

    Table 2-1: Elements of the Amiga Graphical User Interface System
  ______________________________________________________________________
 |                                                                      |
 |  System Element     Purpose                                          |
 |======================================================================|
 |  Intuition          The main toolkit and function library for        |
 |                     creating a graphical user interface (GUI) on the |
 |                     Amiga.                                           |
 |                                                                      |
 |  Workbench          The Amiga file system GUI in which icons         |
 |                     represent applications and files.                |
 |                                                                      |
 |  Preferences        A family of editors and configuration files for  |
 |                     setting Amiga system options.                    |
 |                                                                      |
 |  BOOPSI             Subsystem of Intuition that allows applications  |
 |                     to add extensions to Intuition through           |
 |                     object-oriented techniques (Release 2 only).     |
 |----------------------------------------------------------------------|
 |  Gadtools Library   A support library for creating Intuition gadgets |
 |                     and menus (Release 2 only).                      |
 |                                                                      |
 |  ASL Library        A support library for creating Intuition         |
 |                     requesters (Release 2 only).                     |
 |                                                                      |
 |  Icon Library       Main library for using Workbench icons.          |
 |                                                                      |
 |  Workbench Library  A support library for Workbench icons and menus  |
 |                     (Release 2 only).                                |
 |----------------------------------------------------------------------|
 |  Console Device     An I/O support module which allows windows to be |
 |                     treated as text-based virtual terminals.         |
 |                                                                      |
 |  Graphics Library   The main library of rendering and drawing        |
 |                     routines.                                        |
 |                                                                      |
 |  Layers Library     A support library that manages overlapping,      |
 |                     rectangular drawing areas which Intuition uses   |
 |                     for windows.                                     |
 |______________________________________________________________________|

As you read about Intuition in the chapters to follow, you will be
introduced to each of these elements of the Amiga user interface in more
detail.


2 / About User Interfaces / Goals of Intuition

Intuition was designed with two major goals in mind.  The first is to give
users a friendly and consistent environment to control the functions of
the Amiga operating system and its applications.

The second goal (the big one) is to give application designers a graphical
user interface toolkit that manages all the complexities of sharing the
system with other programs that may be running at the same time.  Since
the Amiga is a multitasking computer, many programs can reside in memory
at the same time sharing the system's resources with one another. Programs
take turns running so that, from the user's point of view, it appears that
many programs are running simultaneously.

On a multitasking computer like the Amiga, the user interface design must
allow the user to control many programs with just one monitor, one
keyboard, and one mouse.  (Imagine driving many cars simultaneously with
one steering wheel.)  Intuition supplies the tools needed to solve this
problem.


2 Intuition and the Graphical Interface / How the User Sees Intuition

Intuition solves the problem of interacting with multiple programs by
dividing the display up into multiple screens and overlapping windows so
that each application has its own work area.  The user sees the Amiga
environment through these windows, each of which can represent a different
task or application context.

     Figure 2-1: The Workbench Screen With Windows

The user performs operations inside screens and windows with the mouse, a
mechanical device that moves a pointer over the Amiga's display.  The user
moves the mouse to position the pointer on graphic symbols of various
objects or actions.  Buttons on the mouse are pressed to select or
activate the item pointed to.

The user can switch back and forth between different jobs, such as writing
a document, drawing an illustration, printing text, or getting help from
the system simply by moving from one window to another with the mouse.
With the mouse, the user can also change the shape and size of application
windows, move them around on the screen, overlap them, bring a window to
the foreground, and send a window to the background.  By changing the
arrangement of the windows, the user selects which information is visible
and which application to work with next.  (Screens may also be moved up or
down in the display, and they can be moved in front of or behind other
screens.)

 Workbench and Preferences    Intuition's 3D Look


2 / How the User Sees Intuition / Workbench and Preferences

Normally, the Workbench screen (shown above) is the first screen the user
sees upon booting the Amiga.  Workbench is a special program supplied with
every Amiga that gives the user a friendly and consistent graphic
interface to the file system.  It's the default environment the user
starts out with.

In Workbench, disks, directories, files and other objects are symbolized
by small pictures called icons which can be manipulated with the mouse.
For instance, a program file can be executed by pointing to its icon with
the mouse and double-clicking the left mouse button.  The Workbench screen
is automatically set up by Intuition and can be easily shared, so many
application programs use it too.

User control of the OS is also supported through Preferences.  Preferences
is a family of editors and associated configuration files that allow the
user to control the basic set up of the operating system.  For example
Printer Preferences sets up all the printer options.

Workbench, together with Preferences, gives the user an easy way to
control the OS and launch applications.  These programs are built with the
same Intuition tools available to application programmers giving the whole
Amiga system an integrated look and feel.  Workbench and Preferences are
important components of the Amiga graphic user interface system and are
discussed in greater detail in later chapters.


2 / How the User Sees Intuition / Intuition's 3D Look

The Amiga operating system comes in different versions.  The latest
version, Release 2, contains significant improvements in the appearance of
the Intuition graphical user interface, usually referred to as the 3D Look
of Intuition.

     Figure 2-2: An Example of the 3D Look of Intuition

In the new 3D look of Intuition, objects are drawn so that light appears
to come from the upper left of the display with shadows cast to the lower
right.  Using light and shadow gives the illusion of depth so that images
appear to stand out or recede from the display.  By convention, an image
with a raised appearance indicates an object that is available for use or
modifiable.  An image with a recessed appearance indicates an object that
is unmodifiable, or for display purposes only. Applications should follow
the same conventions.

Release 2 has other improvements over 1.3 (V34) and earlier versions of
the operating system.  Among these are new display resolutions, display
sizes, and new function libraries to support Intuition.  Most of the
examples listed in this book assume Release 2.  Where appropriate, the old
1.3 methods are also described.


2 Intuition & Graphical Interface / How an Application Sees Intuition

Intuition is organized as a library of over 100 functions.  Before using
an Intuition function you must first open the Intuition library.  (In
general, you must always open a library before you can call the functions
of that library.  See Chapter 1, "Introduction to Amiga System Libraries".)

 Components of Intuition
 Screens and Windows
 Gadgets, Menus and Requesters


2 / How an Application Sees Intuition / Components of Intuition

The types of data objects that the Intuition library functions create and
control fall into six broad categories.  These are the main components an
application uses to build and operate a graphic user interface on the
Amiga.

                Table 2-2: GUI Components of Intuition
  ____________________________________________________________________
 |                                                                    |
 |  Screens       The display environment. Sets the resolution and    |
 |                number of colors.                                   |
 |                                                                    |
 |  Windows       A graphic rectangle within a screen representing a  |
 |                working context.                                    |
 |                                                                    |
 |  Menus         A list of choices displayed at the top of a screen  |
 |                that can be selected with the mouse.                |
 |                                                                    |
 |  Gadgets       A control symbolized by a graphic image that can be |
 |                operated with the mouse or keyboard.                |
 |                                                                    |
 |  Requesters    Sub-windows for confirming actions, accessing files |
 |                and other special options.                          |
 |                                                                    |
 |  Input events  Mouse, keyboard or other input activity.            |
 |____________________________________________________________________|


2 / How an Application Sees Intuition / Screens and Windows

As mentioned earlier, Intuition allows multiple programs to share the
display by managing a system of multiple screens and overlapping windows.
A screen sets up the display environment and forms the background that
application windows operate in.  A window is simply a graphic rectangle
that represents a work context.  Each screen can have many windows on it.

Multiple screens and windows give each application its own separate visual
context so that many programs can output graphics and text to the display
at the same time without interfering with one another.  Intuition (using
the layers library) handles all the details of clipping graphics so they
stay inside window bounds and remembering graphics that go temporarily out
of sight when the user rearranges windows.

The keyboard and mouse are shared among applications through a simpler
technique:  only one application window at a time can have the
input focus.  Hence, Intuition ensures that only one window, called the
active window gets to know about keyboard, mouse and other types of input
activity.

Each application window is like a virtual terminal or console.  Your
program will seem to have the entire machine and display to itself.  It
can send text and graphics to its terminal window, and ask for input from
any number of sources, ignoring the fact that other programs may be
performing these same operations.  Intuition handles all the housekeeping.
In fact, your program can open several of these virtual terminals and
treat each one as if it were the only program running on the machine.
Intuition will keep track of all the activity and make sure commands and
data are dispatched to the right place.


2 / How an Application Sees Intuition / Gadgets, Menus And Requesters

Intuition screens and windows provide an orderly way for multiple programs
to share the display and input devices.  Each application also needs a
method for the user to send commands to it and select its options.
Intuition supplies gadgets, menus and requesters for this purpose.

 Gadgets    Requesters
 Menus      The Intuition Input Event Loop


2 / / Gadgets, Menus And Requesters / Gadgets

A gadget is an application control symbolized by a graphic image that can
be operated with the mouse or keyboard.  The imagery used for a gadget
could look like a switch, a knob, a button, or just about anything.
Intuition supplies some pre-fabricated gadgets, called system gadgets, for
controlling window and screen arrangements.  Other gadget types allow the
user to select colors, enter text or numbers, and perform other simple
operations.

     Figure 2-3: An Intuition Window with Gadgets

Most of the user's input for a typical Intuition application will be
obtained with gadgets.  Gadgets are discussed in detail in Chapter 5,
"Intuition Gadgets".  Additional information on programming gadgets for
Release 2 of the operating system can be found in Chapter 15,
"GadTools Library".


2 / / Gadgets, Menus And Requesters / Menus

Intuition also supplies a menu system for accepting commands and options
from the user.  A menu is a list of choices displayed at the top of the
screen from which the user can select with the mouse.  Each screen has one
menu bar that all application windows operating on the screen share.
Whichever window is active controls what appears in the menu bar.

     Figure 2-4: An Intuition Menu

The current set of menu choices can always be brought into view by
pressing the right mouse button (the menu button) thus providing the user
with a familiar landmark even in unfamiliar applications.  Menus allow the
user to browse through the possible set of actions that can be performed
giving an outline-like overview of the functions offered by a program.

Menus are discussed in detail in Chapter 6, "Intuition Menus".  Additional
information on programming menus for Release 2 of the operating system can
be found in Chapter 15, "GadTools Library".


2 / / Gadgets, Menus And Requesters / Requesters

Gadgets and menus do much of the work of getting commands and option
choices from the user.  Sometimes though, an application needs to get
further information from a user in response to a command which has already
been initiated.  In that case, a requester can be used.  A requester is a
temporary sub-window, usually containing several gadgets, used to confirm
actions, access files, or adjust the special options of a command the user
has already given.

     Figure 2-5: An Intuition Requester

Requesters are discussed in detail in Chapter 7,
"Intuition Requesters and Alerts".  Additional information on programming
requesters for Release 2 of the system can be found in Chapter 16,
"ASL Library".


2 / / Gadgets, Menus And Requesters / The Intuition Input Event Loop

Once an application has set up the appropriate screen, window, gadgets
menus and requesters, it waits for the user to do something.  Intuition
can notify an application whenever user activity occurs by sending a
message.  The message is simply a pointer to some memory owned by
Intuition that contains an IntuiMessage data structure describing the user
activity that occurred.

To wait for user activity or other events, the Exec library provides a
special function named Wait().  The Exec Wait() function suspends your
task allowing other applications or system tasks to run while your
application is waiting for input or events from Intuition and other
sources.

Thus, the basic outline for any Intuition program is:

  * Set up the window, screen and any required gadgets, menus or
    requesters.

  * Wait() for a message from Intuition about user activity or other
    events. Copy needed data from the message and tell Intuition you
    received it by replying. Look at the data and take the appropriate
    action.

  * Repeat until the user wants to quit.

These steps, sometimes referred to as the Intuition input event loop are
basically the same for any Intuition application.

As you might expect, Intuition can send a message to your application
whenever the user presses a key on the keyboard or moves the mouse.  Other
types of input events Intuition will notify you about include gadget hits,
menu item selection, time elapsing, disk insertion, disk removal, and
window rearrangement.

Gadgets, menus, requesters are the nuts and bolts of the Intuition GUI
toolkit.  Much of the code in an application that uses Intuition deals
with the set up and operation of these important data objects.  No matter
how simple, complex, or fanciful your program design, it will fit within
the basic Intuition framework of windows and screens, gadgets, menus and
requesters.  The users of the Amiga understand these basic Intuition
elements and trust that the building blocks remain constant.  This
consistency ensures that a well-designed program will be understandable to
the naive user as well as to the sophisticate.


2 Intuition and the Graphical Interface / A Simple Intuition Program

The sample Intuition program that follows shows all of the basic
requirements for an Intuition application. There are three important
points:

  * You must open the Intuition library before you can use the Intuition
    functions.  Certain languages such as  require the pointer to the
    Intuition library to be assigned to a variable called IntuitionBase
    (see Chapter 1 for more about this).

  * When you set up a window, you also specify the events that you want
    to know about.  If the user performs some activity that triggers one
    of the events you specified, Intuition signals you and sends a
    message.  The message is a pointer to an IntuiMessage data structure
    that describes the event in more detail.  Messages about Intuition
    events are sent to a MsgPort structure which queues up the messages
    for you in a linked list so that you may respond to them at your
    convenience.

  * Resources must be returned to the system.  In this case, any windows,
    screens or libraries that were opened are closed before exiting.

 Example Intuition Event Loop
 Intuition Example (V36 And Later)
 Intuition Example (All Versions)


2 / A Simple Intuition Program / Example Intuition Event Loop

The Intuition event loop used in the example is very simple.  The example
first sets up a custom screen, opens a window on it, then waits for
Intuition to send messages about user input with the following event loop:

    winsignal = 1L << window1->UserPort->mp_SigBit;  /* window signal */
    signalmask = winsignal;   /* example only waits for window events */

    while( !done )  {
        signals = Wait(signalmask);
        if (signals & winsignal)
            done = handleIDCMP(window1);
    }

Intuition sends messages about user activity to a special port known as
the IDCMP.  Each window can have its own IDCMP (in the code above the
IDCMP is window1->UserPort).  To wait for event messages to arrive at the
IDCMP port, the example code calls the Exec Wait() function.  It then
processes and replies to any event messages that it gets in a subroutine
named handleIDCMP().  For this example, the only event Intuition will
report is the close window event.  When the example detects this event, it
closes the window, closes the screen, closes the Intuition library and
exits.  Event loops similar to this one are used in Intuition examples
throughout this book.  For more information about IDCMP and user input,
see the chapters on "Intuition Windows" and "Intuition Input and Output".


Amiga® RKM Libraries: 3 Intuition Screens

Intuition screens are the basis of any display Intuition can make.
Screens determine the fundamental characteristics of the display such as
the resolution and palette and they set up the environment for multiple,
overlapping windows that makes it possible for each application to have
its own separate visual context.  This chapter shows how to use existing
screens and how to create new screens.

 Types of Screens            Overscan and the Display Clip
 Screen Data Structures      Intuition Screens and the Graphics Library
 Custom Screen Functions     Advanced Screen Programming
 Public Screen Functions     Other Screen Functions
 DrawInfo and the 3D Look    Function Reference


3 Intuition Screens / Types of Screens

Screens are important because they determine the basic resolution and
maximum number of colors in the display.  Once a screen is set up, these
attributes cannot be changed so any graphics work done on a given screen
is restricted to that screen's resolution and number of colors.  Hence,
the type of screen used is a basic design decision.

With Intuition screens, a video display can be created in any one of the
many Amiga display modes.  The basic parameters of the video display such
as resolution, total size, frame rate, genlock compatibility, support of
screen movement and number of colors are defined by these modes.  There
are currently four basic modes available on all Amiga models.  These basic
modes work with conventional monitors (15 kHz scan rate) and older
versions of the operating system.

            Table 3-1: Basic Amiga Display Modes

     Basic Amiga      Resolution  Maximum    Supports
    Display Modes        NTSC       PAL       Colors    HAM/EHB*
    -------------     ----------  -------    --------   -------
    Lores              320x200    320x256   32 of 4096    Yes
    Lores-Interlaced   320x400    320x512   32 of 4096    Yes
    Hires              640x200    640x256   16 of 4096    No
    Hires-Interlaced   640x400    640x512   16 of 4096    No

    * HAM and EHB modes provide for additional colors with some
      restrictions.

With Release 2 of the operating system, many other display modes are
available (these usually require a special monitor or ECS).  All these
display modes, including the specialized modes, are integrated through the
graphics library display database.  See the "Graphics Primitives" chapter
for a complete list of all Amiga display modes.

 Multiple Screens
 Public Screens and Custom Screens
 Screen Components


3 / Types of Screens / Multiple Screens

All Intuition display objects (such as windows and menus) take graphical
characteristics from the screen.  These objects are restricted to the same
resolution and maximum number of colors as the screen they operate in.
Other characteristics such as the palette, pens and fonts are inherited
from the screen (but may be changed on a case by case basis).

This is not too much of a restriction because the Amiga can maintain
multiple screens in memory at the same time.  In other words, one
application can use a high resolution screen (with 16 colors) while
another application uses a low resolution screen (with 32 colors) at the
same time.  Screens typically take up the entire viewing area so only one
is usually visible.  But screens can be moved up and down or rearranged
allowing the user (or application) to move between screens easily.


3 / Types of Screens / Public Screens and Custom Screens

An application may choose to use an existing screen or to create its own
screen.  For instance, the normal Amiga startup process opens the
Workbench screen (Workbench is the Amiga's default user interface).  Any
application is free to use the Workbench screen instead of opening a new
one.  Screens that can be shared this way are called public screens.

Public screens are a new feature of Release 2 (V36).  In older versions of
the OS, only the Workbench screen could be shared.  Now any screen may be
set up as a public screen so that other applications may use it.

The use of an existing public screen, like the Workbench screen, requires
little effort by the application and does not use up any memory.  However,
using  Workbench or another existing public screen means some flexibility
is lost; the resolution, maximum number of colors and other attributes are
already set.  If the application cannot function under these limitations,
it may open its own custom screen.

Custom screens allow for complete control of the display space so an
application can get exactly the kind of display it wants.  However, since
creating a new, custom screen uses up memory, they should only be used
when there are no suitable public screens available.

Owners of a custom screen can keep their screen private, or they may allow
other applications to share their screen by registering the screen with
the operating system as a public screen.  See the section on
"Public Screen Functions" later in this chapter for more about public
screens and Workbench.


3 / Types of Screens / Screen Components

Screens have very little visual impact, they simply provide a resolution
specific area to place other objects such as windows and menus.  Screens
have no borders.  Only the title bar marks the screen limits (specifying
the left and top edges, and the width of the screen), and the title bar
may be hidden, or obscured by graphics or windows.

The title bar also serves as the menu bar when the user presses the menu
button on the mouse.  The menu bar area is shared by all applications
operating within the screen.

Within the title bar, there are two gadgets: a screen drag gadget and a
depth-arrangement gadget.  The screen drag gadget allows the screen to be
moved up and down.  The depth-arrangement gadget allows the screen to be
placed in front or behind all other screens.

     Figure 3-1: An Intuition Screen (Workbench)

Screens are always rectangular, and the areas at the sides and bottom of
the display that are not within the screen's limits are filled with the
background color.  The area above all visible screens is filled with the
background color of the highest screen.  These areas surrounding the
screen (normally unused) are known as the overscan area.  The Amiga
display system allows the overscan area to be used for graphics under
special circumstances (see the section on "Overscan and the Display Clip"
later in this chapter).


3 Intuition Screens / Screen Data Structures

The Amiga uses color registers and bitplane organization as its internal
representation of display data.  Screens require a color table and display
raster memory for each bitplane.  This is the memory where imagery is
rendered and later translated by the hardware into the actual video
display.  This information is contained in data structures from the
Amiga's graphics library.

A ViewPort is the main data structure used by the graphics library to
represent a screen.  Pointers to each of the screen's bitplanes are stored
in the graphics library BitMap structure.  Color table information is
stored in a graphics structure called a ColorMap.  And the screen's
drawing and font information is stored in the RastPort structure.

The graphics RastPort structure is a general-purpose handle that the
graphics library uses for drawing operations.  Many Intuition drawing
functions also take a RastPort address as a parameter.  This makes sense
since the RastPort structure contains drawing variables as well as a
pointer to the BitMap telling where to draw.  See the
"Graphics Primitives" chapter for more information on these structures and
how they are used.

 The Intuition Screen Data Structure    Other Screen Data Structures


3 / Screen Data Structures / The Intuition Screen Data Structure

The structures mentioned above are unified along with other information in
Intuition's Screen data structure defined in the include file
<intuition/screens.h>.  Notice that the Screen structure contains
instances of a ViewPort, RastPort and BitMap.

struct Screen
    {
    struct Screen *NextScreen;
    struct Window *FirstWindow;
    WORD LeftEdge, TopEdge, Width, Height;
    WORD MouseY, MouseX;
    UWORD Flags;
    UBYTE *Title, *DefaultTitle;
    BYTE BarHeight, BarVBorder, BarHBorder, MenuVBorder, MenuHBorder;
    BYTE WBorTop, WBorLeft, WBorRight, WBorBottom;
    struct TextAttr *Font;
    struct ViewPort ViewPort;
    struct RastPort RastPort;
    struct BitMap BitMap;
    struct Layer_Info LayerInfo;
    struct Gadget *FirstGadget;
    UBYTE DetailPen, BlockPen;
    UWORD SaveColor0;
    struct Layer *BarLayer;
    UBYTE *ExtData, *UserData;
    };

In general, applications don't need to access the fields in the Screen
structure directly; they use Intuition functions to manipulate the screen
instead.  Likewise, applications do not set up the Screen themselves; they
use one of the OpenScreen() calls.  Here is a description of some of the
more interesting members of the Screen structure (it is not meant to be a
complete description of all the fields).

LeftEdge, TopEdge
    The LeftEdge and TopEdge variables give the position of the screen
    relative to the upper left corner of the monitor's visible display
    (as set by the user in the Overscan preferences editor).  If it is
    positioned down or to the right, the values are positive.  If the
    screen is positioned up or to the left, the values are negative.  The
    values are in screen resolution pixels.  In systems prior to V36,
    LeftEdge positioning is ignored and negative TopEdge positions are
    illegal.

    The screen position may be set when the screen is opened or later by
    calling the MoveScreen() function. Note that the screen's actual
    display position may not exactly equal the coordinates given in the
    LeftEdge and TopEdge fields of the Screen structure.  This can cause
    a window which is opened in the visible part of the screen to be
    incorrectly positioned by a few pixels in each direction.  This
    complication is due to hardware constraints that limit the fineness
    of screen positioning.  For instance, high resolution screens can
    only be positioned in low resolution pixel coordinates, yet the
    values in the LeftEdge and TopEdge use high resolution pixel
    coordinates.  So when the screen is displayed, its position is
    rounded to a position available for the monitor.

MouseX, MouseY
    Position of the mouse with respect to the upper left corner of the
    screen.

ViewPort, RastPort, BitMap, LayerInfo
    Actual instances of the graphics library data structures associated
    with this screen (not pointers to structures).  For normal use of
    custom screens, these structures may be ignored.

BarLayer
    A pointer to the Layer structure for the screen's title bar.

WBorTop, WBorLeft, WBorRight, WBorBottom
    Window border values, see the "Intuition Windows" chapter for
    information on pre-calculating the size of window borders for windows
    that open in this screen.

Font
    The default screen font, this can be used to pre-calculate the size
    of the window borders for windows that open in this screen.

UserData
    Free for application use.

Other Screen structure members provide information on the title bar layer,
and attributes of menus and windows opened in the screen.  Of particular
interest are the values that allow precalculation of window border size.
These variables will be discussed in the chapter "Intuition Windows".


3 / Screen Data Structures / Other Screen Data Structures

In addition to the Screen structure, Intuition uses some other supporting
structures defined in the include file <intuition/screens.h> and in
<utility/tagitems.h>.  (See the Amiga ROM Kernel Reference Manual:
Includes and Autodocs for a complete listing.)

      Table 3-2: Data Structures Used with Intuition Screens

  Structure Name  Description                    Defined in Include File
  --------------  -----------                    -----------------------
  Screen          Main Intuition structure that   <intuition/screens.h>
                  defines a screen (see above)

  DrawInfo        Holds the screen's pen, font    <intuition/screens.h>
                  and aspect data for Intuition

  TagItem         General purpose parameter        <utility/tagitem.h>
                  structure used to set up
                  screens in V36

  NewScreen       Parameter structure used to     <intuition/screens.h>
                  create a screen in V34

  ExtNewScreen    An extension to the NewScreen   <intuition/screens.h>
                  structure used in V37 for
                  backward compatibility with
                  older systems

As previously mentioned, there is an Intuition Screen structure (and a
corresponding graphics ViewPort) for every screen in memory.  Under
Release 2, whenever a new screen is created, Intuition also creates an
auxiliary data structure called a DrawInfo.

The DrawInfo structure is similar to a RastPort in that it holds drawing
information.  But where a RastPort is used at the lower graphics level,
the DrawInfo structure is used at the higher Intuition level.
Specifically, DrawInfo contains data needed to support the New Look of
Intuition in Release 2.  (For more information see the section below,
"DrawInfo and the 3D Look".)

Another new feature of Release 2 is tag items.  A TagItem is a general
purpose parameter structure used to pass arguments to many of the
functions in the Release 2 system software.  Each tag consists of a LONG
tag ID (ti_Tag) and a LONG tag data value (ti_Data).  With screens, tag
items are used to describe the attributes an application wants for a new,
custom screen.  Tag items replace the NewScreen structure, the set of
parameters used in older versions of the OS to set up a screen.

Applications may wish to use tag items to set up a new screen instead of
the NewScreen structure since tag items are often more convenient.  For
the sake of backwards compatibility, the ExtNewScreen structure is
available.  ExtNewScreen combines the NewScreen method used to define
screens in older versions of the OS with the tag item method used in
Release 2.  The examples listed in the next section show how these various
data structures can be used to set up a new screen.


3 Intuition Screens / Custom Screen Functions

All applications require a screen to work in.  This can be an existing,
public screen or a new, custom screen created by the application itself.
To create a new, custom screen to work with, you call OpenScreen() or one
of its variants.

                 Table 3-3: Custom Screen Functions
  _____________________________________________________________________
 |                                                                     |
 |     OpenScreenTags()  Create a new, custom screen from a tag list.  |
 |  OpenScreenTagList()  Use either one of these with Release 2 (V36)  |
 |                       or later versions of the OS.                  |
 |                                                                     |
 |         OpenScreen()  Create a new, custom screen from an           |
 |                       ExtNewScreen structure.  Use this if your     |
 |                       application must be compatible with 1.3 (V34) |
 |                       or earlier versions of the operating system.  |
 |                                                                     |
 |        CloseScreen()  Close a custom screen and free the memory     |
 |                       it used.                                      |
 |_____________________________________________________________________|

 Creating A New Custom Screen    Screen Attributes


3 / Custom Screen Functions / Creating A New Custom Screen

There are three functions you can use to open a custom screen:
OpenScreen(), OpenScreenTags() or OpenScreenTagList().  Prior to Release 2
(V36), OpenScreen() was used to create a new screen.  With V36 and later
versions of the operating system, this call is superseded by
OpenScreenTagList() and OpenScreenTags().

   struct Screen *OpenScreen( struct NewScreen *)
   struct Screen *OpenScreenTagList( struct NewScreen * , struct TagItem *)
   struct Screen *OpenScreenTags( struct NewScreen *, ULONG, ULONG, ... )

The old OpenScreen() call relied on a fixed size data structure
(NewScreen) which made little allowance for extensions and growth.  The
new calls are tag based, allowing for the addition of new features without
modification of existing structures and applications.  The
"Screen Attributes" section below contains a complete list of all the tag
options available for setting up an Intuition screen.  For a general
description of tag items, see the "Utility Library" chapter.

 A Custom Screen Example
 Creating A Custom Screen that Works With Older Systems
 Return Values from OpenScreenTagList()
 Closing the Screen


3 / / Creating A New Custom Screen / A Custom Screen Example

There are so many tag options available with screens it can be a bit
overwhelming.  Before discussing more details, it may be helpful to look
at a simple example.  The code below opens a new, custom screen using the
OpenScreenTags() call.  The example uses just two tag items (SA_Depth and
SA_Pens) which provide the minimum attributes needed to make a screen that
uses the new 3D look of Intuition available in Release 2.  (See the
section on "DrawInfo and the 3D Look" below for more information.)

     newlookscreen.c

The example above runs only under Release 2 (V36) and later versions of
the OS.  To make a custom screen that works under both Release 2 and
earlier versions of the operating system, use the original OpenScreen()
function.

The NewScreen structure used with OpenScreen() has been extended with a
tag list in V36 to form an ExtNewScreen.  This is done by setting the
NS_EXTENDED bit in the Type field of the NewScreen structure and adding a
pointer to an array of tags to the end of the structure.  The NS_EXTENDED
bit is ignored in older versions of the operating system, so the tags can
be transparently added to existing applications and the features will
appear when executed in a system running V36 or greater.  See the
OpenScreen() Autodocs and the include file <intuition/screens.h> for more
information on NS_EXTENDED and the ExtNewScreen structure.


3 / / / Creating A Custom Screen that Works With Older Systems

Here's an example of how to use the old OpenScreen() call with an
ExtNewScreen structure to make a new, custom screen under any version of
the Amiga operating system.  If the version is V36 or later, additional
Release 2 features specified via tags, in this case the new 3D look of
Intuition, will be incorporated in the window.

     screen34to37.c

As you can see from the examples above, there are many ways to create a
new, custom screen.  Further references to "OpenScreenTagList()" in this
manual are referring to any one of the three calls: OpenScreenTagList(),
OpenScreenTags(), or OpenScreen() used with tags in an ExtNewScreen as
shown above.


3 / / Creating Custom Screen / Return Values from OpenScreenTagList()

OpenScreenTagList() and its variants return a pointer to a Screen
structure on the successful creation of a new screen and NULL on failure.
With V36, the call now supports extended error codes on failure.  The
error returns provide information on the type of failure, giving the
application a greater chance of recovery.  To get the extended error code,
you need to use the SA_ErrorCode tag; the code itself will be placed into
the LONG pointed to by the TagItem.ti_Data field.  Here are the codes:

OSERR_NOMONITOR
    The monitor needed to display the requested mode is not available. An
    example of this error would be opening a Productivity mode screen on
    a system without a VGA or multisync monitor.

OSERR_NOCHIPS
    Newer custom chips are required for this screen mode.  For instance,
    the ECS Denise is required for the productivity modes.

OSERR_NOMEM
    Could not allocate enough memory.

OSERR_NOCHIPMEM
    Could not allocate enough Chip memory.

OSERR_PUBNOTUNIQUE
    Could not create public screen--name already used.  The system
    requires that public screen names be unique.

OSERR_UNKNOWNMODE
    Display mode requested was not recognized.  The system does not
    understand the value specified with the SA_DisplayID tag.


3 / / Creating A New Custom Screen / Closing the Screen

When an application has finished using a screen, the memory that the
screen occupied should be returned to the system by calling CloseScreen().
Normally, an application should close only those screens that it created.
Under V34 and earlier versions of the OS, CloseScreen() returns no values.
Under Release 2, CloseScreen() returns a boolean value, TRUE for success
and FALSE for failure.  CloseScreen() can fail if the screen is public and
another task is still using the screen.


3 / Custom Screen Functions / Screen Attributes

The sections above discuss only the basic functions and screen types that
Intuition programmers need to understand to create a custom screen.
Intuition supports an astonishing number of additional display features
and options.  In this section and the sections to follow, the finer points
of screen attributes and the functions that control them are presented.

Screen attributes are specified using the tag item scheme described in the
"Utility Library" chapter.  Therefore, the screen attributes are listed
here by tag values.  (In V34, the NewScreen structure was used to set
screen attributes so many of the tag options listed here have a
corresponding flag in NewScreen.)  In general, specifying a tag overrides
the corresponding flag or field in the NewScreen structure if you supply
one.

SA_ErrorCode
    Extended error code.  Data is a pointer to a long which will contain
    the error code on return if OpenScreenTagList() returns NULL. The
    error codes are described above.

SA_Left, SA_Top
    Initial screen position (left edge and top edge).  Data is a long,
    signed value.  Offsets are relative to the text overscan rectangle.

    If SA_Left is not specified and a NewScreen structure is not passed
    in the OpenScreenTags/TagList() call and SA_Width is not specified
    or is specified as STDSCREENWIDTH, then the left edge of the screen
    will default to the left edge of the actual display clip of the
    screen.  If the other conditions are met but some explicit SA_Width
    is specified, then the left edge defaults to zero (text overscan
    rectangle left edge).  Likewise, the top edge may, independent of the
    left edge value, default to zero or to the top edge of the actual
    display clip.  If SA_Top is not specified and a NewScreen structure
    is not passed in the OpenScreenTags/TagList() call and SA_Height is
    not specified or specified as STDSCREENHEIGHT, then the top edge of
    the screen will default to the top edge of the actual display clip of
    the screen.  If the other conditions are met but some explicit
    SA_Height is specified, then the top edge defaults to zero (text
    overscan rectangle top edge).  Prior to V36, left edge positioning is
    ignored and negative top edge positions are illegal.

    When opening a full sized overscan screen, SA_Left should be set to
    the MinX value of the display clip Rectangle used for the screen and
    SA_Top should be set to the MinY value of the display clip.  This may
    be taken from the defaults, as explained above, or explicitly set by
    the application.  See the section below "Overscan and the Display clip"
    and the OpenScreen() Autodoc for more details.

    If your screen is larger than your display clip, you may wish to set
    the SA_Left and SA_Top to values less than your display clip MinX and
    MinY in order to center a large screen on a smaller display.  For an
    example of how to open a centered overscan screen, see
    module/screen.c in the IFF Appendix of the Amiga ROM Kernel Reference
    Manual: Devices.

SA_Width, SA_Height
    Screen dimensions.  Data is a long, unsigned value.  These may be
    larger, smaller or the same as the dimensions of the display clip
    Rectangle.  The use of STDSCREENWIDTH and STDSCREENHEIGHT will make
    the screen size equal to the display clip size.

    To calculate the width of the display clip Rectangle, subtract the
    MinX value from the MaxX value plus one.  Similarly, the height of
    the display clip may be calculated by subtracting the MinY value from
    the MaxY value plus one.

SA_Depth
    Screen bitmap depth.  Data is a long, unsigned value.  The depth of
    the screen determines the number of available colors.  See the
    "Graphics Primitives" for more information on hardware limitations of
    the display.  Do not set the depth to a value greater than that
    supported by the specific display mode.  This information is
    available to the application through the graphics library display
    database.  The default is one bitplane.

SA_DisplayID
    Extended display mode key for the screen.  Data is a long, unsigned
    value.  By using Release 2 DisplayIDs and the display database,
    applications can open a screen in any display mode available on a
    user's system, including PAL and NTSC modes.  See the discussion of
    the display database in the "Graphics Primitives" chapter and the
    include file <graphics/displayinfo.h> for more information.

SA_Pens
    Pen specification for the screen.  Data is a pointer to a UWORD array
    terminated with ~0, as found in the DrawInfo structure.  Specifying
    the SA_Pens tag informs the system that the application is prepared
    to handle a screen rendered with the new 3D look of Intuition.  See
    the section below on "DrawInfo and the 3D Look". Omitting this tag
    produces a screen with a flat look, but whose color usage is more
    backwards compatible.

SA_DetailPen
    Detail pen for the screen.  Data is a long, unsigned value.  Used for
    rendering details in the screen title bar and menus.  Use SA_Pens
    beginning with V36 for more control of pen specification.  If SA_Pens
    is not specified, the screen will not get the new 3D look of
    Intuition available in Release 2.  Instead this value will be used as
    the detail pen.

SA_BlockPen
    Block pen for the screen.  Data is a long, unsigned value.  Used for
    rendering block fills in the screen title bar and menus.  Use SA_Pens
    beginning with V36 for more control of pen specification.  If SA_Pens
    is not specified, the screen will not get the new 3D look and this
    value will be used as the block pen.

SA_Title
    Default screen title.  Data is a pointer to a character string.  This
    is the title displayed when the active window has no screen title or
    when no window is active on the screen.

SA_Colors
    Specifies initial screen palette colors.  Data is a pointer to an
    array of ColorSpec structures, terminated by a ColorSpec structure
    with ColorIndex=-1. Screen colors may be changed after the screen is
    opened with the graphics library functions SetRGB4() and LoadRGB4().
    ColorSpec colors are right-justified, four bits per gun.

SA_FullPalette
    Initialize color table to entire preferences palette (32 colors
    beginning with V36), rather than the subset from V34 and earlier,
    namely pens 0-3, 17-19, with remaining palette as returned by
    GetColorMap().  Data is a boolean value (use TRUE to set the flag).
    Defaults to FALSE.

SA_Font
    Data is a pointer to a TextAttr structure (defined in
    <graphics/text.h> ) which specifies the font, size and style to use
    for the screen.  Equivalent to NewScreen.Font.

SA_SysFont
    Alternative to SA_Font.  Selects one of the preferences system fonts.
    Data is a long, unsigned value, with the following values defined:

        0  Open screen with the user's preferred fixed width font
           (the default).
        1  Open screen with the user's preferred font, which may be
           proportional.

    The Workbench screen is opened with {SA_SysFont , 1}.  Table 3-4
    summarizes how the font selected at OpenScreen() time effects
    subsequent text operations in screens and windows.

                Table 3-4: Intuition Font Selection Chart

       What you tell
       OpenScreen()            Screen font            Window.RPort font
       -------------           -----------            -----------------
    A. NewScreen.Font=myfont  myfont                  myfont
    B. NewScreen.Font=NULL    GfxBase->DefaultFont    GfxBase->DefaultFont
    C. {SA_Font, myfont}      myfont                  myfont
    D. {SA_SysFont, 0}        GfxBase->DefaultFont    GfxBase->DefaultFont
    E. {SA_SysFont, 1}        Font Prefs Screen text  GfxBase->DefaultFont

       Notes:
     * A and B are the options that existed in V34 and earlier OS versions.
     * C and D are tags in Release 2 equivalent to A and B respectively.
     * E is a new option for V36.  The Workbench screen uses this option.
     * For `myfont', any font may be used including a proportional one.
       This is true under all releases of the OS.
     * GfxBase->DefaultFont is always monospace.  (This is the "System
       Default Text" from Font Preferences.)
     * Font Prefs Screen text (the "Screen Text" choice from Font
       Preferences) can be monospace or proportional.

    The screen's font may not legally be changed after a screen is
    opened. The menu bar, window titles, menu items, and the contents of
    a string gadget all use the screen's font.  The font used for menu
    items can be overridden in the menu item's IntuiText structure.
    Under V36 and higher, the font used in a string gadget can be
    overridden through the StringExtend structure.  The font of the menu
    bar and window titles cannot be overridden.

    The Window.RPort font shown above is the initial font that Intuition
    sets in your window's RastPort.  It is legal to change that
    subsequently with SetFont().  IntuiText rendered into a window
    (either through PrintIText() or as a gadget's GadgetText) defaults to
    the window's RastPort font, but can be overridden using its ITextFont
    field.  Text rendered with the graphics library call Text() uses the
    window's RastPort font.

SA_Type
    Equivalent to the SCREENTYPE bits of the NewScreen.Type field.  Data
    is a long, unsigned value which may be set to either CUSTOMSCREEN or
    PUBLICSCREEN (WBENCHSCREEN is reserved for system use).  See the tags
    SA_BitMap, SA_Behind, SA_Quiet, SA_ShowTitle and SA_AutoScroll for
    the other attributes of the NewScreen.Type field.

SA_BitMap
    Use a custom bitmap for this screen.  Data is a pointer to a BitMap
    structure.  This tag is equivalent to NewScreen.CustomBitMap and
    implies the CUSTOMBITMAP flag of the NewScreen.Type field.  The
    application is responsible for allocating and freeing the screen's
    bitmap.

SA_Behind
    Open this screen behind all other screens in the system.  Data is a
    boolean value (TRUE to set flag).  This tag is equivalent to the
    SCREENBEHIND flag of the NewScreen.Type field.

SA_Quiet
    Disable Intuition rendering into screen.  Data is a boolean value
    (TRUE to set flag).  This tag is equivalent to the SCREENQUIET flag
    of the NewScreen.Type field.  The screen will have no visible title
    bar or gadgets, but dragging and depth arrangement still function.
    In order to completely prevent Intuition from rendering into the
    screen, menu operations must be disabled for each window in the
    screen using WFLG_RMBTRAP.

SA_ShowTitle
    Setting this flag places the screen's title bar in front of any
    backdrop windows that are opened on the screen.  Data is a boolean
    value (TRUE to set flag).  This tag is equivalent to the SHOWTITLE
    flag of the NewScreen.Type field.  The title bar of the screen is
    always displayed behind any non-backdrop windows on that screen.
    This attribute can be changed after the screen is open with the
    ShowTitle() function.

SA_AutoScroll
    Setting this flag will enable autoscroll for this screen when it is
    the active screen.  (Currently, the screen may only be made active by
    activating a window in that screen either under user or application
    control.)  Data is a boolean value (TRUE to set flag).  This tag is
    equivalent to the AUTOSCROLL flag of the NewScreen.Type field.

    Autoscroll means that screens larger than the visible display will
    automatically scroll when the user moves the mouse to the edge of the
    screen.  Without this tag, the user moves the screen either by using
    the screen drag bar, or by pressing the mouse select button anywhere
    within the screen while holding down the left Amiga key and moving
    the mouse.

SA_PubName
    Presence of this tag means that the screen is to be a public screen.
    Data is a pointer to a string.  The string is the name of the public
    screen which is used by other applications to find the screen.  This
    tag is order dependent, specify before SA_PubSig and SA_PubTask.

SA_PubSig, SA_PubTask
    Task ID (returned by FindTask()) and signal for notification that the
    last window has closed on a public screen. Data for SA_PubSig is a
    long, unsigned value. Data for SA_PubTask is a pointer to a Task
    structure. These two tags are order dependent, and must be specified
    after the tag SA_PubName.

SA_Overscan
    Set to one of the OSCAN_ specifiers to use a system standard overscan
    display clip and screen dimensions (unless otherwise specified).
    Data is a long, unsigned value.  Do not specify this tag and
    SA_DClip.  SA_Overscan is used to get one of the standard overscan
    dimensions, while SA_DClip is for custom dimensions.  If a display
    clip is not specified with either SA_Overscan or SA_DClip, the
    display clip defaults to OSCAN_TEXT.  See the section below on
    "Overscan and the Display Clip" for more information.

SA_DClip
    Custom display clip specification.  Data is a pointer to a Rectangle
    structure that defines the screen display clip region.


3 Intuition Screens / Public Screen Functions

Public screens are a new feature of Release 2 (V36).  A public screen
allows multiple applications to share a single screen thus saving memory.
If your application opens a public screen, then other applications will be
able to open their windows on your screen.  In older versions of the
operating system, only the Workbench screen could be shared so
applications had to live within its limitations or use up Chip memory
creating their own private, custom screens.

Now the system allows any screen to be set up as a public screen so there
may be many public screens in memory at once, not just Workbench.  This
permits the power user to set up different work environments that multiple
applications can share in a way that is memory efficient (each one with a
display mode appropriate to a particular job).

Workbench is a special case public screen because it is the initial
default public screen.  The default public screen is the screen
applications will get when they ask for a public screen but don't specify
a name.  Under normal conditions, Workbench is the default public screen
and is created by the system at startup time.  However, keep in mind that
the default public screen can be changed (it's not always guaranteed to be
Workbench).

    Screens for the Novice.
    -----------------------
    If you're not sure what kind of screen to use, then use the default
    public screen.  Under Release 2, you can open a window on the default
    public screen without doing any screen set-up work.  See the
    "Intuition Windows" chapter for more details.

Generally, it is much easier to use an existing, public screen than to set
up one of your own.  Here are the basic functions you use to work with an
existing public screen.

                Table 3-5: Public Screen Functions
  ______________________________________________________________________
 |                                                                      |
 |        LockPubScreen()  Find Workbench or any other public screen;   |
 |                         prevent it from closing while a window is    |
 |                         opened or its attributes copied.             |
 |                                                                      |
 |      UnlockPubScreen()  Release the lock allowing the screen to      |
 |                         later be closed.                             |
 |                                                                      |
 |  SetDefaultPubScreen()  Establishes a given public screen as the     |
 |                         default.                                     |
 |                                                                      |
 |  GetDefaultPubScreen()  Copies the name of the default screen to a   |
 |                         user supplied buffer for use by the screen   |
 |                         manager utility (the name is not needed by   |
 |                         normal applications, use LockPubScreen(NULL) |
 |                         instead).                                    |
 |                                                                      |
 |      PubScreenStatus()  Converts a screen to private or public       |
 |                         status.                                      |
 |                                                                      |
 |    SetPubScreenModes()  Controls the public screen global mode bits. |
 |______________________________________________________________________|

By using an existing public screen, an application is no longer
responsible for setting up the display, however, it also loses flexibility
and control.  It can no longer set the palette or depth, and it cannot
write directly into screen memory without cooperation from the owner of
the public screen.  (If these limitations are too confining, the
application can create a new screen instead.)

 Accessing a Public Screen by Name
 The Default Public Screen and Workbench
 Taking a New Custom Screen Public
 Searching the Public Screen List


3 / Public Screen Functions / Accessing a Public Screen by Name

The main calls for accessing an existing public screen are LockPubScreen()
and UnlockPubScreen().  To use these functions you need to know the name
of the public screen you want to access.  If you do not know the name of
the public screen or if you are not sure, you can lock the default public
screen with LockPubScreen(NULL).

    struct Screen *LockPubScreen( UBYTE * )
     VOID        UnlockPubScreen( UBYTE * , struct Screen *)

These calls enable the application to determine that a public screen
exists, and to ensure its continued existence while opening a window on
it.  This function also serves as an improvement over the old
GetScreenData() function from V34 by returning a pointer to the Screen
structure of the locked screen so that its attributes can be examined.

Be sure to unlock the public screen when done with it.  Note that once a
window is open on the screen the program does not need to hold the screen
lock, as the window acts as a lock on the screen.  The pointer to the
screen structure is valid as long as a lock on the screen is held by the
application, or the application has a window open on the screen.

Locks should not be held without reason.  Holding unnecessary locks on
screens may prevent the user from closing a public screen that has no
apparent activity.  Keep in mind that as long as you have a window open on
a public screen, the window acts as a lock preventing the screen from
closing.

Shown here is a simple example of how to find the Workbench public screen
using LockPubScreen() and UnlockPubScreen().

     pubscreenbeep.c


3 / Public Screen Functions / The Default Public Screen and Workbench

As mentioned earlier, Workbench is a special case public screen because it
is the initial default public screen.  There are other reasons Workbench
has a special status.  Normally, it's the first thing the user sees
because it is the default user interface on all Amiga computers.  Many
older applications written for V34 and earlier versions of the OS expect
to run in the Workbench screen.  Also, Workbench is currently the only
public screen supported by system Preferences and the only screen
Intuition can automatically open.

Because of its close ties with the operating system, there are some extra
functions available to manipulate the Workbench screen.  One function
which controls both Workbench and other public screens is
SetPubScreenModes().  This function controls the global public screen mode
bits, SHANGHAI and POPPUBSCREEN.  If the SHANGHAI mode bit is set, older
applications which expect to open on the Workbench screen will open
instead on the default public screen (which may or may not be the
Workbench screen).  The POPPUBSCREEN bit controls whether public screens
will be popped to the front when a window is opened.  These modes are
documented in the "Intuition Windows" chapter in the section on
"Windows and Screens".

Other functions which control the Workbench screen are listed in the table
below.

           Table 3-6: Workbench Public Screen Functions
  ______________________________________________________________________
 |                                                                      |
 |    WBenchToBack()  Move the Workbench screen behind all other        |
 |                    screens.                                          |
 |                                                                      |
 |   WBenchToFront()  Move the Workbench screen in front of all other   |
 |                    screens.                                          |
 |                                                                      |
 |   OpenWorkBench()  Open the Workbench screen.  If the screen is      |
 |                    already open, this call has no effect.  This call |
 |                    will re-awaken the Workbench application if it    |
 |                    was active when CloseWorkBench() was called.      |
 |                                                                      |
 |  CloseWorkBench()  Attempt to reclaim memory used for the Workbench  |
 |                    screen.  If successful, this call closes the      |
 |                    screen and puts the Workbench application to      |
 |                    sleep.  This call fails if any application has    |
 |                    windows open or locks on the Workbench screen.    |
 |______________________________________________________________________|

Programs can attempt to reclaim memory used by the Workbench screen by
calling CloseWorkBench().  Programs that have closed Workbench, should
call OpenWorkBench() as they exit or allow the user to re-open the screen
through a menu or gadget.

If Workbench is closed, any of the following events can re-open it:
calling OpenWorkBench(); opening a window on the Workbench (including
EasyRequests() such as the DOS "Insert Disk" requester); calling
LockPubScreen("Workbench");  calling LockPubScreen(NULL) when Workbench is
the default public screen.


3 / Public Screen Functions / Taking a New Custom Screen Public

Applications that open a new screen should consider taking the screen
public.  If the screen's characteristics are not very esoteric, making the
screen public is useful because it allows other applications to share the
working context.  This makes an application more powerful and more
attractive to the user because it allows the user to add supporting
applications and utilities from other vendors to make a customized and
integrated work environment.

To make your own custom screen into a public screen that other
applications may use, you give the screen a public name and then register
the screen with Intuition.  The screen must be declared as public in the
OpenScreenTagList() call by specifying a public name string with the
SA_PubName tag.  The application's task ID and a signal bit may also be
registered when the screen is opened with the SA_PubTask and SA_PubSig
tags.  If these tags are given, the system will signal your task when the
last window on the screen closes.

When a new public screen is opened, it starts out private so the
application can perform any desired initialization (for instance, opening
a backdrop window) before the screen is made public.  Use the
PubScreenStatus() function to make the screen public and available to
other applications (or to take the screen private again, later).  The
screen may not be taken private or closed until all windows on the screen
are closed and all locksn on the screen are released.  However, the screen
does not need to be made private before closing it.

CloseScreen() will fail if an attempt is made to close a public screen
that still has visitor windows or locks on it.  If the user selects close
screen, but the screen will not close due to visitor windows, a requester
should be displayed informing the user of the condition and instructing
them to close any windows before closing the screen.


3 / Public Screen Functions / Searching the Public Screen List

To access an existing public screen the application may take one of three
approaches.  To get a lock on the default public screen, either
LockPubScreen(NULL) or {WA_PubScreenName , NULL} may be used.

If the name of the screen is known, the application may use
LockPubScreen() to gain a lock on the screen as shown in the
example above (or use OpenWindowTagList() with the WA_PubScreenName tag as
described in the  "Intuition Windows" chapter).  Failure to lock the
screen or open the window probably indicates that the screen does not
exist.

A third approach is to search the public screen list for a screen that
meets the requirements of the application.  These requirements may be
related to the name or attributes of the screen.  Here are the functions
to use with the public screen list maintained by Intuition.

                Table 3-7: Public Screen List Functions
  _____________________________________________________________________
 |                                                                     |
 |    LockPubScreenList()  Lock the public screen list maintained by   |
 |                         Intuition so that it may be quickly copied. |
 |                                                                     |
 |  UnlockPubScreenList()  Release the lock on the public screen list. |
 |                                                                     |
 |        NextPubScreen()  Find the next screen in the public screen   |
 |                         list.                                       |
 |_____________________________________________________________________|

The main function used to access the public screen list is
LockPubScreenList().  This function, intended for use by the public screen
manager utility, locks the list to allow data from it to be quickly
copied.  The list is stored in an Exec List structure, with each node in
the list being a PubScreenNode structure.  See <intuition/screens> for
details.

Do not interpret the list while in a locked state, instead, copy any
values required to local variables and release the lock.  All required
data must be copied, including the name of the screen which is not part of
the structure.  Pointers that reference the list or structures attached to
the list are not valid after releasing the lock.  Once the lock is
released, the screen pointers in the list (psn_Screen) may be tested for
equality against other screen pointers, but referencing any part of the
screen structure from this pointer is strictly illegal.  After the lock is
released with UnlockPubScreenList(), the application may access the data
in the screen structure by obtaining a lock on the screen using
LockPubScreen() with the name of the screen.

The application should only require accessing three fields in the
PubScreenNode, these are ln_Name, psn_Screen and psn_Flags.  The name of
the public screen is maintained in the ln_Name field of the Node
(psn_Node) structure.  Access to other information on the screen may be
done by getting a lock on this name and reading the data from the Screen
structure.  The screen pointer (psn_Screen) may only be used for testing
against other screen pointers, never reference the screen structure from
this value.  Finally, the public screen flags are maintained in psn_Flags.
Currently, only PSNF_PRIVATE is defined for this field.  PSNF_PRIVATE
indicates that the screen is not currently public.

Remember that all information in the public screen list is transitory,
that is, it may change at any time.  Do not rely on the values in the
list.  The only way to ensure the existence or mode of a screen is to lock
it, either directly with LockPubScreen() or by opening a window on the
screen.  To update the copy of the list, lock it and copy the data again.
Don't forget to release the lock when finished.

As an alternative to dealing with the public screen list, NextPubScreen()
can be used.  This call takes the name of a public screen as its argument
and returns the name of the next screen in the public screen list.  This
helps an application move a window through the entire rotation of public
screens.  Repeated calls to NextPubScreen() could be used to get the names
of all public screens one at a time.  Keep in mind though that the list of
public screens is subject to sudden change; the task that owns a public
screen might close it after you obtain the name, but before you access the
screen.

Always use LockPubScreen() to access screen information after scanning the
public screen list.


3 Intuition Screens / DrawInfo and the 3D Look

In Release 2, whenever a new screen is created, Intuition also creates an
auxiliary data structure called a DrawInfo.  The DrawInfo structure
provides information Intuition uses to support the new 3D look of Release
2 and  specifies graphical information for applications that use the
screen.  The information includes such items as aspect ratio (resolution),
font, number of colors and drawing pens.

struct DrawInfo
{
    UWORD       dri_Version;    /* will be  DRI_VERSION                 */
    UWORD       dri_NumPens;    /* guaranteed to be >= numDrIPens       */
    UWORD       *dri_Pens;      /* pointer to pen array	                */

    struct TextFont     *dri_Font;  /* screen default font              */
    UWORD       dri_Depth;          /* (initial) depth of screen bitmap */

    struct {    /* from DisplayInfo database for initial display mode   */
    UWORD   X;
    UWORD   Y;
    }           dri_Resolution;

    ULONG       dri_Flags;              /* defined below                */
    ULONG       dri_Reserved[7];        /* avoid recompilation ;^)      */
};

Before an application uses fields in the DrawInfo structure, it should
check the version of the structure to ensure that all fields are
available.  If the field dri_Version is greater than or equal to the
constant DRI_VERSION that the application was compiled with, it can be
assured that all fields in DrawInfo that it knows about are being
supported by Intuition.

 The Pen Specification in DrawInfo
 The Font Specification in DrawInfo
 Cloning a Public Screen (Workbench)


3 / DrawInfo and the 3D Look / The Pen Specification in DrawInfo

The drawing pen specification in DrawInfo.dri_Pens allows applications to
use appropriate colors for graphic operations such as drawing text,
shading 3D objects and filling items selected by the user.

Intuition has two default sets of pens, one for multi-bitplane screens and
one for single bitplane screens.  In addition, there is a special
compatibility mode for screens that do not specify the SA_Pens tag.

New 3D Look
    The is the full 3D look as found by default on the Workbench screen
    in Release 2.  Objects are drawn so that light appears to come from
    the upper left of the screen with shadows cast to the lower right
    giving them a three-dimensional look.

Monochrome New Look
    It is impossible to produce the full 3D look in a single bitplane
    (two color) screen.  Intuition provides a fallback pen specification
    that is used in monochrome screens with no loss of information.

Compatible New Look
    Custom screens that do not provide the SA_Pens tag are assumed to
    have no knowledge of the pen array.  They are rendered in a special
    version of the monochrome new look, which uses the screen's DetailPen
    and BlockPen to get its colors.  This is provided for compatibility
    with V34 and older versions of the operating system.

It is very easy for an application to use the default pen specification.
Simply specify an empty pen specification (in C, {~0}), and Intuition will
fill in all of the values with defaults appropriate for the screen.  This
technique is demonstrated in the first two examples (newlookscreen.c and
screen34to37.c)listed earlier in this chapter.

For certain applications, a custom pen specification is required.  A
custom pen specification is set up when the screen is opened by using the
SA_Pens tag and a pointer to a pen array.  Currently, Intuition uses nine
pens to support the 3D look.  The application can specify all of these, or
only a few pens and Intuition will fill in the rest.  Intuition will only
fill in pens that are past the end of those specified by the application,
there is no facility for using default values for "leading" pens (those at
the beginning of the array) without using the defaults for the rest of the
pens.

Using the pen specification of an existing public screen is a bit more
involved.  First, the application must get a pointer to the screen
structure of the public screen using the LockPubScreen() call.  A copy of
the screen's DrawInfo structure may then be obtained by calling
GetScreenDrawInfo().  The DrawInfo structure contains a copy of the pen
specification for the screen that can be used in the OpenScreenTagList()
call with the SA_Pens tag.  The pen array is copied to the data structures
of the new screen (it is not kept as a pointer to the information passed),
so the application may immediately call FreeScreenDrawInfo() and
UnlockPubScreen() after the new screen is open.

     publicscreen.c

Beginning with V36, the pen specification for the Workbench screen happens
to match the Intuition default specification, however, this is not
required and may change in the future.  To create a screen that uses the
pens defined in the Workbench screen, the application must get a copy of
the pen array from the Workbench screen and use this copy with the SA_Pens
tag as described above.

Here is a list of the pens defined under V36 that support the 3D look
along with their uses.  To read the value of a particular pen, use UWORD
penvalue = myDrawInfo->dri_Pens[PENNAME], where myDrawInfo is a pointer to
a DrawInfo structure and PENNAME is taken from the list below:

DETAILPEN
    Pen compatible with V34. Used to render text in the screen's title bar.

BLOCKPEN
    Pen compatible with V34. Used to fill the screen's title bar.

TEXTPEN
    Pen for regular text on BACKGROUNDPEN.

SHINEPEN
    Pen for the bright edge on 3D objects.

SHADOWPEN
    Pen for the dark edge on 3D objects.

FILLPEN
    Pen for filling the active window borders and selected gadgets.

FILLTEXTPEN
    Pen for text rendered over FILLPEN.

BACKGROUNDPEN
    Pen for the background color.  Currently must be zero.

HIGHLIGHTTEXTPEN
    Pen for "special color" or highlighted text on BACKGROUNDPEN.


3 / DrawInfo and the 3D Look / The Font Specification in DrawInfo

Font information for a screen comes from a number of different places.

SA_Font
    The application may specify the font to be used in a screen by
    providing the SA_Font tag with a TextAttr structure.  In this case,
    the font will be used by the screen and will be the default font for
    the RastPort of any window opening in the screen.

SA_SysFont, 0
    If the application requests the user's preferred monospace font, it
    is taken from GfxBase->DefaultFont.  Any window's RastPorts are also
    initialized to use this same font.

SA_SysFont, 1
    The screen font selected by the user from the Preferences font editor
    may be used for the screen by using the SA_SysFont tag.  This font,
    the "preferred screen font", may be proportional.  For compatibility
    reasons, if this font is specified for the screen, the window's
    RastPort will be initialized to GfxBase->DefaultFont (a
    non-proportional font).

To access information on an open screen's font, the application may
reference Screen.Font or DrawInfo.dri_Font.  These fonts are identical,
the DrawInfo structure simply provides an alternate method of accessing
the information.  Note that Screen.Font is a pointer to a TextAttr
structure and that DrawInfo.dri_Font is a pointer to a TextFont structure.
The application may use whichever form is best suited to its requirements.

It is illegal to change the screen's font after the screen is opened.
This means that the font specified in the Screen and DrawInfo structures
is guaranteed to remain open as long is the screen is open.

The menu bar, window titles, menu items, and the contents of a string
gadget all use the screen's font.  The font used for menu items can be
overridden in the menu item's IntuiText structure.  Under V36 and higher,
the font used in a string gadget can be overridden through the
StringExtend structure.  The font of the menu bar and window titles cannot
be overridden.

For more information on screen fonts, see the description of the SA_Font
and SA_SysFont tags in the "Screen Attributes" section above.


3 / DrawInfo and the 3D Look / Cloning a Public Screen (Workbench)

User preferences for screen attributes are generally reflected in the
Workbench screen or in the default public screen.  In some cases it may be
useful to create a new screen with the same attributes.

Under V34, information on a screen was available through the
GetScreenData() call.  Due to extensions in V36 screen and graphics
capabilities, this call is no longer sufficient to completely describe the
display.  Applications should now use a variety of calls; the specific
call depends on the information required.

LockPubScreen() returns a pointer to the Screen structure of a specific
screen.  GetScreenDrawInfo() returns rendering information on the screen,
such as the pen array and font used.  QueryOverscan() returns the overscan
information of a specific display mode (for more information, see the
section on "Overscan and the Display Clip").

The example below shows how to use GetScreenDrawInfo() to examine the
attributes of the Workbench screen so that a new screen with the same
attributes can be created.

    struct DrawInfo *GetScreenDrawInfo( struct Screen * )

The attributes required to clone an existing screen are its width, height,
depth, pens and mode.  The pens and screen depth are available through the
DrawInfo structure.  The width and height may be obtained from the Screen
structure.  (The width and height may be larger than the overscan area if
the screen is scrollable, and autoscroll may always be enabled as it does
not effect displays smaller than or equal to the overscan area.)

The screen's display mode can be obtained using the graphics library call
GetVPModeID().  This call returns the display ID of an existing screen
which can then be used as the data for the SA_DisplayID tag in
OpenScreenTagList().  Note that the example assumes the screen should be
open to the user's text overscan preference.  If an exact copy of the
display clip of the existing screen is required, use the VideoControl()
command of the graphics library to access the ViewPortExtra structure.

The colors of the screen may be copied using the graphics library calls
GetRGB4(), SetRGB4(), SetRGB4CM() and LoadRGB4().  The example code does
not copy the colors.

The example copies the font from the cloned screen.  A reasonable
alternative would be to use the user's preference font, which may be
accessed through the SA_SysFont tag.

     clonescreen.c


3 Intuition Screens / Overscan and the Display Clip

Screens may be larger or smaller than the defined display area (overscan
rectangle or display clip).  When a screen is smaller than the display
area, the display clip acts as a "container" for the screen.  The screen
may be moved anywhere within the display clip.  When a screen is larger
than the display area, the display clip acts as a "window" into the
screen.  The screen may be moved so that different parts are visible.
Each dimension of the screen is independent and may be larger than, the
same as, or smaller than the dimensions of the display clip.

The system is very flexible in its specification of screen size.  Unless
an application fixes its screen size with hard coded values, it should be
prepared to handle the possibility that the user has changed the default
overscan presets or the default monitor (NTSC/PAL).

Use the constants STDSCREENHEIGHT and STDSCREENWIDTH with the SA_Width and
SA_Height tags to open a screen the same size as the display clip.  These
constants will work with any of the preset overscan values set with
SA_Overscan, and with custom overscan values set with SA_DClip.

 Preset Overscan Values


3 / Overscan and the Display Clip / Preset Overscan Values

Four preset overscan dimensions are provided.  Applications that support
overscan should use these preset values where possible since they will be
tailored to each individual system.  Avoid using custom values that happen
to look good on a specific system.  However, be aware that the size and
positioning of overscan screens can be different on every system depending
on how the user has set Overscan Preferences.  These preset values are
also dependent on the underlying display mode so keep in mind that both
offset and size parameters will change under different screen modes.
Overscan presets can be used, among other things, with the SA_Overscan tag
to set the size of the screen's display clip or passed as an argument to
QueryOverscan() to find their current overscan settings.

OSCAN_TEXT
    This overscan region is based on user preference settings and
    indicates a display that is completely within the visible bounds of
    the monitor. The View origin is set to the upper left corner of the
    text overscan rectangle which is the highest leftmost point known to
    be visible on the physical display.  This position is set by the user
    through the Overscan Preferences editor.  All screen positions and
    display clips are relative to this origin.

OSCAN_STANDARD
    The edges of OSCAN_STANDARD display are also based on user
    preferences and are set to be just outside the visible bounds of the
    monitor.  OSCAN_STANDARD provides the smallest possible display that
    will fill the entire screen with no border around it.  Parts of the
    display created with OSCAN_STANDARD may not be visible to the user.

OSCAN_MAX
    Create the largest display fully supported by Intuition and the
    graphics library.  This is the largest size for which all enclosed
    sizes and positions are legal.  Parts of the display created with
    OSCAN_MAX may not be visible to the user.

OSCAN_VIDEO
    Create the largest display, restricted by the hardware.  This is the
    only legal size and position that is possibly (but not necessarily)
    larger than OSCAN_MAX.  You must use the exact size and position
    specified.  OSCAN_VIDEO does not support variable left edge, top edge
    positioning.  Parts of the display created with OSCAN_VIDEO may not
    be visible to the user.

If custom clipping is required, a display clip may be explicitly specified
using the SA_DClip tag and a Rectangle structure specification.  This
custom rectangle must fit within the OSCAN_MAX rectangle, offset included.
It is not permitted to specify custom rectangles whose values are in
between OSCAN_MAX and OSCAN_VIDEO, nor is it permitted to specify
rectangles larger than OSCAN_VIDEO.  For an example of how to open a
centered overscan screen based on user preferences, see the
module/screen.c listing in the IFF Appendix of the Amiga ROM Kernel
Reference Manual: Devices.

Use the Graphics library call VideoControl() to find the true display clip
of a screen.  See the Graphics Autodocs and the chapter
"Graphics Primitives" for more information on VideoControl().  The
ViewPortExtra structure contains the display clip information.

If any dimension of a screen is not equal to the equivalent display clip
dimension, then the screen may be scrolled. If the screen's dimensions are
smaller than the display clip, then the screen may be positioned within
the display clip. If the screen is larger than the display clip, then it
may be positioned such that any part of the screen is visible.

AutoScroll may be activated by setting the tag SA_AutoScroll. Screens will
only scroll when they are the active screen. Activate a window in the
screen to make the screen active.

    About the Default Display Clip.
    -------------------------------
    The default display clip for a screen is the entire screen, that
    is, the rectangle starting from the upper left corner of the screen
    and ending at the lower right corner of the screen.  This display
    clip is only used if the application does not specify SA_Overscan or
    SA_DClip.  When using this default display clip the screen will not
    scroll as the screen exactly fits into the clipping region.

When opening a window in an overscanned screen, it is often useful to open
it relative to the visible part of the screen rather than relative to the
entire screen.  Use QueryOverscan() to find the overscan region and where
the screen is positioned relative to it.

    LONG QueryOverscan(ULONG displayID,
                       struct Rectangle *rect, WORD overscanType )

This example was taken from the chapter "Intuition Windows" in the section
"A Display Sized Window Example". The complete example is reproduced
there.

/* this technique returns the text overscan rectangle of the screen that
** we are opening on.  If you really need the actual value set into the
** display clip of the screen, use the VideoControl() command of the
** graphics library to return a copy of the ViewPortExtra structure.  See
** the Graphics library chapter and Autodocs for more details.
**
** GetVPModeID() is a graphics call...
*/

screen_modeID = GetVPModeID(&(pub_screen->ViewPort))))
if (screen_modeID != INVALID_ID)
    {
    if ( QueryOverscan(screen_modeID, &rect, OSCAN_TEXT) )
        {
        /* if this screen's origin is up or to the left of the */
        /* view origin then move the window down and to the right */
        left = max(0, -pub_screen->LeftEdge);
        top  = max(0, -pub_screen->TopEdge);

        /* get width and height from size of display clip */
        width  = rect.MaxX - rect.MinX + 1;
        height = rect.MaxY - rect.MinY + 1;

        /* adjust height for pulled-down screen (only show visible part) */
        if (pub_screen->TopEdge > 0)
            height -= pub_screen->TopEdge;

        /* ensure that window fits on screen */
        height = min(height, pub_screen->Height);
        width  = min(width,  pub_screen->Width);

        /* make sure window is at least minimum size */
        width  = max(width,  MIN_WINDOW_WIDTH);
        height = max(height, MIN_WINDOW_HEIGHT);
        }
    }


3 Intuition Screens / Intuition Screens and the Graphics Library

As previously mentioned, an Intuition screen is related to a number of
underlying graphics library structures.

         Table 3-8: Graphics Data Structures Used with Screens

    Structure Name  Description                   Defined in Include File
    --------------  -----------                   -----------------------
    View            Root structure of the            <graphics/view.h>
                    graphics display system

    ViewPort        The graphics structure that      <graphics/view.h>
                    corresponds to a screen

    BitMap          Contains size and pointers to    <graphics/gfx.h>
                    the screen's bit planes

    ColorMap        Contains size and pointer to     <graphics/view.h>
                    the screen's color table

    RastPort        Holds drawing, pen and font    <graphics/rastport.h>
                    settings and the BitMap
                    address

These data structures are unified in Intuition's Screen structure (which
also incorporates higher level Intuition constructs such as menus and
windows).  Here's a brief explanation of the graphics library structures
used with Intuition.

View
    The View is the graphics structure that corresponds to the whole
    display, including all visible screens.  The system has just one
    View; it's what you see on the monitor.  The address of the View may
    be obtained from any screen by using ViewAddress().

ViewPort
    The ViewPort is the underlying graphics structure corresponding to a
    screen.  Every screen has one ViewPort.  To get the address of the
    ViewPort from the Screen structure, use (&my_screen-> ViewPort).
    From the ViewPort an application may obtain pointers to all the
    screen's bitplanes and to its color table.

BitMap
    The BitMap structure contains pointers to all the bit planes (up to
    8) and their sizes.  For future compatibility, use
    (my_screen->RastPort.BitMap) to get the address of the BitMap from
    the screen rather than (&my_screen->BitMap).

    The BitMap.BytesPerRow field specifies the number of bytes that have
    been allocated for each raster line.  This may be larger than the
    screen width depending on display alignment restrictions.  Alignment
    restrictions may change.  Always use this variable, not a hard-coded
    value.

ColorMap
    The ColorMap contains a pointer to the color table, an array of 32
    WORDs for the hardware color registers.  Use SetRGB4(), GetRGB4(),
    SetRGB4CM() and LoadRGB4() from the graphics library to access the
    color table.  Do not read or write it directly.

RastPort
    A RastPort controls the graphics rendering to any display area (not
    just screens).  Screens have a RastPort to allow direct rendering
    into the screen.  Applications may find the RastPort address of a
    screen with (&my_screen->RastPort).  This generally is not useful
    since applications normally render into windows.

 Changing Screen Colors
 Direct Screen Access
 Screen Functions That Integrate Intuition and Graphics
 Limitations of the Graphics Subsystem


3 / Intuition Screens and Graphics Library / Changing Screen Colors

Screen colors are set at the time the screen is opened with the SA_Colors
tag.  If the colors need to be changed after the screen is opened, the
graphics library function, LoadRGB4() should be used.  To change a single
entry in the color table, use SetRGB4() and SetRGB4CM().  See the
"Graphics Primitives" chapter for more information on these functions.


3 / Intuition Screens and the Graphics Library / Direct Screen Access

Sometimes an application may want direct access to the custom screen's
bitmap to use with low-level graphics library calls.  This may be useful
if the application needs to do custom manipulation of the display but also
needs Intuition functionality.  For instance, an application may want to
use the graphics library primitives to perform double buffering then, when
detecting user input, switch to Intuition control of the screen so that
windows, gadgets and menus may be used to process the user input.  If an
application chooses to combine these techniques, it must take special care
to avoid conflicts with Intuition rendered graphics.  An example of how to
do this is listed in the next section, "Advanced Screen Programming".

Application programs that open custom screens may use the screen's display
memory in any way they choose.  However, this memory is also used by
Intuition for windows and other high level display components on the
screen.  Writing directly to the screen memory, whether through direct
access or through graphics library calls that access the screen's
RastPort, is not compatible with many Intuition constructs such as windows
and menus.

Techniques such as this require great care and understanding of the Amiga.
If possible, the application should avoid these techniques and only use
standard Intuition display and input processing.  Directly accessing the
screen's bitmap, while possible, is not recommended.  A better way to
access the screen display is through windows.  Windows provide access to
the screen through layers which perform clipping and arbitration between
multiple drawing areas.

Alternatives to writing directly to a screen, such as using a backdrop
window, greatly limit the number of cases where an application must access
screen memory.  The ShowTitle() function allows the screen's title bar
layer to be positioned in front of or behind any backdrop windows that are
opened on the screen.  Hence, a backdrop window may be created that uses
the entire visible area of the monitor. Application programs that use
existing public screens do not have the same freedom to access the
screen's display memory as they do with custom screens.  In general,
public screens must be shared through the use of windows and menus rather
than directly accessing the screen's display memory.

    Use Direct Access Only On Screens You Own.
    ------------------------------------------
    An application may not steal the bitmap of a screen that it does not
    own.  Stealing the Workbench screen's bitmap, or that of any other
    public screen, is strictly illegal.  Accessing the underlying
    graphics structures of a screen may only be done on custom screens
    opened by the application itself.

    Do Not Perform Layers Operations Directly.
    ------------------------------------------
    While layers are not part of the graphics library, it is appropriate
    to mention them here.  Certain types of layers operations are not
    allowed with Intuition.  You may not, for example, call SizeLayer()
    on a window (use SizeWindow() instead). To access layers library
    features with screens, use Intuition windows!

A custom screen may be created to allow for modification of the screen's
Copper list.  The Copper is the display synchronized co-processor that
handles the actual video display by directly affecting the hardware
registers.  See the Amiga Hardware Reference Manual or the graphics
library chapters for more information on programming the Copper.


3 / / Screen Functions That Integrate Intuition and Graphics

These functions, normally used only by the system, integrate high-level
Intuition structures with the lower-level constructs used by the graphics
library to create the display.

    Table 3-9: Screen Functions That Integrate Intuition and Graphics
  _______________________________________________________________________
 |                                                                       |
 |      MakeScreen()  Update a single screen's copper list               |
 |                                                                       |
 |  RethinkDisplay()  Merge copper lists from all screens to form a View |
 |                                                                       |
 |   RemakeDisplay()  Update all screen copper lists then merge them to  |
 |                    form a View                                        |
 |_______________________________________________________________________|

Advanced Intuition programmers may use these functions to achieve special
screen effects such as double-buffering or dual-playfield Intuition
screens.  For examples of these see the next section.

MakeScreen() updates, but does not install, a screen's Copper list.  This
function is the Intuition equivalent of the low-level MakeVPort() graphics
library function.  MakeScreen() performs the MakeVPort() call,
synchronized with Intuition's own use of the screen's ViewPort.  Call
RethinkDisplay() after MakeScreen() to allow the new Copper list for the
screen to take effect.  The MakeScreen() function takes one argument, a
pointer to the Screen that contains the Copper list to be updated.

RethinkDisplay() combines all the screen's copper lists into a single
view.  This procedure performs the Intuition global display
reconstruction, which includes massaging some of Intuition's internal
state data, rethinking all of the Intuition screen ViewPorts and their
relationship to one another, and, finally, reconstructing the entire
display by merging the new screens into the graphics View structure.
Custom screens that handle their own Copper instructions, use this call to
install the Copper list previously updated with MakeScreen().
RethinkDisplay() calls lower-level graphics primitives MrgCop() and
LoadView() to install the Copper list.  This function takes no arguments.

RemakeDisplay() remakes the entire Intuition display.  It is equivalent to
calling MakeScreen() for each screen in the system, then calling
RethinkDisplay().  This routine performs a MakeVPort() (graphics
primitive) on every Intuition screen and then calls RethinkDisplay() to
recreate the View.  It takes no arguments.

Both RemakeDisplay() and RethinkDisplay() take several milliseconds to run
and lock out all other tasks while they run.  This can seriously degrade
system performance, so do not use these routines lightly.


3 / Screens and Graphics Lib / Limitations of the Graphics Subsystem

If each of the visible screens does not have the same physical attributes,
it may not be possible to display the data in its proper screen mode.
Screen coercion is the technique that allows multiple screens with
differing physical attributes to be displayed simultaneously.  When a
coerced screen is visible, its aspect ratio and colors may appear
significantly changed.  This is normal and the screen will be displayed
correctly when it is the frontmost screen.

Hardware restrictions prevent certain types of displays.  For instance,
screens always use the full width of the display, regardless of the width
of the overscan rectangle.  This prevents any changes in display mode
within a video line.  Other modes, such as the VGA modes, require specific
revisions of the custom chips and may not be available on all machines.
See the "Graphics Primitives" chapter and the Amiga Hardware Reference
Manual for more information on Amiga display organization and limitations.


3 Intuition Screens / Advanced Screen Programming

This section discusses how to perform double-buffering of Intuition
screens, how to create a dual-playfield Intuition screen and other
advanced topics.

 Double Buffering    Dual-Playfield Screen Example


3 / Advanced Screen Programming / Double Buffering

Double buffering of an Intuition screen involves the swapping of bitmaps
of the screen, then updating the copper list to install the changes.  The
trick is that after installing the bitmaps to the screen the display is
not updated to access these new bitmaps until the program explicitly
updates the copper list.  Any rendering performed before the copper list
is updated will be rendered into the off-display bitmaps, appearing on the
screen in completed form when the copper list is updated.

First, install the alternate bitmaps into the screen.

    /* switch the bitmap so that we are drawing into the correct place */
    screen->RastPort.BitMap          = myBitMaps[toggleFrame];
    screen->ViewPort.RasInfo->BitMap = myBitMaps[toggleFrame];

Rendering may then take place into the off screen bitmaps by drawing into
screen->RastPort.

The copper list of the screen is updated by calling MakeScreen(). This
call refreshes the copper list, but does not install it into the system.
Call RethinkDisplay() to install the new copper list so that the data is
visible.

    /* update the physical display to match the newly drawn bitmap. */
    MakeScreen(screen); /* Tell intuition to do its stuff.          */
    RethinkDisplay();   /* Intuition compatible MrgCop & LoadView   */
                        /*               it also does a WaitTOF().  */

Note that it is possible for the user to force the updating of the
screen's copper list by dragging or depth-arranging the screen. This may
cause information to be displayed before it is complete.

A complete example of double buffering a screen follows.

     doublebuffer.c


3 / Advanced Screen Programming / Dual-Playfield Screen Example

This example shows how to create a dual-playfield display.  Note that this
technique is only valid for screen modes which support dual-playfield, do
not try to convert other modes.

Setting up dual playfield mode in the OpenScreen() call is not the best
method of obtaining a dual playfield viewport for a screen.  It is better
to open a standard screen, passing to Intuition (or letting Intuition
create) only one of the playfield bitmaps (the front one).  Next allocate
and set up a second bitmap, its bitplanes, and a RasInfo structure
installing these into the new screen's viewport.  Update the viewport
modes to include DUALPF and call MakeScreen() and RethinkDisplay().  This
method, shown in the example below, keeps Intuition rendering (gadgets,
menus, windows) in a single playfield.

     dualplayfield.c


3 Intuition Screens / Other Screen Functions

Other screen functions provided by Intuition control screen depth
arrangement, screen movement, the screen title bar and provide a visual
"error beep".

 Screen Depth Arrangement
 Screen Movement and Scrolling
 Miscellaneous Screen Functions


3 / Other Screen Functions / Screen Depth Arrangement

ScreenToFront() and ScreenToBack() make a screen either the frontmost or
the backmost screen.  If an application needs to render into a screen
before the screen becomes visible to the user, the screen may be opened
behind all other screens and later moved to the front when ready with
ScreenToFront().

    VOID ScreenToFront( struct Screen * )
    VOID ScreenToBack ( struct Screen * )

Depth control of screens is also available through the depth arrangement
gadget in the screen's title bar or through keyboard shortcuts.  The N key
with the Left-Amiga qualifier moves the Workbench screen to front.  The M
key with the Left-Amiga qualifier moves the frontmost screen to back.
Repeated selection of Left-Amiga-M will cycle through available screens.
These keys are processed through the keymap and will retain their value
even if the key location changes.


3 / Other Screen Functions / Screen Movement and Scrolling

The MoveScreen() function moves the screen origin by the number of pixels
specified in dx and dy.

    VOID MoveScreen( struct Screen *myscreen, WORD dx, WORD dy )

Calls to MoveScreen() are asynchronous; the screen is not necessarily
moved upon return of this function.  If the calls happen too quickly,
there may be unexpected results.  One way to pace these calls is to call
the function one time for each IDCMP_INTUITICKS event.

Screen movement is also available through the screen's drag gadget in the
title bar and through a keyboard/mouse shortcut.  Left-Amiga with the
select button of the mouse anywhere within the screen will drag the screen
(even if the title bar is totally concealed by a window).  Dragging a
screen down will reveal any screen(s) behind it.  Screens are never
revealed to the left, right or bottom of another screen.

Additionally, oversized screens may be moved with the new autoscroll
feature of Release 2.  With autoscroll, the screen is automatically
scrolled as the pointer reaches one of the edges of the display.
Autoscroll only works on the active screen.

Another screen movement feature added in Release 2 is screen menu snap.
When a screen much larger than the viewing area is scrolled such that the
upper left corner is not visible (scrolled down or to the right), menus
may could be out of the visible portion of the screen.  To prevent this,
menu snap moves the screen to a position where the menus will be visible
before rendering them.  The screen appears to snap to the home position as
the menus are selected, moving back when the operation is complete.  If
the Left-Amiga qualifier is held when the menus are selected then the
screen will remain in the home position when the menu button is released.

The Intuition preferences editor, IControl, allows the user to change a
number of Intuition features.  Some of these features include the ability
to globally disable menu snap, and to change the select qualifier for
dragging the screen.  See the User's Manual for more information on
Preferences editors.


3 / Other Screen Functions / Miscellaneous Screen Functions

Three other functions used with screens are DisplayBeep(), ShowTitle() and
GetScreenData().  DisplayBeep() flashes the screen colors to inform the
user of an error or problem.

    VOID DisplayBeep( struct Screen *myscreen )

Since not all users will have speakers attached to the system,
DisplayBeep() can be used to provide a visible bell.  DisplayBeep() can
beep any single screen or, if myscreen is set to NULL, all screens.

ShowTitle() determines whether the screen's title bar will be displayed in
front of or behind any backdrop windows on the screen.

    VOID ShowTitle( struct Screen *myscreen, BOOL infront )

By default, the screen's title bar is set to display in front of backdrop
windows.  Call this function with infront set to FALSE to put the screen
title bar behind backdrop windows.  This can also be set when the screen
is opened with the SA_ShowTitle tag.

Under 1.3 (V34) and earlier versions of the Amiga OS, applications used
the GetScreenData() to get a copy of the Workbench Screen structure in
order to examine its attributes.

    success = BOOL GetScreenData( APTR buffer, UWORD bufsize,
                                  UWORD type, struct Screen *scr)

If successful, GetScreenData() copies a given Screen structure to a buffer
supplied by the application.  A copy of the Workbench Screen data can be
obtained without knowing its location in memory using GetScreenData(buf,
sizeof(struct Screen), WBENCHSCREEN, NULL).  However, for Release 2 and
later versions of the operating system, this function may return some
false information about the Workbench screen.  This false screen
information helps prevent older applications that used the call from
malfunctioning when run in a Release 2 system that has Workbench set up
with one of the newer modes.

Applications that want to get information on the Workbench screen should
use GetScreenData() when run under 1.3 and LockPubScreen() when run under
under Release 2.  For more about LockPubScreen() and Workbench, see the
section on "Public Screen Functions" earlier in this chapter.


3 Intuition Screens / Function Reference

The following are brief descriptions of the Intuition functions that
relate to the use of Intuition screens.  See the Amiga ROM Kernel
Reference Manual: Includes and Autodocs for details on each function call.

             Table 3-10: Functions for Intuition Screens
  ______________________________________________________________________
 |                                                                      |
 |          Function                  Description                       |
 |======================================================================|
 |    OpenScreenTagList()  Open a screen.                               |
 |       OpenScreenTags()  Alternate calling sequence for               |
 |                         OpenScreenTagList().                         |
 |           OpenScreen()  Pre-V36 open screen function.                |
 |          CloseScreen()  Close an open screen.                        |
 |----------------------------------------------------------------------|
 |           MoveScreen()  Change the position of an open screen.       |
 |         ScreenToBack()  Move a screen behind all other screens.      |
 |        ScreenToFront()  Move a screen in front of all other screens. |
 |            ShowTitle()  Show the screen in front of through backdrop |
 |                         windows.                                     |
 |----------------------------------------------------------------------|
 |    GetScreenDrawInfo()  Get the DrawInfo information for an open     |
 |                         screen.                                      |
 |   FreeScreenDrawInfo()  Free the DrawInfo information for a screen.  |
 |----------------------------------------------------------------------|
 |        QueryOverscan()  Find overscan information for a specific     |
 |                         display type.                                |
 |----------------------------------------------------------------------|
 |        LockPubScreen()  Obtain a lock on a public screen.            |
 |      UnlockPubScreen()  Release a lock on a public screen.           |
 |        NextPubScreen()  Return the name of the next public screen in |
 |                         the list.                                    |
 |      PubScreenStatus()  Make a public screen private or private      |
 |                         screen public.                               |
 |----------------------------------------------------------------------|
 |    LockPubScreenList()  Lock the public screen list (for a public    |
 |                         screen utility).                             |
 |  UnlockPubScreenList()  Unlock the public screen list.               |
 |  SetDefaultPubScreen()  Change the default public screen.            |
 |    SetPubScreenModes()  Establish global public screen behavior.     |
 |  GetDefaultPubScreen()  Copies the name of the default public screen |
 |                         to a buffer.                                 |
 |----------------------------------------------------------------------|
 |        OpenWorkBench()  Open the Workbench screen, if closed.        |
 |       CloseWorkBench()  Close the Workbench screen, if possible.     |
 |         WBenchToBack()  Move the Workbench screen behind all other   |
 |                         screens.                                     |
 |        WBenchToFront()  Move the Workbench screen in front of all    |
 |                         other screens.                               |
 |        GetScreenData()  Pre-V36 way to return information on an open |
 |                         screen.                                      |
 |----------------------------------------------------------------------|
 |          ViewAddress()  Return the address of a screen's View.       |
 |      ViewPortAddress()  Use &screen->ViewPort instead.               |
 |----------------------------------------------------------------------|
 |           MakeScreen()  Low level screen handling--rebuild Copper    |
 |                         list.                                        |
 |       RethinkDisplay()  Low level screen handling--incorporate       |
 |                         Copper list changes.                         |
 |        RemakeDisplay()  MakeScreen() for all screens, then           |
 |                         RethinkDisplay().                            |
 |______________________________________________________________________|


Amiga® RKM Libraries: 4 Intuition Windows

This chapter provides a general description of windows: how to open
windows and define their characteristics; how to get the system gadgets
for shaping, moving, closing, and depth arranging windows; how to handle
window I/O; and how to preserve the display when windows get overlapped.

 About Windows                            The Window Structure
 Basic Window Structures and Functions    Window Attributes
 Communicating with Intuition             Other Window Functions
 Window Types                             Function Reference
 Preserving the Window Display


4 Intuition Windows / About Windows

Windows are rectangular display areas that open on screens.  The window
acts as a virtual terminal allowing a program to interact with the user as
if it had the entire display all to itself.

Each window opens on a specific screen and takes certain characteristics,
such as resolution, colors and display attributes, from that screen. These
values cannot be adjusted on a window by window basis.  Other window
characteristics such as the text font are inherited from the screen but
can be changed.

An application may open several windows at the same time on a single
screen.  The Workbench and other public (shareable) screens allow windows
opened by different applications to coexist on the same screen.

Windows are moveable and can be positioned anywhere within the screen on
which they exist.  Windows may also have a title and borders containing
various gadgets for controlling the window.

 Window System Gadgets    The Active Window


4 / About Windows / Window System Gadgets

Each window may have a number of system gadgets which allow the user to
control window size, shape and arrangement.  These gadgets are: the drag
bar, the depth gadget, the sizing gadget, the zoom gadget and the close
gadget.

The drag bar allows the user to change the position of the window with
respect to the screen.  The drag bar is in the top border of a window and
occupies any space in the top border that is not used by other gadgets.
The window may be dragged left, right, up and down on the screen, with the
limitation that the entire window must remain within the screen's
boundaries.  This is done by positioning the pointer over the title bar,
selecting the window and dragging to the new position.  Window drag may be
cancelled by pressing the right mouse button before the drag is completed.

     Figure 4-1: A Window with System Gadgets

The depth gadget allows the user to depth arrange a window with respect to
other windows on the screen.  The depth gadget is always positioned in the
upper right corner of the window.  Clicking the depth gadget will move the
frontmost window behind all other windows.  If the window is not the
frontmost, it will be moved to the front.  Selecting the depth gadget with
the Shift qualifier always moves the window to the back (behind other
windows).

The sizing gadget allows the user to change the size of the window.
Sizing is subject to minimum and maximum values set by the application.
Width and height are independent in a sizing operation.  The sizing gadget
is always positioned in the lower right corner of the window.  It allows
the user to drag this corner of the window to a new position relative to
the upper left corner of the window, thus changing the width and height of
the window. Window sizing using the sizing gadget may be cancelled by
pressing the right mouse button before the size is completed.

The zoom gadget allows the user to quickly alternate between two preset
window size and position values.  The zoom gadget is always placed
immediately to the left of the depth gadget.  If there is no depth gadget
on the window, the zoom gadget will still appear next to where the depth
gadget would have been.

The close gadget performs no direct action on the window, rather it causes
Intuition to send a message to the application to close the window. This
allows the application to perform any required processing or to warn the
user before it closes the window.  The close gadget is always positioned
in the upper left corner of the window.


4 / About Windows / The Active Window

There is only one window in the system active at any time.  The active
window receives all user input, including keyboard and mouse events.  This
is also known as the input focus, as all input is focused at this single
point.

Some areas of the active window are displayed more boldly than those on
inactive windows.  The active window's borders are filled in with a color
which is designed to stand out from the background while inactive windows
have their borders filled with the background color.  The specific
coloring of active and inactive windows is dependent on the screen on
which the window is opened.  See the section "DrawInfo and the 3D Look" in
the "Intuition Screens" chapter for more information.

Windows have two optional titles:  one for the window and one for the
screen.  The window title appears in the top border of the window,
regardless of whether the window is active or inactive.  The window's
screen title appears in the screen's title bar only when the window is
active.  This gives the user a secondary clue as to what application is
active in the screen.

The active window's menus are displayed on the screen when the right mouse
button (the menu button ) is pressed.  If the active window has no menus,
then none will be displayed.

Each window may also have its own mouse-pointer image.  Changing the
active window will change the pointer to the one currently set for the new
active window.


4 Intuition Windows / Basic Window Structures and Functions

This section introduces the basic data structures and functions an
application uses to create an Intuition window.  Intuition uses the Window
data structure defined in <intuition/intuition.h> to represent windows.
Most of Intuition's window functions use this structure in some way.
Other related structures used to create and operate windows are summarized
in Table 4-1.

       Table 4-1: Data Structures Used with Intuition Windows

  Structure Name  Description                    Defined in Include File
  --------------  -----------                    -----------------------
  Window          Main Intuition structure that  <intuition/intuition.h>
                  defines a window

  TagItem         General purpose parameter        <utility/tagitem.h>
                  structure used to set up
                  windows in V37

  NewWindow       Parameter structure used to    <intuition/intuition.h>
                  create a window in V34

  ExtNewWindow    An extension to the NewWindow  <intuition/intuition.h>
                  structure used in V37 for
                  backward compatibility with
                  older systems

  Layer           A drawing rectangle that          <graphics/clip.h>
                  clips graphic operations
                  falling within its boundaries

  RastPort        General purpose handle used     <graphics/rastport.h>
                  for graphics library drawing
                  operations.

Intuition's window system relies on the layers library and graphics
library to implement many of its features.  The Window structure is
closely related to the Layer structure defined in <graphics/clip.h> and
the RastPort structure defined in <graphics/rastport.h>.  The system uses
these structures to store drawing state data. In general, applications
don't have to worry about the internal details of these structures but use
them instead as convenient handles, passing them as arguments to
lower-level functions. See the "Layers Library" and "Graphics Primitives"
chapters for more information.

 Opening a Window                Window Dimensions
 Closing Windows                 Window Border Dimensions
 Windows and Screens             Changing Window Size Limits
 Graphics and Text in Windows


4 / Basic Window Structures and Functions / Opening a Window

A window is opened and displayed by a call to one of the OpenWindow()
functions:  OpenWindow(), OpenWindowTagList() or OpenWindowTags().

    struct Window *OpenWindowTagList( struct NewWindow *newWindow,
                                     struct TagItem *tagList );
    struct Window *OpenWindowTags( struct NewWindow *newWindow,
                                  unsigned long tag1Type, ... );
    struct Window *OpenWindow( struct NewWindow *newWindow );

The type of window and its attributes are specified in NewWindow or
TagItem structures depending on which function is used.  These functions
all return a pointer to a new Window structure if they succeed.  A NULL
return indicates failure.

OpenWindowTagList() and OpenWindowTags() are available only in Release 2
(V36) and later versions of the OS.  For these functions, window
attributes are specified in TagItem structures which are paired data items
specifying an attribute and its setting.  (See the `Utility Library'
chapter for more information on TagItems.)

OpenWindow() is available in all versions of the OS.  Window attributes
can be specified using a NewWindow structure but only a limited set of
window attributes are available this way.  To support both the new window
features of Release 2 and compatibility with older versions of the OS, use
OpenWindow() with an extended version of the NewWindow structure named
ExtNewWindow.  See the WFLG_NW_EXTENDED flag description in the "Window
Attributes" section below for more information on using OpenWindow() with
the extended NewWindow structure.

Further references to OpenWindow() in this chapter will apply to all three
functions.  These calls are the only proper method for allocating a Window
structure.  The tag based versions are recommended for V36 and later
versions of the OS.  Use the ExtNewWindow structure with OpenWindow() to
provide backward compatibility.

 OpenWindowTagList() Example    Setting Window Attributes


4 / / Opening A Window / Setting Window Attributes

Depending on which function is used to open a window, the window's
attributes may be specified using TagItems, or a NewWindow structure or an
ExtNewWindow structure.  In the code above, the window attributes are set
up with an array of TagItems:

    struct TagItem win_tags[] =
        {
        {WA_Left,       MY_WIN_LEFT},
        {WA_Top,        MY_WIN_TOP},
        {WA_Width,      MY_WIN_WIDTH},
        {WA_Height,     MY_WIN_HEIGHT},
        {WA_CloseGadget,TRUE},
        {WA_IDCMP,      IDCMP_CLOSEWINDOW},
        {TAG_DONE, NULL},
        };

These window attributes set the window's position (WA_Left, WA_Top) and
size (WA_Width, WA_Height), request a close gadget on the window
(WA_CloseGadget) and ask Intuition to send a message whenever the user
activates the close gadget (WA_IDCMP).

Throughout this chapter window attributes are referred to by their TagItem
ID name (the name is always prefixed with "WA_").  See the section below
on "Window Attributes" for a complete list.

    Old and New Flag Names.
    -----------------------
    The names used for IDCMP flags and window flags have been changed
    under Release 2.  IDCMP flag names are now preceded by "IDCMP_".
    Likewise window flag names are now preceded by "WFLG_".  The old
    names (and their new equivalents) are listed in
    <intuition/iobsolete.h>.  You may want to refer to this file if
    you are working with example code written for V34 and older versions
    of the OS.


4 / Basic Window Structures and Functions / Closing Windows

Call the CloseWindow() function to close a window, remove its imagery from
the display, and clean up any system resources used by the window.
Typically, you call CloseWindow() when Intuition informs you that the user
has selected the window's close gadget but this is not a requirement nor
does the window have to be active to be closed.

    void CloseWindow( struct Window *window );

Pass this function a pointer to the Window structure returned by one of
the OpenWindow() calls.

If you call CloseWindow() on the active window, the previously active
window (if available) will become the active window.  If the previously
active window has already closed, then the window active prior to that
window will become the active window.  (Applications should not rely on
this behavior.  To make a specific window become active, call the
ActivateWindow() function.)

Intuition does not automatically close a window when the user selects the
close window gadget.  Instead, Intuition sends your program a message
about the user's action.  The program can then perform whatever cleanup is
necessary before closing the window with the CloseWindow() function.


4 / Basic Window Structures and Functions / Windows and Screens

Windows may be opened on one of three screen types:  a custom screen, a
public screen or the Workbench screen.  A custom screen is one created and
controlled by your application.  Once you have set up a custom screen, you
may open a window on it directly by calling one of the three open window
functions.

To open a window on a custom screen, call OpenWindowTagList() (or
OpenWindowTags()) with the WA_CustomScreen tag along with a pointer to the
custom screen.  This must be a pointer to a screen created by your
application.  For systems prior to Release 2, use the OpenWindow() call
with NewWindow.Type set to CUSTOMSCREEN and NewWindow.Screen set to a
pointer to your custom screen.

You may choose to open a window on an existing public (shareable) screen
instead of setting up your own custom screen.  Such windows are often
referred to as visitor windows because they "visit" a screen managed by
the system or another application.

For Workbench or other public screens that are not created and managed
directly by your application, you must lock the screen before opening the
window.  This ensures that the screen remains open while your call to open
the window is processed.  One way to obtain a lock on a public screen is
by calling the LockPubScreen() function (see the "Intuition Screens"
chapter).

Use WA_PubScreenName with NULL to open a visitor window on the default
public screen (normally the Workbench screen).  If a name is provided and
the named screen exists, the visitor window will open on that named
screen.  In this case the system locks the named screen for you so there
is no need to call LockPubScreen() directly.  The open window call will
fail if it cannot obtain a lock on the screen.  If the
WA_PubScreenFallBack tag is TRUE, the window will open on the default
public screen when WA_PubScreenName can't be found.

Another method to open a visitor window on a public screen is to use the
WA_PubScreen tag along with a pointer to the Screen structure of the
public screen obtained via LockPubScreen().

The application may also request the name of the "next" public screen,
which allows windows to "jump" between public screens.  This is done by
closing the application window on the first screen and opening a new
window on the next screen.  (See the "Intuition Screens" chapter for more
information on public and custom screens.)

If no action is taken by the programmer to open the window on a specific
screen, the window will open on the default public screen (normally the
Workbench).  This behavior is shown in the above example using
OpenWindowTagList().

There are two global modes which come into play when a visitor window is
opened on a public screen.  If the global mode SHANGHAI is set, Workbench
application windows will be opened on the default public screen.  A second
global mode, POPPUBSCREEN, forces a public screen to be moved to the front
when a visitor window opens on it.  These modes can be changed using
SetPubScreenModes(), however, these should only be set according to the
preferences of the user.

 Simple Window on a Public Screen Example


4 / Window Structures and Functions / Graphics and Text in Windows

Applications can call functions in both the graphics library and the
Intuition library to render images, lines, text and other graphic elements
in windows.  The graphics library provides primitive operations such as
area fill, line drawing, text and animation.

The number of colors and the palette available in a window are defined by
the screen in which the window opens.  Applications should never change
the palette of a screen unless the screen is a custom screen created by
the application.

Graphics rendered into the window should respect the drawing pens defined
for the screen.  See the section on "DrawInfo and the 3D Look" in the
"Intuition Screens" chapter for more information.

Default window fonts come from one of two places, depending on the screen
on which the window opens.  The window title font is always taken from the
screen font.  If the screen is opened with a font specified, either by
specifying the tag SA_Font or the variable NewScreen.Font, then
Window.RPort->Font is taken from the screen's font.  Otherwise, the
window's rastport's font is taken from GfxBase->DefaultFont. This
information is available to the application if it opened the screen.

If the application did not open the screen, it has no way of knowing which
font has been used for the window.  Applications that require to know the
window's font before the window is open must explicitly set the font
(using SetFont()) for that window after opening it.  In this case, the
application may use any font it desires.  It is recommended that
applications use the screen's font if they support proportional fonts, and
GfxBase->DefaultFont otherwise, as these fonts are generally the user's
preference.

Intuition also provides a minimal high level interface to some of the
functions in the Graphics library.  This includes calls to draw lines,
text and images.  See the chapter entitled
"Intuition Images, Line Drawing and Text," for more information about
using Intuition to render graphics.


4 / Basic Window Structures and Functions / Window Dimensions

The initial position and dimensions of the window are defined in the
OpenWindowTagList() call.  These values undergo error checking before the
window is actually opened on the screen.  If the dimensions are too big,
the window will fail to open.  (Or, you can use the WA_AutoAdjust tag if
you want Intuition to move or size your window to fit.)

Maximum and minimum size values may also be defined, but are not required
If the window does not have a sizing gadget.  In setting these dimensions,
bear in mind the horizontal and vertical resolutions of the screen in
which the window will open.

The maximum dimensions of the window are unsigned values and may legally
be set to the maximum by using the value 0xFFFF, better expressed as "~0".
Using this value for the maximum dimensions allows the window to be sized
to the full screen.

 A Display Sized Window Example


4 / / Window Dimensions / A Display Sized Window Example

A full screen window is not always desirable.  If the user is working on a
large, scrolling screen, they may only want a window the size of the
visible display.  The following example calculates the visible area on a
screen and opens a window in that area.  The example assumes that the
screen display clip is as large or larger than text overscan (OSCAN_TEXT)
which is set by the user.  The window is opened in the text overscan area,
not within the actual display clip that is used for the screen.  Use
QueryOverscan() to find the standard overscan rectangles (display clips)
for a screen.  Use the graphics library call VideoControl() to find the
true display clip of the screen (see the chapter on "Graphics Primitives"
for more information on VideoControl()).  The ViewPortExtra structure
contains the display clip information.

    About Screen Coordinates.
    -------------------------
    The screen's actual position may not exactly equal the coordinates
    given in the LeftEdge and TopEdge fields of the Screen
    structure.  This is due to hardware constraints that limit the
    fineness of the positioning of the underlying constructs.  This may
    cause a window which is opened in the visible part of the screen to
    be incorrectly positioned by a small number of pixels in each
    direction.  See the discussion of the screen's LeftEdge and
    TopEdge in the "Intuition Screens" chapter for more information.

     visiblewindow.c


4 / Basic Window Structures and Functions / Window Border Dimensions

Intuition automatically draws a border around a window unless directed
otherwise, such as by setting the WFLG_BORDERLESS flag.  Borderless
windows may not have a window title or gadgets in the border (this
includes the standard system gadgets).  Otherwise they won't come out
properly borderless.

The size of the border of an open window is available in the Window
structure variables BorderLeft, BorderTop, BorderRight and BorderBottom.
Intuition fills these in when the window is opened.  To calculate the
window border sizes before the window is opened you use information in the
Screen structure as shown in the next listing.

    Gadgets Can Change Border Sizes.
    --------------------------------
    The following calculations do not take application border gadgets
    into account. If the program adds gadgets into the window's borders,
    Intuition will expand the borders to hold the gadgets.

if (NULL != (screen = LockPubScreen(NULL)))
    {
    top_border    = screen->WBorTop + screen->Font->ta_YSize + 1;
    left_border   = screen->WBorLeft;
    right_border  = screen->WBorRight;
    bottom_border = screen->WBorBottom;

    UnlockPubScreen(NULL,screen);
    }

/* if the sizing gadget is specified, then the border size must
** be adjusted for the border containing the gadget.  This may
** be the right border, the bottom border or both.
**
** We are using fixed values.  There is currently no system-approved
** method of finding this information before the window is opened.
** If you need to know these sizes BEFORE your window is opened,
** use the fixed values below.  Otherwise, use Window->BorderRight,
** etc. AFTER you have opened your window.
*/

/* values for non-lo-res screen */
right_border  = 18;  /* if sizing gadget in right border  */
bottom_border = 10;  /* if sizing gadget in bottom border */

/* values for lo-res screen */
right_border  = 13;  /* if sizing gadget in right border  */
bottom_border = 11;  /* if sizing gadget in bottom border */

Use the border sizes to position visual elements within the window.
Coordinates may be offset into the window by the size of the top and left
borders, for instance (x, y) becomes (x + BorderLeft, y + BorderTop).
This may look clumsy, but it offers a way of avoiding a GimmeZeroZero
window, which, although much more convenient to use, requires extra memory
and degrades performance.

The right and bottom border values specify the width of these borders.
The area within the borders of a window is defined as (BorderLeft,
BorderTop) to (Width - 1 - BorderRight, Height - 1 - BorderBottom).  The
calculations subtract one from the height and width of the windows as
positions count from zero, but dimensions count from one.

The window title bar is only available if one or more of the following is
specified:  window title, window drag gadget, window depth gadget, window
close gadget or window zoom gadget.  If none of these are specified, the
top border will be much narrower.

Application gadgets may be added to the window border by setting a flag in
the Gadget structure.  A special flag must additionally be set to place
gadgets into the borders of GimmeZeroZero windows.  See the chapter
"Intuition Gadgets," for more information about gadgets and their
positioning.  (Borderless windows have no visible border outlines and
gadgets should not be placed in their borders.)


4 / Window Structures and Functions / Changing Window Size Limits

To change the sizing limits after the window has been opened, call
WindowLimits() with the new values.

   BOOL WindowLimits( struct Window *window, long widthMin, long heightMin,
                      unsigned long widthMax, unsigned long heightMax );

To maintain the current dimension, set the corresponding argument to 0.
Out of range numbers are ignored.  If the user is currently sizing the
window, new limits take effect after the user releases the select button.


4 Intuition Windows / Communicating with Intuition

Intuition can notify an application when the user moves the mouse, makes a
menu choice, selects an application gadget or changes the window's size.
To find out about user activity from Intuition, there are two methods:

  * Use the Intuition Direct Communications Message Port (IDCMP) system.
    Input events are received as standard Exec messages at a port
    Intuition creates for your window.

  * Use the console.device to receive all input events as character
    sequences.

 The IDCMP             The IDCMP And The Active Window
 The Console Device    The IDCMP And Gadgets


4 / Communicating with Intuition / The IDCMP

The IDCMP gives an application convenient access to many types of user
input events through the Exec message and port system.  Intuition input
event messages include mouse and keyboard activity as well as high level
events from menus and gadgets.

With the IDCMP, you specify the input events you want to know about when
you open the window.  The input events are specified with one or more of
the IDCMP flags in <intuition/intuition.h>.  Use the flags with the
WA_IDCMP tag for the OpenWindowTagList() (or OpenWindowTags()) function.
Or, set the flags in NewWindow.IDCMPFlags for the OpenWindow() function.  If
any IDCMP flags are set when the window is opened, Intuition automatically
creates a message port for you to receive messages about user activity.
If NULL is specified for IDCMP flags, no port is created.  For more
information on receiving messages from Intuition, see the IDCMP sections
in the chapter "Intuition Input and Output Methods."


4 / Communicating with Intuition / The Console Device

An alternative to the message system used by the IDCMP is the console
device.  The console device gives your application input data translated
to ASCII characters or ANSI escape sequences.  Raw (untranslated) input is
also available through the console device as ANSI escape sequences.

The console device also provides for convenient output of control codes
and non-proportional (mono-spaced) text to the window.  Output is
character based, and includes capabilities such as automatic line wrapping
and scrolling.  The console device automatically formats and interprets
the output stream.  Output is kept within the window boundaries
automatically so the application need not worry about overwriting the
border (no GimmeZeroZero window required).

The console device must be opened by the application before it is used.
See the chapter entitled "Intuition Input and Output Methods" or refer to
the "Console Device" chapter of the Amiga ROM Kernel Reference Manual:
Devices for more information about using the console device with your
Intuition windows.


4 / Communicating with Intuition / The IDCMP And The Active Window

On the Amiga, all input is directed to a single window called the active
window.  In general, changing the active window should be left up to the
user.  (The user activates a window by pressing the select button while
the pointer is within the window boundaries.)  If the active window is
changed, the user may be confused if the change was not performed at their
direction.  Hence, new windows should be activated only when they open as
a direct and synchronous response to the user's action.  Existing windows
should almost never be activated by the application.

An application can learn when one of its windows is activated or
deactivated by setting the IDCMP flags IDCMP_ACTIVEWINDOW and
IDCMP_INACTIVEWINDOW. When these flags are specified, the program will
receive a message each time the user activates the window or causes the
window to become inactive by activating some other window.

The application may specify that a window is to become active when it
opens.  This is done with the WA_Activate tag or by setting WFLG_ACTIVATE
in NewWindow.Flags when the window is opened.

The application may also activate an existing window.  This is done by
calling the ActivateWindow() function, which will activate the window as
soon as possible.  Try to use this function only in response to user
action since it may cause a shift in the input focus:

    LONG ActivateWindow( struct Window *window );

This function call may have its action deferred.  Do not assume that the
selected window has become active when this call returns.  Intuition will
inform the application when this window has become active by sending an
IDCMP_ACTIVEWINDOW message.  Getting this message is the only supported
way of tracking the activation status of your windows.


4 / Communicating with Intuition / The IDCMP And Gadgets

One way for a user to communicate with a program running under Intuition
is through the use of gadgets.  There are two basic kinds of gadgets:
system gadgets, which are predefined and managed by Intuition, and
application gadgets.

 System Gadgets    Application Gadgets


4 / / The IDCMP And Gadgets / System Gadgets

System gadgets on each window provide the user with the ability to manage
the following aspects of the window:  size, position and depth.  These
gadgets are managed by Intuition and the application does not need to take
any action for them to operate properly.  An additional system gadget is
provided for the "close window" function.  The close action is not
directly managed by Intuition; selecting the close gadget will simply send
a message to the application, which is responsible for closing the window.

All of these gadgets are optional, and independent of each other.  The
graphic representations of these gadgets are predefined, and Intuition
always displays them in the same standard locations in the window borders.

The application may choose to be notified when the window changes size, or
it may choose to control the timing of the sizing of the window.
Controlling the timing of sizing operations is done through the use of the
IDCMP_SIZEVERIFY message.  IDCMP_SIZEVERIFY messages time out if the
application does not respond fast enough.  When these an IDCMP_SIZEVERIFY
message times out the window sizing operation is cancelled by Intuition.

No information is available to the program on user changes to the depth
arrangement of a window.  However a refresh message will be sent if part
of the window needs to be redrawn as a result of a change to the depth
arrangement.

Notification of changes to the position of the window or the size of the
window are available through the IDCMP_CHANGEWINDOW and IDCMP_NEWSIZE
flags.  The application specifies the initial size, the maximum and
minimum limits for sizing, and whether the sizing gadget is contained in
the right border, bottom border or both borders.  (See the section on
"Border Dimensions" for information on how the specification of the sizing
gadget affects the border sizes.)

The drag gadget has no imagery other than the implicit imagery of the
title bar.  Setting the window title does not interfere with drag gadget
operation, nor does the drag gadget interfere with the display of the
window title.


4 / / The IDCMP And Gadgets / Application Gadgets

The application may place gadgets in windows to request various kinds of
input from the user.  These gadgets may be specified in the
OpenWindowTagList() call, or they may be created and added to the window
later.  For details about creating and using gadgets, see the chapters on
"Intuition Gadgets" and the "GadTools Library".


4 Intuition Windows / Window Types

There are three special window types:  Backdrop, Borderless and
GimmeZeroZero.  Backdrop windows stay anchored to the back of the display.
Borderless windows have no borders rendered by Intuition. GimmeZeroZero
windows provide clipping to protect the borders from graphics rendered
into the window.

These window types can be combined, although the combinations are not
always useful.  For instance, a borderless, backdrop window can be
created; however, a borderless, GimmeZeroZero window does not make sense.
A window is not required to be any of these types.

 Backdrop Window Type      GimmeZeroZero Window Type
 Borderless Window Type


4 / Window Types / Backdrop Window Type

Backdrop windows open behind all other non-backdrop windows, but in front
of other backdrop windows that might already be open.  Depth arrangement
of a backdrop window affects the order of the window relative to other
backdrop windows, but backdrop windows always stay behind all non-backdrop
windows.  No amount of depth arrangement will ever move a non-backdrop
window behind a backdrop window.

The only system gadget that can be attached to a backdrop window is the
closewindow gadget. Application gadgets are not restricted in backdrop
windows.

Backdrop windows may often be used in place of drawing directly into the
display memory of a custom screen.  Such a technique is preferred, as
backdrop windows are compatible with the Intuition windowing system.
Using a backdrop window eliminates the danger of writing to the screen
memory at a "bad" time or at the wrong position and overwriting data in a
window.

To provide a full screen display area that is compatible with the
windowing system, create a full sized, borderless, backdrop window with no
system gadgets.  Use the ShowTitle() call to hide or reveal the screen's
title bar, as appropriate.  See the Amiga ROM Kernel Reference Manual:
Includes and Autodocs for a complete list of arguments for ShowTitle().

Backdrop windows are created by specifying the WFLG_BACKDROP flag or the
WA_Backdrop tag in the OpenWindowTagList() call.


4 / Window Types / Borderless Window Type

The borderless window type has no borders rendered by Intuition.  Such a
window will have no visual delineation from the rest of the display.  Be
aware that a Borderless window which does not cover the entire display may
cause visual confusion for the user.  When using a borderless window that
does not cover the entire display, the application should provide some
form of graphics to replace the borders provided by Intuition.

In general, none of the system gadgets or the window title should be
specified for a borderless window, as they may cause at least part of the
border to be rendered.

A typical application of a borderless window is to simulate graphics drawn
directly into the screen, while remaining compatible with windows and
menus. In this case, the application will often create a full sized,
borderless, backdrop window.

Use the WFLG_BORDERLESS flag or the WA_Borderless tag to get this window
type.


4 / Window Types / GimmeZeroZero Window Type

GimmeZeroZero windows provide a window border layer separate from the main
(inner) window layer.  This allows the application to freely render into
the window without worrying about the window border and its contents.

System gadgets and the window title are placed in the border layer.
Application gadgets go into the inner window by default, but may be placed
in the border.  To position application gadgets in the border layer, the
GTYP_GZZGADGET flag and the appropriate Gadget border flag must be set in
the Activation field of the Gadget.

The top left coordinates of the inner window are always (0,0), regardless
of the size or contents of the border, thus the name "GimmeZeroZero."  The
application need not take the border size into account when rendering.
The inner window always begins at (0,0) and extends to
(GZZWidth,GZZHeight).  The GZZWidth and GZZHeight variables are available
in the Window structure.

The GZZMouseX and GZZMouseY variables provide the position of the mouse
relative to the inner window.  Note that the mouse positions in
IDCMP_MOUSEMOVE events are always relative to the total window, even for
GimmeZeroZero windows.

Requesters in a GimmeZeroZero window are also positioned relative to the
inner window.  See the chapter entitled "Intuition Requesters and Alerts,"
for more information about requester location.

To specify a GimmeZeroZero window, set the WFLG_GIMMEZEROZERO flag or the
WA_GimmeZeroZero tag in the OpenWindowTagList() call.

    WARNING!
    --------
    The GimmeZeroZero window uses more system resources than other window
    types because the window creates a separate layer for the border
    display.  Using multiple GimmeZeroZero windows will quickly degrade
    performance in the positioning and sizing of windows.

    Applications should consider using regions as an alternative to
    GimmeZeroZero windows.  See the "Layers Library" chapter,
    especially the InstallClipRegion() function, for information on
    setting up regions to limit graphics display in the window.


4 Intuition Windows / Preserving the Window Display

The layers library is what allows the display and manipulation of multiple
overlapping rectangles, or layers.  Intuition uses the layers library to
manage its windows, by associating a layer to each window.

Each window is a virtual display.  When rendering, the application does
not have to worry about the current size or position of its window, and
what other windows might be partly or fully obscuring its window.  The
window's RastPort is the handle to the its virtual display space.
Intuition and graphics library rendering calls will recognize that this
RastPort belongs to a layer, and act accordingly.

As windows are moved, resized, rearranged, opened, or closed, the
on-screen representation changes.  When part of a window which was visible
now needs to appear in a new location, the layers library will move that
imagery without involving the application.  However, when part of a window
that was previously obscured is revealed, or when a window is made larger,
the imagery for the newly-visible part of the window needs to be redrawn.
Intuition, through layers, offers three choices for how this is managed,
trading off speed, memory usage, and application complexity.

  * The most basic type of window is called Simple Refresh.  When any
    graphics operation takes place in this kind of window, the visible
    parts are updated, but rendering to the obscured parts is discarded.
    When the window arrangement changes to reveal a previously obscured
    part of such a window, the application must refresh that area.

  * Alternately, a window may be made Smart Refresh, which means that
    when rendering occurs, the system will not only update the visible
    parts of the window, but it will maintain the obscured parts as well,
    by using off-screen buffers.  This means that when an obscured part
    of the window is revealed, the system will restore the imagery that
    belongs there.  The application needs only to refresh parts of the
    window that appear when the window is made bigger.  Smart Refresh
    windows use more memory than Simple Refresh windows (for the storage
    of obscured areas), but they are faster.

  * The third kind of window is called SuperBitMap.  In such a window,
    the system can refresh the window even when it is sized bigger.  For
    this to work, the application must store a complete bitmap for the
    window's maximum size.  Such a window is more work to manage, and
    uses yet more memory.  SuperBitMap windows are used less often than
    the other two types.

Intuition helps your application manage window refresh.  First, Intuition
will take care of redrawing the window border and any system and
application gadgets in the window.  Your application never has to worry
about that.  Second, Intuition will notify your application when it needs
to refresh its window (by sending the IDCMP_REFRESHWINDOW event).  Third,
Intuition provides functions that restrict your rendering to the
newly-revealed (damaged) areas only, which speeds up your refresh
rendering and makes it look cleaner.

The Intuition, layers, and graphics libraries work together to make
rendering into and managing windows easy.  You obtain your windows through
Intuition, which uses the Layers library to manage the overlapping,
resizing, and re-positioning of the window layers.  The layers library is
responsible for identifying the areas of each window that are visible,
obscured but preserved off-screen, or obscured and not preserved.  The
rendering functions in the graphics library and Intuition library know how
to render into the multiple areas that layers library establishes.

 Note that you may not directly manipulate layers on an Intuition screen.
You cannot create your own layers on an Intuition screen, nor can you use
the layers movement, sizing, or arrangement functions on Intuition
windows.  Use the corresponding Intuition calls instead. Some other
Layers library calls (such as the locking calls) are sometimes used on
Intuition screens and windows.

 Damage Regions                  Optimized Window Refreshing
 Refreshing Intuition Windows    Setting Up a SuperBitMap Window
 Intuition Refresh Events


4 / Preserving the Window Display / Damage Regions

The layers library and Intuition maintain a damage region for each window,
which is the part of the window whose imagery is in need of repair, or
refreshing.  Several things can add areas of the window to the damage
region:

  * Revealing an obscured part of a Simple Refresh window adds that area
    to the damage region

  * Sizing a Simple or Smart Refresh window bigger along either axis adds
    the new area to the damage region

  * Resizing a Simple or Smart Refresh window (smaller or bigger) adds
    the old and new border areas, and the areas occupied by certain
    gadgets (those whose position or size depend on window size) to the
    damage region.


4 / Preserving the Window Display / Refreshing Intuition Windows

When the user or an application performs an Intuition operation which
causes damage to a window, Intuition notifies that window's application.
It does this by sending a message of the class IDCMP_REFRESHWINDOW to that
window's IDCMP.

In response to this message, your application should update the damaged
areas.  Rendering proceeds faster and looks cleaner if it is restricted to
the damaged areas only.  The BeginRefresh()/EndRefresh() pair achieve
that.  The application should call BeginRefresh() for the window, and then
do its rendering.  Any rendering that would have gone into undamaged areas
of the window is automatically discarded; only the area in need of repair
is affected.  Finally, the application should call EndRefresh(), which
removes the restriction on rendering, and informs the system that the
damage region has been dealt with. Even if your application intends to do
no rendering, it must at least call BeginRefresh()/EndRefresh(), to inform
the system that the damage region is no longer needed.  If your
application never needs to render in response to a refresh event, it can
avoid having to call BeginRefresh()/EndRefresh() by setting the
WFLG_NOCAREREFRESH flag or the WA_NoCareRefresh tag in the
OpenWindowTagList() call.

Note that by the time that your application receives notification that
refresh is needed, Intuition will have already refreshed your window's
border and all gadgets in the window, as needed.  Thus, it is unnecessary
to use any of the gadget-refreshing functions in response to an
IDCMP_REFRESHWINDOW event.

Operations performed between the BeginRefresh()/EndRefresh() pair should
be restricted to simple rendering.  All of the rendering functions in
Intuition library and Graphics library are safe.  Avoid RefreshGList() or
RefreshGadgets(), or you risk deadlocking the computer.  Avoid calls that
may lock the LayerInfo or get complicated in Intuition, since
BeginRefresh() leaves the window's layer or layers locked.  Avoid
AutoRequest() and EasyRequest(), and therefore all direct or indirect disk
related DOS calls.  See the "Intuition Gadgets" chapter for more
information on gadget restrictions with BeginRefresh()/EndRefresh().

 Simple Refresh    Smart Refresh    SuperBitMap Refresh


4 / / Refreshing Intuition Windows / Simple Refresh

For a Simple Refresh window, only those pixels actually on-screen are
maintained by the system.  When part of a Simple Refresh window is
obscured, the imagery that was there is lost.  As well, any rendering into
obscured portions of such a window is discarded.

When part of the window is newly revealed (either because the window was
just made larger, or because that part used to be obscured by another
window), the application must refresh any rendering it wishes to appear
into that part.  The application will learn that refresh is needed because
Intuition sends an IDCMP_REFRESHWINDOW event.


4 / / Refreshing Intuition Windows / Smart Refresh

If a window is of the Smart Refresh type, then the system will not only
preserve those pixels which are actually on-screen, but it will save all
obscured pixels that are within the current window's size. The system will
refresh those parts of the window revealed by changes in the overlapping
with other windows on the screen, without involving the application.
However, any part of the window revealed through the sizing of the window
must be redrawn by the application.  Again, Intuition will notify the
application through the IDCMP_REFRESHWINDOW event.

Because the obscured areas are kept in off-screen buffers, Smart Refresh
windows are refreshed faster than Simple Refresh windows are, and often
without involving the application.  Of course, for the same reason, they
use more display memory.


4 / / Refreshing Intuition Windows / SuperBitMap Refresh

The SuperBitMap refresh type allows the application to provide and
maintain bitmap memory for graphics in the window.  The bitmap can be any
size as long as the window sizing limits respect the maximum size of the
bitmap.

SuperBitMap windows have their own memory for maintaining all obscured
parts of the window up to the size of the defined bitmap, including those
parts outside of the current window.  Intuition will update all parts of
the window that are revealed through changes in sizing and changes in
window overlapping.  The application never needs to redraw portions of the
window that were revealed by sizing or positioning windows in the screen.

SuperBitMap windows require the application to allocate a bitmap for use
as off-screen memory, instead of using Intuition managed buffers.  This
bitmap must be as large as, or larger than, the inner window's maximum
dimensions (that is, the window's outside dimensions less the border
sizes).

SuperBitMap windows are almost always WFLG_GIMMEZEROZERO, which renders
the borders and system gadgets in a separate bitmap.  If the application
wishes to create a SuperBitMap window that is not GimmeZeroZero, it must
make the window borderless with no system gadgets, so that no border
imagery is rendered by Intuition into the application's bitmap.


4 / Preserving the Window Display / Intuition Refresh Events

When using a Simple Refresh or a Smart Refresh windows, the program may
receive refresh events, informing it to update the display.  See the above
discussion for information on when refresh events are sent.

A message of the class IDCMP_REFRESHWINDOW arrives at the IDCMP, informing
the program of the need to update the display.  The program must take some
action when it receives a refresh event, even if it is just the acceptable
minimum action described below.

On receiving a refresh event, BeginRefresh() must be called, then the
program should redraw its display, and, finally, call EndRefresh().  The
minimum required action is to call the BeginRefresh()/EndRefresh() pair.
This allows Intuition and the Layers library keep things sorted and
organized.


4 / Preserving the Window Display / Optimized Window Refreshing

Bracketing the display updating in the BeginRefresh()/EndRefresh() pair
automatically restricts all rendering to the "damaged" areas.

    void BeginRefresh( struct Window *window );
    void EndRefresh  ( struct Window *window, long complete );

These functions makes sure that refreshing is done in the most efficient
way, only redrawing those portions of the window that really need to be
redrawn.  The rest of the rendering commands are discarded.

Operations performed between the BeginRefresh()/EndRefresh() pair should
be restricted to simple rendering.  All of the rendering functions in
Intuition library and Graphics library are safe.  Calls to
RefreshGadgets() are not permitted.  Avoid calls that may lock the
LayerInfo, or get complicated in Intuition, since BeginRefresh() leaves
the window's layer or layers locked.  Avoid AutoRequest(), and therefore
all direct or indirect disk related DOS calls.  See the
"Intuition Gadgets" chapter for more information on gadget restrictions
with BeginRefresh()/EndRefresh().

Certain applications do not need to receive refresh events, and can avoid
having to call BeginRefresh() and EndRefresh() by setting the
WFLG_NOCAREREFRESH flag or the WA_NoCareRefresh tag in the
OpenWindowTagList() call.

The EndRefresh() function takes a boolean value as an argument (complete
in the prototype above).  This value determines whether refreshing is
completely finished.  When set to FALSE, further refreshing may be
performed between subsequent BeginRefresh()/ EndRefresh() pairs.  Set the
boolean to TRUE for the last call to EndRefresh().

It is critical that applications performing multiple
BeginRefresh()/EndRefresh() pairs using EndRefresh(win,FALSE) hold layers
locked through the entire process.  The layer lock may only be released
after the final call to EndRefresh(win,TRUE). See the "Layers Library" for
more details.

The procedures outlined in this section take care of refreshing what is
inside the window.  Another function named RefreshWindowFrame() refreshes
window borders, including the title region and gadgets:

    void RefreshWindowFrame( struct Window *window );

Applications can use this function to update window borders after
overwriting them with graphics.


4 / Preserving the Window Display / Setting Up A SuperBitMap Window

SuperBitMap windows are created by setting the WFLG_SUPER_BITMAP flag, or
by specifying the WA_SuperBitMap tag in the OpenWindowTagList() call.  A
pointer to an allocated and initialized BitMap structure must be provided.

A SuperBitMap window requires the application to allocate and initialize
its own bitmap.  This entails allocating a BitMap structure, initializing
the structure and allocating memory for the bit planes.

Allocate a BitMap structure with the Exec AllocMem() function.  Then use
the graphics function InitBitMap() to initialize the BitMap structure:

    void InitBitMap( struct BitMap *bitMap, long depth,
                     long width, long height );

InitBitMap() fills in fields in the BitMap structure describing how a
linear memory area is organized as a series of one or more rectangular
bit-planes.

Once you have allocated and initialized the BitMap structure, use the
graphics library function AllocRaster() to allocate the memory space for
all the bit planes.

    PLANEPTR AllocRaster( unsigned long width, unsigned long height );

The example listed in the next section shows how to allocate a BitMap
structure, initialize it with InitBitMap() and use AllocRaster() function
to set up memory for the bitplanes.

 Graphics and Layers Functions for SuperBitMap Windows
 SuperBitMap Window Example


4 / / Setting Up A SuperBitMap Window / Graphics and Layers Functions

The portion of the bitmap showing within a SuperBitMap window is
controlled by the application.  Initially, the window shows the bitmap
starting from its origin (0,0) and clipped to fit within the window layer.
The visible portion of the bitmap can be scrolled around within the window
using the layers library ScrollLayer() function:

    void ScrollLayer(LONG unused, struct Layer *layer, LONG dx, LONG dy)

Pass this function a pointer to the window's layer in layer and the scroll
offsets in dx and dy.  (A pointer to the window's layer can be obtained
from Window.RPort->Layer.)

When rendering operations are performed in a SuperBitMap window, any
rendering that falls outside window boundaries is done in the
application's bitmap.  Rendering that falls within window bounds is done
in the screen's bitmap.  Before performing an operation such as a save on
the application bitmap, the graphics library function SyncSBitMap() should
be called:

    void SyncSBitMap(struct Layer *layer)

Pass this function a pointer to the window's layer.  SyncSBitMap() copies
the window contents to the corresponding part of the application bitmap,
bringing it up to date.  (If no rendering operations have been performed
this call is not necessary.)

Similarly, after making any changes to the application bitmap such as
loading a new one, the window's layer should be locked and the
CopySBitMap() function should be called.

    void CopySBitMap(struct Layer *)

This function copies the new information in the appropriate area of the
underlying bitmap to the window's layer.

For more information about bitmaps and layers, see the
"Graphics Primitives" and "Layers Library" chapters of this manual.  Also
see the <graphics/clip.h>, <graphics/gfx.h>, <graphics/layers.h>,
graphics library and layers library sections of the Amiga ROM Kernel
Reference Manual: Includes and Autodocs.


4 Intuition Windows / The Window Structure

The Window structure is the main Intuition data structure used to
represent a window.  For the most part, applications treat this structure
only as a handle.  Window operations are performed by calling system
functions that take Window as an argument instead of directly manipulating
fields within the structure.  However, there are some useful variables in
a Window structure which are discussed in this section.

   struct Window
       {
       struct Window *NextWindow;
       WORD LeftEdge, TopEdge, Width, Height;
       WORD MouseY, MouseX;
       WORD MinWidth, MinHeight;
       UWORD MaxWidth, MaxHeight;
       ULONG Flags;
       struct Menu *MenuStrip;
       UBYTE *Title;
       struct Requester *FirstRequest, *DMRequest;
       WORD ReqCount;
       struct Screen *WScreen;
       struct RastPort *RPort;
       BYTE BorderLeft, BorderTop, BorderRight, BorderBottom;
       struct RastPort *BorderRPort;
       struct Gadget *FirstGadget;
       struct Window *Parent, *Descendant;
       UWORD *Pointer;
       BYTE PtrHeight, PtrWidth;
       BYTE XOffset, YOffset;
       ULONG IDCMPFlags;
       struct MsgPort *UserPort, *WindowPort;
       struct IntuiMessage *MessageKey;
       UBYTE DetailPen, BlockPen;
       struct Image *CheckMark;
       UBYTE *ScreenTitle;
       WORD GZZMouseX, GZZMouseY, GZZWidth, GZZHeight;
       UBYTE *ExtData;
       BYTE *UserData;
       struct Layer *WLayer;
       struct TextFont *IFont;
       ULONG MoreFlags;
       };

LeftEdge, TopEdge, Width and Height
    These variables reflect current position and size of the window.  If
    the user sizes or positions the window, then these values will
    change. The position of the window is relative to the upper left
    corner of the screen.

MouseX, MouseY, GZZMouseX, GZZMouseY
    The current position of the Intuition pointer with respect to the
    window, whether or not this window is currently the active one.  For
    GimmeZeroZero windows, the GZZ variables reflect the position
    relative to the inner layer (see "Window Types" below).  For normal
    windows, the GZZ variables reflect the position relative to the
    window origin after taking the borders into account.

ReqCount
    Contains a count of the number of requesters currently displayed in
    the window.  Do not rely on the value in this field, instead use
    IDCMP_REQSET and IDCMP_REQCLEAR to indirectly determine the number of
    open requesters in the window.

WScreen
    A pointer to the Screen structure of the screen on which this window
    was opened.

RPort
    A pointer to this window's RastPort structure.  Use this RastPort
    pointer to render into your window with Intuition or graphics library
    rendering functions.

BorderLeft, BorderTop, BorderRight, BorderBottom
    These variables describe the actual size of the window borders. The
    border size is not changed after the window is opened.

BorderRPort
    With GimmeZeroZero windows, this variable points to the RastPort for
    the outer layer, in which the border gadgets are kept.

UserData
    This pointer is available for application use.  The program can
    attach a data block to this window by setting this variable to point
    to the data.

For a commented listing of the Window structure see
<intuition/intuition.h> in the Amiga ROM Kernel Reference Manual: Includes
and Autodocs.


4 Intuition Windows / Window Attributes

This section discusses all window attributes.  As mentioned earlier, a
window's attributes may be specified with either TagItems, NewWindow or
ExtNewWindow depending on how the window is opened.

Attributes are listed here by their TagItem ID name (TagItem.ti_Tag).  For
each tag item, the equivalent field setting in the NewWindow structure is
also listed if it exists.  Some window attributes specified with tags are
available only in Release 2 and have no NewWindow equivalent.

 Extended New Window
 Window Attribute Tags
 Boolean Window Attribute Tags


4 / Window Attributes / Extended New Window

Of the three functions for opening a window, only OpenWindow() is present
in all versions of the OS.  This function takes a NewWindow structure as
its sole argument.  In order to allow applications to use the OpenWindow()
call with Release 2 TagItem attributes, an extended version of the
NewWindow structure has been created named ExtNewWindow.

Setting WFLG_NW_EXTENDED in the NewWindow.Flags field specifies to the
OpenWindow() call that this NewWindow structure is really an ExtNewWindow
structure.  This is simply a standard NewWindow structure with a pointer
to a tag list at the end.  Since WFLG_NW_EXTENDED is ignored prior to V36,
information provided in the tag list will be ignored by earlier versions
of Intuition.  Note that WFLG_NW_EXTENDED may not be specified in the
WA_Flags tag.


4 / Window Attributes / Window Attribute Tags

WA_Left, WA_Top, WA_Width and WA_Height
    Describe where the window will first appear on the screen and how
    large it will be initially. These dimensions are relative to the top
    left corner of the screen, which has the coordinates (0,0).

    WA_Left is the initial x position, or offset, from the left edge of
    the screen.  The leftmost pixel is pixel 0, and values increase to
    the right.  Equivalent to NewWindow.LeftEdge.

    WA_Top is the initial y position, or offset, from the top edge of the
    screen.  The topmost pixel is pixel 0, and values increase to the
    bottom.  Equivalent to NewWindow.TopEdge.

    WA_Width is the initial window width in pixels.  Equivalent to
    NewWindow.Width.

    WA_Height is the initial window height in lines.  Equivalent to
    NewWindow.Height.

WA_DetailPen and WA_BlockPen
    WA_DetailPen specifies the pen number for the rendering of window
    details like gadgets or text in the title bar.  WA_BlockPen specifies
    the pen number for window block fills, like the title bar.  These
    pens are also used for rendering menus.  Equivalent to
    NewWindow.DetailPen and NewWindow.BlockPen.

    The specific color associated with each pen number depends on the
    screen.  Specifying -1 for these values sets the window's detail and
    block pen the same as the screen's detail and block pen.

    Detail pen and block pen have largely been replaced starting with V36
    by the pen array in the DrawInfo structure.  See the section on
    "DrawInfo and the 3D Look" in the "Intuition Screens" chapter for
    more information.

WA_IDCMP
    IDCMP flags tell Intuition what user input events the application
    wants to be notified about.  The IDCMP flags are listed and described
    in the OpenWindowTagList() description in the Amiga ROM Kernel
    Reference Manual: Includes and Autodocs and in the chapter
    "Intuition Input and Output Methods" in this book.  Equivalent to
    NewWindow.IDCMPFlags.

    If any of these flags are set, Intuition creates a pair of message
    ports for the window (one internal to Intuition and one used by the
    application). These ports are for handling messages about user input
    events.  If WA_IDCMP is NULL or unspecified, no IDCMP is created for
    this window.

    The ModifyIDCMP() function can be used to change the window's IDCMP
    flags after it is open.

WA_Gadgets
    A pointer to the first in the linked list of Gadget structures that
    are to be included in this window.  These gadgets are application
    gadgets, not system gadgets.  See the "Intuition Gadgets" chapter for
    more information.  Equivalent to NewWindow.FirstGadget.

WA_Checkmark
    A pointer to an Image structure, which is to be used as the checkmark
    image in this window's menus.  To use the default checkmark, do not
    specify this tag or set this field to NULL.  Equivalent to
    NewWindow.CheckMark.

WA_Title
    A pointer to a NULL terminated text string, which is used as the
    window title and is displayed in the window's title bar.

    Intuition draws the text using the colors defined in the DrawInfo pen
    array (DrawInfo.dri_Pens) and displays as much as possible of the
    window title, depending upon the current width of the title bar.
    Equivalent to NewWindow.Title.  See the section on
    "DrawInfo and the 3D Look" in the "Intuition Screens" chapter for
    more information on the pen array.

    The title is rendered in the screen's default font.

    A title bar is added to the window if any of the properties
    WA_DragBar (WFLG_DRAGBAR), WA_DepthGadget (WFLG_DEPTHGADGET),
    WA_CloseGadget (WFLG_CLOSEGADGET) or WA_Zoom are specified, or if
    text is specified for a window title.  If no text is provided for the
    title, but one or more of these system gadgets are specified, the
    title bar will be blank.  Equivalent to NewWindow.Title.

WA_ScreenTitle
    A pointer to a NULL terminated text string, which is used as the
    screen title and is displayed, when the window is active, in the
    screen's title bar.  After the screen has been opened the screen's
    title may be changed by calling SetWindowTitles() (which is the only
    method of setting the window's screen title prior to V36).

WA_CustomScreen
    A pointer to the Screen structure of a screen created by this
    application.  The window will be opened on this screen.  The custom
    screen must already be opened when the OpenWindowTagList() call is
    made.  Equivalent to NewWindow.Screen, also implies NewWindow.Type of
    CUSTOMSCREEN.

WA_MinWidth, WA_MinHeight, WA_MaxWidth and WA_MaxHeight
    These tags set the minimum and maximum values to which the user may
    size the window.  If the flag WFLG_SIZEGADGET is not set, then
    these variables are ignored.  Values are measured in pixels.  Use
    (~0) for the WA_MaxWidth (WA_MaxHeight) to allow for a window as wide
    (tall) as the screen.  This is the complete screen, not the visible
    part or display clip.

    Setting any of these variables to 0, will take the setting for that
    dimension from its initial value.  For example, setting MinWidth to
    0, will make the minimum width of this window equal to the initial
    width of the window.

    Equivalent to NewWindow.MinWidth, NewWindow.MinHeight,
    NewWindow.MaxWidth and NewWindow.MaxHeight.  Use the WindowLimits()
    function to change window size limits after the window is opened.

WA_InnerWidth and WA_InnerHeight
    Specify the dimensions of the interior region of the window, i.e.,
    inside the border, independent of the border widths.  When using
    WA_InnerWidth and WA_InnerHeight an application will probably want to
    set WA_AutoAdjust.

WA_PubScreen
    Open the window as a visitor window on the public screen whose
    address is in the ti_Data field of the WA_PubScreen TagItem.  To
    ensure that this screen remains open until OpenWindowTagList() has
    completed, the application must either be the screen's owner, have a
    window open on the screen, or use LockPubScreen().  Setting this tag
    implies screen type of PUBLICSCREEN.

WA_PubScreenName
    Declares that the window is to be opened as a visitor on the public
    screen whose name is pointed to by the ti_Data field of the
    WA_PubScreenName TagItem.  The OpenWindowTagList() call will fail if
    it cannot obtain a lock on the named public screen and no fall back
    name (WA_PubScreenFallBack) is specified.  Setting this tag implies
    screen type of PUBLICSCREEN.

WA_PubScreenFallBack
    A Boolean, specifies whether a visitor window should "fall back" to
    the default public screen (or Workbench) if the named public screen
    isn't available This tag is only meaningful when used in conjunction
    with WA_PubScreenName.

WA_Zoom
    Pointer to an array of four WORDs, the initial LeftEdge, TopEdge,
    Width and Height values for the alternate zoom position and size.  It
    also specifies that the application wants a zoom gadget for the
    window, whether or not it has a sizing gadget.

    A zoom gadget is always supplied to a window if it has both depth and
    sizing gadgets.  This tag allows the application to open a window
    with a zoom gadget when the window does not have both the depth and
    sizing gadgets.

WA_MouseQueue
    An initial value for the mouse message backlog limit for this window.
    The SetMouseQueue() function will change this limit after the window
    is opened.

WA_RptQueue
    An initial value of repeat key backlog limit for this window.


4 / Window Attributes / Boolean Window Attribute Tags

These boolean window tags are alternatives to the NewWindow.Flags bit
fields with similar names.  Unlike the tags discussed above, the ti_Data
field of these TagItems is set to either TRUE or FALSE.

WA_SizeGadget
    Specifying this flag tells Intuition to add a sizing gadget to the
    window.  Intuition places the sizing gadget in the lower right corner
    of the window.  By default, the right border is adjusted to
    accommodate the sizing gadget, but the application can specify one of
    the following two flags to change this behavior.  The WFLG_SIZEBRIGHT
    flag puts the sizing gadget in the right border.  The
    WFLG_SIZEBBOTTOM flag puts the sizing gadget in the bottom border.
    Both flags may be specified, placing the gadget in both borders.
    Equivalent to NewWindow.Flags WFLG_SIZEGADGET.

WA_SizeBRight
    Place the size gadget in the right border.  Equivalent to
    NewWindow.Flags WFLG_SIZEBRIGHT.

WA_SizeBBottom
    Place the size gadget in the bottom border.  Equivalent to
    NewWindow.Flags WFLG_SIZEBBOTTOM.

WA_DragBar
    This flag turns the entire title bar of the window into a drag
    gadget, allowing the user to position the window by clicking in the
    title bar and dragging the mouse.  Equivalent to NewWindow.Flags
    WFLG_DRAGBAR.

WA_DepthGadget
    Setting this flag adds a depth gadget to the window.  This allows the
    user to change the window's depth arrangement with respect to other
    windows on the screen.  Intuition places the depth gadget in the
    upper right corner of the window.  Equivalent to NewWindow.Flags
    WFLG_DEPTHGADGET.

WA_CloseGadget
    Setting this flag attaches a close gadget to the window.  When the
    user selects this gadget, Intuition transmits a message to the
    application.  It is up to the application to close the window with a
    CloseWindow() call. Intuition places the close gadget in the upper
    left corner of the window. Equivalent to NewWindow.Flags
    WFLG_CLOSEGADGET.

WA_ReportMouse
    Send mouse movement events to the window as x,y coordinates.  Also
    see the description of the IDCMP flag IDCMP_MOUSEMOVE, in the chapter
    "Intuition Input and Output Methods."  Equivalent to NewWindow.Flags
    WFLG_REPORTMOUSE.

    The WFLG_REPORTMOUSE flag in the Flags field of the Window structure
    may be modified on the fly  by the program.  Changing this flag must
    be done as an atomic operation.  Most compilers generate atomic code
    for operations such as window->flags |= WFLG_REPORTMOUSE or
    window->flags &= ~WFLG_REPORTMOUSE.  If you are unsure of getting an
    atomic operation from your compiler, you may wish to do this
    operation in assembler, or bracket the code with a Forbid()/Permit()
    pair.

    The use of the ReportMouse() function is strongly discouraged, due to
    historic confusion over the parameter ordering.

WA_NoCareRefresh
    This window does not want IDCMP_REFRESHWINDOW events.  Set this flag
    to prevent the window from receiving refresh window messages.
    Equivalent to NewWindow.Flags WFLG_NOCAREREFRESH.  Intuition will
    manage BeginRefresh() and EndRefresh() internally.

WA_Borderless
    Open a window with no borders rendered by Intuition.  Equivalent to
    NewWindow.Flags WFLG_BORDERLESS.

    Use caution setting this flag, as it may cause visual confusion on
    the screen.  Also, some borders may be rendered if any of the system
    gadgets are requested, if text is supplied for the window's title
    bar, or if any of application gadgets are in the borders.

WA_Backdrop
    Make this window a Backdrop window.  Equivalent to NewWindow.Flags
    WFLG_BACKDROP.

WA_GimmeZeroZero
    Set this tag to create a GimmeZeroZero window. GimmeZeroZero windows
    have the window border and border gadgets rendered into an extra
    layer. This extra layer slows down window operations, thus it is
    recommended that applications only use GimmeZeroZero windows when
    they are required. For clipping graphics to the area within the
    borders of a window, see the discussion of "Regions" in the "Layers
    Library" chapter. Equivalent to NewWindow.Flags WFLG_GIMMEZEROZERO.

WA_Activate
    Activate the window when it opens.  Equivalent to NewWindow.Flags
    WFLG_ACTIVATE.  Use this flag carefully, as it can change where the
    user's input is going.

WA_RMBTrap
    Catch right mouse button events for application use.  Set this flag
    to disable menu operations for the window.  When set, right mouse
    button events will be received as IDCMP_MOUSEBUTTONS with the MENUUP
    and MENUDOWN qualifiers.  Equivalent to NewWindow.Flags WFLG_RMBTRAP.

    The WFLG_RMBTRAP flag in the Window structure Flags field may be
    modified on the fly by the program.  Changing this flag must be done
    as an atomic operation, as Intuition can preempt a multistep set or
    clear operation.  An atomic operation can be done in assembler, using
    68000 instructions that operate directly on memory.  If you are
    unsure of generating such an instruction, place the operation within
    a Forbid()/Permit() pair.  This will ensure proper operation by
    disabling multitasking while the flag is being changed.

WA_SimpleRefresh
    The application program takes complete responsibility for updating
    the window.  Only specify if TRUE.  Equivalent to NewWindow.Flags
    WFLG_SIMPLE_REFRESH.

WA_SmartRefresh
    Intuition handles all window updating, except for parts of the window
    revealed when the window is sized larger.  Only specify if TRUE.
    Equivalent to NewWindow.Flags WFLG_SMART_REFRESH.

    WA_SmartRefresh windows without a sizing gadget will never receive
    refresh events due to the user sizing the window.  However, if the
    application sizes the window through a call like ChangeWindowBox(),
    ZipWindow() or SizeWindow(), a refresh event may be generated.  Use
    WA_NoCareRefresh to disable refresh events.

WA_SuperBitMap
    This is a pointer to a BitMap structure for a SuperBitMap window. The
    application will be allocating and maintaining its own bitmap.
    Equivalent to NewWindow.BitMap.  Setting this tag implies the
    WFLG_SUPER_BITMAP property.

    For complete information about SuperBitMap, see
    "Setting Up a SuperBitMap Window" in this chapter.

WA_AutoAdjust
    Allow Intuition to change the window's position and dimensions in
    order to fit it on screen.  The window's position is adjusted first,
    then the size.  This property may be especially important when using
    WA_InnerWidth and WA_InnerHeight as border size depends on a user
    specified font.

WA_MenuHelp (new for V37, ignored by V36)
    Enables IDCMP_MENUHELP: pressing Help during menus will return
    IDCMP_MENUHELP message.  See the "Intuition Menus" chapter for more
    information.

WA_Flags
    Multiple initialization of window flags, equivalent to
    NewWindow.Flags. Use the WFLG_ constants to initialize this field,
    multiple bits may be set by ORing the values together.

WA_BackFill
    Allows you to specify a backfill hook for your window's layer.  See
    the description of CreateUpFrontHookLayer() in the "Includes and
    Autodocs" manual.  Note that this tag is implemented in V37, contrary
    to what some versions of the include files may say.


4 Intuition Windows / Other Window Functions

This section contains a brief overview of other Intuition functions that
affect windows.  For a complete description of all Intuition functions,
see the Amiga ROM Kernel Reference Manual: Includes and Autodocs.

 Menus and the Active Window
 Requesters in the Window
 Program Control of Window Arrangement
 Changing the Window or Screen Title
 Changing Message Queue Limits
 Changing Pointer Position Reports
 Custom Pointers


4 / Other Window Functions / Menus and the Active Window

Menus for the active window will be displayed when the user presses the
menu button on the mouse.  Menus may be disabled for the window by not
providing a menu strip, or by clearing the menus with ClearMenuStrip().
Similarly, if the active window has WFLG_RMBTRAP set, the menu button will
not bring up the menus.

Two other functions, SetMenuStrip() and ResetMenuStrip(), are used to
attach or update the menu strip for a window.

    void ClearMenuStrip( struct Window *window );
    BOOL SetMenuStrip( struct Window *window, struct Menu *menu );
    BOOL ResetMenuStrip( struct Window *window, struct Menu *menu );

If SetMenuStrip() has been called for a window, ClearMenuStrip() must be
called before closing the window.  After ClearMenuStrip() has been called,
the user can no longer access menus for this window.  See the chapter
"Intuition Menus," for complete information about setting up menus.


4 / Other Window Functions / Requesters in the Window

Requesters are temporary sub-windows, usually containing several gadgets,
used to confirm actions, access files, or adjust the options of a command
the user has just given.  Request() creates and activates a requester in
the window.  EndRequest() removes the requester from the window.

    BOOL Request( struct Requester *requester, struct Window *window );
    void EndRequest( struct Requester *requester, struct Window *window );

For simple requesters in a format that matches system requesters, two new
functions have been added to Release 2:

    LONG EasyRequestArgs( struct Window *window,
                          struct EasyStruct *easyStruct,
                          ULONG *idcmpPtr, APTR args );
    LONG EasyRequest( struct Window *window,
                          struct EasyStruct *easyStruct,
                          ULONG *idcmpPtr, APTR arg1, ... );

The EasyRequest() functions support requesters with one or more gadgets
automatically providing a layout that is sensitive to the current font and
screen resolution.  See the chapter "Intuition Requesters and Alerts" for
more information on using requester functions.


4 / Other Window Functions / Program Control of Window Arrangement

MoveWindow(), SizeWindow(), WindowToFront() and WindowToBack() allow the
program to modify the size and placement of its windows.  These calls are
available in all versions of the operating system.

MoveWindowInFrontOf(), ChangeWindowBox() and ZipWindow() have been added
in Release 2 to provide more flexible control over the size and placement
of windows.

All of these functions are asynchronous.  The window will not be affected
by them immediately, rather, Intuition will act on the request the next
time it receives an input event.  Currently this happens at a minimum rate
of ten times per second, and a maximum of sixty times per second.  There
is no guarantee that the operation has taken place when the function
returns.  In some cases, there are IDCMP messages which will inform the
application when the change has completed (for example, an IDCMP_NEWSIZE
event indicates that a resize operation has completed).

Use the MoveWindow() function to move a window to a new position in the
screen.  Use SizeWindow() to change the size of the window:

    void MoveWindow( struct Window *window, long dx, long dy );
    void SizeWindow( struct Window *window, long dx, long dy );

Note that both MoveWindow() and SizeWindow() take the amount of change in
each axis (delta values instead of absolute coordinates).  To specify the
coordinates as absolute numbers, use ChangeWindowBox().  The SizeWindow()
function will respect the window's maximum and minimum dimensions only if
the window has a sizing gadget.

A new function in Release 2, ChangeWindowBox(), allows an application to
change the window size and position in a single call:

    void ChangeWindowBox( struct Window *window, long left, long top,
                          long width, long height );

Note that the position and size values are absolutes and not deltas.  The
window's maximum and minimum dimensions are always respected.

To depth arrange windows under program control, use WindowToFront() and
WindowToBack():

    void WindowToFront( struct Window *window );
    void WindowToBack( struct Window *window );

WindowToFront() depth arranges a given window in front of all other
windows on its screen.  WindowToBack() depth arranges a given window
behind all other windows on its screen.

To move a window in front of a specific, given window (as opposed to all
windows), use MoveWindowInFrontOf():

    void MoveWindowInFrontOf( struct Window *window,
                              struct Window *behindWindow );

MoveWindowInFrontOf() is a new call provided in Release 2 and is not
available in older versions of the OS.

To toggle the window size between its two zoom settings use ZipWindow().
This performs the same action that occurs when the user selects the zoom
gadget:

    void ZipWindow( struct Window *window );

The two zoom settings are the initial size and position of the window when
it was first opened and the alternate position specified with the WA_Zoom
tag.  If no WA_Zoom tag is provided, the alternate position is taken from
the window's minimum dimensions, unless the window was opened at its
minimum dimension.  In that case, the alternate position is taken from the
window's maximum dimension.  ZipWindow() is a new call provided in Release
2 and is not available in older versions of the OS.


4 / Other Window Functions / Changing the Window or Screen Title

Each window has its own window title and local screen title.  The window
title, if specified, is always displayed in the window.  The local screen
title, if specified, is only displayed in the screen's title bar when the
window is active.  If the window does not specify a local screen title,
then the default screen title is used in the screen title bar when this
window is active.

    void SetWindowTitles( struct Window *window, UBYTE *windowTitle,
                          UBYTE *screenTitle );

This function changes the window title or local screen title for the given
window.  Both windowTitle and screenTitle can be set to -1, NULL or a NULL
terminated string.  Specifying -1 will not change the title from the
current value.  Specifying NULL will clear the window title or reset the
screen title to the default title for the screen.


4 / Other Window Functions / Changing Message Queue Limits

Starting with V36, windows have limits on the number of mouse movement and
repeat key messages that may be waiting at their IDCMP at any time.  These
queue limits prevent the accumulation of these messages, which may arrive
at the IDCMP message port in large numbers.

Once a queue limit is reached, further messages of that type will be
discarded by Intuition.  The application will never hear about the
discarded messages; they are gone forever.  (Note that only mouse move and
key repeat messages are limited this way.  Other types of messages will
still be added to the port.)  Messages of the limited type will arrive at
the port again after the application has replied to one of the messages in
the queue.

The queue limits are independent of each other.  Having reached the limit
for one type of message does not prevent other types of messages (that
have not yet reached their queuing limits) from being added to the IDCMP.
Note that the queues apply only to the IDCMP and not to messages received
directly via an input handler or from the console device.

Order of event arrival is not a factor in the message count.  Messages may
be sequential or interspersed with other events--only the number of
messages of the specific type waiting at the IDCMP matters.

The WA_RptQueue tag allows setting an initial value for the repeat key
backlog limit for the window.  There is no function to change this value
as of V37.  The default value for WA_RptQueue is 3.

The WA_MouseQueue tag allows setting an initial value for the mouse
message backlog limit for the window.  The default value for WA_MouseQueue
is 5.  The number may later be changed with a call to SetMouseQueue():

    LONG SetMouseQueue( struct Window *window, unsigned long queueLength );

Note that real information may be lost if the queue fills and Intuition is
forced to discard messages.  See the chapter
"Intuition Mouse and Keyboard" for more information.


4 / Other Window Functions / Changing Pointer Position Reports

Pointer position messages to a window may be turned on and off by simply
setting or clearing the WFLG_REPORTMOUSE flag bit in Window->Flags, in an
atomic way, as explained for the WA_RMBTrap tag in the "Window Attributes"
section above.  Using this direct method of setting the flag avoids the
historic confusion on the ordering of the arguments of the ReportMouse()
function call.

Mouse reporting may be turned on even if mouse movements were not
activated when the window was opened.  The proper IDCMP flags must be set
for the window to receive the messages.  See the chapter
"Intuition Mouse and Keyboard" for more details on enabling mouse
reporting in an application.


4 / Other Window Functions / Custom Pointers

The active window also has control over the pointer.  If the active window
changes the image for the pointer using the functions SetPointer() or
ClearPointer(), the pointer image will change:

    void SetPointer( struct Window *window, UWORD *pointer, long height,
                     long width, long xOffset, long yOffset );

    void ClearPointer( struct Window *window );

SetPointer() sets up the window with a sprite definition for a custom
pointer.  If the window is active, the change takes place immediately.
The pointer will not change if an inactive window calls SetPointer().  In
this way, each window may have its own custom pointer that is displayed
only when the window is active.

ClearPointer() clears the custom pointer from the window and restores it
to the default Intuition pointer, which is set by the user.  Setting a
pointer for a window is discussed further in the chapter
"Intuition Mouse and Keyboard".


4 Intuition Windows / Function Reference

The following are brief descriptions of the Intuition functions that
relate to the use of Intuition windows.  See the Amiga ROM Kernel
Reference Manual: Includes and Autodocs for details on each function call.

                Table 4-2: Functions for Intuition Windows
  ______________________________________________________________________
 |                                                                      |
 |          Function                  Description                       |
 |======================================================================|
 |    OpenWindowTagList()  Open a window.                               |
 |       OpenWindowTags()  Alternate calling sequence for               |
 |                         OpenWindowTagList().                         |
 |           OpenWindow()  Pre-V36 way to open a window.                |
 |          CloseWindow()  Close a window.                              |
 |----------------------------------------------------------------------|
 |         BeginRefresh()  Turn on optimized window refresh mode.       |
 |           EndRefresh()  Turn off optimized window refresh mode.      |
 |   RefreshWindowFrame()  Redraw the borders and border gadgets of an  |
 |                         open window.                                 |
 |----------------------------------------------------------------------|
 |       ActivateWindow()  Make an open window active.                  |
 |           SizeWindow()  Change the size of an open window.           |
 |           MoveWindow()  Change the position of an open window.       |
 |      ChangeWindowBox()  Change the size and position of an open      |
 |                         window.                                      |
 |         WindowLimits()  Change the minimum and maximum sizes of an   |
 |                         open window.                                 |
 |         WindowToBack()  Move a window behind all other windows.      |
 |        WindowToFront()  Move a window in front of all other windows. |
 |  MoveWindowInFrontOf()  Move a window in front of another window.    |
 |            ZipWindow()  Change the size of window to its alternate   |
 |                         size.                                        |
 |      SetWindowTitles()  Change the window titles for the window and  |
 |                         the screen.                                  |
 |           SetPointer()  Set up a custom pointer to display whenever  |
 |                         the window is active.                        |
 |         ClearPointer()  Restore the mouse pointer to its default     |
 |                         imagery.                                     |
 |______________________________________________________________________|


Amiga® RKM Libraries: 5 Intuition Gadgets

This chapter describes the multi-purpose software controls called gadgets.
Gadgets are software controls symbolized by an image that the user can
operate with the mouse or keyboard.  They are the Amiga's equivalent of
buttons, knobs and dials.

Much of the user's input to an application takes place through gadgets in
the application's windows and requesters.  Gadgets are also used by
Intuition itself for handling screen and window movement and depth
arrangement, as well as window sizing and closing.

Intuition maintains gadget imagery, watches for activation and
deactivation and performs other management required by the gadget.  The
application can choose its level of involvement from simply receiving
gadget activation messages to processing the actual mouse button presses
and movements.  To make gadget programming even easier, Release 2 of the
Amiga operating system includes the new GadTools library.  Applications
written for Release 2 should take advantage of this new library (described
separately in the "GadTools Library" chapter).

 About Gadgets                    Gadget Pointer Movements
 Gadget Imagery                   Gadget Structure
 Gadget Selection                 Boolean Gadget Type
 Gadget Size and Position         Proportional Gadget Type
 Gadget Highlighting              String Gadget Type
 Gadget Refreshing                Custom Gadgets
 Gadget Enabling and Disabling    Function Reference


5 Intuition Gadgets / About Gadgets

There are two kinds of gadgets: system gadgets and application gadgets.
System gadgets are set up by Intuition to handle the positioning and depth
arranging of screens, and to handle the positioning, sizing, closing and
depth arranging of windows.  System gadgets always use the same imagery
and location giving the windows and screens of any application a basic set
of controls that are familiar and easy to operate.  In general,
applications do not have to do any processing for system gadgets;
Intuition does all the work.

Application gadgets are set up by an application program.  These may be
the basic gadget types described in this chapter, the pre-fabricated
gadgets supplied by the GadTools library, or special gadget types defined
through Intuition's custom gadget and BOOPSI facilities.  Application
gadgets can be placed anywhere within a window and can use just about any
image.  The action associated with an application gadget is carried out by
the application.

There are four basic types of application gadgets:

  * Boolean (or button) gadgets elicit true/false or yes/no kinds of
    answers from the user.

  * Proportional gadgets allow the user to select from a continuous range
    of options, such as volume or speed.

  * String gadgets are used to get or display character based information
    (a special class of string gadget allows entry of numeric data.)

  * Custom gadgets, a new, generalized form of gadget, provide
    flexibility to perform any type of function.

The way a gadget is used varies according to the type of gadget.  For a
boolean gadget, the user operates the gadget by simply clicking the mouse
select button.  For a string gadget, a cursor appears, allowing the user
to enter data from the keyboard.  For a proportional gadget, the user can
either drag the knob with the mouse or click in the gadget container to
move the knob by a set increment.

Gadgets are chosen by positioning the pointer within an area called the
select box, which is application defined, and pressing the mouse select
button (left mouse button).

When a gadget is selected, its imagery is changed to indicate that it is
activated.  The highlighting method for the gadget may be set by the
application.  Highlighting methods include alternate image, alternate
border, a box around the gadget and color complementing.

     Figure 5-1: System and Application Gadgets

A gadget can be either enabled or disabled.  Disabled gadgets cannot be
operated and are indicated by ghosting the gadget, that is, overlaying its
image with a pattern of dots.  Gadgets may also be directly modified and
redrawn by first removing the gadget from the system.

 System Gadgets         Adding and Removing Gadgets
 Application Gadgets


5 / About Gadgets / System Gadgets

System gadgets are predefined gadgets provided by Intuition to support
standard operations of windows and screens.  System gadgets have a
standard image and location in the borders of screens or windows.
Intuition manages the operation of all system gadgets except the close
gadget.

The drag and depth gadgets are automatically attached to each screen in
the system.  The application cannot control the creation of these gadgets,
but can control their display and operation.  Screens may be opened
"quiet", without any of the gadget imagery displayed.  Applications should
avoid covering the screen's gadgets with windows as this may prevent the
user from freely positioning the screen.  See the "Intuition Screens"
chapter for more information on the positioning and use of system gadgets
for screens.

The drag, depth, close, sizing and zoom gadgets are available to be
attached to each window.  These gadgets are not provided automatically,
the application must specify which gadgets it requires.  See the
"Intuition Windows" chapter for more information on the positioning and
use of system gadgets for windows.


5 / About Gadgets / Application Gadgets

Application gadgets imitate real life controls: they are the switches,
knobs, handles and buttons of the Intuition environment.  Gadgets can be
created with almost any imaginable type of imagery and function.  Visual
imagery for gadgets can combine text with hand drawn imagery or lines of
multiple colors.

A gadget is created by declaring and initializing a Gadget structure as
defined in <intuition/intuition.h>.  See the "Gadget Structure" section
later in this chapter for more details.

Gadgets always appear in a window or requester.  All windows and
requesters keep a list of the gadgets they contain.  Gadgets can be added
when the window or requester is opened, or they can be added or removed
from the window or requester after it is open.

As with other types of input events, Intuition notifies your application
about gadget activity by sending a message to your window's I/O channels:
the IDCMP (Window.UserPort) or the console device.  The message is sent as
an Intuition IntuiMessage structure.  The Class field of this structure is
set to IDCMP_GADGETDOWN or IDCMP_GADGETUP with the IAddress field set to
the address of the Gadget that was activated.  (See the chapter on
"Intuition Input and Output Methods" for details.)

Application gadgets can go anywhere in windows or requesters, including in
the borders, and can be any size or shape.  When application gadgets are
placed into the window's border at the time the window is opened,
Intuition will adjust the border size accordingly.  Application gadgets
are not supported in screens (although this may be simulated by placing
the gadget in a backdrop window).

Gadget size can be fixed, or can change relative to the window size.
Gadget position can be set relative to either the top or bottom border,
and either the left or right border of the window, allowing the gadget to
move with a border as the window is sized.

This flexibility provides the application designer the freedom to create
gadgets that mimic real devices, such as light switches or joysticks, as
well as the freedom to create controls that satisfy the unique needs of
the application.

 A Simple Gadget Example


5 / About Gadgets / Adding and Removing Gadgets

Gadgets may be added to a window or requester when the window or requester
is opened, or they may be added later.  To add the gadgets when a window
is opened, use the WA_Gadgets tag with the OpenWindowTagList() call.  This
technique is demonstrated in the example above.  For a requester, set the
ReqGadget field in the Requester structure to point to the first gadget in
the list.

To add or remove gadgets in a window or requester that is already open,
use AddGList() or RemoveGList().  These functions operate on gadgets
arranged in a list.  A gadget list is linked together by the NextGadget
field of the Gadget structure (see the description of the Gadget structure
later in this chapter).

AddGList() adds a gadget list that you specify to the existing gadget list
of a window or requester:

    UWORD AddGList( struct Window *window, struct Gadget *agadget,
                    unsigned long position, long numGad,
                    struct Requester *requester );

Up to numGad gadgets will be added from the gadget list you specify
beginning with agadget.  The position argument determines where your
gadgets will be placed in the existing list of gadgets for the window or
requester.  Use (~0) to add your gadget list to the end of the window or
requester's gadget list.  This function returns the actual position where
your gadgets are added in the existing list.

To remove gadgets from a window or requester use RemoveGList():

    UWORD RemoveGList( struct Window *remPtr, struct Gadget *agadget,
                       long numGad );

This function removes up to numGad gadgets from a window or requester,
beginning with the specified one.  Starting with V37, if one of the
gadgets that is being removed is the active gadget, this routine will wait
for the user to release the mouse button before deactivating and removing
the gadget.  This function returns the former position of the removed
gadget or -1 if the specified gadget was not found.

The Gadget structure should never be directly modified after it has been
added to a window or requester.  To modify a gadget, first remove it with
RemoveGList(), modify the structure as needed, and then add the gadget
back to the system with AddGList().  Finally, refresh the gadget imagery
with RefreshGList(). (See the section on "Gadget Refreshing" below for
more information.)

Some attributes of a gadget may be modified through special Intuition
functions that perform the modification.  When using such functions it is
not necessary to remove, add or refresh the gadget.  These functions, such
as NewModifyProp(), OnGadget() and OffGadget(), are described later in
this chapter.


5 Intuition Gadgets / Gadget Imagery

Gadget imagery can be rendered with a series of straight lines, a bitmap
image or no imagery at all.  In addition to the line or bitmap imagery,
gadgets may include a series of text strings.

 Hand Drawn Gadgets    Gadget Text
 Line Drawn Gadgets    Gadgets Without Imagery


5 / Gadget Imagery / Hand Drawn Gadgets

Bitmap or custom images are used as imagery for a gadget by setting the
GFLG_GADGIMAGE flag in the Flags field of the Gadget structure.  An Image
structure must be set up to manage the bitmap data.  The address of the
Image structure is placed into the gadget's GadgetRender field.  The
bitmap image will be positioned relative to the gadget's select box.  For
more information about creating Intuition images, see the chapter
"Intuition Images, Line Drawing, and Text."  For a listing of the Gadget
structure and all its flags see the "Gadget Structure" section later in
this chapter.


5 / Gadget Imagery / Line Drawn Gadgets

Gadget imagery can also be created by specifying a series of lines to be
drawn.  These lines can go around or through the select box of the gadget,
and can be drawn using any color pen and draw mode.  Multiple groups of
lines may be specified, each with its own pen and draw mode.

The Border structure is used to describe the lines to be drawn.  The
Border structure is incorporated into the gadget by clearing the
GFLG_GADGIMAGE flag in the gadget's Flags field.  The address of the
Border structure is placed into the gadget's GadgetRender field.  The
border imagery will be positioned relative to the gadget's select box.
For more information about creating a Border structure, see the chapter
"Intuition Images, Line Drawing, and Text."


5 / Gadget Imagery / Gadget Text

Gadgets may include text information in the form of a linked list of
IntuiText structures.  A pointer to the first IntuiText structure in the
list is placed in the Gadget structure's GadgetText field.  The text is
positioned relative to the top left corner of the gadget's select box.
For more information on IntuiText, see the
"Intuition Images, Line Drawing and Text" chapter.


5 / Gadget Imagery / Gadgets Without Imagery

Gadgets can be created without any defining imagery.  This type of gadget
may be used where mouse information is required but graphical definition
of the gadget is not, or where the existing graphics sufficiently define
the gadget that no additional imagery is required.  A gadget with no
imagery may be created by clearing the GFLG_GADGIMAGE flag in the gadget's
Flags field, and by setting the gadget's GadgetRender and GadgetText
fields to NULL.

The text display of a word processor is a case where mouse information is
required without any additional graphics.  If a large gadget is placed
over the text display, gadget and mouse event messages may be received at
the IDCMP (Window.UserPort) when the mouse select button is either pressed
or released.  The mouse information is used to position the pointer in the
text, or to allow the user to mark blocks of text.  The drag bar of a
window is another example of a gadget where existing imagery defines the
gadget such that additional graphics are not required.


5 Intuition Gadgets / Gadget Selection

The user operates a gadget by pressing the select button while the mouse
pointer is within the gadget's select box.  Intuition provides two ways of
notifying your program about the user operating a gadget.  If your
application needs immediate notification when the gadget is chosen, set
the GACT_IMMEDIATE flag in the gadget's Activation field.  Intuition will
send an IDCMP_GADGETDOWN message to the window's UserPort when it detects
the mouse select button being pressed on the gadget.

If the application needs notification when the gadget is released, i.e.,
when the user releases the mouse select button, set the GACT_RELVERIFY
(for "release verify") flag in the gadget's Activation field.  For boolean
gadgets, Intuition will send an IDCMP_GADGETUP message to the window's
UserPort when the mouse select button is released over a GACT_RELVERIFY
gadget.  The program will only receive the IDCMP_GADGETUP message if the
user still has the pointer positioned over the select box of the gadget
when the mouse select button is released.

If the user moves the mouse out of the gadget's select box before
releasing the mouse button an IDCMP_MOUSEBUTTONS event will be sent with a
code of SELECTUP.  This indicates the user's desire to not proceed with
the action.  Boolean gadgets that are GACT_RELVERIFY allow the user a
chance to cancel a selection by rolling the mouse off of the gadget before
releasing the select button.

String gadgets have a slightly different behavior, in that they remain
active after the mouse button has been released.  The gadget remains
active until Return or Enter is pressed, the user tabs to the next or
previous gadget, another window becomes active or the user chooses another
object with the mouse.  An IDCMP_GADGETUP message is only sent for
GACT_RELVERIFY string gadgets if the user ends the gadget interaction
through the Return, Enter or (if activated) one of the tab keys.

GACT_RELVERIFY proportional gadgets send IDCMP_GADGETUP events even if the
mouse button is released when the pointer is not positioned over the
select box of the gadget.

Gadgets can specify both the GACT_IMMEDIATE and GACT_RELVERIFY activation
types, in which case, the program will receive both IDCMP_GADGETDOWN and
IDCMP_GADGETUP messages.


5 Intuition Gadgets / Gadget Size and Position

The position and dimensions of the gadget's select box are defined in the
Gadget structure.  The LeftEdge, TopEdge, Width and Height values can be
absolute numbers or values relative to the size of the window.  When using
absolute numbers, the values are set once, when the gadget is created.
When using relative numbers, the size and position of the select box are
adjusted dynamically every time the window size changes.

The gadget image is positioned relative to the select box so when the
select box moves the whole gadget moves.  The size of the gadget image,
however, is not usually affected by changes in the select box size
(proportional gadgets are the exception).  To create a gadget image that
changes size when the select box and window change size, you have to
handle gadget rendering yourself or use a BOOPSI gadget.

 Select Box Position     Positioning Gadgets in Window Borders
 Select Box Dimension


5 / Gadget Size and Position / Select Box Position

To specify relative position or size for the gadget's select box, set or
more of the flags GFLG_RELRIGHT, GFLG_RELBOTTOM, GFLG_RELWIDTH or
GFLG_RELHEIGHT in the Flags field of the Gadget structure.  When using
GFLG_RELxxx flags, the gadget size or position is recomputed each time the
window is sized.

    Positioning the Select Box.
    ---------------------------
    With GFLG_RELxxx gadgets, all of the imagery must be contained
    within the gadget's select box.  This allows Intuition to erase the
    gadget's imagery when the window is sized.  Intuition must be able to
    erase the gadget's imagery since the gadget's position or size will
    change as the window size changes.  If the old one were not removed,
    imagery from both sizes/positions would be visible.

    If a GFLG_RELxxx gadget's imagery must extend outside of its select
    box, position another GFLG_RELxxx gadget with a larger select box
    such that all of the first gadget's imagery is within the second
    gadget's select box. This "shadow" gadget is only used to clear the
    first gadget's imagery and, as such, it should not have imagery nor
    should it generate any messages. It should also be positioned later
    in the gadget list than the first gadget so that its select box does
    not interfere with the first gadget.

The left-right position of the select box is defined by the variable
LeftEdge, which is an offset from either the left or right edge of the
display element.  The offset method is determined by the GFLG_RELRIGHT
flag.  For the LeftEdge variable, positive values move toward the right
and negative values move toward the left of the containing display
element.  If GFLG_RELRIGHT is cleared, LeftEdge is an offset (usually a
positive value) from the left edge of the display element.

If GFLG_RELRIGHT is set, LeftEdge is an offset (usually a negative value)
from the right edge of the display element.  When this is set, the
left-right position of the select box in the window is recomputed each
time the window is sized.  The gadget will automatically move with the
left border as the window is sized.

The top-bottom position of the select box is defined by the variable
TopEdge, which is an offset from either the top or bottom edge of the
display element (window or requester).  The offset method is determined by
the GFLG_RELBOTTOM flag.  For the TopEdge variable, positive values move
toward the bottom and negative values move toward the top of the
containing display element.

If GFLG_RELBOTTOM is cleared, TopEdge is an offset (usually a positive
value) from the top of the display element.  If GFLG_RELBOTTOM is set,
TopEdge is an offset (usually a negative value) from the bottom of the
display element.  When this is set, the position of the select box is
recomputed each time the window is sized.  The gadget will automatically
move with the bottom border as the window is sized.


5 / Gadget Size and Position / Select Box Dimension

The height and width of the gadget select box can be absolute or they can
be relative to the height and width of the display element in which the
gadget resides.

Set the gadget's GFLG_RELWIDTH flag to make the gadget's width relative to
the width of the window.  When this flag is set, the Width value is added
to the current window width to determine the width of the gadget select
box.  The Width value is usually negative in this case, making the width
of the gadget smaller than the width of the window.  If GFLG_RELWIDTH is
not set, Width will specify the actual width of the select box.

The actual width of the box will be recomputed each time the window is
sized.  Setting GFLG_RELWIDTH and a gadget width of zero will create a
gadget that is always as wide as the window, regardless of how the window
is sized.

The GFLG_RELHEIGHT flag has the same effect on the height of the gadget
select box.  If the flag is set, the height of the select box will be
relative to the height of the window, and the actual height will be
recomputed each time the window is sized.  If the flag is not set, the
value will specify the actual height of the select box.

Here are a few examples of gadgets that take advantage of the special
relativity modes of the select box.  Consider the Intuition window sizing
gadget.  The LeftEdge and TopEdge of this gadget are both defined relative
to the right and bottom edges of the window.  No matter how the window is
sized, the gadget always appears in the lower right corner.

For the window drag gadget, the LeftEdge and TopEdge are always absolute
in relation to the top left corner of the window.  Height of this gadget
is always an absolute quantity.  Width of the gadget, however, is defined
to be zero.  When Width is combined with the effect of the GFLG_RELWIDTH
flag, the drag gadget is always as wide as the window.

For a program with several requesters, each of which has an "OK" gadget in
the lower left corner and a "Cancel" gadget in the lower right corner, two
gadgets may be designed that will appear in the correct position
regardless of the size of the requester.  Design the "OK" and "Cancel"
gadgets such that they are relative to the lower left and lower right
corners of the requester.  Regardless of the size of the requesters, these
gadgets will appear in the correct position relative to these corners.
Note that these gadgets may only be used in one window or requester at a
time.


5 / Gadget Size and Position / Positioning Gadgets in Window Borders

Gadgets may be placed in the borders of a window.  To do this, set one or
more of the border flags in the Gadget structure and position the gadget
in the window border.  Setting these flags also tells Intuition to adjust
the size of the window's borders to accommodate the gadget.

Borders are adjusted only when the window is opened.  Although the
application can add and remove gadgets with AddGList() and RemoveGList()
after the window is opened, Intuition does not readjust the borders.

A gadget may be placed into two borders by setting multiple border flags.
If a gadget is to be placed in two borders, it only makes sense to put the
gadget into adjoining borders.  Setting both side border flags or both the
top and bottom border flags for a particular gadget, will create a window
that is all border.

See the SuperBitMap example, lines.c, in the "Intuition Windows" chapter
for an example of creating proportional gadgets that are positioned within
a window's borders.

There are circumstances where the border size will not adjust properly so
that the gadget has the correct visual appearance.  One way to correct
this problem is to place a "hidden" gadget into the border, which forces
the border to the correct size.  Such a gadget would have no imagery and
would not cause any IDCMP messages to be sent on mouse button activity.
The gadget should be placed at the end of the gadget list of the window,
so that it does not cover up any other border gadgets.

Sometimes the sizing gadget can be used to adjust the width of the
borders, as in the case of proportional gadgets in the right or bottom
border.  The proportional gadget will only increase the width of the
border by enough so that the select box of the gadget fits within the
border, no space is reserved between the gadget and the inner edge of the
window.  By placing the size gadget in both borders (using the window
flags WFLG_SIZEBRIGHT and WFLG_SIZEBBOTTOM), the prop gadget sizes can be
adjusted so that there is an even margin on all sides.  This technique is
used in the lines.c example mentioned above.

    size gadget in        size gadget in        size gadget in
     both borders         bottom border          side border
    --------------        --------------        --------------

          |     |                    ||               |     |
          |     |                    ||               |     |
          |     |                    ||               |     |
          |     |                    ||               |     |
          |     |                    ||               |     |
     _____|_____|          __________||               |_____|
          |     |               |     |               |     |
          |   /||               |   /||               |   /||
          |  / ||               |  / ||               |  / ||
          | /__||               | /__||          _____| /__||
     _____|_____|          _____|_____|          _____|_____|

   Figure 5-2: Size Gadget in Various Window Border Combinations

The border flags GACT_RIGHTBORDER, GACT_LEFTBORDER, GACT_TOPBORDER and
GACT_BOTTOMBORDER which are set in the Activation field of the Gadget
structure declare that the gadget will be positioned in the border.
Gadgets which are declared to be in the border are automatically refreshed
by Intuition whenever the window borders need to be redrawn.  This
prevents the gadget imagery from being obliterated.

Some applications forgot to declare some of their gadgets as being in the
border.  While they looked fine prior to V36, they would have had some
gadget imagery overwritten by the new style of window borders introduced
with that release.  To ensure compatibility with such applications,
Intuition attempts to identify gadgets that are substantially in the
border but do not have the appropriate border flags set.  Such gadgets are
marked for the same refresh treatment as explicit border gadgets.
Applications should not rely on this behavior, but should instead declare
their border gadgets properly.

Gadgets that are not declared to be in the border, and whose dimensions
are 1 x 1 or smaller are never marked by Intuition as being effectively in
the border.  This is because some applications tuck a small non-selectable
gadget (of size 0x0 or 1x1) into the window border, and attach imagery for
the window to that gadget.  The application does this to get automatic
refresh of that imagery, since Intuition refreshes gadget imagery when
window damage occurs.

Beginning with V36, Intuition attempts to locate gadgets within the border
that do not have the appropriate flags set.  This may cause gadgets to
appear in the border when the application has not set any of the border
flags.  Applications should not rely on this behavior, nor should they
place non-border gadgets fully or partially within the window's borders.


5 Intuition Gadgets / Gadget Highlighting

In general, the appearance of an active or selected gadget changes to
inform the user the gadget state has changed.  A highlighting method is
specified by setting one of the highlighting flags in the Gadget
structure's Flags field.

Intuition supports three methods of activation or selection highlighting:

  * Highlighting by color complementing (GFLG_GADGHCOMP)

  * Highlighting by drawing a box (GFLG_GADGHBOX)

  * Highlighting by an alternate image or border (GFLG_GADGHIMAGE)

  * No highlighting (GFLG_GADGHNONE)

One of the highlighting types or GFLG_GADGHNONE must be specified for each
gadget.

 Highlighting by Color Complementing
 Highlighting by Drawing a Box
 Highlighting with an Alternate Image or Alternate Border


5 / Gadget Highlighting / Highlighting by Color Complementing

Highlighting may be accomplished by complementing all of the colors in the
gadget's select box. In this context, complementing means the complement
of the binary number used to represent a particular color register.  For
example, if the color in color register 2 is used (binary 10) in a
specific pixel of the gadget, the complemented value of that pixel will be
the color in color register 1 (binary 01).

To use this highlighting method, set the GFLG_GADGHCOMP flag.

Only the select box of the gadget is complemented; any portion of the
text, image, or border which is outside of the select box is not
disturbed. See the chapter "Intuition Images, Line Drawing, and Text," for
more information about complementing and about color in general.


5 / Gadget Highlighting / Highlighting by Drawing a Box

To highlight by drawing a simple border around the gadget's select box,
set the GFLG_GADGHBOX bit in the Flags field.


5 / Gadget Highlighting / With an Alternate Image or Alternate Border

An alternate image may be supplied as highlighting for gadgets that use
image rendering, similarly an alternate border may be supplied for gadgets
that use border rendering.  When the gadget is active or selected, the
alternate image or border is displayed in place of the default image or
border.  For this highlighting method, set the SelectRender field of the
Gadget structure to point to the Image structure or Border structure for
the alternate display.

Specify that highlighting is to be done with alternate imagery by setting
the GFLG_GADGHIMAGE flag in the Flags field of the Gadget structure.  When
using GFLG_GADGHIMAGE, remember to set the GFLG_GADGIMAGE flag for images,
clear it for borders.

When using alternate images and borders for highlighting, gadgets rendered
with images must highlight with another image and gadgets rendered with
borders must highlight with another border.  For information about how to
create an Image or Border structure, see the chapter "Intuition Images,
Line Drawing, and Text."


5 Intuition Gadgets / Gadget Refreshing

Gadget imagery is redrawn by Intuition at appropriate times, e.g., when
the user operates the gadget.  The imagery can also be updated under
application control.

 Gadget Refreshing by Intuition    Gadget Refreshing by the Program


5 / Gadget Refreshing / Gadget Refreshing by Intuition

Intuition will refresh a gadget whenever an operation has damaged the
layer of the window or requester to which it is attached.  Because of
this, the typical application does not need to call RefreshGList() as a
part of its IDCMP_REFRESHWINDOW event handling.

Intuition's refreshing of the gadgets of a damaged layer is done through
the layer's damage list.  This means that rendering is clipped or limited
to the layer's damage region--that part of the window or requester that
needs refreshing.

Intuition directly calls the Layers library functions BeginUpdate() and
EndUpdate(), so that rendering is restricted to the proper area.
Applications should not directly call these functions under Intuition,
instead, use the BeginRefresh() and EndRefresh() calls.  Calls to
RefreshGList() or RefreshGadgets() between BeginRefresh() and EndRefresh()
are not permitted.  Never add or remove gadgets between the BeginRefresh()
and EndRefresh() calls.

For more information on BeginRefresh() and EndRefresh(), see the
"Intuition Windows" chapter and the Amiga ROM Kernel Reference Manual:
Includes and Autodocs.

Gadgets which are positioned using GFLG_RELBOTTOM or GFLG_RELRIGHT, or
sized using GFLG_RELWIDTH or GFLG_RELHEIGHT pose a problem for this
scheme.  When the window is sized, the images for these gadgets must
change, even though they are not necessarily in the damage region.
Therefore, Intuition must add the original and new visual regions for such
relative gadgets to the damage region before refreshing the gadgets.  The
result of this is that applications should ensure that any gadgets with
relative position or size do not have Border, Image or IntuiText imagery
that extends beyond their select boxes.


5 / Gadget Refreshing / Gadget Refreshing by the Program

The AddGList() function adds gadgets to Intuition's internal lists but do
not display their imagery.  Subsequently calls to RefreshGList() must be
made to draw the gadgets into the window or requester.

Programs may use RefreshGList() to update the display after making changes
to their gadgets.  The supported changes include (not an exhaustive list):
changing the GFLG_SELECTED flag for boolean gadgets to implement mutually
exclusive gadgets, changing the GadgetText of a gadget to change its
label, changing the GFLG_DISABLED flag, and changing the contents of the
StringInfo structure Buffer of a string gadget.  When making changes to a
gadget, be sure to remove the gadget from the system with RemoveGList()
before altering it.  Remember to add the gadget back and refresh its
imagery.

Boolean gadgets rendered with borders, instead of images, or highlighted
with surrounding boxes (GFLG_GADGHBOX) are handled very simply by
Intuition, and complicated transitions done by the program can get the
rendering out of phase.  Applications should avoid modifying the imagery
and refreshing gadgets that may be highlighted due to selection by the
user.  Such operations may leave pixels highlighted when the gadget is no
longer selected.  The problems with such transitions can often be avoided
by providing imagery, either image or border, that covers all pixels in
the select box.  For GFLG_GADGHIMAGE gadgets, the select imagery should
cover all pixels covered in the normal imagery.

 Updating a Gadget's Imagery    gadget Refresh Function


5 / / Gadget Refreshing by the Program / Updating a Gadget's Imagery

The RefreshGList() function was designed to draw gadgets from scratch, and
assumes that the underlying area is blank.  This function cannot be used
blindly to update gadget imagery.  The typical problem that arises is that
the application cannot change a gadget from selected to unselected state
(or from disabled to enabled state) and have the imagery appear correct.
However, with a little care, the desired results can be obtained.

Depending on the imagery you select for your gadget, the rendering of one
state may not completely overwrite the rendering of a previous one.  For
example, consider a button which consists of a complement-highlighted
boolean gadget, whose imagery is a surrounding Border and whose label is
an IntuiText.  Attempting to visually unselect such a gadget by clearing
its GFLG_SELECTED flag and refreshing it will leave incorrect imagery
because RefreshGList() just redraws the border and text, and never knows
to erase the field area around the text and inside the gadget.  That area
will remain complemented from before.

One solution is to use a gadget whose imagery is certain to overwrite any
imagery left over from a different state.  Disabling a gadget or
highlighting it with complement mode affects the imagery in the entire
select box.  To overwrite this successfully, the gadget's imagery
(GadgetRender) should be an Image structure which fully covers the select
box.  Such a gadget may be highlighted with color complementing
(GFLG_GADGHCOMP), or with an alternate image (GFLG_GADGHIMAGE) for its
SelectRender.  Or, for a gadget which will never be disabled but needs to
be deselected programmatically, you may also use a Border structure for
its GadgetRender, and an identically-shaped (but differently colored)
Border for its SelectRender.

The other technique is to pre-clear the underlying area before
re-rendering the gadget.  To do this, remove the gadget, erase the
rectangle of the gadget's select area, change the GFLG_SELECTED or the
GFLG_DISABLED flag, add the gadget back, and refresh it.

If the gadget has a relative size and/or position (i.e., if of the
GFLG_RELxxx flags are used), then the application will need to compute the
rectangle of the gadget's select area based on the window's current width
and/or height.  Since the window size is involved in the calculation, it
is important that the window not change size between the call to
RemoveGList() and the call to RectFill().  To ensure this, the application
should set IDCMP_SIZEVERIFY so that Intuition will first notify you before
beginning a sizing operation.  (Note that applications using any of the
IDCMP verify events such as IDCMP_SIZEVERIFY should not delay long in
processing such events, since that holds up the user, and also Intuition
may give up and stop waiting for you).


5 / / Gadget Refreshing by the Program / Gadget Refresh Function

Use the RefreshGList() function to refresh one or more gadgets in a window
or requester.

    void RefreshGList( struct Gadget *gadgets, struct Window *window,
                       struct Requester *requester, long numGad );

This function redraws no more than numGad gadgets, starting with the
specified gadget, in a window or requester.  The application should
refresh any gadgets after adding them.  The function should also be used
after the application has modified the imagery of the gadgets to display
the new imagery.


5 Intuition Gadgets / Gadget Enabling and Disabling

A gadget may be disabled so that it cannot be chosen by the user.  When a
gadget is disabled, its image is ghosted.  A ghosted gadget is overlaid
with a pattern of dots, thereby making the imagery less distinct.  The
dots are drawn into the select box of the gadget and any imagery that
extends outside of the select box is not affected by the ghosting.

The application may initialize whether a gadget is disabled by setting the
GFLG_DISABLED flag in the Gadget structure's Flags field before a gadget
is submitted to Intuition.  Clear this flag to create an enabled gadget.

After a gadget is submitted to Intuition for display, its current enable
state may be changed by calling OnGadget() or OffGadget().  If the gadget
is in a requester, the requester must currently be displayed when calling
these functions.

    void OnGadget ( struct Gadget *gadget, struct Window *window,
                    struct Requester *requester );
    void OffGadget( struct Gadget *gadget, struct Window *window,
                    struct Requester *requester );

Depending on what sort of imagery you choose for your gadget, OnGadget()
may not be smart enough to correct the gadget's displayed imagery.  See
the section on "Updating a Gadget's Imagery" for more details.

Multiple gadgets may be enabled or disabled by calling OnGadget() or
OffGadget() for each gadget, or by removing the gadgets with
RemoveGList(), setting or clearing the GFLG_DISABLED flag on each,
replacing the gadgets with AddGList(), and refreshing with RefreshGList().


5 Intuition Gadgets / Gadget Pointer Movements

If the GACT_FOLLOWMOUSE flag is set for a gadget, the application will
receive mouse movement broadcasts as long as the gadget is active. This
section covers the behavior of proportional, boolean and string gadgets,
although there are major caveats in some cases:

  * Unlike IDCMP_GADGETUP and IDCMP_GADGETDOWN IntuiMessages, the
    IAddress field of an IDCMP_MOUSEMOVE IntuiMessage does not point to
    the gadget.  The application must track the active gadget (this
    information is readily obtained from the IDCMP_GADGETDOWN message)
    instead of using the IAddress field.

    Right                          Wrong
        -----                          -----
        imsg=GetMsg(win->UserPort);    imsg=GetMsg(win->UserPort);
        class=imsg->Class;             class=imsg->Class;
        code=imsg->Code;               code=imsg->Code;
        /* OK */                       /* ILLEGAL ! */
        iaddress=imsg->IAddress;       gadid=((struct Gadget *)
                                               imsg->IAddress)->GadgetID;
        ReplyMsg(imsg);                ReplyMsg(imsg);

    Using the code in the left column, it is acceptable to get the
    address of a gadget with gadid=((struct Gadget *)iaddress)->GadgetID
    but only after you have checked to make sure the message is an
    IDCMP_GADGETUP or IDCMP_GADGETDOWN.

  * Boolean gadgets only receive mouse messages if both GACT_RELVERIFY
    and GACT_FOLLOWMOUSE are set.  Those cases described below with
    GACT_RELVERIFY cleared do not apply to boolean gadgets.

  * In general, IDCMP_MOUSEMOVE messages are sent when the mouse changes
    position while the gadget is active.  Boolean and proportional
    gadgets are active while the mouse button is held down, thus mouse
    move messages will be received when the user "drags" with the mouse.
    String gadgets are active until terminated by keyboard entry or
    another object becomes active (generally by user clicking the other
    object).  GACT_FOLLOWMOUSE string gadgets will generate mouse moves
    the entire time they are active, not just when the mouse button is
    held.

The broadcasts received differ according to the gadget's flag settings.
If using the GACT_IMMEDIATE and GACT_RELVERIFY activation flags, the
program gets a gadget down message, receives mouse reports
(IDCMP_MOUSEMOVE) as the mouse moves, and receives a gadget up message
when the mouse button is released.  For boolean gadgets, the mouse button
must be released while the pointer is over the gadget. If the button is
not released over the boolean gadget, an IDCMP_MOUSEBUTTONS message with
the SELECTUP qualifier will be sent.

If only using the GACT_IMMEDIATE activation flag, the program gets a
gadget down message and receives mouse reports as the mouse moves. The
mouse reports will stop when the user releases the mouse select button.
This case does not apply to boolean gadgets as GACT_RELVERIFY must be set
for boolean gadgets to receive mouse messages. If only using the
GACT_RELVERIFY activation flag, the program gets mouse reports followed by
an up event for a gadget.  For boolean gadgets, the IDCMP_GADGETUP event
will only be received if the button was released while the pointer was
over the gadget.  If the button is not released over the boolean gadget, a
IDCMP_MOUSEBUTTONS message with the SELECTUP qualifier will be received if
the program is receiving these events.

If neither the GACT_IMMEDIATE nor the GACT_RELVERIFY activation flags are
set, the program will only receive mouse reports.  This case does not
apply to boolean gadgets  as GACT_RELVERIFY must be set for boolean
gadgets to receive mouse messages.


5 Intuition Gadgets / Gadget Structure

Here is the specification for the Gadget structure defined in
<intuition/intuition.h>.  You create an instance of this structure for
each gadget you place in a window or requester:

    struct Gadget
        {
        struct Gadget *NextGadget;
        WORD LeftEdge, TopEdge;
        WORD Width, Height;
        UWORD Flags;
        UWORD Activation;
        UWORD GadgetType;
        APTR GadgetRender;
        APTR SelectRender;
        struct IntuiText *GadgetText;
        LONG MutualExclude;
        APTR SpecialInfo;
        UWORD GadgetID;
        APTR UserData;
        };

NextGadget
    Applications may create lists of gadgets that may be added to a
    window or requester with a single instruction.  NextGadget is a
    pointer to the next gadget in the list.  The last gadget in the list
    should have a NextGadget value of NULL.

    When gadgets are added or removed, Intuition will modify the
    appropriate NextGadget fields to maintain a correctly linked list of
    gadgets for that window or requester.  However, removing one or more
    gadgets does not reset the last removed gadget's NextGadget field to
    NULL.

LeftEdge, TopEdge, Width, Height
    These variables describe the location and dimensions of the select
    box of the gadget.  Both location and dimensions can be either
    absolute values or else relative to the edges and size of the window
    or requester that contains the gadget.

    LeftEdge and TopEdge are relative to one of the corners of the
    display element, according to how GFLG_RELRIGHT and GFLG_RELBOTTOM
    are set in the Flags variable (see below).

    Width and Height are either absolute dimensions or a negative
    increment to the width abd height of a requester or a window,
    according to to how the GFLG_RELWIDTH and GFLG_RELHEIGHT flags are
    set (see below).

Flags
    The Flags field is shared by the program and Intuition.  See the
    section below on "Gadget Flags" for a complete description of all the
    flag bits.

Activation
    This field is used for information about some gadget attributes.  See
    the "Gadget Activation Flags" section below for a description of the
    various flags.

GadgetType
    This field contains information about gadget type and in what sort of
    display element the gadget is to be displayed.  One of the following
    flags must be set to specify the type:

    GTYP_BOOLGADGET
        Boolean gadget type.

    GTYP_STRGADGET
        String gadget type.  For an integer gadget, also set the
        GACT_LONGINT flag.  See the "Gadget Activation Flags" section
        below.

    GTYP_PROPGADGET
        Proportional gadget type.

    GTYP_CUSTOMGADGET
        Normally not set by the application.  Used by custom BOOPSI
        gadget types, discussed in the "BOOPSI" chapter.

    The following gadget types may be set in addition to one of the above
    types.  None of the following types are required:

    GTYP_GZZGADGET
        If the gadget is placed in a GimmeZeroZero window, setting this
        flag will place the gadget in the border layer, out of the inner
        window.  If this flag is not set, the gadget will go into the
        inner window.  Do not set this bit if this gadget is not placed
        in a GimmeZeroZero window.

    GTYP_REQGADGET
        Set this bit if this gadget is placed in a requester.

GadgetRender
    A pointer to the Image or Border structure containing the graphics
    imagery of this gadget.  If this field is set to NULL, no rendering
    will be done.

    If the graphics of this gadget are implemented with an Image
    structure, this field should contain a pointer to that structure and
    the GFLG_GADGIMAGE flag must be set.  If a Border structure is used,
    this field should contain a pointer to the Border structure, and the
    GFLG_GADGIMAGE bit must be cleared.

SelectRender
    If the application does not use an alternate image for highlighting,
    set this field to NULL.  Otherwise, if the flag GFLG_GADGHIMAGE is
    set, this field must contain a pointer to an Image or Border
    structure.  The GFLG_GADGIMAGE flag determines the type of the
    rendering. Provide a pointer to an IntuiText structure to include a
    text component to the gadget.  Multiple IntuiText structures may be
    chained.  Set this field to NULL if the gadget has no associated text.

GadgetText
    Provide a pointer to an IntuiText structure to include a text
    component to the gadget.  Multiple IntuiText structures may be
    chained.  Set this field to NULL if the gadget has no associated text.

    The offsets in the IntuiText structure are relative to the top left
    of the gadget's select box.

MutualExclude
    This field is currently ignored by Intuition, but is reserved. Do not
    store information here. Starting with V36, if the GadgetType is
    GTYP_CUSTOMGADGET this field is used to point to a Hook for the
    custom gadget.

SpecialInfo
    SpecialInfo contains a pointer to an extension structure which
    contains the special information needed by the gadget.

    If this is a proportional gadget, this variable must contain a
    pointer to an instance of a PropInfo data structure. If this is a
    string or integer gadget, this variable must contain a pointer to an
    instance of a StringInfo data structure. If this is a boolean gadget
    with GACT_BOOLEXTEND activation, this variable must contain a pointer
    to an instance of a BoolInfo data structure. Otherwise, this variable
    is ignored.

GadgetID
    This variable is for application use and may contain any value.  It
    is often used to identify the specific gadget within an event
    processing loop.  This variable is ignored by Intuition.

UserData
    This variable is for application use and may contain any value.  It
    is often used as a pointer to a data block specific to the
    application or gadget.  This variable is ignored by Intuition.

 Gadget Flags    Gadget Activation Flags


5 / Gadget Structure / Gadget Flags

The following are the flags that can be set in the Flags variable of the
Gadget structure.  There are four highlighting methods to choose from.
These determine how the gadget imagery will be changed when the gadget is
selected.  One of these four flags must be set.

GFLG_GADGHNONE
    Set this flag for no highlighting.

GFLG_GADGHCOMP
    This flag chooses highlighting by complementing all of the bits
    contained within the gadget's select box.

GFLG_GADGHBOX
    This flag chooses highlighting by drawing a complemented box around
    the gadget's select box.

GFLG_GADGHIMAGE
    Set this flag to indicate highlighting with an alternate image.

In addition to the highlighting flags, these other values may be set in
the Flags field of the Gadget structure.

GFLG_GADGIMAGE
    If the gadget has a graphic, and it is implemented with an Image
    structure, set this bit.  If the graphic is implemented with a Border
    structure, make sure this bit is clear.  This bit is also used by
    SelectRender to determine the rendering type.

GFLG_RELBOTTOM
    Set this flag if the gadget's TopEdge variable describes an offset
    relative to the bottom of the display element (window or requester)
    containing it.  A GFLG_RELBOTTOM gadget moves automatically as its
    window is made taller or shorter.  Clear this flag if TopEdge is
    relative to the top of the display element.  If GFLG_RELBOTTOM is
    set, TopEdge should contain a negative value, which will position it
    up from the bottom of the display element.

GFLG_RELRIGHT
    Set this flag if the gadget's LeftEdge variable describes an offset
    relative to the right edge of the display element containing it.  A
    GFLG_RELRIGHT gadget moves automatically as its window is made wider
    or narrower.  Clear this flag if LeftEdge is relative to the left
    edge of the display element.  If GFLG_RELRIGHT is set, LeftEdge
    should contain a negative value, which will position the gadget left
    of the right edge of the display element.

GFLG_RELWIDTH
    Set this flag for "relative gadget width."  If this flag is set, the
    width of the gadget's select box changes automatically whenever the
    width of its window changes.  When using GFLG_RELWIDTH, set the
    gadget's Width to a negative value.  This value will be added to the
    width of the gadget's display element (window or requester) to
    determine the actual width of the gadget's select box.

GFLG_RELHEIGHT
    Set this flag for "relative gadget height."  If this flag is set, the
    height of the gadget's select box changes automatically whenever the
    height of its window changes.  When using GFLG_RELHEIGHT, set the
    gadget's Height to a negative value.  This value will be added to the
    height of the gadget's display element (window or requester) to
    determine the actual height of the gadget's select box.

GFLG_SELECTED
    Use this flag to preset the on/off selected state for a toggle-select
    boolean gadget (see the discussion of the GACT_TOGGLESELCT flag
    below).  If the flag is set, the gadget is initially selected and is
    highlighted.  If the flag is clear, the gadget starts off in the
    unselected state.  To change the selection state of one or more
    gadgets, change their GFLG_SELECTED bits as appropriate, add them
    back and refresh them.  However, see the section on
    "Updating a Gadget's Imagery" for important details.

GFLG_DISABLED
    If this flag is set, this gadget is disabled. To enable or disable a
    gadget after the gadget has been added to the system, call the
    routines OnGadget() and OffGadget().  The GFLG_DISABLED flag can be
    programmatically altered in much the same way as GFLG_SELECTED above.
    See the section on "Updating a Gadget's Imagery" for important
    details.

GFLG_STRINGEXTEND
    The StringInfo Extension field points to a valid StringExtend
    structure.  Use of this structure is described later in the
    "String Gadget Type" section of this chapter.  This flag is ignored
    prior to V37, see GACT_STRINGEXTEND for the same functionality under
    V36.  Note that GACT_STRINGEXTEND is not ignored prior to V36 and
    should only be set in V36 or later systems.

GFLG_TABCYCLE
    This string participates in cycling activation with the tab (or
    shifted tab) key.  If this flag is set, the tab keys will de-activate
    this gadget as if the Return or Enter keys had been pressed, sending
    an IDCMP_GADGETUP message to the application, then the next string
    gadget with GFLG_TABCYCLE set will be activated.  Shifted tab
    activates the previous gadget.


5 / Gadget Structure / Gadget Activation Flags

These flags may be set in the Activation field of the Gadget structure.

GACT_TOGGLESELECT
    This flag applies only to boolean gadgets, and tells Intuition that
    this is to be a toggle-select gadget, not a hit-select one.  Preset
    the selection state with the gadget flag GFLG_SELECTED (see above).
    The program may check if the gadget is in the selected state by
    examining the GFLG_SELECTED flag at any time.

GACT_IMMEDIATE
    If this bit is set, the program will be sent an IDCMP_GADGETDOWN
    message when the gadget is first picked.  The message will be sent
    when the user presses the mouse select button.

GACT_RELVERIFY
    This is short for "release verify."  If this bit is set, the program
    will be sent an IDCMP_GADGETUP message when the gadget is
    deactivated.  IDCMP_GADGETUP will be sent for boolean gadgets when
    the user releases the mouse select button while the pointer is over
    the select box, for proportional gadgets whenever the user releases
    the mouse select button (regardless of the pointer position), and for
    string and integer gadgets when the user completes the text entry by
    pressing return or tabbing to the next gadget (where supported).

    For boolean gadgets, if the user releases the mouse button while the
    pointer is outside of the gadget's select box IDCMP_GADGETUP will not
    be generated.  Instead, the program will receive an
    IDCMP_MOUSEBUTTONS event with the SELECTUP code set.  For string
    gadgets, if the user deactivates the gadget by clicking elsewhere, it
    may not be possible to detect.

GACT_ENDGADGET
    This flag pertains only to gadgets attached to requesters.  If a
    gadget with the GACT_ENDGADGET flag set is chosen by the user the
    requester will be terminated as if the application had called the
    EndRequest() function.

    See the chapter "Intuition Requesters and Alerts," for more
    information about requester gadget considerations.

GACT_FOLLOWMOUSE
    These flags may be set in the Activation field of the Gadget
    structure. As long as a gadget that has this flag set is active, the
    program will receive mouse position messages for each change of mouse
    position.  For GTYP_BOOLGADGET gadgets, GACT_RELVERIFY must also be
    set for the program to receive mouse events.

The following flags are used to place application gadgets into a specified
window border.  Intuition will adjust the size of a window's borders
appropriately provided these gadgets are set up with a call to
OpenWindow(), OpenWindowTags() or OpenWindowTagList().  Intuition knows to
refresh gadgets marked with these flags when the window border is changed,
e.g., when the window is activated.  For GimmeZeroZero windows, the
GTYP_GZZGADGET flag must also be set for border gadgets.

GACT_RIGHTBORDER
    If this flag is set, the gadget is placed in the right border of the
    window and the width and position of this gadget are used in deriving
    the width of the window's right border.

GACT_LEFTBORDER
    If this flag is set, the gadget is placed in the left border of the
    window and the width and position of this gadget are used in deriving
    the width of the window's left border.

GACT_TOPBORDER
    If this flag is set, the gadget is placed in the top border of the
    window and the height and position of this gadget are used in
    deriving the height of the window's top border.

GACT_BOTTOMBORDER
    If this flag is set, the gadget is placed in the bottom border of the
    window and the height and position of this gadget are used in
    deriving the height of the window's bottom border.

The following flags apply only to string gadgets:

GACT_STRINGCENTER
    If this flag is set, the text in a string gadget is centered within
    the select box.

GACT_STRINGRIGHT
    If this flag is set, the text in a string gadget is right justified
    within the select box.

GACT_STRINGLEFT
    This "flag" has a value of zero.  By default, the text in a string
    gadget is left justified within the select box.

GACT_LONGINT
    If this flag is set, the user can construct a 32-bit signed integer
    value in a normal string gadget. The input buffer of the string
    gadget must be initialized with an ASCII representation of the
    starting integer value.

GACT_ALTKEYMAP
    These flags may be set in the Activation field of the Gadget
    structure.  A pointer to the keymap must be placed in the StringInfo
    structure variable AltKeyMap.

GACT_BOOLEXTEND
    This flag applies only to boolean gadgets.  If this flag is set, then
    the boolean gadget has a BoolInfo structure associated with it.  A
    pointer to the BoolInfo structure must be placed in the SpecialInfo
    field of the Gadget structure.

GACT_STRINGEXTEND
    This is an obsolete flag originally defined in V36.  It applies only
    to string gadgets and indicates that StringInfo.Extension points to a
    valid StringExtend structure.  Although this flag works, it is not
    ignored prior to V36 as it should be in order to be backward
    compatible.  This flag is replaced by GFLG_STRINGEXTEND in V37.
    GFLG_STRINGEXTEND performs the same function and is properly ignored
    on systems prior to V36.


5 Intuition Gadgets / Boolean Gadget Type

A boolean gadget gets yes/no or on/off responses from the user.  To make a
boolean gadget set the GadgetType field to GTYP_BOOLGADGET in the Gadget
structure.

Boolean gadgets come in two types: hit-select and toggle-select.
Hit-select gadgets are only active while the user holds down the mouse
select button.  When the button is released, the gadget is unhighlighted.
Action buttons, such as "OK" and "Cancel", are hit-select.

Toggle-select gadgets become selected when the user clicks them.  To
"unselect" the gadget, the user has to click the gadget again.  Switches,
such as a checkbox, are toggle-select.

Set the GACT_TOGGLESELECT flag in the Activation field of the Gadget
structure to create a toggle-select gadget.

The GFLG_SELECTED flag in Gadget structure Flags field determines the
initial and current on/off selected state of a toggle-select gadget.  If
GFLG_SELECTED is set, the gadget will be highlighted.  The application can
set the GFLG_SELECTED flag before submitting the gadget to Intuition.  The
program may examine this flag at any time to determine the current state
of this gadget.

Try to make the imagery for toggle-select gadgets visually distinct from
hit-select gadgets so that their operation can be determined by the user
through visual inspection.

 Masked Boolean Gadgets    BoolInfo Structure    Mutual Exclude


5 / Boolean Gadget Type / Masked Boolean Gadgets

Imagery for boolean gadgets is rectangular by default, but non-rectangular
boolean gadgets are possible, with some restrictions. An auxiliary bit
plane, called a mask, may be associated with a boolean gadget. When the
user clicks within the select box of the gadget, a further test is made to
see if the chosen point is contained within the mask. Only if it is, does
the interaction count as a gadget hit.

With masked boolean gadgets, if the gadget has highlight type
GFLG_GADGHCOMP then the complement rendering is restricted to the mask.
This allows for non-rectangular shapes, such as an oval gadget which
highlights only within the oval.

There are some shortcomings to non-rectangular boolean gadgets.  For
instance, the gadget image is not rendered through the mask.  Images are
rectangular blocks, with all bits rendered.  In the case of an oval mask,
the image will be rendered in the corner areas even though they are
outside of the oval.  Also, it is not possible to mask out the select box,
thus non-rectangular masked gadgets cannot overlap in the masked area.
Therefore, such gadgets can't be crowded together without care.  Likewise,
the ghosting of a disabled gadget does not respect the mask, so ghosting
of the corners around an oval may be visible, depending on the colors
involved.

To use a masked boolean gadget, fill out an instance of the BoolInfo
structure.  This structure contains a pointer to the mask plane data.  The
application must also set the GACT_BOOLEXTEND flag in the gadget's
Activation field.


5 / Boolean Gadget Type / BoolInfo Structure

This is the special data structure required for a masked boolean gadget. A
pointer to this structure must be placed in the gadget's SpecialInfo field
for a masked boolean gadget.

    struct BoolInfo
        {
        UWORD  Flags;
        UWORD  *Mask;
        ULONG  Reserved;
        };

Flags
    Flags must be given the value BOOLMASK.

Mask
    This is a bit mask for highlighting and picking the gadget.
    Construct the mask as a single plane of image data.  The image's
    width and height are determined by the width and height  of the
    gadget's select box.  The mask data must be in Chip memory.

Reserved
    Set this field to NULL.


5 / Boolean Gadget Type / Mutual Exclude

Mutual exclusion of boolean gadgets (sometimes referred to as "radio
buttons") is not directly supported by Intuition.  This section describes
the method an application should use to implement this feature.  It is up
to the application to handle the manipulation of excluded gadgets in an
Intuition compatible way.  The program must proceed with caution so as to
maintain the synchronization of the gadget and its imagery.  The rules
provided in this section for the implementation of mutual exclude gadgets
minimize the risk and complexity of the application.  Other techniques may
seem to work with simple input, but may fail in subtle ways when stressed.

 Gadget Type for Mutual Exclusion
 Gadget Highlighting for Mutual Exclusion
 Handling of Mutually Exclusive Gadgets


5 / / Mutual Exclude / Gadget Type for Mutual Exclusion

To implement mutual exclusion, gadgets must be hit-select (not
GACT_TOGGLESELECT) boolean gadgets, with the GACT_IMMEDIATE activation
type (never GACT_RELVERIFY).  All state changes must be executed upon
receiving the IDCMP_GADGETDOWN message for the gadgets.  Failure to do
this could introduce subtle out-of-phase imagery problems.


5 / / Mutual Exclude / Gadget Highlighting for Mutual Exclusion

When using complement mode highlighting, the image supplied must be at
least the size of the complemented area (the gadget select box).  An
extended boolean gadget with a mask may be used to constrain the area that
is highlighted.

Alternate image highlighting may be used provided the two images have
exactly the same size and position.  Likewise, a border and alternate
border may be used provided the two borders are identical in shape and
position, differing only in color.

Do not use other combinations for mutual exclude gadgets such as a gadget
with a border that uses complement mode highlighting or a gadget which
uses highlighting by drawing a box.  See the section on
"Updating a Gadget's Imagery" for more information.


5 / / Mutual Exclude / Handling of Mutually Exclusive Gadgets

Use RemoveGList() to remove the boolean gadget from the window or
requester.  Set or clear the GFLG_SELECTED flag to reflect the displayed
state of the gadget.  Replace the gadget using AddGList() and refresh its
imagery with RefreshGList().  Of course, several gadgets may be processed
with a single call to each of these functions.


5 Intuition Gadgets / Proportional Gadget Type

Proportional gadgets allow an application to get or display an amount,
level, or position by moving a slidable knob within a track.  They are
called proportional gadgets because the size and position of the knob is
proportional to some application-defined quantity, for example the size of
a page, and how much and which part of the page is currently visible.

An example of using proportional gadgets is available in the "Intuition
Windows" chapter.  The SuperBitMap window example, lines.c, uses
proportional gadgets to control the position of the bitmap within the
window.

Proportional gadgets are made up of a container, which is the full size of
the gadget, and a knob, that travels within the container.  Changing the
current value of the gadget is done by dragging the knob, or clicking in
the container around the knob.  Dragging the knob performs a smooth
transition from one value to the next, while clicking in the container
jumps to the next page or setting.  The KNOBHIT flag in the PropInfo
structure is available to allow the program to determine if the gadget was
changed by dragging the knob or by clicking in the container.  If the flag
is set, the user changed the value by dragging the knob.

Proportional gadgets allow display and control of fractional settings on
the vertical axis, the horizontal axis or both.  While the number of
settings has a theoretical limit of 65,536 positions, the actual
positioning of the gadget through sliding the knob is limited by the
resolution of the screen.  Further control is available by clicking in the
container, although this often is not convenient for the user.  Button or
arrow gadgets are often provided for fine tuning of the setting of the
gadget.

 New 3D Look Proportional Gadgets
 Logical Types of Proportional Gadgets
 Proportional Gadget Components
 Initialization of a Proportional Gadget
 Modifying an Existing Proportional Gadget


5 / Proportional Gadget Type / New 3D Look Proportional Gadgets

Set the PROPNEWLOOK flag in the PropInfo Flags field to get the new 3D
look.  The new 3D look proportional gadgets have a dithered pattern in the
container and updated knob imagery.  The knob dimensions are also slightly
changed for those proportional gadgets with a border.

Set the PROPBORDERLESS flag in the PropInfo Flags field if no border
around the container is desired.  Setting this flag with PROPNEWLOOK will
provide a 3D knob.

    Proportional gadgets and the New 3D Look.
    -----------------------------------------
    To create prop gadgets that have the same look as the rest of the
    system, set the PROPNEWLOOK flag and clear the PROPBORDERLESS flag.
    It is recommended that applications follow this guideline to maintain
    a compatible look and feel for all gadgets in the system.

New look proportional gadgets placed in the border of a window will change
to an inactive display state when the window is deactivated.  This only
happens to gadgets that have the PROPNEWLOOK flag set and are in the
window border.  In the inactive state, the knob is filled with
BACKGROUNDPEN.


5 / Proportional Gadget Type / Logical Types of Proportional Gadgets

There are two usual ways in which proportional gadgets are used
(corresponding to the scroller and slider gadgets of the GadTools
library).  The only difference between sliders and scrollers is the way
they are managed internally by the application.  The GadTools library
provides a high level interface to proportional gadgets, simplifying the
management task for these types of objects.

 Scrollers    Sliders


5 / / Logical Types of Proportional Gadgets / Scrollers

The scroller controls and represents a limited window used to display a
large amount of data.  For instance, a text editor may be operating on a
file with hundreds of lines, but is only capable of displaying twenty or
thirty lines at a time.

In a scroller, the container of the gadget is analogous to the total
amount of data, while the knob represents the window.  (Note that window
here is used as an abstract concept and does not necessarily mean
Intuition window.  It just means a display area reserved for viewing the
data.)

The size of the knob with respect to its container is proportional to the
size of the window with respect to the total data.  Thus, if the window
can display half the data, the knob should be half the size of the
container.  When the amount of data is smaller than the window size, the
knob should be as large as its container.

The position of the knob with respect to its container is also
proportional to the position of the window with respect to the total data.
Thus, if the knob starts half way down the container, the top of the
window should display information half way into the data.

Scrollers may be one or two dimensional.  One dimensional scrollers are
used to control linear data; such as a text file, which can be viewed as a
linear array of strings.  Such scrollers only slide on a single axis.

Two dimensional scrollers are used to control two dimensional data, such
as a large graphic image.  Such a scroller can slide on both the
horizontal and vertical axes, and the knob's horizontal and vertical size
and position should be proportional to the window's size and position in
the data set.

Multi-dimensional data may also be controlled by a number of one
dimensional scrollers, one for each axis.  The Workbench windows provide
an example of this, where one scroller is used for control of the x-axis
of the window and another scroller is used for control of the y-axis of
the window.  In this case, the size and position of the knob is
proportional to the size and position of the axis represented by the
gadget.

If the window has a sizing gadget and has a proportional gadget is the
right or bottom border, the sizing gadget is usually placed into the
border containing the proportional gadget, as the border has already been
expanded to contain the gadget.  If the window has proportional gadgets in
both the right and the bottom borders, place the sizing gadget into both
borders.  This creates evenly sized borders that match the height and
width of the sizing gadget, i.e. it is only done for visual effect.


5 / / Logical Types of Proportional Gadgets / Sliders

The slider is used to pick a specific value within a set.  Usually the set
is ordered, but this is not required.  An example of this would be
choosing the volume of a sound, the speed of an animation or the
brightness of a color.  Sliders can move on either the vertical or
horizontal axis.  A slider that moves on both the horizontal and the
vertical axis could be created to choose two values at once.

An example slider which picks an integer between one and ten, should have
the following attributes:

  * It should slide on only one axis.

  * Values should be evenly distributed over the length of the slider.

  * Clicking in the container to either side of the knob should increase
    (or decrease) the value by one unit.

Stylistically, sliding the knob to the right or top should increase the
value, while sliding it to the left or down should decrease the value.
Note that the orientation of proportional gadgets is correct for scrollers
(where the minimum value is topmost or leftmost), but is vertically
inverted for sliders.  Thus, well-behaved vertical sliders need to invert
their value somewhere in the calculations (or else the maximum will end up
at the bottom).


5 / Proportional Gadget Type / Proportional Gadget Components

A proportional gadget has several components that work together. They are
the container, the knob, the pot variables and the body variables.

 The Container         Using the Body and Pot Values
 The Knob              Functions for Using a Scroller
 The Pot Variables     Functions for Using a Slider
 The Body Variables


5 / / Proportional Gadget Components / The Container

The container is the area in which the knob can move.  It is actually the
select box of the gadget.  The size of the container, like that of any
other gadget select box, can be relative to the size of the window.  The
position of the container can be relative to any of the Intuition window's
border.

Clicking in the container around the knob will increment or decrement the
value of the gadget (the pot variables) by the appropriate amount
(specified in the body variables).  The knob will move towards the point
clicked when action is taken.


5 / / Proportional Gadget Components / The Knob

The knob may be manipulated by the user to quickly change the
pot variables.  The knob acts like a real-world proportional control.  For
instance, a knob restricted to movement on a single axis can be thought of
as a control such as the volume knob on a radio.  A knob that moves on
both axes is analogous to the control stick of an airplane.

The user can directly move the knob by dragging it on the vertical or
horizontal axis.  The knob may be indirectly moved by clicking within the
select box around the knob.  With each click, the pot variable is
increased or decreased by one increment, defined by the settings of the
body variables.

The current position of the knob reflects the pot value. A pot value of
zero will place the knob in the top or leftmost position, a value of
MAXPOT will place the knob at the bottom or rightmost position.

The application can provide its own imagery for the knob or it may use
Intuition's auto-knob.  The auto-knob is a rectangle that changes its
width and height according to the current body settings.  The auto-knob is
proportional to the size of the gadget.  Therefore, an auto-knob can be
used in a proportional gadget whose size is relative to the size of the
window, and the knob will maintain the correct size, relative to the size
of the container.

    Use Separate Imagery for Proportional Gadgets.
    ----------------------------------------------
    These Image structures may not be shared between proportional
    gadgets, each must have its own. Again, do not share the Image
    structures between proportional gadgets. This does not work, either
    for auto-knob or custom imagery.

    Use Only One Image for the Knob.
    --------------------------------
    Proportional gadget knob images may not be a list of images.  These
    must be a single image, initialized and ready to display if a custom
    image is used for the knob.


5 / / Proportional Gadget Components / The Pot Variables

The HorizPot and VertPot variables contain the actual proportional values
entered into or displayed by the gadget. The word pot is short for
potentiometer, which is an electrical analog device used to adjust a value
within a continuous range.

The proportional gadget pots allow the program to set the current position
of the knob within the container, or to read the knob's current location.

The pot variable is a 16-bit, unsigned variable that contains a value
ranging from zero to 0xFFFF. For clarity, the constant MAXPOT is
available, which is equivalent to 0xFFFF. A similar constant MAXBODY is
available for the body variables. As the pot variables are only 16 bits,
the resolution of the proportional gadgets has a maximum of 65,536
positions (zero to 65,535).

The values represented in the pot variables are usually translated or
converted to a range of numbers more useful to the application.  For
instance, if a slider covered the range one to three, pot values of zero
to 16,383 would represent one, values of 16,384 to 49,151 would represent
two and values of 49,152 to 65,535 would represent three.  The method of
deriving these numbers is fairly complex, refer to the sample code below
for more information.

There are two pot variables, as proportional gadgets are adjustable on the
horizontal axis, the vertical axis or both.  The two pot variables are
independent and may be initialized to any 16-bit, unsigned value.

Pot values change while the user is manipulating the gadget.  The program
may read the values in the pots at any time after it has submitted the
gadget to the user via Intuition.  The values always have the current
settings as adjusted by the user.


5 / / Proportional Gadget Components / The Body Variables

The HorizBody and VertBody variables describe the standard increment by
which the pot variables change and the relative size of the knob when
auto-knob is used.  The increment, or typical step value, is the value
added to or subtracted from the internal knob position when the user clicks
in the container around the knob.  For example, a proportional gadget for
color mixing might allow the user to add or subtract 1/16 of the full value
each time, thus the body variable should be set to MAXBODY / 16.

Body variables are also used in conjunction with the auto-knob (described
above) to display for the user how much of the total quantity of data is
displayed.  Additionally, the user can tell at a glance that clicking in
the container around the knob will advance the position by an amount
proportional to the size of the knob.

For instance, if the data is a fifteen line text file, and five lines are
visible in the display, then the body variable should be set to one third
of MAXBODY.  In this case, the auto-knob will fill one third of the
container, and clicking in the container ahead of the knob will advance
the position in the file by one third.

For a slider, the body variables are usually set such that the full
percentage increment is represented.  This is not always so for a
scroller.  With a scroller, some overlap is often desired between
successive steps.  For example, when paging through a text editor, one or
two lines are often left on screen from the previous page, making the
transition easier on the user.

The two body variables may be set to the same or different increments.
When the user clicks in the container, the pot variables are adjusted by
an amount derived from the body variables.


5 / / Proportional Gadget Components / Using the Body and Pot Values

The body and pot values of a proportional gadget are "Intuition friendly"
numbers, in that they represent concepts convenient to Intuition, and not
to the application.  The application must translate these numbers to
internal values before acting on them.


5 / / Proportional Gadget Components / Functions for Using a Scroller

/*
**   FindScrollerValues( )
**
** Function to calculate the Body and Pot values of a proportional gadget
** given the three values total, displayable, and top, representing the
** total number of items in a list, the number of items displayable at one
** time, and the top item to be displayed.  For example, a file requester
** may be able to display 10 entries at a time.  The directory has 20
** entries in it, and the top one displayed is number 3 (the fourth one,
** counting from zero), then total = 20, displayable = 10, and top = 3.
**
** Note that this routine assumes that the displayable variable is greater
** than the overlap variable.
**
** A final value, overlap, is used to determine the number of lines of
** "overlap" between pages.  This is the number of lines displayed from the
** previous page when jumping to the next page.
*/

void FindScrollerValues(UWORD total, UWORD displayable, UWORD top,
                        WORD overlap, UWORD *body, UWORD *pot)
{
UWORD hidden;

/* Find the number of unseen lines: */

hidden = max(total - displayable, 0);

/* If top is so great that the remainder of the list won't even
** fill the displayable area, reduce top:
*/

if (top > hidden)
    top = hidden;

/* body is the relative size of the proportional gadget's knob.  Its size
** in the container represents the fraction of the total that is in view.
** If there are no lines hidden, then body should be full-size (MAXBODY).
** Otherwise, body should be the fraction of (the number of displayed
** lines - overlap) / (the total number of lines - overlap).
** The "- overlap" is so that when the  user scrolls by clicking in the
** container of the scroll gadget, then there is some overlap between the
** two views.
*/

(*body) = (hidden > 0) ?
    (UWORD) (((ULONG) (displayable - overlap) * MAXBODY)
                           / (total - overlap)) :
    MAXBODY;

/* pot is the position of the proportional gadget knob, with zero meaning
** that the scroll gadget is all the way up (or left), and full (MAXPOT)
** meaning that the scroll gadget is all the way down (or right).  If we
** can see all the lines, pot should be zero.  Otherwise, pot is the top
** displayed line divided by the number of unseen lines.
*/

(*pot) = (hidden > 0) ? (UWORD) (((ULONG) top * MAXPOT) / hidden) : 0;
}

/*
**   FindScrollerTop( )
**
** Function to calculate the top line that is displayed in a proportional
** gadget, given the total number of items in the list and the number
** displayable, as well as the HorizPot or VertPot value.
*/

UWORD FindScrollerTop(UWORD total, UWORD displayable, UWORD pot)

{
UWORD top, hidden;

/* Find the number of unseen lines: */

hidden = max(total - displayable, 0);

/* pot can be thought of as the fraction of the hidden lines that are
** before the displayed part of the list, in other words a pot of zero
** means all hidden lines are after the displayed part of the list
** (i.e. top = 0), and a pot of MAXPOT means all the hidden lines are
** before the displayed part (i.e. top = hidden).
**
** MAXPOT/2 is added to round up values more than half way to the next
** position.
*/

top = (((ULONG) hidden * pot) + (MAXPOT/2)) >> 16;

/* Once you get back the new value of top, only redraw your list if top
** changed from its previous value.  The proportional gadget may not have
** moved far enough to change the value of top.
*/

return(top);
}


5 / / Proportional Gadget Components / Functions for Using a Slider

/*
**     FindSliderValues( )
**
** Function to calculate the Body and Pot values of a slider gadget given
** the two values numlevels and level, representing the number of levels
** available in the slider, and the current level.  For example, a Red,
** Green, or Blue slider would have (currently) numlevels = 16,
** level = the color level (0-15).
*/

void FindSliderValues(UWORD numlevels, UWORD level,
                      UWORD *body, UWORD *pot)

{
/* body is the relative size of the proportional gadget's body.
** Clearly, this proportion should be 1 / numlevels.
*/

if (numlevels > 0)
    (*body) = (MAXBODY) / numlevels;
else
    (*body) = MAXBODY;

/* pot is the position of the proportional gadget body, with zero meaning
** that the slider is all the way up (or left), and full (MAXPOT) meaning
** that the slider is all the way down (or right).
**
** For slider gadgets the derivation is a bit ugly:
**
** We illustrate a slider of four levels (0, 1, 2, 3) with the slider at
** level 2.  The key observation is that pot refers the the leading edge of
** the knob, and as such MAXPOT is not all the way to the right, but is one
** body's width left of that.
**
** Level:   0       1       2       3
**      ---------------------------------
**      |       |       |*******|       |
**      |       |       |*******|       |
**      |       |       |*******|       |
**      |       |       |*******|       |
**      ---------------------------------
**      |               |       |
**      0              pot    MAXPOT
**
** From which we observe that pot = MAXPOT * (level/(numlevels-1))
*/

if (numlevels > 1)
    {
    (*pot) = (((ULONG)MAXPOT) * level)/(numlevels-1);
    }
else
    {
    (*pot) = 0;
    }
}

/*
**     FindSliderLevel( )
**
** Function to calculate the level of a slider gadget given the total
** number of levels as well as the HorizPot or VertPot value.
*/

UWORD FindSliderLevel(UWORD numlevels, UWORD pot)

{
UWORD level;

/* We illustrate a 4-level slider (0, 1, 2, 3) with the knob on the
** transition point between calling it at levels 1 and 2.
**
** Level:   0       1       2       3
**      ---------------------------------
**      |       |    ***|***    |       |
**      |       |    ***|***    |       |
**      |       |    ***|***    |       |
**      |       |    ***|***    |       |
**      ---------------------------------
**      |           |           |
**      0          pot        MAXPOT
**
**
** We've already shown that the vertical lines (which represent the natural
** position of the knob for a given level are:
**
**     pot = MAXPOT * (level/(numlevels-1))
**
** and we see that the threshold between level and level-1 is half-way
** between pot(level) and pot(level-1), from which we get
**
**     level = (numlevels-1) * (pot/MAXPOT) + 1/2
*/

if (numlevels > 1)
    {
    level = (((ULONG)pot) * (numlevels-1) + MAXPOT/2) / MAXPOT;
    }
else
    {
    level = 0;
    }

return(level);
}


5 / Proportional Gadget / Initialization of a Proportional Gadget

The proportional gadget is initialized like any other gadget, with the
addition of the PropInfo structure.

 Initialization of the PropInfo Structure
 Initialization of the Gadget Structure


5 / / Initialization of Proportional Gadget / the PropInfo Structure

This is the special data required by the proportional gadget.

    struct PropInfo
        {
        UWORD Flags;
        UWORD HorizPot;
        UWORD VertPot;
        UWORD HorizBody;
        UWORD VertBody;
        UWORD CWidth;
        UWORD CHeight;
        UWORD HPotRes, VPotRes;
        UWORD LeftBorder;
        UWORD TopBorder;
        };

Flags
    In the Flags variable, the following flag bits are of interest:

    PROPBORDERLESS
        Set the PROPBORDERLESS flag to create a proportional gadget
        without a border.

    AUTOKNOB
        Set the AUTOKNOB flag in the Flags field to use the auto-knob,
        otherwise the application must provide knob imagery.

    FREEHORIZ and FREEVERT
        Set the FREEHORIZ flag to create a gadget that adjust
        left-to-right, set the FREEVERT flag for top-to-bottom movement.
        Both flags may be set in a single gadget.

    PROPNEWLOOK
        Set the PROPNEWLOOK flag to create a gadget with the new look.
        If this flag is not set, the gadget will be rendered using a V34
        compatible design.

    KNOBHIT
        The KNOBHIT flag is set by Intuition when this knob is hit by
        the user.

HorizPot and VertPot
    Initialize the HorizPot and VertPot variables to their starting
    values before the gadget is added to the system. The variables may be
    read by the application. The gadget must be removed before writing to
    these variables, or they may be modified with NewModifyProp().

HorizBody and VertBody
    Set the HorizBody and VertnBody variables to the desired increment. If
    there is no data to show or the total amount displayed is less than
    the area in which to display it, set the body variables to the
    maximum, MAXBODY.

The remaining variables and flags are reserved for use by Intuition.


5 / / Initialization of Proportional Gadget / of the Gadget Structure

In the Gadget structure, set the GadgetType field to GTYP_PROPGADGET and
place the address of the PropInfo structure in the SpecialInfo field.

When using AUTOKNOB, the GadgetRender field must point to an Image
structure. The Image need not be initialized when using AUTOKNOB, but the
structure must be provided. These Image structures may not be shared
between gadgets, each must have its own.

To use application imagery for the knob, set GadgetRender to point to an
initialized Image structure. If the knob highlighting is done by alternate
image (GFLG_GADGHIMAGE), the alternate image must be the same size and
type as the normal knob image.


5 / Proportional Gadget Type / Modifying an Existing Gadget

To change the flags and the pot and body variables after the gadget is
displayed, the program can call NewModifyProp().

    void NewModifyProp( struct Gadget *gadget, struct Window *window,
                        struct Requester *requester, unsigned long flags,
                        unsigned long horizPot, unsigned long vertPot,
                        unsigned long horizBody, unsigned long vertBody,
                        long numGad );

The gadget's internal state will be recalculated and the imagery will be
redisplayed to show the new state.  When numGads (in the prototype above)
is set to all ones, NewModifyProp() will only update those parts of the
imagery that have changed, which is much faster than removing the gadget,
changing values, adding the gadget back and refreshing its imagery.


5 Intuition Gadgets / String Gadget Type

A string gadget is an area of the display in which a single field of
character data may be entered.  When a string gadget is activated, either
by the user or by the application, a cursor appears prompting the user to
enter some text.  Any characters typed will be placed into the active
string gadget, unless the gadget is deactivated by other mouse activity or
program interaction.

In Release 2, the system also supports tabbing between a group of string
gadgets.  In this mode, pressing the tab key will advance the active
gadget to the next string gadget and pressing shifted tab will advance to
the previous string gadget.

Control characters are generally filtered out, but may be entered by
pressing the Left Amiga key with the desired control character.  The
filtering may be disabled by the program, or by the user via the IControl
Preferences editor.

String gadgets feature auto-insert, which allows the user to insert
characters wherever the cursor is.  Overwrite mode is also available, and
the application may toggle the gadget between the two modes.

When the user activates a string gadget with the mouse, the gadget's
cursor moves to the position of the mouse.  The user may change the
position of the cursor both with the cursor keys and with the mouse
pointer.

A number of simple, keyboard driven editing functions are available to the
user.  These editing functions are shown in the following table.

          Table 5-1: Editing Keys and Their Functions

            Key              Function
            ---              --------
                 <-  Cursor to previous character.

           Shift <-  Cursor to beginning of string.

                 ->  Cursor to next character.

           Shift ->  Cursor to end of string.

                Del  Delete the character under the cursor. Does
                     nothing in fixed field mode.

          Shift Del  Delete from the character under the cursor to the
                     end of the line. Does nothing in fixed field mode.

          Backspace  Delete the character to left of cursor. In fixed
                     field mode, move cursor to previous character.

    Shift Backspace  Delete from the character to the left of the
                     cursor to the start of the line. In fixed field
                     mode, move cursor to beginning of string.

    Return or Enter  Terminate input and deactivate the gadget. If the
                     GACT_RELVERIFY activation flag is set, the
                     program will receive a IDCMP_GADGETUP event for
                     this gadget.

      Right Amiga Q  Undo (cancel) the last editing change to the
                     string.

      Right Amiga X  Clears the input buffer. The undo buffer is left
                     undisturbed. In fixed field mode, move cursor to
                     beginning of string.

The following additional editing functions are available only when "Filter
Control Characters" is on for the string gadget. Control character
filtering is only available if the IControl preferences editor has "Text
Gadget Filter" selected and the individual gadget does not have
SGM_NOFILTER set.

          Table 5-2: Additional Editing Keys and Their Functions

          Key                Function
          ---                --------
         Ctrl A      Jump cursor to start of buffer.

         Ctrl H      Delete the character to the left of the cursor.
                     In fixed field mode, move cursor to previous
                     character.

         Ctrl K      Delete from the character under the cursor to the
                     end of the string. Does nothing in fixed field
                     mode.

         Ctrl M      Equivalent to Return or Enter (end gadget).

         Ctrl W      Delete the previous word. In fixed field mode,
                     jump cursor to the start of the previous word.

         Ctrl U      Delete from the character to the left of the
                     cursor to the start of the buffer. In fixed field
                     mode, jump cursor to the start of the buffer.

         Ctrl X      Clears the input buffer (like Right Amiga X). In
                     fixed field mode, jump cursor to the start of the
                     buffer.

         Ctrl Z      Jump cursor to end of buffer.

 Integer Gadget Type                    StringInfo Structure
 String Gadget IDCMP Messages           Extended String Gadgets
 Program Control of String Gadgets      Custom String Editing
 Tabbing Between String Gadgets
 Gadget Structure For String Gadgets


5 / String Gadget Type / Integer Gadget Type

The integer gadget is really a special case of the string gadget type.
Initialize the gadget as a string gadget, then set the GACT_LONGINT flag
in the gadget's Activation field.

The user interacts with an integer gadget using exactly the same rules as
for a string gadget, but Intuition filters the input, allows the user to
enter only a plus or minus sign and digits.  The integer gadget returns a
signed 32-bit integer in the StringInfo variable LongInt.

To initialize an integer gadget to a value, preload the input buffer with
an ASCII representation of the initial integer. It is not sufficient to
initialize the gadget by merely setting a value in the LongInt variable.

Integer gadgets have the LongInt value updated whenever the ASCII contents
of the gadget changes, and again when the gadget is deactivated.


5 / String Gadget Type / String Gadget IDCMP Messages

If the application has specified the GACT_RELVERIFY activation flag, it
will be sent an IDCMP_GADGETUP message when the gadget is properly
deactivated.  This happens when Return or Enter is pressed, when tabbing
to the next string gadget (where supported), and when a custom string
editing hook returns SGA_END.

The gadget may become inactive without the application receiving an
IDCMP_GADGETUP message.  This will happen if the user performs some other
operation with the mouse or if another window is activated.  The gadget
may still contain updated, valid information even though the
IDCMP_GADGETUP message was not received.


5 / String Gadget Type / Program Control of String Gadgets

ActivateGadget() allows the program to activate a string gadget (and
certain custom gadgets).  If successful, this function has the same effect
as the user clicking the mouse select button when the mouse pointer is
within the gadget's select box and any subsequent keystrokes will effect
the gadget's string.

    BOOL ActivateGadget( struct Gadget *gadget, struct Window *window,
                         struct Requester *requester );

This function will fail if the user is in the middle of some other
interaction, such as menu or proportional gadget operation.  In that case
it returns FALSE, otherwise it returns TRUE. The window or requester
containing the string gadget to be activated must itself be open and
active.  Since some operations in Intuition may occur after the function
that initiates them completes, calling ActivateGadget() after
OpenWindowTagList() or Request() is no guarantee that the gadget will
actually activate. Instead, call ActivateGadget() only after having
received an IDCMP_ACTIVEWINDOW or IDCMP_REQSET message for a newly opened
window or requester, respectively.

    The Window Active Message Is Required.
    --------------------------------------
    It is incorrect to simply insert a small delay between the call to
    OpenWindowTagList() or Request() and the call to ActivateGadget().
    Such schemes fail under various conditions, including changes in
    processor speed and CPU loading.

If you want to activate a string gadget in a newly opened window that has
a shared IDCMP UserPort, there is an additional complication.  Sharing
UserPorts means that the window is opened without any IDCMP messages
enabled, and only later is ModifyIDCMP() called to turn on message
passing.  If the newly opened window becomes active before ModifyIDCMP()
is called, the IDCMP_ACTIVEWINDOW message will not be received (because
IDCMP message passing was off at the time).  The following code will
handle this problem:

       BOOL activated;

       /* Open window with NULL IDCMPFlags */
       win = OpenWindow( ... );

       /* Set the UserPort to your shared port, and turn on message
        * passing, which includes the IDCMP_ACTIVEWINDOW message.
        */
       win->UserPort = sharedport;
       ModifyIDCMP( win, ... | IDCMP_ACTIVEWINDOW | ... );

       /* If the window became active before the ModifyIDCMP() got
        * executed, then this ActivateGadget() can succeed.  If not, then
        * this ActivateGadget() might be too early, but in that case, we
        * know we'll receive the IDCMP_ACTIVEWINDOW event.  We handle that
        * below.
        */
        activated = ActivateGadget( stringgad, win, NULL );

  and later, in the event loop:

    if ( (msg->Class == ACTIVEWINDOW) && ( !activated ) )
        success = ActivateGadget(stringgad,...);

Note however that a window which has the WA_Activate attribute is not
guaranteed to be activated upon opening.  Certain conditions (like an
active string gadget in another window) will prevent the automatic initial
activation of the window.  Therefore, do not let your code depend on
receiving the initial IDCMP_ACTIVEWINDOW message.

 String Gadget Example


5 / String Gadget Type / Tabbing Between String Gadgets

The Amiga allows tabbing to the next string gadget in a window or
requester and shifted tabbing to the previous string gadget.  This
function operates starting with V37.

If the GFLG_TABCYCLE flag is set, this string participates in cycling
activation with Tab or Shift Tab.  If only a single gadget has this flag
set, then the Tab keys will have no effect.  If one of the Tab keys is
pressed while in a string gadget without GFLG_TABCYCLE set, nothing will
happen, even though other string gadgets may have the flag set.

Activation order is determined by the order of the string gadgets in the
gadget list, following the NextGadget link.  The tab key will advance to
the next string gadget with GFLG_TABCYCLE set, shifted tab will move to
the previous gadget.  To order gadgets for tabbing (next/ previous string
gadget), place them in the correct order in the gadget list when they are
added to the system.  This order must be maintained if the gadgets are
removed and put back, or the tabbing order will change.

The tab keys will de-activate the current gadget as if one of the Return
or Enter keys had been pressed, sending an IDCMP_GADGETUP message to the
application.  The application can recognize that tab was pressed by
looking for 0x09 (the ASCII tab character) in the Code field of the
IDCMP_GADGETUP IntuiMessage.  If necessary, it can then inspect the
qualifier field of that message to see if the shift key was pressed.  The
next string gadget with GFLG_TABCYCLE set will be activated, with shifted
tab activating the previous string gadget.


5 / String Gadget Type / Gadget Structure For String Gadgets

To an application, a string gadget consists of a standard Gadget structure
along with an entry buffer, an undo buffer and a number of extensions.

For a string gadget, set the GadgetType field in the Gadget structure to
GTYP_STRGADGET.  Set the SpecialInfo field to point to an instance of a
StringInfo structure, which must be initialized by the application.

The container for a string gadget is its select box.  The application
specifies the size of the container.  As the user types into the string
gadget, the characters appear in the gadget's container.

String gadgets may hold more characters than are displayable in the
container.  To use this feature, the application simply provides a buffer
that is larger than the number of characters that will fit in the
container.  This allows the user to enter and edit strings that are much
longer than the visible portion of the buffer.  Intuition maintains the
cursor position and scrolls the text in the container as needed.

The application may specify the justification of the string in the
container.  The default is GACT_STRINGLEFT, or left justification.  If the
flag GACT_STRINGCENTER is set, the text is center justified; if
GACT_STRINGRIGHT is set, the text is right justified.

When the gadget is activated, the select box contents are redrawn,
including the background area.  If GFLG_STRINGEXTEND is set for the gadget
or the gadget is using a proportional font by default, then the entire
select box will be cleared regardless of the font size or
StringInfo.MaxChars value.  For compatibility reasons, if the string
gadget is not extended then the following conditions apply (see the
section on "Extending String Gadgets" for more information).

  * If the font is monospace (not proportional), the width of the gadget
    will be rounded down to an even multiple of the font width.

  * If the string gadget is left justified (GACT_STRINGLEFT), a maximum
    of StringInfo.MaxChars times the font width pixels of space will be
    cleared.  Thus, if MaxChars is 3 (two characters plus the trailing
    NULL) and the font width is 8, then a maximum of 3 * 8 = 24 pixels
    will be cleared.  If the font defaults to a proportional font, then
    the width returned by FontExtent() will be used as the character
    width.

No facilities are provided to place imagery within the select box of a
string gadget.

 String Gadget Imagery and Highlighting


5 / / Gadget Structure For String Gadgets / Imagery and Highlighting

Any type of image may be supplied for the rendering of a string
gadget--image, border, or no image at all.  The highlighting for a string
gadget must be the complementing type (GFLG_GADGHCOMP).  Alternate imagery
may not be used for highlighting.


5 / String Gadget Type / StringInfo Structure

String gadgets require their own special structure called the StringInfo
structure.

    struct StringInfo
        {
        UBYTE *Buffer;
        UBYTE *UndoBuffer;
        WORD BufferPos;
        WORD MaxChars;
        WORD DispPos;
        WORD UndoPos;
        WORD NumChars;
        WORD DispCount;
        WORD CLeft, CTop;
        struct StringExtend *Extension;
        LONG LongInt;
        struct KeyMap *AltKeyMap;
        };

Buffer
    The application must supply an input buffer (Buffer) and an optional
    undo buffer (UndoBuffer) for the gadget.  The input buffer is where
    data typed into the gadget is placed by Intuition.  The program can
    examine this buffer at any time.

    A string copied into the input buffer before the gadget is added to
    the system will be displayed in the gadget when it is displayed, and
    may then be edited by the user.  The input buffer may be initialized
    to any starting value, as long as the initial string is NULL
    terminated and fits within the buffer.  To initialize the buffer to
    the empty string (no characters), put a NULL in the first position of
    the buffer.

    Integer gadgets must have the ASCII value of the initial number
    placed into the Buffer before the gadget is added to the system.

UndoBuffer
    If a string gadget has an undo buffer, the undo feature will be
    enabled.  "Undo" allows the user to revert to the initial string (the
    value in the buffer before gadget activation) at any time before the
    gadget becomes inactive.  The UndoBuffer is used to hold a copy of
    the previous string while the user edits the current string.  When
    the gadget is activated, the Buffer is copied to the UndoBuffer. The
    Buffer may be restored at any time up to the time the gadget is
    deactivated, by typing right-Amiga Q.

    Multiple string gadgets may share the same undo buffer as long as the
    buffer is as large as the largest input buffer.

MaxChars
    MaxChars tells Intuition the size of the input buffer. This count
    includes the trailing NULL of any data entered into the buffer, so
    the number of characters the gadget may hold is MaxChars - 1.

BufferPos
    BufferPos is initialized to the current position of the cursor in the
    buffer.  BufferPos runs from zero to one less than the length of the
    string.  If this position is not within the characters that will be
    displayed, Intuition will adjust DispPos for the gadget to make the
    cursor visible.

DispPos
    DispPos is initialized to the starting character in the string to
    display on screen.  This allows strings longer than the number of
    displayable characters to be positioned within the gadget.  Intuition
    will not position the string such that there is empty character space
    to the right of the string and characters scrolled out of the gadget
    box to the left.

UndoPos, NumChars, DispCount, CLeft and CTop
    These variables are maintained by Intuition and should not be
    modified by the application.  UndoPos specifies the character
    position in the undo buffer.  NumChars specifies the number of
    characters currently in the buffer.  DispCount specifies the number
    of whole characters visible in the container.

Extension
    The StringInfo Extension allows for additional control over string
    gadget behavior and appearance.  See below for details.

LongInt
    LongInt contains the integer value entered into an Integer type of
    string gadget.  After the user has finished entering an integer, the
    application can read the value in this variable.

 Gadget Key Mapping


5 / / Stringinfo Structure / Gadget Key Mapping

By default, screen characters appear using simple ASCII key translations.
If desired, the application can set up alternate key mapping.  A pointer
to the KeyMap structure is placed into the AltKeyMap field of the
StringInfo structure.  The GACT_ALTKEYMAP bit in the Activation flags of
the gadget must also be set.

See the "Console Device" chapter in the Amiga ROM Kernel Reference Manual:
Devices, and the "Keymap Library" chapter in this manual for more
information about the console device and key mapping.


5 / String Gadget Type / Extended String Gadgets

The StringInfo structure may be extended by setting the GFLG_STRINGEXTEND
gadget flag and placing a pointer to a StringExtend structure in the
StringInfo Extension variable.  GFLG_STRINGEXTEND is available beginning
with V37, under V36 the application must use GACT_STRINGEXTEND to get the
same functionality.  Note that GACT_STRINGEXTEND is not ignored prior to
V36 and should only be set in V36 or later systems.  GFLG_STRINGEXTEND is
ignored prior to V37.

    struct StringExtend
        {
        struct TextFont *Font;
        UBYTE       Pens[2];
        UBYTE       ActivePens[2];
        ULONG       InitialModes;
        struct Hook *EditHook;
        UBYTE       *WorkBuffer;
        ULONG       Reserved[4];
        };

Font
    If a font is specified in the StringExtend structure, that font will
    be used by the gadget.  By default, the string gadget inherits the
    font of the screen on which it appears.  Note that this is a pointer
    to an open font and not a pointer to a TextAttr structure.

    Proportional fonts are supported in string gadgets starting with
    Release 2. If the select box of the gadget is not tall enough to
    render the font, Intuition will fall back to topaz 8.

Pens
    Pens specify the pens used to render the text while the gadget is
    inactive.  Pens[0] is the foreground (text) pen, Pens[1] is the
    background pen.

ActivePens
    ActivePens specify the pens used to render the text while the gadget
    is active. ActivePens[0] is the foreground (text) pen, ActivePens[1]
    is the background pen.

InitialModes
    These modes may be used in StringExtend structure InitialModes field.

    SGM_REPLACE
        If this flag is set, the string gadget will be in replace or
        overwrite mode.  If this flag is cleared, the string gadget will
        be in insert mode.  In replace mode, characters entered
        overwrite the existing characters.  In insert mode, characters
        entered are inserted into the buffer and the following
        characters are advanced by one position until the buffer is
        full.  If the buffer is full in insert mode then characters may
        not be entered until some are deleted.

        When using this flag, always initialize StringInfo with an
        in-range value of BufferPos.  While most changes to gadgets
        require the application to first remove the gadget before
        modifying the gadget, this flag may be toggled without removing
        the gadget from the gadget list.  The change will take effect on
        the next character typed by the user.

    SGM_NOFILTER
        Don't filter control chars, enter them into the gadget as typed.
        In this mode the control character command keys for string
        gadgets are not active.  If the user disables control character
        filtering from the IControl Preferences editor, there is no way
        for the application to turn it on for an individual string
        gadget.  In filter mode, control characters may be entered into
        the string by holding the left Amiga key while the character is
        entered.

        While most changes to gadgets require the application to first
        remove the gadget before modifying the gadget, this flag may be
        toggled without removing the gadget from the gadget list.  The
        change will take effect on the next character typed by the user.

    SGM_FIXEDFIELD
        Fixed length buffer used for editing, the user cannot shorten or
        lengthen the string through edit operations.  The field length
        is taken from the length of the character string in the buffer
        when the gadget is added to the system.  Fixed field mode
        modifies the meanings of many of the string editing keys, as
        explained in the tables above.  Always set SGM_REPLACE when
        using a fixed length buffer.

    SGM_EXITHELP
        Allows the help key to be heard by the application from within
        string gadgets.  The gadget will exit immediately when the help
        key is pressed with the IntuiMessage.Code set to 0x5F (new for
        V37).

EditHook and WorkBuffer
    EditHook and WorkBuffer are used for custom string editing, which is
    discussed below.


5 / String Gadget Type / Custom String Editing

The application may choose to control the editing features provided in
string gadgets used within the application.  To locally install the custom
string editing features, the application provides a hook in the
StringExtend structure EditHook field.

A hook is a well defined calling interface for a user provided subroutine
or function.  Hooks are more fully described in the "Utility Library"
chapter.  A string gadget hook is called in the standard way, where the
hook object is a pointer to a SGWork structure, and the hook message is a
pointer to a command block.  However, unlike a function callback hook, a
string gadget editing hook is called on Intuition's task context, not on
the application's own context.  Therefore, a string gadget editing hook
must not use dos.library, and may not Wait() on application signals or
message ports, and may not call any Intuition function which might wait
for Intuition.

The command block starts with either (longword) SGH_KEY or SGH_CLICK.
There may be new commands added in the future, so the application should
not assume that these are the only possible commands. The hook should
return zero if it doesn't understand the command and non-zero if the
command is supported.

The SGWork structure, defined in <intuition/sghooks.h>, is listed on the
next page.  Use this structure as the hook object for custom string
editing hooks.

 SGWork Structure       Actions with SGH_KEY
 EditOp Definitions     The SGH_CLICK Command
 Actions Definitions    Actions with SGH_CLICK
 The SGH_KEY Command    Example String Gadget Editing Hook


5 / / Custom String Editing / SGWork Structure

    struct SGWork" link Includes/intuition/sghooks.h/MAIN 32}
        {
        struct Gadget       *Gadget;
        struct StringInfo   *StringInfo;
        UBYTE               *WorkBuffer;
        UBYTE               *PrevBuffer;
        ULONG               Modes;
        struct InputEvent   *IEvent;
        UWORD               Code;
        WORD                BufferPos;
        WORD                NumChars;
        ULONG               Actions;
        LONG                LongInt;
        struct GadgetInfo   *GadgetInfo;
        UWORD               EditOp;
        };

The local (application) hook may only change the Code, Actions,
WorkBuffer, NumChars, BufferPos and LongInt fields.  None of the other
fields in the SGWork structure may be modified.

Gadget and StringInfo
    The values in the string gadget before any modification are available
    through the Gadget and StringInfo pointers.

PrevBuffer
    The PrevBuffer provides a shortcut to the old, unmodified string
    buffer.

WorkBuffer, BufferPos, NumChars and LongInt
    WorkBuffer, BufferPos, NumChars and LongInt contain the values that
    the string gadget will take if the edits are accepted.  If the edit
    hook updates these values, the gadget will take on the updated values.

IEvent
    IEvent contains the input event that caused this call to the hook.
    This input event is not keymapped.  Only use this event for action
    keys, like the Return key, function keys or the Esc key.

Code
    If the input event maps to a single character, the keymapped value
    will be in the Code field.  The Code field may also be modified, and
    the value placed in it will be passed back to the application in the
    IDCMP_GADGETUP message when SGA_END is specified in the Actions field.

GadgetInfo
    A structure of information defined in <intuition/cghooks.h>.  This
    structure is read only.  See the "BOOPSI" chapter for more
    information.

Modes
    The modes of the gadget such as insert mode, defined below.

Actions
    The action taken by the edit hook, defined below.

EditOp
    The type of edit operation done by the global hook, defined below.


5 / / Custom String Editing / EditOp Definitions

These values indicate the basic type of operation the global editing hook
has performed on the string before the application gadget's custom editing
hook gets called.  Only global editing hooks must update the value in the
EditOp field before they return.  The value placed in the field should
reflect the action taken.

  EditOp          Action Taken by Global Hook
  ------          ---------------------------
  EO_NOOP         Did nothing.
  EO_DELBACKWARD  Deleted some chars (possibly 0).
  EO_DELFORWARD   Deleted some characters under and in front of the cursor.
  EO_MOVECURSOR   Moved the cursor.
  EO_ENTER        Enter or Return key, terminate.
  EO_RESET        Current Intuition-style undo.
  EO_REPLACECHAR  Replaced one character and (maybe) advanced cursor.
  EO_INSERTCHAR   Inserted one character into string or added one at end.
  EO_BADFORMAT    Didn't like the text data,
                  e.g., alpha characters in a GACT_LONGINT type.
  EO_BIGCHANGE    Complete or major change to the text, e.g. new string.
  EO_UNDO         Some other style of undo.
  EO_CLEAR        Clear the string.
  EO_SPECIAL      An operation that doesn't fit into the categories here.


5 / / Custom String Editing / Actions Definitions

These are the actions to be taken by Intuition after the hook returns.
Set or clear these bits in SGWork structure Actions field.  A number of
these flags may already be set when the hook is called.

  Actions Flag    Purpose
  ------------    -------
  SGA_USE         If set, use contents of SGWork.
  SGA_END         Terminate gadget, Code field is sent to application
                  in IDCMP_GADGETUP event code field.
  SGA_BEEP        Beep (i.e., flash) the screen.
  SGA_REUSE       Reuse the input event.  Only valid with SGA_END.
  SGA_REDISPLAY   Gadget visuals have changed, update on screen.
  SGA_NEXTACTIVE  Make next possible gadget active (new for V37).
  SGA_PREVACTIVE  Make previous possible gadget active (new for V37).


5 / / Custom String Editing / The SGH_KEY Command

The SGH_KEY command indicates that the user has pressed a key while the
gadget is active.  This may be any key, including non-character keys such
as Shift, Ctrl and Alt.  Repeat keys (one call per repeat) and the Amiga
keys also cause the hook to be called with the SGH_KEY command.  The hook
is not called for "key up" events.

The SGH_KEY command must be supported by any custom string editing hook.
There are no parameters following the SGH_KEY command longword.  All
information on the event must be derived from the SGWork structure.

Intuition has already processed the event and filled-in the SGWork
structure before calling the hook.  The information included in this
structure includes the type of action taken (EditOp), the new cursor
position (BufferPos), the new value in the buffer (WorkBuffer),  the
previous value in the buffer (PrevBuffer), the input event that caused
this call (IEvent) and more.


5 / / Custom String Editing / Actions with SGH_KEY

If SGA_USE is set in the SGWork structure Actions field when the hook
returns, Intuition will use the values in the SGWork fields WorkBuffer,
NumChars, BufferPos, and LongInt; copying the WorkBuffer to the StringInfo
Buffer.  SGA_USE is set by Intuition prior to calling the hook, and must
be cleared by the hook if the changes are to be ignored.  If SGA_USE is
cleared when the hook returns, the string gadget will be unchanged.

If SGA_END is set when the hook returns, Intuition will deactivate the
string gadget.  In this case, Intuition will place the value found in
SGWork structure Code field into the IntuiMessage.Code field of the
IDCMP_GADGETUP message it sends to the application.

If SGA_REUSE and SGA_END are set when the hook returns, Intuition will
reuse the input event after it deactivates the gadget.

Starting in V37, the hook may set SGA_PREVACTIVE or SGA_NEXTACTIVE with
SGA_END.  This tells Intuition to activate the next or previous gadget
that has the GFLG_TABCYCLE flag set.

If SGA_BEEP is set when the hook returns, Intuition will call
DisplayBeep().  Use this if the user has typed in error, or buffer is full.

Set SGA_REDISPLAY if the changes to the gadget warrant a gadget redisplay.
Changes to the cursor position require redisplay.


5 / / Custom String Editing / The SGH_CLICK Command

The SGH_CLICK command indicates that the user has clicked the select
button of the mouse within the gadget select box.  There are no parameters
following the SGH_CLICK command longword.

Intuition will have already calculated the mouse position character cell
and placed that value in SGWork.BufferPos.  The previous BufferPos value
remains in the SGWork.StringInfo.BufferPos.

Intuition will again use the SGWork fields listed above for SGH_KEY.  That
is, the WorkBuffer, NumChars, BufferPos and LongInt fields values may be
modified by the hook and are used by Intuition if SGA_USE is set when the
hook returns.


5 / / Custom String Editing / Actions with SGH_CLICK

SGA_END or SGA_REUSE may not be set for the SGH_CLICK command. Intuition
will not allow gadgets which go inactive when chosen by the user. The
gadget always consumes mouse events in its select box.

With SGH_CLICK, always leave the SGA_REDISPLAY flag set, since Intuition
uses this when activating a string gadget.


5 / String Gadget Type / Custom Gadgets

Intuition also supports custom gadgets, where the application can supply
to Intuition its own code to manage gadgets.  This allows the creation of
gadgets with behavior quite different from standard boolean, proportional,
or string gadgets.  For example, it would be possible to create a dial
gadget, where the user could rotate the knob of a gadget.  The code for a
custom gadget needs to respond to various commands and requests from
Intuition, such as "is this pixel in your hit-area?", "please go active"
and "please go inactive".

Intuition has an object-oriented creation and delegation method called
BOOPSI, that allows custom gadgets to be easily created, deleted,
specialized from existing classes of custom gadget, and so on.  See the
Intuition chapter "BOOPSI" for details.


5 Intuition Gadgets / Function Reference

The following are brief descriptions of the Intuition functions that
relate to the use of Intuition gadgets. See the Amiga ROM Kernel Reference
Manual: Includes and Autodocs for details on each function call.

               Table 5-3: Functions for Intuition Gadgets
  _______________________________________________________________________
 |                                                                       |
 |      Function                      Description                        |
 |=======================================================================|
 |       AddGadget()  Add a gadget to an open window or requester.       |
 |        AddGList()  Add some gadgets to an open window or requester.   |
 |    RemoveGadget()  Remove a gadget from an open window or requester.  |
 |     RemoveGList()  Remove some gadgets from an open window or         |
 |                    requester.                                         |
 |  RefreshGadgets()  Refresh all gadgets for the window or requester.   |
 |    RefreshGList()  Refresh some gadgets from the window or requester. |
 |-----------------------------------------------------------------------|
 |      ModifyProp()  Change the values of an open proportional gadget.  |
 |   NewModifyProp()  Optimized version of ModifyProp().                 |
 |-----------------------------------------------------------------------|
 |        OnGadget()  Enable an open gadget.                             |
 |       OffGadget()  Disable an open gadget.                            |
 |-----------------------------------------------------------------------|
 |  ActivateGadget()  Activate an open string gadget.                    |
 |     SetEditHook()  Change the global edit hook for string gadgets.    |
 |_______________________________________________________________________|


Amiga® RKM Libraries: 6 Intuition Menus

Menus are command and option lists associated with an application window
that the user can bring into view at any time.  These lists provide the
user with a simple way to access features of the application without
having to remember or enter complex character-based command strings.

The Intuition menu system handles all of the menu display without
intervention from the application.  The program simply submits an
initialized list of data structures to Intuition and waits for menu events.

This chapter shows how to set up menus that allow the user to choose from
your program's commands and options.

 About Menus         Menu Data Structures    Other Menu Macros
 Setting Up Menus    A Menu Example          Function Reference


6 Intuition Menus / About Menus

Intuition's menu system provides applications with a convenient way to
group together and display the commands and options available to the user.
In most cases menus consist of a fixed list of text choices however this
is not a requirement.  Items in the menu list may be either graphic images
or text, and the two types can be freely used together.  The number of
items in a menu can be changed if necessary.

 Types of Menu Choices    The Menu System    Menu Limitations


6 / About Menus / Types of Menu Choices

Menu choices represent either actions or attributes.  Actions are
analogous to verbs.  An action is executed and then forgotten.  Actions
include such things as saving and printing files, calculating values and
displaying information on the program.

Attributes are analogous to adjectives.  An attribute stays in effect
until canceled.  Attributes include such things as pen type, color, draw
mode and numeric format.

For instance, in a word processor, menus could be used to control the
following types of features:

      * File loading and saving (action).

      * Editing functions (action).

      * Formatting preferences (attributes).

      * Printing functions (action).

      * Current font and style (attributes).

Menus can be set up such that some attribute items are mutually exclusive
(selecting an attribute cancels the effects of one or more other
attributes).  For example, a drawing or graphics package may only allow
one color to be active at a time--selecting a color cancels the previous
active color.

The program can also allow a number of attributes to be in effect at the
same time.  A common example of this appears in most word processing
programs, where the text style may be bold, italic or underlined.
Selecting bold does not rule out italic or underlined, in fact, all three
may be active at the same time.


6 / About Menus / The Menu System

To activate the menu system, the user presses the menu button (the right
mouse button).  This displays the menu bar in the screen's title area.
The menu bar displays a list of topics (called menus) that have menu items
associated with them (see figure).  The menu bar and menu items only
remain visible while the menu button is held down.

     Figure 6-1: Screen with Menu Bar Displayed

When the mouse pointer is moved onto one of the menus in the menu bar, a
list of menu items appears below the menu.  The user can move the pointer
within the list of menu items while holding down the menu button.  A menu
item will highlight when the pointer is over it and, if the item has a
sub-item list, that list will be displayed.

The specific menu that is displayed belongs to the active window. Changing
the active window will change the menu bar and the choices available to
the user.

Unlike some other systems, the Amiga has no "standard menu" that appears
in every menu bar.  In fact, a window need not have any menus at all, thus
holding down the mouse menu button does not guarantee the appearance of a
menu bar.  Although there is no "standard menu", Amiga, Inc. does have a
well-defined set of standards for menu design.  These standards are
covered in The Amiga User Interface Style Guide (also from Addison-Wesley).

 Selecting Menu Items    Menu Item Imagery


6 / / The Menu System / Selecting Menu Items

To select a single menu item, the user releases the menu button when the
pointer is over the desired item.  Intuition can notify your program
whenever the user makes a menu selection by sending an IDCMP message to
your window's UserPort.  Your application is then responsible for carrying
out the action associated with the menu item selected.  Action items lead
to actions taken by the program while attribute items set values in the
program for later reference.

Menu selection is restricted to the most subordinate item.  Top level
menus are never selected.  A menu item can be selected as long as it has
no sub-items, and a sub-item may always be selected.  (Of course, disabled
menu items and sub-items cannot be selected.) Intuition menus allow the
user to select multiple items by:

  * Pressing and releasing the select button (left mouse button) without
    releasing the menu button.  This selects the item and keeps the menus
    active so that other items may be selected.

  * Holding down both mouse buttons and sliding the pointer over several
    items.  This is called drag selecting.  All items highlighted while
    dragging are selected.

Drag selection, single selection with the select button and releasing the
mouse button over an item can all be combined in a single operation.  Any
technique used to select a menu item is also available to select a menu
sub-item.


6 / / The Menu System / Menu Item Imagery

Menu items can be graphic images or text.  There is no conceptual
difference between menus that display text and menus that display images,
in fact, the two techniques may be used together.  The examples in this
chapter use text based menus to avoid the extra code required to define
images.

When the user positions the pointer over an item, the item can be
highlighted through a variety of techniques.  These techniques include a
highlighted box around the selected item, complementing the entire item
and replacing the item with an alternate image or alternate text.

Attribute items can have an image rendered next to them, usually a
checkmark, to indicate whether they are in effect or not.  The checkmark
is positioned to the left of the item.  If the checkmark is present, the
attribute is on.  If not, the attribute is off.

On the right side of menu items, command key alternatives may be
displayed.  Command key alternatives allow the user to make menu
selections with the keyboard instead of the mouse.  This is done by
holding down the right Amiga key and then pressing the single character
command key alternative listed next to the menu item.  Command key
alternatives appear as a reverse video, fancy "A", followed by the single
character command key.

Menu items or whole menus may be enabled or disabled.  Disabling an item
prevents the user from selecting it.  Disabled items are ghosted
(overwritten with a pattern of dots making the image less distinct) in
order to distinguish them from enabled items. Menu help, a new feature of
Release 2, allows the application to be notified when the user presses the
help key at the same time the menu system is activated.  This allows
applications to provide a help feature for every item in its menus.  Menu
help may be requested on any level of a menu.


6 / About Menus / Menu Limitations

Menus are not layered so they lock the screen while they are displayed.
While the screen is locked, applications cannot render graphics into that
screen--any rendering will be suspended until the menus are no longer
displayed.

Menus can only display a limited number of choices.  Each window may have
up to 31 menus, each menu may have up to 63 items, and each item may have
up to 31 sub-items.

Menus always appear at the top of the screen and cannot be repositioned or
sized by the user.  Moving the pointer to the menu bar may be inconvenient
or time consuming for the user.  (This is why it is generally a good idea
to provide keyboard alternatives for menu items.)  If some application has
a function that the user will be performing repeatedly, it may be better
to use a series of gadgets in the window (or a separate window) rather
than a menu item.

 Alternatives to Menus


6 / / Menu Limitations / Alternatives to Menus

You may want to use a requester or a window as an alternative to menus.  A
requester can function as a "super menu" using gadgets to provide the
commands and options of a menu but with fewer restrictions on their
placement, size and layout.  See the chapter entitled
"Intuition Requesters and Alerts," for more information.

A window, also, could be substituted for a menu where an application has
special requirements.  Unlike menus, windows allow layered operations so
that commands and options can be presented without forcing all other
window output in the active screen to halt.

Windows may be sized, positioned and depth arranged.  This positioning
flexibility allows the user to make other parts of the screen and other
windows visible while they are entering data or selecting operations.  The
ability to access or view other data may be important in the user's choice
of actions or attributes.  See the "Intuition Windows" chapter for more
details.


6 Intuition Menus / Setting Up Menus

The application does not have to worry about handling the menu display.
The menus are simply submitted to Intuition and the application waits for
Intuition to send messages about the selection of menu items.  These
messages, along with the data in the menu structures, give the application
all the information required for the processing of the user actions.

Menus can be set up with the GadTools library on systems running Release 2
or a later version of the OS.  Since GadTools makes menu set up easier and
handles much of the detail work of menu processing (including adjusting to
the current font selection), it should be used whenever possible.

Under 1.3 (V34) and older versions of the OS, GadTools is not available.
To set up menus that work with these older systems, you use the Menu and
MenuItem structures.  In general, for each menu in the menu bar, you
declare one instance of the Menu structure.  For each item or sub-item
within a menu, you declare one instance of the MenuItem structure.
Text-based menus like the kind used in this chapter require an additional
IntuiText structure for each menu, menu item and sub-item.  All these
structures are defined in <intuition/intuition.h>.

The data structures used for menus are linked together to form a list
known as a menu strip.  For all the details of how the structures are
linked and for listings of Menu and MenuItem, see the Menu Data Structures"
section later in this chapter.

 Submitting and Removing Menu Strips
 Simple Menu Example
 Disabling Menu Operations
 Changing Menu Strips
 Sharing Menu Strips
 Menu Selection Messages
 Menu Numbers
 Help Key Processing in Menus
 Menu Layout
 About Menu Item Boxes
 Attribute Items and the Checkmark
 Toggle Selection
 Mutual Exclusion
 Managing the State of Checkmarks
 Command Key Sequences
 Enabling and Disabling Menus and Menu Items
 Intercepting Normal Menu Operations


6 / Setting Up Menus / Submitting and Removing Menu Strips

Once the application has set up the proper menu structures, linked them
into a list and attached the list to a window, the menu system completely
handles the menu display.  The menu strip is submitted to Intuition and
attached to the window by calling the function SetMenuStrip().

    BOOL SetMenuStrip( struct Window *window, struct Menu *menu );

SetMenuStrip() always returns TRUE.  This function can also be used to
attach a single menu strip to multiple windows by calling SetMenuStrip()
for each window (see below).

Any menu strip attached to a window must be removed before the window is
closed.  To remove the menu strip, call ClearMenuStrip().

    void ClearMenuStrip( struct Window *window );

The menu example below demonstrates how to use these functions with a
simple menu strip.


6 / Setting Up Menus / Simple Menu Example

Menu concepts are explained in great detail later in this chapter; for now
though it may be helpful to look at an example.  Here is a very simple
example of how to use the Intuition menu system.  The example shows how to
set up a menu strip consisting of a single menu with five menu items.  The
third menu item in the menu has two sub-items.

The example works with all versions of the Amiga OS however it assumes
that the Workbench screen is set up with the the Topaz 8 ROM font.  If the
font is different, the example will exit immediately since the layout of
the menus depends on having a monospaced font with 8 x 8 pixel characters.

     simplemenu.c


6 / Setting Up Menus / Disabling Menu Operations

If an application does not use menus at all, it may set the WFLG_RMBTRAP
flag, which allows the program to trap right mouse button events for its
own use.

By setting the WFLG_RMBTRAP flag with the WA_Flags tag when the window is
opened, the program indicates that it does not want any menu operations at
all for the window.  Whenever the user presses the right button while this
window is active, the program will receive right button events as normal
IDCMP_MOUSEBUTTONS events.


6 / Setting Up Menus / Changing Menu Strips

Direct changes to a menu strip attached to a window may be made only after
the menu strip has been removed from the window.  Use the ClearMenuStrip()
function to remove the menu strip.  It may be added back to the window
after the changes are complete.

Major changes include such things as adding or removing menus, items and
sub-items; changing text or image data; and changing the placement of the
data.  These changes require the system to completely re-layout the menus.

An additional function, ResetMenuStrip(), is available to let the
application make small changes to the menus without the overhead of
SetMenuStrip().  Only two things in the menu strip may be changed before a
call to ResetMenuStrip(), they are: changing the CHECKED flag to turn
checkmarks on or off, and changing the ITEMENABLED flag to enable/disable
menus, items or sub-items.

    BOOL ResetMenuStrip( struct Window *window, struct Menu *menu );

ResetMenuStrip() is called in place of SetMenuStrip(), and may only be
called on menus that were previously initialized with a call to
SetMenuStrip().  As with SetMenuStrip(), the menu strip must be removed
from the window before calling ResetMenuStrip().  Note that the window
used in the ResetMenuStrip() call does not have to be the same window to
which the menu was previously attached.  The window, however, must be on a
screen of the same mode to prevent the need for recalculating the layout
of the menu.

If the application wishes to attach a different menu strip to a window
that already has an existing menu strip, the application must call
ClearMenuStrip() before calling SetMenuStrip() with the new menu strip.

The flow of events for menu operations should be:

     1. OpenWindowTagList().

     2. SetMenuStrip().

     3. Zero or more iterations of ClearMenuStrip() and
        SetMenuStrip()/ResetMenuStrip().

     4. ClearMenuStrip().

     5. CloseWindow().


6 / Setting Up Menus / Sharing Menu Strips

A single menu strip may be attached to multiple windows in an application
by calling SetMenuStrip() for each window.  All of the windows must be on
the same screen for this to work.  Since menus are always associated with
the active window on a given screen, and since only one window may be
active on a screen at a time, only one window may display the shared menu
strip at any given time.

When multiple windows share a single menu strip, they will all "see" the
same state of the menus, that is, changes made to the menu strip from one
window will still exist when a new window is activated.  If the
application wishes to share menu strips but to have a different flag and
enabled status for each window, the program may watch IDCMP_ACTIVEWINDOW
for the windows and modify the menu strip to match the active window's
requirements at that point.  In addition, the application must also set
IDCMP_MENUVERIFY to insure that the user can't access the menus of a newly
activated window before the application can process the IDCMP_ACTIVEWINDOW
message.

ResetMenuStrip() may also be used to set the menus for the multiple
windows as long as SetMenuStrip() is used first to attach the menu strip
to any one window and no major changes are made to the menu strip before
the calls to ResetMenuStrip() on subsequent windows.


6 / Setting Up Menus / Menu Selection Messages

An input event is generated every time the user activates the menu system,
either by pressing the mouse menu button or its keyboard equivalent (right
Amiga Alt), or entering an appropriate command key sequence.  The program
receives a message of type IDCMP_MENUPICK detailing which menu items or
sub-items were selected.  Even if the user activates the menu system
without selecting a menu item or sub-item, an event is generated.

 Multi-Selection of Menu Items


6 / / Menu Selection Messages / Multi-Selection of Menu Items

Each activation of the menu system generates only a single event.  The
user may select none, one or many items using any of the selection
techniques described above; still, only one event is sent.

The program finds out whether or not multiple items have been chosen by
examining the field called NextSelect in the MenuItem structure.  The
selected items are chained together through this field.  This list is only
valid until the user next activates the menu system, as the items are
chained together through the actual MenuItem structures used in the menu
system.  If the user reselects an item, the NextSelect field of that item
will be overwritten.

In processing the menu events, the application should first take the
appropriate action for the item selected by the user, then check the
NextSelect field.  If the number there is equal to the constant MENUNULL,
there is no next selection.  However, if it is not equal to MENUNULL, the
user has selected another option after this one.  The program should
process the next item as well, by checking its NextSelect field, until it
finds a NextSelect equal to MENUNULL.

The following code fragment shows the correct way to process a menu event:

    struct IntuiMessage *msg;
    struct Menu *menuStrip;
    UWORD menuNumber;
    struct MenuItem *item;

    menuNumber = msg->Code;

    while (menuNumber != MENUNULL)
        {
        item = ItemAddress(menuStrip, menuNumber);

        /* process this item */

        menuNumber = item->NextSelect;
        }

Intuition specifies which item or sub-item was selected in the
IDCMP_MENUPICK event by using a shorthand code known as a menu number.
Programs can locate the MenuItem structure that corresponds to a given
menu number by using the ItemAddress() function.  This function translates
a menu number into a pointer to the MenuItem structure represented by the
menu number.

    struct MenuItem *ItemAddress( struct Menu *menuStrip,
                                  unsigned long menuNumber );

This allows the application to gain access to the MenuItem structure and
to correctly process multi-select events.  Again, when the user performs
multiple selection, the program will receive only one message of class
IDCMP_MENUPICK.  For the program to behave correctly, it must pay
attention to the NextSelect field of the MenuItem, which will lead to the
other menu selections.

There may be some cases in an application's logical flow where the
selection of a menu item voids any further menu processing.  For instance,
after processing a "quit" menu selection, the application will, in
general, ignore all further menu selections.


6 / Setting Up Menus / Menu Numbers

The menu numbers Intuition provides in the IDCMP_MENUPICK messages,
describe the ordinal position of the menu in the linked list of menus, the
ordinal position of the menu item beneath that menu, and (if applicable)
the ordinal position of the sub-item beneath that menu item.  Ordinal
means the successive number of the linked items, in this case, starting
from 0.

To determine which menus and menu items (sub-items are special cases of
menu items) were selected, use the following macros:

            Table 6-1: Macros Used with Intuition Menus
  _______________________________________________________________
 |                                                               |
 |  MENUNUM(num)  Extracts the ordinal menu number from num.     |
 |  ITEMNUM(num)  Extracts the ordinal item number from num.     |
 |   SUBNUM(num)  Extracts the ordinal sub-item number from num. |
 |_______________________________________________________________|

MENUNULL is the constant describing "no menu selection made."  Likewise,
NOMENU, NOITEM, and NOSUB describe the conditions "no menu chosen," "no
item chosen" and "no sub-item chosen."

For example:

    if (menuNumber == MENUNULL)
        /* no menu selection was made */ ;
    else
        {
        /* if there were no sub-items attached to that item,
        ** SubNumber will equal NOSUB.
        */
        menuNum = MENUNUM(menuNumber);
        itemNum = ITEMNUM(menuNumber);
        subNum  = SUBNUM(menuNumber);
        }

The menu number received by the program is always set to either MENUNULL
or a valid menu selection.  If the menu number represents a valid
selection, it will always have at least a menu number and a menu item
number.  Users can never select the menu text itself, but they always
select at least an item within a menu.  Therefore, the program always gets
at least the menu selected and the menu item selected.  If the menu item
selected has a sub-item, a sub-item number will also be received.

Just as it is not possible to select an entry in the menu bar, it is not
possible to select a menu item that has attached sub-items.  The user must
select one of the options in the sub-item list before the program hears
about the action as a valid menu selection.

    Help Is Available.
    ------------------
    The restrictions on what can be selected do not apply to
    IDCMP_MENUHELP messages.  Using menu help, a user can select any
    component of a menu, including the menu header itself.

 How Menu Numbers Really Work


6 / / Menu Numbers / How Menu Numbers Really Work

The following is a description of how menu numbers really work.  It should
clarify why there are some restrictions on the number of menu components
Intuition allows.  Programs should not rely on the information given here
to access menu number information directly though.  Always use the
Intuition menu macros to handle menu numbers.

For convenience you should use the menus supplied.  For example, to
extract the item number from the menu number, call the macro
ITEMNUM(menu_number); to construct a menu number, call the macro
FULLMENUNUM(menu, item, sub).  See the section at the end of this chapter
for a more complete description of the menu number macros.

Menu numbers are 16-bit numbers with 5 bits used for the menu number, 6
bits used for the menu item number, and 5 bits used for the sub-item
number.  The three numbers only have meaning when used together to
determine the position of the item or sub-item selected.

bit 15 (MSB)                                                 bit 0 (LSB)
    _______________________________________________________________
   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   |                   |                       |                   |
   |These bits are for |   These bits are for  |  These bits are   |
   |the Sub-items with-|     the Menu Items    |   for the Menu    |
   |in the Menu Items  |     within the Menu   |       number      |
   |                   |                       |                   |
   |___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|

The value "all bits on" means that no selection of this particular
component was made.  MENUNULL actually equals "no selection of any of the
components was made" so MENUNULL always equals "all bits of all components
on."

For example, suppose that the program gets back the menu number (in
hexadecimal) 0x0CA0.  In binary that equals:

bit 15 (MSB)                                                 bit 0 (LSB)
    _______________________________________________________________
   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
   |                   |                       |                   |
   |                   |                       |                   |
   | 0   0   0   0   1 | 1   0   0   1   0   1 | 0   0   0   0   0 |
   |                   |                       |                   |
   |                   |                       |                   |
   |___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|

     Sub_Item number=1    Menu Item number=37      Menu number=0

Again, the application should not examine these numbers directly. Use the
macros described above to ensure proper menu handling.


6 / Setting Up Menus / Help Key Processing in Menus

If the window is opened with the WA_MenuHelp tag, then user selection of
the help key while menus are displayed will be detected.  This tag is only
available under V37 and later.

When the user presses the Help key while using the menu system, the menu
selection is terminated and an IDCMP_MENUHELP event is sent.  The
IDCMP_MENUHELP event is sent in place of the IDCMP_MENUPICK event, not in
addition to it.  IDCMP_MENUHELP never come as multi-select items, and the
event terminates the menu processing session.

The routine that handles the IDCMP_MENUHELP events must be very
careful--it can receive menu information that is impossible under
IDCMP_MENUPICK.  IDCMP_MENUHELP events may be sent for any menu, item or
sub-item in the menu strip, regardless of its state or position in the
list.  The program may receive events for items that are disabled or
ghosted.  IDCMP_MENUHELP events may send the menu header number alone, or
the menu and item numbers, or all three components regardless of the items
linked to the selected menu or item.  This is done because it is
reasonable for a user to request help in a disabled item or a menu header.
If the user requests menu help on a disabled menu item or sub-item, try to
explain to the user why that item is disabled and what steps are necessary
to enable it.  For instance, pressing help while a menu header is
highlighted will trigger an IDCMP_MENUHELP event with a code that has a
valid number for the menu, then NOITEM and NOSUB (IDCMP_MENUPICK would
receive MENUNULL in this case.)

The application should not take the action indicated by the IDCMP_MENUHELP
event, it should provide the user with a description of the use or status
of that menu.  The application should never step through the NextSelect
chain when it receives a IDCMP_MENUHELP event.


6 / Setting Up Menus / Menu Layout

The Amiga allows great flexibility in the specification of fonts for the
display.  Default fonts are chosen by the user to suit their particular
requirements and display resolution.  The application should, where
possible, use one of the preferred fonts.

If the application did not open its own screen and completely specify the
font for that screen, it must perform dynamic menu layout.  This is
because the Menu structure does not specify font.  The menu header always
uses the screen font and the program should update the size and position
of these items at runtime to reflect the font.

The font for menu items may be specified in the MenuItem structure,
allowing the programmer to hard code values for the font, size and
position of these items.  This is not recommended.  A specific font, while
ideal on one system, may be less than ideal on another display type.  Use
the preferred font wherever possible.

If the application does its own menu layout, it must use great care to
handle the font in the menu strip and the font in each item or sub-item.
The code should also keep items from running off the edges of the screen.

See the description of ItemFill in the section "MenuItem Structure" below
for information on the positioning of multiple IntuiText or Image
structures within the menu item.

Applications should use the GadTools library menu layout routines whenever
possible, rather than performing their own layout.  See the chapter on the
"GadTools Library" for more details.


6 / Setting Up Menus / About Menu Item Boxes

The item box is the rectangle containing the menu items or sub-items.

The size and location of the item or sub-item boxes is not directly
described by the application.  Instead, the size is indirectly described
by the placement of items and sub-items.  When presented with a menu
strip, Intuition first calculates the minimum size box required to hold
the items.  It then adjusts the box to ensure the menu display conforms to
certain design philosophy constraints for items and sub-items.

     Figure 6-2: Example Item Box

The item box must start no further right than the leftmost position of the
menu header's select box.  It must end no further left than the rightmost
position of the menu header's select box.  The top edge of each item box
must overlap the screen's title bar by one line.  Each sub-item box must
overlap its item's select box somewhere.

    Always Overlap.
    ---------------
    If your application is designed to work on systems prior to V37, do
    not leave space between sub-items in a sub-item list.  This may cause
    flickering as the pointer moves off one item into the gap between the
    items.  Even a single line between the items may cause flickering.
    This flickering is eliminated starting with V37.

     Figure 6-3: Example Sub-item Box


6 / Setting Up Menus / Attribute Items and the Checkmark

Attribute items are items that have two states: selected and unselected.
In the menu system, these items are often represented as items with
checkmarks.  If the checkmark is visible, then the item (or attribute) is
selected.  Otherwise, the attribute is not selected.

Checkmarked items (attributes) may be toggle selected or mutually
exclusive.  Selecting a toggle selected item toggles its state--if it was
selected, it will become unselected; and if it was unselected, it will
become selected.  Selecting a mutually exclusive item puts it in the
selected state, while possibly clearing one or more other items, where it
remains until it is cleared by the selection of some other item.

A menu item is specified as a checkmark item by setting the CHECKIT flag
in the Flags variable of the item's MenuItem structure.

The program can initialize the state of the checkmark (checked or not) by
presetting the item's CHECKED flag.  If this flag is set when the menu
strip is submitted to Intuition, then the item is considered selected and
the checkmark will be drawn.

The program can use the default Intuition checkmark or provide a custom
checkmark for the menus.  To use a custom checkmark, the application must
provide a pointer to the image with the WA_Checkmark tag when the window
is opened.  See the chapter "Intuition Windows" for details about
supplying a custom checkmark.

The application must provide sufficient blank space at the left edge of
the select box for the checkmark imagery.  Constants are provided to
standardize the space reserved in the menu for the checkmark.
LOWCHECKWIDTH gives the amount of space required for checkmarks on low
resolution screens and CHECKWIDTH gives space for all other screens.

These constants specify the space required by the default checkmarks (with
a bit of space for aesthetic purposes).  If the item box would normally be
placed such that the LeftEdge of the item box without the checkmark is 5, the
item box should start at 5 + CHECKWIDTH if CHECKIT is set.  Also, the select
box must be made CHECKWIDTH wider than it would be without the checkmark.
It is generally accepted on the Amiga that only checkmarked items should
be indented by the size of the checkmark, other items are left justified
within their column.


6 / Setting Up Menus / Toggle Selection

Some of the checkmarked menu items may be of the toggle select type.  Each
time the user accesses such an item, it changes state, selected or
unselected.  To make an attribute item toggle select, set both the CHECKIT
and the MENUTOGGLE flags for that menu item.  Of course, the CHECKED flag
may be preset to the desired initial state.


6 / Setting Up Menus / Mutual Exclusion

Mutual exclusion allows the selection of an item to cause other items to
become unselected.

For example, for a list of menu items describing the available sizes for a
font, the selection of any size could unselect all other sizes.  Use the
MutualExclude variable in the MenuItem structure to specify other menu
items to be excluded when the user selects an item.  Exclusion also
depends upon the CHECKED and CHECKIT flags of the MenuItem, as explained
below.

  * If CHECKED is not set, then this item is available to be selected.
    If the user selects this item, the CHECKED flag is set and the
    checkmark will be drawn to the left of the item.

  * If the item selected has bits set in the MutualExclude field, the
    CHECKED flag is examined in the excluded items.  If any item is
    currently CHECKED, its checkmark is erased, and its CHECKED flag is
    cleared.

  * Mutual exclusion pertains only to items that have the CHECKIT flag
    set.  Attempting to exclude items that do not have the CHECKIT flag
    set has no effect.

    Keep track of deselected items.
    -------------------------------
    It is up to the program to track internally which excluded items have
    been deselected.  See the "Enabling and Disabling Menus and Menu Items"
    section below for more information.

In the MutualExclude field, bit 0 refers to the first item in the item
list, bit 1 to the second, bit 2 to the third, and so on.

In the text style example described above, selecting plain excludes any
other style.  The MutualExclude fields of the four items would look like
this:
                     _____________________
                    |                     |
                    |  Plain      0xFFFE  |
                    |  Bold       0x0001  |
                    |  Italic     0x0001  |
                    |  Underline  0x0001  |
                    |_____________________|

"Plain" is the first item on the list.  It excludes all items except the
first one.  All of the other items exclude only the first item, so that
bold, underlined text may be selected, while bold, plain text may not.


6 / Setting Up Menus / Managing the State of Checkmarks

To correctly handle checkmarked menu items, from time to time the
application will need to read the CHECKED bit of its CHECKIT MenuItems.
It is not adequate to infer which items are checked by tracking what their
state must have become.  There are several reasons for this (although it's
not important to understand the details; just the implication):

  * Using multi-selection of menus, the user can toggle the state of a
    MENUTOGGLE item several times, yet the application will receive only
    a single IDCMP_MENUPICK event, and that item will only appear once
    one the NextSelect chain.

  * When the user selects a mutually exclusive menu item, the
    IDCMP_MENUPICK event refers to that item, but Intuition doesn't
    notify your application of other items that may have been deselected
    through mutual exclusion.

  * Prior to V36, unusually complex multi-selection operations could
    orphan menu selections.  That is to say, some items that were
    selected may not even appear on the NextSelect chain.  If such an
    item had a checkmark, the state of that checkmark could nevertheless
    have changed.

  * For complex multi-selection operations, the NextSelect chain will not
    be in select-order (a side-effect of the fact that the same MenuItem
    cannot appear twice in the same NextSelect chain combined with the
    fix to the orphaning problems mentioned above).  With certain mutual
    exclusion arrangements, it is impossible to predict the state of the
    checkmarks.

  * If the user begins multi-selection in the menus and hits several
    checkmarked items, but then presses the help key, the application
    will receive an IDCMP_MENUHELP message.  No IDCMP_MENUPICK message
    will have been sent.  Thus, some checkmark changes could have gone
    unnoticed by the application.

It is legal to examine the CHECKED state of a MenuItem while that MenuItem
is still attached to a window.  It is unnecessary to first call
ClearMenuStrip().


6 / Setting Up Menus / Command Key Sequences

A command key sequence is an event generated when the user holds down one
of the Amiga keys (the ones with the fancy A) and presses one of the
normal alphanumeric keys at the same time.  There are two different
command or Amiga keys, commonly known as the left Amiga key and the right
Amiga key.

Menu command key sequences are combinations of the right Amiga key with
any alphanumeric character, and may be used by any program.  These
sequences must be accessed through the menu system.  Command key sequences
using the left Amiga key cannot be associated with menu items.

Menu command key sequences, like the menus themselves, are only available
for a window while that window is active.  Each window may control these
keys by setting keyboard shortcuts in the menu item structures which make
up the window's menu strip.

If the user presses a command key sequence that is associated with one of
the menu items, Intuition will send the program an event that is identical
to the event generated by selecting that menu item with the mouse.  Many
users would rather keep their hands on the keyboard than use the mouse to
make a menu selection when accessing often repeated selections.  Menu
command key sequences allow the program to provide shortcuts to the user
who prefers keyboard control.

A command key sequence is associated with a menu item by setting the
COMMSEQ flag in the Flags variable of the MenuItem structure and by
placing the ASCII character (upper or lower case) that is to be associated
with the sequence into the Command variable of the MenuItem structure.

Command keys are not case sensitive and they do not repeat.  Command keys
are processed through the keymap so that they will continue to work even
if the key value is remapped to another position.  International key
values are supported as long as they are accessible without using the Alt
key (right-Amiga-Alt maps to the right mouse button on the mouse).

     Figure 6-4: Menu Items with Command Key Shortcuts

When items have alternate key sequences, the menu boxes show a special
Amiga key glyph rendered roughly one character span plus a few pixels from
the right edge of the menu select box.  The command key used with the
Amiga key is displayed immediately to the right of the Amiga key image, at
the rightmost edge of the menu select box (see figure).

Space must be provided at the right edge of the select box for the Amiga
key imagery and for the actual command character.  Leave COMMWIDTH pixels
on high resolution screens, and LOWCOMMWIDTH pixels on low resolution
screens.  The character's width may be calculated with the graphics
library TextLength() call.  In general, each column of items should leave
enough room for the widest command character plus the width of the Amiga
key imagery.


6 / Setting Up Menus / Enabling and Disabling Menus and Menu Items

Disabling menu items makes them unavailable for selection by the user.

Disabled menus and menu items are displayed in a ghosted fashion; that is,
their imagery is overlaid with a faint pattern of dots, making it less
distinct.

Enabling or disabling a menu or menu item is always a safe procedure,
whether or not the user is currently using the menus.  Of course, by the
time you have disabled the item, the user may have already selected it.
Thus, the program may receive a IDCMP_MENUPICK message for that item, even
though it considers the item disabled.  The program should be prepared to
handle this case and ignore items that it knows are already disabled.
This implies that the program must track internally which items are
enabled and which are disabled.

The OffMenu() and OnMenu() functions may be used to enable or disable
items while a menu strip is attached to the window.

    void OffMenu( struct Window *window, unsigned long menuNumber );
    void OnMenu( struct Window *window, unsigned long menuNumber );

These routines check if the user is currently using the menus and whether
the menus need to be redrawn to reflect the new states.  If the menus are
currently in use, these routines wait for the user to finish before
proceeding.

If the item component referenced by menuNumber equals NOITEM, the entire
menu will be disabled or enabled.  If the item component equates to an
actual component number, then that item will be disabled or enabled.  Use
the macros defined below for the construction of menu numbers from their
component parts.

The program can enable or disable whole menus, just the menu items, or
just single sub-items.

  * To enable or disable a whole menu, set the item component of the menu
    number to NOITEM.  This will enable or disable all items and any
    sub-items for that menu.

  * To enable or disable a single item and all sub-items attached to that
    item, set the item component of the menu number to the item's ordinal
    number.  If the item has a sub-item list, set the sub-item component
    of the menu number to NOSUB.  If the item has no sub-item list, the
    sub-item component of the menu number is ignored.

  * To enable or disable a single sub-item, set the item and sub-item
    components appropriately.

It is also legal to remove the menu strip from each window that it is
attached to (with ClearMenuStrip() ) change the ITEMENABLED or MENUENABLED
flag of one or more Menu or MenuItem structures and add the menu back
using ResetMenuStrip() (in V36 or higher) or SetMenuStrip() (in any
version of the OS).


6 / Setting Up Menus / Intercepting Normal Menu Operations

IDCMP_MENUVERIFY gives the program the opportunity to react before menu
operations take place and, optionally, to cancel menu operations. Menus
may be completely disabled by removing the menu strip with a call to
ClearMenuStrip().

 A Warning on the MENUSTATE Flag    Shortcuts and IDCMP_MENUVERIFY
 Menu Verify                        IDCMP_MENUVERIFY and Deadlock


6 / / Intercepting Menu Operations / A Warning on the MENUSTATE Flag

The MENUSTATE flag is set by Intuition in Window.Flags when the menus of
that window are in use.  Beware: in typical event driven programming, such
a state variable is not on the same timetable as the application's input
message handling, and should not be used to draw profound conclusions in
any program.  Use IDCMP_MENUVERIFY to synchronize with the menu handling.


6 / / Intercepting Normal Menu Operations / Menu Verify

Menu verify is one of the Intuition verification capabilities that allow
an application to ensure that it is prepared for some action taken by
Intuition before that action takes place.  Through menu verify, Intuition
allows all windows in a screen to verify that they are prepared for menu
operations before the operations begin.  In general, use menu verify if
the program is doing something special to the display of a custom screen,
and needs to be sure the operation has completed before menus are rendered.

Any window can access the menu verify feature by setting the
IDCMP_MENUVERIFY flag with the WA_IDCMP tag when opening the window.  When
menus are activated in a screen which contains at least one window with
IDCMP_MENUVERFIY set, menu operations will not proceed until all windows
with the menu verify flag set reply to the notification or until the last
message times out.  The specific menu verify protocol is described below.

In any case, it is vital that the application know when menu operations
terminate, for only then does it have control of the screen again.  For
the active window, this is typically detected by watching for an
IDCMP_MENUPICK message.  If the program cancels the menu operations
(MENUCANCEL), then it will instead receive an IDCMP_MOUSEBUTTONS message
with code equal to MENUUP.  Inactive windows will always receive
IDCMP_MOUSEBUTTONS message with code equal to MENUUP.

The active window is given special menu verify treatment.  It receives the
menu verify message before any other window and has the option of
canceling menu operations altogether.  This could be used, for instance,
to examine where the user has positioned the mouse when the right button
was pressed.  For example, the application may choose to allow normal menu
operations to proceed only when the pointer is in the menu bar area.  When
the pointer is below the menu bar, then the application can choose to
interpret the menu verify message as a right button event for some
non-menu purpose.

The program can tell if it is the active window for the verify event by
examining the Code field of the IDCMP_MENUVERIFY message.  If the Code
field is equal to MENUWAITING, this window is not active and Intuition is
simply waiting for verification that menu operations may continue.
However, if the Code field is equal to MENUHOT, this window is active and
it determines if menu operations should proceed.

If it wishes menu operations to proceed, the active window should reply to
the IDCMP_MENUVERIFY message without changing any values.  To cancel the
menu operation, change the code field of the message to MENUCANCEL before
replying to the message.

When the active window cancels the menu operation it will be sent an
IDCMP_MOUSEBUTTONS message with code equal to MENUUP.  In general, the
window will not then receive an IDCMP_MENUPICK event as it cancelled the
operation.  However, the system should be prepared to handle an
IDCMP_MENUPICK message with code equal to MENUNULL as one may be sent if
the user releases the mouse button before the window replies to the
message.

The system takes no action on screen until the active window either
replies to the menu verify event or the event times out.  If the active
window replies to the event in time and does not cancel the menu
operation, Intuition will then move the screen title bar layer to the
front, display the menu strip and notify all inactive menu verify windows
of the operation.  Layers will not be locked and the actual menus will not
be swapped in until all these inactive windows reply to the message or
time out.  The inactive windows may not cancel the menu operation.

If the user releases the menu button before the active window replies to
the menu verify message, the menu operation will be cancelled and the
active window will be sent an IDCMP_MOUSEBUTTONS message with code equal
to MENUUP.  When the active window finally replies to the message, it will
receive an IDCMP_MENUPICK message with code equal to MENUNULL.

If the event times out before the active window replies to the message, it
will immediately be sent an IDCMP_MENUPICK message with code equal to
MENUNULL.  Then, when the user releases the menu button, the program will
receive an IDCMP_MOUSEBUTTONS message with code equal to MENUUP.

If an inactive window receives an IDCMP_MENUVERIFY message, it will always
receive an IDCMP_MOUSEBUTTONS message with code equal to MENUUP when the
menu operations are completed.

    About Double-Menu Requesters.
    -----------------------------
    The processing described above becomes more complicated when
    double-menu requester processing is introduced.  If an application
    chooses to use a double-menu requester in a window with
    IDCMP_MENUVERIFY set, it should be aware that odd message
    combinations are possible.  For instance, it is possible to receive
    only an IDCMP_MENUVERIFY event with no following IDCMP_MOUSEBUTTONS
    event or IDCMP_MENUPICK event.  Applications should avoid using
    double menu requesters if possible.


6 / / Intercepting Menu Operations / Shortcuts and IDCMP_MENUVERIFY

The idea behind IDCMP_MENUVERIFY is to synchronize the program with
Intuition's menu handling sessions.  The motive was to allow a program to
arbitrate access to a custom screen's bitmap, so that Intuition would not
render menus before the application was prepared for them.

Some programs use IDCMP_MENUVERIFY to permit them to intercept the right
mouse button for their own purposes.  Other programs use it to delay menu
operations while they recover from unusual events such as illegible colors
of the screen or double buffering and related ViewPort operations.

Menu shortcut keystrokes, for compatibility, also respect
IDCMP_MENUVERIFY.  They are always paired with an IDCMP_MENUPICK message
so that the program knows the menu operation is over.  This is true even
if the menu event is cancelled.


6 / / Intercepting Menu Operations / IDCMP_MENUVERIFY and Deadlock

The program may call ModifyIDCMP() to turn IDCMP_MENUVERIFY and the other
VERIFY IDCMP options off.  It is important that this be done each and
every time that the application is directly or indirectly waiting for
Intuition, since Intuition may be waiting for the application, but not
watching the window message port for IDCMP_MENUVERIFY events.  The program
cannot wait for a gadget or mouse event without checking also for any
IDCMP_MENUVERIFY event messages that may require program response.

The most common problem area is System Requesters (AutoRequest() and
EasyRequest()).  Before AutoRequest() and EasyRequest() return control to
the application, Intuition must be free to run and accept a response from
the user.  If the user presses the menu button, Intuition will wait for
the program to reply to the IDCMP_MENUVERIFY event and a deadlock results.

Therefore, it is extremely important to use ModifyIDCMP() to turn off all
verify messages before calling AutoRequest(), EasyRequest() or, directly
or indirectly, AmigaDOS, since many error conditions in the DOS require
user input in the form of an EasyRequest().  Indirect DOS calls include
OpenLibrary(), OpenDevice(), and OpenDiskFont().

Beginning with V36, all windows that have the IDCMP_MENUVERIFY bit set
must respond to Intuition within a set time period, or the menu operation
will time out and the menu action will be canceled.  This prevents the
deadlocks that were possible under previous versions of the operating
system.


6 Intuition Menus / Menu Data Structures

The specifications for the menu structures are given below.  Menus are the
headers that show in the menu bar, and MenuItems are the items and
sub-items that can be chosen by the user.

 Menu Structure    MenuItem Structure    MenuItem Flags


6 / Menu Data Structures / Menu Structure

Here is the specification for a Menu structure:

    struct Menu
        {
        struct Menu *NextMenu;
        WORD LeftEdge, TopEdge;
        WORD Width, Height;
        UWORD Flags;
        BYTE *MenuName;
        struct MenuItem *FirstItem;
        WORD JazzX, JazzY, BeatX, BeatY;
        };

The variables in the Menu structure have the following meanings:

NextMenu
    This variable points to the next Menu header in the list.  The last
    Menu in the list should have a NextMenu value of NULL.

LeftEdge, TopEdge, Width, Height
    These fields describe the select box of the header.  Currently, any
    values supplied for TopEdge and Height are ignored by Intuition,
    which uses instead the top of the screen for the TopEdge and the
    height of the screen's title bar for the Height.

    LeftEdge is relative to the LeftEdge of the screen plus the screen's
    left border width, so if LeftEdge is 0, Intuition puts this header at
    the leftmost allowable position.

Flags
    The flag space is shared by the program and Intuition.  The flags are:

    MENUENABLED
        This flag is for Intuition's use and indicates whether or not
        this Menu is currently enabled.  Set this flag before submitting
        the menu strip to Intuition.  If this flag is not set, the menu
        header and all menu items below it will be disabled, and the
        user will be able to view, but not select any of the items.
        After submitting the strip to Intuition, the disabled or enabled
        status may be changed by calling OnMenu() or OffMenu().

    MIDRAWN
        This flag indicates whether or not this menu's items are
        currently displayed to the user.

MenuName
    This is a pointer to a NULL terminated character string that is
    printed on the screen's title bar starting at the LeftEdge of this
    menu's select box and at the TopEdge just below the screen title
    bar's top border.  The text is rendered in the screen's font.

FirstItem
    This points to the first MenuItem structure in the linked list of
    this menu's items.

JazzX, JazzY, BeatX, BeatY
    For internal use only.


6 / Menu Data Structures / MenuItem Structure

The MenuItem structure is used for both items and sub-items.  There is no
internal difference between items and sub-items, other than how they are
linked into the menu strip.  Items are linked directly to Menu structures
through the FirstItem field, sub-items are linked to MenuItem structures
through the SubItem field.

Here is the specification:

    struct MenuItem
        {
        struct MenuItem *NextItem;
        WORD LeftEdge, TopEdge;
        WORD Width, Height;
        UWORD Flags;
        LONG MutualExclude;
        APTR ItemFill;
        APTR SelectFill;
        BYTE Command;
        struct MenuItem *SubItem;
        UWORD NextSelect;
        };

The fields have the following meanings:

NextItem
    This field is a pointer to the next item in the list.  The last item
    in the list should have a NextItem value of NULL.

LeftEdge, TopEdge, Width, Height
    These fields describe the select box of the MenuItem.  The LeftEdge
    is relative to the LeftEdge of the Menu. The TopEdge is relative to
    the topmost position Intuition allows.  TopEdge is based on the way
    the user has the system configured--which font, which resolution, and
    so on.  Use 0 for the topmost position.

Flags
    The flag space is shared by the program and Intuition. See
    "MenuItem Flags" below for a description of the flag bits.

MutualExclude
    Use these bits to describe which of the other items, if any, are
    mutually excluded by this one.  This long word refers to the items in
    the same menu as this one.  A maximum of 32 items may be described by
    this variable, and they must be the first 32 items in the menu.  This
    does not mean that there cannot be more than 32 items in any given
    menu, just that only the first 32 can be mutually excluded.

ItemFill
    This points to the data used in rendering this MenuItem.  It can
    point to either an instance of an IntuiText structure with text for
    this MenuItem or an instance of an Image structure with image data.
    The program tells Intuition the type of data pointed to by this
    variable by setting or clearing the MenuItem flag bit ITEMTEXT.  (See
    "MenuItem Flags" below for more details about ITEMTEXT.)

    Note that the IntuiText or Image data need not be simple imagery,
    either of them may consist of multiple objects of the same type
    chained together, described in "Intuition Images,Line Drawing and Text"
    chapter. By chaining multiple IntuiText structures, the application
    may "fine tune" the positioning of text within each item. This is
    especially important for proportional fonts, where the width of the
    individual characters is not constant.  This also allows items to
    have part of the text left justified and part right justified.

SelectFill
    If HIGHIMAGE is set in the Flags variable as the MenuItem
    highlighting mode, Intuition substitutes this alternate image or text
    for the original rendering described by ItemFill.  The type of this
    structure must be the same as ItemFill.  SelectFill can point to
    either an Image or an IntuiText, where the type is determined by the
    setting of the ITEMTEXT flag.

Command
    This variable is storage for a single alphanumeric character to be
    used as the command key substitute for this menu item.  The command
    key sequence will be rendered in the menu display to the right of the
    item's select area, with a fancy, reverse-video A, followed by the
    command character.  Case is ignored.

    If the flag COMMSEQ is set, the user can hold down the right Amiga
    key on the keyboard (to mimic using the right mouse menu button) and
    press the indicated key as a shortcut for using the mouse to select
    this item.

SubItem
    If this item has a sub-item list, this variable should point to the
    MenuItem structure describing the first sub-item in the list.

    There Is No Such Thing as a Sub-sub-item.
    -----------------------------------------
    A sub-item cannot have a sub-item attached to it.  If this
    MenuItem structure is not an item, this variable is ignored.

NextSelect
    This field is filled in by Intuition when this MenuItem is selected
    by the user.  After an item has been selected by the user, the
    program should process the request and then check the NextSelect
    field.  If the NextSelect field is equal to MENUNULL, no other items
    were selected;  otherwise, there is another item to process.  See
    "Menu Numbers" and "Menu Selection Messages" above for more information
    about user selections.


6 / Menu Data Structures / MenuItem Flags

Here are the flags that can be set by the application in the Flags field
of the MenuItem structure:

CHECKIT
    Set this flag to inform Intuition that this item is a checkmark item
    and should be preceded by a checkmark if the flag CHECKED is set.

CHECKED
    For an item with the CHECKIT flag set, set this bit to specify that
    the checkmark is displayed.  After the menu strip is submitted to
    Intuition, it will maintain the CHECKED bit based on effects from
    other items' mutual exclusions, or, for MENUTOGGLE items, from user
    accesses to this item.

ITEMTEXT
    Set this flag if the representation of the item pointed to by the
    ItemFill field and, possibly, by SelectFill is text and points to an
    IntuiText structure.  Clear this bit if the item is graphic and
    points to an Image structure.

COMMSEQ
    If this flag is set, this item has an equivalent command key sequence
    set in the Command field of the MenuItem structure.

MENUTOGGLE
    This flag is used in conjunction with the CHECKIT flag.  If
    MENUTOGGLE is set, a checkmark that is turned on may be turned off by
    selecting the item.  This allows the user to toggle between the
    checked and non-checked states by repeatedly selecting the item.

ITEMENABLED
    This flag describes whether or not this item is currently enabled.
    If an item is not enabled, its image will be ghosted and the user
    will not be able to select it.  If this item has sub-items, all of
    the sub-items are disabled when the item is disabled.

    Set this flag before submitting the menu strip to Intuition.  Once
    the menu strip has been submitted to Intuition, enable or disable
    items by calling OnMenu() or OffMenu().

HIGHFLAGS
    An item can be highlighted when the user positions the pointer over
    the item.  These bits describe what type of highlighting will be
    used, if any.  One of the following bits must be set, according to
    the type of highlighting desired:

    HIGHCOMP
        This complements all of the bits contained by this item's select
        box.

    HIGHBOX
        This draws a box outside this item's select box.

    HIGHIMAGE
        This displays alternate imagery referenced in SelectFill.  For
        alternate text, make sure that ITEMTEXT is set, and that the
        SelectFill field points to an IntuiText structure.  For
        alternate image, ITEMTEXT must be cleared, and the SelectFill
        field must point to an Image structure.

    HIGHNONE
        This specifies no highlighting.

The following two flags are used by Intuition:

ISDRAWN
    Intuition sets this flag when this item's sub-items are currently
    displayed to the user and clears it when they are not.

HIGHITEM
    Intuition sets this flag when this item is highlighted and clears it
    when the item is not highlighted.


6 Intuition Menus / A Menu Example

This example shows how to implement menus.  The menu code is simply part
of the processing for Intuition messages as shown in the IDCMP example in
the "Intuition Input and Output Methods" chapter.  The example implements
extended selection for menus, adaptation to fonts of different sizes,
mutual exclusion and checkmarks.

If possible, applications should use the menu layout routines available in
the GadTools library, rather than doing the job themselves as this example
does.  See the "GadTools Library" chapter for more information.

     menulayout.c


6 Intuition Menus / Other Menu Macros

The MENUNEM(), ITEMNUM() and SUBNUM() macros let an application break a
menu number down into its component parts--the specific menu number, the
item number and the sub-item number.  (See the section on "Menu Numbers"
earlier in this chapter for details.)  Intuition also supplies macros that
allow an application to construct a menu number given its components:

SHIFTMENU(n)
    Create a properly masked and shifted specific menu number.

SHIFTITEM(n)
    Create a properly masked and shifted item number.

SHIFTSUB(n)
    Create a properly masked and shifted sub-item number.

FULLMENUNUM( menu, item, sub )
    Create a complete composite menu number from its components.


6 Intuition Menus / Function Reference

The following are brief descriptions of the Intuition functions that
relate to the use of Intuition menus.  See the Amiga ROM Kernel Reference
Manual: Includes and Autodocs for details on each function call.

                 Table 6-2: Functions for Intuition Menus
  _______________________________________________________________________
 |                                                                       |
 |       Function                Description                             |
 |=======================================================================|
 |    SetMenuStrip()  Set a menu for an open window.                     |
 |  ClearMenuStrip()  Clear the menu of an open window.                  |
 |  ResetMenuStrip()  Set a pre-calculated menu for an open window.      |
 |-----------------------------------------------------------------------|
 |     ItemAddress()  Find the address of a menu item from its position. |
 |-----------------------------------------------------------------------|
 |         OffMenu()  Disable a menu in a menu strip.                    |
 |          OnMenu()  Enable a menu in a menu strip.                     |
 |_______________________________________________________________________|


Amiga® RKM Libraries: 7 Intuition Requesters and Alerts

This chapter explains how to create requesters, the information exchange
boxes that both the system and applications can use for confirming
actions, getting command options and similar operations.  These boxes are
called requesters because they generally request information from the user.

Alerts provide a function similar to requesters but are reserved for
emergency messages.  Alerts are discussed later in this chapter.

 Types Of Requesters    Easy Requesters      Alerts
 True Requesters        System Requesters    Function Reference
 Requester Structure


7 Intuition Requesters and Alerts / Types Of Requesters

There are at least three kinds of display objects in Amiga terminology
called requesters:  true requesters, system requesters and ASL requesters.

True requesters are general purpose display areas that can be thought of
as temporary sub-windows.  They display information to the user and allow
the user to make a selection.  True requesters always open within an
existing window and are constrained to the boundaries of that window
(often referred to as the parent window).  If a requester extends beyond
the edge of its parent window, either its position is adjusted or its
graphics are clipped.  True requesters always block input to their parent
window as long as they are present.

System requesters are typically used for warnings or to confirm an action
the user has just initiated.  System requesters differ from true
requesters in that they cannot block input to the parent window.  In fact,
system requesters do not open in a parent window at all, but instead open
their own separate window in the screen.  Since these requesters are so
different from true requesters, they will be discussed separately later in
the chapter.  See the sections on "Easy Requesters" and "System Requests"
for more information.

The third type of requester, the ASL requester, is a special purpose
requester available only in Release 2 and later versions of the OS.  ASL
requesters provide an easy, standard way to get a filename from the user
for load and save operations.  They can also be used to get a font
selection from the user.  Since selecting a file or font name is one of
the most common uses for a requester, it has been incorporated into
Release 2 as a standard feature.  For the details about ASL file and font
requesters, see Chapter 16, "ASL Library".


7 Intuition Requesters and Alerts / True Requesters

The primary function of a requester is to display information to the user
from which the user is to make a selection.  Conceptually, requesters are
similar to menus since both menus and requesters offer options to the
user.  Requesters, however, go beyond menus because they can have
customized imagery, can be placed anywhere in a window, can be activated
by the application and may have any type of gadget attached.

For instance, to select a color for a given operation using a menu could
be awkward, especially in an application that supports a large number of
colors.  In that case a requester could be used instead (see figure).

     Figure 7-1: Requester Deluxe

The ability of a true requester to block input to its parent window is
important in understanding how requesters are used.  When input is blocked
by a true requester (also known as a modal requester), the user must take
some action before the program will proceed further, such as making a
selection, correcting an error condition, or acknowledging a warning.
These are situations where a true (modal) requester is appropriate,
however, keep in mind that your application should try to be as
user-responsive as possible.  Putting up a requester merely because you
are in a phase of the program where it would be difficult to deal with
user input is bad style.  Modal requesters should be used only when the
program requires user interaction before proceeding.

True requesters can be created in a window in two different ways.

      * An application can display a requester at any time by calling
        the Request() function.

      * The application can declare a requester as the window's
        double menu requester, which the user can bring up with a
        double-click of the menu button (this method is rarely used).

 Creating Application Requesters
 Requester I/O
 Rendering Requesters
 Requester Refresh Type
 Requester Display Position
 Gadgets in Requesters
 Using a Requester to Block Window Input
 Double Menu Requesters
 IDCMP Requester Features


7 / True Requesters / Creating Application Requesters

To create a requester, the application first allocates memory for or
declares an instance of the Requester structure as defined in
<intuition/intuition.h>.  Once the Requester structure is set up, it is
initialized with the InitRequester() function.

    void InitRequester( struct Requester *requester)

This function simply clears the Requester structure.  The application
should do further initialization depending on its needs.  See the section
on the "Requester Structure" below for an explanation of all the Requester
fields and how to set them.

A true (modal) requester is attached to its parent window and displayed
with the Request() function.

    BOOL Request(struct Requester *requester, struct Window *window)

This function returns TRUE if the requester opens successfully or FALSE if
the requester cannot be opened.  If the requester opens successfully, menu
and gadget input in the parent window is blocked as long as the requester
is displayed.  The application should process input events from the
requester, which are sent to the parent window's Window.UserPort, until
the requester is satisfied.

To remove a requester from its parent window and update the display, use
EndRequest().

    void EndRequest( struct Requester *requester, struct Window *window );

This removes only the one requester specified.  It is possible to set up a
requester with a special gadget that, if selected, will automatically
close the requester.  In that case, EndRequest() need not be called.  If
the program needs to cancel the request early, or cancel it only after
some specific manipulation of the gadgets, EndRequest() should be used.

The application should always provide a safe way for the user to back out
of a requester without taking any action that affects the user's work.
Providing an escape hatch is important, for instance, a requester with the
message "Overwrite File?" should allow the user to cancel the operation
without losing the old data.


7 / True Requesters / Requester I/O

So long as a requester is active in a window, the only gadgets that can be
used are those that are in the requester, plus all of the window's system
gadgets except for the close gadget (i.e., the drag bar, size gadget,
depth gadget, and zoom gadget).  A requester also makes the menus of the
parent window inaccessible.  Additionally, mouse button and keyboard
events will be blocked (unless the requester's NOISYREQ flag is set; see
"Requester Structure" below).  Mouse movement events, if enabled in the
parent window (with WFLG_REPORTMOUSE), are not blocked.

Requesters do not have their own IDCMP message ports.  Instead, events for
a requester are sent to the IDCMP port of the requester's parent window
(Window.UserPort).  Since the window's menus and application gadgets are
inaccessible, no IDCMP events will be sent for them.

Even though the window containing the requester is blocked for input, the
user can work in another application or even in a different window of the
same application without satisfying the requester.  Only input to the
parent window is blocked by a requester.

Output is not blocked by a requester so nothing prevents the application
from writing to the window.  Be aware, however, that the requester
obscures part of the display and cannot be moved within the window so this
may limit the usefulness of any output you send to the parent window.
There are several ways to monitor the comings and goings of requesters
that allow the program to know if requesters are currently displayed in a
given window.  See "IDCMP Requester Features" below.

The information displayed in a requester is placed in its own layer, so it
does not overwrite the information in the window.  Output to the window
while the requester is displayed will not change the requester's display,
it will go into the window's layer.  The requester's layer is clipped to
the window's boundaries, so the data in the requester is only visible if
the window is large enough to allow for the complete display of that data.

The requester will remain in the window and input will remain blocked
until the user satisfies the request or the application removes the
requester.  Applications can set up some or all of the gadgets in the
requester to automatically terminate the requester when the gadget is
selected.  This allows the requester to be removed from the window by user
action.  The application may also remove requesters from the window based
on some event internal to the program.

Multiple requesters may be nested in a single window.  Such requesters
must be satisfied in the reverse order in which they were posted; the last
requester to be displayed must be satisfied first.  Input will not be
restored to a previous requester until all later requesters are satisfied.

Note that the application may not bring up a limitless number of
requesters in a window.  Each requester creates a new layer for rendering
in its window and the system currently has a limit of ten layers per
window.  Normal windows use one layer for the window rendering,
GimmeZeroZero windows use a second layer for the border rendering.  This
leaves a maximum of eight or nine simultaneous requesters open in a window
at any given time.

If the requester is being brought up only to display an error message, the
application may want to use a less intrusive method of bringing the error
to the user's attention than a requester.  Requesters interrupt the flow
of the user's work, and force them to respond before continuing.

As an alternative to bringing up an error requester, the application could
flash the screen instead with Intuition's DisplayBeep() function.  This
allows the application to notify the user of an error that is not serious
enough to warrant a requester and to which the user does not really need
to respond.  For more information, see the description of DisplayBeep() in
the "Intuition Screens" chapter.


7 / True Requesters / Rendering Requesters

The application may choose to use Intuition's rendering facilities to
display the requester, or it may define its own custom bitmap.  The
Requester structure is initialized differently according to the rendering
method chosen.

To use Intuition's rendering facilities, you supply a list of one or more
display objects with the Requester structure and submit the Requester  to
Intuition, allowing it to draw the objects.  These objects can include
independent lists of Borders, IntuiText, Images and Gadgets.  Note that
the abilty to provide a list of Image structures is new in V36, and the
USEREQIMAGE flag must be set for them to be rendered.  For more about
Intuition rendering see the chapter on
"Intuition Images, Line Drawing and Text".

The gadgets in a requester also have their own borders, images and text to
add to the display imagery.  Intuition will allocate the buffers,
construct a bitmap that lasts for the duration of the display, and render
the requester into the window.  This rendering is all done over a solid
color, filled background specified by the BackFill pen in the Requester
structure.  The backfill may be disabled by setting the NOREQBACKFILL flag
(this also a new feature of V36).

On the other hand, a custom requester may be designed with pre-defined,
bitmap imagery for the entire object.  The image bitmap is submitted to
Intuition through the ImageBMap field of the Requester structure.  The
bitmap should be designed to reduce user confusion; gadgets should line up
with their images, and the designer should attempt to use glyphs (symbols)
familiar to the user.

To provide imagery for the requester, applications should always try to
use data structures attached to the Requester structure as described
above.  Although, rendering directly into the requester layer's RastPort
is tolerated, it must be done with great care.

First, a requester is allowed to have gadgets that automatically close the
requester when they are selected (GACT_ENDGADGET).  If such a gadget is
selected, the requester, its layer, and its layer's RastPort will be
deleted asynchronously to your application.  If your application is trying
to render directly into the requester at that time, the results are
unpredictable.  Therefore, do not put GACT_ENDGADGET gadgets into a
requester if you plan on rendering directly into its RastPort.

Second, recall that requesters are clipped to the inside of the window
(not including the borders).  If the window can be sized smaller such that
the requester would be entirely clipped, the requester's layer may be
deleted by Intuition.  If your window's minimum size and the requester
size and position are such that the requester can be completely clipped,
then reading Requester.ReqLayer is unsafe without additional protection.
It would be correct to LockLayerInfo() the screen's Layer_Info, then check
for the existence of the requester's ReqLayer, then render, then unlock.

For reasons such as these, direct rendering is discouraged.


7 / True Requesters / Requester Refresh Type

A requester appears in a Layer.  By default, the requester layer is of
type LAYERSMART, or, in window terminology, WFLG_SMART_REFRESH; so
rendering is preserved in the requester when the window is moved or
revealed.

Requesters may also be simple refresh.  This is the recommended type.  If
possible, make the requester a simple refresh layer requester by
specifying the SIMPLEREQ flag.

For all refresh types, Intuition will keep the gadget, border, image and
bitmap imagery properly refreshed.


7 / True Requesters / Requester Display Position

The location of true requesters may be specified in one of three ways.
The requester may either be a constant location, which is an offset from
the top left corner of the window; a location relative to the current
location of the pointer; or a location relative to the center of the
window.

To display the requester as an offset from the upper left corner of the
window, initialize the TopEdge and LeftEdge variables and clear the
POINTREL flag.  This will create a requester with a fixed position
relative to the upper left corner for both normal requesters and
double menu requesters.

Displaying the requester relative to the pointer can get the user's
attention immediately and closely associates the requester with whatever
the user was doing just before the requester was displayed in the window.
However, only double menu requesters may be positioned relative to the
pointer position.  See below for more information on double menu
requesters.

Requesters that are not double menu requesters may be positioned relative
to the center of the window on systems running Release 2 or a later
version of the OS.  This is done by setting the POINTREL flag and filling
in the relative top and left of the gadget.  Setting RelTop and RelLeft to
zero will center the requester in the window.  Positive values of RelTop
and RelLeft will move the requester down and to the right, negative values
will move it up and to the left.


7 / True Requesters / Gadgets in Requesters

Each requester gadget must have the GTYP_REQGADGET flag set in the
GadgetType field of its Gadget structure.  This informs Intuition that
this gadget is to be rendered in a requester rather than a window.

Requesters can have gadgets in them that automatically satisfy the request
and end the requester.  When one of these gadgets is selected, Intuition
will remove the requester from the window.  This is equivalent to the
application calling EndRequest(), and, if the request is terminated by
selection of such a gadget, the application should not call EndRequest()
for that requester.

Set the GACT_ENDGADGET flag in the Activation field of the Gadget
structure to create a gadget that automatically terminates the requester.
Every time one of the requester's gadgets is selected, Intuition examines
the GACT_ENDGADGET flag.  If GACT_ENDGADGET is set, the requester is
removed from the display and unlinked from the window's active requester
list.

Requesters rendered via Intuition and those that use a custom bitmap
differ in how their gadgets are rendered.  For requesters rendered via
Intuition, the application supplies a regular gadget list just as it would
for application gadgets in a window.

In custom bitmap requesters, however, any gadget imagery is part of the
bitmap supplied for the requester.  Therefore the list of gadgets supplied
for custom bitmap requesters should not provide gadget imagery but rather
it should define only the select boxes, highlighting, and gadget types for
the gadgets.

The Gadget structures used with a custom bitmap requester should have
their GadgetRender, SelectRender and GadgetText fields set to NULL as
these will be ignored.  Other gadget information--select box dimensions,
highlighting, and gadget type--is still relevant.  The select box
information is especially important since the select box must have a well
defined correspondence with the custom bitmap imagery supplied.  The basic
idea is to make sure that the user understands the requester imagery and
gadgets.


7 / True Requesters / Using a Requester to Block Window Input

There may be times when an application needs to block user input without a
visible requester.  In some cases, the application needs to be busy for a
while.  Other times, an application wants the blocking properties of a
requester, but prefers to use a window instead of a true requester.  In
this case, the application can create a requester with no imagery,
attaching it to the parent window to block input.  A new window may then
be opened to act as the requester.

Some of the advantages of using a window as a requester instead of a real
requester include:

  * A window can be resized, and moves independently of the parent window.

  * It is legal to render directly into a window.

  * The window can have its own menus since only the parent window's
    menus are disabled (this is only occasionally useful).

  * Certain code or a library you are using may not work in requesters
    (GadTools library is an example of this).

Of course, using a true requester instead of a window has the advantage
that the requester automatically moves and depth-arranges along with the
parent window.

 A Requester Example


7 / True Requesters / Double Menu Requesters

A double menu requester is exactly like other requesters with one
exception: it is displayed only when the user double clicks the mouse menu
button.  Double menu requesters block input in exactly the same manner as
other true requesters.  A double menu requester is attached to a window by
calling SetDMRequest().

    BOOL SetDMRequest( struct Window *window,
                       struct Requester *requester );

This call does not display the requester, it simply prepares it for
display.  The requester will be brought up when the user double clicks the
mouse menu button.  The parent window will receive IDCMP_REQSET and
IDCMP_REQCLEAR messages when the requester is added and removed.

To prevent the user from bringing up a double menu requester, unlink it
from the window by calling ClearDMRequest().  If a double menu request is
set for a window, ClearDMRequest() should be called to remove the
requester before that window is closed.

    BOOL ClearDMRequest( struct Window *window );

This function unlinks the requester from the window and disables the
ability of the user to bring it up.  ClearDMRequest() will fail if the
double menu request is currently being displayed.

Double menu requesters can be positioned relative to the current mouse
pointer position.  For a mouse relative requester, specify POINTREL in the
Flags field and initialize the RelLeft and RelTop variables.  RelLeft and
RelTop describe the offset of the upper, left corner of the requester from
the pointer position at the time the requester is displayed.  These values
can be either negative or positive.

The values of RelLeft and RelTop are only advisory; the actual position
will be restricted such that the requester is entirely contained within
the borders of its parent window, if possible.  The actual top and left
positions are stored in the TopEdge and LeftEdge variables.

Positioning relative to the mouse pointer is possible only with double
menu requesters.  Setting POINTREL in a requester which is not a double
menu requester will position the requester relative to the center of the
window.


7 / True Requesters / IDCMP Requester Features

Intuition can notify your application about user activity in the requester
by sending a message to the parent window's IDCMP port (Window.UserPort).
When using the IDCMP for input, the following IDCMP flags control how
requester input events will be handled.

IDCMP_REQSET
    With this flag set, the program will receive a message whenever a
    requester opens in its window.  The application will receive one
    IDCMP_REQSET event for each requester opened in the window.

IDCMP_REQCLEAR
    With this flag set, the program will receive a message whenever a
    requester is cleared from its window.  The application will receive
    one IDCMP_REQCLEAR event for each requester closed in the window.  By
    counting the number of IDCMP_REQSET and IDCMP_REQCLEAR events, the
    application may determine how many requesters are currently open in a
    window.

IDCMP_REQVERIFY
    With this flag set, the application can ensure that it is ready to
    allow a requester to appear in the window before the requester is
    displayed.

    When the program receives an IDCMP_REQVERIFY message, it must reply
    to that message before the requester is added to the window.  If
    multiple requesters are opened in the window at the same time, only
    the first one will cause an IDCMP_REQVERIFY event.  It is assumed
    that once a requester is in a window others may be added without the
    program's consent.  After the requester count drops to zero and there
    are no open requesters in the window, the next requester to open will
    cause another IDCMP_REQVERIFY event.

    IDCMP_REQVERIFY is ignored by the Request() function.  Since
    Request() is controlled by the application, it is assumed that the
    program is prepared to handle the request when calling this function.
    Since the system does not render true requesters into an
    application's window (EasyRequest() and AutoRequest() come up in
    their own window, not in the application's window), IDCMP_REQVERIFY
    will only control the timing of double menu requesters.

These flags are set when the parent window is first opened by using either
the WA_IDCMP tag or NewWindow.IDCMPFlags.  They can also be set after the
parent window is open by using the ModifyIDCMP() call.  See the chapter
entitled "Intuition Input and Output Methods," for further information
about these IDCMP flags.  See the "Intuition Windows" chapter for details
on setting IDCMP flags when a window is opened.


7 Intuition Requesters and Alerts / Requester Structure

Unused fields in the Requester structure should be initialized to NULL or
zero before using the structure.  For global data that is pre-initialized,
be sure to set all unused fields to zero.  For dynamically allocated
structures, allocate the storage with the MEMF_CLEAR flag, or call the
InitRequester() function to clear the structure.

    Requesters are Initialized According to Their Type.
    ---------------------------------------------------
    See "Rendering Requesters" and "Gadgets in Requesters" above for
    information about how the initialization of the structure differs
    according to how the requester is rendered.

The specification for a Requester structure, defined in
<intuition/intuition.h>, is as follows.

    struct Requester
        {
        struct Requester *OlderRequest;
        WORD LeftEdge, TopEdge;
        WORD Width, Height;
        WORD RelLeft, RelTop;
        struct Gadget *ReqGadget;
        struct Border *ReqBorder;
        struct IntuiText *ReqText;
        UWORD Flags;
        UBYTE BackFill;
        struct Layer *ReqLayer;
        UBYTE ReqPad1[32];
        struct BitMap *ImageBMap;
        struct Window *RWindow;
        struct Image  *ReqImage;
        UBYTE ReqPad2[32];
        };

Here are the meanings of the fields in the Requester structure:

OlderRequest
    For system use, initialize to NULL.

LeftEdge, TopEdge
    The location of the requester relative to the upper left corner of
    the window.  These values must be set if the POINTREL flag is not
    set.  Use RelLeft and RelTop for POINTREL requesters.

Width, Height
    These fields describe the size of the entire requester rectangle,
    containing all the text and gadgets.

RelLeft, RelTop
    These values are only used if the POINTREL flag in the requester's
    Flags field is set.

    If the requester is a double menu requester and POINTREL is set then
    these values contain the relative offset of the requester's upper
    left corner from the current pointer position.

    If the requester is not a double menu requester and POINTREL is set,
    then these values contain the relative offset of the requester's
    center from the center of the window that the requester is to be
    displayed in.  For example, using POINTREL with a requester which is
    not a double menu requester with RelLeft and RelTop of zero will
    center the requester in the window.  The requester is centered within
    the inner part of the window, that is, within the inside edge of the
    window's borders.

    If the requester is POINTREL and part of the containing box will
    appear out of the window, Intuition will adjust the requester so that
    the upper left corner is visible and as much of the remaining box as
    possible is visible.  The adjustment attempts to maintain the
    requester within the window's borders, not within the window's
    bounding box.

ReqGadget
    This field is a pointer to the first in a linked list of Gadget
    structures.  GTYP_REQGADGET must be specified in the GadgetTypes
    field of all Gadget structures that are used in a requester.  Take
    care not to specify gadgets that extend beyond the Requester
    rectangle specified by the Width and Height fields, as Intuition does
    no boundary checking.

    For requesters with custom imagery, where PREDRAWN is set, ReqGadget
    points to a valid list of gadgets, which are real gadgets in every
    way except that the gadget text and imagery information are ignored
    (and can be NULL).  The select box, highlighting, and gadget type
    data are still used.  Try to maintain a close correspondence between
    the gadgets' select boxes and the supplied imagery.

    String Gadgets and Pre-drawn Requesters.
    ----------------------------------------
    Intuition will not render string gadget text in a predrawn requester.
    The application must use other rendering means than the predrawn
    bitmap if it wishes to use string gadgets with a requester.

ReqBorder
    This field is a pointer to an optional linked list of Border
    structures for drawing lines around and within the requester.  The
    lines specified in the border may go anywhere in the requester; they
    are not confined to the perimeter of the requester.

    For requesters with custom imagery, where PREDRAWN is set, this
    variable is ignored and may be set to NULL.

ReqText
    This field is a pointer to an optional linked list of IntuiText
    structures containing text for the requester.  This is for general
    text in the requester.

    For requesters with custom imagery, where PREDRAWN is set, this
    variable is ignored and can be set to NULL.

Flags
    The following flags may be specified for the Requester:

    POINTREL
        Specify POINTREL to indicate that the requester is to appear in
        a relative rather than a fixed position.

        For double menu requesters, the position is relative to the
        pointer. Otherwise, the position of POINTREL requesters is
        relative to the center of the window.

        See the discussion of RelLeft and RelTop, above.

    PREDRAWN
        Specify PREDRAWN if a custom BitMap structure is supplied for
        the requester and ImageBMap points to the structure.

    NOISYREQ
        Normally, when a requester is active, any gadget, menu, mouse
        and keyboard events within the parent window are blocked.
        Specify the NOISYREQ requester flag to allow keyboard and mouse
        button IDCMP events to be posted, even though the requester is
        active in the parent window.

        If the NOISYREQ requester flag is set, the application will
        receive IDCMP_RAWKEY, IDCMP_VANILLAKEY and IDCMP_MOUSEBUTTONS
        events.  Note that with NOISYREQ set, IDCMP_MOUSEBUTTON events
        will also be sent when the user clicks on any of the blocked
        gadgets in the parent window.

        Although the reporting of mouse button events depends on
        NOISYREQ, mouse movement events do not.  IDCMP_MOUSEMOVE events
        are reported if the window flag WFLG_REPORTMOUSE is set in the
        parent window, or if one of the requester gadgets is down and
        has the GACT_FOLLOWMOUSE flag set.  This is true even if the
        requester is a double menu requester.

    USEREQIMAGE
        Render the linked list of images pointed to by ReqImage after
        rendering the BackFill color but before gadgets and text.

    NOREQBACKFILL
        Do not backfill the requester with the BackFill pen.

    In addition, Intuition uses these flags in the Requester:

    REQOFFWINDOW
        Set by Intuition if the requester is currently active but is
        positioned off window.

    REQACTIVE
        This flag is set or cleared by Intuition as the requester is
        posted and removed.  The active requester is indicated by the
        value of Window.FirstRequest.

    SYSREQUEST
        This flag is set by Intuition if this is a system generated
        requester. Since the system will never create a true requester
        in an application window, the application should not be
        concerned with this flag.

BackFill
    BackFill is the pen number to be used to fill the rectangle of the
    requester before any drawing takes place.  For requesters with custom
    imagery, where PREDRAWN is set, or for requesters with NOREQBACKFILL
    set, this variable is ignored.

ReqLayer
    While the requester is active, this contains the address of the Layer
    structure used in rendering the requester.

ImageBMap
    A pointer to the custom bitmap for this requester.  If this requester
    is not PREDRAWN, Intuition ignores this variable.

    When a custom bitmap is supplied, the PREDRAWN flag in the
    requester's Flags field must be set.

RWindow
    Reserved for system use.

ReqImage
    A pointer to a list of Image structures used to create imagery within
    the requester.  Intuition ignores this field if the flag USEREQIMAGE
    is not set.  This imagery is automatically redrawn by Intuition each
    time the requester needs refreshing.  The images are drawn after
    filling with the BackFill pen, but before the gadgets and text.

ReqPad1, ReqPad2
    Reserved for system use.


7 Intuition Requesters and Alerts / Easy Requesters

EasyRequest() provides a simple way to make a requester that allows the
user to select one of a limited number of choices.  (A similar function,
AutoRequest(), is also available but is not as flexible or as powerful.
See the Amiga ROM Kernel Reference Manual: Includes and Autodocs for more
information.)

     Figure 7-2: A Simple Requester Made with EasyRequest()

The program supplies the text for the body of the requester, text for each
of the possible options, an optional title for the window, and other
arguments.  The body text can consist of one or more lines with lines
separated by the linefeed character.

Each option for an easy requester is displayed as a simple button gadget
positioned beneath the body text you specify.  The layout of the
requester, its text and buttons, is done automatically and is font
sensitive.  The screen font (Screen.Font) is used for all text in the
requester.

Typically, easy requesters have one selection indicating a positive action
and one selection indicating a negative action.  The text used for the
positive action might be "OK", "Yes," "True," "Retry," or similar
responses.  Likewise, the text used for the negative action might be "No,"
"False," "Cancel," and so on.  The negative choice should always be the
rightmost or final choice and will return a zero if selected.

When EasyRequest() is called, Intuition will build the requester, display
it, and wait for user response.

    LONG EasyRequest( struct Window *window,
                      struct EasyStruct *easyStruct,
                      ULONG *idcmpPtr, APTR arg1, ... );

    LONG EasyRequestArgs( struct Window *window,
                          struct EasyStruct *easyStruct,
                          ULONG *idcmpPtr, APTR args );

The window argument is a pointer to the reference window.  The requester
will be displayed on the same screen that the reference window is on and
also takes its title from the reference window, if not otherwise
specified.  This argument can be NULL, which means the requester is to
appear on the Workbench screen, or the default public screen, if defined.

The easyStruct argument is a pointer to an EasyStruct structure which
defines the setup and the text of this easy requester (described below).

The idcmpPtr argument is a pointer to a ULONG containing the IDCMP flags
for the event that you want to terminate this requester.  If such an event
occurs the requester is terminated (with a result of -1) and the ULONG
that idcmpPtr points to will contain the actual class of the event
message.  This feature allows external events to satisfy the request, such
as the user inserting a disk in the disk drive.  This argument can be set
to NULL for no automatic termination.

The gadget and body text for an easy requester is specified in an
EasyStruct structure (see below).  Body text can be specified using a
printf()-style format string that also accepts variables as part of the
text.  If variables are specified in the requester text, their value is
taken from the args (or arg1,...) parameters shown in the prototypes
above.  EasyRequestArgs() takes a pointer to an array of pointers to
arguments, while EasyRequest() has a varargs interface and takes
individual arguments as part of the function call.  The types of these
arguments are specified in the format strings of the EasyStruct structure.
Arguments for es_GadgetFormat follow arguments for es_TextFormat.

The EasyRequest() functions return an integer from 0 to n - 1, where n is
the number of choices specified for the requester.  The numbering from
left-to-right is:  1, 2, ..., n - 1, 0.  This is for compatibility with
AutoRequest() which returns FALSE for the rightmost gadget.

The function will return -1 if it receives an IDCMP event that matches one
of the termination events specified in the idcmpPtr argument.

    Turn Off the Verify Messages.
    -----------------------------
    Use ModifyIDCMP() to turn off all verify messages (such as
    MENUVERIFY) before calling EasyRequest() or AutoRequest(). Neglecting
    to do so can cause situations where Intuition is waiting for the
    return of a message that the application program cannot receive
    because its input is shut off while the requester is up.  If
    Intuition finds itself in a deadlock state, the verify function will
    timeout and will be automatically replied.

 The Easystruct Structure    Low Level Access to Easy Requesters


7 / Easy Requesters / The EasyStruct Structure

The text and setup of an easy requester is specified in an EasyStruct
structure, defined in <intuition/intuition.h>.

    struct EasyStruct
        {
        ULONG       es_StructSize;
        ULONG       es_Flags;
        UBYTE       *es_Title;
        UBYTE       *es_TextFormat;
        UBYTE       *es_GadgetFormat;
        };

es_StructSize
    Contains the size of the EasyStruct structure, sizeof(struct
    EasyStruct).

es_Flags
    Set to zero.

es_Title
    Title of easy requester window.  If this is NULL, the title will be
    taken to be the same as the title of the reference window, if one is
    specified in the EasyRequest() call, else the title will be "System
    Request".

es_TextFormat
    Format string for the text in the requester body, with printf()-style
    variable substitution as described in the Exec library function
    RawDoFmt().  Multiple lines are separated by the linefeed character
    (hex 0x0a or `\n' in C).  Formatting `%' functions are supported
    exactly as in RawDoFmt().  The variables that get substituted in the
    format string come from the last argument passed to EasyRequest()
    (see prototype above).

es_GadgetFormat
    Format string for gadgets, where the text for separate gadgets is
    separated by `|' (vertical bar).  As with the body text,
    printf()-style formatting with variable substitution is supported,
    but multi-line text in the gadgets is not supported.  At least one
    gadget must be specified.

Requesters generated with EasyRequest() and BuildEasyRequest() (including
system requesters, which use SysReqHandler() to handle input) can be
satisfied by the user via the keyboard.  The key strokes left Amiga V and
left Amiga B correspond to selecting the requester's leftmost or rightmost
gadgets with the mouse, respectively.

An easy request must have at least one choice.  Multiple choices are
specified through the "|" (vertical bar) separator character in the
es_GadgetFormat string.  The buttons are displayed evenly spaced, from
left-to-right in the order in which they appear in the string.

The requesters generated by EasyRequest() appear in the visible portion of
the specified screen.  They do not cause the screen to scroll.  Under the
current implementation, the window for an easy requester will appear in
the upper left corner of the display clip for the specified screen.

When a request is posted using EasyRequest() or BuildEasyRequest(), it
will move the screen it appears on to the front, if that screen is not
already the frontmost.  This brings the request to the attention of the
user.  The request also comes up as the active window and could
potentially steal the input focus from the current window.

When the request is satisfied the screen will be moved to back if the
request caused the screen to move to the front when it was displayed.
Note that the final screen position may not be the same as the original
screen position.

 Example Using EasyRequest()


7 / Easy Requesters / Low Level Access to Easy Requesters

The EasyRequest() function calls a lower level Intuition function named
BuildEasyRequest() to construct the requester.  An application can call
BuildEasyRequest() directly if it needs to use an easy requester but
requires custom handling of the events sent to the requester.  Handling of
the events should be done using the SysReqHandler() function as described
below.

The BuildEasyRequest() functions take the same arguments as EasyRequest():

    struct Window *BuildEasyRequestArgs( struct Window *window,
                                         struct EasyStruct *easyStruct,
                                         unsigned long idcmp, APTR args );

    struct Window *BuildEasyRequest( struct Window *window,
                                     struct EasyStruct *easyStruct,
                                     unsigned long idcmp, APTR arg1, ... );

To process input event information directly while an easy requester is
displayed, first call BuildEasyRequest() then call SysReqHandler()
periodically to process user input.

    LONG SysReqHandler( struct Window *window, ULONG *idcmpPtr,
                        long waitInput );

This will provide standard handling of events but allow the application to
control the timing of checking the events.  This handling includes checks
for left Amiga keys.

The FreeSysRequest() function must be called after an application has
finished with a requester (if it was created with BuildEasyRequest() call).

    void FreeSysRequest( struct Window *window );

This function ends the requester and frees any resources allocated with
the BuildEasyRequest() call.


7 Intuition Requesters and Alerts / System Requesters

System requesters, such as DOS requests to "Insert volume foo in any
drive,"  are created by the system using EasyRequest().  Unless otherwise
specified, these requests appear on the default public screen.

System requests may appear at any time the system requires a resource that
is not available.  The user may be in the middle of an action, the program
may be in any state.

Use the function ModifyIDCMP() to turn off all verify messages before
calling any function that might generate a system requester.  Neglecting
to do so can cause situations where Intuition is waiting for the return of
a message which the application program is unable to receive because its
input is shut off while the requester is up.  If Intuition finds itself in
a deadlock state, the verify function will timeout and be automatically
replied.

 Redirecting System Requesters


7 / System Requesters / Redirecting System Requesters

A process can force the system requests which are caused by its actions to
appear on a custom screen by changing the pr_WindowPtr field of its
Process structure.  This field may be set to three values: zero, negative
one or a valid pointer to the Window structure of an open window.  If
pr_WindowPtr is set to zero, the request will appear on the default public
screen.  If pr_WindowPtr is set to negative one, the system request will
never appear and the return code will be as if the user had selected the
rightmost button (negative response).  If pr_WindowPtr is set to a valid
window pointer, then the request will appear on the same screen as the
window.

The original value of pr_WindowPtr should be cached and restored before
the window is closed.


7 Intuition Requesters and Alerts / Alerts

Alerts are for emergency messages.  They can be displayed even when the
system is in a very fragile state, such as when the system is low on
memory or when some of the system lists are corrupt.

Alerts can be displayed by either the system or an application.  They are
reserved for urgent messages and dire warnings in situations that require
the user to take some immediate action.  Alerts should only be used where
no other display type is possible.  For instance, when the system has
crashed or is about to crash, an alert could be used to inform the user of
the cause.

The sudden display of an alert is a jarring experience for the user.  The
system stops dead while the alert is displayed and waits for the user
input.  For this reason, alerts should only be used when there is no
recourse.  If possible, use requesters or windows to display warning
messages in place of alerts.

System alerts are managed entirely by Intuition.  The program does not
have to take any action to invoke or process these alerts.  Alerts do not
have access to the display database or other information required to open
in specialized display modes.  For this reason, alerts must appear in a
display mode available on all machines, namely high resolution,
non-interlaced.  Alerts do not use overscan, so the display is limited to
640 by 200 on an NTSC machine, and 640 by 256 on a PAL machine.

The alert appears at the top of the video display.  They are displayed the
full 640 pixels wide and as tall as needed, up to the limits described
above.  Alerts are always displayed on a black background.  The text of
the alert is displayed within a rectangular border.  Both the text and the
border are displayed in a single color which is determined by the type of
the alert.

The user responds to an alert by pressing one of the mouse buttons.  The
left mouse button signifies a positive response such as "Retry" or "OK".
The right mouse button signifies a negative response such as "Cancel" or
"Abort".

    Alerts Save Up User Input.
    --------------------------
    The events produced by the user during an alert are not consumed by
    the alert.  These events are passed through to the program when the
    alert returns.  There could be a great deal of input queued and
    waiting for processing by the application.

 Types of Alerts    Creating Alerts    Display Alert Example


7 / Alerts / Types of Alerts

There are two levels of severity for alerts:

RECOVERY_ALERT
    Recovery alerts are used in situations where the caller believes that
    the system can resume operations after handling the error.  The alert
    is used as a warning, and is displayed in amber.

    A recoverable alert displays the text of the alert and flashes the
    border while waiting for the user to respond.  It returns TRUE if the
    user presses the left mouse button in response to the alert,
    otherwise FALSE is returned.

DEADEND_ALERT
    Deadend alerts are used in situations where the caller believes that
    no recovery from the error is possible, and further operation of the
    system is impossible.  This alert is used to inform the user of a
    fatal problem and is displayed in red.  Deadend alerts are the same
    as recoverable alerts in every way except color.


7 / Alerts / Creating Alerts

The function DisplayAlert() creates and displays an alert message.  The
message will almost always be displayed regardless of the state of the
machine (with the exception of catastrophic hardware failures).  If the
user presses one of the mouse buttons, the display is restored to its
original state, if possible.  If a recoverable alert cannot be displayed
(because memory is low), DisplayAlert() will return FALSE, as if the user
had selected cancel.  DisplayAlert() is also used by the system to display
the Amiga system alert messages.

    BOOL DisplayAlert( unsigned long alertNumber, UBYTE *string,
                       unsigned long height );

The alertNumber argument is a LONG value, specifying whether this is a
RECOVERY_ALERT or a DEADEND_ALERT (see the <intuition/intuition.h> include
file).

The string argument points to a string that is made up of one or more
substrings.  Each substring contains the following:

  * The first component is a 16 bit x-coordinate and an 8 bit
    y-coordinate describing where to position the substring within the
    alert display.  The units are in pixels.  The y-coordinate describes
    the location of the text baseline.

  * The second component is the text itself.  The substring must be NULL
    terminated (it ends with a zero byte).

  * The last component is the continuation byte.  If this byte is zero,
    this is the last substring in the message.  If this byte is non-zero,
    there is another substring in this alert message.

The complete string must be terminated by two NULL characters; one as the
end of the last substring, and one as a NULL continuation byte, indicating
that this was the last substring. The height argument is the number of
display lines required for the alert.


7 Intuition Requesters and Alerts / Function Reference

The following are brief descriptions of the Intuition functions that
relate to the use of Intuition requesters and alerts.  See the Amiga ROM
Kernel Reference Manual: Includes and Autodocs for details on each
function call.

         Table 7-1: Functions for Intuition Requesters and Alerts
  ________________________________________________________________________
 |                                                                        |
 |          Function                   Description                        |
 |========================================================================|
 |               Request()  Open a requester in an open window.           |
 |            EndRequest()  Close an open requester in a window.          |
 |         InitRequester()  Clear a requester structure before use.       |
 |------------------------------------------------------------------------|
 |       EasyRequestArgs()  Open a system requester.                      |
 |           EasyRequest()  Alternate calling sequence for                |
 |                          EasyRequestArgs().                            |
 |  BuildEasyRequestArgs()  Low level function to open an EasyRequester.  |
 |      BuildEasyRequest()  Alternate calling sequence for                |
 |                          BuildEasyRequestArgs().                       |
 |         SysReqHandler()  Event handler function for EasyRequestArgs(). |
 |------------------------------------------------------------------------|
 |           AutoRequest()  Open a pre-V36 system requester.              |
 |       BuildSysRequest()  Low level function to open an AutoRequest().  |
 |        FreeSysRequest()  Low level function to close an AutoRequest(). |
 |------------------------------------------------------------------------|
 |          SetDMRequest()  Set a double menu requester for an open       |
 |                          window.                                       |
 |        ClearDMRequest()  Clear a double menu requester from an open    |
 |                          window.                                       |
 |------------------------------------------------------------------------|
 |          DisplayAlert()  Open an alert on the screen.                  |
 |________________________________________________________________________|


Amiga® RKM Libraries: 8 Intuition Images, Line Drawing and Text

Intuition supports two general approaches to creating images, lines, and
text in displays:  through Intuition library calls and through graphics
library calls.

This chapter explains the use of Intuition structures and functions for
creating display imagery.  The Intuition graphical functions provide a
high level interface to the graphics library, giving the application quick
and easy rendering capabilities.  As with any high level calls, some power
and flexibility is sacrificed in order to provide a simple interface.

For more flexibility and control over the graphics, the application can
directly call functions in the graphics library as discussed in the
"Graphics Primitives" chapter.  Intuition also has additional features for
defining custom graphic objects.  See the "BOOPSI" chapter for more
information on these objects.

 Intuition Graphic Objects    Creating Borders    Function Reference
 Creating Images              Creating Text


8 Intuition Images, Line Drawing and Text / Intuition Graphic Objects

Intuition graphic objects are easy to create and economical to use.  There
are just three basic types of graphic objects you can use yet these three
types cover most rendering needs:

Image
    Images are graphic objects that can contain any imagery.  They
    consist of a rectangular bitmap that can be any size and describes
    each individual pixel to be displayed.

Border
    Borders are connected lines of any length and number, drawn between
    an arbitrary series of points.  They consist of a series of two
    dimensional coordinates that describe the points between which lines
    will be drawn.

IntuiText
    IntuiText strings are text strings of any length drawn in any font.
    They consist of a text string and font specification that describes
    the text to be rendered.

Each of these three objects may be chained together with other members of
the same type.  For instance, many lines of text may be rendered as a
single object by linking many instances of IntuiText objects together.
Only objects of the same type may be linked.

Any of these types can be rendered into any of the Intuition display
elements (window, requester, menu, etc.).  In fact, the application can
often display the same structure in more than one position or more than
one of the elements at the same time.

 Displaying Images, Borders and IntuiText
 Positioning Graphic Objects


8 / Graphic Objects / Displaying Images, Borders and IntuiText

Images, Borders and IntuiText objects may be directly or indirectly
rendered into the display by the application.  The application can draw
these objects directly into windows or screens by using one of the
functions DrawImage(), DrawBorder() or PrintIText().  The application
supplies the appropriate pointer to a Border, Image or IntuiText structure
as an argument to the function, as well as position information and a
pointer to the correct RastPort.  These rendering functions are discussed
in more detail below.

The application can also draw these objects indirectly by attaching them
to a menu, gadget or requester.  As Intuition places these elements on the
display, it also renders the associated graphics.  The Requester, Gadget,
and MenuItem structures contain one or more fields reserved for rendering
information.  See the specific chapters on these items for information on
attaching graphical objects to them.


8 / Intuition Graphic Objects / Positioning Graphic Objects

The position of these objects is specified as the sum of two independent
components: an external component which gives the position of a base
reference point for the list of objects, and an internal component which
gives the relative offset of a specific object to the base reference point.

The external component is used to position the object list within the
display element.  For objects drawn indirectly by attaching them to a
menu, gadget or requester, this is always a point within the menu, gadget
or requester (the top left corner).

For objects drawn directly with the DrawImage(), DrawBorder() or
PrintIText() functions, specific x and y coordinates are provided as
arguments that specify an offset within the screen's or window's RastPort
at which to display the list of objects.

Each object also has an internal, relative component that is added to the
external component described above to determine the final position of the
object.  This allows the application to reuse a graphical object and have
it appear relative to each object to which it is attached.  For example,
if the application has numerous gadgets of the same size, it can use a
single Border structure to draw lines around all the gadgets.  When the
gadgets are drawn, the base position of the lines will be taken from each
specific gadget in turn.


8 Intuition Images, Line Drawing and Text / Creating Images

With an Image structure an application can create graphic objects quickly
and easily and display them almost anywhere.  Images have an additional
attribute that makes them even more economical--by changing two simple
data elements in the Image structure, the color of the image may be
changed.

Images are rectangular bitmaps which individually define the color of each
pixel represented.  Images may not be masked to allow part of the
background to show through.  The entire rectangular image is drawn into
the target element, overwriting any data it may overlap.  All bitplanes
defined in the target RastPort within the image's rectangle are
overwritten either with image data, ones or zeros.

Images may be directly drawn by the application by using the DrawImage()
function, described below.  The image may be rendered into any screen or
window RastPort with this function.  (DrawImageState() can also be used to
draw the image.

The visual imagery for an Image can be removed from the display by calling
EraseImage().  For a normal Image structure, this will call the graphics
function EraseRect(), which clears the Image rectangle by using the
layer's backfill pen to overwrite it.

Alternately, images can be used indirectly by attaching them to menus,
gadgets or requesters when they are initialized.  For instance, in menus
the MenuItem structure has the ItemFill and SelectFill fields.  If the
ITEMTEXT flag is cleared and the HIGHIMAGE flag is set, the application
may place a pointer to a list of Image structures in each of these fields.
The system will display the ItemFill images when the menu item is not
selected and the SelectFill images when the menu item is selected.  The
application does not have to take any specific action to display these
images.  Once the menus have been added to a window, their management and
display is under Intuition control.

The number of bitplanes in an image does not have to match the number of
bitplanes in the display element in which the image is rendered.  This
provides great flexibility in using Image structures, as the same image
may be reused in many places.

If the application's window is on the Workbench or some other public
screen, it must use caution with hard-coded or constant image data, as the
color palette of that screen is subject to change.  If the application has
its own custom screen, and it is appropriate for the colors of that screen
to change, the same situation arises.  Starting with V36, Intuition allows
the screen opener to provide a mapping of pen number and rendering
functions.  For example, pens are specified for the bright and dark edges
of three dimensional objects.  Applications can obtain this mapping from
the DrawInfo structure.  See the "Intuition Screens" chapter for more
information on DrawInfo and the new 3D look of Intuition in Release 2.

A suitably designed image may be drawn into a screen or window of any
depth.  To accomplish this, the application must ensure that detail is not
lost when the image is displayed in a single bitplane RastPort, where only
the first bitplane of image data will be displayed.  This is important if
the image will ever be displayed on the Workbench screen or any other
public screen.

 Image Structure               Picking Bitplanes for Image Display
 Directly Drawing the Image    Image Example
 Image Data


8 / Creating Images / Image Structure

For images, the application must create one or more instances of the Image
structure.

    struct Image
        {
        WORD LeftEdge;
        WORD TopEdge;
        WORD Width;
        WORD Height;
        WORD Depth;
        UWORD *ImageData;
        UBYTE PlanePick, PlaneOnOff;
        struct Image *NextImage;
        };

The meanings of the fields in the Image structure are:

LeftEdge, TopEdge
    The location of the image relative to its base position when it is
    drawn.  These offsets are added to the base position to determine the
    final location of the image data.

    The base position for images rendered with DrawImage() is taken from
    arguments passed in the function call.  For gadgets and menus, the
    base position is always the upper, left corner of the select box.
    For requesters the base position is always the upper, left corner of
    the requester.

    Negative values of LeftEdge and TopEdge move the position up and to
    the left of the base position.  Positive values move down and to the
    right.

Width, Height
    The width and height of the image.  Width contains the actual width
    of the image in pixels.  Height specifies the height of the image in
    pixels.

    The Width field of the Image structure contains the actual width in
    pixels of the widest part of the image, not how many pixels are
    contained in the words that define the image.

Depth
    The depth of the image, or the number of bitplanes used to define it.
    This is not the depth of the screen or window in which the image will
    be displayed, it is the actual number of bitplanes that are defined
    in the ImageData.

ImageData
    This is a pointer to the bits that define the image and determine the
    colors of each pixel.  Image data must be placed in Chip memory.  The
    data is organized as an array of 16 bit words whose size can be
    computed as follows:

        WordWidth = ((Width + 16) / 16);
        NumImageWords = WordWidth * Height * Depth;

    The width of the image is rounded up to the nearest word (16 bits)
    and extra trailing bits are ignored.  Each line of each bitplane must
    have enough words to contain the image width, with extra bits at the
    end of each line set to zero.  For example, an image 7 bits wide
    requires one word for each line in the bitplane, whereas an image 17
    bits wide requires two words for each line in the bitplane.

PlanePick
    PlanePick tells which planes of the target BitMap are to receive
    planes of image data.  This field is a bit-wise representation of
    bitplane numbers.  For each bit set in PlanePick, there should be a
    corresponding bitplane in the image data.

PlaneOnOff
    PlaneOnOff tells whether to set or clear bits in the planes in the
    target BitMap that receive no image data.  This field is a bit-wise
    representation of bitplane numbers.

NextImage
    This field is a pointer to another instance of an Image structure.
    Set this field to NULL if this is the last Image structure in the
    linked list.


8 / Creating Images / Directly Drawing the Image

As noted above, you use the DrawImage() call to directly draw an image
into a screen or window RastPort.

    void DrawImage( struct RastPort *rp, struct Image *image,
                    long leftOffset, long topOffset );

The rp argument is a pointer to the RastPort into which the image should
be drawn.  This RastPort may come from a Window or Screen structure.

The image argument is a pointer to the list of Image structures that are
to be rendered.  The list may contain a single Image structure.

The leftOffset and topOffset arguments are the external component, or the
base position, for this list of images.  The LeftEdge and TopEdge values
of each Image structure are added to these values to determine the final
position of each image.

Images may also be indirectly drawn by attaching them to gadgets, menus or
requesters when they are initialized.


8 / Creating Images / Image Data

Image data must be in Chip memory.  The Image structure itself may be in
any memory, but the actual data referenced by ImageData field must be in
Chip memory.  This may be done by using compiler specific options, such as
the __chip keyword of SAS/C, or by allocating memory with the MEMF_CHIP
attribute and copying the image data to that memory.

 Defining Image Data


8 / / Image Data / Defining Image Data

Image data consists of binary data organized into a series of 16-bit
words.  The words must be sequential, where each successive word
represents bits that are displayed later in the image.  The image is
defined as follows:

  * The image is broken down into bitplanes.  Each bitplane is considered
    separately.

  * Within a single bitplane, each row of pixels is taken separately.
    First, round the number of pixels up to the next even multiple of 16.
    This determines the number of words used to represent a single row of
    data.  For instance, an image that is 17 bits wide will require two
    16-bit words to represent each row.

    The leftmost 16 pixel values are placed in the first word, followed
    by the next 16 pixel values, and so on.  Any extra pixels at the end
    of the last word of the ImageData should be set to zero.

  * The first row of data is the topmost row of the low order bitplane.
    This is immediately followed by the second row, then the third, until
    all rows in the bitplane have been represented.

  * The data for the low order bitplane is followed immediately by the
    next to lowest, then the next, etc.

The color of each pixel in the image is directly related to the value in
one or more memory bits, depending upon how many bitplanes there are in
the image data and in which bitplanes of the screen or window the display
is displayed.

The color for a single pixel may be determined by combining the bits taken
from the same relative position within each of the bitplanes used to
define the image.  For each pixel, the system combines all the bits in the
same position to create a binary value that corresponds to one of the
system color registers.  This method of determining pixel color is called
color indirection, because the actual color value is not in the display
memory.  Instead, it is in color registers that are located somewhere else
in memory.

In many situations, the image and display will have different number of
bitplanes, which complicates the determination of the color value for a
given pixel.  For now, assume that the image and display have the same
number of bitplanes.  The more complex example will be covered below, in
the section "Image Example".

If an image consists of only one bitplane and is displayed in a one
bitplane display, then wherever there is a 0 bit in the image data, the
color in color register zero is displayed and wherever there is a 1 bit,
the color in color register one is displayed.

In an image composed of two bitplanes, the color of each pixel is obtained
from a binary number formed by the values in two bits, one from the first
bitplane and one from the second bitplane.  If the bit in the first
bitplane is a 1 and the bit in the second bitplane is a 0, then the color
of that pixel will be taken from color register two (since 10 in binary is
two in decimal).  Again, the first bitplane describes all of the low order
bits for each pixel.  The second bitplane describes the next higher bit,
and so on.  This can be extended to any number of bitplanes.

               Image Data           Hexadecimal Representation

    ************************········    F F F F    F F 0 0
    **····················**········    C 0 0 0    0 3 0 0
    **····················**········    C 0 0 0    0 3 0 0
    **····················**········    C 0 0 0    0 3 0 0
    **····················**········    C 0 0 0    0 3 0 0
    **····················**········    C 0 0 0    0 3 0 0
    **····················**········    C 0 0 0    0 3 0 0
    **····················**········    C 0 0 0    0 3 0 0
    **····················**········    C 0 0 0    0 3 0 0
    ************************········    F F F F    F F 0 0

     Figure 8-1: Rendering of the Following Example Image

     simpleimage.c


8 / Creating Images / Picking Bitplanes for Image Display

A single image may be displayed in different colors without changing the
underlying image data.  This is done by selecting which of the target
bitplanes are to receive the image data, and what to do with the target
bitplanes that do not receive any image data.

PlanePick and PlaneOnOff are used to control the bitplane rendering of the
image.  The bits in each of these variables have a direct correspondence
to the bitplanes of the target bitmap.  The lowest bit position
corresponds to the lowest numbered bitplane, the next highest bit position
corresponds to the next bitplane, etc.

For example, for a window or screen with three bitplanes (consisting of
planes 0, 1, and 2), all the possible values for PlanePick or PlaneOnOff
and the planes picked are as follows:

                 __________________________________
                |                                  |
                | PlanePick or                     |
                |  PlaneOnOff   Planes Picked      |
                | ------------  -------------      |
                |     000       No planes          |
                |     001       Plane 0            |
                |     010       Plane 1            |
                |     011       Planes 0 and 1     |
                |     100       Plane 2            |
                |     101       Planes 0 and 2     |
                |     110       Planes 1 and 2     |
                |     111       Planes 0, 1, and 2 |
                |__________________________________|

PlanePick picks the bitplanes of the containing RastPort that will receive
the bitplanes of the image.  For each plane that is picked to receive
data, the next successive plane of image data is drawn there.  For
example, if an image with two bitplanes is drawn into a window with four
bitplanes with a PlanePick of binary 1010, the first bitplane of the image
will be drawn into the second bitplane of the window and the second
bitplane of the image will be drawn into the fourth bitplane of the
window.  Do not set more bits in PlanePick than there are bitplanes in the
image data.

PlaneOnOff specifies what to do with the bitplanes that are not picked to
receive image data.  If the PlaneOnOff bit is zero, then the associated
bitplane will be filled with zeros.  If the PlaneOnOff bit is one, then
the associated bitplane will be filled with ones.  Of course, only bits
that fall within the rectangle defined by the image are affected by this
manipulation.

Only the bits not set in PlanePick are used in PlaneOnOff, that is,
PlaneOnOff only applies to those bitplanes not picked to receive image
data.  For example, if PlanePick is 1010 and PlaneOnOff is 1100, then
PlaneOnOff may be viewed as x1x0 (where the x positions are not taken into
consideration).  In this case, planes two and four would receive image
data and planes one and three would be set by PlaneOnOff.  Each bit in
plane one would be set to zero and each bit in plane three would be set to
one.

PlaneOnOff is only useful where an entire bitplane of an image may be set
to the same value.  If the bitplane is not all set to the same value, even
for just a few bits, then image data must be specified for that plane.

A simple trick to create a filled rectangle of any color may be used by
supplying no image data, where the color is controlled by PlaneOnOff.  The
Depth of such an image is set to zero, the size of the rectangle is
specified in the Width and Height fields and the ImageData pointer may be
NULL.  PlanePick should be set to zero, as there are no planes of image
data to pick.  PlaneOnOff is then set to the color register which contains
the desired color for the rectangle.


8 Intuition Images, Line Drawing and Text / Creating Borders

This data type is called a Border since it was originally used to create
border lines around display objects.  It is actually a general purpose
structure for drawing connected lines between any series of points.

A Border is easier to use than an Image structure.  Only the following
need be specified to define a border:

  * An internal position component which is used in determining the final
    position of the border.

  * A set of coordinate pairs for each vertex.

  * A color for the lines.

  * One of several drawing modes.

 Border Structure Definition     Border Colors and Drawing Modes
 Directly Drawing the Borders    Border Coordinates
 Border Example                  Linking Borders


8 / Creating Borders / Border Structure Definition

To use a border, the application must create one or more instances of the
Border structure.  Here is the specification:

    struct Border
        {
        WORD LeftEdge, TopEdge;
        UBYTE FrontPen, BackPen;
        UBYTE DrawMode;
        BYTE Count;
        WORD *XY;
        struct Border *NextBorder;
        };

Here is a brief description of the fields of the Border structure.

LeftEdge, TopEdge
    These fields are used to determine the position of the Border
    relative to its base position (the base position is the upper left
    corner for requesters, menus, or gadgets and is specified in the call
    to DrawBorder() for windows and screens).

FrontPen, BackPen
    These fields contain color registers numbers.  FrontPen is the color
    used to draw the lines.  BackPen is currently unused.

DrawMode
    Set the DrawMode field to one of the following:

    JAM1
        Use FrontPen to draw the line.

    COMPLEMENT
        Change the pixels within the lines to their complement color.

Count
    Specify the number of data points used in this border.  Each data
    point is described by two words of data in the XY array.

XY  A pointer to an array of coordinate pairs, one pair for each point.
    These coordinates are measured relative to the position of the border.

NextBorder
    This field is a pointer to another instance of a Border structure.
    Set this field to NULL if this is the last Border structure in the
    linked list.


8 / Creating Borders / Directly Drawing the Borders

Borders may be directly drawn by the application by calling the function
DrawBorder().

    void DrawBorder( struct RastPort *rp, struct Border *border,
                     long leftOffset, long topOffset );

The rp argument is a pointer to the RastPort into which the border should
be drawn.  This rastport may come from a Window or Screen structure.

The border argument is a pointer to a list of Border structures which are
to be rendered.  The list may contain a single Border structure.

The leftOffset and topOffset arguments are the external component, or base
position, for this list of Borders.  The LeftEdge and TopEdge values of
each Border structure are added to these to determine the Border position.

Borders may also be indirectly drawn by attaching them to gadgets, menus
or requesters.


8 / Creating Borders / Border Colors and Drawing Modes

Borders can select their colors from the values set in the color registers
for the screen in which they are rendered.  The available number of colors
and palette settings are screen attributes and may not be changed through
border rendering.

Two drawing modes pertain to border lines: JAM1 and COMPLEMENT.  To draw
the line in a specific color, use the JAM1 draw mode.  This mode converts
each pixel in the line to the color set in the FrontPen field.

Selecting the COMPLEMENT draw mode causes the line to be drawn in an
exclusive-or mode that inverts the color of each pixel within the line.
The data bits of the pixel are changed to their binary complement.  This
complement is formed by reversing all bits in the binary representation of
the color register number.  In a three bitplane display, for example,
color 6 is 110 in binary. In COMPLEMENT draw mode, if a pixel is color 6,
it will be changed to the 001 (binary), which is color 1.  Note that a
border drawn in COMPLEMENT mode can be removed from a static display by
drawing the border again in the same position.


8 / Creating Borders / Border Coordinates

Intuition draws lines between points that are specified as sets of X, Y
coordinates.  Border data does not have to be in Chip memory.

The XY field contains a pointer to an array of coordinate pairs.  All of
these coordinates are offsets relative to the Border position, which is
determined by the sum of the external and internal position components as
described above.  The coordinate pairs are ordered sequentially.  The
first two numbers make up the first coordinate pair, the next two numbers
make up the second pair, and so on.  Within a coordinate pair, the first
number is the X offset and the second number is the Y offset.

The first coordinate pair describes the starting point of the first line.
When the Border is rendered, a line is drawn between each pair of points.
The first line is drawn from point one to point two, the second line is
drawn from point two to point three, and so on, until the final point is
reached.

The numbers specified in the XY array may be positive or negative.
Negative values move up and to the left relative to the Border position,
positive values move down and to the right. Again, the Border position is
determined by adding the external position component and the internal
position component.  For example, a Border attached to a Gadget has an
external component equal to the upper left corner of the gadget's select
box.  The internal component is set within the Border structure itself.
These two components are added together and offsets from the resulting
position, specified within the XY array, determine where the lines of the
Border will appear.

Suppose the top left corner of the select box of the gadget is at window
position (10,5).  If the Border has LeftEdge set to 10 and TopEdge set to
10, then the Border is positioned at (10+10,5+10), that is (20,15).  All
XY coordinates will be relative to this Border position.  If the XY array
contains `0,5, 15,5, 15,0', then the relative coordinates will be (0,5),
(15,5) and (15,0).  Adding each coordinate to the Border position gives
the absolute position of the lines within the window.  This Border will
draw two lines in the window, one from (20,20) to (35,20) and the second
from (35,20) to (35,15).

          0    5   10   15   20   25   30   35   40   45   50
          |         |         |         |         |         |
       0__|____|____|____|____|____|____|____|____|____|____|
          |   Top left corner of the
          | gadget's select box (10,5)
       5 _|         * _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
          |
          |         |
      10__|                Border          Third
          |         |     Position       Coordinate
          |                (20,15)      (20+15,15+0)
      15 _|         |         *              *
          |                                  |
          |         |                        |
      20__|                   *______________*
          |         |       First          Second
          |              Coordinate      Coordinate
      25 _|         |    (20+0,15+5)    (20+15,15+5)
          |
          |         |
      30__|

             Figure 8-3: Example of Border Relative Position

To create a border that is outside the select box of a gadget, specify
negative values in the internal component or use negative values for the
initial XY values.  For example, setting LeftEdge to -1 and TopEdge to -1
moves the position of the Border one pixel above and one pixel to the left
of the gadget's select box.


8 / Creating Borders / Linking Borders

The NextBorder field can point to another instance of a Border structure.
This allows complex graphic objects to be created by linking together
Border structures, each with its own data points, color and draw mode.
This might be used, for instance, to draw a double border around a
requester or gadget where the outer border is a second Border structure,
linked to the first inner border.

Note that the borders can share data.  For instance, to create a border
with a shadow, link two borders together each of which points to the same
XY data.  Set the first border to draw in a dark pen (such as the
SHADOWPEN from the screen's DrawInfo structure) and position the border
down and to the right a few pixels by changing LeftEdge and TopEdge in the
Border structure.

The second border should be set to a bright pen (such as the SHINEPEN in
the screen's DrawInfo structure).  When the border is drawn, the first
border will draw in a dark color and then the second border will be drawn
over it in a light color.  Since they use the same data set, and the dark
border is shifted down and to the right, the border will have a three
dimensional appearance.  This technique is demonstrated in the example
listed earlier in this section.


8 Intuition Images, Line Drawing and Text / Creating Text

The IntuiText structure provides a simple way of writing text strings
within an Intuition display element.  These strings may be used in
windows, screens, menus, gadgets and requesters.  To set up an IntuiText,
you specify the following:

  * Pen colors for the text.

  * A draw mode.

  * The starting offset for the text.

  * The font used to render the text.

  * The text string to output.

 IntuiText Structure               Text Colors and Drawing Modes
 Directly Drawing the IntuiText    Fonts
 Determining Text Length           Linking Text Strings
 IntuiText Example


8 / Creating Text / IntuiText Structure

To render text using Intuition, the application must create one or more
instances of the IntuiText structure:

    struct IntuiText
        {
        UBYTE FrontPen, BackPen;
        UBYTE DrawMode;
        WORD LeftEdge;
        WORD TopEdge;
        struct TextAttr *ITextFont;
        UBYTE *IText;
        struct IntuiText *NextText;
        };

Here is a brief description of each member of the IntuiText structure:

FrontPen
    The pen number specifying the color used to draw the text.

BackPen
    The pen number specifying the color used to draw the background for
    the text, if JAM2 drawing mode is specified.

DrawMode
    This field specifies one of four drawing modes:

    JAM1
        FrontPen is used to draw the text; background color is unchanged.

    JAM2
        FrontPen is used to draw the text; background color is changed
        to the color in BackPen.

    COMPLEMENT
        The characters are drawn in the complement of the colors that
        were in the background.

    INVERSVID
        Inverses the draw modes describe above.  For instance INVERVID
        used with JAM1 means the character is untouched while the
        background is filled with the color of the FrontPen.

LeftEdge and TopEdge
    The location of the text relative to its base position when it is
    drawn.  These offsets are added to the base position to determine the
    final location of the text data.

    The base position for text rendered with PrintIText() is taken from
    arguments passed in the function call.  For gadgets and menus, the
    base position is always the upper, left corner of the select box.
    For requesters the base position is always the upper, left corner of
    the requester.

    LeftEdge gives the offset of the left edge of the character cell and
    TopEdge gives the offset of the top edge of the character cell for
    the first character in the text string.  Negative values of LeftEdge
    and TopEdge move the position up and to the left of the base
    position.  Positive values move down and to the right.

ITextFont
    A pointer to a TextAttr structure defining the font to be used. Set
    this to NULL to use the default font.

IText
    A pointer to the NULL terminated text string to be displayed.

NextText
    A pointer to another instance of IntuiText.  Set this field to NULL
    for the last IntuiText in a list.


8 / Creating Text / Directly Drawing the IntuiText

Use the PrintIText() call to directly draw the text into the target
RastPort of a window or screen.

    void PrintIText( struct RastPort *rp, struct IntuiText *iText,
                     long left, long top );

The rp argument is a pointer to the RastPort into which the text should be
drawn.  This RastPort can come from a Window or Screen structure.

The iText argument is a pointer to a list of IntuiText structures which
are to be rendered.  The list may contain a single IntuiText structure.
If the font is not specified in the IntuiText structure, Intuition will
render the text using the RastPort's font.

The left and top arguments give the external component, or base position
for this list of IntuiText structures.  The LeftEdge and TopEdge values in
each IntuiText structure are added to these to determine the final
position of the text.

IntuiText objects may also be drawn indirectly by attaching them to
gadgets, menus or requesters.


8 / Creating Text / Determining Text Length

To determine the pixel length of a given IntuiText string, call the
IntuiTextLength() function.

    LONG IntuiTextLength( struct IntuiText *iText );

Set the iText argument to point to the IntuiText structure whose length is
to be found.  This function will return the length of the iText text
string in pixels.  Note that if the ITextFont field of the given IntuiText
is set to NULL, or Intuition cannot access the specified font, then
GfxBase->DefaultFont will be used in determining the length of the text.
This may not be the same as the RastPort font with which the text would be
printed.


8 / Creating Text / Text Colors and Drawing Modes

IntuiText gets its colors from the values set in the color registers for
the screen in which they are rendered.  The available number of colors and
palette settings are screen attributes and cannot be changed through
IntuiText rendering.

Text characters in general are made up of two areas: the character image
itself and the background area surrounding the character image.  The color
used in each area is determined by the draw mode which can be set to JAM1,
JAM2 or COMPLEMENT.  The flag INVERSVID may also be specified.

JAM1 draw mode renders each character with FrontPen and leaves the
background area unaffected.  Because the background of a character is not
drawn, the pixels of the destination memory  around the character image
are not disturbed.  Graphics beneath the text will be visible in the
background area of each character cell.

JAM2 draw mode renders each character with FrontPen and renders each
character background with BackPen.  Using this mode, any graphics that
previously appeared beneath the character cells will be totally
overwritten.

COMPLEMENT draw mode renders the pixels of each character as the binary
complement of the color that is currently at the destination pixel.  The
destination is the display memory where the text is drawn.  As with JAM1,
nothing is drawn into the background.  FrontPen and BackPen are not used
in COMPLEMENT mode.  To determine the complement color, invert all the
bits in the binary representation of the color register number.  The
resulting number specifies the color register to use for that pixel.  In a
three bitplane display, for example, color 6 (110 in binary) is the
complement of color 1 (001 in binary).

The INVERSVID flag inverses the video for each of the drawing modes.  For
JAM1, nothing is drawn into the character area and the background is drawn
in FrontPen.  For JAM2, the character area is drawn in BackPen and the
background is drawn in FrontPen.  For COMPLEMENT mode, nothing is drawn
into the character area and the background is complemented.


8 / Creating Text / Fonts

The application may choose to specify the font used in rendering the
IntuiText, or it may choose to use the default font for the system.

To use the default font, set the ITextFont field to NULL.  Some care must
be taken when using the default font.  When an IntuiText object is
rendered and no font is specified, the text will be rendered in the font
set in the RastPort.

If the RastPort font is NULL, the text will be rendered using
GfxBase->DefaultFont.  Also, IntuiTextLength() always uses
GfxBase->DefaultFont when ITextFont is NULL.  The application must have
open the graphics library in order to check the default font in GfxBase.
(See the graphics library chapter for more information.)

To use a specific font for this text, place a pointer to an initialized
TextAttr structure in the ITextFont field.  Intuition will only use the
specified font if it is available through a call to the OpenFont()
routine.  To use a font from disk, the application must first open the
font using the OpenDiskFont() function.  For more information about using
fonts, see the "Graphics Library and Text" chapter in this manual.


8 / Creating Text / Linking Text Strings

The NextText field can point to another instance of an IntuiText
structure.  This allows the application to create a complex object which
has several distinct groups of characters, each with its own color, font,
location, and drawing mode.  This can be used to create multiple lines of
text, to position characters in the text very accurately and to change the
color or font of the text.  Each list of IntuiText objects may be drawn
with one call to PrintIText(), or attached to a gadget, menu or requester
as a single object.


8 Intuition Images, Line Drawing and Text / Function Reference

The following are brief descriptions of the Intuition functions that
relate to the use of graphics under Intuition. See the Amiga ROM Kernel
Reference Manual: Includes and Autodocs for details on each function call.

         Table 8-1: Functions for Intuition Drawing Capabilities
  _______________________________________________________________________
 |                                                                       |
 |           Function                Description                         |
 |=======================================================================|
 |          DrawBorder()  Draw a border into a rast port.                |
 |           DrawImage()  Draw a image into a rast port.                 |
 |          PrintIText()  Draw Intuition text into a rast port.          |
 |     IntuiTextLength()  Find the length of an IntuiText string.        |
 |-----------------------------------------------------------------------|
 |        BeginRefresh()  Begin optimized rendering after a refresh      |
 |                        event.                                         |
 |          EndRefresh()  End optimized rendering after a refresh event. |
 |-----------------------------------------------------------------------|
 |   GetScreenDrawInfo()   Get screen drawing information (V36).         |
 |  FreeScreenDrawInfo()  Free screen drawing information (V36).         |
 |_______________________________________________________________________|


Amiga® RKM Libraries: 9 Intuition Input and Output Methods

This chapter discusses the input and output (I/O) techniques used with
Intuition.  I/O facilities are also available through Exec's device
subsystems, such as the console, serial and parallel devices.  (For more
information on these see the Amiga ROM Kernel Reference Manual: Devices.)

For graphical output to the Amiga's display, programs can use Intuition's
drawing features or handle rendering directly through calls to the
graphics library.  See the three graphics library chapters in this manual
for more information on display rendering.  For more about Intuition's
drawing features see the "Intuition Images, Line Drawing and Text"
chapter.

 Overview of System I/O    Console Device I/O    IDCMP Flags
 Intuition Input           Using the IDCMP       Function Reference
 Intuition Output


9 Intuition Input and Output Methods / Overview of System I/O

This section provides a very simplified model of how Amiga I/O and
application programs interact.  The main elements of the Amiga's I/O
system are shown in the diagram below.  Input events begin when mouse
movement is detected by the gameport device or key presses are received by
the keyboard device.  These and other input events are merged into a
single stream by the input device, which then submits the stream to
Intuition for further processing.

     Figure 9-1: Amiga Input Block Diagram

The application program can receive its input from Intuition or the
Console device.  The application may choose to listen to neither, one or
both of these input sources.

     Figure 9-2: Amiga Output Block Diagram

An application's display output can go through the high level interfaces
of the console device or through the Intuition library.  Additionally,
display output may be sent directly to the graphics library.  Notice that
both the Console and Intuition call the graphics library to render to the
display.


9 Intuition Input and Output Methods / Intuition Input

The Amiga has an input device to monitor all input activity.  The input
activity nominally includes keyboard and mouse events, but which can be
extended to include other types of input signals.  When the user moves the
mouse, presses a mouse button or types on the keyboard, the input device
detects the activity from the specific device, and constructs an
InputEvent.

An InputEvent is a message describing a single event, such as the
transition of a key on the keyboard from up to down.

The input device then passes the input events down a prioritized chain of
input handlers, which are routines in memory that process the input
events.  The sequence of input events passing through this chain of input
handlers is known as the input stream.  Any handler linked into this chain
can monitor and modify the event stream.

Each input handler may block (consume) events, allow events to pass
through to the next handler in the chain or add new events to the sequence.

Other devices and programs can add input events to the input stream by
sending messages to the input device.  For instance, AmigaDOS is able to
generate an input event whenever a disk is inserted or removed.

See the "Input Device" chapter of the Amiga ROM Kernel Reference Manual:
Devices for more information on the Input device.

 Intuition as an Input Handler
 Receiving Input Events from Intuition
 IDCMP Events and the Input Focus


9 / Intuition Input / Intuition as an Input Handler

Intuition is an input handler linked into the input stream, and it
monitors and modifies events that it receives.  The input arrives at
Intuition as a single stream of events.  These events are filtered,
altered, and enhanced by Intuition, then dispatched to windows as
appropriate, or passed down to input handlers lower in the chain.  If the
active window has a console attached to it, then it can receive the input
events that are still left in the stream, which can include some events
that Intuition played a role in forming.

Many kinds of input event undergo little conversion by Intuition.  For
instance, raw keyboard events are not modified by Intuition (with the
exception of a few keystrokes that have special meaning).  Other events
may produce differing results based on Intuition's view of the system. For
example, when the mouse select button is pressed, the event may become a
gadget down-press event, a window activation event, or it may remain a
simple button press, depending on the mouse position and the arrangement
of windows and screens.  Still other events are consumed by Intuition, and
the application is not directly notified.  An example would be when the
select button is pressed over a system gadget.

Intuition is also the originator of certain kinds of events.  For example,
a window-refreshing event is generated when Intuition discovers that part
of a window is in need of redrawing.  This might have resulted indirectly
from some other input (for example, the user might have dragged a window),
but not necessarily (the refresh might have been necessitated by a program
bringing a window to the front).


9 / Intuition Input / Receiving Input Events from Intuition

There are two channels through which a window can receive events destined
for it.  The usual way is for the application to ask Intuition to send it
messages which are based on the input event that Intuition has processed.
These messages, called IntuiMessages, are standard Amiga Exec messages,
and are sent to a port called an Intuition Direct Communications Message
Port, or IDCMP.  Every window may have an IDCMP associated with it
(pointed to by Window.UserPort).

There are many classes of IntuiMessages, and the application can control
which classes of events are routed to its window's port by setting the
appropriate IDCMP flags.  When Intuition has an event to send, but the
window does not have the corresponding IDCMP flag set, the event is
generally passed along to the next input handler in the chain.  One input
handler that resides below Intuition's is the console device's handler.
If your application's window has a console attached to it, the console
device will generally convert events it receives into console code
sequences, and send those to your console. In this manner, you can hear
these events.

Because IntuiMessages and the IDCMP are the primary way in which
applications receive communication from Intuition, discussions elsewhere
in the manual frequently refer to events from Intuition as messages,
IntuiMessages, or IDCMP messages.  However, most of the information sent
as IntuiMessages is also available through the console device, though that
option is used less often.  Elsewhere in this chapter, you can learn how
getting your events through the console differs from getting them through
your IDCMP.

Whichever way an application chooses to get its messages, it is frequently
designed to be event-driven.  That is to say, after some amount of
initialization, the application will go into a state where it is waiting
for some event to happen.  This event could be an input event, or some
other kind of event.  Based on the event received, the application would
take appropriate action, and return to its waiting state.


9 / Intuition Input / IDCMP Events and the Input Focus

Although at any given time many applications may be waiting for input, in
most cases only the active application (the one with the currently active
window) will receive IDCMP messages.

Since the IDCMP messages are, in general, directed to a single window,
this window is said to have the input focus--the input from a variety of
sources is focused on this single location.

The active window is generally selected by the user, although it is
possible for applications to change the active window.  See the
"Intuition Windows" chapter for information on selecting or setting the
active window.  Be aware that changing the active window will change the
input focus.  Usually this change is performed following user action--the
user selects a window with the mouse, or activates a new application.
Changes to the input focus without user control, such as activating
another window while the user is working in an application, may confuse
the user. Perform such changes with great care.

Not all events are sent only to the active IDCMP.  Some events, such as
"disk inserted," may be useful to many programs, so Intuition translates
these events into separate messages, one for each application.


9 Intuition Input and Output Methods / Intuition Output

Visual program output, the information written to the display, is sent
through one of three channels.

  * Imagery may be sent to the graphics library primitives.  Graphics
    library includes functions for line drawing, area fill, specialized
    animation and output of text.  See the graphics library chapters
    "Graphics Primitives", "Graphics Libraries and Text" and
    "Graphics Sprites, Bobs and Animation" for more on these functions.

  * Use the Intuition library support functions for rendering text,
    graphical imagery, and line drawing.  These provide some of the same
    functions as the graphics library routines, but the Intuition
    functions perform more of the detail work for you.  See the chapter
    "Intuition Images, Line Drawing and Text" for more information on
    Intuition rendering functions.  Also see, of course, the chapters on
    screens, windows, gadgets, menus and requesters for information on
    managing the display.

  * Output character-based data via the console device. The console
    device is discussed in the next section.


9 Intuition Input and Output Methods / Console Device I/O

A program receives its input stream either directly from Intuition or via
another mechanism known as the console device.

The console device may be used both as a source for input and as a
mechanism for output.  Often, it is convenient to use only the console
device for input and output.  In particular, character-based programs can
open the console and use it for all I/O without worrying about windows,
bitmaps, or message ports.

The console device gives the program "cooked" input data, including key
code conversions to ASCII and conversions of Intuition generated events,
such as IDCMP_CLOSEWINDOW, to ANSI escape sequences.

The console device output provides features such as automatic line
wrapping and scrolling.  If an application just wants to output text, it
may choose to use the console device, which provides formatted text with
little fuss.

If the application is not character-based, it may be better for the it to
use an IDCMP for input and render graphics and text directly through
Intuition and the graphics library primitives.

If necessary, it is possible to open both the console device and an IDCMP
for input.  Such a program might need ASCII input, formatted output and
the IDCMP verification functions (for example, to verify that it has
finished writing to the window before the user can bring up a requester).

For more information on the console device, see the "Console Device"
chapter of the Amiga ROM Kernel Reference Manual: Devices.


9 Intuition Input and Output Methods / Using the IDCMP

The IDCMP allow the application to receive information directly from
Intuition.  The program can use the IDCMP to learn about mouse, keyboard
and other Intuition events.  Also, certain useful Intuition features, most
notably the verification functions (described under "IDCMP Flags" below),
require that the IDCMP be opened, as this is the only mechanism available
for accessing these features.

The IDCMP consists of a pair of message ports, which may be allocated and
initialized by Intuition at the request of the program.  Alternately, the
application may choose to manage part of the allocation, such that one
port is supplied by the application and one port is supplied by Intuition.
These ports are standard Exec message ports, used to allow interprocess
communications in the Amiga multitasking environment.  To learn more about
message ports and message passing, see the "Exec Messages and Ports"
chapter.

The IDCMP is always associated with a window, it is not possible to have
an IDCMP without an open window.  The IDCMP is made up of several fields
in the Window structure:

  * IDCMPFlags stores the IDCMP flags currently set for this port. This
    field should never be directly set by the application; use the
    function ModifyIDCMP() or set them when the window is opened instead.

  * UserPort is a pointer to the standard Exec message port where the
    application receives input event messages from Intuition

  * WindowPort is a pointer to the reply message port used by Intuition.
    The messages sent by Intuition are set up such that ReplyMsg() will
    return them to this port.

To open these ports automatically, set at least one of the IDCMP flags in
the OpenWindowTagList() call.  To free these ports later in the program,
call the function ModifyIDCMP() with NULL for the IDCMP flags or simply
close the window.

    Don't Reply Any Messages After the IDCMP is Freed.
    --------------------------------------------------
    If an IDCMP is freed, either by calling ModifyIDCMP() or by
    closing the window, Intuition will reclaim and deallocate all
    messages waiting at that port without waiting for a ReplyMsg().
    If the program attempts to ReplyMsg() to an IntuiMessages after
    the IDCMP is closed, the system will probably crash.

If the IDCMP flags are NULL when the window is opened, no ports will be
allocated when the window is created.  To have Intuition allocate these
ports later, call the function ModifyIDCMP() with any of the IDCMP flags
set.  (Starting in V37, ModifyIDCMP() returns NULL if it was unable to
create the necessary message ports.  Do not check the return code under
V36 or earlier.)

Once the IDCMP is opened, with the ports allocated, the program can
receive many types of information directly from Intuition, based on the
IDCMP flags that are set.

The IDCMP allows the application to receive only the events that it
considers important.  The program can, for instance, choose to learn about
gadget events but may not want to learn about other mouse or keyboard
events.  This is done by providing a "filter" or "mask" value for the
IDCMP which tells Intuition which events it should send to this specific
port.  Only messages with a type matching one of the flags set in the
Window structure's IDCMPFlags field will be sent to this port.  These
values may be set at creation time, or modified by calling the function
ModifyIDCMP().

Messages sent to the IDCMP are instances of the structure IntuiMessage.
This is an extended form of the Exec Message structure which allows
Intuition to send user interface specific information to the application.
The IntuiMessage structure is discussed at length below.

After the application opens an IDCMP, it must monitor the port for
messages.  At a minimum, this involves removing all messages from the port
and replying to them.  An event loop which processes messages arriving at
the IDCMP is discussed below.

 Standard IntuiMessage Event Loop    Setting Up A Custom User Port
 Event Loop Example                  IntuiMessages


9 / Using the IDCMP / Standard IntuiMessage Event Loop

The application should handle events quickly.  Any delay in this handling
will make the user interface appear sluggish to the user.  Additionally,
certain events such as IDCMP_SIZEVERIFY may time-out if the application
does not respond to them quickly  (this is to help prevent system
deadlocks).  The action taken by Intuition when an event times-out may not
match the action desired by the program.  When IDCMP_SIZEVERIFY times out,
the window sizing operation is cancelled by Intuition.

Code should be able to handle the case where there are multiple events
waiting at the port.  When events are being generated quickly, Intuition
may post many events to the IDCMP before the application regains control.
This can happen regardless of how fast the application processes the
messages waiting at the port.  Since messages queue up but signals do not,
the application may not see a signal for each message posted.  Because of
these facts, the code should remove all the messages waiting at the port,
regardless of the number, each time Wait() returns.

Code should also be able to handle the case where the signal is set but no
events are waiting at the port.  This could happen if a new message
arrives at the IDCMP while an application is still processing the previous
message.  Since applications typically process all queued messages before
returning to Wait(), the second message gets handled with the signal bit
still set.  The subsequent call to Wait() will return immediately even
though no message is present.  These cases should be quietly ignored.


9 / Using the IDCMP / Setting Up A Custom User Port

An application can use its own message port for the IDCMP instead of the
one set up by Intuition, although some care is required.

As described earlier, IDCMP communication takes place through a pair of
Exec message ports attached to a window: the UserPort and the WindowPort.
The UserPort is the port where the application receives IDCMP messages
from Intuition.  The WindowPort is the reply port where Intuition receives
replies from the application (via the ReplyMsg() function).

In the simplest case, Intuition allocates (and deallocates) both of these
ports when the program opens a window with non-NULL IDCMP flags.
Intuition will also allocate these ports if the application calls
ModifyIDCMP() with non-NULL flags for a window that has NULL IDCMP flags.
These port variables will be set to NULL if there is no message port
allocated, otherwise they will contain a pointer to a message port.

If the WindowPort is not already opened when either OpenWindow() or
ModifyIDCMP() is called, it will be allocated and initialized.

The UserPort is checked separately to see whether it is already opened.

When Intuition initializes the UserPort, it also allocates a signal bit
with a call to AllocSignal().  Since the application makes the call to
OpenWindowTagList() or ModifyIDCMP(), this signal bit is valid for the
application's task.  The address of the application's task is saved in the
SigTask variable of the message port.

The program may choose to supply its own UserPort.  This might be done in
an environment where the program is using several windows and would prefer
to monitor the input using only one message port.  This is done by with
the following procedure:

 1. Create a port for the IDCMP by calling either the Exec function
    CreateMsgPort() or the amiga.lib function CreatePort(), both of which
    return a pointer to a port.  (CreateMsgPort() is a new Exec function
    in V36 and can therefore only be used on systems running Release 2 or
    a later version of the OS.)

 2. Open the windows with no IDCMP flags set.  This will prevent
    Intuition from allocating a port for this window.

 3. Place a pointer to the port created in step 1 into the UserPort field
    of the Window structure.

 4. Call ModifyIDCMP() to set the desired IDCMP flags for the port.
    Intuition will use the port supplied with the window.

    Be Careful with Shared IDCMP Ports.
    -----------------------------------
    If the application is sharing an IDCMP among several windows, it
    must be very careful not to call ModifyIDCMP(window,NULL) for any
    of the windows that are using the shared port, as this will free the
    port and the signal bit.

 5. When an application decides to close a window that has a shared
    IDCMP, there may be messages waiting at the port for any of the
    windows including the window being closed.  It is essential that
    messages destined for a given window be removed and replied to before
    that window is closed.

    CloseWindowSafely(), listed in the next example, performs proper
    message cleanup before closing such a window.  It also sets the
    window's UserPort to NULL so that Intuition knows not to delete the
    port, which should be done by the application in this case.  It is
    incorrect (and dangerous) to simply call CloseWindow() on a window
    that has a shared IDCMP.

    Note that CloseWindowSafely() assumes that the window has a UserPort.

 6. After all windows have been closed, and the port has been removed
    from each, delete the port that was created in step 1.  Use the
    amiga.lib function DeletePort() (if CreatePort() was used) or the
    Exec function DeleteMsgPort() (if CreateMsgPort() was used).

 Closing a Window with a Shared IDCMP


9 / Using the IDCMP / IntuiMessages

The IntuiMessage structure is an Exec Message that has been extended to
include Intuition specific information.  The ExecMessage field in the
IntuiMessage is an actual instance of a Message structure and is used by
Exec to manage the transmission of the message.  The Intuition extensions
of the IntuiMessage are used to transmit specialized Intuition data to the
program.

    struct IntuiMessage
        {
        struct Message ExecMessage;
        ULONG Class;
        UWORD Code;
        UWORD Qualifier;
        APTR IAddress;
        WORD MouseX, MouseY;
        ULONG Seconds, Micros;
        struct Window *IDCMPWindow;
        struct IntuiMessage *SpecialLink;
        };

The IntuiMessage structure fields are as follows:

ExecMessage
    This field is maintained by Exec.  It is used for linking the message
    into the system and broadcasting it to a message port.  See the
    chapter "Exec Messages and Ports" for more information on the Message
    structure and its use.

Class
    Class contains the IDCMP type of this specific message.  By comparing
    the Class field to the IDCMP flags, the application can determine the
    type of this message.  Each message may only have a single IDCMP type.

Code
    Code contains data set by Intuition, such as menu numbers or special
    code values.  The meaning of the Code field changes depending on the
    IDCMP type, or Class, of the message.  Often the code field will
    simply contain a copy of the code of the input event which generated
    this IntuiMessage.

    For example, when the message is of class IDCMP_RAWKEY, Code contains
    the raw key code generated by the keyboard device.  When the message
    is of class IDCMP_VANILLAKEY, Code contains the key mapped ASCII
    character.

Qualifier
    This contains a copy of the ie_Qualifier field that is transmitted to
    Intuition by the input device.  This field is useful if your program
    handles raw key codes, since the Qualifier tells the program, for
    instance, whether or not the Shift key or Ctrl key is currently
    pressed.  Check the <devices/inputevent.h> file for the definitions
    of the qualifier bits.

MouseX and MouseY
    Every IntuiMessage will have the mouse coordinates in these
    variables.  The coordinates can either be expressed as absolute
    offsets from the upper left corner of the window, or expressed as the
    amount of change since the last reported positions (delta). If
    IDCMP_DELTAMOVE is set, then these numbers will represent delta
    positions from the last position.  All messages will have zero in
    these values except IDCMP_MOUSEMOVE and IDCMP_MOUSEBUTTON events,
    which will have the correct delta values for the movement.  If
    IDCMP_DELTAMOVE is not set, then these numbers are the actual window
    offset values.

Seconds and Micros
    These values are copies of the current system clock, in seconds and
    microseconds.  They are set when Intuition generates the message.

    Microseconds (Micros) range from zero up to one million minus one.
    The 32 bits allocated to the Seconds variable has enough accuracy to
    count up to 139 years.  Time is measured from Jan 1, 1978.

IAddress
    Typically this variable contains the address of some Intuition
    object, such as a gadget.  The type of the object depends on the
    Class of the IntuiMessage.  Do not assume that the object is of a
    certain type before checking the Class of the object.

    The IAddress pointer is defined only for the following IDCMP Classes.
    Do not attempt to dereference or otherwise interpret the IAddress
    field of any other type of IntuiMessage.

        IntuiMessage Class  Meaning of IAddress Field
        ------------------  -------------------------
        IDCMP_GADGETDOWN    IAddress points to the gadget.
        IDCMP_GADGETUP      IAddress points to the gadget.
        IDCMP_RAWKEY        IAddress points to the dead-key information.
        IDCMP_IDCMPUPDATE   IAddress points to a tag item list.
        Other classes       No meaning.

    In particular, for IDCMP_MOUSEMOVE IntuiMessages emanating from
    GACT_FOLLOWMOUSE gadgets, the IAddress field does not point to the
    gadget.  Interpreting the IAddress as a gadget pointer and trying to
    access the gadget's fields before ascertaining that the event is an
    IDCMP_GADGETUP or IDCMP_GADGETDOWN event is incorrect, and can lead
    to subtle or serious problems.

    (Note that GadTools gadgets do arrange for the IAddress to point to
    the gadget when IDCMP_MOUSEMOVE messages appear).

IDCMPWindow
    Contains the address of the window to which this message was sent.
    If the application is sharing the window's UserPort between multiple
    windows, IDCMPWindow allows it to determine which of the windows the
    message was sent to.

SpecialLink
    For system use only.


9 Intuition Input and Output Methods / IDCMP Flags

The application specifies the information it wants Intuition to send to it
via the IDCMP by setting IDCMP flags.  These may be set either when
opening the window or by calling ModifyIDCMP().

The flags set may be viewed as a filter, in that Intuition will only post
IntuiMessages to an IDCMP if the matching flag is set.  Thus, the
application will only receive the IDCMP messages whose Class matches one
of the bits set in the window's IDCMP.

For many of these messages, there is a separation of the act of filtering
these messages and causing Intuition to send the messages in the first
place.  For instance, menu help events may be activated for a window by
setting the WA_MenuHelp attribute when the window is opened.  However, the
IDCMP will only receive the messages if the IDCMP_MENUHELP flag is set.
If this flag is not set, then the events are passed downstream in the
input and may be picked up by the console device.

 Event Message Classes and Flags    Verification Functions


9 / IDCMP Flags / Event Message Classes and Flags

 Mouse Event Message Classes and Flags
 Gadget Event Message Classes and Flags
 Menu Event Message Classes and Flags
 Requester Event Message Classes and Flags
 Window Event Message Classes and Flags
 Other Event Message Classes and Flags


9 / / Event Message Classes and Flags / Mouse Flags

IDCMP_MOUSEBUTTONS
    Contains reports about mouse button up and down events.  The events
    will be sent to the application only if they are not used internally
    by Intuition.

    The Code field contains information on the specific mouse button
    event this message represents.  The Code field will be equal to
    SELECTDOWN, SELECTUP, MENUDOWN, MENUUP, MIDDLEDOWN or MIDDLEUP,
    depending on the button pressed or released.  In general, the select
    button is the left mouse button, the menu button is the right mouse
    button and the middle button is an optional third button usually
    located between the select and menu buttons.

    Often, a mouse button event has extra meaning to Intuition, and the
    application may hear about it through a more specific message, for
    example a gadget or menu event.  Other times, no event is generated
    at all, such as when the user depth-arranges a screen by clicking on
    the screen depth gadget.  Note that menu button events are normally
    consumed by Intuition for menu handling.  If an application wishes to
    hear IDCMP_MOUSEBUTTONS events for the menu button, it must set the
    WA_RMBTrap attribute for its window.  See the "Intuition  Windows"
    chapter for more information.

IDCMP_MOUSEMOVE
    Reports about mouse movements, sent in the form of x and y
    coordinates relative to the upper left corner of the window.  One
    message will be sent to the application for each "tick" of the mouse.

    The application can opt to receive IDCMP_MOUSEMOVE events only while
    certain gadgets are active, or during normal window operation.  These
    events are sent whenever a gadget with GACT_FOLLOWMOUSE gadget is
    active, or for any window that has the WA_ReportMouse attribute set.
    This window attribute can be set or cleared by the application at
    will.  See the "Intuition Windows" chapter for full details.

    Requesting IDCMP_MOUSEMOVE messages can create a very large volume of
    messages arriving at the window's IDCMP.  Do not request these
    messages unless the program is prepared to keep up with them.
    Starting in V36, Intuition limits the number of mouse move events
    that pile up at your IDCMP.

    All IDCMP messages contain a mouse x and y position that can be
    absolute values or delta values.  See IDCMP_DELTAMOVE, below.  If the
    application requires a less frequent reporting of the mouse position,
    consider using IDCMP_INTUITICKS.  While IDCMP_MOUSEMOVE events are
    generated by changes in the mouse's position, IDCMP_INTUITICKS
    IntuiMessages are based on a timer.  Since they contain mouse
    coordinates, they effectively sample the mouse position.  These
    message come often enough for many applications, but not so
    frequently as to swamp the application.

    The program will not be sent IDCMP_MOUSEMOVE messages while Intuition
    has the layers of the screen locked (during menu operations and
    window sizing/dragging).  This avoids problems of messages
    accumulating while the program is blocked, waiting to render into a
    locked layer.

IDCMP_DELTAMOVE
    IDCMP_DELTAMOVE is not a message type, and events will never be sent
    to the application with this IDCMP identifier.  This flag is a
    modifier, which changes how mouse movements are reported.  When this
    flag is set, mouse movements are sent as delta values rather than as
    absolute positions.

    The deltas are the amount of change of the mouse position from the
    last reported position.  If the mouse does not move, then the delta
    values will be zero.

    This flag works in conjunction with the IDCMP_MOUSEMOVE flag.  When
    IDCMP_DELTAMOVE is set, IDCMP_MOUSEBUTTONS messages will also have
    relative values, instead of the absolute window position of the mouse.

    Delta mouse movements are reported even after the Intuition pointer
    has reached the limits of the display.  That is, if the pointer has
    reached the edge of the display and the user continues to move the
    mouse in the same direction, the IDCMP_MOUSEMOVE messages will
    continue to report changes in the mouse position even though the
    pointer is no longer moving.


9 / / Event Message Classes and Flags / Gadget Flags

IDCMP_GADGETDOWN
    IDCMP_GADGETDOWN messages are sent when the user selects a gadget
    that was created with the GACT_IMMEDIATE flag set.  The IntuiMessage
    structure's IAddress field will contain a pointer to the selected
    gadget.

IDCMP_GADGETUP
    IDCMP_GADGETUP messages are sent when the user selects a gadget that
    was created with the GACT_RELVERIFY flag set.  The IntuiMessage
    structure's IAddress field will contain a pointer to the selected
    gadget.

IDCMP_CLOSEWINDOW
    IDCMP_CLOSEWINDOW messages are sent when the user selects the
    window's close gadget.  Intuition does not close the window when the
    close gadget is selected.  Rather, an IDCMP_CLOSEWINDOW message is
    sent to the window's IDCMP.  It is up to the application to clean up
    and close the window itself.  If closing a window means losing some
    data (perhaps the spreadsheet the user was working on), it would be
    appropriate for the application to first confirm that the user really
    meant to close the window.


9 / / Event Message Classes and Flags / Menu Flags

IDCMP_MENUPICK
    This flag indicates that the user has pressed the menu button.  If a
    menu item was selected, the menu number of the menu item can be found
    in the Code field of the IntuiMessage.  If no item was selected, the
    Code field will be equal to MENUNULL.

IDCMP_MENUVERIFY
    This is a special verification mode which allows the program to
    confirm that it is prepared to handle Intuition rendering, in this
    case, allowing menus to be drawn in the screen.

    This is a special kind of verification, in that any window in the
    entire screen that has this flag set must respond before the menu
    operations may proceed.  Also, the active window of the screen is
    allowed to cancel the menu operation.  This is unique to
    IDCMP_MENUVERIFY.  Refer to the "Intuition Menus" for a complete
    description.

    Also see the "Verification Functions" section below for more
    information.

IDCMP_MENUHELP
    This message is sent by Intuition when the user selects the Help key
    while the menu system is activated.  If a menu item was selected, the
    menu number of the menu item can be found in the Code field of the
    IntuiMessage.  If no item was selected, the Code field will be equal
    to MENUNULL.

    These messages will only be sent if the WA_MenuHelp attribute is set
    for the window.

    The menu number returned in IDCMP_MENUHELP may specify a position
    that cannot be generated through normal menu activity.  For instance,
    the menu number may indicate one of the menu headers with no item or
    sub-item.  See the chapter on "Intuition Menus" for more information.


9 / / Event Message Classes and Flags / Requester Flags

IDCMP_REQSET
    Intuition sends an IDCMP_REQSET message to the window each time a
    requester opens in that window.

IDCMP_REQCLEAR
    Intuition sends an IDCMP_REQCLEAR message to the window each time a
    requester is cleared from that window.

IDCMP_REQVERIFY
    Set this flag to allow the application to ensure it is prepared for
    Intuition to render a requester in the window.  With this flag set,
    Intuition sends the application a message that a requester is
    pending, and then waits for the application to reply before drawing
    the requester in the window.

    If several requesters open in the window, Intuition asks the
    application to verify only the first one.  After that, Intuition
    assumes that all output is being held off until all the requesters
    are gone.

    By setting the IDCMP_REQSET and IDCMP_REQCLEAR flags, the application
    can track how many requesters are open in the window and when the
    last requester is cleared.  Once all of the requesters are cleared
    from the window, it is safe to write to the window until another
    IDCMP_REQVERIFY is received.

    See the "Verification Functions" section below for more discussion on
    using this flag.


9 / / Event Message Classes and Flags / Window Flags

IDCMP_NEWSIZE
    Intuition sends this message after the user has resized the window.
    After receiving this, the program can examine the size variables in
    the window structure to discover the new size of the window.  The
    message is sent, even if the size of the window did not actually
    change.

IDCMP_REFRESHWINDOW
    This message is sent whenever the window needs refreshing.  This flag
    makes sense only with windows that have a refresh type of
    WA_SimpleRefresh or WA_SmartRefresh.

    As a minimum, the application must call BeginRefresh() and
    EndRefresh() for the window after receiving an IDCMP_REFRESHWINDOW
    event.  Create the window with the WA_NoCareRefresh attribute if you
    do not want to manage these events.  See the "Intuition Windows"
    chapter for details.

    Most of the graphics library calls used for display output are
    compatible with Intuition, with the exception of ScrollRaster().
    Intuition will not send an IDCMP_REFRESHWINDOW event when damage is
    caused to a window by ScrollRaster().  This may happen in a simple
    refresh window which is partially obscured by another window--the
    region that scrolls out from behind the front window will be damaged,
    but the window will receive no notification.  Check the LAYERREFRESH
    bit in the Layer structure Flags field to see if damage did happen as
    a result of ScrollRaster().

IDCMP_SIZEVERIFY
    Set this flag if the program must complete some operation before the
    user sizes the window.  When the user sizes the window, Intuition
    sends an IDCMP_SIZEVERIFY message to the application and then waits
    until the program replies before allowing the user to size the
    window.  See the "Verification Functions" section below for some
    things to consider when using this flag.

IDCMP_ACTIVEWINDOW and IDCMP_INACTIVEWINDOW
    Set these flags to discover when the window becomes activated or
    deactivated.


9 / / Event Message Classes and Flags / Other Flags

IDCMP_VANILLAKEY
    IDCMP_VANILLAKEY messages return keyboard events translated into the
    current default character keymap.  The mapped character value is
    returned in the Code field of the IntuiMessage structure.

    An IDCMP_VANILLAKEY message is sent only if the translation results
    in a single byte value, therefore the program cannot read the Help or
    function keys using IDCMP_VANILLAKEY.

    Starting with V36, programs using IDCMP_VANILLAKEY which also require
    the additional information of special keys, such as the Help key and
    the function keys, may set both IDCMP_VANILLAKEY and IDCMP_RAWKEY.
    When this combination is used, all keypresses that map to single
    character values will be returned as IDCMP_VANILLAKEY events; all
    other keyboard events will be sent as IDCMP_RAWKEY messages.  Note
    that IDCMP_VANILLAKEY processing uses all of the key-up events, so
    the application will only receive key-down events in the IDCMP_RAWKEY
    format.

IDCMP_RAWKEY
    IDCMP_RAWKEY messages give the raw keycodes from the keyboard. The
    numeric value of the keycode is sent in the Code field. Separate
    codes are returned for key down and key up.  Qualifier codes, such as
    Shift or Alt and whether this key is a repeat, may be found in the
    Qualifier field of the message.

    In general, the application should not assume any correspondence
    between the keycode and the key value.  Character positions on the
    keyboard change from country to country, and the application should
    respect the keymap set by the user.

    Programs using IDCMP_RAWKEY messages should perform their own key
    mapping by calling the console.device function RawKeyConvert(), or
    the keymap.library function MapRawKey().  (The latter is a bit more
    convenient, but is only available under V36 and higher).  The Autodoc
    for the MapRawKey() function shows how you can process so-called dead
    keys.  A dead key is a key combination that has no immediate effect,
    but instead modifies a subsequent keystroke.  For example, on the
    default keymap, Alt-F is a dead key for the acute accent mark.  The
    sequence of Alt-F followed by the E key yields an é with an acute
    accent.

    For an example of key mapping using the RawKeyConvert() call, see the
    rawkey.c example in the "Intuition Mouse and Keyboard" chapter.

    The application can assume that certain keys will always return the
    same raw keycode, these keys do not have to be mapped.  In general
    these keys are in the high part of the keymap, above hex 40, and
    includes all non-alphanumeric keys.  The fixed keys include the
    function keys, backspace, delete, help and cursor keys.

IDCMP_NEWPREFS
    IDCMP_NEWPREFS messages are sent when the system Preferences are
    changed by a call to SetPrefs().  The program can learn of these
    changes by setting this flag.

    After receiving a message of class IDCMP_NEWPREFS, the application
    should call GetPrefs() to obtain a copy of the new Preferences.

    Under the new Preferences scheme used in Release 2 and later versions
    of the OS, an IDCMP_NEWPREFS message will not always be sent when the
    user changes a Preferences setting.  Only Preferences values
    available under V34, i.e., those that can be modified by a call to
    SetPrefs(), will cause an IDCMP_NEWPREFS message to be sent.  New
    Preferences items such as overscan or font settings rely on
    filesystem notification for monitoring changes.  See the chapter on
    "Preferences" for more information.

    This message type is broadcast to all IDCMP that have this flag set,
    not just to the active window.  If the application has this flag set,
    it should be prepared to handle the event even if it is not active.

IDCMP_DISKINSERTED and IDCMP_DISKREMOVED
    When the user inserts or removes a floppy disk from any drive,
    Intuition will send one of these message types.

    This message type is broadcast to all IDCMP that have this flag set,
    not just to the active window.  If the application has this flag set,
    it should be prepared to handle the event even if it is not active.

IDCMP_INTUITICKS
    Intuition sends these messages to the active window based on an
    internal timer which "ticks" roughly ten times a second. This
    provides the application with simple timer events from Intuition.

    Intuition does not allow IDCMP_INTUITICKS events to accumulate at a
    port.  After an IDCMP_INTUITICKS message has been sent to a port,
    Intuition will not send another until the application replies to the
    first.  This means that an application that has not been able to
    service the IDCMP for an extended period can expect at most one
    IDCMP_INTUITICKS message to be waiting at the port.

    These events are to be used as "prods", and not as time counters.  Do
    not rely on the timing accuracy of the event, or on the exact
    frequency at which they appear.  Remember, IDCMP_INTUITICKS will only
    be sent to the active window.  If the user selects another window,
    the events will no longer be received at the first window.

IDCMP_IDCMPUPDATE
    Used for notification from Boopsi custom gadgets.  See the chapter on
    "BOOPSI" for more information.  The IAddress field contains a pointer
    to a tag item list.  Tag lists are described in the chapter
    "Utility Library".

IDCMP_CHANGEWINDOW
    This message provides the window with notification of any change in
    the size or position of a window.

There are two other message classes reserved for system use:

IDCMP_WBENCHMESSAGE
    Special messages for Workbench, system use only.

IDCMP_LONELYMESSAGE
    For internal tracking by Intuition, system use only.


9 / IDCMP Flags / Verification Functions

IDCMP_SIZEVERIFY, IDCMP_REQVERIFY and IDCMP_MENUVERIFY are exceptional in
that Intuition sends an IntuiMessage to the application and then waits for
the application to reply before Intuition proceeds.  The application
replies by calling the Exec function ReplyMsg().

The implication is that the user requested some operation but the
operation will not happen immediately and, in fact, will not happen at all
until the application says it is safe.  Because this delay can be
frustrating and intimidating, the program should strive to make the delay
as short as possible.  An application should always reply to a
verification message as soon as possible.

These problems may be overcome by setting up a separate task to monitor
the IDCMP and respond to incoming IntuiMessages immediately.  This is
recommended where there is heavy traffic through the IDCMP, which occurs
when many IDCMP flags are set.  Monitoring with a separate task may not be
appropriate if the main program must synchronize with the event before it
can respond to the message.

In previous versions of the operating system, it was not safe to leave any
of the VERIFY functions enabled at a time when the task is unable to
respond for a long period.  This restriction included calls to AmigaDOS
directly (with Open(), for example), or indirectly (with OpenLibrary(),
for a disk based library, for example), when a VERIFY function was active.
This was because there are many cases where AmigaDOS will put up a
requester prompting the user for input, and Intuition may end up waiting
for the application to reply to the VERIFY message, while the application
waits for the AmigaDOS call to finish.  Prior to Release 2, this deadlock
would freeze the Amiga.

Beginning with V36, Intuition will no longer wait forever for the
application to respond to the verify messages.  These messages will now
time-out; that is, if the application does not respond within a set
period, Intuition will act as if it had.  Even in this case, though, the
machine will appear to be locked up until the time-out occurs.

The application should use ModifyIDCMP() to turn off all VERIFY messages
before calling AmigaDOS, or functions that may call AmigaDOS.

If the application sets up a separate task to monitor the IDCMP, and the
task monitoring the IDCMP does not call AmigaDOS functions, and if the
monitor task will always be able to reply to the VERIFY message without
any help from the other task, then the above warning does not apply.

For additional information, see the IDCMP_MENUVERIFY discussion in the
"Intuition Menus" chapter, the IDCMP_REQVERIFY discussion in the
"Intuition Requesters and Alerts" chapter and the IDCMP_SIZEVERIFY
discussion in the "Intuition Windows" chapter.

This message type is broadcast to all IDCMP on the screen that have this
flag set, not just to the active window.  If the application has this flag
set, it should be prepared to handle the event even if it is not active.


9 Intuition Input and Output Methods / Function Reference

The following are brief descriptions of the Intuition functions that
relate to the use of input and output under Intuition. See the Amiga ROM
Kernel Reference Manual: Includes and Autodocs for details on each
function call.

          Table 9-1: Functions for Intuition Input and Output
  ____________________________________________________________________
 |                                                                    |
 |    Function                    Description                         |
 |====================================================================|
 |  ModifyIDCMP()  Change the message filter for an IDCMP.            |
 |                 Starting in V37, this function has a return value. |
 |____________________________________________________________________|


Amiga® RKM Libraries: 10 Intuition Mouse and Keyboard

In the Intuition system, the mouse is the normal method of making
selections and the keyboard is used for entering character data.  This
section describes how users employ the mouse to interact with the system
and how to arrange for a program to use the mouse.  It also describes the
use of the keyboard, both as a character input device and as an alternate
method of controlling the mouse pointer.

 The Mouse    The Pointer    The Keyboard    Function Reference


10 Intuition Mouse and Keyboard / The Mouse

The Amiga mouse is a small, hand-held input device connected to the Amiga
by a flexible cable.  The user can input horizontal and vertical
coordinates with the mouse by sliding it around on a smooth surface.  This
movement causes the repositioning of a pointer on the display; whenever
the mouse is moved the pointer moves, and in the same direction.

The mouse also provides two or three input keys, called mouse buttons,
that allow the user to input information to the computer.  The basic
activities the user can perform with the mouse are shown below.

                 Action                Explanation
                 ------                -----------
            Moving the Mouse  Sliding the body of the mouse over a
                              surface, such as a desk top.

           Pressing a button  Pushing down a mouse button (which is
                              released at some later time).

           Clicking a button  Quickly pressing and releasing a mouse
                              button.

    Double clicking a button  Clicking a button twice in a short
                              period of time.

                    Dragging  Pressing a button and moving the mouse
                              while the button is held down.  The
                              drag operation is completed by
                              releasing the button.

                  Table 10-1: Mouse Activities

The action associated with mouse button presses can occur when the button
is first pressed, or while the button is held down, or when the button is
released.  As an example of this, consider the drag gadget of a window.
When the select button of the mouse is first pressed an outline
representing the window frame is drawn.  While the button is held down the
outline remains, and it moves with the pointer as the mouse is moved.
When the button is released, the outline is erased and the window takes
its new position.

 Intuition's Use of Mouse Events    Mouse Usage Example
 Mouse Messages


10 / The Mouse / Intuition's Use of Mouse Events

When the mouse is moved or its buttons are pressed, the system generates
input events that represent the actions.  The input events are taken from
the input chain by Intuition when the active window requires the events.
Note that only input for a specific window will be affected by changes in
that window's IDCMP flags.

Most events generated by the user with the mouse are used by Intuition.

As the user moves the mouse, Intuition changes the position of its
pointer.  The Intuition pointer moves around the entire video display,
mimicking the user's movement of the mouse.  The user points at an object
by positioning the hot spot of the pointer over the object.  The hot spot
is the active part of the pointer image; the hot spot for Intuition's
default pointer is the pixel at the tip of the arrow.

After pointing to an object, the user can perform some action on that
object by selecting it with one of the mouse buttons.  These can include
any of the actions specified above, such as dragging or double clicking.

The left mouse button is generally used for selection, while the right
mouse button is most often used for information transfer.  The terms
selection and information are intentionally left open to some
interpretation, as it is impossible to imagine all the possible uses for
the mouse buttons.

The selection/information paradigm can be crafted to cover most
interaction between the user and an application.  When using the mouse,
the application should emphasize this model.  It will help the user to
understand and remember the mouse control of the application.

Applications that handle mouse button events directly, bypassing the menu
and gadget systems, should use the same selection/information model used
by Intuition.

 Select Button    Menu Button


10 / / Intuition's Use of Mouse Events / Select Button

When the user presses the left, or select button, Intuition examines the
state of the system and the position of the pointer.  This information is
used to decide whether or not the user is trying to select some object,
operation, or option.  For example, the user positions the pointer over a
gadget and then presses the left button to select that gadget.
Alternatively, the user can position the pointer over a window and press
the select button to activate the window.  The pointer is said to be over
an object when the pointer's hot spot is positioned within the selection
region of the object.

A number of other common techniques involving the select button are
available.  They include:

Drag Select
    Multiple objects or an extended area may be selected by dragging the
    mouse over a range with the select button held down.  For instance,
    in Release 2, multiple icons can be selected in a Workbench window by
    pressing the select button while the pointer is over the background
    of the window (not an icon or a system gadget) and then moving the
    mouse with the select button held down.  A selection rectangle will
    be displayed and all icons within the rectangle will be selected.
    Similarly, the user may highlight blocks of text in a console window
    by pressing the select button over the first desired character and
    dragging the mouse to the last desired character while holding the
    button down.

Multi-Select or Shift Select
    Another way to select multiple objects or an extended area is through
    the shift select technique.  First, select the first member of the
    group of objects in the normal way.  Additional objects can be added
    to the group by holding down the Shift key while the select button is
    pressed.  This technique works with Workbench icons, where icons may
    be added one-at-a-time to the list of selected icons; and with text
    in a console window, where the selected text is extended to include
    the new position.  Note that text need not operate this way, and the
    application may allow multiple discrete blocks to be selected at any
    given time.

Cancel Drag Operation
    Both drag select and the dragging of individual objects may often be
    canceled by pressing the right mouse button before completing the
    drag operation (before releasing the select button).  Examples of
    this include window dragging and sizing, and positioning of Workbench
    icons.


10 / / Intuition's Use of Mouse Events / Menu Button

The right mouse button is used to initiate and control information
gathering processes.  Intuition uses this button most often for menu
operations.

For most active windows, pressing the menu button will display the
window's menu bar at the top of the screen.  Dragging the mouse with the
menu button depressed allows the user to browse through the available
menus.  Releasing the right mouse button over a menu item will select that
item, if it is a valid choice.  Additionally, the user can select multiple
items by repeatedly pressing the select button while the menu button is
held down.

Drag selection is also available in menu operations.  When the menu system
is activated, and the user has the menu button pressed, the select button
may be pressed and the mouse dragged over all items to be selected.  This
only works if the select button is pressed after the menu button, and all
items that the pointer travels over will be selected.

Double clicking the right mouse button can bring up a special requester
for extended exchange of information.  This requester is called the
double-menu requester, because a double click of the menu button is
required to reveal it, and because this requester acts like a super menu
through which a complex exchange of information can take place. Because
the requester is used for the transfer of information, it is appropriate
that this mechanism is called up by using the right button.

The programmer should consult the Amiga User Interface Style Guide for
more information on the standard uses of the mouse and its buttons.

Button activation and mouse movements can be combined to create compound
instructions.  For example, Intuition combines multiple mouse events when
displaying the menu system.  While the right button is pressed to reveal
the menu items of the active window, the user can move the mouse to
position the pointer and display different menu items and sub-items.
Additionally, multiple presses of the left button can be used to select
more than one option from the menus.

Dragging can have different effects, depending on the object being
dragged.  Dragging a window by the drag gadget will change the position of
the window.  Dragging a window by the sizing gadget will change the size
of the window.  Dragging a range in a Workbench window will select all of
the icons in the rectangular range.


10 / The Mouse / Mouse Messages

Mouse events are broadcast to the application via the IDCMP or the console
device.  See the "Intuition Input and Output Methods" chapter in this book
for information on the IDCMP.  See the "Console Device" chapter in the
Amiga ROM Kernel Reference Manual: Devices for more about the console
device.

Simple mouse button activity not associated with any Intuition function
will be reported to the window as an IntuiMessage with a Class of
IDCMP_MOUSEBUTTONS.  The IntuiMessage Code field will be set to
SELECTDOWN, SELECTUP, MIDDLEDOWN, MIDDLEUP, MENUDOWN or MENUUP to specify
changes in the state of the left, middle and right buttons, respectively.

Direct select button events will not be received by the program if the
select button is pressed while the pointer is positioned over a gadget or
other object which uses the button event.  For example, select button
activity over a gadget is reported with a Class of IDCMP_GADGETDOWN or
IDCMP_GADGETUP.  The gadget is said to have consumed the mouse events and
produced gadget events.

If the menu system is enabled, menu selections appear with a Class of
IDCMP_MENUPICK.  To directly receive menu button events, the application
must set the flag WFLG_RMBTRAP for the window either when the window is
opened or by changing the flag in a single, atomic operation.  See the
chapter "Intuition Windows" for more information on the flag WFLG_RMBTRAP.

The program receives mouse position changes in the event Class
IDCMP_MOUSEMOVE.  The MouseX and MouseY position coordinates describe the
position of the mouse relative to the upper left corner of the reference
window.  These coordinates are always in the resolution of the screen
being used, and may represent any pixel position on the screen, even
though the hardware sprites can be positioned only on the even numbered
pixels of a high resolution screen and on the even numbered rows of an
interlaced screen.  Enabling IDCMP_MOUSEMOVE messages is discussed below
in the section on "The Pointer".

To get mouse movement reported as deltas (amount of change from the last
position) instead of as absolute positions, set the IDCMP flag
IDCMP_DELTAMOVE.  When IDCMP_DELTAMOVE is set, the IDCMP_MOUSEMOVE
messages received by the program will have delta values rather than
absolute values.  Note that IDCMP_DELTAMOVE is simply a flag used to
modify the behavior of IDCMP_MOUSEMOVE, and that no messages of class
IDCMP_DELTAMOVE are ever sent.

Each window has a queue limit for the number of IDCMP_MOUSEMOVE messages
waiting on its IDCMP at any given time.  If the number of mouse move
messages waiting at the IDCMP is equal to the queue limit, then Intuition
will discard additional IDCMP_MOUSEMOVE messages until the application
replies to one of the queued mouse move messages.  The default queue limit
for mouse move messages is five.

Be aware that this may cause some data loss, especially when the
application is using IDCMP_DELTAMOVE, as the information contained in the
discarded messages is not repeated.  When using IDCMP_DELTAMOVE, this
could cause the application to lose track of the actual pointer position.
The application may wish to change the default mouse queue size if it is
unable to reply to messages queued at the IDCMP for an extended period.
The mouse queue can be set when the window is opened by using the
WA_MouseQueue tag, and may later be modified using the SetMouseQueue()
call.  Note that the actual mouse position is always available to the
application through the Window structure MouseX and MouseY.


10 / The Mouse / Mouse Usage Example

The example program below shows the use of IDCMP_MOUSEBUTTONS,
IDCMP_MOUSEMOVE and DoubleClick().  DoubleClick() is used to test the
interval between two times and determine if the interval is within the
user specified time for double clicking as set in the Preferences Input
editor.

    BOOL DoubleClick( unsigned long sSeconds, unsigned long sMicros,
                      unsigned long cSeconds, unsigned long cMicros );

The sSeconds and sMicros arguments specify a timestamp value describing
the start of the double click time interval to be tested.  The cSeconds
and cMicros arguments specify a timestamp value describing the end of the
double click time interval to be tested.

DoubleClick() returns TRUE if the time interval was short enough to
qualify as a double-click.  A FALSE return indicates that the time
interval between presses took too long.  The button presses should be
treated as separate events in that case.

     mousetest.c


10 Intuition Mouse and Keyboard / The Pointer

The system provides a pointer to allow the user to make selections from
menus, choose gadgets, and so on.  The user may control the pointer with a
mouse, the keyboard cursor keys or some other type of controller.  The
specific type of controller is not important, as long as the proper types
of input events can be generated.

The pointer is associated with the active window and the input focus.  The
active window controls the pointer imagery and receives the input stream
from the mouse.  The pointer and mouse may be used to change the input
focus by selecting another window.

 Pointer Position    Custom Pointer    Pointer Example


10 / The Pointer / Pointer Position

There are two ways to determine the position of the pointer: by direct
examination of variables in the window structure at any time, and by
examining messages sent by Intuition which inform the application of
pointer movement.  The pointer coordinates are relative to the upper left
corner of the window and are reported in the resolution of the screen,
even though the pointer's visible resolution is always in low-resolution
pixels (note that the pointer is actually a sprite).

The MouseX and MouseY fields of the Window structure always contain the
current pointer x and y coordinates, whether or not the window is the
active one.  If the window is a GimmeZeroZero window, the variables
GZZMouseX and GZZMouseY in the Window structure contain the position of
the mouse relative to the upper left corner of the inner window.

If the window is receiving mouse move messages, it will get a set of x,y
coordinates each time the pointer moves.  To receive messages about
pointer movements, the WFLG_REPORTMOUSE flag must be set in the Window
structure.  This flag can be set when the window is opened.  The flag can
also be modified after the window is open by calling ReportMouse(),
however C programmers should avoid this function.  ReportMouse() has
problems due to historic confusion about the ordering of its C language
arguments.  Do not use ReportMouse() unless you are programming in
assembler.  C programmers should set the flag directly in the Window
structure using an atomic operation.

Most compilers generate atomic code for operations such as mywindow->flags
|= WFLG_REPORTMOUSE or mywindow->flags &= ~WFLG_REPORTMOUSE.  If you are
unsure of getting an atomic operation from your compiler, you may wish to
do this operation in assembler, or bracket the code with a
Forbid()/Permit() pair.

After the WFLG_REPORTMOUSE flag is set, whenever the window is active it
will be sent an IDCMP_MOUSEMOVE messages each time the pointer position
changes. The window must have the IDCMP flag IDCMP_MOUSEMOVE set to
receive these messages.

Mouse movements can cause a very large number of messages to be sent to
the IDCMP, the application should be prepared to handle them efficiently.

Messages about pointer movements may also be activated by setting the flag
GACT_FOLLOWMOUSE in an application Gadget structure. When this flag is set
in a gadget, changes in the pointer position are reported as long as the
gadget is selected by the user. These messages are also sent as
IDCMP_MOUSEMOVE messages.


10 / The Pointer / Custom Pointer

An application can set a custom pointer for a window to replace the
default pointer. This custom pointer will be displayed whenever the window
is the active one.

To place a custom pointer in a window, call SetPointer().

    void SetPointer( struct Window *window, UWORD *pointer, long height,
                     long width, long xOffset, long yOffset );

Set the window argument to the address of the window that is to receive
this custom pointer definition.  The pointer argument is the address of
the data that defines the custom pointer image. The format of this data is
discussed in the next section, "The Sprite Data Structure".

The height and width specify the dimensions of the pointer sprite.  There
is no height restriction but the width of the sprite must be less than or
equal to 16.

The xOffset and yOffset are used to offset the top left corner of the
hardware sprite imagery from what Intuition regards as the current
position of the pointer.  Another way of describing this is the offset of
the default Intuition pointer hot spot from the top left corner of the
sprite.

For instance, by specifying offsets of (0,0), the top left corner of the
sprite image will be placed at the pointer position.  On the other hand,
specifying an xOffset of -7 (remember, sprites are 16 pixels wide) will
center the sprite over the pointer position.  Specifying an xOffset of -15
will place the right edge of the sprite will be over the pointer position.

    Specifying the Hot Spot.
    ------------------------
    For compatibility, the application must specify that the "hot
    spot" of the pointer is one pixel to the left of the desired
    position. Changes to the pointer done by a program must compensate
    for this. The Preferences Pointer editor correctly handles this
    situation.

To remove the custom pointer from the window, call ClearPointer().

    void ClearPointer( struct Window *window );

Set the window argument to the address of the window that is to have its
custom pointer definition cleared.  The pointer will be restored to the
default Intuition pointer imagery

SetPointer() and ClearPointer() take effect immediately if the window is
active, otherwise, the change will only be displayed when the window is
made active.

 The Sprite Data Structure


10 / / Custom Pointer / The Sprite Data Structure

To define the pointer, set up a sprite data structure (sprites are one of
the general purpose Amiga graphics structures). The sprite image data must
be located in Chip memory, which is memory that can be accessed by the
special Amiga hardware chips. Expansion, or Fast memory cannot be
addressed by the custom chips. Ensure that data is in Chip memory by using
the AllocMem() function with the MEMF_CHIP flag, and copying the data to
the allocated space. Alternately, use the tools or flags provided by each
compiler for this purpose. See the "Exec Memory Allocation" chapter for
more information.

A sprite data structure is made up of words of data. In a pointer sprite,
the first two words and the last two words are reserved for the system and
should be set to zero. All other words contain the sprite image data.

The pointer in the example, a standard busy pointer, is sixteen lines high
and sixteen pixels wide.  Currently, all sprites are two bit planes deep,
with one word of data for each line of each plane.  The example sprite
image consists of 36 words (2 planes x 18 lines = 36 words).  Add to this
the four reserved words of control information for a total of 40 words of
data.  See the example below for the complete data definition.

The sprite data words are combined to determine which color will appear at
each pixel position of each row of the sprite.  The first two words of
image data, 0x0400 and 0x07C0, represent the top line of the sprite.  The
numbers must be viewed as binary numbers and combined in a bit-wise
fashion.  The highest bit from each word are combined to form a two bit
number representing the color register for the leftmost pixel.  The next
two bits represent the next pixel in the row, and so on, until the low
order bits from each word represent the rightmost pixel in the row.

For example:

                  Hex                  Binary
                  ---                  ------

    Second word  0x07C0  0 0 0 0 0  1  1 1 1 1  0 0 0 0 0 0
    First word   0x0400  0 0 0 0 0  1  0 0 0 0  0 0 0 0 0 0

                         \________/\_/\_______/\___________/
                             |      |     |          |
                             |      |     |          |
                             |      |     |          `-- 00 = color 0
                             |      |     |
                             |      |     `-- 10 = color 2
                             |      |
                             |      `-- 11 = color 3
                             |
                             `-- 00 = color 0

    Pointer Color Ordering.
    -----------------------
    The first word in a line gives the least significant bit of the
    color register and the second word gives the most significant bit.

Sprites get their color information from the color registers much like
screens do.  See the Amiga Hardware Reference Manual for more information
on the assignment of color registers to sprites.  Note that the color
number given above is added to a base number to determine the actual
hardware color register.

The colors of the Intuition pointer may be changed.  The Intuition pointer
is always sprite 0.  To change the colors of sprite 0, call the graphics
library routine SetRGB4().


10 Intuition Mouse and Keyboard / The Keyboard

A program can receive keyboard data through an IDCMP port by setting the
IDCMP_RAWKEY flag, the IDCMP_VANILLAKEY flag or both.  IDCMP_VANILLAKEY
events provide for simple ASCII text and standard control keys like space,
return and backspace.  IDCMP_RAWKEY events provide a more complex input
stream, which the program must process to generate ASCII data.
IDCMP_RAWKEY returns all keycodes, both key-up and key-down, including
function keys.

    Keystrokes Are Not Always Paired.
    ---------------------------------
    Keystrokes do not always come in key-down/key-up pairs.  For
    example, repeating keys appear as a sequence of key-down messages.

IDCMP_RAWKEY and IDCMP_VANILLAKEY may be set together.  When both flags
are set in the IDCMP, IDCMP_VANILLAKEY messages will be sent for
keystrokes that directly map to a single ASCII value.  IDCMP_RAWKEY
messages will be sent for key sequences that do not map to simple values,
i.e. if a key sequence does not map to an IDCMP_VANILLAKEY message, it
will be sent as an IDCMP_RAWKEY message.  This allows easy access to
mapped characters through IDCMP_VANILLAKEY with control characters
returned as IDCMP_RAWKEY.  Note that the IDCMP_RAWKEY events will only
return the key down events when used with IDCMP_VANILLAKEY.

When Intuition responds to an input event or sequence of events, the
application will not receive those events.  This happens for system
shortcuts (left Amiga + key) if the system shortcut is defined, and for
menu shortcuts (right Amiga + key) if the menu shortcut is defined for the
active window.  If the shortcut is not defined, then the appropriate key
event will be sent with the proper Amiga qualifier set.

Key repeat characters have a queue limit which may be set for each window,
much like the mouse queue described above.  The key repeat queue limit may
only be set when the window is opened using the WA_RptQueue tag, there is
no function call for modifying the value after the window is open.  The
default queue limit for key repeat characters is three.  This limit causes
any IDCMP_RAWKEY, IDCMP_VANILLAKEY or IDCMP_UPDATE message with the
IEQUALIFIER_REPEAT bit set to be discarded if the queue is full
(IDCMP_UPDATE is discussed in the "BOOPSI" chapter).  The queue is said to
be full when the number of waiting repeat key messages is equal to the
queue limit.  Note that the limit is not per character, it is on the total
number of key messages with the repeat bit set.  Once the limit is
reached, no other repeat characters will be posted to the IDCMP until the
application replies to one of the outstanding repeat key messages.  The
repeat queue limit is not as dangerous as the mouse queue limit as only
duplicate keystroke information is discarded, where the mouse queue limit
discards information that cannot be easily reproduced.

 Rawkey Keymapping Example          Menu Shortcuts
 Keyboard Control of the Pointer    Amiga Qualifiers
 Intuition Keyboard Shortcuts


10 / The Keyboard / Keyboard Control of the Pointer

All Intuition mouse activities can be emulated using the keyboard, by
combining the Amiga command keys with other keystrokes.

The pointer can be moved by holding down either Amiga key along with one
of the four cursor keys. The mouse pointer accelerates the longer these
keys are held down. Additionally, holding down either Shift key will make
the pointer jump in larger increments. The pointer position may also be
adjusted in very fine increments through this technique. By holding down
either Amiga key and briefly pressing one of the cursor keys, the pointer
may be moved one pixel in any direction.

Press the left Alt key and either one of the Amiga keys simultaneously
emulates the left button of the mouse.  Similarly, pressing the right Alt
key and either one of the Amiga keys simultaneously emulates the right
button of the mouse.  These key combinations permit users to make gadget
selections and perform menu operations using the keyboard alone.


10 / The Keyboard / Intuition Keyboard Shortcuts

If Intuition sees a command key sequence that means nothing to it, the key
sequence is sent to the active window as usual. See the chapter on
"Intuition Input and Output Methods" for how this works. This section and
the next section describe what Intuition does when it recognizes certain
special command key sequences.

It is recommended that programs abide by certain command key standards to
provide a consistent interface for Amiga users. The Amiga User Interface
Style Guide contains a complete list of the recommended standards.

There are a number of special keyboard shortcuts supported by Intuition.
These involve holding down the left Amiga key and simultaneously pressing
a another key.  These functions allow the user to do such things as move
the Workbench screen to the front using the keyboard.

        Table 10-2: Intuition Keyboard Shortcuts

      Keyboard Shortcut       Function Performed
      -----------------       ------------------

        left Amiga M      Move frontmost screen to back.

        left Amiga N      Move Workbench screen to front.

        left Amiga B      System requester cancel, or select the
                          rightmost button in the system requester.

        left Amiga V      System requester OK, or select the leftmost
                          button in the system requester.

     left Amiga + mouse   Screen drag from any point.  By holding down
       select button      the left Amiga key, the user may drag the
                          screen with the mouse from any part of the
                          screen or window on the screen.

    About System Keyboard Shortcuts
    -------------------------------
    Many of these keyboard commands may be remapped through the IControl
    Preferences editor.  Do not rely on the values reported here.

Intuition consumes these command key sequences for its own use.  That is,
it always detects these events and removes them from the input stream.
The application will not see the events.


10 / The Keyboard / Menu Shortcuts

Menu items and sub-items may be paired with command key sequences to
associate certain characters with specific menu item selections. This
gives the user a shortcut method to select frequently used menu
operations, such as Undo, Cut, and Paste. Whenever the user presses the
right Amiga key with an alphanumeric key, the menu strip of the active
window is scanned to see if there are any command key sequences in the
list that match the sequence entered by the user. If there is a match,
Intuition translates the key combination into the appropriate menu item
number and transmits the menu number to the application program.

    Menu Shortcuts Look Like the Real Thing.
    ----------------------------------------
    To the application it looks as if the user had selected a given
    menu item with the mouse. The program will receive a menu event, not
    a key event. For more information on menu item selection, see the
    "Intuition Menus" chapter.


10 / The Keyboard / Amiga Qualifiers

The Amiga keyboard has several special qualifiers which are listed in the
next table.  Most of these qualifiers are associated with special keys on
the keyboard such as the Shift or Ctrl key.  These keys are used to modify
the meaning of other keys.  Other qualifiers are associated with mouse
button status.  For a complete list of all the qualifiers, see the include
file <devices/inputevent.h>.

The Qualifier field of each IntuiMessage contains the status of all the
qualifiers.  An individual application should never attempt to track the
state of any of the qualifier keys or mouse buttons even though key-down
and key-up information may be available.  Instead use the information
available in the Qualifier field of the IntuiMessage structure.

                 Table 10-3: Keyboard Qualifiers

    Qualifier
      Type          Key Label  Explanation
    ---------       ---------  -----------
    Control         Ctrl       The IEQUALIFIER_CONTROL bit indicates
                               that the Control key is depressed.

    Amiga           Fancy A    There are two Amiga keys, one on each
                               side of the space bar.  The left Amiga
                               key is recognized by the Qualifier bit
                               IEQUALIFIER_LCOMMAND, and the right
                               Amiga key by IEQUALIFIER_RCOMMAND.

    Alternate       Alt        There are two separate Alt keys, one on
                               each side of the space bar, next to the
                               Amiga keys.  These can be treated
                               separately, if desired.  The left Alt
                               key sets the IEQUALIFIER_LALT bit and
                               the right Alt key sets the
                               IEQUALIFIER_RALT bit.

    Shift           Up Arrow   There are two separate Shift keys, one
                               above each Alt key.  These can be
                               treated distinctly, if desired.  The
                               left Shift key sets the
                               IEQUALIFIER_LSHIFT bit and the right
                               Shift key sets the IEQUALIFIER_RSHIFT
                               bit.

    Caps Lock       Caps Lock  The IEQUALIFIER_CAPSLOCK bit is set as
                               long as the Caps Lock light is
                               illuminated.

    Numeric Pad                The IEQUALIFIER_NUMERICPAD bit is set
                               for keys on the numeric keypad.

    Repeat                     Repeat key events are sent with the
                               IEQUALIFIER_REPEAT bit set.

    Mouse Buttons              If mouse buttons are down when the
                               event occurs, one or more of the three
                               bits IEQUALIFIER_LEFTBUTTON,
                               IEQUALIFIER_MIDBUTTON or
                               IEQUALIFIER_RBUTTON will be set.


10 Intuition Mouse and Keyboard / Function Reference

The following are brief descriptions of the Intuition functions that
relate to the use of the mouse and keyboard under Intuition. See the Amiga
ROM Kernel Reference Manual: Includes and Autodocs for details on each
function call.

         Table 10-4: Functions for Intuition Mouse and Keyboard
  ____________________________________________________________________
 |                                                                    |
 |      Function                  Description                         |
 |====================================================================|
 |    DoubleClick()  Test two time values for double click status.    |
 |--------------------------------------------------------------------|
 |     SetPointer()  Change the Intuition pointer imagery for an open |
 |                   window.                                          |
 |   ClearPointer()  Restore the default Intuition pointer imagery.   |
 |--------------------------------------------------------------------|
 |  SetMouseQueue()  Change the mouse queue for an open window.       |
 |    ReportMouse()  A function C programmers should not use.         |
 |____________________________________________________________________|


Amiga® RKM Libraries: 11 Intuition Special Functions

There are several Intuition topics which, while not large enough to fill
chapters of their own, nontheless deserve to be discussed.  The subjects
covered here include locking IntuitionBase, the Intuition memory functions
AllocRemember() and FreeRemember(), using sprites with Intuition, and
Intuition's special internal functions.

 Locking IntuitionBase
 Easy Memory Allocation and Deallocation
 Current Time Values
 Using Sprites in Intuition Windows and Screens
 Intuition and Preferences
 Function Reference


11 Intuition Special Functions / Locking IntuitionBase

It is sometimes necessary to examine the IntuitionBase structure.  Items
such as the address of the active screen and window, current mouse
coordinates and more can be found there.  It is never a good idea to
simply read these fields, as they are prone to sudden change.  The
IntuitionBase structure must always be locked before looking at its fields.

It is necessary to inform Intuition that an application is about to
examine IntuitionBase so that Intuition will not change any variables and
IntuitionBase will remain static during the access.  The call LockIBase()
will lock the state of IntuitionBase so that it may be examined.  During
the time that the application has IntuitionBase locked, all Intuition
input processing is frozen.  Make every effort to examine IntuitionBase
and release the lock as quickly as possible.  The values in IntuitionBase
are read-only.  Applications should never write values to IntuitionBase.

    ULONG LockIBase( unsigned long dontknow );

LockIBase() is passed a ULONG (dontknow in the prototype above) indicating
the Intuition lock desired.  For all foreseeable uses of the call this
value should be 0.  LockIBase() returns a ULONG, that must be passed to
UnlockIBase() later to allow IntuitionBase to change once again.

Every call to LockIBase() must be matched by a subsequent call to
UnlockIBase():

    void UnlockIBase( unsigned long ibLock );

Set the ibLock argument to the value returned by the previous call to
LockIBase().

    About LockIBase().
    ------------------
    This function should not be called while holding any other system
    locks such as Layer and Layer_Info locks.  Between calls to
    LockIBase() and UnlockIBase(), you may not call any Intuition
    or other high-level system functions so it is best to copy the
    information you need and release the lock as quickly as possible.

    About IntuitionBase.
    --------------------
    Never, ever, modify any of the fields in IntuitionBase directly.
    Also, there are fields in IntuitionBase that are considered system
    private that should not be accessed, even for reading.  (Refer to the
    <intuition/intuitionbase> include file.) Application programs
    cannot depend on (and should not use) the contents of these fields;
    their usage is subject to change in future revisions of Intuition.


11 Special Functions / Easy Memory Allocation and Deallocation

Intuition has a pair of routines that enable applications to make multiple
memory allocations which are easily deallocated with a single call.  The
Intuition routines for memory management are AllocRemember() and
FreeRemember().  These routines rely upon the Remember structure to track
allocations.

 Intuition Helps You Remember    The Remember Structure
 How to Remember                 An Example of Remembering


11 / Easy Memory Allocation and Deallocation / Helps You Remember

The AllocRemember() routine calls the Exec AllocMem() function to perform
the memory allocation.  (Of course, the application may directly call Exec
memory functions, see the chapter "Exec Memory Allocation" for details.)

AllocRemember() performs two allocations each time it is called.  The
first allocation is the actual memory requested by the application.  This
memory is of the size and type specified in the call and is independent of
the second block of memory.  The second allocation is memory for a
Remember structure which is used to save the specifics of the allocation
in a linked list.  When FreeRemember() is called it uses the information
in this linked list to free all previous memory allocations at once.  This
is convenient since normally you would have to free each memory block one
at a time which requires knowing the size and base address of each one.

The AllocRemember() call takes three arguments:

    APTR AllocRemember( struct Remember **rememberKey, unsigned long size,
                        unsigned long flags );

The rememberKey is the address of a pointer to a Remember structure.  Note
that this is a double indirection, not just a simple pointer.  The size is
the size, in bytes, of the requested allocation.  The flags argument is
the specification for the memory allocation.  These are the same as the
specifications for the Exec AllocMem() function described in the chapter
on "Exec Memory Allocation".

If AllocRemember() succeeds, it returns the address of the allocated
memory block.  It returns a NULL if the allocation fails.

The FreeRemember() function gives the option of freeing memory in either
of two ways.  The first (and most useful) option is to free both the link
nodes that AllocRemember() created and the memory blocks to which they
correspond.  The second option is to free only the link nodes, leaving the
memory blocks for further use (and later deallocation via Exec's FreeMem()
function).  But, as a general rule, the application should never free only
the link nodes as this can greatly fragment memory.  If the link nodes are
not required, use the Exec memory allocation functions.

The FreeRemember() call is as follows:

    void FreeRemember( struct Remember **rememberKey, long reallyForget );

Set the rememberKey argument to the address of a pointer to a Remember
structure.  This is the same value that was passed to previous calls to
AllocRemember().  The reallyForget argument is a boolean that should be
set to TRUE.  If TRUE, then both the link nodes and the memory blocks are
freed.  If FALSE, then only the link nodes are freed.  Again, applications
should avoid using the FALSE value since it can lead to highly fragmented
memory.


11 / Easy Memory Allocation and Deallocation / How to Remember

To use Intuition's memory functions, first create an anchor for the memory
to be allocated by declaring a variable that is a pointer to a Remember
structure and initializing that pointer to NULL.  This variable is called
the remember key.

    struct Remember *rememberKey = NULL;

Call AllocRemember() with the address of the remember key, along with the
memory requirements for the specific allocation.  Multiple allocations may
be made before a call to FreeRemember().

    memBlockA = AllocRemember(&rememberKey, SIZE_A,
                              MEMF_CLEAR | MEMF_PUBLIC);
    if (memBlockA == NULL)
        {
        /* error: allocation failed */
        printf("Memory allocation failed.\n");
        }
    else
        {
        /* use the memory here */
        printf("Memory allocation succeeded.\n");
        }

AllocRemember() actually performs two memory allocations per call, one for
the memory requested and the other for a Remember structure.  The Remember
structure is filled in with data describing the allocation, and is linked
into the list to which the remember key points.

To free memory that has been allocated, simply call FreeRemember() with
the correct remember key.

    void FreeRemember(&rememberKey, TRUE);

This will free all the memory blocks previously allocated with
AllocRemember() in a single call.


11 / Easy Memory Allocation and Deallocation / The Remember Structure

The Remember structure is defined in <intuition/intuition> as follows:

    struct Remember
        {
        struct Remember *NextRemember;
        ULONG RememberSize;
        UBYTE *Memory;
        };

Generally, the Remember structure is handled only by the system.  Here are
its fields:

    NextRemember - The link to the next Remember structure.
    RememberSize - The size of the memory tracked by this node.
    Memory       - A pointer to the memory tracked by this node.


11 Intuition Special Functions / Current Time Values

The function CurrentTime() gets the current time values.  To use this
function, first declare the variables Seconds and Micros.  Then, when the
application call the function, the current time is copied into the
argument pointers.

    void CurrentTime( ULONG *seconds, ULONG *micros );

See the DOS library Autodocs in the AmigaDOS Manual (Bantam Books) for
more information on functions dealing with the date and time.  The DOS
library includes such functions as DateToStr(), StrToDate(), SetFileDate()
and CompareDates().


11 Special Functions / Using Sprites in Intuition Windows and Screens

Sprite functionality has limitations under Intuition.  The hardware and
graphics library sprite systems manage sprites independently of the
Intuition display.  In particular:

  * Sprites cannot be attached to any particular screen.  Instead, they
    always appear in front of every screen.

  * When a screen is moved, the sprites do not automatically move with
    it. The sprites move to their correct locations only when the
    appropriate function is called (either DrawGList() or MoveSprite()).

Hardware sprites are of limited use under the Intuition paradigm.  They
travel out of windows and out of screens, unlike all other Intuition
mechanisms (except the Intuition pointer, which is meant to be global).

Remember that sprite data must be in Chip memory to be accessible to the
custom chips.  This may be done with a compiler specific feature, such as
the __chip keyword of SAS/C.  Otherwise, Chip memory can be allocated with
the Exec AllocMem() function or the Intuition AllocRemember() function,
setting the memory requirement flag to MEMF_CHIP.  The sprite data may
then be copied to Chip memory using a function like CopyMem() in the Exec
library.  See the chapter "Graphics Sprites, Bobs and Animation" for more
information.


11 Intuition Special Functions / Intuition and Preferences

The SetPrefs() function is used to configure Intuition's internal data
states according to a given Preferences structure.  This call relies on
the Preferences system used in V34 and earlier versions of the OS.  The
old system has been largely superceded in Release 2.  See the
"Preferences" chapter for details.  This routine is called only by:

  * The Preferences program itself after the user changes Preferences
    settings (under V34 and earlier).

  * AmigaDOS when the system is being booted up.  AmigaDOS opens the
    devs:system-configuration file and passes the information found there
    to the SetPrefs() routine.  This way, the user can create an
    environment and have that environment restored every time the system
    is booted.

The function takes three arguments:

    struct Preferences *SetPrefs(struct Preferences *prefbuf,
                                 long size, long realThing)

The prefbuf argument is a pointer to a Preferences structure that will be
used for Intuition's internal settings.  The  size is the number of bytes
contained in your Preferences structure.  Typically, you will use
sizeof(struct Preferences) for this argument.  The realThing argument is a
boolean TRUE or FALSE designating whether or not this is an intermediate
or final version of the Preferences.  The difference is that final changes
to Intuition's internal Preferences settings cause a global broadcast of
NEWPREFS events to every application that is listening for this event.
Intermediate changes may be used, for instance, to update the screen
colors while the user is playing with the color gadgets.

    About SetPrefs().
    -----------------
    The intended use for the SetPrefs() call is entirely to serve
    the user.  You should never use this routine to make your programming
    or design job easier at the cost of yanking the rug out from beneath
    the user.

Refer to the chapter "Preferences" for information about the Preferences
structure and the new Preferences procedure calls used in Release 2.


11 Intuition Special Functions / Function Reference

The following are brief descriptions of the Intuition functions discussed
in this chapter.  See the Amiga ROM Kernel Reference Manual: Includes and
Autodocs for details on each function call.

               Table 11-1: Other Functions for Intuition
  _____________________________________________________________________
 |                                                                     |
 |     Function                 Description                            |
 |=====================================================================|
 |  AllocRemember()  Allocate memory and track the allocation.         |
 |   FreeRemember()  Free memory allocated with AllocRemember().       |
 |---------------------------------------------------------------------|
 |      LockIBase()  Lock IntuitionBase for reading.                   |
 |    UnlockIBase()  Unlock IntuitionBase when done reading.           |
 |---------------------------------------------------------------------|
 |    CurrentTime()  Get the system time in seconds and micro-seconds. |
 |       SetPrefs()  An Intuition internal function you should try to  |
 |                   avoid.                                            |
 |_____________________________________________________________________|


Amiga® RKM Libraries: 12 Boopsi--Object Oriented Intuition

Boopsi is an acronym for Basic Object Oriented Programming System for
Intuition.  Using the Object Oriented Programming (OOP) model, Boopsi
represents certain Intuition entities, like Gadgets and Images, as objects.

There are many advantages to using Boopsi:

  * Boopsi makes Intuition customizable and extensible.  Boopsi
    programmers can create new types of Boopsi objects to suit the needs
    of their applications.  These new types of objects are part of
    Intuition and can be made public so other applications can use them.
    Because applications can share the new types, application writers
    don't have to waste their time duplicating each other's efforts
    writing the same objects.

  * New types of Boopsi objects can build on old types of Boopsi objects,
    inheriting the old object's behavior.  The result is that Boopsi
    programmers don't have to waste their time building new objects from
    scratch, they simply add to the existing object.

  * OOP and Boopsi apply the concept of interchangeable parts to
    Intuition programming.  A Boopsi programmer can combine different
    Boopsi objects (like gadgets and images) to create an entire
    Graphical User Interface (GUI).  The Boopsi programmer doesn't have
    take the time to understand or implement the inner workings of these
    objects.  The Boopsi programmer only needs to know how to interact
    with Boopsi objects and how to make them interact with each other.

  * Boopsi objects have a consistent, command-driven interface.  To the
    Boopsi programmer, there is no difference between displaying a text,
    border, or bitmap-based Boopsi image, even though they are rendered
    quite differently.  Each image object accepts a single command to
    tell it to render itself.

Before reading this chapter, you should already be familiar with several
Amiga concepts.  Boopsi is built on top of Intuition and uses many of its
structures.  These include Intuition gadgets, images, and windows.  Boopsi
also uses the tag concept  to pass parameters.  The "Utility Library"
chapter of this manual discusses tags.  The "Utility Library" chapter also
discusses callback Hooks, which are important to the later sections of
this chapter.

 OOP Overview               Boopsi Gadgets
 Creating a Boopsi Class    Function Reference


12 Boopsi--Object Oriented Intuition / OOP Overview

Understanding Boopsi requires an understanding of several of the concepts
behind Object Oriented Programming.  This section is a general overview of
these concepts as they pertain to Boopsi.  Because Boopsi is in part based
on the concepts present in the OOP language Smalltalk, a reference book on
Smalltalk may provide a deeper understanding of Boopsi in general.
Timothy Budd's book entitled A Little Smalltalk (Addison-Wesley Publishing
ISBN 0-201-10698-1) is a good start.

In the Boopsi version of the Object Oriented Programming model, everything
is an Object.  For example, a proportional gadget named myprop is an
object.  Certain objects have similar characteristics and can be
classified into groups called classes.  As objects, Rover the dog, Bob the
cat, and Sam the bird are all distinct objects but they all have something
in common, they can all be classified as animals.  As objects, myprop the
proportional gadget, mystring the string gadget, and mybutton the button
gadget all have something in common, they can all be classified as
gadgets.  A specific object is an instance of a particular class ("Rover"
is an instance of class "animal", "myslidergadget" is an instance of class
"gadget").

Notice that, although Rover, Bob, and Sam can all be classified as
animals, each belongs to a subgroup of the animal class.  "Rover" is an
instance of class "dog", "Bob" is an instance of class "cat", and "Sam" is
an instance of class "bird".  Because each of these animal types share
common characteristics, each type makes up its own class.  Because dog,
cat, and bird are subclassifications of the animal class, they are known
as subclasses of the animal class.  Conversely, the animal class is the
superclass of the dog, cat, and bird classes.

Following the branches upward from class to superclass will bring you to a
universal root category from which all objects are derived.  The OOP
language Smalltalk calls this class "Object".

                  Figure 12-1: Object Diagram

                            object
                               |
                    ___________|__________
                   /                      \
                  /                        \
               animal                  vegetables
                 |                          |
            _____|_____                _____|_____
           /     |     \              /     |     \
          /      |      \            /      |      \
        dog     cat    mouse       peas    corn  spinach

Like Smalltalk, Boopsi also has a universal root catagory, rootclass.
Currently, Intuition defines three immediate subclasses of rootclass.  The
first, gadgetclass, is the class of Boopsi gadgets.  The second class,
imageclass, makes up the class of Boopsi images.

Unlike gadgetclass and imageclass, the remaining subclass, icclass, does
not correspond to an existing Intuition entity, it is a concept new to
Intuition.  Icclass, or interconnection class, allows one Boopsi object to
notify another Boopsi object when a specific event occurs.  For example,
consider a Boopsi proportional gadget and a Boopsi image object that
displays an integer value.  An application can connect these two objects
so that the prop gadget tells the image object the prop gadget's current
value, which the image object displays.  Every time the user slides the
prop gadget, the prop gadget notifies the image of the change and the
image updates its display to reflect the prop gadget's current integer
value.  Because these objects are talking to each other rather than the
application, the updates happen automatically.  The application doesn't
have to talk to the two objects, it only has to connect them.

     Figure 12-2: Simple Boopsi Diagram

An object's characteristics and behavior are determined by its class. Each
class can define a set of attributes and a set of methods that apply to
all objects of that class.  An attribute is a variable characteristic of
an object.  For example, an attribute for the animal class could be the
number of legs an animal object has.  An example of a Boopsi attribute is
the X coordinate of a Boopsi image object.  The data that makes up the
values of an object's attributes is collectively known as the instance
data for that object.

The behavior of an object depends upon the set of methods associated to it
by its class.  A method is basically a function that applies to objects of
that class.  An example of a Boopsi method is the imageclass method
IM_DRAW.  This method tells a Boopsi image to draw itself.  All Boopsi
actions are carried out via methods.

From the Object Diagram, two of the methods of the "animal" class could be
"eat" and "sleep".  One of the methods of the "dog" class could be "bark".
Notice that instances of the "dog" class can do more than just bark, they
can also eat and sleep. This is because a subclass inherits methods from
its superclasses. If there were a subclass of dog called "attack dog", all
instances of that class would be able to bark, eat, and sleep, as well as
"attack".  Due to inheritance, a subclass has all of the methods and all
of the attributes of its superclass.  For example, the IA_Height attribute
is defined by imageclass.  All instances of the subclasses of imageclass
have their own IA_Height attribute, even though the subclasses do not
explicitly define IA_Height.  In turn, all instances of subclasses of the
imageclass subclasses also inherit the IA_Height attribute.  All classes
on levels below a class will inherit its methods and attributes.

When an application or a Boopsi object wants another Boopsi object to
perform a method, it passes it a command in the form of a Boopsi message.
A Boopsi message tells an object which method to perform.  The message may
also contain some parameters that the method requires.

    Watch Out!
    ----------
    The term "message" used in object oriented terminology can be little
    confusing to the Amiga programmer because the Boopsi message has
    nothing to do with an Exec message.

Boopsi classes can be either public or private.  Public classes have ASCII
names associated with them and are accessible to all applications.
Private classes have no ASCII name and normally can only be accessed by
the application that created the private class.

 Using Boopsi
 The Public Classes
 Making Gadget Objects Talk to Each Other
 Making Gadgets Talk to an Application
 The Interconnection Classes


12 / OOP Overview / Using Boopsi

There are several levels on which a programmer can use Boopsi.  The most
elementary level is to use Intuition functions to create and manipulate
Boopsi objects that are instances of existing, public classes.

At present there is a hierarchy of 14 public classes built into Intuition:

                        Figure 12-3: Class Diagram

                            rootclass
                               /
                 _____________/____________
                /         /                \
               /         /                  \
           icclass      /                gadgetclass
             /         /                      \
            /         /         _______________\___________________
           /     imageclass    /           /         \             \
          /         /         /           /           \             \
     modelclass    /      propgclass  strgclass  buttongclass  groupgclass
                  /                                     \
                 /                                       \
         _______/___________________________        frbuttongclass
        /         \            \            \
       /           \            \            \
  frameiclass  sysiclass  fillrectclass  itexticlass

 Boopsi and Tags
 Creating an Object
 Disposing of an Object
 Setting an Existing Object's Attributes
 Getting an Object's Attributes
 What About the Boopsi Messages and Methods?


12 / / Using Boopsi / Boopsi and Tags

Boopsi uses tag lists to pass and manipulate its attributes.  To Boopsi,
each TagItem (defined in <utility/tagitem.h>) in a tag list is an
attribute/value pair.  The TagItem.ti_Tag field contains an ID for the
attribute and the ti_Data field holds the attribute's value.

For example, the string gadget class defines an attribute called
STRINGA_LongVal, which is the current integer value of the gadget. Certain
gadgetclass objects have an attribute called GA_Image.  Its value is not
an integer, it is a pointer to an image.

Note that these tag lists can also contain utility.library Global System
control tags (like TAG_SKIP and TAG_DONE), which Boopsi uses in processing
its tag lists.  Any application that ends up processing these lists should
do so using the tag manipulation functions from utility.library.  For more
information on tags and utility.library, see the "Utility Library" chapter
of this manual.


12 / / Using Boopsi / Creating an Object

The Intuition function NewObjectA() creates a Boopsi object:

    mynewobject = APTR NewObjectA(Class *privclass, UBYTE *pubclass,
                                  struct TagItem *myattrs)

The pointer that NewObjectA() returns is a pointer to a Boopsi object.  In
general, Boopsi objects are "black boxes".  This means the inner workings
of Boopsi objects are not visible to the application programmer, so the
programmer does not know what goes on inside it.  This really means the
inner workings of these objects are none of your business.  Unless
otherwise documented, only use an object pointer as a handle to the object.

To create an object, NewObjectA() needs to know what class the new object
is an instance of.  To create a public class object, pass a NULL pointer
in privclass and an ASCII string in pubclass naming the object's public
class.  The privclass pointer is used to create a private class object,
which is covered in the "Creating a Boopsi Class" section later in this
chapter.

The myattrs tag list is a list of tag/value pairs, each of which contains
an initial value for some object attribute.  Most objects have a set of
attributes associated with them, so each attribute has a tag name.  For
Boopsi gadgets and images, the attributes include some of the values from
the old Gadget and Image structures (position, size, etc.).

Most applications use the stack-based version of NewObjectA(),
NewObject(), to create objects.  This allows an application to build the
tag list of object attributes on the stack rather than having to allocate
and initialize a tag list.  A code sample from a program that creates a
Boopsi string gadget might look like this:

    mystringgadget = (struct Gadget *)NewObject(NULL, "strgclass",
                                                GA_ID,           1L,
                                                GA_Left,         0L,
                                                GA_Top,          0L,
                                                STRINGA_LongVal, 100L,
                                                TAG_END);

If NewObject() is successful, it returns a pointer to a new Boopsi gadget
object.  Otherwise, it returns NULL.  The class "strgclass" is one of the
public classes built into Release 2.  It is a class of string gadgets.

If you look at the diagram of the public classes built into Intuition,
you'll see that strgclass is a subclass of gadgetclass. In the example
above, the attribute tag IDs that start with "GA_" are defined by
gadgetclass and not by strgclass.  This is because strgclass inherits
these attributes from its superclass, gadgetclass. The other attribute,
STRINGA_LongVal, is defined by strgclass.  It does two things.  First, it
tells the object that it is a special type of string gadget which only
handles an integer value rather than a generic ASCII string.  Second, it
passes the object its initial integer value.


12 / / Using Boopsi / Disposing of an Object

When an application is done with an object it has to dispose of the
object.  To dispose of an object, use the Intuition function
DisposeObject():

    VOID DisposeObject(APTR boopsiobject);

where boopsiobject is a pointer to the Boopsi object to be disposed.  Note
that some classes allow applications to connect child objects to a parent
object so that when the application deletes the parent object, it
automatically disposes of all of its children.  Be careful not to dispose
of an object that has already been disposed.


12 / / Using Boopsi / Setting an Existing Object's Attributes

An object's attributes are not necessarily static.  An application can ask
an object to set certain object attributes using the SetAttrs() function:

    ULONG SetAttrs(APTR myobject, Tag1, Value1, ...);

Because Boopsi gadgets require some extra information about their display,
they use a special version of this function, SetGadgetAttrs():

    ULONG SetGadgetAttrs(struct Gadget *myobject, struct Window *w,
                         struct Requester *r, Tag1, Value1, ...);

Here myobject is a pointer to the Boopsi object, w points to the gadget's
window, r points to the gadget's requester, and the tag/value pairs are
the attributes and their new values.  The return value of SetAttrs() and
SetGadgetAttrs() is class specific.  In general, if the attribute change
causes a visual change to some object, the SetAttrs()/SetGadgetAttrs()
function should return a non-zero value, otherwise, these functions should
return zero (see the Boopsi Class Reference in "Appendix B" of this manual
for information on the return values for specific classes).  The following
is an example of how to set the current integer value and gadget ID of the
gadget created in the NewObject() call above:

    SetGadgetAttrs(mystringgadget, mywindow, NULL, STRINGA_LongVal,   75L,
                                                   GA_ID,             2L,
                                                   TAG_END));

This changes two of mystringgadget's attributes.  It changes the gadget's
current integer value to 75 and it changes the gadget's ID number to 2.

Note that it is not OK to call SetGadgetAttrs() on a Boopsi object that
isn't a gadget, nor is it OK to call SetAttrs() on a Boopsi gadget.

Not all object attributes can be set with SetGadgetAttrs()/SetAttrs().
Some classes are set up so that applications cannot change certain
attributes.  For example, the imagery for the knob of a proportional
gadget cannot be altered after the object has been created.  Whether or
not a specific attribute is "settable" is class dependent.  For more
information about the attributes of specific classes, see the Boopsi Class
Reference in the Appendix B of this manual.


12 / / Using Boopsi / Getting an Object's Attributes

The Intuition function GetAttr() asks an object what the value of a
specific attribute is:

    ULONG GetAttr(ULONG attrID, APTR myobject, ULONG *mydata);

where attrID is the attribute's ID number, myobject is the object to get
the attribute from, and mydata points to a data area that will hold the
attribute value.  This function returns a 0L if the object doesn't
recognize the attribute, otherwise it returns some non-zero value, the
meaning of which depends on the class.  In most cases, GetAttr() returns a
1 when it is successful.

Not all object attributes are obtainable using the GetAttr() function.
Some classes are set up so that applications cannot query the state of
certain attributes.  For example, using the GA_Image attribute, an
application can give a Boopsi prop gadget (propgclass) an Image structure
which the gadget uses as the imagery for its knob. This attribute is not
"gettable" as there is no need for an application to have to ask the
gadget for the structure that the application passed it in the first
place.  Whether or not a specific attribute is "gettable" is class
dependent.  For more information about the attributes of specific classes,
see the Boopsi Class Reference in the Appendix B of this manual.


12 / / Using Boopsi / What About the Boopsi Messages and Methods?

According to the "OOP Overview" section, for an object to perform a
method, something has to pass it a Boopsi message.  The previous section
discussed using Intuition functions to ask an object to do things like set
and get attributes.  The functions in the previous section seem to
completely ignore all that material about methods and messages.  What
happened to the methods and messages?

Nothing--these functions don't ignore the OOP constructs, they just shield
the programmer from them.  Each of these functions corresponds to a Boopsi
method:

    NewObject()                  OM_NEW
    DisposeObject()              OM_DISPOSE
    SetAttrs()/SetGadgetAttrs()  OM_SET
    GetAttr()                    OM_GET

These methods are defined on the rootclass level, so all Boopsi classes
inherit them.  The Intuition functions that correspond to these methods
take care of constructing and sending a Boopsi message with the
appropriate method ID and parameters.


12 / OOPOverview / The Public Classes

Intuition contains 14 public classes, all of which are descendants of the
rootclass.  There are three primary classes that descend directly from
rootclass: imageclass, gadgetclass, and icclass.

 The Imageclass Subclasses    The Gadgetclass Subclasses


12 / / The Public Classes / The Imageclass Subclasses

Normally, an application does not create an imageclass object. Instead, it
will use a subclass of imageclass.  Currently, there are four subclasses:
frameiclass, sysiclass, fillrectclass, and itexticlass.

frameiclass
    An embossed or recessed rectangular frame image, that renders itself
    using the proper DrawInfo pens.  This class is intelligent enough to
    bound or center its contents.

sysiclass
    The class of system images.  The class includes the images for the
    system and GadTools gadgets.

fillrectclass
    A class of rectangle images that have frame and patternfill support.

itexticlass
    A specialized image class used for rendering text.

For more information on these classes see the Boopsi Class Reference in
the Appendix B of this manual.  It describes all of the existing public
classes, their methods, and their attributes.

 The Gadgetclass Subclasses


12 / / The Public Classes / The Gadgetclass Subclasses

Like imageclass, applications do not normally create objects of
gadgetclass, but instead create objects of its subclasses. Currently,
gadgetclass has four subclasses:

propgclass
    An easy to implement, horizontal or vertical proportional gadget.

strgclass
    A string gadget.

groupgclass
    A special gadget class that creates one composite gadget out of
    several others.

buttongclass
    A button gadget that keeps sending button presses while the user
    holds it down.

buttongclass has a subclass of its own:

frbuttonclass
    A buttongclass gadget that outlines its imagery with a frame.

For specific information on these classes, see the Boopsi Class Reference
in the Appendix B of this manual.


12 / OOP Overview / Making Gadget Objects Talk to Each Other

One use for a proportional gadget is to let the user change some integer
value, like the red, green, and blue components of a color. This type of
prop gadget is commonly accompanied by an integer string gadget, enabling
the user to adjust one integer value by either typing the value into the
string gadget or by scrolling the prop gadget.  Because these two gadgets
reflect the value of the same integer, when the user adjusts the state of
one of the gadgets (and thus changing the integer value), the other gadget
should automatically update to reflect the new integer value.

When the user manipulates a conventional gadget, the gadget sends messages
to an IDCMP port to indicate the state change (for information on IDCMP,
see the "Intuition Input and Output Methods" chapter of this manual).  To
connect the string and prop gadgets from the previous paragraph, an
application would have to listen for the IDCMP messages from two different
gadgets, interpret the IDCMP message's meaning, and manually update the
gadgets accordingly. Essentially, the application is responsible for
"gluing" the gadgets together.  This unnecessarily complicates an
application, especially when that application already has to listen for
and interpret many other events.

Boopsi gadgets simplify this.  By setting the appropriate attributes, an
application can ask a Boopsi gadget to tell some other object when its
state changes.  One of the attributes defined by gadgetclass is ICA_TARGET
(defined in <intuition/icclass.h>).  The ICA_TARGET attribute points to
another Boopsi object.  When certain attributes in a Boopsi gadget change
(like the integer value of a prop gadget), that gadget looks to see if it
has an ICA_TARGET.  If it does, it sends the target a message telling it
to perform an OM_UPDATE method.

The OM_UPDATE method is defined by rootclass.  This is basically a special
type of OM_SET method that is used specifically to tell a Boopsi object
that another Boopsi object's state changed.  Only Boopsi objects send
OM_UPDATE messages.  Note that standard classes of Boopsi gadgets only
send out OM_UPDATE messages as a result of the user changing the state of
the gadget (scrolling the prop gadget, typing a new number into an integer
gadget, etc.).  These gadgets do not send out OM_UPDATE messages when they
receive OM_SET or OM_UPDATE messages.

A Boopsi propgclass object has only one attribute that triggers it to send
an OM_UPDATE request: PGA_Top. This attribute contains the integer value
of the prop gadget.  Every time the user moves a prop gadget, the PGA_Top
attribute changes.  If the prop gadget has an ICA_TARGET, the prop gadget
will tell the target object that the PGA_Top value has changed.

A Boopsi integer string gadget (a strgclass object) also has only one
attribute that triggers it to send an OM_UPDATE request: STRINGA_LongVal.
value contains the integer value of the integer string gadget.  Like
the prop gadget, if the integer string gadget has an ICA_TARGET, when the
user changes the gadget's integer value (STRINGA_LongVal), the string
gadget will tell the target object that the STRINGA_LongVal value has
changed.

When a Boopsi gadget sends an OM_UPDATE message, it passes the ID of the
attribute that changed plus that attribute's new value.  For example, if
the user typed a 25 into a Boopsi integer string gadget, that gadget would
send an OM_UPDATE message to its ICA_TARGET saying in essence, "Hey,
STRINGA_LongVal is 25".

If this string gadget's ICA_TARGET is a propgclass object, the propgclass
object will become confused because it has no idea what a STRINGA_LongVal
attribute is.  The string gadget needs to map its STRINGA_LongVal ID to
the PGA_Top ID.  This is what the ICA_MAP attribute is for.

The ICA_MAP attribute is defined by gadgetclass (it is also defined for
icclass--more on that later).  It accepts a tag list of attribute
mappings.  When a gadget sends out an OM_UPDATE message, it uses this map
to translate a specific attribute ID to another attribute ID, without
changing the value of the attribute.  Each TagItem in the ICA_MAP makes up
a single attribute mapping. The TagItem.ti_Tag of the mapping is the ID of
an attribute to translate.  The gadget translates that attribute ID to the
attribute ID in TagItem.ti_Data.  For example, an ICA_MAP that maps a
string gadget's STRINGA_LongVal attribute to a prop gadget's PGA_Top
attribute looks like this:

    struct TagItem slidertostring[] = {
        {PGA_Top, STRINGA_LongVal},
        {TAG_END, }
    };

Note that it is OK to have an ICA_TARGET without having an ICA_MAP.  In
cases where a gadget and its ICA_TARGET have a set of attributes in
common, it would be unnecessary to use an ICA_MAP to match a gadget's
attributes, as they already match.

The following example, Talk2boopsi.c, creates a prop gadget and an integer
string gadget which update each other without the example program having
to process any messages from them.

     Talk2boopsi.c


12 / OOP Overview / Making Gadgets Talk to an Application

There are two questions that the example above brings to mind.  The first
is, "What happens if the user types a value into the string gadget that is
beyond the bounds of the prop gadget?"  The answer is simple: very little.
The prop gadget is smart enough to make sure its integer value does not go
beyond the bounds of its display.  In the example, the prop gadget can
only have values from 0 to 90.  If the user tries to type a value greater
than 90, the prop gadget will set itself to its maximum of 90.  Because
the integer string gadget doesn't have any bounds checking built into it,
the example needs to find an alternative way to check the bounds.

The other question is, "How does talk2boopsi.c know the current value of
the gadgets?"  That answer is simple too: it doesn't.  The example doesn't
ask the gadgets what their current values are (which it would do using
GetAttr()) and the example doesn't pay attention to gadget events at the
window's IDCMP port, so it isn't going to hear about them.

One easy way to hear about changes to the gadget events is to listen for a
"release verify".  Conventional Intuition gadgets can trigger a release
verify IDCMP event when the user finishes manipulating the gadget.  Boopsi
gadgets can do this, too, while continuing to update each other.

To make Talk2boopsi.c do this would require only a few changes. First, the
window's IDCMP port has to be set up to listen for IDCMP_GADGETUP events.
Next, the example needs to set the gadget's GACT_RELVERIFY flags.  It can
do this by setting the gadgetclass GA_RelVerify attribute to TRUE for both
gadgets.  That's enough to trigger the release verify message, so all
Talk2boopsi.c needs to do is account for the new type of IDCMP message,
IDCMP_GADGETUP.  When Talk2boopsi.c gets a release verify message, it can
use GetAttr() to ask the integer gadget its value.  If this value is out
of range, it should explicitly set the value of the integer gadget to a
more suitable value using SetGadgetAttrs().

Using the GACT_RELVERIFY scheme above, an application will only hear about
changes to the gadgets after the user is finished changing them.  The
application does not hear all of the interim updates that, for example, a
prop gadget generates.  This is useful if an application only needs to
hear the final value and not the interim update.

It is also possible to make the IDCMP port of a Boopsi gadget's window the
ICA_TARGET of the gadget.  There is a special value for ICA_TARGET called
ICTARGET_IDCMP (defined in <intuition/icclass.h>). This tells the gadget
to send an IDCMP_IDCMPUPDATE class IntuiMessage to its window's IDCMP
port.  Of course, the window has to be set up to listen for
IDCMP_IDCMPUPDATE IntuiMessages.  The Boopsi gadget passes an address in
the IntuiMessage.IAddress field.  It points to an attribute tag list
containing the attribute (and its new value) that triggered the
IDCMP_IDCMPUPDATE message.  An application can use the utility.library tag
functions to access the gadget's attributes in this list.  Using this
scheme, an application will hear all of the interim gadget updates.  If
the application is using a gadget that generates a lot of interim
OM_UPDATE messages (like a prop gadget), the application should be
prepared to handle a lot of messages.

Using this IDCMP_IDCMPUPDATE scheme, if the gadget uses an ICA_MAP to map
the attribute to a special dummy attribute ICSPECIAL_CODE (defined in
<intuition/icclass.h>), the IntuiMessage.Code field will contain the value
of the attribute.  Because the attribute's value is a 32-bit quantity and
the IntuiMessage.Code field is only 16 bits wide, only the least
significant 16 bits of the attribute will appear in the IntuiMessage.Code
field, so it can't hold a 32-bit quantity, like a pointer.  Applications
should only use the lower 16 bits of the attribute value.


12 / OOP Overview / The Interconnection Classes

The IDCMP_IDCMPUPDATE scheme presents a problem to an application that
wants to make gadgets talk to each other and talk to the application.
Boopsi gadgets only have one ICA_TARGET.  One Boopsi gadget can talk to
either another Boopsi object or its window's IDCMP port, but not both.
Using this scheme alone would force the application to update the integer
value of the gadgets, which is what we are trying to avoid in the first
place.

One of the standard Boopsi classes, icclass, is a class of information
forwarders.  An icclass object receives OM_UPDATE messages from one object
and passes those messages on to its own ICA_TARGET.  If it needs to map
any incoming attributes, it can use its own ICA_MAP to do so.

Icclass has a subclass called modelclass.  Using a modelclass object, an
application can chain a series of these objects together to set up a
"broadcast list" of icclass objects.  The modelclass object is similar to
the icclass object in that it has its own ICA_TARGET and ICA_MAP.  It
differs in that an application can use the modelclass OM_ADDMEMBER method
to add icclass objects to the modelclass object's broadcast list.

The OM_ADDMEMBER method is defined by rootclass.  It adds one Boopsi
object to the personal list of another Boopsi object.  It is up to the
Boopsi object's class to determine the purpose of the objects in the list.
Unlike the other methods mentioned so far in this chapter, OM_ADDMEMBER
does not have an Intuition function equivalent.  To pass an OM_ADDMEMBER
message to an object use the amiga.lib function DoMethodA(), or its
stack-based equivalent, DoMethod():

    ULONG DoMethodA(Object *myobject, Msg boopsimessage);
    ULONG DoMethod(Object *myobject, ULONG methodID, ...);

The return value is class-dependent.  The first argument to both of these
functions points to the object that will receive the Boopsi message.

For DoMethodA(), boopsimessage is the actual Boopsi message.  The layout
of it depends on the method.  Every method's message starts off with an
Msg (from <intuition/classusr.h>):

    typedef struct {
        ULONG MethodID; /* Method-specific data may follow this field */
    } *Msg;

The message that the OM_ADDMEMBER method uses looks like this (from
<intuition/classusr.h>):

    struct opMember {
        ULONG    MethodID;
        Object   *opam_Object;
    };

where MethodID is OM_ADDMEMBER and opam_Object points to the object to add
to myobject's list.

DoMethod() uses the stack to build a message.  To use DoMethod(), just
pass the elements of the method's message structure as arguments to
DoMethod() in the order that they appear in the structure.  For example,
to ask the Boopsi object myobject to add the object addobject to its
personal list:

    DoMethod(myobject, OM_ADDMEMBER, addobject);

To rearrange Talk2boopsi.c so that it uses a modelclass object (also known
as a model):

  * Create the integer and prop gadget.

  * Create the model.

  * Create two icclass objects, one called int2prop and the other called
    prop2int.

  * Make the model the ICA_TARGET of both the integer gadget and the prop
    gadget.  The gadgets do not need an ICA_MAP.

  * Using DoMethod() to call OM_ADDMEMBER, add the icclass objects to the
    model's personal list.

  * Make the prop gadget the ICA_TARGET of int2prop.  Make the integer
    gadget the ICA_TARGET of prop2int.

  * Create an ICA_MAP map list for int2prop that maps STRINGA_LongVal to
    PGA_Top.  Create an ICA_MAP map list for prop2int that maps PGA_Top
    to STRINGA_LongVal.  Make the ICA_TARGET of the model ICTARGET_IDCMP.

Diagrammatically, the new Talk2boopsi.c should look something like this:

     Figure 12-4: ICC Diagram

When either of these gadgets has some interim state change (caused by the
user manipulating the gadgets), it sends an OM_UPDATE message to its
ICA_TARGET, which in this case is the modelclass object.  When this model
gets the message, it does two things.  It sends an IDCMP_IDCMPUPDATE to
the IDCMP port of the gadget's window and it also sends OM_UPDATE messages
to all of the objects in its personal list.  When int2prop gets an
OM_UPDATE message, it forwards that message to its ICA_TARGET, the prop
gadget.  Similarly, when prop2int gets an OM_UPDATE message, it forwards
that message to its ICA_TARGET, the integer gadget.

Although in this case it isn't a problem, icclass and modelclass objects
contain loop inhibition capabilities.  If an icclass object (or modelclass
object) receives an OM_UPDATE message, it forwards the message to its
target.  If somehow that forwarded message gets forwarded (or broadcast)
back to the icclass object, the icclass object ignores the message.  This
prevents the possibility of an infinite OM_UPDATE loop.


12 Boopsi--Object Oriented Intuition / Creating a Boopsi Class

So far this chapter has only hinted at what is possible with Boopsi. Its
power lies in its extensibility.  Boopsi grants the application programmer
the power to add custom features to existing classes.  If an existing
class comes close to your needs, you can build on that class so it does
exactly what you want.  If you want a class that is unlike an existing
class, you can create it.

The heart of a Boopsi class is its method Dispatcher function. According
to the OOP metaphor, when an application wants a Boopsi object to perform
a method, it sends the object a message.  In reality, that object is only
a data structure, so it does not have the power to do anything.  When an
object receives a Boopsi message, a Boopsi message structure is passed to
the dispatcher of that object's class.  The dispatcher examines the
message and figures out what to do about it.

For example, when an application calls SetGadgetAttrs() on an integer
gadget:

    SetGadgetAttrs(myintegergadget, mywindow, NULL,
                   STRINGA_LongVal, 75L,
                   GA_ID,           2L,
                   TAG_END));

the SetGadgetAttrs() function calls the strgclass dispatcher.  A Boopsi
dispatcher receives three arguments: a pointer to the dispatcher's Class
(defined in <intuition/classes.h>), a pointer to the object that is going
to perform the method, and a pointer to the Boopsi message.  In this case,
the SetGadgetAttrs() function builds an OM_SET message, finds the
strgclass dispatcher, and "sends" the dispatcher the OM_SET message.
SetGadgetAttrs() can find the dispatcher because an object contains a
reference to its dispatcher.

When the dispatcher function "gets" the message, it examines the message
to find out its corresponding method.  In this case, the dispatcher
recognizes the message as an OM_SET message and proceeds to set
myintegergadget's attributes.

An OM_SET message looks like this (defined in <intuition/classusr.h>):

    struct opSet {
        ULONG MethodID;               /* This will be set to OM_SET      */
        struct TagItem *ops_AttrList; /* A tag list containing the       */
                                      /*     attribute/value pairs of    */
                                      /*     the attributes to set.      */
        struct GadgetInfo *ops_GInfo; /* Special information for gadgets */
    }

The OM_SET message contains a pointer to a tag list in ops_AttrList that
looks like this:

    {STRINGA_LongVal, 75L},
    {GA_ID, 2L},
    {TAG_END,}

The strgclass dispatcher scans through this tag list and recognizes the
STRINGA_LongVal attribute.  The dispatcher sets myintegergadget's internal
STRINGA_LongVal value to the corresponding value (75L) from the
attribute/value pair.

The strgclass dispatcher continues to scan through the tag list.  When it
finds GA_ID, it does not process it like STRINGA_LongVal.  The strgclass
dispatcher's OM_SET method does not recognize the GA_ID attribute because
strgclass inherited the GA_ID attribute from gadgetclass.  To handle
setting the GA_ID attribute, the strgclass dispatcher passes on the OM_SET
message to its superclass's dispatcher.  The strgclass dispatcher passes
control to the gadgetclass dispatcher, which knows about the GA_ID
attribute.

 Building On Existing Public Classes
 Writing the Dispatcher
 White Boxes - The Transparent Base Classes


12 / Creating a Boopsi Class / Building On Existing Public Classes

A program can create its own subclasses which build on the features of
existing classes.  For example, a program could create a subclass of
modelclass named rkmmodelclass.  Rkmmodelclass builds on modelclass by
adding a new attribute called RKMMOD_CurrVal.  This purpose of this
attribute is simply to hold an integer value.

Because this new attribute is built into an rkmmodel object, the object
could be implemented so that it exercises a certain amount of control over
that value.  For example, rkmmodelclass could be implemented so an
rkmmodel performs bounds checking on its internal value.  When an
application asks an rkmmodel to set its internal RKMMOD_CurrVal, the
rkmmodel makes sure the new value is not beyond a maximum value.  If the
new value is beyond the maximum, it sets its current value to the maximum.
After the rkmmodelclass object has set its internal RKMMOD_CurrVal, it can
broadcast the change on to objects in its broadcast list.

The dispatcher for rkmmodelclass does not have to do a lot of work because
it inherits most of its behavior from its superclasses.  The rkmmodelclass
has to take care of setting aside memory for the RKMMOD_CurrVal attribute
and processing any OM_SET requests to set the RKMMOD_CurrVal attribute.
For any other attributes or methods, the rkmmodelclass dispatcher passes
on processing to its superclass, modelclass.

 Building Rkmmodelclass


12 / / Building On Existing Public Classes / Building Rkmmodelclass

So far, the theoretical class rkmmodelclass has just one attribute,
RKMMOD_CurrVal.  A couple of extra attributes can make it more useful.
Because the rkmmodel object maintains an upper limit on its RKMMOD_CurrVal
integer value, it would be useful if that upper limit was variable.  Using
a new attribute, RKMMOD_Limit, an application can tell a rkmmodel what its
upper limit is.  The rkmmodel will enforce the limit internally, so the
application doesn't have to worry about it.

Another useful addition is a pulse increment and decrement for
RKMMOD_CurrVal.  Whenever the model receives an increment or decrement
command, it increments or decrements its internal value. To make the
example class simple, rkmmodelclass implements incrementing and
decrementing by creating "dummy" attributes called RKMMOD_Up and
RKMMOD_Down.  When an rkmmodel receives an OM_SET message for one of these
attributes, it increments or decrements RKMMOD_CurrVal.  An rkmmodelclass
object does not care what the value of the RKMMOD_Up and RKMMOD_Down
attributes are, it only cares that it received an OM_UPDATE about it.

There are two pieces of data that make up this new class's instance data:
the rkmmodel's current value (RKMMOD_CurrVal) and the upper limit of the
rkmmodel (RKMMOD_Limit).  The example class consolidates them into one
structure:

    struct RKMModData {
        ULONG currval;
        ULONG vallimit;
    };


12 / Creating a Boopsi Class / Writing the Dispatcher

The C prototype for a Boopsi dispatcher looks like this:

    ULONG dispatchRKMModel(Class *cl, Object *recvobject, Msg msg);

where cl points to the Class (defined in <intuition/classes.h>) of the
dispatcher, recvobject points to the object that received the message, and
msg is that Boopsi message.  The format of the message varies according to
the method.  The default Boopsi message is an Msg (from
<intuition/classusr.h>):

    typedef struct {
        ULONG MethodID;
    } *Msg;

Boopsi methods that require parameters use custom message structures. The
first field of any message structure is always the method's methodID.
This makes custom messages look like an Msg.  The dispatcher looks at an
incoming message's first field to tell what its method is.  Rkmmodelclass
objects respond to several rootclass methods:

OM_NEW
    This method creates a new rkmmodelclass object.  It uses an opSet
    structure as its Boopsi message.

OM_DISPOSE
    This method tells an object to dispose of itself.  It uses an Msg as
    its Boopsi message.

OM_SET
    This method tells an object to set one or more of its attribute
    values.  It uses an opSet structure as its Boopsi message.

OM_UPDATE
    This method tells an object to update one or more of its attribute
    values.  It uses an opUpdate structure as its Boopsi message.

OM_GET
    This method tells an object to report an attribute value.  It uses an
    opGet structure as its Boopsi message.

OM_ADDTAIL
    This method tells an object to add itself to the end of an Exec list.
    It uses an opAddTail structure as its Boopsi message.

OM_REMOVE
    This method tells an object to remove itself from an Exec list.  It
    uses an Msg as its Boopsi message.

OM_ADDMEMBER
    This method tells an object to add an object to its broadcast list.
    It uses an opMember structure as its Boopsi message.

OM_REMMEMBER
    This method tells an object to remove an object from its broadcast
    list.  It uses an opMember structure as its Boopsi message.

OM_NOTIFY
    This method tells an object to broadcast an attribute change to its
    broadcast list.  It uses an opSet structure as its Boopsi message.

Of these, rkmmodelclass has to process OM_NEW, OM_SET, OM_UPDATE, and
OM_GET.

 OM_NEW              OM_GET                  RKMModel.c
 OM_SET/OM_UPDATE    Making the New Class


12 / / Writing The Dispatcher / OM_NEW

The OM_NEW method returns a pointer to a newly created Boopsi object, or
NULL if it failed to create the object.  This method receives the
following message structure (defined in <intuition/classusr.h>):

    /* The OM_NEW method uses the same structure as OM_SET */

    struct opSet {
        ULONG             MethodID;
        struct TagItem    *ops_AttrList;
        struct GadgetInfo *ops_GInfo;
    };

The ops_AttrList field contains a pointer to a TagItem array of
attribute/value pairs.  These contain the initial values of the new
object's attributes.  The ops_GInfo field is always NULL for the OM_NEW
method.

Unlike other methods, when a dispatcher gets an OM_NEW message, the object
pointer (recvobject from the dispatchRKMModel() prototype above) does not
point to an object.  It doesn't make sense for recvobject to point to an
object because the idea is to create a new object, not act on an existing
one.

The pointer normally used to pass a Boopsi object is instead used to pass
the address of the object's "true class".  An object's true class is the
class of which the object is an instance.

The first thing the dispatcher does when it processes an OM_NEW message is
pass the OM_NEW message on to its superclass's dispatcher. It does this
using the amiga.lib function DoSuperMethodA():

    ULONG DoSuperMethodA(Class *cl, Object *trueclass, Msg msg);

Each dispatcher passes control to its superclass.  Eventually the message
will arrive at the rootclass dispatcher.  The OM_NEW method in the
rootclass dispatcher looks at the object's true class (trueclass from the
prototype) to find out which class dispatcher is trying to create a new
object.  Note that trueclass is not necessarily the same as the current
dispatcher's class (cl from the dispatchRKMModel() prototype above),
although this would be the case if the object's true class is a subclass
of the current dispatcher's class.

The rootclass dispatcher uses the true class to find out how much memory
to allocate for the object's instance data.  Each class keeps a record of
how much memory its local instance data requires.  The rootclass
dispatcher also looks at each class between the true class and rootclass
to find out much memory the local instance data for those classes require.
The rootclass dispatcher totals the amount of local instance data memory
needed by the true class and each of its superclasses and allocates that
much memory.

If all goes well, the rootclass dispatcher increments a private field in
the true class that keeps track of how many instances of the true class
there currently are.  It then returns a pointer to the newly created
object and passes control back to the subclass dispatcher that called it,
which is icclass in the case of rkmmodelclass.  If there was a problem,
the rootclass dispatcher does not increment the object count and passes
back a NULL.

When the rootclass dispatcher returns, the icclass dispatcher regains
control from DoSuperMethodA().  DoSuperMethodA() will return either a
pointer to the new object or else it returns NULL if there was an error.
Although the rootclass dispatcher allocated all the memory the object
needs, it only initialized the instance data local to rootclass. Now it's
the icclass dispatcher's turn to do some work.  It has to initialize the
instance data that is local to icclass.

A dispatcher finds its local instance data by using the INST_DATA() macro
(defined in <intuition/classes.h>):

   void *INST_DATA(Class *localclass, Object *object);

INST_DATA() takes two arguments, a pointer to a class and a pointer to the
object.  The INST_DATA() macro returns a pointer to the instance data
local to localclass.  When the icclass dispatcher was called, it received
three arguments, one of which was a pointer to the local class (icclass).
The icclass dispatcher passes this pointer and the new object pointer it
got from DoSuperMethodA() to INST_DATA() to get a pointer to the instance
data local to icclass.

After initializing its local instance data, the icclass dispatcher passes
control back to the modelclass dispatcher, which in turn, initializes the
instance data local to modelclass.  Finally, the rkmmodelclass dispatcher
regains control and now has to take care of its local instance data.

To find its local instance data, the rkmmodelclass dispatcher needs a
pointer to its Class and a pointer to the new object.  The dispatcher
function gets its Class pointer as its first argument (cl from the
dispatchRKMModel() prototype above).  It gets the new object pointer as
the return value from DoSuperMethodA().  In this case, INST_DATA() returns
a pointer to an RKMModData structure.

Now the dispatcher has to initialize its local instance data.  It has to
scan through the tag list passed in the OM_NEW message looking for initial
values for the RKMMOD_CurrVal and RKMMOD_Limit attributes. As an
alternative, the dispatcher's OM_NEW method can use its OM_SET method to
handle initializing these "settable" attributes.

Finally, the dispatcher can return.  When the dispatcher returns from an
OM_NEW method, it returns a pointer to the new object.

If the OM_NEW method fails, it should tell the partially initialized
object it got from its superclass's dispatcher to dispose of itself (using
OM_DISPOSE) and return NULL.


12 / / Writing The Dispatcher / OM_SET/OM_UPDATE

For the OM_SET message, the rkmmodelclass dispatcher steps through the
attribute/value pairs passed to it in the OM_SET message looking for the
local attributes (see OM_NEW for the OM_SET message structure).  The
RKMMOD_Limit attribute is easy to process.  Just find it and record the
value in the local RKMModData.vallimit field.

Because the function of the rkmmodelclass's OM_SET and OM_UPDATE methods
are almost identical, the rkmmodelclass dispatcher handles them as the
same case.  The only difference is that, because the OM_UPDATE message
comes from another Boopsi object, the OM_UPDATE method can report on
transitory state changes of an attribute.  For example, when the user
slides a Boopsi prop gadget, that prop gadget sends out an interim
OM_UPDATE message for every interim value of PGA_Top.  When the user lets
go of the prop gadget, the gadget sends out a final OM_UPDATE message.
The OM_UPDATE message is almost identical to the OM_SET message:

    #define OPUF_INTERIM    (1<<0)

    /* the OM_NOTIFY method uses the same structure */

    struct opUpdate {
        ULONG             MethodID;
        struct TagItem    *opu_AttrList;
        struct GadgetInfo *opu_GInfo;
        ULONG             opu_Flags;      /* The extra field */
    };

A dispatcher can tell the difference between an interim and final
OM_UPDATE message because the OM_UPDATE message has an extra field on it
for flags.  If the low order bit (the OPUF_INTERIM bit) is set, this is an
interim OM_UPDATE message.  The interim flag is useful to a class that
wants to ignore any transitory messages, processing only final attribute
values.  Because rkmmodelclass wants to process all changes to its
attributes, it processes all OM_UPDATE messages.

The RKMMOD_CurrVal attribute is a little more complicated to process. The
dispatcher has to make sure the new current value is within the limits set
by RKMMOD_Limit, then record that new value in the local
RKMModData.currval field.  Because other objects need to hear about
changes to RKMMOD_CurrVal,  the dispatcher has to send a notification
request.  It does this by sending itself an OM_NOTIFY message.  The
OM_NOTIFY message tells an object to notify its targets (its ICA_TARGET
and the objects in its broadcast list) about an attribute change.  The
OM_NOTIFY method does this by sending OM_UPDATE messages to all of an
object's targets.

The rkmmodelclass dispatcher does not handle the OM_NOTIFY message itself.
It inherits this method from modelclass, so the rkmmodelclass dispatcher
passes OM_NOTIFY messages on to its superclass. To notify its targets, the
rkmmodelclass dispatcher has to construct an OM_NOTIFY message.  The
OM_NOTIFY method uses the same message structure as OM_UPDATE.  Using the
stack-based version of DoSuperMethodA(), DoSuperMethod(), the dispatcher
can build an OM_NOTIFY message on the stack:

     . . .

    struct TagItem tt[2];
    struct opUpdate *msg;
     . . .

    tt[0].ti_Tag  = RKMMOD_CurrVal;  /* make a tag list.  */
    tt[0].ti_Data = mmd->currval;
    tt[1].ti_Tag  = TAG_END;

    DoSuperMethod(cl, o, OM_NOTIFY, tt, msg->opu__GInfo,
                  ((msg->MethodID == OM_UPDATE) ? (msg->opu_Flags) : 0L));
     . . .

Because the OM_NOTIFY needs a tag list of attributes about which to issue
updates, the dispatcher builds a tag list containing just the
RKMMOD_CurrVal tag and its new value.  The dispatcher doesn't use the tag
list passed to it in the OM_UPDATE/OM_NOTIFY message because that list can
contain many other attributes besides RKMMOD_CurrVal.

The msg variable in the DoSuperMethod() call above is the OM_SET or
OM_UPDATE message that was passed to the dispatcher.  The dispatcher uses
that structure to find a pointer to the GadgetInfo structure that the
OM_NOTIFY message requires.  The GadgetInfo structure comes from Intuition
and contains information that Boopsi gadgets need to render themselves.
For the moment, don't worry about what the GadgetInfo structure actually
does, just pass it on.  The targets of an rkmmodel will probably need it.

Notice that the dispatcher has to test to see if the message is an OM_SET
or OM_UPDATE so it can account for the opu_Flags field at the end of the
OM_UPDATE message.

Processing the RKMMOD_Up and RKMMOD_Down attributes is similar to the
RKMMOD_CurrVal attribute.  When the dispatcher sees one of these, it has
to increment or decrement the local RKMModData.currval, making sure
RKMModData.currval is within limits.  The dispatcher then sends an
OM_NOTIFY message to the superclass about the change to RKMModData.currval.

The return value from the dispatcher's OM_SET method depends on the what
effect the attribute change has to the visual state of the objects in the
rkmmodel's broadcast list.  If an attribute change will not affect the
visual state of the rkmmodel's objects, the OM_SET method returns zero.
If the attribute change could trigger a change to the rkmmodel's objects,
it returns something besides zero. For example, the rkmmodelclass OM_SET
method returns 1L if an rkmmodel's RKMMOD_CurrVal, RKMMOD_Up, or
RKMMOD_Down attribute is changed.

At some point the rkmmodelclass dispatcher has to allow its superclasses
to process these attributes it inherits.  Normally a dispatcher lets the
superclass process its attributes before attempting to process any local
attributes.  The rkmmodelclass dispatcher does this by passing on the
OM_SET or OM_UPDATE message using DoSuperMethodA() (inheritance at work!).
As an alternative, the dispatcher can use the amiga.lib function
SetSuperAttrs().  See the amiga.lib Autodocs for more details on this
function.


12 / / Writing The Dispatcher / OM_GET

The rkmmodel only has one "gettable" attribute: RKMMOD_CurrVal, which
makes processing it easy.  The OM_GET message looks like this (defined in
<intuition/classusr.h>):

    struct opGet {
        ULONG MethodID;     /* OM_GET */
        ULONG opg_AttrID;   /* The attribute to retrieve */
        ULONG *opg_Storage; /* a place to put the attribute's value */
    };

When the rkmmodelclass dispatcher receives an OM_GET message with an
opg_AttrID equal to RKMMOD_CurrVal, it copies the current value
(RKMModData).currval to the memory location opg_Storage points to and
returns a value of TRUE.  The TRUE indicates that there was no error.  If
opg_AttrID is not RKMMOD_CurrVal, the dispatcher should let its superclass
handle this message.

The rkmmodelclass dispatcher can take advantage of the fact that the only
"gettable" attribute available to an rkmmodel is RKMMOD_CurrVal (the
attributes defined by modelclass and icclass are not gettable--see the
Boopsi Class Reference in the Appendix B of this manual for more details
on which attributes are "settable", "gettable", etc.).  If opg_AttrID is
not RKMMOD_CurrVal, the rkmmodelclass dispatcher can return FALSE,
indicating that the attribute was not "gettable".

If the rkmmodelclass dispatcher comes across any other messages besides
OM_NEW, OM_SET, OM_UPDATE, and OM_GET message, it blindly passes them on
to its superclass for processing.


12 / / Writing The Dispatcher / Making the New Class

The Intuition function MakeClass() creates a new Boopsi class:

    Class *MakeClass(UBYTE *newclassID, UBYTE *pubsuperclassID,
                     Class *privsuperclass, UWORD instancesize,
                     ULONG flags);

If the new class is going to be public, newclassID is a string naming the
new class.  If the new class is private, this field is NULL.  The next two
fields tell MakeClass() where to find the new class's superclass.  If the
superclass is public, pubsuperclassID points to a string naming that
public superclass and the privsuperclass pointer is NULL.  If the
superclass is private, privsuperclass points to that superclass's Class
structure and pubsuperclassID is NULL. The size of the new class's local
instance data is instancesize.  The last parameter, flags, is for future
enhancement.  For now, make this zero.

If it is successful, MakeClass() returns a pointer to the new class,
otherwise it returns NULL.  When MakeClass() is successful, it also takes
measures to make sure no one can "close" the new class's superclass (using
FreeClass()).  It does this by incrementing a private field of the
superclass that keeps track of how many subclasses the superclass
currently has.

After successfully creating a class, an application has to tell the class
where its dispatcher is. The Class pointer (defined in
<intuition/classes.h>) returned by MakeClass() contains a Hook structure
called cl_Dispatcher, which is used to call the dispatcher.  The
application has to initialize this hook:

    myclass->cl_Dispatcher.h_Entry = HookEntry;
    /* HookEntry() is defined in amiga.lib */

    myclass->cl_Dispatcher.h_SubEntry = dispatchRKMModel;

The h_Entry field points to a function in amiga.lib that copies the
function arguments to where the dispatcher expects them. See the
"Callback Hooks" section of the "Utility Library" chapter of this manual for
more details.

To make a class public instead of private, an application has to call
AddClass() in addition to giving the class a name in MakeClass().
AddClass() takes one argument, a pointer to a valid Class structure that
has been initialized as a public class by MakeClass().  To remove a public
class added to the system with AddClass(), pass the public class pointer
to RemoveClass().  See the Intuition Autodocs for more details on
AddClass() and RemoveClass().


12 / / Writing The Dispatcher / RKMModel.c

The following code, RKMModel.c,  makes up an initialization function and
the dispatcher function for a private class informally called
rkmmodelclass.

     RKMModel.c

Below is a diagram showing how an application could use an rkmmodelclass
object:

     Figure 12-5: Rkmmodelclass Object Diagram

In this diagram, the application uses buttongclass Boopsi gadgets to send
the rkmmodelclass the RKMMOD_Up and RKMMOD_Down attribute pulses.

The example takes advantage of an odd feature of buttongclass.  When the
user clicks on a buttongclass gadget, it sends an OM_UPDATE to its
ICA_TARGET, even though no Boopsi attribute of buttongclass has changed.
It does this because it's a convenient way to report button clicks.

Whenever a gadget sends a notification, the list of attribute/value pairs
in the OM_NOTIFY message always contains the gadget's GA_ID. This is an
easy way for the button to inform its target of its ID so the target knows
which gadget sent the OM_UPDATE message.  When a buttongclass sends a
notification because of a button click, it only sends out an OM_UPDATE
about its GA_ID because none of its attributes changed.

When the user clicks one of the buttons in the rkmmodelclass diagram, the
button uses an ICA_MAP to map its GA_ID to one of the "dummy" pulse
attributes, RKMMOD_Up and RKMMOD_Down.  When the rkmmodel receives the
OM_UPDATE message about RKMMOD_Up or RKMMOD_Down, it increments or
decrements its internal value.

There is one more important thing to note about rkmmodelclass. Looking at
the rkmmodelclass Object diagram above, an rkmmodel's RKMMOD_CurrVal
changes because it received an OM_UPDATE message from one of its gadgets.
RKMMOD_CurrVal can also change if the application explicitly set
RKMMOD_CurrVal using SetAttrs() or SetGadgetAttrs().

The primary difference between the OM_SET message that SetAttrs() sends
and the OM_SET message that SetGadgetAttrs() sends is that SetAttrs()
passes a NULL in opSet.ops_GInfo instead of a GadgetInfo pointer.  This
doesn't present a problem for the rkmmodel object, because it doesn't use
the GadgetInfo structure.  The problem is that when the rkmmodel notifies
its targets, some of which are gadgets, they can't update their visual
state because they need a GadgetInfo to render themselves.  For this
reason, the rkmmodelclass dispatcher returns a positive non-zero value
when an attribute change occurs that could cause a change in the visual
state of any objects in its broadcast list.  An application that uses
rkmmodelclass must test the return value when calling SetAttrs() on an
rkmmodelclass object to tell if the attribute change requires a visual
refresh of the gadgets (see the Intuition Autodocs for RefreshGadgets()).

    Boopsi Dispatchers Can Execute on Intuition's Context.
    ------------------------------------------------------
    Notice that the gadgets in the figure above send OM_UPDATE messages
    to the rkmmodel when the user manipulates them.  Because Intuition
    handles the user input that triggers the OM_UPDATE messages,
    Intuition itself is sending the OM_UPDATE messages.  This means the
    rkmmodelclass dispatcher must be able to run on Intuition's context,
    which puts some limitations on what the dispatcher is permitted to
    do: it can't use dos.library, it can't wait on application signals or
    message ports, and it can't call any Intuition functions which might
    wait on Intuition.

Although rkmmodelclass serves as an example of a class, it leaves a little
to be desired in a real-world implementation.  To create the
"prop-integer-up/down" super gadget from the diagram above, the
application has to create, initialize, and link nine Boopsi objects, which
is tedious, especially if the application needs several of these super
gadgets.  Ideally, all these functions would be rolled into some subclass
of gadgetclass.  If there were such a class, an application would only
have to create one instance of this subclass to get such a gadget.  When
the subclass received an OM_NEW message, it would take care of creating,
initializing, and linking all of the Boopsi objects that make up the whole
super gadget.


12 / Boopsi Class / White Boxes - The Transparent Base Classes

Boopsi gadgets and images were designed to be backwards compatible with
the old Intuition Gadgets and Images, so as part of their instance data,
both types of objects have the old Intuition structures built into them.
When NewObject() creates a new gadget or image object, the pointer it
returns points to the object's embedded Gadget or Image corresponding
structure. Because Intuition can tell the difference between Boopsi images
and gadgets and the original images and gadgets, applications can use
Boopsi images and gadgets interchangeably with the older Intuition
entities.

Although normally considered a "programming sin", in some cases it is
legal for class dispatchers to directly manipulate some internal fields of
certain Boopsi objects.  For compatibility reasons, a Boopsi image or
gadget object contains an actual Image or Gadget structure.  These objects
are instances of the Transparent Base Classes, imageclass and gadgetclass.

To change an attribute of a Boopsi object, you normally invoke the set
method, OM_SET.  The Intuition functions SetAttrs() and SetGadgetAttrs()
invoke this method.  A Boopsi class is informed of any attribute change at
that time, allowing it to react to this change.  The reaction can include
validating the changed attribute, changing other attributes to match, or
informing other objects of the change.  That is the inherent advantage of
using function calls to change attributes.

When using conventional images and gadgets, you generally modify the
structure's fields directly.  This operation is very fast.  For
conventional images and gadgets, there is no class that needs to know
about the changes, so there is no problem.  However, this is untrue of
Boopsi images and gadgets.  Although directly modifying the Boopsi
object's internal structure would provide a performance increase over
using the Boopsi OM_SET mechanism, altering a Boopsi object's internal
structure directly will not give the class the opportunity to react to any
structure changes.  This violates the Boopsi concept, and therefore cannot
be done in general.

In order to provide a balance between the flexibility of function-access
and the performance of direct-access, the transparent base classes
imageclass and gadgetclass do not depend on being informed of changes to
certain fields in the internal Image and Gadget structures.  This means
that it is OK for the dispatchers of direct subclasses of imageclass and
gadgetclass to modify specific fields of Boopsi images or gadgets.
Applications and indirect subclass dispatchers of imageclass or
gadgetclass may not modify those fields, since their parent classes may
depend on hearing about changes to these fields, which the SetAttrs() call
(or a similar function) provides.

For dispatchers of direct subclasses of imageclass, the following are the
only fields of the Image structure that are alterable:

    LeftEdge      Width     ImageData
    TopEdge       Height    PlanePick
    PlaneOnOff

For dispatchers of direct subclasses of gadgetclass, the following are the
only fields of the Gadget structure that are alterable:

    LeftEdge    Flags           GadgetText
    TopEdge     GadgetType      SpecialInfo
    Width       GadgetRender    Activation
    Height      SelectRender

Under no circumstances may an application or an indirect subclass modify
one of these fields, even if the subclass knows the superclasses do not
depend on notification for this field.  This is the only way to preserve
the possibility for future enhancements to that superclass.  Note that
these fields are not alterable while the gadget or image object is in use
(for example, when it is attached to a window).


12 Boopsi--Object Oriented Intuition / Boopsi Gadgets

One of the major enhancements to Intuition for Release 2 is the
implementation of customizable Boopsi gadgets.  Boopsi gadgets are not
limited by dependencies upon Intuition Image and Gadget structures.
Unlike Release 1.3 gadgets, which were handled exclusively by Intuition,
Boopsi gadgets handle their own rendering and their own user input.

Since Boopsi gadgets draw themselves, there is almost no restriction on
what they can look like.  A Boopsi gadget can use graphics.library
RastPort drawing functions to draw vector-based imagery which the gadget
can scale to any dimension.  Instead of just a two-state Boolean gadget, a
Boopsi gadget can have any number of states, each of which has its own
imagery.  If a programmer wanted to he could even make a Boopsi gadget
that uses the animation system to render itself.

Because Boopsi gadgets handle their own input, they see all the user's
input, which the gadget is free to interpret.  While the user has a Boopsi
gadget selected, the gadget can track mouse moves, process mouse and
keyboard key presses, or watch the timer events.

The power of a Boopsi gadget is not limited to its ability to handle its
own rendering and user input.  Boopsi gadgets are also Boopsi objects so
the gain all the benefits Boopsi provides.  This means all Boopsi gadgets
inherit the methods and attributes from their superclasses.  Boopsi
gadgets can use Boopsi images to take care of rendering their imagery.  A
Boopsi gadget could be a "composite" gadget that is composed of several
Boopsi gadgets, images, and models.

 The Boopsi Gadget Methods    The Active Gadget


12 / Boopsi Gadgets / The Boopsi Gadget Methods

Intuition drives a Boopsi gadget by sending it Boopsi messages. Intuition
uses a series of five Boopsi methods:

GM_RENDER       This method tells the gadget to render itself.

GM_HITTEST      This method asks a gadget whether it has been "hit" by a
                mouse click.

GM_GOACTIVE     This method asks a gadget if it wants to be the active
                gadget.

GM_HANDLEINPUT  This method passes a gadget an input event.

GM_GOINACTIVE   This method tells a gadget that it is no longer active.

The formats of each of these Boopsi messages differ, but they all have two
things in common.  Like all Boopsi messages, each starts with their
respective method ID.  For each of these methods, the method ID field is
followed by a pointer to a GadgetInfo structure (defined in
<intuition/cghooks.h>).  The GadgetInfo structure contains information
about the display on which the gadget needs to render itself:

struct GadgetInfo {
    struct Screen          *gi_Screen;
    struct Window          *gi_Window;     /* null for screen gadgets */
    struct Requester       *gi_Requester;  /* null if not GTYP_REQGADGET */

    /* rendering information: don't use these without cloning/locking.
     * Official way is to call ObtainGIRPort()
     */
    struct RastPort        *gi_RastPort;
    struct Layer           *gi_Layer;

    /* copy of dimensions of screen/window/g00/req(/group)
     * that gadget resides in.  Left/Top of this box is
     * offset from window mouse coordinates to gadget coordinates
     *  screen gadgets:                 0,0 (from screen coords)
     *  window gadgets (no g00):        0,0
     *  GTYP_GZZGADGETs (borderlayer):  0,0
     *  GZZ innerlayer gadget:          borderleft, bordertop
     *  Requester gadgets:              reqleft, reqtop
     */
    struct IBox            gi_Domain;

    /* these are the pens for the window or screen */
    struct {
        UBYTE   DetailPen;
        UBYTE   BlockPen;
    }                      gi_Pens;

    /* the Detail and Block pens in gi_DrInfo->dri_Pens[] are
     * for the screen.  Use the above for window-sensitive colors.
     */
    struct DrawInfo        *gi_DrInfo;

    /* reserved space: this structure is extensible
     * anyway, but using these saves some recompilation
     */
    ULONG                  gi_Reserved[6];
};

All the fields in this structure are read only.

Although this structure contains a pointer to the gadget's RastPort
structure, applications should not use it for rendering.  Instead, use the
intuition.library function ObtainGIRPort() to obtain a copy of the
GadgetInfo's RastPort.  When the gadget is finished with this RastPort, it
should call ReleaseGIRPort() to relinquish the RastPort.

 GM_RENDER     GM_GOACTIVE/GM_HANDLEINPUT
 GM_HITTEST    GM_GOINACTIVE


12 / / The Boopsi Gadget Methods / GM_RENDER

Every time Intuition feels it is necessary to redraw a Boopsi gadget, it
sends a gadget a GM_RENDER message.  The GM_RENDER message (defined in
<intuition/gadgetclass.h>) tells a gadget to render itself:

    struct gpRender
    {
        ULONG             MethodID;   /* GM_RENDER */
        struct GadgetInfo *gpr_GInfo;
        struct RastPort   *gpr_RPort; /* all ready for use */
        LONG              gpr_Redraw; /* might be a "highlight pass" */
    };

Some events that cause Intuition to send a GM_RENDER are: an application
passed the gadget to OpenWindow(), the user moved or resized a gadget's
window, or an application explicitly asked Intuition to refresh some
gadgets.

The GM_RENDER message contains a pointer to the gadget's RastPort so the
GM_RENDER method does not have to extract it from the gpr_GInfo GadgetInfo
structure using ObtainGIRPort()).  The gadget renders itself according to
how much imagery it needs to replace.  The gpr_Redraw field contains one
of three values:

GREDRAW_REDRAW  Redraw the entire gadget.

GREDRAW_UPDATE  The user has manipulated the gadget, causing a change
                to its imagery. Update only that part of the gadget's
                imagery that is effected by the user manipulating the
                gadget (for example, the knob and scrolling field of
                the prop gadget).

GREDRAW_TOGGLE  If this gadget supports it, toggle to or from the
                highlighting imagery.

Intuition is not the only entity that calls this method.  The gadget's
other methods may call this method to render the gadget when it goes
through state changes.  For example, as a prop gadget is following the
mouse from the gadget's GM_HANDLEINPUT method, the gadget could send
itself GM_RENDER messages, telling itself to update its imagery according
to where the mouse has moved.


12 / / The Boopsi Gadget Methods / GM_HITTEST

When Intuition gets a left mouse button click in a window, one of the
things it does is check through the window's list of gadgets to see if
that click was inside the bounds of a gadget's Gadget structure (using the
LeftEdge, TopEdge, Width, and Height fields).  If it was (and that gadget
is a Boopsi gadget), Intuition sends that gadget a GM_HITTEST message
(defined in <intuition/gadgetclass.h>):

    struct gpHitTest
    {
        ULONG             MethodID;     /* GM_HITTEST   */
        struct GadgetInfo *gpht_GInfo;
        struct
        {
            WORD X;     /* Is this point inside of the gadget? */
            WORD Y;
        } gpht_Mouse;
    };

This message contains the coordinates of the mouse click.  These
coordinates are relative to the upper-left of the gadget (LeftEdge,
TopEdge).

Because Intuition can only tell if the user clicked inside gadget's
"bounding box", Intuition only knows that the click was close to the
gadget.  Intuition uses the GM_HITTEST to ask the gadget if the click was
really inside the gadget.  The gadget returns GMR_GADGETHIT (defined in
<intuition/gadgetclass>) to tell Intuition that the user hit it,
otherwise it returns zero.  This method allows a gadget to be any shape or
pattern, rather than just rectangular.


12 / / The Boopsi Gadget Methods / GM_GOACTIVE/GM_HANDLEINPUT

If a gadget returns GMR_GADGETHIT, Intuition will send it a GM_GOACTIVE
message (defined in <intuition/gadgetclass.h>):

    struct gpInput /* Used by GM_GOACTIVE and GM_HANDLEINPUT */
    {
        ULONG             MethodID;
        struct GadgetInfo *gpi_GInfo;
        struct InputEvent *gpi_IEvent;
                             /* The input event that triggered this method
                              * (for GM_GOACTIVE, this can be NULL)      */
        LONG              *gpi_Termination;
                             /* For GADGETUP IntuiMessage.Code           */
        struct
        {
            WORD X;          /* Mouse position relative to upper         */
            WORD Y;          /* left corner of gadget (LeftEdge,TopEdge) */
        } gpi_Mouse;
    };

The GM_GOACTIVE message gives a gadget the opportunity to become the
active gadget.  The active gadget is the gadget that is currently
receiving user input.  Under normal conditions, only one gadget can be the
active gadget (it is possible to have more than one active gadget using a
groupgclass object--See the Boopsi Class Reference in the Appendix B of
this manual for more details).

While a gadget is active, Intuition sends it GM_HANDLEINPUT messages. Each
GM_HANDLEINPUT message corresponds to a single InputEvent structure.
These InputEvents can be keyboard presses, timer events, mouse moves, or
mouse button presses.  The message's gpi_IEvent field points to this
InputEvent structure. It's up to the GM_HANDLEINPUT method to interpret
the meaning of these events and update the visual state of the gadget as
the user manipulates the gadget.  For example, the GM_HANDLEINPUT method
of a prop gadget has to track mouse events to see where the user has moved
the prop gadget's knob and update the gadget's imagery to reflect the new
position of the knob.

For the GM_GOACTIVE method, the gpi_IEvent field points to the struct
InputEvent that triggered the GM_GOACTIVE message. Unlike the
GM_HANDLEINPUT message, GM_GOACTIVE's gpi_IEvent can be NULL.  If the
GM_GOACTIVE message was triggered by a function like intuition.library's
ActivateGadget() and not by a real InputEvent (like the user clicking the
gadget), the gpi_IEvent field will be NULL.

For gadgets that only want to become active as a direct result of a mouse
click, this difference is important.  For example, the prop gadget becomes
active only when the user clicks on its knob.  Because the only way the
user can control the prop gadget is via the mouse, it does not make sense
for anything but the mouse to activate the gadget.  On the other hand, a
string gadget doesn't care how it is activated because, as soon as it's
active, it gets user input from the keyboard rather than the mouse.  Not
all gadgets can become active.  Some gadgets cannot become active because
they have been temporarily disabled (their Gadget.Flags GFLG_DISABLED bit
is set).  Other gadgets will not become active because they don't need to
process input.  For example, a toggle gadget won't become active because
it only needs to process one input event, the mouse click that toggles the
gadget (which it gets from the GM_GOACTIVE message). If a toggle gadget
gets a GM_GOACTIVE message and its gpi_IEvent field is not NULL, it will
toggle its state and refuse to "go active".

The GM_GOACTIVE method has to take care of any visual state changes to a
gadget that a GM_GOACTIVE message might trigger.  For example, the toggle
gadget in the previous paragraph has to take care of toggling its visual
state from selected imagery to unselected imagery.  If the gadget goes
through a state change when it becomes the active gadget, (like when a
string gadget positions its cursor) GM_GOACTIVE has to take care of this.

The return values of both GM_GOACTIVE and GM_HANDLEINPUT tell Intuition
whether or not the gadget wants to be active.  A gadget's GM_GOACTIVE
method returns GMR_MEACTIVE (defined in <intuition/gadgetclass.h>) if it
wants to become the active gadget.  A gadget's GM_HANDLEINPUT method
returns GMR_MEACTIVE if it wants to remain the active gadget.  If a gadget
either does not want to become or remain the active gadget, it returns one
of the "go inactive" return values:

GMR_NOREUSE     Tells Intuition to throw away the gpInput.gpi_IEvent
                InputEvent.

GMR_REUSE       Tells Intuition to process the gpInput.gpi_IEvent
                InputEvent.

GMR_NEXTACTIVE  Tells Intuition to throw away the gpInput.gpi_IEvent
                InputEvent and activate the next GFLG_TABCYCLE gadget.

GMR_PREVACTIVE  Tells Intuition to throw away the gpInput.gpi_IEvent
                InputEvent and activate the previous GFLG_TABCYCLE
                gadget.

GMR_NOREUSE tells Intuition that the gadget does not want to be active and
to throw away the InputEvent that triggered the message.  For example, an
active prop gadget returns GMR_NOREUSE when the user lets go of the left
mouse button (thus letting go of the prop gadget's knob).

For the GM_HANDLEINPUT method, a gadget can also return GMR_REUSE, which
tells Intuition to reuse the InputEvent.  For example, if the user clicks
outside the active string gadget, that string gadget returns GMR_REUSE.
Intuition can now process that mouse click, which can be over another
gadget.  Another case where a string gadget returns GMR_REUSE is when the
user pushes the right mouse button (the menu button).  The string gadget
becomes inactive and the menu button InputEvent gets reused.  Intuition
sees this event and tries to pop up the menu bar.

For the GM_GOACTIVE method, a gadget must not return GMR_REUSE.  If a
gadget gets a GM_GOACTIVE message from Intuition and the message has an
gpi_IEvent, the message was triggered by the user clicking on the gadget.
In this case, Intuition knows that the user is trying to select the
gadget.  Intuition doesn't know if the gadget can be activated, but if it
can be activated, the event that triggered the activation has just taken
place.  If the gadget cannot become active for any reason, it must not let
Intuition reuse that InputEvent as the gadget has already taken care of
the the event's purpose (clicking on the gadget).  In essence, the user
tried to activate the gadget and the gadget refused to become active.

The other two possible return values, GMR_NEXTACTIVE and GMR_PREVACTIVE
were added to the OS for Release 2.04.  These tell Intuition that a gadget
does not want to be active and that the InputEvent should be discarded.
Intuition then looks for the next (GMR_NEXTACTIVE) or previous
(GMR_PREVACTIVE) gadget that has its GFLG_TABCYCLE flag set in its
Gadget.Activation field (see the gadgetclass GA_TabCycle attribute in the
Boopsi Class Reference in the Appendix B of this manual).

For both GM_GOACTIVE and GM_HANDLEINPUT, the gadget can bitwise-OR any of
these "go inactive" return values with GMR_VERIFY.  The GMR_VERIFY flag
tells Intuition to send a GADGETUP IntuiMessage to the gadget's window.
If the gadget uses GMR_VERIFY, it has to supply a value for the
IntuiMessage.Code field.  It does this by passing a value in the
gpInput.gpi_Termination field.  This field points to a long word, the
lower 16-bits of which Intuition copies into the Code field.  The upper
16-bits are for future enhancements, so clear these bits.


12 / / The Boopsi Gadget Methods / GM_GOINACTIVE

After an active gadget deactivates, Intuition sends it a GM_GOINACTIVE
message (defined in <intuition/gadgetclass.h>):

    struct gpGoInactive
    {
        ULONG             MethodID;    /* GM_GOINACTIVE */
        struct GadgetInfo *gpgi_GInfo;

        /* V37 field only!  DO NOT attempt to read under V36!          */
        ULONG             gpgi_Abort; /* gpgi_Abort=1 if gadget was    */
                                      /* aborted by Intuition          */
                                      /* and 0 if gadget went inactive */
                                      /* at its own request.           */
    };

The gpgi_Abort field contains either a 0 or 1.  If 0, the gadget became
inactive on its own power (because the GM_GOACTIVE or GM_HANDLEINPUT
method returned something besides GMR_MEACTIVE).  If gpgi_Abort is 1,
Intuition aborted this active gadget.  Some instances where Intuition
aborts a gadget include: the user clicked in another window or screen, an
application removed the active gadget with RemoveGList(),  and an
application called ActiveWindow() on a window other than the gadget's
window.


12 / Boopsi Gadgets / The Active Gadget

While a gadget is active, Intuition sends it a GM_HANDLEINPUT message for
every timer pulse, mouse move, mouse click, and key press that takes
place.  A timer event pulse arrives about every tenth of a second.  Mouse
move events can arrive at a much higher rate than the timer pulses.
Without even considering the keyboard, a gadget can get a lot of
GM_HANDLEINPUT messages in a short amount of time. Because the active
gadget has to handle a large volume of GM_HANDLEINPUT messages, the
overhead of this method should be kept to a minimum.

Because the gadget will always receive a GM_GOACTIVE message before it is
active and a GM_GOINACTIVE message after it is no longer active, the
gadget can use these methods to allocate, initialize, and deallocate
temporary resources it needs for the GM_HANDLEINPUT method.  This can
significantly reduce the overhead of GM_HANDLEINPUT because it eliminates
the need to allocate, initialize, and deallocate resources for every
GM_HANDLEINPUT message.

Note that the RastPort from ObtainGIRPort() is not cachable using this
method.  If the GM_HANDLEINPUT method needs to use a RastPort, it has to
obtain and release the RastPort for every GM_HANDLEINPUT message using
ObtainGIRPort() and ReleaseGIRPort().

 RKMButtonclass.c


12 / / The Active Gadget / RKMButtonclass.c

The following example is a sample Boopsi gadget, RKMButClass.c.  While the
user has the RKMButton selected, the gadget sends an OM_UPDATE message to
its ICA_TARGET for every timer event the button sees.  The gadget sends
notification about its RKMBUT_Pulse attribute, which is the horizontal
distance in screen pixels the mouse is from the center of the button.  The
gadget takes care of rendering all of its imagery (as opposed to using a
Boopsi image to do it).  The gadget's imagery is scalable to any
dimensions and can be set (using SetGadgetAttrs()) while the gadget is in
place.

One possible use for such a gadget is as buttons for a prop gadget. If the
user has the prop gadget's RKMButton selected, while the mouse is to the
left of the button's center, the knob on the prop gadget moves left.
While the mouse is to the right of the button's center, the knob on the
prop gadget moves right.  The speed at which the knob moves is
proportional to the horizontal distance from the mouse to the active
RKMButton.

     RKMButClass.c


12 Boopsi--Object Oriented Intuition / Function Reference

The following are brief descriptions of the Intuition and amiga.lib
functions discussed in this chapter.  See the "Amiga ROM Kernel Reference
Manual: Includes and Autodocs" for details on each function call.  All
these functions require Release 2 or a later version of the Amiga
operating system.

              Table 12-1: Intuition Library Boopsi Functions
  ________________________________________________________________________
 |                                                                        |
 |       Function                 Description                             |
 |========================================================================|
 |      NewObjectA()  Create a new Boopsi object (tag array form).        |
 |       NewObject()  Create a new Boopsi object (varargs form).          |
 |   DisposeObject()  Dispose of a Boopsi object.                         |
 |        SetAttrs()  Set one or more of a Boopsi object's attributes     |
 |                    (tag array form).                                   |
 |  SetGadgetAttrs()  Set one or more of a Boopsi object's attributes     |
 |                    (varargs form).                                     |
 |         GetAttr()  Obtain an attribute from a Boopsi object.           |
 |------------------------------------------------------------------------|
 |       MakeClass()  Create a new private or public Boopsi class.        |
 |       FreeClass()  Free a Boopsi class created by MakeClass().         |
 |        AddClass()  Add a public Boopsi class to Intuition's internal   |
 |                    list of public classes.                             |
 |     RemoveClass()  Remove a public Boopsi class that was added to      |
 |                    Intuition's internal list with AddClass().          |
 |------------------------------------------------------------------------|
 |   ObtainGIRPort()  Set up a RastPort for use by a Boopsi gadget        |
 |                    dispatcher.                                         |
 |  ReleaseGIRPort()  Free a RastPort set up by ReleaseGIRPort().         |
 |________________________________________________________________________|

                  Table 12-2: Amiga.lib Boopsi Functions
  ________________________________________________________________________
 |                                                                        |
 |       Function                 Description                             |
 |========================================================================|
 |       DoMethodA()  Send a Boopsi message to a Boopsi object            |
 |                    (tag array form).                                   |
 |        DoMethod()  Send a Boopsi message to a Boopsi object            |
 |                    (varargs form).                                     |
 |  DoSuperMethodA()  Send a Boopsi message to a Boopsi object as if the  |
 |                    object was an instance of its class's superclass    |
 |                    (tag array form).                                   |
 |   DoSuperMethod()  Send a Boopsi message to a Boopsi object as if the  |
 |                    object was an instance of its class's superclass    |
 |                    (varargs form).                                     |
 |   CoerceMethodA()  Send a Boopsi message to a Boopsi object as if the  |
 |                    object was an instance of the specified class       |
 |                    (tag array form).                                   |
 |    CoerceMethod()  Send a Boopsi message to a Boopsi object as if the  |
 |                    object was an instance of the specified class       |
 |                    (varargs form).                                     |
 |   SetSuperAttrs()  Send a Boopsi OM_SET message to the Boopsi object's |
 |                    superclass.                                         |
 |________________________________________________________________________|


Amiga® RKM Libraries: 13 Preferences

To make the Amiga operating system easily configurable by the user, the OS
comes with a family of editors and associated data files known
collectively as Preferences.  Preferences allows the user to set
system-wide configuration options such as the printer driver to use,
serial port baud rate and other items.  To make an application appealing
to the user, the system-wide Preferences settings should be respected as
much as possible by applications.  This chapter describes how to use the
Preferences system in your programs.

In Release 2 the number of Preference items and the way they are handled
is very different from 1.3 and earlier versions, though there is backward
compatibility with old Preferences items.  This chapter describes both the
old 1.3 and the new Release 2 Preferences.

 Preferences in 1.3 and Older Versions of the OS
 Preferences in Release 2
 Function Reference


13 Preferences / Preferences in 1.3 and Older Versions of the OS

In 1.3, the Preferences program allows the user to see and change many
system wide parameters, like the Workbench colors, pointer image, printer
settings etc.  When a Preferences item is changed, the new setting can be
used temporarily (until a reset occurs) or stored permanently in the
devs:system-configuration file.   Under 1.3, all Preferences items are
stored in this file which the system reads at boot time to find out how to
set various system-wide options.

The 1.3 Preferences system allows the user to change the following items:

  * Date and time of day. These are automatically saved in the
    battery-backed clock, if one is present.

  * Key repeat speed - the speed at which a key repeats when held down.

  * Key repeat delay - the amount of delay before a key begins repeating.

  * Mouse speed - how fast the pointer moves when the user moves the
    mouse.

  * Double-click delay - maximum time allowed between the two clicks of a
    mouse double click.  For information about how to test for
    double-click timeout, see the description of the DoubleClick()
    function in the Amiga ROM Kernel Reference Manual:
    Includes and Autodocs.

  * Text size - size of the default font characters.  The user can choose
    64-column mode (64 characters on a line in high-resolution and 32
    characters in low-resolution mode) or 80 column mode (80 characters
    on a line in high-resolution and 40 characters in low-resolution
    mode).  The first variable in the Preferences structure is
    FontHeight, which is the height of the characters in display lines.
    If this is equal to the constant TOPAZ_EIGHTY, the user has chosen
    the 80-column mode.  If it is equal to TOPAZ_SIXTY, the user has
    chosen the 64-column mode.  Note that certain utility programs allow
    the user to change the default font under 1.3, so you cannot rely on
    the default font being Topaz 8 or 9.

  * Display centering - allows the user to center the image on the video
    display.

  * Serial port - the user can change the baud rate and other serial port
    parameters to accommodate whatever device is attached to the serial
    connector.  Normally you use these values as defaults when you open
    the serial device.  If you change the baud rate or other serial port
    options locally, it is good practice to reset them to the values
    specified in Preferences before quitting.

  * Workbench colors - the user can change any of the four colors in the
    1.3 Workbench screen by adjusting the amounts of red, green and blue
    in each color.

  * Printer - the user can select from a number of printers supported by
    the Amiga and also indicate whether the printer is connected to the
    serial connector or the parallel connector.

  * Print characteristics - the user can select paper size, right and
    left margin, continuous feed or single sheets, draft or letter
    quality, pitch and line spacing.  For graphic printing, the user can
    specify the density, scaling method, select a vertical or horizontal
    dump, etc.

 Reading 1.3 Preferences         Setting 1.3 Preferences
 Preferences Structure in 1.3    Alternatives to SetPrefs


13 / Preferences in 1.3 and Older Versions / Reading 1.3 Preferences

Applications can obtain a copy of Preferences by calling the Intuition
function GetPrefs().  In a system in which there is no
devs:system-configuration file, GetDefPrefs() can be used to obtain the
Intuition default Preference settings.

    struct Preferences *GetPrefs(struct Preferences *preferences,
                                 LONG size);
    struct Preferences *GetDefPrefs(struct Preferences *preferences,
                                    LONG size);

GetPrefs() and GetDefPrefs() have two arguments, a pointer to a buffer to
receive the copy of the user Preferences and the size of this buffer.  The
most commonly used data is grouped near the beginning of the Preferences
structure and you are free to read only as much as you need.  So, if you
are only interested in the first part of the Preferences structure, you do
not need to allocate a buffer large enough to hold the entire structure.
These functions return a pointer to your buffer if successful, NULL
otherwise.

If you are using Intuition IDCMP for input, you can set the IDCMP flag
IDCMP_NEWPREFS (formerly the NEWPREFS flag under V34 and earlier versions
of the OS).  With this flag set, your program will receive an IntuiMessage
informing you changes have been made to Preferences.  To get the latest
settings, you would again call GetPrefs().


13 / Preferences 1.3 & Older Versions / Preferences Structure in 1.3

The Preferences structure in 1.3 and earlier versions of the OS is a
static 232 byte data structure defined in <intuition/preferences.h> as
follows:

struct Preferences
{
    /* the default font height */
    BYTE FontHeight;                  /* height for system default font  */

    /* constant describing what's hooked up to the port */
    UBYTE PrinterPort;                /* printer port connection         */

    /* the baud rate of the port */
    UWORD BaudRate;                   /* baud rate for the serial port   */

    /* various timing rates */
    struct timeval KeyRptSpeed;       /* repeat speed for keyboard       */
    struct timeval KeyRptDelay;       /* Delay before keys repeat        */
    struct timeval DoubleClick;       /* Interval allowed between clicks */

    /* Intuition Pointer data */
    UWORD PointerMatrix[POINTERSIZE]; /* Definition of pointer sprite    */
    BYTE XOffset;                     /* X-Offset for active 'bit'       */
    BYTE YOffset;                     /* Y-Offset for active 'bit'       */
    UWORD color17;                    /***********************************/
    UWORD color18;                    /* Colours for sprite pointer      */
    UWORD color19;                    /***********************************/
    UWORD PointerTicks;               /* Sensitivity of the pointer      */

    /* Workbench Screen colors */
    UWORD color0;                     /***********************************/
    UWORD color1;                     /*  Standard default colours       */
    UWORD color2;                     /*   Used in the Workbench         */
    UWORD color3;                     /***********************************/

    /* positioning data for the Intuition View */
    BYTE ViewXOffset;                 /* Offset for top lefthand corner  */
    BYTE ViewYOffset;                 /* X and Y dimensions              */
    WORD ViewInitX, ViewInitY;        /* View initial offset values      */

    BOOL EnableCLI;                 /* CLI availability switch (OBSOLETE)*/

    /* printer configurations */
    UWORD PrinterType;                    /* printer type                */
    UBYTE PrinterFilename[FILENAME_SIZE]; /* file for printer            */

    /* print format and quality configurations */
    UWORD PrintPitch;                 /* print pitch                     */
    UWORD PrintQuality;               /* print quality                   */
    UWORD PrintSpacing;               /* number of lines per inch        */
    UWORD PrintLeftMargin;            /* left margin in characters       */
    UWORD PrintRightMargin;           /* right margin in characters      */
    UWORD PrintImage;                 /* positive or negative            */
    UWORD PrintAspect;                /* horizontal or vertical          */
    UWORD PrintShade;                 /* b&w, half-tone, or color        */
    WORD PrintThreshold;              /* darkness ctrl for b/w dumps     */

    /* print paper descriptors */
    UWORD PaperSize;                  /* paper size                      */
    UWORD PaperLength;                /* paper length in number of lines */
    UWORD PaperType;                  /* continuous or single sheet      */

    /* Serial device settings: These are 6 nibble-fields in 3 bytes      */
    /* (these look a little strange so the defaults will map out to 0)   */
    UBYTE   SerRWBits;   /* upper nibble = (8-number of read bits)       */
                         /* lower nibble = (8-number of write bits)      */
    UBYTE   SerStopBuf;  /* upper nibble = (number of stop bits - 1)     */
                         /* lower nibble = (table value for BufSize)     */
    UBYTE   SerParShk;   /* upper nibble = (value for Parity setting)    */
                         /* lower nibble = (value for Handshake mode)    */
    UBYTE   LaceWB;      /* if workbench is to be interlaced             */

    UBYTE   WorkName[FILENAME_SIZE]; /* temp file for printer            */

    BYTE    RowSizeChange;           /* affect NormalDisplayRows/Columns */
    BYTE    ColumnSizeChange;

    UWORD    PrintFlags;    /* user preference flags                     */
    UWORD    PrintMaxWidth; /* max width of printed picture in 10ths/in  */
    UWORD    PrintMaxHeight;/* max height of printed picture in 10ths/in */
    UBYTE    PrintDensity;  /* print density                             */
    UBYTE    PrintXOffset;  /* offset of printed picture in 10ths/inch   */

    UWORD    wb_Width;      /* override default workbench width  */
    UWORD    wb_Height;     /* override default workbench height */
    UBYTE    wb_Depth;      /* override default workbench depth  */

    UBYTE    ext_size;      /* extension information -- do not touch! */
                            /* extension size in blocks of 64 bytes   */
};


13 / Preferences in 1.3 and Older Versions / Setting 1.3 Preferences

The instance of the Preferences structure in memory can be changed with
the Intuition SetPrefs() function:

    struct Preferences *SetPrefs(struct Preferences *preferences,
                                 LONG size, BOOL inform);

In addition to a buffer holding the Preferences structure, and the buffer
size, this function takes an argument which indicates whether an
IDCMP_NEWPREFS message should be broadcast to windows which have this flag
set in the Window.IDCMPFlags field of their window.

    Avoid Using SetPrefs().
    -----------------------
    This function is normally only used by Preferences-like utilities.
    There should be no need for a normal application to set the system
    Preferences with SetPrefs().


13 / Preferences in 1.3 and Older Versions / Alternatives to SetPrefs

Since the Amiga is a multitasking system, it is rarely correct for a
single Amiga application to modify the user's system-wide Preferences.
Instead, use methods such as the following to modify only your own
application's appearance or behavior.

  * Custom screen applications can control their own display mode,
    resolution, palette, and fonts. Use functions such a LoadRGB4() to
    change your own screen's palette, and SetFont() to change your own
    screen and window fonts. Workbench applications should never change
    the attributes of the user's Workbench.

  * The mouse pointer for a window may be changed with SetPointer().

  * Serial device settings can be changed with the command
    SDCMD_SETPARAMS.

  * Printer device settings may be changed by altering the printer's copy
    of the Preferences structure when you have the printer open. Note
    that Amiga applications should only keep the printer open while they
    are printing.  This allows other applications to print, and also
    allows user changes to Printer Preferences to take effect.

See the Inutition and graphics chapters of this manual, and the
"Printer Device" and "Serial Device" chapters of the Amiga ROM Kernel
Reference Manual: Devices for more information.


13 Preferences / Preferences in Release 2

Under Release 2 (V36), the way Preferences are handled is significantly
different.  No longer is there one Preferences program with one
configuration file.  Instead there can be any number of Preferences
editors (there are currently 13), each with its own separate configuration
file covering a specific area.  All these Preferences editors have the
same look and feel.  Using separate Preferences editors and configuration
files allows for adding new Preferences items (and editors) in future
versions of the OS.

 Preferences Editors and Storage
 The ENV: Directory and Notification
 Preference File Format In Release 2

 FONT    INPT    PGFX    SCRM
 ICTL    OSCN    PTXT    SERL

 Other Preferences File Formats in Release 2
 Reading a Preferences File


13 / Preferences in Release 2 / Preferences Editors and Storage

In Release 2, the devs:system-configuration file has been replaced by
various .prefs files, located in the ENV:sys and ENVARC:sys directories.
System Preferences options currently in use are located in ENV:sys.
Permanent, saved copies of system Preferences files are stored in
ENVARC:sys. The contents of ENVARC: is copied at boot time to ENV:.
Applications may also store their own preference files in ENV: but should
use a subdirectory for that purpose.

Currently the following Preferences editors and files are available:

       Table 13-1: Preferences Editors in Release 2

    Preferences Editor  Preferences Configuration File
    ------------------  ------------------------------
    IControl            icontrol.prefs
    Input               input.prefs
    Palette             palette.ilbm
    Pointer             pointer.ilbm
    Printer             printer.prefs
    PrinterGfx          printergfx.prefs
    Overscan            overscan.prefs
    ScreenMode          screenmode.prefs
    Serial              serial.prefs
    ---                 wbconfig.prefs
    Font                wbfont.prefs, sysfont.prefs and screenfont.prefs
    Time                ---
    WBPattern           wb.pat and win.pat

Each .prefs file is managed by editor with the same name, except for
wbconfig.prefs, which is written directly by Workbench and has no editor.
One Preferences editor has no .prefs file, Time.  That Preferences editor
writes directly to the battery backed clock.

When the user makes a change to a Preferences item with one of the
editors, the changes will be saved in either ENV:sys or both ENV:sys and
ENVARC:sys depending on whether the user saves the changes with the "Use"
gadget or "Save" gadget of the Preferences editor.

The "Use" gadget is for making temporary changes and the new preferences
will be stored only in ENV:sys.  If the user reboots, the old preferences
will be restored from the permanent copy in ENVARC:sys.

The "Save" gadget is for making permanent changes and the new preferences
will be stored in both ENV:sys and ENVARC:sys.  That way, if the user
reboots, the new preferences will still be in effect since the system
looks in ENVARC:sys to find out what preferences should be set to at boot
time.


13 / Preferences in Release 2 / The ENV: Directory and Notification

One advantage of the new Preferences system in Release 2 is file
notification.  File notification is a form of interprocess communication
available in Release 2 that allows an application to be automatically
notified if a change is made to a specific file or directory.  This makes
it easy for the application to react to changes the user makes to
Preferences files.

File notification is also used by the system itself.  The Release 2
Preferences control program, IPrefs, sets up notification on most of the
Preferences files in ENV:sys.  If the user alters a Preferences item
(normally this is done with a Preferences editor), the system will notify
IPrefs about the change and IPrefs will attempt to alter the user's
environment to reflect the change.

For example, if the user opens the ScreenMode Preferences editor and
changes the Workbench screen mode to high-resolution, the new settings are
saved in Screenmode.prefs in the ENV:sys directory.  IPrefs sets up
notification on this file at boot time, so the file system will notify
IPrefs of the change.  IPrefs will read in the Screenmode.prefs file and
reset the Workbench screen to high resolution mode.

Here's a short example showing how to set up notification on the
serial.prefs file in ENV:sys.  The program displays a message in a window
whenever this file is changed (e.g., when the user selects the "Use" or
"Save" gadget in the Serial Preferences editor).

     prefnotify.c


13 / Preferences in Release 2 / Preference File Format in Release 2

To understand the format of Preferences files, you must be familiar with
IFF file standard (see the Amiga ROM Kernel Reference Manual: Devices for
the complete specification).

In general all Preferences files are stored in the IFF format with a type
of PREF (see the exceptions noted below).  Each file contains at least two
Chunks, a header Chunk and a data Chunk.

 The Header Chunk    The Data Chunk


13 / / Preference File Format in Release 2 / The Header Chunk

The PRHD header chunk, contains a PrefHeader structure:

    struct PrefHeader
    {
        UBYTE ph_Version;
        UBYTE ph_Type;
        ULONG ph_Flags;
    };

Currently all the fields are set to NULL.  In future revisions these
fields may be used to indicate a particular version and contents of a PREF
chunk.


13 / / Preference File Format in Release 2 / The Data Chunk

The data Chunk that follows the header Chunk depends on the kind of
Preferences data the file contains.  The types of Preferences data Chunks
that are currently part of the system are:

    Table 13-2: IFF Chunk Types in Release 2 Preferences Data Files

    Chunk Name     Used With
    ----------     ---------
       FONT        Fonts, used for all font Preferences files.
                   In future the PrefHeader may indicate what the
                   font is used for.
       ICTL        IControl
       INPT        Input
       OSCN        Overscan
       PGFX        PrinterGfx
       PTXT        PrinterText
       SCRM        ScreenMode
       SERL        Serial

Each chunk contains a structure applicable to the type.


13 / Preferences in Release 2 / FONT

    struct FontPrefs
    {
        LONG            fp_Reserved[4];
        UBYTE           fp_FrontPen;     /* Textcolor */
        UBYTE           fp_BackPen;      /* Character background color */
        UBYTE           fp_DrawMode;
        struct TextAttr fp_TextAttr;
        BYTE            fp_Name[FONTNAMESIZE]; /* Font name */
    };


13 / Preferences in Release 2 / ICTL

    struct IControlPrefs
    {
        LONG  ic_Reserved[4];        /* System reserved            */
        UWORD ic_TimeOut;            /* Verify timeout             */
        WORD  ic_MetaDrag;           /* Meta drag mouse event      */
        ULONG ic_Flags;              /* IControl flags (see below) */
        UBYTE ic_WBtoFront;          /* CKey: WB to front          */
        UBYTE ic_FrontToBack;        /* CKey: front screen to back */
        UBYTE ic_ReqTrue;            /* CKey: Requester TRUE       */
        UBYTE ic_ReqFalse;           /* CKey: Requester FALSE      */
    };

The ic_Flags field can have the following values:

ICF_COERCE_COLORS
    This indicates that a displaymode with a matching number of colors
    has preference over a correct aspect ration when screen coercing
    takes place.

ICF_COERCE_LACE
    This indicates that chosing an interlaced display mode is allowed
    when coercing screens. Otherwise a non-interlaced display mode will
    be selected.

ICF_STRGAD_FILTER
    This indicates that control characters should be filtered out of
    string gadget user input.

ICF_MENUSNAP
    This indicates that an autoscroll screen should be snapped back to
    origin when the mouse menu-button is selected.

Note that the command key values in the last four fields of the
IControlPrefs structure are ANSI codes, not RAWKEY codes.


13 / Preferences in Release 2 / INPT

    struct InputPrefs
    {
        LONG           ip_Reserved[4];
        UWORD          ip_PointerTicks; /* Sensitivity of the pointer */
        struct timeval ip_DoubleClick;  /* Interval between clicks */
        struct timeval ip_KeyRptDelay;  /* keyboard repeat delay   */
        struct timeval ip_KeyRptSpeed;  /* Keyboard repeat speed   */
        WORD           ip_MouseAccel;   /* Mouse acceleration      */
    };


13 / Preferences in Release 2 / OSCN

    struct OverscanPrefs
    {
        ULONG            os_Reserved[4];
        ULONG            os_DisplayID;   /* Displaymode ID */
        Point            os_ViewPos;     /* View X/Y Offset */
        Point            os_Text;        /* TEXT overscan dimension */
        struct Rectangle os_Standard;    /* STANDARD overscan dimension */
    };


13 / Preferences in Release 2 / PGFX

    struct PrinterGfxPrefs
    {
        LONG  pg_Reserved[4];
        UWORD pg_Aspect;          /* Horizontal or vertical */
        UWORD pg_Shade;           /* B&W, Greyscale, Color */
        UWORD pg_Image;           /* Positive or negative image */
        WORD  pg_Threshold;       /* Black threshold */
        UBYTE pg_ColorCorrect;    /* RGB color correction */
        UBYTE pg_Dimensions;      /* Dimension type */
        UBYTE pg_Dithering;       /* Type of dithering */
        UWORD pg_GraphicFlags;    /* Rastport dump flags */
        UBYTE pg_PrintDensity;    /* Print density 1 - 7 */
        UWORD pg_PrintMaxWidth;   /* Maximum width */
        UWORD pg_PrintMaxHeight;  /* Maximum height */
        UBYTE pg_PrintXOffset;    /* X Offset */
        UBYTE pg_PrintYOffset;    /* Y Offset */
    };

The possible values of each field are defined in <prefs/printergfx.h>.
Note that your application is responsible for checking if the supplied
values are valid.


13 / Preferences in Release 2 / PTXT

    struct PrinterTxtPrefs
    {
        LONG  pt_Reserved[4];            /* System reserved            */
        UBYTE pt_Driver[DRIVERNAMESIZE]; /* printer driver filename    */
        UBYTE pt_Port;                   /* printer port connection    */

        UWORD pt_PaperType;              /* Fanfold or single */
        UWORD pt_PaperSize;              /* Standard, Legal, A4, A3 etc. */
        UWORD pt_PaperLength;            /* Paper length in # of lines */

        UWORD pt_Pitch;                  /* Pica or Elite */
        UWORD pt_Spacing;                /* 6 or 8 LPI */
        UWORD pt_LeftMargin;             /* Left margin */
        UWORD pt_RightMargin;            /* Right margin */
        UWORD pt_Quality;                /* Draft or Letter */
    };


13 / Preferences in Release 2 / SCRM

    struct ScreenModePrefs
    {
        ULONG sm_Reserved[4];
        ULONG sm_DisplayID;              /* Displaymode ID */
        UWORD sm_Width;                  /* Screen width */
        UWORD sm_Height;                 /* Screen height */
        UWORD sm_Depth;                  /* Screen depth */
        UWORD sm_Control;                /* BIT 0, Autoscroll yes/no */
    };


13 / Preferences in Release 2 / SERL

    struct SerialPrefs
    {
        LONG  sp_Reserved[4];     /* System reserved                  */
        ULONG sp_BaudRate;        /* Baud rate                        */

        ULONG sp_InputBuffer;     /* Input buffer: 0 - 64K          */
        ULONG sp_OutputBuffer;    /* Future: Output: 0 - 64K, def 0 */

        UBYTE sp_InputHandshake;  /* Input handshaking                */
        UBYTE sp_OutputHandshake; /* Future: Output handshaking       */

        UBYTE sp_Parity;          /* Parity                           */
        UBYTE sp_BitsPerChar;     /* I/O bits per character           */
        UBYTE sp_StopBits;        /* Stop bits                        */
    };


13 / Preferences in Release 2 / Other File Formats in Release 2

Not every Preferences file is stored as an IFF file of type PREF.  The
palette.ilbm and pointer.ilbm files contain a regular ILBM FORM to store
their imagery.  The win.pat and wb.pat files use a raw format with 16
bytes reserved, followed by a WORD giving the total size of the pattern, a
WORD giving the bitplane count, and byte arrays (currently 32 bytes) for
each bitplane.  The format of the wbconfig.prefs file is private.


13 Preferences / Function Reference

The following are brief descriptions of the system functions that relate
to the use of Preferences.  See the Amiga ROM Kernel Reference Manual:
Includes and Autodocs for details on each function call.

               Table 13-3: Functions Used with Preferences
  _______________________________________________________________________
 |                                                                       |
 |      Function                Description                              |
 |=======================================================================|
 |      GetPrefs()  Old 1.3 (V34) function for making a copy of the      |
 |                  Preferences structure                                |
 |      SetPrefs()  Old 1.3 (V34) function for overwriting Preferences   |
 |                  with new data                                        |
 |   GetDefPrefs()  Old 1.3 (V34) function for copying default           |
 |                  Preferences from ROM                                 |
 |-----------------------------------------------------------------------|
 |   StartNotify()  Release 2 DOS library function for monitoring a      |
 |                  .prefs file for changes                              |
 |     EndNotify()  Ends notification started with StartNotify()         |
 |-----------------------------------------------------------------------|
 |      AllocIFF()  IFFParse library function that creates an IFFHandle  |
 |                  for parsing                                          |
 |  InitIFFasDOS()  Initialize the IFFHandle as a DOS stream             |
 |       OpenIFF()  Initialize an IFFHandle for reading or writing a new |
 |                  stream                                               |
 |     PropChunk()  Specify a property chunk to store                    |
 |      ParseIFF()  Parse an IFF file from the IFFHandle stream          |
 |  CurrentChunk()  Returns the top level context of an IFF stream       |
 |      FindProp()  Search for a property chunk previously declared with |
 |                  PropChunk()                                          |
 |      CloseIFF()  Closes an IFF context opened with OpenIFF()          |
 |       FreeIFF()  Frees the IFFHandle created with AllocIFF()          |
 |_______________________________________________________________________|


Amiga® RKM Libraries: 14 Workbench and Icon Library

Workbench is the graphic user interface to the Amiga file system that uses
symbols called icons to represent disks, directories and files.  This
chapter shows how to use Workbench and its two support libraries
workbench.library and icon.library.

Workbench is both a system program and a screen.  Normally it is the first
thing the user sees when the machine is booted providing a friendly
operating environment for launching applications and performing other
important system activities like navigating through the Amiga's
hierarchical filing system.

All application programs should be compatible with Workbench.  There are
only two things you need to know to do this: how to make icons for your
application, data files and directories; and how to get arguments if your
application is launched from Workbench.

 The Info File            The Workbench Library
 Workbench Environment    Workbench and the Startup Code Module
 The Icon Library         Function Reference


14 Workbench and Icon Library / The Info File

The iconic representation of Amiga filing system objects is implemented
through .info files.  In general, for each file, disk or directory that is
visible in the Workbench environment, there is an associated .info file
which contains the icon imagery and other information needed by Workbench.

Icons are associated with a particular file or directory by name.  For
example, the icon for a file named myapp would be stored in a .info file
named myapp.info in the same directory.

To make your application program accessible (and visible) in the
Workbench environment, you need only supply a .info file with
the appropriate name and type.  The are four main types of icons
(and .info files) used to represent Amiga filing system
objects (Table (14-1).

           Table 14-1: Basic Workbench Icon Types

    Workbench          Filing                   Result When
    Icon Type       System Object            Icon Is Activated
    ---------       -------------            -----------------
    Disk       The root level directory    Window opens showing files
                                           and subdirectories

    Drawer     A subdirectory              Window opens showing files
                                           and subdirectories

    Tool       An executable file          Application runs
               (i.e., an application)

    Project    A data file                 Typically, the application
                                           that created the data file
                                           runs and the data file is
                                           automatically loaded into it.

     Figure 14-1: Basic Workbench Icon Types

Icons can be created with the IconEdit program (in the Tools directory of
the Extras disk), or by copying an existing .info file of the correct
type.  Icons can also be created under program control with
PutDiskObject().  See the discussion of the icon library functions below
for more on this.

For an executable file the icon type must be set to tool.  For a data file
the icon type must be set to project. Create icons for your application
disk and directories too.  For a directory, the icon is stored in a .info
file at the same level where the directory name appears (not in the
directory itself).  The icon type should be set to drawer.  The icon for a
disk should always be stored in a file named disk.info at the root level
directory of the disk.  The icon type should be set to disk.  (The icon
type can be set and the icon imagery edited with the IconEdit program.)


14 Workbench and Icon Library / Workbench Environment

On the Amiga there are at least two ways to start a program running:

  * By activating a tool or project icon in Workbench (an icon is
    activated by pointing to it with the mouse and double-clicking
    the mouse select button.)

  * By typing the name of an executable file at the Shell (also
    known as the CLI or Command Line Interface)

In the Workbench environment, a program is run as a separate process.  A
process is simply a task with additional information needed to use DOS
library.

By default, a Workbench program does not have a window to which its output
will go.  Therefore, stdin and stdout do not point to legal file handles.
This means you cannot use stdio functions such as printf() if your program
is started from Workbench unless you first set up a stdio window.

Some compilers have options or defaults to provide a stdio window for
programs started from Workbench.  In Release 2, applications can use an
auto console window for stdio when started from Workbench by opening
"CON:0/0/640/200/auto/close/wait" as a file.  An auto console window will
only open if stdio input or output occurs.  This can also be handled in
the startup code module that comes with your compiler.

 Argument Passing In Workbench
 WBStartup Message
 Example of Parsing Workbench Arguments


14 / Workbench Environment / Argument Passing In Workbench

Applications started from Workbench receive arguments in the form of a
WBStartup structure.  This is similar to obtaining arguments from a
command line interface through argc and argv.  The WBStartup message
contains an argument count and a pointer to a list of file and directory
names.

 One Argument    Two Arguments    Multiple Arguments


14 / / Argument Passing In Workbench / One Argument

A program started by activating its tool icon gets one argument in the
WBStartup message: the name of the tool itself.


14 / / Argument Passing In Workbench / Two Arguments

All project icons (data files) have a default tool field associated with
them that tells Workbench which application tool to run in order to
operate on the data that the icon represents.  When the user activates a
project icon, Workbench runs the application specified in the default tool
field passing it two arguments in the WBStartup message: the name of the
tool and the project icon that the user activated.


14 / / Argument Passing In Workbench / Multiple Arguments

With extended select, the user can activate many icons at once.  (Extended
select means the user holds down the Shift key while clicking the mouse
select button once on each icon in a group, double-clicking on the last
icon.)  If one of the icons in a group activated with extended select is
an application tool, Workbench runs that application passing it the name
of all the other icons in the group.  This allows the user to start an
application with multiple project files as arguments.  If none of the
icons in a group activated with extended select is a tool icon, then
Workbench looks in the default tool field of each icon in the order they
were selected and runs the first tool it finds.


14 / Workbench Environment / WBStartup Message

When Workbench loads and starts a program, its sends the program a
WBStartup message containing the arguments as summarized above.  Normally,
the startup code supplied with your compiler will place a pointer to
WBStartup in argv for you, set argc to zero and call your program.

The WBStartup message, whose structure is outlined in
<workbench/startup.h>, has the following structure elements:

    struct WBStartup
    {
        struct Message   sm_Message;    /* a standard message structure */
        struct MsgPort * sm_Process;    /* process descriptor for you */
        BPTR             sm_Segment;    /* a descriptor for your code */
        LONG             sm_NumArgs;    /* number of elements in ArgList */
        char *           sm_ToolWindow; /* reserved for future use */
        struct WBArg *   sm_ArgList;    /* the arguments themselves */
    };

The fields of the WBStartup structure are used as follows.

    sm_Message
        A standard Exec message.  The reply port is set to the Workbench.

    sm_Process
        The process descriptor for the tool (as returned by
        CreateProc())

    sm_Segment
        The loaded code for the tool (returned by LoadSeg())

    sm_NumArgs
        The number of arguments in sm_ArgList

    sm_ToolWindow
        Reserved (not currently passed in startup message)

    sm_ArgList
        This is the argument list itself.  It is a pointer to an array
        of WBArg structures with sm_NumArgs elements.

Workbench arguments are passed as an array of WBArg structures in the
sm_ArgList field of WBStartup.  The first WBArg in the list is always the
tool itself.  If multiple icons have been selected when a tool is
activated, the selected icons are passed to the tool as additional WBArgs.
If the tool was derived from a default tool, the project will be the
second WBArg.  If extended select was used, arguments other than the tool
are passed in the order of selection; the first icon selected will be
first (after the tool), and so on.

Each argument is a struct WBArg and has two parts:  wa_Name and wa_Lock.

    struct WBArg
    {
        BPTR      wa_Lock;    /* a lock descriptor */
        BYTE *    wa_Name;    /* a string relative to that lock */
    };

The wa_Name element is the name of an AmigaDOS filing system object.  The
wa_Name field of the first WBArg is always the name of your program and
the wa_Lock field is an AmigaDOS Lock on the directory where your program
is stored.

If your program was started by activating a project icon, then you get a
second WBarg with the wa_Name field containing the file name of the
project and the wa_Lock containing an AmigaDOS Lock on the directory where
the project file is stored.

If your program was started through extended select, then you get one
WBArg for each icon in the selected group in the order they were selected.
The wa_Name field contains the file name corresponding to each icon unless
the icon is for a directory, disk, or the Trashcan in which case the
wa_Name is set to NULL.  The wa_Lock field contains an AmigaDOS Lock on
the directory where the file is stored.  (For disk or drawer icons the
wa_Lock is a lock on the directory represented by the icon.  Or, wa_Lock
may be NULL if the icon type does not support locks.)

    Workbench Locks Belong to Workbench.
    ------------------------------------
    You must never call UnLock() on a wa_Lock.  These locks belong to
    Workbench, and Workbench will UnLock() them when the WBStartup
    message is replied by your startup code.  You must also never
    UnLock() your program's initial current directory lock (i.e., the
    lock returned by an initial CurrentDir() call).  The classic symptom
    caused by unlocking Workbench locks is a system hang after your
    program exits, even though the same program exits with no problems
    when started from the Shell.

    You should save the lock returned from an initial CurrentDir(), and
    CurrentDir() back to it before exiting.  In the Workbench
    environment, depending on your startup code, the current directory
    will generally be set to one of the wa_Locks.  By using
    CurrentDir(wa_Lock) and then referencing wa_Name, you can find, read,
    and modify the files that have been passed to your program as WBArgs.


14 Workbench and Icon Library / The Icon Library

The .info file is the center of interaction between applications and
Workbench.  To help support the Workbench iconic interface and manage
.info files, the Amiga operating system provides the icon library. The
icon library allows you to create icons for data files and directories
under program control and examine icons to obtain their Tool Types and
other characteristics.

 Icon Library Data Structures
 Icon Library Functions
 The Tool Types Array
 Example of Reading Icons and Parsing Tool Types


14 / The Icon Library / Icon Library Data Structures

The preceding sections discussed how icons are used to pass file name
arguments to an application run from the Workbench.  Workbench allows
other types of arguments to be passed in the Tool Types array of an icon.
To examine the Tool Types array or find other characteristics of the icon
such as its type, applications need to read in the .info file for the icon.

 The DiskObject Structure    The Gadget Structure


14 / / Icon Library Data Structures / The DiskObject Structure

The actual data present in the .info file is organized as a DiskObject
structure which is defined in the include file <workbench/workbench.h>.
For a complete listing, see the Amiga ROM Kernel Reference Manual:
Includes and Autodocs.  The DiskObject structure contains the following
elements:

    struct DiskObject
        {
        UWORD              do_Magic;   /* magic number at start of file */
        UWORD              do_Version; /* so we can change structure    */
        struct Gadget      do_Gadget;  /* a copy of in core gadget      */
        UBYTE              do_Type;
        char              *do_DefaultTool;
        char             **do_ToolTypes;
        LONG               do_CurrentX;
        LONG               do_CurrentY;
        struct DrawerData *do_DrawerData;
        char              *do_ToolWindow;  /* only applies to tools */
        LONG               do_StackSize;   /* only applies to tools */
        };

do_Magic
    A magic number that the icon library looks for to make sure that the
    file it is reading really contains an icon.  It should be the
    manifest constant WB_DISKMAGIC.  PutDiskObject() will put this value
    in the structure, and GetDiskObject() will not believe that a file is
    really an icon unless this value is correct.

do_Version
    This provides a way to enhance the .info file in an
    upwardly-compatible way.  It should be WB_DISKVERSION.  The icon
    library will set this value for you and will not believe weird values.

do_Gadget
    This contains all the imagery for the icon. See the "Gadget Structure"
    section below for more details.

do_Type
    The type of the icon; can be set to any of the following values.

            WBDISK     The root of a disk
            WBDRAWER   A directory on the disk
            WBTOOL     An executable program
            WBPROJECT  A data file
            WBGARBAGE  The Trashcan directory
            WBKICK     A Kickstart disk
            WBAPPICON  Any object not directly associated
                       with a filing system object, such as
                       a print spooler (new in Release 2).

               Table 14-2: Workbench Object Types

do_DefaultTool
    Default tools are used for project and disk icons.  For projects
    (data files), the default tool is the program Workbench runs when the
    project is activated.  Any valid AmigaDOS path may be entered in this
    field such as "SYS:myprogram", "df0:mypaint", "myeditor" or
    ":work/mytool".

    For disk icons, the default tool is the diskcopy program
    ("SYS:System/DiskCopy") that will be used when this disk is the
    source of a copy.

do_ToolTypes
    This is an array of free-format strings.  Workbench does not enforce
    any rules on these strings, but they are useful for passing
    environment information.  See the section on "The Tool Types Array"
    below for more information.

do_CurrentX, do_CurrentY
    Drawers have a virtual coordinate system.  The user can scroll around
    in this system using the scroll gadgets on the window that opens when
    the drawer is activated.  Each icon in the drawer has a position in
    the coordinate system.  CurrentX and CurrentY contain the icon's
    current position in the drawer.  Picking a position for a newly
    created icon can be tricky.  NO_ICON_POSITION is a system constant
    for do_CurrentX and do_CurrentY that instructs Workbench to pick a
    reasonable place for the icon.  Workbench will place the icon in an
    unused region of the drawer.  If there is no space in the drawers
    window, the icon will be placed just to the right of the visible
    region.

do_DrawerData
    If the icon is associated with a directory (WBDISK, WBDRAWER,
    WBGARBAGE), it needs a DrawerData structure to go with it.  This
    structure contains an Intuition NewWindow structure (see the
    "Intuition Windows" chapter for more information):

        struct DrawerData
            {
            struct NewWindow dd_NewWindow; /* structure to open window */
            LONG             dd_CurrentX;  /* current x coordinate of  */
                                           /* origin                   */
            LONG             dd_CurrentY;  /* current y coordinate of  */
                                           /* origin                   */
            };

    Workbench uses this to hold the current window position and size of
    the window so it will reopen in the same place.

do_ToolWindow
    This field is reserved for future use.

do_StackSize
    This is the size of the stack (in bytes) used for running the tool.
    If this is NULL, then Workbench will use a reasonable default stack
    size (currently 4K bytes).

    Stack Size is Taken from the Project Icon.
    -----------------------------------------
    When a tool is run via the default tool mechanism (i.e., a project
    was activated, not the tool itself), Workbench uses the stack size
    specified in the project's .info file and the tool's .info file is
    ignored.


14 / / Icon Library Data Structures / The Gadget Structure

To hold the icon's image, Workbench uses an Intuition Gadget structure,
defined in <intuition/intuition.h>.  Workbench restricts some of the
values of the gadget.  All unused fields should be set to 0 or NULL.  The
Intuition gadget structure members that Workbench icons use are listed
below.

    Gadget Names in Assembly Language Are Different.
    ------------------------------------------------
    The assembly language version of the Gadget structure has leading
    "gg_" for each variable name.

Width
    This is the width (in pixels) of the icon's active region.  Any mouse
    button press within this range will be interpreted as having selected
    this icon.

Height
    This is the height (in pixels) of the icon's active region.  Any
    mouse button press within this range will be interpreted as having
    selected this icon.

Flags
    The gadget must be of type GADGIMAGE.  Three highlight modes are
    supported:   GADGHCOMP, GADGHIMAGE, and GADGBACKFILL.  GADGHCOMP
    complements everything within the area defined by CurrentX, CurrentY,
    Width, Height.  GADGHIMAGE uses an alternate selection image.
    GADGBACKFILL is similar to GADGHCOMP, but ensures that there is no
    "ring" around the selected image.  It does this by first
    complementing the image, and then flooding all color 3 pixels that
    are on the border of the image to color 0.  All other flag bits
    should be 0.

Activation
    The activation should have only RELVERIFY and GADGIMMEDIATE set.

Type
    The gadget type should be BOOLGADGET.

GadgetRender
    Set this to an appropriate Image structure.

SelectRender
    Set this to an appropriate alternate Image structure if and only if
    the highlight mode is GADGHIMAGE.

The Image structure is typically the same size as the gadget, except that
Height is often one pixel less than the gadget height. This allows a blank
line between the icon image and the icon name. The image depth must be 2;
PlanePick must be 3; and PlaneOnOff should be 0. The NextImage field
should be null.


14 / The Icon Library / Icon Library Functions

The icon library functions do all the work needed to read, write and
examine an icon's .info file and corresponding DiskObject structure:

struct DiskObject *GetDiskObject(UBYTE *name);
struct DiskObject *GetDiskObjectNew(UBYTE *name);                     (V36)
BOOL               PutDiskObject(UBYTE *name, struct DiskObject *diskobj);
void               FreeDiskObject(struct DiskObject *diskobj);
BOOL               DeleteDiskObject(UBYTE *);                         (V37)

UBYTE             *FindToolType(UBYTE **toolTypeArray, UBYTE *typeName);
BOOL               MatchToolValue(UBYTE *typeString, UBYTE *value);

struct DiskObject *GetDefDiskObjectNew(LONG type);                    (V36)
BOOL               PutDefDiskObject(struct DiskObject *diskobj);      (V36)

UBYTE             *BumpRevision(UBYTE *newbuf, UBYTE *oldname);

The icon library routine GetDiskObject() reads an icon's .info file from
disk into a DiskObject structure it creates in memory where it can be
examined or altered.  PutDiskObject() writes the DiskObject out to disk
and FreeDiskObject() frees the memory it used. If you modify any pointers
in a DiskObject acquired via GetDiskObject(), replace the old pointers
before calling FreeDiskObject() so that the proper memory will be freed.

Release 2 includes a new function named GetDiskObjectNew() that works the
same as GetDiskObject(), except that if no .info file is found, a default
DiskObject will be created for you.  Also new for Release 2 is
DeleteDiskObject() for removing .info files from disk, and the functions
GetDefDiskObject() and PutDefDiskObject() which allow the default icons in
ROM to be copied or replaced with new defaults in RAM.

Once an icon's .info file has been read into a DiskObject structure, the
functions FindToolType() and MatchToolValue() can be used to examine the
icon's Tool Types array.


14 / The Icon Library / The Tool Types Array

Earlier sections discussed how Workbench passes filenames as arguments to
a program that's about to run.  Workbench also allows other types of
arguments to be passed in the Tool Types array of an icon. The Tool Types
array is found in the do_ToolTypes field of the icon's DiskObject
structure.

In brief, Tool Types is an array of pointers to strings that contain any
information an application wants to store such as the program options that
were in effect when the icon was created.  These strings can be used to
encode information which will be available to all applications that read
the icon's .info file.  Users can enter and change a selected icon's Tool
Types by choosing Information in the Workbench Icons menu.

Workbench does not place many restrictions on the Tool Types array, but
there are a few conventions you should follow.  A string may be no more
than 128 bytes long.  The alphabet used is 8-bit ANSI (for example, normal
ASCII with foreign-language extensions).  This means that users may enter
Tool Type strings containing international characters.  Avoid special or
nonprinting characters.  The case of the characters is currently
significant, so the string "Window" is not equal to "WINDOW".

The general format for a Tool Types entry is <name>=<value>[|<value>],
where <name> is the field name and <value> is the text to associate with
that name.  Multiple values for one name may be separated by a vertical
bar.  The values may be the type of the file, programs that can access the
data, parameters to be passed to an application, etc.  For example, a
paint program might set:

         FILETYPE = PaintProgram | ILBM

This Tool Type indicates that the file is an ILBM, perhaps with some
additional chunks of data specific to PaintProgram.

Tool Type strings have few restrictions but there are some reserved Tool
Types that are parsed by Workbench itself when an application is started
from an icon.  The reserved Tool Types are TOOLPRI=n (sets the Exec task
priority at which Workbench will start the application), STARTPRI=n (sets
the starting order for icons in the Wbstartup drawer), and DONOTWAIT
(tells Workbench not to wait for the return of a program started via an
icon in the Wbstartup drawer).  In addition to the reserved Tool Types,
which applications should not use, there are standard Tool Types, which
applications should use only in the standard way.  For a list of standard
Tool Types refer to the Amiga User Interface Style Guide.

Two routines are provided to help you deal with the Tool Types array.
FindToolType() returns the value of a Tool Type element.  Using the above
example, if you are looking for FILETYPE, the string "PaintProgram|ILBM"
will be returned.  MatchToolValue() returns nonzero if the specified
string is in the reference value string.  This routine knows how to parse
vertical bars.  For example, using the reference value strings of
"PaintProgram" or "ILBM", MatchToolValue() will return TRUE for "ILBM" and
"PaintProgram" and FALSE for everything else.


14 Workbench and Icon Library / The Workbench Library

Workbench arguments are sent to an application when it is started. There
are also special facilities in Release 2 of Workbench that allow an
application that is already running to get additional arguments.  These
special facilities are known as AppWindow, AppIcon and AppMenuItem.

An AppWindow is a special kind of window that allows the user to drag
icons into it.  Applications that set up an AppWindow will receive a
message from Workbench whenever the user moves an icon into the AppWindow.
The message contains the name of the file or directory that the icon
represents.

An AppIcon is similar to an AppWindow.  It is a special type of icon that
allows the user to drag other icons on top of it.  Like AppWindows, an
application that sets up an AppIcon will receive a message from Workbench
whenever the user moves another icon on top of the AppIcon.  The message
contains the name of the file or directory that the moved icon represents.

An AppMenuItem allows an application to add a custom menu item to the
usual set of menu choices supported by Workbench.  An application that
sets up an AppMenuItem will receive a message from Workbench whenever the
user picks that item from the Workbench menus.

When an application receives the messages described above, the message
will include struct WBArg *am_ArgList containing the names (wa_Name) and
directory locks (wa_Lock) of all selected icons that were passed as
arguments by the user.  This am_ArgList has the same format as the
sm_ArgList of a WBStartup message.

 Workbench Library Functions    An AppMenuItem Example
 An AppIcon Example             An AppWindow Example


14 / The Workbench Library / Workbench Library Functions

AppWindows, AppIcons and AppMenuItems extend the user's ability to perform
operations with the Workbench iconic interface.  They all provide
graphical methods for passing arguments to a running application. In order
to manage AppWindows, AppIcons and AppMenuItems, the Amiga OS includes
these Workbench library functions:

struct AppIcon     *AddAppIconA( ULONG, ULONG, char *, struct MsgPort *,
                                 struct FileLock *, struct DiskObject *,
                                 struct *TagItem );
struct AppMenuItem *AddAppMenuItemA( ULONG, ULONG, char *,
                                     struct MsgPort *, struct *TagItem);
struct AppWindow   *AddAppWindowA( ULONG, ULONG, struct Window *,
                                   struct MsgPort *, struct *TagItem);

BOOL                RemoveAppIcon(struct AppIcon *);
BOOL                RemoveAppMenuItem(struct AppMenuItem *);
BOOL                RemoveAppWindow(struct AppWindow  *);

The functions AddAppMenuItemA(), AddAppWindowA() and AddAppIconA() have
alternate entry points using the same function name without the trailing
A.  The alternate functions accept any TagItem arguments on the stack
instead of from an array. See the listings below for examples.


14 Workbench and Icon Library / Workbench and the Startup Code Module

Standard startup code handles the detail work of interfacing with the
arguments and environment of Workbench and the Shell (or CLI).  This
section describes the behavior of standard startup modules such as the
ones supplied with SAS (Lattice) C and Manx Aztec C.

The environment for a program started from Workbench is quite different
from the environment for a program started from the Shell.  The Shell does
not create a new process for a program; it jumps to the program's code and
the program shares the process with the Shell.  Programs run under the
Shell have access to all the Shell's environment, including the ability to
modify that environment.  (Programs run from the Shell should be careful
to restore all values that existed on startup.) Workbench starts a program
as a new DOS process, explicitly passing the execution environment to the
program.

 Workbench Startup    Shell Startup


14 / Workbench and the Startup Code Module / Workbench Startup

When the user activates a project or tool icon, the program is run as a
separate process asynchronous to Workbench.  This allows the user to take
full advantage of the multitasking features of the Amiga.  A process is
simply a task with additional information needed to use DOS library.

When Workbench loads and starts a program, its sends the program a
WBStartup message containing the arguments as described earlier.  The
WBStartup also contains a pointer to the new Process structure which
describes the execution environment of the program.  The WBStartup message
is posted to the message port of the program's Process structure.

The Process message port is for the exclusive use of DOS, so this message
must be removed from the port before using any DOS library functions.
Normally this is handled by the startup code module that comes with your
compiler so you don't have to worry about this unless you are writing your
own startup code.

Standard startup code modules also set up SysBase, the pointer to the Exec
master library, and open the DOS library setting up DOSBase.   That is why
Exec and AmigaDOS functions can be called by C applications without first
opening a library; the startup code that applications are linked with
handles this.  Some special startups may also set up NIL: input and output
streams, or may open a stdio window so that the Workbench applications can
use stdio functions such as printf().

The startup code can tell if it is running in the Workbench environment
because the pr_CLI field of the Process structure will contain NULL.  In
that case the startup code removes the WBStartup message from the Process
message port with GetMsg() before using any functions in the DOS library.

    Do Not Use the Process Message Port for Anything Else.
    ------------------------------------------------------
    The message port in a Process structure is for the exclusive use
    of the DOS library.

Standard startup code will pass the WBStartup message pointer in argv and
0 (zero) in argc if the program is started from Workbench.  These values
are pushed onto the stack, and the startup code calls the application code
that it is linked with as a function.  When the application code exits
back to the startup code, the startup code closes and frees all opens and
allocations it made.  It will then Forbid(), and ReplyMsg() the WBStartup
message, notifying Workbench that the application Process may be
terminated and its code unloaded from memory.

    Avoid the DOS Exit() function.
    ------------------------------
    The DOS Exit() function does not return an application to the
    startup code that called it.  If you wish to exit your application,
    use the exit function provided by your startup code (usually
    lower-case exit(), or _exit for assembler), passing it a valid
    DOS return code as listed in the include file <libraries/dos.h>.


14 / Workbench and the Startup Code Module / Shell Startup

When a program is started from the Shell (or a Shell script), standard
startup modules will parse the command line (received in A0, with length
in D0) into an array of pointers to individual argument strings placing
them in argv, and an argument count in argc.

If a program is started from the Shell, argc will always equal at least
one and the first element in argv will always be a pointer to the command
name.  Other command line arguments are stored in turn. For example, if
the command line was:

     df0:myprogram   "my file1"   file2    ;this is a comment

then argc will be 3, argv[0] will be "df0:myprogram", argv[1] will be "my
file1", and argv[2] will be "file2".  Correct startup code will strip
spaces between arguments and trailing spaces from the last argument and
will also properly deal with quoted arguments with embedded spaces.

As with Workbench, standard startup code for the Shell sets up SysBase,
the pointer to the Exec master library, and opens the DOS library setting
up DOSBase.  C applications that are linked with standard startup code can
call an Exec or AmigaDOS functions without opening the library first.

The startup code also fills in the stdio file handles (_stdin, _stdout,
etc.) for the application.  Finally argv and argc, are pushed onto the
stack and the application is called via a JSR.  When the application
returns or exits back to the startup code, the startup code closes and
frees all opens and allocations it has made for the application, and then
returns to the system with the whatever value the program exited with.

Link your applications only with standard, tested startup code of some
type such as the module supplied with your compiler.  Startup code
provides your programs with correct, consistent handling of Shell command
line and Workbench arguments and will perform some initializations and
cleanups which would otherwise need to be handled by your own code.  Very
small startups can be used for programs that do not require command line
arguments.

A few words of warning for those of you who do not use standard startup
code:

  * If you are started as a Workbench process, you must GetMsg() the
    WBStartup message before using any functions in the DOS library.

  * You must turn off task switching (with Forbid()) before replying the
    WBStartup message from Workbench.  This will prevent Workbench from
    unloading your code before you can exit properly.

  * If you do your own command line parsing, you must provide the user
    with consistent and correct handling of command line arguments.


14 Workbench and Icon Library / Function Reference

The following are brief descriptions of the functions in workbench.library
and icon.library.  See the Amiga ROM Kernel Reference Manual: Includes and
Autodocs for details on each function call.

                    Table 14-3: Icon Library Functions
  _______________________________________________________________________
 |                                                                       |
 |         Function                  Description                         |
 |=======================================================================|
 |      GetDiskObject()  Read the .info file of an icon into a           |
 |                       DiskObject structure                            |
 |   GetDiskObjectNew()  Same as GetDiskObject() but returns a default   |
 |                       icon if none exists                             |
 |      PutDiskObject()  Write a DiskObject structure to disk as a       |
 |                       .info file                                      |
 |     FreeDiskObject()  Free the DiskObject structure created by        |
 |                       GetDiskObject()                                 |
 |   DeleteDiskObject()  Deletes a given .info file from disk            |
 |-----------------------------------------------------------------------|
 |       FindToolType()  Return the value of an entry in the icon's Tool |
 |                       Type array                                      |
 |     MatchToolValue()  Check a Tool Type entry against a given value   |
 |-----------------------------------------------------------------------|
 |   GetDefDiskObject()  Read the default icon for a given icon type     |
 |   PutDefDiskObject()  Replace the default icon for a given icon type  |
 |                       (V36)                                           |
 |-----------------------------------------------------------------------|
 |        AddFreeList()  Add memory you have allocated to a FreeList     |
 |       FreeFreeList()  Free all the memory for entries in the FreeList |
 |       BumpRevision()  Create a new name for a second copy of a        |
 |                       Workbench object                                |
 |_______________________________________________________________________|

                 Table 14-4: Workbench Library Functions
  _______________________________________________________________________
 |                                                                       |
 |         Function                  Description                         |
 |=======================================================================|
 |         AddAppIcon()  Add an AppIcon to Workbench                     |
 |     AddAppMenuItem()  Add an AppMenuItem to the Workbench Tools menu  |
 |       AddAppWindow()  Add an AppWindow to Workbench                   |
 |-----------------------------------------------------------------------|
 |      RemoveAppIcon()  Remove an AppIcon to Workbench                  |
 |  RemoveAppMenuItem()  Remove an AppMenuItem to the Workbench Tools    |
 |                       menu                                            |
 |    RemoveAppWindow()  Remove an AppWindow to Workbench                |
 |_______________________________________________________________________|


Amiga® RKM Libraries: 15 GadTools Library

GadTools is a new library in Release 2 that is designed to simplify the
task of creating user interfaces with Intuition.  GadTools offers a
flexible and varied selection of gadgets and menus to help programmers
through what used to be a difficult chore.

Intuition, the Amiga's graphical user interface, is a powerful and
flexible environment.  It allows a software designer a great degree of
flexibility in creating dynamic and powerful user interfaces.  However,
the drawback of this flexibility is that programming even straightforward
user interfaces can be complicated, and certainly difficult for first-time
Intuition programmers.

What the Gadget Toolkit (GadTools) attempts to do is harness the power of
Intuition by providing easy-to-use, high-level chunks of user interface.
GadTools doesn't pretend to answer all possible user interface needs of
every application but by meeting the user interface needs of most
applications, GadTools greatly simplifies the problem of designing
user-friendly software on the Amiga.  (For applications with special
needs, custom solutions can be created with Intuition's already-familiar
gadgets or its new Boopsi object-oriented custom gadget system; GadTools
is compatible with these.)

 Elements of GadTools    GadTools Gadgets
 GadTools Menus          Function Reference


15 GadTools Library / Elements of GadTools

GadTools is the easy way to program gadgets and menus.  With GadTools, the
system handles the detail work required to control gadgets and menus so
the application uses less code and simpler data structures.

Another key benefit of GadTools is its standardized and elegant look.  All
applications that use GadTools will share a similar appearance and
behavior.  Users will appreciate a sense of instant familiarity even the
first time they use a product.

GadTools provides a significant degree of visual consistency across
multiple applications that use it.  For instance, in Release 2, the
Preferences editors, the Workbench "Information" window and Commodities
Exchange share the same polished look and feel thanks to GadTools.  There
is also internal consistency between different elements of GadTools; the
look is clean and orderly.  Depth is used not just for visual
embellishment, but as an important cue.  For instance, the user is free to
select symbols that appear inside a "raised" area, but "recessed" areas
are informational only, and clicking in them has no effect.

GadTools is not amenable to creative post-processing or hacking by
programmers looking to achieve a result other than what GadTools currently
offers.  Software developers whose needs extend beyond the standard
features of GadTools should create custom gadgets that share the look and
feel of GadTools by using either BOOPSI or by directly programming gadgets
at a lower level.  See the chapters on "Intuition Gadgets" and "BOOPSI"
for more information.  Follow the GadTools rules.  Only in this way may
GadTools grow and improve without hindrance, even allowing new features to
automatically appear in future software when reasonable.

 GadTools Tags


15 / Elements of GadTools / GadTools Tags

Many of the GadTools functions use TagItem arrays or tag lists to pass
information across the function interface.  These tag-based functions come
in two types, one that takes a pointer to an array of tag items and one
that takes a variable number of tag item arguments directly in the
function call.  In general, the second form, often called the varargs form
because the call takes a variable number of arguments, is provided for
convenience and is internally converted to the first form.  When looking
through the Autodocs or other Amiga reference material, the documentation
for both forms is usually available in the array-based function
description.

All GadTools tags begin with a leading "GT".  In general, they also have a
two-letter mnemonic for the kind of gadget in question.  For example,
slider gadgets recognize tags such as "GTSL_Level".  The GadTools tags are
defined in <libraries/gadtools.h>.  Certain GadTools gadgets also
recognize other Intuition tags such as GA_Disabled and PGA_Freedom, which
can be found in <intuition/gadgetclass.h>.

For more information on tags and tag-based functions, be sure to see the
"Utility Library" chapter in this manual.


15 GadTools Library / GadTools Menus

GadTools menus are easy to use.  Armed only with access to a VisualInfo
data structure, GadTools allows the application to easily create, layout
and delete Intuition menus.

Normally, the greatest difficulty in creating menus is that a large number
of structures must be filled out and linked.  This is bothersome since
much of the required information is orderly and is easier to do
algorithmically than to do manually.  GadTools handles this for you.

There are also many complexities in creating a sensible layout for menus.
This includes some mechanical items such as handling various font sizes,
automatic columnization of menus that are too tall and accounting for
space for checkmarks and Amiga-key equivalents.  There are also aesthetic
considerations, such as how much spacing to provide, where sub-menus
should be placed and so on.

GadTools menu functions support all the features that most applications
will need.  These include:

  * An easily constructed and legible description of the menus.

  * Font-sensitive layout.

  * Support for menus and sub-menus.

  * Sub-menu indicators (a ">>" symbol attached to items with sub-menus).

  * Separator bars for sectioning menus.

  * Command-key equivalents.

  * Checkmarked and mutually exclusive checkmarked menu items.

  * Graphical menu items.

With GadTools, it takes only one structure, the NewMenu structure, to
specifiy the whole menu bar,  For instance, here is how a typical menu
strip containing two menus might be specified:

    struct NewMenu mynewmenu[] =
        {
            { NM_TITLE, "Project",    0 , 0, 0, 0,},
            {  NM_ITEM, "Open...",   "O", 0, 0, 0,},
            {  NM_ITEM, "Save",      "S", 0, 0, 0,},
            {  NM_ITEM, NM_BARLABEL,  0 , 0, 0, 0,},
            {  NM_ITEM, "Print",      0 , 0, 0, 0,},
            {   NM_SUB, "Draft",      0 , 0, 0, 0,},
            {   NM_SUB, "NLQ",        0 , 0, 0, 0,},
            {  NM_ITEM, NM_BARLABEL,  0 , 0, 0, 0,},
            {  NM_ITEM, "Quit...",   "Q", 0, 0, 0,},

            { NM_TITLE, "Edit",       0 , 0, 0, 0,},
            {  NM_ITEM, "Cut",       "X", 0, 0, 0,},
            {  NM_ITEM, "Copy",      "C", 0, 0, 0,},
            {  NM_ITEM, "Paste",     "V", 0, 0, 0,},
            {  NM_ITEM, NM_BARLABEL,  0 , 0, 0, 0,},
            {  NM_ITEM, "Undo",      "Z", 0, 0, 0,},

            {   NM_END, NULL,         0 , 0, 0, 0,},
        };

This NewMenu specification would produce the two menus below:

     Figure 15-1: Two Example Menus

The NewMenu arrays are designed to be read easily.  The elements in the
NewMenu array appear in the same order as they will appear on-screen.
Unlike the lower-level menu structures described in the "Intuition Menus"
chapter earlier, there is no need to specify sub-menus first, then the
menu items with their sub-menus, and finally the menu headers with their
menu items.  The indentation shown above also helps highlight the
relationship between menus, menu items and sub-items.

 The NewMenu Structure           GadTools Menus And IntuiMessages
 GadTools Menus Example          Restrictions on GadTools Menus
 Functions for GadTools Menus    Language-Sensitive Menus


15 / GadTools Menus / The NewMenu Structure

The NewMenu structure used to specify GadTools menus is defined in
<libraries/gadtools.h> as follows:

    struct NewMenu
        {
        UBYTE nm_Type;
        STRPTR nm_Label;
        STRPTR nm_CommKey;
        UWORD nm_Flags;
        LONG nm_MutualExclude;
        APTR nm_UserData;
        };

nm_Type
    The first field, nm_Type, defines what this particular NewMenu
    describes.  The defined types provide an unambiguous and convenient
    representation of the application's menus.

    NM_TITLE
        Used to signify a textual menu heading.  Each NM_TITLE signifies
        the start of a new menu within the menu strip.

    NM_ITEM or IM_ITEM
        Used to signify a textual (NM_ITEM) or graphical (IM_ITEM) menu
        item.  Each NM_ITEM or IM_ITEM becomes a menu item in the
        current menu.

    NM_SUB or IM_SUB
        Used to signify a textual (NM_SUB) or graphical (IM_SUB) menu
        sub-item.  All the consecutive NM_SUBs and IM_SUBs that follow a
        menu item (NM_ITEM or IM_ITEM) compose that item's sub-menu.  A
        subsequent NM_ITEM or IM_ITEM would indicate the start of the
        next item in the original menu, while a subsequent NM_TITLE
        would begin the next menu.

    NM_END
        Used to signify the end of the NewMenu structure array.  The
        last element of the array must have NM_END as its type.

nm_Label
    NM_TITLE, NM_ITEM and NM_SUB are used for textual menu headers, menu
    items and sub-items respectively, in which case nm_Label points to
    the string to be used.  This string is not copied, but rather a
    pointer to it is kept.  Therefore the string must remain valid for
    the active life of the menu.

    Menus don't have to use text, GadTools also supports graphical menu
    items and sub-items (graphical menu headers are not possible since
    they are not supported by Intuition). Simply use IM_ITEM and IM_SUB
    instead and point nm_Label at a valid Image structure.  The Image
    structure can contain just about any graphic image (see the chapter
    on "Intuition Images, Line Drawing and Text" for more on this).

    Sometimes it is a good idea to put a separator between sets of menu
    items or sub-items.  The application may want to separate drastic
    menu items such as "Quit" or "Delete" from more mundane ones.
    Another good idea is to group related checkmarked items by using
    separator bars.

    NM_BARLABEL
        GadTools will provide a separator bar if the special constant
        NM_BARLABEL is supplied for the nm_Label field of an NM_ITEM or
        NM_SUB.

nm_CommKey
    A single character string used as the Amiga-key equivalent for the
    menu item or sub-item.

    Menu headers cannot have command keys.  Note that assigning a
    command-key equivalent to a menu item that has sub-items is
    meaningless and should be avoided.

    The nm_CommKey field is a pointer to a string and not a character
    itself.  This was done in part because routines to support different
    languages typically return strings, not characters.  The first
    character of the string is actually copied into the resulting
    MenuItem structure.

nm_Flags
    The nm_Flags field of the NewMenu structure corresponds roughly to
    the Flags field of the Intuition's lower-level Menu and MenuItem
    structures.

    For programmer convenience the sense of the Intuition MENUENABLED and
    ITEMENABLED flags are inverted.  When using GadTools, menus, menu
    items and sub-items are enabled by default.

    NM_MENUDISABLED
        To specify a disabled menu, set the NM_MENUDISABLED flag in this
        field.

    NM_ITEMDISABLED
        To disable an item or sub-item, set the NM_ITEMDISABLED flag.

    The Intuition flag bits COMMSEQ (indication of a command-key
    equivalent), ITEMTEXT (indication of a textual or graphical item) and
    HIGHFLAGS (method of highlighting) will be automatically set
    depending on other attributes of the menus.  Do not set these values
    in nm_Flags.

    The nm_Flags field is also used to specify checkmarked menu items.
    To get a checkmark that the user can toggle, set the CHECKIT and
    MENUTOGGLE flags in the nm_Flags field.  Also set the CHECKED flag if
    the item or sub-item is to start in the checked state.

nm_MutualExclude
    For specifying mutual exclusion of checkmarked items.  All the items
    or sub-items that are part of a mutually exclusive set should have
    the CHECKIT flag set.

    This field is a bit-wise representation of the items (or sub-items),
    in the same menu or sub-menu, that are excluded by this item (or
    sub-item).  In the simple case of mutual exclusion, where each choice
    excludes all others, set nm_MutualExclude to ~(1<<item number) or ~1,
    ~2, ~4, ~8, etc.  Separator bars count as items and should be
    included in the position calculation.  See the "Intuition Menus"
    chapter for more details on menu mutual exclusion.

nm_UserData
    The NewMenu structure also has a user data field.  This data is
    stored with the Intuition Menu or MenuItem structures that GadTools
    creates. Use the macros GTMENU_USERDATA(menu) and
    GTMENUITEM_USERDATA(menuitem) defined in <libraries/gadtools.h> to
    extract or change the user data fields of menus and menu items,
    respectively.

    The application may place index numbers in this field and perform a
    switch statement on them, instead of using the Intuition menu
    numbers.  The advantage of this is that the numbers chosen remain
    valid even if the menus are rearranged, while the Intuition menu
    numbers would change when the menus are rearranged.

    Alternately, an efficient technique for menu handling is to create a
    handler function for each menu item and put a pointer to that
    function in the corresponding item's UserData field.  When the
    program receives a IDCMP_MENUPICK message it may call the selected
    item's function through this field.


15 / GadTools Menus / Functions for GadTools Menus

In this section the basic GadTools menu functions are presented.  See the
listing above for an example of how to use these functions.

 Creating Menus         Layout for Individual Menus
 Layout of the Menus    Freeing Menus


15 / / Functions for GadTools Menus / Creating Menus

The CreateMenus() function takes an array of NewMenus and creates a set of
initialized and linked Intuition Menu, MenuItem, Image and IntuiText
structures, that need only to be formatted before being used.  Like the
other tag-based functions, there is a CreateMenusA() call that takes a
pointer to an array of TagItems and a CreateMenus() version that expects
to find its tags on the stack.

    struct Menu *CreateMenusA( struct NewMenu *newmenu,
                               struct TagItem *taglist );
    struct Menu *CreateMenus( struct NewMenu *newmenu, Tag tag1, ... );

The first argument to these functions, newmenu, is a pointer to an array
of NewMenu structures as described earlier.  The tag arguments can be any
of the following items:

GTMN_FrontPen (ULONG)
    The pen number to use for menu text and separator bars.  The default
    is zero.

GTMN_FullMenu (BOOL)
    (New for V37, ignored under V36).  This tag instructs CreateMenus()
    to fail if the supplied NewMenu structure does not describe a
    complete Menu structure.  This is useful if the application does not
    have direct control over the NewMenu description, for example if it
    has user-configurable menus.  The default is FALSE.

GTMN_SecondaryError (ULONG *)
    (New for V37, ignored under V36).  This tag allows CreateMenus() to
    return some secondary error codes.  Supply a pointer to a
    NULL-initialized ULONG, which will receive an appropriate error code
    as follows:

    GTMENU_INVALID
        Invalid menu specification.  For instance, a sub-item directly
        following a menu-title or an incomplete menu.  CreateMenus()
        failed in this case, returning NULL.

    GTMENU_NOMEM
        Failed for lack of memory.  CreateMenus() returned NULL.

    GTMENU_TRIMMED
        The number of menus, items or sub-items exceeded the maximum
        number allowed so the menu was trimmed.  In this case,
        CreateMenus() does not fail but returns a pointer to the trimmed
        Menu structure.

    NULL
        If no error was detected.

CreateMenus() returns a pointer to the first Menu structure created, while
all the MenuItem structures and any other Menu structures are attached
through the appropriate pointers.  If the NewMenu structure begins with an
entry of type NM_ITEM or IM_ITEM, then CreateMenus() will return a pointer
to the first MenuItem created, since there will be no first Menu
structure.  If the creation fails, usually due to a lack of memory,
CreateMenus() will return NULL.

Starting with V37, GadTools will not create any menus, menu items or
sub-items in excess of the maximum number allowed by Intuition.  Up to 31
menus may be defined, each menu with up to 63 items, each item with up to
31 sub-items.  See the "Intuition Menus" chapter for more information on
menus and their limitations.  If the NewMenu array describes a menu that
is too big, CreateMenus() will return a trimmed version.
GTMN_SecondaryError can be used to learn when this happens.

Menus need to be added to the window with Intuition's SetMenuStrip()
function.  Before doing this, they must be formatted with a call to
LayoutMenus().


15 / / Functions for GadTools Menus / Layout of the Menus

The Menu and MenuItem structures returned by CreateMenus() contain no size
or positional information.  This information is added in a separate layout
step, using LayoutMenus().  As with the other tag-based functions, the
program may call either LayoutMenus() or LayoutMenusA().

    BOOL LayoutMenusA( struct Menu *firstmenu, APTR vi,
                       struct TagItem *taglist );
    BOOL LayoutMenus( struct Menu *firstmenu, APTR vi, Tag tag1, ... );

Set firstmenu to a pointer to a Menu structure returned by a previous call
to CreateMenus().  The vi argument is a a VisualInfo handle obtained from
GetVisualInfo().  See the documentation of GadTools gadgets below for more
about this call.  For the tag arguments, tag1 or taglist, LayoutMenus()
recognizes a single tag:

GTMN_TextAttr
    A pointer to an openable font (TextAttr structure) to be used for the
    menu item and sub-item text.  The default is to use the screen's font.

LayoutMenus() fills in all the size, font and position information for the
menu strip.  LayoutMenus() returns TRUE if successful and FALSE if it
fails.  The usual reason for failure is that the font supplied cannot be
opened.

LayoutMenus() takes care of calculating the width, height and position of
each individual menu item and sub-item, as well as the positioning of all
menus and sub-menus.  In the event that a menu would be too tall for the
screen, it is broken up into multiple columns.  Additionally, whole menus
may be shifted left from their normal position to ensure that they fit on
screen.  If a large menu is combined with a large font, it is possible,
even with columnization and shifting, to create a menu too big for the
screen.  GadTools does not currently trim off excess menus, items or
sub-items, but relies on Intuition to clip menus at the edges of the
screen.

It is perfectly acceptable to change the menu layout by calling
ClearMenuStrip() to remove the menus, then LayoutMenus() to make the
change and then SetMenuStrip() to display the new layout.  Do this when
changing the menu's font (this can be handled by a tag to LayoutMenus()),
or when updating the menu's text (to a different language, for instance).
Run-time language switching in menus will be discussed later.


15 / / Functions for GadTools Menus / Layout for Individual Menus

LayoutMenuItems() performs the same function as LayoutMenus(), but only
affects the menu items and sub-items of a single menu instead of the whole
menu strip.  Ordinarily, there is no need to call this function after
having called LayoutMenus().  This function is useful for adding menu
items to an extensible menu, such as the Workbench "Tools" menu.

For example, a single MenuItem can be created by calling CreateMenus()
with a two-entry NewMenu array whose first entry is of type NM_ITEM and
whose second is of type NM_END.  The menu strip may then be removed and
this new item linked to the end of an extensible menu by placing its
address in the NextItem field of the last MenuItem in the menu.
LayoutMenuItems() can then be used to to recalculate the layout of just
the items in the extensible menu and, finally, the menu strip can be
reattached to the window.

    BOOL LayoutMenuItemsA( struct MenuItem *firstitem, APTR vi,
                           struct TagItem *taglist );
    BOOL LayoutMenuItems( struct MenuItem *firstitem, APTR vi,
                          Tag tag1, ... );

Set firstitem to a pointer to the first MenuItem in the linked list of
MenuItems that make up the Menu.  (See the "Intuition Menus" chapter for
more about these structures.)  Set vi to the address of a VisualInfo
handle obtained from GetVisualInfo(). The tag arguments, tag1 or taglist,
may be set as follows:

GTMN_TextAttr
    A pointer to an openable font (TextAttr structure) to be used for the
    menu item and sub-item text.  The default is to use the screen's font.

GTMN_Menu
    Use this tag to provide a pointer to the Menu structure whose
    FirstItem is passed as the first parameter to this function.  This
    tag should always be used.

LayoutMenuItems() returns TRUE if it succeeds and FALSE otherwise.


15 / / Functions for GadTools Menus / Freeing Menus

The FreeMenus() function frees all the memory allocated by the
corresponding call to CreateMenus().

    void FreeMenus( struct Menu *menu );

Its one argument is the Menu or MenuItem pointer that was returned by
CreateMenus().  It is safe to call FreeMenus() with a NULL parameter,  the
function will then return immediately.


15 / GadTools Menus / GadTools Menus and IntuiMessages

If the window uses GadTools menus and GadTools gadgets, then use the
GT_GetIMsg() and GT_ReplyIMsg() functions described below (or
GT_FilterIMsg() and GT_PostFilterIMsg(), if applicable).  However, if the
window has GadTools menus, but no GadTools gadgets, it is acceptable to
use GetMsg() and ReplyMsg() in the usual manner.

Additionally, no context need be created with CreateContext() if no
GadTools gadgets are used.  For more about these functions, see the
section on "Other GadTools Functions" later in this chapter.


15 / GadTools Menus / Restrictions on GadTools Menus

GadTools menus are regular Intuition menus.  Once the menus have been laid
out, the program may do anything with them, including attaching them or
removing them from windows, enabling or disabling items, checking or
unchecking checkmarked menu items, etc.  See the documentation for
SetMenuStrip(), ClearMenuStrip(), ResetMenuStrip(), OnMenu() and OffMenu()
in the "Intuition Menus" chapter for full details.

If a GadTools-created menu strip is not currently attached to any window,
the program may change the text in the menu headers (Menu->MenuName), the
command-key equivalents (MenuItem->Command) or the text or imagery of menu
items and sub-items, which can be reached as:

    ((struct IntuiText *)MenuItem->ItemFill)->IText
or
    ((struct Image *)MenuItem->ItemFill)

The application may also link in or unlink menus, menu items or sub-items.
However, do not add sub-items to a menu item that was not created with
sub-items and do not remove all the sub-items from an item that was
created with some.

Any of these changes may be made, provided the program subsequently calls
LayoutMenus() or LayoutMenuItems() as appropriate.  Then, reattach the
menu strip using SetMenuStrip().

Some of these manipulations require walking the menu strip using the usual
Intuition-specified linkages.  Beginning with the first Menu structure,
simply follow its FirstItem pointer to get to the first MenuItem.  The
MenuItem->SubItem pointer will lead to the sub-menus.  MenuItems are
connected via the MenuItem->NextItem field.  Successive menus are linked
together with the Menu->NextMenu pointer.  Again, see the chapter
"Intuition Menus" for details.


15 / GadTools Menus / Language-Sensitive Menus

Allowing the application to switch the language displayed in the menus,
can be done quite easily.  Simply detach the menu strip and replace the
strings in the IntuiText structures as described above.  It may be
convenient to store some kind of index number in the Menu and MenuItem
UserData which can be used to retrieve the appropriate string for the
desired language.  After all the strings have been installed, call
LayoutMenus() and SetMenuStrip().

If the application has the localized strings when the menus are being
created, it simply places the pointers to the strings and command
shortcuts into the appropriate fields of the NewMenu structure.  The menus
may then be processed in the normal way.


15 GadTools Library / GadTools Gadgets

The heart of GadTools is in its ability to easily create and manipulate a
sophisticated and varied array of gadgets.  GadTools supports the
following kinds of gadgets:

  Table 15-1: Standard Gadget Types Supported by the GadTools Library

    Gadget Type         Description or Example Usage
    -----------         ----------------------------
    Button              Familiar action gadgets, such as "OK" or "Cancel".
    String              For text entry.
    Integer             For numeric entry.
    Checkboxes          For on/off items.
    Mutually exclusive  Radio buttons, select one choice among several.
    Cycle               Multiple-choice, pick one of a small number of
                        choices.
    Sliders             To indicate a level within a range.
    Scrollers           To indicate a position in a list or area.
    Listviews           Scrolling lists of text.
    Palette             Color selection.
    Text-display        Read-only text.
    Numeric-display     Read-only numbers.

GadTools gadget handling consists of a body of routines to create, manage
and delete any of the 12 kinds of standard gadgets listed in table 15-1,
such as buttons, sliders, mutually exclusive buttons and scrolling lists.

To illustrate the flexibility, power and simplicity that GadTools offers,
consider the GadTools slider gadget.  This gadget is used to indicate and
control the level of something, for example volume, speed or color
intensity.  Without GadTools, applications have to deal directly with
Intuition proportional and their arcane variables, such as HorizBody to
control the slider knob's size and HorizPot to control the knob's
position.  Using the GadTools slider allows direct specification of the
minimum and maximum levels of the slider, as well as its current level.
For example, a color slider might have a minimum level of 0, a maximum
level of 15 and a current level of 11.

To simplify event-processing for the slider, GadTools only sends the
application a message when the knob has moved far enough to cause the
slider level, as expressed in application terms, to change.  If a user
were to slowly drag the knob of this color slider all the way to the
right, the program will only hear messages for levels 12, 13, 14 and 15,
with an optional additional message when the user releases the
mouse-button.

Changing the current level of the slider from within the program is as
simple as specifying the new level in a function call.  For instance, the
application might set the slider's value to 5.

As a final point, the slider is very well-behaved.  When the user releases
the mouse-button, the slider immediately snaps to the centered position
for the level.  If a user sets their background color to light gray, which
might have red = green = blue = 10, all three color sliders will have
their knobs at precisely the same relative position, instead of anywhere
in the range that means "ten".

 The NewGadget Structure
 Creating Gadgets
 Handling Gadget Messages
 IDCMP Flags
 Freeing Gadgets
 Simple GadTools Gadget Example
 Modifying Gadgets
 The Kinds of GadTools Gadgets
 Functions for Setting Up GadTools Menus and Gadgets
 Creating Gadget Lists
 Gadget Refresh Functions
 Other GadTools Functions
 Gadget Keyboard Equivalents
 Complete GadTools Gadget Example
 Restrictions on GadTools Gadgets
 Documented Side-Effects


15 / GadTools Gadgets / The NewGadget Structure

For most gadgets, the NewGadget structure is used to specify its common
attributes.  Additional attributes that are unique to specific kinds of
gadgets are specified as tags sent to the CreateGadget() function
(described below).

The NewGadget structure is defined in <libraries/gadtools.h> as:

    struct NewGadget
        {
        WORD ng_LeftEdge, ng_TopEdge;
        WORD ng_Width, ng_Height;
        UBYTE *ng_GadgetText;
        struct TextAttr *ng_TextAttr;
        UWORD ng_GadgetID;
        ULONG ng_Flags;
        APTR ng_VisualInfo;
        APTR ng_UserData;
        };

The fields of the NewGadget structure are used as follows:

ng_LeftEdge, ng_TopEdge
    Define the position of the gadget being created.

ng_Width and ng_Height
    Define the size of the gadget being created.

ng_GadgetText
    Most gadgets have an associated label, which might be the text in a
    button or beside a checkmark.  This field contains a pointer to the
    appropriate string.  Note that only the pointer to the text is
    copied, the text itself is not.  The string supplied must remain
    constant and valid for the life of the gadget.

ng_TextAttr
    The application must specify a font to use for the label and any
    other text that may be associated with the gadget.

ng_Flags
    Used to describe general aspects of the gadget, which includes where
    the label is to be placed and whether the label should be rendered in
    the highlight color.  The label may be positioned on the left side,
    the right side, centered above, centered below or dead-center on the
    gadget.  For most gadget kinds, the label is placed on the left side
    by default, exceptions will be noted.

ng_GadgetID, ng_UserData
    These user fields are copied into the resulting Gadget structure.

ng_VisualInfo
    This field must contain a pointer to an instance of the VisualInfo
    structure, which contains information needed to create and render
    GadTools gadgets.  The VisualInfo structure itself is private to
    GadTools and subject to change.  Use the specialized GadTools
    functions for accessing the VisualInfo pointer, defined below.  Never
    access or modify fields within this structure.


15 / GadTools Gadgets / Creating Gadgets

The main call used to create a gadget with GadTools is CreateGadget().
This function can be used to create a single gadget or it can be called
repeatedly to create a linked list of gadgets.  It takes three arguments
followed by a set of tags:

    struct Gadget *CreateGadget( ULONG kind, struct Gadget *prevgad,
                                 struct NewGadget *newgad,
                                 struct TagItem *taglist)
    struct Gadget *CreateGadgetA(ULONG kind, struct Gadget *prevgad,
                                 struct NewGadget *newgad,
                                 struct Tag tag1, ...)

Set the kind argument to one of the 12 gadget types supported by GadTools.
Set the prevgad argument to the gadget address returned by CreateContext()
if this is the first (or only) gadget in the list.  Subsequent calls to
CreateGadget() can be used to create and link AutoDocs/gadgets together in a list
in which case the prevgad argument is set to the address of the gadget
returned by the preceding call to CreateGadget().

Set the newgad argument to the address of the NewGadget structure
describing the gadget to be created and set any special attributes for
this gadget type using the tag arguments, tag1 or taglist.  For instance,
the following code fragment might be used to create the color slider
discussed earlier:

    slidergad = CreateGadget(SLIDER_KIND, newgadget, prevgad,
        GTSL_Min, 0,
        GTSL_Max, 15,
        GTSL_Level, 11,
        TAG_END);

CreateGadget() typically allocates and initializes all the necessary
Intuition structures, including in this case the Gadget, IntuiText and
PropInfo structures, as well as certain buffers.  For more about these
underlying structures, see the "Intuition Gadgets" chapter.

Since CreateGadget() is a tag-based function, it is easy to add more tags
to get a fancier gadget.  For example, GadTools can optionally display the
running level beside the slider.  The caller must supply a printf()-style
formatting string and the maximum length that the string will resolve to
when the number is inserted:

    slidergad = CreateGadget(SLIDER_KIND, newgadget, prevgad,
        GTSL_Min, 0,
        GTSL_Max, 15,
        GTSL_Level, 11,
        GTSL_LevelFormat, "%2ld" /* printf()-style formatting string */
        GTSL_MaxLevelLen, 2,     /* maximum length of string         */
        TAG_END);

The level, 0 to 15 in this example, would then be displayed beside the
slider.  The formatting string could instead be "%2ld/15", so the level
would be displayed as "0/15" through "15/15".


15 / GadTools Gadgets / Handling Gadget Messages

GadTools gadgets follow the same input model as other Intuition
components.  When the user operates a GadTools gadget, Intuition notifies
the application about the input event by sending an IntuiMessage.  The
application can get these messages at the Window.UserPort.  However
GadTools gadgets use different message handling functions to get and reply
these messages.  Instead of the Exec functions GetMsg() and ReplyMsg(),
applications should get and reply these messages through a pair of special
GadTools functions, GT_GetIMsg() and GT_ReplyIMsg().

    struct IntuiMessage *GT_GetIMsg(struct MsgPort *iport)
    void  GT_ReplyIMsg(struct IntuiMessage *imsg)

For GT_GetIMsg(), the iport argument should be set to the window's
UserPort.  For GT_ReplyIMsg(), the imsg argument should be set to a
pointer to the IntuiMessage returned by GT_GetIMsg().

These functions ensure that the application only sees the gadget events
that concern it and in a desirable form.  For example, with a GadTools
slider gadget, a message only gets through to the application when the
slider's level actually changes and that level can be found in the
IntuiMessage's Code field:

    imsg = GT_GetIMsg(win->UserPort);
    object = imsg->IAddress;
    class = imsg->Class;
    code = imsg->Code;
    GT_ReplyIMsg(imsg);
    switch (class)
        {
        case IDCMP_MOUSEMOVE:
            if (object == slidergad)
                {
                printf("Slider at level %ld\n", code);
                }
            ...
            break;
        ...
        }

In general, the IntuiMessages received from GadTools contain more
information in the Code field than is found in regular Intuition gadget
messages.  Also, when dealing with GadTools a lot of messages (mostly
IDCMP_MOUSEMOVEs) do not have to be processed by the application.  These
are two reasons why dealing with GadTools gadgets is much easier than
dealing with regular Intuition gadgets.  Unfortunately this processing
cannot happen magically, so applications must use GT_GetIMsg() and
GT_ReplyIMsg() where they would normally have used GetMsg() and ReplyMsg().

GT_GetIMsg() actually calls GetMsg() to remove a message from the
specified window's UserPort.  If the message pertains to a GadTools gadget
then some dispatching code in GadTools will be called to process the
message.  What the program will receive from GT_GetIMsg() is actually a
copy of the real IntuiMessage, possibly with some supplementary
information from GadTools, such as the information typically found in the
Code field.

The GT_ReplyIMsg() call will take care of cleaning up and replying to the
real IntuiMessage.

    Warning:
    --------
    When an IDCMP_MOUSEMOVE message is received from a GadTools gadget,
    GadTools arranges to have the gadget's pointer in the IAddress
    field of the IntuiMessage.  While this is extremely convenient, it
    is also untrue of messages from regular Intuition gadgets (described
    in the "Intuition Gadgets" chapter).  Do not make the mistake of
    assuming it to be true.

This description of the inner workings of GT_GetIMsg() and GT_ReplyIMsg()
is provided for understanding only; it is crucial that the program make no
assumptions or interpretations about the real IntuiMessage.  Any such
inferences are not likely to hold true in the future.  See the section on
documented side-effects for more information.


15 / GadTools Gadgets / IDCMP Flags

The various GadTools gadget types require certain classes of IDCMP
messages in order to work.  Applications specify these IDCMP classes when
the window is opened or later with ModifyIDCMP() (see "Intuition Windows"
chapter for more on this).  Each kind of GadTools gadget requires
one or more of these IDCMP classes: IDCMP_GADGETUP, IDCMP_GADGETDOWN,
IDCMP_MOUSEMOVE, IDCMP_MOUSEBUTTONS and IDCMP_INTUITICKS.  As a
convenience, the IDCMP classes required by each kind of gadget are defined
in <libraries/gadtools.h>.  For example, SLIDERIDCMP is defined to be:

    #define SLIDERIDCMP (IDCMP_GADGETUP | IDCMP_GADGETDOWN |
                                          IDCMP_MOUSEMOVE)

    Always OR the IDCMP Flag Bits.
    ------------------------------
    When specifying the IDCMP classes for a window, never add the
    flags together, always OR the bits together.  Since many of the
    GadTools IDCMP constants have multiple bits set, adding the values
    will not lead to the proper flag combination.

If a certain kind of GadTools gadget is used, the window must use all
IDCMP classes required by that kind of gadget.  Do not omit any that are
given for that class, even if the application does require the message
type.

Because of the way GadTools gadgets are implemented, programs that use
them always require notification about window refresh events.  Even if the
application performs no rendering of its own, it may not use the
WFLG_NOCAREREFRESH window flag and must always set IDCMP_REFRESHWINDOW.
See the section on "Gadget Refresh Functions" later in this chapter for
more on this.


15 / GadTools Gadgets / Freeing Gadgets

After closing the window, the gadgets allocated using CreateGadget() must
be released.  FreeGadgets() is a simple call that will free all the
GadTools gadgets that it finds, beginning with the gadget whose pointer is
passed as an argument.

    void FreeGadgets( struct Gadget *gad );

The gad argument is a pointer to the first gadget to be freed.  It is safe
to call FreeGadgets() with a NULL gadget pointer, the function will then
return immediately.  Before calling FreeGadgets(), the application must
first either remove the gadgets or close the window.

When the gadget passed to FreeGadgets() is the first gadget in a linked
list, the function frees all the GadTools gadgets on the list without
patching pointers or trying to maintain the integrity of the list.  Any
non-GadTools gadgets found on the list will not be freed, hence the result
will not necessarily form a nice list since any intervening GadTools
gadgets will be gone.

See the section on "Creating Gadget Lists" for more information on using
linked lists of gadgets.


15 / GadTools Gadgets / Modifying Gadgets

The attributes of a gadget are set up when the gadget is created.  Some of
these attributes can be changed later by using the GT_SetGadgetAttrs()
function:

    void GT_SetGadgetAttrs (struct Gadget *gad, struct Window *win,
                            struct Requester *req, Tag tag1, ... )
    void GT_SetGadgetAttrsA(struct Gadget *gad, struct Window *win,
                            struct Requester *req, struct TagItem *taglist)

The gad argument specifies the gadget to be changed while the win argument
specifies the window the gadget is in.  Currently, the req argument is
unused and must be set to NULL.

The gadget attributes are changed by passing tag arguments to these
functions.  The tag arguments can be either a set of TagItems on the stack
for GT_SetGadgetAttrs(), or a pointer to an array of TagItems for
GT_SetGadgetAttrsA().  The tag items specify the attributes that are to be
changed for the gadget.  Keep in mind though that not every gadget
attribute can be modified this way.

For example, in the slider gadget presented earlier, the level-formatting
string may not be changed after the gadget is created.  However, the
slider's level may be changed to 5 as follows:

    GT_SetGadgetAttrs(slidergad, win, req,
        GTSL_Level, 5,
        TAG_END);

Here are some other example uses of GT_SetGadgetAttrs() to change gadget
attributes after it is created.

    /* Disable a button gadget */
    GT_SetGadgetAttrs(buttongad, win, NULL,
                            GA_Disabled, TRUE,
                            TAG_END);

    /* Change a slider's range to be 1 to 100, currently at 50 */
    GT_SetGadgetAttrs(slidergad, win, NULL,
                            GTSL_Min, 1,
                            GTSL_Max, 100,
                            GTSL_Level, 50,
                            TAG_END);

    /* Add a node to the head of listview's list, and make it */
    /* the selected one */
    GT_SetGadgetAttrs(listviewgad, win, NULL,
                            /* detach list before modifying */
                            GTLV_Labels, ~0,
                            TAG_END);
    AddHead(&lvlabels, &newnode);
    GT_SetGadgetAttrs(listviewgad, win, NULL,
                            /* re-attach list */
                            GTLV_Labels, &lvlabels,
                            GTLV_Selected, 0,
                            TAG_END);

When changing a gadget using these functions, the gadget will
automatically update its visuals.  No refresh is required, nor should any
refresh call be performed.

    Warning:
    --------
    The GT_SetGadgetAttrs() functions may not be called inside of a
    GT_BeginRefresh()/GT_EndRefresh() pair.  This is true of Intuition
    gadget functions generally, including those discussed in the
    "Intuition Gadgets" chapter.

In the sections that follow all the possible attributes for each kind of
gadget are discussed.  The tags are also described in the Autodocs for
GT_SetGadgetAttrs() in the Amiga ROM Kernel Reference Manual: Includes and
Autodocs.

    Important:
    ----------
    Tags that can only be sent to CreateGadget() and not to
    GT_SetGadgetAttrs() will be marked as create only in the
    discussion that follows.  Those that are valid parameters to both
    functions will be marked as create and set.


15 / GadTools Gadgets / The Kinds of GadTools Gadgets

This section discusses the unique features of each kind of gadget
supported by the GadTools library.

 Button Gadgets
 Text-Entry and Number-Entry Gadgets
 Checkbox Gadgets
 Mutually-Exclusive Gadgets
 Cycle Gadgets
 Slider Gadgets
 Scroller Gadgets
 Listview Gadgets
 Palette Gadgets
 Text-Display and Numeric-Display Gadgets
 Generic Gadgets


15 / / The Kinds of GadTools Gadgets / Button Gadgets

Button gadgets (BUTTON_KIND) are perhaps the simplest kind of GadTools
gadget.  Button gadgets may be used for objects like the "OK" and "Cancel"
buttons in requesters.  GadTools will create a hit-select button with a
raised bevelled border.  The label supplied will be centered on the
button's face.  Since the label is not clipped, be sure that the gadget is
large enough to contain the text supplied.

Button gadgets recognize only one tag:

GA_Disabled (BOOL)
    Set this attribute to TRUE to disable or ghost the button gadget, to
    FALSE otherwise.  The default is FALSE. (Create and set.)

When the user selects a button gadget, the program will receive an
IDCMP_GADGETUP event.

If clicking on a button causes a requester to appear, for example a button
that brings up a color requester, then the button text should end in
ellipsis (...), as in "Quit..."


15 / / Kinds of GadTools Gadgets / Text-Entry and Number-Entry Gadgets

Text-entry (STRING_KIND) and number-entry (INTEGER_KIND) gadgets are
fairly typical Intuition string gadgets.  The typing area is contained by
a border which is a raised ridge.

Text-entry gadgets accept the following tags:

GTST_String (STRPTR)
    A pointer to the string to be placed into the text-entry gadget
    buffer or NULL to get an empty text-entry gadget.  The string itself
    is actually copied into the gadget's buffer.  The default is NULL.
    (Create and set.)

GTST_MaxChars (UWORD)
    The maximum number of characters that the text-entry gadget should
    hold.  The string buffer that gets created for the gadget will
    actually be one bigger than this number, in order to hold the
    trailing NULL.  The default is 64.  (Create only.)

Number-entry gadgets accept the following tags:

GTIN_Number (ULONG)
    The number to be placed into the number-entry gadget.  The default is
    zero. (Create and set.)

GTIN_MaxChars (UWORD)
    The maximum number of digits that the number-entry gadget should
    hold.  The string buffer that gets created for the gadget will
    actually be one bigger than this, in order to hold the trailing NULL.
    The default is 10. (Create only.)

Both text-entry and number-entry gadgets, which are collectively called
string gadgets, accept these common tags:

STRINGA_Justification
    This attribute controls the placement of the string or number within
    its box and can be one of GACT_STRINGLEFT, GACT_STRINGRIGHT or
    GACT_STRINGCENTER.  The default is GACT_STRINGLEFT.  (Create only.)

STRINGA_ReplaceMode (BOOL)
    Set STRINGA_ReplaceMode to TRUE to get a string gadget which is in
    replace-mode, as opposed to auto-insert mode.  (Create only.)

GA_Disabled (BOOL)
    Set this attribute to TRUE to disable the string gadget, otherwise to
    FALSE.  The default is FALSE.  (Create and set.)

STRINGA_ExitHelp (BOOL)
    (New for V37, ignored under V36).  Set this attribute to TRUE if the
    application wants to hear the Help key from within this string
    gadget.  This feature allows the program to hear the press of the
    Help key in all cases.  If TRUE, pressing the help key while this
    gadget is active will terminate the gadget and send a message.  The
    program will receive an IDCMP_GADGETUP message having a Code value of
    0x5F, the rawkey code for Help.  Typically, the program will want to
    reactivate the gadget after performing the help-display.  The default
    is FALSE.  (Create only.)

GA_TabCycle (BOOL)
    (New for V37, ignored under V36).  If the user types Tab or Shift Tab
    into a GA_TabCycle gadget, Intuition will activate the next or
    previous such gadget in sequence.  This gives the user easy keyboard
    control over which text-entry or number-entry gadget is active.  Tab
    moves to the next GA_TabCycle gadget in the gadget list and Shift Tab
    moves to the previous one.  When the user presses Tab or Shift Tab,
    Intuition will deactivate the gadget and send this program an
    IDCMP_GADGETUP message with the code field set to 0x09, the ASCII
    value for a tab.  Intuition will then activate the next indicated
    gadget.  Check the shift bits of the qualifier field to learn if
    Shift Tab was typed.  The ordering of the gadgets may only be
    controlled by the order in which they were added to the window.  For
    special cases, for example, if there is only one string gadget in the
    window, this feature can be suppressed by specifying the tagitem pair
    {GA_TabCycle, FALSE}.  The default is TRUE.  (Create only.)

GTST_EditHook (struct Hook *)
    (New for V37, ignored under V36).  Pointer to a custom editing hook
    for this string or integer gadget.  See the "Intuition Gadgets"
    chapter for more information on string gadget edit-hooks.

As with all Intuition string gadgets, the program will receive an
IDCMP_GADGETUP message only when the user presses Enter, Return, Help, Tab
or Shift Tab while typing in the gadget.  Note that, like Intuition string
gadgets, the program will not hear anything if the user deactivates the
string gadget by clicking elsewhere.  Therefore, it is a good idea to
always check the string gadget's buffer before using its contents, instead
of just tracking its value as IDCMP_GADGETUP messages are received for
this gadget.

Be sure the code is designed so that nothing drastic happens, like closing
a requester or opening a file, if the IDCMP_GADGETUP message has a
non-zero Code field; the program will want to handle the Tab and Help
cases intelligently.

To read the string gadget's buffer, look at the Gadget's StringInfo Buffer:

    ((struct StringInfo *)gad->SpecialInfo)->Buffer

To determine the value of an integer gadget, look at the Gadget's
StringInfo LongInt in the same way.

Always use the GTST_String or GTIN_Number tags to set these values.  Never
write to the StringInfo->Buffer or StringInfo->LongInt fields directly.

GadTools string and integer gadgets do not directly support the
GA_Immediate property (which would cause Intuition to send an
IDCMP_GADGETDOWN event when such a gadget is first selected).  However,
this property can be very important.  Therefore, the following technique
can be used to enable this property.

    Warning:
    --------
    Note that the technique shown here relies on directly setting flags
    in a GadTools gadget; this is not normally allowed since it hinders
    future compatibility.  Do not attempt to change other flags or
    properties of GadTools gadgets except through the defined interfaces
    of CreateGadgetA() and GT_SetGadgetAttrsA().  Directly modifying
    flags or properties is legal only when officially sanctioned by
    Amiga, Inc..

To get the GA_Immediate property, pass the {GA_Immediate,TRUE} tag to
CreateGadgetA().  Even though this tag is ignored for string and integer
gadgets under V37, this will allow future versions of GadTools to learn of
your request in the correct way.  Then, under V37 only, set the
GACT_IMMEDIATE flag in the gadget's Activation field:

    gad = CreateGadget( STRING_KIND, gad, &ng,
            /* string gadget tags go here */
            GTST_...,

            /* Add this tag for future GadTools releases */
            GA_Immediate, TRUE,
            ...
            TAG_DONE );

    if ( ( gad ) && ( GadToolsBase->lib_Version == 37) )
    {
            /* Under GadTools V37 only, set this attribute
             * directly.  Do not set this attribute under
             * future versions of GadTools, or for gadgets
             * other than STRING_KIND or INTEGER_KIND.
             */
            gad->Activation |= GACT_IMMEDIATE;
    }


15 / / The Kinds of GadTools Gadgets / Checkbox Gadgets

Checkboxes (CHECKBOX_KIND) are appropriate for presenting options which
may be turned on or off.  This kind of gadget consists of a raised box
which contains a checkmark if the option is selected or is blank if the
option is not selected.  Clicking on the box toggles the state of the
checkbox.

The width and height of a checkbox are currently fixed (to 26x11). If
variable-sized checkboxes are added in the future,  they will be done in a
compatible manner.  Currently the width and height specified in the
NewGadget structure are ignored.

The checkbox may be controlled with the following tags:

GTCB_Checked (BOOL)
    Set this attribute to TRUE to set the gadget's state to checked.  Set
    it to FALSE to mark the gadget as unchecked.  The default is FALSE.
    (Create and set.)

GA_Disabled (BOOL)
    Set this attribute to TRUE to disable the checkbox, to FALSE
    otherwise.  The default is FALSE.  (Create and set.)

When the user selects a checkbox, the program will receive an IntuiMessage
with a class of IDCMP_GADGETUP.  As this gadget always toggles, the
program can easily track the state of the gadget.  Feel free to read the
Gadget->Flags GFLG_SELECTED bit.  Note, however, that the Gadget structure
itself is not synchronized to the IntuiMessages received.  If the user
clicks a second time, the GFLG_SELECTED bit can toggle again before the
program gets a chance to read it.  This is true of any of the dynamic
fields of the Gadget structure, and is worth being aware of, although only
rarely will an application have to account for it.


15 / / The Kinds of GadTools Gadgets / Mutually-Exclusive Gadgets

Use mutually exclusive gadgets (MX_KIND), or radio buttons, when the user
must choose only one option from a short list of possibilities.  Mutually
exclusive gadgets are appropriate when there are a small number of
choices, perhaps eight or less.

A set of mutually exclusive gadgets consists of a list of labels and
beside each label, a small raised oval that looks like a button.  Exactly
one of the ovals is recessed and highlighted, to indicate the selected
choice.  The user can pick another choice by clicking on any of the raised
ovals.  This choice will become active and the previously selected choice
will become inactive.  That is, the selected oval will become recessed
while the previous one will pop out, like the buttons on a car radio.

Mutually exclusive gadgets recognize these tags:

GTMX_Labels (STRPTR *)
    A NULL-pointer-terminated array of strings which are to be the labels
    beside each choice in the set of mutually exclusive gadgets.  This
    array determines how many buttons are created.  This array must be
    supplied to CreateGadget() and may not be changed.  The strings
    themselves must remain valid for the lifetime of the gadget.  (Create
    only.)

GTMX_Active (UWORD)
    The ordinal number, counting from zero, of the active choice of the
    set of mutually exclusive gadgets.  The default is zero.  (Create and
    set.)

GTMX_Spacing (UWORD)
    The amount of space, in pixels, that will be placed between
    successive choices in a set of mutually exclusive gadgets.  The
    default is one.  (Create only.)

When the user selects a new choice from a set of mutually exclusive
gadgets, the program will receive an IDCMP_GADGETDOWN IntuiMessage. Look
in the IntuiMessage's Code field for the ordinal number of the new active
selection.

The ng_GadgetText field of the NewGadget structure is ignored for mutually
exclusive gadgets.  The text position specified in ng_Flags  determines
whether the item labels are placed to the left or the right of the radio
buttons themselves.  By default, the labels appear on the left.  Do not
specify PLACETEXT_ABOVE, PLACETEXT_BELOW or PLACETEXT_IN for this kind of
gadget.

Like the checkbox, the size of the radio button is currently fixed, and
the dimensions supplied in the NewGadget structure are ignored.  If in the
future the buttons are made scalable, it will be done in a compatible
manner.  Currently, mutually exclusive gadgets may not be disabled.


15 / / The Kinds of GadTools Gadgets / Cycle Gadgets

Like mutually exclusive gadgets, cycle gadgets (CYCLE_KIND) allow the user
to choose exactly one option from among several.

The cycle gadget appears as a raised rectangular button with a vertical
divider near the left side.  A circular arrow glyph appears to the left of
the divider, while the current choice appears to the right.  Clicking on
the cycle gadget advances to the next choice, while shift-clicking on it
changes it to the previous choice.

Cycle gadgets are more compact than mutually exclusive gadgets, since only
the current choice is displayed.  They are preferable to mutually
exclusive gadgets when a window needs to have several such gadgets as in
the PrinterGfx Preferences editor, or when there is a medium number of
choices.  If the number of choices is much more than about a dozen, it may
become too frustrating and inefficient for the user to find the desired
choice.  In that case, use a listview (scrolling list) instead.

The tags recognized by cycle gadgets are:

GTCY_Labels (STRPTR *)
    Like GTMX_Labels, this tag is associated with a
    NULL-pointer-terminated array of strings which are the choices that
    this gadget allows.  This array must be supplied to CreateGadget(),
    and can only be changed starting in V37.  The strings themselves must
    remain valid for the lifetime of the gadget.  (Create only (V36),
    Create and set (V37).)

GTCY_Active (UWORD)
    The ordinal number, counting from zero, of the active choice of the
    cycle gadget.  The default is zero.  (Create and set.)

GA_Disabled (BOOL)
    (New for V37, ignored by V36.)  Set this attribute to TRUE to disable
    the cycle gadget, to FALSE otherwise.  The default is FALSE.  (Create
    and set.)

When the user clicks or shift-clicks on a cycle gadget, the program will
receive an IDCMP_GADGETUP IntuiMessage.  Look in the Code field of the
IntuiMessage for the ordinal number of the new active selection.


15 / / The Kinds of GadTools Gadgets / Slider Gadgets

Sliders are one of the two kinds of proportional gadgets offered by
GadTools.  Slider gadgets (SLIDER_KIND) are used to control an amount, a
level or an intensity, such as volume or color.  Scroller gadgets
(SCROLLER_KIND) are discussed below.

Slider gadgets accept the following tags:

GTSL_Min (WORD)
    The minimum level of a slider.  The default is zero.  (Create and
    set.)

GTSL_Max (WORD)
    The maximum level of a slider.  The default is 15.  (Create and set.)

GTSL_Level (WORD)
    The current level of a slider. The default is zero. When the level is
    at its minimum, the knob will be all the way to the left for a
    horizontal slider or all the way at the bottom for a vertical slider.
    Conversely, the maximum level corresponds to the knob being to the
    extreme right or top.  (Create and set.)

GTSL_LevelFormat (STRPTR)
    The current level of the slider may be displayed in real-time
    alongside the gadget.  To use the level-display feature, the program
    must be using a monospace font for this gadget.

    GTSL_LevelFormat specifies a printf()-style formatting string used to
    render the slider level beside the slider (the complete set of
    formatting options is described in the Exec library function
    RawDoFmt()).  Be sure to use the `l' (long word) modifier for the
    number.  Field-width specifiers may be used to ensure that the
    resulting string is always of constant width.  The simplest would be
    "%2ld".  A 2-digit hexadecimal slider might use "%02lx", which adds
    leading zeros to the number.  Strings with extra text, such as "%3ld
    hours", are permissible.  If this tag is specified, the program must
    also provide GTSL_MaxLevelLen.  By default, the level is not
    displayed.  (Create only.)

GTSL_MaxLevelLen (UWORD)
    The maximum length of the string that will result from the given
    level-formatting string.  If this tag is specified, the program must
    also provide GTSL_LevelFormat.  By default, the level is not
    displayed.  (Create only.)

GTSL_LevelPlace
    To choose where the optional display of the level is positioned.  It
    must be one of PLACETEXT_LEFT, PLACETEXT_RIGHT, PLACETEXT_ABOVE or
    PLACETEXT_BELOW.  The level may be placed anywhere with the following
    exception: the level and the label may not be both above or both
    below the gadget.  To place them both on the same side, allow space
    in the gadget's label (see the example).  The default is
    PLACETEXT_LEFT.  (Create only.)

GTSL_DispFunc (LONG (*function)(struct Gadget *, WORD))
    Optional function to convert the level for display.  A slider to
    select the number of colors for a screen may operate in screen depth
    (1 to 5, for instance), but actually display the number of colors (2,
    4, 8, 16 or 32).  This may be done by providing a GTSL_DispFunc
    function which returns 1 << level.  The function must take a pointer
    to the Gadget as the first parameter and the level, a WORD, as the
    second and return the result as a LONG.  The default behavior for
    displaying a level is to do so without any conversion.  (Create only.)

GA_Immediate (BOOL)
    Set this to TRUE to receive an IDCMP_GADGETDOWN IntuiMessage when the
    user presses the mouse button over the slider.  The default is FALSE.
    (Create only.)

GA_RelVerify (BOOL)
    Set this to TRUE to receive an IDCMP_GADGETUP IntuiMessage when the
    user releases the mouse button after using the slider.  The default
    is FALSE.  (Create only.)

PGA_Freedom
    Specifies which direction the knob may move.  Set to LORIENT_VERT for
    a vertical slider or LORIENT_HORIZ for a horizontal slider.  The
    default is LORIENT_HORIZ.  (Create only.)

GA_Disabled (BOOL)
    Set this attribute to TRUE to disable the slider, to FALSE otherwise.
    The default is FALSE.  (Create and set.)

Up to three different classes of IntuiMessage may be received at the port
when the user plays with a slider, these are IDCMP_MOUSEMOVE,
IDCMP_GADGETUP and IDCMP_GADGETDOWN.  The program may examine the
IntuiMessage Code field to discover the slider's level.

IDCMP_MOUSEMOVE IntuiMessages will be heard whenever the slider's level
changes.  IDCMP_MOUSEMOVE IntuiMessages will not be heard if the knob has
not moved far enough for the level to actually change.  For example if the
slider runs from 0 to 15 and is currently set to 12, if the user drags the
slider all the way up the program will hear no more than three
IDCMP_MOUSEMOVEs, one each for 13, 14 and 15.

If {GA_Immediate, TRUE} is specified, then the program will always hear an
IDCMP_GADGETDOWN IntuiMessage when the user begins to adjust a slider.  If
{GA_RelVerify, TRUE} is specified, then the program will always hear an
IDCMP_GADGETUP IntuiMessage when the user finishes adjusting the slider.
If IDCMP_GADGETUP or IDCMP_GADGETDOWN IntuiMessages are requested, the
program will always hear them, even if the level has not changed since the
previous IntuiMessage.

Note that the Code field of the IntuiMessage structure is a UWORD, while
the slider's level may be negative, since it is a WORD.  Be sure to copy
or cast the IntuiMessage->Code into a WORD if the slider has negative
levels.

If the user clicks in the container next to the knob, the slider level
will increase or decrease by one.  If the user drags the knob itself, then
the knob will snap to the nearest integral position when it is released.

Here is an example of the screen-depth slider discussed earlier:

    /* NewGadget initialized here. Note the three spaces
     * after "Slider:", to allow a blank plus the two digits
     * of the level display
     */
    ng.ng_Flags = PLACETEXT_LEFT;
    ng.ng_GadgetText = "Slider:   ";

    LONG DepthToColors(struct Gadget *gad, WORD level)
    {
    return ((WORD)(1 << level));
    }

    ...

    gad = CreateGadget(SLIDER_KIND, gad, &ng,
        GTSL_Min, 1,
        GTSL_Max, 5,
        GTSL_Level, current_depth,
        GTSL_MaxLevelLen, 2,
        GTSL_LevelFormat, "%2ld",
        GTSL_DispFunc, DepthToColors,
        TAG_END);


15 / / The Kinds of GadTools Gadgets / Scroller Gadgets

Scrollers (SCROLLER_KIND) bear some similarity to sliders, but are used
for a quite different job: they allow the user to adjust the position of a
limited view into a larger area.  For example, Workbench's windows have
scrollers that allow the user to see icons that are outside the visible
portion of a window.  Another example is a scrolling list in a file
requester which has a scroller that allows the user to see different parts
of the whole list.

A scroller consists of a proportional gadget and usually also has a pair
of arrow buttons.

While the slider deals in minimum, maximum and current level, the scroller
understands Total, Visible and Top.  For a scrolling list, Total would be
the number of items in the entire list, Visible would be the number of
lines visible in the display area and Top would be the number of the first
line displayed in the visible part of the list.  Top would run from zero
to Total - Visible.  For an area-scroller such as those in Workbench's
windows, Total would be the height (or width) of the whole area, Visible
would be the visible height (or width) and Top would be the top (or left)
edge of the visible part.

Note that the position of a scroller should always represent the position
of the visible part of the project and never the position of a cursor or
insertion point.

Scrollers respect the following tags:

GTSC_Top (WORD)
    The top line or position visible in the area that the scroller
    represents.  The default is zero.  (Create and set.)

GTSC_Total (WORD)
    The total number of lines or positions that the scroller represents.
    The default is zero.  (Create and set.)

GTSC_Visible (WORD)
    The visible number of lines or positions that the scroller
    represents.  The default is two.  (Create and set.)

GTSC_Arrows (UWORD)
    Asks for arrow gadgets to be attached to the scroller.  The value
    supplied will be used as the width of each arrow button for a
    horizontal scroller or the height of each arrow button for a vertical
    scroller, the other dimension will be set by GadTools to match the
    scroller size.  It is generally recommend that arrows be provided.
    The default is no arrows.  (Create only.)

GA_Immediate (BOOL)
    Set this to TRUE to receive an IDCMP_GADGETDOWN IntuiMessage when the
    user presses the mouse button over the scroller.  The default is
    FALSE.  (Create only.)

GA_RelVerify (BOOL)
    Set this to TRUE to receive an IDCMP_GADGETUP IntuiMessage when the
    user releases the mouse button after using the scroller.  The default
    is FALSE.  (Create only.)

PGA_Freedom
    Specifies which direction the knob may move.  Set to LORIENT_VERT for
    a vertical scroller or LORIENT_HORIZ for a horizontal scroller.  The
    default is LORIENT_HORIZ.  (Create only.)

GA_Disabled (BOOL)
    Set this attribute to TRUE to disable the scroller, to FALSE
    otherwise.  The default is FALSE.  (Create and set.)

The IntuiMessages received for a scroller gadget are the same in nature as
those for a slider defined above, including the fact that messages are
only heard by the program when the knob moves far enough for the Top value
to actually change. The Code field of the IntuiMessage will contain the
new Top value of the scroller.

If the user clicks on an arrow gadget, the scroller moves by one unit.  If
the user holds the button down over an arrow gadget, it repeats.

If the user clicks in the container next to the knob, the scroller will
move by one page, which is the visible amount less one.  This means that
when the user pages through a scrolling list, any pair of successive views
will overlap by one line.  This helps the user understand the continuity
of the list.  If the program is using a scroller to pan through an area
then there will be an overlap of one unit between successive views.  It is
recommended that Top, Visible and Total be scaled so that one unit
represents about five to ten percent of the visible amount.


15 / / The Kinds of GadTools Gadgets / Listview Gadgets

Listview gadgets (LISTVIEW_KIND) are scrolling lists.  They consist of a
scroller with arrows, an area where the list itself is visible and
optionally a place where the current selection is displayed, which may be
editable.  The user can browse through the list using the scroller or its
arrows and may select an entry by clicking on that item.

There are a number of tags that are used with listviews:

GTLV_Labels (struct List *)
    An Exec list whose nodes' ln_Name fields are to be displayed as items
    in the scrolling list.  If the list is empty, an empty List structure
    or a NULL value may be used for GTLV_Labels.  This tag accepts a
    value of "~0" to detach the list from the listview, defined below.
    The default is NULL.  (Create and set.)

GTLV_Top (UWORD)
    The ordinal number of the top item visible in the listview.  The
    default is zero.  (Create and set.)

GTLV_ReadOnly (BOOL)
    Set this to TRUE for a read-only listview, which the user can browse,
    but not select items from.  A read-only listview can be recognized
    because the list area is recessed, not raised.  The default is FALSE.
    (Create only.)

GTLV_ScrollWidth (UWORD)
    The width of the scroller to be used in the listview.  Any value
    specified must be reasonably bigger than zero.  The default is 16.
    (Create only.)

GTLV_ShowSelected (struct Gadget *)
    Use this tag to show the currently selected entry displayed
    underneath the listview.  Set its value to NULL to get a read-only
    (TEXT_KIND) display of the currently selected entry or set it to a
    pointer to an already-created GadTools STRING_KIND gadget to allow
    the user to directly edit the current entry.  By default, there is no
    display of the currently selected entry.  (Create only.)

GTLV_Selected (UWORD)
    Ordinal number of the item to be placed into the display of the
    current selection under the listview.  This tag is ignored if
    GTLV_ShowSelected is not used.  Set it to "~0" to have no current
    selection.  The default is "~0".  (Create and set.)

LAYOUTA_Spacing (UWORD)
    Extra space, in pixels, to be placed between the entries in the
    listview.  The default is zero.  (Create only.)

The program will only hear from a listview when the user selects an item
from the list.  The program will then receive an IDCMP_GADGETUP
IntuiMessage.  This message will contain the ordinal number of the item
within the list that was selected in the Code field of the message.  This
number is independent of the displayed listview, it is the offset from the
start of the list of items.

If the program attaches a display gadget by using the TagItem
{GTLV_ShowSelected, NULL}, then whenever the user clicks on an entry in
the listview it will be copied into the display gadget.

If the display gadget is to be editable, then the program must first
create a GadTools STRING_KIND gadget whose width matches the width of the
listview.  The TagItem {GTLV_ShowSelected, stringgad} is used to install
the editable gadget, where stringgad is the pointer returned by
CreateGadget().  When the user selects any entry from the listview, it
gets copied into the string gadget.  The user can edit the string and the
program will hear normal string gadget IDCMP_GADGETUP messages from the
STRING_KIND gadget.

The Exec List and its Node structures may not be modified while they are
attached to the listview, since the list might be needed at any time.  If
the program has prepared an entire new list, including a new List
structure and all new nodes, it may replace the currently displayed list
in a single step by calling GT_SetGadgetAttrs() with the TagItem
{GTLV_Labels, newlist}.  If the program needs to operate on the list that
has already been passed to the listview, it should detach the list by
setting the GTLV_Labels attribute to "~0".  When done modifying the list,
resubmit it by setting GTLV_Labels to once again point to it.  This is
better than first setting the labels to NULL and later back to the list,
since setting GTLV_Labels to NULL will visually clear the listview.  If
the GTLV_Labels attribute is set to "~0", the program is expected to set
it back to something determinate, either a list or NULL, soon after.

The height specified for the listview will determine the number of lines
in the list area.  When creating a listview, it will be no bigger than the
size specified in the NewGadget structure.  The size will include the
current-display gadget, if any, that has been requested via the
GTLV_ShowSelected tag.  The listview may end up being less tall than the
application asked for, since the calculated height assumes an integral
number of lines in the list area.

By default, the gadget label will be placed above the listview.  This may
be overridden using ng_Flags.

Currently, a listview may not be disabled.


15 / / The Kinds of GadTools Gadgets / Palette Gadgets

Palette gadgets (PALETTE_KIND) let the user pick a color from a set of
several.  A palette gadget consists of a number of colored squares, one
for each color available.  There may also be an optional indicator square
which is filled with the currently selected color.  To create a color
editor, a palette gadget would be combined with some sliders to control
red, green and blue components, for example.

Palette gadgets use the following tags:

GTPA_Depth (UWORD)
    The number of bitplanes that the palette represents.  There will be 1
    << depth squares in the palette gadget.  The default is one.  (Create
    only.)

GTPA_Color (UBYTE)
    The selected color of the palette.  The default is one.  (Create and
    set.)

GTPA_ColorOffset (UBYTE)
    The first color to use in the palette.  For example, if GTPA_Depth is
    two and GTPA_ColorOffset is four, then the palette will have squares
    for colors four, five, six and seven.  The default is zero.  (Create
    only.)

GTPA_IndicatorWidth (UWORD)
    The desired width of the current-color indicator.  By specifying this
    tag, the application is asking for an indicator to be placed to the
    left of the color selection squares.  The indicator will be as tall
    as the gadget itself.  By default there is no indicator.  (Create
    only.)

GTPA_IndicatorHeight (UWORD)
    The desired height of the current-color indicator.  By specifying
    this tag, the application is asking for an indicator to be placed
    above the color selection squares.  The indicator will be as wide as
    the gadget itself.  By default there is no indicator.  (Create only.)

GA_Disabled (BOOL)
    Set this attribute to TRUE to disable the palette gadget, to FALSE
    otherwise.  The default is FALSE.  (Create and set.)

An IDCMP_GADGETUP IntuiMessage will be received when the user selects a
color from the palette.  The current-color indicator is recessed,
indicating that clicking on it has no effect.

If the palette is wide and not tall, use the GTPA_IndicatorWidth tag to
put the indicator on the left.  If the palette is tall and narrow, put the
indicator on top using GTPA_IndicatorHeight.

By default, the gadget's label will go above the palette gadget, unless
GTPA_IndicatorWidth is specified, in which case the label will go on the
left.  In either case, the default may be overridden by setting the
appropriate flag in the NewGadget's ng_Flags field.

The size specified for the palette gadget will determine how the area is
subdivided to make the individual color squares.  The actual size of the
palette gadget will be no bigger than the size given, but it can be
smaller in order to make the color squares all exactly the same size.


15 / / Kinds of GadTools / Text-Display and Numeric-Display Gadgets

Text-display (TEXT_KIND) and numeric-display (NUMBER_KIND) gadgets are
read-only displays of information.  They are useful for displaying
information that is not editable or selectable, while allowing the
application to use the GadTools formatting and visuals.  Conveniently, the
visuals are automatically refreshed through normal GadTools gadget
processing.  The values displayed may be modified by the program in the
same way other GadTools gadgets may be updated.

Text-display and number-display gadgets consist of a fixed label (the one
supplied as the NewGadget's ng_GadgetText), as well as a changeable string
or number (GTTX_Text or GTNM_Number respectively).  The fixed label is
placed according to the PLACETEXT_ flag chosen in the NewGadget ng_Flags
field.  The variable part is aligned to the left-edge of the gadget.

Text-display gadgets recognize the following tags:

GTTX_Text (STRPTR)
    Pointer to the string to be displayed or NULL for no string.  The
    default is NULL.  (Create and set.)

GTTX_Border (BOOL)
    Set to TRUE to place a recessed border around the displayed string.
    The default is FALSE.  (Create only.)

GTTX_CopyText (BOOL)
    This flag instructs the text-display gadget to copy the supplied
    GTTX_Text string instead of using only a pointer to the string.  This
    only works for the value of GTTX_Text set at CreateGadget() time.  If
    GTTX_Text is changed, the new text will be referenced by pointer, not
    copied.  Do not use this tag without a non-NULL GTTX_Text.  (Create
    only.)

Number-display gadgets have the following tags:

GTNM_Number (LONG)
    The number to be displayed.  The default is zero.  (Create or set.)

GTNM_Border (BOOL)
    Set to TRUE to place a recessed border around the displayed number.
    The default is FALSE.  (Create only.)

Since they are not selectable, text-display and numeric-display gadgets
never cause IntuiMessages to be sent to the application.


15 / / The Kinds of GadTools Gadgets / Generic Gadgets

If the application requires a specialized gadget which does not fit into
any of the defined GadTools kinds but would still like to use the GadTools
gadget creation and deletion functions, it may create a GadTools generic
gadget and use it any way it sees fit.  In fact, all of the kinds of
GadTools gadgets are created out of GadTools GENERIC_KIND gadgets.

The gadget that gets created will heed almost all the information
contained in the NewGadget structure supplied.

If ng_GadgetText is supplied, the Gadget's GadgetText will point to an
IntuiText structure with the provided string and font.  However, do not
specify any of the PLACETEXT ng_Flags, as they are currently ignored by
GENERIC_KIND gadgets.  PLACETEXT flags may be supported by generic
GadTools gadgets in the future.

It is up to the program to set the Flags, Activation, GadgetRender,
SelectRender, MutualExclude and SpecialInfo fields of the Gadget structure.

The application must also set the GadgetType field, but be certain to
preserve the bits set by CreateGadget(). For instance, to make a gadget
boolean, use:

    gad->GadgetType |= GTYP_BOOLGADGET;

and not

    gad->GadgetType = GTYP_BOOLGADGET;

Using direct assignment, (the = operator), clears all other flags in the
GadgetType field and the gadget may not be properly freed by FreeGadgets().


15 / GadTools / Functions for Setting Up GadTools Menus and Gadgets

This section gives all the details on the functions used to set up
GadTools menus and gadgets that were mentioned briefly earlier in this
chapter.

 GetVisualInfo() and FreeVisualInfo()    CreateContext()


15 / / / GetVisualInfo() and FreeVisualInfo()

In order to ensure their best appearance, GadTools gadgets and menus need
information about the screen on which they will appear.  Before creating
any GadTools gadgets or menus, the program must get this information using
the GetVisualInfo() call.

    APTR GetVisualInfoA( struct Screen *screen, struct TagItem *taglist );
    APTR GetVisualInfo( struct Screen *screen, Tag tag1, ... );

Set the screen argument to a pointer to the screen you are using.  The tag
arguments, tag1 or taglist, are reserved for future extensions.  Currently
none are recognized, so only TAG_END should be used.

The function returns an abstract handle called the VisualInfo.  For
GadTools gadgets, the ng_VisualInfo field of the NewGadget structure must
be set to this handle before the gadget can be added to the window.
GadTools menu layout and creation functions also require the VisualInfo
handle as an argument.

There are several ways to get the pointer to the screen on which the
window will be opened.  If the application has its own custom screen, this
pointer is known from the call to OpenScreen() or OpenScreenTags().  If
the application already has its window opened on the Workbench or some
other public screen, the screen pointer can be found in Window.WScreen.
Often the program will create its gadgets and menus before opening the
window.  In this case, use LockPubScreen() to get a pointer to the desired
public screen, which also provides a lock on the screen to prevent it from
closing.  See the chapters "Intuition Screens" and "Intuition Windows" for
more about public screens.

The VisualInfo data must be freed after all the gadgets and menus have
been freed but before releasing the screen.  Custom screens are released
by calling CloseScreen(), public screens are released by calling
CloseWindow() or UnlockPubScreen(), depending on the technique used.  Use
FreeVisualInfo() to free the visual info data.

    void FreeVisualInfo( APTR vi );

This function takes just one argument, the VisualInfo handle as returned
by GetVisualInfo().  The sequence of events for using the VisualInfo
handle could look like this:

    init()
    {
    myscreen = LockPubScreen(NULL);
    if (!myscreen)
        {
        cleanup("Failed to lock default public screen");
        }
    vi = GetVisualInfo(myscreen);
    if (!vi)
        {
        cleanup("Failed to GetVisualInfo");
        }
    /* Create gadgets here */
    ng.ng_VisualInfo = vi;
    ...
    }

    void cleanup(STRPTR errorstr)
    {
    /* These functions may be safely called with a NULL parameter: */
    FreeGadgets(glist);
    FreeVisualInfo(vi);

    if (myscreen)
        UnlockPubScreen(NULL, myscreen);

    printf(errorstr);
    }


15 / / Setting Up GadTools Menus and Gadgets / CreateContext()

Use of GadTools gadgets requires some per-window context information.
CreateContext() establishes a place for that information to go. This
function must be called before any GadTools gadgets are created.

    struct Gadget *CreateContext( struct Gadget **glistptr );

The glistptr argument is a double-pointer to a Gadget structure.  More
specifically, this is a pointer to a NULL-initialized pointer to a Gadget
structure.

The return value of CreateContext() is a pointer to this gadget, which
should be fed to the program's first call to CreateGadget().  This pointer
to the Gadget structure returned by CreateContext(), may then serve as a
handle to the list of gadgets as they are created.  The code fragment
listed in the next section shows how to use CreateContext() together with
CreateGadget() to make a linked list of GadTools gadgets.


15 / GadTools Gadgets / Creating Gadget Lists

In the discussion of CreateGadget() presented earlier, the examples showed
only how to make a single gadget.  For most applications that use
GadTools, however, a whole list of gadgets will be needed.  To do this,
the application could use code such as this:

    struct NewGadget *newgad1, *newgad2, *newgad3;
    struct Gadget *glist = NULL;
    struct Gadget *pgad;

    ...
    /* Initialize NewGadget structures */
    ...

    /* Note that CreateContext() requires a POINTER to a NULL-initialized
     * pointer to struct Gadget:
     */
    pgad = CreateContext(&glist);

    pgad = CreateGadget(BUTTON_KIND, pgad, newgad1, TAG_END);
    pgad = CreateGadget(STRING_KIND, pgad, newgad2, TAG_END);
    pgad = CreateGadget(MX_KIND,     pgad, newgad3, TAG_END);

    if (!pgad)
        {
        FreeGadgets(glist);
        exit_error();
        }
    else
        {
        if ( mywin=OpenWindowTags(NULL,
                                  WA_Gadgets,   glist,
                                  ...
                                  /* Other tags... */
                                  ...
                                  TAG_END) )
            {
            /* Complete the rendering of the gadgets */
            GT_RefreshWindow(win, NULL);
            ...
            /* and continue on... */
            ...
            CloseWindow(mywin);
            }

        FreeGadgets(glist);
        }

The pointer to the previous gadget, pgad in the code fragment above, is
used for three purposes.  First, when CreateGadget() is called multiple
times, each new gadget is automatically linked to the previous gadget's
NextGadget field, thus creating a gadget list.  Second, if one of the
gadget creations fails (usually due to low memory, but other causes are
possible), then for the next call to CreateGadget(), pgad will be NULL and
CreateGadget() will fail  immediately.  This means that the program can
perform several successive calls to CreateGadget() and only have to check
for failure at the end.

Finally, although this information is hidden in the implementation and not
important to the application, certain calls to CreateGadget() actually
cause several Intuition gadgets to be allocated and these are
automatically linked together without program interaction, but only if a
previous gadget pointer is supplied.  If several gadgets are created by a
single CreateGadget() call, they work together to provide the
functionality of a single GadTools gadget.  The application should always
act as though the gadget pointer returned by CreateGadget() points to a
single gadget instance.  See "Documented Side-Effects" for a warning.

There is one exception to the fact that a program only has to check for
failure after the last CreateGadget() call and that is when the
application depends on the successful creation of a gadget and caches or
immediately uses the gadget pointer returned by CreateGadget().

 For instance, if the program wants to create a string gadget and save a
pointer to the string buffer, it might do so as follows:

    gad = CreateGadget(STRING_KIND, gad, &ng,
                            GTST_String, "Hello World",
                            TAG_END);
    if (gad)
        {
        stringbuffer = ((struct StringInfo *)(gad->SpecialInfo))->Buffer;
        }

    /* Creation can continue here: */
    gad = CreateGadget(..._KIND, gad, &ng2,
        ...
        TAG_END);

A major benefit of having a reusable NewGadget structure is that often
many fields do not change and some fields change incrementally.  For
example, the application can set just the NewGadget's ng_VisualInfo and
ng_TextAttr only once and never have to modify them again even if the
structure is reused to create many gadgets.  A set of similar gadgets may
share size and some positional information so that code such as the
following might be used:

    /* Assume that the NewGadget structure 'ng' is fully
     * initialized here for a button labelled "OK"
     */
    gad = CreateGadget(BUTTON_KIND, gad, &ng,
        TAG_END);

    /* Modify only those fields that need to change: */
    ng.ng_GadgetID++;
    ng.ng_LeftEdge += 80;
    ng.ng_GadgetText = "Cancel";
    gad = CreateGadget(BUTTON_KIND, gad, &ng,
                            TAG_END);

    Warning:
    --------
    All gadgets created by GadTools currently have the GADTOOL_TYPE bit
    set in their GadgetType field.  It is not correct to check for,
    set, clear or otherwise rely on this since it is subject to change.


15 / GadTools Gadgets / Gadget Refresh Functions

Normally, GadTools gadgets are created and then attached to a window when
the window is opened, either through the WA_Gadget tag or the
NewWindow.FirstGadget field.  Alternately, they may be added to a window
after it is open by using the functions AddGList() and RefreshGList().

Regardless of which way gadgets are attached to a window, the program must
then call the GT_RefreshWindow() function to complete the rendering of
GadTools gadgets.  This function takes two arguments.

    void GT_RefreshWindow( struct Window *win, struct Requester *req );

This win argument is a pointer to the window that contains the GadTools
gadgets.  The req argument is currently unused and should be set to NULL.
This function should only be called immediately after adding GadTools
gadgets to a window.  Subsequent changes to GadTools gadget imagery made
through calls to GT_SetGadgetAttrs() will be automatically performed by
GadTools when the changes are made.  (There is no need to call
GT_RefreshWindow() in that case.)

As mentioned earlier, applications must always ask for notification of
window refresh events for any window that uses GadTools gadgets.  When the
application receives an IDCMP_REFRESHWINDOW message for a window,
Intuition has already refreshed its gadgets.  Normally, a program would
then call Intuition's BeginRefresh(), perform its own custom rendering
operations, and finally call EndRefresh().  But for a window that uses
GadTools gadgets, the application must call GT_BeginRefresh() and
GT_EndRefresh() in place of BeginRefresh() and EndRefresh().  This allows
the the GadTools gadgets to be fully refreshed.

    void GT_BeginRefresh( struct Window *win );
    void GT_EndRefresh ( struct Window *win, long complete );

For both functions, the win argument is a pointer to the window to be
refreshed.  For GT_EndRefresh(), set the complete argument to TRUE if
refreshing is complete, set it to FALSE otherwise.  See the discussion of
BeginRefresh() and EndRefresh() in the "Intuition Windows" chapter for
more about window refreshing.

When using GadTools gadgets, the program may not set the window's
WFLG_NOCAREREFRESH flag.  Even if there is no custom rendering to be
performed, GadTools gadgets requires this minimum code to handle
IDCMP_REFRESHWINDOW messages:

    case IDCMP_REFRESHWINDOW:
        GT_BeginRefresh(win);
        /* custom rendering, if any, goes here */
        GT_EndRefresh(win, TRUE);
        break;


15 / GadTools Gadgets / Other GadTools Functions

This section discusses some additional support functions in the GadTools
library that serve special needs.

 GT_FilterIMsg() and GT_PostFilterIMsg()    DrawBevelBox()


15 / / Other Functions / GT_FilterIMsg() and GT_PostFilterIMsg()

For most GadTools programs, GT_GetIMsg() and GT_ReplyIMsg() work perfectly
well.  In rare cases an application may find they pose a bit of a problem.
A typical case is when all messages are supposed to go through a
centralized ReplyMsg() that cannot be converted to a GT_ReplyIMsg().
Since calls to GT_GetIMsg() and GT_ReplyIMsg() must be paired, there would
be a problem.

For such cases, the GT_FilterIMsg() and GT_PostFilterIMsg() functions are
available.  These functions allow GetMsg() and ReplyMsg() to be used in a
way that is compatible with GadTools.

    Warning:
    --------
    These functions are for specialized use only and will not be used by
    the majority of applications.  See GT_GetIMsg() and
    GT_ReplyIMsg() for standard message handling.

    struct IntuiMessage *GT_FilterIMsg( struct IntuiMessage *imsg );
    struct IntuiMessage *GT_PostFilterIMsg( struct IntuiMessage *imsg );

The GT_FilterIMsg() function should be called right after GetMsg().  It
takes a pointer to the original IntuiMessage and, if the message applies
to a GadTools gadget, returns either a modified IntuiMessage or a NULL.  A
NULL return signifies that the message was consumed by a GadTools gadget
(and not needed by the application).

The GT_PostFilterIMsg() function should be called before replying to any
message modified by GT_FilterIMsg().  It takes a pointer to the modified
version of an IntuiMessage obtained with GT_FilterIMsg() and returns a
pointer to the original IntuiMessage.

The typical calling sequence for a program that uses these functions, is
to call GetMsg() to get the IntuiMessage.  Then, if the message applies to
a window which contains GadTools gadgets, call GT_FilterIMsg().  Any
message returned by GT_FilterIMsg() should be used like a message returned
from GT_GetIMsg().

When done with the message, the application must call GT_PostFilterIMsg()
to perform any clean up necessitated by the previous call to
GT_FilterIMsg().  In all cases, the application must then reply the
original IntuiMessage using ReplyMsg().  This is true even for consumed
messages as these are not replied by GadTools.  For example, the
application could use code such as this:

    /* port is a message port receiving different messages */
    /* gtwindow is the window that contains GadTools gadgets */

    imsg = GetMsg(port);

    /* Is this the window with GadTools gadgets? */
    if (imsg->IDCMPWindow == gtwindow)
        {
        /* Filter the message and see if action is needed */
        if (gtimsg = GT_FilterIMsg(imsg))
            {
            switch (gtimsg->Class)
                {
                /* Act depending on the message */
                ...
                }
            /* Clean up the filtered message.  The return value is not */
            /* needed since we already have a pointer to the original  */
            /* message.                                                */
            GT_PostFilterIMsg(gtimsg);
            }
        }
    /* other stuff can go here */
    ReplyMsg(imsg);

You should not make any assumptions about the contents of the unfiltered
IntuiMessage (imsg in the above example).  Only two things are guaranteed:
the unfiltered IntuiMessage must be replied to and the unfiltered
IntuiMessage (if it produces anything when passed through GT_FilterIMsg())
will produce a meaningful GadTools IntuiMessage like those described in
the section on the different kinds of gadgets.  The relationship between
the unfiltered and filtered messages are expected to change in the future.
See the section on documented side-effects for more information.


15 / / Other GadTools Functions / DrawBevelBox()

A key visual signature shared by most GadTools gadgets is the raised or
recessed bevelled box imagery.  Since the program may wish to create its
own boxes to match, GadTools provides the DrawBevelBox() and
DrawBevelBoxA() functions.

    void DrawBevelBoxA( struct RastPort *rport, long left, long top,
                        long width, long height, struct TagItem *taglist );
    void DrawBevelBox ( struct RastPort *rport, long left, long top,
                        long width, long height, Tag tag1, ... );

The rport argument is a pointer to the RastPort into which the box is to
be rendered.  The left, top, width and height arguments specify the
dimensions of the desired box.

The tag arguments, tag1 or taglist, may be set as follows:

GT_VisualInfo (APTR)
    The VisualInfo handle as returned by a prior call to GetVisualInfo().
    This value is required.

GTBB_Recessed (BOOL)
    A bevelled box may either appear to be raised to signify an area of
    the window that is selectable or recessed to signify an area of the
    window in which clicking will have no effect.  Set this boolean tag
    to TRUE to get a recessed box.  Omit this tag entirely to get a
    raised box.

DrawBevelBox() is a rendering operation, not a gadget. This means that the
program must refresh any bevelled boxes rendered through this function if
the window gets damaged.


15 / GadTools Gadgets / Gadget Keyboard Equivalents

Often, users find it convenient to control gadgets using the keyboard.
Starting with V37, it is possible to denote the keyboard equivalent for a
GadTools gadget.  The keyboard equivalent will be an underscored character
in the gadget label, for easy identification.  At the present time,
however, the application is still responsible for implementing the
reaction to each keypress.

 Denoting a Gadget's Keyboard Equivalent
 Implementing a Gadget's Keyboard Equivalent Behavior


15 / / Keyboard Equivalents / Denoting a Gadget's Keyboard Equivalent

In order to denote the key equivalent, the application may add a
marker-symbol to the gadget label.  This is done by placing the
marker-symbol immediately before the character to be underscored.  This
symbol can be any character that is not used in the label.  The underscore
character, `_' is the recommended marker-symbol.  So, for example, to mark
the letter "F" as the keyboard equivalent for a button labelled "Select
Font...", create the gadget text:

    ng.ng_GadgetText = "Select _Font...";

To inform GadTools of the underscore in the label, pass the GA_Underscore
tag to CreateGadget() or CreateGadgetA().  The data-value associated with
this tag is a character, not a string, which is the marker-symbol used in
the gadget label:

    GA_Underscore, '_',/* Note '_', not "_" !!! */

GadTools will create a gadget label which consists of the text supplied
with the marker-symbol removed and the character following the
marker-symbol underscored.

The gadget's label would look something like:

    Select Font...
           -


15 / / / Implementing a Gadget's Keyboard Equivalent Behavior

Currently, GadTools does not process keyboard equivalents for gadgets.  It
is up to the application writer to implement the correct behavior,
normally by calling GT_SetGadgetAttrs() on the appropriate gadget.  For
some kinds of gadget, the behavior should be the same regardless of
whether the keyboard equivalent was pressed with or without the shift key.
For other gadgets, shifted and unshifted keystrokes will have different,
usually opposite, effects.

Here is the correct behavior for keyboard equivalents for each kind of
GadTools gadget:

Button Gadgets
    The keyboard equivalent should invoke the same function that clicking
    on the gadget does.  There is currently no way to highlight the
    button visuals programmatically when accessing the button through a
    keyboard equivalent.

Text-Entry and Number-Entry Gadgets
    The keyboard equivalent should activate the gadget so the user may
    type into it.  Use Intuition's ActivateGadget() call.

Checkbox Gadgets
    The keyboard equivalent should toggle the state of the checkbox.  Use
    GT_SetGadgetAttrs() and the GTCB_Checked tag.

Mutually-Exclusive Gadgets
    The unshifted keystroke should activate the next choice, wrapping
    around from the last to the first.  The shifted keystroke should
    activate the previous choice, wrapping around from the first to the
    last.  Use GT_SetGadgetAttrs() and the GTMX_Active tag.

Cycle Gadgets
    The unshifted keystroke should activate the next choice, wrapping
    around from the last to the first.  The shifted keystroke should
    activate the previous choice, wrapping around from the first to the
    last.  Use GT_SetGadgetAttrs() and the GTCY_Active tag.

Slider Gadgets
    The unshifted keystroke should increase the slider's level by one,
    stopping at the maximum, while the shifted keystroke should decrease
    the level by one, stopping at the minimum.  Use GT_SetGadgetAttrs()
    and the GTSL_Level tag.

Scroller Gadgets
    The unshifted keystroke should increase the scroller's top by one,
    stopping at the maximum, while the shifted keystroke should decrease
    the scroller's top by one, stopping at the minimum.  Use
    GT_SetGadgetAttrs() and the GTSC_Top tag.

Listview Gadgets
    The unshifted keystroke should cause the next entry in the list to
    become the selected one, stopping at the last entry, while the
    shifted keystroke should cause the previous entry in the list to
    become the selected one, stopping at the first entry.  Use
    GT_SetGadgetAttrs() and the GTLV_Top and GTLV_Selected tags.

Palette Gadgets
    The unshifted keystroke should select the next color, wrapping around
    from the last to the first.  The shifted keystroke should activate
    the previous color, wrapping around from the first to the last.  Use
    GT_SetGadgetAttrs() and the GTPA_Color tag.

Text-Display and Number-Display Gadgets
    These kinds of GadTools gadget have no keyboard equivalents since
    they are not selectable.

Generic Gadgets
    Define appropriate keyboard functions based on the kinds of keyboard
    behavior defined for other GadTools kinds.


15 / GadTools Gadgets / Restrictions on GadTools Gadgets

There is a strict set of functions and operations that are permitted on
GadTools gadgets.  Even if a technique is discovered that works for a
particular case, be warned that it cannot be guaranteed and should not be
used.  If the trick concocted only works most of the time, it may
introduce subtle problems in the future.

Never selectively or forcibly refresh gadgets.  The only gadget refresh
that should ever be performed is the initial GT_RefreshWindow() after a
window is opened with GadTools gadgets attached.  It is also possible to
add gadgets after the window is opened by calling AddGlist() and
RefreshGlist() followed by GT_RefreshWindow().  These refresh functions
should not be called at any other time.

GadTools gadgets may not overlap with each other, with other gadgets or
with other imagery.  Doing this to modify the gadget's appearance is not
supported.

GadTools gadgets may not be selectively added or removed from a window.
This has to do with the number of Intuition gadgets that each call to
CreateGadget() produces and with refresh constraints.

Never use OnGadget() or OffGadget() or directly modify the GFLG_DISABLED
Flags bit.  The only approved way to disable or enable a gadget is to use
GT_SetGadgetAttrs() and the GA_Disabled tag.  Those kinds of GadTools
gadgets that do not support GA_Disabled may not be disabled (for now).

The application should never write into any of the fields of the Gadget
structure or any of the structures that hang off it, with the exception
noted earlier for GENERIC_KIND gadgets.  Avoid making assumptions about
the contents of these fields unless they are explicitly programmer fields
(GadgetID and UserData, for example) or if they are guaranteed meaningful
(LeftEdge, TopEdge, Width, Height, Flags).  On occasion, the program is
specifically invited to read a field, for example the StringInfo->Buffer
field.

GadTools gadgets may not be made relative sized or relative positioned.
This means that the gadget flags GFLG_RELWIDTH, GFLG_RELHEIGHT,
GFLG_RELBOTTOM and GFLG_RELRIGHT may not be specified.  The activation
type of the gadget may not be modified (for example changing
GACT_IMMEDIATE to GACT_RELVERIFY).  The imagery or the highlighting method
may not be changed.

These restrictions are not imposed without reason; subtle or blatant
problems may arise now or in future versions of GadTools for programs that
violate these guidelines.


15 / GadTools Gadgets / Documented Side-Effects

There are certain aspects of the behavior of GadTools gadgets that should
not be depended on. This will help current applications remain compatible
with future releases of the GadTools library.

When using GT_FilterIMsg() and GT_PostFilterIMsg(), never make assumptions
about the message before or after filtering.  I.e., do not interpret the
unfiltered message, assume that it will or will not result in certain
kinds of filtered message or assume it will result in a consumed message
(i.e., when GT_FilterIMsg() returns NULL).

IDCMP_INTUITICKS messages are consumed when a scroller's arrows are
repeating.  That is, IDCMP_INTUITICKS will not be received while the user
is pressing a scroller arrows.  Do not depend or rely on this side effect,
though, it will not necessarily remain so in the future.

A single call to CreateGadget() may create one or more actual gadgets.
These gadgets, along with the corresponding code in GadTools, define the
behavior of the particular kind of GadTools gadget requested.  Only the
behavior of these gadgets is documented, the number or type of actual
gadgets is subject to change.  Always refer to the gadget pointer received
from CreateGadget() when calling GT_SetGadgetAttrs().  Never refer to
other gadgets created by GadTools, nor create code which depends on their
number or form.

For text-display gadgets, the GTTX_CopyText tag does not cause the text to
be copied when the text is later changed with GTTX_Text.

The PLACETEXT ng_Flags are currently ignored by GENERIC_KIND gadgets.
However, this may not always be so.

All GadTools gadgets set GADTOOL_TYPE in the gadget's GadgetType field.
Do not use this flag to identify GadTools gadgets, as this flag is not
guaranteed to be set in the future.

The palette gadget subdivides its total area into the individual color
squares. Do not assume that the subdivision algorithm won't change.


15 GadTools Library / Function Reference

The following are brief descriptions of the Intuition functions discussed
in this chapter.  See the "Amiga ROM Kernel Reference Manual: Includes and
Autodocs" for details on each function call.  All of these functions
require Release 2 or a later version of the operating system.

               Table 15-2: GadTools Library Functions
  ______________________________________________________________________
 |                                                                      |
 |          Function                  Description                       |
 |======================================================================|
 |       CreateGadgetA()  Allocate GadTools gadget, tag array form.     |
 |        CreateGadget()  Allocate GadTools gadget, varargs form.       |
 |         FreeGadgets()  Free all GadTools gadgets.                    |
 |  GT_SetGadgetAttrsA()  Update gadget, tag array form.                |
 |   GT_SetGadgetAttrs()  Update gadget, varargs form.                  |
 |       CreateContext()  Create a base for adding GadTools gadgets.    |
 |----------------------------------------------------------------------|
 |        CreateMenusA()  Allocate GadTools menu structures, tag array  |
 |                        form.                                         |
 |         CreateMenus()  Allocate GadTools menu structures, varargs    |
 |                        form.                                         |
 |           FreeMenus()  Free menus allocated with CreateMenus().      |
 |    LayoutMenuItemsA()  Format GadTools menu items, tag array form.   |
 |     LayoutMenuItems()  Format GadTools menu items, varargs form.     |
 |        LayoutMenusA()  Format GadTools menus, tag array form.        |
 |         LayoutMenus()  Format GadTools menus, varargs form.          |
 |----------------------------------------------------------------------|
 |          GT_GetIMsg()  GadTools gadget compatible version of         |
 |                        GetMsg().                                     |
 |        GT_ReplyIMsg()  GadTools gadget compatible version of         |
 |                        ReplyMsg().                                   |
 |       GT_FilterIMsg()  Process GadTools gadgets with                 |
 |                        GetMsg()/ReplyMsg().                          |
 |   GT_PostFilterIMsg()  Process GadTools gadgets with                 |
 |                        GetMsg()/ReplyMsg().                          |
 |----------------------------------------------------------------------|
 |    GT_RefreshWindow()  Display GadTools gadget imagery after         |
 |                        creation.                                     |
 |     GT_BeginRefresh()  GadTools gadget compatible version of         |
 |                        BeginRefresh().                               |
 |       GT_EndRefresh()  GadTools gadget compatible version of         |
 |                        EndRefresh().                                 |
 |----------------------------------------------------------------------|
 |       DrawBevelBoxA()  Draw a 3D box, tag array form.                |
 |        DrawBevelBox()  Draw a 3D box, varargs form.                  |
 |----------------------------------------------------------------------|
 |      GetVisualInfoA()  Get drawing information for GadTools, tag     |
 |                        array form.                                   |
 |       GetVisualInfo()  Get drawing information for GadTools, varargs |
 |                        form.                                         |
 |      FreeVisualInfo()  Free drawing information for GadTools.        |
 |______________________________________________________________________|


Amiga® RKM Libraries: 16 ASL Library

This chapter describes the asl.library.  The sole purpose of this library
is to provide standard file and font requesters for application programs.

It is easier to understand the asl.library if you are familiar with some
basic concepts of the Amiga operating system, especially TagItem arrays
(described in the "Utility Library" chapter), Intuition screens and
windows, graphics library font structures, and AmigaDOS pattern matching.

 About Requesters             Calling Custom Functions from a Requester
 Creating a File Requester    Function Reference
 Creating a Font Requester


16 ASL Library / About Requesters

Requesters are temporary sub-windows used for confirming actions or
selecting options.  The most common type of requester is a file requester
which is used to pick a file name for a load or save operation.

Under 1.3 (V34) and earlier versions of the Amiga operating system there
was limited support for requesters.  Intuition provides simple requesters
which can be used to request responses such as OK or Cancel from the user.
More elaborate Intuition requesters can be created by adding additional
features such as string gadgets, however the result of this is that each
application writer develops their own style of requester.  Hence, the
asl.library has been added to Release 2 of the Amiga operating system to
make requesters more consistent.  With asl.library, requesters are also
much easier to create and take less memory.

    The ASL Library Requires Release 2.
    -----------------------------------
    The asl.library requires Release 2 of the Amiga operating system, so
    only applications running under Release 2 and later versions of the
    Amiga OS can call its functions.

Requesters are very flexible and can be used for many different purposes.
The Release 2 asl.library supports the two most common type of requesters:

  * File requesters for choosing a file name in a load or save operation

  * Font requesters for choosing a font in a text operation


16 ASL Library / Creating a File Requester

Opening an ASL requester requires the use of three functions:

    APTR request =  AllocAslRequest( unsigned long type,
                                     struct TagItem *tagList );
    BOOL success =  AslRequest( APTR request, struct TagItem *tagList );
    void            FreeAslRequest( APTR request );

The first function you should call is AllocAslRequest().  This allocates
the main data structure you will use, either a FileRequester structure or
a FontRequester structure.  You specify the type of requester you want for
AllocAslRequest() by setting the type argument.  This can be one of two
values defined in <libraries/asl.h>:  either ASL_FileRequest, to ask for a
FileRequester structure, or ASL_FontRequest, to ask for a FontRequester
structure.

Here's a listing of the FileRequester structure.  (The FontRequester
structure is discussed in more detail later in this chapter.)

    struct FileRequester    {          /* (from <libraries/asl.h>)     */
        APTR    rf_Reserved1;
        BYTE    *rf_File;          /* Filename pointer             */
        BYTE    *rf_Dir;           /* Directory name pointer       */
        CPTR    rf_Reserved2;
        UBYTE   rf_Reserved3;
        UBYTE   rf_Reserved4;
        APTR    rf_Reserved5;
        WORD    rf_LeftEdge,rf_TopEdge; /* Preferred window pos   */
        WORD    rf_Width,rf_Height;     /* Preferred window size  */
        WORD    rf_Reserved6;
        LONG    rf_NumArgs;        /* A-la WB Args, for multiselects */
        struct WBArg *rf_ArgList;
        APTR    rf_UserData;       /* Applihandle (you may write!!)  */
        APTR    rf_Reserved7;
        APTR    rf_Reserved8;
        BYTE    *rf_Pat;           /* Pattern match pointer          */
        };                         /* note - more reserved fields follow */

Whichever requester type you use, you must allocate the requester
structure with the AllocAslRequest() function call.  Do not create the
data structure yourself.  The values in this structure are for read access
only.  Any changes to them must be performed only through asl.library
function calls.

Once you have set up a requester structure with AllocAslRequest(), call
AslRequest() to make the requester appear on screen.  AslRequest() takes
the requester data structure as an argument using it as a specification
for the requester that it creates on screen.

     Figure 16-1: The ASL File Requester

AslRequest() is always synchronous to the calling program.  That is,
control does not return to your program until the user makes a selection
or cancels.  AslRequest() returns TRUE, if the user selects a file (or a
font).  In that case the file (or font) name that the user selected is
returned in the requester data structure.  AslRequest() returns FALSE if
the user cancels the requester or the requester failed for some reason.

When you have finished with a requester use the FreeAslRequest() function
to deallocate the requester data structure.

 Specifying Requester Options with TagItems
 Simple ASL File Requester Example
 File Pattern Matching and Multiple Selects
 ASL Requesters and Custom Screens
 The Save Requester
 The Directory Requester


16 / Creating a File Requester / Specifying Options with TagItems

Both AllocAslRequest() and AslRequest() accept a TagItem array or tag list
as an argument.  The tag list is used to initialize or alter the values in
the requester data structure.

A single TagItem consists of a tag name and an associated tag value.  Tag
items that apply to the asl.library are defined in <libraries/asl.h>.  The
basic tag items (used in the first example listed below) are:

   Requester
   Tag Name        Used For
   ---------       --------
   ASL_Hail        String to place in the title bar of the requester window
   ASL_Width       Requester window width
   ASL_Height      Requester window height
   ASL_LeftEdge    Requester window y origin
   ASL_TopEdge     Requester window x origin
   ASL_OKText      String to place in OK gadget of requester
   ASL_CancelText  String to place in Cancel gadget of requester
   ASL_File        Default file name (for file requesters only)
   ASL_Dir         Default directory name (for file requesters only)

Note that you are currently limited to about six characters for the
replacement text if you use either the ASL_OKText or ASL_CancelText tags
to change the text that appears in the OK and Cancel gadgets.

The contents of an ASL requester data structure are preserved across calls
to AslRequest().  So, until the requester is freed, tag settings and user
selections will remain in the data structure unless they are altered by
tags in subsequent calls to AslRequest().  This is very useful because it
allows the requester to remember and redisplay the user's previous
selections.  However, this also means that the programmer must assure that
any addresses passed in ASL tags remain valid, or are refreshed on each
call to AslRequest().

Generally, options that you wish to specify only once, such as the initial
position and size, should be specified as tags when you allocate the
requester.  Options that you wish to control for each use of the requester
should be passed as tags each time the requester is opened with
AslRequest().


16 / / File Pattern Matching and Multiple Selects

A file requester can filter out certain file and directory entries using
the "wildcard" feature of  AmigaDOS.  To activate the wildcard feature for
a file requester, you use the ASL_FuncFlags tag.  Each bit in the
ASL_FuncFlags tag item controls a special option of the requester
depending on its type (file or font).  See <libraries/asl.h> for a
complete listing of the options that the ASL_FuncFlags tag controls.

 File Requester Flag  Used For
 -------------------  --------
  FILF_PATGAD         Enables the file name pattern matching gadget
  FILF_MULTISELECT    Enables multiple selection of files
  FILF_NEWIDCMP       Use separate IDCMP for requester sharing a custom
                      screen (see below)
  FILF_SAVE           Makes the file requester a save requester (see below)

If the FILF_PATGAD bit of the ASL_FuncFlags tag is set, the file requester
will appear with a "Pattern" gadget in addition to the usual file name and
directory name gadgets.  The user can type an AmigaDOS wildcard pattern
into this gadget and the pattern will be used to limit the file names that
appear in the requester.  An application can also supply a default pattern
using the ASL_Pattern tag item. A hidden unchangeable pattern can be
created by supplying an ASL_Pattern without a FILF_PATGAD gadget. Such
invisible patterns should not be used if there is any reason that the user
may need to access a file which does not match the pattern.

Another feature of the ASL file requester is multiple selection.  When
multiple selection is enabled, the user can choose more than one file name
in a single directory by selecting names in the requester's scrolling list
gadget with the mouse.  This option, like pattern matching, is set up with
the ASL_FuncFlags tag.

If the FILF_MULTISELECT bit of the ASL_FuncFlags tag is set, the file
requester will allow multiple selection.  When the user selects several
file names through the multiple selection feature, the FileRequester's
rf_NumArgs field contains the number of files selected and the rf_ArgList
field contains a pointer to an array of WBArg structures (defined in
<workbench/startup.h>).  There is a WBArg structure containing a file name
for each file the user selected.

The following example illustrates a file requester with both a pattern
matching gadget and multiple selection enabled.

     filepat.c

The previous example demonstrates two alternate functions for creating and
using ASL requesters:

    APTR AllocAslRequestTags( unsigned long type, Tag Tag1, ... );
    BOOL AslRequestTags( APTR request, Tag Tag1, ... );

AllocAslRequestTags() can be used instead of AllocAslRequest() to allocate
and set up the file requester.  This is an amiga.lib function that will
accept TagItems directly in its parameter list, rather than a pointer to
an array of TagItems.

Similarly, AslRequestTags() will accept TagItems directly instead of
requiring a pointer to an array of TagItems as AslRequest() does.


16 / Creating a File Requester / ASL Requesters and Custom Screens

An application that uses a custom screen normally wants its requesters to
open on its screen.  Using the ASL_Window tag, a program can associate a
requester with a specific window so that the requester appears on the same
screen as the window.  The ASL_Window tag is followed by a pointer to a
window structure.  ASL_Window works with both file and font requesters.
The example above shows how the ASL_Window tag is used with a file
requester.

Normally, a requester associated with a window (using ASL_Window) shares
that window's IDCMP port for its communication.  An application may not
want to share an IDCMP port with the requester.  Using the ASL_FuncFlags
tag, a program can ask for a requester that creates its own IDCMP port.
There are two flags that accomplish this.  The first, FILF_NEWIDCMP, is
used on file requesters.   The other, FONF_NEWIDCMP, is used on font
requesters.


16 / Creating a File Requester / The Save Requester

The save requester is a special type of file requester used for save
operations.  It differs from the regular ASL file requester in several
ways.  First, the color of the text making up the file names and the
background color are interchanged.  This makes it more apparent to the
user that they are looking at a save requester (instead of the usual load
requester).

Another difference, is that a save requester does not allow the user to
select an existing file name by double-clicking on an entry in the
scrolling list gadget.  This helps prevent the user from accidentally
overwriting the wrong file.

Save requesters can also create directories.  If the user types a
directory name into the save requester and the directory doesn't exist,
the save requester will create that directory (after getting the user's
permission via another requester).

To create a save requester, set the FILF_SAVE flag of the ASL_FuncFlags
tag. Remember that ASL tags and flag values are preserved across calls to
AslRequest(), so if you use a save requester, you must clear the FILF_SAVE
bit and reset your ASL_FuncFlags when you want a load requester. Note that
it does not make sense to have multiselection in a save requester, so the
FILF_SAVE flag overrides the FILF_MULTISELECT flag.


16 / Creating a File Requester / The Directory Requester

Sometimes a program may only require a directory name from the user. There
is another variation on asl.library's file requester that allows this.
The ASL_ExtFlags1 tag contains a flag bit to toggle this option. If the
FIL1F_NOFILES flag of ASL_ExtFlags1 is set, the requester will appear
without a string gadget for file names and will display only directory
names in the scrolling list gadget. When AslRequest() (or AslRequestTags()
) returns successfully, the rf_Dir field of the FileRequester structure
contains the name of the directory the user selected.

Another flag defined for ASL_ExtFlags1 is FIL1F_MATCHDIRS. If file pattern
matching is on (see the FILF_PATGAD flag for ASL_FuncFlags, setting
FIL1F_MATCHDIRS tells the file requester to pattern match directory names
as well as file names.  Of course, if both of these ASL_ExtFlags1 flags
are set, the requester will only pattern match directory names.


16 ASL Library / Creating a Font Requester

The ASL library also contains a font requester.  Using the font requester
is very similar to using the file requester.  First, allocate a requester
structure with AllocAslRequest() or AllocAslRequestTags().  The type
should be set to ASL_FontRequest in order to get a FontRequester structure:

    struct FontRequester    {
        APTR    fo_Reserved1[2];
        struct TextAttr fo_Attr;        /* Returned TextAttr            */
        UBYTE   fo_FrontPen;            /* Returned pens, if selected   */
        UBYTE   fo_BackPen;
        UBYTE   fo_DrawMode;
        APTR    fo_UserData;
        /* missing from asl.h but present in this structure */
        SHORT   fo_LeftEdge, fo_TopEdge, fo_Width, fo_Height;
        };

Once the requester is set up, call AslRequest() or AslRequestTags() to
make the requester appear on screen.  These functions return TRUE if the
user makes a selection.  In that case, the font selected is returned as a
TextAttr structure in the fo_Attr field of the FontRequester structure.
(The TextAttr structure is defined in <graphics/text.h>.  See the Amiga
ROM Kernel Manual: Includes and Autodocs for a complete listing.)  If the
user cancels the font requester FALSE is returned.

     Figure 16-2: The ASL Font Requester

When the requester is no longer needed, call FreeAslRequest() to
deallocate the requester data structure.

 Specifying Font Requester Options with TagItems
 Example Font Requester


16 / Creating a Font Requester / Specifying Options with TagItems

As with a file requester, the font requester is specified with a TagItem
list.  There are several tags that are specific to the font requester:

  Font Requester
  Tag Name        Used For
  --------------  --------
  ASL_FontName    Default font (fo_Attr.ta_Name)
  ASL_FontHeight  Default font size (fo_Attr.ta_YSize)
  ASL_FontStyles  Default font style (fo_Attr.ta_Style)
  ASL_FontFlags   Default font flags (fo_Attr.ta_Flags)
  ASL_FrontPen    Default font color (fo_FrontPen)
  ASL_BackPen     Default font background color (fo_BackPen)
  ASL_ModeList    Alternate strings for the drawing mode gadget (see below)
  ASL_MinHeight   Minimum font height the requester will display
  ASL_MaxHeight   Maximum font height the requester will display

Note that the last two tags only limit the range of font sizes that the
font requester displays, the user is free to type in any value.

Font requesters have additional special options that are controlled
through the ASL_FuncFlags tag.  This tag works the same way as it does
with file requesters but with different options available.  Recall that
the data for this tag is divided into bit fields, each of which controls a
requester option.  The flags used with the ASL_FuncFlags tag in a font
requester are defined in <libraries/asl.h>:

  Font Requester Flags  Used For
  --------------------  --------
  FONF_FRONTCOLOR       Enables font color selection gadgets
  FONF_BACKCOLOR        Enables font background color selection gadget
  FONF_STYLES           Enables font style selection gadget
  FONF_FIXEDWIDTH       Limits display to fixed width fonts only
  FONF_DRAWMODE         Enables font draw mode gadget

A simple font requester (one without any of the above FONF_ flags set)
only lets the user choose a font and a Y size.  Setting the flags above
adds options to the font requester.  FONF_FRONTCOLOR and FONF_BACKCOLOR
add color selection gadgets to the requester, one for choosing a font's
foreground color (labeled "Text") and the other for choosing the
background color (labeled "Field").  The font requester records the user's
setting in the FontRequester's fo_FrontPen and fo_BackPen fields.

FONF_STYLES sets up several gadgets to choose the style of the font (bold,
italics, underline).  The font requester saves these settings in the
fo_Attr.ta_Style bit field according to the style flags defined in
<graphics/text.h>.  FONF_FIXEDWIDTH limits the font name display to fixed
width (non-proportional) fonts (note that this does not prevent the user
from typing in a proportional font name).

FONF_DRAWMODE adds a cycle gadget to the font requester so the user can
choose the draw mode.  The draw mode is saved in the requester's
fo_DrawMode field.  The number stored there corresponds to the draw mode's
position in the gadget's cycle.

The draw mode cycle gadget initially is labeled "Mode" and has three
elements in its cycle: "JAM1", "JAM2", and "Complement".  These yield a
result of 0, 1, and 2, respectively.  It is possible to change the names
and number of draw modes with the ASL_ModeList tag.  This tag accepts a
pointer to an array of strings.  The first string replaces "Mode" as the
label for the draw mode cycle gadget.  The strings that follow replace the
elements of the cycle gadget.  The last entry in the array has to be NULL
to tell the requester where the list of entries ends.


16 ASL Library / Calling Custom Functions from a Requester

The ASL_HookFunc tag passes an ASL requester a pointer to a custom
function.  The requester can use this function for two purposes.  The
first is to determine if the requester should display a particular file or
font name.  The other purpose is to process messages that the requester
receives at its IDCMP port that are not meant for the requester.  Hook
functions are set up through flag values used with the ASL_FuncFlags tag:

    Hook Function Flag  Used For
    ------------------  --------
    FILF_DOWILDFUNC     Call user hook function on each name in a file
                        requester
    FONF_DOWILDFUNC     Call user hook function on each name in a font
                        requester
    FILF_DOMSGFUNC      Call user hook function for IDCMP messages not
                        used by a file requester
    FONF_DOMSGFUNC      Call user hook function for IDCMP messages not
                        used by a font requester

The FILF_DOWILDFUNC and FONF_DOWILDFUNC flags cause a requester to call
the function you specify with the ASL_HookFunc tag for every file or font
entry.  The requester displays the file or font name only if your hook
function tells it to.  For a file requester, if your hook function returns
a zero, the file requester will display the file name.  For a font
requester, if your hook function returns anything but zero, the font
requester will display the font name and size.

The FILF_DOMSGFUNC and FONF_DOMSGFUNC flags cause a requester to call your
hook function whenever it receives an IntuiMessage that it cannot use at
the IDCMP port that it shares with your window.  (See the section on
"ASL Requesters and Custom Screens" earlier in this chapter for more
information about sharing IDCMP ports.)  If the requester receives any
messages that are not meant for the requester it will call your hook
function (specified with the ASL_HookFunc tag).  Your hook function is
responsible for returning a pointer to the IntuiMessage.  The requester
will take care of replying to the message.

 Parameters Passed to Custom Hook Functions
 Example ASL Requester with Custom Hook Function


16 / Calling Functions / Parameters Passed to Custom Hook Functions

A requester always passes three parameters to your custom hook function:

    ULONG MyHookFunc(ULONG type, CPTR object, CPTR AslRequester)

If MyHookFunc() is called from a file requester doing _DOWILDFUNC, the
three parameters are:

    type = FILF_DOWILDFUNC

    object = pointer to an AnchorPath structure (from <dos/dosasl.h>)

    AslRequester = pointer to the FileRequester that called the hook
                   function (Return a zero to display this file)

The AnchorPath structure is a dos.library structure used in pattern
matching.  Refer to the AmigaDOS Manual, 3rd Edition by Bantam Books for
more information.

If MyHookFunc() is called from a font requester doing _DOWILDFUNC, the
three parameters are:

    type = FONF_DOWILDFUNC

    object = pointer to a TextAttr structure (from <graphics/text.h>)

    AslRequester = pointer to the FontRequester that called the hook
                   function (Return non-zero to display this particular
                   font size)

If MyHookFunc() is called from a file or font requester doing _DOMSGFUNC,
the three parameters are:

    type = FILF_DOMSGFUNC (file requester) or FONF_DOMSGFUNC (font
           requester)

    object = pointer to the IntuiMessage for the function to process

    AslRequester = pointer to the FileRequester or FontRequester that
                   called the hook function (Return a pointer to the
                   IntuiMessage)

Notice that it is possible for a requester to use both _DOWILDFUNC and
_DOMSGFUNC at the same time.  Your hook function has to differentiate
between the two cases by testing the type passed to it.  It is not
possible for a font and file requester to share a hook function for a
_DOWILDFUNC, because FILF_DOWILDFUNC is defined to be the same value as
FONF_DOWILDFUNC, so the hook function cannot tell if the object (from the
prototype above) is a pointer to an AnchorPath structure or a pointer to a
TextAttr structure.  It is possible for font and file requesters to share
one hook function for _DOMSGFUNC (even though FILF_DOMSGFUNC and
FONF_DOMSGFUNC are equal) because, in this case, font and file requesters
both call your hook function in the same manner.


16 ASL Library / Function Reference

The following are brief descriptions of the ASL library functions.  See
the Amiga ROM Kernel Reference Manual: Includes and Autodocs for details
on each function call.  All of these functions require Release 2 or a
later version of the operating system.

                 Table 16-1: Functions for ASL Requesters
  ________________________________________________________________________
 |                                                                        |
 |           Function                   Description                       |
 |========================================================================|
 |                                                                        |
 |      AllocAslRequest()  Allocates an ASL font or file requester from   |
 |                         a TagItem array                                |
 |  AllocAslRequestTags()  Same as AllocAslRequest() but accepts tags     |
 |                         directly                                       |
 |           AslRequest()  Displays an ASL requester with options set up  |
 |                         in a TagItem array                             |
 |       AslRequestTags()  Same as AslRequest() but accepts tags directly |
 |       FreeAslRequest()  Deallocates an ASL requester created with      |
 |                         AllocAslRequest()                              |
 |________________________________________________________________________|


Amiga® RKM Libraries: 17 Introduction to Exec

The Multitasking Executive, better known as Exec, is the heart of the
Amiga's operating system.  All other systems in the Amiga rely on it to
control multitasking, to manage the message-based interprocess
communications system, and to arbitrate access to system resources.
Because just about every software entity on the Amiga (including
application programs) needs to use Exec in some way, every Amiga
programmer has to have a basic understanding of its fundamentals.

 Multitasking                 Interprocess Communications
 Dynamic Memory Allocation    Libraries and Devices
 Signals


17 Introduction to Exec / Multitasking

A conventional micro-computer spends a lot of its time waiting for things
to happen.  It has to wait for such things as the user to push buttons on
the keyboard or mouse, for data to come in through the serial port, and
for data to go out to a disk drive.  To make efficient use of the CPU's
time, an operating system can have the CPU carry out some other task while
it is waiting for such events to occur.

A multitasking operating system reduces the amount of time it wastes, by
switching to another program when the current one needs to wait for an
event.  A multitasking operating system can have several programs, or
tasks, running at the same time.  Each task runs independently of the
others, without having to worry about what the other tasks are doing.
From a task's point of view, it's as if each task has a computer all to
itself.

The Amiga's multitasking works by switching which task is currently using
the CPU.  A task can be a user's application program, or it can be a task
that controls system resources (like the disk drives or the keyboard).
Each task has a priority assigned to it.  Exec will let the task with the
highest priority use the CPU, but only if the task is ready to run.  A
task can be in one of three states: ready, sleeping, or running.

A ready task is not currently using the CPU but is waiting to use the
processor.  Exec keeps a list of the tasks that are ready.  Exec sorts
this list according to task priority, so Exec can easily find the ready
task with the highest priority.  When Exec switches the task that
currently has control of the CPU, it switches to the task at the top of
this list.

A sleeping task is not currently running and is waiting for some event to
happen.  When that event occurs, Exec will move the sleeping task into the
list of ready tasks.

A running task is currently using the CPU.  It will remain the current
task until one of three things occur:

  * A higher priority task becomes ready, so the OS preempts the current
    task and switches to the higher priority task.

  * The currently running task needs to wait for an event, so it goes to
    sleep and Exec switches to the highest priority task in Exec's ready
    list.

  * The currently running task has had control of the CPU for at least a
    preset time period called a quantum and there is another task of
    equal priority ready to run.  In this case, Exec will preempt the
    current task for the ready one with the same priority.  This is known
    as time-slicing.  When there is a group of tasks of equal priority on
    the top of the ready list, Exec will cycle through them, letting each
    one use the CPU for a quantum (a slice of time).

The terms "task" and "process" are often used interchangeably to represent
the generic concept of task.  On the Amiga, this terminology can be a
little confusing because of the names of the data structures that are
associated with Exec tasks.  Each task has a structure associated with it
called a Task structure (defined in <exec/tasks.h>).  Most application
tasks use a superset of the Task structure called a Process structure
(defined in <dos/dosextens.h>).  These terms are confusing to Amiga
programmers because there is an important distinction between the Exec
task with only a Task structure and an Exec task with a Process structure.

The Process structure builds on the Task structure and contains some extra
fields which allow the DOS library to associate an AmigaDOS environment to
the task.  Some elements of a DOS environment include a current input and
output stream and a current working directory.  These elements are
important to applications that need to do standard input and output using
functions like printf().

Exec only pays attention to the Task structure portion of the Process
structure, so, as far as Exec is concerned, there is no difference between
a task with a Task structure and a task with a Process structure.  Exec
considers both of them to be tasks.

An application doesn't normally worry about which structure their task
uses.  Instead, the system that launches the application takes care of it.
Both Workbench and the Shell (CLI) attach a Process structure to the
application tasks that they launch.


17 Introduction to Exec / Dynamic Memory Allocation

The Amiga has a soft machine architecture, meaning that all tasks,
including those that are part of its operating system, do not use fixed
memory addresses.  As a result, any program that needs to use a chunk of
memory must allocate that memory from the operating system.

There are two functions on the Amiga for simple memory allocation:
AllocMem() and AllocVec().  The two functions accept the same parameters,
a ULONG containing the size of the memory block in bytes followed by
32-bit specifier for memory attributes.  Both functions return the address
of a longword aligned memory block if they were successful or NULL if
something went wrong.

AllocVec() differs from AllocMem() in that it records the size of the
memory block allocated so an application does not have to remember the
size of a memory block it allocated.  AllocVec() was introduced in Release
2, so it is not available to the 1.3 developer.

Normally the bitmask of memory attributes passed to these functions will
contain any of the following attributes (these flags are defined in
<exec/memory.h>):

MEMF_ANY
    This indicates that there is no requirement for either Fast or Chip
    memory.  In this case, while there is Fast memory available, Exec
    will only allocate Fast memory.  Exec will allocate Chip memory if
    there is not enough Fast memory.

MEMF_CHIP
    This indicates the application wants a block of Chip memory, meaning
    it wants memory addressable by the Amiga custom chips.  Chip memory
    is required for any data that will be accessed by custom chip DMA.
    This includes floppy disk buffers, screen memory, images that will be
    blitted, sprite data, copper lists, and audio data.  If your
    application requires a block of Chip RAM, it must use this flag to
    allocate the Chip RAM.  Otherwise, the application will fail on
    machines with expanded memory.

MEMF_FAST
    This indicates a memory block outside of the range that the Amiga's
    custom chips can access.  The "FAST" in MEMF_FAST has to do with the
    custom chips and the CPU trying to access the same memory at the same
    time.  Because the custom chips and the CPU both have access to Chip
    RAM, the CPU may have to wait to access Chip RAM while some custom
    chip is reading or writing Chip RAM.  In the case of Fast RAM, the
    custom chips do not have access to it, so the CPU does not have to
    contend with the custom chips access to Fast RAM, making CPU accesses
    to Fast RAM generally faster than CPU access to Chip RAM.

    Since the flag specifies memory that the custom chips cannot access,
    this flag is mutually exclusive with the MEMF_CHIP flag.  If you
    specify the MEMF_FAST flag, your allocation will fail on Amigas that
    have only Chip memory.  Use MEMF_ANY if you would prefer Fast memory.

MEMF_PUBLIC
    This indicates that the memory should be accessible to other tasks.
    Although this flag doesn't do anything right now, using this flag
    will help ensure compatibility with possible future features of the
    OS (like virtual memory and memory protection).

MEMF_CLEAR
    This indicates that the memory should be initialized with zeros.

If an application does not specify any attributes when allocating memory,
the system first looks for MEMF_FAST, then MEMF_CHIP.  There are
additional memory allocation flags for Release 2: MEM_LOCAL, MEMF_24BITDMA
and MEMF_REVERSE.  See the Exec Autodoc for AllocMem() in the Amiga ROM
Kernel Reference Manual: Includes and Autodocs or the include file
<exec/memory.h> for additional information on these flags.  Use of these
flags under earlier versions of the operating system will cause your
allocation to fail.

    Make Sure You Have Memory.
    --------------------------
    Always check the result of any memory allocation to be sure the type
    and amount of memory requested is available.  Failure to do so will
    lead to trying to use an non-valid pointer.

When an application is finished with a block of memory it allocated, it
must return it to the operating system.  There is a function to return
memory for both the AllocMem() and the AllocVec() functions.  FreeMem()
releases memory allocated by AllocMem().

It takes two parameters, a pointer to a memory block and the size of the
memory block.  FreeVec() releases memory allocated by AllocVec().  It
takes only one parameter, a pointer to a memory block allocated by
AllocVec().  The following example shows how to allocate and deallocate
memory.

    APTR  my_mem;

    if (my_mem = AllocMem(100, MEMF_ANY))
    {
        /* Your code goes here */
        FreeMem(my_mem, 100);
    }
    else  { /* couldn't get memory, exit with an error */ }


17 Introduction to Exec / Signals

The Amiga uses a mechanism called signals to tell a task that some event
occurred.  Each task has its own set of 32 signals, 16 of which are set
aside for system use.  When one task signals a second task, it asks the OS
to set a specific bit in the 32-bit long word set aside for the second
task's signals.

Signals are what makes it possible for a task to go to sleep.  When a task
goes to sleep, it asks the OS to wake it up when a specific signal bit
gets set.  That bit is tied to some event.  When that event occurs, that
signal bit gets set.  This triggers the OS into waking up the sleeping
task.

To go to sleep, a task calls a system function called Wait(). This
function takes one argument, a bitmask that tells Exec which of the task's
signal bits to "listen to".  The task will only wake up if it receives one
of the signals whose corresponding bit is set in that bitmask.  For
example, if a task wanted to wait for signals 17 and 19, it would call
Wait() like this:

    mysignals = Wait(1L<<17 | 1L<<19);

Wait() puts the task to sleep and will not return until some other task
sets at least one of these two signals.  When the task wakes up, mysignals
will contain the bitmask of the signal or signals that woke up the task.
It is possible for several signals to occur simultaneously, so any
combination of the signals that the task Wait()ed on can occur.  It is up
to the waking task to use the return value from Wait() to figure out which
signal or signals occurred.

 Looking for Break Keys    Processing Signals Without Wait()ing


17 / Signals / Looking for Break Keys

One common usage of signals on the Amiga is for processing a user break.
As was mentioned earlier, the OS reserves 16 of a tasks 32 signals for
system use.  Four of those 16 signals are used to tell a task about the
Control-C, D, E, and F break keys.  An application can process these
signals.  Usually, only CLI-based programs receive these signals because
the Amiga's console handler is about the only user input source that sets
these signals when it sees the Control-C, D, E, and F key presses.

The signal masks for each of these key presses are defined in <dos/dos.h>:

    SIGBREAKF_CTRL_C
    SIGBREAKF_CTRL_D
    SIGBREAKF_CTRL_E
    SIGBREAKF_CTRL_F

Note that these are bit masks and not bit numbers.


17 / Signals / Processing Signals Without Wait()ing

In some cases an application may need to process signals but cannot go to
sleep to wait for them.  For example, a compiler might want to check to
see if the user hit Control-C, but it can't to go to sleep to check for
the break because that will stop the compiler.  In this case, the task can
periodically check its own signal bits for the Ctrl-C break signal using
the Exec library function, SetSignal():

    oldsignals = ULONG SetSignal(ULONG newsignals, ULONG signalmask);

Although SetSignal() can change a task's signal bits, it can also monitor
them.  The following fragment illustrates using SetSignal() to poll a
task's signal bits for a Ctrl-C break:

    /* Get current state of signals */
    signals = SetSignal(0L, 0L);

    /* check for Ctrl-C */
    if (signals & SIGBREAKF_CTRL_C)
    {
        /* The Ctrl-C signal has been set, take care of processing it... */

        /* ...then clear the Ctrl-C signal */
        SetSignal(0L, SIGBREAKF_CTRL_C);
    }

If your task is waiting for signals, but is also waiting for other events
that have no signal bit (such as input characters from standard input),
you may need to use SetSignal().  In such cases, you must be careful not
to poll in a tight loop (also known as busy-waiting).  Busy-waiting hogs
CPU time and degrades the performance of other tasks.  One easy way around
this is for a task to sleep briefly within its polling loop by using the
timer.device, or the graphics function WaitTOF(), or (if the task is a
Process) the DOS library Delay()) or WaitForChar() functions.

For more information on signals, see the "Exec Signals" chapter of this
manual.


17 Introduction to Exec / Interprocess Communications

Another feature of the Amiga OS is its system of message-based
interprocess communication.  Using this system, a task can send a message
to a message port owned by another task.  Tasks use this mechanism to do
things like trigger events or share data with other tasks, including
system tasks.  Exec's message system is built on top of Exec's task
signaling mechanism.  Most Amiga applications programming (especially
Intuition programming) relies heavily upon this message-based form of
interprocess communication.

When one task sends a message to another task's message port, the OS adds
the message to the port's message queue.  The message stays in this queue
until the task that owns the port is ready to check its port for messages.
Typically, a task has put itself to sleep while it is waiting for an
event, like a message to arrive at its message port. When the message
arrives, the task wakes up to look in its message port.  The messages in
the message port's queue are arranged in first-in-first-out (FIFO) order
so that, when a task receives several messages, it will see the messages
in the order they arrived at the port.

A task can use a message to share any kind of data with another task. This
is possible because a task does not actually transmit an entire message,
it only passes a pointer to a message.  When a task creates a message
(which can have many Kilobytes of data attached to it) and sends it to
another task, the actual message does not move.

Essentially, when task A sends a message to task B, task A lends task B a
chunk of its memory, the memory occupied by the message.  After task A
sends the message, it has relinquished that memory to task B, so it cannot
touch the memory occupied by the message.  Task B has control of that
memory until task B returns the message to task A with the ReplyMsg()
function.

Let's look at an example.  Many applications use Intuition windows as a
source for user input.  Without getting into too much detail about
Intuition, when an application opens a window, it can set up the window so
Intuition will send messages about certain user input events.  Intuition
sends these messages to a message port created by Intuition for use with
this window.  When an application successfully opens a window, it receives
a pointer to a Window structure, which contains a pointer to this message
port (Window.UserPort). For this example, we'll assume the window has been
set up so Intuition will send a message only if the user clicks the
window's close gadget.

When Intuition opens the window in this example, it creates a message port
for the task that opened the Window.  Because the most common message
passing system uses signals, creating this message port involves using one
of the example task's 32 signals.  The OS uses this signal to signal the
task when it receives a message at this message port.  This allows the
task to sleep while waiting for a "Close Window" event to arrive.  Since
this simple example is only waiting for activity at one message port, it
can use the WaitPort() function.  WaitPort() accepts a pointer to a
message port and puts a task to sleep until a message arrives at that port.

This simple example needs two variables, one to hold the address of the
window and the other to hold the address of a message.

    struct Message *mymsg; /*defined in <exec/ports.h> */
    struct Window *mywin;  /* defined in <intuition/intuition.h> */
            ...

    /* at some point, this application would have successfully opened a */
    /* window and stored a pointer to it in mywin.                      */
        ...

        /* Here the application goes to sleep until the user clicks */
        /* the window's close gadget. This window was set up so     */
        /* that the only time Intuition will send a message to this */
        /* window's port is if the user clicks the window's close   */
        /* gadget.                                                  */

        WaitPort(mywin->UserPort);
        while (mymsg = GetMsg(mywin->UserPort))
            /* process message now or copy information from message */
            ReplyMsg(mymsg);
        ...

    /* Close window, clean up */

The Exec function GetMsg() is used to extract messages from the message
port.  Since the memory for these messages belongs to Intuition, the
example relinquishes each message as it finishes with them by calling
ReplyMsg().  Notice that the example keeps on trying to get messages from
the message port until mymsg is NULL.  This is to make sure there are no
messages left in the message port's message queue.  It is possible for
several messages to pile up in the message queue while the task is asleep,
so the example has to make sure it replies to all of them.  Note that the
window should never be closed within this GetMsg() loop because the while
statement is still accessing the window's UserPort.

Note that each task with a Process structure (sometimes referred to as a
process) has a special process message port, Process.pr_MsgPort.  This
message port is only for use by Workbench and the DOS library itself.  No
application should use this port for its own use!

 Waiting on Message Ports and Signals at the Same Time


17 / / Waiting on Message Ports and Signals at the Same Time

Most applications need to wait for a variety of messages and signals from
a variety of sources.  For example, an application might be waiting for
Window events and also timer.device messages.  In this case, an
application must Wait() on the combined signal bits of all signals it is
interested in, including the signals for the message ports where any
messages might arrive.

The MsgPort structure, which is defined in <exec/ports.h>, is what Exec
uses to keep track of a message port.  The UserPort field from the example
above points to one of these structures.  In this structure is a field
called mp_SigBit, which contains the number (not the actual bit mask) of
the message port's signal bit.  To Wait() on the signal of a message port,
Wait() on a bit mask created by shifting 1L to the left mp_SigBit times
(1L << msgport->mp_SigBit).  The resulting bit mask can be OR'd with the
bit masks for any other signals you wish to simultaneously wait on.


17 Introduction to Exec / Libraries and Devices

One of the design goals for the Amiga OS was to make the system dynamic
enough so that the OS could be extended and updated without effecting
existing applications.  Another design goal was to make it easy for
different applications to be able to share common pieces of code.  The
Amiga accomplished these goals through a system of libraries.  An Amiga
library consists of a collection of related functions which can be
anywhere in system memory (RAM or ROM).

Devices are very similar to libraries, except they usually control some
sort of I/O device and contain some extra standard functions. Although
this section does not really discuss devices directly, the material here
applies to them. For more information on devices, see the "Exec Device I/O"
section of this manual or the Amiga ROM Kernel Reference Manual:
Devices.

An application accesses a library's functions through the library's jump,
or vector, table.  Before a task can use the functions of a particular
library, it must first acquire the library's base pointer by calling the
Exec OpenLibrary() function:

    struct Library *OpenLibrary( UBYTE *libName,
                                 unsigned long mylibversion );

where libName is a string naming the library and mylibversion is a version
number for the library.  The version number reflects a revision of the
system software.  The chart below lists the specific Amiga OS release
versions that system libraries versions correspond to:

    30  Kickstart 1.0 -  This revision is obsolete.
    31  Kickstart 1.1 -  This was an NTSC only release and is obsolete.
    32  Kickstart 1.1 -  This was a PAL only release and is obsolete.
    33  Kickstart 1.2 -  This is the oldest revision of the OS still in
                         use.

    34  Kickstart 1.3 -  This is almost the same as release 1.2 except it
                         has an Autobooting expansion.library

    35  This is a special RAM-loaded version of the 1.3 revision, except
                         that it knows about the A2024 display modes.  No
                         application should need this library unless they
                         need to open an A2024 display mode under 1.3.

    36  Kickstart 2.0  - This is the original Release 2 revision that was
                         initially shipped on early Amiga 3000 models.

    37  Kickstart 2.04 - This is the general Release 2 revision for all
                         Amiga models.

The OpenLibrary() function looks for a library with a name that matches
libName and also with a version at least as high as mylibversion.  For
example, to open version 33 or greater of the Intuition library:

    IntuitionBase = OpenLibrary("intuition.library", 33L);

In this example, if version 33 or greater of the Intuition library is not
available, OpenLibrary() returns NULL.  A version of zero in OpenLibrary()
tells the OS to open any version of the library.  Unless your code
requires Release 2 features, it should specify a version number of 33 to
remain backwards compatible with Kickstart 1.2.

When OpenLibrary() looks for a library, it first looks in memory.  If the
library is not in memory, OpenLibrary() will look for the library on disk.
If libName is a library name with an absolute path (for example,
"myapp:mylibs/mylib.library"), OpenLibrary() will follow that absolute
path looking for the library.  If libName is only a library name
("diskfont.library"), OpenLibrary() will look for the library in the
directory that the LIBS: logical assign currently references.

If OpenLibrary() finds the library on disk, it takes care of loading it
and initializing it.  As part of the initialization process, OpenLibrary()
dynamically creates a jump, or vector, table.  There is a vector for each
function in the library.  Each entry in the table consists of a 680x0 jump
instruction (JMP) to one of the library functions.  The OS needs to create
the vector table dynamically because the library functions can be anywhere
in memory.

After the library is loaded into memory and initialized, OpenLibrary() can
actually "open" the library.  It does this by calling the library's Open
function vector.  Every library has a standard vector set aside for an
OPEN function so the library can set up any data or processes that it
needs.  Normally, a library's OPEN function increments its open count to
keep track of how many tasks currently have the library opened.

If any step of OpenLibrary() fails, it returns a NULL value.  If
OpenLibrary() is successful, it returns the address of the library base.
The library base is the address of this library's Library structure
(defined in <exec/libraries.h>).  The Library structure immediately
follows the vector table in memory.

After an application is finished with a library, it must close it by
calling CloseLibrary():

    void CloseLibrary(struct Library *libPtr);

where libPtr is a pointer to the library base returned when the library
was opened with OpenLibrary().

 Library Vector Offsets (LVOs)    Calling a Library Function


17 / Libraries and Devices / Library Vector Offsets (LVOs)

After an application has successfully opened a library, it can start using
the library's functions.  To access a library function, an application
needs the library base address returned by OpenLibrary() and the
function's Library Vector Offset (LVO).  A function's LVO is the offset
from the library's base address to the function's vector in the vector
table, which means an LVO is a negative number (the vectors precedes the
library base in memory).  Application code enters a library function by
doing a jump to subroutine (the 680x0 instruction JSR) to the proper
negative offset (LVO) from the address of the library base.  The library
vector itself is a jump instruction (the 680x0 instruction JMP) to the
actual library function which is somewhere in memory.

                                Low Memory
                                   /|\
                                    |
                    ________________|________________
                   |                                 |
                   |   JMP Function N (LVO=-(N*6))   |
                   |                ·                |
                   |                ·                |
                   |    JMP Function 6 (LVO=-36)     |
                   |    JMP Function 5 (LVO=-30)     |
                   | JMP Function Reserved (LVO=-24) |
                   | JMP Function Expunge (LVO=-18)  |
                   |  JMP Function Close (LVO=-12)   |
                   |   JMP Function Open (LVO=-6)    |
   Library Base____|_________________________________|
                   |                                 |
                   |        Library Structure        |
                   |_________________________________|
                   |                                 |
                   |            Data Area            |
                   |_________________________________|
                                    |
                                    |
                                   \|/
                              High Memory

                 Figure 17-1: An Exec Library Base in RAM

The only legal way for an application to access a library function is
through the vector table.  A function's LVO is always the same on every
system and is not subject to change.  A function's jump vector can, and
does, change.  Assuming that a function's jump vector is static is very
bad, so don't do it.

Each library has four vectors set aside for library housekeeping: OPEN,
CLOSE, EXPUNGE, and RESERVED.  The OPEN vector points to a function that
performs any custom initialization that this library needs, for example,
opening other libraries that this library uses.  The CLOSE function takes
care of any clean up necessary when an application closes a library.  The
EXPUNGE vector points to a function that prepares the library for removal
from the system.  Normally the OS will not remove a library from memory
until the system needs the memory the library occupies.  The other vector,
RESERVED, does not do anything at present and is reserved for future
system use.


17 / Libraries and Devices / Calling a Library Function

To call a function in an Amiga system library, an assembler application
must put the library's base address in register A6 and JSR to the
function's LVO relative to A6.  For example to call the Intuition function
DisplayBeep():

;***********************************************************************
        xref    _LVODisplayBeep
;...
        move.l  A6, -(sp)               ;save the current contents of A6
;---- intuition.library must already be opened
;---- and IntuitionBase must contain its base address
        move.l  IntuitionBase, A6       ;put intuition base pointer in A6
        jsr     _LVODisplayBeep(A6)     ;call DisplayBeep()
        move.l  (SP)+, A6               ;restore A6 to its original value

IntuitionBase contains a pointer to the Intuition library's library base
and _LVODisplayBeep is the LVO for the DisplayBeep() function.  The
external reference (xref) to _LVODisplayBeep is resolved from the linker
library, amiga.lib.  This linker library contains the LVO's for all of the
standard Amiga libraries.  Each LVO label starts with "_LVO" followed by
the name of the library function.

    System Functions Do Not Preserve D0, D1, A0 and A1.
    ---------------------------------------------------
    If you need to preserve D0, D1, A0, or A1 between calls to system
    functions, you will have to save and restore these values yourself.
    Amiga system functions use these registers as scratch registers and
    may write over the values your program left in these registers.  The
    system functions preserve the values of all other registers.  The
    result of a system function, if any, is returned in D0.

      Some Task             LVO Table                  LibFuncY()
      ---------         __________________             ----------
                       |                  |
                       |        ·         |
      main()           |        ·         |
         ·             | JMP to LibFuncZ  |       {
         ·             |- - - - - - - - - |         blah = openblah();
         x=       ____\| JMP to LibFuncY  |____\    dosomething();
      LibFuncY()      /|- - - - - - - - - |    /    closeblah(blah);
         ·             | JMP to LibFuncX  |       }
         ·             |        ·         |
                       |        ·         |
                       |__________________|
                       |                  |
                       |   Library Base   |
                       |__________________|

   A task calls a        which calls the          which JMP's to the
  library function...  functions JMP vector...  actual library function.

                 Figure 17-2: Calling a Library Function

The example above is the actual assembly code generated by the macro named
LINKLIB, which is defined in <exec/libraries.i>.  The following fragment
performs the same function as the fragment above:

    LINKLIB _LVODisplayBeep, IntuitionBase

The amiga.lib linker library also contains small functions called stubs
for each function in the Amiga OS.  These stubs are normally for use with
C code.

Function parameters in C are normally pushed on the stack when a program
calls a function.  This presents a bit of a problem for the C programmer
when calling Amiga OS functions because the Amiga OS functions expect
their parameters to be in specific CPU registers. Stubs solve this problem
by copying the parameters from the stack to the appropriate register.

For example, the Autodoc for the Intuition library function MoveWindow()
shows which registers MoveWindow() expects its parameters to be:

    MoveWindow(window, deltaX, deltaY);
                 A0      D0      D1

The stub for MoveWindow() in amiga.lib has to copy window to register A0,
deltaX to register D0, and deltaY to register D1.

The stub also copies Intuition library base into A6 and does an
address-relative JSR to MoveWindow()'s LVO (relative to A6).  The stub
gets the library base from a global variable in your code called
IntuitionBase.  If you are using the stubs in amiga.lib to call Intuition
library functions, you must declare a global variable called
IntuitionBase.  It must be called IntuitionBase because amiga.lib is
specifically looking for the label IntuitionBase.

    /* This global declaration is here so amiga.lib can find
       the intuition.library base pointer.
    */
    struct Library *IntuitionBase;
            ...

    void main(void)
    {
            ...

            /* initialize IntuitionBase */
            if (IntuitionBase = OpenLibrary("intuition.library", 33L))
            {
                    ...

                    /* When this code gets linked with amiga.lib, the
                       linker extracts the DisplayBeep() stub routine from
                       from amiga.lib and copies it into the executable.
                       The stub copies whatever is in the variable
                       IntuitionBase into A6, and JSRs to
                       _LVODisplayBeep(A6).
                    */
                    DisplayBeep();
                    ...

                    CloseLibrary(IntuitionBase);
            }
            ...
    }

There is a specific label in amiga.lib for the library base of every
library in the Amiga operating system.  The chart below lists the names of
the library base pointer amiga.lib associates with each Amiga OS library.
The labels for library bases are also in the "Function Offsets Reference"
list in the Amiga ROM Kernel Reference Manual: Includes and Autodocs.

                Table 17-1: Amiga.lib Library Base Labels
       _________________________________________________________
      |                                                         |
      |   Library Name                Library Base Pointer Name |
      |---------------------------------------------------------|
      |   asl.library                 AslBase                   |
      |   commodities.library         CxBase                    |
      |   diskfont.library            DiskfontBase              |
      | * dos.library                 DOSBase                   |
      | * exec.library                SysBase                   |
      |   expansion.library           ExpansionBase             |
      |   gadtools.library            GadToolsBase              |
      |   graphics.library            GfxBase                   |
      |   icon.library                IconBase                  |
      |   iffparse.library            IFFParseBase              |
      |   intuition.library           IntuitionBase             |
      |   keymap.library              KeyMapBase                |
      |   layers.library              LayersBase                |
      |   mathffp.library             MathBase                  |
      |   mathieeedoubbas.library     MathIeeeDoubBasBase       |
      |   mathieeedoubtrans.library   MathIeeeDoubTransBase     |
      |   mathieeesingbas.library     MathIeeeSingBasBase       |
      |   mathieeesingtrans.library   MathIeeeSingTransBase     |
      |   mathtrans.library           MathTransBase             |
      |   rexxsys.library             RexxSysBase               |
      |   rexxsupport.library         RexxSupBase               |
      |   translator.library          TranslatorBase            |
      |   utility.library             UtilityBase               |
      |   version .library             (system private)          |
      |   workbench.library           WorkbenchBase             |
      |   Library Name                Library Base Pointer Name |
      |---------------------------------------------------------|
      | * Automatically opened by the standard C startup module |
      |_________________________________________________________|

The chart mentions that SysBase and DOSBase are already set up by the
standard C startup module.  For more information on the startup module,

    You May Not Need amiga.lib.
    ---------------------------
    Many C compilers provide ways of using pragmas or registerized
    parameters, so that a C program does not have to link with an
    amiga.lib stub to access a library function.  See your compiler
    documentation for more details.


Amiga® RKM Libraries: 18 Exec Libraries

Exec maintains lists of libraries and devices.  An Amiga library consists
of a collection of related functions which can be anywhere in system
memory (RAM or ROM).  An Amiga device is very similar to an Amiga library,
except that a device normally controls some sort of I/O hardware, and
generally contains a limited set of standard functions which receive
commands for controlling I/O.  For more information on how to use devices
for I/O, see the "Exec Device I/O" chapter of this book.

    Not for Beginners.
    ------------------
    This chapter concentrates on the internal workings of Exec
    libraries (and devices).  Most application programmers will not to
    know the internals workings of libraries to program the Amiga.  For
    an introduction to libraries and how to use them, see chapter one,
    "Introduction to Amiga System Libraries".

 What is a Library?    Adding a Library


18 Exec Libraries / What is a Library?

A library consists of a group of functions somewhere in memory (ROM or
RAM), a vector table, and a Library structure which can be followed by an
optional private data area for the library.  The library's base pointer
(as returned by OpenLibrary()) points to the library's Library data
structure:

struct Library
{
    struct  Node lib_Node;
    UBYTE   lib_Flags;
    UBYTE   lib_pad;
    UWORD   lib_NegSize;            /* number of bytes before library */
    UWORD   lib_PosSize;            /* number of bytes after library */
    UWORD   lib_Version;
    UWORD   lib_Revision;
    APTR    lib_IdString;
    ULONG   lib_Sum;                /* the checksum itself */
    UWORD   lib_OpenCnt;            /* number of current opens */
};
/* Meaning of the flag bits: */
                               /* A task is currently running a checksum */
#define LIBF_SUMMING (1 << 0)  /* on this library (system maintains this */
                               /* flag)                                  */
#define LIBF_CHANGED (1 << 1)  /* One or more entries have been changed  */
                               /* in the library code vectors used by    */
                               /* SumLibrary (system maintains this flag)*/

#define LIBF_SUMUSED (1 << 2)  /* A checksum fault should cause a system */
                               /* panic (library flag)                   */
#define LIBF_DELEXP (1 << 3)   /* A user has requested expunge but       */
                               /* another user still has the library     */
                               /* open (this is maintained by library)   */

 Using a Library to Reference Data    Relationship of Libraries to Devices
 Minimum Subset of Library Vectors    Changing the Contents of a Library


18 / What is a Library? / Using a Library to Reference Data

Most libraries (such as Intuition, graphics and Exec) have other data that
follows the Library data structure in memory.  Although it is not normally
necessary, a program can use the library base pointer to access the
Library structure and any custom library data.

In general, the system's library base data is read-only, and should be
directly accessed as little as possible, primarily because the format of
the data may change in future revisions of the library.  If the library
provides functions to allow access to library data, use those instead.


18 / What is a Library? / Relationship of Libraries to Devices

A device is a software specification for hardware control based on the
Library structure.  The structures of libraries and devices are so similar
that the routine MakeLibrary() is used to construct both.

Devices require the same initial four code vectors as a library, but must
have two additional code vectors for beginning and terminating special
device I/O commands. The I/O commands that devices are expected to
perform, at minimum, are shown in the "Exec Device I/O" chapter.  An
example device is listed in the Amiga ROM Kernel Reference Manual: Devices.


18 / What is a Library? / Minimum Subset of Library Vectors

The first four code vectors of a library must be the following entries:

OPEN
    is the entry point called by the function OpenLibrary().  In most
    libraries, OPEN increments the library variable lib_OpenCnt. This
    variable is also used by CLOSE and EXPUNGE.

CLOSE
    is the entry point called by the function CloseLibrary(). It
    decrements the library variable lib_OpenCnt and may do a delayed
    EXPUNGE.

EXPUNGE
    prepares the library for removal from the system. This often includes
    deallocating memory resources that were reserved during
    initialization. EXPUNGE not only frees the memory allocated for data
    structures, but also the areas reserved for the library node itself.

RESERVED
    is a fourth function vector reserved for future use. It must always
    return zero.


18 / What is a Library? / Changing the Contents of a Library

The way in which an Amiga library is organized allows a programmer to
change where the system looks for a library routine.  Exec provides a
function to do this: SetFunction().  The SetFunction() routine redirects a
library function call to an application-supplied function. (Although it's
not addressed here, SetFunction() can also be used on Exec devices.)  For
instance, the AmigaDOS command SetPatch uses SetFunction() to replace some
OS routines with improved ones, primarily to fix bugs in ROM libraries.

The format of the SetFunction() routine is as follows:

    SetFunction( struct Library *lib, LONG funcOffset, APTR funcEntry)
                                 A1            A0               D0

The lib argument is a pointer to the library containing the function entry
to be changed.  The funcOffset is the Library Vector Offset (negative) of
the function and funcEntry is the address of the new function you want to
replace it with.  The SetFunction() routine replaces the entry in the
library's vector table at the given Library Vector Offset with a new
address that points to the new routine and returns the old vector address.
The old address can be used in the new routine to call the original
library function.

Normally, programs should not attempt to "improve" library functions.
Because most programmers do not know exactly what system library functions
do internally, OS patches can do more harm than good.  However, a
legitimate use for SetFunction() is in a debugger utility.  Using
SetFunction(), a debugger could reroute system calls to a debugging
routine.  The debugging routine can inspect the arguments to a library
function call before calling the original library function (if everything
is OK).  Such a debugger doesn't do any OS patching, it merely inspects.

    SetFunction() is for Advanced Users Only.
    -----------------------------------------
    It is very difficult to cleanly exit after performing SetFunction()
    because other tasks may be executing your code and also because
    additional SetFunction()'s may have occurred on the same function.
    Also note that certain libraries (for example the V33 version of DOS
    library) and some individual library function vectors are of
    non-standard format and cannot be replaced via SetFunction().

Although useful, performing SetFunction() on a library routines poses
several problems.  If a second task performs SetFunction() on the same
library entry, SetFunction() returns the address of the new routine to the
second task, not the original system vector.  In that case, the first task
can no longer exit cleanly since that would leave the second task with an
invalid pointer to a function which it could be relying on.

You also need to know when it is safe to unload your replacement function.
Removing it while another task is executing it will quickly lead to a
crashed system.  Also, the replacement function will have to be
re-entrant, like all Exec library functions.

    Don't Do This!
    --------------
    For those of you who might be thinking about writing down the ROM
    addresses returned by SetFunction() and using them in some other
    programs: Forget It.  The address returned by SetFunction() is
    only good on the current system at the current time.


18 Exec Libraries / Adding a Library

Exec provides several ways to add your own libraries to the system library
list.  One rarely used way is to call LoadSeg() (a DOS library function)
to load your library and then use the Exec MakeLibrary() and AddLibrary()
functions to initialize your library and add it to the system.

MakeLibrary() allocates space for the code vectors and data area,
initializes the library node, and initializes the data area according to
your specifications, returning to you a library base pointer.  The base
pointer may then be passed to AddLibrary() to add your library to the
system.

Another way to initialize and add a library or device to the system is
through the use of a Resident structure or romtag (see <exec/resident.h>).
A romtag allows you to place your library or device in a directory
(default LIBS: for libraries, DEVS: for devices) and have the OS
automatically load and initialize it when an application tries to open it
with OpenLibrary() or OpenDevice().

Two additional initialization methods exist for a library or device which
is bound to a particular Amiga expansion board.  The library or device
(containing a romtag) may be placed in the SYS:Expansion drawer, along
with an icon containing the Manufacturer and Product number of the board
it requires.  If the startup-sequence BindDrivers command finds that board
in the system, it will load and initialize the matching Expansion drawer
device or library. In addition, since 1.3, the Amiga system software
supports ROM drivers on expansion boards.  See the "Expansion Library"
chapter for additional information on ROM drivers and Expansion drawer
drivers.  The sample device code in the Amiga ROM Kernel Reference Manual:
Devices volume of this manual set may be conditionally assembled as an
Expansion drawer driver.

 Resident (Romtag) Structure


18 / Adding a Library / Resident (Romtag) Structure

A library or device with a romtag should start with MOVEQ #-1,D0 (to
safely return an error if a user tries to execute the file), followed by a
Resident structure:

    STRUCTURE RT,0
       UWORD RT_MATCHWORD   * romtag identifier (==$4AFC)
       APTR  RT_MATCHTAG    * pointer to the above UWORD (RT_MATCHWORD)
       APTR  RT_ENDSKIP     * usually ptr to end of your code
       UBYTE RT_FLAGS       * usually RTF_AUTOINIT
       UBYTE RT_VERSION     * release version number (for example: 37)
       UBYTE RT_TYPE        * type of module (NT_LIBRARY)
       BYTE  RT_PRI         * initialization priority (for example: 0)
       APTR  RT_NAME        * pointer to node name ("my.library")
       APTR  RT_IDSTRING    * pointer to id string ("name ver.rev (date)")
       APTR  RT_INIT        * pointer to init code or AUTOINIT tables
       LABEL RT_SIZE        * size of a Resident structure (romtag)

If you wish to perform MakeLibrary() and AddLibrary() yourself, then your
RT_FLAGS will not include RTF_AUTOINIT, and RT_INIT will be simply be a
pointer to your own initialization code.  To have Exec automatically load
and initialize the library, set the RTF_AUTOINIT flag in the Resident
structure's RT_FLAGS field, and point RT_INIT to a set four longwords
containing the following:

dataSize
    This is the size of your library data area, i.e., the combined size
    of the standard Library node structure plus your own library-specific
    data.

vectors
    This is a pointer to a table of pointers to your library's functions,
    terminated with a -1.  If the first word of the table is -1, then the
    table is interpreted as a table of words specifying the relative
    displacement of each function entry point from the start of the
    table.  Otherwise it is treated as a table of longword address
    pointers to the functions.  vectors must specify a valid table
    address.

structure
    This parameter points to the base of an InitStruct() data region.
    That is, it points to the first location within a table that the
    InitStruct() routine can use to initialize your Library node
    structure, library-specific data, and other memory areas.
    InitStruct() will typically be used to initialize the data segment of
    the library, perhaps forming data tables, task control blocks, I/O
    control blocks, etc. If this entry is a 0, then InitStruct() is not
    called.

initFunction
    This points to a routine that is to be executed after the library (or
    device) node has been allocated and the code and data areas have been
    initialized.  When the routine is called, the base address of the
    newly created library is passed in D0.  If initFunction is zero, no
    initialization routine is called.

Complete source code for an RT_AUTOINIT library may be found in the
appendix C of this book.


Amiga® RKM Libraries: 19 Exec Device I/O

The Amiga system devices are software engines that provide access to the
Amiga hardware.   Through these devices, a programmer can operate a modem,
spin a disk drive motor, time an event, and blast a trumpet sound in
stereo.  Yet, for all that variety, the programmer uses each device in the
same manner.

 What is a Device?     Using A Device            Using An Exec Device
 Accessing a Device    Devices With Functions    Function Reference


19 Exec Device I/O / What is a Device?

An Amiga device is a software module that accepts commands and data and
performs I/O operations based on the commands it receives.  In most cases,
it interacts with either internal or external hardware, (the exceptions
are the clipboard device and ramdrive device which simply use memory).
Generally, an Amiga device runs as a separate task which is capable of
processing your commands while your application attends to other things.

                  Table 19-1: Amiga System Devices

    Amiga Device  Purpose
    ------------  -------
    Audio         Controls the use of the audio hardware.
    Clipboard     Manages the cutting and pasting of common data blocks
    Console       Provides the line-oriented user interface.
    Gameport      Controls the two mouse/joystick ports.
    Input         Processes input from the gameport and keyboard devices.
    Keyboard      Controls the keyboard.
    Narrator      Produces the Amiga synthesized speech.
    Parallel      Controls the parallel port.
    Printer       Converts a standard set of printer control codes to
                  printer specific codes.
    SCSI          Controls the Small Computer Standard Interface hardware.
    Serial        Controls the serial port.
    Timer         Provides timing functions to measure time intervals and
                  send interrupts.
    Trackdisk     Controls the Amiga floppy disk drives.

The philosophy behind the devices is that I/O operations should be
consistent and uniform.  You print a file in the same manner as you play
an audio sample, i.e., you send the device in question a WRITE command and
the address of the buffer holding the data you wish to write.

The result is that the interface presented to the programmer is
essentially device independent and accessible from any computer language.
This greatly expands the power the Amiga brings to the programmer and,
ultimately, to the user.

Devices support two types of commands: Exec standard commands like READ
and WRITE, and device specific commands like the trackdisk device MOTOR
command which controls the floppy drive motor, and the keyboard device
READMATRIX command which returns the state of each key on the keyboard.
You should keep in mind, however, that supporting standard commands does
not mean that all devices execute them in exactly the same manner.

This chapter contains an introduction to the Exec and amiga.lib functions
that are used when accessing Amiga devices.  Consult the Amiga ROM Kernel
Manual: Devices volume for chapters on each of the Amiga devices and the
commands they support.  In addition, the Amiga ROM Kernel Reference
Manual: Includes and Autodocs contains Autodocs summarizing the commands
of each device, and listings of the device include files.  Both are very
useful manuals to have around when you are programming the devices.


19 Exec Device I/O / Accessing a Device

Accessing a device requires obtaining a message port, allocating memory
for a specialized message packet called an I/O request, setting a pointer
to the message port in the I/O request, and finally, establishing the link
to the device itself by opening it. An example of how to do this will be
provided later in this chapter.

 Creating a Message Port    Creating an I/O Request    Opening a Device


19 / Accessing a Device / Creating a Message Port

When a device completes the command in a message, it will return the
message to the message port specifed as the reply port in the message.  A
message port is obtained by calling the CreateMsgPort() or CreatePort()
function.  You must delete the message port when you are finished by
calling the DeleteMsgPort() or DeletePort() function.

If your application needs to be compatible with pre-V36 versions of the
operating system, use the amiga.lib functions CreatePort() and
DeletePort(); if you require V36 or higher, you may use the Exec ROM
functions CreateMsgPort() and DeleteMsgPort().


19 / Accessing a Device / Creating an I/O Request

The I/O request is used to send commands and data from your application to
the device.  The I/O request consists of fields used to hold the command
you wish to execute and any parameters it requires.  You set up the fields
with the appropriate information and send it to the device by using Exec
I/O functions.  Different Amiga devices often require different I/O
request structures.  These structures all start with a simple IORequest or
IoStdReq structure (see <exec/io.h>) which may be followed by various
device-specific fields.  Consult the Autodoc and include file for each
device to determine the type and size I/O request required to access the
device.

I/O request structures are commonly created and deleted with the amiga.lib
functions CreateExtIO() with DeleteExtIO(). These amiga.lib functions are
compatible with Release 2 and previous versions of the operating system.
Applications that already require V37 for other reasons may instead use
the new V37 ROM Exec functions CreateIORequest() and DeleteIORequest().
Any size and type of I/O request may be created with these functions.

Alternately, I/O requests can be created by declaring them as structures
initialized to zero, or by dynamically allocating cleared public memory
for them, but in these cases you will be responsible for the IORequest
structure initializations which are normally handled by the above
functions.  The message port pointer in the I/O request tells the device
where to respond with messages for your application.  You must set a
pointer to the message port in the I/O request if you declare it as a
structure or allocate memory for it using AllocMem().


19 / Accessing a Device / Opening a Device

The device is opened by calling the OpenDevice() function.  In addition to
establishing the link to the device, OpenDevice() also initializes fields
in the I/O request.  OpenDevice() has this format:

    return = OpenDevice(device_name,
                        unit_number,
                  (struct IORequest *)IORequest,
                        flags)

  * device_name is one of the following NULL-terminated strings for
    system devices:

        Audio.device     Parallel.device  Clipboard.device
        Printer.device   Console.device   scsi.device
        Gameport.device  Serial.device    Input.device
        Timer.device     Keyboard.device  Trackdisk.device
                         Narrator.device

  * unit_number is refers to one of the logical units of the device.
    Devices with one unit always use unit 0.  Multiple unit devices like
    the trackdisk device and the timer device use the different units for
    specific purposes.

  * IORequest is the structure discussed above.  Some of the devices have
    their own I/O requests defined in their include files and others use
    standard I/O requests, (IOStdReq).  Refer to the Amiga ROM Kernel
    Reference Manual: Devices for more information.

  * flags are bits set to indicate options for some of the devices. This
    field is set to zero for devices which don't accept options when they
    are opened.  The flags for each device are explained in the Amiga ROM
    Kernel Reference Manual: Devices.

  * return is an indication of whether the OpenDevice() was successful
    with zero indicating success.  Never assume that a device will
    successfully open.  Check the return value and act accordingly.

    Zero Equals Success for OpenDevice().
    -------------------------------------
    Unlike most Amiga system functions, OpenDevice() returns zero for
    success and a device-specific error value for failure.


19 Exec Device I/O / Using a Device

Once a device has been opened, you use it by passing the I/O request to
it.  When the device processes the I/O request, it acts on the information
the I/O request contains and returns a reply message, i.e., the I/O
request, to the message port when it is finished.  The I/O request is
passed to a device using one of three functions, DoIO(), SendIO() and
BeginIO().  They take only one argument: the I/O request you wish to pass
to the device.

  * DoIO() is a synchronous function.  It will not return until the
    device has finished with the I/O request.  DoIO() will wait, if
    necessary, for the request to complete, and will remove (GetMsg())
    any reply message from the message port.

  * SendIO() is an asynchronous function.  It can return immediately, but
    the I/O operation it initiates may take a short or long time. SendIO
    is normally used when your application has other work to do while the
    I/O request is being acted upon, or if your application wishes to
    allow the user to cancel the I/O. Using SendIO() requires that you
    wait on or check for completion of the request, and remove the
    completed request from the message port with GetMsg().

  * BeginIO() is commonly used to control the QuickIO bit when sending an
    I/O request to a device.  When the QuickIO flag (IOF_QUICK) is set in
    the I/O request, a device is allowed to take certain shortcuts in
    performing and completing a request.  If the request can complete
    immediately, the device will not return a reply message and the
    QuickIO flag will remain set.  If the request cannot be completed
    immediately, the QUICK_IO flag will be clear.  DoIO() normally
    requests QuickIO; SendIO() does not.

An I/O request typically has three fields set for every command sent to a
device.  You set the command itself in the io_Command field, a pointer to
the data for the command in the io_Data field, and the length of the data
in the io_Length field.

    SerialIO->IOSer.io_Length   = sizeof(ReadBuffer);
    SerialIO->IOSer.io_Data     = ReadBuffer;
    SerialIO->IOSer.io_Command  = CMD_READ;
    SendIO((struct IORequest *)SerialIO);

Commands consist of two parts (separated by an underscore, all in upper
case): a prefix and the command word.  The prefix indicates whether the
command is an Exec or device specific command.  All Exec standard commands
have "CMD" as the prefix.  They are defined in the include file
<exec/io.h>.

             Table 19-2: Standard Exec Device Commands

            CMD_READ   CMD_START  CMD_UPDATE  CMD_CLEAR
            CMD_WRITE  CMD_STOP   CMD_FLUSH   CMD_RESET

You should not assume that a device supports all standard Exec device
commands.  Always check the documentation before attempting to use one of
them.  Device-specific command prefixes vary with the device.

             Table 19-3: System Device Command Prefixes

        Device     Prefix                       Example
        ------     ------                       -------
        Audio      ADCMD                        ADCMD_ALLOCATE
        Clipboard  CBD                          CBD_POST
        Console    CD                           CD_ASKKEYMAP
        Gameport   GPD                          GPD_SETCTYPE
        Input      IND                          IND_SETMPORT
        Keyboard   KBD                          KBD_READMATRIX
        Narrator   no device specific commands  -
        Parallel   PDCMD                        PDCMD_QUERY
        Printer    PRD                          PRD_PRTCOMMAND
        SCSI       HD                           HD_SCSICMD
        Serial     SDCMD                        SDCMD_BREAK
        Timer      TR                           TR_ADDREQUEST
        Trackdisk  TD and ETD                   TD_MOTOR/ETD_MOTOR

Each device maintains its own I/O request queue.  When a device receives
an I/O request, it either processes the request immediately or puts it in
the queue because one is already being processed. After an I/O request is
completely processed, the device checks its queue and if it finds another
I/O request, begins to process that request.

 Synchronous Vs. Asynchronous Requests    I/O Request Completion


19 / Using A Device / Synchronous Vs. Asynchronous Requests

As stated above, you can send I/O requests to a device synchronously or
asynchronously.  The choice of which to use is largely a function of your
application.

Synchronous requests use the DoIO() function.  DoIO() will not return
control to your application until the I/O request has been satisfied by
the device.  The advantage of this is that you don't have to monitor the
message port for the device reply because DoIO() takes care of all the
message handling.  The disadvantage is that your application will be tied
up while the I/O request is being processed, and should the request not
complete for some reason, DoIO() will not return and your application will
hang.

Asynchronous requests use the SendIO() and BeginIO() functions.  Both
return to your application almost immediately after you call them.  This
allows you to do other operations, including sending more I/O requests to
the device.  Note that any additional I/O requests you send must use
separate I/O request structures. Outstanding I/O requests are not
available for re-use until the device is finished with them.

    Do Not Touch!
    -------------
    When you use SendIO() or BeginIO(), the I/O request you pass to
    the device and any associated data buffers should be considered
    read-only.  Once you send it to the device, you must not modify it
    in any way until you receive the reply message from the device or
    abort the request.

Sending multiple asynchronous I/O requests to a device can be tricky
because devices require them to be unique and initialized.  This means you
can't use an I/O request that's still in the queue, but you need the
fields which were initialized in it when you opened the device.  The
solution is to copy the initialized I/O request to another I/O request(s)
before sending anything to the device.

Regardless of what you do while you are waiting for an asynchronous I/O
request to return, you need to have some mechanism for knowing when the
request has been done.  There are two basic methods for doing this.

The first involves putting your application into a wait state until the
device returns the I/O request to the message port of your application.
You can use the WaitIO(), Wait() or WaitPort() function to wait for the
return of the I/O request. It is important to note that all of the above
functions and also DoIO() may Wait() on the message reply port's
mp_SigBit.  For this reason, the task that created the port must be the
same task the waits for completion of the I/O.  There are three ways to
wait:

      * WaitIO() not only waits for the return of the I/O request, it
        also takes care of all the message handling functions.  This is
        very convenient, but you can pay for this convenience: your
        application will hang if the I/O request does not return.

      * Wait() waits for a signal to be sent to the message port.  It
        will awaken your task when the signal arrives, but you are
        responsible for all of the message handling.

      * WaitPort() waits for the message port to be non-empty.  It
        returns a pointer to the message in the port, but you are
        responsible for all of the message handling.

The second method to detect when the request is complete involves using
the CheckIO() function.  CheckIO() takes an I/O request as its argument
and returns an indication of whether or not it has been completed.  When
CheckIO() returns the completed indication, you will still have to remove
the I/O request from the message port.


19 / Using A Device / I/O Request Completion

A device will set the io_Error field of the I/O request to indicate the
success or failure of an operation.  The indication will be either zero
for success or a non-zero error code for failure. There are two types of
error codes:  Exec I/O and device specific. Exec I/O errors are defined in
the include file <exec/errors.h>; device specific errors are defined in
the include file for each device.  You should always check that the
operation you requested was successful.

The exact method for checking io_Error can depend on whether you use
DoIO() or SendIO().  In both cases, io_Error will be set when the I/O
request is returned, but in the case of DoIO(), the DoIO() function itself
returns the same value as io_Error.  This gives you the option of checking
the function return value:

    SerialIO->IOSer.io_Length   = sizeof(ReadBuffer);
    SerialIO->IOSer.io_Data     = ReadBuffer;
    SerialIO->IOSer.io_Command  = CMD_READ;
    if (DoIO((struct IORequest *)SerialIO)
        printf("Read failed.  Error: %ld\n",SerialIO->IOSer.io_Error);

Or you can check io_Error directly:

    SerialIO->IOSer.io_Length   = sizeof(ReadBuffer);
    SerialIO->IOSer.io_Data     = ReadBuffer;
    SerialIO->IOSer.io_Command  = CMD_READ;
    DoIO((struct IORequest *)SerialIO);
    if (SerialIO->IOSer.io_Error)
        printf("Read failed.  Error: %ld\n",SerialIO->IOSer.io_Error);

Keep in mind that checking io_Error is the only way that I/O requests sent
by SendIO() can be checked.  Testing for a failed I/O request is a minimum
step, what you do beyond that depends on your application.  In some
instances, you may decide to resend the I/O request and in others, you may
decide to stop your application. One thing you'll almost always want to do
is to inform the user that an error has occurred.

    Exiting The Correct Way.
    ------------------------
    If you decide that you must prematurely end your application, you
    should deallocate, release, give back and let go of everything you
    took to run the application.  In other words, you should exit
    gracefully.

 Closing the Device    Ending Device Access


19 / / I/O Request Completion / Closing the Device

You end device access by reversing the steps you did to access it. This
means you close the device, deallocate the I/O request memory and delete
the message port.  In that order!

Closing a device is how you tell Exec that you are finished using a device
and any associated resources.  This can result in housecleaning being
performed by the device.  However, before you close a device, you might
have to do some housecleaning of your own.

A device is closed by calling the CloseDevice() function.  The
CloseDevice() function does not return a value.  It has this format:

    CloseDevice(IORequest);

where IORequest is the I/O request used to open the device.

You should not close a device while there are outstanding I/O requests,
otherwise you can cause major and minor problems.  Let's begin with the
minor problem: memory.  If an I/O request is outstanding at the time you
close a device, you won't be able to reclaim the memory you allocated for
it.

The major problem: the device will try to respond to the I/O request. If
the device tries to respond to an I/O request, and you've deleted the
message port (which is covered below), you will probably crash the system.

One solution would be to wait until all I/O requests you sent to the
device return.  This is not always practical if you've sent a few requests
and the user wants to exit the application immediately.

In that case, the only solution is to abort and remove any outstanding I/O
requests.  You do this with the functions AbortIO() and WaitIO().  They
must be used together for cleaning up.  AbortIO() will abort an I/O
request, but will not prevent a reply message from being sent to the
application requesting the abort.  WaitIO() will wait for an I/O request
to complete and remove it from the message port.  This is why they must be
used together.

    Be Careful With AbortIO()!
    --------------------------
    Do not AbortIO() an I/O request which has not been sent to a
    device.  If you do, you may crash the system.


19 / / I/O Request Completion / Ending Device Access

After the device is closed, you must deallocate the I/O request memory.
The exact method you use depends on how you allocated the memory in the
first place.  For AllocMem() you call FreeMem(), for CreateExtIO() you
call DeleteExtIO(), and for CreateIORequest() you call DeleteIORequest().
If you allocated the I/O request memory at compile time, you naturally
have nothing to free.

Finally, you must delete the message port you created.  You delete the
message port by calling DeleteMsgPort() if you used CreateMsgPort(), or
DeletePort() if you used CreatePort().

Here is the checklist for gracefully exiting:

  * Abort any outstanding I/O requests with AbortIO().

  * Wait for the completion of any outstanding or aborted I/O
    requests with WaitIO().

  * Close the device with CloseDevice().

  * Release the I/O request memory with either DeleteIORequest(),
    DeleteExtIO() or FreeMem() (as appropriate).

  * Delete the message port with DeleteMsgPort() or DeletePort().


19 Exec Device I/O / Devices With Functions

Some devices, in addition to their commands, provide library-style
functions which can be directly called by applications.  These functions
are documented in the device specific FD files and Autodocs of the Amiga
ROM Kernel Reference Manual: Includes and Autodocs, and in the Devices
volume of this manual set.

Devices with functions behave much like Amiga libraries, i.e., you set up
a base address pointer and call the functions as offsets from the pointer.
See the "Exec Libraries" chapter for more information.

The procedure for accessing a device's functions is as follows:

  * Declare the device base address variable in the global data area.
    The correct name for the base address can be found in the device's FD
    file.

  * Create a message port data structure.

  * Create an I/O request data structure.

  * Call OpenDevice(), passing the I/O request.  If OpenDevice() is
    successful (returns 0), the address of the device base may be found
    in the io_Device field of the I/O request structure. Consult the
    include file for the structure you are using to determine the full
    name of the io_Device field.  The base address is only valid while
    the device is open.

  * Set the device base address variable to the pointer returned in the
    io_Device field.

We will use the timer device to illustrate the above method.  The name of
the timer device base address is listed in its FD file as TimerBase.

#include <devices/timer.h>

struct Library *TimerBase;            /* device base address pointer */
struct MsgPort *TimerMP;              /* message port pointer        */
struct timerequest *TimerIO;          /* I/O request pointer         */

if (TimerMP=CreatePort(NULL,NULL))    /* Create the message port.    */
{
    /* Create the I/O request.  */
    if ( TimerIO = (struct timerequest *)
         CreateExtIO(TimerMP,sizeof(struct timerequest)) )
    {
        /* Open the timer device.  */
        if ( !(OpenDevice(TIMERNAME,UNIT_MICROHZ,TimerIO,0)) )
        {
            /* Set up pointer for timer functions.  */
            TimerBase = (struct Library *)TimerIO->tr_node.io_Device;

            /* Use timer device library-style functions such as /*
            /* CmpTime() ...*/

            CloseDevice(TimerIO);     /* Close the timer device. */
        }
        else
            printf("Error: Could not open %s\n",TIMERNAME);
    }
    else
        printf("Error: Could not create I/O request\n");
}
else
    printf("Error: Could not create message port\n");
}


19 Exec Device I/O / Function Reference

The following chart gives a brief description of the Exec functions that
control device I/O.  See the Amiga ROM Kernel Reference Manual: Includes
and Autodocs for details about each call.

                  Table 19-4: Exec Device I/O Functions
  ______________________________________________________________________
 |                                                                      |
 |     Exec Device                                                      |
 |     I/O Function                  Description                        |
 |======================================================================|
 |  CreateIORequest()  Create an IORequest structure (V36).             |
 |  DeleteIORequest()  Delete an IORequest created by CreateIORequest() |
 |                     (V36).                                           |
 |       OpenDevice()  Gain access to an Exec device.                   |
 |      CloseDevice()  Close Exec device opened with OpenDevice().      |
 |             DoIO()  Perform a device I/O command and wait for        |
 |                     completion.                                      |
 |           SendIO()  Initiate an I/O command.  Do not wait for it to  |
 |                     complete.                                        |
 |          CheckIO()  Get the status of an IORequest.                  |
 |           WaitIO()  Wait for completion of an I/O request.           |
 |          AbortIO()  Attempt to abort an I/O request that is in       |
 |                     progress.                                        |
 |______________________________________________________________________|

             Table 19-5: Exec Support Functions in amiga.lib
  ______________________________________________________________________
 |                                                                      |
 |        Function                   Description                        |
 |======================================================================|
 |          BeginIO()  Initiate an asynchronous device I/O request.     |
 |      CreateExtIO()  Create an IORequest data structure.              |
 |      DeleteExtIO()  Free an IORequest structure allocated by         |
 |                     CreateExtIO().                                   |
 |______________________________________________________________________|


Amiga® RKM Libraries: 20 Exec Memory Allocation

Exec manages all of the free memory currently available in the system.
Using linked list structures, Exec keeps track of memory and provides the
functions to allocate and access it.

When an application needs some memory, it can either declare the memory
statically within the program or it can ask Exec for some memory.  When
Exec receives a request for memory, it looks through its list of free
memory regions to find a suitably sized block that matches the size and
attributes requested.

 Memory Functions                     Other Memory Functions
 Allocating Multiple Memory Blocks    Function Reference


20 Exec Memory Allocation / Memory Functions

Normally, an application uses the AllocMem() function to ask for memory:

    APTR AllocMem(ULONG byteSize, ULONG attributes);

The byteSize argument is the amount of memory the application needs and
attributes is a bit field which specifies any special memory
characteristics (described later).  If AllocMem() is successful, it
returns a pointer to a block of memory.  The memory allocation will fail
if the system cannot find a big enough block with the requested
attributes.  If AllocMem() fails, it returns NULL.

Because the system only keeps track of how much free memory is available
and not how much is in use, it has no idea what memory has been allocated
by any task.  This means an application has to explicitly return, or
deallocate, any memory it has allocated so the system can return that
memory to the free memory list.  If an application does not return a block
of memory to the system, the system will not be able to reallocate that
memory to some other task.  That block of memory will be lost until the
Amiga is reset.  If you are using AllocMem() to allocate memory, a call to
FreeMem() will return that memory to the system:

    void FreeMem(APTR mymemblock, ULONG byteSize);

Here mymemblock is a pointer to the memory block the application is
returning to the system and byteSize is the same size that was passed when
the memory was allocated with AllocMem().

Unlike some compiler memory allocation functions, the Amiga system memory
allocation functions return memory blocks that are at least longword
aligned.  This means that the allocated memory will always start on an
address which is at least evenly divisible by four.  This alignment makes
the memory suitable for any system structures or buffers which require
word or longword alignment, and also provides optimal alignment for stacks
and memory copying.

 Memory Attributes
 Allocating System Memory
 Freeing System Memory
 Memory Information Functions
 Using Memory Copy Functions
 Summary of System Controlled Memory Handling Routines


20 / Memory Functions / Memory Attributes

When asking the system for memory, an application can ask for memory with
certain attributes.  The currently supported flags are listed below. Flags
marked "V37" are new memory attributes for Release 2.  Allocations which
specify these new bits may fail on earlier systems.

MEMF_ANY
    This indicates that there is no requirement for either Fast or Chip
    memory.  In this case, while there is Fast memory available, Exec
    will only allocate Fast memory.  Exec will allocate Chip memory if
    there is not enough Fast memory.

MEMF_CHIP
    This indicates the application wants a block of chip memory, meaning
    it wants memory addressable by the Amiga custom chips.  Chip memory
    is required for any data that will be accessed by custom chip DMA.
    This includes screen memory, images that will be blitted, sprite
    data, copper lists, and audio data, and pre-V37 floppy disk buffers.
    If this flag is not specified when allocating memory for these types
    of data, your code will fail on machines with expanded memory.

MEMF_FAST
    This indicates a memory block outside of the range that the special
    purpose chips can access.  "FAST" means that the special-purpose
    chips do not have access to the memory and thus cannot cause
    processor bus contention, therefore processor access will likely be
    faster.  Since the flag specifies memory that the custom chips cannot
    access, this flag is mutually exclusive with the MEMF_CHIP flag.  If
    you specify the MEMF_FAST flag, your allocation will fail on any
    Amiga that has only CHIP memory.  Use MEMF_ANY if you would prefer
    FAST memory.

MEMF_PUBLIC
    This indicates that the memory should be accessible to other tasks.
    Although this flag doesn't do anything right now, using this flag
    will help ensure compatibility with possible future features of the
    OS (like virtual memory and memory protection).

MEMF_CLEAR
    This indicates that the memory should be initialized with zeros.

MEMF_LOCAL (V37)
    This indicates memory which is located on the motherboard which is
    not initialized on reset.

MEMF_24BITDMA (V37)
    This indicates that the memory should be allocated within the 24 bit
    address space, so that the memory can be used in Zorro-II expansion
    device DMA transactions.  This bit is for use by Zorro-II DMA devices
    only.  It is not for general use by applications.

MEMF_REVERSE (V37)
    Indicates that the memory list should be searched backwards for the
    highest address memory chunk which can be used for the memory
    allocation.

If an application does not specify any attributes when allocating memory,
the system tries to satisfy the request with the first memory available on
the system memory lists, which is MEMF_FAST if available, followed by
MEMF_CHIP.

    Make Sure You Have Memory.
    --------------------------
    Always check the result of any memory allocation to be sure the type
    and amount of memory requested is available.  Failure to do so will
    lead to trying to use an non-valid pointer.


20 / Memory Functions / Allocating System Memory

The following examples show how to allocate memory.

    APTR  apointer,anotherptr, yap;

    if (!(apointer = AllocMem(100, MEMF_ANY)))
        {  /* COULDN'T GET MEMORY, EXIT */ }

AllocMem() returns the address of the first byte of a memory block that is
at least 100 bytes in size or NULL if there is not that much free memory.
Because the requirement field is specified as MEMF_ANY (zero), memory will
be allocated from any one of the system-managed memory regions.

    if (!(anotherptr = (APTR)AllocMem(1000, MEMF_CHIP | MEMF_CLEAR)))
        {  /* COULDN'T GET MEMORY, EXIT */ }

The example above allocates only chip-accessible memory, which the system
fills with zeros before it lets the application use the memory.  If the
system free memory list does not contain enough contiguous memory bytes in
an area matching your requirements, AllocMem() returns a zero.  You must
check for this condition.

If you are using Release 2, you can use the AllocVec() function to
allocate memory.  In addition to allocating a block of memory, this
function keeps track of the size of the memory block, so your application
doesn't have to remember it when it deallocates that memory block.  The
AllocVec() function allocates a little more memory to store the size of
the memory allocation request.

    if (!(yap = (APTR)AllocVec(512, MEMF_CLEAR)))
        {  /* COULDN'T GET MEMORY, EXIT */ }


20 / Memory Functions / Freeing System Memory

The following examples free the memory chunks shown in the previous calls
to AllocMem().

    FreeMem(apointer, 100);
    FreeMem(anotherptr, 1000);

A memory block allocated with AllocVec() must be returned to the system
pool with the FreeVec().  This function uses the stored size in the
allocation to free the memory block, so there is no need to specify the
size of the memory block to free.

    FreeVec(yap);

FreeMem() and FreeVec() return no status.  However, if you attempt to free
a memory block in the middle of a chunk that the system believes is
already free, you will cause a system crash. Applications must free the
same size memory blocks that they allocated.  An allocated block may not
be deallocated as smaller pieces.  Due to the internal way the system
rounds up and aligns allocations.  Partial deallocations can corrupt the
system memory list.

    Leave Memory Allocations Out Of Interrupt Code.
    -----------------------------------------------
    Do not allocate or deallocate system memory from within interrupt
    code.  The "Exec Interrupts" chapter explains that an interrupt may
    occur at any time, even during a memory allocation process.  As a
    result, system data structures may not be internally consistent at
    this time.


20 / Memory Functions / Memory Information Functions

The memory information routines AvailMem() and TypeOfMem() can provide the
amount of memory available in the system, and the attributes of a
particular block of memory.

 Memory Requirements    Calling Memory Information Functions


20 / / Memory Information Functions / Memory Requirements

The same attribute flags used in memory allocation routines are valid for
the memory information routines.  There is also an additional flag,
MEMF_LARGEST, which can be used in the AvailMem() routine to find out what
the largest available memory block of a particular type is.  Specifying
the MEMF_TOTAL flag will return the total amount of memory currently
available.


20 / / Memory Info Functions / Calling Memory Information Functions

The following example shows how to find out how much memory of a
particular type is available.

    ULONG size;

    size = AvailMem(MEMF_CHIP|MEMF_LARGEST);

AvailMem() returns the size of the largest chunk of available chip memory.

    AvailMem() May Not Be Totally Accurate.
    ---------------------------------------
    Because of multitasking, the return value from AvailMem() may be
    inaccurate by the time you receive it.

The following example shows how to determine the type of memory of a
specified memory address.

    ULONG memtype;

    memtype = TypeOfMem((APTR)0x090000);
    if ((memtype & MEMF_CHIP) == MEMF_CHIP) {/* ...It's chip memory... */}

TypeOfMem() returns the attributes of the memory at a specific address. If
it is passed an invalid memory address, TypeOfMem() returns NULL. This
routine is normally used to determine if a particular chunk of memory is
in chip memory.


20 / Memory Functions / Using Memory Copy Functions

For memory block copies, the CopyMem() and CopyMemQuick() functions can be
used.

 Copying System Memory


20 / / Using Memory Copy Functions / Copying System Memory

The following samples show how to use the copying routines.

    APTR source, target;

    source = AllocMem(1000, MEMF_CLEAR);
    target = AllocMem(1000, MEMF_CHIP);
    CopyMem(source, target, 1000);

CopyMem() copies the specified number of bytes from the source data region
to the target data region.  The pointers to the regions can be aligned on
arbitrary address boundaries.  CopyMem() will attempt to copy the memory
as efficiently as it can according to the alignment of the memory blocks,
and the amount of data that it has to transfer.  These functions are
optimized for copying large blocks of memory which can result in
unnecessary overhead if used to transfer very small blocks of memory.

    CopyMemQuick(source, target, 1000);

CopyMemQuick() performs an optimized copy of the specified number of bytes
from the source data region to the target data region.  The source and
target pointers must be longword aligned and the size (in bytes) must be
divisible by four.

    Not All Copies Are Supported.
    -----------------------------
    Neither CopyMem() nor CopyMemQuick() supports copying between
    regions that overlap.


20 / / Summary of System Controlled Memory Handling Routines

AllocMem() and FreeMem()
    These are system-wide memory allocation and deallocation routines.
    They use a memory free-list owned and managed by the system.

AvailMem()
    This routine returns the number of free bytes in a specified type of
    memory.

TypeOfMem()
    This routine returns the memory attributes of a specified memory
    address.

CopyMem()/CopyMemQuick()
    CopyMem() is a general purpose memory copy routine. CopyMemQuick() is
    an optimized version of CopyMemQuick(), but has restrictions on the
    size and alignment of the arguments.


20 Exec Memory Allocation / Allocating Multiple Memory Blocks

Exec provides the routines AllocEntry() and FreeEntry() to allocate
multiple memory blocks in a single call. AllocEntry() accepts a data
structure called a MemList, which contains the information about the size
of the memory blocks to be allocated and the requirements, if any, that
you have regarding the allocation. The MemList structure is found in the
include file <exec/memory.h> and is defined as follows:

    struct MemList
    {
        struct Node     ml_Node;
        UWORD           ml_NumEntries;      /* number of MemEntrys */
        struct MemEntry ml_ME[1];           /* where the MemEntrys begin*/
    };

Node
    allows you to link together multiple MemLists.  However, the node is
    ignored by the routines AllocEntry() and FreeEntry().

ml_NumEntries
    tells the system how many MemEntry sets are contained in this
    MemList.  Notice that a MemList is a variable-length structure and
    can contain as many sets of entries as you wish.

The MemEntry structure looks like this:

    struct MemEntry
    {
        union {
            ULONG   meu_Reqs;   /* the AllocMem requirements */
            APTR    meu_Addr;   /* address of your memory */
            } me_Un;
        ULONG   me_Length;      /* the size of this request */
    };

 Sample Code for Allocating Multiple Memory Blocks
 Result of Allocating Multiple Memory Blocks
 Multiple Memory Blocks and Tasks
 Summary of Multiple Memory Blocks Allocation Routines


20 / Allocating Multiple Memory Blocks / Sample Code

Here's an example of showing how to use the AllocEntry() with multiple
blocks of memory.

     allocentry.c

AllocEntry() returns a pointer to a new MemList of the same size as the
MemList that you passed to it.  For example, ROM code can provide a
MemList containing the requirements of a task and create a RAM-resident
copy of the list containing the addresses of the allocated entries.  The
pointer to the MemList is used as the argument for FreeEntry() to free the
memory blocks.

    Assembly Does Not Have MemEntry.
    --------------------------------
    The MemList structure used by assembly programmers is slightly
    different; it has only a label for the start of the MemEntry
    array.  See the Exec AllocEntry() Autodoc for an example of using
    AllocEntry() from assembler.


20 / Allocating Multiple Memory Blocks / Result

The MemList created by AllocEntry() contains MemEntry entries.  MemEntrys
are defined by a union statement, which allows one memory space to be
defined in more than one way.

If AllocEntry() returns a value with bit 31 clear, then all of the
meu_Addr positions in the returned MemList will contain valid memory
addresses meeting the requirements you have provided.  To use this memory
area, you would use code similar to the following:

    #define ALLOCERROR 0x80000000
    struct  MemList *ml;
    APTR    data, moredata;

    if ( ! ((ULONG)ml & ALLOCERROR)))    /* After calling AllocEntry to */
                                         /* allocate ml */
    {
        data     = ml->ml_ME[0].me_Addr;
        moredata = ml->ml_ME[1].me_Addr;
    }
    else  exit(200);                     /* error during AllocEntry */

If AllocEntry() has problems while trying to allocate the memory you have
requested, instead of the address of a new MemList, it will return the
memory requirements value with which it had the problem.  Bit 31 of the
value returned will be set, and no memory will be allocated.  Entries in
the list that were already allocated will be freed.  For example, a failed
allocation of cleared Chip memory (MEMF_CLEAR | MEMF_CHIP) could be
indicated with 0x80010002, where bit 31 indicates failure, bit 16 is the
MEMF_CLEAR flag and bit 1 is the MEMF_CHIP flag.


20 / Allocating Multiple Memory / Multiple Memory Blocks and Tasks

If you want to take advantage of Exec's automatic cleanup, use the MemList
and AllocEntry() facility to do your dynamic memory allocation.

In the Task control block structure, there is a list header named
tc_MemEntry. This is the list header that you initialize to include
MemLists that your task has created by call(s) to AllocEntry().  Here is a
short program segment that handles task memory list header initialization
only.  It assumes that you have already run AllocEntry() as shown in the
simple AllocEntry() example above.

    struct Task *tc;
    struct MemList *ml;

    /* First initialize the task pointer and AllocEntry() the memlist ml */

    if(!tc->tc_MemEntry)
        NewList(tc->tc_MemEntry);  /* Initialize the task's memory    */
                                   /* list header. Do this once only! */
    AddTail(tc->tc_MemEntry, ml);

Assuming that you have only used the AllocEntry() method (or AllocMem()
and built your own custom MemList), the system now knows where to find the
blocks of memory that your task has dynamically allocated.  The RemTask()
function automatically frees all memory found on tc_MemEntry.

    CreateTask() Sets Up A MemList.
    -------------------------------
    The amiga.lib CreateTask() function, and other system task and
    process creation functions use a MemList in tc_MemEntry so that
    the Task structure and stack will be automatically deallocated when
    the Task is removed.


20 / Allocating Multiple Memory / Summary of Allocation Routines

AllocEntry() and FreeEntry()
    These are routines for allocating and freeing multiple memory blocks
    with a single call.

InitStruct()
    This routine initializes memory from data and offset values in a
    table.  Typically only assembly language programs benefit from using
    this routine.  For more details see the Amiga ROM Kernel Reference
    Manual: Include & Autodocs.


20 Exec Memory Allocation / Other Memory Functions

Allocate() and Deallocate() use a memory region header, called MemHeader,
as part of the calling sequence.  You can build your own local header to
manage memory locally. This structure takes the form:

    struct MemHeader {
        struct Node       mh_Node;
        UWORD             mh_Attributes; /* characteristics of region  */
        struct  MemChunk *mh_First;      /* first free region          */
        APTR              mh_Lower;      /* lower memory bound         */
        APTR              mh_Upper;      /* upper memory bound + 1     */
        ULONG             mh_Free;       /* total number of free bytes */
    };

mh_Attributes
    is ignored by Allocate() and Deallocate().

mh_First
    is the pointer to the first MemChunk structure.

mh_Lower
    is the lowest address within the memory block. This must be a
    multiple of eight bytes.

mh_Upper
    is the highest address within the memory block + 1.  The highest
    address will itself be a multiple of eight if the block was allocated
    to you by AllocMem().

mh_Free
    is the total free space.

This structure is included in the include files <exec/memory.h> and
<exec/memory.i>.

The following sample code fragment shows the correct initialization of a
MemHeader structure.  It assumes that you wish to allocate a block of
memory from the global pool and thereafter manage it yourself using
Allocate() and Deallocate().

     allocate.c

    How Memory Is Tagged.
    ---------------------
    Only free memory is "tagged" using a MemChunk linked list. Once
    memory is allocated, the system has no way of determining which task
    now has control of that memory.

If you allocate memory from the system, be sure to deallocate it when your
task exits.  You can accomplish this with matched deallocations, or by
adding a MemList to your task's tc_MemEntry, or you can deallocate the
memory in the finalPC routine (which can be specified if you perform
AddTask() yourself).

 Allocating Memory at an Absolute Address
 Adding Memory to the System Pool


20 / Other Memory Functions / Allocating Memory at an Absolute Address

For special advanced applications, AllocAbs() is provided. Using
AllocAbs(), an application can allocate a memory block starting at a
specified absolute memory address.  If the memory is already allocated or
if there is not enough memory available for the request, AllocAbs()
returns a zero.

Be aware that an absolute memory address which happens to be available on
one Amiga may not be available on a machine with a different configuration
or different operating system revision, or even on the same machine at a
different times.  For example, a piece of memory that is available during
expansion board configuration might not be available at earlier or later
times.  Here is an example call to AllocAbs():

    APTR absoluteptr;

    absoluteptr = (APTR)AllocAbs(10000, 0x2F0000);
    if (!(absoluteptr))
        { /* Couldn't get memory, act accordingly. */  }

    /* After we're done using it, we call FreeMem() to free the memory */
    /* block. */
    FreeMem(absoluteptr, 10000);


20 / Other Memory Functions / Adding Memory to the System Pool

When non-Autoconfig memory needs to be added to the system free pool, the
AddMemList() function can be used.  This function takes the size of the
memoryblock, its type, the priority for the memory list, the base address
and the name of the memory block.  A MemHeader structure will be placed at
the start of the memory block, the remainder of the memory block will be
made available for allocation. For example:

    AddMemList(0x200000, MEMF_FAST, 0, 0xF00000, "FZeroBoard");

will add a two megabyte memory block, starting at $F00000 to the system
free pool as Fast memory.  The memory list entry is identified with
"FZeroBoard".


20 Exec Memory Allocation / Function Reference

The following are brief descriptions of the Exec functions that handle
memory management.  See the Amiga ROM Kernel Reference Manual: Includes
and Autodocs for details on each call.

                    Table 20-1: Exec Memory Functions
  ________________________________________________________________________
 |                                                                        |
 |  Memory Function               Description                             |
 |========================================================================|
 |      AllocMem()  Allocate memory with specified attributes.  If an     |
 |                  application needs to allocate some memory, it will    |
 |                  usually use this function.                            |
 |    AddMemList()  Add memory to the system free pool.                   |
 |      AllocAbs()  Allocate memory at a specified location.              |
 |      Allocate()  Allocate memory from a private memory pool.           |
 |    AllocEntry()  Allocate multiple memory blocks.                      |
 |      AllocVec()  Allocate memory with specified attributes and keep    |
 |                  track of the size (V36).                              |
 |      AvailMem()  Return the amount of free memory, given certain       |
 |                  conditions.                                           |
 |       CopyMem()  Copy memory block, which can be non-aligned and of    |
 |                  arbitrary length.                                     |
 |  CopyMemQuick()  Copy aligned memory block.                            |
 |    Deallocate()  Return memory block allocated, with Allocate() to the |
 |                  private memory pool.                                  |
 |     FreeEntry()  Free multiple memory blocks, allocated with           |
 |                  AllocEntry().                                         |
 |       FreeMem()  Free a memory block of specified size, allocated with |
 |                  AllocMem().                                           |
 |       FreeVec()  Free a memory block allocated with AllocVec().        |
 |    InitStruct()  Initialize memory from a table.                       |
 |     TypeOfMem()  Determine attributes of a specified memory address.   |
 |________________________________________________________________________|


Amiga® RKM Libraries: 21 Exec Tasks

One of the most powerful features of the Amiga operating system is its
ability to run and manage multiple independent program tasks, providing
each task with processor time based on their priority and activity. These
tasks include system device drivers, background utilities, and user
interface environments, as well as normal application programs. This
multitasking capability is provided by the Exec library's management of
task creation, termination, scheduling, event signals, traps, exceptions,
and mutual exclusion.

This chapter deals with Exec on a lower level than most applications
programmers need and assumes you are already familiar with the Exec basics
discussed in the "Introduction to Exec" chapter of this manual.

 Task Structure      Task Exceptions
 Task Creation       Task Traps
 Task Termination    Processor and Cache Control
 Task Exclusion      Function Reference


21 Exec Tasks / Task Structure

Exec maintains task context and state information in a task-control data
structure. Like most Exec structures, Task structures are dynamically
linked onto various task queues through the use of an embedded Exec list
Node structure (see the "Exec Lists and Queues" chapter).  Any task can
find its own task structure by calling FindTask(NULL).  The C-language
form of this structure is defined in the <exec/tasks.h> include file:

    struct Task  {
        struct Node tc_Node;
        UBYTE       tc_Flags;
        UBYTE       tc_State;
        BYTE        tc_IDNestCnt;   /* intr disabled nesting */
        BYTE        tc_TDNestCnt;   /* task disabled nesting */
        ULONG       tc_SigAlloc;    /* sigs allocated */
        ULONG       tc_SigWait;     /* sigs we are waiting for */
        ULONG       tc_SigRecvd;    /* sigs we have received */
        ULONG       tc_SigExcept;   /* sigs we will take excepts for */
        UWORD       tc_TrapAlloc;   /* traps allocated */
        UWORD       tc_TrapAble;    /* traps enabled */
        APTR        tc_ExceptData;  /* points to except data */
        APTR        tc_ExceptCode;  /* points to except code */
        APTR        tc_TrapData;    /* points to trap code */
        APTR        tc_TrapCode;    /* points to trap data */
        APTR        tc_SPReg;       /* stack pointer */
        APTR        tc_SPLower;     /* stack lower bound */
        APTR        tc_SPUpper;     /* stack upper bound + 2*/
        VOID      (*tc_Switch)();   /* task losing CPU */
        VOID      (*tc_Launch)();   /* task getting CPU */
        struct List tc_MemEntry;    /* allocated memory */
        APTR        tc_UserData;    /* per task data */
    };

A similar assembly code structure is available in the <exec/tasks.i>
include file.

Most of these fields are not relevant for simple tasks; they are used by
Exec for state and administrative purposes.  A few fields, however, are
provided for the advanced programs that support higher level environments
(as in the case of processes) or require precise control (as in devices).
The following sections explain these fields in more detail.


21 Exec Tasks / Task Creation

To create a new task you must allocate a task structure, initialize its
various fields, and then link AutoDocs/it into Exec with a call to AddTask(). The
task structure may be allocated by calling the AllocMem() function with
the MEMF_CLEAR and MEMF_PUBLIC allocation attributes.  These attributes
indicate that the data structure is to be pre-initialized to zero and that
the structure is shared.

The Task fields that require initialization depend on how you intend to
use the task.  For the simplest of tasks, only a few fields must be
initialized:

    tc_Node
        The task list node structure.  This includes the task's
        priority, its type, and its name (refer to the chapter
    "Exec Lists and Queues").

    tc_SPLower
        The lower memory bound of the task's stack.

    tc_SPUpper
        The upper memory bound of the task's stack.

    tc_SPReg
        The initial stack pointer.  Because task stacks grow downward in
        memory, this field is usually set to the same value as
        tc_SPUpper.

Zeroing all other unused fields will cause Exec to supply the appropriate
system default values.  Allocating the structure with the MEMF_CLEAR
attribute is an easy way to be sure that this happens.

Once the structure has been initialized, it must be linked to Exec. This
is done with a call to AddTask() in which the following parameters are
specified:

    AddTask(struct Task *task, APTR initialPC, APTR finalPC )

The task argument is a pointer to your initialized Task structure.  Set
initialPC to the entry point of your task code.   This is the address of
the first instruction the new task will execute.

Set finalPC to the address of the finalization code for your task.  This
is a code section that will receive control if the initialPC routine ever
performs a return (RTS). This exists to prevent your task from being
launched into random memory upon an accidental return.  The finalPC
routine should usually perform various program-related clean-up duties and
should then remove the task.  If a zero is supplied for this parameter,
Exec will use its default finalization code (which simply calls the
RemTask() function).

Under Release 2, AddTask() returns the address of the newly added task or
NULL for failure.  Under 1.3 and older versions of the OS, no values are
returned.

 Task Creation With Amiga.lib    Task Stack    Task Priority


21 / Task Creation / Task Creation With Amiga.lib

A simpler method of creating a task is provided by the amiga.lib Exec
support function CreateTask(), which can be accessed if your code is
linked with amiga.lib.

    CreateTask(char *name, LONG priority, APTR initialPC, ULONG stacksize)

A task created with CreateTask() may be removed with the amiga.lib
DeleteTask() function, or it may simply return when it is finished.
CreateTask() adds a MemList to the tc_MemEntry of the task it creates,
describing all memory it has allocated for the task, including the task
stack and the Task structure itself.  This memory will be deallocated by
Exec when the task is either explicitly removed (RemTask() or
DeleteTask()) or when it exits to Exec's default task removal code
(RemTask()).

Note that a bug in the CreateTask() code caused a failed memory allocation
to go unnoticed in V33 and early versions of Release 2 amiga.lib.

If your development language is not linkable with amiga.lib, it may
provide an equivalent built-in function, or you can create your own based
on the "createtask.c" code in the Amiga ROM Kernel Reference Manual:
Includes and Autodocs.

Depending on the priority of a new task and the priorities of other tasks
in the system, the newly added task may begin execution immediately.

    Sharing Library Pointers
    ------------------------
    Although in most cases it is possible for a parent task to pass a
    library base to a child task so the child can use that library, for
    some libraries, this is not possible.  For this reason, the only
    library base sharable between tasks is Exec's library base.

Here is an example of simple task creation.  In this example there is no
coordination or communication between the main process and the simple task
it has created.  A more complex example might use named ports and messages
to coordinate the activities and shutdown of two tasks.  Because our task
is very simple and never calls any system functions which could cause it
to be signalled or awakened, we can safely remove the task at any time.

    Keep This In Mind.
    ------------------
    Because the simple task's code is a function in our program, we must
    stop the subtask before exiting.

     simpletask.c


21 / Task Creation / Task Stack

Every task requires a stack.  All task stacks are user mode stacks (in the
language of the 68000) and are addressed through the A7 CPU register.  All
normal code execution occurs on this task stack.  Special modes of
execution (processor traps and system interrupts for example) execute on a
single supervisor mode stack and do not directly affect task stacks.

Task stacks are normally used to store local variables, subroutine return
addresses, and saved register values.  Additionally, when a task loses the
processor, all of its current registers are preserved on this stack (with
the exception of the stack pointer itself, which must be saved in the task
structure).

The amount of stack used by a task can vary widely.  The theoretical
minimum stack size is 72 bytes, which is the number required to save 17
CPU registers and a single return address.  Of course, a stack of this
size would not give you adequate space to perform any subroutine calls
(because the return address occupies stack space).  On the other hand, a
stack size of 1K would suffice to call most system functions but would not
allow much in the way of local variable storage.  Processes that call DOS
library functions need an additional 1500 bytes of stack.

Because stack-bounds checking is not provided as a service of Exec, it is
important to provide enough space for your task stack.  Stack overflows
are always difficult to debug and may result not only in the erratic
failure of your task but also in the mysterious malfunction of other Amiga
subsystems.  Some compilers provide a stack-checking option.

    You Can't Always Check The Stack.
    ---------------------------------
    Such stack-checking options generally cannot be used if part of your
    code will be running on the system stack (interrupts, 680x0
    exceptions, handlers, servers), or on a different task's stack
    (libraries, devices, created tasks).

When choosing your stack size, do not cut it too close. Remember that any
recursive routines in your code may use varying amounts of stack, and that
future versions of system routines may use additional stack variables.  By
dynamically allocating buffers and arrays, most application programs can
be designed to function comfortably within the default process stack size
of 4000 bytes.


21 / Task Creation / Task Priority

A task's priority indicates its importance relative to other tasks.
Higher-priority tasks receive the processor before lower-priority tasks
do.  Task priority is stored as a signed number ranging from -128 to +127.
Higher priorities are represented by more positive values; zero is
considered the neutral priority.  Normally, system tasks execute somewhere
in the range of +20 to -20, and most application tasks execute at
priority 0.

It is not wise to needlessly raise a task's priority.  Sometimes it may be
necessary to carefully select a priority so that the task can properly
interact with various system tasks.  The SetTaskPri() Exec function is
provided for this purpose.


21 Exec Tasks / Task Termination

Task termination may occur as the result of a number of situations:

  * A program returning from its initialPC routine and dropping into its
    finalPC routine or the system default finalizer.

  * A task trap that is too serious for a recovery action. This includes
    traps like processor bus error, odd address access errors, etc.

  * A trap that is not handled by the task.  For example, the task might
    be terminated if your code happened to encounter a processor TRAP
    instruction and you did not provide a trap handling routine.

  * An explicit call to Exec RemTask() or amiga.lib DeleteTask().

Task termination involves the deallocation of system resources and the
removal of the task structure from Exec.  The most important part of task
termination is the deallocation of system resources.  A task must return
all memory that it allocated for its private use, it must terminate any
outstanding I/O commands, and it must close access to any system libraries
or devices that it has opened.

It is wise to adopt a strategy for task clean-up responsibility.  You
should decide whether resource allocation and deallocation is the duty of
the creator task or the newly created task.  Often it is easier and safer
for the creator to handle the resource allocation and deallocation on
behalf of its offspring.  In such cases, before removing the child task,
you must make sure it is in a safe state such as Wait(0L) and not still
using a resources or waiting for an event or signal that might still occur.

    NOTE:
    -----
    Certain resources, such as signals and created ports, must be
    allocated and deallocated by the same task that will wait on them.
    Also note that if your subtask code is part of your loaded program,
    you must not allow your program to exit before its subtasks have
    cleaned up their allocations, and have been either deleted or placed
    in a safe state such as Wait(0L).


21 Exec Tasks / Task Exclusion

From time to time the advanced system program may find it necessary to
access global system data structures.  Because these structures are shared
by the system and by other tasks that execute asynchronously to your task,
a task must prevent other tasks from using these structures while it is
reading from or writing to them.  This can be accomplished by preventing
the operating system from switching tasks by forbidding or disabling.  A
section of code that requires the use of either of these mechanisms to
lock out access by others is termed a critical section.  Use of these
methods is discouraged.  For arbitrating access to data between your
tasks, semaphores are a superior solution.  (See the "Exec Semaphores"
chapter)

 Forbidding Task Switching    Disabling Tasks    Task Semaphores


21 / Task Exclusion / Forbidding Task Switching

Forbidding is used when a task is accessing shared structures that might
also be accessed at the same time from another task.  It effectively
eliminates the possibility of simultaneous access by imposing
nonpreemptive task scheduling.  This has the net effect of disabling
multitasking for as long as your task remains in its running state. While
forbidden, your task will continue running until it performs a call to
Wait() or exits from the forbidden state.  Interrupts will occur normally,
but no new tasks will be dispatched, regardless of their priorities.

When a task running in the forbidden state calls the Wait() function,
directly or indirectly, it implies a temporary exit from its forbidden
state. Since almost all stdio, device I/O, and file I/O functions must
Wait() for I/O completion, performing such calls will cause your task to
Wait(), temporarily breaking the forbid.  While the task is waiting, the
system will perform normally.  When the task receives one of the signals
it is waiting for, it will again reenter the forbidden state. To become
forbidden, a task calls the Forbid() function.  To escape, the Permit()
function is used.  The use of these functions may be nested with the
expected affects; you will not exit the forbidden mode until you call the
outermost Permit().

As an example, the Exec task list should only be accessed when in a
Forbid() state.  Accessing the list without forbidding could lead to
incorrect results or it could crash the entire system.  To access the task
list also requires the program to disable interrupts which is discussed in
the next section.


21 / Task Exclusion / Disabling Tasks

Disabling is similar to forbidding, but it also prevents interrupts from
occurring during a critical section.  Disabling is required when a task
accesses structures that are shared by interrupt code.  It eliminates the
possibility of an interrupt accessing shared structures by preventing
interrupts from occurring.  Use of disabling is strongly discouraged.

To disable interrupts you can call the Disable() function.  To enable
interrupts again, use the Enable() function.  Although assembler DISABLE
and ENABLE macros are provided, assembler programmers should use the
system functions rather than the macros for upwards compatibility, ease of
debugging, and smaller code size.

Like forbidden sections, disabled sections can be nested.  To restore
normal interrupt processing, an Enable() call must be made for every
Disable().  Also like forbidden sections, any direct or indirect call to
the Wait() function will enable interrupts until the task regains the
processor.

    WARNING:
    --------
    It is important to realize that there is a danger in using disabled
    sections.  Because the software on the Amiga depends heavily on its
    interrupts occurring in nearly real time, you cannot disable for more
    than a very brief instant. Disabling interrupts for more than 250
    microseconds can interfere with the normal operation of vital system
    functions, especially serial I/O.

    WARNING:
    --------
    Masking interrupts by changing the 68000 processor interrupt
    priority levels with the MOVE SR instruction can also be dangerous
    and is very strongly discouraged.  The disable- and enable-related
    functions control interrupts through the 4703 custom chip and not
    through the 68000 priority level.  In addition, the processor
    priority level can be altered only from supervisor mode (which means
    this process is much less efficient).

It is never necessary to both Disable() and Forbid().  Because disabling
prevents interrupts, it also prevents preemptive task scheduling.  When
disable is used within an interrupt, it will have the effect of locking
out all higher level interrupts (lower level interrupts are automatically
disabled by the CPU).  Many Exec lists can only be accessed while
disabled.  Suppose you want to print the names of all system tasks.  You
would need to access both the TaskReady and TaskWait lists from within a
single disabled section.  In addition, you must avoid calling system
functions that would break a disable by an indirect call to Wait()
(printf() for example).  In this example, the names are gathered into a
list while task switching is disabled. Then task switching is enabled and
the names are printed.

     tasklist.c


21 / Task Exclusion / Task Semaphores

Semaphores can be used for the purposes of mutual exclusion.  With this
method of locking, all tasks agree on a locking convention before
accessing shared data structures.  Tasks that do not require access are
not affected and will run normally, so this type of exclusion is
considered preferable to forbidding and disabling.  This form of exclusion
is explained in more detail in the "Exec Semaphores" chapter.


21 Exec Tasks / Task Exceptions

Exec can provide a task with its own task-local "interrupt" called an
exception.  When some exceptional event occurs, an Exec exception occurs
which stops a particular task from executing its normal code and forces it
to execute a special, task-specific exception handling routine.

If you are familiar with the 680x0, you may be used to using the term
"exceptions" in a different way.  The 680x0 has its own form of exception
that has nothing to do with an Exec exception.  These are discussed in
more detail in the "Task Traps" section of this chapter.  Do not confuse
Exec exceptions with 680x0 exceptions.

To set up an exception routine for a task requires setting values in the
task's control structure (the Task structure).  The tc_ExceptCode field
should point to the task's exception handling routine.  If this field is
zero, Exec will ignore all exceptions.  The tc_ExceptData field should
point to any data the exception routine needs.

Exec exceptions work using signals.  When a specific signal or signals
occur, Exec will stop a task and execute its exception routine.  Use the
Exec function SetExcept() to tell Exec which of the task's signals should
trigger the exception.

When an exception occurs, Exec stops executing the tasks normal code and
jumps immediately into the exception routine, no matter what the task was
doing.  The exception routine operates in the same context the task's
normal code; it operates in the CPU's user mode and uses the task's stack.

Before entering the exception routine, Exec pushes the normal task code's
context onto the stack.  This includes the PC, SR, D0-D7, and A0-A6
registers.  Exec then puts certain parameters in the processor registers
for the exception routine to use.  D0 contains a signal mask indicating
which signal bit or bits caused the exception. Exec disables these signals
when the task enters its exception routine.  If more than one signal bit
is set (i.e. if two signals occurred simultaneously), it is up to the
exception routine to decide in what order to process the two different
signals.  A1 points to the related exception data (from tc_ExceptData),
and A6 contains the Exec library base. You can think of an exception as a
subtask outside of your normal task. Because task exception code executes
in user mode, however, the task stack must be large enough to supply the
extra space consumed during an exception.

While processing a given exception, Exec prevents that exception from
occurring recursively.  At exit from your exception-processing code, you
should make sure D0 contains the signal mask the exception routine
received in D0 because Exec looks here to see which signals it should
reactivate.  When the task executes the RTS instruction at the end of the
exception routine, the system restores the previous contents of all of the
task registers and resumes the task at the point where it was interrupted
by the exception signal.

    Exceptions Are Tricky.
    ----------------------
    Exceptions are difficult to use safely.  An exception can interrupt
    a task that is executing a critical section of code within a system
    function, or one that has locked a system resource such as the disk
    or blitter (note that even simple text output uses the blitter.)
    This possibility makes it dangerous to use most system functions
    within an exception unless you are sure that your interrupted task
    was performing only local, non-critical operations.


21 Exec Tasks / Task Traps

Task traps are synchronous exceptions to the normal flow of program
control.  They are always generated as a direct result of an operation
performed by your program's code.  Whether they are accidental or
purposely generated, they will result in your program being forced into a
special condition in which it must immediately handle the trap.  Address
error, privilege violation, zero divide, and trap instructions all result
in task traps.  They may be generated directly by the 68000 processor
(Motorola calls them "exceptions") or simulated by software.

A task that incurs a trap has no choice but to respond immediately. The
task must have a module of code to handle the trap.  Your task may be
aborted if a trap occurs and no means of handling it has been provided.
Default trap handling code (tc_TrapCode) is provided by the OS.  You may
instead choose to do your own processing of traps.  The tc_TrapCode field
is the address of the handler that you have designed to process the trap.
The tc_TrapData field is the address of the data area for use by the trap
handler.

The system's default trap handling code generally displays a Software
Error Requester or Alert containing an exception number and the program
counter or task address.  Processor exceptions generally have numbers in
the range hex 00 to 2F.  The 68000 processor exceptions of particular
interest are as follows.

            Table 21-1: Traps (68000 Exception Vector Numbers)

    2      Bus error            access of nonexistent memory
    3      Address error        long/word access of odd address (68000)
    4      Illegal instruction  illegal opcode (other than Axxx or Fxxx)
    5      Zero divide          processor division by zero
    6      CHK instruction      register bounds error trap by CHK
    7      TRAPV instruction    overflow error trap by TRAPV
    8      Privilege violation  user execution of supervisor opcode
    9      Trace                status register TRACE bit trap
    10     Line 1010 emulator   execution of opcode beginning with $A
    11     Line 1111 emulator   execution of opcode beginning with $F
    32-47  Trap instructions    TRAP N instruction where N = 0 to 15

A system alert for a processor exception may set the high bit of the
longword exception number to indicate an unrecoverable error (for example
$80000005 for an unrecoverable processor exception #5).  System alerts
with more complex numbers are generally Amiga-specific software failures.
These are built from the definitions in the <exec/alerts.h> include file.

The actual stack frames generated for these traps are processor-dependent.
The 68010, 68020, and 68030 processors will generate a different type of
stack frame than the 68000.  If you plan on having your program handle its
own traps, you should not make assumptions about the format of the
supervisor stack frame.  Check the flags in the AttnFlags field of the
ExecBase structure for the type of processor in use and process the stack
frame accordingly.

 Trap Handlers    Trap Instructions


21 / Task Traps / Trap Handlers

For compatibility with the 68000, Exec performs trap handling in
supervisor mode.  This means that all task switching is disabled during
trap handling. At entry to the task's trap handler, the system stack
contains a processor-dependent trap frame as defined in the 68000/10/20/30
manuals.  A longword exception number is added to this frame.  That is,
when a handler gains control, the top of stack contains the exception
number and the trap frame immediately follows.

To return from trap processing, remove the exception number from the stack
(note that this is the supervisor stack, not the user stack) and then
perform a return from exception (RTE).

Because trap processing takes place in supervisor mode, with task
dispatching disabled, it is strongly urged that you keep trap processing
as short as possible or switch back to user mode from within your trap
handler.  If a trap handler already exists when you add your own trap
handler, it is smart to propagate any traps that you do not handle down to
the previous handler.  This can be done by saving the previous address
from tc_TrapCode and having your handler pass control to that address if
the trap which occurred is not one you wish to handle.

The following example installs a simple trap handler which intercepts
processor divide-by-zero traps, and passes on all other traps to the
previous default trap code.  The example has two code modules which are
linked together.  The trap handler code is in assembler.  The C module
installs the handler, demonstrates its effectiveness, then restores the
previous tc_TrapCode.

     trap_c.c example


21 / Task Traps / Trap Instructions

The TRAP instructions in the 68000 generate traps 32-47.  Because many
independent pieces of system code may desire to use these traps, the
AllocTrap() and FreeTrap() functions are provided.  These work in a
fashion similar to that used by AllocSignal() and FreeSignal(), mentioned
in the "Exec Signals" chapter.

Allocating a trap is simply a bookkeeping job within a task.  It does not
affect how the system calls the trap handler; it helps coordinate who owns
what traps.  Exec does nothing to determine whether or not a task is
prepared to handle a particular trap.  It simply calls your code. It is up
to your program to handle the trap.

To allocate any trap, you can use the following code:

    if (-1 == (trap = AllocTrap(-1)))
        printf("all trap instructions are in use\n");

Or you can select a specific trap using this code:

    if (-1 == (trap = AllocTrap(3)))
        printf("trap #3 is in use\n");

To free a trap, you use the FreeTrap() function passing it the trap number
to be freed.


21 Exec Tasks / Processor and Cache Control

Exec provides a number of to control the processor mode and, if available,
the caches.  All these functions work independently of the specific M68000
family processor type.  This enables you to write code which correctly
controls the state of both the MC68000 and the MC68040.  Along with
processor mode and cache control, functions are provided to obtain
information about the condition code register (CCR) and status register
(SR).  No functions are provided to control a paged memory management unit
(PMMU) or floating point unit (FPU).

          Table 21-2: Processor and Cache Control Functions
   __________________________________________________________________
  |                                                                  |
  |     Function              Description                            |
  |==================================================================|
  |         GetCC()  Get processor condition codes.                  |
  |         SetSR()  Get/set processor status register.              |
  |    SuperState()  Set supervisor mode with user stack.            |
  |    Supervisor()  Execute a short supervisor mode function.       |
  |     UserState()  Return to user mode with user stack.            |
  |------------------------------------------------------------------|
  |   CacheClearE()  Flush CPU instruction and/or data caches (V37). |
  |   CacheClearU()  Flush CPU instruction and data caches (V37).    |
  |  CacheControl()  Global cache control (V37).                     |
  |  CachePostDMA()  Perform actions prior to hardware DMA (V37).    |
  |   CachePreDMA()  Perform actions after hardware DMA (V37).       |
  |__________________________________________________________________|

 Supervisor Mode    Condition Code Register    DMA Cache Functions
 Status Register    Cache Functions            The 68040 and CPU Caches


21 / Processor and Cache Control / Supervisor Mode

While in supervisor mode, you have complete access to all data and
registers, including those used for task scheduling and exceptions, and
can execute privileged instructions.  In application programs, normally
only task trap code is directly executed in supervisor mode, to be
compatible with the MC68000.  For normal applications, it should never be
necessary to switch to supervisor mode itself, only indirectly through
Exec function calls.  Remember that task switching is disabled while in
supervisor mode.  If it is absolutely needed to execute code in supervisor
mode, keep it as brief as possible.

Supervisor mode can only be entered when a 680x0 exception occurs (an
interrupt or trap).  The Supervisor() function allows you to trap an
exception to a specified assembly function.  In this function your have
full access to all registers.  No registers are saved when your function
is invoked.  You are responsible for restoring the system to a sane state
when you are done. You must return to user mode with an RTE instruction.
You must not return to user mode by executing a privileged instruction
which clears the supervisor bit in the status register.  Refer to a manual
on the M68000 family of CPUs for information about supervisor mode and
available privileged instructions per processor type.

The MC68000 has two stacks, the user stack (USP) and supervisor stack
(SSP). As of the MC68020 there are two supervisor stacks, the interrupt
stack pointer (ISP) and the master stack pointer (MSP). The SuperState()
function allows you to enter supervisor mode with the USP used as SSP. The
function returns the SSP, which will be the MSP, if an MC68020 or greater
is used. Returning to user mode is done with the UserState() function.
This function takes the SSP as argument, which must be saved when
SuperState() is called.  Because of possible problems with stack size,
Supervisor() is to be preferred over SuperState().


21 / Processor and Cache Control / Status Register

The processor status register bits can be set or read with the SetSR()
function.  This function operates in supervisor mode, thus both the upper
and lower byte of the SR can be read or set.  Be very sure you know what
you are doing when you use this function to set bits in the SR and above
all never try to use this function to enter supervisor mode. Refer to the
M68000 Programmers Reference Manual by Motorola Inc. for information about
the definition of individual SR bits per processor type.


21 / Processor and Cache Control / Condition Code Register

On the MC68000 a copy of the processor condition codes can be obtained
with the MOVE SR,<ea> instruction.  On MC68010 processors and up however,
the instruction MOVE CCR,<ea> must be used.  Using the specific MC68000
instruction on later processors will cause a 680x0 exception since it is a
privileged instruction on those processors.  The GetCC() function provides
a processor independent way of obtaining a copy of the condition codes.
For all processors there are 5 bits which can indicate the result of an
integer or a system control instruction:

    X - extend    N - negative    Z - zero    V - overflow    C - carry

The X bit is used for multiprecision calculations. If used, it is copy of
the carry bit.  The other bits state the result of a processor operation.


21 / Processor and Cache Control / Cache Functions

As of the MC68020 all processors have an instruction cache, 256 bytes on
the MC68020 and MC68030 and 4 KBytes on a MC68040.  The MC68030 and
MC68040 have data caches as well, 256 bytes and 4 KBytes respectively. All
the processors load instructions ahead of the program counter (PC), albeit
it that the MC68000 and MC68010 only prefetch one and two words
respectively. This means the CPU loads instructions ahead of the current
program counter.  For this reason self-modifying code is strongly
discouraged.  If your code modifies or decrypts itself just ahead of the
program counter, the pre-fetched instructions may not match the modified
instructions.  If self-modifying code must be used, flushing the cache is
the safest way to prevent this.


21 / Processor and Cache Control / DMA Cache Functions

The CachePreDMA() and CachePostDMA() functions allow you to flush the data
cache before and after Direct Memory Access. Typically only DMA device
drivers benefit from this. These functions take the processor type,
possible MMU and cache mode into account. When no cache is available they
end up doing nothing.  These functions can be replaced with ones suitable
for different cache hardware.  Refer to the ROM Kernel Reference Manual:
Includes and Autodocs for implementation specifics.

Since DMA device drivers read and write directly to memory, they are
effected by the CopyBack feature of the MC68040 (explained below).  Using
DMA with CopyBack mode requires a cache flush.  If a DMA device needs to
read RAM via DMA, it must make sure that the data in the caches has been
written to memory first, by calling CachePreDMA().  In case of a write to
memory, the DMA device should first clear the caches with CachePreDMA(),
write the data and flush the caches again with CachePostDMA().


21 / Processor and Cache Control / The 68040 and CPU Caches

The 68040 is a much more powerful CPU than its predecessors.  It has 4K of
cache memory for instructions and another 4K cache for data.  The reason
for these two separate caches is so that the CPU core can access data and
CPU instructions at the same time.

Although the 68040 provides greater performance it also brings with it
greater compatibility problems.  Just the fact that the caches are so much
larger than Motorola's 68030 CPU can cause problems.  However, this is not
its biggest obstacle.

The 68040 data cache has a mode that can make the system run much faster
in most cases.  It is called CopyBack mode.  When a program writes data to
memory in this mode, the data goes into the cache but not into the
physical RAM.  That means that if a program or a piece of hardware were to
read that RAM without going through the data cache on the 68040, it will
read old data. CopyBack mode effects two areas of the Amiga: DMA devices
and the CPU's instruction reading.

CopyBack mode effects DMA devices because they read and write data
directly to memory.  Using DMA with CopyBack mode requires a cache flush.
If a DMA device needs to read RAM via DMA, it must first make sure that
data in the caches has been written to memory.  It can do this by calling
the Exec function CachePreDMA(). If a DMA device is about to write to
memory, it should call CachePreDMA() before the write, do the DMA write,
and then call CachePostDMA(),  which makes sure that the CPU uses the data
just written to memory.

An added advantage of using the CachePreDMA() and CachePostDMA() functions
is that they give the OS the chance to tell the DMA device that the
physical addresses and memory sizes are not the same.  This will make it
possible in the future to add features such as virtual memory.  See the
Autodocs for more information on these calls.

The other major compatibility problem with the 68040's CopyBack mode is
with fetching CPU instructions.  CPU instructions have to be loaded into
memory so the CPU can copy them into its instruction cache.  Normally,
instructions that will be executed are written to memory by the CPU (i.e.,
loading a program from disk).  In CopyBack mode, anything the CPU writes
to memory, including CPU instructions, doesn't actually go into memory, it
goes into the data cache.  If instructions are not flushed out of the data
cache to RAM, the 68040 will not be able to find them when it tries to
copy them into the instruction cache for execution.  It will instead find
and attempt to execute whatever garbage data happened to be left at that
location in RAM.

To remedy this, any program that writes instructions to memory must flush
the data cache after writing.  The V37 Exec function CacheClearU() takes
care of this.  Release 2 of the Amiga OS correctly flushes the caches as
needed after it does the LoadSeg() of a program (LoadSeg() loads Amiga
executable programs into memory from disk).  Applications need to do the
same if they write code to memory.  It can do that by calling
CacheClearU() before the call to CreateProc().  In C that would be:

    extern struct ExecBase *SysBase;
    . . .

    /* If we are in 2.0, call CacheClearU() before CreateProc() */
    if (SysBase->LibNode.lib_Version >= 37) CacheClearU();

    /* Now do the CreateProc() call... */
    proc=CreateProc(... /* whatever your call is like */ ...);
    . . .

For those of you programming in assembly language:

    ***********************************************************************
    * Check to see if we are running in V37 ROM or better.  If so, we want
    * to call CacheClearU() to make sure we are safe on future hardware
    * such as the 68040.  This section of code assumes that a6 points at
    * ExecBase.  a0/a1/d0/d1 are trashed in CacheClearU()
    *
            cmpi.w  #37,LIB_VERSION(a6)    ; Check if exec is >= V37
            bcs.s   TooOld                 ; If less than V37, too old...
            jsr     _LVOCacheClearU(a6)    ; Clear the cache...
    TooOld:                                ; Exit gracefully.
    ***********************************************************************

Note that CreateProc() is not the only routine where CopyBack mode could
be a problem.  Any program code copied into memory for execution that is
not done via LoadSeg() will need to call CacheClearU().  Many input device
handlers have been known to allocate and copy the handler code into memory
and then exit back to the system.  These programs also need to have this
call in them.  The above code will work under older versions of the OS,
and will do the correct operations in Release 2 (and beyond).


21 Exec Tasks / Function Reference

The following chart gives a brief description of the Exec functions that
control tasks.  See the Amiga ROM Kernel Reference Manual: Includes and
Autodocs for details about each call.

     Table 21-3: Exec Task, Processor and Cache Control Functions
  ___________________________________________________________________
 |                                                                   |
 |      Exec Task                                                    |
 |      Function          Description                                |
 |===================================================================|
 |       AddTask()  Add a task to the system.                        |
 |     AllocTrap()  Allocate a processor trap vector.                |
 |       Disable()  Disable interrupt processing.                    |
 |        Enable()  Enable interrupt processing.                     |
 |      FindTask()  Find a specific task.                            |
 |        Forbid()  Forbid task rescheduling.                        |
 |      FreeTrap()  Release a process trap.                          |
 |        Permit()  Permit task rescheduling.                        |
 |    SetTaskPri()  Set the priority of a task.                      |
 |       RemTask()  Remove a task from the system.                   |
 |-------------------------------------------------------------------|
 |   CacheClearE()  Flush CPU instruction and/or data caches (V37).  |
 |   CacheClearU()  Flush CPU instruction and data caches (V37).     |
 |  CacheControl()  Global cache control (V37).                      |
 |  CachePostDMA()  Perform actions prior to hardware DMA (V37).     |
 |   CachePreDMA()  Perform actions after hardware DMA (V37).        |
 |         GetCC()  Get processor condition codes.                   |
 |         SetSR()  Get/set processor status register.               |
 |    SuperState()  Set supervisor mode with user stack.             |
 |    Supervisor()  Execute a short supervisor mode function.        |
 |     UserState()  Return to user mode with user stack.             |
 |-------------------------------------------------------------------|
 |    CreateTask()  Amiga.lib function to setup and add a new task.  |
 |    DeleteTask()  Amiga.lib function to delete a task created with |
 |                  CreateTask().                                    |
 |___________________________________________________________________|


Amiga® RKM Libraries: 22 Exec Signals

Tasks often need to coordinate with other concurrent system activities
(like other tasks and interrupts).  This coordination is handled by Exec
through the synchronized exchange of specific event indicators called
signals.

This is the primary mechanism responsible for all intertask communication
and synchronization on the Amiga.  This signal mechanism operates at a low
level and is designed for high performance.  Signals are used extensively
by the Exec message system as a way to indicate the arrival of an
inter-task message.  The message system is described in more detail in the
"Exec Messages and Ports" chapter.

    Not for Beginners.
    ------------------
    This chapter concentrates on details about signals that most
    applications do not need to understand for general Amiga programming.
    For a general overview of signals, see the "Introduction to Exec"
    chapter of this manual.

 The Signal System    Function Reference


22 Exec Signals / The Signal System

The signal system is designed to support independent simultaneous events,
so several signals can occur at the same time.  Each task has 32
independent signals, 16 of which are pre-allocated for use by the
operating system.  The signals in use by a particular task are represented
as bits in a 32-bit field in its Task structure (<exec/tasks.h>).  Two
other 32-bit fields in the Task structure indicate which signals the task
is waiting for, and which signals have been received.

Signals are task relative.  A task can only allocate its own signals, and
may only wait on its own signals.  In addition, a task may assign its own
significance to a particular signal.  Signals are not broadcast to all
tasks; they are directed only to individual tasks. A signal has meaning to
the task that defined it and to those tasks that have been informed of its
meaning.

For example, signal bit 12 may indicate a timeout event to one task, but
to another task it may indicate a message arrival event. You can never
wait on a signal that you did not directly or indirectly allocate
yourself, and any other task that wishes to signal you must use a signal
that you allocated.

 Signal Allocation    Waiting for a Signal    Generating a Signal


22 / The Signal System / Signal Allocation

As mentioned above, a task assigns its own meaning to a particular signal.
Because certain system libraries may occasionally require the use of a
signal, there is a convention for signal allocation.  It is unwise ever to
make assumptions about which signals are actually in use.

Before a signal can be used, it must be allocated with the AllocSignal()
function.  When a signal is no longer needed, it should be freed for reuse
with FreeSignal().

    BYTE AllocSignal( LONG signalNum );
    VOID FreeSignal( LONG signalNum );

AllocSignal() marks a signal as being in use and prevents the accidental
use of the same signal for more than one event.  You may ask for either a
specific signal number, or more commonly, you would pass -1 to request the
next available signal.  The state of the newly allocated signal is cleared
(ready for use).  Generally it is best to let the system assign you the
next free signal.  Of the 32 available signals, the lower 16 are reserved
for system use.  This leaves the upper 16 signals free for application
programs to allocate.  Other subsystems that you may call depend on
AllocSignal().

The following C example asks for the next free signal to be allocated for
its use:

    if (-1 == (signal = AllocSignal(-1)))
        printf("no signal bits available\n");
    else
        {
        printf("allocated signal number %ld\n", signal);
        /* Other code could go here */
        FreeSignal(signal)
        }

The value returned by AllocSignal() is a signal bit number. This value
cannot be used directly in calls to signal-related functions without first
being converted to a mask:

    mask = 1L << signal;

It is important to realize that signal bit allocation is relevant only to
the running task.  You cannot allocate a signal from another task.  Note
that functions which create a signal MsgPort will allocate a signal from
the task that calls the function.  Such functions include OpenWindow(),
CreatePort(), and CreateMsgPort().  For this reason, only the creating
task may Wait() (directly or indirectly) on the MsgPort's signal.
Functions which call Wait() include DoIO(), WaitIO() and WaitPort().


22 / The Signal System / Waiting for a Signal

Signals are most often used to wake up a task upon the occurrence of some
external event.  Applications call the Exec Wait() function, directly or
indirectly, in order to enter a wait state until some external event
triggers a signal which awakens the task.

Though signals are usually not used to interrupt an executing task, they
can be used this way.  Task exceptions, described in the "Exec Tasks"
chapter, allow signals to act as a task-local interrupt.

The Wait() function specifies the set of signals that will wake up the
task and then puts the task to sleep (into the waiting state).

    ULONG Wait( ULONG signalSet );

Any one signal or any combination of signals from this set are sufficient
to awaken the task.  Wait() returns a mask indicating which signals
satisfied the Wait() call.  Note that when signals are used in conjunction
with a message port, a set signal bit does not necessarily mean that there
is a message at the message port.  See the "Exec Messages and Ports"
chapter for details about proper handling of messages.

Because tasks (and interrupts) normally execute asynchronously, it is
often possible to receive a particular signal before a task actually
Wait()s for it.  In such cases the Wait() will be immediately satisfied,
and the task will not be put to sleep.

The Wait() function implicitly clears those signal bits that satisfied the
wait condition.  This effectively resets those signals for reuse.
However, keep in mind that a task might get more signals while it is still
processing the previous signal.  If the same signal is received multiple
times and the signal bit is not cleared between them, some signals will go
unnoticed.

Be aware that using Wait() will break a Forbid() or Disable() state.
Wait() cannot be used in supervisor mode or within interrupts.

A task may Wait() for a combination of signal bits and will wake up when
any of the signals occur.  Wait() returns a signal mask specifying which
signal or signals were received.  Usually the program must check the
returned mask for each signal it was waiting on and take the appropriate
action for each that occurred.  The order in which these bits are checked
is often important.

Here is a hypothetical example of a process that is using the console and
timer devices, and is waiting for a message from either device and a
possible break character issued by the user:

    consoleSignal = 1L << ConsolePort->mp_SigBit;
    timerSignal   = 1L << TimerPort->mp_SigBit;
    userSignal    = SIGBREAKF_CTRL_C;         /* Defined in <dos/dos.h> */

    signals = Wait(consoleSignal | timerSignal | userSignal);

    if (signals & consoleSignal)
        printf("new character\n");

    if (signals & timeOutSignal)
        printf("timeout\n");

    if (signals & userSignal)
        printf("User Ctrl-C Abort\n");

This code will put the task to sleep waiting for a new character, or the
expiration of a time period, or a Ctrl-C break character issued by the
user.  Notice that this code checks for an incoming character signal
before checking for a timeout.  Although a program can check for the
occurrence of a particular event by checking whether its signal has
occurred, this may lead to busy wait polling.  Such polling is wasteful of
the processor and is usually harmful to the proper function of the Amiga
system.  However, if a program needs to do constant processing and also
check signals (a compiler for example) SetSignal(0,0) can be used to get a
copy of your task's current signals.

    ULONG SetSignal( ULONG newSignals, ULONG signalSet );

SetSignal() can also be used to set or clear the state of the signals.
Implementing this can be dangerous and should generally not be done. The
following fragment illustrates a possible use of SetSignal().

    signals = SetSignal(0,0);           /* Get current state of signals */

    if (signals & SIGBREAKF_CTRL_C)     /* Check for Ctrl-C.           */
        {
        printf("Break\n");              /* Ctrl-C signal has been set. */
        SetSignal(0, SIGBREAKF_CTRL_C)  /* Clear Ctrl-C signal.        */
        }


22 / The Signal System / Generating a Signal

Signals may be generated from both tasks and system interrupts with the
Signal() function.

    VOID Signal( struct Task *task, ULONG signalSet );

For example Signal(tc,mask) would signal the task with the specified mask
signals.  More than one signal can be specified in the mask.  The
following example code illustrates Wait() and Signal().

     signals.c


22 Exec Signals / Function Reference

The following chart gives a brief description of the Exec functions that
control task signalling.  See the Amiga ROM Kernel Reference Manual:
Includes and Autodocs for details about each call.

                    Table 22-1: Exec Signal Functions
  _______________________________________________________________________
 |                                                                       |
 |   Exec Signal                                                         |
 |    Function                         Description                       |
 |=======================================================================|
 |  AllocSignal()  Allocate a signal bit.                                |
 |   FreeSignal()  Free a signal bit allocated with AllocSignal().       |
 |    SetSignal()  Query or set the state of the signals for the current |
 |                 task.                                                 |
 |       Signal()  Signal a task by setting signal bits in its Task      |
 |                 structure.                                            |
 |         Wait()  Wait for one or more signals from other tasks or      |
 |                 interrupts.                                           |
 |_______________________________________________________________________|


Amiga® RKM Libraries: 23 Exec Lists and Queues

The Amiga system software operates in a dynamic environment of data
structures.  An early design goal of Exec was to keep the system flexible
and open-ended by eliminating artificial boundaries on the number of
system structures used.  Rather than using static system tables, Exec uses
dynamically created structures that are added and removed as needed.
These structures can be put in an unordered list, or in an ordered list
known as a queue.  A list can be empty, but never full.  This concept is
central to the design of Exec.  Understanding lists and queues is
important to understanding not only Exec itself, but also the mechanism
behind the Amiga's message and port based interprocess communication.

Exec uses lists to maintain its internal database of system structures.
Tasks, interrupts, libraries, devices, messages, I/O requests, and all
other Exec data structures are supported and serviced through the
consistent application of Exec's list mechanism.  Lists have a common data
structure, and a common set of functions is used for manipulating them.
Because all of these structures are treated in a similar manner, only a
small number of list handling functions need be supported by Exec.

 List Structure    List Functions    Function Reference


23 Exec Lists and Queues / List Structure

A list is composed of a header and a doubly-linked chain of elements
called nodes.  The header contains memory pointers to the first and last
nodes of the linked chain.  The address of the header is used as the
handle to the entire list.  To manipulate a list, you must provide the
address of its header.
                                    _______________
                                 _\|               |
                                / /|   First Node  |
                               /  /|_______________|
                              /  /       |  /|\
            _______________  /  /        |   |
           |               |/  /    ____\|/__|_____
           |   Head Node   |/_/    |               |
           |_______________|\      |  Second Node  |
           |               |/_     |_______________|
           |   Tail Node   |\ \          |  /|\
           |_______________|\  \         |   |
                             \  \   ____\|/__|_____
                              \  \ |               |
                               \  \|   Third Node  |
                                \_\|_______________|
                                  /

             Figure 23-1: Simplified Overview of an Exec List

Nodes may be scattered anywhere in memory.  Each node contains two
pointers; a successor and a predecessor.  As illustrated above, a list
header contains two placeholder nodes that contain no data.  In an empty
list, the head and tail nodes point to each other.

 Node Structure Definition    List Header Structure Definition
 Node Initialization          Header Initialization


23 / List Structure / Node Structure Definition

A Node structure is divided into three parts: linkage, information, and
content.  The linkage part contains memory pointers to the node's
successor and predecessor nodes.  The information part contains the node
type, the priority, and a name pointer.  The content part stores the
actual data structure of interest.  For nodes that require linkage only, a
small MinNode structure is used.

    struct MinNode
    {
        struct MinNode *mln_Succ;
        struct MinNode *mln_Pred;
    };

ln_Succ
    points to the next node in the list (successor).

ln_Pred
    points to the previous node in the list (predecessor).

When a type, priority, or name is required, a full-featured Node structure
is used.

    struct Node
    {
        struct Node *ln_Succ;
        struct Node *ln_Pred;
        UBYTE        ln_Type;
        BYTE         ln_Pri;
        char        *ln_Name;
    };

ln_Type
    defines the type of the node (see <exec/nodes.h> for a list).

ln_Pri
    specifies the priority of the node  (+127 (highest) to -128
    (lowest)).

ln_Name
    points to a printable name for the node (a NULL-terminated
    string).

The Node and MinNode structures are often incorporated into larger
structures, so groups of the larger structures can easily be linked
together.   For example, the Exec Interrupt structure is defined as
follows:

    struct Interrupt
    {
        struct Node is_Node;
        APTR        is_Data;
        VOID        (*is_Code)();
    };

Here the is_Data and is_Code fields represent the useful content of the
node.  Because the Interrupt structure begins with a Node structure, it
may be passed to any of the Exec List manipulation functions.


23 / List Structure / Node Initialization

Before linking a node into a list, certain fields may need initialization.
Initialization consists of setting the ln_Type, ln_Pri, and ln_Name fields
to their appropriate values (A MinNode structure does not have these
fields).  The successor and predecessor fields do not require
initialization.

The ln_Type field contains the data type of the node.  This indicates to
Exec (and other subsystems) the type, and hence the structure, of the
content portion of the node (the extra data after the Node structure).
The standard system types are defined in the <exec/nodes.h> include file.
Some examples of standard system types are NT_TASK, NT_INTERRUPT,
NT_DEVICE, and NT_MSGPORT.

The ln_Pri field uses a signed numerical value ranging from +127 to -128
to indicate the priority of the node.  Higher-priority nodes have greater
values; for example, 127 is the highest priority, zero is nominal
priority, and -128 is the lowest priority.  Some Exec lists are kept
sorted by priority order.  In such lists, the highest-priority node is at
the head of the list, and the lowest-priority node is at the tail of the
list.  Most Exec node types do not use a priority.  In such cases,
initialize the priority field to zero.

The ln_Name field is a pointer to a NULL-terminated string of characters.
Node names are used to find and identify list-bound objects (like public
message ports and libraries), and to bind symbolic names to actual nodes.
Names are also useful for debugging purposes, so it is a good idea to
provide every node with a name.  Take care to provide a valid name
pointer; Exec does not copy name strings.

This fragment initializes a Node called myInt, an instance of the
Interrupt data structure introduced above.

    struct Interrupt interrupt;

    interrupt.is_Node.ln_Type = NT_INTERRUPT;
    interrupt.is_Node.ln_Pri  = -10;
    interrupt.is_Node.ln_Name = "sample.interrupt";


23 / List Structure / List Header Structure Definition

As mentioned earlier, a list header maintains memory pointers to the first
and last nodes of the linked chain of nodes.  It also serves as a handle
for referencing the entire list.  The minimum list header ("mlh_") and the
full-featured list header ("lh_") are generally interchangeable.

The structure MinList defines a minimum list header.

    struct MinList
    {
        struct MinNode *mlh_Head;
        struct MinNode *mlh_Tail;
        struct MinNode *mlh_TailPred;
    };

mlh_Head
    points to the first node in the list.

mlh_Tail
    is always NULL.

mlh_TailPred
    points to the last node in the list.

In a few limited cases a full-featured List structure will be required:

    struct List
    {
        struct Node *lh_Head;
        struct Node *lh_Tail;
        struct Node *lh_TailPred;
        UBYTE        lh_Type;
        UBYTE        lh_Pad;
    };

lh_Type
    defines the type of nodes within the list (see <exec/nodes.h>).

lh_pad
    is a structure alignment byte.

One subtlety here must be explained further.  The list header is
constructed in an efficient, but confusing manner.  Think of the header as
a structure containing the head and tail nodes for the list.  The head and
tail nodes are placeholders, and never carry data.  The head and tail
portions of the header actually overlap in memory. lh_Head and lh_Tail
form the head node; lh_Tail and lh_TailPred form the tail node.  This
makes it easy to find the start or end of the list, and eliminates any
special cases for insertion or removal.

           ___________                     ___________
          |           |                   |           |
          |  ln_Succ  |                   |  lh_Head  |
          |___________|___________        |___________|
          |           |           |       |           |
          | ln_Pred=0 | ln_Succ=0 |       | lh_Tail=0 |
          |___________|___________| ____\ |___________|
                      |           |     / |           |
                      |  ln_Pred  |       |lh_TailPred|
                      |___________|       |___________|

               Figure 23-2: List Header Overlap

The lh_Head and lh_Tail fields of the list header act like the ln_Succ and
lh_Pred fields of a node.  The lh_Tail field is set permanently to NULL,
indicating that the head node is indeed the first on the list -- that is,
it has no predecessors.  See the figure above.

Likewise, the lh_Tail and lh_TailPred fields of the list header act like
the ln_Succ and lh_Pred fields of a node. Here the NULL lh_Tail indicates
that the tail node is indeed the last on the list -- that is, it has no
successors.  See the figure above.


23 / List Structure / Header Initialization

List headers must be properly initialized before use.  It is not adequate
to initialize the entire header to zero.  The head and tail entries must
have specific values. The header must be initialized as follows:

    1. Set the lh_Head field to the address of lh_Tail.

    2. Clear the lh_Tail field.

    3. Set the lh_TailPred field to the address of lh_Head.

    4. Set lh_Type to the same data type as the nodes to be kept the list.
       (Unless you are using a MinList).

         Figure 23-3: Initializing a List Header Structure

                                             _________________
                                            |   ___________   |
                                            |  |           |__|
                                            |  |  lh_Head  |/_
                                            |  |___________|\ |
                                            |_\|           |  |
                                              /| lh_Tail=0 |  |
                                               |___________|  |
                                               |           |  |
                                               |lh_TailPred|__|
                                               |_ _ _ _ _ _|
                                               |     |     |
    /* C example - equivalent to NewList() */  |     |     |
    struct List list;                          |_ _ _|_ _ _|

    list.lh_Head          = (struct Node *) &list.lh_Tail;
    list.lh_Tail          = 0;
    list.lh_TailPred      = (struct Node*) &list.lh_Head;
    /* Now set lh_Type, if needed */

    ;Assembly example - equivalent to NEWLIST
          MOVE.L  A0,LH_HEAD(A0)  ;A0 points to the list header
          ADDQ.L  #4,LH_HEAD(A0)  ;Bump LH_HEAD(A0) to address of LH_TAIL
          CLR.L   LH_TAIL(A0)
          MOVE.L  A0,LH_TAILPRED(A0)
    ;Now set LH_TYPE, if needed.

The sequence of assembly instructions in the figure above is equivalent to
the macro NEWLIST, contained in the include file <exec/lists.i>.  Since
the MinList structure is the same as the List structure except for the
type and pad fields, this sequence of assembly language code will work for
both structures.  The sequence performs its function without destroying
the pointer to the list header in A0 (which is why ADDQ.L is used).  This
function may also be accessed from C as a call to NewList(header), where
header is the address of a list header.


23 Exec Lists and Queues / List Functions

Exec provides a number of symmetric functions for handling lists.  There
are functions for inserting and removing nodes, for adding and removing
head and tail nodes, for inserting nodes in a priority order, and for
searching for nodes by name.  The prototypes for Exec list handling
functions are as follows.

   Exec Functions
   --------------
   VOID AddHead( struct List *list, struct Node *node );
   VOID AddTail( struct List *list, struct Node *node );
   VOID Enqueue( struct List *list, struct Node *node );
   struct Node *FindName( struct List *list, UBYTE *name );
   VOID Insert( struct List *list, struct Node *node, struct Node *pred );
   VOID Remove( struct Node *node );
   struct Node *RemHead( struct List *list );
   struct Node *RemTail( struct List *list );

   Exec Support Functions in amiga.lib
   -----------------------------------
   VOID NewList( struct List *list );

In this discussion of the Exec list handling functions, header represents
a pointer to List header, and node represents pointer to a Node.

 Insertion and Removal
 Special Case Insertion
 Special Case Removal
 MinList/MinNode Operations
 Prioritized Insertion
 Searching by Name
 More on the Use of Named Lists
 List Macros for Assembly Language Programmers
 Empty Lists
 Scanning a List
 Important Note About Shared Lists


23 / List Functions / Insertion and Removal

The Insert() function is used for inserting a new node into any position
in a list.  It always inserts the node following a specified node that is
already part of the list.  For example, Insert(header,node,pred) inserts
the node node after the node pred in the specified list.  If the pred node
points to the list header or is NULL, the new node will be inserted at the
head of the list.  Similarly, if the pred node points to the lh_Tail of
the list, the new node will be inserted at the tail of the list.  However,
both of these actions can be better accomplished with the functions
mentioned in the "Special Case Insertion" section below.

The Remove() function is used to remove a specified node from a list.  For
example, Remove(node) will remove the specified node from whatever list it
is in.  To be removed, a node must actually be in a list. If you attempt
to remove a node that is not in a list, you will cause serious system
problems.


23 / List Functions / Special Case Insertion

Although the Insert() function allows new nodes to be inserted at the head
and the tail of a list, the AddHead() and AddTail() functions will do so
with higher efficiency.  Adding to the head or tail of a list is common
practice in first-in-first-out (FIFO) or last-in-first-out (LIFO or stack)
operations.  For example, AddHead(header,node) would insert the node at
the head of the specified list.


23 / List Functions / Special Case Removal

The two functions RemHead() and RemTail() are used in combination with
AddHead() and AddTail() to create special list ordering.  When you combine
AddTail() and RemHead(), you produce a first-in-first-out (FIFO) list.
When you combine AddHead() and RemHead() a last-in-first-out (LIFO or
stack) list is produced.  RemTail() exists for symmetry. Other
combinations of these functions can also be used productively.

Both RemHead() and RemTail() remove a node from the list, and return a
pointer to the removed node. If the list is empty, the function return a
NULL result.


23 / List Functions / MinList/MinNode Operations

All of the above functions and macros will work with long or short format
node structures.  A MinNode structure contains only linkage information.
A full Node structure contains linkage information, as well as type,
priority and name fields.  The smaller MinNode is used where space and
memory alignment issues are important.  The larger Node is used for queues
or lists that require a name tag for each node.


23 / List Functions / Prioritized Insertion

The list functions discussed so far do not make use of the priority field
in a Node. The Enqueue() function is equivalent to Insert(), except it
inserts nodes into a list sorting them according to their priority.  It
keeps the higher-priority nodes towards the head of the list.  All nodes
passed to this function must have their priority and name assigned prior
to the call. Enqueue(header,mynode) inserts mynode behind the lowest
priority node with a priority greater than or equal to mynode's. For
Enqueue() to work properly, the list must already be sort according to
priority.  Because the highest priority node is at the head of the list,
the RemHead() function will remove the highest-priority node.  Likewise,
RemTail() will remove the lowest-priority node.

    FIFO Is Used For The Same Priority.
    -----------------------------------
    If you add a node that has the same priority as another node in the
    queue, Enqueue() will use FIFO ordering.  The new node is inserted
    following the last node of equal priority.


23 / List Functions / Searching by Name

Because many lists contain nodes with symbolic names attached (via the
ln_Name field), it is possible to find a node by its name.  This naming
technique is used throughout Exec for such nodes as tasks, libraries,
devices, and resources.

The FindName() function searches a list for the first node with a given
name.  For example, FindName(header, "Furrbol") returns a pointer to the
first node named "Furrbol." If no such node exists, a NULL is returned.
The case of the name characters is significant; "foo" is different from
"Foo."

  _______________________________________________________________________
 |   ___________       ___________       ___________       ___________   |
 |  |           |____\|           |____\|           |____\|           |__|
 |  |  lh_Head  |/_  /|  ln_Succ  |/_  /|  ln_Succ  |/_  /|  ln_Succ  |/_
 |  |___________|\ \  |___________|\ \  |___________|\ \  |___________|\ |
 |_\|           |   \ |           |   \ |           |   \ |           |  |
   /| lh_Tail=0 |    \|  ln_Pred  |    \|  ln_Pred  |    \|  ln_Pred  |  |
    |___________|     |___________|     |___________|     |___________|  |
    |           |     |           |     |           |     |           |  |
    |lh_TailPred|__   |  ln_Type  |     |  ln_Type  |     |  ln_Type  |  |
    |_ _ _ _ _ _|  |  |___________|     |___________|     |___________|  |
    |     |     |  |  |           |     |           |     |           |  |
    |     |     |  |  |  ln_Pri   |     |  ln_Pri   |     |  ln_Pri   |  |
    |_ _ _|_ _ _|  |  |___________|     |___________|     |___________|  |
                   |  |           |     |           |     |           |  |
                   |  |  ln_Name  |     |  ln_Name  |     |  ln_Name  |  |
                   |  |_ _ _ _ _ _|     |_ _ _ _ _ _|     |_ _ _ _ _ _|  |
                   |  |           |     |           |     |           |  |
                   |  |   Node    |     |   Node    |     |   Node    |  |
                   |  |  Content  |     |  Content  |     |  Content  |  |
                   |  |_ _ _ _ _ _|     |_ _ _ _ _ _|     |_ _ _ _ _ _|  |
                   |_____________________________________________________|

      Figure 23-4: Complete Sample List Showing all Interconnections


23 / List Functions / More on the Use of Named Lists

To find multiple occurrences of nodes with identical names, the FindName()
function is called multiple times.  For example, if you want to find all
the nodes with the name pointed to by name:

    VOID DisplayName(struct List *list,UBYTE *name)
    {
    struct Node *node;

        if (node = FindName(list,name))
            while (node)
            {
                printf("Found %s at location %lx\n",node->ln_Name,node);
                node = FindName((struct List *)node,name);
            }
        else printf("No node with name %s found.\n",name);
    }

Notice that the second search uses the node found by the first search. The
FindName() function never compares the specified name with that of the
starting node.  It always begins the search with the successor of the
starting point.


23 / List Functions / List Macros for Assembly Language Programmers

Assembly language programmers may want to optimize their code by using
assembly code list macros.  Because these macros actually embed the
specified list operation into the code, they result in slightly faster
operations.  The file <exec/lists.i> contains the recommended set of
macros. For example, the following instructions implement the REMOVE macro:

    MOVE.L  LN_SUCC(A1),A0       ; get successor
    MOVE.L  LN_PRED(A1),A1       ; get predecessor
    MOVE.L  A0,LN_SUCC(A1)       ; fix up predecessor's succ pointer
    MOVE.L  A1,LN_PRED(A0)       ; fix up successor's pred pointer


23 / List Functions / Empty Lists

It is often important to determine if a list is empty.  This can be done
in many ways, but only two are worth mentioning.  If either the
lh_TailPred field is pointing to the list header or the ln_Succ field of
the lh_Head is NULL, then the list is empty.

In C, for example, these methods would be written as follows:

    /* You can use this method...   */
    if (list->lh_TailPred == (struct Node *)list)
        printf("list is empty\n");

    /* Or you can use this method   */
    if (NULL == list->lh_Head->ln_Succ)
        printf("list is empty\n");

In assembly code, if A0 points to the list header, these methods would be
written as follows:

    ; Use this method...
    CMP.L   LH_TAILPRED(A0),A0
    BEQ     list_is_empty

    ; Or use this method
    MOVE.L  LH_HEAD(A0),A1
    TST.L   LN_SUCC(A1)
    BEQ     list_is_empty

Because LH_HEAD and LN_SUCC are both zero offsets, the second case may be
simplified or optimized by your assembler.


23 / List Functions / Scanning a List

Occasionally a program may need to scan a list to locate a particular
node, find a node that has a field with a particular value, or just print
the list.  Because lists are linked in both the forward and backward
directions, the list can be scanned from either the head or tail.

Here is a code fragment that uses a for loop to print the names of all
nodes in a list:

    struct List *list;
    struct Node *node;

    for (node = list->lh_Head ; node->ln_Succ ; node = node->ln_Succ)
        printf("%lx -> %s\n",node,node->ln_Name);

A common mistake is to process the head or tail nodes.  Valid data nodes
have non-NULL successor and predecessor pointers.  The above loop exits
when node->ln_Succ is NULL.  Another common mistake is to free a node from
within a loop, then reference the free memory to obtain the next node
pointer.  An extra temporary pointer solves this second problem.

In assembly code, it is more efficient to use a look-ahead cache pointer
when scanning a list.  In this example the list is scanned until the first
zero-priority node is reached:

            MOVE.L  (A1),D1         ; first node
    scan:   MOVE.L  D1,A1
            MOVE.L  (A1),D1         ; lookahead to next
            BEQ.S   not_found       ; end of list...
            TST.B   LN_PRI(A1)
            BNE.S   scan
            ...                     ; found one

    not_found:

     Exec List Example


23 / List Functions / Important Note About Shared Lists

It is possible to run into contention problems with other tasks when
manipulating a list that is shared by more than one task.  None of the
standard Exec list functions arbitrates for access to the list.  For
example, if some other task happens to be modifying a list while your task
scans it, an inconsistent view of the list may be formed.  This can result
in a corrupted system.

Generally it is not permissible to read or write a shared list without
first locking out access from other tasks.  All users of a list must use
the same arbitration method.  Several arbitration techniques are used on
the Amiga.  Some lists are protected by a semaphore.  The ObtainSemaphore()
call grants ownership of the list (see the "Exec Semaphores" chapter for
more information).  Some lists require special arbitration. For example,
you must use the Intuition LockIBase(0) call before accessing any
Intuition lists.  Other lists may be accessed only during Forbid() or
Disable() (see the "Exec Tasks" chapter for more information).

The preferred method for arbitrating use of a shared list is through
semaphores because a semaphores only holds off other tasks that are trying
to access the shared list.  Rather than suspending all multitasking.
Failure to lock a shared list before use will result in unreliable
operation.

Note that I/O functions including printf() generally call Wait() to wait
for I/O completion, and this allows other tasks to run.  Therefore, it is
not safe to print or Wait() while traversing a list unless the list is
fully controlled by your application, or if the list is otherwise
guaranteed not to change during multitasking.


23 Exec Lists and Queues / Function Reference

The following charts give a brief description of the Exec list and queue
functions and assembler macros.  See the Amiga ROM Kernel Reference
Manual: Includes and Autodocs for details about each call.

             Table 23-1: Exec List and Queue Functions
  _________________________________________________________________
 |                                                                 |
 |  Exec Function  Description                                     |
 |=================================================================|
 |    AddHead()  Insert a node at the head of a list.              |
 |    AddTail()  Append a node to the tail of a list.              |
 |    Enqueue()  Insert or append a node to a system queue.        |
 |   FindName()  Find a node with a given name in a system list.   |
 |     Insert()  Insert a node into a list.                        |
 |  IsListEmpty  Test if list is empty                             |
 |    NewList()  Initialize a list structure for use.              |
 |    RemHead()  Remove the head node from a list.                 |
 |     Remove()  Remove a node from a list.                        |
 |    RemTail()  Remove the tail node from a list.                 |
 |_________________________________________________________________|

          Table 23-2: Exec List and Queue Assembler Macros
  _________________________________________________________________
 |                                                                 |
 |  Exec Function  Description                                     |
 |=================================================================|
 |      NEWLIST  Initialize a list header for use.                 |
 |      TSTLIST  Test if list is empty (list address in register). |
 |               No arbitration needed.                            |
 |      TSTLST2  Test is list is empty (from effective address of  |
 |               list).  Arbitration needed.                       |
 |         SUCC  Get next node in a list.                          |
 |         PRED  Get previous node in a list.                      |
 |      IFEMPTY  Branch if list is empty.                          |
 |   IFNOTEMPTY  Branch if list is not empty.                      |
 |      TSTNODE  Get next node, test if at end of list.            |
 |     NEXTNODE  Get next node, go to exit label if at end.        |
 |      ADDHEAD  Add node to head of list.                         |
 |      ADDTAIL  Add node to tail of list.                         |
 |       REMOVE  Remove node from a list.                          |
 |      REMHEAD  Remove node from head of list.                    |
 |     REMHEADQ  Remove node from head of list quickly.            |
 |      REMTAIL  Remove node from tail of list.                    |
 |_________________________________________________________________|


Amiga® RKM Libraries: 24 Exec Messages and Ports

For interprocess communication, Exec provides a consistent,
high-performance mechanism of messages and ports.  This mechanism is used
to pass message structures of arbitrary sizes from task to task, interrupt
to task, or task to software interrupt.  In addition, messages are often
used to coordinate operations between cooperating tasks.  This chapter
describes many of the details of using messages and ports that the casual
Amiga programmer won't need.  See the "Introduction to Exec" chapter of
this manual for a general introduction to using messages and ports.

A message data structure has two parts: system linkage and message body.
The system linkage is used by Exec to attach a given message to its
destination.  The message body contains the actual data of interest.  The
message body is any arbitrary data up to 64K bytes in size.  The message
body data can include pointers to other data blocks of any size.

Messages are always sent to a predetermined destination port. At a port,
incoming messages are queued in a first-in-first-out (FIFO) order.  There
are no system restrictions on the number of ports or the number of
messages that may be queued to a port (other than the amount of available
system memory).

Messages are always queued by reference, i.e., by a pointer to the
message.  For performance reasons message copying is not performed.  In
essence, a message between two tasks is a temporary license for the
receiving task to use a portion of the memory space of the sending task;
that portion being the message itself.  This means that if task A sends a
message to task B, the message is still part of the task A context.  Task
A, however, should not access the message until it has been replied; that
is, until task B has sent the message back, using the ReplyMsg() function.
This technique of message exchange imposes important restrictions on
message access.

 Message Ports    Messages    Function Reference


24 Exec Messages and Ports / Message Ports

Message ports are rendezvous points at which messages are collected. A
port may contain any number of outstanding messages from many different
originators.  When a message arrives at a port, the message is appended to
the end of the list of messages for that port, and a prespecified arrival
action is invoked.  This action may do nothing, or it may cause a
predefined task signal or software interrupt (see the "Exec Interrupts"
chapter).

Like many Exec structures, ports may be given a symbolic name.  Such names
are particularly useful for tasks that must rendezvous with dynamically
created ports.  They are also useful for debugging purposes.

A message port consists of a MsgPort structure as defined in the
<exec/ports.h> and <exec/ports.i> include files.  The C structure for a
port is as follows:

    struct MsgPort {
        struct Node  mp_Node;
        UBYTE        mp_Flags;
        UBYTE        mp_SigBit;
        void        *mp_SigTask;
        struct List  mp_MsgList;
    };

mp_Node
    is a standard Node structure.  This is useful for tasks that might
    want to rendezvous with a particular message port by name.

mp_Flags
    are used to indicate message arrival actions.  See the explanation
    below.

mp_SigBit
    is the signal bit number when a port is used with the task signal
    arrival action.

mp_SigTask
    is a pointer to the task to be signaled.  If a software interrupt
    arrival action is specified, this is a pointer to the interrupt
    structure.

mp_MsgList
    is the list header for all messages queued to this port.  (See the
    "Exec Lists and Queues" chapter).

The mp_Flags field contains a subfield indicated by the PF_ACTION mask.
This sub-field specifies the message arrival action that occurs when a
port receives a new message. The possibilities are as follows:

PA_SIGNAL
    This flag tells Exec to signal the mp_SigTask using signal number
    mp_SigBit on the arrival of a new message.  Every time a message is
    put to the port another signal will occur regardless of how many
    messages have been queued to the port.

PA_SOFTINT
    This flag tells Exec to Cause() a software interrupt when a message
    arrives at the port.  In this case, the mp_SigTask field must contain
    a pointer to a struct Interrupt rather than a Task pointer.  The
    software interrupt will be Caused every time a message is received.

PA_IGNORE
    This flag tells Exec to perform no operation other than queuing the
    message.  This action is often used to stop signaling or software
    interrupts without disturbing the contents of the mp_SigTask field.

It is important to realize that a port's arrival action will occur for
each new message queued, and that there is not a one-to-one correspondence
between messages and signals.  Task signals are only single-bit flags so
there is no record of how many times a particular signal occurred.  There
may be many messages queued and only a single task signal; sometimes
however there may be a signal, but no messages.  All of this has certain
implications when designing code that deals with these actions.  Your code
should not depend on receiving a signal for every message at your port.
All of this is also true for software interrupts.

 Creating a Message Port    How To Rendezvous at a Message Port
 Deleting a Message Port


24 / Message Ports / Creating a Message Port

To create a new message port using an operating system release prior to
V36, you must allocate and initialize a MsgPort structure. If you want to
make the port public, you will also need to call the AddPort() function.
Don't make a port public when it is not necessary for it to be so.  The
easiest way to create a port is to use the amiga.lib function
CreatePort(name,priority).  If NULL is passed for the name, the port will
not be made public. Port structure initialization involves setting up a
Node structure, establishing the message arrival action with its
parameters, and initializing the list header.  The following example of
port creation is equivalent to the CreatePort() function as supplied in
amiga.lib:

    struct MsgPort *CreatePort(UBYTE *name, LONG pri)
    {
        LONG sigBit;
        struct MsgPort *mp;

        if ((sigBit = AllocSignal(-1L)) == -1) return(NULL);

        mp = (struct MsgPort *) AllocMem((ULONG)sizeof(struct MsgPort),
                 (ULONG)MEMF_PUBLIC | MEMF_CLEAR);
        if (!mp) {
            FreeSignal(sigBit);
            return(NULL);
        }
        mp->mp_Node.ln_Name = name;
        mp->mp_Node.ln_Pri  = pri;
        mp->mp_Node.ln_Type = NT_MSGPORT;
        mp->mp_Flags        = PA_SIGNAL;
        mp->mp_SigBit       = sigBit;
        mp->mp_SigTask      = (struct Task *)FindTask(0L);
                                                  /* Find THIS task.   */

        if (name) AddPort(mp);
        else NewList(&(mp->mp_MsgList));          /* init message list */

        return(mp);
    }

As of V36 the Exec CreateMsgPort() function can be used to create a
message port.  This function allocates and initializes a new message port.
Just like CreatePort(), a signal bit will be allocated and the port will
be initialized to signal the creating task (mp_SigTask) when a message
arrives at this port.  To make the port public after CreateMsgPort(), you
must fill out the ln_Name field and call AddPort().  If you do this, you
must remember to RemPort() the port from the public list in your cleanup.
If you need to create a message port and your application already requires
Release 2 or greater, you can use CreateMsgPort() instead of CreatePort().
The following is an example of the usage of CreateMsgPort().

    struct MsgPort *newmp;
            /* A private message port has been created. CreateMsgPort() */
    if (newmp = CreateMsgPort())
            /* returns NULL if the creation of the message port failed. */
    {
        newmp->mp_Node.ln_Name = "Griffin";
        newmp->mp_Node.ln_Pri  = 0;
                                /* To make it public fill in the fields */
        AddPort(newmp);         /* with appropriate values.             */
    }


24 / Message Ports / Deleting a Message Port

Before a message port is deleted, all outstanding messages from other
tasks must be returned.  This is done by getting and replying to all
messages at the port until message queue is empty.  Of course, there is no
need to reply to messages owned by the current task (the task performing
the port deletion).  Public ports attached to the system with AddPort()
must be removed from the system with RemPort() before deallocation.  This
amiga.lib functions CreatePort() and DeletePort() handle this
automatically.

The following example of port deletion is equivalent to the DeletePort()
function as supplied in amiga.lib.  Note that DeletePort() must only be
used on ports created with CreatePort().

    void DeletePort(mp)
    struct MsgPort *mp;
    {
        if ( mp->mp_Node.ln_Name ) RemPort(mp);  /* if it was public... */

        mp->mp_SigTask         = (struct Task *) -1;
                                /* Make it difficult to re-use the port */
        mp->mp_MsgList.lh_Head = (struct Node *) -1;

        FreeSignal( mp->mp_SigBit );
        FreeMem( mp, (ULONG)sizeof(struct MsgPort) );
    }

To delete ports created with CreateMsgPort(), DeleteMsgPort() must be
used.  Note that these functions are only available in V36 and higher.  If
the port was made public with AddPort(), RemPort() must be used first, to
remove the port from the system.  Again, make sure all outstanding
messages are replied to, so that the message queue is empty.

    struct MsgPort *newmp;

    if (newmp)
    {
        if ( newmp->mp_Node.ln_Name ) RemPort(newmp);
                                /* if it was public... */
        DeleteMsgPort(newmp);
    }


24 / Message Ports / How To Rendezvous at a Message Port

The FindPort() function provides a means of finding the address of a
public port given its symbolic name.  For example, FindPort("Griffin")
will return either the address of the message port named "Griffin" or NULL
indicating that no such public port exists.  Since FindPort() does not do
any arbitration over access to public ports, the usage of FindPort() must
be protected with Forbid()/Permit(). Names should be unique to prevent
collisions among multiple applications.  It is a good idea to use your
application name as a prefix for your port name.  FindPort() does not
arbitrate for access to the port list.  The owner of a port might remove
it at any time.  For these reasons a Forbid()/Permit() pair is required
for the use of FindPort().  The port address can no longer be regarded as
being valid after Permit() unless your application knows that the port
cannot go away (for example, if your application created the port).

The following is an example of how to safely put a message to a specific
port:

    #include <exec/types.h>
    #include <exec/ports.h>

       BOOL MsgPort SafePutToPort(struct Message *message, STRPTR portname)
       {
           struct MsgPort *port;

           Forbid();
           port = FindPort(portname);
           if (port) PutMsg(port,message);
           Permit();
           return(port ? TRUE : FALSE);
                           /* If FALSE, the port was not found */

           /* Once we've done a Permit(), the port might go away */
           /* and leave us with an invalid port address. So we   */
           /* return just a BOOL to indicate whether the message */
           /* has been sent or not.                              */
       }


24 Exec Messages and Ports / Messages

As mentioned earlier, a message contains both system header information
and the actual message content.  The system header is of the Message form
defined in <exec/ports.h> and <exec/ports.i>.  In C this structure is as
follows:

    struct Message {
        struct Node     mn_Node;
        struct MsgPort *mn_ReplyPort;
        UWORD           mn_Length;
    };

mn_Node
    is a standard Node structure used for port linkage.

mn_ReplyPort
    is used to indicate a port to which this message will be returned
    when a reply is necessary.

mn_Length
    indicates the total length of the message, including the Message
    structure itself.

This structure is always attached to the head of all messages.  For
example, if you want a message structure that contains the x and y
coordinates of a point on the screen, you could define it as follows:

    struct XYMessage {
        struct Message xy_Msg;
        UWORD          xy_X;
        UWORD          xy_Y;
    }

For this structure, the mn_Length field should be set to sizeof(struct
XYMessage).

 Putting a Message        Getting a Message
 Waiting For a Message    Replying


24 / Messages / Putting a Message

A message is delivered to a given destination port with the PutMsg()
function.  The message is queued to the port, and that port's arrival
action is invoked.  If the action specifies a task signal or a software
interrupt, the originating task may temporarily lose the processor while
the destination processes the message.  If a reply to the message is
required, the mn_ReplyPort field must be set up prior to the call to
PutMsg().

Here is a code fragment for putting a message to a public port.  A
complete example is printed at the end of the chapter.

#Include <exec/types.h>
#include <exec/memory.h>
#include <exec/ports.h>
#include <libraries/dos.h>

VOID main(VOID);
BOOL SafePutToPort(struct Message *, STRPTR);

struct XYMessage {
    struct Message xy_Msg;
    UWORD          xy_X;
    UWORD          xy_Y;
};

VOID main(VOID)
{
    struct MsgPort *xyport, *xyreplyport;
    struct XYMessage *xymsg, *msg;
    BOOL   foundport;

    /* Allocate memory for the message we're going to send. */
    if (xymsg = (struct XYMessage *) AllocMem(sizeof(struct XYMessage),
                                             MEMF_PUBLIC | MEMF_CLEAR))
    {

        /* The replyport we'll use to get response */
        if (xyreplyport = CreateMsgPort()) {
                                         /* or use CreatePort(0,0) */

            xymsg->xy_Msg.mn_Node.ln_Type = NT_MESSAGE;
                                         /* Compose the message    */
            xymsg->xy_Msg.mn_Length = sizeof(struct XYMessage);
            xymsg->xy_Msg.mn_ReplyPort = xyreplyport;
            xymsg->xy_X = 10;
            xymsg->xy_Y = 20;

            /* Now try to send that message to a public port named
             *  "xyport". If foundport eq 0, the port isn't out there.
             */
            if (foundport = SafePutToPort((struct Message *)xymsg,
                                           "xyport"))
            {

            . . .   /* Now let's wait till the someone responds... */

            }
            else printf("Couldn't find 'xyport'\n");

            DeleteMsgPort(xyreplyport);  /* Use DeletePort() if    */
                                         /* the port was created   */
        }                                /* with CreatePort().     */
        else printf("Couldn't create message port\n");
        FreeMem(xymsg, sizeof(struct XYMessage));
    }
    else printf("Couldn't get memory for xymessage\n");
}


24 / Messages / Waiting For a Message

A task may go to sleep waiting for a message to arrive at one or more
ports.  This technique is widely used on the Amiga as a general form of
event notification.  For example, it is used extensively by tasks for I/O
request completion.

The MsgPort.mp_SigTask field contains the address of the task to be
signaled and mp_SigBit contains a preallocated signal number (as described
in the "Exec Tasks" chapter).

You can call the WaitPort() function to wait for a message to arrive at a
port.  This function will return the first message (it may not be the
only) queued to a port.  Note that your application must still call
GetMsg() to remove the message from the port.  If the port is empty, your
task will go to sleep waiting for the first message.  If the port is not
empty, your task will not go to sleep.  It is possible to receive a signal
for a port without a message being present yet.  The code processing the
messages should be able to handle this.  The following code illustrates
WaitPort().

    struct XYMessage *xy_msg;
    struct MsgPort   *xyport;

    xyport = CreatePort("xyport", 0);
    if (xyport == 0)
    {
        printf("Couldn't create xyport\n");
        exit(31);
    }

    xy_msg = WaitPort(xyport);     /* go to sleep until message arrives */

A more general form of waiting for a message involves the use of the
Wait() function (see the "Exec Signals" chapter).  This function waits for
task event signals directly.  If the signal assigned to the message port
occurs, the task will awaken.  Using the Wait() function is more general
because you can wait for more than one signal.  By combining the signal
bits from each port into one mask for the Wait() function, a loop can be
set up to process all messages at all ports.

Here's an example using Wait():

    struct XYMessage *xy_msg;
    struct MsgPort   *xyport;
    ULONG usersig, portsig;
    BOOL ABORT = FALSE;

    if (xyport = CreatePort("xyport", 0))
    {
        portsig = 1 << xyport->mp_SigBit;
        usersig = SIGBREAKF_CTRL_C;     /* User can break with CTRL-C.  */
        for (;;)
        {
            signal = Wait(portsig | usersig);
                                        /* Sleep till someone signals.  */

            if (signal & portsig)       /* Got a signal at the msgport. */
            {   .  .  .
            }
            if (signal & usersig)       /* Got a signal from the user.  */
            {
                ABORT = TRUE;           /* Time to clean up.            */
                 . . .
            }
            if (ABORT) break;
        }
        DeletePort(xyport);
    }
    else printf("Couldn't create xyport\n");

    WaitPort() Does Not Remove A Message.
    -------------------------------------
    WaitPort() only returns a pointer to the first message in a port.
    It does not actually remove the message from the port queue.


24 / Messages / Getting a Message

Messages are usually removed from ports with the GetMsg() function.  This
function removes the next message at the head of the port queue and
returns a pointer to it.  If there are no messages in a port, this
function returns a zero.

The example below illustrates the use of GetMsg() to print the contents of
all messages in a port:

    while (xymsg = GetMsg(xyport)) printf("x=%ld y=%ld\n", xymsg->xy_X,
                                           xymsg->xy_Y);

Certain messages may be more important than others.  Because ports impose
FIFO ordering, these important messages may get queued behind other
messages regardless of their priority.  If it is necessary to recognize
more important messages, it is easiest to create another port for these
special messages.


24 / Messages / Replying

When the operations associated with receiving a new message are finished,
it is usually necessary to send the message back to the originator.  The
receiver replies the message by returning it to the originator using the
ReplyMsg() function.  This is important because it notifies the originator
that the message can be reused or deallocated. The ReplyMsg() function
serves this purpose.  It returns the message to the port specified in the
mn_ReplyPort field of the message.  If this field is zero, no reply is
returned.

The previous example can be enhanced to reply to each of its messages:

    while (xymsg = GetMsg(xyport)) {
        printf("x=%ld y=%ld\n", xymsg->xy_X, xymsg->xy_Y);
        ReplyMsg(xymsg);
    }

Notice that the reply does not occur until after the message values have
been used.

Often the operations associated with receiving a message involve returning
results to the originator.  Typically this is done within the message
itself.  The receiver places the results in fields defined (or perhaps
reused) within the message body before replying the message back to the
originator.  Receipt of the replied message at the originator's reply port
indicates it is once again safe for the originator to use or change the
values found within the message.

The following are two short example tasks that communicate by sending,
waiting for and replying to messages.  Run these two programs together.

     Port1.c    Port2.c


24 Exec Messages and Ports / Function Reference

The following chart gives a brief description of the Exec functions that
control inter-task communication with messages and ports.  See the Amiga
ROM Kernel Reference Manual: Includes and Autodocs for details about each
call.

               Table 24-1: Exec Message and Port Functions
  _____________________________________________________________________
 |                                                                     |
 |       Function                   Description                        |
 |=====================================================================|
 |        AddPort()  Add a public message port to the system list.     |
 |  CreateMsgPort()  Allocate and initialize a new message port (V37). |
 |  DeleteMsgPort()  Free a message port, created with CreateMsgPort() |
 |                   (V37).                                            |
 |       FindPort()  Find a public message port in the system list.    |
 |         GetMsg()  Get next message from the message port.           |
 |         PutMsg()  Put a message to a message port.                  |
 |        RemPort()  Remove a message port from the system list.       |
 |       ReplyMsg()  Reply to a message on its reply port.             |
 |_____________________________________________________________________|

               Table 24-2: Amiga.lib Exec Support Functions
  _____________________________________________________________________
 |                                                                     |
 |       Function                   Description                        |
 |=====================================================================|
 |     CreatePort()  Allocate and initialize a new message port, make  |
 |                   public if named                                   |
 |     DeletePort()  Delete a message port, created with CreatePort(). |
 |_____________________________________________________________________|


Amiga® RKM Libraries: 25 Exec Semaphores

Semaphores are a feature of Exec which provide a general method for tasks
to arbitrate for the use of memory or other system resources they may be
sharing.  This chapter describes the structure of Exec semaphores and the
various support functions provided for their use.  Since the semaphore
system uses Exec lists and signals, some familiarity with these concepts
is helpful for understanding semaphores.

In any multitasking or multi-processing system there is a need to share
data among independently executing tasks.  If the data is static (that is,
it never changes), then there is no problem.  However, if the data is
variable, then there must be some way for a task that is about to make a
change to keep other tasks from looking at the data.

For example, to add a node to a linked list of data, a task would normally
just add the node.  However, if the list is shared with other tasks, this
could be dangerous.  Another task could be walking down the list while the
change is being made and pick up an incorrect pointer.  The problem is
worse if two tasks attempt to add an item to the list at the same time.
Exec semaphores provide a way to prevent such problems.

A semaphore is much like getting a key to a locked data item.  When you
have the key (semaphore), you can access the data item without worrying
about other tasks causing problems.  Any other tasks that try to obtain
the semaphore will be put to sleep until the semaphore becomes available.
When you have completed your work with the data, you return the semaphore.

For semaphores to work correctly, there are two restrictions that must be
observed at all times:

 1) All tasks using shared data that is protected by a semaphore must
    always ask for the semaphore first before accessing the data. If some
    task accesses the data directly without first going through the
    semaphore, the data may be corrupted.  No task will have safe access
    to the data.

 2) A deadlock will occur if a task that owns an exclusive semaphore on
    some data inadvertently calls another task which tries to get an
    exclusive semaphore on that same data in blocking mode.  Deadlocks
    and other such issues are beyond the scope of this manual.  For more
    details on deadlocks and other problems of shared data in a
    multitasking system and the methods used to prevent them, refer to a
    textbook in computer science such as Operating Systems by Tannenbaum
    (Prentice-Hall).

 Semaphore Functions    Function Reference


25 Exec Semaphores / Semaphore Functions

Exec provides a variety of useful functions for setting, checking and
freeing semaphores.  The prototypes for these functions are as follows.

    VOID  AddSemaphore ( struct SignalSemaphore *sigSem );
    ULONG AttemptSemaphore( struct SignalSemaphore *sigSem );
    struct SignalSemaphore *FindSemaphore( UBYTE *sigSem );
    VOID InitSemaphore( struct SignalSemaphore *sigSem );

    VOID ObtainSemaphore( struct SignalSemaphore *sigSem );
    VOID ObtainSemaphoreList( struct List *sigSem );
    void ObtainSemaphoreShared( struct SignalSemaphore *sigSem );

    VOID ReleaseSemaphore( struct SignalSemaphore *sigSem );
    VOID ReleaseSemaphoreList( struct List *sigSem );
    VOID RemSemaphore( struct SignalSemaphore *sigSem );

 The Signal Semaphore    Multiple Semaphores    Semaphore Example


25 / Semaphore Functions / The Signal Semaphore

Exec semaphores are signal based. Using signal semaphores is the easiest
way to protect shared, single-access resources in the Amiga.  Your task
will sleep until the semaphore is available for use.  The SignalSemaphore
structure is as follows:

    struct SignalSemaphore {
        struct  Node ss_Link;
        SHORT   ss_NestCount;
        struct  MinList ss_WaitQueue;
        struct  SemaphoreRequest ss_MultipleLink;
        struct  Task *ss_Owner;
        SHORT   ss_QueueCount;
    };

ss_Link
    is the node structure used to link semaphores together.  The ln_Pri
    and ln_Name fields are used to set the priority of the semaphore in a
    list and to name the semaphore for public access.  If a semaphore is
    not public the ln_Name and ln_Pri fields may be left NULL.

ss_NestCount
    is the count of number of locks the current owner has on the
    semaphore.

ss_WaitQueue
    is the List header for the list of other tasks waiting for this
    semaphore.

ss_MultipleLink
    is the SemaphoreRequest used by ObtainSemaphoreList().

ss_Owner
    is the pointer to the current owning task.

ss_QueueCount
    is the number of other tasks waiting for the semaphore.

A practical application of a SignalSemaphore would be to use it as the
base of a shared data structure.  For example:

    struct SharedList {
        struct SignalSemaphore sl_Semaphore;
        struct MinList         sl_List;
    };

 Creating a SignalSemaphore Structure
 Making a SignalSemaphore Available to the Public
 Obtaining a SignalSemaphore Exclusively
 Obtaining a Shared SignalSemaphore
 Checking a SignalSemaphore
 Releasing a SignalSemaphore
 Removing a SignalSemaphore Structure


25 / / The Signal Semaphore / Creating a SignalSemaphore Structure

To initialize a SignalSemaphore structure use the InitSemaphore()
function.  This function initializes the list structure and the nesting
and queue counters.  It does not change the semaphore's name or priority
fields.

This fragment creates and initializes a semaphore for a data item such as
the SharedList structure above.

    struct SharedList *slist;

    if (slist=(struct SharedList *)
        AllocMem(sizeof(struct SharedList),MEMF_PUBLIC|MEMF_CLEAR))
    {
        NewList(&slist->sl_List);       /* Initialize the MinList       */
        InitSemaphore((struct SignalSemaphore *)slist);
                                        /* And initialize the semaphore */

        /* The semaphore can now be used. */
    }
    else printf("Can't allocate structure\n");


25 / / / Making a SignalSemaphore Available to the Public

A semaphore should be used internally in your program if it has more than
one task operating on shared data structures.  There may also be cases
when you wish to make a data item public to other applications but still
need to restrict its access via semaphores.  In that case, you would give
your semaphore a unique name and add it to the public SignalSemaphore list
maintained by Exec.  The AddSemaphore() function does this for you.  This
works in a manner similar to AddPort() for message ports.

To create and initialize a public semaphore for a data item and add it to
the public semaphore list maintained by Exec, the following function
should be used.  (This will prevent the semaphore from being added or
removed more than once by separate programs that use the semaphore).

   UBYTE *name;   /* name of semaphore to add */
   struct SignalSemaphore *semaphore;

   Forbid();
   /* Make sure the semaphore name is unique */
   if (!FindSemaphore(name)) {
       /* Allocate memory for the structure */
       if (sema=(struct SignalSemaphore *)
           AllocMem(sizeof(struct SignalSemaphore),MEMF_PUBLIC|MEMF_CLEAR))
       {
           sema->ss_Link.ln_Pri=0;         /* Set the priority to zero */
           sema->ss_Link.ln_Name=name;
           /* Note that the string 'name' is not copied. If that is    */
           /* needed, allocate memory for it and copy the string. And  */
           /* add the semaphore the the system list                    */
           AddSemaphore(semaphore);
       }
   }
   Permit();

A value of NULL for semaphore means that the semaphore already exists or
that there was not enough free memory to create it.

Before using the data item or other resource which is protected by a
semaphore, you must first obtain the semaphore.  Depending on your needs,
you can get either exclusive or shared access to the semaphore.


25 / / The Signal Semaphore / Obtaining a SignalSemaphore Exclusively

The ObtainSemaphore() function can be used to get an exclusive lock on a
semaphore.  If another task currently has an exclusive or shared lock(s)
on the semaphore, your task will be put to sleep until all locks on the
the semaphore are released.

    Semaphore Nesting.
    ------------------
    SignalSemaphores have nesting.  That is, if your task already
    owns the semaphore, it will get a second ownership of that semaphore.
    This simplifies the writing of routines that must own the semaphore
    but do not know if the caller has obtained it yet.

To obtain a semaphore use:

    struct SignalSemaphore *semaphore;
    ObtainSemaphore(semaphore);

To get an exclusive lock on a public semaphore, the following code should
be used:

    UBYTE *name;
    struct SignalSemaphore *semaphore;

    Forbid();     /* Make sure the semaphore will not go away if found. */
    if (semaphore=FindSemaphore(name))
        ObtainSemaphore(semaphore);
    Permit();

The value of semaphore is NULL if the semaphore does not exist.  This is
only needed if the semaphore has a chance of going away at any time (i.e.,
the semaphore is public and  might be removed by some other program).  If
there is a guarantee that the semaphore will not disappear, the semaphore
address could be cached, and all that would be needed is a call to the
ObtainSemaphore() function.


25 / / The Signal Semaphore / Obtaining a Shared SignalSemaphore

For read-only purposes, multiple tasks may have a shared lock on a signal
semaphore.  If a semaphore is already exclusively locked, all attempts to
obtain the semaphore shared will be blocked until the exclusive lock is
released.  At that point, all shared locks will be obtained and the
calling tasks will wake up.

To obtain a shared semaphore, use:

    struct SignalSemaphore *semaphore;
    ObtainSemaphoreShared(semaphore);

To obtain a public shared semaphore, the following code should be used:

    UBYTE *name;
    struct SignalSemaphore *semaphore;

    Forbid();
    if (semaphore = FindSemaphore(name))
        ObtainSemaphoreShared(semaphore);
    Permit();


25 / / The Signal Semaphore / Checking a SignalSemaphore

When you attempt to obtain a semaphore with ObtainSemaphore(), your task
will be put to sleep if the semaphore is not currently available. If you
do not want to wait, you can call AttemptSemaphore() instead. If the
semaphore is available for exclusive locking, AttemptSemaphore() obtains
it for you and returns TRUE.  If it is not available, the function returns
FALSE immediately instead of waiting for the semaphore to be released.

To attempt to obtain a semaphore, use the following:

    struct SignalSemaphore *semaphore;
    AttemptSemaphore(semaphore);

To make an attempt to obtain a public semaphore, the following code should
be used:

    UBYTE *name;
    struct SignalSemaphore *semaphore;

    Forbid();
    if (semaphore = FindSemaphore(name)) AttemptSemaphore(semaphore);
    Permit();


25 / / The Signal Semaphore / Releasing a SignalSemaphore

Once you have obtained the semaphore and completed any operations on the
semaphore protected object, you should release the semaphore.  The
ReleaseSemaphore() function does this.  For each successful
ObtainSemaphore(), ObtainSemaphoreShared() and AttemptSemaphore() call you
make, you must have a matching ReleaseSemaphore() call.


25 / / The Signal Semaphore / Removing a SignalSemaphore Structure

Semaphore resources can only be freed if the semaphore is not locked.  A
public semaphore should first be removed from the system semaphore list
with the RemSemaphore() function. This prevents other tasks from finding
the semaphore and trying to lock it. Once the semaphore is removed from
the system list, the semaphore should be locked exclusively so no other
task can lock it.  Once the lock is obtained, it can be released again,
and the resources can be deallocated.

The following code should be used to remove a public semaphore:

    UBYTE *name;
    struct SignalSemaphore *semaphore;

    Forbid();
    if (semaphore=FindSemaphore(name))
    {
        RemSemaphore(semaphore);       /* So no one else can find it... */
        ObtainSemaphore(semaphore);    /* Wait for us to be last user...*/
        ReleaseSemaphore(semaphore);   /* Ready for cleanup...          */
    }
    FreeMem(semaphore, sizeof(struct SignalSemaphore));
    Permit();


25 / Semaphore Functions / Multiple Semaphores

The semaphore system has the ability to ask for ownership of a complete
list of semaphores.  This can help prevent deadlocks when there are two or
more tasks trying to get the same set of semaphores.  If task A gets
semaphore 1 and tries to obtain semaphore 2 after task B has obtained
semaphore 2 but before task B tries to obtain semaphore 1 then both tasks
will hang.  Exec provides ObtainSemaphoreList() and ReleaseSemaphoreList()
to prevent this problem.

A semaphore list is a list header to a list that contains SignalSemaphore
structures.  The semaphore list must not contain any public semaphores.
This is because the semaphore list functions use the standard node
structures in the semaphore.

To arbitrate access to a semaphore list use another semaphore.  Create a
public semaphore and use it to arbitrate access to the list header of the
semaphore list.  This also gives you a locking semaphore, protecting the
ObtainSemaphoreList() call.  Once you have gained access to the list with
ObtainSemaphore(), you may obtain all the semaphores on the list via
ObtainSemaphoreList() (or get individual semaphores with
ObtainSemaphore()).  When you are finished with the protected objects,
release the semaphores on the list with ReleaseSemaphoreList(), and then
release the list semaphore via ReleaseSemaphore().

For example:

    ObtainSemaphore((struct SignalSemaphore *)SemaphoreList);
    ObtainSemaphoreList(SemaphoreList->sl_List);

    /* At this point the objects are protected, and can be manipulated */

    ReleaseSemaphoreList(SemaphoreList->sl_List);
    ReleaseSemaphore((struct SignalSemaphore *)SemaphoreList);

See the SharedList structure above for an example of a semaphore structure
with a list header.


25 Exec Semaphores / Function Reference

The following charts give a brief description of the Exec semaphore
functions.  See the Amiga ROM Kernel Reference Manual: Includes and
Autodocs for details about each call.

                   Table 25-1: Exec Semaphore Functions
  ________________________________________________________________________
 |                                                                        |
 |  Exec Semaphore Function                 Description                   |
 |========================================================================|
 |           AddSemaphore()  Initialize and add a signal semaphore to the |
 |                           system.                                      |
 |       AttemptSemaphore()  Try to get an exclusive lock on a signal     |
 |                           semaphore without blocking.                  |
 |          FindSemaphore()  Find a given system signal semaphore.        |
 |          InitSemaphore()  Initialize a signal semaphore.               |
 |        ObtainSemaphore()  Try to get exclusive access to a signal      |
 |                           semaphore.                                   |
 |    ObtainSemaphoreList()  Try to get exclusive access to a list of     |
 |                           signal semaphores.                           |
 |  ObtainSemaphoreShared()  Try to get shared access to a signal         |
 |                           semaphore (V36).                             |
 |       ReleaseSemaphore()  Release the lock on a signal semaphore.      |
 |   ReleaseSemaphoreList()  Release the locks on a list of signal        |
 |                           semaphores.                                  |
 |           RemSemaphore()  Remove a signal semaphore from the system.   |
 |________________________________________________________________________|


Amiga® RKM Libraries: 26 Exec Interrupts

 Introduction            Software Interrupts     Function Reference
 Servicing Interrupts    Disabling Interrupts


26 Exec Interrupts / Introduction

Exec manages the decoding, dispatching, and sharing of all system
interrupts.  This includes control of hardware interrupts, software
interrupts, task-relative interrupts (see the discussion of exceptions in
the "Exec Tasks" chapter), and interrupt disabling and enabling.  In
addition, Exec supports a more extended prioritization of interrupts than
that provided in the 68000.

The proper operation of multitasking depends heavily on the consistent
management of the interrupt system.  Task activities are often driven by
intersystem communication that is originated by various interrupts.

 Sequence of Events During an Interrupt
 Interrupt Priorities
 Nonmaskable Interrupt


26 / Introduction / Sequence of Events During an Interrupt

Before useful interrupt handling code can be executed, a considerable
amount of hardware and software activity must occur.  Each interrupt must
propagate through several hardware and software interfaces before
application code is finally dispatched:

  * A hardware device decides to cause an interrupt and sends a signal to
    the interrupt control portions of the 4703 (Paula) custom chip.

  * The 4703 interrupt control logic notices this new signal and performs
    two primary operations.  First, it records that the interrupt has
    been requested by setting a flag bit in the INTREQ register.  Second,
    it examines the INTENA register to determine whether the
    corresponding interrupt and the interrupt master are enabled.  If
    both are enabled, the 4703 generates an interrupt request by placing
    the priority level of the request onto the three 68000 interrupt
    control input lines (IPL0, IPL1, IPL2).

  * These three signals correspond to seven interrupt priority levels in
    the 68000.  If the priority of the new interrupt is greater than the
    current processor priority, an interrupt sequence is initiated. The
    priority level of the new interrupt is used to index into the top
    seven words of the processor address space.  The odd byte (a vector
    number) of the indexed word is fetched and then shifted left by two
    to create an offset into the processor's auto-vector interrupt table.
    The vector offsets used are in the range of $064 to $07C.  These are
    labeled as interrupt autovectors in the 68000 manual.  The
    auto-vector table appears in low memory on a 68000 system, but its
    location for other 68000 family processors is determined by the
    processor's CPU Vector Base Register (VBR).  VBR can be accessed from
    supervisor mode with the MOVEC instruction.

  * The processor then switches into supervisor mode (if it is not
    already in that mode), and saves copies of the status register and
    program counter (PC) onto the top of the system stack (additional
    information may be saved by processors other than the 68000).  The
    processor priority is then raised to the level of the active
    interrupt.

  * From the low memory vector address (calculated in step three above),
    a 32-bit autovector address is fetched and loaded into the program
    counter.  This is an entry point into Exec's interrupt dispatcher.

  * Exec must now further decode the interrupt by examining the INTREQ
    and INTENA 4703 chip registers.  Once the active interrupt has been
    determined, Exec indexes into an ExecBase array to fetch the
    interrupt's handler entry point and handler data pointer addresses.

  * Exec now turns control over to the interrupt handler by calling it as
    if it were a subroutine.  This handler may deal with the interrupt
    directly or may propagate control further by invoking interrupt
    server chain processing.

You can see from the above discussion that the interrupt autovectors
should never be altered by the user.  If you wish to provide your own
system interrupt handler, you must use the Exec SetIntVector() function.
You should not change the contents of any autovector location.

Task multiplexing usually occurs as the result of an interrupt.  When an
interrupt has finished and the processor is about to return to user mode,
Exec determines whether task-scheduling attention is required.  If a task
was signaled during interrupt processing, the task scheduler will be
invoked.  Because Exec uses preemptive task scheduling, it can be said
that the interrupt subsystem is the heart of task multiplexing.  If, for
some reason, interrupts do not occur, a task might execute forever because
it cannot be forced to relinquish the CPU.

                    Table 26-1: Interrupts by Priority

                  Exec
    Hardware    Pseodo-
    Priority    Priority   Description                Label   Type
    --------    --------   -----------                -----   ----
              ____
             |     1    Serial transmit buffer empty  TBE      H
             |
       1 ----|     2    disk block complete           DSKBLK   H
             |
             |     3    software interrupt            SOFTINT  H
             |----
       2 ----|     4    external INT2 & CIAA          PORTS    S
             |----
             |     5    graphics coprocessor          COPER    S
             |
       3 ----|     6    vertical blank interval       VERTB    S
             |
             |     7    blitter finished              BLIT     H
             |----
             |     8    audio channel 2               AUD2     H
             |
             |     9    audio channel 0               AUD0     H
       4 ----|
             |     10   audio channel 3               AUD3     H
             |
             |     11   audio channel 1               AUD1     H
             |----
             |     12   Serial receive buffer full    RBF      H
       5 ----|
             |     13   disk sync pattern found       DSKSYNC  H
             |----
             |     14   external INT6 & CIAB          EXTER    S
       6 ----|
             |     15   special (master enable)       INTEN    -
             |----
       7 ----|____ --   non-maskable interrupt        NMI      S


26 / Introduction / Interrupt Priorities

Interrupts are prioritized in hardware and software.  The 68000 CPU
priority at which an interrupt executes is determined strictly by
hardware.  In addition to this, the software imposes a finer level of
pseudo-priorities on interrupts with the same CPU priority. These
pseudo-priorities determine the order in which simultaneous interrupts of
the same CPU priority are processed.  Multiple interrupts with the same
CPU priority but a different pseudo-priority will not interrupt one
another.  Interrupts are serviced by either an exclusive handler or by
server chains to which many servers may be attached, as shown in the Type
field of the table.  The table above summarizes all interrupts by
priority.

The 8520s (also called CIAs) are Amiga peripheral interface adapter chips
that generate the INT2 and INT6 interrupts.  For more information about
them, see the Amiga Hardware Reference Manual.

As described in the Motorola 68000 programmer's manual, interrupts may
nest only in the direction of higher priority.  Because of the
time-critical nature of many interrupts on the Amiga, the CPU priority
level must never be changed by user or system code. When the system is
running in user mode (multitasking), the CPU priority level must remain
set at zero.  When an interrupt occurs, the CPU priority is raised to the
level appropriate for that interrupt. Lowering the CPU priority would
permit unlimited interrupt recursion on the system stack and would
"short-circuit" the interrupt-priority scheme.

Because it is dangerous on the Amiga to hold off interrupts for any period
of time, higher-level interrupt code must perform its business and exit
promptly.  If it is necessary to perform a time-consuming operation as the
result of a high-priority interrupt, the operation should be deferred
either by posting a software interrupt or by signalling a task.  In this
way, interrupt response time is kept to a minimum.  Software interrupts
are described in a later section.


26 / Introduction / Nonmaskable Interrupt

The 68000 provides a nonmaskable interrupt (NMI) of CPU priority 7.
Although this interrupt cannot be generated by the Amiga hardware itself,
it can be generated on the expansion bus by external hardware.  Because
this interrupt does not pass through the 4703 interrupt controller
circuitry, it is capable of violating system code critical sections.  In
particular, it short-circuits the DISABLE mutual-exclusion mechanism.
Code that uses NMI must not assume that it can access system data
structures.


26 Exec Interrupts / Servicing Interrupts

Interrupts are serviced on the Amiga through the use of interrupt handlers
and servers.  An interrupt handler is a system routine that exclusively
handles all processing related to a particular 4703 interrupt.  An
interrupt server is one of possibly many system routines that are invoked
as the result of a single 4703 interrupt.  Interrupt servers provide a
means of interrupt sharing. This concept is useful for general-purpose
interrupts such as vertical blanking.

At system start, Exec designates certain interrupts as handlers and others
as server chains.  The PORTS, COPER, VERTB, EXTER, and NMI interrupts are
initialized as server chains.  Therefore, each of these may execute
multiple interrupt routines per each interrupt.  All other interrupts are
designated as handlers and are always used exclusively.

 Interrupt Data Structure    Interrupt Handlers
 Environment                 Interrupt Servers


26 / Servicing Interrupts / Interrupt Data Structure

Interrupt handlers and servers are defined by the Exec Interrupt
structure.  This structure specifies an interrupt routine entry point and
data pointer.  The C definition of this structure is as follows:

    struct Interrupt
    {
        struct Node is_Node;
        APTR        is_Data;
        VOID      (*is_Code)();
    };

Once this structure has been properly initialized, it can be used for
either a handler or a server.


26 / Servicing Interrupts / Environment

Interrupts execute in an environment different from that of tasks. All
interrupts execute in supervisor mode and utilize the single system stack.
This stack is large enough to handle extreme cases of nested interrupts
(of higher priorities).  Interrupt processing has no effect on task stack
usage.

All interrupt processing code, both handlers and servers, is invoked as
assembly code subroutines.  Normal assembly code register conventions
dictate that the D0, D1, A0 and A1 registers be free for scratch use.  In
the case of an interrupt handler, some of these registers also contain
data that may be useful to the handler code.  See the section on handlers
below.

Because interrupt processing executes outside the context of most system
activities, certain data structures will not be self-consistent and must
be considered off limits for all practical purposes.  This happens because
certain system operations are not atomic in nature and might be
interrupted only after executing part of an important instruction
sequence.  For example, memory allocation and deallocation routines do not
disable interrupts.  This results in the possibility of interrupting a
memory-related routine.  In such a case, a memory linked list may be
inconsistent during and interrupt. Therefore, interrupt routines must not
use any memory allocation or deallocation functions.

In addition, interrupts may not call any system function which might
allocate memory, wait, manipulate unprotected lists, or modify
ExecBase->ThisTask data (for example Forbid(), Permit(), and mathieee
libraries).  In practice, this means that very few system calls may be
used within interrupt code. The following functions may generally be used
safely within interrupts:

    Alert(), Disable(), Enable(), Signal(), Cause(),
    GetMsg(), PutMsg(), ReplyMsg(), FindPort(), FindTask()

and if you are manipulating your own List structures while in an interrupt:

    AddHead(), AddTail(), RemHead(), RemTail(), FindName()

In addition, certain devices (notably the timer device) specifically allow
limited use of SendIO() and BeginIO() within interrupts.


26 / Servicing Interrupts / Interrupt Handlers

As described above, an interrupt handler is a system routine that
exclusively handles all processing related to a particular 4703 interrupt.
There can only be one handler per 4703 interrupt.  Every interrupt handler
consists of an Interrupt structure (as defined above) and a single
assembly code routine.  Optionally, a data structure pointer may also be
provided.  This is particularly useful for ROM-resident interrupt code.

An interrupt handler is passed control as if it were a subroutine of Exec.
Once the handler has finished its business, it must return to Exec by
executing an RTS (return from subroutine) instruction rather than an RTE
(return from exception) instruction. Interrupt handlers should be kept
very short to minimize service-time overhead and thus minimize the
possibilities of interrupt overruns. As described above, an interrupt
handler has the normal scratch registers at its disposal.  In addition, A5
and A6 are free for use.  These registers are saved by Exec as part of the
interrupt initiation cycle.

For the sake of efficiency, Exec passes certain register parameters to the
handler (see the list below).  These register values may be utilized to
trim a few microseconds off the execution time of a handler.  All of the
following registers (D0/D1/A0/A1/A5/A6) may be used as scratch registers
by an interrupt handler, and need not be restored prior to returning.

    Don't Make Assumptions About Registers.
    ---------------------------------------
    Interrupt servers have different register usage rules (see the
    "Interrupt Servers" section).

 Interrupt Handler Register Usage


26 / / Interrupt Handlers / Interrupt Handler Register Usage

Here are the register conventions for interrupt handlers.

 D0 Contains no valid information.

 D1 Contains the 4703 INTENAR and INTREQR registers values AND'ed
    together.  This results in an indication of which interrupts are
    enabled and active.

 A0 Points to the base address of the Amiga custom chips.  This
    information is useful for performing indexed instruction access to
    the chip registers.

 A1 Points to the data area specified by the is_Data field of the
    Interrupt structure.  Because this pointer is always fetched
    (regardless of whether you use it), it is to your advantage to make
    some use of it.

 A5 Is used as a vector to your interrupt code.

 A6 Points to the Exec library base (SysBase).  You may use this register
    to call Exec functions or set it up as a base register to access your
    own library or device.

Interrupt handlers are established by passing the Exec function
SetIntVector(), your initialized Interrupt structure, and the 4703
interrupt bit number of interest.  The parameters for this function are as
follows:

    SetIntVector(ULONG intNumber, struct Interrupt *interrupt)

The first argument is the bit number for which this interrupt server is to
respond (example INTB_VERTB).  The possible bits for interrupts are
defined in <hardware/intbits.h>.  The second argument is the address of an
interrupt server node as described earlier in this chapter.  Keep in mind
that certain interrupts are established as server chains and should not be
accessed as handlers.

The following example demonstrates initialization and installation of an
assembler interrupt handler.  See the "Resources" chapter for more
information on allocating resources, and the "Serial Device" chapter in
the Amiga ROM Kernel Reference Manual: Devices for the more common method
of serial communications.

     rbf.c

The assembler interrupt handler code, RBFHandler, reads the complete word
of serial input data from the serial hardware and then separates the
character and flag bytes into separate buffers. When the buffers are full,
the handler signals the main process causing main to print the character
buffer contents, remove the handler, and exit.

     rbfhandler.asm

    NOTE.
    -----
    The data structure containing the signal to use, task address
    pointer, and buffers is allocated and initialized in main(), and
    passed to the handler via the is_Data pointer of the Interrupt
    structure.


26 / Servicing Interrupts / Interrupt Servers

As mentioned above, an interrupt server is one of possibly many system
interrupt routines that are invoked as the result of a single 4703
interrupt. Interrupt servers provide an essential mechanism for interrupt
sharing.

Interrupt servers must be used for PORTS, COPER, VERTB, EXTER, or NMI
interrupts. For these interrupts, all servers are linked together in a
chain. Every server in the chain will be called in turn as long as the
previous server returned with the processor's Z (zero) flag set.  If you
determine that an interrupt was specifically for your server, you should
return with the processor's Z flag cleared (non-zero condition) so that
the remaining servers on the chain will be skipped.

    Use The Z Flag.
    ---------------
    VERTB (vertical blank) servers should always return with the Z (zero)
    flag set.  The processor Z flag is used rather than the normal
    function convention of returning a result in D0 because it may be
    tested more quickly by Exec upon the server's return.

The easiest way to set the condition code register is to do an immediate
move to the D0 register as follows:

   SetZflag_Calls_Next:
           MOVEQ   #0,D0
           RTS

   ClrZflag_Ends_Chain:
           MOVEQ   #1,D0
           RTS

The same Exec Interrupt structure used for handlers is also used for
servers.  Also, like interrupt handlers, servers must terminate their code
with an RTS instruction.

Interrupt servers are called in priority order.  The priority of a server
is specified in its is_Node.ln_Pri field. Higher-priority servers are
called earlier than lower-priority servers.  Adding and removing interrupt
servers from a particular chain is accomplished with the Exec
AddIntServer() and RemIntServer() functions.  These functions require you
to specify both the 4703 interrupt number and a properly initialized
Interrupt structure.

Servers have different register values passed than handlers do.  A server
cannot count on the D0, D1, A0, or A6 registers containing any useful
information.  However, the highest priority system vertical blank server
currently expects to receive a pointer to the custom chips A0.  Therefore,
if you install a vertical blank server at priority 10 or greater, you must
place custom ($DFF000) in A0 before exiting.  Other than that, a server is
free to use D0-D1 and A0-A1/A5-A6 as scratch.

 Interrupt Server Register Usage


26 / / Interrupt Servers / Interrupt Server Register Usage

 D0 Scratch.

 D1 Scratch.

 A0 Scratch except in certain cases (see note above).

 A1 Points to the data area specified by the is_Data field of the
    Interrupt structure.  Because this pointer is always fetched
    (regardless of whether you use it), it is to your advantage to make
    some use of it (scratch).

 A5 Points to your interrupt code (scratch).

 A6 Scratch.

In a server chain, the interrupt is cleared automatically by the system.
Having a server clear its interrupt is not recommended and not necessary
(clearing could cause the loss of an interrupt on PORTS or EXTER).

Here is an example of a program to install and remove a low-priority
vertical blank interrupt server:

     vertb.c

This is the assembler VertBServer installed by the C example:

     vertbserver.asm


26 Exec Interrupts / Software Interrupts

Exec provides a means of generating software interrupts. Software
interrupts execute at a priority higher than that of tasks but lower than
that of hardware interrupts, so they are often used to defer hardware
interrupt processing to a lower priority.  Software interrupts use the
same Interrupt data structure as hardware interrupts.  As described above,
this structure contains pointers to both interrupt code and data, and
should be initialized as node type NT_INTERRUPT (not NT_SOFTINT which is
an internal Exec flag).

A software interrupt is usually activated with the Cause() function.  If
this function is called from a task, the task will be interrupted and the
software interrupt will occur.  If it is called from a hardware interrupt,
the software interrupt will not be processed until the system exits from
its last hardware interrupt.  If a software interrupt occurs from within
another software interrupt, it is not processed until the current one is
completed.  However, individual software interrupts do not nest, and will
not be caused if already running as a software interrupt.

    Don't Trash A6!
    ---------------
    Software interrupts execute in an environment almost identical to
    that of hardware interrupts, and the same restrictions on allowable
    system function calls (as described earlier) apply to both.  Note
    however that, unlike other interrupts, software interrupts must
    preserve A6.

Software interrupts are prioritized.  Unlike interrupt servers, software
interrupts have only five allowable priority levels:  -32, -16, 0, +16,
and +32.  The priority should be put into the ln_Pri field prior to
calling Cause().

Software interrupts can also be generated by message arrival at a
PA_SOFTINT message port.  The applications of this technique are limited
since it is not permissible, with most devices, to send IO requests from
within interrupt code.  However, the timer.device does allow such
interactions, so a self-perpetuating PA_SOFTINT timer port can provide an
application with quite consistent timing under varying multitasking loads.
The following example demonstrates use of a software interrupt and a
PA_SOFTINT port.  See the "Exec Messages and Ports" chapter for more
information about messages and ports.

     timersoftint.c


26 Exec Interrupts / Disabling Interrupts

As mentioned in the "Exec Tasks" chapter, it is sometimes necessary to
disable interrupts when examining or modifying certain shared system data
structures.  However, for proper system operation, interrupts should never
be disabled unless absolutely necessary, and never for more than 250
microseconds.  Interrupt disabling is controlled with the Disable() and
Enable() functions. Although assembler DISABLE and ENABLE macros are
provided, we strongly suggest that you use the system functions rather
than the macros for upwards compatibility and smaller code size.

In some system code, there are nested disabled sections.  Such code
requires that interrupts be disabled with the first Disable() and not
re-enabled until the last Enable().  The system Enable() and Disable()
functions are designed to permit this sort of nesting.

Disable() increments a counter to track how many levels of disable have
been issued.  Only 126 levels of nesting are permitted. Enable()
decrements the counter, and reenables interrupts when the last disable
level has been exited.


26 Exec Interrupts / Function Reference

The following chart gives a brief description of the Exec functions that
control interrupts.  See the Amiga ROM Kernel Reference Manual: Includes
and Autodocs for details about each call.

                   Table 26-2: Exec Interrupt Functions
  ________________________________________________________________________
 |                                                                        |
 | Interrupt Function                Description                          |
 |========================================================================|
 |  AddIntServer()  Add an interrupt server to a system server chain.     |
 |         Cause()  Cause a software interrupt.                           |
 |       Disable()  Disable interrupt processing.                         |
 |        Enable()  Restart system interrupt processing.                  |
 |  RemIntServer()  Remove an interrupt server from a system server chain.|
 |  SetIntVector()  Set a new handler for a system interrupt vector.      |
 |________________________________________________________________________|


Amiga® RKM Libraries: 27 Graphics Primitives

 Introduction                       User Copper Lists
 Display Routines and Structures    ECS and Genlocking Features
 Advanced Topics                    Function Reference
 Drawing Routines


27 Graphics Primitives / Introduction

This chapter describes the basic graphics functions available to Amiga
programmers.  It covers the graphics support structures, display routines
and drawing routines.  Many of the operations described in this section
are also performed by the Intuition software.  See the Intuition chapters
for more information.

The Amiga supports several basic types of graphics routines: display
routines, drawing routines, sprites and animation.  These routines are
very versatile and allow you to define any combination of drawing and
display areas you may wish to use.

The first section of this chapter defines the display routines.  These
routines show you how to form and manipulate a display, including the
following aspects of display use:

  * How to query the graphics system to find out what type of video
    monitor is attached and which graphics modes can be displayed on
    it.

  * How to identify the memory area that you wish to have displayed.

  * How to position the display area window to show only a certain
    portion of a larger drawing area.

  * How to split the screen into as many vertically stacked slices
    as you wish.

  * How to determine which horizontal and vertical resolution modes
    to use.

  * How to determine the current correct number of pixels across and
    lines down for a particular section of the display.

  * How to specify how many color choices per pixel are to be
    available in a specific section of the display.

The later sections of the chapter explain all of the available modes of
drawing supported by the system software, including how to do the
following:

  * Reserve memory space for use by the drawing routines.

  * Define the colors that can be drawn into a drawing area.

  * Define the colors of the drawing pens (foreground pen,
    background pen for patterns, and outline pen for area-fill
    outlines).

  * Define the pen position in the drawing area.

  * Drawing primitives; lines, rectangles, circles and ellipses.

  * Define vertex points for area-filling, and specify the area-fill
    color and pattern.

  * Define a pattern for patterned line drawing.

  * Change drawing modes.

  * Read or write individual pixels in a drawing area.

  * Copy rectangular blocks of drawing area data from one drawing
    area to another.

  * Use a template (predefined shape) to draw an object into a
    drawing area.

 Components of a Display
 Introduction To Raster Displays
 Interlaced and Non-Interlaced Modes
 Low, High and Super-High Resolution Modes
 About ECS
 Forming an Image
 Role of the Copper (Coprocessor)


27 / Introduction / Components of a Display

In producing a display, you are concerned with two primary components:
sprites and the playfield.  Sprites are the easily movable parts of the
display.  The playfield is the static part of the display and forms a
backdrop against which the sprites can move and with which the sprites can
interact.

This chapter covers the creation of the background.  Sprites are described
in the "Graphics Sprites, Bobs and Animation" chapter.


27 / Introduction / Introduction To Raster Displays

There are three major television standards in common use around the world:
NTSC, PAL, and SECAM.  NTSC is used primarily in the United States and
Japan; PAL and SECAM are used primarily in Europe.  The Amiga currently
supports both NTSC and PAL.  The major differences between the two systems
are refresh frequency and the number of scan lines produced.  Where
necessary, the differences will be described and any special
considerations will be mentioned.

The Amiga produces its video displays on standard television or video
monitors by using raster display techniques.  The picture you see on the
video display screen is made up of a series of horizontal video lines
stacked one on top of another, as illustrated in the following figure.
Each line represents one sweep of an electronic video beam, which "paints"
the picture as it moves along.  The beam sweeps from left to right,
producing the full screen one line at a time.  After producing the full
screen, the beam returns to the top of the display screen.

     Figure 27-1: How the Video Display Picture Is Produced

The diagonal lines in the figure show how the video beam returns to the
start of each horizontal line.

 Effect of Display Overscan on the Viewing Area
 Color Information for the Video Lines


27 / / / Effect of Display Overscan on the Viewing Area

To assure that the picture entirely fills the monitor (or television)
screen, the manufacturer of the video display device usually creates a
deliberate overscan.  That is, the video beam is swept across an area that
is larger than the viewable region of the monitor.

The video beam actually covers 262 vertical lines (312 for PAL).  The
user, however, sees only the portion of the picture that is within the
center region of the display, typically surrounded by a border as
illustrated in the figure below.  The center region is nominally about 200
lines high on an NTSC machine (256 lines for PAL).  Overscan also limits
the amount of video data that can appear on each display line.  The width
of the center region is nominally, about 320 pixels for both PAL and NTSC.

        ___________________
       |                   |
       |       ____________|____________
       |      |           \|/           |
       |      |·························|
       |      |- - - - - - - - - - - - -|   Overscan Region
       |      |- -*******************- -| / ---------------
       |      |- -*- - - - - - - - -*- -|/  Generally Graphics are
       |      |- -*- - - - - - - - -*- -/   not displayed in this area
       |      |   *                 *  /|
              |   *                 *   |
   Vertical   |   *                 *\  |
   Blanking   |   *                 * \ |
   Interval   |   *                 *  \|
              |   *                 *   \
       |      |   *                 *   |\
       |      |- -*- - - - - - - - -*- -| \ Viewable Region
       |      |- -*- - - - - - - - -*- -|   ---------------
       |      |- -*******************- -|   Contains approximately
       |      |- - - - - - - - - - - - -|   200 video lines (256 PAL)
       |      |·························|   and 320 pixels across.
       |      |____________|____________|
       |                   |
       |___________________|

       Figure 27-2: Display Overscan Restricts Usable Picture Area

The flexibility of the Amiga graphics subsystem allows the overscan
region, which normally forms the border of the display, to be used for
application graphics instead.  So the nominal dimensions given above can
be enlarged.

The time during which the video beam is below the bottom line of the
viewable region and above the first line is called the vertical blanking
interval.  The recommended minimum to allow for this interval is 21 lines
for NTSC (29 lines for PAL).  So, for applications that take full
advantage of the overscan area, a maximum of 241 usable lines in NTSC (283
in PAL) can be achieved.  The display resolution can also be changed by
changing the Amiga display mode as discussed in the sections below.


27 / / / Color Information for the Video Lines

The hardware reads the system display memory to obtain the color
information for each line.  As the video display beam sweeps across the
screen producing the display line, it changes color, producing the images
you have defined.  On the current generation of Amiga hardware, there are
4,096 possible colors.


27 / Introduction / Interlaced and Non-Interlaced Modes

In producing the complete display (262 lines in NTSC, 312 in PAL), the
video display device produces the top line, then the next lower line, then
the next, until it reaches the bottom of the screen.  When it reaches the
bottom, it returns to the top to start a new scan of the screen.  Each
complete set of lines is called a display field.  It takes about 1/60th of
a second to produce a complete NTSC display field (1/50th of a second for
PAL).

The Amiga has two vertical display modes: interlaced and non-interlaced.
In non-interlaced mode, the video display produces the same picture for
each successive display field.  A non-interlaced NTSC display normally has
about 200 lines in the viewable area (up to a maximum of 241 lines with
overscan) while a PAL display will normally show 256 lines (up to a
maximum of 283 with overscan).

With interlaced mode, the amount of information in the viewable area can
be doubled.  On an NTSC display this amounts to 400 lines (482 with
overscan), while on a PAL display it amounts to 512 lines (566 with
overscan).

For interlaced mode, the video beam scans the screen at the same rate
(1/60th of a second per complete NTSC video display field); however, it
takes two display fields to form a complete video display picture and
twice as much display memory to store line data.  During the first of each
pair of display fields, the system hardware shows the odd-numbered lines
of an interlaced display (1, 3, 5, and so on).  During the second display
field, it shows the even-numbered lines (2, 4, 6 and so on).  The second
field is positioned slightly lower so that the lines in the second field
are "interlaced" with those of the first field, giving the higher vertical
resolution of this mode.

                 _______________________________________
                |                                       |
                |  Data as Displayed     Data In Memory |
                |  -----------------     -------------- |
                | Odd field - Line 1        Line 1      |
                | Even field - Line 1       Line 2      |
                | Odd field - Line 2        Line 3      |
                | Even field - Line 2       Line 4      |
                |           ·                  ·        |
                |           ·                  ·        |
                |           ·                  ·        |
                | Odd field - Line 200      Line 399    |
                | Even field - Line 200     Line 400    |
                |_______________________________________|

    Figure 27-3: Interlaced Mode -- Display Fields and Data in Memory

The following figure shows a display formed as display lines 1, 2, 3, 4,
... 400.  The 400-line interlaced display uses the same physical display
area as a 200-line non-interlaced display.

           _____________________
  line 1 _|_____________________|_
          |_____________________| \
          |      _________      |  \
          |      _________      |   \
          |                     |    \
          |      Odd Field      |     \   _____________________
          |      _________      |      \_|_____________________|_ Line 1
          |      _________      |       _|_|___________________|_ Line 2
          |_____________________|      / |                     |
          |_____________________|     /  | |                   |
          |_____________________|    /   |    Video Display    |
                                    /    | | (400 lines NTSC   |
           _____________________   /     |    512 lines PAL)   |
  line 2 _|_____________________|_/      | |                   |
          |_____________________|        |                     |
          |      _________      |        |\|/                  |
          |      _________      |        |_____________________|
          |                     |
          |      Even Field     |      Same physical space as used
          |      _________      |       by a 200-line (256) PAL),
          |      _________      |         noninterlaced display.
          |_____________________|
          |_____________________|
          |_____________________|

         Figure 27-4: Interlaced Mode Doubles Vertical Resolution

During an interlaced display, it appears that both display fields are
present on the screen at the same time and form one complete picture.
However, interlaced displays will appear to flicker if adjacent (odd and
even) scan lines have contrasting brightness.  Choosing appropriate colors
for your display will reduce this flicker considerably.  This phenomenon
can also be reduced by using a long-persistence monitor, or alleviated
completely with a hardware de-interlacer.


27 / Introduction / Low, High and Super-High Resolution Modes

The Amiga also has three horizontal display modes: low-resolution (or
Lores), high-resolution (Hires) and super-high-resolution (SuperHires).

Normally, these three horizontal display modes have a width of 320 for
Lores, 640 for Hires or 1280 for SuperHires on both PAL and NTSC machines.
However, by taking full advantage of the overscan region, it is possible
to create dispays up to 362 pixels wide in Lores mode, 724 pixels wide in
Hires or 1448 pixels wide in SuperHires.  Usually, however, you should use
the standard values (320, 640 or 1280) for most applications.

In general, the number of colors available in each display mode decreases
as the resolution increases.  The Amiga has two special display modes that
can be used to increase the number of colors available.  HAM is
Hold-And-Modify mode, EHB is Extra-Half-Brite mode.

Hold-And-Modify (HAM) allows you to display the entire palette of 4,096
colors on-screen at once with certain restrictions, explained later.

Extra-Half-Brite allows for 64 colors on-screen at once; 32 colors plus 32
additional colors that are half the intensity of the first 32.  For
example, if color 1 is defined as 0xFFF (white), then color 33 is 0x777
(grey).

 Display Modes, Colors, and Requirements


27 / / Resolution Modes / Display Modes, Colors, and Requirements

The following chart lists all of the display modes that are available
under Release 2 of the Amiga operating system, as well as those available
under previous releases of the OS.

    15 kHz Amiga            Default Resolution     Maximum   Supports
    Display Modes             NTSC      PAL        Colors    HAM/EHB
    -------------             ----      ---        -------   --------
    Lores                   320x200   320x256    32 of 4096    Yes
    Lores-Interlaced        320x400   320x512    32 of 4096    Yes
    Hires                   640x200   640x256    16 of 4096    No
    Hires-Interlaced        640x400   640x512    16 of 4096    No
    SuperHires*             1280x200  1280x256   4 out of 64   No
    SuperHires-Interlaced*  1280x400  1280x512   4 out of 64   No

    *Requires both Release 2 and ECS.

    31 kHz Amiga               Default         Maximum       Supports
    Display Modes*            Resolution       Colors        HAM/EHB
    --------------            ----------       -------       --------
    VGA-ExtraLores             160x480      32 out of 4096     Yes
    VGA-ExtraLores-Interlace   160x960      32 out of 4096     Yes
    VGA-Lores                  320x480      16 out of 4096     No
    VGA-Lores-Interlace        320x960      16 out of 4096     No
    Productivity               640x480      4 out of 64        No
    Productivity-Interlace     640x960      4 out of 64        No

    *31 kHz modes require Release 2, ECS and either a bi-scan or
    multi-scan monitor.

      A2024*         Default Resolution             Maximum
   Display Modes      NTSC         PAL              Colors
   -------------      ----         ---              -------
    A2024-10Hz      1008x800    1008x1024     4 out of 4 grey levels
    A2024-15Hz      1008x800    1008x1024     4 out of 4 grey levels

    *A2024 modes require special hardware and either Release 2 or
    special software available from the monitor's manufacturer.


27 / Introduction / About ECS

ECS stands for Enhanced Chip Set, the latest version of the Amiga's custom
chips that provides for improved graphics capabilities.  Some of the
special features of the Amiga's graphics sub-system such as the VGA,
Productivity and SuperHires display modes require the ECS.

 SuperHires (35 nanosecond) Pixel Resolutions
 Productivity Mode
 Selectable PAL/NTSC
 Determining Chip Versions


27 / / About ECS / SuperHires (35 nanosecond) Pixel Resolutions

The enhanced version of the Denise chip can generate SuperHires pixels
that are twice as fine as Hires pixels.  It is convenient to refer to
pixels here by their speed, rather than width, for reasons that will be
explained below.  They are approximately 35nS long, while Hires are 70nS,
and Lores 140nS.  In the absence of any other features, this can bring a
new mode with nominal dimensions of 1280 x 200 (NTSC) or 1280 x 256 (PAL).
This mode requires the ECS Agnus chip as well.

When Denise is generating these new fast pixels, simple bandwidth
arithmetic indicates that at most two bitplanes can be supported.  Also
note that with two bitplanes, DMA bandwidth is saturated.  The palette for
SuperHires pixels is also restricted to 64 colors.


27 / / About ECS / Productivity Mode

The enhanced version of the Denise chip can support monitor horizontal
scan frequencies of 31KHz, twice the old 15.75KHz rate.  This provides
over 400 non-interlaced horizontal lines in a frame, but requires the use
of a multiple scan rate, or multi-sync monitor.

This effect speeds up the video beam roughly by a factor of two, which has
the side effect of doubling the width of a pixel emitted at a given speed.
Thus, for a given Denise mode, pixels are twice as fat, and there are half
as many on a given line.

The increased scan rate interacts with all of the Denise modes.  So with
both SuperHires (35nS) pixels and the double scan rate the display
generated would be 640 pixels wide by more than 400 rows, non-interlaced,
with up to four colors from a palette of 64.  This combination is termed
Productivity mode, and the default international height is 480 rows. This
conforms, in a general way, to the VGA Mode 3 Standard 8514/A.

The support in Agnus is actually more flexible, and gives the ability to
conform to special-purpose modes, such as displays synchronized to motion
picture cameras.


27 / / About ECS / Selectable PAL/NTSC

The Enhanced Chip Set can be set to NTSC or PAL modes under software
control.  Its initial default behavior is determined by a jumper or trace
on the system motherboard.  This has no bearing on Productivity mode and
other programmable scan operations, but the new system software can
support displays in either mode.


27 / / About ECS / Determining Chip Versions

It is possible to ascertain whether the ECS chips are in the machine at
run time by looking in the ChipRevBits0 field of the GfxBase structure.
If this field contains the flag for the chip you are interested in (as
defined in the <gfxbase.h> include file), then that chip is present.

For example, if the C statement (GfxBase->ChipRevBits0 & GFXF_HR_AGNUS)
evaluates to non-zero, then the machine contains the ECS version of the
Agnus chip and has advanced features such as the ability to handle larger
rasters.  Older Agnus chips were capable of handling rasters up to 1,024
by 1,024 pixels.  The ECS Agnus can handle rasters up to 16,384 by 16,384
pixels.

If (GfxBase->ChipRevBits0 & GFXF_HR_DENISE) is non-zero, then the ECS
version of the Denise chip is present.  Having both the ECS Agnus and ECS
Denise present allows for the special SuperHires, VGA and Productivity
display modes available in Release 2.  For more information on ECS and the
custom chips, refer to the Amiga Hardware Reference Manual.


27 / Introduction / Forming an Image

To create an image, you write data (that is, you "draw") into a memory
area in the computer.  From this memory area, the system can retrieve the
image for display.  You tell the system exactly how the memory area is
organized, so that the display is correctly produced.  You use a block of
memory words at sequentially increasing addresses to represent a
rectangular region of data bits.  The following figure shows the contents
of three example memory words: 0 bits are shown as blank rectangles, and
1 bits as filled-in rectangles.

                   Contents of three memory words,
                     all adjacent to each other.
             Note that N is expressed as a byte-address.

                   _______________________________
                  |_|_|_|_|_|_|_|#|#|_|_|_|_|_|_|_|

                      Memory Location N (0x0180)

                   _______________________________
                  |_|_|_|_|_|#|#|#|#|#|#|_|_|_|_|_|

                     Memory Location N+2 (0x07E0)

                   _______________________________
                  |_|_|_|_|_|_|_|#|#|_|_|_|_|_|_|_|

                     Memory Location N+4 (0x0180)

                  Figure 27-5: Sample Memory Words

The system software lets you define linear memory as rectangular regions,
called bitplanes.  The figure below shows how the system would organize
three sequential words in memory into a rectangular bitplane with
dimensions of 16 x 3 pixels.

          _______________________________
         |_|_|_|_|_|_|_|#|#|_|_|_|_|_|_|_|  Memory Location N
         |_|_|_|_|_|#|#|#|#|#|#|_|_|_|_|_|  Memory Location N+2
         |_|_|_|_|_|_|_|#|#|_|_|_|_|_|_|_|  Memory Location N+4

       Figure 27-6: A Rectangular Bitplane Made from 3 Memory Words

The following figure shows how 4,000 words (8,000 bytes) of memory can be
organized to provide enough bits to define a single bitplane of a
full-screen, low-resolution video display (320 x 200).

  _______________________________         _______________________________
 |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| ----> |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|

         Memory Location N                     Memory Location N+38
  _______________________________         _______________________________
 |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| ----> |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|

       Memory Location N+40          |         Memory Location N+78
                                     |
                                     |
                                    \|/
  _______________________________         _______________________________
 |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| ----> |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|

      Memory Location N+7960                  Memory Location N+7998

      Figure 27-7: Bitplane for a Full-screen, Low-resolution Display

Each memory data word contains 16 data bits. The color of each pixel on a
video display line is directly related to the value of one or more data
bits in memory, as follows:

  * If you create a display in which each pixel is related to only
    one data bit, you can select from only two possible colors,
    because each bit can have a value of only 0 or 1.

  * If you use two bits per pixel, there is a choice of four
    different colors because there are four possible combinations of
    the values of 0 and 1 from each of the two bits.

  * If you specify three, four, or five bits per pixel, you will
    have eight, sixteen, or thirty-two possible choices of a color
    for a pixel.

  * If you use six bits per pixel, then depending on the video mode
    (EHB or HAM), you will have sixty-four or 4,096 possible choices
    for a pixel.

To create multicolored images, you must tell the system how many bits are
to be used per pixel. The number of bits per pixel is the same as the
number of bitplanes used to define the image.

As the video beam sweeps across the screen, the system retrieves one data
bit from each bitplane. Each of the data bits is taken from a different
bitplane, and one or more bitplanes are used to fully define the video
display screen. For each pixel, data-bits in the same x,y position in each
bitplane are combined by the system hardware to create a binary value.
This value determines the color that appears on the video display for that
pixel.

      _______________
     |
     | ‘          bit-plane 5
     | _\_____________
     ||  \
     || ‘ \        bit-plane 4
      | _\_\_____________
      ||  \ \
      || ‘ \ \      bit-plane 3
       | _\_\_\___________                   Bits from
       ||  \ \ \                               planes     Color
       || ‘ \ \ \    bit-plane 2             5,4,3,2,1  Registers
        | _\_\_\_\__________
        ||  \ \ \ \                                     _________
        || ‘ \ \ \ \  bit-plane 1              00000   |_________|
         | ^\ \ \ \ \                          00001   |_________|
         | | \ \ \ \ \                         00010   |_________|
         | |  \ \ \ \ \                        00011   |_________|
           |   \ \ \ \ \  ___  _ _ _ _ _       00100   |_________|
           |    \ \ \ \ \|   |          |        -     |         |
          One    \ \ \ \ | 1 |                   -     |    |    |
         Pixel    \ \ \ \|___|          |        -     |         |
                   \ \ \ \|   |                  -     |    |    |
                    \ \ \ | 1 |         |        -     |         |
                     \ \ \|___|                  -     |   \|/   |
                      \ \ \|   |        |    \   -     |_________|
                       \ \ | 0 |         - - - 11000   |#########|
                        \ \|___|        |    / 11001   |_________|
                         \ \|   |              11010   |_________|
                          \ | 0 |       |      11011   |_________|
                           \|___|              11100   |_________|
                            \|   |      |      11101   |_________|
                             | 0 |             11110   |_________|
                             |___| _ _ _|      11111   |_________|

        Figure 27-8: Bits from Each Bitplane Select Pixel Color

You will find more information showing how the data bits actually select
the color of the displayed pixel in the section below called
"ViewPort Color Selection."


27 / Introduction / Role of the Copper (Coprocessor)

The Amiga has a special-purpose coprocessor, called the Copper, that can
control nearly the entire graphics system.  The Copper can control
register updates, reposition sprites, change the color palette, and update
the blitter.  The graphics and animation routines use the Copper to set up
lists of instructions for handling displays, and advanced programmers can
create their own custom Copper lists.


27 Graphics Primitives / Display Routines and Structures

    CAUTION:
    --------
    This section describes the lowest-level graphics interface to the
    system hardware.  If you use any of the routines and the data
    structures described in these sections, your program will essentially
    take over the entire display.  In general, this is not compatible
    with Intuition's multiwindow operating environment since Intuition
    calls these low-level routines for you.

The descriptions of the display routines, as well as those of the drawing
routines, occasionally use the same terminology as that in the Intuition
chapters.  These routines and data structures are the same ones that
Intuition software uses to produce its displays.

The computer produces a display from a set of instructions you define.
You organize the instructions as a set of parameters known as the View
structure (see the <graphics/view.h> include file for more information).
The following figure shows how the system interprets the contents of a
View structure.  This drawing shows a complete display composed of two
different component parts, which could (for example) be a low-resolution,
multicolored part and a high-resolution, two-colored part.

                                VIDEO DISPLAY
                          _________________________
                         |                         |
                         |  _____________________  |
                         | |                     | |
                         | |                     | |
                         | |                     | |
                         | |     ViewPort #1     | |
                         | |                     | |   Background color
                         | |                     | | / shows here
                         | |_____________________| |/
                         |    _________________    /
                         |  /|                 |  /|
                         | / |                 | / |
                         |/  |                 |   |
                         /   |   ViewPort #2   |   |
                        /|   |                 |   |
     ViewPorts must be / |   |                 |   |
       seperated by at   |   |_________________|   |
  least one blank line   |                         |
      (sometimes more).  |_________________________|

                        A complete display is composed
                          of one or more "ViewPorts"

            Figure 27-9: The Display Is Composed of ViewPorts

A complete display consists of one or more ViewPorts, whose display
sections are vertically separated from each other by at least one blank
scan line (non-interlaced). (If the system must make many changes to the
display during the transition from one ViewPort to the next, there may be
two or more blank scanlines between the ViewPorts.) The viewable area
defined by each ViewPort is rectangular. It may be only a portion of the
full ViewPort, it may be the full ViewPort, or it may be larger than the
full ViewPort, allowing it to be moved within the limits of its
DisplayClip. You are essentially defining a display consisting of a number
of stacked rectangular areas in which separate sections of graphics
rasters can be shown.

 Limitations on the Use of Viewports
 Characteristics of a Viewport
 Viewport Size Specifications
 Viewport Color Selection
 Viewport Display Modes
 Viewport Display Memory
 Forming a Basic Display
 Loading and Displaying the View
 Monitors, Modes and the Display Database


27 / Display Routines and Structures / Limitations on Use of Viewports

The system software for defining ViewPorts allows only vertically stacked
fields to be defined. The following figure shows acceptable and
unacceptable display configurations.

                                     \\\\                   ////
       _________________________      \\\\_________________////
      |                         |    |                         |
      |  _____________________  |    |  _____________________  |
      | |                     | |    | |                     | |
      | |                     | |    | |                     | |
      | |                     | |    | |                     | |
      | |                     | |    | |                     | |
      | |_____________________| |    | |_____________________| |
      |   ___________________   |    | |                     | |
      |  |                   |  |    | |                     | |
      |  |                   |  |    | |                     | |
      |  |                   |  |    | |                     | |
      |  |___________________|  |    | |_____________________| |
      |  _____________________  |    | |                     | |
      | |                     | |    | |                     | |
      | |                     | |    | |                     | |
      | |                     | |    | |                     | |
      | |_____________________| |    | |_____________________| |
      |                         |    |                         |
      |_________________________|    |_________________________|
                                      ////                 \\\\
              ACCEPTABLE             ////     INCORRECT     \\\\
              ----------                      ---------
                                     (Does not use at least one
                                    blank line between ViewPorts)

      \\\\                   ////    \\\\                   ////
       \\\\_________________////      \\\\_________________////
      |                         |    |                         |
      |  _____________________  |    |  _________   _________  |
      | |                     | |    | |         | |         | |
      | |                     | |    | |         | |         | |
      | |                     | |    | |         | |         | |
      | |     ___________     | |    | |         | |         | |
      | |    |           |    | |    | |         | |         | |
      | |____|           |____| |    | |         | |         | |
      |      |           |      |    | |         | |         | |
      |      |           |      |    | |         | |         | |
      |  ____|           |____  |    | |         | |         | |
      | |    |           |    | |    | |         | |         | |
      | |    |___________|    | |    | |         | |         | |
      | |                     | |    | |         | |         | |
      | |                     | |    | |         | |         | |
      | |                     | |    | |         | |         | |
      | |_____________________| |    | |_________| |_________| |
      |                         |    |                         |
      |_________________________|    |_________________________|
       ////                 \\\\      ////                 \\\\
      ////     INCORRECT     \\\\    ////     INCORRECT     \\\\
               ---------                      ---------
       (Cannot have overlapping        (Cannot create multiple
               ViewPorts)               horizontal ViewPorts)

        Figure 27-10: Correct and Incorrect Uses of ViewPorts

A ViewPort is related to the custom screen option of Intuition. In a
custom screen, you can split the screen into slices as shown in the
"correct" illustration of the above figure. Each custom screen can have
its own set of colors, use its own resolution, and show its own display
area.


27 / Display Routines and Structures / Characteristics of a Viewport

To describe a ViewPort fully, you need to set the following parameters:
height, width, depth and display mode.

In addition to these parameters, you must tell the system the location in
memory from which the data for the ViewPort display should be retrieved
(by associating with it a BitMap structure) and how to position the final
ViewPort display on the screen. The ViewPort will take on the user's
default Workbench colors unless otherwise instructed with a ColorMap.  See
the section called "Preparing the ColorMap Structure" for more information.


27 / Display Routines and Structures / Viewport Size Specifications

The following figure illustrates that the variables DHeight, and DWidth
specify the size of a ViewPort.

                     DISPLAY BIT-PLANES
                  _________________________
                 |                         |
                 |  _____________________  |
                 | |                     | |
                 | |                     | |
                 | |                     | |
                 | |                     | |
                 | |                     | |
                 | |_____________________| |
                 |   __________________ _ _|_ _ _ _ _ _
                 |  |                  |   |       |
                 |  |                  |   |       |
                 |  |                  |   |
                 |  |                  |   |   DHeight = how
                 |  |                  |   |  many lines tall
                 |  |                  |   |
                 |  |                  |   |       |
                 |  |__________________|_ _|_ _ _ _|_ _
                 |                         |
                 |__|__________________|___|

                    |                  |

                    |-- DWidth = how --|
                      many pixels wide
                    |                  |

         Figure 27-11: Size Definition for a ViewPort

 ViewPort Height    ViewPort Width


27 / / Viewport Size Specifications / ViewPort Height

The DHeight field of the ViewPort structure determines how many video
lines will be reserved to show the height of this display segment.  The
size of the actual segment depends on whether you define a non-interlaced
or an interlaced display.  An interlaced ViewPort displays twice as many
lines as does a non-interlaced ViewPort in the same physical height.

For example, a complete View consisting of two ViewPorts might be defined
as follows:

  * ViewPort 1 is 150 lines, high-resolution mode (uses the top
    three-quarters of the display).

  * ViewPort 2 is 49 lines of low-resolution mode (uses the bottom
    quarter of the display and allows the space for the required
    blank line between ViewPorts).

Initialize the height directly in DHeight.  Nominal height for a
non-interlaced display is 200 lines for NTSC, 256 for PAL.  Nominal height
for an interlaced display is 400 lines for NTSC, 512 for PAL.

To set your ViewPort to the maximum supported (displayable) height, use
the following code fragment (this requires Release 2):

    struct DimensionInfo querydims;
    struct Rectangle *oscan;
    struct ViewPort viewport;

    if (GetDisplayInfoData( NULL,(UBYTE *)&querydims,
                            sizeof(struct DimensionInfo),
                            DTAG_DIMS, modeID ))
    {
            /* Use StdOScan instead of MaxOScan to get standard   */
            /* overscan dimensions as set by the user in Overscan */
            /* Preferences                                        */
            oscan = &querydims.MaxOScan;
            viewPort->DHeight = oscan->MaxY - oscan->MinY + 1;
    }


27 / / Viewport Size Specifications / ViewPort Width

The DWidth variable in the ViewPort structure determines how wide, in
pixels, the display segment will be.  To set your ViewPort to the maximum
supported (displayable) NTSC high-resolution width, use the following
fragment (this requires Release 2):

    struct DimensionInfo querydims;
    struct Rectangle *oscan;
    struct ViewPort viewport;

    /* Use PAL_MONITOR_ID instead of NTSC_MONITOR_ID to get PAL   */
    /* dimensions                                                 */
    if (GetDisplayInfoData( NULL,(UBYTE *)&querydims, sizeof(querydims),
        DTAG_DIMS, NTSC_MONITOR_ID|HIRES_KEY ))
    {
            /* Use StdOScan instead of MaxOScan to get standard   */
            /* overscan dimensions as set by the user in Overscan */
            /* Preferences                                        */
            oscan = &querydims.MaxOScan;
            viewPort->DWidth = oscan->MaxX - oscan->MinX + 1;
    }

You may specify a smaller value of pixels per line to produce a narrower
display segment or simply set ViewPort.DWidth to the nominal value for
this resolution.

Although the system software allows you define low-resolution displays as
wide as 362 pixels and high-resolution displays as wide as 724 pixels, you
should use caution in exceeding the normal values of 320 or 640,
respectively.  Because display overscan varies from one monitor to
another, many video displays will not be able to show all of a wider
display, and sprite display may also be affected.  However, if you use the
standard overscan values (DimensionInfo.StdOScan) provided by the Release
2 function GetDisplayInfoData() as shown above, the user's preference for
the size of the display will be satisfied.

If you are using hardware sprites or VSprites with your display, and you
specify ViewPort widths exceeding 320 or 640 pixels (for low or
high-resolution, respectively), it is likely that some hardware sprites
will not be properly rendered on the screen. These sprites may not be
rendered because playfield DMA (direct memory access) takes precedence
over sprite DMA when an extra-wide display is produced.  See the Amiga
Hardware Reference Manual for a more complete description of this
phenomenon.


27 / Display Routines and Structures / Viewport Color Selection

The maximum number of colors that a ViewPort can display is determined by
the depth of the BitMap that the ViewPort displays. The depth is specified
when the BitMap is initialized. See the section below called
"Preparing the BitMap Structure."

Depth determines the number of bitplanes used to define the colors of the
rectangular image you are trying to build (the raster image) and the
number of different colors that can be displayed at the same time within a
ViewPort. For any single pixel, the system can display any one of 4,096
possible colors.

The following table shows depth values and the corresponding number of
possible colors for each value.

    Table 27-1: Depth Values and Number of Colors in the ViewPort

          Colors    Depth Value
          ------    -----------
              2          1
              4          2
              8          3         (Note 1)
             16          4         (Notes 1,2)
             32          5         (Notes 1,2,3)
             16          6         (Notes 1,4)
             64          6         (Notes 1,2,3,5)
          4,096          6         (Notes 1,2,3,6)

        Notes:
        1. Not available for SUPERHIRES.
        2. Single-playfield mode only - DUALPF not one of the
           ViewPort's attributes.
        3. Low-resolution mode only - neither HIRES nor
           SUPERHIRES one of the ViewPort attributes.
        4. Dual Playfield mode - DUALPF is an attribute of this
           ViewPort.  Up to eight colors (in three planes) for
           each playfield.
        5. Extra-Half-Brite mode - EXTRA_HALFBRITE is an
           attribute of this ViewPort.
        6. Hold-And-Modify mode only - HAM is an attribute of
           this ViewPort.

The color palette used by a ViewPort is specified in a ColorMap. See the
section called "Preparing the ColorMap" for more information.

Depending on whether single- or dual-playfield mode is used, the system
will use different color register groupings for interpreting the on-screen
colors. The table below details how the depth and the different ViewPort
modes affect the registers the system uses.

      Table 27-2: Color Registers Used in Single-playfield Mode

                        Color
           Depth   Registers Used
           -----   --------------
             1          0,1
             2          0-3
             3          0-7
             4          0-15
             5          0-31
             6          0-31       (if EXTRA_HALFBRITE is an
                                    attribute of this ViewPort.)

             6          0-15       (if HAM is an attribute of
                                    this ViewPort.)

The following table shows the five possible combinations when DUALPF is an
attribute of the ViewPort.

        Table 27-3: Color Register Used in Dual-playfield Mode

       Depth       Color	   Depth       Color
           (PF-1)    Registers     (PF-2)    Registers
           ------    ---------     ------    ---------
             1          0,1          1          8,9
             2          0-3          1          8,9
             2          0-3          2          8-11
             3          0-7          2          8-11
             3          0-7          3          8-15


27 / Display Routines and Structures / Viewport Display Modes

The system has many different display modes that you can specify for each
ViewPort.  Under 1.3, the eight constants that control the modes are
DUALPF, PFBA, HIRES, SUPERHIRES, LACE, HAM, SPRITES, and EXTRA_HALFBRITE.
Some, but not all of the modes can be combined in a ViewPort.  HIRES and
LACE combine to make a high-resolution, interlaced ViewPort, but HIRES and
SUPERHIRES conflict, and cannot be combined.

Under 1.3, you set these flags directly in the Modes field during
initialization of the ViewPort.  Under Release 2, there are many more
display modes possible than in 1.3 so a new system of flags and structures
is used to set the mode.  With Release 2, you set the display mode for a
ViewPort by using the VideoControl() function as described in the section
on "Monitors, Modes and the Display Database" later in this chapter.

The DUALPF and PFBA modes are related.  DUALPF tells the system to treat
the raster specified by this ViewPort as the first of two independent and
separately controllable playfields. It also modifies the manner in which
the pixel colors are selected for this raster (see the above table).

When PFBA is specified, it indicates that the second playfield has video
priority over the first one.  Playfield relative priorities can be
controlled when the playfield is split into two overlapping regions.
Single-playfield and dual-playfield modes are discussed below in
"Advanced Topics."

HIRES tells the system that the raster specified by this ViewPort is to be
displayed with (nominally) 640 horizontal pixels, rather than the 320
horizontal pixels of Lores mode.

SUPERHIRES tells the system that the raster specified by this ViewPort is
to be displayed with (nominally) 1280 horizontal pixels.  This can be used
with 31 kHz scan rates to provide the VGA and Productivity modes available
in Release 2.  SUPERHIRES modes require both the ECS and Release 2.   See
the section on "Determining Chip Versions" earlier in this chapter for an
explanation of how to find out if the ECS is present.

LACE tells the system that the raster specified by this ViewPort is to be
displayed in interlaced mode. If the ViewPort is non-interlaced and the
View is interlaced, the ViewPort will be displayed at its specified height
and will look only slightly different than it would look when displayed in
a non-interlaced View (this is handled by the system automatically). See
"Interlaced Mode vs. Non-interlaced Mode" below for more information.

HAM tells the system to use "hold-and-modify" mode, a special mode that
lets you display up to 4,096 colors on screen at the same time. It is
described in the "Advanced Topics" section.

SPRITES tells the system that you are using sprites in this display
(either VSprites or Simple Sprites). The system will load color registers
for the sprites. Note that since the mouse pointer is a sprite, omitting
this mode will prevent the mouse pointer from being displayed when this
ViewPort is frontmost. See the "Graphics Sprites, Bobs and Animation"
chapter for more information about sprites.

EXTRA_HALFBRITE tells the system to use the Extra-Half-Brite mode, a
special mode that allows you to display up to 64 colors on screen at the
same time.  It is described in the "Advanced Topics" section.

If you peruse the <graphics/view.h> include file you will see another
flag, EXTENDED_MODE. Never set this flag yourself; it is used by the
Release 2 system to control more advanced mode features.

Be sure to read the section on "Monitors, Modes and the Display Database"
for additional information about the ViewPort mode and how it has changed
in the Release 2 version of the operating system.

 Single-playfield Mode vs. Dual-playfield Mode
 Low-resolution Mode vs. High-resolution Mode
 Interlaced Mode vs. Non-interlaced Mode


27 / / Viewport Display Modes / Single- vs. Dual-playfield Mode

When you specify single-playfield mode you are asking that the system
treat all bitplanes as part of the definition of a single playfield image.
Each of the bitplanes defined as part of this ViewPort contributes data
bits that determine the color of the pixels in a single playfield.

     Figure 27-12: A Single-playfield Display

If you use dual-playfield mode, you can define two independent, separately
controllable playfield areas as shown on the next page.

     Figure 27-13: A Dual-playfield Display

In the previous figure, PFBA was included in the display mode.  If PFBA
had not been included, the relative priorities would have been reversed;
playfield 2 would have appeared to be behind playfield 1.


27 / / Viewport Display Modes / Low- vs. High-resolution Mode

In LORES mode, horizontal lines of 320 pixels fill most of the ordinary
viewing area.  The system software lets you define a screen segment width
up to 362 pixels in this mode, or you can define a screen segment as
narrow as you desire (minimum of 16 pixels).  In HIRES mode, 640 pixels
fill a horizontal line. In this mode you can specify any width from 16 to
724 pixels. In SUPERHIRES mode, 1280 pixels fill a horizontal line. In
this mode you can specify any width from 16 to 1448 pixels. The fact that
many monitor manufacturers set their monitors to overscan the video
display normally limits you to showing only 16 to 320 pixels per line in
LORES, 16 to 640 pixels per line in HIRES, or 16 to 1280 pixels per line
in SUPERHIRES. Under Release 2, the user can set the monitor's viewable
screen size with the Preferences Overscan editor.

  |   |   |   |   |   |   |   |   |   |   |
  |   |   |   |   |   |   |   |   |   |   |
  |   |   |                       |   |   |
  |   |   |   320 Pixels Across   |   |   |  ViewPort.Modes = 0
  |   |   | width of 352 possible |   |   |
  |   |   |                       |   |   |
  |   |   |   |   |   |   |   |   |   |   |
  |   |   |   |   |   |   |   |   |   |   |

  | | | | | | | | | | | | | | | | | | | | |
  | | | | | | | | | | | | | | | | | | | | |
  | | | | | |                   | | | | | |
  | | | | |   640 Pixels Across   | | | | |  ViewPort.Modes = HIRES
  | | | | | width of 704 possible | | | | |
  | | | | |                       | | | | |
  | | | | | | | | | | | | | | | | | | | | |
  | | | | | | | | | | | | | | | | | | | | |

  |||||||||||||||||||||||||||||||||||||||||
  |||||||||||||||||||||||||||||||||||||||||
  |||||||||||                   |||||||||||
  ||||||||||  1280 Pixels Across  |||||||||  ViewPort.Modes = SUPERHIRES
  ||||||||| width of 1408 possible ||||||||
  ||||||||||                      |||||||||
  |||||||||||||||||||||||||||||||||||||||||
  |||||||||||||||||||||||||||||||||||||||||

    Figure 27-14: How HIRES and SUPERHIRES Affect the Width of Pixels


27 / / Viewport Display Modes / Interlaced vs. Non-interlaced Mode

In interlaced mode, there are twice as many lines available as in
non-interlaced mode, providing better vertical resolution in the same
display area.

  -----------------------------------------
  -----------------------------------------
  ------------                -------------
  ----------- 200 lines define ------------  ViewPort.Modes = 0
  -----------  a full screen   ------------
  ------------                -------------
  -----------------------------------------
  -----------------------------------------

  =========================================
  =========================================
  ============                =============
  =========== 400 lines define ============  ViewPort.Modes = LACE
  ===========  a full screen   ============
  ============                =============
  =========================================
  =========================================

            Figure 27-15: How LACE Affects Vertical Resolution

If the View structure does not specify LACE, and the ViewPort specifies
LACE, only the top half of the ViewPort data will be displayed. If the
View structure specifies LACE and the ViewPort is non-interlaced, the same
ViewPort data will be repeated in both fields.  The height of the ViewPort
display is the height specified in the ViewPort structure. If both the
View and the ViewPort are interlaced, the ViewPort will be built with
double the normal vertical resolution.  That means it will need twice as
much data space in memory as a non-interlaced picture to fill the display.


27 / Display Routines and Structures / Viewport Display Memory

The picture you create in memory can be larger than the screen image that
can be displayed within your ViewPort.  This big picture (called a raster
and represented by the BitMap structure) can have a maximum size dependent
upon the version of the Agnus chip in the Amiga.  The ECS Agnus can handle
rasters up to 16,384 by 16,384 pixels.  Older Agnus chips are limited to
rasters up to 1,024 by 1,024 pixels.  The section earlier in this chapter
on "Determining Chip Versions" explains how to find out which Agnus is
installed.

The example in the following figure introduces terms that tell the system
how to find the display data and how to display it in the ViewPort. These
terms are RHeight, RWidth, RyOffset, RxOffset, DHeight, DWidth, DyOffset
and DxOffset.

     Figure 27-16: ViewPort Data Area Parameters

The terms RHeight and RWidth do not appear in actual system data
structures.  They refer to the dimensions of the raster and are used here
to relate the size of the raster to the size of the display area. RHeight
is the number of rows in the raster and RWidth is the number of bytes per
row times 8.  The raster shown in the figure is too big to fit entirely in
the display area, so you tell the system which pixel of the raster should
appear in the upper left corner of the display segment specified by your
ViewPort.  The variables that control that placement are RyOffset and
RxOffset.

To compute RyOffset and RxOffset, you need RHeight, RWidth, DHeight, and
DWidth.  The DHeight and DWidth variables define the height and width in
pixels of the portion of the display that you want to appear in the
ViewPort.  The example shows a full-screen, low-resolution mode
(320-pixel), non-interlaced (200-line) display formed from the larger
overall picture.

Normal values for RyOffset and RxOffset are defined by the formulas:

    0 < = RyOffset < = (RHeight - DHeight)
    0 < = RxOffset < = (RWidth - DWidth)

Once you have defined the size of the raster and the section of that
raster that you wish to display, you need only specify where to put this
ViewPort on the screen.  This is controlled by the ViewPort variables
DyOffset and DxOffset.  These are offsets relative to the View.DxOffset
and DyOffset. Possible NTSC values for DyOffset range from -23 to +217
(-46 to +434 if the ViewPort is interlaced), PAL values range from -15 to
+267 (-30 to +534 for interlaced ViewPorts).  Possible values for DxOffset
range from -18 to +362 (-36 to +724 if the ViewPort is Hires, -72 to +1448
if SuperHires), when the View is in its default, initialized position.

The parameters shown in the figure above are distributed in the following
data structures:

  * View (information about the whole display) includes the variables
    that you use to position the whole display on the screen.  The View
    structure contains a Modes field used to determine if the whole
    display is to be interlaced or non-interlaced.  It also contains
    pointers to its list of ViewPorts and pointers to the Copper
    instructions produced by the system to create the display you have
    defined.

  * ViewPort (information about this segment of the display) includes the
    values DxOffset and DyOffset that are used to position this portion
    relative to the overall View.  The ViewPort also contains the
    variables DHeight and DWidth, which define the size of this display
    segment; a Modes variable; and a pointer to the local ColorMap.
    Under Release 2, the VideoControl() function and its various tags are
    used to manipulate the ColorMap and ViewPort.Modes.  Each ViewPort
    also contains a pointer to the next ViewPort.  You create a linked
    list of ViewPorts to define the complete display.

  * RasInfo (information about the raster) contains the variables
    RxOffset and RyOffset. It also contains pointers to the BitMap
    structure and to a companion RasInfo structure if this is a dual
    playfield.

  * BitMap (information about memory usage) tells the system where to
    find the display and drawing area memory and shows how this memory
    space is organized, including the display's depth.

You must allocate enough memory for the display you define. The memory you
use for the display may be shared with the area control structures used
for drawing.  This allows you to draw into the same areas that you are
currently displaying on the screen.

As an alternative, you can define two BitMaps.  One of them can be the
active structure (that being displayed) and the other can be the inactive
structure.  If you draw into one BitMap while displaying another, the user
cannot see the drawing taking place. This is called double-buffering of
the display.  See "Advanced Topics" below for an explanation of the steps
required for double-buffering.  Double-buffering takes twice as much
memory as single-buffering because two full displays are produced.

To determine the amount of required memory for each ViewPort for
single-buffering, you can use the following formula.

    #include <graphics/gfx.h>

    /* Depth, Width, and Height get set to something reasonable. */
    UBYTE Depth, Width, Height;

    /* Calculate resulting VP size. */
    bytes_per_ViewPort = Depth * RASSIZE(Width, Height);

RASSIZE() is a system macro attuned to the current design of the system
memory allocation for display rasters.  See the <graphics/gfx.h> include
file for the formula with which RASSIZE() is calculated.

For example, a 32-color ViewPort (depth = 5), 320 pixels wide by 200 lines
high currently uses 40,000 bytes.  A 16-color ViewPort (depth = 4), 640
pixels wide by 400 lines high currently uses 128,000 bytes.


27 / Display Routines and Structures / Forming a Basic Display

Here are the data structures that you need to define to create a basic
display:

    struct View view;               /* These get used in all versions of */
    struct ViewPort viewPort;       /* the OS */
    struct BitMap bitMap;
    struct RasInfo rasInfo;
    struct ColorMap *cm;

    struct ViewExtra *vextra;       /* Extra View data, new in Release 2 */
    struct ViewPortExtra *vpextra;  /* Extra ViewPort data, new in       */
                                    /* Release 2 */
    struct MonitorSpec *monspec;    /* Monitor data needed in Release 2  */
    struct DimensionInfo dimquery;  /* Display dimension data needed in  */
                                    /* Release 2 */

ViewExtra and ViewPortExtra are new data structures used in Release 2 to
hold extended data about their corresponding parent structure.  ViewExtra
contains information about the video monitor being used to render the
View.  ViewPortExtra contains information required for clipping of the
ViewPort.

GfxNew() is used to create these extended data structures and
GfxAssociate() is used to associate the extended data structure with an
appropriate parent structure.  Although GfxAssociate() can associate a
ViewPortExtra structure with a ViewPort, it is better to use
VideoControl() with the VTAG_VIEWPORTEXTRA_SET tag instead.  Keep in mind
that GfxNew() allocates memory for the resulting data structure which must
be returned using GfxFree() before the application exits.  The function
GfxLookUp() will find the address of an extended data structure from the
address of its parent.

 Preparing the View Structure
 Preparing the BitMap Structure
 Preparing the RasInfo Structure
 Preparing the ViewPort Structure
 Preparing the ColorMap Structure
 Creating the Display Instructions


27 / / Forming a Basic Display / Preparing the View Structure

The following code prepares the View structure for further use:

    InitView(&view);      /* Initialize the View.          */
    view.Modes |= LACE;   /* Only interlaced, 1.3 displays */
                          /* require this                  */

For Release 2 applications, a ViewExtra structure must also be created
with GfxNew() and associated with this View with GfxAssociate() as shown
in the example programs RGBBoxes.c and WBClone.c.

    /* Form the ModeID from values in <displayinfo.h> */
    modeID=DEFAULT_MONITOR_ID | HIRESLACE_KEY;

    /* Make the ViewExtra structure */
    if( vextra=GfxNew(VIEW_EXTRA_TYPE) )
        {
        /* Attach the ViewExtra to the View */
        GfxAssociate(&view , vextra);
        view.Modes |= EXTEND_VSTRUCT;

        /* Initialize the MonitorSpec field of the ViewExtra */
        if( monspec=OpenMonitor(NULL,modeID) )
            vextra->Monitor=monspec;
        else
            fail("Could not get MonitorSpec\n");
        }
     else fail("Could not get ViewExtra\n");


27 / / Forming a Basic Display / Preparing the BitMap Structure

The BitMap structure tells the system where to find the display and
drawing memory and how this memory space is organized. The following code
section prepares a BitMap structure, including allocation of memory for
the bitmap.  This is done with two functions, InitBitMap() and
AllocRaster().  InitBitMap() takes four arguments--a pointer to a BitMap
and the depth, width, and height of the desired bitmap.  Once the bitmap
is initialized, memory for its bitplanes must be allocated.  AllocRaster()
takes two arguments--width and height.  Here is a code section to
initialize a bitmap:

    /*  Init BitMap for RasInfo.  */
    InitBitMap(&bitMap, DEPTH, WIDTH, HEIGHT);

    /* Set the plane pointers to NULL so the cleanup routine will know */
    /* if they were used. */
    for(depth=0; depth<DEPTH; depth++)
        bitMap.Planes[depth] = NULL;

    /*  Allocate space for BitMap.  */
    for(depth=0; depth<DEPTH; depth++)
        {
        bitMap.Planes[depth] = (PLANEPTR)AllocRaster(WIDTH, HEIGHT);
        if (bitMap.Planes[depth] == NULL)
            cleanExit(RETURN_WARN);
        }

This code allocates enough memory to handle the display area for as many
bitplanes as the depth you have defined.


27 / / Forming a Basic Display / Preparing the RasInfo Structure

The RasInfo structure provides information to the system about the
location of the BitMap as well as the positioning of the display area as a
window against a larger drawing area. Use the following steps to prepare
the RasInfo structure:

    /* Initialize the RasInfos. */
    rasInfo.BitMap = &bitMap;  /* Attach the corresponding BitMap.       */
    rasInfo.RxOffset = 0;      /* Align upper left corners of display    */
    rasInfo.RyOffset = 0;      /* with upper left corner of drawing area.*/
    rasInfo.Next = NULL;       /* for a single playfield display, there
                                * is only one RasInfo structure present  */

The system may be made to reinterpret the RxOffset and RyOffset values in
a ViewPort's RasInfo structure by calling ScrollVPort() with the address
of the ViewPort. Changing one or both offsets and calling ScrollVPort()
has the effect of scrolling the ViewPort.


27 / / Forming a Basic Display / Preparing the ViewPort Structure

To prepare the ViewPort structure for further use, you call InitVPort()
and initialize certain fields as follows:

    InitVPort(&viewPort);        /* Initialize the ViewPort.             */
    viewPort.RasInfo = &rasInfo; /* The rasInfo must also be initialized */
    viewPort.DWidth  = WIDTH;
    viewPort.DHeight = HEIGHT;

    /* Under 1.3, you should set viewPort.Modes here to select a display
     * mode. Under Release 2, use VideoControl() with VTAG_NORMAL_DISP_SET
     * to select a display mode by attaching a DisplayInfo structure to
     *  the ViewPort.                                                    */

The InitVPort() routine presets certain default values in the ViewPort
structure.  The defaults include:

  * Modes variable set to zero--this means you select a low-resolution
    display.  (To alter this, use VideoControl() with the
    VTAG_NORMAL_DISP_SET tag as explained below.)

  * Next variable set to NULL--no other ViewPort is linked to this one.
    If you want a display with multiple ViewPorts, you must fill in the
    link yourself.

If you want to create a View with two or more ViewPorts you must declare
and initialize the ViewPorts as above.  Then link them together using the
ViewPort.Next field with a NULL link for the ViewPort at the end of the
chain:

    viewPortA.Next = &viewPortB; /* Tell 1st one the address of the 2nd. */
    viewPortB.Next = NULL;       /* There are no others after this one.  */

For Release 2 applications, once a ViewPort has been prepared, a
ViewPortExtra structure must also be created with GfxNew(), initialized,
and associated with the ViewPort via the VideoControl() function.  In
addition, a DisplayInfo for this mode must be attached to the ViewPort.
The fragment below shows how to do this.  For complete examples, refer to
the program listings of RGBBoxes.c and WBClone.c.

struct TagItem vcTags[] =              /* These tags will be passed to   */
{                                      /* the VideoControl() function to */
    { VTAG_ATTACH_CM_SET, NULL },      /* set up the extended ViewPort   */
    { VTAG_VIEWPORTEXTRA_SET, NULL },  /* structures required in Release */
    { VTAG_NORMAL_DISP_SET, NULL },    /* 2. The NULL ti_Data field of   */
    { VTAG_END_CM, NULL }              /* these tags must be filled in   */
};                                     /* before making the call to      */
                                       /* VideoControl().                */

struct DimensionInfo dimquery;  /* Release 2 structure for display size  */
                                /* data */

/* Make a ViewPortExtra and get ready to attach it */
if( vpextra = GfxNew(VIEWPORT_EXTRA_TYPE) )
    {
    vcTags[1].ti_Data = (ULONG) vpextra;

    /* Initialize the DisplayClip field of the ViewPortExtra structure */
    if( GetDisplayInfoData( NULL , (UBYTE *) &dimquery ,
                           sizeof(struct dimquery) , DTAG_DIMS, modeID) )
        {
        vpextra->DisplayClip = dimquery.Nominal;

        /* Make a DisplayInfo and get ready to attach it */
        if( !(vcTags[2].ti_Data = (ULONG) FindDisplayInfo(modeID)) )
            fail("Could not get DisplayInfo\n");
        }
    else fail("Could not get DimensionInfo\n");
    }
else fail("Could not get ViewPortExtra\n");

/* This is for backwards compatibility with, for example,   */
/* a 1.3 screen saver utility that looks at the Modes field */
viewPort.Modes = (UWORD) (modeID & 0x0000ffff);


27 / / Forming a Basic Display / Preparing the ColorMap Structure

When the View is created, Copper instructions are generated to change the
current contents of each color register just before the topmost line of a
ViewPort so that this ViewPort's color registers will be used for
interpreting its display.  To set the color registers you create a
ColorMap for the ViewPort with GetColorMap() and call SetRGB4().  Here are
the steps used in 1.3 to initialize a ColorMap:

    if( view.ColorMap=GetColorMap( 4L ) )
        LoadRGB4((&viewPort, colortable, 4);

Under Release 2, a ColorMap is attached to the View -- usually along with
DisplayInfo and ViewExtra -- by calling the VideoControl() function.

    /*  RGB values for the four colors used.  */
    #define BLACK 0x000
    #define RED   0xf00
    #define GREEN 0x0f0
    #define BLUE  0x00f

    /*  Define some colors in an array of UWORDS.  */
    static UWORD colortable[] = { BLACK, RED, GREEN, BLUE };

    /* Fill the TagItem Data field with the address of the properly
       initialized (including ViewPortExtra) structure to be passed to
       VideoControl().                                                 */
    vc[0].ti_Data = (ULONG)viewPort;

    /* Init ColorMap.  2 planes deep, so 4 entries
       (2 raised to #planes power).                */
    if(cm = GetColorMap( 4L ) )
    {
        /* For applications that must be compatible with 1.3, replace  */
        /* the next 2 lines with: viewPort.ColorMap=cm;                */
        if( VideoControl( cm , vcTags ) )
            fail("Could not attach extended structures\n");

        /*  Change colors to those in colortable.  */
        LoadRGB4(&viewPort, colortable, 4);
    }

    The 4 Is For Bits, Not Entries.
    -------------------------------
    The 4 in the name LoadRGB4() refers to the fact that each of the red,
    green, and blue values in a color table entry consists of four bits.
    It has nothing to do with the fact that this particular color table
    contains four entries. The call GetRGB4() returns the RGB value of a
    single entry of a ColorMap. SetRGB4CM() allows individual control of
    the entries in the ColorMap before or after linking it into the
    ViewPort.

The LoadRGB4() call above could be replaced with the following:

    register USHORT entry;

    /*  Operate on the same four ColorMap entries as above.  */
    for (entry = 0; entry < 4; entry++)
        {
        /* Call SetRGB4CM() with the address of the ColorMap, the entry to
           be changed, and the Red, Green, and Blue values to be stored
           there.
        */
        SetRGB4CM(viewPort.ColorMap, entry,
        /* Extract the three color values from the one colortable entry. */
            ((colortable[entry] & 0x0f00) >> 8),
                ((colortable[entry] & 0x00f0) >> 4),
                    (colortable[entry] & 0x000f));
        }

Notice above how the four bits for each color are masked out and shifted
right to get values from 0 to 15.

    WARNING!
    --------
    It is important to use only the standard system ColorMap-related
    calls to access the ColorMap entries.  These calls will remain
    compatible with recent and future enhancements to the ColorMap
    structure.

You might need to specify more colors in the color map than you think. If
you use a dual playfield display (covered later in this chapter) with a
depth of 1 for each of the two playfields, this means a total of four
colors (two for each playfield). However, because playfield 2 uses color
registers starting from number 8 on up when in dual-playfield mode, the
color map must be initialized to contain at least 10 entries. That is, it
must contain entries for colors 0 and 1 (for playfield 1) and color
numbers 8 and 9 (for playfield 2). Space for sprite colors must be
allocated as well. For Amiga system software version 1.3 and earlier, when
in doubt, allocate a ColorMap with 32 entries, just in case.


27 / / Forming a Basic Display / Creating the Display Instructions

Now that you have initialized the system data structures, you can request
that the system prepare a set of display instructions for the Copper using
these structures as input data. During the one or more blank vertical
lines that precede each ViewPort, the Copper is busy changing the
characteristics of the display hardware to match the characteristics you
expect for this ViewPort. This may include a change in display resolution,
a change in the colors to be used, or other user-defined modifications to
system registers.

Here is the code that creates the display instructions:

    /*  Construct preliminary Copper instruction list.  */
    MakeVPort( &view, &viewPort );

In this line of code, &view is the address of the View structure and
&viewPort is the address of the first ViewPort structure. Using these
structures, the system has enough information to build the instruction
stream that defines your display.

MakeVPort() creates a special set of instructions that controls the
appearance of the display. If you are using animation, the graphics
animation routines create a special set of instructions to control the
hardware sprites and the system color registers. In addition, the advanced
user can create special instructions (called user Copper instructions) to
change system operations based on the position of the video beam on the
screen.

All of these special instructions must be merged together before the
system can use them to produce the display you have designed. This is done
by the system routine MrgCop() (which stands for "Merge Coprocessor
Instructions").  Here is a typical call:

    /* Merge preliminary lists into a real Copper list in the view
       structure.                                                  */
    MrgCop( &view );


27 / Display Routines and Structures / Loading and Displaying the View

To display the View, you need to load it using LoadView() and turn on the
direct memory access (DMA). A typical call is shown below.

    LoadView(&view);

The &view argument is the address of the View structure defined in the
example above.

There are two macros, defined in <graphics/gfxmacros.h>, that control
display DMA: ON_DISPLAY and OFF_DISPLAY. They simply turn the display DMA
control bit in the DMA control register on or off.

If you are drawing to the display area and do not want the user to see
intermediate steps in the drawing, you can turn off the display.  Because
OFF_DISPLAY shuts down the display DMA and possibly speeds up other system
operations, it can be used to provide additional memory cycles to the
blitter or the 68000.  The distribution of system DMA, however, allows
four-channel sound, disk read/write, and a sixteen-color, low-resolution
display (or four-color, high-resolution display) to operate at the same
time with no slowdown (7.1 megahertz effective rate) in the operation of
the 68000.  Using OFF_DISPLAY in a multitasking environment may, however,
be an unfriendly thing to do to the other running processes.  Use
OFF_DISPLAY with discretion.

 A Custom ViewPort Example    Exiting Gracefully


27 / / Loading and Displaying the View / Exiting Gracefully

The preceding sample program provides a way of exiting gracefully with the
cleanup() subroutine.  This function returns to the memory manager all
dynamically-allocated memory chunks.  Notice the calls to FreeRaster() and
FreeColorMap(). These calls correspond directly to the allocation calls
AllocRaster() and GetColorMap() located in the body of the program. Now
look at the calls within cleanup() to FreeVPortCopLists() and
FreeCprList(). When you call MakeVPort(), the graphics system dynamically
allocates some space to hold intermediate instructions from which a final
Copper instruction list is created. When you call MrgCop(), these
intermediate Copper lists are merged together into the final Copper list,
which is then given to the hardware for interpretation. It is this list
that provides the stable display on the screen, split into separate
ViewPorts with their own colors and resolutions and so on.

When your program completes, you must see that it returns all of the
memory resources that it used so that those memory areas are again
available to the system for reassignment to other tasks.  Therefore, if
you use the routines MakeVPort() or MrgCop(), you must also arrange to use
FreeCprList() (pointing to each of those lists in the View structure) and
FreeVPortCopLists() (pointing to the ViewPort that is about to be
deallocated).  If your View is interlaced, you will also have to call
FreeCprList(&view.SHFCprList) because an interlaced view has a separate
Copper list for each of the two fields displayed. Do not confuse
FreeVPortCopLists() with FreeCprList(). The former works on intermediate
Copper lists for a specific ViewPort, the latter directly on a hardware
Copper list from the View.

As a final caveat, notice that when you do free everything, the memory
manager or other programs may immediately change the contents of the freed
memory.  Therefore, if the Copper is still executing an instruction stream
(as a result of a previous LoadView()) when you free that memory, the
display will malfunction. Once another View has been installed via
LoadView(), do a WaitTOF() for the new View to begin displaying, and then
you can begin freeing up your resources.  WaitTOF() waits for the vertical
blanking period to begin and all vertical blank interrupts to complete
before returning to the caller. The routine WaitBOVP() (for
"WaitBottomOfViewPort") busy waits until the vertical beam reaches the
bottom of the specified ViewPort before returning to the caller.  This
means no other tasks run until this function returns.


27 / Routines and Structures / Monitors, Modes and Display Database

The Release 2 graphics library supports a variety of new video monitors,
and new programmable video modes not available in older versions of the
operating system.  Inquiries about the availability of these modes, their
dimensions and currently accessible options can be made through a database
indexed by the same key information used to open Intuition screens.  This
design provides a good degree of compatibility with existing software,
between differently equipped hardware platforms and for both static and
dynamic data storage.

The Release 2 software may be running on A1000 computers which will not
have ECS, on A500 computers which may not have the latest ECS upgrade, and
on A2000 computers which generally have the latest ECS but may not have a
multi-sync monitor currently attached.  This means that there are
compatibility issues to consider--what should happen when a required ECS
or monitor resource is not available for the desired mode.

Here are the compatibility criteria, in a simplified fashion:

Requires Release 2, and ECS Chips only
    SuperHires mode (35nS pixel resolutions).  This allows for very high
    horizontal resolutions with the new ECS chip set and a standard NTSC
    or PAL monitor.  (SuperHires has twice as much horizontal resolution
    as the old Hires mode.)

Requires Release 2, ECS Chips, and appropriate monitor
    Productivity mode.  This allows for flicker-free 640 x 480 color
    displays with the addition of a multi-sync or bi-sync 31 Khz monitor.
    (Productivity mode conforms, in a general way, to the VGA Mode 3
    Standard 8514/A.)

Requires Release 2 (or the V35 of graphics.library under 1.3)
and appropriate monitor only
    A2024 Scan Conversion.  This allows for a very high resolution
    grayscale display, typically 1008x800, suitable for desktop
    publishing or similar applications.  A special video monitor is
    required (the monitor also supports the normal Amiga modes in
    greyscale).

Requires Release 2 but not ECS Chips or appropriate monitor
    Display database inquiries.  This allows for programmers to determine
    if the required resources are currently available for the requested
    mode.

In addition, there are fallback modes (which do not require Release 2)
which resort to some reasonable display when a required resource is not
available.

 New Monitors
 New Modes
 Mode Specification, Screen Interface
 Mode Specification, ViewPort Interface
 Coexisting Modes
 ModeID Identifiers
 The Display Database and the DisplayInfo Record
 Accessing the DisplayInfo
 Mode Availability
 Accessing the MonitorSpec
 Mode Properties
 Nominal Values
 Preference Items
 Run-Time Name Binding of Mode Information
 Relase 2 Custom ViewPort Example


27 / / Monitors, Modes and the Display Database / New Monitors

Currently, there are five possible monitor settings in the display
database (more may be added in future releases):

default.monitor
    Since the default system monitor must be capable of displaying an
    image no matter what chips are installed or what software revision is
    in ROM, the graphics.library default.monitor is defined as a 15 Khz
    monitor which can display NTSC in the U.S. or PAL in Europe.

ntsc.monitor
    Since the ECS chip set allows for dynamic choice of standard scan
    rates, NTSC applications running on European machines may choose to
    be displayed on the ntsc.monitor to preserve the aspect ratio.

pal.monitor
    Since the ECS chip set allows for dynamic choice of standard scan
    rates, PAL applications running on American machines may choose to be
    displayed on the pal.monitor to preserve the aspect ratio.

multisync.monitor
    Programmably variable scan rates from 15 Khz through 31 Khz or more.
    Responds to signal timings to decide what scan rate to display.
    Required for Productivity (640 x 480 x 2 non-interlaced) display.

A2024.monitor
    Scan converter monitor which provides 1008 x 800 x 2 (U.S.) or 1008 x
    1024 x 2 (European) high-resolution, greyscale display.  Does not
    require ECS.  Does require Release 2 (or 1.3 V35) graphics library.


27 / / Monitors, Modes and the Display Database / New Modes

In V1.3 and earlier versions of the OS, the mode for a display was
determined by a 16 bit-value specified either in the ViewPort.Modes field
(for displays set up with the graphics library) or in the
NewScreen.ViewModes field (for displays set up with Intuition).  Prior to
Release 2, it was sufficient to indicate the mode of a display by setting
bits in the ViewPort.Modes field.  Furthermore, programs routinely made
interpretations about a given display mode based on bit-by-bit testing of
this 16-bit value.

             Table 27-4: ViewPort Modes Used in 1.3

    Bit      Name    1.3 ViewPort Modes
    ---      ----    ------------------
    15       HIRES           RP
    14       SPRITE          DC
    13       VPHIDE          DC        R = respected by 1.3
    12       reserved        IP        I = ignored by 1.3
    11       HAM             RP        D = dynamic
    10       DUALPF          RP        C = cleared on write by 1.3
    9        reserved        IP            IFF writers
    8        GENAUD          IC        P = preserved on write by 1.3
    7        EHB             RP            IFF writers
    6        PFBA (PF2PRI)   RP
    5        reserved        IP
    4        reserved        IP
    3        reserved        IP
    2        LACE            RP
    1        GENVID          IC
    0        reserved        IP

Considering all the possible new mode combinations and the need for future
expansion, it is clear that the 16-bit mode specification used in 1.3
needs to be extended.  Also, the specification of a mode needs to be
separated from its interpretation.  Furthermore, since modes can be
grouped by the special monitor or physical device needed for the display,
it is also beneficial to make provisions to support additional monitors
and their modes in the future.

The approach taken in Release 2 is to introduce a new 32-bit display mode
specifier called a ModeID.  The upper half of this specifier is called the
monitor part and the lower half is informally called the mode part.  There
is a correspondence between the monitor part and the monitor's operating
modes (referred to as virtual monitors or MonitorSpecs after a system data
structure).

For example, the A2024 monitor, PAL and NTSC are all different virtual
monitors--the actual, physical monitor may be able to support more than
one of these virtual types.  Another new concept in Release 2 is the
default monitor.  The default monitor, represented by a zero value for the
ModeID monitor part, may be either PAL or NTSC depending on a jumper on
the motherboard.

Compatibility considerations--especially for IFF files and their CAMG
chunk--have dictated very careful choices for the bit values which make up
the mode part of the 32-bit ModeIDs.  For example, the ModeIDs
corresponding to the older, 1.3 display modes have been constructed out of
a zero in the monitor part and the old 16-bit ViewPort.Modes bits in the
lower part (after several extraneous bits such as SPRITES and VP_HIDE are
cleared).

There are other such coincidences, but steps for compatibility with old
programs notwithstanding, there is a new rule:

    Programmers shall never interpret ModeIDs on a bit-by-bit basis.

For example, if the HIRES bit is set it does not mean the display is 640
pixels wide because there can also be a doubling of the beam scan rate
under Release 2.   Programs should not attempt to interpret modes directly
from the ViewPort.Modes field.  The Release 2 graphics library provides a
suitable substitute for this information through its new display database
facility (explained below).

Likewise, under Release 2, the Mode of a ViewPort is no longer set
directly.  Instead it is set indirectly by associating the ViewPort with
an abstract, 32-bit ModeID via the VideoControl() function.

These 32-bit ModeIDs have been carefully designed so that their lower 16
bits, when passed to graphics in the ViewPort.Modes field, provide some
degree of compatibility between different systems.  Older V1.3 programs
will continue to work within the new scheme.  (They will, however, not
gain the benefits of the new modes and monitors available.)

       Table 27-5: Extended ViewPort Modes Used in Release 2

    Bit      Name    Release 2 ViewPort Modes
    ---      ----    ------------------------
    15       MDBIT9             RP
    14       SPRITE             DC
    13       VPHIDE             DC           R = respected by Release
    12       EXTEND             RP           I = ignored by Release 2
    11       MDBIT8             RP           D = dynamic
    10       MDBIT7             RP           C = cleared on write by
    9        MDBIT6             RP               Release 2 IFF writers
    8        reserved           IC           P = preserved on write by
    7        MDBIT5             RP               Release 2 IFF writers
    6        PF2PRI             RP
    5        MDBIT4             RP
    4        MDBIT3             RP
    3        MDBIT2             RP
    2        MDBIT1             RP
    1        reserved           IC
    0        MDBIT0             RP

Refer to the example program, WBClone.c, at the end of this section for
examples on opening Release 2 ViewPorts using the new ModeID specification.


27 / / / Mode Specification, Screen Interface

Opening an Intuition screen in one of the new modes requires the
specification of 32 bits of mode data.  The NewScreen.ViewModes field is a
UWORD (16 bits).  Therefore, the new Release 2 function OpenScreenTags()
must be used along with a SA_DisplayID tag which specifies the 32-bit
ModeID.  See the "Intuition Screens" chapter for more on this.

The new display modes also introduce some complexity for applications that
want to support "mode-sensitive" processing.  If a program wishes to open
a screen in the highest resolution that a user has available, there are
many more cases to handle under Release 2.  Therefore, it will become
increasingly important to algorithmically layout a screen for correct,
functional and aesthetic operation.  All the information needed to be
mode-flexible is available through the display database functions
(explained below).


27 / / / Mode Specification, ViewPort Interface

When working directly with graphics, the interface is based on View and
ViewPort structures, rather than on Intuition's Screen structure.  As
previously mentioned, new information must be associated with the ViewPort
to specify the new Release 2 modes, and also with the View to specify what
virtual monitor the whole View will be displayed on.  There is also a lot
of information to associate with a ViewPort regarding enhanced genlock
capabilities.

This association of this new data with the View is made through a display
database system which has been added to the Release 2 graphics library.
All correctly written programs that allocate a ColorMap structure for a
ViewPort use the GetColorMap() function to do it.  Hence, in Release 2 the
ColorMap structure is used as the general purpose black box extension of
the ViewPort data.

To set or obtain the data in the extended structures, Release 2 provides a
new function named VideoControl() which takes a ColorMap as an argument.
This allows the setting and getting of the new extended display data.
This mechanism is used to associate a DisplayInfo handle (not a ModeID)
with a ViewPort.  A DisplayInfo handle is an abstract link to the display
database area associated with a particular ModeID.  This handle is passed
to the graphics database functions when getting or setting information
about the mode. Using VideoControl(), a program can enable, disable, or
obtain the state of a ViewPort's ColorMap, mode, genlock and other
features.  The function uses a tag based interface and returns NULL if no
error occurred.

    error = BOOL VideoControl( struct ColorMap *cm, struct TagItem *tag );

The first argument is a pointer to a ColorMap structure as returned by the
GetColorMap() function.  The second argument is a pointer to an array of
video control tag items, used to indicate whether information is being
given or requested as well as to pass (or receive the information).  The
tags you can use with VideoControl() include the following:

VTAG_ATTACH_CM_GET (or _SET) is used to obtain the ColorMap structure from
the indicated ViewPort or attach a given ColorMap to it.

VTAG_VIEWPORTEXTRA_GET (or _SET) is used to obtain the ViewPortExtra
structure from the indicated ColorMap structure or attach a given
ViewPortExtra to it.  A ViewPortExtra structure is an extension of the
ViewPort structure and should be allocated and freed with GfxNew() and
GfxFree() and associated with the ViewPort with VideoControl().

VTAG_NORMAL_DISP_GET (or _SET) is used to obtain or set the DisplayInfo
structure for the standard or "normal" mode.

See <graphics/videocontrol.h> for a list of all the available tags.  See
the section on genlocking for information on using VideoControl() to
interact with the Amiga's genlock capabilities.  Note that the graphics
library will modify the tag list passed to VideoControl().


27 / / Monitors, Modes and the Display Database / Coexisting Modes

Each display mode specifies (among other things) a pixel resolution and a
monitor scan rate.  Though the Amiga has the unique ability to change
pixel resolutions on the fly, it is not possible to change the speed of a
monitor beam in mid-frame. Therefore, if you set up a display of two or
more ViewPorts in different display modes requiring different scan rates,
at least one of the ViewPorts will be displayed with the wrong scan rate.

Such ViewPorts can be coerced into a different mode designed for the scan
rate currently in effect.  You can do this in a couple of ways,
introducing or removing interlace to adjust the vertical dimension, and
changing to faster or slower pixels (higher or lower resolution) for the
horizontal dimension.

The disadvantage of introducing interlace is flicker.  The disadvantage of
increasing resolution is the lessening of the video bus bandwidth and
possibly a reduction in the number of colors or palette resolution.

Under Intuition, the frontmost screen determines which of the conflicting
modes will take precedence.  With the graphics library, the Modes field of
the View and its frontmost ViewPort or, in Release 2, the MonitorSpec of
the ViewExtra determine the scan rate.  For some monitors (such as the
A2024), simultaneous display is excluded.  This is a requirement only
because the A2024 modes require very special and intricate display Copper
list management.


27 / / Monitors, Modes and the Display Database / ModeID Identifiers

The following definitions appear in the include file
<graphics/displayinfo.h>.  These values form the 32-bit ModeID which
consists of a _MONITOR_ID in the upper word, and a _MODE_KEY in the lower
word.  Never interpret these bits directly.  Instead use them with the
display database to obtain the information you need about the display mode.

    /* normal identifiers */

    #define MONITOR_ID_MASK                         0xFFFF1000

    #define DEFAULT_MONITOR_ID                      0x00000000
    #define NTSC_MONITOR_ID                         0x00011000
    #define PAL_MONITOR_ID                          0x00021000

    /* the following 20 composite keys are for Modes on the default */
    /* Monitor NTSC & PAL "flavors" of these particular keys may be */
    /* made by OR'ing  the NTSC or PAL MONITOR_ID with the desired  */
    /* MODE_KEY... */

    #define LORES_KEY                               0x00000000
    #define HIRES_KEY                               0x00008000
    #define SUPER_KEY                               0x00008020
    #define HAM_KEY                                 0x00000800
    #define LORESLACE_KEY                           0x00000004
    #define HIRESLACE_KEY                           0x00008004
    #define SUPERLACE_KEY                           0x00008024
    #define HAMLACE_KEY                             0x00000804
    #define LORESDPF_KEY                            0x00000400
    #define HIRESDPF_KEY                            0x00008400
    #define SUPERDPF_KEY                            0x00008420
    #define LORESLACEDPF_KEY                        0x00000404
    #define HIRESLACEDPF_KEY                        0x00008404
    #define SUPERLACEDPF_KEY                        0x00008424
    #define LORESDPF2_KEY                           0x00000440
    #define HIRESDPF2_KEY                           0x00008440
    #define SUPERDPF2_KEY                           0x00008460
    #define LORESLACEDPF2_KEY                       0x00000444
    #define HIRESLACEDPF2_KEY                       0x00008444
    #define SUPERLACEDPF2_KEY                       0x00008464
    #define EXTRAHALFBRITE_KEY                      0x00000080
    #define EXTRAHALFBRITELACE_KEY                  0x00000084

    /* vga identifiers */

    #define VGA_MONITOR_ID                          0x00031000

    #define VGAEXTRALORES_KEY                       0x00031004
    #define VGALORES_KEY                            0x00039004
    #define VGAPRODUCT_KEY                          0x00039024
    #define VGAHAM_KEY                              0x00031804
    #define VGAEXTRALORESLACE_KEY                   0x00031005
    #define VGALORESLACE_KEY                        0x00039005
    #define VGAPRODUCTLACE_KEY                      0x00039025
    #define VGAHAMLACE_KEY                          0x00031805
    #define VGAEXTRALORESDPF_KEY                    0x00031404
    #define VGALORESDPF_KEY                         0x00039404
    #define VGAPRODUCTDPF_KEY                       0x00039424
    #define VGAEXTRALORESLACEDPF_KEY                0x00031405
    #define VGALORESLACEDPF_KEY                     0x00039405
    #define VGAPRODUCTLACEDPF_KEY                   0x00039425
    #define VGAEXTRALORESDPF2_KEY                   0x00031444
    #define VGALORESDPF2_KEY                        0x00039444
    #define VGAPRODUCTDPF2_KEY                      0x00039464
    #define VGAEXTRALORESLACEDPF2_KEY               0x00031445
    #define VGALORESLACEDPF2_KEY                    0x00039445
    #define VGAPRODUCTLACEDPF2_KEY                  0x00039465
    #define VGAEXTRAHALFBRITE_KEY                   0x00031084
    #define VGAEXTRAHALFBRITELACE_KEY               0x00031085

    /* a2024 identifiers */

    #define A2024_MONITOR_ID                        0x00041000

    #define A2024TENHERTZ_KEY                       0x00041000
    #define A2024FIFTEENHERTZ_KEY                   0x00049000

    /* prototype identifiers */

    #define PROTO_MONITOR_ID                        0x00051000


27 / / / The Display Database and the DisplayInfo Record

For each ModeID, the graphics library has a body of data that enables the
set up of the display hardware and provides applications with information
about the properties of the display mode.

The display information in the database is accessed by searching it for a
record with a given ModeID.  For performance reasons, a look-up function
named FindDisplayInfo() is provided which, given a ModeID, will return a
handle to the internal data record about the attributes of the display.

This handle is then used for queries to the display database and
specification of display mode to the low-level graphics routines.  It is
never used as a pointer.  The private data structure associated with a
given ModeID is called a DisplayInfo.  From the <graphics/displayinfo.h>
include file:

    /* the "public" handle to a DisplayInfo  */

     typedef APTR DisplayInfoHandle;

In order to obtain database information about an existing ViewPort, you
must first gain reference to its 32-bit ModeID.  A graphics function
GetVPModeID() simplifies this operation:

    modeID = ULONG GetVPModeID(struct ViewPort *vp )

The vp argument is pointer to a ViewPort structure.  This function returns
the normal display ModeID, if one is currently associated with this
ViewPort.  If no ModeID exists this function returns INVALID_ID.

Each new valid 32-bit ModeID is associated with data initialized by the
graphics library at powerup.  This data is accessed by obtaining a handle
to it with the graphics function FindDisplayInfo().

    handle = DisplayInfoHandle FindDisplayInfo(ULONG modeID);

Given a 32-bit ModeID key (modeID in the prototype above)
FindDisplayInfo() returns a handle to a valid DisplayInfo Record found in
the graphics database, or NULL.  Using this handle, you can obtain
information about this video mode, including its default dimensions,
properties and whether it is currently available for use.

For instance, you can use a DisplayInfoHandle with the GetDisplayInfoData()
function to look up the properties of a mode (see below).  Or use the
DisplayInfoHandle with VideoControl() and the VTAG_NORMAL_DISP_SET tag to
set up a custom ViewPort.


27 / / Monitors, Modes and Display Database / Accessing DisplayInfo

Basic information about a display can be obtained by calling the Release 2
graphics function GetDisplayInfoData().  You also call this function
during the set up of a ViewPort.

   result = ULONG GetDisplayInfoData( DisplayInfoHandle handle, UBYTE *buf,
                                  ULONG size, ULONG tagID, ULONG modeID )

Set the handle argument to the DisplayInfoHandle returned by a previous
call to FindDisplayInfo().  This function will also accept a 32-bit ModeID
directly as an argument.  The handle argument should be set to NULL in
that case.

The buf argument points to a destination buffer you have set up to hold
the information about the properties of the display.  The size argument
gives the size of the buffer which depends on the type of inquiry you make.

The tagID argument specifies the type information you want to know about
and may be set as follows:

    DTAG_DISP  Returns display properties and availability information
               (the buffer should be set to the size of a DisplayInfo
               structure).

    DTAG_DIMS  Returns default dimensions and overscan information (the
               buffer should be set to the size of a DimensionInfo
               structure).

    DTAG_MNTR  Returns monitor type, view position, scan rate, and
               compatibility (the buffer should be set to the size of a
               MonitorInfo structure).

    DTAG_NAME  Returns the user friendly name for this mode (the buffer
               should be set to the size of a NameInfo structure).

If the call succeeds, result is positive and reports the number of bytes
actually transferred to the buffer.  If the call fails (no information for
the ModeID was available), result is zero.


27 / / Monitors, Modes and the Display Database / Mode Availability

Even if the video monitor (NTSC, PAL, VGA, A2024) or ECS chips required to
support a given mode are not available, there will be a DisplayInfo for
all of the display modes.  (This will not be the case for disk-based modes
such as Euro36, Euro72, etc.)

Thus, the graphics library provides the ModeNotAvailable() function to
determine whether a given mode is available, and if not, why not.  Data
corruption might cause the look-up function, GetVPModeID(), to fail even
when it should not, so the careful programmer will always test the look-up
function's return value.

    error =  ULONG ModeNotAvailable( ULONG modeID )

The modeID argument is again a 32-bit ModeID as shown in
<graphics/displayinfo.h>.  This function returns an error code, indicating
why this modeID is not available, or NULL if there is no known reason why
this mode should not be there.  The ULONG return values from this function
are a proper superset of the DisplayInfo.NotAvailable field (defined in
<graphics/displayinfo.h>).

The graphics library checks for the presence of the ECS chips at power up,
but the monitor attached to the system cannot be detected and so must be
specified by the user through a separate utility named AddMonitor.


27 / / Monitors, Modes and Display Database / Accessing MonitorSpec

The OpenMonitor() function will locate and open the requested MonitorSpec.
It is called with either the name of the monitor or a ModeID.

    mspc = struct MonitorSpec *OpenMonitor(STRPTR name, ULONG modeID)

If the name argument is non-NULL, the MonitorSpec is chosen by name.  If
the name argument is NULL, the MonitorSpec is chosen by ModeID.  If both
the name and ModeID arguments are NULL, a pointer to the MonitorSpec for
the default monitor is returned.  OpenMonitor() returns either a pointer
to a MonitorSpec structure, or NULL if the requested MonitorSpec could not
be opened.  The CloseMonitor() function relinquishes access to a
MonitorSpec previously acquired with OpenMonitor().

To set up a View in Release 2, a ViewExtra structure must also be created
and attached to it.  The ViewExtra.Monitor field must be initialized to
the address of a valid MonitorSpec structure before the View is displayed.
Use OpenMonitor() to initialize the Monitor field.


27 / / Monitors, Modes and the Display Database / Mode Properties

Here is an example of how to query the properties of a given mode from a
DisplayInfoHandle.

#include <graphics/displayinfo.h>

check_properties( handle )
DisplayInfoHandle handle;
{
    struct DisplayInfo queryinfo;

    /* fill in the displayinfo buffer with basic Mode display data */

    if(GetDisplayInfoData(handle, (UBYTE *)&queryinfo,sizeof(queryinfo),
       DTAG_DISP,NULL)))
    {
        /* check for Properties of this Mode */

        if(queryinfo.PropertyFlags)
        {
            if(queryinfo.PropertyFlags & DIPF_IS_LACE)
                printf("mode is interlaced");
            if(queryinfo.PropertyFlags & DIPF_IS_DUALPF)
                printf("mode has dual playfields");
            if(queryinfo.PropertyFlags & DIPF_IS_PF2PRI)
                printf("mode has playfield two priority");
            if(queryinfo.PropertyFlags & DIPF_IS_HAM)
                printf("mode uses hold-and-modify");
            if(queryinfo.PropertyFlags & DIPF_IS_ECS)
                printf("mode requires the ECS chip set");
            if(queryinfo.PropertyFlags & DIPF_IS_PAL)
                printf("mode is naturally displayed on pal.monitor");
            if(queryinfo.PropertyFlags & DIPF_IS_SPRITES)
                printf("mode has sprites");
            if(queryinfo.PropertyFlags & DIPF_IS_GENLOCK)
                printf("mode is compatible with genlock displays");
            if(queryinfo.PropertyFlags & DIPF_IS_WB)
                printf("mode will support workbench displays");
            if(queryinfo.PropertyFlags & DIPF_IS_DRAGGABLE)
                printf("mode may be dragged to new positions");
            if(queryinfo.PropertyFlags & DIPF_IS_PANELLED)
                printf("mode is broken up for scan conversion");
            if(queryinfo.PropertyFlags & DIPF_IS_BEAMSYNC)
                printf("mode supports beam synchronization");
        }
    }
}


27 / / Monitors, Modes and the Display Database / Nominal Values

Some of the display information is initialized in ROM for each mode such
as recommended nominal (or default) dimensions.  Even though this
information is presumably static, it would still be a mistake to hardcode
assumptions about these nominal values into your code.

Gathering information about the nominal dimensions of various modes is
handled in a fashion similar to to the basic queries above.  Here is an
example of how to query the nominal dimensions of a given mode from a
DisplayInfoHandle.

#include <graphics/displayinfo.h>

check_dimensions( handle )
DisplayInfoHandle handle;
{
    struct DimensionInfo query;

    /* fill the buffer with Mode dimension information */

    if(GetDisplayInfoData(handle, (UBYTE *)&query,sizeof(query),
       DTAG_DIMS,NULL)))
    {
        /* display Nominal dimensions of this Mode */

        printf("nominal width  = %ld",
                query.Nominal.MaxX - query.Nominal.MinX + 1);

        printf("nominal height = %ld",
                query.Nominal.MaxY - query.Nominal.MinY + 1);
    }
}


27 / / Monitors, Modes and the Display Database / Preference Items

Some display information is changed in response to user Preference
specification.  Until further notice, this will be reserved as a system
activity and use private interface methods.

One Preferences setting that may affect the display data is the user's
preferred overscan limits to the monitor associated with this mode.  Here
is an example of how to query the overscan dimensions of a given mode from
a DisplayInfoHandle.

 #include <graphics/displayinfo.h>

check_overscan( handle )
DisplayInfoHandle handle;
{
    struct DimensionInfo query;

    /* fill the buffer with Mode dimension information */

    if(GetDisplayInfoData(handle, (UBYTE *)&query,sizeof(query),
       DTAG_DIMS,NULL)))
    {
        /* display standard overscan dimensions of this Mode */

        printf("overscan width  = %ld",
                query.StdOScan.MaxX - query.StdOScan.MinX + 1);

        printf("overscan height = %ld",
                query.StdOScan.MaxY - query.StdOScan.MinY + 1);
    }
}


27 / / / Run-Time Name Binding of Mode Information

It is useful to associate common names with the various display modes.
The Release 2 graphics library includes a provision for binding a name to
a display mode so that it will be available via a query.  This will be
useful in the implementation of a standard screen-format requester.  Note
however that no names are bound initially since the bound names will take
up RAM at all times.  Instead defaults are used.

Bound names will override the defaults though, so that, until the
screen-format requester is localized to a non-English language, the modes
can be localized by binding foreign language names to them.  Here is an
example of how to query the run-time name binding of a given mode from a
DisplayInfoHandle.

#include <graphics/displayinfo.h>

check_name_bound( handle )
DisplayInfoHandle handle;
{
    struct NameInfo query;

    /* fill the buffer with Mode dimension information */

    if(GetDisplayInfoData(handle, (UBYTE *)&query,sizeof(query),
       DTAG_NAME,NULL)))
    {
        printf("%s", query.Name);
    }
}


27 Graphics Primitives / Advanced Topics

This section covers advanced display topics such as dual-playfield mode,
double-buffering, EHB mode and HAM mode.

 Creating a Dual-Playfield Display     Extra-Half-Brite Mode
 Creating a Double-Buffered Display    Hold-And-Modify Mode


27 / Advanced Topics / Creating a Dual-Playfield Display

In dual-playfield mode, you have two separately controllable playfields.
You specify dual-playfield mode in 1.3 by setting the DUALPF bit in the
ViewPort.Modes field.  In Release 2, you specify dual-playfield by using
any ModeID that includes DPF in its name as listed in <graphics/displayinfo.h>.

In dual-playfield mode, you always define two RasInfo data structures.
Each of these structures defines one of the playfields. There are five
different ways you can configure a dual-playfield display, because there
are five different distributions of the bitplanes which the system
hardware allows.

        Table 27-6: Bitplane Assignment in Dual-playfield Mode

               Number of    Playfield 1    Playfield 2
               Bitplanes       Depth          Depth
               ---------       -----          -----
                   2             1              1
                   3             2              1
                   4             2              2
                   5             3              2
                   6             3              3

Under 1.3 if PFBA is set in the ViewPort.Modes field, or, under Release 2,
if the ModeID includes DPF2 in its name, then the playfield priorities are
swapped and playfield 2 will be displayed in front of playfield 1.  In
this way, you can get more bitplanes in the background playfield than you
have in the foreground playfield. The playfield priority affects only one
ViewPort at a time.  If you have multiple ViewPorts with dual-playfields,
the playfield priority is set for each one individually.

Here's a summary of the steps you need to take to create a dual-playfield
display:

  * Allocate one View structure and one ViewPort structure.

  * Allocate two BitMap structures.  Allocate two RasInfo structures
    (linked together), each pointing to a separate BitMap. The two
    RasInfo structures are linked together as follows:

        struct RasInfo playfield1, playfield2;

        playfield1.Next = &playfield2;
        playfield2.Next = NULL;

  * Initialize each BitMap structure to describe one playfield, using one
    of the permissible bitplane distributions shown in the above table
    and allocate memory for the bitplanes themselves.  Note that BitMap 1
    and BitMap 2 need not be the same width and height.

  * Initialize the ViewPort structure.  In 1.3, specify dual-playfield
    mode by setting the DUALPF bit (and PFBA, if appropriate) in the
    ViewPort.Modes field.  Under Release 2, specify dual-playfield mode
    by selecting a ModeID that includes DPF (or DPF2) in its name as
    listed in <graphics/displayinfo.h>.  Set the ViewPort.RasInfo field
    to the address of the playfield 1 RasInfo.

  * Set up the ColorMap information

  * Call MakeVPort(), MrgCop() and LoadView() to display the newly
    created ViewPort.

For display purposes, each of the two BitMaps is assigned to a separate
ViewPort.  To draw separately into the BitMaps, you must also assign these
BitMaps to two separate RastPorts.  The section called
"Initializing a RastPort Structure" shows you how to use a RastPort data
structure to control your drawing routines.


27 / Advanced Topics / Creating a Double-Buffered Display

To produce smooth animation or similar effects, it is occasionally
necessary to double-buffer your display.  To prevent the user from seeing
your graphics rendering while it is in progress, you will want to draw
into one memory area while actually displaying a different area.

There are two methods of creating and displaying a double-buffered
display.  The simplest method is to create two complete Views and switch
back and forth between them with LoadView() and WaitTOF().

The second method consists of creating two separate display areas and two
sets of pointers to those areas for a single View.  This is more
complicated but takes less memory.

  * Allocate one ViewPort structure and one View structure.

  * Allocate two BitMap structures and one RasInfo structure. Initialize
    each BitMap structure to describe one drawing area and allocate
    memory for the bitplanes themselves. Initialize the RasInfo
    structure, setting the RasInfo.BitMap field to the address of one of
    the two BitMaps you created.

  * Call MakeVPort(), MrgCop() and LoadView(). When you call MrgCop(),
    the system uses the information you have provided to create a Copper
    instruction list for the Copper to execute.  The system allocates
    memory for a long-frame (LOF) Copper list and, if this is an
    interlaced display, a short-frame (SHF) Copper list as well.  The
    system places a pointer to the long-frame Copper list in
    View.LOFCprList and a pointer to a short-frame Copper list (if this
    is an interlaced display) in View.SHFCprList.  The Copper instruction
    stream referenced by these pointers applies to the first BitMap.

  * Save the values in View.LOFCprList and View.SHFCprlist and reset
    these fields to zero.  Place a pointer to the second BitMap structure
    in the RasInfo.BitMap field.  Next call MakeVPort() and MrgCop().

  * When you perform MrgCop() with the Copper instruction list fields of
    the View set to zero, the system automatically allocates and fills in
    a new list of instructions for the Copper.  Now you have created two
    sets of instruction streams for the Copper, one that works with data
    in the first BitMap and the other that works with data in the second
    BitMap.

  * You can save pointers to the second list of Copper instructions as
    well.  Then, to perform the double-buffering, alternate between the
    two Copper lists.  The code for the double-buffering loop would be as
    follows: call WaitTOF(), change the Copper instruction list pointers
    in the View, call LoadView() to show one of the BitMaps while drawing
    into the other BitMap, and repeat.

Remember that you will have to call FreeCprList() on both sets of Copper
lists when you have finished.


27 / Advanced Topics / Extra-Half-Brite Mode

In the Extra-Half-Brite mode you can create a single-playfield,
low-resolution display with up to 64 colors, double the normal maximum of
32.  This requires your ViewPort to be defined with six bitplanes.  Under
1.3, you specify EHB mode by setting the EXTRA_HALFBRITE bit in the
ViewPort.Modes field.  Under Release 2, you specify EHB by selecting any
ModeID which includes EXTRAHALFBRITE in its name as defined in the include
file <graphics/displayinfo.h>.

When setting up the color palette for an EHB display, you only specify
values for registers 0 to 31.  If you draw using color numbers 0 through
31, the pixel you draw will be the color specified in that particular
system color register.  If you draw using a color number from 32 to 63,
then the color displayed will be half the intensity value of the
corresponding color register from 0 to 31.  For example, if color register
0 is set to 0xFFF (white), then color number 32 would be half this value
or 0x777 (grey).

EHB mode uses all six bitplanes.  The color register (0 through 31) is
obtained from the bit combinations from planes 5 to 1, in that order of
significance.  Plane 6 is used to determine whether the full intensity
(bit value 0) color or half-intensity (bit value 1) color is to be
displayed.


27 / Advanced Topics / Hold-And-Modify Mode

In hold-and-modify mode you can create a single-playfield, low-resolution
display in which 4,096 different colors can be displayed simultaneously.
This requires your ViewPort to be defined with six bitplanes.  Under 1.3,
you specify HAM mode by setting the HAM flag in the ViewPort.Modes field.
Under Release 2, you specify HAM by selecting any ModeID which includes
HAM in its name as defined in <graphics/displayinfo.h>.

When you draw into the BitMap associated with this ViewPort, you can
choose colors in one of four different ways.  If you draw using color
numbers 0 to 15, the pixel you draw will appear in the color specified in
that particular system color register.  If you draw with any other color
value (16 to 63) the color displayed depends on the color of the pixel
that is to the immediate left of this pixel on the screen.  To see how
this works, consider how the bitplanes are used in HAM.

Hold-and-modify mode requires six bitplanes.  Planes 5 and 6 are used to
modify the way bits from planes 1 through 4 are treated, as follows:

  * If the bit combination from planes 6 and 5 for any given pixel is 00,
    normal color selection procedure is followed.  Thus, the bit
    combinations from planes 4 to 1, in that order of significance, are
    used to choose one of 16 color registers (registers 0 through 15).

  * If the bit combination in planes 6 and 5 is 01, the color of the
    pixel immediately to the left of this pixel is duplicated and then
    modified.  The bit combinations from planes 4 through 1 are used to
    replace the four bits representing the blue value of the preceding
    pixel color. (No color registers are changed.)

  * If the bit combination in planes 6 and 5 is 10, then the color of the
    pixel immediately to the left of this pixel is duplicated and
    modified.  The bit combinations from planes 4 through 1 are used to
    replace the four bits representing the red value of the preceding
    pixel color.

  * If the bit combination in planes 6 and 5 is 11, then the color of the
    pixel immediately to the left of this pixel is duplicated and
    modified.  The bit combinations from planes 4 through 1 are used to
    replace the four bits representing the green value of the preceding
    pixel color.

You can use just five bitplanes in HAM mode.  In that case, the data for
the sixth plane is automatically assumed to be 0.  Note that for the first
pixel in each line, hold-and-modify begins with the background color.  The
color choice does not carry over from the preceding line.

    Note:
    -----
    Since a typical hold-and-modify pixel only changes one of the three
    RGB color values at a time, color selection is limited.  HAM mode
    does allow for the display of 4,096 colors simultaneously, but there
    are only 64 color options for any given pixel (not 4,096).  The color
    of a pixel depends on the color of the preceding pixel.


27 Graphics Primitives / Drawing Routines

Most of the graphics drawing routines require information about how the
drawing is to take place.  For this reason, most graphics drawing routines
use a data structure called a RastPort, that contains pointers to the
drawing area and drawing variables such as the current pen color and font
to use.  In general, you pass a pointer to your RastPort structure as an
argument whenever you call a drawing function.

 The RastPort Structure
 Using the Graphics Drawing Routines
 Performing Data Move Operations


27 / Drawing Routines / The RastPort Structure

The RastPort data structure can be found in the include files
<graphics/rastport.h> and <graphics/rastport.i>. It contains the following
information:

struct RastPort
{
    struct  Layer  *Layer;
    struct  BitMap *BitMap;
    UWORD          *AreaPtrn;  /* Ptr to areafill pattern */
    struct  TmpRas *TmpRas;
    struct  AreaInfo *AreaInfo;
    struct  GelsInfo *GelsInfo;
    UBYTE   Mask;              /* Write mask for this raster */
    BYTE    FgPen;             /* Foreground pen for this raster */
    BYTE    BgPen;             /* Background pen  */
    BYTE    AOlPen;            /* Areafill outline pen */
    BYTE    DrawMode;          /* Drawing mode for fill, lines, and text */
    BYTE    AreaPtSz;          /* 2^n words for areafill pattern */
    BYTE    linpatcnt;         /* Current line drawing pattern preshift */
    BYTE    dummy;
    UWORD   Flags;             /* Miscellaneous control bits */
    UWORD   LinePtrn;          /* 16 bits for textured lines */
    WORD    cp_x, cp_y;	       /* Current pen position */
    UBYTE   minterms[8];
    WORD    PenWidth;
    WORD    PenHeight;
    struct  TextFont *Font;    /* Current font address */
    UBYTE   AlgoStyle;         /* The algorithmically generated style */
    UBYTE   TxFlags;           /* Text specific flags */
    UWORD   TxHeight;          /* Text height */
    UWORD   TxWidth;           /* Text nominal width */
    UWORD   TxBaseline;        /* Text baseline */
    WORD    TxSpacing;         /* Text spacing (per character) */
    APTR    *RP_User;
    ULONG   longreserved[2];
#ifndef GFX_RASTPORT_1_2
    UWORD   wordreserved[7];   /* Used to be a node */
    UBYTE   reserved[8];       /* For future use */
#endif
};

The sections that follow explain each of the items in the
RastPort structure is used.

 Initializing a BitMap Structure
 Initializing a RastPort Structure
 RastPort Area-fill Information
 RastPort Graphics Element Pointer
 RastPort Write Mask
 RastPort Drawing Pens
 RastPort Drawing Modes
 RastPort Line and Area Drawing Patterns
 RastPort Pen Position and Size
 Text Attributes


27 / / The RastPort Structure / Initializing a BitMap Structure

Associated with the RastPort is another data structure called a BitMap
which contains a description of the organization of the data in the
drawing area.  This tells the graphics library where in memory the drawing
area is located and how it is arranged.  Before you can set up a RastPort
for drawing you must first declare and initialize a BitMap structure,
defining the characteristics of the drawing area, as shown in the
following example. This was already shown in the "Forming a Basic Display"
section, but it is repeated here because it relates to drawing as well as
to display routines. (You need not necessarily use the same BitMap for
both the drawing and the display, e.g., double-buffered displays.)

    #define DEPTH 2       /* Two planes deep. */
    #define WIDTH 320     /* Width in pixels. */
    #define HEIGHT 200    /* Height in scanlines. */

    struct BitMap bitMap;

    /* Initialize the BitMap. */
    InitBitMap(&bitMap, DEPTH, WIDTH, HEIGHT);


27 / / The RastPort Structure / Initializing a RastPort Structure

Once you have a BitMap set up, you can declare and initialize the RastPort
and then link the BitMap into it.  Here is a sample initialization
sequence:

    struct BitMap bitMap = {0};
    struct RastPort rastPort = {0};

    /* Initialize the RastPort and link the BitMap to it. */
    InitRastPort(&rastPort);
    rastPort.BitMap = &bitMap;

    Initialize, Then Link.
    ----------------------
    You cannot link the bitmap in until after the RastPort has been
    initialized.


27 / / The RastPort Structure / RastPort Area-fill Information

Two structures in the RastPort -- AreaInfo and TmpRas -- define certain
information for area filling operations.  The AreaInfo pointer is
initialized by a call to the routine InitArea().

    #define AREA_SIZE 200

    register USHORT i;
    WORD areaBuffer[AREA_SIZE];
    struct AreaInfo areaInfo = {0};

    /*  Clear areaBuffer before calling InitArea().  */
    for (i=0; i<AREA_SIZE; i++)
        areaBuffer[i] = 0;

    InitArea(&areaInfo, areaBuffer, (AREA_SIZE*2)/5);

The area buffer must start on a word boundary.  That is why the sample
declaration shows areaBuffer as composed of unsigned words (200), rather
than unsigned bytes (400).  It still reserves the same amount of space,
but aligns the data space correctly.

To use area fill, you must first provide a work space in memory for the
system to store the list of points that define your area. You must allow a
storage space of 5 bytes per vertex.  To create the areas in the work
space, you use the functions AreaMove(), AreaDraw(), and AreaEnd().

Typically, you prepare the RastPort for area-filling by following the
steps in the code fragment above and then linking your AreaInfo into the
RastPort like so:

    rastPort->AreaInfo = &areaInfo;

In addition to the AreaInfo structure in the RastPort, you must also
provide the system with some work space to build the object whose vertices
you are going to define.  This requires that you initialize a TmpRas
structure, then point to that structure for your RastPort to use. First
the TmpRas structure is initialized (via InitTmpRas()) then it is linked
into the RastPort structure.

    Allocate Enough Space.
    ----------------------
    The area to which TmpRas.RasPtr points must be at least as large
    as the area (width times height) of the largest rectangular region
    you plan to fill. Typically, you allocate a space as large as a
    single bitplane (usually 320 by 200 bits for Lores mode, 640 by 200
    for Hires, and 1280 by 200 for SuperHires).

When you use functions that dynamically allocate memory from the system,
you must remember to return these memory blocks to the system before your
program exits.  See the description of FreeRaster() in the Amiga ROM
Kernel Reference Manual: Includes and Autodocs.


27 / / The RastPort Structure / RastPort Graphics Element Pointer

The graphics element pointer in the RastPort structure is called GelsInfo.
If you are doing graphics animation using the GELS system, this pointer
must refer to a properly initialized GelsInfo structure.  See the chapter
on "Graphics Sprites, Bobs and Animation" for more information.


27 / / The RastPort Structure / RastPort Write Mask

The write mask is a RastPort variable that determines which of the
bitplanes are currently writable. For most applications, this variable is
set to all bits on.  This means that all bitplanes defined in the BitMap
are affected by a graphics writing operation.  You can selectively disable
one or more bitplanes by simply specifying a 0 bit in that specific
position in the control byte.  For example:

    #include <graphics/gfxmacros.h>

    SetWrMsk(&rastPort, 0xFB);    /* disable bitplane 2 */

A useful application for the Mask field is to set or clear plane 6 while
in the Extra-Half-Brite display mode to create shadow effects.  For
example:

    SetWrMsk(&rastPort, 0xE0);          /* Disable planes 1 through 5. */

    SetAPen(&rastPort, 0);           /* Clear the Extra-Half-Brite bit */
    RectFill(&rastPort, 20, 20, 40, 30);    /*   in the old rectangle. */

    SetAPen(&rastPort, 32);            /* Set the Extra-Half-Brite bit */
    RectFill(&rastPort, 30, 25, 50, 35);    /*   in the new rectangle. */

    SetWrMsk(&rastPort, -1);                  /* Re-enable all planes. */


27 / / The RastPort Structure / RastPort Drawing Pens

The Amiga has three different drawing "pens" associated with the graphics
drawing routines.  These are:

  * FgPen--the foreground or primary drawing pen. For historical
    reasons, it is also called the A-Pen.

  * BgPen--the background or secondary drawing pen. For historical
    reasons, it is also called the B-Pen.

  * AOlPen--the area outline pen. For historical reasons, it is also
    called the O-Pen.

A drawing pen variable in the RastPort contains the current value (range
0-255) for a particular color choice.  This value represents a color
register number whose contents are to be used in rendering a particular
type of image.  The effect of the pen value is dependent upon the drawing
mode and can be influenced by the pattern variables and the write mask as
described below. Always use the system calls (e.g. SetAPen()) to set the
different pens, never store values directly into the pen fields of the
RastPort.

    Colors Repeat Beyond 31.
    ------------------------
    The Amiga 500/2000/3000 (with original chips or ECS) contains only
    32 color registers.  Any range beyond that repeats the colors in
    0-31. For example, pen numbers 32-63 refer to the colors in registers
    0-31 (except when you are using Extra-Half-Brite mode).

The graphics library drawing routines support BitMaps up to eight planes
deep allowing for future expansion of the Amiga hardware.

The color in FgPen is used as the primary drawing color for rendering
lines and areas. This pen is used when the drawing mode is JAM1 (see the
next section for drawing modes). JAM1 specifies that only one color is to
be "jammed" into the drawing area.

You establish the color for FgPen using the statement:

    SetAPen(&rastPort, newcolor);

The color in BgPen is used as the secondary drawing color for rendering
lines and areas.  If you specify that the drawing mode is JAM2 (jamming
two colors) and a pattern is being drawn, the primary drawing color
(FgPen) is used where there are 1s in the pattern. The secondary drawing
color (BgPen) is used where there are 0s in the pattern.

You establish the drawing color for BgPen using the statement:

    SetBPen(&rastPort, newcolor);

The area outline pen AOlPen is used in two applications: area fill and
flood fill. (See "Area Fill Operations" below.)  In area fill, you can
specify that an area, once filled, can be outlined in this AOlPen color.
In flood fill (in one of its operating modes) you can fill until the
flood-filler hits a pixel of the color specified in this pen variable.

You establish the drawing color for AOlPen using the statement:

    SetOPen(&rastPort, newcolor);


27 / / The RastPort Structure / RastPort Drawing Modes

Four drawing modes may be specified in the RastPort.DrawMode field:

JAM1
    Whenever you execute a graphics drawing command, one color is jammed
    into the target drawing area. You use only the primary drawing pen
    color, and for each pixel drawn, you replace the color at that
    location with the FgPen color.

JAM2
    Whenever you execute a graphics drawing command, two colors are
    jammed into the target drawing area. This mode tells the system that
    the pattern variables (both line pattern and area pattern--see
    the next section) are to be used for the drawing. Wherever there is a
    1 bit in the pattern variable, the FgPen color replaces the color of
    the pixel at the drawing position. Wherever there is a 0 bit in the
    pattern variable, the BgPen color is used.

COMPLEMENT
    For each 1 bit in the pattern, the corresponding bit in the target
    area is complemented--that is, its state is reversed. As with all
    other drawing modes, the write mask can be used to protect specific
    bitplanes from being modified. Complement mode is often used for
    drawing and then erasing lines.

INVERSVID
    This is the drawing mode used primarily for text. If the drawing mode
    is (JAM1 | INVERSVID), the text appears as a transparent letter
    surrounded by the FgPen color. If the drawing mode is
    (JAM2|INVERSVID), the text appears as in (JAM1|INVERSVID) except that
    the BgPen color is used to draw the text character itself. In this
    mode, the roles of FgPen and BgPen are effectively reversed.

You set the drawing modes using the statement:

    SetDrMd(&rastPort, newmode);

Set the newmode argument to one of the four drawing modes listed above.


27 / / RastPort Structure / RastPort Line and Area Drawing Patterns

The RastPort data structure provides two different pattern variables that
it uses during the various drawing functions: a line pattern and an area
pattern. The line pattern is 16 bits wide and is applied to all lines.
When you initialize a RastPort, this line pattern value is set to all 1s
(hex FFFF), so that solid lines are drawn. You can also set this pattern
to other values to draw dotted lines if you wish. For example, you can
establish a dotted line pattern with the graphics macro SetDrPt():

    SetDrPt(&rastPort, 0xCCCC);

The second argument is a bit-pattern, 1100110011001100, to be applied to
all lines drawn. If you draw multiple, connected lines, the pattern
cleanly connects all the points.

The area pattern is also 16 bits wide and its height is some power of two.
This means that you can define patterns in heights of 1, 2, 4, 8, 16, and
so on.  To tell the system how large a pattern you are providing, use the
graphics macro SetAfPt():

    SetAfPt(&rastPort, &areaPattern, power_of_two);

The &areaPattern argument is the address of the first word of the area
pattern and power_of_two specifies how many words are in the pattern. For
example:

    USHORT ditherData[] =
    {
        0x5555, 0xAAAA
    };

    SetAfPt(&rastPort, ditherData, 1);

This example produces a small cross-hatch pattern, useful for shading.
Because power_of_two is set to 1, the pattern height is 2 to the 1st, or 2
rows high.

To clear the area fill pattern, use:

    SetAfPt(&rastPort, NULL, 0);

    Pattern Positioning.
    --------------------
    The pattern is always positioned with respect to the upper left
    corner of the RastPort drawing area (the 0,0 coordinate).  If you
    draw two rectangles whose edges are adjacent, the pattern will be
    continuous across the rectangle boundaries.

The last example given produces a two-color pattern with one color where
there are 1s and the other color where there are 0s in the pattern.  A
special mode allows you to develop a pattern having up to 256 colors.  To
create this effect, specify power_of_two as a negative value instead of a
positive value.  For instance, the following initialization establishes an
8-color checkerboard pattern where each square in the checkerboard has a
different color.

    USHORT areaPattern[3][8] =
    {
    /* plane 0 pattern */
        {
               0x0000, 0x0000,
               0xffff, 0xffff,
               0x0000, 0x0000,
               0xffff, 0xffff
        },
    /* plane 1 pattern */
        {
               0x0000, 0x0000,
               0x0000, 0x0000,
               0xffff, 0xffff,
               0xffff, 0xffff
        },
    /* plane 2 pattern */
        {
               0xff00, 0xff00,
               0xff00, 0xff00,
               0xff00, 0xff00,
               0xff00, 0xff00
        }
    };

    SetAfPt(&rastPort, &areaPattern, -3);

    /* when doing this, it is best to set */
    /* three other parameters as follows: */
    SetAPen(&rastPort, -1);
    SetBPen(&rastPort, 0);
    SetDrMd(&rastPort, JAM2);

If you use this multicolored pattern mode, you must provide as many planes
of pattern data as there are planes in your BitMap.


27 / / The RastPort Structure / RastPort Pen Position and Size

The graphics drawing routines keep the current position of the drawing pen
in the RastPort fields cp_x and cp_y, for the horizontal and vertical
positions, respectively. The coordinate location 0,0 is in the upper left
corner of the drawing area.  The x value increases proceeding to the
right; the y value increases proceeding toward the bottom of the drawing
area.

The variables RastPort.PenWidth and RastPort.PenHeight are not currently
implemented.  These fields should not be read or written by applications.


27 / / The RastPort Structure / Text Attributes

Text attributes and font information are stored in the RastPort fields
Font, AlgoStyle, TxFlags, TxHeight, TxWidth, TxBaseline and TxSpacing.
These are normally set by calls to the graphics font routines which are
covered separately in the chapter on "Graphics Library and Text".


27 / Drawing Routines / Using the Graphics Drawing Routines

This section shows you how to use the Amiga drawing routines. All of these
routines work either on their own or along with the windowing system and
layers library.  For details about using the layers and windows, see the
chapters on "Layers Library" and "Intuition Windows".

    Use WaitBlit().
    ---------------
    The graphics library rendering and data movement routines generally
    wait to get access to the blitter, start their blit, and then exit.
    Therefore, you must WaitBlit() after a graphics rendering or data
    movement call if you intend to immediately deallocate, examine, or
    perform order-dependent processor operations on the memory used in
    the call.

As you read this section, keep in mind that to use the drawing routines,
you need to pass them a pointer to a RastPort.  You can define the
RastPort directly, as shown in the sample program segments in preceding
sections, or you can get a RastPort from your Window structure using code
like the following:

    struct Window *window;
    struct RastPort *rastPort;

    window = OpenWindow(&newWindow);  /*  You could use OpenWindowTags() */
    if (window)
        rastPort = window->RPort;

You can also get the RastPort from the Layer structure, if you are not
using Intuition.

 Drawing Individual Pixels
 Reading Individual Pixels
 Drawing Ellipses and Circles
 Drawing Lines
 Drawing Patterned Lines
 Drawing Multiple Lines with a Single Command
 Area-fill Operations
 Ellipse and Circle-fill Operations
 Flood-fill Operations
 Rectangle-fill Operations


27 / / Using the Graphics Drawing Routines / Drawing Individual Pixels

You can set a specific pixel to a desired color by using a statement like
this:

    SHORT x, y;
    LONG result;
    result = WritePixel(&rastPort, x, y);

WritePixel() uses the primary drawing pen and changes the pixel at that
x,y position to the desired color if the x,y coordinate falls within the
boundaries of the RastPort. A value of 0 is returned if the write was
successful; a value of -1 is returned if x,y was outside the range of the
RastPort.


27 / / Using the Graphics Drawing Routines / Reading Individual Pixels

You can determine the color of a specific pixel with a statement like this:

    SHORT x, y;
    LONG result;
    result = ReadPixel(&rastPort, x, y);

ReadPixel() returns the value of the pixel color selector at the specified
x,y location. If the coordinates you specify are outside the range of your
RastPort, this function returns a value of -1.


27 / / Using Graphics Drawing Routines / Drawing Ellipses and Circles

Two functions are associated with drawing ellipses: DrawCircle() and
DrawEllipse(). DrawCircle(), a macro that calls DrawEllipse(), will draw a
circle from the specified center point using the specified radius.  This
function is executed by the statement:

    DrawCircle(&rastPort, center_x, center_y, radius);

Similarly, DrawEllipse() draws an ellipse with the specified radii from
the specified center point:

    DrawEllipse(&rastPort, center_x, center_y, horiz_r, vert_r);

Neither function performs clipping on a non-layered RastPort.


27 / / Using the Graphics Drawing Routines / Drawing Lines

Two functions are associated with line drawing: Move() and Draw(). Move()
simply moves the cursor to a new position.  It is like picking up a
drawing pen and placing it at a new location. This function is executed by
the statement:

    Move(&rastPort, x, y);

Draw() draws a line from the current x,y position to a new x,y position
specified in the statement itself. The drawing pen is left at the new
position. This is done by the statement:

    Draw(&rastPort, x, y);

Draw() uses the pen color specified for FgPen. Here is a sample sequence
that draws a line from location (0,0) to (100,50).

    SetAPen(&rastPort, COLOR1);    /* Set A pen color. */
    Move(&rastPort, 0, 0);    /* Move to this location. */
    Draw(&rastPort, 100,50);    /* Draw to a this location. */

    Caution:
    --------
    If you attempt to draw a line outside the bounds of the BitMap,
    using the basic initialized RastPort, you may crash the system.
    You must either do your own software clipping to assure that the line
    is in range, or use the layers library. Software clipping means that
    you need to determine if the line will fall outside your BitMap
    before you draw it, and render only the part which falls inside
    the BitMap.


27 / / Using the Graphics Drawing Routines / Drawing Patterned Lines

To turn the example above into a patterned line draw, simply set a drawing
pattern, such as:

    SetDrPt(&rastPort, 0xAAAA);

Now all lines drawn appear as dotted lines (0xAAAA = 1010101010101010 in
binary).  To resume drawing solid lines, execute the statement:

    SetDrPt(&rastPort, ~0);

Because ~0 is defined as all bits on (11...11) in binary.


27 / / / Drawing Multiple Lines with a Single Command

You can use multiple Draw() statements to draw connected line figures. If
the shapes are all definable as interconnected, continuous lines, you can
use a simpler function, called PolyDraw(). PolyDraw() takes a set of line
endpoints and draws a shape using these points. You call PolyDraw() with
the statement:

    PolyDraw(&rastPort, count, arraypointer);

PolyDraw() reads the array of points and draws a line from the first pair
of coordinates to the second, then a connecting line to each succeeding
pair in the array until count points have been connected. This function
uses the current drawing mode, pens, line pattern, and write mask
specified in the target RastPort; for example, this fragment draws a
rectangle, using the five defined pairs of x,y coordinates.

    SHORT linearray[] =
        {
         3, 3,
        15, 3,
        15,15,
         3,15,
         3, 3
        };

    PolyDraw(&rastPort, 5, linearray);


27 / / Using the Graphics Drawing Routines / Area-fill Operations

Assuming that you have properly initialized your RastPort structure to
include a properly initialized AreaInfo, you can perform area fill by
using the functions described in this section.

AreaMove() tells the system to begin a new polygon, closing off any other
polygon that may already be in process by connecting the end-point of the
previous polygon to its starting point. AreaMove() is executed with the
statement:

    LONG result;
    result = AreaMove(&rastPort, x, y);

AreaMove() returns 0 if successful, -1 if there was no more space left in
the vector list. AreaDraw() tells the system to add a new vertex to a list
that it is building.  No drawing takes place until AreaEnd() is executed.
AreaDraw is executed with the statement:

    LONG result;
    result = AreaDraw(&rastPort, x, y);

AreaDraw() returns 0 if successful, -1 if there was no more space left in
the vector list. AreaEnd() tells the system to draw all of the defined
shapes and fill them.  When this function is executed, it obeys the
drawing mode and uses the line pattern and area pattern specified in your
RastPort to render the objects you have defined.

To fill an area, you do not have to AreaDraw() back to the first point
before calling AreaEnd().  AreaEnd() automatically closes the polygon.
AreaEnd() is executed with the following statement:

    LONG result;
    result = AreaEnd(&rastPort);

AreaEnd() returns 0 if successful, -1 if there was an error. To turn off
the outline function, you have to set the RastPort Flags variable back to
0 with BNDRYOFF():

    #include "graphics/gfxmacros.h"

    BNDRYOFF(&rastPort);

Otherwise, every subsequent area-fill or rectangle-fill operation will
outline their rendering with the outline pen (AOlPen).


27 / / Using Drawing Routines / Ellipse and Circle-fill Operations

Two functions are associated with drawing filled ellipses: AreaCircle()
and AreaEllipse(). AreaCircle()  (a macro that calls AreaEllipse()) will
draw a circle from the specified center point using the specified radius.
This function is executed by the statement:

    AreaCircle(&rastPort, center_x, center_y, radius);

Similarly, AreaEllipse() draws a filled ellipse with the specified radii
from the specified center point:

    AreaEllipse(&rastPort, center_x, center_y, horiz_r, vert_r);

Outlining with SetOPen() is not currently supported by the AreaCircle()
and AreaEllipse() routines.

    Caution:
    --------
    If you attempt to fill an area outside the bounds of the BitMap,
    using the basic initialized RastPort, it may crash the system. You
    must either do your own software clipping to assure that the area is
    in range, or use the layers library.


27 / / Using the Graphics Drawing Routines / Flood-fill Operations

Flood fill is a technique for filling an arbitrary shape with a color.
The Amiga flood-fill routines can use a plain color or do the fill using a
combination of the drawing mode, FgPen, BgPen and the area pattern.

Flood-fill requires a TmpRas structure at least as large as the RastPort
in which the flood-fill will be done.  This is to ensure that even if the
flood-filling operation "leaks", it will not flow outside the TmpRas and
corrupt another task's memory.

You use the Flood() routine for flood fill. The syntax for this routine is
as follows:

    Flood(&rastPort, mode, x, y);

The rastPort argument specifies the RastPort you want to draw into.  The x
and y arguments specify the starting coordinate within the BitMap.  The
mode argument tells how to do the fill.  There are two different modes for
flood fill:

Outline Mode
    In outline mode, you specify an x,y coordinate, and from that point
    the system searches outward in all directions for a pixel whose color
    is the same as that specified in the area outline pen (AOlPen).  All
    horizontally or vertically adjacent pixels not of that color are
    filled with a colored pattern or plain color.  The fill stops at the
    outline color. Outline mode is selected when the mode argument to
    Flood() is set to a 0.

Color Mode
    In color mode, you specify an x,y coordinate, and whatever pixel
    color is found at that position defines the area to be filled. The
    system searches for all horizontally or vertically adjacent pixels
    whose color is the same as this one and replaces them with the
    colored pattern or plain color.  Color mode is selected when the mode
    argument ot Flood() is set to a one.

The following sample program fragment creates and then flood-fills a
triangular region. The overall effect is exactly the same as shown in the
preceding area-fill example above, except that flood-fill is slightly
slower than area-fill. Mode 0 (fill to a pixel that has the color of the
outline pen) is used in the example.

    BYTE oldAPen;
    UWORD oldDrPt;
    struct RastPort *rastPort = Window->RPort;

    /* Save the old values of the foreground pen and draw pattern. */
    oldAPen = rastPort->FgPen;
    oldDrPt = rastPort->LinePtrn;

    /* Use AreaOutline pen color for foreground pen. */
    SetAPen(rastPort, rastPort->AOlPen);
    SetDrPt(rastPort, ~0);      /* Insure a solid draw pattern. */

    Move(rastPort, 0, 0);  /* Using mode 0 to create a triangular shape */
    Draw(rastPort, 0, 100);
    Draw(rastPort, 100, 100);
    Draw(rastPort, 0, 0);       /* close it */

    SetAPen(rastPort, oldAPen); /* Restore original foreground pen. */
    Flood(rastPort, 0, 10, 50); /* Start Flood() inside triangle. */

    SetDrPt(rastPort, oldDrPt); /* Restore original draw mode. */

This example saves the current FgPen value and draws the shape in the same
color as AOlPen. Then FgPen is restored to its original color so that
FgPen, BgPen, DrawMode, and AreaPtrn can be used to define the fill within
the outline.


27 / / Using the Graphics Drawing Routines / Rectangle-fill Operations

The final fill function, RectFill(), is for filling rectangular areas.
The form of this function follows:

    RectFill(&rastPort, xmin, ymin, xmax, ymax);

As usual, the rastPort argument specifies the RastPort you want to draw
into.  The xmin and ymin arguments specify the upper left corner of the
rectangle to be filled. The xmax and ymax arguments specify the lower
right corner of the rectangle to be filled.  Note that the variable xmax
must be equal to or greater than xmin, and ymax must be equal to or
greater than ymin.

Rectangle-fill uses FgPen, BgPen, AOlPen, DrawMode, AreaPtrn and Mask to
fill the area you specify. Remember that the fill can be multicolored as
well as single- or two-colored.  When the DrawMode is COMPLEMENT, it
complements all bit planes, rather than only those planes in which the
foreground is non-zero.


27 / Drawing Routines / Performing Data Move Operations

The graphics library includes several routines that use the hardware
blitter to handle the rectangularly organized data that you work with when
doing raster-based graphics.  These blitter routines do the following:

      * Clear an entire segment of memory

      * Set a raster to a specific color

      * Scroll a subrectangle of a raster

      * Draw a pattern "through a stencil"

      * Extract a pattern from a bit-packed array and draw it into a
        raster

      * Copy rectangular regions from one bitmap to another

      * Control and utilize the hardware-based data mover, the blitter

The following sections cover these routines in detail.

    WARNING:
    --------
    The graphics library rendering and data movement routines generally
    wait to get access to the blitter, start their blit, and then exit
    without waiting for the blit to finish.  Therefore, you must
    WaitBlit() after a graphics rendering or data movement call if you
    intend to immediately deallocate, examine, or perform order-dependent
    processor operations on the memory used in the call.

 Clearing a Memory Area
 Setting a Whole Raster to a Color
 Scrolling a Sub-rectangle of a Raster
 Drawing through a Stencil
 Extracting from a Bit-packed Array
 Copying Rectangular Areas
 Scaling Rectangular Areas
 When to Wait for the Blitter
 Accessing the Blitter Directly


27 / / Performing Data Move Operations / Clearing a Memory Area

For memory that is accessible to the blitter (that is, internal Chip
memory), the most efficient way to clear a range of memory is to use the
blitter. You use the blitter to clear a block of memory with the statement:

    BltClear(memblock, bytecount, flags);

The memblock argument is a pointer to the location of the first byte to be
cleared and bytecount is the number of bytes to set to zero.  In general
the flags variable should be set to one to wait for the blitter operation
to complete.  Refer to the Amiga ROM Kernel Manual: Includes and Autodocs
for other details about the flag argument.


27 / / Data Move Operations / Setting a Whole Raster to a Color

You can preset a whole raster to a single color by using the function
SetRast(). A call to this function takes the following form:

    SetRast(&rastPort, pen);

As always, the &rastPort is a pointer to the RastPort you wish to use.
Set the pen argument to the color register you want to fill the RastPort
with.


27 / / Data Move Operations / Scrolling a Sub-rectangle of a Raster

You can scroll a sub-rectangle of a raster in any direction--up, down,
left, right, or diagonally. To perform a scroll, you use the
ScrollRaster() routine and specify a dx and dy (delta-x, delta-y) by which
the rectangle image should be moved relative to the (0,0) location.

As a result of this operation, the data within the rectangle will become
physically smaller by the size of delta-x and delta-y, and the area
vacated by the data when it has been cropped and moved is filled with the
background color (color in BgPen). ScrollRaster() is affected by the Mask
setting.

Here is the syntax of the ScrollRaster() function:

    ScrollRaster(&rastPort, dx, dy, xmin, ymin, xmax, ymax);

The &rastPort argument is a pointer to a RastPort.  The dx and dy
arguments are the distances (positive, 0, or negative) to move the
rectangle.  The outer bounds of the sub-rectangle are defined by the xmin,
xmax, ymin and ymax arguments.

Here are some examples that scroll a sub-rectangle:

    /* scroll up 2 */
    ScrollRaster(&rastPort, 0, 2, 10, 10, 50, 50);

    /* scroll right 1 */
    ScrollRaster(&rastPort, -1, 0, 10, 10, 50, 50);

When scrolling a Simple Refresh window (or other layered RastPort),
ScrollRaster() scrolls the appropriate existing damage region.  Refer to
the "Intuition Windows" chapter for an explanation of Simple Refresh
windows and damage regions.

When scrolling a SuperBitMap window ScrollRaster() requires a properly
initialized TmpRas.  The TmpRas must be initialized to the size of one
bitplane with a width and height the same as the SuperBitMap, using the
technique described in the "Area-Fill Information" section above.

If you are using a SuperBitMap Layer, it is possible that the information
in the BitMap is not fully reflected in the layer and vice-versa.  Two
graphics calls, CopySBitMap() and SyncSBitMap(), remedy these situations.
Again, refer to the "Intuition Windows" chapter for more on this.


27 / / Performing Data Move Operations / Drawing through a Stencil

The routine BltPattern() allows you to change only a very selective
portion of a drawing area. Basically, this routine lets you define a
rectangular region to be affected by a drawing operation and a mask of the
same size that further defines which pixels within the rectangle will be
affected.

The figure below shows an example of what you can do with BltPattern().

                   · = 0 bits    o & # = 1 bits

         Mask contains                   Drawing area contains:

         · · o · o · ·                       · · · · · · ·
         · · o · o · ·                       · # # # # # ·
         · · o · o · ·                       # · · · · · ·
         · · o · o · ·                       · # # # # # ·
         · · o · o · ·                       · · · · · · #
         · · o · o · ·                       · # # # # # ·
         · · o · o · ·                       · · · · · · ·

                       \                   /
                        \                 /
                         \               /

                           · · o · o · ·
                           · # o # o # ·
                           # · o · o · ·
                           · # o # o # ·
                           · · o · o · #
                           · # o # o # ·
                           · · o · o · ·

                      Result of BitPattern():

         Figure 27-17: Example of Drawing Through a Stencil

In the resulting drawing, the lighter squares show where the target
drawing area has been affected.  Exactly what goes into the drawing area
when the mask has 1's is determined by your RastPort's FgPen, BgPen,
DrawMode and AreaPtrn fields.

You call BltPattern() with:

    BltPattern(&rastport, mask, xl, yl, maxx, maxy, bytecnt)

The &rastport argument specifies the RastPort to use.  The operation will
be confined to a rectangular area within the RastPort specified by xl and
yl (upper right corner of the rectangle) and maxx and maxy (lower right
corner of the rectangle).

The mask is a pointer to the mask to use.  This can be NULL, in which case
a simple rectangular region is modified.  Or it can be set to the address
of a byte pattern which allows any arbitrary shape within the rectangle to
be defined.  The bytecount is the number of bytes per row for the mask (it
must be an even number of bytes).

The mask parameter is a rectangularly organized, contiguously stored
pattern.  This means that the pattern is stored in sequential memory
locations stored as (maxy - yl + 1) rows of bytecnt bytes per row.  These
patterns must obey the same rules as BitMaps.  This means that they must
consist of an even number of bytes per row and must be stored in memory
beginning at a legal word address. (The mask for BltPattern() does not
have to be in Chip RAM, though.)


27 / / Data Move Operations / Extracting from a Bit-packed Array

You use the routine BltTemplate() to extract a rectangular area from a
source area and place it into a destination area. The following figure
shows an example.

     Array Start -->· · · · · · · · · · * * * · · ·<-- Line 1 end
  Line 1 end + 1 -->· · · · · · · · · · · * · · · ·
                    · · · · · · · · · · · * · · · ·
                    · · · · · · · · · · · * · · · ·
                    · · · · · · · · · · · * · · · ·
                    · · · · · · · · · · · * · · · ·
                    · · · · · · · · · · * * * · · ·

                    ------------------->
                Character starts 10-bits
               in from starting point on
              the left edge of the array.

    Figure 27-18: Example of Extracting from a Bit-Packed Array

For a rectangular bit array to be extracted from within a larger,
rectangular bit array, the system must know how the larger array is
organized.  For this extraction to occur properly, you also need to tell
the system the modulo for the inner rectangle. The modulo is the value
that must be added to the address pointer so that it points to the correct
word in the next line in this rectangularly organized array.

The following figure represents a single bitplane and the smaller
rectangle to be extracted. The modulo in this instance is 4, because at
the end of each line, you must add 4 to the address pointer to make it
point to the first word in the smaller rectangle.

   ________________________________________________
  |                                                |
  |  20    21    22    23    24    25    26    27  |<-- Larger source
  |                                                |    bit-plane image
  |  28    29    30    31    32    33    34    35  |
  |             ----------------------             |
  |  36    37  | 38    39    40    41 |  42    43  |
  |            |                      |<-----------|--- Smaller rectangle
  |  44    45  | 46    47    48    49 |  50    51  |    to be extracted
  |            |                      |            |
  |  52    53  | 54    55    56    57 |  58    59  |
  |             ----------------------             |
  |  60    61    62    63    64    65    66    67  |
  |________________________________________________|

                Figure 27-19: Modulo

    Warning:
    --------
    The modulo value must be an even number of bytes.

BltTemplate() takes the following arguments:

    BltTemplate(source, srcX, srcMod, &destRastPort, destX, destY,
                sizeX, sizeY);

The source argument specifies the rectangular bit array to use as the
source template.  Set this to the address of the nearest word (rounded
down) that contains the first line of the source rectangle.  The srcX
argument gives the exact bit position (0-15) within the source address at
which the rectangular bit array begins.  The srcMod argument sets the
source modulo so the next line of the rectangular bit array can be found.

The data from the source rectangle is copied into the destination RastPort
specified by destRastPort. The destX and destY arguments indicate where
the data from the source rectangle should be positioned within the
destination RastPort.  The sizeX and sizeY arguments indicate the
dimensions of the data to be moved.

BltTemplate() uses FgPen, BgPen, DrawMode and Mask to place the template
into the destination area. This routine differs from BltPattern() in that
only a solid color is deposited in the destination drawing area, with or
without a second solid color as the background (as in the case of text).
Also, the template can be arbitrarily bit-aligned and sized in x.


27 / / Performing Data Move Operations / Copying Rectangular Areas

Four routines use the blitter to copy rectangular areas from one section
of a BitMap to another: BltBitMap(), BltBitMapRastPort(),
BltMaskBitMapRastPort(), and ClipBlit().  All four of these blitter
routines take a special argument called a minterm.

The minterm variable is an unsigned byte value which represents an action
to be performed during the move.  Since all the blitter routines uses the
hardware blitter to move the data, they can take advantage of the
blitter's ability to logically combine or change the data as the move is
made.  The most common operation is a direct copy from source area to
destination, which uses a minterm set to hex value C0.

You can determine how to set the minterm variable by using the logic
equations shown in the following tables.  B represents data from the
source rectangle and C represents data in the destination area.

             Table 27-7: Minterm Logic Equations

            Leftmost 4 Bits    Logic Term Included
             of MinTermin         Final Output
             ------------         ------------
                  8                    BC  "B AND C"
                                        _
                  4                    BC  "B AND NOT C"
                                       _
                  2                    BC  "NOT B AND C"
                                       __
                  1                    BC  "NOT B AND NOT C"

You can combine values to select the logic terms.  For instance a minterm
value of 0xC0 selects the first two logic terms in the table above.  These
logic terms specify that in the final destination area you will have data
that occurs in source B only.  Thus, C0 means a direct copy.  The logic
equation for this is:
          _         _
    BC + BC = B(C + C) = B

Logic equations may be used to decide on a number of different ways of
moving the data.  For your convenience, a few of the most common ones are
listed below.

    Table 27-8: Some Common MinTerm Values to Use for Copying

    MinTerm
     Value        Logic Operation Performed During Copy
     -----        -------------------------------------
      30       Replace destination area with inverted source B.

      50       Replace destination area with an inverted version
               of itself.

      60       Put B where C is not, put C where B is not (cookie cut).

      80       Only put bits into destination where there is a bit in
               the same position for both source and destination (sieve
               operation).

      C0       Plain vanilla copy from source B to destination C.

The graphics library blitter routines all accept a minterm argument as
described above.  BltBitMap() is the basic blitter routine, moving data
from one BitMap to another.

BltBitMap() allows you to define a rectangle within a source BitMap and
copy it to a destination area of the same size in another (or even the
same) BitMap.  This routine is used by the graphics library itself for
rendering.  BltBitMap() returns the number of planes actually involved in
the blit.  The syntax for the function is:

    ULONG planes;

    planes = BltBitMap(&srcBM, srcX, srcY, &dstBM, dstX, dstY,
                 sizeX, sizeY, minterm, mask, tempA);

The source bitmap is specified by the &srcBM argument.  The position of
the source area within the bitmap is specified by srcX and srcY.  The
destination bitmap is specified by the &dstBM argument.  The position of
the destination area within the bitmap is specified by dstX and dstY.

The dimensions (in pixels) of the area to be moved is indicated by the
sizeX and sizeY arguments.  With the original custom chip set, the blitter
size limits are 992 x 1024.  With ECS the blitter size limits are 32,736 x
32,768.  See the section on "Determining Chip Versions" earlier in this
chapter to find out how to tell if the host system has ECS installed.

The minterm argument determines what logical operation to perform on the
rectangle data as bits are moved (described above).  The mask argument,
normally set to 0xff, specifies which bitplanes will be involved in the
blit operation and which will be ignored.  If a bit is set in the mask
byte, the corresponding bitplane is included.  The tempA argument applies
only to blits that overlap and, if non-NULL, points to Chip memory the
system will use for temporary storage during the blit.

BltBitMapRastPort() takes most of the same arguments as BltBitMap(), but
its destination is a RastPort instead of a BitMap.  The syntax for the
function is:

    VOID BltBitMapRastPort(&srcBM, srcX, srcY, &dstRP, dstX, dstY,
             sizeX, sizeY, minterm);

The arguments here are the same as for BltBitMap() above.  Note that the
BltBitMapRastPort() function will respect the RastPort.Mask field.  Only
the planes specified in the Mask will be included in the operation.

A third type of blitter operation is provided by the
BltMaskBitMapRastPort() function.  This works the same as
BltBitMapRastPort() except that it takes one extra argument, a pointer to
a single bitplane mask of the same height and width as the source.  The
mask acts as a filter for the operation--a blit only occurs where the mask
plane is non-zero.  The syntax for the function is:

    VOID BltMaskBitMapRastPort(&srcBM, srcX, srcY, &dstRP, dstX, dstY,
             sizeX, sizeY, minterm, bltmask);

The bltmask argument points to a word-aligned mask bitplane in Chip memory
with the same dimensions as the source bitmap.  Note that this function
ignores the Mask field of the destination RastPort.

ClipBlit() takes most of the same arguments as the other blitter calls
described above but it works with source and destination RastPorts and
their layers.  Before ClipBlit() moves data, it looks at the area from
which and to which the data is being copied (RastPorts, not BitMaps) and
determines if there are overlapping areas involved.  If so, it splits up
the overall operation into a number of bitmaps to move the data in the way
you request.  To call ClipBlit() use:

    VOID ClipBlit(&srcRP, srcX, srcY, &dstRP, dstX, dstY, XSize, YSize,
                  minterm);

Since ClipBlit() respects the Layer of the source and destination
RastPort, it is the easiest blitter movement call to use with Intuition
windows.  The following code fragments show how to save and restore an
undo buffer using ClipBlit().

    /* Save work rastport to an undo rastport */
    ClipBlit(&drawRP, 0, 0, &undoRP, 0, 0, areaWidth, areaHeight, 0xC0);

    /* restore undo rastport to work rastport */
    ClipBlit(&undoRP, 0, 0, &drawRP, 0, 0, areaWidth, areaHeight, 0xC0);


27 / / Performing Data Move Operations / Scaling Rectangular Areas

BitMapScale() will scale a single bitmap any integral size up to 16,383
times its original size.  This function is available only in Release 2 and
later versions of the OS.  It is called with the address of a BitScaleArgs
structure (see <graphics/scale.h>).

    void BitMapScale(struct BitScaleArgs *bsa)

The bsa argument specifies the BitMaps to use, the source and destination
rectangles, as well as the scaling factor.  The source and destination may
not overlap.  The caller must ensure that the destination BitMap is large
enough to receive the scaled-up copy of the source rectangle.  The
function ScalerDiv() is provided to help in the calculation of the
destination BitMap's size.


27 / / Performing Data Move Operations / When to Wait for the Blitter

This section explains why you might have to call WaitBlit(), a special
graphics function that suspends your task until the blitter is idle.  Many
of the calls in the graphics library use the Amiga's hardware blitter to
perform their operation, most notably those which render text and images,
fill or pattern, draw lines or dots and move blocks of graphic memory.

Internally, these graphics library functions operate in a loop, doing
graphic operations with the blitter one plane at a time as follows:

    OwnBlitter();    /* Gain exclusive access to the hardware blitter    */

    for(planes=0; planes < bitmap->depth; planes++)
            {
            WaitBlit();    /* Sleep until the previous blitter operation */
                           /* completes start a blit                     */
            }

    DisownBlitter(); /* Release exclusive access to the hardware blitter */

Graphics library functions that are implemented this way always wait for
the blitter at the start and exit right after the final blit is started.
It is important to note that when these blitter-using functions return to
your task, the final (or perhaps only) blit has just been started, but not
necessarily completed.  This is efficient if you are making many such
calls in a row because the next graphics blitter call always waits for the
previous blitter operation to complete before starting its first blit.

However, if you are intermixing such graphics blitter calls with other
code that accesses the same graphics memory then you must first WaitBlit()
to make sure that the final blit of a previous graphics call is complete
before you use any of the memory.  For instance, if you plan to
immediately deallocate or reuse any of the memory areas which were passed
to your most recent blitter-using function call as a source, destination,
or mask, it is imperative that you first call WaitBlit().

    Warning:
    --------
    If you do not follow the above procedure, you could end up with a
    program that works correctly most of the time but crashes sometimes.
    Or you may run into problems when your program is run on faster
    machines or under other circumstances where the blitter is not as
    fast as the processor.


27 / / Performing Data Move Operations / Accessing Blitter Directly

To use the blitter directly, you must first be familiar with how its
registers control its operation.  This topic is covered thoroughly in the
Amiga Hardware Reference Manual and is not repeated here.  There are two
basic approaches you can take to perform direct programming of the
blitter: synchronous and asynchronous.

  * Synchronous programming of the blitter is used when you want to do a
    job with the blitter right away.  For synchronous programming, you
    first get exclusive access to the blitter with OwnBlitter().  Next
    call WaitBlit() to ensure that any previous blitter operation that
    might have been in progress is completed.  Then set up your blitter
    operation by programming the blitter registers.  Finally, start the
    blit and call DisownBlitter().

  * Asynchronous programming of the blitter is used when the blitter
    operation you want to perform does not have to happen immediately.
    In that case, you can use the QBlit() and QBSBlit() functions in
    order to queue up requests for the use of the blitter on a
    non-exclusive basis.  You share the blitter with system tasks.

Whichever approach you take, there is one rule you should generally keep
in mind about using the blitter directly:

    Don't Tie Up The Blitter.
    -------------------------
    The system uses the blitter extensively for disk and display
    operation.  While your task is using the blitter, many other system
    processes will be locked out.  Therefore, use it only for brief
    periods and relinquish it as quickly as possible.

To use QBlit() and QBSBlit(), you must create a data structure called a
bltnode (blitter node) that contains a pointer to the blitter code you
want to execute.  The system uses this structure to link blitter usage
requests into a first-in, first-out (FIFO) queue.  When your turn comes,
your own blitter routine can be repeatedly called until your routine says
it is finished using the blitter.

Two separate blitter queues are maintained.  One queue is for the QBlit()
routine.  You use QBlit() when you simply want something done and you do
not necessarily care when it happens.  This may be the case when you are
moving data in a memory area that is not currently being displayed.

The second queue is maintained for QBSBlit(). QBS stands for
"queue-beam-synchronized".  QBSBlit() requests form a beam-synchronized
FIFO queue.  When the video beam gets to a predetermined position, your
blitter routine is called.  Beam synchronization takes precedence over the
simple FIFO.  This means that if the beam sync matches, the
beam-synchronous blit will be done before the non-synchronous blit in the
first position in the queue.  You might use QBSBlit() to draw into an area
of memory that is currently being displayed to modify memory that has
already been "passed-over" by the video beam.  This avoids display flicker
as an area is being updated.

The sole input to both QBlit() and QBSBlit() is a pointer to a bltnode
data structure, defined in the include file <hardware/blit.h>.  Here is a
copy of the structure, followed by details about the items you must
initialize:

    struct bltnode
    {
        struct  bltnode *n;
        int     (*function)();
        char    stat;
        short   blitsize;
        short   beamsync;
        int     (*cleanup)();
    };

struct bltnode *n;
    This is a pointer to the next bltnode, which, for most applications
    will be zero.  You should not link bltnodes together.  This is to be
    performed by the system in a separate call to QBlit() or QBSBlit().

int (*function)( );
    This is the address of your blitter function that the blitter queuer
    will call when your turn comes up.  Your function must be formed as a
    subroutine, with an RTS instruction at the end. Follow Amiga
    programming conventions by placing the return value in D0 (or in C,
    use return(value)).

    If you return a nonzero value, the system will call your routine
    again next time the blitter is idle until you finally return 0.  This
    is done so that you can maintain control over the blitter; for
    example, it allows you to handle all five bitplanes if you are
    blitting an object with 32 colors.  For display purposes, if you are
    blitting multiple objects and then saving and restoring the
    background, you must be sure that all planes of the object are
    positioned before another object is overlaid.  This is the reason for
    the lockup in the blitter queue; it allows all work per object to be
    completed before going on to the next one.

    Note:
    -----
    Not all C compilers can handle *function() properly!  The system
    actually tests the processor status codes for a condition of
    equal-to-zero (Z flag set) or not-equal-to-zero (Z flag clear) when
    your blitter routine returns.  Some C compilers do not set the
    processor status code properly (i.e., according to the value
    returned), thus it is not possible to use such compilers to write the
    (*function)()) routine.  In that case assembly language should be
    used.  Blitter functions are normally written in assembly language
    anyway so they can take advantage of the ability of QBlit() and
    QBSBlit() to pass them parameters in processor registers.

    The register passing conventions for these routines are as follows.
    Register A0 receives a pointer to the system hardware registers so
    that all hardware registers can be referenced as an offset from that
    address.  Register A1 contains a pointer to the current bltnode.  You
    may have queued up multiple blits, each of which perhaps uses the
    same blitter routine.  You can access the data for this particular
    operation as an offset from the value in A1.  For instance, a typical
    user of these routines can precalculate the blitter register values
    to be placed in the blitter registers and, when the routine is
    called, simply copy them in.  For example, you can create a new
    structure such as the following:

        INCLUDE "exec/types.i"
        INCLUDE "hardware/blit.i"

        STRUCTURE mybltnode,0
                          ; Make this new structure compatible with a
                          ; bltnode by making the first element a bltnode
                          ;  structure.
        STRUCT bltnode,bn_SIZEOF
                UWORD   bltcon1         ; Blitter control register 1.
                UWORD   fwmask          ; First and last word masks.
                UWORD   lwmask
                UWORD   bltmda          ; Modulos for sources a, b,and c.
                UWORD   bltmdb
                UWORD   bltmdc
                UWORD   any_more_data   ; add anything else you want
        LABEL mbn_SIZEOF

    Other forms of data structures are certainly possible, but this
    should give you the general idea.

char stat;
    Tells the system whether or not to execute the clean-up routine at
    the end.  This byte should be set to CLEANUP (0x40) if cleanup is to
    be performed.  If not, then the bltnode cleanup variable can be zero.

short beamsync;
    The value that should be in the VBEAM counter for use during a
    beam-synchronous blit before the function() is called. The system
    cooperates with you in planning when to start a blit in the routine
    QBSBlit() by not calling your routine until, for example, the video
    beam has already passed by the area on the screen into which you are
    writing.  This is especially useful during single buffering of your
    displays.  There may be time enough to write the object between scans
    of the video display. You will not be visibly writing while the beam
    is trying to scan the object.  This avoids flicker (part of an old
    view of an object along with part of a new view of the object).

int (*cleanup)();
    The address of a routine that is to be called after your last return
    from the QBlit() routine.  When you finally return a zero, the queuer
    will call this subroutine (ends in RTS or return()) as the clean-up.
    Your first entry to the function may have dynamically allocated some
    memory or may have done something that must be undone to make for a
    clean exit.  This routine must be specified.


27 Graphics Primitives / User Copper Lists

The Copper coprocessor allows you to produce mid-screen changes in certain
hardware registers in addition to changes that the system software already
provides.  For example, it is the Copper that allows the Amiga to split
the viewing area into multiple draggable screens, each with its own
independent set of colors.

To create your own mid-screen effects on the system hardware registers,
you provide "user Copper lists" that can be merged into the system Copper
lists.

In the ViewPort data structure there is a pointer named UCopIns.  If this
pointer value is non-NULL, it points to a user Copper list that you have
dynamically allocated and initialized to contain your own special
hardware-stuffing instructions.

You allocate a user Copper list by an instruction sequence such as the
following:

    struct UCopList *uCopList = NULL;

    /* Allocate memory for the Copper list.  Make certain that the */
    /* initial memory is cleared.                                  */
    uCopList = (struct UCopList *)
            AllocMem(sizeof(struct UCopList), MEMF_PUBLIC|MEMF_CLEAR);

    if (uCopList == NULL)
            return(FALSE);

    Note:
    -----
     User Copper lists do not have to be in Chip RAM.

 Copper List Macros    Copper List Example


27 / User Copper Lists / Copper List Macros

Once this pointer to a user Copper list is available, you can use it with
system macros (<graphics/gfxmacros.h>) to instruct the system what to add
to its own list of things for the Copper to do within a specific ViewPort.
The file <graphics/gfxmacros.h> provides the following five macro
functions that implement user Copper instructions.

CINIT initializes the Copper list buffer. It is used to specify how many
instructions are going to be placed in the Copper list.  It is called as
follows.

    CINIT(uCopList, num_entries);

The uCopList argument is a pointer tot he user Copper list and num_entries
is the number of entries in the list.

CWAIT waits for the video beam to reach a particular horizontal and
vertical position.  Its format is:

    CWAIT(uCopList, v, h)

Again, uCopList is the pointer to the Copper list.  The v argument is the
vertical position for which to wait, specified relative to the top of the
ViewPort.  The legal range of values (for both NTSC and PAL) is from 0 to
255; h is the horizontal position for which to wait.  The legal range of
values (for both NTSC and PAL) is from 0 to 226.

CMOVE installs a particular value into a specified system register. Its
format is:

    CMOVE(uCopList, reg, value)

Again, uCopList is the pointer to the Copper list.  The reg argument is
the register to be affected, specified in this form:  custom.register-name
where the register-name is one of the registers listed in the Custom
structure in <hardware/custom.h>.  The value argument to CMOVE is the
value to place in the register.

CBump() increments the user Copper list pointer to the next position in
thelist.  It is usually invoked for the programmer as part of the macro
definitions CWAIT or CMOVE.  Its format is:

    CBump(uCopList)

where uCopList is the pointer to the user Copper list.

CEND terminates the user Copper list.  Its format is:

    CEND(uCopList)

where uCopList is the pointer to the user Copper list.

Executing any of the user Copper list macros causes the system to
dynamically allocate special data structures called intermediate Copper
lists that are linked into your user Copper list (the list to which
uCopList points) describing the operation. When you call the function
MrgCop(&view) as shown in the section called "Forming A Basic Display,"
the system uses all of its intermediate Copper lists to sort and merge
together the real Copper lists for the system (LOFCprList and SHFCprList).

When your program exits, you must return to the system all of the memory
that you allocated or caused to be allocated.  This means that you must
return the intermediate Copper lists, as well as the user Copper list data
structure.  Here are two different methods for returning this memory to
the system.

    /* Returning memory to the system if you have NOT
     * obtained the ViewPort from Intuition.  */
    FreeVPortCopLists(viewPort);

    /* Returning memory to the system if you HAVE
     * obtained the ViewPort from Intuition.  */
    CloseScreen(screen);    /* Intuition only */

User Copper lists may be clipped, under Release 2 and later, to ViewPort
boundaries if the appropriate tag (VTAG_USERCLIP_SET) is passed to
VideoControl().  Under earlier releases, the user Copper list would "leak"
through to lower ViewPorts.


27 Graphics Primitives / ECS and Genlocking Features

The Enhanced Chip Set (ECS) Denise chip (8373-R2a), coupled with the
Release 2 graphics library, opens up a whole new set of genlocking
possibilities.  Unlike the old Denise, whose only genlocking ability
allowed keying on color register zero, the ECS Denise allows keying on any
color register.  Also, the ECS Denise allows keying on any bitplane of the
ViewPort being genlocked.  With the ECS Denise, the border area
surrounding the display can be made transparent (always passes video) or
opaque (overlays using color 0).  All the new features are set
individually for each ViewPort.  These features can be used in conjunction
with each other, making interesting scenarios possible.

 Genlock Control


27 / ECS and Genlocking Features / Genlock Control

Using VideoControl(), a program can enable, disable, or obtain the state
of a ViewPort's genlocking features.  It returns NULL if no error
occurred.  The function uses a tag based interface:

    error = BOOL VideoControl( struct ColorMap *cm, struct TagItem *ti );

The ti argument is a list of video commands stored in an array of TagItem
structures.  The cm argument specifies which ColorMap and, indirectly,
which ViewPort these genlock commands will be applied to.  The possible
commands are:

    VTAG_BITPLANEKEY_GET, _SET, _CLR
    VTAG_CHROMA_PLANE_GET, _SET
    VTAG_BORDERBLANK_GET, _SET, _CLR
    VTAG_BORDERNOTRANS_GET, _SET, _CLR
    VTAG_CHROMAKEY_GET, _SET, _CLR
    VTAG_CHROMAPEN_GET, _SET, _CLR

This section covers only the genlock VideoControl() tags.  See
<graphics/videocontrol.h> for a complete list of all the available tags
you can use with VideoControl().

VTAG_BITPLANEKEY_GET is used to find out the status of the bitplane keying
mode.  VTAG_BITPLANEKEY_SET and VTAG_BITPLANEKEY_CLR activate and
deactivate bitplane keying mode.  If bitplane key mode is on, genlocking
will key on the bits set in a specific bitplane from the ViewPort (the
specific bitplane is set with a different tag).  The data portion of these
tags is NULL.

For inquiry commands like VTAG_BITPLANEKEY_GET (tags ending in _GET),
VideoControl() changes the _GET tag ID (ti_Tag) to the corresponding _SET
or _CLR tag ID, reflecting the current state of the genlock mode.  For
example, when passed the following tag array:

    struct TagItem videocommands[] =
    {
        {VTAG_BITPLANEKEY_GET, NULL},
        {VTAG_END_CM, NULL}
    };

VideoControl() changes the VTAG_BITPLANEKEY_GET tag ID (ti_Tag) to
VTAG_BITPLANEKEY_SET if bitplane keying is currently on, or to
VTAG_BITPLANEKEY_CLR if bitplane keying is off.  In both of these cases,
VideoControl() only uses the tag's ID, ignoring the tag's data field
(ti_Data).

The VTAG_CHROMA_PLANE_GET tag returns the number of the bitplane keyed on
when bitplane keying mode is on.  VideoControl() changes the tag's data
value to the bitplane number.  VTAG_CHROMA_PLANE_SET sets the bitplane
number to the tag's data value.

VTAG_BORDERBLANK_GET is used to obtain the border blank mode status. This
tag works exactly like VTAG_BITPLANEKEY_GET.  VideoControl() changes the
tag's ID to reflect the current border blanking state.
VTAG_BORDERBLANK_SET and VTAG_BORDERBLANK_CLR activate and deactivate
border blanking.  If border blanking is on, the Amiga will not display
anything in its display border, allowing an external video signal to show
through the border area.  On the Amiga display, the border appears black.
The data portion of these tags is NULL.

The VTAG_BORDERNOTRANS_GET, _SET and _CLR tags are used, respectively, to
obtain the status of border-not-transparent mode, and to activate and to
deactivate this mode.  If set, the Amiga display's border will overlay
external video with the color in register 0.  Because border blanking mode
takes precedence over border-not-transparent mode, setting
border-not-transparent has no effect if border blanking is on.  The data
portion of these tags is NULL.

The VTAG_CHROMAKEY_GET, _SET and _CLR tags are used, respectively, to
obtain the status of chroma keying mode, and to activate and deactivate
chroma keying mode.  If set, the genlock will key on colors from specific
color registers (the specific color registers are set using a different
tag).  If chroma keying is not set, the genlock will key on color register
0.  The data portion of these tags is NULL.

VTAG_CHROMAPEN_GET obtains the chroma keying status of an individual color
register.  The tag's ti_Data field contains the register number.  Like the
other _GET tags, VideoControl() changes the tag ID (ti_Tag) to one that
reflects the current state of the mode.  VTAG_CHROMAPEN_SET and
VTAG_CHROMAPEN_CLR activate and deactivate chroma keying for each
individual color register.  Chroma keying can be active for more than one
register.  By turning off border blanking and activating chroma keying
mode, but turning off chroma keying for each color register, a program can
overlay every part of an external video source, completely blocking it out.

After using VideoControl() to set values in the ColorMap, the
corresponding ViewPort has to be rebuilt with MakeVPort(), MrgCop() and
LoadView(), so the changes can take effect.  A program that uses a
screen's ViewPort rather than its own ViewPort should use the Intuition
functions MakeScreen() and RethinkDisplay() to make the display changes
take effect.

The following code fragment shows how to access the genlock modes.

struct Screen *genscreen;
struct ViewPort *vp;
struct TagItem vtags [24];

    /* The complete example opened a window, rendered some colorbars,  */
    /* and added gadgets to allow the user to turn the various genlock */
    /* modes on and off.                                               */

    vp = &(genscreen->ViewPort);

    /* Ascertain the current state of the various modes. */

    /* Is borderblanking on? */
    vtags[0].ti_Tag = VTAG_BORDERBLANK_GET;
    vtags[0].ti_Data = NULL;

    /* Is bordertransparent set? */
    vtags[1].ti_Tag = VTAG_BORDERNOTRANS_GET;
    vtags[1].ti_Data = NULL;

    /* Key on bitplane? */
    vtags[2].ti_Tag = VTAG_BITPLANEKEY_GET;
    vtags[2].ti_Tag = NULL;

    /* Get plane which is used to key on */
    vtags[3].ti_Tag = VTAG_CHROMA_PLANE_GET;
    vtags[3].ti_Data = NULL;

    /* Chromakey overlay on? */
    vtags[4].ti_Tag = VTAG_CHROMAKEY_GET;
    vtags[4].ti_Data = NULL;

    for (i = 0; i < 16; i++)
    {
        /* Find out which colors overlay */
        vtags[i + 5].ti_Tag = VTAG_CHROMA_PEN_GET;
        vtags[i + 5].ti_Data = i;
    }

    /* Indicate end of tag array */
    vtags[21].ti_Tag = VTAG_END_CM;
    vtags[21].ti_Data = NULL;

    /* And send the commands. On return the Tags themselves will
    * indicate the genlock settings for this ViewPort's ColorMap.
    */
    error = VideoControl(vp->ColorMap, vtags);

    /* The complete program sets gadgets to reflect current states. */

    /* Will only send single commands from here on. */
    vtags[1].ti_Tag = VTAG_END_CM;

    /* At this point the complete program gets an input event and
       sets/clears the genlock modes as requested using the vtag list and
       VideoControl().
    */

    /* send video command */
    error = VideoControl(vp->ColorMap, vtags);

    /* Now use MakeScreen() and RethinkDisplay() to make the VideoControl()
    *  changes take effect.  If we were using our own ViewPort rather than
    *  borrowing one from a screen, we would instead do:
    *
    *   MakeVPort(ViewAddress(),vp);
    *   MrgCop(ViewAddress());
    *   LoadView(ViewAddres());
    */
    MakeScreen(genscreen);
    RethinkDisplay();

/* The complete program closes and frees everything it had opened or
   allocated.
*/

/* The complete example calls the CheckPAL function, which is included
   below in its entirety for illustrative purposes.
*/

BOOL CheckPAL(STRPTR screenname)
{
    struct Screen *screen;
    ULONG modeID = LORES_KEY;
    struct DisplayInfo displayinfo;
    BOOL IsPAL;

    if (GfxBase->LibNode.lib_Version >= 36)
    {
        /*
        * We got at least V36, so lets use the new calls to find out what
        * kind of videomode the user (hopefully) prefers.
        */

        if (screen = LockPubScreen(screenname))
        {
            /*
            * Use graphics.library/GetVPModeID() to get the ModeID of the
            * specified screen.  Will use the default public screen
            * (Workbench most of the time) if NULL It is _very_ unlikely
            * that this would be invalid, heck it's impossible.
            */
            if ((modeID = GetVPModeID(&(screen->ViewPort))) != INVALID_ID)
            {
                /*
                * If the screen is in VGA mode, we can't tell whether the
                * system is PAL or NTSC. So to be foolproof we fall back
                * to the displayinfo of the default monitor by inquiring
                * about just the LORES_KEY displaymode if we don't know.
                * The default.monitor reflects the initial video setup of
                * the system, thus for either ntsc.monitor or pal.monitor.
                * We only use the displaymode of the is an alias specified
                * public screen if it's display mode is PAL or NTSC and
                * NOT the default.
                */
                if (!((modeID & MONITOR_ID_MASK) == NTSC_MONITOR_ID ||
                (modeID & MONITOR_ID_MASK) == PAL_MONITOR_ID))
                modeID = LORES_KEY;
            }
            UnlockPubScreen(NULL, screen);
        } /* if fails modeID = LORES_KEY. Can't lock screen, so fall back
          *  on default monitor.
          */

        if (GetDisplayInfoData(NULL, (UBYTE *) & displayinfo,
        sizeof(struct DisplayInfo), DTAG_DISP, modeID))
        {
            if (displayinfo.PropertyFlags & DIPF_IS_PAL)
                IsPAL = TRUE;
            else
                IsPAL = FALSE;
            /* Currently the default monitor is always either PAL or
            *  NTSC.
            */
        }
    }
    else
        /* < V36. The enhancements to the videosystem in V36 (and above)
        *  cannot be better expressed than with the simple way to determine
        *  PAL in V34.
        */
        IsPAL= (GfxBase->DisplayFlags & PAL) ? TRUE : FALSE;

    return(IsPAL);
}


27 Graphics Primitives / Function Reference

The following are brief descriptions of the Amiga's graphics primitives.
See the Amiga ROM Kernel Reference Manual: Includes and Autodocs for
details on each function call.

                Table 27-9: Graphics Primitives Functions
  ________________________________________________________________________
 |                                                                        |
 |         Display                                                        |
 |     Set-up Functions              Description                          |
 |========================================================================|
 |           InitView()  Initializes the View structure.                  |
 |         InitBitMap()  Initializes the BitMap structure.                |
 |            RASSIZE()  Calculates the size of a ViewPort's BitMap.      |
 |        AllocRaster()  Allocates the bitplanes needed for a BitMap.     |
 |         FreeRaster()  Frees the bitplanes created with AllocRaster().  |
 |          InitVPort()  Initializes the ViewPort structure.              |
 |        GetColorMap()  Returns the ColorMap structure used by           |
 |                       ViewPorts.                                       |
 |       FreeColorMap()  Frees the ColorMap created by GetColorMap().     |
 |           LoadRGB4()  Loads the color registers for a given ViewPort.  |
 |          SetRGB4CM()  Loads an individual color register for a given   |
 |                       ViewPort.                                        |
 |          MakeVPort()  Creates the intermediate Copper list program for |
 |                       a ViewPort.                                      |
 |             MrgCop()  Merges the intermediate Copper lists.            |
 |           LoadView()  Displays a given View.                           |
 |        FreeCprList()  Frees the Copper list created with MrgCop()      |
 |  FreeVPortCopLists()  Frees the intermediate Copper lists created with |
 |                       MakeVPort().                                     |
 |        OFF_DISPLAY()  Turns the video display DMA off                  |
 |         ON_DISPLAY()  Turns the video display DMA back on again.       |
 |________________________________________________________________________|

  ________________________________________________________________________
 |                                                                        |
 |    Release 2 Display                                                   |
 |    Set-up Functions               Description                          |
 |========================================================================|
 |     FindDisplayInfo()  Returns the display database handle for a given |
 |                        ModeID (V36).                                   |
 |  GetDisplayInfoData()  Looks up a display attribute in the display     |
 |                        database (V36).                                 |
 |        VideoControl()  Sets, clears and gets the attributes of an      |
 |                        existing display (V36).                         |
 |              GfxNew()  Creates ViewExtra or ViewPortExtra used in      |
 |                        Release 2 displays (V36).                       |
 |        GfxAssociate()  Attaches a ViewExtra to a View (V36).           |
 |             GfxFree()  Frees the ViewExtra or ViewPortExtra created by |
 |                        GfxNew() (V36).                                 |
 |         OpenMonitor()  Returns the MonitorSpec structure used in       |
 |                        Release 2 Views (V36).                          |
 |        CloseMonitor()  Frees the MonitorSpec structure created by      |
 |                        OpenMonitor() (V36).                            |
 |         GetVPModeID()  Returns the Release 2 ModeID of an existing     |
 |                        ViewPort (V36).                                 |
 |    ModeNotAvailable()  Determines if a display mode is available from  |
 |                        a given ModeID (V36).                           |
 |________________________________________________________________________|

  ________________________________________________________________________
 |                                                                        |
 |      Drawing                                                           |
 |     Functions                     Description                          |
 |========================================================================|
 |  InitRastPort()  Initialize a RastPort structure.                      |
 |      InitArea()  Initialize the AreaInfo structure used with a         |
 |                  RastPort.                                             |
 |     SetWrMask()  Set the RastPort.Mask.                                |
 |       SetAPen()  Set the RastPort.FgPen foreground pen color.          |
 |       SetBPen()  Set the RastPort.BgPen background pen color.          |
 |       SetOPen()  Set the RastPort.AOlPen area fill outline pen color.  |
 |     SetDrMode()  Set the RastPort.DrawMode drawing mode.               |
 |       SetDrPt()  Set the RastPort.LinePtrn line drawing pattern.       |
 |       SetAfPt()  Set the RastPort area fill pattern and size.          |
 |------------------------------------------------------------------------|
 |    WritePixel()  Draw a single pixel in the foreground color at a      |
 |                  given coordinate.                                     |
 |     ReadPixel()  Find the color of the pixel at a given coordinate.    |
 |    DrawCircle()  Draw a circle with a given radius and center point.   |
 |   DrawEllipse()  Draw an ellipse with the given radii and center       |
 |                  point.                                                |
 |          Move()  Move the RastPort drawing pen to a given coordinate.  |
 |          Draw()  Draw a line from the current pen location to a given  |
 |                  coordinate.                                           |
 |------------------------------------------------------------------------|
 |      PolyDraw()  Draw a polygon with a given set of vertices.          |
 |      AreaMove()  Set the anchor point for a filled polygon.            |
 |      AreaDraw()  Add a new vertice to an area-fill polygon.            |
 |       AreaEnd()  Close and area-fill polygon, draw it and fill it.     |
 |      BNDRYOFF()  Turn off area-outline pen usage activated with        |
 |                  SetOPen().                                            |
 |    AreaCircle()  Draw a filled circle with a given radius and center   |
 |                  point.                                                |
 |   AreaEllipse()  Draw a filled ellipse with the given radii and center |
 |                  point.                                                |
 |         Flood()  Flood fill a region starting at a given coordinate.   |
 |      RectFill()  Flood fill a rectangular area at a given location and |
 |                  size.                                                 |
 |________________________________________________________________________|

  ________________________________________________________________________
 |                                                                        |
 |         Data Movement                                                  |
 |           Functions               Description                          |
 |========================================================================|
 |               BltClear()  Use the hardware blitter to clear a block of |
 |                           memory.                                      |
 |                SetRast()  Fill the RastPort.BitMap with a given color. |
 |           ScrollRaster()  Move a portion of a RastPort.BitMap.         |
 |             BltPattern()  Draw a rectangular pattern of pixels into a  |
 |                           RastPort.BitMap.  The x-dimension of the     |
 |                           rectangle must be word-aligned and           |
 |                           word-sized.                                  |
 |            BltTemplate()  Draw a rectangular pattern of pixels into a  |
 |                           RastPort.BitMap.  The x-dimension of the     |
 |                           rectangle can be arbitrarily bit-aligned and |
 |                           sized.                                       |
 |              BltBitMap()  Copy a rectangular area from one BitMap to a |
 |                           given coordinate in another BitMap.          |
 |      BltBitMapRastPort()  Copy a rectangular area from a BitMap to a   |
 |                           given coordinate in a RastPort.BitMap.       |
 |  BltMaskBitMapRastPort()  Copy a rectangular area from a BitMap to a   |
 |                           RastPort.BitMap through a mask bitplane.     |
 |               ClipBlit()  Copy a rectangular area from one RastPort to |
 |                           another with respect to their Layers.        |
 |            BitMapScale()  Scale a rectangular area within a BitMap to  |
 |                           new dimensions (V36).                        |
 |________________________________________________________________________|

  ________________________________________________________________________
 |                                                                        |
 |  Hardware Programming                                                  |
 |       Functions                   Description                          |
 |========================================================================|
 |     OwnBlitter()  Obtain exclusive access to the Amiga's hardware      |
 |                   blitter.                                             |
 |  DisownBlitter()  Relinquish exclusive access to the blitter.          |
 |       WaitBlit()  Suspend until the current blitter operation has      |
 |                   completed.                                           |
 |          QBlit()  Place a bltnode-style asynchronous blitter request   |
 |                   in the system queue                                  |
 |        QBSBlit()  Place a bltnode-style asynchronous blitter request   |
 |                   in the beam synchronized queue.                      |
 |------------------------------------------------------------------------|
 |          CINIT()  Initialize the user Copper list buffer.              |
 |          CWAIT()  Instructs the Copper to wait for the video beam to   |
 |                   reach a given position.                              |
 |          CMOVE()  Instructs the Copper to place a value into a given   |
 |                   hardware register.                                   |
 |          CBump()  Instructs the Copper to increment its Copper list    |
 |                   pointer.                                             |
 |           CEND()  Terminate the user Copper list.                      |
 |________________________________________________________________________|


Amiga® RKM Libraries: 28 Graphics Sprites, Bobs and Animation

This chapter describes how to use the functions provided by the graphics
library to manipulate and animate Graphic Elements (also called GELs).  It
is divided into six sections:

  * An overview of the GELs animation system, including fundamental terms
    and structures

  * Explanation of simple (hardware) Sprites and an example showing their
    usage

  * Explanation of VSprites and an example showing their usage

  * Explanation of Bobs and an example showing their usage

  * Discussion of topics that apply to all GELs such as collision
    detection and data structure extensions.

  * Discussion of animation, using AnimComps and AnimObs and an example
    showing their usage

 About the GELs System
 Using Simple (Hardware) Sprites
 Using Virtual Sprites
 Complete VSprite Example
 VSprite Advanced Topics
 Using Bobs
 Collisions and GEL Structure Extensions
 Animation with GELs
 Function Reference


28 Graphics Sprites, Bobs and Animation / About the GELs System

Before going into details, a quick glossary is in order.  A playfield
forms the background that GELs operate in.  It encompasses the View,
ViewPort, and RastPort data structures.  (VSprites appear over, and Bobs
appear in the playfield.)  Playfields can be created and controlled at
several levels.  Refer to the "Graphics Primitives" and "Layers Library"
chapters for details on lower-level playfield control.  The chapter
"Intuition Screens" explains how to get higher-level access to playfields.

GELs, or graphic elements, are special graphic objects that appear in the
foreground and can be moved easily around the display.  They are software
constructs based on the Amiga's sprite and blitter hardware.  The GELs
system is compatible with all playfield modes, including dual-playfield.
All the various types of GELs are defined by data structures found in
<graphics/gels.h>.

 Types of GELs    The GELs System


28 / About the GELs System / Types of GELs

The GEL types are (in order of increasing complexity):

    VSprites   for Virtual Sprites.  These are represented by the VSprite
               data structure and implemented with sprite hardware.

    Bobs       Blitter Objects.  These are represented by the VSprite and
               Bob data structures and implemented with blitter hardware.

    AnimComps  Animation Components.  These are represented by the
               VSprite, Bob and AnimComp data structures and implemented
               with blitter hardware.

    AnimObs    Animation Objects.  These are used to group AnimComps. They
               are not strictly GELs, but are described here.

 Simple Sprites    Bobs and AnimComps    VSprites vs. Bobs
 VSprites          AnimObs


28 / / Types Of GELs / Simple Sprites

Simple Sprites (also known as hardware sprites) are not really part of the
GELs system but are the basis for VSprites.  Simple Sprites are graphic
objects implemented in hardware that are easy to define and easy to
animate. The Amiga hardware has the ability to handle up to eight such
sprite objects.  Each Simple Sprite is produced by one of the Amiga's
eight sprite DMA channels.  They are 16-bits wide and arbitrarily tall.

The Amiga system software offers a choice of how to use these hardware
sprites.  After a sprite DMA channel has displayed the last line of a
Simple Sprite, the system can reuse the channel for a different sprite
lower on the screen.  This is how VSprites are implemented--as a software
construct based on the sprite hardware.

Hence, Simple Sprites are not really part of the animation system (they
are not GELs).  In fact, if Simple Sprites and GELs are used in the same
display, the GELs system must be told specifically which Simple Sprites to
avoid.  Simple Sprites are described in this chapter because they are
alternatives to VSprites.


28 / / Types Of GELs / VSprites

The VSprite, or virtual sprite, is the simplest type of GEL.  The VSprite
data structure contains just a bit more information than is needed to
define a hardware sprite.  VSprites take advantage of the system's ability
to reuse sprite DMA channels--each VSprite can be temporarily assigned to
a hardware sprite, as needed.  This makes it appear to an application
program that it has a virtually unlimited supply of VSprites.

Since VSprites are based on hardware sprites, rules that apply to hardware
sprites apply to VSprites too.  VSprites are not rendered into the
underlying BitMap of the playfield and so do not affect any bits in the
BitMap.  Because they are hardware based, they are positioned at absolute
display coordinates and are not affected by the movement of screens.  The
starting position of a sprite must not occur before scanline 20, because
of certain hardware DMA time constraints.  VSprites have the same size
limitations as hardware sprites, they are 16-bits wide and arbitrarily
tall.

The VSprite data structure also serves as the root structure of more
complex GEL types--Bobs and AnimComps.


28 / / Types Of GELs / Bobs and AnimComps

Like VSprites, Bobs and AnimComps are graphics objects that make animation
easier.  They are rendered using the blitter.  The blitter is a special
Amiga hardware component used to move data quickly and efficiently,
optionally performing logical operations as it does.  It can be used to
move any kind of data but is especially well suited to moving rectangular
blocks of display data.

It is important to keep in mind that Bobs and AnimComps are based on the
blitter hardware while VSprites use the sprite hardware. However all three
GEL types use the VSprite structure as their root data structure.  The
system uses pointers to link the VSprite, Bob and AnimComp structures,
"extending" the VSprite structure to include all GEL types.

Since Bobs and AnimComps are rendered with the blitter they actually
change the underlying playfield BitMap.  The BitMap area where the GEL is
rendered can be saved.  By moving the GEL to new locations in small
increments while also saving and restoring the Bitmap as you proceed, you
can create an animation effect.  Bobs and AnimComps use the same
coordinates as the playfield and can be any size.


28 / / Types Of GELs / AnimObs

The AnimOb (Animation Object) is a data structure that is used to group
one or more AnimComps for convenient movement.  For example, an AnimOb
could be created that consists of two AnimComps, one that looks like a
planet and another containing a sequence that describes orbiting moons.
By moving just the AnimOb the image of the planet can be moved across the
display and the moons will travel along with it, orbiting the planet the
entire time.  The system automatically manages the movement of all the
AnimComps associated with the AnimOb.


28 / / Types Of GELs / VSprites vs. Bobs

If you are going to manage the movement and sequencing of GELS yourself,
you need to decide if sprite animation (VSprites) or blitter animation
(Bobs, AnimComps and AnimObs) best suit your needs.  If you've got simple
requirements or lots of coding time, you may even opt to use only Simple
Sprites, and control them yourself.  On the other hand if you want the
system to manage your animations,  AnimComps must be used and they are
Bobs at heart.

Some fundamental differences between VSprites and Bobs are:

  * VSprite images and coordinates currently low-resolution pixels, even
    on a high resolution display.  Bob images and coordinates have the
    same resolution as the playfield they are rendered into.

  * VSprites have a maximum width of 16 (low resolution) pixels.  Bobs
    can be any width (although large Bobs tend to slow down the system).
    The height of either VSprites or Bobs can be as tall as the display.

  * VSprites have a maximum of three colors (Simple Sprites can have
    fifteen if they're attached).  Because the system uses the Copper to
    control VSprite colors on the fly, the colors are not necessarily the
    same as those in the background playfield.  Bobs can use any or all
    of the colors in the background playfield.  Limiting factors include
    playfield resolution and display time.  Bobs with more colors take
    longer to display.

  * VSprites are positioned using absolute display coordinates, and don't
    move with screens.  Bobs follow screen movement.

In general, VSprites offer speed, while Bobs offer flexibility.

The following figure shows how the various GEL data structures, VSprites,
Bobs and AnimComps are linked together.

       VSPRITE                  BOB                 ANIMCOMP
     ____________           ____________          ____________
    |            |       _\|            |      _\|            |
    | VSprite    |      | /| VSprite    |     | /| VSprite    |
    |____________|      |  |____________|     |  |____________|
    |            |  _   |  |            |     |  |            |
    | VSpriteBob |-|_|  |  | VSpriteBob |__   |  | VSpriteBob |__
    |____________|      |  |____________|  |  |  |____________|  |
                        |                  |  |                  |
                        |                  |  |                  |
                        |   ____________   |  |   ____________   |
                        |  |            |/_|  |  |            |/_|
                        |  | Bob        |\    |  | Bob        |>___
                        |  |____________|     |  |____________|\   |
                        |  |            |     |  |            |    |
                        |__| BobVSprite |     |__| BobVSprite |__  |
                           |____________|        |____________|  | |
                           |            |  _                     | |
                           | BobComp    |-|_|                    | |
                           |____________|         ____________   | |
                                                 |            |/_| |
                                                 | AnimComp   |\   |
                                                 |____________|    |
                                                 |            |    |
                                                 | Bob        |____|
                                                 |____________|

                  Figure 28-1: GEL Structure Layout


28 / About the GELs System / The GELs System

Before you can use the GELs system, you must set up a playfield.  The GELs
system requires access to a View, ViewPort, and RastPort structure.  These
structures may be set up through the grapics library or Intuition.  For
most examples in this chapter, the Intuition library is used for this
purpose.

All GELs have a VSprite structure at their core.  The system keeps track
of all the GELs that it will display (the active GELs) by using a standard
Exec list structure to link the VSprites.  This list is accessed via the
GelsInfo data structure, which in turn is associated with the RastPort.
The GelsInfo structure is defined in the file <graphics/rastport.h>. When
a new GEL is introduced to the system, the new GEL is added immediately
ahead of the first existing GEL whose x, y value is greater than or equal
to that of the new GEL, always trying to keep the list sorted.

As GELs are moved about the screen, their x, y values are constantly
changing.  SortGList() re-sorts this list by the x, y values. (Although
this is a list of VSprite structures, bear in mind that some or all may
really be Bobs or AnimComps.)

The basic set up of the GelsInfo structure requires three important
fields:  sprRsrvd,  gelHead and gelTail.  The sprRsrvd field tells the
system which hardware sprites not to use when managing true VSprites.  For
instance, Intuition uses sprite 0 for the mouse pointer so this hardware
sprite is not available for assignment to a VSprite.  The gelHead and
gelTail are VSprite structures that are used to manage the list of GELs.
They are never displayed.  To activate or deactivate a GEL, a system call
is made to add it to or delete it from this list.

Other fields must be set up to provide for collision detection, color
optimization, and other features.  A complete example for setting up the
GelsInfo structure is shown in the animtools.c lisitng at the end of this
chapter.

 Initializing the GEL System


28 / / The GELs System / Initializing the GEL System

To initialize the animation system, call the system function InitGels().
It takes the form:

    struct VSprite  *vsHead;
    struct VSprite  *vsTail;
    struct GelsInfo *gInfo;

    InitGels(vsHead, vsTail, gInfo);

The vsHead argument is a pointer to the VSprite structure to be used as
the GEL list head.  (You must allocate an actual VSprite structure for
vsHead to point to.)  The vsTail argument is a pointer to the VSprite
structure to be used as the GEL list tail.  (You must allocate an actual
VSprite structure for vsTail to point to.)  The gInfo argument is a
pointer to the GelsInfo structure to be initialized.

InitGels() forms these structures into a linked list of GELs that is empty
except for these two dummy elements (the head and tail).  It gives the
head VSprite the maximum negative x and y positions and the tail VSprite
the maximum positive x and y positions.  This is to aid the system in
keeping the list sorted by x, y values, so GELs that are closer to the top
and left of the display are nearer the head of the list.  The memory space
that the VSprites and GelsInfo structures take up must already have been
allocated.  This can be done either by declaring them statically or
explicitly allocating memory for them.

Once the GelsInfo structure has been allocated and initialized, GELs can
be added to the system.  Refer to the setupGelSys() and cleanupGelSys()
functions in the animtools.c lisitng at the end of the chapter for
examples of allocating, initializing and freeing a GelsInfo structure.


28 Sprites, Bobs and Animation / Using Simple (Hardware) Sprites

Simple Sprites can be used to create animations, so even though are not
really part of the GELs system, they are desribed here as a possible
alternative to using VSprites.  For more information on the sprite
hardware, including information on attached sprites, see the Amiga
Hardware Reference Manual.

The SimpleSprite structure is found in <graphics/sprite.h>. It has fields
that indicate the height and position of the Simple Sprite and a number
that indicates which of the 8 hardware sprites to use.

Simple Sprites are always 16 bits wide, which is why there is no width
member in the SimpleSprite structure.  Currently, sprites always appear as
low-resolution pixels, and their position is specified in the same way.
If the sprite is being moved across a high-resolution display in single
pixel increments, it will appear to move two high-resolution pixels for
each increment.  In low-resolution mode, a single Lores pixel movement
will be seen.  Similarly, in an interlaced display, the y direction
motions are in two-line increments. The same sprite image data is placed
into both even and odd fields of the interlaced display, so the sprite
will appear to be the same size in any display mode.

The upper left corner of the ViewPort area has coordinates (0,0). Unlike
VSprites, the motion of a Simple Sprite can be relative to this position.
(That is, if you create a Simple Sprite relative to your ViewPort and move
the ViewPort around, the Simple Sprite can move as well, but its movement
is relative to the origin of the ViewPort.)

The Sprite pairs 0/1, 2/3, 4/5, and 6/7 share color registers.  See
"VSprite Advanced Topics" later in this chapter, for precautions to take
if Simple Sprites and VSprites are used at the same time.

The following figure shows which color registers are used by Simple
Sprites.

                    00  Unused
                    01  Unused
                          ·
                          ·
                          ·     _
                    16  Unused   |
                    17  Color 1  |
                    18  Color 2  |-- Sprites 0 and 1
                    19  Color 3 _|
                    20  Unused   |
                    21  Color 1  |
                    22  Color 2  |-- Sprites 2 and 3
                    23  Color 3 _|
                    24  Unused   |
                    25  Color 1  |
                    26  Color 2  |-- Sprites 4 and 5
                    27  Color 3 _|
                    28  Unused   |
                    29  Color 1  |
                    30  Color 2  |-- Sprites 6 and 7
                    31  Color 3 _|

                 Figure 28-2: Sprite Color Registers

Sprites do not have exclusive use of the color registers. If the ViewPort
is 5 bitplanes deep, all 32 of the system color registers will still be
used by the playfield display hardware.

    Note:
    -----
    Color zero for all Sprites is always a "transparent" color, and the
    colors in registers 16, 20, 24, and 28 are not used by sprites. These
    colors will be seen only if they are rendered into a playfield. For
    further information, see the Amiga Hardware Reference Manual.

If there are two ViewPorts with different color sets on the same display,
a sprite will switch colors when it is moved across their boundary.  For
example, Sprite 0 and 1 will appear in colors 17-19 of whatever ViewPort
they happen to be over.  This is because the system jams all the
ViewPort's colors into the display hardware at the top of each ViewPort.

 Simple Sprite Functions


28 / Using Simple (Hardware) Sprites / Simple Sprite Functions

There are four basic functions that you use to to control Simple Sprites:

       GetSprite()  Attempts to allocates a sprite for exclusive use
    ChangeSprite()  Modifies a Simple Sprite's image data
      MoveSprite()  Changes a Simple Sprite's position
      FreeSprite()  Relinquishes a sprite so it can be used by others

To use these Simple Sprite functions (or the VSprite functions) the SPRITE
flag must have been set in the NewScreen structure for OpenScreen(). If
Intuition is not being used, this flag must be specified in the View and
ViewPort data structures before MakeVPort() is called.

 Accessing A Hardware Sprite
 Changing The Appearance Of A Simple Sprite
 Moving A Simple Sprite
 Relinquishing A Simple Sprite
 Controlling Sprite DMA
 Complete Simple Sprite Example


28 / / Simple Sprite Functions / Accessing A Hardware Sprite

GetSprite() is used to gain exclusive access to one of the eight hardware
sprites.  Once you have gained control of a hardware sprite, it can no
longer be allocated by the GELs system for use as a VSprite.  The call is
made like this:

    struct SimpleSprite *sprite;
    SHORT               number;

    if (-1 == (sprite_num = GetSprite(sprite, number)))
        return_code = RETURN_WARN;  /* did not get the sprite */

The inputs to the GetSprite() function are a pointer to a SimpleSprite
structure and the number (0-7) of the hardware sprite to be accessed, or
-1 to get the first available sprite.

A value of 0-7 is returned if the request was granted, specifying which
sprite was allocated.  A returned value of -1 means the requested sprite
was not available.  If the call succeeds, the SimpleSprite data structure
will have its sprite number field filled in with the appropriate number.


28 / / Sprite Functions / Changing The Appearance Of A Simple Sprite

The ChangeSprite() function can be used to alter the appearance of a
Simple Sprite.  ChangeSprite() substitutes new image data for the data
currently used to display a Simple Sprite.  It is called by the following
sequence:

    struct ViewPort     *vp;
    struct SimpleSprite *sprite;
    APTR                newdata;

    ChangeSprite(vp, sprite, newdata);

The vp input to this function is a pointer to the ViewPort for this Sprite
or 0 if this Sprite is relative only to the current View.  The sprite
argument is a pointer to a SimpleSprite data structure.  (You must
allocate an actual SimpleSprite structure for sprite to point to.)  Set
newdata to the address of an image data structure containing the new
image.  The data must reside in Chip (MEMF_CHIP) memory.

The structure for the new sprite image data is shown below.  It is not a
system structure, so it will not be found in the system includes, but it
is described in the documentation for the ChangeSprite() call.

    struct spriteimage
        {
        UWORD posctl[2];  /* position and control data for this Sprite */

        /* Two words per line of Sprite height, first of the two words
         *  contains the MSB for color selection, second word contains
         * LSB (colors 0,1,2,3 from allowable color register selection
         *  set). Color '0' for any Sprite pixel makes it transparent.
         */
        UWORD data[height][2];  /* actual Sprite image */

        UWORD reserved[2];  /* reserved, initialize to 0, 0 */
        };


28 / / Simple Sprite Functions / Moving A Simple Sprite

MoveSprite() repositions a Simple Sprite.  After this function is called,
the Simple Sprite is moved to a new position relative to the upper left
corner of the ViewPort.  It is called as follows:

    struct ViewPort     *vp;
    struct SimpleSprite *sprite;
    SHORT               x, y;

    MoveSprite(vp, sprite, x, y);

There are three inputs to MoveSprite().  Set the vp argument to the
address of the ViewPort with which this Simple Sprite interacts or 0 if
this Simple Sprite's position is relative only to the current View.  Set
sprite to the address of your SimpleSprite data structure.  The x and y
arguments sepcify a pixel position to which the Simple Sprite is to be
moved.


28 / / Simple Sprite Functions / Relinquishing A Simple Sprite

The FreeSprite() function returns a hardware sprite allocated with
GetSprite() to the system so that GELs or other tasks can use it.  After
you call FreeSprite(), the GELs system can use it to allocate VSprites.
The syntax of this function is:

    WORD sprite_number;

    FreeSprite(sprite_number);

The sprite_number argument is the number (0-7) of the sprite to be
returned to the system.


28 / / Simple Sprite Functions / Controlling Sprite DMA

Two additional functions used with Simple Sprites are the graphics library
macros ON_SPRITE and OFF_SPRITE.  These macros can be used to control
sprite DMA.  OFF_SPRITE prevents the system from displaying any sprites,
whether Simple Sprites or VSprites. ON_SPRITE restores the sprite display.

    Be Careful With OFF_SPRITE.
    ---------------------------
    The Intuition mouse pointer is a sprite.  Thus, if OFF_SPRITE is
    used, Intuition's pointer will disappear too.  Use care when calling
    OFF_SPRITE. The macro turns off sprite fetch DMA, so that no new
    sprite data is fetched. Whatever sprite data was last being displayed
    at this point will continue to be displayed for every line on the
    screen.  This may lead to a vertical color bar if a sprite is being
    displayed when OFF_SPRITE is called.


28 Graphics Sprites, Bobs and Animation / Using Virtual Sprites

This section describes how to set up the VSprite structure so that it
represents a true VSprite.  True VSprites are managed by the GELs system
which converts them to Simple Sprites and displays them.  (Later sections
describe how a VSprite structure can be set up for Bobs and AnimComps.)

Before the system is told of a VSprite's existence, space for the VSprite
data structure must be allocated and initialized to correctly represent a
VSprite.  Since the system does no validity checking on the VSprite
structure, the result of using a bogus structure is usually a fireworks
display, followed by a system failure.

The system software provides a way to detect collisions between VSprites
and other on-screen objects.  There is also a method of extending the
VSprite structure to incorporate user defined variables.  These subjects
are applicable to all GELs and are explained later in the section on
"Collisions and GEL Structure Extensions".

 Specification of VSprite Structure
 Reserved VSprite Members
 Using VSprite Flags
 VSprite Position
 VSprite Image Size
 VSprites and Collision Detection
 VSprite Image Data
 Specifying the Colors of a VSprite
 Adding and Removing VSprites
 Changing VSprites
 Getting the VSprite List In Order
 Displaying the VSprites


28 / Using Virtual Sprites / Specification of VSprite Structure

The VSprite structure is defined in the include file <graphics/gels.h> as
follows:

    /* VSprite structure definition */
    struct VSprite {
        struct VSprite *NextVSprite;
        struct VSprite *PrevVSprite;
        struct VSprite *DrawPath;
        struct VSprite *ClearPath;
        WORD            OldY, OldX;
        WORD            Flags;
        WORD            Y, X;
        WORD            Height;
        WORD            Width;
        WORD            Depth;
        WORD            MeMask;
        WORD            HitMask;
        WORD           *ImageData;
        WORD           *BorderLine;
        WORD           *CollMask;
        WORD           *SprColors;
        struct Bob     *VSBob;
        BYTE            PlanePick;
        BYTE            PlaneOnOff;
        VUserStuff      VUserExt;
        };

There are two primary ways to allocate and fill in space for VSprite data.
They can be statically declared, or a memory allocation function can be
called and they can be filled in programmatically.  The declaration to
statically set up a VSprite structure is listed below.

    /* VSprite static data definition.
    ** must set the following for TRUE VSprites:
    **    VSPRITE flag.
    **    Width to 1.
    **    Depth to 2.
    **    VSBob to NULL.
    */
    struct VSprite myVSprite =
        {
        NULL, NULL, NULL, NULL, 0, 0, VSPRITE, 0, 0, 5, 1, 2, 0, 0,
        &myImage, 0, 0, &mySpriteColors, NULL, 0x3, 0, 0
        };

This static allocation gives the required VSprite structure, but does not
allocate or set up collision masks for the VSprite.  Note that the VSprite
structure itself does not need to reside in Chip memory.

Refer to the makeVSprite() and freeVSprite() functions in the animtools.c
listing at the end of the chapter for an example of dynamically
allocating, initializing and freeing a VSprite structure.


28 / Using Virtual Sprites / Reserved VSprite Members

These VSprite structure members are reserved for system use (do not write
to them):

    NextVSprite and PrevVSprite -- These are used as links in the
                                   GelsInfo list.

         DrawPath and ClearPath -- These are used for Bobs, not true
                                   VSprites.

                  OldY and OldX -- Previous position holder, the system
                                   uses these for double buffered Bobs,
                                   but application programs can read
                                   them too.

The values can be set like this:

    myVSprite.NextVSprite = NULL;
    myVSprite.PrevVSprite = NULL;
    myVSprite.DrawPath  = NULL;
    myVSprite.ClearPath = NULL;
    myVSprite.OldY = 0;
    myVSprite.OldX = 0;


28 / Using Virtual Sprites / Using VSprite Flags

The Flags member of the VSprite structure is both read and written by the
system.  Some bits are used by the application to inform the system;
others are used by the system to indicate things to the application.

The only Flags bits that are used by true VSprites are:

VSPRITE
    This may be set to indicate to the system that it should treat the
    structure as a true VSprite, not part of a Bob.  This affects the
    interpretation of the data layout and the use of various system
    variables.

VSOVERFLOW
    The system sets this bit in the true VSprites that it is unable to
    display.  This happens when there are too many in the same scan line,
    and the system has run out of Simple Sprites to assign.  It indicates
    that this VSprite has not been displayed.  If no sprites are
    reserved, this means that more than eight sprites touch one scan
    line.  This bit will not be set for Bobs and should not be changed by
    the application.

GELGONE
    If the system has set GELGONE bit in the Flags member, then the GEL
    associated with this VSprite is not on the display at all, it is
    entirely outside the GEL boundaries.  This area is defined by the
    GelsInfo members topmost, bottommost, leftmost and rightmost (see
    <graphics/rastport.h>). On the basis of that information, the
    application may decide that the object need no longer be part of the
    GEL list and may decide to remove it to speed up the consideration of
    other objects. Use RemVSprite() (or RemBob(), if it's a Bob) to do
    this. This bit should not be changed by the application.

The VSprite.Flags value should be initialized like this for a VSprite
GEL:

    myVSprite.Flags = VSPRITE;


28 / Using Virtual Sprites / VSprite Position

To control the position of a VSprite, the x and y variables in the VSprite
structure are used.  These specify where the upper left corner of the
VSprite will be, relative to the upper left corner of the playfield area
it appears over.  So if VSprites are used under Intuition and within a
screen, they will be positioned relative to the upper left-hand corner of
the screen.

In a 320 by 200 screen, a y value of 0 puts the VSprite at the top of that
display, a y value of (200 - VSprite height) puts the VSprite at the
bottom.  And an x value of 0 puts the VSprite at the left edge of that
display, while an x value of (320 - VSprite width) puts the VSprite at the
far right.  Values of less than (0,0) or greater than (320, 200) may be
used to move the VSprite partially or entirely off the screen, if desired.

See the "Graphics Primitives" chapter for more information on display
coordinates and display size.  See the Amiga Hardware Reference Manual for
more information on hardware sprites.

    Position VSprites Properly.
    ---------------------------
    It is important that the starting position of true VSprites is not
    less than -20 in the y direction, which is the start of the active
    display area for sprites.  Also, if they are moved too far to the
    left, true VSprites may not have enough DMA time to be displayed.

The x, y values may be set like this to put the VSprite in the upper-left:

    myVSprite.Y = 0;
    myVSprite.X = 0;


28 / Using Virtual Sprites / VSprite Image Size

A true VSprite is always one word (16 pixels) wide and may be any number
of lines high.  It can be made to appear thinner by making some pixels
transparent.  Like Simple Sprites, VSprite pixels are always the size of a
pixel in low-resolution mode (320x200); regardless of the resolution the
display is set to.  To specify how many lines make up the VSprite image,
the VSprite structure member, Height, is used. VSprites always have a
Depth of two, allowing for three colors.  The values may be set like this:

    myVSprite.Width  = 1;      /* ALWAYS 1 for true VSprites. */
    myVSprite.Height = 5;      /* The example height. */
    myVSprite.Depth  = 2;      /* ALWAYS 2 for true VSprites. */


28 / Using Virtual Sprites / VSprites and Collision Detection

Some members of the VSprite data structure are used for special purposes
such as collision detection, user extensions or for system extensions
(such as Bobs and AnimComps).  For most applications these fields are set
to zero:

    myVSprite.HitMask    = 0;  /* These are all used for collision */
    myVSprite.MeMask     = 0;  /* detection                        */
    myVSprite.BorderLine = 0;
    myVSprite.CollMask   = 0;

    myVSprite.VUserExt = 0;    /* Only use this for user extensions to */
                               /* VSprite                              */

    myVSprite.VSBob = NULL;    /* Only Bobs and AnimComps need this */

The special uses of these fields are explained further in the sections
that follow.


28 / Using Virtual Sprites / VSprite Image Data

The ImageData pointer of the VSprite structure must be initialized with
the address of the first word of the image data array.  The image data
array must be in Chip memory.  It takes two sequential 16-bit words to
define each line of a VSprite.  This means that the data area containing
the VSprite image is always Height x 2 (10 in the example case) words long.

A VSprite image is defined just like a real hardware sprite.  The
combination of bits in corresponding locations in the two data words that
define each line select the color for that pixel.  The first of the pair
of words supplies the low-order bit of the color selector for that pixel;
the second word supplies the high-order bit.

These binary values select colors as follows:

    00 - selects "transparent"
    01 - selects the first of three VSprite colors
    10 - selects the second VSprite color
    11 - selects the third VSprite color

In those areas where the combination of bits yields a value of 0, the
VSprite is transparent.  This means that the playfield, and all Bobs and
AnimComps, and any VSprite whose priority is lower than this VSprite will
all show through in transparent sections.  For example:

    (&VSprite->ImageData)           1010 0000 0000 0000
    (&VSprite->ImageData + 1)       0110 0000 0000 0000

Reading from top to bottom, left to right, the combinations of these two
sequential data words form the binary values of 01, 10, 11, and then all
00s.  This VSprite's first pixel will be color 1, the next color 2, the
third color 3. The rest will be transparent, making this VSprite appear to
be three pixels wide. Thus, a three-color image, with some transparent
areas, can be formed from a data set like the following sample:

    Address        Binary Data        VSprite Image Data
    -------        -----------        ------------------
    mem        1111 1111 1111 1111    Defines top line
    mem + 1    1111 1111 1111 1111    3333 3333 3333 3333

    mem + 2    0011 1100 0011 1100    Defines second line
    mem + 3    0011 0000 0000 1100    0033 1100 0011 3300

    mem + 4    0000 1100 0011 0000    Defines third line
    mem + 5    0000 1111 1111 0000    0000 3322 2233 0000

    mem + 6    0000 0010 0100 0000    Defines fourth line
    mem + 7    0000 0011 1100 0000    0000 0032 2300 0000

    mem + 8    0000 0001 1000 0000    Defines fifth line
    mem + 9    0000 0001 1000 0000    0000 0003 3000 0000

The VSprite.Height for this sample image is 5.


28 / Using Virtual Sprites / Specifying the Colors of a VSprite

The system software provides a great deal of versatility in the choice of
colors for Virtual Sprites.  Each VSprite has its own set of three colors,
pointed to by SprColors, which the system jams into the display's Copper
list as needed.

SprColors points to the first of three 16-bit values. The first value
represents the color used for the VSprite bits that select color 1, the
second value is color 2, and the third value is color 3.  When the system
assigns a hardware sprite to carry the VSprite's image, it jams these
color values into the Copper list (the intermediate Copper list, not the
color table), so that the View's colors will be correct for this VSprite
at the time the VSprite is displayed.  It doesn't jam the original
palette's colors back after the VSprite is done.  If there is another
VSprite later, that VSprite's colors will get jammed; if there is not
another VSprite, the colors will remain the same until the next ViewPort's
colors get loaded.

If the SprColors pointer is set to NULL, that VSprite does not generate a
color-change instruction stream for the Copper. Instead, the VSprite
appears drawn in whatever color set that the hardware sprite happens to
have in it already.

Since the registers are initially loaded with the colors from the
ViewPort's ColorMap, if all VSprites have NULL SprColors, they will appear
in the ViewPort's colors.

To continue our example, a set of colors can be declared and the VSprite
colors set with the following statements:

    WORD mySpriteColors[] = { 0x0000,
                              0x00f0,
                              0x0f00 };  /* Declare colors statically  */

    myVSprite.SprColors = mySpriteColors;  /* Assign colors to VSprite */


28 / Using Virtual Sprites / Adding and Removing VSprites

Once a true VSprite has been set up and initialized, the obvious next step
is to give it to the system by adding it to the GEL list. The VSprite may
then be manipulated as needed.  Before the program ends, the VSprite
should be removed from the GELs list by calling RemVSprite(). A typical
calling sequence could be performed like so:

    struct VSprite  myVSprite = {0};
    struct RastPort myRastPort = {0};

    AddVSprite(&myVSprite, &myRastPort);

    /* Manipulate the VSprite as needed here */

    RemVSprite(&myVSprite);

The &myVSprite argument is a fully initialized VSprite structure and
&myRastPort is the RastPort with which this VSprite is to be associated.
Note that you will probably not like the results if you try to
RemVSprite() a VSprite that has not been added to the system with
AddVSprite().  See the Amiga ROM Kernel Reference Manual: Includes and
Autodocs for additional information on these functions.


28 / Using Virtual Sprites / Changing VSprites

Once the VSprite has been added to the GELs list and is in the display,
some of its characteristics can be changed dynamically by:

    * Changing y, x to a new VSprite position

    * Changing ImageData to point to a new VSprite image

    * Changing SprColors to point to a new VSprite color set

Study the next two sections to find out how to reserve hardware Sprites
for use outside the VSprite system and how to assign the VSprites.


28 / Using Virtual Sprites / Getting the VSprite List In Order

When the system has displayed the last line of a VSprite, it is able to
reassign the hardware sprite to another VSprite located at a lower
position on the screen.  The system allocates hardware sprites in the
order in which it encounters the VSprites in the list.  Therefore, the
list of VSprites must be sorted before the system can assign the use of
the hardware Sprites correctly.

The function SortGList() must be used to get the GELs in the correct order
before the system is asked to display them.  This sorting step is
essential!  It should be done before calling DrawGList(), whenever a GEL
has changed position.  This function is called as follows:

    struct RastPort myRastPort = {0};

    SortGList(&myRastPort);

The only argument is a pointer to the RastPort structure containing the
GelsInfo.


28 / Using Virtual Sprites / Displaying the VSprites

The next few sections explain how to display the VSprites. The following
system functions are used:

    DrawGList()  Draws the VSprites into the current RastPort.
       MrgCop()  Installs the VSprites into the display.
     LoadView()  Asks the system to display the new View.
      WaitTOF()  Synchronizes the functions with the display.

 Drawing the Graphics Elements    Loading the New View
 Merging VSprite Instructions     Synchronizing with the Display


28 / / Displaying the VSprites / Drawing the Graphics Elements

The system function called DrawGList() looks through the list of GELS and
prepares the necessary Copper instructions and memory areas to display the
data.  This function is called as follows:

    struct RastPort myRastPort = {0};
    struct ViewPort myViewPort = {0};

    DrawGList(&myRastPort, &myViewPort);

The myRastPort argument specifies the RastPort containing the GelsInfo
list with the VSprites that you want to display.  The &myViewPort argument
is a pointer to the ViewPort for which the VSprites will be created.


28 / / Displaying the VSprites / Merging VSprite Instructions

Once DrawGList() has prepared the necessary instructions and memory areas
to display the data, the VSprites are installed into the display with
MrgCop().  (DrawGList() does not actually draw the VSprites, it only
prepares the Copper instructions.)

    struct View *view;

    MrgCop(view);

The view is a pointer to the View structure whose Copper instructions are
to be merged.


28 / / Displaying the VSprites / Loading the New View

Now that the display instructions include the definition of the VSprites,
the system can display this newly configured View with the LoadView()
function:

    struct View *view;

    LoadView(view);

Again, view is a pointer to the View that contains the the new Copper
instruction list (if you are using GELs in an Intuition Screen, do not
call LoadView().)

The Copper instruction lists are double-buffered, so this instruction does
not actually take effect until the next display field occurs. This avoids
the possibility of some function trying to update the Copper instruction
list while the Copper is trying to use it to create the display.


28 / / Displaying the VSprites / Synchronizing with the Display

To synchronize application functions with the display, call the system
function WaitTOF(). WaitTOF() holds your task until the vertical-blanking
interval (blank area at the top of the screen) has begun.  At that time,
the system has retrieved the current Copper instruction list and is ready
to allow generation of a new list.

    WaitTOF();

WaitTOF() takes no arguments and returns no values.  It simply suspends
your task until the video beam is at the top of field.


28 Graphics: Sprites, Bobs and Animation / VSprite Advanced Topics

This section describes advanced topics pertaining to VSprites. It contains
details about reserving hardware sprites for use outside of the GELs
VSprite system, information about how VSprites are assigned, and more
information about VSprite colors.

 Reserving Hardware Sprites
 How VSprites Are Assigned
 How VSprite and Playfield Colors Interact


28 / VSprite Advanced Topics / Reserving Hardware Sprites

To prevent the VSprite system from using specific hardware sprites, set
the sprRsrvd member of the GelsInfo structure. The pointer to the GelsInfo
structure is contained in the RastPort structure. If all of the bits of
this 8-bit value are ones (0xFF), then all of the hardware sprites may be
used by the VSprite system. If any of the bits is a 0, the sprite
corresponding to that bit will not be utilized by VSprites.

    Reserving Can Cause Problems.
    -----------------------------
    Reserving sprites increases the likelihood of the system not being
    able to display a VSprite (VSOVERFLOW). See the next section,
    "How VSprites are Assigned," for further details on this topic.

You reserve a sprite by setting its corresponding bit in sprRsrvd.  For
instance, to reserve sprite zero only, set sprRsrvd to 0x01.  To reserve
sprite three only, set sprRsrvd to 0x08.

If a hardware sprite is reserved, the system will not consider it when it
makes VSprite assignments.  Remember, hardware sprite pairs share color
register sets.  If a hardware sprite is reserved, its mate should probably
be reserved too, otherwise the reserved sprite's colors will change as the
unreserved mate is assigned different VSprites.  For example, it is common
practice to reserve Sprites 0 and 1, so that the Intuition pointer (Sprite
0) is left alone.  This could be accomplished with the following
statements:

    struct RastPort myRastPort = {0};  /* the View structure is defined */

    myRastPort.GelsInfo->sprRsrvd = 0x03;  /* reserve 0 and 1 */

The GfxBase structure may be examined to find which sprites are already in
use.  This may, at your option, impact what sprites you reserve.  If
Intuition is running, sprite 0 will already be in use as its pointer.

The reserved sprite status is accessible as

    currentreserved = GfxBase->SpriteReserved;

The next section presents a few trouble-shooting techniques for VSprite
assignment.


28 / VSprite Advanced Topics / How VSprites Are Assigned

Although VSprites are managed for you by the GELs system there are some
underlying limitations which could cause the system to run out of VSprites.

As the system goes through the GEL list during DrawGList(), whenever it
finds a true VSprite, it goes through the following procedure. If there is
a Simple Sprite available (after the reserved sprites and preceding
VSprites are accounted for), Copper instructions are added that will load
the sprite hardware with this VSprite's data at the right point on the
screen. It may need to add a Copper instruction sequence to load the
display's colors associated with the sprite as well.

 There are only 8 real sprite DMA channels.  The system will run out of
hardware sprites if it is asked to display more than eight VSprites on one
scan line.  This limit goes down to four when the VSprites have different
SprColor pointers. During the time that there is a conflict, the VSprites
that could not be put into Simple Sprites will disappear.  They will
reappear when (as the VSprites are moved about the screen) circumstances
permit.

These problems can be alleviated by taking some precautions:

  * Minimize the number of VSprites to appear on a single horizontal line.

  * If colors for some Virtual Sprites are the same, make sure that the
    pointer for each of the VSprite structures for these Virtual Sprites
    points to the same memory location, rather than to a duplicate set of
    colors elsewhere in memory. The system will know to map these into
    Sprite pairs.

If a VSprite's SprColors are set to NULL, the VSprite will appear in the
ViewPort's ColorMap colors.  The system will display the VSprite in any
one of a set of four different possible color groupings as indicated in
the Simple Sprite section above.

If SprColors points to a color set, the system will jam SprColors into the
display hardware (via the Copper list), effectively overriding those
ColorMap registers.  The values in the ColorMap are not overwritten, but
anything in the background display that used to appear in the ColorMap
colors will appear in SprColors colors.


28 / Advanced Topics / How VSprite and Playfield Colors Interact

At the start of each display, the system loads the colors from the
ViewPort's color table into the display's hardware registers, so whatever
is rendered into the BitMap is displayed correctly. But if the VSprite
system is used, and the colors are specified (via SprColors) for each
VSprite, the SprColors will be loaded by the system into the display
hardware, as needed. The system does this by generating Copper
instructions that will jam the colors into the hardware at specific
moments in the display cycle.  Any BitMap rendering, including Bobs, which
share colors with VSprites, may change colors constantly as the video
display beam progresses down the screen.

This color changing can be avoided by taking one of the following
precautions:

  * Use a four bitplane playfield, which only allows the lower 16 colors
    to be rendered into the BitMap (and allows Hires display mode).

  * If a 32-color playfield display is being used, avoid rendering in
    colors 17-19, 21-23, 25-27, and 29-32, which are the colors affected
    by the VSprite system.

  * Specify the VSprite SprColors pointer as a value of NULL to avoid
    changing the contents of any of the hardware sprite color registers.
    This may cause the VSprites to change colors depending on their
    positions relative to each other, as described in the
    previous section.


28 Graphics Sprites, Bobs and Animation / Using Bobs

The following section describes how to define a Bob (blitter object). Like
VSprites, a Bob is a software construct designed to make animation easier.
The main advantage of a Bob over a VSprite is that it allows more colors
and a width greater than 16 pixels to be defined.

To create a Bob, you need both a Bob structure and a VSprite structure.
The components common to all GELs -- height, collision-handling
information, position in the drawing area and pointers to the image
definition -- are part of the VSprite structure.  The added features --
such as drawing sequence, data about saving and restoring the background,
and other features not applicable to VSprites -- are further specified in
the Bob structure.

 The VSprite Structure and Bobs        Bob Priorities
 VSprite Flags and Bobs                Adding a Bob
 The Bob Structure                     Removing a Bob
 Using Bob Flags                       Sorting and Displaying Bobs
 Specifying the Size of a Bob          Changing Bobs
 Specifying the Shape of a Bob         Complete Bob Example
 Specifying the Colors of a Bob        Double-Buffering
 Other Items Influencing Bob Colors


28 / Using Bobs / The VSprite Structure and Bobs

The root VSprite structure is set up as described earlier for true
VSprites, with the following exceptions:

             Y, X  Bob position is always in pixels that are the same
                   resolution as the display.

            Flags  For Bobs, the VSPRITE flag must be cleared.  SAVEBACK
                   or OVERLAY can also be used.

    Height, Width  Bob pixels are the size of the background pixels. The
                   Width of Bobs may be greater than one word.

            Depth  The Depth of a Bob may be up to as deep as the
                   playfield, provided that enough image data is provided.

        ImageData  This is still a pointer to the image, but the data
                   there is organized differently.

        SprColors  This pointer should be set to NULL for Bobs.

            VSBob  This is a pointer to the Bob structure set up as
                   described below.


28 / Using Bobs / VSprite Flags and Bobs

The bits in the VSprite.Flags field that apply to a Bob are the VSPRITE
flag, the SAVEBACK flag and the OVERLAY flag.  When a VSprite structure is
used to define a Bob, the VSPRITE flag in the VSprite.Flags field must be
set to zero.  This tells the system that this GEL is a Bob type.

To have the GEL routines save the background before the Bob is drawn and
restore the background after the Bob is removed, specify the SAVEBACK flag
(stands for "save the background") in the VSprite structure Flags field.
If this flag is set, the SaveBuffer must have been allocated, which is
where the system puts this saved background area.  The buffer must be
large enough to save all the background bitplanes, regardless of how many
planes the Bob has.  The size in words can be calculated as follows:

    /* Note that Bob.Width is in units of words. */
    size = Bob.Width * Bob.Height * RastPort.BitMap.Depth;

To allocate this space, the graphics function AllocRaster() can be used.
AllocRaster() takes the width in bits, so it is a convenient way to
allocate the space needed.  The makeBob() routine below shows another way
to correctly allocate this buffer. For example:

    /* space for 16 bits times 5 lines times 5 bitplanes */
    myBob.SaveBuffer = AllocRaster( (UWORD) 16, (UWORD) (5 * 5) );

    Warning:
    --------
    The SaveBuffer must be allocated from Chip memory and contain an
    even number of word-aligned bytes.  The AllocRaster() function
    does this for you.  The AllocRaster() function rounds the width
    value up to the next integer multiple of 16 bits which is greater
    than or equal to the current value an it obtains memory from the Chip
    memory pool.

OVERLAY is the other VSprite.Flags item that applies to Bobs. If this flag
is set, it means that the background's original pixels show through in any
area where there are 0 bits in the Bob's shadow mask (ImageShadow,
explained later).  The space for the ImageShadow shadow mask must have
been allocated and initialized.  The ImageShadow mask must be allocated
from Chip memory.

If the OVERLAY bit is cleared, the system uses the entire rectangle of
words that define the Bob image to replace the playfield area at the
specified x,y coordinates.  See the paragraphs below called "ImageShadow".


28 / Using Bobs / The Bob Structure

The Bob structure is defined in the include file <graphics/gels.h> as
follows:

struct Bob
  {
  WORD               Flags;     /* general purpose flags                 */
  WORD              *SaveBuffer;/* buffer for background save            */
  WORD              *ImageShadow; /* shadow mask of image                */
  struct Bob        *Before;   /* draw this Bob before Bobs on this list */
  struct Bob        *After;     /* draw this Bob after Bobs on this list */
  struct VSprite    *BobVSprite;/* this Bob's VSprite definition         */
  struct AnimComp   *BobComp;   /* pointer to this Bob's AnimComp def    */
  struct DBufPacket *DBuffer;   /* pointer to this Bob's dBuf packet     */
  BUserStuff         BUserExt;  /* Bob user extension                    */
  };

The Bob structure itself does not need to be in Chip memory. The (global)
static declaration of a Bob structure could be done like so:

    struct Bob myBob =
        {
        0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
        };

However, since most of the Bob structure members are pointers, it is more
common to allocate and set the Bob up dynamically. Refer to the makeBob()
and freeBob() functions in the "animtools.c" example at the end of the
chapter for an example of allocating, initializing and freeing a Bob
structure.

 Linking Bob and VSprite Structures


28 / / The Bob Structure / Linking Bob and VSprite Structures

The VSprite and Bob structures must point to one another, so that the
system can find the entire GEL.  The structures are linked with statements
like this:

    myBob.BobVSprite = &myVSprite;
    myVSprite.VSBob  = &myBob;

Now the system (and the application program) can go back and forth between
the two structures to obtain the various Bob variables.


28 / Using Bobs / Using Bob Flags

The following paragraphs describe how to set the Flags field in the Bob
structure (note that these flags do not apply to the Flags field of the
VSprite structure).

SAVEBOB
    To tell the system not to erase the old image of the Bob when the Bob
    is moved, specify the SAVEBOB flag in the Bob structure Flags field.
    This makes the Bob behave like a paintbrush.  It has the opposite
    effect of SAVEBACK.

    It's Faster To Draw A New Bob.
    ------------------------------
    It takes longer to preserve and restore the raster image than simply
    to draw a new Bob image wherever required.

BOBISCOMP
    If this Bob is part of an AnimComp, set the BOBISCOMP flag in the Bob
    structure to 1.  If the flag is a 1, the pointer named BobComp must
    have been initialized.  Otherwise, the system ignores the pointer,
    and it may be left alone (though it's good practice to initialize it
    to NULL).  See "Animation Data Structures" for a discussion
    of AnimComps.

BWAITING
    This flag is used solely by the system, and should be left alone.
    When a Bob is waiting to be drawn, the system sets the BWAITING flag
    in the Bob structure to 1.  This occurs only if the system has found
    a Before pointer in this Bob's structure that points to another Bob.
    Thus, the system flag BWAITING provides current draw-status to the
    system.  Currently, the system clears this flag on return from each
    call to DrawGList().

BDRAWN
    This is a system status flag that indicates to the system whether or
    not this Bob has already been drawn.  Therefore, in the process of
    examining the various Before and After flags, the drawing routines
    can determine the drawing sequence.  The system clears this flag on
    return from each call to DrawGList().

BOBSAWAY
    To initiate the removal of a Bob during the next call to DrawGList(),
    set BOBSAWAY to 1.  Either the application or the system may set this
    Bob structure system flag.  The system restores the background where
    it has last drawn the Bob.  The system will unlink the Bob from the
    system GEL list the next time DrawGList() is called, unless the
    application is using double-buffering.  In that case, the Bob will
    not be unlinked and completely removed until two calls to DrawGList()
    have occurred and the Bob has been removed from both buffers.  The
    RemBob() macro sets the BOBSAWAY flag.

BOBNIX
    When a Bob has been completely removed, the system sets the BOBNIX
    flag to 1 on return from DrawGList().  In other words, when the
    background area has been fully restored and the Bob has been removed
    from the GEL list, this flag in is set to a 1.  BOBNIX is especially
    significant when double-buffering because when an application asks
    for a Bob to be removed, the system must remove it from both the
    drawing buffer and from the display buffer.  Once BOBNIX has been
    set, it means the Bob has been removed from both buffers and the
    application is free to reuse or deallocate the Bob.

SAVEPRESERVE
    The SAVEPRESERVE flag is a double-buffer version of the SAVEBACK
    flag.  If using double-buffering and wishing to save and restore the
    background, set SAVEBACK to 1.  SAVEPRESERVE is used by the system to
    indicate whether the Bob in the "other" buffer has been restored; it
    is for system use only.


28 / Using Bobs / Specifying the Size of a Bob

Bobs do not have the 16-pixel width limit that applies to VSprites.  To
specify the overall size of a Bob, use the Height and Width members of the
root VSprite structure.  Specify the Width as the number of 16-bit words
it takes to fully contain the object.  The number of lines is still
specified with the Height member in the VSprite data structure.

As an example, suppose the Bob is 24 pixels wide and 20 lines tall.  Use
statements like the following to specify the size:

    myVSprite.Height = 20;  /* 20 lines tall. */
    myVSprite.Width  = 2;   /* 24 bits fit into two words. */

Because Bobs are drawn into the background playfield, the pixels of the
Bob are the same size as the background pixels, and share the color
palette of the ViewPort.


28 / Using Bobs / Specifying the Shape of a Bob

The layout of the data of a Bob's image is different from that of a
VSprite because of the way the system retrieves data to draw Bobs.
VSprite images are organized in a way convenient to the Sprite hardware;
Bob images are set up for easy blitter manipulation.  The ImageData
pointer is still initialized to point to the first word of the image
definition.

    Note:
    -----
    As with all image data, a Bob's ImageData must be in Chip memory
    for access by the blitter.

The sample image below shows the same image defined as a VSprite in the
"Using Virtual Sprites" section above.  The data here, however, is laid
out for a Bob.  The shape is 2 planes deep and is triangular:

            <first bitplane data>

  mem        1111 1111 1111 1111    Least significant bit of sprite line 1
  mem + 1    0011 1100 0011 1100    Least significant bit of sprite line 2
  mem + 2    0000 1100 0011 0000    Least significant bit of sprite line 3
  mem + 3    0000 0010 0100 0000    Least significant bit of sprite line 4
  mem + 4    0000 0001 1000 0000    Least significant bit of sprite line 5

            <second bitplane data>

  mem + 5    1111 1111 1111 1111    Most significant bit of sprite line 1
  mem + 6    0011 0000 0000 1100    Most significant bit of sprite line 2
  mem + 7    0000 1111 1111 0000    Most significant bit of sprite line 3
  mem + 8    0000 0011 1100 0000    Most significant bit of sprite line 4
  mem + 9    0000 0001 1000 0000    Most significant bit of sprite line 5

            <more bitplanes of data if Bob is deeper>


28 / Using Bobs / Specifying the Colors of a Bob

Typically a five-bitplane, low-resolution mode display allows playfield
pixels (and therefore, Bob pixels) to be selected from any of 32 active
colors out of a system palette of 4,096 different color choices. Bob
colors are limited to the colors used in the background playfield.

The system ignores the sprColors member of the VSprite structure when the
VSprite structure is the root of a Bob. Instead, the Bob's colors are
determined by the combination of the Depth of the Bob image and its
PlanePick, PlaneOnOff and ImageShadow members.

Use the Depth member in the VSprite structure to indicate how many planes
of image data is provided to define the Bob. This also defines how many
colors the Bob will have. The combination of bits in corresponding Y,X
positions in each bitplane determines the color of the pixel at that
position.

For example, if a Depth of one plane is specified, then the bits of that
image allow only two colors to be selected:  one color for each bit that
is a 0, a second color for each bit that is a 1.  Likewise, if there are 5
planes of image data, all 32 colors can be used in the Bob.  The Bob Depth
must not exceed the background depth.  Specify Depth using a statement
such as the following:

    myVSprite.Depth = 5;   /* Allow a 32 color, 5-bitplane image. */


28 / Using Bobs / Other Items Influencing Bob Colors

The three other members in the VSprite structure that affect the color of
Bob pixels are ImageShadow, PlanePick, and PlaneOnOff.

 ImageShadow    PlanePick    PlaneOnOff


28 / / Other Items Influencing Bob Colors / ImageShadow

The ImageShadow member is a pointer to the shadow mask of a Bob. A shadow
mask is the logical or of all bitplanes of a Bob image. The system uses
the shadow mask in conjunction with PlaneOnOff, discussed below, for color
selection. It also uses the shadow mask to "cookie cut" the bits that will
be overwritten by this Bob, to save and later restore the background.

The following figure shows the shadow mask of the image described above.

    mem + 0    1111 1111 1111 1111    Shadow mask for line 1
    mem + 1    0011 1100 0011 1100    Shadow mask for line 2
    mem + 2    0000 1111 1111 0000    Shadow mask for line 3
    mem + 3    0000 0011 1100 0000    Shadow mask for line 4
    mem + 4    0000 0001 1000 0000    Shadow mask for line 5

Space for the ImageShadow must be provided and this pointer initialized to
point to it.  The amount of memory needed is equivalent to one plane of
the image:

    shadow_size = myBob->BobVSprite->Height * myBob->BobVSprite->Width;

The example image is 5 high and 1 word wide, so, 5 words must be made
available.

    Note:
    -----
    The ImageShadow memory must be allocated from Chip memory
    (MEMF_CHIP).


28 / / Other Items Influencing Bob Colors / PlanePick

Because the Depth of the Bob can be less than the background, the
PlanePick member is provided so that the application can indicate which
background bitplanes are to have image data put into them.  The system
starts with the least significant plane of the Bob, and scans PlanePick
starting at the least significant bit, looking for a plane of the RastPort
to put it in.

For example, if PlanePick has a binary value of: 0 0 0 0   0 0 1 1 (0x03)
then the system draws the first plane of the Bob's image into background
plane 0 and the second plane into background plane 1.

Alternatively, a PlanePick value of:  0 0 0 1   0 0 1 0 (0x12) directs the
system to put the first Bob plane into plane 1, and the second Bob plane
into plane 4.


28 / / Other Items Influencing Bob Colors / PlaneOnOff

What happens to the background planes that aren't picked?  The shadow mask
is used to either set or clear the bits in those planes in the exact shape
of the Bob if OVERLAY is set, otherwise the entire rectangle containing
the Bob is used.  The PlaneOnOff member tells the system whether to put
down the shadow mask as zeros or ones for each plane.  The relationship
between bit positions in PlaneOnOff and background plane numbers is
identical to PlanePick: the least significant bit position indicates the
lowest-numbered bitplane.  A zero bit clears the shadow mask shape in the
corresponding plane, while a one bit sets the shadow mask shape.  The
planes Picked by PlanePick have image data - not shadow mask - blitted in.

This provides a great deal of color versatility.  One image definition can
be used for many Bobs.  By having different PlanePick / PlaneOnOff
combinations, each Bob can use a different subset of the background color
set.

There is a member in the VSprite structure called CollMask (the collision
mask, covered under "Detecting GEL Collisions") for which the application
may also reserve some memory space.  The ImageShadow and CollMask pointers
usually, but not necessarily, point to the same data, which must be
located in Chip memory.  If they point to the same location, obviously,
the memory only need be allocated once.

An example of the kinds of statements that accomplish these actions (see
the makeVSprite() and makeBob() examples for more details):

#define BOBW 1
#define BOBH 5
#define BOBD 2

/* Data definition from example layout */
WORD chip BobData[]=
    {
    0xFFFF, 0x300C, 0x0FF0, 0x03C0, 0x0180,
    0xFFFF, 0x3E7C, 0x0C30, 0x03C0, 0x0180
    };

/* Reserve space for the collision mask for this Bob */
WORD chip BobCollision[BOBW * BOBH];

myVSprite.Width  = BOBW;     /* Image is 16 pixels wide (1 word) */
myVSprite.Height = BOBH;    /* 5 lines for each plane of the Bob */
myVSprite.Depth  = BOBD;     /* 2 Planes are in ImageData */

/* Show the system where it can find the data image of the Bob */
myVSprite.ImageData = BobData;

/* binary 0101, render image data into bitplanes 0 and 2 */
myVSprite.PlanePick = 0x05;

/* binary 0000, means colors 1, 4, and 5 will be used.
*  binary 0010 would mean colors 3, 6, and 7.
*    "    1000   "    "     "    9, C, and D.
*    "    1010   "    "     "    B, E, and F.
*/
myVSprite.PlaneOnOff = 0x00;

/* Where to put collision mask */
myVSprite.CollMask = BobCollision;

/* Tell the system where it can assemble a GEL shadow */
/* Point to same area as CollMask */
myBob.ImageShadow = BobCollision;

/* Create the Sprite collision mask in the VSprite structure */
InitMasks(&myVSprite);


28 / Using Bobs / Bob Priorities

This subsection describes the choices for inter-Bob priorities.  The
inter-Bob priorities tell the system what order to render the Bobs.  Bobs
rendered earlier will appear to be behind later Bobs.  A Bob drawn earlier
is said to have the lower priority and a Bob drawn later is said to have
the higher priority.  Thus, the highest priority Bob will be drawn last
and will never be obstructed by another Bob.

 Letting the System Decide Priorities
 Specifying the Drawing Order


28 / / Bob Priorities / Letting the System Decide Priorities

The priority issue can be ignored and the system will render the Bobs as
it finds them in the GelsInfo list.  To do this, set the Bob's Before and
After pointers to NULL.  Since the GelsInfo list is sorted by GEL x, y
values, Bobs that are higher on the display will appear behind the lower
ones, and Bobs that are more to the left on the display will appear behind
Bobs on the right.

As Bobs are moved about the display, their priorities will change.


28 / / Bob Priorities / Specifying the Drawing Order

To specify the priorities of the Bobs, use the Before and After pointers.
Before points to the Bob that this Bob should be drawn before, and After
points to the Bob that this Bob should be drawn after.  By following these
pointers, from Bob to Bob, the system can determine the order in which the
Bobs should be drawn.  (Take care to avoid circular dependencies in this
list!)

    Note:
    -----
    This terminology is often confusing, but, due to historical reasons,
    cannot be changed.  The system does not draw the Bobs on the Before
    list first, it draws the Bobs on the After list first. Next, it draws
    the current Bob, and, finally, the Bobs on the Before list.

For example, to assure that myBob1 always appears in front of myBob2, The
Before and After pointers must be initialized so that the system will
always draw myBob1 after myBob2.

    myBob2.Before = &myBob1;     /* draw Bob2 before drawing Bob1 */
    myBob2.After  = NULL;        /* draw Bob2 after  no other Bob */
    myBob1.After  = &myBob2;     /* draw Bob1 after  drawing Bob2 */
    myBob1.Before = NULL;        /* draw Bob1 before no other Bob */

As the system goes through the GelsInfo list, it checks the Bob's After
pointer.  If this is not NULL, it follows the After pointer until it hits
a NULL.  Then it starts rendering the Bobs, going back up the Before
pointers until it hits a NULL.  Then it continues through the GelsInfo
list.  So, it is important that all Before and After pointers of a group
properly point to each other.

    Note:
    -----
    In a screen with a number of complex GELs, you may want to specify
    the Before and After order for Bobs that are not in the same
    AnimOb.  This will keep large objects together.  If you do not do
    this, you may have an object drawn with half of its Bobs in front of
    another object!  Also, in sequences you only set the Before and
    After pointers for the active AnimComp in the sequence.


28 / Using Bobs / Adding a Bob

To add a Bob to the system GEL list, use the AddBob() routine.  The Bob
and VSprite structures must be correct and cohesive when this call is
made.  See the makeBob() and makeVSprite() routines in the animtools.c
file listed at the end of this chapter for a detailed example of setting
up Bobs and VSprites.  See the setupGelSys() function for a more complete
example of the initialization of the GELs system.

For example:

    struct GelsInfo myGelsInfo = {0};
    struct VSprite dummySpriteA = {0}, dummySpriteB = {0};
    struct Bob myBob = {0};
    struct RastPort rastport = {0};

    /* Done ONCE, for this GelsInfo.  See setupGelSys() at the end of this
    ** chapter for a more complete initialization of the Gel system
    */
    InitGels(&dummySpriteA, &dummySpriteB, &myGelsInfo);

    /* Initialize the Bob members here, then AddBob() */
    AddBob(&myBob, &rastport);


28 / Using Bobs / Removing a Bob

Two methods may be used to remove a Bob.  The first method uses the
RemBob() macro.  RemBob() causes the system to remove the Bob during the
next call to DrawGList() (or two calls to DrawGList() if the system is
double-buffered).  RemBob() asks the system to remove the Bob at the next
convenient time.  See the description of the BOBSAWAY and BOBNIX flags
above. It is called as follows:

    struct Bob myBob = {0};

    RemBob(&myBob);

The second method uses the RemIBob() routine.  RemIBob() tells the system
to remove this Bob immediately.  For example:

    struct Bob      myBob = {0};
    struct RastPort rastport = {0};
    struct ViewPort viewport = {0};

    RemIBob(&myBob, &rastport, &viewport);

This causes the system to erase the Bob from the drawing area and causes
the immediate erasure of any other Bob that had been drawn subsequent to
(and on top of) this one.  The system then unlinks the Bob from the system
GEL list.  To redraw the Bobs that were drawn on top of the one just
removed, another call to DrawGList() must be made.


28 / Using Bobs / Sorting and Displaying Bobs

As with VSprites, the GelsInfo list must be sorted before any Bobs can be
displayed.  This is accomplished with the SortGList() function.  For Bobs,
the system uses the position information to decide inter-Bob priorities,
if not explicitly set by using the Bob.Before and Bob.After pointers.

Once the GelsInfo list has been sorted, the Bobs in the list can be
displayed by calling DrawGList().  This call should then be followed by a
call to WaitTOF() if the application wants to be sure that the Bobs are
rendered before proceeding.  Call these functions as follows:

    struct RastPort myRastPort = {0};  /* Of course, these have to be */
    struct ViewPort myViewPort = {0};  /* initialized...              */

    SortGList(&myRastPort);
    DrawGList(&myRastPort, &myViewPort);/* Draw the elements (Bobs only) */
    WaitTOF();

    Warning:
    --------
    If your GelsInfo list contains VSprites in addition to Bobs, you
    must also call MrgCop() and LoadView() to make all the GELs
    visible.  Or, under Intuition, RethinkDisplay() must be called to
    make all the GELs visible.


28 / Using Bobs / Changing Bobs

The following characteristics of Bobs can be changed dynamically between
calls to DrawGList():

  * To change the location of the Bob in the RastPort drawing area,
    adjust the X and Y values in the VSprite structure associated with
    this Bob.

  * To change a Bob's appearance, the pointer to the ImageData in the
    associated VSprite structure may be changed.  Note that a change in
    the ImageData also requires a change or recalculation of the
    ImageShadow, using InitMasks().

  * To change a Bob's colors modify the PlanePick, PlaneOnOff or Depth
    parameters in the VSprite structure associated with this Bob.

  * To change a Bob's display priorities, alter the Before and After
    pointers in the Bob structure.

  * To change the Bob into a paintbrush, specify the SAVEBOB flag in the
    Bob.Flags field.

    Changes Are Not Immediately Seen.
    ---------------------------------
    Neither these nor other changes are evident until SortGList() and
    then DrawGList() are called.


28 / Using Bobs / Double-Buffering

Double-buffering is the technique of supplying two different memory areas
in which the drawing routines may create images.  The system displays one
memory space while drawing into the other area.  This eliminates the
"flickering" that is visible when a single display is being rendered into
at the same time that it is being displayed.

    Double-buffering For One Means Double-buffering For All.
    --------------------------------------------------------
    If any of the Bobs is double-buffered, then all of them must be
    double-buffered.

To find whether a Bob is to be double-buffered, the system examines the
pointer named DBuffer in the Bob structure.  If this pointer has a value
of NULL, the system does not use double-buffering for this Bob.  For
example:

    myBob.DBuffer = NULL; /* do this if this Bob is NOT double-buffered */

 DBufPacket and Double-Buffering


28 / / Double-Buffering / DBufPacket and Double-Buffering

For double-buffering, a place must be provided for the system to store the
extra information it needs.  The system maintains these data, and does not
expect the application to change them.  The DBufPacket structure consists
of the following members:

BufY, BufX  Lets the system keep track of where the object was located
            in the last frame (as compared to the Bob structure
            members called OldY and OldX that tell where the object
            was two frames ago).  BufY and BufX provide for correct
            restoration of the background within the currently active
            drawing buffer.

BufPath     Assures that the system restores the backgrounds in the
            correct sequence; it relates to the VSprite members
            DrawPath and ClearPath.

BufBuffer   This field must be set to point to a buffer the same size
            as the Bob's SaveBuffer.  This buffer is used to store the
            background for later restoration when the system moves the
            object.  This buffer must be allocated from Chip memory.

To create a double-buffered Bob, execute a code sequence similar to the
following:

    struct Bob        myBob = {0};
    struct DBufPacket myDBufPacket = {0};

    /* Allocate a DBufPacket for myBob same size as previous example */
    if (NULL != (myDBufPacket.BufBuffer = AllocRaster(48, 20 * 5)))
        {
        /* tell Bob about its double buff status */
        myBob.DBuffer = myDBufPacket;
        }

The example routines makeBob() and freeBob() in the animtools.c listing at
the end of this chapter show how to correctly allocate and free a
double-buffered Bob.


28 / / Collisions and GEL Structure Extensions

This section covers two topics that are applicable to all GELs: how to
extend GEL data structures for your own purposes and how to detect
collisions between GELs and other graphics objects.

 Detecting Gel Collisions
 Setting Up For Boundary Collisions
 Adding User Extensions To Gel Data Structures


28 / Collisions and GEL Structure Extensions / Detecting Gel Collisions

All GELs, including VSprites, can participate in the software collision
detection features of the graphics library.  Simple Sprites must use
hardware collision detection.  See the Amiga Hardware Reference Manual for
information about hardware collision detection.

Two kinds of collisions are handled by the system routines:
GEL-to-boundary hits and GEL-to-GEL hits.  You can set up as many as 16
different routines to handle different collision combinations; one routine
to handle the boundary hits, and up to fifteen more to handle different
inter-GEL hits.

You supply the actual collision handling routines, and provide their
addresses to the system so that it can call them as needed (when the hits
are detected).  These addresses are kept in a collision handler table
pointed to by the CollHandler field of the GelsInfo list.  Which routine
is called depends on the 16-bit MeMask and HitMask members of the VSprite
structures involved in the collision.

When you call DoCollision(), the system goes through the GelsInfo list
which, is constantly kept sorted by x, y position.  If a GEL intersects
the display boundaries and the GELs HitMask indicates it is appropriate,
the boundary collision routine is called.  When DoCollision() finds that
two GELs overlap, it compares the MeMask of one with the HitMask of the
other.  If corresponding bits are set in both, it calls the appropriate
inter-GEL collision routine at the table position corresponding to the
bits in the HitMask and MeMask, as outlined below.

 Preparing for Collision Detection         VSprite BorderLine
 Building a Table of Collision Routines    VSprite HitMask and MeMask
 VSprite Collision Mask                    Using HitMask and MeMask


28 / / Detecting Gel Collisions / Preparing for Collision Detection

Before you can use the system to detect collisions between GELS, you must
allocate and initialize a table of collision-detection routines and place
the address of the table in the GelsInfo.CollHandler field.  This table is
an array of pointers to the actual routines that you have provided for
your collision types.  You must also prepare some members of the VSprite
structure: CollMask, BorderLine, HitMask, and MeMask.


28 / / Detecting Collisions / Building a Table of Collision Routines

The collision handler table is a structure, CollTable, defined in
<graphics/gels.h>.  It is accessed as the CollHandler member of the
GelsInfo structure.  The table only needs to be as large as the number of
bits for which you wish to provide collision processing.  It is safest,
though, to allocate space for all 16 entries, considering the small amount
of space required.

Call the routine SetCollision() to initialize the table entries that
correspond to the HitMask and MeMask bits that you plan to use.  Do not
set any of the table entries directly, instead give the address to
SetCollision() routine and let it handle the set up of the
GelsInfo.CollTable field.

For example, SetCollision() could be called as follows:

    ULONG            num;
    VOID           (*routine)();
    struct GelsInfo *GInfo;

    VOID myCollisionRoutine(GELA, GELB)   /* sample collision routine */
    struct VSprite *GELA;
    struct VSprite *GELB;
    {
        /* process gels here - GELA and GELB point to the base VSprites */
        /* of the gels, you can use the user extensions to identify what */
        /* hit (if you need the info). */
    }

    /* GelsInfo must be allocated and initialized */

    routine = myCollisionRoutine;

    SetCollision(num, routine, GInfo)

The num argument is the collision table vector number (0-15).  The
(*routine)() argument is a pointer to your collision routine.  And the
GInfo argument is a pointer to the GelsInfo structure.


28 / / Detecting Gel Collisions / VSprite Collision Mask

The CollMask member of the VSprite is a pointer to a memory area allocated
for holding the collision mask of that GEL.  This area must be in Chip
memory and its size is the equivalent of one bitplane of the GEL's image.
The collision mask is usually the same as the shadow mask of the GEL,
formed from a logical-OR combination of all planes of the image.  The
following figure shows an example collision mask.

     If this is the        ...and this is the        ...then its
    image in plane 1...    image in plane 2...       CollMask is:

     ···············        ···············        ···············
     ·*************·        ···············        ·*************·
     ··*·········*··        ···············        ··*·········*··
     ···*·······*···        ······***······        ···*··***··*···
     ····*·····*····        ·······*·······        ····*··*··*····
     ·····*···*·····        ···············        ·····*···*·····
     ······*·*······        ···············        ······*·*······
     ·······*·······        ···············        ·······*·······
     ···············        ···············        ···············

                     Figure 28-3: A Collision Mask

Alternatively, you may have a collision mask that is not derived from the
image.  In this case, the actual image isn't relevant.  The system will
not register collisions unless the other objects touch the collision mask.
If the collision mask is smaller than the image, other objects will pass
through the edges without a collision.


28 / / Detecting Gel Collisions / VSprite BorderLine

For faster collision detection, the system uses the BorderLine member of
the VSprite structure. BorderLine specifies the location of the horizontal
logical-OR combination of all of the bits of the object.  It may be
compared to taking the whole object's shadow/collision mask and squishing
it down into a single horizontal line.  You provide the system with a
place to store this line.  The size of the data area you allocate must be
at least as large as the image width.

In other words, if it takes three 16-bit words to hold one line of a GEL,
then you must reserve three words for the BorderLine.  In the VSprite
examples, the routine makeVSprite() correctly allocates and initializes
the collision mask and borderline.  For example:

    WORD myBorderLineData[3];  /* reserve space for BorderLine */
                               /* for this Bob */

    myVSprite.BorderLine = myBorderLineData;  /* tell the system */
                                              /* where it is */

Here is a sample of an object and its BorderLine image:

              011000001100    Object
              001100011000
              001100011000
              000110110000
              000010100000

              011110111100    BorderLine image

Using this squished image, the system can quickly determine if the image
is touching the left or rightmost boundary of the drawing area.

To establish default BorderLine and CollMask data, call the InitMasks()
function.


28 / / Detecting Gel Collisions / VSprite HitMask and MeMask

Software collision detection is independently enabled and disabled for
each GEL. Further, you can specify which of 16 possible collision routines
you wish to have automatically executed.  DoCollision(), in addition to
sensing an overlap between objects, uses these masks to determine which
routine (if any) the system will call when a collision occurs.

When the system determines a collision, it performs a logical-AND of the
HitMask of the upper-leftmost object in the colliding pair with the MeMask
of the lower-rightmost object of the pair.  The bits that are 1s after the
logical-AND operation choose which one of the 16 possible collision
routines to perform.

  * If the collision is with the boundary, bit 0 is always a 1 and the
    system calls the collision handling routine number 0.  Always assign
    the routine that handles boundary collisions to vector 0 in the
    collision handling table. The system uses the flag called BORDERHIT
    to indicate that an object has landed on or moved beyond the
    outermost bounds of the drawing area (the edge of the clipping
    region).  The VSprite example earlier in this chapter uses collision
    detection to check for border hits.

  * If any one of the other bits (1 to 15) is set, then the system calls
    your collision handling routine corresponding to the bit set.

  * If more than one bit is set in both masks, the system calls the
    vector corresponding to the rightmost (the least significant) bit
    only.


28 / / Detecting Gel Collisions / Using HitMask and MeMask

This section illustrates the use of the HitMask and MeMask to define one
type of collision.

Suppose there are two classes of objects that you wish to control on the
display:  ENEMYTANK and MYMISSILE.  Objects of class ENEMYTANK should be
able to pass across one another without registering any collisions.
Objects of class MYMISSILE should also be able to pass across one another
without collisions.  However, when MYMISSILE and ENEMYTANK collide, the
system should generate a call to a collision routine.

Choose a pair of collision detect bits not yet assigned within MeMask, one
to represent ENEMYTANK, the other to represent MYMISSILE.  You will use
the same two bits in the corresponding HitMask.  In this example, bit 1
represents ENEMYTANK objects and bit 2 represents MYMISSLE objects.

                          MeMask  HitMask
                          ------  -------
              Bit Number   2  1    2  1
              --- ------   -  -    -  -
              ENEMYTANK 1  0  1    1  0
              ENEMYTANK 2  0  1    1  0
              MYMISSILE    1  0    0  1

In the MeMask, bit 1 is set to indicate that this object is an ENEMYTANK.
Bit 2 is clear (zero) indicating this object is not a MYMISSILE object.
In the HitMask for ENEMYTANK objects, bit 1 is clear (zero) which means,
"I will not register collisions with other ENEMYTANK objects."  However,
bit 2 is set (one) which means, "I will register collisions with MYMISSILE
objects."

Thus when a call to DoCollision() occurs, for any objects that appear to
be colliding, the system ANDs the MeMask of one object with the HitMask of
the other object.  If there are non-zero bits present, the system will
call one of your collision routines.

In this example, suppose that the system senses a collision between
ENEMYTANK 1 and ENEMYTANK 2.  Suppose also that ENEMYTANK 1 is the
top/leftmost object of the pair.  Here is the way that the collision
testing routine performs the test to see if the system will call any
collision-handling routines:

              Bit Number             2  1
              --- ------             -  -
              ENEMYTANK 1  MeMask    0  1
              ENEMYTANK 2  HitMask   1  0

              Result of logical-AND  0  0

Therefore, the system does not call a collision routine.  But suppose that
DoCollision() finds an overlap between ENEMYTANK 1 and MYMISSILE, where
MYMISSILE is the top/leftmost of the pair:

              Bit Number             2  1
              --- ------             -  -
              MYMISSILE MeMask       1  0
              ENEMYTANK 2 HitMask    1  0

              Result of logical-AND  1  0

Therefore, the system calls the collision routine at position 2 in the
table of collision-handling routines.


28 / / Setting Up For Boundary Collisions

To specify the region in the playfield that the system will use to define
the outermost limits of the GEL boundaries, you use these GelsInfo
members: topmost, bottommost, leftmost, and rightmost. The DoCollision()
routine tests these boundaries when determining boundary collisions within
this RastPort.  They have nothing whatsoever to do with graphical
clipping.  Graphical clipping makes use of the RastPort's clipping
rectangle.

Here is a typical program segment that assigns the members correctly (for
boundaries 50, 100, 80, 240).  It assumes that you already have a RastPort
structure pointer named myRastPort.

    myRastPort->GelsInfo->topmost    = 50;
    myRastPort->GelsInfo->bottommost = 100;
    myRastPort->GelsInfo->leftmost   = 80;
    myRastPort->GelsInfo->rightmost  = 240;

 Parameters To Your Boundary Collision Routine
 Parameters To Your Inter-GEL Collision Routines
 Handling Multiple Collisions


28 / / / Parameters To Your Boundary Collision Routine

During the operation of the DoCollision() routine, if you have enabled
boundary collisions for a GEL (by setting the least significant bit of its
HitMask) and it has crossed a boundary, the system calls the boundary
routine you have defined.  The system will call the routine once for every
GEL that has hit, or gone outside of the boundary.  The system will call
your routine with the following two arguments:

  * A pointer to the VSprite structure of the GEL that hit the boundary

  * A flag word containing one to four bits set, representing top,
    bottom, left and right boundaries, telling you which of the
    boundaries it has hit or exceeded. To test these bits, compare to the
    constants TOPHIT, BOTTOMHIT, LEFTHIT, and RIGHTHIT.

See the VSprite example given earlier for an example of using boundary
collision.


28 / / / Parameters To Your Inter-GEL Collision Routines

If, instead of a GEL-to-boundary collision, DoCollision() senses a
GEL-to-GEL collision, the system calls your collision routine with the
following two arguments:

  * Address of the VSprite that is the uppermost (or leftmost if y
    coordinates are identical) GEL of a colliding pair.

  * Address of the VSprite that is the lowermost (or rightmost if y
    coordinates are identical) GEL of the pair.


28 / / Set Up For Boundary Collisions / Handling Multiple Collisions

When multiple elements collide within the same display field, the
following set of sequential calls to the collision routines occurs:

  * The system issues each call in a sorted order for GELs starting at
    the upper left-hand corner of the screen and proceeding to the right
    and down the screen.

  * For any colliding GEL pair, the system issues only one call, to the
    collision routine for the object that is the topmost and leftmost of
    the pair.


28 / / Adding User Extensions To Gel Data Structures

This section describes how to expand the size and scope of the VSprite,
Bob and AnimOb data structures.  In the definition for these structures,
there is an item called UserExt at the end of each.  If you want to expand
these structures (to hold your own special data), you define the UserExt
member before the <graphics/gels.h> file is included.  If this member has
already been defined when the <graphics/gels.h> file is parsed,  the
compiler preprocessor will extend the structure definition automatically.
If these members have not been defined, the system will make them SHORTs,
and you may still consider these as being reserved for your private use.

To show the kind of use you can make of this feature, the example below
adds speed and acceleration figures to each GEL by extending the VSprite
structure.  When your collision routine is called, it could use these
values to transfer energy between the two colliding objects (say, billiard
balls).  You would have to set up additional routines, executed between
calls to DoCollision(), that would add the values to the GELs position
appropriately.  You could do this with code similar o the following:

     struct myInfo
         {
         short xvelocity;
         short yvelocity;
         short xaccel;
         short yaccel;
         };

These members are for example only.  You may use any definition for your
user extensions.  You would then also provide the following line, to
extend the VSprites structure, use:

     /* Redefine VUserStuff for my own use. */
     #define VUserStuff struct myInfo

To extend the Bobs structure, use:

     #define BUserStuff struct myInfo

To extend the AnimObs structure, use:

     #define AUserStuff struct myInfo

When the system is compiling the <graphics/gels.h> file with your program,
the compiler preprocessor substitutes "struct myInfo" everywhere that
UserExt is used in the header. The structure is thereby customized to
include the items you wish to associate with it.

    Typedef Cannot Be Used.
    -----------------------
    You cannot use the C-language construct typedef for the above
    statements.  If you want to substitute your own data type for one of
    the UserStuff variables, you must use a #define.


28 Graphics Sprites, Bobs and Animation / Animation with GELs

An animation sequence is composed of a series of drawings.  Each drawing
differs from the preceding one so that when they are arranged in a stack
and viewed sequentially, the images appear to flow naturally.

In classic film animation, image drawing is done in two stages.  The
background for each scene is painted just once.  Then, the cartoon
characters and any other foreground objects are painted on transparent
sheets of celluloid called cells which are placed over the background.
With cells, animation can be achieved by redrawing only the parts of the
scene that move while the background stays the same.  Animation on the
Amiga works similarly.  The background is formed by the playfield while
the objects that move can be conveniently handled with the GELs system.

 Animation Data Structures          Moving the Objects
 Animation Types                    Your Own Animation Routine Calls
 Specifying Animation Components    Standard Gel Rules Still Apply
 Specifying the Animation Object    Animations Special Numbering System
 The AnimKey                        Animtools.h and Animtools.c
 Adding Animation Objects


28 / Animation with GELs / Animation Data Structures

There are two main data structures involved in Amiga animation: AnimComp
and AnimOb.

The AnimComp (Animation Component), is an extension of the Bob structure
discussed in the previous section.  An AnimComp provides a convenient way
to link together a series of images so that they can be sequenced
automatically, and so multiple sequences can be grouped together.  An
AnimComp is analogous to one sheet of celluloid representing a single
image to be placed over the background.

    struct AnimComp
    {
        WORD Flags;                 /* AnimComp flags for system & user */
        WORD Timer;
        WORD TimeSet;
        struct AnimComp  *NextComp;
        struct AnimComp  *PrevComp;
        struct AnimComp  *NextSeq;
        struct AnimComp  *PrevSeq;
        WORD (*AnimCRoutine)();
        WORD YTrans;
        WORD XTrans;
        struct AnimOb    *HeadOb;
                           /* Pointer back to the controlling AnimOb */
        struct Bob       *AnimBob;
                           /* Underlying Bob structure for this AnimComp */
    };

The AnimComp structure contains pointers, PrevSeq and NextSeq, that lets
you group these cells into stacks that will be viewed sequentially.  The
AnimComp structure also has PrevComp and NextComp pointers that let you
group stacks into complex objects containing multiple independently moving
parts.

The second animation data structure is the AnimOb which provides the
variables needed for overall control over a group of AnimComps.  The
AnimOb itself contains no imagery; it simply provides a common reference
point for the sequenced images and specifies how the system should move
that point.

    struct AnimOb
    {
        struct AnimOb    *NextOb, *PrevOb;
        LONG Clock;
        WORD AnOldY, AnOldX;            /* old y,x coordinates          */
        WORD AnY, AnX;                  /* y,x coordinates of the AnimOb*/
        WORD YVel, XVel;                /* velocities of this object    */
        WORD YAccel, XAccel;            /* accelerations of this object */
        WORD RingYTrans, RingXTrans;    /* ring translation values      */
        WORD (*AnimORoutine)();         /* address of user procedure    */
        struct AnimComp  *HeadComp;     /* pointer to first component   */
        AUserStuff AUserExt;            /* AnimOb user extension        */
    };

These structures can be used in various ways.  A simple animation of a
rotating ball could be created with three or four AnimComps linked
together in a circular list by their NextSeq and PrevSeq fields.  The
system displays the initial AnimComp (the "top of the stack"), then
switches to the AnimComp pointed to by NextSeq, and then switches to its
NextSeq and so on until it reaches the end of the sequence.  The sequence
starts over again automatically if the last AnimComp.NextSeq points back
to the first AnimComp in the stack.

For a more complex animation of a walking human, you could use five
stacks, i.e., five circular lists of AnimComps; four stacks for the arms
and legs and a single stack for the head and torso.  To group these stacks
into one cohesive unit showing a human figure, you use the PrevComp and
NextComp pointers in the AnimComp structure.  All the stacks would also
share a common AnimOb, so that the combined sequences can be moved as a
single object.

     Figure 28-4: Linking AnimComps For a Multiple Component AnimOb


28 / Animation with GELs / Animation Types

The GELs system provides several ways of setting up automatic animation,
loosely based on some categories of movement in real life.  Some things
(like balls or arrows) can move independently of the background, and look
even more realistic if they tumble or rotate as they move; other things
(like worms, wheels, and people) must be anchored to the background, or
they will appear to slide unnaturally.

The system software allows these types of animation through simple motion
control, motion control with sequenced drawing, and sequenced drawing
using Ring Motion Control.

 Simple Motion Control    Sequenced Drawing    Ring Motion Control


28 / / Animation Types / Simple Motion Control

To produce motion of a simple object, such as a ball, the object is simply
moved relative to a background display, a little at a time.  This is
simple motion control, and can be accomplished with one AnimComp and one
AnimOb, by simply changing the AnimOb's position every N video frames.
The apparent speed of the object is a combination of how often it is moved
(every frame, every other frame, etc.) and how far it is moved (how much
the AnimOb's AnX and AnY are changed).


28 / / Animation Types / Sequenced Drawing

To make the ball appear to rotate is a little more complex.  To produce
apparent movement within the image, sequencing is used.  This is done by
having a stack of AnimComp's that are laid down one after the other, a
frame at a time.  The stack can be arranged in a circular list for
repeating movement.  So, when you combine a sequence of drawings using
AnimComps with simple motion control using an AnimOb, you can perform more
complex animations such as having a rotating ball bounce around.


28 / / Animation Types / Ring Motion Control

Making a worm appear to crawl is similar to the rotating ball.  There is
still a stack of AnimComps that are sequenced automatically, and one
controlling AnimOb.  But each AnimComp image is drawn so that it appears
to move relative to an internal point that remains stationary throughout
the stack.  So instead of the AnimOb's common reference point moving in
each frame, you tell the system how far to move only at the end of each
AnimComp sequence.

     Figure 28-5: Ring Motion Control

As illustrated in the figure at left, the sequence of events for Ring
Motion Control look like this:

    Draw AnimComp1, Draw AnimComp2, Draw AnimComp3, Move AnimOb,
    Draw AnimComp1, Draw AnimComp2, Draw AnimComp3, Move AnimOb,
    Draw AnimComp1...


28 / Animation with GELs / Specifying Animation Components

For each AnimComp, you initially specify:

      * A pointer to the AnimComp's controlling AnimOb.

      * Initial and alternate views, their timing and order.

      * The initial inter-component drawing priorities (for multiple
        AnimComp sequences, this specifies which sequence to display
        frontmost).

      * A pointer to a special animation routine related to this
        component (optional).

      * Your own extensions to this structure (optional).

 Sequencing AnimComps              Linking Multiple AnimComp Sequences
 Position of an AnimComp           Component Ordering
 Specifying Time for Each Image


28 / / Specifying Animation Components / Sequencing AnimComps

To specify the sequencing of AnimComp images, the pointers called PrevSeq
and NextSeq are used to build a doubly-linked list.  The sequence can be
made circular (and usually is) by linking the first and last AnimComps in
the sequence: the NextSeq of the last AnimComp must point back to the
first AnimComp, and the PrevSeq of the first AnimComp must point to the
last AnimComp.  If the list is a loop, then the system will continue to
cycle through the list until it is stopped.  If the list is not a loop,
then the program must act to restart the sequence after the last item is
displayed.  The AnimCRoutine field of the last AnimComp can be used to do
this.


28 / / Specifying Animation Components / Position of an AnimComp

To specify the placement of each AnimComp relative to its controlling
AnimOb, you set the AnimComp members XTrans and YTrans.  These values can
be positive or negative.

The system is designed so that only one of the AnimComps in any given
sequence is "active" (being displayed) at a given point in time.  It is
the only image in the sequence that is (or is about to be) linked into the
GelsInfo list. The Timer determines how long each Component in the
sequence remains active, as described below.


28 / / Animation Components / Specifying Time for Each Image

The AnimComp members Timer and TimeSet are used to specify how long the
system should keep each sequential image on the screen.

When the system makes an animation component active, it copies the value
you have put in the TimeSet member into the Timer member.  As the
animation proceeds, the system decrements Timer; as long as it is greater
than zero, then that AnimComp remains active.  When the Timer value
reaches zero, the system makes the next AnimComp in the sequence active,
and the process repeats.

If you initialize the value in TimeSet to zero, the system will not
sequence this component at all (and Timer will remain zero).


28 / / Animation Components / Linking Multiple AnimComp Sequences

When an AnimOb is built from multiple AnimComp sequences, the sequences
are linked together by the the PrevComp and NextComp fields of the
AnimComps.  These pointers must be initialized only in the initial
AnimComp of each sequence.  The other components that are not initially
active should have their PrevComp and NextComp pointers set to NULL.

    Do Not Use Empty Fields.
    ------------------------
    You cannot store data in the empty PrevComp and NextComp fields.  As
    the system cycles through the AnimComps, the NextComp and PrevComp
    fields are set to NULL when an old AnimComps is replaced by a new
    AnimComp.  The new AnimComp is then linked in to the list of
    sequences in place of the old one.


28 / / Specifying Animation Components / Component Ordering

The PrevSeq, NextSeq, PrevComp and NextComp linkages have no bearing on
the order in which AnimComps in any given video frame are drawn.  To
specify the inter-component priorities (so that the closest objects appear
frontmost) the Before and After pointers in the initially active
AnimComp's underlying Bob structure are linked in to the rest of the
system, as described previously in the discussion of Bobs.

This setup needs to be done once, for the initially active AnimComps of
the AnimOb only.

The animation system adjusts the Before and After pointers of all the
underlying Bob structures to constantly maintain the inter-component
drawing sequence, even though different components are being made active
as sequencing occurs.

These pointers also assure that one complete object always has priority
over another object. The Bob Before and After pointers are used to link
together the last AnimComp's Bob of one AnimOb to the first AnimComp's Bob
of the next AnimOb.


28 / Animation with GELs / Specifying the Animation Object

For each AnimOb, you initially specify:

      * The starting position of this object

      * Its velocity and acceleration (optional).

      * A pointer to the first of its AnimComps.

      * A pointer to a special animation routine related to this object
        (optional).

      * Your own extensions to this structure (optional).

 Linking the AnimComp Sequences to the AnimOb
 Position of an AnimOb
 Setting Up Simple Motion Control
 Setting Up Ring Motion Control
 Using Sequenced Drawing and Motion Control


28 / / / Linking the AnimComp Sequences to the AnimOb

Within each AnimOb there may be one or more AnimComp sequences.  The
HeadComp of the AnimOb points to the first AnimComp in the list of
sequences.

Each sequence is identified by its "active" AnimComp.  There can only be
one active AnimComp in each sequence.  The sequences are linked together
by their active AnimComps; for each of these the NextComp and PrevComp
fields link the sequences together to create a list.  The first sequence
in the list (HeadComp of the AnimOb), has its PrevComp set to NULL.  The
last sequence in the list has its NextComp set to NULL.  None of the
inactive AnimComps should have NextComp or PrevComp fields set.

To find the active AnimComp at run time, you can look in the AnimOb's
HeadComp field.  To find the active AnimComp from any another AnimComp,
use the HeadOb field to find the controlling AnimOb first and then look in
its HeadComp field to find the active AnimComp.

The figure below shows all the linkages in data structures needed to
create the animation GELs.

  ___________________
 |                   |
 |    Next AnimOb    |
 |___________________|
 |                   |
 |  Previous AnimOb  |                                  Non-Current
 |___________________|          Original                -----------
 |                   |          --------             Additional views
 | \\\\\\\\\\\\\\\\\ |        (first view)          of each component,
 | \\\\\\\\\\\\\\\\\ |        of an AnimOb          waiting to be used.
 |___________________|     ___________________      _ _ _ _ _ _ _ _ _ _
 |                   |----|                   |    |                   |
 |     HeadComp      |  _\|   Next AnimComp   |__  |   Next AnimComp   |
 |___________________| | /|___________________|  | |_ _ _ _ _ _ _ _ _ _|
                       |  |                   |  | |                   |
                       |  | Previous AnimComp |  | | Previous AnimComp |
                       |  |___________________|  | |_ _ _ _ _ _ _ _ _ _|
                       |  |                   |  | |                   |
                       |  | Sequence Linkage  |--|-| Sequence linkage  |--
                       |  |___________________|  | |_ _ _ _ _ _ _ _ _ _|
                       |  |                   |  | |                   |
                       |  | \\\\\\\\\\\\\\\\\ |  | | \\\\\\\\\\\\\\\\\ |
                       |  |___________________|  | |_ _ _ _ _ _ _ _ _ _|
                       |                         |
                       |                         |
                       |   ___________________   |  _ _ _ _ _ _ _ _ _ _
                       |  |                   |/_| |                   |
                      _|_\|   Next AnimComp   |\   |   Next AnimComp   |
                     | | /|___________________|--. |_ _ _ _ _ _ _ _ _ _|
                     | |  |                   |  | |                   |
                     | |__| Previous AnimComp |  | | Previous AnimComp |
                     |    |___________________|  | |_ _ _ _ _ _ _ _ _ _|
                     |    |                   |  | |                   |
                     |    | Sequence Linkage  |--|-| Sequence linkage  |--
                     |    |___________________|  | |_ _ _ _ _ _ _ _ _ _|
                     |    |                   |  | |                   |
                     |    | \\\\\\\\\\\\\\\\\ |  | | \\\\\\\\\\\\\\\\\ |
                     |    |___________________|  | |_ _ _ _ _ _ _ _ _ _|
                     |                           |
                     |                           |
                     |     ___________________   |  _ _ _ _ _ _ _ _ _ _
                     |    |                   |/_| |                   |
                     |    |   Next AnimComp   |\   |   Next AnimComp   |
                     |    |___________________|    |_ _ _ _ _ _ _ _ _ _|
                     |    |                   |    |                   |
                     |____| Previous AnimComp |    | Previous AnimComp |
                          |___________________|    |_ _ _ _ _ _ _ _ _ _|
                          |                   |    |                   |
                          | Sequence Linkage  |----| Sequence linkage  |--
                          |___________________|    |_ _ _ _ _ _ _ _ _ _|
                          |                   |    |                   |
                          | \\\\\\\\\\\\\\\\\ |    | \\\\\\\\\\\\\\\\\ |
                          |___________________|    |_ _ _ _ _ _ _ _ _ _|

                    Figure 28-6: Linking of an AnimOb


28 / / Specifying the Animation Object / Position of an AnimOb

To position the object and its component parts, use the AnimOb structure
members AnX and AnY.  The following figure illustrates how each component
has its own offset from the AnimOb's common reference point.

     Figure 28-7: Specifying an AnimOb Position

When you change the animation object's AnX and AnY, all of the component
parts will be redrawn relative to it the next time DrawGList() is called.


28 / / Specifying Animation Object / Setting Up Simple Motion Control

In this form of animation, you can specify objects that have independently
controllable velocities and accelerations in the X and Y directions.
Components can still sequence.

The variables that control this motion are located in the AnimOb structure
and are called:

  * YVel, XVel--the velocities in the y and x directions. These
    values are added to the position values on each call to Animate()
    (see below).

  * YAccel, XAccel--the accelerations in the xa nd y directions.
    These values are added to the velocity values on each call to
    Animate() (see below).  The velocity values are updated before the
    position values.


28 / / Specifying Animation Object / Setting Up Ring Motion Control

To make a given component trigger a move of the AnimOb you set the
RINGTRIGGER bit of that AnimComp's Flags field. When the system software
encounters this flag, it adds the values of RingXTrans and RingYTrans to
the AnX and AnY values of the controlling AnimOb.  The next time you
execute DrawGList(), the drawing sequence will use the new position.

You usually set RINGTRIGGER in only one of the animation components in a
sequence (the last one); however, you can use this flag and the
translation variables any way you wish.


28 / / / Using Sequenced Drawing and Motion Control

If you are using Ring Motion Control, you will probably set the velocity
and acceleration variables to zero.  For instance, consider the example of
a person walking.  With Ring Motion Control, as each foot falls it is
positioned on the ground exactly where originally drawn.  If you included
a velocity value, the person's foot would not be stationary with respect
to the ground, and the person would appear to "skate" rather than walk.
If you set the velocity and acceleration variables at zero, you avoid this
problem.

When the system activates a new AnimComp, it checks the Flags field to see
if the RINGTRIGGER bit is set.  If so, the system adds RingYTrans and
RingXTrans to AnY and AnX respectively.


28 / Animation with GELs / The AnimKey

The system uses one pointer, known as the AnimKey, to keep track of all
the AnimObs via their PrevOb and NextOb linkage fields.  The AnimKey acts
as the anchor for the list of AnimObs you are using and is initialized
with code such as the following:

    struct AnimOb *animKey;

    InitAnimate(&animKey);
        /* Only do this once to initialize the AnimOb list */

As each new object is added (via AddAnimOb()), it is linked in at the
beginning of the list, so AnimKey will always point to the object most
recently added to the list.  To search forward through the list, start
with the AnimKey and move forward on the NextOb link.  Continue to move
forward until the NextOb is NULL, indicating the end of the list.  The
PrevOb link will allow you to move back to a previous object.

    Set Up PrevOb and NextOb Correctly.
    -----------------------------------
    It is important that the NextOb link of the last object is NULL,
    and that the PrevOb of the first object is NULL.  In fact, the
    system expects the animation object lists to be exactly the way
    that they are described above.  If they are not, the system will
    produce unexpected results.


28 / Animation with GELs / Adding Animation Objects

Use the routine AddAnimOb() to add animation objects to the controlled
object list.  This routine will link the PrevOb and NextOb pointers to
chain all the AnimObs that the system is controlling.

    struct RastPort myRPort;
    struct AnimOb myAnimOb;
    struct AnimOb *animKey;  /* Must be initialized with InitAnimate() */

    AddAnimOb(&myAnimOb, &animKey, &myRPort);


28 / Animation with GELs / Moving the Objects

When you have defined all of the structures and have established all of
the links, you can call the Animate() routine to move the objects.
Animate() adjusts the positions of the objects as described above, and
calls the various subroutines (AnimCRoutines and AnimORoutines) that you
have specified.

After the system has completed the Animate() routine, some GELs may have
been moved, so the GelsInfo list order may possibly be incorrect.
Therefore, the list must be re-sorted with SortGList() before passing it
to a system routine.

If you are using collision detection, you then perform DoCollision().
Your collision routines may also have an effect on the relative position
of the GELs.  Therefore, you should again call SortGList() to assure that
the system correctly orders the objects before you call DrawGList(). When
you call DrawGList(), the system renders all the GELs it finds in the
GelsInfo list and any changes caused by the previous call to Animate() can
then be seen.

This is illustrated in the following typical call sequence:

    struct AnimOb **myAnimKey;
    struct RastPort *rp;
    struct ViewPort *vp;

    /* ... setup of graphics elements and objects */

    Animate(myAnimKey, rp);       /* "move" objects per instructions */
    SortGList(rp);                /*  put them in order */
    DoCollision(rp);              /*  software collision detect/action */
    SortGList(rp);                /*  put them back into right order */
    DrawGList(vp, rp);            /*  draw into current RastPort */


28 / Animation with GELs / Your Own Animation Routine Calls

The AnimOb and AnimComp structures can include pointers for your own
routines that you want the system to call.  These pointers are stored in
the AnimOb's AnimORoutine field and in the AnimComp's AnimCRoutine field,
respectively.

When Animate() is called, the system performs the following steps for
every AnimOb in the AnimKey list:

    * Updates the AnimOb's location and velocities.

    * Calls the AnimOb.AnimORoutine routine if one is supplied.

    * The for each AnimComp of the AnimOb:

         · If this sequence times out, switches to the new AnimComp.

         · Calls the AnimComp.AnimCRoutine if one is supplied.

         · Sets the underlying VSprite's x,y coordinates.

If you want a routine to be called, you put the address of the routine in
either AnimComp.AnimCRoutine or AnimOb.AnimORoutine member as needed.  If
no routine is to be called, you must set these fields to NULL.  Your
routines will be passed one parameter, a pointer to the AnimOb or AnimComp
it was related to.  You can use the user structure extensions discussed
earlier to hold the variables you need for your own routines.

For example, if you provide a routine such as this:

    VOID MyOCode(struct AnimOb *anOb)
    {
    /* whatever needs to be done */
    }

Then, if you put the address of the routine in an AnimOb structure:

    myAnimOb.AnimORoutine = MyOCode;

MyOCode() will be called with the address of this AnimOb when Animate()
processes this AnimOb.


28 / Animation with GELs / Standard Gel Rules Still Apply

Before you use the animation system, you must have called the routine
InitGels().  The section called "Bob Priorities" describes how the system
maintains the list of GELs to draw on the screen according to their
various data fields.  The animation system selectively adds GELs to and
removes GELs from this list of screen objects during the Animate()
routine.  On the next call to DrawGList(), the system will draw the GELs
in the list into the selected RastPort.


28 / Animation with GELs / Animations Special Numbering System

Velocities and accelerations can be either positive or negative. The
system treats the velocity, acceleration and Ring values as fixed-point
binary fractions, with the decimal point at position 6 in the word.  That
is: vvvvvvvvvv.ffffff where v stands for actual values that you add to the
x or y (AnX, AnY) positions of the object for each call to Animate(), and
f stands for the fractional part.  By using a fractional part, you can
specify the speed of an object in increments as precise as 1/64th of an
interval.

If you set the value of XVel at 0x0001, it will take 64 calls to the
Animate() routine before the system will modify the object's x coordinate
position by a step of one. The system constant ANFRACSIZE can be used to
shift values correctly.  So if you set the value to (1 << ANFRACSIZE), it
will be set to 0x0040, the value required to move the object one step per
call to Animate(). The system constant ANIMHALF can be used if you want
the object to move every other call to Animate().

Each call you make to Animate() simply adds the value of XAccel to the
current value of XVel, and YAccel to the current value of YVel, modifying
these values accordingly.


28 / Animation with GELs / Animtools.h and Animtools.c

Here is the listing of the animtools.h header file and the animtools.c
link file used by the examples in this chapter.  The makeSeq() and
makeComp() subroutines here demonstrate how to use the GELs animation
system.

     animtools.h          animtools.c


28 Graphics Sprites, Bobs and Animation / Function Reference

The following are brief descriptions of the Amiga's graphics animation
functions.  See the Amiga ROM Kernel Reference Manual: Includes and
Autodocs for details on each function call.

                 Table 28-1: Graphics Animation Functions
  ________________________________________________________________________
 |                                                                        |
 |     Animation                                                          |
 |     Function                   Description                             |
 |========================================================================|
 |     AddAnimOb()  Add an AnimOb to the linked list of AnimObs.          |
 |        AddBob()  Add a Bob to the current gel list.                    |
 |    AddVSprite()  Add a VSprite to the current gel list.                |
 |       Animate()  Process every AnimOb in the current animation list.   |
 |  ChangeSprite()  Change the sprite image pointer.                      |
 |   DoCollision()  Test every gel in gel list for collisions.            |
 |     DrawGList()  Process the gel list, queueing VSprites, drawing Bobs.|
 |  FreeGBuffers()  Deallocate memory obtained by GetGBuffers().          |
 |    FreeSprite()  Return sprite for use by others and virtual sprite    |
 |                  machine.                                              |
 |   GetGBuffers()  Attempt to allocate all buffers of an entire AnimOb.  |
 |     GetSprite()  Attempt to get a sprite for the simple sprite manager.|
 |      InitGels()  Initialize a gel list; must be called before using    |
 |                  gels.                                                 |
 |    InitGMasks()  Initialize all of the masks of an AnimOb.             |
 |     InitMasks()  Initialize the BorderLine and CollMask masks of a     |
 |                  VSprite.                                              |
 |    MoveSprite()  Move sprite to a point relative to top of ViewPort.   |
 |        RemBob()  Remove a Bob from the gel list.                       |
 |       RemIBob()  Immediately remove a Bob from the gel list and the    |
 |                  RastPort.                                             |
 |    RemVSprite()  Remove a VSprite from the current gel list.           |
 |  SetCollision()  Set a pointer to a user collision routine.            |
 |     SortGList()  Sort the current gel list, ordering its y,x           |
 |                  coordinates.                                          |
 |________________________________________________________________________|


Amiga® RKM Libraries: 29 Graphics Library and Text

On the Amiga, rendering text is similar to rendering lines and shapes.
The Amiga graphics library provides text functions based around the
RastPort structure, which makes it easy to intermix graphics and text.

 About Amiga Fonts
 The Text Function
 Does the Text Fit?
 Font Scaling and Aspect Ratio
 Some Things to Look Out For
 What Fonts Are Available?
 How is an Amiga Font Structured in Memory?
 But What About Color Fonts?
 The Composition of a Bitmap Font on Disk
 Function Reference


29 Graphics Library and Text / About Amiga Fonts

In order to render text, the Amiga needs to have a graphical
representation for each symbol or text character.  These individual images
are known as glyphs.  The Amiga gets each glyph from a font in the system
font list.  At present, the fonts in the system list contain a bitmap of a
specific point size for all the characters and symbols of the font.

Fonts are broken up into different font families.  For example, the
Amiga's Topaz is a font family.  Each font family shares a basic look but
can have a variety of styles and point sizes.

The style of a font refers to a minor alteration in the way the plain
version of the font's characters are rendered.  Currently, the Amiga
supports three font styles: bold, italics and underline (the font's style
may also be considered plain when it does not have any of these styles).
Although these styles can be inherent to a font, they are normally added
algorithmically as text is rendered.

On the Amiga, the point size of a font normally refers to the height of
the font in pixels.  For example, Topaz-8 is 8 pixels high.  Because the
size of Amiga pixels varies between display modes, the appearance of a
font will also vary between display modes.  Future versions of the Amiga
OS may measure font size in other units.  For example, the standard point
in the PostScript page description language normally refers to a point as
being a square dot that is 1/72 of an inch on a side.  Using a standard
measuring unit such as the PostScript point makes it possible to create a
WYSIWYG (What You See Is What You Get) display that exactly matches
printer or other device output.

When the Amiga first starts up, the only fonts in the system font list are
Topaz-8 and Topaz-9, both of which are in ROM.  Any other fonts must be
loaded from disk or generated somehow.  In Amiga operating systems prior
to Release 2, additional fonts have to be loaded from disk (usually from
the FONTS: directory) using the diskfont.library.  For each font size of
each font family there is a corresponding bitmap file on disk.  If there
is no bitmap on disk or in ROM for a specific font size, that font size is
not available (if the operating system is 1.3 or earlier).

 System Fonts In Release 2


29 / About Amiga Fonts / System Fonts In Release 2

Under Release 2 and later versions of the OS, the system has additional
font sources at its disposal.  If an application asks the diskfont.library
to load a font of a size that has no corresponding bitmap on disk, the
library can generate that size font.  If diskfont.library can find a
smaller or larger version of the font requested, it can scale that font's
bitmap to the size needed.  Of course, because the library is scaling a
bitmap, the quality of the bitmap can degenerate in the scaling process.

A more significant improvement to the diskfont.library is that contains
AGFA's Intellifont® engine.  As of Release 2.04 (V37) the diskfont.library
can utilize AGFA Compugraphic font outlines.  The Compugraphic fonts (CG
fonts) are mathematical outlines that describe what the font's characters
look like.  The advantage of the outline fonts is that they can be scaled
to any point size without the loss of resolution inherent in bitmap
scaling.  From the programmers point of view, no extra information is
necessary for using the CG fonts, the diskfont.library takes care of all
the scaling.  Future releases of the OS may bring finer control over the
font scaling engine which will allow an application to rotate and shear
glyphs.


29 Graphics Library and Text / The Text Function

Amiga text rendering is centered around the graphics.library function
Text(), which renders text into a rastport:

    void Text( struct RastPort *myrp, STRPTR mystring, ULONG count );

where myrp is a pointer to the target rastport, mystring is the string to
render, and count is the number of characters of mystring to render.
Text() renders at the current rastport position and it takes care of
moving the rastport's current X position as it renders each letter.
Text() only renders text horizontally, so repositioning the rastport's Y
position (for example, for a new line) is the responsibility of the
application.  This is covered in more detail later in this chapter.

Like the other rastport based graphics primitives, most of the text
rendering attributes are specified within the RastPort structure itself.
The current position, the color of the text, and even the font itself are
all specified in the RastPort structure.

 Choosing the Font                      Rendering the Text
 Setting the Text Drawing Attributes    Setting the Font Style


29 / The Text Function / Choosing the Font

The graphics.library function SetFont() changes the rastport's current
font:

    void SetFont( struct RastPort *myrp, struct TextFont *mytf );

The parameter mytf is a pointer to an open, valid TextFont structure.  The
system uses the TextFont structure to keep track of fonts (The TextFont
structure is discussed in detail later in this chapter).  The OpenFont()
(from graphics.library) and OpenDiskFont() (from diskfont.library)
functions both return a pointer to a valid TextFont structure.  The
OpenFont() function will only open fonts that have already been loaded and
are currently in the system list.  Normally applications use the
OpenDiskFont() call instead of OpenFont() because OpenDiskFont() can load
and open fonts from disk as well as open those that are already in the
system list.

Here are prototypes for these functions:

    struct TextFont *OpenDiskFont( struct TextAttr *mytextAttr );
    struct TextFont *OpenFont( struct TextAttr *mytextAttr );

The mytextAttr argument  points to a TextAttr structure that describes the
requested font.  The TextAttr structure (from <graphics/text.h>) looks
like this:

    struct TextAttr {
        STRPTR  ta_Name;            /* name of the font */
        UWORD   ta_YSize;           /* height of the font */
        UBYTE   ta_Style;           /* intrinsic font style */
        UBYTE   ta_Flags;           /* font preferences and flags */
    };

where ta_Name is a string naming the font to open, ta_YSize is the point
size of the font (normally in pixels), ta_Style is a bitfield describing
the font style, and ta_Flags is a bitfield that further describes
characteristics of the font.  Note that the name of the font can either be
the font name alone (<font name>.font) or it can be prepended with a full
path.  Without a path to the font, if the font is not already loaded into
the system list, OpenDiskFont() will look in the FONTS: directory for the
font file.  If there is a path, OpenDiskFont() will look in that directory
for the font files, allowing the user to put fonts in any directory
(although this is discouraged).  OpenFont() and OpenDiskFont() try to find
a font that matches your TextAttr description.  An important thing to
remember about OpenDiskFont() is that only a process can call it (as
opposed to a task).  This is primarily because the function has to use
dos.library to scan disks for font files.

The font styles for ta_Style (from <graphics/text.h>) are:

    FSF_UNDERLINED      The font is underlined
    FSF_BOLD            The font is bolded
    FSF_ITALIC          The font is italicized
    FSF_EXTENDED        The font is extra wide

The flags for ta_Flags (from <graphics/text.h>) are:

    FPF_ROMFONT       This font is built into the ROM (currently, only
                      Topaz-8 and Topaz-9 are ROM fonts).
    FPF_DISKFONT      This font was loaded from disk (with
                      diskfont.library)
    FPF_REVPATH       This font is designed to be printed from from right
                      to left (Hebrew is written from right to left)
    FPF_TALLDOT       This font was designed for a Hires screen (640x200
                      NTSC, non-interlaced)
    FPF_WIDEDOT       This font was designed for a Lores Interlaced screen
                      (320x400 NTSC)
    FPF_PROPORTIONAL  The character widths of this font are not constant
    FPF_DESIGNED      This font size was explicitly designed at this size
                      rather than constructed.  If you do not set this bit
                      in your TextAttr, then the system may generate a
                      font for you by scaling an existing ROM or disk font
                      (under V36 and above).

For example to open an 11 point bold, italic Topaz font, the code would
look something like this:

     pseudotext.c

The example above uses the graphics.library's SetFont() function to change
the rastport's current font.  Notice that this example restores the
rastport's original font (myrp->Font) before exiting.  This isn't normally
necessary unless some other process assumes the rastport's font (or other
drawing attributes) will not change.  Intuition does not rely on the
window's RPort.Font field for rendering or closing the default window
font, so applications can change that font without having to restore it.

Prior to Release 2, some applications assumed that any window they opened
would always use Topaz-8 without bothering to explicitly set it.  Since
Topaz-8 was the normal default font before Release 2, this was usually not
a problem.  However, under Release 2 and later versions of the OS, the
user can easily change the default system fonts with the Font Preferences
editor.  Hence, applications that make assumptions about the size of the
default font look terrible under Release 2 (and in some cases are
unusable).  Program designers should not make assumptions about the system
font, and wherever possible, honor the user font preferences.  See the
"Preferences" chapter of this manual for more information on how to find
user preferences.


29 / The Text Function / Setting the Text Drawing Attributes

In addition to SetFont(), there are three rastport control functions that
set attributes for text rendering:

    void SetAPen( struct RastPort *rp, ULONG pen );
    void SetBPen( struct RastPort *rp, ULONG pen );
    void SetDrMd( struct RastPort *rp, ULONG drawMode );

The color of the text depends upon the rastport's current drawing mode and
pen colors.  You set the draw mode with the SetDrMd() function passing it
a pointer to a rastport and a drawing mode: JAM1, JAM2, COMPLEMENT or
INVERSEID.

If the drawing mode is JAM1, the text will be rendered in the
RastPort.FgPen color.  Wherever there is a set bit in the character's
bitmap image, Text() will set the corresponding bit in the rastport to the
FgPen color.  This is known as overstrike mode.  You set the FgPen color
with the SetAPen() function by passing it a pointer to the rastport and a
color number.

If the drawing mode is set to JAM2, Text() will place the FgPen color as
in the JAM1 mode, but it will also set the bits in the rastport to the
RastPort.BgPen color wherever there is a corresponding cleared bit in the
character's bitmap image.  Basically, this prints the character themselves
in the FgPen color and fills in the surrounding parts of the character
image with the BgPen color.   You set the BgPen color with the SetBPen()
function by passing it a pointer to the rastport and a color number.

If the drawing mode is COMPLEMENT, for every bit set in the character's
bitmap image, the corresponding bits in the rastport (in all of the
rastport's bitplanes) will have their state reversed.  cleared bits in the
character's bitmap image have no effect on the destination rastport.  As
with the other drawing modes, the write mask can be used to protect
certain bitplanes from being modified (see the "graphics primitives"
chapter for more details).

The JAM1, JAM2, and COMPLEMENT drawing modes are mutually exclusive of
each other but each can be modified by the INVERSVID drawing mode.  If you
combine any of the drawing modes with INVERSVID, the Amiga will reverse
the state of all the bits in the source drawing area before writing
anything into the rastport.

The idea of using a RastPort structure to hold all the rendering
attributes is convenient if the rastport's drawing attributes aren't going
to change much.  This is not the case where several processes need to
render into a rastport using very different drawing attributes.  An easy
way around this problem is to clone the RastPort.  By making an exact
duplicate of a RastPort, you can change the various rendering parameters
of your RastPort without effecting other programs that render into the
RastPort you cloned.  Because a RastPort only contains a pointer to the
rendering area (the bitmap), the original RastPort and the cloned RastPort
both render into the bitmap, but they can use different drawing parameters
(font, drawing mode, colors, etc.).


29 / The Text Function / Rendering the Text

When the Text() routine renders text, it renders at the current rastport
position along the text's baseline.  The baseline is an imaginary line on
top of which the text is rendered.  Each font has a baseline that is a
constant number of pixels from the top of the font's bitmap.  For most
fonts, parts of some characters are rendered both above and below the
baseline (for example, y, g, and j usually have parts above and below the
baseline).  The part below the baseline is called the descender.

     Figure 29-1: Descenders and Baseline of Amiga Fonts

Because Text() only increments the rastport's current X position as it
renders text horizontally, programs that need to print several lines of
text have to take care of moving the current pointer to the beginning of
the next line, usually with the graphics.library's Move() function:

    void Move( struct RastPort *rp, LONG x, long y );

When moving the current position to the beginning of the next line, an
application must make sure it leaves enough space above and below the
baseline to prevent characters on different lines from overlapping each
other.  There are a few fields in the TextFont structure returned by
OpenFont() and OpenDiskFont() that are useful for spacing and rendering
text:

struct TextFont {
    struct Message tf_Message; /* reply message for font removal */
                               /* font name in LN       | used in this */
    UWORD   tf_YSize;          /* font height           | order to best */
    UBYTE   tf_Style;          /* font style            | match a font */
    UBYTE   tf_Flags;          /* preferences and flags / request. */
    UWORD   tf_XSize;      /* nominal font width */
    UWORD   tf_Baseline;   /* distance from the top of char to baseline */
    UWORD   tf_BoldSmear;  /* smear to affect a bold enhancement */

    UWORD   tf_Accessors;  /* access count */

    UBYTE   tf_LoChar;     /* the first character described here */
    UBYTE   tf_HiChar;     /* the last character described here */
    APTR    tf_CharData;   /* the bit character data */

    UWORD   tf_Modulo;     /* the row modulo for the strike font data */
    APTR    tf_CharLoc;    /* ptr to location data for the strike font */
                           /*   2 words: bit offset then size */
    APTR    tf_CharSpace;  /* ptr to words of proportional spacing data */
    APTR    tf_CharKern;   /* ptr to words of kerning data */
};

The fields of interest to applications are as follows.

tf_YSize
    The "height", in pixels, of this font.  None of the characters in
    this font will be taller than this value.

tf_XSize
    This is the character width for monospaced (non-proportional) fonts.
    The width includes the extra space needed to the left and right of
    the character to keep the characters from running together.

tf_Baseline
    The distance in pixels from the top line of the font to the baseline.

tf_LoChar
    This is the first character glyph (the graphical symbol associated
    with this font) defined in this font.  All characters that have ASCII
    values below this value do not have an associated glyph.

tf_HiChar
    This is the last character glyph defined in this font.  All
    characters that have ASCII values above this value do not have an
    associated glyph.  An application can use these values to avoid
    rendering characters which have no associated glyphs.  Any characters
    without an associated glyph will have the default glyph associated to
    them.  Normally, the default glyph is a rectangle.

To erase text, the graphics.library provides two functions that were
specifically designed to clear parts of a rastport based on the dimensions
of the current font:

    void ClearEOL( struct RastPort *rp );
    void ClearScreen( struct RastPort *rp );

Using the current font, ClearEOL() will clear the rest of the current text
line from the rastport's current position to the edge of the rastport.
ClearEOL() was introduced in the Release 2 graphics.library.
ClearScreen() will clear the rest of the line as ClearEOL() does, but it
will also clear the rastport below the current line of text.


29 / The Text Function / Setting the Font Style

The OpenFont() and OpenDiskFont() functions both search through the fonts
available to them, looking for the font that most closely matches the
TextAttr structure.  If these functions can't find a font that matches
exactly, they will open the one with the same name that most closely
matches the TextAttr structure's ta_YSize, ta_Style, and ta_Flags fields
(in that order of preference).

If the font doesn't match your style choice exactly, it is possible to ask
the system to alter how it renders the font so it matches the style you
need.  The rastport contains some flags that tell the system's text
rendering functions to algorithmically add styles to characters as they
are rendered.  Currently, the system can add up to three styles to a font:
italics, bold, and underline.  The system cannot alter the style of a font
if the style is already intrinsic to the font.  For example, it is not
possible to add (or remove) the bold styling to a font if the font was
designed to be bolded.  There are two graphics.library functions that deal
with software font style setting:

    ULONG AskSoftStyle( struct RastPort *rp );
    ULONG SetSoftStyle( struct RastPort *rp, ULONG newstyle,
                        ULONG enable );

The AskSoftStyle() function returns a bitmask of the style bits available
to the rastport's current font.  The style bits are the same ones used by
the TextAttr's ta_Style field (from <graphics/text.h>).  SetSoftStyle()
changes the rastport's current software style setting according to the
style bits set in the newstyle field (from the function prototype above).

SetSoftStyle() pays attention only to the bits of newstyle that have the
corresponding bit in the enable field set as well.  This function returns
the style, which is the combined result of previous soft style selection,
the effect of this function, and the style inherent in the set font.  The
following code fragment turns on the algorithmic font attributes for the
rastport (myrastport) based on those style attributes that were requested
in the OpenDiskFont() call (mytextattr.ta_Style) and not inherent in the
font.

    /* Set the font and add software styling to the text if I asked for
       a style in OpenFont() and didn't get it.  Because most Amiga fonts
       do not have styling built into them (with the exception of the CG
       outline fonts), if the user selected some kind of styling for the
       text, it will have to be added algorithmically by calling
       SetSoftStyle().
    */
    if (myfont = OpenDiskFont(mytextattr))
    {
            SetFont(myrastport, myfont);
            SetSoftStyle(myrastport,
                         mytextattr.ta_Style ^ myfont->tf_Style,
                         (FSF_BOLD | FSF_UNDERLINED | FSF_ITALIC));
    ...
    ...
            CloseFont(myfont);
    }


29 Graphics Library and Text / Does the Text Fit?

The Text() function renders its text on a single horizontal line without
considering whether or not the text it renders will actually fit in the
visible portion of the display area.  Although for some applications this
behavior is acceptable, other applications, for example a word processor,
need to render all of their text where the user can see it.  These
applications need to measure the display area to determine how much text
can fit along a given baseline.  The graphics.library contains several
functions that perform some of the necessary measurements:

    WORD TextLength( struct RastPort *my_rp, STRPTR mystring,
                     ULONG mycount );

    void TextExtent( struct RastPort *my_rp, STRPTR mystring, LONG mycount,
                     struct TextExtent *textExtent );

    void FontExtent( struct TextFont *font,
                     struct TextExtent *fontExtent );

    ULONG TextFit  ( struct RastPort *rp, STRPTR mystring, ULONG strLen,
                     struct TextExtent *textExtent,
                     struct TextExtent *constrainingExtent,
                     LONG strDirection, ULONG constrainingBitWidth,
                     ULONG constrainingBitHeight );

The TextLength() function is intended to mimic the Text() function without
rendering the text.  Using the exact same parameters as the Text()
function, TextLength() returns the change in my_rp's current X position
(my_rp.cp_x) that would result if the text had been rendered using the
Text() function.  As in Text(), the mycount parameter tells how many
characters of mystring to measure.

Some fonts have characters that intrinsically render outside of the normal
rectangular bounds.  This can result for example, from the Amiga's version
of kerning (which is discussed later in this chapter) or from algorithmic
italicizing.  In such cases, TextLength() is insufficient for determining
whether a text string can fit within a given rectangular bounds.

The TextExtent() function offers a more complete measurement of a string
than the TextLength() function.  TextExtent(), which was introduced in
Release 2, fills in the TextExtent structure passed to it based on the
current rendering settings in my_rp. T The TextExtent structure
<graphics/text.h>) supplies the dimensions of mystring's bounding box:

    struct TextExtent {
        UWORD   te_Width;           /* same as TextLength */
        UWORD   te_Height;          /* same as tf_YSize   */
        struct Rectangle te_Extent; /* relative to CP     */
    };

The Rectangle structure (from <graphics/gfx.h>):

    struct Rectangle
    {
        WORD   MinX,MinY;
        WORD   MaxX,MaxY;
    };

TextExtent() fills in the TextExtent as follows:

    te_Width        the same value returned by TextLength().

    te_Height       the font's Y size.

    te_Extent.MinX  the pixel offset from the rastport's current X position
                    to the left side of the bounding box defined by the
                    rectangle structure.  Normally, this is zero.

    te_Extent.MinY  the distance in pixels from the baseline to the top of
                    the bounding box.

    te_Extent.MaxX  the pixel offset from the rastport's current X position
                    to the right side of the bounding box.  Normally, this
                    is te_Width - 1.

    te_Extent.MaxY  the distance from the baseline to the bottom of the
                    bounding box.

The FontExtent() function is similar to the TextExtent() function.  It
fills in a TextExtent structure that describes the bounding box of the
largest possible single character in a particular open font, including the
effects of kerning.  Because the FontExtent() function looks at an open
TextFont structure rather than a rastport to figure out values of the
TextExtent structure, it cannot consider the effects of algorithmic
styling.  Like TextExtent(), FontExtent() was introduced in Release 2, so
it is not available under the 1.3 or earlier OS releases.

The TextFit() function looks at a string and returns the number of
characters of the string that will fit into a given rectangular bounds.
TextFit() takes the current rastport rendering settings into consideration
when measuring the text.  Its parameters (from the prototype above) are:

    my_rp                  tells which rastport to get the rendering
                           attributes from

    mystring               the string to "fit"

    strLen                 number of characters of mystring to "fit"

    constrainingExtent     a TextExtent describing the bounding
                           box in which to "fit" mystring

    strDirection           the offset to add to the string pointer to get
                           to the next character in mystring (can be
                           negative)

    constrainingBitWidth   an alternative way to specify the width of the
                           bounding box in which to "fit" mystring

    constrainingBitHeight  an alternative way to specify the height of the
                           bounding box in which to "fit" mystring

TextFit() will only pay attention to the constrainingBitWidth and
constrainingBitHeight fields if constrainingExtent is NULL.

 Text Measuring Example


29 Graphics Library and Text / Font Scaling and Aspect Ratio

The Release 2 OS offers a significant improvement over the Amiga's
previous font resources: it now has the ability to scale fonts to new
sizes and dimensions.  This means, if the diskfont.library can't find the
font size an application requests, it can create a new bitmap font by
scaling the bitmap of a different size font in the same font family.  The
2.04 (V37) release of the OS improved upon the diskfont.library's font
scaling ability so the Amiga now can utilize AGFA Compugraphic outline
fonts, yielding scalable fonts that don't have the exaggerated jagged
edges inherent in bitmap scaling.

The best thing about the Amiga's font scaling is that its addition to the
system is completely invisible to an application program.  Because the
diskfont.library takes care of all the font scaling, any program that uses
OpenDiskFont() to open a font can have scalable fonts available to it.
For simple scaling, the programming interface is the same using Release 2
as it was under 1.3.

However, there is one feature of the Release 2 diskfont.library that the
1.3 programming interface cannot handle.  When scaling a font (either from
an outline or from another bitmap), the Release 2 diskfont.library can
adjust the width of a font's glyphs according to an aspect ratio passed to
OpenDiskFont().  A font glyph is the graphical representations associated
with each symbol or character of a font.

The aspect ratio refers to the shape of the pixels that make up the bitmap
that diskfont.library creates when it scales a font.  This ratio is the
width of a pixel to the height of the pixel (XWidth/ YWidth).  The
diskfont.library uses this ratio to figure out how wide to make the font
glyphs so that the look of a font's glyphs will be the same on display
modes with very different aspect ratios.

To add this new feature, several changes to the OS were necessary:

 1) The OS needed to be able to store an aspect ratio for any font loaded
    into the system list.

 2) The structures that diskfont.library uses to store bitmap fonts on
    disk had to be updated so they can store the aspect ratio a font was
    designed for.

 3) The way in which an application requests fonts from diskfont.library
    had to be altered so that an application could ask for a specific
    aspect ratio.

For the diskfont.library to be able to scale a font to a new aspect ratio,
it needs to know what the font's current aspect ratio is.  The Amiga gets
the aspect ratio of a font currently in the system list from an extension
to the TextFont structure called (oddly enough) TextFontExtension.  Under
Release 2, when the system opens a new font (and there is sufficient
memory), it creates this extension.

A font's TextFont structure contains a pointer to its associated
TextFontExtension.  While the font is opened, the TextFont's
tf_Message.mn_ReplyPort field points to a font's TextFontExtension.  The
<graphics/text.h> include file #defines tf_Message.mn_ReplyPort as
tf_Extension.

The TextFontExtension structure contains only one field of interest: a
pointer to a tag list associated with this font:

    struct TagItem *tfe_Tags;               /* Text Tags for the font */

If a font has an aspect ratio associated with it, the OS stores the aspect
ratio as a tag/value pair in the tfe_Tags tag list.

The TA_DeviceDPI tag holds a font's aspect ratio.  The data portion of the
TA_DeviceDPI tag contains an X DPI (dots per inch) value in its upper word
and a Y DPI value in its lower word.  These values are unsigned words
(UWORD).  At present, these values do not necessarily reflect the font's
true X and Y DPI, so their specific values are not relevant.  At present,
only the ratio of the X aspect to the Y aspect is important (more on this
later in the article).

Notice that the X and Y DPI values are not aspect values.  The X and Y
aspect values are the reciprocals of the X and Y DPI values, respectively:

    XDPI = 1/XAspect
    YDPI = 1/YAspect

so, the aspect ratio is YDPI/XDPI, not XDPI/YDPI.

Before accessing the tag list, an application should make sure that this
font has a corresponding TextFontExtension.  The ExtendFont() function
will return a value of TRUE if this font already has an extension or
ExtendFont() was able to create an extension for this font.

The Amiga has a place to store a font's X and Y DPI values once the font
is loaded into memory, but where do these X and Y values come from?  A
font's X and Y DPI values can come from several sources.  The X and Y DPI
can come from a font's disk-based representation, or it can be set by the
programmer.

For the traditional Amiga bitmap fonts, in order to store the X and Y DPI
values in a bitmap font's ".font" file, the structures that make up the
".font" file had to be expanded slightly.  See the discussion of the
FontContentsHeader structure in the "Composition of a Bitmap Font on Disk"
section later in this chapter for more information.  Currently, out of all
the system standard bitmap fonts (those loaded from bitmaps on disk or
ROM, not scaled from a bitmap or outline), only one has a built in aspect
ratio: Topaz-9.

For the Compugraphic outline fonts, the X and Y DPI values are built into
the font outline.  Because the format of the Compugraphic outline fonts is
proprietary, information about their layout is available only from AGFA
Compugraphic.  For most people, the format of the outline fonts is not
important, as the diskfont.library handles converting the fonts to an
Amiga-usable form.

The other place where a font can get an aspect ratio is an application.
When an application opens a font with OpenDiskFont(), it can supply the
TA_DeviceDPI tag that the diskfont.library uses to scale (if necessary)
the font according to the aspect ratio.  To do so, an application has to
pass OpenDiskFont() an extended version of the TextAttr structure called
the TTextAttr:

    struct TTextAttr {
        STRPTR  tta_Name;           /* name of the font           */
        UWORD   tta_YSize;          /* height of the font         */
        UBYTE   tta_Style;          /* intrinsic font style       */
        UBYTE   tta_Flags;          /* font preferences and flags */
        struct TagItem *tta_Tags;   /* extended attributes        */
    };

The TextAttr and the TTextAttr are identical except that the tta_Tags
field points to a tag list where you place your TA_DeviceDPI tag.  To tell
OpenDiskFont() that it has a TTextAttr structure rather than a TextAttr
structure, set the FSF_TAGGED bit in the tta_Style field.

For example, to ask for Topaz-9 scaled to an aspect ratio of 75 to 50 the
code might look something like this:

    #define MYXDPI (75L << 16)
    #define MYYDPI (50L)

    struct TTextAttr mytta = {
        "topaz.font", 9,
        FSF_TAGGED,   0, NULL
    };

    struct TagItem tagitem[2];
    struct TextFont *myfont;
    ULONG dpivalue;

     . . .

    tagitem[0].ti_tag = TA_DeviceDPI;
    tagitem[0].ti_Data = MYXDPI | MYYDPI;
    tagitem[1].ti_tag = TAG_END;
    mytta.tta_tags = tagitem;

     . . .

    if (myfont = OpenDiskFont(&mytta))
    {
        dpi = GetTagData(TA_DeviceDPI,
                         OL,
                         ((struct TextFontExtension *)
                          (myfont->tf_Extension))->tfe_Tags);
        if (dpi) printf("XDPI = %d    YDPI = %d\n",
                        ((dpi & 0xFFFF0000)>>16),
                        (dpi & 0x0000FFFF));
              . . .                             /* Blah Blah print blah */

        CloseFont(myfont);
    }


29 Graphics Library and Text / Some Things to Look Out For

One misleading thing about the TA_DeviceDPI tag is that its name implies
that the diskfont.library is going to scale the font glyphs according to
an actual DPI (dots per inch) value.  As far as scaling is concerned, this
tag serves only as a way to specify the aspect ratio, so the actual values
of the X and Y elements are not important, just the ratio of one to the
other.  A font glyph will look the same if the ratio is 2:1 or 200:100 as
these two ratios are equal.

To makes things a little more complicated, when diskfont.library scales a
bitmap font using an aspect ratio, the X and Y DPI values that the OS
stores in the font's TextFontExtension are identical to the X and Y DPI
values passed in the TA_DeviceDPI tag.  This means the system can
associate an X and Y DPI value to an open font size that is very different
from the font size's actual X and Y DPI.  For this reason, applications
should not use these values as real DPI values.  Instead, only use them to
calculate a ratio.

For the Compugraphic outline fonts, things are a little different.  The X
and Y DPI values are built into the font outline and reflect a true X and
Y DPI.  When the diskfont.library creates a font from an outline, scaling
it according to an application-supplied aspect ratio, diskfont.library
does not change the Y DPI setting.  Instead, it calculates a new X DPI
based on the font's Y DPI value and the aspect ratio passed in the
TA_DeviceDPI tag.  It does this because the Amiga thinks of a font size as
being a height in pixels.  If an application was able to change the true Y
DPI of a font, the diskfont.library would end up creating font sizes that
were much larger or smaller than the YSize the application asked for.  If
an application needs to scale a font according to height as well as width,
the application can adjust the value of the YSize it asks for in the
TTextAttr.

As mentioned earlier, almost all of the system standard bitmap fonts do
not have a built in aspect ratio.  This means that if an application loads
one of these bitmap fonts without supplying an aspect ratio, the system
will not put a TA_DeviceDPI tag in the font's TextFontExtension: the font
will not have an aspect ratio.  If a font size that is already in the
system font list does not have an associated X and Y DPI, the
diskfont.library cannot create a new font of the same size with a
different aspect ratio.

The reason for this is the diskfont.library cannot tell the difference
between two instances of the same font size where one has an aspect ratio
and the other does not.  Because diskfont.library cannot see this
difference, when an application asks, for example, for Topaz-8 with an
aspect ratio of 2:1, OpenDiskFont() first looks through the system list to
see if that font is loaded.  OpenDiskFont() happens to find the ROM font
Topaz-8 in the system font list, which has no X and Y DPI.  Because it
cannot see the difference, diskfont.library thinks it has found what it
was looking for, so it does not create a new Topaz-8 with an aspect ratio
of 2:1, and instead opens the Topaz-8 with no aspect ratio.

This also causes problems for programs that do not ask for a specific
aspect ratio.  When an application asks for a font size without specifying
an aspect ratio, OpenDiskFont() will not consider the aspect ratios of
fonts in the system font list when it is looking for a matching font.  If
a font of the same font and style is already in the system font list, even
though it may have a wildly distorted aspect ratio, OpenDiskFont() will
return the font already in the system rather than creating a new one.

 Font Aspect Ratio Example }


29 Graphics Library and Text / What Fonts Are Available?

The diskfont.library function AvailFonts() fills in a memory area
designated by you with a list of all of the fonts available to the system.
AvailFonts() searches the AmigaDOS directory path currently assigned to
FONTS: and locates all available fonts.  If you haven't issued a DOS
Assign command to change the FONTS: directory path, it defaults to the
sys:fonts directory.

    LONG AvailFonts( struct AvailFontsHeader *mybuffer, LONG bufBytes,
                     LONG flags );

AvailFonts() fills in a memory area, mybuffer, which is bufBytes bytes
long, with an AvailFontsHeader structure:

    struct AvailFontsHeader {
        UWORD   afh_NumEntries;      /* number of AvailFonts elements */
        /* struct AvailFonts afh_AF[], or struct TAvailFonts afh_TAF[]; */
    };

This structure is followed by an array of AvailFonts structures with the
number of entries in the array equal to afh_NumEntries:

    struct AvailFonts {
        UWORD   af_Type;            /* MEMORY, DISK, or SCALED */
        struct TextAttr af_Attr;    /* text attributes for font */
    };

Each AvailFonts structure describes a font available to the OS.  The flags
field lets AvailFonts() know which fonts you want to hear about.  At
present, there are four possible flags:

AFF_MEMORY  Create AvailFonts structures for all TextFont's currently in
            the system list.

AFF_DISK    Create AvailFonts structures for all TextFont's that are
            currently available from disk.

AFF_SCALED  Create AvailFonts structures for TextFont's that do not have
            their FPF_DESIGNED flag set.  If the AFF_SCALED flag is not
            present, AvailFonts() will not create AvailFonts structures
            for fonts that have been scaled, which do not have the
            FPF_DESIGNED flag set.

AFF_TAGGED  These AvailFonts structures are really TAvailFonts structures.
            These structures were created for Release 2 to allow
            AvailFonts() to list tag values:

            struct TAvailFonts {
                UWORD   taf_Type;           /* MEMORY, DISK, or SCALED */
                struct TTextAttr taf_Attr;  /* text attributes for font */
            };

Notice that AFF_MEMORY and AFF_DISK are not mutually exclusive; a font
that is currently in memory may also be available for loading from disk.
In this case, the font will appear twice in the array of AvailFonts (or
TAvailFonts) structures.

If AvailFonts() fails without any major system problems, it will be
because the buffer for the AvailFontsHeader structure was not big enough
to contain all of the AvailFonts or TAvailFonts structures.  In this case,
AvailFonts() returns the number of additional bytes that mybuffer needed
to contain all of the TAvailFonts or AvailFonts structures.  You can then
use that return value to figure out how big the buffer needs to be,
allocate that memory, and try AvailFonts() again:

int afShortage, afSize;
struct AvailFontsHeader *afh;
 . . .

    afSize = AvailFonts(afh, 0L, AFF_MEMORY|AFF_DISK|AFF_SCALED|
                                                     AFF_TAGGED);
    do
    {
        afh = (struct AvailFontsHeader *) AllocMem(afSize, 0);
        if (afh)
        {
            afShortage = AvailFonts(afh, afSize, AFF_MEMORY|AFF_DISK|
                                                 AFF_SCALED|AFF_TAGGED);
            if (afShortage)
            {
                FreeMem(afh, afSize);
                afSize += afShortage;
            }
        }
        else
        {
            fail("AllocMem of AvailFonts buffer afh failed\n");
            break;
        }
    } while (afShortage); /* if (afh) non-zero here, then:             */
                          /* 1. it points to a valid AvailFontsHeader, */
                          /* 2. it must have FreeMem(afh, afSize)      */
                          /* called for it after use. */

The following code, AvailFonts.c, uses AvailFonts() to find out what fonts
are available to the system.  It uses this information to open every
available font (one at a time), print some information about the font
(including the TA_DeviceDPI tag values if they are present), and renders a
sample of the font into a clipping region.

     AvailFonts.c


29 Graphics Library and Text / How an Amiga Font Structured in Memory?

So far, this chapter has concentrated on using library functions to render
text, letting the system worry about the layout of the underlying font
data.  As far as the OS representation of a loaded font is concerned,
outline fonts and normal bitmap fonts are structured identically.  Color
fonts have some extras information associated with them and are discussed
a little later.  Every loaded font, including color fonts, has a TextFont
structure associated with them:

    struct TextFont {
        struct Message tf_Message;  /* reply message for font removal */
        UWORD   tf_YSize;
        UBYTE   tf_Style;
        UBYTE   tf_Flags;
        UWORD   tf_XSize;
        UWORD   tf_Baseline;
        UWORD   tf_BoldSmear; /* smear to affect a bold enhancement */

        UWORD   tf_Accessors;
        UBYTE   tf_LoChar;
        UBYTE   tf_HiChar;
        APTR    tf_CharData;  /* the bit character data */

        UWORD   tf_Modulo;  /* the row modulo for the strike font data  */
        APTR    tf_CharLoc; /* ptr to location data for the strike font */
                            /*   2 words: bit offset then size          */
        APTR    tf_CharSpace;
                           /* ptr to words of proportional spacing data */
        APTR    tf_CharKern; /* ptr to words of kerning data            */
    };

The first field in this structure is a Message structure.  The node in
this Message structure is what the OS uses to link together the fonts in
the system list.  From this node, an application can extract a font's
name.  The other fields in the TextFont structure are as follows:

tf_YSize
    The maximum height of this font in pixels.

tf_Style
    The style bits for this particular font, which are defined in
    <graphics/text.h>.  These include the same style bits that were
    mentioned in the discussion of the TextAttr structure in the
    "Choosing the Font" section of this chapter.  In addition to those
    bits, there is also the FSF_COLORFONT bit, which identifies this as a
    special kind of TextFont structure called a ColorTextFont structure.
    This is discussed later in this chapter.

tf_Flags
    The flags for this font, which were mentioned along with the style
    bits in the section, "Choosing the Font".

tf_XSize
    If this font is monospaced (non-proportional), tf_XSize is the width
    of each character.  The width includes the extra space needed to the
    left and right of the character to keep the characters from running
    together.

tf_Baseline
    The distance in pixels from the top line of the font to the baseline.

tf_BoldSmear
    When algorithmically bolding, the Amiga currently "smears" a glyph by
    rendering it, moving over tf_BoldSmear number of pixels, and
    rerendering the glyph.

tf_Accessors
    The number of currently open instances of this font (like the open
    count for libraries).

tf_LoChar
    This is the first character glyph (the graphical symbol associated
    with this font) defined in this font.  All characters that have ASCII
    values below this value do not have an associated glyph.

tf_HiChar
    This is the last character glyph defined in this font.  All
    characters that have ASCII values above this value do not have an
    associated glyph.  An application can use these values to avoid
    rendering characters which have no associated glyphs.  Any characters
    without an associated glyph will have the default glyph associated to
    them.  Normally, the default glyph is a rectangle.

tf_CharData
    This is the address of the bitmap from which the OS extracts the
    font's glyphs.  The individual glyphs are bit-packed together.  The
    individual bitmaps of the glyphs are placed in ASCII order side by
    side, left to right.  The last glyph is the default glyph.  The
    following is what the bitmap of the suits-8 font example looks like
    (suits8 is the complete, disk-based bitmap font example used later
    in this chapter):

      .@@@...@@@......@........@.......@@@....@@@@@@@@@@@@............
      @@@@@.@@@@@...@@@@@.....@@@.....@@@@@...@@........@@............
      .@@@@@@@@@..@@@@@@@@@..@@@@@..@@..@..@@.@@........@@............
      ..@@@@@@@..@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@........@@............
      ...@@@@@....@@@.@.@@@..@@@@@..@@..@..@@.@@........@@............
      ....@@@.........@.......@@@.......@.....@@........@@............
      .....@........@@@@@......@......@@@@@...@@@@@@@@@@@@............
      ................................................................

    This font is rather sparse, as it only has five glyphs.  Most fonts
    at least have glyphs for each letter of the alphabet.  In this
    example, each glyph represents a symbol for a suit in a standard deck
    of cards (from left to right: hearts, spades, diamonds, and clubs).
    Notice that there is no space between the individual glyphs.  The
    spacing information is kept in separate tables to reduce the amount
    of memory occupied by the font.

tf_Modulo
    This is number of bytes the pointer must move to go from one line of
    a glyph to the next.  This is the pixel width of the entire font
    bitmap divided by eight.  Notice that the bitmap above does not stop
    after it gets to the end of the last glyph.  It is padded with zero
    bits to the nearest WORD boundary.

tf_CharLoc
    This is a pointer to the CharLoc, the character location table. This
    table tells the OS how far into the bitmap to look for a character
    and how many pixels to fetch from each row.  The CharLoc table for
    the suits-8 font looks like this:

        $0000000B,$000B000B,$00160007,$001D000B,$0028000C

    Each of the five long words in this character location table
    corresponds to a glyph in Suits-8.  Each long word is broken up into
    two word values.  The first word is the offset in pixels from the
    left edge of the bitmap to the first column containing the
    corresponding glyph.  The second word is the width in pixels of the
    corresponding glyph image in the bitmap (note, this is not the width
    of the actual glyph as the actual glyph will have some space on
    either side of it).  For example, the diamond character (the third
    character) starts at offset $16 (22) and it is 7 pixels wide.

tf_CharSpace
    This is a pointer to an array of WORDs containing the width of each
    glyph in the font.  Each entry tells the OS how much to increment the
    current horizontal position (usually RastPort.cp_X).  For reverse
    path fonts, these values can be negative.

tf_CharKern
    This is a pointer to an array of "kerning" values.  As it is used
    here, the term "kerning" is unorthodox.  On the Amiga, kerning refers
    to the number pixels to leave blank before rendering a glyph.  The
    normal typographical definition of the word refers to the number of
    pixels to back up before rendering the current glyph and is usually
    associated with a specific pair of glyphs rather than one particular
    glyph.

For each glyph the system renders, it has to do several things:

    1) Get the value from the kerning table that corresponds to this
       glyph and begin the rendering that number of pixels to the right.

    2) Find this glyph's bitmap using the CharLoc table and blit the
       glyph to the rastport.

    3) If this is a proportional font, look in the spacing table and
       figure how many pixels to advance the rastport's horizontal
       position.  For a monospaced font, the horizontal position
       advance comes from the TextFont's tf_XSize field.

Under Release 2, when the system opens a new font, it creates an extension
to the TextFont structure called the TextFontExtension.  This extension is
important because it contains a pointer to the font's tag list, which is
where the system keeps the font's TA_DeviceDPI values.  The TextFont's
tf_Message.mn_ReplyPort field contains a pointer to the TextFontExtension
structure (the <graphics/text.h> include file #defines
tf_Message.mn_ReplyPort as tf_Extension).  The only field of interest in
the TextFontExtension structure is:

    struct TagItem *tfe_Tags;           /* Text Tags for the font */

which points to the font's tag list.  Before accessing the tag list, an
application should make sure that this font has a corresponding
TextFontExtension.  The ExtendFont() function will return a value of TRUE
if this font already has an extension or ExtendFont() was able to create
an extension for this font.


29 Graphics Library and Text / But What About Color Fonts?

When the Amiga loads a color font, it has to account for more information
than will fit into the TextFont structures.  For color fonts, the Amiga
uses a superset of the TextFont structure called the ColorTextFont
structure (defined in <graphics/text.h>):

    struct ColorTextFont {
        struct TextFont ctf_TF;
        UWORD ctf_Flags;      /* extended flags */
        UBYTE ctf_Depth;      /* number of bit planes */
        UBYTE ctf_FgColor;    /* color that is remapped to FgPen */
        UBYTE ctf_Low;        /* lowest color represented here */
        UBYTE ctf_High;       /* highest color represented here */
        UBYTE ctf_PlanePick;      /* PlanePick ala Images */
        UBYTE ctf_PlaneOnOff;     /* PlaneOnOff ala Images */
        struct ColorFontColors *ctf_ColorFontColors; /* colors for font */
        APTR ctf_CharData[8]; /* pointers to bit planes ala tf_CharData */
    };

The ctf_TF field is the TextFont structure described in the previous
section.  There are two minor differences between the data stored in a
color font's TextFont structure and an ordinary TextFont structure.  The
first is that the color font's TextFont.tf_Style field has the
FSF_COLORFONT bit set.  The other difference is that the bitmap that
TextFont.tf_CharData points to can be a multi-plane bitmap.

The ctf_Flags field is a bitfield that supports the following flags:

CT_COLORFONT  The color map for this font contains colors specified by the
              designer.

CT_GREYFONT   The colors for this font describe evenly stepped gray shades
              from low to high.

The ctf_Depth field contains the bitplane depth of this font's bitmap.

The ctf_FgColor contains the color that will be dynamically remapped
during output by changing ctf_FgColor to RastPort.FgPen.  This field
allows a ColorTextFont to contain color outlines, shadows, etc. while also
containing a predominant color that can be changed by the user.  If the
font does not have a predominant color, ctf_FgColor is 0xFF.  For example,
given a color font that has a blue and red outline and a white center, the
person designing the font can set ctf_FgColor equal to white.  Then when
the font is used in a paint package that supports color fonts, the white
will change to the current foreground color.

The fields ctf_Low and ctf_High contain the lowest and highest color
values in the ColorTextFont.  For example, a four bitplane color font can
have sixteen colors, but the font may use only nine of those colors, thus
ctf_Low=0 and ctf_High=8.  The most important use of these colors is for
defining the boundaries of a gray scale font.  If the font uses less than
the total number of colors around but needs white as the lowest and black
as the highest level of gray, the boundaries would have to be defined in
order for the font to be rendered correctly.  Defaults for these values
should be the lowest and the highest values for the given number of
bitplanes.

The ctf_PlanePick and ctf_PlaneOnOff contain information for saving space
in memory for some types of ColorTextFont structures.  The ctf_PlanePick
field contains information about where each plane of data will be rendered
in a given bitmap.  The ctf_PlaneOnOff field contains information about
planes that are not used to render a plane of font data.  If
ctf_PlaneOnOff contains a zero bit for a given plane, that bitplane is
cleared.  If ctf_PlaneOnOff contains a set bit for a given plane, that
bitplane is filled.  For more information on how the ctf_PlaneOnOff and
ctf_PlanePick fields work see the "Specifying the Colors of a Bob" section
of the "Graphics Sprites, Bobs and Animation" chapter of this book.

The ctf_ColorFontColors field contains a pointer to a ColorFontColors
structure:

    struct ColorFontColors {
        UWORD   cfc_Reserved;   /* *must* be zero */
        UWORD   cfc_Count;      /* number of entries in cfc_ColorTable */
        UWORD  *cfc_ColorTable;
                          /* 4 bit per component color map packed xRGB */
    };

Which specifies the colors used by this font.  The ColorFontColors
cfc_Count field contains the number of colors defined in this structure.
Each color is defined as a single, UWORD entry in the cfc_ColorTable.  For
each entry in cfc_ColorTable, the lowest four bits make up the blue
element, the next four bits the green element, the next four bits the red
element, and the upper four bits should be masked out.

The ctf_CharData[] fields is an array of pointers to each of the bitplanes
of the color font data.


29 Graphics Library and Text / Composition of a Bitmap Font on Disk

For each Amiga bitmap font stored on disk (normally in the FONTS: assign
directory), there is a corresponding ".font" file, a directory, and within
that directory, a series of files bearing numeric names.  For example, for
the font Sapphire, within FONTS:, there is a file called sapphire.font, a
directory called Sapphire, and within the directory Sapphire are the files
14 and 19.

For a bitmap font (including color fonts), the ".font" file is a
FontContentsHeader structure:

    struct FontContentsHeader {
        UWORD   fch_FileID;     /* FCH_ID */
        UWORD   fch_NumEntries; /* the number of FontContents elements */
        struct FontContents fch_FC[];
                                /* or struct TFontContents fch_TFC[];  */
    };

    #define MAXFONTPATH 256

Where the fch_FileID field can be be either:

    FCH_ID    0x0f00    This FontContentsHeader uses FontContents
                        structures to describe the available sizes of
                        this font.

    TFCH_ID   0x0f02    This FontContentsHeader uses TFontContents
                        structures to describe the available sizes of
                        this font.

The fch_FileID can also be equal to 0x0f03, but that is only for scalable
outline fonts.

The FontContents structure:

    struct FontContents {
        char    fc_FileName[MAXFONTPATH];
        UWORD   fc_YSize;
        UBYTE   fc_Style;
        UBYTE   fc_Flags;
    };

describes one of the sizes of this font that is available to the system as
a designed font size.  For each FontContents structure, there should be a
corresponding font descriptor file in this font's directory that contains
data for this size font.  The FontContents fields correspond to the
similarly named field in the TextFont structure.

The TFontContents structure is almost the same as the FontContents
structure except that it allows the OS to store tag value pairs in the
extra space not used by the file name.  Currently, this allows the OS to
preserve the X and Y DPI (TA_DeviceDPI) values for a font.

    struct TFontContents {
        char    tfc_FileName[MAXFONTPATH-2];
        UWORD   tfc_TagCount;       /* including the TAG_DONE tag */
        /*
         *  if tfc_TagCount is non-zero, tfc_FileName is overlaid with
         *  Text Tags starting at:  (struct TagItem *)
         *      &tfc_FileName[MAXFONTPATH-(tfc_TagCount*sizeof
         *                                 (struct TagItem))]
         */
        UWORD   tfc_YSize;
        UBYTE   tfc_Style;
        UBYTE   tfc_Flags;
    };

The fch_NumEntries contains the number of font sizes (and the number of
FontContents or TFontContents structures) that this ".font" file
describes.  The fch_FC[] is the array of FontContents or TFontContents
structures that describe this font.

For each font size described in a FontContents (or TFontContents)
structure, there is a corresponding file in that font's directory whose
name is its size.  For example, for the font size Sapphire-19, there is a
file in the Sapphire directory called 19.  That file is basically a
DiskFontHeader disguised as a loadable DOS hunk and is known as a font
descriptor file.  This allows the diskfont.library to use the dos.library
to load the module just like it was a hunk of relocatable 680x0
instructions.  It even contains two instructions before the real
DiskFontHeader structure that will cause the 680x0 to stop running the
DiskFontHeader if it does inadvertently get executed.

    #define  MAXFONTNAME    32      /* font name including ".font" */

    struct DiskFontHeader {
        /* the following 8 bytes are not actually considered a part of */
        /* the DiskFontHeader, but immediately precede it. The         */
        /* NextSegment is supplied by the linker/loader, and the       */
        /* ReturnCode is the code at the beginning of the font in case */
        /* someone runs it...                                          */
        /*   ULONG dfh_NextSegment;               actually a BPTR      */
        /*   ULONG dfh_ReturnCode;                MOVEQ #0,D0 : RTS    */
        /* here then is the official start of the DiskFontHeader...    */
        struct Node dfh_DF;            /* node to link disk fonts */
        UWORD dfh_FileID;            /* DFH_ID */
        UWORD dfh_Revision;          /* the font revision */
        LONG  dfh_Segment;           /* the segment address when loaded */
        char  dfh_Name[MAXFONTNAME]; /* the font name (null terminated) */
        struct TextFont dfh_TF;        /* loaded TextFont structure */
    };

    /* unfortunately, this needs to be explicitly typed */
    /* used only if dfh_TF.tf_Style FSB_TAGGED bit is set */
    #define dfh_TagList     dfh_Segment     /* destroyed during loading */

The dfh_DF field is an Exec Node structure that the diskfont library uses
to link together the fonts it has loaded.  The dfh_FileID field contains
the file type, which currently is DFH_ID (defined in
<libraries/diskfont.h>).  The dfh_Revision field contains a revision
number for this font.  The dfh_Segment field will contain the segment
address when the font is loaded.  The dfh_FontName field will contain the
font's name after the font descriptor is LoadSeg()'ed.  The last field,
dfh_TextFont is a TextFont structure (or ColorTextFont structure) as
described in the previous section.  The following is a complete example of
a proportional, bitmap font.

     suites8.asm


29 Graphics Library and Text / Function Reference

The following are brief descriptions of the Graphics and Diskfont library
functions that deal with text.  See the Amiga ROM Kernel Reference Manual:
Includes and Autodocs for details on each function call.

               Table 29-1: Graphics Library Text Functions
  _______________________________________________________________________
 |                                                                       |
 |      Function                  Description                            |
 |=======================================================================|
 |          Text()  Render a text string to a RastPort.                  |
 |       SetFont()  Set a RastPort's font.                               |
 |       AskFont()  Get the TextAttr for a RastPort's font.              |
 |      OpenFont()  Open a font currently in the system font list.       |
 |     CloseFont()  Close a font.                                        |
 |       AddFont()  Add a font to the system list.                       |
 |       RemFont()  Remove a font from the system list.                  |
 |     StripFont()  Remove the tf_Extension from a font (V36).           |
 |  WeighTAMatch()  Get a measure of how well two fonts match (V36).     |
 |-----------------------------------------------------------------------|
 |   ClearScreen()  Clear RastPort from the current position to the end  |
 |                  of the RastPort.                                     |
 |      ClearEOL()  Clear RastPort from the current position to the end  |
 |                  of the line.                                         |
 |  AskSoftStyle()  Get the soft style bits of a RastPort's font.        |
 |  SetSoftStyle()  Set the soft style bits of a RastPort's font.        |
 |    TextLength()  Determine the horizontal raster length of a text     |
 |                  string using the current RastPort settings.          |
 |    TextExtent()  Determine the raster extent (along the X and Y axes) |
 |                  of a text string using the current RastPort settings |
 |                  (V36).                                               |
 |    FontExtent()  Fill in a TextExtent structure with the bounding box |
 |                  for the characters in the specified font (V36).      |
 |       TextFit()  Count the number of characters in a given string     |
 |                  that will fit into a given bounds, using the current |
 |                  RastPort settings (V36).                             |
 |_______________________________________________________________________|

               Table 29-2: Diskfont Library Text Functions
  _______________________________________________________________________
 |                                                                       |
 |           Function             Description                            |
 |=======================================================================|
 |           AvailFonts()  Inquire which fonts are available from disk   |
 |                         and/or memory.                                |
 |      NewFontContents()  Create a FontContents image for a font.       |
 |  DisposeFontContents()  Free the result from NewFontContents().       |
 |    NewScaledDiskFont()  Create a DiskFont scaled from another font    |
 |                         (V36).                                        |
 |         OpenDiskFont()  Open a font, loading it from disk if          |
 |                         necessary.                                    |
 |_______________________________________________________________________|


Amiga® RKM Libraries: 30 Layers Library

This chapter describes the layers library which provides routines that are
used to manage overlapping rectangular drawing areas that share a common
display.  Intuition uses the layers library to manage its system of
windows.

The chapter also describes the use of regions, special structures used to
mask off areas where drawing can take place.  Regions are installed
through the layers library function InstallClipRegion() but the routines
for the creation, disposal and manipulation of regions are part of the
graphics library.

 Layers    Regions    Function Reference


30 Layers Library / Layers

The concept of a layer is closely tied to Intuition windows.  A layer is a
rectangular drawing area.  A layer can overlap other layers and has a
display priority that determines whether it will appear in front or behind
other layers.  Every Intuition window has an associated Layer structure.
Layers allow Intuition and application programs to :

    * Share a display's BitMap among various tasks in an orderly way
      by creating layers, separate drawing rectangles, within the
      BitMap.

    * Move, size or depth-arrange a layer while automatically keeping
      track of which portions of other layers are hidden or revealed
      by the operation.

    * Manage the remapping of coordinates, so the application need not
      track the layer's offset into the BitMap.

    * Maintain each layer as a separate entity, which may optionally
      have its own BitMap.

    * Automatically update same newly visible portions.

The layers library takes care of housekeeping: the low level, repetitive
tasks which are required to keep track of where to place bits.  The layers
library also provides a locking mechanism which coordinates display
updating when multiple tasks are drawing graphics to layers.  The
windowing environment provided by the Intuition library is largely based
on layers.

    WARNING:
    --------
    Layers may not be created or used directly with Intuition screens.
    Intuition windows are the only supported method of adding layers to
    Intuition screens.  Only the layer locking and unlocking functions
    are safe to use with Intuition.  An application must create and
    manage its own View if it will be creating layers directly on the
    display.

 The Layer Structure           Working With Existing Layers
 The Layer's RastPort          Creating and Using New Layers
 Types of Layers               Layers Example
 Opening the Layers Library


30 / Layers / The Layer Structure

The internal representation of layers is essentially a set of clipping
rectangles.  Each layer is represented by an instance of the Layer
structure.  All the layers in a display are linked together through the
Layer_Info structure.  Any display shared by multiple layers (such as an
Intuition screen) requires one Layer_Info data structure to handle
interactions between the various layers. Here is a partial listing of the
Layer structure from <graphics/clip.h>.  (For a complete listing refer to
the Amiga ROM Kernel Reference Manual: Includes and Autodocs.)

    struct Layer
    {
        struct  Layer *front,*back;
        struct  ClipRect   *ClipRect; /* read ROMs to find 1st cliprect */
        struct  RastPort   *rp;
        struct  Rectangle  bounds;
          ...

        UWORD   Flags;                /* obscured ?, Virtual BitMap? */
        struct  BitMap  *SuperBitMap;
          ...

        struct  Region  *DamageList;  /* list of rectangles to refresh */
                                      /* through */
    };

    The Layer Structure is Read-Only.
    ---------------------------------
    Applications should never directly modify any of the elements of the
    Layer structure. In addition, applications should only read the
    front, back, rp, bounds, Flags, SuperBitMap and DamageList elements
    of the Layer structure. (Some of these elements are subject to
    dynamic change by the system so proper layer locking procedures must
    be followed when relying on what the application has read.)


30 / Layers / The Layer's RastPort

When a layer is created, a RastPort is automatically to go along with it.
The pointer to the RastPort is contained in the layer data structure.
Using this RastPort, the application may draw anywhere into the layer's
bounds rectangle.  If the application tries to draw outside of this
rectangle, the graphics routines will clip the graphics.

Here is sample code showing how to access the layer's RastPort:

    struct RastPort *myRPort;
        /* allocate a RastPort pointer for each layer */

    myRPort = layer->rp;

    /* The layer's RastPort may be used with any of the graphics library
    ** calls that require this structure.  For instance, to fill layer
    ** with color:
    */
    SetRast(layer->rp, color);

    /* set up for writing text into layer */
    SetDrMd(layer->rp,JAM1);
    SetAPen(layer->rp,0);
    Move(layer->rp, 5, 7);

    /* write into layer */
    Text(layer->rp, string, strlen(string));


30 / Layers / Types of Layers

The layers library supports three types of layers: simple refresh, smart
refresh and super bitmap.  The type of the layer, specified by the Flags
field in the Layers structure, determines what facilities the layer
provides.

    Use Only One Layer Type Flag
    ----------------------------
    The three layer-type Flags are mutually exclusive.  That is, only one
    layer-type flag (LAYERSIMPLE, LAYERSMART and LAYERSUPER) should be
    specified.

 Simple Refresh Layer    Super Bitmap Layer
 Smart Refresh Layer     Backdrop Layer


30 / / Types of Layers / Simple Refresh Layer

When an application draws into the layer, any portion of the layer that is
visible (not obscured) will be rendered into the common BitMap of the
viewing area.  All graphics rendering routines are "clipped", so that only
exposed sections of the layer are drawn into.  No back-up of obscured
areas is provided.

If another layer operation is performed that causes an obscured part of a
simple refresh layer to be exposed, the application must determine if the
section need be refreshed, re-drawing the newly exposed part of the layer
as required.

The basic advantage of simple refresh is that it does not require back-up
area to save drawing sections that cannot be seen, saving memory. However,
the application needs to monitor the layer to see if it needs refreshing.
This is typically performed with statements like:

    if (layer->Flags & LAYERREFRESH)
        refresh(layer);


30 / / Types of Layers / Smart Refresh Layer

Under smart refresh, the system provides dynamic backup of obscured
sections of the layer. The graphics routines will automatically draw into
these backup areas when they encounter an obscured part of the layer. The
backup memory will be used to automatically update the display when
obscured sections later become exposed.

With smart refresh layers, the system handles all of the refresh
requirements of the layer, except when the layer is made larger. When
parts of the layer are exposed by a sizing operation, the application must
refresh the newly exposed areas.

The advantage of smart refresh is the speed of updating exposed regions of
the layer and the ability of the system to manage part of the updating
process for the application.. Its main disadvantage is the additional
memory required to handle this automatic refresh.


30 / / Types of Layers / Super Bitmap Layer

A super bitmap layer is similar to a smart refresh layer.  It too has a
back-up area for rendering graphics for currently obscured parts of the
display.  Whenever an obscured area is made visible, the corresponding
part of the backup area is copied to the display automatically.

However, it differs from smart refresh in that:

  * The back-up BitMap is user-supplied, rather than being allocated
    dynamically by the system.

  * The back-up BitMap may be as large or larger than the the current
    size of the layer. It may also be larger than the maximum size of the
    layer.

To see a larger portion of a super bitmap on-display, use SizeLayer().  To
see a different portion of the super bitmap in the layer, use
ScrollLayer().

When the graphics routines perform drawing commands, part of the drawing
appears in the common BitMap (the on-display portion). Any drawing outside
the displayed portion itself is rendered into the super bitmap. When the
layer is scrolled or sized, the layer contents are copied into the super
bitmap, the scroll or size positioning is modified, and the appropriate
portions are then copied back into the layer. (Refer to the graphics
library functions SyncSBitMap() and CopySBitMap().


30 / / Types of Layers / Backdrop Layer

A layer of any type may be designated a backdrop layer which will always
appear behind all other layers. They may not be moved, sized, or
depth-arranged. Non-backdrop layers will always remain in front of
backdrop layers regardless of how the non-backdrop layer is moved, sized
or depth-arranged.


30 / Layers / Opening the Layers Library

Like all libraries, the layers library must be opened before it may be
used.  Check the Layers Autodocs to determine what version of the library
is required for any particular Layers function.

    struct Library *LayersBase;

    if (NULL != (LayersBase = OpenLibrary("layers.library",33L)))
        {
        /* use Layers library */

        CloseLibrary((struct Library *)LayersBase);
        }


30 / Layers / Working With Existing Layers

A common operation performed by applications is to render text or graphics
into an existing layer such as an Intuition window.  To prevent Intuition
from changing the layer (for instance when the user resizes or moves the
window) during a series of graphic operations, the layers library provides
locking functions for obtaining exclusive access to a layer.

These locking functions are also useful for applications that create their
own layers if the application has more than one task operating on the
layers asynchronously.  These calls coordinate multiple access to layers.

  Table 30-1: Functions for Intertask Control of Layers (Layers Library)
   ____________________________________________________________________
  |                                                                    |
  |        LockLayer()  Lock out rendering in a single layer.          |
  |      UnlockLayer()  Release LockLayer() lock.                      |
  |       LockLayers()  Lock out rendering in all layers of a display. |
  |     UnlockLayers()  Release LockLayers() lock.                     |
  |    LockLayerInfo()  Gain exclusive access to the display's layers. |
  |  UnlockLayerInfo()  Release LockLayerInfo() lock.                  |
  |____________________________________________________________________|

The following routines from the graphics library also allow multitasking
access to layer structures:

 Table 30-2: Functions for Intertask Control of Layers (Graphics Library)
   ____________________________________________________________________
  |                                                                    |
  |         LockLayerRom()  Same as LockLayer(), from layers library.  |
  |       UnlockLayerRom()  Release LockLayerRom() lock.               |
  |  AttemptLockLayerRom()  Lock layer only if it is immediately       |
  |                         available.                                 |
  |____________________________________________________________________|

These functions are similar to the layers LockLayer() and UnlockLayer()
functions, but do not require the layers library to be open.  See the
Amiga ROM Kernel Reference Manual: Includes and Autodocs for details.

 Intertask Operations    Determining Layer Position


30 / / Working With Existing Layers / Intertask Operations

If multiple tasks are manipulating layers on the same display they will be
sharing a Layer_Info structure and their use of it and its related data
structures need to be coordinated.  To ensure that a structure remains
cohesive, it should be operated on by only one task at a time.  The
Layer_Info encompasses all the layers existing on a single display.

LockLayerInfo() must be called whenever the visible portions of layers may
be affected, or when the Layer_Info structure is changed.

    void LockLayerInfo( struct Layer_Info *li );

The lock should be obtained whenever a layer is created, deleted sized or
moved, as the list of layers that is being managed by the Layer_Info data
structure must be updated.

It is not necessary to lock the Layer_Info data structure while rendering,
or when calling routines like ScrollLayer(), because layer sizes and
on-display positions are not being affected.

Use UnlockLayerInfo() when you have finished the layer operation:

    void UnlockLayerInfo( struct Layer_Info *li );

If you don't unlock the Layer_Info then any other task calling
LockLayerInfo() on the same Layer_Info structure will be blocked creating
a potential deadlock situation.

In addition to locking the Layer_Info structure, the layer itself should
be locked if it is shared between tasks so that only one task at a time
renders graphics to it.  LockLayer() is used to get exclusive graphics
output to a layer.

    void LockLayer( long dummy, struct Layer *layer );

If a graphics function is in process, the lock will return when the
function is completed.  Other tasks are blocked only if they attempt to
draw graphics into this layer, or try to obtain a lock on this layer. The
MoveLayer(), SizeLayer() and ScrollLayer() functions automatically lock
and unlock the layer they operate on.

UnlockLayer() should be used after the graphics operation to make the
layer available to other tasks again.

    void UnlockLayer( struct Layer *layer );

If more than one layer must be locked, then the LockLayer() calls should
be surrounded by LockLayerInfo() and UnlockLayerInfo() calls, to prevent
deadlock situations.

The layers library provides two additional functions, LockLayers() and
UnlockLayers(), for locking multiple layers.

    void LockLayers( struct Layer_Info *li );
    void UnlockLayers( struct Layer_Info *li );

LockLayers() is used to lock all layers in a single command.
UnlockLayers() releases the layers lock.  The system calls these routines
during the BehindLayer(), UpfrontLayer() and MoveLayerInFrontOf()
operations (described below).


30 / / Working With Existing Layers / Determining Layer Position

If the viewing area has been separated into several layers, the
application may need to find out which layer is topmost at a particular
x,y coordinate.  Use the WhichLayer() function for this:

    struct Layer *WhichLayer( struct Layer_Info *li, long x, long y );

To be sure that no task adds, deletes, or changes the sequence of layers
before this information is used, call LockLayerInfo() before calling
WhichLayer(), and call UnlockLayerInfo() when the operation is complete.
In this way, the program may ensure that it is acting on valid
information.  Always check for a NULL return value (coordinate not in a
layer) from WhichLayer().


30 / Layers / Creating and Using New Layers

The functions described in this section are generally not safe to use with
Intuition.  To create new layers for Intuition you use Intuition window
calls (see the "Intuition Windows" chapter earlier in this book).

Only applications that create and mange their own View will be able to
call the layer creation and updating functions discussed here.

         Table 30-3: Functions for Creating and Updating Layers
   ___________________________________________________________________
  |                                                                   |
  |              NewLayerInfo()  Allocating a Layer_Info structure.   |
  |          DisposeLayerInfo()  Deallocating a Layer_Info structure. |
  |-------------------------------------------------------------------|
  |        CreateUpfrontLayer()  Make a new layer in front of others. |
  |         CreateBehindLayer()  Make a new layer behind others.      |
  |               DeleteLayer()  Remove and delete an existing layer. |
  |-------------------------------------------------------------------|
  |                 MoveLayer()  Change the position (not depth) of a |
  |                              layer.                               |
  |                 SizeLayer()  Change the size of a layer.          |
  |               ScrollLayer()  Change the internal coordinates of a |
  |                              layer.                               |
  |-------------------------------------------------------------------|
  |               BehindLayer()  Depth arrange a layer behind others. |
  |              UpfrontLayer()  Depth arrange a layer in front of    |
  |                              others.                              |
  |        MoveLayerInFrontOf()  Depth arrange a layer to a specific  |
  |                              position.                            |
  |-------------------------------------------------------------------|
  |  SwapBitsRastPortClipRect()  Fast, non-layered and non-damaging   |
  |                              display operation.                   |
  |-------------------------------------------------------------------|
  |               BeginUpdate()  Synchronize optimized refreshing for |
  |                              layer.                               |
  |                 EndUpdate()  End optimized layer refresh.         |
  |___________________________________________________________________|

 Creating a Viewing Workspace
 Creating the Layers
 Allocating and Deallocating Layer_Info
 Allocating and Deallocating Layers
 Moving and Sizing Layers
 Changing a Viewpoint
 Reordering Layers
 Sub-Layer Rectangle Operations


30 / / Creating and Using New Layers / Creating a Viewing Workspace

A viewing workspace may be created by using the primitives InitVPort(),
InitView(), MakeVPort(), MrgCop(), and LoadView(). Please reference the
"Graphics Primitives" chapter for details on creating a low-level graphics
display.  Do not create Layers directly on Intuition screens.  Windows are
the only supported method of creating a layer on a screen.


30 / / Creating and Using New Layers / Creating the Layers

The application must first allocate and initialize a Layer_Info data
structure which the system uses to keep track of layers that are created,
use statements like:

    struct Layer_Info *theLayerInfo;

    if (NULL != (theLayerInfo = NewLayerInfo()))
        {
        /* use Layer_Info */

        DisposeLayerInfo(theLayerInfo);
        }

Layers may be created in the common bit map by calling
CreateUpfrontLayer() or CreateBehindLayer(), with a sequence such as the
following:

    struct Layer      *layer;
    struct Layer_Info *theLayerInfo;
    struct BitMap     *theBitMap;

    /* requests construction of a smart refresh layer. */
    if (NULL == (layer = CreateUpfrontLayer(theLayerInfo, theBitMap,
              20, 20, 100, 80, LAYERSMART, NULL)))
        error("CreateUpfrontLayer() failed.");
    else
        {
        ; /* layer successfully created here. */
        }


30 / / / Allocating and Deallocating Layer_Info

Use NewLayerInfo() to allocate and initialize a Layer_Info structure and
associated sub-structures.

    struct Layer_Info *NewLayerInfo( void );

You must call this function before attempting to use any of the other
layers functions described below.  When you have finished with a
Layer_Info structure, use DisposeLayerInfo() to deallocate it.

    void DisposeLayerInfo( struct Layer_Info *li );

This function deallocates a Layer_Info and associated structures
previously allocated with NewLayerInfo().


30 / / Creating and Using Layers / Allocating and Deallocating Layers

Layers are created using the routines CreateUpfrontLayer()
and CreateBehindLayer().  CreateUpfrontLayer()
creates a layer that will appear in front of any existing layers.

    struct Layer *CreateUpfrontLayer( struct Layer_Info *li,
                                      struct BitMap *bm,
                                      long x0, long y0, long x1, long y1,
                                      long flags, struct BitMap *bm2 );

CreateBehindLayer() creates a layer that appears behind existing layers,
but in front of backdrop layers.

    struct Layer *CreateBehindLayer( struct Layer_Info *li,
                                     struct BitMap *bm,
                                     long x0, long y0, long x1, long y1,
                                     long flags, struct BitMap *bm2 );

Both of these routines return a pointer to a Layer data structure (as
defined in the include file <graphics/layers.h>), or NULL if the operation
was unsuccessful.

    A New Layer Also Gets a RastPort.
    ---------------------------------
    When a layer is created, the routine automatically creates a
    RastPort to go along with it.  If the layer's RastPort is passed
    to the drawing routines, drawing will be restricted to the layer.
    See "The Layer's RastPort" section above.

Use the DeleteLayer() call to remove a layer:

    LONG DeleteLayer( long dummy, struct Layer *layer );

DeleteLayer() removes a layer from the layer list and frees the memory
allocated by the layer creation calls listed above.


30 / / Creating and Using New Layers / Moving and Sizing Layers

The layers library includes three functions for moving and sizing layers:

    LONG MoveLayer( long dummy, struct Layer *layer, long dx, long dy );
    LONG SizeLayer( long dummy, struct Layer *layer, long dx, long dy );
    LONG MoveSizeLayer( struct Layer *layer, long dx, long dy, long dw,
                        long dh);

MoveLayer() moves a layer to a new position relative to its current
position.  SizeLayer() changes the size of a layer by modifying the
coordinates of the lower right corner of the layer.  MoveSizeLayer()
changes both the size and position of a layer in a single call.


30 / / Creating and Using New Layers / Changing a Viewpoint

The ScrollLayer() function changes the portion of a super bitmap that is
shown by a layer:

    void ScrollLayer( long dummy, struct Layer *layer, long dx, long dy );

This function is most useful with super bitmap layers but can also
simulate the effect on other layer types by adding the scroll offset to
all future rendering.


30 / / Creating and Using New Layers / Reordering Layers

The layers library provides three function calls for reordering layers:

    LONG BehindLayer ( long dummy, struct Layer *layer );
    LONG UpfrontLayer( long dummy, struct Layer *layer );
    LONG MoveLayerInFrontOf( struct Layer *layer_to_move,
                             struct Layer *other_layer );

BehindLayer() moves a layer behind all other layers.  This function
considers any backdrop layers, moving a current layer behind all others
except backdrop layers.  UpfrontLayer() moves a layer in front of all
other layers.  MoveLayerInFrontOf() is used to place a layer at a specific
depth, just in front of a given layer.

As areas of simple refresh layers become exposed, due to layer movement or
sizing for example, the newly exposed areas have not been drawn into, and
need refreshing.  The system keeps track of these areas by using a
DamageList.  To update only those areas that need it, the BeginUpdate()
EndUpdate() functions are called.

    LONG BeginUpdate( struct Layer *l );
    void EndUpdate  ( struct Layer *layer, unsigned long flag );

BeginUpdate() saves the pointer to the current clipping rectangles and
installs a pointer to a set of ClipRects generated from the DamageList in
the layer structure.  To repair the layer, use the graphics rendering
routines as if to redraw the entire layer, and the routines will
automatically use the new clipping rectangle list.  So, only the damaged
areas are actually rendered into, saving time.

    Never Modify the DamageList.
    ----------------------------
    The system generates and maintains the DamageList region.  All
    application clipping should be done through the InstallClipRegion()
    function.

To complete the update process call EndUpdate() which will restore the
original ClipRect list.


30 / / Creating and Using New Layers / Sub-Layer Rectangle Operations

The SwapBitsRastPortClipRect() routine is for applications that do not
want to worry about clipping rectangles.

    void SwapBitsRastPortClipRect( struct RastPort *rp,
                                   struct ClipRect *cr );

For instance, you may use The SwapBitsRastPortClipRect() to produce a menu
without using Intuition.  There are two ways to produce such a menu:

 1. Create an up-front layer with CreateUpfrontLayer(), then render the
    menu in it.  This could use lots of memory and require a lot of (very
    temporary) "slice-and-dice" operations to create all of the clipping
    rectangles for the existing windows and so on.

 2. Use SwapBitsRastPortClipRect(), directly on the display drawing area:

      * Render the menu in a back-up area off the display, then lock all
        of the on-display layers so that no task may use graphics
        routines to draw over the menu area on the display.

      * Next, swap the on-display bits with the off-display bits, making
        the menu appear.

      * When finished with the menu, swap again and unlock the layers.

The second method is faster and leaves the clipping rectangles and most of
the rest of the window data structures untouched.

    Warning:
    --------
    All of the layers must be locked while the menu is visible if you
    use the second method above.  Any task that is using any of the
    layers for graphics output will be halted while the menu operations
    are taking place.  If, on the other hand, the menu is rendered as a
    layer, no task need be halted while the menu is up because the lower
    layers need not be locked.


30 Layers Library / Regions

Regions allow the application to install clipping rectangles into layers.
A clipping rectangle is a rectangular area into which the graphics
routines will draw.  All drawing that would fall outside of that
rectangular area is clipped (not rendered).

User clipping regions are linked lists of clipping rectangles created by
an application program through the graphics library routines described
below.  By combining together various clipping rectangles, any arbitrary
clipping shape can be created.  Once the region is set up, you use the
layers library call InstallClipRegion() to make the clipping region active
in a layer.

Regions are safe to use with layers created by Intuition (i.e., windows).
The following table describes the routines available for the creation,
manipulation and use of regions.

                Table 30-4: Functions Used with Regions
  ____________________________________________________________________
 |                                                                    |
 |          Routine      Library         Description                  |
 |====================================================================|
 |  InstallClipRegion()  Layers    Add a clipping region to a layer.  |
 |--------------------------------------------------------------------|
 |          NewRegion()  Graphics  Create a new, empty region.        |
 |      DisposeRegion()  Graphics  Dispose of an existing region and  |
 |                                 its rectangles.                    |
 |--------------------------------------------------------------------|
 |      AndRectRegion()  Graphics  And a rectangle into a region.     |
 |       OrRectRegion()  Graphics  Or a rectangle into a region.      |
 |      XorRectRegion()  Graphics  Exclusive-or a rectangle into a    |
 |                                 region.                            |
 |    ClearRectRegion()  Graphics  Clear a rectangular portion of a   |
 |                                 region.                            |
 |    AndRegionRegion()  Graphics  And two regions together.          |
 |     OrRegionRegion()  Graphics  Or two regions together.           |
 |    XorRegionRegion()  Graphics  Exclusive-or two regions together. |
 |--------------------------------------------------------------------|
 |        ClearRegion()  Graphics  Clear a region.                    |
 |____________________________________________________________________|

With these functions, the application can selectively update a
custom-shaped part of a layer without disturbing any of the other layers
that might be present.

    Never Modify the DamageList of a Layer Directly.
    ------------------------------------------------
    Use the routine InstallClipRegion() to add clipping to the layer.
    The regions installed by InstallClipRegion() are independent of
    the layer's DamageList and use of user clipping regions will not
    interfere with optimized window refreshing.

    Do Not Modify A Region After It Has Been Added.
    -----------------------------------------------
    After a region has been added with InstallClipRegion(), the
    program may not modify it until the region has been removed with
    another call to InstallClipRegion().

 Creating and Deleting Regions    Changing a Region
 Installing Regions               Regions Example


30 / Regions / Creating and Deleting Regions

You allocate a Region data structure with the NewRegion() call.

    struct Region *NewRegion( void );

The NewRegion() function allocates and initializes a Region structure that
has no drawable areas defined in it.  If the application draws through a
new region, nothing will be drawn as the region is empty.  The application
must add rectangles to the region before any graphics will appear.

Use DisposeRegion() to free the Region structure when you are done with it.

    void DisposeRegion( struct Region *region );

DisposeRegion() returns all memory associated with a region to the system
and deallocates all rectangles that have been linked to it.

    Don't Forget to Free Your Rectangles.
    -------------------------------------
    All of the functions that add rectangles to the region make copies
    of the rectangles.  If the program allocates a rectangle, then adds
    it to a region, it still must deallocate the rectangle.  The call to
    DisposeRegion() will not deallocate rectangles explicitly
    allocated by the application.


30 / Regions / Installing Regions

Use the function InstallClipRegion() to install the region.

    struct Region *InstallClipRegion( struct Layer *layer,
                                      struct Region *region );

This installs a transparent clipping region to a layer.  All subsequent
graphics calls will be clipped to this region.  The region must be removed
with a second call to InstallClipRegion() before removing the layer.

    /*
    ** Sample installation and removal of a clipping region
    */
    register struct Region     *new_region ;
    register struct Region     *old_region ;

    /* If the application owns the layer and has not installed a region,
    ** old_region will return NULL here.
    */
    old_region = InstallClipRegion(win->WLayer, new_region);

    /* draw into the layer or window */

    if (NULL != (old_region = InstallClipRegion(win->WLayer, old_region)))
        {
        /* throw the used region away.  This region could be saved and
        ** used again later, if desired by the application.
        */
        DisposeRegion(new_region) ;
        }

    A Warning About InstallClipRegion().
    ------------------------------------
    The program must not call InstallClipRegion() inside of a
    Begin/EndRefresh() or Begin/EndUpdate() pair.  The following code
    segment shows how to modify the user clipping region when using these
    calls.  See the Autodoc for BeginRefresh() for more details.

    register struct Region     *new_region ;
    register struct Region     *old_region ;

    /* you have to have already setup the new_region and old_region */

    BeginRefresh(window);
    /* draw through the damage list */
    /* into the layer or window */
    EndRefresh(window, FALSE);              /* keep the damage list */

    old_region = InstallClipRegion(win->WLayer, new_region);

    BeginRefresh(window);
    /* draw through the damage list and the new_region */
    /* into the layer or window */
    EndRefresh(window, FALSE);              /* keep the damage list */

    /* put back the old region */
    new_region = InstallClipRegion(win->WLayer, old_region);

    BeginRefresh(window);
    EndRefresh(window, TRUE);               /* remove the damage list */

    old_region = InstallClipRegion(win->WLayer, new_region);

    BeginRefresh(window);
    /* draw through the new_region only into the layer or window */
    EndRefresh(window, FALSE);

    /* finally get rid of the new region, old_region still installed */
    if (NULL != (new_region = InstallClipRegion(win->WLayer, old_region)))
        DisposeRegion(new_region) ;


30 / Regions / Changing a Region

Regions may be modified by performing logical operations with rectangles,
or with other regions.

    Reuse Your Rectangles.
    ----------------------
    In all of the rectangle and region routines the clipping rectangle
    is copied into the region.  This means that a single clipping
    rectangle (Rectangle structure) may be used many times by simply
    changing the x and y values.  The application need not create a
    new instance of the Rectangle structure for each rectangle added
    to a region.

For instance:

    extern struct Region *RowRegion;  /* created elsewhere */

    WORD ktr;
    struct Rectangle rect;

    for (ktr = 1; ktr < 6; ktr++)
        {
        rect.MinX = 50;
        rect.MaxX = 315;
        rect.MinY = (ktr * 10) - 5;
        rect.MaxY = (ktr * 10);

        if (!OrRectRegion(RowRegion, &rect))
            clean_exit(RETURN_WARN);
        }

 Rectangles and Regions    Regions and Regions


30 / / Changing a Region / Rectangles and Regions

There are four functions for changing a region through logical operations
with a rectangle.

    BOOL OrRectRegion   ( struct Region *region,
                          struct Rectangle *rectangle );
    void AndRectRegion  ( struct Region *region,
                          struct Rectangle *rectangle );
    BOOL XorRectRegion  ( struct Region *region,
                          struct Rectangle *rectangle );
    BOOL ClearRectRegion( struct Region *region,
                          struct Rectangle *rectangle );

OrRectRegion() modifies a region structure by or'ing a clipping rectangle
into the region.  When the application draws through this region (assuming
that the region was originally empty), only the pixels within the clipping
rectangle will be affected. If the region already has drawable areas, they
will still exist, this rectangle is added to the drawable area.

AndRectRegion() modifies the region structure by and'ing a clipping
rectangle into the region.  Only those pixels that were already drawable
and within the rectangle will remain drawable, any that are outside of it
will be clipped in future.

XorRectRegion() applies the rectangle to the region in an exclusive-or
mode.  Within the given rectangle, any areas that were drawable become
clipped, any areas that were clipped become drawable.  Areas outside of
the rectangle are not affected.

ClearRectRegion() clears the rectangle from the region.  Within the given
rectangle, any areas that were drawable become clipped.  Areas outside of
the rectangle are not affected.


30 / / Changing a Region / Regions and Regions

As with rectangles and regions, there are four layers library functions
for combining regions with regions:

    BOOL AndRegionRegion( struct Region *srcRegion,
                          struct Region *destRegion );
    BOOL OrRegionRegion ( struct Region *srcRegion,
                          struct Region *destRegion );
    BOOL XorRegionRegion( struct Region *srcRegion,
                          struct Region *destRegion );
    void ClearRegion    ( struct Region *region );

AndRegionRegion() performs a logical and operation on the two regions,
leaving the result in the second region.  The operation leaves drawable
areas wherever the regions drawable areas overlap.  That is, where there
are drawable areas in both region 1 and region 2, there will be drawable
areas left in the result region.

OrRegionRegion() performs a logical or operation on the two regions,
leaving the result in the second region. The operation leaves drawable
areas wherever there are drawable areas in either region. That is, where
there are drawable areas in either region 1 or region 2, there will be
drawable areas left in the result region.

XorRegionRegion() performs a logical exclusive-or operation on the two
regions, leaving the result in the second region.  The operation leaves
drawable areas wherever there are drawable areas in either region but not
both.  That is, where there are drawable areas in either region 1 or
region 2, there will be drawable areas left in the result region.  But
where there are drawable areas in both region 1 and region 2, there will
not be drawable areas left in the result region.

ClearRegion() puts the region back to the same state it was in when the
region was created with NewRegion(), that is, no areas are drawable.


30 Layers Library / Function Reference

The following are brief descriptions of the layers library functions and
related routines from the graphics library.  See the Amiga ROM Kernel
Reference Manual: Includes and Autodocs for details on each function call.

                  Table 30-5: Layers Library Functions
  ______________________________________________________________________
 |                                                                      |
 |              Function                   Description                  |
 |======================================================================|
 |              NewLayerInfo()  Allocating a Layer_Info structure.      |
 |          DisposeLayerInfo()  Deallocating a Layer_Info structure.    |
 |----------------------------------------------------------------------|
 |        CreateUpfrontLayer()  Make a new layer in front of others.    |
 |         CreateBehindLayer()  Make a new layer behind others.         |
 |               DeleteLayer()  Remove and delete an existing layer.    |
 |----------------------------------------------------------------------|
 |                 MoveLayer()  Change the position (not depth) of a    |
 |                              layer.                                  |
 |                 SizeLayer()  Change the size of a layer.             |
 |               ScrollLayer()  Change the internal coordinates of a    |
 |                              layer.                                  |
 |----------------------------------------------------------------------|
 |               BehindLayer()  Depth arrange a layer behind others.    |
 |              UpfrontLayer()  Depth arrange a layer in front of       |
 |                              others.                                 |
 |        MoveLayerInFrontOf()  Depth arrange a layer to a specific     |
 |                              position.                               |
 |----------------------------------------------------------------------|
 |                WhichLayer()  Find the frontmost layer at a position. |
 |----------------------------------------------------------------------|
 |  SwapBitsRastPortClipRect()  Fast, non-layered and non-damaging      |
 |                              display operation.                      |
 |----------------------------------------------------------------------|
 |               BeginUpdate()  Synchronize optimized refreshing for    |
 |                              layer.                                  |
 |                 EndUpdate()  End optimized layer refresh.            |
 |----------------------------------------------------------------------|
 |                 LockLayer()  Lock out rendering in a single layer.   |
 |               UnlockLayer()  Release LockLayer() lock.               |
 |                LockLayers()  Lock out rendering in all layers of a   |
 |                              display.                                |
 |              UnlockLayers()  Release LockLayers() lock.              |
 |             LockLayerInfo()  Gain exclusive access to the display's  |
 |                              layers.                                 |
 |           UnlockLayerInfo()  Release LockLayerInfo() lock.           |
 |----------------------------------------------------------------------|
 |         InstallClipRegion()  Add a clipping region to a layer.       |
 |______________________________________________________________________|

The following routines from graphics library are also required for certain
layers library functions:

  ______________________________________________________________________
 |                                                                      |
 |            Routine                        Description                |
 |======================================================================|
 |         LockLayerRom()  Same as LockLayer(), from layers library.    |
 |       UnlockLayerRom()  Release LockLayerRom() lock.                 |
 |  AttemptLockLayerRom()  Lock layer only if it is immediately         |
 |                         available.                                   |
 |----------------------------------------------------------------------|
 |            NewRegion()  Create a new, empty region.                  |
 |        DisposeRegion()  Dispose of an existing region and its        |
 |                         rectangles.                                  |
 |----------------------------------------------------------------------|
 |        AndRectRegion()  AND a rectangle into a region.               |
 |         OrRectRegion()  OR a rectangle into a region.                |
 |        XorRectRegion()  Exclusive-OR a rectangle into a region.      |
 |      ClearRectRegion()  Clear a region.                              |
 |      AndRegionRegion()  AND two regions together.                    |
 |       OrRegionRegion()  OR two regions together.                     |
 |      XorRegionRegion()  Exclusive-OR two regions together.           |
 |          ClearRegion()  Clear a region.                              |
 |______________________________________________________________________|


Amiga® RKM Libraries: 31 Commodities Exchange Library

This chapter describes Commodities Exchange, the library of routines used
to add a custom input handler to the Amiga.  With Commodities Exchange,
any program function can be associated with key combinations or other
input events globally allowing the creation utility programs that run in
the background for all tasks.

 Custom Input Handlers                           CxObject Errors
 CxObjects                                       Uniqueness
 Installing A Broker Object                      Signal CxObjects
 CxMessages                                      Custom CxObjects
 Commodity Tool Types                            Debug CxObjects
 Filter Objects and Input Description Strings    The IX Structure
 Connecting CxObjects                            Controlling CxMessages
 Sender CxObjects                                New Input Events
 Translate CxObjects                             Function Reference


31 Commodities Exchange Library / Custom Input Handlers

The input.device has a hand in almost all user input on the Amiga.  It
gathers input events from the keyboard, the gameport (mouse), and several
other sources, into one input "stream".  Special programs called input
event handlers intercept input events along this stream, examining and
sometimes changing the input events.  Both Intuition and the console
device use input handlers to process user input.

     Figure 31-1: The Amiga Input Stream

Using the input.device, a program can introduce its own custom handler
into the chain of input handlers at almost any point in the chain.  "Hot
key" programs, shell pop-up programs, and screen blankers all commonly use
custom input handlers to monitor user input before it gets to the
Intuition input handler.

     Figure 31-2: A Custom Input Handler

Custom input handlers do have their drawbacks, however.  Not only are
these handlers hard to program, but because there is no standard way to
implement and control them, multiple handlers often do not work well
together.  Their antisocial behavior can result in load order dependencies
and incompatibilities between different custom input handlers.  Even for
the expert user, having several custom input handlers coexist peacefully
can be next to impossible.

     Figure 31-3: The Commodities Network

Commodities Exchange eliminates these problems by providing a simple,
standardized way to program and control custom input handlers.  It is
divided into three parts: an Exec library, a controller program, and some
amiga.lib functions.

The Exec library is called commodities.library.  When it is first opened,
commodities.library establishes a single input handler just before
Intuition in the input chain.  When this input handler receives an input
event, it creates a CxMessage (Commodities Exchange Message) corresponding
to the input event, and diverts the CxMessage through the network of
Commodities Exchange input handlers (Figure 31-3).

These handlers are made up of trees of different CxObjects (Commodities
Exchange Objects), each of which performs a simple operation on the
CxMessages.  Any CxMessages that exit the network are returned to the
input.device's input stream as input events.

Through function calls to the commodities.library, an application can
install a custom input handler.  A Commodities Exchange application,
sometimes simply referred to as a commodity, uses the CxObject primitives
to do things such as filter certain CxMessages, translate CxMessages,
signal a task when a CxObject receives a CxMessage, send a message when a
CxObject receives a CxMessage, or if necessary, call a custom function
when a CxObject receives a CxMessage.

The controller program is called Commodities Exchange.  The user can
monitor and control all the currently running Commodities Exchange
applications from this one program.  The user can enable and disable a
commodity, kill a commodity, or, if the commodity has a window, ask the
commodity to show or hide its window.  When the user requests any of these
actions, the controller program sends the commodity a message, telling it
which action to perform.

The third component of Commodities Exchange is its scanned library
functions.  These functions are part of the amiga.lib scanned library.
They do a lot of the work involved with parsing command lines and Tool
Types.

Commodities Exchange is ideal for programs like hot keys/pop ups, screen
blankers, and mouse blankers that need to monitor all user input.
Commodities Exchange should never be used as an alternate method of
receiving user input for an application.  Other applications depend on
getting user input in some form or another from the input stream.   A
greedy program that diverts input to itself rather than letting the input
go to where the user expects it can seriously confuse the user, not to
mention compromise the advantages of multitasking.


31 Commodities Exchange Library / CxObjects

CxObjects are the basic building blocks used to construct a commodity.  A
commodity uses CxObjects to take care of all manipulations of CxMessages.
When a CxMessage "arrives" at a CxObject, that CxObject carries out its
primitive action and then, if it has not deleted the CxMessage, it passes
the CxMessage on to the next CxObject.  A commodity links together
CxObjects into a tree, organizing these simple action objects to perform
some higher function.

A CxObject is in one of two states, active or inactive.  An active
CxObject performs its primitive action every time it receives a CxMessage.
If a CxObject is inactive, CxMessages bypass it, continuing to the
CxObject that follows the inactive one.  By default, all CxObjects except
the type called brokers are created in the active state.

Currently, there are seven types of CxObjects (Table 31-1).

   Object Type   Purpose
   -----------   -------
    Broker       Registers a new commodity with the commodity network
    Filter       Accepts or rejects input events based on criteria set
                 up by the application
    Sender       Sends a message to a message port
    Translate    Replaces the input event with a different one
    Signal       Signals a task
    Custom       Calls a custom function provided by the commodity
    Debug        Sends debug information out the serial port

                 Table 31-1: Commodities Exchange Object Types


31 Commodities Exchange Library / Installing A Broker Object

The Commodities Exchange input handler maintains a master list of
CxObjects to which it diverts input events using CxMessages.  The
CxObjects in this master list are a special type of CxObject called
brokers.  The only thing a broker CxObject does is divert CxMessages to
its own personal list of CxObjects.  A commodity creates a broker and
attaches other CxObjects to it.  These attached objects take care of the
actual input handler related work of the commodity and make up the
broker's personal list.

The first program listing, Broker.c, is a very simple example of a working
commodity.  It serves only to illustrate the basics of a commodity, not to
actually perform any useful function.  It shows how to set up a broker and
process commands from the controller program.

Besides opening commodities.library and creating an Exec message port,
setting up a commodity requires creating a broker.  The function
CxBroker() creates a broker and adds it to the master list.

    CxObj *CxBroker(struct NewBroker *nb, long *error);

CxBroker()'s first argument is a pointer to a NewBroker structure:

    struct NewBroker {
        BYTE    nb_Version;
                    /* There is an implicit pad byte after this BYTE */
        BYTE    *nb_Name;
        BYTE    *nb_Title;
        BYTE    *nb_Descr;
        SHORT   nb_Unique;
        SHORT   nb_Flags;
        BYTE    nb_Pri;
                    /* There is an implicit pad byte after this BYTE */
        struct  MsgPort   *nb_Port;
        WORD    nb_ReservedChannel;
                    /* Unused, make zero for future compatibility */
    };

Commodities Exchange gets all the information it needs about the broker
from this structure.  NewBroker's nb_Version field contains the version
number of the NewBroker structure.  This should be set to NB_VERSION which
is defined in <libraries/commodities.h>.  The nb_Name, nb_Title, and
nb_Descr point to strings which hold the name, title, and description of
the broker.  The two bit fields, nb_Unique and nb_Flags, toggle certain
features of Commodities Exchange based on their values.  They are
discussed in detail later in this chapter.

The nb_Pri field contains the broker's priority.  Commodities Exchange
inserts the broker into the master list based on this number.  Higher
priority brokers get CxMessages before lower priority brokers.

CxBroker()'s second argument is a pointer to a LONG.  If this pointer is
not NULL, CxBroker() fills in this field with one of the following error
return codes from <libraries/commodities.h>:

    CBERR_OK        0        /* No error                         */
    CBERR_SYSERR    1        /* System error , no memory, etc    */
    CBERR_DUP       2        /* uniqueness violation             */
    CBERR_VERSION   3        /* didn't understand nb_VERSION     */

Once the broker object is created with CxBroker(), it must be activated
with ActivateCxObj().

    oldactivationvalue = LONG ActivateCxObj(CxObj *co,
                                            long newactivationvalue);

After successfully completing the initial set up and activating the
broker, a commodity can begin its input processing loop waiting for
CxMessages to arrive.


31 Commodities Exchange Library / CxMessages

There are actually two types of CxMessages.  The first, CXM_IEVENT,
corresponds to an input event and travels through the Commodities Exchange
network.  The other type, CXM_COMMAND, carries a command to a commodity.
A CXM_COMMAND normally comes from the controller program and is used to
pass user commands on to a commodity.  A commodity receives these commands
through an Exec message port that the commodity sets up before it calls
CxBroker().  The NewBroker's nb_Port field points to this message port.  A
commodity can tell the difference between the two types of CxMessages by
calling the CxMsgType() function.

    ULONG  CxMsgType( CxMsg *cxm );
    UBYTE *CxMsgData( CxMsg *cxm );
    LONG   CxMsgID  ( CxMsg *cxm );

A CxMessage not only has a type, it can also have a data pointer as well
as an ID associated with it.  The data associated with a CXM_IEVENT
CxMessage is an InputEvent structure.  By using the CxMsgData() function,
a commodity can obtain a pointer to the corresponding InputEvent of a
CXM_IEVENT message.  Commodities Exchange gives an ID of zero to any
CXM_IEVENT CxMessage that it introduces to the Commodities network but
certain CxObjects can assign an ID to them.

For a CXM_COMMAND CxMessages, the data pointer is generally not used but
the ID specifies a command passed to the commodity from the user operating
the controller program.  The CxMsgID() macro extracts the ID from a
CxMessage.

 A Simple Commodity Example
 Controller Commands
 Shutting Down the Commodity


31 / CxMessages / Controller Commands

The commands that a commodity can receive from the controller program (as
defined in <libraries/commodities.h>) are:

    CXCMD_DISABLE     /* please disable yourself       */
    CXCMD_ENABLE      /* please enable yourself        */
    CXCMD_KILL        /* go away for good              */
    CXCMD_APPEAR      /* open your window, if you can  */
    CXCMD_DISAPPEAR   /* hide your window              */

The CXCMD_DISABLE, CXCMD_ENABLE, and CXCMD_KILL commands correspond to the
similarly named controller program gadgets, Disable, Enable, and Kill;
CXCMD_APPEAR and CXCMD_DISAPPEAR correspond to the controller program
gadgets, Show and Hide.  These gadgets are ghosted in Broker.c because it
has no window (It doesn't make much sense to give the user a chance to
click the Show and Hide gadgets).  In order to do this, Broker.c  has to
tell Commodities Exchange to ghost these gadgets.  When CxBroker() sets up
a broker, it looks at the NewBroker.nb_Flags field to see if the
COF_SHOW_HIDE bit (from <libraries/commodities.h>) is set.  If it is, the
"Show" and "Hide" gadgets for this broker will be selectable.  Otherwise
they are ghosted and disabled.


31 / CxMessages / Shutting Down the Commodity

Shutting down a commodity is easy.  After replying to all CxMessages
waiting at the broker's message port, a commodity can delete its
CxObjects.  The DeleteCxObj() function removes a single CxObject from the
Commodities network.  DeleteCxObjAll() removes multiple objects.

    void DeleteCxObj( CxObj *co );
    void DeleteCxObjAll( CxObj *delete_co );

If a commodity has a lot of CxObjects, deleting each individually can be a
bit tedious.  DeleteCxObjAll() will delete a CxObject and any other
CxObjects that are attached to it.  The HotKey.c example given later in
this chapter uses this function to delete all its CxObjects.  A commodity
that uses DeleteCxObjAll() to delete all its CxObjects should make sure
that they are all connected to the main one.  (See the section
"Connecting CxObjects" below.)

After deleting its CxObjects, a commodity must take care of any CxMessages
that might have arrived at the message port just before the commodity
deleted its objects.

    while(msg = (CxMsg *)GetMsg(broker_mp))
        ReplyMsg((struct Message *)msg);


31 Commodities Exchange Library / Commodity Tool Types

A goal of Commodities Exchange is to improve user control over input
handlers.  One way in which it accomplishes this goal is through the use
of standard icon Tool Types.  The user will expect commodities to
recognize the set of standard Tool Types:

        CX_PRIORITY
        CX_POPUP
        CX_POPKEY

CX_PRIORITY lets the user set the priority of a commodity.  The string
"CX_PRIORITY=" is a number from -128 to 127.  The higher the number, the
higher the priority of the commodity, giving it access to input events
before lower priority commodities.  All commodities should recognize
CX_PRIORITY.

CX_POPUP and CX_POPKEY are only relevant to commodities with a window.
The string "CX_POPUP=" should be followed by a "yes" or "no", telling the
commodity if it should or shouldn't show its window when it is first
launched.  CX_POPKEY is followed by a string describing the key to use as
a hot key for making the commodity's window appear (pop up).  The
description string for CX_POPKEY describes an input event.  The specific
format of the string is discussed in the next section
("Filter Objects and the Input Description String").

Commodities Exchange's support library functions simplify parsing
arguments from either the Workbench or the Shell (CLI).  A Workbench
launched commodity gets its arguments directly from the Tool Types in the
commodity's icon.  Shell launched commodities get their arguments from the
command line, but these arguments look exactly like the Tool Types from
the commodity's icon.  For example, the following command line sets the
priority of a commodity called HotKey to 5:

    HotKey "CX_PRIORITY=5"

Commodities Exchange has several support library functions used to parse
arguments:

    tooltypearray = UBYTE **ArgArrayInit(LONG argc, UBYTE **argv);
                    void    ArgArrayDone(void);

    tooltypevalue = STRPTR  ArgString(UBYTE **tooltypearray,
                                      STRPTR tooltype,
                                      STRPTR defaultvalue);
    tooltypevalue = LONG  *ArgInt(UBYTE **tooltypearray,
                                  STRPTR tooltype,
                                  LONG defaultvalue);

ArgArrayInit() initializes a Tool Type array of strings which it creates
from the startup arguments, argc and argv.  It doesn't matter if these
startup arguments come from the Workbench or from a Shell, ArgArrayInit()
can extract arguments from either source.  Because ArgArrayInit() uses
some icon.library functions, a commodity is responsible for opening that
library before using the function.

ArgArrayInit() also uses some resources that must be returned to the
system when the commodity is done.  ArgArrayDone() performs this clean up.
Like ArgArrayInit(), ArgArrayDone() uses icon.library, so the library has
to remain open until ArgArrayDone() is finished.

The support library has two functions that use the Tool Type array set up
by ArgArrayInit(), ArgString() and ArgInt().  ArgString() scans the Tool
Type array for a specific Tool Type.  If successful, it returns a pointer
to the value associated with that Tool Type.  If it doesn't find the Tool
Type, it returns the default value passed to it.  ArgInt() is similar to
ArgString().  It also scans the ArgArrayInit()'s Tool Type array, but it
returns a LONG rather than a string pointer.  ArgInt() extracts the
integer value associated with a Tool Type, or, if that Tool Type is not
present, it returns the default value.

Of course, these Tool Type parsing functions are not restricted to the
standard Commodities Exchange Tool Types.  A commodity that requires any
arguments should use these functions along with custom Tool Types to
obtain these values.  Because the Commodities Exchange standard arguments
are processed as Tool Types, the user will expect to enter other arguments
as Tool Types too.


31 Commodities Exchange / Filter Objects and Input Description Strings

Because not all commodities are interested in every input event that makes
it way down the input chain, Commodities Exchange has a method for
filtering them.  A filter CxObject compares the CxMessages it receives to
a pattern.  If a CxMessage matches the pattern, the filter diverts the
CxMessage down its personal list of CxObjects.

    CxObj *CxFilter(UBYTE *descriptionstring);

The C macro CxFilter() (defined in <libraries/commodities.h>) returns a
pointer to a filter CxObject.  The macro has only one argument, a pointer
to a string describing which input events to filter.  The following
regular expression outlines the format of the input event description
string (CX_POPKEY uses the same description string format):

    [class]  {[-] (qualifier|synonym)}  [[-] upstroke]  [highmap|ANSICode]

Class can be any one of the class strings in the table below.  Each class
string corresponds to a class of input event as defined in
<devices/inputevent.h>.  Commodities Exchange will assume the class is
rawkey if the class is not explicitly stated.

     Class String      Input Event Class
     ------------      -----------------
    "rawkey"           IECLASS_RAWKEY
    "rawmouse"         IECLASS_RAWMOUSE
    "event"            IECLASS_EVENT
    "pointerpos"       IECLASS_POINTERPOS
    "timer"            IECLASS_TIMER
    "newprefs"         IECLASS_NEWPREFS
    "diskremoved"      IECLASS_DISKREMOVED
    "diskinserted"     IECLASS_DISKINSERTED

Qualifier is one of the qualifier strings from the table below.  Each
string corresponds to an input event qualifier as defined in
<devices/inputevent.h>).  A dash preceding the qualifier string tells the
filter object not to care if that qualifier is present in the input event.
Notice that there can be more than one qualifier (or none at all) in the
input description string.

   Qualifier String    Input Event Class
   ----------------    -----------------
    "lshift"           IEQUALIFIER_LSHIFT
    "rshift"           IEQUALIFIER_RSHIFT
    "capslock"         IEQUALIFIER_CAPSLOCK
    "control"          IEQUALIFIER_CONTROL
    "lalt"             IEQUALIFIER_LALT
    "ralt"             IEQUALIFIER_RALT
    "lcommand"         IEQUALIFIER_LCOMMAND
    "rcommand"         IEQUALIFIER_RCOMMAND
    "numericpad"       IEQUALIFIER_NUMERICPAD
    "repeat"           IEQUALIFIER_REPEAT
    "midbutton"        IEQUALIFIER_MIDBUTTON
    "rbutton"          IEQUALIFIER_RBUTTON
    "leftbutton"       IEQUALIFIER_LEFTBUTTON
    "relativemouse"    IEQUALIFIER_RELATIVEMOUSE

Synonym is one of the synonym strings from the table below.  These
strings act as synonyms for groups of qualifiers.  Each string corresponds
to a synonym identifier as defined in <libraries/commodities.h>.  A dash
preceding the synonym string tells the filter object not to care if that
synonym is present in the input event.  Notice that there can be more
than one synonym (or none at all) in the input description string.

    Synonym     Synonym
    String     Identifier
    -------    ----------
    "shift"    IXSYM_SHIFT    /* look for either shift key */
    "caps"     IXSYM_CAPS     /* look for either shift key or capslock */
    "alt"      IXSYM_ALT      /* look for either alt key */

Upstroke is the literal string "upstroke".  If this string is absent, the
filter considers only downstrokes.  If it is present alone, the filter
considers only upstrokes.  If preceded by a dash, the filter considers
both upstrokes and downstrokes.

Highmap is one of the following strings:

    "space", "backspace", "tab", "enter", "return", "esc", "del",
    "up", "down", "right", "left", "f1", "f2", "f3", "f4", "f5",
    "f6", "f7", "f8", "f9", "f10", "help".

ANSICode is a single character (for example `a') that Commodities Exchange
looks up in the system default keymap.

Here are some example description strings.  For function key F2 with the
left Shift and either Alt key pressed, the input description string would
be:

    "rawkey lshift alt f2"

To specify the key that produces an `a' (this may or may not be the A key
depending on the keymap), with or without any Shift, Alt, or control keys
pressed use:

    "-shift -alt -control a"

For a mouse move with the right mouse button down, use:

    "rawmouse rbutton"

To specify a timer event use:

    "timer"


31 Commodities Exchange Library / Connecting CxObjects

A CxObject has to be inserted into the Commodities network before it can
process any CxMessages.  AttachCxObj() adds a CxObject to the personal
list of another CxObject.  The HotKey.c example uses it to attach its
filter to a broker.

    void AttachCxObj ( CxObj *headobj, CxObj *co);
    void InsertCxObj ( CxObj *headobj, CxObj *co, CxObj *co_pred );
    void EnqueueCxObj( CxObj *headobj, CxObj *co );
    void SetCxObjPri ( CxObj *co, long pri );
    void RemoveCxObj ( CxObj *co );

AttachCxObj() adds the CxObject to the end of headobj's personal list.
The ordering of a CxObject list determines which object gets CxMessages
first.  InsertCxObj() also inserts a CxObject, but it inserts it after
another CxObject already in the personal list (co_pred in the prototype
above).

Brokers aren't the only CxObjects with a priority.  All CxObjects have a
priority associated with them.  To change the priority of any CxObject,
use the SetCxObjPri() function.  A commodity can use the priority to keep
CxObjects in a personal list sorted by their priority.  The
commodities.library function EnqueueCxObj() inserts a CxObject into
another CxObject's personal list based on priority.

Like its name implies, the RemoveCxObj() function removes a CxObject from
a personal list.  Note that it is not necessary to remove a CxObject from
a list in order to delete it.

     HotKey.c


31 Commodities Exchange Library / Sender CxObjects

A filter CxObject by itself is not especially useful.  It needs some other
CxObjects attached to it.  A commodity interested in knowing if a specific
key was pressed uses a filter to detect and divert the corresponding
CxMessage down the filter's personal list.  The filter does this without
letting the commodity know what happened.  The sender CxObject can be
attached to a filter to notify a commodity that it received a CxMessage.
CxSender() is a macro that creates a sender CxObject.

    senderCxObj = CxObj *CxSender(struct MsgPort *senderport, LONG cxmID);

CxSender() supplies the sender with an Exec message port and an ID.  For
every CxMessage a sender receives, it sends a new CxMessage to the Exec
message port passed in CxSender().  Normally, the commodity creates this
port.  It is not unusual for a commodity's broker and sender(s) to share
an Exec message port.  The HotKey.c example does this to avoid creating
unnecessary message ports.  A sender uses the ID (cxmID) passed to
CxSender() as the ID for all the CxMessages that the it transmits.  A
commodity uses the ID to monitor CxMessages from several senders at a
single message port.

A sender does several things when it receives a CxMessage.  First, it
duplicates the CxMessage's corresponding input event and creates a new
CxMessage.  Then, it points the new CxMessage's data field to the copy of
the input event and sets the new CxMessage's ID to the ID passed to
CxSender().  Finally, it sends the new CxMessage to the port passed to
CxSender(), asynchronously.

Because HotKey uses only one message port between its broker and sender
object, it has to extract the CxMessage's type so it can tell if it is a
CXM_IEVENT or a CXM_COMMAND.  If HotKey gets a CXM_IEVENT, it compares the
CxMessage's ID to the sender's ID, EVT_HOTKEY, to see which sender sent
the CxMessage.  Of course HotKey has only one sender, so it only checks
for only one ID.  If it had more senders, HotKey would check for the ID of
each of the other senders as well.

Although HotKey doesn't use it, a CXM_IEVENT CxMessage contains a pointer
to the copy of an input event.  A commodity can extract this pointer
( using CxMsgData() ) if it needs to examine the input event copy.  This
pointer is only valid before the CxMessage reply.  Note that it does not
make any sense to modify the input event copy.

Senders are attached almost exclusively to CxObjects that filter out most
input events (usually a filter CxObject).  Because a sender sends a
CxMessage for every single input event it gets, it should only get a
select few input events.  The AttachCxObj() function can add a CxObject to
the end of a filter's (or some other filtering CxObject's) personal list.
A commodity should not attach a CxObject to a sender as a sender ignores
any CxObjects in its personal list.


31 Commodities Exchange Library / Translate CxObjects

Normally, after a commodity processes a hot key input event, it needs to
eliminate that input event.  Other commodities may need to replace an
input event with a different one.  The translate CxObject can be used for
these purposes.

    translateCxObj = CxObj  *CxTranslate(struct InputEvent *newinputevent);

The macro CxTranslate() creates a new translate CxObject.  CxTranslate()'s
only argument is a pointer to a chain of one or more InputEvent structures.

When a translate CxObject receives a CxMessage, it eliminates the
CxMessage and its corresponding input event from the system.  The
translator introduces a new input event, which Commodities Exchange copies
from the InputEvent structure passed to CxTranslate() (newinputevent from
the function prototype above), in place of the deleted input event.

A translator is normally attached to some kind of filtering CxObject.  If
it wasn't, it would translate all input events into the same exact input
event.  Like the sender CxObject, a translator does not divert CxMessages
down its personal list, so it doesn't serve any purpose to add any to it.

    void SetTranslate( CxObj *translator, struct InputEvent *ie );

It is possible to change the InputEvent structure that a translator looks
at when it creates and introduces new input events into the input stream.
The function SetTranslate() accepts a pointer to the new InputEvent
structure, which the translator will duplicate and introduce when it
receives a CxMessage.

HotKey utilizes a special kind of translator.  Instead of supplying a new
input event, HotKey passes a NULL to CxTranslate().  If a translator has a
NULL new input event pointer, it does not introduce a new input event, but
still eliminates any CxMessages and corresponding input events it receives.


31 Commodities Exchange Library / CxObject Errors

A Commodities Exchange function that acts on a CxObject records errors in
the CxObject's accumulated error field.  The function CxObjError() returns
a CxObject's error field.

    co_errorfield = LONG CxObjError( CxObj *co );

Each bit in the error field corresponds to a specific type of error.  The
following is a list of the currently defined CxObject errors and their
corresponding bit mask constants.

    Error Constant    Meaning
    --------------    -------
    COERR_ISNULL      CxObjError() was passed a NULL.
    COERR_NULLATTACH  Someone tried to attach a NULL CxObject to this
                      CxObject.
    COERR_BADFILTER   This filter CxObject currently has an invalid
                      filter description.
    COERR_BADTYPE     Someone tried to perform a type specific function
                      on the wrong type of CxObject (for example calling
                      SetFilter() on a sender CxObject).

The remaining bits are reserved for future use.  HotKey.c
checks the error field of its filter CxObject to make sure the filter is
valid.  HotKey.c does not need to check the other objects with
CxObjError() because it already makes sure that these other objects are
not NULL, which is the only other kind of error the other objects can
cause in this situation.

Commodities Exchange has a function that clears a CxObject's accumulated
error field, ClearCxObjError().

    void ClearCxObjError( CxObj *co );

A commodity should be careful about using this, especially on a filter.
If a commodity clears a filter's error field and the COERR_BADFILTER bit
is set, Commodities Exchange will think that the filter is OK and start
sending messages through it.


31 Commodities Exchange Library / Uniqueness

When a commodity opens its broker, it can ask Commodities Exchange not to
launch another broker with the same name (nb_Name).  The purpose of the
uniqueness feature is to prevent the user from starting duplicate
commodities.  If a commodity asks, Commodities Exchange will not only
refuse to create a new, similarly named broker, but it will also notify
the original commodity if someone tries to do so.

A commodity tells Commodities Exchange not to allow duplicates by setting
certain bits in the nb_Unique field of the NewBroker structure it sends to
CxBroker():

    NBU_UNIQUE      bit 0
    NBU_NOTIFY      bit 1

Setting the NBU_UNIQUE bit prevents duplicate commodities.  Setting the
NBU_NOTIFY bit tells Commodities Exchange to notify a commodity if an
attempt was made to launch a duplicate.  Such a commodity will receive a
CXM_COMMAND CxMessage with an ID of CXCMD_UNIQUE when someone tries to
duplicate it. Because the uniqueness feature uses the name a programmer
gives a commodity to differentiate it from other commodities, it is
possible for completely different commodities to share the same name,
preventing the two from coexisting.  For this reason, a commodity should
not use a name that is likely to be in use by other commodities (like
"filter" or "hotkey").  Instead, use a name that matches the commodity
name.

When HotKey.c gets a CXCMD_UNIQUE CxMessage, it shuts itself down.
HotKey.c and all the windowless commodities that come with the Release 2
Workbench shut themselves down when they get a CXCMD_UNIQUE CxMessage.
Because the user will expect all windowless commodities to work this way,
all windowless commodities should follow this standard.

When the user tries to launch a duplicate of a system commodity that has a
window, the system commodity moves its window to the front of the display,
as if the user had clicked the "Show" gadget in the controller program's
window.  A windowed commodity should mimic conventions set by existing
windowed system commodities, and move its window to the front of the
display.


31 Commodities Exchange Library / Signal CxObjects

A commodity can use a sender CxObject to find out if a CxMessage has
"visited" a CxObject, but this method unnecessarily uses system resources.
A commodity that is only interested in knowing if such a visitation took
place does not need to see a corresponding input event or a CxMessage ID.
Instead, Commodities Exchange has a CxObject that uses an Exec signal.

    signalCxObj = CxObj  *CxSignal(struct Task *, LONG cx_signal);

CxSignal() sets up a signal CxObject.  When a signal CxObject receives a
CxMessage, it signals a task.  The commodity is responsible for
determining the proper task ID and allocating the signal.  Normally, a
commodity wants to be signalled so it uses FindTask(NULL) to find it's own
task address.  Note that cx_signal from the above prototype is the signal
number as returned by AllocSignal(), not the signal mask made from that
number.  For more information on signals, see the "Exec Signals" chapter.

The example Divert.c (shown a little later in this chapter) uses a signal
CxObject.


31 Commodities Exchange Library / Custom CxObjects

Although the CxObjects mentioned so far take care of most of the input
event handling a commodity needs to do, they cannot do it all.  This is
why Commodities Exchange has a custom CxObject.  When a custom CxObject
receives a CxMessage, it calls a function provided by the commodity.

    customCxObj = CxObj  *CxCustom(LONG *customfunction(), LONG  cxmID);

A custom CxObject is the only means by which a commodity can directly
modify input events as they pass through the Commodities network as
CxMessages.  For this reason, it is probably the most dangerous of the
CxObjects to use.

    A Warning About Custom CxObjects.
    ---------------------------------
    Unlike the rest of the code a commodities programmer writes, the
    code passed to a custom CxObject runs as part of the input.device
    task, putting severe restrictions on the function.  No DOS or
    Intuition functions can be called.  No assumptions can be made about
    the values of registers upon entry.  Any function passed to
    CxCustom() should be very quick and very simple, with a minimum of
    stack usage.

Commodities Exchange calls a custom CxObject's function as follows:

    void customfunction(CxMsg *cxm, CxObj *customcxobj);

where cxm is a pointer to a CxMessage corresponding to a real input event,
and customcxobj is a pointer to the custom CxObject.  The custom function
can extract the pointer to the input event by calling CxMsgData().  Before
passing the CxMessage to the custom function, Commodities Exchange sets
the CxMessage's ID to the ID passed to CxCustom().

The following is an example of a custom CxObject function that swaps
the function of the left and right mouse buttons.

custom = CxCustom(CxFunction, 0L)

/* The custom function for the custom CxObject.  Any code for a */
/* custom CxObj must be short and sweet. This code runs as part */
/* of the input.device task                                     */
#define CODEMASK (0x00FF & IECODE_LBUTTON & IECODE_RBUTTON)
void CxFunction(register CxMsg *cxm, CxObj *co)
{
    struct InputEvent *ie;
    UWORD mousequals = 0x0000;

    /* Get the struct InputEvent associated with this CxMsg.  Unlike
     * the InputEvent extracted from a CxSender's CxMsg, this is a
     *  *REAL* input event, be careful with it.
     */
    ie = (struct InputEvent *)CxMsgData(cxm);

    /* Check to see if this input event is a left or right mouse button
     * by itself (a mouse button can also be a qualifier).  If it is,
     * flip the low order bit to switch leftbutton <--> rightbutton.
     */
    if (ie->ie_Class == IECLASS_RAWMOUSE)
        if ((ie->ie_Code & CODEMASK) == CODEMASK)  ie->ie_Code ^= 0x0001;

    /* Check the qualifiers. If a mouse button was down when this */
    /* input event occurred, set the other mouse button bit.      */
    if (ie->ie_Qualifier & IEQUALIFIER_RBUTTON)  mousequals |=
                                                   IEQUALIFIER_LEFTBUTTON;
    if (ie->ie_Qualifier & IEQUALIFIER_LEFTBUTTON)  mousequals |=
                                                      IEQUALIFIER_RBUTTON;

    /* clear the RBUTTON and LEFTBUTTON qualifier bits */
    ie->ie_Qualifier &= ~(IEQUALIFIER_LEFTBUTTON | IEQUALIFIER_RBUTTON);

    /* set the mouse button qualifier bits to their new values */
    ie->ie_Qualifier |= mousequals;
}


31 Commodities Exchange Library / Debug CxObjects

The final CxObject is the debug CxObject.  When a debug CxObject receives
a CxMessage, it sends debugging information to the serial port using
KPrintF().

    debugCxObj  = CxObj  *CxDebug(LONG ID);

The debug CxObject will KPrintF() the following information about itself,
the CxMsg, and the corresponding InputEvent structure:

    DEBUG NODE: 7CB5AB0, ID: 2
     CxMsg: 7CA6EF2, type: 0, data 2007CA destination 6F1E07CB
    dump IE: 7CA6F1E
     Class 1
     Code 40
     Qualifier 8000
     EventAddress 40001802

There has to be a terminal connected to the Amiga's serial port to receive
this information.  See the KPrintF() Autodoc (debug.lib) for more details.
Note that the debug CxObject did not work before V37.


31 Commodities Exchange Library / The IX Structure

Commodities Exchange does not use the input event description strings
discussed earlier to match input events.  Instead, Commodities Exchange
converts these strings to its own internal format.  These input
expressions are available for commodities to use instead of the input
description strings.  The following is the IX structure as defined in
<libraries/commodities.h>:

    #define IX_VERSION   2

    struct InputXpression {
       UBYTE   ix_Version;     /* must be set to IX_VERSION  */
       UBYTE   ix_Class;       /* class must match exactly   */
       UWORD   ix_Code;
       UWORD   ix_CodeMask;    /* normally used for UPCODE   */
       UWORD   ix_Qualifier;
       UWORD   ix_QualMask;
       UWORD   ix_QualSame;    /* synonyms in qualifier      */
       };
    typedef struct InputXpression IX;

The ix_Version field contains the current version number of the
InputXpression structure.  The current version is defined as IX_VERSION.
The ix_Class field contains the IECLASS_ constant (defined in
<devices/inputevent.h>) of the class of input event sought.  Commodities
Exchange uses the ix_Code and ix_CodeMask fields to match the ie_Code
field of a struct InputEvent.  The bits of ix_CodeMask indicate which bits
are relevant in the ix_Code field when trying to match against a ie_Code.
If any bits in ix_CodeMask are off, Commodities Exchange does not consider
the corresponding bit in ie_Code when trying to match input events.  This
is used primarily to mask out the IECODE_UP_PREFIX bit of rawkey events,
making it easier to match both up and down presses of a particular key.

IX's qualifier fields, ix_Qualifier, ix_QualMask, and ix_QualSame, are
used to match the ie_Qualifier field of an InputEvent structure.  The
ix_Qualifier and ix_QualMask fields work just like ix_Code and
ix_CodeMask.  The bits of ix_QualMask indicate which bits are relevant
when comparing ix_Qualifier to ie_Qualifier.  The ix_QualSame field tells
Commodities Exchange that certain qualifiers are equivalent:

    #define IXSYM_SHIFT  1  /* left- and right- shift are equivalent     */
    #define IXSYM_CAPS   2  /* either shift or caps lock are equivalent  */
    #define IXSYM_ALT    4  /* left- and right- alt are equivalent       */

For example, the input description string

    "rawkey -caps -lalt -relativemouse -upstroke ralt tab"

matches a tab upstroke or downstroke with the right Alt key pressed
whether or not the left Alt, either Shift, or the Caps Lock keys are down.
The following IX structure corresponds to that input description string:

    IX ix = {
        IX_VERSION,             /* The version */
        IECLASS_RAWKEY,         /* We're looking for a RAWKEY event */
        0x42,                   /* The key the usa0 keymap maps to a tab */
        0x00FF & (~IECODE_UP_PREFIX), /* We want up and down key presses */
        IEQUALIFIER_RALT,             /* The right alt key must be down */
        0xFFFF & ~(IEQUALIFIER_LALT | IEQUALIFIER_LSHIFT |
                   IEQUALIFIER_RSHIFT | IEQUALIFIER_CAPSLOCK |
                   IEQUALIFIER_RELATIVEMOUSE),
                   /* don't care about left alt, shift, capslock, or */
                   /* relativemouse qualifiers                       */
        IXSYM_CAPS  /* The shift keys and the capslock key */
                    /* qualifiers are all equivalent       */
    };

The CxFilter() macro only accepts a description string to describe an
input event.  A commodity can change this filter, however, with the
SetFilter() and SetFilterIX() function calls.

    void SetFilter( CxObj *filter, UBYTE *descrstring );
    void SetFilterIX( CxObj *filter, IX *ix );

SetFilter() and SetFilterIX() change which input events a filter CxObject
diverts.  SetFilter() accepts a pointer to an input description string.
SetFilterIX() accepts a pointer to an IX input expression.  A commodity
that uses either of these functions should check the filter's error code
with CxObjError() to make sure the change worked.

The function ParseIX() parses an input description string and translates
it into an IX input expression.

    errorcode = LONG ParseIX( UBYTE *descrstring, IX *ix );

Commodities Exchange uses ParseIX() to convert the description string in
CxFilter() to an IX input expression.  As was mentioned previously, as of
commodities.library version 37.3, ParseIX() does not work with certain
kinds of input strings.


31 Commodities Exchange Library / Controlling CxMessages

A Custom CxObject has the power to directly manipulate the CxMessages that
travel around the Commodities network.  One way is to directly change
values in the corresponding input event.  Another way is to redirect (or
dispose of) the CxMessages.

    void DivertCxMsg ( CxMsg *cxm, CxObj *headobj, CxObj *retobj );
    void RouteCxMsg  ( CxMsg *cxm, CxObj *co );
    void DisposeCxMsg( CxMsg *cxm );

DivertCxMsg() and RouteCxMsg() dictate where the CxMessage will go next.
Conceptually, DivertCxMsg() is analogous to a subroutine in a program; the
CxMessage will travel down the personal list of a CxObject (headobj in the
prototype) until it gets to the end of that list.  It then returns and
visits the CxObject that follows the return CxObject (the return CxObject
in the prototype above is retobj).  RouteCxMsg() is analogous to a goto in
a program; it has no CxObject to return to.

DisposeCxMsg() removes a CxMessage from the network and releases its
resources.  The translate CxObject uses this function to remove a
CxMessage.

The example Divert.c shows how to use DivertCxMsg() as well as a
signal CxObject.

     divert.c


31 Commodities Exchange Library / New Input Events

Commodities Exchange also has functions used to introduce new input events
to the input stream.

    struct InputEvent *InvertString( UBYTE *string, ULONG *keymap );
    void               FreeIEvents( struct InputEvent *ie );
    void               AddIEvents( struct InputEvent *ie );

InvertString() is an amiga.lib function that accepts an ASCII string and
creates a linked list of input events that translate into the string using
the supplied keymap (or the system default if the key map is NULL).  The
NULL terminated string may contain ANSI character codes, an input
description enclosed in angle (<>) brackets, or one of the following
backslash escape characters:

    \r -- return
    \t -- tab
    \\ -- backslash

For example:

    abc<alt f1>\rhi there.

FreeIEvents() frees a list of input events allocated by InvertString().
AddIEvents() is a commodities.library function that adds a linked list of
input events at the the top of the Commodities network.  Each input event
in the list is made into an individual CxMessage.  Note that if passed a
linked list of input events created by InvertString(), the order the
events appear in the string will be reversed.

     PopShell.c


31 Commodities Exchange Library / Function Reference

The following are brief descriptions of the Commodities Exchange functions
covered in this chapter.  All of these functions require Release 2 or a
later version of the Amiga operating system.  See the Amiga ROM Kernel
Reference Manual: Includes and Autodocs for details on each function call.

              Table 31-2: Commodities Exchange Functions
  _____________________________________________________________________
 |                                                                     |
 |         Function              Description                           |
 |=====================================================================|
 |         CxBroker()  Creates a CxObject of type Broker.              |
 |         CxFilter()  Creates a CxObject of type Filter.              |
 |         CxSender()  Creates a CxObject of type Sender.              |
 |      CxTranslate()  Creates a CxObject of type Translate.           |
 |         CxSignal()  Creates a CxObject of type Signal.              |
 |         CxCustom()  Creates a CxObject of type Custom.              |
 |          CxDebug()  Creates a CxObject of type Debug.               |
 |      DeleteCxObj()  Frees a single CxObject                         |
 |   DeleteCxObjAll()  Frees a group of connected CxObjects            |
 |---------------------------------------------------------------------|
 |    ActivateCxObj()  Activates a newly created CxObject in the       |
 |                     commodities network.                            |
 |---------------------------------------------------------------------|
 |     SetTranslate()  Sets up substitution of one input event for     |
 |                     another by translate CxObjects.                 |
 |---------------------------------------------------------------------|
 |        CxMsgType()  Finds the type of a CxMessage.                  |
 |        CxMsgData()  Returns the CxMessage data.                     |
 |          CxMsgID()  Returns the CxMessage ID.                       |
 |---------------------------------------------------------------------|
 |       CxObjError()  Returns the CxObject's accumulated error field. |
 |  ClearCxObjError()  Clear the CxObject's accumulated error field.   |
 |---------------------------------------------------------------------|
 |     ArgArrayInit()  Create a Tool Types array from argc and argv    |
 |                     (Workbench or Shell).                           |
 |     ArgArrayDone()  Free the resources used by ArgArrayInit().      |
 |        ArgString()  Return the string associated with a given Tool  |
 |                     Type in the array.                              |
 |           ArgInt()  Return the integer associated with a given Tool |
 |                     Type in the array.                              |
 |---------------------------------------------------------------------|
 |      AttachCxObj()  Attaches a CxObject to the end of a given       |
 |                     CxObject's list.                                |
 |      InsertCxObj()  Inserts a CxObject in a given position in a     |
 |                     CxObject's list.                                |
 |     EnqueueCxObj()  Inserts a CxObject in a CxObject's list by      |
 |                     priority.                                       |
 |      SetCxObjPri()  Sets a CxObject's priority for EnqueueCxObj().  |
 |      RemoveCxObj()  Removes a CxObject from a list.                 |
 |---------------------------------------------------------------------|
 |        SetFilter()  Set a filter for a CxObject from an input       |
 |                     description string.                             |
 |      SetFilterIX()  Set a filter for a CxObject from an IX data     |
 |                     structure.                                      |
 |---------------------------------------------------------------------|
 |          ParseIX()  Convert an input description string to an IX    |
 |                     data structure.                                 |
 |---------------------------------------------------------------------|
 |      DivertCxMsg()  Divert a CxMessage to one CxObject and return   |
 |                     it to another.                                  |
 |       RouteCxMsg()  Redirect a CxMessage to a new CxObject.         |
 |     DisposeCxMsg()  Cancel a CxMessage removing it from the         |
 |                     Commodities network.                            |
 |---------------------------------------------------------------------|
 |     InvertString()  Creates a linked list of input events that      |
 |                     correspond to a given string.                   |
 |      FreeIEvents()  Frees the linked list of input events created   |
 |                     with InvertString().                            |
 |       AddIEvents()  Converts a list of input events to CxMessages   |
 |                     and puts them into the network.                 |
 |_____________________________________________________________________|


Amiga® RKM Libraries: 32 Expansion Library

Amiga RAM expansion boards and other expansion bus peripherals are
designed to reside at dynamically assigned address spaces within the
system. The configuration and initialization of these expansion
peripherals is performed by the expansion.library.

 AUTOCONFIG(TM)            Expansion Board Drivers
 The Expansion Sequence    Function Reference


32 Expansion Library / AUTOCONFIG(TM)

The Amiga AUTOCONFIG protocol is designed to allow the dynamic assignment
of available address space to expansion boards, eliminating the need for
user configuration via jumpers. Such expansion boards include memory
boards, hard disk controllers, network interfaces, and other special
purpose expansion devices. Some expansion devices, such as RAM boards,
require no special driver software.  Other types of expansion devices may
use a disk-loaded driver from the DEVS: or SYS:Expansion drawer, or an
on-board ROM driver (for example, a self-booting hard disk controller).

This chapter will concentrate on the software and driver side of Zorro
expansion devices, using a Zorro II device as an example. Zorro III
devices have additional identifying bits and memory size options which are
described in the Zorro III hardware documentation. For more information on
Zorro II and Zorro III expansion hardware, see the "Zorro Expansion Bus"
appendix of the Amiga Hardware Reference Manual, 3rd Edition from
Addison-Wesley.  For additional information specific to Zorro II boards,
see the Commodore publication A500/A2000 Technical Reference Manual.

AUTOCONFIG occurs whenever the Amiga is powered on or reset.  During early
system initialization, expansion.library identifies the expansion boards
that are installed in the Amiga and dynamically assigns an appropriate
address range for each board to reside at.  During this AUTOCONFIG
process, each expansion board first appears in turn at $E80000 (Zorro II)
or $FF000000 (Zorro III), presenting readable identification information,
generally in a PAL or a ROM, at the beginning of the board.  The
identification includes the size of the board, its address space
preferences, type of board (memory or other), and a unique Hardware
Manufacturer Number assigned by Commodore Applications and Technical
Support (CATS), West Chester, Pennsylvania.

The unique Hardware Manufacturer number, in combination with a
vendor-supplied product number, provides a way for boards to be identified
and for disk-based drivers to be matched with expansion boards.  All
expansion boards for the Amiga must implement the AUTOCONFIG protocol.

    Note:
    -----
    A unique Hardware Manufacturer number assigned by CATS is not the
    same as a Developer number.


32 Expansion Library / The Expansion Sequence

During system initialization, expansion.library configures each expansion
peripheral in turn by examining its identification information and
assigning it an appropriate address space.  If the board is a RAM board,
it can be added to the system memory list to make the RAM available for
allocation by system tasks.

Descriptions of all configured boards are kept in a private ExpansionBase
list of ConfigDev structures.  A board's identification information is
stored in the ExpansionRom sub-structure contained within the ConfigDev
structure.  Applications can examine individual or all ConfigDev
structures with the expansion.library function FindConfigDev().

The ConfigDev structure is defined in <libraries/configvars.h> and <.i>:

struct ConfigDev {
   struct Node         cd_Node;
   UBYTE               cd_Flags;     /* (read/write) */
   UBYTE               cd_Pad;       /* reserved */
   struct ExpansionRom cd_Rom;       /* copy of board's expansion ROM */
   APTR                cd_BoardAddr; /* memory where board was placed */
   ULONG               cd_BoardSize; /* size of board in bytes */
   UWORD               cd_SlotAddr;  /* which slot number (PRIVATE) */
   UWORD               cd_SlotSize;  /* number of slots (PRIVATE) */
   APTR                cd_Driver;    /* pointer to node of driver */
   struct ConfigDev    *cd_NextCD;   /* linked list of drivers to config */
   ULONG               cd_Unused[4]; /* for whatever the driver wants */
};

/* cd_Flags */
#define CDB_SHUTUP      0       /* this board has been shut up */
#define CDB_CONFIGME    1       /* this board needs a driver to claim it */

#define CDF_SHUTUP      0x01
#define CDF_CONFIGME    0x02

The ExpansionRom structure within ConfigDev contains the board
identification information that is read from the board's PAL or ROM at
expansion time.  The actual onboard identification information of a Zorro
II board appears in the high nibbles of the first $40 words at the start
of the board.  Except for the first nibble pair ($00/$02) which when
combined form er_Type, the information is stored in inverted
("ones-complement") format where binary 1's are represented as 0's and 0's
are represented as 1's.  The expansion.library reads the nibbles of
expansion information from the board, un-inverts them (except for $00/$02
er_Type which is already un-inverted), and combines them to form the
elements of the ExpansionRom structure.

The ExpansionRom structure is defined in <libraries/configregs.h> and <.i>:

struct ExpansionRom {            /* First 16 bytes of the expansion ROM */
    UBYTE  er_Type;         /* Board type, size and flags */
    UBYTE  er_Product;      /* Product number, assigned by manufacturer */
    UBYTE  er_Flags;        /* Flags */
    UBYTE  er_Reserved03;   /* Must be zero ($ff inverted) */
    UWORD  er_Manufacturer; /* Unique ID,ASSIGNED BY AMIGA, INC.! */
    ULONG  er_SerialNumber; /* Available for use by manufacturer */
    UWORD  er_InitDiagVec;  /* Offset to optional "DiagArea" structure */
    UBYTE  er_Reserved0c;
    UBYTE  er_Reserved0d;
    UBYTE  er_Reserved0e;
    UBYTE  er_Reserved0f;
};

 Simple Expansion Library Example


32 / The Expansion Sequence / Simple Expansion Library Example

The following example uses FindConfigDev() to print out information about
all of the configured expansion peripherals in the system.
FindConfigDev() searches the system's list of ConfigDev structures and
returns a pointer to the ConfigDev structure matching a specified board:

    newconfigdev = struct ConfigDev *
                       FindConfigDev( struct ConfigDev *oldconfigdev,
                                      LONG manufacturer, LONG product )

The oldconfigdev argument may be set to NULL to begin searching at the top
of the system list or, if it points to a valid ConfigDev, searching will
begin after that entry in the system list.  The manufacturer and product
arguments can be set to search for a specific manufacturer and product by
number, or, if these are set to -1, the function will match any board.

     findboards.c


32 Expansion Library / Expansion Board Drivers

The Amiga operating system contains support for matching up disk-based
drivers with AUTOCONFIG boards.  Though such drivers are commonly Exec
devices, this is not required.  The driver may, for instance, be an Exec
library or task.  Since 1.3, the system software also supports the
initialization of onboard ROM driver software.

 Disk Based Drivers           ROM Based and Autoboot Drivers
 Expansion Drivers and DOS    RigidDiskBlock And Alternate Filesystems


32 / Expansion Board Drivers / Disk Based Drivers

Disk-based expansion board drivers and their icons are generally placed in
the SYS:Expansion drawer of the user's SYS: disk or partition.  The icon
Tool Type field must contain the unique Hardware Manufacturer number, and
the Product number of the expansion board(s) the driver is written for.
(For more about icon Tool Type fields refer to the chapter on
"Workbench and Icon Library".)

The BindDrivers command issued during the disk startup-sequence attempts
to match disk-based drivers with their expansion boards.  To do this,
BindDrivers looks in the Tool Types field of all icon files in
SYS:Expansion.  If the Tool Type "PRODUCT" is found in the icon, then this
is an icon file for a driver.  Binddrivers will then attempt to match the
manufacturer and product number in this PRODUCT Tool Type with those of a
board that was configured at expansion time.

For example, suppose you are manufacturer #1019.  You have two products,
#1 and #2 which both use the same driver.  The icon for your driver for
these two products would have a Tool Type set to "PRODUCT=1019/1|1019/2".
This means: I am an icon for a driver that works with product number 1 or
2 from manufacturer 1019, now bind me.  Spaces are not legal.  Here are
two other examples:

        PRODUCT=1208/11    is the Tool Type for a driver for product
                           11 from manufacturer number 1208.

        PRODUCT=1017       is the Tool Type for a driver for any
                           product from manufacturer number 1017.

If a matching board is found for the disk-based driver, the driver code is
loaded and then initialized with the Exec InitResident() function.  From
within its initialization code, the driver can get information about the
board it is bound to by calling the expansion.library function
GetCurrentBinding().  This function will provide the driver with a copy of
a CurrentBinding structure, including a pointer to a ConfigDev structure
(possibly linked to additional ConfigDevs via the cd_NextCD field) of the
expansion board(s) that matched the manufacturer and product IDs.

    /* this structure is used by GetCurrentBinding() */
    /* and SetCurrentBinding()                       */
    struct CurrentBinding {
        struct ConfigDev *cb_ConfigDev;    /* first configdev in chain */
        UBYTE *          cb_FileName;      /* file name of driver */
        UBYTE *          cb_ProductString; /* product # string */
        UBYTE **         cb_ToolTypes;     /* tooltypes from disk object */
    };

GetCurrentBinding() allows the driver to find out the base address and
other information about its board(s).  The driver must unset the CONFIGME
bit in the cd_Flags field of the ConfigDev structure for each board it
intends to drive, and record the driver's Exec node pointer in the
cd_Driver structure.  This node should contain the LN_NAME and LN_TYPE
(i.e., NT_DEVICE, NT_TASK, etc.) of the driver.

    Important Note:
    ---------------
    The GetCurrentBinding() function, and driver binding in general, must
    be bracketed by an ObtainConfigBinding() and ReleaseConfigBinding()
    semaphore. The BindDrivers command obtains this semaphore and
    performs a SetCurrentBinding() before calling InitResident(),
    allowing the driver to simply do a GetCurrentBinding().

Full source code for a disk-based Expansion or DEVS: sample device driver
may be found in the Addison-Wesley Amiga ROM Kernel Reference Manual:
Devices.  Autodocs for expansion.library functions may be found in the
Addison-Wesley Amiga ROM Kernel Reference Manual: Includes and Autodocs.


32 / Expansion Board Drivers / Expansion Drivers and DOS

Two other expansion.library functions commonly used by expansion board
drivers are MakeDosNode() and AddDosNode().  These functions allow a
driver to create and add a DOS device node (for example DH0:) to the
system.   A new function, AddBootNode(), is also available in Release 2
(V36 and later versions of the OS) that can be used to add an autobooting
DOS device node.

MakeDosNode() requires an initialized structure of environment information
for creating a DOS device node. The format of the function is:

    struct DeviceNode *deviceNode = MakeDosNode(parameterPkt);

The parameterPkt argument is a pointer (passed in A0 from assembler) to an
initialized packet of environment parameters.

The parameter packet for MakeDosNode() consists of four longwords followed
by a DosEnvec structure:

;-----------------------------------------------------------------------
;
; Layout of parameter packet for MakeDosNode
;
;-----------------------------------------------------------------------

* The packet for MakeDosNode starts with the following four
* longwords, directly followed by a DosEnvec structure.

    APTR  dosName    ; Points to a DOS device name (ex. 'RAM1',0)
    APTR  execName   ; Points to device driver name (ex. 'ram.device',0)
    ULONG unit       ; Unit number
    ULONG flags      ; OpenDevice flags

* The DosEnvec disk "environment" is a longword array that describes the
* disk geometry.  It is variable sized, with the length at the beginning.
* Here are the constants for a standard geometry.
* See libraries/filehandler.i for additional notes.

 STRUCTURE DosEnvec,0
    ULONG de_TableSize       ; Size of Environment vector
    ULONG de_SizeBlock       ; in longwords: standard value is 128
    ULONG de_SecOrg          ; not used; must be 0
    ULONG de_Surfaces        ; # of heads (surfaces). drive specific
    ULONG de_SectorPerBlock  ; not used; must be 1
    ULONG de_BlocksPerTrack  ; blocks per track. drive specific
    ULONG de_Reserved        ; DOS reserved blocks at start of partition.
    ULONG de_PreAlloc        ; DOS reserved blocks at end of partition
    ULONG de_Interleave      ; usually 0
    ULONG de_LowCyl          ; starting cylinder. typically 0
    ULONG de_HighCyl         ; max cylinder. drive specific
    ULONG de_NumBuffers      ; Initial # DOS of buffers.
    ULONG de_BufMemType      ; type of mem to allocate for buffers
    ULONG de_MaxTransfer     ; Max number of bytes to transfer at a time
    ULONG de_Mask            ; Address Mask to block out certain memory
    LONG  de_BootPri         ; Boot priority for autoboot
    ULONG de_DosType         ; ASCII (HEX) string showing filesystem type;
                             ; 0X444F5300 is old filesystem,
                             ; 0X444F5301 is fast file system
    ULONG de_Baud            ; Baud rate for serial handler
    ULONG de_Control         ; Control word for handler/filesystem
                             ; (used as filesystem/handler desires)
    ULONG de_BootBlocks      ; Number of blocks containing boot code
                             ; (for non-AmigaDOS filesystems)
    LABEL DosEnvec_SIZEOF

After making a DOS device node, drivers (except for autoboot drivers) use
AddDosNode(deviceNode) to add their node to the system. Autoboot drivers
will instead use the new Release 2 expansion.library AddBootNode()
function (if running under V36 or higher) or the Exec Enqueue() function
(if running under pre-V36) to add a BootNode to the
ExpansionBase.eb_MountList.


32 / Expansion Board Drivers / ROM Based and Autoboot Drivers

Since 1.3, the system software supports the initialization of ROM drivers
residing on expansion peripherals, including the ability for drivers to
provide a DOS node which the system can boot from. This feature is known
as Autoboot.

Automatic boot from a ROM-equipped expansion board is accomplished before
DOS is initialized.  This facility makes it possible to automatically boot
from a hard disk without any floppy disks inserted.  Likewise, it is
possible to automatically boot from any device which supports the ROM
protocol, even allowing the initialization of a disk operating system
other than the Amiga's dos.library.  ROM-based drivers contain several
special entry points that are called at different stages of system
initialization. These three stages are known as DIAG, ROMTAG INIT and BOOT.

 Events At DIAG Time    Events At ROMTAG INIT Time    Events At BOOT Time


32 / / ROM Based and Autoboot Drivers / Events At DIAG Time

When your AUTOCONFIG hardware board is configured by the expansion
initialization routine, its ExpansionRom structure is copied into the
ExpansionRom subfield of a ConfigDev structure.  This ConfigDev structure
will be linked to the expansion.library's private list of configured
boards.

After the board is configured, the er_Type field of its ExpansionRom
structure is checked.  The DIAGVALID bit set declares that there is a
valid DiagArea (a ROM/diagnostic area) on this board.  If there is a valid
DiagArea, expansion next tests the er_InitDiagVec vector in its copy of
the ExpansionRom structure.  This offset is added to the base address of
the configured board; the resulting address points to the start of this
board's DiagArea.

    struct ExpansionRom
    {
        UBYTE   er_Type;          /* <-- if ERTB_DIAGVALID set */
        UBYTE   er_Product;
        UBYTE   er_Flags;
        UBYTE   er_Reserved03;
        UWORD   er_Manufacturer;
        ULONG   er_SerialNumber;
        UWORD   er_InitDiagVec;   /* <-- then er_InitDiagVec      */
        UBYTE   er_Reserved0c;    /*     is added to cd_BoardAddr */
        UBYTE   er_Reserved0d;    /*     and points to DiagArea   */
        UBYTE   er_Reserved0e;
        UBYTE   er_Reserved0f;
    };

Now expansion knows that there is a DiagArea, and knows where it is.

     struct DiagArea
     {
         UBYTE   da_Config;        /* <-- if DAC_CONFIGTIME is set */
         UBYTE   da_Flags;
         UWORD   da_Size;          /* <-- then da_Size bytes will  */
         UWORD   da_DiagPoint;     /*     be copied into RAM       */
         UWORD   da_BootPoint;
         UWORD   da_Name;
         UWORD   da_Reserved01;
         UWORD   da_Reserved02;
     };

    /* da_Config definitions */
    #define DAC_BUSWIDTH    0xC0  /* two bits for bus width */
    #define DAC_NIBBLEWIDE  0x00
    #define DAC_BYTEWIDE    0x40  /* invalid for 1.3 - see note below */
    #define DAC_WORDWIDE    0x80

    #define DAC_BOOTTIME    0x30  /* two bits for when to boot */
    #define DAC_NEVER       0x00  /* obvious */
    #define DAC_CONFIGTIME  0x10  /* call da_BootPoint when first
                                     configging the device */
    #define DAC_BINDTIME    0x20  /* run when binding drivers to boards */

Next, expansion tests the first byte of the DiagArea structure to
determine if the CONFIGTIME bit is set.  If this bit is set, it checks the
da_BootPoint offset vector to make sure that a valid bootstrap routine
exists.  If so, expansion copies da_Size bytes into RAM memory, starting
at beginning of the DiagArea structure.

The copy will include the DiagArea structure itself, and typically will
also include the da_DiagPoint ROM/diagnostic routine, a Resident structure
(romtag), a device driver (or at least the device initialization tables or
structures which need patching), and the da_BootPoint routine.  In
addition, the BootNode and parameter packet for MakeDosNode() may be
included in the copy area for Diag-time patching.  Strings such as DOS and
Exec device names, library names, and the romtag ID string may also be
included in the copy area so that both position-independent ROM code and
position-independent routines in the copy area may reference them PC
relative.

The copy will be made either nibblewise, or wordwise, according to the
BUSWIDTH subfield of da_Config. Note that the da_BootPoint offset must be
non-NULL, or else no copy will occur. (Note - under 1.3, DAC_BYTEWIDE is
not supported. Byte wide ROMs must use DAC_NIBBLEWIDE and drivers must
supply additional code to re-copy their DiagArea)

The following illustrates an example Diag copy area, and specifies the
various fields which should be coded as relative offsets for later
patching by your DiagPoint routine.

                      Example DiagArea Copy in RAM

DiagStart:          ; a struct DiagArea
            CCFF    ; da_Config, da_Flags
            SIZE    ; da_Size         - coded as EndCopy-DiagStart
            DIAG    ; da_DiagPoint    - coded as DiagEntry-DiagStart
            BOOT    ; da_BootPoint    - coded as BootEntry-DiagStart
            NAME    ; da_Name         - coded as DevName-DiagStart
            0000    ; da_Reserved01   - Above fields above are supposed
            0000    ; da_Reserved02     to be relative. No patching needed

Romtag:     rrrr    ; a struct Resident ("Romtag")
            ...       RT_MATCHTAG, RT_ENDSKIP, RT_NAME and  RT_IDSTRING
            ...       addresses are coded relatively as label-DiagStart.
            ...       The RT_INIT vector is coded as a relative offset
            ...       from the start of the ROM.  DiagEntry patches these.

DevName:    ssss..0 ; The name string for the exec device
IdString:   iiii..0 ; The ID string for the Romtag

BootEntry:  BBBB    ; Boot-time code
            ...

DiagEntry:  DDDD    ; Diag-time code (position independent)
            ...       When called, performs patching of the relative-
                      coded addresses which need to be absolute.
OtherData:
            dddd    ; Device node or structs/tables (patch names, vectors)
            bbbb    ; BootNode (patch ln_Name and bn_DeviceNode)
            pppp    ; MakeDosNode packet (patch dos and exec names)

            ssss    ; other name, ID, and library name strings
            ...
EndCopy:

Now the ROM "image" exists in RAM memory.  Expansion stores the ULONG
address of that "image" in the UBYTES er_Reserved0c, 0d, 0e and 0f.  The
address is stored with the most significant byte in er_Reserved0c, the
next to most significant byte in er_Reserved0d, the next to least
significant byte in er_Reserved0e, and the least significant byte in
er_Reserved0f - i.e., it is stored as a longword at the address
er_Reserved0c.

Expansion finally checks the da_DiagPoint offset vector, and if valid
executes the ROM/diagnostic routine contained as part of the ROM "image".
This diagnostic routine is responsible for patching the ROM image so that
required absolute addresses are relocated to reflect the actual location
of code and strings, as well as performing any diagnostic functions
essential to the operation of its associated AUTOCONFIG board. The
structures which require patching are located within the copy area so that
they can be patched at this time. Patching is required because many of the
structures involved require absolute pointers to such things as name
strings and code, but the absolute locations of the board and the RAM copy
area are not known when code the structures.

The patching may be accomplished by coding pointers which require absolute
addresses instead as relative offsets from either the start of the
DiagArea structure, or the start of the board's ROM (depending on whether
the final absolute pointer will point to a RAM or ROM location). The Diag
routine is passed both the actual base address of the board, and the
address of the Diag copy area in RAM. The routine can then patch the
structures in the Diag copy area by adding the appropriate address to
resolve each pointer.

Example DiagArea and Diag patching routine:

     Diag.asm

Your da_DiagPoint ROM/diagnostic routine should return a non-zero value to
indicate success;  otherwise the ROM "image" will be unloaded from memory,
and its address will be replaced with NULL bytes in locations
er_Reserved0c, 0d, 0e and 0f.

Now that the ROM "image" has been copied into RAM, validated, and linked
to board's ConfigDev structure, the expansion module is free to configure
all other boards on the utility.library's private list of boards.

It may help to see just how a card's ROM AUTOCONFIG information
corresponds to the ExpansionRom structure.  This chart shows the contents
of on-card memory for a fictional expansion card.  Note that the
ExpansionRom.Flags field ($3F in addresses $08/$0A below) is shown
interpreted in its inverted form of $3F.  Once the value is uninverted to
become $C0, you should use the #defines in <libraries/configregs.h> to
interpret it.

Table 32-1: Sample Zorro II AUTOCONFIG ROM Information Viewed as a Hex Dump

            FLAG AND FIELD DEFINITIONS                THIS BOARD
    -----------------------------------------------------------------
              1xxx chained                          11 = Normal type
              x111 size                             Don't addmem
              000=8meg,001=64K,010=128K,etc.        ROM Vector Valid
     11xx type     /        1xxx nopref             Not chained
     xx1x addmem  /         x1xx canshut            Size 256K
     xxx1 ROM    /          xx11 reserved           Product#=~$FE=1
        \       / ~Prod#      /                     Flags=~$3F=$C0
         \     /   /  \      /  res. reserved       Prefer exp space
    0000: D0003000 F000E000 3000F000 F000F000       Can't be shut up
    -----------------------------------------------------------------
          ~Manufacturer#    ~HiWord Serial#    Manu#=~$F824=$7DB=2011
           /   /  \   \      /   /  \   \      HiSer=~$FFDA=$0025=37
    0010: F0008000 20004000 F000F000 D000A000
    -----------------------------------------------------------------
          ~LoWord Serial#    ~Rom Vector       LoSer=~$FFFE=$0001=1
           /   /  \ \      /   /  \   \      Rom Vector=~$FF7F=$80
    0020: F000F000 F000E000 F000F000 7000F000        from board base
    -----------------------------------------------------------------

The AUTOCONFIG information from the above card would appear as follows in
an ExpansionRom structure:

        Nibble Pairs        ExpansionRom Field    Value
        ------------        ------------------    -----
        00/02               er_Type               $D3
        04/06               er_Product            $01 = 1
        08/0A               er_Flags              $C0
        10/12 and 14/16     er_Manufacturer       $07DB = 2011
        18/1A thru 24/26    er_SerialNumber       $00250001
        28/2A and 2C/2E     er_InitDiagVec        $0080

If a card contains a ROM driver (Rom Vector valid), and the vector is at
offset $80 (as in this example) the DiagArea structure will appear at
offset $0080 from the base address of the board.  This example card's
Resident structure (romtag) directly follows its DiagArea structure.

       WORDWIDE+CONFIGTIME              ROMTAG
        \ flags    DiagPt   Devname     starts
         \ \ DAsize  / BootPt /          here       DiagPt, BootPt,
          \ \  /\   /\  /\   /\ res. res. /\        DevName relative
    0080: 90000088 004A0076 00280000 00004AFC       to Diag struct
    -----------------------------------------------------------------
                       COLDSTART  NT_DEVICE         backptr,endskip,
                           \ ver  /priority         and DevName coded
          backptr  endskip  \ \  / /  DevName       relative, patched
    0090: 0000000E 00000088 01250314 00000028       at Diag time
    -----------------------------------------------------------------
                                                    ID and InitEntry
          IDstring InitEntry                        coded relative,
    00A0: 00000033 00000116                         patched at Diag
    -----------------------------------------------------------------


32 / / ROM Based and Autoboot Drivers / Events At ROMTAG INIT Time

Next, most resident system modules (for example graphics) are initialized.
As part of the system initialization procedure a search is made of the
expansion.library's private list of boards (which contains a ConfigDev
structure for each of the AUTOCONFIG hardware boards). If the cd_Flags
specify CONFIGME and the er_Type specifies DIAGVALID, the system
initialization will do three things:

First, it will set the current ConfigDev as the current binding (see the
expansion.library SetCurrentBinding() function).  Second, it will check
the DiagArea's da_Config flag to make sure that the CONFIGTIME bit is set.
Third, it will search the ROM "image" associated with this hardware board
for a valid Resident structure (<exec/resident.h>); and, if one is
located, will call InitResident() on it, passing a NULL segment list
pointer as part of the call.

Next, the board's device driver is initialized.  The Resident structure
associated with this board's device driver (which has now been patched by
the ROM/diagnostic routine) should follow standard system conventions in
initializing the device driver provided in the boot ROMs.  This driver
should obtain the address of its associated ConfigDev structure via
GetCurrentBinding().

Once the driver is initialized, it is responsible for some further steps.
It must clear the CONFIGME bit in the cd_Flags of its ConfigDev structure,
so that the system knows not to configure this device again if binddrivers
is run after bootstrap.  Also, though it is not currently mandatory, the
driver should place a pointer to its Exec node in the cd_Driver field of
the ConfigDev structure.  This will generally be a device (NT_DEVICE)
node.  And for this device to be bootable, the driver must create a
BootNode structure, and link this BootNode onto the expansion.library's
eb_MountList.

The BootNode structure (see <libraries/expansionbase.h>) contains a Node
of the new type NT_BOOTNODE (see <exec/nodes.h>).  The driver must
initialize the ln_Name field to point to the ConfigDev structure which it
has obtained via the GetCurrentBinding() call.  The bn_Flags subfield is
currently unused and should be initialized to NULL.  The bn_DeviceNode
must be initialized to point to the DosNode for the device.

When the DOS is initialized later, it will attempt to boot from the first
BootNode on the eb_MountList.  The eb_MountList is a priority sorted List,
with nodes of the highest priority at the head of the List.  For this
reason, the device driver must enqueue a BootNode onto the list using the
Exec library function Enqueue().

In the case of an autoboot of AmigaDOS, the BootNode must be linked to a
DeviceNode of the AmigaDOS type (see <libraries/filehandler.h>), which the
driver can create via the expansion library MakeDosNode() function call.
When the DOS "wakes up", it will attempt to boot from this DeviceNode.


32 / / ROM Based and Autoboot Drivers / Events At BOOT Time

If there is no boot disk in the internal floppy drive, the system strap
module will call a routine to perform autoboot. It will examine the
eb_MountList; find the highest priority BootNode structure at the head of
the List; validate the BootNode; determine which ConfigDev is associated
with this BootNode; find its DiagArea; and call its da_BootPoint function
in the ROM "image" to bootstrap the appropriate DOS.  Generally, the
BootPoint code of a ROM driver will perform the same function as the boot
code installed on a floppy disk, i.e., it will FindResident() the
dos.library, and jump to its RT_INIT vector.  The da_BootPoint call, if
successful, should not return.

If a boot disk is in the internal floppy drive, the system strap will
Enqueue() a BootNode on the eb_MountList for DF0: at the suggested
priority (see the Autodoc for the expansion.library AddDosNode()
function).  Strap will then open AmigaDOS, overriding the autoboot.
AmigaDOS will boot from the highest priority node on the eb_MountList
which should, in this case, be DF0:.  Thus, games and other bootable
floppy disks will still be able to obtain the system for their own use.

In the event that there is no boot disk in the internal floppy drive and
there are no ROM bootable devices on the autoconfiguration chain, the
system does the normal thing, asking the user to insert a Workbench disk,
and waiting until its request is satisfied before proceeding.


32 / Expansion Board Drivers / RigidDiskBlock and Alternate Filesystems

Through the use of RigidDiskBlock information and the FileSys.resource, it
is possible for an autoboot driver to have access to enough information to
mount all of its device partitions and even load alternate filesystems for
use with these partitions.

The RigidDiskBlock specification (also known as "hardblocks") defines
blocks of data that exist on a hard disk to describe that disk.  These
blocks are created or modified with an installation utility (such as the
hard drive Prep utility for the A2090A ST506/SCSI controller card)
provided by the disk controller manufacturer, and they are read and used
by the device driver ROM (or expansion) code.  They are not generally
accessible to the user as they do not appear on any DOS device.  The
blocks are tagged with a unique identifier, checksummed, and linked
together.

The five block types currently defined are RigidDiskBlock, BadBlockBlock,
PartitionBlock, FileSysHeaderBlock, and LoadSegBlock.

The root of these blocks is the RigidDiskBlock.  The RigidDiskBlock must
exist on the disk within the first RDB_LOCATION_LIMIT (16) blocks.  This
inhibits the use of the first cylinder(s) in an AmigaDOS partition:
although it is strictly possible to store the RigidDiskBlock data in the
reserved area of a partition, this practice is discouraged since the
reserved blocks of a partition are overwritten by Format, Install,
DiskCopy, etc.  The recommended disk layout, then, is to use the first
cylinder(s) to store all the drive data specified by these blocks: i.e.
partition descriptions, file system load images, drive bad block maps,
spare blocks, etc.  This allocation range is described in the
RigidDiskBlock.

The RigidDiskBlock contains basic information about the configuration of
the drive: number and size of blocks, tracks, and cylinders, as well as
other relevant information.  The RigidDiskBlock points to bad block,
partition, file system and drive initialization description blocks.

The BadBlockBlock list contains a series of bad-block/good-block pairs.
Each block contains as many as will fit in a physical sector on the drive.
These mappings are to be handled by the driver on read and write requests.

The drive initialization description blocks are LoadSegBlocks that are
loaded at boot time to perform drive-specific initialization.  They are
called with both C-style parameters on the stack, and assembler parameters
in registers as follows:

      d0  =  DriveInit(lun, rdb, ior)(d0/a0/a1)

where lun is the SCSI logical unit number (needed to construct SCSI
commands), rdb is a pointer to a memory copy of the RigidDiskBlock (which
should not be altered), and ior is a standard IO request block that can be
used to access the drive with synchronous DoIO() calls.

The result of DriveInit() is either -1, 0, or 1.  A -1 signifies that an
error occurred and drive initialization cannot continue.  A 0 (zero)
result reports success. In cases -1 and 0, the code is unloaded.  A result
of 1 reports success, and causes the code to be kept loaded.  Furthermore,
this resident code will be called whenever a reset is detected on the SCSI
bus.

The FileSysHeaderBlock entries contain code for alternate file handlers to
be used by partitions.  There are several strategies that can be used to
determine which of them to load. The most robust would scan all drives for
those that are both required by partitions and have the highest
fhb_Version, and load those. Whatever method is used, the loaded file
handlers are added to the Exec resource FileSystem.resource, where they
are used as needed to mount disk partitions.

The PartitionBlock entries contains most of the data necessary to add each
partition to the system.  They replace the Mount and DEVS:MountList
mechanism for adding these partitions. The only items required by the
expansion.library MakeDosNode() function which are not in this partition
block are the Exec device name and unit, which is expected to be known by
driver reading this information.  The file system to be used is specified
in the pb_Environment.  If it is not the default file system (i.e.,
'DOS\\0' or 'DOS\\1'), the node created by MakeDosNode() is modified as
specified in a FileSystem.resource's FileSysEntry before adding it to the
DOS list.

Only 512 byte blocks were supported by the pre-V36 file system, but this
proposal was forward-looking by making the block size explicit, and by
using only the first 256 bytes for all blocks but the LoadSeg and BadBlock
data.  Under the present filesystem, this allows using drives formatted
with sectors 256 bytes or larger (i.e., 256, 512, 1024, etc).  LoadSeg and
BadBlock data use whatever space is available in a sector.

 RigidDiskBlock    PartitionBlock        LoadSegBlock
 BadBlockBlock     FileSysHeaderBlock    filesysres.h and .i


32 / / RigidDiskBlock and Alternate Filesystems / RigidDiskBlock

This is the current specification for the RigidDiskBlock:

   rdb_ID              == 'RDSK'
   rdb_SummedLongs     == 64

   rdb_ChkSum          block checksum (longword sum to zero)

   rdb_HostID          SCSI Target ID of host
                       This is the initiator ID of the creator of this
                       RigidDiskBlock.  It is intended that
                       modification of the RigidDiskBlock, or of any
                       of the blocks pointed to by it, by another
                       initiator (other than the one specified here)
                       be allowed only after a suitable warning.  The
                       user is then expected to perform an audio
                       lock out ("Hey, is anyone else setting up SCSI
                       stuff on this bus?").  The rdb_HostID may
                       become something other than the initiator ID
                       when connected to a real network: that is an
                       area for future standardization.

   rdb_BlockBytes      size of disk blocks
                       Under pre-V36 filesystem, this must be 512 for
                       a disk with any AmigaDOS partitions on it.
                       Present filesystem supports 256, 512, 1024, etc.

   rdb_Flags           longword of flags:

       RDBF._LAST          no disks exist to be configured after this
                           one on this controller (SCSI bus).

       RDBF._LASTLUN       no LUNs exist to be configured greater
                           than this one at this SCSI Target ID

       RDBF._LASTTID       no Target IDs exist to be configured
                           greater than this one on this SCSI bus

       RDBF._NORESELECT    don't bother trying to perform reselection
                           when talking to this drive

       RDBF._DISKID        rdb_Disk... identification variables below
                           contain valid data.

       RDBF._CTRLRID       rdb_Controller... identification variables
                           below contain valid data.

       RDBF._SYNCH         drive supports scsi synchronous mode
                           CAN BE DANGEROUS TO USE IF IT DOESN'T!

These fields point to other blocks on the disk which are not a part of any
filesystem.  All block pointers referred to are block numbers on the drive.

   rdb_BadBlockList        optional bad block list
                           A singly linked list of blocks of type
                           PartitionBlock

   rdb_PartitionList       optional first partition block
                           A singly linked list of blocks of type
                           PartitionBlock

   rdb_FileSysHeaderList   optional file system header block
                           A singly linked list of blocks of type
                           FileSysHeaderBlock

   rdb_DriveInit           optional drive-specific init code
                           A singly linked list of blocks of type
                           LoadSegBlock containing initialization code.
                           Called as DriveInit(lun,rdb,ior)(d0/a0/a1).

   rdb_Reserved1[6]        set to $ffffffffs
                           These are reserved for future block lists.
                           Since NULL for block lists is $ffffffff, these
                           reserved entries must be set to $ffffffff.

These fields describe the physical layout of the drive.

   rdb_Cylinders           number of drive cylinders
   rdb_Sectors             sectors per track
   rdb_Heads               number of drive heads

   rdb_Interleave          interleave
                           This drive interleave is independent from, and
                           unknown to, the DOS's understanding of
                           interleave as set in the partition's
                           environment vector.

   rdb_Park                landing zone cylinder
   rdb_Reserved2[3]        set to zeros

These fields are intended for ST506 disks.  They are generally unused for
SCSI devices and set to zero.

   rdb_WritePreComp        starting cylinder: write precompensation
   rdb_ReducedWrite        starting cylinder: reduced write current
   rdb_StepRate            drive step rate
   rdb_Reserved3[5]        set to zeros

These fields are used while partitions are set up to constrain the
partitionable area and help describe the relationship between the drive's
logical and physical layout.

   rdb_RDBlocksLo          low block of the range allocated for
                           blocks described here.  Replacement blocks
                           for bad blocks may also live in this range.

   rdb_RDBlocksHi          high block of this range (inclusive)

   rdb_LoCylinder          low cylinder of partitionable disk area
                           Blocks described by this include file will
                           generally be found in cylinders below this one.

   rdb_HiCylinder          high cylinder of partitionable data area
                           Usually rdb_Cylinders-1.

   rdb_CylBlocks           number of blocks available per cylinder
                           This may be rdb_Sectors*rdb_Heads, but a SCSI
                           disk that, for example, reserves one block per
                           cylinder for  bad block mapping would use
                           rdb_Sectors*rdb_Heads-1.

   rdb_AutoParkSeconds     number of seconds to wait before parking
                           drive heads automatically.  If zero, this
                           feature is not desired.

   rdb_HighRDSKBlock       highest block used by these drive definitions
                           Must be less than or equal to rdb_RDBBlocksHi.
                           All replacements for bad blocks should be
                           between rdb_HighRDSKBlock+1 and rdb_RDBBlocksHi
                           (inclusive).

   rdb_Reserved4           set to zeros

These fields are of the form available from a SCSI Identify command.
Their purpose is to help the user identify the disk during setup.  Entries
exist for both controller and disk for non-embedded SCSI disks.

   rdb_DiskVendor          vendor name of the disk
   rdb_DiskProduct         product name of the disk
   rdb_DiskRevision        revision code of the disk
   rdb_ControllerVendor    vendor name of the disk controller
   rdb_ControllerProduct   product name of the disk controller
   rdb_ControllerRevision  revision code of the disk controller
   rdb_Reserved5[10]       set to zeros


32 / / RigidDiskBlock and Alternate Filesystems / BadBlockBlock

This is the current specification for the BadBlockBlock. The end of data
occurs when bbb_Next is NULL ($FFFFFFFF), and the summed data is exhausted.

   bbb_ID                  == 'BADB'

   bbb_SummedLongs         size of this checksummed structure
                           Note that this is not 64 like most of the other
                           structures.  This is the number of valid longs
                           in this image, and can be from 6 to
                           rdb_BlockBytes/4.  The latter is the best size
                           for all blocks other than the last one.

   bbb_ChkSum              block checksum (longword sum to zero)

   bbb_HostID              SCSI Target ID of host
                           This describes the initiator ID for the creator
                           of these blocks.  (see rdb_HostID discussion)

   bbb_Next                block number of the next BadBlockBlock
   bbb_Reserved            set to zeros

   bbb_BlockPairs[61]      pairs of block remapping information
                           The data starts here and continues as long as
                           indicated by bbb_SummedLongs-6: e.g. if
                           bbb_SummedLongs is 128 (512 bytes), 61 pairs
                           are described here.


32 / / RigidDiskBlock and Alternate Filesystems / PartitionBlock

This is the current specification for the PartitionBlock. Note that while
reading these blocks you may encounter partitions that are not to be
mounted because the pb_HostID does not match, or because the pb_DriveName
is in use and no fallback strategy exists, or because PBF._NOMOUNT is set,
or because the proper filesystem cannot be found.  Some partitions may be
mounted but not be bootable because PBF._BOOTABLE is not set.

   pb_ID                   == 'PART'
   pb_SummedLongs          == 64
   pb_ChkSum               block checksum (longword sum to zero)

   pb_HostID               SCSI Target ID of host
                           This describes the initiator ID for the owner
                           of this partition.  (see rdb_HostID discussion)

   pb_Next                 block number of the next PartitionBlock

   pb_Flags                see below for defines

       PBF._BOOTABLE       this partition is intended to be bootable
                           (e.g. expected directories and files exist)

       PBF._NOMOUNT        this partition description is to reserve
                           space on the disk without mounting it.
                           It may be manually mounted later.
   pb_Reserved1[2]         set to zeros

   pb_DevFlags             preferred flags for OpenDevice
   pb_DriveName            preferred DOS device name: BSTR form
                           This name is not to be used if it is already
                           in use.

Note that pb_Reserved2 will always be at least 4 longwords so that the RAM
image of this record may be converted to the parameter packet to the
expansion.library function MakeDosNode().

   pb_Reserved2[15]        filler to make 32 longwords so far

The specification of the location of the partition is one of the
components of the environment, below.  If possible, describe the partition
in a manner that tells the DOS about the physical layout of the partition:
specifically, where the cylinder boundaries are.  This allows the
filesystem's smart block allocation strategy to work.

   pb_Environment[17]      environment vector for this partition
                           containing:

       de_TableSize        size of Environment vector
       de_SizeBlock        == 128 (for 512 bytes/logical block)
       de_SecOrg           == 0
       de_Surfaces         number of heads (see layout discussion)
       de_SectorPerBlock   == 1
       de_BlocksPerTrack   blocks per track (see layout discussion)

       de_Reserved         DOS reserved blocks at start of partition.
                           Must be >= 1.  2 is recommended.

       de_PreAlloc         DOS reserved blocks at end of partition
                           Valid only for filesystem type DOS^A (the
                           fast file system).  Zero otherwise.

       de_Interleave       DOS interleave
                           Valid only for filesystem type DOS^@ (the
                           old file system).  Zero otherwise.

       de_LowCyl           starting cylinder
       de_HighCyl          max cylinder
       de_NumBuffers       initial # DOS of buffers.

       de_BufMemType       type of mem to allocate for buffers
                           The second argument to AllocMem().

       de_MaxTransfer      max number of bytes to transfer at a time.
                           Drivers should be written to handle requests
                           of any length.

       de_Mask             address mask to block out certain memory
                           Normally $00ffffff  for DMA devices.

       de_BootPri          Boot priority for autoboot
                           Suggested value: zero.  Keep less than
                           five, so it won't override a boot floppy.

       de_DosType          ASCII string showing filesystem type;
                           DOS^@ ($444F5300) is old filesystem,
                           DOS^A ($444F5301) is fast file system.
                           UNI<anything> is a Unix partition.

   pb_EReserved[15]        reserved for future environment vector


32 / / RigidDiskBlock and Alternate Filesystems / FileSysHeaderBlock

The current specification for the FileSysHeaderBlock follows.

   fhb_ID                  == 'FSHD'
   fhb_SummedLongs         == 64
   fhb_ChkSum              block checksum (longword sum to zero)

   fhb_HostID              SCSI Target ID of host
                           This describes the initiator ID for the
                           creator of this block.  (see rdb_HostID
                           discussion)

   fhb_Next                block number of next FileSysHeaderBlock
   fhb_Flags               see below for defines
   fhb_Reserved1[2]        set to zero

The following information is used to construct a FileSysEntry node in the
FileSystem.resource.

   fhb_DosType             file system description
                           This is matched with a partition environment's
                           de_DosType entry.

   fhb_Version             release version of this load image
                           Usually MSW is version, LSW is revision.

   fhb_PatchFlags          patch flags
                           These are bits set for those of the following
                           that need to be substituted into a standard
                           device node for this file system, lsb first:
                           e.g. 0x180 to substitute SegList & GlobalVec

   fhb_Type                device node type: zero
   fhb_Task                standard dos "task" field: zero
   fhb_Lock                not used for devices: zero
   fhb_Handler             filename to loadseg: zero placeholder
   fhb_StackSize           stacksize to use when starting task
   fhb_Priority            task priority when starting task
   fhb_Startup             startup msg: zero placeholder

   fhb_SegListBlocks       first of linked list of LoadSegBlocks:
                           Note that if the fhb_PatchFlags bit for this
                           entry is set (bit 7), the blocks pointed to by
                           this entry must be LoadSeg'd and the resulting
                           BPTR put in the FileSysEntry node.

   fhb_GlobalVec           BCPL global vector when starting task
                           Zero or -1.

   fhb_Reserved2[23]       (those reserved by PatchFlags)
   fhb_Reserved3[21]       set to zero


32 / / RigidDiskBlock and Alternate Filesystems / LoadSegBlock

This is the current specification of the LoadSegBlock. The end of data
occurs when lsb_Next is NULL ($FFFFFFFF), and the summed data is exhausted.

   lsb_ID                  == 'LSEG'

   lsb_SummedLongs         size of this checksummed structure
                           Note that this is not 64 like most of the other
                           structures.  This is the number of valid longs
                           in this image, like bbb_SummedLongs.

   lsb_ChkSum              block checksum (longword sum to zero)

   lsb_HostID              SCSI Target ID of host
                           This describes the initiator ID for the creator
                           of these blocks.  (see rdb_HostID discussion)

   lsb_Next                block number of the next LoadSegBlock

   lsb_LoadData            data for "loadseg"
                           The data starts here and continues as long
                           as indicated by lsb_SummedLongs-5: e.g. if
                           lsb_SummedLongs is 128 (ie. for 512 byte
                           blocks), 123 longs of data are valid here.


32 / / RigidDiskBlock and Alternate Filesystems / filesysres.h and .i

The FileSysResource is created by the first code that needs to use it.  It
is added to the resource list for others to use. (Checking and creation
should be performed while Forbid() is in effect).  Under Release 2 the
resource is created by the system early on in the initialization sequence.
Under 1.3 it is the responsibility of the first RDB driver to create it.

 FileSysResource

   fsr_Node              on resource list with the name FileSystem.resource
   fsr_Creator           name of creator of this resource
   fsr_FileSysEntries    list of FileSysEntry structs

 FileSysEntry

   fse_Node              on fsr_FileSysEntries list
                         ln_Name is of creator of this entry
   fse_DosType           DosType of this FileSys
   fse_Version           release version of this FileSys
                         Usually MSW is version, LSW is revision.

   fse_PatchFlags        bits set for those of the following that
                         need to be substituted into a standard
                         device node for this file system: e.g.
                         $180 for substitute SegList & GlobalVec

   fse_Type              device node type: zero
   fse_Task              standard dos "task" field
   fse_Lock              not used for devices: zero
   fse_Handler           filename to loadseg (if SegList is null)
   fse_StackSize         stacksize to use when starting task
   fse_Priority          task priority when starting task
   fse_Startup           startup msg: FileSysStartupMsg for disks
   fse_SegList           segment of code to run to start new task
   fse_GlobalVec         BCPL global vector when starting task

   No more entries need exist than those implied by fse_PatchFlags, so
   entries do not have a fixed size.

For additional information on initializing and booting a Rigid Disk Block
filesystem device, see the SCSI Device chapter of the Addison-Wesley Amiga
ROM Kernel Reference Manual: Devices. Writers of drivers for expansion
devices that perform their own DMA (direct memory access) should consult
the Exec chapters and Autodocs for information on Release 2 processor
cache control functions including CachePreDMA() and CachePostDMA(). See
the following include files for additional notes and related structures:
<libraries/configvers.h> and <.i>, <libraries/configregs.h> and <.i>,
<devices/hardblocks.h> and <.i>, <resources/filesysres.h> and <.i>, and
<libraries/filehandler.h> and <.i>.


32 Expansion Library / Function Reference

The following are brief descriptions of the expansion library functions
that are useful for expansion device drivers and related applications.
See the Amiga ROM Kernel Reference Manual: Includes and Autodocs for the
complete descriptions of all the expansion library functions.

                 Table 32-2: Expansion Library Functions
  ______________________________________________________________________
 |                                                                      |
 |            Function                 Description                      |
 |======================================================================|
 |          FindConfigDev()  Returns a pointer to the ConfigDev         |
 |                           structure of a given expansion device.     |
 |----------------------------------------------------------------------|
 |            MakeDosNode()  Creates the DOS device node for disk and   |
 |                           similar expansion devices.                 |
 |             AddDosNode()  Adds a DOS device node to the system.      |
 |            AddBootNode()  Adds an autobooting DOS device node to the |
 |                           system (V36).                              |
 |----------------------------------------------------------------------|
 |      GetCurrentBinding()  Returns a pointer to the CurrentBinding    |
 |                           structure of a given device.               |
 |      SetCurrentBinding()  Set up for reading the CurrentBinding with |
 |                           GetCurrentBinding().                       |
 |    ObtainConfigBinding()  Protect the ConfigDev structure with a     |
 |                           semaphore.                                 |
 |   ReleaseConfigBinding()  Release a semaphore on ConfigDev set up    |
 |                           with ObtainCurrentBinding().               |
 |______________________________________________________________________|


Amiga® RKM Libraries: 33 IFFParse Library

The iffparse.library was created to help simplify the job of parsing IFF
files.  Unlike other IFF libraries, iffparse.library is not form-specific.
This means that the job of interpreting the structure and contents of the
IFF file is up to you.  Previous IFF file parsers were either simple but
not general, or general but not simple.  IFFParse tries to be both simple
and general.

 The Structure of IFF Files    Error Handling
 Parsing an IFF File           Advanced Topics
 Stream Management             IFF FORM Specifications
 Parsing                       IFFParse Examples
 Writing IFF Files             Function Reference
 Context Functions


33 IFFParse Library / The Structure of IFF Files

Many people have a misconception that IFF means image files.  This is not
the case.  IFF (short for Interchange File Format) is a method of portably
storing structured information in machine-readable form. The actual
information can be anything, but the manner in which it is stored is very
specifically detailed.  This specification is the IFF standard.

The IFF standard was originally designed in 1985 by Electronic Arts in
conjunction with a committee of developers.  The full standard along with
file descriptions and sample code is published in the Amiga ROM Kernel
Reference Manual: Devices (3rd edition).

The goal of the IFF standard is to allow customers to move their own data
between independently developed software products.  The types of data
objects to exchange are open-ended and currently include plain and
formatted text, raster and structured graphics, fonts, music, sound
effects, musical instrument descriptions, and animation.  IFF addresses
these needs by defining a standard for self-identifying file structures
and rules for accessing these files.

 Chunks: The Building Blocks of IFF    Composite Data Types


33 / The Structure of IFF Files / Chunks: The Building Blocks of IFF

IFF files contain various types and amounts of data grouped in data
chunks, each starting with a four-letter ASCII identifier (the chunk ID)
followed by a 32-bit length count (the chunk size).  The identifier and
length count make it possible for IFF readers to skip over chunks that
they don't understand or don't care about, and extract only the
information they need.  It may be helpful to think of these chunks as the
building blocks of an IFF file (Figure 33-1).

          Figure 33-1: The Chunk - The Building Block of IFF
                       ________________________
                      |                        |
                      |  `CKID' Size           |
                      |------------------------|
                      |  data data data data   |
                      |  data data data data   |
                      |  data data data ...    |
                      |________________________|

The `CKID' (chunk ID) characters of a real chunk will be a four letter
identifier such as `BODY' or `CMAP', specifying the type and format of
data stored in the chunk.  Most chunks contain a simple defined grouping
of byte, word, and long variables similar to the contents of a C
structure.  Others such as sound sample and bitmap image body chunks,
contain a stream of compressed data.

Chunk writing is fairly straightforward with the one caveat that all
chunks must be word-aligned.  Therefore an odd-length chunk must be
followed by a pad byte of zero (which is not counted in the size of the
chunk).  When chunks are nested, the enclosing chunk must state the total
size of its composite contents (including any pad bytes).

    About Chunk Length.
    -------------------
    Every IFF data chunk begins with a 4-character identifier field
    followed by a 32-bit size field (these 8 bytes are sometimes referred
    to as the chunk header).  The size field is a count of the rest of
    the data bytes in the chunk, not including any pad byte.  Hence,
    the total space occupied by a chunk is given by its size field
    (rounded to the nearest even number) + 8 bytes for the chunk header.


33 / The Structure of IFF Files / Composite Data Types

Standard IFF files generally contain a variable number of chunks within
one of the standard IFF composite data types (which may be thought of as
chunks which contain other chunks).  The IFF specification defines three
basic composite data types, `FORM', `CAT ', and `LIST'.  A special
composite data type, the `PROP', is found only inside a LIST.

              Table 33-1: Usage of Composite IFF Types

        FORM  A grouping of chunks which describe one set of data
        LIST  A grouping of the same type of FORMs with shared
              properties in a PROP
        PROP  May appear in a LIST to define chunks shared by
              several FORMs
        CAT   A concatenation of related FORMs or LISTs

The special IFF composite data types, like simple chunks, start with a
4-character identifier (such as `FORM'), followed by a 32-bit length.  But
their data begins with a second 4-character identifier that tells you what
type of data is in the composite.  For example, a FORM ILBM contains
chunks describing a bitmap image, and a FORM FTXT contains chunks
describing formatted text.

It may help to think of each composite data type as a box containing
chunks, the IFF building blocks.  Figure 33-2 shows a diagram of a
typical composite.

        Figure 33-2: The FORM - The Most Common IFF File Type
                        ____________________
                       |                    |
                       | `FORM' Size `NAME' |
                       |  ________________  |
                       | |                | |
                       | | `CKID' Size    | |
                       | | data data data | |
                       | | data data ...  | |
                       | |________________| |
                       |  ________________  |
                       | |                | |
                       | | `CKID' Size    | |
                       | | data data data | |
                       | | data data ...  | |
                       | |________________| |
                       |  ________________  |
                       | |                | |
                       | | `CKID' Size    | |
                       | | data data data | |
                       | | data data ...  | |
                       | |________________| |
                       |____________________|

The example FORM in figure 33-2 is outlined below showing the size of
chunks within the FORM.  Notice that the size of a composite includes its
second 4-character identifier (shown below as `NAME').

 .FORM 72 NAME  (72 is the size of the FORM starting with the "N" of NAME)
 ..CKID 22     (then 22 bytes of data, so chunk header + chunk size is 30)
 ..CKID 10     (then 10 bytes of data, so chunk header + chunk size is 18)
 ..CKID 12     (then 12 bytes of data, so chunk header + chunk size is 20)

    Note
    ----
    In the example above, indentation represents the nesting of the
    chunks within the FORM.  Real FORMs and chunks would have different
    four-character identifiers rather than `NAME' and `CKID':

Any odd-length chunks must have a pad byte of zero at the end of the
chunk.  As shown below, this pad byte is not counted in the size of the
chunk but is counted in the size of any composite types (such as FORM)
that contain an odd-length chunk.  Warning: some IFF readers and writers
do not deal with this properly.

 .FORM 72 NAME  (72 is the size of the FORM starting with the "N" of NAME)
 ..CKID 21     (then 21 bytes of data, so chunk header + chunk size is 29)
 ..0           (pad byte of zero, size 1)
 ..CKID 10     (then 10 bytes of data, so chunk header + chunk size is 18)
 ..CKID 12     (then 12 bytes of data, so chunk header + chunk size is 20)

Most IFF files are of the composite type FORM.  Generally, a FORM is a
simple grouping of chunks that provide information about some data, and
the data itself.  Although some standard chunks have common usage within
different FORMS, the identity and format of most chunks within a FORM are
relative to the definition and specification of the FORM.  For example, a
CRNG chunk in a FORM ILBM may have a totally different format and contents
than a chunk named CRNG in a different type of FORM.

One of the most popular IFF FORMs that has been defined is the ILBM
standard.  This is how most Amiga bitmap imagery is stored.  Since this is
the most common IFF file, it is used frequently as an example.

Here is the output of a program called Sift.c that displays a text
description of the contents of an IFF file (Sift.c is listed at the end of
this chapter).  The file shown below is a fairly simple ILBM.

                .FORM 11068 ILBM
                ..BMHD 20
                ..CAMG 4
                ..CMAP 12
                ..BODY 10995

    Computing the Size of a FORM.
    -----------------------------
    The size of the FORM (11068 bytes) is equal to the sum of the sizes
    stated in each chunk contained within the FORM, plus 8 bytes for the
    overhead of each chunk header (4 bytes for the 4-character chunk ID,
    and 4 bytes for the 32-bit chunk size), plus 4 bytes for the FORM's
    own 4-character ID (`ILBM'), plus 1 byte more for each pad byte that
    follow any odd-length chunks.


33 IFFParse Library / Parsing an IFF File

Chunk reading requires a parser to scan each chunk and dispatch the proper
access/conversion procedure.  For a simple IFF file, such parsing may be
relatively easy, consisting mainly reading in the data of desired chunks,
and seeking over unwanted chunks (and the pad byte after odd-length
chunks). Interpreting nested chunks is more complex, and requires a method
for keeping track of the current context, i.e., the data which is still
relevant at any particular depth into the nest.  The original IFF
specifications compare an IFF file to a C program.  Such a metaphor can be
useful in understanding the scope of of the chunks in an IFF file.

The IFFParse library addresses general IFF parsing requirements by
providing a run-time library which can extract the chunks you want from an
IFF file, with the ability to pass control to you when it reaches a chunk
that requires special processing such as decompression.  IFFParse also
understands complex nested IFF formats and will keep track of the context
for you.

 Basic Functions and Structures of IFFParse Library


33 / / Basic Functions and Structures of IFFParse Library

The structures and flags of the IFFParse library are defined in the
include files <libraries/iffparse.h> and <libraries/iffparse.i>.  IFF
files are manipulated through a structure called an IFFHandle.  Only some
of the fields in the IFFHandle are publicly documented.  The rest are
managed internally by IFFParse.  This handle is passed to all IFFParse
functions, and contains the current parse state and position in the file.
An IFFHandle is obtained by calling AllocIFF(), and freed through
FreeIFF().  This is the only legal way to obtain and dispose of an
IFFHandle.

The public portion of if IFFHandle is defined as follows:

    /*
     * Structure associated with an active IFF stream.
     * "iff_Stream" is a value used by the client's read/write/seek
     * functions - it will not be accessed by the library itself and
     * can have any value (could even be a pointer or a BPTR).
     */
    struct IFFHandle {
            ULONG   iff_Stream;
            ULONG   iff_Flags;
            LONG    iff_Depth;      /*  Depth of context stack.  */
            /*  There are private fields hiding here.  */
    };


33 IFFParse Library / Stream Management

A stream is a linear array of bytes that may be accessed sequentially or
randomly.  DOS files are streams.  IFFParse uses Release 2 Hook structures
(defined in <utility/hooks.h>) to implement a general stream management
facility.  This allows the IFFParse library to read, write, and seek any
type of file handle or device by using an application-provided hook
function to open, read, write, seek and close the stream.

Built on top of this facility, IFFParse has two internal stream managers:
one for unbuffered DOS files (AmigaDOS filehandles), and one for the
Clipboard.

 Initialization    Termination    Custom Streams


33 / Stream Management / Initialization

As shown above, the IFFHandle structure contains the public field
iff_Stream.  This is a longword that must be initialized to contain
something meaningful to the stream manager.  IFFParse never looks at this
field itself (at least not directly).  Your iff_Stream may be an AmigaDOS
filehandle, or an IFFParse ClipboardHandle, or a custom stream of any type
if you provide your own custom stream handler (see the section on
"Custom Stream Handlers" later in this chapter).  You must initialize your
IFFHandle structure's iff_Stream to your stream, and then initialize the
IFFHandle's flags and stream hook.

Three sample initializations are shown here.  In the case of the internal
DOS stream manager, iff_Stream is an AmigaDOS filehandle as returned by
Open():

    iff->iff_Stream = (ULONG) Open ("filename", MODE_OLDFILE);
    if(iff->iff_Stream) InitIFFasDOS (iff);
        /* use internal DOS stream manager */

In the case of the internal Clipboard stream manager, iff_Stream is a
pointer to an IFFParse ClipboardHandle structure (the OpenClipboard() call
used here is a function of iffparse.library, not the clipboard.device):

    iff->iff_Stream = (ULONG) OpenClipboard (PRIMARY_CLIP);
    InitIFFasClip (iff); /* use internal Clipboard stream manager  */

When using a custom handle such as an fopen() file handle, or a device
other than the clipboard, you must provide your own flags and stream
handler:

    iff->iff_Stream = (ULONG) OpenMyCustomStream("foo");
    InitIFF (iff, IFFF_FSEEK | IFFF_RSEEK, &mystreamhook);

IFFParse "knows" the seek capabilities of DOS and ClipboardHandle streams,
so InitIFFasDOS() and InitIFFasClip() set the flags for you.

    You May Change the Seek Bits in iff_Flags:
    ------------------------------------------
    IFFParse sets IFFF_FSEEK | IFFF_RSEEK for DOS files.  This is not
    always true (e.g., pipes).  If you know that a DOS file has different
    seek characteristics, your application may correct the seek bits in
    iff_Flags after calling InitIFFasDOS().

When using InitIFF() to provide a custom handler, you must also provide
flags to tell IFFParse the capabilities of your stream.  The flags are:

    IFFF_FSEEK:  This stream has forward-seek capability only.
    IFFF_RSEEK:  This stream has random-seek capability.
                 IFFF_RSEEK tends to imply IFFF_FSEEK, but it's
                 best to specify both.

If neither flag is specified, you're telling IFFParse that it can't seek
through the stream.

After your stream is initialized, call OpenIFF():

    error = OpenIFF (iff, IFFF_READ);

Once you establish a read/write mode (by passing IFFF_READ or IFFF_WRITE),
you remain in that mode until you call CloseIFF().


33 / Stream Management / Termination

Termination is simple.  Just call CloseIFF(iff).  This may be called at
any time, and terminates IFFParse's transaction with the stream.  The
stream itself is not closed.  The IFFHandle may be reused; you may safely
call OpenIFF() on it again.  You are responsible for closing the streams
you opened.  A stream used in an IFFHandle must generally remain open
until you CloseIFF().


33 / Stream Management / Custom Streams

A custom stream handler can allow you (and iffparse.library) to use your
compiler's own file I/O functions such as fopen(), fread() and fwrite(),
rather than the lower-level AmigaDOS equivalents Open(), Read(), and
Write().  A custom stream handler could also be used to read or write IFF
files from an Exec device or an unusual handler or filesystem.

If you install your own stream handler function, iffparse.library will
call your function whenever it needs to read, write, or seek on your file.
Your stream handler function will then perform these stream actions for
iffparse.library.  See the "Custom Stream Handlers" section for more
information on custom stream handlers.


33 IFFParse Library / Parsing

This is both simple and complicated.  It's simple in that it's just one
call.  It's complicated in that you have to seize control of the parser to
get your data.

The parser operates automatically, scanning the file, verifying syntax and
layout rules.  If left to its default behavior, it will scan through the
entire file until it reaches the end, whereupon it will tell you that it
got to the end.

The whole scanning procedure is controlled through one call:

    error = ParseIFF (iff, controlmode);

The control modes are IFFPARSE_SCAN, IFFPARSE_STEP and IFFPARSE_RAWSTEP.
For now, only the IFFPARSE_SCAN control mode is considered.

 Controlling Parsing                 Reading Chunk Data
 Putting It Together                 Other Parsing Modes
 Other Chunk Management Functions


33 / Parsing / Controlling Parsing

ParseIFF(), if left to itself, wouldn't do anything useful.  Ideally, it
should stop at strategic places so we can look at the chunks.  Here's
where it can get complicated.

There are many functions provided to help control the parsing process;
only the common ones are covered here.  Additional functions are described
in the Autodocs for iffparse.library (for the complete Autodocs, refer to
the Amiga ROM Kernel Reference Manual: Includes and Autodocs also by
Addison-Wesley).

 StopChunk()    PropChunk()/FindProp()


33 / / Controlling Parsing / StopChunk()

You can instruct the parser to stop when it encounters a specific IFF
chunk by using the function StopChunk():

    error = StopChunk (iff, ID_ILBM, ID_BODY);

When the parser encounters the requested chunk, parsing will stop, and
ParseIFF() will return the value zero.  The stream will be positioned
ready to read the first data byte in the chunk.  You may then call
ReadChunkBytes() or ReadChunkRecords() to pull the data out of the chunk.

You may call StopChunk() any number of times for any number of different
chunk types.  If you wish to identify the chunk on which you've stopped,
you may call CurrentChunk() to get a pointer to the current ContextNode,
and examine the cn_Type and cn_ID fields.

Using StopChunk() for every chunk, you can parse IFF files in a manner
very similar to the way you're probably doing it now, using a state
machine.  However, this would be a terrible underuse of IFFParse.


33 / / Controlling Parsing / PropChunk()/FindProp()

In the case of a FORM ILBM, certain chunks are defined as being able to
appear in any order.  Among these are the BMHD, CMAP, and CAMG. Typically,
BMHD appears first, followed by CMAP and CAMG, but you can't make this
assumption.  The IFF and ILBM standards require you to assume these chunks
will appear in any order.  So ideally, what you'd like to do is collect
them as they arrive, but not do anything with them until you actually need
them.

This is where PropChunk() comes in.  The syntax for PropChunk() is
identical to StopChunk():

    error = PropChunk (iff, ID_ILBM, ID_BMHD);

When you call ParseIFF(), the parser will look for chunks declared with
PropChunk().  When it sees them, the parser will internally copy the
contents of the chunk into memory for you before continuing its parsing.

When you're ready to examine the contents of the chunk, you use the
function FindProp():

    StoredProperty = FindProp (iff, ID_ILBM, ID_BMHD);

FindProp() returns a pointer to a struct StoredProperty, which contains
the chunk size and data.  If the chunk was never encountered, NULL is
returned.  This permits you to process the property chunks in any order
you wish, regardless of how they appeared in the file.  This provides much
better control of data interpretation and also reduces headaches.  The
following fragment shows how ILBM BitMapHeader data could be accessed
after using ParseIFF() with PropChunk(iff, ID_ILBM, ID_BMHD):

    struct StoredProperty *sp;      /* defined in iffparse.h */
    struct BitMapHeader *bmhd;      /* defined in IFF spec   */

    if (sp = FindProp(iff, ID_ILBM, ID_BMHD))
            {
            /* If property is BMHD, sp->sp_Data is ptr to data in BMHD */
            bmhd = (struct BitMapHeader *)sp->sp_Data;
            printf("BMHD: PageWidth      = %ld\n",bmhd->PageWidth);
            }


33 / Parsing / Putting It Together

With just StopChunk(), PropChunk(), and ParseIFF(), you can write a viable
ILBM display program.  Since IFFParse knows all about IFF structure and
scoping, such a display program would have the added ability to parse
complex FORMs, LISTs, and CATs and attempt to find imagery buried within.

Such an ILBM reader might appear as follows:

iff = AllocIFF();
iff->iff_Stream = Open ("shuttle dog", MODE_OLDFILE);
InitIFFasDOS (iff);
OpenIFF (iff, IFFF_READ);

PropChunk (iff, ID_ILBM, ID_BMHD);
PropChunk (iff, ID_ILBM, ID_CMAP);
PropChunk (iff, ID_ILBM, ID_CAMG);
StopChunk (iff, ID_ILBM, ID_BODY);
ParseIFF (iff, IFFPARSE_SCAN);

if (bmhdprop = FindProp (iff, ID_ILBM, ID_BMHD))
    configurescreen (bmhdprop);
else
    bye ("No BMHD, no picture.");

if (cmapprop = FindProp (iff, ID_ILBM, ID_CMAP))
    setcolors (cmapprop);
else
    usedefaultcolors ();

if (camgprop = FindProp (iff, ID_ILBM, ID_CAMG))
    setdisplaymodes (camgprop);

decodebody (iff);
showpicture ();
CloseIFF (iff);
Close (iff->iff_Stream);
FreeIFF (iff);

    Open the Library.
    -----------------
    Application programs must always open iffparse.library before using
    the functions outlined above.

    Only Example Programs Skip Error Checking.
    ------------------------------------------
    Error checking is not used in the example above for the sake of
    clarity.  A real application should always check for errors.


33 / Parsing / Other Chunk Management Functions

Several other functions are available for controlling the parser.

 CollectionChunk() and FindCollection()
 StopOnExit()
 EntryHandler()
 ExitHandler()


33 / / Management Functions / CollectionChunk() and FindCollection()

PropChunk() keeps only one copy of the declared chunk (the one currently
in scope).  CollectionChunk() collects and keeps all instances of a
specified chunk.  This is useful for chunks such as the ILBM CRNG chunk,
which can appear multiple times in a FORM, and which don't override
previous instances of themselves.  CollectionChunk() is called identically
to PropChunk():

    error = CollectionChunk (iff, type, id);

When you wish to find the collected chunks currently in scope, you use the
function FindCollection():

    ci = FindCollection (iff, type, id);

You will be returned a pointer to a CollectionItem, which is part of a
singly-linked list of all copies of the specified chunk collected so far
that are currently in scope.

    struct CollectionItem {
            struct CollectionItem   *ci_Next;
            LONG                    ci_Size;
            UBYTE                   *ci_Data;
    };

The size of this copy of the chunk is in the CollectionItem's ci_Size
field.  The ci_Data field points to the chunk data itself.  The ci_Next
field points to the next CollectionItem in the list.  The last element in
the list has ci_Next set to NULL.

The most recently-encountered instance of the chunk will be first in the
list, followed by earlier chunks.  Some might consider this ordering
backwards.

If NULL is returned, the specified chunk was never encountered.


33 / / Other Chunk Management Functions / StopOnExit()

Whereas StopChunk() will stop the parser just as it enters the declared
chunk, StopOnExit() will stop just before it leaves the chunk. This is
useful for finding the end of FORMs, which would indicate that you've
collected all possible data in this FORM and may now act on it.

    /* Ask ParseIFF() to stop with IFFERR_EOC when leaving a FORM ILBM */
    StopOnExit(iff,ID_ILBM, ID_FORM);


33 / / Other Chunk Management Functions / EntryHandler()

This is used to install your own custom chunk entry handler.  See the
"Custom Chunk Handlers" section below for more information.  StopChunk(),
PropChunk(), and CollectionChunk() are internally built on top of this.


33 / / Other Chunk Management Functions / ExitHandler()

This is used to install your own custom chunk exit handler.  See the
"Custom Chunk Handlers" section below for more information.  StopOnExit()
is internally built on top of this.


33 / Parsing / Reading Chunk Data

To read data from a chunk, use the functions ReadChunkBytes() and
ReadChunkRecords().  Both calls truncate attempts to read past the end of
a chunk.  For odd-length chunks, the parser will skip over the pad bytes
for you.  Remember that for chunks which have been gathered using
PropChunk() (or CollectionChunk() ), you may directly reference the data
by using FindProp() (or FindCollection() ) to get a pointer to the data.
ReadChunkBytes() is commonly used when loading and decompressing bitmap
and sound sample data or sequentially reading in data chunks such as FTXT
CHRS text chunks.  See the code listing ClipFTXT.c for an example usage of
ReadChunkBytes().


33 / Parsing / Other Parsing Modes

In addition to the mode IFFPARSE_SCAN, there are the modes IFFPARSE_STEP
and IFFPARSE_RAWSTEP.

 IFFPARSE_RAWSTEP    IFFPARSE_STEP


33 / / Other Parsing Modes / IFFPARSE_RAWSTEP

This mode causes the parser to progress through the stream step by step,
rather than in the automated fashion provided by IFFPARSE_SCAN.  In this
mode, ParseIFF() will return upon every entry to and departure from a
context.

When the parser enters a context, ParseIFF() will return zero.
CurrentChunk() will report the type and ID of the chunk just entered, and
the stream will be positioned to read the first byte in the chunk.  When
entering a FORM, LIST, CAT or PROP chunk, the longword containing the type
(e.g., ILBM, FTXT, etc.) is read by the parser.  In this case, the stream
will be positioned to read the byte immediately following the type.)

When the parser leaves a context, ParseIFF() will return the value
IFFERR_EOC.  This is not strictly an error, but an indication that you are
about to leave the current context.  CurrentChunk() will report the type
and ID of the chunk you are about to leave.  The stream is not positioned
predictably within the chunk.

The parser does not call any installed chunk handlers when using this mode
(e.g., property chunks declared with PropChunk() will not be collected).

See the example program, Sift.c, for a demonstration of IFFPARSE_RAWSTEP.


33 / / Other Parsing Modes / IFFPARSE_STEP

This mode is identical to IFFPARSE_RAWSTEP, except that, before control
returns to your code, the chunk handler (if any) for the chunk is invoked.


33 IFFParse Library / Writing IFF Files

IFFParse provides facilities for writing IFF files.  Again, IFFParse makes
no assumptions about the data you're writing, and concerns itself with
verifying the syntax of your output.

 Creating Chunks In a File    Writing Chunk Data    A Note On Seekability


33 / Writing IFF Files / Creating Chunks In a File

Because the IFF specification has nesting and scoping rules, you can nest
chunks inside one another.  One instance is the BMHD chunk, which is
commonly nested inside a FORM chunk.  Thus, it is necessary for you to
inform IFFParse when you are starting and ending chunks.

 PushChunk()    PopChunk()


33 / / Creating Chunks In a File / PushChunk()

To tell IFFParse you are about to begin writing a new chunk, you use the
function PushChunk():

    error = PushChunk (iff, ID_ILBM, ID_BMHD,chunksize);

The chunk ID and size are written to the stream.  IFFParse will enforce
the chunk size you specified; attempts to write past the end of the chunk
will be truncated.  If, as a chunk size argument, you pass IFFSIZE_UNKNOWN,
the chunk will be expanded in size as you write data to it.


33 / / Creating Chunks In a File / PopChunk()

When you are through writing data to a chunk, you complete the write by
calling PopChunk():

    error = PopChunk (iff);

If you wrote fewer bytes than you declared with PushChunk(), PopChunk()
will return an error.  If you specified IFFSIZE_UNKNOWN, PopChunk() will
seek backward on the stream and write the final size.  If you specified a
chunk size that was odd, PopChunk() will write the pad byte automatically.

PushChunk() and PopChunk() nest; every call to PushChunk() must have a
corresponding call to PopChunk().


33 / Writing IFF Files / Writing Chunk Data

Writing the IFF chunk data is done with either the WriteChunkBytes() or
WriteChunkRecords() functions.

    error = WriteChunkBytes (iff, buf, size);
    error = WriteChunkRecords (iff, buf, recsize, numrec);

If you specified a valid chunk size when you called PushChunk(),
WriteChunkBytes() and WriteChunkRecords() will truncate attempts to write
past the end of the chunk.

Code to write an ILBM file might take the following form:

    iff = AllocIFF ();
    iff->iff_Stream = Open ("foo", MODE_NEWFILE);
    InitIFFasDOS (iff);
    OpenIFF (iff, IFFF_WRITE);

    PushChunk (iff, ID_ILBM, ID_FORM, IFFSIZE_UNKNOWN);

    PushChunk (iff, ID_ILBM, ID_BMHD, sizeof (struct BitMapHeader));
    WriteChunkBytes (iff, &bmhd, sizeof (bmhd));
    PopChunk (iff);

    PushChunk (iff, ID_ILBM, ID_CMAP, cmapsize);
    WriteChunkBytes (iff, cmapdata, cmapsize);
    PopChunk (iff);

    PushChunk (iff, ID_ILBM, ID_BODY, IFFSIZE_UNKNOWN);
    packwritebody (iff);
    PopChunk (iff);

    PopChunk (iff);

    CloseIFF (iff);
    Close (iff->iff_Stream);
    FreeIFF (iff);

Again, error checking is not present for clarity. See the example code
ClipFTXT.c which writes a simple FTXT clip to the clipboard.


33 / Writing IFF Files / A Note On Seekability

As you can see from the above examples, IFFParse works best with a stream
that can seek randomly.  However, it is not possible to seek on some
streams (e.g., pipes).

IFFParse will read and write streams with limited or no seek capability.
In the case of reading, only forward-seek capability is desirable.
Failing this, IFFParse will fake forward seeks with a number of short
reads.

In the case of writing, if the stream lacks random seek capability,
IFFParse will buffer the entire contents of the file until you do the
final PopChunk(), or when you CloseIFF() the handle.  At that time, the
entire stream will be written in one go.  This buffering happens whether
or not you specify all the chunk sizes to PushChunk().

    About the Internal Buffering.
    -----------------------------
    The current implementation of this internal buffering could be
    more efficient.  Be aware that Amiga, Inc. reserves the right to alter
    this behavior of the parser, to improve performance or reduce memory
    requirements.  We mention this behavior on the off chance it is
    important to you.


33 IFFParse Library / Context Functions

Internally, IFFParse maintains IFF nesting and scoping context via a
context stack.  The PushChunk() and PopChunk() functions get their names
from this basic idea of the iffparse.library.  Direct access to this stack
is not allowed.  However, many functions are provided to assist in
examining and manipulating the context stack.

    About the Context Stack.
    ------------------------
    It is probably easier to think of a stack of blocks on a table in
    front of you when reading this discussion.

As the nesting level increases (as would happen when parsing a nested LIST
or FORM), the depth of the context stack increases; new elements are added
to the top.  When these contexts expire, the ContextNodes are deleted and
the stack shrinks.

 Context Nodes
 The Default Context
 Context-Specific Data: LocalContextItems
 Storing LCIs
 Some Interesting Internal Details


33 / Context Functions / Context Nodes

The current context is said to be the top element on the stack.
Contextual information is stored in a structure called a ContextNode:

    struct ContextNode {
            struct MinNode  cn_Node;
            LONG            cn_ID;
            LONG            cn_Type;
            LONG            cn_Size; /*  Size of this chunk             */
            LONG            cn_Scan; /*  # of bytes read/written so far */
            /*  There are private fields hiding here.  */
            };

 CurrentChunk()    ParentChunk()


33 / / Context Nodes / CurrentChunk()

You can obtain a pointer to the current ContextNode through the function
CurrentChunk():

    currentnode = CurrentChunk (iff);

The ContextNode tells you the type, ID, and size of the currently active
chunk.  If there is no currently active context, NULL is returned.


33 / / Context Nodes / ParentChunk()

To find the parent of a context, you call ParentChunk() on the relevant
ContextNode:

    parentnode = ParentChunk(currentnode);

If there is no parent context, NULL is returned.


33 / Context Functions / The Default Context

When you first obtain an IFFHandle through AllocIFF(), a hidden default
context node is created.  You cannot get direct access to this node
through CurrentChunk() or ParentChunk().  However, using StoreLocalItem(),
you can store information in this context.


33 / Context Functions / Context-Specific Data: LocalContextItems

ContextNodes can contain application data specific to that context.  These
data objects are called LocalContextItems.  LocalContextItems (LCIs) are a
grey-box structure which contain a type, ID and identification field.
LCIs are used to store context-sensitive data.  The format of this data is
application-defined.  A ContextNode can contain as many LCIs as you want.

        __________________
       |                  |
       |   ContextNode    |
       |   -----------    |
       |  Type - ID_ILBM  |
       |  ID   - ID_BODY  |
       |__________________|
                |
        ________|_________      _______________________________
       |                  |    |                               |
       |   ContextNode    |    |       LocalContextItem        |
       |   -----------    |____|       ----------------        |
       |  Type - ID_ILBM  |    |  Type  - ID_ILBM              |
       |  ID   - ID_FORM  |    |  ID    - ID_BMHD              |
       |__________________|    |  Ident - IFFLCI_PROP          |
                |              |_______________________________|
        ________|_________      _______________________________
       |                  |    |                               |
       |   ContextNode    |    |       LocalContextItem        |
       |   -----------    |    |       ----------------        |
       |  Type - ID_ZOID  |____|  Type  - ID_ILBM              |
       |  ID   - ID_LIST  |    |  ID    - ID_BMHD              |
       |__________________|    |  Ident - IFFLCI_ENTRYHANDLER  |
                |              |_______________________________|
        ________|______________________________________________
       |                                                       |
       |                   I F F H a n d l e                   |
       |_______________________________________________________|

                 Figure 33-3: IFFParse Context Stack

Figure 33-3 shows the relationship between the IFFHandle, the
ContextNodes, and the LCIs.  The IFFHandle is the root of the tree, so to
speak.  ContextNodes "grow" out of the IFFHandle.  In turn, LCIs "grow"
out of the ContextNodes.  What grows out of an LCI is client-defined.

 AllocLocalItem()    LocalItemData()


33 / / Context-Specific Data: LocalContextItems / AllocLocalItem()

To create an LCI, you use the function AllocLocalItem():

    lci = AllocLocalItem (type, id, ident, datasize);

If successful, you will be returned a pointer to an LCI having the
specified type, ID, and identification values; and with datasize bytes of
buffer space for your application to use.


33 / / Context-Specific Data: LocalContextItems / LocalItemData()

To get a pointer to an LCIs data buffer, you use LocalItemData():

    buf = LocalItemData (lci);

You may read and write the buffer to your heart's content; it is yours.
You should not, however, write beyond the end of the buffer.  The size of
the buffer is what you asked for when you called AllocLocalItem().


33 / Context Functions / Storing LCIs

Once you've created and initialized an LCI, you'll want to attach it to a
ContextNode.  Though a ContextNode can have many LCIs, a given LCI can be
linked to only one ContextNode.  Once linked, an LCI cannot be removed
from a ContextNode (this may change in the future).  Storing an LCI in a
ContextNode is done with the functions StoreLocalItem() and
StoreItemInContext().

 StoreLocalItem()    StoreItemInContext()    FindLocalItem()


33 / / Storing LCIs / StoreLocalItem()

The StoreLocalItem() function is called as follows:

    error = StoreLocalItem (iff, lci, position);

The position argument determines where the LCI is stored.  The possible
values are IFFSLI_ROOT, IFFSLI_TOP, and IFFSLI_PROP.

IFFSLI_ROOT causes StoreLocalItem() to store your LCI in the default
ContextNode.

IFFSLI_TOP gets your LCI stored in the top (current) ContextNode.

    The LCI Ends When the Current Context Ends.
    -------------------------------------------
    When the current context expires, your LCI will be deleted by
    the parser.

IFFSLI_PROP causes your LCI to be stored in the topmost context from which
a property would apply.  This is usually the topmost FORM or LIST chunk.
For example, suppose you had a deeply nested ILBM FORM, and you wanted to
store the BMHD property in its correct context such that, when the current
FORM context expired, the BMHD property would be deleted.  IFFSLI_PROP
will cause StoreLocalItem() to locate the proper context for such scoping,
and store the LCI there.  See the section on "Finding the Prop Context"
for additional information on the scope of properties.


33 / / Storing LCIs / StoreItemInContext()

StoreItemInContext() is used when you already have a pointer to the
ContextNode to which you want to attach your LCI.  It is called like so:

    StoreItemInContext (iff, lci, contextnode);

StoreItemInContext() links your LCI into the specified ContextNode.  Then
it searches the ContextNode to see if there is another LCI with the same
type, ID, and identification values.  If so, the old one is deleted.


33 / / Storing LCIs / FindLocalItem()

After you've stored your LCI in a ContextNode, you will no doubt want to
be able to find it again later.  You do this with the function
FindLocalItem(), which is called as follows:

    lci = FindLocalItem (iff, type, id, ident);

FindLocalItem() attempts to locate an LCI having the specified type, ID,
and identification values.  The search proceeds as follows (refer to
Figure 33-3 to understand this better).

FindLocalItem() starts at the top (current) ContextNode and searches all
LCIs in that context.  If no matching LCIs are found, it proceeds down the
context stack to the next ContextNode and searches all its LCIs.  The
process repeats until it finds the desired LCI (whereupon it returns a
pointer to it), or reaches the end without finding anything (where it
returns NULL).

    Context Stack Position.
    -----------------------
    LCIs higher in the stack will "override" lower LCIs with the
    same type, ID, and identification field.  This is how property
    scoping is handled.  As ContextNodes are popped off the context
    stack, all its LCIs are deleted as well.  See the section on
    "Freeing LCIs" below for additional information on deleting LCIs.


33 / Context Functions / Some Interesting Internal Details

    WARNING:
    --------
    This section details some internal implementation details of
    iffparse.library which may help you to understand it better.  Use of
    the following information to do "clever" things in an application is
    forbidden and unsupportable.  Don't even think about it.

It turns out that StoredProperties, CollectionItems, and entry and exit
handlers are all implemented using LCIs.  For example, when you call
FindProp(), you are actually calling a front-end to FindLocalItem().  The
mysterious identification value (which has heretofore never been
discussed) is a value which permits you to differentiate between LCIs
having the same type and ID.

For instance, suppose you called PropChunk(), asking it to store an ILBM
BMHD.  PropChunk() will install an entry handler in the form of an LCI,
having type equal to `ILBM', ID equal to `BMHD', and an identification
value of IFFLCI_ENTRYHANDLER.

When an ILBM BMHD is encountered, the entry handler is called, and it
creates and stores another LCI having type equal to `ILBM', ID equal to
`BMHD' and an identification value of IFFLCI_PROP.

Thus, when you call FindProp(), it merely calls FindLocalItem() with your
type and ID, and supplies IFFLCI_PROP for the identification value.

Therefore, handlers, StoredProperties, CollectionItems and your own custom
LCIs can never be confused with each other, since they all have unique
identification values.  Since they are all handled (and searched for) in
the same way, they all "override" each other in a consistent way. Just as
StoredProperties higher in the context stack will be found and returned
before identical ones in lower contexts, so will chunk handlers be found
and invoked before ones lower on the context stack (recall
FindLocalItem()'s search procedure).

This means you can temporarily override a chunk handler by installing an
identical handler in a higher context.  The handler will persist until the
context in which it is stored expires, after which, the original one
regains scope.


33 IFFParse Library / Error Handling

If at any time during reading or writing you encounter an error, the
IFFHandle is left in an undefined state.  Upon detection of an error, you
should perform an abort sequence and CloseIFF() the IFFHandle.  Once
CloseIFF() has been called, the IFFHandle is restored to normalcy and may
be reused.


33 IFFParse Library / Advanced Topics

This section discusses customizing of IFFParse data handling.  For
applications with special needs, IFFParse supports both custom stream
handlers and custom chunk handlers.

 Custom Stream Handlers    Finding The PROP Context
 Custom Chunk Handlers     Freeing LCIs


33 / Advanced Topics / Custom Stream Handlers

As discussed earlier, IFFParse contains built-in stream handlers for
AmigaDOS file handles as returned by Open(), and for the clipboard.device.
If you are using AmigaDOS filehandles or the clipboard.device, you need
not supply a custom stream handler.

If you wish to use your compiler's own file I/O functions (such as fread()
) or need to read or write to an unusual handler or Exec device, you must
provide a custom stream handler for your IFFHandle.  Your custom stream
handler will be called to perform all reads, writes, and seeks on your
custom stream.  The allows you to use compiler file I/O functions, Exec
device commands, or any other method to perform the requested stream
operations.

If you are implementing your own custom stream handler, you will need to
know the mechanics of hook call-backs, and how to interpret the
parameters.  An IFFParse custom stream handler is simply a function in
your code that follows Release 2 hook function conventions (Hook functions
are also known as callback functions.  See the "Utility Library" chapter
for more details).

 Installing a Custom Stream Handler
 Inside a Custom Stream Handler


33 / / Custom Stream Handlers / Installing a Custom Stream Handler

To initialize your IFFHandle to point to your custom stream and stream
handler, you must open your stream and place a pointer to the stream in
your IFFHandle's iff_Stream field.  This pointer could be the return from
fopen(), or an Exec device I/O request, or any other type of pointer which
will provide your custom stream handler with a way to manage your stream.
For example:

    iff->iff_Stream = (ULONG) fopen("foo");

Next, you must install your custom handler for this stream, and also tell
IFFParse the seek capabilities of your stream.  To install your custom
stream handler, you must first set up a Hook structure (<utility/hooks.h>)
to point to your stream handling function.  Then use InitIFF() to install
your stream handler and also tell IFFParse the seek capabilities of your
stream.  There is "some assembly required".

Release 2 hook function calling conventions specify a register interface.
For an IFFParse custom stream hook, at entry, A0 contains a pointer to the
hook, A2 is a pointer to your IFFHandle, and A1 is a pointer to a command
packet, which tells you what to do.  A6 contains a pointer to
IFFParseBase.  You may trash A0, A1, D0, and D1.  All other registers must
be preserved.  You return your error code in D0.  A return of 0 indicates
success.  A non-zero return indicates an error.

If your compiler supports registered function parameters, you may use a
registerized C function entry as the h_Entry hook entry point:

/* mystreamhandler - SAS C custom stream handler with */
/* registerized arguments                             */
static LONG __saveds __asm
mystreamhandler (
    register __a0 struct Hook               *hook,
    register __a2 struct IFFHandle          *iff,
    register __a1 struct IFFStreamCmd       *actionpkt
    )
{
/*
 * Code to handle the stream commands - see end this section
 * for a complete example custom stream handler function.
 *
 */
}

/* Initialization of Hook structure for registerized  */
/* handler function                                   */
struct Hook mystreamhook {
    { NULL },
    (ULONG (*)()) mystreamhandler,
                  /* h_Entry, registerized function entry */
    NULL,
    NULL };

/* Open custom stream and InitIFF to custom stream handler */
if ( iff->iff_Stream = (ULONG) myopen("foo") )
    {
    InitIFF (iff, IFFF_FSEEK | IFFF_RSEEK, &mystreamhook);
    }

Alternately, you could initialize your Hook structure's h_Entry to point
to a standard assembler stub which would push the register arguments on
the stack and then call a standard args C function.  In this case, you
must store the address of your C function in the h_SubEntry field of the
Hook structure so the assembler stub can find and call your C entry point.
A sample assembler hook entry stub follows.  This would be assembled as
hookentry.o and linked with your C code.

* HookEntry.asm for SAS C

        INCLUDE "exec/types.i"
        INCLUDE "utility/hooks.i"

        XDEF    _HookEntry

        section code

 _HookEntry:
        move.l  a6,-(sp)
        move.l  a1,-(sp)                ; push message packet pointer
        move.l  a2,-(sp)                ; push object pointer
        move.l  a0,-(sp)                ; push hook pointer
        move.l  h_SubEntry(a0),a0       ; fetch C entry point ...
        jsr     (a0)                    ; ... and call it
        lea     12(sp),sp               ; fix stack
        move.l  (sp)+,a6
        rts

        end

When using an assembler HookEntry stub, your C program's custom stream
handler interface would be initialized as follows:

extern LONG HookEntry();        /* The assembler entry */

/* mystreamhandler - a standard args C function custom stream handler*/
static LONG mystreamhandler ( struct Hook *hook,
                              struct IFFHandle *iff,
                              struct IFFStreamCmd *actionpkt )
{
/* Code to handle the stream commands - see end of this section
 * for a complete example custom stream handler function.
 */
}

/* Initialization of Hook for asm HookEntry and std args C function */
struct Hook mystreamhook {
    { NULL },
    (ULONG (*)()) HookEntry,        /* h_Entry, assembler stub entry */
    (ULONG (*)()) mystreamhandler,
                              /* h_SubEntry, std args function entry */
    NULL };

/* Open custom stream and InitIFF to custom stream handler */
if ( iff->iff_Stream = (ULONG) myopen("foo") )
        {
        InitIFF (iff, IFFF_FSEEK | IFFF_RSEEK, &mystreamhook);
        }


33 / / Custom Stream Handlers / Inside a Custom Stream Handler

When the library calls your stream handler, you'll be passed a pointer to
the Hook structure (hook in the example used here), a pointer to the
IFFHandle (iff), and a pointer to an IFFStreamCmd structure (actionpkt).
Your stream pointer may be found in iff->iff_Stream where you previously
stored it.  The IFFStreamCmd (actionpkt) will describe the action that
IFFParse needs you to perform on your stream:

/* Custom stream handler is passed struct IFFStreamCmd *actionpkt */
struct IFFStreamCmd {
    LONG    sc_Command;     /*  Operation to be performed (IFFCMD_) */
    APTR    sc_Buf;         /*  Pointer to data buffer              */
    LONG    sc_NBytes;      /*  Number of bytes to be affected      */
    };

/* Possible call-back command values.  (Using 0 as the value for
 * IFFCMD_INIT was, in retrospect, probably a bad idea.)
 */
#define IFFCMD_INIT     0   /*  Prepare the stream for a session    */
#define IFFCMD_CLEANUP  1   /*  Terminate stream session            */
#define IFFCMD_READ     2   /*  Read bytes from stream              */
#define IFFCMD_WRITE    3   /*  Write bytes to stream               */
#define IFFCMD_SEEK     4   /*  Seek on stream                      */
#define IFFCMD_ENTRY    5   /*  You just entered a new context      */
#define IFFCMD_EXIT     6   /*  You're about to leave a context     */
#define IFFCMD_PURGELCI 7   /*  Purge a LocalContextItem            */

Your custom stream handler should perform the requested action on your
custom stream, and then return 0 for success or an IFFParse error if an
error occurred.  The following code demonstrates a sample stream handler
for a stream which was opened with a compiler's fopen() buffered file I/O
function:

static LONG mystreamhandler ( struct Hook *hook,
                              struct IFFHandle *iff,
                              struct IFFStreamCmd *actionpkt )
{
    register FILE   *stream;
    register LONG   nbytes, error;
    register UBYTE  *buf;

    stream  = (FILE *) iff->iff_Stream;    /* get stream pointer */
    nbytes  = actionpkt->sc_NBytes;        /* length for command */
    buf     = (UBYTE *) actionpkt->sc_Buf; /* buffer for the command */

    /* Now perform the action specified by the actionpkt->sc_Command */

    switch (actionpkt->sc_Command) {
    case IFFCMD_READ:
        /*
         * IFFCMD_READ means read sc_NBytes from the stream and place
         * it in the memory pointed to by sc_Buf.  Be aware that
         * sc_NBytes may be larger than can be contained in an int.
         * This is important if you plan on recompiling this for
         * 16-bit ints, since fread() takes int arguments.
         *
         * Any error code returned will be remapped by IFFParse into
         * IFFERR_READ.
         */
        error = (fread (buf, 1, nbytes, stream) != nbytes);
        break;

    case IFFCMD_WRITE:
        /*
         * IFFCMD_WRITE is analogous to IFFCMD_READ.
         *
         * Any error code returned will be remapped by IFFParse into
         * IFFERR_WRITE.
         */
        error = (fwrite (buf, 1, nbytes, stream) != nbytes);
        break;

    case IFFCMD_SEEK:
        /*
         * IFFCMD_SEEK asks that you performs a seek relative to the
         * current position.  sc_NBytes is a signed number,
         * indicating seek direction (positive for forward, negative
         * for backward).  sc_Buf has no meaning here.
         *
         * Any error code returned will be remapped by IFFParse into
         * IFFERR_SEEK.
         */
        error = (fseek (stream, nbytes, 1) == -1);
        break;

    case IFFCMD_INIT:
        /*
         * IFFCMD_INIT means to prepare your stream for reading.
         * This is used for certain streams that can't be read
         * immediately upon opening, and need further preparation.
         * This operation is allowed to fail;  the error code placed
         * in D0 will be returned directly to the client.
         *
         * An example of such a stream is the clipboard.  The
         * clipboard.device requires you to set the io_ClipID and
         * io_Offset to zero before starting a read.  You would
         * perform such a sequence here.  (Stdio files need no such
         * preparation, so we simply return zero for success.)
         */
    case IFFCMD_CLEANUP:
        /*
         * IFFCMD_CLEANUP means to terminate the transaction with
         * the associated stream.  This is used for streams that
         * can't simply be closed.  This operation is not allowed to
         * fail;  any error returned will be ignored.
         *
         * An example of such a stream is (surprise!) the clipboard.
         * It requires you to explicitly end reads by CMD_READing
         * past the end of a clip, and end writes by sending a
         * CMD_UPDATE.  You would perform such a sequence here.
         * (Again, stdio needs no such sequence.)
         */
        error = 0;
        break;
    }
    return (error);
}


33 / Advanced Topics / Custom Chunk Handlers

Like custom stream handlers, custom chunk handlers are implemented using
Release 2 Hook structures.  See the previous section for details on how a
handler function may be interfaced using a Hook structure.

There are two types of chunk handlers:  entry handlers and exit handlers.
Entry handlers are invoked just after the parser enters the chunk; the
stream will be positioned to read the first byte in the chunk. (If the
chunk is a FORM, LIST, CAT, or PROP, the longword type will be read by the
parser; the stream will be positioned to read the byte immediately
following the type.)  Exit handlers are invoked just before the parser
leaves the chunk; the stream is not positioned predictably within the
chunk.

 Installing a Custom Chunk Handler
 Inside a Custom Chunk Handler
 The Object Parameter


33 / / Custom Chunk Handlers / Installing a Custom Chunk Handler

To install an entry handler, you call EntryHandler() in the following
manner:

    error = EntryHandler (iff, type, id, position, hookptr, object);

An exit handler is installed by saying:

    error = ExitHandler (iff, type, id, position, hookptr, object);

In both cases, a handler is installed for chunks having the specified type
and id.  The position argument specifies in what context to install the
handler, and is identical to the position argument used by
StoreLocalItem().  The hookptr argument given above is a pointer to your
Hook structure.


33 / / Custom Chunk Handlers / Inside a Custom Chunk Handler

The mechanics of receiving parameters through the Hook are covered in the
"Custom Stream Handlers" section, and are not duplicated here.  Refer to
the EntryHandler() and ExitHandler() Autodocs for the contents of the
registers upon entry.

Once inside your handler, you can call nearly all functions in the
iffparse.library, however, you should avoid calling ParseIFF() from within
chunk handlers.

Your handler runs in the same environment as whoever called ParseIFF().
The propagation sequence is:

     __________            ____________            ________________
    |          |          |            |          |                |
    | mainline |--calls-->| ParseIFF() |--calls-->| your_handler() |
    |__________|          |____________|          |________________|

Thus, your handler runs on your mainline's stack, and can call any OS
functions the mainline code can.  (Your handler will have to set the
global base pointer if your code uses base-relative addressing.)

When leaving the handler, you must follow the standard register
preservation conventions (D0/D1/A0/A1 may be trashed, all others must be
preserved).  D0 contains your return code, which will affect the parser in
a number of ways:

If you return zero (a normal, uneventful return), ParseIFF() will continue
normally.  If you return the value IFFERR_RETURN2CLIENT, ParseIFF() will
stop and return the value zero to the mainline code.

If you return any other value, ParseIFF() will stop and return that value
to the mainline code.  This is how you should return error conditions to
the client code.


33 / / Custom Chunk Handlers / The Object Parameter

The object parameter supplied to EntryHandler() and ExitHandler() is a
pointer which will be passed to your handler when invoked.  This pointer
can be anything; the parser doesn't use it directly.  As an example, you
might pass the pointer to the IFFHandle.  This way, when your handler is
called, you'll be able to easily perform operations on the IFFHandle
within your handler.  Such code might appear as follows:

    error = EntryHandler (iff, ID_ILBM, ID_BMHD, IFFSLI_ROOT, hook, iff);

And your handler would be declared as follows:

    /* Registerized handler hook h_Entry using */
    /* SAS C registerized parameters           */
    LONG __asm MyHandler (register __a0 struct Hook      *hook,
                          register __a1 LONG             *cmd,
                          register __a2 struct IFFHandle *iff)

    /* Standard args handler hook h_SubEntry using */
    /* HookEntry.asm as Hook h_Entry               */
    LONG MyHandler ( struct Hook      *hook,
                     LONG             *cmd,
                     struct IFFHandle *iff )

From within your handler, you could then call CurrentChunk(),
ReadChunkBytes(), or nearly any other operation on the IFFHandle. Please
refer to the EntryHandler() and ExitHandler() Autodocs for additional
information on the use of chunk handlers.


33 / Advanced Topics / Finding The PROP Context

Earlier it was mentioned that supplying a position value of IFFSLI_PROP to
StoreLocalItem() would store it in the topmost property scope.
FindPropContext() is the routine that finds that topmost context.

Property chunks (such as the BMHD, CMAP, and others) have dominion over
the FORM that contains them; they are said to be "in scope" and their
definition persists until the FORM's context ends.  Thus, a property chunk
has a scoping level equal to the FORM that contains it; when the FORM
ends, the property dies with it.

Consider a more complicated example.  Suppose you have a LIST with a PROP
in it.  PROPs are the global variables of LISTs; thus a property chunk
declared in a PROP will persist until the LIST's context ends.

This is what FindPropContext() is looking for; a context level in which a
property chunk may be installed.

FindPropContext() starts at the parent of the current context (second from
the top of the context stack) and starts searching downward, looking for
the first FORM or LIST context it finds.  If it finds one, it returns a
pointer to that ContextNode.  If it can't find a suitable context level,
it returns NULL.

FindPropContext() is called as follows:

    struct ContextNode *cn;

    cn = FindPropContext (iff);


33 / Advanced Topics / Freeing LCIs

Ordinarily, the parser will automatically delete LCIs you have allocated
and installed.  However, you may have a case where simply FreeMem()ing
your LCI is not enough; you may need to free some ancillary memory, or
decrement a counter, or send a signal, or something.  This is where
SetLocalItemPurge() comes in.  It is called as follows:

    SetLocalItemPurge (lci, hookptr);

When the parser is ready to delete your LCI, your purge handler code will
be called through the Hook you supplied.  You can then perform all your
necessary operations.  One of these operations should be to free the LCI
itself.  This is done with FreeLocalItem():

    FreeLocalItem (lci);

This deallocates the memory used to store the LCI and the client buffer
allocated with it.  FreeLocalItem() is only called as part of a custom
purge handler.

As with custom chunk handlers, your purge handler executes in the same
environment as the mainline code that called ParseIFF().  It is
recommended that you keep purge handlers short and to the point; super
clever stuff should be reserved for custom chunk handlers, or for the
client's mainline code.  Custom purge handlers must always work; failures
will be ignored.


33 IFFParse Library / IFF FORM Specifications

The specifications for Amiga IFF formats are maintained by Commodore
Applications and Technical Support (CATS) and updated periodically.  The
latest specifications are published in the Amiga ROM Kernel Reference
Manual: Devices (3rd edition) and also available in electronic form
directly from CATS.  Between updates of the IFF Manual, selected new FORMs
and changes to existing FORMs are documented in Amiga Mail a technical
newsletter for Amiga developers published by Commodore's CATS group.

Some of the most commonly used IFF FORMs are the four that were originally
specified in the EA IFF-85 standard:

             ___________________________________
            |                                   |
            |  ILBM  Bitmap images and palettes |
            |  FTXT  Simple formatted text      |
            |  SMUS  Simple musical scores      |
            |  8SVX  8-bit sound samples        |
            |___________________________________|

Of these four, ILBM is the most commonly encountered FORM, and FTXT is
becoming increasingly important since the Release 2 conclip command passes
clipped console text through the clipboard as FTXT.  All data clipped to
the clipboard must be in an IFF format.

This section will provide a brief summary of the ILBM and FTXT FORMs and
their most used common chunks.  Please consult the EA-IFF specifications
for additional information.

 FORM ILBM    FORM FTXT


33 / IFF FORM Specifications / FORM ILBM

The IFF file format for graphic images on the Amiga is called FORM ILBM
(InterLeaved BitMap).  It follows a standard parsable IFF format.

 ILBM.BMHD BitMapHeader Chunk
 Sample Hex Dump of an ILBM
 Interpreting ILBMs
 ILBM BODY Compression
 Interpreting the Scan Line Data
 Other ILBM Notes


33 / / FORM ILBM / ILBM.BMHD BitMapHeader Chunk

The most important chunk in a FORM ILBM is the BMHD (BitMapHeader) chunk
which describes the size and compression of the image:

typedef UBYTE Masking;  /* Choice of masking technique - Usually 0. */
#define mskNone                 0
#define mskHasMask              1
#define mskHasTransparentColor  2
#define mskLasso                3

/* Compression algorithm applied to the rows of all source
 * and mask planes. "cmpByteRun1" is byte run encoding.
 * Do not compress across rows!  Compression is usually 1.
 */
typedef UBYTE Compression;
#define cmpNone                 0
#define cmpByteRun1             1

/* The BitMapHeader structure expressed as a C structure */
typedef struct {
    UWORD w, h;                 /* raster width & height in pixels      */
    WORD  x, y;                 /* pixel position for this image        */
    UBYTE nPlanes;              /* # bitplanes (without mask, if any)   */
    Masking     masking;        /* One of the values above.  Usually 0  */
    Compression compression;    /* One of the values above.  Usually 1  */
    UBYTE reserved1;            /* reserved; ignore on read, write as 0 */
    UWORD transparentColor;     /* transparent color number. Usually 0  */
    UBYTE xAspect, yAspect;     /* pixel aspect, a ratio width : height */
    WORD  pageWidth, pageHeight;    /* source "page" size in pixels */
} BitMapHeader;


33 / / FORM ILBM / Sample Hex Dump of an ILBM

    WARNING:
    --------
    This hex dump is shown only to help the reader understand how IFF
    chunks appear in a file.  You cannot ever depend on any particular
    ILBM chunk being at any particular offset into the file.  IFF files
    are composed, in their simplest form, of chunks within a FORM.  Each
    chunk starts with a 4-letter chunkID, followed by a 32-bit length of
    the rest of the chunk.  You must parse IFF files, skipping past
    unneeded or unknown chunks by seeking their length (+1 if odd length)
    to the next 4-letter chunk ID.  In a real ILBM file, you are likely
    to encounter additional optional chunks.  See the IFF Specification
    listed in the Amiga ROM Kernel Reference Manual: Devices for
    additional information on such chunks.

0000: 464F524D 00016418 494C424D 424D4844    FORM..d.ILBMBMHD
0010: 00000014 01400190 00000000 06000100    .....@..........
0020: 00000A0B 01400190 43414D47 00000004    .....@..CAMG....
0030: 00000804 434D4150 00000030 001000E0    ....CMAP...0....
0040: E0E00000 20000050 30303050 50500030    .... ..P000PPP.0
0050: 90805040 70707010 60E02060 E06080D0    ..P@ppp.`. `.`..
0060: A0A0A0A0 90E0C0C0 C0D0A0E0 424F4459    ............BODY
0070: 000163AC F8000F80 148A5544 2ABDEFFF    ..c.......UD*...  etc.

Interpretation:

      'F O R M' length  'I L B M"B M H D' <- start of BitMapHeader chunk
0000: 464F524D 00016418 494C424D 424D4844    FORM..d.ILBMBMHD

                                             Planes Mask
       length  WideHigh XorgYorg PlMkCoRe <- Compression Reserved
0010: 00000014 01400190 00000000 06000100    .....@..........

                                             start of C-AMiGa
      TranAspt PagwPagh 'C A M G' length  <- View modes chunk
0020: 00000A0B 01400190 43414D47 00000004    .....@..CAMG....

dir include:

      ViewMode 'C M A P' length   R g b R <- ViewMode 800=HAM | 4=LACE
0030: 00000804 434D4150 00000030 001000E0    ....CMAP...0....

       g b R g  b R g b  R g b R  g b R g <- Rgb's are for reg0 thru regN
0040: E0E00000 20000050 30303050 50500030    .... ..P000PPP.0

       b R g b  R g b R  g b R g  b R g b
0050: 90805040 70707010 60E02060 E06080D0    ..P@ppp.`. `.`..

       R g b R  g b R g  b R g b 'B O D Y'
0060: A0A0A0A0 90E0C0C0 C0D0A000 424F4459    ............BODY

                                             Compacted
       length   start of body data        <- (Compression=1 above)
0070: 000163AC F8000F80 148A5544 2ABDEFFF    ..c.......UD*...
0080: FFBFF800 0F7FF7FC FF04F85A 77AD5DFE    ...........Zw.].  etc.

Simple CAMG ViewModes:  HIRES=0x8000  LACE=0x4  HAM=0x800  HALFBRITE=0x80

( Release 2 ILBMs may contain a LONGWORD ViewPort ModeID in CAMG )


33 / / FORM ILBM / Interpreting ILBMs

ILBM is a fairly simple IFF FORM.  All you really need to deal with to
extract the image are the following chunks:

BMHD
    Information about the size, depth, compaction method (see interpreted
    hex dump above).

CAMG
    Optional Amiga ViewModes chunk.  Most HAM and HALFBRITE ILBMs should
    have this chunk.  If no CAMG chunk is present, and image is 6 planes
    deep, assume HAM and you'll probably be right.  Some Amiga ViewModes
    flags are HIRES=0x8000, LACE=0x4, HAM=0x800, HALFBRITE=0x80.  2.0
    ILBM writers should write a full 32-bit mode ID in the CAMG.  See the
    IFF Manual for more information on writing and interpreting 32-bit
    CAMG values.

CMAP
    RGB values for color registers 0 to N.  Previously, 4-bit RGB
    components each left justified in a byte.  These should now be stored
    as a full 8-bit RGB values by duplicating 4-bit values in the high
    and low nibble of the byte.

BODY
    The pixel data, stored in an interleaved fashion as follows (each
    line individually compacted if BMHD Compression = 1):

                plane 0 scan line 0
                plane 1 scan line 0
                plane 2 scan line 0
                ...
                plane n scan line 0
                plane 0 scan line 1
                plane 1 scan line 1
                etc.

Optional Chunks
    Also watch for AUTH Author chunks and (c) copyright chunks and
    preserve any copyright information if you rewrite the ILBM.


33 / / FORM ILBM / ILBM BODY Compression

The BODY contains pixel data for the image.  Width, Height, and depth
(Planes) is specified in the BMHD.

If the BMHD Compression byte is 0, then the scan line data is not
compressed. If Compression=1, then each scan line is individually
compressed as follows:

    while (not produced the desired number of bytes)

            /* get a byte, call it N */

            if (N >= 0 && N <= 127)
                    /* copy the next N+1 bytes literally */

            if (N >= -127 && N <= -1)
                    /* repeat the next byte N+1 times */

            if (N == -128)
                    /* skip it, presumably it's padding */


33 / / FORM ILBM / Interpreting the Scan Line Data

If the ILBM is not HAM or HALFBRITE, then after parsing and uncompacting
if necessary, you will have N planes of pixel data.  Color register used
for each pixel is specified by looking at each pixel thru the planes. For
instance, if you have 5 planes, and the bit for a particular pixel is set
in planes 0 and 3:

        PLANE     4 3 2 1 0
        PIXEL     0 1 0 0 1

then that pixel uses color register binary 01001 = 9.

The RGB value for each color register is stored in the CMAP chunk of the
ILBM, starting with register 0, with each register's RGB value stored as
one byte of R, one byte G, and one byte of B, with each component left
justified in the byte.  (ie. Amiga R, G, and B components are each stored
in the high nibble of a byte)

But, if the picture is HAM or HALFBRITE, it is interpreted differently.
Hopefully, if the picture is HAM or HALFBRITE, the package that saved it
properly saved a CAMG chunk (look at a hex dump of your file with ASCII
interpretation - you will see the chunks - they all start with a
4-ASCII-char chunk ID).  If the picture is 6 planes deep and has no CAMG
chunk, it is probably HAM.   If you see a CAMG chunk, the `CAMG' is
followed by the 32-bit chunk length, and then the 32-bit Amiga view mode
flags.

HAM pictures will have the 0x800 bit set in CAMG chunk ViewModes. HALBRITE
pictures will have the 0x80 bit set.  See the graphics library chapters or
the Amiga Hardware Reference Manual for more information on HAM and
HALFBRITE modes.


33 / / FORM ILBM / Other ILBM Notes

Amiga ILBMs images must be stored as an even number of bytes in width.
However, the ILBM BMHD field w (width) should describe the actual image
width, not the rounded up width as stored.

ILBMs created with Electronic Arts IBM or Amiga Deluxe Paint II packages
are compatible (though you may have to use a `.lbm' filename extension on
an IBM).  The ILBM graphic files may be transferred between the machines
(or between the Amiga and IBM sides your Amiga if you have a CBM
Bridgeboard card installed) and loaded into either package.


33 / IFF FORM Specifications / FORM FTXT

The FTXT (Formatted TeXT) form is the standard format for sharing text on
the Amiga.  The Release 2 console device clip and paste functions, in
conjunction with the startup-sequence conclip command, pass clipped
console text through the clipboard as FTXT.

By supporting reading and writing of clipboard device FTXT, your
application will allow users to cut and paste text between your
application, other applications, and Amiga Shell windows.

The FTXT form is very simple.  Generally, for clip and paste operations,
you will only be concerned with the CHRS (character string) chunks of an
FTXT.  There may be one or more CHRS chunks, each of which contains a
non-NULL-terminated string of ASCII characters whose length is equal to
the length (StoredProperty.sp_Size) of the chunk.

Be aware that if you CollectionChunk() the CHRS chunks of an FTXT, the
list accumulated by IFFParse will be in reverse order from the chunk order
in the file.  See the ClipFTXT.c example at the end of this chapter for a
simple example of reading (and optionally writing) FTXT to and from the
clipboard.  See also the "Clipboard Device" and "Console Device" chapters
of the Amiga ROM Kernel Reference Manual: Devices for more information on
Release 2 console clip and paste.


33 IFFParse Library / IFFParse Examples

Two examples follow: ClipFTXT.c, and Sift.c.  These are simple examples
that demonstrate the use of the IFFParse library.  More complex examples
for displaying and saving ILBMs may be found in the IFF Appendix of the
Amiga ROM Kernel Reference Manual: Devices.

 Clipboard FTXT Example    IFF Scanner Example


33 IFFParse Library / Function Reference

The following are brief descriptions of the IFFParse functions discussed
in this chapter.  IFFParse library functions are avialable in Release 2 of
the Amiga OS and are backward compatible with older versions of the
system.  Further information about these and other IFFParse functions can
be found in the 3rd edition of the Amiga ROM Kernel Reference Manual:
Includes and Autodocs, also from Addison-Wesley.

                  Table 33-2: IFFParse Library Functions
  _______________________________________________________________________
 |                                                                       |
 |            Function              Description                          |
 |=======================================================================|
 |            AllocIFF()  Creates an IFFHandle structure.                |
 |             FreeIFF()  Frees the IFFHandle structure created with     |
 |                        AllocIFF().                                    |
 |             OpenIFF()  Initialize an IFFHandle structure to read or   |
 |                        write an IFF stream.                           |
 |            CloseIFF()  Closes an IFF context.                         |
 |-----------------------------------------------------------------------|
 |             InitIFF()  Initialize an IFFHandle as a user-defined      |
 |                        stream.                                        |
 |        InitIFFasDOS()  Initialize an IFFHandle as an AmigaDOS stream. |
 |       InitIFFasClip()  Initialize an IFFHandle as a clipboard stream. |
 |-----------------------------------------------------------------------|
 |       OpenClipboard()  Create a handle on a clipboard unit for        |
 |                        InitIFFasClip().                               |
 |            ParseIFF()  Parse an IFF file from an IFFHandle stream.    |
 |      ReadChunkBytes()  Read bytes from current chunk into a buffer.   |
 |    ReadChunkRecords()  Read record elements from the current chunk    |
 |                        into a buffer.                                 |
 |           StopChunk()  Declare a chunk that should cause ParseIFF()   |
 |                        to return.                                     |
 |        CurrentChunk()  Get the context node for the current chunk.    |
 |           PropChunk()  Specify a property chunk to store.             |
 |            FindProp()  Search for a stored property in a given        |
 |                        context.                                       |
 |     CollectionChunk()  Declare a chunk type for collection.           |
 |      FindCollection()  Get a pointer to the current list of           |
 |                        collection items.                              |
 |          StopOnExit()  Declare a stop condition for exiting a chunk.  |
 |        EntryHandler()  Add an entry handler to the IFFHandle context. |
 |         ExitHandler()  Add an exit handler to the IFFHandle context.  |
 |-----------------------------------------------------------------------|
 |           PushChunk()  Push a given context node onto the top of the  |
 |                        context stack.                                 |
 |            PopChunk()  Pop the top context node off of the context    |
 |                        stack.                                         |
 |        CurrentChunk()  Get the top context node for the current chunk.|
 |         ParentChunk()  Get the nesting context node for a given chunk.|
 |-----------------------------------------------------------------------|
 |      AllocLocalItem()  Create a LocalContextItem (LCI) structure.     |
 |       LocalItemData()  Returns a pointer to the user data of a        |
 |                        LocalContextItem (LCI).                        |
 |      StoreLocalItem()  Insert a LocalContextItem (LCI).               |
 |  StoreItemInContext()  Store a LocalContextItem in a given context    |
 |                        node.                                          |
 |     FindPropContext()  Find the property context for the current      |
 |                        state.                                         |
 |       FindLocalItem()  Return a LocalContextItem from the context     |
 |                        stack.                                         |
 |       FreeLocalItem()  Free a LocalContextItem (LCI) created with     |
 |                        AllocLocalItem().                              |
 |   SetLocalItemPurge()  Set purge vector for a local context item.     |
 |_______________________________________________________________________|


Amiga® RKM Libraries: 34 Keymap Library

Amiga computers are sold internationally with a variety of local keyboards
which match the standards of particular countries. All Amigas have
keyboards which are physically similar, and keys which output the same
low-level raw key code for any particular physical key.  However, in
different countries, the keycaps of the keys may contain different letters
or symbols.  Since the physical position of a key determines the raw key
code that it generates, raw key codes are not internationally compatible.
For instance, on the German keyboard, the Y and Z keys are swapped when
compared to the USA keyboard.  The second key on the fifth row will
generate the same raw key code on all Amiga keyboards, but should be
decoded as a Z on a US keyboard and as a Y on a German keyboard.

The Amiga uses the ECMA-94 Latin1 International 8-bit character set, and
can map raw key codes to any desired ANSI character value, string, or
escape sequence.  This allows national keyboards to be supported by using
keymaps.  A keymap is a file which describes what character or string is
tied to what key code.  Generally, the user's startup-sequence will set a
system default keymap that is correct for the user's keyboard.  The
console.device translates the raw key codes into the correct characters
based on the installed keymap.  This includes the translation of special
deadkey sequential key combinations to produce accented international
characters.

Programs which perform keyboard input using the console.device, CON:,
RAW:, or Intuition VANILLAKEY, will receive the correct ASCII values for a
user's keycaps, based on their keymap.  But some applications may require
custom keymaps, or may need to perform their own translation between raw
key codes and ANSI characters. In this chapter, the term ANSI refers to
standard 8-bit character definitions which include printable ASCII
characters, special characters, and escape sequences.

Until V37, keymapping commands were only available in the console.device.
Keymap.library is a new library in Release 2 (V37).  It offers the some of
the keymap commands of the console.device, enabling applications to
inquire after the default keymap and map key codes to ANSI characters. It
also provides the ability to map ANSI characters back into raw codes.
Unlike the console.device however, it can not be used to select a keymap
for only one application, i.e., one console window.

As a prelude to the following material, note that the Amiga keyboard
transmits raw key information to the computer in the form of a key
position and a transition.  Raw key positions range from hexadecimal 00 to
7F.  When a key is released, its raw key position, plus hexadecimal 80, is
transmitted.

 Keymap Functions    Keyboard Layout    Function Reference


34 Keymap Library / Keymap Functions

                   Table 34-1: Keymap Library Functions
  ________________________________________________________________________
 |                       |                                                |
 | AskKeyMapDefault()    | Ask for a pointer to current default keymap    |
 |-----------------------|------------------------------------------------|
 | MapANSI()             | Encode an ANSI string into key codes           |
 |-----------------------|------------------------------------------------|
 | MapRawKey()           | Decode a raw key input event to an ANSI string |
 |-----------------------|------------------------------------------------|
 | SetKeyMapDefault()    | Set the current default keymap for the system  |
 |_______________________|________________________________________________|

                Table 34-2: Console Device Keymap Commands
  ________________________________________________________________________
 |                       |                                                |
 | CD_ASKKEYMAP          | Ask for the current console's keymap           |
 |-----------------------|------------------------------------------------|
 | CD_SETKEYMAP          | Set the current console's keymap               |
 |-----------------------|------------------------------------------------|
 | CD_ASKDEFAULTKEYMAP*  | Set the current default keymap                 |
 |-----------------------|------------------------------------------------|
 | CD_SETDEFAULTKEYMAP** | Ask for a pointer to current default keymap    |
 |-----------------------|------------------------------------------------|
 | *  Obsolete - use AskKeyMapDefault()                                   |
 | ** Obsolete - use SetKeyMapDefault()                                   |
 |________________________________________________________________________|

All of these commands deal with a set of pointers to key translation
arrays, known as a KeyMap structure.  The KeyMap structure is defined in
<devices/keymap.h> and is shown below.

    struct KeyMap
        {
        UBYTE *km_LoKeyMapTypes;
        ULONG *km_LoKeyMap;
        UBYTE *km_LoCapsable;
        UBYTE *km_LoRepeatable;
        UBYTE *km_HiKeyMapTypes;
        ULONG *km_HiKeyMap;
        UBYTE *km_HiCapsable;
        UBYTE *km_HiRepeatable;
        };

The KeyMap structure contains pointers to arrays which define the ANSI
character or string that should be produced when a key or a combination of
keys are pressed.  For example, a keymap might specify that the key with
raw value hex 20 should produce the ANSI character "a", and if the Shift
key is being held it should produce the character "A".

 Asking For the Default Keymap
 Setting the Default Keymap
 Accessing the Keymap For the Current Console
 Mapping Key Codes To ANSI Strings
 Mapping ANSI Strings To Key Codes
 Details Of the Keymap Structure
 Key Map Standards
 Dead-Class Keys
 Double-Dead Keys


34 / Keymap Functions / Asking For the Default Keymap

The AskKeyMapDefault() returns a pointer to the current default keymap.
To use the mapping functions in keymap.library it is normally not
necessary to call this function. They accept NULL as equivalent to 'use
default keymap' and will call this function for you. You can use this
pointer for example to cache the system default in order to temporarily
change the keymap your applications uses, or find the keymap in the
keymap.resource list of loaded keymaps.  You should never change the
system wide default keymap unless the user asks you to do so; since the
Amiga is a multitasking system, changing the keymap could interfere with
the behaviour of other applications.


34 / Keymap Functions / Setting the Default Keymap

The system default keymap can be set with the SetKeyMapDefault() function.
This function takes a pointer to a loaded keymap. In general, this
function should never be used by an application unless the application is
a system Preferences editor, or an application that takes over the system.
Normal applications should instead attach a console.device unit to their
own Intuition window (see the Devices volume), and use the console.device
command CD_SETKEYMAP to set a keymap only for their own console.

When making a keymap the system default, first check whether the keymap
has been loaded previously by checking the keymap list of the
keymap.resource.  If it has not been loaded already, it can be loaded from
devs:Keymaps, and added to the keymap list of keymap.resource. This will
ensure that other applications which may want the keymap will not have to
load a second instance. Once made the default, the keymap can never be
safely removed from memory, even after if it is no longer the default,
since other applications may still have and use a pointer to it.


34 / Keymap Functions / Accessing the Keymap For the Current Console

The function AskKeyMap() shown below does not return a pointer to a table
of pointers to currently assigned key mapping. Instead, it copies the
current set of pointers to a user-designated area of memory.  AskKeyMap()
returns a TRUE or FALSE value that says whether or not the function
succeeded.

The function SetKeyMap(), also shown below, copies the designated key map
data structure to the console device.  Thus this routine is complementary
to AskKeymap() in that it can restore an original key mapping as well as
establish a new one.

    Ask/SetKeyMap() functions.
    --------------------------
    These functions assume that you have already opened the console.device
    and that request is a valid IOStdReq structure for the newly opened
    console. These functions are not part of the keymap.library, nor of
    the console.device.  These merely demonstrate CD_ASKKEYMAP and
    CD_SETKEYMAP which are console.device commands.

/* These functions require that you have created a port and an IO request,
 * and have opened the console device as shown in the Console Device
 * chapter of the Devices volume of this manual set.
 */
#include <devices/keymap.h>

BOOL AskKeyMap(struct IOStdReq *request, struct KeyMap *keymap)
{
    request->io_Command = CD_ASKKEYMAP;
    request->io_Length = sizeof(struct KeyMap);
    request->io_Data = (APTR)keymap;  /* where to put it */
    DoIO(request);
    if(request->io_Error) return(FALSE);
    else  return(TRUE); /* if no error, it worked. */
}

BOOL SetKeyMap(struct IOStdReq *request,struct KeyMap *keymap)
{
    request->io_Command = CD_SETKEYMAP;
    request->io_Length = sizeof(struct KeyMap);
    request->io_Data = (APTR)keymap;      /* where to get it */
    DoIO(request);
    if(request->io_Error) return(FALSE);
    else  return(TRUE);     /* if no error, it worked. */
}


34 / Keymap Functions / Mapping Key Codes To ANSI Strings

MapRawKey() is converts raw key codes to ANSI characters based on a
default or supplied keymap.

    WORD MapRawKey(struct InputEvent *inputevent, UBYTE *buffer,
                   WORD bufferlength, struct Keymap *keymap);

MapRawKey() takes an IECLASS_RAWKEY inputevent, which may be chained, and
converts the key codes to ANSI characters which are placed in the
specified buffer. If the buffer would overflow, for example because a
longer string is attached to a key, -1 will be returned. If no error
occurred, MapRawKey() will return the number of bytes written in the
buffer.  The keymap argument can be set to NULL if the default keymap is
to be used for translation, or can be a pointer to a specific KeyMap
structure.

The following example shows how to implement the MapRawKey() function.

     maprawkey.c


34 / Keymap Functions / Mapping ANSI Strings To Key Codes

The MapANSI() function translates ANSI strings into raw key codes,
complete with qualifiers and (double) dead keys, based on a default or
supplied keymap.

    LONG MapANSI(UBYTE *string, LONG stringlength, UBYTE *buffer,
                 LONG bufferlength, struct KeyMap *keymap);

The string argument is a pointer to an ANSI string, of length
stringlength. The buffer argument is a pointer to the memory block where
the translated key codes will be placed.  The length of this buffer must
be indicated in WORDs since each translation will occupy one byte for the
key code and one for the qualifier. Since one ANSI character can be
translated to two dead keys and one key, the buffer must be at least 3
WORDs per character in the string to be translated. The keymap argument
can be set to NULL if the default keymap is to be used, or can be a
pointer to a KeyMap structure.  Upon return, the function will indicate
how many key code/qualifier combinations are placed in the buffer or a
negative number in case an error occurred. If zero is returned, the
character could not be translated.

The following example shows the usage of MapANSI() and demonstrates how
returned key codes can be processed.

     mapansi.c


34 / Keymap Functions / Details Of the Keymap Structure

A KeyMap structure contains pointers to arrays which determine the
translation from raw key codes to ANSI characters.

    struct KeyMap
        {
        UBYTE *km_LoKeyMapTypes;
        ULONG *km_LoKeyMap;
        UBYTE *km_LoCapsable;
        UBYTE *km_LoRepeatable;
        UBYTE *km_HiKeyMapTypes;
        ULONG *km_HiKeyMap;
        UBYTE *km_HiCapsable;
        UBYTE *km_HiRepeatable;
        };

 LoKeyMap and HighKeyMap            String Output Keys
 LoKeyMapTypes and HiKeyMapTypes    Capsable Bit Tables
 More About Qualifiers              Repeatable Bit Tables


34 / / Details Of the Keymap Structure / LoKeyMap and HighKeyMap

The low key map provides translation of the key values from hex 00-3F; the
high key map provides translation of key values from hex 40-7F. Key values
from hex 68-7F are not used by the existing keyboards, but this may change
in the future. A raw key value (hex 00-7F) plus hex 80 is the release of
that key. If you need to check for raw key releases do it like this:

    if (keyvalue & 0x80)     {  /* do key up processing   */  }
    else                     {  /* do key down processing */  }

Raw output from the keyboard for the low key map does not include the
space bar, Tab, Alt, Ctrl, arrow keys, and several other keys.

                   Table 34-3: High Key Map Hex Values

     Key    Keycap Legend                Key    Keycap Legend
    Number  or Function                 Number  or Function
    ------  -------------               ------  -------------
      40    Space                       50-59   Function keys F1-F10
      41    Backspace                   5A-5E   Numeric Pad characters
      42    Tab                         5F      Help
      43    Enter                       60      Left Shift
      44    Return                      61      Right Shift
      45    Escape                      62      Caps Lock
      46    Delete                      63      Control
      4A    Numeric Pad character       64      Left Alt
      4C    Cursor Up                   65      Right Alt
      4D    Cursor Down                 66      Left Amiga
      4E    Cursor Right                67      Right Amiga
      4F    Cursor Left

The keymap table for the low and high keymaps consists of 4-byte entries,
one per hex key code. These entries are interpreted in one of three
possible ways:

    * As four separate bytes, specifying how the key is to be
      interpreted when pressed alone, with one qualifier, with another
      qualifier, or with both qualifiers (where a qualifier is one of
      three possible keys:  Ctrl, Alt, or Shift).

    * As a longword containing the address of a string descriptor,
      where a string of characters is to be output when this key is
      pressed. If a string is to be output, any combination of
      qualifiers can affect the string that may be transmitted.

    * As a longword containing the address of a dead-key descriptor,
      where additional data describe the character to be output when
      this key is pressed alone or with another dead key.

    The keymap tables must be word aligned.
    ---------------------------------------
    The keymap tables must begin aligned on a word boundary.  Each
    entry is four bytes long, thereby maintaining word alignment
    throughout the table.  This is necessary because some of the entries
    may be longword addresses and must be aligned properly for the
    68000.


34 / / Details Of Keymap Structure / LoKeyMapTypes and HiKeyMapTypes

The tables named km_LoKeyMapTypes and km_HiKeyMapTypes each contain one
byte per raw key code. Each byte defines the type of entry that is found
in the keymap table for that raw key code.

Possible key types are:

    * Any of the qualifier groupings noted below

    * KCF_STRING + any combination of KCF_SHIFT, KCF_ALT, KCF_CONTROL
      (or KC_NOQUAL) if the result of pressing the key is to be a
      stream of bytes (and key-with-one-or-more-qualifiers is to be
      one or more alternate streams of bytes).

      Any key can be made to output up to eight unique byte streams if
      KCF_STRING is set in its keytype. The only limitation is that
      the total length of all of the strings assigned to a key must be
      within the "jump range" of a single byte increment. See the
      "String Output Keys" section below for more information.

    * KCF_DEAD + any combination of KCF_SHIFT, KCF_ALT, KCF_CONTROL
      (or KC_NOQUAL) if the key is a dead-class key and can thus
      modify or be modified by another dead-class key. See the
      "Dead-Class Keys" section below for more information.

The low keytype table covers the raw key codes from hex 00-3F and contains
one byte per key code. Therefore this table contains 64 (decimal) bytes.
The high keytype table covers the raw key codes from hex 40-7F and
contains 64 (decimal) bytes.


34 / / Details Of the Keymap Structure / More About Qualifiers

For keys such as the Return key or Esc key, the qualifiers specified in
the keytypes table (up to two) are the qualifiers used to establish the
response to the key.  This is done as follows.  In the keytypes table, the
values listed for the key types are those listed for the qualifiers in
<devices/keymap.h> and <devices/keymap.i>. Specifically, these qualifier
equates are:

                    KC_NOQUAL    0x00
                    KCF_SHIFT    0x01
                    KCF_ALT      0x02
                    KCF_CONTROL  0x04
                    KC_VANILLA   0x07
                    KCF_DOWNUP   0x08
                    KCF_STRING   0x40

As shown above, the qualifiers for the various types of keys occupy
specific bit positions in the key types control byte. As you may have
noticed, there are three possible qualifiers, but only a 4-byte space in
the table for each key. This does not allow space to describe what the
computer should output for all possible combinations of qualifiers. A
solution exists, however, for "vanilla" keys, such as the alphabetic keys.
Here is how that works.

Keys of type KC_VANILLA use the 4 bytes to represent the data output for
the key alone, Shifted key, Alt'ed key, and Shifted-and-Alt'ed key. Then
for the Ctrl-key-plus-vanilla-key, use the code for the key alone with
bits 6 and 5 set to 0.

    The Vanilla Qualifier Does Not Mean Plain.
    ------------------------------------------
    The qualifier KC_VANILLA is equivalent to
    KCF_SHIFT+KCF_ALT+KCF_CONTROL.

This table shows how to interpret the keymap for various combinations of
the qualifier bits:

                    Table 34-4: Keymap Qualifier Bits

                           Then data at this position in the keytable is
    If Keytype is:         output when the key is pressed along with:
    --------------         ---------------------------------------------
    KC_NOQUAL                    -           -     -      alone
    KCF_SHIFT                    -           -     Shift  alone
    KCF_ALT                      -           -     Alt    alone
    KCF_CONTROL                  -           -     Ctrl   alone
    KCF_ALT+KCF_SHIFT            Shift+Alt   Alt   Shift  alone
    KCF_CONTROL+KCF_ALT          Ctrl+Alt    Ctrl  Alt    alone
    KCF_CONTROL+KCF_SHIFT        Ctrl+Shift  Ctrl  Shift  alone
    KC_VANILLA                   Shift+Alt   Alt   Shift  alone*

    *Special case--Ctrl key, when pressed with one of the alphabet keys
    and certain others, is to output key-alone value with the bits 6 and
    5 set to zero.


34 / / Details Of the Keymap Structure / String Output Keys

When a key is to output a string, the keymap table contains the address of
a string descriptor in place of a 4-byte mapping of a key. Here is a
partial table for a new high keymap table that contains only three entries
thus far. The first two are for the space bar and the backspace key; the
third is for the tab key, which is to output a string that says "[TAB]".
An alternate string, "[SHIFTED-TAB]", is also to be output when a shifted
TAB key is pressed.

    newHiMapTypes:
      DC.B  KCF_ALT,KC_NOQUAL,    ;key 41
      DC.B  KCF_STRING+KCF_SHIFT, ;key 42
          ...  ;(more)
    newHiMap:
      DC.B  0,0,$A0,$20  ;key 40: space bar, and Alt-space bar
      DC.B  0,0,0,$08    ;key 41: Back Space key only
      DC.L  newkey42     ;key 42: new string definition to output for Tab
          ...  ;(more)
    newkey42:
      DC.B  new42ue - new42us   ;length of the unshifted string
      DC.B  new42us - newkey42  ;number of bytes from start of
                                ;string descriptor to start of this string
      DC.B  new42se - new42ss   ;length of the shifted string
      DC.B  new42ss - newkey42  ;number of bytes from start of
                                ;string descriptor to start of this string
    new42us:  DC.B        '[TAB]'
    new42ue:
    new42ss:  DC.B        '[SHIFTED-TAB]'
    new42se:

The new high map table points to the string descriptor at address
newkey42. The new high map types table says that there is one qualifier,
which means that there are two strings in the key string descriptor.

Each string in the descriptor takes two bytes in this part of the table:
the first byte is the length of the string, and the second byte is the
distance from the start of the descriptor to the start of the string.
Therefore, a single string (KCF_STRING + KC_NOQUAL) takes 2 bytes of
string descriptor. If there is one qualifier, 4 bytes of descriptor are
used. If there are two qualifiers, 8 bytes of descriptor are used. If
there are 3 qualifiers, 16 bytes of descriptor are used. All strings start
immediately following the string descriptor in that they are accessed as
single-byte offsets from the start of the descriptor itself. Therefore,
the distance from the start of the descriptor to the last string in the
set (the one that uses the entire set of specified qualifiers) must start
within 255 bytes of the descriptor address.

Because the length of the string is contained in a single byte, the length
of any single string must be 255 bytes or less while also meeting the
"reach" requirement. However, the console input buffer size limits the
string output from any individual key to 32 bytes maximum.

The length of a keymap containing string descriptors and strings is
variable and depends on the number and size of the strings that you
provide.


34 / / Details Of the Keymap Structure / Capsable Bit Tables

The vectors km_LoCapsable and km_HiCapsable each point to an array of 8
bytes that contain more information about the keytable entries.
Specifically, if the Caps Lock key has been pressed (the Caps Lock LED is
on) and if there is a bit on in that position in the capsable map, then
this key will be treated as though the Shift key is now currently pressed.
For example, in the default key mapping, the alphabetic keys are
"capsable" but the punctuation keys are not. This allows you to set the
Caps Lock key, just as on a normal typewriter, and get all capital
letters. However, unlike a normal typewriter, you need not go out of Caps
Lock to correctly type the punctuation symbols or numeric keys.

In the byte array, the bits that control this feature are numbered from
the lowest bit in the byte, and from the lowest memory byte address to the
highest. For example, the bit representing capsable status for the key
that transmits raw code 00 is bit 0 in byte 0; for the key that transmits
raw code 08 it is bit 0 in byte 1, and so on.

There are 64 bits (8 bytes) in each of the two capsable tables.


34 / / Details Of the Keymap Structure / Repeatable Bit Tables

The vectors km_LoRepeatable and km_HiRepeatable each point to an array of
8 bytes that contain additional information about the keytable entries. A
bit for each key indicates whether or not the specified key should repeat
at the rate set by the Input Preferences program.

The bit positions correspond to those specified in the capsable bit table.
If there is a 1 in a specific position, the key can repeat. There are 64
bits (8 bytes) in each of the two repeatable tables.


34 / Keymap Functions / Key Map Standards

Users and programs depend on certain predictable behaviors from all
keyboards and keymaps. With the exception of dead-class keys (see
"Dead-Class Keys" section), mapping of keys in the low key map should
follow these general rules:

    * When pressed alone, keys should transmit the ASCII equivalent of
      the unshifted letter or lower symbol on the keycap.

    * When Shifted, keys should transmit the ASCII equivalent of the
      shifted letter or upper symbol printed on the keycap.

    * When Alt'ed, keys should generally transmit the same character
      (or act as the same deadkey) as the Alt'ed key in the usa1
      keymap.

    * When pressed with CTRL alone, alphabetic keys should generally
      transmit their unshifted value but with bits 5 and 6 cleared.
      This allows keyboard typing of "control characters."  For
      example, the C key (normally value $63) should transmit value
      $03 (Ctrl-C) when Ctrl and C are pressed together.

The keys in the high key map (keys with raw key values $40 and higher) are
generally non-alphanumeric keys such as those used for editing (backspace,
delete, cursor keys, etc.), and special Amiga keys such as the function
and help keys. Keymaps should translate these keys to the same values or
strings as those shown in table 34-6, ROM Default Key Mapping.

In addition to their normal unshifted and shifted values, the following
translations are standard for particular qualified high keymap keys:

                   Generates     If Used with Qualifier,
        Key        This Value    Generates This Value
        ---        ----------    -----------------------
        Space         $20        $A0 with qualifier KCF_ALT
        Return        $0D        $0A with qualifier KCF_CONTROL
        Esc           $1B        $9B with qualifier KCF_ALT


34 / Keymap Functions / Dead-Class Keys

All of the national keymaps, including USA, contain dead-class keys. This
term refers to keys that either modify or can themselves be modified by
other dead-class keys.  There are two types of dead-class keys: dead and
deadable.  A dead key is one which can modify certain keys pressed
immediately following.  For example, on the German keyboard there is a
dead key marked with the grave accent (`). The dead key produces no
console output, but when followed by (for instance) the A key, the
combination will produce the a-grave  (à) character (National Character
Code $E0).  On the U.S. keyboard, Alt-G is the deadkey used to add the
grave accent (`) to the next appropriate character typed. A deadable key
is one that can be prefixed by a dead key.  The A key in the previous
example is a deadable key.  Thus, a dead key can only affect the output of
a deadable key.

For any key that is to have a dead-class function, whether dead or
deadable, the qualifier KCF_DEAD flag must be included in the entry for
the key in the KeyMapTypes table.  The KCF_DEAD type may also be used in
conjunction with the other qualifiers.  Furthermore, the key's keymap
table entry must contain the longword address of the key's dead-key
descriptor data area in place of the usual 4 ASCII character mapping.

Below is an excerpt from the Amiga 1000 German key map which is referred
to in the following discussion.

    KMLowMapType:
        DC.B    KCF_DEAD+KC_VANILLA     ; aA (Key 20)
                    ...                 ; (more...)
        DC.B    KCF_DEAD+KC_VANILLA     ; hH (Key 25)
                    ...                 ; (more...)
    KMLowMap:
        DC.L    key20                   ; a, A, ae, AE
                    ...                 ; (more...)
        DC.L    key25                   ; h, H, dead ^
                    ...                 ; (more...)
    ;------ possible dead keys
    key25:
        DC.B    0,'h',0,'H'             ; h, H
        DC.B    DPF_DEAD,3,DPF_DEAD,3   ; dead ^, dead ^
        DC.B    0,$08,0,$08,0,$88,0,$88 ; control translation
                    ...                 ; (more...)
    ;------ deadable keys (modified by dead keys)
    key20:              ; a, A, ae, AE
        DC.B    DPF_MOD,key20u-key20    ; deadable flag, number of
                                        ; bytes from start of key20
                                        ; descriptor to start of un-
                                        ; shifted data
        DC.B    DPF_MOD,key20s-key20    ; deadable flag, number of
                                        ; bytes from start of key20
                                        ; descriptor to start of shift-
                                        ; ed data
        DC.B    0,$E6,0,$C6             ; null flags followed by rest
        DC.B    0,$01,0,$01,0,$81,0,$81 ; of values (ALT, CTRL...)
    key20u:
        DC.B    'a',$E1,$E0,$E2,$E3,$E4 ; 'a' alone and characters to
                                        ; output when key alone is
                                        ; prefixed by a dead key
        DC.B    $E1,$E1,$E2,$E1,$E1,$E1 ; most recent is '
        DC.B    $E0,$E2,$E0,$E0,$E0,$E0 ; most recent is `
    key20s:
        DC.B    'A',$C1,$C0,$C2,$C3,$C4 ; SHIFTed 'a' and characters to
                                        ; output when SHIFTed key is
                                        ; prefixed by a dead key
        DC.B    $C1,$C1,$C2,$C1,$C1,$C1 ; most recent is '
        DC.B    $C0,$C2,$C0,$C0,$C0,$C0 ; most recent is `

In the example, key 25 (the H key) is a dead key and key 20 (the A key) is
a deadable key.  Both keys use the addresses of their descriptor data
areas as entries in the LoKeyMap table.  The LoKeyMapTypes table says that
there are four qualifiers for both: the requisite KCF_DEAD, as well as
KCF_SHIFT, KCF_ALT, and KCF_CONTROL.  The number of qualifiers determine
length and arrangement of the descriptor data areas for each key.  The
next table shows how to interpret the KeyMapTypes for various combinations
of the qualifier bits.  For each possible position a pair of bytes is
needed.  The first byte in each pair tells how to interpret the second
byte (more about this below).

                   Table 34-5: Dead Key Qualifier Bits
     _______________________________________________________________
    |                 |                                             |
    |                 | Then the pair of bytes in this position     |
    |                 | in the dead-class key descriptor data is    |
    | If type is:     | output when the key is pressed along with:  |
    |_________________|_____________________________________________|
    |                 |       |   |   |     |   |     |     |       |
    | NOQUAL          | alone | - | - |  -  | - |  -  |  -  |   -   |
    |-----------------|-------|---|---|-----|---|-----|-----|-------|
    | A               | alone | A | - |  -  | - |  -  |  -  |   -   |
    |-----------------|-------|---|---|-----|---|-----|-----|-------|
    | C               | alone | C | - |  -  | - |  -  |  -  |   -   |
    |-----------------|-------|---|---|-----|---|-----|-----|-------|
    | S               | alone | S | - |  -  | - |  -  |  -  |   -   |
    |-----------------|-------|---|---|-----|---|-----|-----|-------|
    | A+C             | alone | A | C | A+C | - |  -  |  -  |   -   |
    |-----------------|-------|---|---|-----|---|-----|-----|-------|
    | A+S             | alone | S | A | A+S | - |  -  |  -  |   -   |
    |-----------------|-------|---|---|-----|---|-----|-----|-------|
    | C+S             | alone | S | C | C+S | - |  -  |  -  |   -   |
    |-----------------|-------|---|---|-----|---|-----|-----|-------|
    | S+A+C (VANILLA) | alone | S | A | S+A | C | C+S | C+A | C+S+A |
    |_________________|_______|___|___|_____|___|_____|_____|_______|
    |                                                               |
    | The abbreviations A, C, S stand for KCF_ALT, KCF_CONTROL, and |
    | KCF_SHIFT, respectively.  Also note that the ordering is      |
    | reversed from that in the normal KeyMap table.                |
    |_______________________________________________________________|

Because keys 20 and 25 each use three qualifier bits (not including
KCF_DEAD), according to the table there must be 8 pairs of data, arranged
as shown. Had only KCF_ALT been set, for instance, (not including
KCF_DEAD), just two pairs would have been needed.

As mentioned earlier, the first byte of each data pair in the descriptor
data area specifies how to interpret the second byte.  There are three
possible values: 0, DPF_DEAD and DPF_MOD.  In the Amiga 1000 German keymap
listed above, DPF_DEAD appears in the data for key 25,  while DPF_MOD is
used for key 20.  It is the use of these flags that determines whether a
dead-class key has dead or deadable function.  A value of zero causes the
unrestricted output of the following byte.

If the flag byte is DPF_DEAD, then that particular key combination
(determined by the placement of the pair of bytes in the data table) is
dead and will modify the output of the next key pressed (if deadable). How
it modifies is controlled by the second byte of the pair which is used as
an index into part(s) of the data area for ALL the deadable (DPF_MOD set)
keys.

Before going further, an understanding of the structure of a descriptor
data area wherein DPF_MOD is set for one (or more) of its members is
necessary. Referring to the example, we see that DPF_MOD is set for the
first and second pairs of bytes.  According to its LoKeyMapTypes entry,
and using table 34-5 (Dead Key Qualifier Bits) as a guide, these pairs
represent the alone and SHIFTed values for the key.  When DPF_MOD is set,
the byte immediately following the flag must be the offset from the start
of the key's descriptor data area to the start of a table of bytes
describing the characters to output when this key combination is preceded
by any dead keys.  This is where the index mentioned above comes in.  The
value of the index from a prefixing dead key is used to determine which of
the bytes from the deadable keys special table to output.  The byte in the
index+1 position is sent out.  (The very first byte is the value to output
if the key was not prefixed by a dead key.)  Thus, if Alt-H is pressed
(dead) and then Shift-A, an `a' with a circumflex (^) accent will be
output. This is because:

    * The byte pair for the ALT position of the H key (key 25) is
      DPF_DEAD,3 so the index is 3.

    * The byte pair for the SHIFT position of the A key (key 20) is
      DPF_MOD, key20s-key20, so we refer to the table-of-bytes at
      key20s.

    * The third+1 byte of the table-of-bytes is $C2, an `a' character.

    A Note About Table Size.
    ------------------------
    The number of bytes in the table-of-bytes for all deadable keys
    must be equal to the highest index value of all dead keys plus 1.


34 / Keymap Functions / Double-Dead Keys

Double-dead keys are an extension of the dead-class keys explained above.
Unlike normal dead keys wherein one dead key of type DPF_DEAD can modify a
second of type DPF_MOD, double-dead keys employ two consecutive keys of
type DPF_DEAD to together modify a third of type DPF_MOD.

For example, the key on the German keyboard labeled with single quotes (
`' ) is a double-dead key.  When this key is pressed alone and then
pressed again shifted, there is no output.  But when followed by an
appropriate third key, for example the A key, the three keypresses combine
to produce an `a' with a circumflex (^) accent (character code $E2). Thus
the double-dead pair qualify the output of the A key.

The system always keeps the last two down key codes for possible further
translation.  If they are both of type DPF_DEAD and the key immediately
following is DPF_MOD then the two are used to form an index into the
(third) key's translation table as follows:

In addition to the index found after the DPF_DEAD qualifier in a normal
dead key, a second factor is included in the high nibble of double-dead
keys (it is shifted into place with DP_2DFACSHIFT).  Its value equals the
total number of dead key types + 1 in the keymap.  This second index also
serves as an identifying flag to the system that two dead keys can be
significant.

When a key of type DPF_MOD is pressed, the system checks the two key codes
which preceded the current one.  If they were both DPF_DEAD then the most
recent of the two is checked for the double-dead index/flag.  If it is
found then a new index is formed by multiplying the value in lower nibble
with that in the upper.  Then, the lower nibble of the least recent
DPF_DEAD key is added in to form the final offset.

Finally, this last value is used as an index into the translation table of
the current, DPF_MOD, key.

The translation table of all deadable (DPF_MOD) keys has [number of dead
key types + 1] * [number of double dead key types + 1] entries, arranged
in [number of double dead key types + 1] rows of [number of dead key types
+ 1] entries. This is because as indices are assigned for dead keys in the
keymap, those that are double dead keys are assigned the lower numbers.

Following is a code fragment from the German (d) keymap source:

    key0C:
        DC.B    DPF_DEAD,1+(6<<DP_2DFACSHIFT)   ; dead '
        DC.B    DPF_DEAD,2+(6<<DP_2DFACSHIFT)   ; dead `
        DC.B    0,'=',0,'+'                     ; =, +
    key20:                  ; a, A, ae, AE
        DC.B    DPF_MOD,key20u-key20,DPF_MOD,key20s-key20
        DC.B    0,$E6,0,$C6
        DC.B    0,$01,0,$01,0,$81,0,$81 ; control translation
    key20u:
        DC.B    'a',$E1,$E0,$E2,$E3,$E4
        DC.B    $E1,$E1,$E2,$E1,$E1,$E1 ; most recent is '
        DC.B    $E0,$E2,$E0,$E0,$E0,$E0 ; most recent is `
    key20s:
        DC.B    'A',$C1,$C0,$C2,$C3,$C4
        DC.B    $C1,$C1,$C2,$C1,$C1,$C1 ; most recent is '
        DC.B    $C0,$C2,$C0,$C0,$C0,$C0 ; most recent is `

Raw key0C, the German single quotes ( `' ) key, is a double dead key.
Pressing this key alone, then again while the shift key is down will
produce no output but will form a double-dead qualifier. The output of
key20 (A), a deadable key, will consequently be modified, producing an "a"
with a circumflex (^) accent. The mechanics are as follows:

  * When key0C is pressed alone the DPF_DEAD of the first byte pair in
    the key's table indicates that the key as dead. The second byte is
    then held by the system.

  * Next, when key0C is pressed again, this time with the Shift key down,
    the DPF_DEAD of the second byte pair (recall that the second pair is
    used because of the SHIFT qualifier) again indicates the key is a
    dead key.  The second byte of this pair is also held by the system.

  * Finally, when the A key is pressed the system recalls the latter of
    the two bytes it has saved. The upper nibble, $6, is multiplied by
    the lower nibble, $2. The result, $0C, is then added to the lower
    nibble of the earlier of the two saved bytes, $1. This new value,
    $0D, is used as an index into the (unshifted) translation table of
    key20. The character at position $0D is character $E2, an `a' with a
    circumflex (^) accent.

    Note About Double Dead Keys.
    ----------------------------
    If only one double-dead key is pressed before a deadable key then the
    output is the same as if the double-dead were a normal dead key. If
    shifted key0C is pressed on the German keyboard and then immediately
    followed by key20, the output produced is character $E0, ` à '.  As
    before, the upper nibble is multiplied with the lower, resulting in
    $0C. But because there was no second dead-key, this product is used
    as the final index.


34 Keymap Library / Keyboard Layout

The keys with key codes $2B and $30 in the following keyboard diagrams are
keys which are present on some national Amiga keyboards.

     Figure 34-1: Amiga 1000 Keyboard Showing Key Codes in Hex

     Figure 34-2: Amiga 500/2000/3000 Keyboard Showing Key Codes in Hex

The default values given above correspond to the values the console device
will return when these keys are pressed with the keycaps as shipped with
the standard American keyboard.

  Table 34-6: ROM Default (USA0) and USA1 Console Key Mapping

   Raw                    Unshifted          Shifted
   Key       Keycap        Default           Default
  Number     Legend         Value             Value
  ------     ------         -----             -----
    00        ` ~             ` (Accent grave)  ~ (tilde)
    01        1 !             1                 !
    02        2 @             2                 @
    03        3 #             3                 #
    04        4 $             4                 $
    05        5 %             5                 %
    06        6 ^             6                 ^
    07        7 &             7                 &
    08        8 *             8                 *
    09        9 (             9                 (
    0A        0 )             0                 )
    0B        - _             - (Hyphen)        _ (Underscore)
    0C        = +             =                 +
    0D        |                                 |
    0E                        (undefined)
    0F        0               0                 0 (Numeric pad)
    10        Q               q                 Q
    11        W               w                 W
    12        E               e                 E
    13        R               r                 R
    14        T               t                 T
    15        Y               y                 Y
    16        U               u                 U
    17        I               i                 I
    18        O               o                 O
    19        P               p                 P
    1A        [ {             [                 {
    1B        ] }             ]                 }
    1C                        (undefined)
    1D        1               1                 1 (Numeric pad)
    1E        2               2                 2 (Numeric pad)
    1F        3               3                 3 (Numeric pad)
    20        A               a                 A
    21        S               s                 S
    22        D               d                 D
    23        F               f                 F
    24        G               g                 G
    25        H               h                 H
    26        J               j                 J
    27        K               k                 K
    28        L               l                 L
    29        ; :             ;                 :
    2A        ' "             ' (single quote)  "
    2B                        (not on most
                               US keyboards)
    2C                        (undefined)
    2D        4               4                 4 (Numeric pad)
    2E        5               5                 5 (Numeric pad)
    2F        6               6                 6 (Numeric pad)
    30                        (not on most
                               US keyboards)
    31        Z               z                 Z
    32        X               x                 X
    33        C               c                 C
    34        V               v                 V
    35        B               b                 B
    36        N               n                 N
    37        M               m                 M
    38        , <             , (comma)         <
    39        . >             . (period)        >
    3A        / ?             /       ?
    3B                        (undefined)
    3C        .               .                 . (Numeric pad)
    3D        7               7                 7 (Numeric pad)
    3E        8               8                 8 (Numeric pad)
    3F        9               9                 9 (Numeric pad)
    40        (Space bar)     20                20
    41        Back Space      08                08
    42        Tab             09                09
    43        Enter           0D                0D (Numeric pad)
    44        Return          0D                0D
    45        Esc             1B                1B
    46        Del             7F                7F
    47                        (undefined)
    48                        (undefined)
    49                        (undefined)
    4A        -               -                 - (Numeric Pad)
    4B                        (undefined)
    4C        Up arrow        <CSI>A            <CSI>T
    4D        Down arrow      <CSI>B            <CSI>S
    4E        Forward arrow   <CSI>C            <CSI> A (note blank space
                                                           after <CSI>)
    4F        Backward arrow  <CSI>D            <CSI> @ (note blank space
                                                           after <CSI>)
    50        F1              <CSI>0~           <CSI>10~
    51        F2              <CSI>1~           <CSI>11~
    52        F3              <CSI>2~           <CSI>12~
    53        F4              <CSI>3~           <CSI>13~
    54        F5              <CSI>4~           <CSI>14~
    55        F6              <CSI>5~           <CSI>15~
    56        F7              <CSI>6~           <CSI>16~
    57        F8              <CSI>7~           <CSI>17~
    58        F9              <CSI>8~           <CSI>18~
    59        F10             <CSI>9~           <CSI>19~
    5A        (               (                 ( (usa1 Numeric pad)
    5B        )               )                 ) (usa1 Numeric pad)
    5C        /               /                 / (usa1 Numeric pad)
    5D        *               *                 * (usa1 Numeric pad)
    5E        +               +                 + (usa1 Numeric pad)
    5F        HELP            <CSI>?~           <CSI>?~

   Raw        Function
   Key        or Keycap
  Number      Legend
  ------      ---------
    60        Shift (left of space bar)
    61        Shift (right of space bar)
    62        Caps Lock
    63        Ctrl
    64        (Left) Alt
    65        (Right) Alt
    66        Amiga (left of space bar)            Left Amiga
    67        Amiga (right of space bar)           Right Amiga
    68        Left mouse button (not converted)    Inputs are only for the
    69        Right mouse button (not converted)   mouse connected to
    6A        Middle mouse button (not converted)  Intuition, (currently
    6B        (undefined)                          gameport one).
    6C        (undefined)
    6D        (undefined)
    6E        (undefined)
    6F        (undefined)
    70-7F     (undefined)
    80-F8     Up transition (release or unpress key of one
              of the above keys) (80 for 00, F8 for 7F)
    F9        Last key code was bad
              (was sent in order to resynchronize)
    FA        Keyboard buffer overflow
    FB        (undefined, reserved for
              keyboard processor catastrophe)
    FC        Keyboard selftest failed
    FD        Power-up key stream start.
              Keys pressed or stuck at power-up
              will be sent between FD and FE.
    FE        Power-up key stream end
    FF        (undefined, reserved)
    FF        Mouse event, movement only,
              no button change (not converted)

    Notes about the preceding table:

    1) "<CSI>" is the Control Sequence Introducer, value hex 9B.

    2) "(undefined)" indicates that the current keyboard design should not
       generate this number.  If you are using SetKeyMap() to change the
       key map, the entries for these numbers must still be included.

    3) "(not converted)" refers to mouse button events. You must use the
       sequence "<CSI>2{" to inform the console driver that you wish to
       receive mouse events; otherwise these will not be transmitted.

    4) "(RESERVED)" indicates that these key codes have been reserved for
       national keyboards.  The $2B code key will be between the
       double-quote (") and Return keys. The $30 code key will be between
       the Shift and Z keys.

          +---------------------------------------------------------------+
          | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
          | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 |
          | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 |
          | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 |
          |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
          | 00| 01| 02| 03| 04| 05| 06| 07| 08| 09| 0a| 0b| 0c| 0d| 0e| 0f|
+---------|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0000 00 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
| 0001 10 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
| 0010 20 | SP| ! | " | # | $ | % | & | ' | ( | ) | * | + | , | - | . | / |
| 0011 30 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | : | ; | < | = | > | ? |
| 0100 40 | @ | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O |
| 0101 50 | P | Q | R | S | T | U | V | W | X | Y | Z | [ | \ | ] | ^ | _ |
| 0110 60 | ` | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o |
| 0111 70 | p | q | r | s | t | u | v | w | x | y | z | { | | | } | ~ |   |
| 1000 80 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
| 1001 90 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
| 1010 a0 |NBSP ¡ | ¢ | £ | ¤ | ¥ | ¦ | § | ¨ | © | ª | « | ¬ |SHY| ® | ¯ |
| 1011 b0 | ° | ± | ² | ³ | ´ | µ | ¶ | · | ¸ | ¹ | º | » | ¼ | ½ | ¾ | ¿ |
| 1100 c0 | À | Á | Â | Ã | Ä | Å | Æ | Ç | È | É | Ê | Ë | Ì | Í | Î | Ï |
| 1101 d0 | Ð | Ñ | Ò | Ó | Ô | Õ | Ö | × | Ø | Ù | Ú | Û | Ü | Ý | Þ | ß |
| 1110 e0 | à | á | â | ã | ä | å | æ | ç | è | é | ê | ë | ì | í | î | ï |
| 1111 f0 | ð | ñ | ò | ó | ô | õ | ö | ÷ | ø | ù | ú | û | ü | ý | þ | ÿ |
+-------------------------------------------------------------------------+

      Figure 34-3: ECMA-94 Latin1 International 8-Bit Character Set


34 Keymap Library / Function Reference

The following chart gives a brief desription of the functions covered in
this chapter.  All of these functions require Release 2 or a later version
of the Amiga operating system.  See the Amiga ROM Kernel Reference Manual:
Includes and Autodocs for details on each function call.

                 Table 34-7: Keymap Library Functions
  __________________________________________________________________
 |                                                                  |
 |       Function                 Description                       |
 |==================================================================|
 |  AskKeyMapDefault()  Get a pointer to the current system default |
 |                      keymap                                      |
 |           MapANSI()  Convert ANSII string to raw key events      |
 |         MapRawKey()  Convert raw key events to ANSII             |
 |  SetKeyMapDefault()  Set the system default keymap               |
 |__________________________________________________________________|


Amiga® RKM Libraries: 35 Math Libraries

This chapter describes the structure and calling sequences required to
access the Motorola Fast Floating Point (FFP), the IEEE single-precision
math libraries and the IEEE double-precision math libraries via the
Amiga-supplied interfaces.

In its present state, the FFP library consists of three separate entities:
the basic math library, the transcendental math library, and C and
assembly-language interfaces to the basic math library plus FFP conversion
functions.  The IEEE single-precision, introduced in Release 2, and the
double-precision libraries each presently consists of two entities: the
basic math library and the transcendental math library.

    Open Each Library Separately.
    -----------------------------
    Each Task using an IEEE math library must open the library itself.
    Library base pointers to these libraries may not be shared.
    Libraries can be context sensitive and may use the Task structure to
    keep track of the current context.  Sharing of library bases by Tasks
    may seem to work in some systems.  This is true for any of the IEEE
    math libraries.

Depending on the compiler used, it is not always necessary to explicitly
call the library functions for basic floating point operations as adding,
subtracting, dividing, etc.  Consult the manual supplied with the compiler
for information regarding the compiler options for floating point
functions.

 Math Libraries and Functions
 FFP Floating Point Data Format
 FFP Basic Mathematics Library
 FFP Transcendental Mathematics Library
 FFP Mathematics Conversion Library
 IEEE Single-Precision Data Format
 IEEE Single-Precision Basic Math Library
 IEEE Single-Precision Transcendental Math Library
 IEEE Double-Precision Data Format
 IEEE Double-Precision Basic Math Library
 IEEE Double-Precision Transcendental Math Library
 Function Reference
 Compile and Link Commands for SAS C 5.10


35 Math Libraries / Math Libraries and Functions

There are six math libraries providing functions ranging from adding two
floating point numbers to calculating a hyperbolic cosine.  They are:

mathffp.library
    the basic function library

mathtrans.library
    the FFP transcendental math library

mathieeesingbas.library
    the IEEE single-precision library

mathieesingtrans.library
    the IEEE single-precision transcendental library

mathieeedoubbas.library
    the IEEE double-precision library

mathieesingtrans.library
    the IEEE double-precision transcendental library


35 Math Libraries / FFP Floating Point Data Format

FFP floating-point variables are defined within C by the float or FLOAT
directive. In assembly language they are simply defined by a DC.L/DS.L
statement. All FFP floating-point variables are defined as 32-bit entities
(longwords) with the following format:

         _____________________________________________
        |                                             |
        | MMMMMMMM    MMMMMMMM    MMMMMMMM    EEEEEEE |
        | 31          23          15          7       |
        |_____________________________________________|

The mantissa is considered to be a binary fixed-point fraction; except for
0, it is always normalized (the mantissa is shifted over and the exponent
adjusted, so that the mantissa has a 1 bit in its highest position).
Thus, it represents a value of less than 1 but greater than or equal to
1/2.

The sign bit is reset (0) for a positive value and set (1) for a negative
value.

The exponent is the power of two needed to correctly position the mantissa
to reflect the number's true arithmetic value.  It is held in excess-64
notation, which means that the two's-complement values are adjusted upward
by 64, thus changing $40 (-64) through $3F (+63) to $00 through $7F.  This
facilitates comparisons among floating-point values.

The value of 0 is defined as all 32 bits being 0s.  The sign, exponent,
and mantissa are entirely cleared.  Thus, 0s are always treated as
positive.

The range allowed by this format is as follows:

    DECIMAL:

         9.22337177 * 10^18 > +VALUE > 5.42101070 * 10^-20
        -9.22337177 * 10^18 < -VALUE < -2.71050535 * 10^-20

    BINARY (HEXADECIMAL):

         .FFFFFF * 2^63 > +VALUE > .800000 * 2^-63
        -.FFFFFF * 2^63 < -VALUE < -.800000 * 2^-64

Remember that you cannot perform any arithmetic on these variables without
using the fast floating-point libraries.  The formats of the variables are
incompatible with the arithmetic format of C-generated code; hence, all
floating-point operations are performed through function calls.


35 Math Libraries / FFP Basic Mathematics Library

The FFP basic math library contains entries for the basic mathematics
functions such as add, subtract and divide.  It resides in ROM and is
opened by calling OpenLibrary() with "mathffp.library" as the argument.

    #include <exec/types.h>
    #include <libraries/mathffp.h>

    #include <clib/mathffp_protos.h>

    struct Library *MathBase;

    VOID main()
    {
    if (MathBase = OpenLibrary("mathffp.library", 0))
        {
               . . .

        CloseLibrary(MathBase);
        }
    else
        printf("Can't open mathffp.library\n");
    }

The global variable MathBase is used internally for all future library
references.

 FFP Basic Functions


35 / FFP Basic Mathematics Library / FFP Basic Functions

SPAbs()    FLOAT SPAbs( FLOAT parm );
Take absolute value of FFP variable.

SPAdd()    FLOAT SPAdd( FLOAT leftParm, FLOAT rightParm);
    Add two FFP variables.

SPCeil()   FLOAT SPCeil( FLOAT parm );
    Computer largest integer less than or equal to variable.

SPCmp()    LONG  SPCmp( FLOAT leftParm, FLOAT rightParm);
    Compare two FFP variables.

SPDiv()    FLOAT SPDiv( FLOAT leftParm, FLOAT rightParm);
    Divide two FFP variables.

SPFix()    LONG  SPFix( FLOAT parm );
    Convert FFP variable to integer.

SPFloor()  FLOAT SPFloor( FLOAT parm );
    Compute least integer greater than or equal to variable.

SPFlt()    FLOAT SPFlt( long integer );
    Convert integer variable to FFP.

SPMul()    FLOAT SPMul( FLOAT leftParm, FLOAT rightParm);
    Multiply two FFP variables.

SPNeg()    FLOAT SPNeg( FLOAT parm );
    Take two's complement of FFP variable.

SPSub()    FLOAT SPSub( FLOAT leftParm, FLOAT rightParm);
    Subtract two FFP variables.

SPTst()    LONG  SPTst( FLOAT parm );
    Test an FFP variable against zero.

Be sure to include the proper data type definitions shown below.

    #include <exec/types.h>
    #include <libraries/mathffp.h>

    #include <clib/mathffp_protos.h>

    struct Library *MathBase;

    VOID main()
    {
    FLOAT f1, f2, f3;
    LONG   i1;

    if (MathBase = OpenLibrary("mathffp.library", 0))
        {
        i1 = SPFix(f1);            /* Call SPFix entry */
        f1 = SPFlt(i1);            /* Call SPFlt entry */

        if (SPCmp(f1,f2)) {};      /* Call SPCmp entry */
        if (!(SPTst(f1))) {};      /* Call SPTst entry */

        f1 = SPAbs(f2);            /* Call SPAbs entry */
        f1 = SPNeg(f2);            /* Call SPNeg entry */
        f1 = SPAdd(f2, f3);        /* Call SPAdd entry */
        f1 = SPSub(f2, f3);        /* Call SPSub entry */
        f1 = SPMul(f2, f3);        /* Call SPMul entry */
        f1 = SPDiv(f2, f3);        /* Call SPDiv entry */
        f1 = SPCeil(f2);           /* Call SPCeil entry */
        f1 = SPFloor(f2);          /* Call SPFloor entry */

        CloseLibrary(MathBase);
        }
    else
        printf("Can't open mathffp.library\n");
    }

The assembly language interface to the FFP basic math routines is shown
below, including some details about how the system flags are affected by
each operation.  The access mechanism is:

        MOVEA.L _MathBase,A6
        JSR _LVOSPFix(A6)

  __________________________________________________________________
 |                                                                  |
 |                FFP Basic Assembly Functions                      |
 |                                                                  |
 | Function      Input         Output               Condition Codes |
 |__________________________________________________________________|
 |             |             |                    |                 |
 | _LVOSPAbs   | D0=FFP arg  | D0=FFP absolute    | N=0             |
 |             |             |        value       | Z=1 if result   |
 |             |             |                    |     is zero     |
 |             |             |                    | V=0             |
 |             |             |                    | C=undefined     |
 |             |             |                    | X=undefined     |
 |-------------|-------------|--------------------|-----------------|
 | _LVOSPAdd   | D1=FFP arg1 | D0=FFP addition    | N=1 if result   |
 |             | D0=FFP arg2 |    of arg1 + arg2  |     is negative |
 |             |             |                    | Z=1 if result   |
 |             |             |                    |     is zero     |
 |             |             |                    | V=1 if result   |
 |             |             |                    |     overflowed  |
 |             |             |                    | C=undefined     |
 |             |             |                    | Z=undefined     |
 |-------------|-------------|--------------------|-----------------|
 | _LVOSPCeil  | D0=FFP arg  | D0=least integer   | N=1 if result   |
 |             |             | >=arg              |     is negative |
 |             |             |                    | Z=1 if result   |
 |             |             |                    |     is zero     |
 |             |             |                    | V=undefined     |
 |             |             |                    | C=undefined     |
 |             |             |                    | Z=undefined     |
 |-------------|-------------|--------------------|-----------------|
 | _LVOSPCmp   | D1=FFP arg1 | D0=+1 if arg1>arg2 | N=0             |
 |             | D0=FFP arg2 | D0=-1 if arg1<arg2 | Z=1 if result   |
 |             |             | D0=0 if arg1=arg2  |     is zero     |
 |             |             |                    | V=0             |
 |             |             |                    | C=undefined     |
 |             |             |                    | X=undefined     |
 |             |             |                    | GT=arg2>arg1    |
 |             |             |                    | GE=arg2>=arg1   |
 |             |             |                    | EQ=arg2=arg1    |
 |             |             |                    | NE=arg2<>arg1   |
 |             |             |                    | LT=arg2<arg1    |
 |             |             |                    | LE=arg2<=arg1   |
 |-------------|-------------|--------------------|-----------------|
 | _LVOSPDiv   | D1=FFP arg1 | D0=FFP division    | N=1 if result   |
 |             | D0=FFP arg2 |    of arg2/arg1    |     is negative |
 |             |             |                    | Z=1 if result   |
 |             |             |                    |     is zero     |
 |             |             |                    | V=1 if result   |
 |             |             |                    |     overflowed  |
 |             |             |                    | C=undefined     |
 |             |             |                    | Z=undefined     |
 |-------------|-------------|--------------------|-----------------|
 | _LVOSPFix   | D0=FFP arg  | D0=Integer         | N=1 if result   |
 |             |             | (two's complement) |     is negative |
 |             |             |                    | Z=1 if result   |
 |             |             |                    |     is zero     |
 |             |             |                    | V=1 if overflow |
 |             |             |                    |     occurred    |
 |             |             |                    | C=undefined     |
 |             |             |                    | X=undefined     |
 |-------------|-------------|--------------------|-----------------|
 | _LVOSPFloor | D0=FFP arg  | D0=largest integer | N=1 if result   |
 |             |             | <= arg             |     is negative |
 |             |             |                    | Z=1 if result   |
 |             |             |                    |     is zero     |
 |             |             |                    | V=undefined     |
 |             |             |                    | C=undefined     |
 |             |             |                    | Z=undefined     |
 |-------------|-------------|--------------------|-----------------|
 | _LVOSPFlt   | D0=Integer  | D0=FFP result      | N=1 if result   |
 |             |   (two's    |                    |     is negative |
 |             | complement) |                    | Z=1 if result   |
 |             |             |                    |     is zero     |
 |             |             |                    | V=0             |
 |             |             |                    | C=undefined     |
 |             |             |                    | X=undefined     |
 |-------------|-------------|--------------------|-----------------|
 | _LVOSPMul   | D0=FFP arg1 | D0=FFP             | N=1 if result   |
 |             | D1=FFP arg2 |    multiplication  |     is negative |
 |             |             |    of arg1*arg2    | Z=1 if result   |
 |             |             |                    |     is zero     |
 |             |             |                    | V=1 if result   |
 |             |             |                    |     overflowed  |
 |             |             |                    | C=undefined     |
 |             |             |                    | Z=undefined     |
 |             |             |                    |                 |
 |-------------|-------------|--------------------|-----------------|
 | _LVOSPNeg   | D0=FFP arg  | D0=FFP negated     | N=1 if result   |
 |             |             |                    |     is negative |
 |             |             |                    | Z=1 if result   |
 |             |             |                    |     is zero     |
 |             |             |                    | V=0             |
 |             |             |                    | C=undefined     |
 |             |             |                    | X=undefined     |
 |-------------|-------------|--------------------|-----------------|
 | _LVOSPSub   | D1=FFP arg1 | D0=FFP subtraction | N=1 if result   |
 |             | D0=FFP arg2 |    of arg2-arg1    |     is negative |
 |             |             |                    | Z=1 if result   |
 |             |             |                    |     is zero     |
 |             |             |                    | V=1 if result   |
 |             |             |                    |     overflowed  |
 |             |             |                    | C=undefined     |
 |             |             |                    | Z=undefined     |
 |-------------|-------------|--------------------|-----------------|
 | _LVOSPTst   | D1=FFP arg  | D0=+1 if arg>0.0   | N=1 if result   |
 |             |             | D0=-1 if arg<0.0   |     is negative |
 |             |             | D0=0 if arg=0.0    | Z=1 if result   |
 |             |             |                    |     is zero     |
 |             |             |                    | V=0             |
 |             |             |                    | C=undefined     |
 |             |             |                    | X=undefined     |
 |             | Note: This  |                    | EQ=arg=0.0      |
 |             | routine     |                    | NE=arg<>0.0     |
 |             | trashes the |                    | PL=arg>=0.0     |
 |             | arg in D1.  |                    | MI=arg<0.0      |
 |_____________|_____________|____________________|_________________|


35 Math Libraries / FFP Transcendental Mathematics Library

The FFP transcendental math library contains entries for the
transcendental math functions sine, cosine, and square root. It resides on
disk and is opened by calling OpenLibrary() with "mathtrans.library" as
the argument.

    #include <exec/types.h>
    #include <libraries/mathffp.h>

    #include <clib/mathffp_protos.h>
    #include <clib/mathtrans_protos.h>

    struct Library *MathTransBase;

    VOID main()
    {
    if (MathTransBase = OpenLibrary("mathtrans.library",0))
        {
                .
                .
                .
        CloseLibrary(MathTransBase);
        }
    else
        printf("Can't open mathtrans.library\n");
    }

The global variable MathTransBase is used internally for all future
library references.  Note that the transcendental math library is
dependent upon the basic math library, which it will open if it is not
open already.  If you want to use the basic math functions in conjunction
with the transcendental math functions however, you have to specifically
open the basic math library yourself.

 FFP Transcendental Functions


35 / Transcendental Mathematics Library / FFP Transcendental Functions

SPAsin()   FLOAT SPAsin( FLOAT parm );
    Return arccosine of FFP variable.

SPAcos()   FLOAT SPAcos( FLOAT parm );
    Return arctangent of FFP variable.

SPAtan()   FLOAT SPAtan( FLOAT parm );
    Return arcsine of FFP variable.

SPSin()    FLOAT SPSin( FLOAT parm );
    Return sine of FFP variable. This function accepts an FFP radian
    argument and returns the trigonometric sine value.  For extremely
    large arguments where little or no precision would result, the
    computation is aborted and the "V" condition code is set.  A direct
    return to the caller is made.

SPCos()    FLOAT SPCos( FLOAT parm );
    Return cosine of FFP variable.  This function accepts an FFP radian
    argument and returns the trigonometric cosine value.  For extremely
    large arguments where little or no precision would result, the
    computation is aborted and the "V" condition code is set.  A direct
    return to the caller is made.

SPTan()    FLOAT SPTan( FLOAT parm );
    Return tangent of FFP variable.  This function accepts an FFP radian
    argument and returns the trigonometric tangent value.  For extremely
    large arguments where little or no precision would result, the
    computation is aborted and the "V" condition code is set.  A direct
    return to the caller is made.

SPSincos() FLOAT SPSincos( FLOAT *cosResult, FLOAT parm);
    Return sine and cosine of FFP variable.  This function accepts an FFP
    radian argument and returns the trigonometric sine as its result and
    the trigonometric cosine in the first parameter.  If both the sine
    and cosine are required for a single radian value, this function will
    result in almost twice the execution speed of calling the SPSin() and
    SPCos() functions independently.  For extremely large arguments where
    little or no precision would result, the computation is aborted and
    the "V" condition code is set.  A direct return to the caller is made.

SPSinh()   FLOAT SPSinh( FLOAT parm );
    Return hyperbolic sine of FFP variable.

SPCosh()   FLOAT SPCosh( FLOAT parm );
    Return hyperbolic cosine of FFP variable.

SPTanh()   FLOAT SPTanh( FLOAT parm );
    Return hyperbolic tangent of FFP variable.

SPExp()    FLOAT SPExp( FLOAT parm );
    Return e to the FFP variable power.  This function accepts an FFP
    argument and returns the result representing the value of e
    (2.71828...) raised to that power.

SPLog()    FLOAT SPLog( FLOAT parm );
    Return natural log (base e) of FFP variable.

SPLog10()  FLOAT SPLog10( FLOAT parm );
    Return log (base 10) of FFP variable.

SPPow() FLOAT SPPow( FLOAT power, FLOAT arg );
    Return FFP arg2 to FFP arg1.

SPSqrt()   FLOAT SPSqrt( FLOAT parm );
    Return square root of FFP variable.

SPTieee()  FLOAT SPTieee( FLOAT parm );
    Convert FFP variable to IEEE format

SPFieee()  FLOAT SPFieee( FLOAT parm );
    Convert IEEE variable to FFP format.

Be sure to include proper data type definitions, as shown in the example
below.

     mathtrans.c

The Amiga assembly language interface to the FFP transcendental math
routines is shown below, including some details about how the system flags
are affected by the operation.  This interface resides in the library file
amiga.lib and must be linked with the user code. Note that the access
mechanism from assembly language is:

        MOVEA.L _MathTransBase,A6
        JSR     _LVOSPAsin(A6)

  _______________________________________________________________________
 |                                                                       |
 |               FFP Transcendental Assembly Functions                   |
 |                                                                       |
 | Function       Input            Output               Condition Codes  |
 |_______________________________________________________________________|
 |              |                |                    |                  |
 | _LVOSPAsin   | D0=FFP arg     | D0=FFP arcsine     | N=0              |
 |              |                |    radian          | Z=1 if result    |
 |              |                |                    |     is zero      |
 |              |                |                    | V=0              |
 |              |                |                    | C=undefined      |
 |              |                |                    | X=undefined      |
 |--------------|----------------|--------------------|------------------|
 | _LVOSPAcos   | D0=FFP arg     | D0=FFP arccosine   | N=0              |
 |              |                |    radian          | Z=1 if result    |
 |              |                |                    |     is zero      |
 |              |                |                    | V=1 if overflow  |
 |              |                |                    |     occurred     |
 |              |                |                    | C=undefined      |
 |              |                |                    | X=undefined      |
 |--------------|----------------|--------------------|------------------|
 | _LVOSPAtan   | D0=FFP arg     | D0=FFP arctangent  | N=0              |
 |              |                |    radian          | Z=1 if result    |
 |              |                |                    |     is zero      |
 |              |                |                    | V=0              |
 |              |                |                    | C=undefined      |
 |              |                |                    | X=undefined      |
 |--------------|----------------|--------------------|------------------|
 | _LVOSPSin    | D0=FFP arg     | D0=FFP sine        | N=1 if result    |
 |              |    in radians  |                    |     is negative  |
 |              |                |                    | Z=1 if result    |
 |              |                |                    |     is zero      |
 |              |                |                    | V=1 if result    |
 |              |                |                    | is meaningless   |
 |              |                |                    | (input magnitude |
 |              |                |                    |  too large)      |
 |              |                |                    | C=undefined      |
 |              |                |                    | X=undefined      |
 |--------------|----------------|--------------------|------------------|
 | _LVOSPCos    | D0=FFP arg     | D0=FFP cosine      | N=1 if result    |
 |              |    in radians  |                    |     is negative  |
 |              |                |                    | Z=1 if result    |
 |              |                |                    |     is zero      |
 |              |                |                    | V=1 if result    |
 |              |                |                    | is meaningless   |
 |              |                |                    | (input magnitude |
 |              |                |                    |  too large)      |
 |              |                |                    | C=undefined      |
 |              |                |                    | X=undefined      |
 |--------------|----------------|--------------------|------------------|
 | _LVOSPTan    | D0=FFP arg     | D0=FFP tangent     | N=1 if result    |
 |              |    in radians  |                    |     is negative  |
 |              |                |                    | Z=1 if result    |
 |              |                |                    |     is zero      |
 |              |                |                    | V=1 if result    |
 |              |                |                    | is meaningless   |
 |              |                |                    | (input magnitude |
 |              |                |                    |  too large)      |
 |              |                |                    | C=undefined      |
 |              |                |                    | X=undefined      |
 |--------------|----------------|--------------------|------------------|
 | _LVOSPSincos | D0=FFP arg     | D0=FFP sine        | N=1 if result    |
 |              |    in radians  | (D1)=FFP cosine    |     is negative  |
 |              | D1=Address     |                    | Z=1 if result    |
 |              |    to store    |                    |     is zero      |
 |              | cosine result  |                    | V=1 if result    |
 |              |                |                    | is meaningless   |
 |              |                |                    | (input magnitude |
 |              |                |                    |  too large)      |
 |              |                |                    | C=undefined      |
 |              |                |                    | X=undefined      |
 |--------------|----------------|--------------------|------------------|
 | _LVOSPSinh   | D0=FFP arg     | D0=FFP hyperbolic  | N=1 if result    |
 |              |    in radians  |    sine            |     is negative  |
 |              |                |                    | Z=1 if result    |
 |              |                |                    |     is zero      |
 |              |                |                    | V=1 if overflow  |
 |              |                |                    |     occurred     |
 |              |                |                    | C=undefined      |
 |              |                |                    | X=undefined      |
 |--------------|----------------|--------------------|------------------|
 | _LVOSPCosh   | D0=FFP arg     | D0=FFP hyperbolic  | N=1 if result    |
 |              |    in radians  |    cosine          |     is negative  |
 |              |                |                    | Z=1 if result    |
 |              |                |                    |     is zero      |
 |              |                |                    | V=1 if overflow  |
 |              |                |                    |     occurred     |
 |              |                |                    | C=undefined      |
 |              |                |                    | X=undefined      |
 |--------------|----------------|--------------------|------------------|
 | _LVOSPTanh   | D0=FFP arg     | D0=FFP hyperbolic  | N=1 if result    |
 |              |    in radians  |    tangent         |     is negative  |
 |              |                |                    | Z=1 if result    |
 |              |                |                    |     is zero      |
 |              |                |                    | V=1 if overflow  |
 |              |                |                    |     occurred     |
 |              |                |                    | C=undefined      |
 |              |                |                    | X=undefined      |
 |--------------|----------------|--------------------|------------------|
 | _LVOSPExp    | D0=FFP arg     | D0=FFP exponential | N=0              |
 |              |                |                    | Z=1 if result    |
 |              |                |                    |     is zero      |
 |              |                |                    | V=1 if overflow  |
 |              |                |                    |     occurred     |
 |              |                |                    | C=undefined      |
 |              |                |                    | Z=undefined      |
 |--------------|----------------|--------------------|------------------|
 | _LVOSPLog    | D0=FFP arg     | D0=FFP natural     | N=1 if result    |
 |              |                |    logarithm       |     is negative  |
 |              |                |                    | Z=1 if result    |
 |              |                |                    |     is zero      |
 |              |                |                    | V=1 if arg is    |
 |              |                |                    | negative or zero |
 |              |                |                    | C=undefined      |
 |              |                |                    | Z=undefined      |
 |--------------|----------------|--------------------|------------------|
 | _LVOSPLog10  | D0=FFP arg     | D0=FFP logarithm   | N=1 if result    |
 |              |                |    (base 10)       |     is negative  |
 |              |                |                    |Z=1 if result     |
 |              |                |                    |    is zero       |
 |              |                |                    |V=1 if arg is     |
 |              |                |                    | negative or zero |
 |              |                |                    | C=undefined      |
 |              |                |                    | Z=undefined      |
 |--------------|----------------|--------------------|------------------|
 | _LVOSPPow    | D0=FFP         | D0=FFP result of   | N=0              |
 |              | exponent value |    arg taken to    | Z=1 if result    |
 |              | D1=FFP         |    exp power       |     is zero      |
 |              | arg value      |                    | V=1 if result    |
 |              |                |                    |     overflowed   |
 |              |                |                    |     or arg < 0   |
 |              |                |                    | C=undefined      |
 |              |                |                    | Z=undefined      |
 |--------------|----------------|--------------------|------------------|
 | _LVOSPSqrt   | D0=FFP arg     | D0=FFP square root | N=0              |
 |              |                |                    | Z=1 if result    |
 |              |                |                    |     is zero      |
 |              |                |                    | V=1 if arg was   |
 |              |                |                    |     negative     |
 |              |                |                    | C=undefined      |
 |              |                |                    | Z=undefined      |
 |--------------|----------------|--------------------|------------------|
 | _LVOSPTieee  | D0=FFP         | D0=IEEE            | N=1 if result    |
 |              | format arg     |    floating-point  |     is negative  |
 |              |                |    format          | Z=1 if result    |
 |              |                |                    |     is zero      |
 |              |                |                    | V=undefined      |
 |              |                |                    | C=undefined      |
 |              |                |                    | Z=undefined      |
 |--------------|----------------|--------------------|------------------|
 | _LVOSPFieee  | D0=IEEE        | D0=FFP format      | N=undefined      |
 |              | floating-point |                    | Z=1 if result    |
 |              | format arg     |                    |     is zero      |
 |              |                |                    | V=1 if result    |
 |              |                |                    |     overflowed   |
 |              |                |                    | C=undefined      |
 |              |                |                    | Z=undefined      |
 |______________|________________|____________________|__________________|


35 Math Libraries / FFP Mathematics Conversion Library

The FFP mathematics conversion library provides functions to convert ASCII
strings to their FFP equivalents and vice versa.

It is accessed by linking code into the executable file being created. The
name of the file to include in the library description of the link command
line is amiga.lib.  When this is included, direct calls are made to the
conversion functions.  Only a C interface exists for the conversion
functions; there is no assembly language interface.  The basic math
library is required in order to access these functions.

    #include <exec/types.h>
    #include <libraries/mathffp.h>

    #include <clib/mathffp_protos.h>

    struct Library *MathBase;

    VOID main()
    {
    if (MathBase = OpenLibrary("mathffp.library", 33))
        {
               . . .

        CloseLibrary(MathBase);
        }
    else
        printf("Can't open mathffp.library\n");
    }

 Math Support Functions


35 / FFP Mathematics Conversion Library / Math Support Functions

afp()    FLOAT afp( BYTE *string );
    Convert ASCII string into FFP equivalent.

arnd()   VOID arnd( LONG place, LONG exp, BYTE *string);
    Round ASCII representation of FFP number.

dbf()    FLOAT dbf( ULONG exp, ULONG mant);
    Convert FFP dual-binary number to FFP equivalent.

fpa()    LONG fpa( FLOAT fnum, BYTE *string);
    Convert FFP variable into ASCII equivalent.

Be sure to include proper data type definitions, as shown in the example
below.  Print statements have been included to help clarify the format of
the math conversion function calls.

     mathffp.c


35 Math Libraries / IEEE Single-Precision Data Format

The IEEE single-precision variables are defined as 32-bit entities with
the following format:

         ______________________________________________
        |                                              |
        | SEEEEEEE    MMMMMMMM    MMMMMMMM    MMMMMMMM |
        | 31          23          15          7        |
        |______________________________________________|

    Hidden Bit In The Mantissa.
    ---------------------------
    There is a "hidden" bit in the mantissa part of the IEEE numbers.
    Since all numbers are normalized, the integer (high) bit of the
    mantissa is dropped off.  The IEEE single-precision range is 1.3E-38
    (1.4E-45 de-normalized) to 3.4E+38.

The exponent is the power of two needed to correctly position the mantissa
to reflect the number's true arithmetic value.  If both the exponent and
the mantissa have zero in every position, the value is zero.  If only the
exponent has zero in every position, the value is an unnormal (extremely
small).  If all bits of the exponent are set to 1 the value is either a
positive or negative infinity or a Not a Number (NaN).  NaN is sometimes
used to indicate an uninitialized variable.


35 Math Libraries / IEEE Single-Precision Basic Math Library

The ROM-based IEEE single-precision basic math library was introduced in
V36.  This library contains entries for the basic IEEE single-precision
mathematics functions, such as add, subtract, and divide.  (Note,
registered developers can license a disk-based version of this library
from CATS, for usage with V33).

The library is opened by making calling OpenLibrary() with
"mathieeesingbas.library" as the argument.  Do not share the library base
pointer between tasks -- see note at beginning of chapter for details.

    #include <exec/types.h>
    #include <libraries/mathieeesp.h>

    #include <clib/mathsingbas_protos.h>

    struct Library *MathIeeeSingBasBase;

    VOID main()
    {
        /* do not share base pointer between tasks. */
    if (MathIeeeSingBasBase = OpenLibrary("mathieeesingbas.library", 37))
        {
               .
               .
               .
        CloseLibrary(MathIeeeSingBasBase);
        }
    else
        printf("Can't open mathieeesingbas.library\n");
    }

The global variable MathIeeeSingBasBase is used internally for all future
library references.

If an 680X0/68881/68882 processor combination is available, it will be
used by the IEEE single-precision basic library instead of the software
emulation.  Also, if an autoconfigured math resource is available, that
will be used.  Typically this is a 68881 designed as a 16 bit I/O port,
but it could be another device as well.

 SP IEEE Basic Functions (V36 or Greater)


35 / SP Basic Math Library / SP IEEE Basic Functions (V36 or Greater)

IEEESPAbs()    FLOAT ( FLOAT parm );
    Take absolute value of IEEE single-precision variable.

IEEESPAdd()    FLOAT IEEESPAdd( FLOAT leftParm, FLOAT rightParm);
    Add two IEEE single-precision variables.

IEEESPCeil()   FLOAT IEEESPCeil( FLOAT parm );
    Compute least integer greater than or equal to variable.

IEEESPCmp()    LONG  IEEESPCmp( FLOAT leftParm, FLOAT rightParm );
    Compare two IEEE single-precision variables.

IEEESPDiv()    FLOAT IEEESPDiv( FLOAT dividend, FLOAT divisor );
    Divide two IEEE single-precision variables.

IEEESPFix()    LONG  IEEESPFix( FLOAT parm );
    Convert IEEE single-precision  variable to integer.

IEEESPFloor()  FLOAT IEEESPFloor( FLOAT parm );
    Compute largest integer less than or equal to variable.

IEEESPFlt()    FLOAT IEEESPFlt( long integer );
    Convert integer variable to IEEE single-precision.

IEEESPMul()    FLOAT IEEESPMul( FLOAT leftParm, FLOAT rightParm );
    Multiply two IEEE single-precision variables.

IEEESPNeg()    FLOAT IEEESPNeg( FLOAT parm );
    Take two's complement of IEEE single-precision variable.

IEEESPSub()    FLOAT IEEESPSub( FLOAT leftParm, FLOAT rightParm );
    Subtract two IEEE single-precision variables.

IEEESPTst()    LONG  IEEESPTst( FLOAT parm );
    Test an IEEE single-precision variable against zero.

Be sure to include proper data type definitions, as shown in the example
below.

     mathieeesingbas.c

The Amiga assembly language interface to the IEEE single-precision basic
math routines is shown below, including some details about how the system
flags are affected by each operation.  Note that the access mechanism from
assembly language is as shown below:

        MOVEA.L _MathIeeeSingBasBase,A6
        JSR     _LVOIEEESPFix(A6)

 _________________________________________________________________________
|                                                                         |
|                    SP IEEE Basic Assembly Functions                     |
|                                                                         |
| Function          Input              Output              Condition Codes|
|_________________________________________________________________________|
|                 |                  |                    |               |
| _LVOIEEESPFix   | D0=IEEE arg      | D0=Integer         | N=undefined   |
|                 | double-precision | (two's complement) | Z=undefined   |
|                 |                  |                    | V=undefined   |
|                 |                  |                    | C=undefined   |
|                 |                  |                    | X=undefined   |
|-----------------|------------------|--------------------|---------------|
| _LVOIEEESPFlt   | D0=Integer arg   | D0=IEEE            | N=undefined   |
|                 |    (two's        | single-precision   | Z=undefined   |
|                 |  complement)     |                    | V=undefined   |
|                 |                  |                    | C=undefined   |
|                 |                  |                    | X=undefined   |
|-----------------|------------------|--------------------|---------------|
| _LVOIEEESPCmp   | D0=IEEE arg1     | D0=+1 if arg1>arg2 | N=1 if result |
|                 | single-precision | D0=-1 if arg1<arg2 | is negative   |
|                 | D1=IEEE arg2     | D0=0 if arg1=arg2  | Z=1 if result |
|                 | single-precision |                    |     is zero   |
|                 |                  |                    | V=0           |
|                 |                  |                    | C=undefined   |
|                 |                  |                    | X=undefined   |
|                 |                  |                    | GT=arg2>arg1  |
|                 |                  |                    | GE=arg2>=arg1 |
|                 |                  |                    | EQ=arg2=arg1  |
|                 |                  |                    | NE=arg2<>arg1 |
|                 |                  |                    | LT=arg2<arg1  |
|                 |                  |                    | E= arg2<=arg1 |
|-----------------|------------------|--------------------|---------------|
| _LVOIEEESPTst   | D0=IEEE arg      | D0=+1 if arg>0.0   | N=1 if result |
|                 | single-precision | D0=-1 if arg<0.0   |   is negative |
|                 |                  | D0=0 if arg=0.0    | Z=1 if result |
|                 |                  |                    |     is zero   |
|                 |                  |                    | V=0           |
|                 |                  |                    | C=undefined   |
|                 |                  |                    | X=undefined   |
|                 |                  |                    | EQ=arg=0.0    |
|                 |                  |                    | NE=arg<>0.0   |
|                 |                  |                    | PL=arg>=0.0   |
|                 |                  |                    | MI=arg<0.0    |
|-----------------|------------------|--------------------|---------------|
| _LVOIEEESPAbs   | D0=IEEE arg      | D0=IEEE            | N=undefined   |
|                 | single-precision | single-precision   | Z=undefined   |
|                 |                  | absolute value     | V=undefined   |
|                 |                  |                    | C=undefined   |
|                 |                  |                    | X=undefined   |
|-----------------|------------------|--------------------|---------------|
| _LVOIEEESPNeg   | D0=IEEE arg      | D0=IEEE            | N=undefined   |
|                 | single-precision | single-precision   | Z=undefined   |
|                 |                  | negated            | V=undefined   |
|                 |                  |                    | C=undefined   |
|                 |                  |                    | X=undefined   |
|-----------------|------------------|--------------------|---------------|
| _LVOIEEESPAdd   | D0=IEEE arg1     | D0=IEEE            | N=undefined   |
|                 | single-precision | single-precision   | Z=undefined   |
|                 | D1=IEEE arg2     | addition of        | V=undefined   |
|                 | single-precision | arg1+arg2          | C=undefined   |
|                 |                  |                    | X=undefined   |
|-----------------|------------------|--------------------|---------------|
| _LVOIEEESPSub   | D0=IEEE arg1     | D0=IEEE            | N=undefined   |
|                 | single-precision | single-precision   | Z=undefined   |
|                 | D1=IEEE arg2     | subtraction of     | V=undefined   |
|                 | single-precision | arg1-arg2          | C=undefined   |
|                 |                  |                    | X=undefined   |
|-----------------|------------------|--------------------|---------------|
| _LVOIEEESPMul   | D0=IEEE arg1     | D0=IEEE            | N=undefined   |
|                 | single-precision | single-precision   | Z=undefined   |
|                 | D1=IEEE arg2     | multiplication of  | V=undefined   |
|                 | single-precision | arg1*arg2          | C=undefined   |
|                 |                  |                    | X=undefined   |
|-----------------|------------------|--------------------|---------------|
| _LVOIEEESPDiv   | D0=IEEE arg1     | D0=IEEE            | N=undefined   |
|                 | single-precision | single-precision   | Z=undefined   |
|                 | D1=IEEE arg2     | division of        | V=undefined   |
|                 | single-precision | arg1/arg2          | C=undefined   |
|                 |                  |                    | X=undefined   |
|-----------------|------------------|--------------------|---------------|
| _LVOIEEESPCeil  | D0=IEEE variable | D0=least integer   | N=undefined   |
|                 | single-precision | >= variable        | Z=undefined   |
|                 |                  |                    | V=undefined   |
|                 |                  |                    | C=undefined   |
|                 |                  |                    | X=undefined   |
|-----------------|------------------|--------------------|---------------|
| _LVOIEEESPFloor | D0=IEEE variable | D0=largest integer | N=undefined   |
|                 | single-precision | <= arg             | Z=undefined   |
|                 |                  |                    | V=undefined   |
|                 |                  |                    | C=undefined   |
|                 |                  |                    | X=undefined   |
|_________________|__________________|____________________|_______________|


35 Math Libraries / IEEE Single-Precision Transcendental Math Library

The IEEE single-precision transcendental math library was introduced in
V36.  It contains entries for transcendental math functions such as sine,
cosine, and square root.

This library resides on disk and is opened by calling OpenLibrary() with
"mathieeesingtrans.library" as the argument.  Do not share the library
base pointer between tasks -- see note at beginning of chapter.

   #include <exec/types.h>
   #include <libraries/mathieeesp.h>

   struct Library *MathIeeeSingTransBase;

   #include <clib/mathsingtrans_protos.h>

   VOID main()
   {
   if (MathIeeeSingTransBase = OpenLibrary("mathieeesingtrans.library",37))
       {
              . . .

       CloseLibrary(MathIeeeSingTransBase);
       }
   else  printf("Can't open mathieeesingtrans.library\n");
   }

The global variable MathIeeeSingTransBase is used internally for all
future library references.

The IEEE single-precision transcendental math library is dependent upon
the IEEE single-precision basic math library, which it will open if it is
not open already.  If you want to use the IEEE single-precision basic math
functions in conjunction with the transcendental math functions however,
you have to specifically open the basic math library yourself.

Just as the IEEE single-precision basic math library, the IEEE
single-precision transcendental math library will take advantage of a
680X0/68881 combination or another math resource, if present.

 SP IEEE Transcendental Functions (V36 Or Greater)


35 / / SP IEEE Transcendental Functions (V36 Or Greater)

IEEESPAsin()   FLOAT IEEESPAsin( FLOAT parm );
    Return arcsine of IEEE single-precision variable.

IEEESPAcos()   FLOAT IEEESPAcos( FLOAT parm );
    Return arccosine of IEEE single-precision variable.

IEEESPAtan()   FLOAT IEEESPAtan( FLOAT parm );
    Return arctangent of IEEE single-precision variable.

IEEESPSin()    FLOAT IEEESPSin( FLOAT parm );
    Return sine of IEEE single-precision variable.  This function accepts
    an IEEE radian argument and returns the trigonometric sine value.

IEEESPCos()    FLOAT IEEESPCos( FLOAT parm );
    Return cosine of IEEE single-precision variable.  This function
    accepts an IEEE radian argument and returns the trigonometric cosine
    value.

IEEESPTan()    FLOAT IEEESPTan( FLOAT parm );
    Return tangent of IEEE single-precision variable.  This function
    accepts an IEEE radian argument and returns the trigonometric tangent
    value.

IEEESPSincos() FLOAT IEEESPSincos( FLOAT *cosptr, FLOAT parm );
    Return sine and cosine of IEEE single-precision variable.  This
    function accepts an IEEE radian argument and returns the
    trigonometric sine as its result and the cosine in the first
    parameter.

IEEESPSinh()   FLOAT IEEESPSinh( FLOAT parm );
    Return hyperbolic sine of IEEE single-precision variable.

IEEESPCosh()   FLOAT IEEESPCosh( FLOAT parm );
    Return hyperbolic cosine of IEEE single-precision variable.

IEEESPTanh()   FLOAT IEEESPTanh( FLOAT parm );
    Return hyperbolic tangent of IEEE single-precision variable.

IEEESPExp()    FLOAT IEEESPExp( FLOAT parm );
    Return e to the IEEE variable power.  This function accept an IEEE
    single-precision argument and returns the result representing the
    value of e (2.712828...) raised to that power.

IEEESPFieee()  FLOAT IEEESPFieee( FLOAT parm );
    Convert IEEE single-precision number to IEEE single-precision number.
    The only purpose of this function is to provide consistency with the
    double-precision math IEEE library.

IEEESPLog()    FLOAT IEEESPLog( FLOAT parm );
    Return natural log (base e of IEEE single-precision variable.

IEEESPLog10()  FLOAT IEEESPLog10( FLOAT parm );
    Return log (base 10) of IEEE single-precision variable.

IEEESPPow()    FLOAT IEEESPPow( FLOAT exp, FLOAT arg );
    Return IEEE single-precision arg2 to IEEE single-precision arg1.

IEEESPSqrt()   FLOAT IEEESPSqrt( FLOAT parm );
    Return square root of IEEE single-precision variable.

IEEESPTieee()  FLOAT IEEESPTieee( FLOAT parm );
    Convert IEEE single-precision number to IEEE single-precision number.
    The only purpose of this function is to provide consistency with the
    double-precision math IEEE library.

Be sure to include the proper data type definitions as shown below.

     mathieeesingtrans.c

The section below describes the Amiga assembly interface to the IEEE
single-precision transcendental math library.  The access mechanism from
assembly language is:

        MOVEA.L _MathIeeeSingTransBase,A6
        JSR     _LVOIEEESPAsin(A6)

 _________________________________________________________________________
|                                                                         |
|               SP IEEE Transcendental Assembly Functions                 |
|                                                                         |
| Function           Input              Output            Condition Codes |
|_________________________________________________________________________|
|                  |                  |                     |             |
| _LVOIEEESPAsin   | D0=IEEE arg      | D0=IEEE arcsine     | N=undefined |
|                  |                  |    radian           | Z=undefined |
|                  |                  |                     | V=undefined |
|                  |                  |                     | C=undefined |
|                  |                  |                     | X=undefined |
|------------------|------------------|---------------------|-------------|
| _LVOIEEESPAcos   | D0=IEEE arg      | D0=IEEE arccosine   | N=undefined |
|                  | single-precision |    radian           | Z=undefined |
|                  |                  |                     | V=undefined |
|                  |                  |                     | C=undefined |
|                  |                  |                     | X=undefined |
|------------------|------------------|---------------------|-------------|
| _LVOIEEESPAtan   | D0=IEEE arg      | D0=IEEE arctangent  | N=undefined |
|                  | single-precision |    radian           | Z=undefined |
|                  |                  |                     | V=undefined |
|                  |                  |                     | C=undefined |
|                  |                  |                     | X=undefined |
|------------------|------------------|---------------------|-------------|
| _LVOIEEESPSin    | D0=IEEE arg      | D0=IEEE sine        | N=undefined |
|                  |    in radians    |                     | Z=undefined |
|                  | single-precision |                     | V=undefined |
|                  |                  |                     | C=undefined |
|                  |                  |                     | X=undefined |
|------------------|------------------|---------------------|-------------|
| _LVOIEEESPCos    | D0=IEEE arg      | D0=IEEE cosine      | N=undefined |
|                  |    in radians    |                     | Z=undefined |
|                  | single-precision |                     | V=undefined |
|                  |                  |                     | C=undefined |
|                  |                  |                     | X=undefined |
|------------------|------------------|---------------------|-------------|
| _LVOIEEESPTan    | D0=IEEE arg      | D0=IEEE tangent     | N=undefined |
|                  |    in radians    |                     | Z=undefined |
|                  | single-precision |                     | V=undefined |
|                  |                  |                     | C=undefined |
|                  |                  |                     | X=undefined |
|------------------|------------------|---------------------|-------------|
| _LVOIEEESPSincos | A0=Addr to store | D0=IEEE sine        | N=undefined |
|                  |    cosine result | (A0)=IEEE cosine    | Z=undefined |
|                  | D0=IEEE arg      |                     | V=undefined |
|                  |    in radians    |                     | C=undefined |
|                  |                  |                     | X=undefined |
|------------------|------------------|---------------------|-------------|
| _LVOIEEESPSinh   | D0=IEEE arg      | D0=IEEE hyperbolic  | N=undefined |
|                  |    in radians    |    sine             | Z=undefined |
|                  | single-precision |                     | V=undefined |
|                  |                  |                     | C=undefined |
|                  |                  |                     | X=undefined |
|------------------|------------------|---------------------|-------------|
| _LVOIEEESPCosh   | D0=IEEE arg      | D0=IEEE hyperbolic  | N=undefined |
|                  |    in radians    |    cosine           | Z=undefined |
|                  | single-precision |                     | V=undefined |
|                  |                  |                     | C=undefined |
|                  |                  |                     | X=undefined |
|------------------|------------------|---------------------|-------------|
| _LVOIEEESPTanh   | D0=IEEE arg      | D0=IEEE hyperbolic  | N=undefined |
|                  |    in radians    |    tangent          | Z=undefined |
|                  | single-precision |                     | V=undefined |
|                  |                  |                     | C=undefined |
|                  |                  |                     | X=undefined |
|------------------|------------------|---------------------|-------------|
| _LVOIEEESPExp    | D0=IEEE arg      | D0=IEEE exponential | N=undefined |
|                  | single-precision |                     | Z=undefined |
|                  |                  |                     | V=undefined |
|                  |                  |                     | C=undefined |
|                  |                  |                     | X=undefined |
|------------------|------------------|---------------------|-------------|
| _LVOIEEESPLog    | D0=IEEE arg      | D0=IEEE natural     | N=undefined |
|                  | single-precision |    logarithm        | Z=undefined |
|                  |                  |                     | V=undefined |
|                  |                  |                     | C=undefined |
|                  |                  |                     | X=undefined |
|------------------|------------------|---------------------|-------------|
| _LVOIEEESPLog10  | D0=IEEE arg      | D0=IEEE logarithm   | N=undefined |
|                  | single-precision |    (base 10)        | Z=undefined |
|                  |                  |                     | V=undefined |
|                  |                  |                     | C=undefined |
|                  |                  |                     | X=undefined |
|------------------|------------------|---------------------|-------------|
| _LVOIEEESPPow    | D0=IEEE          | D0=IEEE result of   | N=undefined |
|                  |   exponent value |    arg taken to     | Z=undefined |
|                  | single-precision |    exp power        | V=undefined |
|                  | D1=IEEE          |                     | C=undefined |
|                  |    arg value     |                     | X=undefined |
|                  | single-precision |                     |             |
|------------------|------------------|---------------------|-------------|
| _LVOIEEESPSqrt   | D0=IEEE arg      | D0=IEEE square root | N=undefined |
|                  | single-precision |                     | Z=undefined |
|                  |                  |                     | V=undefined |
|                  |                  |                     | C=undefined |
|                  |                  |                     | X=undefined |
|__________________|__________________|_____________________|_____________|


35 Math Libraries / IEEE Double-Precision Data Format

The IEEE double-precision variables are defined as 64-bit entities with
the following format:

         ______________________________________________
        |                                              |
        | SEEEEEEE    EEEEEIMM    MMMMMMMM    MMMMMMMM |
        | 63          55          47          39       |
        |______________________________________________|

         ______________________________________________
        |                                              |
        | MMMMMMMM    MMMMMMMM    MMMMMMMM    MMMMMMMM |
        | 31          23          15          7        |
        |______________________________________________|

    Hidden Bit In The Mantissa.
    ---------------------------
    There is a "hidden" bit in the mantissa part of the IEEE numbers.
    Since all numbers are normalized, the integer (high) bit of the
    mantissa is dropped off.  The IEEE double-precision range is 2.2E-308
    (4.9E-324 de-normalized) to 1.8E+307.

The exponent is the power of two needed to correctly position the mantissa
to reflect the number's true arithmetic value.  If both the exponent and
the mantissa have zero in every position, the value is zero.  If only the
exponent has zero in every position, the value is an unnormal (extremely
small).  If all bits of the exponent are set to 1 the value is either a
positive or negative infinity or a Not a Number (NaN).  NaN is sometimes
used to indicate an uninitialized variable.


35 Math Libraries / IEEE Double-Precision Basic Math Library

The IEEE double-precision basic math library contains entries for the
basic IEEE mathematics functions, such as add, subtract, and divide. This
library resides on disk and is opened by calling OpenLibrary() with
"mathieeedoubbas.library" as the argument.  Do not share the library base
pointer between tasks -- see note at beginning of chapter for details.

    #include <exec/types.h>
    #include <libraries/mathieeedp.h>

    #include <clib/mathdoubbas_protos.h>

    struct Library *MathIeeeDoubBasBase;

    VOID main()
    {
        /* do not share base pointer between tasks. */
    if (MathIeeeDoubBasBase = OpenLibrary("mathieeedoubbas.library", 34))
        {
               . . .

        CloseLibrary(MathIeeeDoubBasBase);
        }
    else printf("Can't open mathieeedoubbas.library\n");
    }

The global variable MathIeeeDoubBasBase is used internally for all future
library references.

If an 680X0/68881/68882 processor combination is available, it will be
used by the IEEE basic library instead of the software emulation.  Also,
if an autoconfigured math resource is available, that will be used.
Typically this is a 68881 designed as a 16 bit I/O port, but it could be
another device as well.

 DP IEEE Basic Functions


35 /IEEE Double-Precision Basic Math Library / DP IEEE Basic Functions

IEEEDPAbs()    DOUBLE IEEEDPAbs( DOUBLE parm );
    Take absolute value of IEEE double-precision variable.

IEEEDPAdd()    DOUBLE IEEEDPAdd( DOUBLE leftParm, DOUBLE rightParm );
    Add two IEEE double-precision variables.

IEEEDPCeil()   DOUBLE IEEEDPCeil( DOUBLE parm );
    Compute least integer greater than or equal to variable.

IEEEDPCmp()    LONG IEEEDPCmp( DOUBLE leftParm, DOUBLE rightParm );
    Compare two IEEE double-precision variables.

IEEEDPDiv()    DOUBLE IEEEDPDiv( DOUBLE dividend, DOUBLE divisor );
    Divide two IEEE double-precision variables.

IEEEDPFix()    LONG IEEEDPFix( DOUBLE parm );
    Convert IEEE double-precision  variable to integer.

IEEEDPFloor()  DOUBLE IEEEDPFloor( DOUBLE parm );
    Compute largest integer less than or equal to variable.

IEEEDPFlt()    DOUBLE IEEEDPFlt( long integer );
    Convert integer variable to IEEE double-precision.

IEEEDPMul()    DOUBLE IEEEDPMul( DOUBLE factor1, DOUBLE factor2 );
    Multiply two IEEE double-precision variables.

IEEEDPNeg()    DOUBLE IEEEDPNeg( DOUBLE parm );
    Take two's complement of IEEE double-precision variable.

IEEEDPSub()    DOUBLE IEEEDPSub( DOUBLE leftParm, DOUBLE rightParm );
    Subtract two IEEE double-precision variables.

IEEEDPTst()    LONG IEEEDPTst( DOUBLE parm );
    Test an IEEE double-precision variable against zero.

Be sure to include proper data type definitions, as shown in the example
below.

     mathieeedoubbas.c

The Amiga assembly language interface to the IEEE double-precision
floating-point basic math routines is shown below, including some details
about how the system flags are affected by each operation.  The access
mechanism from assembly language is:

        MOVEA.L _MathIeeeDoubBasBase,A6
        JSR     _LVOIEEEDPFix(A6)

 _________________________________________________________________________
|                                                                         |
|                    DP IEEE Basic Assembly Functions                     |
|                                                                         |
| Function          Input              Output             Condition Codes |
|_________________________________________________________________________|
|                 |                  |                    |               |
| _LVOIEEEDPFix   | D0/D1=IEEE arg   | D0=Integer         | N=undefined   |
|                 | double-precision | (two's complement) | Z=undefined   |
|                 |                  |                    | V=undefined   |
|                 |                  |                    | C=undefined   |
|                 |                  |                    | X=undefined   |
|-----------------|------------------|--------------------|---------------|
| _LVOIEEEDPFl    | D0=Integer arg   | D0/D1=IEEE         | N=undefined   |
|                 |     (two's       | double-precision   | Z=undefined   |
|                 |   complement)    |                    | V=undefined   |
|                 |                  |                    | C=undefined   |
|                 |                  |                    | X=undefined   |
|-----------------|------------------|--------------------|---------------|
| _LVOIEEEDPCmp   | D0/D1=IEEE arg1  | D0=+1 if arg1>arg2 | N=1 if result |
|                 | double-precision | D0=-1 if arg1<arg2 |   is negative |
|                 | D2/D3=IEEE arg2  | D0=0 if arg1=arg2  | Z=1 if result |
|                 | double-precision |                    |     is zero   |
|                 |                  |                    | V=0           |
|                 |                  |                    | C=undefined   |
|                 |                  |                    | X=undefined   |
|                 |                  |                    | GT=arg2>arg1  |
|                 |                  |                    | GE=arg2>=arg1 |
|                 |                  |                    | EQ=arg2=arg1  |
|                 |                  |                    | NE=arg2<>arg1 |
|                 |                  |                    | LT=arg2<arg1  |
|                 |                  |                    | LE=arg2<=arg1 |
|-----------------|------------------|--------------------|---------------|
| _LVOIEEEDPTst   | D0/D1=IEEE arg   | D0=+1 if arg>0.0   | N=1 if result |
|                 | double-precision | D0=-1 if arg<0.0   |   is negative |
|                 |                  | D0=0 if arg=0.0    | Z=1 if result |
|                 |                  |                    |     is zero   |
|                 |                  |                    | V=0           |
|                 |                  |                    | C=undefined   |
|                 |                  |                    | X=undefined   |
|                 |                  |                    | EQ=arg=0.0    |
|                 |                  |                    | NE=arg<>0.0   |
|                 |                  |                    | PL=arg>=0.0   |
|                 |                  |                    | MI=arg<0.0    |
|-----------------|------------------|--------------------|---------------|
| _LVOIEEEDPAbs   | D0/D1=IEEE arg   | D0/D1=IEEE         | N=undefined   |
|                 | double-precision | double-precision   | Z=undefined   |
|                 |                  | absolute value     | V=undefined   |
|                 |                  |                    | C=undefined   |
|                 |                  |                    | X=undefined   |
|-----------------|------------------|--------------------|---------------|
| _LVOIEEEDPNeg   | D0/D1=IEEE arg   | D0/D1=IEEE         | N=undefined   |
|                 | double-precision | double-precision   | Z=undefined   |
|                 |                  | negated            | V=undefined   |
|                 |                  |                    | C=undefined   |
|                 |                  |                    | X=undefined   |
|-----------------|------------------|--------------------|---------------|
| _LVOIEEEDPAdd   | D0/D1=IEEE arg1  | D0/D1=IEEE         | N=undefined   |
|                 | double-precision | double-precision   | Z=undefined   |
|                 |                  | addition of        | V=undefined   |
|                 | D2/D3=IEEE arg2  | arg1+arg2          | C=undefined   |
|                 | double-precision |                    | X=undefined   |
|-----------------|------------------|--------------------|---------------|
| _LVOIEEEDPSub   | D0/D1=IEEE arg1  | D0/D1=IEEE         | N=undefined   |
|                 | double-precision | double-precision   | Z=undefined   |
|                 |                  | subtraction of     | V=undefined   |
|                 | D2/D3=IEEE arg2  | arg1-arg2          | C=undefined   |
|                 | double-precision |                    | X=undefined   |
|-----------------|------------------|--------------------|---------------|
| _LVOIEEEDPMul   | D0/D1=IEEE arg1  | D0/D1=IEEE         | N=undefined   |
|                 | double-precision | double-precision   | Z=undefined   |
|                 |                  | multiplication of  | V=undefined   |
|                 | D2/D3=IEEE arg2  | arg1*arg2          | C=undefined   |
|                 | double-precision |                    | X=undefined   |
|-----------------|------------------|--------------------|---------------|
| _LVOIEEEDPDiv   | D0/D1=IEEE arg1  | D0/D1=IEEE         | N=undefined   |
|                 | double-precision | double-precision   | Z=undefined   |
|                 |                  | division of        | V=undefined   |
|                 | D2/D3=IEEE arg2  | arg1/arg2          | C=undefined   |
|                 | double-precision |                    | X=undefined   |
|-----------------|------------------|--------------------|---------------|
| _LVOIEEEDPCeil  | D0/D1=IEEE arg   | D0/D1=least        | N=undefined   |
|                 | double-precision |       integer      | Z=undefined   |
|                 |                  | >= arg             | V=undefined   |
|                 |                  |                    | C=undefined   |
|                 |                  |                    | X=undefined   |
|-----------------|------------------|--------------------|---------------|
| _LVOIEEEDPFloor | D0/D1=IEEE arg   | D0/D1=largest      | N=undefined   |
|                 | double-precision |       integer      | Z=undefined   |
|                 |                  | <= arg             | V=undefined   |
|                 |                  |                    | C=undefined   |
|                 |                  |                    | X=undefined   |
|_________________|__________________|____________________|_______________|


35 Math Libraries / IEEE Double-Precision Transcendental Math Library

The IEEE double-precision transcendental math library contains entries for
the transcendental math functions such as sine, cosine, and square root.
The library resides on disk and is opened by calling OpenLibrary() with
"mathieeedoubtrans.library" as the argument. Do not share the library base
pointer between tasks -- see note at beginning of chapter for details.

   #include <exec/types.h>
   #include <libraries/mathieeedp.h>

   #include <clib/mathdoubtrans_protos.h>

   struct Library *MathIeeeDoubTransBase;

   VOID main()
   {
   if (MathIeeeDoubTransBase = OpenLibrary("mathieeedoubtrans.library",34))
       {
              . . .

       CloseLibrary(MathIeeeDoubTransBase);
       }
   else printf("Can't open mathieeedoubtrans.library\n");
   }

The global variable MathIeeeDoubTransBase is used internally for all
future library references.

The IEEE double-precision transcendental math library is dependent upon
the IEEE double-precision basic math library, which it will open if it is
not open already.  If you want to use the IEEE double-precision basic math
functions in conjunction with the transcendental math functions however,
you have to specifically open the basic math library yourself.

Just as the IEEE double-precision basic math library, the IEEE
double-precision transcendental math library will take advantage of a
680X0/68881 combination or another math resource, if present.

 DP IEEE Transcendental Functions


35 / / DP IEEE Transcendental Functions

IEEEDPAsin()   DOUBLE IEEEDPAsin( DOUBLE parm );
    Return arcsine of IEEE variable.

IEEEDPAcos()   DOUBLE IEEEDPAcos( DOUBLE parm );
    Return arccosine of IEEE variable.

IEEEDPAtan()   DOUBLE IEEEDPAtan( DOUBLE parm );
    Return arctangent of IEEE variable.

IEEEDPSin()    DOUBLE IEEEDPSin( DOUBLE parm );
    Return sine of IEEE variable.  This function accepts an IEEE radian
    argument and returns the trigonometric sine value.

IEEEDPCos()    DOUBLE IEEEDPCos( DOUBLE parm );
    Return cosine of IEEE variable.  This function accepts an IEEE radian
    argument and returns the trigonometric cosine value.

IEEEDPTan()    DOUBLE IEEEDPTan( DOUBLE parm );
    Return tangent of IEEE variable.  This function accepts an IEEE
    radian argument and returns the trigonometric tangent value.

IEEEDPSincos() DOUBLE IEEEDPSincos( DOUBLE *pf2, DOUBLE parm );
    Return sine and cosine of IEEE variable.  This function accepts an
    IEEE radian argument and returns the trigonometric sine as its result
    and the trigonometric cosine in the first parameter.

IEEEDPSinh()   DOUBLE IEEEDPSinh( DOUBLE parm );
    Return hyperbolic sine of IEEE variable.

IEEEDPCosh()   DOUBLE IEEEDPCosh( DOUBLE parm );
    Return hyperbolic cosine of IEEE variable.

IEEEDPTanh()   DOUBLE IEEEDPTanh( DOUBLE parm );
    Return hyperbolic tangent of IEEE variable.

IEEEDPExp()    DOUBLE IEEEDPExp( DOUBLE parm );
    Return e to the IEEE variable power.  This function accept an IEEE
    argument and returns the result representing the value of e
    (2.712828...) raised to that power.

IEEEDPFieee()  DOUBLE IEEEDPFieee( FLOAT single );
    Convert IEEE single-precision number to IEEE double-precision number.

IEEEDPLog()    DOUBLE IEEEDPLog( DOUBLE parm );
    Return natural log (base e of IEEE variable.

IEEEDPLog10()  DOUBLE IEEEDPLog10( DOUBLE parm );
    Return log (base 10) of IEEE variable.

IEEEDPPow()    DOUBLE IEEEDPPow( DOUBLE exp, DOUBLE arg );
    Return IEEE arg2 to IEEE arg1.

IEEEDPSqrt()   DOUBLE IEEEDPSqrt( DOUBLE parm );
    Return square root of IEEE variable.

IEEEDPTieee()  FLOAT IEEEDPTieee( DOUBLE parm );
    Convert IEEE double-precision number to IEEE single-precision number.

Be sure to include proper data type definitions as shown below.

     mathieeedoubtrans.c

The section below describes the Amiga assembly interface to the IEEE
double-precision transcendental math library.  The access mechanism from
assembly language is:

        MOVEA.L _MathIeeeDoubTransBase,A6
        JSR     _LVOIEEEDPAsin(A6)

  _______________________________________________________________________
 |                                                                       |
 |             DP IEEE Transcendental Assembly Functions                 |
 |                                                                       |
 | Function           Input            Output            Condition Codes |
 |_______________________________________________________________________|
 |                  |                |                     |             |
 | _LVOIEEEDPAsin   | D0/D1=IEEE arg | D0/D1=IEEE          | N=undefined |
 |                  |                | arcsine radian      | Z=undefined |
 |                  |                |                     | V=undefined |
 |                  |                |                     | C=undefined |
 |                  |                |                     | X=undefined |
 |------------------|----------------|---------------------|-------------|
 | _LVOIEEEDPAcos   | D0/D1=IEEE arg | D0/D1=IEEE          | N=undefined |
 |                  |                | arccosine radian    | Z=undefined |
 |                  |                |                     | V=undefined |
 |                  |                |                     | C=undefined |
 |                  |                |                     | X=undefined |
 |------------------|----------------|---------------------|-------------|
 | _LVOIEEEDPAtan   | D0/D1=IEEE arg | D0/D1=IEEE          | N=undefined |
 |                  |                | arctangent radian   | Z=undefined |
 |                  |                |                     | V=undefined |
 |                  |                |                     | C=undefined |
 |                  |                |                     | X=undefined |
 |------------------|----------------|---------------------|-------------|
 | _LVOIEEEDPSin    | D0/D1=IEEE arg | D0/D1=IEEE sine     | N=undefined |
 |                  |   in radians   |                     | Z=undefined |
 |                  |                |                     | V=undefined |
 |                  |                |                     | C=undefined |
 |                  |                |                     | X=undefined |
 |------------------|----------------|---------------------|-------------|
 | _LVOIEEEDPCos    | D0/D1=IEEE arg | D0/D1=IEEE cosine   | N=undefined |
 |                  |   in radians   |                     | Z=undefined |
 |                  |                |                     | V=undefined |
 |                  |                |                     | C=undefined |
 |                  |                |                     | X=undefined |
 |------------------|----------------|---------------------|-------------|
 | _LVOIEEEDPTan    | D0/D1=IEEE arg | D0/D1=IEEE tangent  | N=undefined |
 |                  |   in radians   |                     | Z=undefined |
 |                  |                |                     | V=undefined |
 |                  |                |                     | C=undefined |
 |                  |                |                     | X=undefined |
 |------------------|----------------|---------------------|-------------|
 | _LVOIEEEDPSincos | A0=Address to  | D0/D1=IEEE sine     | N=undefined |
 |                  |   store cosine | (A0)=IEEE cosine    | Z=undefined |
 |                  |   result       |                     | V=undefined |
 |                  | D0/D1=IEEE arg |                     | C=undefined |
 |                  |   in radians   |                     | X=undefined |
 |------------------|----------------|---------------------|-------------|
 | _LVOIEEEDPSin    | D0/D1=IEEE arg | D0/D1=IEEE          | N=undefined |
 |                  |   in radians   | hyperbolic sine     | Z=undefined |
 |                  |                |                     | V=undefined |
 |                  |                |                     | C=undefined |
 |                  |                |                     | X=undefined |
 |------------------|----------------|---------------------|-------------|
 | _LVOIEEEDPCosh   | D0/D1=IEEE arg | D0/D1=IEEE          | N=undefined |
 |                  |   in radians   | hyperbolic cosine   | Z=undefined |
 |                  |                |                     | V=undefined |
 |                  |                |                     | C=undefined |
 |                  |                |                     | X=undefined |
 |------------------|----------------|---------------------|-------------|
 | _LVOIEEEDPTanh   | D0/D1=IEEE arg | D0/D1=IEEE          | N=undefined |
 |                  |   in radians   | hyperbolic tangent  | Z=undefined |
 |                  |                |                     | V=undefined |
 |                  |                |                     | C=undefined |
 |                  |                |                     | X=undefined |
 |------------------|----------------|---------------------|-------------|
 | _LVOIEEEDPExp    | D0/D1=IEEE arg | D0/D1=IEEE          | N=undefined |
 |                  |                | exponential         | Z=undefined |
 |                  |                |                     | V=undefined |
 |                  |                |                     | C=undefined |
 |                  |                |                     | X=undefined |
 |------------------|----------------|---------------------|-------------|
 | _LVOIEEEDPLog    | D0/D1=IEEE arg | D0/D1=IEEE natural  | N=undefined |
 |                  |                |  logarithm          | Z=undefined |
 |                  |                |                     | V=undefined |
 |                  |                |                     | C=undefined |
 |                  |                |                     | X=undefined |
 |------------------|----------------|---------------------|-------------|
 | _LVOIEEEDPLog10  | D0/D1=IEEE arg | D0/D1=IEEE          | N=undefined |
 |                  |                | logarithm           | Z=undefined |
 |                  |                | (base 10)           | V=undefined |
 |                  |                |                     | C=undefined |
 |                  |                |                     | X=undefined |
 |------------------|----------------|---------------------|-------------|
 | _LVOIEEEDPPow    | D0/D1=IEEE exp | D0/D1=IEEE          | N=undefined |
 |                  | D2/D3=IEEE arg | of arg taken to     | Z=undefined |
 |                  |                | exp power           | V=undefined |
 |                  |                |                     | C=undefined |
 |                  |                |                     | X=undefined |
 |------------------|----------------|---------------------|-------------|
 | _LVOIEEEDPSqrt   | D0/D1=IEEE arg | D0/D1=IEEE          | N=undefined |
 |                  |                | square root         | Z=undefined |
 |                  |                |                     | V=undefined |
 |                  |                |                     | C=undefined |
 |                  |                |                     | X=undefined |
 |------------------|----------------|---------------------|-------------|
 | _LVOIEEEDPTieee  | D0/D1=IEEE arg | D0=single-precision | N=undefined |
 |                  |                | IEEE floating-point | Z=undefined |
 |                  |                | format              | V=undefined |
 |                  |                |                     | C=undefined |
 |                  |                |                     | X=undefined |
 |__________________|________________|_____________________|_____________|


35 Math Libraries / Function Reference

Here's a brief summary of the functions covered in this chapter.  Refer to
the Amiga ROM Kernel Reference Manual: Includes and Autodocs for
additional information.

  _______________________________________________________________________
 |                                                                       |
 |                          FFP Basic Functions                          |
 |=======================================================================|
 |    SPAbs()  Take absolute value of FFP variable                       |
 |    SPAdd()  Add two FFP variables                                     |
 |   SPCeil()  Compute least integer greater than or equal to variable.  |
 |    SPCmp()  Compare two FFP variables                                 |
 |    SPDiv()  Divide two FFP variables                                  |
 |    SPFix()  Convert FFP variable to integer                           |
 |  SPFloor()  Computer largest integer less than or equal to variable.  |
 |    SPFlt()  Convert integer variable to FFP                           |
 |    SPMul()  Multiply two FFP variables                                |
 |    SPNeg()  Take two's complement of FFP variable                     |
 |    SPSub()  Subtract two FFP variables                                |
 |    SPTst()  Test an FFP variable against zero                         |
 |_______________________________________________________________________|

  _______________________________________________________________________
 |                                                                       |
 |                      FFP Transcendental Functions                     |
 |=======================================================================|
 |       SPAcos()  Return arccosine of FFP variable.                     |
 |       SPAsin()  Return arcsine of FFP variable.                       |
 |       SPAtan()  Return arctangent of FFP variable.                    |
 |        SPCos()  Return cosine of FFP variable.                        |
 |       SPCosh()  Return hyperbolic cosine of FFP variable.             |
 |        SPExp()  Return e to the FFP variable power.                   |
 |      SPFieee()  Convert IEEE variable to FFP format.                  |
 |        SPLog()  Return natural log (base e) of FFP variable.          |
 |      SPLog10()  Return log (base 10) of FFP variable.                 |
 |        SPPow()  Return FFP arg2 to FFP arg1.                          |
 |        SPSin()  Return sine of FFP variable.                          |
 |     SPSincos()  Return sine and cosine of FFP variable.               |
 |       SPSinh()  Return hyperbolic sine of FFP variable.               |
 |       SPSqrt()  Return square root of FFP variable.                   |
 |        SPTan()  Return tangent of FFP variable.                       |
 |       SPTanh()  Return hyperbolic tangent of FFP variable.            |
 |      SPTieee()  Convert FFP variable to IEEE format                   |
 |_______________________________________________________________________|

  _______________________________________________________________________
 |                                                                       |
 |                        Math Support Functions                         |
 |=======================================================================|
 |      afp()  Convert ASCII string into FFP equivalent.                 |
 |      fpa()  Convert FFP variable into ASCII equivalent.               |
 |     arnd()  Round ASCII representation of FFP number.                 |
 |      dbf()  Convert FFP dual-binary number to FFP equivalent.         |
 |_______________________________________________________________________|

  _______________________________________________________________________
 |                                                                       |
 |                    SP IEEE Basic Functions (V36)                      |
 |=======================================================================|
 |   IEEESPAbs()  Take absolute value of IEEE single-precision variable. |
 |   IEEESPAdd()  Add two IEEE single-precision variables.               |
 |  IEEESPCeil()  Compute least integer greater than or equal to         |
 |                variable.                                              |
 |   IEEESPCmp()  Compare two IEEE single-precision variables.           |
 |   IEEESPDiv()  Divide two IEEE single-precision variables.            |
 |   IEEESPFix()  Convert IEEE single-precision  variable to integer.    |
 | IEEESPFloor()  Compute largest integer less than or equal to          |
 |                variable.                                              |
 |   IEEESPFlt()  Convert integer variable to IEEE single-precision.     |
 |   IEEESPMul()  Multiply two IEEE single-precision variables.          |
 |   IEEESPNeg()  Take two's complement of IEEE single-precision         |
 |                variable.                                              |
 |   IEEESPSub()  Subtract two IEEE single-precision variables.          |
 |   IEEESPTst()  Test an IEEE single-precision variable against zero.   |
 |_______________________________________________________________________|

  _______________________________________________________________________
 |                                                                       |
 |                SP IEEE Transcendental Functions (V36)                 |
 |=======================================================================|
 |   IEEESPACos()  Return arccosine of IEEE single-precision variable.   |
 |   IEEESPASin()  Return arcsine of IEEE single-precision variable.     |
 |   IEEESPAtan()  Return arctangent of IEEE single-precision variable.  |
 |    IEEESPCos()  Return cosine of IEEE single-precision variable.      |
 |   IEEESPCosh()  Return hyperbolic cosine of IEEE single-precision     |
 |                 variable.                                             |
 |    IEEESPExp()  Return e to the IEEE variable power.                  |
 |    IEEESPLog()  Return natural log (base e of IEEE single-precision   |
 |                 variable.                                             |
 |  IEEESPLog10()  Return log (base 10) of IEEE single-precision         |
 |                 variable.                                             |
 |    IEEESPPow()  Return power of IEEE single-precision variable.       |
 |    IEEESPSin()  Return sine of IEEE single-precision variable.        |
 | IEEESPSincos()  Return sine and cosine of IEEE single-precision       |
 |                 variable.                                             |
 |   IEEESPSinh()  Return hyperbolic sine of IEEE single-precision       |
 |                variable.                                              |
 |   IEEESPSqrt()  Return square root of IEEE single-precision variable. |
 |    IEEESPTan()  Return tangent of IEEE single-precision variable.     |
 |   IEEESPTanh()  Return hyperbolic tangent of IEEE single-precision    |
 |                 variable.                                             |
 |_______________________________________________________________________|

  _______________________________________________________________________
 |                                                                       |
 |                       DP IEEE Basic Functions                         |
 |=======================================================================|
 |   IEEEDPAbs()  Take absolute value of IEEE double-precision variable. |
 |   IEEEDPAdd()  Add two IEEE double-precision variables.               |
 |  IEEEDPCeil()  Compute least integer greater than or equal to         |
 |                variable.                                              |
 |   IEEEDPCmp()  Compare two IEEE double-precision variables.           |
 |   IEEEDPDiv()  Divide two IEEE double-precision variables.            |
 |   IEEEDPFix()  Convert IEEE double-precision  variable to integer.    |
 | IEEEDPFloor()  Compute largest integer less than or equal to          |
 |                variable.                                              |
 |   IEEEDPFlt()  Convert integer variable to IEEE double-precision.     |
 |   IEEEDPMul()  Multiply two IEEE double-precision variables.          |
 |   IEEEDPNeg()  Take two's complement of IEEE double-precision         |
 |                variable.                                              |
 |   IEEEDPSub()  Subtract two IEEE single-precision variables.          |
 |   IEEEDPTst()  Test an IEEE double-precision variable against zero.   |
 |_______________________________________________________________________|

  _______________________________________________________________________
 |                                                                       |
 |                   DP IEEE Transcendental Functions                    |
 |=======================================================================|
 |   IEEEDPACos()  Return arccosine of IEEE double-precision variable.   |
 |   IEEEDPASin()  Return arcsine of IEEE double-precision variable.     |
 |   IEEEDPAtan()  Return arctangent of IEEE double-precision variable.  |
 |    IEEEDPCos()  Return cosine of IEEE double-precision variable.      |
 |   IEEEDPCosh()  Return hyperbolic cosine of IEEE double-precision     |
 |                 variable.                                             |
 |    IEEEDPExp()  Return e to the IEEE variable power.                  |
 |  IEEEDPFieee()  Convert IEEE single-precision number to IEEE          |
 |                 double-precision number.                              |
 |    IEEEDPLog()  Return natural log (base e of IEEE double-precision   |
 |                 variable.                                             |
 |  IEEEDPLog10()  Return log (base 10) of IEEE double-precision         |
 |                 variable.                                             |
 |    IEEEDPPow()  Return power of IEEE double-precision variable.       |
 |    IEEEDPSin()  Return sine of IEEE double-precision variable.        |
 | IEEEDPSincos()  Return sine and cosine of IEEE double-precision       |
 |                 variable.                                             |
 |   IEEEDPSinh()  Return hyperbolic sine of IEEE double-precision       |
 |                 variable.                                             |
 |   IEEEDPSqrt()  Return square root of IEEE double-precision variable. |
 |    IEEEDPTan()  Return tangent of IEEE double-precision variable.     |
 |   IEEEDPTanh()  Return hyperbolic tangent of IEEE double-precision    |
 |                 variable.                                             |
 |  IEEEDPTieee()  Convert IEEE double-precision number to IEEE          |
 |                 single-precision number.                              |
 |_______________________________________________________________________|


35 Math Libraries / Compile and Link Commands for SAS C 5.10

FFP Basic, Transcendental and Math Support functions
----------------------------------------------------
    lc -b1 -cfistq -ff -v -y <filename>.c
    blink lib:c.o + <filename>.o TO
        <filename> LIB lib:lcmffp.lib + lib:lc.lib + lib:amiga.lib

IEEE Single-Precision and Double-Precision Basic and Transcendental
Functions
-------------------------------------------------------------------
    lc -b1 -cfistq -fi -v -y <filename>.c
    blink lib:c.o + <filename>.o TO
         <filename> LIB lib:lcmieee.lib + lib:lc.lib + lib:amiga.lib


Amiga® RKM Libraries: 36 Translator Library

This chapter describes the translator library which, together with the
narrator device, provides the Amiga's text-to-speech capability. To fully
understand how speech is produced on the Amiga, you should also read the
"Narrator Device" chapter of the Amiga ROM Kernel Reference Manual:
Devices.

The translator library provides a single function, Translate(), that
converts an English language string into a phonetic string. You may then
pass this phonetic string to the narrator device which will say the string
using the Amiga's audio hardware. The two subsystems may also be used
individually.  You don't have to use the narrator to say the phonetic
strings; you could use them instead for phonetic analysis or some other
special purpose.

 Opening the Translator Library    Closing the Translator Library
 Using the Translate Function      Additional Notes About Translate


36 Translator Library / Opening the Translator Library

To use the Translate() function, you must first open the translator
library. Setting a global variable, TranslatorBase, to the value returned
from the call to OpenLibrary() enables the Amiga linker to correctly
locate the translator library:

    struct Library *TranslatorBase;

    TranslatorBase = OpenLibrary("translator.library",REVISION);
    if(TranslatorBase != NULL)
        {
        /* use translator here -- library open */
        }

    LIBS: must contain translator.library.
    --------------------------------------
    Since translator is a disk-based library, the call to
    OpenLibrary() will work only if the LIBS: directory contains
    translator.library.


36 Translator Library / Using the Translate Function

Once the library is open, you can call the translate function:

    #define BUFLEN 500

    STRPTR EnglStr;                 /* pointer to sample input string */
    LONG EnglLen;                   /* input length */
    UBYTE PhonBuffer[BUFLEN];       /* place to put the translation */
    LONG rtnCode;                   /* return code from function */

    EnglStr = "This is Amiga speaking.";    /* a test string */
    EnglLen = strlen(EnglStr);
    rtnCode = Translate(EnglStr, EnglLen, (STRPTR)&PhonBuffer[0], BUFLEN);

The input string will be translated into its phonetic equivalent and can
be used to feed the narrator device. If you receive a non-zero return
code, you haven't provided enough output buffer space to hold the entire
translation. In this case, the Translate() function breaks the translation
at the end of a word in the input stream and returns the position in the
input stream at which the translation ended. You can use the output
buffer, then call the Translate() function again, starting at this
original ending position, to continue the translation where you left off.
This method will sound smoothest if the ending position ends on sentence
boundaries.

    Translate() returns negative values.
    ------------------------------------
    To get the proper character offset, you must use -(rtnCode) as
    the starting point for a new translation.


36 Translator Library / Closing the Translator Library

As with all other libraries of functions, if you have successfully opened
the translator library for use, be sure to close it before your program
exits. If the system needs memory resources, it can then expunge closed
libraries to gain additional memory space:

    struct Library *TranslatorBase;

    if(TranslatorBase) CloseLibrary(TranslatorBase);


36 Translator Library / Additional Notes About Translate

The English language has many words that do not sound the same as they are
spelled. The translator library has exception rules that it consults as
the translation progresses. It also provides for common abbreviations such
as Dr., Prof., LB., etc. Words that are not in the exception table are
translated literally. This translation allows unrestricted English text as
input, and uses over four hundred and fifty context sensitive rules. It
automatically accents content words, and leaves function words (e.g. of,
by, the, and at) unaccented. It is possible, however, that certain words
will not translate well. You can improve the quality of translation by
handling those words on your own.

The phoneme table that the narrator uses is listed in the
"Narrator Device" chapter of the Amiga ROM Kernel Reference Manual:
Devices.  You will also find other important information about the Amiga's
speech capability in the narrator chapter including a working example
which shows how to use the translator library together with the narrator
device.


Amiga® RKM Libraries: 37 Utility Library

Utility library is the home for all the OS functions which don't fit in
the other libraries.  Among the calls in utility library are calls to
manage tags and tag lists, callback hooks, and some generic 32-bit math
functions, all discussed below.

 Tags                             International String Functions
 Callback Hooks                   Date Functions
 32-bit Integer Math Functions    Function Reference


37 Utility Library / Tags

The implementation of tags is one of the many new features of Release 2.
Tags make it possible to add new parameters to system functions without
interfering with the original parameters.  They also make specifying
parameter lists much clearer and easier.

 Tag Functions and Structures    Simple Tag Usage Example
 Simple Tag Usage                Advanced Tag Usage


37 / Tags / Tag Functions and Structures

A tag is made up of an attribute/value pair as defined below (from
<utility/tagitem.h>):

    struct TagItem
    {
        ULONG  ti_Tag;    /* identifies the type of this item */
        ULONG  ti_Data;   /* type-specific data, can be a pointer */
    };

The ti_Tag field specifies an attribute to set.  The possible values of
ti_Tag are implementation specific.  System tags are defined in the
include files.  The value the attribute is set to is specified in ti_Data.
An example of the attribute/value pair that will specify a window's name
is:

    ti_Tag  = WA_Title;
    ti_Data = "My Window's Name";

The ti_Data field often contains 32-bit data as well as pointers.

These are brief descriptions of the utility functions you can use to
manipulate and access tags.  For complete descriptions, see the
"Simple Tag Usage" and "Advanced Tag Usage" sections.

The following utility library calls are for supporting tags:

                Table 37-1: Utility Library Tag Functions
  ______________________________________________________________________
 |                                                                      |
 |     AllocateTagItems()  Allocate a TagItem array (or chain).         |
 |         FreeTagItems()  Frees allocated TagItem lists.               |
 |----------------------------------------------------------------------|
 |        CloneTagItems()  Copies a TagItem list.                       |
 | RefreshTagItemClones()  Rejuvenates a clone from the original.       |
 |----------------------------------------------------------------------|
 |          FindTagItem()  Scans TagItem list for a tag.                |
 |           GetTagData()  Obtain data corresponding to tag.            |
 |          NextTagItem()  Iterate TagItem lists.                       |
 |           TagInArray()  Check if a tag value appears in a Tag array. |
 |----------------------------------------------------------------------|
 |     FilterTagChanges()  Eliminate TagItems which specify no change.  |
 |       FilterTagItems()  Remove selected items from a TagItem list.   |
 |              MapTags()  Convert ti_Tag values in a list via map      |
 |                         pairing.                                     |
 |         PackBoolTags()  Builds a "Flag" word from a TagItem list.    |
 |______________________________________________________________________|


37 / Tags / Simple Tag Usage

One way tags are passed to system functions is in the form of tag lists. A
tag list is an array or chain of arrays of TagItem structures.  Within
this array, different data items are identified by the value of ti_Tag.
Items specific to a subsystem (Intuition, Graphics,...) have a ti_Tag
value which has the TAG_USER bit set. Global system tags have a ti_Tag
value with TAG_USER bit clear.  The global system tags include:

                      Table 37-2: Global System Tags
  ____________________________________________________________________
 |                                                                    |
 | Tag Value   Meaning                                                |
 |====================================================================|
 | TAG_IGNORE  A no-op.  The data item is ignored.                    |
 |                                                                    |
 | TAG_MORE    The ti_Data points to another tag list, to support     |
 |             chaining of TagItem arrays.                            |
 |                                                                    |
 | TAG_DONE    Terminates the TagItem array (or chain).               |
 |                                                                    |
 | TAG_SKIP    Ignore the current tag item, and skip the next n array |
 |             elements, where n is kept in ti_Data.                  |
 |____________________________________________________________________|

Note that user tags need only be unique within the particular context of
their use.  For example, the attribute tags defined for OpenWindow() have
the same numeric value as some tags used by OpenScreen(), but the same
numeric value has different meaning in the different contexts.

System functions receive TagItems in several ways.  One way is illustrated
in the Intuition function OpenWindow().  This function supports an
extented NewWindow structure called ExtNewWindow.  When the NW_EXTENDED
flag is set in the ExtNewWindow.Flags field, OpenWindow() assumes that the
ExtNewWindow.Extension field contains a pointer to a tag list.

Another method of passing a tag list is to directly pass a pointer to a
tag list, as OpenWindowTagList() does in the following code fragment.

    struct TagItem tagitem[3];
    struct Screen *screen;
    struct Window *window;

    tagitem[0].ti_Tag = WA_CustomScreen;
    tagitem[0].ti_Data = screen;    /* Open on my own screen */
    tagitem[1].ti_Tag = WA_Title;
    tagitem[1].ti_Data = "RKM Test Window";
    tagitem[2].ti_Tag = TAG_DONE;   /* Marks the end of the tag array. */

    /* Use defaults for everything else. Will open as big as the screen. */
    /* Because all window parameters are specified using tags, we don't  */
    /* need a NewWindow structure                                        */

    if (window = OpenWindowTagList(NULL, tagitem))
    {
        /* rest of code */
        CloseWindow(window);
    }

Notice that window parameters need not be explicitly specified. Functions
that utilize tags have reasonable defaults to fall back on in case no
valid attribute/value pair was supplied for a particular parameter. This
fall back capability is a useful feature. An application only has to
specify the attributes that differ from the default, rather than
unnecessarily listing all the possible attributes.

The amiga.lib support library offers another way to pass TagItems to a
function.  Rather than passing a tag list, the function OpenWindowTags()
receives the attribute/value pairs in the argument list, much like
printf() receives its arguments.  Any number of attribute/value pairs can
be specified.  This type of argument passing is called VarArgs. The
following code fragment illustrates the usage of OpenWindowTags().

    struct Window *window;

    /* Just pass NULL to show we aren't using a NewWindow */
    window = OpenWindowTags( NULL,
                             WA_CustomScreen, screen,
                             WA_Title, "RKM Test Window",
                             TAG_DONE );

Tags are not exclusively for use with the operating system; the programmer
can implement them as well.  The run-time utility library contains several
functions to make using tags easier.


37 / Tags / Advanced Tag Usage

The previous section provided the background material necessary to start
using tags.  This section will show how to use the more advanced features
of tags using functions within utility library.

 Creating a New Tag List           Sequential Access of Tag Lists
 Copying an Existing Tag List      Random Access of Tag Lists
 Filtering an Existing Tag List    Obtaining Boolean Values
 Locating an Attribute             Mapping Tag Attributes


37 / / Advanced Tag Usage / Creating a New Tag List

The AllocateTagItems() function can be used to create a new tag array
ready for use.  The tag array should be passed to FreeTagItems() when the
application is done with it.

    struct TagItem *tags;
    ULONG tags_needed;

    /* Indicate how many tags we need */
    tags_needed = 10;

    /* Allocate a tag array */
    if (tags = AllocateTagItems(tags_needed))
    {
        /* ...do something with the array... */

        /* Free the array when your done with it */
        FreeTagItems (tags);
    }


37 / / Advanced Tag Usage / Copying an Existing Tag List

The CloneTagItems() function is used to copy an existing tag array into a
new tag array.

    struct TagItem *otags;      /* Original tag array */
    struct TagItem *ntags;      /* New tag array */

    /* Make sure there is a TagItem array */
    if (otags)
    {
        /* Copy the original tags into a new tag array */
        if (ntags = CloneTagItems(otags))
        {
            /* ...do something with the array... */

            /* Free the array when your done with it */
            FreeTagItems (ntags);
        }
    }

This function can also be used to implement a function that will insert
tag items into an array.

    struct TagItem *otags;      /* Original tag array */
    struct TagItem *tags;       /* New tag array */

    /* Insert a couple of tags into an existing tag array */
    if (tags = MakeNewTagList (GA_LeftEdge, 10,
                               GA_TopEdge, 20,
                               TAG_MORE, otags))
    {
        /* ...do something with the array... */

        /* Free the array when your done with it */
        FreeTagItems (tags);
    }

    /* This function will create a tag array from tag pairs placed on
     * the stack */
    struct TagItem *MakeNewTagList (ULONG data,...)
    {
        struct TagItem *tags = (struct TagItem *) &data;

        return (CloneTagItems (tags));
    }


37 / / Advanced Tag Usage / Filtering an Existing Tag List

Sometimes it is necessary to only allow certain attributes to be visible
in a tag list.  In order to achieve this, the tag array would need to be
filtered.

A number of functions are provided for filtering items in a tag array.
They are FilterTagChanges(), FilterTagItems() and RefreshTagItemClones().

    /* We want the text entry gadget to receive the following tags */
    Tag string_attrs[] =
    {
        STRINGA_MaxChars,
        STRINGA_Buffer,
        STRINGA_TextVal,
        TAG_END,
    };

    /* These are attributes that the model understands */
    Tag model_attrs[] =
    {
        CGTA_Total,
        CGTA_Visible,
        CGTA_Top,
        ICA_TARGET,
        ICA_MAP,
        TAG_END,
    };

    struct TagItem *otags;      /* Original tag list */
    struct TagItem *ntags;      /* New, work, tag list */

    /* Make a copy of the original for us to work with */
    ntags = CloneTagItems (otags);

    /* Create a tag list that only contains attributes that are
     * listed in the model_attrs list. */
    if (FilterTagItems (ntags, model_attrs, TAGFILTER_AND))
    {
        /* Work with filtered tag list (ntags) */

        /* Restore the tag list */
        RefreshTagItemClones (ntags, otags);

        /* Create a tag list that only contains attributes that
         * aren't in the model_attrs list. */
        if (FilterTagItems (ntags, model_attrs, TAGFILTER_NOT))
        {
            /* Work with filtered tag list (ntags) */
        }

        /* Restore the tag list */
        RefreshTagItemClones (ntags, otags);

        /* Create a tag list that only contains attributes that
         * are in the string_attrs list. */
        if (FilterTagItems (ntags, string_attrs, TAGFILTER_AND))
        {
            /* Work with filtered tag list (ntags) */
        }
    }

    /* Free work tag list. */
    FreeTagItems (ntags);


37 / / Advanced Tag Usage / Locating an Attribute

To see if an attribute is in a tag array, the TagInArray() function is
used.

    /* See if the listview labels attribute is located in a tag array */
    if (TagItemArray(GTLV_Labels, tags))
    {
        /* Yes, the attribute is in the list */
    }
    else
    {
        /* No, the attribute isn't in the list */
    }

The FindTagItem() function will return a pointer to the actual tag that
has the desired attribute.  This allows you to manipulate the tag or to
determine if the attribute exists but just has a NULL value.

    struct TagItem *tag;

    /* See if they are trying to set a sound */
    if (tag = FindTagItem(MGA_Sound, attrs))
    {
        /* Set the sound attribute to point to the specified sound data */
        tag->ti_Data = sound;
    }


37 / / Advanced Tag Usage / Sequential Access of Tag Lists

In order to sequentially access the members of a tag array, the
NextTagItem() function is used.

    struct TagItem *tags = msg->ops_AttrList;
    struct TagItem *tstate;
    struct TagItem *tag;
    ULONG tidata;

    /* Start at the beginning */
    tstate = tags;

    /* Step through the tag list while there are still items in the
     * list */
    while (tag = NextTagItem (&tstate))
    {
        /* Cache the data for the current element */
        tidata = tag->ti_Data;

        /* Handle each attribute that we understand */
        switch (tag->ti_Tag)
        {
            /* Put a case statement here for each attribute that your
             * function understands */
            case PGA_Freedom:
                lod->lod_Flags |= tidata;
                break;

            case GTLV_Labels:
                lod->lod_List = (struct List *) tidata;
                break;

            /* We don't understand this attribute */
            default:
                break;
        }
    }


37 / / Advanced Tag Usage / Random Access of Tag Lists

The GetTagData() function will return the data for the specified
attribute.  If there isn't a tag that matches, then the default value is
returned.

    APTR sound;

    /* Get the sound data that our function will use. */
    sound = (APTR) GetTagData (MGA_Sound, (ULONG) DefaultSound, attrs);


37 / / Advanced Tag Usage / Obtaining Boolean Values

Often times data is best represented as simple boolean (TRUE or FALSE)
values.  The PackBoolTags() function provides an easy method for
converting a tag list to bit fields.

    /* These are the attributes that we understand, with the
     * corresponding flag value. */
    struct TagItem activation_bools[] =
    {
        /* Attribute            Flags */
        {GA_ENDGADGET,          ENDGADGET},
        {GA_IMMEDIATE,          GADGIMMEDIATE},
        {GA_RELVERIFY,          RELVERIFY},
        {GA_FOLLOWMOUSE,        FOLLOWMOUSE},
        {GA_RIGHTBORDER,        RIGHTBORDER},
        {GA_LEFTBORDER,         LEFTBORDER},
        {GA_TOPBORDER,          TOPBORDER},
        {GA_BOTTOMBORDER,       BOTTOMBORDER},
        {GA_TOGGLESELECT,       TOGGLESELECT},

        /* Terminate the array */
        {TAG_END}
    };

    /* Set the activation field, based on the attributes passed */
    g->Activation = PackBoolTags(g->Activation, tags, activation_bools);


37 / / Advanced Tag Usage / Mapping Tag Attributes

To translate all occurrences of an attribute to another attribute, the
MapTags() function is used.

For Release 2, the third parameter of this function is always TRUE (tags
remain in the array even if they can't be mapped).

    struct TagItem map_list[] =
    {
        /* Original     New */
        {MGA_LeftEdge,  GA_LeftEdge},
        {MGA_TopEdge,   GA_TopEdge},
        {MGA_Width,     GA_Width},
        {MGA_Height,    GA_Height},

        /* Terminate the array */
        {TAG_END},
    }

    /* Map the tags to the new attributes, keeping all attributes that
     * aren't included in the mapping array */
    MapTags(tags, map_list, TRUE);


37 Utility Library / Callback Hooks

The callback features of Release 2 provide a standard means for
applications to extend the functionality of libraries, devices, and
applications.  This standard makes it easy for the operating system to use
custom modules from different high level programming languages as part of
the operating system.  For example, the layers library, which takes care
of treating a display as a series of layered regions, allows an
application to attach a pattern function to a display layer.  Instead of
filling in the background of a layer with the background color, the layers
library calls the custom pattern function which fills in the layer display
with a custom background pattern.

 Callback Hook Structure and Function


37 / Callback Hooks / Callback Hook Structure and Function

An application passes a custom function in the form of a callback Hook
(from <utility/hooks.h>):

    struct Hook
    {
        struct MinNode h_MinNode;
        ULONG (*h_Entry)();     /* stub function entry point */
        ULONG (*h_SubEntry)();  /* the custom function entry point */
        VOID *h_Data;           /* owner specific */
    };

h_MinNode
    This field is reserved for use by the module that will call the Hook.

h_Entry
    This is the address of the Hook stub.  When the OS calls a callback
    function, it puts parameters for the callback function in CPU
    registers A0, A1, and A2.  This makes it tough for higher level
    language programmers to use a callback function because most higher
    level languages don't have a way to manipulate CPU registers
    directly.  The solution is a stub function which first copies the
    parameters from the CPU registers to a place where a high level
    language function can get to them.   The stub function then calls the
    callback function.  Typically, the stub pushes the registers onto the
    stack in a specific order and the callback function pops them off the
    stack.

h_SubEntry
    This is the address of the actual callback function that the
    application has defined.  The stub calls this function.

h_Data
    This field is for the application to use.  It could point to a global
    storage structure that the callback function utilizes.

There is only one function defined in utility library that relates to
callback hooks:

    ULONG CallHookPkt(struct Hook *hook, VOID *object, VOID *paramPkt);

This function calls a standard callback Hook function.

 Simple Callback Hook Usage


37 / / Hook Structure And Function / Simple Callback Hook Usage

A Hook function must accept the following three parameters in these
specific registers:

      A0 - Pointer to the Hook structure.
      A2 - Pointer to an object to manipulate. The object is
           context specific.
      A1 - Pointer to a message packet. This is also context
           specific.

For a callback function written in C, the parameters should appear in this
order:

    myCallbackFunction(Pointer to Hook (A0),
                       Pointer to Object (A2),
                       Pointer to message (A1));

This is because the standard C stub pushes the parameters onto the stack
in the following order: A1, A2, A0.  The following assembly language
routine is a callback stub for C:

    INCLUDE 'exec/types.i'
    INCLUDE 'utility/hooks.i'

    xdef        _hookEntry

    _hookEntry:
        move.l  a1,-(sp)                ; push message packet pointer
        move.l  a2,-(sp)                ; push object pointer
        move.l  a0,-(sp)                ; push hook pointer
        move.l  h_SubEntry(a0),a0       ; fetch actual Hook entry point ...
        jsr     (a0)                    ; and call it
        lea     12(sp),sp               ; fix stack
        rts

If your C compiler supports registerized parameters, your callback
functions can get the parameters directly from the CPU registers instead
of having to use a stub to push them on the stack.  The following C
language routine uses registerized parameters to put parameters in the
right registers.  This routine requires a C compiler that supports
registerized parameters.

    #include <exec/types.h>
    #include <utility/hooks.h>

    #define     ASM     __asm
    #define     REG(x)  register __ ## x

    /* This function converts register-parameter hook calling
     * convention into standard C conventions.  It requires a C
     * compiler that supports registerized parameters, such as
     * SAS/C 5.xx or greater.
     */
    ULONG ASM
    hookEntry(REG(a0) struct Hook *h, REG(a2) VOID *o, REG(a1) VOID *msg)
    {
        return ((*h->h_SubEntry)(h, o, msg));
    }

A callback function is executed on the context of the module that invoked
it.  This usually means that callback functions cannot call functions that
need to look at environment specific data.  For example, printf() needs to
look at the current process's input and output stream.  Entities like
Intuition have no input and output stream.  This also means that in order
for the function to access any of its global data, it needs to make sure
the CPU can find the function's data segment.  It does this by forcing the
function to load the offset for the program's data segment into CPU
register A4.  See your compiler documentation for details.

The following is a simple function that can be used in a callback hook.

    ULONG MyFunction (struct Hook *h, VOID *o, VOID *msg)
    {
        /* A SASC and Manx function that obtains access to the global
           data segment */
        geta4();

        /* Debugging function to send a string to the serial port */
        KPrintF("Inside MyFunction()\n");

        return (1);
    }

The next step is to initialize the Hook for use.  This basically means
that the fields of the Hook structure must be filled with appropriate
values.

The following simple function initializes a Hook structure.

    /* This simple function is used to initialize a Hook */
    VOID InitHook (struct Hook *h, ULONG (*func)(), VOID *data)
    {
        /* Make sure a pointer was passed */
        if (h)
        {
            /* Fill in the hook fields */
            h->h_Entry = (ULONG (*)()) hookEntry;
            h->h_SubEntry = func;
            h->h_Data = data;
        }
    }

The following is a simple example of a callback hook function.

     hooks1.c


37 Utility Library / 32-bit Integer Math Functions

Utility library contains some high-speed math functions for 32-bit integer
division and multiplication. These functions will take advantage of
available processor instructions (like DIVUL), if a 68020 processor or
higher is present. If not, these functions will mimic those instructions
in 68000 only instructions, thus providing processor independency.

Currently the following functions are implemented:

  ____________________________________________________________
 |                                                            |
 |  SDivMod32()  Signed 32 by 32-bit division and modulus.    |
 |    SMult32()  Signed 32 by 32-bit multiplication.          |
 |  UDivMod32()  Unsigned 32 by 32-bit division and modulus.  |
 |    UMult32()  Unsigned 32 by 32-bit multiplication.        |
 |____________________________________________________________|

       Table 37-3: Utility Library 32-bit Math Functions

The division functions return the quotient in D0 and the remainder in D1.
To obtain the remainder in a higher level language, either a compiler
specific instruction to fetch the contents of a specific register must be
used (like getreg() in SAS C) or a small assembler stub.

Following a simple example of the usage of the 32-bit integer math
functions in C.

     uptime.c


37 Utility Library / International String Functions

The international string functions in utility library are a way to make
use of a future localization library which Amiga, Inc. will provide.
When the localization library is opened, the functions will be replaced by
ones which will take the locale as defined by the user into account. This
means that the compare order may change according to the locale, so care
should be taken not to rely on obtaining specific compare sequences.

Currently implemented are:

  _______________________________________________________________
 |                                                               |
 |  Stricmp()  Compare string case-insensitive.                  |
 | Strnicmp()  Compare string case-insensitive, with a specified |
 |             length.                                           |
 |  ToLower()  Convert a character to lower case.                |
 |  ToUpper()  Convert a character to upper case.                |
 |_______________________________________________________________|

    Table 37-4: Utility Library International String Functions

These functions operate in the same manner as their ANSI C equivalents,
for the most part.  For more information, see the "Utility Library"
Autodocs in the Amiga ROM Kernel Reference Manual: Includes and Autodocs.
Here is a simple example of the usage of the international string
functions.

     istr.c


37 Utility Library / Date Functions

To ease date-related calculations, the utility library has some functions
to convert a date, specified in a ClockData structure, in the number of
seconds since 00:00:00 01-Jan-78 and vice versa. To indicate the date, the
ClockData structure (in <utility/date.h>) is used.

    struct ClockData
    {
        UWORD sec;     /* seconds (0 - 59)*/
        UWORD min;     /* minutes (0 - 59) */
        UWORD hour;    /* hour (0 - 23) */
        UWORD mday;    /* day of the month (1 - 31) */
        UWORD month;   /* month of the year (1 - 12)
        UWORD year;    /* 1978 - */
        UWORD wday;    /* day of the week (0 - 6, where 0 is Sunday) */
    };

The following functions are available to operate on ClockData:

  ________________________________________________________________
 |                                                                |
 | Amiga2Date()  Calculate the date from the specified timestamp  |
 |               (in seconds).                                    |
 |  CheckDate()  Check the legality of a date.                    |
 | Date2Amiga()  Calculate the timestamp from the specified date. |
 |________________________________________________________________|

            Table 37-5: Utility Library Date Functins

Amiga2Date() takes a number of seconds from 01-Jan-78 as argument and
fills in the supplied ClockData structure with the date and time.

CheckDate() checks if the supplied ClockData structure is valid, and
returns the number of seconds from 01-Jan-78 if it is. Note that this
function currently does not take the supplied day of the week in account.

Date2Amiga() takes a ClockData structure as argument and returns the
number of seconds since 01-Jan-78. The supplied ClockData structure MUST
be valid, since no checking is done.

The following example shows various uses of the utility library date
functions.

     a2d.c


37 Utility Library / Function Reference

The tables which follow contain breif descriptions of the functions inside
the utility library.  All these functions require Release2 or a later
version of the Amiga operating system.  See the Amiga ROM Kernel Reference
Manual: Includes and Autodocs for details on each function call.

 Tag Function Reference
 Callback Hook Function Reference
 32-Bit Integer Math Function Reference
 International String Function Reference
 Date Function Reference


37 / Function Reference / Tag Function Reference

The following are brief descriptions of the utility library functions
which pertain to tags and tag lusts.

                    Table 37-6: Utility Tag Functions
  ______________________________________________________________________
 |                                                                      |
 |           Function                 Description                       |
 |======================================================================|
 |     AllocateTagItems()  Allocate a TagItem array (or chain).         |
 |         FreeTagItems()  Frees allocated TagItem lists.               |
 |----------------------------------------------------------------------|
 |        CloneTagItems()  Copies a TagItem list.                       |
 | RefreshTagItemClones()  Rejuvenates a clone from the original.       |
 |----------------------------------------------------------------------|
 |          FindTagItem()  Scans TagItem list for a tag.                |
 |           GetTagData()  Obtain data corresponding to tag.            |
 |          NextTagItem()  Iterate TagItem lists.                       |
 |           TagInArray()  Check if a tag value appears in a Tag array. |
 |----------------------------------------------------------------------|
 |     FilterTagChanges()  Eliminate TagItems which specify no change.  |
 |       FilterTagItems()  Remove selected items from a TagItem list.   |
 |              MapTags()  Convert ti_Tag values in a list via map      |
 |----------------------------------------------------------------------|
 |         PackBoolTags()  Builds a "Flag" word from a TagItem list.    |
 |______________________________________________________________________|


37 / Function Reference / Callback Hook Function Reference

The following are brief descriptions of the utility library functions
which pertain to callback hooks.

                   Table 37-7: Utility Hook Functions
     ___________________________________________________________
    |                                                           |
    |    Function                 Description                   |
    |===========================================================|
    |  CallHookPkt()  Call a standard callback Hook function.   |
    |___________________________________________________________|


37 / Function Reference / 32-Bit Integer Math Function Reference

The following are brief descriptions of the utility library functions
which pertain to 32-bit integer math.

              Table 37-8: Utility 32-Bit Math Functions
     ___________________________________________________________
    |                                                           |
    |   Function                 Description                    |
    |===========================================================|
    |  SDivMod32()  Signed 32 by 32-bit division and modulus.   |
    |    SMult32()  Signed 32 by 32-bit multiplication.         |
    |-----------------------------------------------------------|
    |  UDivMod32()  Unsigned 32 by 32-bit division modulus.     |
    |    UMult32()  Unsigned 32 by 32-bit multiplication.       |
    |___________________________________________________________|


37 / Function Reference / International String Function Reference

The following are brief descriptions of the utility library functions
which pertain to string operations using the international ASCII character
set.

          Table 37-9: Utility International String Functions
   _________________________________________________________________
  |                                                                 |
  |   Function               Description                            |
  |=================================================================|
  |   Stricmp()  Compare strings, case-insensitive.                 |
  |  Strnicmp()  Compare strings, case-insensitive, with specified  |
  |              length.                                            |
  |-----------------------------------------------------------------|
  |   ToLower()  Convert a character to lower case.                 |
  |   ToUpper()  Convert a character to upper case.                 |
  |_________________________________________________________________|


37 / Function Reference / Date Function Reference

The following are brief descriptions of the utility library functions
which pertain to date conversion.

                   Table 37-10: Utility Date Functions
   ________________________________________________________________
  |                                                                |
  |    Function           Description                              |
  |================================================================|
  |   CheckDate()  Check the legality of a date.                   |
  |----------------------------------------------------------------|
  |  Amiga2Date()  Calculate the date from a specified timestamp.  |
  |  Date2Amiga()  Calculate the timestamp from a specified date.  |
  |________________________________________________________________|


Amiga® RKM Libraries: A Linker Libraries

This section describes the amiga.lib and debug.lib libraries. Unlike the
libraries described in the other chapters of the manual, these are not
shared run-time libraries.  Code from the linker libraries is inserted by
the linker into your final program.  Only the functions you use are pulled
into your code.  These libraries are typically supplied by your language
or compiler vendor.

 Amiga.lib      Debug.lib


A Appendix A: Linker Libraries / Amiga.lib

This is the main Amiga scanned linker library, linked with most programs
for the Amiga.  The major components of amiga.lib are:

  * stubs        Functions for each Amiga ROM routine that copy
                 arguments from the stack to the CPU registers --
                 thereby enabling stack-based C compilers to call
                 register-based Amiga ROM routines.

  * offsets      The negative offset from the library base for each
                 Amiga function. These are called Library Vector
                 Offsets (_LVO).

  * Exec         C functions which simplify many Exec procedures such
                 as the creation and deletion of tasks, ports, and I/O
                 request structures.

  * clib         C support functions including pseudo-random number
                 generation and a limited set of file and stdio
                 functions designed to work directly with AmigaDOS file
                 handles.

  * Math         C functions which provide some basic conversions to
                 and from Fast Floating Point (FFP) format numbers.

  * Graphics     C support functions to add and remove tasks from the
                 vertical-blanking interval interrupt server chain.

  * ARexx        C support functions for ARexx variable handling and
                 message checking.

    NOTE:
    -----
    The Timer, Commodities, and Intuition support functions listed below
    are valid only for use with Release 2.04 (V37) or a later version of
    the system software.

  * Timer        C support functions to do common timer device
                 operations.

  * Commodities  C functions which support the Commodities system.
                 Included are functions to deal with ToolTypes, and to
                 create various Commodities objects.

  * Intuition    Functions which provide support for Intuition's hook
                 and Boopsi sub-systems.

Most applications link with and use at least one function in amiga.lib.
The functions available are as follows.

 Exec Support      Math          Arexx      Commodities
 Clib              Graphics      Timer      Intuition


A / Amiga.lib / Exec Support

BeginIO()
    This function takes an IORequest and passes it directly to the
    BEGINIO vector of the proper device.  This works exactly like
    SendIO(), but does not clear the io_Flags field first. This function
    does not wait for the I/O to complete.

CreateExtIO() and DeleteExtIO()
    CreateExtIO() allocates memory for and initializes a new I/O request
    block of a program-specified number of bytes.  The number of bytes
    must be the size of a legal IORequest (or extended request) or very
    nasty things will happen. DeleteExtIO() frees up an I/O request as
    allocated by CreateExtIO(). The mn_Length field determines how much
    memory to deallocate.

CreatePort() and DeletePort()
    CreatePort() allocates and initializes a new message port. The
    message list of the new port will be prepared for use via NewList().
    The port will be set to signal your task when a message arrives
    (PA_SIGNAL). DeletePort() deletes the port created by CreatePort().
    All messages that may have been attached to that port must already
    have been replied to.

CreateStdIO() and DeleteStdIO()
    CreateStdIO() allocates memory for and initializes a new IOStdReq
    structure. DeleteStdIO() frees up an IOStdReq allocated by
    CreateStdIO().

CreateTask() and DeleteTask()
    These functions simplify creation and deletion of subtasks by
    dynamically allocating and initializing the required structures and
    stack space.  They also add the task to Exec's task list with the
    given name and priority.  A tc_MemEntry list is provided so that all
    stack and structure memory allocated by CreateTask() is automatically
    deallocated when the task is removed. Before deleting a  task with
    DeleteTask(), you must first make sure that the task is not currently
    executing any system code which might try to signal the task after it
    is gone.

NewList()
    Prepares a List structure for use; the list will be empty and ready
    to use.


A / Amiga.lib / Clib

FastRand()
    Generates a pseudo-random number.  The seed value is taken from
    stack, shifted left one position, exclusive-or'ed with hex value
    $1D872B41 and returned.

RangeRand()
    RangeRand() accepts a value from 1 to 65535, and returns a value
    within that range (a 16-bit integer).  Note that this function is
    implemented in C.

fclose()
    Closes a file.

fgetc()
    Gets a character from a file.

fprintf()
    Prints a formatted output line to a file.

fputc()
    Puts character to file.

fputs()
    Writes a string to file.

getchar()
    Gets a character from stdin.

printf()
    Puts format data to stdout.

putchar()
    Puts character to stdout.

puts()
    Puts a string to stdout, followed by newline.

sprintf()
    Formats data into a string (see Exec RawDoFmt() ).


A / Amiga.lib / Math

afp()
    Converts ASCII string variable into fast floating-point.

arnd()
    ASCII round-off of the provided floating-point string."

dbf()
    Accepts a dual-binary format floating-point number and converts it to
    FFP format.

fpa()
    Accepts an FFP number and the address of the ASCII string where its
    converted output is to be stored.  The number is converted to a NULL
    terminated ASCII string and stored at the address provided.
    Additionally, the base ten (10) exponent in binary form is returned.


A / Amiga.lib / Graphics

AddTOF() and RemTOF()
    AddTOF() adds a task to the vertical-blanking interval interrupt
    server chain. This frees C programmers from the burden of having to
    write an assembly language routine to perform this function. The task
    can be removed with RemTOF().


A / Amiga.lib / ARexx

GetRexxVar() and SetRexxVar()
    GetRexxVar() attempts to extract the value of a variable from a
    running ARexx script/program.  SetRexxVar() will attempt to set the
    value of a particular variable in a running ARexx script.

CheckRexxMsg()
    This function checks to make sure that a RexxMsg is from ARexx
    directly. Messages used by the Rexx Variable Interface (RVI) routines
    are required to be directly from ARexx.


A / Amiga.lib / Timer

TimeDelay()
    This function waits for a specified period of time before returning
    to the the caller.


A / Amiga.lib / Commodities

ArgArrayInit() and ArgArrayDone()
    ArgArrayInit() returns an array of strings suitable for sending to
    icon.library/FindToolType(). This array will be the ToolTypes array
    of the program's icon, if it was started from Workbench. It will just
    be 'argv' if the program was started from a shell. ArgArrayDone()
    frees memory and does cleanup required after a call to ArgArrayInit().

ArgInt() and ArgString()
    These functions look for a particular entry in a ToolType array
    returned by ArgArrayInit() and return the integer (ArgInt()) or
    string (ArgString()) associated with that entry.  A default value can
    be passed to each function which will be returned in the event that
    the requested entry could not be found in the ToolType array.

CxCustom()
    This function creates a custom commodity object. The action of this
    object on receiving a commodity message is to call a function of the
    application programmer's choice.

CxDebug()
    This function creates a Commodities debug object. The action of this
    object on receiving a Commodities message is to print out information
    about the message through the serial port (using the
    debug.lib/KprintF() routine). A specified 'id' will also be displayed.

CxFilter()
    Creates a Commodities input event filter object that matches a
    description string. The description string is in the same format as
    strings expected by commodities.library/SetFilter(). If the
    description string is NULL, the filter will not match any messages.

CxSender()
    This function creates a Commodities sender object. The action of this
    object on receiving a Commodities message is to copy the Commodities
    message into a standard Exec Message, to put a supplied id in the
    message as well, and to send the message off to the message port.

CxSignal()
    This function creates a Commodities signal object. The action of this
    object on receiving a Commodities message is to send a signal to a
    task.  The caller is responsible for allocating the signal and
    determining the proper task ID.

CxTranslate()
    This function creates a Commodities translator object. The action of
    this object on receiving a Commodities message is to replace that
    message in the commodities network with a chain of Commodities input
    messages.

HotKey()
    This function creates a triad of commodity objects to accomplish a
    high-level function.

    The three objects are a filter, which is created to match by
    CxFilter(), a sender created by CxSender(), and a translator which is
    created by CxTranslate(), so that it swallows any commodity input
    event messages that are passed down by the filter.

    This is the simple way to get a message sent to your program when the
    user performs a particular input action.

InvertString()
    This function returns a linked list of input events which would
    translate into the string using the supplied keymap (or the system
    default keymap if the supplied keymap is NULL).

    This chain should eventually be freed using FreeIEvents().

FreeIEvents()
    This function frees a linked list of input events as obtained from
    InvertString().


A / Amiga.lib / Intuition

CallHook() and CallHookA()
    These functions invoke hooks.  CallHook() expects a parameter packet
    ("message") on the stack, while CallHookA() takes a pointer to the
    message.

DoMethod() and DoMethodA()
    Boopsi support functions that ask a specified Boopsi object to
    perform a specific message.  The message is passed in the function
    call for DoMethodA() and on the stack for DoMethod().  The message is
    invoked on the object's true class.

DoSuperMethod() and DoSuperMethodA()
    Boopsi support functions that ask a Boopsi object to perform a
    supplied message as if it was an instance of its superclass.  The
    message is passed in the function call for DoSuperMethodA() and on
    the stack for DoSuperMethod().

CoerceMethod() and CoerceMethodA()
    Boopsi support functions that ask a Boopsi object to perform a
    supplied message as if it was an instance of some other class. The
    message is passed in the function call for CoerceMethodA() and on the
    stack for CoerceMethod.

SetSuperAttrs()
    Boopsi support function which invokes the OM_SET method on the
    superclass of the supplied class for the supplied object. Allows the
    ops_AttrList to be supplied on the stack (i.e. in a varargs way).


A Appendix A: Linker Libraries / Debug.lib

This link library contains standard I/O (stdio) style functions for
communicating with a serial terminal connected to the Amiga via its
built-in serial port.  Typically this  terminal will be a 9600-baud, 8
data-bits, one stop-bit connection to an external terminal or an Amiga
running a terminal package.  The debug.lib functions allow you to output
messages and prompt for input (even from within low level task or
interrupt code) without disturbing the Amiga's display and or current
state (other than the serial hardware itself).

No matter how badly the system may have crashed, these functions can
usually get a message out.  A similar debugging library (currently called
ddebug.lib) is available for sending debugging output to the parallel
port.  This is useful for debugging serial applications. Ddebug.lib is not
documented here.  It contains functions similar to debug.lib but with
names starting with `D' instead of `K'.

Debug.lib is a link library that provides useful diagnostic functions that
are handy for developing code.  It includes the following functions:

KCmpStr()
    Compare two null-terminated strings.

KGetChar()
    Get a character from the console.

KGetNum()
    Get a number from the console.

KMayGetChar()
    Return a character if present, but don't wait.

KPrintF()
    Print formatted data to the console.

KPutChar()
    Put a character to the console.

KPutStr()
    Put a string to the console.

Please refer to the Amiga ROM Kernel Reference Manual: Includes and
Autodocs for a detailed description of the functions.


Amiga® RKM Libraries: B Boopsi Class Reference

The Boopsi Class Reference documents all of the classes built into
Intuition.  Each class entry in the reference starts off with:

   Class:         The class's name (for example, gadgetclass)
   Superclass:    The class's superclass (for example, rootclass)
   Include File:  The class's include file (for example,
                  <intuition/gadgetclass.h>)

The include file contains the class's message structures, attribute IDs,
and method IDs.  This is followed by a short description of the class.

The rest of a class entry is broken up into three sections:

  * New Methods      Describes each new method that the class defines.

  * Changed Methods  Describes each method to which this class makes
                     significant changes.

  * Attributes       Describes the attributes that this class defines as
                     well as inherited ones that this class alters.

 Introduction    imageclass       itexticlass    buttongclass
 rootclass       frameiclass      gadgetclass    frbuttonclass
 icclass         sysiclass        propgclass     groupgclass
 modelclass      fillrectclass    strgclass


B Boopsi Class Reference / Introduction

There are 14 public classes built into the Release 2.04 ROM:

                            rootclass
                               /
                 _____________/____________
                /         /                \
               /         /                  \
           icclass      /                gadgetclass
             /         /                      \
            /         /         _______________\___________________
           /     imageclass    /           /         \             \
          /         /         /           /           \             \
     modelclass    /      propgclass  strgclass  buttongclass  groupgclass
                  /                                     \
                 /                                       \
         _______/___________________________        frbuttongclass
        /         \            \            \
       /           \            \            \
  frameiclass  sysiclass  fillrectclass  itexticlass

This appendix documents all the standard Boopsi classes, including their
methods and attributes.

Each class entry in this document can have two sets of methods: new
methods that the class defines and inherited methods that the class has
modified significantly.  Similarly, each class entry can have two sets of
attributes: those that the class defines and those that the class
inherited and modified.  Unless documented otherwise,  all classes inherit
all of its superclass's methods and attributes.

Each method has a Boopsi message associated with it.  These messages are
in the form of C structures.  Many methods use the default message
structure:

    typedef struct
    {
        ULONG MethodID;
    } *Msg;

Some methods require a customized message so they can pass other
parameters besides the Method ID.  If a method requires a custom message,
its custom message structure is documented along with the method.

All methods have to return some sort of return value.  The meaning of the
return value depends on the class and method.  Normally a return value of
zero indicates that either the method failed or it is not supported by the
class.  A method can use the return value to return a pointer to an
object.  If a class does not directly support a particular method, the
class's dispatcher should pass the method on to its superclass for
processing.  The class dispatcher should record the return value it gets
from its superclass and use that as its return value.  Methods that assign
no meaning to their return value can return 1L to indicate that the method
is implemented.

The description of each attribute contains a code which lists the
rootclass methods that apply to that attribute:

    I  OM_NEW     Attribute can be set at initialization
    S  OM_SET     Attribute can be set with OM_SET method
    G  OM_GET     Attribute can be read with OM_GET method
    N  OM_NOTIFY  Changing the attribute triggers object to send
                  notifications
    U  OM_UPDATE  Attribute can be set with OM_UPDATE method

For example, the itexticlass attribute IA_Left has the code (ISG) after
it.  This means an application can set IA_Left when it creates an instance
of itexticlass (OM_NEW) and when it uses the OM_SET method.  The
application can also ask an itexticlass object what the IA_Left value is,
using the OM_GET method.

The OM_NEW, OM_SET, OM_NOTIFY, and OM_UPDATE messages all contain a
pointer to a tag list.  This tag list contains the attributes and
corresponding values that the method affects.  Each TagItem in this list
makes up an attribute/value pair.  The ti_Tag portion of the TagItem
contains the attribute's ID while the ti_Data field contains the
attribute's value.  Note that these tag lists can also contain
utility.library Global System control tags (like TAG_SKIP and TAG_DONE),
so dispatchers should use the tag functions from utility.library to
process these lists.  See documentation on the Utility library for more
information.

All methods are called via a class dispatcher:

    classDispatcher(Class *class, Object *object, Msg msg);

The first argument, class, is a pointer to the dispatcher's Class
structure (defined in <intuition/classes.h>).  The second parameter,
object, is a pointer to the Boopsi object to which the Boopsi message (the
third argument, msg) refers.  Both Object and Msg are defined in
<intuition/classusr.h>.


B Boopsi Class Reference / rootclass

Class:                  rootclass
Superclass:             None
Include File:           <intuition/classusr.h>

This is the universal base class for all other classes.

New Methods:
------------
 OM_NEW        OM_ADDTAIL
 OM_DISPOSE    OM_REMOVE

The following methods are described at the rootclass level although its up
to the subclasses to actually implement them.  If a class does not
implement these methods, it should either return zero, indicating that
this class does not support the method, or defer processing on to its
superclass.

 OM_ADDMEMBER    OM_GET    OM_UPDATE
 OM_REMMEMBER    OM_SET    OM_NOTIFY

Changed Methods:
----------------
Not applicable.

Attributes:
-----------
None.


B / rootclass / New Methods: OM_NEW

This method tells a class to create a new instance of itself.  If OM_NEW
is successful, it returns a pointer to the new object, otherwise it
returns NULL.

For programmers who are only creating Boopsi objects rather than creating
custom classes, use the intuition.library function NewObject():

    APTR NewObject(struct IClass  *privateclass,
                   UBYTE          *publicclassname,
                   ULONG          firsttag,
                   ...)

The OM_NEW method receives the following arguments (defined in
<intuition/classusr.h>):

    struct opSet /* The OM_NEW method uses the same structure as OM_SET */
    {
        ULONG             MethodID;      /* OM_NEW */
        struct TagItem    *ops_AttrList; /* tag attributes to initialize */
        struct GadgetInfo *ops_GInfo;    /* Always NULL for OM_NEW */
    };

The ops_AttrList field contains a pointer to a tag list of attribute/value
pairs.  Each pair contains an attribute ID and the initial value of the
corresponding attribute.

The ops_GInfo field is always NULL for the OM_NEW method.

Unlike other methods, when the dispatcher gets an OM_NEW message, the
object pointer (newobject from the dispatchRKMModel() prototype above)
does not point to an object, since the idea is to create a new object.
The pointer normally used to pass a Boopsi object is instead used to pass
the address of the object's "true class" (the class of which the object
is an instance).

The first thing the dispatcher does when it processes an OM_NEW message is
pass the OM_NEW message on to its superclass's dispatcher.  It does this
using the amiga.lib function DoSuperMethodA():

    ULONG DoSuperMethodA(Class *cl, Object *trueclass, Msg msg);

Each superclass's dispatcher does this until the message gets to the
rootclass dispatcher.

Each class keeps a record of how much memory its local instance data
requires.  The rootclass dispatcher's OM_NEW method looks at the object's
true class (newobject from the prototype) to find out how much memory to
allocate for the object's instance data.  The rootclass dispatcher
allocates enough memory for the true class's local instance data, plus
enough memory for the local instance data of each of the true class's
superclasses.  If all goes well, the rootclass dispatcher increments the
true class's internal count of instances of true class, and returns a
pointer to the newly created object.  it passes control back to the
subclass dispatcher that called it.  If there was a problem, the rootclass
dispatcher passes back a NULL.

When the rootclass dispatcher returns, the subclass dispatcher regains
control from DoSuperMethodA().  DoSuperMethodA() will return either a
pointer to the new object or NULL if there was an error.  Although the
rootclass dispatcher allocated all the memory the object needs, it did not
set up any of that memory.  Now its the the subclass dispatcher's turn to
do some work.  It has to initialize the instance data that is local to its
class.  A dispatcher finds its local instance data by using the
INST_DATA() macro (defined in <intuition/classes.h>).

After initializing its local instance data, the subclass dispatcher passes
control down to its subclass dispatcher, which in turn, initializes its
local instance data.  Control passes down from class to subclass until the
true class dispatcher regains control.

Now the true class dispatcher has to initialize its local instance data.
It has to scan through the tag list of attribute/value pairs passed in the
OM_NEW message (opSet.ops_AttrList).  If the dispatcher finds any
attributes that the true class recognizes, it has to initialize them to
the value passed in the attribute/value pair.

At this point, the new object can allocate other resources it needs that
it did not allocate as part of its instance data.  For example, the new
Boopsi object might need a frame image around itself, so it can create a
new one using a Boopsi frame image.  If the object allocates any resources
in this step, it must deallocate these resources later when it is disposed
in the OM_DISPOSE method.

Finally, the dispatcher can return.  When the dispatcher returns from an
OM_NEW method, it returns a pointer to the new object.


B / rootclass / New Methods: OM_DISPOSE

This method instructs an object to delete itself.  The rootclass
dispatcher's OM_DISPOSE method decrements the true class's internal count
of instances of true class.  The return value for this method is not
explicitly defined.

This method uses the default Boopsi message.

Applications should not call this method directly.  Instead they should
use the intuition.library function DisposeObject().

For the OM_DISPOSE method, an object should do the following:

Free any additional resources the object explicitly allocated itself in
the OM_NEW method (this does not include the instance data).

Pass the message up to the superclass, which will eventually reach
rootclass, which will free the instance data allocated for the object.

If a class does not allocate any extra resources when it creates an
object, it can defer all OM_DISPOSE processing to its superclass.


B / rootclass / New Methods: OM_ADDTAIL

This method tells an object to add itself to the end of a specified Exec
list.  Boopsi objects contain a MinNode structure used for this purpose.
The return value for this method is not explicitly defined.

The method uses a custom message (defined in <intuition/classusr.h>):

    struct opAddTail {
        ULONG       MethodID;   /* OM_ADDTAIL */
        struct List *opat_List; /* The exec list to add the object to */
    };

The opat_List can be any Exec list.  Use the Intuition function
NextObject() to step through this list.


B / rootclass / New Methods: OM_REMOVE

Remove an object from an Exec list.  The return value for this method is
not explicitly defined.  This method uses the default Boopsi message.


B / rootclass / New Methods: OM_ADDMEMBER

Tells an object to add another object to its personal Exec list.  What the
list is for depends on the class.  The return value for this method is not
explicitly defined.

One class that uses this method is modelclass.  A modelclass object
maintains a broadcast list.  When a modelclass object gets an OM_NOTIFY
message, it broadcasts an OM_UPDATE message about the OM_NOTIFY to every
object in its broadcast list.

This method uses a custom message (defined in <intuition/classusr.h>):

    #define  opAddMember opMember
    struct opMember {
        ULONG  MethodID;     /* OM_ADDMEMBER (or OM_REMMEMBER) */
        Object *opam_Object; /* add (or remove) this object    */
    };                       /* to (from) personal list.       */

opam_Object is the object to add to the list.  A dispatcher typically
implements OM_ADDMEMBER by sending the OM_ADDTAIL message to the
opam_Object object.


B / rootclass / New Methods: OM_REMMEMBER

Tells an object to remove a member object from its personal list.  The
member object should have already been added with OM_ADDMEMBER.  This
method uses the same custom message as OM_ADDMEMBER.  Normally a
dispatcher implements OM_REMMEMBER by sending the OM_REMOVE message to the
opam_Object object.  The return value for this method is not explicitly
defined.


B / rootclass / New Methods: OM_GET

Tells an object to report an attribute's value.  Applications should not
call this method directly.  Instead, use the intuition.library function
GetAttr().  The return value for this method is not explicitly defined.

This method uses a custom message (defined in <intuition/classusr.h>):

    struct opGet {
        ULONG MethodID;     /* OM_GET */
        ULONG opg_AttrID;   /* ID of attribute to get */
        ULONG *opg_Storage; /* place to put attribute value */
    };

If the object's dispatcher recognizes opg_AttrID as one of the attributes
defined by this class, the dispatcher should copy the value of that
attribute to where opg_Storage points:

    struct opGet *myopget;
    ...
    *(myopget->opg_Storage) = my_attribute_value;
    ...

If the dispatcher does not recognize opg_AttrID, it should pass the
message on to the superclass.


B / rootclass / New Methods: OM_SET

This method tells an object to set one or more of its attributes.
Applications should not call this method directly.  Instead, use the
intuition.library functions SetAttrs() and SetGadgetAttrs() to call this
method.  The return value for this method is not explicitly defined.

The return value for this method is not explicitly defined.  However, in
general, when implementing the OM_SET method, if setting an object
attribute causes some sort of visual state change, the OM_SET method
should return a value greater than zero.  If changing an attribute does
not affect the visual state, OM_SET should return zero.

This method uses a custom message (defined in <intuition/classusr.h>):

    struct opSet {
        ULONG             MethodID;      /* OM_SET */
        struct TagItem    *ops_AttrList; /* tag list of attributes to set*/
        struct GadgetInfo *ops_GInfo;
    };

The ops_AttrList field contains a pointer to a tag list of attribute/value
pairs.  These pairs contain the IDs and the new values of the attributes
to set.  The dispatcher has to look through this list (see docs for the
utility.library NextTagItem() function) for attributes its class
recognizes and set the attribute's value accordingly.  The dispatcher
should let its superclass handle any attributes it does not recognize.

If the object is a gadget, the ops_GInfo field contains a pointer to a
GadgetInfo structure.  Otherwise, the value in ops_GInfo is undefined.
Intuition use the GadgetInfo structure to pass display information to
gadgets.  See the gadgetclass methods for more details.


B / rootclass / New Methods: OM_UPDATE

This method tells an object to update one or more of its attributes.  No
application should call this method.  Only Boopsi objects send OM_UPDATE
messages.  The return value for this method is not explicitly defined.

A Boopsi object uses an OM_UPDATE message to notify another Boopsi object
about transitory changes to one or more attributes.

From the point of view of most objects, an OM_UPDATE message is almost
identical to OM_SET.  Because the methods are so similar, When a typical
dispatcher receives an OM_UPDATE message, it processes the OM_UPDATE the
same way it would process an OM_SET message, usually using the same code.

There are actually two kinds of OM_UPDATE, an interim and final one.
While a Boopsi object's attribute is in a transient state, it can send out
interim OM_UPDATE messages to its target(s).  For example, while the user
is sliding a Boopsi prop gadget, the prop gadget sends interim OM_UPDATE
message about changes to its PGA_Top value (the integer value of the prop
gadget is the PGA_Top attribute) to some target object.  When the user
lets go of the prop gadget, the gadget is no longer in a transient state,
so the gadget sends out a final OM_UPDATE about its PGA_Top attribute.
The target object can choose to change one of its attributes based on the
OM_UPDATE messages it receives.

The layout of the OM_UPDATE message is almost identical to the OM_SET
message:

    struct opUpdate {  /* the OM_NOTIFY method also uses this structure */
        ULONG             MethodID;           /* OM_UPDATE              */
        struct TagItem    *opu_AttrList;      /* tag list of attributes */
        struct GadgetInfo *opu_GInfo;         /*   that changed.        */
        ULONG             opu_Flags;          /* The extra field        */
    };

    #define OPUF_INTERIM    (1<<0)

Some dispatchers need to know the difference between an interim and final
OM_UPDATE.  A dispatcher can tell the difference between an interim and
final OM_UPDATE message because the OM_UPDATE message has an extra field
for flags.  If the low order bit (the OPUF_INTERIM bit) is set, this is an
interim OM_UPDATE message.  The interim flag is useful to a class that
wants to ignore any interim messages, processing only final attribute
values.


B / rootclass / New Methods: OM_NOTIFY

This method tells an object to broadcast an attribute change to a set of
target objects using OM_UPDATE messages.  The return value for this method
is not explicitly defined.

The OM_NOTIFY method uses the same message structure as OM_UPDATE.

Most dispatchers do not handle the OM_NOTIFY message directly.  Normally
they inherit this method from a superclass, so they pass the OM_NOTIFY
message on to the superclass dispatcher.

Although most dispatchers don't have to process OM_NOTIFY messages, most
do have to send them.  Whenever an object receives an OM_SET or OM_UPDATE
about one of its attributes, it may need to notify other objects of the
change.  For example, when a prop gadget's PGA_Top value changes, its
target object(s) need to hear about it.

If an object needs to notify other objects about a change to one or more
of its attributes, it sends itself an OM_NOTIFY message.  The OM_NOTIFY
message will eventually end up in the hands of a superclass that
understands OM_NOTIFY and it will send OM_UPDATE messages to the target
objects.


B Boopsi Class Reference / icclass

Class:                  icclass (interconnection class)
Superclass:             rootclass
Include File:           <intuition/icclass.h>

Base class of simple OM_UPDATE forwarding objects.  When an icclass object
gets an OM_UPDATE message, it maps the attributes in the OM_UPDATE message
according to its mapping list (its ICA_MAP attribute) and forwards the
OM_UPDATE to its target (its ICA_TARGET attribute).

New Methods:
------------
None.

Changed Methods:
----------------
 OM_SET    OM_UPDATE/OM_NOTIFY

Attributes:
-----------
 ICA_TARGET (IS)    ICA_MAP (IS)    ICSPECIAL_CODE (*)


B / icclass / Changed Methods: OM_SET

This method sets its attributes and returns 0.


B / icclass / Changed Methods: OM_UPDATE/OM_NOTIFY

These methods tell the object to notify its ICA_TARGET of attribute
changes by sending the target an OM_UPDATE message.  If the object has an
ICA_MAP, it maps the attribute IDs it finds to new attribute IDs.  See the
rootclass descriptions of OM_NOTIFY and OM_UPDATE for more information.
The return value for this method is not explicitly defined.


B / icclass / Attributes: ICA_TARGET (IS)

This attribute stores the address of the icclass object's target object.
Whenever the icclass object receives an OM_NOTIFY or OM_UPDATE message, it
forwards that message to its target in the form of an OM_UPDATE message.
If the icclass object has an attribute mapping list (see the ICA_MAP
attribute below), it also maps the OM_NOTIFY/OM_UPDATE message's attribute
IDs to new ones before forwarding the message.

If the value of ICA_TARGET is ICTARGET_IDCMP, the icclass object sends an
IDCMP_IDCMPUPDATE IntuiMessage to its window instead of forwarding an
OM_UPDATE message.  See the rootclass description of OM_UPDATE for more
information.


B / icclass / Attributes: ICA_MAP (IS)

This attribute points to a tag list of attribute mappings which the
icclass object uses to change the attribute IDs of an OM_UPDATE's
attribute/value pairs.  For example, if an icclass object had the
following ICA_MAP:

    struct TagItem map[] =
    {
        {PGA_Top, STRINGA_LongVal},
        {MYATTR, MYNEWATTR},
        {TAG_END, }
    };

before sending an OM_UPDATE to its ICA_TARGET, the icclass object scans
through the OM_UPDATE message's attribute/value pairs looking for the
PGA_Top and MYATTR attributes.  If it finds the PGA_Top attribute, it
changes PGA_Top to STRINGA_LongVal.  Likewise, if the icclass object finds
the MYATTR attribute, it changes MYATTR to MYNEWATTR.  The icclass object
does not disturb the attribute's value.


B / icclass / Attributes: ICSPECIAL_CODE ()

This is a dummy attribute for the ICA_MAP.  If any attribute maps to
ICSPECIAL_CODE and ICA_TARGET is ICTARGET_IDCMP, then the value of the
mapped attribute will be copied into the IntuiMessage.Code field of the
IDCMP_IDCMPUPDATE message (just the lower sixteen bits of the attribute
value will fit).


B Boopsi Class Reference / modelclass

Class:                  modelclass
Superclass:             icclass
Include File:           <intuition/icclass.h>

A class of OM_UPDATE forwarding objects that have multiple targets.  In
addition to the features the modelclass object inherits from icclass, when
a modelclass object gets an OM_UPDATE message, it forwards that OM_UPDATE
message to all of the objects in its broadcast list.

New Methods:
------------
None.

Changed Methods:
----------------
 OM_ADDMEMBER    OM_REMMEMBER    OM_DISPOSE    OM_NOTIFY/OM_UPDATE

Attributes:
-----------
None.


B / modelclass / Changed Methods: OM_ADDMEMBER

This method tells a model to add an object to its broadcast list.  When
the object disposes of itself, it will also dispose of any objects
remaining on its broadcast list.  The return value for this method is not
explicitly defined.  See the rootclass description of OM_ADDMEMBER for
more information.


B / modelclass / Changed Methods: OM_REMMEMBER

This method tells a model to remove an object from its broadcast list.
The return value for this method is not explicitly defined.  See the
rootclass description of OM_REMMEMBER for more information.


B / modelclass / Changed Methods: OM_DISPOSE

This method tells a model to dispose of itself plus the objects remaining
on its broadcast list.  The return value for this method is not explicitly
defined.


B / modelclass / Changed Methods: OM_NOTIFY/OM_UPDATE

This method tells an object to forward the message in the form of an
OM_UPDATE message to all the objects in its broadcast list.  The
modelclass does not map the attributes in these OM_UPDATE messages.
Because modelclass inherits behavior from icclass, if the model has an
ICA_TARGET and ICA_MAP, it will also send a mapped OM_UPDATE message to
its ICA_TARGET.  The return values for these methods are not explicitly
defined.  See the rootclass OM_NOTIFY/OM_UPDATE and icclass
OM_NOTIFY/OM_UPDATE descriptions for more information.


B Boopsi Class Reference / imageclass

Class:                  imageclass
Superclass:             rootclass
Include File:           <intuition/imageclass.h>

This class is the base class for Boopsi Images.  These images are
backwards compatible with the conventional Intuition Images.  Every Boopsi
image has an Intuition Image structure embedded in it so Intuition can
access the Boopsi image as a conventional Image structure when necessary.
Normally there are no direct instances of this class, only instances of
subclasses of imageclass.

New Methods:
------------
 IM_DRAW       IM_ERASE        IM_HITFRAME      IM_FRAMEBOX
 IM_HITTEST    IM_DRAWFRAME    IM_ERASEFRAME

Changed Methods:
----------------
 OM_NEW    OM_SET

Attributes:
-----------
 IA_Left, IA_Top, IA_Width, IA_Height (ISG)
 IA_FGPen, IA_BGPen (ISG)
 IA_Data (ISG)
 IA_Pens ()


B / imageclass / New Methods: IM_DRAW

This method tells an image object to draw itself.  Applications should not
call this method directly, instead use the intuition.library function
DrawImageState().  The return value for this method is not explicitly
defined.

The IM_DRAW method uses a custom message structure:

    struct impDraw
    {
        ULONG           MethodID;    /* IM_DRAW                    */
        struct RastPort *imp_RPort;  /* RastPort to render into    */
        struct
        {                            /* X and Y offset relative to */
            WORD X;                  /* the image's IA_Left and    */
            WORD Y;                  /* IA_Top attributes          */
        } imp_Offset;
        ULONG           imp_State;   /* Visual state of image      */
        struct DrawInfo *imp_DrInfo; /* describing rendering area  */
    };
n

The imp_State field contains the visual state to render the image.  The
visual states (defined in <intuition/imageclass.h>) are:

IDS_NORMAL            Render using normal imagery.  This is the only
                      kind of imagery available to non-Boopsi images.

IDS_SELECTED          Render using "selected" imagery.  "Selected"
                      refers to the state of a gadget's imagery when it
                      is the selected gadget.

IDS_DISABLED          Render using "disabled" imagery.  "Disabled"
                      refers to the state of a gadget's imagery when it
                      is disabled.  Typically, a disabled image has a
                      ghosting pattern on top of it.

IDS_INACTIVENORMAL    This is a special version of IDS_NORMAL for a
                      "normal" image that is in the border of an
                      inactive window.

IDS_INACTIVESELECTED  This is a special version of IDS_SELECTED for a
                      "selected" image that is in the border of an
                      inactive window.

IDS_INACTIVEDISABLED  This is a special version of IDS_DISABLED for a
                      "disabled" image that is in the border of an
                      inactive window.

IDS_BUSY              Render using "busy" imagery as if the object
                      was the image of a gadget in a busy state.  The
                      busy gadget state is not yet supported by
                      Intuition.

IDS_INDETERMINATE     Render using "indeterminate" imagery as if the
                      object was the image of a gadget in an
                      indeterminate state.  The indeterminate gadget
                      state is not yet supported by Intuition.

Most image objects do not have different visual states for each possible
imp_State.  See the imageclass entries in this index for more details.

When setting the pens to render an image, use the values from the
imp_DrInfo->dri_Pens pen array (Note that it is possible for imp_DrInfo to
be NULL).  The possible pen values are defined in <intuition/screens.h>.
See the "Intuition Screens" chapter of the Amiga ROM Kernel Reference
Manual: Libraries for more information on the pen array.


B / imageclass / New Methods: IM_HITTEST

This method returns TRUE if a point is within the old Image structure box
defined by the Image structure's LeftEdge, TopEdge, Width, and Height
fields.  Subclasses of imageclass can redefine this method if they need to
change the criteria for deciding if a point is within an image.
Application programs should not call this method directly, instead use the
Intuition function PointInImage().  The IM_HITTEST method uses a custom
message structure:

    struct impHitTest
    {
        ULONG MethodID; /* IM_HITTEST */
        struct
        {
            WORD X;     /* Coordinates of point to test for hit */
            WORD Y;
        } imp_Point;
    };

If an image object doesn't need to make any changes to how its superclass
handles IM_HITTEST, it can blindly pass this method on to its superclass.


B / imageclass / New Methods: IM_ERASE

The IM_ERASE method tells an image to erase itself.  Applications should
not call this method directly, instead they should call the Intuition
function EraseImage().  The return value for this method is not explicitly
defined.

The IM_ERASE method uses a custom message structure:

    struct impErase
    {
        ULONG           MethodID;   /* IM_ERASE */
        struct RastPort *imp_RPort; /* The image's RastPort */
        struct
        {
            WORD X;                 /* X and Y offset relative */
            WORD Y;                 /* to the image's IA_Left  */
        } imp_Offset;               /* and IA_Top attributes.  */
    };

The imageclass dispatcher calls the graphics.library function EraseRect()
to erase the image.  The imageclass dispatcher gets the position of the
image using the offsets from the IM_ERASE message and the dimensions it
finds in the object's Image structure.  The imageclass dispatcher does not
do any bounds checking before calling EraseRect().


B / imageclass / New Methods: IM_DRAWFRAME

The IM_DRAWFRAME method instructs an image object to render itself within
the confines of a given rectangle.  The return value for this method is
not explicitly defined.

This method uses a custom message structure that is basically an extension
of the IM_DRAW message: struct impDraw

    {
        ULONG           MethodID;    /* IM_DRAWFRAME */
        struct RastPort *imp_RPort;  /* RastPort to render into */
        struct
        {
            WORD X;                  /* X and Y offset relative to the */
            WORD Y;           /* image's IA_Left and IA_Top attributes */
        } imp_Offset;
        ULONG    imp_State;  /* Visual state of image (see defines below)*/
        struct DrawInfo *imp_DrInfo;
                    /* DrawInfo describing target RastPort (can be NULL) */
        struct
        {
            WORD Width;   /* scale, clip, restrict, etc. to these bounds */
            WORD Height;
        } imp_Dimensions;
    };

The Width and Height fields provide the object's rectangular bounds.  How
the image object deals with the frame is implementation specific.  If the
imageclass dispatcher sees this message, it will convert it to an IM_DRAW
message and send it back to the image's true class.  An image subclass
which assigns proper meaning to this method (i.e., frameiclass) should
handle this method itself.

This method is useful to classes of images that can scale or clip
themselves to arbitrary dimensions.  Typically, an instance of a class
that truly supports this method will massage its imagery as best it can to
fit into the rectangle.

In general, applications that use this method to draw an object should use
the IM_ERASEFRAME method to erase it (see below).  This will ensure that
the image erases itself at the proper scale.


B / imageclass / New Methods: IM_HITFRAME

This method is a special version of IM_HITTEST for images that support
IM_DRAWFRAME.  It asks an image if a point would be inside it if the image
was confined (scaled, clipped, etc.) to a rectangular bounds.  The return
value for this method is not explicitly defined.

This method uses a custom message structure:

    struct impHitTest
    {
        ULONG MethodID;    /* IM_HITFRAME */
        struct
        {
            WORD X;        /* Coordinates of point to test for hit */
            WORD Y;
        } imp_Point;

        struct
        {
            WORD Width;  /* scale, clip, restrict, etc. to these bounds */
            WORD Height;
        } imp_Dimensions;
    };

The imageclass dispatcher treats IM_HITFRAME just like IM_HITTEST,
ignoring the restricting dimensions.


B / imageclass / New Methods: IM_ERASEFRAME

This method is a special version of IM_ERASE for images that support
IM_DRAWFRAME.  It asks an image to erase itself as if it were confined
(scaled, clipped, etc.) to a rectangular bounds.  The return value for
this method is not explicitly defined.

This method uses a custom message structure:

struct impErase /* NOTE: This is a subset of impDraw */
    {
        ULONG           MethodID;   /* IM_ERASEFRAME */
        struct RastPort *imp_RPort; /* The image's RastPort */
        struct
        {
            WORD X;      /* X and Y offset relative to the */
            WORD Y;      /* image's IA_Left and IA_Top attributes */
        } imp_Offset;

        struct
        {
            WORD Width;  /* scale, clip, restrict, etc. to these bounds */
            WORD Height;
        } imp_Dimensions;
    };

The imageclass dispatcher handles an IM_ERASEFRAME message as if it was an
IM_ERASE message, ignoring the bounds.  See the imageclass description for
IM_ERASE for more details.


B / imageclass / New Methods: IM_FRAMEBOX

This method applies to image classes that are used to put a frame centered
around some other objects.  This method asks a framing image what its
dimensions should be if it had to frame some object or set of objects that
fit into a rectangular bounds.  For example, to draw an frameiclass image
around a group of gadgets that fit into a specific rectangle, you first
send the frameiclass object an IM_FRAMEBOX message describing the
dimensions and position of that rectangle.  The frame reports what its
position and dimensions would have to be to surround those gadgets.  Use
these results to draw the frameiclass image.  The return value for this
method is not explicitly defined.

IM_FRAMEBOX uses a custom message structure:

    struct impFrameBox
    {
        ULONG           MethodID;         /* IM_FRAMEBOX  */
        struct IBox     *imp_ContentsBox; /* The object fills in this  */
                                          /* structure with the        */
                                          /* dimensions of a rectangle */
                                          /* big enough to frame...    */
        struct IBox     *imp_FrameBox;    /* <------- this rectangle.  */
        struct DrawInfo *imp_DrInfo;      /* imp_DrInfo can be NULL.   */
        ULONG           imp_FrameFlags;
    };
    #define FRAMEF_SPECIFY  (1<<0)  /* Make do with the dimensions */
                                    /* passed in FrameBox.         */

The imp_FrameBox field points to an IBox structure (defined in
<intuition/intuition.h>) describing the dimensions and position of the
rectangle to frame.  After the framing image determines the position and
size it should be in order to properly frame imp_FrameBox, it stores the
result in the imp_ContentsBox IBox.  This method allows an application to
use a framing image without having to worry about image specific details
such as the thickness of the frame or centering the frame around the
object.

The imp_FrameFlags field is a bit field used to specify certain options
for the IM_FRAMEBOX method.  Currently, there is only one defined for it,
FRAMEF_SPECIFY.  If this bit is set, the imp_FrameBox contains a width and
height that the frame image has to use as its width and height, even if
the imp_FrameBox is smaller than imp_ContentsBox.  The frame is free to
adjust its position, but it is stuck with the imp_FrameBox dimensions.
This allows an application to set the size of the frame image and still
allow the frame image to position itself so it is centered on a rectangle.

The imageclass dispatcher does not support this method.  It returns zero.


B / imageclass / Changed Methods: OM_NEW

The instance data for imageclass contains an Image structure, and its
Depth field is initialized to CUSTOMIMAGEDEPTH, which identifies such
images to Intuition.  The Image's Width and Height fields default to
arbitrary positive numbers for safety, but an imageclass subclass or an
application should set these attributes to something meaningful.


B / imageclass / Changed Methods: OM_SET

This method applies to all imageclass attributes.  OM_SET returns 1.


B / imageclass / Attributes:IA_Left, IA_Top, IA_Width, IA_Height (ISG)

These attributes correspond to similarly named fields in the Intuition
Image structure.  The imageclass dispatcher stores these attributes in
their corresponding fields in the image object's embedded Image structure.


B / imageclass / Attributes: IA_FGPen, IA_BGPen (ISG)

These attributes are copied into the Image structure's PlanePick and
PlaneOnOff fields, respectively.


B / imageclass / Attributes: IA_Data (ISG)

A pointer to general image data.  This value is stored in the ImageData
field of the Image structure.


B / imageclass / Attributes: IA_Pens ()

This attribute points to an alternative pen array for the image.
Imageclass does not support this attribute, it is described here for
subclasses to use.  See the "Intuition Screens" chapter of the Amiga ROM
Kernel Reference Manual: Libraries for more information on the pen array.


B Boopsi Class Reference / frameiclass

Class:                  frameiclass
Superclass:             imageclass
Include File:           <intuition/imageclass.h>

This is a class of framing image, which can optionally fill itself.  Its
purpose is to frame other display elements using an embossed or recessed
rectangular frame.  The frame renders itself using the appropriate
DrawInfo pens (SHINEPEN, SHADOWPEN, etc.).  This class is intelligent
enough to bound or center its contents.

New Methods:
------------
None.

Changed Methods:
----------------
 IM_DRAW
 IDS_NORMAL, IDS_INACTIVENORMAL, IDS_DISABLED
 IDS_SELECTED, IDS_INACTIVESELECTED
 IM_DRAWFRAME
 IM_FRAMEBOX

Attributes:
-----------
 IA_Recessed (IS)    IA_EdgesOnly (IS)


B / frameiclass / Changed Methods: IM_DRAW

This method tells a frameiclass object to render itself using the position
and dimensions of its Image structure.  It supports two sets of drawing
states (passes in the impDraw.imp_State field):


B / frameiclass / IDS_NORMAL, IDS_INACTIVENORMAL, IDS_DISABLED

In these states, the frame renders its edges using SHADOWPEN and SHINEPEN.
If it is a filled frame the frame uses the BACKGROUNDPEN for its interior.
Note that the frame renders the same imagery for all three of these states.


B / frameiclass / Changed Methods: IDS_SELECTED, IDS_INACTIVESELECTED

In these states, the frame renders its edges using SHADOWPEN and SHINEPEN.
If it is a filled frame the frame uses the FILLPEN for its interior.

See the imageclass description for IM_DRAW for more details.


B / frameiclass / Changed Methods: IM_DRAWFRAME

This method is almost the same as the frameiclass IM_DRAW method, except
this method accepts a width and height that overrides the width and height
stored in the object's Image structure.  It uses the same drawing states
as the frameiclass's IM_DRAW method.  See the imageclass description for
IM_DRAWFRAME for more information.


B / frameiclass / Changed Methods: IM_FRAMEBOX

This method asks a frameiclass image what its dimensions would be if it
has to frame a specific rectangular area.  See the imageclass description
for IM_FRAMEBOX for more information.


B / frameiclass / Attributes: IA_Recessed (IS)

If this attribute is TRUE, a frameiclass object will appear recessed into
the drawing surface.  It does this by swapping its use of the SHADOWPEN
and SHINEPEN.  By default, the frame appears to be raised from the surface.


B / frameiclass / Attributes: IA_EdgesOnly (IS)

If this attribute is TRUE, the frame does not fill itself, it just draws
its edges.


B Boopsi Class Reference / sysiclass

Class:                  sysiclass
Superclass:             imageclass
Include File:           <intuition/imageclass.h>

This is a class of system images and standard application images.  As of
Intuition version 37, there are 11 possible sysiclass image glyphs to
choose from:

    DEPTHIMAGE   Window depth arrangement image.
    ZOOMIMAGE    Window Zoom image.
    SIZEIMAGE    Window Sizing image.
    CLOSEIMAGE   Window close image.
    SDEPTHIMAGE  Screen depth arrangement image.
    LEFTIMAGE    Left arrow image.
    RIGHTIMAGE   Right arrow image.
    UPIMAGE      Up arrow image.
    DOWNIMAGE    Down arrow image.
    CHECKIMAGE   Checkmark image.
    MXIMAGE      Radio button image.

The class caches the image's bitmap to improve rendering speed.

New Methods:
------------
None.

Changed Methods:
----------------
None.

Attributes:
-----------
 SYSIA_DrawInfo (I)    SYSIA_Which (I)    SYSIA_Size (I)


B / sysiclass / Attributes: SYSIA_DrawInfo (I)

This attribute contains a pointer to a DrawInfo structure (defined in
<intuition/screens.h>) describing the target screen.  The class requires
this attribute in order to generate the image into a bitmap cache.


B / sysiclass / Attributes: SYSIA_Which (I)

This attribute identifies which of the system image glyphs the sysiclass
object uses.  It can be one of the 11 glyphs described above.


B / sysiclass / Attributes: SYSIA_Size (I)

This attribute identifies which image size to use for the object.  This
generalizes Intuition's older concept of two different system image
dimensions.  There are three possible values for this attribute:

    SYSISIZE_MEDRES  Meant for Hires, non-interlaced 640x200/256 display.
    SYSISIZE_HIRES   Meant for Hires, interlaced 640x400/512 display.
    SYSISIZE_LOWRES  Meant for Lores 320x200/256 display.

These sizes do not apply to all of the glyphs consistently.  See the chart
below for image dimensions (width x height) according to the SYSIA_Size
and the glyph type.  An 'H' for the height means the glyph allows its
height to be specified with IA_Height.

    SYSISIZE        LOWRES      SYSISIZE_MEDRES  SYSISIZE_HIRES
    --------        ------      ---------------  --------------
    DEPTHIMAGE      18 x H          24 x H          24 x H
    ZOOMIMAGE       18 x H          24 x H          24 x H
    SIZEIMAGE       13 x 11         18 x 10         18 x 10
    CLOSEIMAGE      15 x H          20 x H          20 x H
    SDEPTHIMAGE     17 x H          23 x H          23 x H

    LEFTIMAGE       16 x 11         16 x 10         23 x 22
    RIGHTIMAGE      16 x 11         16 x 10         23 x 22
    UPIMAGE         13 x 11         18 x 11         23 x 22
    DOWNIMAGE       13 x 11         18 x 11         23 x 22

    CHECKIMAGE      26 x 11         26 x 11         26 x 11
    MXIMAGE         17 x 9          17 x 9          17 x 9


B Boopsi Class Reference / fillrectclass

Class:                  fillrectclass
Superclass:             imageclass
Include File:           <intuition/imageclass.h>

This is a class of filled rectangles.  The fillrectclass object can use a
pattern to fill in its interior.

New Methods:
------------
None.

Changed Methods:
----------------
 IM_DRAW    IM_DRAW

Attributes:
-----------
 IA_APattern, IA_APatSize (IS)    IA_Mode (IS)


B / fillrectclass / Changed Methods: IM_DRAW

This method asks a fillrectclass object to render itself relative to the
position (LeftEdge and TopEdge) and dimensions (Width and Height) in its
embedded Image structure.  See the imageclass description of IM_DRAW for
more details.


B / fillrectclass / Changed Methods: IM_DRAWFRAME

This method asks a fillrectclass object to render itself relative to the
position in its embedded Image structure, but using the width and height
passed in the message's Dimensions.Width and Dimensions.Height fields.
See the imageclass description of IM_DRAWFRAME for more details.


B / fillrectclass / Attributes: IA_APattern, IA_APatSize (IS)

These attributes supply the fillrectclass object with an area fill
pattern.  The IA_APattern attribute points to the area fill pattern for
the object.  The IA_APatSize attribute is the depth of the area fill
pattern.  These attribute values are similar to the parameters passed to
the SetAfPt() macro (defined in <graphics/gfxmacros.h>) and indirectly
correspond to fields in a RastPort structure.  For more information on
these patterns, see the section on patterns in the "Graphics Primitives"
chapter of the Amiga ROM Kernel Reference Manual: Libraries.


B / fillrectclass / Attributes: IA_Mode (IS)

This attribute contains the drawing mode for the pattern (JAM1, JAM2, etc.)


B Boopsi Class Reference / itexticlass

Class:                  itexticlass
Superclass:             imageclass
Include File:           <intuition/imageclass.h>

This is a class of image objects that render an IntuiText structure.
Using some of the imageclass attributes, the object can override some of
the parameters in the IntuiText structure.  This class makes it easy to
share an IntuiText structure between objects.

New Methods:
------------
None.

Changed Methods:
----------------
 IM_DRAW/IM_DRAWFRAME


B / itexticlass / New Methods: IM_DRAW/IM_DRAWFRAME

These methods ask an itexticlass object to render its IntuiText structure,
which it gets from the imageclass IA_Data attribute.  An itexticlass
object renders its IntuiText relative to the IA_Left and IA_Top attributes
it inherits from imageclass.  This method uses the JAM1 drawing mode and
the IA_FGPen to render the text.  See the imageclass description of
IM_DRAW/IM_DRAWFRAME for more details.


B Boopsi Class Reference / gadgetclass

Class:                  gadgetclass
Superclass:             rootclass
Include File:           <intuition/gadgetclass.h>

This is a base class for Intuition compatible gadget objects.  The
dispatcher for this class takes care of creating an Intuition Gadget
structure as part of its local instance data.  All of the standard Boopsi
gadget classes build on this class.  Normally there are no direct
instances of this class, only instances of subclasses of gadgetclass.

The behavior of a Boopsi gadget depends on how it handles the five Boopsi
gadget methods: GM_HITTEST, GM_RENDER, GM_GOACTIVE, GM_HANDLEINPUT, and
GM_GOINACTIVE.  Intuition controls a Boopsi gadget by sending it these
types of messages.  The structures that these methods use for their
messages begin with the method's ID followed by a pointer to a GadgetInfo
structure (defined in <intuition/cghooks.h>).  The GadgetInfo structure is
a read-only structure that contains information about the gadget's
rendering environment.  The gadget uses this to find things like its
window, screen, or pen array.  Although this structure does contain a
pointer to a RastPort for the gadget, the gadget must not use this
RastPort for rendering.  The gadget can obtain a RastPort for rendering by
calling the Intuition function ObtainGIRPort() using the GadgetInfo
structure.  See the intuition.library Autodocs for more details on this
function.

These methods are not defined directly by gadgetclass.  It is up to
subclasses of gadgetclass to implement them.

Like all Boopsi methods, these methods run on the context of the task that
called the method.  Normally, Intuition is the only entity that calls
these methods, so these normally operate in the input.device's task.
Because a gadget may have to process a large number of input events, poor
implementations of gadget methods (especially the GM_HANDLEINPUT method)
can degrade system performance.

New Methods:
------------
 GM_HITTEST    GM_GOACTIVE       GM_GOINACTIVE
 GM_RENDER     GM_HANDLEINPUT

Changed Methods:
----------------
 OM_NEW    OM_NOTIFY

Attributes:
-----------
 GA_Previous (I)
 ICA_TARGET (IS)
 ICA_MAP (IS)
 GA_Left, GA_Top, GA_Width, GA_Height (IS)
 GA_RelRight, GA_RelBottom, GA_RelWidth, GA_RelHeight (IS)

The remaining attributes defined by gadgetclass are used to set the fields
in the Gadget structure of the Boopsi gadget.  Some Boopsi gadgets do not
pay attention to many of the fields in its Gadget structure, so most
applications will not have to worry about the majority of these
attributes.  Some gadget classes assign special meanings to these
attributes.  See the documentation of the specific gadget classes for more
details.

 GA_IntuiText, GA_Text, GA_LabelImage (IS)
 GA_Image (IS)
 GA_Border, GA_SelectRender, GA_ID, GA_UserData, GA_SpecialInfo (IS)
 GA_GZZGadget, GA_SysGadget (IS)
 GA_Disabled, GA_Selected (IS)
 GA_EndGadget, GA_Immediate, GA_RelVerify, GA_FollowMouse, (IS)
 GA_RightBorder, GA_LeftBorder, GA_TopBorder, GA_BottomBorder, (IS)
 GA_ToggleSelect, GA_TabCycle (IS)
 GA_Highlight (IS)
 GA_SysGType (IS)


B / gadgetclass / New Methods: GM_HITTEST

This method asks a gadget if a point is within its bounds. Usually the
point corresponds to a mouse click.  Intuition sends a gadget this message
when the user clicks inside the rectangular bounds found in the object's
Gadget structure (using its TopEdge, LeftEdge, Width, and Height fields).
This method returns GMR_GADGETHIT if a point is within the gadget,
otherwise it returns zero.  Because the gadget decides if it was hit, the
gadget can be almost any shape or pattern.  Boopsi gadgets that default to
using the bounds of their Gadget structure should always return
GMR_GADGETHIT.

GM_HITTEST uses a custom message structure (defined in
<intuition/gadgetclass.h>):

    struct gpHitTest
    {
        ULONG             MethodID;     /* GM_HITTEST   */
        struct GadgetInfo *gpht_GInfo;
        struct
        {
            WORD X;                     /* Is this point inside */
            WORD Y;                     /* of the gadget?       */
        } gpht_Mouse;
    };

The gpht_Mouse.X and gpht_Mouse.Y fields make up the X and Y coordinates
of the hit point.  These coordinates are relative to the upper-left corner
of the gadget (Gadget.LeftEdge, Gadget.TopEdge).


B / gadgetclass / New Methods: GM_RENDER

This method tells a gadget to render itself.  The return value for this
method is not explicitly defined.

GM_RENDER uses a custom message structure (defined in
<intuition/gadgetclass.h>):

    struct gpRender
    {
        ULONG             MethodID;   /* GM_RENDER */
        struct GadgetInfo *gpr_GInfo;
        struct RastPort   *gpr_RPort; /* all ready for use */
        LONG              gpr_Redraw; /* might be a "highlight pass" */
    };

The GM_RENDER message contains a pointer to the Gadget's RastPort which it
can use for rendering.  The Gadget renders itself according to how much
imagery it needs to replace.  The gpr_Redraw field contains one of three
values:

GREDRAW_REDRAW  Redraw the entire gadget.

GREDRAW_UPDATE  The user has manipulated the gadget changing the
                imagery.  Update only that part of the gadget's
                imagery that is effected by the user manipulating the
                gadget (for example, the knob and scrolling field of
                the prop gadget).

GREDRAW_TOGGLE  If this gadget supports it, toggle to or from the
                highlighting imagery.


B / gadgetclass / New Methods: GM_GOACTIVE

This method asks a gadget if it is OK to make it the active gadget.  The
active gadget is the gadget that is currently receiving user input.
Intuition sends this message after a gadget responds affirmatively to the
GM_HITTEST method.  A gadget becomes active because it needs to process
input events (like a prop gadget or string gadget).

Some types of gadget do not need to become active.  These gadgets do not
have to process input from the user, they only have to deal with a single
mouse click to toggle their state.  Because that mouse click triggered
this method, the button already has all of the user input it requires.
Note that the behavior of the GadTools button differs from a Boopsi
buttongclass gadget, which processes other input events besides a single
mouse click.  See the entry for buttongclass in this Appendix for more
details.

GM_GOACTIVE uses a custom message structure (defined in
<intuition/gadgetclass.h>):

    struct gpInput
    {
        ULONG             MethodID;    /* GM_GOACTIVE or GM_HANDLEINPUT */
        struct GadgetInfo *gpi_GInfo;
        struct InputEvent *gpi_IEvent; /* The input event that triggered */
                                       /* this method (can be NULL for   */
                                       /* GM_GOACTIVE).                  */
        LONG         *gpi_Termination; /* For GADGETUP IntuiMessage.Code */
        struct
        {
            WORD X;             /* Mouse position relative to upper      */
            WORD Y;             /* left corner of gadget (LeftEdge,      */
        } gpi_Mouse;            /* TopEdge).                             */
    };

The gpi_IEvent field points to the struct InputEvent that triggered the
GM_GOACTIVE message.  If gpi_IEvent is NULL, the GM_GOACTIVE message was
triggered by a function like intuition.library's ActivateGadget() and not
by the user clicking the gadget.

For gadgets that only want to become active as a direct result of a mouse
click, this difference is important.  For example, the prop gadget becomes
active only when the user clicks on its knob.  Because the only way the
user can control the prop gadget is via the mouse, it would not make sense
for it to be activated by anything besides the mouse.  On the other hand,
a string gadget gets input from the keyboard, so a string gadget doesn't
care what activates it.  Its input comes from the keyboard rather than the
mouse.

A gadget's GM_GOACTIVE method returns GMR_MEACTIVE (defined in
<intuition/gadgetclass.h>) if it wants to be the active gadget.  Otherwise
it returns GMR_NOREUSE.  For a description of what these values mean, See
their description in the gadgetclass's GM_HANDLEINPUT method, below.

If necessary, a gadget's GM_GOACTIVE method can precalculate and cache
information before it becomes the active gadget.  The gadget will use this
information while it's processing user input with the GM_HANDLEINPUT
method.  When it is time for the active gadget to become inactive,
Intuition will send the gadget a GM_GOINACTIVE message.  The gadget can
clean up its precalculations and cache in the GM_GOINACTIVE method.  For
more information on GM_GOINACTIVE, see its description below.


B / gadgetclass / New Methods: GM_HANDLEINPUT

This method asks an active gadget to handle an input event.  After
Intuition gets an OK to make this gadget object active (see the
GM_GOACTIVE method above), Intuition starts sending input events to the
gadget.  Intuition sends them in the form of a GM_HANDLEINPUT message.
This method uses the same custom message structure as GM_GOACTIVE (see the
gpInput structure above).

The information in the gpInput structure is the same for GM_HANDLEINPUT as
it is for GM_GOACTIVE.  The only difference is that the GM_HANDLEINPUT
message's gpi_IEvent can never be NULL.  It always points to an InputEvent
structure.

The gadget has to examine the incoming InputEvents to see how its state
may have changed.  For example,  a string gadget processes key presses,
inserting them into the gadgets string.  When the string changes, the
gadget has to update its visual state to reflect that change.  Another
example is the prop gadget.  If the user picks up the prop gadget's knob,
the prop gadget has to track the mouse to process changes to the gadget's
internal values.  It does this by processing IECLASS_RAWMOUSE events.

If the GM_HANDLEINPUT method needs to do some rendering, it must call
ObtainGIRPort() on the GM_HANDLEINPUT message's gpi_GInfo to get a pointer
to a RastPort.  To relinquish this RastPort, the GM_HANDLEINPUT method
must call ReleaseGIRPort().  The GM_HANDLEINPUT method has to allocate and
release this RastPort, it cannot be cached in the GM_GOACTIVE method.

The return value from GM_HANDLEINPUT informs Intuition if the gadget wants
to remain active.  The return values for the GM_HANDLEINPUT are similar to
GM_GOACTIVE.  The gadget tells Intuition that it wants to remain active by
returning GMR_MEACTIVE.  A gadget tells Intuition it wants to become
inactive by returning one of the "go inactive" return values:

GMR_NOREUSE     Tells Intuition to throw away the gpInput.gpi_IEvent
                InputEvent.

GMR_REUSE       Tells Intuition to reprocess the gpInput.gpi_IEvent
                InputEvent after deactivating the gadget.

GMR_NEXTACTIVE  Tells Intuition to throw away the gpInput.gpi_IEvent
                InputEvent and activate the next GFLG_TABCYCLE gadget.

GMR_PREVACTIVE  Tells Intuition to throw away the gpInput.gpi_IEvent
                InputEvent and activate the previous GFLG_TABCYCLE gadget.

GMR_NOREUSE tells Intuition that the gadget does not want to be active and
should throw away the InputEvent that triggered the GM_HANDLEINPUT message
(or the GM_GOACTIVE message).  For example, an active prop gadget returns
GMR_NOREUSE when the user lets go of the left mouse button (thus letting
go of the prop gadget's knob).

A gadget can also return GMR_REUSE, which tells Intuition to reuse the
InputEvent.  For example, if the user clicks outside of an active string
gadget, that string gadget returns GMR_REUSE so Intuition can process that
mouse click, which could be over another gadget.  Another case where a
string gadget returns GMR_REUSE is when the user pushes the right mouse
button (the menu button).  The string gadget becomes inactive and the menu
button InputEvent gets reused by Intuition so it can pop up the menu bar.

The other two possible return values, GMR_NEXTACTIVE and GMR_PREVACTIVE
were added to the OS for Release 2.04.  These tell Intuition that a gadget
no longer wants to be active and that the GM_HANDLEINPUT message
InputEvent should be discarded.  Intuition then looks for the next
non-disabled (GMR_NEXTACTIVE) or previous (GMR_PREVACTIVE) gadget that has
its GFLG_TABCYCLE flag set in its Gadget.Activation field (see the
gadgetclass GA_TabCycle attribute below), and attempts to activate it.

For both GM_GOACTIVE and GM_HANDLEINPUT, the gadget can bitwise OR any of
these "go inactive" return values with GMR_VERIFY.  The GMR_VERIFY flag
tells Intuition to send a IDCMP_GADGETUP IntuiMessage to the gadget's
window. If the gadget uses GMR_VERIFY, it has to supply a value for the
IntuiMessage's Code field.  It does this by passing a value in the
gpInput's gpi_Termination field.  This field points to a long word, the
lower 16-bits of which Intuition copies into the Code field.  The upper
16-bits are for future enhancements, so clear these bits.


B / gadgetclass / New Methods: GM_GOINACTIVE

This method tells the active gadget to become inactive.  The return value
for this method is not explicitly defined.

GM_GOINACTIVE uses a custom message structure (defined in
<intuition/gadgetclass.h>):

    struct gpGoInactive
    {
        ULONG             MethodID;    /* GM_GOINACTIVE */
        struct GadgetInfo *gpgi_GInfo;

    /* V37 field only!  DO NOT attempt to read under V36! */
        ULONG             gpgi_Abort; /* gpgi_Abort=1 if gadget was    */
                                      /* aborted by Intuition and 0 if */
                                      /* gadget went inactive at its   */
                                      /* own request.                  */
    };

The gpgi_Abort field contains either a 0 or 1.  If it is 0, the gadget
became inactive at its own request (because the GM_HANDLEINPUT method
returned something besides GMR_MEACTIVE).  If gpgi_Abort is 1, Intuition
aborted this active gadget.  Some cases where Intuition aborts a gadget
include: the user clicked in another window or screen, an application
removed the active gadget with RemoveGList(), and an application called
ActivateWindow() on a window other than the gadget's window.

If the gadget allocated any resources to cache or precalculate information
in the GM_GOACTIVE method, it should deallocate those resources in this
method.


B / gadgetclass / Changed Methods: OM_NEW

This method allocates space for an embedded struct Gadget (defined in
<intuition/intuition.h>) and initializes some of the attributes defined by
gadgetclass.


B / gadgetclass / Changed Methods: OM_NOTIFY

This method tells a gadget to send an OM_UPDATE message to its target
object.  Boopsi gadgets have a function similar to icclass objects--each
gadget can have an ICA_TARGET and ICA_MAP in order to notify some target
object of attribute changes.  When a Boopsi gadget sends an OM_NOTIFY
message, it always includes its GA_ID.  This makes it easy for an
application to tell which gadget initially sent the OM_NOTIFY.  See the
description of icclass's OM_NOTIFY and OM_UPDATE and the rootclass's
OM_NOTIFY and OM_UPDATE methods for more details.


B / gadgetclass / Attributes: GA_Previous (I)

This attribute is used to insert a new gadget into a list of gadgets
linked by their Gadget.NextGadget field.  When the OM_NEW method creates
the new gadget, it inserts the new gadget into the list following the
GA_Previous gadget.  This attribute is a pointer to the gadget  (struct
Gadget *) that the new gadget will follow.  This attribute cannot be used
to link new gadgets into the gadget list of an open window or requester,
use AddGList() instead.


B / gadgetclass / Attributes: ICA_TARGET (IS)

This attribute stores the address of the gadget's target object.  Whenever
the gadget receives an OM_NOTIFY message, it sends an OM_UPDATE message to
its target.  If the gadget has an attribute mapping list (see the ICA_MAP
attribute below), it also maps the IDs from the OM_NOTIFY message.

If the value of ICA_TARGET is ICTARGET_IDCMP, the gadget sends an
IDCMP_IDCMPUPDATE IntuiMessage to its window.  See the rootclass
description of OM_UPDATE for more information.


B / gadgetclass / Attributes: ICA_MAP (IS)

This attribute points to a tag list of attribute mappings which the gadget
uses to change the attribute IDs of an OM_UPDATE's attribute/value pairs.
For example, if a gadget had the following ICA_MAP:

    struct TagItem map[] =
    {
        {PGA_Top, STRINGA_LongVal},
        {MYATTR, MYNEWATTR},
        {TAG_END, }
    };

before it sends an OM_UPDATE to its ICA_TARGET, the gadget scans through
the OM_UPDATE message's attribute/value pairs looking for the PGA_Top and
MYATTR attributes.  If it finds the PGA_Top attribute, it changes PGA_Top
to STRINGA_LongVal.  Likewise, if the gadget finds the MYATTR attribute,
it changes MYATTR to MYNEWATTR.  The gadget does not disturb the
attribute's value, only its ID.


B / gadgetclass / Attributes:GA_Left, GA_Top, GA_Width, GA_Height (IS)

These attributes correspond to the Gadget structure's LeftEdge, TopEdge,
Width, and Height fields.  Setting these clears the "gadget relative"
flags (below).


B / / GA_RelRight, GA_RelBottom, GA_RelWidth, GA_RelHeight (IS)

These attributes correspond to the Gadget structure's LeftEdge, TopEdge,
Width, and Height fields.  Setting any of these attributes also sets the
corresponding "relative" flag in the Gadget structure's Flags field
(respectively, GFLG_RELRIGHT, GFLG_RELBOTTOM, GFLG_RELWIDTH, and
GFLG_RELHEIGHT).  Note that the value passed in this attribute is normally
a negative LONG.  See the "Intuition Gadgets" chapter of the Amiga ROM
Kernel Reference Manual: Libraries for more information on these flags.


B / gadgetclass / Attributes:GA_IntuiText, GA_Text, GA_LabelImage (IS)

These attributes correspond to one field in the object's embedded Gadget
structure--the GadgetText field.  Setting any of these attributes copies
the attribute's value blindly into the GadgetText field.  In addition,
setting GA_Text also sets the GFLG_LABELSTRING flag in Gadget.Flags and
setting GA_LabelImage sets the GFLG_LABELIMAGE flag in Gadget.Flags.  The
GA_IntuiText attribute must be an IntuiText pointer, as with old-style
gadgets.  GA_Text takes a pointer to a NULL- terminated string (UBYTE *).
GA_LabelImage takes a pointer to a (Boopsi) image.  Note that most gadget
classes do not support GA_Text and GA_LabelImage.  See the description of
specific gadget classes for more details.


B / gadgetclass / Attributes: GA_Image (IS)

This attibute is a pointer to either a Boopsi image or a Release
1.3-compatible Intuition image.  This attribute corresponds to the
Gadget's GadgetRender field.  The gadgetclass dispatcher will not dispose
of this image when it disposes of the gadget object.


B / gadgetclass / Attributes: GA_Border - GA_SpecialInfo (IS)

GA_Border, GA_SelectRender, GA_ID, GA_UserData, GA_SpecialInfo (IS) -
These attributes correspond to the similarly named fields in the Gadget
structure embedded in the gadget object.


B / gadgetclass / Attributes: GA_GZZGadget, GA_SysGadget (IS)

These are boolean attributes that correspond to the flags in the object's
Gadget.GadgetType field.  If the value passed with the attribute is TRUE,
the corresponding flag in Gadget.GadgetType is set.  If the value passed
with the attribute is FALSE, the corresponding flag in Gadget.GadgetType
is cleared.  See the <intuition/intuition.h> include file or the
"Intuition Gadgets" chapter of the Amiga ROM Kernel Reference Manual:
Libraries for more information.


B / gadgetclass / Attributes: GA_Disabled, GA_Selected (IS)

These are boolean attributes that correspond to the similarly named flags
in the object's Gadget.Flags field.  If the value passed with the
attribute is TRUE, the corresponding flag in Gadget.Flags is set.  If the
value passed with the attribute is FALSE, the corresponding flag in
Gadget.Flags is cleared.  See the <intuition/intuition.h> include file or
the "Intuition Gadgets" chapter of the Amiga ROM Kernel Reference Manual:
Libraries for more information.


B / gadgetclass / Attributes: GA_EndGadget - GA_TabCycle (IS)

GA_EndGadget, GA_Immediate, GA_RelVerify, GA_FollowMouse, (IS)
GA_RightBorder, GA_LeftBorder, GA_TopBorder, GA_BottomBorder, (IS)
GA_ToggleSelect, GA_TabCycle (IS) - These are boolean attributes that
correspond to the flags in the object's Gadget.Activation field.  If the
value passed with the attribute is TRUE, the corresponding flag in
Gadget.Activation is set.  If the value passed with the attribute is
FALSE, the corresponding flag in Gadget.Activation is cleared.  See the
<intuition/intuition.h> include file or the "Intuition Gadgets" chapter of
the Amiga ROM Kernel Reference Manual: Libraries for more information.


B / gadgetclass / Attributes: GA_Highlight (IS)

This attribute corresponds to the GFLG_GADGHIGHBITS portion of the
gadget's Gadget.Flags field.  This attribute can be one of four values
(from <intuition/intuition.h>):

    GFLG_GADGHCOMP, GFLG_GADGHBOX, GFLG_GADGHIMAGE, GFLG_GADGHNONE

See the "Intuition Gadgets" chapter of the Amiga ROM Kernel Reference
Manual: Libraries for more information.


B / gadgetclass / Attributes: GA_SysGType (IS)

This attribute corresponds to the system gadget type portion of the
gadget's Gadget.GadgetType fields.  This attribute is any one of the
following flags (from <intuition/intuition.h>):

    GTYP_SIZING, GTYP_WDRAGGING, GTYP_SDRAGGING, GTYP_WUPFRONT,
    GTYP_SUPFRONT, GTYP_WDOWNBACK, GTYP_SDOWNBACK, GTYP_CLOSE

See the "Intuition Gadgets" chapter of the Amiga ROM Kernel Reference
Manual: Libraries for more information.


B Boopsi Class Reference / propgclass

Class:                  propgclass
Superclass:             gadgetclass
Include File:           <intuition/gadgetclass.h>

A Boopsi proportional ("prop") gadget.  The Boopsi prop gadget is similar
to the conventional prop gadget, but extends its function to make it
easier to use.  The Boopsi prop gadget keeps its current integer value in
its PGA_Top attribute.

New Methods:
------------
None.

Changed Methods:
----------------
 GM_HANDLEINPUT

Attributes:
-----------
 GA_Image (I)        PGA_Freedom (IG)      PGA_Top (ISGNU)
 GA_Border (I)       PGA_NewLook (I)       PGA_Visible, PGA_Total (ISU)
 GA_Highlight (I)    PGA_Borderless (I)


B / propgclass / Changed Methods: GM_HANDLEINPUT

If the knob position changes sufficiently to change a propgclass object's
PGA_Top attribute, the gadget will send an OM_NOTIFY message to itself,
which the propgclass dispatcher passes on to the gadgetclass dispatcher
for processing (see the rootclass description of OM_NOTIFY and OM_UPDATE
for more information).

The OM_NOTIFY message will contain two attribute/value pairs, PGA_Top and
GA_ID.  While the prop gadget's PGA_Top is in a transitory state (while it
is active and the user is moving the prop gadget's knob), the gadget sends
interim OM_NOTIFY messages.  The interim OM_NOTIFY messages have the
OPUF_INTERIM flag of the opUpdate.opu_Flags field set.  When the user
finishes manipulating the gadget (by letting go of the knob), the gadget
sends a final OM_NOTIFY message, which has a cleared OPUF_INTERIM flag.


B / propgclass / Attributes: GA_Image (I)

Propgclass intercepts this gadgetclass attribute before passing it on to
gadgetclass.  This attribute passes an image for the prop gadget's knob,
which gets stored in the propgclass object's Gadget.Image structure.  If
the propgclass does not get a GA_Image when it creates a prop gadget, the
prop gadget's knob defaults to an AUTOKNOB.  An AUTOKNOB automatically
sizes itself according to how large the range of the gadget is compared to
the visible range of the gadget.  See the PGA_Visible and PGA_Total
attributes for more details.


B / propgclass / Attributes: GA_Border (I)

Propgclass intercepts this gadgetclass attribute to prevent gadgetclass
from setting up a border.  If an application tries to set this attribute
for a propgclass gadget, the prop gadget turns itself into an AUTOKNOB
gadget.


B / propgclass / Attributes: GA_Highlight (I)

Propgclass intercepts this gadgetclass attribute before passing it on to
gadgetclass.  It does this to make sure the highlighting is not set to
GADGHBOX.  GADGHBOX will be converted to GADGHCOMP.  See the
"Intuition Gadgets" chapter of the Amiga ROM Kernel Reference Manual:
Libraries for more information on the types of gadget highlighting.

Other gadgetclass attributes are passed along to the superclass.


B / propgclass / Attributes: PGA_Freedom (IG)

This attribute tells a propgclass object on which axis the gadget's knob
is free to move, the horizontal or the vertical.  It is either FREEHORIZ
or FREEVERT.  The default is FREEVERT.


B / propgclass / Attributes: PGA_NewLook (I)

This is a boolean attribute which corresponds to the PROPNEWLOOK flag
PropInfo structure's Flags field (defined in <intuition/intuition.h>).  If
this attribute is TRUE, the new propgclass object will use Release 2
imagery rather than the Release 1.3 imagery.


B / propgclass / Attributes: PGA_Borderless (I)

This is a boolean attribute which corresponds to the PROPBORDERLESS flag of
the PropInfo structure's Flags field (defined in <intuition/intuition.h>).
If this attribute is TRUE, the new propgclass object will not have a
border around it.  In an AUTOKNOB propgclass gadget, if the PROPNEWLOOK
flag is set as well (see the PGA_NewLook attribute), the knob will have a
3D appearance.


B / propgclass / PGA_Top (ISGNU), PGA_Visible, PGA_Total (ISU)

These attributes replace the Pot and Body variables of the Release 1.3
prop gadget. They are based on the use of proportional gadgets to control
scrolling text.  When scrolling 100 lines of text in a 25 line visible
window, you would set PGA_Total to 100, PGA_Visible to 25, and watch
PGA_Top run from 0 to 75 (the top line of the last page).

If the user clicks in the prop gadget but not on the knob, the entire knob
jumps one "page" (the size of the visible area minus one, PGA_Visible-1).
The page jump will leave an overlap of one line, unless the value
PGA_Visible is 1, in which case the prop gadget acts as an integer numeric
slider, sliding from 0 to PGA_Total - 1.

Note that when PGA_Top changes, the gadget sends itself an OM_NOTIFY
message about this attribute change (see the propgclass description of
GM_HANDLEINPUT for more information).  All three of these attributes have
OM_UPDATE access, so they can be controlled from other objects.


B Boopsi Class Reference / strgclass

Class:                  strgclass
Superclass:             gadgetclass
Include File:           <intuition/gadgetclass.h>

Intuition compatible string gadgets.  The Boopsi string gadget can either
be a plain string gadget or an integer string gadget.  An integer gadget
filters out all characters except those that make up integer values.

New Methods:
------------
None.

Changed Methods:
----------------
 OM_NEW

Attributes:
-----------
 STRINGA_LongVal (ISGNU)    STRINGA_TextVal (ISGNU)

The remaining strgclass attributes correspond to the flags and fields that
the conventional Intuition string gadget uses.  See the "STRING GADGET
TYPE" section of the "Intuition Gadgets" chapter of the Amiga ROM Kernel
Reference Manual: Libraries for more information.

 STRINGA_MaxChars, STRINGA_Buffer, (I)
 STRINGA_UndoBuffer, STRINGA_WorkBuffer (I)
 STRINGA_BufferPos, STRINGA_DispPos (ISU)
 STRINGA_AltKeyMap (IS)
 STRINGA_Font (IS)
 STRINGA_Pens (IS)
 STRINGA_ActivePens (IS)
 STRINGA_EditHook (I)
 STRINGA_EditModes (IS)
 STRINGA_ReplaceMode, STRINGA_FixedFieldMode, STRINGA_NoFilterMode (IS)
 STRINGA_Justification (IS)
 STRINGA_ExitHelp (IS)


B / strgclass / Changed Methods: OM_NEW

This method sets up the string gadget's StringInfo and StringExtend
structures.  It allocates a buffer if needed and will use shared data
buffers for UndoBuffer and WorkBuffer if the MaxChars is less than
SG_DEFAULTMAXCHARS (128).  Default text pens are: Foreground = 1,
Background = 0.  See the rootclass description of the OM_NEW method for
more details.


B / strgclass / Attributes: STRINGA_LongVal (ISGNU)

This attribute tells strgclass that this gadget is an integer string
gadget and the new value of the integer is this attribute's value.


B / strgclass / Attributes: STRINGA_TextVal (ISGNU)

This attribute tells strgclass that this gadget is a plain string gadget.
The attribute points to a string which the object copies into the string
gadget's current string value buffer.

When a strgclass gadget's internal STRINGA_LongVal or STRINGA_TextVal
value changes (usually because the user manipulated the gadget), it sends
itself an OM_NOTIFY message.  The OM_NOTIFY message will contain two
attribute/value pairs, GA_ID and either STRINGA_LongVal or STRINGA_TextVal
(depending on what kind of strgclass gadget it is).  Strgclass gadgets
only send a final OM_NOTIFY message (one's with the OPUF_INTERIM flag of
the opUpdate.opu_Flags field cleared).


B / strgclass / Attributes: STRINGA_MaxChars - STRINGA_WorkBuffer (I)

STRINGA_MaxChars, STRINGA_Buffer, STRINGA_UndoBuffer, STRINGA_WorkBuffer
(I) - Specify various buffers defined for string gadgets and extended
string gadgets.  If your value of STRINGA_MaxChars is less than
SG_DEFAULTMAXCHARS (128 for now), then this class can provide all these
buffers for you.  Note that UndoBuffer and WorkBuffer can be shared by
many separate gadgets, providing they are as large as the largest MaxChars
they will encounter.


B / strgclass / Attributes: STRINGA_BufferPos, STRINGA_DispPos (ISU)

The attributes tell the object its cursor and scroll position.


B / strgclass / Attributes: STRINGA_AltKeyMap (IS)

This attribute corresponds to the StringInfo.AltKeyMap field.


B / strgclass / Attributes: STRINGA_Font (IS)

This attributes points to an open TextFont structure that the string
gadget uses for rendering its text.


B / strgclass / Attributes: STRINGA_Pens (IS)

Pen numbers, packed as two WORDs into a longword, for rendering gadget
text.


B / strgclass / Attributes: STRINGA_ActivePens (IS)

Optional pen numbers, packed as two WORDs into a longword, for rendering
gadget text when the gadget is active.


B / strgclass / Attributes: STRINGA_EditHook (I)

Custom string gadget edit hook.


B / strgclass / Attributes: STRINGA_EditModes (IS)

Value taken from flags defined in <intuition/cghooks.h> for initial
editing modes.


B / strgclass / STRINGA_ReplaceMode - STRINGA_NoFilterMode (IS)

STRINGA_ReplaceMode, STRINGA_FixedFieldMode, STRINGA_NoFilterMode (IS) -
These three are independent Boolean equivalents to the individual flags
that you can set for STRINGA_EditModes.


B / strgclass / Attributes: STRINGA_Justification (IS)

Takes the values STRINGCENTER, STRINGRIGHT, and STRINGLEFT (which is 0).


B / strgclass / Attributes: STRINGA_ExitHelp (IS)

Set this if you want the gadget to exit when the "Help" key is pressed.
Look for a code of 0x5F, the rawkey code for help.


B Boopsi Class Reference / buttongclass

Class:                  buttongclass
Superclass:             gadgetclass
Include File:           <intuition/gadgetclass.h>

A class of button gadget that continually sends interim OM_UPDATE messages
to its target while the user holds down the button.  The button sends a
final OM_UPDATE message when the user lets  go of the button.  The imagery
for these objects is not built directly into the gadget.  Instead, a
buttongclass object uses a Boopsi image object, which it gets from its
GA_Image attribute.

New Methods:
------------
None.

Changed Methods:
----------------
 GM_HITTEST    GM_HANDLEINPUT    GM_RENDER

Attributes:
-----------
 GA_IMAGE (IS)


B / buttongclass / Changed Methods: GM_HITTEST

This method gets passed over to the button's image for processing.  The
button's IM_HITTEST checks for the hit.


B / buttongclass / Changed Methods: GM_HANDLEINPUT

This method continuously issues OM_NOTIFY messages for each IECLASS_TIMER
event it gets.  The OM_NOTIFY message's OPUF_INTERIM flag (from
opUpdate.opu_Flags) is set for all but the final OM_NOTIFY.

The OM_NOTIFY message contains one attribute/value pair, GA_ID.  If the
pointer is currently over the gadget image, the value of this
attribute/value pair is the gadget's actual GA_ID (from the
Gadget.GadgetID field).  If the pointer isn't over the image, the value is
the negative of the gadget's actual GA_ID.


B / buttongclass / Changed Methods: GM_RENDER

All rendering is passed along to the GadgetRender.Image (the GA_Image
attribute).  This method can tell its image to render in any of four image
states: IDS_INACTIVESELECTED, IDS_INACTIVENORMAL, IDS_SELECTED, or
IDS_NORMAL.


B / buttongclass / Attributes: GA_Image (IS)

This attribute points to the gadget's Boopsi image.  Changing this
attribute will cause the gadget to refresh its imagery.


B Boopsi Class Reference / frbuttonclass

Class:                  frbuttonclass
Superclass:             buttongclass
Include File:           <intuition/gadgetclass.h>

This is a special class of button gadget that puts a Boopsi framing image
around some other display element.  This display element can be one of
three things: plain text from the GA_Text attribute, an IntuiText from the
GA_IntuiText attribute, or an Image from the GA_LabelImage attribute.

The user activates the gadget by clicking within the bounds of the
gadget's framing image, which it gets from the GA_Image attribute.
Usually the framing image is an instance of an image class that supports
the IM_FRAMEBOX method (like frameiclass).  If the framing image supports
the IM_FRAMEBOX method, the frbuttonclass object centers the frame image
around the display element.  See the imageclass description of IM_FRAMEBOX
for more information.

New Methods:
------------
None.

Changed Methods:
----------------
 OM_NEW    GM_HITTEST    GM_RENDER

Attributes:
-----------
 GA_Width, GA_Height (S)
 GA_DrawInfo (I)
 GA_Text, GA_IntuiText, GA_LabelImage (IS)


B / frbuttonclass / Changed Methods: OM_NEW

When this class creates an object, it sets the object's embedded
Gadget.Width and Gadget.Height fields according to the frame image in
GA_Image.  If the GA_Image understands the IM_FRAMEBOX method, the gadget
asks the GA_Image what it dimensions would be if it had to surround the
display element.  If the GA_Image does not support IM_FRAMEBOX, it just
copies the GA_Image image's width and height into the Gadget structure.


B / frbuttonclass / Changed Methods: GM_HITTEST

The gadget delegates this method to the framing image's IM_HITFRAME method.


B / frbuttonclass / Changed Methods: GM_RENDER

For this method, the frbuttonclass object first draws the framing image by
sending the image an IM_DRAWFRAME message.  The object then draws its
display element.


B / frbuttonclass / Attributes: GA_Width, GA_Height (S)

These attribute correspond to the gadget's Width and Height fields.  If
the framing image supports IM_FRAMEBOX, changing these resizes the framing
image.  The framing image re-centers itself around the display element as
best it can, and the frbuttonclass gadget re-renders the whole itself.


B / frbuttonclass / Attributes: GA_DrawInfo (I)

This attribute passes a pointer to a valid DrawInfo structure.  If the
frbuttonclass gadget is going to frame plain text (passed to it in the
GA_Text attribute), the frbuttonclass gadget requires a DrawInfo structure
to properly calculate the dimensions of the text.


B / frbuttonclass / Attributes:GA_Text,GA_IntuiText,GA_LabelImage (IS)

These attributes tell the frbuttonclass object what kind of imagery to use
as its display element.  See their description in the gadgetclass entry
for more information.


B Boopsi Class Reference / groupgclass

Class:                  groupgclass
Superclass:             gadgetclass
Include File:           <intuition/gadgetclass.h>

This is a class of objects that maintains an internal list of gadgets.
Its purpose is to make it easier to layout a group of gadgets.  Any
gadgets that are a member of a groupgclass object are rendered relative to
the groupgclass object's GA_Left and GA_Top attributes.  As new gadgets
are added to the groupgclass object, the groupgclass object's dimensions
grow to enclose the new gadgets.  When the groupgclass object receives an
OM_DISPOSE message, it not only disposes of itself, it also disposes of
all the gadgets in its list.  Groupgclass does not support the gadget
relative flags (GA_RelWidth, GA_RelHeight, GA_RelBottom, and GA_RelRight).

New Methods:
------------
None.

Changed Methods:
----------------
 OM_SET          GM_HITTEST
 OM_ADDMEMBER    GM_RENDER
 OM_REMMEMBER    GM_GOACTIVE/GM_GOINACTIVE/GM_HANDLEINPUT
 OM_DISPOSE

Attributes:
-----------
 GA_Left, GA_Top (IS)


B / groupgclass / Changed Methods: OM_SET

This method passes most attributes to the superclass, but propagates
changes in position to its members appropriately. Also, GA_Width and
GA_Height are calculated from the position and dimension of the membership.


B / groupgclass / Changed Methods: OM_ADDMEMBER

This method adds a gadget to the group object's list.  The group object
will increase the size of its select box to include the new gadget's
select box.  The group object moves the new member to an absolute location
(by changing the new member's GA_Left and GA_Top attributes) relative to
the group object's upper-left corner.  Note that all members of the
groupgclass object will be deleted by OM_DISPOSE.


B / groupgclass / Changed Methods: OM_REMMEMBER

This method removes a gadget added to the group object's list with
OM_ADDMEMBER.  Note that all members of the groupgclass object will be
deleted by OM_DISPOSE.


B / groupgclass / Changed Methods: OM_DISPOSE

This method disposes of the groupgclass object and all its member gadgets.


B / groupgclass / Changed Methods: GM_HITTEST

This method works its way through the list of group members, sending each
a GM_HITTEST message, looking for the first member in the list that says
it has been hit.  This member gadget becomes the active member.


B / groupgclass / Changed Methods: GM_RENDER

This method sends a GM_HITTEST message to each of its members.


B / groupgclass / Changed: GM_GOACTIVE/GM_GOINACTIVE/GM_HANDLEINPUT

This method passes the message to the active member's dispatcher for
processing.   For GM_GOINACTIVE and GM_HANDLEINPUT, the coordinates passed
to the member's dispatcher in the message's gpi_Mouse.X and gpi_Mouse.Y
fields are translated so that they are relative to the gadget's upper-left
corner.


B / groupgclass / Attributes: GA_Left, GA_Top (IS)

These attributes correspond to the embedded Gadget.LeftEdge and
Gadget.TopEdge fields.  Setting these attributes in groupgclass object
causes it to change its position as well as the position of each of the
gadgets that have been added to the group gadget.


Amiga® RKM Libraries: C Sample Library Source Code

This appendix contains the source code to an Exec library called
sample.library.  It also includes some example code that uses the library.
The files include:

 makefile            A make file to build the library and examples.
 asmsupp.i           Assorted low level assembly support routines used by
                     the example library.
 sample_rev.i        The version file generated by bumprev.
 sample_protos.h     Prototypes for sample.library functions.
 sample_pragmas.h    Pragmas for sample.library functions.
 samplebase.i        Definition of sample.library base.
 samplebase.h        include file defining sample.library base.
 sample.library.asm  Example run-time library source code.
 sample_lvos.asm     The .fd file for the sample library.
 sample_stubs.asm    Assembler stubs for C interface to library functions.
 clibtest.c          C example that calls the sample.library functions.
 alibtest.asm        Assembly code example that calls the sample.library
                     functions.


Amiga® RKM Libraries: D Troubleshooting Guide

Many Amiga programming errors have classic symptoms. This guide will help
you to eliminate or avoid these problems in your software.

 Errors    General Debugging Techniques    A Final Word About Testing


D Troubleshooting Guide / Errors

 Audio--Corrupted Samples
 Character Input/Output Problems
 CLI Error Message Problems
 CLI Won't Close on RUN
 Crashes and Memory Corruption
 Crashes--After Exit
 Crashes--Only on 68000 and 68010
 Crashes--Only on 68040
 Crashes--Subtasks, Interrupts
 Crashes--Window Related
 Crashes--Workbench Only
 Device-related Problems
 Disk Icon Won't Go Away
 DOS-related Problems
 Fails only on 68020/30
 Fails only on 68000
 Fails only on Older ROMs or Older WB
 Fails only on Newer ROMs or Newer WB
 Fails only on Chip-RAM-Only Machines
 Fails only on machines with Fast RAM
 Fails only with Enhanced Chips
 Fireworks
 Graphics--Corrupted Images
 Hang--One Program Only
 Hang--Whole System
 Memory Loss
 Memory Loss--CLI Only
 Memory Loss--Ctrl-C Exit Only
 Memory Loss--During Execution
 Memory Loss--Workbench Only
 Menu Problems
 Out-of-Sync Response to Input
 Performance Loss in Other Processes
 Performance Loss--On A3000
 Trackdisk Data not Transferred
 Windows--Borders Flicker after Resize
 Windows--Visual Problems


D / Errors / Audio--Corrupted Samples

The bit data for audio samples must be in Chip RAM.  Check your compiler
manual for directives or flags which will place your audio sample data in
Chip RAM.  Or dynamically allocate Chip RAM and copy or load the audio
sample there.


D / Errors / Character Input/Output Problems

RAWKEY users must be aware that RAWKEY codes can be different letters or
symbols on national keyboards.  If you need to use RAWKEY, run the codes
through RawKeyConvert() (see the "Intuition Input and Output Methods"
chapter) to get proper translation to correct ASCII codes. Improper
display or processing of high-ASCII international characters can be caused
by incorrect tolower()/toupper(), or by sign extension of character values
when switched on or assigned into larger size variables. Use unsigned
variables such as UBYTE (not char) for strings and characters whenever
possible. Internationally correct string functions are provided in the 2.0
utility.library.


D / Errors / CLI Error Message Problems

Improper error messages are caused by calling exit(n) with an invalid or
missing return value n.  Assembler programmers using startup code should
jump to the startup code's _exit with a valid return value on the stack.
Programs without startup code should return with a valid value in D0.
Valid return values such as RETURN_OK, RETURN_WARN, RETURN_FAIL are
defined in <dos/dos.h> and <dos/dos.i>.  Values outside of these ranges
(-1 for instance) can cause invalid CLI error messages such as "not an
object module".  Useful hint--if your program is called from a script,
your valid return value can be conditionally branched on in the script
(i.e., call program, then perform actions based on IF WARN or IF NOT
WARN).  RETURN_FAIL will cause the script to stop if a normal FAILAT value
is being used in script.


D / Errors / CLI Won't Close on RUN

A CLI can't close if a program has a Lock() on the CLI input or output
stream ("*").  If your program is RUN >NIL: from a CLI, that CLI should be
able to close unless your code or your compiler's startup code explicitly
opens "*".


D / Errors / Crashes and Memory Corruption

Memory corruption, address errors, and illegal instruction errors are
generally caused by use of an uninitialized, incorrectly initialized, or
already freed/closed pointer or memory.  You may be using the pointer
directly, or it may be one that you placed (or forgot to place) in a
structure passed to system calls.  Or you may be overwriting one of your
arrays, or accidentally modifying or incrementing a pointer later used in
a free/close.  Be sure to test the return of all open/allocation type
functions before using the result, and only close/free things that you
successfully opened/allocated.  Use watchdog/torture utilities such as
Enforcer and MungWall in combination to catch use of uninitialized
pointers or freed memory, and other memory misuse problems.  Use the
debugging tool TNT to get additional debugging information instead of a
Software Error requester.  You may also be overflowing your stack--your
compiler's stack checking option may be able to catch this.  Cut stack
usage by dynamically allocating large structures, buffers, and arrays
which are currently defined inside your functions.

Corruption or crashes can also be caused by passing wrong or missing
arguments to a system call (for example SetAPen(3) or SetAPen(win,3),
instead of SetAPen(rp,3)).  C programmers should use function prototypes
to catch such errors.  If using short integers be sure to explicitly type
long constants as long (e.g., 42L). (For example, with short ints, 1 << 17
may become zero).  If corruption is occurring during exit, use printf()
(or KPrintF(), etc.) with Delay(n) to slow down your cleanup and broadcast
each step. A bad pointer that causes a system crash will often be reported
as an standard 680x0 processor exception $00000003 or 4, or less often a
number in the range of $00000006-B.  Or an Amiga-specific alert number may
result.  See <exec/alerts.h> for Amiga-specific alert numbers. Also see
"Crashes--After Exit" below.


D / Errors / Crashes--After Exit

If this only happens when you start your program from Workbench, then you
are probably UnLock()ing one of the WBStartup message wa_Locks, or
UnLock()ing the Lock() returned from an initial CurrentDir() call.  If you
CurrentDir(), save the lock returned initially, and CurrentDir() back to
it before you exit. Only UnLock() locks that you created.

If you are crashing from both Workbench and CLI, and you are only crashing
after exit, then you are probably either freeing/closing something twice,
or freeing/closing something your did not actually allocate/open, or you
may be leaving an outstanding device I/O request or other wakeup request.
You must abort and WaitIO() any outstanding I/O requests before you free
things and exit (see the Autodocs for your device, and for Exec AbortIO()
and WaitIO()).  Similar problems can be caused by deleting a subtask that
might be in a WaitTOF().  Only delete subtasks when you are sure they are
in a safe state such as Wait(0L).


D / Errors / Crashes--Only on 68000 and 68010

This can be caused by illegal instructions (80000000.00000004) such as new
68020/30/40 instructions or inline 68881/882 code.  But this is usually
caused by a word or longword access at an odd address.  This is legal on
the 68020 and above, but will generate an Address Error
(80000000.00000003) on a 68000 or 68010.  This can be caused by using
uninitialized pointers, using freed memory, or using system structures
improperly (for example, referencing into IntuiMessage->IAddress as a
struct Gadget *  on a non-Gadget message).


D / Errors / Crashes--Only on 68040

Because of the instruction pipelining of the 68040, it is very difficult
to recover from a bus error.  If your program has an "Enforcer hit" (i.e.,
an illegal reference to memory), the resulting 68040 processor bus error
will probably crash the machine.  Use Enforcer  (on an '030) to track down
your problems, then correct them.


D / Errors / Crashes--Subtasks, Interrupts

If part of your code runs on a different stack or the system stack, you
must turn off compiler stack-checking options.  If part of your code is
called directly by the system or by other tasks, you must use long
code/long data or use special compiler flags or options to assure that the
correct base registers are set up for your subtask or interrupt code.


D / Errors / Crashes--Window Related

Be careful not to CloseWindow() a window during a while(msg=GetMsg(...))
loop on that window's port (next GetMsg() would be on freed pointer).
Also, use ModifyIDCMP(NULL) with care, especially if using one port with
multiple windows.  Be sure to ClearMenuStrip() any menus before closing a
window, and do not free items such as dynamically allocated gadgets and
menus while they are attached to a window.  Do not reference an
IntuiMessage's IAddress field as a structure pointer of any kind before
determining it is a structure pointer (this depends on the Class of the
IntuiMessage).  If a crash or problem only occurs when opening a window
after extended use of your program, check to make sure that your program
is properly freeing up signals allocated indirectly by CreatePort(),
OpenWindow() or ModifyIDCMP().


D / Errors / Crashes--Workbench Only

If you are crashing near the first DOS call, either your stack is too
small or your startup code did not GetMsg() the WBStartup message from the
process message port.  If your program crashes during execution or during
your exit procedure only when started from Workbench, and your startup
opens no stdio window or NIL: file handles for WB programs, then make sure
you are not writing anything to stdout (printf(), etc.) when started from
WB (argc==0).  See also "Crashes--After Exit".


D / Errors / Device-related Problems

Device-related problems may caused by: improperly initialized port or I/O
request structures (use CreatePort() and CreateExtIO()); use of a
too-small I/O request (see the device's <.h> files and Autodocs for
information on the required type of I/O request); re-use of an I/O request
before it has returned from the device (use the debugging tool IO_Torture
to catch this); failure to abort and wait for an outstanding device
request before exiting; waiting on a signal/port/message allocated by a
different task.


D / Errors / Disk Icon Won't Go Away

This occurs when a program leaves a Lock() on one or more of a disk's
files or directories.  A memory loss of exactly 24 bytes is usually Lock()
which has not been UnLock()ed.


D / Errors / DOS-related Problems

In general, any dos.library function which fills in a structure for you
(for example, Examine()), requires that the structure be longword aligned.
In most cases, the only way to insure longword alignment in C is to
dynamically allocate the structure.  Unless documented otherwise,
dos.library functions may only be called from a process, not from a task.
Also note that a process's pr_MsgPort is intended for the exclusive use of
dos.library.  (The port may be used to receive a WBStartup message as long
as the message is GetMsg()'d from the port before DOS is used.


D / Errors / Fails only on 68020/30

The following programming practices can cause this problem: using the
upper bytes of addresses as flags; doing signed math on addresses;
self-modifying code; using the MOVE SR assembler instruction (use Exec
GetCC() instead); software delay loops; assumptions about the order in
which asynchronous tasks will finish.  The following differences in
68020/30 can cause problems: data and/or instruction caches must be
flushed if data or code is changed by DMA or other non-processor
modification; different exception stack frame; interrupt autovectors may
be moved by VBR; 68020/30 CLR instruction does a single write access
unlike the 68000 CLR instruction which does a separate read and write
access (this might affect a read-triggered register in I/O space--use MOVE
instead).


D / Errors / Fails only on 68000

The following programming practices can be the cause of this problem:
software delay loops; word or longword access of an odd address (illegal
on the 68000).  Note that this can occur under 2.0 if you reference
IntuiMessage->IAddress as a structure pointer without first determining
that the IntuiMessage's Class is defined as having a structure pointer in
its IAddress; use of the assembler CLR instruction on a hardware register
which is triggered by any access.  The 68000 CLR instruction performs two
accesses (read and write) while 68020/30 CLR does a single write access.
Use MOVE instead; assumptions about the order in which asynchronous tasks
will finish; use of compiler flags which have generated inline 68881/68882
math coprocessor instructions or 68020/30 specific code.


D / Errors / Fails only on Older ROMs or Older WB

This can be caused by asking for a library version higher than you need
(Do not use the #define LIBRARY_VERSION when compiling!).  Can also be
caused by calling functions or using structures which do not exist in the
older version of the operating system.  Ask for the lowest version which
provides the functions you need (usually 33), and exit gracefully and
informatively if an OpenLibrary() fails (returns NULL).  Or code
conditionally to only use new functions and structures if the available
Library's lib_Version supports them.


D / Errors / Fails only on Newer ROMs or Newer WB

This should not happen with proper programming.  Possible causes include:
running too close to your stack limits or the memory limits of a base
machine (newer versions of the operating system may use slightly more
stack in system calls, and usually use more free memory); using system
functions improperly; not testing function return values; improper
register or condition code handling in assembler code. Remember that
result, if any, is returned in D0, and condition codes and D1/A0/A1 are
undefined after a system call; using improperly initialized pointers;
trashing memory; assuming something (such as a flag) is B if it is not A;
failing to initialize formerly reserved structure fields to zero;
violating Amiga programming guidelines (for example: depending on or
poking private system structures, jumping into ROM, depending on
undocumented or unsupported behaviors); failure to read the function
Autodocs.

See Appendix E, "Release 2 Compatibility", for more information on 2.0
compatibility problem areas.


D / Errors / Fails only on Chip-RAM-Only Machines

Caused by specifically asking for or requiring MEMF_FAST memory.  If you
don't need Chip RAM, ask for memory type 0L, or MEMF_CLEAR, or
MEMF_PUBLIC|MEMF_CLEAR as applicable.  If there is Fast memory available,
you will be given Fast memory.  If not, you will get Chip RAM.  May also
be caused by trackdisk-level loading of code or data over important system
memory or structures which might reside in low Chip memory on a
Chip-RAM-Only machine.


D / Errors / Fails only on machines with Fast RAM

Data and buffers which will be accessed directly by the custom chips must
be in Chip RAM.  This includes bitplanes (use OpenScreen() or
AllocRaster()), audio samples, trackdisk buffers, and the graphic image
data for sprites, pointers, bobs, images, gadgets, etc.  Use compiler or
linker flags to force Chip RAM loading of any initialized data needing to
be in Chip RAM, or dynamically allocate Chip RAM and copy any
initialization data there.


D / Errors / Fails only with Enhanced Chips

Usually caused by writing or reading addresses past the end of older
custom chips, or writing something other than 0 (zero) to bits which are
undefined in older chip registers, or failing to mask out undefined bits
when interpreting the value read from a chip register.  Note that system
copper lists are different under 2.0 when ECS chips are present. See
"Fails only on Chip-RAM-Only Machines".


D / Errors / Fireworks

A dazzling pyrotechnic video display is caused by trashing or freeing a
copper list which is in use, or trashing the pointers to the copper list.
If you aren't messing with copper lists, see above section called
"Crashes and Memory Corruption".


D / Errors / Graphics--Corrupted Images

The bit data for graphic images such as sprites, pointers, bobs, and
gadgets must be in Chip RAM.  Check your compiler manual for directives or
flags which will place your graphic image data in Chip RAM.  Or
dynamically allocate Chip RAM and copy them there.


D / Errors / Hang--One Program Only

Program hangs are generally caused by Wait()ing on the wrong signal bits,
on the wrong port, on the wrong message, or on some other event that will
never occur.  This can occur if the event you are waiting on is not
coming, or if one task tries to Wait(), WaitPort(), or WaitIO() on a
signal, port, or window that was created by a different task.  Both
WaitIO() and WaitPort() can call Wait(), and you cannot Wait() on another
task's signals.  Hangs can also be caused by verify deadlocks. Be sure to
turn off all Intuition verify messages (such as MENUVERIFY) before calling
AutoRequest() or doing disk access.


D / Errors / Hang--Whole System

This is generally caused by a Disable() without a corresponding Enable().
It can also be caused by memory corruption, especially corruption of low
memory.  See "Crashes and Memory Corruption".


D / Errors / Memory Loss

First determine that your program is actually causing a memory loss.  It
is important to boot with a standard Workbench because a number of third
party items such as some background utilities, shells, and network
handlers dynamically allocate and free pieces of memory.  Open a Shell for
memory checking, and a Shell or Workbench drawer for starting your
program.  Arrange windows so that all are accessible, and so that no
window rearrangement will be needed to run your program.

In the Shell, type Avail FLUSH<RET> several times (2.0 option).  This will
flush all non-open disk-loaded fonts, devices, etc., from memory. Note the
amount of free memory.  Now without rearranging any windows, start your
program and use all of your program features.  Exit your program, wait a
few seconds, then type Avail FLUSH<RET> several times.  Note the amount of
free memory.  If this matches the first value you noted, your program is
fine, and is not causing a memory loss.

If memory was actually lost, and your program can be run from CLI or
Workbench, then try the above procedure with both methods of starting your
program.  Note that under 2.0, there will be a slight permanent (until
reboot) memory usage of about 672 bytes when the audio.device or
narrator.device is first opened.  See "Memory Loss--CLI Only" and
"Memory Loss--WorkBench Only" if appropriate.  If you lose memory from
both WB and CLI, then check all of the open/alloc/get/create/lock type
calls in your code, and make sure that there is a matching
close/free/delete/unlock type call for each of them (note--there are a few
system calls that have or require no corresponding free--check the
Autodocs).  Generally, the close/free/delete/unlock calls should be in
opposite order of the allocations.

If you are losing a fixed small amount of memory, look for a structure of
that size in the Structure Offsets listing in the Amiga ROM Kernel
Reference Manual: Includes and Autodocs.  For example, a loss of exactly
24 bytes is probably a Lock() which has not been UnLock()ed.  If you are
using ScrollRaster(), be aware that ScrollRaster() left or right in a
Superbitmap window with no TmpRas will lose memory under 1.3
(workaround--attach a TmpRas).  If you lose much more memory when started
from Workbench, make sure your program is not using Exit(n).  This would
bypass startup code cleanups and prevent a Workbench-loaded program from
being unloaded.  Use exit(n) instead.


D / Errors / Memory Loss--CLI Only

Make sure you are testing in a standard environment.  Some third-party
shells dynamically allocate history buffers, or cause other memory
fluctuations.  Also, if your program executes different code when started
from CLI, check that code and its cleanup.  And check your startup.asm if
you wrote your own.


D / Errors / Memory Loss--Ctrl-C Exit Only

You have Amiga-specific resources opened or allocated and you have not
disabled your compiler's automatic Ctrl-C handling (causing all of your
program cleanups to be skipped).  Disable the compiler's Ctrl-C handling
and handle Ctrl-C (SIGBREAKF_CTRL_C) yourself.


D / Errors / Memory Loss--During Execution

A continuing memory loss during execution can be caused by failure to keep
up with voluminous IDCMP messages such as MOUSEMOVE messages. Intuition
cannot re-use IDCMP message blocks until you ReplyMsg() them.  If your
window's allotted message blocks are all in use, new sets will be
allocated and not freed till the window is closed.  Continuing memory
losses can also be caused by a program loop containing an allocation-type
call without a corresponding free.


D / Errors / Memory Loss--Workbench Only

Commonly, this is caused by a failure of your code to unload after you
exit.  Make sure that your code is being linked with a standard correct
startup module, and do not use the Exit(n) function to exit your program.
This function will bypass your startup code's cleanup, including its
ReplyMsg() of the WBStartup message (which would signal Workbench to
unload your program from memory).  You should exit via either exit(n)
where n is a valid DOS error code such as RETURN_OK (<dos/dos.h>), or via
final "}" or return.  Assembler programmers using startup code can JMP to
_exit with a long return value on stack, or use the RTS instruction.


D / Errors / Menu Problems

A flickering menu is caused by leaving a pixel or more space between menu
subitems when designing your menu.  Crashing after browsing a menu
(looking at menu without selecting any items) is caused by not properly
handling MENUNULL select messages.  Multiple selection not working is
caused by not handling NextSelect properly.  See the "Intuition Menus"
chapter.


D / Errors / Out-of-Sync Response to Input

Caused by failing to handle all received signals or all possible messages
after a Wait() or WaitPort() call.  More than one event or message may
have caused your program to awakened.  Check the signals returned by
Wait() and act on every one that is set.  At ports which may have more
than one message (for instance, a window's IDCMP port), you must handle
the messages in a while(msg=GetMsg(...)) loop.


D / Errors / Performance Loss in Other Processes

This is often caused by a one program doing one or more of the following:
busy waiting or polling; running at a higher priority; doing lengthy
Forbid()s, Disable()s, or interrupts.


D / Errors / Performance Loss--On A3000

If your program has "Enforcer hits" (i.e., illegal references to memory
caused by improperly initialized pointers), this will cause Bus Errors.
The A3000 bus error handler contains a built-in delay to let the bus
settle.  If you have many enforcer hits, this could slow your program down
substantially.


D / Errors / Trackdisk Data not Transferred

Make sure your trackdisk buffers are in Chip RAM under 1.3 and lower
versions of the operating system.


D / Errors / Windows--Borders Flicker after Resize

Set the NOCAREREFESH flag.  Even SMART_REFRESH windows may generate
refresh events if there is a sizing gadget.  If you don't have specific
code to handle this, you must set the NOCAREREFRESH flag.  If you do have
refresh code, be sure to use the Begin/EndRefresh() calls.  Failure to
do one or the other will leave Intuition in an intermediate state, and
slow down operation for all windows on the screen.


D / Errors / Windows--Visual Problems

Many visual problems in windows can be caused by improper font
specification or improper setting of gadget flags.  See the Appendix E on
"Release 2 Compatibility" for detailed information on common problems.


D Troubleshooting Guide / General Debugging Techniques

Narrow the search
    Use methodical testing procedures, and debugging messages if
    necessary, to locate the problem area.  Low level code can be
    debugged using KPrintF() serial (or dprintf() parallel) messages.
    Check the initial values, allocation, use, and freeing of all
    pointers and structures used in the problem area.  Check that all of
    your system and internal function calls pass correct initialized
    arguments, and that all possible error returns are checked for and
    handled.

Isolate the problem
    If errors cannot be found, simplify your code to the smallest
    possible example that still functions.  Often you will find that this
    smallest example will not have the problem.  If so, add back the
    other features of your code until the problem reappears, then debug
    that section.

Use debugging tools
    A variety of debugging tools are available to help locate faulty
    code. Some of these are source level and other debuggers, crash
    interceptors, vital watchdog and memory invalidation tools like
    Enforcer and MungWall.


D Troubleshooting Guide / A Final Word About Testing

Test your program with memory watchdog and invalidation tools on a wide
variety of systems and configurations.  Programs with coding errors may
appear to work properly on one or more configurations, but may fail or
cause fatal problems on another.  Make sure that your code is tested on
both a 68000 and a 68020/30, on machines with and without Fast RAM, and on
machines with and without enhanced chips.  Test all of your program
functions on every machine.

Test all error and abort code.  A program with missing error checks or
unsafe cleanup might work fine when all of the items it opens or allocates
are available, but may fail fatally when an error or problem is
encountered.  Try your code with missing files, filenames with spaces,
incorrect filenames, cancelled requesters, Ctrl-C, missing libraries or
devices, low memory, missing hardware, etc.

Test all of your text input functions with high-ASCII characters (such as
the character produced by pressing Alt-F then "A").  Note that RAWKEY
codes can be different keyboard characters on national keyboards (higher
levels of keyboard input are automatically translated to the proper
characters).  If your program will be distributed internationally, support
and take advantage of the additional screen lines available on a PAL
system.  Enhanced Agnus chip machines may be switched to be PAL or NTSC
via motherboard jumper J102 in A2000s and jumper J200 in A3000s.  Note
that a base PAL machine will have less memory free due to the larger
display size.

Write good code.  Test it.  Then make it great.


Amiga® RKM Libraries: E Release 2 Compatibility

If you are developing new software or updating older software, you need to
avoid compatibility traps.  This comprehensive list of Release 2
compatibility problem areas can help you avoid and diagnose compatibility
problems  In addition, refer to the "General Amiga Development Guidelines"
listed in Chapter 1.

 General Compatibility Problem Areas
 Release 2 Changes That Can Affect Compatibility
 Additional Information


E Release 2 Compatibility / General Compatibility Problem Areas

The following improper Amiga programming practices are likely to fail on
new ROMs or hardware.

  * Requiring all free RAM.

  * Overwriting memory allocations.  With 32-bit addresses, a 1-byte
    overwrite of a string array can wipe out the high byte of a pointer
    or stack return address.  This bug could go unnoticed on a 24-bit
    address machine (e.g., A500) but crash the system or cause other
    problems on an A3000.

  * Improper flags or garbage in system structures.  A bit that means
    nothing under one OS may drastically change the behavior of a
    function in a newer version of the OS.  Clear structures before
    using, and use correct flags.

  * Misuse of function return values.  Use function prototypes and read
    the Autodocs for the functions you are using.  Some system functions
    return just success or failure, or nothing at all (void).  In such
    cases, the value which the function happens to return must not be
    used except as it is documented.

  * Depending on unsupported side effects or undocumented behavior.  Be
    sure to read the Autodocs, include file comments and other
    documentation.

  * Assuming current choices, configurations or initial values.  If the
    current possibilities are A, B, or C, do not assume C if it isn't A
    or B.  Check specifically for the choices currently implemented, and
    provide default behavior for unexpected values.

Amiga debugging tools such as Enforcer, Mungwall and Scratch can find many
program bugs that may affect compatibility. A program that is
Enforcer/Mungwall/Scratch clean stands a much better chance of working
well under current and future versions of the OS.


E Compatibility / Release 2 Changes That Can Affect Compatibility

There are several areas where Relase 2 OS changes and enhancements can
cause compatibility problems for some software.

 Exec               Serial Device             Preferences
 Expansion          Timer Device              Workbench
 Strap              Trackdisk Device          Layers
 DOS                CIA Timers               Graphics
 Audio Device       Other Hardware Issues    Fonts
 Gameport Device    Intuition                CLI/Shell


E / Release 2 Changes That Can Affect Compatibility / Exec

  * Do not jump to location $FC0002 -- the start of the ROM under
    1.3 -- as part of performing a system RESET.  The 2.04 Kickstart
    ROM has a temporary compatibility hack called "Kickety-Split" which
    is a redirecting jump at $FC0002.  This hack does not appear on the
    A3000 ROM and due to space considerations will not appear on future
    machines.

  * Everything has moved.

  * The Supervisor stack is not in the same place as it was under 1.3.
    This has caused problems for some games that completely take over the
    Amiga.  If your program goes into Supervisor mode, you must either
    respect allocated memory or provide your own Supervisor stack when
    taking over the machine.

  * ExecBase is moved to expansion memory if possible.  Before, ExecBase
    would only end up in one of two fixed locations.  Now, ColdCapture
    may be called after expansion memory has been configured.

  * Exception/Interrupt vectors may move.  This means the 68010 and above
    Vector Base Register (VBR) may contain a non-zero value.  Poking
    assumed low memory vector addresses may have no effect.  You must
    read the VBR on 68010 and above to find the base.

  * No longer tolerant of wild Forbid() counts.  Under 1.3, sometimes
    this bug could go unnoticed.  Make sure that all Forbid()s are
    matched with one and only one Permit() (and vice versa).

  * When an Exec device gets an IORequest, it must validate io_Command.
    If the io_Command is 0 or out of range, the device must return
    IOERR_NOCMD and take no other action.  The filesystem now sends new
    commands and expects older devices to properly ignore them.

  * A fix to task-switching in Release 2 allows a busy task to properly
    regain the processor after an interrupt until either its quantum (4
    vertical blanks) is up or a higher priority task preempts it.  This
    can dramatically change the behavior of multitask programs where one
    task busyloops while another same-priority task Wait()s.  See
    "Task Switching" in the "Additional Information" section below.


E / Release 2 Changes That Can Affect Compatibility / Expansion

  * ExpansionBase is private - use FindConfigDev().

  * Memory from contiguous cards of the same memory type is automatically
    merged into one memory pool.


E / Release 2 Changes That Can Affect Compatibility / Strap

  * Romboot.library is gone.

  * Audio.device cannot be OpenDevice()ed by a boot block program.  See
    "Audio Device" below.

  * Boot from other floppies (+5,-10,-20,-30) is possible.

  * Undocumented system stack and register usage at Diag and Boot time
    have changed.


E / Release 2 Changes That Can Affect Compatibility / DOS

  * DOS is now written in C and assembler, not BCPL.  The BCPL compiler
    artifact which caused D0 function results to also be in D1 is gone.
    System patches in Release 2 that return some DOS function results in
    both D0 and D1 are not guaranteed to remain in the next release. Fix
    your programs!  Use Scratch to find these problems in your code.

  * DOS now has a real library base with normal LVO vectors.

  * Stack usage has all changed (variables, direction).

  * New packet and lock types.  Make sure you are not passing stack
    garbage for the second argument to Lock().

  * Process structure is bigger.  "Rolling your own" Process structure
    from a Task fails.  Use dos.library System() or CreateNewProc().

  * Unless documented otherwise, you must be a process to call DOS
    functions. DOS function dependence on special process structures can
    change with OS revisions.


E / Release 2 Changes That Can Affect Compatibility / Audio Device

  * Now not initialized until used.  This means low memory open failure
    is possible.  Check your return values from OpenDevice().  This also
    means audio.device cannot be opened during 2.0 Strap unless
    InitResident()ed first.  If OpenDevice() of audio.device fails during
    strap, you must FindResident()/InitResident() audio.device, and then
    try OpenDevice() again.  There will be a small memory loss (until
    reboot) generated by the first opener of audio.device or
    narrator.device (memory used in building of audio.device's base).


E / Release 2 Changes That Can Affect Compatibility / Gameport Device

  * Initial state of hardware lines may differ.


E / Release 2 Changes That Can Affect Compatibility / Serial Device

  * Clears io_Device on CloseDevice() (since 1.3.2)


E / Release 2 Changes That Can Affect Compatibility / Timer Device

  * The most common mistake programmers make with timer.device is to send
    off a particular timerequest before the previous use of that
    timerequest has completed.  Use IO_Torture to catch this.

  * IO_QUICK requests may be deferred and be replied as documented.

  * VBLANK timer requests, as documented, now wait at least as long as
    the full number of VBlanks you asked for.  Previously, a partial
    vertical blank could count towards your requested number.  The new
    behavior is more correct and matches the docs, but it can cause
    VBlank requests to now take up to 1 VBlank longer under 2.0 as
    compared to 1.3. For example, a 1/10 second request, may take 6-7
    Vblanks instead of 5-6 VBlanks, or about 15% longer.


E / Release 2 Changes That Can Affect Compatibility / Trackdisk Device

  * Private trackdisk structures have changed.  See trackdisk.doc for a
    compatible REMCHANGEINT.

  * Buffer is freeable, so low memory open failure is possible.

  * Do not disable interrupts (any of them), then expect trackdisk to
    function while they are disabled.


E / Release 2 Changes That Can Affect Compatibility / CIA Timers

  * System use of CIA timers has changed.  Don't assume how they're used.

  * Don't depend on initial values of CIA registers.

  * Don't mess with CIABase. Use cia.resource.

  * If your code requires hardware level CIA timers, allocate the timers
    using cia.resource AddICRVector()!  This is very important. Operating
    system usage of the CIA timers has changed.  The new 2.0 timer.device
    ("Jumpy the Magic Timer Device") will try to jump to different CIAs
    so programs that properly allocate timers will have a better chance
    of getting what they want.  If possible, be flexible and design your
    code to work with whatever timer you can successfully allocate.

  * OS usage of INT6 is increasing.  Do not totally take over INT6, and
    do not terminate the server chain if an interrupt is not for you.


E /Release 2 Changes That Affect Compatibility / Other Hardware Issues

  * Battery-backed clock is different on A3000.  Use battclock.resource
    to access the real-time clock if battclock.resource can be opened.

  * A 68030 hardware characteristic causes longword-aligned longword
    writes to allocate a valid entry in the data cache,  even if the
    hardware area shouldn't be cached.  This can cause problems for I/O
    registers and shared memory devices.  To solve this: 1) don't do that
    2) flush the cache or 3) use Enforcer Quiet.  See the Motorola 68030
    manual under the description of the Write Allocate bit (which must be
    set for the Amiga to run with the Data Cache).


E / Release 2 Changes That Can Affect Compatibility / Intuition

  * Private IntuitionBase variables have moved/changed.  Reading them is
    illegal.  Writing them is both illegal and dangerous.

  * Poking IntuitionBase MaxMouse variables is now a no-op, but stop
    poking when Intuition version is >35.

  * If you are opening on the Workbench screen, be prepared to handle
    larger screens, new modes, new fonts, and overscan.  Also see
    "Fonts" compatibility information.

  * Screen TopEdge and LeftEdge may be negative.

  * Left-Amiga-Select is used for dragging large screens. Do not use
    left-Amiga-key combinations for application command keys.  The
    left-Amiga key is reserved for system use.

  * For compatibility reasons, GetScreenData() lies if the Workbench
    screen is a mode only available after 1.3.  It will try to return the
    most sensible mode that old OpenScreen() can open.  This was
    necessary to prevent problems in applications that cloned the
    Workbench screen. To properly handle new modes, see LockPubScreen(),
    GetVPModeID(), and the SA_DisplayID tag for OpenScreenTags().

  * Using combined RAWKEY and VANILLAKEY now gives VANILLAKEY messages
    for regular keys, and RAWKEY messages for special keys (fkeys, help,
    etc.)

  * Moving a SIMPLE_REFRESH window does not necessarily cause a
    REFRESHWINDOW event because layers now preserves all the bits it can.

  * Sizing a SIMPLE_REFRESH window will not clear it.

  * MENUVERIFY/REQVERIFY/SIZEVERIFY can time out if you take too long to
    ReplyMsg().

  * Menu-key equivalents are ignored while string gadgets are active.

  * You can't type control characters into string gadgets by default.
    Use Ctrl-Amiga-char to type them in or use IControl Prefs to change
    the default behavior.

  * Width and Height parameters of AutoRequest() are ignored.

  * New default colors, new gadget images.

  * JAM1 rendering/text in border may be invisible gadgets over default
    colors.

  * The cursor for string gadgets can no longer reside outside the
    cleared container area.  If your gadget is 32 pixels wide, with
    MaxChars of 4, all 32 pixels will be cleared, instead of just 24, as
    was true in 1.3.

  * Applications and requesters that fail to specify desired fonts will
    get the fonts the user sets up in Font Preferences in Release 2.
    These could be much larger, or proportional in some cases.  Screen
    and window titlebars (and their gadgets) will be taller when
    accommodating a larger font.  Applications which open on the
    Workbench screen must adapt to variable size titlebars.  Any
    application which accepts system defaults for its screen, window,
    menu, Text or IntuiText fonts must adapt to different fonts and
    titlebar sizes.  String gadgets whose height is too small for a font
    will revert to a smaller ROM font.  There are now 2 different
    user-specifiable default system fonts which affect different
    Intuition features.  This can lead to mismatches in mixed gadgets and
    text.  See the "Intuition Screens" chapter.

  * Don't modify gadgets directly without first removing them from the
    gadget list, unless you are using a system function designed for that
    purpose, such as NewModifyProp() or SetGadgetAttrs().

  * Don't rely on NewModifyProp() to fully refresh your prop gadget after
    you've changed values in the structure.  NewModifyProp() will only
    correctly refresh changes which were passed to it as parameters.  Use
    Remove/Add/RefreshGList() for other kinds of changes.

  * Custom screens must be of type CUSTOMSCREEN or PUBLICSCREEN.  Other
    types are illegal.  One application opens its screen with
    NewScreen.Type = 0 (instead of CUSTOMSCREEN, 0x0F).  Then, when it
    opens its windows, it specifies NewWindow.Type of 0 and
    NewWindow.Screen of NULL, instead of Type = CUSTOMSCREEN and
    Screen = (their screen). That happened to work before, but no longer.

  * Referencing IntuiMessage->IAddress as a Gadget pointer on non-Gadget
    IDCMP messages, or as a Window pointer (rather than looking at the
    proper field IntuiMessage->IDCMPWindow) may now cause Enforcer hits
    or crashes.  The IAddress field always used to contain a pointer of
    some type even for IDCMP events for which no IAddress value is
    documented.  Now, for some IDCMP events, IAddress may contain a
    non-address, possibly an odd value that would crash a 68000 based
    system).

  * Using Intuition flags in the wrong structure fields (for example,
    using ACTIVEWINDOW instead of ACTIVATE).  To alleviate this problem,
    2.0 has introduced new synonyms that are less confusing than the old
    ones.  For example, IDCMP_ACTIVEWINDOW and WFLG_ACTIVATE.  This
    particular example of confusion (there are several) was the nastiest,
    since IDCMP_ACTIVEWINDOW, when stuffed into NewWindow.Flags,
    corresponds numerically to WFLG_NW_EXTENDED, which informs Intuition
    that the NewWindow structure is immediately followed by a TagItem,
    list which isn't there!  Intuition does some validation on the
    tag-list pointer, in order to partially compensate.  To make your
    compiler use the new synonyms only, add this line to your code before
    Intuition include files: #define INTUI_V36_NAMES_ONLY.

  * Do not place spaces into the StringInfo->Buffer of a GACT_LONGINT
    string gadget. Under 1.3, this worked, but the 2.0 validation routine
    that checks for illegal keystrokes looks at the contents for illegal
    (i.e., non-numeric) characters, and if any are found assumes that the
    user typed an illegal keystroke.  The user's only options may be
    shift-delete or Amiga-X. Use the correct justification instead.

  * If you specify NULL for a font in an IntuiText, don't assume you'll
    get Topaz 8.  Either explicitly supply the font you you need or be
    prepared to size accordingly.  Otherwise, your rendering will be
    wrong, and the user will have to reset his Preferences just to make
    your software work right.

  * Window borders are now drawn in the screen's DetailPen and BlockPen
    rather than the Window's pens.  For best appearance, you should pass
    an SA_Pens array to OpenScreen(). This can be done in a backwards
    compatible manner with the ExtNewScreen structure and the NS_EXTENDED
    flag.

  * The system now renders into the full width of window borders,
    although the widths themselves are unchanged.  Window borders are
    filled upon activation and inactivation.

  * Window border rendering has changed significantly for 2.0.  Note that
    the border dimensions are unchanged from 1.x (Look at
    Window->BorderLeft/Top/Right/Bottom if you don't believe us!).  If
    your gadget intersects the border area, although it may have looked
    OK under 1.3, a visual conflict may occur under 2.0.  If Intuition
    notices a gadget which is substantially in the border but not
    declared as such, it treats it as though it were (this is called
    "bordersniffing").  Never rely on Intuition to sniff these out for
    you; always declare them explicitly (see the Gadget Activation flags
    GACT_RIGHTBORDER, etc.).  See "Intuition Gadgets and Window Borders"
    in the "Additional Information" section below.


E / Release 2 Changes That Can Affect Compatibility / Preferences

  * Some old struct Preferences fields are now ignored by SetPrefs() (for
    example FontHeight). SetPrefs() also stops listening to the pointer
    fields as soon as a new-style pointer is passed to Intuition
    (new-style pointers can be taller or deeper).

  * Preferences ViewX/YOffset only applies to the default mode. You
    cannot use these fields to move the position of all modes.

  * The Preferences LaceWB bit is not necessarily correct when Workbench
    is in a new display mode (akin to GetScreenData()).


E / Release 2 Changes That Can Affect Compatibility / Workbench

  * The Workbench GUI now has new screen sizes, screen top/left offsets,
    depths, modes, and fonts.

  * Default Tool now searches paths.

  * New Look (boxed) icons take more space.

  * Do not use icons which have more 1bits set in PlanePick than planes
    in the ImageData (one IFF-to-Icon utility does this).  Such icons
    will appear trashed on deeper Workbenches.

  * New Look colors have black and white swapped (as compared to 1.3).

  * The Workbench screen may not be open at startup-sequence time until
    some output occurs to the initial Shell window.  This can break
    startup-sequence-started games that think they can steal WB's screen
    bitplanes.  Do not steal the Workbench screen's bitplanes.  (For
    compatibility, booting off pre-2.0 disks forces the initial screen
    open. This is not guaranteed to remain in the system.)  Use startup
    code that can detach when RUN (such as cback.o) and use
    CloseWorkbench() to regain the screen's memory.  In addition, see
    "Workbench and Startup" in the "Additional Information" section
    below.


E / Release 2 Changes That Can Affect Compatibility / Layers

  * Use NewLayerInfo() to create, not FattenLayerInfo(), ThinLayerInfo(),
    InitLayers().

  * Simple-refresh preserves all of the pixels it can.  Sizing a
    SIMPLE_REFRESH window no longer clears the whole window.

  * Speed of layer operations is different.  Don't depend on layer
    operations to finish before or after other asynchronous actions.


E / Release 2 Changes That Can Affect Compatibility / Graphics

  * Do not rely on the order of Copper list instructions.  The Release 2
    MrgCop() function builds different Copper lists to that of 1.3, by
    including new registers in the list (e.g., MOVE xxxx,DIWHIGH).  This
    changes the positions of  the  other  instructions.  We  know  of one
    game that 'assumes' the BPLxPTRs  would be at a certain offset in the
    Copper list, and that is now broken on machines running 2.0 with the
    new Denise chip.

  * Graphics and layers functions which use the blitter generally return
    after starting the final blit.  If you are mixing graphics rendering
    calls and processor access of the same memory, you must WaitBlit()
    before touching (or deallocating) the source or destination memory
    with the processor.  For example, the Text() function is faster in
    Release 2, causing some programs to trash partial lines of text.

  * ColorMap structure is bigger.  Programs must use GetColorMap() to
    create one.

  * Blitter rtns decide ascend/descend on 1st plane only.

  * Changing the display mode of an existing screen or viewport while
    open is still not a supported operation.

  * GfxBase DisplayFlags and row/cols may not match Workbench screen.

  * Do not hardcode modulo values - use BitMap->BytesPerRow.

  * If the graphics Autodocs say that you need a TmpRas of a certain size
    for some functions, then you must make that the minimum size.  In
    some cases, before 2.0, you may have gotten away with using a smaller
    TmpRas with some functions (for example Flood()).  To be more robust,
    graphics now checks the TmpRas size and will fail the function call
    if the TmpRas is too small.

  * ECS chips under 2.0 generate displays differently. The display window
    registers now control DMA.

  * LoadRGB4() used to poke colors into the active copperlist with no
    protection against deallocation of that copperlist while it was being
    poked.  Under 2.0, semaphore protection of the copperlist was added
    to LoadRGB4() which makes it totally incorrect and extremely
    dangerous to call LoadRGB4() during an interrupt.  The general
    symptom of this problem is that a system deadlock can be caused by
    dragging one screen up and down while another is cycling.  Color
    cycling should be performed from within a task, not an interrupt.  In
    general, the only functions which may be safely called from within an
    interrupt are the small list of Exec functions documented in the
    "Exec Interrupts" chapter.


E / Release 2 Changes That Can Affect Compatibility / Fonts

  * Some font format changes (old format supported).

  * Private format of .font files has changed (use FixFonts to create).

  * Default fonts may be larger, proportional.

  * Topaz is now sans-serif.

  * Any size font will be created via scaling as long as TextAttr.Flags
    FPF_DESIGNED bit is not set.  If you were asking for an extreme size,
    like size 1 to get smallest available, or 999 to get largest
    available, you will get a big (or very very small) surprise now.

  * Do not use -1 for TextAttr.Flags or Styles, nor as the flags for
    AvailFonts (one high bit now causes AvailFonts to return different
    structures).  Only set what you know you want.  A kludge has been
    added to the OS to protect applications which currently pass -1 for
    AvailFonts flags.


E / Release 2 Changes That Can Affect Compatibility / CLI/Shell

  * Many more commands are now built-in (no longer in C:).  This can
    break installation scripts that copy C:commandname, and programs that
    try to Lock() or Open() C:commandname to check for the command's
    existence.

  * The limit of 20 CLI processes is gone and the DOSBase CLI table has
    changed to accommodate this.  Under V36 and higher, you should use
    new 2.0 functions rather than accessing the CLI table directly.

  * Shell windows now have close gadgets.  The EOF character is passed
    for the close gadget of a Shell.  This is -1L with CON: getchar(),
    and the Close Gadget raw event ESC seq with RAW:.

  * Shells now use the simple-refresh character-mapped console.

  * By default, CON: now opens SIMPLE_REFRESH windows using the V36/V37
    console character mapped mode.  Because of some differences between
    character mapped consoles, and SMART_REFRESH non-mapped consoles,
    this may cause incompatibilities with some applications.  For
    example, the Amiga private sequences to set left/top offset, and set
    line/page length behave differently in character mapped console
    windows.  The only known work-around is to recompile asking for a
    CON: (or RAW:) window using the SMART flag.

  * Simple refresh/character mapped console windows now support
    highlighting and copying text with the mouse.  This feature, as well
    as pasting text should be transparent to programs which use CON: for
    console input, and output.  Pasted text will appear in your input
    stream as if the user had typed it.

  * While CONCLIP (see s:startup-sequence) is running, programs may
    receive "<CSI>0 v" in their input stream indicating the user wants to
    paste text from the clipboard.  This shouldn't cause any problems for
    programs which parse correctly (however we know that it does; the
    most common problems are outputting the sequence, or confusing it
    with another sequence like that for FKEY 1 which is "<CSI>0~").

  * The console.device now renders a ghosted cursor in inactive console
    windows (both SMART_REFRESH, and SIMPLE_REFRESH with character maps).
    Therefore, rendering over the console's cursor with graphics.library
    calls can trash the cursor; if you must do this, first turn off the
    cursor.

  * Some degree of unofficial support has been put in for programs which
    use SMART_REFRESH console windows, and use graphics.library calls
    mixed with console.device sequences to scroll, draw text, clear, etc.
    This is not supported in SIMPLE_REFRESH windows with character maps,
    and is strongly discouraged in all cases.

  * Closing an Intuition window before closing the attached
    console.device will now crash or hang the machine.

  * Under 1.2 and 1.3, vacated portions of a console window (e.g., areas
    vacated because of a clear, or a scroll) were filled in with the
    character cell color.  As of V36 this is no longer true, vacated
    areas are filled in with the global background color which can be set
    using the SGR sequence "<ESC>[>##m" where ## is a value between 0-7.
    In order to set the background color under Release 2, send the SGR to
    set background color, and a form feed to clear the screen.

  * Note that SIMPLE_REFRESH character mapped consoles are immediately
    redrawn with the global background color when changed--this is not
    possible with SMART_REFRESH windows.


E Release 2 Compatibility / Additional Information

 Task Switching
 Intuition Gadgets and Window Borders
 Workbench and Startup


E / Additional Information / Task Switching

The 1.3 Kickstart contained two task switching bugs.  After an interrupt,
a task could lose the CPU to another equal priority task, even if the
first task's time was not up.  The second bug allowed a task whose time
was up to hold on to the CPU either forever, or until a higher priority
task was scheduled.  Two busy-waiting tasks at high priority would never
share the CPU.  Because the input.device runs at priority 20, usually the
effect of these bugs was masked out for low priority tasks.  The
ExecBase->Quantum field had little effect because of the bugs.

For 2.0, a task runs until either its Quantum is up, or a higher priority
task preempts it.  When the Quantum time is up, the task will now lose the
CPU.  The Quantum was set to 16/60 second for 1.3, and 4/60 second for 2.0.

In general, the 2.0 change makes the system more efficient by eliminating
unnecessary task switches on interrupt-busy systems (for example, during
serial input).  However, the change has caused problems for some programs
that use two tasks of equal priority, one busy-waiting and one Wait()ing
on events such as serial input.  Previously, each incoming serial
character interrupt would cause task context switch allowing the
event-handling task to run immediately.  Under 2.0 the two tasks share the
processor fairly.


E / Additional Information / Intuition Gadgets and Window Borders

If 2.0 Intuition finds a gadget whose hit area (Gadget LeftEdge/TopEdge/
Width/Height) is substantially inside the border, it will be treated as
though it was declared in the border.  This is called "bordersniffing".
Gadgets declared as being in the border or detected by Intuition as being
in the border are refreshed each time after the border is refreshed, and
thus aren't clobbered.

Noteworthy special cases:

 1) A gadget that has several pixels not in the border is not
    bordersniffed. An example would be an 18-pixel high gadget in the
    bottom border of a SIZEBBOTTOM window.  About half the gadget will be
    clobbered by the border rendering.

 2) A gadget that is not substantially in the border but has imagery that
    extends into the border cannot be sniffed out by Intuition.

 3) A gadget that is substantially in the border but has imagery that
    extends into the main part of the window will be sniffed out as a
    border gadget, and this could change the refreshing results.  A
    common trick to put imagery in a window is to put a 1x1 or 0x0 dummy
    gadget at window location (0,0) and attach the window imagery to it.
    To support this, Intuition will never bordersniff gadgets of size 1x1
    or smaller.

    All these cases can be fixed by setting the appropriate
    GACT_xxxBORDER gadget Activation flag.

 4) In rare cases, buttons rendered with Border structures and JAM1 text
    may appear invisible under Release 2.

The height of the window's title bar is affected by the current font
settings.  See the discussion of "Screen Attributes" in the "Intuition
Screens" chapter. To predict your window's titlebar height before you call
OpenWindow():

    topborder = screen->WBorTop + screen->Font->ta_YSize + 1

The screen's font may not legally be changed after a screen is opened.

Be sure the screen cannot go away on you.  This is true if:

    1) You opened the screen yourself.

    2) You currently have a window open on the screen.

    3) You currently hold a lock on this screen (see LockPubScreen()).

IntuiText rendered into a window (either through PrintIText() or as a
gadget's GadgetText) defaults to the Window RastPort font, but can be
overridden using its ITextFont field.  Text rendered with the Text()
function appears in the Window RastPort font.

The Window's RPort's font shown above is the initial font that Intuition
sets for you in your window's RastPort. It is legal to change that
subsequently with SetFont().


E / Additional Information / Workbench And Startup

Under 1.3, the Workbench Screen and initial Shell (CLI) opened before the
first line in s:startup-sequence.  Some naughty programmers, in an attempt
to recover memory, would search for the bitplane pointers and appropriate
the memory for their own use.  This behavior is unsafe.

By default 2.0 opens the initial CLI on the first _output_ from the
s:startup-sequence.  This allows screen modes and other parameters to be
set before the user sees the screen.  However, this broke so many programs
that we put in the "silent-startup" hack.  A disk installed with 1.3
install opens the screen as before.  A disk installed under 2.0 opens
silently. Never steal the Workbench bitplanes.  You don't know where they
are, how big they are, what format they may be in, or even if they are
allocated.  Recovering the memory is a bit tricky.

Under 2.0, simply avoid any output from your s:startup-sequence.  If your
program opens a screen it will be the first screen the user ever sees.
Note that if ENDCLI is ever hit, the screen will pop open.

Under 1.3, after ENDCLI, use CloseWorkbench() to close the screen.  This
also works under 2.0.  Loop on CloseWorkbench() with a delay between
loops.  Continue looping until CloseWorkbench() succeeds or too much time
has passed.  Note that a new program called EndRun is available for
starting non-returning programs from the startup-sequence.  EndRun will
reduce memory fragmentation and will close Workbench if it is open.
EndRun.lzh will be available in Commodore's Amiga listings area on BIX.


Amiga® RKM Libraries: F Sample Startup Code

This appendix contains the source code to build Startup code modules.
The files include:

 lmkfile             A makefile to build the startup code modules.
 startup.asm         Assembler source for startup modules
 allstartup.i        Main include file
               __
 Astartup.i      |
 AWstartup.i     |
 Qstartup.i      |-- Include files for specific startup modules
 Rstartup.i      |
 RWstartup.i     |
 RXstartup.i   __|

The object code for the above include files can be found in the
Reference_Library/Lib_Startup drawer on this disc.


lib_examples/easy.c

/* easy.c: a complete example of how to open an Amiga function library in
 * C. In this case the function library is Intuition.  Once the Intuition
 * function library is open, any Intuition function can be called.  This
 * example uses the DisplayBeep() function of Intuition to flash the
 * screen With SAS/C (Lattice), compile with lc -L easy.c
 */

/* Declare the return type of the functions we will use.                 */
struct Library *OpenLibrary();  /* These Exec library functions can be   */
void            CloseLibrary(); /* called anytime (Exec is always open). */

void            DisplayBeep();  /* Before using this Intuition function, */
                                /* the Intuition library must be opened  */

struct IntuitionBase *IntuitionBase; /* Get storage for the library base */
                                     /* The base name MUST be            */
                                     /* IntuitionBase                    */
int main()
{
    IntuitionBase=(struct IntuitionBase *)
                  OpenLibrary("intuition.library",33L);

    if(IntuitionBase)           /* Check to see if it actually opened.   */
        {                       /* The Intuition library is now open so  */
        DisplayBeep(0L);        /* any of its functions may be used.     */

        CloseLibrary(IntuitionBase); /* Always close a library if not    */
                                     /* in use.                          */
        }
    else                        /* The library did not open so return an */
       {                        /* error code.  The exit() function is   */
       exit(20);                /* not part of the OS, it is part of the */
       }                        /* compiler link library.                */
}


lib_examples/easy.asm

**********************************************************************
* A complete ready-to-assemble example of how to open an Amiga function
* library in 68000 assembler.  In this case the Intuition function library
* is opened and one of its functions, DisplayBeep() is called.
*
* When calling an Amiga function, the library base pointer *must* be in
* A6 (the library is free to depend on this).  Registers D0, D1, A0
* and A1 may be destroyed by the library, all others will be preserved.
*
_AbsExecBase EQU  4          ;System pointer to Exec's library base

        XREF    _LVOOpenLibrary       ;Offset from Exec base for OpenLibrary()
        XREF    _LVOCloseLibrary      ;Offset from Exec base for CloseLibrary()
        XREF    _LVODisplayBeep       ;Offset from Intuition base for DisplayBeep()

        move.l  _AbsExecBase,a6       ;Move exec.library base to a6
        lea.l   IntuiName(pc),a1      ;Pointer to "intuition.library" string
        moveq   #33,d0                ;Version of library needed
        jsr     _LVOOpenLibrary(a6)   ;Call Exec's OpenLibrary() and
        tst.l   d0                    ;check to see if it succeeded
        bne.s   open_ok
        moveq   #20,d0                ;Set failure code
        rts                           ;Failed exit

open_ok move.l  d0,a6                 ;Put IntuitionBase in a6.
        suba.l  a0,a0                 ;Load zero into a0
        jsr     _LVODisplayBeep(a6)   ;Call Intuition's DisplayBeep()

        move.l  a6,a1                 ;Put IntuitionBase into a1
        move.l  _AbsExecBase,a6
        jsr     _LVOCloseLibrary(a6)  ;Call Exec's CloseLibrary()
        moveq   #0,d0                 ;Set return code
        rts

IntuiName:      dc.b 'intuition.library',0
        END


lib_examples/uptime.c

;/* uptime.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfis -j73 uptime.c
Blink FROM LIB:c.o,uptime.o TO uptime LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
*/
    /* Uses SAS C getreg() */

    #include <exec/types.h>
    #include <exec/memory.h>
    #include <dos/dos.h>
    #include <dos/dosextens.h>
    #include <dos/datetime.h>
    #include <utility/date.h>
    #include <dos.h>

    #include <clib/exec_protos.h>
    #include <clib/dos_protos.h>
    #include <clib/utility_protos.h>

    #include <stdlib.h>

    struct Library *UtilityBase;

    LONG main(void);

    LONG main(void)
    {
      struct InfoData *infodata;
      struct DeviceList *ramdevice;
      struct DateStamp *now;
      LONG currenttime, boottime;
      BPTR lock;
      LONG vargs[3];
      LONG rc = RETURN_FAIL;

      /* Fails silently if < 37 */
      if (UtilityBase = OpenLibrary("utility.library", 37))
      {
        if (infodata = AllocMem(sizeof(struct InfoData), MEMF_CLEAR))
        {
          if (now = AllocMem(sizeof(struct DateStamp), MEMF_CLEAR))
          {
            if (lock = Lock("RAM:", SHARED_LOCK))
            {
              if ((Info(lock, infodata)) == DOSTRUE)
              {
                /* Make C pointer */

                ramdevice = BADDR(infodata->id_VolumeNode);

                boottime = SMult32(ramdevice->dl_VolumeDate.ds_Days, 86400) +
                           SMult32(ramdevice->dl_VolumeDate.ds_Minute, 60) +
                           SDivMod32(ramdevice->dl_VolumeDate.ds_Tick,
                                     TICKS_PER_SECOND );

                DateStamp(now);

                currenttime = SMult32(now->ds_Days, 86400) +
                              SMult32(now->ds_Minute, 60) +
                              SDivMod32(now->ds_Tick, TICKS_PER_SECOND);

                currenttime -= boottime;

                if (currenttime > 0)
                {
                  vargs[0] = UDivMod32(currenttime, 86400);

                  vargs[1] = getreg(1);
                  vargs[1] = UDivMod32(vargs[1], 3600);

                  vargs[2] =getreg(1);
                  vargs[2] = UDivMod32(vargs[2], 60);

                  /*
                   * Passing the address of the array allows the VPrintf()
                   * function to access the array contents.  Keep in mind
                   * that VPrintf() does _NOT_ know how many elements are
                   * really valid in the final parameter, and will gleefully
                   * run past the valid arguments.
                   */
                  VFPrintf(Output(),
                           "up for %ld days, %ld hours, %ld minutes\n",
                           vargs );

                  rc = RETURN_OK;
                }
              }
              UnLock(lock);
            }
            FreeMem(now, sizeof(struct DateStamp));
          }
          FreeMem(infodata, sizeof(struct InfoData));
        }
        CloseLibrary(UtilityBase);
      }
      exit(rc);
    }


Lib_examples/bob.c

/* This example must be linked with animtools.c and includes the header
** files animtools.h and animtools_proto.h.  These files are listed at
** the end of the chapter.
**
** bob.c
**
** SAS/C V5.10a
** lc -b1 -cfist -v -y bob.c
** blink FROM LIB:c.o bob.o animtools.o LIB LIB:lc.lib LIB:amiga.lib TO bob
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuitionbase.h>
#include <graphics/gfx.h>
#include <graphics/gfxbase.h>
#include <graphics/gels.h>
#include <libraries/dos.h>
#include <stdlib.h>
#include "animtools.h"

VOID bobDrawGList(struct RastPort *rport, struct ViewPort *vport);
VOID process_window(struct Window *win, struct Bob *myBob);
VOID do_Bob(struct Window *win);

struct GfxBase       *GfxBase;       /* pointer to Graphics library */
struct IntuitionBase *IntuitionBase; /* pointer to Intuition library*/
int return_code;
#define GEL_SIZE  4                  /* number of lines in the bob  */

/* Bob data - two sets that are alternated between.  Note that this */
/* data is at the resolution of the screen.                         */

/* data is 2 planes by 2 words by GEL_SIZE lines                    */
WORD chip bob_data1[2 * 2 * GEL_SIZE] =
        {
        /* plane 1 */
        0xffff, 0x0003, 0xfff0, 0x0003, 0xfff0, 0x0003, 0xffff, 0x0003,
        /* plane 2 */
        0x3fff, 0xfffc, 0x3ff0, 0x0ffc, 0x3ff0, 0x0ffc, 0x3fff, 0xfffc
        };

/* data is 2 planes by 2 words by GEL_SIZE lines                     */
WORD chip bob_data2[2 * 2 * GEL_SIZE] =
        {
        /* plane 1 */
        0xc000, 0xffff, 0xc000, 0x0fff, 0xc000, 0x0fff, 0xc000, 0xffff,
        /* plane 2 */
        0x3fff, 0xfffc, 0x3ff0, 0x0ffc, 0x3ff0, 0x0ffc, 0x3fff, 0xfffc
        };

NEWBOB myNewBob =                     /* Data for the new bob structure defined in animtools.h */
        {                             /* Initial image, WORD width, line height                */
        bob_data2, 2,  GEL_SIZE,      /* Image depth, plane pick, plane on off, VSprite flags  */
        2, 3, 0, SAVEBACK | OVERLAY,  /* dbuf (0=false), raster depth, x,y position, hit mask, */
        0, 2, 160, 100,  0,0,         /* me mask                                               */
        };

struct NewWindow myNewWindow =
        {                             /* information for the new window */
        80, 20, 400, 150, -1, -1, CLOSEWINDOW | INTUITICKS,
        ACTIVATE | WINDOWCLOSE | WINDOWDEPTH | RMBTRAP,
        NULL, NULL, "Bob", NULL, NULL, 0, 0, 0, 0, WBENCHSCREEN
        };

/* Draw the Bobs into the RastPort. */
VOID bobDrawGList(struct RastPort *rport, struct ViewPort *vport)
{
SortGList(rport);
DrawGList(rport, vport);
/* If the GelsList includes true VSprites, MrgCop() and LoadView() here */
WaitTOF() ;
}

/* Process window and dynamically change bob: Get messages. Go away on CLOSEWINDOW.
** Update and redisplay bob on INTUITICKS. Wait for more messages.
*/
VOID process_window(struct Window *win, struct Bob *myBob)
{
struct IntuiMessage *msg;

FOREVER {
        Wait(1L << win->UserPort->mp_SigBit);
        while (NULL != (msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
                {
                /* only CLOSEWINDOW and INTUITICKS are active */
                if (msg->Class == CLOSEWINDOW)
                        {
                        ReplyMsg((struct Message *)msg);
                        return;
                        }
                /* Must be INTUITICKS:  change x and y values on the fly.  Note:
                ** do not have to add window offset, Bob is relative to the
                ** window (sprite relative to screen).
                */
                myBob->BobVSprite->X = msg->MouseX + 20;
                myBob->BobVSprite->Y = msg->MouseY + 1;
                ReplyMsg((struct Message *)msg);
                }
        /* after getting a message, change image data on the fly */
        myBob->BobVSprite->ImageData =
                (myBob->BobVSprite->ImageData == bob_data1) ? bob_data2 : bob_data1;
        InitMasks(myBob->BobVSprite); /* set up masks for new image */
        bobDrawGList(win->RPort, ViewPortAddress(win));
        }
}

/* Working with the Bob: setup the GEL system, and get a new Bob (makeBob()).
** Add the bob to the system and display. Use the Bob.  When done, remove
** the Bob and update the display without the bob. Cleanup everything.
*/
VOID do_Bob(struct Window *win)
{
struct Bob         *myBob;
struct GelsInfo    *my_ginfo;

if (NULL == (my_ginfo = setupGelSys(win->RPort, 0x03)))
        return_code = RETURN_WARN;
else
        {
        if (NULL == (myBob = makeBob(&myNewBob)))
                return_code = RETURN_WARN;
        else
                {
                AddBob(myBob, win->RPort);
                bobDrawGList(win->RPort, ViewPortAddress(win));
                process_window(win, myBob);
                RemBob(myBob);
                bobDrawGList(win->RPort, ViewPortAddress(win));
                freeBob(myBob, myNewBob.nb_RasDepth);
                }
        cleanupGelSys(my_ginfo,win->RPort);
        }
}

/* Example bob program: First open up the libraries and a window. */
VOID main(int argc, char **argv)
{
struct Window      *win;

return_code = RETURN_OK;

if (NULL == (GfxBase = (struct GfxBase *)OpenLibrary(GRAPHICSNAME,37L)))
        return_code = RETURN_FAIL;
else
        {
        if (NULL == (IntuitionBase = (struct IntuitionBase *)OpenLibrary(INTUITIONNAME,37L)))
                return_code = RETURN_FAIL;
        else
                {
                if (NULL == (win = OpenWindow(&myNewWindow)))
                        return_code = RETURN_FAIL;
                else
                        {
                        do_Bob(win);
                        CloseWindow(win);
                        }
                CloseLibrary((struct Library *)IntuitionBase);
                }
        CloseLibrary((struct Library *)GfxBase);
        }
exit(return_code);
}


Lib_examples/filehook.c

;/* filehook.c - Execute me to compile me with Lattice 5.10
LC -b1 -cfistq -v -y -j73 filehook.c
Blink FROM LIB:c.o,filehook.o TO filehook LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
**
** The following example illustrates the use of a hook function for
** both _DOWILDFUNC and _DOMSGFUNC.
**
*/
#include <exec/types.h>
#include <intuition/intuition.h>
#include <dos/dosasl.h>
#include <libraries/asl.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/asl_protos.h>
#include <clib/intuition_protos.h>
#include <stdio.h>

#ifdef LATTICE
int CXBRK(void)     { return(0); }  /* Disable Lattice CTRL/C handling */
void chkabort(void) { return; }     /* really */
#endif

#define DESTPATLENGTH 20

UBYTE *vers = "$VER: filehook 37.0";

CPTR HookFunc();

struct Library *AslBase = NULL;
struct Library *IntuitionBase = NULL;
struct Window  *window = NULL;

/* this is the pattern matching string that the hook function uses */
UBYTE *sourcepattern = "(#?.info)";
UBYTE pat[DESTPATLENGTH];

void main(int argc, char **argv)
{
    struct FileRequester *fr;

    if (AslBase = OpenLibrary("asl.library", 37L))
    {
        if (IntuitionBase = (struct IntuitionBase *)
                    OpenLibrary("intuition.library", 37L))
        {
            /* This is a V37 dos.library function that turns a pattern matching
            ** string into something the DOS pattern matching functions can
            ** understand.
            */
            ParsePattern(sourcepattern, pat, DESTPATLENGTH);

            /* open a window that gets ACTIVEWINDOW events */
            if (window = (struct Window *)OpenWindowTags(NULL,
                    WA_Title, "ASL Hook Function Example",
                    WA_IDCMP, IDCMP_ACTIVEWINDOW,
                    WA_Flags, WFLG_DEPTHGADGET,
                    TAG_END))
            {
                if (fr = AllocFileRequest())
                {
                    if (AslRequestTags(fr,
                        ASL_Dir, (ULONG)"SYS:Utilities",
                        ASL_Window, window,
                        ASL_TopEdge, 0L,
                        ASL_Height, 200L,
                        ASL_Hail, (ULONG)"Pick an icon, select save",
                        ASL_HookFunc, (ULONG)HookFunc,
                        ASL_FuncFlags, FILF_DOWILDFUNC | FILF_DOMSGFUNC | FILF_SAVE,
                        ASL_OKText, (ULONG)"Save",
                        TAG_DONE))
                    {
                        printf("PATH=%s FILE=%s\n", fr->rf_Dir, fr->rf_File);
                        printf("To combine the path and filename, copy the path\n");
                        printf("to a buffer, add the filename with Dos AddPart().\n");
                    }
                    FreeFileRequest(fr);
                }
                CloseWindow(window);
            }
            CloseLibrary(IntuitionBase);
        }
        CloseLibrary(AslBase);
    }
}

CPTR HookFunc(LONG type, CPTR obj, struct FileRequester *fr)
{
    static BOOL returnvalue;
    switch(type)
    {
        case FILF_DOMSGFUNC:
        /* We got a message meant for the window */
            printf("You activated the window\n");
            return(obj);
            break;
        case FILF_DOWILDFUNC:
        /* We got an AnchorPath structure, should
        ** the requester display this file? */

            /* MatchPattern() is a dos.library function that
            ** compares a matching pattern (parsed by the
            ** ParsePattern() DOS function) to a string and
            ** returns true if they match. */
            returnvalue = MatchPattern(pat,
                    ((struct AnchorPath *)obj)->ap_Info.fib_FileName);

            /* we have to negate MatchPattern()'s return value
            ** because the file requester expects a zero for
            ** a match not a TRUE value */
            return( (CPTR)(! returnvalue) );
            break;
    }
}


Lib_examples/filepat.c

;/* filepat.c - Execute me to compile me with SASC 5.10
LC -b1 -cfistq -v -y -j73 filepat.c
Blink FROM LIB:c.o,filepat.o TO filepat LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
*/
#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/screens.h>
#include <graphics/displayinfo.h>
#include <libraries/asl.h>
#include <workbench/startup.h>

#include <clib/asl_protos.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <stdio.h>

#ifdef LATTICE
int CXBRK(void)     { return(0); }  /* Disable Lattice CTRL/C handling */
void chkabort(void) { return; }     /* really */
#endif

UBYTE *vers = "$VER: filepat 37.0";

struct Library *AslBase = NULL;
struct Library *IntuitionBase = NULL;
struct Screen *screen = NULL;
struct Window *window = NULL;

void main(int argc, char **argv)
{
    struct FileRequester *fr;
    struct WBArg *frargs;
    int x;

    if (AslBase = OpenLibrary("asl.library", 37L))
    {
        if (IntuitionBase = (struct IntuitionBase *)
                OpenLibrary("intuition.library", 37L))
        {
            if (screen = (struct Screen *)OpenScreenTags(NULL,
                    SA_DisplayID, HIRESLACE_KEY,
                    SA_Title, "ASL Test Screen",
                    TAG_END))
            {
                if (window = (struct Window *)OpenWindowTags(NULL,
                        WA_CustomScreen, screen,
                        WA_Title, "Demo Customscreen, File Pattern, Multi-select",
                        WA_Flags, WINDOWDEPTH | WINDOWDRAG,
                        TAG_END))
                {
                    if (fr = (struct FileRequester *)
                        AllocAslRequestTags(ASL_FileRequest,
                            ASL_Hail, (ULONG)"FilePat/MultiSelect Demo",
                            ASL_Dir,  (ULONG)"libs:",
                            ASL_File, (ULONG)"asl.library",

                            /* Initial pattern string for pattern matching */
                            ASL_Pattern, (ULONG)"~(rexx#?|math#?)",

                            /* Enable multiselection and pattern match gadget */
                            ASL_FuncFlags, FILF_MULTISELECT | FILF_PATGAD,

                            /* This requester comes up on the screen of this
                            ** window (and uses window's message port, if any).
                            */
                            ASL_Window, window,
                            TAG_DONE))
                    {
                        /* Put up file requester */
                        if (AslRequest(fr, 0L))
                        {
                            /* If the file requester's rf_NumArgs field
                            ** is not zero, the user multiselected. The
                            ** number of files is stored in rf_NumArgs.
                            */
                            if (fr->rf_NumArgs)
                            {
                                /* rf_ArgList is an array of WBArg structures
                                ** (see <workbench/startup.h>). Each entry in
                                ** this array corresponds to one of the files
                                ** the user selected (in alphabetical order).
                                */
                                frargs = fr->rf_ArgList;

                                /* The user multiselected, step through
                                ** the list of selected files.
                                */
                                for ( x=0;  x < fr->rf_NumArgs;  x++ )
                                    printf("Argument %d: PATH=%s FILE=%s\n",
                                        x, fr->rf_Dir, frargs[x].wa_Name);
                            }
                            else
                                /* The user didn't multiselect, use the
                                ** normal way to get the file name.
                                */
                                printf("PATH=%s FILE=%s\n", fr->rf_Dir, fr->rf_File);
                        }
                        /* Done with the FileRequester, better return it */
                        FreeAslRequest(fr);
                    }
                    CloseWindow(window);
                }
                CloseScreen(screen);
            }
            CloseLibrary(IntuitionBase);
        }
        CloseLibrary(AslBase);
    }
}


Lib_examples/fontreq.c

;/* fontreq.c - Execute me to compile me with Lattice 5.10
LC -b1 -cfistq -v -y -j73 fontreq.c
Blink FROM LIB:c.o,fontreq.o TO fontreq LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
**
** The following example illustrates how to use a font requester.
*/

#include <exec/types.h>
#include <libraries/asl.h>

#include <clib/asl_protos.h>
#include <clib/exec_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void)     { return(0); }  /* Disable Lattice CTRL/C handling */
void chkabort(void) { return; }     /* really */
#endif

UBYTE *vers = "$VER: fontreq 37.0";

struct Library *AslBase = NULL;

/* Our replacement strings for the "mode" cycle gadget.  The
** first string is the cycle gadget's label.  The other strings
** are the actual strings that will appear on the cycle gadget.
*/
UBYTE *modelist[] =
{
    "RKM Modes",
    "Mode 0",
    "Mode 1",
    "Mode 2",
    "Mode 3",
    "Mode 4",
    NULL
};

void main(int argc, char **argv)
{
    struct FontRequester *fr;

    if (AslBase = OpenLibrary("asl.library", 37L))
    {
        if (fr = (struct FontRequester *)
            AllocAslRequestTags(ASL_FontRequest,
                /* tell the requester to use my custom mode names */
                ASL_ModeList, modelist,

                /* Supply initial values for requester */
                ASL_FontName, (ULONG)"topaz.font",
                ASL_FontHeight, 11L,
                ASL_FontStyles, FSF_BOLD | FSF_ITALIC,
                ASL_FrontPen,  0x00L,
                ASL_BackPen,   0x01L,

                /* Only display font sizes between 8 and 14, inclusive. */
                ASL_MinHeight, 8L,
                ASL_MaxHeight, 14L,

                /* Give all the gadgetry, but only display fixed width fonts */
                ASL_FuncFlags, FONF_FRONTCOLOR | FONF_BACKCOLOR |
                    FONF_DRAWMODE | FONF_STYLES | FONF_FIXEDWIDTH,
                TAG_DONE))
        {
            /* Pop up the requester */
            if (AslRequest(fr, NULL))
            {
                /* The user selected something,  report their choice */
                printf("%s\n  YSize = %d  Style = 0x%x   Flags = 0x%x\n"
                       "  FPen = 0x%x   BPen = 0x%x   DrawMode = 0x%x\n",
                               fr->fo_Attr.ta_Name,
                               fr->fo_Attr.ta_YSize,
                               fr->fo_Attr.ta_Style,
                               fr->fo_Attr.ta_Flags,
                               fr->fo_FrontPen,
                               fr->fo_BackPen,
                               fr->fo_DrawMode);
            }
            else
                /* The user cancelled the requester, or some kind of error
                ** occurred preventing the requester from opening. */
                printf("Request Cancelled\n");
            FreeAslRequest(fr);
        }
        CloseLibrary(AslBase);
    }
}


Lib_examples/filereq.c

;/* filereq.c - Execute me to compile me with SASC 5.10
LC -b1 -cfistq -v -y -j73 filereq.c
Blink FROM LIB:c.o,filereq.o TO filereq LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
**
** Here's a short example showing how to create a file requester with
** asl.library.  If AslRequest() returns TRUE then the rf_File and
** rf_Dir fields of the requester data structure contain the name and
** directory of the file the user selected.  Note that the user can type
** in the a name for the file and directory, which makes it possible for
** a file requester to return a file and directory that do not
** (currently) exist.
*/
#include <exec/types.h>
#include <exec/libraries.h>
#include <libraries/asl.h>
#include <clib/exec_protos.h>
#include <clib/asl_protos.h>
#include <stdio.h>

#ifdef LATTICE
int CXBRK(void)     { return(0); }  /* Disable Lattice CTRL/C handling */
void chkabort(void) { return; }     /* really */
#endif

UBYTE *vers = "$VER: filereq 37.0";

#define MYLEFTEDGE 0
#define MYTOPEDGE  0
#define MYWIDTH    320
#define MYHEIGHT   400

struct Library *AslBase = NULL;

struct TagItem frtags[] =
{
    ASL_Hail,       (ULONG)"The RKM file requester",
    ASL_Height,     MYHEIGHT,
    ASL_Width,      MYWIDTH,
    ASL_LeftEdge,   MYLEFTEDGE,
    ASL_TopEdge,    MYTOPEDGE,
    ASL_OKText,     (ULONG)"O KAY",
    ASL_CancelText, (ULONG)"not OK",
    ASL_File,       (ULONG)"asl.library",
    ASL_Dir,        (ULONG)"libs:",
    TAG_DONE
};

void main(int argc, char **argv)
{
    struct FileRequester *fr;

    if (AslBase = OpenLibrary("asl.library", 37L))
    {
        if (fr = (struct FileRequester *)
            AllocAslRequest(ASL_FileRequest, frtags))
        {
            if (AslRequest(fr, NULL))
            {
                printf("PATH=%s  FILE=%s\n", fr->rf_Dir, fr->rf_File);
                printf("To combine the path and filename, copy the path\n");
                printf("to a buffer, add the filename with Dos AddPart().\n");
            }
            FreeAslRequest(fr);
        }
        else printf("User Cancelled\n");

        CloseLibrary(AslBase);
    }
}


Lib_examples/RKMButClass.c

;/* RKMButClass.c - Example Boopsi gadget for RKRM:Libraries
; Execute me to compile me with Lattice 5.10b
LC -b1 -d0 -cfistq -v -y -j73 RKMButClass.c
Blink FROM LIB:c.o,RKMButClass.o TO TestBut LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
*/

#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/classes.h>
#include <intuition/classusr.h>
#include <intuition/imageclass.h>
#include <intuition/gadgetclass.h>
#include <intuition/cghooks.h>
#include <intuition/icclass.h>
#include <utility/tagitem.h>
#include <utility/hooks.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/utility_protos.h>
#include <clib/alib_protos.h>
#include <clib/alib_stdio_protos.h>

#include <graphics/gfxmacros.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }
#endif

UBYTE *vers = "\0$VER: TestBut 37.1";

/***********************************************************/
/****************      Class specifics      ****************/
/***********************************************************/
#define RKMBUT_Pulse   (TAG_USER + 1)

struct ButINST
{
    LONG midX, midY; /* Coordinates of middle of gadget */
};

/* ButINST has one flag:  */
#define ERASE_ONLY   0x00000001 /* Tells rendering routine to */
                                /* only erase the gadget, not */
                                /* rerender a new one.  This  */
                                /* lets the gadget erase it-  */
                                /* self before it rescales.   */

/* The functions in this module */
Class *initRKMButGadClass(void);
BOOL   freeRKMButGadClass(Class *);
ULONG  dispatchRKMButGad(Class *, Object *, Msg);
void   NotifyPulse(Class *, Object *, ULONG, LONG, struct gpInput *);
ULONG  RenderRKMBut(Class *, struct Gadget *, struct gpRender *);
void   geta4(void);
void   MainLoop(ULONG, ULONG);

/*************************************************************************************************/
/* The main() function connects an RKMButClass object to a Boopsi integer gadget, which displays */
/* the RKMButClass gadget's RKMBUT_Pulse value.  The code scales and move the gadget while it is */
/* in place.                                                                                     */
/*************************************************************************************************/

struct TagItem pulse2int[] =
{
    {RKMBUT_Pulse, STRINGA_LongVal},
    {TAG_END,}
};

#define INTWIDTH  40
#define INTHEIGHT 20

struct Library *IntuitionBase, *UtilityBase, *GfxBase;
struct Window *w;
Class *rkmbutcl;
struct Gadget *integer, *but;
struct IntuiMessage *msg;

void main(void)
{
    if (IntuitionBase = OpenLibrary("intuition.library", 37L))
    {
        if (UtilityBase = OpenLibrary("utility.library", 37L))
        {
            if (GfxBase = OpenLibrary("graphics.library", 37L))
            {
                if (w = OpenWindowTags(NULL,
                    WA_Flags,       WFLG_DEPTHGADGET | WFLG_DRAGBAR |
                                        WFLG_CLOSEGADGET | WFLG_SIZEGADGET,
                    WA_IDCMP,       IDCMP_CLOSEWINDOW,
                    WA_Width,           640,
                    WA_Height,          200,
                    TAG_END))
                {
                    WindowLimits(w, 450, 200, 640, 200);

                    if (rkmbutcl = initRKMButGadClass())
                    {
                        if (integer = (struct Gadget *)NewObject(NULL,
                                       "strgclass",
                                       GA_ID,            1L,
                                       GA_Top,           (w->BorderTop) + 5L,
                                       GA_Left,          (w->BorderLeft) + 5L,
                                       GA_Width,         INTWIDTH,
                                       GA_Height,        INTHEIGHT,
                                       STRINGA_LongVal,  0L,
                                       STRINGA_MaxChars, 5L,
                                       TAG_END))
                        {
                            if (but = (struct Gadget *)NewObject(rkmbutcl,
                                       NULL,
                                       GA_ID,       2L,
                                       GA_Top,      (w->BorderTop) + 5L,
                                       GA_Left,     integer->LeftEdge +
                                                        integer->Width + 5L,
                                       GA_Width,    40L,
                                       GA_Height,   INTHEIGHT,
                                       GA_Previous, integer,
                                       ICA_MAP,     pulse2int,
                                       ICA_TARGET,  integer,
                                       TAG_END))
                            {
                                AddGList(w, integer, -1, -1, NULL);
                                RefreshGList(integer, w, NULL, -1);

                                SetWindowTitles(w,
                                    "<-- Click to resize gadget Height",
                                    NULL);
                                MainLoop(TAG_DONE, 0L);

                                SetWindowTitles(w,
                                    "<-- Click to resize gadget Width",
                                    NULL);
                                MainLoop(GA_Height, 100L);

                                SetWindowTitles(w,
                                    "<-- Click to resize gadget Y position",
                                    NULL);
                                MainLoop(GA_Width, 100L);

                                SetWindowTitles(w,
                                    "<-- Click to resize gadget X position",
                                    NULL);
                                MainLoop(GA_Top, but->TopEdge + 20);

                                SetWindowTitles(w,
                                    "<-- Click to quit", NULL);
                                MainLoop(GA_Left, but->LeftEdge + 20);

                                RemoveGList(w, integer, -1);
                                DisposeObject(but);
                            }
                            DisposeObject(integer);
                        }
                        freeRKMButGadClass(rkmbutcl);
                    }
                    CloseWindow(w);
                }
                CloseLibrary(GfxBase);
            }
            CloseLibrary(UtilityBase);
        }
        CloseLibrary(IntuitionBase);
    }
}

void MainLoop(ULONG attr, ULONG value)
{
    ULONG done = FALSE;

    SetGadgetAttrs(but, w, NULL, attr, value, TAG_DONE);

    while (done == FALSE)
    {
        WaitPort((struct MsgPort *)w->UserPort);
        while (msg = (struct IntuiMessage *)
           GetMsg((struct MsgPort *)w->UserPort))
        {
            if (msg->Class == IDCMP_CLOSEWINDOW)
            {
                done = TRUE;
            }
            ReplyMsg(msg);
        }
    }
}

/***********************************************************/
/**    Make the class and set up the dispatcher's hook    **/
/***********************************************************/
Class   *initRKMButGadClass(void)
{
    Class *cl = NULL;
    extern ULONG HookEntry();     /* defined in amiga.lib */

    if ( cl =  MakeClass( NULL,
                "gadgetclass", NULL,
                sizeof ( struct ButINST ),
                0 ))
    {
        /* initialize the cl_Dispatcher Hook    */
        cl->cl_Dispatcher.h_Entry = HookEntry;
        cl->cl_Dispatcher.h_SubEntry = dispatchRKMButGad;
    }
    return ( cl );
}

/***********************************************************/
/******************     Free the class      ****************/
/***********************************************************/
BOOL freeRKMButGadClass( Class *cl )
{
    return (FreeClass(cl));
}

/***********************************************************/
/**********       The RKMBut class dispatcher      *********/
/***********************************************************/
ULONG dispatchRKMButGad(Class *cl, Object *o, Msg msg)
{
    struct ButINST *inst;
    ULONG retval = FALSE;
    Object *object;

    /* SAS/C and Manx function to make sure register A4
       contains a pointer to global data */
    geta4();

    switch (msg->MethodID)
    {
        case OM_NEW:       /* First, pass up to superclass */
            if (object = (Object *)DoSuperMethodA(cl, o, msg))
            {
                struct Gadget *g = (struct Gadget *)object;

                            /* Initial local instance data */
                inst = INST_DATA(cl, object);
                inst->midX   = g->LeftEdge + ( (g->Width) / 2);
                inst->midY   = g->TopEdge + ( (g->Height) / 2);

                retval = (ULONG)object;
            }
            break;
        case GM_HITTEST:
                   /* Since this is a rectangular gadget this  */
                   /* method always returns GMR_GADGETHIT.     */
            retval = GMR_GADGETHIT;
            break;
        case GM_GOACTIVE:
            inst = INST_DATA(cl, o);

                    /* Only become active if the GM_GOACTIVE   */
                    /* was triggered by direct user input.     */
            if (((struct gpInput *)msg)->gpi_IEvent)
            {
                       /* This gadget is now active, change    */
                       /* visual state to selected and render. */
                ((struct Gadget *)o)->Flags |= GFLG_SELECTED;
                                RenderRKMBut(cl, (struct Gadget *)o, (struct gpRender *)msg);
                retval = GMR_MEACTIVE;
            }
            else            /* The GM_GOACTIVE was not         */
                            /* triggered by direct user input. */
                retval = GMR_NOREUSE;
            break;
        case GM_RENDER:
            retval = RenderRKMBut(cl, (struct Gadget *)o, (struct gpRender *)msg);
            break;
        case GM_HANDLEINPUT:   /* While it is active, this gadget sends its superclass an        */
                               /* OM_NOTIFY pulse for every IECLASS_TIMER event that goes by     */
                               /* (about one every 10th of a second).  Any object that is        */
                               /* connected to this gadget will get A LOT of OM_UPDATE messages. */
            {
                struct Gadget *g = (struct Gadget *)o;
                struct gpInput *gpi = (struct gpInput *)msg;
                struct InputEvent *ie = gpi->gpi_IEvent;

                inst = INST_DATA(cl, o);

                retval = GMR_MEACTIVE;

                if (ie->ie_Class == IECLASS_RAWMOUSE)
                {
                    switch (ie->ie_Code)
                    {
                        case SELECTUP: /* The user let go of the gadget so return GMR_NOREUSE    */
                                       /* to deactivate and to tell Intuition not to reuse       */
                                       /* this Input Event as we have already processed it.      */

                                       /*If the user let go of the gadget while the mouse was    */
                                       /*over it, mask GMR_VERIFY into the return value so       */
                                       /*Intuition will send a Release Verify (GADGETUP).        */
                            if ( ((gpi->gpi_Mouse).X < g->LeftEdge) ||
                                 ((gpi->gpi_Mouse).X > g->LeftEdge + g->Width) ||
                                 ((gpi->gpi_Mouse).Y < g->TopEdge) ||
                                 ((gpi->gpi_Mouse).Y > g->TopEdge + g->Height) )
                                retval = GMR_NOREUSE | GMR_VERIFY;
                            else
                                retval = GMR_NOREUSE;

                                           /* Since the gadget is going inactive, send a final   */
                                           /* notification to the ICA_TARGET.                    */
                            NotifyPulse(cl , o, 0L, inst->midX, (struct gp_Input *)msg);
                            break;
                        case MENUDOWN: /* The user hit the menu button. Go inactive and let      */
                                       /* Intuition reuse the menu button event so Intuition can */
                                       /* pop up the menu bar.                                   */
                            retval = GMR_REUSE;

                                           /* Since the gadget is going inactive, send a final   */
                                           /* notification to the ICA_TARGET.                    */
                            NotifyPulse(cl , o, 0L, inst->midX, (struct gp_Input *)msg);
                            break;
                        default:
                            retval = GMR_MEACTIVE;
                    }

                }
                else if (ie->ie_Class == IECLASS_TIMER)
                              /* If the gadget gets a timer event, it sends an interim OM_NOTIFY */
                    NotifyPulse(cl, o, OPUF_INTERIM, inst->midX, gpi); /*     to its superclass. */
            }
            break;

        case GM_GOINACTIVE:           /* Intuition said to go inactive.  Clear the GFLG_SELECTED */
                                      /* bit and render using unselected imagery.                */
            ((struct Gadget *)o)->Flags &= ~GFLG_SELECTED;
            RenderRKMBut(cl, (struct Gadget *)o, (struct gpRender *)msg);
            break;
        case OM_SET:/* Although this class doesn't have settable attributes, this gadget class   */
                    /* does have scaleable imagery, so it needs to find out when its size and/or */
                    /* position has changed so it can erase itself, THEN scale, and rerender.    */
            if ( FindTagItem(GA_Width,  ((struct opSet *)msg)->ops_AttrList) ||
                 FindTagItem(GA_Height, ((struct opSet *)msg)->ops_AttrList) ||
                 FindTagItem(GA_Top,    ((struct opSet *)msg)->ops_AttrList) ||
                 FindTagItem(GA_Left,   ((struct opSet *)msg)->ops_AttrList) )
            {
                struct RastPort *rp;
                struct Gadget *g = (struct Gadget *)o;

                WORD x,y,w,h;

                x = g->LeftEdge;
                y = g->TopEdge;
                w = g->Width;
                h = g->Height;

                inst = INST_DATA(cl, o);

                retval = DoSuperMethodA(cl, o, msg);

                                                          /* Get pointer to RastPort for gadget. */
                if (rp = ObtainGIRPort( ((struct opSet *)msg)->ops_GInfo) )
                {
                    UWORD *pens = ((struct opSet *)msg)->ops_GInfo->gi_DrInfo->dri_Pens;

                    SetAPen(rp, pens[BACKGROUNDPEN]);
                    SetDrMd(rp, JAM1);                            /* Erase the old gadget.       */
                    RectFill(rp, x, y, x+w, y+h);

                    inst->midX = g->LeftEdge + ( (g->Width) / 2); /* Recalculate where the       */
                    inst->midY = g->TopEdge + ( (g->Height) / 2); /* center of the gadget is.    */

                                                                  /* Rerender the gadget.        */
                    DoMethod(o, GM_RENDER, ((struct opSet *)msg)->ops_GInfo, rp, GREDRAW_REDRAW);
                    ReleaseGIRPort(rp);
                }
            }
            else
                retval = DoSuperMethodA(cl, o, msg);
            break;
        default:          /* rkmmodelclass does not recognize the methodID, let the superclass's */
                          /* dispatcher take a look at it.                                       */
            retval = DoSuperMethodA(cl, o, msg);
            break;
    }
    return(retval);
}

/*************************************************************************************************/
/************** Build an OM_NOTIFY message for RKMBUT_Pulse and send it to the superclass. *******/
/*************************************************************************************************/
void NotifyPulse(Class *cl, Object *o, ULONG flags, LONG mid, struct gpInput *gpi)
{
    struct TagItem tt[3];

    tt[0].ti_Tag = RKMBUT_Pulse;
    tt[0].ti_Data = mid - ((gpi->gpi_Mouse).X + ((struct Gadget *)o)->LeftEdge);

    tt[1].ti_Tag = GA_ID;
    tt[1].ti_Data = ((struct Gadget *)o)->GadgetID;

    tt[2].ti_Tag = TAG_DONE;

    DoSuperMethod(cl, o, OM_NOTIFY, tt, gpi->gpi_GInfo, flags);
}

/*************************************************************************************************/
/*******************************   Erase and rerender the gadget.   ******************************/
/*************************************************************************************************/
ULONG RenderRKMBut(Class *cl, struct Gadget *g, struct gpRender *msg)
{
    struct ButINST *inst = INST_DATA(cl, (Object *)g);
    struct RastPort *rp;
    ULONG retval = TRUE;
    UWORD *pens = msg->gpr_GInfo->gi_DrInfo->dri_Pens;

    if (msg->MethodID == GM_RENDER)   /* If msg is truly a GM_RENDER message (not a gpInput that */
                                      /* looks like a gpRender), use the rastport within it...   */
        rp = msg->gpr_RPort;
    else                              /* ...Otherwise, get a rastport using ObtainGIRPort().     */
        rp = ObtainGIRPort(msg->gpr_GInfo);

    if (rp)
    {
        UWORD back, shine, shadow, w, h, x, y;

        if (g->Flags & GFLG_SELECTED) /* If the gadget is selected, reverse the meanings of the  */
        {                             /* pens.                                                   */
            back   = pens[FILLPEN];
            shine  = pens[SHADOWPEN];
            shadow = pens[SHINEPEN];
        }
        else
        {
            back   = pens[BACKGROUNDPEN];
            shine  = pens[SHINEPEN];
            shadow = pens[SHADOWPEN];
        }
        SetDrMd(rp, JAM1);

        SetAPen(rp, back);          /* Erase the old gadget.       */
        RectFill(rp, g->LeftEdge,
                     g->TopEdge,
                     g->LeftEdge + g->Width,
                     g->TopEdge + g->Height);

        SetAPen(rp, shadow);     /* Draw shadow edge.            */
        Move(rp, g->LeftEdge + 1, g->TopEdge + g->Height);
        Draw(rp, g->LeftEdge + g->Width, g->TopEdge + g->Height);
        Draw(rp, g->LeftEdge + g->Width, g->TopEdge + 1);

        w = g->Width / 4;       /* Draw Arrows - Sorry, no frills imagery */
        h = g->Height / 2;
        x = g->LeftEdge + (w/2);
        y = g->TopEdge + (h/2);

        Move(rp, x, inst->midY);
        Draw(rp, x + w, y);
        Draw(rp, x + w, y + (g->Height) - h);
        Draw(rp, x, inst->midY);

        x = g->LeftEdge + (w/2) + g->Width / 2;

        Move(rp, x + w, inst->midY);
        Draw(rp, x, y);
        Draw(rp, x, y  + (g->Height) - h);
        Draw(rp, x + w, inst->midY);

        SetAPen(rp, shine);    /* Draw shine edge.           */
        Move(rp, g->LeftEdge, g->TopEdge + g->Height - 1);
        Draw(rp, g->LeftEdge, g->TopEdge);
        Draw(rp, g->LeftEdge + g->Width - 1, g->TopEdge);

        if (msg->MethodID != GM_RENDER) /* If we allocated a rastport, give it back.             */
            ReleaseGIRPort(rp);
    }
    else retval = FALSE;
    return(retval);
}


Lib_examples/RKMModel.c

;/* RKMModel.c - A simple custom modelclass subclass.
LC -cfist -b1 -y -v -j73 rkmmodel.c
quit ;*/

#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/classes.h>
#include <intuition/classusr.h>
#include <intuition/imageclass.h>
#include <intuition/gadgetclass.h>
#include <intuition/cghooks.h>
#include <intuition/icclass.h>
#include <utility/tagitem.h>
#include <utility/hooks.h>
#include <clib/intuition_protos.h>
#include <clib/utility_protos.h>
#include <clib/alib_protos.h>
#include <clib/alib_stdio_protos.h>

extern struct Library *IntuitionBase, *UtilityBase;

/*************************************************************************************************/
/****************  The attributes defined by this class  *****************************************/
/*************************************************************************************************/
#define RKMMOD_CurrVal  (TAG_USER + 1) /* This attribute is the current value of the model.*******/
                                       /**********************************************************/
#define RKMMOD_Up       (TAG_USER + 2) /* These two are fake attributes that rkmmodelclass *******/
#define RKMMOD_Down     (TAG_USER + 3) /* uses as pulse values to increment/decrement the  *******/
                                       /* rkmmodel's RKMMOD_CurrVal attribute.             *******/
                                       /**********************************************************/
#define RKMMOD_Limit    (TAG_USER + 4) /* This attribute contains the upper bound of the   *******/
                                       /* rkmmodel's RKMMOD_CurrVal.  The rkmmodel has a   *******/
                                       /* static lower bound of zero.                      *******/
/*************************************************************************************************/

#define DEFAULTVALLIMIT 100L /* If the programmer doesn't set               */
                             /* RKMMOD_Limit, it defaults to this.          */
struct RKMModData {
    ULONG currval;       /* The instance data for this class.               */
    ULONG vallimit;
};

/*************************************************************************************************/
/**************************      The functions in this module     ********************************/
/*************************************************************************************************/
void    geta4(void);                                                              /***************/
Class  *initRKMModClass(void);                                                    /***************/
BOOL    freeRKMModClass(Class *);                                                 /***************/
ULONG   dispatchRKMModel(Class *, Object *, Msg);                                 /***************/
void    NotifyCurrVal(Class *, Object *, struct opUpdate *, struct RKMModData *); /***************/
/*************************************************************************************************/

/*************************************************************************************************/
/********************************   Initialize the class    **************************************/
/*************************************************************************************************/
Class   *initRKMModClass(void)                /* Make the class and set     */
{                                             /* up the dispatcher's hook.  */
    Class *cl;
    extern ULONG HookEntry();  /*      <-------   defined in amiga.lib.     */

    if ( cl =  MakeClass( NULL,
                "modelclass", NULL,
                sizeof ( struct RKMModData ),
                0 ))
    {
        cl->cl_Dispatcher.h_Entry = HookEntry;           /* initialize the  */
        cl->cl_Dispatcher.h_SubEntry = dispatchRKMModel; /* cl_Dispatcher   */
                                                         /* Hook.           */
    }
    return ( cl );
}

/*************************************************************************************************/
/*********************************      Free the class     ***************************************/
/*************************************************************************************************/
BOOL freeRKMModClass( Class *cl )
{
    return (FreeClass(cl));
}

/*************************************************************************************************/
/********************************     The class Dispatcher     ***********************************/
/*************************************************************************************************/
ULONG dispatchRKMModel(Class *cl, Object *o, Msg msg)
{
    struct RKMModData *mmd;
    APTR retval = NULL;  /* A generic return value used by this class's methods.  The            */
                         /* meaning of this field depends on the method.  For example,           */
                         /* OM_GET uses this a a boolean return value, while OM_NEW              */
                         /* uses it as a pointer to the new object.                              */
    geta4();    /* SAS/C and Manx function - makes sure A4 contains global data pointer.         */

    switch (msg->MethodID)
    {
        case OM_NEW:     /* Pass message onto superclass first so it can set aside the memory    */
                         /* for the object and take care of superclass instance data.            */
            if (retval = (APTR)DoSuperMethodA(cl, o, msg))
            {            /************************************************************************/
                         /* For the OM_NEW method, the object pointer passed to the dispatcher   */
                         /* does not point to an object (how could it? The object doesn't exist  */
                         /* yet.)  DoSuperMethodA() returns a pointer to a newly created         */
                         /* object. INST_DATA() is a macro defined in <intuition/classes.h>      */
                         /* that returns a pointer to the object's instance data that is local   */
                         /* to this class. For example, the instance data local to this class    */
                         /* is the RKMModData structure defined above.                           */
                         /************************************************************************/
                mmd = INST_DATA(cl, retval);
                mmd->currval = GetTagData(RKMMOD_CurrVal, 0L, /* initialize object's attributes. */
                                          ((struct opSet *)msg)->ops_AttrList);
                mmd->vallimit = GetTagData(RKMMOD_Limit, DEFAULTVALLIMIT,
                                           ((struct opSet *)msg)->ops_AttrList);
            }
            break;
        case OM_SET:
        case OM_UPDATE:
            mmd = INST_DATA(cl, o);
            DoSuperMethodA(cl, o, msg);   /* Let the superclasses set their attributes first.    */
            {
                struct TagItem *tstate, *ti;    /* grab some temp variables off of the stack.    */

                ti = ((struct opSet *)msg)->ops_AttrList;
                tstate = ti;

                        /* Step through all of the attribute/value pairs in the list.  Use the   */
                        /* utility.library tag functions to do this so they can properly process */
                        /* special tag IDs like TAG_SKIP, TAG_IGNORE, etc.                       */

                while (ti = NextTagItem(&tstate))    /* Step through all of the attribute/value  */
                {                 /* pairs in the list. Use the utility.library tag functions    */
                                  /* to do this so they can properly process special tag IDs     */
                                  /* like TAG_SKIP, TAG_IGNORE, etc.                             */
                    switch (ti->ti_Tag)
                    {
                        case RKMMOD_CurrVal:
                            if ((ti->ti_Data) > mmd->vallimit) ti->ti_Data =
                                    mmd->vallimit;
                            mmd->currval = ti->ti_Data;
                            NotifyCurrVal(cl, o, msg, mmd);
                            retval = (APTR)1L;  /* Changing RKMMOD_CurrVal can cause a visual    */
                            break;              /* change to gadgets in the rkmmodel's broadcast */
                                                /* list.  The rkmmodel has to tell the applica-  */
                                                /* tion by returning a value besides zero.       */
                        case RKMMOD_Up:
                            mmd->currval++;

                                 /* Make sure the current value is not greater than value limit. */
                            if ((mmd->currval) > mmd->vallimit) mmd->currval = mmd->vallimit;
                            NotifyCurrVal(cl, o, msg, mmd);
                            retval = (APTR)1L;  /* Changing RKMMOD_Up can cause a visual         */
                            break;              /* change to gadgets in the rkmmodel's broadcast */
                                                /* list.  The rkmmodel has to tell the applica-  */
                                                /* tion by returning a value besides zero.       */
                        case RKMMOD_Down:
                            mmd->currval--;
                                    /* Make sure currval didn't go negative. */
                            if ((LONG)(mmd->currval) == -1L)
                                mmd->currval = 0L;
                            NotifyCurrVal(cl, o, msg, mmd);
                            retval = (APTR)1L;  /* Changing RKMMOD_Down can cause a visual       */
                            break;              /* change to gadgets in the rkmmodel's broadcast */
                                                /* list.  The rkmmodel has to tell the applica-  */
                                                /* tion by returning a value besides zero.       */
                        case RKMMOD_Limit:
                            mmd->vallimit = ti->ti_Data; /* Set the limit.  Note that this does  */
                            break;                       /* not do bounds checking on the        */
                                                         /* current RKMModData.currval value.    */
                    }
                }
            }
            break;
        case OM_GET:                     /* The only attribute that is "gettable" in this        */
            mmd = INST_DATA(cl, o);      /* class or its superclasses is RKMMOD_CurrVal.         */
            if ((((struct opGet *)msg)->opg_AttrID) == RKMMOD_CurrVal)
            {
                *(((struct opGet *)msg)->opg_Storage) = mmd->currval;
                retval = (Object *)TRUE;
            }
            else retval = (APTR)DoSuperMethodA(cl, o, msg);
            break;
        default:       /* rkmmodelclass does not recognize the methodID, so let the superclass's */
                       /* dispatcher take a look at it.                                          */
            retval = (APTR)DoSuperMethodA(cl, o, msg);
            break;
    }
    return((ULONG)retval);
}

void NotifyCurrVal(Class *cl, Object *o, struct opUpdate *msg, struct RKMModData *mmd)
{
    struct TagItem tt[2];

    tt[0].ti_Tag = RKMMOD_CurrVal; /* make a tag list.  */
    tt[0].ti_Data = mmd->currval;
    tt[1].ti_Tag = TAG_DONE;
                                /* If the RKMMOD_CurrVal changes, we want everyone to know about */
    DoSuperMethod(cl, o,        /* it. Theoretically, the class is supposed to send itself a     */
             OM_NOTIFY,         /* OM_NOTIFY message. Because this class lets its superclass     */
             tt,                /* handle the OM_NOTIFY message, it skips the middleman and      */
             msg->opu_GInfo,    /* sends the OM_NOTIFY directly to its superclass.               */

             ((msg->MethodID == OM_UPDATE) ? (msg->opu_Flags) : 0L)); /* If this is an OM_UPDATE */
                                /* method, make sure the part the OM_UPDATE message adds to the  */
                                /* OM_SET message gets added.  That lets the dispatcher handle   */
}                               /* OM_UPDATE and OM_SET in the same case.                        */


Lib_examples/Talk2boopsi.c

;/* Talk2boopsi.c - Execute me to compile me with SAS/C 5.10b
LC -b1 -cfistq -v -y -j73 Talk2boopsi.c
Blink FROM LIB:c.o,Talk2boopsi.o TO Talk2boopsi LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit ;*/
/* This example creates a Boopsi prop gadget and integer string gadget, connecting them so they */
/* update each other when the user changes their value.  The example program only initializes   */
/* the gadgets and puts them on the window; it doesn't have to interact with them to make them  */
/* talk to each other.                                                                          */

#include <exec/types.h>
#include <utility/tagitem.h>
#include <intuition/intuition.h>
#include <intuition/gadgetclass.h> /* contains IDs for gadget attributes */
#include <intuition/icclass.h>     /* contains ICA_MAP, ICA_TARGET       */
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>

#ifdef LATTICE                     /* Disable SAS/C CTRL/C handling    */
int CXBRK(void) { return(0); }
int chkabort(void) { return(0); }
#endif

UBYTE *vers = "\0$VER: Talk2boopsi 37.1";

struct Library *IntuitionBase;
struct Window *w;
struct IntuiMessage *msg;
struct Gadget *prop, *integer;

/* The attribute mapping lists */
struct TagItem prop2intmap[] =    /* This tells the prop gadget to */
{                                 /* map its PGA_Top attribute to  */
    {PGA_Top,   STRINGA_LongVal}, /* STRINGA_LongVal when it       */
    {TAG_END,}                    /* issues an update about the    */
};                                /* change to its PGA_Top value.  */

struct TagItem int2propmap[] =    /* This tells the string gadget */
{                                 /* to map its STRINGA_LongVal   */
    {STRINGA_LongVal,   PGA_Top}, /* attribute to PGA_Top when it */
    {TAG_END,}                    /* issues an update.            */
};

#define PROPGADGET_ID       1L
#define INTGADGET_ID        2L
#define PROPGADGETWIDTH     10L
#define PROPGADGETHEIGHT    80L
#define INTGADGETHEIGHT     18L
#define VISIBLE             10L
#define TOTAL               100L
#define INITIALVAL          25L
#define MINWINDOWWIDTH      80
#define MINWINDOWHEIGHT     (PROPGADGETHEIGHT + 70)
#define MAXCHARS            3L

void main(void)
{
    BOOL done = FALSE;

    if (IntuitionBase = OpenLibrary("intuition.library", 37L))
    {                                /* Open the window--notice that the window's IDCMP port     */
                                     /* does not listen for GADGETUP messages.                   */
        if (w = OpenWindowTags(NULL,
                 WA_Flags,       WFLG_DEPTHGADGET | WFLG_DRAGBAR |
                                     WFLG_CLOSEGADGET | WFLG_SIZEGADGET,
                 WA_IDCMP,       IDCMP_CLOSEWINDOW,
                 WA_MinWidth,    MINWINDOWWIDTH,
                 WA_MinHeight,   MINWINDOWHEIGHT,
                 TAG_END))
        {                                 /* Create a new propgclass object */
            if (prop = (struct Gadget *)NewObject(NULL, "propgclass",
                GA_ID,     PROPGADGET_ID,        /* These are defined by gadgetclass and         */
                GA_Top,    (w->BorderTop) + 5L,  /* correspond to similarly named fields in      */
                GA_Left,   (w->BorderLeft) + 5L, /* the Gadget structure.                        */
                GA_Width,  PROPGADGETWIDTH,
                GA_Height, PROPGADGETHEIGHT,

                ICA_MAP,      prop2intmap, /* The prop gadget's attribute map */

             /* The rest of this gadget's attributes are defined by propgclass. */
                PGA_Total,     TOTAL,          /* This is the integer range of the prop gadget.  */
                PGA_Top,       INITIALVAL,     /* The initial integer value of the prop gadget.  */

                PGA_Visible,   VISIBLE, /* This determines how much of the prop gadget area is   */
                                        /* covered by the prop gadget's knob, or how much of     */
                                        /* the gadget's TOTAL range is taken up by the prop      */
                                        /* gadget's knob.                                        */

                PGA_NewLook,   TRUE,    /* Use new-look prop gadget imagery */
                TAG_END))
            {                           /* create the integer string gadget.                     */
                if (integer = (struct Gadget *)NewObject(NULL, "strgclass",
                    GA_ID,      INTGADGET_ID,         /* Parameters for the Gadget structure     */
                    GA_Top,     (w->BorderTop) + 5L,
                    GA_Left,    (w->BorderLeft) + PROPGADGETWIDTH + 10L,
                    GA_Width,   MINWINDOWWIDTH -
                                  (w->BorderLeft + w->BorderRight +
                                  PROPGADGETWIDTH + 15L),
                    GA_Height,  INTGADGETHEIGHT,

                    ICA_MAP,    int2propmap,           /* The attribute map */
                    ICA_TARGET, prop,                  /* plus the target.  */

                            /* Th GA_Previous attribute is defined by gadgetclass and is used to */
                            /* wedge a new gadget into a list of gadget's linked by their        */
                            /* Gadget.NextGadget field.  When NewObject() creates this gadget,   */
                            /* it inserts the new gadget into this list behind the GA_Previous   */
                            /* gadget. This attribute is a pointer to the previous gadget        */
                            /* (struct Gadget *).  This attribute cannot be used to link new     */
                            /* gadgetsinto the gadget list of an open window or requester,       */
                    GA_Previous, prop,  /* use AddGList() instead.                               */

                    STRINGA_LongVal,  INITIALVAL, /* These attributes are defined by strgclass.  */
                    STRINGA_MaxChars, MAXCHARS,   /* The first contains the value of the         */
                    TAG_END))                     /* integer string gadget. The second is the    */
                                                  /* maximum number of characters the user is    */
                                                  /* allowed to type into the gadget.            */
                 {
                    SetGadgetAttrs(prop, w, NULL, /* Because the integer string gadget did not   */
                        ICA_TARGET, integer,      /* exist when this example created the prop    */
                        TAG_END);                 /* gadget, it had to wait to set the           */
                                                  /* ICA_Target of the prop gadget.              */

                    AddGList(w, prop, -1, -1, NULL);  /* Add the gadgets to the                  */
                    RefreshGList(prop, w, NULL, -1);  /* window and display them.                */

                    while (done == FALSE)     /* Wait for the user to click */
                    {                         /* the window close gadget.   */
                        WaitPort((struct MsgPort *)w->UserPort);
                        while (msg = (struct IntuiMessage *)
                           GetMsg((struct MsgPort *)w->UserPort))
                        {
                            if (msg->Class == IDCMP_CLOSEWINDOW)
                                done = TRUE;
                            ReplyMsg(msg);
                        }
                    }
                    RemoveGList(w, prop, -1);
                    DisposeObject(integer);
                 }
                DisposeObject(prop);
            }
            CloseWindow(w);
        }
        CloseLibrary(IntuitionBase);
    }
}


Lib_examples/CloseWindowSafely.c

/* This example shows the CloseWindowSafely() function.  Use this
** function to close any windows that share an IDCMP port with another
** window.
**
** CloseWindowSafely.c
**
** these functions close an Intuition window that shares a port with other
** Intuition windows.
**
** We are careful to set the UserPort to NULL before closing, and to free
** any messages that it might have been sent.
*/
#include "exec/types.h"
#include "exec/nodes.h"
#include "exec/lists.h"
#include "exec/ports.h"
#include "intuition/intuition.h"

/*
** function to remove and reply all IntuiMessages on a port that have been
** sent to a particular window (note that we don't rely on the ln_Succ
** pointer of a message after we have replied it)
*/
VOID StripIntuiMessages(struct MsgPort *mp, struct Window *win)
{
struct IntuiMessage *msg;
struct Node *succ;

msg = (struct IntuiMessage *)mp->mp_MsgList.lh_Head;

while (succ = msg->ExecMessage.mn_Node.ln_Succ)
    {
    if (msg->IDCMPWindow == win)
        {
        /* Intuition is about to free this message.
        ** Make sure that we have politely sent it back.
        */
        Remove(msg);

        ReplyMsg(msg);
        }
    msg = (struct IntuiMessage *)succ;
    }
}

/*
** Entry point to CloseWindowSafely()
** Strip all IntuiMessages from an IDCMP which are waiting for a specific
** window.  When the messages are gone, set the UserPort of the window to
** NULL and call ModifyIDCMP(win,0).  This will free the Intuition arts of
** the IDMCMP and trun off message to this port without changing the
** original UserPort (which may be in use by other windows).
*/
VOID CloseWindowSafely(struct Window *win)
{
/* we forbid here to keep out of race conditions with Intuition */
Forbid();

/* send back any messages for this window  that have not yet been
** processed
*/
StripIntuiMessages(win->UserPort, win);

/* clear UserPort so Intuition will not free it */
win->UserPort = NULL;

/* tell Intuition to stop sending more messages */
ModifyIDCMP(win, 0L);

/* turn multitasking back on */
Permit();

/* Now it's safe to really close the window */
CloseWindow(win);
}


Lib_examples/PopShell.c

;/* PopShell.c - Simple hot key commodity compiled with SASC 5.10
LC -b0 -cfist -v -j73 popshell.c
Blink FROM LIB:c.o,popshell.o TO popshell LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
*/
#include <exec/libraries.h>
#include <libraries/commodities.h>
#include <dos/dos.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/alib_stdio_protos.h>
#include <clib/commodities_protos.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }
#endif

void main(int, char **);
void ProcessMsg(void);

#define EVT_HOTKEY 1L
struct Library *CxBase, *IconBase;
struct MsgPort *broker_mp;
CxObj *broker, *filter, *sender, *translate;

struct NewBroker newbroker =
{
    NB_VERSION,
    "RKM PopShell",           /* string to identify this broker */
    "A Simple PopShell",
    "A simple PopShell commodity",
    NBU_UNIQUE | NBU_NOTIFY,      /* Don't want any new commodities starting with this name. */
    0, 0, 0, 0                    /* If someone tries it, let me know */
};

UBYTE *newshell = "\rllehswen";  /* "newshell" spelled backwards */
struct InputEvent *ie;
ULONG cxsigflag;

void main(int argc, char **argv)
{
    UBYTE *hotkey, **ttypes;
    CxMsg *msg;

    if (CxBase = OpenLibrary("commodities.library", 37L))
    {
        if (IconBase = OpenLibrary("icon.library", 36L))
        {
            if (broker_mp = CreateMsgPort())
            {
                newbroker.nb_Port = broker_mp;
                cxsigflag = 1L << broker_mp->mp_SigBit;
                ttypes = ArgArrayInit(argc, argv);
                newbroker.nb_Pri = (BYTE)ArgInt(ttypes, "CX_PRIORITY", 0);
                hotkey = ArgString(ttypes, "HOTKEY", "rawkey control esc");

                if (broker = CxBroker(&newbroker, NULL))
                {
                    /* HotKey() is an amiga.lib function that creates a filter, sender */
                    /* and translate CxObject and connects them to report a hot key    */
                    /* press and delete its input event. */
                    if (filter = HotKey(hotkey, broker_mp, EVT_HOTKEY))
                    {
                        AttachCxObj(broker, filter); /* Add a CxObject to another's personal list */

                        if (! CxObjError(filter))
                        {
                            /* InvertString() is an amiga.lib function that creates a linked */
                            /* list of input events which would translate into the string    */
                            /* passed to it.  Note that it puts the input events in the      */
                            /* opposite order in which the corresponding letters appear in   */
                            /* the string.  A translate CxObject expects them backwards.     */
                            if (ie = InvertString(newshell, NULL))
                            {
                                ActivateCxObj(broker, 1L);
                                ProcessMsg();
                                /* we have to release the memory allocated by InvertString.       */
                                FreeIEvents(ie);
                            }
                        }
                    }
                    /* DeleteCxObjAll() is a commodities.library function that not only      */
                    /* deletes the CxObject pointed to in its argument, but deletes all of   */
                    /* the CxObjects attached to it.                                         */
                    DeleteCxObjAll(broker);

                    /* Empty the port of all CxMsgs */
                    while(msg = (CxMsg *)GetMsg(broker_mp))
                        ReplyMsg((struct Message *)msg);
                }
                DeletePort(broker_mp);
            }
            ArgArrayDone();  /* this amiga.lib function cleans up after ArgArrayInit() */
            CloseLibrary(IconBase);
        }
        CloseLibrary(CxBase);
    }
}

void ProcessMsg(void)
{
    extern struct MsgPort *broker_mp;
    extern CxObj *broker;
    extern ULONG cxsigflag;
    CxMsg *msg;
    ULONG sigrcvd, msgid, msgtype;
    LONG returnvalue = 1L;

    while (returnvalue)
    {
        sigrcvd = Wait(SIGBREAKF_CTRL_C | cxsigflag);

        while(msg = (CxMsg *)GetMsg(broker_mp))
        {
            msgid = CxMsgID(msg);
            msgtype = CxMsgType(msg);
            ReplyMsg((struct Message *)msg);

            switch(msgtype)
            {
                case CXM_IEVENT:
                    printf("A CXM_EVENT, ");
                    switch(msgid)
                    {
                        case EVT_HOTKEY:
                            /* We got the message from the sender CxObject */
                            printf("You hit the HotKey.\n");
                            /* Add the string "newshell" to input * stream.  If a shell       */
                            /* gets it, it'll open a new shell.                               */
                            AddIEvents(ie);
                            break;
                        default:
                            printf("unknown.\n");
                            break;
                    }
                    break;
                case CXM_COMMAND:
                    printf("A command: ");
                    switch(msgid)
                    {
                        case CXCMD_DISABLE:
                            printf("CXCMD_DISABLE\n");
                            ActivateCxObj(broker, 0L);
                            break;
                        case CXCMD_ENABLE:
                            printf("CXCMD_ENABLE\n");
                            ActivateCxObj(broker, 1L);
                            break;
                        case CXCMD_KILL:
                            printf("CXCMD_KILL\n");
                            returnvalue = 0L;
                            break;
                        case CXCMD_UNIQUE:
                        /* Commodities Exchange can be told not only to refuse to launch a    */
                        /* commodity with a name already in use but also can notify the       */
                        /* already running commodity that it happened.  It does this by       */
                        /* sending a CXM_COMMAND with the ID set to CXMCMD_UNIQUE.  If the    */
                        /* user tries to run a windowless commodity that is already running,  */
                        /* the user wants the commodity to shut down.                         */
                            printf("CXCMD_UNIQUE\n");
                            returnvalue = 0L;
                            break;
                        default:
                            printf("Unknown msgid\n");
                            break;
                    }
                    break;
                default:
                    printf("Unknown msgtype\n");
                    break;
            }
        }

        if (sigrcvd & SIGBREAKF_CTRL_C)
        {
            returnvalue = 0L;
            printf("CTRL C signal break\n");
        }
    }
}


Lib_examples/divert.c

;/* divert.c - commodity to monitor user inactivity - compiled with SASC 5.10
LC -b0 -cfist -v -j73 divert.c
Blink FROM LIB:c.o,divert.o TO divert LIBRARY LIB:LC.lib,LIB:Amiga.lib NODEBUG SC SD
quit; */
#include <exec/libraries.h>
#include <libraries/commodities.h>
#include <dos/dos.h>
#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/alib_stdio_protos.h>
#include <clib/commodities_protos.h>
#include <devices/inputevent.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }
#endif

#define TIMER_CLICKS 100

void main(int, char **);
void ProcessMsg(void);
void CxFunction(CxMsg *, CxObj *);

struct Library *CxBase, *IconBase;
struct MsgPort *broker_mp;
CxObj *broker, *cocustom, *cosignal;

struct NewBroker newbroker =
{
    NB_VERSION,
    "Divert",           /* string to identify this broker */
    "Divert",
    "show divert",
    NBU_UNIQUE | NBU_NOTIFY,  /* Don't want any new commodities starting with this name. */
    0, 0, 0, 0                /* If someone tries it, let me know                        */
};

struct Task *task;
ULONG cxsigflag, signal, cxobjsignal;

void main(int argc, char **argv)
{
    UBYTE **ttypes;
    CxMsg *msg;

    if (CxBase = OpenLibrary("commodities.library", 37L))
    {
        /* open the icon.library for support library functions, ArgArrayInit() and ArgArrayDone() */
        if (IconBase = OpenLibrary("icon.library", 36L))
        {
            if (broker_mp = CreateMsgPort())
            {
                newbroker.nb_Port = broker_mp;
                cxsigflag = 1L << broker_mp->mp_SigBit;

                /* ArgArrayInit() is a support library function (in the 2.0 version of amiga.lib) */
                /* that makes it easy to read arguments from either a CLI or from Workbench's     */
                /* ToolTypes. Because it uses icon.library, the library has to be open before     */
                /* before calling this function.  ArgArrayDone() cleans up after this function.   */
                ttypes = ArgArrayInit(argc, argv);

                /* ArgInt() (in amiga.lib) searches through the array set up by ArgArrayInit()    */
                /* for a specific ToolType.  If it finds one, it returns the numeric value of the */
                /* number that followed the ToolType (i.e., CX_PRIORITY=7).  If it  doesn't find  */
                /* the ToolType, it returns the default value (the third argument)                */
                newbroker.nb_Pri = (BYTE)ArgInt(ttypes, "CX_PRIORITY", 0);

                if (broker = CxBroker(&newbroker, NULL))
                {
                    /* CxCustom() takes two arguments, a pointer to the custom function           */
                    /* and an ID. Commodities Exchange will assign that ID to any CxMsg           */
                    /* passed to the custom  function.                                            */
                    if (cocustom = CxCustom(CxFunction, 0L))
                    {
                        AttachCxObj(broker, cocustom);

                        /* Allocate a signal bit for the signal CxObj */
                        if ( (signal = (ULONG)AllocSignal(-1L)) != -1)
                        {
                            /* set up the signal mask */
                            cxobjsignal = 1L << signal;
                            cxsigflag |= cxobjsignal;

                            /* CxSignal takes two arguments, a pointer to the task to signal      */
                            /* (normally the commodity) and the number of the signal bit the      */
                            /* commodity acquired to signal with.                                 */
                            task = FindTask(NULL);
                            if (cosignal = CxSignal(task, signal))
                            {
                                AttachCxObj(cocustom, cosignal);
                                ActivateCxObj(broker, 1L);
                                ProcessMsg();
                            }
                            FreeSignal(signal);
                        }
                    }
                    /* DeleteCxObjAll() is a commodities.library function that not only deletes   */
                    /* the CxObject pointed to in its argument, but it deletes all of the         */
                    /* CxObjects that are attached to it.                                         */
                    DeleteCxObjAll(broker);

                    /* Empty the port of all CxMsgs */
                    while(msg = (CxMsg *)GetMsg(broker_mp))
                        ReplyMsg((struct Message *)msg);
                }
                DeletePort(broker_mp);
            }
            ArgArrayDone();   /* this amiga.lib function cleans up after ArgArrayInit()           */
            CloseLibrary(IconBase);
        }
        CloseLibrary(CxBase);
    }
}

void ProcessMsg(void)
{
    extern struct MsgPort *broker_mp;
    extern CxObj *broker;
    extern ULONG cxsigflag;
    CxMsg *msg;
    ULONG sigrcvd, msgid;
    LONG returnvalue = 1L;

    while (returnvalue)
    {
        sigrcvd = Wait(SIGBREAKF_CTRL_C | cxsigflag);

        while(msg = (CxMsg *)GetMsg(broker_mp))
        {
            msgid = CxMsgID(msg);
            ReplyMsg((struct Message *)msg);

            switch(msgid)
            {
                case CXCMD_DISABLE:
                    ActivateCxObj(broker, 0L);
                    break;
                case CXCMD_ENABLE:
                    ActivateCxObj(broker, 1L);
                    break;
                case CXCMD_KILL:
                    returnvalue = 0L;
                    break;
                case CXCMD_UNIQUE:
                    returnvalue = 0L;
                    break;
            }
        }

        if (sigrcvd & SIGBREAKF_CTRL_C) returnvalue = 0L;

        /* Check to see if the signal CxObj signalled us. */
        if (sigrcvd & cxobjsignal) printf("Got Signal\n");
    }
}

/* The custom function for the custom CxObject.  Any code for a custom CxObj must be short        */
/* and sweet because it runs as part of the input.device task.                                    */
void CxFunction(register CxMsg *cxm, CxObj *co)
{
    struct InputEvent *ie;
    static ULONG time = 0L;

    /* Get the struct InputEvent associated with this CxMsg. Unlike the InputEvent                */
    /* extracted from a CxSender's CxMsg, this is a *REAL* input event, be careful with it.       */
    ie = (struct InputEvent *)CxMsgData(cxm);

    /* This custom function counts the number of timer events that go by while no other input     */
    /* events occur.  If it counts more than a certain amount of timer events, it clears the      */
    /* count and diverts the timer event CxMsg to the custom object's personal                    */
    /* list.  If an event besides a timer event passes by, the timer event count is reset.        */
    if (ie->ie_Class == IECLASS_TIMER)
    {
        time++;
        if (time >= TIMER_CLICKS)
        {
            time = 0L;
            DivertCxMsg(cxm, co, co);
        }
    }
    else
        time = 0L;
}


Lib_examples/broker.c

/* The example below, Broker.c, receives input from one source, the
 * controller program.  The controller program sends a CxMessage each
 * time the user clicks its Enable, Disable, or Kill gadgets.  Using the
 * CxMsgID() function, the commodity finds out what the command is and
 * executes it.
 *
 * broker.c - Simple skeletal example of opening a broker
 *
 * compiled with SASC 5.10
 * LC -b0 -cfist -v broker.c
 * Blink FROM LIB:c.o,broker.o TO broker LIBRARY LIB:LC.lib,LIB:Amiga.lib
 */
#include <exec/libraries.h>
#include <libraries/commodities.h>
#include <dos/dos.h>
#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/alib_stdio_protos.h>
#include <clib/commodities_protos.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }
#endif

void main(void);
void ProcessMsg(void);

struct Library *CxBase;

CxObj *broker;
struct MsgPort *broker_mp;
ULONG cxsigflag;

struct NewBroker newbroker = {
    NB_VERSION,   /* nb_Version - Version of the NewBroker structure */
    "RKM broker", /* nb_Name - Name Commodities uses to identify this commodity */
    "Broker",     /* nb_Title - Title of commodity that appears in CXExchange */
    "A simple example of a broker",  /* nb_Descr - Description of the commodity */
    0,            /* nb_Unique - Tells CX not to launch another commodity with same name */
    0,            /* nb_Flags - Tells CX if this commodity has a window */
    0,            /* nb_Pri - This commodity's priority */
    0,            /* nb_Port - MsgPort CX talks to */
    0             /* nb_ReservedChannel - reserved for later use */
};

void main(void)
{
    CxMsg *msg;

    /* Before bothering with anything else, open the library */
    if (CxBase = OpenLibrary("commodities.library", 37L))
    {
        /* Commodities talks to a Commodities application through */
        /* an Exec Message port, which the application provides   */
        if (broker_mp = CreateMsgPort())
        {
            newbroker.nb_Port = broker_mp;

            /* The commodities.library function CxBroker() adds a borker to the
             * master list.  It takes two arguments, a pointer to a NewBroker
             * structure and a pointer to a LONG.  The NewBroker structure contains
             * information to set up the broker.  If the second argument is not
             * NULL, CxBroker will fill it in with an error code.
             */
            if (broker = CxBroker(&newbroker, NULL))
            {
                cxsigflag = 1L << broker_mp->mp_SigBit;

                /* After it's set up correctly, the broker has to be activated */
                ActivateCxObj(broker, 1L);

                /* the main processing loop */
                ProcessMsg();

                /* It's time to clean up.  Start by removing the broker from the
                 * Commodities master list.  The DeleteCxObjAll() function will
                 * take care of removing a CxObject and all those connected
                 * to it from the Commodities network
                 */
                DeleteCxObj(broker);

                /* Empty the port of CxMsgs */
                while(msg = (CxMsg *)GetMsg(broker_mp))
                    ReplyMsg((struct Message *)msg);
            }
            DeletePort(broker_mp);
        }
        CloseLibrary(CxBase);
    }
}

void ProcessMsg(void)
{
    CxMsg *msg;

    ULONG sigrcvd, msgid, msgtype;
    LONG returnvalue = 1L;

    while (returnvalue)
    {
        /* wait for something to happen */
        sigrcvd = Wait(SIGBREAKF_CTRL_C | cxsigflag);

        /* process any messages */
        while(msg = (CxMsg *)GetMsg(broker_mp))
        {
            /* Extract necessary information from the CxMessage and return it */
            msgid = CxMsgID(msg);
            msgtype = CxMsgType(msg);
            ReplyMsg((struct Message *)msg);

            switch(msgtype)
            {
                case CXM_IEVENT:
                    /* Shouldn't get any of these in this example */
                    break;
                case CXM_COMMAND:
                    /* Commodities has sent a command */
                    printf("A command: ");
                    switch(msgid)
                    {
                        case CXCMD_DISABLE:
                            printf("CXCMD_DISABLE\n");
                            /* The user clicked Commodities Exchange disable
                             * gadget better disable
                             */
                            ActivateCxObj(broker, 0L);
                            break;
                        case CXCMD_ENABLE:
                            /* user clicked enable gadget */
                            printf("CXCMD_ENABLE\n");
                            ActivateCxObj(broker, 1L);
                            break;
                        case CXCMD_KILL:
                            /* user clicked kill gadget, better quit */
                            printf("CXCMD_KILL\n");
                            returnvalue = 0L;
                            break;
                    }
                    break;
                default:
                    printf("Unknown msgtype\n");
                    break;
            }
        }
        /* Test to see if user tried to break */
        if (sigrcvd & SIGBREAKF_CTRL_C)
        {
            returnvalue = 0L;
            printf("CTRL C signal break\n");
        }
    }
}

/* Notice that Broker.c uses Ctrl-C as a break key.  The break key for
** any commodity should be Ctrl-C.
*/


Lib_examples/HotKey.c

;/* HotKey.c - Simple hot key commodity compiled with SASC 5.10
LC -b0 -cfist -v -j73 hotkey.c
Blink FROM LIB:c.o,hotkey.o TO hotkey LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
 */
#include <exec/libraries.h>
#include <libraries/commodities.h>
#include <dos/dos.h>
#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/alib_stdio_protos.h>
#include <clib/commodities_protos.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }
#endif

#define EVT_HOTKEY 1L

void main(int, char **);
void ProcessMsg(void);

struct Library *CxBase, *IconBase;
struct MsgPort *broker_mp;
CxObj *broker, *filter, *sender, *translate;

struct NewBroker newbroker = {
    NB_VERSION,
    "RKM HotKey",           /* string to identify this broker */
    "A Simple HotKey",
    "A simple hot key commodity",
    NBU_UNIQUE | NBU_NOTIFY,    /* Don't want any new commodities starting with this name. */
    0, 0, 0, 0                  /* If someone tries it, let me know */
};

ULONG cxsigflag;

void main(int argc, char **argv)
{
    UBYTE *hotkey, **ttypes;
    CxMsg *msg;

    if (CxBase = OpenLibrary("commodities.library", 37L))
    {
        /* open the icon.library for the support library */
        /* functions, ArgArrayInit() and ArgArrayDone()  */
        if (IconBase = OpenLibrary("icon.library", 36L))
        {
            if (broker_mp = CreateMsgPort())
            {
                newbroker.nb_Port = broker_mp;
                cxsigflag = 1L << broker_mp->mp_SigBit;

                /* ArgArrayInit() is a support library function (from the 2.0 version
                 * of amiga.lib) that makes it easy to read arguments from either a
                 * CLI or from Workbench's ToolTypes.  Because it uses icon.library,
                 * the library has to be open before calling this function.
                 * ArgArrayDone() cleans up after this function.
                 */
                ttypes = ArgArrayInit(argc, argv);

                /* ArgInt() (also from amiga.lib) searches through the array set up
                 * by ArgArrayInit() for a specific ToolType.  If it finds one, it
                 * returns the numeric value of the number that followed the
                 * ToolType (i.e., CX_PRIORITY=7). If it doesn't find the ToolType,
                 * it returns the default value (the third argument)
                 */
                newbroker.nb_Pri = (BYTE)ArgInt(ttypes, "CX_PRIORITY", 0);

                /* ArgString() works just like ArgInt(), except it returns a pointer to a string
                 * rather than an integer. In the example below, if there is no ToolType
                 * "HOTKEY", the function returns a pointer to "rawkey control esc".
                 */
                hotkey = ArgString(ttypes, "HOTKEY", "rawkey control esc");

                if (broker = CxBroker(&newbroker, NULL))
                {
                    /* CxFilter() is a macro that creates a filter CxObject.  This filter
                     * passes input events that match the string pointed to by hotkey.
                     */
                    if (filter = CxFilter(hotkey))
                    {
                        /* Add a CxObject to another's personal list */
                        AttachCxObj(broker, filter);

                        /* CxSender() creates a sender CxObject.  Every time a sender gets
                         * a CxMessage, it sends a new CxMessage to the port pointed to in
                         * the first argument. CxSender()'s second argument will be the ID
                         * of any CxMessages the sender sends to the port.  The data pointer
                         * associated with the CxMessage will point to a *COPY* of the
                         * InputEvent structure associated with the orginal CxMessage.
                         */
                        if (sender = CxSender(broker_mp, EVT_HOTKEY))
                        {
                            AttachCxObj(filter, sender);

                            /* CxTranslate() creates a translate CxObject. When a translate
                             * CxObject gets a CxMessage, it deletes the original CxMessage
                             * and adds a new input event to the input.device's input stream
                             * after the Commodities input handler. CxTranslate's argument
                             * points to an InputEvent structure from which to create the new
                             * input event.  In this example, the pointer is NULL, meaning no
                             * new event should be introduced, which causes any event that
                             * reaches this object to disappear from the input stream.
                             */
                            if (translate = (CxTranslate(NULL)))
                            {
                                AttachCxObj(filter, translate);

                                /* CxObjError() is a commodities.library function that returns
                                 * the internal accumulated error code of a CxObject.
                                 */
                                if (! CxObjError(filter))
                                {
                                    ActivateCxObj(broker, 1L);
                                    ProcessMsg();
                                }
                            }
                        }
                    }
                    /* DeleteCxObjAll() is a commodities.library function that not only
                     * deletes the CxObject pointed to in its argument, but it deletes
                     * all of the CxObjects that are attached to it.
                     */
                    DeleteCxObjAll(broker);

                    /* Empty the port of all CxMsgs */
                    while(msg = (CxMsg *)GetMsg(broker_mp))
                        ReplyMsg((struct Message *)msg);
                }
                DeletePort(broker_mp);
            }
            /* this amiga.lib function cleans up after ArgArrayInit() */
            ArgArrayDone();
            CloseLibrary(IconBase);
        }
        CloseLibrary(CxBase);
    }
}
void ProcessMsg(void)
{
    extern struct MsgPort *broker_mp;
    extern CxObj *broker;
    extern ULONG cxsigflag;
    CxMsg *msg;
    ULONG sigrcvd, msgid, msgtype;
    LONG returnvalue = 1L;

    while(returnvalue)
    {
        sigrcvd = Wait(SIGBREAKF_CTRL_C | cxsigflag);

        while(msg = (CxMsg *)GetMsg(broker_mp))
        {
            msgid = CxMsgID(msg);
            msgtype = CxMsgType(msg);
            ReplyMsg((struct Message *)msg);

            switch(msgtype)
            {
                case CXM_IEVENT:
                    printf("A CXM_EVENT, ");
                    switch(msgid)
                    {
                        case EVT_HOTKEY: /* We got the message from the sender CxObject */
                            printf("You hit the HotKey.\n");
                            break;
                        default:
                            printf("unknown.\n");
                            break;
                    }
                    break;
                case CXM_COMMAND:
                    printf("A command: ");
                    switch(msgid)
                    {
                        case CXCMD_DISABLE:
                            printf("CXCMD_DISABLE\n");
                            ActivateCxObj(broker, 0L);
                            break;
                        case CXCMD_ENABLE:
                            printf("CXCMD_ENABLE\n");
                            ActivateCxObj(broker, 1L);
                            break;
                        case CXCMD_KILL:
                            printf("CXCMD_KILL\n");
                            returnvalue = 0L;
                            break;
                        case CXCMD_UNIQUE:
                        /* Commodities Exchange can be told not only to refuse to launch a
                         * commodity with a name already in use but also can notify the
                         * already running commodity that it happened. It does this by
                         * sending a CXM_COMMAND with the ID set to CXMCMD_UNIQUE.  If the
                         * user tries to run a windowless commodity that is already running,
                         * the user wants the commodity to shut down. */
                            printf("CXCMD_UNIQUE\n");
                            returnvalue = 0L;
                            break;
                        default:
                            printf("Unknown msgid\n");
                            break;
                    }
                    break;
                default:
                    printf("Unknown msgtype\n");
                    break;
            }
        }
        if (sigrcvd & SIGBREAKF_CTRL_C)
        {
            returnvalue = 0L;
            printf("CTRL C signal break\n");
        }
    }
}


Lib_examples/a2d.c

;/* a2d.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfis -j73 a2d.c
Blink FROM LIB:c.o,a2d.o TO a2d LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
*/
    #include <exec/types.h>
    #include <exec/memory.h>
    #include <dos/datetime.h>
    #include <devices/timer.h>

    #include <clib/exec_protos.h>
    #include <clib/timer_protos.h>
    #include <clib/utility_protos.h>

    #include <stdio.h>

    LONG main(void);

    struct Library *TimerBase;
    struct Library *UtilityBase;

    LONG main(void)
    {
      struct ClockData *clockdata;
      struct timerequest *tr;
      struct timeval *tv;
      LONG seconds;

      if (UtilityBase = OpenLibrary("utility.library", 37))
      {
        if (tr = AllocMem(sizeof(struct timerequest), MEMF_CLEAR))
        {
          if (tv = AllocMem(sizeof(struct timeval), MEMF_CLEAR))
          {
            if (clockdata = AllocMem(sizeof(struct ClockData), MEMF_CLEAR))
            {
              if (!(OpenDevice("timer.device", UNIT_VBLANK, (struct IORequest *)tr, 0) ))
              {
                TimerBase = tr->tr_node.io_Device;

                GetSysTime(tv);

                printf("GetSysTime():\t%d %d\n", tv->tv_secs, tv->tv_micro);

                Amiga2Date(tv->tv_secs, clockdata);

                printf("Amiga2Date():  sec %d min %d hour %d\n", clockdata->sec,
                        clockdata->min, clockdata->hour);

                printf("               mday %d month %d year %d wday %d\n", clockdata->mday,
                       clockdata->month, clockdata->year, clockdata->wday);

                seconds = CheckDate(clockdata);

                printf("CheckDate():\t%ld\n", seconds);

                seconds = Date2Amiga(clockdata);

                printf("Date2Amiga():\t%ld\n", seconds);

                CloseDevice((struct IORequest *)tr);
              }
              FreeMem(clockdata, sizeof(struct ClockData));
            }
            FreeMem(tv, sizeof(struct timeval));
          }
          FreeMem(tr, sizeof(struct timerequest));
        }
        CloseLibrary(UtilityBase);
      }
    }


Lib_examples/prefnotify.c

;/* prefnotify.c.  - Execute me to compile me with SAS/C 5.10
lc -cfistq -v -y -j73 prefnotify.c
blink from LIB:c.o,prefnotify.o to prefnotify lib LIB:LC.lib LIB:amiga.lib
quit

** prefnotify.c - notified if serial prefs change
*/

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <dos/notify.h>

#include <stdio.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

#define PREFSFILENAME "ENV:sys/serial.prefs"

static UBYTE   *VersTag = "\0$VER: prefnot 37.1 (09.07.91)";

extern struct Library *DOSBase;

void main(int argc, char **argv)
{
BOOL done=FALSE;
struct NotifyRequest *notifyrequest;
UBYTE          *filename;
LONG           signum;
ULONG          signals;

/* We need at least V37 for notification */
if (DOSBase->lib_Version >= 37)
    {
    /* Allocate a NotifyRequest structure */
    if (notifyrequest = AllocMem(sizeof(struct NotifyRequest), MEMF_CLEAR))
        {
        /* And allocate a signalsbit */
        if ((signum = AllocSignal(-1L)) != -1)
            {
            /* Initialize notification request */
            filename = PREFSFILENAME;
            notifyrequest->nr_Name = filename;
            notifyrequest->nr_Flags = NRF_SEND_SIGNAL;
            /* Signal this task */
            notifyrequest->nr_stuff.nr_Signal.nr_Task = (struct Task *) FindTask(NULL);
            /* with this signals bit */
            notifyrequest->nr_stuff.nr_Signal.nr_SignalNum = signum;

            if ((StartNotify(notifyrequest)) == DOSTRUE)
                {
                printf("Select Serial Prefs SAVE or USE to notify this program\n");
                printf("CTRL-C to exit\n\n");
                /* Loop until Ctrl-C to exit */
                while(!done)
                    {
                    signals = Wait(  (1L << signum) | SIGBREAKF_CTRL_C  );
                    if (signals & (1L << signum))
                        printf("Notification signal received.\n");
                    if (signals & SIGBREAKF_CTRL_C)
                        {
                        EndNotify(notifyrequest);
                        done=TRUE;
                        }
                    }
                }
            else printf("Can't start notification\n");
            FreeSignal(signum);
            }
        else printf("No signals available\n");
        FreeMem(notifyrequest, sizeof(struct NotifyRequest));
        }
    else printf("Not enough memory for NotifyRequest.\n");
    }
else printf("Requires at least V37 dos.library\n");
}


Lib_examples/eventloop.c

;/* eventloop.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 eventloop.c
Blink FROM LIB:c.o,eventloop.o TO eventloop LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
**
** This example shows how to receive Intuition events.  It reports on a
** variety of events: close window, keyboard, disk insertion and removal,
** select button up and down and menu button up and down.  Note that the
** menu button events will only be received by the program if the
** WA_RMBTrap attribute is set for the window.
**
** eventloop.c - standard technique to handle IntuiMessages from an IDCMP.
*/
#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <intuition/intuition.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

/* our function prototypes */
BOOL handleIDCMP(struct Window *win, BOOL done);

struct Library *IntuitionBase = NULL;

/*
** main routine.
** Open required library and window, then process the events from the
** window.  Free all resources when done.
*/
VOID main(int argc, char **argv)
{
ULONG signals;
UBYTE done;
struct Window *win;

IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37);
if (IntuitionBase != NULL)
    {
    if (win = OpenWindowTags(NULL,
                        WA_Title,       "Press Keys and Mouse in this Window",
                        WA_Width,       500,
                        WA_Height,      50,
                        WA_Activate,    TRUE,
                        WA_CloseGadget, TRUE,
                        WA_RMBTrap,     TRUE,
                        WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY |
                            IDCMP_RAWKEY | IDCMP_DISKINSERTED |
                            IDCMP_DISKREMOVED | IDCMP_MOUSEBUTTONS,
                        TAG_END))
        {
        done = FALSE;

        /* perform this loop until the message handling routine signals
        ** that we are done.
        **
        ** When the Wait() returns, check which signal hit and process
        ** the correct port.  There is only one port here, so the test
        ** could be eliminated.  If multiple ports were being watched,
        ** the test would become:
        **
        **    signals = Wait( (1L << win1->UserPort->mp_SigBit) |
        **                    (1L << win2->UserPort->mp_SigBit) |
        **                    (1L << win3->UserPort->mp_SigBit))
        **    if (signals & (1L << win1->UserPort->mp_SigBit))
        **        done = handleWin1IDCMP(win1,done);
        **    else if (signals & (1L << win2->UserPort->mp_SigBit))
        **        done = handleWin2IDCMP(win2,done);
        **    else if (signals & (1L << win3->UserPort->mp_SigBit))
        **        done = handleWin3IDCMP(win3,done);
        **
        ** Note that these could all call the same routine with different
        ** window pointers (if the handling was identical).
        **
        ** handleIDCMP() should remove all of the messages from the port.
        */
        while (!done)
            {
            signals = Wait(1L << win->UserPort->mp_SigBit);
            if (signals & (1L << win->UserPort->mp_SigBit))
                done = handleIDCMP(win,done);
            };
        CloseWindow(win);
        }
    CloseLibrary(IntuitionBase);
    }
}

/*
** handleIDCMP() - handle all of the messages from an IDCMP.
*/
BOOL handleIDCMP(struct Window *win, BOOL done)
{
struct IntuiMessage *message;
USHORT code;
SHORT mousex, mousey;
ULONG class;

/* Remove all of the messages from the port by calling GetMsg()
** until it returns NULL.
**
** The code should be able to handle three cases:
**
** 1.  No messages waiting at the port, and the first call to GetMsg()
** returns NULL.  In this case the code should do nothing.
**
** 2.  A single message waiting.  The code should remove the message,
** processes it, and finish.
**
** 3.  Multiple messages waiting.  The code should process each waiting
** message, and finish.
*/
while (NULL != (message = (struct IntuiMessage *)GetMsg(win->UserPort)))
    {
    /* It is often convenient to copy the data out of the message.
    ** In many cases, this lets the application reply to the message
    ** quickly.  Copying the data is not required, if the code does
    ** not reply to the message until the end of the loop, then
    ** it may directly reference the message information anywhere
    ** before the reply.
    */
    class  = message->Class;
    code   = message->Code;
    mousex = message->MouseX;
    mousey = message->MouseY;

    /* The loop should reply as soon as possible.  Note that the code
    ** may not reference data in the message after replying to the
    ** message.  Thus, the application should not reply to the message
    ** until it is done referencing information in it.
    **
    ** Be sure to reply to every message received with GetMsg().
    */
    ReplyMsg((struct Message *)message);

    /* The class contains the IDCMP type of the message. */
    switch (class)
        {
        case IDCMP_CLOSEWINDOW:
            done = TRUE;
            break;
        case IDCMP_VANILLAKEY:
            printf("IDCMP_VANILLAKEY (%lc)\n",code);
            break;
        case IDCMP_RAWKEY:
            printf("IDCMP_RAWKEY\n");
            break;
        case IDCMP_DISKINSERTED:
            printf("IDCMP_DISKINSERTED\n");
            break;
        case IDCMP_DISKREMOVED:
            printf("IDCMP_DISKREMOVED\n");
            break;
        case IDCMP_MOUSEBUTTONS:
            /* the code often contains useful data, such as the ASCII
            ** value (for IDCMP_VANILLAKEY), or the type of button
            ** event here.
            */
            switch (code)
                {
                case SELECTUP:
                    printf("SELECTUP at %d,%d\n",mousex,mousey);
                    break;
                case SELECTDOWN:
                    printf("SELECTDOWN at %d,%d\n",mousex,mousey);
                    break;
                case MENUUP:
                    printf("MENUUP\n");
                    break;
                case MENUDOWN:
                    printf("MENUDOWN\n");
                    break;
                default:
                    printf("UNKNOWN CODE\n");
                    break;
                }
            break;
        default:
            printf("Unknown IDCMP message\n");
            break;
        }
    }
return(done);
}


Lib_examples/buildlist.c

;/* buildlist.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 buildlist.c
Blink FROM LIB:c.o,buildlist.o TO buildlist LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit

** The code below demonstrates the concepts and functions discussed in this
** chapter by building an application-defined Exec List.
**
** buildlist.c - example which uses an application-specific Exec list
*/

#include <exec/types.h>
#include <exec/lists.h>
#include <exec/nodes.h>
#include <exec/memory.h>

#include <clib/alib_protos.h>
#include <clib/exec_protos.h>

#include <string.h>
#include <stdio.h>

#ifdef LATTICE
int CXBRK(void)  { return(0); }  /* Disable Lattice CTRL/C handling */
void chkabort(void) { return; }  /* really */
#endif

/* Our function prototypes */
VOID AddName(struct List *, UBYTE *);
VOID FreeNameNodes(struct List *);
VOID DisplayNameList(struct List *);
VOID DisplayName(struct List *, UBYTE *);

struct NameNode {
    struct Node nn_Node;        /* System Node structure */
    UBYTE  nn_Data[62];         /* Node-specific data */
};

#define NAMENODE_ID   100       /* The type of "NameNode" */

VOID main(VOID)
{
    struct  List    *NameList;    /* Note that a MinList would also work */

    if (!( NameList = AllocMem(sizeof(struct List),MEMF_CLEAR)) )
        printf("Out of memory\n");
    else {
        NewList(NameList);        /* Important: prepare header for use */

        AddName(NameList,"Name7");   AddName(NameList,"Name6");
        AddName(NameList,"Name5");   AddName(NameList,"Name4");
        AddName(NameList,"Name2");   AddName(NameList,"Name0");

        AddName(NameList,"Name7");   AddName(NameList,"Name5");
        AddName(NameList,"Name3");   AddName(NameList,"Name1");

        DisplayName(NameList,"Name5");
        DisplayNameList(NameList);

        FreeNameNodes(NameList);
        FreeMem(NameList,sizeof(struct List));  /* Free list header */
    }
}

/* Allocate a NameNode structure, copy the given name into the structure,
 * then add it the specified list.  This example does not provide an
 * error return for the out of memory condition.
*/
VOID AddName(struct List *list, UBYTE *name)
{
    struct NameNode *namenode;

    if (!( namenode = AllocMem(sizeof(struct NameNode),MEMF_CLEAR) ))
        printf("Out of memory\n");
    else {
        strcpy(namenode->nn_Data,name);
        namenode->nn_Node.ln_Name = namenode->nn_Data;
        namenode->nn_Node.ln_Type = NAMENODE_ID;
        namenode->nn_Node.ln_Pri  = 0;
        AddHead((struct List *)list,(struct Node *)namenode);
    }
}

/*
 * Free the entire list, including the header.  The header is not updated
 * as the list is freed.  This function demonstrates how to avoid
 * referencing freed memory when deallocating nodes.
 */
VOID FreeNameNodes(struct List *list)
{
    struct NameNode *worknode;
    struct NameNode *nextnode;

    worknode = (struct NameNode *)(list->lh_Head); /* First node */
    while (nextnode = (struct NameNode *)(worknode->nn_Node.ln_Succ)) {
        FreeMem(worknode,sizeof(struct NameNode));
        worknode = nextnode;
    }

}

/*
 * Print the names of each node in a list.
 */
VOID DisplayNameList(struct List *list)
{
struct Node *node;

    if (list->lh_TailPred == (struct Node *)list)
        printf("List is empty.\n");
    else {
        for (node = list->lh_Head ; node->ln_Succ ; node = node->ln_Succ)
            printf("%lx -> %s\n",node,node->ln_Name);
    }
}

/*
 * Print the location of all nodes with a specified name.
 */
VOID DisplayName(struct List *list, UBYTE *name)
{
struct Node *node;

    if (node = FindName(list,name)) {
        while (node) {
            printf("Found a %s at location %lx\n",node->ln_Name,node);
            node = FindName((struct List *)node,name);
        }
    } else printf("No node with name %s found.\n",name);
}


Lib_examples/sample.library.asm

*******************************************************************************************
*   sample.library.asm -- Example run-time library source code
*
*   Assemble and link, without startup code, to create Sample.library,
*     a LIBS: drawer run-time shared library
*
*  Linkage Info:
*  FROM     sample.library.o
*  LIBRARY  LIB:Amiga.lib
*  TO       sample.library
*******************************************************************************************

   SECTION   code

   NOLIST
   INCLUDE "exec/types.i"
   INCLUDE "exec/initializers.i"
   INCLUDE "exec/libraries.i"
   INCLUDE "exec/lists.i"
   INCLUDE "exec/alerts.i"
   INCLUDE "exec/resident.i"
   INCLUDE "libraries/dos.i"

   INCLUDE "sampleinclude/asmsupp.i"
   INCLUDE "sampleinclude/samplebase.i"
   INCLUDE "sampleinclude/sample_rev.i"

   LIST

   XDEF   InitTable                    ;------ These don't have to be external but it helps
   XDEF   Open                         ;------ some debuggers to have them globally visible
   XDEF   Close
   XDEF   Expunge
   XDEF   Null
   XDEF   LibName
   XDEF   Double
   XDEF   AddThese

   XREF   _AbsExecBase

   XLIB   OpenLibrary
   XLIB   CloseLibrary
   XLIB   Alert
   XLIB   FreeMem
   XLIB   Remove

   ; The first executable location.  This should return an error in case someone tried to
   ; run you as a program (instead of loading you as a library).
Start:
   MOVEQ   #-1,d0
   rts

;------------------------------------------------------------------------------------------
; A romtag structure.  Both "exec" and "ramlib" look for this structure to discover magic
; constants about you (such as where to start running you from...).  The include file
; sample_rev.i (created by hand or preferable with the developer tool ``bumprev''
; resolves the VERSION, REVISION, and VSTRING.
;------------------------------------------------------------------------------------------
   ; Few people will need a priority and should leave it at zero.  The RT_PRI field is used
   ; in configuring the ROMs.  Use "mods" from wack to look at other romtags in the system.
MYPRI   EQU   0

RomTag:
               ;STRUCTURE RT,0
     DC.W    RTC_MATCHWORD      ; UWORD RT_MATCHWORD
     DC.L    RomTag             ; APTR  RT_MATCHTAG
     DC.L    EndCode            ; APTR  RT_ENDSKIP
     DC.B    RTF_AUTOINIT       ; UBYTE RT_FLAGS
     DC.B    VERSION            ; UBYTE RT_VERSION  (defined in sample_rev.i)
     DC.B    NT_LIBRARY         ; UBYTE RT_TYPE
     DC.B    MYPRI              ; BYTE  RT_PRI
     DC.L    LibName            ; APTR  RT_NAME
     DC.L    IDString           ; APTR  RT_IDSTRING
     DC.L    InitTable          ; APTR  RT_INIT  table for InitResident()

   ; this is the name that the library will have
LibName:   SAMPLENAME
   ; standard name/version/date ID string from bumprev-created sample_rev.i
IDString:  VSTRING

dosName:   DOSNAME

   ; force word alignment
   ds.w   0

   ; The romtag specified that we were "RTF_AUTOINIT".  This means that the RT_INIT
   ; structure member points to one of these tables below.  If the AUTOINIT bit was not
   ; set then RT_INIT would point to a routine to run.

InitTable:
   DC.L   SampleBase_SIZEOF ; size of library base data space
   DC.L   funcTable         ; pointer to function initializers
   DC.L   dataTable         ; pointer to data initializers
   DC.L   initRoutine       ; routine to run

funcTable:

   ;------ standard system routines
   dc.l   Open
   dc.l   Close
   dc.l   Expunge
   dc.l   Null

   ;------ my libraries definitions
   dc.l   Double
   dc.l   AddThese

   ;------ function table end marker
   dc.l   -1

   ; The data table initializes static data structures.  The format is specified in
   ; exec/InitStruct routine's manual pages.  The INITBYTE/INITWORD/INITLONG routines are
   ; in the file "exec/initializers.i".  The first argument is the offset from the library
   ; base for this byte/word/long.  The second argument is the value to put in that cell.
   ; The table is null terminated.
   ; NOTE - LN_TYPE below is a correction - old example had LH_TYPE.

dataTable:
        INITBYTE        LN_TYPE,NT_LIBRARY
        INITLONG        LN_NAME,LibName
        INITBYTE        LIB_FLAGS,LIBF_SUMUSED!LIBF_CHANGED
        INITWORD        LIB_VERSION,VERSION
        INITWORD        LIB_REVISION,REVISION
        INITLONG        LIB_IDSTRING,IDString
        DC.L   0

   ; This routine gets called after the library has been allocated.  The library pointer is
   ; in D0.  The segment list is in A0.  If it returns non-zero then the library will be
   ; linked into the library list.

initRoutine:

   ;------ get the library pointer into a convenient A register
   move.l   a5,-(sp)
   move.l   d0,a5

   ;------ save a pointer to exec
   move.l   a6,sb_SysLib(a5)

   ;------ save a pointer to our loaded code
   move.l   a0,sb_SegList(a5)

   ;------ open the dos library
   lea   dosName(pc),a1
   CLEAR   d0
   CALLSYS   OpenLibrary

   move.l   d0,sb_DosLib(a5)
   bne.s   1$

   ;------ can't open the dos!  what gives
   ALERT   AG_OpenLib!AO_DOSLib

1$:
   ;------ now build the static data that we need
   ;
   ; put your initialization here...
   ;

   move.l   a5,d0
   move.l   (sp)+,a5
   rts

;------------------------------------------------------------------------------------------
; here begins the system interface commands.  When the user calls OpenLibrary/CloseLibrary/
; RemoveLibrary, this eventually gets translated into a call to the following routines
; (Open/Close/Expunge).  Exec has already put our library pointer in A6 for us.  Exec has
; turned off task switching while in these routines (via Forbid/Permit), so we should not
; take too long in them.
;------------------------------------------------------------------------------------------

   ; Open returns the library pointer in d0 if the open was successful.  If the open failed
   ; then null is returned.  It might fail if we allocated memory on each open, or if only
   ; open application could have the library open at a time...

Open:      ; ( libptr:a6, version:d0 )

   ;------ mark us as having another opener
   addq.w   #1,LIB_OPENCNT(a6)

   ;------ prevent delayed expunges
   bclr   #LIBB_DELEXP,sb_Flags(a6)

   move.l   a6,d0
   rts

   ; There are two different things that might be returned from the Close routine.  If the
   ; library is no longer open and there is a delayed expunge then Close should return the
   ; segment list (as given to Init).  Otherwise close should return NULL.

Close:      ; ( libptr:a6 )

   ;------ set the return value
   CLEAR   d0

   ;------ mark us as having one fewer openers
   subq.w   #1,LIB_OPENCNT(a6)

   ;------ see if there is anyone left with us open
   bne.s   1$

   ;------ see if we have a delayed expunge pending
   btst   #LIBB_DELEXP,sb_Flags(a6)
   beq.s   1$

   ;------ do the expunge
   bsr   Expunge
1$:
   rts

   ; There are two different things that might be returned from the Expunge routine.  If
   ; the library is no longer open then Expunge should return the segment list (as given
   ; to Init).  Otherwise Expunge should set the delayed expunge flag and return NULL.
   ;
   ; One other important note: because Expunge is called from the memory allocator, it may
   ; NEVER Wait() or otherwise take long time to complete.

Expunge:   ; ( libptr: a6 )

   movem.l   d2/a5/a6,-(sp)
   move.l   a6,a5
   move.l   sb_SysLib(a5),a6

   ;------ see if anyone has us open
   tst.w   LIB_OPENCNT(a5)
   beq   1$

   ;------ it is still open.  set the delayed expunge flag
   bset   #LIBB_DELEXP,sb_Flags(a5)
   CLEAR   d0
   bra.s   Expunge_End

1$:
   ;------ go ahead and get rid of us.  Store our seglist in d2
   move.l   sb_SegList(a5),d2

   ;------ unlink from library list
   move.l   a5,a1
   CALLSYS   Remove

   ;
   ; device specific closings here...
   ;

   ;------ close the dos library
   move.l   sb_DosLib(a5),a1
   CALLSYS   CloseLibrary

   ;------ free our memory
   CLEAR   d0
   move.l   a5,a1
   move.w   LIB_NEGSIZE(a5),d0

   sub.l   d0,a1
   add.w   LIB_POSSIZE(a5),d0

   CALLSYS   FreeMem

   ;------ set up our return value
   move.l   d2,d0

Expunge_End:
   movem.l   (sp)+,d2/a5/a6
   rts

Null:
   CLEAR   d0
   rts

;------------------------------------------------------------------------------------------
; Here begins the library specific functions.  Both of these simple functions are entirely
; in assembler, but you can write your functions in C if you wish and interface to them
; here.  If, for instance, the bulk of the AddThese function was written in C, you could
; interface to it as follows:
;
;   - write a C function  addTheseC(n1,n2) and compile it
;   - XDEF _addThese C  in this library code
;   - change the AddThese function code below to:
;       move.l d1,-(sp)     ;push rightmost C arg first
;       move.l d0,-(sp)     ;push other C arg(s), right to left
;       jsr    _addTheseC   ;call the C code
;       addq   #8,sp        ;fix stack
;       rts                 ;return with result in d0
;------------------------------------------------------------------------------------------

*----- Double(d0)
Double:
   lsl     #1,d0
   rts

*----- AddThese(d0,d1)
AddThese:
   add.l   d1,d0
   rts

   ; EndCode is a marker that show the end of your code.  Make sure it does not span
   ; sections nor is before the rom tag in memory!  It is ok to put it right after the ROM
   ; tag--that way you are always safe.  I put it here because it happens to be the "right"
   ; thing to do, and I know that it is safe in this case.
EndCode:

   END


Lib_examples/semaphore.c

/* A simple "do nothing" example of Exec signal semaphore use is shown   */
/* below. When the semaphore is owned by a task, attempted access by     */
/* other tasks will block.  A nesting count is maintained, so the        */
/* current task can safely call ObtainSemaphore() on the same semaphore. */
/*
/* semaphore.c - Exec semaphore example - compile with lc -L semaphore.c */
#include <exec/types.h>
#include <exec/semaphores.h>
#include <clib/exec_protos.h>
#include <stdio.h>

#ifdef LATTICE
int CXBRK(void)  { return(0); }  /* Disable Lattice CTRL/C handling */
void chkabort(void) { return; }  /* really */
#endif

struct SignalSemaphore LockSemaphore = {0};

VOID main(int argc,char *argv[])
{
    InitSemaphore(&LockSemaphore);
    ObtainSemaphore(&LockSemaphore);  /* Task now owns the semaphore. */
         ...
    ReleaseSemaphore(&LockSemaphore); /* Task has released the semaphore. */
}


Lib_examples/signals.c

;/* signals.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 signals.c
Blink FROM LIB:c.o,signals.o TO signals LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
*/

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/alib_protos.h>
#include "stdio.h"

#ifdef LATTICE
int CXBRK(void) { return(0); }     /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

static UBYTE *VersTag = "$VER: signals 37.1 (28.3.91)";

void subtaskcode(void);    /* prototype for our subtask routine */

LONG  mainsignum = -1;
ULONG mainsig, wakeupsigs;
struct Task *maintask = NULL, *subtask = NULL;
UBYTE subtaskname[] = "RKM_signal_subtask";

void main(int argc, char **argv)
{
BOOL Done = FALSE, WaitingForSubtask = TRUE;

/* We must allocate any special signals we want to receive. */
mainsignum = AllocSignal(-1);
if(mainsignum == -1)
    printf("No signals available\n");
else
    {
    mainsig = 1L << mainsignum;    /* subtask can access this global */
    maintask = FindTask(NULL);     /* subtask can access this global */

    printf("We alloc a signal, create a task, wait for signals\n");
    subtask = CreateTask(subtaskname, 0L, subtaskcode, 2000);
    if(!subtask)
        printf("Can't create subtask\n");
    else
        {
        printf("After subtask signals, press CTRL-C or CTRL-D to exit\n");

        while((!Done)||(WaitingForSubtask))
            {
            /* Wait on the combined mask for all of the signals we are
             * interested in.  All processes have the CTRL_C thru CTRL_F
             * signals.  We're also Waiting on the mainsig we allocated
             * for our subtask to signal us with.  We could also Wait on
             * the signals of any ports/windows our main task created ... */

            wakeupsigs = Wait(mainsig | SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D);

            /* Deal with all signals that woke us up - may be more than one */
            if(wakeupsigs & mainsig)
                {
                printf("Signalled by subtask\n");
                WaitingForSubtask = FALSE;   /* OK to kill subtask now */
                }
            if(wakeupsigs & SIGBREAKF_CTRL_C)
                {
                printf("Got CTRL-C signal\n");
                Done = TRUE;
                }
            if(wakeupsigs & SIGBREAKF_CTRL_D)
                {
                printf("Got CTRL-D signal\n");
                Done = TRUE;
                }
            }
        Forbid();
        DeleteTask(subtask);
        Permit();
        }
    FreeSignal(mainsignum);
    }
}

void subtaskcode(void)
    {
    Signal(maintask,mainsig);
    Wait(0L);    /* safe state in which this subtask can be deleted */
    }


Lib_examples/simpletask.c

;/* simpletask.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 simpletask.c
Blink FROM LIB:c.o,simpletask.o TO simpletask LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit

simpletask.c - Uses the amiga.lib function CreateTask() to create a simple
subtask.  See the Includes and Autodocs manual for CreateTask() source code
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <exec/tasks.h>
#include <libraries/dos.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>

#include <stdlib.h>
#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }   /* Disable Lattice CTRL/C handling */
int chkabort(void) {return(0);}
#endif

#define STACK_SIZE 1000L

/* Task name, pointers for allocated task struct and stack */
struct Task *task = NULL;
char *simpletaskname = "SimpleTask";

ULONG sharedvar;

/* our function prototypes */
void simpletask(void);
void cleanexit(UBYTE *,LONG);

void main(int argc,char **argv)
{
    sharedvar = 0L;

    task = CreateTask(simpletaskname,0,simpletask,STACK_SIZE);
    if(!task)  cleanexit("Can't create task",RETURN_FAIL);

    printf("This program initialized a variable to zero, then started a\n");
    printf("separate task which is incrementing that variable right now,\n");
    printf("while this program waits for you to press RETURN.\n");
    printf("Press RETURN now: ");
    getchar();

    printf("The shared variable now equals %ld\n",sharedvar);

    /* We can simply remove the task we added because our simpletask does not make */
    /* any system calls which could cause it to be awakened or signalled later.    */
    Forbid();
    DeleteTask(task);
    Permit();
    cleanexit("",RETURN_OK);
}

void simpletask()
{
    while(sharedvar < 0x8000000) sharedvar++;
    /* Wait forever because main() is going to RemTask() us */
    Wait(0L);
}

void cleanexit(UBYTE *s, LONG e)
{
    if(*s) printf("%s\n",s);
    exit(e);
}


Lib_examples/tasklist.c

;/* tasklist.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 tasklist.c
Blink FROM LIB:c.o,tasklist.o TO tasklist LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit

tasklist.c - Snapshots and prints the ExecBase task list
*/
#include <exec/types.h>
#include <exec/lists.h>
#include <exec/nodes.h>
#include <exec/memory.h>
#include <exec/execbase.h>

#include <clib/alib_protos.h>
#include <clib/exec_protos.h>

#include <stdio.h>
#include <string.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }   /* disable SAS/C CTRL-C handing */
int chkabort(void) {return(0); }
#endif

static UBYTE *VersTag = "$VER: tasklist 37.2 (31.3.92)";
extern struct ExecBase *SysBase;

/* Use extended structure to hold task information */
struct TaskNode {
    struct Node tn_Node;
    ULONG tn_TaskAddress;
    ULONG tn_SigAlloc;
    ULONG tn_SigWait;
    UBYTE tn_Name[32];
};

void main(int argc, char **argv)
{
    struct List *ourtasklist;
    struct List *exectasklist;
    struct Task *task;
    struct TaskNode *node, *tnode, *rnode = NULL;
    struct Node *execnode;

    /* Allocate memory for our list */
    if (ourtasklist = AllocMem(sizeof(struct List), MEMF_CLEAR)) {
        /* Initialize list structure (ala NewList()) */
        ourtasklist->lh_Head = (struct Node *)&ourtasklist->lh_Tail;
        ourtasklist->lh_Tail = 0;
        ourtasklist->lh_TailPred = (struct Node *)&ourtasklist->lh_Head;

        /* Make sure tasks won't switch lists or go away */
        Disable();

        /* Snapshot task WAIT list */
        exectasklist = &(SysBase->TaskWait);
        for (execnode = exectasklist->lh_Head;
                 execnode->ln_Succ; execnode = execnode->ln_Succ)
        {
            if (tnode = AllocMem(sizeof(struct TaskNode), MEMF_CLEAR))
            {
                /* Save task information we want to print */
                strncpy(tnode->tn_Name, execnode->ln_Name, 32);
                tnode->tn_Node.ln_Pri = execnode->ln_Pri;
                tnode->tn_TaskAddress = (ULONG)execnode;
                tnode->tn_SigAlloc = ((struct Task *)execnode)->tc_SigAlloc;
                tnode->tn_SigWait = ((struct Task*)execnode)->tc_SigWait;
                AddTail(ourtasklist, (struct Node *)tnode);
            }
            else break;
        }

        /* Snapshot task READY list */
        exectasklist = &(SysBase->TaskReady);
        for (execnode = exectasklist->lh_Head;
                 execnode->ln_Succ; execnode = execnode->ln_Succ)
        {
            if (tnode = AllocMem(sizeof(struct TaskNode), MEMF_CLEAR))
            {
                /* Save task information we want to print */
                strncpy(tnode->tn_Name, execnode->ln_Name, 32);
                tnode->tn_Node.ln_Pri = execnode->ln_Pri;
                tnode->tn_TaskAddress = (ULONG)execnode;
                tnode->tn_SigAlloc = ((struct Task *)execnode)->tc_SigAlloc;
                tnode->tn_SigWait = ((struct Task*)execnode)->tc_SigWait;
                AddTail(ourtasklist, (struct Node *)tnode);
                if(!rnode)  rnode = tnode;  /* first READY task */
            }
            else
                break;
        }

        /* Re-enable interrupts and taskswitching */
        Enable();

        /* Print now (printing above would have defeated a Forbid or Disable) */
        printf("Pri Address     SigAlloc    SigWait    Taskname\n");

        node = (struct TaskNode *)(ourtasklist->lh_Head);
        printf("\nWAITING:\n");
        while (tnode = (struct TaskNode *)node->tn_Node.ln_Succ)
        {
            if(tnode == rnode)
                printf("\nREADY:\n");  /* we set rnode above */
            printf("%02d  0x%08lx  0x%08lx  0x%08lx %s\n",
                    node->tn_Node.ln_Pri, node->tn_TaskAddress, node->tn_SigAlloc,
                    node->tn_SigWait, node->tn_Name);

            /* Free the memory, no need to remove the node, referenced once only */
            FreeMem(node,sizeof(struct TaskNode));
            node = tnode;
        }
        FreeMem(ourtasklist, sizeof(struct List));

        /* Say who we are */
        printf("\nTHIS TASK:\n");
        task = FindTask(NULL);
        printf("%02d  0x%08lx  0x%08lx  0x%08lx %s\n",
                task->tc_Node.ln_Pri, task, task->tc_SigAlloc,
                task->tc_SigWait, task->tc_Node.ln_Name);

    }
}


Lib_examples/trap_c.c

;/* trap_c.c - Execute me to compile me with SAS C 5.10
LC -b0 -cfistq -v -y -j73 trap_c.c
Blink FROM LIB:c.o,trap_c.o,trap_a.o TO trap LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit

trap_c.c - C module of sample integer divide-by-zero trap
*/
#include <exec/types.h>
#include <exec/tasks.h>
#include <clib/exec_protos.h>
#include <stdlib.h>
#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) {return(0); }
#endif

extern ULONG trapa();           /* assembler trap code in trap_a.asm */

APTR oldTrapCode;
ULONG countdiv0;

void main(int argc, char **argv)
{
    struct Task *thistask;
    ULONG k,j;

    thistask = FindTask(NULL);

    /* Save our task's current trap code pointer */
    oldTrapCode = thistask->tc_TrapCode;

    /* Point task to our assembler trap handler code.  Ours will just count */
    /* divide-by-zero traps, and pass other traps on to the normal TrapCode */
    thistask->tc_TrapCode = (APTR)trapa;

    countdiv0 = 0L;

    for(k=0; k<4; k++)            /* Let's divide by zero a few times */
       {
       printf("dividing %ld by zero... ",k);
       j = k/0L;
       printf("did it\n");
       }
    printf("\nDivide by zero happened %ld times\n",countdiv0);

    thistask->tc_TrapCode = oldTrapCode;     /* Restore old trap code */
}

* trap_a.asm - Example trap handling code (leaves D0 intact).  Entered
* in supervisor mode with the following on the supervisor stack:
*    0(sp).l = trap#
*    4(sp) Processor dependent exception frame

    INCLUDE "exec/types.i"
    INCLUDE "libraries/dos.i"

        XDEF _trapa
        XREF _countdiv0
        XREF _oldTrapCode

        CODE
_trapa:                                 ; our trap handler entry
        CMPI.L  #5,(SP)                 ; is this a divide by zero ?
        BNE.S   notdiv0                 ; no
        ADD.L   #1,_countdiv0           ; yes, increment our div0 count
endtrap:
        ADDQ    #4,SP                   ; remove exception number from SSP
        RTE                             ; return from exception
notdiv0:
        TST.L   _oldTrapCode            ; is there another trap handler ?
        BEQ.S   endtrap                 ; no, so we'll exit
        MOVE.L  _oldTrapCode,-(SP)      ; yes, go on to old TrapCode
        RTS                             ; jumps to old TrapCode

        END


Lib_examples/DeviceUse.c

;/* DeviceUse.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 DeviceUse.c
Blink FROM LIB:c.o,DeviceUse.o TO DeviceUse LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit

/* The following short example demonstrates use of an Amiga device.  The */
/* example opens the serial.device and then demonstrates both            */
/* synchronous (DoIO()) and asynchronous (SendIO()) use of the serial    */
/* command SDCMD_QUERY.  This command is used to determine the status of */
/* the serial device lines and registers.  The example uses the backward */
/* compatible amiga.lib functions for creation and deletion of the       */
/* message port and I/O request.                                         */

/* DeviceUse.c - an example of using an Amiga device (here, serial device)    */
/*    - attempt to create a message port with CreatePort()   (from amiga.lib) */
/*    - attempt to create the I/O request with CreateExtIO() (from amiga.lib) */
/*    - attempt to open the serial device with Exec OpenDevice()              */
/*                                                                            */
/* If successful, use the serial command SDCMD_QUERY, then reverse our steps. */
/* If we encounter an error at any time, we will gracefully exit.  Note that  */
/* applications which require at least V37 OS should use the Exec functions   */
/* CreateMsgPort()/DeleteMsgPort() and CreateIORequest()/DeleteIORequest()    */
/* instead of the similar amiga.lib functions which are used in this example. */

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/io.h>
#include <devices/serial.h>

#include <clib/exec_protos.h> /* Prototypes for Exec library functions */
#include <clib/alib_protos.h> /* Prototypes for amiga.lib functions    */

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }     /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

void main(void)
{
    struct MsgPort  *serialMP;      /* for pointer to our message port */
    struct IOExtSer *serialIO;      /* for pointer to our I/O request  */
    struct IOExtSer *reply;         /* for use with GetMsg             */

    if (serialMP=CreatePort(NULL,NULL)) /* Create the message port. */
    {
        /* Create the I/O request. Note that <devices/serial.h> defines the type */
        /* of IORequest required by the serial device--an IOExtSer. Many devices */
        /* require specialized extended IO requests which start with an embedded */
        /* struct IORequest. The generic Exec and amiga.lib device IO functions  */
        /* are prototyped for IORequest, so some pointer casting is necessary.   */

        if (serialIO = (struct IOExtSer *)CreateExtIO(serialMP,sizeof(struct IOExtSer)))
        {
            /* Open the serial device (non-zero return value means failure here). */
            if (OpenDevice( SERIALNAME, 0, (struct IORequest *)serialIO, 0L))
                printf("Error: %s did not open\n",SERIALNAME);
            else
            {
                /* Device is open */                         /* DoIO - demonstrates synchronous */
                serialIO->IOSer.io_Command  = SDCMD_QUERY;   /* device use, returns error or 0. */
                if (DoIO((struct IORequest *)serialIO))
                    printf("Query  failed. Error - %d\n",serialIO->IOSer.io_Error);
                else
                    /* Print serial device status - see include file for meaning */
                    /* Note that with DoIO, the Wait and GetMsg are done by Exec */
                    printf("Serial device status: $%x\n\n",serialIO->io_Status);

                serialIO->IOSer.io_Command  = SDCMD_QUERY; /* SendIO - demonstrates asynchronous */
                SendIO((struct IORequest *)serialIO);      /* device use (returns immediately).  */

                /* We could do other things here while the query is being done.      */
                /* And to manage our asynchronous device IO:                         */
                /*   - we can CheckIO(serialIO) to check for completion              */
                /*   - we can AbortIO(serialIO) to abort the command                 */
                /*   - we can WaitPort(serialMP) to wait for any serial port reply   */
                /*  OR we can WaitIO(serialIO) to wait for this specific IO request  */
                /*  OR we can Wait(1L << serialMP_>mp_SigBit) for reply port signal  */

                Wait(1L << serialMP->mp_SigBit);

                while(reply = (struct IOExtSer *)GetMsg(serialMP))
                {    /* Since we sent out only one serialIO request the while loop is */
                     /* not really needed--we only expect one reply to our one query  */
                     /* command, and the reply message pointer returned by GetMsg()   */
                     /* will just be another pointer to our one serialIO request.     */
                     /* With Wait() or WaitPort(), you must GetMsg() the message.     */
                    if(reply->IOSer.io_Error)
                        printf("Query  failed. Error - %d\n",reply->IOSer.io_Error);
                    else
                        printf("Serial device status: $%x\n\n",reply->io_Status);
                }
                CloseDevice((struct IORequest *)serialIO);  /* Close the serial device.    */
            }
            DeleteExtIO(serialIO);                          /* Delete the I/O request.     */
        }
        else printf("Error: Could create I/O request\n");   /* Inform user that the I/O    */
                                                            /* request could be created.   */
        DeletePort(serialMP);                               /* Delete the message port.    */
    }
    else printf("Error: Could not create message port\n");  /* Inform user that the message*/
}                                                           /* port could not be created.  */


Lib_examples/findboards.c

;/* findboards.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 findboards.c
Blink FROM LIB:c.o,findboards.o TO findboards LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <libraries/configvars.h>

#include <clib/exec_protos.h>
#include <clib/expansion_protos.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

struct Library   *ExpansionBase = NULL;

void main(int argc, char **argv)
{
    struct ConfigDev *myCD;
    UWORD m,i;
    UBYTE p,f,t;

    if((ExpansionBase=OpenLibrary("expansion.library",0L))==NULL)
    exit(RETURN_FAIL);

    /*--------------------------------------------------*/
    /* FindConfigDev(oldConfigDev,manufacturer,product) */
    /* oldConfigDev = NULL for the top of the list      */
    /* manufacturer = -1 for any manufacturer           */
    /* product      = -1 for any product                */
    /*--------------------------------------------------*/

    myCD = NULL;
    while(myCD=FindConfigDev(myCD,-1L,-1L)) /* search for all ConfigDevs */
    {
    printf("\n---ConfigDev structure found at location $%lx---\n",myCD);

    /* These values were read directly from the board at expansion time */
    printf("Board ID (ExpansionRom) information:\n");

    t = myCD->cd_Rom.er_Type;
    m = myCD->cd_Rom.er_Manufacturer;
    p = myCD->cd_Rom.er_Product;
    f = myCD->cd_Rom.er_Flags;
    i = myCD->cd_Rom.er_InitDiagVec;

    printf("er_Manufacturer         =%d=$%04x=(~$%4x)\n",m,m,(UWORD)~m);
    printf("er_Product              =%d=$%02x=(~$%2x)\n",p,p,(UBYTE)~p);

    printf("er_Type                 =$%02x",myCD->cd_Rom.er_Type);
    if(myCD->cd_Rom.er_Type & ERTF_MEMLIST)
        printf("  (Adds memory to free list)\n");
    else printf("\n");

    printf("er_Flags                =$%02x=(~$%2x)\n",f,(UBYTE)~f);
    printf("er_InitDiagVec          =$%04x=(~$%4x)\n",i,(UWORD)~i);

    /* These values are generated when the AUTOCONFIG(tm) software
     * relocates the board
     */
    printf("Configuration (ConfigDev) information:\n");
    printf("cd_BoardAddr            =$%lx\n",myCD->cd_BoardAddr);
    printf("cd_BoardSize            =$%lx (%ldK)\n",
           myCD->cd_BoardSize,((ULONG)myCD->cd_BoardSize)/1024);

    printf("cd_Flags                =$%x",myCD->cd_Flags);
    if(myCD->cd_Flags & CDF_CONFIGME)
        printf("\n");
    else printf("  (driver clears CONFIGME bit)\n");
    }
    CloseLibrary(ExpansionBase);
}


Lib_examples/Diag.asm

**
** Sample autoboot code fragment
**
** These are the calling conventions for the Diag routine
**
** A7 -- points to at least 2K of stack
** A6 -- ExecBase
** A5 -- ExpansionBase
** A3 -- your board's ConfigDev structure
** A2 -- Base of diag/init area that was copied
** A0 -- Base of your board
**
** Your Diag routine should return a non-zero value in D0 for success.
** If this value is NULL, then the diag/init area that was copied
** will be returned to the free memory pool.
**

            INCLUDE "exec/types.i"
            INCLUDE "exec/nodes.i"
            INCLUDE "exec/resident.i"
            INCLUDE "libraries/configvars.i"

            ; LVO's resolved by linking with library amiga.lib
            XREF   _LVOFindResident

ROMINFO     EQU      1
ROMOFFS     EQU     $0

* ROMINFO defines whether you want the AUTOCONFIG information in
* the beginning of your ROM (set to 0 if you instead have PALS
* providing the AUTOCONFIG information instead)
*
* ROMOFFS is the offset from your board base where your ROMs appear.
* Your ROMs might appear at offset 0 and contain your AUTOCONFIG
* information in the high nibbles of the first $40 words ($80 bytes).
* Or, your autoconfig ID information may be in a PAL, with your
* ROMs possibly being addressed at some offset (for example $2000)
* from your board base.  This ROMOFFS constant will be used as an
* additional offset from your configured board address when patching
* structures which require absolute pointers to ROM code or data.

*----- We'll store Version and Revision in serial number
VERSION 	EQU	37		; also the high word of serial number
REVISION	EQU	1		; also the low word of serial number

* See the Addison-Wesley Amiga Hardware Manual for more info.

MANUF_ID	EQU	2011		; CBM assigned (2011 for hackers only)
PRODUCT_ID	EQU	1		; Manufacturer picks product ID

BOARDSIZE	EQU	$40000          ; How much address space board decodes
SIZE_FLAG	EQU	3		; Autoconfig 3-bit flag for BOARDSIZE
                    ;   0=$800000(8meg)  4=$80000(512K)
                    ;   1=$10000(64K)    5=$100000(1meg)
                    ;   2=$20000(128K)   6=$200000(2meg)
                    ;   3=$40000(256K)   7=$400000(4meg)
            CODE

*******  RomStart  ***************************************************
**********************************************************************

RomStart:

    IFGT    ROMINFO
;
;   ExpansionRom structure
;
;   Note - If you implement your ExpansionRom and ExpansionControl
;   with PALS, then you can comment out everything until DiagStart:
;   (ie. Make ROMID EQU 0)

*    ; High nibbles of first two words ($00,$02) are er_Type (not inverted)
                        ; er_Type
        dc.w	$D000			;   11xx normal board type
                        ;   xx0x not in memory free list
                        ;   xxx1 Diag valid (has driver)
        dc.w	(SIZE_FLAG<<12)&$7000	;   0xxx not chained
                        ;   xnnn flags board size

*    ; High nibbles of next two words are er_Product
*    ; These are inverted (~), as are all other words except $40 and $42

                        ; er_Product
        dc.w	(~(PRODUCT_ID<<8))&$f000,(~(PRODUCT_ID<<12))&$f000

                        ; er_Flags
        dc.w	(~$C000)&$f000		;   ~1xxx board is moveable
                        ;   ~x1xx board can't be shut up
        dc.w	(~0)&$f000		;

        dc.w	(~0)&$f000,(~0)&$f000	; er_Reserved03

                        ; er_Manufacturer
        dc.w	(~(MANUF_ID))&$f000,(~(MANUF_ID<<4))&$f000
        dc.w	(~(MANUF_ID<<8))&$f000,(~(MANUF_ID<<12))&$f000

                        ; er_SerialNumber
        dc.w	(~(VERSION))&$f000,(~(VERSION<<4))&$f000
        dc.w	(~(VERSION<<8))&$f000,(~(VERSION<<12))&$f000
        dc.w	(~(REVISION))&$f000,(~(REVISION<<4))&$f000
        dc.w	(~(REVISION<<8))&$f000,(~(REVISION<<12))&$f000

                        ; er_InitDiagVec
        dc.w	(~((DiagStart-RomStart)))&$f000
        dc.w	(~((DiagStart-RomStart)<<4))&$f000
        dc.w	(~((DiagStart-RomStart)<<8))&$f000
        dc.w	(~((DiagStart-RomStart)<<12))&$f000

        dc.w	(~0)&$f000,(~0)&$f000	; er_Reserved0c
        dc.w	(~0)&$f000,(~0)&$f000	; er_Reserved0d
        dc.w	(~0)&$f000,(~0)&$f000	; er_Reserved0e
        dc.w	(~0)&$f000,(~0)&$f000	; er_Reserved0f

    IFNE	*-RomStart-$40
    FAIL	"ExpansionRom structure not the right size"
    ENDC

        ;Note: nibbles $40 and $42 are not to be inverted
        dc.w	(0)&$f000,(0)&$f000	; ec_Interrupt (no interrupts)
        dc.w	(~0)&$f000,(~0)&$f000	; ec_Reserved11
        dc.w	(~0)&$f000,(~0)&$f000	; ec_BaseAddress (write only)
        dc.w	(~0)&$f000,(~0)&$f000	; ec_Shutup (write only)
        dc.w	(~0)&$f000,(~0)&$f000	; ec_Reserved14
        dc.w	(~0)&$f000,(~0)&$f000	; ec_Reserved15
        dc.w	(~0)&$f000,(~0)&$f000	; ec_Reserved16
        dc.w	(~0)&$f000,(~0)&$f000	; ec_Reserved17
        dc.w	(~0)&$f000,(~0)&$f000	; ec_Reserved18
        dc.w	(~0)&$f000,(~0)&$f000	; ec_Reserved19
        dc.w	(~0)&$f000,(~0)&$f000	; ec_Reserved1a
        dc.w	(~0)&$f000,(~0)&$f000	; ec_Reserved1b
        dc.w	(~0)&$f000,(~0)&$f000	; ec_Reserved1c
        dc.w	(~0)&$f000,(~0)&$f000	; ec_Reserved1d
        dc.w	(~0)&$f000,(~0)&$f000	; ec_Reserved1e
        dc.w	(~0)&$f000,(~0)&$f000	; ec_Reserved1f

    IFNE	*-RomStart-$80
    FAIL	"Expansion Control structure not the right size"
    ENDC

    ENDC	;ROMINFO

*******  DiagStart  **************************************************
DiagStart:  ; This is the DiagArea structure whose relative offset from
            ; your board base appears as the Init Diag vector in your
            ; autoconfig ID information.  This structure is designed
            ; to use all relative pointers (no patching needed).
            dc.b    DAC_WORDWIDE+DAC_CONFIGTIME    ; da_Config
            dc.b    0                              ; da_Flags
            dc.w    EndCopy-DiagStart              ; da_Size
            dc.w    DiagEntry-DiagStart            ; da_DiagPoint
            dc.w    BootEntry-DiagStart            ; da_BootPoint
            dc.w    DevName-DiagStart              ; da_Name
            dc.w    0                              ; da_Reserved01
            dc.w    0                              ; da_Reserved02

*******  Resident Structure  *****************************************
Romtag:
            dc.w    RTC_MATCHWORD      ; UWORD RT_MATCHWORD
rt_Match:   dc.l    Romtag-DiagStart   ; APTR  RT_MATCHTAG
rt_End:     dc.l    EndCopy-DiagStart  ; APTR  RT_ENDSKIP
            dc.b    RTW_COLDSTART      ; UBYTE RT_FLAGS
            dc.b    VERSION            ; UBYTE RT_VERSION
            dc.b    NT_DEVICE          ; UBYTE RT_TYPE
            dc.b    20                 ; BYTE  RT_PRI
rt_Name:    dc.l    DevName-DiagStart  ; APTR  RT_NAME
rt_Id:      dc.l    IdString-DiagStart ; APTR  RT_IDSTRING
rt_Init:    dc.l    Init-RomStart      ; APTR  RT_INIT

******* Strings referenced in Diag Copy area  ************************
DevName:    dc.b    'abc.device',0                      ; Name string
IdString    dc.b    'abc ',48+VERSION,'.',48+REVISION   ; Id string

DosName:    dc.b    'dos.library',0                ; DOS library name

DosDevName: dc.b    'ABC',0        ; dos device name for MakeDosNode()
                                   ;   (dos device will be ABC:)

            ds.w    0              ; word align

*******  DiagEntry  **************************************************
**********************************************************************
*
*   success = DiagEntry(BoardBase,DiagCopy, configDev)
*   d0                  a0         a2                  a3
*
*   Called by expansion architecture to relocate any pointers
*   in the copied diagnostic area.   We will patch the romtag.
*   If you have pre-coded your MakeDosNode packet, BootNode,
*   or device initialization structures, they would also need
*   to be within this copy area, and patched by this routine.
*
**********************************************************************

DiagEntry:
            lea      patchTable-RomStart(a0),a1   ; find patch table
            adda.l   #ROMOFFS,a1                  ; adjusting for ROMOFFS

* Patch relative pointers to labels within DiagCopy area
* by adding Diag RAM copy address.  These pointers were coded as
* long relative offsets from base of the DiagArea structure.
*
dpatches:
            move.l   a2,d1           ;d1=base of ram Diag copy
dloop:
            move.w   (a1)+,d0        ;d0=word offs. into Diag needing patch
            bmi.s    bpatches        ;-1 is end of word patch offset table
            add.l    d1,0(a2,d0.w)   ;add DiagCopy addr to coded rel. offset
            bra.s    dloop

* Patches relative pointers to labels within the ROM by adding
* the board base address + ROMOFFS.  These pointers were coded as
* long relative offsets from RomStart.
*
bpatches:
            move.l   a0,d1           ;d1 = board base address
            add.l    #ROMOFFS,d1     ;add offset to where your ROMs are
rloop:
            move.w   (a1)+,d0        ;d0=word offs. into Diag needing patch
            bmi.s   endpatches       ;-1 is end of patch offset table
            add.l   d1,0(a2,d0.w)    ;add ROM address to coded relative offset
            bra.s   rloop

endpatches:
            moveq.l #1,d0           ; indicate "success"
            rts

*******  BootEntry  **************************************************
**********************************************************************

BootEntry:  lea     DosName(PC),a1          ; 'dos.library',0
            jsr     _LVOFindResident(a6)    ; find the DOS resident tag
            move.l  d0,a0                   ; in order to bootstrap
            move.l  RT_INIT(A0),a0          ; set vector to DOS INIT
            jsr     (a0)                    ; and initialize DOS
            rts

*
* End of the Diag copy area which is copied to RAM
*
EndCopy:
*************************************************************************

*************************************************************************
*
*   Beginning of ROM driver code and data that is accessed only in
*   the ROM space.  This must all be position-independent.
*

patchTable:
* Word offsets into Diag area where pointers need Diag copy address added
            dc.w   rt_Match-DiagStart
            dc.w   rt_End-DiagStart
            dc.w   rt_Name-DiagStart
            dc.w   rt_Id-DiagStart
            dc.w   -1

* Word offsets into Diag area where pointers need boardbase+ROMOFFS added
            dc.w   rt_Init-DiagStart
            dc.w   -1

*******  Romtag InitEntry  **********************************************
*************************************************************************

Init:       ; After Diag patching, our romtag will point to this
            ; routine in ROM so that it can be called at Resident
            ; initialization time.
            ; This routine will be similar to a normal expansion device
            ; initialization routine, but will MakeDosNode then set up a
            ; BootNode, and Enqueue() on eb_MountList.
            ;
            rts

            ; Rest of your position-independent device code goes here.

            END


Lib_examples/simplegad.c

;/* simplegad.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 simplegad.c
Blink FROM LIB:c.o,simplegad.o TO simplegad LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
**
** The example below demonstrates a simple application gadget.  The
** program declares a Gadget structure set up as a boolean gadget with
** complement mode highlighting.  The gadget is attached to the window
** when it is opened by using the WA_Gadgets tag in the OpenWindowTags()
** call.
**
** simplegad.c - show the use of a button gadget.
*/

#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

struct Library *IntuitionBase;

#define BUTTON_GAD_NUM   (3)
#define MYBUTTONGADWIDTH (100)
#define MYBUTTONGADHEIGHT (50)

/* NOTE that the use of constant size and positioning values are
** not recommended; it just makes it easy to show what is going on.
** The position of the gadget should be dynamically adjusted depending
** on the height of the font in the title bar of the window.
*/

UWORD buttonBorderData[] =
    {
    0,0, MYBUTTONGADWIDTH + 1,0, MYBUTTONGADWIDTH + 1,MYBUTTONGADHEIGHT + 1,
    0,MYBUTTONGADHEIGHT + 1, 0,0,
    };

struct Border buttonBorder =
    {
    -1,-1,1,0,JAM1,5,buttonBorderData,NULL,
    };

struct Gadget buttonGad =
    {
    NULL, 20,20, MYBUTTONGADWIDTH,MYBUTTONGADHEIGHT,
    GFLG_GADGHCOMP, GACT_RELVERIFY | GACT_IMMEDIATE,
    GTYP_BOOLGADGET, &buttonBorder, NULL, NULL,0,NULL,BUTTON_GAD_NUM,NULL,
    };

/*
** routine to show the use of a button (boolean) gadget.
*/
VOID main(int argc, char **argv)
{
struct Window *win;
struct IntuiMessage *msg;
struct Gadget *gad;
ULONG  class;
BOOL done;

/* make sure to get intuition version 37, for OpenWindowTags() */
IntuitionBase = OpenLibrary("intuition.library", 37);
if (IntuitionBase)
    {
    if (win = OpenWindowTags(NULL,
                            WA_Width, 400,
                            WA_Height, 100,
                            WA_Gadgets, &buttonGad,
                            WA_Activate, TRUE,
                            WA_CloseGadget, TRUE,
                            WA_IDCMP, IDCMP_GADGETDOWN | IDCMP_GADGETUP |
                                      IDCMP_CLOSEWINDOW,
                            TAG_END))
        {
        done = FALSE;
        while (done == FALSE)
            {
            Wait(1L << win->UserPort->mp_SigBit);
            while ( (done == FALSE) &&
                    (msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
                {
                /* Stash message contents and reply, important when message
                ** triggers some lengthy processing
                */
                class = msg->Class;

                /* gadget address is ONLY valid for gadget messages! */
                if ((class == IDCMP_GADGETUP) || (class == IDCMP_GADGETDOWN))
                    gad = (struct Gadget *)(msg->IAddress);

                ReplyMsg((struct Message *)msg);

                /* switch on the type of the event */
                switch (class)
                    {
                    case IDCMP_GADGETUP:
                        /* caused by GACT_RELVERIFY */
                        printf("received an IDCMP_GADGETUP, gadget number %d\n",
                               gad->GadgetID);
                        break;
                    case IDCMP_GADGETDOWN:
                        /* caused by GACT_IMMEDIATE */
                        printf("received an IDCMP_GADGETDOWN, gadget number %d\n",
                               gad->GadgetID);
                        break;
                    case IDCMP_CLOSEWINDOW:
                        /* set a flag that we are done processing events... */
                        printf("received an IDCMP_CLOSEWINDOW\n");
                        done = TRUE;
                        break;
                    }
                }
            }
        CloseWindow(win);
        }
    CloseLibrary(IntuitionBase);
    }
}


Lib_examples/strhooks.c

;/* strhooks.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 strhooks.c
Blink FROM LIB:c.o,strhooks.o TO strhooks LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
**   strhooks.c - string gadget hooks demo
**
** WARNING: This file contains "callback" functions.
** You must disable stack checking (SAS -v flag) for them to work.
*/
#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <exec/memory.h>
#include <utility/hooks.h>
#include <devices/inputevent.h>
#include <intuition/intuition.h>
#include <intuition/sghooks.h>
#include <graphics/displayinfo.h>

#include <clib/intuition_protos.h>
#include <clib/utility_protos.h>
#include <clib/exec_protos.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

/* our function prototypes */
BOOL IsHexDigit(UBYTE test_char);
ULONG str_hookRoutine(struct Hook *hook, struct SGWork *sgw, ULONG *msg);
void initHook(struct Hook *hook, ULONG (*ccode)());
VOID handleWindow(struct Vars *vars);

struct Library    *IntuitionBase;
struct Library    *UtilityBase;

#define SG_STRLEN     (44)
#define MYSTRGADWIDTH (200)
#define INIT_LATER	0

/* A border for the string gadget */
UWORD strBorderData[] =	/* init elements 5 and 7 later (height adjust) */
    {
    0,0,  MYSTRGADWIDTH + 3,0,  MYSTRGADWIDTH + 3,INIT_LATER,
    0,INIT_LATER,   0,0,
    };
struct Border strBorder =
    {
    -2,-2, 1, 0,JAM1,5,strBorderData,NULL,
    };

/* We'll dynamically allocate/clear most structures, buffers */
struct Vars
    {
    struct Window      *sgg_Window;
    struct Gadget       sgg_Gadget;
    struct StringInfo   sgg_StrInfo;
    struct StringExtend sgg_Extend;
    struct Hook         sgg_Hook;
    UBYTE               sgg_Buff[SG_STRLEN];
    UBYTE               sgg_WBuff[SG_STRLEN];
    UBYTE               sgg_UBuff[SG_STRLEN];
    };

/*   Main entry point.
**
** Open all required libraries, set-up the string gadget.
** Prepare the hook, open the sgg_Window and go...
*/
VOID main(int argc, char **argv)
{
struct Vars   *vars;
struct Screen   *screen;
struct DrawInfo *drawinfo;

if (IntuitionBase = OpenLibrary("intuition.library", 37L))
    {
    if (UtilityBase = OpenLibrary("utility.library", 37L))
        {
        /* get the correct pens for the screen. */
        if (screen = LockPubScreen(NULL))
            {
            if (drawinfo = GetScreenDrawInfo(screen))
                {
                vars = (struct Vars *)AllocMem(sizeof(struct Vars),MEMF_CLEAR);
                if (vars != NULL)
                    {
                    vars->sgg_Extend.Pens[0] = drawinfo->dri_Pens[FILLTEXTPEN];
                    vars->sgg_Extend.Pens[1] = drawinfo->dri_Pens[FILLPEN];
                    vars->sgg_Extend.ActivePens[0] = drawinfo->dri_Pens[FILLTEXTPEN];
                    vars->sgg_Extend.ActivePens[1] = drawinfo->dri_Pens[FILLPEN];
                    vars->sgg_Extend.EditHook = &(vars->sgg_Hook);
                    vars->sgg_Extend.WorkBuffer = vars->sgg_WBuff;

                    vars->sgg_StrInfo.Buffer = vars->sgg_Buff;
                    vars->sgg_StrInfo.UndoBuffer = vars->sgg_UBuff;
                    vars->sgg_StrInfo.MaxChars = SG_STRLEN;
                    vars->sgg_StrInfo.Extension = &(vars->sgg_Extend);

                    /* There should probably be a border around the string gadget.
                    ** As is, it is hard to locate when disabled.
                    */
                    vars->sgg_Gadget.LeftEdge = 20;
                    vars->sgg_Gadget.TopEdge = 30;
                    vars->sgg_Gadget.Width = MYSTRGADWIDTH;
                    vars->sgg_Gadget.Height = screen->RastPort.TxHeight;
                    vars->sgg_Gadget.Flags = GFLG_GADGHCOMP | GFLG_STRINGEXTEND;
                    vars->sgg_Gadget.Activation = GACT_RELVERIFY;
                    vars->sgg_Gadget.GadgetType = GTYP_STRGADGET;
                    vars->sgg_Gadget.SpecialInfo = &(vars->sgg_StrInfo);
                    vars->sgg_Gadget.GadgetRender = (APTR)&strBorder;
                    strBorderData[5] = strBorderData[7] =
                          screen->RastPort.TxHeight + 3;

                    initHook(&(vars->sgg_Hook), str_hookRoutine);

                    if (vars->sgg_Window = OpenWindowTags(NULL,
                            WA_PubScreen,       screen,
                            WA_Left,      21,   WA_Top,       20,
                            WA_Width,    500,   WA_Height,   150,
                            WA_MinWidth,  50,   WA_MaxWidth,  ~0,
                            WA_MinHeight, 30,   WA_MaxHeight, ~0,
                            WA_SimpleRefresh, TRUE,
                            WA_NoCareRefresh, TRUE,
                            WA_RMBTrap,       TRUE,
                            WA_IDCMP,         IDCMP_GADGETUP | IDCMP_CLOSEWINDOW,
                            WA_Flags,         WFLG_CLOSEGADGET | WFLG_NOCAREREFRESH |
                                              WFLG_DRAGBAR | WFLG_DEPTHGADGET |
                                              WFLG_SIMPLE_REFRESH,
                            WA_Title,         "String Hook Accepts HEX Digits Only",
                            WA_Gadgets,       &(vars->sgg_Gadget),
                            TAG_DONE))
                        {
                        handleWindow(vars);

                        CloseWindow(vars->sgg_Window);
                        }
                    FreeMem(vars,sizeof(struct Vars));
                    }
                FreeScreenDrawInfo(screen, drawinfo);
                }
            UnlockPubScreen(NULL, screen);
            }
        CloseLibrary(UtilityBase);
        }
    CloseLibrary(IntuitionBase);
    }
}

/*
** This is an example string editing hook, which shows the basics of
** creating a string editing function.  This hook restricts entry to
** hexadecimal digits (0-9, A-F, a-f) and converts them to upper case.
** To demonstrate processing of mouse-clicks, this hook also detects
** clicking on a character, and converts it to a zero.
**
** NOTE: String editing hooks are called on Intuition's task context,
** so the hook may not use DOS and may not cause Wait() to be called.
*/

ULONG str_hookRoutine(struct Hook *hook, struct SGWork *sgw, ULONG *msg)
{
UBYTE *work_ptr;
ULONG return_code;

/* Hook must return non-zero if command is supported.
** This will be changed to zero if the command is unsupported.
*/
return_code = ~0L;

if (*msg == SGH_KEY)
    {
    /* key hit -- could be any key (Shift, repeat, character, etc.) */

    /* allow only upper case characters to be entered.
    ** act only on modes that add or update characters in the buffer.
    */
    if ((sgw->EditOp == EO_REPLACECHAR) ||
        (sgw->EditOp == EO_INSERTCHAR))
        {
        /* Code contains the ASCII representation of the character
        ** entered, if it maps to a single byte.  We could also look
        ** into the work buffer to find the new character.
        **
        **     sgw->Code == sgw->WorkBuffer[sgw->BufferPos - 1]
        **
        ** If the character is not a legal hex digit, don't use
        ** the work buffer and beep the screen.
        */
        if (!IsHexDigit(sgw->Code))
            {
            sgw->Actions |= SGA_BEEP;
            sgw->Actions &= ~SGA_USE;
            }
        else
            {
            /* And make it upper-case, for nicety */
            sgw->WorkBuffer[sgw->BufferPos - 1] = ToUpper(sgw->Code);
            }
        }
    }
else if (*msg == SGH_CLICK)
    {
    /* mouse click
    ** zero the digit clicked on
    */
    if (sgw->BufferPos < sgw->NumChars)
        {
        work_ptr = sgw->WorkBuffer + sgw->BufferPos;
        *work_ptr = '0';
        }
    }
else
    {
    /* UNKNOWN COMMAND
    ** hook should return zero if the command is not supported.
    */
    return_code = 0;
    }

return(return_code);
}

/*
** This is a function which converts register-parameter
** hook calling convention into standard C conventions.
** It only works with SAS C 5.0+
**
** Without the fancy __asm stuff, you'd probably need to
** write this in assembler.
**
** You could conceivably declare all your C hook functions
** this way, and eliminate the middleman (you'd initialize
** the h_Entry field to your C function's address, and not
** bother with the h_SubEntry field).
**
** This is nice and easy, though, and since we're using the
** small data model, using a single interface routine like this
** (which does the necessary __saveds), it might
** actually turn out to be smaller to use a single entry point
** like this rather than declaring each of many hooks __saveds.
*/
ULONG __saveds __asm hookEntry(register __a0 struct Hook *hookptr,
    register __a2 void  *object,
    register __a1 void  *message)
{
return((*hookptr->h_SubEntry)(hookptr, object, message));
}

/*
** Initialize the hook to use the hookEntry() routine above.
*/
void initHook(struct Hook *hook, ULONG (*ccode)())
{
hook->h_Entry    = hookEntry;
hook->h_SubEntry = ccode;
hook->h_Data     = 0;   /* this program does not use this */
}

/*
** Process messages received by the sgg_Window.  Quit when the close gadget
** is selected.
*/
VOID handleWindow(struct Vars *vars)
{
struct IntuiMessage *msg;
ULONG  class;
USHORT code;

for (;;)
    {
    Wait(1L << vars->sgg_Window->UserPort->mp_SigBit);
    while (msg =
            (struct IntuiMessage *)GetMsg(vars->sgg_Window->UserPort))
        {
        /* Stash message contents and reply, important when message
        ** triggers some lengthy processing
        */
        class = msg->Class;
        code  = msg->Code;
        ReplyMsg((struct Message *)msg);

        switch (class)
            {
            case IDCMP_GADGETUP:
                /* if a code is set in the hook after an SGH_KEY
                ** command, where SGA_END is set on return from
                ** the hook, the code will be returned in the Code
                ** field of the IDCMP_GADGETUP message.
                */
                break;
            case IDCMP_CLOSEWINDOW:
                return;
                break;
            }
        }
    }
}

/*
** IsHexDigit()
**
** Return TRUE if the character is a hex digit (0-9, A-F, a-f)
*/
BOOL IsHexDigit(UBYTE test_char)
{
test_char = ToUpper(test_char);
if (((test_char >= '0') && (test_char <= '9')) ||
    ((test_char >= 'A') && (test_char <= 'F')))
    return(TRUE);
else
    return(FALSE);
}


Lib_examples/updatestrgad.c

;/* updatestrgad.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 updatestrgad.c
Blink FROM LIB:c.o,updatestrgad.o TO updatestrgad LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
**
** The values of a string gadget may be updated by removing the gadget,
** modifying the information in the StringInfo structure, adding the
** gadget back and refreshing its imagery.
**
** updatestrgad.c - Show the use of a string gadget.  Shows both the use
** of ActivateGadget() and how to properly modify the contents of a string
** gadget.
*/
#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>

#include <string.h>
#include <stdio.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

/* our function prototypes */
VOID updateStrGad(struct Window *win, struct Gadget *gad, UBYTE *newstr);
VOID handleWindow(struct Window *win, struct Gadget *gad);

struct Library *IntuitionBase;

/* NOTE that the use of constant size and positioning values are
** not recommended; it just makes it easy to show what is going on.
** The position of the gadget should be dynamically adjusted depending
** on the height of the font in the title bar of the window.  This
** example adapts the gadget height to the screen font. Alternately,
** you could specify your font under V37 with the StringExtend structure.
*/
#define BUFSIZE (100)
#define MYSTRGADWIDTH (200)
#define MYSTRGADHEIGHT (8)

UWORD strBorderData[] =
    {
    0,0, MYSTRGADWIDTH + 3,0, MYSTRGADWIDTH + 3,MYSTRGADHEIGHT + 3,
    0,MYSTRGADHEIGHT + 3, 0,0,
    };
struct Border strBorder =
    {
    -2,-2,1,0,JAM1,5,strBorderData,NULL,
    };
UBYTE strBuffer[BUFSIZE];
UBYTE strUndoBuffer[BUFSIZE];
struct StringInfo strInfo =
    {
    strBuffer,strUndoBuffer,0,BUFSIZE, /* compiler sets remaining fields to zero */
    };
struct Gadget strGad =
    {
    NULL, 20,20,MYSTRGADWIDTH,MYSTRGADHEIGHT,
    GFLG_GADGHCOMP, GACT_RELVERIFY | GACT_STRINGCENTER,
    GTYP_STRGADGET, &strBorder, NULL, NULL,0,&strInfo,0,NULL,
    };

#define ANSCNT 4
UBYTE *answers[ANSCNT] = {"Try again","Sorry","Perhaps","A Winner"};
int ansnum = 0;
UBYTE *activated_txt = "Activated";

/*   main - show the use of a string gadget.
*/
VOID main(int argc, char **argv)
{
struct Window *win;

/* make sure to get intuition version 37, for OpenWindowTags() */
IntuitionBase = OpenLibrary("intuition.library", 37);
if (IntuitionBase)
    {
    /* Load a value into the string gadget buffer.
    ** This will be displayed when the gadget is first created.
    */
    strcpy(strBuffer, "START");

    if (win = OpenWindowTags(NULL,
                            WA_Width, 400,
                            WA_Height, 100,
                            WA_Title,"Activate Window, Enter Text",
                            WA_Gadgets, &strGad,
                            WA_CloseGadget, TRUE,
                            WA_IDCMP, IDCMP_ACTIVEWINDOW |
                                IDCMP_CLOSEWINDOW | IDCMP_GADGETUP,
                            TAG_END))
        {
        handleWindow(win,&strGad);

        CloseWindow(win);
        }
    CloseLibrary(IntuitionBase);
    }
}

/*
** Process messages received by the window.  Quit when the close gadget
** is selected, activate the gadget when the window becomes active.
*/
VOID handleWindow(struct Window *win, struct Gadget *gad)
{
struct IntuiMessage *msg;
struct Gadget *gadget;
ULONG  class;

for (;;)
    {
    Wait(1L << win->UserPort->mp_SigBit);
    while (msg = (struct IntuiMessage *)GetMsg(win->UserPort))
        {
        /* Stash message contents and reply, important when message
        ** triggers some lengthy processing
        */
        class = msg->Class;
    /* If it's a gadget message, IAddress points to Gadget */
        if((class == IDCMP_GADGETUP)||(class == IDCMP_GADGETDOWN))
                gadget = (struct Gadget *)msg->IAddress;
        ReplyMsg((struct Message *)msg);

        switch (class)
            {
            case IDCMP_ACTIVEWINDOW:
                /* activate the string gadget.  This is how to activate a
                ** string gadget in a new window--wait for the window to
                ** become active by waiting for the IDCMP_ACTIVEWINDOW
                ** event, then activate the gadget.  Here we report on
                ** the success or failure.
                */
                if(ActivateGadget(gad,win,NULL))
                    updateStrGad(win,gad,activated_txt);
                break;
            case IDCMP_CLOSEWINDOW:
                /* here is the way out of the loop and the routine.
                ** be sure that the message was replied...
                */
                return;
                break;
            case IDCMP_GADGETUP:
                /* If user hit RETURN in our string gadget for demonstration,
                ** we will change what he entered.  We only have 1 gadget,
                ** so we don't have to check which gadget.
                */
                updateStrGad(win, &strGad, answers[ansnum]);
        if(++ansnum > ANSCNT) ansnum = 0;  /* point to next answer */
                break;
            }
        }
    }
}

/*
** Routine to update the value in the string gadget's buffer, then
** activate the gadget.
*/
VOID updateStrGad(struct Window *win, struct Gadget *gad, UBYTE *newstr)
{
/* first, remove the gadget from the window.  this must be done before
** modifying any part of the gadget!!!
*/
RemoveGList(win,gad,1);

/* For fun, change the value in the buffer, as well as the cursor and
** initial display position.
*/
strcpy(((struct StringInfo *)(gad->SpecialInfo))->Buffer, newstr);
((struct StringInfo *)(gad->SpecialInfo))->BufferPos = 0;
((struct StringInfo *)(gad->SpecialInfo))->DispPos   = 0;

/* Add the gadget back, placing it at the end of the list (~0)
** and refresh its imagery.
*/
AddGList(win,gad,~0,1,NULL);
RefreshGList(gad,win,NULL,1);

/* Activate the string gadget */
ActivateGadget(gad,win,NULL);
}


Lib_examples/gadtoolsgadgets.c

/* gadtoolsgadgets.c
** Simple example of using a number of gadtools gadgets.
**
** Here's a working example showing how to set up and use a linked list
** of GadTools gadgets complete with keyboard shortcuts.
**
** Compiled with SAS C v5.10a
** lc -b1 -cfistq -v -y gadtoolsgadgets
** blink FROM LIB:c.o gadtoolsgadgets.o TO gadtoolsgadgets LIB LIB:lc.lib LIB:amiga.lib
*/
#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <libraries/gadtools.h>

#include <clib/exec_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
#include <clib/gadtools_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

/* Gadget defines of our choosing, to be used as GadgetID's,
** also used as the index into the gadget array my_gads[].
*/
#define MYGAD_SLIDER    (0)
#define MYGAD_STRING1   (1)
#define MYGAD_STRING2   (2)
#define MYGAD_STRING3   (3)
#define MYGAD_BUTTON    (4)

/* Range for the slider: */
#define SLIDER_MIN  (1)
#define SLIDER_MAX (20)

struct TextAttr Topaz80 = { "topaz.font", 8, 0, 0, };

struct Library      *IntuitionBase;
struct Library      *GfxBase;
struct Library      *GadToolsBase;

/* Print any error message.  We could do more fancy handling (like
** an EasyRequest()), but this is only a demo.
*/
void errorMessage(STRPTR error)
{
if (error)
    printf("Error: %s\n", error);
}

/*
** Function to handle a GADGETUP or GADGETDOWN event.  For GadTools gadgets,
** it is possible to use this function to handle MOUSEMOVEs as well, with
** little or no work.
*/
VOID handleGadgetEvent(struct Window *win, struct Gadget *gad, UWORD code,
    WORD *slider_level, struct Gadget *my_gads[])
{
switch (gad->GadgetID)
    {
    case MYGAD_SLIDER:
        /* Sliders report their level in the IntuiMessage Code field: */
        printf("Slider at level %ld\n", code);
        *slider_level = code;
        break;
    case MYGAD_STRING1:
        /* String gadgets report GADGETUP's */
        printf("String gadget 1: '%s'.\n",
                ((struct StringInfo *)gad->SpecialInfo)->Buffer);
        break;
    case MYGAD_STRING2:
        /* String gadgets report GADGETUP's */
        printf("String gadget 2: '%s'.\n",
                ((struct StringInfo *)gad->SpecialInfo)->Buffer);
        break;
    case MYGAD_STRING3:
        /* String gadgets report GADGETUP's */
        printf("String gadget 3: '%s'.\n",
                ((struct StringInfo *)gad->SpecialInfo)->Buffer);
        break;
    case MYGAD_BUTTON:
        /* Buttons report GADGETUP's (button resets slider to 10) */
        printf("Button was pressed, slider reset to 10.\n");
        *slider_level = 10;
        GT_SetGadgetAttrs(my_gads[MYGAD_SLIDER], win, NULL,
                            GTSL_Level, *slider_level,
                            TAG_END);
        break;
    }
}

/*
** Function to handle vanilla keys.
*/
VOID handleVanillaKey(struct Window *win, UWORD code,
    WORD *slider_level, struct Gadget *my_gads[])
{
switch (code)
    {
    case 'v':
        /* increase slider level, but not past maximum */
        if (++*slider_level > SLIDER_MAX)
            *slider_level = SLIDER_MAX;
        GT_SetGadgetAttrs(my_gads[MYGAD_SLIDER], win, NULL,
                            GTSL_Level, *slider_level,
                            TAG_END);
        break;
    case 'V':
        /* decrease slider level, but not past minimum */
        if (--*slider_level < SLIDER_MIN)
            *slider_level = SLIDER_MIN;
        GT_SetGadgetAttrs(my_gads[MYGAD_SLIDER], win, NULL,
                            GTSL_Level, *slider_level,
                            TAG_END);
        break;
    case 'c':
    case 'C':
        /* button resets slider to 10 */
        *slider_level = 10;
        GT_SetGadgetAttrs(my_gads[MYGAD_SLIDER], win, NULL,
                            GTSL_Level, *slider_level,
                            TAG_END);
        break;
    case 'f':
    case 'F':
        ActivateGadget(my_gads[MYGAD_STRING1], win, NULL);
        break;
    case 's':
    case 'S':
        ActivateGadget(my_gads[MYGAD_STRING2], win, NULL);
        break;
    case 't':
    case 'T':
        ActivateGadget(my_gads[MYGAD_STRING3], win, NULL);
        break;
    }
}

/*
** Here is where all the initialization and creation of GadTools gadgets
** take place.  This function requires a pointer to a NULL-initialized
** gadget list pointer.  It returns a pointer to the last created gadget,
** which can be checked for success/failure.
*/
struct Gadget *createAllGadgets(struct Gadget **glistptr, void *vi,
    UWORD topborder, WORD slider_level, struct Gadget *my_gads[])
{
struct NewGadget ng;
struct Gadget *gad;

/* All the gadget creation calls accept a pointer to the previous gadget, and
** link the new gadget to that gadget's NextGadget field.  Also, they exit
** gracefully, returning NULL, if any previous gadget was NULL.  This limits
** the amount of checking for failure that is needed.  You only need to check
** before you tweak any gadget structure or use any of its fields, and finally
** once at the end, before you add the gadgets.
*/

/* The following operation is required of any program that uses GadTools.
** It gives the toolkit a place to stuff context data.
*/
gad = CreateContext(glistptr);

/* Since the NewGadget structure is unmodified by any of the CreateGadget()
** calls, we need only change those fields which are different.
*/
ng.ng_LeftEdge   = 140;
ng.ng_TopEdge    = 20+topborder;
ng.ng_Width      = 200;
ng.ng_Height     = 12;
ng.ng_GadgetText = "_Volume:   ";
ng.ng_TextAttr   = &Topaz80;
ng.ng_VisualInfo = vi;
ng.ng_GadgetID   = MYGAD_SLIDER;
ng.ng_Flags      = NG_HIGHLABEL;

my_gads[MYGAD_SLIDER] = gad = CreateGadget(SLIDER_KIND, gad, &ng,
                    GTSL_Min,         SLIDER_MIN,
                    GTSL_Max,         SLIDER_MAX,
                    GTSL_Level,       slider_level,
                    GTSL_LevelFormat, "%2ld",
                    GTSL_MaxLevelLen, 2,
                    GT_Underscore,    '_',
                    TAG_END);

ng.ng_TopEdge   += 20;
ng.ng_Height     = 14;
ng.ng_GadgetText = "_First:";
ng.ng_GadgetID   = MYGAD_STRING1;
my_gads[MYGAD_STRING1] = gad = CreateGadget(STRING_KIND, gad, &ng,
                    GTST_String,   "Try pressing",
                    GTST_MaxChars, 50,
                    GT_Underscore, '_',
                    TAG_END);

ng.ng_TopEdge   += 20;
ng.ng_GadgetText = "_Second:";
ng.ng_GadgetID   = MYGAD_STRING2;
my_gads[MYGAD_STRING2] = gad = CreateGadget(STRING_KIND, gad, &ng,
                    GTST_String,   "TAB or Shift-TAB",
                    GTST_MaxChars, 50,
                    GT_Underscore, '_',
                    TAG_END);

ng.ng_TopEdge   += 20;
ng.ng_GadgetText = "_Third:";
ng.ng_GadgetID   = MYGAD_STRING3;
my_gads[MYGAD_STRING3] = gad = CreateGadget(STRING_KIND, gad, &ng,
                    GTST_String,   "To see what happens!",
                    GTST_MaxChars, 50,
                    GT_Underscore, '_',
                    TAG_END);

ng.ng_LeftEdge  += 50;
ng.ng_TopEdge   += 20;
ng.ng_Width      = 100;
ng.ng_Height     = 12;
ng.ng_GadgetText = "_Click Here";
ng.ng_GadgetID   = MYGAD_BUTTON;
ng.ng_Flags      = 0;
gad = CreateGadget(BUTTON_KIND, gad, &ng,
                    GT_Underscore, '_',
                    TAG_END);
return(gad);
}

/*
** Standard message handling loop with GadTools message handling functions
** used (GT_GetIMsg() and GT_ReplyIMsg()).
*/
VOID process_window_events(struct Window *mywin,
    WORD *slider_level, struct Gadget *my_gads[])
{
struct IntuiMessage *imsg;
ULONG imsgClass;
UWORD imsgCode;
struct Gadget *gad;
BOOL terminated = FALSE;

while (!terminated)
    {
    Wait (1 << mywin->UserPort->mp_SigBit);

    /* GT_GetIMsg() returns an IntuiMessage with more friendly information for
    ** complex gadget classes.  Use it wherever you get IntuiMessages where
    ** using GadTools gadgets.
    */
    while ((!terminated) &&
           (imsg = GT_GetIMsg(mywin->UserPort)))
        {
        /* Presuming a gadget, of course, but no harm...
        ** Only dereference this value (gad) where the Class specifies
        ** that it is a gadget event.
        */
        gad = (struct Gadget *)imsg->IAddress;

        imsgClass = imsg->Class;
        imsgCode = imsg->Code;

        /* Use the toolkit message-replying function here... */
        GT_ReplyIMsg(imsg);

        switch (imsgClass)
            {
            /*  --- WARNING --- WARNING --- WARNING --- WARNING --- WARNING ---
            ** GadTools puts the gadget address into IAddress of IDCMP_MOUSEMOVE
            ** messages.  This is NOT true for standard Intuition messages,
            ** but is an added feature of GadTools.
            */
            case IDCMP_GADGETDOWN:
            case IDCMP_MOUSEMOVE:
            case IDCMP_GADGETUP:
                handleGadgetEvent(mywin, gad, imsgCode, slider_level, my_gads);
                break;
            case IDCMP_VANILLAKEY:
                handleVanillaKey(mywin, imsgCode, slider_level, my_gads);
                break;
            case IDCMP_CLOSEWINDOW:
                terminated = TRUE;
                break;
            case IDCMP_REFRESHWINDOW:
                /* With GadTools, the application must use GT_BeginRefresh()
                ** where it would normally have used BeginRefresh()
                */
                GT_BeginRefresh(mywin);
                GT_EndRefresh(mywin, TRUE);
                break;
            }
        }
    }
}

/*
** Prepare for using GadTools, set up gadgets and open window.
** Clean up and when done or on error.
*/
VOID gadtoolsWindow(VOID)
{
struct TextFont *font;
struct Screen   *mysc;
struct Window   *mywin;
struct Gadget   *glist, *my_gads[4];
void            *vi;
WORD            slider_level = 5;
UWORD           topborder;

/* Open topaz 8 font, so we can be sure it's openable
** when we later set ng_TextAttr to &Topaz80:
*/
if (NULL == (font = OpenFont(&Topaz80)))
    errorMessage( "Failed to open Topaz 80");
else
    {
    if (NULL == (mysc = LockPubScreen(NULL)))
        errorMessage( "Couldn't lock default public screen");
    else
        {
        if (NULL == (vi = GetVisualInfo(mysc, TAG_END)))
            errorMessage( "GetVisualInfo() failed");
        else
            {
            /* Here is how we can figure out ahead of time how tall the  */
            /* window's title bar will be:                               */
            topborder = mysc->WBorTop + (mysc->Font->ta_YSize + 1);

            if (NULL == createAllGadgets(&glist, vi, topborder,
                                         slider_level, my_gads))
                errorMessage( "createAllGadgets() failed");
            else
                {
                if (NULL == (mywin = OpenWindowTags(NULL,
                        WA_Title,     "GadTools Gadget Demo",
                        WA_Gadgets,   glist,      WA_AutoAdjust,    TRUE,
                        WA_Width,       400,      WA_MinWidth,        50,
                        WA_InnerHeight, 140,      WA_MinHeight,       50,
                        WA_DragBar,    TRUE,      WA_DepthGadget,   TRUE,
                        WA_Activate,   TRUE,      WA_CloseGadget,   TRUE,
                        WA_SizeGadget, TRUE,      WA_SimpleRefresh, TRUE,
                        WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_REFRESHWINDOW |
                            IDCMP_VANILLAKEY | SLIDERIDCMP | STRINGIDCMP |
                            BUTTONIDCMP,
                        WA_PubScreen, mysc,
                        TAG_END)))
                    errorMessage( "OpenWindow() failed");
                else
                    {
                    /* After window is open, gadgets must be refreshed with a
                    ** call to the GadTools refresh window function.
                    */
                    GT_RefreshWindow(mywin, NULL);

                    process_window_events(mywin, &slider_level, my_gads);

                    CloseWindow(mywin);
                    }
                }
            /* FreeGadgets() even if createAllGadgets() fails, as some
            ** of the gadgets may have been created...If glist is NULL
            ** then FreeGadgets() will do nothing.
            */
            FreeGadgets(glist);
            FreeVisualInfo(vi);
            }
        UnlockPubScreen(NULL, mysc);
        }
    CloseFont(font);
    }
}

/*
** Open all libraries and run.  Clean up when finished or on error..
*/
void main(void)
{
if (NULL == (IntuitionBase = OpenLibrary("intuition.library", 37)))
    errorMessage( "Requires V37 intuition.library");
else
    {
    if (NULL == (GfxBase = OpenLibrary("graphics.library", 37)))
        errorMessage( "Requires V37 graphics.library");
    else
        {
        if (NULL == (GadToolsBase = OpenLibrary("gadtools.library", 37)))
            errorMessage( "Requires V37 gadtools.library");
        else
            {
            gadtoolsWindow();

            CloseLibrary(GadToolsBase);
            }
        CloseLibrary(GfxBase);
        }
    CloseLibrary(IntuitionBase);
    }
}


Lib_examples/simplegtgadget.c

;/* simplegtgadget.c -- execute me to compile me
lc -b1 -cfistq -v -y simplegtgadget
blink FROM LIB:c.o simplegtgadget.o TO simplegtgadget LIB LIB:lc.lib LIB:amiga.lib
quit
**
** The example listed here shows how to use the NewGadget structure and
** the GadTools library functions discussed above to create a simple
** button gadget.
**
** Simple example of a GadTools gadget.  Compiled with SAS C v5.10a
*/
#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <libraries/gadtools.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/gadtools_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

/* Gadget defines of our choosing, to be used as GadgetID's. */
#define MYGAD_BUTTON    (4)

VOID process_window_events(struct Window *);
VOID gadtoolsWindow(VOID);

struct TextAttr Topaz80 = { "topaz.font", 8, 0, 0, };

struct Library *IntuitionBase;
struct Library *GadToolsBase;

/*
** Open all libraries and run.  Clean up when finished or on error..
*/
void main(void)
{
if ( (IntuitionBase = OpenLibrary("intuition.library", 37)) != NULL )
    {
    if ( (GadToolsBase = OpenLibrary("gadtools.library", 37)) != NULL )
        {
        gadtoolsWindow();

        CloseLibrary(GadToolsBase);
        }
    CloseLibrary(IntuitionBase);
    }
}

/*
** Prepare for using GadTools, set up gadgets and open window.
** Clean up and when done or on error.
*/
VOID gadtoolsWindow(VOID)
{
struct Screen    *mysc;
struct Window    *mywin;
struct Gadget    *glist, *gad;
struct NewGadget ng;
void             *vi;

glist = NULL;

if ( (mysc = LockPubScreen(NULL)) != NULL )
    {
    if ( (vi = GetVisualInfo(mysc, TAG_END)) != NULL )
        {
        /* GadTools gadgets require this step to be taken */
        gad = CreateContext(&glist);

        /* create a button gadget centered below the window title */
        ng.ng_TextAttr   = &Topaz80;
        ng.ng_VisualInfo = vi;
        ng.ng_LeftEdge   = 150;
        ng.ng_TopEdge    = 20 + mysc->WBorTop + (mysc->Font->ta_YSize + 1);
        ng.ng_Width      = 100;
        ng.ng_Height     = 12;
        ng.ng_GadgetText = "Click Here";
        ng.ng_GadgetID   = MYGAD_BUTTON;
        ng.ng_Flags      = 0;
        gad = CreateGadget(BUTTON_KIND, gad, &ng, TAG_END);

        if (gad != NULL)
            {
            if ( (mywin = OpenWindowTags(NULL,
                    WA_Title,     "GadTools Gadget Demo",
                    WA_Gadgets,   glist,      WA_AutoAdjust,    TRUE,
                    WA_Width,       400,      WA_InnerHeight,    100,
                    WA_DragBar,    TRUE,      WA_DepthGadget,   TRUE,
                    WA_Activate,   TRUE,      WA_CloseGadget,   TRUE,
                    WA_IDCMP, IDCMP_CLOSEWINDOW |
                              IDCMP_REFRESHWINDOW | BUTTONIDCMP,
                    WA_PubScreen,   mysc,
                    TAG_END)) != NULL )
                {
                GT_RefreshWindow(mywin, NULL);

                process_window_events(mywin);

                CloseWindow(mywin);
                }
            }
        /* FreeGadgets() must be called after the context has been
        ** created.  It does nothing if glist is NULL
        */
        FreeGadgets(glist);
        FreeVisualInfo(vi);
        }
    UnlockPubScreen(NULL, mysc);
    }
}

/*
** Standard message handling loop with GadTools message handling functions
** used (GT_GetIMsg() and GT_ReplyIMsg()).
*/
VOID process_window_events(struct Window *mywin)
{
struct IntuiMessage *imsg;
struct Gadget *gad;
BOOL  terminated = FALSE;

while (!terminated)
    {
    Wait (1 << mywin->UserPort->mp_SigBit);

    /* Use GT_GetIMsg() and GT_ReplyIMsg() for handling */
    /* IntuiMessages with GadTools gadgets.             */
    while ((!terminated) && (imsg = GT_GetIMsg(mywin->UserPort)))
        {
        /* GT_ReplyIMsg() at end of loop */

        switch (imsg->Class)
            {
            case IDCMP_GADGETUP:       /* Buttons only report GADGETUP */
                gad = (struct Gadget *)imsg->IAddress;
                if (gad->GadgetID == MYGAD_BUTTON)
                        printf("Button was pressed.\n");
                break;
            case IDCMP_CLOSEWINDOW:
                terminated = TRUE;
                break;
            case IDCMP_REFRESHWINDOW:
                /* This handling is REQUIRED with GadTools. */
                GT_BeginRefresh(mywin);
                GT_EndRefresh(mywin, TRUE);
                break;
            }
        /* Use the toolkit message-replying function here... */
        GT_ReplyIMsg(imsg);
        }
    }
}


Lib_examples/gadtoolsmenu.c

/* The functions used to set up and control GadTools menus are discussed
 * in the next section.  Before looking at these functions in detail, it
 * may be helpful to look at a brief example.
 */

/* gadtoolsmenu.c
** Example showing the basic usage of the menu system with a window.
** Menu layout is done with GadTools, as is recommended for applications.
**
** Compiled with SAS C v5.10a
** lc -b1 -cfistq -v -y gadtoolsmenu
** blink FROM LIB:c.o gadtoolsmenu.o TO gadtoolsmenu LIB LIB:lc.lib LIB:amiga.lib
*/

#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <libraries/gadtools.h>

#include <clib/exec_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/intuition_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

struct Library *GadToolsBase;
struct IntuitionBase *IntuitionBase;

struct NewMenu mynewmenu[] =
    {
        { NM_TITLE, "Project",    0 , 0, 0, 0,},
        {  NM_ITEM, "Open...",   "O", 0, 0, 0,},
        {  NM_ITEM, "Save",      "S", 0, 0, 0,},
        {  NM_ITEM, NM_BARLABEL,  0 , 0, 0, 0,},
        {  NM_ITEM, "Print",      0 , 0, 0, 0,},
        {   NM_SUB, "Draft",      0 , 0, 0, 0,},
        {   NM_SUB, "NLQ",        0 , 0, 0, 0,},
        {  NM_ITEM, NM_BARLABEL,  0 , 0, 0, 0,},
        {  NM_ITEM, "Quit...",   "Q", 0, 0, 0,},

        { NM_TITLE, "Edit",       0 , 0, 0, 0,},
        {  NM_ITEM, "Cut",       "X", 0, 0, 0,},
        {  NM_ITEM, "Copy",      "C", 0, 0, 0,},
        {  NM_ITEM, "Paste",     "V", 0, 0, 0,},
        {  NM_ITEM, NM_BARLABEL,  0 , 0, 0, 0,},
        {  NM_ITEM, "Undo",      "Z", 0, 0, 0,},

        {   NM_END, NULL,         0 , 0, 0, 0,},
    };

/*
** Watch the menus and wait for the user to select the close gadget
** or quit from the menus.
*/
VOID handle_window_events(struct Window *win, struct Menu *menuStrip)
{
struct IntuiMessage *msg;
SHORT done;
UWORD menuNumber;
UWORD menuNum;
UWORD itemNum;
UWORD subNum;
struct MenuItem *item;

done = FALSE;
while (FALSE == done)
    {
    /* we only have one signal bit, so we do not have to check which
    ** bit broke the Wait().
    */
    Wait(1L << win->UserPort->mp_SigBit);

    while ( (FALSE == done) &&
            (NULL != (msg = (struct IntuiMessage *)GetMsg(win->UserPort))))
        {
        switch (msg->Class)
            {
            case IDCMP_CLOSEWINDOW:
                done = TRUE;
                break;
            case IDCMP_MENUPICK:
                menuNumber = msg->Code;
                while ((menuNumber != MENUNULL) && (!done))
                    {
                    item = ItemAddress(menuStrip, menuNumber);

                    /* process the item here! */
                    menuNum = MENUNUM(menuNumber);
                    itemNum = ITEMNUM(menuNumber);
                    subNum  = SUBNUM(menuNumber);

                    /* stop if quit is selected. */
                    if ((menuNum == 0) && (itemNum == 5))
                        done = TRUE;

                    menuNumber = item->NextSelect;
                    }
                break;
            }
        ReplyMsg((struct Message *)msg);
        }
    }
}

/*
** Open all of the required libraries and set-up the menus.
*/
VOID main(int argc, char *argv[])
{
struct Window *win;
APTR *my_VisualInfo;
struct Menu *menuStrip;

/* Open the Intuition Library */
IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 37);
if (IntuitionBase != NULL)
    {
    /* Open the gadtools Library */
    GadToolsBase = OpenLibrary("gadtools.library", 37);
    if (GadToolsBase != NULL)
        {
        if (NULL != (win = OpenWindowTags(NULL,
                            WA_Width,  400,       WA_Activate,    TRUE,
                            WA_Height, 100,       WA_CloseGadget, TRUE,
                            WA_Title,  "Menu Test Window",
                            WA_IDCMP,  IDCMP_CLOSEWINDOW | IDCMP_MENUPICK,
                            TAG_END)))
            {
            if (NULL != (my_VisualInfo = GetVisualInfo(win->WScreen, TAG_END)))
                {
                if (NULL != (menuStrip = CreateMenus(mynewmenu, TAG_END)))
                    {
                    if (LayoutMenus(menuStrip, my_VisualInfo, TAG_END))
                        {
                        if (SetMenuStrip(win, menuStrip))
                            {
                            handle_window_events(win,menuStrip);

                            ClearMenuStrip(win);
                            }
                        FreeMenus(menuStrip);
                        }
                    }
                FreeVisualInfo(my_VisualInfo);
                }
            CloseWindow(win);
            }
        CloseLibrary((struct Library *)GadToolsBase);
        }
    CloseLibrary((struct Library *)IntuitionBase);
    }
}


Lib_examples/WBClone.c

/* The following program will create a display with the same attributes
** as the user's Workbench screen.  It does this by first inquiring as
** to those attributes, duplicating them, and then creating a similar
** display.
*/

/**********************************************************************/
/*                                                                    */
/*       WBClone.c: To clone the Workbench using graphics calls       */
/*                                                                    */
/*       Compile : SAS/C 5.10a LC -b1 -cfist -L -v -y                 */
/*                                                                    */
/**********************************************************************/

#include <exec/types.h>
#include <exec/exec.h>
#include <clib/exec_protos.h>
#include <intuition/screens.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <clib/intuition_protos.h>
#include <graphics/gfx.h>
#include <graphics/gfxbase.h>
#include <graphics/view.h>
#include <graphics/gfxnodes.h>
#include <graphics/videocontrol.h>
#include <clib/graphics_protos.h>

#include <stdio.h>
#include <stdlib.h>

#define INTUITIONNAME "intuition.library"

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

/*********************************************************************/
/*                            GLOBAL VARIABLES                       */
/*********************************************************************/

struct IntuitionBase *IntuitionBase = NULL ;
struct GfxBase *GfxBase = NULL ;

/**********************************************************************/
/*                                                                    */
/* VOID Error (char *String)                                          */
/*                                                                    */
/* Print string and exit                                              */
/*                                                                    */
/**********************************************************************/

VOID Error (char *String)
{
    VOID CloseAll (VOID) ;

    printf (String) ;

    CloseAll () ;
    exit(0) ;
}

/**********************************************************************/
/*                                                                    */
/* VOID Init ()                                                       */
/*                                                                    */
/* Opens all the required libraries allocates all memory, etc.        */
/*                                                                    */
/**********************************************************************/

VOID Init ( VOID )
{
    /* Open the intuition library.... */
    if ((IntuitionBase = (struct IntuitionBase *)OpenLibrary (INTUITIONNAME, 37L)) == NULL)
        Error ("Could not open the Intuition.library") ;

    /* Open the graphics library.... */
    if ((GfxBase = (struct GfxBase *)OpenLibrary (GRAPHICSNAME, 36L)) == NULL)
        Error ("Could not open the Graphics.library") ;
}

/**********************************************************************/
/*                                                                    */
/* VOID CloseAll ()                                                   */
/*                                                                    */
/* Closes and tidies up everything that was used.                     */
/*                                                                    */
/**********************************************************************/

VOID CloseAll ( VOID )
{
    /* Close everything in the reverse order in which they were opened */

    /* Close the Graphics Library */
    if (GfxBase)
        CloseLibrary ((struct Library *) GfxBase) ;

    /* Close the Intuition Library */
    if (IntuitionBase)
        CloseLibrary ((struct Library *) IntuitionBase) ;
}

/**********************************************************************/
/*                                                                    */
/* VOID DestroyView(struct View *view)                                */
/*                                                                    */
/* Close and free everything to do with the View                      */
/*                                                                    */
/**********************************************************************/

VOID DestroyView(struct View *view)
{
    struct ViewExtra *ve;

    if (view)
    {
        if (ve = (struct ViewExtra *)GfxLookUp(view))
        {
            if (ve->Monitor)
                CloseMonitor(ve->Monitor);

            GfxFree((struct ExtendedNode *)ve);
        }

        /* Free up the copper lists */
        if (view->LOFCprList)
            FreeCprList(view->LOFCprList);

        if (view->SHFCprList)
            FreeCprList(view->SHFCprList);

        FreeVec(view);
    }
}

/**********************************************************************/
/*                                                                    */
/* struct View *DupView(struct View *v, ULONG ModeID)                 */
/*                                                                    */
/* Duplicate the View.                                                */
/*                                                                    */
/**********************************************************************/

struct View *DupView(struct View *v, ULONG ModeID)
{
    /* Allocate and init a View structure.  Also, get a ViewExtra
     * structure and attach the monitor type to the View.
     */

    struct View *view = NULL;
    struct ViewExtra *ve = NULL;
    struct MonitorSpec *mspc = NULL;

    if (view = AllocVec(sizeof(struct View), MEMF_PUBLIC | MEMF_CLEAR))
    {
        if (ve = GfxNew(VIEW_EXTRA_TYPE))
        {
            if (mspc = OpenMonitor(NULL, ModeID))
            {
                InitView(view);
                view->DyOffset = v->DyOffset;
                view->DxOffset = v->DxOffset;
                view->Modes = v->Modes;
                GfxAssociate(view, (struct ExtendedNode *)ve);
                ve->Monitor = mspc;
            }
            else printf("Could not open monitor\n");
        }
        else printf("Could not get ViewExtra\n");
    }
    else printf("Could not create View\n");

    if (view && ve && mspc)
        return(view);
    else
    {
        DestroyView(view);
        return(NULL);
    }
}

/**********************************************************************/
/*                                                                    */
/* VOID DestroyViewPort(struct ViewPort *vp)                          */
/*                                                                    */
/* Close and free everything to do with the ViewPort.                 */
/*                                                                    */
/**********************************************************************/

VOID DestroyViewPort(struct ViewPort *vp)
{
    if (vp)
    {
        /* Find the ViewPort's ColorMap. From that use VideoControl
         *  to get the ViewPortExtra, and free it.
         * Then free the ColorMap, and finally the ViewPort itself.
         */
        struct ColorMap *cm = vp->ColorMap;
        struct TagItem ti[] =
        {
            {VTAG_VIEWPORTEXTRA_GET, NULL},	/* <-- This field will be filled in */
            {VTAG_END_CM, NULL}
        };

        if (cm)
        {
            if (VideoControl(cm, ti) == NULL)
                GfxFree((struct ExtendedNode *)ti[0].ti_Data);
            else
                printf("VideoControl error in DestroyViewPort()\n");

            FreeColorMap(cm);
        }
        else
        {
            printf("Could not free the ColorMap\n");
        }

        FreeVPortCopLists(vp);

        FreeVec(vp);
    }
}

/**********************************************************************/
/*                                                                    */
/* struct ViewPort *DupViewPort(struct ViewPort *vp, ULONG ModeID)    */
/*                                                                    */
/* Duplicate the ViewPort.                                            */
/*                                                                    */
/**********************************************************************/

struct ViewPort *DupViewPort(struct ViewPort *vp, ULONG ModeID)
{
    /* Allocate and initialise a ViewPort. Copy the ViewPort width and
     * heights, offsets, and modes values.  Allocate and initialize a
     * ColorMap.
     *
     * Also, allocate a ViewPortExtra, and copy the TextOScan values of the
     * ModeID from the database into the ViewPortExtra.
     */

    #define COLOURS 32
    struct ViewPort *Myvp;
    struct ViewPortExtra *vpe;
    struct ColorMap *cm;
    struct TagItem ti[] = 			/* to attach everything */
    {
        {VTAG_ATTACH_CM_SET, NULL},	/* these NULLs will be replaced in the code */
        {VTAG_VIEWPORTEXTRA_SET, NULL},
        {VTAG_NORMAL_DISP_SET, NULL},
        {VTAG_END_CM, NULL}
    };
    struct DimensionInfo query = {0};
    UWORD colour;
    int c;
    ULONG gotinfo = NULL;

    if (Myvp = AllocVec(sizeof(struct ViewPort), MEMF_CLEAR | MEMF_PUBLIC))
    {
        if (vpe = (struct ViewPortExtra *)GfxNew(VIEWPORT_EXTRA_TYPE))
        {
            if (cm = GetColorMap(32))
            {
                if (gotinfo = GetDisplayInfoData(NULL, (APTR)&query,
                                                                 sizeof(query), DTAG_DIMS, ModeID))
                {
                    InitVPort(Myvp);

                    /* duplicate the ViewPort structure */
                    Myvp->DWidth = vp->DWidth;
                    Myvp->DHeight = vp->DHeight;
                    Myvp->DxOffset = vp->DxOffset;
                    Myvp->DyOffset = vp->DyOffset;
                    Myvp->Modes = vp->Modes;
                    Myvp->SpritePriorities = vp->SpritePriorities;
                    Myvp->ExtendedModes = vp->ExtendedModes;

                    /* duplicate the Overscan values */
                    vpe->DisplayClip = query.TxtOScan;

                    /* attach everything together */
                    ti[0].ti_Data = (ULONG)Myvp;
                    ti[1].ti_Data = (ULONG)vpe;
                    ti[2].ti_Data = (ULONG)FindDisplayInfo(ModeID);
                    if (VideoControl(cm, ti) != NULL)
                    {
                        printf("VideoControl error in CreateViewPort()\n");
                    }

                    /* copy the colours from the workbench */
                    for (c = 0; c < COLOURS; c++)
                    {
                        if ((colour = GetRGB4(vp->ColorMap, c)) != -1)
                        {
                        SetRGB4CM(cm, c, (colour >> 8),
                              ((colour >> 4) & 0xf), (colour & 0xf));
                        }
                    }
                }
                else printf("Database error\n");
            }
            else printf("Could not get the ColorMap\n");
        }
        else printf("Could not get the ViewPortExtra\n");
    }
    else printf("Could not get the ViewPort\n");

    if (Myvp && vpe && cm && gotinfo)
        return(Myvp);
    else
    {
        DestroyViewPort(vp);
        return(NULL);
    }
}

/***********************************************************************************/
/*                                                                                 */
/* VOID DestroyBitMap(struct BitMap *Mybm, SHORT width, SHORT height, SHORT depth) */
/*                                                                                 */
/* Close and free everything to do with the BitMap                                 */
/*                                                                                 */
/***********************************************************************************/

VOID DestroyBitMap(struct BitMap *Mybm, SHORT width, SHORT height, SHORT depth)
{
    int i;

    if (Mybm)
    {
        for (i = 0; (i < depth); i++)
        {
            if (Mybm->Planes[i])
                FreeRaster(Mybm->Planes[i], width, height);
        }
        FreeVec(Mybm);
    }
}

/***********************************************************************/
/*                                                                     */
/* struct BitMap *CreateBitMap(SHORT width, SHORT height, SHORT depth) */
/*                                                                     */
/* Create the BitMap.                                                  */
/*                                                                     */
/***********************************************************************/

struct BitMap *CreateBitMap(SHORT width, SHORT height, SHORT depth)
{
    /* Allocate a BitMap structure, initialise it, and allocate each plane. */

    struct BitMap *Mybm;
    PLANEPTR allocated = (PLANEPTR) 1;
    int i;

    if (Mybm = AllocVec(sizeof(struct BitMap), MEMF_CLEAR | MEMF_PUBLIC))
    {
        InitBitMap(Mybm, depth, width, height);
        for (i = 0; ((i < depth) && (allocated)); i++)
            allocated = (Mybm->Planes[i] = AllocRaster(width, height));

        if (allocated == NULL)
        {
            printf("Could not allocate all the planes\n");
            DestroyBitMap(Mybm, width, height, depth);
            Mybm = NULL;
        }
    }
    else printf("Could not get BitMap\n");

    return(Mybm);
}

/********************************************************************************/
/*                                                                              */
/* VOID ShowView(struct View *view, struct ViewPort *vp, struct BitMap *bm,    */
/*                                                SHORT width, SHORT height)    */
/*                                                                              */
/* Assemble and display the View.                                               */
/*                                                                              */
/********************************************************************************/

VOID ShowView(struct View *view, struct ViewPort *vp, struct BitMap *bm,
                                               SHORT width, SHORT height)
{
    /* Attach the BitMap to the ViewPort via a RasInfo.  Attach the ViewPort
     * to the View.  Clear the BitMap, and draw into it by attaching the BitMap
     * to a RastPort.  Then MakeVPort(), MrgCop() and LoadView().
     * Just wait for the user to press <RETURN> before returning.
     */

    struct RastPort *rp;
    struct RasInfo *ri;

    if (rp = AllocVec(sizeof(struct RastPort), MEMF_CLEAR | MEMF_PUBLIC))
    {
        if (ri = AllocVec(sizeof(struct RasInfo), MEMF_CLEAR | MEMF_PUBLIC))
        {
            InitRastPort(rp);
            ri->BitMap = rp->BitMap = bm;
            vp->RasInfo = ri;
            view->ViewPort = vp;

            /* render */
            SetRast(rp, 0);		/* clear the background */
            SetAPen(rp, ((1 << bm->Depth) - 1));	/* use the last pen */
            Move(rp, 0, 0);
            Draw(rp, width, 0);
            Draw(rp, width, height);
            Draw(rp, 0, height);
            Draw(rp, 0, 0);

            /* display it */
            MakeVPort(view, vp);
            MrgCop(view);
            LoadView(view);

            getchar();

            /* bring back the system */
            RethinkDisplay();

            FreeVec(ri);
        }
        else printf("Could not get RasInfo\n");

        FreeVec(rp);
    }
    else printf("Could not get RastPort\n");

}

/**********************************************************************/
/*                                                                    */
/* VOID main (int argc, char *argv[])                                 */
/*                                                                    */
/* Clone the Workbench View using Graphics Library calls.             */
/*                                                                    */
/**********************************************************************/

VOID main (int argc, char *argv[])
{
    struct Screen *wb;
    struct View *Myview;
    struct ViewPort *Myvp;
    struct BitMap *Mybm;
    ULONG ModeID;
    ULONG IbaseLock;

    Init () ;		/* to open the libraries */

    /* To clone the Workbench using graphics calls involves duplicating
     * the Workbench ViewPort, ViewPort mode, and Intuition's View.
     * This also involves duplicating the DisplayClip for the overscan
     * value, the colours, and the View position.
     *
     * When this is all done, the View, ViewPort, ColorMap and BitMap
     * (and ViewPortExtra, ViewExtra and RasInfo) all have to be linked
     * together, and the copperlists made to create the display.
     *
     * This is not as difficult as it sounds (trust me!)
     */

    /* First, lock the Workbench screen, so no changes can be made to it
     * while we are duplicating it.
     */
    if (wb = LockPubScreen("Workbench"))
    {
        /* Find the Workbench's ModeID. This is a 32-bit number that
         * identifies the monitor type, and the display mode of that monitor.
         */
        ModeID = GetVPModeID(&wb->ViewPort);

        /* We need to duplicate Intuition's View structure, so lock IntuitionBase
         * to prevent the View changing under our feet.
         */
        IbaseLock = LockIBase(0);
        if (Myview = DupView(&IntuitionBase->ViewLord, ModeID))
        {
            /* The View has been cloned, so we don't need to keep it locked. */
            UnlockIBase(IbaseLock);

            /* Now duplicate the Workbench's ViewPort. Remember, we still have
             * the Workbench locked.
             */
            if (Myvp = DupViewPort(&wb->ViewPort, ModeID))
            {
                /* Create a BitMap to render into. This will be of the
                 * same dimensions as the Workbench.
                 */
                if (Mybm = CreateBitMap(wb->Width, wb->Height, wb->BitMap.Depth))
                {
                    /* Now we have everything copied, show something */
                    ShowView(Myview, Myvp, Mybm, wb->Width-1, wb->Height-1);

                    /* Now free up everything we have allocated */
                    DestroyBitMap(Mybm, wb->Width, wb->Height, wb->BitMap.Depth);
                }
                DestroyViewPort(Myvp);
            }
            DestroyView(Myview);
        }
        else
        {
            UnlockIBase(IbaseLock);
        }
        UnlockPubScreen(NULL, wb);
    }
    CloseAll () ;
}


Lib_examples/animtools.c

/* animtools.c
**
** This file is a collection of tools which are used with the VSprite, Bob and Animation
** system software. It is intended as a useful EXAMPLE, and while it shows what must be
** done, it is not the only way to do it.  If Not Enough Memory, or error return, each
** cleans up after itself before returning.  NOTE that these routines assume a very specific
** structure to the GEL lists.  Make sure that you use the correct pairs together
** (i.e. makeOb()/freeOb(), etc.)
**
** Compile with SAS/C 5.10b: lc -b1 -cfist -v -y -oanimtools.o animtools.c
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <graphics/gfx.h>
#include <graphics/gels.h>
#include <graphics/clip.h>
#include <graphics/rastport.h>
#include <graphics/view.h>
#include <graphics/gfxbase.h>
#include "animtools.h"

/* Setup the GELs system.  After this call is made you can use VSprites, Bobs, AnimComps
** and AnimObs.  Note that this links the GelsInfo structure into the RastPort, and calls
** InitGels().  It uses information in your RastPort structure to establish boundary collision
** defaults at the outer edges of the raster.  This routine sets up for everything - collision
** detection and all. You must already have run LoadView before ReadyGelSys is called.
*/
struct GelsInfo *setupGelSys(struct RastPort *rPort, BYTE reserved)
{
struct GelsInfo *gInfo;
struct VSprite  *vsHead;
struct VSprite  *vsTail;

if (NULL != (gInfo = (struct GelsInfo *)AllocMem(sizeof(struct GelsInfo), MEMF_CLEAR)))
        {
        if (NULL != (gInfo->nextLine = (WORD *)AllocMem(sizeof(WORD) * 8, MEMF_CLEAR)))
            {
            if (NULL != (gInfo->lastColor = (WORD **)AllocMem(sizeof(LONG) * 8, MEMF_CLEAR)))
                {
                if (NULL != (gInfo->collHandler = (struct collTable *)
                        AllocMem(sizeof(struct collTable),MEMF_CLEAR)))
                    {
                    if (NULL != (vsHead = (struct VSprite *)
                            AllocMem((LONG)sizeof(struct VSprite), MEMF_CLEAR)))
                        {
                        if (NULL != (vsTail = (struct VSprite *)
                                AllocMem(sizeof(struct VSprite), MEMF_CLEAR)))
                            {
                            gInfo->sprRsrvd   = reserved;
                            /* Set left- and top-most to 1 to better keep items */
                            /* inside the display boundaries.                   */
                            gInfo->leftmost   = gInfo->topmost    = 1;
                            gInfo->rightmost  = (rPort->BitMap->BytesPerRow << 3) - 1;
                            gInfo->bottommost = rPort->BitMap->Rows - 1;
                            rPort->GelsInfo = gInfo;
                            InitGels(vsHead, vsTail, gInfo);
                            return(gInfo);
                            }
                        FreeMem(vsHead, (LONG)sizeof(*vsHead));
                        }
                    FreeMem(gInfo->collHandler, (LONG)sizeof(struct collTable));
                    }
                FreeMem(gInfo->lastColor, (LONG)sizeof(LONG) * 8);
                }
            FreeMem(gInfo->nextLine, (LONG)sizeof(WORD) * 8);
            }
        FreeMem(gInfo, (LONG)sizeof(*gInfo));
        }
return(NULL);
}

/* Free all of the stuff allocated by setupGelSys().  Only call this routine if
** setupGelSys() returned successfully.  The GelsInfo structure is the one returned
** by setupGelSys().   It also unlinks the GelsInfo from the RastPort.
*/
VOID cleanupGelSys(struct GelsInfo *gInfo, struct RastPort *rPort)
{
rPort->GelsInfo = NULL;
FreeMem(gInfo->collHandler, (LONG)sizeof(struct collTable));
FreeMem(gInfo->lastColor, (LONG)sizeof(LONG) * 8);
FreeMem(gInfo->nextLine, (LONG)sizeof(WORD) * 8);
FreeMem(gInfo->gelHead, (LONG)sizeof(struct VSprite));
FreeMem(gInfo->gelTail, (LONG)sizeof(struct VSprite));
FreeMem(gInfo, (LONG)sizeof(*gInfo));
}

/* Create a VSprite from the information given in nVSprite.  Use freeVSprite()
** to free this GEL.
*/
struct VSprite *makeVSprite(NEWVSPRITE *nVSprite)
{
struct VSprite *vsprite;
LONG            line_size;
LONG            plane_size;

line_size = sizeof(WORD) * nVSprite->nvs_WordWidth;
plane_size = line_size * nVSprite->nvs_LineHeight;

if (NULL != (vsprite = (struct VSprite *)AllocMem((LONG)sizeof(struct VSprite), MEMF_CLEAR)))
        {
        if (NULL != (vsprite->BorderLine = (WORD *)AllocMem(line_size, MEMF_CHIP)))
            {
            if (NULL != (vsprite->CollMask = (WORD *)AllocMem(plane_size, MEMF_CHIP)))
                {
                vsprite->Y          = nVSprite->nvs_Y;
                vsprite->X          = nVSprite->nvs_X;
                vsprite->Flags      = nVSprite->nvs_Flags;
                vsprite->Width      = nVSprite->nvs_WordWidth;
                vsprite->Depth      = nVSprite->nvs_ImageDepth;
                vsprite->Height     = nVSprite->nvs_LineHeight;
                vsprite->MeMask     = nVSprite->nvs_MeMask;
                vsprite->HitMask    = nVSprite->nvs_HitMask;
                vsprite->ImageData  = nVSprite->nvs_Image;
                vsprite->SprColors  = nVSprite->nvs_ColorSet;
                vsprite->PlanePick  = vsprite->PlaneOnOff = 0x00;
                InitMasks(vsprite);
                return(vsprite);
                }
            FreeMem(vsprite->BorderLine, line_size);
            }
        FreeMem(vsprite, (LONG)sizeof(*vsprite));
        }
return(NULL);
}

/* Create a Bob from the information given in nBob.  Use freeBob() to free this GEL.
** A VSprite is created for this bob.  This routine properly allocates all double
** buffered information if it is required.
*/
struct Bob *makeBob(NEWBOB *nBob)
{
struct Bob         *bob;
struct VSprite     *vsprite;
NEWVSPRITE          nVSprite ;
LONG                rassize;

rassize = (LONG)sizeof(UWORD) * nBob->nb_WordWidth * nBob->nb_LineHeight * nBob->nb_RasDepth;

if (NULL != (bob = (struct Bob *)AllocMem((LONG)sizeof(struct Bob), MEMF_CLEAR)))
        {
        if (NULL != (bob->SaveBuffer = (WORD *)AllocMem(rassize, MEMF_CHIP)))
            {
            nVSprite.nvs_WordWidth  = nBob->nb_WordWidth;
            nVSprite.nvs_LineHeight = nBob->nb_LineHeight;
            nVSprite.nvs_ImageDepth = nBob->nb_ImageDepth;
            nVSprite.nvs_Image      = nBob->nb_Image;
            nVSprite.nvs_X          = nBob->nb_X;
            nVSprite.nvs_Y          = nBob->nb_Y;
            nVSprite.nvs_ColorSet   = NULL;
            nVSprite.nvs_Flags      = nBob->nb_BFlags;
            /* Push the values into the NEWVSPRITE structure for use in makeVSprite(). */
            nVSprite.nvs_MeMask     = nBob->nb_MeMask;
            nVSprite.nvs_HitMask    = nBob->nb_HitMask;

            if ((vsprite = makeVSprite(&nVSprite)) != NULL)
                {
                vsprite->PlanePick = nBob->nb_PlanePick;
                vsprite->PlaneOnOff = nBob->nb_PlaneOnOff;
                vsprite->VSBob   = bob;
                bob->BobVSprite  = vsprite;
                bob->ImageShadow = vsprite->CollMask;
                bob->Flags       = 0;
                bob->Before      = NULL;
                bob->After       = NULL;
                bob->BobComp     = NULL;

                if (nBob->nb_DBuf)
                    {
                    if (NULL != (bob->DBuffer = (struct DBufPacket *)
                            AllocMem((LONG)sizeof(struct DBufPacket), MEMF_CLEAR)))
                        {
                        if (NULL != (bob->DBuffer->BufBuffer = (WORD *)AllocMem(rassize, MEMF_CHIP)))
                            return(bob);
                        FreeMem(bob->DBuffer, (LONG)sizeof(struct DBufPacket));
                        }
                    }
                else
                    {
                    bob->DBuffer = NULL;
                    return(bob);
                    }
                freeVSprite(vsprite);
                }
            FreeMem(bob->SaveBuffer, rassize);
            }
        FreeMem(bob, (LONG)sizeof(*bob));
        }
return(NULL);
}

/*
** Create a Animation Component from the information given in nAnimComp and nBob.  Use
** freeComp() to free this GEL.  makeComp() calls makeBob(), and links the Bob into an AnimComp.
*/
struct AnimComp *makeComp(NEWBOB *nBob, NEWANIMCOMP *nAnimComp)
{
struct Bob      *compBob;
struct AnimComp *aComp;

if ((aComp = AllocMem((LONG)sizeof(struct AnimComp),MEMF_CLEAR)) != NULL)
        {
        if ((compBob = makeBob(nBob)) != NULL)
            {
            compBob->After   = compBob->Before  = NULL;
            compBob->BobComp = aComp;   /* Link 'em up. */
            aComp->AnimBob      = compBob;
            aComp->TimeSet      = nAnimComp->nac_Time; /* Num ticks active. */
            aComp->YTrans       = nAnimComp->nac_Yt; /* Offset rel to HeadOb */
            aComp->XTrans       = nAnimComp->nac_Xt;
            aComp->AnimCRoutine = nAnimComp->nac_Routine;
            aComp->Flags        = nAnimComp->nac_CFlags;
            aComp->Timer        = 0;
            aComp->NextSeq      = aComp->PrevSeq  = NULL;
            aComp->NextComp     = aComp->PrevComp = NULL;
            aComp->HeadOb       = NULL;
            return(aComp);
            }
        FreeMem(aComp, (LONG)sizeof(struct AnimComp));
        }
return(NULL);
}

/* Create an Animation Sequence from the information given in nAnimSeq and nBob.  Use
** freeSeq() to free this GEL.  This routine creates a linked list of animation components
** which make up the animation sequence.  It links them all up, making a circular list of
** the PrevSeq and NextSeq pointers. That is to say, the first component of the sequences'
** PrevSeq points to the last component; the last component of * the sequences' NextSeq
** points back to the first component.  If dbuf is on, the underlying Bobs will be set up
** for double buffering.  If singleImage is non-zero, the pImages pointer is assumed to
** point to an array of only one image, instead of an array of 'count' images, and all
** Bobs will use the same image.
*/
struct AnimComp *makeSeq(NEWBOB *nBob, NEWANIMSEQ *nAnimSeq)
{
int seq;
struct AnimComp *firstCompInSeq = NULL;
struct AnimComp *seqComp = NULL;
struct AnimComp *lastCompMade = NULL;
LONG image_size;
NEWANIMCOMP nAnimComp;

/* get the initial image.  this is the only image that is used
** if nAnimSeq->nas_SingleImage is non-zero.
*/
nBob->nb_Image = nAnimSeq->nas_Images;
image_size = nBob->nb_LineHeight * nBob->nb_ImageDepth * nBob->nb_WordWidth;

/* for each comp in the sequence */
for (seq = 0; seq < nAnimSeq->nas_Count; seq++)
        {
        nAnimComp.nac_Xt        = *(nAnimSeq->nas_Xt + seq);
        nAnimComp.nac_Yt        = *(nAnimSeq->nas_Yt + seq);
        nAnimComp.nac_Time      = *(nAnimSeq->nas_Times + seq);
        nAnimComp.nac_Routine   = nAnimSeq->nas_Routines[seq];
        nAnimComp.nac_CFlags    = nAnimSeq->nas_CFlags;
        if ((seqComp = makeComp(nBob, &nAnimComp)) == NULL)
            {
            if (firstCompInSeq != NULL)
                freeSeq(firstCompInSeq, (LONG)nBob->nb_RasDepth);
            return(NULL);
            }
        seqComp->HeadOb = nAnimSeq->nas_HeadOb;
        /* Make a note of where the first component is. */
        if (firstCompInSeq == NULL) firstCompInSeq = seqComp;
        /* link the component into the list */
        if (lastCompMade != NULL) lastCompMade->NextSeq = seqComp;
        seqComp->NextSeq = NULL;
        seqComp->PrevSeq = lastCompMade;
        lastCompMade = seqComp;
        /* If nAnimSeq->nas_SingleImage is zero, the image array has nAnimSeq->nas_Count images. */
        if (!nAnimSeq->nas_SingleImage)
            nBob->nb_Image += image_size;
        }
/* On The last component in the sequence, set Next/Prev to make */
/* the linked list a loop of components.                        */
lastCompMade->NextSeq = firstCompInSeq;
firstCompInSeq->PrevSeq = lastCompMade;

return(firstCompInSeq);
}

/* Free the data created by makeVSprite().  Assumes images deallocated elsewhere. */
VOID freeVSprite(struct VSprite *vsprite)
{
LONG    line_size;
LONG    plane_size;

line_size = (LONG)sizeof(WORD) * vsprite->Width;
plane_size = line_size * vsprite->Height;
FreeMem(vsprite->BorderLine, line_size);
FreeMem(vsprite->CollMask, plane_size);
FreeMem(vsprite, (LONG)sizeof(*vsprite));
}

/* Free the data created by makeBob().  It's important that rasdepth match the depth you */
/* passed to makeBob() when this gel was made. Assumes images deallocated elsewhere.     */
VOID freeBob(struct Bob *bob, LONG rasdepth)
{
LONG    rassize =  sizeof(UWORD) * bob->BobVSprite->Width * bob->BobVSprite->Height * rasdepth;

if (bob->DBuffer != NULL)
        {
        FreeMem(bob->DBuffer->BufBuffer, rassize);
        FreeMem(bob->DBuffer, (LONG)sizeof(struct DBufPacket));
        }
FreeMem(bob->SaveBuffer, rassize);
freeVSprite(bob->BobVSprite);
FreeMem(bob, (LONG)sizeof(*bob));
}

/* Free the data created by makeComp().  It's important that rasdepth match the depth you */
/* passed to makeComp() when this GEL was made. Assumes images deallocated elsewhere.    */
VOID freeComp(struct AnimComp *myComp, LONG rasdepth)
{
freeBob(myComp->AnimBob, rasdepth);
FreeMem(myComp, (LONG)sizeof(struct AnimComp));
}

/* Free the data created by makeSeq().  Complimentary to makeSeq(), this routine goes through
** the NextSeq pointers and frees the Components.  This routine only goes forward through the
** list, and so it must be passed the first component in the sequence, or the sequence must
** be circular (which is guaranteed if you use makeSeq()).  It's important that rasdepth match
** the depth you passed to makeSeq() when this gel was made.   Assumes images deallocated elsewhere!
*/
VOID freeSeq(struct AnimComp *headComp, LONG rasdepth)
{
struct AnimComp *curComp;
struct AnimComp *nextComp;

/* Break the NextSeq loop, so we get a NULL at the end of the list. */
headComp->PrevSeq->NextSeq = NULL;

curComp = headComp;         /* get the start of the list */
while (curComp != NULL)
        {
        nextComp = curComp->NextSeq;
        freeComp(curComp, rasdepth);
        curComp = nextComp;
        }
}

/* Free an animation object (list of sequences).  freeOb() goes through the NextComp
** pointers, starting at the AnimObs' HeadComp, and frees every sequence.  It only
** goes forward. It then frees the Object itself.  Assumes images deallocated elsewhere!
*/
VOID freeOb(struct AnimOb *headOb, LONG rasdepth)
{
struct AnimComp *curSeq;
struct AnimComp *nextSeq;

curSeq = headOb->HeadComp;          /* get the start of the list */
while (curSeq != NULL)
        {
        nextSeq = curSeq->NextComp;
        freeSeq(curSeq, rasdepth);
        curSeq = nextSeq;
        }
FreeMem(headOb, sizeof(struct AnimOb));
}


Lib_examples/RGBBoxes.c

;/*  RGBBoxes.c simple ViewPort example -- works with 1.3 and Release 2
LC -b1 -cfistq -v -y -j73 RGBBoxes.c
Blink FROM LIB:c.o,RGBBoxes.o TO RGBBoxes LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
**
** The following example creates a View consisting of one ViewPort set
** to an NTSC, high-resolution, interlaced display mode of nominal
** dimensions.  This example shows both the old 1.3 way of setting up
** the ViewPort and the new method used in Release 2.
*/

#include <exec/types.h>
#include <graphics/gfx.h>
#include <graphics/gfxbase.h>
#include <graphics/gfxmacros.h>
#include <graphics/copper.h>
#include <graphics/view.h>
#include <graphics/displayinfo.h>
#include <graphics/gfxnodes.h>
#include <graphics/videocontrol.h>
#include <libraries/dos.h>
#include <utility/tagitem.h>

#include <clib/graphics_protos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>

#include <stdio.h>
#include <stdlib.h>

#define DEPTH 2     /*  The number of bitplanes.  */
#define WIDTH 640   /*  Nominal width and height  */
#define HEIGHT 400  /*  used in 1.3.              */

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

VOID drawFilledBox(WORD , WORD );  /* Function prototypes */
VOID cleanup(int );
VOID fail(STRPTR);

struct GfxBase *GfxBase = NULL;

/*  Construct a simple display.  These are global to make freeing easier.   */
struct View view, *oldview=NULL;  /*  Pointer to old View we can restore it.*/
struct ViewPort viewPort = { 0 };
struct BitMap bitMap = { 0 };
struct ColorMap *cm=NULL;

struct ViewExtra *vextra=NULL;      /* Extended structures used in Release 2 */
struct MonitorSpec *monspec=NULL;
struct ViewPortExtra *vpextra=NULL;
struct DimensionInfo dimquery = { 0 };

UBYTE *displaymem = NULL;     /*  Pointer for writing to BitMap memory.  */

#define BLACK 0x000           /*  RGB values for the four colors used.   */
#define RED   0xf00
#define GREEN 0x0f0
#define BLUE  0x00f

/*
 * main():  create a custom display; works under either 1.3 or Release 2
 */
VOID main(VOID)
{
WORD depth, box;
struct RasInfo rasInfo;
ULONG modeID;

struct TagItem vcTags[] =
{
    {VTAG_ATTACH_CM_SET, NULL },
    {VTAG_VIEWPORTEXTRA_SET, NULL },
    {VTAG_NORMAL_DISP_SET, NULL },
    {VTAG_END_CM, NULL }
};

/*  Offsets in BitMap where boxes will be drawn.  */
static SHORT boxoffsets[] = { 802, 2010, 3218 };

static UWORD colortable[] = { BLACK, RED, GREEN, BLUE };

/* Open the graphics library */
GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 33L);
if(GfxBase == NULL)
    fail("Could not open graphics library\n");

/*  Example steals screen from Intuition if Intuition is around.      */
oldview = GfxBase->ActiView;   /* Save current View to restore later. */

InitView(&view);           /*  Initialize the View and set View.Modes.     */
view.Modes |= LACE;        /*  This is the old 1.3 way (only LACE counts). */

if(GfxBase->LibNode.lib_Version >= 36)
    {
    /* Form the ModeID from values in <displayinfo.h> */
    modeID=DEFAULT_MONITOR_ID | HIRESLACE_KEY;

    /*  Make the ViewExtra structure   */
    if( vextra=GfxNew(VIEW_EXTRA_TYPE) )
        {
        /* Attach the ViewExtra to the View */
        GfxAssociate(&view , vextra);
        view.Modes |= EXTEND_VSTRUCT;

        /* Create and attach a MonitorSpec to the ViewExtra */
        if( monspec=OpenMonitor(NULL,modeID) )
            vextra->Monitor=monspec;
        else
            fail("Could not get MonitorSpec\n");
        }
     else fail("Could not get ViewExtra\n");
     }

/*  Initialize the BitMap for RasInfo.  */
InitBitMap(&bitMap, DEPTH, WIDTH, HEIGHT);

/* Set the plane pointers to NULL so the cleanup routine */
/* will know if they were used.                          */
for(depth=0; depth<DEPTH; depth++)
    bitMap.Planes[depth] = NULL;

/*  Allocate space for BitMap.             */
for (depth=0; depth<DEPTH; depth++)
    {
    bitMap.Planes[depth] = (PLANEPTR)AllocRaster(WIDTH, HEIGHT);
    if (bitMap.Planes[depth] == NULL)
        fail("Could not get BitPlanes\n");
    }

rasInfo.BitMap = &bitMap;       /*  Initialize the RasInfo.  */
rasInfo.RxOffset = 0;
rasInfo.RyOffset = 0;
rasInfo.Next = NULL;

InitVPort(&viewPort);           /*  Initialize the ViewPort.  */
view.ViewPort = &viewPort;      /*  Link the ViewPort into the View.  */
viewPort.RasInfo = &rasInfo;
viewPort.DWidth = WIDTH;
viewPort.DHeight = HEIGHT;

/* Set the display mode the old-fashioned way */
viewPort.Modes=HIRES | LACE;

if(GfxBase->LibNode.lib_Version >= 36)
{
    /* Make a ViewPortExtra and get ready to attach it */
    if( vpextra = GfxNew(VIEWPORT_EXTRA_TYPE) )
        {
        vcTags[1].ti_Data = (ULONG) vpextra;

        /* Initialize the DisplayClip field of the ViewPortExtra */
        if( GetDisplayInfoData( NULL , (UBYTE *) &dimquery ,
                                sizeof(dimquery) , DTAG_DIMS, modeID) )
            {
            vpextra->DisplayClip = dimquery.Nominal;

            /* Make a DisplayInfo and get ready to attach it */
            if( !(vcTags[2].ti_Data = (ULONG) FindDisplayInfo(modeID)) )
                fail("Could not get DisplayInfo\n");
             }
        else fail("Could not get DimensionInfo \n");
        }
    else fail("Could not get ViewPortExtra\n");

    /* This is for backwards compatibility with, for example,   */
    /* a 1.3 screen saver utility that looks at the Modes field */
    viewPort.Modes = (UWORD) (modeID & 0x0000ffff);
    }

/*  Initialize the ColorMap.  */
/*  2 planes deep, so 4 entries (2 raised to the #_planes power).  */
cm = GetColorMap(4L);
if(cm == NULL)
    fail("Could not get ColorMap\n");

if(GfxBase->LibNode.lib_Version >= 36)
    {
    /* Get ready to attach the ColorMap, Release 2-style */
    vcTags[0].ti_Data = (ULONG) &viewPort;

    /* Attach the color map and Release 2 extended structures */
    if( VideoControl(cm,vcTags) )
        fail("Could not attach extended structures\n");
    }
else
    /* Attach the ColorMap, old 1.3-style */
    viewPort.ColorMap = cm;

LoadRGB4(&viewPort, colortable, 4);  /* Change colors to those in colortable. */

MakeVPort( &view, &viewPort ); /* Construct preliminary Copper instruction list.    */

/* Merge preliminary lists into a real Copper list in the View structure. */
MrgCop( &view );

/* Clear the ViewPort */
for(depth=0; depth<DEPTH; depth++)
    {
    displaymem = (UBYTE *)bitMap.Planes[depth];
    BltClear(displaymem, (bitMap.BytesPerRow * bitMap.Rows), 1L);
    }

LoadView(&view);

/*  Now fill some boxes so that user can see something.          */
/*  Always draw into both planes to assure true colors.          */
for (box=1; box<=3; box++)  /* Three boxes; red, green and blue. */
    {
    for (depth=0; depth<DEPTH; depth++)        /*  Two planes.   */
        {
        displaymem = bitMap.Planes[depth] + boxoffsets[box-1];
        drawFilledBox(box, depth);
        }
    }

Delay(10L * TICKS_PER_SECOND);   /*  Pause for 10 seconds.                */
LoadView(oldview);               /*  Put back the old View.               */
WaitTOF();                       /*  Wait until the the View is being     */
                                 /*    rendered to free memory.           */
FreeCprList(view.LOFCprList);    /*  Deallocate the hardware Copper list  */
if(view.SHFCprList)              /*    created by MrgCop().  Since this   */
    FreeCprList(view.SHFCprList);/*    is interlace, also check for a     */
                                 /*    short frame copper list to free.   */
FreeVPortCopLists(&viewPort);    /*  Free all intermediate Copper lists   */
                                 /*    from created by MakeVPort().       */
cleanup(RETURN_OK);              /*  Success.                             */
}

/*
 * fail():  print the error string and call cleanup() to exit
 */
void fail(STRPTR errorstring)
{
printf(errorstring);
cleanup(RETURN_FAIL);
}

/*
 * cleanup():  free everything that was allocated.
 */
VOID cleanup(int returncode)
{
WORD depth;

/*  Free the color map created by GetColorMap().  */
if(cm) FreeColorMap(cm);

/* Free the ViewPortExtra created by GfxNew() */
if(vpextra) GfxFree(vpextra);

/*  Free the BitPlanes drawing area.  */
for(depth=0; depth<DEPTH; depth++)
    {
    if (bitMap.Planes[depth])
        FreeRaster(bitMap.Planes[depth], WIDTH, HEIGHT);
    }

/* Free the MonitorSpec created with OpenMonitor() */
if(monspec) CloseMonitor( monspec );

/* Free the ViewExtra created with GfxNew() */
if(vextra) GfxFree(vextra);

/* Close the graphics library */
CloseLibrary((struct Library *)GfxBase);

exit(returncode);
}

/*
 * drawFilledBox(): create a WIDTH/2 by HEIGHT/2 box of color
 *                  "fillcolor" into the given plane.
 */
VOID drawFilledBox(WORD fillcolor, WORD plane)
{
UBYTE value;
WORD boxHeight, boxWidth, width;

/*  Divide (WIDTH/2) by eight because each UBYTE that */
/* is written stuffs eight bits into the BitMap.      */
boxWidth = (WIDTH/2)/8;
boxHeight = HEIGHT/2;

value = ((fillcolor & (1 << plane)) != 0) ?  0xff : 0x00;

for( ; boxHeight; boxHeight--)
    {
    for(width=0 ; width < boxWidth; width++)
        *displaymem++ = value;

    displaymem += (bitMap.BytesPerRow - boxWidth);
    }
}


Lib_examples/UserCopperExample.c

/*  The example program below shows the use of user Copper lists
    under Intuition.

    UserCopperExample.c
    User Copper List Example
    For SAS/C 5.10a,
    compile with:  LC -b1 -cfist -L -v -y UserCopperExample.c
    link with lc.lib and amiga.lib
*/

#include <exec/types.h>
#include <exec/memory.h>
#include <graphics/gfxbase.h>
#include <graphics/gfxmacros.h>
#include <graphics/copper.h>
#include <graphics/videocontrol.h>
#include <intuition/intuition.h>
#include <intuition/preferences.h>
#include <hardware/custom.h>
#include <libraries/dos.h>

#include <clib/exec_protos.h>           /*  Prototypes.  */
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
#include <clib/dos_protos.h>

#include <stdlib.h>

/*  Use this structure to gain access to the custom registers.  */
extern struct Custom far custom;

/*  Global variables.  */
struct GfxBase        *GfxBase = NULL;
struct IntuitionBase  *IntuitionBase = NULL;
struct Screen         *screen = NULL;
struct Window         *window = NULL;

VOID main( VOID ), cleanExit( WORD );
WORD openAll( VOID ), loadCopper( VOID );

/*
 *   The main() routine -- just calls subroutines
 */
VOID main( VOID )
{
WORD ret_val;
struct IntuiMessage     *intuiMessage;

        /*  Open the libraries, a screen and a window.  */
        ret_val = openAll();
        if (RETURN_OK == ret_val)
        {
                /*  Create and attach the user Copper list.  */
                ret_val = loadCopper();
                if (RETURN_OK == ret_val)
                {
                        /*  Wait until the user clicks in the close gadget.  */
                        (VOID) Wait(1<<window->UserPort->mp_SigBit);

                        while (intuiMessage = (struct IntuiMessage *)GetMsg(window->UserPort))
                                ReplyMsg((struct Message *)intuiMessage);
                }
        }
        cleanExit(ret_val);
}

/*
 * openAll() -- opens the libraries, screen and window
 */
WORD openAll( VOID )
{
#define MY_WA_WIDTH 270 /*  Width of window.  */

        WORD ret_val = RETURN_OK;

        /*  Prepare to explicitly request Topaz 60 as the screen font.  */
        struct TextAttr topaz60 =
        {
                (STRPTR)"topaz.font",
                (UWORD)TOPAZ_SIXTY, (UBYTE)0, (UBYTE)0
        };

        GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 37L);
        if (GfxBase == NULL)
                ret_val = ERROR_INVALID_RESIDENT_LIBRARY;
        else
        {
                IntuitionBase = (struct IntuitionBase *)
                        OpenLibrary("intuition.library", 37L);

                if (IntuitionBase == NULL)
                        ret_val = ERROR_INVALID_RESIDENT_LIBRARY;
                else
                {
                        screen = OpenScreenTags( NULL,
                                 SA_Overscan, OSCAN_STANDARD,
                                 SA_Title,    "User Copper List Example",
                                 SA_Font,     (ULONG)&topaz60,
                                 TAG_DONE);

                        if (NULL == screen)
                                ret_val = ERROR_NO_FREE_STORE;
                        else
                        {
                                window = OpenWindowTags( NULL,
                                         WA_CustomScreen, screen,
                                         WA_Title,        "<- Click here to quit.",
                                         WA_IDCMP,        CLOSEWINDOW,
                                         WA_Flags,        WINDOWDRAG|WINDOWCLOSE|INACTIVEWINDOW,
                                         WA_Left,         (screen->Width-MY_WA_WIDTH)/2,
                                         WA_Top,          screen->Height/2,
                                         WA_Height,       screen->Font->ta_YSize + 3,
                                         WA_Width,        MY_WA_WIDTH,
                                         TAG_DONE);

                                if (NULL == window)
                                        ret_val = ERROR_NO_FREE_STORE;
                        }
                }
        }

        return(ret_val);
}

/*
 * loadCopper() -- creates a Copper list program and adds it to the system
 */
WORD loadCopper( VOID )
{
register USHORT   i, scanlines_per_color;
         WORD     ret_val    = RETURN_OK;
struct   ViewPort *viewPort;
struct   UCopList *uCopList  = NULL;
struct   TagItem  uCopTags[] =
          {
                { VTAG_USERCLIP_SET, NULL },
                { VTAG_END_CM, NULL }
          };

UWORD    spectrum[] =
          {
                0x0604, 0x0605, 0x0606, 0x0607, 0x0617, 0x0618, 0x0619,
                0x0629, 0x072a, 0x073b, 0x074b, 0x074c, 0x075d, 0x076e,
                0x077e, 0x088f, 0x07af, 0x06cf, 0x05ff, 0x04fb, 0x04f7,
                0x03f3, 0x07f2, 0x0bf1, 0x0ff0, 0x0fc0, 0x0ea0, 0x0e80,
                0x0e60, 0x0d40, 0x0d20, 0x0d00
          };

#define NUMCOLORS 32

        /*  Allocate memory for the Copper list.  */
        /*  Make certain that the initial memory is cleared.  */
        uCopList = (struct UCopList *)
                AllocMem(sizeof(struct UCopList), MEMF_PUBLIC|MEMF_CLEAR);

        if (NULL == uCopList)
                ret_val = ERROR_NO_FREE_STORE;
        else
        {
                /*  Initialize the Copper list buffer.  */
                CINIT(uCopList, NUMCOLORS);

                scanlines_per_color = screen->Height/NUMCOLORS;

                /*  Load in each color.  */
                for (i=0; i<NUMCOLORS; i++)
                        {
                        CWAIT(uCopList, (i*scanlines_per_color), 0);
                        CMOVE(uCopList, custom.color[0], spectrum[i]);
                        }

                CEND(uCopList); /*  End the Copper list  */

                viewPort = ViewPortAddress(window);     /*  Get a pointer to the ViewPort.  */
                Forbid();       /*  Forbid task switching while changing the Copper list.  */
                viewPort->UCopIns=uCopList;
                Permit();       /*  Permit task switching again.  */

                /*  Enable user copper list clipping for this ViewPort.  */
                (VOID) VideoControl( viewPort->ColorMap, uCopTags );

                RethinkDisplay();       /*  Display the new Copper list.  */

                return(ret_val);
        }
}

/*
 *  cleanExit() -- returns all resources that were used.
 */
VOID cleanExit( WORD retval )
{
struct ViewPort *viewPort;

if (NULL != IntuitionBase)
{
        if (NULL != screen)
        {
                if (NULL != window)
                {
                        viewPort = ViewPortAddress(window);
                        if (NULL != viewPort->UCopIns)
                        {
                                /*  Free the memory allocated for the Copper.  */
                                FreeVPortCopLists(viewPort);
                                RemakeDisplay();
                        }
                        CloseWindow(window);
                }
                CloseScreen(screen);
        }
        CloseLibrary((struct Library *)IntuitionBase);
}

if (NULL != GfxBase)
        CloseLibrary((struct Library *)GfxBase);

exit((int)retval);
}


Lib_examples/ClipFTXT.c

;/* clipftxt.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -j73 clipftxt.c
Blink FROM LIB:c.o,clipftxt.o TO clipftxt LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
*
* ClipFTXT.c demonstrates reading (and optional writing) of clipboard
* device FTXT.  This example may be used as the basis for supporting
* Release 2 console pastes.
*
* clipftxt.c:	Writes ASCII text to clipboard unit as FTXT
*		(All clipboard data must be IFF)
*
* Usage: clipftxt unitnumber
*
* To convert to an example of reading only, comment out #define WRITEREAD
*/

#include <exec/types.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <libraries/iffparse.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/iffparse_protos.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

/* Causes example to write FTXT first, then read it back
 * Comment out to create a reader only
 */
#define WRITEREAD

#define MINARGS 2

/* 2.0 Version string for c:Version to find */
UBYTE vers[] = "\0$VER: clipftxt 37.2";

UBYTE usage[] = "Usage: clipftxt unitnumber (use zero for primary unit)";

/*
 * Text error messages for possible IFFERR_#? returns from various
 * IFF routines.  To get the index into this array, take your IFFERR code,
 * negate it, and subtract one.
 *  idx = -error - 1;
 */
char	*errormsgs[] = {
    "End of file (not an error).",
    "End of context (not an error).",
    "No lexical scope.",
    "Insufficient memory.",
    "Stream read error.",
    "Stream write error.",
    "Stream seek error.",
    "File is corrupt.",
    "IFF syntax error.",
    "Not an IFF file.",
    "Required call-back hook missing.",
    "Return to client.  You should never see this."
};

#define RBUFSZ 512

#define  ID_FTXT	MAKE_ID('F','T','X','T')
#define  ID_CHRS	MAKE_ID('C','H','R','S')

struct Library *IFFParseBase;

UBYTE mytext[]="This FTXT written to clipboard by clipftxt example.\n";

void main(int argc, char **argv)
{
    struct IFFHandle	*iff = NULL;
    struct ContextNode  *cn;
    long		error=0, unitnumber=0, rlen;
    int textlen;
    UBYTE readbuf[RBUFSZ];

        /* if not enough args or '?', print usage */
        if(((argc)&&(argc<MINARGS))||(argv[argc-1][0]=='?'))
        {
            printf("%s\n",usage);
            exit(RETURN_WARN);
            }

    unitnumber = atoi(argv[1]);

    if (!(IFFParseBase = OpenLibrary ("iffparse.library", 0L)))
        {
        puts("Can't open iff parsing library.");
        goto bye;
        }

    /*
     * Allocate IFF_File structure.
     */
    if (!(iff = AllocIFF ()))
        {
        puts ("AllocIFF() failed.");
        goto bye;
        }

    /*
     * Set up IFF_File for Clipboard I/O.
     */
    if (!(iff->iff_Stream = (ULONG) OpenClipboard (unitnumber)))
        {
        puts ("Clipboard open failed.");
        goto bye;
        }
    else printf("Opened clipboard unit %ld\n",unitnumber);

    InitIFFasClip (iff);

#ifdef WRITEREAD

    /*
     * Start the IFF transaction.
     */
    if (error = OpenIFF (iff, IFFF_WRITE))
        {
        puts ("OpenIFF for write failed.");
        goto bye;
        }

    /*
     * Write our text to the clipboard as CHRS chunk in FORM FTXT
     *
     * First, write the FORM ID (FTXT)
     */
        if(!(error=PushChunk(iff, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN)))
        {
        /* Now the CHRS chunk ID followed by the chunk data
         * We'll just write one CHRS chunk.
         * You could write more chunks.
         */
            if(!(error=PushChunk(iff, 0, ID_CHRS, IFFSIZE_UNKNOWN)))
            {
            /* Now the actual data (the text) */
            textlen = strlen(mytext);
            if(WriteChunkBytes(iff, mytext, textlen) != textlen)
                {
                puts("Error writing CHRS data.");
                error = IFFERR_WRITE;
                }
            }
        if(!error) error = PopChunk(iff);
        }
    if(!error) error = PopChunk(iff);

    if(error)
        {
        printf ("IFF write failed, error %ld: %s\n",
            error, errormsgs[-error - 1]);
        goto bye;
        }
    else printf("Wrote text to clipboard as FTXT\n");

    /*
     * Now let's close it, then read it back
     * First close the write handle, then close the clipboard
     */
    CloseIFF(iff);
    if (iff->iff_Stream) CloseClipboard ((struct ClipboardHandle *)
                        iff->iff_Stream);

    if (!(iff->iff_Stream = (ULONG) OpenClipboard (unitnumber)))
        {
        puts ("Reopen of Clipboard failed.");
        goto bye;
        }
    else printf("Reopened clipboard unit %ld\n",unitnumber);

#endif /* WRITEREAD */

    if (error = OpenIFF (iff, IFFF_READ))
        {
        puts ("OpenIFF for read failed.");
        goto bye;
        }

    /* Tell iffparse we want to stop on FTXT CHRS chunks */
    if (error = StopChunk(iff, ID_FTXT, ID_CHRS))
        {
        puts ("StopChunk failed.");
        goto bye;
        }

    /* Find all of the FTXT CHRS chunks */
    while(1)
        {
        error = ParseIFF(iff,IFFPARSE_SCAN);
        if(error == IFFERR_EOC) continue;	/* enter next context */
        else if(error) break;

        /* We only asked to stop at FTXT CHRS chunks
         * If no error we've hit a stop chunk
         * Read the CHRS chunk data
         */
        cn = CurrentChunk(iff);

        if((cn)&&(cn->cn_Type == ID_FTXT)&&(cn->cn_ID == ID_CHRS))
            {
            printf("CHRS chunk contains:\n");
            while((rlen = ReadChunkBytes(iff,readbuf,RBUFSZ)) > 0)
                {
                Write(Output(),readbuf,rlen);
                }
            if(rlen < 0)	error = rlen;
            }
        }

    if((error)&&(error != IFFERR_EOF))
        {
        printf ("IFF read failed, error %ld: %s\n",
            error, errormsgs[-error - 1]);
        }

bye:
    if (iff) {
        /*
         * Terminate the IFF transaction with the stream.  Free
         * all associated structures.
         */
        CloseIFF (iff);

        /*
         * Close the clipboard stream
         */
        if (iff->iff_Stream)
                CloseClipboard ((struct ClipboardHandle *)
                        iff->iff_Stream);
        /*
         * Free the IFF_File structure itself.
         */
        FreeIFF (iff);
        }
    if (IFFParseBase)	CloseLibrary (IFFParseBase);

    exit (RETURN_OK);
}


Lib_examples/Sift.c

;/* sift.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -j73 sift.c
Blink FROM LIB:c.o,sift.o TO sift LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
*
* Sift.c lists the type and size of every chunk in an IFF file and
* checks the IFF file for correct syntax.  You should use Sift to
* check IFF files created by your programs.
*
* sift.c:	Takes any IFF file and tells you what's in it.  Verifies syntax and all that cool stuff.
*
* Usage: sift -c		; For clipboard scanning
*    or  sift <file>		; For DOS file scanning
*
* Reads the specified stream and prints an IFFCheck-like listing of the contents of the IFF file, if any.
* Stream is a DOS file for <file> argument, or is the clipboard's primary clip for -c.
* This program must be run from a CLI.
*
*/

#include <exec/types.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <libraries/iffparse.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/iffparse_protos.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }     /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

#define MINARGS 2

UBYTE vers[] = "\0$VER: sift 37.1";       /* 2.0 Version string for c:Version to find */
UBYTE usage[] = "Usage: sift IFFfilename (or -c for clipboard)";

void PrintTopChunk (struct IFFHandle *);  /* proto for our function */

/*
 * Text error messages for possible IFFERR_#? returns from various IFF routines.  To get the index into
 * this array, take your IFFERR code, negate it, and subtract one.
 *  idx = -error - 1;
 */
char	*errormsgs[] = {
    "End of file (not an error).", "End of context (not an error).", "No lexical scope.",
    "Insufficient memory.", "Stream read error.", "Stream write error.",
    "Stream seek error.", "File is corrupt.", "IFF syntax error.",
    "Not an IFF file.", "Required call-back hook missing.", "Return to client.  You should never see this."
};

struct Library *IFFParseBase;

void main(int argc, char **argv)
{
    struct IFFHandle	*iff = NULL;
    long		error;
    short		cbio;

        /* if not enough args or '?', print usage */
        if(((argc)&&(argc<MINARGS))||(argv[argc-1][0]=='?'))
        {
            printf("%s\n",usage);
            goto bye;
            }

    /* Check to see if we are doing I/O to the Clipboard. */
    cbio = (argv[1][0] == '-'  &&  argv[1][1] == 'c');

    if (!(IFFParseBase = OpenLibrary ("iffparse.library", 0L)))
        {
        puts("Can't open iff parsing library.");
        goto bye;
        }

    /* Allocate IFF_File structure. */
    if (!(iff = AllocIFF ()))
        {
        puts ("AllocIFF() failed.");
        goto bye;
        }

    /*
     * Internal support is provided for both AmigaDOS files, and the clipboard.device.  This bizarre
     * 'if' statement performs the appropriate machinations for each case.
     */
    if (cbio)
        {
        /*
         * Set up IFF_File for Clipboard I/O.
         */
        if (!(iff->iff_Stream =
                (ULONG) OpenClipboard (PRIMARY_CLIP)))
            {
            puts ("Clipboard open failed.");
            goto bye;
            }
        InitIFFasClip (iff);
        }
    else
        {
        /* Set up IFF_File for AmigaDOS I/O.  */
        if (!(iff->iff_Stream = Open (argv[1], MODE_OLDFILE)))
            {
            puts ("File open failed.");
            goto bye;
            }
        InitIFFasDOS (iff);
        }

    /* Start the IFF transaction. */
    if (error = OpenIFF (iff, IFFF_READ))
        {
        puts ("OpenIFF failed.");
        goto bye;
        }

    while (1)
        {
        /*
         * The interesting bit.  IFFPARSE_RAWSTEP permits us to have precision monitoring of the
         * parsing process, which is necessary if we wish to print the structure of an IFF file.
         * ParseIFF() with _RAWSTEP will return the following things for the following reasons:
         *
         * Return code:			Reason:
         * 0				Entered new context.
         * IFFERR_EOC			About to leave a context.
         * IFFERR_EOF			Encountered end-of-file.
         * <anything else>		A parsing error.
         */
        error = ParseIFF (iff, IFFPARSE_RAWSTEP);

        /*
         * Since we're only interested in when we enter a context, we "discard" end-of-context
         * (_EOC) events.
         */
        if (error == IFFERR_EOC)
            continue;
        else if (error)
            /*
             * Leave the loop if there is any other error.
             */
            break;

        /* If we get here, error was zero. Print out the current state of affairs. */
        PrintTopChunk (iff);
        }

    /*
     * If error was IFFERR_EOF, then the parser encountered the end of
     * the file without problems.  Otherwise, we print a diagnostic.
     */
    if (error == IFFERR_EOF)
        puts ("File scan complete.");
    else
        printf ("File scan aborted, error %ld: %s\n",
            error, errormsgs[-error - 1]);

bye:
    if (iff) {
        /* Terminate the IFF transaction with the stream.  Free all associated structures. */
        CloseIFF (iff);

        /*
         * Close the stream itself.
         */
        if (iff->iff_Stream)
            if (cbio)
                CloseClipboard ((struct ClipboardHandle *)
                        iff->iff_Stream);
            else
                Close (iff->iff_Stream);

        /* Free the IFF_File structure itself. */
        FreeIFF (iff);
        }
    if (IFFParseBase)	CloseLibrary (IFFParseBase);

    exit (RETURN_OK);
}

void
PrintTopChunk (iff)
struct IFFHandle *iff;
{
    struct ContextNode	*top;
    short			i;
    char			idbuf[5];

    /* Get a pointer to the context node describing the current context. */
    if (!(top = CurrentChunk (iff)))
        return;

    /*
     * Print a series of dots equivalent to the current nesting depth of chunks processed so far.
     * This will cause nested chunks to be printed out indented.
     */
    for (i = iff->iff_Depth;  i--; )
        printf (". ");

    /* Print out the current chunk's ID and size. */
    printf ("%s %ld ", IDtoStr (top->cn_ID, idbuf), top->cn_Size);

    /* Print the current chunk's type, with a newline. */
    puts (IDtoStr (top->cn_Type, idbuf));
}


Lib_examples/blockinput.c

;/* blockinput.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 blockinput.c
Blink FROM LIB:c.o,blockinput.o TO blockinput LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
**
** To use a window as a requester, first bring up a zero-sized requester
** attached to the main window (this provides the blocking feature).
** Then, bring up your second window, or bring up a busy pointer.  The
** following example illustrates bringing up a busy pointer.

** blockinput.c -- program to demonstrate how to block the input from a
** window using a minimal requester, and how to put up a busy pointer.
*/
#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <intuition/intuition.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

/* our function prototypes */
BOOL beginWait(struct Window *win, struct Requester *waitRequest);
VOID endWait(struct Window *win, struct Requester *waitRequest);
VOID processIDCMP(struct Window *win);

struct Library *IntuitionBase;

/* data for a busy pointer.
** this data must be in chip memory!!!
*/
UWORD __chip waitPointer[] =
    {
    0x0000, 0x0000,     /* reserved, must be NULL */

    0x0400, 0x07C0,
    0x0000, 0x07C0,
    0x0100, 0x0380,
    0x0000, 0x07E0,
    0x07C0, 0x1FF8,
    0x1FF0, 0x3FEC,
    0x3FF8, 0x7FDE,
    0x3FF8, 0x7FBE,
    0x7FFC, 0xFF7F,
    0x7EFC, 0xFFFF,
    0x7FFC, 0xFFFF,
    0x3FF8, 0x7FFE,
    0x3FF8, 0x7FFE,
    0x1FF0, 0x3FFC,
    0x07C0, 0x1FF8,
    0x0000, 0x07E0,

    0x0000, 0x0000,     /* reserved, must be NULL */
    };

/*
** main()
**
** Open a window and display a busy-pointer for a short time then wait for
** the user to hit the close gadget (in processIDCMP()).  Normally, the
** application would bracket sections of code where it wishes to block window
** input with the beginWait() and endWait() functions.
*/
VOID main (int argc, char **argv)
{
struct Window *win;

if (IntuitionBase = OpenLibrary("intuition.library",37))
    {
    if (win = OpenWindowTags(NULL,
                        WA_IDCMP, IDCMP_CLOSEWINDOW|IDCMP_INTUITICKS,
                        WA_Activate, TRUE,
                        WA_Width,  320,
                        WA_Height, 100,
                        WA_CloseGadget, TRUE,
                        WA_DragBar, TRUE,
                        WA_DepthGadget, TRUE,
                        WA_SizeGadget, TRUE,
                        WA_MaxWidth, ~0,
                        WA_MaxHeight, ~0,
                        TAG_END))
        {
        processIDCMP(win);
        CloseWindow(win);
        }
    CloseLibrary(IntuitionBase);
    }
}

/*
** beginWait()
**
** Clear the requester with InitRequester.  This makes a requester of
** width = 0, height = 0, left = 0, top = 0; in fact, everything is zero.
** This requester will simply block input to the window until
** EndRequest is called.
**
** The pointer is set to a reasonable 4-color busy pointer, with proper offsets.
*/
BOOL beginWait(struct Window *win, struct Requester *waitRequest)
{
extern UWORD __chip waitPointer[];

InitRequester(waitRequest);
if (Request(waitRequest, win))
    {
    SetPointer(win, waitPointer, 16, 16, -6, 0);
    SetWindowTitles(win,"Busy - Input Blocked",(UBYTE *)~0);
    return(TRUE);
    }
else
    return(FALSE);
}

/*
** endWait()
**
** Routine to reset the pointer to the system default, and remove the
** requester installed with beginWait().
*/
VOID endWait(struct Window *win, struct Requester *waitRequest)
{
ClearPointer(win);
EndRequest(waitRequest, win);
SetWindowTitles(win,"Not Busy",(UBYTE *)~0);
}

/*
** processIDCMP()
**
** Wait for the user to close the window.
*/
VOID processIDCMP(struct Window *win)
{
WORD done;
struct IntuiMessage *msg;
ULONG class;
struct Requester myreq;
UWORD tick_count;

done = FALSE;

/* Put up a requester with no imagery (size zero). */
if (beginWait(win,&myreq))
    {
    /*
    ** Insert code here for a window to act as the requester.
    */

    /* We'll count down INTUITICKS, which come about ten times
    ** a second.  We'll keep the busy state for about three seconds.
    */
    tick_count = 30;
    }

while (!done)
    {
    Wait(1L << win->UserPort->mp_SigBit);

    while (NULL != (msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
        {
        class = msg->Class;
        ReplyMsg((struct Message *)msg);

        switch (class)
            {
            case IDCMP_CLOSEWINDOW:
                done = TRUE;
                break;

            case IDCMP_INTUITICKS:
                if (tick_count > 0)
                    {
                    if (--tick_count == 0)  endWait(win,&myreq);
                    }
                break;
            }
        }
    }
}


Lib_examples/compleximage.c

/* compleximage.c - program to show the use of a complex Intuition Image.
**
** compiled with:
** lc -b1 -cfist -v -y compleximage.c
** blink FROM LIB:c.o compleximage.o TO compleximage LIB LIB:lc.lib LIB:amiga.lib
*/

#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

struct IntuitionBase *IntuitionBase = NULL;

#define MYIMAGE_LEFT    (0)
#define MYIMAGE_TOP     (0)
#define MYIMAGE_WIDTH   (24)
#define MYIMAGE_HEIGHT  (10)
#define MYIMAGE_DEPTH   (2)

/* This is the image data.  It is a two bitplane open rectangle which
** is 24 pixels wide and 10 high.  Make sure that it is in CHIP memory,
** or allocate a block of chip memory with a call like:
**
**     AllocMem(data_size,MEMF_CHIP)
**
** and copy the data to that block.  See the Exec chapter on
** Memory Allocation for more information on AllocMem().
*/
UWORD __chip myImageData[] =
    {
    /* first bitplane of data,
    ** open rectangle.
    */
    0xFFFF, 0xFF00,
    0xC000, 0x0300,
    0xC000, 0x0300,
    0xC000, 0x0300,
    0xC000, 0x0300,
    0xC000, 0x0300,
    0xC000, 0x0300,
    0xC000, 0x0300,
    0xC000, 0x0300,
    0xFFFF, 0xFF00,

    /* second bitplane of data,
    ** filled rectangle to appear within open rectangle.
    */
    0x0000, 0x0000,
    0x0000, 0x0000,
    0x0000, 0x0000,
    0x00FF, 0x0000,
    0x00FF, 0x0000,
    0x00FF, 0x0000,
    0x00FF, 0x0000,
    0x0000, 0x0000,
    0x0000, 0x0000,
    0x0000, 0x0000,
    };

/* used to get the "new look" on a custom screen */
UWORD pens[] = { ~0 };

/*
** main routine. Open required library and window and draw the images.
** This routine opens a very simple window with no IDCMP.  See the
** chapters on "Windows" and "Input and Output Methods" for more info.
** Free all resources when done.
*/
VOID main(int argc, char *argv[])
{
struct Screen *scr;
struct Window *win;
struct Image myImage;

IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37);
if (IntuitionBase != NULL)
    {
    if (NULL != (scr = OpenScreenTags(NULL,
                        SA_Depth,       4,
                        SA_Pens,        &pens,
                        TAG_END)))
        {
        if (NULL != (win = OpenWindowTags(NULL,
                            WA_RMBTrap,      TRUE,
                            WA_CustomScreen, scr,
                            TAG_END)))
            {
            myImage.LeftEdge    = MYIMAGE_LEFT;
            myImage.TopEdge     = MYIMAGE_TOP;
            myImage.Width       = MYIMAGE_WIDTH;
            myImage.Height      = MYIMAGE_HEIGHT;
            myImage.Depth       = MYIMAGE_DEPTH;
            myImage.ImageData   = myImageData;
            myImage.PlanePick   = 0x3;              /* use first two bitplanes */
            myImage.PlaneOnOff  = 0x0;              /* clear all unused planes  */
            myImage.NextImage   = NULL;

            /* Draw the image into the first two bitplanes */
            DrawImage(win->RPort,&myImage,10,10);

            /* Draw the same image at a new location */
            DrawImage(win->RPort,&myImage,100,10);

            /* Change the image to use the second and fourth bitplanes,
            ** PlanePick is 1010 binary or 0xA,
            ** and draw it again at a different location
            */
            myImage.PlanePick = 0xA;
            DrawImage(win->RPort,&myImage,10,50);

            /* Now set all the bits in the first bitplane with PlaneOnOff.
            ** This will make all the bits set in the second bitplane
            ** appear as color 3 (0011 binary), all the bits set in the
            ** fourth bitplane appear as color 9 (1001 binary) and all
            ** other pixels will be color 1 (0001 binary.  If there were
            ** any points in the image where both bits were set, they
            ** would appear as color 11 (1011 binary).
            ** Draw the image at a different location.
            */
            myImage.PlaneOnOff = 0x1;
            DrawImage(win->RPort,&myImage,100,50);

            /* Wait a bit, then quit.
            ** In a real application, this would be an event loop, like the
            ** one described in the Intuition Input and Output Methods chapter.
            */
            Delay(200);

            CloseWindow(win);
            }
        CloseScreen(scr);
        }
    CloseLibrary((struct Library *)IntuitionBase);
    }
}


Lib_examples/custompointer.c

;/* custompointer.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 custompointer.c
Blink FROM LIB:c.o,custompointer.o TO custompointer LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
**
** The program shows how to set the pointer for a window.  In this
** example, the pointer imagery is changed to a stopwatch symbol which
** could be used to indicate a busy period.
**
** custompointer.c - Show the use of a custom busy pointer, as well as
** using a requester to block input to a window.
*/
#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <exec/libraries.h>
#include <intuition/intuition.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

struct Library *IntuitionBase;

UWORD __chip waitPointer[] =
    {
    0x0000, 0x0000,     /* reserved, must be NULL */

    0x0400, 0x07C0,
    0x0000, 0x07C0,
    0x0100, 0x0380,
    0x0000, 0x07E0,
    0x07C0, 0x1FF8,
    0x1FF0, 0x3FEC,
    0x3FF8, 0x7FDE,
    0x3FF8, 0x7FBE,
    0x7FFC, 0xFF7F,
    0x7EFC, 0xFFFF,
    0x7FFC, 0xFFFF,
    0x3FF8, 0x7FFE,
    0x3FF8, 0x7FFE,
    0x1FF0, 0x3FFC,
    0x07C0, 0x1FF8,
    0x0000, 0x07E0,

    0x0000, 0x0000,     /* reserved, must be NULL */
    };

/*
** The main() routine
*/
VOID main(int argc, char **argv)
{
struct Window *win;
struct Requester null_request;
extern UWORD __chip waitPointer[];

if (IntuitionBase = OpenLibrary("intuition.library",37))
    {
    /* the window is opened as active (WA_Activate) so that the busy
    ** pointer will be visible.  If the window was not active, the
    ** user would have to activate it to see the change in the pointer.
    */
    if (win = OpenWindowTags(NULL,
                             WA_Activate, TRUE,
                             TAG_END))
        {
        /* a NULL requester can be used to block input
        ** in a window without any imagery provided.
        */
        InitRequester(&null_request);

        Delay(50);  /* simulate activity in the program. */

        /* Put up the requester to block user input in the window,
        ** and set the pointer to the busy pointer.
        */
        if (Request(&null_request, win))
            {
            SetPointer(win, waitPointer, 16, 16, -6, 0);

            Delay(100);  /* simulate activity in the program. */

            /* clear the pointer (which resets the window to the default
            ** pointer) and remove the requester.
            */
            ClearPointer(win);
            EndRequest(&null_request, win);
            }

        Delay(100);  /* simulate activity in the program. */

        CloseWindow(win);
        }
    CloseLibrary(IntuitionBase);
    }
}


Lib_examples/displayalert.c

;/* displayalert.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 displayalert.c
Blink FROM LIB:c.o,displayalert.o TO displayalert LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
**
** This program demonstrates an alert.  An explanation of the positioning
** values for the alert strings is in the comment that precedes the
** alertMsg string.
**
** displayalert.c -  This program implements a recoverable alert
*/
#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <intuition/intuition.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

/* Each string requires its own positioning information, as explained
** in the manual.  Hex notation has been used to specify the positions of
** the text. Hex numbers start with a backslash, an "x" and the characters
** that make up the number.
**
** Each line needs 2 bytes of X position, and 1 byte of Y position.
**   In our 1st line: x = \x00\xF0 (2 bytes) and y = \x14 (1 byte)
**   In our 2nd line: x = \x00\xA0 (2 bytes) and y = \x24 (1 byte)
** Each line is null terminated plus a continuation character (0=done).
** This example assumes that the complier will concatenate adjacent
** strings into a single string with no extra NULLs.  The compiler does
** add the terminating NULL at the end of the entire string...The entire
** alert must end in TWO NULLs, one for the end of the string, and one
** for the NULL continuation character.
*/

UBYTE *alertMsg =
    "\x00\xF0\x14" "OH NO, NOT AGAIN!" "\x00\x01"
    "\x00\x80\x24" "PRESS MOUSEBUTTON:   LEFT=TRUE   RIGHT=FALSE" "\x00";

struct Library *IntuitionBase;

VOID main(int argc, char **argv)
{
if (IntuitionBase = OpenLibrary("intuition.library",33))
    {
    if (DisplayAlert(RECOVERY_ALERT, alertMsg, 52))
        printf("Alert returned TRUE\n");
    else
        printf("Alert returned FALSE\n");

    CloseLibrary(IntuitionBase);
    }
}


Lib_examples/easyintuition.c

/* Here's the same example as above written for both Release 2 and
 * earlier versions of the operating system.  The main difference
 * here is that this example avoids using any new Release 2
 * functions, but does pass extended structures to the older
 * Intuition functions so that some new Release 2 features may be
 * accessed in a backward-compatible manner.
 */

/* easyintuition.c  Simple backward-compatible V37 Intuition example    */
/*                                                                      */
/* This example uses extended structures with the pre-V37 OpenScreen()  */
/* and OpenWindow() functions to compatibly open an Intuition display.  */
/* Enhanced V37 options specified via tags are ignored on 1.3 systems.  */
/* Compiled with Lattice C v5.10: lc -L easyintuition.c                 */

/* Force use of new variable names to help prevent errors  */
#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>             /* The Amiga data types file.         */
#include <intuition/intuition.h>    /* Intuition data strucutres, etc.    */
#include <libraries/dos.h>          /* Official return codes defined here */

#include <clib/exec_protos.h>       /* Exec function prototypes           */
#include <clib/intuition_protos.h>  /* Intuition function prototypes      */

#ifdef LATTICE                      /* Disable Ctrl-C handling in SAS/C   */
int CXBRK(void)  {return(0);}
void chkabort(void) {return;}
#endif

/* Use lowest non-obsolete version that supplies the functions needed. */
#define INTUITION_REV 33L

/* Declare the prototypes of our own functions. Prototypes for system  */
/* functions are declared in the header files in the clib directory    */
VOID cleanExit( struct Screen *, struct Window *, LONG );
BOOL handleIDCMP( struct Window *);

struct Library *IntuitionBase = NULL;

/* We can specify that we want the V37-compatible 3D look when
 * running under V37 by adding an SA_Pens tag.
 */
WORD pens[] = {~0};	/* empty pen array to get default 3D look */
struct TagItem ourscreentags[] = {
    { SA_Pens, (ULONG)pens },
    { TAG_DONE }};

/* ExtNewScreen is an extended NewScreen structure.
 * NS_EXTENDED flags that there is a tag pointer to additional
 * tag information at the end of this structure.  The tags will
 * be parsed by Release 2 but ignored by earlier OS versions.
 */
struct ExtNewScreen fullHires =
    {
    0,                /* LeftEdge must be zero prior to Release 2 */
    0,                /* TopEdge */
    640,              /* Width (high-resolution) */
    STDSCREENHEIGHT,  /* Height (non-interlace)  */
    2,                /* Depth (4 colors will be available) */
    0,1,              /* Default DetailPen and BlockPen  */
    HIRES,            /* the high-resolution display mode */
    CUSTOMSCREEN | NS_EXTENDED,     /* the screen type */
    NULL,             /* no special font */
    "Our Screen",     /* the screen title */
    NULL,             /* no custom screen gadgets (not supported) */
    NULL,             /* no CustomBitMap */
    ourscreentags     /* tags for additional V37 features */
    };

/* Position and sizes for our window */
#define WIN_LEFTEDGE   20
#define WIN_TOPEDGE    20
#define WIN_WIDTH     400
#define WIN_MINWIDTH   80
#define WIN_HEIGHT    150
#define WIN_MINHEIGHT  20

/* Under V37, we'll get a special screen title when our window is active */
UBYTE activetitle[] = {"Our Screen - EasyWindow is Active"};

struct TagItem ourwindowtags[] = {
    { WA_ScreenTitle, (ULONG)&activetitle[0] },
    { TAG_DONE }};

/* ExtNewWindow is an extended NewWindow structure.
 * NW_EXTENDED indicates that there is a tag pointer to additional tag
 * information at the end of this structure.  The tags will be parsed
 * by Release 2 but ignored by earlier OS versions.
 */
struct ExtNewWindow easyWindow =
    {
    WIN_LEFTEDGE,
    WIN_TOPEDGE,
    WIN_WIDTH,
    WIN_HEIGHT,
    -1,-1,             /* Means use the screen's Detail and Block pens   */

    IDCMP_CLOSEWINDOW, /* This field specifies the events we want to get */

    /* These flags specify system gadgets and other window attributes    */
    /* including the EXTENDED flag which flags this as an ExtNewWindow   */
    WFLG_CLOSEGADGET | WFLG_SMART_REFRESH | WFLG_ACTIVATE | WFLG_DRAGBAR |
    WFLG_DEPTHGADGET | WFLG_SIZEGADGET  | WFLG_NOCAREREFRESH |
    WFLG_NW_EXTENDED,

    NULL,             /* Pointer to the first gadget  */
    NULL,             /* No checkmark.                */
    "EasyWindow",     /* Window title.                */
    NULL,             /* Attach a screen later.       */
    NULL,             /* Let Intuition set up BitMap  */
    WIN_MINWIDTH,     /* Minimum width.       */
    WIN_MINHEIGHT,    /* Minimum height.      */
    -1,               /* Maximum width (screen size)  */
    -1,               /* Maximum height (screen size) */
    CUSTOMSCREEN,     /* A screen of our own. */
    ourwindowtags     /* tags for additional V37 features */
    };

VOID main(int argc, char *argv[])
{
    /* Declare variables here */
    ULONG signalmask, winsignal, signals;
    BOOL done = FALSE;
    struct Screen *screen1 = NULL;
    struct Window *window1 = NULL;

    /* Open Intuition Library.  NOTE - We are accepting version 33 (1.2)
     * or higher because we are opening our display in a compatible manner.
     * However - If you add to this example, do NOT use any NEW V37
     * functions unless IntuitionBase->lib_Version is >= 37
     */
    IntuitionBase = OpenLibrary( "intuition.library",INTUITION_REV );
    if (IntuitionBase == NULL)
        cleanExit(screen1, window1, RETURN_WARN);

    /* Open any other required libraries and make */
    /* any assignments that were postponed above  */

    /* Open the screen */
    screen1 = OpenScreen(&fullHires);
    if (screen1 == NULL)
        cleanExit(screen1, window1, RETURN_WARN);

    /* Attach the window to the open screen ... */
    easyWindow.Screen = screen1;

    /* ... and open the window */
    window1 = OpenWindow(&easyWindow);
    if (window1 == NULL)
        cleanExit(screen1, window1, RETURN_WARN);

    /* Set up the signals for the events we want to hear about ...   */
    winsignal = 1L << window1->UserPort->mp_SigBit;  /* window IDCMP */
    signalmask = winsignal;     /* we will only wait on IDCMP events */

    /* Here's the main input event loop where we wait for events.    */
    /* We have asked Intuition to send us CLOSEWINDOW IDCMP events   */
    /* Exec will wake us if any event we are waiting for occurs.     */
    while( !done )
    {
        signals = Wait(signalmask);

        /* An event occurred - now act on the signal(s) we received.*/
        /* We were only waiting on one signal (winsignal) in our    */
        /* signalmask, so we actually know we received winsignal.   */
        if(signals & winsignal)
            done = handleIDCMP(window1);    /* done if close gadget */
    }
    cleanExit(screen1, window1, RETURN_OK); /* Exit the program     */
}

BOOL handleIDCMP( struct Window *win )
{
    BOOL done = FALSE;
    struct IntuiMessage *message;
    ULONG class;

    /* Examine pending messages */
    while( message = (struct IntuiMessage *)GetMsg(win->UserPort) )
    {
        class = message->Class;   /* get all data we need from message */

        /* When we're through with a message, reply */
        ReplyMsg( (struct Message *)message);

        /* See what events occurred */
        switch( class )
        {
            case IDCMP_CLOSEWINDOW:
                done = TRUE;
                break;
            default:
                break;
        }
    }
    return(done);
}

VOID cleanExit( struct Screen *scrn, struct Window *wind, LONG returnValue )
{
    /* Close things in the reverse order of opening */
    if (wind) CloseWindow( wind );      /* Close window if opened */
    if (scrn) CloseScreen( scrn );      /* Close screen if opened */

    /* Close the library, and then exit */
    if (IntuitionBase) CloseLibrary( IntuitionBase );
    exit(returnValue);
}


Lib_examples/easyintuition37.c

/* This example shows a simple Intuition program that works with
 * Release 2 (V36) and later versions of the Amiga operating system.
 */

/* easyintuition37.c -- Simple Intuition program for V37   */
/* (Release 2) and later versions of the operating system. */
/* Compiled with Lattice C v5.04: lc -L easyintuition37.c  */

#include <exec/types.h>             /* The Amiga data types file.         */
#include <intuition/intuition.h>    /* Intuition data strucutres, etc.    */
#include <graphics/displayinfo.h>   /* Release 2 Amiga display mode ID's  */
#include <libraries/dos.h>          /* Official return codes defined here */

#include <clib/exec_protos.h>       /* Exec function prototypes           */
#include <clib/intuition_protos.h>  /* Intuition function prototypes      */

/* Force use of new variable names to help prevent errors  */
#define INTUI_V36_NAMES_ONLY

#ifdef LATTICE                      /* Disable Ctrl-C handling in SAS/C   */
int CXBRK(void)  {return(0);}
void chkabort(void) {return;}
#endif

/* Use lowest non-obsolete version that supplies the functions needed. */
#define INTUITION_REV 37

/* Declare the prototypes of our own functions.  Prototypes for system */
/* functions are declared in the header files in the clib directory.   */
VOID cleanExit( struct Screen *, struct Window *, LONG );
BOOL handleIDCMP( struct Window *);

struct Library *IntuitionBase = NULL;

/* Position and sizes for our window */
#define WIN_LEFTEDGE   20
#define WIN_TOPEDGE    20
#define WIN_WIDTH     400
#define WIN_MINWIDTH   80
#define WIN_HEIGHT    150
#define WIN_MINHEIGHT  20

VOID main(int argc, char *argv[])
{
    /* Declare variables here */
    ULONG signalmask, winsignal, signals;
    BOOL done = FALSE;
    UWORD pens[]={~0};

    struct Screen *screen1 = NULL;
    struct Window *window1 = NULL;

    /* Open the Intuition Library */
    IntuitionBase = OpenLibrary( "intuition.library",INTUITION_REV );
    if (IntuitionBase == NULL)
        cleanExit(screen1, window1, RETURN_WARN);

    /* Open any other required libraries and make */
    /* any assignments that were postponed above  */

    /* Open the screen */
    screen1 = OpenScreenTags(NULL,
                             SA_Pens,  (ULONG)pens,
                             SA_DisplayID, HIRES_KEY,
                             SA_Depth, 2,
                             SA_Title, (ULONG)"Our Screen",
                             TAG_DONE);

    if (screen1 == NULL)
        cleanExit(screen1, window1, RETURN_WARN);

    /* ... and open the window */
    window1 = OpenWindowTags(NULL,
                             /* Specify window dimensions and limits */
                             WA_Left,         WIN_LEFTEDGE,
                             WA_Top,          WIN_TOPEDGE,
                             WA_Width,        WIN_WIDTH,
                             WA_Height,       WIN_HEIGHT,
                             WA_MinWidth,     WIN_MINWIDTH,
                             WA_MinHeight,    WIN_MINHEIGHT,
                             WA_MaxWidth,     ~0,
                             WA_MaxHeight,    ~0,
                             /* Specify the system gadgets we want */
                             WA_CloseGadget,  TRUE,
                             WA_SizeGadget,   TRUE,
                             WA_DepthGadget,  TRUE,
                             WA_DragBar,      TRUE,
                             /* Specify other attributes           */
                             WA_Activate,     TRUE,
                             WA_NoCareRefresh,TRUE,

                             /* Specify the events we want to know about */
                             WA_IDCMP,        IDCMP_CLOSEWINDOW,

                             /* Attach the window to the open screen ...*/
                             WA_CustomScreen, screen1,
                             WA_Title,        "EasyWindow",
                             WA_ScreenTitle,  "Our Screen - EasyWindow is Active",
                             TAG_DONE);
    if (window1 == NULL)
        cleanExit(screen1, window1, RETURN_WARN);

    /* Set up the signals for the events we want to hear about ...   */
    winsignal = 1L << window1->UserPort->mp_SigBit;  /* window IDCMP */
    signalmask = winsignal;   /* we are only waiting on IDCMP events */

    /* Here's the main input event loop where we wait for events.    */
    /* We have asked Intuition to send us CLOSEWINDOW IDCMP events   */
    /* Exec will wake us if any event we are waiting for occurs.     */
    while( !done )
    {
        signals = Wait(signalmask);

        /* An event occurred - now act on the signal(s) we received.*/
        /* We were only waiting on one signal (winsignal) in our    */
        /* signalmask, so we actually know we received winsignal.   */
        if(signals & winsignal)
            done = handleIDCMP(window1);    /* done if close gadget */
    }
    cleanExit(screen1, window1, RETURN_OK); /* Exit the program     */
}

BOOL handleIDCMP( struct Window *win )
{
    BOOL done = FALSE;
    struct IntuiMessage *message = NULL;
    ULONG class;

    /* Examine pending messages */
    while( message = (struct IntuiMessage *)GetMsg(win->UserPort) )
    {
        class = message->Class;  /* get all data we need from message */

        /* When we're through with a message, reply */
        ReplyMsg( (struct Message *)message);

        /* See what events occurred */
        switch( class )
        {
            case IDCMP_CLOSEWINDOW:
                done = TRUE;
                break;
            default:
                break;
        }
    }
    return(done);
}

VOID cleanExit( struct Screen *scrn, struct Window *wind, LONG returnValue )
{
    /* Close things in the reverse order of opening */
    if (wind) CloseWindow( wind );      /* Close window if opened */
    if (scrn) CloseScreen( scrn );      /* Close screen if opened */

    /* Close the library, and then exit */
    if (IntuitionBase) CloseLibrary( IntuitionBase );
    exit(returnValue);
}


Lib_examples/easyrequest.c

;/* easyrequest.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 easyrequest.c
Blink FROM LIB:c.o,easyrequest.o TO easyrequest LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit

** easyrequest.c - show the use of an easy requester.
*/
#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <intuition/intuition.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

/* declare the easy request structure.
** this uses many features of EasyRequest(), including:
**     multiple lines of body text separated by '\n'.
**     variable substitution of a string (%s) in the body text.
**     multiple button gadgets separated by '|'.
**     variable substitution in a gadget (long decimal '%ld').
*/
struct EasyStruct myES =
    {
    sizeof(struct EasyStruct),
    0,
    "Request Window Name",
    "Text for the request\nSecond line of %s text\nThird line of text for the request",
    "Yes|%ld|No",
    };

struct Library *IntuitionBase;

/*
** Main routine to show the use of EasyRequest()
*/
VOID main (int argc, char **argv)
{
LONG answer;
LONG number;

number = 3125794;  /* for use in the middle button */

if (IntuitionBase = OpenLibrary("intuition.library",37))
    {
    /* note in the variable substitution:
    **     the string goes in the first open variable (in body text).
    **     the number goes in the second open (gadget text).
    */
    answer = EasyRequest(NULL, &myES, NULL, "(Variable)", number);

    /* Process the answer.  Note that the buttons are numbered in
    ** a strange order.  This is because the rightmost button is
    ** always a negative reply.  The code can use this if it chooses,
    ** with a construct like:
    **
    **     if (EasyRequest())
    **          positive_response();
    */
    switch (answer)
        {
        case 1:
            printf("selected 'Yes'\n");
            break;
        case 2:
            printf("selected '%ld'\n", number);
            break;
        case 0:
            printf("selected 'No'\n");
            break;
        }

    CloseLibrary(IntuitionBase);
    }
}


Lib_examples/intuitext.c

;/* intuitext.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 intuitext.c
Blink FROM LIB:c.o,intuitext.o TO intuitext LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit

** intuitext.c - program to show the use of an Intuition IntuiText object.
*/
#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <intuition/intuition.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

struct Library *IntuitionBase = NULL;

#define MYTEXT_LEFT (0)
#define MYTEXT_TOP  (0)

/*
** main routine. Open required library and window and draw the images.
** This routine opens a very simple window with no IDCMP.  See the
** chapters on "Windows" and "Input and Output Methods" for more info.
** Free all resources when done.
*/
VOID main(int argc, char **argv)
{
struct Screen    *screen;
struct DrawInfo  *drawinfo;
struct Window    *win;
struct IntuiText  myIText;
struct TextAttr   myTextAttr;

ULONG myTEXTPEN;
ULONG myBACKGROUNDPEN;

IntuitionBase = OpenLibrary("intuition.library",37);
if (IntuitionBase)
    {
    if (screen = LockPubScreen(NULL))
        {
        if (drawinfo = GetScreenDrawInfo(screen))
            {
            /* Get a copy of the correct pens for the screen.
            ** This is very important in case the user or the
            ** application has the pens set in a unusual way.
            */
            myTEXTPEN = drawinfo->dri_Pens[TEXTPEN];
            myBACKGROUNDPEN  = drawinfo->dri_Pens[BACKGROUNDPEN];

            /* create a TextAttr that matches the specified font. */
            myTextAttr.ta_Name  = drawinfo->dri_Font->tf_Message.mn_Node.ln_Name;
            myTextAttr.ta_YSize = drawinfo->dri_Font->tf_YSize;
            myTextAttr.ta_Style = drawinfo->dri_Font->tf_Style;
            myTextAttr.ta_Flags = drawinfo->dri_Font->tf_Flags;

            /* open a simple window on the workbench screen for displaying
            ** a text string.  An application would probably never use such a
            ** window, but it is useful for demonstrating graphics...
            */
            if (win = OpenWindowTags(NULL,
                                WA_PubScreen,    screen,
                                WA_RMBTrap,      TRUE,
                                TAG_END))
                {
                myIText.FrontPen    = myTEXTPEN;
                myIText.BackPen     = myBACKGROUNDPEN;
                myIText.DrawMode    = JAM2;
                myIText.LeftEdge    = MYTEXT_LEFT;
                myIText.TopEdge     = MYTEXT_TOP;
                myIText.ITextFont   = &myTextAttr;
                myIText.IText       = "Hello, World.  ;-)";
                myIText.NextText    = NULL;

                /* Draw the text string at 10,10 */
                PrintIText(win->RPort,&myIText,10,10);

                /* Wait a bit, then quit.
                ** In a real application, this would be an event loop,
                ** like the one described in the Intuition Input and
                ** Output Methods chapter.
                */
                Delay(200);

                CloseWindow(win);
                }
            FreeScreenDrawInfo(screen,drawinfo);
            }
        UnlockPubScreen(NULL,screen);
        }
    CloseLibrary(IntuitionBase);
    }
}


Lib_examples/mousetest.c

;/* mousetest.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 mousetest.c
Blink FROM LIB:c.o,mousetest.o TO mousetest LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit

** mousetest.c - Read position and button events from the mouse.
*/
#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <intuition/intuition.h>
#include <graphics/gfxbase.h>
#include <devices/inputevent.h>

#include <clib/exec_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

#define BUFSIZE 16

/* something to use to track the time between messages
** to test for double-clicks.
*/
typedef struct myTimeVal
    {
    ULONG LeftSeconds;
    ULONG LeftMicros;
    ULONG RightSeconds;
    ULONG RightMicros;
    } MYTIMEVAL;

/* our function prototypes */
VOID doButtons(struct IntuiMessage *msg, MYTIMEVAL *tv);
VOID process_window(struct Window *win);

struct Library *IntuitionBase;
struct GfxBase       *GfxBase;	/* we need GfxBase->DefaultFont */

/*
** main() -- set-up everything.
*/
VOID main(int argc, char **argv)
{
struct Window *win;
struct Screen *scr;
struct DrawInfo *dr_info;
ULONG width;

/* Open the libraries we will use.  Requires Release 2 (KS V2.04, V37) */
if (IntuitionBase = OpenLibrary("intuition.library",37))
    {
    if (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 37))
        {
        /* Lock the default public screen in order to read its DrawInfo data */
        if (scr = LockPubScreen(NULL))
            {
            if (dr_info = GetScreenDrawInfo(scr))
                {
                /* use wider of space needed for output (18 chars and spaces)
                 * or titlebar text plus room for titlebar gads (approx 18 each)
                 */
                width = max((GfxBase->DefaultFont->tf_XSize * 18),
                            (18 * 2) + TextLength(&scr->RastPort,"MouseTest",9));

                if (win = OpenWindowTags(NULL,
                            WA_Top,    20,
                            WA_Left,   100,
                            WA_InnerWidth,  width,
                            WA_Height, (2 * GfxBase->DefaultFont->tf_YSize) +
                                       scr->WBorTop + scr->Font->ta_YSize + 1 +
                                       scr->WBorBottom,
                            WA_Flags, WFLG_DEPTHGADGET | WFLG_CLOSEGADGET |
                                      WFLG_ACTIVATE    | WFLG_REPORTMOUSE |
                                      WFLG_RMBTRAP     | WFLG_DRAGBAR,
                            WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_RAWKEY |
                                      IDCMP_MOUSEMOVE   | IDCMP_MOUSEBUTTONS,
                            WA_Title, "MouseTest",
                            WA_PubScreen, scr,
                            TAG_END))
                    {
                    printf("Monitors the Mouse:\n");
                    printf("    Move Mouse, Click and DoubleClick in Window\n");

                    SetAPen(win->RPort,dr_info->dri_Pens[TEXTPEN]);
                    SetBPen(win->RPort,dr_info->dri_Pens[BACKGROUNDPEN]);
                    SetDrMd(win->RPort,JAM2);

                    process_window(win);

                    CloseWindow(win);
                    }
                FreeScreenDrawInfo(scr, dr_info);
                }
            UnlockPubScreen(NULL,scr);
            }
        CloseLibrary((struct Library *)GfxBase);
        }
    CloseLibrary(IntuitionBase);
    }
}

/*
** process_window() - simple message loop for processing IntuiMessages
*/
VOID process_window(struct Window *win)
{
USHORT done;
struct IntuiMessage *msg;
MYTIMEVAL tv;
UBYTE prt_buff[14];
LONG xText, yText;  /* places to position text in window. */

done = FALSE;
tv.LeftSeconds = 0; /* initial values for testing double-click */
tv.LeftMicros  = 0;
tv.RightSeconds = 0;
tv.RightMicros  = 0;
xText = win->BorderLeft + (win->IFont->tf_XSize * 2);
yText = win->BorderTop + 3 + win->IFont->tf_Baseline;

while (!done)
    {
    Wait((1L<<win->UserPort->mp_SigBit));

    while ((!done) &&
           (msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
        {
        switch (msg->Class)
            {
            case IDCMP_CLOSEWINDOW:
                done = TRUE;
                break;
            /* NOTE NOTE NOTE:  If the mouse queue backs up a lot, Intuition
            ** will start dropping MOUSEMOVE messages off the end until the
            ** queue is serviced.  This may cause the program to lose some
            ** of the MOUSEMOVE events at the end of the stream.
            **
            ** Look in the window structure if you need the true position
            ** of the mouse pointer at any given time.  Look in the
            ** MOUSEBUTTONS message if you need position when it clicked.
            ** An alternate to this processing would be to set a flag that
            ** a mousemove event arrived, then print the position of the
            ** mouse outside of the "while (GetMsg())" loop.  This allows
            ** a single processing call for many mouse events, which speeds
            ** up processing A LOT!  Something like:
            **
            ** while (GetMsg())
            **    {
            **    if (class == IDCMP_MOUSEMOVE)
            **        mouse_flag = TRUE;
            **    ReplyMsg();   NOTE: copy out all needed fields first !
            **    }
            ** if (mouse_flag)
            **    {
            **    process_mouse_event();
            **    mouse_flag = FALSE;
            **    }
            **
            ** You can also use IDCMP_INTUITICKS for slower paced messages
            ** (all messages have mouse coordinates.)
            */
            case IDCMP_MOUSEMOVE:
                /* Show the current position of the mouse relative to the
                ** upper left hand corner of our window
                */
                Move(win->RPort,xText,yText);
                sprintf(prt_buff, "X%5d Y%5d", msg->MouseX, msg->MouseY);
                Text(win->RPort,prt_buff,13);
                break;
            case IDCMP_MOUSEBUTTONS:
                doButtons(msg,&tv);
                break;
            }
        ReplyMsg((struct Message *)msg);
        }
    }
}

/*
** Show what mouse buttons where pushed
*/
VOID doButtons(struct IntuiMessage *msg, MYTIMEVAL *tv)
{
/* Yes, qualifiers can apply to the mouse also.  That is how
** we get the shift select on the Workbench.  This shows how
** to see if a specific bit is set within the qualifier
*/
if (msg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
    printf("Shift ");

switch (msg->Code)
    {
    case SELECTDOWN:
        printf("Left Button Down at X%ld Y%ld", msg->MouseX, msg->MouseY);
        if(DoubleClick(tv->LeftSeconds, tv->LeftMicros, msg->Seconds, msg->Micros))
            printf(" DoubleClick!");
        else
            {
            tv->LeftSeconds = msg->Seconds;
            tv->LeftMicros  = msg->Micros;
            tv->RightSeconds = 0;
            tv->RightMicros  = 0;
            }
        break;
    case SELECTUP:
        printf("Left Button Up   at X%ld Y%ld", msg->MouseX, msg->MouseY);
        break;
    case MENUDOWN:
        printf("Right Button down at X%ld Y%ld", msg->MouseX, msg->MouseY);
        if(DoubleClick(tv->RightSeconds, tv->RightMicros, msg->Seconds, msg->Micros))
            printf(" DoubleClick!");
        else
            {
            tv->LeftSeconds = 0;
            tv->LeftMicros  = 0;
            tv->RightSeconds = msg->Seconds;
            tv->RightMicros  = msg->Micros;
            }
        break;
    case MENUUP:
        printf("Right Button Up   at X%ld Y%ld", msg->MouseX, msg->MouseY);
        break;
    }
printf("\n");
}


Lib_examples/remembertest.c

;/* remembertest.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 remembertest.c
Blink FROM LIB:c.o,remembertest.o TO remembertest LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit

** RememberTest - Illustrates the use of AllocRemember() and FreeRemember().
*/
#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <intuition/intuition.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>

#include <stdlib.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

/* our function prototypes */
VOID methodOne(VOID);
VOID methodTwo(VOID);

struct IntuitionBase *IntuitionBase;

/* random sizes to demonstrate the Remember functions. */
#define SIZE_A 100L
#define SIZE_B 200L

/*
** main() - Initialize everything.
*/
VOID main(int argc, char **argv)
{
LONG exitVal = RETURN_OK;

IntuitionBase = OpenLibrary("intuition.library", 33L);
if (IntuitionBase == NULL)
    exitVal = RETURN_FAIL;
else
    {
    methodOne();
    methodTwo();

    CloseLibrary(IntuitionBase);
    }
exit(exitVal);
}

/*
** MethodOne
** Illustrates using AllocRemember() to allocate all memory and
** FreeRemember() to free it all.
*/
VOID methodOne(VOID)
{
APTR memBlockA = NULL, memBlockB = NULL;
struct Remember *rememberKey = NULL;

memBlockA = AllocRemember(&rememberKey, SIZE_A, MEMF_CLEAR | MEMF_PUBLIC);
if (memBlockA)
    {
    /*  The memBlockA allocation succeeded; try for memBlockB.  */
    memBlockB = AllocRemember(&rememberKey, SIZE_B, MEMF_CLEAR | MEMF_PUBLIC);
    if (memBlockB)
        {
        /*  Both memory allocations succeeded.
        **  The program may now use this memory.
        */
        }
    }

/* It is not necessary to keep track of the status of each allocation.
** Intuition has kept track of all successful allocations by updating its
** linked list of Remember nodes.  The following call to FreeRemember() will
** deallocate any and all of the memory that was successfully allocated.
** The memory blocks as well as the link nodes will be deallocated because
** the "ReallyForget" parameter is TRUE.
**
** It is possible to have reached the call to FreeRemember()
** in one of three states.  Here they are, along with their results.
**
** 1. Both memory allocations failed.
**       RememberKey is still NULL.  FreeRemember() will do nothing.
** 2. The memBlockA allocation succeeded but the memBlockB allocation failed.
**       FreeRemember() will free the memory block pointed to by memBlockA.
** 3. Both memory allocations were successful.
**       FreeRemember() will free the memory blocks pointed to by
**       memBlockA and memBlockB.
*/
FreeRemember(&rememberKey, TRUE);
}

/*
** MethodTwo
** Illustrates using AllocRemember() to allocate all memory,
** FreeRemember() to free the link nodes, and FreeMem() to
** free the actual memory blocks.
*/
VOID methodTwo(VOID)
{
APTR memBlockA = NULL, memBlockB = NULL;
struct Remember *rememberKey = NULL;

memBlockA = AllocRemember(&rememberKey, SIZE_A, MEMF_CLEAR | MEMF_PUBLIC);
if (memBlockA)
    {
    /*  The memBlockA allocation succeeded; try for memBlockB.  */
    memBlockB = AllocRemember(&rememberKey, SIZE_B, MEMF_CLEAR | MEMF_PUBLIC);
    if (memBlockB)
        {
        /* Both memory allocations succeeded.
        ** For the purpose of illustration, FreeRemember() is called at
        ** this point, but only to free the link nodes.  The memory pointed
        ** to by memBlockA and memBlockB is retained.
        */
        FreeRemember(&rememberKey, FALSE);

        /* Individually free the two memory blocks. The Exec FreeMem()
        ** call must be used, as the link nodes are no longer available.
        */
        FreeMem((VOID *)memBlockA, SIZE_A);
        FreeMem((VOID *)memBlockB, SIZE_B);
        }
    }

/* It is possible to have reached the call to FreeRemember()
** in one of three states.  Here they are, along with their results.
**
** 1. Both memory allocations failed.
**    RememberKey is still NULL.  FreeRemember() will do nothing.
** 2. The memBlockA allocation succeeded but the memBlockB allocation failed.
**    FreeRemember() will free the memory block pointed to by memBlockA.
** 3. Both memory allocations were successful.
**    If this is the case, the program has already freed the link nodes
**    with FreeRemember() and the memory blocks with FreeMem().
**    When FreeRemember() freed the link nodes, it reset RememberKey
**    to NULL.  This (second) call to FreeRemember() will do nothing.
*/
FreeRemember(&rememberKey, TRUE);
}


Lib_examples/shadowborder.c

;/* shadowborder.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 shadowborder.c
Blink FROM LIB:c.o,shadowborder.o TO shadowborder LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
**
** The following example draws a double border using two pens to create a
** shadow effect.  The border is drawn in two positions to show the
** flexibility in positioning borders, note that it could also be attached
** to a menu, gadget or requester.
**
** shadowborder.c - program to show the use of an Intuition Border.
*/
#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <intuition/intuition.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

struct Library *IntuitionBase = NULL;

#define MYBORDER_LEFT   (0)
#define MYBORDER_TOP    (0)

/* This is the border data. */
WORD myBorderData[] =
    {
    0,0, 50,0, 50,30, 0,30, 0,0,
    };

/*
** main routine. Open required library and window and draw the images.
** This routine opens a very simple window with no IDCMP.  See the
** chapters on "Windows" and "Input and Output Methods" for more info.
** Free all resources when done.
*/
VOID main(int argc, char **argv)
{
struct Screen   *screen;
struct DrawInfo *drawinfo;
struct Window   *win;
struct Border    shineBorder;
struct Border    shadowBorder;

ULONG mySHADOWPEN = 1;  /* set default values for pens */
ULONG mySHINEPEN  = 2;  /* in case can't get info...   */

IntuitionBase = OpenLibrary("intuition.library",37);
if (IntuitionBase)
    {
    if (screen = LockPubScreen(NULL))
        {
        if (drawinfo = GetScreenDrawInfo(screen))
            {
            /* Get a copy of the correct pens for the screen.
            ** This is very important in case the user or the
            ** application has the pens set in a unusual way.
            */
            mySHADOWPEN = drawinfo->dri_Pens[SHADOWPEN];
            mySHINEPEN  = drawinfo->dri_Pens[SHINEPEN];

            FreeScreenDrawInfo(screen,drawinfo);
            }
        UnlockPubScreen(NULL,screen);
        }

    /* open a simple window on the workbench screen for displaying
    ** a border.  An application would probably never use such a
    ** window, but it is useful for demonstrating graphics...
    */
    if (win = OpenWindowTags(NULL,
                        WA_PubScreen,  screen,
                        WA_RMBTrap,      TRUE,
                        TAG_END))
        {
        /* set information specific to the shadow component of the border */
        shadowBorder.LeftEdge   = MYBORDER_LEFT + 1;
        shadowBorder.TopEdge    = MYBORDER_TOP + 1;
        shadowBorder.FrontPen   = mySHADOWPEN;
        shadowBorder.NextBorder = &shineBorder;

        /* set information specific to the shine component of the border */
        shineBorder.LeftEdge    = MYBORDER_LEFT;
        shineBorder.TopEdge     = MYBORDER_TOP;
        shineBorder.FrontPen    = mySHINEPEN;
        shineBorder.NextBorder  = NULL;

        /* the following attributes are the same for both borders. */
        shadowBorder.BackPen    = shineBorder.BackPen   = 0;
        shadowBorder.DrawMode   = shineBorder.DrawMode  = JAM1;
        shadowBorder.Count      = shineBorder.Count     = 5;
        shadowBorder.XY         = shineBorder.XY        = myBorderData;

        /* Draw the border at 10,10 */
        DrawBorder(win->RPort,&shadowBorder,10,10);

        /* Draw the border again at 100,10 */
        DrawBorder(win->RPort,&shadowBorder,100,10);

        /* Wait a bit, then quit.
        ** In a real application, this would be an event loop, like the
        ** one described in the Intuition Input and Output Methods chapter.
        */
        Delay(200);

        CloseWindow(win);
        }
    CloseLibrary(IntuitionBase);
    }
}


Lib_examples/simpleimage.c

/* simpleimage.c - program to show the use of a simple Intuition Image.
**
** compiled with:
** lc -b1 -cfist -v -y simpleimage.c
** blink FROM LIB:c.o+"simpleimage.o" TO "simpleimage" LIB LIB:lc.lib LIB:amiga.lib
*/
#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

struct IntuitionBase *IntuitionBase = NULL;

#define MYIMAGE_LEFT    (0)
#define MYIMAGE_TOP     (0)
#define MYIMAGE_WIDTH   (24)
#define MYIMAGE_HEIGHT  (10)
#define MYIMAGE_DEPTH   (1)

/* This is the image data.  It is a one bit-plane open rectangle which is 24
** pixels wide and 10 high.  Make sure that it is in CHIP memory, or allocate
** a block of chip memory with a call like this: AllocMem(data_size,MEMF_CHIP),
** and then copy the data to that block.  See the Exec chapter on Memory
** Allocation for more information on AllocMem().
*/
UWORD __chip myImageData[] =
    {
    0xFFFF, 0xFF00,
    0xC000, 0x0300,
    0xC000, 0x0300,
    0xC000, 0x0300,
    0xC000, 0x0300,
    0xC000, 0x0300,
    0xC000, 0x0300,
    0xC000, 0x0300,
    0xC000, 0x0300,
    0xFFFF, 0xFF00,
    };

/*
** main routine. Open required library and window and draw the images.
** This routine opens a very simple window with no IDCMP.  See the
** chapters on "Windows" and "Input and Output Methods" for more info.
** Free all resources when done.
*/
VOID main(int argc, char *argv[])
{
struct Window *win;
struct Image myImage;

IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37);
if (IntuitionBase != NULL)
    {
    if (NULL != (win = OpenWindowTags(NULL,
                        WA_Width,       200,
                        WA_Height,      100,
                        WA_RMBTrap,     TRUE,
                        TAG_END)))
        {
        myImage.LeftEdge    = MYIMAGE_LEFT;
        myImage.TopEdge     = MYIMAGE_TOP;
        myImage.Width       = MYIMAGE_WIDTH;
        myImage.Height      = MYIMAGE_HEIGHT;
        myImage.Depth       = MYIMAGE_DEPTH;
        myImage.ImageData   = myImageData;
        myImage.PlanePick   = 0x1;              /* use first bit-plane     */
        myImage.PlaneOnOff  = 0x0;              /* clear all unused planes */
        myImage.NextImage   = NULL;

        /* Draw the 1 bit-plane image into the first bit-plane (color 1) */
        DrawImage(win->RPort,&myImage,10,10);

        /* Draw the same image at a new location */
        DrawImage(win->RPort,&myImage,100,10);

        /* Wait a bit, then quit.
        ** In a real application, this would be an event loop, like the
        ** one described in the Intuition Input and Output Methods chapter.
        */
        Delay(200);

        CloseWindow(win);
        }
    CloseLibrary((struct Library *)IntuitionBase);
    }
}


Lib_examples/maprawkey.c

;/* maprawkey.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 maprawkey.c
Blink FROM LIB:c.o,maprawkey.o TO maprawkey LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
* maprawkey.c - Map Intuition RAWKEY events to ANSI with MapRawKey();
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <intuition/intuition.h>
#include <devices/inputevent.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/keymap_protos.h>
#include <clib/intuition_protos.h>

#include <stdio.h>
#include <stdlib.h>

#ifdef LATTICE
int CXBRK(void)  { return(0); }  /* Disable Lattice CTRL/C handling */
void chkabort(void) { return; }  /* really */
#endif

/* our function prototypes */
void openall(void);
void closeall(void);
void closeout(UBYTE *errstring, LONG rc);

struct Library    *IntuitionBase = NULL;
struct Library    *KeymapBase    = NULL;
struct Window     *window        = NULL;

void main(int argc, char **argv)
{
    struct IntuiMessage *imsg;
    APTR                *eventptr;
    struct InputEvent   inputevent = {0};
    LONG                windowsignal;
    UBYTE               buffer[8];
    COUNT               i;
    BOOL                Done = FALSE;

    openall();

    window = OpenWindowTags(NULL,
                            WA_Width,  500,
                            WA_Height, 60,
                            WA_Title, "MapRawKey - Press Keys",
                            WA_Flags, WFLG_CLOSEGADGET | WFLG_ACTIVATE,
                            WA_IDCMP, IDCMP_RAWKEY | IDCMP_CLOSEWINDOW,
                            TAG_DONE);
    if(window == NULL)   closeout("Can't open window",RETURN_FAIL);

    windowsignal = 1L << window->UserPort->mp_SigBit;

    /* Initialize InputEvent structure (already cleared to 0) */
    inputevent.ie_Class = IECLASS_RAWKEY;

    while(!Done)
       {
       Wait(windowsignal);

       while (imsg = (struct IntuiMessage *)GetMsg(window->UserPort))
           {
           switch(imsg->Class)
               {
                case IDCMP_CLOSEWINDOW:
                    Done = TRUE;
                    break;

                case IDCMP_RAWKEY:
                    inputevent.ie_Code = imsg->Code;
                    inputevent.ie_Qualifier = imsg->Qualifier;

                    printf("RAWKEY: Code=$%04x  Qualifier=$%04lx\n",
                             imsg->Code, imsg->Qualifier);

                    /* Make sure deadkeys and qualifiers are taken
                     * into account.
                     */
                    eventptr = imsg->IAddress;
                    inputevent.ie_EventAddress = *eventptr;

                    /* Map RAWKEY to ANSI */
                    i = MapRawKey(&inputevent, buffer, 8, NULL);

                    if (i == -1) Write(Output(),"*Overflow*",10);
                    else if (i)
                        {
                        /* This key or key combination mapped to something */
                        printf("MAPS TO: ");
                        Write(Output(),buffer,i);
                        printf("\n");
                        }
                    break;
                }
            ReplyMsg((struct Message *)imsg);
            }
        }
    CloseWindow(window);
    closeall();
    exit(RETURN_OK);
}

void openall(void)
{

    KeymapBase = OpenLibrary("keymap.library", 37);
    if (KeymapBase == NULL)    closeout("Kickstart 2.0 required",RETURN_FAIL);

    IntuitionBase = OpenLibrary("intuition.library", 37);
    if (IntuitionBase == NULL) closeout("Can't open intuition",RETURN_FAIL);
}

void closeall(void)
{
    if (IntuitionBase)  CloseLibrary(IntuitionBase);
    if (KeymapBase)     CloseLibrary(KeymapBase);
}

void closeout(UBYTE *errstring, LONG rc)
{
    if (*errstring)  printf("%s\n",errstring);
    closeall();
    exit(rc);
}


Lib_examples/mapansi.c

;/* mapansi.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 mapansi.c
Blink FROM LIB:c.o,mapansi.o TO mapansi LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit

mapansi.c - converts a string to input events using MapANSI() function.

            This example will also take the created input events
            and add them to the input stream using the simple
            commodities.library function AddIEvents().  Alternately,
            you could open the input.device and use the input device
            command IND_WRITEEVENT to add events to the input stream.
*/

#include       <exec/types.h>
#include       <exec/memory.h>
#include       <exec/io.h>
#include       <dos/dos.h>
#include       <devices/input.h>
#include       <devices/inputevent.h>

#include       <clib/exec_protos.h>
#include       <clib/dos_protos.h>
#include       <clib/keymap_protos.h>
#include       <clib/commodities_protos.h>

#include       <stdio.h>
#include       <stdlib.h>

#ifdef LATTICE
int CXBRK(void)  { return(0); }  /* Disable Lattice CTRL/C handling */
void chkabort(void) { return; }  /* really */
#endif

struct Library          *KeymapBase = NULL;       /* MapAnsi() function    */
struct Library          *CxBase = NULL;           /* AddIEvents() function */

struct InputEvent       *InputEvent = NULL;       /* we'll allocate this */

/* prototypes for our program functions */

void openall(void);
void closeall(void);
void closeout(UBYTE *errstring, LONG rc);

void main(int argc, char **argv)
{
    UBYTE               *string;
    UBYTE               *tmp1;
    UBYTE               *tmp2;
    UBYTE               iebuffer[6];            /* Space for two dead keys */
                                                /* + 1 key + qualifiers    */
    COUNT               i;
    LONG                rc = 0;

    openall();

    string = ";String converted to input events and sent to input device\n";

    InputEvent->ie_Class = IECLASS_RAWKEY;

    /* Turn each character into an InputEvent */
    tmp1 = string;

    while (*tmp1)
    {
        /* Convert one character, use default key map */
        i = MapANSI(tmp1, 1, iebuffer, 3, NULL);

        /* Make sure we start without deadkeys */
        InputEvent->ie_Prev1DownCode = InputEvent->ie_Prev1DownQual = 0;
        InputEvent->ie_Prev2DownCode = InputEvent->ie_Prev2DownQual = 0;

        tmp2 = iebuffer;

        switch (i)
        {
          case -2:
            printf("Internal error\n", NULL);
            rc = RETURN_FAIL;
            break;

          case -1:
            printf("Overflow\n", NULL);
            rc = RETURN_FAIL;
            break;

          case 0:
            printf("Can't generate code\n", NULL);
            break;

          case 3:
            InputEvent->ie_Prev2DownCode = *tmp2++;
            InputEvent->ie_Prev2DownQual = *tmp2++;
            /* FALL THROUGH */

          case 2:
            InputEvent->ie_Prev1DownCode = *tmp2++;
            InputEvent->ie_Prev1DownQual = *tmp2++;
            /* FALL THROUGH */

          case 1:
            InputEvent->ie_Code = *tmp2++;
            InputEvent->ie_Qualifier = *tmp2;
            break;
        }

        if (rc == RETURN_OK)
        {
            /* Send the key down event */
            AddIEvents(InputEvent);

            /* Create a key up event */
            InputEvent->ie_Code |= IECODE_UP_PREFIX;

            /* Send the key up event */
            AddIEvents(InputEvent);
         }

        if (rc != RETURN_OK)
            break;

        tmp1++;
    }

    closeall();
    exit(rc);
}

void openall(void)
{
    KeymapBase = OpenLibrary("keymap.library", 37);
    if (KeymapBase == NULL)  closeout("Kickstart 2.0 required", RETURN_FAIL);

    CxBase = OpenLibrary("commodities.library", 37);
    if (CxBase == NULL)  closeout("Kickstart 2.0 required", RETURN_FAIL);

    InputEvent = AllocMem(sizeof(struct InputEvent), MEMF_CLEAR);
    if (InputEvent == NULL)  closeout("Can't allocate input event",RETURN_FAIL);
}

void closeall()
{
    if (InputEvent)    FreeMem(InputEvent, sizeof(struct InputEvent));
    if (CxBase)        CloseLibrary(CxBase);
    if (KeymapBase)    CloseLibrary(KeymapBase);
}

void closeout(UBYTE *errstring, LONG rc)
{
    if(*errstring)     printf("%s\n",errstring);
    closeall();
    exit(rc);
}


Lib_examples/menulayout.c

;/* menulayout.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 menulayout.c
Blink FROM LIB:c.o,menulayout.o TO menulayout LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
** menulayout.c - Example showing how to do menu layout in general.  This example
** also illustrates handling menu events, including IDCMP_MENUHELP events.
**
** Note that handling arbitrary fonts is fairly complex.  Applications that require V37
** should use the simpler menu layout routines found in the GadTools library.
*/
#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <graphics/gfxbase.h>
#include <dos/dos.h>
#include <clib/exec_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif
/* Our function prototypes */
BOOL processMenus(USHORT selection, BOOL done);
BOOL handleIDCMP(struct Window *win);
USHORT MaxLength(struct RastPort *textRPort, struct MenuItem *first_item, USHORT char_size);
VOID setITextAttr(struct IntuiText *first_IText, struct TextAttr *textAttr);
VOID adjustItems(struct RastPort *textRPort, struct MenuItem *first_item, struct TextAttr *textAttr,
                 USHORT char_size, USHORT height, USHORT level, USHORT left_edge);
BOOL adjustMenus(struct Menu *first_menu, struct TextAttr *textAttr);
LONG doWindow(void);

/* Settings Item IntuiText */
struct IntuiText SettText[] = {
        {0,1,JAM2,2,         1, NULL, "Sound...",        NULL },
        {0,1,JAM2,CHECKWIDTH,1, NULL, " Auto Save",      NULL },
        {0,1,JAM2,CHECKWIDTH,1, NULL, " Have Your Cake", NULL },
        {0,1,JAM2,CHECKWIDTH,1, NULL, " Eat It Too",     NULL }
    };

struct MenuItem SettItem[] = {
    { /* "Sound..." */
        &SettItem[1], 0, 0, 0, 0, ITEMTEXT|ITEMENABLED|HIGHCOMP, 0,
        (APTR)&SettText[0], NULL, NULL, NULL, MENUNULL },
        { /* "Auto Save" (toggle-select, initially selected) */
        &SettItem[2], 0, 0, 0, 0, ITEMTEXT|ITEMENABLED|HIGHCOMP|CHECKIT|MENUTOGGLE|CHECKED, 0,
        (APTR)&SettText[1], NULL, NULL, NULL, MENUNULL },
    { /* "Have Your Cake" (initially selected, excludes "Eat It Too") */
        &SettItem[3], 0, 0, 0, 0, ITEMTEXT|ITEMENABLED|HIGHCOMP|CHECKIT|CHECKED, 8,
        (APTR)&SettText[2], NULL, NULL, NULL, MENUNULL },
        { /* "Eat It Too" (excludes "Have Your Cake") */
        NULL, 0, 0, 0, 0, ITEMTEXT|ITEMENABLED|HIGHCOMP|CHECKIT, 4,
        (APTR)&SettText[3], NULL, NULL, NULL, MENUNULL }
    };

/* Edit Menu Item IntuiText */
struct IntuiText EditText[] = {
        {0,1,JAM2,2,1, NULL, "Cut",       NULL },
        {0,1,JAM2,2,1, NULL, "Copy",      NULL },
        {0,1,JAM2,2,1, NULL, "Paste",     NULL },
        {0,1,JAM2,2,1, NULL, "Erase",     NULL },
        {0,1,JAM2,2,1, NULL, "Undo",      NULL }
    };

/* Edit Menu Items */
struct MenuItem EditItem[] = {
        { /* "Cut" (key-equivalent: 'X') */
        &EditItem[1], 0, 0, 0, 0, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0,
        (APTR)&EditText[0], NULL, 'X', NULL, MENUNULL },
        { /* "Copy" (key-equivalent: 'C') */
        &EditItem[2], 0, 0, 0, 0, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0,
        (APTR)&EditText[1], NULL, 'C', NULL, MENUNULL },
        { /* "Paste" (key-equivalent: 'V') */
        &EditItem[3], 0, 0, 0, 0, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0,
        (APTR)&EditText[2], NULL, 'V', NULL, MENUNULL },
        { /* "Erase" (disabled) */
        &EditItem[4], 0, 0, 0, 0, ITEMTEXT|HIGHCOMP, 0,
        (APTR)&EditText[3], NULL, NULL, NULL, MENUNULL },
        { /* "Undo" MenuItem (key-equivalent: 'Z') */
        NULL, 0, 0, 0, 0, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0,
        (APTR)&EditText[4], NULL, 'Z', NULL, MENUNULL }
    };

/* IntuiText for the Print Sub-Items */
struct IntuiText PrtText[] = {
        {0,1, JAM2,2,1, NULL, "NLQ",   NULL },
        {0,1, JAM2,2,1, NULL, "Draft", NULL }
    };

/* Print Sub-Items */
struct MenuItem PrtItem[] = {
        { /* "NLQ" */
        &PrtItem[1], 0, 0, 0, 0, ITEMTEXT|ITEMENABLED|HIGHCOMP, 0,
        (APTR)&PrtText[0], NULL, NULL, NULL, MENUNULL },
        { /* "Draft" */
        NULL, 0, 0, 0, 0, ITEMTEXT|ITEMENABLED|HIGHCOMP, 0,
        (APTR)&PrtText[1], NULL, NULL, NULL, MENUNULL }
    };
/* Uses the >> character to indicate a sub-menu item.
** This is \273 Octal, 0xBB Hex or Alt-0 from the Keyboard.
**
** NOTE that standard menus place this character at the right margin of the menu box.
** This may be done by using a second IntuiText structure for the single character,
** linking this IntuiText to the first one, and positioning the IntuiText so that the
** character appears at the right margin.  GadTools library will provide the correct behavior.
*/

/* Project Menu Item IntuiText */
struct IntuiText ProjText[] = {
        {0,1, JAM2,2,1, NULL, "New",         NULL },
        {0,1, JAM2,2,1, NULL, "Open...",     NULL },
        {0,1, JAM2,2,1, NULL, "Save",        NULL },
        {0,1, JAM2,2,1, NULL, "Save As...",  NULL },
        {0,1, JAM2,2,1, NULL, "Print     \273", NULL },
        {0,1, JAM2,2,1, NULL, "About...",    NULL },
        {0,1, JAM2,2,1, NULL, "Quit",        NULL }
    };

/* Project Menu Items */
struct MenuItem ProjItem[] = {
        { /* "New" (key-equivalent: 'N' */
        &ProjItem[1],0, 0, 0, 0, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0,
        (APTR)&ProjText[0], NULL, 'N', NULL, MENUNULL },
        { /* "Open..." (key-equivalent: 'O') */
        &ProjItem[2],0, 0, 0, 0, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0,
        (APTR)&ProjText[1], NULL, 'O', NULL, MENUNULL },
        { /* "Save" (key-equivalent: 'S') */
        &ProjItem[3],0, 0, 0, 0, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0,
        (APTR)&ProjText[2], NULL, 'S', NULL, MENUNULL },
        { /* "Save As..." (key-equivalent: 'A') */
        &ProjItem[4],0, 0, 0, 0, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0,
        (APTR)&ProjText[3], NULL, 'A', NULL, MENUNULL },
        { /* "Print" (has sub-menu) */
        &ProjItem[5],0, 0, 0, 0, ITEMTEXT|ITEMENABLED|HIGHCOMP, 0,
        (APTR)&ProjText[4], NULL, NULL, &PrtItem[0], MENUNULL },
        { /* "About..." */
        &ProjItem[6],0, 0, 0, 0, ITEMTEXT|ITEMENABLED|HIGHCOMP, 0,
        (APTR)&ProjText[5], NULL, NULL, NULL, MENUNULL },
        { /* "Quit" (key-equivalent: 'Q' */
        NULL, 0, 0, 0, 0, ITEMTEXT|COMMSEQ|ITEMENABLED|HIGHCOMP, 0,
        (APTR)&ProjText[6], NULL, 'Q', NULL, MENUNULL }
    };

/* Menu Titles */
struct Menu Menus[] = {
        {&Menus[1],  0, 0, 63, 0, MENUENABLED, "Project",    &ProjItem[0]},
        {&Menus[2], 70, 0, 39, 0, MENUENABLED, "Edit",       &EditItem[0]},
        {NULL,     120, 0, 88, 0, MENUENABLED, "Settings",   &SettItem[0]},
    };

/* A pointer to the first menu for easy reference */
struct Menu *FirstMenu = &Menus[0];

/* Window Text for Explanation of Program */
struct IntuiText WinText[] = {
        {0, 0, JAM2, 0, 0, NULL, "How to do a Menu", NULL},
        {0, 0, JAM2, 0, 0, NULL, "(with Style)", &WinText[0]}
    };

/* Globals */
struct Library  *IntuitionBase = NULL;
struct Library  *GfxBase = NULL;

/* open all of the required libraries.  Note that we require
** Intuition V37, as the routine uses OpenWindowTags().
*/
VOID main(int argc, char **argv)
{
LONG returnValue;

/* This gets set to RETURN_OK if everything goes well. */
returnValue = RETURN_FAIL;

/* Open the Intuition Library */
IntuitionBase = OpenLibrary("intuition.library", 37);
if (IntuitionBase)
    {
    /* Open the Graphics Library */
    GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 33);
    if (GfxBase)
        {
        returnValue = doWindow();

        CloseLibrary(GfxBase);
        }
    CloseLibrary(IntuitionBase);
    }
exit(returnValue);
}

/* Open a window with some properly positioned text.  Layout and set
** the menus, then process any events received.  Cleanup when done.
*/

LONG doWindow()
{
struct Window *window;
struct Screen *screen;
struct DrawInfo *drawinfo;
ULONG  signalmask, signals;
ULONG  win_width, alt_width, win_height;
LONG   returnValue = RETURN_FAIL;
BOOL   done = FALSE;

if (screen = LockPubScreen(NULL))
    {
    if (drawinfo = GetScreenDrawInfo(screen))
        {
        /* get the colors for the window text */
        WinText[0].FrontPen = WinText[1].FrontPen = drawinfo->dri_Pens[TEXTPEN];
        WinText[0].BackPen  = WinText[1].BackPen  = drawinfo->dri_Pens[BACKGROUNDPEN];

        /* use the screen's font for the text */
        WinText[0].ITextFont = WinText[1].ITextFont = screen->Font;

        /* calculate window size */
        win_width  = 100 + IntuiTextLength(&(WinText[0]));
        alt_width  = 100 + IntuiTextLength(&(WinText[1]));
        if (win_width < alt_width)
            win_width  = alt_width;
        win_height = 1 + screen->WBorTop + screen->WBorBottom +
                     (screen->Font->ta_YSize * 5);

        /* calculate the correct positions for the text in the window */
        WinText[0].LeftEdge = (win_width - IntuiTextLength(&(WinText[0]))) >> 1;
        WinText[0].TopEdge  = 1 + screen->WBorTop + (2 * screen->Font->ta_YSize);
        WinText[1].LeftEdge = (win_width - IntuiTextLength(&(WinText[1]))) >> 1;
        WinText[1].TopEdge  = WinText[0].TopEdge + screen->Font->ta_YSize;

        /* Open the window */
        window = OpenWindowTags(NULL,
            WA_PubScreen, screen,
            WA_IDCMP,     IDCMP_MENUPICK | IDCMP_CLOSEWINDOW | IDCMP_MENUHELP,
            WA_Flags,     WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET |
                              WFLG_ACTIVATE | WFLG_NOCAREREFRESH,
            WA_Left,      10,             WA_Top,       screen->BarHeight + 1,
            WA_Width,     win_width,      WA_Height,    win_height,
            WA_Title,     "Menu Example", WA_MenuHelp,  TRUE,
            TAG_END);

        if (window)
            {
            returnValue = RETURN_OK;  /* program initialized ok */

            /* Give a brief explanation of the program */
            PrintIText(window->RPort,&WinText[1],0,0);

            /* Adjust the menu to conform to the font (TextAttr) */
            adjustMenus(FirstMenu, window->WScreen->Font);

            /* attach the menu to the window */
            SetMenuStrip(window, FirstMenu);

            /* Set up the signals that you want to hear about ... */
            signalmask = 1L << window->UserPort->mp_SigBit;

            /* And wait to hear from your signals */
            while (!done)
                {
                signals = Wait(signalmask);
                if (signals & signalmask) done = handleIDCMP(window);
                };

            /* clean up everything used here */
            ClearMenuStrip(window);
            CloseWindow(window);
            }
        FreeScreenDrawInfo(screen,drawinfo);
        }
    UnlockPubScreen(NULL,screen);
    }
return(returnValue);
}

/* print out what menu was selected.  Properly handle the IDCMP_MENUHELP
** events.  Set done to TRUE if quit is selected.
*/
BOOL processMenus(USHORT selection, BOOL done)
{
USHORT flags;
USHORT menuNum, itemNum, subNum;

menuNum = MENUNUM(selection);
itemNum = ITEMNUM(selection);
subNum  = SUBNUM(selection);

/* when processing IDCMP_MENUHELP, you are not guaranteed
** to get a menu item.
*/
if (itemNum != NOITEM)
    {
    flags = ((struct MenuItem *)ItemAddress(FirstMenu,(LONG)selection))->Flags;
    if (flags & CHECKED)
        printf("(Checked) ");
    }

switch (menuNum)
    {
    case 0:      /* Project Menu */
        switch (itemNum)
            {
            case NOITEM: printf("Project Menu\n");        break;
            case 0:      printf("New\n");                 break;
            case 1:      printf("Open\n");                break;
            case 2:      printf("Save\n");                break;
            case 3:      printf("Save As\n");             break;
            case 4:      printf("Print ");
                switch (subNum)
                    {
                    case NOSUB: printf("Item\n");  break;
                    case 0:     printf("NLQ\n");   break;
                    case 1:     printf("Draft\n"); break;
                    }
                break;
            case 5:      printf("About\n");               break;
            case 6:      printf("Quit\n");   done = TRUE; break;
            }
        break;

    case 1:      /* Edit Menu */
        switch (itemNum) {
            case NOITEM: printf("Edit Menu\n"); break;
            case 0:      printf("Cut\n");       break;
            case 1:      printf("Copy\n");      break;
            case 2:      printf("Paste\n");     break;
            case 3:      printf("Erase\n");     break;
            case 4:      printf("Undo\n");      break;
            }
        break;
    case 2:      /* Settings Menu */
        switch (itemNum) {
            case NOITEM: printf("Settings Menu\n"); break;
            case 0:      printf("Sound\n");            break;
            case 1:      printf("Auto Save\n");        break;
            case 2:      printf("Have Your Cake\n");   break;
            case 3:      printf("Eat It Too\n");       break;
            }
        break;
    case NOMENU: /* No menu selected, can happen with IDCMP_MENUHELP */
        printf("no menu\n");
        break;
    }
return(done);
}

/* Handle the IDCMP messages.  Set done to TRUE if quit or closewindow is selected. */
BOOL handleIDCMP(struct Window *win)
{
BOOL done;
USHORT code, selection;
struct IntuiMessage *message = NULL;
ULONG  class;

done = FALSE;

/* Examine pending messages */
while (message = (struct IntuiMessage *)GetMsg(win->UserPort)) {
    class = message->Class;
    code = message->Code;

    /* When we're through with a message, reply */
    ReplyMsg((struct Message *)message);

    /* See what events occurred */
    switch (class) {
        case IDCMP_CLOSEWINDOW:
            done = TRUE;
            break;
        case IDCMP_MENUHELP:
            /*
        ** The routine that handles the menus for IDCMP_MENUHELP must be very careful
        ** it can receive menu information that is impossible under IDCMP_MENUPICK.
        ** For instance, the code value on a IDCMP_MENUHELP may have a valid number
        ** for the menu, then NOITEM and NOSUB. IDCMP_MENUPICK would get MENUNULL
        ** in this case.  IDCMP_MENUHELP never come as multi-select items, and the
        ** event terminates the menu processing session.
            **
            ** Note that I do not keep the return value from the processMenus() routine here--the
        ** application should not quit if the user selects "help" over the quit menu item.
            */
            printf("IDCMP_MENUHELP: Help on ");
            processMenus(code,done);
            break;
        case IDCMP_MENUPICK:
            for ( selection = code; selection != MENUNULL;
                  selection = (ItemAddress(FirstMenu,(LONG)selection))->NextSelect)
                {
                printf("IDCMP_MENUPICK: Selected ");
                done = processMenus(selection,done);
                }
            break;
        }
    }
return(done);
}
/* Steps thru each item to determine the maximum width of the strip */
USHORT MaxLength(struct RastPort *textRPort, struct MenuItem *first_item, USHORT char_size)
{
USHORT maxLength;
USHORT total_textlen;
struct MenuItem  *cur_item;
struct IntuiText *itext;
USHORT extra_width;
USHORT maxCommCharWidth;
USHORT commCharWidth;

extra_width = char_size;  /* used as padding for each item. */

/* Find the maximum length of a command character, if any.
** If found, it will be added to the extra_width field.
*/
maxCommCharWidth = 0;
for (cur_item = first_item; cur_item != NULL; cur_item = cur_item->NextItem)
    {
    if (cur_item->Flags & COMMSEQ)
        {
        commCharWidth = TextLength(textRPort,&(cur_item->Command),1);
        if (commCharWidth > maxCommCharWidth)
            maxCommCharWidth = commCharWidth;
        }
    }

/* if we found a command sequence, add it to the extra required space.  Add
** space for the Amiga key glyph plus space for the command character.  Note
** this only works for HIRES screens, for LORES, use LOWCOMMWIDTH.
*/
if (maxCommCharWidth > 0)
    extra_width += maxCommCharWidth + COMMWIDTH;

/* Find the maximum length of the menu items, given the extra width calculated above. */
maxLength = 0;
for (cur_item = first_item; cur_item != NULL; cur_item = cur_item->NextItem)
    {
    itext = (struct IntuiText *)cur_item->ItemFill;
    total_textlen = extra_width + itext->LeftEdge +
          TextLength(textRPort, itext->IText, strlen(itext->IText));

    /* returns the greater of the two */
    if (total_textlen > maxLength)
        maxLength = total_textlen;
    }
return(maxLength);
}

/* Set all IntuiText in a chain (they are linked through the NextText ** field) to the same font. */
VOID setITextAttr(struct IntuiText *first_IText, struct TextAttr *textAttr)
{
struct IntuiText *cur_IText;

for (cur_IText = first_IText; cur_IText != NULL; cur_IText = cur_IText->NextText)
    cur_IText->ITextFont = textAttr;
}

/* Adjust the MenuItems and SubItems */
VOID adjustItems(struct RastPort *textRPort, struct MenuItem *first_item,
                 struct TextAttr *textAttr, USHORT char_size, USHORT height,
                 USHORT level, USHORT left_edge)
{
register USHORT item_num;
struct   MenuItem *cur_item;
USHORT   strip_width, subitem_edge;

if (first_item == NULL)
    return;

/* The width of this strip is the maximum length of its members. */
strip_width = MaxLength(textRPort, first_item, char_size);

/* Position the items. */
for (cur_item = first_item, item_num = 0; cur_item != NULL; cur_item = cur_item->NextItem, item_num++)
    {
    cur_item->TopEdge  = (item_num * height) - level;
    cur_item->LeftEdge = left_edge;
    cur_item->Width    = strip_width;
    cur_item->Height   = height;

    /* place the sub_item 3/4 of the way over on the item. */
    subitem_edge = strip_width - (strip_width >> 2);

    setITextAttr((struct IntuiText *)cur_item->ItemFill, textAttr);
    adjustItems(textRPort,cur_item->SubItem,textAttr,char_size,height,1,subitem_edge);
    }
}

/* The following routines adjust an entire menu system to conform to the specified fonts' width and
** height.  Allows for Proportional Fonts. This is necessary for a clean look regardless of what the
** users preference in Fonts may be.  Using these routines, you don't need to specify TopEdge,
** LeftEdge, Width or Height in the MenuItem structures.
**
** NOTE that this routine does not work for menus with images, but assumes that all menu items are
** rendered with IntuiText.
**
** This set of routines does NOT check/correct if the menu runs off
** the screen due to large fonts, too many items, lo-res screen.
*/
BOOL adjustMenus(struct Menu *first_menu, struct TextAttr *textAttr)
{
struct RastPort   textrp = {0};             /* Temporary RastPort */
struct Menu      *cur_menu;
struct TextFont  *font;                     /* Font to use */
USHORT            start, char_size, height;
BOOL              returnValue = FALSE;

/* open the font */
if (font = OpenFont(textAttr))
    {
    SetFont(&textrp, font);       /* Put font into temporary RastPort */

    char_size = TextLength(&textrp, "n", 1);    /* Get the Width of the Font */

    /* To prevent crowding of the Amiga key when using COMMSEQ, don't allow the items to be less
    ** than 8 pixels high.  Also, add an extra pixel for inter-line spacing.
    */
    if (font->tf_YSize > 8)
        height = 1 + font->tf_YSize;
    else
        height = 1 + 8;

    start = 2;      /* Set Starting Pixel */

    /* Step thru the menu structure and adjust it */
    for (cur_menu = first_menu; cur_menu != NULL; cur_menu = cur_menu->NextMenu)
        {
        cur_menu->LeftEdge = start;
        cur_menu->Width = char_size +
            TextLength(&textrp, cur_menu->MenuName, strlen(cur_menu->MenuName));
        adjustItems(&textrp, cur_menu->FirstItem, textAttr, char_size, height, 0, 0);
        start += cur_menu->Width + char_size + char_size;
        }
    CloseFont(font);              /* Close the Font */
    returnValue = TRUE;
    }
return(returnValue);
}


Lib_examples/simplemenu.c

;/* simplemenu.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 simplemenu.c
Blink FROM LIB:c.o,simplemenu.o TO simplemenu LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit

** simplemenu.c: how to use the menu system with a window under all OS versions.
*/
#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <exec/memory.h>
#include <graphics/text.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>

#include <clib/exec_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>

#include <stdio.h>
#include <string.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

/*  These values are based on the ROM font Topaz8. Adjust these  */
/*  values to correctly handle the screen's current font.        */
#define MENWIDTH  (56+8)  /* Longest menu item name * font width */
                          /* + 8 pixels for trim                 */
#define MENHEIGHT (10)    /* Font height + 2 pixels              */

struct Library *GfxBase;
struct Library *IntuitionBase;

/* To keep this example simple, we'll hard-code the font used for menu */
/* items.  Algorithmic layout can be used to handle arbitrary fonts.   */
/* Under Release 2, GadTools provides font-sensitive menu layout.      */
/* Note that we still must handle fonts for the menu headers.          */
struct TextAttr Topaz80 =
{
    "topaz.font", 8, 0, 0
};

struct IntuiText menuIText[] =
{
    { 0, 1, JAM2, 0, 1, &Topaz80, "Open...",  NULL },
    { 0, 1, JAM2, 0, 1, &Topaz80, "Save",     NULL },
    { 0, 1, JAM2, 0, 1, &Topaz80, "Print \273",  NULL },
    { 0, 1, JAM2, 0, 1, &Topaz80, "Draft",    NULL },
    { 0, 1, JAM2, 0, 1, &Topaz80, "NLQ",      NULL },
    { 0, 1, JAM2, 0, 1, &Topaz80, "Quit",     NULL }
};

struct MenuItem submenu1[] =
{
    { /* Draft  */
    &submenu1[1], MENWIDTH-2,  -2 ,            MENWIDTH, MENHEIGHT,
    ITEMTEXT | MENUTOGGLE | ITEMENABLED | HIGHCOMP,
    0, (APTR)&menuIText[3], NULL, NULL, NULL, NULL
    },
    { /* NLQ    */
    NULL,         MENWIDTH-2, MENHEIGHT-2, MENWIDTH, MENHEIGHT,
    ITEMTEXT | MENUTOGGLE | ITEMENABLED | HIGHCOMP,
    0, (APTR)&menuIText[4], NULL, NULL, NULL, NULL
    }
};

struct MenuItem menu1[] =
{
    { /* Open... */
    &menu1[1], 0, 0,            MENWIDTH, MENHEIGHT,
    ITEMTEXT | MENUTOGGLE | ITEMENABLED | HIGHCOMP,
    0, (APTR)&menuIText[0], NULL, NULL, NULL, NULL
    },
    { /* Save    */
    &menu1[2], 0,  MENHEIGHT ,  MENWIDTH, MENHEIGHT,
    ITEMTEXT | MENUTOGGLE | ITEMENABLED | HIGHCOMP,
    0, (APTR)&menuIText[1], NULL, NULL, NULL, NULL
    },
    { /* Print   */
    &menu1[3], 0, 2*MENHEIGHT , MENWIDTH, MENHEIGHT,
    ITEMTEXT | MENUTOGGLE | ITEMENABLED | HIGHCOMP,
    0, (APTR)&menuIText[2], NULL, NULL, &submenu1[0] , NULL
    },
    { /* Quit    */
    NULL, 0, 3*MENHEIGHT , MENWIDTH, MENHEIGHT,
    ITEMTEXT | MENUTOGGLE | ITEMENABLED | HIGHCOMP,
    0, (APTR)&menuIText[5], NULL, NULL, NULL, NULL
    },
};

/* We only use a single menu, but the code is generalizable to */
/* more than one menu.                                         */
#define NUM_MENUS 1

STRPTR menutitle[NUM_MENUS] =  {   "Project"   };

struct Menu menustrip[NUM_MENUS] =
{
    {
    NULL,                    /* Next Menu          */
    0, 0,                    /* LeftEdge, TopEdge, */
    0, MENHEIGHT,            /* Width, Height,     */
    MENUENABLED,             /* Flags              */
    NULL,                    /* Title              */
    &menu1[0]                /* First item         */
    }
};

struct NewWindow mynewWindow =
{
40,40, 300,100, 0,1, IDCMP_CLOSEWINDOW | IDCMP_MENUPICK,
WFLG_DRAGBAR | WFLG_ACTIVATE | WFLG_CLOSEGADGET, NULL,NULL,
"Menu Test Window", NULL,NULL,0,0,0,0,WBENCHSCREEN
};

/* our function prototypes */
VOID handleWindow(struct Window *win, struct Menu *menuStrip);

/*      Main routine.         */
/*                            */
VOID main(int argc, char **argv)
{
struct Window *win=NULL;
UWORD left, m;

/* Open the Graphics Library */
GfxBase = OpenLibrary("graphics.library",33);
if (GfxBase)
    {
    /* Open the Intuition Library */
    IntuitionBase = OpenLibrary("intuition.library", 33);
    if (IntuitionBase)
        {
        if ( win = OpenWindow(&mynewWindow) )
            {
            left = 2;
            for (m = 0; m < NUM_MENUS; m++)
                {
                menustrip[m].LeftEdge = left;
                menustrip[m].MenuName = menutitle[m];
                menustrip[m].Width = TextLength(&win->WScreen->RastPort,
                    menutitle[m], strlen(menutitle[m])) + 8;
                left += menustrip[m].Width;
                }
            if (SetMenuStrip(win, menustrip))
                {
                handleWindow(win, menustrip);
                ClearMenuStrip(win);
                }
            CloseWindow(win);
            }
        CloseLibrary(IntuitionBase);
        }
    CloseLibrary(GfxBase);
    }
}

/*
**   Wait for the user to select the close gadget.
*/
VOID handleWindow(struct Window *win, struct Menu *menuStrip)
{
struct IntuiMessage *msg;
SHORT done;
ULONG class;
UWORD menuNumber;
UWORD menuNum;
UWORD itemNum;
UWORD subNum;
struct MenuItem *item;

done = FALSE;
while (FALSE == done)
    {
    /* we only have one signal bit, so we do not have to check which
    ** bit broke the Wait().
    */
    Wait(1L << win->UserPort->mp_SigBit);

    while ( (FALSE == done) &&
            (msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
        {
        class = msg->Class;
        if(class == IDCMP_MENUPICK)   menuNumber = msg->Code;

        switch (class)
            {
            case IDCMP_CLOSEWINDOW:
                done = TRUE;
                break;
            case IDCMP_MENUPICK:
                while ((menuNumber != MENUNULL) && (!done))
                    {
                    item = ItemAddress(menuStrip, menuNumber);

                    /* process this item
                    ** if there were no sub-items attached to that item,
                    ** SubNumber will equal NOSUB.
                    */
                    menuNum = MENUNUM(menuNumber);
                    itemNum = ITEMNUM(menuNumber);
                    subNum  = SUBNUM(menuNumber);

                    /* Note that we are printing all values, even things
                    ** like NOMENU, NOITEM and NOSUB.  An application should
                    ** check for these cases.
                    */
                    printf("IDCMP_MENUPICK: menu %d, item %d, sub %d\n",
                        menuNum, itemNum, subNum);

                    /* This one is the quit menu selection...
                    ** stop if we get it, and don't process any more.
                    */
                    if ((menuNum == 0) && (itemNum == 4))
                        done = TRUE;

                    menuNumber = item->NextSelect;
                    }
                break;
            }
        ReplyMsg((struct Message *)msg);
        }
    }
}


Lib_examples/showprefs.c

;/* showprefs.c - Execute me to compile me with SAS C 5.10
LC -b0 -d0 -cfis -v -j73 showprefs.c
Blink FROM showprefs.o TO showprefs LIBRARY LIB:Amiga.lib
quit
**
** The following example shows a way to read a Preferences file.
**
** showprefs.c - parse and show some info from an IFF Preferences file
** NOTE: This example requires upcoming 2.1 prefs/ include files.
**
** IMPORTANT!! This example is not linked with startup code (eg. c.o).
** It uses strictly direct AmigaDOS stdio, and also demonstrates
** direct ReadArgs argument parsing.  Therefore it is a CLI-only
** example.  If launched from Workbench, packet errors would occur
** since the WbStartup message is still sitting in the process's
** pr_MsgPort, and the code would never be unloaded from memory.
*/

#include <exec/types.h>
#include <dos/dos.h>
#include <libraries/dos.h>
#include <libraries/iffparse.h>
#include <prefs/prefhdr.h>
#include <prefs/font.h>
#include <prefs/icontrol.h>
#include <prefs/input.h>
#include <prefs/overscan.h>
#include <prefs/printergfx.h>
#include <prefs/printertxt.h>
#include <prefs/screenmode.h>
#include <prefs/serial.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/iffparse_protos.h>

struct ExecBase *SysBase;
struct Library *DOSBase;
struct Library *IFFParseBase;

static UBYTE *IFFErrTxt[] = {
  "EOF",    /* (end of file, not an error) */
  "EOC",     /* (end of context, not an error) */
  "no lexical scope",
  "insufficient memory",
  "stream read error",
  "stream write error",
  "stream seek error",
  "file corrupt",
  "IFF syntax error",
  "not an IFF file",
  "required call-back hook missing",
  NULL,     /* (return to client, never shown) */
};

LONG main(void)
{
  struct RDArgs *readargs = NULL;
  LONG rargs[2];
  struct IFFHandle *iffhandle;
  struct ContextNode *cnode;
  struct StoredProperty *hdrsp;
  struct StoredProperty *sp;
  UBYTE *filename = NULL;
  LONG ifferror, error = 0, rc = RETURN_OK;

  /* We must set up SysBase (we are not linked with startup code) */
  SysBase = (*((struct Library **) 4));

  /* This no-startup-code example may not be used from Workbench */
  if ((((struct Process *)FindTask(NULL))->pr_CLI)==NULL)
        return(RETURN_FAIL);

  if (DOSBase = OpenLibrary("dos.library", 37)) {
    if (IFFParseBase = OpenLibrary ("iffparse.library", 37)) {

      readargs = ReadArgs("FILE/A", rargs, NULL);
      if( (readargs) && (rargs[0]) ) {

        filename = (UBYTE *)rargs[0];

        /* allocate an IFF handle */
        if (iffhandle = AllocIFF()) {
          /* Open the file for reading */
          if (iffhandle->iff_Stream = (LONG)Open(filename, MODE_OLDFILE)) {
            /* initialize the iff handle */
            InitIFFasDOS (iffhandle);
            if ((ifferror = OpenIFF (iffhandle, IFFF_READ)) == 0) {
              PropChunk(iffhandle, ID_PREF, ID_PRHD);

              PropChunk(iffhandle, ID_PREF, ID_FONT);
              PropChunk(iffhandle, ID_PREF, ID_ICTL);
              PropChunk(iffhandle, ID_PREF, ID_INPT);
              PropChunk(iffhandle, ID_PREF, ID_OSCN);
              PropChunk(iffhandle, ID_PREF, ID_PGFX);
              PropChunk(iffhandle, ID_PREF, ID_PTXT);
              PropChunk(iffhandle, ID_PREF, ID_SCRM);
              PropChunk(iffhandle, ID_PREF, ID_SERL);

              for (;;) {
                ifferror = ParseIFF(iffhandle, IFFPARSE_STEP);

                 if (ifferror == IFFERR_EOC)
                   continue;
                else if (ifferror)
                  break;

                /* Do nothing is this is a PrefHeader chunk,
                 * we'll pop it later when there is a pref
                 * chunk.
                 */
                if (cnode = CurrentChunk(iffhandle))
                  if (cnode->cn_ID == ID_PRHD || cnode->cn_ID == ID_FORM)
                    continue;

                /* Get the preferences header, stored previously */
                hdrsp = FindProp(iffhandle, ID_PREF, ID_PRHD);

                if (sp = FindProp(iffhandle, ID_PREF, ID_FONT)) {
                  Printf("FrontPen:  %ld\n",
                        ((struct FontPrefs *)sp->sp_Data)->fp_FrontPen);
                  Printf("BackPen:   %ld\n",
                        ((struct FontPrefs *)sp->sp_Data)->fp_BackPen);
                  Printf("DrawMode:  %ld\n",
                        ((struct FontPrefs *)sp->sp_Data)->fp_DrawMode);
                  Printf("Font:      %s\n",
                        (LONG)((struct FontPrefs *)sp->sp_Data)->fp_Name);
                  Printf("ta_YSize:  %ld\n",
                        ((struct FontPrefs *)sp->sp_Data)->fp_TextAttr.ta_YSize);
                  Printf("ta_Style:  %ld\n",
                        ((struct FontPrefs *)sp->sp_Data)->fp_TextAttr.ta_Style);
                  Printf("ta_Flags:  %ld\n",
                        ((struct FontPrefs *)sp->sp_Data)->fp_TextAttr.ta_Flags);
                } else   if (sp = FindProp(iffhandle, ID_PREF, ID_ICTL)) {
                  Printf("TimeOut:   %ld\n",
                        ((struct IControlPrefs *)sp->sp_Data)->ic_TimeOut);
                  Printf("MetaDrag:  %ld\n",
                        ((struct IControlPrefs *)sp->sp_Data)->ic_MetaDrag);
                  Printf("WBtoFront: %ld\n",
                        ((struct IControlPrefs *)sp->sp_Data)->ic_WBtoFront);
                  Printf("FrontToBack: %ld\n",
                        ((struct IControlPrefs *)sp->sp_Data)->ic_FrontToBack);
                  Printf("ReqTrue:    %ld\n",
                        ((struct IControlPrefs *)sp->sp_Data)->ic_ReqTrue);
                  Printf("ReqFalse:    %ld\n",
                        ((struct IControlPrefs *)sp->sp_Data)->ic_ReqFalse);
                  /* etc */
                } else if (sp = FindProp(iffhandle, ID_PREF, ID_INPT)) {
                  Printf("PointerTicks:      %ld\n",
                        ((struct InputPrefs *)sp->sp_Data)->ip_PointerTicks);
                  Printf("DoubleClick/Secs:  %ld\n",
                        ((struct InputPrefs *)sp->sp_Data)->ip_DoubleClick.tv_secs);
                  Printf("DoubleClick/Micro: %ld\n",
                        ((struct InputPrefs *)sp->sp_Data)->ip_DoubleClick.tv_micro);
                  /* etc */
                } else if (sp = FindProp(iffhandle, ID_PREF, ID_OSCN)) {
                  Printf("DisplayID:  0x%lx\n",
                        ((struct OverscanPrefs *)sp->sp_Data)->os_DisplayID);
                  /* etc */
                } else if (sp = FindProp(iffhandle, ID_PREF, ID_PGFX)) {
                  Printf("Aspect:     %ld\n",
                        ((struct PrinterGfxPrefs *)sp->sp_Data)->pg_Aspect);
                  /* etc */
                } else if (sp = FindProp(iffhandle, ID_PREF, ID_PTXT)) {
                  Printf("Driver:     %s\n",
                        (LONG)((struct PrinterTxtPrefs *)sp->sp_Data)->pt_Driver);
                  /* etc */
                } else if (sp = FindProp(iffhandle, ID_PREF, ID_SCRM)) {
                  Printf("DisplayID:  0x%lx\n",
                        ((struct ScreenModePrefs *)sp->sp_Data)->sm_DisplayID);
                  /* etc */
                } else if (sp = FindProp(iffhandle, ID_PREF, ID_SERL)) {
                  Printf("BaudRate:   %ld\n",
                        ((struct SerialPrefs *)sp->sp_Data)->sp_BaudRate);
                  /* etc */
                }
              }

              CloseIFF(iffhandle);
            }

            if (ifferror != IFFERR_EOF) {
              rargs[1] = (LONG)IFFErrTxt[-ifferror - 1];
              VFPrintf(Output(), "%s: %s\n", rargs);
              rc = RETURN_FAIL;
            }

            Close(iffhandle->iff_Stream);
          } else
            error = IoErr();

          FreeIFF(iffhandle);
        } else {
          VFPrintf(Output(), "Can't allocate IFF handle\n", NULL);
          rc = RETURN_FAIL;
        }
      } else
        error = IoErr();
      CloseLibrary(IFFParseBase);

      SetIoErr(error);
      if (error) {
        rc = RETURN_FAIL;
        PrintFault(error, filename ? filename : "");
      }
    }

    if(readargs) FreeArgs(readargs);
    CloseLibrary(DOSBase);

  } else {
      rc = RETURN_FAIL;
      Write(Output(), "Kickstart 2.0 required\n", 23);
    }

  return(rc);
}


Lib_examples/clonescreen.c

/* clonescreen.c
** clone an existing public screen.
**
** SAS/C 5.10a
** lc -b1 -cfist -v -y clonescreen
** blink FROM LIB:c.o clonescreen.o TO clonescreen LIB LIB:lc.lib LIB:amiga.lib
*/

#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <intuition/screens.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>

#include <string.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

VOID cloneScreen( UBYTE * );

struct Library *IntuitionBase;
struct GfxBase *GfxBase;

/*
** Open all libraries for the cloneScreen() subroutine.
*/
VOID main(int argc, char **argv)
{
UBYTE *pub_screen_name = "Workbench";

IntuitionBase = OpenLibrary("intuition.library",0);
if (IntuitionBase != NULL)
    {
    /* Require version 37 of Intuition. */
    if (IntuitionBase->lib_Version >= 37)
        {
        /* Note the two methods of getting the library version
        ** that you really want.
        */
        GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",37);
        if (GfxBase != NULL)
            {
            cloneScreen(pub_screen_name);

            CloseLibrary((struct Library *)GfxBase);
            }
        }
    CloseLibrary(IntuitionBase);
    }
}

/* Clone a public screen whose name is passed to the routine.
**    Width, Height, Depth, Pens, Font and DisplayID attributes are
** all copied from the screen.
**    Overscan is assumed to be OSCAN_TEXT, as there is no easy way to
** find the overscan type of an existing screen.
**    AutoScroll is turned on, as it does not hurt.  Screens that are
** smaller than the display clip will not scroll.
*/

VOID cloneScreen(UBYTE *pub_screen_name)
{
struct Screen *my_screen;
ULONG  screen_modeID;
UBYTE *pub_scr_font_name;
UBYTE *font_name;
ULONG  font_name_size;
struct TextAttr pub_screen_font;
struct TextFont *opened_font;

struct Screen   *pub_screen = NULL;
struct DrawInfo *screen_drawinfo = NULL;

/* name is a (UBYTE *) pointer to the name of the public screen to clone */
pub_screen = LockPubScreen(pub_screen_name);
if (pub_screen != NULL)
    {
    /* Get the DrawInfo structure from the locked screen
    ** This returns pen, depth and font info.
    */
    screen_drawinfo = GetScreenDrawInfo(pub_screen);
    if (screen_drawinfo != NULL)
        {
        screen_modeID = GetVPModeID(&(pub_screen->ViewPort));
        if( screen_modeID != INVALID_ID )
            {
            /* Get a copy of the font
            ** The name of the font must be copied as the public screen may
            ** go away at any time after we unlock it.
            ** Allocate enough memory to copy the font name, create a
            ** TextAttr that matches the font, and open the font.
            */
            pub_scr_font_name = screen_drawinfo->dri_Font->tf_Message.mn_Node.ln_Name;
            font_name_size = 1 + strlen(pub_scr_font_name);
            font_name = AllocMem(font_name_size, MEMF_CLEAR);
            if (font_name != NULL)
                {
                strcpy(font_name, pub_scr_font_name);
                pub_screen_font.ta_Name  = font_name;
                pub_screen_font.ta_YSize = screen_drawinfo->dri_Font->tf_YSize;
                pub_screen_font.ta_Style = screen_drawinfo->dri_Font->tf_Style;
                pub_screen_font.ta_Flags = screen_drawinfo->dri_Font->tf_Flags;

                opened_font = OpenFont(&pub_screen_font);
                if (opened_font != NULL)
                    {
                    /* screen_modeID may now be used in a call to
                    ** OpenScreenTagList() with the tag SA_DisplayID.
                    */
                    my_screen = OpenScreenTags(NULL,
                        SA_Width,      pub_screen->Width,
                        SA_Height,     pub_screen->Height,
                        SA_Depth,      screen_drawinfo->dri_Depth,
                        SA_Overscan,   OSCAN_TEXT,
                        SA_AutoScroll, TRUE,
                        SA_Pens,       (ULONG)(screen_drawinfo->dri_Pens),
                        SA_Font,       (ULONG)&pub_screen_font,
                        SA_DisplayID,  screen_modeID,
                        SA_Title,      "Cloned Screen",
                        TAG_END);
                    if (my_screen != NULL)
                        {
                        /* Free the drawinfo and public screen as we don't
                        ** need them any more.  We now have our own screen.
                        */
                        FreeScreenDrawInfo(pub_screen,screen_drawinfo);
                        screen_drawinfo = NULL;
                        UnlockPubScreen(pub_screen_name,pub_screen);
                        pub_screen = NULL;

                        Delay(300);   /* should be rest_of_program */

                        CloseScreen(my_screen);
                        }
                    CloseFont(opened_font);
                    }
                FreeMem(font_name, font_name_size);
                }
            }
        }
    }

/* These are freed in the main loop if OpenScreenTagList() does
** not fail.  If something goes wrong, free them here.
*/
if (screen_drawinfo != NULL )
    FreeScreenDrawInfo(pub_screen,screen_drawinfo);
if (pub_screen != NULL )
    UnlockPubScreen(pub_screen_name,pub_screen);
}


Lib_examples/doublebuffer.c

/* doublebuffer.c
** show the use of a double-buffered screen.
**
** SAS/C 5.10a
** lc -b1 -cfist -v -y doublebuffer
** blink FROM LIB:c.o doublebuffer.o TO doublebuffer LIB LIB:lc.lib LIB:amiga.lib
*/

#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <intuition/screens.h>

#include <clib/exec_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

/* characteristics of the screen */
#define SCR_WIDTH  (320)
#define SCR_HEIGHT (200)
#define SCR_DEPTH    (2)

/* Prototypes for our functions */
VOID   runDBuff(struct Screen *, struct BitMap ** );
struct BitMap **setupBitMaps( LONG, LONG, LONG );
VOID   freeBitMaps(struct BitMap **,LONG, LONG, LONG );
LONG   setupPlanes(struct BitMap *, LONG, LONG, LONG );
VOID    freePlanes(struct BitMap *, LONG, LONG, LONG );

struct Library *IntuitionBase = NULL;
struct Library *GfxBase       = NULL;

/*
** Main routine.  Setup for using the double buffered screen.
** Clean up all resources when done or on any error.
*/

VOID main(int argc, char **argv)
{
struct BitMap **myBitMaps;
struct Screen  *screen;
struct NewScreen myNewScreen;

IntuitionBase = OpenLibrary("intuition.library", 33L);
if ( IntuitionBase != NULL )
    {
    GfxBase = OpenLibrary("graphics.library", 33L);
    if ( GfxBase != NULL )
        {
        myBitMaps = setupBitMaps(SCR_DEPTH, SCR_WIDTH, SCR_HEIGHT);
        if ( myBitMaps != NULL )
            {
            /* Open a simple quiet screen that is using the first
            ** of the two bitmaps.
            */
            myNewScreen.LeftEdge=0;
            myNewScreen.TopEdge=0;
            myNewScreen.Width=SCR_WIDTH;
            myNewScreen.Height=SCR_HEIGHT;
            myNewScreen.Depth=SCR_DEPTH;
            myNewScreen.DetailPen=0;
            myNewScreen.BlockPen=1;
            myNewScreen.ViewModes=HIRES;
            myNewScreen.Type=CUSTOMSCREEN | CUSTOMBITMAP | SCREENQUIET;
            myNewScreen.Font=NULL;
            myNewScreen.DefaultTitle=NULL;
            myNewScreen.Gadgets=NULL;
            myNewScreen.CustomBitMap=myBitMaps[0];

            screen = OpenScreen(&myNewScreen);
            if (screen != NULL)
                {
                /* Indicate that the rastport is double buffered. */
                screen->RastPort.Flags = DBUFFER;

                runDBuff(screen, myBitMaps);

                CloseScreen(screen);
                }
            freeBitMaps(myBitMaps, SCR_DEPTH, SCR_WIDTH, SCR_HEIGHT);
            }
        CloseLibrary(GfxBase);
        }
    CloseLibrary(IntuitionBase);
    }
}

/*
** setupBitMaps(): allocate the bit maps for a double buffered screen.
*/
struct BitMap **setupBitMaps(LONG depth, LONG width, LONG height)
{
/* this must be static -- it cannot go away when the routine exits. */
static struct BitMap *myBitMaps[2];

myBitMaps[0] = (struct BitMap *) AllocMem((LONG)sizeof(struct BitMap), MEMF_CLEAR);
if (myBitMaps[0] != NULL)
    {
    myBitMaps[1] = (struct BitMap *)AllocMem((LONG)sizeof(struct BitMap), MEMF_CLEAR);
    if (myBitMaps[1] != NULL)
        {
        InitBitMap(myBitMaps[0], depth, width, height);
        InitBitMap(myBitMaps[1], depth, width, height);

        if (NULL != setupPlanes(myBitMaps[0], depth, width, height))
            {
            if (NULL != setupPlanes(myBitMaps[1], depth, width, height))
                return(myBitMaps);

            freePlanes(myBitMaps[0], depth, width, height);
            }
        FreeMem(myBitMaps[1], (LONG)sizeof(struct BitMap));
        }
    FreeMem(myBitMaps[0], (LONG)sizeof(struct BitMap));
    }
return(NULL);
}

/*
** runDBuff(): loop through a number of iterations of drawing into
** alternate frames of the double-buffered screen.  Note that the
** object is drawn in color 1.
*/
VOID runDBuff(struct Screen *screen, struct BitMap **myBitMaps)
{
WORD ktr, xpos, ypos;
WORD toggleFrame;

toggleFrame = 0;
SetAPen(&(screen->RastPort), 1);

for (ktr = 1; ktr < 200; ktr++)
    {
    /* Calculate a position to place the object, these
    ** calculations insure the object will stay on the screen
    ** given the range of ktr and the size of the object.
    */
    xpos = ktr;
    if ((ktr % 100) >= 50)
        ypos = 50 - (ktr % 50);
    else
        ypos = ktr % 50;

    /* switch the bitmap so that we are drawing into the correct place */
    screen->RastPort.BitMap          = myBitMaps[toggleFrame];
    screen->ViewPort.RasInfo->BitMap = myBitMaps[toggleFrame];

    /* Draw the objects.
    ** Here we clear the old frame and draw a simple filled rectangle.
    */
    SetRast(&(screen->RastPort), 0);
    RectFill(&(screen->RastPort), xpos, ypos, xpos+100, ypos+100);

    /* update the physical display to match the newly drawn bitmap. */
    MakeScreen(screen); /* Tell intuition to do its stuff.          */
    RethinkDisplay();   /* Intuition compatible MrgCop & LoadView   */
                        /*               it also does a WaitTOF().  */

    /* switch the frame number for next time through */
    toggleFrame ^= 1;
    }
}

/*
** freeBitMaps(): free up the memory allocated by setupBitMaps().
*/
VOID freeBitMaps(struct BitMap **myBitMaps, LONG depth, LONG width, LONG height)
{
freePlanes(myBitMaps[0], depth, width, height);
freePlanes(myBitMaps[1], depth, width, height);

FreeMem(myBitMaps[0], (LONG)sizeof(struct BitMap));
FreeMem(myBitMaps[1], (LONG)sizeof(struct BitMap));
}

/*
** setupPlanes(): allocate the bit planes for a screen bit map.
*/
LONG setupPlanes(struct BitMap *bitMap, LONG depth, LONG width, LONG height)
{
SHORT plane_num ;

for (plane_num = 0; plane_num < depth; plane_num++)
    {
    bitMap->Planes[plane_num] = (PLANEPTR)AllocRaster(width, height);
    if (bitMap->Planes[plane_num] != NULL )
        BltClear(bitMap->Planes[plane_num], (width / 8) * height, 1);
    else
        {
        freePlanes(bitMap, depth, width, height);
        return(NULL);
        }
    }
return(TRUE);
}

/*
** freePlanes(): free up the memory allocated by setupPlanes().
*/
VOID freePlanes(struct BitMap *bitMap, LONG depth, LONG width, LONG height)
{
SHORT plane_num ;

for (plane_num = 0; plane_num < depth; plane_num++)
    {
    if (bitMap->Planes[plane_num] != NULL)
        FreeRaster(bitMap->Planes[plane_num], width, height);
    }
}


Lib_examples/dualplayfield.c

/* dualplayfield.c
** Shows how to turn on dual-playfield mode in a screen.
**
** SAS/C 5.10a
** lc -b1 -cfist -v -y dualplayfield
** blink FROM LIB:c.o dualplayfield.o TO dualplayfield LIB LIB:lc.lib LIB:amiga.lib
*/

#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <graphics/displayinfo.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>

VOID doDualPF ( struct Window * );
BOOL installDualPF( struct Screen *, struct RastInfo * );
VOID drawSomething( struct RastPort * );
VOID handleIDCMP ( struct Window * );
VOID removeDualPF( struct Screen *s );

struct Library *IntuitionBase;
struct Library *GfxBase;

VOID main(int argc, char **argv)
{
struct Window *win;
struct Screen *scr;

IntuitionBase = OpenLibrary("intuition.library",37);
if (IntuitionBase != NULL)
    {
    GfxBase = OpenLibrary("graphics.library", 37);
    if (GfxBase != NULL)
        {
        scr = OpenScreenTags(NULL,
                             SA_Depth,     2,
                             SA_DisplayID, HIRES_KEY,
                             SA_Title,     "Dual Playfield Test Screen",
                             TAG_END);
        if ( scr != NULL )
            {
            win = OpenWindowTags(NULL,
                                 WA_Title,        "Dual Playfield Mode",
                                 WA_IDCMP,        IDCMP_CLOSEWINDOW,
                                 WA_Width,        200,
                                 WA_Height,       100,
                                 WA_DragBar,      TRUE,
                                 WA_CloseGadget,  TRUE,
                                 WA_CustomScreen, scr,
                                 TAG_END);
            if ( win != NULL )
                {
                doDualPF(win);

                CloseWindow(win);
                }
            CloseScreen(scr);
            }
        CloseLibrary(GfxBase);
        }
    CloseLibrary(IntuitionBase);
    }
}

/*
** Allocate all of the stuff required to add dual playfield to a screen.
*/
VOID doDualPF(struct Window *win)
{
struct Screen   *myscreen;
struct RasInfo  *rinfo2;
struct BitMap   *bmap2;
struct RastPort *rport2;

myscreen = win->WScreen;   /* Find the window's screen */

/* Allocate the second playfield's rasinfo, bitmap, and bitplane */
rinfo2 = (struct RasInfo *) AllocMem(sizeof(struct RasInfo), MEMF_PUBLIC | MEMF_CLEAR);
if ( rinfo2 != NULL )
    {
    /* Get a rastport, and set it up for rendering into bmap2 */
    rport2 = (struct RastPort *) AllocMem(sizeof(struct RastPort), MEMF_PUBLIC );
    if (rport2 != NULL )
        {
        bmap2 = (struct BitMap *) AllocMem(sizeof(struct BitMap), MEMF_PUBLIC | MEMF_CLEAR);
        if (bmap2 != NULL )
            {
            InitBitMap(bmap2, 1, myscreen->Width, myscreen->Height);

            /* extra playfield will only use one bitplane here. */
            bmap2->Planes[0] = (PLANEPTR) AllocRaster(myscreen->Width, myscreen->Height);
            if (bmap2->Planes[0] != NULL )
                {
                InitRastPort(rport2);
                rport2->BitMap = rinfo2->BitMap = bmap2;

                SetRast(rport2, 0);

                if (installDualPF(myscreen,rinfo2))
                    {
                    /* Set foreground color; color 9 is color 1 for
                    ** second playfield of hi-res viewport
                    */
                    SetRGB4(&myscreen->ViewPort, 9, 0, 0xF, 0);

                    drawSomething(rport2);

                    handleIDCMP(win);

                    removeDualPF(myscreen);
                    }
                FreeRaster(bmap2->Planes[0], myscreen->Width, myscreen->Height);
                }
            FreeMem(bmap2, sizeof(struct BitMap));
            }
        FreeMem(rport2, sizeof(struct RastPort));
        }
    FreeMem(rinfo2, sizeof(struct RasInfo));
    }
}

/*
** Manhandle the viewport:
** install second playfield and change modes
*/
BOOL installDualPF(struct Screen *scrn, struct RastInfo *rinfo2)
{
ULONG screen_modeID;
BOOL return_code = FALSE;

screen_modeID = GetVPModeID(&(scrn->ViewPort));
if( screen_modeID != INVALID_ID )
    {
    /* you can only play with the bits in the Modes field
    ** if the upper half of the screen mode ID is zero!!!
    */
    if ( (screen_modeID & 0xFFFF0000L) == 0L )
        {
        return_code = TRUE;

        Forbid();

        /* Install rinfo for viewport's second playfield */
        scrn->ViewPort.RasInfo->Next = rinfo2;
        scrn->ViewPort.Modes |= DUALPF;

        Permit();

        /* Put viewport change into effect */
        MakeScreen(scrn);
        RethinkDisplay();
        }
    }
return(return_code);
}

/*
** Draw some lines in a rast port...This is used to get some data into
** the second playfield.  The windows on the screen will move underneath
** these graphics without disturbing them.
*/
VOID drawSomething(struct RastPort *rp)
{
int width, height;
int r, c;

width = rp->BitMap->BytesPerRow * 8;
height = rp->BitMap->Rows;

SetAPen(rp, 1);

for (r = 0; r < height; r += 40)
    {
    for (c = 0; c < width; c += 40)
        {
        Move(rp, 0L, r);
        Draw(rp, c, 0L);
        }
    }
}

/*
** simple event loop to wait for the user to hit the close gadget
** on the window.
*/
VOID handleIDCMP(struct Window *win)
{
BOOL done = FALSE;
struct IntuiMessage *message = NULL;
ULONG class;
ULONG signals;

while (!done)
    {
    signals = Wait(1L << win->UserPort->mp_SigBit);
    if (signals & (1L << win->UserPort->mp_SigBit))
        {
        while ((!done) &&
               (message = (struct IntuiMessage *)GetMsg(win->UserPort)))
            {
            class = message->Class;
            ReplyMsg((struct Message *)message);

            switch (class)
                {
                case IDCMP_CLOSEWINDOW:
                    done = TRUE;
                    break;
                }
            }
        }
    }
}

/*
** remove the effects of installDualPF().
** only call if installDualPF() succeeded.
*/
VOID removeDualPF(struct Screen *scrn)
{
Forbid();

scrn->ViewPort.RasInfo->Next = NULL;
scrn->ViewPort.Modes &= ~DUALPF;

Permit();

MakeScreen(scrn);
RethinkDisplay();
}


Lib_examples/pubscreenbeep.c

;/* pubscreenbeep.c - Execute me to compile me with SAS 5.10
LC -b1 -cfistq -v -y -j73 pubscreenbeep.c
blink LIB:c.o pubscreenbeep.o TO pubscreenbeep LIB LIB:lc.lib LIB:amiga.lib
quit
*/

#include <exec/types.h>               /* Amiga data types.               */
#include <exec/libraries.h>
#include <intuition/intuition.h>      /* Lots of important Intuition     */
#include <intuition/screens.h>        /* structures we will be using.    */

#include <clib/exec_protos.h>         /* Function prototypes             */
#include <clib/intuition_protos.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }     /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }     /* really */
#endif

struct Library *IntuitionBase;        /* Intuition library base           */

/* Simple example of how to find a public screen to work with in Release 2.
 */

VOID main(int argc, char **argv)
{
struct Screen  *my_wbscreen_ptr;     /* Pointer to the Workbench screen */

/* Open the library before you call any functions */
IntuitionBase = OpenLibrary("intuition.library",0);
if (NULL != IntuitionBase)
   {
   if(IntuitionBase->lib_Version>=36)
      {
      /* OK, we have the right version of the OS so we can use
      ** the new public screen functions of Release 2 (V36)
      */
      if(NULL!=(my_wbscreen_ptr=LockPubScreen("Workbench")))
          {
          /* OK found the Workbench screen.                      */
          /* Normally the program would be here.  A window could */
          /* be opened or the attributes of the screen copied    */
          DisplayBeep(my_wbscreen_ptr);

          UnlockPubScreen(NULL,my_wbscreen_ptr);
          }
      }
   else
      {
      /* Prior to Release 2 (V36), there were no public screens,     */
      /* just Workbench.  In those older systems, windows can be     */
      /* opened on Workbench without locking or a pointer by setting */
      /* the Type=WBENCHSCREEN in struct NewWindow.  Attributes can  */
      /* be obtained by setting the Type argument to WBENCHSCREEN in */
      /* the call to GetScreenData().                                */
      }
   CloseLibrary(IntuitionBase);
   }
}


Lib_examples/publicscreen.c

/* publicscreen.c
** open a screen with the pens from a public screen.
**
** SAS/C 5.10a
** lc -b1 -cfist -v -y publicscreen
** blink FROM LIB:c.o publicscreen.o TO publicscreen LIB LIB:lc.lib LIB:amiga.lib
*/
#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/screens.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

VOID usePubScreenPens(void);

struct Library *IntuitionBase;

/* main(): open libraries, clean up when done.
*/
VOID main(int argc, char **argv)
{
IntuitionBase = OpenLibrary("intuition.library",0);
if ( IntuitionBase != NULL )
    {
    /* Check the version number; Release 2 is */
    /* required for public screen functions   */
    if (IntuitionBase->lib_Version >= 37)
        {
        usePubScreenPens();
        }
    CloseLibrary(IntuitionBase);
    }
}

/* Open a screen that uses the pens of an existing public screen
** (the Workbench screen in this case).
*/
VOID usePubScreenPens(void)
{
struct Screen *my_screen;
struct TagItem screen_tags[2];
UBYTE *pubScreenName = "Workbench";

struct Screen *pub_screen = NULL;
struct DrawInfo *screen_drawinfo = NULL;

/* Get a lock on the Workbench screen */
pub_screen = LockPubScreen(pubScreenName);
if ( pub_screen != NULL )
    {
    /* get the DrawInfo structure from the locked screen */
    screen_drawinfo = GetScreenDrawInfo(pub_screen);
    if ( screen_drawinfo != NULL)
        {
        /* the pens are copied in the OpenScreenTagList() call,
        ** so we can simply use a pointer to the pens in the tag list.
        **
        ** This works better if the depth and colors of the new screen
        ** matches that of the public screen.  Here we are forcing the
        ** workbench screen pens on a monochrome screen (which may not
        ** be a good idea).  You could add the tag:
        **      (SA_Depth, screen_drawinfo->dri_Depth)
        */
        screen_tags[0].ti_Tag  = SA_Pens;
        screen_tags[0].ti_Data = (ULONG)(screen_drawinfo->dri_Pens);
        screen_tags[0].ti_Tag  = TAG_END;
        screen_tags[0].ti_Data = NULL;

        my_screen = OpenScreenTagList(NULL, screen_tags);
        if (my_screen != NULL)
            {
            /* We no longer need to hold the lock on the public screen
            ** or a copy of its DrawInfo structure as we now have our
            ** own screen.  Release the screen.
            */
            FreeScreenDrawInfo(pub_screen,screen_drawinfo);
            screen_drawinfo = NULL;
            UnlockPubScreen(pubScreenName,pub_screen);
            pub_screen = NULL;

            Delay(90);   /* should be rest_of_program */

            CloseScreen(my_screen);
            }
        }
    }

/* These are freed in the main loop if OpenScreenTagList() does
** not fail.  If something goes wrong, free them here.
*/
if ( screen_drawinfo != NULL )
    FreeScreenDrawInfo(pub_screen,screen_drawinfo);
if ( pub_screen!= NULL )
    UnlockPubScreen(pubScreenName,pub_screen);
}


Lib_examples/AvailFonts.c

;/* AvailFonts.c - Execute me to compile me with Lattice 5.10a
LC -cfistq -v -y -j73 AvailFonts.c
Blink FROM LIB:c.o,AvailFonts.o TO AvailFonts LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit ;*/

#include <exec/types.h>
#include <dos/rdargs.h>
#include <dos/dosextens.h>
#include <intuition/intuition.h>
#include <intuition/screens.h>
#include <graphics/text.h>
#include <graphics/displayinfo.h>
#include <graphics/regions.h>
#include <graphics/gfx.h>
#include <libraries/diskfont.h>
#include <utility/tagitem.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/layers_protos.h>
#include <clib/alib_stdio_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/diskfont_protos.h>
#include <clib/utility_protos.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }
#endif

UBYTE *vers = "\0$VER: AvailFonts 36.3";

void MainLoop(void);
ULONG StrLen(UBYTE *);

struct stringstruct {
        UBYTE *string;
        LONG charcount;
        WORD stringwidth;
};

UBYTE *alphabetstring = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
struct stringstruct fname, fheight, XDPI, YDPI, entrynum;
struct Library *DiskfontBase, *IntuitionBase, *LayersBase, *GfxBase, *UtilityBase;
struct Window *mywin;
struct RastPort *mycliprp, myrp;
struct Rectangle myrect;
struct Region *new_region, *old_region;
struct DrawInfo *mydrawinfo;
struct AvailFontsHeader *afh;
LONG fontheight, alphabetcharcount;
WORD stringwidth;

void main(int argc, char **argv)
{
  struct TextFont *defaultfont = NULL;
  struct TextAttr defaultfontattr = { "topaz.font", 9, 0, 0 };

  LONG afsize, afshortage, cliprectside;

  fname.string = "Font Name:  ";
  fheight.string = "Font Height:  ";
  XDPI.string = "X DPI:  ";
  YDPI.string = "Y DPI:  ";
  entrynum.string = "Entry #:  ";

  if (DiskfontBase = OpenLibrary("diskfont.library", 37L))              /* Open the libraries. */
  {
    if (IntuitionBase = OpenLibrary("intuition.library", 37L))
    {
      if (GfxBase = OpenLibrary("graphics.library", 37L))
      {
        if (LayersBase = OpenLibrary("layers.library", 37L))
        {
          if (UtilityBase = OpenLibrary("utility.library", 37L))
          {
            if (mywin = OpenWindowTags(NULL,                              /* Open that window. */
                                    WA_SmartRefresh,TRUE,
                                    WA_SizeGadget,  FALSE,
                                    WA_CloseGadget, TRUE,
                                    WA_IDCMP,       IDCMP_CLOSEWINDOW,
                                    WA_DragBar,     TRUE,
                                    WA_DepthGadget, TRUE,
                                    WA_Title,       (ULONG)"AvailFonts() example",
                                    TAG_END))
            {
              myrp = *(mywin->RPort);       /* A structure assign: clone my window's Rastport. */
                                            /* RastPort.  This RastPort will be used to render */
                                            /* the font specs, not the actual font sample.     */
              if (mydrawinfo = GetScreenDrawInfo(mywin->WScreen))
              {
                SetFont(&myrp, mydrawinfo->dri_Font);

                myrect.MinX = mywin->BorderLeft;                          /* LAYOUT THE WINDOW */
                myrect.MinY = mywin->BorderTop;
                myrect.MaxX = mywin->Width - (mywin->BorderRight + 1);
                myrect.MaxY = mywin->Height - (mywin->BorderBottom + 1);

                cliprectside = (myrect.MaxX - myrect.MinX) / 20;

                fname.charcount    = StrLen(fname.string);
                fheight.charcount  = StrLen(fheight.string);
                XDPI.charcount     = StrLen(XDPI.string);
                YDPI.charcount     = StrLen(YDPI.string);
                entrynum.charcount = StrLen(entrynum.string);
                alphabetcharcount  = StrLen(alphabetstring);

                fontheight = (myrp.Font->tf_YSize) + 2;

                if (fontheight > ((myrect.MaxY - myrect.MinY) / 6))  /* If the default screen  */
                {                                                    /* font is more than one- */
                  defaultfont = OpenFont(&defaultfontattr);          /* sixth the size of the  */
                  SetFont(&myrp, defaultfont);                       /* window, use topaz-9.   */
                  fontheight = (myrp.Font->tf_YSize) + 2;
                }

                fname.stringwidth   = TextLength(&myrp, (STRPTR)fname.string, fname.charcount);
                fheight.stringwidth = TextLength(&myrp, (STRPTR)fheight.string, fheight.charcount);
                XDPI.stringwidth    = TextLength(&myrp, (STRPTR)XDPI.string, XDPI.charcount);
                YDPI.stringwidth    = TextLength(&myrp, (STRPTR)YDPI.string, YDPI.charcount);
                entrynum.stringwidth =
                    TextLength(&myrp, (STRPTR)entrynum.string, entrynum.charcount);

                stringwidth = fname.stringwidth;         /* What is the largest string length? */
                stringwidth =
                    (fheight.stringwidth > stringwidth) ? fheight.stringwidth : stringwidth;
                stringwidth = (XDPI.stringwidth > stringwidth) ? XDPI.stringwidth : stringwidth;
                stringwidth = (YDPI.stringwidth > stringwidth) ? YDPI.stringwidth : stringwidth;
                stringwidth =
                    (entrynum.stringwidth > stringwidth) ? entrynum.stringwidth : stringwidth;
                stringwidth += mywin->BorderLeft;

                if (stringwidth < ((myrect.MaxX - myrect.MinX) >> 1)) /* If the stringwidth is */
                {                                                 /* more than half the viewing*/
                  SetAPen(&myrp, mydrawinfo->dri_Pens[TEXTPEN]);  /* area, quit because the    */
                  SetDrMd(&myrp, JAM2);                           /* font is just too big.     */

                  Move(&myrp, myrect.MinX + 8 + stringwidth - fname.stringwidth,
                               myrect.MinY + 4 + (myrp.Font->tf_Baseline));
                  Text(&myrp, fname.string, fname.charcount);

                  Move(&myrp, myrect.MinX + 8 + stringwidth - fheight.stringwidth,
                              myrp.cp_y + fontheight);
                  Text(&myrp, fheight.string, fheight.charcount);

                  Move(&myrp, myrect.MinX + 8 + stringwidth - XDPI.stringwidth,
                              myrp.cp_y + fontheight);
                  Text(&myrp, XDPI.string, XDPI.charcount);

                  Move(&myrp, myrect.MinX + 8 + stringwidth - YDPI.stringwidth,
                              myrp.cp_y + fontheight);
                  Text(&myrp, YDPI.string, YDPI.charcount);

                  Move(&myrp, myrect.MinX + 8 + stringwidth - entrynum.stringwidth,
                              myrp.cp_y + fontheight);
                  Text(&myrp, entrynum.string, entrynum.charcount);

                  myrect.MinX = myrect.MinX + cliprectside;
                  myrect.MaxX = myrect.MaxX - cliprectside;
                  myrect.MinY = myrect.MinY + (5 * fontheight) + 8;
                  myrect.MaxY = myrect.MaxY - 8;

                  SetAPen(&myrp, mydrawinfo->dri_Pens[SHINEPEN]);         /* Draw a box around */
                  Move(&myrp, myrect.MinX - 1, myrect.MaxY + 1);          /* the cliprect.     */
                  Draw(&myrp, myrect.MaxX + 1, myrect.MaxY + 1);
                  Draw(&myrp, myrect.MaxX + 1, myrect.MinY - 1);

                  SetAPen(&myrp, mydrawinfo->dri_Pens[SHADOWPEN]);
                  Draw(&myrp, myrect.MinX - 1, myrect.MinY - 1);
                  Draw(&myrp, myrect.MinX - 1, myrect.MaxY);

                  SetAPen(&myrp, mydrawinfo->dri_Pens[TEXTPEN]);
                                          /* Fill up a buffer with a list of the available fonts */
                  afsize = AvailFonts((STRPTR)afh, 0L, AFF_MEMORY|AFF_DISK|AFF_SCALED|AFF_TAGGED);
                  do
                  {
                    afh = (struct AvailFontsHeader *) AllocMem(afsize, 0);
                    if (afh)
                    {
                      afshortage = AvailFonts((STRPTR)afh, afsize,
                                              AFF_MEMORY|AFF_DISK|AFF_SCALED|AFF_TAGGED);
                      if (afshortage)
                      {
                        FreeMem(afh, afsize);
                        afsize += afshortage;
                        afh = (struct AvailFontsHeader *)(-1L);
                      }
                    }
                  } while (afshortage && afh);

                  if (afh)
                  {
                    /* This is for the layers.library clipping region that gets attached to */
                    /* the window.  This prevents the application from unnecessarily        */
                    /* rendering beyond the bounds of the inner part of the window. For     */
                    /* more information on clipping, see the Layers chapter of this manual. */

                    if (new_region = NewRegion())                 /* More layers stuff */
                    {
                      if (OrRectRegion(new_region, &myrect));/* Even more layers stuff */
                      {
                         /* Obtain a pointer to the window's rastport and set up some of    */
                         /* the rastport attributes.  This example obtains the text pen     */
                         /* for the window's screen using the GetScreenDrawInfo() function. */
                         mycliprp = mywin->RPort;
                         SetAPen(mycliprp, mydrawinfo->dri_Pens[TEXTPEN]);

                         MainLoop();
                      }
                      DisposeRegion(new_region);
                    }
                    FreeMem(afh, afsize);
                  }
                }
                FreeScreenDrawInfo(mywin->WScreen, mydrawinfo);
              }
              CloseWindow(mywin);
            }
            CloseLibrary(UtilityBase);
          }
          CloseLibrary(LayersBase);
        }
        CloseLibrary(GfxBase);
      }
      CloseLibrary(IntuitionBase);
    }
    CloseLibrary(DiskfontBase);
  }
}

void MainLoop(void)
{
  UWORD x;
  struct Task *mytask;
  struct IntuiMessage *mymsg;
  BOOL aok = TRUE;
  struct TAvailFonts *afont;
  struct TextFont *myfont;
  UBYTE buf[8];
  ULONG dpi;

  mytask = FindTask(NULL);
  afont = (struct TAvailFonts *)&(afh[1]);

  for (x = 0; (x < afh->afh_NumEntries); x++)
  {
    if (aok)
    {
      if (myfont = OpenDiskFont(&(afont->taf_Attr)))
      {
        SetAPen(&myrp, mydrawinfo->dri_Pens[BACKGROUNDPEN]);   /* Print the TextFont attributes. */
        RectFill( &myrp, stringwidth, mywin->BorderTop + 4,
                  mywin->Width - (mywin->BorderRight + 1), myrect.MinY - 2 );

        SetAPen(&myrp, mydrawinfo->dri_Pens[TEXTPEN]);
        Move( &myrp, stringwidth + mywin->BorderLeft,
              mywin->BorderTop + 4 + (myrp.Font->tf_Baseline) );
        Text( &myrp, (UBYTE *)myfont->tf_Message.mn_Node.ln_Name,
              StrLen((UBYTE *)myfont->tf_Message.mn_Node.ln_Name) );

        Move(&myrp, stringwidth + mywin->BorderLeft, myrp.cp_y + fontheight); /* Print the      */
        sprintf(buf, "%d\0", myfont->tf_YSize);                               /* font's Y Size. */
        Text(&myrp, buf, StrLen(buf));

        Move(&myrp, stringwidth + mywin->BorderLeft, myrp.cp_y + fontheight); /* Print the X DPI */
        dpi = GetTagData( TA_DeviceDPI, 0L,
                          ((struct TextFontExtension *)(myfont->tf_Extension))->tfe_Tags);
        if (dpi)
        {
            sprintf(buf, "%d\0", ((dpi & 0xFFFF0000)>>16));
            Text(&myrp, buf, StrLen(buf));
        }
        else Text(&myrp, "nil", 3L);

        Move(&myrp, stringwidth + mywin->BorderLeft, myrp.cp_y + fontheight); /* Print the Y DPI */
        if (dpi)
        {
            sprintf(buf, "%d\0", (dpi & 0x0000FFFF));
            Text(&myrp, buf, StrLen(buf));
        }
        else Text(&myrp, "nil", 3L);

        Move(&myrp, stringwidth + mywin->BorderLeft, myrp.cp_y + fontheight);     /* Print the */
        sprintf(buf, "%d\0", x);                                                   /* entrynum. */
        Text(&myrp, buf, StrLen(buf));

        SetFont(mycliprp, myfont);
        old_region = InstallClipRegion(mywin->WLayer, new_region); /* Install clipping rectangle */

        SetRast(mycliprp, mydrawinfo->dri_Pens[BACKGROUNDPEN]);
        Move( mycliprp, myrect.MinX, myrect.MaxY - (myfont->tf_YSize - myfont->tf_Baseline) );
        Text(mycliprp, alphabetstring, alphabetcharcount);

        Delay(100);

        new_region = InstallClipRegion(mywin->WLayer, old_region);  /* Remove clipping rectangle */

        while (mymsg = (struct IntuiMessage *)GetMsg(mywin->UserPort))
        {
            aok = FALSE;
            x = afh->afh_NumEntries;
            ReplyMsg((struct Message *)mymsg);
        }

        if (mytask->tc_SigRecvd & SIGBREAKF_CTRL_C)        /* Did the user hit CTRL-C (the shell */
        {                                                  /* window has to receive the CTRL-C)? */
            aok = FALSE;
            x = afh->afh_NumEntries;
            VPrintf("Ctrl-C Break\n", NULL);
        }
        CloseFont(myfont);
      }
    }
    afont++;
  }
}

ULONG StrLen(UBYTE *string)
{
    ULONG x = 0L;

    while (string[x++]);
    return(--x);
}


Lib_examples/MeasureText.c

;/* MeasureText.c - Execute me to compile me with Lattice 5.10a
LC -b0 -cfistq -v -y -j73 MeasureText.c
Blink FROM LIB:c.o, MeasureText.o TO MeasureText LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit ;
**
** The following example, measuretext.c, opens a window on the default
** public screen and renders the contents of an ASCII file into the
** window.  It uses TextFit() to measure how much of a line of text will
** fit across the window.  If the entire line doesn't fit, measuretext
** will wrap the remainder of the line into the rows that follow.  This
** example makes use of an ASL font requester, letting the user choose
** the font, style, size, drawing mode, and color.
*/
#define INTUITION_IOBSOLETE_H
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <graphics/text.h>
#include <graphics/rastport.h>
#include <intuition/intuition.h>
#include <exec/libraries.h>

#include <clib/alib_stdio_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
#include <clib/diskfont_protos.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/asl_protos.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }
#endif

#define BUFSIZE 32768

UBYTE *vers = "\0$VER: MeasureText 37.1";

UBYTE buffer[BUFSIZE];

void MainLoop(void);
void EOP(void);

struct Library *IntuitionBase, *GfxBase, *DiskfontBase, *AslBase;
BPTR myfile;
UWORD wtbarheight;
struct FontRequester *fr;
struct TextFont *myfont;
struct Window *w;
struct RastPort *myrp;
struct Task *mytask;

void main(int argc, char **argv)
{
  struct TextAttr myta;

  if (argc == 2)
  {
    if (myfile = Open(argv[1], MODE_OLDFILE))                 /* Open the file to print out. */
    {
      if (DiskfontBase = OpenLibrary("diskfont.library", 37L))        /* Open the libraries. */
      {
        if (IntuitionBase = OpenLibrary("intuition.library", 37L))
        {
          if (GfxBase = OpenLibrary("graphics.library", 37L))
          {
            if (AslBase = OpenLibrary("asl.library", 37L))
            {
              if (fr = (struct FontRequester *)                /* Open an ASL font requester */
                       AllocAslRequestTags(ASL_FontRequest,
                                    /* Supply initial values for requester */
                                    ASL_FontName, (ULONG)"topaz.font",
                                    ASL_FontHeight, 11L,
                                    ASL_FontStyles, FSF_BOLD | FSF_ITALIC,
                                    ASL_FrontPen,  0x01L,
                                    ASL_BackPen,   0x00L,

                                     /* Give us all the gadgetry */
                                    ASL_FuncFlags, FONF_FRONTCOLOR | FONF_BACKCOLOR |
                                                   FONF_DRAWMODE | FONF_STYLES,
                                    TAG_DONE))

              {
                /* Pop up the requester */
                if (AslRequest(fr, 0L))
                {
                  myta.ta_Name       = fr->fo_Attr.ta_Name;         /* extract the font and */
                  myta.ta_YSize      = fr->fo_Attr.ta_YSize;        /* display attributes   */
                  myta.ta_Style      = fr->fo_Attr.ta_Style;        /* from the FontRequest */
                  myta.ta_Flags      = fr->fo_Attr.ta_Flags;        /* structure.           */

                  if (myfont = OpenDiskFont(&myta))
                  {
                    if (w = OpenWindowTags(NULL,WA_SizeGadget,  TRUE,
                                                WA_MinWidth,    200,
                                                WA_MinHeight,   200,
                                                WA_DragBar,     TRUE,
                                                WA_DepthGadget, TRUE,
                                                WA_Title,       (ULONG)argv[1],
                                                TAG_DONE))
                    {
                      myrp = w->RPort;
                      /* figure out where the baseline of the uppermost line should be. */
                      wtbarheight = w->WScreen->BarHeight + myfont->tf_Baseline + 2;

                      /* Set the font and add software styling to the text if I asked for it */
                      /* in OpenFont() and didn't get it.  Because most Amiga fonts do not   */
                      /* have styling built into them (with the exception of the CG outline  */
                      /* fonts), if the user selected some kind of styling for the text, it  */
                      /* will to be added algorithmically by calling SetSoftStyle().         */

                      SetFont(myrp, myfont);
                      SetSoftStyle(myrp,   myta.ta_Style ^ myfont->tf_Style,
                                    (FSF_BOLD | FSF_UNDERLINED | FSF_ITALIC));
                      SetDrMd(myrp, fr->fo_DrawMode);
                      SetAPen(myrp, fr->fo_FrontPen);
                      SetBPen(myrp, fr->fo_BackPen);
                      Move(myrp, w->WScreen->WBorLeft, wtbarheight);
                      mytask = FindTask(NULL);

                      MainLoop();

                      Delay(25);                    /* short delay to give user a chance to */
                      CloseWindow(w);               /* see the text before it goes away.    */
                    }
                    CloseFont(myfont);
                  }
                }
                else
                  VPrintf("Request Cancelled\n", NULL);
                FreeAslRequest(fr);
              }
              CloseLibrary(AslBase);
            }
            CloseLibrary(GfxBase);
          }
          CloseLibrary(IntuitionBase);
        }
        CloseLibrary(DiskfontBase);
      }
      Close(myfile);
    }
  }
  else
    VPrintf("template: MeasureText <file name>\n", NULL);
}

void MainLoop(void)
{
  struct TextExtent resulttextent;
  LONG fit, actual, count, printable, crrts;
  BOOL aok = TRUE;

  while (((actual = Read(myfile, buffer, BUFSIZE)) > 0) && aok)  /* while there's something to */
  {                                                              /* read, fill the buffer.     */
    count = 0;

    while(count < actual)
    {
      crrts = 0;

      while ( ((buffer[count] < myfont->tf_LoChar) ||    /* skip non-printable characters, but */
               (buffer[count] > myfont->tf_HiChar)) &&   /* account for newline characters.    */
               (count < actual) )
      {
        if (buffer[count] == '\012') crrts++; /* is this character a newline?  if it is, bump */
        count++;                               /* up the newline count.                        */
      }

      if (crrts > 0)                  /* if there where any newlines, be sure to display them. */
      {
        Move(myrp, w->BorderLeft, myrp->cp_y + (crrts * (myfont->tf_YSize + 1)));
        EOP();                                          /* did we go past the end of the page? */
      }

      printable = count;
      while ( (buffer[printable] >= myfont->tf_LoChar) &&      /* find the next non-printables */
              (buffer[printable] <= myfont->tf_HiChar) &&
              (printable < actual) )
      {
        printable++;
      }                                  /* print the string of printable characters wrapping  */
      while (count < printable)          /* lines to the beginning of the next line as needed. */
      {
        /* how many characters in the current string of printable characters will fit */
        /* between the rastport's current X position and the edge of the window?      */
        fit = TextFit(  myrp,                &(buffer[count]),
                        (printable - count), &resulttextent,
                        NULL,                1,
                        (w->Width  - (myrp->cp_x + w->BorderLeft + w->BorderRight)),
                        myfont->tf_YSize + 1  );
        if ( fit == 0 )
        {
            /* nothing else fits on this line, need to wrap to the next line.         */
            Move(myrp, w->BorderLeft, myrp->cp_y + myfont->tf_YSize + 1);
        }
        else
        {
           Text(myrp, &(buffer[count]), fit);
           count += fit;
        }
        EOP();
      }

      if (mytask->tc_SigRecvd & SIGBREAKF_CTRL_C)        /* did the user hit CTRL-C (the shell */
      {                                                  /* window has to receive the CTRL-C)? */
        aok = FALSE;
        VPrintf("Ctrl-C Break\n", NULL);
        count = BUFSIZE + 1;
      }
    }
  }
  if (actual < 0)
    VPrintf("Error while reading\n", NULL);
}

void EOP(void)
{
    if (myrp->cp_y > (w->Height - (w->BorderBottom + 2))) /* If we reached page bottom, clear the */
    {                                                     /* rastport and move back to the top.   */
        Delay(25);

        SetAPen(myrp, 0);
        RectFill(myrp, (LONG)w->BorderLeft, (LONG)w->BorderTop, w->Width - (w->BorderRight + 1),
                 w->Height - (w->BorderBottom + 1) );
        SetAPen(myrp, 1);
        Move(myrp, w->BorderLeft + 1, wtbarheight);
        SetAPen(myrp, fr->fo_FrontPen);
    }
}


Lib_examples/cliptext.c

;/* cliptext.c - Execute me to compile me with Lattice 5.10a
LC -cfistq -v -y -j73 cliptext.c
Blink FROM LIB:c.o,cliptext.o TO cliptext LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit ;
**
** The following example, cliptext.c, renders the contents of a text
** file to a Workbench window.  This example gets the new aspect ratio
** for a font by asking the display database what the aspect ratio of
** the current display mode is.
*/
#include <exec/types.h>
#include <dos/rdargs.h>
#include <dos/dosextens.h>
#include <intuition/intuition.h>
#include <graphics/text.h>
#include <graphics/displayinfo.h>
#include <graphics/regions.h>
#include <graphics/gfx.h>
#include <libraries/diskfont.h>
#include <libraries/diskfonttag.h>
#include <utility/tagitem.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/layers_protos.h>
#include <clib/alib_stdio_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/diskfont_protos.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }
#endif

UBYTE *vers = "\0$VER: cliptext 37.2";

#define BUFSIZE          4096
#define FONT_NAME        0
#define FONT_SIZE        1
#define FILE_NAME        2
#define JAM_MODE         3
#define XASP             4
#define YASP             5
#define NUM_ARGS         6
#define DEFAULTFONTSIZE  11L
#define DEFAULTJAMMODE   0L
#define DEFAULTXASP      0L
#define DEFAULTYASP      0L

void MainLoop(void);

LONG args[NUM_ARGS];
struct TagItem tagitem[2];
UBYTE buffer[BUFSIZE];
BPTR myfile;
struct Library *DiskfontBase, *IntuitionBase, *LayersBase, *GfxBase;
struct IntuiMessage *mymsg;
struct DrawInfo *mydrawinfo;
struct Window *mywin;
struct RastPort *myrp;
struct TTextAttr myta;
struct TextFont *myfont;
struct Rectangle myrectangle;
struct Region *new_region;

void main(int argc, char **argv)
{
  struct RDArgs *myrda;
  struct DisplayInfo mydi;
  ULONG mymodeid;

  LONG mydefaultfontsize = DEFAULTFONTSIZE;
  LONG mydefaultJAMMode = DEFAULTJAMMODE;
  LONG mydefaultXASP = 0L;
  LONG mydefaultYASP = 0L;
  args[FONT_NAME] = (LONG)"topaz.font";
  args[FONT_SIZE] = (LONG)&mydefaultfontsize;
  args[FILE_NAME] = (LONG)"s:startup-sequence";
  args[JAM_MODE]  = (LONG)&mydefaultJAMMode;
  args[XASP]      = (LONG)&mydefaultXASP;
  args[YASP]      = (LONG)&mydefaultYASP;

  /* dos.library standard command line parsing--See the dos.library Autodoc for details */
  if (myrda = ReadArgs("FontName,FontSize/N,FileName,Jam/N,XASP/N,YASP/N\n", args, NULL))
  {
    if (myfile = Open((UBYTE *)args[FILE_NAME], MODE_OLDFILE) )   /* Open the file to display. */
    {
      if (DiskfontBase = OpenLibrary("diskfont.library", 37L))          /* Open the libraries. */
      {
        if (IntuitionBase = OpenLibrary("intuition.library", 37L))
        {
          if (GfxBase = OpenLibrary("graphics.library", 37L))
          {
            if (LayersBase = OpenLibrary("layers.library", 37L))
            {
              if (mywin = OpenWindowTags(NULL,                            /* Open that window. */
                     WA_MinWidth,     100,     /* This application wants to hear about three   */
                     WA_MinHeight,    100,     /* things: 1) When the user clicks the window's */
                     WA_SmartRefresh, TRUE,    /* close gadget, 2) when the user starts to     */
                     WA_SizeGadget,   TRUE,    /* resize the window, 3) and when the user has  */
                     WA_CloseGadget,  TRUE,    /* finished resizing the window.                */
                     WA_IDCMP,       IDCMP_CLOSEWINDOW | IDCMP_NEWSIZE | IDCMP_SIZEVERIFY,
                     WA_DragBar,     TRUE,
                     WA_DepthGadget, TRUE,
                     WA_Title,       (ULONG)args[FILE_NAME],
                     TAG_END))
              {
                tagitem[0].ti_Tag = OT_DeviceDPI;

                /* See if there is a non-zero value in the XASP or YASP fields. Diskfont.library */
                /* will get a divide by zero GURU if you give it a zero XDPI or YDPI value.      */

                /* if there is a zero value in one of them... */
                if (  ( (*(ULONG *)args[XASP]) == 0) || ( (*(ULONG *)args[YASP]) == 0)  )
                {
                  /* ...then use the aspect ratio of the current display as a default... */
                  mymodeid = GetVPModeID(&(mywin->WScreen->ViewPort));
                  if (GetDisplayInfoData( NULL, (UBYTE *)&mydi,
                                          sizeof(struct DisplayInfo), DTAG_DISP, mymodeid))
                  {
                    mydefaultXASP = mydi.Resolution.x;
                    mydefaultYASP = mydi.Resolution.y;
                    printf("XAsp = %ld    YAsp = %ld\n", mydefaultXASP, mydefaultYASP);
                    /* Notice that the X and Y get _swapped_ to keep the look of the    */
                    /* font glyphs the same using screens with different aspect ratios. */
                    args[YASP]    = (LONG)&mydefaultXASP;
                    args[XASP]    = (LONG)&mydefaultYASP;
                  }
                  else /* ...unless something is preventing us from getting the screen  */
                       /* screens resolution.  In that case, forget about the DPI tag.  */
                       tagitem[0].ti_Tag = TAG_END;
                }
                /* Here we have to put the X and Y DPI into the OT_DeviceDPI tags data field.  */
                /* THESE ARE NOT REAL X AND Y DPI VALUES FOR THIS FONT OR DISPLAY. They only   */
                /* serve to supply the diskfont.library with values to calculate the aspect    */
                /* ratio.  The X value gets stored in the upper word of the tag value and the Y*/
                /* DPI gets stored in the lower word.  Because ReadArgs() stores the _address_ */
                /* of integers it gets from the command line, you have to dereference the      */
                /* pointer it puts into the argument array, which results in some ugly casting.*/

                tagitem[0].ti_Data = (ULONG)( ( (UWORD) *( (ULONG *)args[XASP] ) << 16) |
                                               ((UWORD) *( (ULONG *)args[YASP]) ) );
                tagitem[1].ti_Tag = TAG_END;

                myta.tta_Name = (STRPTR)args[FONT_NAME];           /* Set up the TTextAttr     */
                myta.tta_YSize = *((LONG *)args[FONT_SIZE]);       /* structure to match the   */
                myta.tta_Style = FSF_TAGGED;                       /* font the user requested. */
                myta.tta_Flags = 0L;
                myta.tta_Tags = tagitem;

                if (myfont = OpenDiskFont(&myta))       /* open that font */
                {
                 /* This is for the layers.library clipping region that gets attached to the   */
                 /* window.  This prevents the application from unnecessarily rendering beyond */
                  myrectangle.MinX = mywin->BorderLeft; /* the bounds of the inner part of     */
                  myrectangle.MinY = mywin->BorderTop;  /* the window.  For now, you can       */
                  myrectangle.MaxX = mywin->Width -     /* ignore the layers stuff if you are  */
                      (mywin->BorderRight + 1);         /* just interested in learning about   */
                  myrectangle.MaxY = mywin->Height -    /* using text.  For more information   */
                      (mywin->BorderBottom + 1);        /* on clipping regions and layers, see */
                                                        /* the Layers chapter of this manual.  */

                  if (new_region = NewRegion())                           /* more layers stuff */
                  {
                    if (OrRectRegion(new_region, &myrectangle));     /* Even more layers stuff */
                    {
                      InstallClipRegion(mywin->WLayer, new_region);
                      /* Obtain a pointer to the window's rastport and set up some of the      */
                      myrp = mywin->RPort;    /* rastport attributes. This example obtains the */
                      SetFont(myrp, myfont);  /* text pen for the window's screen using        */
                      if (mydrawinfo =GetScreenDrawInfo(mywin->WScreen)) /* GetScreenDrawInfo()*/
                      {
                        SetAPen(myrp, mydrawinfo->dri_Pens[TEXTPEN]);
                        FreeScreenDrawInfo(mywin->WScreen, mydrawinfo);
                      }
                      SetDrMd(myrp, (BYTE)(*((LONG *)args[JAM_MODE])));

                      MainLoop();
                    }
                    DisposeRegion(new_region);
                  }
                  CloseFont(myfont);
                }
                CloseWindow(mywin);
              }
              CloseLibrary(LayersBase);
            }
            CloseLibrary(GfxBase);
          }
          CloseLibrary(IntuitionBase);
        }
        CloseLibrary(DiskfontBase);
      }
      Close(myfile);
    }
    FreeArgs(myrda);
  }
  else VPrintf("Error parsing arguments\n", NULL);
}

void MainLoop(void)
{
    LONG count, actual, position;
    BOOL aok = TRUE, waitfornewsize = FALSE;
    struct Task *mytask;

    mytask = FindTask(NULL);
    Move(myrp, mywin->BorderLeft + 1, mywin->BorderTop + myfont->tf_YSize + 1);

    while (((actual = Read(myfile, buffer, BUFSIZE)) > 0) && aok) /* While there's something   */
    {                                                             /* to read, fill the buffer. */
        position = 0;
        count = 0;

        while (position <= actual)
        {
           if (!(waitfornewsize))
           {
               while ( ((buffer[count] >= myfont->tf_LoChar) &&
                       (buffer[count] <= myfont->tf_HiChar)) && (count <= actual) )
                   count++;

               Text(myrp, &(buffer[position]), (count)-position);

               while ( ((buffer[count] < myfont->tf_LoChar) ||
                       (buffer[count] > myfont->tf_HiChar)) && (count <= actual) )
               {
                   if (buffer[count] == 0x0A)
                       Move(myrp, mywin->BorderLeft, myrp->cp_y + myfont->tf_YSize + 1);
                   count++;
               }
               position = count;
           }
           else WaitPort(mywin->UserPort);

           while (mymsg = (struct IntuiMessage *)GetMsg(mywin->UserPort))
           {
               if (mymsg->Class == IDCMP_CLOSEWINDOW)     /* The user clicked the close gadget */
               {
                   aok = FALSE;
                   position = actual + 1;
                   ReplyMsg((struct Message *)mymsg);
               }                                                     /* The user picked up the */
               else if (mymsg->Class == IDCMP_SIZEVERIFY)            /* window's sizing gadget */
               {
                  /* When the user has picked up the window's sizing gadget when the           */
                  /* IDCMP_SIZEVERIFY flag is set, the application has to reply to this message*/
                  /* to tell Intuition to allow the user to move the sizing gadget and resize  */
                  /* the window.  The reason for using this here is because the user can resize*/
                  /* the window while cliptext.c is rendering text to the window. Cliptext.c   */
                  /* has to stop rendering text when it receives an IDCMP_SIZEVERIFY message.  */
                  /*                                                                           */
                  /* if this example had instead asked to hear about IDCMP events that could   */
                  /* take place between SIZEVERIFY and NEWSIZE events (especially INTUITICKS), */
                  /* it should turn off those events here using ModifyIDCMP().                 */
                  /*                                                                           */
                  /* After we allow the user to resize the window, we cannot write into the    */
                  /* window until the user has finished resizing it because we need the        */
                  /* window's new size to adjust the clipping area.  Specifically, we have     */
                  /* to wait for an IDCMP_NEWSIZE message which Intuition will send when the   */
                  /* user lets go of the resize gadget.  For now, we set the waitfornewsize    */
                  /* flag to stop rendering until we get that NEWSIZE message.                 */

                   waitfornewsize = TRUE;
                   WaitBlit();

                   ReplyMsg((struct Message *)mymsg);            /* The blitter is done, let the */
               }                                                 /* user resize the window.      */
               else
               {
                   ReplyMsg((struct Message *)mymsg);
                   waitfornewsize = FALSE;
                          /* The user has resized the window, so get the new window dimensions */
                   myrectangle.MinX = mywin->BorderLeft;      /* and readjust the layers       */
                   myrectangle.MinY = mywin->BorderTop;       /* clipping region accordingly.  */
                   myrectangle.MaxX = mywin->Width - (mywin->BorderRight + 1);
                   myrectangle.MaxY = mywin->Height - (mywin->BorderBottom + 1);
                   InstallClipRegion(mywin->WLayer, NULL);
                   ClearRegion(new_region);
                   if (OrRectRegion(new_region, &myrectangle))
                       InstallClipRegion(mywin->WLayer, new_region);
                   else
                   {
                       aok = FALSE;
                       position = actual + 1;
                   }
               }
           }
           if (mytask->tc_SigRecvd & SIGBREAKF_CTRL_C)              /* Check for user break.   */
           {
               aok = FALSE;
               position = actual + 1;
           }

           if (myrp->cp_y > (mywin->Height - (mywin->BorderBottom + 2))) /* if we reached the  */
           {                                               /* bottom of the page, clear the    */
               Delay(25);                                  /* rastport and move back to the top*/

               SetRast(myrp, 0);      /* Set the entire rastport to color zero.  This will not */
               Move(myrp,             /* the window borders because of the layers clipping.    */
               mywin->BorderLeft + 1,
               mywin->BorderTop + myfont->tf_YSize + 1);
            }
        }
    }
    if (actual < 0) VPrintf("Error while reading\n", NULL);
}


Lib_examples/suits8.asm

* A sparse (but complete) sample font.
*
* 1.  Assemble this file (assumed to have been saved as "suits8.asm"). For
* example, if you have the CAPE 680x0 assembler, and you have assigned
* "include:" to the directory containing your include files, use:
*          CAsm -a "suits8.asm" -o "suits8.o" -i "include:"
*
*     Link "suits8.o".  For example, if you have Lattice, use:
*          BLink from "suits8.o" to "suits8"
*
* 2.  Create the subdirectory "Fonts:suits".  Copy the file "suits8"
*     (created in step 1) to "Fonts:suits/8".
*
* 3.  Create a font contents file for the font.  You can do this by two
*      methods:
*
*   a. Run the program "System/FixFonts" which will create the file
*      "Fonts:suits.font" automatically.
*   b. Use the NewFontContents() call in the diskfont library to create a
*      FontContentsHeader structure, which can be saved in the Fonts:
*      directory as "suits.font".   This is essentially what FixFonts does.
*
* The next word contains the font YSize; in this case, 0x0008.
*
* The next byte contains the font Flags, in this case 0x00.
*
* The last byte contains the font characteristics, in this case 0x60.  This
* says it is a disk-based font (bit 1 set) and the font has been removed
* (bit 7 set), saying that the font is not currently resident.
*
* Summary of suits.font file:
*
* Name: fch_FileID fch_NumEntries fc_FileName    fc_YSize fc_Flags fc_Style
* Size: word       word     MAXFONTPATH bytes word     byte     byte
* Hex:  0f00       0001     73756974732F3800  0008     00       60
* ASCII:            s u i t s / 8 \0
*
* The correct length of a font file may be calculated with this formula:
* length = ((number of font contents entries) * (MAXFONTPATH+4)) + 4. In
* this case (one entry), this becomes (MAXFONTPATH + 8) or 264.
*
* To try out this example font, do the following.  Use the Fonts
* Preferences editor or a program that allows the user to select fonts.
* Choose the "suits" font in size 8.  This example font defines ASCII
* characters 'a' 'b' 'c' and 'd' only. All other characters map to a
* rectangle, meaning "character unknown".

    INCLUDE  "exec/types.i"
    INCLUDE  "exec/nodes.i"
    INCLUDE  "libraries/diskfont.i"

    MOVEQ  #-1,D0    ; Provide an easy exit in case this file is
    RTS              ; "Run" instead of merely loaded.

    DC.L   0         ; ln_Succ   * These five entries comprise a Node
    DC.L   0         ; ln_Pred   * structure, used by the system to link
    DC.B   NT_FONT   ; ln_Type   * disk fonts into a list.  See the
    DC.B   0         ; ln_Pri    * definition of the "DiskFontHeader"
    DC.L   fontName  ; ln_Name   * structure in the "libraries/diskfont.i"
                                 * includefile for more information.
    DC.W   DFH_ID    ; FileID
    DC.W   1         ; Revision
    DC.L   0         ; Segment

* The next MAXFONTNAME bytes are a placeholder.  The name of the font
* contents file (e.g. "suits.font") will be copied here after this font
* descriptor is LoadSeg-ed into memory.  The Name field could have been
* left blank, but inserting the font name and size (or style) allows one to
* tell something about the font by using "Type OPT H" on the file.

fontName:
    DC.B      "suits8"    ; Name

* If your assembler needs an absolute value in place of the "length"
* variable, simply count the number of characters in Name and use that.

length  EQU     *-fontName           ; Assembler calculates Name's length.
        DCB.B   MAXFONTNAME-length,0 ; Padding of null characters.

font:
    DC.L  0          ; ln_Succ       * The rest of the information is a
    DC.L  0          ; ln_Pred       * TextFont structure.  See the
    DC.B  NT_FONT    ; ln_Type       * "graphics/text.i" include file for
    DC.B  0          ; ln_Pri        * more information.
    DC.L  fontName   ; ln_Name
    DC.L  0          ; mn_ReplyPort
    DC.W  0          ; (Reserved for 1.4 system use.)
    DC.W  8          ; tf_YSize
    DC.B  0          ; tf_Style
    DC.B  FPF_DESIGNED!FPF_PROPORTIONAL!FPF_DISKFONT ; tf_Flags
    DC.W  14         ; tf_XSize
    DC.W  6          ; tf_Baseline  <----* tf_Baseline must be no greater
    DC.W  1          ; tf_BoldSmear      * than tf_YSize-1, otherwise
    DC.W  0          ; tf_Accessors      * algorithmically-generated styles
    DC.B  97         ; tf_LoChar         * (italic in particular) can
    DC.B  100        ; tf_HiChar         *  corrupt system memory.
    DC.L  fontData   ; tf_CharData
    DC.W  8          ; tf_Modulo  <- * add this to the data pointer to go
                     ;               * from one row of a character to the
                                     * next row of it.
    DC.L  fontLoc    ; tf_CharLoc <------* bit position in the font data
    DC.L  fontSpace  ; tf_CharSpace      * at which the character begins.
    DC.L  fontKern   ; tf_CharKern

* The four characters of this font define the four playing-card suit
* symbols.  The heart, club, diamond, and spade map to the lower-case ASCII
* characters 'a', 'b', 'c', and 'd' respectively The fifth entry in the
* table is the character to be output when there is no entry defined in the
* character set for the requested ASCII value.  Font data is bit-packed
* edge to edge to save space.

fontData:                             ;   97 (a)       98 (b)       99 (c)   100 (d)      255
    DC.W  $071C0,$08040,$070FF,$0F000 ; <        X        X    X        X        >
    DC.W  $0FBE3,$0E0E0,$0F8C0,$03000 ;  .@@@...@@@.  .....@.....  ...@...  ....@@@....  @@@@@@@@@@@@
    DC.W  $07FCF,$0F9F3,$026C0,$03000 ;  @@@@@.@@@@@  ...@@@@@...  ..@@@..  ...@@@@@...  @@........@@
    DC.W  $03F9F,$0FFFF,$0FFC0,$03000 ;  .@@@@@@@@@.  .@@@@@@@@@.  .@@@@@.  .@@..@..@@.  @@........@@
    DC.W  $01F0E,$0B9F3,$026C0,$03000 ;  ..@@@@@@@..  @@@@@@@@@@@  @@@@@@@  @@@@@@@@@@@  @@........@@
    DC.W  $00E00,$080E0,$020C0,$03000 ;  ...@@@@@...  .@@@.@.@@@.  .@@@@@.  .@@..@..@@.  @@........@@
    DC.W  $00403,$0E040,$0F8FF,$0F000 ;  ....@@@....  .....@.....  ..@@@..  .....@.....  @@........@@
    DC.W  $00000,$00000,$00000,$00000 ;  .....@.....  ...@@@@@...  ...@...  ...@@@@@...  @@@@@@@@@@@@
    DC.W  $00000,$00000,$00000,$00000 ;  ...........  ...........  .......  ...........  ............

fontLoc:              ; The fontLoc information is used to "unpack" the
    DC.L  $00000000B  ; fontData. Each pair of words specifies how the
    DC.L  $0000B000B  ; characters are bit-packed.  For example, the first
    DC.L  $000160007  ; character starts at bit position 0x0000, and is
    DC.L  $0001D000B  ; 0x000B (11) bits wide.  The second character starts
    DC.L  $00028000C  ; at bit position 0x000B and is 0x000B bits wide, and
                      ; so on.  This tellsthe font handler how to unpack
                      ; the bits from the array.

fontSpace:                      ; fontSpace array:  Use a space this wide
    DC.W  000012,000012         ; to contain this character when it is
    DC.W  000008,000012,000013  ; printed.  For reverse-path fonts these
                                ; values would be small or negative.

fontKern:                       ; fontKern array:  Place a space this wide
    DC.W  000001,000001         ; after the corresponding character to
    DC.W  000001,000001,000001  ; separate it from the following character.
                                ; For reverse-path fonts these values would
                                ; be large negative numbers, approximately
                                ; the width of the characters.
fontEnd:
    END


Lib_examples/pseudotext.c

/* pseudotext.c */

void main(void, void)
{
    struct TextAttr myta = {
        "topaz.font"
        11,
        FSF_ITALIC | FSF_BOLD,
        NULL
    };

    struct TextFont *myfont, *oldfont;
    struct RastPort *myrp;
    struct Window   *mywin;

    . . .

    /* open the graphics and diskfont libraries and whatever else you may need */
    . . .

    if (myfont = OpenDiskFont(&myta))
    {
        /* you would probably set the font of the rastport you are going to use */
        myrp    = mywin->RPort
        oldfont = myrp->Font;
        SetFont(myrp, myfont);

        . . .

        /* perform whatever drawing you need to do */

        . . .

        /* time to clean up.  If the rastport is not exclusively yours,
           you may need to restore the original font or other Rasport values */
        SetFont(myrp, oldfont);
        CloseFont(myfont);
    }

    /* close whatever libraries and other resources you allocated */
}


Lib_examples/openwindowtags.c

;/* openwindowtags.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 openwindowtags.c
Blink FROM LIB:c.o,openwindowtags.o TO openwindowtags LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
**
** Here's an example showing how to open a new window using the
** OpenWindowTagList() function with window attributes set up
** in a TagItem array.
**
** openwindowtags.c - open a window using tags.
*/

#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <intuition/screens.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

#define MY_WIN_LEFT   (20)
#define MY_WIN_TOP    (10)
#define MY_WIN_WIDTH  (300)
#define MY_WIN_HEIGHT (110)

void handle_window_events(struct Window *);

struct Library *IntuitionBase;

struct TagItem win_tags[] =
    {
    {WA_Left,       MY_WIN_LEFT},
    {WA_Top,        MY_WIN_TOP},
    {WA_Width,      MY_WIN_WIDTH},
    {WA_Height,     MY_WIN_HEIGHT},
    {WA_CloseGadget,TRUE},
    {WA_IDCMP,      IDCMP_CLOSEWINDOW},
    {TAG_DONE, NULL},
    };

/*
** Open a simple window using OpenWindowTagList()
*/
VOID main(int argc, char **argv)
{
struct Window *win;

/* these calls are only valid if we have Intuition version 37 or greater */
IntuitionBase = OpenLibrary("intuition.library",37);
if (IntuitionBase!=NULL)
    {
    win = OpenWindowTagList(NULL,win_tags);
    if (win==NULL)
        {
        /* window failed to open */
        }
    else
        {
        /* window successfully opened here */
        handle_window_events(win);

        CloseWindow(win);
        }
    CloseLibrary((struct Library *)IntuitionBase);
    }
}

/* Normally this routine would contain an event loop like the one given
** in the chapter "Intuition Input and Output Methods".  Here we just
** wait for any messages we requested to appear at the Window's port.
*/
VOID handle_window_events(struct Window *win)
{
WaitPort(win->UserPort);
}


Lib_examples/lines.c

;/* lines.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 lines.c
Blink FROM LIB:c.o,lines.o TO lines LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
**
** This example shows how to implement a superbitmap, and uses a host of
** Intuition facilities.  Further reading of other Intuition and graphics
** chapters may be required for a complete understanding of this example.
**
** lines.c -- implements a superbitmap with scroll gadgets
** This program requires V37, as it uses calls to OpenWindowTags(),
** LockPubScreen().
*/

/* Enforces use of new prefixed Intuition flag names */
#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>

#include <clib/exec_protos.h>
#include <clib/layers_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>

/* Random number function in amiga.lib (see amiga.lib.doc) */
UWORD RangeRand( unsigned long maxValue );

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

#define WIDTH_SUPER     (800)
#define HEIGHT_SUPER    (600)

#define UP_DOWN_GADGET    (0)
#define LEFT_RIGHT_GADGET (1)
#define NO_GADGET         (2)

#define MAXPROPVAL (0xFFFFL)

#define GADGETID(x) (((struct Gadget *)(msg->IAddress))->GadgetID)

#define LAYERXOFFSET(x) (x->RPort->Layer->Scroll_X)
#define LAYERYOFFSET(x) (x->RPort->Layer->Scroll_Y)

/* A string with this format will be found by the version command
** supplied by Amiga, Inc.  This will allow users to give version
** numbers with error reports.
*/
UBYTE vers[] = "$VER: lines 37.2";

struct Library *GfxBase;
struct Library *IntuitionBase;
struct Library *LayersBase;

struct Window      *Win = NULL;          /* window pointer */
struct PropInfo     BotGadInfo = {0};
struct Image        BotGadImage = {0};
struct Gadget       BotGad = {0};
struct PropInfo     SideGadInfo = {0};
struct Image        SideGadImage = {0};
struct Gadget       SideGad = {0};

/* Prototypes for our functions */
VOID initBorderProps(struct Screen *myscreen);
VOID doNewSize(void);
VOID doDrawStuff(void);
VOID doMsgLoop(void);
VOID superWindow(struct Screen *myscreen);

/*
** main
** Open all required libraries and get a pointer to the default public screen.
** Cleanup when done or on error.
*/
VOID main(int argc, char **argv)
{
struct Screen *myscreen;

/* open all of the required libraries for the program.
**
** require version 37 of the Intuition library.
*/

if (IntuitionBase = OpenLibrary("intuition.library",37L))
    {
    if (GfxBase = OpenLibrary("graphics.library",33L))
        {
        if (LayersBase = OpenLibrary("layers.library",33L))
            {
            /* LockPubScreen()/UnlockPubScreen is only available under V36
            ** and later... Use GetScreenData() under V34 systems to get a
            ** copy of the screen structure...
            */
            if (NULL != (myscreen = LockPubScreen(NULL)))
                {
                superWindow(myscreen);
                UnlockPubScreen(NULL,myscreen);
                }
            CloseLibrary(LayersBase);
            }
        CloseLibrary(GfxBase);
        }
    CloseLibrary(IntuitionBase);
    }
}

/*
** Create, initialize and process the super bitmap window.
** Cleanup if any error.
*/
VOID superWindow(struct Screen *myscreen)
{
struct BitMap *bigBitMap;
WORD planeNum;
WORD allocatedBitMaps;

/* set-up the border prop gadgets for the OpenWindow() call. */
initBorderProps(myscreen);

/* The code relies on the allocation of the BitMap structure with
** the MEMF_CLEAR flag.  This allows the assumption that all of the
** bitmap pointers are NULL, except those successfully allocated
** by the program.
*/
if (bigBitMap = AllocMem(sizeof(struct BitMap), MEMF_PUBLIC | MEMF_CLEAR))
    {
    InitBitMap(bigBitMap, myscreen->BitMap.Depth, WIDTH_SUPER, HEIGHT_SUPER);

    allocatedBitMaps = TRUE;
    for (planeNum = 0;
         (planeNum < myscreen->BitMap.Depth) && (allocatedBitMaps == TRUE);
             planeNum++)
        {
        bigBitMap->Planes[planeNum] = AllocRaster(WIDTH_SUPER, HEIGHT_SUPER);
        if (NULL == bigBitMap->Planes[planeNum])
            allocatedBitMaps = FALSE;
        }

    /* Only open the window if the bitplanes were successfully
    ** allocated.  Fail silently if they were not.
    */
    if (TRUE == allocatedBitMaps)
        {
        /* OpenWindowTags() and OpenWindowTagList() are only available
        ** when the library version is at least V36.  Under earlier
        ** versions of Intuition, use OpenWindow() with a NewWindow
        ** structure.
        */
        if (NULL != (Win = OpenWindowTags(NULL,
                WA_Width,  150,
                WA_Height, 4 * (myscreen->WBorTop + myscreen->Font->ta_YSize + 1),
                WA_MaxWidth,  WIDTH_SUPER,
                WA_MaxHeight, HEIGHT_SUPER,
                WA_IDCMP, IDCMP_GADGETUP | IDCMP_GADGETDOWN |
                    IDCMP_NEWSIZE | IDCMP_INTUITICKS | IDCMP_CLOSEWINDOW,
                WA_Flags, WFLG_SIZEGADGET | WFLG_SIZEBRIGHT | WFLG_SIZEBBOTTOM |
                    WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET |
                    WFLG_SUPER_BITMAP | WFLG_GIMMEZEROZERO | WFLG_NOCAREREFRESH,
                WA_Gadgets, &(SideGad),
                WA_Title, &vers[6], /* take title from version string */
                WA_PubScreen, myscreen,
                WA_SuperBitMap, bigBitMap,
                TAG_DONE)))
            {
            /* set-up the window display */
            SetRast(Win->RPort,0); /* clear the bitplanes */
            SetDrMd(Win->RPort,JAM1);

        doNewSize();    /* adjust props to represent portion visible */
            doDrawStuff();

            /* process the window, return on IDCMP_CLOSEWINDOW */
            doMsgLoop();

            CloseWindow(Win);
            }
        }

    for (planeNum = 0; planeNum < myscreen->BitMap.Depth; planeNum++)
        {
        /* free only the bitplanes actually allocated... */
        if (NULL != bigBitMap->Planes[planeNum])
            FreeRaster(bigBitMap->Planes[planeNum], WIDTH_SUPER, HEIGHT_SUPER);
        }
    FreeMem(bigBitMap,sizeof(struct BitMap));
    }
}

/*
** Set-up the prop gadgets--initialize them to values that fit
** into the window border.  The height of the prop gadget on the side
** of the window takes the height of the title bar into account in its
** set-up. note the initialization assumes a fixed size "sizing" gadget.
**
** Note also, that the size of the sizing gadget is dependent on the
** screen resolution.  The numbers given here are only valid if the
** screen is NOT lo-res.  These values must be re-worked slightly
** for lo-res screens.
**
** The PROPNEWLOOK flag is ignored by 1.3.
*/
VOID initBorderProps(struct Screen *myscreen)
{
/* initializes the two prop gadgets.
**
** Note where the PROPNEWLOOK flag goes.  Adding this flag requires
** no extra storage, but tells the system that our program is
** expecting the new-look prop gadgets under 2.0.
*/
BotGadInfo.Flags     = AUTOKNOB | FREEHORIZ | PROPNEWLOOK;
BotGadInfo.HorizPot  = 0;
BotGadInfo.VertPot   = 0;
BotGadInfo.HorizBody = -1;
BotGadInfo.VertBody  = -1;

BotGad.LeftEdge     = 3;
BotGad.TopEdge      = -7;
BotGad.Width        = -23;
BotGad.Height       = 6;

BotGad.Flags        = GFLG_RELBOTTOM | GFLG_RELWIDTH;
BotGad.Activation   = GACT_RELVERIFY | GACT_IMMEDIATE | GACT_BOTTOMBORDER;
BotGad.GadgetType   = GTYP_PROPGADGET | GTYP_GZZGADGET;
BotGad.GadgetRender = (APTR)&(BotGadImage);
BotGad.SpecialInfo  = (APTR)&(BotGadInfo);
BotGad.GadgetID     = LEFT_RIGHT_GADGET;

SideGadInfo.Flags     = AUTOKNOB | FREEVERT | PROPNEWLOOK;
SideGadInfo.HorizPot  = 0;
SideGadInfo.VertPot   = 0;
SideGadInfo.HorizBody = -1;
SideGadInfo.VertBody  = -1;

/* NOTE the TopEdge adjustment for the border and the font for V36.
*/
SideGad.LeftEdge   = -14;
SideGad.TopEdge    = myscreen->WBorTop + myscreen->Font->ta_YSize + 2;
SideGad.Width      = 12;
SideGad.Height     = -SideGad.TopEdge - 11;

SideGad.Flags        = GFLG_RELRIGHT | GFLG_RELHEIGHT;
SideGad.Activation   = GACT_RELVERIFY | GACT_IMMEDIATE | GACT_RIGHTBORDER;
SideGad.GadgetType   = GTYP_PROPGADGET | GTYP_GZZGADGET;
SideGad.GadgetRender = (APTR)&(SideGadImage);
SideGad.SpecialInfo  = (APTR)&(SideGadInfo);
SideGad.GadgetID     = UP_DOWN_GADGET;
SideGad.NextGadget   = &(BotGad);
}

/*
** This function does all the work of drawing the lines
*/
VOID doDrawStuff()
{
WORD x1,y1,x2,y2;
WORD pen,ncolors,deltx,delty;

ncolors = 1 << Win->WScreen->BitMap.Depth;
deltx = RangeRand(6)+2;
delty = RangeRand(6)+2;

pen = RangeRand(ncolors-1) + 1;
SetAPen(Win->RPort,pen);
for(x1=0, y1=0, x2=WIDTH_SUPER-1, y2=HEIGHT_SUPER-1;
    x1 < WIDTH_SUPER;
        x1 += deltx, x2 -= deltx)
    {
    Move(Win->RPort,x1,y1);
    Draw(Win->RPort,x2,y2);
    }

pen = RangeRand(ncolors-1) + 1;
SetAPen(Win->RPort,pen);
for(x1=0, y1=0, x2=WIDTH_SUPER-1, y2=HEIGHT_SUPER-1;
    y1 < HEIGHT_SUPER;
        y1 += delty, y2 -= delty)
    {
    Move(Win->RPort,x1,y1);
    Draw(Win->RPort,x2,y2);
    }
}

/*
** This function provides a simple interface to ScrollLayer
*/
VOID slideBitMap(WORD Dx,WORD Dy)
{
ScrollLayer(0,Win->RPort->Layer,Dx,Dy);
}

/*
** Update the prop gadgets and bitmap positioning when the size changes.
*/
VOID doNewSize()
{
ULONG tmp;

tmp = LAYERXOFFSET(Win) + Win->GZZWidth;
if (tmp >= WIDTH_SUPER)
    slideBitMap(WIDTH_SUPER-tmp,0);

NewModifyProp(&(BotGad),Win,NULL,AUTOKNOB | FREEHORIZ,
    ((LAYERXOFFSET(Win) * MAXPROPVAL) /
        (WIDTH_SUPER - Win->GZZWidth)),
    NULL,
    ((Win->GZZWidth * MAXPROPVAL) / WIDTH_SUPER),
    MAXPROPVAL,
    1);

tmp = LAYERYOFFSET(Win) + Win->GZZHeight;
if (tmp >= HEIGHT_SUPER)
    slideBitMap(0,HEIGHT_SUPER-tmp);

NewModifyProp(&(SideGad),Win,NULL,AUTOKNOB | FREEVERT,
    NULL,
    ((LAYERYOFFSET(Win) * MAXPROPVAL) /
        (HEIGHT_SUPER - Win->GZZHeight)),
    MAXPROPVAL,
    ((Win->GZZHeight * MAXPROPVAL) / HEIGHT_SUPER),
    1);
}

/*
** Process the currently selected gadget.
** This is called from IDCMP_INTUITICKS and when the gadget is released
** IDCMP_GADGETUP.
*/
VOID checkGadget(UWORD gadgetID)
{
ULONG tmp;
WORD dX = 0;
WORD dY = 0;

switch (gadgetID)
    {
    case UP_DOWN_GADGET:
        tmp = HEIGHT_SUPER - Win->GZZHeight;
        tmp = tmp * SideGadInfo.VertPot;
        tmp = tmp / MAXPROPVAL;
        dY = tmp - LAYERYOFFSET(Win);
        break;
    case LEFT_RIGHT_GADGET:
        tmp = WIDTH_SUPER - Win->GZZWidth;
        tmp = tmp * BotGadInfo.HorizPot;
        tmp = tmp / MAXPROPVAL;
        dX = tmp - LAYERXOFFSET(Win);
        break;
    }
if (dX || dY)
    slideBitMap(dX,dY);
}

/*
** Main message loop for the window.
*/
VOID doMsgLoop()
{
struct IntuiMessage *msg;
WORD flag = TRUE;
UWORD currentGadget = NO_GADGET;

while (flag)
    {
    /* Whenever you want to wait on just one message port */
    /* you can use WaitPort(). WaitPort() doesn't require */
    /* the setting of a signal bit. The only argument it  */
    /* requires is the pointer to the window's UserPort   */
    WaitPort(Win->UserPort);
    while (msg = (struct IntuiMessage *)GetMsg(Win->UserPort))
        {
        switch (msg->Class)
            {
            case IDCMP_CLOSEWINDOW:
                flag = FALSE;
                break;
            case IDCMP_NEWSIZE:
                doNewSize();
            doDrawStuff();
                break;
            case IDCMP_GADGETDOWN:
                currentGadget = GADGETID(msg);
                break;
            case IDCMP_GADGETUP:
                checkGadget(currentGadget);
                currentGadget = NO_GADGET;
                break;
            case IDCMP_INTUITICKS:
                checkGadget(currentGadget);
                break;
            }
        ReplyMsg((struct Message *)msg);
        }
    }
}


Lib_examples/winpubscreen.c

;/* winpubscreen.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 winpubscreen.c
Blink FROM LIB:c.o,winpubscreen.o TO winpubscreen LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
**
** winpubscreen.c
** open a window on the default public screen (usually the Workbench screen)
*/

#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <intuition/intuition.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

struct Library *IntuitionBase;

/* our function prototypes */
VOID handle_window_events(struct Window *win);

/*
** Open a simple window on the default public screen,
** then leave it open until the user selects the close gadget.
*/
VOID main(int argc, char **argv)
{
struct Window *test_window = NULL;
struct Screen *test_screen = NULL;

IntuitionBase = OpenLibrary("intuition.library",37);
if (IntuitionBase)
    {
    /* get a lock on the default public screen */
    if (test_screen = LockPubScreen(NULL))
            {
            /* open the window on the public screen */
            test_window = OpenWindowTags(NULL,
                    WA_Left,  10,    WA_Top,    20,
                    WA_Width, 300,   WA_Height, 100,
                    WA_DragBar,         TRUE,
                    WA_CloseGadget,     TRUE,
                    WA_SmartRefresh,    TRUE,
                    WA_NoCareRefresh,   TRUE,
                    WA_IDCMP,           IDCMP_CLOSEWINDOW,
                    WA_Title,           "Window Title",
                    WA_PubScreen,       test_screen,
                    TAG_END);

            /* Unlock the screen.  The window now acts as a lock on
            ** the screen, and we do not need the screen after the
            ** window has been closed.
            */
            UnlockPubScreen(NULL, test_screen);

            /* if we have a valid window open, run the rest of the
            ** program, then clean up when done.
            */
            if (test_window)
                {
                handle_window_events(test_window);
                CloseWindow(test_window);
                }
            }
    CloseLibrary(IntuitionBase);
    }
}

/*
** Wait for the user to select the close gadget.
*/
VOID handle_window_events(struct Window *win)
{
struct IntuiMessage *msg;
BOOL done = FALSE;

while (! done)
    {
    /* We have no other ports of signals to wait on,
    ** so we'll just use WaitPort() instead of Wait()
    */
    WaitPort(win->UserPort);

    while ( (! done) &&
            (msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
        {
        /* use a switch statement if looking for multiple event types */
        if (msg->Class == IDCMP_CLOSEWINDOW)
            done = TRUE;

        ReplyMsg((struct Message *)msg);
        }
    }
}


Lib_examples/visiblewindow.c

;/* visiblewindow.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 visiblewindow.c
Blink FROM LIB:c.o,visiblewindow.o TO visiblewindow LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
**
** open a window on the visible part of a screen, with the window as large
** as the visible part of the screen.  It is assumed that the visible part
** of the screen is OSCAN_TEXT, which how the user has set their preferences.
*/
#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <graphics/displayinfo.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

/* Minimum window width and height:
** These values should really be calculated dynamically given the size
** of the font and the window borders.  Here, to keep the example simple
** they are hard-coded values.
*/
#define MIN_WINDOW_WIDTH  (100)
#define MIN_WINDOW_HEIGHT (50)

/* minimum and maximum calculations...Note that each argument is
** evaluated twice (don't use max(a++,foo(c))).
*/
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<=(b)?(a):(b))

struct Library *IntuitionBase;
struct Library *GfxBase;

/* our function prototypes */
VOID handle_window_events(struct Window *win);
VOID fullScreen(VOID);

/*
** open all the libraries and run the code.  Cleanup when done.
*/
VOID main(int argc, char **argv)
{
/* these calls are only valid if we have Intuition version 37 or greater */
if (GfxBase = OpenLibrary("graphics.library",37))
    {
    if (IntuitionBase = OpenLibrary("intuition.library",37))
        {
        fullScreen();

        CloseLibrary(IntuitionBase);
        }
    CloseLibrary(GfxBase);
    }
}

/*
** Open a window on the default public screen, then leave it open until the
** user selects the close gadget. The window is full-sized, positioned in the
** currently visible OSCAN_TEXT area.
*/
VOID fullScreen(VOID)
{
struct Window *test_window;
struct Screen *pub_screen;
struct Rectangle rect;
ULONG screen_modeID;
LONG width, height, left, top;

left  = 0;   /* set some reasonable defaults for left, top, width and height. */
top   = 0;   /* we'll pick up the real values with the call to QueryOverscan(). */
width = 640;
height= 200;

/* get a lock on the default public screen */
if (NULL != (pub_screen = LockPubScreen(NULL)))
    {
    /* this technique returns the text overscan rectangle of the screen that we
    ** are opening on.  If you really need the actual value set into the display
    ** clip of the screen, use the VideoControl() command of the graphics library
    ** to return a copy of the ViewPortExtra structure.  See the Graphics
    ** library chapter and Autodocs for more details.
    **
    ** GetVPModeID() is a graphics call...
    */

    screen_modeID = GetVPModeID(&pub_screen->ViewPort);
    if(screen_modeID != INVALID_ID)
        {
        if (QueryOverscan(screen_modeID, &rect, OSCAN_TEXT))
            {
            /* make sure window coordinates are positive or zero */
            left = max(0, -pub_screen->LeftEdge);
            top  = max(0, -pub_screen->TopEdge);

            /* get width and height from size of display clip */
            width  = rect.MaxX - rect.MinX + 1;
            height = rect.MaxY - rect.MinY + 1;

            /* adjust height for pulled-down screen (only show visible part) */
            if (pub_screen->TopEdge > 0)
                height -= pub_screen->TopEdge;

            /* insure that window fits on screen */
            height = min(height, pub_screen->Height);
            width  = min(width,  pub_screen->Width);

            /* make sure window is at least minimum size */
            width  = max(width,  MIN_WINDOW_WIDTH);
            height = max(height, MIN_WINDOW_HEIGHT);
            }
        }

    /* open the window on the public screen */
    test_window = OpenWindowTags(NULL,
            WA_Left, left,            WA_Width,  width,
            WA_Top,  top,             WA_Height, height,
            WA_CloseGadget, TRUE,
            WA_IDCMP,       IDCMP_CLOSEWINDOW,
            WA_PubScreen,   pub_screen,
            TAG_END);

    /* unlock the screen.  The window now acts as a lock on the screen,
    ** and we do not need the screen after the window has been closed.
    */
    UnlockPubScreen(NULL, pub_screen);

    /* if we have a valid window open, run the rest of the
    ** program, then clean up when done.
    */
    if (test_window)
        {
        handle_window_events(test_window);
        CloseWindow(test_window);
        }
    }
}

/*
** Wait for the user to select the close gadget.
*/
VOID handle_window_events(struct Window *win)
{
struct IntuiMessage *msg;
BOOL done = FALSE;

while (! done)
    {
    /* we only have one signal bit, so we do not have to check which
    ** bit(s) broke the Wait() (i.e. the return value of Wait)
    */
    Wait(1L << win->UserPort->mp_SigBit);

    while ( (! done) &&
            (msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
        {
        /* use a switch statement if looking for multiple event types */
        if (msg->Class == IDCMP_CLOSEWINDOW)
            done = TRUE;

        ReplyMsg((struct Message *)msg);
        }
    }
}


Lib_examples/appicon.c

/* The example listed here shows how to create an AppIcon and obtain
 * arguments from Workbench when the user drops other icons on top of
 * it. The AppIcon will appear as a disk icon named "TestAppIcon" on the
 * Workbench screen.  (All AppIcons appear on the Workbench screen or
 * window.)
 *
 * For convenience, this example code uses GetDefDiskObject() to create
 * the icon imagery for the AppIcon.  Applications should never do this.
 * Use your own custom imagery for AppIcons instead.
 */

/* appicon.c - Compiled under SAS C 5.10 with lc -L appicon.c               */
/* Requires Kickstart version 37 or later.  Works from the Shell (CLI) only */

#include <exec/types.h>          /* Need this for the Amiga variable types  */
#include <workbench/workbench.h> /* This has DiskObject and AppIcon structs */
#include <workbench/startup.h>   /* This has WBStartup and WBArg structs    */
#include <exec/libraries.h>      /* Need this to check library versions     */

#include <clib/icon_protos.h>    /* Icon (DiskObject) function prototypes   */
#include <clib/exec_protos.h>    /* Exec message, port and library functions*/
#include <clib/wb_protos.h>      /* AppIcon function protos                 */

#ifdef LATTICE
int CXBRK(void) { return(0); }   /* Disable SAS Lattice CTRL/C handling */
int chkabort(void) { return(0); }/* really */
#endif

extern struct Library *SysBase;
struct Library *IconBase;
struct Library *WorkbenchBase;

void main(int argc, char **argv)
{
struct DiskObject   *dobj=NULL;
struct MsgPort    *myport=NULL;
struct AppIcon   *appicon=NULL;
struct AppMessage *appmsg=NULL;

LONG dropcount=0L;
ULONG x;
BOOL success=0L;

/* Get the the right version of the Icon Library, initialize IconBase */
if(IconBase = OpenLibrary("icon.library",37))
  {
  /* Get the the right version of the Workbench Library */
  if (WorkbenchBase=OpenLibrary("workbench.library",37))
    {
    /* This is the easy way to get some icon imagery */
    /* Real applications should use custom imagery   */
    dobj=GetDefDiskObject(WBDISK);
    if(dobj!=0)
      {
      /* The type must be set to NULL for a WBAPPICON */
      dobj->do_Type=NULL;

      /* The CreateMsgPort() function is in Exec version 37 and later only */
      myport=CreateMsgPort();
      if(myport)
        {
        /* Put the AppIcon up on the Workbench window */
        appicon=AddAppIconA(0L,0L,"TestAppIcon",myport,NULL,dobj,NULL);
        if(appicon)
          {
          /* For the sake of this example, we allow the AppIcon */
          /* to be activated only five times.                   */
          printf("Drop files on the Workbench AppIcon\n");
          printf("Example exits after 5 drops\n");

          while(dropcount<5)
            {
            /* Here's the main event loop where we wait for */
            /* messages to show up from the AppIcon         */
            WaitPort(myport);

            /* Might be more than one message at the port... */
            while(appmsg=(struct AppMessage *)GetMsg(myport))
              {
              if(appmsg->am_NumArgs==0L)
                {
                /* If NumArgs is 0 the AppIcon was activated directly */
                printf("User activated the AppIcon.\n");
                printf("A Help window for the user would be good here\n");
                }
              else if(appmsg->am_NumArgs>0L)
                {
                /* If NumArgs is >0 the AppIcon was activated by */
                /* having one or more icons dropped on top of it */
                printf("User dropped %ld icons on the AppIcon\n",
                                              appmsg->am_NumArgs);
                for(x=0;x<appmsg->am_NumArgs;x++)
                  {
                  printf("#%ld name='%s'\n",x+1,appmsg->am_ArgList[x].wa_Name);
                  }
                }
              /* Let Workbench know we're done with the message */
              ReplyMsg((struct Message *)appmsg);
              }
            dropcount++;
            }
          success=RemoveAppIcon(appicon);
          }
        /* Clear away any messages that arrived at the last moment */
        while(appmsg=(struct AppMessage *)GetMsg(myport))
            ReplyMsg((struct Message *)appmsg);
        DeleteMsgPort(myport);
        }
      FreeDiskObject(dobj);
      }
    CloseLibrary(WorkbenchBase);
    }
  CloseLibrary(IconBase);
  }
}


Lib_examples/appmenuitem.c

/* This example shows how to create an AppMenuItem.  The example adds a
 * menu item named "Browse Files" to the Workbench Tools menu.  (All
 * AppMenuItems appear in the Workbench Tools menu.)  When the menu item
 * is activated, the example program receives a message from Workbench
 * and then attempts to start up an instance of the More program. (The
 * More program is in the Utilities directory of the Workbench disk.)
 *
 * The example starts up the More program as a separate, asynchronous
 * process using the new SystemTags() function of Release 2 AmigaDOS.
 * For more about the SystemTags() function refer to the AmigaDOS
 * Manual, 3rd Edition from Bantam Books.  When the AppMenuItem has been
 * activated five times, the program exits after freeing any system
 * resources it has used.
 */

/* appmenuitem.c - Compiled under SAS C 5.10 with lc -L appmenuitem.c       */
/* Requires Kickstart version 37 or later.  Works from the Shell (CLI) only */

#include <exec/types.h>          /* Need this for the Amiga variable types  */
#include <workbench/workbench.h> /* This has DiskObject and AppIcon structs */
#include <workbench/startup.h>   /* This has WBStartup and WBArg structs    */
#include <exec/libraries.h>
#include <dos/dostags.h>
#include <stdio.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>    /* Exec message, port and library functions*/
#include <clib/wb_protos.h>      /* AppMenuItem function protos             */

#ifdef LATTICE
int CXBRK(void) { return(0); }   /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }/* really */
#endif

extern struct Library *SysBase;
struct Library *WorkbenchBase;

void main(int argc, char **argv)
{
struct MsgPort      *myport=NULL;
struct AppMenuItem *appitem=NULL;
struct AppMessage   *appmsg=NULL;
LONG result, x, count=0L;
BOOL success=0L;
BPTR file;

if (WorkbenchBase = OpenLibrary("workbench.library",37))
  {
  /* The CreateMsgPort() function is in Exec version 37 and later only */
  if(myport = CreateMsgPort())
    {
    /* Add our own AppMenuItem to the Workbench Tools Menu */
    appitem=AddAppMenuItemA(0L,                   /* Our ID# for item */
                    (ULONG)"SYS:Utilities/More",  /* Our UserData     */
                           "Browse Files",        /* MenuItem Text    */
                            myport,NULL);         /* MsgPort, no tags */
    if(appitem)
      {
      printf("Select Workbench Tools demo menuitem 'Browse Files'\n");

      /* For this example, we allow the AppMenuItem to be selected */
      /* only once, then we remove it and exit                     */
      WaitPort(myport);
      while((appmsg=(struct AppMessage *)GetMsg(myport)) && (count<1))
        {
        /* Handle messages from the AppMenuItem - we have only one  */
        /* item so we don't have to check its appmsg->am_ID number. */
        /* We'll System() the command string that we passed as      */
        /* userdata when we added the menu item.                    */
        /* We find our userdata pointer in appmsg->am_UserData      */

        printf("User picked AppMenuItem with %ld icons selected\n",
                                                appmsg->am_NumArgs);
        for(x=0;x<appmsg->am_NumArgs;x++)
           printf("  #%ld name='%s'\n",x+1,appmsg->am_ArgList[x].wa_Name);

        count++;
        if( file=Open("CON:0/40/640/150/AppMenu Example/auto/close/wait",
                         MODE_OLDFILE)  )     /* for any stdio output */
          {
          result=SystemTags((UBYTE *)appmsg->am_UserData,SYS_Input,file,
                                                         SYS_Output,NULL,
                                                         SYS_Asynch,TRUE,
                                                         TAG_DONE);
          /* If Asynch System() itself fails, we must close file */
          if(result == -1) Close(file);
          }
        ReplyMsg((struct Message *)appmsg);
        }
      success=RemoveAppMenuItem(appitem);
      }

    /* Clear away any messages that arrived at the last moment */
    /* and let Workbench know we're done with the messages     */
    while(appmsg=(struct AppMessage *)GetMsg(myport))
      {
      ReplyMsg((struct Message *)appmsg);
      }
    DeleteMsgPort(myport);
    }
  CloseLibrary(WorkbenchBase);
  }
}


Lib_examples/appwindow.c

/* This example shows how to create an AppWindow and obtain arguments
 * from Workbench when the user drops an icon into it.  The AppWindow
 * will appear on the Workbench screen with the name "AppWindow" and
 * will run until the window's close gadget is selected.  If any icons
 * are dropped into the AppWindow, the program prints their arguments in
 * the Shell window.
 */

/* appwindow.c - Compiled under SAS C 5.10 with lc -L appwindow.c           */
/* Requires Kickstart version 37 or later.  Works from the Shell (CLI) only */

#include <exec/types.h>          /* Need this for the Amiga variable types  */
#include <workbench/workbench.h> /* This has DiskObject and AppWindow       */
#include <workbench/startup.h>   /* This has WBStartup and WBArg structs    */
#include <exec/libraries.h>      /* Need this to check library versions     */

#include <stdio.h>

#include <clib/intuition_protos.h>
#include <clib/exec_protos.h>
#include <clib/wb_protos.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }   /* Disable SAS Lattice CTRL/C handling */
int chkabort(void) { return(0); }/* really */
#endif

struct Library      *IntuitionBase;
struct Library      *WorkbenchBase;

void main(int argc, char **argv)
{
  struct MsgPort *awport;
  struct Window  *win;
  struct AppWindow *appwin;
  struct IntuiMessage *imsg;
  struct AppMessage *amsg;
  struct WBArg   *argptr;

  ULONG           winsig, appwinsig, signals, id = 1, userdata = 0;
  BOOL            done = FALSE;
  int             i;

  if (IntuitionBase = OpenLibrary("intuition.library", 37))
    {
    if (WorkbenchBase = OpenLibrary("workbench.library", 37))
      {
      /* The CreateMsgPort() function is in Exec version 37 and later only */
      if (awport = CreateMsgPort())
         {
         if (win = OpenWindowTags(NULL,
                                  WA_Width, 200,        WA_Height, 50,
                                  WA_IDCMP, CLOSEWINDOW,
                                  WA_Flags, WINDOWCLOSE | WINDOWDRAG,
                                  WA_Title, "AppWindow",
                                  TAG_DONE))
          {
          if (appwin = AddAppWindow(id, userdata, win, awport, NULL))
            {
            printf("AppWindow added... Drag files into AppWindow\n");
            winsig    = 1L << win->UserPort->mp_SigBit;
            appwinsig = 1L << awport->mp_SigBit;

            while (! done)
              {
              /* Wait for IDCMP messages and AppMessages */
              signals = Wait( winsig | appwinsig );

              if(signals & winsig)      /* Got an IDCMP message */
                {
                while (imsg = (struct IntuiMessage *) GetMsg(win->UserPort))
                  {
                  if (imsg->Class = CLOSEWINDOW)   done = TRUE;
                  ReplyMsg((struct Message *) imsg);
                  }
                }
              if(signals & appwinsig)   /* Got an AppMessage */
                {
                while (amsg = (struct AppMessage *) GetMsg(awport))
                  {
                  printf("AppMsg: Type=%ld, ID=%ld, NumArgs=%ld\n",
                           amsg->am_Type, amsg->am_ID, amsg->am_NumArgs);
                  argptr = amsg->am_ArgList;
                  for (i = 0; i < amsg->am_NumArgs; i++)
                    {
                    printf("   arg(%ld): Name='%s', Lock=%lx\n",
                             i, argptr->wa_Name, argptr->wa_Lock);
                    argptr++;
                    }
                  ReplyMsg((struct Message *) amsg);
                  }
                }
              }     /* done */
            RemoveAppWindow(appwin);
            }
          CloseWindow(win);
      }
        /* Make sure there are no more outstanding messages */
        while(amsg = (struct AppMessage *)GetMsg(awport))
              ReplyMsg((struct Message *)amsg);
        DeleteMsgPort(awport);
        }
      CloseLibrary(WorkbenchBase);
      }
    CloseLibrary(IntuitionBase);
    }
}


Lib_examples/iconexample.c

;/* iconexample.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 iconexample.c
Blink FROM LIB:c.o,iconexample.o TO iconexample LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
**
** The following example demonstrates icon creation, icon reading and
** Tool Type parsing in the Workbench environment.  When called from the
** Shell, the example creates a small data file in RAM: and creates or
** updates a project icon for the data file.  The created project icon
** points to this example as its default tool.  When the new project
** icon is double-clicked, Workbench will invoke the default tool (this
** example) as a Workbench process, and pass it a description of the
** project data file as a Workbench argument (WBArg) in the WBStartup
** message.
**
** iconexample.c - Workbench icon startup, creation, and parsing example
*/

#include <exec/types.h>
#include <libraries/dos.h>
#include <workbench/workbench.h>
#include <workbench/startup.h>

#include <clib/alib_protos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/icon_protos.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }   /* Disable SAS Lattice CTRL/C handling */
int chkabort(void) { return(0); }/* really */
#endif

/* our functions */
void cleanexit(UBYTE *,LONG);
void cleanup(void);
void message(UBYTE *);
BOOL makeIcon(UBYTE *, char **, char *);
BOOL showToolTypes(struct WBArg *);

UBYTE *projname     = "RAM:Example_Project";
UBYTE *conwinname   = "CON:10/10/620/180/iconexample";

UBYTE deftoolname[] = {"iconexample"};

USHORT IconImageData1[] =  {
/* Plane 0 */
    0x0000,0x0000,0x0000,0x1000,0x0000,0x0000,0x0000,0x3000,
    0x0FFF,0xFFFC,0x0000,0x3000,0x0800,0x0004,0x0000,0x3000,
    0x0800,0x07FF,0xFFC0,0x3000,0x08A8,0xA400,0x00A0,0x3000,
    0x0800,0x0400,0x0090,0x3000,0x08AA,0xA400,0x0088,0x3000,
    0x0800,0x042A,0xA0FC,0x3000,0x082A,0xA400,0x0002,0x3000,
    0x0800,0x0400,0x0002,0x3000,0x0800,0xA42A,0xA0A2,0x3000,
    0x0800,0x0400,0x0002,0x3000,0x0950,0xA42A,0x8AA2,0x3000,
    0x0800,0x0400,0x0002,0x3000,0x082A,0xA400,0x0002,0x3000,
    0x0800,0x042A,0x2AA2,0x3000,0x0FFF,0xFC00,0x0002,0x3000,
    0x0000,0x0400,0x0002,0x3000,0x0000,0x07FF,0xFFFE,0x3000,
    0x0000,0x0000,0x0000,0x3000,0x7FFF,0xFFFF,0xFFFF,0xF000,
/* Plane 1 */
    0xFFFF,0xFFFF,0xFFFF,0xE000,0xD555,0x5555,0x5555,0x4000,
    0xD000,0x0001,0x5555,0x4000,0xD7FF,0xFFF9,0x5555,0x4000,
    0xD7FF,0xF800,0x0015,0x4000,0xD757,0x5BFF,0xFF55,0x4000,
    0xD7FF,0xFBFF,0xFF65,0x4000,0xD755,0x5BFF,0xFF75,0x4000,
    0xD7FF,0xFBD5,0x5F01,0x4000,0xD7D5,0x5BFF,0xFFFD,0x4000,
    0xD7FF,0xFBFF,0xFFFD,0x4000,0xD7FF,0x5BD5,0x5F5D,0x4000,
    0xD7FF,0xFBFF,0xFFFD,0x4000,0xD6AF,0x5BD5,0x755D,0x4000,
    0xD7FF,0xFBFF,0xFFFD,0x4000,0xD7D5,0x5BFF,0xFFFD,0x4000,
    0xD7FF,0xFBD5,0xD55D,0x4000,0xD000,0x03FF,0xFFFD,0x4000,
    0xD555,0x53FF,0xFFFD,0x4000,0xD555,0x5000,0x0001,0x4000,
    0xD555,0x5555,0x5555,0x4000,0x8000,0x0000,0x0000,0x0000,
};

struct Image iconImage1 =
    {
    0, 0,                /* Top Corner */
    52, 22, 2,           /* Width, Height, Depth */
    &IconImageData1[0],  /* Image Data */
    0x003, 0x000,        /* PlanePick,PlaneOnOff */
    NULL                 /* Next Image */
    };

UBYTE *toolTypes[] =
    {
    "FILETYPE=text",
    "FLAGS=BOLD|ITALICS",
    NULL
    };

struct DiskObject projIcon =
    {
    WB_DISKMAGIC,                   /* Magic Number */
    WB_DISKVERSION,                 /* Version */
        {                           /* Embedded Gadget Structure */
        NULL,                       /* Next Gadget Pointer */
        97,12,52,23,                /* Left,Top,Width,Height */
        GADGIMAGE|GADGHBOX,         /* Flags */
        GADGIMMEDIATE|RELVERIFY,    /* Activation Flags */
        BOOLGADGET,                 /* Gadget Type */
        (APTR)&iconImage1,          /* Render Image */
        NULL,                       /* Select Image */
        NULL,                       /* Gadget Text */
        NULL,                       /* Mutual Exclude */
        NULL,                       /* Special Info */
        0,                          /* Gadget ID */
        NULL                        /* User Data */
        },
    WBPROJECT,                      /* Icon Type */
    deftoolname,                    /* Default Tool */
    toolTypes,                      /* Tool Type Array */
    NO_ICON_POSITION,               /* Current X */
    NO_ICON_POSITION,               /* Current Y */
    NULL,                           /* Drawer Structure */
    NULL,                           /* Tool Window */
    4000                            /* Stack Size */
    };

/* Opens and allocations we must clean up */
struct Library *IconBase = NULL;
FILE *conwin = NULL;
LONG olddir = -1;

BOOL FromWb;

void main(int argc, char **argv)
    {
    struct WBStartup *WBenchMsg;
    struct WBArg *wbarg;
    FILE  *file;
    LONG  wLen;
    SHORT i;

    FromWb = (argc==0) ? TRUE : FALSE;

    /* Open icon.library */
    if(!(IconBase = OpenLibrary("icon.library",33)))
         cleanexit("Can't open icon.library\n",RETURN_FAIL);

    /* If started from CLI, this example will create a small text
     * file RAM:Example_Project, and create an icon for the file
     * which points to this program as its default tool.
     */
    if(!FromWb)
        {
        /* Make a sample project (data) file */
        wLen = -1;
        if(file=fopen(projname,"w"))
            {
            wLen = fprintf(file,"Have a nice day\n");
            fclose(file);
            }
        if(wLen < 0) cleanexit("Error writing data file\n",RETURN_FAIL);

        /* Now save/update icon for this data file */
        if(makeIcon(projname, toolTypes, deftoolname))
             {
             printf("%s data file and icon saved.\n",projname);
             printf("Use Workbench menu Icon Information to examine the icon.\n");
             printf("Then copy this example (iconexample) to RAM:\n");
             printf("and double-click the %s project icon\n",projname);
             }
        else cleanexit("Error writing icon\n",RETURN_FAIL);
        }

    else  /* Else we are FromWb - ie. we were either
           * started by a tool icon, or as in this case,
           * by being the default tool of a project icon.
           */
        {
        if(!(conwin = fopen(conwinname,"r+")))
             cleanexit("Can't open output window\n",RETURN_FAIL);

        WBenchMsg = (struct WBStartup *)argv;

        /* Note wbarg++ at end of FOR statement steps through wbargs.
         * First arg is our executable (tool).  Any additional args
         * are projects/icons passed to us via either extend select
         * or default tool method.
         */
        for(i=0, wbarg=WBenchMsg->sm_ArgList;
            i < WBenchMsg->sm_NumArgs;
            i++, wbarg++)
            {
            /* if there's a directory lock for this wbarg, CD there */
            olddir = -1;
            if((wbarg->wa_Lock)&&(*wbarg->wa_Name))
                olddir = CurrentDir(wbarg->wa_Lock);

            showToolTypes(wbarg);

            if((i>0)&&(*wbarg->wa_Name))
                fprintf(conwin,"In Main. We could open the %s file here\n",
                                 wbarg->wa_Name);
            if(olddir != -1)  CurrentDir(olddir); /* CD back where we were */
            }
        Delay(500);
        }
    cleanup();
    exit(RETURN_OK);
    }

BOOL makeIcon(UBYTE *name, char **newtooltypes, char *newdeftool)
    {
    struct DiskObject *dobj;
    char *olddeftool;
    char **oldtooltypes;
    BOOL success = FALSE;

    if(dobj=GetDiskObject(name))
        {
        /* If file already has an icon, we will save off any fields we
         * need to update, update those fields, put the object, restore
         * the old field pointers and then free the object.  This will
         * preserve any custom imagery the user has, and the user's
         * current placement of the icon.  If your application does
         * not know where the user currently keeps your application,
         * you should not update his dobj->do_DefaultTool.
         */
         oldtooltypes = dobj->do_ToolTypes;
         olddeftool = dobj->do_DefaultTool;

         dobj->do_ToolTypes = newtooltypes;
         dobj->do_DefaultTool = newdeftool;

         success = PutDiskObject(name,dobj);

         /* we must restore the original pointers before freeing */
         dobj->do_ToolTypes = oldtooltypes;
         dobj->do_DefaultTool = olddeftool;
         FreeDiskObject(dobj);
         }
    /* Else, put our default icon */
    if(!success)  success = PutDiskObject(name,&projIcon);
    return(success);
    }

BOOL showToolTypes(struct WBArg *wbarg)
    {
    struct DiskObject *dobj;
    char **toolarray;
    char *s;
    BOOL success = FALSE;

    fprintf(conwin,"\nWBArg Lock=0x%lx, Name=%s\n",
                           wbarg->wa_Lock,wbarg->wa_Name);

    if((*wbarg->wa_Name) && (dobj=GetDiskObject(wbarg->wa_Name)))
        {
        fprintf(conwin,"  We have read the DiskObject (icon) for this arg\n");
        toolarray = (char **)dobj->do_ToolTypes;

        if(s=(char *)FindToolType(toolarray,"FILETYPE"))
            {
            fprintf(conwin,"    Found tooltype FILETYPE with value %s\n",s);
            }
        if(s=(char *)FindToolType(toolarray,"FLAGS"))
            {
            fprintf(conwin,"    Found tooltype FLAGS with value %s\n",s);
            if(MatchToolValue(s,"BOLD"))
                fprintf(conwin,"      BOLD flag requested\n");
            if(MatchToolValue(s,"ITALICS"))
                fprintf(conwin,"      ITALICS flag requested\n");
            }
        /* Free the diskobject we got */
        FreeDiskObject(dobj);
        success = TRUE;
        }
    else if(!(*wbarg->wa_Name))
        fprintf(conwin,"  Must be a disk or drawer icon\n");
    else
        fprintf(conwin,"  Can't find any DiskObject (icon) for this WBArg\n");
    return(success);
    }

/* Workbench-started programs with no output window may want to display
 * messages in a different manner (requester, window title, etc)
 */
void message(UBYTE *s)
    {
    if(FromWb && conwin)  fprintf(conwin,s,strlen(s));
    else if (!FromWb) printf(s);
    }

void cleanexit(UBYTE *s, LONG n)
    {
    if(*s)  message(s);
    cleanup();
    exit(n);
    }

void cleanup()
   {
   if(conwin)    fclose(conwin);
   if(IconBase)  CloseLibrary(IconBase);
   }


Lib_examples/prargs.c

;/* prargs.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 prargs.c
Blink FROM LIB:c.o,prargs.o LIB LIB:LC.lib,LIB:Amiga.lib TO prargs DEFINE __main=__tinymain
quit
**
** The following example will display all WBArgs if started from
** Workbench, and all Shell arguments if started from the Shell.
**
** NOTE: main and tinymain are prepended with two underscores.
**
** PrArgs.c - This program prints all Workbench or Shell (CLI) arguments.
*/
#include <exec/types.h>
#include <workbench/startup.h>
#include <clib/dos_protos.h>
#include <clib/icon_protos.h>

#include <stdlib.h>
#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }   /* Disable SAS Lattice CTRL/C handling */
int chkabort(void) { return(0); }/* really */
#endif

void main(int argc, char **argv)
{
struct WBStartup *argmsg;
struct WBArg *wb_arg;
LONG ktr;
BPTR olddir;
FILE *outFile;

/* argc is zero when run from the Workbench,
**         positive when run from the CLI.
*/
if (argc == 0)
    {
    /* AmigaDOS has a special facility that  allows a window  */
    /* with a console and a file handle to be easily created. */
    /* CON: windows allow you to use fprintf() with no hassle */
    if (NULL != (outFile = fopen("CON:0/0/640/200/PrArgs","r+")))
        {
        /* in SAS/Lattice, argv is a pointer to the WBStartup message
        ** when argc is zero.  (run under the Workbench.)
        */
        argmsg = (struct WBStartup *)argv ;
        wb_arg = argmsg->sm_ArgList ;         /* head of the arg list */

        fprintf(outFile, "Run from the workbench, %ld args.\n",
                         argmsg->sm_NumArgs);

        for (ktr = 0; ktr < argmsg->sm_NumArgs; ktr++, wb_arg++)
            {
            if (NULL != wb_arg->wa_Lock)
                {
                /* locks supported, change to the proper directory */
                olddir = CurrentDir(wb_arg->wa_Lock) ;

                /* process the file.
                ** If you have done the CurrentDir() above, then you can
                ** access the file by its name.  Otherwise, you have to
                ** examine the lock to get a complete path to the file.
                */
                fprintf(outFile, "\tArg %2.2ld (w/ lock): '%s'.\n",
                                 ktr, wb_arg->wa_Name);

                /* change back to the original directory when done.
                ** be sure to change back before you exit.
                */
                CurrentDir(olddir) ;
                }
            else
                {
                /* something that does not support locks */
                fprintf(outFile, "\tArg %2.2ld (no lock): '%s'.\n",
                                 ktr, wb_arg->wa_Name);
                }
            }
        /* wait before closing down */
        Delay(500L);
        fclose(outFile);
        }
    }
else
    {
    /* using 'tinymain' from lattice c.
    ** define a place to send the output (originating CLI window = "*")
    ** Note - if you open "*" and your program is RUN, the user will not
    ** be able to close the CLI window until you close the "*" file.
    */
    if (NULL != (outFile = fopen("*","r+")))
        {
        fprintf(outFile, "Run from the CLI, %d args.\n", argc);

        for ( ktr = 0; ktr < argc; ktr++)
            {
            /* print an arg, and its number */
            fprintf(outFile, "\tArg %2.2ld: '%s'.\n", ktr, argv[ktr]);
            }
        fclose(outFile);
        }
    }
}


Lib_examples/hooks1.c

;/* hooks1.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfis -j73 hooks1.c
Blink FROM LIB:c.o,hooks1.o TO hooks1 LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
*/

    #include <exec/types.h>
    #include <exec/libraries.h>
    #include <utility/hooks.h>
    #include <dos.h>

    #include <clib/exec_protos.h>
    #include <clib/dos_protos.h>
    #include <clib/utility_protos.h>

    #include <stdio.h>

    extern struct Library *SysBase;
    struct Library *UtilityBase;

    #define ASM     __asm
    #define REG(x)  register __ ## x

    /* This function converts register-parameter Hook calling
     * convention into standard C conventions.  It requires a C
     * compiler that supports registerized parameters, such as
     * SAS/C 5.xx or greater.
     */

    ULONG ASM
    hookEntry(REG(a0) struct Hook *h, REG(a2) VOID *o, REG(a1) VOID *msg)
    {
        return ((*(ULONG (*)(struct Hook *,VOID *,VOID *))(h->h_SubEntry))(h, o, msg));
    }

    /* This simple function is used to initialize a Hook */
    VOID InitHook (struct Hook *h, ULONG (*func)(), VOID *data)
    {
        /* Make sure a pointer was passed */
        if (h)
        {
            /* Fill in the Hook fields */
            h->h_Entry = (ULONG (*)()) hookEntry;
            h->h_SubEntry = func;
            h->h_Data = data;
        }
    }

    /* This function only prints out a message indicating that we are
     * inside the callback function.
     */

    ULONG MyFunction (struct Hook *h, VOID *o, VOID *msg)
    {
        /* Obtain access to the global data segment */
        geta4();

        /* Debugging function to send a string to the serial port */
        printf("Inside MyFunction()\n");

        return (1);
    }

    int main (int argc, char **argv)
    {
        struct Hook h;

        /* Open the utility library */
        if (UtilityBase = OpenLibrary ("utility.library", 36))
        {
            /* Initialize the callback Hook */
            InitHook (&h, MyFunction, NULL);

            /* Use the utility library function to invoke the Hook */
            CallHookPkt (&h, NULL, NULL);

            /* Close utility library now that we're done with it */
            CloseLibrary (UtilityBase);
        }
        else printf ("Couldn't open utility.library\n");
    }


Lib_examples/clipping.c

/* The following example shows the use of the layers library call
** InstallClipRegion(), as well as simple use of the graphics library
** regions functions. Be aware that it uses Release 2 functions for
** opening and closing Intuition windows.
**
** clipping.c
**
** SAS/C 5.10a
** lc -b1 -cfist -v -y clipping
** blink FROM LIB:c.o clipping.o TO clipping LIB LIB:lc.lib LIB:amiga.lib
*/

/* Force use of new variable names to help prevent errors */
#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <graphics/displayinfo.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/layers_protos.h>

#include <stdio.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

#define MY_WIN_WIDTH  (300)
#define MY_WIN_HEIGHT (100)

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Library *LayersBase;

/*
** unclipWindow()
**
** Used to remove a clipping region installed by clipWindow() or
** clipWindowToBorders(), disposing of the installed region and
** reinstalling the region removed.
*/
void unclipWindow(struct Window *win)
{
struct Region     *old_region;

/* Remove any old region by installing a NULL region,
** then dispose of the old region if one was installed.
*/
if (NULL != (old_region = InstallClipRegion(win->WLayer, NULL)))
    DisposeRegion(old_region);
}

/*
** clipWindow()
** Clip a window to a specified rectangle (given by upper left and
** lower right corner.)  the removed region is returned so that it
** may be re-installed later.
*/
struct Region *clipWindow(struct Window *win,
    LONG minX, LONG minY, LONG maxX, LONG maxY)
{
struct Region    *new_region;
struct Rectangle  my_rectangle;

/* set up the limits for the clip */
my_rectangle.MinX = minX;
my_rectangle.MinY = minY;
my_rectangle.MaxX = maxX;
my_rectangle.MaxY = maxY;

/* get a new region and OR in the limits. */
if (NULL != (new_region = NewRegion()))
    {
    if (FALSE == OrRectRegion(new_region, &my_rectangle))
        {
        DisposeRegion(new_region);
        new_region = NULL;
        }
    }

/* Install the new region, and return any existing region.
** If the above allocation and region processing failed, then
** new_region will be NULL and no clip region will be installed.
*/
return(InstallClipRegion(win->WLayer, new_region));
}

/*
** clipWindowToBorders()
** clip a window to its borders.
** The removed region is returned so that it may be re-installed later.
*/
struct Region *clipWindowToBorders(struct Window *win)
{
return(clipWindow(win, win->BorderLeft, win->BorderTop,
    win->Width - win->BorderRight - 1, win->Height - win->BorderBottom - 1));
}

/*
** Wait for the user to select the close gadget.
*/
VOID wait_for_close(struct Window *win)
{
struct IntuiMessage *msg;
SHORT done;

done = FALSE;
while (FALSE == done)
    {
    /* we only have one signal bit, so we do not have to check which
    ** bit broke the Wait().
    */
    Wait(1L << win->UserPort->mp_SigBit);

    while ( (FALSE == done) &&
            (NULL != (msg = (struct IntuiMessage *)GetMsg(win->UserPort))))
        {
        /* use a switch statement if looking for multiple event types */
        if (msg->Class == IDCMP_CLOSEWINDOW)
            done = TRUE;

        ReplyMsg((struct Message *)msg);
        }
    }
}

/*
** Simple routine to blast all bits in a window with color three to show
** where the window is clipped.  After a delay, flush back to color zero
** and refresh the window borders.
*/
VOID draw_in_window(struct Window *win, UBYTE *message)
{
printf("%s...", message); fflush(stdout);
SetRast(win->RPort, 3);
Delay(200);
SetRast(win->RPort, 0);
RefreshWindowFrame(win);
printf("done\n");
}

/*
** Show drawing into an unclipped window, a window clipped to the
** borders and a window clipped to a random rectangle.  It is possible
** to clip more complex shapes by AND'ing, OR'ing and exclusive-OR'ing
** regions and rectangles to build a user clip region.
**
** This example assumes that old regions are not going to be re-used,
** so it simply throws them away.
*/
VOID clip_test(struct Window *win)
{
struct Region    *old_region;

draw_in_window(win,"Window with no clipping");

/* if the application has never installed a user clip region,
** then old_region will be NULL here.  Otherwise, delete the
** old region (you could save it and re-install it later...)
*/
if (NULL != (old_region = clipWindowToBorders(win)))
    DisposeRegion(old_region);
draw_in_window(win,"Window clipped to window borders");
unclipWindow(win);

/* here we know old_region will be NULL, as that is what we
** installed with unclipWindow()...
*/
if (NULL != (old_region = clipWindow(win,20,20,100,50)))
    DisposeRegion(old_region);
draw_in_window(win,"Window clipped from (20,20) to (100,50)");
unclipWindow(win);

wait_for_close(win);
}

/*
** Open and close resources, call the test routine when ready.
*/
VOID main(int argc, char **argv)
{
struct Window *win;

if (NULL != (IntuitionBase =
        (struct IntuitionBase *)OpenLibrary("intuition.library",37)))
    {
    if (NULL != (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",37)))
        {
        if (NULL != (LayersBase = OpenLibrary("layers.library",37)))
            {
            if (NULL != (win = OpenWindowTags(NULL,
                                WA_Width,       MY_WIN_WIDTH,
                                WA_Height,      MY_WIN_HEIGHT,
                                WA_IDCMP,       IDCMP_CLOSEWINDOW,
                                WA_CloseGadget, TRUE,
                                WA_DragBar,     TRUE,
                                WA_Activate,    TRUE,
                                TAG_END)))
                {
                clip_test(win);

                CloseWindow(win);
                }
            CloseLibrary(LayersBase);
            }
        CloseLibrary((struct Library *)GfxBase);
        }
    CloseLibrary((struct Library *)IntuitionBase);
    }
}


Lib_examples/istr.c

;/* istr.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfis -j73 istr.c
Blink FROM LIB:c.o,istr.o TO istr LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
*/

    #include <exec/types.h>
    #include <stdio.h>
    #include <string.h>

    #include <clib/exec_protos.h>
    #include <clib/utility_protos.h>

    void main(void);
    struct Library *UtilityBase;

    void main(void)
    {
        UBYTE *butter = "Bøtervløøt";
        UBYTE *bread = "Knåckerbrøt";
        UBYTE ch1, ch2;
        LONG result;

        /* Fails silently if < 37 */
        if (UtilityBase = OpenLibrary("utility.library", 37))
        {
                result = Stricmp(butter, bread);

                printf("comparing %s with %s yields %ld\n", butter, bread, result );

                result = Strnicmp(bread, butter, strlen(bread));

                printf("comparing (with length) %s with %s yields %ld\n", bread, butter, result );

                ch1 = ToUpper(0xE6); æ /* ASCII character 230 ae ligature */
                ch2 = ToLower(0xD0); Ð /* ASCII character 208 Icelandic Eth */

                printf("Chars %c %c\n", ch1, ch2);
        }
    }


Lib_examples/Layers.c

/* For the sake of brevity, the example is a single task.  No Layer
** locking is done.  Also note that the routine myLabelLayer() is used
** to redraw a given layer.  It is called only when a layer needs
** refreshing.
**
** Layers.c
**
** SAS/C 5.10a
** lc -b1 -cfist -v -y layers
** blink FROM LIB:c.o layers.o TO layers LIB LIB:lc.lib LIB:amiga.lib
*/

/* Force use of new variable names to help prevent errors */
#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <graphics/gfxbase.h>
#include <graphics/layers.h>
#include <graphics/displayinfo.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/graphics_protos.h>
#include <clib/layers_protos.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

#define L_DELAY  (100)
#define S_DELAY   (50)

#define DUMMY      (0L)

#define RED_PEN    (1)
#define GREEN_PEN  (2)
#define BLUE_PEN   (3)

#define SCREEN_D   (2)
#define SCREEN_W (320)
#define SCREEN_H (200)

/* the starting size of example layers, offsets are used for placement */
#define W_H (50)
#define W_T (5)
#define W_B ((W_T+W_H)-1)
#define W_W (80)
#define W_L ((SCREEN_W/2) - (W_W/2))
#define W_R ((W_L+W_W)-1)

/* size of the superbitmap */
#define SUPER_H SCREEN_H
#define SUPER_W SCREEN_W

/* starting size of the message layer */
#define M_H (10)
#define M_T (SCREEN_H-M_H)
#define M_B ((M_T+M_H)-1)
#define M_W (SCREEN_W)
#define M_L (0)
#define M_R ((M_L+M_W)-1)

struct GfxBase *GfxBase;
struct Library *LayersBase;

/* global constant data for initializing the layers */
LONG  theLayerFlags[3] = { LAYERSUPER, LAYERSMART, LAYERSIMPLE };
UWORD colortable[]     = { 0x000, 0xf44, 0x4f4, 0x44f };

/*
** Clear the layer then draw in a text string.
*/
VOID myLabelLayer(struct Layer *layer, LONG color, UBYTE *string)
{
/* fill layer with color */
SetRast(layer->rp, color);

/* set up for writing text into layer */
SetDrMd(layer->rp,JAM1);
SetAPen(layer->rp,0);
Move(layer->rp, 5, 7);

/* write into layer */
Text(layer->rp, string, strlen(string));
}

/*
** write a message into a layer with a delay.
*/
VOID pMessage(struct Layer *layer, UBYTE *string)
{
Delay(S_DELAY);
myLabelLayer(layer, GREEN_PEN, string);
}

/*
** write an error message into a layer with a delay.
*/
VOID error(struct Layer *layer, UBYTE *string)
{
myLabelLayer(layer, RED_PEN, string);
Delay(L_DELAY);
}

/*
** do some layers manipulations to demonstrate their abilities.
*/
VOID doLayers(struct Layer *msgLayer, struct Layer *layer_array[])
{
WORD ktr;
WORD ktr_2;

pMessage(msgLayer, "Label all Layers");
myLabelLayer(layer_array[0], RED_PEN,   "Super");
myLabelLayer(layer_array[1], GREEN_PEN, "Smart");
myLabelLayer(layer_array[2], BLUE_PEN,  "Simple");

pMessage(msgLayer, "MoveLayer 1 InFrontOf 0");
if (!MoveLayerInFrontOf(layer_array[1], layer_array[0]))
    error(msgLayer, "MoveLayerInFrontOf() failed.");

pMessage(msgLayer, "MoveLayer 2 InFrontOf 1");
if (!MoveLayerInFrontOf(layer_array[2], layer_array[1]))
    error(msgLayer, "MoveLayerInFrontOf() failed.");

pMessage(msgLayer, "Refresh Simple Refresh Layer");
myLabelLayer(layer_array[2], BLUE_PEN, "Simple");

pMessage(msgLayer, "Incrementally MoveLayers...");
for(ktr = 0; ktr < 30; ktr++)
    {
    if (!MoveLayer(DUMMY, layer_array[1], -1, 0))
        error(msgLayer, "MoveLayer() failed.");
    if (!MoveLayer(DUMMY, layer_array[2], -2, 0))
        error(msgLayer, "MoveLayer() failed.");
    }

pMessage(msgLayer, "Refresh Simple Refresh Layer");
myLabelLayer(layer_array[2], BLUE_PEN, "Simple");

pMessage(msgLayer, "make Layer 0 the UpfrontLayer");
if (!UpfrontLayer(DUMMY, layer_array[0]))
    error(msgLayer, "UpfrontLayer() failed.");

pMessage(msgLayer, "make Layer 2 the BehindLayer");
if (!BehindLayer(DUMMY, layer_array[2]))
    error(msgLayer, "BehindLayer() failed.");

pMessage(msgLayer, "Incrementally MoveLayers again...");
for(ktr = 0; ktr < 30; ktr++)
    {
    if (!MoveLayer(DUMMY, layer_array[1], 0, 1))
        error(msgLayer, "MoveLayer() failed.");
    if (!MoveLayer(DUMMY, layer_array[2], 0, 2))
        error(msgLayer, "MoveLayer() failed.");
    }

pMessage(msgLayer, "Refresh Simple Refresh Layer");
myLabelLayer(layer_array[2], BLUE_PEN, "Simple");

pMessage(msgLayer, "Big MoveLayer");
for(ktr = 0; ktr < 3; ktr++)
    {
    if (!MoveLayer(DUMMY, layer_array[ktr], -layer_array[ktr]->bounds.MinX, 0))
        error(msgLayer, "MoveLayer() failed.");
    }

pMessage(msgLayer, "Incrementally increase size");
for(ktr = 0; ktr < 5; ktr++)
    {
    for(ktr_2 = 0; ktr_2 < 3; ktr_2++)
        {
        if (!SizeLayer(DUMMY, layer_array[ktr_2], 1, 1))
            error(msgLayer, "SizeLayer() failed.");
        }
    }

pMessage(msgLayer, "Refresh Smart Refresh Layer");
myLabelLayer(layer_array[1], GREEN_PEN, "Smart");
pMessage(msgLayer, "Refresh Simple Refresh Layer");
myLabelLayer(layer_array[2], BLUE_PEN,  "Simple");

pMessage(msgLayer, "Big SizeLayer");
for(ktr = 0; ktr < 3; ktr++)
    {
    if (!SizeLayer(DUMMY,layer_array[ktr],
                SCREEN_W-(layer_array[ktr]->bounds.MaxX)-1,0))
        error(msgLayer, "SizeLayer() failed.");
    }

pMessage(msgLayer, "Refresh Smart Refresh Layer");
myLabelLayer(layer_array[1], GREEN_PEN, "Smart");
pMessage(msgLayer, "Refresh Simple Refresh Layer");
myLabelLayer(layer_array[2], BLUE_PEN,  "Simple");

pMessage(msgLayer, "ScrollLayer down");
for(ktr = 0; ktr < 30; ktr++)
    {
    for(ktr_2 = 0; ktr_2 < 3; ktr_2++)
        {
        ScrollLayer(DUMMY, layer_array[ktr_2], 0, -1);
        }
    }

pMessage(msgLayer, "Refresh Smart Refresh Layer");
myLabelLayer(layer_array[1], GREEN_PEN, "Smart");
pMessage(msgLayer, "Refresh Simple Refresh Layer");
myLabelLayer(layer_array[2], BLUE_PEN,  "Simple");

pMessage(msgLayer, "ScrollLayer up");
for(ktr = 0; ktr < 30; ktr++)
    {
    for(ktr_2 = 0; ktr_2 < 3; ktr_2++)
        {
        ScrollLayer(DUMMY, layer_array[ktr_2], 0, 1);
        }
    }

pMessage(msgLayer, "Refresh Smart Refresh Layer");
myLabelLayer(layer_array[1], GREEN_PEN, "Smart");
pMessage(msgLayer, "Refresh Simple Refresh Layer");
myLabelLayer(layer_array[2], BLUE_PEN,  "Simple");

Delay(L_DELAY);
}

/*
** delete the layer array created by allocLayers().
*/
VOID disposeLayers(struct Layer *msgLayer, struct Layer *layer_array[])
{
WORD ktr;

for (ktr = 0; ktr < 3; ktr++)
    {
    if (layer_array[ktr] != NULL)
        {
        if (!DeleteLayer(DUMMY, layer_array[ktr]))
            error(msgLayer, "Error deleting layer");
        }
    }
}

/*
** Create some hard-coded layers.  The first must be super-bitmap, with
** the bitmap passed as an argument.  The others must not be super-bitmap.
** The pointers to the created layers are returned in layer_array.
**
** Return FALSE on failure.  On a FALSE return, the layers are
** properly cleaned up.
*/
BOOL allocLayers(struct Layer *msgLayer, struct Layer *layer_array[],
    struct BitMap *super_bitmap, struct Layer_Info *theLayerInfo,
    struct BitMap *theBitMap)
{
WORD ktr;
BOOL create_layer_ok = TRUE;

for (ktr = 0;
     (ktr < 3) && (create_layer_ok);
     ktr++)
    {
    pMessage(msgLayer, "Create BehindLayer");
    if (ktr == 0)
        {
        if ((layer_array[ktr] = CreateBehindLayer(theLayerInfo, theBitMap,
                  W_L+(ktr*30), W_T+(ktr*30), W_R+(ktr*30), W_B+(ktr*30),
                  theLayerFlags[ktr], super_bitmap)) == NULL)
            create_layer_ok = FALSE;
        }
     else
        {
        if ((layer_array[ktr] = CreateBehindLayer(theLayerInfo, theBitMap,
                  W_L+(ktr*30), W_T+(ktr*30), W_R+(ktr*30), W_B+(ktr*30),
                  theLayerFlags[ktr], NULL)) == NULL)
            create_layer_ok = FALSE;
        }

    if (create_layer_ok)
        {
        pMessage(msgLayer, "Fill the RastPort");
        SetRast(layer_array[ktr]->rp, ktr + 1);
        }
    }

if (!create_layer_ok)
    disposeLayers(msgLayer, layer_array);

return(create_layer_ok);
}

/*
** Free the bitmap and all bitplanes created by allocBitMap().
*/
VOID disposeBitMap(struct BitMap *bitmap, LONG depth, LONG width, LONG height)
{
WORD ktr;

if (NULL != bitmap)
    {
    for (ktr = 0; ktr < depth; ktr++)
        {
        if (NULL != bitmap->Planes[ktr])
            FreeRaster(bitmap->Planes[ktr], width, height);
        }

    FreeMem(bitmap, sizeof(*bitmap));
    }
}

/*
** Allocate and initialize a bitmap structure.
*/
struct BitMap *allocBitMap(LONG depth, LONG width, LONG height)
{
WORD ktr;
BOOL bit_map_failed = FALSE;
struct BitMap *bitmap = NULL;

if (NULL != (bitmap = AllocMem(sizeof(*bitmap),NULL)))
    {
    InitBitMap(bitmap,depth,width,height);

    for (ktr = 0; ktr < depth; ktr++)
        {
        if (NULL == (bitmap->Planes[ktr] = (PLANEPTR)AllocRaster(width,height)))
            bit_map_failed = TRUE;
        else
            BltClear(bitmap->Planes[ktr], RASSIZE(width,height), 1);
        }
    if (bit_map_failed)
        {
        disposeBitMap(bitmap,depth,width,height);
        bitmap = NULL;
        }
    }
return(bitmap);
}

/*
** Set up to run the layers example, doLayers(). Clean up when done.
*/
VOID startLayers(struct Layer_Info *theLayerInfo, struct BitMap *theBitMap)
{
struct Layer  *msgLayer;
struct BitMap *theSuperBitMap;
struct Layer  *theLayers[3] = { NULL, NULL, NULL, };

if (NULL != (msgLayer = CreateUpfrontLayer(theLayerInfo, theBitMap,
                     M_L, M_T, M_R, M_B, LAYERSMART, NULL)))
    {
    pMessage(msgLayer, "Setting up Layers");

    if (NULL != (theSuperBitMap = allocBitMap(SCREEN_D, SUPER_W, SUPER_H)))
        {
        if (allocLayers(msgLayer, theLayers, theSuperBitMap, theLayerInfo, theBitMap))
            {
            doLayers(msgLayer, theLayers);

            disposeLayers(msgLayer, theLayers);
            }
        disposeBitMap(theSuperBitMap, SCREEN_D, SUPER_W, SUPER_H);
        }
    if (!DeleteLayer(DUMMY, msgLayer))
        error(msgLayer, "Error deleting layer");
    }
}

/*
** Set up a low-level graphics display for layers to work on.  Layers
** should not be built directly on Intuition screens, use a low-level
** graphics view.  If you need mouse or other events for the layers
** display, you have to get them directly from the input device.  The
** only supported method of using layers library calls with Intuition
** (other than the InstallClipRegion() call) is through Intuition windows.
**
** See graphics primitives chapter for details on creating and using the
** low-level graphics calls.
*/
VOID runNewView(VOID)
{
struct View        theView;
struct View       *oldview;
struct ViewPort    theViewPort;
struct RasInfo     theRasInfo;
struct ColorMap   *theColorMap;
struct Layer_Info *theLayerInfo;
struct BitMap     *theBitMap;
UWORD             *colorpalette;
WORD               ktr;

/* save current view, to be restored when done */
if (NULL != (oldview = GfxBase->ActiView))
    {
    /* get a LayerInfo structure */
    if (NULL != (theLayerInfo = NewLayerInfo()))
        {
        if (NULL != (theColorMap = GetColorMap(4)))
            {
            colorpalette = (UWORD *)theColorMap->ColorTable;
            for(ktr = 0; ktr < 4; ktr++)
                *colorpalette++ = colortable[ktr];

            if (NULL != (theBitMap = allocBitMap(SCREEN_D, SCREEN_W, SCREEN_H)))
                {
                InitView(&theView);
                InitVPort(&theViewPort);

                theView.ViewPort = &theViewPort;

                theViewPort.DWidth   = SCREEN_W;
                theViewPort.DHeight  = SCREEN_H;
                theViewPort.RasInfo  = &theRasInfo;
                theViewPort.ColorMap = theColorMap;

                theRasInfo.BitMap   = theBitMap;
                theRasInfo.RxOffset = 0;
                theRasInfo.RyOffset = 0;
                theRasInfo.Next     = NULL;

                MakeVPort(&theView, &theViewPort);
                MrgCop(&theView);
                LoadView(&theView);
                WaitTOF();

                startLayers(theLayerInfo, theBitMap);

                /* put back the old view, wait for it to become
                ** active before freeing any of our display
                */
                LoadView(oldview);
                WaitTOF();

                /* free dynamically created structures */
                FreeVPortCopLists(&theViewPort);
                FreeCprList(theView.LOFCprList);

                disposeBitMap(theBitMap, SCREEN_D, SCREEN_W, SCREEN_H);
                }
            FreeColorMap(theColorMap);       /* free the color map */
            }
        DisposeLayerInfo(theLayerInfo);
        }
    }
}

/*
** Open the libraries used by the example.  Clean up when done.
*/
VOID main(int argc, char **argv)
{
if (NULL != (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",33L)))
    {
    if (NULL != (LayersBase = OpenLibrary("layers.library",33L)))
        {
        runNewView();

        CloseLibrary((struct Library *)LayersBase);
        }
    CloseLibrary((struct Library *)GfxBase);
    }
}


Lib_examples/tag1.c

;/* tag1.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfis -j73 tag1.c
Blink FROM LIB:c.o,tag1.o TO tag1 LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
**
** The following example shows simple usage of tags.  It shows how to
** allocate a tag array and use it, it also shows how to build a tag
** array on the stack.
*/

#include <exec/types.h>
#include <exec/libraries.h>
#include <utility/tagitem.h>
#include <intuition/intuition.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/utility_protos.h>

extern struct Library *SysBase;
struct Library *IntuitionBase, *UtilityBase;

int main (int argc, char **argv)
{
    struct TagItem *tags;
    struct Window  *win;

    /* For this example we need Version 2.0 */
    if (IntuitionBase = OpenLibrary ("intuition.library", 37))
    {
        /* We need the utility library for this example */
        if (UtilityBase = OpenLibrary ("utility.library", 37))
        {

        /****************************************************************/
        /* This section allocates a tag array, fills it in with values, */
        /* and then uses it.                                            */
        /****************************************************************/

            /* Allocate a tag array */
            if (tags = AllocateTagItems (7))
            {
                /* Fill in our tag array */
                tags[0].ti_Tag = WA_Width;
                tags[0].ti_Data = 320;
                tags[1].ti_Tag = WA_Height;
                tags[1].ti_Data = 50;
                tags[2].ti_Tag = WA_Title;
                tags[2].ti_Data = (ULONG) "RKM Tag Example 1";
                tags[3].ti_Tag = WA_IDCMP;
                tags[3].ti_Data = IDCMP_CLOSEWINDOW;
                tags[4].ti_Tag = WA_CloseGadget;
                tags[4].ti_Data = TRUE;
                tags[5].ti_Tag = WA_DragBar;
                tags[5].ti_Data = TRUE;
                tags[6].ti_Tag = TAG_DONE;

                /* Open the window, using the tag attributes as the
                 * only description. */
                if (win = OpenWindowTagList (NULL, tags))
                {
                    /* Wait for an event to occur */
                    WaitPort (win->UserPort);

                    /* Close the window now that we're done with it */
                    CloseWindow (win);
                }

                /* Free the tag list now that we're done with it */
                FreeTagItems(tags);
            }

        /****************************************************************/
        /* This section builds the tag array on the stack, and passes   */
        /* the array to a function.                                     */
        /****************************************************************/

            /* Now use the VarArgs (or stack based) version. */
            if (win = OpenWindowTags ( NULL,
                                       WA_Width, 320,
                                       WA_Height, 50,
                                       WA_Title, (ULONG)"RKM Tag Example 1",
                                       WA_IDCMP, IDCMP_CLOSEWINDOW,
                                       WA_CloseGadget, TRUE,
                                       WA_DragBar, TRUE,
                                       TAG_DONE))
            {
                /* Wait for an event to occur */
                WaitPort (win->UserPort);

                /* Close the window now that we're done with it */
                CloseWindow (win);
            }

            /* Close the library now */
            CloseLibrary (UtilityBase);
        }

        /* Close the library now that we're done with it */
        CloseLibrary (IntuitionBase);
    }
}


lib_examples/newlookscreen.c

/* newlookscreen.c
** open a screen with the "new look".
**
** SAS/C 5.10a
** lc -b1 -cfist -v -y newlookscreen
** blink LIB:c.o newlookscreen.o TO newlookscreen LIB LIB:lc.lib LIB:amiga.lib
*/

#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/screens.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

struct Library *IntuitionBase;

/* Simple routine to demonstrate opening a screen with the new look.
** Simply supply the tag SA_Pens along with a minimal pen specification,
** Intuition will fill in all unspecified values with defaults.
** Since we are not supplying values, all are Intuition defaults.
*/
VOID main(int argc, char **argv)
{
UWORD pens[] = { ~0 };
struct Screen *my_screen;

IntuitionBase = OpenLibrary("intuition.library",0);
if (NULL != IntuitionBase)
    {
    if (IntuitionBase->lib_Version >= 37)
        {
        /* The screen is opened two bitplanes deep so that the
        ** new look will show-up better.
        */
        if (NULL != (my_screen = OpenScreenTags(NULL,
                                     SA_Pens, (ULONG)pens,
                                     SA_Depth, 2,
                                     TAG_DONE)))
            {
            /* screen successfully opened */
            Delay(30L);  /* normally the program would be here */

            CloseScreen(my_screen);
            }
        }
    CloseLibrary(IntuitionBase);
    }
}


lib_examples/screen34to37.c

;/* screen34to37.c - Execute me to compile me with SAS 5.10
LC -b1 -cfistq -v -y -j73 screen34to37.c
blink FROM LIB:c.o screen34to37.o TO screen34to37 LIB LIB:lc.lib LIB:amiga.lib
quit
*/

#define INTUI_V36_NAMES_ONLY         /* We'll use the newer Intuition names. */

#include <exec/types.h>              /* Amiga data types.              */
#include <intuition/intuition.h>     /* Lots of important Intuition    */
#include <intuition/screens.h>       /* structures we will be using.   */

#include <clib/exec_protos.h>        /* Function prototypes            */
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }    /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }    /* really */
#endif

struct Library *IntuitionBase;       /* Intuition library base          */

/* Simple example to show how to open a custom screen that gives the new look
 * under V37, yet still works with older version of the operating system.
 * Attach the tag SA_Pens and a minimal pen specification to ExtNewScreen,
 * and call the old OpenScreen() function.  The tags will be ignored by
 * V34 and earlier versions of the OS.  In V36 and later the tags are
 * accepted by Intuition.
*/

VOID main(int argc, char **argv)
{
UWORD pens[] = { ~0 };               /* This is the minimal pen specification*/
struct Screen      *my_screen;       /* Pointer to our new, custom screen    */
struct ExtNewScreen myscreen_setup;  /* Same as NewScreen with tags attached */
struct TagItem      myscreen_tags[2];/* A small tag array                    */

/* Open the library before you call any functions */
IntuitionBase = OpenLibrary("intuition.library",0);
if (NULL != IntuitionBase)
   {
      /* Fill in the tag list with the minimal pen specification */
      myscreen_tags[0].ti_Tag=SA_Pens;
      myscreen_tags[0].ti_Data=(ULONG) pens;
      myscreen_tags[1].ti_Tag=TAG_DONE;

      /* The screen is opened two bitplanes deep so that the
      ** new look will show-up better.
      **/
      myscreen_setup.LeftEdge=0;
      myscreen_setup.TopEdge=0;
      myscreen_setup.Width=640;              /* Smaller values here reduce   */
      myscreen_setup.Height=STDSCREENHEIGHT; /* drawing area and save memory.*/
      myscreen_setup.Depth=2;                /* Two planes means 4 colors.   */
      myscreen_setup.DetailPen=0;            /* Normal V34 pen colors.       */
      myscreen_setup.BlockPen=1;
      myscreen_setup.ViewModes=HIRES;
      myscreen_setup.Type=CUSTOMSCREEN | NS_EXTENDED; /* Extended NewScreen flag */
      myscreen_setup.Font=NULL;
      myscreen_setup.DefaultTitle="My Screen";
      myscreen_setup.Gadgets=NULL;
      myscreen_setup.CustomBitMap=NULL;
      /* Attach the pen specification tags to the ExtNewScreen structure */
      myscreen_setup.Extension=myscreen_tags;

      if (NULL != (my_screen =
        OpenScreen((struct NewScreen *)&myscreen_setup)));
          {
          /* screen successfully opened */

          Delay(200L);  /* normally the program would be here */

          CloseScreen(my_screen);
          }
      CloseLibrary(IntuitionBase);
   }
}


devices/modules/screen.c

/* screen.c - 2.0 screen module for Display
 * based on scdemo, oscandemo, looki
 */

/*
Copyright (c) 1989-1999 Amiga, Inc.

Executables based on this information may be used in software
for Amiga computers. All other rights reserved.
This information is provided "as is"; no warranties are made.
All use is at your own risk, and no liability or responsibility
is assumed.
*/

#include "iffp/ilbmapp.h"

BOOL   VideoControlTags(struct ColorMap *,ULONG tags, ...);

extern struct Library *GfxBase;
extern struct Library *IntuitionBase;

struct TextAttr SafeFont = { (UBYTE *) "topaz.font", 8, 0, 0, };
UWORD  penarray[] = {~0};

/* default new window if none supplied in ilbm->nw */
struct   NewWindow      defnw = {
   0, 0,                                  /* LeftEdge and TopEdge */
   0, 0,                          	  /* Width and Height */
   -1, -1,                                /* DetailPen and BlockPen */
   VANILLAKEY|MOUSEBUTTONS,               /* IDCMP Flags with Flags below */
   BACKDROP|BORDERLESS|SMART_REFRESH|NOCAREREFRESH|ACTIVATE|RMBTRAP,
   NULL, NULL,                            /* Gadget and Image pointers */
   NULL,                                  /* Title string */
   NULL,                                  /* Screen ptr null till opened */
   NULL,                                  /* BitMap pointer */
   50, 20,                                /* MinWidth and MinHeight */
   0 , 0,                                 /* MaxWidth and MaxHeight */
   CUSTOMSCREEN                           /* Type of window */
   };

/* opendisplay - passed ILBMInfo, dimensions, modeID
 *
 *    Attempts to open correct 2.0 modeID screen and window,
 *    else an old 1.3 mode screen and window.
 *
 * Returns *window or NULL.
 */

struct Window *opendisplay(struct ILBMInfo *ilbm,
               SHORT wide, SHORT high, SHORT deep,
               ULONG mode)
    {
    struct NewWindow newwin, *nw;

    closedisplay(ilbm);
    if(ilbm->scr = openidscreen(ilbm, wide, high, deep, mode))
    {
    nw = &newwin;
    if(ilbm->windef) *nw = *(ilbm->windef);
    else *nw = *(&defnw);
    nw->Screen	= ilbm->scr;

    D(bug("sizes: scr= %ld x %ld  passed= %ld x %ld\n",
        ilbm->scr->Width,ilbm->scr->Height,wide,high));

    nw->Width	= wide;
    nw->Height	= high;
    if (!(ilbm->win = OpenWindow(nw)))
        {
        closedisplay(ilbm);
        D(bug("Failed to open window."));
        }
    else
        {
        if(ilbm->win->Flags & BACKDROP)
        {
        ShowTitle(ilbm->scr, FALSE);
        ilbm->TBState = FALSE;
        }
        }
    }

    if(ilbm->scr)	/* nulled out by closedisplay if OpenWindow failed */
    {
    ilbm->vp  = &ilbm->scr->ViewPort;
    ilbm->srp = &ilbm->scr->RastPort;
    ilbm->wrp = ilbm->win->RPort;
    }
    return(ilbm->win);
    }

void closedisplay(struct ILBMInfo *ilbm)
    {
    if(ilbm)
    {
        if (ilbm->win)	CloseWindow(ilbm->win), ilbm->win = NULL;
        if (ilbm->scr)	CloseScreen(ilbm->scr), ilbm->scr = NULL;
        ilbm->vp  = NULL;
        ilbm->srp = ilbm->wrp = NULL;
    }
    }

/* openidscreen - ILBMInfo, dimensions, modeID
 *
 *    Attempts to open correct 2.0 modeID screen with centered
 *    overscan based on user's prefs,
 *    else old 1.3 mode screen.
 *
 * If ilbm->stype includes CUSTOMBITMAP, ilbm->brbitmap will be
 *   	used as the screen's bitmap.
 * If ilbm->stags is non-NULL, these tags will be added to the
 *	end of the taglist.
 *
 * Returns *screen or NULL.
 */

struct Screen *openidscreen(struct ILBMInfo *ilbm,
                SHORT wide, SHORT high, SHORT deep,
                ULONG mode)
    {
    struct NewScreen ns;			/* for old style OpenScreen */
    struct Rectangle spos, dclip, txto, stdo, maxo, uclip;  /* display rectangles */
    struct Rectangle *uclipp;
    struct Screen   *scr = NULL;
    LONG   error, trynew;
    ULONG  bitmaptag, passedtags;
    BOOL   vctl;

    if (trynew = ((((struct Library *)GfxBase)->lib_Version >= 36)&&
          (((struct Library *)IntuitionBase)->lib_Version >= 36)))
    {
        /* if >= v36, see if mode is available */
    if(error = ModeNotAvailable(mode))
        {
        D(bug("Mode $%08lx not available, error=%ld:\n",mode,error));
        /* if not available, try fall back mode */
        mode = modefallback(mode,wide,high,deep);
        error = ModeNotAvailable(mode);

        D(bug("$%08lx ModeNotAvailable=%ld:\n",mode,error));
        }

    if(error) trynew = FALSE;
    else trynew=((QueryOverscan(mode,&txto,OSCAN_TEXT))&&
            (QueryOverscan(mode,&stdo,OSCAN_STANDARD))&&
                (QueryOverscan(mode,&maxo,OSCAN_MAX)));
    }

    D(bug("\nILBM: w=%ld, h=%ld, d=%ld, mode=0x%08lx\n",
        wide,high,deep,mode));
    D(bug("OPEN: %s.\n",
        trynew	? "Is >= 2.0 and mode available, trying OpenScreenTags"
        : "Not 2.0, doing old OpenScreen"));

    if(trynew)
    {
    /* If user clip type specified and available, use it */
    if(ilbm->Video) ilbm->ucliptype = OSCAN_VIDEO;
    if((ilbm->ucliptype)&&(QueryOverscan(mode,&uclip,ilbm->ucliptype)))
        uclipp = &uclip;
    else uclipp = NULL;

    clipit(wide,high,&spos,&dclip,&txto,&stdo,&maxo,uclipp);

    D(bug("Using dclip  %ld,%ld  to  %ld,%ld... width=%ld height=%ld\n",
            dclip.MinX,dclip.MinY,dclip.MaxX,dclip.MaxY,
            dclip.MaxX-dclip.MinX+1,dclip.MaxY-dclip.MinY+1));
    D(bug("spos->minx = %ld, spos->miny = %ld\n",spos.MinX,spos.MinY));
    D(bug("DEBUG: About to attempt OpenScreenTags\n"));

    bitmaptag = ((ilbm->brbitmap)&&(ilbm->stype & CUSTOMBITMAP)) ?
        SA_BitMap : TAG_IGNORE;
    passedtags = ilbm->stags ? TAG_MORE : TAG_IGNORE;

    scr=(struct Screen *)OpenScreenTags((struct NewScreen *)NULL,
        SA_DisplayID,	mode,
        SA_Type,	ilbm->stype,
        SA_Behind,	TRUE,
        SA_Top,		spos.MinY,
        SA_Left,	spos.MinX,
        SA_Width,	wide,
        SA_Height,	high,
        SA_Depth,	deep,
        SA_DClip,	&dclip,
        SA_AutoScroll,	ilbm->Autoscroll ? TRUE : FALSE,
        SA_Title,	ilbm->stitle,
        SA_Font,	&SafeFont,
        SA_Pens,	penarray,
        SA_ErrorCode,	&error,
        bitmaptag,	ilbm->brbitmap,
        passedtags,	ilbm->stags,
        TAG_DONE
        );

        D(bug("DEBUG: OpenScreenTags scr at 0x%lx\n",scr));

        if(scr)
        {
        if(ilbm->Notransb)
            {
            vctl=VideoControlTags(scr->ViewPort.ColorMap,
                VTAG_BORDERNOTRANS_SET, TRUE,
                TAG_DONE);

    D(bug("VideoControl to set bordernotrans, error = %ld\n",vctl));

            MakeScreen(scr);
            RethinkDisplay();
            }
        }
        else modeErrorMsg(mode,error);
        }

    if(!scr)
    {
    /* ns initialization for 1.3 old style OpenScreen only
         */
    ns.LeftEdge = ns.TopEdge = 0;
    ns.Width 	=	wide;
    ns.Height 	=	high;
    ns.Depth	=	deep;
    ns.ViewModes	= 	modefallback(mode,wide,high,deep);
    ns.DetailPen	=	0;
    ns.BlockPen	=	1;
    ns.Gadgets	=	NULL;
    ns.CustomBitMap	=	((ilbm->brbitmap)&&(ilbm->stype & CUSTOMBITMAP))
                    ? ilbm->brbitmap : NULL;
    ns.Font		=	&SafeFont;
    ns.DefaultTitle = 	ilbm->stitle;
    ns.Type		=	ilbm->stype & 0x01FF;  /* allow only 1.3 types */

    scr=(struct Screen *)OpenScreen(&ns);

    D(bug("DEBUG: ns.ViewModes=0x%lx, vp->Modes=0x%lx\n",
                 ns.ViewModes,scr->ViewPort.Modes));
    D(bug("DEBUG: non-extended scr at 0x%lx (0=failure)\n",scr));
    }
    return(scr);
    }

/*
 * modefallback - passed a mode id, attempts to provide a
 *                suitable old mode to use instead
 */

/* for old 1.3 screens */
#define MODE_ID_MASK (LACE|HIRES|HAM|EXTRA_HALFBRITE)

ULONG modefallback(ULONG mode, SHORT wide, SHORT high, SHORT deep)
{
ULONG newmode;

    /* For now, simply masks out everything but old mode bits.
     * This is just a cheap way to get some kind of display open
     *   and may be totally invalid for future modes.
     * Should search the display database for a suitable mode
     * based on the specific needs of your application.
     */
    newmode = mode & MODE_ID_MASK;

    D(bug("Try 0x%08lx instead of 0x%08lx\n",newmode,mode));
    return(newmode);
}

/*
 * clipit - passed width and height of a display, and the text, std, and
 *          max overscan rectangles for the mode, clipit fills in the
 *          spos (screen pos) and dclip rectangles to use in centering.
 *          Centered around smallest containing user-editable oscan pref,
 *          with dclip confined to legal maxoscan limits.
 *          Screens which center such that their top is below text
 *          oscan top, will be moved up.
 *          If a non-null uclip is passed, that clip is used instead.
 */
void clipit(SHORT wide, SHORT high,
        struct Rectangle *spos, struct Rectangle *dclip,
        struct Rectangle *txto, struct Rectangle *stdo,
        struct Rectangle *maxo, struct Rectangle *uclip)
{
struct  Rectangle *besto;
SHORT	minx, maxx, miny, maxy;
SHORT	txtw, txth, stdw, stdh, maxw, maxh, bestw, besth;

    /* get the txt, std and max widths and heights */
    txtw = txto->MaxX - txto->MinX + 1;
    txth = txto->MaxY - txto->MinY + 1;
    stdw = stdo->MaxX - stdo->MinX + 1;
    stdh = stdo->MaxY - stdo->MinY + 1;
    maxw = maxo->MaxX - maxo->MinX + 1;
    maxh = maxo->MaxY - maxo->MinY + 1;

    if((wide <= txtw)&&(high <= txth))
    {
    besto = txto;
    bestw = txtw;
    besth = txth;

    D(bug("Best clip is txto\n"));
    }
    else
    {
    besto = stdo;
    bestw = stdw;
    besth = stdh;

    D(bug("Best clip is stdo\n"));
    }

    D(bug("TXTO: mnx=%ld mny=%ld mxx=%ld mxy=%ld  stdw=%ld stdh=%ld\n",
        txto->MinX,txto->MinY,txto->MaxX,txto->MaxY,txtw,txth));
    D(bug("STDO: mnx=%ld mny=%ld mxx=%ld mxy=%ld  stdw=%ld stdh=%ld\n",
        stdo->MinX,stdo->MinY,stdo->MaxX,stdo->MaxY,stdw,stdh));
    D(bug("MAXO: mnx=%ld mny=%ld mxx=%ld mxy=%ld  maxw=%ld maxh=%ld\n",
        maxo->MinX,maxo->MinY,maxo->MaxX,maxo->MaxY,maxw,maxh));

    if(uclip)
    {
    *dclip = *uclip;
        spos->MinX = uclip->MinX;
    spos->MinY = uclip->MinY;

    D(bug("UCLIP: mnx=%ld mny=%ld maxx=%ld maxy=%ld\n",
            dclip->MinX,dclip->MinY,dclip->MaxX,dclip->MaxY));
    }
    else
    {
    /* CENTER the screen based on best oscan prefs
     * but confine dclip within max oscan limits
     *
     * FIX MinX first */
    spos->MinX = minx = besto->MinX - ((wide - bestw) >> 1);
    maxx = wide + minx - 1;
    if(maxx > maxo->MaxX)  maxx = maxo->MaxX;	/* too right */
    if(minx < maxo->MinX)  minx = maxo->MinX;	/* too left  */

    D(bug("DCLIP: minx adjust from %ld to %ld\n",spos->MinX,minx));

    /* FIX MinY */
    spos->MinY = miny = besto->MinY - ((high - besth) >> 1);
    /* if lower than top of txto, move up */
    spos->MinY = miny = MIN(spos->MinY,txto->MinY);
    maxy = high + miny - 1;
    if(maxy > maxo->MaxY)  maxy = maxo->MaxY;	/* too down  */
    if(miny < maxo->MinY)  miny = maxo->MinY;	/* too up    */

    D(bug("DCLIP: miny adjust from %ld to %ld\n",spos->MinY,miny));

    /* SET up dclip */
    dclip->MinX = minx;
    dclip->MinY = miny;
    dclip->MaxX = maxx;
    dclip->MaxY = maxy;

    D(bug("CENTER: mnx=%ld mny=%ld maxx=%ld maxy=%ld\n",
            dclip->MinX,dclip->MinY,dclip->MaxX,dclip->MaxY));
    }
}

void modeErrorMsg(ULONG mode, ULONG errorcode)
   {
   UBYTE *s=NULL;

    D(bug("DEBUG: Can't open mode ID 0x%08lx screen: ",mode));

        switch ( errorcode )
    {
    case OSERR_NOMEM:
        s="Not enough memory.";
        break;
    case OSERR_NOCHIPMEM:
        s="Not enough chip memory.";
        break;
#ifdef DEBUG
    case OSERR_NOMONITOR:
        s="monitor not available.";
        break;

    case OSERR_NOCHIPS:
        s="new chipset not available.";
        break;

    case OSERR_PUBNOTUNIQUE:
        s="public screen already open.";
        break;
    case OSERR_UNKNOWNMODE:
        s="mode ID is unknown.";
        break;
    default:
        message("unknown mode error %ld\n",errorcode);
#endif
    }
    if(s) message("%s\n",s);
    }

/*----------------------------------------------------------------------*/

BOOL VideoControlTags(struct ColorMap *cm, ULONG tags, ...)
    {
    return (VideoControl(cm, (struct TagItem *)&tags));
    }

/*----------------------------------------------------------------------*/


Includes/prefs/printergfx.h

#ifndef PREFS_PRINTERGFX_H
#define PREFS_PRINTERGFX_H
/*
**	$VER: printergfx.h 38.2 (03.07.91)
**	Includes Release 38.56
**
**	File format for graphics printer preferences
**
**	(C) Copyright 1991-1999 Amiga, Inc.
**	All Rights Reserved
*/

/*****************************************************************************/

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef LIBRARIES_IFFPARSE_H
#include <libraries/iffparse.h>
#endif

/*****************************************************************************/

#define ID_PGFX MAKE_ID('P','G','F','X')

struct PrinterGfxPrefs
{
    LONG  pg_Reserved[4];
    UWORD pg_Aspect;
    UWORD pg_Shade;
    UWORD pg_Image;
    WORD  pg_Threshold;
    UBYTE pg_ColorCorrect;
    UBYTE pg_Dimensions;
    UBYTE pg_Dithering;
    UWORD pg_GraphicFlags;
    UBYTE pg_PrintDensity;		/* Print density 1 - 7 */
    UWORD pg_PrintMaxWidth;
    UWORD pg_PrintMaxHeight;
    UBYTE pg_PrintXOffset;
    UBYTE pg_PrintYOffset;
};

/* constants for PrinterGfxPrefs.pg_Aspect */
#define PA_HORIZONTAL 0
#define PA_VERTICAL   1

/* constants for PrinterGfxPrefs.pg_Shade */
#define PS_BW		0
#define PS_GREYSCALE	1
#define PS_COLOR	2
#define PS_GREY_SCALE2	3

/* constants for PrinterGfxPrefs.pg_Image */
#define PI_POSITIVE 0
#define PI_NEGATIVE 1

/* flags for PrinterGfxPrefs.pg_ColorCorrect */
#define PCCB_RED   1	/* color correct red shades   */
#define PCCB_GREEN 2	/* color correct green shades */
#define PCCB_BLUE  3	/* color correct blue shades  */

#define PCCF_RED   (1<<0)
#define PCCF_GREEN (1<<1)
#define PCCF_BLUE  (1<<2)

/* constants for PrinterGfxPrefs.pg_Dimensions */
#define PD_IGNORE   0  /* ignore max width/height settings */
#define PD_BOUNDED  1  /* use max w/h as boundaries	   */
#define PD_ABSOLUTE 2  /* use max w/h as absolutes	   */
#define PD_PIXEL    3  /* use max w/h as prt pixels	   */
#define PD_MULTIPLY 4  /* use max w/h as multipliers	   */

/* constants for PrinterGfxPrefs.pg_Dithering */
#define PD_ORDERED	0  /* ordered dithering	*/
#define PD_HALFTONE	1  /* halftone dithering	*/
#define PD_FLOYD	2  /* Floyd-Steinberg dithering */

/* flags for PrinterGfxPrefs.pg_GraphicsFlags */
#define PGFB_CENTER_IMAGE	0	/* center image on paper */
#define PGFB_INTEGER_SCALING	1	/* force integer scaling */
#define PGFB_ANTI_ALIAS		2	/* anti-alias image	 */

#define PGFF_CENTER_IMAGE	(1<<0)
#define PGFF_INTEGER_SCALING	(1<<1)
#define PGFF_ANTI_ALIAS		(1<<2)

/*****************************************************************************/

#endif /* PREFS_PRINTERGFX_H */


lib_examples/allocentry.c

;/* allocentry.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 allocentry.c
Blink FROM LIB:c.o,allocentry.o TO allocentry LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit ;

allocentry.c - example of allocating several memory areas.
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <clib/exec_protos.h>
#include <stdio.h>
#include <stdlib.h>

#ifdef LATTICE
int CXBRK(void)  { return(0); }  /* Disable Lattice CTRL/C handling */
void chkabort(void) { return; }  /* really */
#endif

#define ALLOCERROR 0x80000000

struct MemList *memlist;             /* pointer to a MemList structure        */

struct MemBlocks /* define a new structure because C cannot initialize unions */
{
    struct MemList  mn_head;         /* one entry in the header               */
    struct MemEntry mn_body[3];      /* additional entries follow directly as */
} memblocks;                         /* part of the same data structure       */

VOID main(VOID)
{
    memblocks.mn_head.ml_NumEntries = 4; /* 4! Since the MemEntry starts at 1! */

    /* Describe the first piece of memory we want.  Because of our MemBlocks structure */
    /* setup, we reference the first MemEntry differently when initializing it.        */
    memblocks.mn_head.ml_ME[0].me_Reqs = MEMF_CLEAR;
    memblocks.mn_head.ml_ME[0].me_Length = 4000;

    memblocks.mn_body[0].me_Reqs   = MEMF_CHIP | MEMF_CLEAR;   /* Describe the other pieces of    */
    memblocks.mn_body[0].me_Length = 100000;                   /* memory we want. Additional      */
    memblocks.mn_body[1].me_Reqs   = MEMF_PUBLIC | MEMF_CLEAR; /* MemEntries are initialized this */
    memblocks.mn_body[1].me_Length = 200000;                   /* way. If we wanted even more en- */
    memblocks.mn_body[2].me_Reqs   = MEMF_PUBLIC;              /* tries, we would need to declare */
    memblocks.mn_body[2].me_Length = 25000;                    /* a larger MemEntry array in our  */
                                                               /* MemBlocks structure.            */

    memlist = (struct MemList *)AllocEntry((struct MemList *)&memblocks);

    if ((ULONG)memlist & ALLOCERROR)          /* 'error' bit 31 is set (see below). */
    {
       printf("AllocEntry FAILED\n");
       exit(200);
    }
    /* We got all memory we wanted.  Use it and call FreeEntry() to free it */
    printf("AllocEntry succeeded - now freeing all allocated blocks\n");
    FreeEntry(memlist);
}


lib_examples/allocate.c

;/* allocate.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 allocate.c
Blink FROM LIB:c.o,allocate.o TO allocate LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit ;
allocate.c - example of allocating and using a private memory pool.
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <clib/exec_protos.h>
#include <stdio.h>
#include <stdlib.h>

#ifdef LATTICE
int CXBRK(void)  { return(0); }  /* Disable Lattice CTRL/C handling */
void chkabort(void) { return; }  /* really */
#endif

#define BLOCKSIZE 4000     /* or whatever you need */

VOID main(VOID)
{
    struct MemHeader *mh;
    struct MemChunk  *mc;
    APTR   block1, block2;

    /* Get the MemHeader needed to keep track of our new block. */
    mh = (struct MemHeader *)AllocMem((LONG)sizeof(struct MemHeader), MEMF_CLEAR);
    if (!mh) exit(10);

    /* Get the actual block the above MemHeader will manage. */
    if ( !(mc = (struct MemChunk *)AllocMem(BLOCKSIZE, 0)) );
    {
        FreeMem(mh, (LONG)sizeof(struct MemHeader));
        exit(10);
    }
    mh->mh_Node.ln_Type = NT_MEMORY;
    mh->mh_First        = mc;
    mh->mh_Lower        = (APTR)mc;
    mh->mh_Upper        = (APTR)(BLOCKSIZE + (ULONG)mc);
    mh->mh_Free         = BLOCKSIZE;

    mc->mc_Next  = NULL;                     /* Set up first chunk in the freelist */
    mc->mc_Bytes = BLOCKSIZE;

    block1 = (APTR)Allocate(mh,20);
    block2 = (APTR)Allocate(mh, 314);

    printf("Our MemHeader struct at $%lx. Our block of memory at $%lx\n", mh, mc);
    printf("Allocated from our pool: block1 at $%lx, block2 at $%lx\n", block1, block2);

    FreeMem(mh, (LONG)sizeof(struct MemHeader));
    FreeMem(mc, (LONG)BLOCKSIZE);
}


lib_examples/port2.c

;/* port2.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 port2.c
Blink FROM LIB:c.o,port2.o TO port2 LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit

** port2.c - port and message example, run at the same time as port1.c
*/

#include <exec/types.h>
#include <exec/ports.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL-C handling */
int chkabort(void) {return(0);}
#endif

BOOL SafePutToPort(struct Message *, STRPTR);

struct XYMessage {
    struct Message xy_Msg;
    WORD           xy_X;
    WORD           xy_Y;
};

void main(int argc, char **argv)
{
    struct MsgPort *xyreplyport;
    struct XYMessage *xymsg, *reply;
                                                           /* Using CreatePort() with no name       */
    if (xyreplyport = CreatePort(0,0))                     /* because this port need not be public. */
    {
        if (xymsg = (struct XYMessage *) AllocMem(sizeof(struct XYMessage), MEMF_PUBLIC | MEMF_CLEAR))
        {
            xymsg->xy_Msg.mn_Node.ln_Type = NT_MESSAGE;                /* make up a message,        */
            xymsg->xy_Msg.mn_Length = sizeof(struct XYMessage);        /* including the reply port. */
            xymsg->xy_Msg.mn_ReplyPort = xyreplyport;
            xymsg->xy_X = 10;                                   /* our special message information. */
            xymsg->xy_Y = 20;

            printf("Sending to port1: x = %d y = %d\n", xymsg->xy_X, xymsg->xy_Y);
                                                                   /* port2 will simply try to put  */

            if (SafePutToPort((struct Message *)xymsg, "xyport"))  /* one message to port1 wait for */
            {                                                      /*  the reply, and then exit     */
                WaitPort(xyreplyport);
                if (reply = (struct XYMessage *)GetMsg(xyreplyport))
                    printf("Reply contains: x = %d y = %d\n",         /* We don't ReplyMsg since   */
                            xymsg->xy_X, xymsg->xy_Y);                /* WE initiated the message. */

                      /* Since we only use this private port for receiving replies, and we sent     */
                      /* only one and got one reply there is no need to cleanup. For a public port, */
                      /* or if you pass a pointer to the port to another process, it is a very good */
                      /* habit to always handle all messages at the port before you delete it.      */
            }
            else printf("Can't find 'xyport'; start port1 in a separate shell\n");
            FreeMem(xymsg, sizeof(struct XYMessage));
        }
        else printf("Couldn't get memory\n");
        DeletePort(xyreplyport);
    }
    else printf("Couldn't create xyreplyport\n");
}

BOOL SafePutToPort(struct Message *message, STRPTR portname)
{
    struct MsgPort *port;

    Forbid();
    port = FindPort(portname);
    if (port) PutMsg(port, message);
    Permit();
    return(port ? TRUE : FALSE); /* FALSE if the port was not found */

         /* Once we've done a Permit(), the port might go away and leave us with an invalid port    */
}        /* address. So we return just a BOOL to indicate whether the message has been sent or not. */


lib_examples/port1.c

;/* port1.c - Execute me to compile with SAS C 5.10
LC -b1 -cfistq -v -y -j73 port1.c
Blink FROM LIB:c.o,port1.o TO port1 LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit

* port1.c - port and message example, run at the same time as port2.c
*/

#include <exec/types.h>
#include <exec/ports.h>
#include <dos/dos.h>
#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL-C handling */
int chkabort(void) {return(0);}
#endif

struct XYMessage {
    struct Message xym_Msg;
    WORD           xy_X;
    WORD           xy_Y;
};

void main(int argc, char **argv)
{
    struct MsgPort *xyport;
    struct XYMessage *xymsg;
    ULONG portsig, usersig, signal;
    BOOL ABORT = FALSE;

    if (xyport = CreatePort("xyport", 0))
    {
        portsig = 1 << xyport->mp_SigBit;       /* Give user a `break' signal. */
        usersig = SIGBREAKF_CTRL_C;

        printf("Start port2 in another shell.  CTRL-C here when done.\n");
        do
        {                                                 /* port1 will wait forever and reply   */
            signal = Wait(portsig | usersig);             /* to messages, until the user breaks. */

                                   /* Since we only have one port that might get messages we     */
            if (signal & portsig)  /* have to reply to, it is not really necessary to test for   */
            {                      /* the portsignal. If there is not message at the port, xymsg */

                while(xymsg = (struct XYMessage *)GetMsg(xyport))        /* simply will be NULL. */
                {
                    printf("port1 received: x = %d y = %d\n", xymsg->xy_X, xymsg->xy_Y);

                    xymsg->xy_X += 50;       /* Since we have not replied yet to the owner of    */
                    xymsg->xy_Y += 50;       /* xymsg, we can change the data contents of xymsg. */

                    printf("port1 replying with: x = %d y = %d\n", xymsg->xy_X, xymsg->xy_Y);
                    ReplyMsg((struct Message *)xymsg);
                }
            }

            if (signal & usersig)                                    /* The user wants to abort. */
            {
                while(xymsg = (struct XYMessage *)GetMsg(xyport))    /* Make sure port is empty. */
                    ReplyMsg((struct Message *)xymsg);
                ABORT = TRUE;
            }
        }
        while (ABORT == FALSE);
            DeletePort(xyport);
        }
    else printf("Couldn't create 'xyport'\n");
}


lib_examples/rbf.c

;/* rbf.c - Execute me to compile me with SAS C 5.10
LC -d0 -b1 -cfistq -v -y -j73 rbf.c
Blink FROM LIB:c.o,rbf.o,rbfhandler.o TO rbf LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit

** rbf.c - serial receive buffer full interrupt handler example.
** Must be linked with assembler handler rbfhandler.o
**
** To receive characters, this example requires ASCII serial input
** at your Amiga's current serial hardware baud rate (ie. 9600 after
** reboot, else last baud rate used)
*/

#include <exec/execbase.h>
#include <exec/memory.h>
#include <exec/interrupts.h>
#include <resources/misc.h>
#include <hardware/custom.h>
#include <hardware/intbits.h>
#include <dos/dos.h>

#include <clib/exec_protos.h>
#include <clib/misc_protos.h>

#include <stdio.h>
#include <string.h>

#ifdef LATTICE
int CXBRK(void)  { return(0); }  /* Disable Lattice CTRL/C handling */
void chkabort(void) { return; }  /* really */
#endif

#define BUFFERSIZE 256

extern void RBFHandler();   /* proto for asm interrupt handler */
void main(void);

struct MiscResource *MiscBase;
extern struct ExecBase *SysBase;
extern struct Custom far custom;    /* defined in amiga.lib */

static UBYTE *allocname = "rbf-example";

struct RBFData {
    struct Task *rd_Task;
    ULONG rd_Signal;
    ULONG rd_BufferCount;
    UBYTE rd_CharBuffer[BUFFERSIZE + 2];
    UBYTE rd_FlagBuffer[BUFFERSIZE + 2];
    UBYTE rd_Name[32];
};

void main(void)
{
    struct RBFData *rbfdata;
    UBYTE *currentuser;
    BYTE signr;
    struct Device *serdevice;
    struct Interrupt *rbfint, *priorint;
    BOOL priorenable;
    ULONG signal;

    if (MiscBase = OpenResource("misc.resource"))
    {
        currentuser = AllocMiscResource(MR_SERIALPORT, allocname);        /* Allocate the serial */
        if (currentuser)                                                  /* port registers.     */
        {
            printf("serial hardware allocated by %s. Trying to remove it\n",
                   currentuser);                                         /* Hey! someone got it! */
            Forbid();
            if (serdevice = (struct Device *)FindName(&SysBase->DeviceList, currentuser))
                RemDevice(serdevice);
            Permit();

            currentuser = AllocMiscResource(MR_SERIALPORT, allocname);          /* and try again */
        }
        if (currentuser == NULL)
        {                                                                      /* Get the serial */
            currentuser = AllocMiscResource(MR_SERIALBITS, allocname);         /* control bits.  */
            if (currentuser)
            {
                printf("serial control allocated by %s\n", currentuser);            /* Give up. */
                FreeMiscResource(MR_SERIALPORT);
            }
            else
            {                                                                  /* Got them both. */
                printf("serial hardware allocated\n");
                if ((signr = AllocSignal(-1)) != -1)          /* Allocate a signal bit for the   */
                {                                             /* interrupt handler to signal us. */
                    if (rbfint = AllocMem(sizeof(struct Interrupt), MEMF_PUBLIC|MEMF_CLEAR))
                    {
                        if (rbfdata = AllocMem(sizeof(struct RBFData), MEMF_PUBLIC|MEMF_CLEAR))
                        {
                            rbfdata->rd_Task = FindTask(NULL);        /* Init rfbdata structure. */
                            rbfdata->rd_Signal = 1L << signr;

                            rbfint->is_Node.ln_Type = NT_INTERRUPT;      /* Init interrupt node. */
                            strcpy(rbfdata->rd_Name, allocname);
                            rbfint->is_Node.ln_Name = rbfdata->rd_Name;
                            rbfint->is_Data = (APTR)rbfdata;
                            rbfint->is_Code = RBFHandler;
                                                                        /* Save state of RBF and */
                            priorenable = custom.intenar & INTF_RBF ? TRUE : FALSE; /* interrupt */
                            custom.intena = INTF_RBF;                             /* disable it. */
                            priorint = SetIntVector(INTB_RBF, rbfint);

                            if (priorint) printf("replaced the %s RBF interrupt handler\n",
                                                 priorint->is_Node.ln_Name);
                            printf("enabling RBF interrupt\n");
                            custom.intena = INTF_SETCLR | INTF_RBF;

                            printf("waiting for buffer to fill up. Use CTRL-C to break\n");
                            signal = Wait(1L << signr | SIGBREAKF_CTRL_C);

                            if (signal & SIGBREAKF_CTRL_C) printf(">break<\n");
                            printf("Character buffer contains:\n%s\n", rbfdata->rd_CharBuffer);

                            custom.intena = INTF_RBF;               /* Restore previous handler. */
                            SetIntVector(INTB_RBF, priorint);
                                                                  /* Enable it if it was enabled */
                            if (priorenable) custom.intena = INTF_SETCLR|INTF_RBF;    /* before. */

                            FreeMem(rbfdata, sizeof(struct RBFData));
                        }
                        else  printf("can't allocate memory for rbf data\n");
                        FreeMem(rbfint, sizeof(struct Interrupt));
                    }
                    else printf("can't allocate memory for interrupt structure\n");
                    FreeSignal(signr);
                }
                else printf("can't allocate signal\n");

                FreeMiscResource(MR_SERIALBITS);   /* release serial hardware */
                FreeMiscResource(MR_SERIALPORT);
            }
        }
    } /* There is no 'CloseResource()' function */
}


lib_examples/rbfhandler.asm

* rbfhandler.asm. Example interrupt handler for rbf.
*
* Assembled with Howesoft Adapt 680x0 Macro Assembler Rel. 1.0
* hx68 from: rbfhandler.asm to rbfhandler.o INCDIR include:
* blink from lib:c.o rbf.o rbfhandler.o to rbf lib lib:lc.lib lib:amiga.lib
*
    INCLUDE "exec/types.i"
    INCLUDE "hardware/custom.i"
    INCLUDE "hardware/intbits.i"

        XDEF    _RBFHandler

JSRLIB MACRO
       XREF _LVO\1
       JSR  _LVO\1(A6)
       ENDM

BUFLEN    EQU    256

       STRUCTURE RBFDATA,0
        APTR   rd_task
        ULONG  rd_signal
        UWORD  rd_buffercount
        STRUCT rd_charbuffer,BUFLEN+2
        STRUCT rd_flagbuffer,BUFLEN+2
        STRUCT rd_name,32
        LABEL RBFDATA_SIZEOF

* Entered with:
*  D0 == scratch
*  D1 == INTENAT & INTREQR (scratch)
*  A0 == custom chips (scratch)
*  A1 == is_Data which is RBFDATA structure (scratch)
*  A5 == vector to our code (scratch)
*  A6 == pointer to ExecBase (scratch)
*
* Note - This simple handler just receives one buffer full of serial
* input data, signals main, then ignores all subsequent serial data.
*
    section code

_RBFHandler:                            ;entry to our interrupt handler

        MOVE.W  serdatr(A0),D1          ;get the input word (flags and char)

        MOVE.W  rd_buffercount(A1),D0   ;get our buffer index
        CMPI.W  #BUFLEN,D0              ;no more room in our buffer ?
        BEQ.S   ExitHandler             ;yes - just exit (ignore new char)
        LEA.L   rd_charbuffer(A1),A5    ;else get our character buffer address
        MOVE.B  D1,0(A5,D0.W)           ;store character in our character buffer
        LEA.L   rd_flagbuffer(A1),A5    ;get our flag buffer address
        LSR.W   #8,d1                   ;shift flags down
        MOVE.B  D1,0(A5,D0.W)           ;store flags in flagbuffer

        ADDQ.W  #1,D0                   ;increment our buffer index
        MOVE.W  D0,rd_buffercount(A1)   ;   and replace it
        CMPI.W  #BUFLEN,D0              ;did our buffer just become full ?
        BNE.S   ExitHandler             ;no - we can exit
        MOVE.L  A0,-(SP)                ;yes - save custom
        MOVE.L  rd_signal(A1),D0        ;get signal allocated in main()
        MOVE.L  rd_task(A1),A1          ;and pointer to main task
        JSRLIB  Signal                  ;tell main we are full
        MOVE.L  (SP)+,A0                ;restore custom
                                        ;Note: system call trashed D0-D1/A0-A1
ExitHandler:
        MOVE.W  #INTF_RBF,intreq(A0)    ;clear the interrupt
        RTS                             ;return to exec

        END


lib_examples/vertb.c

;/* vertb.c - Execute me to compile me with SAS C 5.10
LC -d0 -b1 -cfistq -v -y -j73 vertb.c
Blink FROM LIB:c.o,vertb.o,vertbserver.o TO vertb LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit ; */
/* vertb.c - Vertical blank interrupt server example.  Must be linked with vertbserver.o. */

#include <exec/memory.h>
#include <exec/interrupts.h>
#include <dos/dos.h>
#include <hardware/custom.h>
#include <hardware/intbits.h>
#include <clib/exec_protos.h>
#include <stdio.h>

#ifdef LATTICE
int CXBRK(void)  { return(0); }  /* Disable Lattice CTRL/C handling */
void chkabort(void) { return; }  /* really */
#endif

extern void VertBServer();  /* proto for asm interrupt server */

void main(void)
{
    struct Interrupt *vbint;
    ULONG counter = 0;
    ULONG endcount;
                                                                         /* Allocate memory for  */
    if (vbint = AllocMem(sizeof(struct Interrupt), MEMF_PUBLIC|MEMF_CLEAR))   /* interrupt node. */
    {
        vbint->is_Node.ln_Type = NT_INTERRUPT;         /* Initialize the node. */
        vbint->is_Node.ln_Pri = -60;
        vbint->is_Node.ln_Name = "VertB-Example";
        vbint->is_Data = (APTR)&counter;
        vbint->is_Code = VertBServer;

        AddIntServer(INTB_VERTB, vbint); /* Kick this interrupt server to life. */

        printf("VBlank server will increment a counter every frame.\n");
        printf("counter started at zero, CTRL-C to remove server\n");

        Wait(SIGBREAKF_CTRL_C);
        endcount = counter;
        printf("%ld vertical blanks occurred\nRemoving server\n", endcount);

        RemIntServer(INTB_VERTB, vbint);
        FreeMem(vbint, sizeof(struct Interrupt));
    }
    else printf("Can't allocate memory for interrupt node\n");
}


lib_examples/vertbserver.asm

* vertbserver.asm. Example simple interrupt server for vertical blank
*
* Assembled with Howesoft Adapt 680x0 Macro Assembler Rel. 1.0
* hx68 from: vertbserver.asm to vertbserver.o INCDIR include:
* blink from lib:c.o vertb.o vertbserver.o to vertb lib lib:lc.lib lib:amiga.lib
*
    INCLUDE "exec/types.i"
    INCLUDE "hardware/custom.i"
    INCLUDE "hardware/intbits.i"

        XDEF    _VertBServer

* Entered with:       A0 == scratch (execpt for highest pri vertb server)
*  D0 == scratch      A1 == is_Data
*  D1 == scratch      A5 == vector to interrupt code (scratch)
*                     A6 == scratch
*
    section code

_VertBServer:
        ADDI.L  #1,(a1)           ; increments counter is_Data points to
        MOVEQ.L #0,d0             ; set Z flag to continue to process other vb-servers
        RTS                       ;return to exec
        END


lib_examples/timersoftint.c

;/* timersoftint.c - Execute me to compile me with SAS C 5.10
LC -b1 -d0 -cfistq -v -y -j73 timersoftint.c
Blink FROM LIB:c.o,timersoftint.o TO timersoftint LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit ; */
/* timersoftint.c - Timer device software interrupt message port example. */

#include <exec/memory.h>
#include <exec/interrupts.h>
#include <devices/timer.h>
#include <dos/dos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/alib_protos.h>
#include <stdio.h>

#ifdef LATTICE
int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
void chkabort(void) { return; }  /* really */
#endif

#define MICRO_DELAY 1000
#define OFF     0
#define ON      1
#define STOPPED 2

struct TSIData {
    ULONG tsi_Counter;
    ULONG tsi_Flag;
    struct MsgPort *tsi_Port;
};

struct TSIData *tsidata;

void tsoftcode(void);    /* Prototype for our software interrupt code */

void main(void)
{
    struct MsgPort *port;
    struct Interrupt *softint;
    struct timerequest *tr;

    ULONG endcount;

    /* Allocate message port, data & interrupt structures. Don't use CreatePort() */
    /* or CreateMsgPort() since they allocate a signal (don't need that) for a    */
    /* PA_SIGNAL type port. We need PA_SOFTINT.                                   */
    if (tsidata = AllocMem(sizeof(struct TSIData), MEMF_PUBLIC|MEMF_CLEAR))
    {
        if(port = AllocMem(sizeof(struct MsgPort), MEMF_PUBLIC|MEMF_CLEAR))
        {
            NewList(&(port->mp_MsgList));                             /* Initialize message list */
            if (softint = AllocMem(sizeof(struct Interrupt), MEMF_PUBLIC|MEMF_CLEAR))
            {
                /* Set up the (software)interrupt structure. Note that this task runs at  */
                /* priority 0. Software interrupts may only be priority -32, -16, 0, +16, */
                /* +32. Also not that the correct node type for a software interrupt is   */
                /* NT_INTERRUPT. (NT_SOFTINT is an internal Exec flag). This is the same  */
                /* setup as that for a software interrupt which you Cause(). If our       */
                /* interrupt code was in assembler, you could initialize is_Data here to  */
                /* contain a pointer to shared data structures. An assembler software     */
                /* interrupt routine would receive the is_Data in A1.                     */

                softint->is_Code = tsoftcode;    /* The software interrupt routine */
                softint->is_Data = tsidata;
                softint->is_Node.ln_Pri = 0;

                port->mp_Node.ln_Type = NT_MSGPORT;       /* Set up the PA_SOFTINT message port  */
                port->mp_Flags = PA_SOFTINT;              /* (no need to make this port public). */
                port->mp_SigTask = (struct Task *)softint;     /* pointer to interrupt structure */

                /* Allocate timerequest */
                if (tr = (struct timerequest *) CreateExtIO(port, sizeof(struct timerequest)))
                {
                    /* Open timer.device. NULL is success. */
                    if (!(OpenDevice("timer.device", UNIT_MICROHZ, (struct IORequest *)tr, 0)))
                    {
                        tsidata->tsi_Flag = ON;        /* Init data structure to share globally. */
                        tsidata->tsi_Port = port;

                        /* Send of the first timerequest to start. IMPORTANT: Do NOT   */
                        /* BeginIO() to any device other than audio or timer from      */
                        /* within a software or hardware interrupt. The BeginIO() code */
                        /* may allocate memory, wait or perform other functions which  */
                        /* are illegal or dangerous during interrupts.                 */
                        printf("starting softint. CTRL-C to break...\n");

                        tr->tr_node.io_Command = TR_ADDREQUEST;    /* Initial iorequest to start */
                        tr->tr_time.tv_micro = MICRO_DELAY;        /* software interrupt.        */
                        BeginIO((struct IORequest *)tr);

                        Wait(SIGBREAKF_CTRL_C);
                        endcount = tsidata->tsi_Counter;
                        printf("timer softint counted %ld milliseconds.\n", endcount);

                        printf("Stopping timer...\n");
                        tsidata->tsi_Flag = OFF;

                        while (tsidata->tsi_Flag != STOPPED) Delay(10);

                        CloseDevice((struct IORequest *)tr);
                    }
                    else printf("couldn't open timer.device\n");
                    DeleteExtIO(tr);
                }
                else printf("couldn't create timerequest\n");
                FreeMem(softint, sizeof(struct Interrupt));
            }
            FreeMem(port, sizeof(struct MsgPort));
        }
        FreeMem(tsidata, sizeof(struct TSIData));
    }
}

void tsoftcode(void)
{
    struct timerequest *tr;

    /* Remove the message from the port. */
    tr = (struct timerequest *)GetMsg(tsidata->tsi_Port);

    /* Keep on going if main() hasn't set flag to OFF. */
    if ((tr) && (tsidata->tsi_Flag == ON))
    {
        /* increment counter and re-send timerequest--IMPORTANT: This         */
        /* self-perpetuating technique of calling BeginIO() during a software */
        /* interrupt may only be used with the audio and timer device.        */
        tsidata->tsi_Counter++;
        tr->tr_node.io_Command = TR_ADDREQUEST;
        tr->tr_time.tv_micro = MICRO_DELAY;
        BeginIO((struct IORequest *)tr);
    }
    /* Tell main() we're out of here. */
    else tsidata->tsi_Flag = STOPPED;
}


lib_examples/vsprite.c

/* The listing given here shows a complete VSprite example.  This
** program requires the animtools.c, animtools.h and animtools_proto.h
** support files in order to compile and run.  These files are listed at
** the end of this chapter.
**
** vsprite.c
**
** SAS/C V5.10a
** lc -b1 -cfist -v -y vsprite.c
** blink FROM LIB:c.o vsprite.o animtools.o LIB LIB:lc.lib LIB:amiga.lib TO vsprite
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuitionbase.h>
#include <graphics/gfx.h>
#include <graphics/gfxbase.h>
#include <graphics/gels.h>
#include <graphics/collide.h>
#include <libraries/dos.h>
#include <stdlib.h>
#include "animtools.h"

VOID borderCheck(struct VSprite *hitVSprite, LONG borderflags);
VOID process_window(struct Window *win, struct RastPort *myRPort, struct VSprite *MyVSprite);
VOID do_VSprite(struct Window *win, struct RastPort *myRPort);
VOID vspriteDrawGList(struct Window *win, struct RastPort *myRPort);

struct GfxBase		 *GfxBase;   /* pointer to Graphics library  */
struct IntuitionBase *IntuitionBase; /* pointer to Intuition library */

int return_code;
#define GEL_SIZE	4 /* number of lines in the vsprite */

/* VSprite data - there are two sets that are alternated between. */
/* note that this data is always displayed as low resolution.	  */
WORD chip vsprite_data1[] = { 0x7ffe, 0x80ff,
                              0x7c3e, 0x803f,
                              0x7c3e, 0x803f,
                              0x7ffe, 0x80ff,
                              0, 0 };

WORD chip vsprite_data2[] = { 0x7ffe, 0xff01,
                              0x7c3e, 0xfc01,
                              0x7c3e, 0xfc01,
                              0x7ffe, 0xff01,
                              0, 0 };

WORD mySpriteColors[] =     { 0x0000, 0x00f0, 0x0f00 };
WORD mySpriteAltColors[] =  { 0x000f, 0x0f00, 0x0ff0 };

NEWVSPRITE myNewVSprite = {              /* information for the new VSprite       */
        /* Image data, sprite color array word width (must be 1 for true VSprite) */
        vsprite_data1, mySpriteColors,1,
        /* Line height, image depth (must be 2 for true VSprite), x, y position   */                                                           */
        GEL_SIZE, 2, 160, 100,
        /* Flags (VSPRITE == true VSprite), hit mask and me mask                  */
        VSPRITE, 1 << BORDERHIT, 0
        };

struct NewWindow myNewWindow = {        /* information for the new window */
    80, 20, 400, 150, -1, -1, CLOSEWINDOW | INTUITICKS,
    ACTIVATE | WINDOWCLOSE | WINDOWDEPTH | RMBTRAP | WINDOWDRAG,
    NULL, NULL, "VSprite", NULL, NULL, 0, 0, 0, 0, WBENCHSCREEN
    };

/* Basic VSprite display subroutine */
VOID vspriteDrawGList(struct Window *win, struct RastPort *myRPort)
{
SortGList(myRPort);
DrawGList(myRPort, ViewPortAddress(win));
RethinkDisplay();
}

/* Collision routine for vsprite hitting border.  Note that when the collision is VSprite to */
/* VSprite (or Bob to Bob, Bob to AnimOb, etc), then the parameters are both pointers to a VSprite. */
VOID borderCheck(struct VSprite *hitVSprite, LONG borderflags)
{
if (borderflags & RIGHTHIT)
    {
    hitVSprite->SprColors = mySpriteAltColors;
    hitVSprite->VUserExt  = -40;
    }
if (borderflags & LEFTHIT)
    {
    hitVSprite->SprColors = mySpriteColors;
    hitVSprite->VUserExt  = 20;
    }
}

/* Process window and dynamically change vsprite. Get messages. Go away on           */
/* CLOSEWINDOW.  Update and redisplay vsprite on INTUITICKS. Wait for more messages. */
VOID process_window(struct Window *win, struct RastPort *myRPort, struct VSprite *myVSprite)
{
struct IntuiMessage *msg;

FOREVER
    {
    Wait(1L << win->UserPort->mp_SigBit);
    while (NULL != (msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
        {
        /* Only CLOSEWINDOW and INTUITICKS are active */
        if (msg->Class == CLOSEWINDOW)
            {
            ReplyMsg((struct Message *)msg);
            return;
            }
        /* Must be an INTUITICKS:  change x and y values on the fly.  Note offset by
        ** window left and top edge--sprite relative to the screen, not window.  Divide
        ** the MouseY in half to adjust for Lores movement increments on a Hires screen.
        */
        myVSprite->X = win->LeftEdge + msg->MouseX + myVSprite->VUserExt;
        myVSprite->Y = win->TopEdge  + msg->MouseY/2 + 1;
        ReplyMsg((struct Message *)msg);
        }
    /* Got a message, change image data on the fly */
    myVSprite->ImageData = (myVSprite->ImageData == vsprite_data1) ? vsprite_data2 : vsprite_data1;
    SortGList(myRPort);
    DoCollision(myRPort);
    vspriteDrawGList(win, myRPort);
    }
}

/* Working with the VSprite.  Setup the GEL system and get a new VSprite (makeVSprite()).   */
/* Add VSprite to the system and display.  Use the vsprite.  When done, remove VSprite and  */
/* update the display without the VSprite.  Cleanup everything.                             */
VOID do_VSprite(struct Window *win, struct RastPort *myRPort)
{
struct VSprite       *myVSprite;
struct GelsInfo       *my_ginfo;

if (NULL == (my_ginfo = setupGelSys(myRPort, 0xfc)))
    return_code = RETURN_WARN;
else
    {
    if (NULL == (myVSprite = makeVSprite(&myNewVSprite)))
        return_code = RETURN_WARN;
    else
        {
        AddVSprite(myVSprite, myRPort);
        vspriteDrawGList(win, myRPort);
        myVSprite->VUserExt = 20;
        SetCollision(BORDERHIT, borderCheck, myRPort->GelsInfo);
        process_window(win, myRPort, myVSprite);
        RemVSprite(myVSprite);
        freeVSprite(myVSprite);
        }
    vspriteDrawGList(win, myRPort);
    cleanupGelSys(my_ginfo, myRPort);
    }
}

/* Example VSprite program.  First open up the libraries and a window. */
VOID main(int argc, char **argv)
{
struct Window       *win;
struct RastPort    myRPort = {0};

return_code = RETURN_OK;

if (NULL == (GfxBase = (struct GfxBase *)OpenLibrary(GRAPHICSNAME,37L)))
    return_code = RETURN_FAIL;
else
    {
    if (NULL == (IntuitionBase = (struct IntuitionBase *)OpenLibrary(INTUITIONNAME,37L)))
        return_code = RETURN_FAIL;
    else
        {
        if (NULL == (win = OpenWindow(&myNewWindow)))
            return_code = RETURN_WARN;
        else
            {
            InitRastPort(&myRPort);
            myRPort = win->WScreen->RastPort;       /* Copy the structure. */
            do_VSprite(win, &myRPort);
            CloseWindow(win);
            }
        CloseLibrary((struct Library *)IntuitionBase);
        }
    CloseLibrary((struct Library *)GfxBase);
    }
exit(return_code);
}


lib_examples/ssprite.c

/* The following example demonstrates how to set up, move and free a
** Simple Sprite.  The animtools.h file included is listed at the end of
** the chapter.
**
** ssprite.c - Simple Sprite example
**
** SAS/C V5.10a
** lc -b1 -cfist -v -y ssprite.c
** blink FROM LIB:c.o ssprite.o LIB LIB:lc.lib LIB:amiga.lib TO ssprite
*/
#include <exec/types.h>
#include <graphics/gfx.h>
#include <graphics/gfxbase.h>
#include <graphics/gfxmacros.h>
#include <graphics/sprite.h>
#include <intuition/intuitionbase.h>
#include <intuition/screens.h>
#include <hardware/custom.h>
#include <hardware/dmabits.h>
#include <libraries/dos.h>

#include <clib/graphics_protos.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/alib_stdio_protos.h>

#include <stdlib.h>

struct GfxBase *GfxBase = NULL;
struct IntuitionBase *IntuitionBase = NULL;
extern struct Custom far custom ;

/* real boring sprite data */
UWORD chip sprite_data[ ] = {
    0, 0,           /* position control           */
    0xffff, 0x0000, /* image data line 1, color 1 */
    0xffff, 0x0000, /* image data line 2, color 1 */
    0x0000, 0xffff, /* image data line 3, color 2 */
    0x0000, 0xffff, /* image data line 4, color 2 */
    0x0000, 0x0000, /* image data line 5, transparent */
    0x0000, 0xffff, /* image data line 6, color 2 */
    0x0000, 0xffff, /* image data line 7, color 2 */
    0xffff, 0xffff, /* image data line 8, color 3 */
    0xffff, 0xffff, /* image data line 9, color 3 */
    0, 0            /* reserved, must init to 0 0 */
    };

VOID main(int argc, char **argv)
{
struct SimpleSprite    sprite = {0};
struct ViewPort        *viewport;

WORD sprite_num;
SHORT delta_move, ktr1, ktr2, color_reg;
struct Screen *screen;
int return_code;

return_code = RETURN_OK;

if (NULL == (GfxBase = (struct GfxBase *) OpenLibrary("graphics.library",37L)))
    return_code = RETURN_FAIL;
else
    {
    if (NULL == (IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37L)))
        return_code = RETURN_FAIL;
    else
        {
        /* opened library, need a viewport to render a sprite over. */
        if (NULL == (screen = OpenScreenTagList(NULL, NULL)))
            return_code = RETURN_FAIL;
        else
            {
            viewport = &screen->ViewPort;
            if (-1 == (sprite_num = GetSprite(&sprite, 2)))
                return_code = RETURN_WARN;
            else
                {
                /* Calculate the correct base color register number, */
                /* set up the color registers.                       */
                color_reg = 16 + ((sprite_num & 0x06) << 1);
                printf("color_reg=%d\n", color_reg);
                SetRGB4(viewport, color_reg + 1, 12,  3,  8);
                SetRGB4(viewport, color_reg + 2, 13, 13, 13);
                SetRGB4(viewport, color_reg + 3,  4,  4, 15);

                sprite.x = 0;       /* initialize position and size info    */
                sprite.y = 0;       /* to match that shown in sprite_data   */
                sprite.height = 9;  /* so system knows layout of data later */

                /* install sprite data and move sprite to start position. */
                ChangeSprite(NULL, &sprite, (APTR)sprite_data);
                MoveSprite(NULL, &sprite, 30, 0);

                /* move the sprite back and forth. */
                for ( ktr1 = 0, delta_move = 1;
                      ktr1 < 6; ktr1++, delta_move = -delta_move)
                    {
                    for ( ktr2 = 0; ktr2 < 100; ktr2++)
                        {
                        MoveSprite( NULL, &sprite, (LONG)(sprite.x + delta_move),
                                    (LONG)(sprite.y + delta_move) );
                        WaitTOF(); /* one move per video frame */

                        /* Show the effect of turning off sprite DMA. */
                        if (ktr2 == 40) OFF_SPRITE ;
                        if (ktr2 == 60) ON_SPRITE ;
                        }
                    }
                /* NOTE:  if you turn off the sprite at the wrong time (when it
                ** is being displayed), the sprite will appear as a vertical bar
                ** on the screen.  To really get rid of the sprite, you must
                ** OFF_SPRITE while it is not displayed.  This is hard in a
                ** multi-tasking system (the solution is not addressed in
                ** this program).
                */
                ON_SPRITE ; /* just to be sure */
                FreeSprite((WORD)sprite_num);
                }
            (VOID) CloseScreen(screen);
            }
        CloseLibrary((struct Library *)IntuitionBase);
        }
    CloseLibrary((struct Library *)GfxBase);
    }
exit(return_code);
}


lib_examples/animtools.h

/* animtools.h */
#ifndef GELTOOLS_H
#define GELTOOLS_H

/*
** These data structures are used by the functions in animtools.c to
** allow for an easier interface to the animation system.
*/

/* Data structure to hold information for a new VSprite.                */
typedef struct newVSprite {
        WORD           *nvs_Image;      /* image data for the vsprite   */
        WORD           *nvs_ColorSet;   /* color array for the vsprite  */
        SHORT           nvs_WordWidth;  /* width in words               */
        SHORT           nvs_LineHeight; /* height in lines              */
        SHORT           nvs_ImageDepth; /* depth of the image           */
        SHORT           nvs_X;          /* initial x position           */
        SHORT           nvs_Y;          /* initial y position           */
        SHORT           nvs_Flags;      /* vsprite flags                */
        USHORT          nvs_HitMask;    /* Hit mask.                    */
        USHORT          nvs_MeMask;     /* Me mask.                     */
        } NEWVSPRITE;

/* Data structure to hold information for a new Bob.                */
typedef struct newBob {
        WORD       *nb_Image;       /* image data for the bob       */
        SHORT       nb_WordWidth;   /* width in words               */
        SHORT       nb_LineHeight;  /* height in lines              */
        SHORT       nb_ImageDepth;  /* depth of the image           */
        SHORT       nb_PlanePick;   /* planes that get image data   */
        SHORT       nb_PlaneOnOff;  /* unused planes to turn on     */
        SHORT       nb_BFlags;      /* bob flags                    */
        SHORT       nb_DBuf;        /* 1=double buf, 0=not          */
        SHORT       nb_RasDepth;    /* depth of the raster          */
        SHORT       nb_X;           /* initial x position           */
        SHORT       nb_Y;           /* initial y position           */
        USHORT      nb_HitMask;     /* Hit mask.                    */
        USHORT      nb_MeMask;      /* Me mask.                     */
        } NEWBOB ;

/* Data structure to hold information for a new animation component.       */
typedef struct newAnimComp {
        WORD  (*nac_Routine)(); /* routine called when Comp is displayed.   */
        SHORT   nac_Xt;         /* initial delta offset position.           */
        SHORT   nac_Yt;         /* initial delta offset position.           */
        SHORT   nac_Time;       /* Initial Timer value.                     */
        SHORT   nac_CFlags;     /* Flags for the Component.                 */
        } NEWANIMCOMP;

/* Data structure to hold information for a new animation sequence.         */
typedef struct newAnimSeq {
        struct AnimOb  *nas_HeadOb; /* common Head of Object.               */
        WORD   *nas_Images;         /* array of Comp image data             */
        SHORT  *nas_Xt;             /* arrays of initial offsets.           */
        SHORT  *nas_Yt;             /* arrays of initial offsets.           */
        SHORT  *nas_Times;          /* array of Initial Timer value.        */
        WORD (**nas_Routines)();    /* Array of fns called when comp drawn  */
        SHORT   nas_CFlags;         /* Flags for the Component.             */
        SHORT   nas_Count;          /* Num Comps in seq (= arrays size)     */
        SHORT   nas_SingleImage;    /* one (or count) images.               */
        } NEWANIMSEQ;

#define INTUITIONNAME "intuition.library" /* intuitionbase.h does not define a library name. */

#include "animtools_proto.h"              /* Include Prototyping. */
#endif

/* animtools_proto.h */
#include        <clib/dos_protos.h>
#include        <clib/exec_protos.h>
#include        <clib/graphics_protos.h>
#include        <clib/intuition_protos.h>

struct GelsInfo *setupGelSys(struct RastPort *rPort, BYTE reserved);
VOID            cleanupGelSys(struct GelsInfo *gInfo, struct RastPort *rPort);
struct VSprite  *makeVSprite(NEWVSPRITE *nVSprite);
struct Bob      *makeBob(NEWBOB *nBob);
struct AnimComp *makeComp(NEWBOB *nBob, NEWANIMCOMP *nAnimComp);
struct AnimComp *makeSeq(NEWBOB *nBob, NEWANIMSEQ *nAnimSeq);
VOID            freeVSprite(struct VSprite *vsprite);
VOID            freeBob(struct Bob *bob, LONG rasdepth);
VOID            freeComp(struct AnimComp *myComp, LONG rasdepth);
VOID            freeSeq(struct AnimComp *headComp, LONG rasdepth);
VOID            freeOb(struct AnimOb *headOb, LONG rasdepth);


Includes/diskfont/diskfont.h

#ifndef	DISKFONT_DISKFONT_H
#define	DISKFONT_DISKFONT_H
/*
**	$VER: diskfont.h 38.0 (18.06.92)
**	Includes Release 38.56
**
**	diskfont library definitions
**
**	(C) Copyright 1990 Robert R. Burns
**	    All Rights Reserved
**	(C) Copyright 1985-1999 Amiga, Inc.
**	    All Rights Reserved
*/

#ifndef     EXEC_NODES_H
#include "exec/nodes.h"
#endif
#ifndef     EXEC_LISTS_H
#include "exec/lists.h"
#endif
#ifndef     GRAPHICS_TEXT_H
#include "graphics/text.h"
#endif

#define     MAXFONTPATH 256   /* including null terminator */

struct FontContents {
    char    fc_FileName[MAXFONTPATH];
    UWORD   fc_YSize;
    UBYTE   fc_Style;
    UBYTE   fc_Flags;
};

struct TFontContents {
    char    tfc_FileName[MAXFONTPATH-2];
    UWORD   tfc_TagCount;	/* including the TAG_DONE tag */
    /*
     *	if tfc_TagCount is non-zero, tfc_FileName is overlayed with
     *	Text Tags starting at:	(struct TagItem *)
     *	    &tfc_FileName[MAXFONTPATH-(tfc_TagCount*sizeof(struct TagItem))]
     */
    UWORD   tfc_YSize;
    UBYTE   tfc_Style;
    UBYTE   tfc_Flags;
};

#define  FCH_ID		0x0f00	/* FontContentsHeader, then FontContents */
#define  TFCH_ID	0x0f02	/* FontContentsHeader, then TFontContents */
#define  OFCH_ID	0x0f03	/* FontContentsHeader, then TFontContents,
                 * associated with outline font */

struct FontContentsHeader {
    UWORD   fch_FileID;		/* FCH_ID */
    UWORD   fch_NumEntries;	/* the number of FontContents elements */
    /* struct FontContents fch_FC[], or struct TFontContents fch_TFC[]; */
};

#define  DFH_ID		0x0f80
#define  MAXFONTNAME	32	/* font name including ".font\0" */

struct DiskFontHeader {
    /* the following 8 bytes are not actually considered a part of the	*/
    /* DiskFontHeader, but immediately preceed it. The NextSegment is	*/
    /* supplied by the linker/loader, and the ReturnCode is the code	*/
    /* at the beginning of the font in case someone runs it...		*/
    /*	 ULONG dfh_NextSegment;			\* actually a BPTR	*/
    /*	 ULONG dfh_ReturnCode;			\* MOVEQ #0,D0 : RTS	*/
    /* here then is the official start of the DiskFontHeader...		*/
    struct Node dfh_DF;		/* node to link disk fonts */
    UWORD   dfh_FileID;		/* DFH_ID */
    UWORD   dfh_Revision;	/* the font revision */
    LONG    dfh_Segment;	/* the segment address when loaded */
    char    dfh_Name[MAXFONTNAME]; /* the font name (null terminated) */
    struct TextFont dfh_TF;	/* loaded TextFont structure */
};

/* unfortunately, this needs to be explicitly typed */
/* used only if dfh_TF.tf_Style FSB_TAGGED bit is set */
#define	dfh_TagList	dfh_Segment	/* destroyed during loading */

#define     AFB_MEMORY	0
#define     AFF_MEMORY	0x0001
#define     AFB_DISK	1
#define     AFF_DISK	0x0002
#define     AFB_SCALED	2
#define     AFF_SCALED	0x0004
#define     AFB_BITMAP	3
#define     AFF_BITMAP	0x0008

#define     AFB_TAGGED	16	/* return TAvailFonts */
#define     AFF_TAGGED	0x10000L

struct AvailFonts {
    UWORD   af_Type;		/* MEMORY, DISK, or SCALED */
    struct TextAttr af_Attr;	/* text attributes for font */
};

struct TAvailFonts {
    UWORD   taf_Type;		/* MEMORY, DISK, or SCALED */
    struct TTextAttr taf_Attr;	/* text attributes for font */
};

struct AvailFontsHeader {
    UWORD   afh_NumEntries;	 /* number of AvailFonts elements */
    /* struct AvailFonts afh_AF[], or struct TAvailFonts afh_TAF[]; */
};

#endif	/* DISKFONT_DISKFONT_H */


lib_examples/mathtrans.c

#include <exec/types.h>
#include <libraries/mathffp.h>

#include <clib/mathffp_protos.h>
#include <clib/mathtrans_protos.h>

struct Library *MathTransBase;

VOID main()
{
FLOAT f1, f2, f3;
FLOAT i1;

if (MathTransBase = OpenLibrary("mathtrans.library",33))
    {
    f1 = SPAsin(f2);        /* Call SPAsin entry */
    f1 = SPAcos(f2);        /* Call SPAcos entry */
    f1 = SPAtan(f2);        /* Call SPAtan entry */

    f1 = SPSin(f2);         /* Call SPSin entry */
    f1 = SPCos(f2);         /* Call SPCos entry */
    f1 = SPTan(f2);         /* Call SPTan entry */
    f1 = SPSincos(&f3, f2); /* Call SPSincos entry */

    f1 = SPSinh(f2);        /* Call SPSinh entry */
    f1 = SPCosh(f2);        /* Call SPCosh entry */
    f1 = SPTanh(f2);        /* Call SPTanh entry */

    f1 = SPExp(f2);         /* Call SPExp entry */
    f1 = SPLog(f2);         /* Call SPLog entry */
    f1 = SPLog10(f2);       /* Call SPLog10 entry */
    f1 = SPPow(f2);         /* Call SPPow entry */
    f1 = SPSqrt(f2);        /* Call SPSqrt entry */

    i1 = SPTieee(f2);       /* Call SPTieee entry */
    f1 = SPFieee(i1);       /* Call SPFieee entry */

    CloseLibrary(MathTransBase);
    }
else
    printf("Can't open mathtrans.library\n");
}


lib_examples/mathffp.c

#include <exec/types.h>
#include <libraries/mathffp.h>

#include <clib/mathffp_protos.h>
#include <clib/alib_protos.h>

struct Library *MathBase;

UBYTE st1[80] = "3.1415926535897";
UBYTE st2[80] = "2.718281828459045";
UBYTE st3[80], st4[80];

VOID main()
{
FLOAT num1, num2;
FLOAT n1, n2, n3, n4;
LONG  exp1, exp2, exp3, exp4;
LONG  mant1, mant2, mant3, mant4;
LONG  place1, place2;

if (MathBase = OpenLibrary("mathffp.library", 33))
    {

    n1 = afp(st1);            /* Call afp entry */
    n2 = afp(st2);            /* Call afp entry */
    printf("\n\nASCII %s converts to floating point %f", st1, n1);
    printf("\nASCII %s converts to floating point %f", st2, n2);

    num1 = 3.1415926535897;
    num2 = 2.718281828459045;

    exp1 = fpa(num1, st3);    /* Call fpa entry */
    exp2 = fpa(num2, st4);    /* Call fpa entry */
    printf("\n\nfloating point %f converts to ASCII %s", num1, st3);
    printf("\nfloating point %f converts to ASCII %s", num2, st4);

    place1 = -2;
    place2 = -1;
    arnd(place1, exp1, st3);    /* Call arnd entry */
    arnd(place2, exp2, st4);    /* Call arnd entry */
    printf("\n\nASCII round of %f to %d places yields %s", num1, place1, st3);
    printf("\nASCII round of %f to %d places yields %s", num2, place2, st4);

    exp1  = -3;   exp2  = 3;    exp3  = -3;   exp4  = 3;
    mant1 = 12345;  mant2 = -54321;  mant3 = -12345; mant4 = 54321;

    n1 = dbf(exp1, mant1);        /* Call dbf entry */
    n2 = dbf(exp2, mant2);        /* Call dbf entry */
    n3 = dbf(exp3, mant3);        /* Call dbf entry */
    n4 = dbf(exp4, mant4);        /* Call dbf entry */
    printf("\n\ndbf of exp = %d and mant = %d yields FFP number of %f", exp1, mant1, n1);
    printf("\ndbf of exp = %d and mant = %d yields FFP number of %f", exp2, mant2, n2);
    printf("\ndbf of exp = %d and mant = %d yields FFP number of %f", exp3, mant3, n3);
    printf("\ndbf of exp = %d and mant = %d yields FFP number of %f", exp4, mant4, n4);

    CloseLibrary(MathBase);
    }
else
    printf("Can't open mathffp.library\n");
}


lib_examples/mathieeesingbas.c

#include <exec/types.h>
#include <libraries/mathieeesp.h>

#include <clib/mathsingbas_protos.h>

struct Library *MathIeeeSingBasBase;

VOID main()
{
FLOAT f1, f2, f3;
LONG   i1;

if (MathIeeeSingBasBase = OpenLibrary("mathieeesingbas.library",37))
    {
    i1 = IEEESPFix(f1);                /* Call IEEESPFix entry */
    fi = IEEESPFlt(i1);                /* Call IEEESPFlt entry */
    switch (IEEESPCmp(f1, f2)) {};     /* Call IEEESPCmp entry */
    switch (IEEESPTst(f1)) {};         /* Call IEEESPTst entry */
    f1 = IEEESPAbs(f2);                /* Call IEEESPAbs entry */
    f1 = IEEESPNeg(f2);                /* Call IEEESPNeg entry */
    f1 = IEEESPAdd(f2, f3);            /* Call IEEESPAdd entry */
    f1 = IEEESPSub(f2, f3);            /* Call IEEESPSub entry */
    f1 = IEEESPMul(f2, f3);            /* Call IEEESPMul entry */
    f1 = IEEESPDiv(f2, f3);            /* Call IEEESPDiv entry */
    f1 = IEEESPCeil(f2);               /* Call IEEESPCeil entry */
    f1 = IEEESPFloor(f2);              /* Call IEEESPFloor entry */

    CloseLibrary(MathIeeeSingBasBase);
    }
else
    printf("Can't open mathieeesingbas.library\n");
}


lib_examples/mathieeesingtrans.c

#include <exec/types.h>
#include <libraries/mathieeesp.h>

#include <clib/mathsingtrans_protos.h>

struct Library *MathIeeeSingTransBase;

VOID main()
{
FLOAT f1, f2, f3;

if (MathIeeeSingTransBase = OpenLibrary("mathieeesingtrans.library",37))
    {
    f1 = IEEEDPAsin(f2);        /* Call IEEESPAsin entry */
    f1 = IEEEDPAcos(f2);        /* Call IEEESPAcos entry */
    f1 = IEEEDPAtan(f2);        /* Call IEEESPAtan entry */
    f1 = IEEEDPSin(f2);         /* Call IEEESPSin entry */
    f1 = IEEEDPCos(f2);         /* Call IEEESPCos entry */
    f1 = IEEEDPTan(f2);         /* Call IEEESPTan entry */
    f1 = IEEEDPSincos(&f3, f2); /* Call IEEESPSincos entry */
    f1 = IEEEDPSinh(f2);        /* Call IEEESPSinh entry */
    f1 = IEEEDPCosh(f2);        /* Call IEEESPCosh entry */
    f1 = IEEEDPTanh(f2);        /* Call IEEESPTanh entry */
    f1 = IEEEDPExp(f2);         /* Call IEEESPExp entry */
    f1 = IEEEDPLog(f2);         /* Call IEEESPLog entry */
    f1 = IEEEDPLog10(f2);       /* Call IEEESPLog10 entry */
    f1 = IEEEDPPow(d2, f3);     /* Call IEEESPPow entry */
    f1 = IEEEDPSqrt(f2);        /* Call IEEESPSqrt entry */

    CloseLibrary(MathIeeeSingTransBase);
    }
else printf("Can't open mathieeesingtrans.library\n");
}


lib_examples/mathieeedoubbas.c

#include <exec/types.h>
#include <libraries/mathieeedp.h>

#include <clib/mathieeedoubbas_protos.h>

struct Library *MathIeeeDoubBasBase;

VOID main()
{
DOUBLE d1, d2, d3;
LONG   i1;

if (MathIeeeDoubBasBase = OpenLibrary("mathieeedoubbas.library",34))
    {

    i1 = IEEEDPFix(d1);                /* Call IEEEDPFix entry */
    fi = IEEEDPFlt(i1);                /* Call IEEEDPFlt entry */
    switch (IEEEDPCmp(d1, d2)) {};     /* Call IEEEDPCmp entry */
    switch (IEEEDPTst(d1)) {};         /* Call IEEEDPTst entry */
    d1 = IEEEDPAbs(d2);                /* Call IEEEDPAbs entry */
    d1 = IEEEDPNeg(d2);                /* Call IEEEDPNeg entry */
    d1 = IEEEDPAdd(d2, d3);            /* Call IEEEDPAdd entry */
    d1 = IEEEDPSub(d2, d3);            /* Call IEEEDPSub entry */
    d1 = IEEEDPMul(d2, d3);            /* Call IEEEDPMul entry */
    d1 = IEEEDPDiv(d2, d3);            /* Call IEEEDPDiv entry */
    d1 = IEEEDPCeil(d2);               /* Call IEEEDPCeil entry */
    d1 = IEEEDPFloor(d2);              /* Call IEEEDPFloor entry */

    CloseLibrary(MathIeeeDoubBasBase);
    }
else printf("Can't open mathieeedoubbas.library\n");
}


lib_examples/mathieeedoubtrans.c

#include <exec/types.h>
#include <libraries/mathieeedp.h>
#include <clib/mathdoubtrans_protos.h>

struct Library *MathIeeeDoubTransBase;

VOID main()
{
DOUBLE d1, d2, d3;
FLOAT f1;

if (MathIeeeDoubTransBase = OpenLibrary("mathieeedoubtrans.library",34))
    {
    d1 = IEEEDPAsin(d2);        /* Call IEEEDPAsin entry */
    d1 = IEEEDPAcos(d2);        /* Call IEEEDPAcos entry */
    d1 = IEEEDPAtan(d2);        /* Call IEEEDPAtan entry */
    d1 = IEEEDPSin(d2);         /* Call IEEEDPSin entry */
    d1 = IEEEDPCos(d2);         /* Call IEEEDPCos entry */
    d1 = IEEEDPTan(d2);         /* Call IEEEDPTan entry */
    d1 = IEEEDPSincos(&d3, d2); /* Call IEEEDPSincos entry */
    d1 = IEEEDPSinh(d2);        /* Call IEEEDPSinh entry */
    d1 = IEEEDPCosh(d2);        /* Call IEEEDPCosh entry */
    d1 = IEEEDPTanh(d2);        /* Call IEEEDPTanh entry */
    d1 = IEEEDPExp(d2);         /* Call IEEEDPExp entry */
    d1 = IEEEDPLog(d2);         /* Call IEEEDPLog entry */
    d1 = IEEEDPLog10(d2);       /* Call IEEEDPLog10 entry */
    d1 = IEEEDPPow(d2, d3);     /* Call IEEEDPPow entry */
    d1 = IEEEDPSqrt(d2);        /* Call IEEEDPSqrt entry */
    f1 = IEEEDPTieee(d2);       /* Call IEEEDPTieee entry */
    d1 = IEEEDPFieee(f1);       /* Call IEEEDPFieee entry */

    CloseLibrary(MathIeeeDoubTransBase);
    }
else printf("Can't open mathieeedoubtrans.library\n");
}


lib_examples/makefile

# MAKEFILE for sample.library, sample.lib, and asm library test program
# define linker command
LINKER = Blink

all: sample.library sample.lib alibtest

sample.library: sample.library.o
    $(LINKER) from sample.library.o to sample.library LIB lib:amiga.lib

sample.lib: sample_stubs.o sample_lvos.o
    JOIN sample_stubs.o sample_lvos.o AS sample.lib

alibtest: alibtest.o
  $(LINKER) from astartup.obj,alibtest.o to alibtest LIB lib:amiga.lib,sample.lib

# assembler command line for Adapt assembler
.asm.o:
    HX68 -A $*.asm -iINCLUDE: -o$*.o


lib_examples/asmsupp.i

**********************************************************************************
*assorted low level assembly support routines used by the sample Library & Device*
**********************************************************************************
CLEAR   MACRO           ;quick way to clear a D register on 68000
        MOVEQ   #0,\1
        ENDM

LINKSYS MACRO           ; link to a library without having to see a _LVO
        MOVE.L  A6,-(SP)
        MOVE.L  \2,A6
        JSR     _LVO\1(A6)
        MOVE.L  (SP)+,A6
        ENDM

CALLSYS MACRO           ; call a library via A6 without having to see _LVO
        JSR     _LVO\1(A6)
        ENDM

XLIB    MACRO           ; define a library reference without the _LVO
        XREF    _LVO\1
        ENDM
;
; Put a message to the serial port at 9600 baud.  Used as so:
;
;     PUTMSG   30,<'%s/Init: called'>
;
; Parameters can be printed out by pushing them on the stack and
; adding the appropriate C printf-style % formatting commands.
;
                XREF    KPutFmt
PUTMSG:         MACRO   * level,msg

                IFGE    INFO_LEVEL-\1

                PEA     subSysName(PC)
                MOVEM.L A0/A1/D0/D1,-(SP)
                LEA     msg\@(pc),A0    ;Point to static format string
                LEA     4*4(SP),A1      ;Point to args
                JSR     KPutFmt
                MOVEM.L (SP)+,D0/D1/A0/A1
                ADDQ.L  #4,SP
                BRA.S   end\@

msg\@           DC.B    \2
                DC.B    10
                DC.B    0
                DS.W    0
end\@
                ENDC
                ENDM


lib_examples/sample_rev.i

* sample_rev.i version file (generated with the ``bumprev'' command)

VERSION         EQU     37
REVISION        EQU     1
DATE    MACRO
                dc.b    '2.3.92'
        ENDM
VERS    MACRO
                dc.b    'sample 37.1'
        ENDM
VSTRING MACRO
                dc.b    'sample 37.1 (2.3.92)',13,10,0
        ENDM
VERSTAG MACRO
                dc.b    0,'$VER: sample 37.1 (2.3.92)',0
        ENDM


lib_examples/sample_protos.h

/* sample_protos.h - prototypes for sample.library functions */

#ifndef SAMPLE_PROTOS_H
#define SAMPLE_PROTOS_H

LONG AddThese(LONG,LONG);
LONG Double(LONG);

#endif  /* SAMPLE_PROTOS_H */


lib_examples/sample_pragmas.h

/* sample_pragmas.h - "sample.library" */
#pragma libcall SampleBase Double 1E 001
#pragma libcall SampleBase AddThese 24 1002


lib_examples/samplebase.i

* samplebase.i -- definition of sample.library base

   IFND  SAMPLE_BASE_I
SAMPLE_BASE_I SET 1

   IFND  EXEC_TYPES_I
   INCLUDE  "exec/types.i"
   ENDC   ; EXEC_TYPES_I

   IFND  EXEC_LIBRARIES_I
   INCLUDE  "exec/libraries.i"
   ENDC   ; EXEC_LIBRARIES_I

;--------------------------
; library data structures
;--------------------------

;  Note that the library base begins with a library node

   STRUCTURE SampleBase,LIB_SIZE
   UBYTE   sb_Flags
   UBYTE   sb_pad
   ;We are now longword aligned
   ULONG   sb_SysLib
   ULONG   sb_DosLib
   ULONG   sb_SegList
   LABEL   SampleBase_SIZEOF

SAMPLENAME   MACRO
      DC.B   'sample.library',0
      ENDM

   ENDC  ;SAMPLE_BASE_I


lib_examples/samplebase.h

/* samplebase.h -- C include file defining sample.library base */

#ifndef SAMPLE_BASE_H
#define SAMPLE_BASE_H

#ifndef  EXEC_TYPES_H
#include  <exec/types.h>
#endif   EXEC_TYPES_H

#ifndef  EXEC_LIBRARIES_H
#include <exec/libraries.h>
#endif   EXEC_LIBRARIES_H

/* library data structures-- Note that the library base begins with a library node */

struct SampleBase {
   struct Library LibNode;
   UBYTE  Flags;
   UBYTE  pad;
   /* We are now longword aligned */
   ULONG  SysLib;
   ULONG  DosLib;
   ULONG  SegList;
   };

#define SAMPLENAME   "sample.library"

#endif  /* SAMPLE_BASE_H */


lib_examples/sample_lvos.asm

***************************************************************************
* sample_lvos.asm   _LVO definitions
*
*  This is the .fd file for our sample library:
*
* Note - the slash in (D0/D1) means that a stub-maker can use MOVEM.L to
* load these registers from the stack, rather than using a separate MOVE
* instruction for each register. Alternately, something like  (A0,D2) would
* show that a separate MOVE instruction is needed for each load.
*
*       ##base _SampleBase
*       ##bias 30
*       ##public
*       Double(n1)(D0)
*       AddThese(n1,n2)(D0/D1)
*       ##end
*
* After assembling,
*   JOIN sample_stubs.o sample_lvos.o AS sample.lib
*
* Apps LINK with LIBRARY sample.lib when calling sample.library functions
***************************************************************************

   INCLUDE  "exec/types.i"
   INCLUDE  "exec/libraries.i"

          SECTION data

*----- LIBINIT initializes an LVO value to -30 to skip the first four
*----- 6-byte required library vectors (Open, Expunge, etc)

             LIBINIT

*----- LIBDEF assigns the current LVO value to a label, and then
*----- bumps the LVO value by -6 in preparation for next LVO label

*----- This assigns the value -30 to our first _LVO label

             LIBDEF      _LVODouble     ;-30
             XDEF        _LVODouble

*----- The value -30-6 is asigned to our second _LVO label

             LIBDEF      _LVOAddThese   ;-36
             XDEF        _LVOAddThese

             END


lib_examples/sample_stubs.asm

*******************************************************************************************
* sample_stubs.asm
*
* Stubs match this .fd file:
*
*       ##base _SampleBase
*       ##bias 30
*       ##public
*       Double(n1)(D0)
*       AddThese(n1,n2)(D0/D1)
*       ##end
*
* After assembling,
*   JOIN sample_stubs.o sample_lvos.o AS sample.lib
*
* Apps LINK with LIBRARY sample.lib when calling sample.library functions
*
* If you put all of your stubs in one file, as shown here, then ALL of the stubs will be
* linked into an application that references one stub.  For larger libraries, you should
* place each stub in a separate assembler file, assemble them each separately, then join
* all of the .o's together. That will allow each stub to be independently pulled into the
* application that links with the .lib.
*******************************************************************************************
   INCLUDE  "exec/types.i"
   INCLUDE  "exec/libraries.i"

          section code

*------ Caller declares and initializes SampleBase in their C code

            XREF        _SampleBase

*------ Must externally reference the _LVO labels defined in samplelib_lvos

            XREF        _LVODouble
            XREF        _LVOAddThese

*------ Make C function stubs available to caller

            XDEF        _Double
            XDEF        _AddThese

*------- These stubs move C args from stack to appropriate registers,
*------- call the library function, and return result in d0

_Double:
            MOVE.L      A6,-(SP)           ;Save register(s)
            MOVE.L      8(SP),D0           ;Copy param to register
            MOVE.L      _SampleBase,A6     ;Library base to A6
            JSR         _LVODouble(A6)     ;Go to real routine
            MOVE.L      (SP)+,A6           ;Restore register(s)
            RTS

_AddThese:
            MOVE.L      A6,-(SP)           ;Save register(s)
            MOVEM.L     8(SP),D0/D1        ;Copy params to registers
                                           ;8(SP)  goes into D0
                                           ;12(SP) goes into D1
            MOVE.L      _SampleBase,A6     ;Library base to A6
            JSR         _LVOAddThese(A6)   ;Go to real routine
            MOVE.L      (SP)+,A6           ;Restore register(s)
            RTS

          END


lib_examples/clibtest.c

;/* clibtest.c--Calls the Sample.library functions (execute to compile with Lattice 5.10a)
LC -b1 -cfistq -v -y -j73 clibtest.c
Blink FROM LIB:c.o,clibtest.o TO clibtest LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
; note - you must also link with sample.lib if not using sample_pragmas.h
*/

#include <exec/types.h>
#include <exec/libraries.h>
#include <libraries/dos.h>

#include <clib/exec_protos.h>

#include <stdlib.h>
#include <stdio.h>

#include "sampleinclude/samplebase.h"
#include "sampleinclude/sample_protos.h"
#include "sampleinclude/sample_pragmas.h"

#ifdef LATTICE
int CXBRK(void)     { return(0); }      /* Disable Lattice CTRL/C handling */
void chkabort(void) { return; }         /* really */
#endif

struct Library *SampleBase = NULL;

void main(int argc, char **argv)
   {
   LONG n;

   /* Open sample.library */
   if(!(SampleBase=OpenLibrary("sample.library",0)))
      {
      printf("Can't open sample.library\n");
      exit(RETURN_FAIL);
      }
   /* Print library name, ID string, version, revision */
   printf("%s  Version=%ld   Revision=%ld  IdString: %s\n",
             SampleBase->lib_Node.ln_Name, SampleBase->lib_Version,
             SampleBase->lib_Revision, SampleBase->lib_IdString);

   /* Call the two functions */
   n = Double(-7);
   printf("Function Double(-7) returned %ld\n", n);
   n = AddThese(21,4);
   printf("Function AddThese(21,4) returned %ld\n", n);

   CloseLibrary(SampleBase);
   exit(RETURN_OK);
   }


lib_examples/alibtest.asm

************************************************************************
*  alibtest.asm -- Asm example that calls the Sample.library functions
*
*  Linkage Info:
*  FROM     Astartup.obj, alibtest.o
*  LIBRARY  LIB:amiga.lib, LIB:sample.lib
*  TO       ALibTest
************************************************************************

   INCLUDE   "exec/types.i"
   INCLUDE   "exec/libraries.i"

   INCLUDE   "sampleinclude/asmsupp.i"
   INCLUDE   "sampleinclude/samplebase.i"

ABSEXECBASE  EQU  4

   XDEF   _main

   XREF   _printf
   XREF   _LVODouble
   XREF   _LVOAddThese

   XLIB   OpenLibrary
   XLIB   CloseLibrary

        section code
_main:
   ;------ open the test library: this will bring it in from disk
   move.l   ABSEXECBASE,a6
   lea      sampleName(pc),a1
   moveq    #0,d0
   jsr      _LVOOpenLibrary(a6)

   tst.l    d0
   bne.s    1$

   ;------ couldn't find the library
   pea      sampleName(pc)
   pea      nolibmsg(pc)
   jsr      _printf
   addq.l   #8,sp

   bra      main_end

1$:
   move.l   d0,a6    ;sample.library base to a6

   ;------ print the library name, version, and revision
   clr.l    d0
   move.w   LIB_REVISION(a6),d0
   move.l   d0,-(sp)
   move.w   LIB_VERSION(a6),d0
   move.l   d0,-(sp)
   move.l   LN_NAME(a6),-(sp)
   pea      verRevMsg(pc)
   jsr      _printf           ;call Amiga.lib printf
   adda.l   #16,sp            ;fix 4 long stack pushes

   ;------ call the first test function
   moveq    #-7,d0
   jsr      _LVODouble(a6)
   move.l   d0,-(sp)
   pea      doubleMsg(pc)
   jsr      _printf
   lea      8(sp),sp          ;fix 2 long stack pushes

   ;------ call the second test function
   moveq    #21,d0
   moveq    #4,d1
   jsr      _LVOAddThese(a6)
   move.l   d0,-(sp)
   pea      addTheseMsg(pc)
   jsr      _printf
   lea      8(sp),sp

   ;------ close the library
   move.l   a6,a1
   move.l   ABSEXECBASE,a6
   jsr      _LVOCloseLibrary(a6)

main_end:
            rts

sampleName:  SAMPLENAME
nolibmsg:    dc.b   'can not open library "%s"',10,0
doubleMsg:   dc.b   'Function Double(-7) returned %ld',10,0
addTheseMsg: dc.b   'Function AddThese(21,4) returned %ld',10,0
verRevMsg:   dc.b   '%s   Version %ld   Revision %ld',10,0
   END


lib_startup/lmkfile

ASM = casm

SNAME	= startup
AFILE  	= $(SNAME).asm
AFLAGS 	= -c s -i V36:include
OFILES	= Astartup.obj AWstartup.obj Rstartup.obj RWstartup.obj RXstartup.obj Qstartup.obj
.SUFFIXES:	.obj .c .h .asm .i

Qstartup.obj:	startup.asm
    $(ASM) -a startup.asm $(AFLAGS) -hastartup.i -o Astartup.obj

    $(ASM) -a startup.asm $(AFLAGS) -hawstartup.i -o AWstartup.obj

    $(ASM) -a startup.asm $(AFLAGS) -hrstartup.i -o Rstartup.obj

    $(ASM) -a startup.asm $(AFLAGS) -hrwstartup.i -o RWstartup.obj

    $(ASM) -a startup.asm $(AFLAGS) -hrxstartup.i -o RXstartup.obj

    $(ASM) -a startup.asm $(AFLAGS) -hqstartup.i -o Qstartup.obj


lib_startup/startup.asm

*
* Copyright (c) 1990-1999 Amiga, Inc.
*
* This example is provided in electronic form by Amiga, Inc. for
* use with the "Amiga ROM Kernel Reference Manual: Devices", 3rd Edition,
* published by Addison-Wesley (ISBN 0-201-56775-X).
*
* The "Amiga ROM Kernel Reference Manual: Devices" contains additional
* information on the correct usage of the techniques and operating system
* functions presented in these examples.  The source and executable code
* of these examples may only be distributed in free electronic form, via
* bulletin board or as part of a fully non-commercial and freely
* redistributable diskette.  Both the source and executable code (including
* comments) must be included, without modification, in any copy.  This
* example may not be published in printed form or distributed with any
* commercial product.  However, the programming techniques and support
* routines set forth in these examples may be used in the development
* of original executable software products for Amiga computers.
*
* All other rights reserved.
*
* This example is provided "as-is" and is subject to change; no
* warranties are made.  All use is at your own risk. No liability or
* responsibility is assumed.
*
**********************************************************************
*
*------ startup.asm  v 36.13
*
**********************************************************************

*
* Copyright (c) 1990-1999 Amiga, Inc.
*
*
*------
*------ Conditional assembly flags
*------ ASTART:   1=Standard Globals Defined    0=Reentrant Only
*------ WINDOW:   1=AppWindow for WB startup    0=No AppWindow code
*------ XNIL:     1=Remove startup NIL: init    0=Default Nil: WB Output
*------ NARGS:    1=Argv[0] only                0=Normal cmd line arg parse
*------ DEBUG:    1=Set up old statics for Wack 0=No extra statics
*------ QARG:     1=No argv                     0=Passes argc,argv

* Include the appropriate startup.i (example rstartup.i) here or in
* your assem line

        INCLUDE "allstartup.i"

* Flags for  [A]start  AWstart  Rstart  RWstart  RXstart  QStart
* ASTART         1        1       0        0        0       0
* WINDOW         0        1       0        1        0       0
* XNIL           0        0       0        0        1       1
* NARGS          0        0       0        0        0       0
* DEBUG          0        0       0        0        0       0
* QARG           0        0       0        0        0       1

;------   Flag WB output initialization
NNIL	  SET	(1-XNIL)
WBOUT     SET   (ASTART!WINDOW!NNIL)

************************************************************************
*
*   startup.asm --- Reentrant C Program Startup/Exit (CLI and WB)
*                   v36.13  011/07/90
*
*   Copyright (c) 1988-1999 Amiga, Inc.
*
*   Title to this software and all copies thereof remain vested in the
*   authors indicated in the above copyright notice.  The object version
*   of this code may be used in software for Amiga computers.
*   All other rights are reserved.
*
*   NO REPRESENTATIONS OR WARRANTIES ARE MADE WITH RESPECT TO THE
*   ACCURACY, RELIABILITY, PERFORMANCE OR OPERATION OF THIS SOFTWARE,
*   AND ALL SUCH USE IS AT YOUR OWN RISK.  NEITHER AMIGA NOR THE
*   AUTHORS ASSUME ANY RESPONSIBILITY OR LIABILITY WHATSOEVER WITH
*   RESPECT TO YOUR USE OF THIS SOFTWARE.
*
*
*   RSTARTUP.ASM
*
*  Changes for 2.0 - since commands may now receive a >256 character command
*  line, the argv buffer size is now dynamic, based on DosCmdLen passed in.
*  The argv count is also dynamic, based on number of spaces in the command
*  line.
*
*      This startup dynamically allocates a structure which includes
*   the argv buffers.  If you use this startup, your code must return
*   to this startup when it exits.  Use exit(n) or final curly brace
*   (rts) to return here.  Do not use AmigaDOS Exit( ) function.
*   Due to this dynamic allocation and some code consolidation, this
*   startup can make executables several hundred bytes smaller.
*
*       Because a static initialSP variable can not be used, this
*   code depends on the fact that AmigaDOS places the address of
*   the top of our stack in SP and proc->pr_ReturnAddr right before
*   JSR'ing to us.  This code uses pr_ReturnAddr when restoring SP.
*
*       Most versions of startup will initialize a Workbench process's
*   input and output streams (and stdio globals if present) to NIL:
*   if no other form of Workbench output (like WINDOW) is provided.
*   This should help prevent crashes if a user puts an icon on a CLI
*   program, and will also protect against careless stdio debugging
*   or error messages left in a Workbench program.  The code for
*   initializing Workbench IO streams only be removed by assembling
*   startup with ASTART and WINDOW set to 0, and XNIL set to 1.
*
*
*   Some startups which can be conditionally assembled:
*
*      1. Standard Astartup for non-reentrant code
*      2. Reentrant Rstartup (no unshareable globals)
*      3. Smaller reentrant-only RXstartup (no NIL: WB init code)
*      4. Standard AWstartup (WB output window) for non-reentrant code
*      5. Reentrant RWstartup (WB output window, no unshareable globals)
*      6. Smallest Qstartup  (No argv - argv is ptr to NULL string)
*
*
*   Explanation of conditional assembly flags:
*
*      ASTART (ASTART SET 1) startups will set up and XDEF the
*   global variables _stdin, _stdout, _stderr, _errno and  _WBenchMsg.
*   These startups can be used as smaller replacements for startups
*   like (A)startup.obj and TWstartup.obj.  Startups with ASTART
*   would generally be used for non-reentrant programs, although the
*   startup code itself is still reentrant if the globals are not
*   referenced.
*      Reentrant (ASTART SET 0) startups will NOT set up or
*   XDEF the stdio and WBenchMsg globals.  This not only makes the
*   startup slightly smaller, but also lets you know if your code
*   is referencing these non-reentrant globals (you will get an
*   unresolved external reference when you link).  Programs
*   get their input and output handles from Input( ) and Output( ),
*   and the WBenchMsg is passed in argv on Workbench startup.
*
*      WINDOW (WINDOW SET 1) startups use an XREF'd CON: string
*   named AppWindow, defined in your application, to open a stdio
*   console window when your application is started from Workbench.
*   For non-reentrant programs, this window can be used for normal
*   stdio (printf, getchar, etc).  For reentrant programs the window
*   is Input( ) and Output( ).  WINDOW is useful when adding Workbench
*   capability to a stdio application, and also for debugging other
*   Workbench applications.  To insure that applications requiring
*   a window startup are linked with a window startup, the label
*   _NeedWStartup can be externed and referenced in the application
*   so that a linker error will occur if linked with a standard
*   startup.
*
*       example:   /* Optional safety reference to NeedWStartup */
*                    extern UBYTE  NeedWStartup;
*                    UBYTE  *HaveWStartup = &NeedWStartup;
*                  /* Required window specification */
*                    char AppWindow[] = "CON:30/30/200/150/MyProgram";
*                    ( OR  char AppWindow[] = "\0";  for no window )
*
*
*      XNIL (XNIL SET 1) allows the creation of a smaller startup
*   by removing the code that initializes a Workbench process's
*   output streams to NIL:.  This flag can only remove the code
*   if it is not required for ASTART or WINDOW.
*
*      NARGS (NARGS SET 1) removes the code used to parse command line
*   arguments.  The command name is still passed to _main as argv[0].
*   This option can take about 120 bytes off the size of any program that
*   does not use command line args.
*
*      DEBUG (DEBUG SET 1) will cause the old startup.asm statics
*   initialSP, dosCmdLen and dosCmdBuf to be defined and initialized
*   by the startup code, for use as debugging symbols when using Wack.
*
*      QARG (QARG SET TO 1) will bypass all argument parsing.  A CLI
*   startup is passed argc == 1, and a Workbench startup is passed
*   argc == 0.  Argv[0] will be a pointer to a NULL string rather than
*   a pointer to the command name.  This option creates a very small
*   startup with no sVar structure allocation, and therefore must be used
*   with XNIL (it is incompatible with default or AWindow output options).
*
*
*   RULES FOR REENTRANT CODE
*
*      - Make no direct or indirect (printf, etc) references to the
*        globals _stdin, _stdout, _stderr, _errno, or _WBenchMsg.
*
*      - For stdio use either special versions of printf and getchar
*        that use Input( ) and Output( ) rather than _stdin and _stdout,
*        or use fprintf and fgetc with Input( ) and Output( ) file handles.
*
*      - Workbench applications must get the pointer to the WBenchMsg
*        from argv rather than from a global extern WBenchMsg.
*
*      - Use no global or static variables within your code.  Instead,
*        put all former globals in a dynamically allocated structure, and
*        pass around a pointer to that structure.  The only acceptable
*        globals are constants (message strings, etc) and global copies
*        of Library Bases to resolve Amiga.lib references.  Your code
*        must return all OpenLibrary's into non-global variables,
*        copy the result to the global library base only if successful,
*        and use the non-globals when deciding whether to Close any
*        opened libraries.
*
************************************************************************

******* Included Files *************************************************

        INCLUDE "exec/types.i"
        INCLUDE "exec/alerts.i"
        INCLUDE "exec/memory.i"
        INCLUDE "libraries/dos.i"
        INCLUDE "libraries/dosextens.i"
        INCLUDE "workbench/startup.i"

******* MACROS *********************************************************

    CODE

xlib    macro
        xref    _LVO\1
        endm

callsys macro
        CALLLIB _LVO\1
        endm

******* Imported *******************************************************

ABSEXECBASE     EQU     4

        xref    _main           ; C code entry point

        IFGT    WINDOW
        xref    _AppWindow      ; CON: spec in application for WB stdio window
        xdef    _NeedWStartup   ; May be externed and referenced in application
        ENDC    WINDOW

        xlib    Alert
        xlib    AllocMem
        xlib    FindTask
        xlib    Forbid
        xlib    FreeMem
        xlib    GetMsg
        xlib    OpenLibrary
        xlib    CloseLibrary
        xlib    ReplyMsg
        xlib    Wait
        xlib    WaitPort

        xlib    CurrentDir
        xlib    Open
        xlib    Close
        xlib    Input
        xlib    Output

******* Exported *******************************************************

*----- These globals are set up for standard startup code only
        IFGT    ASTART
        xdef    _stdin
        xdef    _stdout
        xdef    _stderr
        xdef    _errno
        xdef    _WBenchMsg
        ENDC    ASTART

*----- These globals available to normal and reentrant code

        xdef    _SysBase
        xdef    _DOSBase
        xdef    _exit           ; standard C exit function

***** Startup Variables structure **********************************

        IFEQ    QARG

; NOTE - the ArgvArray must be last
; It and the ArgvBuffer which follow it are dynamically sized/allocated (2.0)

 STRUCTURE  SVar,0
    ULONG   sv_Size
    LONG    sv_WbOutput
    ULONG   sv_ArgvBufPtr
    ULONG   sv_MaxArgc
    LABEL   sv_ArgvArray
    LABEL   SV_SIZEOF
        ENDC    QARG

************************************************************************
*   Standard Program Entry Point
************************************************************************
*
*       Entered with
*           d0  dosCmdLen
*           a0  dosCmdBuf
*       Any registers (except sp) are allowed to be modified
*
*       Calls
*           main (argc, argv)
*               int   argc;
*               char *argv[];
*
*           For Workbench startup, argc=0, argv=WBenchMsg
*
************************************************************************
startup:
        IFGT    DEBUG
                move.l  sp,initialSP
                move.l  d0,dosCmdLen
                move.l  a0,dosCmdBuf
        ENDC    DEBUG

        IFEQ    QARG
                move.l  d0,d2
                move.l  a0,a2
        ENDC    QARG

        ;------ get Exec library base pointer
                movea.l ABSEXECBASE,a6
                move.l  a6,_SysBase

        ;------ get the address of our task
                suba.l  a1,a1           ; clear a1
                callsys FindTask
                move.l  d0,a4           ; keep task address in a4

        ;------ get DOS library base pointer
                moveq   #0,d0
                lea     DOSName(pc),A1  ; dos.library
                callsys OpenLibrary

                tst.l   d0
                beq     alertDOS        ; fail on null with alert
                move.l  d0,_DOSBase     ; Else set the global

        IFEQ    QARG
        ;------ branch over argv calculations if not a CLI process
                move.l  pr_CLI(A4),d0
        bne.s	vcnt
        moveq	#2,d4		; if wb startup alloc 2 argv's
        moveq   #8,d2		; fake dos cmd line size for alloc
                bra.s   wbnoargs

vcnt:
    ;------ estimate max number of argv's for CLI command line
    ;------ command + number spaces + 1 + null argv
        movea.l	a2,a0		; dos command line
        moveq	#3,d4		; start count at 3, add spaces
vcnt1:
        cmp.b	#' ',(a0)
        bne.s	vcnt2
        addq	#1,d4
vcnt2:
        tst.b	(a0)+
        bne.s	vcnt1

    ;------ branch to here has d4=2, d2=8 for wb startup
wbnoargs:

    ;------ d4 now equals at least max number argv's needed
        move.l	d4,d0
        lsl.l	#2,d0		; convert to bytes needed for argv ptrs
        move.l	d0,d5		; save in d5
        add.l	d2,d0		; add dos command line size for buffer

                add.l  #SV_SIZEOF+1,d0	; add structure size + 1 for null term

        ;------ alloc the argument structure
        move.l	d0,d3		; save total size for de-allocation
                move.l  #(MEMF_PUBLIC!MEMF_CLEAR),d1
                callsys AllocMem
                tst.l   d0
                beq     alertMem        ; fail on null with alert
                move.l  d0,-(sp)        ; save sVar ptr on stack
                move.l  d0,a5           ; sVar ptr to a5
        move.l	d3,sv_Size(a5)  ; size for de-allocation later (2.0)
        subq.l	#1,d4
        move.l	d4,sv_MaxArgc(a5) ; max argc
        lea.l	sv_ArgvArray(a5),a0
        adda.l	d5,a0
        move.l  a0,sv_ArgvBufPtr(a5)

        ENDC    QARG
        IFGT    QARG
                clr.l   -(sp)
        ENDC    QARG

                clr.l   -(sp)           ; reserve space for WBenchMsg if any

        ;------ branch to Workbench startup code if not a CLI process
                move.l  pr_CLI(A4),d0
                beq     fromWorkbench

;=======================================================================
;====== CLI Startup Code ===============================================
;=======================================================================
;       d0  process CLI BPTR (passed in), then temporary
;       d2  dos command length (passed in)
;       d3  argument count
;       a0  temporary
;       a1  argv buffer
;       a2  dos command buffer (passed in)
;       a3  argv array
;       a4  Task (passed in)
;       a5  SVar structure if not QARG (passed in)
;       a6  AbsExecBase (passed in)
;       sp  WBenchMsg (still 0), sVar or 0, then RetAddr (passed in)
;       sp  argc, argv, WBenchMsg, sVar or 0,RetAddr (at bra domain)

        IFEQ    QARG
        ;------ find command name
                lsl.l   #2,d0           ; pr_CLI bcpl pointer conversion
                move.l  d0,a0
                move.l  cli_CommandName(a0),d0
                lsl.l   #2,d0           ; bcpl pointer conversion

                ;-- start argv array
                move.l	sv_ArgvBufPtr(a5),a1
                lea     sv_ArgvArray(a5),a3

                ;-- copy command name
                move.l  d0,a0
                moveq.l #0,d0
                move.b  (a0)+,d0        ; size of command name
                clr.b   0(a0,d0.l)      ; terminate the command name
                move.l  a0,(a3)+
                moveq   #1,d3           ; start counting arguments

        IFEQ    NARGS
        ;------ null terminate the arguments, eat trailing control characters
                lea     0(a2,d2.l),a0
stripjunk:
                cmp.b   #' ',-(a0)
                dbhi    d2,stripjunk

                clr.b   1(a0)

        ;------ start gathering arguments into buffer
newarg:
                ;-- skip spaces
                move.b  (a2)+,d1
                beq.s   parmExit
                cmp.b   #' ',d1
                beq.s   newarg
                cmp.b   #9,d1           ; tab
                beq.s   newarg

                ;-- check for argument count overflow
                cmp.l   sv_MaxArgc(a5),d3
                beq.s   parmExit

                ;-- push address of the next parameter
                move.l  a1,(a3)+
                addq.w  #1,d3

                ;-- process quotes
                cmp.b   #'"',d1
                beq.s   doquote

                ;-- copy the parameter in
                move.b  d1,(a1)+

nextchar:
                ;------ null termination check
                move.b  (a2)+,d1
                beq.s   parmExit
                cmp.b   #' ',d1
                beq.s   endarg

                move.b  d1,(a1)+
                bra.s   nextchar

endarg:
                clr.b   (a1)+
                bra.s   newarg

doquote:
        ;------ process quoted strings
                move.b  (a2)+,d1
                beq.s   parmExit
                cmp.b   #'"',d1
                beq.s   endarg

                ;-- '*' is the BCPL escape character
                cmp.b   #'*',d1
                bne.s   addquotechar

                move.b  (a2)+,d1
                move.b  d1,d2
                and.b   #$df,d2         ;d2 is temp toupper'd d1

                cmp.b   #'N',d2         ;check for dos newline char
                bne.s   checkEscape

                ;--     got a *N -- turn into a newline
                moveq   #10,d1
                bra.s   addquotechar

checkEscape:
                cmp.b   #'E',d2
                bne.s   addquotechar

                ;--     got a *E -- turn into a escape
                moveq   #27,d1

addquotechar:
                move.b  d1,(a1)+
                bra.s   doquote

parmExit:
        ;------ all done -- null terminate the arguments
                clr.b   (a1)
                clr.l   (a3)
        ENDC NARGS

                pea     sv_ArgvArray(a5) ; argv
                move.l  d3,-(sp)         ; argc
        ENDC    QARG

        IFGT    QARG
                pea     nullArgV(pc)    ; pointer to pointer to null string
                pea     1               ; only one pointer
        ENDC

        IFGT    ASTART
                movea.l _DOSBase,a6
        ;------ get standard input handle:
                callsys Input
                move.l  d0,_stdin

        ;------ get standard output handle:
                callsys Output
                move.l  d0,_stdout
                move.l  d0,_stderr
                movea.l ABSEXECBASE,a6
        ENDC ASTART

                bra     domain

;=======================================================================
;====== Workbench Startup Code =========================================
;=======================================================================
;       a2  WBenchMsg
;       a4  Task (passed in)
;       a5  SVar structure if not QARG (passed in)
;       a6  AbsExecBase (passed in)
;       sp  WBenchMsg (still 0), sVar or 0, then RetAddr (passed in)
;       sp  argc=0,argv=WBenchMsg,WBenchMsg,sVar or 0,RetAddr (at domain)

fromWorkbench:
        ;------ get the startup message that workbench will send to us.
        ;       must get this message before doing any DOS calls
                bsr.s   getWbMsg

        ;------ save the message so we can return it later
                move.l  d0,(sp)
        IFGT    ASTART
                move.l  d0,_WBenchMsg
        ENDC    ASTART

        ;------ push the message on the stack for wbmain (as argv)
                move.l  d0,-(sp)
                clr.l   -(sp)           ; indicate run from Workbench (argc=0)

        IFNE    (1-QARG)+WBOUT
        ;------ put DOSBase in a6 for next few calls
                move.l  _DOSBase,a6
        ENDC    (1-QARG)+WBOUT

        IFEQ    QARG
        ;------ get the first argument
                move.l  d0,a2
                move.l  sm_ArgList(a2),d0
                beq.s   doCons

        ;------ and set the current directory to the same directory
                move.l  d0,a0
                move.l  wa_Lock(a0),d1
                ;should be a  beq.s doCons  here
                callsys CurrentDir
doCons:
        ENDC    QARG

        IFGT    WBOUT

        ;------ Open NIL: or AppWindow for WB Input()/Output() handle
        ;       Also for possible initialization of stdio globals
        ;       Stdio used to be initialized to -1

        IFGT    WINDOW
        ;------ Get AppWindow defined in application
                lea     _AppWindow,a0
                cmp.b   #0,(a0)
                bne.s   doOpen          ; Open if not null string
        ENDC    WINDOW

        ;------ Open NIL: if no window provided
        lea     NilName(PC),a0

doOpen:
        ;------ Open up the file whose name is in a0
        ;       DOSBase still in a6
                move.l  a0,d1
                move.l  #MODE_OLDFILE,d2
                callsys Open
        ;------ d0 now contains handle for Workbench Output
        ;------ save handle for closing on exit
                move.l  d0,sv_WbOutput(a5)
                bne.s   gotOpen
                moveq.l #RETURN_FAIL,d2
                bra     exit2
gotOpen:
        IFGT ASTART
        ;------ set the C input and output descriptors
                move.l  d0,_stdin
                move.l  d0,_stdout
                move.l  d0,_stderr
        ENDC ASTART

        ;------ set the console task (so Open( "*", mode ) will work
        ;       task pointer still in A4
                move.l  d0,pr_CIS(A4)
                move.l  d0,pr_COS(A4)
                lsl.l   #2,d0
                move.l  d0,a0
                move.l  fh_Type(a0),d0
                beq.s   noConTask
                move.l  d0,pr_ConsoleTask(A4)
noConTask:
        ENDC WBOUT

        ;------ Fall though to common WB/CLI code

****************************************************
** This code now used by both CLI and WB startup  **
****************************************************

domain:
                jsr     _main
        ;------ main didn't use exit(n) so provide success return code
                moveq.l #RETURN_OK,d2
                bra.s   exit2

****************************************************
**    subroutines here to allow short branches    **
****************************************************

getWbMsg:
        ;------ a6 = ExecBase
                lea     pr_MsgPort(A4),a0       ; our process base
                callsys WaitPort
                lea     pr_MsgPort(A4),a0       ; our process base
                callsys GetMsg
                rts

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

alertDOS:
        ;------ do recoverable alert for no DOS and exit
                ALERT   (AG_OpenLib!AO_DOSLib)

        ;------ do recoverable alert for no memory and exit
        ;------ If we got this far, DOS is open, so close it
        IFEQ QARG
                bra.s   failExit
alertMem:
                movea.l _DOSBase,a1
                callsys CloseLibrary
                ALERT   AG_NoMemory
        ENDC QARG
failExit:
                tst.l   pr_CLI(a4)
                bne.s   fail2
                bsr.s   getWbMsg
                movea.l d0,a2
                bsr.s   repWbMsg
fail2:
                moveq.l #RETURN_FAIL,d0
                rts

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

repWbMsg:
        ;------ return the startup message to our parent
        ;       a6 = ExecBase (passed)
        ;       a2 = WBenchMsg (passed)
        ;       we forbid so workbench can't UnLoadSeg() us before we are done
                callsys Forbid
                move.l  a2,a1
                callsys ReplyMsg
                rts

*******************************************************
**  C Program exit() Function, return code on stack  **
**                                                   **
**  pr_ReturnAddr points to our RTS addr on stack    **
**  and we use this to calculate our stack ptr:      **
**                                                   **
**      SP ->   WBenchMsg or 0 (CLI)                 **
**              sVar ptr or 0 (QARG)                 **
**              Address for RTS to DOS               **
*******************************************************

_exit:
                move.l  4(sp),d2        ; exit(n) return code to d2

exit2:                                  ;exit code in d2
        ;------ restore initial stack ptr
                ;-- FindTask
                movea.l ABSEXECBASE,a6
                suba.l  a1,a1
                callsys FindTask
                ;-- get SP as it was prior to DOS's jsr to us
                move.l  d0,a4
                move.l  pr_ReturnAddr(a4),a5
                ;-- subtract 4 for return address, 4 for SVar, 4 for WBenchMsg
                suba.l  #12,a5

                ;-- restore sp
                move.l  a5,sp

                ;-- recover WBenchMsg
                move.l  (sp)+,a2
                ;-- recover SVar
                move.l  (sp)+,a5

        IFGT    WBOUT
        ;------ Close any WbOutput file before closing dos.library
                move.l  sv_WbOutput(a5),d1
                beq.s   noWbOut
                move.l  _DOSBase,a6
                callsys Close
noWbOut:
        ;------ Restore a6 = ExecBase
                movea.l ABSEXECBASE,a6
        ENDC    WBOUT

        ;------ Close DOS library, if we got here it was opened
        ;       SysBase still in a6
                movea.l _DOSBase,a1
                callsys CloseLibrary

        ;------ if we ran from CLI, skip workbench reply
checkWB:
                move.l  a2,d0
                beq.s   deallocSV

                bsr.s   repWbMsg

deallocSV:
        IFEQ    QARG
        ;------ deallocate the SVar structure
                move.l  a5,a1
                move.l  sv_Size(a5),d0
                callsys FreeMem
        ENDC    QARG

        ;------ this rts sends us back to DOS:
                move.l  d2,d0
                rts

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

;----- PC relative data

DOSName         DOSNAME
NilName         dc.b    'NIL:',0
        IFGT    QARG
        CNOP	0,2
nullArgV        dc.l    nullArg
nullArg         dc.l    0               ; "" & the null entry after nullArgV
        ENDC

**********************************************************************
        DATA
**********************************************************************

_SysBase        dc.l    0
_DOSBase        dc.l    0

        IFGT    ASTART
_WBenchMsg      dc.l    0
_stdin          dc.l    0
_stdout         dc.l    0
_stderr         dc.l    0
_errno          dc.l    0
        ENDC    ASTART

        IFGT    DEBUG
initialSP       dc.l    0
dosCmdLen       dc.l    0
dosCmdBuf       dc.l    0
        ENDC    DEBUG

VerRev          dc.w    36,13
        IFGT    ASTART
                dc.b    'A'
        ENDC    ASTART
        IFEQ    ASTART
                dc.b    'R'
        ENDC    ASTART
        IFGT    WINDOW
_NeedWStartup:
                dc.b    'W'
        ENDC    WINDOW
        IFEQ    WBOUT
                dc.b    'X'
        ENDC    WBOUT
        IFGT    NARGS
                dc.b    'N'
        ENDC    NARGS
        IFGT    DEBUG
                dc.b    'D'
        ENDC    DEBUG
        IFGT    QARG
                dc.b    'Q'
        ENDC    QARG

        END


lib_startup/allstartup.i

* define one of the following in your asm command line
* to produce the desired startup

    IFD ASTARTUP
*------ astartup.i
ASTART    SET   1
WINDOW    SET   0
XNIL      SET   0
NARGS     SET   0
DEBUG     SET   0
QARG      SET   0
    ENDC

    IFD AWSTARTUP
*------ awstartup.i
ASTART    SET   1
WINDOW    SET   1
XNIL      SET   0
NARGS     SET   0
DEBUG     SET   0
QARG      SET   0
    ENDC

    IFD RSTARTUP
*------ rstartup.i
ASTART    SET   0
WINDOW    SET   0
XNIL      SET   0
NARGS     SET   0
DEBUG     SET   0
QARG      SET   0
    ENDC

    IFD RWSTARTUP
*------ rwstartup.i
ASTART    SET   0
WINDOW    SET   1
XNIL      SET   0
NARGS     SET   0
DEBUG     SET   0
QARG      SET   0
    ENDC

    IFD	RXSTARTUP
*------ rxstartup.i

ASTART    SET   0
WINDOW    SET   0
XNIL      SET   1
NARGS     SET   0
DEBUG     SET   0
QARG      SET   0
    ENDC

    IFD QSTARTUP
*------ qstartup.i
ASTART    SET   0
WINDOW    SET   0
XNIL      SET   1
NARGS     SET   0
DEBUG     SET   0
QARG      SET   1
    ENDC


lib_startup/Astartup.i

ASTARTUP	SET	1


lib_startup/AWstartup.i

AWSTARTUP	SET	1


lib_startup/Qstartup.i

QSTARTUP	SET	1


lib_startup/Rstartup.i

RSTARTUP	SET 1


lib_startup/RWstartup.i

RWSTARTUP	SET	1


lib_startup/RXstartup.i

RXSTARTUP	SET 1